Adding AIM protocol from Alexander Botero-Lowry, but it needs polishing.

This commit is contained in:
plfiorini 2010-05-12 20:42:46 +00:00
parent 7d4a7d1c24
commit 8d6d06dbfe
28 changed files with 5917 additions and 6 deletions

View File

@ -30,7 +30,7 @@ ContactLinker::ContactLinker(BString id, BMessenger msgn)
RegisterObserver(fRosterItem);
// By default we use protocol icon as avatar icon
fAvatarBitmap = ProtocolManager::Get()->GetProtocolIcon("gtalk");
fAvatarBitmap = ProtocolManager::Get()->GetProtocolIcon("aim");
}

View File

@ -26,7 +26,7 @@
Server::Server(MainWindow* mainWindow)
: BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE)
{
CayaProtocol* pp = ProtocolManager::Get()->GetProtocol("gtalk");
CayaProtocol* pp = ProtocolManager::Get()->GetProtocol("aim");
if (!pp)
debugger("something wrong");

View File

@ -1,7 +1,8 @@
SubDir TOP libs ;
# Include all the components.
SubInclude TOP libs libjabber ;
SubInclude TOP libs librunview ;
SubInclude TOP libs libinterface ;
SubInclude TOP libs libjabber ;
SubInclude TOP libs libsupport ;
SubInclude TOP libs libinterface ;
SubInclude TOP libs libimcomm ;

29
libs/libimcomm/COPYING Normal file
View File

@ -0,0 +1,29 @@
Copyright (C) 2003-2005, Claudio Leite
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the BSF Software Project nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

12
libs/libimcomm/Jamfile Normal file
View File

@ -0,0 +1,12 @@
SubDir TOP libs libimcomm ;
StaticLibrary libimcomm.a :
misc.c
packet.c
flap.c
bos_signon.c
imcomm.c
snac.c
md5.c
proxy.c
;

190
libs/libimcomm/README Normal file
View File

@ -0,0 +1,190 @@
This is rather roughly written at the moment. Please forgive any grammar
mistakes I made when I rushed this together.
-Claudio
-----
IMCOMM REFERENCE GUIDE
1. Data structures
IMComm operates on "handles," which are simply structures filled
with the information IMComm needs for one single IM session. In
order to allow multiple connections per program, IMComm leaves
the pointers to those structures up to the user.
Users should use a void * pointer to set up the structure.
Example:
void *handle;
handle = imcomm_create_handle();
2. Callbacks
All IMComm events operate on callbacks. The list of events can
be found in imcomm.h. Developers should register the callbacks
after creating a handle and before signing on.
Example:
imcomm_register_callback(handle, IMCOMM_IM_INCOMING, incoming_im);
This will make the library call the function incoming_im when
an incoming message is received on the conncection pointed by
handle.
The first parameter a for any called back function is the handle.
Following that, the parameter varies based on the event type.
3. Signing on
Signing on is rather simple.
imcomm_im_signon(handle, username, password);
4. Errors and status
All errors are handled using callbacks. To register the error callback,
use the IMCOMM_ERROR callback ID with imcomm_register_callback();
The error types are in an enumerated list in imcomm.h
for example:
void error_cb(void *handle, int event)
{
switch(event) {
case IMCOMM_STATUS_CONNECTED:
printf("Connected.\n");
break;
}
}
EVENTS CURRENTLY IMPLEMENTED:
IMCOMM_IM_SIGNON
(void *handle, char *who)
Buddy <who> has come online.
IMCOMM_IM_SIGNOFF
(void *handle, char *who)
Buddy <who> has gone offline.
IMCOMM_IM_BUDDYAWAY
(void *handle, char *who)
Buddy <who> is away.
IMCOMM_IM_BUDDYUNAWAY
(void *handle, char *who)
Buddy <who> is no longer away.
IMCOMM_IM_IDLEINFO
(void *handle, char *who, long idletime)
Buddy's idletime, reported in minutes.
IMCOMM_IM_INCOMING
(void *handle, char *who, int automessage, char *message)
<who> has sent you a message. If automessage is 1, then
the message is an auto response.
IMCOMM_IM_PROFILE
(void *handle, char *who, char *profile)
Buddy's profile after a profile request.
IMCOMM_IM_AWAYMSG
(void *handle, char *who, char *msg)
Buddy's away message after a away message request.
IMCOMM_ERROR
(void *handle, int errortype, void *ptr1, void *ptr2, void *ptr3)
Error of error <errortype>. ptr1-3 are currently unused.
FUNCTIONS FOR PROGRAMMERS
imcomm_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)
This is where the main work is done. It behaves just like a standard
select() call, meaning it can be used to multiplex keyboard input and
AIM input.
It cycles through every handle known to IMComm (a list is kept internally),
checking for input and processing if necessary.
Example:
fd_set readfs;
struct timeval tm;
while(1) {
FD_ZERO(&readfs);
FD_SET(fileno(stdin), &readfs);
tm.tv_sec = 1;
tm.tv_usec = 15;
/*
* this will check fileno(stdin) AND all of the
* sessions currently established.
*/
imcomm_select(fileno(stdin), &readfs, NULL, NULL &tm);
if(FD_ISSET(fileno(stdin))) {
/* keyboard input handler */
}
}
imcomm_set_profile(void *handle, char *profile);
Sets the user profile.
imcomm_set_away(void *handle, char *msg);
Sets away message.
imcomm_set_unaway(void *handle);
Unsets away message.
imcomm_im_send_message(void *handle, const char *whom, const char *msg, int automsg);
Sends message to user <whom>. If automsg is 1, then it is sent as
an auto response.
imcomm_request_profile(void *handle, char *sn);
Requests profile for user <sn>.
imcomm_request_awaymsg(void *handle, char *sn);
Requests away message for user <sn>.
imcomm_im_add_buddy(void *handle, char *sn);
Adds buddy to session buddy list.
imcomm_im_remove_buddy(void *handle, char *sn);
Removes buddy from session buddy list.
imcomm_compare_nicks(void *handle, char *sn1, char *sn2)
Compares two screen names, ignoring spaces and case.
char *imcomm_simplify_sn(char *sn)
Returns a simplified version of a screen name, all lowercase
with no spaces. Note that you must free this string later,
since it is malloc'ed by imcomm.

684
libs/libimcomm/bos_signon.c Normal file
View File

@ -0,0 +1,684 @@
/** _
** (_)_ __ __ ___ _ __ _ __
** | | ' \/ _/ _ \ ' \| ' \
** |_|_|_|_\__\___/_|_|_|_|_|_|
**
** Copyright (C) 2003-2005, Claudio Leite
** All rights reserved.
**
** Please see the file 'COPYING' for licensing information.
**/
#include "imcomm.h"
#ifdef MD5_LOGIN
#include "md5.h"
#endif
#define CLIENT_IDENT "AOL Instant Messenger, version 5.5.3595/WIN32"
#ifdef MACINTOSH_CLASSIC
/*
* Thanks to PuTTY source code for a lot of help on the MacTCP stuff.
* Learning obsolete API's can be rather difficult...
*
* This should explain the similarities on variable and function names.
*/
int initialized = 0;
short refnum;
ProcessSerialNumber psn;
static pascal void mactcp_lookupdone(struct hostInfo *, char *);
static pascal void
mactcp_asr(StreamPtr, unsigned short, Ptr,
unsigned short, struct ICMPReport *);
static ResultUPP mactcp_lookupdone_upp;
static TCPNotifyUPP mactcp_asr_upp;
OSErr err;
static pascal void
mactcp_lookupdone(struct hostInfo * hi, char *cookie)
{
volatile int *donep = (int *) cookie;
*donep = TRUE;
}
static pascal void
mactcp_asr(StreamPtr str, unsigned short event, Ptr cookie,
unsigned short termin_reason, struct ICMPReport * icmp)
{
WakeUpProcess(&psn);
}
void
mactcp_close(void *handle)
{
TCPiopb pb;
pb.ioCRefNum = refnum;
pb.csCode = TCPClose;
pb.tcpStream = ((IMCOMM *) handle)->s;
pb.csParam.close.validityFlags = 0;
pb.csParam.close.userDataPtr = (Ptr) handle;
PBControlSync((ParmBlkPtr) & pb);
pb.ioCRefNum = refnum;
pb.csCode = TCPAbort;
pb.tcpStream = ((IMCOMM *) handle)->s;
pb.csParam.abort.userDataPtr = (Ptr) handle;
PBControlSync((ParmBlkPtr) & pb);
pb.ioCRefNum = refnum;
pb.csCode = TCPRelease;
pb.tcpStream = ((IMCOMM *) handle)->s;
pb.csParam.create.userDataPtr = (Ptr) handle;
err = PBControlSync((ParmBlkPtr) & pb);
if (err == noErr)
free(pb.csParam.create.rcvBuff);
}
#endif
/* PROTO */
IMCOMM_RET
imcomm_im_signon(void *handle, const char *sn, const char *pw)
{
IMCOMM_RET ret;
pkt_t *packet;
#ifdef MACINTOSH_CLASSIC
OSErr err;
struct hostInfo hostinfo;
volatile int resolverDone = FALSE;
TCPiopb pb;
UDPiopb upb;
size_t buflen;
#else
struct sockaddr_in sin;
struct hostent *he;
#endif
#ifndef MD5_LOGIN
const char client_ident[] = CLIENT_IDENT;
const unsigned char roaststring[] =
{0xF3, 0x26, 0x81, 0xC4, 0x39, 0x86, 0xDB, 0x92, 0x71, 0xA3, 0xB9,
0xE6, 0x53, 0x7A, 0x95, 0x7C};
unsigned char *roastpw;
int x;
#else
pkt_t *pk2;
#endif
#ifdef MACINTOSH_CLASSIC
if (!initialized) {
err = OpenDriver("\p.IPP", &refnum);
if (err != noErr) {
printf("Error initializing driver.\n");
return IMCOMM_RET_ERROR;
}
err = OpenResolver(NULL);
if (err != noErr) {
printf("Error initializing resolver.\n");
return IMCOMM_RET_ERROR;
}
mactcp_lookupdone_upp = NewResultProc(&mactcp_lookupdone);
mactcp_asr_upp = NewTCPNotifyProc(&mactcp_asr);
initialized = 1;
}
err =
StrToAddr("login.oscar.aol.com", &hostinfo, mactcp_lookupdone_upp,
(char *) &resolverDone);
if (err == cacheFault)
while (!resolverDone)
continue;
upb.ioCRefNum = refnum;
upb.csCode = UDPMaxMTUSize;
upb.csParam.mtu.remoteHost = hostinfo.addr[0];
upb.csParam.mtu.userDataPtr = (Ptr) handle;
err = PBControlSync((ParmBlkPtr) & upb);
if (err != noErr) {
printf("Error retrieving MTU.\n");
return IMCOMM_RET_ERROR;
}
buflen = upb.csParam.mtu.mtuSize * 4 + 1024;
if (buflen < 4096)
buflen = 4096;
GetCurrentProcess(&psn);
pb.ioCRefNum = refnum;
pb.csCode = TCPCreate;
pb.csParam.create.rcvBuff = malloc(buflen);
pb.csParam.create.rcvBuffLen = buflen;
pb.csParam.create.notifyProc = mactcp_asr_upp;
pb.csParam.create.userDataPtr = (Ptr) handle;
err = PBControlSync((ParmBlkPtr) & pb);
if (err != noErr) {
printf("Error creating TCP stream.\n");
return IMCOMM_RET_ERROR;
}
((IMCOMM *) handle)->s = pb.tcpStream;
pb.ioCRefNum = refnum;
pb.csCode = TCPActiveOpen;
pb.tcpStream = ((IMCOMM *) handle)->s;
pb.csParam.open.validityFlags = 0;
pb.csParam.open.remoteHost = hostinfo.addr[0];
pb.csParam.open.remotePort = ((IMCOMM *) handle)->oscarport;
pb.csParam.open.localPort = 0;
pb.csParam.open.timeToLive = 0;
pb.csParam.open.security = 0;
pb.csParam.open.optionCnt = 0;
pb.csParam.open.userDataPtr = (Ptr) handle;
err = PBControlSync((ParmBlkPtr) & pb);
if (err != noErr) {
printf("Connection failed.\n");
return IMCOMM_RET_ERROR;
}
((IMCOMM *) handle)->readable = 1;
#else
/* XXX insert modular socket code here */
#ifdef __MINGW32__
if (WSAStartup(0x101, &((IMCOMM *) handle)->wsadata)) {
printf("ERROR: %i\n", WSAGetLastError());
return IMCOMM_RET_ERROR;
}
#endif
if (((IMCOMM *) handle)->proxymode == PROXY_TYPE_SOCKS5) {
connect_socks5(handle, "login.oscar.aol.com",
((IMCOMM *) handle)->oscarport);
} else if (((IMCOMM *) handle)->proxymode == PROXY_TYPE_HTTPS) {
connect_https(handle, "login.oscar.aol.com",
((IMCOMM *) handle)->oscarport);
} else {
if ((he = gethostbyname("login.oscar.aol.com")) == NULL) {
perror("gethostbyname()");
return IMCOMM_RET_ERROR;
}
if ((((IMCOMM *) handle)->socket =
socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket()");
return IMCOMM_RET_ERROR;
}
sin.sin_family = AF_INET;
sin.sin_port = htons(((IMCOMM *) handle)->oscarport);
sin.sin_addr = *((struct in_addr *) he->h_addr);
memset(&(sin.sin_zero), 0, 8);
if (connect
(((IMCOMM *) handle)->socket, (struct sockaddr *) & sin,
sizeof(struct sockaddr)) == -1) {
perror("connect()");
return IMCOMM_RET_ERROR;
}
}
/* end socket code for now */
#endif
#ifdef MD5_LOGIN
((IMCOMM *) handle)->pw = strdup((char *) pw);
((IMCOMM *) handle)->sn = strdup((char *) sn);
packet = pkt_init(12 + strlen(sn));
#else
roastpw = malloc(strlen(pw) + 1);
memset(roastpw, 0, strlen(pw) + 1);
for (x = 0; x < (int) strlen(pw); x++)
roastpw[x] = (pw[x] ^ roaststring[x]);
packet = pkt_init(66 + strlen(client_ident) + strlen(sn) + strlen(pw));
pkt_add32(packet, 0x00000001);
#endif
/*
* I should really build a TLV here instead, but this works.
*/
/*
* Add SN length + SN
*/
pkt_add16(packet, 0x0001);
pkt_add16(packet, (uint16_t) strlen(sn));
pkt_addraw(packet, (uint8_t *) sn, strlen(sn));
#ifdef MD5_LOGIN
/*
* Add unknown TLV's...
*/
pkt_add16(packet, 0x004B);
pkt_add16(packet, 0x0000);
pkt_add16(packet, 0x005A);
pkt_add16(packet, 0x0000);
#else
/*
* Add roasted PW length + roasted PW
*/
pkt_add16(packet, 0x0002);
pkt_add16(packet, (uint16_t) strlen(pw));
pkt_addraw(packet, (uint8_t *) pw, strlen(pw));
/*
* Add client ident string
*/
pkt_add16(packet, 0x0003);
pkt_add16(packet, (uint16_t) strlen(client_ident));
pkt_addraw(packet, (uint8_t *) client_ident, strlen(client_ident));
/*
* Add client ID (hardcoded)
*/
pkt_add16(packet, 0x0016);
pkt_add16(packet, 0x0002);
pkt_add16(packet, 0x0109);
/*
* Add client versions (hardcoded)
*/
pkt_add16(packet, 0x0017);
pkt_add16(packet, 0x0002);
pkt_add16(packet, 0x0005);
pkt_add16(packet, 0x0018);
pkt_add16(packet, 0x0002);
pkt_add16(packet, 0x0005);
pkt_add16(packet, 0x0019);
pkt_add16(packet, 0x0002);
pkt_add16(packet, 0x0000);
pkt_add16(packet, 0x001A);
pkt_add16(packet, 0x0002);
pkt_add16(packet, 0x0057);
pkt_add16(packet, 0x0014);
pkt_add16(packet, 0x0004);
pkt_add32(packet, 0x000000ef);
pkt_add16(packet, 0x000F);
pkt_add16(packet, 0x0002);
pkt_addraw(packet, (unsigned char *) "en", 2);
pkt_add16(packet, 0x000E);
pkt_add16(packet, 0x0002);
pkt_addraw(packet, (unsigned char *) "us", 2);
#endif
#ifdef MD5_LOGIN
pk2 = pkt_init(4);
pkt_add32(pk2, 0x00000001);
flap_sendpkt(handle, 0x01, pk2, 0);
pkt_free(pk2);
ret = snac_sendpkt(handle, 0x17, 0x06, packet, 0);
#else
ret = flap_sendpkt(handle, 0x01, packet, 0);
free(roastpw);
#endif
pkt_free(packet);
return ret;
}
/* PROTO */
IMCOMM_RET
bos_signon_phase2(void *handle, unsigned const char *server, unsigned const char *cookie, uint16_t cookie_len)
{
char *host;
uint16_t port;
pkt_t *packet;
int x, ret;
int newlen;
#ifdef MACINTOSH_CLASSIC
OSErr err;
struct hostInfo hostinfo;
volatile int resolverDone = FALSE;
TCPiopb pb;
UDPiopb upb;
size_t buflen;
#else
struct sockaddr_in sin;
#endif
#if defined(PLAN9) || defined(__MINGW32__)
long addy;
struct in_addr ina;
#else
struct hostent *he;
#endif
port = atoi(strchr((char *) server, ':') + 1);
host = (char *) malloc(strlen((char *) server) + 1);
#ifdef __OpenBSD__
strlcpy(host, (char *) server, strlen((char *) server));
#else
strcpy(host, (char *) server);
#endif
for (x = 0; x < (int) strlen(host); x++)
if (host[x] == ':') {
host[x] = 0;
break;
}
#ifdef MACINTOSH_CLASSIC
mactcp_close(handle);
((IMCOMM *) handle)->readable = 0;
err =
StrToAddr(host, &hostinfo, mactcp_lookupdone_upp,
(char *) &resolverDone);
if (err == cacheFault)
while (!resolverDone)
continue;
upb.ioCRefNum = refnum;
upb.csCode = UDPMaxMTUSize;
upb.csParam.mtu.remoteHost = hostinfo.addr[0];
upb.csParam.mtu.userDataPtr = (Ptr) handle;
err = PBControlSync((ParmBlkPtr) & upb);
if (err != noErr) {
printf("Error retrieving MTU.\n");
return IMCOMM_RET_ERROR;
}
buflen = upb.csParam.mtu.mtuSize * 4 + 1024;
if (buflen < 4096)
buflen = 4096;
pb.ioCRefNum = refnum;
pb.csCode = TCPCreate;
pb.csParam.create.rcvBuff = malloc(buflen);
pb.csParam.create.rcvBuffLen = buflen;
pb.csParam.create.notifyProc = mactcp_asr_upp;
pb.csParam.create.userDataPtr = (Ptr) handle;
err = PBControlSync((ParmBlkPtr) & pb);
if (err != noErr) {
printf("Error creating TCP stream.\n");
return IMCOMM_RET_ERROR;
}
((IMCOMM *) handle)->s = pb.tcpStream;
pb.ioCRefNum = refnum;
pb.csCode = TCPActiveOpen;
pb.tcpStream = ((IMCOMM *) handle)->s;
pb.csParam.open.validityFlags = 0;
pb.csParam.open.remoteHost = hostinfo.addr[0];
pb.csParam.open.remotePort = port;
pb.csParam.open.localPort = 0;
pb.csParam.open.timeToLive = 0;
pb.csParam.open.security = 0;
pb.csParam.open.optionCnt = 0;
pb.csParam.open.userDataPtr = (Ptr) handle;
err = PBControlSync((ParmBlkPtr) & pb);
if (err != noErr) {
printf("Connection failed.\n");
return IMCOMM_RET_ERROR;
}
((IMCOMM *) handle)->readable = 1;
#else
if (((IMCOMM *) handle)->ischild == 0)
shutdown(((IMCOMM *) handle)->socket, 0x02);
if (((IMCOMM *) handle)->proxymode == PROXY_TYPE_SOCKS5) {
connect_socks5(handle, host, port);
} else if (((IMCOMM *) handle)->proxymode == PROXY_TYPE_HTTPS) {
connect_https(handle, host, port);
} else {
#if !defined(PLAN9) && !defined(__MINGW32__)
if ((he = gethostbyname(host)) == NULL) {
perror("gethostbyname()");
free(host);
return IMCOMM_RET_ERROR;
}
free(host);
#else
addy = inet_addr(host);
ina.s_addr = addy;
free(host);
#endif
if ((((IMCOMM *) handle)->socket =
socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket()");
return IMCOMM_RET_ERROR;
}
sin.sin_family = AF_INET;
sin.sin_port = htons(port);
#if defined(PLAN9) || defined(__MINGW32__)
sin.sin_addr = ina;
#else
sin.sin_addr = *((struct in_addr *) he->h_addr);
#endif
memset(&(sin.sin_zero), 0, 8);
if (connect
(((IMCOMM *) handle)->socket, (struct sockaddr *) & sin,
sizeof(struct sockaddr)) == -1) {
perror("connect()");
return IMCOMM_RET_ERROR;
}
#endif
}
newlen = cookie_len + 8;
packet = pkt_init(newlen);
pkt_add32(packet, 0x00000001);
pkt_add16(packet, 0x0006);
pkt_add16(packet, cookie_len);
pkt_addraw(packet, (uint8_t *) cookie, cookie_len);
ret = flap_sendpkt(handle, 0x01, packet, 0);
pkt_free(packet);
return ret;
}
/* PROTO */
void
handle_srv_migration(void *handle, uint8_t * data, uint16_t len)
{
TLVLIST *tlv, *trav;
uint16_t num_family, cookie_len = 0;
pkt_t *inpkt;
int status = 0;
char *bos_server = 0;
uint8_t *cookie = 0;
inpkt = pkt_initP(data + 10, len - 10);
num_family = pkt_get16(inpkt);
if (num_family != 0 && num_family != ((IMCOMM *) handle)->num_families) {
printf("migration has different number of families.\n");
printf("not proceeding (bifurcated?)\n");
return;
}
pkt_freeP(inpkt);
if (((IMCOMM *) handle)->srv_pause)
((IMCOMM *) handle)->srv_pause = 0;
tlv =
tlv_split(data + 12 + (num_family * 2),
len - (12 + (num_family * 2)), 0);
printf("migration beginning.\n");
for (trav = tlv; trav != NULL; trav = trav->next) {
if (trav->type == 0x0005) {
bos_server = malloc(trav->len + 1);
memcpy(bos_server, trav->value, trav->len);
bos_server[trav->len] = 0;
status++;
} else if (trav->type == 0x0006) {
cookie = malloc(trav->len);
cookie_len = trav->len;
memcpy(cookie, trav->value, trav->len);
status++;
}
}
clear_tlv_list(tlv);
printf("server: %s\n", bos_server);
if (((IMCOMM *) handle)->callbacks[IMCOMM_ERROR])
((IMCOMM *) handle)->callbacks[IMCOMM_ERROR] (handle,
IMCOMM_STATUS_MIGRATIONDONE);
bos_signon_phase2(handle, (unsigned char *) bos_server, cookie,
cookie_len);
free(bos_server);
free(cookie);
}
#ifdef MD5_LOGIN
#define AIM_MD5_STRING "AOL Instant Messenger (SM)"
/*
* New stuff for MD5-based login
*/
/* PROTO */
void
bos_md5snac(void *handle, uint8_t * data, uint16_t len)
{
uint8_t *authkey;
uint16_t authkeylen;
md5_state_t state;
md5_byte_t auth_hash[16];
pkt_t *packet;
if (data[3] == 0x07) {
const char client_ident[] = CLIENT_IDENT;
authkeylen = two_to_16(data + 10);
authkey = malloc(authkeylen);
memcpy(authkey, data + 12, authkeylen);
md5_init(&state);
md5_append(&state, (const md5_byte_t *) authkey, authkeylen);
md5_append(&state, (const md5_byte_t *) ((IMCOMM *) handle)->pw,
strlen(((IMCOMM *) handle)->pw));
md5_append(&state, (const md5_byte_t *) AIM_MD5_STRING,
strlen(AIM_MD5_STRING));
md5_finish(&state, auth_hash);
free(authkey);
packet =
pkt_init(67 + strlen(CLIENT_IDENT) + 16 +
strlen(((IMCOMM *) handle)->sn));
/*
* I should really build a TLV here instead, but this works.
*/
/*
* Add SN length + SN
*/
pkt_add16(packet, 0x0001);
pkt_add16(packet, (uint16_t) strlen(((IMCOMM *) handle)->sn));
pkt_addraw(packet, (uint8_t *) ((IMCOMM *) handle)->sn,
strlen(((IMCOMM *) handle)->sn));
pkt_add16(packet, 0x0025);
pkt_add16(packet, 0x0010);
pkt_addraw(packet, (uint8_t *) auth_hash, 16);
/*
* Add client ident string
*/
pkt_add16(packet, 0x0003);
pkt_add16(packet, (uint16_t) strlen(client_ident));
pkt_addraw(packet, (uint8_t *) client_ident, strlen(client_ident));
/*
* Add client ID (hardcoded)
*/
pkt_add16(packet, 0x0016);
pkt_add16(packet, 0x0002);
pkt_add16(packet, 0x0109);
/*
* Add client versions (hardcoded)
*/
pkt_add16(packet, 0x0017);
pkt_add16(packet, 0x0002);
pkt_add16(packet, 0x0005);
pkt_add16(packet, 0x0018);
pkt_add16(packet, 0x0002);
pkt_add16(packet, 0x0005);
pkt_add16(packet, 0x0019);
pkt_add16(packet, 0x0002);
pkt_add16(packet, 0x0000);
pkt_add16(packet, 0x001A);
pkt_add16(packet, 0x0002);
pkt_add16(packet, 0x0e0b);
pkt_add16(packet, 0x0014);
pkt_add16(packet, 0x0004);
pkt_add32(packet, 0x00000104);
pkt_add16(packet, 0x000F);
pkt_add16(packet, 0x0002);
pkt_addraw(packet, (unsigned char *) "en", 2);
pkt_add16(packet, 0x000E);
pkt_add16(packet, 0x0002);
pkt_addraw(packet, (unsigned char *) "us", 2);
pkt_add16(packet, 0x004A);
pkt_add16(packet, 0x0001);
pkt_add8(packet, 0x01);
snac_sendpkt(handle, 0x17, 0x02, packet, 0);
pkt_free(packet);
return;
} else if (data[3] == 0x03) {
TLVLIST *tlv, *trav;
uint16_t numtlv, cookie_len = 0;
int status = 0;
char *bos_server = 0;
uint8_t *cookie = 0;
numtlv = count_tlv(data + 10, len - 10);
tlv = tlv_split(data + 10, len - 10, numtlv);
for (trav = tlv; trav != NULL; trav = trav->next) {
if (trav->type == 0x0008) {
if (((IMCOMM *) handle)->callbacks[IMCOMM_ERROR])
((IMCOMM *) handle)->callbacks[IMCOMM_ERROR] (handle,
IMCOMM_ERROR_INVALID_LOGIN);
#ifdef MACINTOSH_CLASSIC
#else
shutdown(((IMCOMM *) handle)->socket, 0x02);
((IMCOMM *) handle)->socket = -1;
#endif
} else if (trav->type == 0x0005) {
bos_server = malloc(trav->len + 1);
memcpy(bos_server, trav->value, trav->len);
bos_server[trav->len] = 0;
status++;
} else if (trav->type == 0x0006) {
cookie = malloc(trav->len);
cookie_len = trav->len;
memcpy(cookie, trav->value, trav->len);
status++;
}
}
clear_tlv_list(tlv);
if (status == 2) {
if (((IMCOMM *) handle)->callbacks[IMCOMM_ERROR])
((IMCOMM *) handle)->callbacks[IMCOMM_ERROR] (handle,
IMCOMM_STATUS_AUTHDONE);
bos_signon_phase2(handle, (unsigned char *) bos_server, cookie,
cookie_len);
free(bos_server);
free(cookie);
}
}
}
#endif /* MD5_LOGIN */

View File

@ -0,0 +1,7 @@
#define BYTE_SWAP_16(x) (((x & 0xFF00) >> 8) | \
((x & 0x00FF) << 8))
#define BYTE_SWAP_32(x) (((x & 0xFF000000) >> 24) | \
((x & 0x00FF0000) >> 8) | \
((x & 0x0000FF00) << 8) | \
((x & 0x000000FF) << 24))

490
libs/libimcomm/flap.c Normal file
View File

@ -0,0 +1,490 @@
/** _
** (_)_ __ __ ___ _ __ _ __
** | | ' \/ _/ _ \ ' \| ' \
** |_|_|_|_\__\___/_|_|_|_|_|_|
**
** Copyright (C) 2003-2005, Claudio Leite
** All rights reserved.
**
** Please see the file 'COPYING' for licensing information.
**/
#include "imcomm.h"
extern int endianness;
#ifdef MACINTOSH_CLASSIC
extern short refnum;
OSErr
mactcp_recv(void *handle, char *inbuf, size_t len)
{
TCPiopb pb;
OSErr err;
size_t dataRead = 0;
pb.ioCRefNum = refnum;
pb.csCode = TCPRcv;
pb.tcpStream = ((IMCOMM *) handle)->s;
pb.csParam.receive.commandTimeoutValue = 2;
pb.csParam.receive.rcvBuff = inbuf;
pb.csParam.receive.rcvBuffLen = len;
pb.csParam.receive.userDataPtr = (Ptr) handle;
err = PBControlSync((ParmBlkPtr) & pb);
if (err != noErr)
return err;
return noErr;
}
#endif
#ifndef SEND_QUEUES
/* PROTO */
IMCOMM_RET
flap_send(void *handle, uint8_t channel, unsigned char *packet, size_t len, int updateidle)
{
pkt_t *outpacket;
size_t totallen;
#ifdef MACINTOSH_CLASSIC
TCPiopb pb;
wdsEntry wds[2];
OSErr err;
#endif
totallen = len + 6;
outpacket = pkt_init(totallen);
pkt_add8(outpacket, 0x2A);
pkt_add8(outpacket, channel);
pkt_add16(outpacket, ((IMCOMM *) handle)->seqnum);
pkt_add16(outpacket, (uint16_t) len);
pkt_addraw(outpacket, packet, len);
#ifdef MACINTOSH_CLASSIC
wds[0].length = outpacket->len;
wds[0].ptr = (char *) outpacket->data;
wds[1].length = 0;
pb.ioCRefNum = refnum;
pb.csCode = TCPSend;
pb.tcpStream = ((IMCOMM *) handle)->s;
pb.csParam.send.validityFlags = 0;
pb.csParam.send.pushFlag = TRUE;
pb.csParam.send.urgentFlag = 0;
pb.csParam.send.wdsPtr = (Ptr) wds;
pb.csParam.send.userDataPtr = (Ptr) handle;
err = PBControlSync((ParmBlkPtr) & pb);
#else
if (send
(((IMCOMM *) handle)->socket, outpacket->data, outpacket->len,
0) < 0) {
pkt_free(outpacket);
return IMCOMM_RET_ERROR;
}
#endif
if (((IMCOMM *) handle)->seqnum < 0xFFFF)
((IMCOMM *) handle)->seqnum++;
else
((IMCOMM *) handle)->seqnum = 0;
if (updateidle == 1) {
((IMCOMM *) handle)->last_operation_time = time(NULL);
if (((IMCOMM *) handle)->isidle == 1)
imcomm_set_idle_time(handle, 0);
}
pkt_free(outpacket);
return IMCOMM_RET_OK;
}
/* PROTO */
struct MultiPacket *
MultiPktInit(void)
{
struct MultiPacket *npkt;
npkt = malloc(sizeof(struct MultiPacket));
npkt->init = -1;
return npkt;
}
/* PROTO */
void
MultiPktFree(struct MultiPacket * h)
{
struct MultiPacket *trav, *tmp;
for (trav = h; trav != NULL;) {
free(trav->packet);
tmp = trav;
trav = trav->next;
free(tmp);
}
}
/* PROTO */
void
flap_addToMulti(struct MultiPacket * mpkt, uint8_t channel, unsigned char *packet, size_t len, int updateidle)
{
struct MultiPacket *trav, *npkt;
int first;
if (mpkt->init == -1) {
npkt = mpkt;
first = 1;
} else {
npkt = malloc(sizeof(struct MultiPacket));
first = 0;
}
npkt->channel = channel;
npkt->packet = malloc(len);
memcpy(npkt->packet, packet, len);
npkt->len = len;
npkt->updateidle = updateidle;
npkt->next = NULL;
npkt->init = 1;
if (!first) {
for (trav = mpkt; trav->next != NULL; trav = trav->next);
trav->next = npkt;
}
}
/* PROTO */
IMCOMM_RET
flap_sendMulti(void *handle, struct MultiPacket * pktlist)
{
pkt_t *outpacket;
size_t totallen;
struct MultiPacket *trav;
int updateidle = 0;
#ifdef MACINTOSH_CLASSIC
TCPiopb pb;
wdsEntry wds[2];
OSErr err;
#endif
for (trav = pktlist, totallen = 0; trav != NULL; trav = trav->next) {
totallen += 6 + trav->len;
if (trav->updateidle == 1)
updateidle = 1;
}
outpacket = pkt_init(totallen);
for (trav = pktlist; trav != NULL; trav = trav->next) {
pkt_add8(outpacket, 0x2A);
pkt_add8(outpacket, trav->channel);
pkt_add16(outpacket, ((IMCOMM *) handle)->seqnum);
pkt_add16(outpacket, (uint16_t) trav->len);
pkt_addraw(outpacket, trav->packet, trav->len);
if (((IMCOMM *) handle)->seqnum < 0xFFFF)
((IMCOMM *) handle)->seqnum++;
else
((IMCOMM *) handle)->seqnum = 0;
}
#ifdef MACINTOSH_CLASSIC
wds[0].length = outpacket->len;
wds[0].ptr = (char *) outpacket->data;
wds[1].length = 0;
pb.ioCRefNum = refnum;
pb.csCode = TCPSend;
pb.tcpStream = ((IMCOMM *) handle)->s;
pb.csParam.send.validityFlags = 0;
pb.csParam.send.pushFlag = TRUE;
pb.csParam.send.urgentFlag = 0;
pb.csParam.send.wdsPtr = (Ptr) wds;
pb.csParam.send.userDataPtr = (Ptr) handle;
err = PBControlSync((ParmBlkPtr) & pb);
#else
if (send
(((IMCOMM *) handle)->socket, outpacket->data, outpacket->len,
0) < 0) {
pkt_free(outpacket);
return IMCOMM_RET_ERROR;
}
#endif
if (updateidle == 1) {
((IMCOMM *) handle)->last_operation_time = time(NULL);
if (((IMCOMM *) handle)->isidle == 1)
imcomm_set_idle_time(handle, 0);
}
pkt_free(outpacket);
return IMCOMM_RET_OK;
}
#else
/* PROTO */
IMCOMM_RET
flap_sendAct(void *handle, uint8_t channel, unsigned char *packet, size_t len, int updateidle)
{
pkt_t *outpacket;
size_t totallen;
#ifdef MACINTOSH_CLASSIC
TCPiopb pb;
wdsEntry wds[2];
OSErr err;
#endif
totallen = len + 6;
outpacket = pkt_init(totallen);
pkt_add8(outpacket, 0x2A);
pkt_add8(outpacket, channel);
pkt_add16(outpacket, ((IMCOMM *) handle)->seqnum);
pkt_add16(outpacket, (uint16_t) len);
pkt_addraw(outpacket, packet, len);
#ifdef MACINTOSH_CLASSIC
wds[0].length = outpacket->len;
wds[0].ptr = (char *) outpacket->data;
wds[1].length = 0;
pb.ioCRefNum = refnum;
pb.csCode = TCPSend;
pb.tcpStream = ((IMCOMM *) handle)->s;
pb.csParam.send.validityFlags = 0;
pb.csParam.send.pushFlag = TRUE;
pb.csParam.send.urgentFlag = 0;
pb.csParam.send.wdsPtr = (Ptr) wds;
pb.csParam.send.userDataPtr = (Ptr) handle;
err = PBControlSync((ParmBlkPtr) & pb);
#else
if (send
(((IMCOMM *) handle)->socket, outpacket->data, outpacket->len,
0) < 0) {
pkt_free(outpacket);
return IMCOMM_RET_ERROR;
}
#endif
if (((IMCOMM *) handle)->seqnum < 0xFFFF)
((IMCOMM *) handle)->seqnum++;
else
((IMCOMM *) handle)->seqnum = 0;
if (updateidle == 1) {
((IMCOMM *) handle)->last_operation_time = time(NULL);
if (((IMCOMM *) handle)->isidle == 1)
imcomm_set_idle_time(handle, 0);
}
pkt_free(outpacket);
return IMCOMM_RET_OK;
}
/* PROTO */
IMCOMM_RET
flap_sendnext(void *handle)
{
IMCOMM_RET ret = IMCOMM_RET_OK;
send_q *nq, *head = ((IMCOMM *) handle)->s_queue;
if (head) {
ret =
flap_sendAct(handle, head->channel, head->data, head->len,
head->updateidle);
nq = head;
head = head->next;
((IMCOMM *) handle)->s_queue = head;
free(nq->data);
free(nq);
}
return ret;
}
IMCOMM_RET
flap_send(void *handle, uint8_t channel, unsigned char *packet, size_t len, int updateidle)
{
send_q *nq, *trav, *head = ((IMCOMM *) handle)->s_queue;
nq = malloc(sizeof(struct IMCommSendQ));
nq->next = NULL;
nq->updateidle = updateidle;
nq->data = malloc(len);
nq->channel = channel;
memcpy(nq->data, packet, len);
nq->len = len;
if (head == NULL) {
((IMCOMM *) handle)->s_queue = nq;
} else {
for (trav = head; trav->next != NULL; trav = trav->next);
trav->next = nq;
}
return IMCOMM_RET_OK;
}
#endif /* SEND_QUEUES */
/* PROTO */
IMCOMM_RET
flap_sendpkt(void *handle, uint8_t channel, pkt_t * pkt, int updateidle)
{
return flap_send(handle, channel, pkt->data, pkt->len, updateidle);
}
/* PROTO */
IMCOMM_RET
flap_decode(void *handle, unsigned char *header, unsigned char *data)
{
pkt_t *packet;
#ifdef DEBUG
int y, z;
int x;
#endif
uint16_t len, sn_len;
uint16_t family, subfamily;
unsigned char *sn = NULL;
IMCOMM_RET ret = IMCOMM_RET_OK;
#ifdef DUMP
FILE *dump;
int xx;
dump = fopen("imcomm.dump", "a");
#endif
memcpy(&len, header + 4, 2);
if (endianness == HOST_LITTLE_ENDIAN)
len = BYTE_SWAP_16(len);
packet = pkt_initP(data, len);
#ifdef DUMP
for (xx = 0; x < 6; xx++)
fputc(header[xx], dump);
for (xx = 0; x < len; xx++)
fputc(data[xx], dump);
fclose(dump);
#endif
#ifdef DEBUG
printf("Packet length: %u\n", (unsigned int) packet->len);
for (x = 0, y = 0; x < len; x++) {
printf("%02X ", data[x]);
y++;
if (y == 16) {
for (y = 15; y >= 0; y--) {
if (data[x - y] > 31 && data[x - y] < 128)
putchar(data[x - y]);
else
putchar('.');
}
printf("\n");
y = 0;
}
}
if (y < 16) {
for (z = 0; z < (16 - y); z++)
printf(" ");
while (y > 0) {
if (data[x - y] > 31 && data[x - y] < 128)
putchar(data[x - y]);
else
putchar('.');
y--;
}
printf("\n");
}
printf("\n");
#endif
switch (header[1]) {
case 0x02:
ret = snac_decode(handle, data, len);
break;
case 0x04:
family = pkt_get16(packet);
if (family == 0x0009) {
subfamily = pkt_get16(packet);
if (subfamily == 0x0002) {
if (((IMCOMM *) handle)->callbacks[IMCOMM_ERROR])
((IMCOMM *) handle)->callbacks[IMCOMM_ERROR] (handle,
IMCOMM_ERROR_OTHER_SIGNON);
#ifdef MACINTOSH_CLASSIC
#else
shutdown(((IMCOMM *) handle)->socket, 2);
((IMCOMM *) handle)->socket = -1;
#endif
break;
}
} else if (family == 0x0001) {
/*
* SRV_COOKIE
*/
sn_len = pkt_get16(packet);
sn = pkt_getstr(packet, sn_len);
if (((IMCOMM *) handle)->callbacks[IMCOMM_FORMATTED_SN])
((IMCOMM *) handle)->
callbacks[IMCOMM_FORMATTED_SN] (handle, sn);
subfamily = pkt_get16(packet);
switch (subfamily) {
case 0x0005:
{
unsigned char *server, *cookie;
uint16_t server_len, cookie_len;
server_len = pkt_get16(packet);
server = pkt_getstr(packet, server_len);
subfamily = pkt_get16(packet);
#ifdef DEBUG
if (subfamily != 0x0006) {
printf("WARNING: Cookie family not 0x0006!\n");
}
#endif
cookie_len = pkt_get16(packet);
cookie = pkt_getstr(packet, cookie_len);
if (((IMCOMM *) handle)->callbacks[IMCOMM_ERROR])
((IMCOMM *) handle)->
callbacks[IMCOMM_ERROR] (handle,
IMCOMM_STATUS_AUTHDONE);
ret =
bos_signon_phase2(handle, server, cookie,
cookie_len);
free(server);
free(cookie);
}
break;
case 0x0008:
case 0x0004:
if (((IMCOMM *) handle)->callbacks[IMCOMM_ERROR])
((IMCOMM *) handle)->callbacks[IMCOMM_ERROR] (handle,
IMCOMM_ERROR_INVALID_LOGIN);
#ifdef MACINTOSH_CLASSIC
#else
shutdown(((IMCOMM *) handle)->socket, 0x02);
((IMCOMM *) handle)->socket = -1;
#endif
break;
}
}
break;
}
if (sn != NULL)
free(sn);
/*
* This'll also free the incoming data buffer
*/
pkt_free(packet);
return ret;
}

770
libs/libimcomm/imcomm.c Normal file
View File

@ -0,0 +1,770 @@
/** _
** (_)_ __ __ ___ _ __ _ __
** | | ' \/ _/ _ \ ' \| ' \
** |_|_|_|_\__\___/_|_|_|_|_|_|
**
** Copyright (C) 2003-2005, Claudio Leite
** All rights reserved.
**
** Please see the file 'COPYING' for licensing information.
**/
#include "imcomm.h"
IMCOMM_HANDLES *handles = NULL;
int endianness;
int nodes_to_delete = 0;
#ifdef MACINTOSH_CLASSIC
extern short refnum;
#endif
/* PROTO */
void *
imcomm_create_handle(void)
{
IMCOMM *handle;
IMCOMM_HANDLES *tmp;
int xx;
handle = malloc(sizeof(IMCOMM));
handle->proxymode = PROXY_TYPE_NONE;
handle->proxyserver = NULL;
handle->proxyport = 0;
handle->to_delete = 0;
handle->ischild = 0;
handle->seqnum = 0x1000;
handle->snacreq = 0;
handle->families = NULL;
handle->num_families = 0;
handle->buddylist = NULL;
handle->buddies_online = NULL;
handle->isidle = 0;
handle->isinvisible = 0;
handle->last_operation_time = time(NULL);
handle->profile_str = NULL;
handle->away_msg = NULL;
handle->icondata = 0;
handle->iconlen = 0;
handle->socket = 0;
handle->connected = 0;
handle->srv_pause = 0;
handle->data = NULL;
handle->header_pos = 0;
handle->oscarport = 5190;
#ifdef MD5_LOGIN
handle->pw = NULL;
handle->sn = NULL;
#endif
#ifdef IMCOMM_KEEPALIVE
handle->last_keepalive_time = 0;
#endif
#ifdef SEND_QUEUES
handle->s_queue = NULL;
#endif
#ifdef MACINTOSH_CLASSIC
handle->readable = 0;
#endif
endianness = getbyteorder();
for (xx = 0; xx < NUM_CALLBACKS; xx++)
handle->callbacks[xx] = NULL;
if (handles == NULL) {
handles = malloc(sizeof(IMCOMM_HANDLES));
handles->handle = handle;
handles->next = NULL;
} else {
tmp = handles;
while (tmp->next != NULL)
tmp = tmp->next;
tmp->next = malloc(sizeof(IMCOMM_HANDLES));
tmp->next->handle = handle;
tmp->next->next = NULL;
}
return (void *) handle;
}
/* PROTO */
int
imcomm_delete_handle_now(void *vhandle)
{
IMCOMM_HANDLES *tmp, *tr;
if (handles == NULL)
return 0;
if (handles->handle == (IMCOMM *) vhandle) {
tmp = handles;
handles = handles->next;
imcomm_delete_handle_only((void *) tmp->handle);
free(tmp);
} else {
for (tr = handles; tr;) {
if (tr->handle == (IMCOMM *) vhandle) {
tmp = tr;
tr = tr->next;
imcomm_delete_handle_only((void *) tmp->handle);
free(tmp);
continue;
}
tr = tr->next;
}
}
return 1;
}
/* PROTO */
int
imcomm_delete_handle(void *vhandle)
{
((IMCOMM *) vhandle)->to_delete = 1;
nodes_to_delete = 1;
return 1;
}
/* PROTO */
int
imcomm_delete_handle_only(void *vhandle)
{
IMCOMM *handle = (IMCOMM *) vhandle;
if (handle->buddylist)
imcomm_delete_buddylist(handle->buddylist);
if (handle->buddies_online)
imcomm_delete_buddylist(handle->buddies_online);
if (handle->families)
imcomm_delete_familieslist(handle->families);
if (handle->profile_str)
free(handle->profile_str);
if (handle->away_msg)
free(handle->away_msg);
if (handle->icondata)
free(handle->icondata);
if (handle->data)
free(handle->data);
#ifdef MD5_LOGIN
if (handle->sn)
free(handle->sn);
if (handle->pw)
free(handle->pw);
#endif
if (handle->proxyserver)
free(handle->proxyserver);
if (handle->socket != -1)
shutdown(handle->socket, 0x02);
free(vhandle);
return 1;
}
/* PROTO */
void
imcomm_delete_buddylist(struct IMComm_BuddyList * buddylist)
{
struct IMComm_BuddyList *tr, *tmp;
for (tr = buddylist; tr;) {
if (tr->sn)
free(tr->sn);
if (tr->formattedsn)
free(tr->formattedsn);
tmp = tr;
tr = tr->next;
free(tmp);
}
}
/* PROTO */
void
imcomm_delete_familieslist(struct IMComm_Families * families)
{
struct IMComm_Families *tr, *tmp;
for (tr = families; tr;) {
tmp = tr;
tr = tr->next;
free(tmp);
}
}
/* PROTO */
void
imcomm_set_oscar_port(void *handle, uint16_t port)
{
((IMCOMM *) handle)->oscarport = port;
}
/* PROTO */
void *
imcomm_create_child_handle(void *parent)
{
IMCOMM *handle;
IMCOMM_HANDLES *tmp;
int xx;
handle = malloc(sizeof(IMCOMM));
handle->ischild = 1;
handle->proxymode = ((IMCOMM *) parent)->proxymode;
handle->proxyserver = ((IMCOMM *) parent)->proxyserver;
handle->proxyport = ((IMCOMM *) parent)->proxyport;
handle->parent = parent;
handle->to_delete = 0;
handle->seqnum = 0x1000;
handle->snacreq = 0;
handle->families = NULL;
handle->buddylist = NULL;
handle->buddies_online = NULL;
handle->isidle = 0;
handle->last_operation_time = time(NULL);
handle->profile_str = NULL;
handle->away_msg = NULL;
handle->icondata = 0;
handle->iconlen = 0;
handle->socket = 0;
handle->connected = 0;
handle->data = NULL;
handle->header_pos = 0;
#ifdef IMCOMM_KEEPALIVE
handle->last_keepalive_time = 0;
#endif
#ifdef SEND_QUEUES
handle->s_queue = NULL;
#endif
#ifdef MACINTOSH_CLASSIC
handle->readable = 0;
#endif
for (xx = 0; xx < NUM_CALLBACKS; xx++)
handle->callbacks[xx] = ((IMCOMM *) parent)->callbacks[xx];
if (handles == NULL) {
handles = malloc(sizeof(IMCOMM_HANDLES));
handles->handle = handle;
handles->next = NULL;
} else {
tmp = handles;
while (tmp->next != NULL)
tmp = tmp->next;
tmp->next = malloc(sizeof(IMCOMM_HANDLES));
tmp->next->handle = handle;
tmp->next->next = NULL;
}
return (void *) handle;
}
/* PROTO */
void
remove_deleted_handles(void)
{
IMCOMM_HANDLES *trav, *tmp;
if (handles == NULL)
return;
if (handles->handle->to_delete == 1) {
/*
* the last thing it'll do before deleting itself is to send
* a callback saying it's about to be deleted.
*/
if (handles->handle->callbacks[IMCOMM_HANDLE_DELETED])
handles->handle->
callbacks[IMCOMM_HANDLE_DELETED] ((void *) handles->
handle);
tmp = handles;
handles = handles->next;
imcomm_delete_handle_only(tmp->handle);
free(tmp);
remove_deleted_handles();
} else {
for (trav = handles; trav->next;) {
if (trav->next->handle->to_delete == 1) {
tmp = trav->next;
trav->next = trav->next->next;
trav = trav->next;
if (tmp->handle->callbacks[IMCOMM_HANDLE_DELETED])
tmp->handle->
callbacks[IMCOMM_HANDLE_DELETED] ((void *) tmp->
handle);
imcomm_delete_handle_only(tmp->handle);
free(tmp);
}
}
}
}
/* PROTO */
void
imcomm_set_proxy(void *handle, int type, char *proxyserver, uint16_t proxyport)
{
((IMCOMM *) handle)->proxymode = type;
((IMCOMM *) handle)->proxyserver = strdup(proxyserver);
((IMCOMM *) handle)->proxyport = proxyport;
}
/* PROTO */
void
imcomm_register_callback(void *handle, int event, void (*ptr) ())
{
((IMCOMM *) handle)->callbacks[event] = ptr;
}
/* PROTO */
IMCOMM_RET
imcomm_select(int nfds, fd_set * readfds, fd_set * writefds, fd_set * exceptfds, struct timeval * timeout)
{
IMCOMM_HANDLES *tmp;
IMCOMM_RET ret = IMCOMM_RET_OK;
int maxfd = nfds;
#ifdef FULL_PACKET_AT_ONCE
int bytesread;
#endif
/*
* trim the handle list
*/
if (nodes_to_delete == 1) {
remove_deleted_handles();
nodes_to_delete = 0;
}
tmp = handles;
#ifdef MACINTOSH_CLASSIC
TCPiopb pb;
OSErr err;
for (tmp = handles; tmp != NULL; tmp = tmp->next) {
if (tmp->handle->readable == 0)
continue;
pb.ioCRefNum = refnum;
pb.csCode = TCPStatus;
pb.tcpStream = tmp->handle->s;
pb.csParam.status.userDataPtr = (Ptr) tmp->handle;
err = PBControlSync((ParmBlkPtr) & pb);
if (err != noErr)
continue;
if (pb.csParam.status.amtUnreadData >= 6) {
mactcp_recv(tmp->handle, (char *) tmp->handle->header, 6);
tmp->handle->data_len = two_to_16(tmp->handle->header + 4);
tmp->handle->data = malloc(tmp->handle->data_len);
mactcp_recv(tmp->handle, (char *) tmp->handle->data,
tmp->handle->data_len);
ret =
flap_decode(tmp->handle, tmp->handle->header,
tmp->handle->data);
tmp->handle->data = NULL;
}
}
#else
while (tmp != NULL) {
if ((int) tmp->handle->socket > maxfd)
maxfd = tmp->handle->socket;
if (tmp->handle->socket != -1)
FD_SET(tmp->handle->socket, readfds);
tmp = tmp->next;
}
if (select(maxfd + 1, readfds, writefds, exceptfds, timeout) == -1)
return IMCOMM_RET_ERROR;
for (tmp = handles; tmp; tmp = tmp->next) {
if (tmp->handle->socket == -1)
continue;
#ifdef SEND_QUEUES
if (tmp->handle->s_queue != NULL)
flap_sendnext(tmp->handle);
#endif
if (FD_ISSET(tmp->handle->socket, readfds)) {
#ifdef FULL_PACKET_AT_ONCE
bytesread = 0;
do {
if ((bytesread +=
recv(tmp->handle->socket,
tmp->handle->header + bytesread, 6 - bytesread,
0)) <= 0) {
shutdown(tmp->handle->socket, 0x02);
tmp->handle->socket = -1;
tmp->handle->data = NULL;
tmp->handle->connected = 0;
if (tmp->handle->callbacks[IMCOMM_ERROR])
tmp->handle->callbacks[IMCOMM_ERROR] (tmp->handle,
IMCOMM_ERROR_DISCONNECTED);
return IMCOMM_RET_ERROR;
}
} while (bytesread < 6);
tmp->handle->data_len = two_to_16(tmp->handle->header + 4);
tmp->handle->data = malloc(tmp->handle->data_len);
bytesread = 0;
do {
if ((bytesread +=
recv(tmp->handle->socket,
tmp->handle->data + bytesread,
tmp->handle->data_len - bytesread, 0)) <= 0) {
shutdown(tmp->handle->socket, 0x02);
tmp->handle->socket = -1;
tmp->handle->connected = 0;
tmp->handle->data = NULL;
if (tmp->handle->callbacks[IMCOMM_ERROR])
tmp->handle->callbacks[IMCOMM_ERROR] (tmp->handle,
IMCOMM_ERROR_DISCONNECTED);
return IMCOMM_RET_ERROR;
}
} while (bytesread < tmp->handle->data_len);
ret =
flap_decode(tmp->handle, tmp->handle->header,
tmp->handle->data);
tmp->handle->data = NULL;
#else
if (tmp->handle->header_pos < 6) {
if (recv
(tmp->handle->socket,
&tmp->handle->header[tmp->handle->header_pos], 1,
0) <= 0) {
shutdown(tmp->handle->socket, 0x02);
tmp->handle->socket = -1;
tmp->handle->connected = 0;
tmp->handle->header_pos = 0;
tmp->handle->data = NULL;
if (tmp->handle->callbacks[IMCOMM_ERROR])
tmp->handle->callbacks[IMCOMM_ERROR] (tmp->handle,
IMCOMM_ERROR_DISCONNECTED);
return IMCOMM_RET_ERROR;
}
tmp->handle->header_pos++;
if (tmp->handle->header_pos == 6) {
tmp->handle->data_len =
two_to_16(tmp->handle->header + 4);
tmp->handle->data = malloc(tmp->handle->data_len);
tmp->handle->data_pos = 0;
}
} else {
if (recv
(tmp->handle->socket,
&tmp->handle->data[tmp->handle->data_pos], 1,
0) <= 0) {
free(tmp->handle->data);
tmp->handle->data = NULL;
shutdown(tmp->handle->socket, 0x02);
tmp->handle->socket = -1;
tmp->handle->connected = 0;
tmp->handle->header_pos = 0;
if (tmp->handle->callbacks[IMCOMM_ERROR])
tmp->handle->callbacks[IMCOMM_ERROR] (tmp->handle,
IMCOMM_ERROR_DISCONNECTED);
return IMCOMM_RET_ERROR;
}
tmp->handle->data_pos++;
if (tmp->handle->data_pos == tmp->handle->data_len) {
ret =
flap_decode(tmp->handle, tmp->handle->header,
tmp->handle->data);
tmp->handle->data = NULL;
tmp->handle->header_pos = 0;
}
}
#endif
}
/*
* This seems to slow down the DOS port on slower machines,
* so let's get rid of it...
*/
#ifdef IMCOMM_KEEPALIVE
if (time(NULL) - tmp->handle->last_keepalive_time > 300) {
tmp->handle->last_keepalive_time = time(NULL);
if (tmp->handle->srv_pause == 0)
flap_send(tmp->handle, 0x05, NULL, 0, 0);
}
#endif
#if !defined(__DJGPP__) && !defined(NO_AUTO_IDLE)
imcomm_set_idle_time(tmp->handle,
time(NULL) -
tmp->handle->last_operation_time);
#endif
}
#endif
return ret;
}
/* PROTO */
int
imcomm_internal_add_buddy(void *handle, char *sn, const unsigned long idletime, const unsigned long onlinetime, int isaway)
{
IMCOMM_BUDDYLIST *temp, *trav;
char *sname;
sname = imcomm_simplify_sn(sn);
for (trav = ((IMCOMM *) handle)->buddies_online; trav != NULL;
trav = trav->next) {
if (strcmp(sname, trav->sn) == 0) {
free(sname);
return 0;
}
}
temp = malloc(sizeof(IMCOMM_BUDDYLIST));
temp->sn = sname;
temp->formattedsn = NULL;
temp->next = NULL;
temp->isaway = isaway;
temp->idletime = idletime;
temp->onlinetime = onlinetime;
if (((IMCOMM *) handle)->buddies_online == NULL)
((IMCOMM *) handle)->buddies_online = temp;
else {
for (trav = ((IMCOMM *) handle)->buddies_online;
trav->next != NULL; trav = trav->next);
trav->next = temp;
}
return 1;
}
/* PROTO */
void
imcomm_update_buddy_times(void *handle, const char *sn, int type, unsigned long value)
{
IMCOMM_BUDDYLIST *trav = ((IMCOMM *) handle)->buddies_online;
char *sname;
sname = imcomm_simplify_sn(sn);
for (; trav != NULL; trav = trav->next) {
if (strcmp(sname, trav->sn) == 0) {
switch (type) {
case 1:
trav->idletime = value;
if (((IMCOMM *) handle)->callbacks[IMCOMM_IM_IDLEINFO])
((IMCOMM *) handle)->
callbacks[IMCOMM_IM_IDLEINFO] (handle, sn, value);
break;
case 2:
trav->onlinetime = value;
break;
}
}
}
free(sname);
}
/* PROTO */
void
imcomm_update_buddy_away(void *handle, const char *sn, int isaway)
{
char *sname;
IMCOMM_BUDDYLIST *trav = ((IMCOMM *) handle)->buddies_online;
sname = imcomm_simplify_sn(sn);
for (; trav != NULL; trav = trav->next) {
if (strcmp(sname, trav->sn) == 0) {
if (isaway) {
if (!trav->isaway) {
trav->isaway = 1;
if (((IMCOMM *) handle)->
callbacks[IMCOMM_IM_BUDDYAWAY])
((IMCOMM *) handle)->
callbacks[IMCOMM_IM_BUDDYAWAY] (handle, sn);
break;
}
} else if (trav->isaway) {
trav->isaway = 0;
if (((IMCOMM *) handle)->callbacks[IMCOMM_IM_BUDDYUNAWAY])
((IMCOMM *) handle)->
callbacks[IMCOMM_IM_BUDDYUNAWAY] (handle, sn);
break;
}
}
}
free(sname);
}
/* PROTO */
void
imcomm_internal_delete_buddy(void *handle, const char *sn)
{
char *sname;
IMCOMM_BUDDYLIST *temp, *trav;
if (((IMCOMM *) handle)->buddies_online == NULL)
return;
sname = imcomm_simplify_sn(sn);
if (strcmp(((IMCOMM *) handle)->buddies_online->sn, sname) == 0) {
temp = ((IMCOMM *) handle)->buddies_online;
((IMCOMM *) handle)->buddies_online =
((IMCOMM *) handle)->buddies_online->next;
free(temp->sn);
free(temp);
free(sname);
} else {
for (trav = ((IMCOMM *) handle)->buddies_online;
trav->next != NULL; trav = trav->next) {
if (strcmp(trav->next->sn, sname) == 0) {
temp = trav->next;
trav->next = trav->next->next;
free(temp->sn);
free(temp);
free(sname);
break;
}
}
}
}
/* PROTO */
char *
imcomm_simplify_sn(const char *sn)
{
char *temp;
int x, count;
temp = malloc(strlen(sn) + 1);
for (x = 0, count = 0; x < (int) strlen(sn); x++) {
if (sn[x] == ' ')
continue;
temp[count] = tolower(sn[x]);
count++;
}
temp = realloc(temp, count + 1);
temp[count] = 0;
return temp;
}
/* PROTO */
void
imcomm_set_idle_time(void *handle, uint32_t idlesecs)
{
pkt_t *packet;
packet = pkt_init(4);
pkt_add32(packet, idlesecs);
if (idlesecs > 600) {
if (((IMCOMM *) handle)->isidle == 0) {
((IMCOMM *) handle)->isidle = 1;
snac_sendpkt(handle, 0x01, 0x11, packet, 0);
}
} else {
if (((IMCOMM *) handle)->isidle && idlesecs == 0) {
((IMCOMM *) handle)->isidle = 0;
snac_sendpkt(handle, 0x01, 0x11, packet, 0);
}
}
pkt_free(packet);
}
/* PROTO */
void
imcomm_set_profile(void *handle, char *profile)
{
if (((IMCOMM *) handle)->profile_str != NULL)
free(((IMCOMM *) handle)->profile_str);
((IMCOMM *) handle)->profile_str = (unsigned char *) strdup(profile);
if (((IMCOMM *) handle)->socket != 0)
snac_set_location_info(handle);
}
/* PROTO */
void
imcomm_set_invisible(void *handle, int inv)
{
((IMCOMM *) handle)->isinvisible = inv;
snac_send_cli_update(handle);
}
/* PROTO */
void
imcomm_set_away(void *handle, char *msg)
{
IMCOMM *tmp = (IMCOMM *) handle;
tmp->isaway = 1;
tmp->away_msg = (unsigned char *) strdup(msg);
if (tmp->socket != 0)
snac_set_location_info(handle);
}
/* PROTO */
void
imcomm_set_unaway(void *handle)
{
IMCOMM *tmp = (IMCOMM *) handle;
if (tmp->isaway) {
free(tmp->away_msg);
tmp->isaway = 0;
tmp->away_msg = NULL;
if (tmp->socket != 0)
snac_set_location_info(handle);
}
}
/* PROTO */
int
imcomm_compare_nicks(void *handle, const char *s1, const char *s2)
{
char *s3, *s4;
int ret = 0;
s3 = imcomm_simplify_sn(s1);
s4 = imcomm_simplify_sn(s2);
if (strcmp(s3, s4) == 0)
ret = 1;
free(s3);
free(s4);
return ret;
}
/* PROTO */
uint16_t
imcomm_get_max_message_size(void *handle)
{
return ((IMCOMM *) handle)->max_message_size;
}

311
libs/libimcomm/imcomm.h Normal file
View File

@ -0,0 +1,311 @@
/** _
** (_)_ __ __ ___ _ __ _ __
** | | ' \/ _/ _ \ ' \| ' \
** |_|_|_|_\__\___/_|_|_|_|_|_|
**
** Copyright (C) 2003-2005, Claudio Leite
** All rights reserved.
**
** Please see the file 'COPYING' for licensing information.
**/
#ifndef IMCOMM_H
#define IMCOMM_H
#ifdef PLAN9
#define _POSIX_SOURCE
#define _BSD_EXTENSION
#define _POSIX_EXTENSION
#include <errno.h>
/**
** On 386, this is correct. This may not be
** correct on other architectures.
**/
#define uint32_t unsigned long
#define uint16_t unsigned short
#define uint8_t unsigned char
#define int32_t long
#endif
#include <stdio.h>
#include <stdlib.h>
#ifdef _MSC_VER
#define snprintf _snprintf
#else
#include <unistd.h>
#endif
#if defined(WATCOM_WIN32) || defined(_MSC_VER)
#define __MINGW32__ /* works for now */
#endif
#ifdef MACINTOSH_CLASSIC
#include <Types.h>
#include <MacTCP.h>
#include <AddressXlation.h>
#include <time.h>
#else
#ifndef __MINGW32__
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#ifndef __BEOS__
#include <arpa/inet.h>
#endif
#include <netdb.h>
#else
#include <winsock.h>
#ifdef _MSC_VER
typedef __int32 int32_t;
typedef unsigned __int32 uint32_t;
typedef __int16 int16_t;
typedef unsigned __int16 uint16_t;
typedef __int8 int8_t;
typedef unsigned __int8 uint8_t;
#else
#include <stdint.h>
#endif
#include <time.h>
#endif
#endif
#ifdef __BEOS__
#include <inttypes.h>
#endif
#define MD5_LOGIN
#ifdef MACINTOSH_CLASSIC
typedef void fd_set;
typedef unsigned long uint32_t;
typedef unsigned short uint16_t;
typedef unsigned char uint8_t;
char *strdup(char *);
char *strcasecmp(char *, char *);
void mactcp_close(void *handle);
OSErr mactcp_recv(void *handle, char *inbuf, size_t len);
#endif
#ifdef __AMIGA__
#define uint32_t u_int32_t
#define uint16_t u_int16_t
#define uint8_t u_int8_t
#endif
/*
* Read the whole packet at once rather than one byte at a time.
*
* This is necessary for DOS, but all other platforms seem to be OK with reading
* one byte at a time.
*
* UPDATED 0.80: I'm making this the default. I have yet to see an instance
* where this is unacceptable, but yet I've seen plenty of occasions where
* not having it slows old machines down considerably.
*
* Full packet may be frustrating on slow connections?
*/
#define FULL_PACKET_AT_ONCE
#ifndef __DJGPP__
#define IMCOMM_KEEPALIVE
#endif
#define NO_AUTO_IDLE
#ifdef linux
#include <time.h>
#endif
#if defined(__APPLE__) || defined(linux)
#include <stdint.h>
#endif
#include <string.h>
#include <ctype.h>
#define HOST_BIG_ENDIAN 0
#define HOST_LITTLE_ENDIAN 1
#ifdef __DJGPP__
#ifndef __dj_stdint__h_
typedef unsigned long uint32_t;
typedef unsigned short uint16_t;
typedef unsigned char uint8_t;
#endif
#endif
typedef int IMCOMM_RET;
#define IMCOMM_RET_ERROR -1
#define IMCOMM_RET_OK 1
#define NUM_CALLBACKS 11
enum {
IMCOMM_IM_SIGNON,
IMCOMM_IM_SIGNOFF,
IMCOMM_IM_BUDDYAWAY,
IMCOMM_IM_BUDDYUNAWAY,
IMCOMM_IM_IDLEINFO,
IMCOMM_IM_INCOMING,
IMCOMM_IM_PROFILE,
IMCOMM_IM_AWAYMSG,
IMCOMM_ERROR,
IMCOMM_FORMATTED_SN,
IMCOMM_HANDLE_DELETED
};
enum {
PROXY_TYPE_NONE,
PROXY_TYPE_HTTPS,
PROXY_TYPE_SOCKS5
};
enum {
PROXY_ERROR_AUTH,
PROXY_ERROR_CONNECT,
PROXY_ERROR_PROXYCONNECT,
PROXY_ERROR_UNKNOWN
};
enum {
IMCOMM_ERROR_DISCONNECTED,
IMCOMM_STATUS_CONNECTED,
IMCOMM_ERROR_INVALID_LOGIN,
IMCOMM_ERROR_OTHER_SIGNON,
IMCOMM_STATUS_AUTHDONE,
IMCOMM_RATE_LIMIT_WARN,
IMCOMM_WARN_PAUSE,
IMCOMM_WARN_UNPAUSE,
IMCOMM_STATUS_MIGRATIONDONE,
IMCOMM_ERROR_USER_OFFLINE,
IMCOMM_ERROR_PROXY
};
#ifdef SEND_QUEUES
typedef struct IMCommSendQ {
unsigned char *data;
size_t len;
int updateidle;
uint8_t channel;
struct IMCommSendQ *next;
} send_q;
#endif
typedef struct IMComm {
#ifdef MACINTOSH_CLASSIC
StreamPtr s;
int readable;
#endif
#ifdef __MINGW32__
WSADATA wsadata;
SOCKET socket;
#else
int socket;
#endif
#ifdef MD5_LOGIN
char *sn;
char *pw;
#endif
int proxymode;
char *proxyserver;
uint16_t proxyport;
uint16_t oscarport;
unsigned char header[6];
uint8_t header_pos;
unsigned char *data;
uint16_t data_pos;
uint16_t data_len;
int connected;
int srv_pause;
int to_delete;
uint16_t seqnum;
uint32_t snacreq;
uint16_t max_profile_len;
uint16_t max_capabilities;
uint16_t max_buddylist_size;
uint16_t max_num_watchers;
uint16_t max_online_notifications;
uint16_t max_message_size;
uint16_t max_sender_warning;
uint16_t max_receiver_warning;
uint16_t max_message_interval;
uint16_t max_visible_list_size;
uint16_t max_invisible_list_size;
/* void (*callbacks[NUM_CALLBACKS]) (void *,...); */
void (*callbacks[NUM_CALLBACKS]) ();
struct IMComm_Families *families;
int num_families;
struct IMComm_BuddyList *buddylist;
struct IMComm_BuddyList *buddies_online;
int isidle;
int isaway;
int isinvisible;
long last_operation_time;
unsigned char *profile_str;
unsigned char *away_msg;
#ifdef IMCOMM_KEEPALIVE
long last_keepalive_time;
#endif
#ifdef SEND_QUEUES
send_q *s_queue;
#endif
int ischild;
void *parent;
uint8_t *icondata;
uint16_t iconlen;
} IMCOMM;
typedef struct IMComm_Families {
uint16_t family;
struct IMComm_Families *next;
} IMCOMM_FAMILIES;
typedef struct IMComm_BuddyList {
char *sn;
char *formattedsn;
unsigned long idletime;
unsigned long onlinetime;
uint16_t ssi_id;
uint16_t group_id;
int isaway;
struct IMComm_BuddyList *next;
} IMCOMM_BUDDYLIST;
typedef struct IMComm_Handles {
IMCOMM *handle;
struct IMComm_Handles *next;
} IMCOMM_HANDLES;
typedef struct TLVList {
uint16_t type;
uint16_t len;
uint8_t *value;
struct TLVList *next;
} TLVLIST;
typedef struct IMComm_Packet {
unsigned char *data;
size_t len;
size_t offset;
} pkt_t;
struct MultiPacket {
int init;
uint8_t channel;
unsigned char *packet;
size_t len;
int updateidle;
struct MultiPacket *next;
};
#include "protos.h"
#include "byteswap.h"
#endif

View File

@ -0,0 +1,18 @@
# Get prototypes from a .c file
# $Id: makeprotos-sed,v 1.1.1.1 2004/07/19 14:32:40 leitec Exp $
# /* PROTO */ must be above return type which are above function.
# Args are on one line
# eg.
# /* PROTO */
# void ------> void main(int argc, char **argv);
# main(int argc, char **argv)
# {
# }
#
/^[/][*] PROTO [*][/]$/{
n
N
s/\n\([_a-zA-Z][_a-zA-Z0-9]* *\)(/ \1 (/
s/$/;/
p
}

394
libs/libimcomm/md5.c Normal file
View File

@ -0,0 +1,394 @@
/*
* NOTE: I changed "int" to "int32_t" across the board, plus the changes
* indicated in md5.h
*
* Claudio Leite
*/
/*
* Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved.
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from
* the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not claim
* that you wrote the original software. If you use this software in a
* product, an acknowledgment in the product documentation would be
* appreciated but is not required. 2. Altered source versions must be
* plainly marked as such, and must not be misrepresented as being the
* original software. 3. This notice may not be removed or altered from any
* source distribution.
*
* L. Peter Deutsch ghost@aladdin.com
*
*/
/* $Id: md5.c,v 1.8 2007/09/15 14:52:24 leitec Exp $ */
/*
* Independent implementation of MD5 (RFC 1321).
*
* This code implements the MD5 Algorithm defined in RFC 1321, whose text is
* available at http://www.ietf.org/rfc/rfc1321.txt The code is derived from
* the text of the RFC, including the test suite (section A.5) but excluding
* the rest of Appendix A. It does not include any code or documentation
* that is identified in the RFC as being copyrighted.
*
* The original and principal author of md5.c is L. Peter Deutsch
* <ghost@aladdin.com>. Other authors are noted in the change history that
* follows (in reverse chronological order):
*
* 2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order
* either statically or dynamically; added missing #include <string.h> in
* library. 2002-03-11 lpd Corrected argument list for main(), and added int
* return type, in test program and T value program. 2002-02-21 lpd Added
* missing #include <stdio.h> in test program. 2000-07-03 lpd Patched to
* eliminate warnings about "constant is unsigned in ANSI C, signed in
* traditional"; made test program self-checking. 1999-11-04 lpd Edited
* comments slightly for automatic TOC extraction. 1999-10-18 lpd Fixed typo
* in header comment (ansi2knr rather than md5). 1999-05-03 lpd Original
* version.
*/
#include "md5.h"
#include <string.h>
#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 =
* unknown */
#ifdef ARCH_IS_BIG_ENDIAN
#define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1)
#else
#define BYTE_ORDER 0
#endif
#define T_MASK ((md5_word_t)~0)
#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
#define T3 0x242070db
#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
#define T6 0x4787c62a
#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
#define T9 0x698098d8
#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
#define T13 0x6b901122
#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
#define T16 0x49b40821
#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
#define T19 0x265e5a51
#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
#define T22 0x02441453
#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
#define T25 0x21e1cde6
#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
#define T28 0x455a14ed
#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
#define T31 0x676f02d9
#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
#define T35 0x6d9d6122
#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
#define T38 0x4bdecfa9
#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
#define T41 0x289b7ec6
#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
#define T44 0x04881d05
#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
#define T47 0x1fa27cf8
#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
#define T50 0x432aff97
#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
#define T53 0x655b59c3
#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
#define T57 0x6fa87e4f
#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
#define T60 0x4e0811a1
#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
#define T63 0x2ad7d2bb
#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
static void
md5_process(md5_state_t * pms, const md5_byte_t * data /* [64] */ )
{
md5_word_t a = pms->abcd[0], b = pms->abcd[1], c = pms->abcd[2], d =
pms->abcd[3];
md5_word_t t;
#if BYTE_ORDER > 0
/* Define storage only for big-endian CPUs. */
md5_word_t X[16];
#else
/* Define storage for little-endian or both types of CPUs. */
md5_word_t xbuf[16];
const md5_word_t *X;
#endif
{
#if BYTE_ORDER == 0
/*
* Determine dynamically whether this is a big-endian or
* little-endian machine, since we can use a more efficient
* algorithm on the latter.
*/
static const int32_t w = 1;
if (*((const md5_byte_t *) & w)) /* dynamic little-endian */
#endif
#if BYTE_ORDER <= 0 /* little-endian */
{
/*
* On little-endian machines, we can process properly
* aligned data without copying it.
*/
if (!((data - (const md5_byte_t *) 0) & 3)) {
/* data are properly aligned */
X = (const md5_word_t *) data;
} else {
/* not aligned */
memcpy(xbuf, data, 64);
X = xbuf;
}
}
#endif
#if BYTE_ORDER == 0
else /* dynamic big-endian */
#endif
#if BYTE_ORDER >= 0 /* big-endian */
{
/*
* On big-endian machines, we must arrange the bytes
* in the right order.
*/
const md5_byte_t *xp = data;
int32_t i;
#if BYTE_ORDER == 0
X = xbuf; /* (dynamic only) */
#else
#define xbuf X /* (static only) */
#endif
for (i = 0; i < 16; ++i, xp += 4)
xbuf[i] =
xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
}
#endif
}
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
/* Round 1. */
/*
* Let [abcd k s i] denote the operation a = b + ((a + F(b,c,d) +
* X[k] + T[i]) <<< s).
*/
#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
#define SET(a, b, c, d, k, s, Ti)\
t = a + F(b,c,d) + X[k] + Ti;\
a = ROTATE_LEFT(t, s) + b
/* Do the following 16 operations. */
SET(a, b, c, d, 0, 7, T1);
SET(d, a, b, c, 1, 12, T2);
SET(c, d, a, b, 2, 17, T3);
SET(b, c, d, a, 3, 22, T4);
SET(a, b, c, d, 4, 7, T5);
SET(d, a, b, c, 5, 12, T6);
SET(c, d, a, b, 6, 17, T7);
SET(b, c, d, a, 7, 22, T8);
SET(a, b, c, d, 8, 7, T9);
SET(d, a, b, c, 9, 12, T10);
SET(c, d, a, b, 10, 17, T11);
SET(b, c, d, a, 11, 22, T12);
SET(a, b, c, d, 12, 7, T13);
SET(d, a, b, c, 13, 12, T14);
SET(c, d, a, b, 14, 17, T15);
SET(b, c, d, a, 15, 22, T16);
#undef SET
/* Round 2. */
/*
* Let [abcd k s i] denote the operation a = b + ((a + G(b,c,d) +
* X[k] + T[i]) <<< s).
*/
#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
#define SET(a, b, c, d, k, s, Ti)\
t = a + G(b,c,d) + X[k] + Ti;\
a = ROTATE_LEFT(t, s) + b
/* Do the following 16 operations. */
SET(a, b, c, d, 1, 5, T17);
SET(d, a, b, c, 6, 9, T18);
SET(c, d, a, b, 11, 14, T19);
SET(b, c, d, a, 0, 20, T20);
SET(a, b, c, d, 5, 5, T21);
SET(d, a, b, c, 10, 9, T22);
SET(c, d, a, b, 15, 14, T23);
SET(b, c, d, a, 4, 20, T24);
SET(a, b, c, d, 9, 5, T25);
SET(d, a, b, c, 14, 9, T26);
SET(c, d, a, b, 3, 14, T27);
SET(b, c, d, a, 8, 20, T28);
SET(a, b, c, d, 13, 5, T29);
SET(d, a, b, c, 2, 9, T30);
SET(c, d, a, b, 7, 14, T31);
SET(b, c, d, a, 12, 20, T32);
#undef SET
/* Round 3. */
/*
* Let [abcd k s t] denote the operation a = b + ((a + H(b,c,d) +
* X[k] + T[i]) <<< s).
*/
#define H(x, y, z) ((x) ^ (y) ^ (z))
#define SET(a, b, c, d, k, s, Ti)\
t = a + H(b,c,d) + X[k] + Ti;\
a = ROTATE_LEFT(t, s) + b
/* Do the following 16 operations. */
SET(a, b, c, d, 5, 4, T33);
SET(d, a, b, c, 8, 11, T34);
SET(c, d, a, b, 11, 16, T35);
SET(b, c, d, a, 14, 23, T36);
SET(a, b, c, d, 1, 4, T37);
SET(d, a, b, c, 4, 11, T38);
SET(c, d, a, b, 7, 16, T39);
SET(b, c, d, a, 10, 23, T40);
SET(a, b, c, d, 13, 4, T41);
SET(d, a, b, c, 0, 11, T42);
SET(c, d, a, b, 3, 16, T43);
SET(b, c, d, a, 6, 23, T44);
SET(a, b, c, d, 9, 4, T45);
SET(d, a, b, c, 12, 11, T46);
SET(c, d, a, b, 15, 16, T47);
SET(b, c, d, a, 2, 23, T48);
#undef SET
/* Round 4. */
/*
* Let [abcd k s t] denote the operation a = b + ((a + I(b,c,d) +
* X[k] + T[i]) <<< s).
*/
#define I(x, y, z) ((y) ^ ((x) | ~(z)))
#define SET(a, b, c, d, k, s, Ti)\
t = a + I(b,c,d) + X[k] + Ti;\
a = ROTATE_LEFT(t, s) + b
/* Do the following 16 operations. */
SET(a, b, c, d, 0, 6, T49);
SET(d, a, b, c, 7, 10, T50);
SET(c, d, a, b, 14, 15, T51);
SET(b, c, d, a, 5, 21, T52);
SET(a, b, c, d, 12, 6, T53);
SET(d, a, b, c, 3, 10, T54);
SET(c, d, a, b, 10, 15, T55);
SET(b, c, d, a, 1, 21, T56);
SET(a, b, c, d, 8, 6, T57);
SET(d, a, b, c, 15, 10, T58);
SET(c, d, a, b, 6, 15, T59);
SET(b, c, d, a, 13, 21, T60);
SET(a, b, c, d, 4, 6, T61);
SET(d, a, b, c, 11, 10, T62);
SET(c, d, a, b, 2, 15, T63);
SET(b, c, d, a, 9, 21, T64);
#undef SET
/*
* Then perform the following additions. (That is increment each of
* the four registers by the value it had before this block was
* started.)
*/
pms->abcd[0] += a;
pms->abcd[1] += b;
pms->abcd[2] += c;
pms->abcd[3] += d;
}
void
md5_init(md5_state_t * pms)
{
pms->count[0] = pms->count[1] = 0;
pms->abcd[0] = 0x67452301;
pms->abcd[1] = /* 0xefcdab89 */ T_MASK ^ 0x10325476;
pms->abcd[2] = /* 0x98badcfe */ T_MASK ^ 0x67452301;
pms->abcd[3] = 0x10325476;
}
void
md5_append(md5_state_t * pms, const md5_byte_t * data, int32_t nbytes)
{
const md5_byte_t *p = data;
int32_t left = nbytes;
int32_t offset = (pms->count[0] >> 3) & 63;
md5_word_t nbits = (md5_word_t) (nbytes << 3);
if (nbytes <= 0)
return;
/* Update the message length. */
pms->count[1] += nbytes >> 29;
pms->count[0] += nbits;
if (pms->count[0] < nbits)
pms->count[1]++;
/* Process an initial partial block. */
if (offset) {
int32_t copy =
(offset + nbytes > 64 ? 64 - offset : nbytes);
memcpy(pms->buf + offset, p, copy);
if (offset + copy < 64)
return;
p += copy;
left -= copy;
md5_process(pms, pms->buf);
}
/* Process full blocks. */
for (; left >= 64; p += 64, left -= 64)
md5_process(pms, p);
/* Process a final partial block. */
if (left)
memcpy(pms->buf, p, left);
}
void
md5_finish(md5_state_t * pms, md5_byte_t digest[16])
{
static const md5_byte_t pad[64] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
md5_byte_t data[8];
int32_t i;
/* Save the length before padding. */
for (i = 0; i < 8; ++i)
data[i] = (md5_byte_t) (pms->count[i >> 2] >> ((i & 3) << 3));
/* Pad to 56 bytes mod 64. */
md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
/* Append the length. */
md5_append(pms, data, 8);
for (i = 0; i < 16; ++i)
digest[i] = (md5_byte_t) (pms->abcd[i >> 2] >> ((i & 3) << 3));
}

98
libs/libimcomm/md5.h Normal file
View File

@ -0,0 +1,98 @@
/*
* NOTE:
*
* I've changed some of the int types around to match the rest of the IMcomm
* source.
*
* -Claudio Leite
*/
/*
* Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved.
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from
* the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not claim
* that you wrote the original software. If you use this software in a
* product, an acknowledgment in the product documentation would be
* appreciated but is not required. 2. Altered source versions must be
* plainly marked as such, and must not be misrepresented as being the
* original software. 3. This notice may not be removed or altered from any
* source distribution.
*
* L. Peter Deutsch ghost@aladdin.com
*
*/
/* $Id: md5.h,v 1.8 2007/09/15 14:52:24 leitec Exp $ */
/*
* Independent implementation of MD5 (RFC 1321).
*
* This code implements the MD5 Algorithm defined in RFC 1321, whose text is
* available at http://www.ietf.org/rfc/rfc1321.txt The code is derived from
* the text of the RFC, including the test suite (section A.5) but excluding
* the rest of Appendix A. It does not include any code or documentation
* that is identified in the RFC as being copyrighted.
*
* The original and principal author of md5.h is L. Peter Deutsch
* <ghost@aladdin.com>. Other authors are noted in the change history that
* follows (in reverse chronological order):
*
* 2002-04-13 lpd Removed support for non-ANSI compilers; removed references to
* Ghostscript; clarified derivation from RFC 1321; now handles byte order
* either statically or dynamically. 1999-11-04 lpd Edited comments slightly
* for automatic TOC extraction. 1999-10-18 lpd Fixed typo in header comment
* (ansi2knr rather than md5); added conditionalization for C++ compilation
* from Martin Purschke <purschke@bnl.gov>. 1999-05-03 lpd Original version.
*/
#ifndef md5_INCLUDED
#define md5_INCLUDED
/* added by Claudio Leite */
#include "imcomm.h"
/* end */
/*
* This package supports both compile-time and run-time determination of CPU
* byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be
* compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is
* defined as non-zero, the code will be compiled to run only on big-endian
* CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to
* run on either big- or little-endian CPUs, but will run slightly less
* efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined.
*/
typedef uint8_t md5_byte_t; /* 8-bit byte */
typedef uint32_t md5_word_t; /* 32-bit word */
/* Define the state of the MD5 Algorithm. */
typedef struct md5_state_s {
md5_word_t count[2]; /* message length in bits, lsw first */
md5_word_t abcd[4];/* digest buffer */
md5_byte_t buf[64];/* accumulate block */
} md5_state_t;
#ifdef __cplusplus
extern "C" {
#endif
/* Initialize the algorithm. */
void md5_init(md5_state_t * pms);
/* Append a string to the message. */
void md5_append(md5_state_t * pms, const md5_byte_t * data,
int32_t nbytes);
/* Finish the message and return the digest. */
void md5_finish(md5_state_t * pms, md5_byte_t digest[16]);
#ifdef __cplusplus
} /* end extern "C" */
#endif
#endif /* md5_INCLUDED */

25
libs/libimcomm/misc.c Normal file
View File

@ -0,0 +1,25 @@
/** _
** (_)_ __ __ ___ _ __ _ __
** | | ' \/ _/ _ \ ' \| ' \
** |_|_|_|_\__\___/_|_|_|_|_|_|
**
** Copyright (C) 2003-2005, Claudio Leite
** All rights reserved.
**
** Please see the file 'COPYING' for licensing information.
**/
#include "imcomm.h"
/* PROTO */
int
getbyteorder(void)
{
uint16_t blah = 0x5533;
uint8_t *ptr = (uint8_t *) & blah;
if ((*ptr) == 0x55)
return HOST_BIG_ENDIAN;
else
return HOST_LITTLE_ENDIAN;
}

6
libs/libimcomm/mkprotos Normal file
View File

@ -0,0 +1,6 @@
#!/bin/sh
rm -f protos.h
for i in *.c; do
sed -n -f ./makeprotos-sed $i >> protos.h
done

303
libs/libimcomm/packet.c Normal file
View File

@ -0,0 +1,303 @@
/** _
** (_)_ __ __ ___ _ __ _ __
** | | ' \/ _/ _ \ ' \| ' \
** |_|_|_|_\__\___/_|_|_|_|_|_|
**
** Copyright (C) 2003-2005, Claudio Leite
** All rights reserved.
**
** Please see the file 'COPYING' for licensing information.
**/
/*
* packet.c
*
* Contains the packet code. This is inspired by FAIM's bstream code, and will
* resolve the portability problems caused by my shoddy allocations in
* previous versions.
*
* Basically, instead of doing everything manually by using assignment
* statements like: unsigned char packet[] = {0x00, 0x01, 0x03} or
* packet[pos++] = 0x04; we define a packet dynamically, allocating memory
* once (pkt_init) and then creating a separate function for each data type
* to be added, with a "raw" function for any unhandled data.
*
* This is mostly because the older code didn't compile on basically anything
* but GCC. When I came around to porting to Macintosh, it became apparent
* that my nasty code had to change!
*/
#include "imcomm.h"
#include <assert.h>
extern int endianness;
/*
* Create an empty packet.
*/
/* PROTO */
pkt_t *
pkt_init(size_t len)
{
pkt_t *pkt = NULL;
pkt = malloc((size_t) sizeof(struct IMComm_Packet));
pkt->data = malloc(len);
pkt->len = len;
pkt->offset = 0;
return pkt;
}
/* PROTO */
void
pkt_zero(pkt_t * pkt)
{
assert(pkt != NULL);
memset(pkt->data, 0, pkt->len);
}
/* PROTO */
void
pkt_free(pkt_t * pkt)
{
assert(pkt != NULL);
if (pkt->data != NULL) {
free(pkt->data);
}
free(pkt);
}
/* PROTO */
void
pkt_freeP(pkt_t * pkt)
{
assert(pkt != NULL);
/* don't touch the data */
free(pkt);
}
/*
* This points the data to an already initialized buffer (say, a received
* packet) instead of copying data.
*/
/* PROTO */
pkt_t *
pkt_initP(uint8_t * data, uint16_t len)
{
pkt_t *pkt;
pkt = malloc(sizeof(struct IMComm_Packet));
pkt->data = data;
pkt->len = (size_t) len;
pkt->offset = 0;
return pkt;
}
/* PROTO */
size_t
pkt_empty(pkt_t * pkt)
{
return pkt->len - pkt->offset;
}
/* PROTO */
size_t
pkt_getoffset(pkt_t * pkt)
{
return pkt->offset;
}
/* PROTO */
void
pkt_skip(pkt_t * pkt, size_t skipnum)
{
/* assert(pkt->offset + skipnum < pkt->len); */
pkt->offset += skipnum;
}
/* PROTO */
void
pkt_setoffset(pkt_t * pkt, size_t offset)
{
assert(offset < pkt->len);
pkt->offset = offset;
}
/* PROTO */
int
pkt_end(pkt_t * pkt)
{
if (pkt->offset >= pkt->len)
return 1;
else
return 0;
}
/* PROTO */
IMCOMM_RET
pkt_add8(pkt_t * pkt, uint8_t data)
{
if (pkt_empty(pkt) < 1)
return IMCOMM_RET_ERROR;
memcpy(pkt->data + pkt->offset, &data, 1);
pkt->offset++;
return IMCOMM_RET_OK;
}
/*
* AIM is big-endian.
*
* Endianness is determined at startup and stored in a global var.
*/
/* PROTO */
IMCOMM_RET
pkt_add16(pkt_t * pkt, uint16_t val)
{
uint16_t tmpval;
if (pkt_empty(pkt) < 2)
return IMCOMM_RET_ERROR;
if (endianness == HOST_BIG_ENDIAN) {
memcpy(pkt->data + pkt->offset, &val, 2);
} else {
tmpval = BYTE_SWAP_16(val);
memcpy(pkt->data + pkt->offset, &tmpval, 2);
}
pkt->offset += 2;
return IMCOMM_RET_OK;
}
/* PROTO */
IMCOMM_RET
pkt_add32(pkt_t * pkt, uint32_t val)
{
uint32_t tmpval;
if (pkt_empty(pkt) < 4)
return IMCOMM_RET_ERROR;
if (endianness == HOST_BIG_ENDIAN) {
memcpy(pkt->data + pkt->offset, &val, 4);
} else {
tmpval = BYTE_SWAP_32(val);
memcpy(pkt->data + pkt->offset, &tmpval, 4);
}
pkt->offset += 4;
return IMCOMM_RET_OK;
}
/* PROTO */
IMCOMM_RET
pkt_addraw(pkt_t * pkt, uint8_t * data, size_t len)
{
if (pkt_empty(pkt) < len)
return IMCOMM_RET_ERROR;
memcpy(pkt->data + pkt->offset, data, len);
pkt->offset += len;
return IMCOMM_RET_OK;
}
/* PROTO */
uint8_t
pkt_get8(pkt_t * pkt)
{
uint8_t val;
memcpy(&val, pkt->data + pkt->offset, 1);
pkt->offset++;
return val;
}
/* PROTO */
uint16_t
pkt_get16(pkt_t * pkt)
{
uint16_t val;
memcpy(&val, pkt->data + pkt->offset, 2);
if (endianness == HOST_LITTLE_ENDIAN)
val = BYTE_SWAP_16(val);
pkt->offset += 2;
return val;
}
/* PROTO */
uint32_t
pkt_get32(pkt_t * pkt)
{
uint32_t val;
memcpy(&val, pkt->data + pkt->offset, 4);
if (endianness == HOST_LITTLE_ENDIAN)
val = BYTE_SWAP_32(val);
pkt->offset += 4;
return val;
}
/* PROTO */
uint8_t *
pkt_getraw(pkt_t * pkt, size_t len)
{
uint8_t *buf;
buf = malloc(len);
memcpy(buf, pkt->data + pkt->offset, len);
pkt->offset += (uint16_t) len;
return buf;
}
/* PROTO */
uint8_t *
pkt_getstr(pkt_t * pkt, size_t len)
{
uint8_t *buf;
buf = malloc(len + 1);
memcpy(buf, pkt->data + pkt->offset, len);
pkt->offset += (uint16_t) len;
buf[len] = 0;
return buf;
}
#ifdef DEBUG
/* PROTO */
void
pkt_dump(pkt_t * pkt)
{
int x;
printf("!! ");
for (x = 0; x < pkt->len; x++) {
if (pkt->data[x] >= 32 && pkt->data[x] < 128)
putchar(pkt->data[x]);
else
putchar('.');
}
printf("\n!! ");
for (x = 0; x < pkt->len; x++)
printf("%02X ", pkt->data[x]);
printf("\n");
}
#endif

109
libs/libimcomm/protos.h Normal file
View File

@ -0,0 +1,109 @@
#ifdef __cplusplus
extern "C" {
#endif
IMCOMM_RET imcomm_im_signon(void *handle, const char *sn, const char *pw);
IMCOMM_RET bos_signon_phase2(void *handle, unsigned const char *server, unsigned const char *cookie, uint16_t cookie_len);
void handle_srv_migration(void *handle, uint8_t * data, uint16_t len);
void bos_md5snac(void *handle, uint8_t * data, uint16_t len);
IMCOMM_RET flap_send(void *handle, uint8_t channel, unsigned char *packet, size_t len, int updateidle);
struct MultiPacket *MultiPktInit(void);
void MultiPktFree(struct MultiPacket * h);
void flap_addToMulti(struct MultiPacket * mpkt, uint8_t channel, unsigned char *packet, size_t len, int updateidle);
IMCOMM_RET flap_sendMulti(void *handle, struct MultiPacket * pktlist);
IMCOMM_RET flap_sendAct(void *handle, uint8_t channel, unsigned char *packet, size_t len, int updateidle);
IMCOMM_RET flap_sendnext(void *handle);
IMCOMM_RET flap_sendpkt(void *handle, uint8_t channel, pkt_t * pkt, int updateidle);
IMCOMM_RET flap_decode(void *handle, unsigned char *header, unsigned char *data);
void *imcomm_create_handle(void);
int imcomm_delete_handle_now(void *vhandle);
int imcomm_delete_handle(void *vhandle);
int imcomm_delete_handle_only(void *vhandle);
void imcomm_delete_buddylist(struct IMComm_BuddyList * buddylist);
void imcomm_delete_familieslist(struct IMComm_Families * families);
void imcomm_set_oscar_port(void *handle, uint16_t port);
void *imcomm_create_child_handle(void *parent);
void remove_deleted_handles(void);
void imcomm_set_proxy(void *handle, int type, char *proxyserver, uint16_t proxyport);
void imcomm_register_callback(void *handle, int event, void (*ptr) ());
IMCOMM_RET imcomm_select(int nfds, fd_set * readfds, fd_set * writefds, fd_set * exceptfds, struct timeval * timeout);
int imcomm_internal_add_buddy(void *handle, char *sn, const unsigned long idletime, const unsigned long onlinetime, int isaway);
void imcomm_update_buddy_times(void *handle, const char *sn, int type, unsigned long value);
void imcomm_update_buddy_away(void *handle, const char *sn, int isaway);
void imcomm_internal_delete_buddy(void *handle, const char *sn);
char *imcomm_simplify_sn(const char *sn);
void imcomm_set_idle_time(void *handle, uint32_t idlesecs);
void imcomm_set_profile(void *handle, char *profile);
void imcomm_set_invisible(void *handle, int inv);
void imcomm_set_away(void *handle, char *msg);
void imcomm_set_unaway(void *handle);
int imcomm_compare_nicks(void *handle, const char *s1, const char *s2);
uint16_t imcomm_get_max_message_size(void *handle);
int getbyteorder(void);
pkt_t *pkt_init(size_t len);
void pkt_zero(pkt_t * pkt);
void pkt_free(pkt_t * pkt);
void pkt_freeP(pkt_t * pkt);
pkt_t *pkt_initP(uint8_t * data, uint16_t len);
size_t pkt_empty(pkt_t * pkt);
size_t pkt_getoffset(pkt_t * pkt);
void pkt_skip(pkt_t * pkt, size_t skipnum);
void pkt_setoffset(pkt_t * pkt, size_t offset);
int pkt_end(pkt_t * pkt);
IMCOMM_RET pkt_add8(pkt_t * pkt, uint8_t data);
IMCOMM_RET pkt_add16(pkt_t * pkt, uint16_t val);
IMCOMM_RET pkt_add32(pkt_t * pkt, uint32_t val);
IMCOMM_RET pkt_addraw(pkt_t * pkt, uint8_t * data, size_t len);
uint8_t pkt_get8(pkt_t * pkt);
uint16_t pkt_get16(pkt_t * pkt);
uint32_t pkt_get32(pkt_t * pkt);
uint8_t *pkt_getraw(pkt_t * pkt, size_t len);
uint8_t *pkt_getstr(pkt_t * pkt, size_t len);
void pkt_dump(pkt_t * pkt);
int connect_socks5(void *handle, char *host, uint16_t port);
int connect_https(void *handle, char *host, uint16_t port);
IMCOMM_RET snac_decode(void *handle, uint8_t * data, uint16_t len);
void snac_addToMulti(void *handle, struct MultiPacket * mpkt, uint16_t family, uint16_t subtype, unsigned char *data, uint16_t len, int updateidle);
IMCOMM_RET snac_send(void *handle, uint16_t family, uint16_t subtype, unsigned char *data, uint16_t len, int updateidle);
IMCOMM_RET snac_sendpkt(void *handle, uint8_t family, uint8_t subtype, pkt_t * pkt, int updateidle);
IMCOMM_RET snac_send_versions(void *handle);
IMCOMM_RET snac_request_limits(void *handle);
IMCOMM_RET snac_ack_srv_pause(void *handle, uint8_t * data, size_t len);
IMCOMM_RET snac_get_srv_families(void *handle, uint8_t * data, size_t len);
IMCOMM_RET snac_ack_limits(void *handle, unsigned char *data, size_t len);
IMCOMM_RET snac_multireq(void *handle);
IMCOMM_RET snac_get_privacy_rights(void *handle, uint8_t * data, uint16_t len);
IMCOMM_RET snac_set_location_info(void *handle);
IMCOMM_RET snac_send_icbm_params(void *handle, uint16_t channel, uint16_t max_msg_size);
IMCOMM_RET snac_ssi_activate(void *handle);
IMCOMM_RET snac_ssi_get_list(void *handle, uint8_t * data, uint16_t len);
IMCOMM_RET snac_send_cli_update(void *handle);
IMCOMM_RET multi_ssiact_cliready(void *handle);
IMCOMM_RET snac_send_cli_ready(void *handle);
size_t count_tlv(unsigned char *data, size_t len);
size_t count_tlv_pkt(pkt_t * tp);
TLVLIST *tlv_split(unsigned char *data, size_t len, size_t numtlv);
void clear_tlv_list(TLVLIST * tlvlist);
uint32_t four_to_32(unsigned char *value);
uint16_t two_to_16(unsigned char *value);
IMCOMM_RET snac_get_incoming_im(void *handle, uint8_t * data, uint16_t len);
IMCOMM_RET snac_get_signoff(void *handle, uint8_t * data, uint16_t len);
IMCOMM_RET snac_get_signon(void *handle, uint8_t * data, uint16_t len);
void snac_get_user_info(void *handle, uint8_t * data, uint16_t len);
void imcomm_im_send_message(void *handle, const char *whom, const char *msg, int automsg);
void imcomm_request_awayprofile(void *handle, char *sn);
void imcomm_request_profile(void *handle, char *sn);
void imcomm_request_awaymsg(void *handle, char *sn);
void imcomm_request_massawaymsg(void *handle, char **sns, int num);
void imcomm_addtobuddylist(void *handle, char *sn, uint16_t id, uint16_t group_id);
uint16_t imcomm_get_next_id(void *handle);
void imcomm_im_add_buddy(void *handle, char *sn);
void imcomm_im_remove_buddy(void *handle, const char *sn);
void snac_request_new_service(void *handle, uint16_t service);
void snac_new_subconnection(void *handle, unsigned char *data, uint16_t len);
void imcomm_upload_icon(void *handle, uint8_t * data, uint16_t icon_len);
void snac_finish_buddy_icon(void *handle);
#ifdef __cplusplus
}
#endif

227
libs/libimcomm/proxy.c Normal file
View File

@ -0,0 +1,227 @@
/** _
** (_)_ __ __ ___ _ __ _ __
** | | ' \/ _/ _ \ ' \| ' \
** |_|_|_|_\__\___/_|_|_|_|_|_|
**
** Copyright (C) 2003-2005, Claudio Leite
** All rights reserved.
**
** Please see the file 'COPYING' for licensing information.
**/
#include "imcomm.h"
/* PROTO */
int
connect_socks5(void *handle, char *host, uint16_t port)
{
IMCOMM *h = (IMCOMM *) handle;
struct sockaddr_in sin;
struct hostent *he = NULL;
long addy;
struct in_addr ina = {0};
pkt_t *sockspkt;
uint8_t len;
unsigned char sockbuf[512];
#ifdef DEBUG
printf("Connecting via SOCKS5 to %s/%u\n", host, port);
printf("SOCKS5 proxy server: %s/%u\n", h->proxyserver, h->proxyport);
#endif
if ((he = gethostbyname(h->proxyserver)) == NULL) {
addy = inet_addr(h->proxyserver);
ina.s_addr = addy;
}
if ((h->socket = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
if (h->callbacks[IMCOMM_ERROR])
h->callbacks[IMCOMM_ERROR] (handle, IMCOMM_ERROR_PROXY,
PROXY_ERROR_CONNECT);
return IMCOMM_RET_ERROR;
}
sin.sin_family = AF_INET;
sin.sin_port = htons(h->proxyport);
if (he == NULL)
sin.sin_addr = ina;
else
sin.sin_addr = *((struct in_addr *) he->h_addr);
memset(&(sin.sin_zero), 0, 8);
if (connect
(h->socket, (struct sockaddr *) & sin,
sizeof(struct sockaddr)) == -1) {
if (h->callbacks[IMCOMM_ERROR])
h->callbacks[IMCOMM_ERROR] (handle, IMCOMM_ERROR_PROXY,
PROXY_ERROR_CONNECT);
return IMCOMM_RET_ERROR;
}
sockspkt = pkt_init(3);
pkt_add8(sockspkt, 0x05);
pkt_add8(sockspkt, 0x01);
pkt_add8(sockspkt, 0x00);
if (send(h->socket, sockspkt->data, sockspkt->len, 0) < 0) {
pkt_free(sockspkt);
if (h->callbacks[IMCOMM_ERROR])
h->callbacks[IMCOMM_ERROR] (handle, IMCOMM_ERROR_DISCONNECTED,
0);
shutdown(h->socket, 0x02);
h->socket = -1;
return IMCOMM_RET_ERROR;
}
pkt_free(sockspkt);
recv(h->socket, sockbuf, 2, 0);
if (sockbuf[1] != 0x00) {
if (h->callbacks[IMCOMM_ERROR])
h->callbacks[IMCOMM_ERROR] (handle, IMCOMM_ERROR_PROXY,
PROXY_ERROR_AUTH);
return IMCOMM_RET_ERROR;
}
sockspkt = pkt_init(7 + strlen(host));
pkt_add8(sockspkt, 0x05);
pkt_add8(sockspkt, 0x01);
pkt_add8(sockspkt, 0x00);
pkt_add8(sockspkt, 0x03);
pkt_add8(sockspkt, (uint8_t) strlen(host));
pkt_addraw(sockspkt, (unsigned char *) host, strlen(host));
pkt_add16(sockspkt, port);
if (send(h->socket, sockspkt->data, sockspkt->len, 0) < 0) {
pkt_free(sockspkt);
if (h->callbacks[IMCOMM_ERROR])
h->callbacks[IMCOMM_ERROR] (handle, IMCOMM_ERROR_DISCONNECTED,
0);
shutdown(h->socket, 0x02);
h->socket = -1;
return IMCOMM_RET_ERROR;
}
pkt_free(sockspkt);
recv(h->socket, sockbuf, 4, 0);
if (sockbuf[1] != 0x00) {
if (h->callbacks[IMCOMM_ERROR])
h->callbacks[IMCOMM_ERROR] (handle, IMCOMM_ERROR_PROXY,
PROXY_ERROR_PROXYCONNECT);
shutdown(h->socket, 0x02);
h->socket = -1;
return IMCOMM_RET_ERROR;
}
if (sockbuf[3] == 0x03) {
recv(h->socket, &len, 1, 0);
recv(h->socket, sockbuf, len + 2, 0);
} else if (sockbuf[3] == 0x01) {
recv(h->socket, sockbuf, 6, 0);
} else {
if (h->callbacks[IMCOMM_ERROR])
h->callbacks[IMCOMM_ERROR] (handle, IMCOMM_ERROR_PROXY,
PROXY_ERROR_UNKNOWN);
shutdown(h->socket, 0x02);
h->socket = -1;
return IMCOMM_RET_ERROR;
}
/* now we should be set to read the connection */
return IMCOMM_RET_OK;
}
/* PROTO */
int
connect_https(void *handle, char *host, uint16_t port)
{
IMCOMM *h = (IMCOMM *) handle;
struct sockaddr_in sin;
struct hostent *he = NULL;
long addy;
struct in_addr ina = {0};
unsigned char sockbuf[512];
char *sptr;
int received, retcode;
#ifdef DEBUG
printf("Connecting via HTTPS to %s/%d.\n", host, port);
printf("Proxy server: %s/%d\n", h->proxyserver, h->proxyport);
#endif
if ((he = gethostbyname(h->proxyserver)) == NULL) {
addy = inet_addr(h->proxyserver);
ina.s_addr = addy;
}
if ((h->socket = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
if (h->callbacks[IMCOMM_ERROR])
h->callbacks[IMCOMM_ERROR] (handle, IMCOMM_ERROR_PROXY,
PROXY_ERROR_CONNECT);
return IMCOMM_RET_ERROR;
}
sin.sin_family = AF_INET;
sin.sin_port = htons(h->proxyport);
if (he == NULL)
sin.sin_addr = ina;
else
sin.sin_addr = *((struct in_addr *) he->h_addr);
memset(&(sin.sin_zero), 0, 8);
if (connect
(h->socket, (struct sockaddr *) & sin,
sizeof(struct sockaddr)) == -1) {
if (h->callbacks[IMCOMM_ERROR])
h->callbacks[IMCOMM_ERROR] (handle, IMCOMM_ERROR_PROXY,
PROXY_ERROR_CONNECT);
return IMCOMM_RET_ERROR;
}
/*
* This user agent seems pretty well-accepted. Not sure if this is
* any sort of problem...
*/
snprintf((char *) sockbuf, sizeof(sockbuf),
"CONNECT %s:%d HTTP/1.0\r\nUser-agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.0.2) Gecko/20021120 Netscape/7.01\r\n\r\n",
host, port);
if (send(h->socket, sockbuf, strlen((char *) sockbuf), 0) < 0) {
if (h->callbacks[IMCOMM_ERROR])
h->callbacks[IMCOMM_ERROR] (handle, IMCOMM_ERROR_DISCONNECTED,
0);
shutdown(h->socket, 0x02);
h->socket = -1;
return IMCOMM_RET_ERROR;
}
received = recv(h->socket, sockbuf, sizeof(sockbuf), 0);
sockbuf[received] = 0;
sptr = strchr((char *) sockbuf, ' ');
retcode = atoi(sptr + 1);
if (retcode != 200) {
if (h->callbacks[IMCOMM_ERROR])
h->callbacks[IMCOMM_ERROR] (handle, IMCOMM_ERROR_PROXY,
PROXY_ERROR_PROXYCONNECT);
shutdown(h->socket, 0x02);
h->socket = -1;
return IMCOMM_RET_ERROR;
} else {
while (strstr((char *) sockbuf, "\r\n\r\n") == NULL) {
received = recv(h->socket, sockbuf, sizeof(sockbuf), 0);
sockbuf[received] = 0;
}
}
/* now we should be set to read the connection */
return IMCOMM_RET_OK;
}

1433
libs/libimcomm/snac.c Normal file

File diff suppressed because it is too large Load Diff

186
libs/libimcomm/test.c Normal file
View File

@ -0,0 +1,186 @@
/** _
** (_)_ __ __ ___ _ __ _ __
** | | ' \/ _/ _ \ ' \| ' \
** |_|_|_|_\__\___/_|_|_|_|_|_|
**
** Copyright (C) 2003-2005, Claudio Leite
** All rights reserved.
**
** Please see the file 'COPYING' for licensing information.
**/
#include "imcomm.h"
void buddy_online(void *h, const char *who);
void buddy_offline(void *h, const char *who);
void idleinfo(void *, const char *, unsigned long);
void error(void *h, int errornum);
void incoming_im(void *, const char *, const int, const char *);
char *strip_html(char *message);
void
incoming_im(void *handle, const char *who, const int automessage,
const char *message)
{
char *msg;
msg = strip_html((char *) message);
printf("[%s] %s\n", who, msg);
if (strcmp(msg, "quit now") == 0) {
#ifdef MACINTOSH_CLASSIC
mactcp_close(handle);
CloseResolver();
#endif
free(msg);
exit(0);
}
free(msg);
}
int
main(int argc, char *argv[])
{
void *handle;
#ifndef MACINTOSH_CLASSIC
fd_set readfs;
struct timeval tm;
tm.tv_sec = 2;
tm.tv_usec = 150000;
#endif
handle = imcomm_create_handle();
imcomm_register_callback(handle, IMCOMM_IM_SIGNON, buddy_online);
imcomm_register_callback(handle, IMCOMM_IM_SIGNOFF, buddy_offline);
imcomm_register_callback(handle, IMCOMM_IM_IDLEINFO, idleinfo);
imcomm_register_callback(handle, IMCOMM_ERROR, error);
imcomm_register_callback(handle, IMCOMM_IM_INCOMING, incoming_im);
imcomm_im_signon(handle, argv[1], argv[2]);
printf("Starting IMComm test program...\n");
while (1) {
#ifdef MACINTOSH_CLASSIC
imcomm_select(NULL, NULL, NULL, NULL, NULL);
#else
FD_ZERO(&readfs);
#if 0
FD_SET(fileno(stdin), &readfs);
#endif
imcomm_select(0, &readfs, NULL, NULL, &tm);
fflush(stdout);
#endif
}
return 0;
}
void
buddy_online(void *h, const char *who)
{
printf(">>> %s is now online\n", who);
return;
}
void
buddy_offline(void *h, const char *who)
{
printf("<<< %s is now offline\n", who);
return;
}
void
idleinfo(void *h, const char *who, unsigned long time)
{
printf("*** Idle: %s, %ld\n", who, time);
return;
}
void
error(void *h, int errornum)
{
printf("*** ");
switch (errornum) {
case IMCOMM_STATUS_CONNECTED:
printf("Connected.\n");
break;
case IMCOMM_ERROR_INVALID_LOGIN:
printf("Login failed.\n");
break;
case IMCOMM_ERROR_DISCONNECTED:
printf("Disconnected.\n");
break;
case IMCOMM_ERROR_OTHER_SIGNON:
printf
("You've been disconnected because you signed on at a different location.\n");
break;
case IMCOMM_STATUS_AUTHDONE:
printf("Authentication succeeded.\n");
break;
default:
printf("Unknown error type.\n");
break;
}
}
char *
strip_html(char *message)
{
char *temp;
int x, count, inhtml;
temp = malloc(strlen(message) + 1);
for (x = 0, count = 0, inhtml = 0; x < strlen(message); x++) {
if (message[x] == '&') {
if (x + 4 < strlen(message)) {
if (strncmp(message + x, "&amp;", 5) == 0) {
temp[count] = '&';
count++;
x += 4;
continue;
}
}
if (x + 5 < strlen(message)) {
if (strncmp(message + x, "&quot;", 6) == 0) {
temp[count] = '\"';
count++;
x += 5;
continue;
}
}
if (x + 3 < strlen(message)) {
if (strncmp(message + x, "&lt;", 4) == 0) {
temp[count] = '<';
count++;
x += 3;
continue;
}
}
if (x + 3 < strlen(message)) {
if (strncmp(message + x, "&gt;", 4) == 0) {
temp[count] = '>';
count++;
x += 3;
continue;
}
}
}
if (message[x] == '<')
inhtml = 1;
if (inhtml) {
if (message[x] == '>')
inhtml = 0;
continue;
}
if (message[x] == '\n' || message[x] == '\r')
temp[count] = ' ';
else
temp[count] = message[x];
count++;
}
temp = realloc(temp, count + 1);
temp[count] = 0;
return temp;
}

View File

@ -30,5 +30,3 @@ if $(HAVE_OPENSSL) {
}
StaticLibrary libjabber.a : $(sources) ;

View File

@ -2,3 +2,4 @@ SubDir TOP protocols ;
# Include all the components.
SubInclude TOP protocols gtalk ;
SubInclude TOP protocols aim ;

496
protocols/aim/AIM.cpp Normal file
View File

@ -0,0 +1,496 @@
#include <stdio.h>
#include <errno.h>
#include <string>
#include <Entry.h>
#include "AIM.h"
const char* kProtocolName = "aim";
CayaProtocolMessengerInterface *gServerMsgr;
AIMProtocol::AIMProtocol()
{
}
AIMProtocol::~AIMProtocol()
{
Shutdown();
}
status_t
AIMProtocol::Init(CayaProtocolMessengerInterface* msgr)
{
printf("init\n");
gServerMsgr = msgr;
fIMCommHandle = imcomm_create_handle();
fOnline = false;
imcomm_register_callback(fIMCommHandle, IMCOMM_IM_INCOMING, (void (*)())GotMessage);
imcomm_register_callback(fIMCommHandle, IMCOMM_IM_SIGNON, (void (*)())BuddyOnline);
imcomm_register_callback(fIMCommHandle, IMCOMM_IM_SIGNOFF, (void (*)())BuddyOffline);
imcomm_register_callback(fIMCommHandle, IMCOMM_IM_BUDDYAWAY, (void (*)())BuddyAway);
imcomm_register_callback(fIMCommHandle, IMCOMM_IM_BUDDYUNAWAY, (void (*)())BuddyBack);
imcomm_register_callback(fIMCommHandle, IMCOMM_IM_AWAYMSG, (void (*)())BuddyAwayMsg);
imcomm_register_callback(fIMCommHandle, IMCOMM_IM_IDLEINFO, (void (*)())BuddyIdle);
imcomm_register_callback(fIMCommHandle, IMCOMM_IM_PROFILE, (void (*)())BuddyProfile);
// XXX missing IMCOMM_ERROR, IMCOMM_FORMATTED_SN, IMCOMM_HANDLE_DELETED
return B_OK;
}
status_t
AIMProtocol::Shutdown()
{
LogOff();
return B_OK;
}
status_t
AIMProtocol::Process(BMessage* msg)
{
msg->PrintToStream();
switch (msg->what) {
case IM_MESSAGE:
{
int32 im_what = 0;
msg->FindInt32("im_what", &im_what);
switch (im_what) {
case IM_SET_STATUS:
{
int32 status = msg->FindInt32("status");
BString status_msg("");
msg->FindString("message", &status_msg);
char *smsg = strdup(status_msg.String());
switch (status) {
case CAYA_ONLINE:
{
if (!fOnline) {
A_LogOn();
} else {
imcomm_set_unaway(fIMCommHandle);
}
break;
}
case CAYA_AWAY:
imcomm_set_away(fIMCommHandle,
smsg);
break;
case CAYA_EXTENDED_AWAY:
imcomm_set_away(fIMCommHandle,
smsg);
// UnsupportedOperation(); ?
break;
case CAYA_DO_NOT_DISTURB:
imcomm_set_away(fIMCommHandle,
smsg);
// UnsupportedOperation(); ?
break;
case CAYA_OFFLINE:
LogOff();
break;
default:
break;
}
free(smsg);
BMessage msg(IM_MESSAGE);
msg.AddInt32("im_what", IM_STATUS_SET);
msg.AddString("protocol", kProtocolName);
msg.AddInt32("status", status);
gServerMsgr->SendMessage(&msg);
break;
}
case IM_SET_NICKNAME:
{
UnsupportedOperation();
break;
}
case IM_SEND_MESSAGE:
{
const char* buddy = msg->FindString("id");
const char* sms = msg->FindString("message");
imcomm_im_send_message(fIMCommHandle, buddy,
sms, 0);
// XXX send a message to let caya know
// we did it
BMessage msg(IM_MESSAGE);
msg.AddInt32("im_what", IM_MESSAGE_SENT);
msg.AddString("protocol", kProtocolName);
msg.AddString("id", buddy);
msg.AddString("message", sms);
gServerMsgr->SendMessage(&msg);
break;
}
case IM_REGISTER_CONTACTS:
{
const char* buddy = NULL;
char *buddy_copy;
for (int i = 0;
msg->FindString("id", i, &buddy) == B_OK;
i++) {
buddy_copy = strdup(buddy);
imcomm_im_add_buddy(fIMCommHandle, buddy_copy);
free(buddy_copy);
}
break;
}
case IM_UNREGISTER_CONTACTS:
{
const char* buddy = NULL;
for (int i = 0;
msg->FindString("id", i, &buddy) == B_OK;
i++) {
imcomm_im_remove_buddy(fIMCommHandle, buddy);
}
break;
}
case IM_USER_STARTED_TYPING:
{
// UnsupportedOperation();
break;
}
case IM_USER_STOPPED_TYPING:
{
// UnsupportedOperation();
break;
}
case IM_GET_CONTACT_INFO:
UnsupportedOperation();
break;
case IM_SEND_AUTH_ACK:
{
UnsupportedOperation();
break;
}
case IM_SPECIAL_TO_PROTOCOL:
UnsupportedOperation();
break;
default:
msg->PrintToStream();
return B_ERROR;
}
break;
}
default:
// We don't handle this what code
return B_ERROR;
}
return B_OK;
}
void
AIMProtocol::UnsupportedOperation() {
printf("noop\n");
}
const char*
AIMProtocol::GetSignature()
{
return kProtocolName;
}
const char*
AIMProtocol::GetFriendlySignature()
{
return "AOL Instant Messenger";
}
status_t
AIMProtocol::UpdateSettings(BMessage& msg)
{
const char* username = NULL;
const char* password = NULL;
msg.FindString("username", &username);
msg.FindString("password", &password);
// msg.FindString("server", &server);
// msg.FindInt32("port", &server);
if ((username == NULL) || (password == NULL)) {
//LOG( kProtocolName, liHigh, "Invalid settings!");
printf("Invalid settings");
return B_ERROR;
}
if ((fUsername != username) || (fPassword != password)) {
fUsername = username;
fPassword = password;
// XXX kill the handle and sign back in?
}
return B_OK;
}
uint32
AIMProtocol::GetEncoding()
{
return 0xffff; // No conversion, AIMProtocol handles UTF-8 ???
}
status_t
AIMProtocol::A_LogOn()
{
int ret = imcomm_im_signon(fIMCommHandle, fUsername, fPassword);
printf("ret: %d\n", ret);
if (ret == IMCOMM_RET_OK) {
fIMCommThread = spawn_thread(WaitForData, "imcomm receiver",
B_LOW_PRIORITY, this);
resume_thread(fIMCommThread);
fOnline = true;
return B_OK;
}
return B_ERROR;
}
status_t
AIMProtocol::LogOff()
{
fOnline = false;
imcomm_delete_handle_now(fIMCommHandle);
return B_OK;
}
int32
AIMProtocol::WaitForData(void *aimProtocol) {
// XXX No need for aimProtocol since imcomm does its own callback thing
printf("wait\n");
fd_set readset;
struct timeval tm;
while (1) {
FD_ZERO(&readset);
tm.tv_sec = 2;
tm.tv_usec = 500000;
IMCOMM_RET ret = imcomm_select(1, &readset, NULL, NULL, &tm);
if (ret != IMCOMM_RET_OK && errno == EINTR) continue;
}
return 0;
}
void
AIMProtocol::GotMessage(void *imcomm, char *who, int auto, char *recvmsg) {
BMessage msg(IM_MESSAGE);
msg.AddInt32("im_what", IM_MESSAGE_RECEIVED);
msg.AddString("protocol", kProtocolName);
msg.AddString("id", who);
msg.AddString("message", strip_html(recvmsg));
gServerMsgr->SendMessage(&msg);
}
void
AIMProtocol::BuddyOnline(void *imcomm, char *who) {
BMessage msg(IM_MESSAGE);
msg.AddInt32("im_what", IM_STATUS_CHANGED);
msg.AddString("protocol", kProtocolName);
msg.AddString("id", who);
msg.AddInt32("status", CAYA_ONLINE);
gServerMsgr->SendMessage(&msg);
}
void
AIMProtocol::BuddyOffline(void *imcomm, char *who) {
BMessage msg(IM_MESSAGE);
msg.AddInt32("im_what", IM_STATUS_CHANGED);
msg.AddString("protocol", kProtocolName);
msg.AddString("id", who);
msg.AddInt32("status", CAYA_OFFLINE);
gServerMsgr->SendMessage(&msg);
}
void
AIMProtocol::BuddyAway(void *imcomm, char *who) {
imcomm_request_awaymsg(imcomm, who);
}
void
AIMProtocol::BuddyBack(void *imcomm, char *who) {
BMessage msg(IM_MESSAGE);
msg.AddInt32("im_what", IM_STATUS_CHANGED);
msg.AddString("protocol", kProtocolName);
msg.AddString("id", who);
msg.AddInt32("status", CAYA_ONLINE);
gServerMsgr->SendMessage(&msg);
}
void
AIMProtocol::BuddyAwayMsg(void *imcomm, char *who, char *awaymsg) {
BMessage msg(IM_MESSAGE);
msg.AddInt32("im_what", IM_STATUS_CHANGED);
msg.AddString("protocol", kProtocolName);
msg.AddString("id", who);
msg.AddInt32("status", CAYA_EXTENDED_AWAY);
msg.AddString("message", strip_html(awaymsg));
gServerMsgr->SendMessage(&msg);
}
void
AIMProtocol::BuddyIdle(void *imcomm, char *who, long idletime) {
BMessage msg(IM_MESSAGE);
msg.AddInt32("im_what", IM_STATUS_CHANGED);
msg.AddString("protocol", kProtocolName);
msg.AddString("id", who);
msg.AddInt32("status", CAYA_ONLINE);
gServerMsgr->SendMessage(&msg);
}
void
AIMProtocol::BuddyProfile(void *handle, char *who, char *profile) {
// XXX vcard is probably an issue
}
char *
AIMProtocol::strip_html(const char *message)
{
char *temp;
int x, xnot, y, count, inhtml;
size_t len = strlen(message);
temp = (char*)malloc(len + 1);
for (x = 0, count = 0, inhtml = 0; x < len; x++) {
if (message[x] == '<' && inhtml == 0) {
if (x + 10 < len) {
/**
** Convert links into
** [http://url] link text
**/
if (strncasecmp(message + x, "<a href=\"", 9) == 0) {
xnot = x + 9;
for (y = xnot; y < len; y++) {
if (message[y] == '\"') {
/*
* we don't have to
* worry about the
* buffer size,
* because it's
* guaranteed to be
* bigger
*/
memcpy(temp + count, "[", 1);
memcpy(temp + count + 1, message + xnot,
y - xnot);
memcpy(temp + count + 1 + (y - xnot), "] ", 2);
count += y - xnot + 3;
x = y;
break;
}
}
}
}
if (x + 3 < len) {
if (strncasecmp(message + x, "<br>", 4) == 0) {
temp[count] = '\n';
count++;
x += 3;
continue;
}
}
inhtml = 1;
continue;
}
if (inhtml) {
if (message[x] == '>')
inhtml = 0;
continue;
}
if (message[x] == '&') {
if (x + 4 < len) {
if (strncmp(message + x, "&amp;", 5) == 0) {
temp[count] = '&';
count++;
x += 4;
continue;
}
}
if (x + 5 < len) {
if (strncmp(message + x, "&quot;", 6) == 0) {
temp[count] = '\"';
count++;
x += 5;
continue;
}
if (strncmp(message + x, "&nbsp;", 6) == 0) {
temp[count] = ' ';
count++;
x += 5;
continue;
}
}
if (x + 3 < len) {
if (strncmp(message + x, "&lt;", 4) == 0) {
temp[count] = '<';
count++;
x += 3;
continue;
}
}
if (x + 3 < len) {
if (strncmp(message + x, "&gt;", 4) == 0) {
temp[count] = '>';
count++;
x += 3;
continue;
}
}
}
if (message[x] == '\n' || message[x] == '\r')
continue;
else
temp[count] = message[x];
count++;
}
temp = (char*)realloc(temp, count + 1);
temp[count] = 0;
return temp;
}

58
protocols/aim/AIM.h Normal file
View File

@ -0,0 +1,58 @@
/*
* Copyright 2004-2009, IM Kit Team. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef IMKIT_AIM_H
#define IMKIT_AIM_H
#include <List.h>
#include <Messenger.h>
#include <String.h>
#include "CayaProtocol.h"
#include "CayaConstants.h"
#include "imcomm.h"
class AIMProtocol : public CayaProtocol {
public:
AIMProtocol();
virtual ~AIMProtocol();
virtual status_t Init( CayaProtocolMessengerInterface* );
virtual status_t Shutdown();
virtual status_t Process( BMessage * );
virtual const char * GetSignature();
virtual const char * GetFriendlySignature();
virtual status_t UpdateSettings( BMessage & );
virtual uint32 GetEncoding();
static int32 WaitForData(void *);
static void GotMessage(void *, char *, int, char *);
static void BuddyOnline(void *, char *);
static void BuddyOffline(void *, char *);
static void BuddyAway(void *, char *);
static void BuddyBack(void *, char *);
static void BuddyAwayMsg(void *, char *, char *);
static void BuddyIdle(void *, char *, long);
static void BuddyProfile(void *, char *, char *);
BString fUsername;
BString fPassword;
bool fOnline;
thread_id fIMCommThread;
void * fIMCommHandle;
protected:
status_t A_LogOn();
status_t LogOff();
void UnsupportedOperation();
static char * strip_html (const char *message);
};
#endif // IMKIT_AIM_H

23
protocols/aim/Jamfile Normal file
View File

@ -0,0 +1,23 @@
SubDir TOP protocols aim ;
SubDirSysHdrs [ FDirName $(TOP) ] ;
SubDirSysHdrs [ FDirName $(TOP) application ] ;
SubDirSysHdrs [ FDirName $(TOP) libs ] ;
SubDirSysHdrs [ FDirName $(TOP) libs libimcomm ] ;
SEARCH_SOURCE += [ FDirName $(TOP) protocols aim ] ;
local sources =
AIM.cpp
main.cpp
;
AddOn aim :
$(sources)
: libimcomm.a be network $(TARGET_LIBSTDC++)
: aim.rdef
;
Depends aim : libimcomm.a ;
InstallBin $(APPS_DIRECTORY)/caya/protocols : aim ;

34
protocols/aim/aim.rdef Normal file
View File

@ -0,0 +1,34 @@
resource app_version {
major = 0,
middle = 0,
minor = 0,
variety = B_APPV_ALPHA,
internal = 0,
short_info = "AIM Protocol for Caya",
long_info = "©2010 Alexander Botero-Lowry"
};
resource vector_icon {
$"6E636966080501040046020106023E40000000000000003D4000494000470000"
$"7EFFFFFFFFE5E1DA02000602000000BBC0004000000000009220244AF0000000"
$"33CCFC3366FF02000602000000BA000040000000000092202448800000336699"
$"FF6699CC02000602000000B9000040000000000092202448E00000CC0000FFFF"
$"000002000602000000BA000040000000000092202448800000FF9900FFFBFF00"
$"02000602000000BA000040000000000092202448800000006600FF00CC000A02"
$"06C22622C7562239222E342E2B2E3D4146364441483C50404C3C504A444A4E55"
$"44CBB634CBB83E5E2A0206C22622C7562239222E342E2B2E3D4146364441483C"
$"50404C3C504C464A505744CBB634CBB83E5E2A02024C265928532A583B59335D"
$"350610CAFFFEAF375335543B3B5A3B5A395D325D355D2C5D274F275627483241"
$"2C413541BDA7C2A83942BDA7C2A8394A3F463F463C40324036402A40234F2346"
$"2358325E2A5E395EBF5C5A3F5CBF5C5A3F544053080234313C310404FE372C37"
$"393739373A393B383B3A3B3B393B3A3B390406FE0B4536403640363F363E383E"
$"373E383E393E393E3A403B3F3B413B453A0405FE03453C453445344533433244"
$"324332403240323F323E343E333E3408024D2C4D3C0803553C4F3655300D0A00"
$"01001001178400040A020101000A010102000A0101032021210A010204053021"
$"2101178200040A0102070630212101178200040A010108301D2101178200040A"
$"0102090830212101178200040A030103000A040204051001178200040A050207"
$"061001178200040A060108301C2001178200040A07020908100117820004"
};

8
protocols/aim/main.cpp Normal file
View File

@ -0,0 +1,8 @@
#include "AIM.h"
extern "C" __declspec(dllexport) CayaProtocol *main_protocol ();
CayaProtocol *main_protocol ()
{
return (CayaProtocol *)(new AIMProtocol());
}