1 /***************************************************************************
2 
3     copyright            : (C) 2006 by mean
4     email                : fixounet@free.fr
5  ***************************************************************************/
6 
7 /***************************************************************************
8  *                                                                         *
9  *   This program is free software; you can redistribute it and/or modify  *
10  *   it under the terms of the GNU General Public License as published by  *
11  *   the Free Software Foundation; either version 2 of the License, or     *
12  *   (at your option) any later version.                                   *
13  *                                                                         *
14  ***************************************************************************/
15 
16 
17 #include <errno.h>
18 #include <string>
19 #include <io.h>
20 #include <direct.h>
21 #include <shlobj.h>
22 #include "ADM_win32.h"
23 
24 #include "ADM_default.h"
25 
26 extern void simplify_path(char **buf);
27 extern char *ADM_getRelativePath(const char *base0, const char *base1, const char *base2, const char *base3);
28 static char ADM_basedir[1024] = {0};
29 static char ADM_logdir[1024] = {0};
30 static std::string ADM_autodir;
31 static std::string ADM_systemPluginSettings;
32 
33 #undef fread
34 #undef fwrite
35 #undef fopen
36 #undef fclose
37 
38 /**
39     \fn ADM_getAutoDir
40     \brief  Get the  directory where auto script are stored. No need to free the string.
41 ******************************************************/
ADM_getAutoDir(void)42 const std::string ADM_getAutoDir(void)
43 {
44     if (ADM_autodir.size())
45         return ADM_autodir;
46     const char *startDir=ADM_RELATIVE_LIB_DIR;
47     const char *s = ADM_getInstallRelativePath(startDir, ADM_PLUGIN_DIR, "autoScripts");
48     ADM_autodir = std::string(s);
49     delete [] s;
50     s=NULL;
51     return ADM_autodir;
52 }
53 /**
54     \fn ADM_getPluginSettingsDir
55     \brief Get the folder containing the plugin settings (presets etc..)
56 */
ADM_getSystemPluginSettingsDir(void)57 const std::string ADM_getSystemPluginSettingsDir(void)
58 {
59     if(ADM_systemPluginSettings.size())
60         return ADM_systemPluginSettings;
61     const char *startDir=ADM_RELATIVE_LIB_DIR;
62     const char *s = ADM_getInstallRelativePath(startDir, ADM_PLUGIN_DIR, "pluginSettings");
63     ADM_systemPluginSettings = std::string(s);
64     delete [] s;
65     s=NULL;
66     return ADM_systemPluginSettings;
67 }
68 
69 
AddSeparator(char * path)70 static void AddSeparator(char *path)
71 {
72 	if (path && (strlen(path) < strlen(ADM_SEPARATOR) || strncmp(path + strlen(path) - strlen(ADM_SEPARATOR), ADM_SEPARATOR, strlen(ADM_SEPARATOR)) != 0))
73 		strcat(path, ADM_SEPARATOR);
74 }
75 
76 /**
77  * 	\fn char *ADM_getHomeRelativePath(const char *base1, const char *base2=NULL,const char *base3=NULL);
78  *  \brief Returns home directory +base 1 + base 2... The return value is a copy, and must be deleted []
79  */
ADM_getHomeRelativePath(const char * base1,const char * base2,const char * base3)80 char *ADM_getHomeRelativePath(const char *base1, const char *base2, const char *base3)
81 {
82 	return ADM_getRelativePath(ADM_getBaseDir(), base1, base2, base3);
83 }
84 
85 
86 /*
87       Get the root directory for .avidemux stuff
88 ******************************************************/
ADM_getBaseDir(void)89 const char *ADM_getBaseDir(void)
90 {
91 	return ADM_basedir;
92 }
93 
94 /*
95       Get the root directory for .avidemux stuff
96 ******************************************************/
ADM_getLogDir(void)97 const char *ADM_getLogDir(void)
98 {
99 	return ADM_logdir;
100 }
101 
102 /**
103  * \fn ADM_initBaseDir
104  * \brief ADM_initBaseDir
105  */
ADM_initBaseDir(int argc,char * argv[])106 void ADM_initBaseDir(int argc, char *argv[])
107 {
108 	char *home = NULL;
109 	char *log = NULL;
110 
111     bool portableMode=isPortableMode(argc,argv);
112 	// Get the base directory
113 
114     if (portableMode)
115     {
116         // Portable mode...
117         home = ADM_getInstallRelativePath(NULL, NULL, NULL);
118         log = ADM_getInstallRelativePath(NULL, NULL, NULL);
119     }
120 	else
121     {
122         wchar_t wcHome[MAX_PATH];
123         wchar_t wcLog[MAX_PATH];
124 
125         if (SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, 0, wcHome) == S_OK)
126         {
127             int len = wideCharStringToUtf8(wcHome, -1, NULL);
128             home = new char[len];
129 
130             wideCharStringToUtf8(wcHome, -1, home);
131         }
132         else
133         {
134             printf("Oops: can't determine the Application Data folder.");
135             home=new char[10];
136             strcpy(home,"c:\\");
137         }
138 
139         if (SHGetFolderPathW(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, wcLog) == S_OK)
140         {
141             int len = wideCharStringToUtf8(wcLog, -1, NULL);
142             log = new char[len];
143 
144             wideCharStringToUtf8(wcLog, -1, log);
145         }
146         else
147         {
148             printf("Oops: can't determine the Local Application Data folder.");
149             log=new char[10];
150             strcpy(log,"c:\\");
151         }
152     }
153 
154 
155 	// Try to open the .avidemux directory
156 
157 	if (home)
158 	{
159 		strcpy(ADM_basedir, home);
160 		AddSeparator(ADM_basedir);
161 
162 
163 		const char *ADM_DIR_NAME;
164 
165 		if (portableMode)
166 			ADM_DIR_NAME = "settings";
167 		else
168 			ADM_DIR_NAME = "avidemux";
169 
170 		strcat(ADM_basedir, ADM_DIR_NAME);
171 		strcat(ADM_basedir, ADM_SEPARATOR);
172 
173 		delete [] home;
174 
175 		if (ADM_mkdir(ADM_basedir))
176 		{
177 			printf("Using %s as base directory for prefs, jobs, etc.\n", ADM_basedir);
178 		}
179 		else
180 		{
181 			ADM_error("Oops: cannot create the .avidemux directoryi (%s)\n", ADM_basedir);
182 		}
183 	}
184 
185 	if (log)
186 	{
187 		strcpy(ADM_logdir, log);
188 		AddSeparator(ADM_logdir);
189 
190 
191 		const char *ADM_DIR_NAME;
192 
193 		if (portableMode)
194 			ADM_DIR_NAME = "settings";
195 		else
196 			ADM_DIR_NAME = "avidemux";
197 
198 		strcat(ADM_logdir, ADM_DIR_NAME);
199 		strcat(ADM_logdir, ADM_SEPARATOR);
200 
201 		delete [] log;
202 
203 		if (ADM_mkdir(ADM_logdir))
204 		{
205 			printf("Using %s as log directory.\n", ADM_logdir);
206 		}
207 		else
208 		{
209 			ADM_error("Oops: cannot create the log directory (%s)\n", ADM_logdir);
210 		}
211 	}
212 }
213 /**
214  * \fn ADM_getI8NDir
215  */
ADM_getI8NDir(const std::string & flavor)216 const std::string ADM_getI8NDir(const std::string &flavor)
217 {
218     //
219     char *home = ADM_getInstallRelativePath(flavor.c_str(), "i18n", NULL);
220     std::string r=std::string(home);
221     delete [] home;
222     return r;
223 }
224 //--- 8< 8< 8<
225 
226 #	include <io.h>
227 #	include <direct.h>
228 #	include <shlobj.h>
229 #	include <fcntl.h>
230 #	include "ADM_win32.h"
231 
232 /*
233 
234 ** note: it modifies it's first argument
235 */
simplify_path(char ** buf)236 void simplify_path(char **buf)
237 {
238 	unsigned int last1slash = 0;
239 	unsigned int last2slash = 0;
240 
241 	while (!strncmp(*buf, "/../", 4))
242 		memmove(*buf, *buf + 3, strlen(*buf + 3) + 1);
243 
244 	for (unsigned int i = 0; i < strlen(*buf) - 2; i++)
245 		while (!strncmp(*buf + i, "/./", 3))
246 			memmove(*buf + i, *buf + i + 2, strlen(*buf + i + 2) + 1);
247 
248 	for (unsigned int i = 0; i < strlen(*buf) - 3; i++)
249 	{
250 		if (*(*buf + i) == '/')
251 		{
252 			last2slash = last1slash;
253 			last1slash = i;
254 		}
255 
256 		if (!strncmp(*buf + i, "/../", 4))
257 		{
258 			memmove(*buf + last2slash, *buf + i + 3, strlen(*buf + i + 3) + 1);
259 
260 			return simplify_path(buf);
261 		}
262 	}
263 }
264 
265 
266 /**
267         \fn ADM_PathCanonize
268         \brief Canonize the path, returns a copy of the absolute path given as parameter
269 */
ADM_PathCanonize(const char * tmpname)270 char *ADM_PathCanonize(const char *tmpname)
271 {
272 	char path[300];
273 	char *out;
274 
275 	if (!getcwd(path, 300))
276 	{
277 		fprintf(stderr, "\ngetcwd() failed with: %s (%u)\n", strerror(errno), errno);
278 		path[0] = '\0';
279 	}
280 
281 	if (!tmpname || tmpname[0] == 0)
282 	{
283 		out = new char[strlen(path) + 2];
284 		strcpy(out, path);
285 #ifndef _WIN32
286 		strcat(out, "/");
287 #else
288 		strcat(out, "\\");
289 #endif
290 		printf("\n Canonizing null string ??? (%s)\n", out);
291 	}
292 	else if (tmpname[0] == '/'
293 #if defined(_WIN32)
294 		|| tmpname[1] == ':'
295 #endif
296 		)
297 	{
298 		out = new char[strlen(tmpname) + 1];
299 		strcpy(out, tmpname);
300 
301 		return out;
302 	}
303 	else
304 	{
305 		out = new char[strlen(path) + strlen(tmpname) + 6];
306 		strcpy(out, path);
307 #ifndef _WIN32
308 		strcat(out, "/");
309 #else
310 		strcat(out, "\\");
311 #endif
312 		strcat(out, tmpname);
313 	}
314 
315 	simplify_path(&out);
316 
317 	return out;
318 }
319 
320 /**
321         \fn ADM_PathStripName
322 	\brief Returns path only /foo/bar.avi -> /foo INPLACE, no copy done
323 
324 */
ADM_extractPath(const std::string & str)325 std::string ADM_extractPath(const std::string &str)
326 {
327     std::string p;
328          p=str;
329          size_t idx=p.find_last_of ("\\");
330          if(idx!=std::string::npos)
331             p.resize(idx);
332          return p;
333 }
334 
335 /**
336     \fn ADM_GetFileName
337     \brief Get the filename without path. /foo/bar.avi -> bar.avi INPLACE, NO COPY
338 
339 */
ADM_getFileName(const std::string & str)340 const std::string ADM_getFileName(const std::string &str)
341 {
342     size_t idx=str.find_last_of ("\\");
343     size_t idx2=str.find_last_of ("/");
344 
345 
346     // no / nor \
347 
348     if(idx2==std::string::npos && idx==std::string::npos)
349         return str;
350     // Both, take the further one
351     if(idx2!=std::string::npos && idx!=std::string::npos)
352         if(idx2>idx)
353             return str.substr(idx2+1);
354         else
355             return str.substr(idx+1);
356 
357     // Only one found
358     if(idx2!=std::string::npos)
359          return str.substr(idx2+1);
360     return str.substr(idx+1);
361 }
362 
363 /**
364     \fn ADM_eraseFile
365     \brief utf8-capable unlink(), so that we can use utf8 string even on win32
366 */
ADM_eraseFile(const char * file)367 uint8_t ADM_eraseFile(const char *file)
368 {
369     int fileNameLength = utf8StringToWideChar(file, -1, NULL);
370     wchar_t *wcFile = new wchar_t[fileNameLength];
371 
372     utf8StringToWideChar(file, -1, wcFile);
373 
374     bool r = DeleteFileW(wcFile);
375     delete [] wcFile;
376     if(!r)
377         return 0;
378     return 1;
379 }
380 
381 // EOF
382