diff -urN jit-1.1.6.orig/jabberd/base/base_accept.c jit-1.1.6/jabberd/base/base_accept.c --- jit-1.1.6.orig/jabberd/base/base_accept.c Sun Mar 16 12:25:33 2003 +++ jit-1.1.6/jabberd/base/base_accept.c Tue Sep 14 00:58:23 2004 @@ -58,6 +58,7 @@ queue q_start,q_end; dpacket dplast; pthread_mutex_t sem; + int xdb_rethread; } *accept_instance, _accept_instance; @@ -213,11 +214,11 @@ /* END LOG */ /* xdb packet sends through socket goes to mtq */ - if ((ai->dplast) && (ai->dplast->type == p_XDB)) { - /* XXX mtq_send */ - deliver(ai->dplast, ai->i); - ai->dplast = NULL; - return; + if ((ai->dplast) && (ai->xdb_rethread) && (ai->dplast->type == p_XDB)) { + /* XXX mtq_send */ + deliver(ai->dplast, ai->i); + ai->dplast = NULL; + return; } else { deliver(ai->dplast, ai->i); @@ -377,8 +378,14 @@ inst->port = port; inst->log = j_atoi(xmlnode_get_tag_data(x, "log"),-1); inst->timeout = j_atoi(xmlnode_get_tag_data(x, "timeout"),30); /* 30 sec */ + inst->xdb_rethread = xmlnode_get_tag(x, "xdb_thread") ? 1 : 0; pthread_mutex_init(&(inst->sem),NULL); + if (inst->xdb_rethread) { + log_alert(ZONE,"xdb requests will be moved to mtq thread in accept instance %s", + id->id); + } + /* Start a new listening thread and associate this tag with it */ if(mio_listen(inst->port, inst->ip, base_accept_process_xml, (void*)inst, NULL, mio_handlers_new(NULL, NULL, MIO_XML_PARSER)) == NULL) { @@ -404,6 +411,3 @@ log_debug(ZONE,"base_accept loading...\n"); register_config("accept",base_accept_config,NULL); } - - - diff -urN jit-1.1.6.orig/jabberd/base/base_connect.c jit-1.1.6/jabberd/base/base_connect.c --- jit-1.1.6.orig/jabberd/base/base_connect.c Sat Feb 1 02:21:10 2003 +++ jit-1.1.6/jabberd/base/base_connect.c Tue Sep 14 00:58:23 2004 @@ -72,9 +72,10 @@ pool mempool; /* Memory pool for this struct */ instance inst; /* Matching instance for this connection */ char * event; /* event, informs when connection is opened, closed */ + int xdb_rethread; pthread_mutex_t sem; queue q_start,q_end; - dpacket dplast; /* special circular reference detector */ + dpacket dplast; /* special circular reference detector */ } *conn_info, _conn_info; /* conn_write_buf - stores a dpacket that needs to be written to the socket */ @@ -164,11 +165,11 @@ cur = xstream_header("jabber:component:accept", ci->inst->id, NULL); mio_write(m, NULL, xstream_header_char(cur), -1); xmlnode_free(cur); - + return; - - case MIO_XML_ROOT: - /* Extract stream ID and generate a key to hash */ + + case MIO_XML_ROOT: + /* Extract stream ID and generate a key to hash */ shahash_r(spools(x->p, xmlnode_get_attrib(x, "id"), ci->secret, x->p), hashbuf); /* Build a handshake packet */ @@ -184,38 +185,48 @@ case MIO_XML_NODE: /* Only deliver packets after the connection is auth'd */ - if (ci->state == conn_AUTHD) + if (ci->state == conn_AUTHD) { - if (j_strcmp(xmlnode_get_name(x), "endconnection") == 0){ - log_alert(ZONE,"Server is closing. stop sending to him"); - xmlnode_free(x); - ci->state = conn_CLOSED; - - if (ci->event != NULL) { - xmlnode cur; - - log_debug(ZONE,"event disconnection"); - - cur = xmlnode_new_tag("route"); - xmlnode_put_attrib(cur,"type","disconnected"); - xmlnode_put_attrib(cur,"to",ci->event); - xmlnode_put_attrib(cur,"from",ci->inst->id); - deliver(dpacket_new(cur),ci->inst); - } - - - return; - } - else { + if (j_strcmp(xmlnode_get_name(x), "endconnection") == 0){ + log_alert(ZONE,"Server is closing. stop sending to him"); + xmlnode_free(x); + ci->state = conn_CLOSED; + + if (ci->event != NULL) { + xmlnode cur; + + log_debug(ZONE,"event disconnection"); + + cur = xmlnode_new_tag("route"); + xmlnode_put_attrib(cur,"type","disconnected"); + xmlnode_put_attrib(cur,"to",ci->event); + xmlnode_put_attrib(cur,"from",ci->inst->id); + deliver(dpacket_new(cur),ci->inst); + } + + + return; + } + else { ci->dplast = dpacket_new(x); /* store the addr of the dpacket we're sending to detect circular delevieries */ - deliver(ci->dplast, ci->inst); - ci->dplast = NULL; - return; - } - } + if ((ci->dplast) && (ci->xdb_rethread) && (ci->dplast->type == p_XDB)) { + /* XXX mtq_send */ + deliver(ci->dplast, ci->inst); + ci->dplast = NULL; + return; + } + else { + deliver(ci->dplast, ci->inst); + ci->dplast = NULL; + return; + } + + } + } + /* If a handshake packet is recv'd from the server, we have successfully auth'd -- go ahead and update the connection state */ - if (j_strcmp(xmlnode_get_name(x), "handshake") == 0) + if (j_strcmp(xmlnode_get_name(x), "handshake") == 0) { /* Flush all packets queued up for delivery */ log_debug(ZONE,"flush old packets"); @@ -330,8 +341,13 @@ ci->hostport = port; ci->secret = pstrdup(ci->mempool, secret); ci->event = xmlnode_get_tag_data(x, "event"); + ci->xdb_rethread = xmlnode_get_tag(x, "xdb_thread") ? 1 : 0; pthread_mutex_init(&(ci->sem),NULL); /* sem for queue */ - // ci->write_queue = pth_msgport_create(ci->hostip); + + if (ci->xdb_rethread) { + log_alert(ZONE,"xdb requests will be moved to mtq thread in connect instance %s", + id->id); + } ci->timeout = timeout; ci->tries_left = tries; diff -urN jit-1.1.6.orig/jabberd/heartbeat.c jit-1.1.6/jabberd/heartbeat.c --- jit-1.1.6.orig/jabberd/heartbeat.c Thu Feb 27 13:00:39 2003 +++ jit-1.1.6/jabberd/heartbeat.c Tue Sep 14 00:58:23 2004 @@ -43,31 +43,33 @@ /* master hook for the ring */ beat heartbeat__ring; -pthread_mutex_t heartbeat__sem; -pthread_t heartbeat__t; +SEM_VAR heartbeat__sem; +THREAD_VAR heartbeat__t; void *heartbeat(void *arg) { beat b, b2; result r; - while(1) - { - sleep(1); - - /* run through the ring */ - pthread_mutex_lock(&heartbeat__sem); - - if ( jab_shutdown ) break; - - for(b = heartbeat__ring->next; b != heartbeat__ring; b = b->next) - { + while(1) { + sleep(1); + + /* run through the ring */ + SEM_LOCK(heartbeat__sem); + + if ( jab_shutdown ) break; + + for(b = heartbeat__ring->next; b != heartbeat__ring; b = b->next) { /* beats can fire on a frequency, just keep a counter */ - if(b->last++ == b->freq) - { + if(b->last++ == b->freq) { b->last = 0; + SEM_UNLOCK(heartbeat__sem); + + /* call function */ r = (b->f)(b->arg); + SEM_LOCK(heartbeat__sem); + if(r == r_UNREG) { /* this beat doesn't want to be fired anymore, unlink and free */ b2 = b->prev; @@ -77,12 +79,12 @@ b = b2; /* reset b to accomodate the for loop */ } } - } - pthread_mutex_unlock(&heartbeat__sem); + } + SEM_UNLOCK(heartbeat__sem); } - - pthread_mutex_unlock(&heartbeat__sem); - + + SEM_UNLOCK(heartbeat__sem); + return NULL; } @@ -125,29 +127,6 @@ pthread_mutex_unlock(&heartbeat__sem); } -/* register a function to receive heartbeats - with no sem, use this function in heartbeat thread */ -void register_beat_safe(int freq, beathandler f, void *arg) -{ - beat newb; - - if(freq <= 0 || f == NULL || heartbeat__ring == NULL) return; /* uhh, probbably don't want to allow negative heartbeats, since the counter will count infinitly to a core */ - - - /* setup the new beat */ - newb = new_beat(); - newb->f = f; - newb->arg = arg; - newb->freq = freq; - newb->last = 0; - - /* insert into global ring */ - newb->next = heartbeat__ring->next; - heartbeat__ring->next = newb; - newb->prev = heartbeat__ring; - newb->next->prev = newb; -} - /* start up the heartbeat */ void heartbeat_birth(void) @@ -156,14 +135,10 @@ heartbeat__ring = new_beat(); heartbeat__ring->next = heartbeat__ring->prev = heartbeat__ring; - pthread_mutex_init(&heartbeat__sem,NULL); + SEM_INIT(heartbeat__sem); /* start the thread */ - // pthread_attr_init(&attr); - // pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - // pthread_create(&thread, &attr, heartbeat, NULL); pthread_create(&heartbeat__t, NULL, heartbeat, NULL); - // pthread_attr_destroy(&attr); } void heartbeat_death(void) diff -urN jit-1.1.6.orig/jabberd/jabberd.c jit-1.1.6/jabberd/jabberd.c --- jit-1.1.6.orig/jabberd/jabberd.c Fri Feb 28 19:50:26 2003 +++ jit-1.1.6/jabberd/jabberd.c Tue Sep 14 00:58:23 2004 @@ -182,7 +182,7 @@ /* were there any bad parameters? */ if(help) { - fprintf(stderr,"Usage:\njabberd &\n Optional Parameters:\n -c\t\t configuration file\n -D\t\tenable debug output\n -H\t\tlocation of home folder\n -v\t\tserver version\n -V\t\tserver version -d\t\trun as demon -u\t\tchange user and group\n"); + fprintf(stderr,"Usage:\njabberd &\n Optional Parameters:\n -c\t\t configuration file\n -D\t\tenable debug output\n -H\t\tlocation of home folder\n -v\t\tserver version\n -V\t\tserver version\n -d\t\trun as demon\n -u\t\tchange user and group\n"); exit(0); } @@ -262,9 +262,11 @@ #ifdef POOL_DEBUG #warning Compiling in debug mode static int counter=0; - if (!(counter++%100)) pool_stat(1); //Co 60 s + if (!(counter++%100)) pool_stat(1); //Every 60 s + Sleep(1000); +#else + Sleep(1000); #endif - Sleep(100); } log_alert(NULL,"Recieved Kill. Jabberd shutting down."); diff -urN jit-1.1.6.orig/jabberd/jabberd.h jit-1.1.6/jabberd/jabberd.h --- jit-1.1.6.orig/jabberd/jabberd.h Mon Jun 2 12:23:50 2003 +++ jit-1.1.6/jabberd/jabberd.h Tue Sep 14 00:58:23 2004 @@ -47,7 +47,7 @@ #include #include -#include "util.h" +#include #ifdef HAVE_SSL #include @@ -61,7 +61,7 @@ extern "C" { #endif -#define VERSION "Jabberd 1.1.0 stable / with real threads / by Lukas Karwacki" +#define VERSION "Jabberd 1.1.2 stable / with real threads / by Lukas Karwacki" /* packet types */ typedef enum { p_NONE, p_NORM, p_XDB, p_LOG, p_ROUTE } ptype; @@ -132,7 +132,6 @@ void unregister_instance(instance i, char *host); /* disassociate an id with a hostname for that packet type */ void register_phandler(instance id, order o, phandler f, void *arg); /* register a function to handle delivery for this instance */ void register_beat(int freq, beathandler f, void *arg); /* register the function to be called from the heartbeat, freq is how often, <= 0 is ignored */ -void register_beat_safe(int freq, beathandler f, void *arg); /* for heartbeat thread */ typedef void(*shutdown_func)(void*arg); void register_shutdown(shutdown_func f,void *arg); /* register to be notified when the server is shutting down */ @@ -223,7 +222,8 @@ _mtqqueue queue[MTQ_QUEUE_LONG]; volatile int dl; /* number of actions to do */ int length; /* length of the queue */ - pthread_mutex_t sem; + SEM_VAR sem; + COND_VAR cond; volatile int users_count; /* number of users in this queue */ } *mtq, _mtq; @@ -250,6 +250,7 @@ /* MIO */ /* struct to handle the write queue */ +#ifndef NO_MIO typedef enum { queue_XMLNODE, queue_CDATA } mio_queue_type; typedef struct mio_wb_q_st { @@ -401,6 +402,7 @@ /* connects to an ip */ void mio_connect(char *host, int port, void *cb, void *cb_arg, int timeout, mio_connect_func f, mio_handlers mh); +void mio_connect_bind(char *host, int port, void *cb, void *cb_arg, int timeout, mio_connect_func f, mio_handlers mh, char *bind); /* starts listening on a port/ip, returns NULL if failed to listen */ mio mio_listen(int port, char *sourceip, void *cb, void *cb_arg, mio_accept_func f, mio_handlers mh); @@ -412,6 +414,8 @@ /* some nice api utilities */ #define mio_pool(m) (m->p) #define mio_ip(m) (m->ip) + +#endif typedef unsigned long DWORD; diff -urN jit-1.1.6.orig/jabberd/lib/lib.h jit-1.1.6/jabberd/lib/lib.h --- jit-1.1.6.orig/jabberd/lib/lib.h Fri May 30 16:10:24 2003 +++ jit-1.1.6/jabberd/lib/lib.h Tue Sep 14 00:58:23 2004 @@ -650,6 +650,9 @@ #define NS_ENVELOPE "jabber:x:envelope" #define NS_EXPIRE "jabber:x:expire" #define NS_XHTML "http://www.w3.org/1999/xhtml" +#define NS_DISCO_ITEMS "http://jabber.org/protocol/disco#items" +#define NS_DISCO_INFO "http://jabber.org/protocol/disco#info" + #define NS_XDBGINSERT "jabber:xdb:ginsert" #define NS_XDBNSLIST "jabber:xdb:nslist" diff -urN jit-1.1.6.orig/jabberd/mio.c jit-1.1.6/jabberd/mio.c --- jit-1.1.6.orig/jabberd/mio.c Thu Apr 24 13:02:30 2003 +++ jit-1.1.6/jabberd/mio.c Tue Sep 14 00:58:23 2004 @@ -34,7 +34,9 @@ * --------------------------------------------------------------------------*/ +#ifndef NODEBUG #define NODEBUG +#endif #include @@ -64,6 +66,8 @@ pthread_t t; int timeout; int connected; + /** bind address */ + char *bind; } _connect_data, *connect_data; /* global object */ @@ -447,16 +451,26 @@ return NULL; } - if(xmlnode_get_tag_data(greymatter__, "io/bind") != NULL) - { - struct sockaddr_in sa; - sa.sin_family = AF_INET; - sa.sin_port = 0; - inet_aton(xmlnode_get_tag_data(greymatter__, "io/bind"), &sa.sin_addr); - bind(new->fd, (struct sockaddr*)&sa, sizeof(struct sockaddr_in)); - } - - + if (cd->bind) { + struct sockaddr_in sa; + sa.sin_family = AF_INET; + sa.sin_port = 0; + inet_aton(cd->bind, &sa.sin_addr); + if (bind(new->fd, (struct sockaddr*)&sa, sizeof(struct sockaddr_in)) < 0) { + log_alert("bind","Error %d",errno); + } + } + else + if (xmlnode_get_tag_data(greymatter__, "io/bind") != NULL) { + struct sockaddr_in sa; + sa.sin_family = AF_INET; + sa.sin_port = 0; + inet_aton(xmlnode_get_tag_data(greymatter__, "io/bind"), &sa.sin_addr); + if (bind(new->fd, (struct sockaddr*)&sa, sizeof(struct sockaddr_in)) < 0) { + log_alert("bind","io/bind Error %d",errno); + } + } + flags = fcntl(new->fd, F_GETFL, 0); flags |= O_NONBLOCK; fcntl(new->fd, F_SETFL, flags); @@ -599,32 +613,13 @@ FD_ZERO(&all_wfds); FD_ZERO(&all_rfds); - sleep(1); + Sleep(1000); - /* loop forever -- will only exit when - * mio__data->master__list is NULL */ + /* loop forever -- will only exit when mio__data->shutdown == 1 */ while (1) { /* give same CPU to another threads , may be usleep(500) */ - Sleep(1); - - /* time */ - time = timeGetTime(); - - if ((time-karma_time) > mio__data->karma_time) - { - karma_time = time; - - if ((mtq__master)&&(mtq__master->all[0]->mtq)) - { - /* incease karma only when queue is not long */ - if (mtq__master->all[0]->mtq->dl < 100) - karma = 1; - } - else - karma = 1; - } - + // Sleep(1); rfds = all_rfds; wfds = all_wfds; @@ -633,12 +628,29 @@ break; /* wait for a socket event */ - tv.tv_sec=0; + tv.tv_sec=1; tv.tv_usec=0; retval = select(maxfd+1, &rfds, &wfds, NULL, &tv); + /* time */ + time = timeGetTime(); + + if ((time-karma_time) > mio__data->karma_time) { + karma_time = time; + + if ((mtq__master)&&(mtq__master->all[0]->mtq)){ + /* incease karma only when first queue is not long */ + if (mtq__master->all[0]->mtq->dl < 100) + karma = 1; + } + else + karma = 1; + + log_debug(ZONE,"karma %d",karma); + } + - pthread_mutex_lock(&(mio__data->sem)); + SEM_LOCK(mio__data->sem); /* loop through the sockets, check for stuff to do */ for(cur = mio__data->master__list; cur != NULL;) @@ -759,45 +771,47 @@ /* if we need to write to this socket */ if(FD_ISSET(cur->fd, &wfds)) { - if (cur->queue != NULL) - { - int ret; - - /* write the current buffer */ - ret = _mio_write_dump(cur); - - /* if an error occured */ - if(ret == -1) - { - mio_close(cur); - continue; /* loop on the same socket to kill it for real */ - } - /* if we are done writing */ - else if(ret == 0) + if (cur->queue != NULL) + { + int ret; + + /* write the current buffer */ + ret = _mio_write_dump(cur); + + /* if an error occured */ + if(ret == -1) + { + mio_close(cur); + continue; /* loop on the same socket to kill it for real */ + } + /* if we are done writing */ + else if(ret == 0) FD_CLR(cur->fd, &all_wfds); - /* if we still have more to write */ - else if(ret == 1) + /* if we still have more to write */ + else if(ret == 1) FD_SET(cur->fd, &all_wfds); - - /* we may have wanted the socket closed after this operation */ - if(cur->state == state_CLOSE) + + /* we may have wanted the socket closed after this operation */ + if(cur->state == state_CLOSE) continue; /* loop on the same socket to kill it for real */ - } + } + else { + FD_CLR(cur->fd, &all_wfds); + } } - else if ((cur->queue != NULL)&&(!FD_ISSET(cur->fd, &all_wfds))) - { - FD_SET(cur->fd, &all_wfds); - } - + else if ((cur->queue != NULL)&&(!FD_ISSET(cur->fd, &all_wfds))) { + FD_SET(cur->fd, &all_wfds); + } + /* check the next socket */ cur = cur->next; } - pthread_mutex_unlock(&(mio__data->sem)); + SEM_UNLOCK(mio__data->sem); - if (karma == 1) karma = 0; - - }/* while(1) end */ + if (karma == 1) karma = 0; + + } /* while(1) end */ return NULL; } @@ -1029,6 +1043,12 @@ m->tail = new; pthread_mutex_unlock(&(m->sem)); + + + /* if an error occured */ + if(_mio_write_dump(m) == -1) { + mio_close(m); + } } @@ -1121,6 +1141,48 @@ /* no xmlnodes found */ pthread_mutex_unlock(&(m->sem)); return NULL; +} + +/* + * request to connect to a remote host + */ + +void mio_connect_bind(char *host, int port, void *cb, void *cb_arg, int timeout, mio_connect_func f, mio_handlers mh,char *bind) +{ + connect_data cd = NULL; + pool p = NULL; + pthread_attr_t attr; + + + if(host == NULL || port == 0) + return; + + if(timeout <= 0) + timeout = 30; + + if(f == NULL) + f = MIO_RAW_CONNECT; + + if(mh == NULL) + mh = mio_handlers_new(NULL, NULL, NULL); + + p = pool_heap(4096); + cd = pmalloco(p, sizeof(_connect_data)); + cd->p = p; + cd->ip = pstrdup(p, host); + cd->port = port; + cd->cb = cb; + cd->cb_arg = cb_arg; + cd->cf = f; + cd->mh = mh; + cd->timeout = timeout; + cd->bind = pstrdup(p,bind); + + + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + pthread_create(&cd->t, &attr, _mio_connect, (void*)cd); + pthread_attr_destroy(&attr); } /* diff -urN jit-1.1.6.orig/jabberd/mio_xml.c jit-1.1.6/jabberd/mio_xml.c --- jit-1.1.6.orig/jabberd/mio_xml.c Tue Dec 17 16:40:09 2002 +++ jit-1.1.6/jabberd/mio_xml.c Tue Sep 14 00:58:23 2004 @@ -142,14 +142,12 @@ nul += 4; bufsz = bufsz - (nul - buf); buf = nul; - mio_write(m,NULL,"HTTP/1.0 200 Ok -Server: jabber/xmlstream-hack-0.1 -Expires: Fri, 10 Oct 1997 10:10:10 GMT -Pragma: no-cache -Cache-control: private -Connection: close - -",-1); + mio_write(m,NULL,"HTTP/1.0 200 Ok\r\n" + "Server: jabber/xmlstream-hack-0.1\r\n" + "Expires: Fri, 10 Oct 1997 10:10:10 GMT\r\n" + "Pragma: no-cache\r\n" + "Cache-control: private\r\n" + "Connection: close\r\n\r\n",-1); m->type = type_NORMAL; } diff -urN jit-1.1.6.orig/jabberd/mtq.c jit-1.1.6/jabberd/mtq.c --- jit-1.1.6.orig/jabberd/mtq.c Wed Apr 9 16:10:49 2003 +++ jit-1.1.6/jabberd/mtq.c Tue Sep 14 00:58:23 2004 @@ -36,7 +36,7 @@ mtqmaster mtq__master = NULL; -int mtq__shutdown=0; +volatile int mtq__shutdown = 0; void mtq_cleanup(void *arg) { @@ -126,47 +126,43 @@ while(1) { - if (t->mtq->last == NULL ) { - Sleep(1); - } + /* check if something to resolv */ + SEM_LOCK(t->mtq->sem); + if (t->mtq->last == NULL) { + COND_WAIT(t->mtq->cond,t->mtq->sem); + } + /* get element */ + mq = t->mtq->last; + if (mq != NULL) { + mqcall.f = mq->f; + mqcall.arg = mq->arg; - if (t->mtq->last != NULL) { - log_debug("MTQ","process call"); - - while ( t->mtq->last != NULL ) { - pthread_mutex_lock(&(t->mtq->sem)); - mq = t->mtq->last; - mqcall.f = mq->f; - mqcall.arg = mq->arg; - - /* remove call from list */ - t->mtq->last = t->mtq->last->prev; - t->mtq->dl--; - - /* add mq to list */ - mq->prev = NULL; - - if (t->mtq->free_last == NULL) - t->mtq->free_last = mq; - else - t->mtq->free_first->prev = mq; - - t->mtq->free_first = mq; - - /* exec call */ - pthread_mutex_unlock(&(t->mtq->sem)); - - log_debug("MTQ","call long=%d",t->mtq->dl); - - (*(mqcall.f))(mqcall.arg); - } - } - + /* remove call from list */ + t->mtq->last = t->mtq->last->prev; + t->mtq->dl--; - if ((mtq__shutdown == 1) && (t->mtq->last == NULL)) - break; + /* add mq to list */ + mq->prev = NULL; + + if (t->mtq->free_last == NULL) + t->mtq->free_last = mq; + else + t->mtq->free_first->prev = mq; + t->mtq->free_first = mq; + } + + SEM_UNLOCK(t->mtq->sem); + + if (mq != NULL) { + (*(mqcall.f))(mqcall.arg); + } + else { + /* mq is NULL here, so no more packets in queue */ + if (mtq__shutdown == 1) + break; + } } /* loop end */ log_debug("mtq","%X ending mq=%d",t->thread,t->mtq); @@ -207,7 +203,8 @@ for(n=0;n < MTQ_THREADS;n++) { t = mtq__master->all[n]; - + /* signal exit */ + COND_SIGNAL(t->mtq->cond); /* wait */ pthread_join(t->thread,&ret); } @@ -253,14 +250,14 @@ log_debug(ZONE,"mtq_send insert into mtq=%p",mtq); /* lock operation on queue */ - pthread_mutex_lock(&(mtq->sem)); + SEM_LOCK(mtq->sem); /* find free memory */ mq = mtq->free_last; if (mq == NULL) { - while ((mq = malloc(sizeof(_mtqqueue)))==NULL) Sleep(1); + while ((mq = malloc(sizeof(_mtqqueue)))==NULL) Sleep(1000); /* it means new malloc maybe we should free this mq later ? */ log_alert(ZONE,"MTQ new queue malloc"); @@ -286,7 +283,9 @@ mtq->first = mq; - pthread_mutex_unlock(&(mtq->sem)); + COND_SIGNAL(mtq->cond); + + SEM_UNLOCK(mtq->sem); } void mtq_init() { @@ -329,9 +328,17 @@ mtq->length++; } - pthread_mutex_init(&(t->mtq->sem),NULL); + SEM_INIT(t->mtq->sem); + COND_INIT(t->mtq->cond); pthread_create(&(t->thread), NULL, mtq_main, (void *)t); mtq__master->all[n] = t; /* assign it as available */ } } + + + + + + + diff -urN jit-1.1.6.orig/jabberd/util.h jit-1.1.6/jabberd/util.h --- jit-1.1.6.orig/jabberd/util.h Thu Feb 27 16:13:48 2003 +++ jit-1.1.6/jabberd/util.h Tue Sep 14 00:58:23 2004 @@ -1,5 +1,4 @@ - #ifdef OTHER #warning Compiling without safe INC and DEC #define THREAD_INC(X); X++; @@ -19,6 +18,7 @@ #define SEM_VAR pthread_mutex_t #define COND_VAR pthread_cond_t +#define THREAD_VAR pthread_t #define SEM_INIT(x) pthread_mutex_init(&x,NULL) #define SEM_LOCK(x) pthread_mutex_lock(&x) #define SEM_UNLOCK(x) pthread_mutex_unlock(&x) @@ -26,4 +26,12 @@ #define COND_INIT(x) pthread_cond_init(&x,NULL) #define COND_SIGNAL(x) pthread_cond_signal(&x) #define COND_WAIT(x,s) pthread_cond_wait(&x,&s) +#define THREAD_CREATE(t,f,a) pthread_create(&t, NULL, f, a) +#define THREAD_JOIN(t,r) pthread_join(t,&r) +#define THREAD_CREATE_DETACHED(t,f,a) { \ +pthread_attr_t attr;\ +pthread_attr_init(&attr);\ +pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);\ +pthread_create(&t, &attr, f, a);\ +pthread_attr_destroy(&attr); } diff -urN jit-1.1.6.orig/jabberd/wphash.c jit-1.1.6/jabberd/wphash.c --- jit-1.1.6.orig/jabberd/wphash.c Thu May 29 13:56:27 2003 +++ jit-1.1.6/jabberd/wphash.c Tue Sep 14 00:58:23 2004 @@ -8,7 +8,7 @@ * --------------------------------------------------------------------------*/ -#include +#include "jabberd.h" /* Generates a hash code for a string. * This function uses the ELF hashing algorithm as reprinted in @@ -56,6 +56,17 @@ return xnew; } +wpxht wpxhash_new_pool(int prime, pool p) +{ + wpxht xnew; + + xnew = pmalloco(p, sizeof(_wpxht) + sizeof(wpxhn)*prime); + xnew->prime = prime; + xnew->p = p; + return xnew; +} + + /* init + alloc extra memory */ wpxht wpxhash_new_extra(int prime, int extra) { @@ -114,7 +125,7 @@ ((wpxhn)val)->wpnext = n->wpnext; ((wpxhn)val)->wpkey = key; - return 1; + return 2; } lastn->wpnext = (wpxhn)val; @@ -123,14 +134,25 @@ return 1; } - - void *wpxhash_get(wpxht h, const char *key) { if(h == NULL || key == NULL) return NULL; return _wpxhash_node_get(h, key, _wpxhasher(key)); +} + +char *wpxhash_get_value(wpxht h, const char *key) { + wpxhn_char a; + + if(h == NULL || key == NULL) + return NULL; + + a = (wpxhn_char) _wpxhash_node_get(h, key, _wpxhasher(key)); + if (!a) + return NULL; + else + return a->value; } diff -urN jit-1.1.6.orig/jabberd/wphash.h jit-1.1.6/jabberd/wphash.h --- jit-1.1.6.orig/jabberd/wphash.h Wed May 28 14:22:45 2003 +++ jit-1.1.6/jabberd/wphash.h Tue Sep 14 00:58:23 2004 @@ -18,6 +18,12 @@ WPHASH_BUCKET; } *wpxhn, _wpxhn; +typedef struct wpxhn_char_struct +{ + WPHASH_BUCKET; + char *value; +} *wpxhn_char, _wpxhn_char; + typedef struct wpxht_struct { pool p; @@ -26,9 +32,11 @@ } *wpxht, _wpxht; wpxht wpxhash_new(int prime); +wpxht wpxhash_new_pool(int prime,pool p); wpxht wpxhash_new_extra(int prime, int extra); int wpxhash_put(wpxht h, const char *key, void *val); void *wpxhash_get(wpxht h, const char *key); +char *wpxhash_get_value(wpxht h, const char *key); void wpxhash_zap(wpxht h, const char *key); void wpxhash_free(wpxht h); typedef int (*wpghash_walker)(void *user_data, const void *key, void *data); diff -urN jit-1.1.6.orig/jit/jit/contact.c jit-1.1.6/jit/jit/contact.c --- jit-1.1.6.orig/jit/jit/contact.c Tue Apr 29 14:46:31 2003 +++ jit-1.1.6/jit/jit/contact.c Tue Sep 14 00:58:23 2004 @@ -419,8 +419,7 @@ contact to the user's roster if it was not present */ x = jutil_presnew(JPACKET__SUBSCRIBED,jid_full(s->id),NULL); xmlnode_put_attrib(x,"from",jid_full(it_uin2jid(xmlnode_pool(x),c->uin,s->from->server))); - if(name != NULL) - xmlnode_put_attrib(x,"name",it_convert_windows2utf8(xmlnode_pool(x),name)); + if(name != NULL) xmlnode_put_attrib(x,"name",name); it_deliver(s->ti,x); } diff -urN jit-1.1.6.orig/jit/jit/icqtransport.c jit-1.1.6/jit/jit/icqtransport.c --- jit-1.1.6.orig/jit/jit/icqtransport.c Tue Apr 29 14:34:51 2003 +++ jit-1.1.6/jit/jit/icqtransport.c Tue Sep 14 00:58:23 2004 @@ -16,6 +16,7 @@ result it_sessions_check(void * arg); void it_shutdown(void *arg); +iconv_t _ucs2utf; iconv_t _win2utf; iconv_t _utf2win; @@ -60,6 +61,8 @@ log_debug(i->id,"Charset not specified, set default to %s ",DEFAULT_CHARSET); ti->charset = pstrdup(p,DEFAULT_CHARSET); } + + _ucs2utf = iconv_open("UTF-8","UCS-2BE"); _win2utf = iconv_open("UTF-8",ti->charset); if (_win2utf==(iconv_t)-1) { diff -urN jit-1.1.6.orig/jit/jit/icqtransport.h jit-1.1.6/jit/jit/icqtransport.h --- jit-1.1.6.orig/jit/jit/icqtransport.h Mon Jun 2 14:06:51 2003 +++ jit-1.1.6/jit/jit/icqtransport.h Tue Sep 14 00:58:23 2004 @@ -290,6 +290,10 @@ void it_iq_gateway_set(session s, jpacket jp); void it_iq_browse_server(iti ti, jpacket jp); void it_iq_browse_user(session s, jpacket jp); +void it_iq_disco_info_server(iti ti, jpacket jp); +void it_iq_disco_info_user(session s, jpacket jp); +void it_iq_disco_items_server(iti ti, jpacket jp); +void it_iq_disco_items_user(session s, jpacket jp); void it_save_contacts(session s); @@ -313,6 +317,7 @@ char *it_convert_utf82windows(pool p, const char *utf8_str); char *it_convert_windows2utf8(pool p, const char *windows_str); +char *it_convert_ucs2utf8(pool p, unsigned int len, const char ucs2_str[]); jid it_xdb_id(pool p, jid id, char *server); void it_xdb_convert(iti ti, char *user, jid nid); diff -urN jit-1.1.6.orig/jit/jit/iq.c jit-1.1.6/jit/jit/iq.c --- jit-1.1.6.orig/jit/jit/iq.c Tue Apr 29 15:03:53 2003 +++ jit-1.1.6/jit/jit/iq.c Tue Sep 14 00:58:23 2004 @@ -29,6 +29,10 @@ void it_iq_gateway_set(session s, jpacket jp); void it_iq_browse_server(iti ti, jpacket jp); void it_iq_browse_user(session s, jpacket jp); +void it_iq_disco_info_server(iti ti, jpacket jp); +void it_iq_disco_info_user(session s, jpacket jp); +void it_iq_disco_items_server(iti ti, jpacket jp); +void it_iq_disco_items_user(session s, jpacket jp); void SendSearchUINRequest(session s,UIN_t uin); void SendSearchUsersRequest(session s, @@ -73,6 +77,10 @@ it_iq_gateway_get(s,jp); else if (j_strcmp(ns,NS_BROWSE) == 0) jp->to->user ? it_iq_browse_user(s,jp) : it_iq_browse_server(s->ti,jp); + else if (j_strcmp(ns,NS_DISCO_INFO) == 0) + jp->to->user ? it_iq_disco_info_user(s,jp) : it_iq_disco_info_server(s->ti,jp); + else if (j_strcmp(ns,NS_DISCO_ITEMS) == 0) + jp->to->user ? it_iq_disco_items_user(s,jp) : it_iq_disco_items_server(s->ti,jp); else if (j_strcmp(ns,NS_VCARD) == 0) jp->to->user ? it_iq_vcard(s,jp) : it_iq_vcard_server(s->ti,jp); else if (j_strcmp(ns,NS_LAST) == 0) @@ -503,6 +511,8 @@ xmlnode_insert_cdata(xmlnode_insert_tag(q,"ns"),NS_REGISTER,-1); xmlnode_insert_cdata(xmlnode_insert_tag(q,"ns"),NS_SEARCH,-1); xmlnode_insert_cdata(xmlnode_insert_tag(q,"ns"),NS_GATEWAY,-1); + xmlnode_insert_cdata(xmlnode_insert_tag(q,"ns"),NS_DISCO_INFO,-1); + xmlnode_insert_cdata(xmlnode_insert_tag(q,"ns"),NS_DISCO_ITEMS,-1); it_deliver(ti,jp->x); } @@ -538,6 +548,131 @@ it_deliver(s->ti,jp->x); } +/** Service Discovery support (JEP-0030) */ +/** Info */ + +void it_iq_disco_info_server(iti ti, jpacket jp) +{ + xmlnode q, x; + + if(xmlnode_get_attrib(xmlnode_get_tag(jp->x, "query"),"node") != NULL) + { + jutil_error(jp->x,TERROR_NOTALLOWED); + it_deliver(ti,jp->x); + return; + } + + q = xmlnode_insert_tag(jutil_iqresult(jp->x),"query"); + xmlnode_put_attrib(q,"xmlns",NS_DISCO_INFO); + + x = xmlnode_insert_tag(q,"identity"); + xmlnode_put_attrib(x,"category","gateway"); + xmlnode_put_attrib(x,"type","icq"); + xmlnode_put_attrib(x,"name",xmlnode_get_tag_data(ti->vcard,"FN")); + + xmlnode_put_attrib(xmlnode_insert_tag(q,"feature"),"var",NS_REGISTER); + xmlnode_put_attrib(xmlnode_insert_tag(q,"feature"),"var",NS_SEARCH); + xmlnode_put_attrib(xmlnode_insert_tag(q,"feature"),"var",NS_VERSION); + xmlnode_put_attrib(xmlnode_insert_tag(q,"feature"),"var",NS_TIME); + xmlnode_put_attrib(xmlnode_insert_tag(q,"feature"),"var",NS_LAST); + + it_deliver(ti,jp->x); +} + +void it_iq_disco_info_user(session s, jpacket jp) +{ + xmlnode q, x; + + if (s->type == stype_register) + { + queue_elem queue; + + queue = pmalloco(jp->p,sizeof(_queue_elem)); + queue->elem = (void *)jp; + + QUEUE_PUT(s->queue,s->queue_last,queue); + return; + } + + if (it_jid2uin(jp->from) == 0) + { + jutil_error(jp->x,TERROR_BAD); + it_deliver(s->ti,jp->x); + return; + } + + if(xmlnode_get_attrib(xmlnode_get_tag(jp->x, "query"),"node") != NULL) + { + jutil_error(jp->x,TERROR_NOTALLOWED); + it_deliver(s->ti,jp->x); + return; + } + + q = xmlnode_insert_tag(jutil_iqresult(jp->x),"query"); + xmlnode_put_attrib(q,"xmlns",NS_DISCO_INFO); + x = xmlnode_insert_tag(q,"identity"); + xmlnode_put_attrib(x,"category","user"); + xmlnode_put_attrib(x,"type","client"); + xmlnode_put_attrib(x,"name", jp->to->user); + + it_deliver(s->ti,jp->x); +} + +/** Service Discovery support (JEP-0030) */ +/** Items */ + +void it_iq_disco_items_server(iti ti, jpacket jp) +{ + xmlnode q; + + if(xmlnode_get_attrib(xmlnode_get_tag(jp->x, "query"),"node") != NULL) + { + jutil_error(jp->x,TERROR_NOTALLOWED); + it_deliver(ti,jp->x); + return; + } + + q = xmlnode_insert_tag(jutil_iqresult(jp->x),"query"); + xmlnode_put_attrib(q,"xmlns",NS_DISCO_ITEMS); + + it_deliver(ti,jp->x); +} + +void it_iq_disco_items_user(session s, jpacket jp) +{ + xmlnode q; + + if (s->type == stype_register) + { + queue_elem queue; + + queue = pmalloco(jp->p,sizeof(_queue_elem)); + queue->elem = (void *)jp; + + QUEUE_PUT(s->queue,s->queue_last,queue); + return; + } + + if (it_jid2uin(jp->from) == 0) + { + jutil_error(jp->x,TERROR_BAD); + it_deliver(s->ti,jp->x); + return; + } + + if(xmlnode_get_attrib(xmlnode_get_tag(jp->x, "query"),"node") != NULL) + { + jutil_error(jp->x,TERROR_NOTALLOWED); + it_deliver(s->ti,jp->x); + return; + } + + q = xmlnode_insert_tag(jutil_iqresult(jp->x),"query"); + xmlnode_put_attrib(q,"xmlns",NS_DISCO_ITEMS); + + it_deliver(s->ti,jp->x); +} + /** Send reply to a version inquiry to Jabber */ void it_iq_version(iti ti, jpacket jp) { @@ -555,7 +690,7 @@ xmlnode_insert_cdata(xmlnode_insert_tag(q,"version"),buf,-1); os = xmlnode_insert_tag(q,"os"); - xmlnode_insert_cdata(os,"Linux System",-1); + xmlnode_insert_cdata(os,"Linux/Unix System",-1); it_deliver(ti,x); } diff -urN jit-1.1.6.orig/jit/jit/message.c jit-1.1.6/jit/jit/message.c --- jit-1.1.6.orig/jit/jit/message.c Thu May 8 18:13:21 2003 +++ jit-1.1.6/jit/jit/message.c Tue Sep 14 00:58:23 2004 @@ -53,9 +53,9 @@ else c = it_contact_get(s,uin); - // if (c == NULL) { - // c = it_unknown_contact_add(s,jp->to->user,uin); - // } + if (c == NULL) { + c = it_contact_add(s,uin); + } if (j_strcmp(jp->to->server,s->ti->sms_id)==0) { /* Send SMS message */ diff -urN jit-1.1.6.orig/jit/jit/server.cpp jit-1.1.6/jit/jit/server.cpp --- jit-1.1.6.orig/jit/jit/server.cpp Mon Feb 17 16:53:01 2003 +++ jit-1.1.6/jit/jit/server.cpp Tue Sep 14 00:58:23 2004 @@ -385,8 +385,8 @@ /* birth day */ cur = c->getHomepageInfo().getBirthDate(); - if (cur.size()) { - snprintf(buf,50,"%d:%d:%d", + if (cur.size() && cur != "Unspecified") { + snprintf(buf,50,"%04d-%02d-%02d", c->getHomepageInfo().birth_year, c->getHomepageInfo().birth_month, c->getHomepageInfo().birth_day); @@ -485,7 +485,7 @@ { unsigned int uh = c->getLanIP(); - sprintf(buf,"IP: %d.%d.%d.%d:%d", (uh >> 24) & 0xff, (uh >> 16) & 0xff, + sprintf(buf,"\n\nIP: %d.%d.%d.%d:%d", (uh >> 24) & 0xff, (uh >> 16) & 0xff, (uh >> 8) & 0xff, uh & 0xff,c->getLanPort()); cur += ( string(buf) ); diff -urN jit-1.1.6.orig/jit/jit/session.c jit-1.1.6/jit/jit/session.c --- jit-1.1.6.orig/jit/jit/session.c Mon May 12 15:07:53 2003 +++ jit-1.1.6/jit/jit/session.c Tue Sep 14 00:58:23 2004 @@ -429,6 +429,11 @@ time(NULL)-s->start_time); } + if ((s->ti->own_roster)&&(s->roster_changed)) { + it_save_contacts(s); + s->roster_changed = 0; + } + /* remove from hash */ SEM_LOCK(s->ti->sessions_sem); wpxhash_zap(s->ti->sessions,jid_full(s->id)); @@ -455,7 +460,7 @@ time(NULL)-s->start_time); /* reconnect if network error or unknown error or turboing */ - if (e.code == 502) { + if (e.code == 502 || e.code==503) { /* if session time > 5 min reset reconnect_count */ if ((time(NULL) - s->start_time) > 60*5) @@ -467,6 +472,11 @@ } else it_session_regerr(s,e); + + if ((s->ti->own_roster)&&(s->roster_changed)) { + it_save_contacts(s); + s->roster_changed = 0; + } /* remove from hash */ SEM_LOCK(s->ti->sessions_sem); diff -urN jit-1.1.6.orig/jit/jit/unknown.c jit-1.1.6/jit/jit/unknown.c --- jit-1.1.6.orig/jit/jit/unknown.c Tue Apr 29 14:19:42 2003 +++ jit-1.1.6/jit/jit/unknown.c Tue Sep 14 00:58:23 2004 @@ -84,6 +84,10 @@ } else if (j_strcmp(ns,NS_BROWSE) == 0) it_iq_browse_server(ti,jp); + else if (j_strcmp(ns,NS_DISCO_INFO) == 0) + it_iq_disco_info_server(ti,jp); + else if (j_strcmp(ns,NS_DISCO_ITEMS) == 0) + it_iq_disco_items_server(ti,jp); else if (j_strcmp(ns,NS_VERSION) == 0) it_iq_version(ti,jp); else if (j_strcmp(ns,NS_TIME) == 0) diff -urN jit-1.1.6.orig/jit/jit/wp_client.cpp jit-1.1.6/jit/jit/wp_client.cpp --- jit-1.1.6.orig/jit/jit/wp_client.cpp Tue Apr 29 14:59:24 2003 +++ jit-1.1.6/jit/jit/wp_client.cpp Tue Sep 14 00:58:23 2004 @@ -146,7 +146,8 @@ } void WPclient::SignalDisconnected(DisconnectedEvent *ev) { - terror e = (terror){0,""}; + terror e; + e = (terror){0,""}; switch(ev->getReason()){ case DisconnectedEvent::FAILED_BADUSERNAME: @@ -230,7 +231,21 @@ if(type_chat) xmlnode_put_attrib(msg,"type","chat"); - xmlnode_insert_cdata(xmlnode_insert_tag(msg,"body"), + log_debug(ZONE,"Message: len->%i encoding->%i text->%s",int((nm->getMessage()).length()), + int(nm->getTextEncoding()),(nm->getMessage()).c_str()); + if (nm->getTextEncoding()==2) // UCS2BE + xmlnode_insert_cdata(xmlnode_insert_tag(msg,"body"), + it_convert_ucs2utf8(xmlnode_pool(msg), + (nm->getMessage()).length(), + (nm->getMessage()).c_str()), + (unsigned int)-1); + else if (nm->getTextEncoding()==8) // UTF-8 + xmlnode_insert_cdata( xmlnode_insert_tag(msg,"body") , + (nm->getMessage()).c_str() , + (unsigned int)-1); + + else // 0==ASCII and 3==locale_encoded will go here. + xmlnode_insert_cdata(xmlnode_insert_tag(msg,"body"), it_convert_windows2utf8(xmlnode_pool(msg), (nm->getMessage()).c_str()), (unsigned int)-1); diff -urN jit-1.1.6.orig/jit/libicq2000/Capabilities.h jit-1.1.6/jit/libicq2000/Capabilities.h --- jit-1.1.6.orig/jit/libicq2000/Capabilities.h Thu Jan 9 15:41:54 2003 +++ jit-1.1.6/jit/libicq2000/Capabilities.h Tue Sep 14 00:58:23 2004 @@ -55,7 +55,9 @@ Empty = 14, TrillianCrypt = 15, APInfo = 16, - ICQUnknown2 = 17 + ICQUTF8 = 17, + MacICQ = 18, + AIMInteroperate = 19 }; private: @@ -81,6 +83,8 @@ bool has_capability_flag(Flag f) const; void Parse(Buffer& b, unsigned short len); + void ParseString(Buffer& b, unsigned short len); + void OutputString(Buffer& b) const; void Output(Buffer& b) const; unsigned short get_length() const; diff -urN jit-1.1.6.orig/jit/libicq2000/ICQ.h jit-1.1.6/jit/libicq2000/ICQ.h --- jit-1.1.6.orig/jit/libicq2000/ICQ.h Thu Jan 9 15:41:54 2003 +++ jit-1.1.6/jit/libicq2000/ICQ.h Tue Sep 14 00:58:23 2004 @@ -151,6 +151,7 @@ std::string m_message; bool m_multi; unsigned int m_foreground, m_background; + Encoding m_encoding; public: NormalICQSubType(bool multi); @@ -169,6 +170,9 @@ void OutputBodyUIN(Buffer& b) const; void ParseBodyUINACK(Buffer& b); void OutputBodyUINACK(Buffer& b) const; + + Encoding getTextEncoding() const; + void setTextEncoding( Encoding e ); unsigned short Length() const; unsigned char getType() const; diff -urN jit-1.1.6.orig/jit/libicq2000/TLV.h jit-1.1.6/jit/libicq2000/TLV.h --- jit-1.1.6.orig/jit/libicq2000/TLV.h Thu Jan 9 15:41:54 2003 +++ jit-1.1.6/jit/libicq2000/TLV.h Tue Sep 14 00:58:23 2004 @@ -485,6 +485,9 @@ void ParseValue(Buffer& b); }; + const unsigned short MESSAGETEXT_FLAG1_UCS2 = 0x02; + const unsigned short MESSAGETEXT_FLAG1_LOCALE = 0x03; + class MessageTextTLV : public InTLV { protected: std::string m_message; @@ -496,15 +499,22 @@ std::string getMessage() { return m_message; } unsigned short getFlag1() { return m_flag1; } - unsigned short getFlag2() { return m_flag1; } + unsigned short getFlag2() { return m_flag2; } void ParseValue(Buffer& b); unsigned short Type() const { return TLV_MessageText; } unsigned short Length() const { return 0; } }; + class MessageCapsTLV : public StringTLV { + public: + MessageCapsTLV() { } + unsigned short Type() const { return TLV_Unknown0501; } + }; + class MessageDataTLV : public InTLV { MessageTextTLV mttlv; + std::string caps; public: MessageDataTLV(); @@ -512,6 +522,7 @@ std::string getMessage() { return mttlv.getMessage(); } unsigned short getFlag1() { return mttlv.getFlag1(); } unsigned short getFlag2() { return mttlv.getFlag2(); } + std::string getCaps() { return caps; } void ParseValue(Buffer& b); unsigned short Type() const { return TLV_MessageData; } diff -urN jit-1.1.6.orig/jit/libicq2000/constants.h jit-1.1.6/jit/libicq2000/constants.h --- jit-1.1.6.orig/jit/libicq2000/constants.h Thu Jan 9 15:41:54 2003 +++ jit-1.1.6/jit/libicq2000/constants.h Tue Sep 14 00:58:23 2004 @@ -35,6 +35,25 @@ STATUS_OFFLINE, }; +/*** + * The encoding type the string is expected in. For example - most + * messages are in the encoding of the locale on the contact's + * computer. However, server-based lists are all stored in + * UTF-8. Lastly, email/pager messages from the ICQ website are + * sent to you are in ISO-8859-1. It is up to the translator how to + * do these conversions to provide a consistent character set to + * the client. +****/ + +enum Encoding +{ + ENCODING_UNSPECIFIED = 0, + ENCODING_ISO_8859_1 = 1, + ENCODING_UCS2 = 2, + ENCODING_CONTACT_LOCALE = 3, + ENCODING_UTF8 = 8, +}; + static const char* const Status_text[] = { "Online", "Away", "N/A", diff -urN jit-1.1.6.orig/jit/libicq2000/events.h jit-1.1.6/jit/libicq2000/events.h --- jit-1.1.6.orig/jit/libicq2000/events.h Thu Jan 9 15:41:54 2003 +++ jit-1.1.6/jit/libicq2000/events.h Tue Sep 14 00:58:23 2004 @@ -379,9 +379,10 @@ std::string m_message; bool m_multi; unsigned int m_foreground, m_background; + Encoding m_encoding; public: - NormalMessageEvent(ContactRef c, const std::string& msg, bool multi = false); + NormalMessageEvent(ContactRef c, const std::string& msg, bool multi = false, Encoding encoding = ENCODING_UNSPECIFIED); NormalMessageEvent(ContactRef c, const std::string& msg, time_t t, bool multi); NormalMessageEvent(ContactRef c, const std::string& msg, unsigned int fg, unsigned int bg); @@ -392,6 +393,8 @@ unsigned int getBackground() const; void setForeground(unsigned int f); void setBackground(unsigned int b); + Encoding getTextEncoding() const; + void setTextEncoding( Encoding e ); ICQMessageEvent* copy() const; }; diff -urN jit-1.1.6.orig/jit/src/Capabilities.cpp jit-1.1.6/jit/src/Capabilities.cpp --- jit-1.1.6.orig/jit/src/Capabilities.cpp Thu Jan 9 15:41:56 2003 +++ jit-1.1.6/jit/src/Capabilities.cpp Tue Sep 14 00:58:23 2004 @@ -20,6 +20,7 @@ */ #include +#include using std::set; @@ -100,7 +101,7 @@ {0x09, 0x46, 0x13, 0x4b, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, - {ICQUnknown2, + {ICQUTF8, {0x09, 0x46, 0x13, 0x4e, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, @@ -122,7 +123,15 @@ {APInfo, {0xaa, 0x4a, 0x32, 0xb5, 0xf8, 0x84, 0x48, 0xc6, - 0xa3, 0xd7, 0x8c, 0x50, 0x97, 0x19, 0xfd, 0x5b}} + 0xa3, 0xd7, 0x8c, 0x50, 0x97, 0x19, 0xfd, 0x5b}}, + + {MacICQ, + {0xDD, 0x16, 0xF2, 0x02, 0x84, 0xE6, 0x11, 0xD4, + 0x90, 0xDB, 0x00, 0x10, 0x4B, 0x9B, 0x4B, 0x7D}}, + + {AIMInteroperate, + {0x09, 0x46, 0x13, 0x4d, 0x4c, 0x7f, 0x11, 0xd1, + 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}} }; Capabilities::Capabilities() @@ -133,6 +142,8 @@ clear(); set_capability_flag( ICQa ); set_capability_flag( ICQServerRelay ); +// MITZ for UTF8 support + set_capability_flag( ICQUTF8 ); } void Capabilities::default_icq2002_capabilities() @@ -141,7 +152,7 @@ set_capability_flag( ICQa ); set_capability_flag( ICQServerRelay ); set_capability_flag( ICQRTF ); - set_capability_flag( ICQUnknown2 ); + set_capability_flag( ICQUTF8 ); } void Capabilities::clear() @@ -182,6 +193,75 @@ // any remainder (there shouldn't be any, but..) b.advance( len - i * sizeof_cap ); + } + + void Capabilities::ParseString(Buffer& b, unsigned short len) + { + int i = len; + int l; + bool inside = false; + unsigned char cap[sizeof_cap]; + while ( i>0 ) { + unsigned char c, d; + b >> c; + i--; + switch (c) + { + case '{': + inside = true; + l = 0; + break; + case '}': + if ( inside ) + { + inside = false; + if ( l==sizeof_cap ) + { + // search for capability in list + for (unsigned int k = 0; k < sizeof(caps) / sizeof(Block); ++k) + if ( memcmp( caps[k].data, cap, sizeof_cap ) == 0 ) { + set_capability_flag( caps[k].flag ); + break; + } + } + } + break; + default: + if ( inside ) + { + if ( (c>='0' && c<='9' || c>='A' && c<='F' || c>='a' && c<='f') && i>0 ) + { + if ( l==sizeof_cap ) + inside = false; + else + { + b >> d; + i--; + if ( d>='0' && d<='9' || d>='A' && d<='F' || d>='a' && d<='f' ) + cap[l++] = ( ( c>='a' ? c+10-'a' : ( c>='A' ? c+10-'A' : c-'0' ) )<<4 ) + + ( d>='a' ? d+10-'a' : ( d>='A' ? d+10-'A' : d-'0' ) ); + } + } + } + break; + } + } + } + + void Capabilities::OutputString( Buffer& b ) const + { + for (set::const_iterator curr = m_flags.begin(); + curr != m_flags.end(); ++curr) + for (unsigned int i = 0; i < sizeof(caps) / sizeof(Block); ++i) + if ( caps[i].flag == *curr ) { + char capstr[39]; + const unsigned char *data = caps[i].data; + sprintf( capstr, "{%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X}", data[0], data[1], data[2], data[3], + data[4], data[5], data[6], data[7], data[8], data[9], + data[10], data[11], data[12], data[13], data[14], data[15] ); + b.Pack( (const unsigned char *)capstr, 38 ); + break; + } } void Capabilities::Output(Buffer& b) const diff -urN jit-1.1.6.orig/jit/src/ICQ.cpp jit-1.1.6/jit/src/ICQ.cpp --- jit-1.1.6.orig/jit/src/ICQ.cpp Thu Jan 9 15:41:56 2003 +++ jit-1.1.6/jit/src/ICQ.cpp Tue Sep 14 00:58:23 2004 @@ -21,6 +21,8 @@ #include +#include + #include "sstream_fix.h" #include @@ -227,17 +229,21 @@ NormalICQSubType::NormalICQSubType(bool multi) : m_multi(multi), m_foreground(0x00000000), - m_background(0x00ffffff) { } + m_background(0x00ffffff), m_encoding(ENCODING_UNSPECIFIED) { } NormalICQSubType::NormalICQSubType(const string& msg) : m_message(msg), m_foreground(0x00000000), - m_background(0x00ffffff) { } + m_background(0x00ffffff), m_encoding(ENCODING_UNSPECIFIED) { } string NormalICQSubType::getMessage() const { return m_message; } bool NormalICQSubType::isMultiParty() const { return m_multi; } void NormalICQSubType::setMessage(const string& msg) { m_message = msg; } + + Encoding NormalICQSubType::getTextEncoding() const { return m_encoding; } + + void NormalICQSubType::setTextEncoding( Encoding e ) { m_encoding = e; } void NormalICQSubType::ParseBodyUIN(Buffer& b) { b.UnpackUint16StringNull(m_message); @@ -246,6 +252,15 @@ if (m_advanced) { b >> m_foreground >> m_background; + if ( m_message.length() ) + { + unsigned int capslen; + b >> capslen; + Capabilities caps; + caps.ParseString( b, capslen ); + if ( caps.has_capability_flag( Capabilities::ICQUTF8 ) ) + m_encoding = ENCODING_UTF8; + } } else { m_foreground = 0x00000000; m_background = 0x00ffffff; @@ -258,6 +273,13 @@ if (m_advanced) { b << (unsigned int)m_foreground << (unsigned int)m_background; + if (m_encoding==ENCODING_UTF8) + { + b << (unsigned int)38; // size of one capability + Capabilities caps; + caps.set_capability_flag( Capabilities::ICQUTF8 ); + caps.OutputString( b ); + } } } diff -urN jit-1.1.6.orig/jit/src/MessageHandler.cpp jit-1.1.6/jit/src/MessageHandler.cpp --- jit-1.1.6.orig/jit/src/MessageHandler.cpp Thu Jan 9 15:41:56 2003 +++ jit-1.1.6/jit/src/MessageHandler.cpp Tue Sep 14 00:58:23 2004 @@ -235,7 +235,7 @@ { NormalICQSubType *nst = static_cast(st); e = new NormalMessageEvent(contact, - nst->getMessage(), nst->isMultiParty() ); + nst->getMessage(), nst->isMultiParty(), nst->getTextEncoding() ); break; } @@ -386,6 +386,7 @@ NormalMessageEvent *nv = static_cast(ev); ist = new NormalICQSubType(nv->getMessage()); + ( static_cast(ist))->setTextEncoding( (static_cast(ev))->getTextEncoding() ); } else if (ev->getType() == MessageEvent::URL) { diff -urN jit-1.1.6.orig/jit/src/SNAC-MSG.cpp jit-1.1.6/jit/src/SNAC-MSG.cpp --- jit-1.1.6.orig/jit/src/SNAC-MSG.cpp Thu Jan 9 15:41:56 2003 +++ jit-1.1.6/jit/src/SNAC-MSG.cpp Tue Sep 14 00:58:23 2004 @@ -272,6 +272,8 @@ NormalICQSubType *nst = new NormalICQSubType(false); nst->setAdvanced(false); nst->setMessage( t->getMessage() ); + if ( t->getCaps().find( 0x06, 0 )!=string::npos && t->getFlag1()==MESSAGETEXT_FLAG1_UCS2 ) + nst->setTextEncoding( ENCODING_UCS2 ); m_icqsubtype = nst; } else if (channel == 0x0002) { diff -urN jit-1.1.6.orig/jit/src/TLV.cpp jit-1.1.6/jit/src/TLV.cpp --- jit-1.1.6.orig/jit/src/TLV.cpp Thu Jan 9 15:41:56 2003 +++ jit-1.1.6/jit/src/TLV.cpp Tue Sep 14 00:58:23 2004 @@ -145,9 +145,12 @@ // ----- INMESSAGEDATA ----- case TLV_ParseMode_InMessageData: switch(type) { - case TLV_MessageText: - tlv = new MessageTextTLV(); - break; + case TLV_MessageText: + tlv = new MessageTextTLV(); + break; + case TLV_Unknown0501: + tlv = new MessageCapsTLV(); + break; } break; @@ -426,7 +429,10 @@ if (tlvlist.exists(TLV_MessageText)) mttlv = *(static_cast(tlvlist[TLV_MessageText])); - + if (tlvlist.exists(TLV_Unknown0501)) + caps = (static_cast(tlvlist[TLV_Unknown0501]))->Value(); + else + caps = ""; } void MessageTextTLV::ParseValue(Buffer& b) { diff -urN jit-1.1.6.orig/jit/src/events.cpp jit-1.1.6/jit/src/events.cpp --- jit-1.1.6.orig/jit/src/events.cpp Thu Jan 9 15:41:56 2003 +++ jit-1.1.6/jit/src/events.cpp Tue Sep 14 00:58:23 2004 @@ -478,8 +478,8 @@ * @param msg the message * @param multi tag message as a multireceipt message */ - NormalMessageEvent::NormalMessageEvent(ContactRef c, const string& msg, bool multi) - : ICQMessageEvent(c), m_message(msg), m_multi(multi), + NormalMessageEvent::NormalMessageEvent(ContactRef c, const string& msg, bool multi, Encoding encoding ) + : ICQMessageEvent(c), m_message(msg), m_multi(multi), m_encoding(encoding), m_foreground(0x00000000), m_background(0x00ffffff) { setDirect(false); } @@ -494,7 +494,7 @@ */ NormalMessageEvent::NormalMessageEvent(ContactRef c, const string& msg, time_t t, bool multi) : ICQMessageEvent(c), m_message(msg), m_multi(multi), - m_foreground(0x00000000), m_background(0x00ffffff) { + m_foreground(0x00000000), m_background(0x00ffffff), m_encoding(ENCODING_UNSPECIFIED) { setDirect(false); setOfflineMessage(true); m_time = t; @@ -510,7 +510,7 @@ */ NormalMessageEvent::NormalMessageEvent(ContactRef c, const string& msg, unsigned int fg, unsigned int bg) : ICQMessageEvent(c), m_message(msg), m_multi(false) /* todo */, - m_foreground(fg), m_background(bg) { + m_foreground(fg), m_background(bg), m_encoding(ENCODING_UNSPECIFIED) { setDirect(true); } @@ -557,6 +557,10 @@ * @param b background colour of the message */ void NormalMessageEvent::setBackground(unsigned int b) { m_background = b; } + + Encoding NormalMessageEvent::getTextEncoding() const { return m_encoding; } + + void NormalMessageEvent::setTextEncoding( Encoding e ) { m_encoding = e; } ICQMessageEvent* NormalMessageEvent::copy() const { diff -urN jit-1.1.6.orig/jit/utils/charset.c jit-1.1.6/jit/utils/charset.c --- jit-1.1.6.orig/jit/utils/charset.c Fri Mar 7 18:16:57 2003 +++ jit-1.1.6/jit/utils/charset.c Tue Sep 14 00:58:23 2004 @@ -10,8 +10,58 @@ #include "jit/icqtransport.h" +extern iconv_t _ucs2utf; extern iconv_t _win2utf; extern iconv_t _utf2win; + +char *it_convert_ucs2utf8(pool p, unsigned int len, const char ucs2_str[]) +{ + size_t size_in, size_out; + char *out_utf; + char *in; + char *out; + size_t numconv; + int q; + + if (!len) + return NULL; + + size_in = len; + size_out = 4*size_in+3; + + out_utf = pmalloco(p,size_out); + + in=(char*)ucs2_str; + out=out_utf; + + q = 1; + while (q) { + numconv = iconv(_ucs2utf,&in,&size_in,&out,&size_out); + + if (numconv == (size_t)(-1)) { + switch (errno) { + case EILSEQ: + case EINVAL: + size_in--; + size_out--; + in++; + *out++ = '?'; + break; + case E2BIG: + default: + q = 0; + break; + } + } + else { + q = 0; + } + } + + *out = '\0'; + return out_utf; +} + char *it_convert_windows2utf8(pool p, const char *windows_str) {