summaryrefslogtreecommitdiffstats
path: root/kopete/protocols/gadu/libgadu
diff options
context:
space:
mode:
Diffstat (limited to 'kopete/protocols/gadu/libgadu')
-rw-r--r--kopete/protocols/gadu/libgadu/COPYING504
-rw-r--r--kopete/protocols/gadu/libgadu/Makefile.am12
-rw-r--r--kopete/protocols/gadu/libgadu/common.c827
-rw-r--r--kopete/protocols/gadu/libgadu/compat.h29
-rw-r--r--kopete/protocols/gadu/libgadu/dcc.c1298
-rw-r--r--kopete/protocols/gadu/libgadu/events.c1580
-rw-r--r--kopete/protocols/gadu/libgadu/http.c522
-rw-r--r--kopete/protocols/gadu/libgadu/libgadu-config.h.in30
-rw-r--r--kopete/protocols/gadu/libgadu/libgadu.c1818
-rw-r--r--kopete/protocols/gadu/libgadu/libgadu.h1310
-rw-r--r--kopete/protocols/gadu/libgadu/pubdir.c689
-rw-r--r--kopete/protocols/gadu/libgadu/pubdir50.c467
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:
- */