1 //////////////////////////////////////////////////////////////////////////
2 //
3 // pgAdmin III - PostgreSQL Tools
4 //
5 // Copyright (C) 2002 - 2016, The pgAdmin Development Team
6 // This software is released under the PostgreSQL Licence
7 //
8 // dlgSelectDatabase.cpp - Database Selection for connection string
9 //
10 //////////////////////////////////////////////////////////////////////////
11
12 // App headers
13 #include "pgAdmin3.h"
14
15 #include <wx/regex.h>
16
17 #include "utils/misc.h"
18 #include "dlg/dlgSelectDatabase.h"
19 #include "schema/pgServer.h"
20 #include "schema/pgDatabase.h"
21 #include "frm/frmMain.h"
22
23 extern frmMain *winMain;
24 wxWindowID TCSERVER_ID = ::wxNewId();
25
BEGIN_EVENT_TABLE(dlgSelectDatabase,wxDialog)26 BEGIN_EVENT_TABLE(dlgSelectDatabase, wxDialog)
27 EVT_TREE_ITEM_ACTIVATED (TCSERVER_ID, dlgSelectDatabase::OnSelActivate)
28 EVT_TREE_SEL_CHANGED (TCSERVER_ID, dlgSelectDatabase::OnSelect)
29 END_EVENT_TABLE()
30
31
32 dlgSelectDatabase::dlgSelectDatabase(wxWindow *parent, int id, const wxPoint &pos, const wxSize &size, long style):
33 wxDialog(parent, id, wxT("Select Database"), pos, size, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
34 {
35
36 #ifdef __WXMSW__
37 SetWindowStyleFlag(GetWindowStyleFlag() & ~wxMAXIMIZE_BOX);
38 #endif
39
40 wxBoxSizer *mainSizer = new wxBoxSizer(wxVERTICAL);
41
42 tcServers = new wxTreeCtrl(this, TCSERVER_ID);
43 mainSizer->Add(tcServers, 1, wxEXPAND, 0);
44
45 wxBoxSizer *bottomSizer = new wxBoxSizer(wxHORIZONTAL);
46
47 bottomSizer->AddStretchSpacer();
48
49 wxButton *btnOk = new wxButton(this, wxID_OK, wxT("&OK"));
50 bottomSizer->Add(btnOk);
51
52 wxButton *btnCANCEL = new wxButton(this, wxID_CANCEL, wxT("&Cancel"));
53 bottomSizer->Add(btnCANCEL, 0, wxLEFT, 10);
54
55 mainSizer->Add(bottomSizer, 0, wxALL | wxALIGN_RIGHT, 5);
56 SetSizer(mainSizer);
57
58 SetSize(wxSize(200, 240));
59
60 Layout();
61 Centre();
62
63 Initialize();
64 }
65
Initialize()66 void dlgSelectDatabase::Initialize()
67 {
68 // Add the root node
69 pgServerCollection *serversObj = new pgServerCollection(serverFactory.GetCollectionFactory());
70 wxTreeItemId rootItemID = tcServers->AddRoot(wxGetTranslation(serverFactory.GetCollectionFactory()->GetTypeName()),
71 serversObj->GetIconId(), -1, serversObj);
72 tcServers->SetImageList(imageList);
73
74 ctlTree *browser = winMain->GetBrowser();
75
76 wxTreeItemId servers = tcServers->GetRootItem();
77
78 wxTreeItemIdValue foldercookie;
79 wxTreeItemId folderitem = browser->GetFirstChild(browser->GetRootItem(), foldercookie);
80 while (folderitem)
81 {
82 if (browser->ItemHasChildren(folderitem))
83 {
84 wxCookieType cookie;
85 wxTreeItemId serverItem = browser->GetFirstChild(folderitem, cookie);
86
87 wxTreeItemId tcGroupsItem = tcServers->AppendItem(rootItemID, browser->GetItemText(folderitem), serversObj->GetIconId());
88 while (serverItem)
89 {
90 pgServer *server = (pgServer *)browser->GetObject(serverItem);
91
92 if (server && server->IsCreatedBy(serverFactory))
93 {
94 dlgSelDBNode *cnInfo = new dlgSelDBNode(server);
95 wxTreeItemId itm = tcServers->AppendItem(tcGroupsItem, server->GetFullName(), server->GetIconId(), -1, cnInfo);
96
97 pgConn *conn = server->connection();
98
99 if (conn && conn->IsAlive())
100 {
101 pgSet *res = conn->ExecuteSet(wxT("SELECT datname, datallowconn FROM pg_catalog.pg_database"));
102 if (res)
103 {
104 while (!res->Eof())
105 {
106 if (res->GetBool(wxT("datallowconn")))
107 {
108 dlgSelDBNode *cnInfo = new dlgSelDBNode(server, res->GetVal(wxT("datname")));
109 tcServers->AppendItem(itm, cnInfo->getDatabase(), databaseFactory.GetIconId(), -1, cnInfo);
110 }
111
112 res->MoveNext();
113 }
114 delete res;
115 }
116 }
117 }
118
119 serverItem = browser->GetNextChild(folderitem, cookie);
120 }
121 folderitem = browser->GetNextChild(browser->GetRootItem(), foldercookie);
122 }
123 }
124
125 tcServers->Expand(servers);
126 selectedConn = NULL;
127 }
128
OnSelect(wxTreeEvent & ev)129 void dlgSelectDatabase::OnSelect(wxTreeEvent &ev)
130 {
131 wxTreeItemId sel = tcServers->GetSelection();
132
133 if (sel.IsOk() && sel != tcServers->GetRootItem() && tcServers->GetItemParent(sel) != tcServers->GetRootItem())
134 {
135 selectedConn = (dlgSelDBNode *)tcServers->GetItemData(sel);
136 }
137 else
138 {
139 selectedConn = NULL;
140 }
141 }
142
OnSelActivate(wxTreeEvent & ev)143 void dlgSelectDatabase::OnSelActivate(wxTreeEvent &ev)
144 {
145 wxTreeItemId selID = tcServers->GetSelection();
146
147 if (selID.IsOk() && selID != tcServers->GetRootItem())
148 {
149 selectedConn = (dlgSelDBNode *)tcServers->GetItemData(selID);
150
151 if (selectedConn->dbname.IsEmpty() && tcServers->GetChildrenCount(selID, false) == 0)
152 {
153 winMain->ReconnectServer(selectedConn->server, true);
154
155 pgConn *conn = selectedConn->server->connection();
156 if (conn && conn->GetStatus() == PGCONN_OK)
157 {
158 pgSet *res = conn->ExecuteSet(wxT("SELECT datname, datallowconn FROM pg_catalog.pg_database"));
159 if (res)
160 {
161 while (!res->Eof())
162 {
163 if (res->GetBool(wxT("datallowconn")))
164 {
165 dlgSelDBNode *cnInfo = new dlgSelDBNode(selectedConn->server, res->GetVal(wxT("datname")));
166 tcServers->AppendItem(selID, cnInfo->getDatabase(), databaseFactory.GetIconId(), -1, cnInfo);
167 }
168
169 res->MoveNext();
170 }
171 }
172 delete res;
173 }
174 tcServers->Expand(selID);
175 }
176 }
177 else
178 {
179 selectedConn = NULL;
180 }
181 }
182
183
getConnInfo()184 wxString dlgSelectDatabase::getConnInfo()
185 {
186 if (selectedConn)
187 {
188 return selectedConn->getConnectionString();
189 }
190
191 return wxEmptyString;
192 }
193
getValidConnectionString(wxString connStr,wxString & resultStr)194 bool dlgSelectDatabase::getValidConnectionString(wxString connStr, wxString &resultStr)
195 {
196 wxString user;
197 wxString dbname;
198 wxString host;
199 unsigned long port = 0;
200 wxString password;
201 unsigned long connection_timeout = 0;
202
203 wxRegEx propertyExp;
204
205 // Remove white-spaces ahead the '="
206 bool res = propertyExp.Compile(wxT("(([ ]*[\t]*)+)="));
207 propertyExp.ReplaceAll(&connStr, wxT("="));
208
209 // Remove white-spaces after the '="
210 res = propertyExp.Compile(wxT("=(([ ]*[\t]*)+)"));
211 propertyExp.ReplaceAll(&connStr, wxT("="));
212 wxArrayString tokens = wxStringTokenize(connStr, wxT("\t \n\r"));
213
214 unsigned int index = 0;
215 while (index < tokens.Count())
216 {
217 wxString prop, value;
218
219 // Find pairs
220 // i.e. user=xxx
221 // password=xxx
222 wxArrayString pairs = wxStringTokenize(tokens[index++], wxT("="));
223
224 // pair must exist in pair=value format
225 if (pairs.GetCount() != 2)
226 return false;
227
228 prop = pairs[0];
229 value = pairs[1];
230
231 if (prop.CmpNoCase(wxT("user")) == 0)
232 user = value;
233 else if (prop.CmpNoCase(wxT("host")) == 0 || prop.CmpNoCase(wxT("hostAddr")) == 0)
234 host = value;
235 else if (prop.CmpNoCase(wxT("port")) == 0)
236 {
237 if (!value.ToULong(&port))
238 // port must be an unsigned integer
239 return false;
240 }
241 else if (prop.CmpNoCase(wxT("password")) == 0)
242 password = value;
243 else if (prop.CmpNoCase(wxT("connection_timeout")) == 0)
244 {
245 if (!value.ToULong(&connection_timeout))
246 // connection timeout must be an unsigned interger
247 return false;
248 }
249 else if (prop.CmpNoCase(wxT("dbname")) == 0)
250 dbname = value;
251 else
252 // Not valid property found
253 return false;
254 }
255
256 if (dbname.IsEmpty())
257 return false;
258
259 if (!user.IsEmpty())
260 resultStr = wxT("user=") + user + wxT(" ");
261
262 if (!host.IsEmpty())
263 {
264 resultStr += wxT("host=") + host + wxT(" ");
265 }
266
267
268 if (!resultStr.IsEmpty())
269 resultStr += wxT(" ");
270 resultStr += wxT("dbname=") + dbname + wxT(" ");
271
272 if (port != 0)
273 {
274 wxString portStr;
275 portStr.Printf(wxT("port=%ld"), port);
276 resultStr += portStr + wxT(" ");
277 }
278
279
280 if (connection_timeout != 0)
281 {
282 wxString strConnTimeOut;
283 strConnTimeOut.Printf(wxT("connection_timeout=%ld"), connection_timeout);
284 resultStr += strConnTimeOut + wxT(" ");
285 }
286
287 if (!password.IsEmpty())
288 {
289 resultStr += wxT("password=") + password + wxT(" ");
290 }
291
292 resultStr = resultStr.Trim();
293
294 return true;
295 }
296
dlgSelDBNode(pgServer * _server,const wxString & _dbname)297 dlgSelDBNode::dlgSelDBNode (pgServer *_server, const wxString &_dbname)
298 {
299 server = _server;
300 dbname = _dbname;
301 }
302
getConnectionString()303 wxString dlgSelDBNode::getConnectionString()
304 {
305 if (dbname.IsEmpty())
306 return wxEmptyString;
307
308 pgConn *conn = server->connection();
309 wxString connStr;
310
311 if (conn && conn->GetStatus() == PGCONN_OK)
312 {
313 connStr += wxT("user=") + conn->GetUser() + wxT(" ");
314 connStr += wxT("host=") + conn->GetHostName() + wxT(" ");
315
316 wxString port;
317 port.Printf(wxT("port=%d "), conn->GetPort());
318 connStr += port;
319
320 connStr += wxT("dbname=") + dbname;
321 }
322
323 return connStr;
324 }
325
326