INT_PTR __cdecl CJabberProto::JabberServiceParseXmppURI(WPARAM, LPARAM lParam)
{
	TCHAR *arg = (TCHAR *)lParam;
	if (arg == NULL)
		return 1;

	// skip leading prefix
	TCHAR szUri[ 1024 ];
	_tcsncpy_s(szUri, SIZEOF(szUri), arg, _TRUNCATE);
	TCHAR *szJid = _tcschr(szUri, _T(':'));
	if (szJid == NULL)
		return 1;

	// skip //
	for (++szJid; *szJid == _T('/'); ++szJid);

	// empty jid?
	if (!*szJid)
		return 1;

	// command code
	TCHAR *szCommand = szJid;
	szCommand = _tcschr(szCommand, _T('?'));
	if (szCommand)
		*(szCommand++) = 0;

	// parameters
	TCHAR *szSecondParam = szCommand ? _tcschr(szCommand, _T(';')) : NULL;
	if (szSecondParam)
		*(szSecondParam++) = 0;

	// no command or message command
	if (!szCommand || (szCommand && !_tcsicmp(szCommand, _T("message")))) {
		// message
		if (!ServiceExists(MS_MSG_SENDMESSAGEW))
			return 1;

		TCHAR *szMsgBody = NULL;
		HANDLE hContact = HContactFromJID(szJid, TRUE);
		if (hContact == NULL)
			hContact = DBCreateContact(szJid, szJid, TRUE, TRUE);
		if (hContact == NULL)
			return 1;

		if (szSecondParam) { //there are parameters to message
			szMsgBody = _tcsstr(szSecondParam, _T("body="));
			if (szMsgBody) {
				szMsgBody += 5;
				TCHAR *szDelim = _tcschr(szMsgBody, _T(';'));
				if (szDelim)
					szDelim = 0;
				JabberHttpUrlDecode(szMsgBody);
			}
		}

		CallService(MS_MSG_SENDMESSAGEW, (WPARAM)hContact, (LPARAM)szMsgBody);
		return 0;
	}
	
	if (!_tcsicmp(szCommand, _T("roster"))) {
		if (!HContactFromJID(szJid)) {
			JABBER_SEARCH_RESULT jsr = { 0 };
			jsr.hdr.cbSize = sizeof(JABBER_SEARCH_RESULT);
			jsr.hdr.flags = PSR_TCHAR;
			jsr.hdr.nick = szJid;
			jsr.hdr.id = szJid;
			_tcsncpy(jsr.jid, szJid, SIZEOF(jsr.jid) - 1);

			ADDCONTACTSTRUCT acs;
			acs.handleType = HANDLE_SEARCHRESULT;
			acs.szProto = m_szModuleName;
			acs.psr = &jsr.hdr;
			CallService(MS_ADDCONTACT_SHOW, 0, (LPARAM)&acs);
		}
		return 0;
	}
	
	// chat join invitation
	if (!_tcsicmp(szCommand, _T("join"))) {
		GroupchatJoinRoomByJid(NULL, szJid);
		return 0;
	}
	
	// service discovery request
	if (!_tcsicmp(szCommand, _T("disco"))) {
		OnMenuHandleServiceDiscovery(0, (LPARAM)szJid);
		return 0;
	}
	
	// ad-hoc commands
	if (!_tcsicmp(szCommand, _T("command"))) {
		if (szSecondParam) {
			if (!_tcsnicmp(szSecondParam, _T("node="), 5)) {
				szSecondParam += 5;
				if (!*szSecondParam)
					szSecondParam = NULL;
			}
			else szSecondParam = NULL;
		}
		CJabberAdhocStartupParams* pStartupParams = new CJabberAdhocStartupParams(this, szJid, szSecondParam);
		ContactMenuRunCommands(0, (LPARAM)pStartupParams);
		return 0;
	}
	
	// send file
	if (!_tcsicmp(szCommand, _T("sendfile"))) {
		if (!ServiceExists(MS_FILE_SENDFILE))
			return 1;

		HANDLE hContact = HContactFromJID(szJid, TRUE);
		if (hContact == NULL)
			hContact = DBCreateContact(szJid, szJid, TRUE, TRUE);
		if (hContact == NULL)
			return 1;
		CallService(MS_FILE_SENDFILE, (WPARAM)hContact, (LPARAM)NULL);
		return 0;
	}

	return 1; /* parse failed */
}
Exemple #2
0
int CJabberProto::FileReceiveParse(filetransfer *ft, char* buffer, int datalen)
{
	char* p, *q, *s, *eob;
	int num, code;

	eob = buffer + datalen;
	p = buffer;
	num = 0;
	while (true) {
		if (ft->state == FT_CONNECTING || ft->state == FT_INITIALIZING) {
			for (q = p; q + 1 < eob && (*q != '\r' || *(q + 1) != '\n'); q++);
			if (q + 1 >= eob)
				break;

			ptrA str(mir_strndup(p, size_t(q - p)));
			if (str == NULL) {
				ft->state = FT_ERROR;
				break;
			}

			debugLogA("FT Got: %s", str);
			if (ft->state == FT_CONNECTING) {
				// looking for "HTTP/1.1 200 OK"
				if (sscanf(str, "HTTP/%*d.%*d %d %*s", &code) == 1 && code == 200) {
					ft->state = FT_INITIALIZING;
					ft->std.currentFileSize = -1;
					debugLogA("Change to FT_INITIALIZING");
					ProtoBroadcastAck(ft->std.hContact, ACKTYPE_FILE, ACKRESULT_INITIALISING, ft, 0);
				}
			}
			else {	// FT_INITIALIZING
				if (str[0] == '\0') {
					TCHAR *s;
					if ((s = _tcsrchr(ft->httpPath, '/')) != NULL)
						s++;
					else
						s = ft->httpPath;
					ft->std.tszCurrentFile = mir_tstrdup(s);
					JabberHttpUrlDecode(ft->std.tszCurrentFile);
					if (ft->create() == -1) {
						ft->state = FT_ERROR;
						break;
					}
					ft->state = FT_RECEIVING;
					ft->std.currentFileProgress = 0;
					debugLogA("Change to FT_RECEIVING");
				}
				else if ((s = strchr(str, ':')) != NULL) {
					*s = '\0';
					if (!mir_strcmp(str, "Content-Length"))
						ft->std.totalBytes = ft->std.currentFileSize = _atoi64(s + 1);
				}
			}

			q += 2;
			num += (q - p);
			p = q;
		}
		else if (ft->state == FT_RECEIVING) {
			int bufferSize, writeSize;
			__int64 remainingBytes;

			if (ft->std.currentFileProgress < ft->std.currentFileSize) {
				bufferSize = eob - p;
				remainingBytes = ft->std.currentFileSize - ft->std.currentFileProgress;
				if (remainingBytes < bufferSize)
					writeSize = remainingBytes;
				else
					writeSize = bufferSize;
				if (_write(ft->fileId, p, writeSize) != writeSize) {
					debugLogA("_write() error");
					ft->state = FT_ERROR;
				}
				else {
					ft->std.currentFileProgress += writeSize;
					ft->std.totalProgress += writeSize;
					ProtoBroadcastAck(ft->std.hContact, ACKTYPE_FILE, ACKRESULT_DATA, ft, (LPARAM)&ft->std);
					if (ft->std.currentFileProgress == ft->std.currentFileSize)
						ft->state = FT_DONE;
				}
			}
			num = datalen;
			break;
		}
		else break;
	}

	return num;
}
Exemple #3
0
BOOL CJabberProto::OnIqRequestOOB(HXML, CJabberIqInfo *pInfo)
{
	if (!pInfo->GetFrom() || !pInfo->GetHContact())
		return TRUE;

	HXML n = XmlGetChild(pInfo->GetChildNode(), "url");
	if (!n || !XmlGetText(n))
		return TRUE;

	if (m_options.BsOnlyIBB) {
		// reject
		XmlNodeIq iq(_T("error"), pInfo);
		HXML e = XmlAddChild(iq, _T("error"), _T("File transfer refused")); XmlAddAttr(e, _T("code"), 406);
		m_ThreadInfo->send(iq);
		return TRUE;
	}

	filetransfer *ft = new filetransfer(this);
	ft->std.totalFiles = 1;
	ft->jid = mir_tstrdup(pInfo->GetFrom());
	ft->std.hContact = pInfo->GetHContact();
	ft->type = FT_OOB;
	ft->httpHostName = NULL;
	ft->httpPort = 80;
	ft->httpPath = NULL;

	// Parse the URL
	TCHAR *str = (TCHAR*)XmlGetText(n);	// URL of the file to get
	if (!_tcsnicmp(str, _T("http://"), 7)) {
		TCHAR *p = str + 7, *q;
		if ((q = _tcschr(p, '/')) != NULL) {
			TCHAR text[1024];
			if (q - p < _countof(text)) {
				_tcsncpy_s(text, p, q - p);
				text[q - p] = '\0';
				if ((p = _tcschr(text, ':')) != NULL) {
					ft->httpPort = (WORD)_ttoi(p + 1);
					*p = '\0';
				}
				ft->httpHostName = mir_t2a(text);
			}
		}
	}

	if (pInfo->GetIdStr())
		ft->szId = JabberId2string(pInfo->GetIqId());

	if (ft->httpHostName && ft->httpPath) {
		TCHAR *desc = NULL;

		debugLogA("Host=%s Port=%d Path=%s", ft->httpHostName, ft->httpPort, ft->httpPath);
		if ((n = XmlGetChild(pInfo->GetChildNode(), "desc")) != NULL)
			desc = (TCHAR*)XmlGetText(n);

		TCHAR *str2;
		debugLog(_T("description = %s"), desc);
		if ((str2 = _tcsrchr(ft->httpPath, '/')) != NULL)
			str2++;
		else
			str2 = ft->httpPath;
		str2 = mir_tstrdup(str2);
		JabberHttpUrlDecode(str2);

		PROTORECVFILET pre;
		pre.dwFlags = PRFF_TCHAR;
		pre.timestamp = time(NULL);
		pre.descr.t = desc;
		pre.files.t = &str2;
		pre.fileCount = 1;
		pre.lParam = (LPARAM)ft;
		ProtoChainRecvFile(ft->std.hContact, &pre);
		mir_free(str2);
	}
	else {
		// reject
		XmlNodeIq iq(_T("error"), pInfo);
		HXML e = XmlAddChild(iq, _T("error"), _T("File transfer refused")); XmlAddAttr(e, _T("code"), 406);
		m_ThreadInfo->send(iq);
		delete ft;
	}
	return TRUE;
}
Exemple #4
0
int CJabberProto::FileSendParse(JABBER_SOCKET s, filetransfer *ft, char* buffer, int datalen)
{
	char* p, *q, *t, *eob;
	char* str;
	int num;
	int currentFile;
	int fileId;
	int numRead;

	eob = buffer + datalen;
	p = buffer;
	num = 0;
	while (ft->state == FT_CONNECTING || ft->state == FT_INITIALIZING) {
		for (q = p; q + 1 < eob && (*q != '\r' || *(q + 1) != '\n'); q++);
		if (q + 1 >= eob)
			break;
		if ((str = (char*)mir_alloc(q - p + 1)) == NULL) {
			ft->state = FT_ERROR;
			break;
		}
		strncpy_s(str, q - p, p, _TRUNCATE);
		str[q - p] = '\0';
		debugLogA("FT Got: %s", str);
		if (ft->state == FT_CONNECTING) {
			// looking for "GET filename.ext HTTP/1.1"
			if (!strncmp(str, "GET ", 4)) {
				for (t = str + 4; *t != '\0' && *t != ' '; t++);
				*t = '\0';
				for (t = str + 4; *t != '\0' && *t == '/'; t++);
				ft->httpPath = mir_a2t(t);
				JabberHttpUrlDecode(ft->httpPath);
				ft->state = FT_INITIALIZING;
				debugLogA("Change to FT_INITIALIZING");
			}
		}
		else {	// FT_INITIALIZING
			if (str[0] == '\0') {
				struct _stati64 statbuf;

				mir_free(str);
				num += 2;

				currentFile = ft->std.currentFileNumber;
				TCHAR *t = _tcsrchr(ft->std.ptszFiles[currentFile], '\\');
				if (t != NULL)
					t++;
				else
					t = ft->std.ptszFiles[currentFile];

				if (ft->httpPath == NULL || mir_tstrcmp(ft->httpPath, t)) {
					if (ft->httpPath == NULL)
						debugLogA("Requested file name does not matched (httpPath == NULL)");
					else
						debugLog(_T("Requested file name does not matched ('%s' vs. '%s')"), ft->httpPath, t);
					ft->state = FT_ERROR;
					break;
				}
				debugLog(_T("Sending [%s]"), ft->std.ptszFiles[currentFile]);
				_tstati64(ft->std.ptszFiles[currentFile], &statbuf);	// file size in statbuf.st_size
				if ((fileId = _topen(ft->std.ptszFiles[currentFile], _O_BINARY | _O_RDONLY)) < 0) {
					debugLogA("File cannot be opened");
					ft->state = FT_ERROR;
					mir_free(ft->httpPath);
					ft->httpPath = NULL;
					break;
				}

				char fileBuffer[2048];
				int bytes = mir_snprintf(fileBuffer, _countof(fileBuffer), "HTTP/1.1 200 OK\r\nContent-Length: %I64u\r\n\r\n", statbuf.st_size);
				WsSend(s, fileBuffer, bytes, MSG_DUMPASTEXT);

				ft->std.flags |= PFTS_SENDING;
				ft->std.currentFileProgress = 0;
				debugLogA("Sending file data...");

				while ((numRead = _read(fileId, fileBuffer, 2048)) > 0) {
					if (Netlib_Send(s, fileBuffer, numRead, 0) != numRead) {
						ft->state = FT_ERROR;
						break;
					}
					ft->std.currentFileProgress += numRead;
					ft->std.totalProgress += numRead;
					ProtoBroadcastAck(ft->std.hContact, ACKTYPE_FILE, ACKRESULT_DATA, ft, (LPARAM)&ft->std);
				}
				_close(fileId);
				if (ft->state != FT_ERROR)
					ft->state = FT_DONE;
				debugLogA("Finishing this file...");
				mir_free(ft->httpPath);
				ft->httpPath = NULL;
				break;
		}	}

		mir_free(str);
		q += 2;
		num += (q-p);
		p = q;
	}

	return num;
}