Chat-O-Matic/libs/libmsn/msntest.cpp

1376 lines
48 KiB
C++
Raw Normal View History

/*
* msntest.cpp
* libmsn
*
* Created by Meredydd Luff.
* Refactored by Tiago Salem Herrmann
* Copyright (c) 2004 Meredydd Luff. All rights reserved.
* Copyright (c) 2007 Tiago Salem Herrmann. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/poll.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/ssl.h>
#include "msn.h"
#include <string>
#include <iostream>
class Callbacks : public MSN::Callbacks
{
virtual void registerSocket(void *s, int read, int write, bool isSSL);
virtual void unregisterSocket(void *s);
virtual void closeSocket(void *s);
virtual void showError(MSN::Connection * conn, std::string msg);
virtual void buddyChangedStatus(MSN::NotificationServerConnection * conn, MSN::Passport buddy, std::string friendlyname, MSN::BuddyStatus state, unsigned int clientID, std::string msnobject);
virtual void buddyOffline(MSN::NotificationServerConnection * conn, MSN::Passport buddy);
virtual void log(int writing, const char* buf);
virtual void buddyChangedPersonalInfo(MSN::NotificationServerConnection * conn, MSN::Passport fromPassport, MSN::personalInfo);
virtual void gotFriendlyName(MSN::NotificationServerConnection * conn, std::string friendlyname);
virtual void gotBuddyListInfo(MSN::NotificationServerConnection * conn, MSN::ListSyncInfo * data);
virtual void gotLatestListSerial(MSN::NotificationServerConnection * conn, std::string lastChange);
virtual void gotGTC(MSN::NotificationServerConnection * conn, char c);
virtual void gotBLP(MSN::NotificationServerConnection * conn, char c);
virtual void addedListEntry(MSN::NotificationServerConnection * conn, MSN::ContactList list, MSN::Passport buddy, std::string friendlyname);
virtual void removedListEntry(MSN::NotificationServerConnection * conn, MSN::ContactList list, MSN::Passport buddy);
virtual void addedGroup(MSN::NotificationServerConnection * conn, bool added, std::string groupName, std::string groupID);
virtual void removedGroup(MSN::NotificationServerConnection * conn, bool removed, std::string groupID);
virtual void renamedGroup(MSN::NotificationServerConnection * conn, bool renamed, std::string newGroupName, std::string groupID);
virtual void addedContactToGroup(MSN::NotificationServerConnection * conn, bool added, std::string groupId, std::string contactId);
virtual void removedContactFromGroup(MSN::NotificationServerConnection * conn, bool removed, std::string groupId, std::string contactId);
virtual void addedContactToAddressBook(MSN::NotificationServerConnection * conn, bool added, std::string passport, std::string displayName, std::string guid);
virtual void removedContactFromAddressBook(MSN::NotificationServerConnection * conn, bool removed, std::string contactId, std::string passport);
virtual void enabledContactOnAddressBook(MSN::NotificationServerConnection * conn, bool enabled, std::string contactId, std::string passport);
virtual void disabledContactOnAddressBook(MSN::NotificationServerConnection * conn, bool disabled, std::string contactId);
virtual void gotSwitchboard(MSN::SwitchboardServerConnection * conn, const void * tag);
virtual void buddyJoinedConversation(MSN::SwitchboardServerConnection * conn, MSN::Passport buddy, std::string friendlyname, int is_initial);
virtual void buddyLeftConversation(MSN::SwitchboardServerConnection * conn, MSN::Passport buddy);
virtual void gotInstantMessage(MSN::SwitchboardServerConnection * conn, MSN::Passport buddy, std::string friendlyname, MSN::Message * msg);
virtual void gotMessageSentACK(MSN::SwitchboardServerConnection * conn, int trID);
virtual void gotEmoticonNotification(MSN::SwitchboardServerConnection * conn, MSN::Passport buddy, std::string alias, std::string msnobject);
virtual void failedSendingMessage(MSN::Connection * conn);
virtual void buddyTyping(MSN::SwitchboardServerConnection * conn, MSN::Passport buddy, std::string friendlyname);
virtual void gotNudge(MSN::SwitchboardServerConnection * conn, MSN::Passport from);
virtual void gotVoiceClipNotification(MSN::SwitchboardServerConnection * conn, MSN::Passport from, std::string msnobject);
virtual void gotWinkNotification(MSN::SwitchboardServerConnection * conn, MSN::Passport from, std::string msnobject);
virtual void gotInk(MSN::SwitchboardServerConnection * conn, MSN::Passport from, std::string image);
virtual void gotVoiceClipFile(MSN::SwitchboardServerConnection * conn, unsigned int sessionID, std::string file);
virtual void gotEmoticonFile(MSN::SwitchboardServerConnection * conn, unsigned int sessionID, std::string alias, std::string file);
virtual void gotWinkFile(MSN::SwitchboardServerConnection * conn, unsigned int sessionID, std::string file);
virtual void gotActionMessage(MSN::SwitchboardServerConnection * conn, MSN::Passport username, std::string message);
virtual void gotInitialEmailNotification(MSN::NotificationServerConnection * conn, int msgs_inbox, int unread_inbox, int msgs_folders, int unread_folders);
virtual void gotNewEmailNotification(MSN::NotificationServerConnection * conn, std::string from, std::string subject);
virtual void fileTransferProgress(MSN::SwitchboardServerConnection * conn, unsigned int sessionID, long long unsigned transferred, long long unsigned total);
virtual void fileTransferFailed(MSN::SwitchboardServerConnection * conn, unsigned int sessionID, MSN::fileTransferError error);
virtual void fileTransferSucceeded(MSN::SwitchboardServerConnection * conn, unsigned int sessionID);
virtual void fileTransferInviteResponse(MSN::SwitchboardServerConnection * conn, unsigned int sessionID, bool response);
virtual void gotNewConnection(MSN::Connection * conn);
virtual void gotOIMList(MSN::NotificationServerConnection * conn, std::vector<MSN::eachOIM> OIMs);
virtual void gotOIM(MSN::NotificationServerConnection * conn, bool success, std::string id, std::string message);
virtual void gotOIMSendConfirmation(MSN::NotificationServerConnection * conn, bool success, int id);
virtual void gotOIMDeleteConfirmation(MSN::NotificationServerConnection * conn, bool success, std::string id);
virtual void gotContactDisplayPicture(MSN::SwitchboardServerConnection * conn, MSN::Passport passport, std::string filename );
virtual void closingConnection(MSN::Connection * conn);
virtual void changedStatus(MSN::NotificationServerConnection * conn, MSN::BuddyStatus state);
virtual void * connectToServer(std::string server, int port, bool *connected, bool isSSL);
virtual void connectionReady(MSN::Connection * conn);
virtual void askFileTransfer(MSN::SwitchboardServerConnection *conn, MSN::fileTransferInvite ft);
virtual int listenOnPort(int port);
virtual std::string getOurIP();
virtual int getSocketFileDescriptor (void *sock);
virtual size_t getDataFromSocket (void *sock, char *data, size_t size);
virtual size_t writeDataToSocket (void *sock, char *data, size_t size);
virtual std::string getSecureHTTPProxy();
virtual void gotInboxUrl (MSN::NotificationServerConnection *conn, MSN::hotmailInfo info);
};
struct pollfd mySockets[21];
struct ssl {
bool isSSL;
bool isConnected;
SSL *ssl;
SSL_CTX *ctx;
} mySocketsSsl[21];
void handle_command(MSN::NotificationServerConnection &);
int countsocks(void);
std::string myFriendlyName;
std::string myUsername;
//std::string lastObject;
// should be random
unsigned int sessionID = 123456;
int main()
{
for (int i = 1; i < 20; i++)
{
mySockets[i].fd = -1;
mySockets[i].events = POLLIN;
mySockets[i].revents = 0;
mySocketsSsl[i].isSSL = false;
mySocketsSsl[i].isConnected = false;
mySocketsSsl[i].ctx = NULL;
mySocketsSsl[i].ssl = NULL;
}
mySockets[0].fd = 0;
mySockets[0].events = POLLIN;
mySockets[0].revents = 0;
Callbacks cb;
MSN::Passport uname;
char *pass = NULL;
while (1)
{
fprintf(stderr, "Enter your login name: ");
fflush(stdout);
try
{
std::cin >> uname;
myUsername = uname;
break;
}
catch (MSN::InvalidPassport & e)
{
std::cout << e.what() << std::endl;
}
}
pass = getpass("Enter your password: ");
fprintf(stderr, "Connecting to the MSN Messenger service...\n");
MSN::NotificationServerConnection mainConnection(uname, pass, cb);
mainConnection.connect("messenger.hotmail.com", 1863);
fprintf(stderr, "> ");
fflush(stderr);
while (1)
{
poll(mySockets, 20, -1);
for (int i = 1; i < 20; i++)
{
if (mySockets[i].fd == -1)
break;
if (mySockets[i].revents & POLLHUP) {
mySockets[i].revents = 0;
continue;
}
if (mySockets[i].revents & (POLLIN | POLLOUT | POLLPRI))
{
MSN::Connection *c;
// Retrieve the connection associated with the
// socket's file handle on which the event has
// occurred.
c = mainConnection.connectionWithSocket((void*)mySockets[i].fd);
// if this is a libmsn socket
if (c != NULL)
{
// If we aren't connected yet, a socket event means that
// our connection attempt has completed.
if(mySocketsSsl[i].isSSL && !mySocketsSsl[i].isConnected)
{
BIO *bio_socket_new;
SSL_METHOD *meth=NULL;
meth=const_cast<SSL_METHOD *>(SSLv23_client_method());
SSLeay_add_ssl_algorithms();
mySocketsSsl[i].ctx = SSL_CTX_new(meth);
mySocketsSsl[i].ssl = SSL_new(mySocketsSsl[i].ctx);
bio_socket_new = BIO_new_socket(mySockets[i].fd, BIO_CLOSE);
if(!mySocketsSsl[i].ssl)
break;
BIO_set_nbio(bio_socket_new, 0);
SSL_set_bio(mySocketsSsl[i].ssl, bio_socket_new, bio_socket_new);
SSL_set_mode(mySocketsSsl[i].ssl, SSL_MODE_AUTO_RETRY);
// TODO - fix-me - not async and buggy
int ret = SSL_connect(mySocketsSsl[i].ssl);
mySocketsSsl[i].isConnected = true;
}
if (c->isConnected() == false)
c->socketConnectionCompleted();
// If this event is due to new data becoming available
if (mySockets[i].revents & POLLIN)
{
if(mySocketsSsl[i].isSSL && mySocketsSsl[i].isConnected)
{
if(SSL_want_read(mySocketsSsl[i].ssl))
{
mySockets[i].revents = 0;
continue;
}
}
c->dataArrivedOnSocket();
}
// If this event is due to the socket becoming writable
if (mySockets[i].revents & POLLOUT)
{
c->socketIsWritable();
}
}
}
if (mySockets[i].revents & (POLLERR | POLLNVAL))
{
printf("Dud socket (%d)! Code %x (ERR=%x, INVAL=%x)\n", mySockets[i].fd, mySockets[i].revents, POLLERR, POLLNVAL);
MSN::Connection *c;
// Retrieve the connection associated with the
// socket's file handle on which the event has
// occurred.
c = mainConnection.connectionWithSocket((void*)mySockets[i].fd);
// if this is a libmsn socket
if (c != NULL)
{
// Delete the connection. This will cause the resources
// that are being used to be freed.
delete c;
}
mySockets[i].fd = -1;
mySockets[i].revents = 0;
continue;
}
}
if (mySockets[0].revents & POLLIN)
{
handle_command(mainConnection);
mySockets[0].revents = 0;
}
}
}
void handle_command(MSN::NotificationServerConnection & mainConnection)
{
char command[40];
if (scanf(" %s", command) == EOF)
{
printf("\n");
exit(0);
}
if (!strcmp(command, "quit"))
{
exit(0);
} else if (!strcmp(command, "sendoim")) {
char rcpt[80];
char msg[1024];
scanf(" %s", rcpt);
fgets(msg, 1024, stdin);
msg[strlen(msg)-1] = '\0';
const std::string rcpt_ = rcpt;
const std::string msg_ = msg;
MSN::Soap::OIM oim;
oim.myFname = myFriendlyName;
oim.toUsername = rcpt;
oim.message = msg;
oim.myUsername = myUsername;
oim.id = 1;
mainConnection.send_oim(oim);
} else if (!strcmp(command, "addtogroup")) {
char gid[80];
char uid[80];
scanf(" %s", gid);
fgets(uid, 80, stdin);
uid[strlen(uid)-1] = '\0';
const std::string uid_ = uid;
const std::string gid_ = gid;
mainConnection.addToGroup(gid,uid);
} else if (!strcmp(command, "delfromgroup")) {
char gid[80];
char uid[80];
scanf(" %s", gid);
fgets(uid, 80, stdin);
uid[strlen(uid)-1] = '\0';
const std::string uid_ = uid;
const std::string gid_ = gid;
mainConnection.removeFromGroup(gid,uid);
} else if (!strcmp(command, "renamegroup")) {
char gid[80];
char name[80];
scanf(" %s", gid);
fgets(name, 80, stdin);
name[strlen(name)-1] = '\0';
const std::string name_ = name;
const std::string gid_ = gid;
mainConnection.renameGroup(gid,name);
} else if (!strcmp(command, "getoim")) {
char id[80];
scanf(" %s", id);
const std::string _id = id;
mainConnection.get_oim(id,false);
} else if (!strcmp(command, "addgroup")) {
char gname[80];
scanf(" %s", gname);
const std::string _gname = gname;
mainConnection.addGroup(_gname);
} else if (!strcmp(command, "delgroup")) {
char gname[80];
scanf(" %s", gname);
const std::string _gname = gname;
mainConnection.removeGroup(_gname);
} else if (!strcmp(command, "deloim")) {
char id[80];
scanf(" %s", id);
const std::string _id = id;
mainConnection.delete_oim(id);
} else if (!strcmp(command, "msg")) {
char rcpt[80];
char msg[1024];
scanf(" %s", rcpt);
fgets(msg, 1024, stdin);
msg[strlen(msg)-1] = '\0';
const std::string rcpt_ = rcpt;
const std::string msg_ = msg;
const std::pair<std::string, std::string> *ctx = new std::pair<std::string, std::string>(rcpt_, msg_);
mainConnection.requestSwitchboardConnection(ctx);
} else if (!strcmp(command, "status")) {
char state[10];
scanf(" %s", state);
mainConnection.change_DisplayPicture("/tmp/global-photo.png");
uint clientid=0;
clientid += MSN::MSNC7;
clientid += MSN::MSNC6;
clientid += MSN::MSNC5;
clientid += MSN::MSNC4;
clientid += MSN::MSNC3;
clientid += MSN::MSNC2;
clientid += MSN::MSNC1;
clientid += MSN::SupportWinks;
clientid += MSN::VoiceClips;
clientid += MSN::InkGifSupport;
clientid += MSN::SIPInvitations;
clientid += MSN::SupportMultiPacketMessaging;
mainConnection.setState(MSN::buddyStatusFromString(state), clientid);
} else if (!strcmp(command, "friendlyname")) {
char fn[256];
fgets(fn, 256, stdin);
fn[strlen(fn)-1] = '\0';
mainConnection.setFriendlyName(fn);
} else if (!strcmp(command, "addtolist")) {
MSN::ContactList list;
char user[128];
scanf(" %d %s", (int*)&list, user);
mainConnection.addToList(list, user);
} else if (!strcmp(command, "add")) {
char user[128];
char nick[128];
scanf(" %s %s", user, nick);
mainConnection.addToAddressBook(user, nick);
} else if (!strcmp(command, "block")) {
char user[128];
scanf(" %s", user);
mainConnection.blockContact(user);
} else if (!strcmp(command, "unblock")) {
char user[128];
scanf(" %s", user);
mainConnection.unblockContact(user);
} else if (!strcmp(command, "delfromlist")) {
MSN::ContactList list;
char user[128];
scanf(" %d %s", (int*)&list, user);
mainConnection.removeFromList(list, user);
} else if (!strcmp(command, "del")) {
char contactid[128];
char passport[128];
scanf(" %s %s", contactid, passport);
mainConnection.delFromAddressBook(contactid, passport);
} else if (!strcmp(command, "enable")) {
char contactid[128];
char passport[128];
scanf(" %s %s", contactid, passport);
mainConnection.enableContactOnAddressBook(contactid,passport);
} else if (!strcmp(command, "disable")) {
char contactid[128];
char passport[128];
scanf(" %s %s", contactid, passport);
mainConnection.disableContactOnAddressBook(contactid,passport);
} else if (!strcmp(command, "reconnect")) {
if (mainConnection.connectionState() != MSN::NotificationServerConnection::NS_DISCONNECTED)
mainConnection.disconnect();
mainConnection.connect("messenger.hotmail.com", 1863);
} else if (!strcmp(command, "disconnect")) {
mainConnection.disconnectNS();
} else if (!strcmp(command, "inboxurl")) {
mainConnection.getInboxUrl();
} else {
fprintf(stderr, "\nBad command \"%s\"", command);
}
fprintf(stderr, "\n> ");
fflush(stderr);
}
int countsocks(void)
{
int retval = 0;
for (int a = 0; a < 20; a++)
{
if (mySockets[a].fd == -1)
break;
retval++;
}
return retval;
}
void Callbacks::registerSocket(void *s, int reading, int writing, bool isSSL)
{
for (int a = 1; a < 20; a++)
{
if (mySockets[a].fd == -1 || mySockets[a].fd == getSocketFileDescriptor(s))
{
if(mySockets[a].fd == -1)
mySockets[a].events = 0;
if (reading)
mySockets[a].events |= POLLIN;
if (writing)
mySockets[a].events |= POLLOUT;
mySockets[a].fd = getSocketFileDescriptor(s);
if(isSSL)
mySocketsSsl[a].isSSL = true;
return;
}
}
}
int
Callbacks::getSocketFileDescriptor (void *sock)
{
long a = (long)sock;
return (int)a;
}
void Callbacks::closeSocket(void *s)
{
for (int a = 1; a < 20; a++)
{
if (mySockets[a].fd == getSocketFileDescriptor(s))
{
close(getSocketFileDescriptor(s));
if(mySocketsSsl[a].isSSL)
{
if(mySocketsSsl[a].ssl)
{
if(mySocketsSsl[a].ssl) SSL_set_shutdown(mySocketsSsl[a].ssl, SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
if(mySocketsSsl[a].ssl) SSL_free(mySocketsSsl[a].ssl);
if(mySocketsSsl[a].ctx) SSL_CTX_free(mySocketsSsl[a].ctx);
mySocketsSsl[a].ssl=NULL;
mySocketsSsl[a].ctx=NULL;
}
}
for (int b = a; b < 19; b++)
{
mySockets[b].fd = mySockets[b + 1].fd;
mySockets[b].revents = mySockets[b + 1].revents;
mySockets[b].events = mySockets[b + 1].events;
mySocketsSsl[b].isSSL = mySocketsSsl[b + 1].isSSL;
mySocketsSsl[b].isConnected = mySocketsSsl[b + 1].isConnected;
mySocketsSsl[b].ssl = mySocketsSsl[b + 1].ssl;
mySocketsSsl[b].ctx = mySocketsSsl[b + 1].ctx;
}
mySockets[19].fd = -1;
mySocketsSsl[19].isConnected = false;
mySocketsSsl[19].isSSL = false;
mySocketsSsl[19].ssl = NULL;
mySocketsSsl[19].ctx = NULL;
}
}
}
void Callbacks::unregisterSocket(void *s)
{
for (int a = 1; a < 20; a++)
{
if (mySockets[a].fd == getSocketFileDescriptor(s))
{
mySockets[a].events = 0;
}
}
}
void Callbacks::gotFriendlyName(MSN::NotificationServerConnection * conn, std::string friendlyname)
{
myFriendlyName = friendlyname.c_str();
printf("Your friendlyname is now: %s\n", friendlyname.c_str());
}
void Callbacks::gotBuddyListInfo(MSN::NotificationServerConnection * conn, MSN::ListSyncInfo * info)
{
// IMPORTANT
// Here you need to fill a vector with all your contacts
// both received by the server and previous ones.
// Next pass this vector to the function completeConnection()
// if you dont call completeConnection(), the service will
// not work.
std::map<std::string, MSN::Buddy *>::iterator i = info->contactList.begin();
std::map<std::string, int> allContacts;
for (; i != info->contactList.end(); i++)
{
MSN::Buddy *contact = (*i).second;
if(contact->lists & MSN::LST_AB ) // only if it is the address book
{
allContacts[contact->userName.c_str()]=0;
allContacts[contact->userName.c_str()] |= MSN::LST_AB;
printf("-AB %s (%s)\n Id: %s\n", contact->friendlyName.c_str(), contact->userName.c_str(), contact->properties["contactId"].c_str());
if(contact->properties["isMessengerUser"]=="false")
printf(" Not Messenger User\n");
std::list<MSN::Buddy::PhoneNumber>::iterator pns = contact->phoneNumbers.begin();
std::list<MSN::Group *>::iterator g = contact->groups.begin();
for (; g != contact->groups.end(); g++)
{
printf(" G: %s\n", (*g)->name.c_str());
}
for (; pns != contact->phoneNumbers.end(); pns++)
{
printf(" %s: %s (%d)\n", (*pns).title.c_str(), (*pns).number.c_str(), (*pns).enabled);
}
}
if(contact->lists & MSN::LST_AL )
{
allContacts[contact->userName.c_str()] |= MSN::LST_AL;
printf("-AL %s \n", contact->userName.c_str());
}
if(contact->lists & MSN::LST_BL )
{
allContacts[contact->userName.c_str()] |= MSN::LST_BL;
printf("-BL %s \n", contact->userName.c_str());
}
if(contact->lists & MSN::LST_RL )
{
printf("-RL %s \n", contact->userName.c_str());
}
if(contact->lists & MSN::LST_PL )
{
printf("-PL %s \n", contact->userName.c_str());
}
}
printf("Available Groups:\n");
std::map<std::string, MSN::Group>::iterator g = info->groups.begin();
for (; g != info->groups.end(); g++)
{
printf(" %s: %s\n", (*g).second.groupID.c_str(), (*g).second.name.c_str());
}
std::map<std::string, int>::iterator b = allContacts.begin();
// this will send the ADL command to the server
// It is necessary. Dont forget to add *all* your contacts to allContacts,
// (both Forward, allow and block lists) or you probably will
// loose someone.
// A contact cannot be present both on allow and block lists or the
// server will return an error, so you need to let your application
// choose the better list to put it in.
conn->completeConnection(allContacts,info);
}
void Callbacks::gotLatestListSerial(MSN::NotificationServerConnection * conn, std::string lastChange)
{
// The application needs to track this number to not ask for the whole contact
// list every login
printf("The latest change number is: %s\n", lastChange.c_str());
}
void Callbacks::gotGTC(MSN::NotificationServerConnection * conn, char c)
{
printf("Your GTC value is now %c\n", c);
}
void Callbacks::gotOIMDeleteConfirmation(MSN::NotificationServerConnection * conn, bool success, std::string id)
{
if(success)
std::cout << "OIM "<< id << " removed sucessfully." << std::endl;
else
std::cout << "OIM "<< id << " not removed sucessfully." << std::endl;
}
void Callbacks::gotOIMSendConfirmation(MSN::NotificationServerConnection * conn, bool success, int id)
{
if(success)
std::cout << "OIM " << id << " sent sucessfully." << std::endl;
else
std::cout << "OIM " << id << " not sent sucessfully." << std::endl;
}
void Callbacks::gotOIM(MSN::NotificationServerConnection * conn, bool success, std::string id, std::string message)
{
if(success)
std::cout << "ID: " << id << std::endl << "\t" << message << std::endl;
else
std::cout << "Error retreiving OIM " << id << std::endl;
}
void Callbacks::gotOIMList(MSN::NotificationServerConnection * conn, std::vector<MSN::eachOIM> OIMs)
{
if(OIMs.size()==0)
{
printf("No Offline messages\n");
return;
}
std::vector<MSN::eachOIM>::iterator i = OIMs.begin();
for(; i<OIMs.end();i++)
{
printf("Offline message from: %s\n\t - Friendly Name: %s\n\t - Id: %s\n",(*i).from.c_str(), (*i).fromFN.c_str(), (*i).id.c_str());
}
}
void Callbacks::connectionReady(MSN::Connection * conn)
{
printf("The connection is ready. You can change your status now!\n");
}
void Callbacks::gotBLP(MSN::NotificationServerConnection * conn, char c)
{
printf("Your BLP value is now %cL\n", c);
}
void Callbacks::addedListEntry(MSN::NotificationServerConnection * conn, MSN::ContactList list, MSN::Passport username, std::string friendlyname)
{
if(list == MSN::LST_RL)
// after adding the user you need to delete it from the pending list.
// it will be added automatically by the msn service
printf("%s is now on your list %d. FriendlyName: %s\n", username.c_str(), list, friendlyname.c_str());
else
// on normal lists you'll never receive the contacts displayname
// it is not needed anyway
printf("%s is now on your list %d\n", username.c_str(), list);
}
void Callbacks::removedListEntry(MSN::NotificationServerConnection * conn, MSN::ContactList list, MSN::Passport username)
{
// list is a number which matches with MSN::ContactList enum on util.h
printf("%s has been removed from list %d\n", username.c_str(), list);
}
void Callbacks::addedGroup(MSN::NotificationServerConnection * conn, bool added, std::string groupName, std::string groupID)
{
if(added)
printf("A group named %s (%s) was added\n", groupName.c_str(), groupID.c_str());
else
printf("Group (%s) was NOT added\n", groupName.c_str());
}
void Callbacks::removedGroup(MSN::NotificationServerConnection * conn, bool removed, std::string groupID)
{
if(removed)
printf("A group with ID %s was removed\n", groupID.c_str());
else
printf("Group (%s) was NOT removed\n", groupID.c_str());
}
void Callbacks::renamedGroup(MSN::NotificationServerConnection * conn, bool renamed, std::string newGroupName, std::string groupID)
{
if(renamed)
printf("A group with ID %s was renamed to %s\n", groupID.c_str(), newGroupName.c_str());
else
printf("A group with ID %s was NOT renamed to %s\n", groupID.c_str(), newGroupName.c_str());
}
void Callbacks::showError(MSN::Connection * conn, std::string msg)
{
printf("MSN: Error: %s\n", msg.c_str());
}
void Callbacks::buddyChangedStatus(MSN::NotificationServerConnection * conn, MSN::Passport buddy, std::string friendlyname, MSN::BuddyStatus status, unsigned int clientID, std::string msnobject)
{
printf("%s (%s) is now %s\n", friendlyname.c_str(), buddy.c_str(), MSN::buddyStatusToString(status).c_str());
if (clientID & MSN::SupportWebcam)
printf("\t Supports Webcam\n");
if (clientID & MSN::VoiceClips)
printf("\t Supports VoiceClips\n");
if (clientID & MSN::SupportDirectIM)
printf("\t Supports DirectIM\n");
if (clientID & MSN::SharingFolders)
printf("\t Supports SharingFolders\n");
if (clientID & MSN::MSNC1)
printf("\t Supports MSNC1\n");
if (clientID & MSN::MSNC2)
printf("\t Supports MSNC2\n");
if (clientID & MSN::MSNC3)
printf("\t Supports MSNC3\n");
if (clientID & MSN::MSNC4)
printf("\t Supports MSNC4\n");
if (clientID & MSN::MSNC5)
printf("\t Supports MSNC5\n");
if (clientID & MSN::MSNC6)
printf("\t Supports MSNC6\n");
if (clientID & MSN::MSNC7)
printf("\t Supports MSNC7\n");
if (clientID & MSN::InkGifSupport)
printf("\t Supports Ink Gif\n");
if (clientID & MSN::InkIsfSupport)
printf("\t Supports Ink Isf\n");
// lastObject = msnobject;
}
void Callbacks::buddyOffline(MSN::NotificationServerConnection * conn, MSN::Passport buddy)
{
printf("%s is now offline\n", buddy.c_str());
}
void Callbacks::gotSwitchboard(MSN::SwitchboardServerConnection * conn, const void * tag)
{
printf("Got switchboard connection\n");
if (tag)
{
const std::pair<std::string, std::string> *ctx = static_cast<const std::pair<std::string, std::string> *>(tag);
conn->inviteUser(ctx->first);
}
}
void Callbacks::buddyJoinedConversation(MSN::SwitchboardServerConnection * conn, MSN::Passport username, std::string friendlyname, int is_initial)
{
printf("%s (%s) is now in the session\n", friendlyname.c_str(), username.c_str());
if (conn->auth.tag)
{
const std::pair<std::string, std::string> *ctx = static_cast<const std::pair<std::string, std::string> *>(conn->auth.tag);
// Example of sending a custom emoticon
// conn->sendEmoticon("(EMOTICON)", filename);
int trid = conn->sendMessage(ctx->second);
std::cout << "Message " << trid << " queued" << std::endl;
delete ctx;
conn->auth.tag = NULL;
//Example of sending a file
// MSN::fileTransferInvite ft;
// ft.filename = "/tmp/filetosend.txt";
// ft.friendlyname = "filetosend2.txt";
// ft.sessionId = sessionID++;
// ft.type = MSN::FILE_TRANSFER_WITHOUT_PREVIEW;
// conn->sendFile(ft);
// conn->sendNudge();
// conn->sendAction("Action message here");
// Exemple of requesting a display picture.
// std::string filename2("/tmp/displayPicture.bin"+MSN::toStr(sessionID));
// lastObject is the msnobject received on each contact status change
// you should generate a random sessionID
// conn->requestDisplayPicture(sessionID++, filename2, lastObject);
// Example of sending a voice clip
// conn->myNotificationServer()->msnobj.addMSNObject("/tmp/voiceclip.wav",11);
// std::string obj;
// conn->myNotificationServer()->msnobj.getMSNObjectXML("/tmp/voiceclip.wav", 11, obj);
// conn->sendVoiceClip(obj);
// exemple of sending an ink
// std::string ink("base64 data here...");
// conn->sendInk(ink);
}
}
void Callbacks::buddyLeftConversation(MSN::SwitchboardServerConnection * conn, MSN::Passport username)
{
printf("%s has now left the session\n", username.c_str());
}
void Callbacks::gotInstantMessage(MSN::SwitchboardServerConnection * conn, MSN::Passport username, std::string friendlyname, MSN::Message * msg)
{
printf("--- Message from %s (%s) in font %s:\n%s\n", friendlyname.c_str(), username.c_str(), msg->getFontName().c_str(), msg->getBody().c_str());
}
void Callbacks::gotEmoticonNotification(MSN::SwitchboardServerConnection * conn, MSN::Passport username, std::string alias, std::string msnobject)
{
std::string filename2("/tmp/emoticon.bin"+MSN::toStr(sessionID));
printf("--- Emoticon '%s' from %s -> %s\n", alias.c_str(), username.c_str(), msnobject.c_str());
conn->requestEmoticon(sessionID++, filename2, msnobject, alias);
}
void Callbacks::failedSendingMessage(MSN::Connection * conn)
{
printf("**************************************************\n");
printf("ERROR: Your last message failed to send correctly\n");
printf("**************************************************\n");
}
void Callbacks::buddyTyping(MSN::SwitchboardServerConnection * conn, MSN::Passport username, std::string friendlyname)
{
printf("\t%s (%s) is typing...\n", friendlyname.c_str(), username.c_str());
}
void Callbacks::gotNudge(MSN::SwitchboardServerConnection * conn, MSN::Passport username)
{
printf("\t%s sent you a nudge ...\n", username.c_str());
}
void Callbacks::gotVoiceClipNotification(MSN::SwitchboardServerConnection * conn, MSN::Passport username, std::string msnobject)
{
printf("\t%s sent you a voice clip...\n", username.c_str());
std::string filename2("/tmp/voiceclip.bin"+MSN::toStr(sessionID));
conn->requestVoiceClip(sessionID++, filename2, msnobject);
}
void Callbacks::gotWinkNotification(MSN::SwitchboardServerConnection * conn, MSN::Passport username, std::string msnobject)
{
printf("\t%s sent you a Wink...\n", username.c_str());
std::string filename2("/tmp/wink.bin"+MSN::toStr(sessionID));
// you should generate a random sessionID number
conn->requestWink(sessionID++, filename2, msnobject);
}
void Callbacks::gotInk(MSN::SwitchboardServerConnection * conn, MSN::Passport username, std::string image)
{
// image variable is the base64 encoded gif file
printf("\t%s sent you an Ink...\n", username.c_str());
// std::string filename2("/tmp/ink.bin"+MSN::toStr(sessionID));
// you should generate a random sessionID number
// conn->requestFile(sessionID++, filename2, msnobject);
}
void Callbacks::gotContactDisplayPicture(MSN::SwitchboardServerConnection * conn, MSN::Passport passport, std::string filename )
{
printf("Received display picture from %s. File: %s\n", passport.c_str(), filename.c_str());
}
void Callbacks::gotActionMessage(MSN::SwitchboardServerConnection * conn, MSN::Passport username, std::string message)
{
printf("\t%s sent you an action message: %s\n", username.c_str(), message.c_str());
}
void Callbacks::gotInitialEmailNotification(MSN::NotificationServerConnection * conn, int msgs_inbox, int unread_inbox, int msgs_folders, int unread_folders)
{
if (unread_inbox > 0)
printf("You have %d new messages in your Inbox. Total: %d\n", unread_inbox, msgs_inbox);
if (unread_folders > 0)
printf("You have %d new messages in other folders. Total: %d\n", unread_folders, msgs_folders);
}
void Callbacks::gotNewEmailNotification(MSN::NotificationServerConnection * conn, std::string from, std::string subject)
{
printf("New e-mail has arrived from %s.\nSubject: %s\n", from.c_str(), subject.c_str());
}
void Callbacks::fileTransferInviteResponse(MSN::SwitchboardServerConnection * conn, unsigned int sessionID, bool response)
{
if(response)
printf("Session accepted %d: \n", sessionID);
else
printf("Session not accepted %d: \n", sessionID);
}
void Callbacks::fileTransferProgress(MSN::SwitchboardServerConnection * conn, unsigned int sessionID, unsigned long long transferred, unsigned long long total)
{
printf("File transfer: session %d\t(%llu/%llu bytes sent/received)\n", sessionID, transferred, total);
}
void Callbacks::fileTransferFailed(MSN::SwitchboardServerConnection * conn, unsigned int sessionID, MSN::fileTransferError error)
{
if( error == MSN::FILE_TRANSFER_ERROR_USER_CANCELED)
printf("The other user canceled the file transfer failed. Session: %d\n", sessionID);
if( error == MSN::FILE_TRANSFER_ERROR_UNKNOWN)
printf("File transfer failed. Session: %d\n", sessionID);
}
void Callbacks::fileTransferSucceeded(MSN::SwitchboardServerConnection * conn, unsigned int sessionID)
{
printf("File transfer successfully completed. session: %d\n", sessionID);
}
void Callbacks::gotNewConnection(MSN::Connection * conn)
{
if (dynamic_cast<MSN::NotificationServerConnection *>(conn))
dynamic_cast<MSN::NotificationServerConnection *>(conn)->synchronizeContactList();
}
void Callbacks::buddyChangedPersonalInfo(MSN::NotificationServerConnection * conn, MSN::Passport fromPassport, MSN::personalInfo pInfo)
{
// MSN::personalInfo shows all the data you can grab from the contact
printf("User %s Personal Message: %s\n", fromPassport.c_str(),pInfo.PSM.c_str());
}
void Callbacks::closingConnection(MSN::Connection * conn)
{
printf("Closed connection with socket %d\n", conn->sock);
}
void Callbacks::changedStatus(MSN::NotificationServerConnection * conn, MSN::BuddyStatus state)
{
printf("Your state is now: %s\n", MSN::buddyStatusToString(state).c_str());
MSN::personalInfo pInfo;
pInfo.PSM="my personal message";
pInfo.mediaType="Music";
pInfo.mediaIsEnabled=1;
pInfo.mediaFormat="{0} - {1}";
pInfo.mediaLines.push_back("Artist");
pInfo.mediaLines.push_back("Song");
conn->setPersonalStatus(pInfo);
}
void * Callbacks::connectToServer(std::string hostname, int port, bool *connected, bool isSSL)
{
struct sockaddr_in sa;
struct hostent *hp;
int s;
if ((hp = gethostbyname(hostname.c_str())) == NULL) {
errno = ECONNREFUSED;
return (void*)-1;
}
memset(&sa,0,sizeof(sa));
memcpy((char *)&sa.sin_addr,hp->h_addr,hp->h_length); /* set address */
sa.sin_family = hp->h_addrtype;
sa.sin_port = htons((u_short)port);
if ((s = socket(hp->h_addrtype,SOCK_STREAM,0)) < 0) /* get socket */
return (void*)-1;
int oldfdArgs = fcntl(s, F_GETFL, 0);
fcntl(s, F_SETFL, oldfdArgs | O_NONBLOCK);
if (connect(s,(struct sockaddr *)&sa,sizeof sa) < 0)
{
if (errno != EINPROGRESS)
{
close(s);
return (void*)-1;
}
*connected = false;
}
else
*connected = true;
return (void*)s;
}
int Callbacks::listenOnPort(int port)
{
int s;
struct sockaddr_in addr;
if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
return -1;
}
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
if (bind(s, (sockaddr *)(&addr), sizeof(addr)) < 0 || listen(s, 1) < 0)
{
close(s);
return -1;
}
return s;
}
std::string Callbacks::getOurIP(void)
{
struct hostent * hn;
char buf2[1024];
gethostname(buf2,1024);
hn = gethostbyname(buf2);
return inet_ntoa( *((struct in_addr*)hn->h_addr));
}
void Callbacks::log(int i, const char *s)
{
}
std::string Callbacks::getSecureHTTPProxy()
{
return "";
}
void Callbacks::gotMessageSentACK(MSN::SwitchboardServerConnection * conn, int trID)
{
std::cout << "Message " << trID << " delivered" << std::endl;
}
void Callbacks::askFileTransfer(MSN::SwitchboardServerConnection * conn, MSN::fileTransferInvite ft)
{
std::string filename2("/tmp/"+ft.filename);
switch(ft.type)
{
case MSN::FILE_TRANSFER_BACKGROUND_SHARING:
printf("User %s wants to share with you a background file named %s. Size: %llu. Accepting..\n", ft.userPassport.c_str(), ft.filename.c_str(), ft.filesize);
break;
case MSN::FILE_TRANSFER_BACKGROUND_SHARING_CUSTOM:
printf("User %s wants to share with you a *custom background file named %s. Size: %llu. Accepting..\n", ft.userPassport.c_str(), ft.filename.c_str(), ft.filesize);
break;
case MSN::FILE_TRANSFER_WITH_PREVIEW:
printf("User %s wants to send you a file *with preview named %s. Size: %llu. Accepting..\n", ft.userPassport.c_str(), ft.filename.c_str(), ft.filesize);
// ft.preview has the base64 encoded png file
break;
case MSN::FILE_TRANSFER_WITHOUT_PREVIEW:
printf("User %s wants to send you a file *without preview named %s. Size: %llu. Accepting..\n", ft.userPassport.c_str(), ft.filename.c_str(), ft.filesize);
break;
default:
printf("Unknown filetransfer type from %s..\n", ft.userPassport.c_str());
}
conn->fileTransferResponse(ft.sessionId, filename2, true);
}
void Callbacks::addedContactToGroup(MSN::NotificationServerConnection * conn, bool added, std::string groupId, std::string contactId)
{
if(added)
printf("User Id (%s) added to group Id (%s)\n", contactId.c_str(),groupId.c_str());
else
printf("User Id (%s) NOT added to group Id (%s)\n", contactId.c_str(),groupId.c_str());
}
void Callbacks::removedContactFromGroup(MSN::NotificationServerConnection * conn, bool removed, std::string groupId, std::string contactId)
{
if(removed)
printf("User Id (%s) removed from group Id (%s)\n", contactId.c_str(),groupId.c_str());
else
printf("User Id (%s) NOT removed from group Id (%s)\n", contactId.c_str(),groupId.c_str());
}
void Callbacks::addedContactToAddressBook(MSN::NotificationServerConnection * conn, bool added, std::string passport, std::string displayName, std::string guid)
{
if(added)
printf("User (%s - %s) added to AddressBook. Guid (%s)\n", passport.c_str(),displayName.c_str(), guid.c_str());
else
printf("User (%s - %s) NOT added to AddressBook.\n", passport.c_str(),displayName.c_str());
}
void Callbacks::removedContactFromAddressBook(MSN::NotificationServerConnection * conn, bool removed, std::string contactId, std::string passport)
{
if(removed)
printf("User %s removed from AddressBook. Guid (%s)\n", passport.c_str(), contactId.c_str());
else
printf("User %s NOT removed from AddressBook. Guid (%s)\n", passport.c_str(), contactId.c_str());
}
void Callbacks::enabledContactOnAddressBook(MSN::NotificationServerConnection * conn, bool enabled, std::string contactId, std::string passport)
{
// this is used to enable a contact previously disabled from msn, but not fully removed
if(enabled)
printf("User (%s) enabled on AddressBook. Guid (%s)\n", passport.c_str(), contactId.c_str());
else
printf("User (%s) NOT enabled on AddressBook. Guid (%s)\n", passport.c_str(), contactId.c_str());
}
void Callbacks::disabledContactOnAddressBook(MSN::NotificationServerConnection * conn, bool disabled, std::string contactId)
{
// this is used when you have disabled this user from msn, but not deleted from hotmail
// I suggest to delete the contact instead of disable, since I haven't tested this too much yet
if(disabled)
printf("User disabled on AddressBook. Guid (%s)\n", contactId.c_str());
else
printf("User NOT disabled on AddressBook. Guid (%s)\n", contactId.c_str());
}
size_t Callbacks::getDataFromSocket (void *sock, char *data, size_t size)
{
int fd;
int idx=0;
bool ssl_done = false;
int amountRead = 0;
int newAmountRead = 0;
for (int i = 1; i < 20; i++)
{
if(mySockets[i].fd == getSocketFileDescriptor(sock))
{
idx = i;
break;
}
}
if(!idx)
return 0;
if(!mySocketsSsl[idx].isSSL)
{
int newWritten = ::recv(getSocketFileDescriptor(sock), data, size, 0);
if (errno == EAGAIN)
return -1;
return newWritten;
}
if (!mySocketsSsl[idx].isConnected)
return 0;
while(!ssl_done)
{
if(!mySocketsSsl[idx].ssl) break;
newAmountRead = SSL_read(mySocketsSsl[idx].ssl, data, size);
switch(SSL_get_error(mySocketsSsl[idx].ssl,newAmountRead))
{
case SSL_ERROR_NONE:
return newAmountRead;
case SSL_ERROR_ZERO_RETURN:
return 0;
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
ssl_done=false;
break;
case SSL_ERROR_SSL:
return 0;
break;
case SSL_ERROR_SYSCALL:
return 0;
break;
default:
return newAmountRead;
}
}
return 0;
}
size_t Callbacks::writeDataToSocket (void *sock, char *data, size_t size)
{
size_t written = 0;
int idx;
for (int i = 1; i < 20; i++)
{
if(mySockets[i].fd == getSocketFileDescriptor(sock))
{
idx = i;
break;
}
}
while (written < size)
{
int newWritten;
if (mySocketsSsl[idx].isSSL)
{
if(!mySocketsSsl[idx].isConnected)
return 0;
newWritten = SSL_write(mySocketsSsl[idx].ssl, data, (int) (size - written));
int error = SSL_get_error(mySocketsSsl[idx].ssl,newWritten);
switch(error)
{
case SSL_ERROR_NONE:
written += newWritten;
data+=newWritten;
break;
case SSL_ERROR_WANT_WRITE:
case SSL_ERROR_WANT_READ:
continue;
case SSL_ERROR_ZERO_RETURN:
break;
case SSL_ERROR_SYSCALL:
default:
break;
}
}
else
{
newWritten = ::send(getSocketFileDescriptor(sock), data, (int)(size - written), 0);
if (newWritten <= 0)
{
if (errno == EAGAIN)
continue;
else
break;
}
written += newWritten;
data+=newWritten;
}
}
if (written != size)
{
// TODO: return an error
showError(NULL, "Error on socket");
unregisterSocket(sock);
closeSocket(sock);
return written;
}
return written;
}
void Callbacks::gotVoiceClipFile(MSN::SwitchboardServerConnection * conn, unsigned int sessionID, std::string file)
{
printf("--- Voice clip file '%s'\n", file.c_str());
}
void Callbacks::gotEmoticonFile(MSN::SwitchboardServerConnection * conn, unsigned int sessionID, std::string alias, std::string file)
{
printf("--- Voice emoticon file '%s' for '%s'\n", file.c_str(), alias.c_str());
}
void Callbacks::gotWinkFile(MSN::SwitchboardServerConnection * conn, unsigned int sessionID, std::string file)
{
printf("--- Voice Wink file '%s'\n", file.c_str());
}
void Callbacks::gotInboxUrl(MSN::NotificationServerConnection *conn, MSN::hotmailInfo info)
{
std::vector<std::string>::const_iterator i;
std::cout << "--- Inbox URL data :" << std::endl;
std::cout << "sid: " << info.sid << std::endl;
std::cout << "kv: " << info.kv << std::endl;
std::cout << "id: " << info.id << std::endl;
std::cout << "sl: " << info.sl << std::endl;
std::cout << "rru: " << info.rru << std::endl;
std::cout << "auth: " << info.MSPAuth << std::endl;
std::cout << "creds: " << info.creds << std::endl;
}