1 /*
2  * %kadu copyright begin%
3  * Copyright 2014 Rafał Przemysław Malinowski (rafal.przemyslaw.malinowski@gmail.com)
4  * %kadu copyright end%
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation; either version 2 of
9  * the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include <QtCore/QCoreApplication>
21 #include <QtCore/QDir>
22 #include <QtCore/QFile>
23 #include <QtCore/QFileInfo>
24 
25 #ifdef Q_OS_WIN
26 #include <shlobj.h>
27 #include <windows.h>
28 #endif
29 
30 #include "kadu-config.h"
31 
32 #include "paths-provider.h"
33 
homePath()34 QString PathsProvider::homePath()
35 {
36 #ifdef Q_OS_WIN
37 	wchar_t homepath[MAX_PATH];
38 
39 	// There is unfortunately no way to get this path using Qt4 API.
40 	if (SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, 0, homepath)))
41 		return QDir(QString::fromWCharArray(homepath)).canonicalPath();
42 #endif
43 
44 	return QDir::homePath();
45 }
46 
webKitPath(const QString & path)47 QString PathsProvider::webKitPath(const QString &path)
48 {
49 	if (path.isEmpty())
50 		return path;
51 	if (path.startsWith(QStringLiteral("file:///")))
52 		return path;
53 	if (path.startsWith('/'))
54 		return "file://" + path;
55 	return "file:///" + path;
56 }
57 
PathsProvider(const QString & customProfileDir,QObject * parent)58 PathsProvider::PathsProvider(const QString &customProfileDir, QObject *parent) :
59 		QObject{parent}
60 {
61 	initBasicPaths();
62 	initProfilePath(customProfileDir);
63 }
64 
~PathsProvider()65 PathsProvider::~PathsProvider()
66 {
67 }
68 
initBasicPaths()69 void PathsProvider::initBasicPaths()
70 {
71 #if defined(Q_OS_UNIX)
72 	DesktopFilePath = QCoreApplication::applicationDirPath() + QStringLiteral("/" KADU_DESKTOP_FILE_PATH_RELATIVE_TO_BIN);
73 	DesktopFilePath = QFileInfo(DesktopFilePath).canonicalFilePath();
74 #endif
75 
76 	DataPath = QCoreApplication::applicationDirPath() + QStringLiteral("/" KADU_DATADIR_RELATIVE_TO_BIN);
77 	QString canonicalPath = QDir(DataPath).canonicalPath();
78 	if (!canonicalPath.isEmpty())
79 		DataPath = canonicalPath + '/';
80 
81 	PluginsLibPath = QCoreApplication::applicationDirPath() + QStringLiteral("/" KADU_PLUGINS_LIBDIR_RELATIVE_TO_BIN);
82 	canonicalPath = QDir(PluginsLibPath).canonicalPath();
83 	if (!canonicalPath.isEmpty())
84 		PluginsLibPath = canonicalPath + '/';
85 }
86 
initProfilePath(const QString & customProfileDir)87 void PathsProvider::initProfilePath(const QString &customProfileDir)
88 {
89 #if defined(Q_OS_WIN)
90 	const QString defaultConfigDirRelativeToHome = QStringLiteral("Kadu");
91 	const QString &oldMidConfigDir = defaultConfigDirRelativeToHome;
92 #else
93 	const QString defaultConfigDirRelativeToHome = QStringLiteral(".kadu");
94 	const QString oldMidConfigDir = QStringLiteral("kadu");
95 #endif
96 
97 	if (customProfileDir.isEmpty())
98 	{
99 		if (QFileInfo(dataPath() + QStringLiteral("portable")).exists())
100 			ProfilePath = dataPath() + QStringLiteral("config");
101 		else
102 			ProfilePath = homePath() + '/' + defaultConfigDirRelativeToHome;
103 	}
104 	else
105 	{
106 		if (customProfileDir.startsWith(QStringLiteral("./"))
107 #ifdef Q_OS_WIN
108 				|| customProfileDir.startsWith(QStringLiteral(".\\"))
109 #endif
110 				)
111 			ProfilePath = QDir::currentPath() + '/' + customProfileDir;
112 		else if (QDir(customProfileDir).isAbsolute())
113 			ProfilePath = customProfileDir;
114 		else if (QFileInfo(dataPath() + QStringLiteral("portable")).exists())
115 			ProfilePath = dataPath() + customProfileDir;
116 		else
117 			ProfilePath = homePath() + '/' + customProfileDir;
118 
119 		// compatibility with 0.6.5 and older versions
120 		if (QDir(ProfilePath + '/' + oldMidConfigDir).exists())
121 			ProfilePath += '/' + oldMidConfigDir;
122 	}
123 
124 	// Do not cache QDir objects here unless you know what you are doing and
125 	// you have tested your changes thoroughly under Windows. Using official
126 	// Qt 4.8.1 MSVC 2010 build QDir thinks the dir does not exist if initially
127 	// it did not exist, even though we successfully call QDir::mkpath(). Hence
128 	// QDir::canonicalPath() returs empty string.
129 	if (!QDir(ProfilePath).exists())
130 	{
131 		QDir().mkpath(ProfilePath);
132 		// This equals to 0700 on Unix-like.
133 		QFile(ProfilePath).setPermissions(QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner | QFile::ReadUser | QFile::WriteUser | QFile::ExeUser);
134 	}
135 
136 	QString canonicalPath = QDir(ProfilePath).canonicalPath();
137 	if (!canonicalPath.isEmpty())
138 		ProfilePath = canonicalPath;
139 	if (!ProfilePath.isEmpty() && !ProfilePath.endsWith(QStringLiteral("/")))
140 		ProfilePath += '/';
141 }
142