çÒÕÐÐÁ :: çÒÁÆÉÞÅÓËÉÅ ÏÂÏÌÏÞËÉ/KDE
ðÁËÅÔ: kdenetwork
çÌÁ×ÎÁÑ éÚÍÅÎÅÎÉÑ óÐÅË ðÁÔÞÉ úÁÇÒÕÚÉÔØ Bugs and FR
ðÁÔÞ: post-3.3.2-kdenetwork-libgadu.patch
Index: kopete/protocols/gadu/libgadu/libgadu.h
===================================================================
--- kopete/protocols/gadu/libgadu/libgadu.h (.../KDE_3_3_BRANCH/kdenetwork/kopete/protocols/gadu/libgadu) (revision 367579)
+++ kopete/protocols/gadu/libgadu/libgadu.h (.../KDE/3.3/kdenetwork/kopete/protocols/gadu/libgadu) (working copy)
@@ -19,7 +19,8 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
+ * USA.
*/
#ifndef __GG_LIBGADU_H
@@ -32,15 +33,15 @@
extern "C" {
#endif
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
#include <libgadu-config.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdarg.h>
-#ifdef HAVE_STDINT_H
-#include <stdint.h>
-#endif
-
#ifdef __GG_LIBGADU_HAVE_OPENSSL
#include <openssl/ssl.h>
#endif
@@ -56,10 +57,10 @@
* 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 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 */ \
@@ -110,7 +111,7 @@
char *recv_buf; /* bufor na otrzymywane pakiety */
int recv_done; /* ile ju¿ wczytano do bufora */
- int recv_left; /* i ile jeszcze trzeba wczytaæ */
+ int recv_left; /* i ile jeszcze trzeba wczytaæ */
int protocol_version; /* wersja u¿ywanego protoko³u */
char *client_version; /* wersja u¿ywanego klienta */
@@ -149,17 +150,17 @@
struct gg_http {
gg_common_head(struct gg_http)
- int async; /* czy po³±czenie asynchroniczne */
+ 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 */
+ 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 */
+ void *data; /* dane danej operacji http */
char *user_data; /* dane u¿ytkownika, nie s± zwalniane przez gg_http_free() */
@@ -264,27 +265,27 @@
* opisuje stan asynchronicznej maszyny.
*/
enum gg_state_t {
- /* wspólne */
- GG_STATE_IDLE = 0, /* nie powinno wyst±piæ. */
- GG_STATE_RESOLVING, /* wywo³a³ gethostbyname() */
+ /* 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_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_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_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 */
@@ -349,8 +350,9 @@
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[7 * sizeof(int)]; /* miejsce na kolejnych 8 zmiennych,
+ char dummy[6 * sizeof(int)]; /* miejsce na kolejnych 6 zmiennych,
* ¿eby z dodaniem parametru nie
* zmienia³ siê rozmiar struktury */
};
@@ -499,8 +501,8 @@
*/
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 */
+ 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 */
@@ -521,20 +523,20 @@
int formats_length; /* d³ugo¶æ informacji o formatowaniu tekstu */
void *formats; /* informacje o formatowaniu tekstu */
- } msg;
+ } 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 */
+ 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 */
+ struct { /* @status60 zmiana stanu -- GG_EVENT_STATUS60 */
uin_t uin; /* numer */
int status; /* nowy stan */
uint32_t remote_ip; /* adres ip */
@@ -747,6 +749,7 @@
/* 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
@@ -812,6 +815,7 @@
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
@@ -939,10 +943,11 @@
#define GG_HTTPS_PORT 443
#define GG_HTTP_USERAGENT "Mozilla/4.7 [en] (Win98; I)"
-#define GG_DEFAULT_CLIENT_VERSION "6, 0, 0, 132"
-#define GG_DEFAULT_PROTOCOL_VERSION 0x20
+#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
@@ -1204,8 +1209,10 @@
#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 {
Index: kopete/protocols/gadu/libgadu/http.c
===================================================================
--- kopete/protocols/gadu/libgadu/http.c (.../KDE_3_3_BRANCH/kdenetwork/kopete/protocols/gadu/libgadu) (revision 367579)
+++ kopete/protocols/gadu/libgadu/http.c (.../KDE/3.3/kdenetwork/kopete/protocols/gadu/libgadu) (working copy)
@@ -14,7 +14,8 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
+ * USA.
*/
#include <sys/types.h>
@@ -60,19 +61,19 @@
struct gg_http *h;
if (!hostname || !port || !method || !path || !header) {
- gg_debug(GG_DEBUG_MISC, "// gg_http_connect() invalid arguments\n");
- errno = EINVAL;
+ gg_debug(GG_DEBUG_MISC, "// gg_http_connect() invalid arguments\n");
+ errno = EFAULT;
return NULL;
}
if (!(h = malloc(sizeof(*h))))
- return NULL;
+ return NULL;
memset(h, 0, sizeof(*h));
h->async = async;
h->port = port;
h->fd = -1;
- h->type = GG_SESSION_HTTP;
+ h->type = GG_SESSION_HTTP;
if (gg_proxy_enabled) {
char *auth = gg_proxy_auth();
@@ -91,9 +92,9 @@
}
if (!h->query) {
- gg_debug(GG_DEBUG_MISC, "// gg_http_connect() not enough memory for query\n");
+ gg_debug(GG_DEBUG_MISC, "// gg_http_connect() not enough memory for query\n");
free(h);
- errno = ENOMEM;
+ errno = ENOMEM;
return NULL;
}
@@ -105,9 +106,9 @@
#else
if (gg_resolve_pthread(&h->fd, &h->resolver, hostname)) {
#endif
- gg_debug(GG_DEBUG_MISC, "// gg_http_connect() resolver failed\n");
+ gg_debug(GG_DEBUG_MISC, "// gg_http_connect() resolver failed\n");
gg_http_free(h);
- errno = ENOENT;
+ errno = ENOENT;
return NULL;
}
@@ -130,7 +131,7 @@
}
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_debug(GG_DEBUG_MISC, "// gg_http_connect() connection failed (errno=%d, %s)\n", errno, strerror(errno));
gg_http_free(h);
return NULL;
}
@@ -143,7 +144,7 @@
}
if (h->state != GG_STATE_PARSING) {
- gg_debug(GG_DEBUG_MISC, "// gg_http_connect() some strange error\n");
+ gg_debug(GG_DEBUG_MISC, "// gg_http_connect() some strange error\n");
gg_http_free(h);
return NULL;
}
@@ -180,7 +181,7 @@
if (!h) {
gg_debug(GG_DEBUG_MISC, "// gg_http_watch_fd() invalid arguments\n");
- errno = EINVAL;
+ errno = EFAULT;
return -1;
}
@@ -242,7 +243,7 @@
}
if (h->state == GG_STATE_SENDING_QUERY) {
- unsigned int res;
+ 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);
@@ -271,7 +272,7 @@
if (h->state == GG_STATE_READING_HEADER) {
char buf[1024], *tmp;
- unsigned int res;
+ int res;
if ((res = read(h->fd, buf, sizeof(buf))) == -1) {
gg_debug(GG_DEBUG_MISC, "=> http, reading header failed (errno=%d)\n", errno);
@@ -320,7 +321,7 @@
/* 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, "=> -----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);
@@ -379,7 +380,7 @@
if (h->state == GG_STATE_READING_DATA) {
char buf[1024];
- unsigned int res;
+ int res;
if ((res = read(h->fd, buf, sizeof(buf))) == -1) {
gg_debug(GG_DEBUG_MISC, "=> http, reading body failed (errno=%d)\n", errno);
@@ -464,7 +465,7 @@
if (h->fd != -1)
close(h->fd);
- h->fd = -1;
+ h->fd = -1;
}
/*
Index: kopete/protocols/gadu/libgadu/events.c
===================================================================
--- kopete/protocols/gadu/libgadu/events.c (.../KDE_3_3_BRANCH/kdenetwork/kopete/protocols/gadu/libgadu) (revision 367579)
+++ kopete/protocols/gadu/libgadu/events.c (.../KDE/3.3/kdenetwork/kopete/protocols/gadu/libgadu) (working copy)
@@ -16,7 +16,8 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
+ * USA.
*/
#include <sys/types.h>
@@ -132,7 +133,7 @@
int gg_image_queue_remove(struct gg_session *s, struct gg_image_queue *q, int freeq)
{
if (!s || !q) {
- errno = EINVAL;
+ errno = EFAULT;
return -1;
}
@@ -166,13 +167,15 @@
* - e - opis zdarzenia
* -
*/
-static void gg_image_queue_parse(struct gg_event *e, char *p, int len, struct gg_session *sess, uin_t sender)
+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)
+ if (!p || !sess || !e) {
+ errno = EFAULT;
return;
+ }
/* znajd¼ dany obrazek w kolejce danej sesji */
@@ -298,19 +301,21 @@
count = gg_fix32(m->count);
- if (p + count * sizeof(uin_t) > packet_end) {
+ 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");
- errno = ENOMEM;
goto fail;
}
- for (i = 0; i < count; i++, p += sizeof(uin_t))
- e->event.msg.recipients[i] = gg_fix32(*((uint32_t*) p));
+ 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;
@@ -319,7 +324,7 @@
case 0x02: /* richtext */
{
- unsigned short len;
+ uint16_t len;
char *buf;
if (p + 3 > packet_end) {
@@ -327,11 +332,11 @@
goto malformed;
}
- len = gg_fix16(*((unsigned short*) (p + 1)));
+ 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");
- errno = ENOMEM;
goto fail;
}
@@ -374,12 +379,29 @@
case 0x05: /* image_reply */
case 0x06:
{
- if (p + sizeof(struct gg_msg_image_reply) + 1 > packet_end) {
+ 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;
}
- gg_image_queue_parse(e, p, (int)(packet_end - p), sess, gg_fix32(r->sender));
+ 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;
}
@@ -456,7 +478,7 @@
case GG_NOTIFY_REPLY:
{
struct gg_notify_reply *n = (void*) p;
- int count, i;
+ unsigned int count, i;
char *tmp;
gg_debug(GG_DEBUG_MISC, "// gg_watch_fd_connected() received a notify reply\n");
@@ -467,24 +489,23 @@
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) {
+ 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");
- errno = ENOMEM;
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_ip = e->event.notify_descr.notify[0].remote_ip;
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");
- errno = ENOMEM;
goto fail;
}
memcpy(tmp, p + sizeof(*n), count);
@@ -496,7 +517,6 @@
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");
- errno = ENOMEM;
goto fail;
}
@@ -507,7 +527,8 @@
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);
+ e->event.notify[i].remote_ip = e->event.notify[i].remote_ip;
+ e->event.notify[i].remote_port = gg_fix16(e->event.notify[i].remote_port);
}
}
@@ -570,6 +591,11 @@
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));
@@ -629,6 +655,8 @@
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);
@@ -641,8 +669,11 @@
e->event.status60.descr = buf;
- if (len > 4 && p[h->length - 5] == 0)
- e->event.status60.time = *((int*) (p + h->length - 4));
+ 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;
@@ -708,7 +739,7 @@
if (h->length > 1) {
char *tmp;
- int len = (sess->userlist_reply) ? strlen(sess->userlist_reply) : 0;
+ 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);
@@ -766,6 +797,7 @@
struct gg_event *e;
int res = 0;
int port = 0;
+ int errno2 = 0;
gg_debug(GG_DEBUG_FUNCTION, "** gg_watch_fd(%p);\n", sess);
@@ -792,6 +824,7 @@
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);
@@ -808,8 +841,10 @@
}
#endif
- if (failed)
+ if (failed) {
+ errno = errno2;
goto fail_resolving;
+ }
/* je¶li jeste¶my w resolverze i mamy ustawiony port
* proxy, znaczy, ¿e resolvowali¶my proxy. zatem
@@ -924,7 +959,7 @@
sess->client_version = NULL;
}
- gg_debug(GG_DEBUG_MISC, "=> -----BEGIN-HTTP-QUERY-----\n%s\n=> -----END-HTTP-QUERY-----\n", buf);
+ 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,
@@ -1056,7 +1091,7 @@
if ((tmp = strchr(host, ':'))) {
*tmp = 0;
- port = atoi(tmp+1);
+ port = atoi(tmp + 1);
}
addr.s_addr = inet_addr(host);
@@ -1155,9 +1190,15 @@
/* 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;
- snprintf(buf, sizeof(buf), "CONNECT %s:%d HTTP/1.0\r\n", inet_ntoa(*((struct in_addr*) &sess->server_addr)), sess->port);
+ 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,
@@ -1326,7 +1367,9 @@
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;
}
@@ -1355,7 +1398,11 @@
free(sess->password);
sess->password = NULL;
- gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() gg_dcc_ip = %s\n", inet_ntoa(*((struct in_addr*) &gg_dcc_ip)));
+ {
+ 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;
@@ -1382,7 +1429,7 @@
if (sess->external_addr && sess->external_port > 1023) {
l.external_ip = sess->external_addr;
- l.external_port = sess->external_port;
+ l.external_port = gg_fix16(sess->external_port);
}
gg_debug(GG_DEBUG_TRAFFIC, "// gg_watch_fd() sending GG_LOGIN60 packet\n");
@@ -1393,8 +1440,9 @@
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;
@@ -1418,7 +1466,9 @@
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;
}
@@ -1449,7 +1499,9 @@
e->type = GG_EVENT_CONN_FAILED;
sess->state = GG_STATE_IDLE;
+ errno2 = errno;
close(sess->fd);
+ errno = errno2;
sess->fd = -1;
free(h);
@@ -1486,7 +1538,9 @@
fail_connecting:
if (sess->fd != -1) {
+ errno2 = errno;
close(sess->fd);
+ errno = errno2;
sess->fd = -1;
}
e->type = GG_EVENT_CONN_FAILED;
Index: kopete/protocols/gadu/libgadu/pubdir.c
===================================================================
--- kopete/protocols/gadu/libgadu/pubdir.c (.../KDE_3_3_BRANCH/kdenetwork/kopete/protocols/gadu/libgadu) (revision 367579)
+++ kopete/protocols/gadu/libgadu/pubdir.c (.../KDE/3.3/kdenetwork/kopete/protocols/gadu/libgadu) (working copy)
@@ -15,7 +15,8 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
+ * USA.
*/
#include <ctype.h>
@@ -45,12 +46,12 @@
*/
struct gg_http *gg_register3(const char *email, const char *password, const char *tokenid, const char *tokenval, int async)
{
- struct gg_http *h;
+ struct gg_http *h;
char *__pwd, *__email, *__tokenid, *__tokenval, *form, *query;
- if (!email | !password | !tokenid | !tokenval) {
+ if (!email || !password || !tokenid || !tokenval) {
gg_debug(GG_DEBUG_MISC, "=> register, NULL parameter\n");
- errno = EINVAL;
+ errno = EFAULT;
return NULL;
}
@@ -65,7 +66,6 @@
free(__email);
free(__tokenid);
free(__tokenval);
- errno = ENOMEM;
return NULL;
}
@@ -80,7 +80,6 @@
if (!form) {
gg_debug(GG_DEBUG_MISC, "=> register, not enough memory for form query\n");
- errno = ENOMEM;
return NULL;
}
@@ -98,10 +97,15 @@
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;
+ return NULL;
}
h->type = GG_SESSION_REGISTER;
@@ -138,7 +142,7 @@
if (!password || !tokenid || !tokenval) {
gg_debug(GG_DEBUG_MISC, "=> unregister, NULL parameter\n");
- errno = EINVAL;
+ errno = EFAULT;
return NULL;
}
@@ -153,7 +157,6 @@
free(__fmpwd);
free(__tokenid);
free(__tokenval);
- errno = ENOMEM;
return NULL;
}
@@ -166,7 +169,6 @@
if (!form) {
gg_debug(GG_DEBUG_MISC, "=> unregister, not enough memory for form query\n");
- errno = ENOMEM;
return NULL;
}
@@ -184,6 +186,11 @@
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);
@@ -227,7 +234,7 @@
if (!uin || !email || !passwd || !newpasswd || !tokenid || !tokenval) {
gg_debug(GG_DEBUG_MISC, "=> change, NULL parameter\n");
- errno = EINVAL;
+ errno = EFAULT;
return NULL;
}
@@ -244,7 +251,6 @@
free(__email);
free(__tokenid);
free(__tokenval);
- errno = ENOMEM;
return NULL;
}
@@ -256,7 +262,6 @@
free(__tokenid);
free(__tokenval);
- errno = ENOMEM;
return NULL;
}
@@ -268,21 +273,26 @@
gg_debug(GG_DEBUG_MISC, "=> change, %s\n", form);
- query = gg_saprintf(
+ 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);
+ "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);
+ free(query);
return NULL;
}
@@ -300,11 +310,12 @@
}
/*
- * gg_remind_passwd()
+ * 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
@@ -312,56 +323,63 @@
* 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_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)
{
struct gg_http *h;
- char *form, *query, *__tokenid, *__tokenval;
+ char *form, *query, *__tokenid, *__tokenval, *__email;
- if (!tokenid || !tokenval) {
+ if (!tokenid || !tokenval || !email) {
gg_debug(GG_DEBUG_MISC, "=> remind, NULL parameter\n");
- errno = EINVAL;
+ errno = EFAULT;
return NULL;
}
__tokenid = gg_urlencode(tokenid);
__tokenval = gg_urlencode(tokenval);
+ __email = gg_urlencode(email);
- if (!__tokenid || !__tokenval) {
+ if (!__tokenid || !__tokenval || !__email) {
gg_debug(GG_DEBUG_MISC, "=> remind, not enough memory for form fields\n");
free(__tokenid);
free(__tokenval);
- errno = ENOMEM;
+ free(__email);
return NULL;
}
- if (!(form = gg_saprintf("userid=%d&code=%u&tokenid=%s&tokenval=%s", uin, gg_http_hash("u", uin), __tokenid, __tokenval))) {
+ 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");
- errno = ENOMEM;
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(
+ 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);
+ "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);
+ free(query);
return NULL;
}
@@ -396,33 +414,34 @@
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_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;
+ errno = EINVAL;
return -1;
}
}
if (h->state != GG_STATE_PARSING)
- return 0;
+ return 0;
- h->state = GG_STATE_DONE;
+ 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;
@@ -507,33 +526,34 @@
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_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;
+ errno = EINVAL;
return -1;
}
}
if (h->state != GG_STATE_PARSING)
- return 0;
+ 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;
+ char *url = NULL, *tokenid = NULL, *path, *headers;
+ const char *host;
struct gg_http *h2;
struct gg_token *t;
@@ -549,29 +569,59 @@
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 (!(path = gg_saprintf("%s?tokenid=%s", url, tokenid))) {
+ if (strncmp(url, "http://", 7)) {
+ path = gg_saprintf("%s?tokenid=%s", url, tokenid);
+ host = GG_REGISTER_HOST;
+ } else {
+ char *slash = 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;
}
- free(url);
-
- if (!(h2 = gg_http_connect(GG_REGISTER_HOST, GG_REGISTER_PORT, h->async, "GET", path, "Host: " GG_REGISTER_HOST "\r\nUser-Agent: " GG_HTTP_USERAGENT "\r\n\r\n"))) {
+ 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);
Index: kopete/protocols/gadu/libgadu/libgadu.c
===================================================================
--- kopete/protocols/gadu/libgadu/libgadu.c (.../KDE_3_3_BRANCH/kdenetwork/kopete/protocols/gadu/libgadu) (revision 367579)
+++ kopete/protocols/gadu/libgadu/libgadu.c (.../KDE/3.3/kdenetwork/kopete/protocols/gadu/libgadu) (working copy)
@@ -17,7 +17,8 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
+ * USA.
*/
#include <sys/types.h>
@@ -106,9 +107,9 @@
#else
return (uint32_t)
(((x & (uint32_t) 0x000000ffU) << 24) |
- ((x & (uint32_t) 0x0000ff00U) << 8) |
- ((x & (uint32_t) 0x00ff0000U) >> 8) |
- ((x & (uint32_t) 0xff000000U) >> 24));
+ ((x & (uint32_t) 0x0000ff00U) << 8) |
+ ((x & (uint32_t) 0x00ff0000U) >> 8) |
+ ((x & (uint32_t) 0xff000000U) >> 24));
#endif
}
@@ -130,7 +131,7 @@
#else
return (uint16_t)
(((x & (uint16_t) 0x00ffU) << 8) |
- ((x & (uint16_t) 0xff00U) >> 8));
+ ((x & (uint16_t) 0xff00U) >> 8));
#endif
}
@@ -186,6 +187,7 @@
{
int pipes[2], res;
struct in_addr a;
+ int errno2;
gg_debug(GG_DEBUG_FUNCTION, "** gg_resolve(%p, %p, \"%s\");\n", fd, pid, hostname);
@@ -198,8 +200,10 @@
return -1;
if ((res = fork()) == -1) {
+ errno2 = errno;
close(pipes[0]);
close(pipes[1]);
+ errno = errno2;
return -1;
}
@@ -240,6 +244,8 @@
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;
@@ -294,7 +300,6 @@
if (!(tmp = malloc(sizeof(pthread_t)))) {
gg_debug(GG_DEBUG_MISC, "// gg_resolve_pthread() out of memory for pthread id\n");
- errno = ENOMEM;
return -1;
}
@@ -306,7 +311,7 @@
if (!(d = malloc(sizeof(*d)))) {
gg_debug(GG_DEBUG_MISC, "// gg_resolve_pthread() out of memory\n");
- new_errno = ENOMEM;
+ new_errno = errno;
goto cleanup;
}
@@ -314,7 +319,7 @@
if (!(d->hostname = strdup(hostname))) {
gg_debug(GG_DEBUG_MISC, "// gg_resolve_pthread() out of memory\n");
- new_errno = ENOMEM;
+ new_errno = errno;
goto cleanup;
}
@@ -403,7 +408,7 @@
*/
int gg_write(struct gg_session *sess, const char *buf, int length)
{
- int res;
+ int res = 0;
#ifdef __GG_LIBGADU_HAVE_OPENSSL
if (sess->ssl) {
@@ -450,13 +455,16 @@
*
* - sess - opis sesji
*
- * w przypadku b³êdu NULL, kod b³êdu w errno.
+ * 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, offset, size = 0;
+ int ret = 0;
+ unsigned int offset, size = 0;
gg_debug(GG_DEBUG_FUNCTION, "** gg_recv_packet(%p);\n", sess);
@@ -480,7 +488,7 @@
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 = 0;
+ errno = ECONNRESET;
gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() header recv() failed: connection broken\n");
return NULL;
}
@@ -519,7 +527,7 @@
memcpy(&h, sess->recv_buf, sizeof(h));
/* jakie¶ sensowne limity na rozmiar pakietu */
- if (h.length < 0 || h.length > 65535) {
+ if (h.length > 65535) {
gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() invalid packet length (%d)\n", h.length);
errno = ERANGE;
return NULL;
@@ -545,11 +553,20 @@
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;
@@ -600,25 +617,21 @@
{
struct gg_header *h;
char *tmp;
- int tmp_length;
+ unsigned int tmp_length;
void *payload;
- int payload_length;
+ 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 = 0;
+ tmp_length = sizeof(struct gg_header);
- if (!(tmp = malloc(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;
}
- h = (struct gg_header*) tmp;
- h->type = gg_fix32(type);
- h->length = gg_fix32(0);
-
va_start(ap, type);
payload = va_arg(ap, void *);
@@ -626,21 +639,18 @@
while (payload) {
char *tmp2;
- payload_length = va_arg(ap, int);
+ payload_length = va_arg(ap, unsigned int);
- if (payload_length < 0)
- gg_debug(GG_DEBUG_MISC, "// gg_send_packet() invalid payload length (%d)\n", payload_length);
-
- if (!(tmp2 = realloc(tmp, sizeof(struct gg_header) + tmp_length + payload_length))) {
- gg_debug(GG_DEBUG_MISC, "// gg_send_packet() not enough memory for payload\n");
+ 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;
- }
+ return -1;
+ }
tmp = tmp2;
- memcpy(tmp + sizeof(struct gg_header) + tmp_length, payload, payload_length);
+ memcpy(tmp + tmp_length, payload, payload_length);
tmp_length += payload_length;
payload = va_arg(ap, void *);
@@ -649,19 +659,18 @@
va_end(ap);
h = (struct gg_header*) tmp;
- h->length = gg_fix32(tmp_length);
+ 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 < sizeof(struct gg_header) + gg_fix32(h->length); i++)
- gg_debug(GG_DEBUG_DUMP, " %.2x", (unsigned char) tmp[i]);
- gg_debug(GG_DEBUG_DUMP, "\n");
- }
+ 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");
+ }
- tmp_length += sizeof(struct gg_header);
-
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);
@@ -681,7 +690,7 @@
static int gg_session_callback(struct gg_session *s)
{
if (!s) {
- errno = EINVAL;
+ errno = EFAULT;
return -1;
}
@@ -711,7 +720,7 @@
if (!p) {
gg_debug(GG_DEBUG_FUNCTION, "** gg_login(%p);\n", p);
- errno = EINVAL;
+ errno = EFAULT;
return NULL;
}
@@ -726,7 +735,7 @@
if (!p->password || !p->uin) {
gg_debug(GG_DEBUG_MISC, "// gg_login() invalid arguments. uin and password needed\n");
- errno = EINVAL;
+ errno = EFAULT;
goto fail;
}
@@ -745,7 +754,7 @@
sess->check = GG_CHECK_READ;
sess->timeout = GG_DEFAULT_TIMEOUT;
sess->async = p->async;
- sess->type = GG_SESSION_GG;
+ sess->type = GG_SESSION_GG;
sess->initial_status = p->status;
sess->callback = gg_session_callback;
sess->destroy = gg_free_session;
@@ -754,6 +763,8 @@
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;
@@ -1094,7 +1105,7 @@
#endif
if (sess->fd != -1) {
- shutdown(sess->fd, 2);
+ shutdown(sess->fd, SHUT_RDWR);
close(sess->fd);
sess->fd = -1;
}
@@ -1131,6 +1142,11 @@
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);
@@ -1143,15 +1159,21 @@
if (!res) {
struct gg_image_queue *q = malloc(sizeof(*q));
- char *buf = malloc(size);
+ char *buf;
if (!q) {
gg_debug(GG_DEBUG_MISC, "// gg_image_request() not enough memory for image queue\n");
- free(buf);
- errno = ENOMEM;
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;
@@ -1193,7 +1215,7 @@
struct gg_send_msg s;
const char *tmp;
char buf[1910];
- int res;
+ int res = -1;
gg_debug(GG_DEBUG_FUNCTION, "** gg_image_reply(%p, %d, \"%s\", %p, %d);\n", sess, recipient, filename, image, size);
@@ -1202,6 +1224,16 @@
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;
@@ -1211,11 +1243,6 @@
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(GG_CLASS_MSG);
@@ -1338,12 +1365,17 @@
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);
@@ -1408,12 +1440,17 @@
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);
@@ -1423,6 +1460,9 @@
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]);
@@ -1724,10 +1764,15 @@
int len;
if (!sess) {
- errno = EINVAL;
+ 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);
Index: kopete/protocols/gadu/libgadu/common.c
===================================================================
--- kopete/protocols/gadu/libgadu/common.c (.../KDE_3_3_BRANCH/kdenetwork/kopete/protocols/gadu/libgadu) (revision 367579)
+++ kopete/protocols/gadu/libgadu/common.c (.../KDE/3.3/kdenetwork/kopete/protocols/gadu/libgadu) (working copy)
@@ -15,7 +15,8 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
+ * USA.
*/
#include <sys/types.h>
@@ -90,7 +91,7 @@
*/
char *gg_vsaprintf(const char *format, va_list ap)
{
- int size = 0;
+ int size = 0;
const char *start;
char *buf = NULL;
@@ -192,23 +193,23 @@
*/
char *gg_get_line(char **ptr)
{
- char *foo, *res;
+ char *foo, *res;
- if (!ptr || !*ptr || !strcmp(*ptr, ""))
- return NULL;
+ if (!ptr || !*ptr || !strcmp(*ptr, ""))
+ return NULL;
- res = *ptr;
+ res = *ptr;
- if (!(foo = strchr(*ptr, '\n')))
- *ptr += strlen(*ptr);
- else {
- *ptr = foo + 1;
- *foo = 0;
- if (strlen(res) > 1 && res[strlen(res) - 1] == '\r')
- res[strlen(res) - 1] = 0;
- }
+ if (!(foo = strchr(*ptr, '\n')))
+ *ptr += strlen(*ptr);
+ else {
+ *ptr = foo + 1;
+ *foo = 0;
+ if (strlen(res) > 1 && res[strlen(res) - 1] == '\r')
+ res[strlen(res) - 1] = 0;
+ }
- return res;
+ return res;
}
/*
@@ -226,10 +227,10 @@
*/
int gg_connect(void *addr, int port, int async)
{
- int sock, one = 1;
+ int sock, one = 1, errno2;
struct sockaddr_in sin;
struct in_addr *a = addr;
- struct sockaddr_in myaddr;
+ struct sockaddr_in myaddr;
gg_debug(GG_DEBUG_FUNCTION, "** gg_connect(%s, %d, %d);\n", inet_ntoa(*a), port, async);
@@ -238,16 +239,16 @@
return -1;
}
- memset(&myaddr, 0, sizeof(myaddr));
- myaddr.sin_family = AF_INET;
+ 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;
- }
+ 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
@@ -259,7 +260,9 @@
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;
}
}
@@ -271,7 +274,9 @@
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");
@@ -289,12 +294,16 @@
* - buf - wska¼nik do bufora
* - length - d³ugo¶æ bufora
*
- * je¶li trafi na b³±d odczytu, zwraca NULL. inaczej zwraca buf.
+ * 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) {
@@ -327,13 +336,17 @@
*/
void gg_chomp(char *line)
{
- if (!line || strlen(line) < 1)
+ int len;
+
+ if (!line)
return;
- if (line[strlen(line) - 1] == '\n')
- line[strlen(line) - 1] = 0;
- if (line[strlen(line) - 1] == '\r')
- line[strlen(line) - 1] = 0;
+ len = strlen(line);
+
+ if (len > 0 && line[len - 1] == '\n')
+ line[--len] = 0;
+ if (len > 0 && line[len - 1] == '\r')
+ line[--len] = 0;
}
/*
@@ -351,10 +364,10 @@
{
char *q, *buf, hex[] = "0123456789abcdef";
const char *p;
- int size = 0;
+ unsigned int size = 0;
- if (!str && !(str = strdup("")))
- return NULL;
+ 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 == '-'))
@@ -403,18 +416,18 @@
va_start(ap, format);
for (j = 0; j < strlen(format); j++) {
- unsigned char *arg, buf[16];
+ 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, unsigned char*)))
+ if (!(arg = va_arg(ap, char*)))
arg = "";
}
i = 0;
- while ((c = (int) arg[i++]) != 0) {
+ while ((c = (unsigned char) arg[i++]) != 0) {
a = (c ^ b) + (c << 8);
b = (a >> 24) | (a << 8);
}
@@ -496,7 +509,6 @@
struct hostent *hp;
if (!(addr = malloc(sizeof(struct in_addr)))) {
- errno = ENOMEM;
goto cleanup;
}
@@ -556,37 +568,36 @@
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) {
+ closesocket(wsk->socket);
+ *p_wsk = wsk->next;
+ free(wsk);
+ return 1;
+ } else if (!socket) {
/* socket zostaje zwrocony */
return wsk->socket;
- } else {
+ } else {
/* socket zostaje ustawiony */
wsk->socket = socket;
return socket;
}
- }
-
- p_wsk = &(wsk->next);
- wsk = wsk->next;
- }
-
- if (close && socket != -1)
+ }
+ p_wsk = &(wsk->next);
+ wsk = wsk->next;
+ }
+
+ if (close && socket != -1)
closesocket(socket);
- if (close || !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;
+ /* 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 */
@@ -606,7 +617,7 @@
char *gg_base64_encode(const char *buf)
{
char *out, *res;
- int i = 0, j = 0, k = 0, len = strlen(buf);
+ unsigned int i = 0, j = 0, k = 0, len = strlen(buf);
res = out = malloc((len / 3 + 1) * 4 + 2);
@@ -664,7 +675,7 @@
{
char *res, *save, *foo, val;
const char *end;
- int index = 0;
+ unsigned int index = 0;
if (!buf)
return NULL;
@@ -758,7 +769,7 @@
static void gg_crc32_make_table()
{
uint32_t h = 1;
- int i, j;
+ unsigned int i, j;
memset(gg_crc32_table, 0, sizeof(gg_crc32_table));
@@ -788,6 +799,9 @@
if (!gg_crc32_initialized)
gg_crc32_make_table();
+ if (!buf || len < 0)
+ return crc;
+
crc ^= 0xffffffffL;
while (len--)
Index: kopete/protocols/gadu/libgadu/compat.h
===================================================================
--- kopete/protocols/gadu/libgadu/compat.h (.../KDE_3_3_BRANCH/kdenetwork/kopete/protocols/gadu/libgadu) (revision 367579)
+++ kopete/protocols/gadu/libgadu/compat.h (.../KDE/3.3/kdenetwork/kopete/protocols/gadu/libgadu) (working copy)
@@ -15,7 +15,8 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
+ * USA.
*/
#ifndef __COMPAT_H
Index: kopete/protocols/gadu/libgadu/dcc.c
===================================================================
--- kopete/protocols/gadu/libgadu/dcc.c (.../KDE_3_3_BRANCH/kdenetwork/kopete/protocols/gadu/libgadu) (revision 367579)
+++ kopete/protocols/gadu/libgadu/dcc.c (.../KDE/3.3/kdenetwork/kopete/protocols/gadu/libgadu) (working copy)
@@ -15,7 +15,8 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
+ * USA.
*/
#include <sys/types.h>
@@ -51,9 +52,9 @@
* - buf - bufor z danymi
* - size - rozmiar danych
*/
-static void gg_dcc_debug_data(const char *prefix, int fd, const void *buf, int size)
+static void gg_dcc_debug_data(const char *prefix, int fd, const void *buf, unsigned int size)
{
- int i;
+ unsigned int i;
gg_debug(GG_DEBUG_MISC, "++ gg_dcc %s (fd=%d,len=%d)", prefix, fd, size);
@@ -123,31 +124,48 @@
*/
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_info(%p, \"%s\");\n", d, filename);
-
+
+ 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_info() invalid arguments\n");
+ gg_debug(GG_DEBUG_MISC, "// gg_dcc_fill_file_info2() invalid arguments\n");
errno = EINVAL;
return -1;
}
-
- if (stat(filename, &st) == -1) {
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_fill_file_info() stat() failed (%s)\n", strerror(errno));
+
+ 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_info() that's a directory\n");
+ gg_debug(GG_DEBUG_MISC, "// gg_dcc_fill_file_info2() that's a directory\n");
errno = EINVAL;
return -1;
}
- if ((d->file_fd = open(filename, O_RDONLY)) == -1) {
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_fill_file_info() open() failed (%s)\n", strerror(errno));
+ 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;
}
@@ -159,7 +177,7 @@
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 */
@@ -173,14 +191,40 @@
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]);
-
}
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_fill_file_info() short name \"%s\", dos name \"%s\"\n", name, d->file_info.short_filename);
+ 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;
@@ -345,9 +389,9 @@
{
struct gg_dcc *c;
struct sockaddr_in sin;
- int sock, bound = 0;
+ int sock, bound = 0, errno2;
- gg_debug(GG_DEBUG_FUNCTION, "** gg_create_dcc_socket(%d, %d);\n", uin, port);
+ 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");
@@ -374,6 +418,7 @@
else {
if (++port == 65535) {
gg_debug(GG_DEBUG_MISC, "// gg_create_dcc_socket() no free port found\n");
+ close(sock);
return NULL;
}
}
@@ -381,6 +426,9 @@
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;
}
@@ -389,13 +437,13 @@
if (!(c = malloc(sizeof(*c)))) {
gg_debug(GG_DEBUG_MISC, "// gg_create_dcc_socket() not enough memory for struct\n");
close(sock);
- return NULL;
+ return NULL;
}
memset(c, 0, sizeof(*c));
c->port = c->id = port;
c->fd = sock;
- c->type = GG_SESSION_DCC_SOCKET;
+ c->type = GG_SESSION_DCC_SOCKET;
c->uin = uin;
c->timeout = -1;
c->state = GG_STATE_LISTENING;
@@ -403,7 +451,6 @@
c->callback = gg_dcc_callback;
c->destroy = gg_dcc_free;
- gg_dcc_ip = INADDR_ANY;
return c;
}
@@ -429,6 +476,7 @@
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;
}
@@ -500,7 +548,7 @@
struct gg_event *e;
int foo;
- gg_debug(GG_DEBUG_FUNCTION, "** gg_dcc_watch_fd(%p);\n", h);
+ 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");
@@ -508,12 +556,12 @@
return NULL;
}
- if (!(e = (void*) calloc(1, sizeof(*e)))) {
+ if (!(e = (void*) calloc(1, sizeof(*e)))) {
gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() not enough memory\n");
- return NULL;
- }
+ return NULL;
+ }
- e->type = GG_EVENT_NONE;
+ e->type = GG_EVENT_NONE;
if (h->type == GG_SESSION_DCC_SOCKET) {
struct sockaddr_in sin;
@@ -860,7 +908,6 @@
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;
@@ -1056,6 +1103,15 @@
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);
@@ -1213,7 +1269,7 @@
*/
void gg_dcc_free(struct gg_dcc *d)
{
- gg_debug(GG_DEBUG_FUNCTION, "** gg_dcc_free(%p);\n", d);
+ gg_debug(GG_DEBUG_FUNCTION, "** gg_dcc_free(%p);\n", d);
if (!d)
return;
Index: kopete/protocols/gadu/libgadu/pubdir50.c
===================================================================
--- kopete/protocols/gadu/libgadu/pubdir50.c (.../KDE_3_3_BRANCH/kdenetwork/kopete/protocols/gadu/libgadu) (revision 367579)
+++ kopete/protocols/gadu/libgadu/pubdir50.c (.../KDE/3.3/kdenetwork/kopete/protocols/gadu/libgadu) (working copy)
@@ -14,7 +14,8 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
+ * USA.
*/
#include <errno.h>
@@ -265,7 +266,7 @@
if (!e || !packet) {
gg_debug(GG_DEBUG_MISC, "// gg_pubdir50_handle_reply() invalid arguments\n");
- errno = EINVAL;
+ errno = EFAULT;
return -1;
}