diff options
Diffstat (limited to 'kopete/protocols/gadu/libgadu')
-rw-r--r-- | kopete/protocols/gadu/libgadu/COPYING | 504 | ||||
-rw-r--r-- | kopete/protocols/gadu/libgadu/Makefile.am | 12 | ||||
-rw-r--r-- | kopete/protocols/gadu/libgadu/common.c | 827 | ||||
-rw-r--r-- | kopete/protocols/gadu/libgadu/compat.h | 29 | ||||
-rw-r--r-- | kopete/protocols/gadu/libgadu/dcc.c | 1298 | ||||
-rw-r--r-- | kopete/protocols/gadu/libgadu/events.c | 1580 | ||||
-rw-r--r-- | kopete/protocols/gadu/libgadu/http.c | 522 | ||||
-rw-r--r-- | kopete/protocols/gadu/libgadu/libgadu-config.h.in | 30 | ||||
-rw-r--r-- | kopete/protocols/gadu/libgadu/libgadu.c | 1818 | ||||
-rw-r--r-- | kopete/protocols/gadu/libgadu/libgadu.h | 1310 | ||||
-rw-r--r-- | kopete/protocols/gadu/libgadu/pubdir.c | 689 | ||||
-rw-r--r-- | kopete/protocols/gadu/libgadu/pubdir50.c | 467 |
12 files changed, 0 insertions, 9086 deletions
diff --git a/kopete/protocols/gadu/libgadu/COPYING b/kopete/protocols/gadu/libgadu/COPYING deleted file mode 100644 index 071eee49..00000000 --- a/kopete/protocols/gadu/libgadu/COPYING +++ /dev/null @@ -1,504 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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.1 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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! - - diff --git a/kopete/protocols/gadu/libgadu/Makefile.am b/kopete/protocols/gadu/libgadu/Makefile.am deleted file mode 100644 index 94693d38..00000000 --- a/kopete/protocols/gadu/libgadu/Makefile.am +++ /dev/null @@ -1,12 +0,0 @@ -METASOURCES = AUTO -noinst_LTLIBRARIES = libgadu_copy.la -INCLUDES = $(SSL_INCLUDES) $(all_includes) -libgadu_copy_la_LDFLAGS = $(SSL_LDFLAGS) $(all_libraries) -libgadu_copy_la_LIBADD = $(LIBSSL) $(LIBPTHREAD) -libgadu_copy_la_SOURCES = common.c \ - dcc.c \ - events.c \ - http.c \ - libgadu.c \ - pubdir50.c \ - pubdir.c diff --git a/kopete/protocols/gadu/libgadu/common.c b/kopete/protocols/gadu/libgadu/common.c deleted file mode 100644 index 9e20422a..00000000 --- a/kopete/protocols/gadu/libgadu/common.c +++ /dev/null @@ -1,827 +0,0 @@ -/* $Id$ */ - -/* - * (C) Copyright 2001-2002 Wojtek Kaniewski <wojtekka@irc.pl> - * Robert J. Wo�ny <speedy@ziew.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License Version - * 2.1 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA. - */ - -#include <sys/types.h> -#include <sys/ioctl.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#ifdef sun -# include <sys/filio.h> -#endif - -#include <errno.h> -#include <fcntl.h> -#include <netdb.h> -#include <stdarg.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#include "libgadu.h" - -FILE *gg_debug_file = NULL; - -#ifndef GG_DEBUG_DISABLE - -/* - * gg_debug() // funkcja wewn�trzna - * - * wy�wietla komunikat o danym poziomie, o ile u�ytkownik sobie tego �yczy. - * - * - level - poziom wiadomo�ci - * - format... - tre�� wiadomo�ci (kompatybilna z printf()) - */ -void gg_debug(int level, const char *format, ...) -{ - va_list ap; - int old_errno = errno; - - if (gg_debug_handler) { - va_start(ap, format); - (*gg_debug_handler)(level, format, ap); - va_end(ap); - - goto cleanup; - } - - if ((gg_debug_level & level)) { - va_start(ap, format); - vfprintf((gg_debug_file) ? gg_debug_file : stderr, format, ap); - va_end(ap); - } - -cleanup: - errno = old_errno; -} - -#endif - -/* - * gg_vsaprintf() // funkcja pomocnicza - * - * robi dok�adnie to samo, co vsprintf(), tyle �e alokuje sobie wcze�niej - * miejsce na dane. powinno dzia�a� na tych maszynach, kt�re maj� funkcj� - * vsnprintf() zgodn� z C99, jak i na wcze�niejszych. - * - * - format - opis wy�wietlanego tekstu jak dla printf() - * - ap - lista argument�w dla printf() - * - * zaalokowany bufor, kt�ry nale�y p��niej zwolni�, lub NULL - * je�li nie uda�o si� wykona� zadania. - */ -char *gg_vsaprintf(const char *format, va_list ap) -{ - int size = 0; - const char *start; - char *buf = NULL; - -#ifdef __GG_LIBGADU_HAVE_VA_COPY - va_list aq; - - va_copy(aq, ap); -#else -# ifdef __GG_LIBGADU_HAVE___VA_COPY - va_list aq; - - __va_copy(aq, ap); -# endif -#endif - - start = format; - -#ifndef __GG_LIBGADU_HAVE_C99_VSNPRINTF - { - int res; - char *tmp; - - size = 128; - do { - size *= 2; - if (!(tmp = realloc(buf, size))) { - free(buf); - return NULL; - } - buf = tmp; - res = vsnprintf(buf, size, format, ap); - } while (res == size - 1 || res == -1); - } -#else - { - char tmp[2]; - - /* libce Solarisa przy buforze NULL zawsze zwracaj� -1, wi�c - * musimy poda� co� istniej�cego jako cel printf()owania. */ - size = vsnprintf(tmp, sizeof(tmp), format, ap); - if (!(buf = malloc(size + 1))) - return NULL; - } -#endif - - format = start; - -#ifdef __GG_LIBGADU_HAVE_VA_COPY - vsnprintf(buf, size + 1, format, aq); - va_end(aq); -#else -# ifdef __GG_LIBGADU_HAVE___VA_COPY - vsnprintf(buf, size + 1, format, aq); - va_end(aq); -# else - vsnprintf(buf, size + 1, format, ap); -# endif -#endif - - return buf; -} - -/* - * gg_saprintf() // funkcja pomocnicza - * - * robi dok�adnie to samo, co sprintf(), tyle �e alokuje sobie wcze�niej - * miejsce na dane. powinno dzia�a� na tych maszynach, kt�re maj� funkcj� - * vsnprintf() zgodn� z C99, jak i na wcze�niejszych. - * - * - format... - tre�� taka sama jak w funkcji printf() - * - * zaalokowany bufor, kt�ry nale�y p��niej zwolni�, lub NULL - * je�li nie uda�o si� wykona� zadania. - */ -char *gg_saprintf(const char *format, ...) -{ - va_list ap; - char *res; - - va_start(ap, format); - res = gg_vsaprintf(format, ap); - va_end(ap); - - return res; -} - -/* - * gg_get_line() // funkcja pomocnicza - * - * podaje kolejn� lini� z bufora tekstowego. niszczy go bezpowrotnie, dziel�c - * na kolejne stringi. zdarza si�, nie ma potrzeby pisania funkcji dubluj�cej - * bufor �eby tylko mie� nieruszone dane wej�ciowe, skoro i tak nie b�d� nam - * po�niej potrzebne. obcina `\r\n'. - * - * - ptr - wska�nik do zmiennej, kt�ra przechowuje aktualn� pozycj� - * w przemiatanym buforze - * - * wska�nik do kolejnej linii tekstu lub NULL, je�li to ju� koniec bufora. - */ -char *gg_get_line(char **ptr) -{ - const char *foo; - char *res; - - if (!ptr || !*ptr || !strcmp(*ptr, "")) - return NULL; - - res = *ptr; - - if (!(foo = strchr(*ptr, '\n'))) - *ptr += strlen(*ptr); - else { - *ptr = foo + 1; - if (strlen(res) > 1 && res[strlen(res) - 1] == '\r') - res[strlen(res) - 1] = 0; - } - - return res; -} - -/* - * gg_connect() // funkcja pomocnicza - * - * ��czy si� z serwerem. pierwszy argument jest typu (void *), �eby nie - * musie� niczego inkludowa� w libgadu.h i nie psu� jaki� g�upich zale�no�ci - * na dziwnych systemach. - * - * - addr - adres serwera (struct in_addr *) - * - port - port serwera - * - async - asynchroniczne po��czenie - * - * deskryptor gniazda lub -1 w przypadku b��du (kod b��du w zmiennej errno). - */ -int gg_connect(void *addr, int port, int async) -{ - int sock, one = 1, errno2; - struct sockaddr_in sin; - struct in_addr *a = addr; - struct sockaddr_in myaddr; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_connect(%s, %d, %d);\n", inet_ntoa(*a), port, async); - - if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) { - gg_debug(GG_DEBUG_MISC, "// gg_connect() socket() failed (errno=%d, %s)\n", errno, strerror(errno)); - return -1; - } - - memset(&myaddr, 0, sizeof(myaddr)); - myaddr.sin_family = AF_INET; - - myaddr.sin_addr.s_addr = gg_local_ip; - - if (bind(sock, (struct sockaddr *) &myaddr, sizeof(myaddr)) == -1) { - gg_debug(GG_DEBUG_MISC, "// gg_connect() bind() failed (errno=%d, %s)\n", errno, strerror(errno)); - return -1; - } - -#ifdef ASSIGN_SOCKETS_TO_THREADS - gg_win32_thread_socket(0, sock); -#endif - - if (async) { -#ifdef FIONBIO - if (ioctl(sock, FIONBIO, &one) == -1) { -#else - if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1) { -#endif - gg_debug(GG_DEBUG_MISC, "// gg_connect() ioctl() failed (errno=%d, %s)\n", errno, strerror(errno)); - errno2 = errno; - close(sock); - errno = errno2; - return -1; - } - } - - sin.sin_port = htons(port); - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = a->s_addr; - - if (connect(sock, (struct sockaddr*) &sin, sizeof(sin)) == -1) { - if (errno && (!async || errno != EINPROGRESS)) { - gg_debug(GG_DEBUG_MISC, "// gg_connect() connect() failed (errno=%d, %s)\n", errno, strerror(errno)); - errno2 = errno; - close(sock); - errno = errno2; - return -1; - } - gg_debug(GG_DEBUG_MISC, "// gg_connect() connect() in progress\n"); - } - - return sock; -} - -/* - * gg_read_line() // funkcja pomocnicza - * - * czyta jedn� lini� tekstu z gniazda. - * - * - sock - deskryptor gniazda - * - buf - wska�nik do bufora - * - length - d�ugo�� bufora - * - * je�li trafi na b��d odczytu lub podano nieprawid�owe parametry, zwraca NULL. - * inaczej zwraca buf. - */ -char *gg_read_line(int sock, char *buf, int length) -{ - int ret; - - if (!buf || length < 0) - return NULL; - - for (; length > 1; buf++, length--) { - do { - if ((ret = read(sock, buf, 1)) == -1 && errno != EINTR) { - gg_debug(GG_DEBUG_MISC, "// gg_read_line() error on read (errno=%d, %s)\n", errno, strerror(errno)); - *buf = 0; - return NULL; - } else if (ret == 0) { - gg_debug(GG_DEBUG_MISC, "// gg_read_line() eof reached\n"); - *buf = 0; - return NULL; - } - } while (ret == -1 && errno == EINTR); - - if (*buf == '\n') { - buf++; - break; - } - } - - *buf = 0; - return buf; -} - -/* - * gg_chomp() // funkcja pomocnicza - * - * ucina "\r\n" lub "\n" z ko�ca linii. - * - * - line - linia do przyci�cia - */ -void gg_chomp(char *line) -{ - int len; - - if (!line) - return; - - len = strlen(line); - - if (len > 0 && line[len - 1] == '\n') - line[--len] = 0; - if (len > 0 && line[len - 1] == '\r') - line[--len] = 0; -} - -/* - * gg_urlencode() // funkcja wewn�trzna - * - * zamienia podany tekst na ci�g znak�w do formularza http. przydaje si� - * przy r��nych us�ugach katalogu publicznego. - * - * - str - ci�g znak�w do zakodowania - * - * zaalokowany bufor, kt�ry nale�y p��niej zwolni� albo NULL - * w przypadku b��du. - */ -char *gg_urlencode(const char *str) -{ - char *q, *buf, hex[] = "0123456789abcdef"; - const char *p; - unsigned int size = 0; - - if (!str) - str = ""; - - for (p = str; *p; p++, size++) { - if (!((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z') || (*p >= '0' && *p <= '9') || *p == ' ') || (*p == '@') || (*p == '.') || (*p == '-')) - size += 2; - } - - if (!(buf = malloc(size + 1))) - return NULL; - - for (p = str, q = buf; *p; p++, q++) { - if ((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z') || (*p >= '0' && *p <= '9') || (*p == '@') || (*p == '.') || (*p == '-')) - *q = *p; - else { - if (*p == ' ') - *q = '+'; - else { - *q++ = '%'; - *q++ = hex[*p >> 4 & 15]; - *q = hex[*p & 15]; - } - } - } - - *q = 0; - - return buf; -} - -/* - * gg_http_hash() // funkcja wewn�trzna - * - * funkcja licz�ca hash dla adresu e-mail, has�a i paru innych. - * - * - format... - format kolejnych parametr�w ('s' je�li dany parametr jest - * ci�giem znak�w lub 'u' je�li numerem GG) - * - * hash wykorzystywany przy rejestracji i wszelkich manipulacjach w�asnego - * wpisu w katalogu publicznym. - */ -int gg_http_hash(const char *format, ...) -{ - unsigned int a, c, i, j; - va_list ap; - int b = -1; - - va_start(ap, format); - - for (j = 0; j < strlen(format); j++) { - char *arg, buf[16]; - - if (format[j] == 'u') { - snprintf(buf, sizeof(buf), "%d", va_arg(ap, uin_t)); - arg = buf; - } else { - if (!(arg = va_arg(ap, char*))) - arg = ""; - } - - i = 0; - while ((c = (unsigned char) arg[i++]) != 0) { - a = (c ^ b) + (c << 8); - b = (a >> 24) | (a << 8); - } - } - - va_end(ap); - - return (b < 0 ? -b : b); -} - -/* - * gg_gethostbyname() // funkcja pomocnicza - * - * odpowiednik gethostbyname() troszcz�cy si� o wsp��bie�no��, gdy mamy do - * dyspozycji funkcj� gethostbyname_r(). - * - * - hostname - nazwa serwera - * - * zwraca wska�nik na struktur� in_addr, kt�r� nale�y zwolni�. - */ -struct in_addr *gg_gethostbyname(const char *hostname) -{ - struct in_addr *addr = NULL; - -#ifdef HAVE_GETHOSTBYNAME_R - char *tmpbuf = NULL, *buf = NULL; - struct hostent *hp = NULL, *hp2 = NULL; - int h_errnop, ret; - size_t buflen = 1024; - int new_errno; - - new_errno = ENOMEM; - - if (!(addr = malloc(sizeof(struct in_addr)))) - goto cleanup; - - if (!(hp = calloc(1, sizeof(*hp)))) - goto cleanup; - - if (!(buf = malloc(buflen))) - goto cleanup; - - tmpbuf = buf; - - while ((ret = gethostbyname_r(hostname, hp, buf, buflen, &hp2, &h_errnop)) == ERANGE) { - buflen *= 2; - - if (!(tmpbuf = realloc(buf, buflen))) - break; - - buf = tmpbuf; - } - - if (ret) - new_errno = h_errnop; - - if (ret || !hp2 || !tmpbuf) - goto cleanup; - - memcpy(addr, hp->h_addr, sizeof(struct in_addr)); - - free(buf); - free(hp); - - return addr; - -cleanup: - errno = new_errno; - - if (addr) - free(addr); - if (hp) - free(hp); - if (buf) - free(buf); - - return NULL; -#else - struct hostent *hp; - - if (!(addr = malloc(sizeof(struct in_addr)))) { - goto cleanup; - } - - if (!(hp = gethostbyname(hostname))) - goto cleanup; - - memcpy(addr, hp->h_addr, sizeof(struct in_addr)); - - return addr; - -cleanup: - if (addr) - free(addr); - - return NULL; -#endif -} - -#ifdef ASSIGN_SOCKETS_TO_THREADS - -typedef struct gg_win32_thread { - int id; - int socket; - struct gg_win32_thread *next; -} gg_win32_thread; - -struct gg_win32_thread *gg_win32_threads = 0; - -/* - * gg_win32_thread_socket() // funkcja pomocnicza, tylko dla win32 - * - * zwraca deskryptor gniazda, kt�re by�o ostatnio tworzone dla w�tku - * o podanym identyfikatorze. - * - * je�li na win32 przy po��czeniach synchronicznych zapami�tamy w jakim - * w�tku uruchomili�my funkcj�, kt�ra si� z czymkolwiek ��czy, to z osobnego - * w�tku mo�emy anulowa� po��czenie poprzez gg_win32_thread_socket(watek, -1); - * - * - thread_id - id w�tku. je�li jest r�wne 0, brany jest aktualny w�tek, - * je�li r�wne -1, usuwa wpis o podanym sockecie. - * - socket - deskryptor gniazda. je�li r�wne 0, zwraca deskryptor gniazda - * dla podanego w�tku, je�li r�wne -1, usuwa wpis, je�li co� - * innego, ustawia dla podanego w�tku dany numer deskryptora. - * - * je�li socket jest r�wne 0, zwraca deskryptor gniazda dla podanego w�tku. - */ -int gg_win32_thread_socket(int thread_id, int socket) -{ - char close = (thread_id == -1) || socket == -1; - gg_win32_thread *wsk = gg_win32_threads; - gg_win32_thread **p_wsk = &gg_win32_threads; - - if (!thread_id) - thread_id = GetCurrentThreadId(); - - while (wsk) { - if ((thread_id == -1 && wsk->socket == socket) || wsk->id == thread_id) { - if (close) { - /* socket zostaje usuniety */ - closesocket(wsk->socket); - *p_wsk = wsk->next; - free(wsk); - return 1; - } else if (!socket) { - /* socket zostaje zwrocony */ - return wsk->socket; - } else { - /* socket zostaje ustawiony */ - wsk->socket = socket; - return socket; - } - } - p_wsk = &(wsk->next); - wsk = wsk->next; - } - - if (close && socket != -1) - closesocket(socket); - if (close || !socket) - return 0; - - /* Dodaje nowy element */ - wsk = malloc(sizeof(gg_win32_thread)); - wsk->id = thread_id; - wsk->socket = socket; - wsk->next = 0; - *p_wsk = wsk; - - return socket; -} - -#endif /* ASSIGN_SOCKETS_TO_THREADS */ - -static char gg_base64_charset[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - -/* - * gg_base64_encode() - * - * zapisuje ci�g znak�w w base64. - * - * - buf - ci�g znak�w. - * - * zaalokowany bufor. - */ -char *gg_base64_encode(const char *buf) -{ - char *out, *res; - unsigned int i = 0, j = 0, k = 0, len = strlen(buf); - - res = out = malloc((len / 3 + 1) * 4 + 2); - - if (!res) - return NULL; - - while (j <= len) { - switch (i % 4) { - case 0: - k = (buf[j] & 252) >> 2; - break; - case 1: - if (j < len) - k = ((buf[j] & 3) << 4) | ((buf[j + 1] & 240) >> 4); - else - k = (buf[j] & 3) << 4; - - j++; - break; - case 2: - if (j < len) - k = ((buf[j] & 15) << 2) | ((buf[j + 1] & 192) >> 6); - else - k = (buf[j] & 15) << 2; - - j++; - break; - case 3: - k = buf[j++] & 63; - break; - } - *out++ = gg_base64_charset[k]; - i++; - } - - if (i % 4) - for (j = 0; j < 4 - (i % 4); j++, out++) - *out = '='; - - *out = 0; - - return res; -} - -/* - * gg_base64_decode() - * - * dekoduje ci�g znak�w z base64. - * - * - buf - ci�g znak�w. - * - * zaalokowany bufor. - */ -char *gg_base64_decode(const char *buf) -{ - const char *foo2; - char *res, *save, *foo, val; - const char *end; - unsigned int index = 0; - - if (!buf) - return NULL; - - save = res = calloc(1, (strlen(buf) / 4 + 1) * 3 + 2); - - if (!save) - return NULL; - - end = buf + strlen(buf); - - while (*buf && buf < end) { - if (*buf == '\r' || *buf == '\n') { - buf++; - continue; - } - if (!(foo2 = strchr(gg_base64_charset, *buf))) { - foo = gg_base64_charset; - } - else { - foo = foo2; - } - val = (int)(foo - gg_base64_charset); - buf++; - switch (index) { - case 0: - *res |= val << 2; - break; - case 1: - *res++ |= val >> 4; - *res |= val << 4; - break; - case 2: - *res++ |= val >> 2; - *res |= val << 6; - break; - case 3: - *res++ |= val; - break; - } - index++; - index %= 4; - } - *res = 0; - - return save; -} - -/* - * gg_proxy_auth() // funkcja wewn�trzna - * - * tworzy nag��wek autoryzacji dla proxy. - * - * zaalokowany tekst lub NULL, je�li proxy nie jest w��czone lub nie wymaga - * autoryzacji. - */ -char *gg_proxy_auth() -{ - char *tmp, *enc, *out; - unsigned int tmp_size; - - if (!gg_proxy_enabled || !gg_proxy_username || !gg_proxy_password) - return NULL; - - if (!(tmp = malloc((tmp_size = strlen(gg_proxy_username) + strlen(gg_proxy_password) + 2)))) - return NULL; - - snprintf(tmp, tmp_size, "%s:%s", gg_proxy_username, gg_proxy_password); - - if (!(enc = gg_base64_encode(tmp))) { - free(tmp); - return NULL; - } - - free(tmp); - - if (!(out = malloc(strlen(enc) + 40))) { - free(enc); - return NULL; - } - - snprintf(out, strlen(enc) + 40, "Proxy-Authorization: Basic %s\r\n", enc); - - free(enc); - - return out; -} - -static uint32_t gg_crc32_table[256]; -static int gg_crc32_initialized = 0; - -/* - * gg_crc32_make_table() // funkcja wewn�trzna - */ -static void gg_crc32_make_table() -{ - uint32_t h = 1; - unsigned int i, j; - - memset(gg_crc32_table, 0, sizeof(gg_crc32_table)); - - for (i = 128; i; i >>= 1) { - h = (h >> 1) ^ ((h & 1) ? 0xedb88320L : 0); - - for (j = 0; j < 256; j += 2 * i) - gg_crc32_table[i + j] = gg_crc32_table[j] ^ h; - } - - gg_crc32_initialized = 1; -} - -/* - * gg_crc32() - * - * wyznacza sum� kontroln� CRC32 danego bloku danych. - * - * - crc - suma kontrola poprzedniego bloku danych lub 0 je�li pierwszy - * - buf - bufor danych - * - size - ilo�� danych - * - * suma kontrolna CRC32. - */ -uint32_t gg_crc32(uint32_t crc, const unsigned char *buf, int len) -{ - if (!gg_crc32_initialized) - gg_crc32_make_table(); - - if (!buf || len < 0) - return crc; - - crc ^= 0xffffffffL; - - while (len--) - crc = (crc >> 8) ^ gg_crc32_table[(crc ^ *buf++) & 0xff]; - - return crc ^ 0xffffffffL; -} - - -/* - * Local variables: - * c-indentation-style: k&r - * c-basic-offset: 8 - * indent-tabs-mode: notnil - * End: - * - * vim: shiftwidth=8: - */ diff --git a/kopete/protocols/gadu/libgadu/compat.h b/kopete/protocols/gadu/libgadu/compat.h deleted file mode 100644 index 8b9098fe..00000000 --- a/kopete/protocols/gadu/libgadu/compat.h +++ /dev/null @@ -1,29 +0,0 @@ -/* $Id$ */ - -/* - * (C) Copyright 2001-2002 Wojtek Kaniewski <wojtekka@irc.pl> - * Robert J. Wo¼ny <speedy@ziew.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License Version - * 2.1 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA. - */ - -#ifndef __COMPAT_H -#define __COMPAT_H - -#ifdef sun -# define INADDR_NONE ((in_addr_t) 0xffffffff) -#endif - -#endif diff --git a/kopete/protocols/gadu/libgadu/dcc.c b/kopete/protocols/gadu/libgadu/dcc.c deleted file mode 100644 index d6b3c7cc..00000000 --- a/kopete/protocols/gadu/libgadu/dcc.c +++ /dev/null @@ -1,1298 +0,0 @@ -/* $Id$ */ - -/* - * (C) Copyright 2001-2006 Wojtek Kaniewski <wojtekka@irc.pl> - * Tomasz Chiliñski <chilek@chilan.com> - * Adam Wysocki <gophi@ekg.chmurka.net> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License Version - * 2.1 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA. - */ - -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/ioctl.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#ifdef sun -# include <sys/filio.h> -#endif - -#include <ctype.h> -#include <errno.h> -#include <fcntl.h> -#include <stdarg.h> -#include <string.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> - -#include "compat.h" -#include "libgadu.h" - -#ifndef GG_DEBUG_DISABLE -/* - * gg_dcc_debug_data() // funkcja wewnêtrzna - * - * wy¶wietla zrzut pakietu w hexie. - * - * - prefix - prefiks zrzutu pakietu - * - fd - deskryptor gniazda - * - buf - bufor z danymi - * - size - rozmiar danych - */ -static void gg_dcc_debug_data(const char *prefix, int fd, const void *buf, unsigned int size) -{ - unsigned int i; - - gg_debug(GG_DEBUG_MISC, "++ gg_dcc %s (fd=%d,len=%d)", prefix, fd, size); - - for (i = 0; i < size; i++) - gg_debug(GG_DEBUG_MISC, " %.2x", ((unsigned char*) buf)[i]); - - gg_debug(GG_DEBUG_MISC, "\n"); -} -#else -#define gg_dcc_debug_data(a,b,c,d) do { } while (0) -#endif - -/* - * gg_dcc_request() - * - * wysy³a informacjê o tym, ¿e dany klient powinien siê z nami po³±czyæ. - * wykorzystywane, kiedy druga strona, której chcemy co¶ wys³aæ jest za - * maskarad±. - * - * - sess - struktura opisuj±ca sesjê GG - * - uin - numerek odbiorcy - * - * patrz gg_send_message_ctcp(). - */ -int gg_dcc_request(struct gg_session *sess, uin_t uin) -{ - return gg_send_message_ctcp(sess, GG_CLASS_CTCP, uin, "\002", 1); -} - -/* - * gg_dcc_fill_filetime() // funkcja wewnêtrzna - * - * zamienia czas w postaci unixowej na windowsowy. - * - * - unix - czas w postaci unixowej - * - filetime - czas w postaci windowsowej - */ -static void gg_dcc_fill_filetime(uint32_t ut, uint32_t *ft) -{ -#ifdef __GG_LIBGADU_HAVE_LONG_LONG - unsigned long long tmp; - - tmp = ut; - tmp += 11644473600LL; - tmp *= 10000000LL; - -#ifndef __GG_LIBGADU_BIGENDIAN - ft[0] = (uint32_t) tmp; - ft[1] = (uint32_t) (tmp >> 32); -#else - ft[0] = gg_fix32((uint32_t) (tmp >> 32)); - ft[1] = gg_fix32((uint32_t) tmp); -#endif - -#endif -} - -/* - * gg_dcc_fill_file_info() - * - * wype³nia pola struct gg_dcc niezbêdne do wys³ania pliku. - * - * - d - struktura opisuj±ca po³±czenie DCC - * - filename - nazwa pliku - * - * 0, -1. - */ -int gg_dcc_fill_file_info(struct gg_dcc *d, const char *filename) -{ - return gg_dcc_fill_file_info2(d, filename, filename); -} - -/* - * gg_dcc_fill_file_info2() - * - * wype³nia pola struct gg_dcc niezbêdne do wys³ania pliku. - * - * - d - struktura opisuj±ca po³±czenie DCC - * - filename - nazwa pliku - * - local_filename - nazwa na lokalnym systemie plików - * - * 0, -1. - */ -int gg_dcc_fill_file_info2(struct gg_dcc *d, const char *filename, const char *local_filename) -{ - struct stat st; - const char *name, *ext, *p; - unsigned char *q; - int i, j; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_dcc_fill_file_info2(%p, \"%s\", \"%s\");\n", d, filename, local_filename); - - if (!d || d->type != GG_SESSION_DCC_SEND) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_fill_file_info2() invalid arguments\n"); - errno = EINVAL; - return -1; - } - - if (stat(local_filename, &st) == -1) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_fill_file_info2() stat() failed (%s)\n", strerror(errno)); - return -1; - } - - if ((st.st_mode & S_IFDIR)) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_fill_file_info2() that's a directory\n"); - errno = EINVAL; - return -1; - } - - if ((d->file_fd = open(local_filename, O_RDONLY)) == -1) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_fill_file_info2() open() failed (%s)\n", strerror(errno)); - return -1; - } - - memset(&d->file_info, 0, sizeof(d->file_info)); - - if (!(st.st_mode & S_IWUSR)) - d->file_info.mode |= gg_fix32(GG_DCC_FILEATTR_READONLY); - - gg_dcc_fill_filetime(st.st_atime, d->file_info.atime); - gg_dcc_fill_filetime(st.st_mtime, d->file_info.mtime); - gg_dcc_fill_filetime(st.st_ctime, d->file_info.ctime); - - d->file_info.size = gg_fix32(st.st_size); - d->file_info.mode = gg_fix32(0x20); /* FILE_ATTRIBUTE_ARCHIVE */ - - if (!(name = strrchr(filename, '/'))) - name = filename; - else - name++; - - if (!(ext = strrchr(name, '.'))) - ext = name + strlen(name); - - for (i = 0, p = name; i < 8 && p < ext; i++, p++) - d->file_info.short_filename[i] = toupper(name[i]); - - if (i == 8 && p < ext) { - d->file_info.short_filename[6] = '~'; - d->file_info.short_filename[7] = '1'; - } - - if (strlen(ext) > 0) { - for (j = 0; *ext && j < 4; j++, p++) - d->file_info.short_filename[i + j] = toupper(ext[j]); - } - - for (q = d->file_info.short_filename; *q; q++) { - if (*q == 185) { - *q = 165; - } else if (*q == 230) { - *q = 198; - } else if (*q == 234) { - *q = 202; - } else if (*q == 179) { - *q = 163; - } else if (*q == 241) { - *q = 209; - } else if (*q == 243) { - *q = 211; - } else if (*q == 156) { - *q = 140; - } else if (*q == 159) { - *q = 143; - } else if (*q == 191) { - *q = 175; - } - } - - gg_debug(GG_DEBUG_MISC, "// gg_dcc_fill_file_info2() short name \"%s\", dos name \"%s\"\n", name, d->file_info.short_filename); - strncpy(d->file_info.filename, name, sizeof(d->file_info.filename) - 1); - - return 0; -} - -/* - * gg_dcc_transfer() // funkcja wewnêtrzna - * - * inicjuje proces wymiany pliku z danym klientem. - * - * - ip - adres ip odbiorcy - * - port - port odbiorcy - * - my_uin - w³asny numer - * - peer_uin - numer obiorcy - * - type - rodzaj wymiany (GG_SESSION_DCC_SEND lub GG_SESSION_DCC_GET) - * - * zaalokowana struct gg_dcc lub NULL je¶li wyst±pi³ b³±d. - */ -static struct gg_dcc *gg_dcc_transfer(uint32_t ip, uint16_t port, uin_t my_uin, uin_t peer_uin, int type) -{ - struct gg_dcc *d = NULL; - struct in_addr addr; - - addr.s_addr = ip; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_dcc_transfer(%s, %d, %ld, %ld, %s);\n", inet_ntoa(addr), port, my_uin, peer_uin, (type == GG_SESSION_DCC_SEND) ? "SEND" : "GET"); - - if (!ip || ip == INADDR_NONE || !port || !my_uin || !peer_uin) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_transfer() invalid arguments\n"); - errno = EINVAL; - return NULL; - } - - if (!(d = (void*) calloc(1, sizeof(*d)))) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_transfer() not enough memory\n"); - return NULL; - } - - d->check = GG_CHECK_WRITE; - d->state = GG_STATE_CONNECTING; - d->type = type; - d->timeout = GG_DEFAULT_TIMEOUT; - d->file_fd = -1; - d->active = 1; - d->fd = -1; - d->uin = my_uin; - d->peer_uin = peer_uin; - - if ((d->fd = gg_connect(&addr, port, 1)) == -1) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_transfer() connection failed\n"); - free(d); - return NULL; - } - - return d; -} - -/* - * gg_dcc_get_file() - * - * inicjuje proces odbierania pliku od danego klienta, gdy ten wys³a³ do - * nas ¿±danie po³±czenia. - * - * - ip - adres ip odbiorcy - * - port - port odbiorcy - * - my_uin - w³asny numer - * - peer_uin - numer obiorcy - * - * zaalokowana struct gg_dcc lub NULL je¶li wyst±pi³ b³±d. - */ -struct gg_dcc *gg_dcc_get_file(uint32_t ip, uint16_t port, uin_t my_uin, uin_t peer_uin) -{ - gg_debug(GG_DEBUG_MISC, "// gg_dcc_get_file() handing over to gg_dcc_transfer()\n"); - - return gg_dcc_transfer(ip, port, my_uin, peer_uin, GG_SESSION_DCC_GET); -} - -/* - * gg_dcc_send_file() - * - * inicjuje proces wysy³ania pliku do danego klienta. - * - * - ip - adres ip odbiorcy - * - port - port odbiorcy - * - my_uin - w³asny numer - * - peer_uin - numer obiorcy - * - * zaalokowana struct gg_dcc lub NULL je¶li wyst±pi³ b³±d. - */ -struct gg_dcc *gg_dcc_send_file(uint32_t ip, uint16_t port, uin_t my_uin, uin_t peer_uin) -{ - gg_debug(GG_DEBUG_MISC, "// gg_dcc_send_file() handing over to gg_dcc_transfer()\n"); - - return gg_dcc_transfer(ip, port, my_uin, peer_uin, GG_SESSION_DCC_SEND); -} - -/* - * gg_dcc_voice_chat() - * - * próbuje nawi±zaæ po³±czenie g³osowe. - * - * - ip - adres ip odbiorcy - * - port - port odbiorcy - * - my_uin - w³asny numer - * - peer_uin - numer obiorcy - * - * zaalokowana struct gg_dcc lub NULL je¶li wyst±pi³ b³±d. - */ -struct gg_dcc *gg_dcc_voice_chat(uint32_t ip, uint16_t port, uin_t my_uin, uin_t peer_uin) -{ - gg_debug(GG_DEBUG_MISC, "// gg_dcc_voice_chat() handing over to gg_dcc_transfer()\n"); - - return gg_dcc_transfer(ip, port, my_uin, peer_uin, GG_SESSION_DCC_VOICE); -} - -/* - * gg_dcc_set_type() - * - * po zdarzeniu GG_EVENT_DCC_CALLBACK nale¿y ustawiæ typ po³±czenia za - * pomoc± tej funkcji. - * - * - d - struktura opisuj±ca po³±czenie - * - type - typ po³±czenia (GG_SESSION_DCC_SEND lub GG_SESSION_DCC_VOICE) - */ -void gg_dcc_set_type(struct gg_dcc *d, int type) -{ - d->type = type; - d->state = (type == GG_SESSION_DCC_SEND) ? GG_STATE_SENDING_FILE_INFO : GG_STATE_SENDING_VOICE_REQUEST; -} - -/* - * gg_dcc_callback() // funkcja wewnêtrzna - * - * wywo³ywana z struct gg_dcc->callback, odpala gg_dcc_watch_fd i umieszcza - * rezultat w struct gg_dcc->event. - * - * - d - structura opisuj±ca po³±czenie - * - * 0, -1. - */ -static int gg_dcc_callback(struct gg_dcc *d) -{ - struct gg_event *e = gg_dcc_watch_fd(d); - - d->event = e; - - return (e != NULL) ? 0 : -1; -} - -/* - * gg_dcc_socket_create() - * - * tworzy gniazdo dla bezpo¶redniej komunikacji miêdzy klientami. - * - * - uin - w³asny numer - * - port - preferowany port, je¶li równy 0 lub -1, próbuje domy¶lnego - * - * zaalokowana struct gg_dcc, któr± po¼niej nale¿y zwolniæ funkcj± - * gg_dcc_free(), albo NULL je¶li wyst±pi³ b³±d. - */ -struct gg_dcc *gg_dcc_socket_create(uin_t uin, uint16_t port) -{ - struct gg_dcc *c; - struct sockaddr_in sin; - int sock, bound = 0, errno2; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_create_dcc_socket(%d, %d);\n", uin, port); - - if (!uin) { - gg_debug(GG_DEBUG_MISC, "// gg_create_dcc_socket() invalid arguments\n"); - errno = EINVAL; - return NULL; - } - - if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) { - gg_debug(GG_DEBUG_MISC, "// gg_create_dcc_socket() can't create socket (%s)\n", strerror(errno)); - return NULL; - } - - if (!port) - port = GG_DEFAULT_DCC_PORT; - - while (!bound) { - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = INADDR_ANY; - sin.sin_port = htons(port); - - gg_debug(GG_DEBUG_MISC, "// gg_create_dcc_socket() trying port %d\n", port); - if (!bind(sock, (struct sockaddr*) &sin, sizeof(sin))) - bound = 1; - else { - if (++port == 65535) { - gg_debug(GG_DEBUG_MISC, "// gg_create_dcc_socket() no free port found\n"); - close(sock); - return NULL; - } - } - } - - if (listen(sock, 10)) { - gg_debug(GG_DEBUG_MISC, "// gg_create_dcc_socket() unable to listen (%s)\n", strerror(errno)); - errno2 = errno; - close(sock); - errno = errno2; - return NULL; - } - - gg_debug(GG_DEBUG_MISC, "// gg_create_dcc_socket() bound to port %d\n", port); - - if (!(c = malloc(sizeof(*c)))) { - gg_debug(GG_DEBUG_MISC, "// gg_create_dcc_socket() not enough memory for struct\n"); - close(sock); - return NULL; - } - memset(c, 0, sizeof(*c)); - - c->port = c->id = port; - c->fd = sock; - c->type = GG_SESSION_DCC_SOCKET; - c->uin = uin; - c->timeout = -1; - c->state = GG_STATE_LISTENING; - c->check = GG_CHECK_READ; - c->callback = gg_dcc_callback; - c->destroy = gg_dcc_free; - - return c; -} - -/* - * gg_dcc_voice_send() - * - * wysy³a ramkê danych dla rozmowy g³osowej. - * - * - d - struktura opisuj±ca po³±czenie dcc - * - buf - bufor z danymi - * - length - rozmiar ramki - * - * 0, -1. - */ -int gg_dcc_voice_send(struct gg_dcc *d, char *buf, int length) -{ - struct packet_s { - uint8_t type; - uint32_t length; - } GG_PACKED; - struct packet_s packet; - - gg_debug(GG_DEBUG_FUNCTION, "++ gg_dcc_voice_send(%p, %p, %d);\n", d, buf, length); - if (!d || !buf || length < 0 || d->type != GG_SESSION_DCC_VOICE) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_voice_send() invalid argument\n"); - errno = EINVAL; - return -1; - } - - packet.type = 0x03; /* XXX */ - packet.length = gg_fix32(length); - - if (write(d->fd, &packet, sizeof(packet)) < (signed)sizeof(packet)) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_voice_send() write() failed\n"); - return -1; - } - gg_dcc_debug_data("write", d->fd, &packet, sizeof(packet)); - - if (write(d->fd, buf, length) < length) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_voice_send() write() failed\n"); - return -1; - } - gg_dcc_debug_data("write", d->fd, buf, length); - - return 0; -} - -#define gg_read(fd, buf, size) \ -{ \ - int tmp = read(fd, buf, size); \ - \ - if (tmp < (int) size) { \ - if (tmp == -1) { \ - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() read() failed (errno=%d, %s)\n", errno, strerror(errno)); \ - } else if (tmp == 0) { \ - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() read() failed, connection broken\n"); \ - } else { \ - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() read() failed (%d bytes, %d needed)\n", tmp, size); \ - } \ - e->type = GG_EVENT_DCC_ERROR; \ - e->event.dcc_error = GG_ERROR_DCC_HANDSHAKE; \ - return e; \ - } \ - gg_dcc_debug_data("read", fd, buf, size); \ -} - -#define gg_write(fd, buf, size) \ -{ \ - int tmp; \ - gg_dcc_debug_data("write", fd, buf, size); \ - tmp = write(fd, buf, size); \ - if (tmp < (int) size) { \ - if (tmp == -1) { \ - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() write() failed (errno=%d, %s)\n", errno, strerror(errno)); \ - } else { \ - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() write() failed (%d needed, %d done)\n", size, tmp); \ - } \ - e->type = GG_EVENT_DCC_ERROR; \ - e->event.dcc_error = GG_ERROR_DCC_HANDSHAKE; \ - return e; \ - } \ -} - -/* - * gg_dcc_watch_fd() - * - * funkcja, któr± nale¿y wywo³aæ, gdy co¶ siê zmieni na gg_dcc->fd. - * - * - h - struktura zwrócona przez gg_create_dcc_socket() - * - * zaalokowana struct gg_event lub NULL, je¶li zabrak³o pamiêci na ni±. - */ -struct gg_event *gg_dcc_watch_fd(struct gg_dcc *h) -{ - struct gg_event *e; - int foo; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_dcc_watch_fd(%p);\n", h); - - if (!h || (h->type != GG_SESSION_DCC && h->type != GG_SESSION_DCC_SOCKET && h->type != GG_SESSION_DCC_SEND && h->type != GG_SESSION_DCC_GET && h->type != GG_SESSION_DCC_VOICE)) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() invalid argument\n"); - errno = EINVAL; - return NULL; - } - - if (!(e = (void*) calloc(1, sizeof(*e)))) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() not enough memory\n"); - return NULL; - } - - e->type = GG_EVENT_NONE; - - if (h->type == GG_SESSION_DCC_SOCKET) { - struct sockaddr_in sin; - struct gg_dcc *c; - int fd, sin_len = sizeof(sin), one = 1; - - if ((fd = accept(h->fd, (struct sockaddr*) &sin, &sin_len)) == -1) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() can't accept() new connection (errno=%d, %s)\n", errno, strerror(errno)); - return e; - } - - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() new direct connection from %s:%d\n", inet_ntoa(sin.sin_addr), htons(sin.sin_port)); - -#ifdef FIONBIO - if (ioctl(fd, FIONBIO, &one) == -1) { -#else - if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1) { -#endif - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() can't set nonblocking (errno=%d, %s)\n", errno, strerror(errno)); - close(fd); - e->type = GG_EVENT_DCC_ERROR; - e->event.dcc_error = GG_ERROR_DCC_HANDSHAKE; - return e; - } - - if (!(c = (void*) calloc(1, sizeof(*c)))) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() not enough memory for client data\n"); - - free(e); - close(fd); - return NULL; - } - - c->fd = fd; - c->check = GG_CHECK_READ; - c->state = GG_STATE_READING_UIN_1; - c->type = GG_SESSION_DCC; - c->timeout = GG_DEFAULT_TIMEOUT; - c->file_fd = -1; - c->remote_addr = sin.sin_addr.s_addr; - c->remote_port = ntohs(sin.sin_port); - - e->type = GG_EVENT_DCC_NEW; - e->event.dcc_new = c; - - return e; - } else { - struct gg_dcc_tiny_packet tiny; - struct gg_dcc_small_packet small; - struct gg_dcc_big_packet big; - int size, tmp, res, res_size = sizeof(res); - unsigned int utmp; - char buf[1024], ack[] = "UDAG"; - - struct gg_dcc_file_info_packet { - struct gg_dcc_big_packet big; - struct gg_file_info file_info; - } GG_PACKED; - struct gg_dcc_file_info_packet file_info_packet; - - switch (h->state) { - case GG_STATE_READING_UIN_1: - case GG_STATE_READING_UIN_2: - { - uin_t uin; - - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_READING_UIN_%d\n", (h->state == GG_STATE_READING_UIN_1) ? 1 : 2); - - gg_read(h->fd, &uin, sizeof(uin)); - - if (h->state == GG_STATE_READING_UIN_1) { - h->state = GG_STATE_READING_UIN_2; - h->check = GG_CHECK_READ; - h->timeout = GG_DEFAULT_TIMEOUT; - h->peer_uin = gg_fix32(uin); - } else { - h->state = GG_STATE_SENDING_ACK; - h->check = GG_CHECK_WRITE; - h->timeout = GG_DEFAULT_TIMEOUT; - h->uin = gg_fix32(uin); - e->type = GG_EVENT_DCC_CLIENT_ACCEPT; - } - - return e; - } - - case GG_STATE_SENDING_ACK: - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_SENDING_ACK\n"); - - gg_write(h->fd, ack, 4); - - h->state = GG_STATE_READING_TYPE; - h->check = GG_CHECK_READ; - h->timeout = GG_DEFAULT_TIMEOUT; - - return e; - - case GG_STATE_READING_TYPE: - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_READING_TYPE\n"); - - gg_read(h->fd, &small, sizeof(small)); - - small.type = gg_fix32(small.type); - - switch (small.type) { - case 0x0003: /* XXX */ - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() callback\n"); - h->type = GG_SESSION_DCC_SEND; - h->state = GG_STATE_SENDING_FILE_INFO; - h->check = GG_CHECK_WRITE; - h->timeout = GG_DEFAULT_TIMEOUT; - - e->type = GG_EVENT_DCC_CALLBACK; - - break; - - case 0x0002: /* XXX */ - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() dialin\n"); - h->type = GG_SESSION_DCC_GET; - h->state = GG_STATE_READING_REQUEST; - h->check = GG_CHECK_READ; - h->timeout = GG_DEFAULT_TIMEOUT; - h->incoming = 1; - - break; - - default: - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() unknown dcc type (%.4x) from %ld\n", small.type, h->peer_uin); - e->type = GG_EVENT_DCC_ERROR; - e->event.dcc_error = GG_ERROR_DCC_HANDSHAKE; - } - - return e; - - case GG_STATE_READING_REQUEST: - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_READING_REQUEST\n"); - - gg_read(h->fd, &small, sizeof(small)); - - small.type = gg_fix32(small.type); - - switch (small.type) { - case 0x0001: /* XXX */ - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() file transfer request\n"); - h->state = GG_STATE_READING_FILE_INFO; - h->check = GG_CHECK_READ; - h->timeout = GG_DEFAULT_TIMEOUT; - break; - - case 0x0003: /* XXX */ - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() voice chat request\n"); - h->state = GG_STATE_SENDING_VOICE_ACK; - h->check = GG_CHECK_WRITE; - h->timeout = GG_DCC_TIMEOUT_VOICE_ACK; - h->type = GG_SESSION_DCC_VOICE; - e->type = GG_EVENT_DCC_NEED_VOICE_ACK; - - break; - - default: - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() unknown dcc request (%.4x) from %ld\n", small.type, h->peer_uin); - e->type = GG_EVENT_DCC_ERROR; - e->event.dcc_error = GG_ERROR_DCC_HANDSHAKE; - } - - return e; - - case GG_STATE_READING_FILE_INFO: - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_READING_FILE_INFO\n"); - - gg_read(h->fd, &file_info_packet, sizeof(file_info_packet)); - - memcpy(&h->file_info, &file_info_packet.file_info, sizeof(h->file_info)); - - h->file_info.mode = gg_fix32(h->file_info.mode); - h->file_info.size = gg_fix32(h->file_info.size); - - h->state = GG_STATE_SENDING_FILE_ACK; - h->check = GG_CHECK_WRITE; - h->timeout = GG_DCC_TIMEOUT_FILE_ACK; - - e->type = GG_EVENT_DCC_NEED_FILE_ACK; - - return e; - - case GG_STATE_SENDING_FILE_ACK: - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_SENDING_FILE_ACK\n"); - - big.type = gg_fix32(0x0006); /* XXX */ - big.dunno1 = gg_fix32(h->offset); - big.dunno2 = 0; - - gg_write(h->fd, &big, sizeof(big)); - - h->state = GG_STATE_READING_FILE_HEADER; - h->chunk_size = sizeof(big); - h->chunk_offset = 0; - if (!(h->chunk_buf = malloc(sizeof(big)))) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() out of memory\n"); - free(e); - return NULL; - } - h->check = GG_CHECK_READ; - h->timeout = GG_DEFAULT_TIMEOUT; - - return e; - - case GG_STATE_SENDING_VOICE_ACK: - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_SENDING_VOICE_ACK\n"); - - tiny.type = 0x01; /* XXX */ - - gg_write(h->fd, &tiny, sizeof(tiny)); - - h->state = GG_STATE_READING_VOICE_HEADER; - h->check = GG_CHECK_READ; - h->timeout = GG_DEFAULT_TIMEOUT; - - h->offset = 0; - - return e; - - case GG_STATE_READING_FILE_HEADER: - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_READING_FILE_HEADER\n"); - - tmp = read(h->fd, h->chunk_buf + h->chunk_offset, h->chunk_size - h->chunk_offset); - - if (tmp == -1) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() read() failed (errno=%d, %s)\n", errno, strerror(errno)); - e->type = GG_EVENT_DCC_ERROR; - e->event.dcc_error = GG_ERROR_DCC_NET; - return e; - } - - gg_dcc_debug_data("read", h->fd, h->chunk_buf + h->chunk_offset, h->chunk_size - h->chunk_offset); - - h->chunk_offset += tmp; - - if (h->chunk_offset < h->chunk_size) - return e; - - memcpy(&big, h->chunk_buf, sizeof(big)); - free(h->chunk_buf); - h->chunk_buf = NULL; - - big.type = gg_fix32(big.type); - h->chunk_size = gg_fix32(big.dunno1); - h->chunk_offset = 0; - - if (big.type == 0x0005) { /* XXX */ - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() transfer refused\n"); - e->type = GG_EVENT_DCC_ERROR; - e->event.dcc_error = GG_ERROR_DCC_REFUSED; - return e; - } - - if (h->chunk_size == 0) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() empty chunk, EOF\n"); - e->type = GG_EVENT_DCC_DONE; - return e; - } - - h->state = GG_STATE_GETTING_FILE; - h->check = GG_CHECK_READ; - h->timeout = GG_DEFAULT_TIMEOUT; - h->established = 1; - - return e; - - case GG_STATE_READING_VOICE_HEADER: - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_READING_VOICE_HEADER\n"); - - gg_read(h->fd, &tiny, sizeof(tiny)); - - switch (tiny.type) { - case 0x03: /* XXX */ - h->state = GG_STATE_READING_VOICE_SIZE; - h->check = GG_CHECK_READ; - h->timeout = GG_DEFAULT_TIMEOUT; - h->established = 1; - break; - case 0x04: /* XXX */ - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() peer breaking connection\n"); - /* XXX zwracaæ odpowiedni event */ - default: - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() unknown request (%.2x)\n", tiny.type); - e->type = GG_EVENT_DCC_ERROR; - e->event.dcc_error = GG_ERROR_DCC_HANDSHAKE; - } - - return e; - - case GG_STATE_READING_VOICE_SIZE: - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_READING_VOICE_SIZE\n"); - - gg_read(h->fd, &small, sizeof(small)); - - small.type = gg_fix32(small.type); - - if (small.type < 16 || small.type > sizeof(buf)) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() invalid voice frame size (%d)\n", small.type); - e->type = GG_EVENT_DCC_ERROR; - e->event.dcc_error = GG_ERROR_DCC_NET; - - return e; - } - - h->chunk_size = small.type; - h->chunk_offset = 0; - - if (!(h->voice_buf = malloc(h->chunk_size))) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() out of memory for voice frame\n"); - free(e); - return NULL; - } - - h->state = GG_STATE_READING_VOICE_DATA; - h->check = GG_CHECK_READ; - h->timeout = GG_DEFAULT_TIMEOUT; - - return e; - - case GG_STATE_READING_VOICE_DATA: - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_READING_VOICE_DATA\n"); - - tmp = read(h->fd, h->voice_buf + h->chunk_offset, h->chunk_size - h->chunk_offset); - if (tmp < 1) { - if (tmp == -1) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() read() failed (errno=%d, %s)\n", errno, strerror(errno)); - } else { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() read() failed, connection broken\n"); - } - e->type = GG_EVENT_DCC_ERROR; - e->event.dcc_error = GG_ERROR_DCC_NET; - return e; - } - - gg_dcc_debug_data("read", h->fd, h->voice_buf + h->chunk_offset, tmp); - - h->chunk_offset += tmp; - - if (h->chunk_offset >= h->chunk_size) { - e->type = GG_EVENT_DCC_VOICE_DATA; - e->event.dcc_voice_data.data = h->voice_buf; - e->event.dcc_voice_data.length = h->chunk_size; - h->state = GG_STATE_READING_VOICE_HEADER; - h->voice_buf = NULL; - } - - h->check = GG_CHECK_READ; - h->timeout = GG_DEFAULT_TIMEOUT; - - return e; - - case GG_STATE_CONNECTING: - { - uin_t uins[2]; - - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_CONNECTING\n"); - - res = 0; - if ((foo = getsockopt(h->fd, SOL_SOCKET, SO_ERROR, &res, &res_size)) || res) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() connection failed (fd=%d,errno=%d(%s),foo=%d,res=%d(%s))\n", h->fd, errno, strerror(errno), foo, res, strerror(res)); - e->type = GG_EVENT_DCC_ERROR; - e->event.dcc_error = GG_ERROR_DCC_HANDSHAKE; - return e; - } - - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() connected, sending uins\n"); - - uins[0] = gg_fix32(h->uin); - uins[1] = gg_fix32(h->peer_uin); - - gg_write(h->fd, uins, sizeof(uins)); - - h->state = GG_STATE_READING_ACK; - h->check = GG_CHECK_READ; - h->timeout = GG_DEFAULT_TIMEOUT; - - return e; - } - - case GG_STATE_READING_ACK: - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_READING_ACK\n"); - - gg_read(h->fd, buf, 4); - - if (strncmp(buf, ack, 4)) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() did't get ack\n"); - - e->type = GG_EVENT_DCC_ERROR; - e->event.dcc_error = GG_ERROR_DCC_HANDSHAKE; - return e; - } - - h->check = GG_CHECK_WRITE; - h->timeout = GG_DEFAULT_TIMEOUT; - h->state = GG_STATE_SENDING_REQUEST; - - return e; - - case GG_STATE_SENDING_VOICE_REQUEST: - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_SENDING_VOICE_REQUEST\n"); - - small.type = gg_fix32(0x0003); - - gg_write(h->fd, &small, sizeof(small)); - - h->state = GG_STATE_READING_VOICE_ACK; - h->check = GG_CHECK_READ; - h->timeout = GG_DEFAULT_TIMEOUT; - - return e; - - case GG_STATE_SENDING_REQUEST: - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_SENDING_REQUEST\n"); - - small.type = (h->type == GG_SESSION_DCC_GET) ? gg_fix32(0x0003) : gg_fix32(0x0002); /* XXX */ - - gg_write(h->fd, &small, sizeof(small)); - - switch (h->type) { - case GG_SESSION_DCC_GET: - h->state = GG_STATE_READING_REQUEST; - h->check = GG_CHECK_READ; - h->timeout = GG_DEFAULT_TIMEOUT; - break; - - case GG_SESSION_DCC_SEND: - h->state = GG_STATE_SENDING_FILE_INFO; - h->check = GG_CHECK_WRITE; - h->timeout = GG_DEFAULT_TIMEOUT; - - if (h->file_fd == -1) - e->type = GG_EVENT_DCC_NEED_FILE_INFO; - break; - - case GG_SESSION_DCC_VOICE: - h->state = GG_STATE_SENDING_VOICE_REQUEST; - h->check = GG_CHECK_WRITE; - h->timeout = GG_DEFAULT_TIMEOUT; - break; - } - - return e; - - case GG_STATE_SENDING_FILE_INFO: - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_SENDING_FILE_INFO\n"); - - if (h->file_fd == -1) { - e->type = GG_EVENT_DCC_NEED_FILE_INFO; - return e; - } - - small.type = gg_fix32(0x0001); /* XXX */ - - gg_write(h->fd, &small, sizeof(small)); - - file_info_packet.big.type = gg_fix32(0x0003); /* XXX */ - file_info_packet.big.dunno1 = 0; - file_info_packet.big.dunno2 = 0; - - memcpy(&file_info_packet.file_info, &h->file_info, sizeof(h->file_info)); - - /* zostaj± teraz u nas, wiêc odwracamy z powrotem */ - h->file_info.size = gg_fix32(h->file_info.size); - h->file_info.mode = gg_fix32(h->file_info.mode); - - gg_write(h->fd, &file_info_packet, sizeof(file_info_packet)); - - h->state = GG_STATE_READING_FILE_ACK; - h->check = GG_CHECK_READ; - h->timeout = GG_DCC_TIMEOUT_FILE_ACK; - - return e; - - case GG_STATE_READING_FILE_ACK: - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_READING_FILE_ACK\n"); - - gg_read(h->fd, &big, sizeof(big)); - - /* XXX sprawdzaæ wynik */ - h->offset = gg_fix32(big.dunno1); - - h->state = GG_STATE_SENDING_FILE_HEADER; - h->check = GG_CHECK_WRITE; - h->timeout = GG_DEFAULT_TIMEOUT; - - e->type = GG_EVENT_DCC_ACK; - - return e; - - case GG_STATE_READING_VOICE_ACK: - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_READING_VOICE_ACK\n"); - - gg_read(h->fd, &tiny, sizeof(tiny)); - - if (tiny.type != 0x01) { - gg_debug(GG_DEBUG_MISC, "// invalid reply (%.2x), connection refused\n", tiny.type); - e->type = GG_EVENT_DCC_ERROR; - e->event.dcc_error = GG_ERROR_DCC_REFUSED; - return e; - } - - h->state = GG_STATE_READING_VOICE_HEADER; - h->check = GG_CHECK_READ; - h->timeout = GG_DEFAULT_TIMEOUT; - - e->type = GG_EVENT_DCC_ACK; - - return e; - - case GG_STATE_SENDING_FILE_HEADER: - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_SENDING_FILE_HEADER\n"); - - h->chunk_offset = 0; - - if ((h->chunk_size = h->file_info.size - h->offset) > 4096) { - h->chunk_size = 4096; - big.type = gg_fix32(0x0003); /* XXX */ - } else - big.type = gg_fix32(0x0002); /* XXX */ - - big.dunno1 = gg_fix32(h->chunk_size); - big.dunno2 = 0; - - gg_write(h->fd, &big, sizeof(big)); - - h->state = GG_STATE_SENDING_FILE; - h->check = GG_CHECK_WRITE; - h->timeout = GG_DEFAULT_TIMEOUT; - h->established = 1; - - return e; - - case GG_STATE_SENDING_FILE: - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_SENDING_FILE\n"); - - if ((utmp = h->chunk_size - h->chunk_offset) > sizeof(buf)) - utmp = sizeof(buf); - - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() offset=%d, size=%d\n", h->offset, h->file_info.size); - - /* koniec pliku? */ - if (h->file_info.size == 0) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() read() reached eof on empty file\n"); - e->type = GG_EVENT_DCC_DONE; - - return e; - } - - lseek(h->file_fd, h->offset, SEEK_SET); - - size = read(h->file_fd, buf, utmp); - - /* b³±d */ - if (size == -1) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() read() failed. (errno=%d, %s)\n", errno, strerror(errno)); - - e->type = GG_EVENT_DCC_ERROR; - e->event.dcc_error = GG_ERROR_DCC_FILE; - - return e; - } - - /* koniec pliku? */ - if (size == 0) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() read() reached eof\n"); - e->type = GG_EVENT_DCC_ERROR; - e->event.dcc_error = GG_ERROR_DCC_EOF; - - return e; - } - - /* je¶li wczytali¶my wiêcej, utnijmy. */ - if (h->offset + size > h->file_info.size) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() read() too much (read=%d, ofs=%d, size=%d)\n", size, h->offset, h->file_info.size); - size = h->file_info.size - h->offset; - - if (size < 1) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() reached EOF after cutting\n"); - e->type = GG_EVENT_DCC_DONE; - return e; - } - } - - tmp = write(h->fd, buf, size); - - if (tmp == -1) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() write() failed (%s)\n", strerror(errno)); - e->type = GG_EVENT_DCC_ERROR; - e->event.dcc_error = GG_ERROR_DCC_NET; - return e; - } - - h->offset += size; - - if (h->offset >= h->file_info.size) { - e->type = GG_EVENT_DCC_DONE; - return e; - } - - h->chunk_offset += size; - - if (h->chunk_offset >= h->chunk_size) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() chunk finished\n"); - h->state = GG_STATE_SENDING_FILE_HEADER; - h->timeout = GG_DEFAULT_TIMEOUT; - } else { - h->state = GG_STATE_SENDING_FILE; - h->timeout = GG_DCC_TIMEOUT_SEND; - } - - h->check = GG_CHECK_WRITE; - - return e; - - case GG_STATE_GETTING_FILE: - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_GETTING_FILE\n"); - - if ((utmp = h->chunk_size - h->chunk_offset) > sizeof(buf)) - utmp = sizeof(buf); - - size = read(h->fd, buf, utmp); - - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() ofs=%d, size=%d, read()=%d\n", h->offset, h->file_info.size, size); - - /* b³±d */ - if (size == -1) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() read() failed. (errno=%d, %s)\n", errno, strerror(errno)); - - e->type = GG_EVENT_DCC_ERROR; - e->event.dcc_error = GG_ERROR_DCC_NET; - - return e; - } - - /* koniec? */ - if (size == 0) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() read() reached eof\n"); - e->type = GG_EVENT_DCC_ERROR; - e->event.dcc_error = GG_ERROR_DCC_EOF; - - return e; - } - - tmp = write(h->file_fd, buf, size); - - if (tmp == -1 || tmp < size) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() write() failed (%d:fd=%d:res=%d:%s)\n", tmp, h->file_fd, size, strerror(errno)); - e->type = GG_EVENT_DCC_ERROR; - e->event.dcc_error = GG_ERROR_DCC_NET; - return e; - } - - h->offset += size; - - if (h->offset >= h->file_info.size) { - e->type = GG_EVENT_DCC_DONE; - return e; - } - - h->chunk_offset += size; - - if (h->chunk_offset >= h->chunk_size) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() chunk finished\n"); - h->state = GG_STATE_READING_FILE_HEADER; - h->timeout = GG_DEFAULT_TIMEOUT; - h->chunk_offset = 0; - h->chunk_size = sizeof(big); - if (!(h->chunk_buf = malloc(sizeof(big)))) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() out of memory\n"); - free(e); - return NULL; - } - } else { - h->state = GG_STATE_GETTING_FILE; - h->timeout = GG_DCC_TIMEOUT_GET; - } - - h->check = GG_CHECK_READ; - - return e; - - default: - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_???\n"); - e->type = GG_EVENT_DCC_ERROR; - e->event.dcc_error = GG_ERROR_DCC_HANDSHAKE; - - return e; - } - } - - return e; -} - -#undef gg_read -#undef gg_write - -/* - * gg_dcc_free() - * - * zwalnia pamiêæ po strukturze po³±czenia dcc. - * - * - d - zwalniana struktura - */ -void gg_dcc_free(struct gg_dcc *d) -{ - gg_debug(GG_DEBUG_FUNCTION, "** gg_dcc_free(%p);\n", d); - - if (!d) - return; - - if (d->fd != -1) - close(d->fd); - - if (d->chunk_buf) { - free(d->chunk_buf); - d->chunk_buf = NULL; - } - - free(d); -} - -/* - * Local variables: - * c-indentation-style: k&r - * c-basic-offset: 8 - * indent-tabs-mode: notnil - * End: - * - * vim: shiftwidth=8: - */ diff --git a/kopete/protocols/gadu/libgadu/events.c b/kopete/protocols/gadu/libgadu/events.c deleted file mode 100644 index 1bf67690..00000000 --- a/kopete/protocols/gadu/libgadu/events.c +++ /dev/null @@ -1,1580 +0,0 @@ -/* $Id$ */ - -/* - * (C) Copyright 2001-2006 Wojtek Kaniewski <wojtekka@irc.pl> - * Robert J. Wo�ny <speedy@ziew.org> - * Arkadiusz Mi�kiewicz <arekm@pld-linux.org> - * Adam Wysocki <gophi@ekg.chmurka.net> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License Version - * 2.1 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA. - */ - -#include <sys/types.h> -#include <sys/wait.h> -#include <sys/ioctl.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> - -#include "libgadu-config.h" - -#include <errno.h> -#ifdef __GG_LIBGADU_HAVE_PTHREAD -# include <pthread.h> -#endif -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <time.h> -#include <unistd.h> -#ifdef __GG_LIBGADU_HAVE_OPENSSL -# include <openssl/err.h> -# include <openssl/x509.h> -#endif - -#include "compat.h" -#include "libgadu.h" - -/* - * gg_event_free() - * - * zwalnia pami�� zajmowan� przez informacj� o zdarzeniu. - * - * - e - wska�nik do informacji o zdarzeniu - */ -void gg_event_free(struct gg_event *e) -{ - gg_debug(GG_DEBUG_FUNCTION, "** gg_event_free(%p);\n", e); - - if (!e) - return; - - switch (e->type) { - case GG_EVENT_MSG: - free(e->event.msg.message); - free(e->event.msg.formats); - free(e->event.msg.recipients); - break; - - case GG_EVENT_NOTIFY: - free(e->event.notify); - break; - - case GG_EVENT_NOTIFY60: - { - int i; - - for (i = 0; e->event.notify60[i].uin; i++) - free(e->event.notify60[i].descr); - - free(e->event.notify60); - - break; - } - - case GG_EVENT_STATUS60: - free(e->event.status60.descr); - break; - - case GG_EVENT_STATUS: - free(e->event.status.descr); - break; - - case GG_EVENT_NOTIFY_DESCR: - free(e->event.notify_descr.notify); - free(e->event.notify_descr.descr); - break; - - case GG_EVENT_DCC_VOICE_DATA: - free(e->event.dcc_voice_data.data); - break; - - case GG_EVENT_PUBDIR50_SEARCH_REPLY: - case GG_EVENT_PUBDIR50_READ: - case GG_EVENT_PUBDIR50_WRITE: - gg_pubdir50_free(e->event.pubdir50); - break; - - case GG_EVENT_USERLIST: - free(e->event.userlist.reply); - break; - - case GG_EVENT_IMAGE_REPLY: - free(e->event.image_reply.filename); - free(e->event.image_reply.image); - break; - } - - free(e); -} - -/* - * gg_image_queue_remove() - * - * usuwa z kolejki dany wpis. - * - * - s - sesja - * - q - kolejka - * - freeq - czy zwolni� kolejk� - * - * 0/-1 - */ -int gg_image_queue_remove(struct gg_session *s, struct gg_image_queue *q, int freeq) -{ - if (!s || !q) { - errno = EFAULT; - return -1; - } - - if (s->images == q) - s->images = q->next; - else { - struct gg_image_queue *qq; - - for (qq = s->images; qq; qq = qq->next) { - if (qq->next == q) { - qq->next = q->next; - break; - } - } - } - - if (freeq) { - free(q->image); - free(q->filename); - free(q); - } - - return 0; -} - -/* - * gg_image_queue_parse() // funkcja wewn�trzna - * - * parsuje przychodz�cy pakiet z obrazkiem. - * - * - e - opis zdarzenia - * - - */ -static void gg_image_queue_parse(struct gg_event *e, char *p, unsigned int len, struct gg_session *sess, uin_t sender) -{ - struct gg_msg_image_reply *i = (void*) p; - struct gg_image_queue *q, *qq; - - if (!p || !sess || !e) { - errno = EFAULT; - return; - } - - /* znajd� dany obrazek w kolejce danej sesji */ - - for (qq = sess->images, q = NULL; qq; qq = qq->next) { - if (sender == qq->sender && i->size == qq->size && i->crc32 == qq->crc32) { - q = qq; - break; - } - } - - if (!q) { - gg_debug(GG_DEBUG_MISC, "// gg_image_queue_parse() unknown image from %d, size=%d, crc32=%.8x\n", sender, i->size, i->crc32); - return; - } - - if (p[0] == 0x05) { - int i, ok = 0; - - q->done = 0; - - len -= sizeof(struct gg_msg_image_reply); - p += sizeof(struct gg_msg_image_reply); - - /* sprawd�, czy mamy tekst zako�czony \0 */ - - for (i = 0; i < len; i++) { - if (!p[i]) { - ok = 1; - break; - } - } - - if (!ok) { - gg_debug(GG_DEBUG_MISC, "// gg_image_queue_parse() malformed packet from %d, unlimited filename\n", sender); - return; - } - - if (!(q->filename = strdup(p))) { - gg_debug(GG_DEBUG_MISC, "// gg_image_queue_parse() not enough memory for filename\n"); - return; - } - - len -= strlen(p) + 1; - p += strlen(p) + 1; - } else { - len -= sizeof(struct gg_msg_image_reply); - p += sizeof(struct gg_msg_image_reply); - } - - if (q->done + len > q->size) - len = q->size - q->done; - - memcpy(q->image + q->done, p, len); - q->done += len; - - /* je�li sko�czono odbiera� obrazek, wygeneruj zdarzenie */ - - if (q->done >= q->size) { - e->type = GG_EVENT_IMAGE_REPLY; - e->event.image_reply.sender = sender; - e->event.image_reply.size = q->size; - e->event.image_reply.crc32 = q->crc32; - e->event.image_reply.filename = q->filename; - e->event.image_reply.image = q->image; - - gg_image_queue_remove(sess, q, 0); - - free(q); - } -} - -/* - * gg_handle_recv_msg() // funkcja wewn�trzna - * - * obs�uguje pakiet z przychodz�c� wiadomo�ci�, rozbijaj�c go na dodatkowe - * struktury (konferencje, kolorki) w razie potrzeby. - * - * - h - nag��wek pakietu - * - e - opis zdarzenia - * - * 0, -1. - */ -static int gg_handle_recv_msg(struct gg_header *h, struct gg_event *e, struct gg_session *sess) -{ - struct gg_recv_msg *r = (struct gg_recv_msg*) ((char*) h + sizeof(struct gg_header)); - char *p, *packet_end = (char*) r + h->length; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_handle_recv_msg(%p, %p);\n", h, e); - - if (!r->seq && !r->msgclass) { - gg_debug(GG_DEBUG_MISC, "// gg_handle_recv_msg() oops, silently ignoring the bait\n"); - e->type = GG_EVENT_NONE; - return 0; - } - - for (p = (char*) r + sizeof(*r); *p; p++) { - if (*p == 0x02 && p == packet_end - 1) { - gg_debug(GG_DEBUG_MISC, "// gg_handle_recv_msg() received ctcp packet\n"); - break; - } - if (p >= packet_end) { - gg_debug(GG_DEBUG_MISC, "// gg_handle_recv_msg() malformed packet, message out of bounds (0)\n"); - goto malformed; - } - } - - p++; - - /* przeanalizuj dodatkowe opcje */ - while (p < packet_end) { - switch (*p) { - case 0x01: /* konferencja */ - { - struct gg_msg_recipients *m = (void*) p; - uint32_t i, count; - - p += sizeof(*m); - - if (p > packet_end) { - gg_debug(GG_DEBUG_MISC, "// gg_handle_recv_msg() packet out of bounds (1)\n"); - goto malformed; - } - - count = gg_fix32(m->count); - - if (p + count * sizeof(uin_t) > packet_end || p + count * sizeof(uin_t) < p || count > 0xffff) { - gg_debug(GG_DEBUG_MISC, "// gg_handle_recv_msg() packet out of bounds (1.5)\n"); - goto malformed; - } - - if (!(e->event.msg.recipients = (void*) malloc(count * sizeof(uin_t)))) { - gg_debug(GG_DEBUG_MISC, "// gg_handle_recv_msg() not enough memory for recipients data\n"); - goto fail; - } - - for (i = 0; i < count; i++, p += sizeof(uint32_t)) { - uint32_t u; - memcpy(&u, p, sizeof(uint32_t)); - e->event.msg.recipients[i] = gg_fix32(u); - } - - e->event.msg.recipients_count = count; - - break; - } - - case 0x02: /* richtext */ - { - uint16_t len; - char *buf; - - if (p + 3 > packet_end) { - gg_debug(GG_DEBUG_MISC, "// gg_handle_recv_msg() packet out of bounds (2)\n"); - goto malformed; - } - - memcpy(&len, p + 1, sizeof(uint16_t)); - len = gg_fix16(len); - - if (!(buf = malloc(len))) { - gg_debug(GG_DEBUG_MISC, "// gg_handle_recv_msg() not enough memory for richtext data\n"); - goto fail; - } - - p += 3; - - if (p + len > packet_end) { - gg_debug(GG_DEBUG_MISC, "// gg_handle_recv_msg() packet out of bounds (3)\n"); - free(buf); - goto malformed; - } - - memcpy(buf, p, len); - - e->event.msg.formats = buf; - e->event.msg.formats_length = len; - - p += len; - - break; - } - - case 0x04: /* image_request */ - { - struct gg_msg_image_request *i = (void*) p; - - if (p + sizeof(*i) > packet_end) { - gg_debug(GG_DEBUG_MISC, "// gg_handle_recv_msg() packet out of bounds (3)\n"); - goto malformed; - } - - e->event.image_request.sender = gg_fix32(r->sender); - e->event.image_request.size = gg_fix32(i->size); - e->event.image_request.crc32 = gg_fix32(i->crc32); - - e->type = GG_EVENT_IMAGE_REQUEST; - - return 0; - } - - case 0x05: /* image_reply */ - case 0x06: - { - struct gg_msg_image_reply *rep = (void*) p; - - if (p + sizeof(struct gg_msg_image_reply) == packet_end) { - - /* pusta odpowied� - klient po drugiej stronie nie ma ��danego obrazka */ - - e->type = GG_EVENT_IMAGE_REPLY; - e->event.image_reply.sender = gg_fix32(r->sender); - e->event.image_reply.size = 0; - e->event.image_reply.crc32 = gg_fix32(rep->crc32); - e->event.image_reply.filename = NULL; - e->event.image_reply.image = NULL; - return 0; - - } else if (p + sizeof(struct gg_msg_image_reply) + 1 > packet_end) { - - gg_debug(GG_DEBUG_MISC, "// gg_handle_recv_msg() packet out of bounds (4)\n"); - goto malformed; - } - - rep->size = gg_fix32(rep->size); - rep->crc32 = gg_fix32(rep->crc32); - gg_image_queue_parse(e, p, (unsigned int)(packet_end - p), sess, gg_fix32(r->sender)); - - return 0; - } - - default: - { - gg_debug(GG_DEBUG_MISC, "// gg_handle_recv_msg() unknown payload 0x%.2x\n", *p); - p = packet_end; - } - } - } - - e->type = GG_EVENT_MSG; - e->event.msg.msgclass = gg_fix32(r->msgclass); - e->event.msg.sender = gg_fix32(r->sender); - e->event.msg.time = gg_fix32(r->time); - e->event.msg.message = strdup((char*) r + sizeof(*r)); - - return 0; - -malformed: - e->type = GG_EVENT_NONE; - - free(e->event.msg.recipients); - free(e->event.msg.formats); - - return 0; - -fail: - free(e->event.msg.recipients); - free(e->event.msg.formats); - return -1; -} - -/* - * gg_watch_fd_connected() // funkcja wewn�trzna - * - * patrzy na gniazdo, odbiera pakiet i wype�nia struktur� zdarzenia. - * - * - sess - struktura opisuj�ca sesj� - * - e - opis zdarzenia - * - * 0, -1. - */ -static int gg_watch_fd_connected(struct gg_session *sess, struct gg_event *e) -{ - struct gg_header *h = NULL; - char *p; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_watch_fd_connected(%p, %p);\n", sess, e); - - if (!sess) { - errno = EFAULT; - return -1; - } - - if (!(h = gg_recv_packet(sess))) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd_connected() gg_recv_packet failed (errno=%d, %s)\n", errno, strerror(errno)); - goto fail; - } - - p = (char*) h + sizeof(struct gg_header); - - switch (h->type) { - case GG_RECV_MSG: - { - if (h->length >= sizeof(struct gg_recv_msg)) - if (gg_handle_recv_msg(h, e, sess)) - goto fail; - - break; - } - - case GG_NOTIFY_REPLY: - { - struct gg_notify_reply *n = (void*) p; - unsigned int count, i; - char *tmp; - - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd_connected() received a notify reply\n"); - - if (h->length < sizeof(*n)) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd_connected() incomplete packet\n"); - errno = EINVAL; - goto fail; - } - - if (gg_fix32(n->status) == GG_STATUS_BUSY_DESCR || gg_fix32(n->status) == GG_STATUS_NOT_AVAIL_DESCR || gg_fix32(n->status) == GG_STATUS_AVAIL_DESCR) { - e->type = GG_EVENT_NOTIFY_DESCR; - - if (!(e->event.notify_descr.notify = (void*) malloc(sizeof(*n) * 2))) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd_connected() not enough memory for notify data\n"); - goto fail; - } - e->event.notify_descr.notify[1].uin = 0; - memcpy(e->event.notify_descr.notify, p, sizeof(*n)); - e->event.notify_descr.notify[0].uin = gg_fix32(e->event.notify_descr.notify[0].uin); - e->event.notify_descr.notify[0].status = gg_fix32(e->event.notify_descr.notify[0].status); - e->event.notify_descr.notify[0].remote_port = gg_fix16(e->event.notify_descr.notify[0].remote_port); - - count = h->length - sizeof(*n); - if (!(tmp = malloc(count + 1))) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd_connected() not enough memory for notify data\n"); - goto fail; - } - memcpy(tmp, p + sizeof(*n), count); - tmp[count] = 0; - e->event.notify_descr.descr = tmp; - - } else { - e->type = GG_EVENT_NOTIFY; - - if (!(e->event.notify = (void*) malloc(h->length + 2 * sizeof(*n)))) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd_connected() not enough memory for notify data\n"); - goto fail; - } - - memcpy(e->event.notify, p, h->length); - count = h->length / sizeof(*n); - e->event.notify[count].uin = 0; - - for (i = 0; i < count; i++) { - e->event.notify[i].uin = gg_fix32(e->event.notify[i].uin); - e->event.notify[i].status = gg_fix32(e->event.notify[i].status); - e->event.notify[i].remote_port = gg_fix16(e->event.notify[i].remote_port); - } - } - - break; - } - - case GG_STATUS: - { - struct gg_status *s = (void*) p; - - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd_connected() received a status change\n"); - - if (h->length >= sizeof(*s)) { - e->type = GG_EVENT_STATUS; - memcpy(&e->event.status, p, sizeof(*s)); - e->event.status.uin = gg_fix32(e->event.status.uin); - e->event.status.status = gg_fix32(e->event.status.status); - if (h->length > sizeof(*s)) { - int len = h->length - sizeof(*s); - char *buf = malloc(len + 1); - if (buf) { - memcpy(buf, p + sizeof(*s), len); - buf[len] = 0; - } - e->event.status.descr = buf; - } else - e->event.status.descr = NULL; - } - - break; - } - - case GG_NOTIFY_REPLY60: - { - struct gg_notify_reply60 *n = (void*) p; - unsigned int length = h->length, i = 0; - - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd_connected() received a notify reply\n"); - - e->type = GG_EVENT_NOTIFY60; - e->event.notify60 = malloc(sizeof(*e->event.notify60)); - - if (!e->event.notify60) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd_connected() not enough memory for notify data\n"); - goto fail; - } - - e->event.notify60[0].uin = 0; - - while (length >= sizeof(struct gg_notify_reply60)) { - uin_t uin = gg_fix32(n->uin); - char *tmp; - - e->event.notify60[i].uin = uin & 0x00ffffff; - e->event.notify60[i].status = n->status; - e->event.notify60[i].remote_ip = n->remote_ip; - e->event.notify60[i].remote_port = gg_fix16(n->remote_port); - e->event.notify60[i].version = n->version; - e->event.notify60[i].image_size = n->image_size; - e->event.notify60[i].descr = NULL; - e->event.notify60[i].time = 0; - - if (uin & 0x40000000) - e->event.notify60[i].version |= GG_HAS_AUDIO_MASK; - if (uin & 0x08000000) - e->event.notify60[i].version |= GG_ERA_OMNIX_MASK; - - if (GG_S_D(n->status)) { - unsigned char descr_len = *((char*) n + sizeof(struct gg_notify_reply60)); - - if (descr_len < length) { - if (!(e->event.notify60[i].descr = malloc(descr_len + 1))) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd_connected() not enough memory for notify data\n"); - goto fail; - } - - memcpy(e->event.notify60[i].descr, (char*) n + sizeof(struct gg_notify_reply60) + 1, descr_len); - e->event.notify60[i].descr[descr_len] = 0; - - /* XXX czas */ - } - - length -= sizeof(struct gg_notify_reply60) + descr_len + 1; - n = (void*) ((char*) n + sizeof(struct gg_notify_reply60) + descr_len + 1); - } else { - length -= sizeof(struct gg_notify_reply60); - n = (void*) ((char*) n + sizeof(struct gg_notify_reply60)); - } - - if (!(tmp = realloc(e->event.notify60, (i + 2) * sizeof(*e->event.notify60)))) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd_connected() not enough memory for notify data\n"); - free(e->event.notify60); - goto fail; - } - - e->event.notify60 = (void*) tmp; - e->event.notify60[++i].uin = 0; - } - - break; - } - - case GG_STATUS60: - { - struct gg_status60 *s = (void*) p; - uint32_t uin; - - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd_connected() received a status change\n"); - - if (h->length < sizeof(*s)) - break; - - uin = gg_fix32(s->uin); - - e->type = GG_EVENT_STATUS60; - e->event.status60.uin = uin & 0x00ffffff; - e->event.status60.status = s->status; - e->event.status60.remote_ip = s->remote_ip; - e->event.status60.remote_port = gg_fix16(s->remote_port); - e->event.status60.version = s->version; - e->event.status60.image_size = s->image_size; - e->event.status60.descr = NULL; - e->event.status60.time = 0; - - if (uin & 0x40000000) - e->event.status60.version |= GG_HAS_AUDIO_MASK; - if (uin & 0x08000000) - e->event.status60.version |= GG_ERA_OMNIX_MASK; - - if (h->length > sizeof(*s)) { - int len = h->length - sizeof(*s); - char *buf = malloc(len + 1); - - if (buf) { - memcpy(buf, (char*) p + sizeof(*s), len); - buf[len] = 0; - } - - e->event.status60.descr = buf; - - if (len > 4 && p[h->length - 5] == 0) { - uint32_t t; - memcpy(&t, p + h->length - 4, sizeof(uint32_t)); - e->event.status60.time = gg_fix32(t); - } - } - - break; - } - - case GG_SEND_MSG_ACK: - { - struct gg_send_msg_ack *s = (void*) p; - - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd_connected() received a message ack\n"); - - if (h->length < sizeof(*s)) - break; - - e->type = GG_EVENT_ACK; - e->event.ack.status = gg_fix32(s->status); - e->event.ack.recipient = gg_fix32(s->recipient); - e->event.ack.seq = gg_fix32(s->seq); - - break; - } - - case GG_PONG: - { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd_connected() received a pong\n"); - - e->type = GG_EVENT_PONG; - sess->last_pong = time(NULL); - - break; - } - - case GG_DISCONNECTING: - { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd_connected() received disconnection warning\n"); - e->type = GG_EVENT_DISCONNECT; - break; - } - - case GG_PUBDIR50_REPLY: - { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd_connected() received pubdir/search reply\n"); - if (gg_pubdir50_handle_reply(e, p, h->length) == -1) - goto fail; - break; - } - - case GG_USERLIST_REPLY: - { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd_connected() received userlist reply\n"); - - if (h->length < 1) - break; - - /* je�li odpowied� na eksport, wywo�aj zdarzenie tylko - * gdy otrzymano wszystkie odpowiedzi */ - if (p[0] == GG_USERLIST_PUT_REPLY || p[0] == GG_USERLIST_PUT_MORE_REPLY) { - if (--sess->userlist_blocks) - break; - - p[0] = GG_USERLIST_PUT_REPLY; - } - - if (h->length > 1) { - char *tmp; - unsigned int len = (sess->userlist_reply) ? strlen(sess->userlist_reply) : 0; - - gg_debug(GG_DEBUG_MISC, "userlist_reply=%p, len=%d\n", sess->userlist_reply, len); - - if (!(tmp = realloc(sess->userlist_reply, len + h->length))) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd_connected() not enough memory for userlist reply\n"); - free(sess->userlist_reply); - sess->userlist_reply = NULL; - goto fail; - } - - sess->userlist_reply = tmp; - sess->userlist_reply[len + h->length - 1] = 0; - memcpy(sess->userlist_reply + len, p + 1, h->length - 1); - } - - if (p[0] == GG_USERLIST_GET_MORE_REPLY) - break; - - e->type = GG_EVENT_USERLIST; - e->event.userlist.type = p[0]; - e->event.userlist.reply = sess->userlist_reply; - sess->userlist_reply = NULL; - - break; - } - - default: - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd_connected() received unknown packet 0x%.2x\n", h->type); - } - - free(h); - return 0; - -fail: - free(h); - return -1; -} - -/* - * gg_watch_fd() - * - * funkcja, kt�r� nale�y wywo�a�, gdy co� si� stanie z obserwowanym - * deskryptorem. zwraca klientowi informacj� o tym, co si� dzieje. - * - * - sess - opis sesji - * - * wska�nik do struktury gg_event, kt�r� trzeba zwolni� p��niej - * za pomoc� gg_event_free(). jesli rodzaj zdarzenia jest r�wny - * GG_EVENT_NONE, nale�y je zignorowa�. je�li zwr�ci�o NULL, - * sta�o si� co� niedobrego -- albo zabrak�o pami�ci albo zerwa�o - * po��czenie. - */ -struct gg_event *gg_watch_fd(struct gg_session *sess) -{ - struct gg_event *e; - int res = 0; - int port = 0; - int errno2 = 0; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_watch_fd(%p);\n", sess); - - if (!sess) { - errno = EFAULT; - return NULL; - } - - if (!(e = (void*) calloc(1, sizeof(*e)))) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() not enough memory for event data\n"); - return NULL; - } - - e->type = GG_EVENT_NONE; - - switch (sess->state) { - case GG_STATE_RESOLVING: - { - struct in_addr addr; - int failed = 0; - - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() GG_STATE_RESOLVING\n"); - - if (read(sess->fd, &addr, sizeof(addr)) < (signed)sizeof(addr) || addr.s_addr == INADDR_NONE) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() resolving failed\n"); - failed = 1; - errno2 = errno; - } - - close(sess->fd); - sess->fd = -1; - -#ifndef __GG_LIBGADU_HAVE_PTHREAD - waitpid(sess->pid, NULL, 0); - sess->pid = -1; -#else - if (sess->resolver) { - pthread_cancel(*((pthread_t*) sess->resolver)); - free(sess->resolver); - sess->resolver = NULL; - } -#endif - - if (failed) { - errno = errno2; - goto fail_resolving; - } - - /* je�li jeste�my w resolverze i mamy ustawiony port - * proxy, znaczy, �e resolvowali�my proxy. zatem - * wpiszmy jego adres. */ - if (sess->proxy_port) - sess->proxy_addr = addr.s_addr; - - /* zapiszmy sobie adres huba i adres serwera (do - * bezpo�redniego po��czenia, je�li hub le�y) - * z resolvera. */ - if (sess->proxy_addr && sess->proxy_port) - port = sess->proxy_port; - else { - sess->server_addr = sess->hub_addr = addr.s_addr; - port = GG_APPMSG_PORT; - } - - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() resolved, connecting to %s:%d\n", inet_ntoa(addr), port); - - /* ��czymy si� albo z hubem, albo z proxy, zale�nie - * od tego, co resolvowali�my. */ - if ((sess->fd = gg_connect(&addr, port, sess->async)) == -1) { - /* je�li w trybie asynchronicznym gg_connect() - * zwr�ci b��d, nie ma sensu pr�bowa� dalej. */ - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() connection failed (errno=%d, %s), critical\n", errno, strerror(errno)); - goto fail_connecting; - } - - /* je�li podano serwer i ��czmy si� przez proxy, - * jest to bezpo�rednie po��czenie, inaczej jest - * do huba. */ - sess->state = (sess->proxy_addr && sess->proxy_port && sess->server_addr) ? GG_STATE_CONNECTING_GG : GG_STATE_CONNECTING_HUB; - sess->check = GG_CHECK_WRITE; - sess->timeout = GG_DEFAULT_TIMEOUT; - - break; - } - - case GG_STATE_CONNECTING_HUB: - { - char buf[1024], *client, *auth; - int res = 0, res_size = sizeof(res); - const char *host, *appmsg; - - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() GG_STATE_CONNECTING_HUB\n"); - - /* je�li asynchroniczne, sprawdzamy, czy nie wyst�pi� - * przypadkiem jaki� b��d. */ - if (sess->async && (getsockopt(sess->fd, SOL_SOCKET, SO_ERROR, &res, &res_size) || res)) { - /* no tak, nie uda�o si� po��czy� z proxy. nawet - * nie pr�bujemy dalej. */ - if (sess->proxy_addr && sess->proxy_port) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() connection to proxy failed (errno=%d, %s)\n", res, strerror(res)); - goto fail_connecting; - } - - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() connection to hub failed (errno=%d, %s), trying direct connection\n", res, strerror(res)); - close(sess->fd); - - if ((sess->fd = gg_connect(&sess->hub_addr, GG_DEFAULT_PORT, sess->async)) == -1) { - /* przy asynchronicznych, gg_connect() - * zwraca -1 przy b��dach socket(), - * ioctl(), braku routingu itd. dlatego - * nawet nie pr�bujemy dalej. */ - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() direct connection failed (errno=%d, %s), critical\n", errno, strerror(errno)); - goto fail_connecting; - } - - sess->state = GG_STATE_CONNECTING_GG; - sess->check = GG_CHECK_WRITE; - sess->timeout = GG_DEFAULT_TIMEOUT; - break; - } - - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() connected to hub, sending query\n"); - - if (!(client = gg_urlencode((sess->client_version) ? sess->client_version : GG_DEFAULT_CLIENT_VERSION))) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() out of memory for client version\n"); - goto fail_connecting; - } - - if (!gg_proxy_http_only && sess->proxy_addr && sess->proxy_port) - host = "http://" GG_APPMSG_HOST; - else - host = ""; - -#ifdef __GG_LIBGADU_HAVE_OPENSSL - if (sess->ssl) - appmsg = "appmsg3.asp"; - else -#endif - appmsg = "appmsg2.asp"; - - auth = gg_proxy_auth(); - - snprintf(buf, sizeof(buf) - 1, - "GET %s/appsvc/%s?fmnumber=%u&version=%s&lastmsg=%d HTTP/1.0\r\n" - "Host: " GG_APPMSG_HOST "\r\n" - "User-Agent: " GG_HTTP_USERAGENT "\r\n" - "Pragma: no-cache\r\n" - "%s" - "\r\n", host, appmsg, sess->uin, client, sess->last_sysmsg, (auth) ? auth : ""); - - if (auth) - free(auth); - - free(client); - - /* zwolnij pami�� po wersji klienta. */ - if (sess->client_version) { - free(sess->client_version); - sess->client_version = NULL; - } - - gg_debug(GG_DEBUG_MISC, "=> -----BEGIN-HTTP-QUERY-----\n%s\n=> -----END-HTTP-QUERY-----\n", buf); - - /* zapytanie jest kr�tkie, wi�c zawsze zmie�ci si� - * do bufora gniazda. je�li write() zwr�ci mniej, - * sta�o si� co� z�ego. */ - if (write(sess->fd, buf, strlen(buf)) < (signed)strlen(buf)) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() sending query failed\n"); - - e->type = GG_EVENT_CONN_FAILED; - e->event.failure = GG_FAILURE_WRITING; - sess->state = GG_STATE_IDLE; - close(sess->fd); - sess->fd = -1; - break; - } - - sess->state = GG_STATE_READING_DATA; - sess->check = GG_CHECK_READ; - sess->timeout = GG_DEFAULT_TIMEOUT; - - break; - } - - case GG_STATE_READING_DATA: - { - char buf[1024], *tmp, *host; - int port = GG_DEFAULT_PORT; - struct in_addr addr; - - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() GG_STATE_READING_DATA\n"); - - /* czytamy lini� z gniazda i obcinamy \r\n. */ - gg_read_line(sess->fd, buf, sizeof(buf) - 1); - gg_chomp(buf); - gg_debug(GG_DEBUG_TRAFFIC, "// gg_watch_fd() received http header (%s)\n", buf); - - /* sprawdzamy, czy wszystko w porz�dku. */ - if (strncmp(buf, "HTTP/1.", 7) || strncmp(buf + 9, "200", 3)) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() that's not what we've expected, trying direct connection\n"); - - close(sess->fd); - - /* je�li otrzymali�my jakie� dziwne informacje, - * pr�bujemy si� ��czy� z pomini�ciem huba. */ - if (sess->proxy_addr && sess->proxy_port) { - if ((sess->fd = gg_connect(&sess->proxy_addr, sess->proxy_port, sess->async)) == -1) { - /* trudno. nie wysz�o. */ - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() connection to proxy failed (errno=%d, %s)\n", errno, strerror(errno)); - goto fail_connecting; - } - - sess->state = GG_STATE_CONNECTING_GG; - sess->check = GG_CHECK_WRITE; - sess->timeout = GG_DEFAULT_TIMEOUT; - break; - } - - sess->port = GG_DEFAULT_PORT; - - /* ��czymy si� na port 8074 huba. */ - if ((sess->fd = gg_connect(&sess->hub_addr, sess->port, sess->async)) == -1) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() connection failed (errno=%d, %s), trying https\n", errno, strerror(errno)); - - sess->port = GG_HTTPS_PORT; - - /* ��czymy si� na port 443. */ - if ((sess->fd = gg_connect(&sess->hub_addr, sess->port, sess->async)) == -1) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() connection failed (errno=%d, %s)\n", errno, strerror(errno)); - goto fail_connecting; - } - } - - sess->state = GG_STATE_CONNECTING_GG; - sess->check = GG_CHECK_WRITE; - sess->timeout = GG_DEFAULT_TIMEOUT; - break; - } - - /* ignorujemy reszt� nag��wka. */ - while (strcmp(buf, "\r\n") && strcmp(buf, "")) - gg_read_line(sess->fd, buf, sizeof(buf) - 1); - - /* czytamy pierwsz� lini� danych. */ - gg_read_line(sess->fd, buf, sizeof(buf) - 1); - gg_chomp(buf); - - /* je�li pierwsza liczba w linii nie jest r�wna zeru, - * oznacza to, �e mamy wiadomo�� systemow�. */ - if (atoi(buf)) { - char tmp[1024], *foo, *sysmsg_buf = NULL; - int len = 0; - - while (gg_read_line(sess->fd, tmp, sizeof(tmp) - 1)) { - if (!(foo = realloc(sysmsg_buf, len + strlen(tmp) + 2))) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() out of memory for system message, ignoring\n"); - break; - } - - sysmsg_buf = foo; - - if (!len) - strcpy(sysmsg_buf, tmp); - else - strcat(sysmsg_buf, tmp); - - len += strlen(tmp); - } - - e->type = GG_EVENT_MSG; - e->event.msg.msgclass = atoi(buf); - e->event.msg.sender = 0; - e->event.msg.message = sysmsg_buf; - } - - close(sess->fd); - - gg_debug(GG_DEBUG_TRAFFIC, "// gg_watch_fd() received http data (%s)\n", buf); - - /* analizujemy otrzymane dane. */ - tmp = buf; - - while (*tmp && *tmp != ' ') - tmp++; - while (*tmp && *tmp == ' ') - tmp++; - host = tmp; - while (*tmp && *tmp != ' ') - tmp++; - *tmp = 0; - - if ((tmp = (char*)strchr(host, ':'))) { - *tmp = 0; - port = atoi(tmp + 1); - } - - if (!strcmp(host, "notoperating")) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() service unavailable\n", errno, strerror(errno)); - sess->fd = -1; - goto fail_unavailable; - } - - addr.s_addr = inet_addr(host); - sess->server_addr = addr.s_addr; - - if (!gg_proxy_http_only && sess->proxy_addr && sess->proxy_port) { - /* je�li mamy proxy, ��czymy si� z nim. */ - if ((sess->fd = gg_connect(&sess->proxy_addr, sess->proxy_port, sess->async)) == -1) { - /* nie wysz�o? trudno. */ - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() connection to proxy failed (errno=%d, %s)\n", errno, strerror(errno)); - goto fail_connecting; - } - - sess->state = GG_STATE_CONNECTING_GG; - sess->check = GG_CHECK_WRITE; - sess->timeout = GG_DEFAULT_TIMEOUT; - break; - } - - sess->port = port; - - /* ��czymy si� z w�a�ciwym serwerem. */ - if ((sess->fd = gg_connect(&addr, sess->port, sess->async)) == -1) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() connection failed (errno=%d, %s), trying https\n", errno, strerror(errno)); - - sess->port = GG_HTTPS_PORT; - - /* nie wysz�o? pr�bujemy portu 443. */ - if ((sess->fd = gg_connect(&addr, GG_HTTPS_PORT, sess->async)) == -1) { - /* ostatnia deska ratunku zawiod�a? - * w takim razie zwijamy manatki. */ - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() connection failed (errno=%d, %s)\n", errno, strerror(errno)); - goto fail_connecting; - } - } - - sess->state = GG_STATE_CONNECTING_GG; - sess->check = GG_CHECK_WRITE; - sess->timeout = GG_DEFAULT_TIMEOUT; - - break; - } - - case GG_STATE_CONNECTING_GG: - { - int res = 0, res_size = sizeof(res); - - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() GG_STATE_CONNECTING_GG\n"); - - /* je�li wyst�pi� b��d podczas ��czenia si�... */ - if (sess->async && (sess->timeout == 0 || getsockopt(sess->fd, SOL_SOCKET, SO_ERROR, &res, &res_size) || res)) { - /* je�li nie uda�o si� po��czenie z proxy, - * nie mamy czego pr�bowa� wi�cej. */ - if (sess->proxy_addr && sess->proxy_port) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() connection to proxy failed (errno=%d, %s)\n", res, strerror(res)); - goto fail_connecting; - } - - close(sess->fd); - sess->fd = -1; - -#ifdef ETIMEDOUT - if (sess->timeout == 0) - errno = ETIMEDOUT; -#endif - -#ifdef __GG_LIBGADU_HAVE_OPENSSL - /* je�li logujemy si� po TLS, nie pr�bujemy - * si� ��czy� ju� z niczym innym w przypadku - * b��du. nie do��, �e nie ma sensu, to i - * trzeba by si� bawi� w tworzenie na nowo - * SSL i SSL_CTX. */ - - if (sess->ssl) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() connection failed (errno=%d, %s)\n", res, strerror(res)); - goto fail_connecting; - } -#endif - - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() connection failed (errno=%d, %s), trying https\n", res, strerror(res)); - - sess->port = GG_HTTPS_PORT; - - /* pr�bujemy na port 443. */ - if ((sess->fd = gg_connect(&sess->server_addr, sess->port, sess->async)) == -1) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() connection failed (errno=%d, %s)\n", errno, strerror(errno)); - goto fail_connecting; - } - } - - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() connected\n"); - - if (gg_proxy_http_only) - sess->proxy_port = 0; - - /* je�li mamy proxy, wy�lijmy zapytanie. */ - if (sess->proxy_addr && sess->proxy_port) { - char buf[100], *auth = gg_proxy_auth(); - struct in_addr addr; - - if (sess->server_addr) - addr.s_addr = sess->server_addr; - else - addr.s_addr = sess->hub_addr; - - snprintf(buf, sizeof(buf), "CONNECT %s:%d HTTP/1.0\r\n", inet_ntoa(addr), sess->port); - - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() proxy request:\n// %s", buf); - - /* wysy�amy zapytanie. jest ono na tyle kr�tkie, - * �e musi si� zmie�ci� w buforze gniazda. je�li - * write() zawiedzie, sta�o si� co� z�ego. */ - if (write(sess->fd, buf, strlen(buf)) < (signed)strlen(buf)) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() can't send proxy request\n"); - if (auth) - free(auth); - goto fail_connecting; - } - - if (auth) { - gg_debug(GG_DEBUG_MISC, "// %s", auth); - if (write(sess->fd, auth, strlen(auth)) < (signed)strlen(auth)) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() can't send proxy request\n"); - free(auth); - goto fail_connecting; - } - - free(auth); - } - - if (write(sess->fd, "\r\n", 2) < 2) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() can't send proxy request\n"); - goto fail_connecting; - } - } - -#ifdef __GG_LIBGADU_HAVE_OPENSSL - if (sess->ssl) { - SSL_set_fd(sess->ssl, sess->fd); - - sess->state = GG_STATE_TLS_NEGOTIATION; - sess->check = GG_CHECK_WRITE; - sess->timeout = GG_DEFAULT_TIMEOUT; - - break; - } -#endif - - sess->state = GG_STATE_READING_KEY; - sess->check = GG_CHECK_READ; - sess->timeout = GG_DEFAULT_TIMEOUT; - - break; - } - -#ifdef __GG_LIBGADU_HAVE_OPENSSL - case GG_STATE_TLS_NEGOTIATION: - { - int res; - X509 *peer; - - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() GG_STATE_TLS_NEGOTIATION\n"); - - if ((res = SSL_connect(sess->ssl)) <= 0) { - int err = SSL_get_error(sess->ssl, res); - - if (res == 0) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() disconnected during TLS negotiation\n"); - - e->type = GG_EVENT_CONN_FAILED; - e->event.failure = GG_FAILURE_TLS; - sess->state = GG_STATE_IDLE; - close(sess->fd); - sess->fd = -1; - break; - } - - if (err == SSL_ERROR_WANT_READ) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() SSL_connect() wants to read\n"); - - sess->state = GG_STATE_TLS_NEGOTIATION; - sess->check = GG_CHECK_READ; - sess->timeout = GG_DEFAULT_TIMEOUT; - - break; - } else if (err == SSL_ERROR_WANT_WRITE) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() SSL_connect() wants to write\n"); - - sess->state = GG_STATE_TLS_NEGOTIATION; - sess->check = GG_CHECK_WRITE; - sess->timeout = GG_DEFAULT_TIMEOUT; - - break; - } else { - char buf[1024]; - - ERR_error_string_n(ERR_get_error(), buf, sizeof(buf)); - - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() SSL_connect() bailed out: %s\n", buf); - - e->type = GG_EVENT_CONN_FAILED; - e->event.failure = GG_FAILURE_TLS; - sess->state = GG_STATE_IDLE; - close(sess->fd); - sess->fd = -1; - break; - } - } - - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() TLS negotiation succeded:\n// cipher: %s\n", SSL_get_cipher_name(sess->ssl)); - - peer = SSL_get_peer_certificate(sess->ssl); - - if (!peer) - gg_debug(GG_DEBUG_MISC, "// WARNING! unable to get peer certificate!\n"); - else { - char buf[1024]; - - X509_NAME_oneline(X509_get_subject_name(peer), buf, sizeof(buf)); - gg_debug(GG_DEBUG_MISC, "// cert subject: %s\n", buf); - - X509_NAME_oneline(X509_get_issuer_name(peer), buf, sizeof(buf)); - gg_debug(GG_DEBUG_MISC, "// cert issuer: %s\n", buf); - } - - sess->state = GG_STATE_READING_KEY; - sess->check = GG_CHECK_READ; - sess->timeout = GG_DEFAULT_TIMEOUT; - - break; - } -#endif - - case GG_STATE_READING_KEY: - { - struct gg_header *h; - struct gg_welcome *w; - struct gg_login60 l; - unsigned int hash; - unsigned char *password = sess->password; - int ret; - - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() GG_STATE_READING_KEY\n"); - - memset(&l, 0, sizeof(l)); - l.dunno2 = 0xbe; - - /* XXX bardzo, bardzo, bardzo g�upi pomys� na pozbycie - * si� tekstu wrzucanego przez proxy. */ - if (sess->proxy_addr && sess->proxy_port) { - char buf[100]; - - strcpy(buf, ""); - gg_read_line(sess->fd, buf, sizeof(buf) - 1); - gg_chomp(buf); - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() proxy response:\n// %s\n", buf); - - while (strcmp(buf, "")) { - gg_read_line(sess->fd, buf, sizeof(buf) - 1); - gg_chomp(buf); - if (strcmp(buf, "")) - gg_debug(GG_DEBUG_MISC, "// %s\n", buf); - } - - /* XXX niech czeka jeszcze raz w tej samej - * fazie. g�upio, ale dzia�a. */ - sess->proxy_port = 0; - - break; - } - - /* czytaj pierwszy pakiet. */ - if (!(h = gg_recv_packet(sess))) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() didn't receive packet (errno=%d, %s)\n", errno, strerror(errno)); - - e->type = GG_EVENT_CONN_FAILED; - e->event.failure = GG_FAILURE_READING; - sess->state = GG_STATE_IDLE; - errno2 = errno; - close(sess->fd); - errno = errno2; - sess->fd = -1; - break; - } - - if (h->type != GG_WELCOME) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() invalid packet received\n"); - free(h); - close(sess->fd); - sess->fd = -1; - errno = EINVAL; - e->type = GG_EVENT_CONN_FAILED; - e->event.failure = GG_FAILURE_INVALID; - sess->state = GG_STATE_IDLE; - break; - } - - w = (struct gg_welcome*) ((char*) h + sizeof(struct gg_header)); - w->key = gg_fix32(w->key); - - hash = gg_login_hash(password, w->key); - - gg_debug(GG_DEBUG_DUMP, "// gg_watch_fd() challenge %.4x --> hash %.8x\n", w->key, hash); - - free(h); - - free(sess->password); - sess->password = NULL; - - { - struct in_addr dcc_ip; - dcc_ip.s_addr = gg_dcc_ip; - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() gg_dcc_ip = %s\n", inet_ntoa(dcc_ip)); - } - - if (gg_dcc_ip == (unsigned long) inet_addr("255.255.255.255")) { - struct sockaddr_in sin; - int sin_len = sizeof(sin); - - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() detecting address\n"); - - if (!getsockname(sess->fd, (struct sockaddr*) &sin, &sin_len)) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() detected address to %s\n", inet_ntoa(sin.sin_addr)); - l.local_ip = sin.sin_addr.s_addr; - } else { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() unable to detect address\n"); - l.local_ip = 0; - } - } else - l.local_ip = gg_dcc_ip; - - l.uin = gg_fix32(sess->uin); - l.hash = gg_fix32(hash); - l.status = gg_fix32(sess->initial_status ? sess->initial_status : GG_STATUS_AVAIL); - l.version = gg_fix32(sess->protocol_version); - l.local_port = gg_fix16(gg_dcc_port); - l.image_size = sess->image_size; - - if (sess->external_addr && sess->external_port > 1023) { - l.external_ip = sess->external_addr; - l.external_port = gg_fix16(sess->external_port); - } - - gg_debug(GG_DEBUG_TRAFFIC, "// gg_watch_fd() sending GG_LOGIN60 packet\n"); - ret = gg_send_packet(sess, GG_LOGIN60, &l, sizeof(l), sess->initial_descr, (sess->initial_descr) ? strlen(sess->initial_descr) : 0, NULL); - - free(sess->initial_descr); - sess->initial_descr = NULL; - - if (ret == -1) { - gg_debug(GG_DEBUG_TRAFFIC, "// gg_watch_fd() sending packet failed. (errno=%d, %s)\n", errno, strerror(errno)); - errno2 = errno; - close(sess->fd); - errno = errno2; - sess->fd = -1; - e->type = GG_EVENT_CONN_FAILED; - e->event.failure = GG_FAILURE_WRITING; - sess->state = GG_STATE_IDLE; - break; - } - - sess->state = GG_STATE_READING_REPLY; - - break; - } - - case GG_STATE_READING_REPLY: - { - struct gg_header *h; - - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() GG_STATE_READING_REPLY\n"); - - if (!(h = gg_recv_packet(sess))) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() didn't receive packet (errno=%d, %s)\n", errno, strerror(errno)); - e->type = GG_EVENT_CONN_FAILED; - e->event.failure = GG_FAILURE_READING; - sess->state = GG_STATE_IDLE; - errno2 = errno; - close(sess->fd); - errno = errno2; - sess->fd = -1; - break; - } - - if (h->type == GG_LOGIN_OK || h->type == GG_NEED_EMAIL) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() login succeded\n"); - e->type = GG_EVENT_CONN_SUCCESS; - sess->state = GG_STATE_CONNECTED; - sess->timeout = -1; - sess->status = (sess->initial_status) ? sess->initial_status : GG_STATUS_AVAIL; - free(h); - break; - } - - if (h->type == GG_LOGIN_FAILED) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() login failed\n"); - e->event.failure = GG_FAILURE_PASSWORD; - errno = EACCES; - } else if (h->type == GG_DISCONNECTING) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() too many incorrect password attempts\n"); - e->event.failure = GG_FAILURE_INTRUDER; - errno = EACCES; - } else { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() invalid packet\n"); - e->event.failure = GG_FAILURE_INVALID; - errno = EINVAL; - } - - e->type = GG_EVENT_CONN_FAILED; - sess->state = GG_STATE_IDLE; - errno2 = errno; - close(sess->fd); - errno = errno2; - sess->fd = -1; - free(h); - - break; - } - - case GG_STATE_CONNECTED: - { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() GG_STATE_CONNECTED\n"); - - sess->last_event = time(NULL); - - if ((res = gg_watch_fd_connected(sess, e)) == -1) { - - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() watch_fd_connected failed (errno=%d, %s)\n", errno, strerror(errno)); - - if (errno == EAGAIN) { - e->type = GG_EVENT_NONE; - res = 0; - } else - res = -1; - } - break; - } - } - -done: - if (res == -1) { - free(e); - e = NULL; - } - - return e; - -fail_connecting: - if (sess->fd != -1) { - errno2 = errno; - close(sess->fd); - errno = errno2; - sess->fd = -1; - } - e->type = GG_EVENT_CONN_FAILED; - e->event.failure = GG_FAILURE_CONNECTING; - sess->state = GG_STATE_IDLE; - goto done; - -fail_resolving: - e->type = GG_EVENT_CONN_FAILED; - e->event.failure = GG_FAILURE_RESOLVING; - sess->state = GG_STATE_IDLE; - goto done; - -fail_unavailable: - e->type = GG_EVENT_CONN_FAILED; - e->event.failure = GG_FAILURE_UNAVAILABLE; - sess->state = GG_STATE_IDLE; - goto done; -} - -/* - * Local variables: - * c-indentation-style: k&r - * c-basic-offset: 8 - * indent-tabs-mode: notnil - * End: - * - * vim: shiftwidth=8: - */ diff --git a/kopete/protocols/gadu/libgadu/http.c b/kopete/protocols/gadu/libgadu/http.c deleted file mode 100644 index 9f7369c5..00000000 --- a/kopete/protocols/gadu/libgadu/http.c +++ /dev/null @@ -1,522 +0,0 @@ -/* $Id$ */ - -/* - * (C) Copyright 2001-2002 Wojtek Kaniewski <wojtekka@irc.pl> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License Version - * 2.1 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA. - */ - -#include <sys/types.h> -#include <sys/wait.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> - -#include "libgadu-config.h" - -#include <ctype.h> -#include <errno.h> -#include <netdb.h> -#ifdef __GG_LIBGADU_HAVE_PTHREAD -# include <pthread.h> -#endif -#include <stdarg.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#include "compat.h" -#include "libgadu.h" - -/* - * gg_http_connect() // funkcja pomocnicza - * - * rozpoczyna po��czenie po http. - * - * - hostname - adres serwera - * - port - port serwera - * - async - asynchroniczne po��czenie - * - method - metoda http (GET, POST, cokolwiek) - * - path - �cie�ka do zasobu (musi by� poprzedzona ,,/'') - * - header - nag��wek zapytania plus ewentualne dane dla POST - * - * zaalokowana struct gg_http, kt�r� po�niej nale�y - * zwolni� funkcj� gg_http_free(), albo NULL je�li wyst�pi� b��d. - */ -struct gg_http *gg_http_connect(const char *hostname, int port, int async, const char *method, const char *path, const char *header) -{ - struct gg_http *h; - - if (!hostname || !port || !method || !path || !header) { - gg_debug(GG_DEBUG_MISC, "// gg_http_connect() invalid arguments\n"); - errno = EFAULT; - return NULL; - } - - if (!(h = malloc(sizeof(*h)))) - return NULL; - memset(h, 0, sizeof(*h)); - - h->async = async; - h->port = port; - h->fd = -1; - h->type = GG_SESSION_HTTP; - - if (gg_proxy_enabled) { - char *auth = gg_proxy_auth(); - - h->query = gg_saprintf("%s http://%s:%d%s HTTP/1.0\r\n%s%s", - method, hostname, port, path, (auth) ? auth : - "", header); - hostname = gg_proxy_host; - h->port = port = gg_proxy_port; - - if (auth) - free(auth); - } else { - h->query = gg_saprintf("%s %s HTTP/1.0\r\n%s", - method, path, header); - } - - if (!h->query) { - gg_debug(GG_DEBUG_MISC, "// gg_http_connect() not enough memory for query\n"); - free(h); - errno = ENOMEM; - return NULL; - } - - gg_debug(GG_DEBUG_MISC, "=> -----BEGIN-HTTP-QUERY-----\n%s\n=> -----END-HTTP-QUERY-----\n", h->query); - - if (async) { -#ifndef __GG_LIBGADU_HAVE_PTHREAD - if (gg_resolve(&h->fd, &h->pid, hostname)) { -#else - if (gg_resolve_pthread(&h->fd, &h->resolver, hostname)) { -#endif - gg_debug(GG_DEBUG_MISC, "// gg_http_connect() resolver failed\n"); - gg_http_free(h); - errno = ENOENT; - return NULL; - } - - gg_debug(GG_DEBUG_MISC, "// gg_http_connect() resolver = %p\n", h->resolver); - - h->state = GG_STATE_RESOLVING; - h->check = GG_CHECK_READ; - h->timeout = GG_DEFAULT_TIMEOUT; - } else { - struct in_addr *hn, a; - - if (!(hn = gg_gethostbyname(hostname))) { - gg_debug(GG_DEBUG_MISC, "// gg_http_connect() host not found\n"); - gg_http_free(h); - errno = ENOENT; - return NULL; - } else { - a.s_addr = hn->s_addr; - free(hn); - } - - if (!(h->fd = gg_connect(&a, port, 0)) == -1) { - gg_debug(GG_DEBUG_MISC, "// gg_http_connect() connection failed (errno=%d, %s)\n", errno, strerror(errno)); - gg_http_free(h); - return NULL; - } - - h->state = GG_STATE_CONNECTING; - - while (h->state != GG_STATE_ERROR && h->state != GG_STATE_PARSING) { - if (gg_http_watch_fd(h) == -1) - break; - } - - if (h->state != GG_STATE_PARSING) { - gg_debug(GG_DEBUG_MISC, "// gg_http_connect() some strange error\n"); - gg_http_free(h); - return NULL; - } - } - - h->callback = gg_http_watch_fd; - h->destroy = gg_http_free; - - return h; -} - -#define gg_http_error(x) \ - close(h->fd); \ - h->fd = -1; \ - h->state = GG_STATE_ERROR; \ - h->error = x; \ - return 0; - -/* - * gg_http_watch_fd() - * - * przy asynchronicznej obs�udze HTTP funkcj� t� nale�y wywo�a�, je�li - * zmieni�o si� co� na obserwowanym deskryptorze. - * - * - h - struktura opisuj�ca po��czenie - * - * je�li wszystko posz�o dobrze to 0, inaczej -1. po��czenie b�dzie - * zako�czone, je�li h->state == GG_STATE_PARSING. je�li wyst�pi jaki� - * b��d, to b�dzie tam GG_STATE_ERROR i odpowiedni kod b��du w h->error. - */ -int gg_http_watch_fd(struct gg_http *h) -{ - gg_debug(GG_DEBUG_FUNCTION, "** gg_http_watch_fd(%p);\n", h); - - if (!h) { - gg_debug(GG_DEBUG_MISC, "// gg_http_watch_fd() invalid arguments\n"); - errno = EFAULT; - return -1; - } - - if (h->state == GG_STATE_RESOLVING) { - struct in_addr a; - - gg_debug(GG_DEBUG_MISC, "=> http, resolving done\n"); - - if (read(h->fd, &a, sizeof(a)) < (signed)sizeof(a) || a.s_addr == INADDR_NONE) { - gg_debug(GG_DEBUG_MISC, "=> http, resolver thread failed\n"); - gg_http_error(GG_ERROR_RESOLVING); - } - - close(h->fd); - h->fd = -1; - -#ifndef __GG_LIBGADU_HAVE_PTHREAD - waitpid(h->pid, NULL, 0); -#else - if (h->resolver) { - pthread_cancel(*((pthread_t *) h->resolver)); - free(h->resolver); - h->resolver = NULL; - } -#endif - - gg_debug(GG_DEBUG_MISC, "=> http, connecting to %s:%d\n", inet_ntoa(a), h->port); - - if ((h->fd = gg_connect(&a, h->port, h->async)) == -1) { - gg_debug(GG_DEBUG_MISC, "=> http, connection failed (errno=%d, %s)\n", errno, strerror(errno)); - gg_http_error(GG_ERROR_CONNECTING); - } - - h->state = GG_STATE_CONNECTING; - h->check = GG_CHECK_WRITE; - h->timeout = GG_DEFAULT_TIMEOUT; - - return 0; - } - - if (h->state == GG_STATE_CONNECTING) { - int res = 0; - unsigned int res_size = sizeof(res); - - if (h->async && (getsockopt(h->fd, SOL_SOCKET, SO_ERROR, &res, &res_size) || res)) { - gg_debug(GG_DEBUG_MISC, "=> http, async connection failed (errno=%d, %s)\n", (res) ? res : errno , strerror((res) ? res : errno)); - close(h->fd); - h->fd = -1; - h->state = GG_STATE_ERROR; - h->error = GG_ERROR_CONNECTING; - if (res) - errno = res; - return 0; - } - - gg_debug(GG_DEBUG_MISC, "=> http, connected, sending request\n"); - - h->state = GG_STATE_SENDING_QUERY; - } - - if (h->state == GG_STATE_SENDING_QUERY) { - int res; - - if ((res = write(h->fd, h->query, strlen(h->query))) < 1) { - gg_debug(GG_DEBUG_MISC, "=> http, write() failed (len=%d, res=%d, errno=%d)\n", strlen(h->query), res, errno); - gg_http_error(GG_ERROR_WRITING); - } - - if (res < strlen(h->query)) { - gg_debug(GG_DEBUG_MISC, "=> http, partial header sent (led=%d, sent=%d)\n", strlen(h->query), res); - - memmove(h->query, h->query + res, strlen(h->query) - res + 1); - h->state = GG_STATE_SENDING_QUERY; - h->check = GG_CHECK_WRITE; - h->timeout = GG_DEFAULT_TIMEOUT; - } else { - gg_debug(GG_DEBUG_MISC, "=> http, request sent (len=%d)\n", strlen(h->query)); - free(h->query); - h->query = NULL; - - h->state = GG_STATE_READING_HEADER; - h->check = GG_CHECK_READ; - h->timeout = GG_DEFAULT_TIMEOUT; - } - - return 0; - } - - if (h->state == GG_STATE_READING_HEADER) { - char buf[1024], *tmp; - int res; - - if ((res = read(h->fd, buf, sizeof(buf))) == -1) { - gg_debug(GG_DEBUG_MISC, "=> http, reading header failed (errno=%d)\n", errno); - if (h->header) { - free(h->header); - h->header = NULL; - } - gg_http_error(GG_ERROR_READING); - } - - if (!res) { - gg_debug(GG_DEBUG_MISC, "=> http, connection reset by peer\n"); - if (h->header) { - free(h->header); - h->header = NULL; - } - gg_http_error(GG_ERROR_READING); - } - - gg_debug(GG_DEBUG_MISC, "=> http, read %d bytes of header\n", res); - - if (!(tmp = realloc(h->header, h->header_size + res + 1))) { - gg_debug(GG_DEBUG_MISC, "=> http, not enough memory for header\n"); - free(h->header); - h->header = NULL; - gg_http_error(GG_ERROR_READING); - } - - h->header = tmp; - - memcpy(h->header + h->header_size, buf, res); - h->header_size += res; - - gg_debug(GG_DEBUG_MISC, "=> http, header_buf=%p, header_size=%d\n", h->header, h->header_size); - - h->header[h->header_size] = 0; - - if ((tmp = strstr(h->header, "\r\n\r\n")) || (tmp = strstr(h->header, "\n\n"))) { - int sep_len = (*tmp == '\r') ? 4 : 2; - unsigned int left; - char *line; - - left = h->header_size - ((long)(tmp) - (long)(h->header) + sep_len); - - gg_debug(GG_DEBUG_MISC, "=> http, got all header (%d bytes, %d left)\n", h->header_size - left, left); - - /* HTTP/1.1 200 OK */ - if (strlen(h->header) < 16 || strncmp(h->header + 9, "200", 3)) { - gg_debug(GG_DEBUG_MISC, "=> -----BEGIN-HTTP-HEADER-----\n%s\n=> -----END-HTTP-HEADER-----\n", h->header); - - gg_debug(GG_DEBUG_MISC, "=> http, didn't get 200 OK -- no results\n"); - free(h->header); - h->header = NULL; - gg_http_error(GG_ERROR_CONNECTING); - } - - h->body_size = 0; - line = h->header; - *tmp = 0; - - gg_debug(GG_DEBUG_MISC, "=> -----BEGIN-HTTP-HEADER-----\n%s\n=> -----END-HTTP-HEADER-----\n", h->header); - - while (line) { - if (!strncasecmp(line, "Content-length: ", 16)) { - h->body_size = atoi(line + 16); - } - line = (char*)strchr(line, '\n'); - if (line) - line++; - } - - if (h->body_size <= 0) { - gg_debug(GG_DEBUG_MISC, "=> http, content-length not found\n"); - h->body_size = left; - } - - if (left > h->body_size) { - gg_debug(GG_DEBUG_MISC, "=> http, oversized reply (%d bytes needed, %d bytes left)\n", h->body_size, left); - h->body_size = left; - } - - gg_debug(GG_DEBUG_MISC, "=> http, body_size=%d\n", h->body_size); - - if (!(h->body = malloc(h->body_size + 1))) { - gg_debug(GG_DEBUG_MISC, "=> http, not enough memory (%d bytes for body_buf)\n", h->body_size + 1); - free(h->header); - h->header = NULL; - gg_http_error(GG_ERROR_READING); - } - - if (left) { - memcpy(h->body, tmp + sep_len, left); - h->body_done = left; - } - - h->body[left] = 0; - - h->state = GG_STATE_READING_DATA; - h->check = GG_CHECK_READ; - h->timeout = GG_DEFAULT_TIMEOUT; - } - - return 0; - } - - if (h->state == GG_STATE_READING_DATA) { - char buf[1024]; - int res; - - if ((res = read(h->fd, buf, sizeof(buf))) == -1) { - gg_debug(GG_DEBUG_MISC, "=> http, reading body failed (errno=%d)\n", errno); - if (h->body) { - free(h->body); - h->body = NULL; - } - gg_http_error(GG_ERROR_READING); - } - - if (!res) { - if (h->body_done >= h->body_size) { - gg_debug(GG_DEBUG_MISC, "=> http, we're done, closing socket\n"); - h->state = GG_STATE_PARSING; - close(h->fd); - h->fd = -1; - } else { - gg_debug(GG_DEBUG_MISC, "=> http, connection closed while reading (have %d, need %d)\n", h->body_done, h->body_size); - if (h->body) { - free(h->body); - h->body = NULL; - } - gg_http_error(GG_ERROR_READING); - } - - return 0; - } - - gg_debug(GG_DEBUG_MISC, "=> http, read %d bytes of body\n", res); - - if (h->body_done + res > h->body_size) { - char *tmp; - - gg_debug(GG_DEBUG_MISC, "=> http, too much data (%d bytes, %d needed), enlarging buffer\n", h->body_done + res, h->body_size); - - if (!(tmp = realloc(h->body, h->body_done + res + 1))) { - gg_debug(GG_DEBUG_MISC, "=> http, not enough memory for data (%d needed)\n", h->body_done + res + 1); - free(h->body); - h->body = NULL; - gg_http_error(GG_ERROR_READING); - } - - h->body = tmp; - h->body_size = h->body_done + res; - } - - h->body[h->body_done + res] = 0; - memcpy(h->body + h->body_done, buf, res); - h->body_done += res; - - gg_debug(GG_DEBUG_MISC, "=> body_done=%d, body_size=%d\n", h->body_done, h->body_size); - - return 0; - } - - if (h->fd != -1) - close(h->fd); - - h->fd = -1; - h->state = GG_STATE_ERROR; - h->error = 0; - - return -1; -} - -#undef gg_http_error - -/* - * gg_http_stop() - * - * je�li po��czenie jest w trakcie, przerywa je. nie zwalnia h->data. - * - * - h - struktura opisuj�ca po��czenie - */ -void gg_http_stop(struct gg_http *h) -{ - if (!h) - return; - - if (h->state == GG_STATE_ERROR || h->state == GG_STATE_DONE) - return; - - if (h->fd != -1) - close(h->fd); - h->fd = -1; -} - -/* - * gg_http_free_fields() // funkcja wewn�trzna - * - * zwalnia pola struct gg_http, ale nie zwalnia samej struktury. - */ -void gg_http_free_fields(struct gg_http *h) -{ - if (!h) - return; - - if (h->body) { - free(h->body); - h->body = NULL; - } - - if (h->query) { - free(h->query); - h->query = NULL; - } - - if (h->header) { - free(h->header); - h->header = NULL; - } -} - -/* - * gg_http_free() - * - * pr�buje zamkn�� po��czenie i zwalnia pami�� po nim. - * - * - h - struktura, kt�r� nale�y zlikwidowa� - */ -void gg_http_free(struct gg_http *h) -{ - if (!h) - return; - - gg_http_stop(h); - gg_http_free_fields(h); - free(h); -} - -/* - * Local variables: - * c-indentation-style: k&r - * c-basic-offset: 8 - * indent-tabs-mode: notnil - * End: - * - * vim: shiftwidth=8: - */ diff --git a/kopete/protocols/gadu/libgadu/libgadu-config.h.in b/kopete/protocols/gadu/libgadu/libgadu-config.h.in deleted file mode 100644 index dc4fb435..00000000 --- a/kopete/protocols/gadu/libgadu/libgadu-config.h.in +++ /dev/null @@ -1,30 +0,0 @@ -/* Local libgadu configuration. */ - -#ifndef __GG_LIBGADU_CONFIG_H -#define __GG_LIBGADU_CONFIG_H - -/* Defined if libgadu was compiled for bigendian machine. */ -#undef __GG_LIBGADU_BIGENDIAN - -/* Defined if libgadu was compiled and linked with pthread support. */ -#define __GG_LIBGADU_HAVE_PTHREAD - -/* Defined if this machine has C99-compiliant vsnprintf(). */ -#undef __GG_LIBGADU_HAVE_C99_VSNPRINTF - -/* Defined if this machine has va_copy(). */ -#undef __GG_LIBGADU_HAVE_VA_COPY - -/* Defined if this machine has __va_copy(). */ -#undef __GG_LIBGADU_HAVE___VA_COPY - -/* Defined if this machine supports long long. */ -#undef __GG_LIBGADU_HAVE_LONG_LONG - -/* Defined if libgadu was compiled and linked with TLS support. */ -#undef __GG_LIBGADU_HAVE_OPENSSL - -/* Include file containing uintXX_t declarations. */ -#include <inttypes.h> - -#endif /* __GG_LIBGADU_CONFIG_H */ diff --git a/kopete/protocols/gadu/libgadu/libgadu.c b/kopete/protocols/gadu/libgadu/libgadu.c deleted file mode 100644 index 79f0a170..00000000 --- a/kopete/protocols/gadu/libgadu/libgadu.c +++ /dev/null @@ -1,1818 +0,0 @@ -/* $Id$ */ - -/* - * (C) Copyright 2001-2006 Wojtek Kaniewski <wojtekka@irc.pl> - * Robert J. Wo¼ny <speedy@ziew.org> - * Arkadiusz Mi¶kiewicz <arekm@pld-linux.org> - * Tomasz Chiliñski <chilek@chilan.com> - * Adam Wysocki <gophi@ekg.chmurka.net> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License Version - * 2.1 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA. - */ - -#include <sys/types.h> -#include <sys/wait.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#ifdef sun -# include <sys/filio.h> -#endif - -#include "libgadu-config.h" - -#include <errno.h> -#include <netdb.h> -#ifdef __GG_LIBGADU_HAVE_PTHREAD -# include <pthread.h> -#endif -#include <stdarg.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <signal.h> -#include <unistd.h> -#ifdef __GG_LIBGADU_HAVE_OPENSSL -# include <openssl/err.h> -# include <openssl/rand.h> -#endif - -#include "compat.h" -#include "libgadu.h" - -int gg_debug_level = 0; -void (*gg_debug_handler)(int level, const char *format, va_list ap) = NULL; - -int gg_dcc_port = 0; -unsigned long gg_dcc_ip = 0; - -unsigned long gg_local_ip = 0; -/* - * zmienne opisuj±ce parametry proxy http. - */ -char *gg_proxy_host = NULL; -int gg_proxy_port = 0; -int gg_proxy_enabled = 0; -int gg_proxy_http_only = 0; -char *gg_proxy_username = NULL; -char *gg_proxy_password = NULL; - -#ifndef lint -static char rcsid[] -#ifdef __GNUC__ -__attribute__ ((unused)) -#endif -= "$Id$"; -#endif - -/* - * gg_libgadu_version() - * - * zwraca wersjê libgadu. - * - * - brak - * - * wersja libgadu. - */ -const char *gg_libgadu_version() -{ - return GG_LIBGADU_VERSION; -} - -/* - * gg_fix32() - * - * zamienia kolejno¶æ bajtów w liczbie 32-bitowej tak, by odpowiada³a - * kolejno¶ci bajtów w protokole GG. ze wzglêdu na LE-owo¶æ serwera, - * zamienia tylko na maszynach BE-wych. - * - * - x - liczba do zamiany - * - * liczba z odpowiedni± kolejno¶ci± bajtów. - */ -uint32_t gg_fix32(uint32_t x) -{ -#ifndef __GG_LIBGADU_BIGENDIAN - return x; -#else - return (uint32_t) - (((x & (uint32_t) 0x000000ffU) << 24) | - ((x & (uint32_t) 0x0000ff00U) << 8) | - ((x & (uint32_t) 0x00ff0000U) >> 8) | - ((x & (uint32_t) 0xff000000U) >> 24)); -#endif -} - -/* - * gg_fix16() - * - * zamienia kolejno¶æ bajtów w liczbie 16-bitowej tak, by odpowiada³a - * kolejno¶ci bajtów w protokole GG. ze wzglêdu na LE-owo¶æ serwera, - * zamienia tylko na maszynach BE-wych. - * - * - x - liczba do zamiany - * - * liczba z odpowiedni± kolejno¶ci± bajtów. - */ -uint16_t gg_fix16(uint16_t x) -{ -#ifndef __GG_LIBGADU_BIGENDIAN - return x; -#else - return (uint16_t) - (((x & (uint16_t) 0x00ffU) << 8) | - ((x & (uint16_t) 0xff00U) >> 8)); -#endif -} - -/* - * gg_login_hash() // funkcja wewnêtrzna - * - * liczy hash z has³a i danego seeda. - * - * - password - has³o do hashowania - * - seed - warto¶æ podana przez serwer - * - * hash. - */ -unsigned int gg_login_hash(const unsigned char *password, unsigned int seed) -{ - unsigned int x, y, z; - - y = seed; - - for (x = 0; *password; password++) { - x = (x & 0xffffff00) | *password; - y ^= x; - y += x; - x <<= 8; - y ^= x; - x <<= 8; - y -= x; - x <<= 8; - y ^= x; - - z = y & 0x1F; - y = (y << z) | (y >> (32 - z)); - } - - return y; -} - -/* - * gg_resolve() // funkcja wewnêtrzna - * - * tworzy potok, forkuje siê i w drugim procesie zaczyna resolvowaæ - * podanego hosta. zapisuje w sesji deskryptor potoku. je¶li co¶ tam - * bêdzie gotowego, znaczy, ¿e mo¿na wczytaæ struct in_addr. je¶li - * nie znajdzie, zwraca INADDR_NONE. - * - * - fd - wska¼nik gdzie wrzuciæ deskryptor - * - pid - gdzie wrzuciæ pid procesu potomnego - * - hostname - nazwa hosta do zresolvowania - * - * 0, -1. - */ -int gg_resolve(int *fd, int *pid, const char *hostname) -{ - int pipes[2], res; - struct in_addr a; - int errno2; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_resolve(%p, %p, \"%s\");\n", fd, pid, hostname); - - if (!fd || !pid) { - errno = EFAULT; - return -1; - } - - if (pipe(pipes) == -1) - return -1; - - if ((res = fork()) == -1) { - errno2 = errno; - close(pipes[0]); - close(pipes[1]); - errno = errno2; - return -1; - } - - if (!res) { - close(pipes[0]); - - if ((a.s_addr = inet_addr(hostname)) == INADDR_NONE) { - struct in_addr *hn; - - if (!(hn = gg_gethostbyname(hostname))) - a.s_addr = INADDR_NONE; - else { - a.s_addr = hn->s_addr; - free(hn); - } - } - - write(pipes[1], &a, sizeof(a)); - - exit(0); - } - - close(pipes[1]); - - *fd = pipes[0]; - *pid = res; - - return 0; -} - -#ifdef __GG_LIBGADU_HAVE_PTHREAD - -struct gg_resolve_pthread_data { - char *hostname; - int fd; -}; - -static void *gg_resolve_pthread_thread(void *arg) -{ - struct gg_resolve_pthread_data *d = arg; - struct in_addr a; - - pthread_detach(pthread_self()); - - if ((a.s_addr = inet_addr(d->hostname)) == INADDR_NONE) { - struct in_addr *hn; - - if (!(hn = gg_gethostbyname(d->hostname))) - a.s_addr = INADDR_NONE; - else { - a.s_addr = hn->s_addr; - free(hn); - } - } - - write(d->fd, &a, sizeof(a)); - close(d->fd); - - free(d->hostname); - d->hostname = NULL; - - free(d); - - pthread_exit(NULL); - - return NULL; /* ¿eby kompilator nie marudzi³ */ -} - -/* - * gg_resolve_pthread() // funkcja wewnêtrzna - * - * tworzy potok, nowy w±tek i w nim zaczyna resolvowaæ podanego hosta. - * zapisuje w sesji deskryptor potoku. je¶li co¶ tam bêdzie gotowego, - * znaczy, ¿e mo¿na wczytaæ struct in_addr. je¶li nie znajdzie, zwraca - * INADDR_NONE. - * - * - fd - wska¼nik do zmiennej przechowuj±cej desktyptor resolvera - * - resolver - wska¼nik do wska¼nika resolvera - * - hostname - nazwa hosta do zresolvowania - * - * 0, -1. - */ -int gg_resolve_pthread(int *fd, void **resolver, const char *hostname) -{ - struct gg_resolve_pthread_data *d = NULL; - pthread_t *tmp; - int pipes[2], new_errno; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_resolve_pthread(%p, %p, \"%s\");\n", fd, resolver, hostname); - - if (!resolver || !fd || !hostname) { - gg_debug(GG_DEBUG_MISC, "// gg_resolve_pthread() invalid arguments\n"); - errno = EFAULT; - return -1; - } - - if (!(tmp = malloc(sizeof(pthread_t)))) { - gg_debug(GG_DEBUG_MISC, "// gg_resolve_pthread() out of memory for pthread id\n"); - return -1; - } - - if (pipe(pipes) == -1) { - gg_debug(GG_DEBUG_MISC, "// gg_resolve_pthread() unable to create pipes (errno=%d, %s)\n", errno, strerror(errno)); - free(tmp); - return -1; - } - - if (!(d = malloc(sizeof(*d)))) { - gg_debug(GG_DEBUG_MISC, "// gg_resolve_pthread() out of memory\n"); - new_errno = errno; - goto cleanup; - } - - d->hostname = NULL; - - if (!(d->hostname = strdup(hostname))) { - gg_debug(GG_DEBUG_MISC, "// gg_resolve_pthread() out of memory\n"); - new_errno = errno; - goto cleanup; - } - - d->fd = pipes[1]; - - if (pthread_create(tmp, NULL, gg_resolve_pthread_thread, d)) { - gg_debug(GG_DEBUG_MISC, "// gg_resolve_phread() unable to create thread\n"); - new_errno = errno; - goto cleanup; - } - - gg_debug(GG_DEBUG_MISC, "// gg_resolve_pthread() %p\n", tmp); - - *resolver = tmp; - - *fd = pipes[0]; - - return 0; - -cleanup: - if (d) { - free(d->hostname); - free(d); - } - - close(pipes[0]); - close(pipes[1]); - - free(tmp); - - errno = new_errno; - - return -1; -} - -#endif - -/* - * gg_read() // funkcja pomocnicza - * - * czyta z gniazda okre¶lon± ilo¶æ bajtów. bierze pod uwagê, czy mamy - * po³±czenie zwyk³e czy TLS. - * - * - sess - sesja, - * - buf - bufor, - * - length - ilo¶æ bajtów, - * - * takie same warto¶ci jak read(). - */ -int gg_read(struct gg_session *sess, char *buf, int length) -{ - int res; - -#ifdef __GG_LIBGADU_HAVE_OPENSSL - if (sess->ssl) { - int err; - - res = SSL_read(sess->ssl, buf, length); - - if (res < 0) { - err = SSL_get_error(sess->ssl, res); - - if (err == SSL_ERROR_WANT_READ) - errno = EAGAIN; - - return -1; - } - } else -#endif - res = read(sess->fd, buf, length); - - return res; -} - -/* - * gg_write() // funkcja pomocnicza - * - * zapisuje do gniazda okre¶lon± ilo¶æ bajtów. bierze pod uwagê, czy mamy - * po³±czenie zwyk³e czy TLS. - * - * - sess - sesja, - * - buf - bufor, - * - length - ilo¶æ bajtów, - * - * takie same warto¶ci jak write(). - */ -int gg_write(struct gg_session *sess, const char *buf, int length) -{ - int res = 0; - -#ifdef __GG_LIBGADU_HAVE_OPENSSL - if (sess->ssl) { - int err; - - res = SSL_write(sess->ssl, buf, length); - - if (res < 0) { - err = SSL_get_error(sess->ssl, res); - - if (err == SSL_ERROR_WANT_WRITE) - errno = EAGAIN; - - return -1; - } - } else -#endif - { - int written = 0; - - while (written < length) { - res = write(sess->fd, buf + written, length - written); - - if (res == -1) { - if (errno == EAGAIN) - continue; - else - break; - } else { - written += res; - res = written; - } - } - } - - return res; -} - -/* - * gg_recv_packet() // funkcja wewnêtrzna - * - * odbiera jeden pakiet i zwraca wska¼nik do niego. pamiêæ po nim - * nale¿y zwolniæ za pomoc± free(). - * - * - sess - opis sesji - * - * w przypadku b³êdu NULL, kod b³êdu w errno. nale¿y zwróciæ uwagê, ¿e gdy - * po³±czenie jest nieblokuj±ce, a kod b³êdu wynosi EAGAIN, nie uda³o siê - * odczytaæ ca³ego pakietu i nie nale¿y tego traktowaæ jako b³±d. - */ -void *gg_recv_packet(struct gg_session *sess) -{ - struct gg_header h; - char *buf = NULL; - int ret = 0; - unsigned int offset, size = 0; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_recv_packet(%p);\n", sess); - - if (!sess) { - errno = EFAULT; - return NULL; - } - - if (sess->recv_left < 1) { - if (sess->header_buf) { - memcpy(&h, sess->header_buf, sess->header_done); - gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() header recv: resuming last read (%d bytes left)\n", sizeof(h) - sess->header_done); - free(sess->header_buf); - sess->header_buf = NULL; - } else - sess->header_done = 0; - - while (sess->header_done < sizeof(h)) { - ret = gg_read(sess, (char*) &h + sess->header_done, sizeof(h) - sess->header_done); - - gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() header recv(%d,%p,%d) = %d\n", sess->fd, &h + sess->header_done, sizeof(h) - sess->header_done, ret); - - if (!ret) { - errno = ECONNRESET; - gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() header recv() failed: connection broken\n"); - return NULL; - } - - if (ret == -1) { - if (errno == EINTR) { - gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() header recv() interrupted system call, resuming\n"); - continue; - } - - if (errno == EAGAIN) { - gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() header recv() incomplete header received\n"); - - if (!(sess->header_buf = malloc(sess->header_done))) { - gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() header recv() not enough memory\n"); - return NULL; - } - - memcpy(sess->header_buf, &h, sess->header_done); - - return NULL; - } - - gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() header recv() failed: errno=%d, %s\n", errno, strerror(errno)); - - return NULL; - } - - sess->header_done += ret; - - } - - h.type = gg_fix32(h.type); - h.length = gg_fix32(h.length); - } else - memcpy(&h, sess->recv_buf, sizeof(h)); - - /* jakie¶ sensowne limity na rozmiar pakietu */ - if (h.length > 65535) { - gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() invalid packet length (%d)\n", h.length); - errno = ERANGE; - return NULL; - } - - if (sess->recv_left > 0) { - gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() resuming last gg_recv_packet()\n"); - size = sess->recv_left; - offset = sess->recv_done; - buf = sess->recv_buf; - } else { - if (!(buf = malloc(sizeof(h) + h.length + 1))) { - gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() not enough memory for packet data\n"); - return NULL; - } - - memcpy(buf, &h, sizeof(h)); - - offset = 0; - size = h.length; - } - - while (size > 0) { - ret = gg_read(sess, buf + sizeof(h) + offset, size); - gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() body recv(%d,%p,%d) = %d\n", sess->fd, buf + sizeof(h) + offset, size, ret); - if (!ret) { - gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() body recv() failed: connection broken\n"); - errno = ECONNRESET; - return NULL; - } - if (ret > -1 && ret <= size) { - offset += ret; - size -= ret; - } else if (ret == -1) { - int errno2 = errno; - - gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() body recv() failed (errno=%d, %s)\n", errno, strerror(errno)); - errno = errno2; - - if (errno == EAGAIN) { - gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() %d bytes received, %d left\n", offset, size); - sess->recv_buf = buf; - sess->recv_left = size; - sess->recv_done = offset; - return NULL; - } - if (errno != EINTR) { - free(buf); - return NULL; - } - } - } - - sess->recv_left = 0; - - if ((gg_debug_level & GG_DEBUG_DUMP)) { - unsigned int i; - - gg_debug(GG_DEBUG_DUMP, "// gg_recv_packet(%.2x)", h.type); - for (i = 0; i < sizeof(h) + h.length; i++) - gg_debug(GG_DEBUG_DUMP, " %.2x", (unsigned char) buf[i]); - gg_debug(GG_DEBUG_DUMP, "\n"); - } - - return buf; -} - -/* - * gg_send_packet() // funkcja wewnêtrzna - * - * konstruuje pakiet i wysy³a go do serwera. - * - * - sock - deskryptor gniazda - * - type - typ pakietu - * - payload_1 - pierwsza czê¶æ pakietu - * - payload_length_1 - d³ugo¶æ pierwszej czê¶ci - * - payload_2 - druga czê¶æ pakietu - * - payload_length_2 - d³ugo¶æ drugiej czê¶ci - * - ... - kolejne czê¶ci pakietu i ich d³ugo¶ci - * - NULL - koñcowym parametr (konieczny!) - * - * je¶li siê powiod³o, zwraca 0, w przypadku b³êdu -1. je¶li errno == ENOMEM, - * zabrak³o pamiêci. inaczej by³ b³±d przy wysy³aniu pakietu. dla errno == 0 - * nie wys³ano ca³ego pakietu. - */ -int gg_send_packet(struct gg_session *sess, int type, ...) -{ - struct gg_header *h; - char *tmp; - unsigned int tmp_length; - void *payload; - unsigned int payload_length; - va_list ap; - int res; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_send_packet(%p, 0x%.2x, ...)\n", sess, type); - - tmp_length = sizeof(struct gg_header); - - if (!(tmp = malloc(tmp_length))) { - gg_debug(GG_DEBUG_MISC, "// gg_send_packet() not enough memory for packet header\n"); - return -1; - } - - va_start(ap, type); - - payload = va_arg(ap, void *); - - while (payload) { - char *tmp2; - - payload_length = va_arg(ap, unsigned int); - - if (!(tmp2 = realloc(tmp, tmp_length + payload_length))) { - gg_debug(GG_DEBUG_MISC, "// gg_send_packet() not enough memory for payload\n"); - free(tmp); - va_end(ap); - return -1; - } - - tmp = tmp2; - - memcpy(tmp + tmp_length, payload, payload_length); - tmp_length += payload_length; - - payload = va_arg(ap, void *); - } - - va_end(ap); - - h = (struct gg_header*) tmp; - h->type = gg_fix32(type); - h->length = gg_fix32(tmp_length - sizeof(struct gg_header)); - - if ((gg_debug_level & GG_DEBUG_DUMP)) { - unsigned int i; - - gg_debug(GG_DEBUG_DUMP, "// gg_send_packet(0x%.2x)", gg_fix32(h->type)); - for (i = 0; i < tmp_length; ++i) - gg_debug(GG_DEBUG_DUMP, " %.2x", (unsigned char) tmp[i]); - gg_debug(GG_DEBUG_DUMP, "\n"); - } - - if ((res = gg_write(sess, tmp, tmp_length)) < tmp_length) { - gg_debug(GG_DEBUG_MISC, "// gg_send_packet() write() failed. res = %d, errno = %d (%s)\n", res, errno, strerror(errno)); - free(tmp); - return -1; - } - - free(tmp); - return 0; -} - -/* - * gg_session_callback() // funkcja wewnêtrzna - * - * wywo³ywany z gg_session->callback, wykonuje gg_watch_fd() i pakuje - * do gg_session->event jego wynik. - */ -static int gg_session_callback(struct gg_session *s) -{ - if (!s) { - errno = EFAULT; - return -1; - } - - return ((s->event = gg_watch_fd(s)) != NULL) ? 0 : -1; -} - -/* - * gg_login() - * - * rozpoczyna procedurê ³±czenia siê z serwerem. resztê obs³uguje siê przez - * gg_watch_fd(). - * - * UWAGA! program musi obs³u¿yæ SIGCHLD, je¶li ³±czy siê asynchronicznie, - * ¿eby poprawnie zamkn±æ proces resolvera. - * - * - p - struktura opisuj±ca pocz±tkowy stan. wymagane pola: uin, - * password - * - * w przypadku b³êdu NULL, je¶li idzie dobrze (async) albo posz³o - * dobrze (sync), zwróci wska¼nik do zaalokowanej struct gg_session. - */ -struct gg_session *gg_login(const struct gg_login_params *p) -{ - struct gg_session *sess = NULL; - char *hostname; - int port; - - if (!p) { - gg_debug(GG_DEBUG_FUNCTION, "** gg_login(%p);\n", p); - errno = EFAULT; - return NULL; - } - - gg_debug(GG_DEBUG_FUNCTION, "** gg_login(%p: [uin=%u, async=%d, ...]);\n", p, p->uin, p->async); - - if (!(sess = malloc(sizeof(struct gg_session)))) { - gg_debug(GG_DEBUG_MISC, "// gg_login() not enough memory for session data\n"); - goto fail; - } - - memset(sess, 0, sizeof(struct gg_session)); - - if (!p->password || !p->uin) { - gg_debug(GG_DEBUG_MISC, "// gg_login() invalid arguments. uin and password needed\n"); - errno = EFAULT; - goto fail; - } - - if (!(sess->password = strdup(p->password))) { - gg_debug(GG_DEBUG_MISC, "// gg_login() not enough memory for password\n"); - goto fail; - } - - if (p->status_descr && !(sess->initial_descr = strdup(p->status_descr))) { - gg_debug(GG_DEBUG_MISC, "// gg_login() not enough memory for status\n"); - goto fail; - } - - sess->uin = p->uin; - sess->state = GG_STATE_RESOLVING; - sess->check = GG_CHECK_READ; - sess->timeout = GG_DEFAULT_TIMEOUT; - sess->async = p->async; - sess->type = GG_SESSION_GG; - sess->initial_status = p->status; - sess->callback = gg_session_callback; - sess->destroy = gg_free_session; - sess->port = (p->server_port) ? p->server_port : ((gg_proxy_enabled) ? GG_HTTPS_PORT : GG_DEFAULT_PORT); - sess->server_addr = p->server_addr; - sess->external_port = p->external_port; - sess->external_addr = p->external_addr; - sess->protocol_version = (p->protocol_version) ? p->protocol_version : GG_DEFAULT_PROTOCOL_VERSION; - if (p->era_omnix) - sess->protocol_version |= GG_ERA_OMNIX_MASK; - if (p->has_audio) - sess->protocol_version |= GG_HAS_AUDIO_MASK; - sess->client_version = (p->client_version) ? strdup(p->client_version) : NULL; - sess->last_sysmsg = p->last_sysmsg; - sess->image_size = p->image_size; - sess->pid = -1; - - if (p->tls == 1) { -#ifdef __GG_LIBGADU_HAVE_OPENSSL - char buf[1024]; - - OpenSSL_add_ssl_algorithms(); - - if (!RAND_status()) { - char rdata[1024]; - struct { - time_t time; - void *ptr; - } rstruct; - - time(&rstruct.time); - rstruct.ptr = (void *) &rstruct; - - RAND_seed((void *) rdata, sizeof(rdata)); - RAND_seed((void *) &rstruct, sizeof(rstruct)); - } - - sess->ssl_ctx = SSL_CTX_new(TLSv1_client_method()); - - if (!sess->ssl_ctx) { - ERR_error_string_n(ERR_get_error(), buf, sizeof(buf)); - gg_debug(GG_DEBUG_MISC, "// gg_login() SSL_CTX_new() failed: %s\n", buf); - goto fail; - } - - SSL_CTX_set_verify(sess->ssl_ctx, SSL_VERIFY_NONE, NULL); - - sess->ssl = SSL_new(sess->ssl_ctx); - - if (!sess->ssl) { - ERR_error_string_n(ERR_get_error(), buf, sizeof(buf)); - gg_debug(GG_DEBUG_MISC, "// gg_login() SSL_new() failed: %s\n", buf); - goto fail; - } -#else - gg_debug(GG_DEBUG_MISC, "// gg_login() client requested TLS but no support compiled in\n"); -#endif - } - - if (gg_proxy_enabled) { - hostname = gg_proxy_host; - sess->proxy_port = port = gg_proxy_port; - } else { - hostname = GG_APPMSG_HOST; - port = GG_APPMSG_PORT; - } - - if (!p->async) { - struct in_addr a; - - if (!p->server_addr || !p->server_port) { - if ((a.s_addr = inet_addr(hostname)) == INADDR_NONE) { - struct in_addr *hn; - - if (!(hn = gg_gethostbyname(hostname))) { - gg_debug(GG_DEBUG_MISC, "// gg_login() host \"%s\" not found\n", hostname); - goto fail; - } else { - a.s_addr = hn->s_addr; - free(hn); - } - } - } else { - a.s_addr = p->server_addr; - port = p->server_port; - } - - sess->hub_addr = a.s_addr; - - if (gg_proxy_enabled) - sess->proxy_addr = a.s_addr; - - if ((sess->fd = gg_connect(&a, port, 0)) == -1) { - gg_debug(GG_DEBUG_MISC, "// gg_login() connection failed (errno=%d, %s)\n", errno, strerror(errno)); - goto fail; - } - - if (p->server_addr && p->server_port) - sess->state = GG_STATE_CONNECTING_GG; - else - sess->state = GG_STATE_CONNECTING_HUB; - - while (sess->state != GG_STATE_CONNECTED) { - struct gg_event *e; - - if (!(e = gg_watch_fd(sess))) { - gg_debug(GG_DEBUG_MISC, "// gg_login() critical error in gg_watch_fd()\n"); - goto fail; - } - - if (e->type == GG_EVENT_CONN_FAILED) { - errno = EACCES; - gg_debug(GG_DEBUG_MISC, "// gg_login() could not login\n"); - gg_event_free(e); - goto fail; - } - - gg_event_free(e); - } - - return sess; - } - - if (!sess->server_addr || gg_proxy_enabled) { -#ifndef __GG_LIBGADU_HAVE_PTHREAD - if (gg_resolve(&sess->fd, &sess->pid, hostname)) { -#else - if (gg_resolve_pthread(&sess->fd, &sess->resolver, hostname)) { -#endif - gg_debug(GG_DEBUG_MISC, "// gg_login() resolving failed (errno=%d, %s)\n", errno, strerror(errno)); - goto fail; - } - } else { - if ((sess->fd = gg_connect(&sess->server_addr, sess->port, sess->async)) == -1) { - gg_debug(GG_DEBUG_MISC, "// gg_login() direct connection failed (errno=%d, %s)\n", errno, strerror(errno)); - goto fail; - } - sess->state = GG_STATE_CONNECTING_GG; - sess->check = GG_CHECK_WRITE; - } - - return sess; - -fail: - if (sess) { - if (sess->password) - free(sess->password); - if (sess->initial_descr) - free(sess->initial_descr); - free(sess); - } - - return NULL; -} - -/* - * gg_free_session() - * - * próbuje zamkn±æ po³±czenia i zwalnia pamiêæ zajmowan± przez sesjê. - * - * - sess - opis sesji - */ -void gg_free_session(struct gg_session *sess) -{ - if (!sess) - return; - - /* XXX dopisaæ zwalnianie i zamykanie wszystkiego, co mog³o zostaæ */ - - if (sess->password) - free(sess->password); - - if (sess->initial_descr) - free(sess->initial_descr); - - if (sess->client_version) - free(sess->client_version); - - if (sess->header_buf) - free(sess->header_buf); - -#ifdef __GG_LIBGADU_HAVE_OPENSSL - if (sess->ssl) - SSL_free(sess->ssl); - - if (sess->ssl_ctx) - SSL_CTX_free(sess->ssl_ctx); -#endif - -#ifdef __GG_LIBGADU_HAVE_PTHREAD - if (sess->resolver) { - pthread_cancel(*((pthread_t*) sess->resolver)); - free(sess->resolver); - sess->resolver = NULL; - } -#else - if (sess->pid != -1) { - kill(sess->pid, SIGTERM); - waitpid(sess->pid, NULL, WNOHANG); - } -#endif - - if (sess->fd != -1) - close(sess->fd); - - while (sess->images) - gg_image_queue_remove(sess, sess->images, 1); - - free(sess); -} - -/* - * gg_change_status() - * - * zmienia status u¿ytkownika. przydatne do /away i /busy oraz /quit. - * - * - sess - opis sesji - * - status - nowy status u¿ytkownika - * - * 0, -1. - */ -int gg_change_status(struct gg_session *sess, int status) -{ - struct gg_new_status p; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_change_status(%p, %d);\n", sess, status); - - if (!sess) { - errno = EFAULT; - return -1; - } - - if (sess->state != GG_STATE_CONNECTED) { - errno = ENOTCONN; - return -1; - } - - p.status = gg_fix32(status); - - sess->status = status; - - return gg_send_packet(sess, GG_NEW_STATUS, &p, sizeof(p), NULL); -} - -/* - * gg_change_status_descr() - * - * zmienia status u¿ytkownika na opisowy. - * - * - sess - opis sesji - * - status - nowy status u¿ytkownika - * - descr - opis statusu - * - * 0, -1. - */ -int gg_change_status_descr(struct gg_session *sess, int status, const char *descr) -{ - struct gg_new_status p; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_change_status_descr(%p, %d, \"%s\");\n", sess, status, descr); - - if (!sess || !descr) { - errno = EFAULT; - return -1; - } - - if (sess->state != GG_STATE_CONNECTED) { - errno = ENOTCONN; - return -1; - } - - p.status = gg_fix32(status); - - sess->status = status; - - return gg_send_packet(sess, GG_NEW_STATUS, &p, sizeof(p), descr, (strlen(descr) > GG_STATUS_DESCR_MAXSIZE) ? GG_STATUS_DESCR_MAXSIZE : strlen(descr), NULL); -} - -/* - * gg_change_status_descr_time() - * - * zmienia status u¿ytkownika na opisowy z godzin± powrotu. - * - * - sess - opis sesji - * - status - nowy status u¿ytkownika - * - descr - opis statusu - * - time - czas w formacie uniksowym - * - * 0, -1. - */ -int gg_change_status_descr_time(struct gg_session *sess, int status, const char *descr, int time) -{ - struct gg_new_status p; - uint32_t newtime; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_change_status_descr_time(%p, %d, \"%s\", %d);\n", sess, status, descr, time); - - if (!sess || !descr || !time) { - errno = EFAULT; - return -1; - } - - if (sess->state != GG_STATE_CONNECTED) { - errno = ENOTCONN; - return -1; - } - - p.status = gg_fix32(status); - - sess->status = status; - - newtime = gg_fix32(time); - - return gg_send_packet(sess, GG_NEW_STATUS, &p, sizeof(p), descr, (strlen(descr) > GG_STATUS_DESCR_MAXSIZE) ? GG_STATUS_DESCR_MAXSIZE : strlen(descr), &newtime, sizeof(newtime), NULL); -} - -/* - * gg_logoff() - * - * wylogowuje u¿ytkownika i zamyka po³±czenie, ale nie zwalnia pamiêci. - * - * - sess - opis sesji - */ -void gg_logoff(struct gg_session *sess) -{ - if (!sess) - return; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_logoff(%p);\n", sess); - - if (GG_S_NA(sess->status & ~GG_STATUS_FRIENDS_MASK)) - gg_change_status(sess, GG_STATUS_NOT_AVAIL); - -#ifdef __GG_LIBGADU_HAVE_OPENSSL - if (sess->ssl) - SSL_shutdown(sess->ssl); -#endif - -#ifdef __GG_LIBGADU_HAVE_PTHREAD - if (sess->resolver) { - pthread_cancel(*((pthread_t*) sess->resolver)); - free(sess->resolver); - sess->resolver = NULL; - } -#else - if (sess->pid != -1) { - kill(sess->pid, SIGTERM); - waitpid(sess->pid, NULL, WNOHANG); - sess->pid = -1; - } -#endif - - if (sess->fd != -1) { - shutdown(sess->fd, SHUT_RDWR); - close(sess->fd); - sess->fd = -1; - } -} - -/* - * gg_image_request() - * - * wysy³a ¿±danie wys³ania obrazka o podanych parametrach. - * - * - sess - opis sesji - * - recipient - numer adresata - * - size - rozmiar obrazka - * - crc32 - suma kontrolna obrazka - * - * 0/-1 - */ -int gg_image_request(struct gg_session *sess, uin_t recipient, int size, uint32_t crc32) -{ - struct gg_send_msg s; - struct gg_msg_image_request r; - char dummy = 0; - int res; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_image_request(%p, %d, %u, 0x%.4x);\n", sess, recipient, size, crc32); - - if (!sess) { - errno = EFAULT; - return -1; - } - - if (sess->state != GG_STATE_CONNECTED) { - errno = ENOTCONN; - return -1; - } - - if (size < 0) { - errno = EINVAL; - return -1; - } - - s.recipient = gg_fix32(recipient); - s.seq = gg_fix32(0); - s.msgclass = gg_fix32(GG_CLASS_MSG); - - r.flag = 0x04; - r.size = gg_fix32(size); - r.crc32 = gg_fix32(crc32); - - res = gg_send_packet(sess, GG_SEND_MSG, &s, sizeof(s), &dummy, 1, &r, sizeof(r), NULL); - - if (!res) { - struct gg_image_queue *q = malloc(sizeof(*q)); - char *buf; - - if (!q) { - gg_debug(GG_DEBUG_MISC, "// gg_image_request() not enough memory for image queue\n"); - return -1; - } - - buf = malloc(size); - if (size && !buf) - { - gg_debug(GG_DEBUG_MISC, "// gg_image_request() not enough memory for image\n"); - free(q); - return -1; - } - - memset(q, 0, sizeof(*q)); - - q->sender = recipient; - q->size = size; - q->crc32 = crc32; - q->image = buf; - - if (!sess->images) - sess->images = q; - else { - struct gg_image_queue *qq; - - for (qq = sess->images; qq->next; qq = qq->next) - ; - - qq->next = q; - } - } - - return res; -} - -/* - * gg_image_reply() - * - * wysy³a ¿±dany obrazek. - * - * - sess - opis sesji - * - recipient - numer adresata - * - filename - nazwa pliku - * - image - bufor z obrazkiem - * - size - rozmiar obrazka - * - * 0/-1 - */ -int gg_image_reply(struct gg_session *sess, uin_t recipient, const char *filename, const char *image, int size) -{ - struct gg_msg_image_reply *r; - struct gg_send_msg s; - const char *tmp; - char buf[1910]; - int res = -1; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_image_reply(%p, %d, \"%s\", %p, %d);\n", sess, recipient, filename, image, size); - - if (!sess || !filename || !image) { - errno = EFAULT; - return -1; - } - - if (sess->state != GG_STATE_CONNECTED) { - errno = ENOTCONN; - return -1; - } - - if (size < 0) { - errno = EINVAL; - return -1; - } - - /* wytnij ¶cie¿ki, zostaw tylko nazwê pliku */ - while ((tmp = strrchr(filename, '/')) || (tmp = strrchr(filename, '\\'))) - filename = tmp + 1; - - if (strlen(filename) < 1 || strlen(filename) > 1024) { - errno = EINVAL; - return -1; - } - - s.recipient = gg_fix32(recipient); - s.seq = gg_fix32(0); - s.msgclass = gg_fix32(GG_CLASS_MSG); - - buf[0] = 0; - r = (void*) &buf[1]; - - r->flag = 0x05; - r->size = gg_fix32(size); - r->crc32 = gg_fix32(gg_crc32(0, image, size)); - - while (size > 0) { - int buflen, chunklen; - - /* \0 + struct gg_msg_image_reply */ - buflen = sizeof(struct gg_msg_image_reply) + 1; - - /* w pierwszym kawa³ku jest nazwa pliku */ - if (r->flag == 0x05) { - strcpy(buf + buflen, filename); - buflen += strlen(filename) + 1; - } - - chunklen = (size >= sizeof(buf) - buflen) ? (sizeof(buf) - buflen) : size; - - memcpy(buf + buflen, image, chunklen); - size -= chunklen; - image += chunklen; - - res = gg_send_packet(sess, GG_SEND_MSG, &s, sizeof(s), buf, buflen + chunklen, NULL); - - if (res == -1) - break; - - r->flag = 0x06; - } - - return res; -} - -/* - * gg_send_message_ctcp() - * - * wysy³a wiadomo¶æ do innego u¿ytkownika. zwraca losowy numer - * sekwencyjny, który mo¿na zignorowaæ albo wykorzystaæ do potwierdzenia. - * - * - sess - opis sesji - * - msgclass - rodzaj wiadomo¶ci - * - recipient - numer adresata - * - message - tre¶æ wiadomo¶ci - * - message_len - d³ugo¶æ - * - * numer sekwencyjny wiadomo¶ci lub -1 w przypadku b³êdu. - */ -int gg_send_message_ctcp(struct gg_session *sess, int msgclass, uin_t recipient, const unsigned char *message, int message_len) -{ - struct gg_send_msg s; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_send_message_ctcp(%p, %d, %u, ...);\n", sess, msgclass, recipient); - - if (!sess) { - errno = EFAULT; - return -1; - } - - if (sess->state != GG_STATE_CONNECTED) { - errno = ENOTCONN; - return -1; - } - - s.recipient = gg_fix32(recipient); - s.seq = gg_fix32(0); - s.msgclass = gg_fix32(msgclass); - - return gg_send_packet(sess, GG_SEND_MSG, &s, sizeof(s), message, message_len, NULL); -} - -/* - * gg_send_message() - * - * wysy³a wiadomo¶æ do innego u¿ytkownika. zwraca losowy numer - * sekwencyjny, który mo¿na zignorowaæ albo wykorzystaæ do potwierdzenia. - * - * - sess - opis sesji - * - msgclass - rodzaj wiadomo¶ci - * - recipient - numer adresata - * - message - tre¶æ wiadomo¶ci - * - * numer sekwencyjny wiadomo¶ci lub -1 w przypadku b³êdu. - */ -int gg_send_message(struct gg_session *sess, int msgclass, uin_t recipient, const unsigned char *message) -{ - gg_debug(GG_DEBUG_FUNCTION, "** gg_send_message(%p, %d, %u, %p)\n", sess, msgclass, recipient, message); - - return gg_send_message_richtext(sess, msgclass, recipient, message, NULL, 0); -} - -/* - * gg_send_message_richtext() - * - * wysy³a kolorow± wiadomo¶æ do innego u¿ytkownika. zwraca losowy numer - * sekwencyjny, który mo¿na zignorowaæ albo wykorzystaæ do potwierdzenia. - * - * - sess - opis sesji - * - msgclass - rodzaj wiadomo¶ci - * - recipient - numer adresata - * - message - tre¶æ wiadomo¶ci - * - format - informacje o formatowaniu - * - formatlen - d³ugo¶æ informacji o formatowaniu - * - * numer sekwencyjny wiadomo¶ci lub -1 w przypadku b³êdu. - */ -int gg_send_message_richtext(struct gg_session *sess, int msgclass, uin_t recipient, const unsigned char *message, const unsigned char *format, int formatlen) -{ - struct gg_send_msg s; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_send_message_richtext(%p, %d, %u, %p, %p, %d);\n", sess, msgclass, recipient, message, format, formatlen); - - if (!sess) { - errno = EFAULT; - return -1; - } - - if (sess->state != GG_STATE_CONNECTED) { - errno = ENOTCONN; - return -1; - } - - if (!message) { - errno = EFAULT; - return -1; - } - - s.recipient = gg_fix32(recipient); - if (!sess->seq) - sess->seq = 0x01740000 | (rand() & 0xffff); - s.seq = gg_fix32(sess->seq); - s.msgclass = gg_fix32(msgclass); - sess->seq += (rand() % 0x300) + 0x300; - - if (gg_send_packet(sess, GG_SEND_MSG, &s, sizeof(s), message, strlen(message) + 1, format, formatlen, NULL) == -1) - return -1; - - return gg_fix32(s.seq); -} - -/* - * gg_send_message_confer() - * - * wysy³a wiadomo¶æ do kilku u¿ytkownikow (konferencja). zwraca losowy numer - * sekwencyjny, który mo¿na zignorowaæ albo wykorzystaæ do potwierdzenia. - * - * - sess - opis sesji - * - msgclass - rodzaj wiadomo¶ci - * - recipients_count - ilo¶æ adresatów - * - recipients - numerki adresatów - * - message - tre¶æ wiadomo¶ci - * - * numer sekwencyjny wiadomo¶ci lub -1 w przypadku b³êdu. - */ -int gg_send_message_confer(struct gg_session *sess, int msgclass, int recipients_count, uin_t *recipients, const unsigned char *message) -{ - gg_debug(GG_DEBUG_FUNCTION, "** gg_send_message_confer(%p, %d, %d, %p, %p);\n", sess, msgclass, recipients_count, recipients, message); - - return gg_send_message_confer_richtext(sess, msgclass, recipients_count, recipients, message, NULL, 0); -} - -/* - * gg_send_message_confer_richtext() - * - * wysy³a kolorow± wiadomo¶æ do kilku u¿ytkownikow (konferencja). zwraca - * losowy numer sekwencyjny, który mo¿na zignorowaæ albo wykorzystaæ do - * potwierdzenia. - * - * - sess - opis sesji - * - msgclass - rodzaj wiadomo¶ci - * - recipients_count - ilo¶æ adresatów - * - recipients - numerki adresatów - * - message - tre¶æ wiadomo¶ci - * - format - informacje o formatowaniu - * - formatlen - d³ugo¶æ informacji o formatowaniu - * - * numer sekwencyjny wiadomo¶ci lub -1 w przypadku b³êdu. - */ -int gg_send_message_confer_richtext(struct gg_session *sess, int msgclass, int recipients_count, uin_t *recipients, const unsigned char *message, const unsigned char *format, int formatlen) -{ - struct gg_send_msg s; - struct gg_msg_recipients r; - int i, j, k; - uin_t *recps; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_send_message_confer_richtext(%p, %d, %d, %p, %p, %p, %d);\n", sess, msgclass, recipients_count, recipients, message, format, formatlen); - - if (!sess) { - errno = EFAULT; - return -1; - } - - if (sess->state != GG_STATE_CONNECTED) { - errno = ENOTCONN; - return -1; - } - - if (!message || recipients_count <= 0 || recipients_count > 0xffff || !recipients) { - errno = EINVAL; - return -1; - } - - r.flag = 0x01; - r.count = gg_fix32(recipients_count - 1); - - if (!sess->seq) - sess->seq = 0x01740000 | (rand() & 0xffff); - s.seq = gg_fix32(sess->seq); - s.msgclass = gg_fix32(msgclass); - - recps = malloc(sizeof(uin_t) * recipients_count); - if (!recps) - return -1; - - for (i = 0; i < recipients_count; i++) { - - s.recipient = gg_fix32(recipients[i]); - - for (j = 0, k = 0; j < recipients_count; j++) - if (recipients[j] != recipients[i]) { - recps[k] = gg_fix32(recipients[j]); - k++; - } - - if (!i) - sess->seq += (rand() % 0x300) + 0x300; - - if (gg_send_packet(sess, GG_SEND_MSG, &s, sizeof(s), message, strlen(message) + 1, &r, sizeof(r), recps, (recipients_count - 1) * sizeof(uin_t), format, formatlen, NULL) == -1) { - free(recps); - return -1; - } - } - - free(recps); - - return gg_fix32(s.seq); -} - -/* - * gg_ping() - * - * wysy³a do serwera pakiet ping. - * - * - sess - opis sesji - * - * 0, -1. - */ -int gg_ping(struct gg_session *sess) -{ - gg_debug(GG_DEBUG_FUNCTION, "** gg_ping(%p);\n", sess); - - if (!sess) { - errno = EFAULT; - return -1; - } - - if (sess->state != GG_STATE_CONNECTED) { - errno = ENOTCONN; - return -1; - } - - return gg_send_packet(sess, GG_PING, NULL); -} - -/* - * gg_notify_ex() - * - * wysy³a serwerowi listê kontaktów (wraz z odpowiadaj±cymi im typami userów), - * dziêki czemu wie, czyj stan nas interesuje. - * - * - sess - opis sesji - * - userlist - wska¼nik do tablicy numerów - * - types - wska¼nik do tablicy typów u¿ytkowników - * - count - ilo¶æ numerków - * - * 0, -1. - */ -int gg_notify_ex(struct gg_session *sess, uin_t *userlist, char *types, int count) -{ - struct gg_notify *n; - uin_t *u; - char *t; - int i, res = 0; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_notify_ex(%p, %p, %p, %d);\n", sess, userlist, types, count); - - if (!sess) { - errno = EFAULT; - return -1; - } - - if (sess->state != GG_STATE_CONNECTED) { - errno = ENOTCONN; - return -1; - } - - if (!userlist || !count) - return gg_send_packet(sess, GG_LIST_EMPTY, NULL); - - while (count > 0) { - int part_count, packet_type; - - if (count > 400) { - part_count = 400; - packet_type = GG_NOTIFY_FIRST; - } else { - part_count = count; - packet_type = GG_NOTIFY_LAST; - } - - if (!(n = (struct gg_notify*) malloc(sizeof(*n) * part_count))) - return -1; - - for (u = userlist, t = types, i = 0; i < part_count; u++, t++, i++) { - n[i].uin = gg_fix32(*u); - n[i].dunno1 = *t; - } - - if (gg_send_packet(sess, packet_type, n, sizeof(*n) * part_count, NULL) == -1) { - free(n); - res = -1; - break; - } - - count -= part_count; - userlist += part_count; - types += part_count; - - free(n); - } - - return res; -} - -/* - * gg_notify() - * - * wysy³a serwerowi listê kontaktów, dziêki czemu wie, czyj stan nas - * interesuje. - * - * - sess - opis sesji - * - userlist - wska¼nik do tablicy numerów - * - count - ilo¶æ numerków - * - * 0, -1. - */ -int gg_notify(struct gg_session *sess, uin_t *userlist, int count) -{ - struct gg_notify *n; - uin_t *u; - int i, res = 0; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_notify(%p, %p, %d);\n", sess, userlist, count); - - if (!sess) { - errno = EFAULT; - return -1; - } - - if (sess->state != GG_STATE_CONNECTED) { - errno = ENOTCONN; - return -1; - } - - if (!userlist || !count) - return gg_send_packet(sess, GG_LIST_EMPTY, NULL); - - while (count > 0) { - int part_count, packet_type; - - if (count > 400) { - part_count = 400; - packet_type = GG_NOTIFY_FIRST; - } else { - part_count = count; - packet_type = GG_NOTIFY_LAST; - } - - if (!(n = (struct gg_notify*) malloc(sizeof(*n) * part_count))) - return -1; - - for (u = userlist, i = 0; i < part_count; u++, i++) { - n[i].uin = gg_fix32(*u); - n[i].dunno1 = GG_USER_NORMAL; - } - - if (gg_send_packet(sess, packet_type, n, sizeof(*n) * part_count, NULL) == -1) { - res = -1; - free(n); - break; - } - - free(n); - - userlist += part_count; - count -= part_count; - } - - return res; -} - -/* - * gg_add_notify_ex() - * - * dodaje do listy kontaktów dany numer w trakcie po³±czenia. - * dodawanemu u¿ytkownikowi okre¶lamy jego typ (patrz protocol.html) - * - * - sess - opis sesji - * - uin - numer - * - type - typ - * - * 0, -1. - */ -int gg_add_notify_ex(struct gg_session *sess, uin_t uin, char type) -{ - struct gg_add_remove a; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_add_notify_ex(%p, %u, %d);\n", sess, uin, type); - - if (!sess) { - errno = EFAULT; - return -1; - } - - if (sess->state != GG_STATE_CONNECTED) { - errno = ENOTCONN; - return -1; - } - - a.uin = gg_fix32(uin); - a.dunno1 = type; - - return gg_send_packet(sess, GG_ADD_NOTIFY, &a, sizeof(a), NULL); -} - -/* - * gg_add_notify() - * - * dodaje do listy kontaktów dany numer w trakcie po³±czenia. - * - * - sess - opis sesji - * - uin - numer - * - * 0, -1. - */ -int gg_add_notify(struct gg_session *sess, uin_t uin) -{ - return gg_add_notify_ex(sess, uin, GG_USER_NORMAL); -} - -/* - * gg_remove_notify_ex() - * - * usuwa z listy kontaktów w trakcie po³±czenia. - * usuwanemu u¿ytkownikowi okre¶lamy jego typ (patrz protocol.html) - * - * - sess - opis sesji - * - uin - numer - * - type - typ - * - * 0, -1. - */ -int gg_remove_notify_ex(struct gg_session *sess, uin_t uin, char type) -{ - struct gg_add_remove a; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_remove_notify_ex(%p, %u, %d);\n", sess, uin, type); - - if (!sess) { - errno = EFAULT; - return -1; - } - - if (sess->state != GG_STATE_CONNECTED) { - errno = ENOTCONN; - return -1; - } - - a.uin = gg_fix32(uin); - a.dunno1 = type; - - return gg_send_packet(sess, GG_REMOVE_NOTIFY, &a, sizeof(a), NULL); -} - -/* - * gg_remove_notify() - * - * usuwa z listy kontaktów w trakcie po³±czenia. - * - * - sess - opis sesji - * - uin - numer - * - * 0, -1. - */ -int gg_remove_notify(struct gg_session *sess, uin_t uin) -{ - return gg_remove_notify_ex(sess, uin, GG_USER_NORMAL); -} - -/* - * gg_userlist_request() - * - * wysy³a ¿±danie/zapytanie listy kontaktów na serwerze. - * - * - sess - opis sesji - * - type - rodzaj zapytania/¿±dania - * - request - tre¶æ zapytania/¿±dania (mo¿e byæ NULL) - * - * 0, -1 - */ -int gg_userlist_request(struct gg_session *sess, char type, const char *request) -{ - int len; - - if (!sess) { - errno = EFAULT; - return -1; - } - - if (sess->state != GG_STATE_CONNECTED) { - errno = ENOTCONN; - return -1; - } - - if (!request) { - sess->userlist_blocks = 1; - return gg_send_packet(sess, GG_USERLIST_REQUEST, &type, sizeof(type), NULL); - } - - len = strlen(request); - - sess->userlist_blocks = 0; - - while (len > 2047) { - sess->userlist_blocks++; - - if (gg_send_packet(sess, GG_USERLIST_REQUEST, &type, sizeof(type), request, 2047, NULL) == -1) - return -1; - - if (type == GG_USERLIST_PUT) - type = GG_USERLIST_PUT_MORE; - - request += 2047; - len -= 2047; - } - - sess->userlist_blocks++; - - return gg_send_packet(sess, GG_USERLIST_REQUEST, &type, sizeof(type), request, len, NULL); -} - -/* - * Local variables: - * c-indentation-style: k&r - * c-basic-offset: 8 - * indent-tabs-mode: notnil - * End: - * - * vim: shiftwidth=8: - */ diff --git a/kopete/protocols/gadu/libgadu/libgadu.h b/kopete/protocols/gadu/libgadu/libgadu.h deleted file mode 100644 index 85c54953..00000000 --- a/kopete/protocols/gadu/libgadu/libgadu.h +++ /dev/null @@ -1,1310 +0,0 @@ -/* $Id$ */ - -/* - * (C) Copyright 2001-2003 Wojtek Kaniewski <wojtekka@irc.pl> - * Robert J. Wo¼ny <speedy@ziew.org> - * Arkadiusz Mi¶kiewicz <arekm@pld-linux.org> - * Tomasz Chiliñski <chilek@chilan.com> - * Piotr Wysocki <wysek@linux.bydg.org> - * Dawid Jarosz <dawjar@poczta.onet.pl> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License Version - * 2.1 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA. - */ - -#ifndef __GG_LIBGADU_H -#define __GG_LIBGADU_H - -#ifdef __cplusplus -#ifdef _WIN32 -#pragma pack(push, 1) -#endif -extern "C" { -#endif - -#include <libgadu-config.h> -#include <sys/types.h> -#include <stdio.h> -#include <stdarg.h> - -#ifdef __GG_LIBGADU_HAVE_OPENSSL -#include <openssl/ssl.h> -#endif - -/* - * typedef uin_t - * - * typ reprezentuj±cy numer osoby. - */ -typedef uint32_t uin_t; - -/* - * ogólna struktura opisuj±ca ró¿ne sesje. przydatna w klientach. - */ -#define gg_common_head(x) \ - int fd; /* podgl±dany deskryptor */ \ - int check; /* sprawdzamy zapis czy odczyt */ \ - int state; /* aktualny stan maszynki */ \ - int error; /* kod b³êdu dla GG_STATE_ERROR */ \ - int type; /* rodzaj sesji */ \ - int id; /* identyfikator */ \ - int timeout; /* sugerowany timeout w sekundach */ \ - int (*callback)(x*); /* callback przy zmianach */ \ - void (*destroy)(x*); /* funkcja niszczenia */ - -struct gg_common { - gg_common_head(struct gg_common) -}; - -struct gg_image_queue; - -/* - * struct gg_session - * - * struktura opisuj±ca dan± sesjê. tworzona przez gg_login(), zwalniana - * przez gg_free_session(). - */ -struct gg_session { - gg_common_head(struct gg_session) - - int async; /* czy po³±czenie jest asynchroniczne */ - int pid; /* pid procesu resolvera */ - int port; /* port, z którym siê ³±czymy */ - int seq; /* numer sekwencyjny ostatniej wiadomo¶ci */ - int last_pong; /* czas otrzymania ostatniego ping/pong */ - int last_event; /* czas otrzymania ostatniego pakietu */ - - struct gg_event *event; /* zdarzenie po ->callback() */ - - uint32_t proxy_addr; /* adres proxy, keszowany */ - uint16_t proxy_port; /* port proxy */ - - uint32_t hub_addr; /* adres huba po resolvniêciu */ - uint32_t server_addr; /* adres serwera, od huba */ - - uint32_t client_addr; /* adres klienta */ - uint16_t client_port; /* port, na którym klient s³ucha */ - - uint32_t external_addr; /* adres zewnetrzny klienta */ - uint16_t external_port; /* port zewnetrzny klienta */ - - uin_t uin; /* numerek klienta */ - char *password; /* i jego has³o. zwalniane automagicznie */ - - int initial_status; /* pocz±tkowy stan klienta */ - int status; /* aktualny stan klienta */ - - char *recv_buf; /* bufor na otrzymywane pakiety */ - int recv_done; /* ile ju¿ wczytano do bufora */ - int recv_left; /* i ile jeszcze trzeba wczytaæ */ - - int protocol_version; /* wersja u¿ywanego protoko³u */ - char *client_version; /* wersja u¿ywanego klienta */ - int last_sysmsg; /* ostatnia wiadomo¶æ systemowa */ - - char *initial_descr; /* pocz±tkowy opis stanu klienta */ - - void *resolver; /* wska¼nik na informacje resolvera */ - - char *header_buf; /* bufor na pocz±tek nag³ówka */ - unsigned int header_done;/* ile ju¿ mamy */ - -#ifdef __GG_LIBGADU_HAVE_OPENSSL - SSL *ssl; /* sesja TLS */ - SSL_CTX *ssl_ctx; /* kontekst sesji? */ -#else - void *ssl; /* zachowujemy ABI */ - void *ssl_ctx; -#endif - - int image_size; /* maksymalny rozmiar obrazków w KiB */ - - char *userlist_reply; /* fragment odpowiedzi listy kontaktów */ - - int userlist_blocks; /* na ile kawa³ków podzielono listê kontaktów */ - - struct gg_image_queue *images; /* aktualnie wczytywane obrazki */ -}; - -/* - * struct gg_http - * - * ogólna struktura opisuj±ca stan wszystkich operacji HTTP. tworzona - * przez gg_http_connect(), zwalniana przez gg_http_free(). - */ -struct gg_http { - gg_common_head(struct gg_http) - - int async; /* czy po³±czenie asynchroniczne */ - int pid; /* pid procesu resolvera */ - int port; /* port, z którym siê ³±czymy */ - - char *query; /* bufor zapytania http */ - char *header; /* bufor nag³ówka */ - int header_size; /* rozmiar wczytanego nag³ówka */ - char *body; /* bufor otrzymanych informacji */ - unsigned int body_size; /* oczekiwana ilo¶æ informacji */ - - void *data; /* dane danej operacji http */ - - char *user_data; /* dane u¿ytkownika, nie s± zwalniane przez gg_http_free() */ - - void *resolver; /* wska¼nik na informacje resolvera */ - - unsigned int body_done; /* ile ju¿ tre¶ci odebrano? */ -}; - -#ifdef __GNUC__ -#define GG_PACKED __attribute__ ((packed)) -#else -#define GG_PACKED -#endif - -#define GG_MAX_PATH 276 - -/* - * struct gg_file_info - * - * odpowiednik windowsowej struktury WIN32_FIND_DATA niezbêdnej przy - * wysy³aniu plików. - */ -struct gg_file_info { - uint32_t mode; /* dwFileAttributes */ - uint32_t ctime[2]; /* ftCreationTime */ - uint32_t atime[2]; /* ftLastAccessTime */ - uint32_t mtime[2]; /* ftLastWriteTime */ - uint32_t size_hi; /* nFileSizeHigh */ - uint32_t size; /* nFileSizeLow */ - uint32_t reserved0; /* dwReserved0 */ - uint32_t reserved1; /* dwReserved1 */ - unsigned char filename[GG_MAX_PATH - 14]; /* cFileName */ - unsigned char short_filename[14]; /* cAlternateFileName */ -} GG_PACKED; - -/* - * struct gg_dcc - * - * struktura opisuj±ca nas³uchuj±ce gniazdo po³±czeñ miêdzy klientami. - * tworzona przez gg_dcc_socket_create(), zwalniana przez gg_dcc_free(). - */ -struct gg_dcc { - gg_common_head(struct gg_dcc) - - struct gg_event *event; /* opis zdarzenia */ - - int active; /* czy to my siê ³±czymy? */ - int port; /* port, na którym siedzi */ - uin_t uin; /* uin klienta */ - uin_t peer_uin; /* uin drugiej strony */ - int file_fd; /* deskryptor pliku */ - unsigned int offset; /* offset w pliku */ - unsigned int chunk_size;/* rozmiar kawa³ka */ - unsigned int chunk_offset;/* offset w aktualnym kawa³ku */ - struct gg_file_info file_info; - /* informacje o pliku */ - int established; /* po³±czenie ustanowione */ - char *voice_buf; /* bufor na pakiet po³±czenia g³osowego */ - int incoming; /* po³±czenie przychodz±ce */ - char *chunk_buf; /* bufor na kawa³ek danych */ - uint32_t remote_addr; /* adres drugiej strony */ - uint16_t remote_port; /* port drugiej strony */ -}; - -/* - * enum gg_session_t - * - * rodzaje sesji. - */ -enum gg_session_t { - GG_SESSION_GG = 1, /* po³±czenie z serwerem gg */ - GG_SESSION_HTTP, /* ogólna sesja http */ - GG_SESSION_SEARCH, /* szukanie */ - GG_SESSION_REGISTER, /* rejestrowanie */ - GG_SESSION_REMIND, /* przypominanie has³a */ - GG_SESSION_PASSWD, /* zmiana has³a */ - GG_SESSION_CHANGE, /* zmiana informacji o sobie */ - GG_SESSION_DCC, /* ogólne po³±czenie DCC */ - GG_SESSION_DCC_SOCKET, /* nas³uchuj±cy socket */ - GG_SESSION_DCC_SEND, /* wysy³anie pliku */ - GG_SESSION_DCC_GET, /* odbieranie pliku */ - GG_SESSION_DCC_VOICE, /* rozmowa g³osowa */ - GG_SESSION_USERLIST_GET, /* pobieranie userlisty */ - GG_SESSION_USERLIST_PUT, /* wysy³anie userlisty */ - GG_SESSION_UNREGISTER, /* usuwanie konta */ - GG_SESSION_USERLIST_REMOVE, /* usuwanie userlisty */ - GG_SESSION_TOKEN, /* pobieranie tokenu */ - - GG_SESSION_USER0 = 256, /* zdefiniowana dla u¿ytkownika */ - GG_SESSION_USER1, /* j.w. */ - GG_SESSION_USER2, /* j.w. */ - GG_SESSION_USER3, /* j.w. */ - GG_SESSION_USER4, /* j.w. */ - GG_SESSION_USER5, /* j.w. */ - GG_SESSION_USER6, /* j.w. */ - GG_SESSION_USER7 /* j.w. */ -}; - -/* - * enum gg_state_t - * - * opisuje stan asynchronicznej maszyny. - */ -enum gg_state_t { - /* wspólne */ - GG_STATE_IDLE = 0, /* nie powinno wyst±piæ. */ - GG_STATE_RESOLVING, /* wywo³a³ gethostbyname() */ - GG_STATE_CONNECTING, /* wywo³a³ connect() */ - GG_STATE_READING_DATA, /* czeka na dane http */ - GG_STATE_ERROR, /* wyst±pi³ b³±d. kod w x->error */ - - /* gg_session */ - GG_STATE_CONNECTING_HUB, /* wywo³a³ connect() na huba */ - GG_STATE_CONNECTING_GG, /* wywo³a³ connect() na serwer */ - GG_STATE_READING_KEY, /* czeka na klucz */ - GG_STATE_READING_REPLY, /* czeka na odpowied¼ */ - GG_STATE_CONNECTED, /* po³±czy³ siê */ - - /* gg_http */ - GG_STATE_SENDING_QUERY, /* wysy³a zapytanie http */ - GG_STATE_READING_HEADER, /* czeka na nag³ówek http */ - GG_STATE_PARSING, /* przetwarza dane */ - GG_STATE_DONE, /* skoñczy³ */ - - /* gg_dcc */ - GG_STATE_LISTENING, /* czeka na po³±czenia */ - GG_STATE_READING_UIN_1, /* czeka na uin peera */ - GG_STATE_READING_UIN_2, /* czeka na swój uin */ - GG_STATE_SENDING_ACK, /* wysy³a potwierdzenie dcc */ - GG_STATE_READING_ACK, /* czeka na potwierdzenie dcc */ - GG_STATE_READING_REQUEST, /* czeka na komendê */ - GG_STATE_SENDING_REQUEST, /* wysy³a komendê */ - GG_STATE_SENDING_FILE_INFO, /* wysy³a informacje o pliku */ - GG_STATE_READING_PRE_FILE_INFO, /* czeka na pakiet przed file_info */ - GG_STATE_READING_FILE_INFO, /* czeka na informacje o pliku */ - GG_STATE_SENDING_FILE_ACK, /* wysy³a potwierdzenie pliku */ - GG_STATE_READING_FILE_ACK, /* czeka na potwierdzenie pliku */ - GG_STATE_SENDING_FILE_HEADER, /* wysy³a nag³ówek pliku */ - GG_STATE_READING_FILE_HEADER, /* czeka na nag³ówek */ - GG_STATE_GETTING_FILE, /* odbiera plik */ - GG_STATE_SENDING_FILE, /* wysy³a plik */ - GG_STATE_READING_VOICE_ACK, /* czeka na potwierdzenie voip */ - GG_STATE_READING_VOICE_HEADER, /* czeka na rodzaj bloku voip */ - GG_STATE_READING_VOICE_SIZE, /* czeka na rozmiar bloku voip */ - GG_STATE_READING_VOICE_DATA, /* czeka na dane voip */ - GG_STATE_SENDING_VOICE_ACK, /* wysy³a potwierdzenie voip */ - GG_STATE_SENDING_VOICE_REQUEST, /* wysy³a ¿±danie voip */ - GG_STATE_READING_TYPE, /* czeka na typ po³±czenia */ - - /* nowe. bez sensu jest to API. */ - GG_STATE_TLS_NEGOTIATION /* negocjuje po³±czenie TLS */ -}; - -/* - * enum gg_check_t - * - * informuje, co proces klienta powinien sprawdziæ na deskryptorze danego - * po³±czenia. - */ -enum gg_check_t { - GG_CHECK_NONE = 0, /* nic. nie powinno wyst±piæ */ - GG_CHECK_WRITE = 1, /* sprawdzamy mo¿liwo¶æ zapisu */ - GG_CHECK_READ = 2 /* sprawdzamy mo¿liwo¶æ odczytu */ -}; - -/* - * struct gg_login_params - * - * parametry gg_login(). przeniesiono do struktury, ¿eby unikn±æ problemów - * z ci±g³ymi zmianami API, gdy dodano co¶ nowego do protoko³u. - */ -struct gg_login_params { - uin_t uin; /* numerek */ - char *password; /* has³o */ - int async; /* asynchroniczne sockety? */ - int status; /* pocz±tkowy status klienta */ - char *status_descr; /* opis statusu */ - uint32_t server_addr; /* adres serwera gg */ - uint16_t server_port; /* port serwera gg */ - uint32_t client_addr; /* adres dcc klienta */ - uint16_t client_port; /* port dcc klienta */ - int protocol_version; /* wersja protoko³u */ - char *client_version; /* wersja klienta */ - int has_audio; /* czy ma d¼wiêk? */ - int last_sysmsg; /* ostatnia wiadomo¶æ systemowa */ - uint32_t external_addr; /* adres widziany na zewnatrz */ - uint16_t external_port; /* port widziany na zewnatrz */ - int tls; /* czy ³±czymy po TLS? */ - int image_size; /* maksymalny rozmiar obrazka w KiB */ - int era_omnix; /* czy udawaæ klienta era omnix? */ - - char dummy[6 * sizeof(int)]; /* miejsce na kolejnych 6 zmiennych, - * ¿eby z dodaniem parametru nie - * zmienia³ siê rozmiar struktury */ -}; - -struct gg_session *gg_login(const struct gg_login_params *p); -void gg_free_session(struct gg_session *sess); -void gg_logoff(struct gg_session *sess); -int gg_change_status(struct gg_session *sess, int status); -int gg_change_status_descr(struct gg_session *sess, int status, const char *descr); -int gg_change_status_descr_time(struct gg_session *sess, int status, const char *descr, int time); -int gg_send_message(struct gg_session *sess, int msgclass, uin_t recipient, const unsigned char *message); -int gg_send_message_richtext(struct gg_session *sess, int msgclass, uin_t recipient, const unsigned char *message, const unsigned char *format, int formatlen); -int gg_send_message_confer(struct gg_session *sess, int msgclass, int recipients_count, uin_t *recipients, const unsigned char *message); -int gg_send_message_confer_richtext(struct gg_session *sess, int msgclass, int recipients_count, uin_t *recipients, const unsigned char *message, const unsigned char *format, int formatlen); -int gg_send_message_ctcp(struct gg_session *sess, int msgclass, uin_t recipient, const unsigned char *message, int message_len); -int gg_ping(struct gg_session *sess); -int gg_userlist_request(struct gg_session *sess, char type, const char *request); -int gg_image_request(struct gg_session *sess, uin_t recipient, int size, uint32_t crc32); -int gg_image_reply(struct gg_session *sess, uin_t recipient, const char *filename, const char *image, int size); - -uint32_t gg_crc32(uint32_t crc, const unsigned char *buf, int len); - -struct gg_image_queue { - uin_t sender; /* nadawca obrazka */ - uint32_t size; /* rozmiar */ - uint32_t crc32; /* suma kontrolna */ - char *filename; /* nazwa pliku */ - char *image; /* bufor z obrazem */ - uint32_t done; /* ile ju¿ wczytano */ - - struct gg_image_queue *next; /* nastêpny na li¶cie */ -}; - -/* - * enum gg_event_t - * - * rodzaje zdarzeñ. - */ -enum gg_event_t { - GG_EVENT_NONE = 0, /* nic siê nie wydarzy³o */ - GG_EVENT_MSG, /* otrzymano wiadomo¶æ */ - GG_EVENT_NOTIFY, /* kto¶ siê pojawi³ */ - GG_EVENT_NOTIFY_DESCR, /* kto¶ siê pojawi³ z opisem */ - GG_EVENT_STATUS, /* kto¶ zmieni³ stan */ - GG_EVENT_ACK, /* potwierdzenie wys³ania wiadomo¶ci */ - GG_EVENT_PONG, /* pakiet pong */ - GG_EVENT_CONN_FAILED, /* po³±czenie siê nie uda³o */ - GG_EVENT_CONN_SUCCESS, /* po³±czenie siê powiod³o */ - GG_EVENT_DISCONNECT, /* serwer zrywa po³±czenie */ - - GG_EVENT_DCC_NEW, /* nowe po³±czenie miêdzy klientami */ - GG_EVENT_DCC_ERROR, /* b³±d po³±czenia miêdzy klientami */ - GG_EVENT_DCC_DONE, /* zakoñczono po³±czenie */ - GG_EVENT_DCC_CLIENT_ACCEPT, /* moment akceptacji klienta */ - GG_EVENT_DCC_CALLBACK, /* klient siê po³±czy³ na ¿±danie */ - GG_EVENT_DCC_NEED_FILE_INFO, /* nale¿y wype³niæ file_info */ - GG_EVENT_DCC_NEED_FILE_ACK, /* czeka na potwierdzenie pliku */ - GG_EVENT_DCC_NEED_VOICE_ACK, /* czeka na potwierdzenie rozmowy */ - GG_EVENT_DCC_VOICE_DATA, /* ramka danych rozmowy g³osowej */ - - GG_EVENT_PUBDIR50_SEARCH_REPLY, /* odpowiedz wyszukiwania */ - GG_EVENT_PUBDIR50_READ, /* odczytano w³asne dane z katalogu */ - GG_EVENT_PUBDIR50_WRITE, /* wpisano w³asne dane do katalogu */ - - GG_EVENT_STATUS60, /* kto¶ zmieni³ stan w GG 6.0 */ - GG_EVENT_NOTIFY60, /* kto¶ siê pojawi³ w GG 6.0 */ - GG_EVENT_USERLIST, /* odpowied¼ listy kontaktów w GG 6.0 */ - GG_EVENT_IMAGE_REQUEST, /* pro¶ba o wys³anie obrazka GG 6.0 */ - GG_EVENT_IMAGE_REPLY, /* podes³any obrazek GG 6.0 */ - GG_EVENT_DCC_ACK /* potwierdzenie transmisji */ -}; - -#define GG_EVENT_SEARCH50_REPLY GG_EVENT_PUBDIR50_SEARCH_REPLY - -/* - * enum gg_failure_t - * - * okre¶la powód nieudanego po³±czenia. - */ -enum gg_failure_t { - GG_FAILURE_RESOLVING = 1, /* nie znaleziono serwera */ - GG_FAILURE_CONNECTING, /* nie mo¿na siê po³±czyæ */ - GG_FAILURE_INVALID, /* serwer zwróci³ nieprawid³owe dane */ - GG_FAILURE_READING, /* zerwano po³±czenie podczas odczytu */ - GG_FAILURE_WRITING, /* zerwano po³±czenie podczas zapisu */ - GG_FAILURE_PASSWORD, /* nieprawid³owe has³o */ - GG_FAILURE_404, /* XXX nieu¿ywane */ - GG_FAILURE_TLS, /* b³±d negocjacji TLS */ - GG_FAILURE_NEED_EMAIL, /* serwer roz³±czy³ nas z pro¶b± o zmianê emaila */ - GG_FAILURE_INTRUDER, /* za du¿o prób po³±czenia siê z nieprawid³owym has³em */ - GG_FAILURE_UNAVAILABLE /* serwery s± wy³±czone */ -}; - -/* - * enum gg_error_t - * - * okre¶la rodzaj b³êdu wywo³anego przez dan± operacjê. nie zawiera - * przesadnie szczegó³owych informacji o powodzie b³êdu, by nie komplikowaæ - * obs³ugi b³êdów. je¶li wymagana jest wiêksza dok³adno¶æ, nale¿y sprawdziæ - * zawarto¶æ zmiennej errno. - */ -enum gg_error_t { - GG_ERROR_RESOLVING = 1, /* b³±d znajdowania hosta */ - GG_ERROR_CONNECTING, /* b³±d ³aczenia siê */ - GG_ERROR_READING, /* b³±d odczytu */ - GG_ERROR_WRITING, /* b³±d wysy³ania */ - - GG_ERROR_DCC_HANDSHAKE, /* b³±d negocjacji */ - GG_ERROR_DCC_FILE, /* b³±d odczytu/zapisu pliku */ - GG_ERROR_DCC_EOF, /* plik siê skoñczy³? */ - GG_ERROR_DCC_NET, /* b³±d wysy³ania/odbierania */ - GG_ERROR_DCC_REFUSED /* po³±czenie odrzucone przez usera */ -}; - -/* - * struktury dotycz±ce wyszukiwania w GG 5.0. NIE NALE¯Y SIÊ DO NICH - * ODWO£YWAÆ BEZPO¦REDNIO! do dostêpu do nich s³u¿± funkcje gg_pubdir50_*() - */ -struct gg_pubdir50_entry { - int num; - char *field; - char *value; -}; - -struct gg_pubdir50_s { - int count; - uin_t next; - int type; - uint32_t seq; - struct gg_pubdir50_entry *entries; - int entries_count; -}; - -/* - * typedef gg_pubdir_50_t - * - * typ opisuj±cy zapytanie lub wynik zapytania katalogu publicznego - * z protoko³u GG 5.0. nie nale¿y siê odwo³ywaæ bezpo¶rednio do jego - * pól -- s³u¿± do tego funkcje gg_pubdir50_*() - */ -typedef struct gg_pubdir50_s *gg_pubdir50_t; - -/* - * struct gg_event - * - * struktura opisuj±ca rodzaj zdarzenia. wychodzi z gg_watch_fd() lub - * z gg_dcc_watch_fd() - */ -struct gg_event { - int type; /* rodzaj zdarzenia -- gg_event_t */ - union { /* @event */ - struct gg_notify_reply *notify; /* informacje o li¶cie kontaktów -- GG_EVENT_NOTIFY */ - - enum gg_failure_t failure; /* b³±d po³±czenia -- GG_EVENT_FAILURE */ - - struct gg_dcc *dcc_new; /* nowe po³±czenie bezpo¶rednie -- GG_EVENT_DCC_NEW */ - - int dcc_error; /* b³±d po³±czenia bezpo¶redniego -- GG_EVENT_DCC_ERROR */ - - gg_pubdir50_t pubdir50; /* wynik operacji zwi±zanej z katalogiem publicznym -- GG_EVENT_PUBDIR50_* */ - - struct { /* @msg odebrano wiadomo¶æ -- GG_EVENT_MSG */ - uin_t sender; /* numer nadawcy */ - int msgclass; /* klasa wiadomo¶ci */ - time_t time; /* czas nadania */ - unsigned char *message; /* tre¶æ wiadomo¶ci */ - - int recipients_count; /* ilo¶æ odbiorców konferencji */ - uin_t *recipients; /* odbiorcy konferencji */ - - int formats_length; /* d³ugo¶æ informacji o formatowaniu tekstu */ - void *formats; /* informacje o formatowaniu tekstu */ - } msg; - - struct { /* @notify_descr informacje o li¶cie kontaktów z opisami stanu -- GG_EVENT_NOTIFY_DESCR */ - struct gg_notify_reply *notify; /* informacje o li¶cie kontaktów */ - char *descr; /* opis stanu */ - } notify_descr; - - struct { /* @status zmiana stanu -- GG_EVENT_STATUS */ - uin_t uin; /* numer */ - uint32_t status; /* nowy stan */ - char *descr; /* opis stanu */ - } status; - - struct { /* @status60 zmiana stanu -- GG_EVENT_STATUS60 */ - uin_t uin; /* numer */ - int status; /* nowy stan */ - uint32_t remote_ip; /* adres ip */ - uint16_t remote_port; /* port */ - int version; /* wersja klienta */ - int image_size; /* maksymalny rozmiar grafiki w KiB */ - char *descr; /* opis stanu */ - time_t time; /* czas powrotu */ - } status60; - - struct { /* @notify60 informacja o li¶cie kontaktów -- GG_EVENT_NOTIFY60 */ - uin_t uin; /* numer */ - int status; /* stan */ - uint32_t remote_ip; /* adres ip */ - uint16_t remote_port; /* port */ - int version; /* wersja klienta */ - int image_size; /* maksymalny rozmiar grafiki w KiB */ - char *descr; /* opis stanu */ - time_t time; /* czas powrotu */ - } *notify60; - - struct { /* @ack potwierdzenie wiadomo¶ci -- GG_EVENT_ACK */ - uin_t recipient; /* numer odbiorcy */ - int status; /* stan dorêczenia wiadomo¶ci */ - int seq; /* numer sekwencyjny wiadomo¶ci */ - } ack; - - struct { /* @dcc_voice_data otrzymano dane d¼wiêkowe -- GG_EVENT_DCC_VOICE_DATA */ - uint8_t *data; /* dane d¼wiêkowe */ - int length; /* ilo¶æ danych d¼wiêkowych */ - } dcc_voice_data; - - struct { /* @userlist odpowied¼ listy kontaktów serwera */ - char type; /* rodzaj odpowiedzi */ - char *reply; /* tre¶æ odpowiedzi */ - } userlist; - - struct { /* @image_request pro¶ba o obrazek */ - uin_t sender; /* nadawca pro¶by */ - uint32_t size; /* rozmiar obrazka */ - uint32_t crc32; /* suma kontrolna */ - } image_request; - - struct { /* @image_reply odpowied¼ z obrazkiem */ - uin_t sender; /* nadawca odpowiedzi */ - uint32_t size; /* rozmiar obrazka */ - uint32_t crc32; /* suma kontrolna */ - char *filename; /* nazwa pliku */ - char *image; /* bufor z obrazkiem */ - } image_reply; - } event; -}; - -struct gg_event *gg_watch_fd(struct gg_session *sess); -void gg_event_free(struct gg_event *e); -#define gg_free_event gg_event_free - -/* - * funkcje obs³ugi listy kontaktów. - */ -int gg_notify_ex(struct gg_session *sess, uin_t *userlist, char *types, int count); -int gg_notify(struct gg_session *sess, uin_t *userlist, int count); -int gg_add_notify_ex(struct gg_session *sess, uin_t uin, char type); -int gg_add_notify(struct gg_session *sess, uin_t uin); -int gg_remove_notify_ex(struct gg_session *sess, uin_t uin, char type); -int gg_remove_notify(struct gg_session *sess, uin_t uin); - -/* - * funkcje obs³ugi http. - */ -struct gg_http *gg_http_connect(const char *hostname, int port, int async, const char *method, const char *path, const char *header); -int gg_http_watch_fd(struct gg_http *h); -void gg_http_stop(struct gg_http *h); -void gg_http_free(struct gg_http *h); -void gg_http_free_fields(struct gg_http *h); -#define gg_free_http gg_http_free - -/* - * struktury opisuj±ca kryteria wyszukiwania dla gg_search(). nieaktualne, - * zast±pione przez gg_pubdir50_t. pozostawiono je dla zachowania ABI. - */ -struct gg_search_request { - int active; - unsigned int start; - char *nickname; - char *first_name; - char *last_name; - char *city; - int gender; - int min_birth; - int max_birth; - char *email; - char *phone; - uin_t uin; -}; - -struct gg_search { - int count; - struct gg_search_result *results; -}; - -struct gg_search_result { - uin_t uin; - char *first_name; - char *last_name; - char *nickname; - int born; - int gender; - char *city; - int active; -}; - -#define GG_GENDER_NONE 0 -#define GG_GENDER_FEMALE 1 -#define GG_GENDER_MALE 2 - -/* - * funkcje wyszukiwania. - */ -struct gg_http *gg_search(const struct gg_search_request *r, int async); -int gg_search_watch_fd(struct gg_http *f); -void gg_free_search(struct gg_http *f); -#define gg_search_free gg_free_search - -const struct gg_search_request *gg_search_request_mode_0(char *nickname, char *first_name, char *last_name, char *city, int gender, int min_birth, int max_birth, int active, int start); -const struct gg_search_request *gg_search_request_mode_1(char *email, int active, int start); -const struct gg_search_request *gg_search_request_mode_2(char *phone, int active, int start); -const struct gg_search_request *gg_search_request_mode_3(uin_t uin, int active, int start); -void gg_search_request_free(struct gg_search_request *r); - -/* - * funkcje obs³ugi katalogu publicznego zgodne z GG 5.0. tym razem funkcje - * zachowuj± pewien poziom abstrakcji, ¿eby unikn±æ zmian ABI przy zmianach - * w protokole. - * - * NIE NALE¯Y SIÊ ODWO£YWAÆ DO PÓL gg_pubdir50_t BEZPO¦REDNIO! - */ -uint32_t gg_pubdir50(struct gg_session *sess, gg_pubdir50_t req); -gg_pubdir50_t gg_pubdir50_new(int type); -int gg_pubdir50_add(gg_pubdir50_t req, const char *field, const char *value); -int gg_pubdir50_seq_set(gg_pubdir50_t req, uint32_t seq); -const char *gg_pubdir50_get(gg_pubdir50_t res, int num, const char *field); -int gg_pubdir50_type(gg_pubdir50_t res); -int gg_pubdir50_count(gg_pubdir50_t res); -uin_t gg_pubdir50_next(gg_pubdir50_t res); -uint32_t gg_pubdir50_seq(gg_pubdir50_t res); -void gg_pubdir50_free(gg_pubdir50_t res); - -#define GG_PUBDIR50_UIN "FmNumber" -#define GG_PUBDIR50_STATUS "FmStatus" -#define GG_PUBDIR50_FIRSTNAME "firstname" -#define GG_PUBDIR50_LASTNAME "lastname" -#define GG_PUBDIR50_NICKNAME "nickname" -#define GG_PUBDIR50_BIRTHYEAR "birthyear" -#define GG_PUBDIR50_CITY "city" -#define GG_PUBDIR50_GENDER "gender" -#define GG_PUBDIR50_GENDER_FEMALE "1" -#define GG_PUBDIR50_GENDER_MALE "2" -#define GG_PUBDIR50_GENDER_SET_FEMALE "2" -#define GG_PUBDIR50_GENDER_SET_MALE "1" -#define GG_PUBDIR50_ACTIVE "ActiveOnly" -#define GG_PUBDIR50_ACTIVE_TRUE "1" -#define GG_PUBDIR50_START "fmstart" -#define GG_PUBDIR50_FAMILYNAME "familyname" -#define GG_PUBDIR50_FAMILYCITY "familycity" - -int gg_pubdir50_handle_reply(struct gg_event *e, const char *packet, int length); - -/* - * struct gg_pubdir - * - * operacje na katalogu publicznym. - */ -struct gg_pubdir { - int success; /* czy siê uda³o */ - uin_t uin; /* otrzymany numerek. 0 je¶li b³±d */ -}; - -/* ogólne funkcje, nie powinny byæ u¿ywane */ -int gg_pubdir_watch_fd(struct gg_http *f); -void gg_pubdir_free(struct gg_http *f); -#define gg_free_pubdir gg_pubdir_free - -struct gg_token { - int width; /* szeroko¶æ obrazka */ - int height; /* wysoko¶æ obrazka */ - int length; /* ilo¶æ znaków w tokenie */ - char *tokenid; /* id tokenu */ -}; - -/* funkcje dotycz±ce tokenów */ -struct gg_http *gg_token(int async); -int gg_token_watch_fd(struct gg_http *h); -void gg_token_free(struct gg_http *h); - -/* rejestracja nowego numerka */ -struct gg_http *gg_register(const char *email, const char *password, int async); -struct gg_http *gg_register2(const char *email, const char *password, const char *qa, int async); -struct gg_http *gg_register3(const char *email, const char *password, const char *tokenid, const char *tokenval, int async); -#define gg_register_watch_fd gg_pubdir_watch_fd -#define gg_register_free gg_pubdir_free -#define gg_free_register gg_pubdir_free - -struct gg_http *gg_unregister(uin_t uin, const char *password, const char *email, int async); -struct gg_http *gg_unregister2(uin_t uin, const char *password, const char *qa, int async); -struct gg_http *gg_unregister3(uin_t uin, const char *password, const char *tokenid, const char *tokenval, int async); -#define gg_unregister_watch_fd gg_pubdir_watch_fd -#define gg_unregister_free gg_pubdir_free - -/* przypomnienie has³a e-mailem */ -struct gg_http *gg_remind_passwd(uin_t uin, int async); -struct gg_http *gg_remind_passwd2(uin_t uin, const char *tokenid, const char *tokenval, int async); -struct gg_http *gg_remind_passwd3(uin_t uin, const char *email, const char *tokenid, const char *tokenval, int async); -#define gg_remind_passwd_watch_fd gg_pubdir_watch_fd -#define gg_remind_passwd_free gg_pubdir_free -#define gg_free_remind_passwd gg_pubdir_free - -/* zmiana has³a */ -struct gg_http *gg_change_passwd(uin_t uin, const char *passwd, const char *newpasswd, const char *newemail, int async); -struct gg_http *gg_change_passwd2(uin_t uin, const char *passwd, const char *newpasswd, const char *email, const char *newemail, int async); -struct gg_http *gg_change_passwd3(uin_t uin, const char *passwd, const char *newpasswd, const char *qa, int async); -struct gg_http *gg_change_passwd4(uin_t uin, const char *email, const char *passwd, const char *newpasswd, const char *tokenid, const char *tokenval, int async); -#define gg_change_passwd_free gg_pubdir_free -#define gg_free_change_passwd gg_pubdir_free - -/* - * struct gg_change_info_request - * - * opis ¿±dania zmiany informacji w katalogu publicznym. - */ -struct gg_change_info_request { - char *first_name; /* imiê */ - char *last_name; /* nazwisko */ - char *nickname; /* pseudonim */ - char *email; /* email */ - int born; /* rok urodzenia */ - int gender; /* p³eæ */ - char *city; /* miasto */ -}; - -struct gg_change_info_request *gg_change_info_request_new(const char *first_name, const char *last_name, const char *nickname, const char *email, int born, int gender, const char *city); -void gg_change_info_request_free(struct gg_change_info_request *r); - -struct gg_http *gg_change_info(uin_t uin, const char *passwd, const struct gg_change_info_request *request, int async); -#define gg_change_pubdir_watch_fd gg_pubdir_watch_fd -#define gg_change_pubdir_free gg_pubdir_free -#define gg_free_change_pubdir gg_pubdir_free - -/* - * funkcje dotycz±ce listy kontaktów na serwerze. - */ -struct gg_http *gg_userlist_get(uin_t uin, const char *password, int async); -int gg_userlist_get_watch_fd(struct gg_http *f); -void gg_userlist_get_free(struct gg_http *f); - -struct gg_http *gg_userlist_put(uin_t uin, const char *password, const char *contacts, int async); -int gg_userlist_put_watch_fd(struct gg_http *f); -void gg_userlist_put_free(struct gg_http *f); - -struct gg_http *gg_userlist_remove(uin_t uin, const char *password, int async); -int gg_userlist_remove_watch_fd(struct gg_http *f); -void gg_userlist_remove_free(struct gg_http *f); - - - -/* - * funkcje dotycz±ce komunikacji miêdzy klientami. - */ -extern int gg_dcc_port; /* port, na którym nas³uchuje klient */ -extern unsigned long gg_dcc_ip; /* adres, na którym nas³uchuje klient */ - -int gg_dcc_request(struct gg_session *sess, uin_t uin); - -struct gg_dcc *gg_dcc_send_file(uint32_t ip, uint16_t port, uin_t my_uin, uin_t peer_uin); -struct gg_dcc *gg_dcc_get_file(uint32_t ip, uint16_t port, uin_t my_uin, uin_t peer_uin); -struct gg_dcc *gg_dcc_voice_chat(uint32_t ip, uint16_t port, uin_t my_uin, uin_t peer_uin); -void gg_dcc_set_type(struct gg_dcc *d, int type); -int gg_dcc_fill_file_info(struct gg_dcc *d, const char *filename); -int gg_dcc_fill_file_info2(struct gg_dcc *d, const char *filename, const char *local_filename); -int gg_dcc_voice_send(struct gg_dcc *d, char *buf, int length); - -#define GG_DCC_VOICE_FRAME_LENGTH 195 -#define GG_DCC_VOICE_FRAME_LENGTH_505 326 - -struct gg_dcc *gg_dcc_socket_create(uin_t uin, uint16_t port); -#define gg_dcc_socket_free gg_free_dcc -#define gg_dcc_socket_watch_fd gg_dcc_watch_fd - -struct gg_event *gg_dcc_watch_fd(struct gg_dcc *d); - -void gg_dcc_free(struct gg_dcc *c); -#define gg_free_dcc gg_dcc_free - -/* - * je¶li chcemy sobie podebugowaæ, wystarczy ustawiæ `gg_debug_level'. - * niestety w miarê przybywania wpisów `gg_debug(...)' nie chcia³o mi - * siê ustawiaæ odpowiednich leveli, wiêc wiêkszo¶æ sz³a do _MISC. - */ -extern int gg_debug_level; /* poziom debugowania. mapa bitowa sta³ych GG_DEBUG_* */ - -/* - * mo¿na podaæ wska¼nik do funkcji obs³uguj±cej wywo³ania gg_debug(). - * nieoficjalne, nieudokumentowane, mo¿e siê zmieniæ. je¶li kto¶ jest - * zainteresowany, niech da znaæ na ekg-devel. - */ -extern void (*gg_debug_handler)(int level, const char *format, va_list ap); - -/* - * mo¿na podaæ plik, do którego bêd± zapisywane teksty z gg_debug(). - */ -extern FILE *gg_debug_file; - -#define GG_DEBUG_NET 1 -#define GG_DEBUG_TRAFFIC 2 -#define GG_DEBUG_DUMP 4 -#define GG_DEBUG_FUNCTION 8 -#define GG_DEBUG_MISC 16 - -#ifdef GG_DEBUG_DISABLE -#define gg_debug(x, y...) do { } while(0) -#else -void gg_debug(int level, const char *format, ...); -#endif - -const char *gg_libgadu_version(void); - -/* - * konfiguracja http proxy. - */ -extern int gg_proxy_enabled; /* w³±cza obs³ugê proxy */ -extern char *gg_proxy_host; /* okre¶la adres serwera proxy */ -extern int gg_proxy_port; /* okre¶la port serwera proxy */ -extern char *gg_proxy_username; /* okre¶la nazwê u¿ytkownika przy autoryzacji serwera proxy */ -extern char *gg_proxy_password; /* okre¶la has³o u¿ytkownika przy autoryzacji serwera proxy */ -extern int gg_proxy_http_only; /* w³±cza obs³ugê proxy wy³±cznie dla us³ug HTTP */ - - -/* - * adres, z którego ¶lemy pakiety (np ³±czymy siê z serwerem) - * u¿ywany przy gg_connect() - */ -extern unsigned long gg_local_ip; -/* - * ------------------------------------------------------------------------- - * poni¿ej znajduj± siê wewnêtrzne sprawy biblioteki. zwyk³y klient nie - * powinien ich w ogóle ruszaæ, bo i nie ma po co. wszystko mo¿na za³atwiæ - * procedurami wy¿szego poziomu, których definicje znajduj± siê na pocz±tku - * tego pliku. - * ------------------------------------------------------------------------- - */ - -#ifdef __GG_LIBGADU_HAVE_PTHREAD -int gg_resolve_pthread(int *fd, void **resolver, const char *hostname); -#endif - -#ifdef _WIN32 -int gg_thread_socket(int thread_id, int socket); -#endif - -int gg_resolve(int *fd, int *pid, const char *hostname); - -#ifdef __GNUC__ -char *gg_saprintf(const char *format, ...) __attribute__ ((format (printf, 1, 2))); -#else -char *gg_saprintf(const char *format, ...); -#endif - -char *gg_vsaprintf(const char *format, va_list ap); - -#define gg_alloc_sprintf gg_saprintf - -char *gg_get_line(char **ptr); - -int gg_connect(void *addr, int port, int async); -struct in_addr *gg_gethostbyname(const char *hostname); -char *gg_read_line(int sock, char *buf, int length); -void gg_chomp(char *line); -char *gg_urlencode(const char *str); -int gg_http_hash(const char *format, ...); -int gg_read(struct gg_session *sess, char *buf, int length); -int gg_write(struct gg_session *sess, const char *buf, int length); -void *gg_recv_packet(struct gg_session *sess); -int gg_send_packet(struct gg_session *sess, int type, ...); -unsigned int gg_login_hash(const unsigned char *password, unsigned int seed); -uint32_t gg_fix32(uint32_t x); -uint16_t gg_fix16(uint16_t x); -#define fix16 gg_fix16 -#define fix32 gg_fix32 -char *gg_proxy_auth(void); -char *gg_base64_encode(const char *buf); -char *gg_base64_decode(const char *buf); -int gg_image_queue_remove(struct gg_session *s, struct gg_image_queue *q, int freeq); - -#define GG_APPMSG_HOST "appmsg.gadu-gadu.pl" -#define GG_APPMSG_PORT 80 -#define GG_PUBDIR_HOST "pubdir.gadu-gadu.pl" -#define GG_PUBDIR_PORT 80 -#define GG_REGISTER_HOST "register.gadu-gadu.pl" -#define GG_REGISTER_PORT 80 -#define GG_REMIND_HOST "retr.gadu-gadu.pl" -#define GG_REMIND_PORT 80 - -#define GG_DEFAULT_PORT 8074 -#define GG_HTTPS_PORT 443 -#define GG_HTTP_USERAGENT "Mozilla/4.7 [en] (Win98; I)" - -#define GG_DEFAULT_CLIENT_VERSION "6, 1, 0, 158" -#define GG_DEFAULT_PROTOCOL_VERSION 0x24 -#define GG_DEFAULT_TIMEOUT 30 -#define GG_HAS_AUDIO_MASK 0x40000000 -#define GG_ERA_OMNIX_MASK 0x04000000 -#define GG_LIBGADU_VERSION "CVS" - -#define GG_DEFAULT_DCC_PORT 1550 - -struct gg_header { - uint32_t type; /* typ pakietu */ - uint32_t length; /* d³ugo¶æ reszty pakietu */ -} GG_PACKED; - -#define GG_WELCOME 0x0001 -#define GG_NEED_EMAIL 0x0014 - -struct gg_welcome { - uint32_t key; /* klucz szyfrowania has³a */ -} GG_PACKED; - -#define GG_LOGIN 0x000c - -struct gg_login { - uint32_t uin; /* mój numerek */ - uint32_t hash; /* hash has³a */ - uint32_t status; /* status na dzieñ dobry */ - uint32_t version; /* moja wersja klienta */ - uint32_t local_ip; /* mój adres ip */ - uint16_t local_port; /* port, na którym s³ucham */ -} GG_PACKED; - -#define GG_LOGIN_EXT 0x0013 - -struct gg_login_ext { - uint32_t uin; /* mój numerek */ - uint32_t hash; /* hash has³a */ - uint32_t status; /* status na dzieñ dobry */ - uint32_t version; /* moja wersja klienta */ - uint32_t local_ip; /* mój adres ip */ - uint16_t local_port; /* port, na którym s³ucham */ - uint32_t external_ip; /* zewnêtrzny adres ip */ - uint16_t external_port; /* zewnêtrzny port */ -} GG_PACKED; - -#define GG_LOGIN60 0x0015 - -struct gg_login60 { - uint32_t uin; /* mój numerek */ - uint32_t hash; /* hash has³a */ - uint32_t status; /* status na dzieñ dobry */ - uint32_t version; /* moja wersja klienta */ - uint8_t dunno1; /* 0x00 */ - uint32_t local_ip; /* mój adres ip */ - uint16_t local_port; /* port, na którym s³ucham */ - uint32_t external_ip; /* zewnêtrzny adres ip */ - uint16_t external_port; /* zewnêtrzny port */ - uint8_t image_size; /* maksymalny rozmiar grafiki w KiB */ - uint8_t dunno2; /* 0xbe */ -} GG_PACKED; - -#define GG_LOGIN_OK 0x0003 - -#define GG_LOGIN_FAILED 0x0009 - -#define GG_PUBDIR50_REQUEST 0x0014 - -#define GG_PUBDIR50_WRITE 0x01 -#define GG_PUBDIR50_READ 0x02 -#define GG_PUBDIR50_SEARCH 0x03 -#define GG_PUBDIR50_SEARCH_REQUEST GG_PUBDIR50_SEARCH -#define GG_PUBDIR50_SEARCH_REPLY 0x05 - -struct gg_pubdir50_request { - uint8_t type; /* GG_PUBDIR50_* */ - uint32_t seq; /* czas wys³ania zapytania */ -} GG_PACKED; - -#define GG_PUBDIR50_REPLY 0x000e - -struct gg_pubdir50_reply { - uint8_t type; /* GG_PUBDIR50_* */ - uint32_t seq; /* czas wys³ania zapytania */ -} GG_PACKED; - -#define GG_NEW_STATUS 0x0002 - -#define GG_STATUS_NOT_AVAIL 0x0001 /* niedostêpny */ -#define GG_STATUS_NOT_AVAIL_DESCR 0x0015 /* niedostêpny z opisem (4.8) */ -#define GG_STATUS_AVAIL 0x0002 /* dostêpny */ -#define GG_STATUS_AVAIL_DESCR 0x0004 /* dostêpny z opisem (4.9) */ -#define GG_STATUS_BUSY 0x0003 /* zajêty */ -#define GG_STATUS_BUSY_DESCR 0x0005 /* zajêty z opisem (4.8) */ -#define GG_STATUS_INVISIBLE 0x0014 /* niewidoczny (4.6) */ -#define GG_STATUS_INVISIBLE_DESCR 0x0016 /* niewidoczny z opisem (4.9) */ -#define GG_STATUS_BLOCKED 0x0006 /* zablokowany */ - -#define GG_STATUS_FRIENDS_MASK 0x8000 /* tylko dla znajomych (4.6) */ - -#define GG_STATUS_DESCR_MAXSIZE 70 - -/* - * makra do ³atwego i szybkiego sprawdzania stanu. - */ - -/* GG_S_F() tryb tylko dla znajomych */ -#define GG_S_F(x) (((x) & GG_STATUS_FRIENDS_MASK) != 0) - -/* GG_S() stan bez uwzglêdnienia trybu tylko dla znajomych */ -#define GG_S(x) ((x) & ~GG_STATUS_FRIENDS_MASK) - -/* GG_S_A() dostêpny */ -#define GG_S_A(x) (GG_S(x) == GG_STATUS_AVAIL || GG_S(x) == GG_STATUS_AVAIL_DESCR) - -/* GG_S_NA() niedostêpny */ -#define GG_S_NA(x) (GG_S(x) == GG_STATUS_NOT_AVAIL || GG_S(x) == GG_STATUS_NOT_AVAIL_DESCR) - -/* GG_S_B() zajêty */ -#define GG_S_B(x) (GG_S(x) == GG_STATUS_BUSY || GG_S(x) == GG_STATUS_BUSY_DESCR) - -/* GG_S_I() niewidoczny */ -#define GG_S_I(x) (GG_S(x) == GG_STATUS_INVISIBLE || GG_S(x) == GG_STATUS_INVISIBLE_DESCR) - -/* GG_S_D() stan opisowy */ -#define GG_S_D(x) (GG_S(x) == GG_STATUS_NOT_AVAIL_DESCR || GG_S(x) == GG_STATUS_AVAIL_DESCR || GG_S(x) == GG_STATUS_BUSY_DESCR || GG_S(x) == GG_STATUS_INVISIBLE_DESCR) - -/* GG_S_BL() blokowany lub blokuj±cy */ -#define GG_S_BL(x) (GG_S(x) == GG_STATUS_BLOCKED) - -struct gg_new_status { - uint32_t status; /* na jaki zmieniæ? */ -} GG_PACKED; - -#define GG_NOTIFY_FIRST 0x000f -#define GG_NOTIFY_LAST 0x0010 - -#define GG_NOTIFY 0x0010 - -struct gg_notify { - uint32_t uin; /* numerek danej osoby */ - uint8_t dunno1; /* rodzaj wpisu w li¶cie */ -} GG_PACKED; - -#define GG_USER_OFFLINE 0x01 /* bêdziemy niewidoczni dla u¿ytkownika */ -#define GG_USER_NORMAL 0x03 /* zwyk³y u¿ytkownik */ -#define GG_USER_BLOCKED 0x04 /* zablokowany u¿ytkownik */ - -#define GG_LIST_EMPTY 0x0012 - -#define GG_NOTIFY_REPLY 0x000c /* tak, to samo co GG_LOGIN */ - -struct gg_notify_reply { - uint32_t uin; /* numerek */ - uint32_t status; /* status danej osoby */ - uint32_t remote_ip; /* adres ip delikwenta */ - uint16_t remote_port; /* port, na którym s³ucha klient */ - uint32_t version; /* wersja klienta */ - uint16_t dunno2; /* znowu port? */ -} GG_PACKED; - -#define GG_NOTIFY_REPLY60 0x0011 - -struct gg_notify_reply60 { - uint32_t uin; /* numerek plus flagi w MSB */ - uint8_t status; /* status danej osoby */ - uint32_t remote_ip; /* adres ip delikwenta */ - uint16_t remote_port; /* port, na którym s³ucha klient */ - uint8_t version; /* wersja klienta */ - uint8_t image_size; /* maksymalny rozmiar grafiki w KiB */ - uint8_t dunno1; /* 0x00 */ -} GG_PACKED; - -#define GG_STATUS60 0x000f - -struct gg_status60 { - uint32_t uin; /* numerek plus flagi w MSB */ - uint8_t status; /* status danej osoby */ - uint32_t remote_ip; /* adres ip delikwenta */ - uint16_t remote_port; /* port, na którym s³ucha klient */ - uint8_t version; /* wersja klienta */ - uint8_t image_size; /* maksymalny rozmiar grafiki w KiB */ - uint8_t dunno1; /* 0x00 */ -} GG_PACKED; - -#define GG_ADD_NOTIFY 0x000d -#define GG_REMOVE_NOTIFY 0x000e - -struct gg_add_remove { - uint32_t uin; /* numerek */ - uint8_t dunno1; /* bitmapa */ -} GG_PACKED; - -#define GG_STATUS 0x0002 - -struct gg_status { - uint32_t uin; /* numerek */ - uint32_t status; /* nowy stan */ -} GG_PACKED; - -#define GG_SEND_MSG 0x000b - -#define GG_CLASS_QUEUED 0x0001 -#define GG_CLASS_OFFLINE GG_CLASS_QUEUED -#define GG_CLASS_MSG 0x0004 -#define GG_CLASS_CHAT 0x0008 -#define GG_CLASS_CTCP 0x0010 -#define GG_CLASS_ACK 0x0020 -#define GG_CLASS_EXT GG_CLASS_ACK /* kompatybilno¶æ wstecz */ - -#define GG_MSG_MAXSIZE 2000 - -struct gg_send_msg { - uint32_t recipient; - uint32_t seq; - uint32_t msgclass; -} GG_PACKED; - -struct gg_msg_richtext { - uint8_t flag; - uint16_t length; -} GG_PACKED; - -struct gg_msg_richtext_format { - uint16_t position; - uint8_t font; -} GG_PACKED; - -struct gg_msg_richtext_image { - uint16_t unknown1; - uint32_t size; - uint32_t crc32; -} GG_PACKED; - -#define GG_FONT_BOLD 0x01 -#define GG_FONT_ITALIC 0x02 -#define GG_FONT_UNDERLINE 0x04 -#define GG_FONT_COLOR 0x08 -#define GG_FONT_IMAGE 0x80 - -struct gg_msg_richtext_color { - uint8_t red; - uint8_t green; - uint8_t blue; -} GG_PACKED; - -struct gg_msg_recipients { - uint8_t flag; - uint32_t count; -} GG_PACKED; - -struct gg_msg_image_request { - uint8_t flag; - uint32_t size; - uint32_t crc32; -} GG_PACKED; - -struct gg_msg_image_reply { - uint8_t flag; - uint32_t size; - uint32_t crc32; - /* char filename[]; */ - /* char image[]; */ -} GG_PACKED; - -#define GG_SEND_MSG_ACK 0x0005 - -#define GG_ACK_BLOCKED 0x0001 -#define GG_ACK_DELIVERED 0x0002 -#define GG_ACK_QUEUED 0x0003 -#define GG_ACK_MBOXFULL 0x0004 -#define GG_ACK_NOT_DELIVERED 0x0006 - -struct gg_send_msg_ack { - uint32_t status; - uint32_t recipient; - uint32_t seq; -} GG_PACKED; - -#define GG_RECV_MSG 0x000a - -struct gg_recv_msg { - uint32_t sender; - uint32_t seq; - uint32_t time; - uint32_t msgclass; -} GG_PACKED; - -#define GG_PING 0x0008 - -#define GG_PONG 0x0007 - -#define GG_DISCONNECTING 0x000b - -#define GG_USERLIST_REQUEST 0x0016 - -#define GG_USERLIST_PUT 0x00 -#define GG_USERLIST_PUT_MORE 0x01 -#define GG_USERLIST_GET 0x02 - -struct gg_userlist_request { - uint8_t type; -} GG_PACKED; - -#define GG_USERLIST_REPLY 0x0010 - -#define GG_USERLIST_PUT_REPLY 0x00 -#define GG_USERLIST_PUT_MORE_REPLY 0x02 -#define GG_USERLIST_GET_REPLY 0x06 -#define GG_USERLIST_GET_MORE_REPLY 0x04 - -struct gg_userlist_reply { - uint8_t type; -} GG_PACKED; - -/* - * pakiety, sta³e, struktury dla DCC - */ - -struct gg_dcc_tiny_packet { - uint8_t type; /* rodzaj pakietu */ -} GG_PACKED; - -struct gg_dcc_small_packet { - uint32_t type; /* rodzaj pakietu */ -} GG_PACKED; - -struct gg_dcc_big_packet { - uint32_t type; /* rodzaj pakietu */ - uint32_t dunno1; /* niewiadoma */ - uint32_t dunno2; /* niewiadoma */ -} GG_PACKED; - -/* - * póki co, nie znamy dok³adnie protoko³u. nie wiemy, co czemu odpowiada. - * nazwy s± niepowa¿ne i tymczasowe. - */ -#define GG_DCC_WANT_FILE 0x0003 /* peer chce plik */ -#define GG_DCC_HAVE_FILE 0x0001 /* wiêc mu damy */ -#define GG_DCC_HAVE_FILEINFO 0x0003 /* niech ma informacje o pliku */ -#define GG_DCC_GIMME_FILE 0x0006 /* peer jest pewny */ -#define GG_DCC_CATCH_FILE 0x0002 /* wysy³amy plik */ - -#define GG_DCC_FILEATTR_READONLY 0x0020 - -#define GG_DCC_TIMEOUT_SEND 1800 /* 30 minut */ -#define GG_DCC_TIMEOUT_GET 1800 /* 30 minut */ -#define GG_DCC_TIMEOUT_FILE_ACK 300 /* 5 minut */ -#define GG_DCC_TIMEOUT_VOICE_ACK 300 /* 5 minut */ - -#ifdef __cplusplus -} -#ifdef _WIN32 -#pragma pack(pop) -#endif -#endif - -#endif /* __GG_LIBGADU_H */ - -/* - * Local variables: - * c-indentation-style: k&r - * c-basic-offset: 8 - * indent-tabs-mode: notnil - * End: - * - * vim: shiftwidth=8: - */ diff --git a/kopete/protocols/gadu/libgadu/pubdir.c b/kopete/protocols/gadu/libgadu/pubdir.c deleted file mode 100644 index 2741ea4b..00000000 --- a/kopete/protocols/gadu/libgadu/pubdir.c +++ /dev/null @@ -1,689 +0,0 @@ -/* $Id$ */ - -/* - * (C) Copyright 2001-2006 Wojtek Kaniewski <wojtekka@irc.pl> - * Dawid Jarosz <dawjar@poczta.onet.pl> - * Adam Wysocki <gophi@ekg.chmurka.net> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License Version - * 2.1 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA. - */ - -#include <ctype.h> -#include <errno.h> -#include <stdarg.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#include "libgadu.h" - -/* - * gg_register3() - * - * rozpoczyna rejestracj� u�ytkownika protoko�em GG 6.0. wymaga wcze�niejszego - * pobrania tokenu za pomoc� funkcji gg_token(). - * - * - email - adres e-mail klienta - * - password - has�o klienta - * - tokenid - identyfikator tokenu - * - tokenval - warto�� tokenu - * - async - po��czenie asynchroniczne - * - * zaalokowana struct gg_http, kt�r� po�niej nale�y zwolni� - * funkcj� gg_register_free(), albo NULL je�li wyst�pi� b��d. - */ -struct gg_http *gg_register3(const char *email, const char *password, const char *tokenid, const char *tokenval, int async) -{ - struct gg_http *h; - char *__pwd, *__email, *__tokenid, *__tokenval, *form, *query; - - if (!email || !password || !tokenid || !tokenval) { - gg_debug(GG_DEBUG_MISC, "=> register, NULL parameter\n"); - errno = EFAULT; - return NULL; - } - - __pwd = gg_urlencode(password); - __email = gg_urlencode(email); - __tokenid = gg_urlencode(tokenid); - __tokenval = gg_urlencode(tokenval); - - if (!__pwd || !__email || !__tokenid || !__tokenval) { - gg_debug(GG_DEBUG_MISC, "=> register, not enough memory for form fields\n"); - free(__pwd); - free(__email); - free(__tokenid); - free(__tokenval); - return NULL; - } - - form = gg_saprintf("pwd=%s&email=%s&tokenid=%s&tokenval=%s&code=%u", - __pwd, __email, __tokenid, __tokenval, - gg_http_hash("ss", email, password)); - - free(__pwd); - free(__email); - free(__tokenid); - free(__tokenval); - - if (!form) { - gg_debug(GG_DEBUG_MISC, "=> register, not enough memory for form query\n"); - return NULL; - } - - gg_debug(GG_DEBUG_MISC, "=> register, %s\n", form); - - query = gg_saprintf( - "Host: " GG_REGISTER_HOST "\r\n" - "Content-Type: application/x-www-form-urlencoded\r\n" - "User-Agent: " GG_HTTP_USERAGENT "\r\n" - "Content-Length: %d\r\n" - "Pragma: no-cache\r\n" - "\r\n" - "%s", - (int) strlen(form), form); - - free(form); - - if (!query) { - gg_debug(GG_DEBUG_MISC, "=> register, not enough memory for query\n"); - return NULL; - } - - if (!(h = gg_http_connect(GG_REGISTER_HOST, GG_REGISTER_PORT, async, "POST", "/appsvc/fmregister3.asp", query))) { - gg_debug(GG_DEBUG_MISC, "=> register, gg_http_connect() failed mysteriously\n"); - free(query); - return NULL; - } - - h->type = GG_SESSION_REGISTER; - - free(query); - - h->callback = gg_pubdir_watch_fd; - h->destroy = gg_pubdir_free; - - if (!async) - gg_pubdir_watch_fd(h); - - return h; -} - -/* - * gg_unregister3() - * - * usuwa konto u�ytkownika z serwera protoko�em GG 6.0 - * - * - uin - numerek GG - * - password - has�o klienta - * - tokenid - identyfikator tokenu - * - tokenval - warto�� tokenu - * - async - po��czenie asynchroniczne - * - * zaalokowana struct gg_http, kt�r� po�niej nale�y zwolni� - * funkcj� gg_unregister_free(), albo NULL je�li wyst�pi� b��d. - */ -struct gg_http *gg_unregister3(uin_t uin, const char *password, const char *tokenid, const char *tokenval, int async) -{ - struct gg_http *h; - char *__fmpwd, *__pwd, *__tokenid, *__tokenval, *form, *query; - - if (!password || !tokenid || !tokenval) { - gg_debug(GG_DEBUG_MISC, "=> unregister, NULL parameter\n"); - errno = EFAULT; - return NULL; - } - - __pwd = gg_saprintf("%ld", random()); - __fmpwd = gg_urlencode(password); - __tokenid = gg_urlencode(tokenid); - __tokenval = gg_urlencode(tokenval); - - if (!__fmpwd || !__pwd || !__tokenid || !__tokenval) { - gg_debug(GG_DEBUG_MISC, "=> unregister, not enough memory for form fields\n"); - free(__pwd); - free(__fmpwd); - free(__tokenid); - free(__tokenval); - return NULL; - } - - form = gg_saprintf("fmnumber=%d&fmpwd=%s&delete=1&pwd=%s&email=deletedaccount@gadu-gadu.pl&tokenid=%s&tokenval=%s&code=%u", uin, __fmpwd, __pwd, __tokenid, __tokenval, gg_http_hash("ss", "deletedaccount@gadu-gadu.pl", __pwd)); - - free(__fmpwd); - free(__pwd); - free(__tokenid); - free(__tokenval); - - if (!form) { - gg_debug(GG_DEBUG_MISC, "=> unregister, not enough memory for form query\n"); - return NULL; - } - - gg_debug(GG_DEBUG_MISC, "=> unregister, %s\n", form); - - query = gg_saprintf( - "Host: " GG_REGISTER_HOST "\r\n" - "Content-Type: application/x-www-form-urlencoded\r\n" - "User-Agent: " GG_HTTP_USERAGENT "\r\n" - "Content-Length: %d\r\n" - "Pragma: no-cache\r\n" - "\r\n" - "%s", - (int) strlen(form), form); - - free(form); - - if (!query) { - gg_debug(GG_DEBUG_MISC, "=> unregister, not enough memory for query\n"); - return NULL; - } - - if (!(h = gg_http_connect(GG_REGISTER_HOST, GG_REGISTER_PORT, async, "POST", "/appsvc/fmregister3.asp", query))) { - gg_debug(GG_DEBUG_MISC, "=> unregister, gg_http_connect() failed mysteriously\n"); - free(query); - return NULL; - } - - h->type = GG_SESSION_UNREGISTER; - - free(query); - - h->callback = gg_pubdir_watch_fd; - h->destroy = gg_pubdir_free; - - if (!async) - gg_pubdir_watch_fd(h); - - return h; -} - -/* - * gg_change_passwd4() - * - * wysy�a ��danie zmiany has�a zgodnie z protoko�em GG 6.0. wymaga - * wcze�niejszego pobrania tokenu za pomoc� funkcji gg_token(). - * - * - uin - numer - * - email - adres e-mail - * - passwd - stare has�o - * - newpasswd - nowe has�o - * - tokenid - identyfikator tokenu - * - tokenval - warto�� tokenu - * - async - po��czenie asynchroniczne - * - * zaalokowana struct gg_http, kt�r� po�niej nale�y zwolni� - * funkcj� gg_change_passwd_free(), albo NULL je�li wyst�pi� b��d. - */ -struct gg_http *gg_change_passwd4(uin_t uin, const char *email, const char *passwd, const char *newpasswd, const char *tokenid, const char *tokenval, int async) -{ - struct gg_http *h; - char *form, *query, *__email, *__fmpwd, *__pwd, *__tokenid, *__tokenval; - - if (!uin || !email || !passwd || !newpasswd || !tokenid || !tokenval) { - gg_debug(GG_DEBUG_MISC, "=> change, NULL parameter\n"); - errno = EFAULT; - return NULL; - } - - __fmpwd = gg_urlencode(passwd); - __pwd = gg_urlencode(newpasswd); - __email = gg_urlencode(email); - __tokenid = gg_urlencode(tokenid); - __tokenval = gg_urlencode(tokenval); - - if (!__fmpwd || !__pwd || !__email || !__tokenid || !__tokenval) { - gg_debug(GG_DEBUG_MISC, "=> change, not enough memory for form fields\n"); - free(__fmpwd); - free(__pwd); - free(__email); - free(__tokenid); - free(__tokenval); - return NULL; - } - - if (!(form = gg_saprintf("fmnumber=%d&fmpwd=%s&pwd=%s&email=%s&tokenid=%s&tokenval=%s&code=%u", uin, __fmpwd, __pwd, __email, __tokenid, __tokenval, gg_http_hash("ss", email, newpasswd)))) { - gg_debug(GG_DEBUG_MISC, "=> change, not enough memory for form fields\n"); - free(__fmpwd); - free(__pwd); - free(__email); - free(__tokenid); - free(__tokenval); - - return NULL; - } - - free(__fmpwd); - free(__pwd); - free(__email); - free(__tokenid); - free(__tokenval); - - gg_debug(GG_DEBUG_MISC, "=> change, %s\n", form); - - query = gg_saprintf( - "Host: " GG_REGISTER_HOST "\r\n" - "Content-Type: application/x-www-form-urlencoded\r\n" - "User-Agent: " GG_HTTP_USERAGENT "\r\n" - "Content-Length: %d\r\n" - "Pragma: no-cache\r\n" - "\r\n" - "%s", - (int) strlen(form), form); - - free(form); - - if (!query) { - gg_debug(GG_DEBUG_MISC, "=> change, not enough memory for query\n"); - return NULL; - } - - if (!(h = gg_http_connect(GG_REGISTER_HOST, GG_REGISTER_PORT, async, "POST", "/appsvc/fmregister3.asp", query))) { - gg_debug(GG_DEBUG_MISC, "=> change, gg_http_connect() failed mysteriously\n"); - free(query); - return NULL; - } - - h->type = GG_SESSION_PASSWD; - - free(query); - - h->callback = gg_pubdir_watch_fd; - h->destroy = gg_pubdir_free; - - if (!async) - gg_pubdir_watch_fd(h); - - return h; -} - -/* - * gg_remind_passwd3() - * - * wysy�a ��danie przypomnienia has�a e-mailem. - * - * - uin - numer - * - email - adres e-mail taki, jak ten zapisany na serwerze - * - async - po��czenie asynchroniczne - * - tokenid - identyfikator tokenu - * - tokenval - warto�� tokenu - * - * zaalokowana struct gg_http, kt�r� po�niej nale�y zwolni� - * funkcj� gg_remind_passwd_free(), albo NULL je�li wyst�pi� b��d. - */ -struct gg_http *gg_remind_passwd3(uin_t uin, const char *email, const char *tokenid, const char *tokenval, int async) -{ - struct gg_http *h; - char *form, *query, *__tokenid, *__tokenval, *__email; - - if (!tokenid || !tokenval || !email) { - gg_debug(GG_DEBUG_MISC, "=> remind, NULL parameter\n"); - errno = EFAULT; - return NULL; - } - - __tokenid = gg_urlencode(tokenid); - __tokenval = gg_urlencode(tokenval); - __email = gg_urlencode(email); - - if (!__tokenid || !__tokenval || !__email) { - gg_debug(GG_DEBUG_MISC, "=> remind, not enough memory for form fields\n"); - free(__tokenid); - free(__tokenval); - free(__email); - return NULL; - } - - if (!(form = gg_saprintf("userid=%d&code=%u&tokenid=%s&tokenval=%s&email=%s", uin, gg_http_hash("u", uin), __tokenid, __tokenval, __email))) { - gg_debug(GG_DEBUG_MISC, "=> remind, not enough memory for form fields\n"); - free(__tokenid); - free(__tokenval); - free(__email); - return NULL; - } - - free(__tokenid); - free(__tokenval); - free(__email); - - gg_debug(GG_DEBUG_MISC, "=> remind, %s\n", form); - - query = gg_saprintf( - "Host: " GG_REMIND_HOST "\r\n" - "Content-Type: application/x-www-form-urlencoded\r\n" - "User-Agent: " GG_HTTP_USERAGENT "\r\n" - "Content-Length: %d\r\n" - "Pragma: no-cache\r\n" - "\r\n" - "%s", - (int) strlen(form), form); - - free(form); - - if (!query) { - gg_debug(GG_DEBUG_MISC, "=> remind, not enough memory for query\n"); - return NULL; - } - - if (!(h = gg_http_connect(GG_REMIND_HOST, GG_REMIND_PORT, async, "POST", "/appsvc/fmsendpwd3.asp", query))) { - gg_debug(GG_DEBUG_MISC, "=> remind, gg_http_connect() failed mysteriously\n"); - free(query); - return NULL; - } - - h->type = GG_SESSION_REMIND; - - free(query); - - h->callback = gg_pubdir_watch_fd; - h->destroy = gg_pubdir_free; - - if (!async) - gg_pubdir_watch_fd(h); - - return h; -} - -/* - * gg_pubdir_watch_fd() - * - * przy asynchronicznych operacjach na katalogu publicznym nale�y wywo�ywa� - * t� funkcj� przy zmianach na obserwowanym deskryptorze. - * - * - h - struktura opisuj�ca po��czenie - * - * je�li wszystko posz�o dobrze to 0, inaczej -1. operacja b�dzie - * zako�czona, je�li h->state == GG_STATE_DONE. je�li wyst�pi jaki� - * b��d, to b�dzie tam GG_STATE_ERROR i odpowiedni kod b��du w h->error. - */ -int gg_pubdir_watch_fd(struct gg_http *h) -{ - struct gg_pubdir *p; - char *tmp; - - if (!h) { - errno = EFAULT; - return -1; - } - - if (h->state == GG_STATE_ERROR) { - gg_debug(GG_DEBUG_MISC, "=> pubdir, watch_fd issued on failed session\n"); - errno = EINVAL; - return -1; - } - - if (h->state != GG_STATE_PARSING) { - if (gg_http_watch_fd(h) == -1) { - gg_debug(GG_DEBUG_MISC, "=> pubdir, http failure\n"); - errno = EINVAL; - return -1; - } - } - - if (h->state != GG_STATE_PARSING) - return 0; - - h->state = GG_STATE_DONE; - - if (!(h->data = p = malloc(sizeof(struct gg_pubdir)))) { - gg_debug(GG_DEBUG_MISC, "=> pubdir, not enough memory for results\n"); - return -1; - } - - p->success = 0; - p->uin = 0; - - gg_debug(GG_DEBUG_MISC, "=> pubdir, let's parse \"%s\"\n", h->body); - - if ((tmp = strstr(h->body, "Tokens okregisterreply_packet.reg.dwUserId="))) { - p->success = 1; - p->uin = strtol(tmp + sizeof("Tokens okregisterreply_packet.reg.dwUserId=") - 1, NULL, 0); - gg_debug(GG_DEBUG_MISC, "=> pubdir, success (okregisterreply, uin=%d)\n", p->uin); - } else if ((tmp = strstr(h->body, "success")) || (tmp = strstr(h->body, "results"))) { - p->success = 1; - if (tmp[7] == ':') - p->uin = strtol(tmp + 8, NULL, 0); - gg_debug(GG_DEBUG_MISC, "=> pubdir, success (uin=%d)\n", p->uin); - } else - gg_debug(GG_DEBUG_MISC, "=> pubdir, error.\n"); - - return 0; -} - -/* - * gg_pubdir_free() - * - * zwalnia pami�� po efektach operacji na katalogu publicznym. - * - * - h - zwalniana struktura - */ -void gg_pubdir_free(struct gg_http *h) -{ - if (!h) - return; - - free(h->data); - gg_http_free(h); -} - -/* - * gg_token() - * - * pobiera z serwera token do autoryzacji zak�adania konta, usuwania - * konta i zmiany has�a. - * - * zaalokowana struct gg_http, kt�r� po�niej nale�y zwolni� - * funkcj� gg_token_free(), albo NULL je�li wyst�pi� b��d. - */ -struct gg_http *gg_token(int async) -{ - struct gg_http *h; - const char *query; - - query = "Host: " GG_REGISTER_HOST "\r\n" - "Content-Type: application/x-www-form-urlencoded\r\n" - "User-Agent: " GG_HTTP_USERAGENT "\r\n" - "Content-Length: 0\r\n" - "Pragma: no-cache\r\n" - "\r\n"; - - if (!(h = gg_http_connect(GG_REGISTER_HOST, GG_REGISTER_PORT, async, "POST", "/appsvc/regtoken.asp", query))) { - gg_debug(GG_DEBUG_MISC, "=> token, gg_http_connect() failed mysteriously\n"); - return NULL; - } - - h->type = GG_SESSION_TOKEN; - - h->callback = gg_token_watch_fd; - h->destroy = gg_token_free; - - if (!async) - gg_token_watch_fd(h); - - return h; -} - -/* - * gg_token_watch_fd() - * - * przy asynchronicznych operacjach zwi�zanych z tokenem nale�y wywo�ywa� - * t� funkcj� przy zmianach na obserwowanym deskryptorze. - * - * - h - struktura opisuj�ca po��czenie - * - * je�li wszystko posz�o dobrze to 0, inaczej -1. operacja b�dzie - * zako�czona, je�li h->state == GG_STATE_DONE. je�li wyst�pi jaki� - * b��d, to b�dzie tam GG_STATE_ERROR i odpowiedni kod b��du w h->error. - */ -int gg_token_watch_fd(struct gg_http *h) -{ - if (!h) { - errno = EFAULT; - return -1; - } - - if (h->state == GG_STATE_ERROR) { - gg_debug(GG_DEBUG_MISC, "=> token, watch_fd issued on failed session\n"); - errno = EINVAL; - return -1; - } - - if (h->state != GG_STATE_PARSING) { - if (gg_http_watch_fd(h) == -1) { - gg_debug(GG_DEBUG_MISC, "=> token, http failure\n"); - errno = EINVAL; - return -1; - } - } - - if (h->state != GG_STATE_PARSING) - return 0; - - /* je�li h->data jest puste, to �ci�gali�my tokenid i url do niego, - * ale je�li co� tam jest, to znaczy, �e mamy drugi etap polegaj�cy - * na pobieraniu tokenu. */ - if (!h->data) { - int width, height, length; - char *url = NULL, *tokenid = NULL, *path, *headers; - const char *host; - struct gg_http *h2; - struct gg_token *t; - - gg_debug(GG_DEBUG_MISC, "=> token body \"%s\"\n", h->body); - - if (h->body && (!(url = malloc(strlen(h->body))) || !(tokenid = malloc(strlen(h->body))))) { - gg_debug(GG_DEBUG_MISC, "=> token, not enough memory for results\n"); - free(url); - return -1; - } - - if (!h->body || sscanf(h->body, "%d %d %d\r\n%s\r\n%s", &width, &height, &length, tokenid, url) != 5) { - gg_debug(GG_DEBUG_MISC, "=> token, parsing failed\n"); - free(url); - free(tokenid); - errno = EINVAL; - return -1; - } - - /* dostali�my tokenid i wszystkie niezb�dne informacje, - * wi�c pobierzmy obrazek z tokenem */ - - if (strncmp(url, "http://", 7)) { - path = gg_saprintf("%s?tokenid=%s", url, tokenid); - host = GG_REGISTER_HOST; - } else { - char *slash = (char*)strchr(url + 7, '/'); - - if (slash) { - path = gg_saprintf("%s?tokenid=%s", slash, tokenid); - *slash = 0; - host = url + 7; - } else { - gg_debug(GG_DEBUG_MISC, "=> token, url parsing failed\n"); - free(url); - free(tokenid); - errno = EINVAL; - return -1; - } - } - - if (!path) { - gg_debug(GG_DEBUG_MISC, "=> token, not enough memory for token url\n"); - free(url); - free(tokenid); - return -1; - } - - if (!(headers = gg_saprintf("Host: %s\r\nUser-Agent: " GG_HTTP_USERAGENT "\r\n\r\n", host))) { - gg_debug(GG_DEBUG_MISC, "=> token, not enough memory for token url\n"); - free(path); - free(url); - free(tokenid); - return -1; - } - - if (!(h2 = gg_http_connect(host, GG_REGISTER_PORT, h->async, "GET", path, headers))) { - gg_debug(GG_DEBUG_MISC, "=> token, gg_http_connect() failed mysteriously\n"); - free(headers); - free(url); - free(path); - free(tokenid); - return -1; - } - - free(headers); - free(path); - free(url); - - memcpy(h, h2, sizeof(struct gg_http)); - free(h2); - - h->type = GG_SESSION_TOKEN; - - h->callback = gg_token_watch_fd; - h->destroy = gg_token_free; - - if (!h->async) - gg_token_watch_fd(h); - - if (!(h->data = t = malloc(sizeof(struct gg_token)))) { - gg_debug(GG_DEBUG_MISC, "=> token, not enough memory for token data\n"); - free(tokenid); - return -1; - } - - t->width = width; - t->height = height; - t->length = length; - t->tokenid = tokenid; - } else { - /* obrazek mamy w h->body */ - h->state = GG_STATE_DONE; - } - - return 0; -} - -/* - * gg_token_free() - * - * zwalnia pami�� po efektach pobierania tokenu. - * - * - h - zwalniana struktura - */ -void gg_token_free(struct gg_http *h) -{ - struct gg_token *t; - - if (!h) - return; - - if ((t = h->data)) - free(t->tokenid); - - free(h->data); - gg_http_free(h); -} - -/* - * Local variables: - * c-indentation-style: k&r - * c-basic-offset: 8 - * indent-tabs-mode: notnil - * End: - * - * vim: shiftwidth=8: - */ diff --git a/kopete/protocols/gadu/libgadu/pubdir50.c b/kopete/protocols/gadu/libgadu/pubdir50.c deleted file mode 100644 index 877ab83e..00000000 --- a/kopete/protocols/gadu/libgadu/pubdir50.c +++ /dev/null @@ -1,467 +0,0 @@ -/* $Id$ */ - -/* - * (C) Copyright 2003 Wojtek Kaniewski <wojtekka@irc.pl> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License Version - * 2.1 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA. - */ - -#include <errno.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> - -#include "libgadu.h" - -/* - * gg_pubdir50_new() - * - * tworzy now± zmienn± typu gg_pubdir50_t. - * - * zaalokowana zmienna lub NULL w przypadku braku pamiêci. - */ -gg_pubdir50_t gg_pubdir50_new(int type) -{ - gg_pubdir50_t res = malloc(sizeof(struct gg_pubdir50_s)); - - gg_debug(GG_DEBUG_FUNCTION, "** gg_pubdir50_new(%d);\n", type); - - if (!res) { - gg_debug(GG_DEBUG_MISC, "// gg_pubdir50_new() out of memory\n"); - return NULL; - } - - memset(res, 0, sizeof(struct gg_pubdir50_s)); - - res->type = type; - - return res; -} - -/* - * gg_pubdir50_add_n() // funkcja wewnêtrzna - * - * funkcja dodaje lub zastêpuje istniej±ce pole do zapytania lub odpowiedzi. - * - * - req - wska¼nik opisu zapytania, - * - num - numer wyniku (0 dla zapytania), - * - field - nazwa pola, - * - value - warto¶æ pola, - * - * 0/-1 - */ -static int gg_pubdir50_add_n(gg_pubdir50_t req, int num, const char *field, const char *value) -{ - struct gg_pubdir50_entry *tmp = NULL, *entry; - char *dupfield, *dupvalue; - int i; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_pubdir50_add_n(%p, %d, \"%s\", \"%s\");\n", req, num, field, value); - - if (!(dupvalue = strdup(value))) { - gg_debug(GG_DEBUG_MISC, "// gg_pubdir50_add_n() out of memory\n"); - return -1; - } - - for (i = 0; i < req->entries_count; i++) { - if (req->entries[i].num != num || strcmp(req->entries[i].field, field)) - continue; - - free(req->entries[i].value); - req->entries[i].value = dupvalue; - - return 0; - } - - if (!(dupfield = strdup(field))) { - gg_debug(GG_DEBUG_MISC, "// gg_pubdir50_add_n() out of memory\n"); - free(dupvalue); - return -1; - } - - if (!(tmp = realloc(req->entries, sizeof(struct gg_pubdir50_entry) * (req->entries_count + 1)))) { - gg_debug(GG_DEBUG_MISC, "// gg_pubdir50_add_n() out of memory\n"); - free(dupfield); - free(dupvalue); - return -1; - } - - req->entries = tmp; - - entry = &req->entries[req->entries_count]; - entry->num = num; - entry->field = dupfield; - entry->value = dupvalue; - - req->entries_count++; - - return 0; -} - -/* - * gg_pubdir50_add() - * - * funkcja dodaje pole do zapytania. - * - * - req - wska¼nik opisu zapytania, - * - field - nazwa pola, - * - value - warto¶æ pola, - * - * 0/-1 - */ -int gg_pubdir50_add(gg_pubdir50_t req, const char *field, const char *value) -{ - return gg_pubdir50_add_n(req, 0, field, value); -} - -/* - * gg_pubdir50_seq_set() - * - * ustawia numer sekwencyjny zapytania. - * - * - req - zapytanie, - * - seq - nowy numer sekwencyjny. - * - * 0/-1. - */ -int gg_pubdir50_seq_set(gg_pubdir50_t req, uint32_t seq) -{ - gg_debug(GG_DEBUG_FUNCTION, "** gg_pubdir50_seq_set(%p, %d);\n", req, seq); - - if (!req) { - gg_debug(GG_DEBUG_MISC, "// gg_pubdir50_seq_set() invalid arguments\n"); - errno = EFAULT; - return -1; - } - - req->seq = seq; - - return 0; -} - -/* - * gg_pubdir50_free() - * - * zwalnia pamiêæ po zapytaniu lub rezultacie szukania u¿ytkownika. - * - * - s - zwalniana zmienna, - */ -void gg_pubdir50_free(gg_pubdir50_t s) -{ - int i; - - if (!s) - return; - - for (i = 0; i < s->entries_count; i++) { - free(s->entries[i].field); - free(s->entries[i].value); - } - - free(s->entries); - free(s); -} - -/* - * gg_pubdir50() - * - * wysy³a zapytanie katalogu publicznego do serwera. - * - * - sess - sesja, - * - req - zapytanie. - * - * numer sekwencyjny wyszukiwania lub 0 w przypadku b³êdu. - */ -uint32_t gg_pubdir50(struct gg_session *sess, gg_pubdir50_t req) -{ - int i, size = 5; - uint32_t res; - char *buf, *p; - struct gg_pubdir50_request *r; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_pubdir50(%p, %p);\n", sess, req); - - if (!sess || !req) { - gg_debug(GG_DEBUG_MISC, "// gg_pubdir50() invalid arguments\n"); - errno = EFAULT; - return 0; - } - - if (sess->state != GG_STATE_CONNECTED) { - gg_debug(GG_DEBUG_MISC, "// gg_pubdir50() not connected\n"); - errno = ENOTCONN; - return 0; - } - - for (i = 0; i < req->entries_count; i++) { - /* wyszukiwanie bierze tylko pierwszy wpis */ - if (req->entries[i].num) - continue; - - size += strlen(req->entries[i].field) + 1; - size += strlen(req->entries[i].value) + 1; - } - - if (!(buf = malloc(size))) { - gg_debug(GG_DEBUG_MISC, "// gg_pubdir50() out of memory (%d bytes)\n", size); - return 0; - } - - r = (struct gg_pubdir50_request*) buf; - res = time(NULL); - r->type = req->type; - r->seq = (req->seq) ? gg_fix32(req->seq) : gg_fix32(time(NULL)); - req->seq = gg_fix32(r->seq); - - for (i = 0, p = buf + 5; i < req->entries_count; i++) { - if (req->entries[i].num) - continue; - - strcpy(p, req->entries[i].field); - p += strlen(p) + 1; - - strcpy(p, req->entries[i].value); - p += strlen(p) + 1; - } - - if (gg_send_packet(sess, GG_PUBDIR50_REQUEST, buf, size, NULL, 0) == -1) - res = 0; - - free(buf); - - return res; -} - -/* - * gg_pubdir50_handle_reply() // funkcja wewnêtrzna - * - * analizuje przychodz±cy pakiet odpowiedzi i zapisuje wynik w struct gg_event. - * - * - e - opis zdarzenia - * - packet - zawarto¶æ pakietu odpowiedzi - * - length - d³ugo¶æ pakietu odpowiedzi - * - * 0/-1 - */ -int gg_pubdir50_handle_reply(struct gg_event *e, const char *packet, int length) -{ - const char *end = packet + length, *p; - struct gg_pubdir50_reply *r = (struct gg_pubdir50_reply*) packet; - gg_pubdir50_t res; - int num = 0; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_pubdir50_handle_reply(%p, %p, %d);\n", e, packet, length); - - if (!e || !packet) { - gg_debug(GG_DEBUG_MISC, "// gg_pubdir50_handle_reply() invalid arguments\n"); - errno = EFAULT; - return -1; - } - - if (length < 5) { - gg_debug(GG_DEBUG_MISC, "// gg_pubdir50_handle_reply() packet too short\n"); - errno = EINVAL; - return -1; - } - - if (!(res = gg_pubdir50_new(r->type))) { - gg_debug(GG_DEBUG_MISC, "// gg_pubdir50_handle_reply() unable to allocate reply\n"); - return -1; - } - - e->event.pubdir50 = res; - - res->seq = gg_fix32(r->seq); - - switch (res->type) { - case GG_PUBDIR50_READ: - e->type = GG_EVENT_PUBDIR50_READ; - break; - - case GG_PUBDIR50_WRITE: - e->type = GG_EVENT_PUBDIR50_WRITE; - break; - - default: - e->type = GG_EVENT_PUBDIR50_SEARCH_REPLY; - break; - } - - /* brak wyników? */ - if (length == 5) - return 0; - - /* pomiñ pocz±tek odpowiedzi */ - p = packet + 5; - - while (p < end) { - const char *field, *value; - - field = p; - - /* sprawd¼, czy nie mamy podzia³u na kolejne pole */ - if (!*field) { - num++; - field++; - } - - value = NULL; - - for (p = field; p < end; p++) { - /* je¶li mamy koniec tekstu... */ - if (!*p) { - /* ...i jeszcze nie mieli¶my warto¶ci pola to - * wiemy, ¿e po tym zerze jest warto¶æ... */ - if (!value) - value = p + 1; - else - /* ...w przeciwym wypadku koniec - * warto¶ci i mo¿emy wychodziæ - * grzecznie z pêtli */ - break; - } - } - - /* sprawd¼my, czy pole nie wychodzi poza pakiet, ¿eby nie - * mieæ segfaultów, je¶li serwer przestanie zakañczaæ pakietów - * przez \0 */ - - if (p == end) { - gg_debug(GG_DEBUG_MISC, "// gg_pubdir50_handle_reply() premature end of packet\n"); - goto failure; - } - - p++; - - /* je¶li dostali¶my namier na nastêpne wyniki, to znaczy ¿e - * mamy koniec wyników i nie jest to kolejna osoba. */ - if (!strcasecmp(field, "nextstart")) { - res->next = atoi(value); - num--; - } else { - if (gg_pubdir50_add_n(res, num, field, value) == -1) - goto failure; - } - } - - res->count = num + 1; - - return 0; - -failure: - gg_pubdir50_free(res); - return -1; -} - -/* - * gg_pubdir50_get() - * - * pobiera informacjê z rezultatu wyszukiwania. - * - * - res - rezultat wyszukiwania, - * - num - numer odpowiedzi, - * - field - nazwa pola (wielko¶æ liter nie ma znaczenia). - * - * warto¶æ pola lub NULL, je¶li nie znaleziono. - */ -const char *gg_pubdir50_get(gg_pubdir50_t res, int num, const char *field) -{ - char *value = NULL; - int i; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_pubdir50_get(%p, %d, \"%s\");\n", res, num, field); - - if (!res || num < 0 || !field) { - gg_debug(GG_DEBUG_MISC, "// gg_pubdir50_get() invalid arguments\n"); - errno = EINVAL; - return NULL; - } - - for (i = 0; i < res->entries_count; i++) { - if (res->entries[i].num == num && !strcasecmp(res->entries[i].field, field)) { - value = res->entries[i].value; - break; - } - } - - return value; -} - -/* - * gg_pubdir50_count() - * - * zwraca ilo¶æ wyników danego zapytania. - * - * - res - odpowied¼ - * - * ilo¶æ lub -1 w przypadku b³êdu. - */ -int gg_pubdir50_count(gg_pubdir50_t res) -{ - return (!res) ? -1 : res->count; -} - -/* - * gg_pubdir50_type() - * - * zwraca rodzaj zapytania lub odpowiedzi. - * - * - res - zapytanie lub odpowied¼ - * - * ilo¶æ lub -1 w przypadku b³êdu. - */ -int gg_pubdir50_type(gg_pubdir50_t res) -{ - return (!res) ? -1 : res->type; -} - -/* - * gg_pubdir50_next() - * - * zwraca numer, od którego nale¿y rozpocz±æ kolejne wyszukiwanie, je¶li - * zale¿y nam na kolejnych wynikach. - * - * - res - odpowied¼ - * - * numer lub -1 w przypadku b³êdu. - */ -uin_t gg_pubdir50_next(gg_pubdir50_t res) -{ - return (!res) ? (unsigned) -1 : res->next; -} - -/* - * gg_pubdir50_seq() - * - * zwraca numer sekwencyjny zapytania lub odpowiedzi. - * - * - res - zapytanie lub odpowied¼ - * - * numer lub -1 w przypadku b³êdu. - */ -uint32_t gg_pubdir50_seq(gg_pubdir50_t res) -{ - return (!res) ? (unsigned) -1 : res->seq; -} - -/* - * Local variables: - * c-indentation-style: k&r - * c-basic-offset: 8 - * indent-tabs-mode: notnil - * End: - * - * vim: shiftwidth=8: - */ |