kexi

kexidbshortcutfile.cpp
1/* This file is part of the KDE project
2 Copyright (C) 2005 Jaroslaw Staniek <js@iidea.pl>
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18*/
19
20#include "kexidbshortcutfile.h"
21#include <core/kexiprojectdata.h>
22#include <kexidb/connectiondata.h>
23#include <kexiutils/utils.h>
24
25#include <tdeconfig.h>
26#include <kdebug.h>
27
28#include <tqstringlist.h>
29#include <tqdir.h>
30
32#define KexiDBShortcutFile_version 2
33/* CHANGELOG:
34 v1: initial version
35 v2: "encryptedPassword" field added.
36 For backward compatibility, it is not used if the connection data has been loaded from
37 a file saved with version 1. In such cases unencrypted "password" field is used.
38*/
39
41class KexiDBShortcutFile::Private
42{
43 public:
44 Private()
45 : isDatabaseShortcut(true)
46 {
47 }
48 TQString fileName;
49 bool isDatabaseShortcut : 1;
50};
51
52KexiDBShortcutFile::KexiDBShortcutFile( const TQString& fileName )
53 : d( new KexiDBShortcutFile::Private() )
54{
55 d->fileName = TQDir(fileName).absPath();
56}
57
58KexiDBShortcutFile::~KexiDBShortcutFile()
59{
60 delete d;
61}
62
64{
65 TDEConfig config(d->fileName, true /* readOnly */, false /* local */ );
66 config.setGroup("File Information");
67 data.formatVersion = config.readNumEntry("version", KexiDBShortcutFile_version);
68
69 TQString groupKey;
70 if (!_groupKey || _groupKey->isEmpty()) {
71 TQStringList groups(config.groupList());
72 foreach (TQStringList::ConstIterator, it, groups) {
73 if ((*it).lower()!="file information") {
74 groupKey = *it;
75 break;
76 }
77 }
78 if (groupKey.isEmpty()) {
79 //ERR: "File %1 contains no connection information"
80 return false;
81 }
82 if (_groupKey)
83 *_groupKey = groupKey;
84 }
85 else {
86 if (!config.hasGroup(*_groupKey))
87 return false;
88 groupKey = *_groupKey;
89 }
90
91 config.setGroup(groupKey);
92 TQString type( config.readEntry("type", "database").lower() );
93
94 if (type=="database") {
95 d->isDatabaseShortcut = true;
96 } else if (type=="connection") {
97 d->isDatabaseShortcut = false;
98 }
99 else {
100 //ERR: i18n("No valid "type" field specified for section \"%1\": unknown value \"%2\".").arg(group).arg(type)
101 return false;
102 }
103
104/* kexidbg << "version=" << version
105 << " using group key=" << groupKey
106 << " type=" << type
107 << " caption=" << config.readEntry("caption")
108 << " name=" << config.readEntry("name")
109 << " engine=" << config.readEntry("engine")
110 << " server=" << config.readEntry("server")
111 << " user=" << config.readEntry("user")
112 << " password=" << TQString().fill('*', config.readEntry("password").length())
113 << " comment=" << config.readEntry("comment")
114 << endl;*/
115
116 //no filename by default
117 data.connectionData()->setFileName(TQString());
118
119 if (d->isDatabaseShortcut) {
120 data.setCaption( config.readEntry("caption") );
121 data.setDescription( config.readEntry("comment") );
122 data.connectionData()->description = TQString();
123 data.connectionData()->caption = TQString(); /* connection name is not specified... */
124 data.setDatabaseName( config.readEntry("name") );
125 }
126 else {
127 data.setCaption( TQString() );
128 data.connectionData()->caption = config.readEntry("caption");
129 data.setDescription( TQString() );
130 data.connectionData()->description = config.readEntry("comment");
131 data.setDatabaseName( TQString() ); /* db name is not specified... */
132 }
133 data.connectionData()->driverName = config.readEntry("engine");
134 if (data.connectionData()->driverName.isEmpty()) {
135 //ERR: "No valid "engine" field specified for %1 section" group
136 return false;
137 }
138 data.connectionData()->hostName = config.readEntry("server"); //empty allowed
139 data.connectionData()->port = config.readNumEntry("port", 0);
140 data.connectionData()->useLocalSocketFile = config.readBoolEntry("useLocalSocketFile", false);
141 data.connectionData()->localSocketFileName = config.readEntry("localSocketFile");
142 data.connectionData()->savePassword = config.hasKey("password") || config.hasKey("encryptedPassword");
143 if (data.formatVersion >= 2) {
144 kdDebug() << config.hasKey("encryptedPassword") << endl;
145 data.connectionData()->password = config.readEntry("encryptedPassword");
146 KexiUtils::simpleDecrypt(data.connectionData()->password);
147 }
148 if (data.connectionData()->password.isEmpty()) {//no "encryptedPassword", for compatibility
149 //UNSAFE
150 data.connectionData()->password = config.readEntry("password");
151 }
152// data.connectionData()->savePassword = !data.connectionData()->password.isEmpty();
153 data.connectionData()->userName = config.readEntry("user");
154/* @todo add "options=", eg. as string list? */
155 return true;
156}
157
159 bool savePassword, TQString* _groupKey, bool overwriteFirstGroup)
160{
161 TDEConfig config(d->fileName, false /*rw*/, false /* local */);
162 config.setGroup("File Information");
163
164 uint realFormatVersion = data.formatVersion;
165 if (realFormatVersion == 0) /* 0 means "default version"*/
166 realFormatVersion = KexiDBShortcutFile_version;
167 config.writeEntry("version", realFormatVersion);
168
169 const bool thisIsConnectionData = data.databaseName().isEmpty();
170
171 //use or find a nonempty group key
172 TQString groupKey;
173 if (_groupKey && !_groupKey->isEmpty()) {
174 groupKey = *_groupKey;
175 }
176 else {
177 TQString groupPrefix;
178 const TQStringList groups(config.groupList());
179 if (overwriteFirstGroup && !groups.isEmpty()) {
180// groupKey = groups.first(); //found
181 foreach (TQStringList::ConstIterator, it, groups) {
182 if ((*it).lower()!="file information") {
183 groupKey = *it;
184 break;
185 }
186 }
187 }
188
189 if (groupKey.isEmpty()) {
190 //find a new unique name
191 if (thisIsConnectionData)
192 groupPrefix = "Connection%1"; //do not i18n!
193 else
194 groupPrefix = "Database%1"; //do not i18n!
195
196 int number = 1;
197 while (config.hasGroup(groupPrefix.arg(number))) //a new group key couldn't exist
198 number++;
199 groupKey = groupPrefix.arg(number);
200 }
201 if (_groupKey) //return this one (generated or found)
202 *_groupKey = groupKey;
203 }
204
205 config.deleteGroup(groupKey);
206 config.setGroup(groupKey);
207 if (thisIsConnectionData) {
208 config.writeEntry("type", "connection");
209 config.writeEntry("caption", data.constConnectionData()->caption);
210 if (!data.constConnectionData()->description.isEmpty())
211 config.writeEntry("comment", data.constConnectionData()->description);
212 }
213 else {//database
214 config.writeEntry("type", "database");
215 config.writeEntry("caption", data.caption());
216 config.writeEntry("name", data.databaseName());
217 if (!data.description().isEmpty())
218 config.writeEntry("comment", data.description());
219 }
220
221 config.writeEntry("engine", data.constConnectionData()->driverName);
222 if (!data.constConnectionData()->hostName.isEmpty())
223 config.writeEntry("server", data.constConnectionData()->hostName);
224
225 if (data.constConnectionData()->port!=0)
226 config.writeEntry("port", data.constConnectionData()->port);
227 config.writeEntry("useLocalSocketFile", data.constConnectionData()->useLocalSocketFile);
228 if (!data.constConnectionData()->localSocketFileName.isEmpty())
229 config.writeEntry("localSocketFile", data.constConnectionData()->localSocketFileName);
230
231 if (savePassword || data.constConnectionData()->savePassword) {
232 if (realFormatVersion < 2) {
233 config.writeEntry("password", data.constConnectionData()->password);
234 }
235 else {
236 TQString encryptedPassword = data.constConnectionData()->password;
237 KexiUtils::simpleCrypt(encryptedPassword);
238 config.writeEntry("encryptedPassword", encryptedPassword);
239 encryptedPassword.fill(' '); //for security
240 }
241 }
242
243 if (!data.constConnectionData()->userName.isEmpty())
244 config.writeEntry("user", data.constConnectionData()->userName);
245/* @todo add "options=", eg. as string list? */
246 config.sync();
247 return true;
248}
249
251{
252 return d->fileName;
253}
254
255//---------------------------------------------
256
258 : KexiDBShortcutFile( fileName )
259{
260}
261
262KexiDBConnShortcutFile::~KexiDBConnShortcutFile()
263{
264}
265
267{
268 KexiProjectData pdata(data);
269 if (!loadProjectData(pdata, _groupKey))
270 return false;
271 data = *pdata.connectionData();
272 return true;
273}
274
276 bool savePassword, TQString* groupKey, bool overwriteFirstGroup)
277{
278 KexiProjectData pdata(data);
279 return saveProjectData(pdata, savePassword, groupKey, overwriteFirstGroup);
280}
281
282//---------------------------------------------
283
284#if 0
286bool KexiDBConnSetShortcutFiles::loadConnectionDataSet(KexiDBConnectionSet& set)
287{
288 set.clear();
289// TQStringList dirs( TDEGlobal::dirs()->findDirs("data", "kexi/connections") );
290// kexidbg << dirs << endl;
291 TQStringList files( TDEGlobal::dirs()->findAllResources("data", "kexi/connections/*.kexic") );
292// //also try for capital file extension
293// files += TDEGlobal::dirs()->findAllResources("data", "kexi/connections/*.KEXIC");
294 kexidbg << files << endl;
295
296 foreach(TQStringList::ConstIterator, it, files) {
298 KexiDBConnShortcutFile shortcutFile( *it );
299 if (!shortcutFile.loadConnectionData(*data)) {
300 delete data;
301 continue;
302 }
303 set.addConnectionData(data);
304 }
305}
306
307
310bool KexiDBConnSetShortcutFiles::saveConnectionDataSet(const KexiDBConnectionSet& set)
311{
312}
313
314#endif
KexiDBConnShortcutFile(const TQString &fileName)
bool saveConnectionData(const KexiDB::ConnectionData &data, bool savePassword, TQString *groupKey=0, bool overwriteFirstGroup=true)
bool loadConnectionData(KexiDB::ConnectionData &data, TQString *groupKey=0)
bool addConnectionData(KexiDB::ConnectionData *data, const TQString &filename=TQString())
bool saveProjectData(const KexiProjectData &data, bool savePassword, TQString *groupKey=0, bool overwriteFirstGroup=true)
bool loadProjectData(KexiProjectData &data, TQString *groupKey=0)
TQString fileName() const
KexiDBShortcutFile(const TQString &fileName)
bool savePassword
True if password should be saved to a file for the connection.
TQString caption
The caption of the connection.
TQString localSocketFileName
Name of local (named) socket file.
TQString description
The additional description for the connection.
TQString userName
Username used for the connection.
TQString password
Password used for the connection.
TQString driverName
the name of the driver that should be used to create a connection
unsigned short int port
Port used for the remote connection.
TQString hostName
Host name used for the remote connection.
bool useLocalSocketFile
True if local socket file should be used instead of TCP/IP port.
Database specific connection data, e.g. host, port.
void setFileName(const TQString &fn)
Set the filename used by the connection.
Kexi project core data member.
TQString databaseName() const
KEXIUTILS_EXPORT void simpleCrypt(TQString &string)
KEXIUTILS_EXPORT void simpleDecrypt(TQString &string)