summaryrefslogtreecommitdiff
path: root/src/modules/utils/path.cpp
diff options
context:
space:
mode:
authorVadim Dashevskiy <watcherhd@gmail.com>2012-05-15 10:38:20 +0000
committerVadim Dashevskiy <watcherhd@gmail.com>2012-05-15 10:38:20 +0000
commit48540940b6c28bb4378abfeb500ec45a625b37b6 (patch)
tree2ef294c0763e802f91d868bdef4229b6868527de /src/modules/utils/path.cpp
parent5c350913f011e119127baeb32a6aedeb4f0d33bc (diff)
initial commit
git-svn-id: http://svn.miranda-ng.org/main/trunk@2 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'src/modules/utils/path.cpp')
-rw-r--r--src/modules/utils/path.cpp600
1 files changed, 600 insertions, 0 deletions
diff --git a/src/modules/utils/path.cpp b/src/modules/utils/path.cpp
new file mode 100644
index 0000000000..80333a3075
--- /dev/null
+++ b/src/modules/utils/path.cpp
@@ -0,0 +1,600 @@
+/*
+
+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 "commonheaders.h"
+#include "../database/profilemanager.h"
+#include "../srfile/file.h"
+
+extern TCHAR g_profileDir[MAX_PATH];
+
+static char szMirandaPath[MAX_PATH];
+static char szMirandaPathLower[MAX_PATH];
+
+static INT_PTR replaceVars(WPARAM wParam, LPARAM lParam);
+
+static int pathIsAbsolute(const char *path)
+{
+ if ( strlen(path) <= 2 )
+ return 0;
+ if ((path[1]==':'&&path[2]=='\\')||(path[0]=='\\'&&path[1]=='\\'))
+ return 1;
+ return 0;
+}
+
+static INT_PTR pathToRelative(WPARAM wParam, LPARAM lParam)
+{
+ char *pSrc = (char*)wParam;
+ char *pOut = (char*)lParam;
+ if (!pSrc||!strlen(pSrc)||strlen(pSrc)>MAX_PATH) return 0;
+ if (!pathIsAbsolute(pSrc)) {
+ mir_snprintf(pOut, MAX_PATH, "%s", pSrc);
+ return strlen(pOut);
+ }
+ else {
+ char szTmp[MAX_PATH];
+
+ mir_snprintf(szTmp, SIZEOF(szTmp), "%s", pSrc);
+ _strlwr(szTmp);
+ if (strstr(szTmp, szMirandaPathLower)) {
+ mir_snprintf(pOut, MAX_PATH, "%s", pSrc+strlen(szMirandaPathLower));
+ return strlen(pOut);
+ }
+ else {
+ mir_snprintf(pOut, MAX_PATH, "%s", pSrc);
+ return strlen(pOut);
+ }
+ }
+}
+
+int pathToAbsolute(const char *pSrc, char *pOut, char* base)
+{
+ if ( !pSrc || !strlen( pSrc ) || strlen( pSrc ) > MAX_PATH )
+ return 0;
+
+ if ( base == NULL )
+ base = szMirandaPath;
+
+ char buf[MAX_PATH];
+ if ( pSrc[0] < ' ')
+ return mir_snprintf( pOut, MAX_PATH, "%s", pSrc );
+ else if ( pathIsAbsolute( pSrc ))
+ return GetFullPathNameA(pSrc, MAX_PATH, pOut, NULL);
+ else if ( pSrc[0] != '\\' )
+ mir_snprintf( buf, MAX_PATH, "%s%s", base, pSrc );
+ else
+ mir_snprintf( buf, MAX_PATH, "%s%s", base, pSrc+1 );
+
+ return GetFullPathNameA(buf, MAX_PATH, pOut, NULL);
+}
+
+static INT_PTR pathToAbsolute(WPARAM wParam, LPARAM lParam)
+{
+ return pathToAbsolute((char*)wParam, (char*)lParam, szMirandaPath);
+}
+
+void CreatePathToFile( char* szFilePath )
+{
+ char* pszLastBackslash = strrchr( szFilePath, '\\' );
+ if ( pszLastBackslash == NULL )
+ return;
+
+ *pszLastBackslash = '\0';
+ CreateDirectoryTree( szFilePath );
+ *pszLastBackslash = '\\';
+}
+
+int CreateDirectoryTree( const char *szDir )
+{
+ DWORD dwAttributes;
+ char *pszLastBackslash, szTestDir[ MAX_PATH ];
+
+ lstrcpynA( szTestDir, szDir, SIZEOF( szTestDir ));
+ if (( dwAttributes = GetFileAttributesA( szTestDir )) != INVALID_FILE_ATTRIBUTES && ( dwAttributes & FILE_ATTRIBUTE_DIRECTORY ))
+ return 0;
+
+ pszLastBackslash = strrchr( szTestDir, '\\' );
+ if ( pszLastBackslash == NULL )
+ return 0;
+
+ *pszLastBackslash = '\0';
+ CreateDirectoryTree( szTestDir );
+ *pszLastBackslash = '\\';
+ return ( CreateDirectoryA( szTestDir, NULL ) == 0 ) ? GetLastError() : 0;
+}
+
+static INT_PTR createDirTree(WPARAM, LPARAM lParam)
+{
+ if ( lParam == 0 )
+ return 1;
+
+ return CreateDirectoryTree(( char* )lParam );
+}
+
+#ifdef _UNICODE
+static TCHAR szMirandaPathW[MAX_PATH];
+static TCHAR szMirandaPathWLower[MAX_PATH];
+
+static int pathIsAbsoluteW(const TCHAR *path)
+{
+ if ( lstrlen(path) <= 2 )
+ return 0;
+ if ((path[1]==':'&&path[2]=='\\')||(path[0]=='\\'&&path[1]=='\\'))
+ return 1;
+ return 0;
+}
+
+static INT_PTR pathToRelativeW(WPARAM wParam, LPARAM lParam)
+{
+ TCHAR *pSrc = (TCHAR*)wParam;
+ TCHAR *pOut = (TCHAR*)lParam;
+ if ( !pSrc || !lstrlen(pSrc) || lstrlen(pSrc) > MAX_PATH )
+ return 0;
+
+ if ( !pathIsAbsoluteW( pSrc ))
+ mir_sntprintf(pOut, MAX_PATH, _T("%s"), pSrc);
+ else {
+ TCHAR szTmp[MAX_PATH];
+
+ mir_sntprintf(szTmp, SIZEOF(szTmp), _T("%s"), pSrc);
+ _tcslwr(szTmp);
+ if (_tcsstr(szTmp, szMirandaPathWLower))
+ mir_sntprintf(pOut, MAX_PATH, _T("%s"), pSrc+lstrlen(szMirandaPathWLower));
+ else
+ mir_sntprintf(pOut, MAX_PATH, _T("%s"), pSrc);
+ }
+ return lstrlen(pOut);
+}
+
+int pathToAbsoluteW(const TCHAR *pSrc, TCHAR *pOut, TCHAR* base)
+{
+ if ( !pSrc || !wcslen(pSrc) || wcslen(pSrc) > MAX_PATH)
+ return 0;
+
+ if ( base == NULL )
+ base = szMirandaPathW;
+
+ TCHAR buf[MAX_PATH];
+ if ( pSrc[0] < ' ')
+ return mir_sntprintf( pOut, MAX_PATH, _T("%s"), pSrc );
+ else if ( pathIsAbsoluteW( pSrc ))
+ return GetFullPathName(pSrc, MAX_PATH, pOut, NULL);
+ else if ( pSrc[0] != '\\' )
+ mir_sntprintf( buf, MAX_PATH, _T("%s%s"), base, pSrc );
+ else
+ mir_sntprintf( buf, MAX_PATH, _T("%s%s"), base, pSrc+1 );
+
+ return GetFullPathName(buf, MAX_PATH, pOut, NULL);
+}
+
+static INT_PTR pathToAbsoluteW(WPARAM wParam, LPARAM lParam)
+{
+ return pathToAbsoluteW((TCHAR*)wParam, (TCHAR*)lParam, szMirandaPathW);
+}
+
+void CreatePathToFileW( WCHAR* wszFilePath )
+{
+ WCHAR* pszLastBackslash = wcsrchr( wszFilePath, '\\' );
+ if ( pszLastBackslash == NULL )
+ return;
+
+ *pszLastBackslash = '\0';
+ CreateDirectoryTreeW( wszFilePath );
+ *pszLastBackslash = '\\';
+}
+
+int CreateDirectoryTreeW( const WCHAR* szDir )
+{
+ DWORD dwAttributes;
+ WCHAR* pszLastBackslash, szTestDir[ MAX_PATH ];
+
+ lstrcpynW( szTestDir, szDir, SIZEOF( szTestDir ));
+ if (( dwAttributes = GetFileAttributesW( szTestDir )) != INVALID_FILE_ATTRIBUTES && ( dwAttributes & FILE_ATTRIBUTE_DIRECTORY ))
+ return 0;
+
+ pszLastBackslash = wcsrchr( szTestDir, '\\' );
+ if ( pszLastBackslash == NULL )
+ return 0;
+
+ *pszLastBackslash = '\0';
+ CreateDirectoryTreeW( szTestDir );
+ *pszLastBackslash = '\\';
+ return ( CreateDirectoryW( szTestDir, NULL ) == 0 ) ? GetLastError() : 0;
+}
+
+static INT_PTR createDirTreeW(WPARAM, LPARAM lParam)
+{
+ if ( lParam == 0 )
+ return 1;
+
+ return CreateDirectoryTreeW(( WCHAR* )lParam );
+}
+
+int InitPathUtilsW(void)
+{
+ GetModuleFileName(hMirandaInst, szMirandaPathW, SIZEOF(szMirandaPathW));
+ TCHAR *p = _tcsrchr(szMirandaPathW,'\\');
+ if ( p )
+ p[1] = 0;
+ mir_sntprintf(szMirandaPathWLower, SIZEOF(szMirandaPathWLower), _T("%s"), szMirandaPathW);
+ _tcslwr(szMirandaPathWLower);
+ CreateServiceFunction(MS_UTILS_PATHTORELATIVEW, pathToRelativeW);
+ CreateServiceFunction(MS_UTILS_PATHTOABSOLUTEW, pathToAbsoluteW);
+ CreateServiceFunction(MS_UTILS_CREATEDIRTREEW, createDirTreeW);
+ return 0;
+}
+#endif
+
+TCHAR *GetContactID(HANDLE hContact)
+{
+ TCHAR *theValue = {0};
+ char *szProto = ( char* )CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+ if (DBGetContactSettingByte(hContact, szProto, "ChatRoom", 0) == 1) {
+ DBVARIANT dbv;
+ if (!DBGetContactSettingTString(hContact, szProto, "ChatRoomID", &dbv)) {
+ theValue = (TCHAR *)mir_tstrdup(dbv.ptszVal);
+ DBFreeVariant(&dbv);
+ return theValue;
+ } }
+ else {
+ CONTACTINFO ci = {0};
+ ci.cbSize = sizeof(ci);
+ ci.hContact = hContact;
+ ci.szProto = szProto;
+ ci.dwFlag = CNF_UNIQUEID | CNF_TCHAR;
+ if (!CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM) & ci)) {
+ switch (ci.type) {
+ case CNFT_ASCIIZ:
+ return (TCHAR *)ci.pszVal;
+ break;
+ case CNFT_DWORD:
+ return _itot(ci.dVal, (TCHAR *)mir_alloc(sizeof(TCHAR)*32), 10);
+ break;
+ } } }
+ return NULL;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Variables parser
+
+#define XSTR(target, s) _xstrselect(target, s, _T(s))
+
+static __forceinline int _xcscmp(const char *s1, const char *s2) { return strcmp(s1, s2); }
+static __forceinline int _xcsncmp(const char *s1, const char *s2, size_t n) { return strncmp(s1, s2, n); }
+static __forceinline size_t _xcslen(const char *s1) { return strlen(s1); }
+static __forceinline char *_xcscpy(char *s1, const char *s2) { return strcpy(s1, s2); }
+static __forceinline char *_xcsncpy(char *s1, const char *s2, size_t n) { return strncpy(s1, s2, n); }
+static __forceinline char *_xstrselect(char *, char *s1, TCHAR *s2) { return s1; }
+static __forceinline char *_itox(char *, int a) { return itoa(a, (char *)mir_alloc(sizeof(char)*20), 10); }
+static __forceinline char *mir_a2x(char *, char *s) { return mir_strdup(s); }
+static __forceinline char *GetContactNickX(char *, HANDLE hContact)
+{
+ return mir_strdup((char *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, 0));
+}
+static __forceinline char *GetContactIDX(char *, HANDLE hContact)
+{
+ TCHAR *id = GetContactID(hContact);
+ char* res = mir_t2a(id);
+ mir_free(id);
+ return res;
+}
+static __forceinline char *GetEnvironmentVariableX(char *variable)
+{
+ char result[512];
+ if (GetEnvironmentVariableA(variable, result, SIZEOF(result)))
+ return mir_strdup(result);
+ return NULL;
+}
+static __forceinline char *GetProfileDirX( char* )
+{
+ return mir_t2a( g_profileDir );
+}
+static __forceinline char *SHGetSpecialFolderPathX(int iCSIDL, char* var)
+{
+ char result[512];
+ if (shGetSpecialFolderPathA && shGetSpecialFolderPathA(NULL, result, iCSIDL, FALSE))
+ return mir_strdup(result);
+ return NULL;
+}
+static __forceinline char *GetModulePathX(char *, HMODULE hModule)
+{
+ char result[MAX_PATH];
+ GetModuleFileNameA(hModule, result, sizeof(result));
+ char* str = strrchr(result, '\\');
+ if (str) *str = 0;
+ return mir_strdup(result);
+}
+static __forceinline char *GetUserNameX(char *)
+{
+ char result[128];
+ DWORD size = SIZEOF(result);
+ if (GetUserNameA(result, &size))
+ return mir_strdup(result);
+ return NULL;
+}
+static __forceinline char *GetProfileNameX(char *)
+{
+ TCHAR szProfileName[MAX_PATH];
+ _tcscpy( szProfileName, g_profileName );
+ TCHAR *pos = _tcsrchr(szProfileName, '.');
+ if ( lstrcmp( pos, _T(".dat")) == 0 )
+ *pos = 0;
+ return mir_t2a( szProfileName );
+}
+static __forceinline char *GetPathVarX(char *, int code)
+{
+ TCHAR szFullPath[MAX_PATH], szProfileName[MAX_PATH];
+ _tcscpy( szProfileName, g_profileName );
+ _tcslwr( szProfileName );
+ TCHAR *pos = _tcsrchr(szProfileName, '.');
+ if ( lstrcmp( pos, _T(".dat")) == 0 )
+ *pos = 0;
+
+ switch( code ) {
+ case 1:
+ mir_sntprintf(szFullPath, SIZEOF(szFullPath), _T("%s\\%s\\AvatarCache"), g_profileDir, szProfileName);
+ break;
+ case 2:
+ mir_sntprintf(szFullPath, SIZEOF(szFullPath), _T("%s\\%s\\Logs"), g_profileDir, szProfileName);
+ break;
+ case 3:
+ mir_sntprintf(szFullPath, SIZEOF(szFullPath), _T("%s\\%s"), g_profileDir, szProfileName);
+ break;
+ }
+ return makeFileName( szFullPath );
+}
+
+#ifdef _UNICODE
+static __forceinline int _xcscmp(const TCHAR *s1, const TCHAR *s2) { return _tcscmp(s1, s2); }
+static __forceinline int _xcsncmp(const TCHAR *s1, const TCHAR *s2, size_t n) { return _tcsncmp(s1, s2, n); }
+static __forceinline size_t _xcslen(const TCHAR *s1) { return _tcslen(s1); }
+static __forceinline TCHAR *_xcscpy(TCHAR *s1, const TCHAR *s2) { return _tcscpy(s1, s2); }
+static __forceinline TCHAR *_xcsncpy(TCHAR *s1, const TCHAR *s2, size_t n) { return _tcsncpy(s1, s2, n); }
+static __forceinline TCHAR *_xstrselect(TCHAR *, char *s1, TCHAR *s2) { return s2; }
+static __forceinline TCHAR *_itox(TCHAR *, int a) { return _itot(a, (TCHAR *)mir_alloc(sizeof(TCHAR)*20), 10); }
+static __forceinline TCHAR *mir_a2x(TCHAR *, char *s) { return mir_a2t(s); }
+static __forceinline TCHAR *GetContactNickX(TCHAR *, HANDLE hContact)
+{
+ return mir_tstrdup((TCHAR *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR));
+}
+static __forceinline TCHAR *GetContactIDX(TCHAR *, HANDLE hContact)
+{
+ return GetContactID(hContact);
+}
+static __forceinline TCHAR *GetEnvironmentVariableX(TCHAR *variable)
+{
+ TCHAR result[512];
+ if (GetEnvironmentVariable(variable, result, SIZEOF(result)))
+ return mir_tstrdup(result);
+ return NULL;
+}
+static __forceinline TCHAR *SHGetSpecialFolderPathX(int iCSIDL, TCHAR* var)
+{
+ TCHAR result[512];
+ if (shGetSpecialFolderPath && shGetSpecialFolderPath(NULL, result, iCSIDL, FALSE))
+ return mir_tstrdup(result);
+ return NULL;
+}
+static __forceinline TCHAR *GetProfileDirX( TCHAR* )
+{
+ return mir_tstrdup( g_profileDir );
+}
+static __forceinline TCHAR *GetModulePathX(TCHAR *, HMODULE hModule)
+{
+ TCHAR result[MAX_PATH];
+ GetModuleFileName(hModule, result, SIZEOF(result));
+ TCHAR* str = _tcsrchr(result, '\\');
+ if (str) *str = 0;
+ return mir_tstrdup(result);
+}
+static __forceinline TCHAR *GetUserNameX(TCHAR *)
+{
+ TCHAR result[128];
+ DWORD size = SIZEOF(result);
+ if (GetUserName(result, &size))
+ return mir_tstrdup(result);
+ return NULL;
+}
+static __forceinline TCHAR *GetProfileNameX(TCHAR *)
+{
+ TCHAR szProfileName[MAX_PATH];
+ _tcscpy( szProfileName, g_profileName );
+ TCHAR *pos = _tcsrchr(szProfileName, '.');
+ if ( lstrcmp( pos, _T(".dat")) == 0 )
+ *pos = 0;
+ return mir_tstrdup( szProfileName );
+}
+static __forceinline TCHAR *GetPathVarX(TCHAR *, int code)
+{
+ TCHAR szFullPath[MAX_PATH], szProfileName[MAX_PATH];
+ _tcscpy( szProfileName, g_profileName );
+ TCHAR *pos = _tcsrchr(szProfileName, '.');
+ if ( lstrcmp( pos, _T(".dat")) == 0 )
+ *pos = 0;
+
+ switch( code ) {
+ case 1:
+ mir_sntprintf(szFullPath, SIZEOF(szFullPath), _T("%s\\%s\\AvatarCache"), g_profileDir, szProfileName);
+ break;
+ case 2:
+ mir_sntprintf(szFullPath, SIZEOF(szFullPath), _T("%s\\%s\\Logs"), g_profileDir, szProfileName);
+ break;
+ case 3:
+ mir_sntprintf(szFullPath, SIZEOF(szFullPath), _T("%s\\%s"), g_profileDir, szProfileName);
+ break;
+ }
+ return mir_tstrdup( szFullPath );
+}
+#endif
+
+template<typename XCHAR>
+XCHAR *GetInternalVariable(XCHAR *key, size_t keyLength, HANDLE hContact)
+{
+ XCHAR *theValue = NULL;
+ XCHAR *theKey = (XCHAR *)_alloca(sizeof(XCHAR) * (keyLength + 1));
+ _xcsncpy(theKey, key, keyLength);
+ theKey[keyLength] = 0;
+
+ if (hContact) {
+ if (!_xcscmp(theKey, XSTR(key, "nick")))
+ theValue = GetContactNickX(key, hContact);
+ else if (!_xcscmp(theKey, XSTR(key, "proto")))
+ theValue = mir_a2x(key, (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact,0));
+ else if (!_xcscmp(theKey, XSTR(key, "userid")))
+ theValue = GetContactIDX(key, hContact);
+ }
+
+ if (!theValue) {
+ if (!_xcscmp(theKey, XSTR(key, "miranda_path")))
+ theValue = GetModulePathX(key, NULL);
+ else if (!_xcscmp(theKey, XSTR(key, "appdata")))
+ theValue = SHGetSpecialFolderPathX(CSIDL_APPDATA, theKey);
+ else if (!_xcscmp(theKey, XSTR(key, "mydocuments")))
+ theValue = SHGetSpecialFolderPathX(CSIDL_PERSONAL, theKey);
+ else if (!_xcscmp(theKey, XSTR(key, "desktop")))
+ theValue = SHGetSpecialFolderPathX(CSIDL_DESKTOPDIRECTORY, theKey);
+ else if (!_xcscmp(theKey, XSTR(key, "miranda_profile")))
+ theValue = GetProfileDirX(key);
+ else if (!_xcscmp(theKey, XSTR(key, "miranda_profilename")))
+ theValue = GetProfileNameX(key);
+ else if (!_xcscmp(theKey, XSTR(key, "username")))
+ theValue = GetUserNameX(key);
+ else if (!_xcscmp(theKey, XSTR(key, "miranda_avatarcache")))
+ theValue = GetPathVarX(key,1);
+ else if (!_xcscmp(theKey, XSTR(key, "miranda_logpath")))
+ theValue = GetPathVarX(key,2);
+ else if (!_xcscmp(theKey, XSTR(key, "miranda_userdata")))
+ theValue = GetPathVarX(key,3);
+ }
+
+ if (!theValue)
+ theValue = GetEnvironmentVariableX(theKey);
+
+ return theValue;
+}
+
+template<typename XCHAR>
+XCHAR *GetVariableFromArray(REPLACEVARSARRAY *vars, XCHAR *key, size_t keyLength, HANDLE hContact, bool *bFree)
+{
+ *bFree = false;
+ for (REPLACEVARSARRAY *var = vars; var && var->lptzKey; ++var)
+ if ((_xcslen((XCHAR *)var->lptzKey) == keyLength) && !_xcsncmp(key, (XCHAR *)var->lptzKey, keyLength))
+ return (XCHAR *)var->lptzValue;
+
+ *bFree = true;
+ return GetInternalVariable(key, keyLength, hContact);
+}
+
+template<typename XCHAR>
+XCHAR *ReplaceVariables(XCHAR *str, REPLACEVARSDATA *data)
+{
+ if (!str)
+ return NULL;
+
+ XCHAR *p;
+ XCHAR *varStart = 0;
+ size_t length = 0;
+ bool bFree;
+
+ for (p = str; *p; ++p) {
+ if (*p == '%') {
+ if (varStart) {
+ if (p == varStart)
+ length++;
+ else if (XCHAR *value = GetVariableFromArray(data->variables, varStart, p-varStart, data->hContact, &bFree)) {
+ length += _xcslen(value);
+ if (bFree) mir_free(value);
+ }
+ else // variable not found
+ length += p-varStart+2;
+
+ varStart = 0;
+ }
+ else varStart = p+1;
+ }
+ else if (!varStart)
+ length++;
+ }
+
+ XCHAR *result = (XCHAR *)mir_alloc(sizeof(XCHAR) * (length + 1));
+ XCHAR *q = result;
+ varStart = NULL;
+
+ for (p = str; *p; ++p) {
+ if (*p == '%') {
+ if (varStart) {
+ if (p == varStart)
+ *q++ = '%';
+ else if (XCHAR *value = GetVariableFromArray(data->variables, varStart, p-varStart, data->hContact, &bFree)) {
+ _xcscpy(q, value);
+ q += _xcslen(value);
+ if (bFree) mir_free(value);
+ }
+ else {
+ // variable not found
+ _xcsncpy(q, varStart-1, p-varStart+2);
+ q += p-varStart+2;
+ }
+ varStart = 0;
+ }
+ else varStart = p+1;
+ }
+ else if (!varStart)
+ *q++ = *p;
+ }
+
+ *q = 0;
+
+ return result;
+}
+
+static INT_PTR replaceVars(WPARAM wParam, LPARAM lParam)
+{
+ REPLACEVARSDATA *data = (REPLACEVARSDATA *)lParam;
+ if (!(data->dwFlags & RVF_UNICODE))
+ return (INT_PTR)ReplaceVariables<char>((char *)wParam, data);
+
+#ifdef _UNICODE
+ return (INT_PTR)ReplaceVariables<WCHAR>((WCHAR *)wParam, data);
+#else
+ return NULL;
+#endif
+}
+
+int InitPathUtils(void)
+{
+ char *p = 0;
+ GetModuleFileNameA(hMirandaInst, szMirandaPath, SIZEOF(szMirandaPath));
+ p = strrchr(szMirandaPath,'\\');
+ if ( p )
+ p[1] = 0;
+ mir_snprintf(szMirandaPathLower, MAX_PATH, "%s", szMirandaPath);
+ _strlwr(szMirandaPathLower);
+ CreateServiceFunction(MS_UTILS_PATHTORELATIVE, pathToRelative);
+ CreateServiceFunction(MS_UTILS_PATHTOABSOLUTE, pathToAbsolute);
+ CreateServiceFunction(MS_UTILS_CREATEDIRTREE, createDirTree);
+ CreateServiceFunction(MS_UTILS_REPLACEVARS, replaceVars);
+#ifdef _UNICODE
+ return InitPathUtilsW();
+#else
+ return 0;
+#endif
+}