Index: kopete/protocols/gadu/libgadu/http.c =================================================================== --- kopete/protocols/gadu/libgadu/http.c (.../KDE_3_2_BRANCH/kdenetwork/kopete/protocols/gadu/libgadu) (revision 316997) +++ kopete/protocols/gadu/libgadu/http.c (.../KDE/3.2/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 @@ -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; } @@ -117,21 +118,20 @@ h->check = GG_CHECK_READ; h->timeout = GG_DEFAULT_TIMEOUT; } else { - struct hostent *he; - struct in_addr a; + struct in_addr *hn, a; - if (!(he = gg_gethostbyname(hostname))) { - gg_debug(GG_DEBUG_MISC, "// gg_http_connect() host not found\n"); + 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 { - memcpy((char*) &a, he->h_addr, sizeof(a)); - free(he); + 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_debug(GG_DEBUG_MISC, "// gg_http_connect() connection failed (errno=%d, %s)\n", errno, strerror(errno)); gg_http_free(h); return NULL; } @@ -144,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; } @@ -181,7 +181,7 @@ if (!h) { gg_debug(GG_DEBUG_MISC, "// gg_http_watch_fd() invalid arguments\n"); - errno = EINVAL; + errno = EFAULT; return -1; } @@ -243,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); @@ -272,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); @@ -321,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); @@ -380,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); @@ -465,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_2_BRANCH/kdenetwork/kopete/protocols/gadu/libgadu) (revision 316997) +++ kopete/protocols/gadu/libgadu/events.c (.../KDE/3.2/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 @@ -59,47 +60,60 @@ if (!e) return; - if (e->type == GG_EVENT_MSG) { - free(e->event.msg.message); - free(e->event.msg.formats); - free(e->event.msg.recipients); - } + switch (e->type) { + case GG_EVENT_MSG: + free(e->event.msg.message); + free(e->event.msg.formats); + free(e->event.msg.recipients); + break; - if (e->type == GG_EVENT_NOTIFY) - free(e->event.notify); + case GG_EVENT_NOTIFY: + free(e->event.notify); + break; - if (e->type == GG_EVENT_NOTIFY60) { - int i; + case GG_EVENT_NOTIFY60: + { + int i; - for (i = 0; e->event.notify60[i].uin; i++) - free(e->event.notify60[i].descr); + for (i = 0; e->event.notify60[i].uin; i++) + free(e->event.notify60[i].descr); - free(e->event.notify60); - } + free(e->event.notify60); - if (e->type == GG_EVENT_STATUS60) - free(e->event.status60.descr); + break; + } + + case GG_EVENT_STATUS60: + free(e->event.status60.descr); + break; - if (e->type == GG_EVENT_STATUS) - free(e->event.status.descr); + case GG_EVENT_STATUS: + free(e->event.status.descr); + break; - if (e->type == GG_EVENT_NOTIFY_DESCR) { - free(e->event.notify_descr.notify); - free(e->event.notify_descr.descr); - } + case GG_EVENT_NOTIFY_DESCR: + free(e->event.notify_descr.notify); + free(e->event.notify_descr.descr); + break; - if (e->type == GG_EVENT_DCC_VOICE_DATA) - free(e->event.dcc_voice_data.data); + case GG_EVENT_DCC_VOICE_DATA: + free(e->event.dcc_voice_data.data); + break; - if (e->type == GG_EVENT_PUBDIR50_SEARCH_REPLY || e->type == GG_EVENT_PUBDIR50_READ || e->type == GG_EVENT_PUBDIR50_WRITE) - gg_pubdir50_free(e->event.pubdir50); + case GG_EVENT_PUBDIR50_SEARCH_REPLY: + case GG_EVENT_PUBDIR50_READ: + case GG_EVENT_PUBDIR50_WRITE: + gg_pubdir50_free(e->event.pubdir50); + break; - if (e->type == GG_EVENT_USERLIST) - free(e->event.userlist.reply); + case GG_EVENT_USERLIST: + free(e->event.userlist.reply); + break; - if (e->type == GG_EVENT_IMAGE_REPLY) { - free(e->event.image_reply.filename); - free(e->event.image_reply.image); + case GG_EVENT_IMAGE_REPLY: + free(e->event.image_reply.filename); + free(e->event.image_reply.image); + break; } free(e); @@ -119,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; } @@ -153,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 */ @@ -285,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; @@ -306,7 +324,7 @@ case 0x02: /* richtext */ { - unsigned short len; + uint16_t len; char *buf; if (p + 3 > packet_end) { @@ -314,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; } @@ -361,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; } @@ -443,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"); @@ -454,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); @@ -483,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; } @@ -494,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); } } @@ -557,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)); @@ -616,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); @@ -628,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; @@ -695,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); @@ -753,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); @@ -779,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); @@ -795,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 @@ -837,7 +885,7 @@ case GG_STATE_CONNECTING_HUB: { - char buf[1024], *client; + char buf[1024], *client, *auth; int res = 0, res_size = sizeof(res); const char *host, *appmsg; @@ -890,12 +938,18 @@ #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" - "\r\n", host, appmsg, sess->uin, client, sess->last_sysmsg); + "%s" + "\r\n", host, appmsg, sess->uin, client, sess->last_sysmsg, (auth) ? auth : ""); + + if (auth) + free(auth); free(client); @@ -905,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, @@ -1037,7 +1091,7 @@ if ((tmp = strchr(host, ':'))) { *tmp = 0; - port = atoi(tmp+1); + port = atoi(tmp + 1); } addr.s_addr = inet_addr(host); @@ -1136,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, @@ -1307,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; } @@ -1336,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; @@ -1363,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"); @@ -1374,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; @@ -1399,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; } @@ -1430,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); @@ -1467,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/libgadu-config.h.in =================================================================== --- kopete/protocols/gadu/libgadu/libgadu-config.h.in (.../KDE_3_2_BRANCH/kdenetwork/kopete/protocols/gadu/libgadu) (revision 316997) +++ kopete/protocols/gadu/libgadu/libgadu-config.h.in (.../KDE/3.2/kdenetwork/kopete/protocols/gadu/libgadu) (working copy) @@ -25,6 +25,6 @@ #undef __GG_LIBGADU_HAVE_OPENSSL /* Include file containing uintXX_t declarations. */ -#include +#include #endif /* __GG_LIBGADU_CONFIG_H */ Index: kopete/protocols/gadu/libgadu/pubdir.c =================================================================== --- kopete/protocols/gadu/libgadu/pubdir.c (.../KDE_3_2_BRANCH/kdenetwork/kopete/protocols/gadu/libgadu) (revision 316997) +++ kopete/protocols/gadu/libgadu/pubdir.c (.../KDE/3.2/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 @@ -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; @@ -476,7 +495,7 @@ "Pragma: no-cache\r\n" "\r\n"; - if (!(h = gg_http_connect(GG_APPMSG_HOST, GG_APPMSG_PORT, async, "POST", "/appsvc/regtoken.asp", query))) { + 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; } @@ -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_APPMSG_HOST, GG_APPMSG_PORT, h->async, "GET", path, "Host: " GG_APPMSG_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_2_BRANCH/kdenetwork/kopete/protocols/gadu/libgadu) (revision 316997) +++ kopete/protocols/gadu/libgadu/libgadu.c (.../KDE/3.2/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 @@ -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); @@ -197,18 +199,23 @@ if (pipe(pipes) == -1) return -1; - if ((res = fork()) == -1) + if ((res = fork()) == -1) { + errno2 = errno; + close(pipes[0]); + close(pipes[1]); + errno = errno2; return -1; + } if (!res) { if ((a.s_addr = inet_addr(hostname)) == INADDR_NONE) { - struct hostent *he; + struct in_addr *hn; - if (!(he = gg_gethostbyname(hostname))) + if (!(hn = gg_gethostbyname(hostname))) a.s_addr = INADDR_NONE; else { - memcpy((char*) &a, he->h_addr, sizeof(a)); - free(he); + a.s_addr = hn->s_addr; + free(hn); } } @@ -237,14 +244,16 @@ 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 hostent *he; + struct in_addr *hn; - if (!(he = gg_gethostbyname(d->hostname))) + if (!(hn = gg_gethostbyname(d->hostname))) a.s_addr = INADDR_NONE; else { - memcpy((char*) &a, he->h_addr, sizeof(a)); - free(he); + a.s_addr = hn->s_addr; + free(hn); } } @@ -277,9 +286,9 @@ */ int gg_resolve_pthread(int *fd, void **resolver, const char *hostname) { - struct gg_resolve_pthread_data *d; + struct gg_resolve_pthread_data *d = NULL; pthread_t *tmp; - int pipes[2]; + int pipes[2], new_errno; gg_debug(GG_DEBUG_FUNCTION, "** gg_resolve_pthread(%p, %p, \"%s\");\n", fd, resolver, hostname); @@ -300,20 +309,26 @@ return -1; } - if (!(d = malloc(sizeof(*d))) || !(d->hostname = strdup(hostname))) { + if (!(d = malloc(sizeof(*d)))) { gg_debug(GG_DEBUG_MISC, "// gg_resolve_pthread() out of memory\n"); - free(tmp); - return -1; + 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"); - close(pipes[0]); - close(pipes[1]); - free(tmp); - return -1; + new_errno = errno; + goto cleanup; } gg_debug(GG_DEBUG_MISC, "// gg_resolve_pthread() %p\n", tmp); @@ -323,6 +338,21 @@ *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 @@ -378,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) { @@ -396,8 +426,24 @@ } } else #endif - res = write(sess->fd, buf, length); + { + 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; } @@ -409,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); @@ -439,6 +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 = ECONNRESET; gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() header recv() failed: connection broken\n"); return NULL; } @@ -477,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; @@ -503,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; @@ -558,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 *); @@ -584,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 *); @@ -607,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); @@ -639,7 +690,7 @@ static int gg_session_callback(struct gg_session *s) { if (!s) { - errno = EINVAL; + errno = EFAULT; return -1; } @@ -669,7 +720,7 @@ if (!p) { gg_debug(GG_DEBUG_FUNCTION, "** gg_login(%p);\n", p); - errno = EINVAL; + errno = EFAULT; return NULL; } @@ -684,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; } @@ -703,15 +754,17 @@ 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; - sess->port = (p->server_port) ? p->server_port : GG_DEFAULT_PORT; + 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; @@ -774,14 +827,14 @@ if (!p->server_addr || !p->server_port) { if ((a.s_addr = inet_addr(hostname)) == INADDR_NONE) { - struct hostent *he; + struct in_addr *hn; - if (!(he = gg_gethostbyname(hostname))) { + if (!(hn = gg_gethostbyname(hostname))) { gg_debug(GG_DEBUG_MISC, "// gg_login() host \"%s\" not found\n", hostname); goto fail; } else { - memcpy((char*) &a, he->h_addr, sizeof(a)); - free(he); + a.s_addr = hn->s_addr; + free(hn); } } } else { @@ -791,6 +844,9 @@ 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; @@ -1049,7 +1105,7 @@ #endif if (sess->fd != -1) { - shutdown(sess->fd, 2); + shutdown(sess->fd, SHUT_RDWR); close(sess->fd); sess->fd = -1; } @@ -1086,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); @@ -1098,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; @@ -1148,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); @@ -1157,8 +1224,18 @@ 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 = rindex(filename, '/')) || (tmp = rindex(filename, '\\'))) + while ((tmp = strrchr(filename, '/')) || (tmp = strrchr(filename, '\\'))) filename = tmp + 1; if (strlen(filename) < 1 || strlen(filename) > 1024) { @@ -1166,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); @@ -1293,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); @@ -1363,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); @@ -1378,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]); @@ -1679,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_2_BRANCH/kdenetwork/kopete/protocols/gadu/libgadu) (revision 316997) +++ kopete/protocols/gadu/libgadu/common.c (.../KDE/3.2/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 @@ -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); } @@ -428,28 +441,90 @@ /* * gg_gethostbyname() // funkcja pomocnicza * - * odpowiednik gethostbyname() używający gethostbyname_r(), gdy potrzebna - * jest wielobieżność. chwilowo korzysta ze zwykłego gethostbyname(). + * odpowiednik gethostbyname() troszczący się o współbieżność, gdy mamy do + * dyspozycji funkcję gethostbyname_r(). * * - hostname - nazwa serwera * - * zaalokowany bufor, który należy zwolnić lub NULL w przypadku błędu. + * zwraca wskaźnik na strukturę in_addr, którą należy zwolnić. */ -struct hostent *gg_gethostbyname(const char *hostname) +struct in_addr *gg_gethostbyname(const char *hostname) { - /* XXX użyć gethostbyname_r() */ + struct in_addr *addr = NULL; - struct hostent *hp, *hp2; +#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))) - return NULL; + goto cleanup; - if (!(hp2 = calloc(1, sizeof(*hp)))) - return NULL; + memcpy(addr, hp->h_addr, sizeof(struct in_addr)); - memcpy(hp2, hp, sizeof(*hp)); + return addr; + +cleanup: + if (addr) + free(addr); - return hp2; + return NULL; +#endif } #ifdef ASSIGN_SOCKETS_TO_THREADS @@ -493,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 */ @@ -543,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); @@ -601,7 +675,7 @@ { char *res, *save, *foo, val; const char *end; - int index = 0; + unsigned int index = 0; if (!buf) return NULL; @@ -694,8 +768,8 @@ */ static void gg_crc32_make_table() { - uint32_t h = 0; - int i, j; + uint32_t h = 1; + unsigned int i, j; memset(gg_crc32_table, 0, sizeof(gg_crc32_table)); @@ -725,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_2_BRANCH/kdenetwork/kopete/protocols/gadu/libgadu) (revision 316997) +++ kopete/protocols/gadu/libgadu/compat.h (.../KDE/3.2/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_2_BRANCH/kdenetwork/kopete/protocols/gadu/libgadu) (revision 316997) +++ kopete/protocols/gadu/libgadu/dcc.c (.../KDE/3.2/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 @@ -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_2_BRANCH/kdenetwork/kopete/protocols/gadu/libgadu) (revision 316997) +++ kopete/protocols/gadu/libgadu/pubdir50.c (.../KDE/3.2/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 @@ -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; } Index: kopete/protocols/gadu/libgadu/libgadu.h =================================================================== --- kopete/protocols/gadu/libgadu/libgadu.h (.../KDE_3_2_BRANCH/kdenetwork/kopete/protocols/gadu/libgadu) (revision 316997) +++ kopete/protocols/gadu/libgadu/libgadu.h (.../KDE/3.2/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,6 +33,10 @@ extern "C" { #endif +#ifdef HAVE_STDINT_H +#include +#endif + #include #include #include @@ -52,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 */ \ @@ -106,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 */ @@ -145,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() */ @@ -260,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 */ @@ -345,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 */ }; @@ -495,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 */ @@ -517,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 */ @@ -743,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 @@ -808,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 @@ -903,7 +911,7 @@ char *gg_get_line(char **ptr); int gg_connect(void *addr, int port, int async); -struct hostent *gg_gethostbyname(const char *hostname); +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); @@ -935,11 +943,12 @@ #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_LIBGADU_VERSION "1.4.20040512" +#define GG_ERA_OMNIX_MASK 0x04000000 +#define GG_LIBGADU_VERSION "CVS" #define GG_DEFAULT_DCC_PORT 1550 @@ -1200,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 {