Index: ctl/ctlDefaultSecurityPanel.cpp
===================================================================
--- ctl/ctlDefaultSecurityPanel.cpp	(revision 0)
+++ ctl/ctlDefaultSecurityPanel.cpp	(revision 0)
@@ -0,0 +1,783 @@
+//////////////////////////////////////////////////////////////////////////
+//
+// pgAdmin III - PostgreSQL Tools
+// RCS-ID:      $Id$
+// Copyright (C) 2002 - 2010, The pgAdmin Development Team
+// This software is released under the PostgreSQL Licence
+//
+// ctlDefaultSecurityPanel.cpp - Panel with default security information
+//
+//////////////////////////////////////////////////////////////////////////
+
+
+// wxWindows headers
+#include <wx/wx.h>
+#include <wx/settings.h>
+#include <wx/imaglist.h>
+
+// App headers
+#include "pgAdmin3.h"
+#include "ctl/ctlDefaultSecurityPanel.h"
+#include "db/pgConn.h"
+#include "dlg/dlgProperty.h"
+#include "schema/pgGroup.h"
+#include "schema/pgUser.h"
+#include "utils/sysLogger.h"
+
+#include <wx/arrimpl.cpp>
+
+defaultPrivilegesOn g_defPrivTables('r', wxT("TABLES"), wxT("arwdDxt")),
+                    g_defPrivSequences('S', wxT("SEQUENCES"), wxT("rwU")),
+                    g_defPrivFunctions('f', wxT("FUNCTIONS"), wxT("X"));
+
+static wxString GetPrivilegeName(wxChar privilege);
+static bool     findUserPrivs(wxString& , wxString&, wxString&);
+
+defaultPrivilegesOn::defaultPrivilegesOn(const wxChar privType, const wxString& privOn, const wxString& privileges)
+  : m_privilegeType(privType), m_privilegesOn(privOn), m_privileges(privileges) {}
+
+ctlDefaultSecurityPanel::ctlDefaultSecurityPanel(pgConn* conn, wxNotebook* nb, wxImageList* imgList)
+  : wxPanel(nb, -1, wxDefaultPosition, wxDefaultSize), m_connection(conn)
+{
+    nb->AddPage(this, _("Default Privileges"));
+
+    wxFlexGridSizer *mainSizer = new wxFlexGridSizer(1, 1, 1, 1);
+    mainSizer->AddGrowableCol(0);
+    mainSizer->AddGrowableRow(0);
+
+    wxStaticBox* sb = new wxStaticBox(this, -1, _("PRIVILEGES ON"));
+    wxBoxSizer* sbSizer = new wxStaticBoxSizer(sb, wxVERTICAL);
+
+    wxFlexGridSizer *notebookSizer  = new wxFlexGridSizer(1, 1, 1, 1);
+    notebookSizer->AddGrowableCol(0);
+    notebookSizer->AddGrowableRow(0);
+
+    nbNotebook = new wxNotebook(this, -1, wxDefaultPosition, wxDefaultSize, 0, _("Privileges On"));
+
+    new ctlDefaultPrivilegesPanel(this, nbNotebook, g_defPrivTables, imgList);
+    new ctlDefaultPrivilegesPanel(this, nbNotebook, g_defPrivSequences, imgList);
+    new ctlDefaultPrivilegesPanel(this, nbNotebook, g_defPrivFunctions, imgList);
+
+    notebookSizer->Add(nbNotebook, 0, wxEXPAND|wxALIGN_CENTRE_VERTICAL|wxTOP|wxLEFT|wxRIGHT, 0);
+    sbSizer->Add(notebookSizer, 0, wxEXPAND|wxALIGN_CENTRE_VERTICAL|wxTOP|wxLEFT|wxRIGHT, 0);
+    mainSizer->Add(sbSizer, 0, wxEXPAND|wxALL, 2);
+    
+    this->SetSizer(mainSizer);
+    notebookSizer->Fit(this);
+
+}
+
+
+void  ctlDefaultSecurityPanel::UpdatePrivilegePages(const wxString& schemaOid)
+{
+    int nPageCount = nbNotebook->GetPageCount();
+    for (int index=0; index < nPageCount; index++)
+    {
+        (dynamic_cast<ctlDefaultPrivilegesPanel *>(nbNotebook->GetPage(index)))->Update(schemaOid);
+    }
+}
+
+
+wxString ctlDefaultSecurityPanel::GetDefaultPrivileges(const wxString& schemaName)
+{
+    wxString strDefPrivs;
+    int nPageCount = nbNotebook->GetPageCount();
+    for (int index=0; index < nPageCount; index++)
+    {
+        strDefPrivs += (dynamic_cast<ctlDefaultPrivilegesPanel *>(nbNotebook->GetPage(index)))->GetDefaultPrivileges(schemaName);
+    }
+    return strDefPrivs;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// ctlDefaultPrivilegesPanel
+///////////////////////////////////////////////////////////////////////////////
+
+BEGIN_EVENT_TABLE(ctlDefaultPrivilegesPanel, wxPanel)
+    EVT_LIST_ITEM_SELECTED(CTL_DEFLBPRIV,  ctlDefaultPrivilegesPanel::OnPrivSelChange)
+    EVT_BUTTON(CTL_DEFADDPRIV,             ctlDefaultPrivilegesPanel::OnAddPriv)
+    EVT_BUTTON(CTL_DEFDELPRIV,             ctlDefaultPrivilegesPanel::OnDelPriv)
+    EVT_TEXT(CTL_DEFCBGROUP,               ctlDefaultPrivilegesPanel::OnGroupChange)
+    EVT_COMBOBOX(CTL_DEFCBGROUP,           ctlDefaultPrivilegesPanel::OnGroupChange)
+    EVT_CHECKBOX(CTL_DEFALLPRIV,           ctlDefaultPrivilegesPanel::OnPrivCheckAll)
+    EVT_CHECKBOX(CTL_DEFALLPRIVGRANT,      ctlDefaultPrivilegesPanel::OnPrivCheckAllGrant)
+    EVT_CHECKBOX(CTL_DEFPRIVCB,            ctlDefaultPrivilegesPanel::OnPrivCheck)
+    EVT_CHECKBOX(CTL_DEFPRIVCB+2,          ctlDefaultPrivilegesPanel::OnPrivCheck)
+    EVT_CHECKBOX(CTL_DEFPRIVCB+4,          ctlDefaultPrivilegesPanel::OnPrivCheck)
+    EVT_CHECKBOX(CTL_DEFPRIVCB+6,          ctlDefaultPrivilegesPanel::OnPrivCheck)
+    EVT_CHECKBOX(CTL_DEFPRIVCB+8,          ctlDefaultPrivilegesPanel::OnPrivCheck)
+    EVT_CHECKBOX(CTL_DEFPRIVCB+10,         ctlDefaultPrivilegesPanel::OnPrivCheck)
+    EVT_CHECKBOX(CTL_DEFPRIVCB+12,         ctlDefaultPrivilegesPanel::OnPrivCheck)
+    EVT_CHECKBOX(CTL_DEFPRIVCB+14,         ctlDefaultPrivilegesPanel::OnPrivCheck)
+    EVT_CHECKBOX(CTL_DEFPRIVCB+16,         ctlDefaultPrivilegesPanel::OnPrivCheck)
+END_EVENT_TABLE();
+
+DEFINE_EVENT_TYPE(EVT_DEFAULTSECURITYPANEL_CHANGE)
+
+ctlDefaultPrivilegesPanel::ctlDefaultPrivilegesPanel(ctlDefaultSecurityPanel *defSecurityPanel, wxNotebook *nb,
+                                                     defaultPrivilegesOn &privOn, wxImageList *imgList)
+  : wxPanel(nb, -1, wxDefaultPosition, wxDefaultSize), m_defPrivChanged(false),
+    m_privilegeType(privOn), m_defSecurityPanel(defSecurityPanel)
+{
+    
+    nb->AddPage(this, m_privilegeType.m_privilegesOn);
+
+    allPrivileges=0;
+    privCheckboxes=0;
+
+    privilegeCount=m_privilegeType.m_privileges.Length();
+    
+    wxFlexGridSizer *item0 = new wxFlexGridSizer(3, 1, 5, 5);
+    item0->AddGrowableCol(0);
+    item0->AddGrowableRow(0);
+
+    privCheckboxes = new wxCheckBox*[privilegeCount*2];
+
+    wxFlexGridSizer *itemSizer1 = new wxFlexGridSizer(1, 1, 5, 5);
+    itemSizer1->AddGrowableCol(0);
+    itemSizer1->AddGrowableRow(0);
+
+    wxString strGroupLabel = settings->GetShowUsersForPrivileges() ? _("Group/User") : _("Group");
+
+    lbPrivileges = new ctlListView(this, CTL_DEFLBPRIV, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER|wxLC_REPORT);
+    lbPrivileges->SetImageList(imgList, wxIMAGE_LIST_SMALL);
+    lbPrivileges->AddColumn(_("User/Group"), 50, wxLIST_FORMAT_LEFT);
+    lbPrivileges->AddColumn(_("Privileges"), 35, wxLIST_FORMAT_LEFT);
+    itemSizer1->Add(lbPrivileges, 0, wxEXPAND|wxALIGN_CENTRE_VERTICAL|wxTOP|wxLEFT|wxRIGHT, 4);
+    item0->Add(itemSizer1, 0, wxEXPAND|wxALL, 5);
+
+    wxBoxSizer* itemSizer2 = new wxBoxSizer(wxHORIZONTAL);
+    btnAddPriv = new wxButton(this, CTL_DEFADDPRIV, _("Add/Change"));
+    itemSizer2->Add(btnAddPriv, 0, wxEXPAND|wxALIGN_CENTRE_VERTICAL|wxTOP|wxLEFT|wxRIGHT, 4);
+    btnDelPriv = new wxButton(this, CTL_DEFDELPRIV, _("Remove"));
+    itemSizer2->Add(btnDelPriv, 0, wxEXPAND|wxALIGN_CENTRE_VERTICAL|wxTOP|wxLEFT|wxRIGHT, 4);
+    item0->Add(itemSizer2, 0, wxEXPAND|wxALL, 0);
+
+    wxStaticBox* sb = new wxStaticBox(this, -1, _("Privileges"));
+    wxBoxSizer* itemSizer3 = new wxStaticBoxSizer( sb, wxVERTICAL );
+    item0->Add(itemSizer3, 0, wxEXPAND|wxALL, 5);
+
+    wxBoxSizer* itemSizer4a = new wxBoxSizer(wxHORIZONTAL);
+    stGroup = new wxStaticText(this, CTL_DEFSTATICGROUP, strGroupLabel);
+    itemSizer4a->Add(stGroup, 0, wxEXPAND|wxALIGN_CENTRE_VERTICAL|wxTOP|wxLEFT|wxRIGHT, 4);
+    cbGroups = new ctlComboBox(this, CTL_DEFCBGROUP, wxDefaultPosition, wxDefaultSize);
+    itemSizer4a->Add(cbGroups, wxEXPAND|wxALIGN_CENTRE_VERTICAL|wxTOP|wxLEFT|wxRIGHT);
+    itemSizer3->Add(itemSizer4a, 0, wxEXPAND|wxALL, 0);
+
+    /* border size depends on the plateform */
+#ifdef __WXMSW__
+    int bordersize = 4;
+#endif
+#ifdef __WXMAC__
+    int bordersize = 3;
+#endif
+#ifdef __WXGTK__
+    int bordersize = 0;
+#endif
+
+    wxBoxSizer* itemSizer5 = new wxBoxSizer(wxHORIZONTAL);
+    allPrivileges = new wxCheckBox(this, CTL_DEFALLPRIV, wxT("ALL"));
+    itemSizer5->Add(allPrivileges, wxEXPAND|wxALIGN_CENTRE_VERTICAL|wxTOP|wxLEFT|wxRIGHT);
+    allPrivilegesGrant = new wxCheckBox(this, CTL_DEFALLPRIVGRANT, wxT("WITH GRANT OPTION"));
+    itemSizer5->Add(allPrivilegesGrant, wxEXPAND|wxALIGN_CENTRE_VERTICAL|wxTOP|wxLEFT|wxRIGHT);
+    allPrivilegesGrant->Disable();
+    itemSizer3->Add(itemSizer5, 0, wxALL, bordersize);
+
+    for (int index=0; index < privilegeCount; index++)
+    {
+        int i = index * 2;
+        wxChar privilege = m_privilegeType.m_privileges.GetChar(index);
+        wxString priv = GetPrivilegeName(privilege);
+
+        wxCheckBox *cb;
+        wxBoxSizer* itemSizer6 = new wxBoxSizer(wxHORIZONTAL);
+        cb = new wxCheckBox(this, CTL_DEFPRIVCB + i, priv);
+        itemSizer6->Add(cb, wxEXPAND|wxALIGN_CENTRE_VERTICAL|wxTOP|wxLEFT|wxRIGHT);
+        privCheckboxes[i++] = cb;
+        cb = new wxCheckBox(this, CTL_DEFPRIVCB + i, wxT("WITH GRANT OPTION"));
+        itemSizer6->Add(cb, wxEXPAND|wxALIGN_CENTRE_VERTICAL|wxTOP|wxLEFT|wxRIGHT);
+        cb->Disable();
+        privCheckboxes[i] = cb;
+        itemSizer3->Add(itemSizer6, 0, wxALL, bordersize);
+
+    }
+
+    this->SetSizer(item0);
+    item0->Fit(this);
+}
+
+static wxString GetPrivilegeName(wxChar privilege)
+{
+   switch(privilege) {
+     case 'a':
+         return wxT("INSERT");
+     case 'r':
+         return wxT("SELECT");
+     case 'w':
+         return wxT("UPDATE");
+     case 'd':
+         return wxT("DELETE");
+     case 'D':
+         return wxT("TRUNCATE");
+     case 'x':
+         return wxT("REFERENCES");
+     case 't':
+         return wxT("TRIGGER");
+     case 'U':
+         return wxT("USAGE");
+     case 'X':
+         return wxT("EXECUTE");
+     default:
+         return wxT("UNKNOWN");
+   }
+}
+
+static bool findUserPrivs(wxString& strDefPrivs, wxString& strUser, wxString& strPriv)
+{
+    strUser = strPriv = wxT("");
+    if (strDefPrivs.IsEmpty()) return false;
+
+    bool startsWithQuote = false;
+    if (strDefPrivs.StartsWith(wxT("\""))) startsWithQuote = true;
+
+    if (strDefPrivs.StartsWith(wxT("\"\"")))
+    {
+        wxChar currChar;
+        int    quoteCount = 0;
+        int    index = 0;
+
+        currChar = strDefPrivs.GetChar(index);
+
+        while (true)
+        {
+            if (currChar == wxT('=') && quoteCount%2 == 0)
+                break;
+            strUser += currChar;
+            currChar = strDefPrivs.GetChar(++index);
+            if (currChar == wxT('"')) quoteCount++;
+        }
+        strUser = strUser.SubString(2, strUser.Length() - 2);
+        strUser.Replace(wxT("\"\""), wxT("\""), true);
+        strDefPrivs = strDefPrivs.SubString(index + 1, strDefPrivs.Length());
+    }
+    else
+    {
+        /* Remove first quote */
+        if (startsWithQuote) strDefPrivs = strDefPrivs.SubString(1, strDefPrivs.Length());
+
+        int equalCharAt = strDefPrivs.Find(wxT('='));
+
+        if (equalCharAt != 0)
+            strUser = strDefPrivs.SubString(0, equalCharAt - 1);
+        else
+            strUser = wxT("PUBLIC");
+        strDefPrivs = strDefPrivs.SubString(equalCharAt + 1, strDefPrivs.Length());
+    }
+
+    int slashCharAt = strDefPrivs.Find(wxT('/'));
+    strPriv = strDefPrivs.SubString(0, slashCharAt - 1);
+
+    strDefPrivs = strDefPrivs.SubString(strPriv.Length() + 2, strDefPrivs.Length());
+
+    if (!strDefPrivs.StartsWith(wxT("\"")))
+    {
+        int commaCharAt = strDefPrivs.Find(wxT(','));
+        if (commaCharAt == wxNOT_FOUND) strDefPrivs = wxT("");
+        else strDefPrivs = strDefPrivs.SubString(commaCharAt + 1, strDefPrivs.Length());
+    }
+    else
+    {
+        wxChar currChar;
+        int    quoteCount = 0;
+        int    index = 0;
+
+        currChar = strDefPrivs.GetChar(index);
+        while (true)
+        {
+            if (currChar == wxT(',') && quoteCount%2 == 0)
+                break;
+            currChar = strDefPrivs.GetChar(++index);
+            if (currChar == wxT('"')) quoteCount++;
+        }
+        strDefPrivs = strDefPrivs.SubString(index, strDefPrivs.Length());
+    }
+
+    return true;
+}
+
+
+ctlDefaultPrivilegesPanel::~ctlDefaultPrivilegesPanel()
+{
+    cbGroups->Clear();
+    if (privCheckboxes)
+        delete[] privCheckboxes;
+}
+
+// Find the privileges for the selected user from the map
+// and select the check-boxes accordingly
+bool ctlDefaultPrivilegesPanel::PrivCheckBoxUpdate(wxString& strUser)
+{
+    int index = 0;
+    wxString strKey  = strUser;
+    defPrivHash::iterator priv = m_privileges.find(strKey);
+    bool canGrant = CanGrant();
+
+    if (priv == m_privileges.end())
+    {
+        m_currentSelectedPriv = NULL;
+        allPrivileges->SetValue(true);
+        allPrivilegesGrant->Enable(canGrant);
+        for (; index < privilegeCount; index++)
+        {
+            privCheckboxes[index*2]->Enable();
+            privCheckboxes[index*2]->SetValue(true);
+            privCheckboxes[index*2 + 1]->Enable(canGrant);
+        }
+        return false;
+    }
+    else
+    {
+        allPrivileges->SetValue(false);
+        allPrivilegesGrant->SetValue(false);
+        allPrivilegesGrant->Enable(false);
+    }
+
+    wxString currentPrivileges = priv->second.m_modified ? priv->second.m_newPriv : priv->second.m_origPriv;
+    m_currentSelectedPriv = &priv->second;
+
+    for (index = 0; index < privilegeCount; index++)
+    {
+        int privAt = currentPrivileges.Find(m_privilegeType.m_privileges.GetChar(index));
+        if (privAt != wxNOT_FOUND)
+        {
+            privCheckboxes[index*2]->SetValue(true);
+            privCheckboxes[index*2 + 1]->Enable(canGrant);
+            if (canGrant && (unsigned int)privAt < currentPrivileges.Length() - 1 && currentPrivileges.GetChar(privAt + 1) == wxT('*'))
+                privCheckboxes[index*2 + 1]->SetValue(true);
+            else
+                privCheckboxes[index*2 + 1]->SetValue(false);
+        }
+        else
+        {
+            privCheckboxes[index*2]->SetValue(false);
+            privCheckboxes[index*2 + 1]->SetValue(false);
+            privCheckboxes[index*2 + 1]->Disable();
+        }
+    }
+    return false;
+}
+
+
+bool ctlDefaultPrivilegesPanel::CanGrant()
+{
+    if (cbGroups->GetValue() == wxT("PUBLIC"))
+        return false;
+    return true;
+}
+
+
+void ctlDefaultPrivilegesPanel::OnGroupChange(wxCommandEvent &ev)
+{
+    cbGroups->GuessSelection(ev);
+
+    wxString strRole   = cbGroups->GetValue();
+
+    if (strRole.IsEmpty())
+        return;
+
+    btnAddPriv->Enable(!PrivCheckBoxUpdate(strRole));
+}
+
+
+void ctlDefaultPrivilegesPanel::OnPrivCheckAll(wxCommandEvent& ev)
+{
+    bool all = allPrivileges->GetValue();
+    allPrivilegesGrant->Enable(all && CanGrant());
+
+    for (int i = 0; i < privilegeCount; i++)
+    {
+        privCheckboxes[i*2]->SetValue(all);
+        CheckGrantOpt(i);
+    }
+}
+
+void ctlDefaultPrivilegesPanel::OnPrivCheckAllGrant(wxCommandEvent& ev)
+{
+    bool grant=allPrivilegesGrant->GetValue();
+    for (int i=0 ; i < privilegeCount ; i++)
+        privCheckboxes[i*2+1]->SetValue(grant);
+}
+
+
+void ctlDefaultPrivilegesPanel::OnPrivCheck(wxCommandEvent& ev)
+{
+    int id=(ev.GetId()-CTL_DEFPRIVCB) /2;
+    CheckGrantOpt(id);
+    btnAddPriv->Enable();
+    if (!privCheckboxes[id*2]->GetValue())
+       allPrivileges->SetValue(false);
+}
+
+
+void ctlDefaultPrivilegesPanel::CheckGrantOpt(int id)
+{
+    bool canGrant=(privCheckboxes[id*2]->GetValue() && CanGrant());
+    if (canGrant)
+        privCheckboxes[id*2+1]->Enable(true);
+    else
+    {
+        privCheckboxes[id*2+1]->SetValue(false);
+        privCheckboxes[id*2+1]->Disable();
+    }
+    btnAddPriv->Enable();
+}
+
+
+void ctlDefaultPrivilegesPanel::OnDelPriv(wxCommandEvent &ev)
+{
+    int pos;
+    wxString strRole;
+    if ((pos = lbPrivileges->GetFirstSelected()) == -1)
+        return;
+
+    wxListItem info;
+    info.m_itemId = pos;
+    info.m_col    = 0;
+    info.m_mask = wxLIST_MASK_TEXT;
+
+    if (lbPrivileges->GetItem(info))
+        strRole = info.m_text;
+
+    wxString strKey  = strRole;
+    defPrivHash::iterator priv = m_privileges.find(strKey);
+
+    if (priv != m_privileges.end())
+    {
+        priv->second.m_modified = true;
+        priv->second.m_newPriv = wxT("");
+        if (m_currentSelectedPriv == &priv->second)
+            PrivCheckBoxUpdate(strRole);
+    }
+    
+    lbPrivileges->DeleteCurrentItem();
+    
+    ev.Skip();
+}
+
+
+void ctlDefaultPrivilegesPanel::OnAddPriv(wxCommandEvent &ev)
+{
+    wxString strRole, strPriv;
+    bool isPresent = m_currentSelectedPriv != NULL &&
+                     ((m_currentSelectedPriv->m_modified &&
+                       !m_currentSelectedPriv->m_newPriv.IsEmpty()) ||
+                      (!m_currentSelectedPriv->m_modified));
+
+    if (allPrivileges && allPrivileges->GetValue())
+    {
+        if (allPrivilegesGrant->GetValue())
+        {
+            for (int index = 0; index < privilegeCount; index++)
+            {
+                strPriv += m_privilegeType.m_privileges.GetChar(index);
+                strPriv += wxT('*');
+            }
+        }
+        else
+            strPriv =  m_privilegeType.m_privileges;
+    }
+    else
+    {
+        for (int index = 0; index < privilegeCount; index++)
+        {
+            if (privCheckboxes[index*2]->GetValue())
+            {
+                strPriv += m_privilegeType.m_privileges.GetChar(index);
+                if(privCheckboxes[index*2 + 1]->IsEnabled() && privCheckboxes[index*2 + 1]->GetValue())
+                    strPriv += wxT('*');
+            }
+        }
+    }
+
+    if (!m_currentSelectedPriv)
+    {
+        strRole   = cbGroups->GetGuessedStringSelection();
+
+        defPrivilege priv;
+        priv.m_username = strRole;
+        priv.m_origPriv = wxT("");
+        priv.m_modified = true;
+        priv.m_newPriv  = strPriv;
+    
+        wxString strKey = strRole;
+        m_privileges[strKey] = priv;
+
+        defPrivHash::iterator itr = m_privileges.find(strKey);
+        m_currentSelectedPriv = &itr->second;
+    }
+    else
+    {
+        if (m_currentSelectedPriv->m_modified ? 
+              m_currentSelectedPriv->m_newPriv == strPriv :
+              m_currentSelectedPriv->m_origPriv == strPriv)
+        {
+            ev.Skip();
+            return;
+        }
+        strRole   = m_currentSelectedPriv->m_username;
+        m_currentSelectedPriv->m_modified = true;
+        m_currentSelectedPriv->m_newPriv  = strPriv;
+    }
+
+    if (!isPresent)
+    {
+        int icon;
+        if (strRole.IsSameAs(wxT("PUBLIC"), true))
+            icon = PGICON_PUBLIC;
+        else if (strRole.StartsWith(wxT("GROUP ")))
+            icon = groupFactory.GetIconId();
+        else
+            icon = userFactory.GetIconId();
+        long pos = lbPrivileges->GetItemCount();
+
+        lbPrivileges->InsertItem(pos, strRole, icon);
+        lbPrivileges->SetItem(pos, 1, strPriv);
+    }
+    else
+    {
+        long nCount =  lbPrivileges->GetItemCount();
+        wxListItem info;
+
+        for (int index=0; index < nCount; index++)
+        {
+            wxString strTempRole;
+
+            info.m_itemId = index;
+            info.m_col    = 0;
+            info.m_mask = wxLIST_MASK_TEXT;
+        
+            if (lbPrivileges->GetItem(info))
+                strTempRole = info.m_text;
+
+            if (strTempRole == strRole)
+            {
+                lbPrivileges->SetItem(index, 1, strPriv);
+                break;
+            }
+        }
+    }
+    m_defPrivChanged = true;
+
+    ev.Skip();
+}
+
+
+void ctlDefaultPrivilegesPanel::OnPrivSelChange(wxListEvent &ev)
+{
+    if (!cbGroups)
+        return;
+    btnAddPriv->Enable();
+}
+
+
+void ctlDefaultPrivilegesPanel::Update(const wxString& schemaOid)
+{
+    unsigned int index=0;
+
+    cbGroups->Clear();
+    lbPrivileges->DeleteAllItems();
+
+    m_privileges.clear();
+
+    cbGroups->Append(wxT("PUBLIC"));
+
+    for (; index < m_defSecurityPanel->m_groups.GetCount(); index++)
+        cbGroups->Append(m_defSecurityPanel->m_groups[index]);
+
+    if (m_defSecurityPanel->m_connection && !schemaOid.IsEmpty())
+    {
+        pgSet *setPrivileges = m_defSecurityPanel->m_connection->ExecuteSet(wxT("SELECT defaclacl FROM pg_catalog.pg_default_acl dacl WHERE dacl.defaclnamespace = ") + schemaOid + wxT(" AND defaclobjtype='") + wxString(m_privilegeType.m_privilegeType) + wxT("'"));
+        if (setPrivileges)
+        {
+            while(!setPrivileges->Eof())
+            {
+                wxString strDefPrivs  = setPrivileges->GetVal(0);
+
+                wxString strUser, strPriv;
+                strDefPrivs.Replace(wxT("\\\""), wxT("\""), true);
+                strDefPrivs.Replace(wxT("\\\\"), wxT("\\"), true);
+
+                // Removing starting brace '{' and ending brace '}'
+                strDefPrivs = strDefPrivs.SubString(1, strDefPrivs.Length() - 1);
+
+                long pos = 0;
+
+                while (findUserPrivs(strDefPrivs, strUser, strPriv))
+                {
+                    int icon;
+                    if (strUser.IsSameAs(wxT("PUBLIC"), true))
+                        icon = PGICON_PUBLIC;
+                    else if (cbGroups->FindString(strUser) != wxNOT_FOUND)
+                        icon = userFactory.GetIconId();
+                    else if (cbGroups->FindString(wxT("GROUP ") + strUser) != wxNOT_FOUND)
+                    {
+                        icon = groupFactory.GetIconId();
+                        strUser = wxT("GROUP ") + strUser;
+                    }
+                    else
+                        continue;
+
+                    defPrivilege priv;
+                    priv.m_username = strUser;
+                    priv.m_origPriv = strPriv;
+                    priv.m_modified = false;
+                    priv.m_newPriv  = wxT("");
+
+                    /*
+                    fprintf(stdout, "  SCHEMA:%s\n\tUSER:%s\n\tPRIV:%s\n", (const char*)strSchema.mb_str(wxConvUTF8),
+                                                                         (const char*)strUser.mb_str(wxConvUTF8),
+                                                                         (const char*)strPriv.mb_str(wxConvUTF8));
+                    */
+
+                    wxString strKey = strUser;
+                    m_privileges[strKey] = priv;
+
+                    pos = lbPrivileges->GetItemCount();
+
+                    lbPrivileges->InsertItem(pos, strUser, icon);
+                    lbPrivileges->SetItem(pos, 1, strPriv);
+
+                    strUser = wxT("");
+                    strPriv = wxT("");
+                    pos++;
+                }
+
+                setPrivileges->MoveNext();
+            }
+            delete setPrivileges;
+        }
+    }
+}
+
+
+wxString ctlDefaultPrivilegesPanel::GetDefaultPrivileges(const wxString& schemaName)
+{
+    if(!m_defPrivChanged)
+        return wxT("");
+
+    wxString strDefPrivs;
+    defPrivHash::iterator itr = m_privileges.begin();
+
+    for (; itr != m_privileges.end(); itr++)
+    {
+        if(itr->second.m_modified)
+        {
+            wxString strGrant, strRevoke, strGrantOption, strRevokeGrantOption;
+            for (int index=0; index < privilegeCount; index++)
+            {
+                bool inOrigPriv = false, inNewPriv = false, grantOptInOrigPriv = false, grantOptInNewPriv = false;
+                wxChar privChar = m_privilegeType.m_privileges.GetChar(index);
+                int privAt = itr->second.m_origPriv.Find(privChar);
+                if (privAt != wxNOT_FOUND)
+                {
+                    inOrigPriv =  true;
+                    if ((unsigned int)privAt < itr->second.m_origPriv.Length() - 1 &&
+                        itr->second.m_origPriv.GetChar(privAt + 1) == wxT('*'))
+                        grantOptInOrigPriv = true;
+                }
+
+                privAt = itr->second.m_newPriv.Find(privChar);
+                if (privAt != wxNOT_FOUND)
+                {
+                    inNewPriv =  true;
+                    if ((unsigned int)privAt < itr->second.m_newPriv.Length() - 1 &&
+                        itr->second.m_newPriv.GetChar(privAt + 1) == wxT('*'))
+                        grantOptInNewPriv = true;
+                }
+                if (inOrigPriv || inNewPriv || grantOptInOrigPriv || grantOptInNewPriv)
+                {
+                    wxString strPrivilege = GetPrivilegeName(privChar);
+                    if (!inOrigPriv && inNewPriv)
+                    {
+                        // GRANT PRIVILEGES
+                        if (!grantOptInNewPriv)
+                            strGrant             += strPrivilege + wxT(", ");
+                        // GRANT PRVILEGES WITH GRANT OPTION
+                        else
+                            strGrantOption       += strPrivilege + wxT(", ");
+                    }
+                    // REVOKE PRIVILEGES
+                    else if (inOrigPriv && !inNewPriv)
+                        strRevoke                += strPrivilege + wxT(", ");
+                    else if (inOrigPriv && inNewPriv)
+                    {
+                        // REVOKE ONLY 'WITH GRANT OPTION'
+                        if(grantOptInOrigPriv && !grantOptInNewPriv)
+                            strRevokeGrantOption += strPrivilege + wxT(", ");
+                        // GRANT PRVILEGES WITH GRANT OPTION
+                        else if (!grantOptInOrigPriv && grantOptInNewPriv)
+                            strGrantOption       += strPrivilege + wxT(", ");
+                    }
+                }
+            }
+
+            wxString strRole   = itr->second.m_username;
+            if (strRole.StartsWith(wxT("GROUP ")))
+            {
+                strRole = strRole.SubString(6, strRole.Length());
+                strRole = qtIdent(strRole);
+            }
+            else if (strRole != wxT("PUBLIC"))
+                strRole = qtIdent(strRole);
+
+            bool isModified = false;
+            wxString strAltDefPriv;
+
+            if (!schemaName.IsEmpty())
+                strAltDefPriv = wxT("ALTER DEFAULT PRIVILEGES IN SCHEMA ") + schemaName;
+            else
+                strAltDefPriv = wxT("ALTER DEFAULT PRIVILEGES ");
+             
+            // Remove trailing comma character
+            if (!strGrant.IsEmpty())
+            {
+                isModified = true;
+ 
+                strGrant = strGrant.SubString(0, strGrant.Length() - 3);
+                strDefPrivs += strAltDefPriv +
+                      wxT("\n    GRANT ") + strGrant + wxT(" ON ") + m_privilegeType.m_privilegesOn +
+                      wxT("\n    TO ") + strRole + wxT(";\n"); 
+            }
+            if (!strGrantOption.IsEmpty())
+            {
+                isModified = true;
+                strGrantOption = strGrantOption.SubString(0, strGrantOption.Length() - 3);
+                strDefPrivs += strAltDefPriv +
+                      wxT("\n    GRANT ") + strGrantOption + wxT(" ON ") + m_privilegeType.m_privilegesOn +
+                      wxT("\n    TO ") + strRole + wxT(" WITH GRANT OPTION;\n"); 
+            }
+            if (!strRevoke.IsEmpty())
+            {
+                isModified = true;
+                strRevoke = strRevoke.SubString(0, strRevoke.Length() - 3);
+                strDefPrivs += strAltDefPriv +
+                      wxT("\n    REVOKE ") + strRevoke + wxT(" ON ") + m_privilegeType.m_privilegesOn +
+                      wxT("\n    FROM ") + strRole + wxT(";\n"); 
+            }
+            if (!strRevokeGrantOption.IsEmpty())
+            {
+                isModified = true;
+                strRevokeGrantOption = strRevokeGrantOption.SubString(0, strRevokeGrantOption.Length() - 3);
+                strDefPrivs += strAltDefPriv +
+                      wxT("\n    REVOKE GRANT OPTION FOR ") + strRevokeGrantOption + wxT(" ON ") + m_privilegeType.m_privilegesOn +
+                      wxT("\n    FROM ") + strRole + wxT(";\n"); 
+            }
+            if (isModified)
+                strDefPrivs += wxT("\n");
+        }
+    }
+    return strDefPrivs;
+}
+
+
Index: ctl/module.mk
===================================================================
--- ctl/module.mk	(revision 8256)
+++ ctl/module.mk	(working copy)
@@ -19,6 +19,7 @@
         $(srcdir)/ctl/ctlSQLBox.cpp \
         $(srcdir)/ctl/ctlSQLGrid.cpp \
         $(srcdir)/ctl/ctlSQLResult.cpp \
+        $(srcdir)/ctl/ctlDefaultSecurityPanel.cpp \
         $(srcdir)/ctl/ctlSecurityPanel.cpp \
         $(srcdir)/ctl/ctlTree.cpp \
         $(srcdir)/ctl/explainCanvas.cpp \
Index: include/ctl/ctlDefaultSecurityPanel.h
===================================================================
--- include/ctl/ctlDefaultSecurityPanel.h	(revision 0)
+++ include/ctl/ctlDefaultSecurityPanel.h	(revision 0)
@@ -0,0 +1,127 @@
+//////////////////////////////////////////////////////////////////////////
+//
+// pgAdmin III - PostgreSQL Tools
+// RCS-ID:      $Id$
+// Copyright (C) 2002 - 2010, The pgAdmin Development Team
+// This software is released under the PostgreSQL Licence
+//
+// ctlDefaultSecurityPanel.h - Panel with default security information
+//
+//////////////////////////////////////////////////////////////////////////
+
+
+#ifndef CTL_DEFDEFSECPANEL_H
+#define CTL_DEFDEFSECPANEL_H
+
+#include <wx/wx.h>
+#include <wx/dynarray.h>
+#include <wx/notebook.h>
+
+enum
+{
+    CTL_DEFPROPSQL=500,
+    CTL_DEFMSG,
+    CTL_DEFLBPRIV,
+    CTL_DEFSTATICGROUP,
+    CTL_DEFCBGROUP,
+    CTL_DEFADDPRIV,
+    CTL_DEFDELPRIV,
+    CTL_DEFALLPRIV,
+    CTL_DEFALLPRIVGRANT,
+    CTL_DEFPRIVCB          // base for all privilege checkboxes, must be last
+};
+
+class defaultPrivilegesOn
+{
+public:
+    defaultPrivilegesOn(const wxChar, const wxString&, const wxString&);
+
+    wxChar   m_privilegeType;
+    wxString m_privilegesOn;
+    wxString m_privileges;
+    wxArrayString m_privilegesList;
+};
+
+
+DECLARE_EVENT_TYPE(EVT_DEFAULTSECURITYPANEL_CHANGE, -1)
+
+class pgConn;
+class ctlDefaultPrivilegesPanel;
+class dlgDefaultSecurityProperty;
+
+class ctlDefaultSecurityPanel : public wxPanel
+{
+
+public:
+    ctlDefaultSecurityPanel(pgConn* , wxNotebook* , wxImageList*);
+
+    wxString GetDefaultPrivileges(const wxString& schemaName);
+    void     UpdatePrivilegePages(const wxString& schemaOid);
+
+protected:
+    wxNotebook                 *nbNotebook;
+    pgConn                     *m_connection;
+
+    wxArrayString m_groups;
+    wxArrayString m_namespaces;
+
+    friend class ctlDefaultPrivilegesPanel;
+    friend class dlgDefaultSecurityProperty;
+};
+
+class ctlDefaultPrivilegesPanel : public wxPanel
+{
+
+public:
+
+    ctlDefaultPrivilegesPanel(ctlDefaultSecurityPanel *, wxNotebook *, defaultPrivilegesOn&, wxImageList *);
+    ~ctlDefaultPrivilegesPanel();
+
+    void Update(const wxString& schemaOid);
+    wxString GetDefaultPrivileges(const wxString& schemaName);
+
+protected:
+
+    typedef struct {
+        wxString m_username;
+        wxString m_origPriv;
+        wxString m_newPriv;
+        bool     m_modified;
+    } defPrivilege;
+
+public:
+    WX_DECLARE_STRING_HASH_MAP(defPrivilege, defPrivHash);
+
+protected:
+
+    bool                 m_defPrivChanged;
+    int                  privilegeCount;
+    defaultPrivilegesOn  m_privilegeType;
+    defPrivHash          m_privileges;
+    defPrivilege        *m_currentSelectedPriv;
+
+    ctlDefaultSecurityPanel *m_defSecurityPanel;
+    wxButton                *btnAddPriv, *btnDelPriv;
+    wxCheckBox              **privCheckboxes;
+    wxCheckBox              *allPrivileges, *allPrivilegesGrant;
+    ctlListView             *lbPrivileges;
+    ctlComboBox             *cbGroups;
+    wxStaticText            *stGroup;
+
+    void OnPrivSelChange(wxListEvent &ev);
+    void OnAddPriv(wxCommandEvent& ev);
+    void OnGroupChange(wxCommandEvent &ev);
+    void OnDelPriv(wxCommandEvent& ev);
+    void OnPrivCheck(wxCommandEvent& ev);
+    void OnPrivCheckAll(wxCommandEvent& ev);
+    void OnPrivCheckAllGrant(wxCommandEvent& ev);
+
+    bool PrivCheckBoxUpdate(wxString& strUser);
+    void CheckGrantOpt(int index);
+    bool CanGrant();
+
+    DECLARE_EVENT_TABLE()
+};
+
+#endif
+
Index: include/ctl/module.mk
===================================================================
--- include/ctl/module.mk	(revision 8256)
+++ include/ctl/module.mk	(working copy)
@@ -16,6 +16,7 @@
 	$(srcdir)/include/ctl/ctlComboBox.h \
 	$(srcdir)/include/ctl/ctlListView.h \
 	$(srcdir)/include/ctl/ctlMenuToolbar.h \
+	$(srcdir)/include/ctl/ctlDefaultSecurityPanel.h \
 	$(srcdir)/include/ctl/ctlSecurityPanel.h \
 	$(srcdir)/include/ctl/ctlSQLBox.h \
 	$(srcdir)/include/ctl/ctlSQLGrid.h \
Index: include/dlg/dlgDatabase.h
===================================================================
--- include/dlg/dlgDatabase.h	(revision 8256)
+++ include/dlg/dlgDatabase.h	(working copy)
@@ -17,7 +17,7 @@
 
 class pgDatabase;
 
-class dlgDatabase : public dlgSecurityProperty
+class dlgDatabase : public dlgDefaultSecurityProperty
 {
 public:
     dlgDatabase(pgaFactory *factory, frmMain *frame, pgDatabase *db);
@@ -54,6 +54,7 @@
     void OnOK(wxCommandEvent &ev);
 
     void SetupVarEditor(int var);
+    bool executeDDLSql(const wxString& strSql);
 
 	bool dirtyVars;
 
Index: include/dlg/dlgSchema.h
===================================================================
--- include/dlg/dlgSchema.h	(revision 8256)
+++ include/dlg/dlgSchema.h	(working copy)
@@ -17,7 +17,7 @@
 
 class pgSchema;
 
-class dlgSchema : public dlgSecurityProperty
+class dlgSchema : public dlgDefaultSecurityProperty
 {
 public:
     dlgSchema(pgaFactory *factory, frmMain *frame, pgSchema *db);
Index: include/dlg/dlgProperty.h
===================================================================
--- include/dlg/dlgProperty.h	(revision 8256)
+++ include/dlg/dlgProperty.h	(working copy)
@@ -23,7 +23,6 @@
 class pgSchema;
 class pgTable;
 class frmMain;
-class ctlSecurityPanel;
 class pgaFactory;
 
 #define stComment       CTRL_STATIC("stComment")
@@ -45,6 +44,23 @@
        
 };
 
+
+/*
+ * We need the definition of replClientData in dlgDatabase too, to hack
+ * the execution of default privileges statements (sqls) before getting
+ * disconnected.
+ */
+class replClientData : public wxClientData
+{
+public:
+    replClientData(const wxString &c, long s, long ma, long mi) { cluster=c; setId=s; majorVer=ma; minorVer=mi; }
+    wxString cluster;
+    long setId;
+    long majorVer;
+    long minorVer;
+};
+
+
 WX_DEFINE_ARRAY(dataType *, dataTypeCache);
 
 class dlgProperty : public DialogWithHelp
@@ -67,7 +83,7 @@
     virtual void CreateAdditionalPages();
     virtual wxString GetHelpPage() const;
     virtual wxString GetHelpPage(bool forCreate) const { return wxEmptyString; }
-    void SetConnection(pgConn *conn) { connection=conn; }
+    virtual void SetConnection(pgConn *conn) { connection=conn; }
     void SetDatabase(pgDatabase *db);
     void SetDatatypeCache(dataTypeCache cache);
     virtual int Go(bool modal=false);
@@ -211,20 +227,52 @@
     void OnChangeSize(wxSizeEvent &ev);
 #endif
 
+    ctlSecurityPanel *securityPage;
+
 private:
 
     void OnAddPriv(wxCommandEvent& ev);
     void OnDelPriv(wxCommandEvent& ev);
     bool securityChanged;
 
-    ctlSecurityPanel *securityPage;
     wxArrayString currentAcl;
 
     DECLARE_EVENT_TABLE()
 };
 
+class ctlDefaultSecurityPanel;
 
+class dlgDefaultSecurityProperty : public dlgSecurityProperty
+{
 
+protected:
+    dlgDefaultSecurityProperty(pgaFactory *factory, frmMain *frame, pgObject *obj, const wxString &resName,
+                               const wxString& privilegeList, const char *privilegeChar, bool createDefPrivPanel=true);
+
+    virtual int      Go(bool modal=false, const wxString& schemaOid=wxT("0::OID"));
+    virtual wxString GetHelpPage() const;
+
+    void     EnableOK(bool enable);
+    wxString GetDefaultPrivileges(const wxString& schemaName = wxT(""));
+    void     AddGroups(ctlComboBox *comboBox=0);
+    void     AddUsers(ctlComboBox *comboBox=0);
+#ifdef __WXMAC__
+    void        OnChangeSize(wxSizeEvent &ev);
+#endif
+
+    bool defaultSecurityChanged;
+
+private:
+    void OnAddPriv(wxCommandEvent& ev);
+    void OnDelPriv(wxCommandEvent& ev);
+
+    ctlDefaultSecurityPanel *defaultSecurityPage;
+
+    DECLARE_EVENT_TABLE()
+};
+
+
+
 class dlgAgentProperty : public dlgProperty
 {
 public:
Index: pgAdmin3.vcproj
===================================================================
--- pgAdmin3.vcproj	(revision 8256)
+++ pgAdmin3.vcproj	(working copy)
@@ -404,6 +404,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\ctl\ctlDefaultSecurityPanel.cpp"
+				>
+			</File>
+			<File
 				RelativePath=".\ctl\ctlSQLBox.cpp"
 				>
 			</File>
@@ -959,6 +963,10 @@
 					>
 				</File>
 				<File
+					RelativePath=".\include\ctl\ctlDefaultSecurityPanel.h"
+					>
+				</File>
+				<File
 					RelativePath=".\include\ctl\ctlSQLBox.h"
 					>
 				</File>
Index: dlg/dlgProperty.cpp
===================================================================
--- dlg/dlgProperty.cpp	(revision 8256)
+++ dlg/dlgProperty.cpp	(working copy)
@@ -22,6 +22,7 @@
 #include "utils/misc.h"
 #include "utils/pgDefs.h"
 #include "ctl/ctlSecurityPanel.h"
+#include "ctl/ctlDefaultSecurityPanel.h"
 
 // Images
 #include "images/properties.xpm"
@@ -59,17 +60,6 @@
 #include "schema/pgUser.h"
 
 
-class replClientData : public wxClientData
-{
-public:
-    replClientData(const wxString &c, long s, long ma, long mi) { cluster=c; setId=s; majorVer=ma; minorVer=mi; }
-    wxString cluster;
-    long setId;
-    long majorVer;
-    long minorVer;
-};
-
-
 void dataType::SetOid(OID id)
 {
     oid = id;
@@ -240,12 +230,6 @@
 }
 
 
-void dlgSecurityProperty::SetPrivilegesLayout()
-{
-    securityPage->lbPrivileges->GetParent()->Layout();
-}
-
-
 int dlgProperty::Go(bool modal)
 {
     wxASSERT(factory != 0);
@@ -1699,14 +1683,12 @@
 }
 
 
-
-
 wxString dlgSecurityProperty::GetGrant(const wxString &allPattern, const wxString &grantObject)
 {
     if (securityPage)
         return securityPage->GetGrant(allPattern, grantObject, &currentAcl);
     else
-    return wxString();
+        return wxString();
 }
 
 bool dlgSecurityProperty::DisablePrivilege(const wxString &priv) 
@@ -1721,6 +1703,164 @@
 /////////////////////////////////////////////////////////////////////////////
 
 
+BEGIN_EVENT_TABLE(dlgDefaultSecurityProperty, dlgSecurityProperty)
+    EVT_BUTTON(CTL_DEFADDPRIV, dlgDefaultSecurityProperty::OnAddPriv)
+    EVT_BUTTON(CTL_DEFDELPRIV, dlgDefaultSecurityProperty::OnDelPriv)
+#ifdef __WXMAC__
+    EVT_SIZE(                  dlgDefaultSecurityProperty::OnChangeSize)
+#endif
+END_EVENT_TABLE();
+
+
+dlgDefaultSecurityProperty::dlgDefaultSecurityProperty(pgaFactory *f, frmMain *frame, pgObject *obj, const wxString &resName, const wxString& privList, const char *privChar, bool createDefPrivPanel)
+  : dlgSecurityProperty(f, frame, obj, resName, privList, privChar), defaultSecurityChanged(false)
+{
+    if ((!obj || obj->CanCreate()) && createDefPrivPanel)
+    {
+        defaultSecurityPage = new ctlDefaultSecurityPanel(obj ? obj->GetConnection() : NULL, nbNotebook, frame->GetImageList());
+        if (obj && !obj->GetConnection()->BackendMinimumVersion(9, 0))
+            defaultSecurityPage->Disable();
+    }
+    else
+        defaultSecurityPage = NULL;
+}
+
+
+void dlgDefaultSecurityProperty::AddGroups(ctlComboBox *comboBox)
+{
+    if (!((securityPage && securityPage->cbGroups) || comboBox || defaultSecurityPage))
+        return;
+
+    pgSet *set=connection->ExecuteSet(wxT("SELECT groname FROM pg_group ORDER BY groname"));
+
+    if (set)
+    {
+        while (!set->Eof())
+        {
+            if (securityPage && securityPage->cbGroups)
+                securityPage->cbGroups->Append(wxT("group ") + set->GetVal(0));
+
+            if (comboBox)
+                comboBox->Append(set->GetVal(0));
+
+            if (defaultSecurityPage)
+                defaultSecurityPage->m_groups.Add(wxT("GROUP ") + set->GetVal(0));
+
+            set->MoveNext();
+        }
+        delete set;
+    }
+}
+
+
+void dlgDefaultSecurityProperty::AddUsers(ctlComboBox *combobox)
+{
+    if ((securityPage && securityPage->cbGroups) || defaultSecurityPage || combobox)
+    {
+        wxString strFetchUserQuery =
+            connection->BackendMinimumVersion(8, 1) ?
+              wxT("SELECT rolname FROM pg_roles WHERE rolcanlogin ORDER BY 1") :
+              wxT("SELECT usename FROM pg_user ORDER BY 1");
+
+        pgSet *set=connection->ExecuteSet(strFetchUserQuery);
+        if (set)
+        {
+            while (!set->Eof())
+            {
+                if (settings->GetShowUsersForPrivileges())
+                {
+                    if (securityPage && securityPage->cbGroups)
+                        securityPage->cbGroups->Append(set->GetVal(0));
+
+                    if (defaultSecurityPage)
+                        defaultSecurityPage->m_groups.Add(set->GetVal(0));
+                }
+
+                if (combobox)
+                    combobox->Append(set->GetVal(0));
+
+                set->MoveNext();
+            }
+        }
+    }
+}
+
+#ifdef __WXMAC__
+void dlgDefaultSecurityProperty::OnChangeSize(wxSizeEvent &ev)
+{
+    defaultSecurityPage->lbPrivileges->SetSize(wxDefaultCoord, wxDefaultCoord,
+        ev.GetSize().GetWidth(), ev.GetSize().GetHeight() - 550);
+    if (GetAutoLayout())
+    {
+        Layout();
+    }
+}
+#endif
+
+
+void dlgDefaultSecurityProperty::EnableOK(bool enable)
+{
+    // Don't enable the OK button if the object isn't yet created,
+    // leave that to the object dialog.
+    if (GetObject())
+    {
+        wxString sql=GetSql();
+        if (sql.IsEmpty())
+        {
+            enable=false;
+        }
+        else
+            enable=true;
+    }
+    dlgSecurityProperty::EnableOK(enable);
+}
+
+
+void dlgDefaultSecurityProperty::OnAddPriv(wxCommandEvent &ev)
+{
+    defaultSecurityChanged=true;
+    EnableOK(btnOK->IsEnabled());
+}
+
+
+void dlgDefaultSecurityProperty::OnDelPriv(wxCommandEvent &ev)
+{
+    defaultSecurityChanged=true;
+    EnableOK(btnOK->IsEnabled());
+}
+
+wxString dlgDefaultSecurityProperty::GetDefaultPrivileges(const wxString& schemaName)
+{
+    if (defaultSecurityChanged)
+        return defaultSecurityPage->GetDefaultPrivileges(schemaName);
+    return wxT("");
+}
+
+int dlgDefaultSecurityProperty::Go(bool modal, const wxString& schemaOid)
+{
+    if (defaultSecurityPage)
+        defaultSecurityPage->UpdatePrivilegePages(schemaOid);
+    return dlgSecurityProperty::Go(modal);
+}
+
+wxString dlgDefaultSecurityProperty::GetHelpPage() const
+{
+    int nDiff      = nbNotebook->GetPageCount() - nbNotebook->GetSelection();
+
+    switch (nDiff)
+    {
+    case 3:
+        return wxT("pg/sql-grant");
+    case 2:
+        return wxT("pg/sql-alterdefaultprivileges");
+    default:
+        return dlgProperty::GetHelpPage();
+    }
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+
 BEGIN_EVENT_TABLE(dlgAgentProperty, dlgProperty)
     EVT_BUTTON (wxID_OK,                            dlgAgentProperty::OnOK)
 END_EVENT_TABLE();
@@ -1992,3 +2132,4 @@
     // so it's Good Enough (tm) for now.
     return obj != 0 && !obj->IsCreatedBy(serverFactory.GetCollectionFactory());
 }
+
Index: dlg/dlgDatabase.cpp
===================================================================
--- dlg/dlgDatabase.cpp	(revision 8256)
+++ dlg/dlgDatabase.cpp	(working copy)
@@ -19,6 +19,7 @@
 #include "utils/misc.h"
 #include "dlg/dlgDatabase.h"
 #include "schema/pgDatabase.h"
+#include "ctl/ctlDefaultSecurityPanel.h"
 
 
 // pointer to controls
@@ -47,13 +48,13 @@
     if (dlg && !node)
     {
         // use the server's connection to avoid "template1 in use"
-        dlg->connection=parent->GetConnection();
+        dlg->SetConnection(parent->GetConnection());
     }
     return dlg;
 }
 
 
-BEGIN_EVENT_TABLE(dlgDatabase, dlgSecurityProperty)
+BEGIN_EVENT_TABLE(dlgDatabase, dlgDefaultSecurityProperty)
     EVT_TEXT(XRCID("txtPath"),                      dlgProperty::OnChange)
     EVT_TEXT(XRCID("cbTablespace"),                 dlgProperty::OnChange)
     EVT_COMBOBOX(XRCID("cbTablespace"),             dlgProperty::OnChange)
@@ -77,7 +78,7 @@
 
 
 dlgDatabase::dlgDatabase(pgaFactory *f, frmMain *frame, pgDatabase *node)
-: dlgSecurityProperty(f, frame, node, wxT("dlgDatabase"), wxT("CREATE,TEMP,CONNECT"), "CTc")
+: dlgDefaultSecurityProperty(f, frame, node, wxT("dlgDatabase"), wxT("CREATE,TEMP,CONNECT"), "CTc", node != NULL ? true : false)
 {
     database=node;
     schemaRestrictionOk=true;
@@ -98,7 +99,7 @@
 {
     if (nbNotebook->GetSelection() == 1)
         return wxT("pg/runtime-config");
-    return dlgSecurityProperty::GetHelpPage();
+    return dlgDefaultSecurityProperty::GetHelpPage();
 }
 
 
@@ -110,10 +111,12 @@
     AddGroups();
     AddUsers(cbOwner);
 
-    if (connection->BackendMinimumVersion(8,5))
+    if (connection->BackendMinimumVersion(9, 0))
     {
         cbVarUsername->Append(wxT(""));
-        AddUsers(cbVarUsername);
+        // AddUsers function of dlgDefaultSecurity has already been called.
+        // Hence, calling dlgProperty::AddUsers instead of that.
+        dlgProperty::AddUsers(cbVarUsername);
     }
     else
         cbVarUsername->Enable(false);
@@ -162,7 +165,7 @@
 
         cbVarname->SetSelection(0);
 
-        if (connection->BackendMinimumVersion(8,5))
+        if (connection->BackendMinimumVersion(9, 0))
         {
             cbVarUsername->SetSelection(0);
         }
@@ -313,7 +316,7 @@
 
     SetupVarEditor(1);
 
-    return dlgSecurityProperty::Go(modal);
+    return dlgDefaultSecurityProperty::Go(modal);
 }
 
 
@@ -364,11 +367,75 @@
     {
         database->iSetSchemaRestriction(txtSchemaRestr->GetValue().Trim());
         settings->Write(wxString::Format(wxT("Servers/%d/Databases/%s/SchemaRestriction"), database->GetServer()->GetServerIndex(), database->GetName().c_str()), txtSchemaRestr->GetValue().Trim());
+
+        /*
+         * The connection from the database will get disconnected before execution of any
+         * sql statements for the database.
+         *
+         * Hence, we need to hack the execution of the default privileges statements(sqls)
+         * before getting disconnected from this database. So that, these statements will
+         * run against the current database connection, and not against the server connection.
+         */
+        // defaultSecurityChanged will be true only for PostgreSQL 9.0 or later
+        if (defaultSecurityChanged)
+        {
+            wxString strDefPrivs = GetDefaultPrivileges();
+            if (!executeDDLSql(strDefPrivs))
+            {
+                EnableOK(true);
+                return;
+            }
+            defaultSecurityChanged = false;
+        }
     }
-    dlgSecurityProperty::OnOK(ev);
+    dlgDefaultSecurityProperty::OnOK(ev);
 }
 
+/*
+ * Execute any ddl statement (sql)
+ *
+ * - Hacked to execute any DDL statement (sql) for dlgDatabse against this database, because
+ *   connection for this database object is getting disconnected, and replaced by the server
+ *   connection, before execution of any statements (sqls) in dlgPropery::apply function called
+ *   from dlgPropery::OnOK event handler.
+ */
+bool dlgDatabase::executeDDLSql(const wxString& strSql)
+{
+    pgConn *myConn = connection;
 
+    if (!strSql.IsEmpty())
+    {
+        wxString tmp;
+        if (cbClusterSet && cbClusterSet->GetSelection() > 0)
+        {
+            replClientData *data=(replClientData*)cbClusterSet->GetClientData(cbClusterSet->GetSelection());
+
+            if (data->majorVer > 1 || (data->majorVer == 1 && data->minorVer >= 2))
+            {
+                tmp = wxT("SELECT ") + qtIdent(data->cluster)
+                    + wxT(".ddlscript_prepare(") + NumToStr(data->setId) + wxT(", 0);\n")
+                    + wxT("SELECT ") + qtIdent(data->cluster)
+                    + wxT(".ddlscript_complete(") + NumToStr(data->setId) + wxT(", ")
+                    + qtDbString(strSql) + wxT(", 0);\n");
+            }
+            else
+            {
+                tmp = wxT("SELECT ") + qtIdent(data->cluster)
+                    + wxT(".ddlscript(") + NumToStr(data->setId) + wxT(", ")
+                    + qtDbString(strSql) + wxT(", 0);\n");
+            }
+        }
+        else
+            tmp = strSql;
+
+        if (!myConn->ExecuteVoid(tmp))
+            // error message is displayed inside ExecuteVoid
+            return false;
+    }
+    return true;
+}
+
+
 void dlgDatabase::CheckChange()
 {
     bool enable=true;
@@ -695,6 +762,9 @@
                     +  wxT(" RESET ") + varname + wxT(";\n");
             }
         }
+
+        if (connection->BackendMinimumVersion(9, 0) && defaultSecurityChanged)
+            sql += GetDefaultPrivileges();
     }
     else
     {
Index: dlg/dlgSchema.cpp
===================================================================
--- dlg/dlgSchema.cpp	(revision 8256)
+++ dlg/dlgSchema.cpp	(working copy)
@@ -21,7 +21,7 @@
 
 // pointer to controls
 
-BEGIN_EVENT_TABLE(dlgSchema, dlgSecurityProperty)
+BEGIN_EVENT_TABLE(dlgSchema, dlgDefaultSecurityProperty)
 END_EVENT_TABLE();
 
 dlgProperty *pgSchemaBaseFactory::CreateDialog(frmMain *frame, pgObject *node, pgObject *parent)
@@ -30,7 +30,7 @@
 }
 
 dlgSchema::dlgSchema(pgaFactory *f, frmMain *frame, pgSchema *node)
-: dlgSecurityProperty(f, frame, node, wxT("dlgSchema"), wxT("USAGE,CREATE"), "UC")
+: dlgDefaultSecurityProperty(f, frame, node, wxT("dlgSchema"), wxT("USAGE,CREATE"), "UC")
 {
     schema=node;
 }
@@ -44,6 +44,7 @@
 
 int dlgSchema::Go(bool modal)
 {
+    wxString schemaOid;
     if (!schema)
         cbOwner->Append(wxT(""));
 
@@ -52,7 +53,6 @@
     if (schema)
     {
         // edit mode
-
         if (!connection->BackendMinimumVersion(7, 5))
             cbOwner->Disable();
 
@@ -61,13 +61,14 @@
             cbOwner->Disable();
             txtName->Disable();
         }
+        schemaOid = schema->GetOidStr();
     }
     else
     {
         // create mode
     }
 
-    return dlgSecurityProperty::Go(modal);
+    return dlgDefaultSecurityProperty::Go(modal, schemaOid);
 }
 
 
@@ -115,26 +116,29 @@
 wxString dlgSchema::GetSql()
 {
     wxString sql, name;
-    name=GetName();
+    name = qtIdent(GetName());
 
     if (schema)
     {
         // edit mode
         AppendNameChange(sql);
-        AppendOwnerChange(sql, wxT("SCHEMA ") + qtIdent(name));
+        AppendOwnerChange(sql, wxT("SCHEMA ") + name);
     }
     else
     {
         // create mode
-        sql = wxT("CREATE SCHEMA ") + qtIdent(name);
+        sql = wxT("CREATE SCHEMA ") + name;
         AppendIfFilled(sql, wxT("\n       AUTHORIZATION "), qtIdent(cbOwner->GetValue()));
         sql += wxT(";\n");
 
     }
     AppendComment(sql, wxT("SCHEMA"), 0, schema);
 
-    sql += GetGrant(wxT("UC"), wxT("SCHEMA ") + qtIdent(name));
+    sql += GetGrant(wxT("UC"), wxT("SCHEMA ") + name);
 
+    if (connection->BackendMinimumVersion(9, 0) && defaultSecurityChanged)
+        sql += GetDefaultPrivileges(name);
+
     return sql;
 }
 
Index: ui/dlgSchema.xrc
===================================================================
--- ui/dlgSchema.xrc	(revision 8256)
+++ ui/dlgSchema.xrc	(working copy)
@@ -2,7 +2,7 @@
 <resource>
   <object class="wxDialog" name="dlgSchema">
     <title></title>
-    <size>220,250d</size>
+    <size>220,280d</size>
     <style>wxDEFAULT_DIALOG_STYLE|wxCAPTION|wxSYSTEM_MENU|wxRESIZE_BORDER|wxRESIZE_BOX|wxTHICK_FRAME</style>
     <object class="wxFlexGridSizer">
       <cols>1</cols>
@@ -10,7 +10,7 @@
       <growablecols>0</growablecols>
       <object class="sizeritem">
         <object class="wxNotebook" name="nbNotebook">
-          <size>216,225d</size>
+          <size>216,260d</size>
           <selected>0</selected>
           <object class="notebookpage">
             <label>Properties</label>
Index: ui/xrcDialogs.cpp
===================================================================
--- ui/xrcDialogs.cpp	(revision 8256)
+++ ui/xrcDialogs.cpp	(working copy)
@@ -2312,7 +2312,7 @@
 101,99,116,32,99,108,97,115,115,61,34,119,120,78,111,116,101,98,111,111,
 107,34,32,110,97,109,101,61,34,110,98,78,111,116,101,98,111,111,107,34,
 62,10,32,32,32,32,32,32,32,32,32,32,60,115,105,122,101,62,50,49,54,44,50,
-53,53,100,60,47,115,105,122,101,62,10,32,32,32,32,32,32,32,32,32,32,60,
+54,48,100,60,47,115,105,122,101,62,10,32,32,32,32,32,32,32,32,32,32,60,
 115,101,108,101,99,116,101,100,62,48,60,47,115,101,108,101,99,116,101,100,
 62,10,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,
 97,115,115,61,34,110,111,116,101,98,111,111,107,112,97,103,101,34,62,10,
@@ -15569,7 +15569,7 @@
 32,99,108,97,115,115,61,34,119,120,68,105,97,108,111,103,34,32,110,97,109,
 101,61,34,100,108,103,83,99,104,101,109,97,34,62,10,32,32,32,32,60,116,
 105,116,108,101,47,62,10,32,32,32,32,60,115,105,122,101,62,50,50,48,44,
-50,53,48,100,60,47,115,105,122,101,62,10,32,32,32,32,60,115,116,121,108,
+50,56,48,100,60,47,115,105,122,101,62,10,32,32,32,32,60,115,116,121,108,
 101,62,119,120,68,69,70,65,85,76,84,95,68,73,65,76,79,71,95,83,84,89,76,
 69,124,119,120,67,65,80,84,73,79,78,124,119,120,83,89,83,84,69,77,95,77,
 69,78,85,124,119,120,82,69,83,73,90,69,95,66,79,82,68,69,82,124,119,120,
@@ -15585,7 +15585,7 @@
 114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,60,111,98,106,101,
 99,116,32,99,108,97,115,115,61,34,119,120,78,111,116,101,98,111,111,107,
 34,32,110,97,109,101,61,34,110,98,78,111,116,101,98,111,111,107,34,62,10,
-32,32,32,32,32,32,32,32,32,32,60,115,105,122,101,62,50,49,54,44,50,50,53,
+32,32,32,32,32,32,32,32,32,32,60,115,105,122,101,62,50,49,54,44,50,54,48,
 100,60,47,115,105,122,101,62,10,32,32,32,32,32,32,32,32,32,32,60,115,101,
 108,101,99,116,101,100,62,48,60,47,115,101,108,101,99,116,101,100,62,10,
 32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,
Index: ui/dlgDatabase.xrc
===================================================================
--- ui/dlgDatabase.xrc	(revision 8256)
+++ ui/dlgDatabase.xrc	(working copy)
@@ -10,7 +10,7 @@
       <growablecols>0</growablecols>
       <object class="sizeritem">
         <object class="wxNotebook" name="nbNotebook">
-          <size>216,255d</size>
+          <size>216,260d</size>
           <selected>0</selected>
           <object class="notebookpage">
             <label>Properties</label>
