/* "Last Seen mod" plugin for Miranda IM Copyright ( C ) 2002-03 micron-x Copyright ( C ) 2005-07 Y.B. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or ( at your option ) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. File name : $URL: http://svn.berlios.de/svnroot/repos/mgoodies/trunk/lastseen-mod/utils.c $ Revision : $Rev: 1570 $ Last change on : $Date: 2007-12-30 01:30:07 +0300 (Вс, 30 дек 2007) $ Last change by : $Author: y_b $ */ #include "seen.h" #include #include void FileWrite(HANDLE); void HistoryWrite(HANDLE hcontact); //void SetOffline(void); void ShowHistory(HANDLE hContact, BYTE isAlert); char * courProtoName = 0; //copied from ..\..\miranda32\protocols\protocols\protocols.c PROTOCOLDESCRIPTOR* Proto_IsProtocolLoaded(const char* szProto) { return (PROTOCOLDESCRIPTOR*) CallService(MS_PROTO_ISPROTOCOLLOADED, 0, (LPARAM)szProto); } /* Returns true if the protocols is to be monitored */ int IsWatchedProtocol(const char* szProto) { DBVARIANT dbv; char *szProtoPointer, *szWatched; int iProtoLen, iWatchedLen; int retval = 0; PROTOCOLDESCRIPTOR *pd; if (szProto == NULL) return 0; pd=Proto_IsProtocolLoaded(szProto); if (pd==NULL || pd->type!=PROTOTYPE_PROTOCOL || CallProtoService(pd->szName,PS_GETCAPS,PFLAGNUM_2,0)==0) return 0; iProtoLen = (int)_tcslen(szProto); if(DBGetContactSetting(NULL, S_MOD, "WatchedProtocols", &dbv)) szWatched = DEFAULT_WATCHEDPROTOCOLS; else szWatched = dbv.pszVal; iWatchedLen = (int)_tcslen(szWatched); if (*szWatched == '\0') { retval=1; //empty string: all protocols are watched } else { char sTemp [MAXMODULELABELLENGTH+1]=""; strcat(sTemp,szProto); strcat(sTemp," "); szProtoPointer = strstr(szWatched, sTemp); if (szProtoPointer == NULL) retval=0; else retval=1; } DBFreeVariant(&dbv); return retval; } BOOL isYahoo(char * protoname){ if (protoname) { char *pszUniqueSetting = (char*)CallProtoService(protoname, PS_GETCAPS, PFLAG_UNIQUEIDSETTING, 0); if (pszUniqueSetting){ return (!strcmp(pszUniqueSetting,"yahoo_id")); } } return FALSE; } BOOL isJabber(char * protoname){ if (protoname) { char *pszUniqueSetting = (char*)CallProtoService(protoname, PS_GETCAPS, PFLAG_UNIQUEIDSETTING, 0); if (pszUniqueSetting){ return (!strcmp(pszUniqueSetting,"jid")); } } return FALSE; } BOOL isICQ(char * protoname){ if (protoname) { char *pszUniqueSetting = (char*)CallProtoService(protoname, PS_GETCAPS, PFLAG_UNIQUEIDSETTING, 0); if (pszUniqueSetting){ return (!strcmp(pszUniqueSetting,"UIN")); } } return FALSE; } BOOL isMSN(char * protoname){ if (protoname) { char *pszUniqueSetting = (char*)CallProtoService(protoname, PS_GETCAPS, PFLAG_UNIQUEIDSETTING, 0); if (pszUniqueSetting){ return (!strcmp(pszUniqueSetting,"e-mail")); } } return FALSE; } DWORD isSeen(HANDLE hcontact, SYSTEMTIME *st){ DWORD res = 0; FILETIME ft; ULONGLONG ll; res = DBGetContactSettingDword(hcontact,S_MOD,"seenTS",0); if (res){ if (st) { ll = UInt32x32To64(CallService(MS_DB_TIME_TIMESTAMPTOLOCAL,res,0), 10000000) + NUM100NANOSEC; ft.dwLowDateTime = (DWORD)ll; ft.dwHighDateTime = (DWORD)(ll >> 32); FileTimeToSystemTime(&ft, st); } return res; } else { SYSTEMTIME lst; ZeroMemory(&lst,sizeof(lst)); if (lst.wYear = DBGetContactSettingWord(hcontact,S_MOD,"Year",0)) { if (lst.wMonth = DBGetContactSettingWord(hcontact,S_MOD,"Month",0)) { if (lst.wDay = DBGetContactSettingWord(hcontact,S_MOD,"Day",0)) { lst.wDayOfWeek = DBGetContactSettingWord(hcontact,S_MOD,"WeekDay",0); lst.wHour = DBGetContactSettingWord(hcontact,S_MOD,"Hours",0); lst.wMinute = DBGetContactSettingWord(hcontact,S_MOD,"Minutes",0); lst.wSecond = DBGetContactSettingWord(hcontact,S_MOD,"Seconds",0); if (SystemTimeToFileTime(&lst,&ft)) { ll = ((LONGLONG)ft.dwHighDateTime<<32)|((LONGLONG)ft.dwLowDateTime); ll -= NUM100NANOSEC; ll /= 10000000; //perform LOCALTOTIMESTAMP res = (DWORD)ll - CallService(MS_DB_TIME_TIMESTAMPTOLOCAL,0,0); //nevel look for Year/Month/Day/Hour/Minute/Second again DBWriteContactSettingDword(hcontact,S_MOD,"seenTS",res); } } } } if (st) CopyMemory (st, &lst, sizeof (SYSTEMTIME)); } return res; } char *ParseString(char *szstring,HANDLE hcontact,BYTE isfile) { #define MAXSIZE 1024 static char sztemp[MAXSIZE+1]; int sztemplen = 0; char szdbsetting[128]=""; char *charPtr; UINT loop=0; int isetting=0; DWORD dwsetting=0; struct in_addr ia; char *weekdays[]={"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"}; char *wdays_short[]={"Sun.","Mon.","Tue.","Wed.","Thu.","Fri.","Sat."}; char *monthnames[]={"January","February","March","April","May","June","July","August","September","October","November","December"}; char *mnames_short[]={"Jan.","Feb.","Mar.","Apr.","May","Jun.","Jul.","Aug.","Sep.","Oct.","Nov.","Dec."}; CONTACTINFO ci; BOOL wantempty; SYSTEMTIME st; sztemp[0] = '\0'; if (!isSeen(hcontact,&st)) { strcat(sztemp,Translate("")); return sztemp; } ci.cbSize=sizeof(CONTACTINFO); ci.hContact=hcontact; ci.szProto=hcontact?(char *)CallService(MS_PROTO_GETCONTACTBASEPROTO,(WPARAM)hcontact,0):courProtoName; for (;loop"); goto LBL_charPtr; } charPtr = Translate(weekdays[isetting]); LBL_charPtr: sztemplen += mir_snprintf(sztemp+sztemplen,MAXSIZE-sztemplen,"%s",charPtr); break; case 'w': isetting=st.wDayOfWeek; if(isetting==-1)goto LBL_noData; charPtr = Translate(wdays_short[isetting]); goto LBL_charPtr; case 'E': if (!(isetting=st.wMonth))goto LBL_noData; charPtr = Translate(monthnames[isetting-1]); goto LBL_charPtr; case 'e': if (!(isetting=st.wMonth))goto LBL_noData; charPtr = Translate(mnames_short[isetting-1]); goto LBL_charPtr; case 'H': if ((isetting=st.wHour)==-1)goto LBL_noData; goto LBL_2DigNum; case 'h': if ((isetting=st.wHour)==-1)goto LBL_noData; if (!isetting) isetting=12; isetting = isetting-((isetting>12)?12:0); goto LBL_2DigNum; case 'p': if ((isetting=st.wHour)==-1)goto LBL_noData; charPtr = (isetting>=12)?"PM":"AM"; goto LBL_charPtr; case 'M': if ((isetting=st.wMinute)==-1)goto LBL_noData; goto LBL_2DigNum; case 'S': if ((isetting=st.wHour)==-1)goto LBL_noData; goto LBL_2DigNum; case 'n': charPtr = hcontact?(char *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME,(WPARAM)hcontact,0):(wantempty?"":"---"); goto LBL_charPtr; case 'N': ci.dwFlag=CNF_NICK; if (!CallService(MS_CONTACT_GETCONTACTINFO,(WPARAM)0,(LPARAM)&ci)) { charPtr = ci.pszVal; } else goto LBL_noData; goto LBL_charPtr; case 'G': { DBVARIANT dbv; if (!DBGetContactSetting(hcontact,"CList","Group",&dbv)) { strcpy(szdbsetting,dbv.pszVal); DBFreeVariant(&dbv); charPtr = szdbsetting; goto LBL_charPtr; } else; //do nothing } break; case 'u': ci.dwFlag=CNF_UNIQUEID; if (!CallService(MS_CONTACT_GETCONTACTINFO,(WPARAM)0,(LPARAM)&ci)) { switch(ci.type) { case CNFT_BYTE: _ltot(ci.bVal, szdbsetting, 10); break; case CNFT_WORD: _ltot(ci.wVal, szdbsetting, 10); break; case CNFT_DWORD: _ltot(ci.dVal, szdbsetting, 10); break; case CNFT_ASCIIZ: strcpy(szdbsetting, ci.pszVal); break; } } else if (ci.szProto != NULL) { if (isYahoo(ci.szProto)) // YAHOO support { DBVARIANT dbv; DBGetContactSetting(hcontact,ci.szProto,"id",&dbv); strcpy(szdbsetting,dbv.pszVal); DBFreeVariant(&dbv); } else if (isJabber(ci.szProto)) // JABBER support { DBVARIANT dbv; if (DBGetContactSetting(hcontact,ci.szProto,"LoginName",&dbv)) goto LBL_noData; strcpy(szdbsetting,dbv.pszVal); DBFreeVariant(&dbv); DBGetContactSetting(hcontact,ci.szProto,"LoginServer",&dbv); strcat(szdbsetting,"@"); strcat(szdbsetting,dbv.pszVal); DBFreeVariant(&dbv); } else goto LBL_noData; } else goto LBL_noData; charPtr = szdbsetting; goto LBL_charPtr; case 's': if (isetting=DBGetContactSettingWord(hcontact,S_MOD,hcontact?"StatusTriger":courProtoName,0)) { strcpy(szdbsetting,Translate((const char *)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION,(WPARAM)(isetting|0x8000),0))); if (!(isetting&0x8000)) { strcat(szdbsetting,"/"); strcat(szdbsetting,Translate("Idle")); } charPtr = szdbsetting; } else goto LBL_noData; goto LBL_charPtr; case 'T': { DBVARIANT dbv; if (!DBGetContactSetting(hcontact,"CList","StatusMsg",&dbv)) { sztemplen += mir_snprintf(sztemp+sztemplen,MAXSIZE-sztemplen,"%s",dbv.pszVal); DBFreeVariant(&dbv); } else goto LBL_noData; } break; case 'o': if (isetting=DBGetContactSettingWord(hcontact,S_MOD,hcontact?"OldStatus":courProtoName,0)) { strcpy(szdbsetting,Translate((const char *)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION,(WPARAM)isetting,0))); if (includeIdle) if (hcontact) if (DBGetContactSettingByte(hcontact,S_MOD,"OldIdle",0)) { strcat(szdbsetting,"/"); strcat(szdbsetting,Translate("Idle")); } charPtr = szdbsetting; } else goto LBL_noData; goto LBL_charPtr; case 'i': case 'r': if (isJabber(ci.szProto)) { DBVARIANT dbv; if (!DBGetContactSetting(hcontact,ci.szProto,szstring[loop]=='i'?"Resource":"System",&dbv)) { strcpy(szdbsetting,dbv.pszVal); DBFreeVariant(&dbv); charPtr = szdbsetting; } else goto LBL_noData; } else { dwsetting=DBGetContactSettingDword(hcontact,ci.szProto,szstring[loop]=='i'?"IP":"RealIP",0); if(dwsetting){ ia.S_un.S_addr=htonl(dwsetting); charPtr = inet_ntoa(ia); } else goto LBL_noData; } goto LBL_charPtr; case 'P':if (ci.szProto) charPtr = ci.szProto; else charPtr = wantempty?"":"ProtoUnknown"; goto LBL_charPtr; case 'b': charPtr = /*"\n"*/"\x0D\x0A"; goto LBL_charPtr; case 'C': // Get Client Info if (isMSN(ci.szProto)) { if (hcontact) { dwsetting = (int)DBGetContactSettingDword(hcontact,ci.szProto,"FlagBits",0); wsprintf(szdbsetting,"MSNC%i",(dwsetting&0x70000000)>>28); if (dwsetting & 0x00000001) strcat(szdbsetting," MobD"); //Mobile Device if (dwsetting & 0x00000004) strcat(szdbsetting," InkG"); //GIF Ink Send/Receive if (dwsetting & 0x00000008) strcat(szdbsetting," InkI"); //ISF Ink Send/Receive if (dwsetting & 0x00000010) strcat(szdbsetting," WCam"); //Webcam if (dwsetting & 0x00000020) strcat(szdbsetting," MPkt"); //Multi packet messages if (dwsetting & 0x00000040) strcat(szdbsetting," SMSr"); //Paging if (dwsetting & 0x00000080) strcat(szdbsetting," DSMS"); //Using MSN Direct if (dwsetting & 0x00000200) strcat(szdbsetting," WebM"); //WebMessenger if (dwsetting & 0x00001000) strcat(szdbsetting," MS7+"); //Unknown (Msgr 7 always[?] sets it) if (dwsetting & 0x00004000) strcat(szdbsetting," DirM"); //DirectIM if (dwsetting & 0x00008000) strcat(szdbsetting," Wink"); //Send/Receive Winks if (dwsetting & 0x00010000) strcat(szdbsetting," MSrc"); //MSN Search ?? if (dwsetting & 0x00040000) strcat(szdbsetting," VoiC"); //Voice Clips } else strcpy(szdbsetting,"Miranda"); } else { DBVARIANT dbv; if (!DBGetContactSetting(hcontact,ci.szProto,"MirVer",&dbv)) { strcpy(szdbsetting,dbv.pszVal); DBFreeVariant(&dbv); } else goto LBL_noData; } charPtr = szdbsetting; goto LBL_charPtr; case 't': charPtr = "\t"; goto LBL_charPtr; default: strncpy(szdbsetting,szstring+loop-1,2); goto LBL_charPtr; } } } return sztemp; } void _DBWriteTime(SYSTEMTIME *st,HANDLE hcontact) { DBWriteContactSettingWord((HANDLE)hcontact,S_MOD,"Day",st->wDay); DBWriteContactSettingWord((HANDLE)hcontact,S_MOD,"Month",st->wMonth); DBWriteContactSettingWord((HANDLE)hcontact,S_MOD,"Year",st->wYear); DBWriteContactSettingWord((HANDLE)hcontact,S_MOD,"Hours",st->wHour); DBWriteContactSettingWord((HANDLE)hcontact,S_MOD,"Minutes",st->wMinute); DBWriteContactSettingWord((HANDLE)hcontact,S_MOD,"Seconds",st->wSecond); DBWriteContactSettingWord((HANDLE)hcontact,S_MOD,"WeekDay",st->wDayOfWeek); } void DBWriteTimeTS(DWORD t, HANDLE hcontact){ SYSTEMTIME st; FILETIME ft; ULONGLONG ll = UInt32x32To64(CallService(MS_DB_TIME_TIMESTAMPTOLOCAL,t,0), 10000000) + NUM100NANOSEC; ft.dwLowDateTime = (DWORD)ll; ft.dwHighDateTime = (DWORD)(ll >> 32); FileTimeToSystemTime(&ft, &st); DBWriteContactSettingDword(hcontact,S_MOD,"seenTS",t); _DBWriteTime(&st, hcontact); } void GetColorsFromDWord(LPCOLORREF First, LPCOLORREF Second, DWORD colDword){ WORD temp; COLORREF res=0; temp = (WORD)(colDword>>16); res |= ((temp & 0x1F) <<3); res |= ((temp & 0x3E0) <<6); res |= ((temp & 0x7C00) <<9); if (First) *First = res; res = 0; temp = (WORD)colDword; res |= ((temp & 0x1F) <<3); res |= ((temp & 0x3E0) <<6); res |= ((temp & 0x7C00) <<9); if (Second) *Second = res; } DWORD StatusColors15bits[] = { 0x63180000, // 0x00C0C0C0, 0x00000000, Offline - LightGray 0x7B350000, // 0x00F0C8A8, 0x00000000, Online - LightBlue 0x33fe0000, // 0x0070E0E0, 0x00000000, Away -LightOrange 0x295C0000, // 0x005050E0, 0x00000000, DND -DarkRed 0x5EFD0000, // 0x00B8B8E8, 0x00000000, NA -LightRed 0x295C0000, // 0x005050E0, 0x00000000, Occupied 0x43900000, // 0x0080E080, 0x00000000, Free for chat - LightGreen 0x76AF0000, // 0x00E8A878, 0x00000000, Invisible 0x431C0000, // 0x0080C0E0, 0x00000000, On the phone 0x5EFD0000, // 0x00B8B8E8, 0x00000000, Out to lunch }; DWORD GetDWordFromColors(COLORREF First, COLORREF Second){ DWORD res = 0; res |= (First&0xF8)>>3; res |= (First&0xF800)>>6; res |= (First&0xF80000)>>9; res <<= 16; res |= (Second&0xF8)>>3; res |= (Second&0xF800)>>6; res |= (Second&0xF80000)>>9; return res; } LRESULT CALLBACK PopupDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { switch(message) { case WM_COMMAND: if (HIWORD(wParam) == STN_CLICKED){ HANDLE hContact = PUGetContact(hwnd); if (hContact > 0) CallService(MS_MSG_SENDMESSAGE,(WPARAM)hContact,0); } case WM_CONTEXTMENU: PUDeletePopUp(hwnd); break; case UM_INITPOPUP: return 0; } return DefWindowProc(hwnd, message, wParam, lParam); }; void ShowPopup(HANDLE hcontact, const char * lpzProto, int newStatus){ if(CallService(MS_IGNORE_ISIGNORED,(WPARAM)hcontact,IGNOREEVENT_USERONLINE)) return; if (ServiceExists(MS_POPUP_QUERY)) { if (DBGetContactSettingByte(NULL,S_MOD,"UsePopups",0)) { if (!DBGetContactSettingByte(hcontact,"CList","Hidden",0)) { POPUPDATAEX ppd = {0}; DBVARIANT dbv = {0}; char szstamp[10]; DWORD sett; sprintf(szstamp, "Col_%d",newStatus-ID_STATUS_OFFLINE); sett = DBGetContactSettingDword(NULL,S_MOD,szstamp,StatusColors15bits[newStatus-ID_STATUS_OFFLINE]); GetColorsFromDWord(&ppd.colorBack,&ppd.colorText,sett); ppd.lchContact = hcontact; ppd.lchIcon = LoadSkinnedProtoIcon(lpzProto, newStatus); strncpy(ppd.lpzContactName,ParseString(!DBGetContactSetting(NULL,S_MOD,"PopupStamp",&dbv)?dbv.pszVal:DEFAULT_POPUPSTAMP,hcontact,0),MAX_CONTACTNAME); DBFreeVariant(&dbv); strncpy(ppd.lpzText,ParseString(!DBGetContactSetting(NULL,S_MOD,"PopupStampText",&dbv)?dbv.pszVal:DEFAULT_POPUPSTAMPTEXT,hcontact,0),MAX_SECONDLINE); DBFreeVariant(&dbv); ppd.PluginWindowProc = (WNDPROC)PopupDlgProc; CallService(MS_POPUP_ADDPOPUPEX, (WPARAM)&ppd, 0); } } } } void myPlaySound(HANDLE hcontact, WORD newStatus, WORD oldStatus){ if(CallService(MS_IGNORE_ISIGNORED,(WPARAM)hcontact,IGNOREEVENT_USERONLINE)) return; //oldStatus and hcontact are not used yet if (DBGetContactSettingByte(NULL,"Skin","UseSound",1)) { char * soundname=0; if ((newStatus==ID_STATUS_ONLINE) || (newStatus==ID_STATUS_FREECHAT)) soundname = "LastSeenTrackedStatusOnline"; else if (newStatus==ID_STATUS_OFFLINE) soundname = "LastSeenTrackedStatusOffline"; else if (oldStatus==ID_STATUS_OFFLINE) soundname = "LastSeenTrackedStatusFromOffline"; else soundname = "LastSeenTrackedStatusChange"; if (!DBGetContactSettingByte(NULL,"SkinSoundsOff",soundname,0)) { DBVARIANT dbv; if (!DBGetContactSetting(NULL,"SkinSounds",soundname,&dbv)) { PlaySoundA(dbv.pszVal, NULL, SND_ASYNC | SND_FILENAME | SND_NOWAIT); DBFreeVariant(&dbv); } } } } //will give hContact position or zero int isContactQueueActive(HANDLE hContact){ int i = 0; if (!hContact) { // MessageBox(0,"Is myself in the queue: never","LastSeen-Mod",0); return 0; } for (i=1;ihContact==hContact) return i; } return 0; } //will add hContact to queue and will return position; int addContactToQueue(HANDLE hContact){ int i = 0; if (!hContact) { // MessageBox(0,"Adding myself to queue","LastSeen-Mod",0); return 0; } for (i=1;iqueueIndex = i; contactQueue[i]->hContact = hContact; return i; } } //no free space. Create some //MessageBox(0,"Creating more space","LastSeen-Mod",0); contactQueue = (logthread_info **)realloc(contactQueue,(contactQueueSize+16)*sizeof(logthread_info *)); memset(&contactQueue[contactQueueSize],0, 16*sizeof(logthread_info *)); i = contactQueueSize; contactQueue[i] = (logthread_info *)malloc(sizeof(logthread_info)); contactQueue[i]->queueIndex = i; contactQueue[i]->hContact = hContact; contactQueueSize += 16; return i; } static DWORD __stdcall waitThread(logthread_info* infoParam) { WORD prevStatus = DBGetContactSettingWord(infoParam->hContact,S_MOD,"StatusTriger",ID_STATUS_OFFLINE); Sleep(1500); // I hope in 1.5 second all the needed info will be set if (includeIdle) if (DBGetContactSettingDword(infoParam->hContact,infoParam->sProtoName,"IdleTS",0)) infoParam->courStatus &=0x7FFF; if (infoParam->courStatus != prevStatus){ DBWriteContactSettingWord(infoParam->hContact,S_MOD,"OldStatus",(WORD)(prevStatus|0x8000)); if (includeIdle) DBWriteContactSettingByte(infoParam->hContact,S_MOD,"OldIdle",(BYTE)((prevStatus&0x8000)==0)); DBWriteContactSettingWord(infoParam->hContact,S_MOD,"StatusTriger",infoParam->courStatus); } contactQueue[infoParam->queueIndex] = 0; free(infoParam); return 0; } int UpdateValues(WPARAM wparam,LPARAM lparam) { DBCONTACTWRITESETTING *cws; BOOL isIdleEvent; // to make this code faster if (!wparam) return 0; cws=(DBCONTACTWRITESETTING *)lparam; //if(CallService(MS_IGNORE_ISIGNORED,(WPARAM)hContact,IGNOREEVENT_USERONLINE)) return 0; isIdleEvent = includeIdle?(strcmp(cws->szSetting,"IdleTS")==0):0; if (strcmp(cws->szSetting,"Status") && strcmp(cws->szSetting,"StatusTriger") && (isIdleEvent==0)) return 0; if (!strcmp(cws->szModule,S_MOD)) { //here we will come when Settings/SeenModule/StatusTriger is changed WORD prevStatus=DBGetContactSettingWord((HANDLE)wparam, S_MOD, "OldStatus", ID_STATUS_OFFLINE); if (includeIdle){ if (DBGetContactSettingByte((HANDLE)wparam, S_MOD, "OldIdle", 0)) prevStatus &= 0x7FFF; else prevStatus |= 0x8000; } if ((cws->value.wVal|0x8000)<=ID_STATUS_OFFLINE) { char * proto; // avoid repeating the offline status if ((prevStatus|0x8000)<=ID_STATUS_OFFLINE) return 0; proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, wparam, 0); DBWriteContactSettingByte((HANDLE)wparam, S_MOD, "Offline", 1); { DWORD t; char *str = (char *)malloc(MAXMODULELABELLENGTH+9); mir_snprintf(str,MAXMODULELABELLENGTH+8,"OffTime-%s",proto); t = DBGetContactSettingDword(NULL,S_MOD,str,0); if (!t) t = time(NULL); free(str); DBWriteTimeTS(t, (HANDLE)wparam); } if (!DBGetContactSettingByte(NULL,S_MOD,"IgnoreOffline",1)) { char * sProto; if(DBGetContactSettingByte(NULL,S_MOD,"FileOutput",0)) FileWrite((HANDLE)wparam); if (CallProtoService(sProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, wparam, 0), PS_GETSTATUS,0,0 )>ID_STATUS_OFFLINE) { myPlaySound((HANDLE)wparam, ID_STATUS_OFFLINE, prevStatus); if(DBGetContactSettingByte(NULL, S_MOD, "UsePopups", 0)) { ShowPopup((HANDLE)wparam, sProto, ID_STATUS_OFFLINE); } } if(DBGetContactSettingByte(NULL, S_MOD, "KeepHistory", 0)) HistoryWrite((HANDLE)wparam); if(DBGetContactSettingByte((HANDLE)wparam, S_MOD, "OnlineAlert", 0)) ShowHistory((HANDLE)wparam, 1); } } else { if(cws->value.wVal==prevStatus && !DBGetContactSettingByte((HANDLE)wparam, S_MOD, "Offline", 0)) return 0; DBWriteTimeTS(time(NULL), (HANDLE)wparam); //DBWriteContactSettingWord(hContact,S_MOD,"StatusTriger",(WORD)cws->value.wVal); if(DBGetContactSettingByte(NULL, S_MOD, "FileOutput", 0)) FileWrite((HANDLE)wparam); if (prevStatus != cws->value.wVal) myPlaySound((HANDLE)wparam, cws->value.wVal, prevStatus); if(DBGetContactSettingByte(NULL, S_MOD, "UsePopups", 0)) if (prevStatus != cws->value.wVal) ShowPopup((HANDLE)wparam, (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, wparam, 0), cws->value.wVal|0x8000); if(DBGetContactSettingByte(NULL, S_MOD, "KeepHistory", 0)) HistoryWrite((HANDLE)wparam); if(DBGetContactSettingByte((HANDLE)wparam, S_MOD, "OnlineAlert", 0)) ShowHistory((HANDLE)wparam, 1); DBWriteContactSettingByte((HANDLE)wparam, S_MOD, "Offline", 0); } } else if (IsWatchedProtocol(cws->szModule)) { //here we will come when //Status is changed or it is idle event and if is watched if (CallProtoService(cws->szModule,PS_GETSTATUS,0,0)>ID_STATUS_OFFLINE){ int index; if (!(index = isContactQueueActive((HANDLE)wparam))) { index = addContactToQueue((HANDLE)wparam); strncpy(contactQueue[index]->sProtoName,cws->szModule,MAXMODULELABELLENGTH); unsigned int dwThreadId; mir_forkthreadex((pThreadFuncEx)waitThread, contactQueue[index], &dwThreadId); } contactQueue[index]->courStatus = isIdleEvent ? DBGetContactSettingWord((HANDLE)wparam, cws->szModule, "Status", ID_STATUS_OFFLINE) : cws->value.wVal; } } return 0; } static DWORD __stdcall cleanThread(logthread_info* infoParam) { Sleep(10000); // I hope in 10 secons all logged-in contacts will be listed HANDLE hcontact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST,0,0); while(hcontact != NULL) { char *contactProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO,(WPARAM)hcontact,0); if (contactProto) { if ( !strncmp(infoParam->sProtoName, contactProto, MAXMODULELABELLENGTH)) { WORD oldStatus = DBGetContactSettingWord(hcontact,S_MOD,"StatusTriger",ID_STATUS_OFFLINE) | 0x8000; if (oldStatus > ID_STATUS_OFFLINE) { if (DBGetContactSettingWord(hcontact,contactProto,"Status",ID_STATUS_OFFLINE)==ID_STATUS_OFFLINE){ DBWriteContactSettingWord(hcontact,S_MOD,"OldStatus",(WORD)(oldStatus|0x8000)); if (includeIdle)DBWriteContactSettingByte(hcontact,S_MOD,"OldIdle",(BYTE)((oldStatus&0x8000)?0:1)); DBWriteContactSettingWord(hcontact,S_MOD,"StatusTriger",ID_STATUS_OFFLINE); } } } } hcontact=(HANDLE)CallService(MS_DB_CONTACT_FINDNEXT,(WPARAM)hcontact,0); } char *str = (char *)malloc(MAXMODULELABELLENGTH+9); mir_snprintf(str,MAXMODULELABELLENGTH+8,"OffTime-%s",infoParam->sProtoName); DBDeleteContactSetting(NULL,S_MOD,str); free(str); free(infoParam); return 0; } int ModeChange(WPARAM wparam,LPARAM lparam) { ACKDATA *ack; WORD isetting=0; ack=(ACKDATA *)lparam; if(ack->type!=ACKTYPE_STATUS || ack->result!=ACKRESULT_SUCCESS || ack->hContact!=NULL) return 0; courProtoName = (char *)ack->szModule; if (!IsWatchedProtocol(courProtoName) && strncmp(courProtoName,"MetaContacts",12)) { //MessageBox(NULL,"Protocol not watched",courProtoName,0); return 0; } DBWriteTimeTS(time(NULL),NULL); // isetting=CallProtoService(ack->szModule,PS_GETSTATUS,0,0); isetting=(WORD)ack->lParam; if (isettingID_STATUS_OFFLINE)&&((WORD)ack->hProcess<=ID_STATUS_OFFLINE)) { //we have just loged-in db_dword_set(NULL, "UserOnline", ack->szModule, GetTickCount()); if (IsWatchedProtocol(ack->szModule)) { logthread_info *info; info = (logthread_info *)malloc(sizeof(logthread_info)); strncpy(info->sProtoName,courProtoName,MAXMODULELABELLENGTH); info->hContact = 0; info->courStatus = 0; unsigned int dwThreadId; CloseHandle( mir_forkthreadex((pThreadFuncEx)cleanThread, info, &dwThreadId)); } } else if ((isetting==ID_STATUS_OFFLINE)&&((WORD)ack->hProcess>ID_STATUS_OFFLINE)) { //we have just loged-off if (IsWatchedProtocol(ack->szModule)) { char *str = (char *)malloc(MAXMODULELABELLENGTH+9); time_t t; time(&t); mir_snprintf(str,MAXMODULELABELLENGTH+8,"OffTime-%s",ack->szModule); DBWriteContactSettingDword(NULL,S_MOD,str,t); free(str); } } if (isetting==DBGetContactSettingWord(NULL,S_MOD,courProtoName,ID_STATUS_OFFLINE)) return 0; DBWriteContactSettingWord(NULL,S_MOD,courProtoName,isetting); // log "myself" if(DBGetContactSettingByte(NULL,S_MOD,"FileOutput",0)) FileWrite(NULL); // if(isetting==ID_STATUS_OFFLINE) //this is removed 'cause I want other contacts to be logged only if the status changed while I was offline // SetOffline(); courProtoName = NULL; return 0; } short int isDbZero(HANDLE hContact, const char *module_name, const char *setting_name){ DBVARIANT dbv; if (!DBGetContactSetting(hContact, module_name, setting_name, &dbv)) { short int res = 0; switch (dbv.type) { case DBVT_BYTE: res=dbv.bVal==0; break; case DBVT_WORD: res=dbv.wVal==0; break; case DBVT_DWORD: res=dbv.dVal==0; break; case DBVT_BLOB: res=dbv.cpbVal==0; break; default: res=dbv.pszVal[0]==0; break; } DBFreeVariant(&dbv); return res; } else return -1; } WCHAR *any_to_IdleNotidleUnknown(HANDLE hContact, const char *module_name, const char *setting_name, WCHAR *buff, int bufflen) { short int r = isDbZero(hContact, module_name, setting_name); if (r==-1){ wcsncpy(buff, TranslateW(L"Unknown"), bufflen); } else { wcsncpy(buff, TranslateW(r?L"Not Idle":L"Idle"), bufflen); }; buff[bufflen - 1] = 0; return buff; } WCHAR *any_to_Idle(HANDLE hContact, const char *module_name, const char *setting_name, WCHAR *buff, int bufflen) { if(isDbZero(hContact, module_name, setting_name)==0) { //DB setting is NOT zero and exists buff[0] = L'/'; wcsncpy((WCHAR *)&buff[1], TranslateW(L"Idle"), bufflen-1); } else buff[0] = 0; buff[bufflen - 1] = 0; return buff; } /*int GetInfoAck(WPARAM wparam,LPARAM lparam) { ACKDATA *ack; DWORD dwsetting=0; ack=(ACKDATA *)lparam; if(ack->type!=ACKTYPE_GETINFO || ack->hContact==NULL) return 0; if (((int)ack->hProcess-1)!=(int)ack->lParam) return 0; dwsetting=DBGetContactSettingDword(ack->hContact,ack->szModule,"IP",0); if(dwsetting) DBWriteContactSettingDword(ack->hContact,S_MOD,"IP",dwsetting); dwsetting=DBGetContactSettingDword(ack->hContact,ack->szModule,"RealIP",0); if(dwsetting) DBWriteContactSettingDword(ack->hContact,S_MOD,"RealIP",dwsetting); return 0; }*/ /*void SetOffline(void) { HANDLE hcontact=NULL; char * szProto; hcontact=(HANDLE)CallService(MS_DB_CONTACT_FINDFIRST,0,0); while(hcontact!=NULL) { szProto=(char *)CallService(MS_PROTO_GETCONTACTBASEPROTO,(WPARAM)hcontact,0); if (szProto != NULL && IsWatchedProtocol(szProto)) { DBWriteContactSettingByte(hcontact,S_MOD,"Offline",1); } hcontact=(HANDLE)CallService(MS_DB_CONTACT_FINDNEXT,(WPARAM)hcontact,0); } }*/