--- /dev/null +++ src/include/frmGrantWizard.h @@ -0,0 +1,54 @@ +////////////////////////////////////////////////////////////////////////// +// +// pgAdmin III - PostgreSQL Tools +// RCS-ID: $Id: frmGrantWizard.h,v 1.1 2004/06/06 19:42:00 andreas Exp $ +// Copyright (C) 2002 - 2004, The pgAdmin Development Team +// This software is released under the Artistic Licence +// +// frmGrantWizard.h - Grant Wizard Dialogue +// +////////////////////////////////////////////////////////////////////////// + +#ifndef FRMGRANTWIZARD_H +#define FRMGRANTWIZARD_H + +// wxWindows headers +#include + + +// App headers +#include "pgAdmin3.h" +#include "frmMain.h" +#include "dlgClasses.h" + + +class ctlSecurityPanel; + + +class frmGrantWizard : public ExecutionDialog +{ +public: + frmGrantWizard(frmMain *form, pgObject *_object); + ~frmGrantWizard(); + + void Go(); + wxString GetSql(); + wxString GetHelpPage() const; + +private: + + void OnPageSelect(wxNotebookEvent& event); + void OnCheckAll(wxCommandEvent &event); + void OnUncheckAll(wxCommandEvent &event); + + void AddObjects(pgCollection *collection); + + wxArrayPtrVoid objectArray; + ctlSQLBox *sqlPane; + wxNotebook *nbNotebook; + ctlSecurityPanel *securityPage; + + DECLARE_EVENT_TABLE() +}; + +#endif --- /dev/null +++ src/include/dlgClasses.h @@ -0,0 +1,60 @@ +////////////////////////////////////////////////////////////////////////// +// +// pgAdmin III - PostgreSQL Tools +// RCS-ID: $Id: dlgClasses.h,v 1.1 2004/06/06 19:42:00 andreas Exp $ +// Copyright (C) 2002 - 2004, The pgAdmin Development Team +// This software is released under the Artistic Licence +// +// dlgClasses.h - Some dialogue base classes +// +////////////////////////////////////////////////////////////////////////// + +#ifndef DLGCLASSES_H +#define DLGCLASSES_H + +#include + + +#define btnOK CTRL_BUTTON("btnOK") +#define btnCancel CTRL_BUTTON("btnCancel") + + + +class frmMain; + +class DialogWithHelp : public wxDialog +{ +public: + DialogWithHelp(frmMain *frame); + +protected: + frmMain *mainForm; + void OnHelp(wxCommandEvent& ev); + + +private: + virtual wxString GetHelpPage() const = 0; + DECLARE_EVENT_TABLE(); +}; + +class ExecutionDialog : public DialogWithHelp +{ +public: + ExecutionDialog(frmMain *frame, pgObject *_object); + virtual wxString GetSql()=0; + + void OnOK(wxCommandEvent& ev); + void OnCancel(wxCommandEvent& ev); + void OnClose(wxCloseEvent& event); + + void Abort(); + +protected: + pgObject *object; + pgQueryThread *thread; + wxTextCtrl *txtMessages; + +private: + DECLARE_EVENT_TABLE(); +}; +#endif --- /dev/null +++ src/include/ctlSecurityPanel.h @@ -0,0 +1,75 @@ +////////////////////////////////////////////////////////////////////////// +// +// pgAdmin III - PostgreSQL Tools +// RCS-ID: $Id: ctlSecurityPanel.h,v 1.1 2004/06/06 19:42:00 andreas Exp $ +// Copyright (C) 2002 - 2004, The pgAdmin Development Team +// This software is released under the Artistic Licence +// +// ctlSecurityPanel.h - Panel with security information +// +////////////////////////////////////////////////////////////////////////// + + +#ifndef CTL_SECPANEL_H +#define CTL_SECPANEL_H + +#include +#include + +enum +{ + CTL_PROPSQL=250, + CTL_MSG, + CTL_LBPRIV, + CTL_STATICGROUP, + CTL_CBGROUP, + CTL_ADDPRIV, + CTL_DELPRIV, + CTL_ALLPRIV, + CTL_ALLPRIVGRANT, + CTL_PRIVCB // base for all privilege checkboxes, must be last +}; + + +class pgConn; + +class ctlSecurityPanel : public wxPanel +{ + +public: + + ctlSecurityPanel(wxNotebook *nb, const wxString &privList, char *privChars, wxImageList *imgList); + ~ctlSecurityPanel(); + + ctlListView *lbPrivileges; + wxComboBox *cbGroups; + wxStaticText *stGroup; + void SetConnection(pgConn *conn) { connection=conn; } + wxString GetGrant(const wxString &allPattern, const wxString &grantObject, wxArrayString *currentAcl=0); +protected: + wxNotebook *nbNotebook; + pgConn *connection; + + wxButton *btnAddPriv, *btnDelPriv; + int privilegeCount; + char *privilegeChars; + wxCheckBox **privCheckboxes; + wxCheckBox *allPrivileges, *allPrivilegesGrant; + + void OnPrivSelChange(wxListEvent &ev); + void OnAddPriv(wxCommandEvent& ev); + void OnDelPriv(wxCommandEvent& ev); + void OnPrivCheck(wxCommandEvent& ev); + void OnPrivCheckAll(wxCommandEvent& ev); + void OnPrivCheckAllGrant(wxCommandEvent& ev); + + void CheckGrantOpt(int index); + bool GrantAllowed() const; + + + DECLARE_EVENT_TABLE(); +}; + + + +#endif \ No newline at end of file --- /dev/null +++ src/ui/frmGrantWizard.cpp @@ -0,0 +1,236 @@ +////////////////////////////////////////////////////////////////////////// +// +// pgAdmin III - PostgreSQL Tools +// RCS-ID: $Id: frmGrantWizard.cpp,v 1.1 2004/06/06 19:42:00 andreas Exp $ +// Copyright (C) 2002 - 2004, The pgAdmin Development Team +// This software is released under the Artistic Licence +// +// frmGrantWizard.cpp - Grant Wizard dialogue +// +////////////////////////////////////////////////////////////////////////// + +// wxWindows headers +#include +#include +#include + + +// App headers +#include "pgAdmin3.h" +#include "frmGrantWizard.h" +#include "sysLogger.h" +#include "pgFunction.h" +#include "ctlSecurityPanel.h" + +// Icons +#include "images/index.xpm" + + +#define chkList CTRL_CHECKLISTBOX("chkList") + + + +BEGIN_EVENT_TABLE(frmGrantWizard, ExecutionDialog) + EVT_NOTEBOOK_PAGE_CHANGED(XRCID("nbNotebook"), frmGrantWizard::OnPageSelect) + EVT_BUTTON(XRCID("btnChkAll"), frmGrantWizard::OnCheckAll) + EVT_BUTTON(XRCID("btnUnchkAll"), frmGrantWizard::OnUncheckAll) +END_EVENT_TABLE() + + +frmGrantWizard::frmGrantWizard(frmMain *form, pgObject *obj) : ExecutionDialog(form, obj) +{ + wxLogInfo(wxT("Creating a grant wizard dialogue for %s %s"), object->GetTypeName().c_str(), object->GetFullName().c_str()); + + nbNotebook = 0; + + wxWindowBase::SetFont(settings->GetSystemFont()); + wxXmlResource::Get()->LoadDialog(this, form, wxT("frmGrantWizard")); + SetTitle(wxString::Format(_("Privileges for %s %s"), object->GetTypeName().c_str(), object->GetFullIdentifier().c_str())); + + // Icon + SetIcon(wxIcon(index_xpm)); + nbNotebook = CTRL_NOTEBOOK("nbNotebook"); + sqlPane = 0; + + CenterOnParent(); +} + + +frmGrantWizard::~frmGrantWizard() +{ + wxLogInfo(wxT("Destroying a grant wizard dialogue")); + Abort(); +} + + +wxString frmGrantWizard::GetHelpPage() const +{ + wxString page=wxT("sql-grant"); + + return page; +} + + + +void frmGrantWizard::OnUncheckAll(wxCommandEvent& event) +{ + int i; + for (i=0 ; i < chkList->GetCount() ; i++) + chkList->Check(i, false); +} + + + +void frmGrantWizard::OnCheckAll(wxCommandEvent& event) +{ + int i; + for (i=0 ; i < chkList->GetCount() ; i++) + chkList->Check(i, true); +} + + +void frmGrantWizard::OnPageSelect(wxNotebookEvent& event) +{ + if (nbNotebook && sqlPane && event.GetSelection() == (int)nbNotebook->GetPageCount()-2) + { + sqlPane->SetReadOnly(false); + sqlPane->SetText(GetSql()); + sqlPane->SetReadOnly(true); + } +} + + +void frmGrantWizard::AddObjects(pgCollection *collection) +{ + bool traverseKids = (!collection->IsCollection() || collection->GetType() == PG_SCHEMAS); + + if (!traverseKids) + { + if (!collection->IsCollectionForType(PG_TABLE) && + !collection->IsCollectionForType(PG_FUNCTION) && + !collection->IsCollectionForType(PG_TRIGGERFUNCTION) && + !collection->IsCollectionForType(PG_VIEW) && + !collection->IsCollectionForType(PG_SEQUENCE)) + return; + } + wxCookieType cookie; + wxTreeItemId item=mainForm->GetBrowser()->GetFirstChild(collection->GetId(), cookie); + + while (item) + { + pgObject *obj=(pgObject*)mainForm->GetBrowser()->GetItemData(item); + if (obj) + { + if (traverseKids) + AddObjects((pgCollection*)obj); + else + { + objectArray.Add(obj); + chkList->Append(obj->GetTypeName() + wxT(" ") + obj->GetFullIdentifier()); + } + } + item=mainForm->GetBrowser()->GetNextChild(collection->GetId(), cookie); + } + +} + +void frmGrantWizard::Go() +{ + chkList->SetFocus(); + + wxString privList = wxT("INSERT,SELECT,UPDATE,DELETE,RULE,REFERENCES,TRIGGER"); + char *privChar="arwdRxt"; + switch (object->GetType()) + { + case PG_DATABASE: + case PG_SCHEMAS: + case PG_SCHEMA: + privList.Append(wxT(",EXECUTE")); + privChar = "arwdRxtX"; + break; + case PG_FUNCTIONS: + case PG_TRIGGERFUNCTIONS: + privList = wxT(",EXECUTE"); + privChar = "X"; + break; + default: + break; + } + + + securityPage = new ctlSecurityPanel(nbNotebook, privList, privChar, mainForm->GetImageList()); + securityPage->SetConnection(object->GetConnection()); + + sqlPane = new ctlSQLBox(nbNotebook, CTL_PROPSQL, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxSUNKEN_BORDER | wxTE_READONLY | wxTE_RICH2); + nbNotebook->AddPage(sqlPane, wxT("SQL")); + + txtMessages = new wxTextCtrl(nbNotebook, CTL_MSG, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL); + nbNotebook->AddPage(txtMessages, _("Messages")); + + AddObjects((pgCollection*)object); + + + if (securityPage->cbGroups) + { + pgSet *set=object->GetConnection()->ExecuteSet(wxT("SELECT groname FROM pg_group ORDER BY groname")); + + if (set) + { + while (!set->Eof()) + { + securityPage->cbGroups->Append(wxT("group ") + set->GetVal(0)); + set->MoveNext(); + } + delete set; + } + + if (settings->GetShowUsersForPrivileges()) + { + set=object->GetConnection()->ExecuteSet(wxT("SELECT usename FROM pg_user ORDER BY usename")); + + if (set) + { + securityPage->stGroup->SetLabel(_("Group/User")); + + while (!set->Eof()) + { + securityPage->cbGroups->Append(set->GetVal(0)); + set->MoveNext(); + } + delete set; + } + } + } + + Show(true); +} + + +wxString frmGrantWizard::GetSql() +{ + wxString sql; + + int i; + for (i=0 ; i < chkList->GetCount() ; i++) + { + if (chkList->IsChecked(i)) + { + wxString tmp; + + pgObject *obj=(pgObject*)objectArray.Item(i); + + if (obj->GetType() == PG_FUNCTION || obj->GetType() == PG_TRIGGERFUNCTION) + { + tmp = securityPage->GetGrant(wxT("X"), wxT("FUNCTION ") + + obj->GetQuotedFullIdentifier() + wxT("(") + + ((pgFunction*)obj)->GetArgTypes() + wxT(")")); + } + else + tmp = securityPage->GetGrant(wxT("arwdRxt"), obj->GetTypeName().Upper() + wxT(" ") + obj->GetQuotedFullIdentifier()); + + if (!tmp.IsEmpty()) + sql.Append(tmp); + } + } + return sql; +} \ No newline at end of file --- /dev/null +++ src/ui/dlgClasses.cpp @@ -0,0 +1,168 @@ +////////////////////////////////////////////////////////////////////////// +// +// pgAdmin III - PostgreSQL Tools +// RCS-ID: $Id: dlgClasses.cpp,v 1.1 2004/06/06 19:42:00 andreas Exp $ +// Copyright (C) 2002 - 2004, The pgAdmin Development Team +// This software is released under the Artistic Licence +// +// dlgClasses.cpp - Some dialogue base classes +// +////////////////////////////////////////////////////////////////////////// + +// wxWindows headers +#include +#include +#include + + +// App headers +#include "pgAdmin3.h" +#include "frmMain.h" +#include "dlgClasses.h" +#include "pgConn.h" + +#include "menu.h" + + +BEGIN_EVENT_TABLE(DialogWithHelp, wxDialog) + EVT_MENU(MNU_HELP, DialogWithHelp::OnHelp) + EVT_BUTTON(XRCID("btnHelp"), DialogWithHelp::OnHelp) +END_EVENT_TABLE(); + + +DialogWithHelp::DialogWithHelp(frmMain *frame) : wxDialog() +{ + mainForm = frame; + + wxAcceleratorEntry entries[2]; + entries[0].Set(wxACCEL_NORMAL, WXK_F1, MNU_HELP); +// this is for GTK because Meta (usually Numlock) is interpreted like Alt +// there are too many controls to reset m_Meta in all of them + entries[1].Set(wxACCEL_ALT, WXK_F1, MNU_HELP); + wxAcceleratorTable accel(2, entries); + + SetAcceleratorTable(accel); +} + + +void DialogWithHelp::OnHelp(wxCommandEvent& ev) +{ + wxString page=GetHelpPage(); + + if (!page.IsEmpty()) + DisplaySqlHelp(this, page); +} + + + +////////////////////////////////////////////////////////////////77 + + +BEGIN_EVENT_TABLE(ExecutionDialog, DialogWithHelp) + EVT_BUTTON (XRCID("btnOK"), ExecutionDialog::OnOK) + EVT_BUTTON (XRCID("btnCancel"), ExecutionDialog::OnCancel) + EVT_CLOSE( ExecutionDialog::OnClose) +END_EVENT_TABLE() + + +ExecutionDialog::ExecutionDialog(frmMain *frame, pgObject *_object) : DialogWithHelp(frame) +{ + thread=0; + object = _object; + txtMessages = 0; +} + + +void ExecutionDialog::OnClose(wxCloseEvent& event) +{ + Abort(); + Destroy(); +} + + +void ExecutionDialog::OnCancel(wxCommandEvent& ev) +{ + if (thread) + { + btnCancel->Disable(); + Abort(); + btnCancel->Enable(); + btnOK->Enable(); + } + else + { + Destroy(); + } +} + + +void ExecutionDialog::Abort() +{ + if (thread) + { + if (thread->IsRunning()) + thread->Delete(); + delete thread; + thread=0; + } +} + + +void ExecutionDialog::OnOK(wxCommandEvent& ev) +{ + if (!thread) + { + wxString sql=GetSql(); + if (sql.IsEmpty()) + return; + + btnOK->Disable(); + + thread=new pgQueryThread(object->GetConnection(), sql); + if (thread->Create() != wxTHREAD_NO_ERROR) + { + Abort(); + return; + } + + wxLongLong startTime=wxGetLocalTimeMillis(); + thread->Run(); + + while (thread && thread->IsRunning()) + { + wxUsleep(10); + // here could be the animation + if (txtMessages) + txtMessages->AppendText(thread->GetMessagesAndClear()); + wxYield(); + } + + if (thread) + { + if (txtMessages) + txtMessages->AppendText(thread->GetMessagesAndClear()); + + if (thread->DataSet() != NULL) + wxLogDebug(wxString::Format(_("%d rows."), thread->DataSet()->NumRows())); + + if (txtMessages) + txtMessages->AppendText(_("Total query runtime: ") + + (wxGetLocalTimeMillis()-startTime).ToString() + wxT(" ms.")); + + btnOK->SetLabel(_("Done")); + btnCancel->Disable(); + } + else + if (txtMessages) + txtMessages->AppendText(_("\nCancelled.\n")); + + btnOK->Enable(); + } + else + { + Abort(); + Destroy(); + } +} + + --- /dev/null +++ src/ui/ctlSecurityPanel.cpp @@ -0,0 +1,356 @@ +////////////////////////////////////////////////////////////////////////// +// +// pgAdmin III - PostgreSQL Tools +// RCS-ID: $Id: ctlSecurityPanel.cpp,v 1.1 2004/06/06 19:42:00 andreas Exp $ +// Copyright (C) 2002 - 2004, The pgAdmin Development Team +// This software is released under the Artistic Licence +// +// ctlSecurityPanel.cpp - Panel with security information +// +////////////////////////////////////////////////////////////////////////// + + +// wxWindows headers +#include +#include + +// App headers +#include "pgAdmin3.h" +#include "sysLogger.h" +#include "ctlSecurityPanel.h" +#include "pgConn.h" +#include "pgObject.h" + + + +BEGIN_EVENT_TABLE(ctlSecurityPanel, wxPanel) + EVT_LIST_ITEM_SELECTED(CTL_LBPRIV, ctlSecurityPanel::OnPrivSelChange) + EVT_BUTTON(CTL_ADDPRIV, ctlSecurityPanel::OnAddPriv) + EVT_BUTTON(CTL_DELPRIV, ctlSecurityPanel::OnDelPriv) + EVT_CHECKBOX(CTL_ALLPRIV, ctlSecurityPanel::OnPrivCheckAll) + EVT_CHECKBOX(CTL_ALLPRIVGRANT, ctlSecurityPanel::OnPrivCheckAllGrant) + EVT_CHECKBOX(CTL_PRIVCB, ctlSecurityPanel::OnPrivCheck) + EVT_CHECKBOX(CTL_PRIVCB+2, ctlSecurityPanel::OnPrivCheck) + EVT_CHECKBOX(CTL_PRIVCB+4, ctlSecurityPanel::OnPrivCheck) + EVT_CHECKBOX(CTL_PRIVCB+6, ctlSecurityPanel::OnPrivCheck) + EVT_CHECKBOX(CTL_PRIVCB+8, ctlSecurityPanel::OnPrivCheck) + EVT_CHECKBOX(CTL_PRIVCB+10, ctlSecurityPanel::OnPrivCheck) + EVT_CHECKBOX(CTL_PRIVCB+12, ctlSecurityPanel::OnPrivCheck) + EVT_CHECKBOX(CTL_PRIVCB+14, ctlSecurityPanel::OnPrivCheck) +END_EVENT_TABLE(); + + + + + +ctlSecurityPanel::ctlSecurityPanel(wxNotebook *nb, const wxString &privList, char *privChars, wxImageList *imgList) +: wxPanel(nb, -1, wxDefaultPosition, wxDefaultSize) +{ + nbNotebook = nb; + nbNotebook->AddPage(this, _("Security")); + + connection = 0; + privilegeChars=privChars; + allPrivileges=0; + + privCheckboxes=0; + + wxStringTokenizer privileges(privList, wxT(",")); + privilegeCount=privileges.CountTokens(); + + + if (privilegeCount) + { + bool needAll=(privilegeCount > 1); + privCheckboxes = new wxCheckBox*[privilegeCount*2]; + int i=0; + + long chkFlags=0; + int width, height; + GetClientSize(&width, &height); + + wxPoint zeroPos=ConvertDialogToPixels(wxPoint(5, 5)); + wxSize chkSize=ConvertDialogToPixels(wxSize(65,12)); + wxSize btnSize=ConvertDialogToPixels(wxSize(50,15)); + wxSize spcSize=ConvertDialogToPixels(wxSize(2, 2)); + + { + int y = height + - spcSize.GetHeight() + - zeroPos.y * 2 + - chkSize.GetHeight() * (4 + privilegeCount + (needAll ? 0 : 1)); + + lbPrivileges = new ctlListView(this, CTL_LBPRIV, + zeroPos, + wxSize(width - zeroPos.x * 2, y - zeroPos.y - spcSize.GetHeight()), wxSUNKEN_BORDER|wxLC_REPORT); + + lbPrivileges->CreateColumns(imgList, _("User/Group"), _("Privileges"), -1); + + btnAddPriv = new wxButton(this, CTL_ADDPRIV, _("Add/Change"), + wxPoint(zeroPos.x, y), btnSize); + btnDelPriv = new wxButton(this, CTL_DELPRIV, _("Remove"), + wxPoint(zeroPos.x * 2 + btnSize.GetWidth(), y), btnSize); + y += zeroPos.y + btnSize.GetHeight(); + + new wxStaticBox(this, -1, _("Privileges"), + wxPoint(zeroPos.x, y), + wxSize(width - zeroPos.x*2, btnSize.GetHeight() + chkSize.GetHeight() * (2 + privilegeCount-(needAll?0:1)))); + y += zeroPos.y + spcSize.GetHeight(); + + stGroup = new wxStaticText(this, CTL_STATICGROUP, _("Group"), wxPoint(zeroPos.x * 2, y+3), chkSize); + cbGroups = new wxComboBox(this, CTL_CBGROUP, wxT(""), + wxPoint(zeroPos.x * 3 + chkSize.GetWidth(), y), + wxSize(width - zeroPos.x * 4 - chkSize.GetWidth() - spcSize.GetWidth(), chkSize.GetHeight())); + y += btnSize.GetHeight(); + cbGroups->Append(wxT("public")); + cbGroups->SetSelection(0); + + + if (needAll) + { + allPrivileges = new wxCheckBox(this, CTL_ALLPRIV, wxT("ALL"), + wxPoint(zeroPos.x * 2, y), + chkSize); + allPrivilegesGrant = new wxCheckBox(this, CTL_ALLPRIVGRANT, wxT("WITH GRANT OPTION"), + wxPoint(zeroPos.x * 3 + chkSize.GetWidth(), y), + wxSize(width - zeroPos.x * 4 - chkSize.GetWidth() - spcSize.GetWidth(), chkSize.GetHeight())); + y += chkSize.GetHeight(); + allPrivilegesGrant->Disable(); + } + + while (privileges.HasMoreTokens()) + { + wxString priv=privileges.GetNextToken(); + wxCheckBox *cb; + cb=new wxCheckBox(this, CTL_PRIVCB+i, priv, + wxPoint(zeroPos.x * 2, y), + chkSize); + privCheckboxes[i++] = cb; + cb=new wxCheckBox(this, CTL_PRIVCB+i, wxT("WITH GRANT OPTION"), + wxPoint(zeroPos.x * 3 + chkSize.GetWidth(), y), + wxSize(width - zeroPos.x * 4 - chkSize.GetWidth() - spcSize.GetWidth(), chkSize.GetHeight())); + cb->Disable(); + privCheckboxes[i++] = cb; + + y += chkSize.GetHeight(); + } + } + + } +} + + +ctlSecurityPanel::~ctlSecurityPanel() +{ + if (privCheckboxes) + delete[] privCheckboxes; +} + + + + +wxString ctlSecurityPanel::GetGrant(const wxString &allPattern, const wxString &grantObject, wxArrayString *currentAcl) +{ + wxArrayString tmpAcl; + if (currentAcl) + tmpAcl = *currentAcl; + + wxString sql; + int cnt=lbPrivileges->GetItemCount(); + int pos; + unsigned int i; + + for (pos=0 ; pos < cnt ; pos++) + { + wxString name=lbPrivileges->GetText(pos); + wxString value=lbPrivileges->GetText(pos, 1); + + int nameLen=name.Length(); + + bool privWasAssigned=false; + bool privPartiallyAssigned=false; + for (i=0 ; i < tmpAcl.GetCount() ; i++) + { + if (tmpAcl.Item(i).Left(nameLen) == name) + { + privPartiallyAssigned=true; + if (tmpAcl.Item(i).Mid(nameLen+1) == value) + privWasAssigned=true; + tmpAcl.RemoveAt(i); + break; + } + } + + if (name.Left(6).IsSameAs(wxT("group "), false)) + name = wxT("GROUP ") + qtIdent(name.Mid(6)); + else + name=qtIdent(name); + + if (!privWasAssigned) + { + if (privPartiallyAssigned) + sql += pgObject::GetPrivileges(allPattern, wxT(""), grantObject, name); + sql += pgObject::GetPrivileges(allPattern, value, grantObject, name); + } + } + + for (i=0 ; i < tmpAcl.GetCount() ; i++) + { + wxString name=tmpAcl.Item(i).BeforeLast('='); + + if (name.Left(6).IsSameAs(wxT("group "), false)) + name = wxT("GROUP ") + qtIdent(name.Mid(6)); + else + name=qtIdent(name); + sql += pgObject::GetPrivileges(allPattern, wxT(""), grantObject, name); + } + return sql; +} + + +void ctlSecurityPanel::OnPrivCheckAll(wxCommandEvent& ev) +{ + bool all=allPrivileges->GetValue(); + int i; + for (i=0 ; i < privilegeCount ; i++) + { + if (all) + { + privCheckboxes[i*2]->SetValue(true); + privCheckboxes[i*2]->Disable(); + privCheckboxes[i*2+1]->Disable(); + allPrivilegesGrant->Enable(GrantAllowed()); + } + else + { + allPrivilegesGrant->Disable(); + allPrivilegesGrant->SetValue(false); + privCheckboxes[i*2]->Enable(); + CheckGrantOpt(i); + } + } +} + + + +void ctlSecurityPanel::OnPrivCheckAllGrant(wxCommandEvent& ev) +{ + bool grant=allPrivilegesGrant->GetValue(); + int i; + for (i=0 ; i < privilegeCount ; i++) + privCheckboxes[i*2+1]->SetValue(grant); +} + + +void ctlSecurityPanel::OnPrivCheck(wxCommandEvent& ev) +{ + int id=(ev.GetId()-CTL_PRIVCB) /2; + CheckGrantOpt(id); +} + + +void ctlSecurityPanel::CheckGrantOpt(int id) +{ + bool canGrant=(GrantAllowed() && privCheckboxes[id*2]->GetValue()); + if (canGrant) + privCheckboxes[id*2+1]->Enable(); + else + { + privCheckboxes[id*2+1]->SetValue(false); + privCheckboxes[id*2+1]->Disable(); + } +} + + +void ctlSecurityPanel::OnDelPriv(wxCommandEvent &ev) +{ + lbPrivileges->DeleteCurrentItem(); +} + + +void ctlSecurityPanel::OnAddPriv(wxCommandEvent &ev) +{ + wxString name=cbGroups->GetValue(); + + long pos=lbPrivileges->FindItem(-1, name); + if (pos < 0) + { + pos = lbPrivileges->GetItemCount(); + int icon=PGICON_USER; + + if (name.Left(6).IsSameAs(wxT("group "), false)) + icon = PGICON_GROUP; + else if (name.IsSameAs(wxT("public"), false)) + icon = PGICON_PUBLIC; + + lbPrivileges->InsertItem(pos, name, icon); + } + wxString value; + int i; + for (i=0 ; i < privilegeCount ; i++) + { + if (privCheckboxes[i*2]->GetValue()) + { + value += privilegeChars[i]; + if (privCheckboxes[i*2+1]->GetValue()) + value += '*'; + } + } + lbPrivileges->SetItem(pos, 1, value); +} + + +void ctlSecurityPanel::OnPrivSelChange(wxListEvent &ev) +{ + if (!cbGroups) + return; + if (allPrivileges) + { + allPrivileges->SetValue(false); + allPrivilegesGrant->SetValue(false); + allPrivilegesGrant->Disable(); + } + long pos=lbPrivileges->GetSelection(); + if (pos >= 0) + { + wxString name=lbPrivileges->GetText(pos); + wxString value=lbPrivileges->GetText(pos, 1); + + pos=cbGroups->FindString(name); + if (pos < 0) + { + cbGroups->Append(name); + pos=cbGroups->GetCount()-1; + } + cbGroups->SetSelection(pos); + + int i; + for (i=0 ; i < privilegeCount ; i++) + { + privCheckboxes[i*2]->Enable(); + int index=value.Find(privilegeChars[i]); + if (index >= 0) + { + privCheckboxes[i*2]->SetValue(true); + privCheckboxes[i*2+1]->SetValue(value.Mid(index+1, 1) == wxT("*")); + } + else + privCheckboxes[i*2]->SetValue(false); + CheckGrantOpt(i); + } + } +} + + + +bool ctlSecurityPanel::GrantAllowed() const +{ + if (!connection->BackendMinimumVersion(7, 4)) + return false; + + wxString user=cbGroups->GetValue(); + if (user.Left(6).IsSameAs(wxT("group "), false) || user.IsSameAs(wxT("public"), false)) + return false; + + return true; +}