Adding AIM protocol from Alexander Botero-Lowry, but it needs polishing.
This commit is contained in:
parent
7d4a7d1c24
commit
8d6d06dbfe
|
@ -30,7 +30,7 @@ ContactLinker::ContactLinker(BString id, BMessenger msgn)
|
||||||
RegisterObserver(fRosterItem);
|
RegisterObserver(fRosterItem);
|
||||||
|
|
||||||
// By default we use protocol icon as avatar icon
|
// By default we use protocol icon as avatar icon
|
||||||
fAvatarBitmap = ProtocolManager::Get()->GetProtocolIcon("gtalk");
|
fAvatarBitmap = ProtocolManager::Get()->GetProtocolIcon("aim");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
Server::Server(MainWindow* mainWindow)
|
Server::Server(MainWindow* mainWindow)
|
||||||
: BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE)
|
: BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE)
|
||||||
{
|
{
|
||||||
CayaProtocol* pp = ProtocolManager::Get()->GetProtocol("gtalk");
|
CayaProtocol* pp = ProtocolManager::Get()->GetProtocol("aim");
|
||||||
if (!pp)
|
if (!pp)
|
||||||
debugger("something wrong");
|
debugger("something wrong");
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
SubDir TOP libs ;
|
SubDir TOP libs ;
|
||||||
|
|
||||||
# Include all the components.
|
# Include all the components.
|
||||||
SubInclude TOP libs libjabber ;
|
|
||||||
SubInclude TOP libs librunview ;
|
SubInclude TOP libs librunview ;
|
||||||
SubInclude TOP libs libinterface ;
|
SubInclude TOP libs libjabber ;
|
||||||
SubInclude TOP libs libsupport ;
|
SubInclude TOP libs libsupport ;
|
||||||
|
SubInclude TOP libs libinterface ;
|
||||||
|
SubInclude TOP libs libimcomm ;
|
||||||
|
|
|
@ -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.
|
|
@ -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
|
||||||
|
;
|
|
@ -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.
|
|
@ -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 */
|
|
@ -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))
|
|
@ -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;
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -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
|
|
@ -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
|
||||||
|
}
|
|
@ -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));
|
||||||
|
}
|
|
@ -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 */
|
|
@ -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;
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
rm -f protos.h
|
||||||
|
for i in *.c; do
|
||||||
|
sed -n -f ./makeprotos-sed $i >> protos.h
|
||||||
|
done
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -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, "&", 5) == 0) {
|
||||||
|
temp[count] = '&';
|
||||||
|
count++;
|
||||||
|
x += 4;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (x + 5 < strlen(message)) {
|
||||||
|
if (strncmp(message + x, """, 6) == 0) {
|
||||||
|
temp[count] = '\"';
|
||||||
|
count++;
|
||||||
|
x += 5;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (x + 3 < strlen(message)) {
|
||||||
|
if (strncmp(message + x, "<", 4) == 0) {
|
||||||
|
temp[count] = '<';
|
||||||
|
count++;
|
||||||
|
x += 3;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (x + 3 < strlen(message)) {
|
||||||
|
if (strncmp(message + x, ">", 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;
|
||||||
|
}
|
|
@ -30,5 +30,3 @@ if $(HAVE_OPENSSL) {
|
||||||
}
|
}
|
||||||
|
|
||||||
StaticLibrary libjabber.a : $(sources) ;
|
StaticLibrary libjabber.a : $(sources) ;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,3 +2,4 @@ SubDir TOP protocols ;
|
||||||
|
|
||||||
# Include all the components.
|
# Include all the components.
|
||||||
SubInclude TOP protocols gtalk ;
|
SubInclude TOP protocols gtalk ;
|
||||||
|
SubInclude TOP protocols aim ;
|
||||||
|
|
|
@ -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, "&", 5) == 0) {
|
||||||
|
temp[count] = '&';
|
||||||
|
count++;
|
||||||
|
x += 4;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (x + 5 < len) {
|
||||||
|
if (strncmp(message + x, """, 6) == 0) {
|
||||||
|
temp[count] = '\"';
|
||||||
|
count++;
|
||||||
|
x += 5;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (strncmp(message + x, " ", 6) == 0) {
|
||||||
|
temp[count] = ' ';
|
||||||
|
count++;
|
||||||
|
x += 5;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (x + 3 < len) {
|
||||||
|
if (strncmp(message + x, "<", 4) == 0) {
|
||||||
|
temp[count] = '<';
|
||||||
|
count++;
|
||||||
|
x += 3;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (x + 3 < len) {
|
||||||
|
if (strncmp(message + x, ">", 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;
|
||||||
|
}
|
|
@ -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
|
|
@ -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 ;
|
|
@ -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"
|
||||||
|
};
|
|
@ -0,0 +1,8 @@
|
||||||
|
#include "AIM.h"
|
||||||
|
|
||||||
|
extern "C" __declspec(dllexport) CayaProtocol *main_protocol ();
|
||||||
|
|
||||||
|
CayaProtocol *main_protocol ()
|
||||||
|
{
|
||||||
|
return (CayaProtocol *)(new AIMProtocol());
|
||||||
|
}
|
Ŝarĝante…
Reference in New Issue