/* Miranda IM: the free IM client for Microsoft* Windows* Copyright 2000-2009 Miranda ICQ/IM project, all portions of this codebase are copyrighted to the people listed in contributors.txt. 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. */ #include "..\..\core\commonheaders.h" #include "../srfile/file.h" static bool bModuleInitialized = false; static HANDLE hIniChangeNotification; extern TCHAR mirandabootini[MAX_PATH]; extern bool dbCreated; static INT_PTR CALLBACK InstallIniDlgProc(HWND hwndDlg,UINT message,WPARAM wParam,LPARAM lParam) { switch(message) { case WM_INITDIALOG: TranslateDialogDefault(hwndDlg); SetDlgItemText(hwndDlg, IDC_ININAME, (TCHAR*)lParam); { TCHAR szSecurity[11]; const TCHAR *pszSecurityInfo; GetPrivateProfileString(_T("AutoExec"), _T("Warn"), _T("notsafe"), szSecurity, SIZEOF(szSecurity), mirandabootini); if (!lstrcmpi(szSecurity, _T("all"))) pszSecurityInfo = LPGENT("Security systems to prevent malicious changes are in place and you will be warned before every change that is made."); else if (!lstrcmpi(szSecurity, _T("onlyunsafe"))) pszSecurityInfo = LPGENT("Security systems to prevent malicious changes are in place and you will be warned before changes that are known to be unsafe."); else if (!lstrcmpi(szSecurity, _T("none"))) pszSecurityInfo = LPGENT("Security systems to prevent malicious changes have been disabled. You will receive no further warnings."); else pszSecurityInfo = NULL; if (pszSecurityInfo) SetDlgItemText(hwndDlg, IDC_SECURITYINFO, TranslateTS(pszSecurityInfo)); } return TRUE; case WM_COMMAND: switch(LOWORD(wParam)) { case IDC_VIEWINI: { TCHAR szPath[MAX_PATH]; GetDlgItemText(hwndDlg, IDC_ININAME, szPath, SIZEOF(szPath)); ShellExecute(hwndDlg, _T("open"), szPath, NULL, NULL, SW_SHOW); break; } case IDOK: case IDCANCEL: case IDC_NOTOALL: EndDialog(hwndDlg,LOWORD(wParam)); break; } break; } return FALSE; } static bool IsInSpaceSeparatedList(const char *szWord,const char *szList) { const char *szItem,*szEnd; int wordLen = lstrlenA(szWord); for (szItem = szList;;) { szEnd = strchr(szItem,' '); if (szEnd == NULL) return !lstrcmpA( szItem, szWord ); if ( szEnd - szItem == wordLen ) { if ( !strncmp( szItem, szWord, wordLen )) return true; } szItem = szEnd+1; } } struct warnSettingChangeInfo_t { TCHAR *szIniPath; char *szSection; char *szSafeSections; char *szUnsafeSections; char *szName; char *szValue; int warnNoMore,cancel; }; static INT_PTR CALLBACK WarnIniChangeDlgProc(HWND hwndDlg,UINT message,WPARAM wParam,LPARAM lParam) { static struct warnSettingChangeInfo_t *warnInfo; switch(message) { case WM_INITDIALOG: { char szSettingName[256]; const TCHAR *pszSecurityInfo; warnInfo = (warnSettingChangeInfo_t*)lParam; TranslateDialogDefault(hwndDlg); SetDlgItemText(hwndDlg, IDC_ININAME, warnInfo->szIniPath); lstrcpyA(szSettingName, warnInfo->szSection); lstrcatA(szSettingName," / "); lstrcatA(szSettingName,warnInfo->szName); SetDlgItemTextA(hwndDlg,IDC_SETTINGNAME,szSettingName); SetDlgItemTextA(hwndDlg,IDC_NEWVALUE,warnInfo->szValue); if (IsInSpaceSeparatedList(warnInfo->szSection,warnInfo->szSafeSections)) pszSecurityInfo=LPGENT("This change is known to be safe."); else if (IsInSpaceSeparatedList(warnInfo->szSection,warnInfo->szUnsafeSections)) pszSecurityInfo=LPGENT("This change is known to be potentially hazardous."); else pszSecurityInfo=LPGENT("This change is not known to be safe."); SetDlgItemText(hwndDlg,IDC_SECURITYINFO,TranslateTS(pszSecurityInfo)); return TRUE; } case WM_COMMAND: switch(LOWORD(wParam)) { case IDCANCEL: warnInfo->cancel=1; case IDYES: case IDNO: warnInfo->warnNoMore=IsDlgButtonChecked(hwndDlg,IDC_WARNNOMORE); EndDialog(hwndDlg,LOWORD(wParam)); break; } break; } return FALSE; } static INT_PTR CALLBACK IniImportDoneDlgProc(HWND hwndDlg,UINT message,WPARAM wParam,LPARAM lParam) { switch(message) { case WM_INITDIALOG: TranslateDialogDefault(hwndDlg); SetDlgItemText(hwndDlg,IDC_ININAME,(TCHAR*)lParam); SetDlgItemText(hwndDlg,IDC_NEWNAME,(TCHAR*)lParam); return TRUE; case WM_COMMAND: { TCHAR szIniPath[MAX_PATH]; GetDlgItemText(hwndDlg,IDC_ININAME,szIniPath,SIZEOF(szIniPath)); switch(LOWORD(wParam)) { case IDC_DELETE: DeleteFile(szIniPath); case IDC_LEAVE: EndDialog(hwndDlg,LOWORD(wParam)); break; case IDC_RECYCLE: { SHFILEOPSTRUCT shfo={0}; shfo.wFunc=FO_DELETE; shfo.pFrom=szIniPath; szIniPath[lstrlen(szIniPath)+1]='\0'; shfo.fFlags = FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_SILENT | FOF_ALLOWUNDO; SHFileOperation(&shfo); } EndDialog(hwndDlg,LOWORD(wParam)); break; case IDC_MOVE: { TCHAR szNewPath[MAX_PATH]; GetDlgItemText(hwndDlg,IDC_NEWNAME,szNewPath,SIZEOF(szNewPath)); MoveFile(szIniPath,szNewPath); } EndDialog(hwndDlg,LOWORD(wParam)); break; } break; } } return FALSE; } // settings: struct SettingsList { char *name; SettingsList *next; } *setting_items = NULL; int SettingsEnumProc(const char *szSetting, LPARAM lParam) { SettingsList *newItem = (SettingsList *)mir_alloc(sizeof(SettingsList)); newItem->name = mir_strdup(szSetting); newItem->next = setting_items; setting_items = newItem; return 0; } void ConvertBackslashes(char *, UINT); static void ProcessIniFile(TCHAR* szIniPath, char *szSafeSections, char *szUnsafeSections, int secur, bool secFN) { FILE *fp = _tfopen(szIniPath, _T("rt")); if ( fp == NULL ) return; bool warnThisSection = false; char szSection[128]; szSection[0] = 0; while(!feof(fp)) { char szLine[2048]; if (fgets(szLine,sizeof(szLine),fp) == NULL) break; int lineLength = lstrlenA(szLine); while (lineLength && (BYTE)(szLine[lineLength-1])<=' ') szLine[--lineLength]='\0'; if (szLine[0] == ';' || szLine[0]<=' ') continue; if (szLine[0] == '[') { char *szEnd = strchr(szLine+1,']'); if (szEnd == NULL) continue; if (szLine[1] == '!') szSection[0] = '\0'; else { lstrcpynA(szSection,szLine+1,min(sizeof(szSection),(int)(szEnd-szLine))); switch (secur) { case 0: warnThisSection = false; break; case 1: warnThisSection = !IsInSpaceSeparatedList(szSection, szSafeSections); break; case 2: warnThisSection = IsInSpaceSeparatedList(szSection, szUnsafeSections); break; default: warnThisSection = true; break; } if (secFN) warnThisSection=0; } if (szLine[1] == '?') { DBCONTACTENUMSETTINGS dbces; dbces.pfnEnumProc=SettingsEnumProc; lstrcpynA(szSection,szLine+2,min(sizeof(szSection),(int)(szEnd-szLine-1))); dbces.szModule=szSection; dbces.ofsSettings=0; CallService(MS_DB_CONTACT_ENUMSETTINGS,0,(LPARAM)&dbces); while (setting_items) { SettingsList *next = setting_items->next; DBCONTACTGETSETTING dbcgs; dbcgs.szModule = szSection; dbcgs.szSetting = setting_items->name; CallService(MS_DB_CONTACT_DELETESETTING, 0, (LPARAM)&dbcgs); mir_free(setting_items->name); mir_free(setting_items); setting_items = next; } } continue; } if (szSection[0] == '\0') continue; char *szValue=strchr(szLine,'='); if ( szValue == NULL ) continue; char szName[128]; lstrcpynA(szName,szLine,min(sizeof(szName),(int)(szValue-szLine+1))); szValue++; { warnSettingChangeInfo_t warnInfo; warnInfo.szIniPath=szIniPath; warnInfo.szName=szName; warnInfo.szSafeSections=szSafeSections; warnInfo.szSection=szSection; warnInfo.szUnsafeSections=szUnsafeSections; warnInfo.szValue=szValue; warnInfo.warnNoMore=0; warnInfo.cancel=0; if (warnThisSection && IDNO==DialogBoxParam(hMirandaInst,MAKEINTRESOURCE(IDD_WARNINICHANGE),NULL,WarnIniChangeDlgProc,(LPARAM)&warnInfo)) continue; if (warnInfo.cancel) break; if (warnInfo.warnNoMore) warnThisSection=0; } switch(szValue[0]) { case 'b': case 'B': DBWriteContactSettingByte(NULL,szSection,szName,(BYTE)strtol(szValue+1,NULL,0)); break; case 'w': case 'W': DBWriteContactSettingWord(NULL,szSection,szName,(WORD)strtol(szValue+1,NULL,0)); break; case 'd': case 'D': DBWriteContactSettingDword(NULL,szSection,szName,(DWORD)strtoul(szValue+1,NULL,0)); break; case 'l': case 'L': DBDeleteContactSetting(NULL,szSection,szName); break; case 'e': case 'E': ConvertBackslashes(szValue+1, LangPackGetDefaultCodePage()); case 's': case 'S': DBWriteContactSettingString(NULL,szSection,szName,szValue+1); break; case 'g': case 'G': { char *pstr; for (pstr=szValue+1;*pstr;pstr++) { if (*pstr=='\\') { switch(pstr[1]) { case 'n': *pstr='\n'; break; case 't': *pstr='\t'; break; case 'r': *pstr='\r'; break; default: *pstr=pstr[1]; break; } MoveMemory(pstr+1,pstr+2,lstrlenA(pstr+2)+1); } } } case 'u': case 'U': DBWriteContactSettingStringUtf(NULL,szSection,szName,szValue+1); break; case 'n': case 'h': case 'N': case 'H': { PBYTE buf; int len; char *pszValue,*pszEnd; DBCONTACTWRITESETTING cws; buf=(PBYTE)mir_alloc(lstrlenA(szValue+1)); for (len=0,pszValue=szValue+1;;len++) { buf[len]=(BYTE)strtol(pszValue,&pszEnd,0x10); if (pszValue==pszEnd) break; pszValue=pszEnd; } cws.szModule=szSection; cws.szSetting=szName; cws.value.type=DBVT_BLOB; cws.value.pbVal=buf; cws.value.cpbVal=len; CallService(MS_DB_CONTACT_WRITESETTING,(WPARAM)(HANDLE)NULL,(LPARAM)&cws); mir_free(buf); } break; default: MessageBox(NULL,TranslateT("Invalid setting type. The first character of every value must be b, w, d, l, s, e, u, g, h or n."),TranslateT("Install Database Settings"),MB_OK); break; } } fclose(fp); } static void DoAutoExec(void) { TCHAR szUse[7], szIniPath[MAX_PATH], szFindPath[MAX_PATH]; TCHAR *str2; TCHAR buf[2048], szSecurity[11], szOverrideSecurityFilename[MAX_PATH], szOnCreateFilename[MAX_PATH]; char *szSafeSections, *szUnsafeSections; int secur; GetPrivateProfileString(_T("AutoExec"),_T("Use"),_T("prompt"),szUse,SIZEOF(szUse),mirandabootini); if (!lstrcmpi(szUse,_T("no"))) return; GetPrivateProfileString(_T("AutoExec"),_T("Safe"),_T("CLC Icons CLUI CList SkinSounds"),buf,SIZEOF(buf),mirandabootini); szSafeSections = mir_t2a(buf); GetPrivateProfileString(_T("AutoExec"),_T("Unsafe"),_T("ICQ MSN"),buf,SIZEOF(buf),mirandabootini); szUnsafeSections = mir_t2a(buf); GetPrivateProfileString(_T("AutoExec"),_T("Warn"),_T("notsafe"),szSecurity,SIZEOF(szSecurity),mirandabootini); if (!lstrcmpi(szSecurity,_T("none"))) secur = 0; else if (!lstrcmpi(szSecurity,_T("notsafe"))) secur = 1; else if (!lstrcmpi(szSecurity,_T("onlyunsafe"))) secur = 2; GetPrivateProfileString(_T("AutoExec"),_T("OverrideSecurityFilename"),_T(""),szOverrideSecurityFilename,SIZEOF(szOverrideSecurityFilename),mirandabootini); GetPrivateProfileString(_T("AutoExec"),_T("OnCreateFilename"),_T(""),szOnCreateFilename,SIZEOF(szOnCreateFilename),mirandabootini); GetPrivateProfileString(_T("AutoExec"),_T("Glob"),_T("autoexec_*.ini"),szFindPath,SIZEOF(szFindPath),mirandabootini); if (dbCreated && szOnCreateFilename[0]) { str2 = Utils_ReplaceVarsT(szOnCreateFilename); pathToAbsoluteT(str2, szIniPath, NULL); mir_free(str2); ProcessIniFile(szIniPath, szSafeSections, szUnsafeSections, 0, 1); } str2 = Utils_ReplaceVarsT(szFindPath); pathToAbsoluteT(str2, szFindPath, NULL); mir_free(str2); WIN32_FIND_DATA fd; HANDLE hFind = FindFirstFile(szFindPath, &fd); if (hFind == INVALID_HANDLE_VALUE) { mir_free(szSafeSections); mir_free(szUnsafeSections); return; } str2 = _tcsrchr(szFindPath, '\\'); if (str2 == NULL) szFindPath[0] = 0; else str2[1] = 0; do { bool secFN = lstrcmpi(fd.cFileName,szOverrideSecurityFilename) == 0; mir_sntprintf(szIniPath, SIZEOF(szIniPath), _T("%s%s"), szFindPath, fd.cFileName); if (!lstrcmpi(szUse,_T("prompt")) && !secFN) { int result=DialogBoxParam(hMirandaInst,MAKEINTRESOURCE(IDD_INSTALLINI),NULL,InstallIniDlgProc,(LPARAM)szIniPath); if (result==IDC_NOTOALL) break; if (result==IDCANCEL) continue; } ProcessIniFile(szIniPath, szSafeSections, szUnsafeSections, secur, secFN); if (secFN) DeleteFile(szIniPath); else { TCHAR szOnCompletion[8]; GetPrivateProfileString(_T("AutoExec"),_T("OnCompletion"),_T("recycle"),szOnCompletion,SIZEOF(szOnCompletion),mirandabootini); if (!lstrcmpi(szOnCompletion,_T("delete"))) DeleteFile(szIniPath); else if (!lstrcmpi(szOnCompletion,_T("recycle"))) { SHFILEOPSTRUCT shfo={0}; shfo.wFunc=FO_DELETE; shfo.pFrom=szIniPath; szIniPath[lstrlen(szIniPath)+1]=0; shfo.fFlags=FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_SILENT | FOF_ALLOWUNDO; SHFileOperation(&shfo); } else if (!lstrcmpi(szOnCompletion,_T("rename"))) { TCHAR szRenamePrefix[MAX_PATH]; TCHAR szNewPath[MAX_PATH]; GetPrivateProfileString(_T("AutoExec"),_T("RenamePrefix"),_T("done_"),szRenamePrefix,SIZEOF(szRenamePrefix),mirandabootini); lstrcpy(szNewPath,szFindPath); lstrcat(szNewPath,szRenamePrefix); lstrcat(szNewPath,fd.cFileName); MoveFile(szIniPath,szNewPath); } else if (!lstrcmpi(szOnCompletion,_T("ask"))) DialogBoxParam(hMirandaInst,MAKEINTRESOURCE(IDD_INIIMPORTDONE),NULL,IniImportDoneDlgProc,(LPARAM)szIniPath); } } while (FindNextFile(hFind, &fd)); FindClose(hFind); mir_free(szSafeSections); mir_free(szUnsafeSections); } static INT_PTR CheckIniImportNow(WPARAM, LPARAM) { DoAutoExec(); FindNextChangeNotification(hIniChangeNotification); return 0; } int InitIni(void) { TCHAR szMirandaDir[MAX_PATH]; bModuleInitialized = true; DoAutoExec(); pathToAbsoluteT(_T("."), szMirandaDir, NULL); hIniChangeNotification=FindFirstChangeNotification(szMirandaDir, 0, FILE_NOTIFY_CHANGE_FILE_NAME); if (hIniChangeNotification != INVALID_HANDLE_VALUE) { CreateServiceFunction("DB/Ini/CheckImportNow", CheckIniImportNow); CallService(MS_SYSTEM_WAITONHANDLE, (WPARAM)hIniChangeNotification, (LPARAM)"DB/Ini/CheckImportNow"); } return 0; } void UninitIni(void) { if ( !bModuleInitialized ) return; CallService(MS_SYSTEM_REMOVEWAIT,(WPARAM)hIniChangeNotification,0); FindCloseChangeNotification(hIniChangeNotification); }