/* Miranda SmileyAdd Plugin Copyright (C) 2005 - 2011 Boris Krasnovskiy All Rights Reserved Copyright (C) 2003 - 2004 Rein-Peter de Boer 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 version 2 of the License. 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, see . */ #include "smileys.h" #include "smileyroutines.h" #include "options.h" #include "download.h" SmileyPackListType g_SmileyPacks; SmileyCategoryListType g_SmileyCategories; extern HANDLE hNetlibUser; // // SmileyType // SmileyType::SmileyType(void) { m_SmileyIcon = NULL; m_xepimg = NULL; m_flags = 0; m_index = 0; m_size.cx = 0; m_size.cy = 0; } SmileyType::~SmileyType() { if (m_xepimg) m_xepimg->Release(); m_xepimg = NULL; if (m_SmileyIcon != NULL) DestroyIcon(m_SmileyIcon); m_SmileyIcon = NULL; } HICON SmileyType::GetIcon(void) { if (m_SmileyIcon == NULL) { ImageBase* img = CreateCachedImage(); if (!img) return NULL; img->SelectFrame(m_index); m_SmileyIcon = img->GetIcon(); img->Release(); } return m_SmileyIcon; } HICON SmileyType::GetIconDup(void) { ImageBase* img = CreateCachedImage(); img->SelectFrame(m_index); HICON hIcon = img->GetIcon(); img->Release(); return hIcon; } bool SmileyType::LoadFromImage(IStream* pStream) { if (m_xepimg) m_xepimg->Release(); bkstring name; m_xepimg = new ImageType(0, name, pStream); return true; } bool SmileyType::LoadFromResource(const bkstring& file, const int index) { m_index = index; m_filepath = file; return true; } void SmileyType::GetSize(SIZE& size) { if (m_size.cy == 0) { ImageBase* img = CreateCachedImage(); if (img) { img->GetSize(m_size); img->Release(); } } size = m_size; } ImageBase* SmileyType::CreateCachedImage(void) { if (m_xepimg) { m_xepimg->AddRef(); return m_xepimg; } return AddCacheImage(m_filepath, m_index); } void SmileyType::SetImList(HIMAGELIST hImLst, long i) { if (m_xepimg) m_xepimg->Release(); m_xepimg = new ImageListItemType(0, hImLst, i); } HBITMAP SmileyType::GetBitmap(COLORREF bkgClr, int sizeX, int sizeY) { ImageBase* img = CreateCachedImage(); if (!img) return NULL; img->SelectFrame(m_index); HBITMAP hBmp = img->GetBitmap(bkgClr, sizeX, sizeY); img->Release(); return hBmp; } // // SmileyPackType // SmileyPackType::SmileyPackType() { m_hSmList = NULL; errorFound = false; } SmileyType* SmileyPackType::GetSmiley(unsigned index) { return (index < (unsigned)m_SmileyList.getCount()) ? &m_SmileyList[index] : NULL; } static DWORD_PTR ConvertServiceParam(HANDLE hContact, const TCHAR *param) { DWORD_PTR ret; if (param == NULL) ret = 0; else if (_tcsicmp(_T("hContact"), param) == 0) ret = (DWORD_PTR)hContact; else if (_istdigit(*param)) ret = _ttoi(param); else ret = (DWORD_PTR)param; return ret; } void SmileyType::CallSmileyService(HANDLE hContact) { _TPattern * srvsplit = _TPattern::compile(_T("(.*)\\|(.*)\\|(.*)")); _TMatcher * m0 = srvsplit->createTMatcher(GetTriggerText()); m0->findFirstMatch(); bkstring name = m0->getGroup(1); bkstring par1 = m0->getGroup(2); bkstring par2 = m0->getGroup(3); delete m0; delete srvsplit; char str[MAXMODULELABELLENGTH]; const char *proto = ""; if (name[0] == '/') { proto = (const char*) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); if (proto == NULL) return; } mir_snprintf(str, sizeof(str), "%s%s", proto, T2A_SM(name.c_str())); CallService(str, ConvertServiceParam(hContact, par1.c_str()), ConvertServiceParam(hContact, par2.c_str())); } SmileyPackType::~SmileyPackType() { if (m_hSmList != NULL) ImageList_Destroy(m_hSmList); } static const TCHAR urlRegEx[] = _T("(?:ftp|https|http|file|aim|webcal|irc|msnim|xmpp|gopher|mailto|news|nntp|telnet|wais|prospero)://?[\\w.?%:/$+;]*"); static const TCHAR pathRegEx[] = _T("[\\s\"][a-zA-Z]:[\\\\/][\\w.\\-\\\\/]*"); static const TCHAR timeRegEx[] = _T("\\d{1,2}:\\d{2}:\\d{2}|\\d{1,2}:\\d{2}"); void SmileyPackType::AddTriggersToSmileyLookup(void) { _TPattern * p = _TPattern::compile(_T("\\s+")); { bkstring emptystr; m_SmileyLookup.insert(new SmileyLookup(urlRegEx, true, -1, emptystr)); m_SmileyLookup.insert(new SmileyLookup(pathRegEx, true, -1, emptystr)); m_SmileyLookup.insert(new SmileyLookup(timeRegEx, true, -1, emptystr)); } for (int dist = 0; dist < m_SmileyList.getCount(); dist++) { if (m_SmileyList[dist].IsRegEx()) { SmileyLookup* dats = new SmileyLookup(m_SmileyList[dist].GetTriggerText(), true, dist, GetFilename()); if (dats->IsValid()) m_SmileyLookup.insert(dats); else errorFound = true; if (m_SmileyList[dist].m_InsertText.empty()) m_SmileyList[dist].m_InsertText = m_SmileyList[dist].m_ToolText; } else if (!m_SmileyList[dist].IsService()) { bool first = true; int li = 0; _TMatcher * m0 = p->createTMatcher(m_SmileyList[dist].GetTriggerText()); while (m0->findNextMatch()) { int stind = m0->getStartingIndex(); if (li != stind) { bkstring out; ReplaceAllSpecials(m0->getString().substr(li, stind - li), out); SmileyLookup *dats = new SmileyLookup(out, false, dist, GetFilename()); if (dats->IsValid()) { m_SmileyLookup.insert(dats); if (first) { m_SmileyList[dist].m_InsertText = out; first = false; } } } li = m0->getEndingIndex(); } int stind = (int)m0->getString().size(); if (li < stind) { bkstring out; ReplaceAllSpecials(m0->getString().substr(li, stind - li), out); SmileyLookup *dats = new SmileyLookup(out, false, dist, GetFilename()); if (dats->IsValid()) { m_SmileyLookup.insert(dats); if (first) { m_SmileyList[dist].m_InsertText = out; first = false; } } } delete m0; } } delete p; } void SmileyPackType::ReplaceAllSpecials(const bkstring& Input, bkstring& Output) { Output = _TPattern::replace(_T("%%_{1,2}%%"), Input, _T(" ")); Output = _TPattern::replace(_T("%%''%%"), Output, _T("\"")); } void SmileyPackType::Clear(void) { m_SmileyList.destroy(); m_SmileyLookup.destroy(); if (m_hSmList != NULL) { ImageList_Destroy(m_hSmList); m_hSmList = NULL; } m_Filename.clear(); m_Name.clear(); m_Date.clear(); m_Version.clear(); m_Author.clear(); m_VisibleCount = 0; m_ButtonSmiley.clear(); errorFound = false; } bool SmileyPackType::LoadSmileyFile(const bkstring& filename, bool onlyInfo, bool noerr) { Clear(); if (filename.empty()) { m_Name = _T("Nothing loaded"); return false; } bkstring modpath; pathToAbsolute(filename, modpath); // Load xep file int fh = _topen(modpath.c_str(), _O_BINARY | _O_RDONLY); if (fh == -1) { if (!noerr) { static const TCHAR errmsg[] = _T("Smiley Pack %s not found.\n") _T("Select correct Smiley Pack in the Miranda Options | Customize | Smileys."); TCHAR msgtxt[1024]; mir_sntprintf(msgtxt, SIZEOF(msgtxt), TranslateTS(errmsg), modpath.c_str()); ReportError(msgtxt); } m_Name = _T("Nothing loaded"); return false; } m_Filename = filename; // Find file size const long flen = _filelength(fh); // Allocate file buffer char* buf = new char[flen + sizeof(wchar_t)]; // Read xep file in int len = _read(fh, buf, flen); *(wchar_t*)(buf+len) = 0; // Close file _close(fh); bkstring tbuf; if (len>2 && *(wchar_t*)buf == 0xfeff) { tbuf = W2T_SM((wchar_t*)buf+1); } else if (len>3 && buf[0]=='\xef' && buf[1]=='\xbb' && buf[2]=='\xbf') { tbuf = W2T_SM(A2W_SM(buf+3, CP_UTF8)); } else { tbuf = A2T_SM(buf); } delete[] buf; bool res; if (filename.find(_T(".xep")) == filename.npos) res = LoadSmileyFileMSL(tbuf, onlyInfo, modpath); else res = LoadSmileyFileXEP(tbuf, onlyInfo, modpath); if (errorFound) ReportError(TranslateT("There were problems loading smiley pack (it should be corrected).\nSee Network Log for details.")); return res; } bool SmileyPackType::LoadSmileyFileMSL(bkstring& tbuf, bool onlyInfo, bkstring& modpath) { _TPattern * pathsplit = _TPattern::compile(_T("(.*\\\\)(.*)\\.|$")); _TMatcher * m0 = pathsplit->createTMatcher(modpath); m0->findFirstMatch(); const bkstring pathstr = m0->getGroup(1); const bkstring packstr = m0->getGroup(2); delete m0; delete pathsplit; _TPattern * otherf = _TPattern::compile( _T("^\\s*(Name|Author|Date|Version|ButtonSmiley)\\s*=\\s*\"(.*)\""), _TPattern::MULTILINE_MATCHING); m0 = otherf->createTMatcher(tbuf); while (m0->findNextMatch()) { if (m0->getGroup(1) == _T("Name")) m_Name = m0->getGroup(2); if (m0->getGroup(1) == _T("Author")) m_Author = m0->getGroup(2); if (m0->getGroup(1) == _T("Date")) m_Date = m0->getGroup(2); if (m0->getGroup(1) == _T("Version")) m_Version = m0->getGroup(2); if (m0->getGroup(1) == _T("ButtonSmiley")) m_ButtonSmiley = m0->getGroup(2); } delete m0; delete otherf; if (!onlyInfo) { selec.x = 0; selec.y = 0; win.x = 0; win.y = 0; { _TPattern * pat = _TPattern::compile( _T("^\\s*(Selection|Window)Size\\s*=\\s*(\\d+)\\s*,\\s*(\\d+)"), _TPattern::MULTILINE_MATCHING); _TMatcher * m0 = pat->createTMatcher(tbuf); while (m0->findNextMatch()) { POINT tpt; tpt.x = _ttol(m0->getGroup(2).c_str()); tpt.y = _ttol(m0->getGroup(3).c_str()); if (m0->getGroup(1) == _T("Selection")) selec = tpt; else if (m0->getGroup(1) == _T("Window")) win = tpt; } delete m0; delete pat; } _TPattern * smiley = _TPattern::compile( _T("^\\s*Smiley(\\*)?\\s*=") // Is Hidden _T("(?:\\s*\"(.*)\")") // Smiley file name _T("(?:[\\s,]+(\\-?\\d+))") // Icon resource id _T("(?:[\\s,]+(R|S)?\"(.*?)\")") // Trigger text _T("(?:[\\s,]+\"(.*?)\")?") // Tooltip or insert text _T("(?:[\\s,]+\"(.*?)\")?"), // Tooltip text _TPattern::MULTILINE_MATCHING); _TMatcher * m0 = smiley->createTMatcher(tbuf); SmileyVectorType hiddenSmileys; unsigned smnum = 0; while (m0->findNextMatch()) { bkstring resname = m0->getGroup(2); if (resname.find(_T("http://")) != resname.npos) { if (GetSmileyFile(resname, packstr)) continue; } else { if (!resname.empty()) resname.insert(0, pathstr); } SmileyType *dat = new SmileyType; const int iconIndex = _ttol(m0->getGroup(3).c_str()); dat->SetHidden(m0->getStartingIndex(1) >= 0); if (m0->getStartingIndex(4) >= 0) { dat->SetRegEx(m0->getGroup(4) == _T("R")); dat->SetService(m0->getGroup(4) == _T("S")); } dat->m_TriggerText = m0->getGroup(5); if (dat->IsRegEx()) { if (m0->getStartingIndex(6) >= 0) ReplaceAllSpecials(m0->getGroup(6), dat->m_InsertText); if (m0->getStartingIndex(7) >= 0) ReplaceAllSpecials(m0->getGroup(7), dat->m_ToolText); else dat->m_ToolText = dat->m_InsertText; } else { if (m0->getStartingIndex(6) >= 0) ReplaceAllSpecials(m0->getGroup(6), dat->m_ToolText); else ReplaceAllSpecials(dat->m_TriggerText, dat->m_ToolText); } bool noerr; if (resname.empty()) { dat->SetHidden(true); dat->SetText(true); noerr = true; } else noerr = dat->LoadFromResource(resname, iconIndex); if (dat->IsHidden()) hiddenSmileys.insert(dat); else m_SmileyList.insert(dat); if (!noerr) { static const TCHAR errmsg[] = _T("Smiley #%u in file %s for Smiley Pack %s not found."); TCHAR msgtxt[1024]; mir_sntprintf(msgtxt, SIZEOF(msgtxt), TranslateTS(errmsg), smnum, resname.c_str(), modpath.c_str()); CallService(MS_NETLIB_LOG,(WPARAM) hNetlibUser, (LPARAM)(char*)T2A_SM(msgtxt)); errorFound = true; } smnum++; } delete m0; delete smiley; m_VisibleCount = m_SmileyList.getCount(); m_SmileyList.splice(hiddenSmileys); AddTriggersToSmileyLookup(); } return true; } static void DecodeHTML(bkstring& str) { if (str.find('&') != str.npos) { str = _TPattern::replace(bkstring(_T("<")), str, bkstring(_T("<"))); str = _TPattern::replace(bkstring(_T(">")), str, bkstring(_T(">"))); } } static IStream* DecodeBase64Data(const char* data) { NETLIBBASE64 nlb64; nlb64.pszEncoded = (char*)data; nlb64.cchEncoded = (int)strlen(data); nlb64.cbDecoded = Netlib_GetBase64DecodedBufferSize(nlb64.cchEncoded); IStream* pStream = NULL; // Read image list HGLOBAL hBuffer = GlobalAlloc(GMEM_MOVEABLE, nlb64.cbDecoded); if (hBuffer) { nlb64.pbDecoded = (PBYTE)GlobalLock(hBuffer); CallService(MS_NETLIB_BASE64DECODE, 0, (LPARAM)&nlb64); GlobalUnlock(hBuffer); CreateStreamOnHGlobal(hBuffer, TRUE, &pStream); } return pStream; } bool SmileyPackType::LoadSmileyFileXEP(bkstring& tbuf, bool onlyInfo, bkstring& ) { _TMatcher *m0, *m1, *m2; _TPattern * dbname_re = _TPattern::compile(_T("\\s*\"(.*?)\"\\s*"), _TPattern::MULTILINE_MATCHING); _TPattern * author_re = _TPattern::compile(_T("\\s*\"(.*?)\"\\s*"), _TPattern::MULTILINE_MATCHING); _TPattern * settings_re = _TPattern::compile(_T("(.*?)"), _TPattern::MULTILINE_MATCHING | _TPattern::DOT_MATCHES_ALL); m0 = settings_re->createTMatcher(tbuf); if (m0->findFirstMatch()) { bkstring settings = m0->getGroup(1); m1 = author_re->createTMatcher(settings); if (m1->findFirstMatch()) { m_Author = m1->getGroup(1); DecodeHTML(m_Author); } delete m1; m1 = dbname_re->createTMatcher(settings); if (m1->findFirstMatch()) { m_Name = m1->getGroup(1); DecodeHTML(m_Name); } delete m1; } delete m0; delete dbname_re; delete author_re; delete settings_re; if (!onlyInfo) { _TPattern * record_re = _TPattern::compile(_T("(?:\\s*\"(.*?)\")?(.*?)"), _TPattern::MULTILINE_MATCHING | _TPattern::DOT_MATCHES_ALL); _TPattern * expression_re = _TPattern::compile(_T("\\s*\"(.*?)\"\\s*"), _TPattern::MULTILINE_MATCHING); _TPattern * pastetext_re = _TPattern::compile(_T("\\s*\"(.*?)\"\\s*"), _TPattern::MULTILINE_MATCHING); _TPattern * images_re = _TPattern::compile(_T("(.*?)"), _TPattern::MULTILINE_MATCHING | _TPattern::DOT_MATCHES_ALL); _TPattern * image_re = _TPattern::compile(_T("(.*?)"), _TPattern::MULTILINE_MATCHING | _TPattern::DOT_MATCHES_ALL); _TPattern * imagedt_re = _TPattern::compile(_T(""), _TPattern::MULTILINE_MATCHING ); m0 = images_re->createTMatcher(tbuf); if (m0->findFirstMatch()) { bkstring images = m0->getGroup(1); m1 = imagedt_re->createTMatcher(images); if (m1->findFirstMatch()) { IStream* pStream = DecodeBase64Data(T2A_SM(m1->getGroup(1).c_str())); if (pStream != NULL) { if (m_hSmList != NULL) ImageList_Destroy(m_hSmList); m_hSmList = ImageList_Read(pStream); pStream->Release(); } } delete m1; } delete m0; m0 = record_re->createTMatcher(tbuf); while (m0->findNextMatch()) { SmileyType *dat = new SmileyType; dat->SetRegEx(true); dat->SetImList(m_hSmList, _ttol(m0->getGroup(1).c_str())); dat->m_ToolText = m0->getGroup(2); DecodeHTML(dat->m_ToolText); bkstring rec = m0->getGroup(3); m1 = expression_re->createTMatcher(rec); if (m1->findFirstMatch()) { dat->m_TriggerText = m1->getGroup(1); DecodeHTML(dat->m_TriggerText); } delete m1; m1 = pastetext_re->createTMatcher(rec); if (m1->findFirstMatch()) { dat->m_InsertText = m1->getGroup(1); DecodeHTML(dat->m_InsertText); } delete m1; dat->SetHidden(dat->m_InsertText.empty()); m1 = image_re->createTMatcher(rec); if (m1->findFirstMatch()) { bkstring images = m1->getGroup(1); m2 = imagedt_re->createTMatcher(images); if (m2->findFirstMatch()) { IStream* pStream = DecodeBase64Data(T2A_SM(m2->getGroup(1).c_str())); if (pStream != NULL) { dat->LoadFromImage(pStream); pStream->Release(); } } delete m2; } delete m1; m_SmileyList.insert(dat); } delete m0; delete record_re; delete expression_re; delete pastetext_re; delete images_re; delete image_re; delete imagedt_re; } m_VisibleCount = m_SmileyList.getCount(); AddTriggersToSmileyLookup(); selec.x = 0; selec.y = 0; win.x = 0; win.y = 0; return true; } // // SmileyPackListType // bool SmileyPackListType::AddSmileyPack(bkstring& filename) { bool res = true; if (GetSmileyPack(filename) == NULL) { //not exist yet, so add SmileyPackType *smileyPack = new SmileyPackType; res = smileyPack->LoadSmileyFile(filename, FALSE); if (res) m_SmileyPacks.insert(smileyPack); else delete smileyPack; } return res; } SmileyPackType* SmileyPackListType::GetSmileyPack(bkstring& filename) { bkstring modpath; pathToAbsolute(filename, modpath); for (int i = 0; i < m_SmileyPacks.getCount(); i++) { bkstring modpath1; pathToAbsolute(m_SmileyPacks[i].GetFilename(), modpath1); if (lstrcmpi(modpath.c_str(), modpath1.c_str()) == 0) return &m_SmileyPacks[i]; } return NULL; } void SmileyPackListType::ClearAndFreeAll() { m_SmileyPacks.destroy(); } // // SmileyCategoryType // SmileyCategoryType::SmileyCategoryType(SmileyPackListType* pSPS, const bkstring& name, const bkstring& displayName, const bkstring& defaultFilename, SmcType typ) { m_pSmileyPackStore = pSPS; type = typ; m_Name = name; m_DisplayName = displayName; opt.ReadPackFileName(m_Filename, m_Name, defaultFilename); } void SmileyCategoryType::Load(void) { if (!opt.UseOneForAll || type != smcProto) m_pSmileyPackStore->AddSmileyPack(m_Filename); } SmileyPackType* SmileyCategoryType::GetSmileyPack(void) { return m_pSmileyPackStore->GetSmileyPack(m_Filename); } void SmileyCategoryType::SaveSettings(void) { opt.WritePackFileName(m_Filename, m_Name); } // // SmileyCategoryListType // void SmileyCategoryListType::ClearAndLoadAll(void) { m_pSmileyPackStore->ClearAndFreeAll(); for (int i = 0; i < m_SmileyCategories.getCount(); i++) { m_SmileyCategories[i].Load(); } } SmileyCategoryType* SmileyCategoryListType::GetSmileyCategory(const bkstring& name) { for (int i = 0; i < m_SmileyCategories.getCount(); i++) { if (name.comparei(m_SmileyCategories[i].GetName()) == 0) return &m_SmileyCategories[i]; } return NULL; } SmileyCategoryType* SmileyCategoryListType::GetSmileyCategory(unsigned index) { return index < (unsigned)m_SmileyCategories.getCount() ? &m_SmileyCategories[index] : NULL; } SmileyPackType* SmileyCategoryListType::GetSmileyPack(bkstring& categoryname) { SmileyCategoryType* smc = GetSmileyCategory(categoryname); return smc != NULL ? smc->GetSmileyPack() : NULL; } void SmileyCategoryListType::SaveSettings(void) { bkstring catstr; for (int i = 0; i < m_SmileyCategories.getCount(); i++) { m_SmileyCategories[i].SaveSettings(); if (m_SmileyCategories[i].IsCustom()) { if (!catstr.empty()) catstr += '#'; catstr += m_SmileyCategories[i].GetName(); } } opt.WriteCustomCategories(catstr); } void SmileyCategoryListType::AddAndLoad(const bkstring& name, const bkstring& displayName) { if (GetSmileyCategory(name) != NULL) return; AddCategory(name, displayName, smcExt); // Load only if other smileys have been loaded already if (m_SmileyCategories.getCount() > 1) { m_SmileyCategories[m_SmileyCategories.getCount()-1].Load(); } } void SmileyCategoryListType::AddCategory(const bkstring& name, const bkstring& displayName, SmcType typ, const bkstring& defaultFilename) { if (GetSmileyCategory(name) == NULL) m_SmileyCategories.insert(new SmileyCategoryType(m_pSmileyPackStore, name, displayName, defaultFilename, typ)); } bool SmileyCategoryListType::DeleteCustomCategory(int index) { if (index < m_SmileyCategories.getCount()) { if (m_SmileyCategories[index].IsCustom()) { m_SmileyCategories.remove(index); return true; } } return false; } void SmileyCategoryListType::AddAccountAsCategory(PROTOACCOUNT *acc, const bkstring& defaultFile) { if (IsAccountEnabled(acc) && acc->szProtoName && IsSmileyProto(acc->szModuleName)) { bkstring displayName(acc->tszAccountName ? acc->tszAccountName : A2T_SM(acc->szModuleName)); const char* packnam = acc->szProtoName; if (strcmp(packnam, "JABBER") == 0) packnam = "JGMail"; else if (strstr(packnam, "SIP") != NULL) packnam = "MSN"; char path[MAX_PATH]; mir_snprintf(path, sizeof(path), "Smileys\\nova\\%s.msl", packnam); bkstring paths = A2T_SM(path), patha; pathToAbsolute(paths, patha); if (_taccess(patha.c_str(), 0) != 0) paths = defaultFile; bkstring tname(A2T_SM(acc->szModuleName)); AddCategory(tname, displayName, smcProto, paths); } } void SmileyCategoryListType::DeleteAccountAsCategory(PROTOACCOUNT *acc) { bkstring tname(A2T_SM(acc->szModuleName)); HANDLE hContact = (HANDLE)CallService( MS_DB_CONTACT_FINDFIRST, 0, 0); while (hContact != NULL) { char* proto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); if (proto) { DBVARIANT dbv; if (DBGetContactSettingTString(hContact, proto, "Transport", &dbv) == 0) { bool found = (tname.comparei(dbv.ptszVal) == 0); DBFreeVariant(&dbv); if (found) return; } } hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0); } for (int i = 0; i < m_SmileyCategories.getCount(); i++) { if (tname.comparei(m_SmileyCategories[i].GetName()) == 0) { m_SmileyCategories.remove(i); break; } } } void SmileyCategoryListType::AddContactTransportAsCategory(HANDLE hContact, const bkstring& defaultFile) { char* proto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); if (proto == NULL) return; DBVARIANT dbv; if (DBGetContactSettingTString(hContact, proto, "Transport", &dbv) == 0) { if (dbv.ptszVal[0] == '\0') { DBFreeVariant(&dbv); return; } char* trsp = mir_strdup(T2A_SM(dbv.ptszVal)); _strlwr(trsp); const char *packname = NULL; if (strstr(trsp, "msn") != NULL) packname = "msn"; else if (strstr(trsp, "icq") != NULL) packname = "icq"; else if (strstr(trsp, "yahoo") != NULL) packname = "yahoo"; else if (strstr(trsp, "aim") != NULL) packname = "aim"; else if (strstr(trsp, "lcs") != NULL) packname = "msn"; mir_free(trsp); bkstring displayName = dbv.ptszVal; if (packname != NULL) { char path[MAX_PATH]; mir_snprintf(path, sizeof(path), "Smileys\\nova\\%s.msl", packname); bkstring paths = A2T_SM(path), patha; pathToAbsolute(paths, patha); if (_taccess(patha.c_str(), 0) != 0) paths = defaultFile; AddCategory(displayName, displayName, smcProto, paths); } else AddCategory(displayName, displayName, smcProto, defaultFile); DBFreeVariant(&dbv); } } void SmileyCategoryListType::AddAllProtocolsAsCategory(void) { bkstring displayName = TranslateT("Standard"); bkstring tname = _T("Standard"); AddCategory(tname, displayName, smcStd); const bkstring& defaultFile = GetSmileyCategory(tname)->GetFilename(); #if (defined _UNICODE || defined UNICODE) unsigned lpcp = (unsigned)CallService(MS_LANGPACK_GETCODEPAGE, 0, 0); if (lpcp == CALLSERVICE_NOTFOUND) lpcp = CP_ACP; #endif PROTOCOLDESCRIPTOR **protoList; PROTOACCOUNT **accList; int protoCount; if (ProtoEnumAccounts(&protoCount, &accList) == CALLSERVICE_NOTFOUND || (protoCount > 0 && accList[0]->cbSize == 0)) { CallService(MS_PROTO_ENUMPROTOCOLS, (WPARAM)&protoCount, (LPARAM)&protoList); for (int i = 0; i < protoCount; i++) { if (protoList[i]->type != PROTOTYPE_PROTOCOL) continue; if (IsSmileyProto(protoList[i]->szName)) { const char* packnam = protoList[i]->szName; if (strcmp(packnam, "JABBER") == 0) packnam = "JGMail"; else if (strstr(packnam, "SIP") != NULL) packnam = "MSN"; char path[MAX_PATH]; mir_snprintf(path, sizeof(path), "Smileys\\nova\\%s.msl", packnam); bkstring paths = A2T_SM(path), patha; pathToAbsolute(paths, patha); if (_taccess(patha.c_str(), 0) != 0) paths = defaultFile; char protoName[128]; CallProtoService(protoList[i]->szName, PS_GETNAME, sizeof(protoName), (LPARAM)protoName); #if (defined _UNICODE || defined UNICODE) displayName = A2W_SM(protoName, lpcp); #else displayName = protoName; #endif tname = A2T_SM(protoList[i]->szName); AddCategory(tname, displayName, smcProto, paths); } } } else { for (int i = 0; i < protoCount; i++) AddAccountAsCategory(accList[i], defaultFile); } HANDLE hContact = (HANDLE)CallService( MS_DB_CONTACT_FINDFIRST, 0, 0); while (hContact != NULL) { AddContactTransportAsCategory(hContact, defaultFile); hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0); } bkstring cats; opt.ReadCustomCategories(cats); bkstring::size_type cppv = 0; for (;;) { bkstring::size_type cp = cats.find('#', cppv); if (cp != cats.npos) { displayName = cats.substr(cppv, cp - cppv); AddCategory(displayName, displayName, smcCustom, defaultFile); cppv = cp + 1; } else break; } if (cppv != cats.size()) { displayName = cats.substr(cppv, cats.size() - cppv); AddCategory(displayName, displayName, smcCustom, defaultFile); } } SmileyLookup::SmileyLookup(const bkstring& str, const bool regexs, const int ind, const bkstring& smpt) { TCHAR msgtxt[1024]; m_ind = ind; if (regexs) { static const bkstring testString(_T("Test String")); m_pattern = _TPattern::compile(str); m_valid = m_pattern != NULL; if (m_valid) { _TMatcher* matcher = m_pattern->createTMatcher(testString); m_valid &= (!matcher->findFirstMatch() || matcher->getStartingIndex() != matcher->getEndingIndex()); if (!m_valid) { static const TCHAR errmsg[] = _T("Regular Expression \"%s\" in smiley pack \"%s\" could produce \"empty matches\"."); mir_sntprintf(msgtxt, SIZEOF(msgtxt), TranslateTS(errmsg), str.c_str(), smpt.c_str()); } delete matcher; } else { static const TCHAR errmsg[] = _T("Regular Expression \"%s\" in smiley pack \"%s\" malformed.") ; mir_sntprintf(msgtxt, SIZEOF(msgtxt), TranslateTS(errmsg), str.c_str(), smpt.c_str()); } if (!m_valid) CallService(MS_NETLIB_LOG, (WPARAM) hNetlibUser, (LPARAM)(char*)T2A_SM(msgtxt)); } else { m_text = str; m_pattern = NULL; m_valid = !str.empty(); } } SmileyLookup::~SmileyLookup() { if (m_pattern) delete m_pattern; } void SmileyLookup::find(const bkstring& str, SmileyLocVecType& smlcur, bool firstOnly) const { if (!m_valid) return; if (m_text.empty()) { _TMatcher* matcher = m_pattern->createTMatcher(str); while( matcher->findNextMatch() ) { bkstring::size_type st = matcher->getStartingIndex(); bkstring::size_type sz = matcher->getEndingIndex() - st; if (sz != 0) { smlcur.insert(new SmileyLocType(st, sz)); if (firstOnly && m_ind != -1) return; } } delete matcher; } else { const TCHAR* pos = str.c_str(); while( (pos = _tcsstr(pos, m_text.c_str())) != NULL ) { smlcur.insert(new SmileyLocType(pos - str.c_str(), m_text.size())); pos += m_text.size(); if (firstOnly && m_ind != -1) return; } } }