Exemple #1
0
status_t MSNManager::TypingNotification(const char *passport, uint16 typing) {
	LOG(kProtocolName, liDebug, "Typing notify to %s", passport);
		
	if ((fConnectionState != otOffline) && (fConnectionState != otConnecting)) {
		if (fNoticeCon == NULL) {
			LOG(kProtocolName, liDebug, "Can't send typing notify to %s, fNoticeCon is null", passport);
			return B_ERROR;
		}
		
		// Set up message
		Command *msg = new Command("MSG");
		msg->AddParam("U");
		BString format = "MIME-Version: 1.0\r\n"
			"Content-Type: text/x-msmsgscontrol\r\n"
			"TypingUser: "******"\r\n";
		format << "\r\n\r\n";
		
		msg->AddPayload(format.String(), format.Length());
						
		// Find connection
		bool needSB = false;
		connectionlist::iterator it;
		for ( it=fConnections.begin(); it != fConnections.end(); it++ )
		{
			MSNSBConnection * c = dynamic_cast<MSNSBConnection*>( *it );
			
			if ( c != NULL  && c->IsSingleChatWith( passport ) )
				break;
		}
		
		Command *sbReq = NULL;
		
		if (it == fConnections.end()) {
			LOG(kProtocolName, liDebug, "Can't send typing notify to %s, no open connection: opening new",
				passport);
			
			sbReq =  new Command("XFR");
			sbReq->AddParam("SB");	// Request a SB connection;
			
			fNoticeCon->Send(sbReq, qsImmediate);	
			
			needSB = true;
		};
		
		if (needSB) {
			fWaitingSBs[sbReq->TransactionID()] = std::pair<BString,Command*>(passport, msg);
		} else {
			(*it)->Send(msg);
		};
		
		return B_OK;
	};
	
	LOG(kProtocolName, liHigh, "Error sending typing notification to %s", passport);
	
	return B_ERROR;
};
Exemple #2
0
status_t MSNManager::MessageUser(const char *passport, const char *message) {
	if ((fConnectionState != otOffline) && (fConnectionState != otConnecting)) {
		if (fNoticeCon == NULL) {
			LOG(kProtocolName, liDebug, "Could not message %s, fNoticeCon is null", passport);
			return B_ERROR;
		}
		
		// Set up message
		Command *msg = new Command("MSG");
		msg->AddParam("N"); // Don't ack packet
		BString format = "MIME-Version: 1.0\r\n"
			"Content-Type: text/plain; charset=UTF-8\r\n"
			"X-MMS-IM-Format: FN=Arial; EF=I; CO=0; CS=0; PF=22\r\n\r\n";
		format << message;
		
		msg->AddPayload(format.String(), format.Length());
		
		// Find connection
		bool needSB = false;
		connectionlist::iterator it;
		for ( it=fConnections.begin(); it != fConnections.end(); it++ )
		{
			MSNSBConnection * c = dynamic_cast<MSNSBConnection*>( *it );
			
			if ( c != NULL  && c->IsSingleChatWith( passport ) )
				break;
		}
		
		Command *sbReq = NULL;
		
		if (it == fConnections.end()) {
			LOG(kProtocolName, liDebug, "Could not message %s, no open connection: opening new",
				passport);
			
			sbReq =  new Command("XFR");
			sbReq->AddParam("SB");	// Request a SB connection;
			
			fNoticeCon->Send(sbReq, qsImmediate);	
			
			needSB = true;
		};
		
		if (needSB) {
			fWaitingSBs[sbReq->TransactionID()] = std::pair<BString,Command*>(passport, msg);
		} else {
			(*it)->Send(msg);
		};
		
		return B_OK;
	};
	
	LOG(kProtocolName, liHigh, "Error sending message to %s", passport);
	
	return B_ERROR;
};
status_t MSNConnection::HandleUSR( Command * command ) {
	LOG(kProtocolName, liDebug, "C %lX: Processing USR", this);
	status_t result = B_ERROR;

	if (strcmp(command->Param(0), "OK") == 0) {
		Progress("MSN Login", "MSN: Logged in!", 1.0);
		
		GoOnline();
		
		BMessage statusChange(msnmsgOurStatusChanged);
		statusChange.AddInt8("status", fState);
		fManMsgr.SendMessage(&statusChange);

		/*
		 * Depending on the server protocol, server location and the
		 * account being used (non-hotmail/msn acc), the server will not
		 * respond on the PRP MFN command and our connection will break.
		 * Michael
		 */
		BString passport(fManager->Passport());
		
		if ((B_ERROR != passport.FindFirst("@hotmail")) || (B_ERROR != passport.FindFirst("@msn"))) {
			LOG(kProtocolName, liDebug, "Sending PRP MSN command" );
			
			Command *rea = new Command("PRP");
			rea->AddParam("MFN");
			rea->AddParam(fManager->DisplayName(), true);
			Send(rea);
		} else {
			LOG(kProtocolName, liDebug, "Not sending PRP MSN command!");
		};
		
		fManager->Handler()->ContactList(&fContacts);
				
		Command *adl = new Command("ADL");
		
		std::list<BString> contacts;
		std::map<BString, std::list<BString> > domainUsers;
		
		fManager->Handler()->ContactList(&contacts);
		
		// Make our contact list into a list by domain
		for (std::list<BString>::iterator iIt = contacts.begin(); iIt != contacts.end(); iIt++) {
			BString user;
			BString domain;
			
			if (SplitEmail((*iIt).String(), user, domain) == B_OK) {			
				std::map<BString, std::list<BString> >::iterator dIt = domainUsers.find(domain);
				if (dIt == domainUsers.end()) {
					std::list<BString> users;
					users.push_back(user);
					
					domainUsers[domain] = users;
				} else {
					dIt->second.push_back(user);
				};
			};
		};

		BString payload = "<ml l=\"1\">";

		// Package each contact by domain
		for (std::map<BString, std::list<BString> >::iterator dIt = domainUsers.begin(); dIt != domainUsers.end(); dIt++) {
			payload << "<d n=\"" << dIt->first << "\">";
		
			for (std::list<BString>::iterator uIt = dIt->second.begin(); uIt != dIt->second.end(); uIt++) {
				payload << "<c n=\"" << (*uIt) <<  "\" l=\"3\" t=\"1\" />";
			};
			
			payload << "</d>";
		};
		
		payload << "</ml>";
		adl->AddPayload(payload.String());
		
		Send(adl);
		
		Command *chg = new Command("CHG");
		chg->AddParam("NLN");
		BString caps = "";
		caps << kOurCaps;
		chg->AddParam( caps.String() );
		Send(chg);

		result = B_OK;
	} else {
		BString URI = command->Param(2);
		BString nonce = command->Param(3);
		BString authResp = "";
		BString authToken = "";

		SSO *auth = new SSO(NULL, fManager->Passport(), fManager->Password(), URI.String(),
			nonce.String());

		result = auth->Response(authToken, authResp);

		if (result == B_OK) {
			Command *reply = new Command("USR");
			reply->AddParam("SSO");
			reply->AddParam("S");
			reply->AddParam(authToken.String());
			reply->AddParam(authResp.String());
			
			reply->Debug();
			
			Send(reply);
		};

	};
	
	return result;
}
int32 MSNConnection::Receiver(void *con) {
	LOG(kProtocolName, liLow, "C[r] %lX: Receiver init", con);

	MSNConnection *connection = reinterpret_cast<MSNConnection *>(con);

	const uint32 kSleep = 2000000;
	BMessenger **kMsgr = &connection->fSockMsgr;
	int32 socket = 0;
	
	if ( !(*kMsgr)->IsValid() ) {
		LOG(kProtocolName, liLow, "C[r] %lX: Messenger wasn't valid!", connection);
		return B_ERROR;
	}
	
	BMessage reply;
	socket = connection->fSock;
		
	struct fd_set read;
	struct fd_set error;
	int16 bytes = 0;
	int32 processed = 0;
	char buffer[1024];
	BString commandBuff = "";
	int32 kNewLineLen = strlen("\r\n");
	
	LOG(kProtocolName, liLow, "C[r] %lX: Starting receiver loop", connection);
	
	while ((*kMsgr)->IsValid() == true) {
		FD_ZERO(&read);
		FD_ZERO(&error);
		
		FD_SET(socket, &read);
		FD_SET(socket, &error);

		memset(buffer, 0, sizeof(buffer));

		if (select(socket + 1, &read, NULL, &error, NULL) > 0) {

			if (FD_ISSET(socket, &error)) {
				LOG(kProtocolName, liLow, "C[r] %lX: Got socket error", connection);
				snooze(kSleep);
				continue;
			};
			
			if (FD_ISSET(socket, &read)) {
				bytes = recv(socket, buffer, sizeof(buffer), 0);
				if (bytes > 0) {
					commandBuff.Append(buffer, bytes);
					processed += bytes;
				} else {
					if ((*kMsgr)->IsValid() == false) return B_OK;
					
					LOG(kProtocolName, liLow, "C[r] %lX: Socket got less than 0 (or 0)",
						connection);
					perror("SOCKET ERROR");
					
					BMessage msg(msnmsgCloseConnection);
					msg.AddPointer("connection", con);
					
					connection->fManMsgr.SendMessage(&msg);
					connection->fState = otOffline;
					
					return B_ERROR;
				};					
			};
		};
		
		int32 commandLen = commandBuff.FindFirst("\r\n");
		
		while (commandLen > 0) {
			BString command = "";
			int32 totalLen = commandBuff.Length();
			commandBuff.MoveInto(command, 0, commandLen + kNewLineLen);

			processed = totalLen - (commandLen + kNewLineLen);

			Command *comm = new Command("");
			comm->MakeObject(command.String());
			int32 payloadLen = 0;

			if (comm->ExpectsPayload(&payloadLen) == true) {
				LOG(kProtocolName, liDebug, "C[r] %lX: Payload of %i, have %i bytes",
					connection, payloadLen, processed);		
				
				while (processed < payloadLen) {
					FD_ZERO(&read);
					FD_ZERO(&error);
					
					FD_SET(socket, &read);
					FD_SET(socket, &error);
			
					memset(buffer, 0, sizeof(buffer));
			
					if (select(socket + 1, &read, NULL, &error, NULL) > 0) {				
						if (FD_ISSET(socket, &error)) {
							LOG(kProtocolName, liLow, "C[r] %lX: Got socket error", 
								connection);
							snooze(kSleep);
							continue;
						};
						
						if (FD_ISSET(socket, &read)) {
							bytes = recv(socket, buffer, min_c(payloadLen - processed, (int32)sizeof(buffer)), 0);
							if (bytes > 0) {
								commandBuff.Append(buffer, bytes);
								processed += bytes;
							} else {
								if ( (*kMsgr)->IsValid() == false) return B_OK;
		
								LOG(kProtocolName, liLow, "--C[r] %lX: Socket got less than 0 (or 0: %i)",
									connection, bytes);
								perror("SOCKET ERROR");
		
								BMessage msg(msnmsgCloseConnection);
								msg.AddPointer("connection", con);
				
								connection->fManMsgr.SendMessage(&msg);
								connection->fState = otOffline;
								
								return B_ERROR;
							};					
						};
					};
					
				};
				
//				add payload to message?
				comm->AddPayload( commandBuff.String(), payloadLen, false );
				commandBuff.Remove( 0, payloadLen );
				
				processed = commandBuff.Length();
			};
			
			BMessage dataReady(msnmsgDataReady);
			dataReady.AddPointer("command", comm);
			
			(*kMsgr)->SendMessage(&dataReady);
			
// 			this line needed to process several commands at once if they're in the
//			buffer
			commandLen = commandBuff.FindFirst("\r\n");
		};
	};
	
	return B_OK;
};
status_t MSNConnection::HandleCHL( Command * command ) {
	LOG(kProtocolName, liDebug, "C %lX: Processing CHL", this);

	const char *challenge = command->Param(0);
	int i = 0;
	unsigned char buf[256];
	char chlString[128];
	long long high = 0;
	long long low = 0;
	long long temp = 0;
	long long key = 0;
	long long bskey = 0;
	int *chlStringArray = (int *)chlString;
	int *md5hash = (int *)buf;
	char hash1a[17];
	char hash2a[17];

	sprintf((char *)buf + 16, "%s%s", challenge, kClientCode);
	MD5(buf + 16, strlen((char *)buf + 16), buf);
	for (i = 0; i < 16; i++) {
		sprintf((char *)buf + 16 + i * 2,"%02x", buf[i]);
	};
	
	for (i = 0; i < 4; i++) {
	   md5hash[i] = md5hash[i] & 0x7FFFFFFF;
	};
	
	i = (strlen(challenge) + strlen(kClientID) + 7) & 0xF8;
	sprintf(chlString,"%s%s00000000", challenge, kClientID);
	chlString[i] = 0;
	
	for (i = 0; i < (int)strlen(chlString) / 4; i += 2) {
		temp = chlStringArray[i];
		
		temp = (0x0E79A9C1 * temp) % 0x7FFFFFFF;
		temp += high;
		temp = md5hash[0] * temp + md5hash[1];
		temp = temp % 0x7FFFFFFF;
		
		high = chlStringArray[i + 1];
		high = (high + temp) % 0x7FFFFFFF;
		high = md5hash[2] * high + md5hash[3];
		high = high % 0x7FFFFFFF;
		
		low = low + high + temp;
	};
	
	high = (high + md5hash[1]) % 0x7FFFFFFF;
	low = (low + md5hash[3]) % 0x7FFFFFFF;
	
	key = (low << 32) + high;
	for (i= 0; i < 8; i++) {
		bskey <<= 8;
		bskey += key & 255;
		key >>=8;
	};
	
	strncpy((char *)hash1a, (char *)buf + 16, 16);
	strncpy((char *)hash2a, (char *)buf + 32, 16);
	hash1a[16] = '\0';
	hash2a[16] = '\0';
	
	sprintf((char *)buf, "%llx%llx", strtoull(hash1a,NULL,16) ^ bskey,
		strtoull(hash2a,NULL,16) ^ bskey);

	Command *reply = new Command("QRY");
	reply->AddParam(kClientID);
	reply->AddPayload((char *)buf, 32);
	
	Send(reply);
	reply->Debug();
	
	return B_OK;
};