├── .gitignore
├── .project
├── .pydevproject
├── .settings
├── org.eclipse.ltk.core.refactoring.prefs
└── org.springframework.ide.eclipse.xml.namespaces.prefs
├── AboutDlg.xrc
├── AdmDialogs.py
├── Admin4.icns
├── Admin4.ico
├── Admin4.png
├── Admin4Small.png
├── CHANGELOG
├── Critical.png
├── Debug.png
├── Error.png
├── FindPanel.xrc
├── HOW-TO.md
├── HintDlg.xrc
├── Info.png
├── KNOWN-BUGS
├── LICENSE.TXT
├── LogPanel.xrc
├── LoggingDialog.py
├── LoggingDialog.xrc
├── PagedPropertyDlg.xrc
├── PasswordDlg.xrc
├── Preferences.xrc
├── PreferencesDlg.xrc
├── README.V2
├── README.md
├── TODO.md
├── Update.py
├── UpdateDlg.xrc
├── Validator.py
├── adm.py
├── admin4.py
├── close.png
├── close_inactive.png
├── config.py
├── connect.png
├── controlcontainer.py
├── createBundle.py
├── ctl_adm.py
├── delete.png
├── detach.png
├── docker
├── Dockerfile
├── admin4
├── build-container.sh
├── debug-container.sh
├── push-container.sh
└── run-container.sh
├── edit.png
├── edit_find.png
├── find.png
├── folder.png
├── frame.py
├── logger.py
├── main.py
├── modBind
├── CatalogHostRecord.xrc
├── CatalogMemberRecord.xrc
├── CatalogZone.png
├── HOWTO
├── HostRecord.xrc
├── MultiValRecords.xrc
├── RevZone.png
├── Server.png
├── Server.py
├── Server.xrc
├── SingleValRecord.xrc
├── SingleValRecords.xrc
├── Zone.png
├── Zone.py
├── Zone.xrc
├── __init__.py
├── _dns.py
└── _requires.py
├── modImap
├── Mailbox.png
├── Mailbox.py
├── Mailbox.xrc
├── MailboxAcl.xrc
├── MailboxNoselect.png
├── Server.png
├── Server.py
├── Server.xrc
├── User.png
├── __init__.py
├── _imap.py
├── _requires.py
└── imap_utf7.py
├── modLdap
├── Computer.png
├── Contact.xrc
├── Entry.png
├── Entry.py
├── GenericEntry.py
├── GenericEntry.xrc
├── Group.png
├── Group.py
├── Group.xrc
├── Groups.xrc
├── OrgUnit.png
├── Personal.xrc
├── Posix.py
├── PosixUser.png
├── Preferences.xrc
├── SamUser.png
├── Samba.py
├── SambaAccount.xrc
├── SambaDomain.png
├── SambaDomain.xrc
├── SambaGroupMapping.xrc
├── Server.png
├── Server.py
├── Server.xrc
├── ServerConfig.xrc
├── ShadowAccount.xrc
├── SpecificEntry.py
├── User.png
├── UserAccount.xrc
├── __init__.py
├── _ldap.py
├── _requires.py
├── attribEmpty.png
├── attribMay.png
├── attribMust.png
├── attribRDN.png
├── hints
│ └── instrument.html
└── objectClass.png
├── modPg
├── ColumnPanel.xrc
├── ConnectDlg.xrc
├── ConnectionPage.xrc
├── DEBUG.png
├── DataTool.py
├── Database-conn.png
├── Database-noconn.png
├── Database.png
├── Database.py
├── ERROR.png
├── FATAL.png
├── Favourite.py
├── Favourites.png
├── FilterPanel.xrc
├── Function.png
├── Function.py
├── LOG.png
├── LoggingPage.xrc
├── LoglineDlg.xrc
├── MatView.png
├── Partition.png
├── PartitionedTable.png
├── Preferences.xrc
├── PrivilegePanel.xrc
├── QueryTool.py
├── Role.png
├── Role.py
├── Roles.png
├── Schema.png
├── Schema.py
├── Sequence.png
├── Sequence.py
├── Sequence.xrc
├── Server.ico
├── Server.py
├── Server.xrc
├── ServerPages.py
├── ServerSetting.xrc
├── SettingsPage.xrc
├── SqlData.ico
├── SqlPanel.xrc
├── SqlQuery.ico
├── Table.png
├── Table.py
├── View.png
├── View.py
├── __init__.py
├── _explain.py
├── _objects.py
├── _pgsql.py
├── _requires.py
├── _snippet.py
├── _sqledit.py
├── _sqlgrid.py
├── admin.png
├── check.png
├── clip_copy.png
├── clip_cut.png
├── clip_paste.png
├── column.png
├── data_refresh.png
├── data_save.png
├── delete.png
├── edit_clear.png
├── edit_find.png
├── edit_redo.png
├── edit_undo.png
├── ex_aggregate.png
├── ex_append.png
├── ex_bmp_heap.png
├── ex_bmp_index.png
├── ex_group.png
├── ex_hash.png
├── ex_index_scan.png
├── ex_join.png
├── ex_limit.png
├── ex_materialize.png
├── ex_merge.png
├── ex_nested.png
├── ex_result.png
├── ex_scan.png
├── ex_seek.png
├── ex_setop.png
├── ex_sort.png
├── ex_subplan.png
├── ex_tid_scan.png
├── ex_unique.png
├── ex_unknown.png
├── fav.png
├── file_open.png
├── file_save.png
├── filter.png
├── foreignkey.png
├── group.png
├── hints
│ └── instrument.html
├── index.png
├── key.png
├── kwlist.h
├── pg.png
├── primarykey.png
├── query_cancel.png
├── query_execfile.png
├── query_execute.png
├── query_explain.png
├── setting.png
├── settingChanged.png
├── settingInternal.png
├── snippet.png
├── snippet_add.png
├── snippet_replace.png
├── snippets.png
├── statistics.png
└── user.png
├── new.png
├── node.py
├── notebook.py
├── page.py
├── property.png
├── refresh.png
├── requirements-mac.txt
├── tree.py
├── version.py
├── wh.py
├── wxWidgets.ico
├── xmlhelp.py
├── xmlres.py
└── xrced
├── XRCed_16.png
├── XRCed_32.png
├── encode_bitmaps.py
├── globals.py
├── images.py
├── license.txt
├── panel.py
├── params.py
├── tools.py
├── tree.py
├── undo.py
├── xrced.ico
├── xrced.py
├── xrced.xrc
└── xxx.py
/.gitignore:
--------------------------------------------------------------------------------
1 | __version.py
2 | .build/
3 | .DS_Store
4 | modXa
5 |
6 | # Nano
7 | *.swp
8 |
9 | # Byte-compiled / optimized / DLL files
10 | __pycache__/
11 | *.py[cod]
12 |
13 | # C extensions
14 | *.so
15 |
16 | # Distribution / packaging
17 | .Python
18 | env/
19 | bin/
20 | build/
21 | develop-eggs/
22 | dist/
23 | eggs/
24 | lib/
25 | lib64/
26 | parts/
27 | sdist/
28 | var/
29 | *.egg-info/
30 | .installed.cfg
31 | *.egg
32 |
33 | # Installer logs
34 | pip-log.txt
35 | pip-delete-this-directory.txt
36 |
37 | # Unit test / coverage reports
38 | htmlcov/
39 | .tox/
40 | .coverage
41 | .cache
42 | nosetests.xml
43 | coverage.xml
44 |
45 | # Translations
46 | *.mo
47 |
48 | # Mr Developer
49 | .mr.developer.cfg
50 |
51 | # Rope
52 | .ropeproject
53 |
54 | # Django stuff:
55 | *.log
56 | *.pot
57 |
58 | # Sphinx documentation
59 | docs/_build/
60 |
61 | /release
62 | /_update
63 |
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | Admin4
4 |
5 |
6 |
7 |
8 |
9 | org.python.pydev.PyDevBuilder
10 |
11 |
12 |
13 |
14 |
15 | org.python.pydev.pythonNature
16 |
17 |
18 |
19 | 1475337436558
20 |
21 | 22
22 |
23 | org.eclipse.ui.ide.multiFilter
24 | 1.0-name-matches-false-false-*.png
25 |
26 |
27 |
28 | 1475337436562
29 |
30 | 22
31 |
32 | org.eclipse.ui.ide.multiFilter
33 | 1.0-name-matches-false-false-*.ico
34 |
35 |
36 |
37 | 1475337436564
38 |
39 | 22
40 |
41 | org.eclipse.ui.ide.multiFilter
42 | 1.0-name-matches-false-false-*.xrc
43 |
44 |
45 |
46 | 1475337436566
47 |
48 | 10
49 |
50 | org.eclipse.ui.ide.multiFilter
51 | 1.0-name-matches-false-false-release
52 |
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/.pydevproject:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Python3.13
5 |
6 | python interpreter
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.ltk.core.refactoring.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false
3 |
--------------------------------------------------------------------------------
/.settings/org.springframework.ide.eclipse.xml.namespaces.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | org.springframework.ide.eclipse.xml.namespaces.default.version.check.classpath=true
3 | org.springframework.ide.eclipse.xml.namespaces.enable.project.preferences=false
4 | org.springframework.ide.eclipse.xml.namespaces.loadNamespaceHandlerFromClasspath=true
5 | org.springframework.ide.eclipse.xml.namespaces.use.https.for.new.namespace.locations=false
6 |
--------------------------------------------------------------------------------
/AboutDlg.xrc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | About
5 | 1
6 |
7 |
8 |
9 |
10 | Admin4.png
11 |
12 |
13 | wxTOP|wxBOTTOM|wxLEFT|wxRIGHT|wxGROW|wxALIGN_CENTRE_VERTICAL
14 | 10
15 |
16 |
17 |
18 |
19 | Version
20 |
21 |
22 | wxVERTICAL
23 |
24 |
25 | Admin4
26 |
27 | wxALIGN_CENTRE|wxTOP
28 | 20
29 |
30 |
31 |
32 | V1.x
33 |
34 | wxALIGN_CENTRE|wxTOP
35 | 10
36 | 1
37 |
38 |
39 |
40 | Revision
41 |
42 |
43 | wxALIGN_CENTRE|wxTOP
44 | 2
45 | 1
46 |
47 |
48 |
49 | Description
50 |
51 |
52 | wxALIGN_CENTRE|wxTOP
53 | 20
54 | 1
55 |
56 |
57 |
58 |
59 |
60 | Modules
61 |
62 |
63 | 250,-1d
64 |
65 | Copyright
66 |
67 |
68 |
69 |
70 |
71 | License
72 |
73 |
74 |
75 |
76 |
77 | 1
78 | wxTOP|wxBOTTOM|wxRIGHT|wxGROW
79 | 10
80 |
81 | 2
82 | 1
83 | 0
84 | 1
85 |
86 |
87 |
88 |
--------------------------------------------------------------------------------
/Admin4.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/Admin4.icns
--------------------------------------------------------------------------------
/Admin4.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/Admin4.ico
--------------------------------------------------------------------------------
/Admin4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/Admin4.png
--------------------------------------------------------------------------------
/Admin4Small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/Admin4Small.png
--------------------------------------------------------------------------------
/CHANGELOG:
--------------------------------------------------------------------------------
1 |
2 |
3 | V2 End Of Life
4 |
5 | modBind 0.98.8:
6 | - Fix for Bind9.9
7 | Core:
8 | - Fix splitValUnit() as reported by Catalin Mocanu
9 |
10 | modBind 0.98.7:
11 | CAA support (with modpython 1.15)
12 | BIND9.10 support
13 |
14 | modPg 0.5.10:
15 | Datatool sort DESC
16 | Table SQL
17 |
18 | modPg 0.5.9:
19 | roles 9.5+
20 |
21 | modImap 0.5.7:
22 | fix squat
23 |
24 | Changes in 2.2.2:
25 | Core:
26 | - skip verify SSL certificates when downloading updates
27 |
28 | Changes in 2.2.1:
29 | Core:
30 | - ver/rev/mods in update query url
31 | - restart application after update undone; doesn't work
32 | - fix for manual module update
33 | - Fix DisplayDialog to use Frame or Dialog as parentWin
34 | - self.dialog.node.GetCursor().ExecuteDictList
35 |
36 | modImap 0.5.6:
37 | - ACL fixes
38 | modImap 0.5.5:
39 | - recursion fixes
40 | modImap 0.5.4:
41 | - set/del Acl recursive
42 |
43 | modImap 0.5.3:
44 | - fix rights override when deleting for older cyrus
45 | - utf-8 workaround in annotations
46 |
47 | modImap 0.5.2:
48 | - setacl
49 | - acl change fix
50 | - acl who name checking
51 | - quota on Noselect mailboxes
52 |
53 | modBind 0.98.6:
54 | - Fix bool MayHaveChildren()
55 |
56 | modLdap 0.95.10:
57 | - Fix bool MayHaveChildren()
58 | - Squat flag support
59 |
60 | modPg 0.5.8:
61 | - fix connectionPool leak in DataTool
62 | - quoteIdent fixes
63 | - pg_stat_activity fixes
64 | - basic Column support
65 | modPg 0.5.7:
66 | - fix instrumentation if postgresql.conf not in data_directory (debian...)
67 |
68 |
69 | Changes in 2.2.0
70 | Core:
71 | - prepare to use wx 3.0.1.1 on Windows
72 | - fix png iCCS msgbox
73 | - fix shlexSplit with None Argument
74 | - fix node Delete handling in frame
75 | - check node MayHaveChildren in tree.Refresh()
76 | - remove module load restriction from config
77 | - floatToSize() with resolution
78 | - imaplib added (lib 2.1.9)
79 | - Version() work
80 |
81 | modLdap 0.95.9:
82 | - ldap group member candidate fix
83 |
84 | modPg 0.5.6:
85 | - sslmode in connectString was missing
86 |
87 | modImap 0.5.0:
88 | - new
89 |
90 |
91 | Changes in 2.1.9
92 | Core:
93 | - Fix binary download in online update
94 | - removeSmartQuote, quoteIfNeeded
95 |
96 | modPg 0.5.5:
97 | - optimize Favourites speed
98 |
99 | modBind 0.98.5:
100 | - Allow values with spaces as single string using quotes
101 |
102 | modLdap 0.95.8:
103 | - fix Samba code
104 |
105 |
106 | Changes in 2.1.8
107 | Core:
108 | - shlexSplit
109 |
110 | modPg 0.5.4:
111 | - minimal Sequence support
112 | - GrantCommentSql
113 | - Favourites fix
114 |
115 | modLdap 0.95.7:
116 | - fix crash when a duplicated attribute is deleted
117 | - smoother automatic RID generation
118 | - SambaAccount includes PosixAccount
119 | - fix SambaGroup
120 |
121 |
122 |
123 | Changes in 2.1.7
124 | Core:
125 | - Fix in Update Download SHA calculation
126 |
127 | modLdap 0.95.6:
128 | - fixes for uid/gid/rid generation
129 | - User with sambaAcctFlag [U]
130 |
131 |
132 |
133 | Changes in 2.1.6
134 | Core:
135 | - F5 refresh
136 | - fix in default FindObject when notFound
137 | - periodic automatic update
138 |
139 | modPg 0.5.3:
140 | - use SqlEditor in DataTool filter
141 | - ServerLog
142 | - Config page: better visualization of found entry, supports 8.1+
143 |
144 | modLdap 0.95.5:
145 | - fix SSHA password unicode error
146 |
147 | modBind 0.98.4:
148 | - remember position when editing zone record
149 |
150 |
151 |
152 | Changes in 2.1.5
153 | Core:
154 | - Shift key while starting suppresses auto-connect
155 | - two-level online update (major/minor)
156 | - FindObject
157 |
158 | modLdap 0.95.4:
159 | - FindObject in database
160 |
161 | modPg 0.5.2:
162 | - force client_encoding to utf8
163 | - FindObject in database
164 |
165 | modPg 0.5.1:
166 | - fix empty preset preventing Data Tool to come up
167 |
168 |
169 |
170 | Changes in 2.1.4
171 | Core:
172 | - Online update
173 | - fix in Frame.OnCall
174 | - support NotebookPage.availableOn
175 | - remember nodePath
176 | - refactoring of Menu()
177 |
178 | modLdap 0.95.3:
179 | - fix connect to non-instrumented Active Directory
180 | - fix multi-value octet attribs
181 |
182 | modBind 0.98.3:
183 | - check status connection
184 |
185 | modPg 0.5.0:
186 | - pgConnectionPool/pgCursor
187 | - improved QueryTool:
188 | - SQL Snippets
189 | - menu fix
190 | - QueryTool file functions
191 | - syntax highlighting
192 | - error marking
193 | - Data Tool including presets
194 |
195 |
196 |
197 | Changes in 2.1.3
198 | Core:
199 | - Core and Module update procedure
200 | - AskPassword remembers password
201 |
202 | modLdap 0.95.2:
203 | - updatable
204 |
205 | modBind 0.98.2:
206 | - updatable
207 |
208 |
209 |
210 | Changes in 2.1.2 (2014-04-30)
211 | Core:
212 | - centralized AskPassword
213 | - uint Validator length check fix
214 |
215 | modLdap 0.95.1:
216 | - cleanup ConnectionException
217 | - fix changing server properties
218 |
219 | modBind 0.98.1:
220 | - fix manual RemoveZone
221 | - add manual AddRevZone
222 |
--------------------------------------------------------------------------------
/Critical.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/Critical.png
--------------------------------------------------------------------------------
/Debug.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/Debug.png
--------------------------------------------------------------------------------
/Error.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/Error.png
--------------------------------------------------------------------------------
/FindPanel.xrc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | wxVERTICAL
6 |
7 |
8 | 1
9 | wxBOTTOM|wxRIGHT|wxEXPAND|wxGROW
10 | 5
11 |
12 |
13 |
14 | wxHORIZONTAL
15 |
16 |
17 | close_inactive.png
18 |
19 |
20 | wxRIGHT|wxALIGN_CENTRE_VERTICAL
21 | 5
22 |
23 |
24 |
25 | 80,-1d
26 |
27 |
28 | 1
29 | wxALIGN_CENTRE_VERTICAL
30 |
31 |
32 |
33 | find.png
34 |
35 | wxLEFT|wxRIGHT|wxALIGN_CENTRE_VERTICAL
36 | 5
37 |
38 |
39 | wxBOTTOM|wxLEFT|wxEXPAND
40 | 5
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/HOW-TO.md:
--------------------------------------------------------------------------------
1 | # Icons
2 | http://www.iconarchive.com/show/dragon-soft-icons-by-artua/Toolbox-icon.html
3 | http://www.iconarchive.com/show/oxygen-icons-by-oxygen-icons.org.html
4 |
5 | # Mac OSX 10.14:
6 |
7 | pip3 install dnspython
8 | pip3 install python-ldap
9 | pip3 install psycopg2-binary
10 | pip3 install wxPython
11 |
12 |
13 | ## for createBundle:
14 | pip3 install gitpython
15 | pip3 install py2app
16 |
17 | Eclipse/PyDev
18 | - tabsize 2
19 | - ignore name evt
20 | - ignore builtin names
21 |
22 |
--------------------------------------------------------------------------------
/HintDlg.xrc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Hint
5 | 200,200d
6 |
7 |
8 | wxVERTICAL
9 |
10 |
11 | 1
12 | wxLEFT|wxRIGHT|wxEXPAND
13 | 10
14 | 150,100d
15 |
16 |
17 |
18 | wxHORIZONTAL
19 |
20 |
21 | Don't show this hint again
22 | 1
23 |
24 | wxALIGN_LEFT|wxALIGN_CENTRE_VERTICAL
25 |
26 |
27 | 1
28 |
29 |
30 |
31 | OK
32 | 100,180d
33 | 1
34 |
35 | wxALIGN_RIGHT
36 |
37 |
38 | wxTOP|wxBOTTOM|wxLEFT|wxRIGHT|wxGROW
39 | 10
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/Info.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/Info.png
--------------------------------------------------------------------------------
/KNOWN-BUGS:
--------------------------------------------------------------------------------
1 | wxPython < 4.1.2:
2 | GridStringTable misses base class https://github.com/wxWidgets/wxWidgets/pull/22258
3 |
--------------------------------------------------------------------------------
/LogPanel.xrc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | wxVERTICAL
6 |
7 |
8 | 1
9 | wxEXPAND|wxGROW
10 |
11 |
12 |
13 |
14 |
15 | Refresh Rate
16 |
17 | wxALIGN_CENTRE_VERTICAL
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | wxALIGN_CENTRE_VERTICAL
26 | 50,-1d
27 |
28 |
29 |
30 | 2 seconds
31 |
32 | wxALIGN_CENTRE_VERTICAL
33 |
34 |
35 | wxEXPAND|wxGROW
36 |
37 |
38 |
39 | Clear
40 |
41 |
42 |
43 |
44 | Refresh
45 |
46 | wxRIGHT|wxALIGN_CENTRE_VERTICAL
47 |
48 | 6
49 | 10
50 | 2
51 |
52 | wxTOP|wxBOTTOM|wxALL|wxEXPAND|wxGROW
53 | 10
54 |
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/PagedPropertyDlg.xrc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Paged Property
5 |
6 |
7 | wxVERTICAL
8 |
9 |
10 | 1
11 | wxEXPAND
12 |
13 |
14 |
15 | wxHORIZONTAL
16 |
17 | 1
18 |
19 |
20 |
21 | Cancel
22 | 40,145d
23 | 45,15d
24 |
25 | wxBOTTOM|wxRIGHT
26 | 5d
27 |
28 |
29 |
30 | OK
31 | 95,145d
32 | 45,15d
33 |
34 | wxRIGHT
35 | 10
36 |
37 |
38 | wxBOTTOM|wxGROW
39 | 1
40 |
41 |
42 |
43 | wxEXPAND
44 | 12d
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/PasswordDlg.xrc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Password
5 | 1
6 |
7 |
8 | wxVERTICAL
9 |
10 |
11 | Password
12 |
13 | wxTOP|wxLEFT|wxRIGHT
14 | 10
15 |
16 |
17 |
18 | wxALL|wxGROW
19 | 10
20 |
21 |
22 |
23 | wxHORIZONTAL
24 |
25 |
26 | Remember password
27 |
28 | wxRIGHT|wxALIGN_CENTRE_VERTICAL
29 | 10
30 |
31 |
32 | 1
33 |
34 |
35 |
36 | Cancel
37 |
38 | wxLEFT|wxRIGHT
39 | 10
40 |
41 |
42 |
43 | Ok
44 |
45 |
46 |
47 |
48 | wxTOP|wxBOTTOM|wxLEFT|wxRIGHT|wxGROW
49 | 10
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/Preferences.xrc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | wxVERTICAL
6 |
7 |
8 | 2
9 | 5
10 | 5
11 | 1
12 |
13 |
14 | Confirm deletes
15 |
16 | wxALIGN_CENTRE_VERTICAL
17 |
18 |
19 |
20 |
21 | 1
22 |
23 |
24 |
25 |
26 | check for updates
27 |
28 | wxALIGN_CENTRE_VERTICAL
29 |
30 |
31 |
32 |
33 |
34 |
35 | Allow Prereleases
36 |
37 | wxALIGN_CENTRE_VERTICAL
38 |
39 |
40 |
41 |
42 | 1
43 |
44 |
45 |
46 |
47 | Proxy
48 |
49 | wxALIGN_CENTRE_VERTICAL
50 |
51 |
52 |
53 | wxALL|wxEXPAND
54 |
55 |
56 | 1
57 | wxALL|wxEXPAND|wxGROW
58 | 10
59 |
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/PreferencesDlg.xrc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Preferences
5 | 200,200d
6 |
7 |
8 | wxVERTICAL
9 |
10 |
11 | 5,5d
12 |
13 | wxLEFT|wxRIGHT|wxEXPAND
14 | 10
15 | 150,100d
16 |
17 |
18 |
19 | wxHORIZONTAL
20 |
21 | 1
22 |
23 |
24 |
25 | Cancel
26 | 50,180d
27 |
28 | wxLEFT|wxRIGHT
29 | 10
30 |
31 |
32 |
33 | OK
34 | 100,180d
35 |
36 |
37 |
38 |
39 | wxTOP|wxBOTTOM|wxLEFT|wxRIGHT|wxGROW
40 | 10
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/README.V2:
--------------------------------------------------------------------------------
1 | Development has moved to https://github.com/andreas-p/admin4, as are the release files.
2 |
3 | The following information is deprecated, please visit https://github.com/andreas-p/admin4/releases for the current
4 | V3 version.
5 |
6 | ----------------------------------------------------------------------------------------------------------
7 | For complete packages suitable for your platform, see the Vn.n.n directories.
8 | - Windows users: unzip the zip file and move the directory where you like and execute admin4.exe
9 | - Mac users: mount the dmg and move the app where you like.
10 | It might be necessary to right click Admin4 and select "Open" when starting it the first time, dependent on your security settings.
11 | If you continue to have problems starting Admin4, please report it here: https://github.com/andreas-p/admin4/issues/2
12 | - other systems: no packages available yet, use the source and install required python runtime and modules.
13 | Installation instructions and further documentation can be found at http://www.admin4.org/docs
14 |
15 | The Updates directory contains minor releases with bug fixes and additions based on major Vn.n.n files.
16 | It's recommended to use the online update feature which will automatically do the right thing, but you also can download a file and install it manually.
17 |
18 | Please note that most programming is performed on OSX, so if you encounter some strange behaviour on other platforms please don't hesitate to give feedback.
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | 
3 |
4 | # Admin4
5 |
6 | Admin4 is a tool for server maintenance via several plugin modules, running on Windows,
7 | Mac OSX, Linux and many more platforms. Currently, plugins for BIND DNS, LDAP, IMAP
8 | and PostgreSQL are included. It is designed as a framework, using Python
9 | for fast development of plugins and custom modifications.
10 |
11 |
12 | ## Features
13 |
14 | The **Bind DNS** plugin supports browsing and editing of DNS zones.
15 | The plugin should be able to query (axfr) any type of server, and
16 | performs updates via DDNS which insures that it won't interfere with other
17 | DDNS clients (DHCP, SAMBA4). For Bind 9.7 and up, statistics are supported
18 | as well and used to retrieve the server's zones automatically.
19 |
20 | The **LDAP** plugin features browsing and generic editing of all types of
21 | LDAP entries with schema support. In addition, high-level editing of objects
22 | like users, groups and samba domains is supported. Custom objectClasses and attributes
23 | can easily be added. The goal of the plugin was to replace the
24 | windows-only ldapadmin tool with a portable solution.
25 |
26 | The **IMAP** plugin supports browsing and maintaining of mailboxes
27 | for standard IMAP4 mail storage servers. In is an everyday replacement
28 | for cyradm for Cyrus IMAPD servers, and should work with other implementations too.
29 |
30 | The **PostgreSQL** plugin features a nice query tool, a data modification tool
31 | and an object browser. It's aimed to replace pgAdmin3/pgAdmin4 with a modified feature
32 | set targeted at professionals. It supports gui editing only for common tasks
33 | and objects to keep the GUI lean, and emphasizes on features that increase productivity
34 | like object favorites, sql snippets and filter presets.
35 |
36 | ## Implementation
37 |
38 | Python3.7+
39 | wxPython 4.1+
40 |
41 | ## Website
42 |
43 | https://admin4.org
44 |
45 |
46 |
--------------------------------------------------------------------------------
/TODO.md:
--------------------------------------------------------------------------------
1 | # TODO
2 |
3 | ## core
4 |
5 | - hide password preference
6 |
7 | - SSL certificate management
8 |
9 | ## modImap
10 |
11 | - check mailbox move target name
12 | - get/set other annotations for mailbox and server (no plans)
13 |
14 |
15 | ## modLdap
16 |
17 | #### New Object
18 | - default values preferences
19 |
20 | ignoreCert:
21 | ldap.OPT_X_TLS_ALLOW
22 |
23 | checkCert:
24 | - ldap.set_option(ldap.OPT_X_TLS_NEWCTX,ldap.OPT_X_TLS_DEMAND)
25 | - ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT,ldap.OPT_X_TLS_DEMAND)
26 | - ldap.set_option(ldap.OPT_X_TLS_CACERTFILE,certfile)
27 |
28 | #### objectClasses
29 |
30 | - mailGroup/member
31 | - groupOfUniqueNames/uniqueMember
32 |
33 | #### ToFix
34 |
35 | - PrimaryGroupSid
36 | - Group add description/displayname in list
37 | - deleteObjClass: remove attribs
38 | - nach rename refresh (2nd rename fails)
39 | - user.scs doppelt
40 |
41 | ## modPg
42 |
43 | ####Browser
44 |
45 | - update Favorites when deleting on
46 | - Triggers
47 | - Edit Table: Table, Column
48 |
49 | #### DataGrid
50 |
51 | - Drag/drop not from MouseDown for wx>3.0
52 | - OnFilterValidate and executeQuery catch error w/o logging
53 | - FK drilldown
54 | - float edit
55 |
56 | ShowBusy abort enable
57 |
58 | ResetPerspective
59 |
60 | ## modBind
61 |
62 | Check sanity of PTR data
63 |
--------------------------------------------------------------------------------
/UpdateDlg.xrc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Update
5 | 1
6 |
7 |
8 | wxVERTICAL
9 |
10 |
11 |
12 | Online Update
13 |
14 |
15 | 2
16 |
17 |
18 | Check for available update
19 |
20 | wxLEFT|wxALIGN_CENTRE_VERTICAL
21 | 10
22 |
23 |
24 |
25 | Check now
26 |
27 | wxTOP|wxBOTTOM|wxLEFT|wxRIGHT
28 | 10
29 |
30 |
31 |
32 |
33 |
34 | Manual Update
35 |
36 |
37 | wxVERTICAL
38 |
39 |
40 | wxHORIZONTAL
41 |
42 |
43 | Update source
44 |
45 | wxLEFT|wxALIGN_CENTRE_VERTICAL
46 | 10
47 |
48 |
49 |
50 | wxALL
51 | 10
52 | 100,-1d
53 |
54 |
55 |
56 | ...
57 | 12,12d
58 |
59 | wxRIGHT|wxALIGN_CENTRE_VERTICAL
60 | 10
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 | wxLEFT|wxRIGHT|wxEXPAND
69 | 10
70 |
71 |
72 |
73 | Update Info
74 | wxVERTICAL
75 |
76 |
77 | 150, 85d
78 |
79 |
80 | 1
81 | wxEXPAND
82 | 150, 55d
83 |
84 |
85 | 1
86 | wxBOTTOM|wxLEFT|wxRIGHT|wxGROW
87 | 10
88 |
89 |
90 |
91 | wxHORIZONTAL
92 |
93 | 1
94 |
95 |
96 |
97 | Cancel
98 |
99 | wxLEFT|wxRIGHT
100 | 10
101 |
102 |
103 |
104 | Ok
105 |
106 |
107 |
108 |
109 | wxTOP|wxBOTTOM|wxLEFT|wxRIGHT|wxGROW
110 | 10
111 |
112 |
113 |
114 |
115 |
--------------------------------------------------------------------------------
/admin4.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # The Admin4 Project
3 | # (c) 2013-2025 Andreas Pflug
4 | #
5 | # Licensed under the Apache License,
6 | # see LICENSE.TXT for conditions of usage
7 |
8 | if __name__ == "__main__":
9 | import sys, os
10 |
11 | loaddir=os.path.dirname(os.path.abspath(sys.argv[0]))
12 | sys.path.insert(0, loaddir)
13 | from main import main
14 | main(sys.argv)
15 |
--------------------------------------------------------------------------------
/close.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/close.png
--------------------------------------------------------------------------------
/close_inactive.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/close_inactive.png
--------------------------------------------------------------------------------
/connect.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/connect.png
--------------------------------------------------------------------------------
/delete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/delete.png
--------------------------------------------------------------------------------
/detach.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/detach.png
--------------------------------------------------------------------------------
/docker/Dockerfile:
--------------------------------------------------------------------------------
1 | # The Admin4 Project
2 | # (c) 2013-2022 Andreas Pflug
3 | #
4 | # Licensed under the Apache License,
5 | # see LICENSE.TXT for conditions of usage
6 | #
7 |
8 |
9 | FROM python:3.11.4-slim-bookworm
10 |
11 | RUN apt-get update && \
12 | apt-get install -y --no-install-recommends \
13 | wget python3-pip build-essential libgtk-3-dev python3-wxgtk4.0 \
14 | python3-requests python3-dnspython python3-ldap python3-psycopg2 && \
15 | apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* && \
16 | useradd -u 1000 admin4
17 |
18 | COPY admin4/ /admin4/
19 |
20 | WORKDIR /admin4
21 | ENV PYTHONPATH=/usr/local/lib/python3.11/site-packages:/usr/lib/python3/dist-packages
22 | CMD python3 admin4.py
23 |
--------------------------------------------------------------------------------
/docker/admin4:
--------------------------------------------------------------------------------
1 | ../.
--------------------------------------------------------------------------------
/docker/build-container.sh:
--------------------------------------------------------------------------------
1 | #! /bin/bash
2 |
3 | # The Admin4 Project
4 | # (c) 2013-2022 Andreas Pflug
5 | #
6 | # Licensed under the Apache License,
7 | # see LICENSE.TXT for conditions of usage
8 |
9 | cd ..
10 | python3 createBundle.py docker
11 |
--------------------------------------------------------------------------------
/docker/debug-container.sh:
--------------------------------------------------------------------------------
1 | #! /bin/bash
2 | #
3 | # The Admin4 Project
4 | # (c) 2013-2022 Andreas Pflug
5 | #
6 | # Licensed under the Apache License,
7 | # see LICENSE.TXT for conditions of usage
8 |
9 | if [ -z "$(xhost | grep LOCAL:)" ] ; then
10 | # allow local access
11 | xhost local:root
12 | fi
13 |
14 | # defaults to local image
15 | image=${1-adminfour/admin4:latest}
16 | shift
17 |
18 | IFS=":" read user _pwd uid gid _name home _shell <<< $(grep ^$(whoami): /etc/passwd)
19 |
20 | docker run -ti --rm --name admin4 $* \
21 | --net=host --env=DISPLAY=unix$DISPLAY \
22 | --volume /tmp/.X11-unix:/tmp/.X11-unix \
23 | --volume /etc/passwd:/etc/passwd \
24 | --volume $PWD/..:/src \
25 | --volume $home:$home \
26 | --user $uid:$gid \
27 | $image /bin/bash
28 |
29 |
--------------------------------------------------------------------------------
/docker/push-container.sh:
--------------------------------------------------------------------------------
1 | #! /bin/bash
2 | tag=${1-$(git tag | tail -1)}
3 | docker push adminfour/admin4:$tag
4 | docker push adminfour/admin4:latest
5 |
--------------------------------------------------------------------------------
/docker/run-container.sh:
--------------------------------------------------------------------------------
1 | #! /bin/bash
2 | #
3 | # The Admin4 Project
4 | # (c) 2013-2022 Andreas Pflug
5 | #
6 | # Licensed under the Apache License,
7 | # see LICENSE.TXT for conditions of usage
8 |
9 | if [ -z "$(xhost | grep LOCAL:)" ] ; then
10 | # allow local access
11 | xhost local:root
12 | fi
13 |
14 | image=${1-adminfour/admin4:latest}
15 | IFS=":" read user _pwd uid gid _name home _shell <<< $(grep ^$(whoami): /etc/passwd)
16 |
17 | docker run -ti --rm --name admin4 \
18 | --net=host --env=DISPLAY=unix$DISPLAY \
19 | --volume /tmp/.X11-unix:/tmp/.X11-unix \
20 | --volume /etc/passwd:/etc/passwd \
21 | --volume $home:$home \
22 | --user $uid:$gid \
23 | $image
24 |
25 |
--------------------------------------------------------------------------------
/edit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/edit.png
--------------------------------------------------------------------------------
/edit_find.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/edit_find.png
--------------------------------------------------------------------------------
/find.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/find.png
--------------------------------------------------------------------------------
/folder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/folder.png
--------------------------------------------------------------------------------
/logger.py:
--------------------------------------------------------------------------------
1 | # The Admin4 Project
2 | # (c) 2013-2022 Andreas Pflug
3 | #
4 | # Licensed under the Apache License,
5 | # see LICENSE.TXT for conditions of usage
6 |
7 |
8 | import time, traceback
9 |
10 | loglines=[]
11 | querylines=[]
12 | queryfile=None
13 | logfile=None
14 |
15 | class LOGLEVEL:
16 | NONE=0
17 | DEBUG=1
18 | INFO=2
19 | ERROR=3
20 | CRIT=4
21 | @staticmethod
22 | def Text(level):
23 | return ["None", "Debug", "Info", "Error", "Critical"][level]
24 | loglevel=LOGLEVEL.NONE
25 | querylevel=LOGLEVEL.NONE
26 |
27 |
28 | class _Line:
29 | def __init__(self):
30 | self.timestamp=time.time()
31 |
32 | def Timestamp(self):
33 | return time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(self.timestamp))
34 |
35 | def LevelText(self):
36 | return LOGLEVEL.Text(self.level)
37 |
38 | def LevelImageId(self):
39 | from adm import images
40 | if self.level:
41 | return images.GetId(self.LevelText())
42 | return -1
43 |
44 | def __getitem__(self, name):
45 | return self.__dict__.get(name)
46 |
47 |
48 |
49 | class LogLine(_Line):
50 | def __init__(self, level, text, tb=None):
51 | _Line.__init__(self)
52 | self.level=level
53 | self.text=text
54 | self.tb=tb
55 |
56 |
57 |
58 | class QueryLine(_Line):
59 | def __init__(self, level, cmd, error=None, result=None):
60 | _Line.__init__(self)
61 | self.level=level
62 | indent=-1
63 | lines=[]
64 | if cmd:
65 | for line in cmd.splitlines():
66 | line=line.rstrip()
67 | sline=line.lstrip()
68 | if not len(sline):
69 | continue
70 | if indent < 0:
71 | indent = len(line)-len(sline)
72 | lines.append(sline)
73 | else:
74 | ind=len(line)-len(sline) -indent
75 | empty=""
76 | for _i in range(ind):
77 | empty += " "
78 | lines.append(empty + sline)
79 | self.cmd = "\n".join(lines)
80 | self.error=error
81 | self.result=result
82 |
83 |
84 | def __getitem__(self, name):
85 | if name == 'err+result':
86 | if self.error:
87 | if self.result:
88 | return "%s - %s" % (self.error, self.result)
89 | else:
90 | return self.error
91 | return self.result
92 | return self.__dict__.get(name)
93 |
94 |
95 | if False:
96 | loglines.append( LogLine(LOGLEVEL.DEBUG, "Debug message", None))
97 | loglines.append( LogLine(LOGLEVEL.INFO, "info message", None))
98 | loglines.append( LogLine(LOGLEVEL.ERROR, "error message", None))
99 | loglines.append( LogLine(LOGLEVEL.CRIT, "critical message", None))
100 | querylines.append( QueryLine(LOGLEVEL.DEBUG, "Debug message", None, "Some weird result"))
101 | querylines.append( QueryLine(LOGLEVEL.ERROR, "error message", "Some failure", None))
102 |
103 |
104 |
105 | def _log(level, fmt, args, tb=None):
106 | if level < loglevel and not tb:
107 | return
108 |
109 | txt=fmt % args
110 | line=LogLine(level, txt, tb)
111 | loglines.append(line)
112 |
113 | if logfile:
114 | try:
115 | f=open(logfile, 'a')
116 | f.write("%s %s: %s\n" % (line.Timestamp(), line.LevelText(), txt))
117 | if tb:
118 | f.write("%s\n" % tb)
119 | except Exception as e:
120 | print ("CANNOT LOG", e)
121 | pass
122 |
123 |
124 | def trace(offset, level, fmt, *args):
125 | if True:
126 | txt=fmt % args
127 | stack=traceback.extract_stack()
128 | lst=[]
129 | for i in range(len(stack)-offset, len(stack)-offset-level, -1):
130 | file=stack[i][0].split('/')[-1]
131 | lst.append("%s (%s:%d)" % (stack[i][2], file, stack[i][1]))
132 | print (txt, "Stack:", " ".join(lst))
133 |
134 | def debug(fmt, *args):
135 | _log(LOGLEVEL.DEBUG, fmt, args)
136 |
137 | def error(fmt, *args):
138 | _log(LOGLEVEL.ERROR, fmt, args)
139 |
140 | def exception(fmt, *args):
141 | """
142 | exception(formatStr, [args])
143 |
144 | logs error and exception traceback
145 | """
146 | _log(LOGLEVEL.ERROR, fmt, args, traceback.format_exc())
147 |
148 | def sysexception(extype, args, tb):
149 | try: txtargs= " ".join(args)
150 | except: txtargs=""
151 | try: txttb="".join(traceback.format_tb(tb))
152 | except: txttb=""
153 | _log(LOGLEVEL.ERROR, "%s: %s %s", (extype.__name__, txtargs, txttb))
154 |
155 | def querylog(cmd, result=None, error=None):
156 | cmd=str(cmd)
157 | line=None
158 | if querylevel > LOGLEVEL.DEBUG or error:
159 | line=QueryLine(LOGLEVEL.ERROR, cmd, error, result)
160 | elif querylevel == LOGLEVEL.DEBUG:
161 | line=QueryLine(LOGLEVEL.DEBUG, cmd, error, result)
162 | if line:
163 | querylines.append(line)
164 |
165 | global queryfile
166 | if queryfile:
167 | try:
168 | f=open(queryfile, 'a')
169 | f.write(line.cmd)
170 | f.write("\n\n")
171 | f.close()
172 | except:
173 | _log(LOGLEVEL.ERROR, "Query Log File %s cannot be written.", queryfile)
174 | queryfile=None
175 |
--------------------------------------------------------------------------------
/modBind/CatalogHostRecord.xrc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | A/AAAA Record
5 |
6 | wxVERTICAL
7 |
8 |
9 | 2
10 |
11 |
12 | Primary Host
13 |
14 |
15 |
16 |
17 | 80,-1d
18 |
19 |
20 |
21 |
22 | IP Address
23 | 5,7d
24 |
25 |
26 |
27 |
28 | 50,5d
29 |
30 | 150,35d
31 |
32 |
33 |
34 |
35 |
36 | TTL
37 |
38 |
39 |
40 |
41 | 40,-1d
42 |
43 |
44 |
45 |
46 | AAAA TTL
47 |
48 |
49 |
50 |
51 | 40,-1d
52 |
53 |
54 | 10
55 | 10
56 |
57 | wxALL
58 | 10
59 |
60 |
61 |
62 | wxHORIZONTAL
63 |
64 | 1
65 | wxEXPAND
66 |
67 |
68 |
69 | Cancel
70 | 40,130d
71 | 45,-1d
72 |
73 | wxRIGHT
74 | 10
75 |
76 |
77 |
78 | OK
79 | 95,130d
80 | 45,-1d
81 |
82 |
83 |
84 | 1
85 | wxTOP|wxBOTTOM|wxRIGHT|wxEXPAND
86 | 10
87 |
88 |
89 |
90 |
91 |
--------------------------------------------------------------------------------
/modBind/CatalogMemberRecord.xrc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | DNS Record
5 |
6 | wxVERTICAL
7 |
8 |
9 | 2
10 |
11 |
12 | Host name
13 |
14 |
15 |
16 |
17 | 80,-1d
18 |
19 |
20 |
21 |
22 | Value
23 | 5,7d
24 |
25 |
26 |
27 |
28 | 50,5d
29 | 80,-1d
30 |
31 | wxGROW
32 |
33 |
34 |
35 | TTL
36 |
37 |
38 |
39 |
40 | 40,-1d
41 |
42 |
43 | 10
44 | 10
45 | 1
46 |
47 | wxALL|wxEXPAND|wxGROW
48 | 10
49 |
50 |
51 |
52 | wxHORIZONTAL
53 |
54 | 1
55 | wxEXPAND
56 |
57 |
58 |
59 | Cancel
60 | 40,130d
61 | 45,-1d
62 |
63 | wxRIGHT
64 | 10
65 |
66 |
67 |
68 | OK
69 | 95,130d
70 | 45,-1d
71 |
72 |
73 |
74 | 1
75 | wxTOP|wxBOTTOM|wxRIGHT|wxEXPAND
76 | 10
77 |
78 |
79 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/modBind/CatalogZone.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modBind/CatalogZone.png
--------------------------------------------------------------------------------
/modBind/HOWTO:
--------------------------------------------------------------------------------
1 |
2 | named.conf:
3 |
4 | acl "admin4" {
5 | key "rndc-key";
6 | };
7 |
8 | # BIND 9.7+
9 | statistics-channels {
10 | inet * port 8053
11 | allow { 127.0.0.1; 192.168.0.0/24; };
12 | };
13 |
14 | zones:
15 | allow-transfer { admin4; };
16 | allow-update { admin4; };
17 |
18 |
--------------------------------------------------------------------------------
/modBind/HostRecord.xrc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | A/AAAA Record
5 |
6 | wxVERTICAL
7 |
8 |
9 | 2
10 |
11 |
12 | Hostname
13 |
14 |
15 |
16 |
17 | 80,-1d
18 |
19 |
20 |
21 |
22 | IP Address
23 | 5,7d
24 |
25 |
26 |
27 |
28 | 50,5d
29 |
30 | 150,35d
31 |
32 |
33 |
34 |
35 |
36 | TTL
37 |
38 |
39 |
40 |
41 | 40,-1d
42 |
43 |
44 |
45 |
46 | AAAA TTL
47 |
48 |
49 |
50 |
51 | 40,-1d
52 |
53 |
54 |
55 |
56 | Create PTR Record
57 | 5,112d
58 |
59 |
60 |
61 |
62 |
63 | 1
64 | 50,112d
65 |
66 |
67 | 10
68 | 10
69 |
70 | wxALL
71 | 10
72 |
73 |
74 |
75 | wxHORIZONTAL
76 |
77 | 1
78 | wxEXPAND
79 |
80 |
81 |
82 | Cancel
83 | 40,130d
84 | 45,-1d
85 |
86 | wxRIGHT
87 | 10
88 |
89 |
90 |
91 | OK
92 | 95,130d
93 | 45,-1d
94 |
95 |
96 |
97 | 1
98 | wxTOP|wxBOTTOM|wxRIGHT|wxEXPAND
99 | 10
100 |
101 |
102 |
103 |
--------------------------------------------------------------------------------
/modBind/MultiValRecords.xrc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | DNS Record
5 |
6 | wxVERTICAL
7 |
8 |
9 | 2
10 |
11 |
12 | Host name
13 |
14 |
15 |
16 |
17 | 80,-1d
18 |
19 |
20 |
21 |
22 | TTL
23 |
24 |
25 |
26 |
27 | 40,-1d
28 |
29 |
30 | 10
31 | 10
32 | 1
33 |
34 | wxALL
35 | 10
36 |
37 |
38 |
39 | 50,5d
40 | 120,40d
41 |
42 | 1
43 | wxBOTTOM|wxLEFT|wxRIGHT|wxEXPAND|wxGROW
44 | 20
45 |
46 |
47 |
48 | wxHORIZONTAL
49 |
50 | 1
51 | wxEXPAND
52 |
53 |
54 |
55 | Cancel
56 | 40,130d
57 | 45,-1d
58 |
59 | wxRIGHT
60 | 10
61 |
62 |
63 |
64 | OK
65 | 95,130d
66 | 45,-1d
67 |
68 |
69 |
70 | wxTOP|wxBOTTOM|wxRIGHT|wxEXPAND
71 | 10
72 |
73 |
74 |
75 | wxEXPAND|wxGROW
76 | 10d
77 |
78 |
79 | 150,110d
80 |
81 |
82 |
--------------------------------------------------------------------------------
/modBind/RevZone.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modBind/RevZone.png
--------------------------------------------------------------------------------
/modBind/Server.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modBind/Server.png
--------------------------------------------------------------------------------
/modBind/SingleValRecord.xrc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | DNS Record
5 |
6 | wxVERTICAL
7 |
8 |
9 | 2
10 |
11 |
12 | Host name
13 |
14 |
15 |
16 |
17 | 80,-1d
18 |
19 |
20 |
21 |
22 | Value
23 | 5,7d
24 |
25 |
26 |
27 |
28 | 50,5d
29 | 80,-1d
30 |
31 | wxGROW
32 |
33 |
34 |
35 | TTL
36 |
37 |
38 |
39 |
40 | 40,-1d
41 |
42 |
43 | 10
44 | 10
45 | 1
46 |
47 | wxALL|wxEXPAND|wxGROW
48 | 10
49 |
50 |
51 |
52 | wxHORIZONTAL
53 |
54 | 1
55 | wxEXPAND
56 |
57 |
58 |
59 | Cancel
60 | 40,130d
61 | 45,-1d
62 |
63 | wxRIGHT
64 | 10
65 |
66 |
67 |
68 | OK
69 | 95,130d
70 | 45,-1d
71 |
72 |
73 |
74 | 1
75 | wxTOP|wxBOTTOM|wxRIGHT|wxEXPAND
76 | 10
77 |
78 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/modBind/SingleValRecords.xrc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | DNS Record
5 |
6 | wxVERTICAL
7 |
8 |
9 | 2
10 |
11 |
12 | Hostname
13 |
14 |
15 |
16 |
17 | 80,-1d
18 |
19 |
20 |
21 |
22 | Value
23 | 5,7d
24 |
25 |
26 |
27 |
28 | 50,5d
29 | 80,35d
30 |
31 |
32 | wxRIGHT|wxEXPAND|wxGROW
33 |
34 |
35 |
36 | TTL
37 |
38 |
39 |
40 |
41 | 40,-1d
42 |
43 |
44 | 10
45 | 10
46 | 1
47 |
48 | wxALL|wxEXPAND|wxGROW
49 | 10
50 |
51 |
52 |
53 | wxHORIZONTAL
54 |
55 | 1
56 | wxEXPAND
57 |
58 |
59 |
60 | Cancel
61 | 40,130d
62 | 45,-1d
63 |
64 | wxRIGHT
65 | 10
66 |
67 |
68 |
69 | OK
70 | 95,130d
71 | 45,-1d
72 |
73 |
74 |
75 | 1
76 | wxTOP|wxBOTTOM|wxRIGHT|wxEXPAND
77 | 10
78 |
79 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/modBind/Zone.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modBind/Zone.png
--------------------------------------------------------------------------------
/modBind/Zone.xrc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | DNS Zone
5 |
6 | User name
7 | 5,7d
8 |
9 |
10 | 50,5d
11 | 80,-1d
12 |
13 |
14 | Full name
15 | 5,22d
16 |
17 |
18 | 50,20d
19 | 80,-1d
20 |
21 |
22 |
23 | Role
24 | 5,37d
25 |
26 |
27 | 50,35d
28 | 80,-1d
29 |
30 |
31 |
32 | Password
33 | 5,52d
34 |
35 |
36 | 50,50d
37 | 80,-1d
38 |
39 |
40 | Enabled
41 | 5,67d
42 |
43 |
44 |
45 | 1
46 | 50,67d
47 |
48 |
49 | Cancel
50 | 40,100d
51 | 45,-1d
52 |
53 |
54 | OK
55 | 95,100d
56 | 45,-1d
57 |
58 | 150,120d
59 |
60 |
--------------------------------------------------------------------------------
/modBind/__init__.py:
--------------------------------------------------------------------------------
1 | # The Admin4 Project
2 | # (c) 2013-2025 Andreas Pflug
3 | #
4 | # Licensed under the Apache License,
5 | # see LICENSE.TXT for conditions of usage
6 |
7 | moduleinfo={ 'name': "BIND DNS Server",
8 | 'modulename': "BIND",
9 | 'description': "BIND9 DNS server",
10 | 'version': "9.18",
11 | 'revision': "0.99.10",
12 | 'requiredAdmVersion': "3.0.0",
13 | 'testedAdmVersion': "3.0.0",
14 | 'supports': "BIND V9.6 ... V9.18",
15 | 'copyright': "(c) 2014-2025 PSE Consulting Andreas Pflug",
16 | 'credits': "dnspython from http://www.dnspython.org",
17 | }
18 |
19 | import sys
20 | if not hasattr(sys, 'skipSetupInit'):
21 | from . import Server
22 |
23 |
--------------------------------------------------------------------------------
/modBind/_requires.py:
--------------------------------------------------------------------------------
1 | # The Admin4 Project
2 | # (c) 2013-2022 Andreas Pflug
3 | #
4 | # Licensed under the Apache License,
5 | # see LICENSE.TXT for conditions of usage
6 |
7 |
8 | # Mac OSX 10.8, 10.9:
9 | # xcode-select --install
10 | # sudo easy_install pip
11 | # sudo pip install dnspython
12 | # sudo pip install requests
13 | #
14 | # Debian:
15 | # apt-get install python-dnspython python-requests
16 | #
17 | # Windows:
18 | # http://www.dnspython.org
19 | # http://www.python-requests.org
20 |
21 |
22 | def GetPrerequisites(info=False):
23 | try:
24 | import dns.version
25 | if dns.version.version < "2.0.":
26 | if info:
27 | print ("dnspython too old")
28 | return None
29 | return "dns requests"
30 | except:
31 | if info:
32 | print ("dnspython missing")
33 | pass
34 | return None
35 |
--------------------------------------------------------------------------------
/modImap/Mailbox.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modImap/Mailbox.png
--------------------------------------------------------------------------------
/modImap/MailboxAcl.xrc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | wxVERTICAL
7 |
8 |
9 |
10 |
11 | User
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | 2
20 | 2
21 |
22 |
23 | wxVERTICAL
24 |
25 |
26 | Rights
27 |
28 |
29 |
30 | 1
31 | wxEXPAND
32 |
33 |
34 |
35 | Read only
36 |
37 | wxTOP
38 | 5d
39 |
40 |
41 |
42 | Read/write
43 |
44 | wxTOP
45 | 5d
46 |
47 |
48 |
49 | All
50 |
51 | wxTOP
52 | 5d
53 |
54 |
55 |
56 | None
57 |
58 | wxTOP
59 | 5d
60 |
61 |
62 | 1
63 | wxEXPAND
64 |
65 |
66 |
67 |
68 | 120,150d
69 |
70 | 1
71 | wxEXPAND|wxGROW
72 |
73 | 5d
74 | 5d
75 | 1
76 | 1
77 |
78 | 1
79 | wxTOP|wxLEFT|wxRIGHT|wxEXPAND
80 | 5d
81 |
82 |
83 |
84 | wxHORIZONTAL
85 |
86 | 1
87 | wxEXPAND
88 |
89 |
90 |
91 | Cancel
92 | 40,130d
93 | 45,-1d
94 |
95 | wxRIGHT
96 | 10
97 |
98 |
99 |
100 | OK
101 | 95,130d
102 | 45,-1d
103 |
104 |
105 |
106 | wxTOP|wxBOTTOM|wxRIGHT|wxEXPAND
107 | 10
108 |
109 |
110 | 12,12d
111 |
112 |
113 |
114 |
115 |
--------------------------------------------------------------------------------
/modImap/MailboxNoselect.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modImap/MailboxNoselect.png
--------------------------------------------------------------------------------
/modImap/Server.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modImap/Server.png
--------------------------------------------------------------------------------
/modImap/Server.py:
--------------------------------------------------------------------------------
1 | # The Admin4 Project
2 | # (c) 2022 Andreas Pflug
3 | #
4 | # Licensed under the Apache License,
5 | # see LICENSE.TXT for conditions of usage
6 |
7 | import adm
8 | from wh import xlt, YesNo
9 | from ._imap import ImapServer
10 |
11 | class Server(adm.ServerNode):
12 | shortname=xlt("IMAP4 Server")
13 | typename=xlt("IMAP4 Server")
14 | # findObjectIncremental=False
15 |
16 |
17 | def __init__(self, settings):
18 | adm.ServerNode.__init__(self, settings)
19 | self.userList=[]
20 | self.mailboxPath=""
21 |
22 | def IsConnected(self, _deep=False):
23 | return self.connection != None
24 |
25 |
26 | def Disconnect(self):
27 | if self.connection:
28 | self.connection.logout()
29 | self.connection=None
30 |
31 |
32 | def DoConnect(self):
33 | if not self.connection:
34 | self.connection=ImapServer.Create(self)
35 | self.connection.Login(self.user, self.password)
36 | self.flavor=self.connection.id.get('name', '').split()[0].lower()
37 | return self.connection
38 |
39 |
40 | def GetLastError(self):
41 | if self.connection and not self.connection.ok():
42 | return self.connection.lastError
43 | return None
44 |
45 |
46 | def GetProperties(self):
47 | if not self.properties:
48 | sec=self.settings['security']
49 | if sec.startswith('SSL'):
50 | pass
51 | elif sec.startswith('TLS'):
52 | if self.connection.tls: sec="TLS"
53 | else: sec=xlt("unsecured connection")
54 |
55 | self.annotations=self.connection.GetAnnotations("")
56 |
57 | self.properties= [
58 | ( xlt("Name"),self.name),
59 | ( xlt("Protocol"), self.connection.PROTOCOL_VERSION),
60 | ( xlt("Address"), self.address),
61 | ( xlt("Security"), sec),
62 | ( xlt("Port"), self.settings["port"]),
63 | ( xlt("User"), self.user),
64 | ( xlt("Connected"), YesNo(self.IsConnected())),
65 | ( xlt("Autoconnect"), YesNo(self.settings.get('autoconnect'))),
66 | ]
67 | self.AddProperty("Server", self.connection.id.get('name'))
68 | self.AddProperty("Version", self.connection.id.get('version'))
69 | if self.annotations:
70 | fs=self.annotations.Get('/freespace')
71 | if fs != None:
72 | self.AddSizeProperty(xlt("Free space"), float(fs)*1024)
73 |
74 | # if self.IsConnected():
75 | # self.AddChildrenProperty(list(self.connection.capabilities), xlt("Capabilities"), -1)
76 | return self.properties
77 |
78 |
79 | class Dlg(adm.ServerPropertyDialog):
80 | def __init__(self, parentWin, node):
81 | adm.PropertyDialog.__init__(self, parentWin, node, None)
82 | self['Security'].Append( { ' ': xlt("No security"), 'TLS-req': xlt("TLS required"), 'TLS-pref': xlt("TLS if available"), 'SSL': xlt("SSL") } )
83 | self.Bind("HostName HostAddress Port User Password Autoconnect")
84 | self.Bind("Security", self.OnChangeSecurity)
85 |
86 | def OnChangeSecurity(self, _evt):
87 | if self.security == "SSL":
88 | self.port=993
89 | else:
90 | self.port=143
91 |
92 | self.Check()
93 |
94 | def Go(self):
95 | if self.node:
96 | self.SetSettings(self.node.settings)
97 | self["HostName"].Disable()
98 | else:
99 | self.Security="TLS-req"
100 | self.OnCheck()
101 |
102 | def Check(self):
103 | ok=True
104 | if not self.node:
105 | ok=self.CheckValid(ok, self.Hostname, xlt("Host name cannot be empty"))
106 | ok=self.CheckValid(ok, not adm.config.existsServer(self, self.HostName), xlt("Host name already in use"))
107 | ok=self.CheckValid(ok, self.HostAddress, xlt("Host address cannot be empty"))
108 | ok=self.CheckValid(ok, self.Port, xlt("Port cannot be 0"))
109 | return ok
110 |
111 | def Save(self):
112 | if self.GetChanged():
113 | settings=self.GetSettings()
114 | adm.config.storeServerSettings(self, settings)
115 | if self.node:
116 | self.node.settings=settings
117 | self.node.registrationChanged=True
118 | else:
119 | adm.RegisterServer(settings)
120 | return True
121 |
122 | @staticmethod
123 | def Register(parentWin):
124 | adm.DisplayDialog(Server.Dlg, parentWin, None)
125 |
126 | def Edit(self, parentWin):
127 | adm.DisplayDialog(Server.Dlg, parentWin, self)
128 |
129 | nodeinfo=[ { 'class': Server, 'collection': xlt("IMAP4 Server") } ]
130 |
131 |
--------------------------------------------------------------------------------
/modImap/Server.xrc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | PostgreSQL Server
5 |
6 | wxVERTICAL
7 |
8 |
9 | 2
10 |
11 |
12 | Host name
13 | 5,7d
14 |
15 |
16 |
17 |
18 | 50,5d
19 | 80,-1d
20 |
21 |
22 |
23 |
24 | Host address
25 | 5,22d
26 |
27 |
28 |
29 |
30 | 50,20d
31 | 80,-1d
32 |
33 |
34 |
35 |
36 | SSL
37 | 5,37d
38 |
39 |
40 |
41 |
42 | 50,37d
43 |
44 |
45 |
46 |
47 | Port
48 | 5,52d
49 |
50 |
51 |
52 |
53 | 50,50d
54 | 143
55 | 35,-1d
56 |
57 |
58 |
59 |
60 | User
61 | 5,82d
62 |
63 |
64 |
65 |
66 | 50,80d
67 | root
68 | 80,-1d
69 |
70 |
71 |
72 |
73 | Password
74 | 5,97d
75 |
76 |
77 |
78 |
79 | 50,95d
80 | 80,-1d
81 |
82 |
83 |
84 |
85 | Auto connect
86 | 5,112d
87 |
88 |
89 |
90 |
91 |
92 | 1
93 | 50,112d
94 |
95 |
96 | 10
97 | 10
98 |
99 | wxALL
100 | 10
101 |
102 |
103 |
104 | wxHORIZONTAL
105 |
106 | 1
107 | wxEXPAND
108 |
109 |
110 |
111 | Cancel
112 | 40,130d
113 | 45,-1d
114 |
115 | wxRIGHT
116 | 10
117 |
118 |
119 |
120 | OK
121 | 95,130d
122 | 45,-1d
123 |
124 |
125 |
126 | 1
127 | wxTOP|wxBOTTOM|wxRIGHT|wxEXPAND
128 | 10
129 |
130 |
131 |
132 |
--------------------------------------------------------------------------------
/modImap/User.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modImap/User.png
--------------------------------------------------------------------------------
/modImap/__init__.py:
--------------------------------------------------------------------------------
1 | # The Admin4 Project
2 | # (c) 2022 Andreas Pflug
3 | #
4 | # Licensed under the Apache License,
5 | # see LICENSE.TXT for conditions of usage
6 |
7 |
8 | moduleinfo={ 'name': "IMAP Server",
9 | 'modulename': "IMAP",
10 | 'description': "IMAP server",
11 | 'version': "4",
12 | 'revision': "0.8.7",
13 | 'requiredAdmVersion': "3.0.0",
14 | 'testedAdmVersion': "3.0.0",
15 | 'pages': [],
16 | 'copyright': "(c) 2014-2022 PSE Consulting Andreas Pflug",
17 | 'credits': "utf-7 code from https://pypi.python.org/pypi/IMAPClient",
18 | }
19 |
20 |
21 | import sys
22 | if not hasattr(sys, 'skipSetupInit'):
23 | from . import Server
--------------------------------------------------------------------------------
/modImap/_requires.py:
--------------------------------------------------------------------------------
1 | # The Admin4 Project
2 | # (c) 2022 Andreas Pflug
3 | #
4 | # Licensed under the Apache License,
5 | # see LICENSE.TXT for conditions of usage
6 |
7 | def GetPrerequisites(_info=False):
8 | return "imaplib"
9 |
--------------------------------------------------------------------------------
/modImap/imap_utf7.py:
--------------------------------------------------------------------------------
1 | # The contents of this file has been derived code from the Twisted project
2 | # (http://twistedmatrix.com/). The original author is Jp Calderone.
3 |
4 | # Twisted project license follows:
5 |
6 | # Permission is hereby granted, free of charge, to any person obtaining
7 | # a copy of this software and associated documentation files (the
8 | # "Software"), to deal in the Software without restriction, including
9 | # without limitation the rights to use, copy, modify, merge, publish,
10 | # distribute, sublicense, and/or sell copies of the Software, and to
11 | # permit persons to whom the Software is furnished to do so, subject to
12 | # the following conditions:
13 | #
14 | # The above copyright notice and this permission notice shall be
15 | # included in all copies or substantial portions of the Software.
16 | #
17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 | # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 | # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 | # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 |
25 |
26 | # Modified for Pytho3: using str only
27 |
28 | class FolderNameError(ValueError):
29 | pass
30 |
31 |
32 | stdPattern=list(range(0x20, 0x2)) + list(range(0x27, 0x7f))
33 | def encode(s):
34 | if isinstance(s, str) and sum(n for n in (ord(c) for c in s) if n > 127):
35 | raise FolderNameError("%r contains characters not valid in a str folder name. "
36 | "Convert to unicode first?" % s)
37 |
38 | r = []
39 | _in = []
40 | for c in s:
41 | if ord(c) in stdPattern:
42 | if _in:
43 | r.extend(['&', modified_base64(''.join(_in)), '-'])
44 | del _in[:]
45 | r.append(str(c))
46 | elif c == '&':
47 | if _in:
48 | r.extend(['&', modified_base64(''.join(_in)), '-'])
49 | del _in[:]
50 | r.append('&-')
51 | else:
52 | _in.append(c)
53 | if _in:
54 | r.extend(['&', modified_base64(''.join(_in)), '-'])
55 | return ''.join(r)
56 |
57 |
58 | def decode(s):
59 | r = []
60 | decode = []
61 | for c in s:
62 | if c == '&' and not decode:
63 | decode.append('&')
64 | elif c == '-' and decode:
65 | if len(decode) == 1:
66 | r.append('&')
67 | else:
68 | r.append(modified_unbase64(''.join(decode[1:])))
69 | decode = []
70 | elif decode:
71 | decode.append(c)
72 | else:
73 | r.append(c)
74 | if decode:
75 | r.append(modified_unbase64(''.join(decode[1:])))
76 | out = ''.join(r)
77 |
78 | # if not isinstance(out, str):
79 | # out =out.decode('latin-1')
80 | return out
81 |
82 |
83 | def modified_base64(s):
84 | s_utf7 = s.encode('utf-7').decode()
85 | return s_utf7[1:-1].replace('/', ',')
86 |
87 |
88 | def modified_unbase64(s):
89 | s_utf7 = '+' + s.replace(',', '/') + '-'
90 | return s_utf7.encode().decode('utf-7')
91 |
--------------------------------------------------------------------------------
/modLdap/Computer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modLdap/Computer.png
--------------------------------------------------------------------------------
/modLdap/Contact.xrc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | wxVERTICAL
6 |
7 |
8 | 2
9 |
10 |
11 | Phone
12 |
13 |
14 |
15 |
16 | 100,20d
17 |
18 |
19 |
20 |
21 |
22 | Mobile phone
23 |
24 |
25 |
26 |
27 | 100,20d
28 |
29 |
30 |
31 |
32 |
33 | Home phone
34 |
35 |
36 |
37 |
38 |
39 | 100,20d
40 |
41 |
42 |
43 |
44 |
45 | Fax
46 |
47 |
48 |
49 |
50 | 100,-1d
51 |
52 |
53 |
54 |
55 | Pager
56 |
57 |
58 |
59 |
60 | 100,-1d
61 |
62 |
63 |
64 |
65 | Street
66 |
67 |
68 |
69 |
70 | 150,30d
71 |
72 |
73 | 1
74 |
75 | 10
76 | 10
77 |
78 |
79 | Zip, City
80 |
81 |
82 |
83 |
84 | wxHORIZONTAL
85 |
86 |
87 | 40,-1d
88 |
89 | wxRIGHT
90 | 5d
91 |
92 |
93 |
94 | 105,-1d
95 |
96 |
97 |
98 |
99 |
100 |
101 | State
102 |
103 |
104 |
105 |
106 | 150,-1d
107 |
108 |
109 | 1
110 |
111 |
112 | Mail
113 |
114 |
115 |
116 |
117 | 150,30d
118 |
119 |
120 |
121 |
122 | 1
123 | wxALL|wxEXPAND
124 | 5
125 |
126 |
127 |
128 |
--------------------------------------------------------------------------------
/modLdap/Entry.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modLdap/Entry.png
--------------------------------------------------------------------------------
/modLdap/GenericEntry.xrc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | wxVERTICAL
6 |
7 |
8 | 2
9 |
10 |
11 | RDN
12 |
13 | wxSTRETCH_NOT|wxALIGN_CENTRE_VERTICAL|wxADJUST_MINSIZE|wxFIXED_MINSIZE
14 |
15 |
16 |
17 | wxBOTTOM|wxEXPAND|wxALIGN_CENTRE_VERTICAL
18 | 5
19 |
20 |
21 |
22 | objectClasses
23 |
24 | wxRIGHT|wxSTRETCH_NOT|wxALIGN_CENTRE_VERTICAL|wxADJUST_MINSIZE|wxFIXED_MINSIZE
25 | 5
26 |
27 |
28 |
29 | wxHORIZONTAL
30 |
31 |
32 |
33 | - <All>
34 |
35 | 0
36 | 50,-1d
37 |
38 |
39 | 1
40 | wxALIGN_CENTRE_VERTICAL
41 |
42 |
43 |
44 | Del
45 | 30,-1d
46 |
47 | wxLEFT|wxRIGHT|wxALIGN_CENTRE_VERTICAL
48 | 5
49 |
50 |
51 |
52 | Add
53 | 30,-1d
54 |
55 | wxLEFT|wxALIGN_CENTRE_VERTICAL
56 | 5
57 |
58 |
59 | 1
60 | wxEXPAND
61 |
62 | 2
63 | 1
64 |
65 | 0
66 | wxTOP|wxLEFT|wxRIGHT|wxEXPAND
67 | 5
68 |
69 |
70 |
71 | 1
72 | wxALL|wxEXPAND
73 | 4
74 |
75 |
76 |
77 |
--------------------------------------------------------------------------------
/modLdap/Group.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modLdap/Group.png
--------------------------------------------------------------------------------
/modLdap/Group.xrc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | wxVERTICAL
6 |
7 |
8 | 2
9 |
10 |
11 | Name
12 |
13 |
14 |
15 |
16 | 80,-1d
17 |
18 |
19 | 10
20 | 10
21 |
22 |
23 | gid number
24 |
25 |
26 |
27 |
28 | wxHORIZONTAL
29 |
30 |
31 | 35,-1d
32 |
33 |
34 |
35 | 1
36 | wxEXPAND
37 |
38 |
39 |
40 | Generate
41 |
42 |
43 |
44 |
45 | wxEXPAND
46 |
47 |
48 |
49 | Display name
50 |
51 |
52 |
53 |
54 | wxEXPAND
55 |
56 |
57 |
58 | Description
59 |
60 |
61 |
62 |
63 | 1
64 | wxEXPAND
65 |
66 | 1
67 |
68 |
69 | wxVERTICAL
70 |
71 |
72 | Member
73 |
74 |
75 |
76 | 0,0
77 | 1
78 |
79 |
80 |
81 | Add
82 | 35,-1d
83 |
84 | wxTOP|wxBOTTOM|wxALIGN_RIGHT
85 | 5
86 |
87 |
88 |
89 | Delete
90 | 35,-1d
91 |
92 | wxALIGN_RIGHT
93 |
94 |
95 | 1
96 | wxEXPAND
97 |
98 |
99 |
100 | 1
101 | wxEXPAND
102 |
103 |
104 | wxALL|wxEXPAND
105 | 5
106 |
107 |
108 |
109 |
110 |
--------------------------------------------------------------------------------
/modLdap/Groups.xrc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | wxVERTICAL
6 |
7 |
8 | Member of groups
9 |
10 | wxALL
11 | 5
12 |
13 |
14 |
15 | 1
16 | wxBOTTOM|wxLEFT|wxRIGHT|wxEXPAND
17 | 5
18 |
19 |
20 |
21 | wxHORIZONTAL
22 |
23 |
24 | Add
25 | 45,-1d
26 |
27 |
28 |
29 |
30 | Delete
31 | 45,-1d
32 |
33 | wxLEFT
34 | 5
35 |
36 |
37 | wxALL
38 | 5
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/modLdap/OrgUnit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modLdap/OrgUnit.png
--------------------------------------------------------------------------------
/modLdap/Personal.xrc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | wxVERTICAL
6 |
7 |
8 | 2
9 |
10 |
11 | Company
12 |
13 |
14 |
15 |
16 | 100,20d
17 |
18 |
19 |
20 |
21 |
22 | Position
23 |
24 |
25 |
26 |
27 | 100,20d
28 |
29 |
30 |
31 |
32 |
33 | Office
34 |
35 |
36 |
37 |
38 | 100,-1d
39 |
40 |
41 |
42 |
43 | Home address
44 |
45 |
46 |
47 |
48 | 150,40d
49 |
50 |
51 |
52 | 10
53 | 10
54 | 1
55 |
56 | wxALL
57 | 5
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/modLdap/Posix.py:
--------------------------------------------------------------------------------
1 | # The Admin4 Project
2 | # (c) 2013-2022 Andreas Pflug
3 | #
4 | # Licensed under the Apache License,
5 | # see LICENSE.TXT for conditions of usage
6 |
7 |
8 | nodeinfo=[]
9 | from .SpecificEntry import SpecificEntry
10 | from .Entry import Entry
11 | from wh import xlt
12 | import wx, adm
13 |
14 |
15 | class UserAccount(SpecificEntry):
16 | name=xlt("Account")
17 | typename=xlt("LDAP User Account")
18 | shortname=xlt("User")
19 | icon="User"
20 | canClasses="inetorgperson"
21 | startClasses="inetOrgPerson"
22 |
23 | @classmethod
24 | def GetClassIconName(self, node):
25 | if node.HasObjectClass("sambaSAMAccount"):
26 | return "SamUser"
27 | elif node.HasObjectClass("posixAccount"):
28 | return "PosixUser"
29 | return self.icon
30 |
31 | @staticmethod
32 | def New(parentWin, parentNode):
33 | adm.DisplayDialog(Entry.Dlg, parentWin, None, parentNode, UserAccount)
34 |
35 | SpecificEntry.AddClass(UserAccount)
36 | Entry.addNewEntryClass(UserAccount)
37 |
38 |
39 |
40 | class ShadowAccount(SpecificEntry):
41 | name=xlt("POSIX/Shadow")
42 | def __init__(self, dlg, notebook, resname=None):
43 | SpecificEntry.__init__(self, dlg, notebook, resname)
44 | self.Bind("Expires", wx.EVT_CHECKBOX, self.OnExpire)
45 | self.Bind("GenerateUid", self.OnGenerateUid)
46 | self.Bind("GenerateGid", self.OnGenerateGid)
47 |
48 | def Go(self):
49 | SpecificEntry.Go(self)
50 | self.OnExpire()
51 |
52 | def OnGenerateUid(self, evt):
53 | if self.GetIdFromMax("posixAccount", "uidNumber"):
54 | self['GenerateUid'].Disable()
55 |
56 | def OnGenerateGid(self, evt):
57 | if self.GetIdFromMax("posixAccount", "gidNumber"):
58 | self['GenerateGid'].Disable()
59 |
60 |
61 | def Check(self):
62 | ok=SpecificEntry.Check(self)
63 |
64 | if self.dialog.HasObjectClass("posixAccount"):
65 | if not self.uidNumber and self.GetServer().GetIdGeneratorStyle():
66 | dn=self.GetServer().GetSambaUnixIdPoolDN()
67 | if not dn:
68 | if not self.dialog.HasObjectClass("sambaSamAccount"):
69 | ok=self.dialog.CheckValid(ok, dn, xlt("Need sambaUnixIdPoolDN configured for this server or Samba Account data"))
70 |
71 | return ok
72 |
73 |
74 | def OnExpire(self, ev=None):
75 | if self.shadowAccount:
76 | self.EnableControls("shadowExpire shadowWarning", self.Expires)
77 | if not self.Expires:
78 | self.shadowExpire=99999
79 | self.shadowWarning=None
80 | if ev:
81 | self.dialog.OnCheck()
82 | SpecificEntry.AddClass(ShadowAccount)
83 |
84 |
85 |
86 | class Contact(SpecificEntry):
87 | name=xlt("Contact")
88 | SpecificEntry.AddClass(Contact)
89 |
90 | class Personal(SpecificEntry):
91 | name=xlt("Personal")
92 | SpecificEntry.AddClass(Personal)
93 |
94 |
--------------------------------------------------------------------------------
/modLdap/PosixUser.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modLdap/PosixUser.png
--------------------------------------------------------------------------------
/modLdap/Preferences.xrc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Admin Entry RDN
6 | 5,7d
7 |
8 |
9 | 80,5d
10 | 80,-1d
11 |
12 |
13 | Password Hash
14 | 5,22d
15 |
16 |
17 |
18 | - SSHA
19 | - SMD5
20 | - SHA
21 | - MD5
22 | - CLEARTEXT
23 |
24 | 0
25 | 80,20d
26 | 80,-1d
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/modLdap/SamUser.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modLdap/SamUser.png
--------------------------------------------------------------------------------
/modLdap/SambaDomain.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modLdap/SambaDomain.png
--------------------------------------------------------------------------------
/modLdap/SambaGroupMapping.xrc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | wxVERTICAL
6 |
7 |
8 | Samba Group
9 |
10 | wxTOP|wxLEFT
11 | 5
12 |
13 |
14 |
15 | 2
16 |
17 |
18 | Samba SID
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 | Samba Group Type
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 | Samba Domain
39 |
40 | wxALIGN_CENTRE_VERTICAL
41 |
42 |
43 |
44 |
45 | 10
46 | 10
47 |
48 |
49 | Samba RID
50 |
51 |
52 | 1
53 |
54 |
55 | wxHORIZONTAL
56 |
57 |
58 | 40,-1d
59 |
60 |
61 |
62 | 1
63 | wxEXPAND
64 |
65 |
66 |
67 | Generate
68 |
69 |
70 |
71 |
72 | 1
73 | wxEXPAND
74 |
75 |
76 | wxTOP|wxLEFT|wxRIGHT|wxEXPAND
77 | 20
78 |
79 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/modLdap/Server.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modLdap/Server.png
--------------------------------------------------------------------------------
/modLdap/ServerConfig.xrc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Server Configuration
5 | 150,120d
6 |
7 | wxVERTICAL
8 |
9 |
10 |
11 |
12 | sambaUnixIdPool DN
13 |
14 | wxRIGHT|wxALIGN_CENTRE
15 | 5
16 |
17 |
18 |
19 | 1
20 | wxLEFT|wxRIGHT|wxGROW
21 | 5
22 |
23 | 2
24 | 1
25 |
26 | wxTOP|wxBOTTOM|wxLEFT|wxRIGHT|wxGROW
27 | 10
28 |
29 |
30 |
31 | UID/GID/RID Generation Style
32 |
33 | - currentMax+1
34 | - smbldap-tools
35 |
36 |
37 |
38 | wxTOP|wxLEFT|wxRIGHT
39 | 10
40 |
41 |
42 |
43 | Panel Resource Configuration
44 | wxVERTICAL
45 |
46 |
47 | 5,20d
48 |
49 | 1
50 | wxBOTTOM|wxRIGHT|wxGROW
51 | 5
52 | 100,30d
53 |
54 |
55 | 1
56 | wxTOP|wxLEFT|wxRIGHT|wxGROW
57 | 10
58 |
59 |
60 |
61 | wxHORIZONTAL
62 |
63 | 1
64 | wxGROW
65 |
66 |
67 |
68 | OK
69 | 95,160d
70 | 45,-1d
71 |
72 | wxRIGHT
73 | 10
74 |
75 |
76 |
77 | Cancel
78 | 40,160d
79 | 45,-1d
80 |
81 |
82 |
83 | wxTOP|wxBOTTOM|wxLEFT|wxRIGHT|wxGROW
84 | 10
85 |
86 |
87 |
88 |
89 |
--------------------------------------------------------------------------------
/modLdap/User.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modLdap/User.png
--------------------------------------------------------------------------------
/modLdap/UserAccount.xrc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | wxVERTICAL
6 |
7 |
8 | 2
9 |
10 |
11 | User ID
12 |
13 |
14 |
15 |
16 | 80,-1d
17 |
18 |
19 |
20 |
21 | Common Name
22 |
23 |
24 |
25 |
26 | 80,-1d
27 |
28 |
29 |
30 |
31 | Name
32 |
33 |
34 |
35 |
36 | wxALIGN_CENTRE_VERTICAL
37 |
38 | 10
39 | 10
40 |
41 |
42 | Title
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 | Given name
51 |
52 |
53 |
54 |
55 | wxHORIZONTAL
56 |
57 |
58 | 80,-1d
59 |
60 |
61 |
62 |
63 | Initial
64 |
65 | wxLEFT|wxALIGN_CENTRE_VERTICAL
66 | 20
67 |
68 |
69 |
70 | 50,-1d
71 |
72 | wxLEFT
73 | 10
74 |
75 |
76 |
77 |
78 |
79 | Display name
80 |
81 |
82 |
83 |
84 | wxEXPAND
85 |
86 |
87 |
88 | Description
89 |
90 |
91 |
92 |
93 | wxEXPAND
94 |
95 |
96 |
97 | Preferred Language
98 |
99 |
100 |
101 |
102 | 80,-1d
103 |
104 |
105 |
106 | wxALL
107 | 5
108 |
109 |
110 |
111 |
--------------------------------------------------------------------------------
/modLdap/_requires.py:
--------------------------------------------------------------------------------
1 | # The Admin4 Project
2 | # (c) 2013-2022 Andreas Pflug
3 | #
4 | # Licensed under the Apache License,
5 | # see LICENSE.TXT for conditions of usage
6 |
7 |
8 | # Mac OSX 10.8, 10.9:
9 | # xcode-select --install
10 | # sudo easy_install pip
11 | # sudo pip install python-ldap
12 | #
13 | # Debian:
14 | # apt-get install python-ldap
15 | #
16 | # Windows:
17 | # https://pypi.python.org/pypi/python-ldap
18 | # current:
19 | # https://pypi.python.org/packages/2.7/p/python-ldap/python-ldap-2.4.12.win32-py2.7.msi
20 | # alternate:
21 | # http://www.lfd.uci.edu/~gohlke/pythonlibs/
22 | #
23 | # other OS:
24 | # http://www.python-ldap.org/download.shtml
25 |
26 | def GetPrerequisites(info=False):
27 | try:
28 | import ldap
29 | if ldap.__version__ < "3.1.":
30 | if info:
31 | print ("ldap too old")
32 | return None
33 | import wx
34 | if wx.VERSION < (4,1):
35 | if info:
36 | print ("wxPython too old")
37 | return None
38 |
39 | return "ldap"
40 | except:
41 | if info:
42 | print ("ldap missing")
43 | pass
44 | return None
45 |
--------------------------------------------------------------------------------
/modLdap/attribEmpty.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modLdap/attribEmpty.png
--------------------------------------------------------------------------------
/modLdap/attribMay.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modLdap/attribMay.png
--------------------------------------------------------------------------------
/modLdap/attribMust.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modLdap/attribMust.png
--------------------------------------------------------------------------------
/modLdap/attribRDN.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modLdap/attribRDN.png
--------------------------------------------------------------------------------
/modLdap/hints/instrument.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Server %SERVERNAME% is not instrumented
5 |
6 | Server is not instrumented
7 |
8 | $APPNAME implements some advanced features, which require additional procedures and tables in the
9 | maintenance database to work. These advanced features are:
10 |
11 | aborting connections on the connection status page
12 | Favorite objects in the browser tree
13 | SQL code Snippets in the SQL query tool
14 | Filter Presets in the data tool
15 | modifying the server configuration for servers older than 9.4
16 |
17 | Favorites, Snippets and Presets are stored in database tables personal to the user you're using to connect, and are
18 | instantly available on every computer you're connecting from using $APPNAME.
19 |
20 | To prepare the server for improved handling through $APPNAME, execute the instrument
21 | context menu on the server object and close the connection. After re-opening the connection, the instrumentation
22 | state will be detected and the advanced features are available.
23 |
24 | Some instrumentation steps might need preparation before $APPNAME can complete them. Most notably, the adminpack contrib module
25 | must be installed on the server before $APPNAME can register the extension successfully.
26 |
27 | Note: The namespace used for configuration storage is configured in Preferences/PostgreSQL.
28 |
29 |
30 |
--------------------------------------------------------------------------------
/modLdap/objectClass.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modLdap/objectClass.png
--------------------------------------------------------------------------------
/modPg/ConnectDlg.xrc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Connect to database
5 |
6 | wxVERTICAL
7 |
8 |
9 | 2
10 |
11 |
12 | Database
13 |
14 |
15 | 10
16 | 10
17 | 1
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | User
27 |
28 |
29 |
30 |
31 | wxEXPAND
32 |
33 |
34 |
35 | Password
36 |
37 |
38 |
39 |
40 | wxEXPAND
41 |
42 |
43 | 1
44 | wxALL|wxEXPAND
45 | 10
46 |
47 |
48 |
49 | wxHORIZONTAL
50 |
51 | 1
52 |
53 |
54 |
55 | Cancel
56 |
57 | wxRIGHT
58 | 10
59 |
60 |
61 |
62 | OK
63 |
64 |
65 |
66 |
67 | wxBOTTOM|wxLEFT|wxRIGHT|wxEXPAND
68 | 10
69 |
70 |
71 |
72 | 12,12d
73 |
74 | wxEXPAND
75 |
76 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/modPg/ConnectionPage.xrc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | wxVERTICAL
6 |
7 |
8 | 1
9 | wxEXPAND|wxGROW
10 |
11 |
12 |
13 |
14 |
15 | Refresh Rate
16 |
17 | wxLEFT|wxRIGHT|wxALIGN_CENTRE_VERTICAL
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | wxALIGN_CENTRE_VERTICAL
26 | 50,-1d
27 |
28 |
29 |
30 | 2 seconds
31 |
32 | wxALIGN_CENTRE_VERTICAL
33 |
34 |
35 | wxEXPAND|wxGROW
36 |
37 |
38 |
39 | Refresh
40 |
41 | wxRIGHT|wxALIGN_CENTRE_VERTICAL
42 |
43 | 5
44 | 2
45 |
46 | wxTOP|wxBOTTOM|wxALL|wxEXPAND|wxGROW
47 | 10
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/modPg/DEBUG.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/DEBUG.png
--------------------------------------------------------------------------------
/modPg/Database-conn.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/Database-conn.png
--------------------------------------------------------------------------------
/modPg/Database-noconn.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/Database-noconn.png
--------------------------------------------------------------------------------
/modPg/Database.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/Database.png
--------------------------------------------------------------------------------
/modPg/ERROR.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/ERROR.png
--------------------------------------------------------------------------------
/modPg/FATAL.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/FATAL.png
--------------------------------------------------------------------------------
/modPg/Favourite.py:
--------------------------------------------------------------------------------
1 | # The Admin4 Project
2 | # (c) 2013-2022 Andreas Pflug
3 | #
4 | # Licensed under the Apache License,
5 | # see LICENSE.TXT for conditions of usage
6 |
7 |
8 | import adm
9 | from wh import xlt
10 | from .Schema import Schema
11 | from .Table import Table
12 | from .Sequence import Sequence
13 | from .View import View
14 | from .Function import Function
15 |
16 | class Favourites(adm.Node):
17 | typename=xlt("Favourites")
18 | shortname=xlt("Favourites")
19 | defaultname=xlt("unsorted")
20 | def __init__(self, parentNode):
21 | super(Favourites, self).__init__(parentNode, xlt(Favourites.defaultname))
22 |
23 | @staticmethod
24 | def GetInstances(parentNode):
25 | if parentNode.GetServer().fav_table:
26 | return [Favourites(parentNode)]
27 | return None
28 |
29 | def DoRefresh(self):
30 | for treename, fil in self.treeitems.items():
31 | tree=adm.trees[treename]
32 | favitem=fil[0] # tree.Collapse(favitem)
33 | for child in self.childnodes[:]:
34 | itemlist=child.treeitems.get(treename)
35 | if itemlist:
36 | for item in itemlist:
37 | if tree.IsChild(item, favitem):
38 | tree.DeleteItem(item)
39 | self.removeChild(child)
40 | self.properties=[]
41 |
42 | def GetProperties(self):
43 | self.properties=[]
44 | self.PopulateChildren()
45 | for child in self.childnodes:
46 | self.properties.append( (child.name, child.comment, child.GetIcon()))
47 | return self.properties
48 |
49 |
50 |
51 | class Favourite(adm.Node):
52 | typename=xlt("Favourite")
53 | shortname=xlt("Favourite")
54 |
55 | def DoRefresh(self):
56 | for c in self.childnodes:
57 | for treename, itemlist in c.treeitems.items():
58 | item=itemlist[0]
59 | tree=adm.trees[treename]
60 | itemlist=tree.GetChildItems(item)
61 |
62 | tree.Collapse(item)
63 | for item in itemlist:
64 | tree.DeleteItem(item)
65 |
66 | self.childnodes=[]
67 | self.properties=[]
68 | self.RefreshVolatile(True)
69 |
70 |
71 | @staticmethod
72 | def GetInstances(parentNode):
73 | instances=[]
74 | db=parentNode.parentNode
75 | if db.favourites:
76 | schemaOids=db.GetCursor().ExecuteList("SELECT DISTINCT relnamespace FROM pg_class WHERE oid IN (%s)" % ",".join(map(str, db.favourites)))
77 | coll=db.GetCollection(Schema)
78 | coll.PopulateChildren()
79 | schemanodes=[]
80 | schemaOids=db.GetCursor().ExecuteList("SELECT DISTINCT relnamespace FROM pg_class WHERE oid IN (%s)" % ",".join(map(str, db.favourites)))
81 | for schema in coll.childnodes:
82 | if schema.GetOid() in schemaOids:
83 | schemanodes.append(schema)
84 | schema.PopulateChildren()
85 |
86 | for schema in schemanodes:
87 | tables=schema.GetCollection(Table)
88 | for oid in db.favourites:
89 | t=tables.FindNode(Table, str(oid))
90 | if t:
91 | instances.append(t)
92 |
93 | for schema in schemanodes:
94 | views=schema.GetCollection(View)
95 | if views:
96 | for oid in db.favourites:
97 | v=views.FindNode(View, str(oid))
98 | if v:
99 | instances.append(v)
100 |
101 | for schema in schemanodes:
102 | funcs=schema.GetCollection(Function)
103 | if funcs:
104 | for oid in db.favourites:
105 | f=funcs.FindNode(Function, str(oid))
106 | if f:
107 | instances.append(f)
108 |
109 | for schema in schemanodes:
110 | sequences=schema.GetCollection(Sequence)
111 | if sequences:
112 | for oid in db.favourites:
113 | s=sequences.FindNode(Sequence, str(oid))
114 | if s:
115 | instances.append(s)
116 |
117 | return instances
118 |
119 |
120 |
121 | nodeinfo= [
122 | { "class" : Favourites, "parents": ["Database"], "sort": 80, },
123 | { "class" : Favourite, "parents": ["Favourites"], "sort": 80, }
124 | ]
125 |
126 | class AddFavourite:
127 | name=xlt("Add Favourite")
128 | help=xlt("Make object a favourite")
129 |
130 | @staticmethod
131 | def CheckAvailableOn(node):
132 | return hasattr(node, 'favtype') and node.GetOid() not in node.GetDatabase().favourites and node.GetServer().fav_table
133 |
134 | @staticmethod
135 | def OnExecute(_parentwin, node):
136 | node.GetServer().AddFavourite(node)
137 | favgroup=xlt(Favourites.defaultname)
138 | fav=node.GetDatabase().FindNode(Favourites, favgroup)
139 | if not fav:
140 | fav=Favourites(node.GetDatabase(), favgroup)
141 | node.GetDatabase().appendNode(fav)
142 |
143 | if fav.childnodes and not node in fav.childnodes:
144 | fav.appendChild(node)
145 | return True
146 |
147 | class DelFavourite:
148 | name=xlt("Delete Favourite")
149 | help=xlt("Delete object from favourite list")
150 |
151 | @staticmethod
152 | def CheckAvailableOn(node):
153 | return hasattr(node, 'favtype') and node.GetOid() in node.GetDatabase().favourites and node.GetServer().fav_table
154 |
155 |
156 | @staticmethod
157 | def OnExecute(_parentwin, node):
158 | node.GetServer().DelFavourite(node)
159 | return True
160 |
161 |
162 |
163 | menuinfo = [
164 | { "class" : AddFavourite, "nodeclasses" : Table, 'sort': 40 },
165 | { "class" : DelFavourite, "nodeclasses" : Table, 'sort': 40 },
166 | ]
167 |
--------------------------------------------------------------------------------
/modPg/Favourites.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/Favourites.png
--------------------------------------------------------------------------------
/modPg/Function.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/Function.png
--------------------------------------------------------------------------------
/modPg/Function.py:
--------------------------------------------------------------------------------
1 | # The Admin4 Project
2 | # (c) 2013-2022 Andreas Pflug
3 | #
4 | # Licensed under the Apache License,
5 | # see LICENSE.TXT for conditions of usage
6 |
7 |
8 | from ._objects import SchemaObject
9 | from ._pgsql import pgQuery
10 | from wh import xlt, YesNo
11 | import logger
12 |
13 |
14 | class Function(SchemaObject):
15 | typename=xlt("Function")
16 | shortname=xlt("Function")
17 | refreshOid="pro.oid"
18 | allGrants='X'
19 | favtype='f'
20 | relkind='P'
21 |
22 |
23 |
24 | @staticmethod
25 | def FindQuery(schemaName, schemaOid, patterns):
26 | sql=pgQuery("pg_proc p")
27 | sql.AddCol("'P' as kind")
28 | sql.AddCol("nspname")
29 | sql.AddCol("proname as name")
30 | sql.AddCol("n.oid as nspoid")
31 | sql.AddCol("p.oid")
32 | sql.AddJoin("pg_namespace n ON n.oid=pronamespace")
33 | SchemaObject.AddFindRestrictions(sql, schemaName, schemaOid, 'proname', patterns)
34 | return sql
35 |
36 |
37 | @staticmethod
38 | def InstancesQuery(parentNode):
39 | sql=pgQuery("pg_proc pro")
40 | sql.AddCol("pro.oid, pg_get_userbyid(proowner) AS owner, proacl as acl, proname as name, pro.*, nspname, ns.oid as nspoid, lanname, description")
41 | if parentNode.GetServer().version >= 8.4:
42 | sql.AddCol("pg_get_function_arguments(pro.oid) as arguments, pg_get_function_result(pro.oid) as result")
43 | sql.AddJoin("pg_language lang ON lang.oid=prolang")
44 | sql.AddLeft("pg_namespace ns ON ns.oid=pronamespace")
45 | sql.AddLeft("pg_description des ON (des.objoid=pro.oid AND des.objsubid=0)")
46 | sql.AddWhere("pronamespace", parentNode.parentNode.GetOid())
47 | sql.AddOrder("proname")
48 | return sql
49 |
50 | def __init__(self, parentNode, info):
51 | super(Function, self).__init__(parentNode, info)
52 | args=self.info.get('arguments')
53 | if args!= None:
54 | self.name="%s(%s)" % (self.name, args)
55 |
56 | def GetIcon(self):
57 | icons=[]
58 | icons.append("Function")
59 | if self.GetOid() in self.GetDatabase().favourites:
60 | icons.append('fav')
61 | return self.GetImageId(icons)
62 |
63 |
64 | def GetSql(self):
65 | definition=self.info.get('definition')
66 | if not definition:
67 | definition=self.GetCursor().ExecuteSingle("SELECT pg_get_functiondef(%d)" % self.GetOid())
68 | self.info['definition']=definition[:-1] + ";"
69 | return "%(def)s\n%(grant)s" % {
70 | 'object': self.ObjectSql(),
71 | 'def': definition, 'grant': self.GrantCommentSql() }
72 |
73 |
74 | def GetProperties(self):
75 | if not len(self.properties):
76 | args=self.info.get('arguments')
77 | if args == None:
78 | logger.error("PGSQL < 8.4; no function args/returns")
79 | args=""
80 | self.info['arguments']=""
81 | self.info['result']=""
82 | self.info['definition']=None
83 | result=self.info.get('result', "")
84 | self.properties = [
85 | (xlt("Name"), "%s(%s)" % (self.info['name'], args)),
86 | (xlt("Namespace"), self.info['nspname']),
87 | (xlt("Language"), self.info['lanname']),
88 | (xlt("Strict"), YesNo(self.info['proisstrict'])),
89 | ( "OID" , self.info['oid']),
90 | (xlt("Returns"), result),
91 | (xlt("Owner"), self.info['owner']),
92 | (xlt("ACL"), self.info['acl'])
93 | ]
94 |
95 | self.AddProperty(xlt("Description"), self.info['description'])
96 | return self.properties
97 |
98 |
99 | nodeinfo= [ { "class" : Function, "parents": ["Schema"], "sort": 60, "collection": "Functions", "pages": ["SqlPage"] } ]
100 |
101 |
102 |
--------------------------------------------------------------------------------
/modPg/LOG.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/LOG.png
--------------------------------------------------------------------------------
/modPg/LoggingPage.xrc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | wxVERTICAL
6 |
7 |
8 | 1
9 | wxBOTTOM|wxRIGHT|wxEXPAND|wxGROW
10 | 5
11 |
12 |
13 |
14 |
15 |
16 | Refresh Rate
17 |
18 | wxALIGN_CENTRE_VERTICAL
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | wxALIGN_CENTRE_VERTICAL
27 | 50,-1d
28 |
29 |
30 |
31 | 2 seconds
32 |
33 | wxALIGN_CENTRE_VERTICAL
34 |
35 |
36 |
37 |
38 |
39 |
40 | 1
41 | wxEXPAND
42 |
43 |
44 | wxEXPAND|wxGROW
45 |
46 |
47 |
48 | Rotate
49 |
50 |
51 | wxALIGN_CENTRE_VERTICAL
52 |
53 |
54 |
55 | Refresh
56 |
57 | wxRIGHT|wxALIGN_CENTRE_VERTICAL
58 |
59 | 7
60 | 10
61 | 3
62 |
63 | wxEXPAND
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/modPg/LoglineDlg.xrc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Logline
5 | 200,200d
6 |
7 |
8 | wxVERTICAL
9 |
10 |
11 | 1
12 | wxLEFT|wxRIGHT|wxEXPAND
13 | 10
14 | 150,100d
15 |
16 |
17 |
18 | wxHORIZONTAL
19 |
20 |
21 | Query Tool
22 |
23 |
24 |
25 |
26 | 1
27 |
28 |
29 |
30 | OK
31 | 100,180d
32 | 1
33 |
34 |
35 |
36 |
37 | wxTOP|wxBOTTOM|wxLEFT|wxRIGHT|wxGROW
38 | 10
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/modPg/MatView.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/MatView.png
--------------------------------------------------------------------------------
/modPg/Partition.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/Partition.png
--------------------------------------------------------------------------------
/modPg/PartitionedTable.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/PartitionedTable.png
--------------------------------------------------------------------------------
/modPg/Preferences.xrc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | wxVERTICAL
6 |
7 |
8 | 2
9 |
10 |
11 | Admin Namespace
12 | 5,7d
13 |
14 | wxALIGN_CENTRE_VERTICAL
15 |
16 |
17 |
18 | 80,5d
19 | 80,-1d
20 |
21 | wxGROW
22 |
23 |
24 |
25 | Category sort
26 | 5,22d
27 |
28 | wxALIGN_CENTRE_VERTICAL
29 |
30 |
31 |
32 | 80,20d
33 | 80,-1d
34 |
35 | wxGROW
36 |
37 | 5d
38 | 5d
39 | 1
40 |
41 | 1
42 | wxALL|wxGROW
43 | 5d
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/modPg/PrivilegePanel.xrc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | wxVERTICAL
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/modPg/Role.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/Role.png
--------------------------------------------------------------------------------
/modPg/Role.py:
--------------------------------------------------------------------------------
1 | # The Admin4 Project
2 | # (c) 2013-2022 Andreas Pflug
3 | #
4 | # Licensed under the Apache License,
5 | # see LICENSE.TXT for conditions of usage
6 |
7 |
8 | import adm
9 | from wh import xlt, YesNo, prettyDate
10 |
11 | class Role(adm.Node):
12 | typename=xlt("Role")
13 | shortname=xlt("Role")
14 |
15 | @staticmethod
16 | def GetInstances(parentNode):
17 | instances=[]
18 | rowset=parentNode.GetConnection().GetCursor().ExecuteSet("""
19 | SELECT rolname as name, *,
20 | (SELECT array_agg(rolname) FROM pg_roles r JOIN pg_auth_members m on r.oid=m.member WHERE m.roleid=u.oid) AS members,
21 | (SELECT array_agg(rolname) FROM pg_roles r JOIN pg_auth_members m on r.oid=m.roleid WHERE m.member=u.oid) AS memberof
22 | FROM pg_roles u ORDER BY rolname""")
23 | if rowset:
24 | for row in rowset:
25 | if not row:
26 | break
27 | instances.append(Role(parentNode, row['name'], row.getDict()))
28 | return instances
29 |
30 | def __init__(self, parentNode, name, info):
31 | super(Role, self).__init__(parentNode, name)
32 | self.info=info
33 |
34 | def GetIcon(self):
35 | icons=[]
36 | if self.info['members']:
37 | icons.append("Group")
38 | else:
39 | icons.append("User")
40 | return self.GetImageId(icons)
41 |
42 |
43 | def GetProperties(self):
44 | if not len(self.properties):
45 |
46 | self.properties = [
47 | (xlt("Name"), self.name, self.GetImageId('Role')),
48 | ( "OID", self.info['oid']),
49 | (xlt("Can Login"), YesNo(self.info['rolcanlogin'])),
50 | (xlt("Superuser"), YesNo(self.info['rolsuper'])),
51 | (xlt("Catalog Update"), YesNo(self.info['rolcatupdate'])),
52 | (xlt("Create DB"), YesNo(self.info['rolcreatedb'])),
53 | (xlt("Create Role"), YesNo(self.info['rolcreaterole'])),
54 | (xlt("Inherits rights"), YesNo(self.info['rolinherit'])),
55 | ]
56 | until=self.info['rolvaliduntil']
57 | if not until or until.year == 9999:
58 | until=xlt("never")
59 | else:
60 | until=prettyDate(until)
61 | self.properties.append((xlt("Expires"), until))
62 |
63 | self.AddChildrenProperty(self.info['memberof'], xlt("Member of"), self.GetImageId("Group"))
64 | self.AddChildrenProperty(self.info['members'], xlt("Members"), self.GetImageId("User"))
65 | self.AddChildrenProperty(self.info['rolconfig'], xlt("Variables"), -1)
66 |
67 | return self.properties
68 |
69 |
70 | class RolesPage(adm.NotebookPage):
71 | name=xlt("Roles")
72 | order=50
73 | availableOn="Server"
74 | roleFlags={'rolcreaterole': 'createRole',
75 | 'rolcreatedb': 'crDb',
76 | 'rolcatupdate': 'catUpd',
77 | 'rolreplication': 'repl'
78 | }
79 |
80 | def Display(self, node, _detached):
81 | if node != self.lastNode:
82 | self.lastNode=node
83 |
84 | def members(row):
85 | d=row['members']
86 | if d: return ",".join(d)
87 | def flags(row):
88 | fl=[]
89 | for key, desc in self.roleFlags.items():
90 | if row.get(key):
91 | fl.append(desc)
92 | return" ".join(fl)
93 |
94 | add=self.control.AddColumnInfo
95 | add(xlt("Name"), 20, colname='name')
96 | add(xlt("Flags"), 25, proc=flags)
97 | add(xlt("Members"), 40, proc=members)
98 |
99 | values=[]
100 |
101 | self.allRoles=node.GetConnection().GetCursor().ExecuteDictList("""
102 | SELECT rolname as name, *,
103 | (SELECT array_agg(rolname) FROM pg_roles r JOIN pg_auth_members m on r.oid=m.member WHERE m.roleid=u.oid) AS members,
104 | (SELECT array_agg(rolname) FROM pg_roles r JOIN pg_auth_members m on r.oid=m.roleid WHERE m.member=u.oid) AS memberof
105 | FROM pg_roles u ORDER BY rolname""")
106 |
107 | for role in self.allRoles:
108 | # rolsuper, rolcreaterole, colcreatedb, rolcanupdate
109 | icons=[]
110 | if role['members']:
111 | icons.append("group")
112 | elif role['rolsuper']:
113 | icons.append('admin')
114 | else:
115 | icons.append("user")
116 | if role['rolcanlogin']:
117 | icons.append('key')
118 |
119 | icon=self.lastNode.GetImageId(icons)
120 | values.append( (role, icon))
121 | self.control.Fill(values, 'name')
122 |
123 | pageinfo=[RolesPage]
124 | nodeinfo=[]
125 | #nodeinfo= [ { "class" : Role, "parents": ["Server"], "sort": 70, "collection": xlt("Roles") } ]
--------------------------------------------------------------------------------
/modPg/Roles.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/Roles.png
--------------------------------------------------------------------------------
/modPg/Schema.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/Schema.png
--------------------------------------------------------------------------------
/modPg/Schema.py:
--------------------------------------------------------------------------------
1 | # The Admin4 Project
2 | # (c) 2013-2022 Andreas Pflug
3 | #
4 | # Licensed under the Apache License,
5 | # see LICENSE.TXT for conditions of usage
6 |
7 |
8 | from ._objects import DatabaseObject
9 | from ._pgsql import pgQuery
10 | from wh import xlt
11 |
12 |
13 | class Schema(DatabaseObject):
14 | typename=xlt("Schema")
15 | shortname=xlt("Schema")
16 | refreshOid="nsp.oid"
17 |
18 | sysNamespaces=['pg_toast', 'pg_catalog', 'information_schema']
19 |
20 | @staticmethod
21 | def InstancesQuery(parentNode):
22 | sql=pgQuery("pg_namespace nsp")
23 | sql.AddCol("nsp.oid, nspacl, nspname as name, pg_get_userbyid(nspowner) AS owner, description")
24 | sql.AddLeft("pg_description des ON des.objoid=nsp.oid")
25 | sql.AddWhere("nspname not in (%s)" % ",".join(map(lambda x: "'%s'" % x, Schema.sysNamespaces)))
26 | sql.AddOrder("nspname")
27 | return sql
28 |
29 |
30 | def GetIcon(self):
31 | icons=[]
32 | icons.append("Schema")
33 | if self.name in self.sysNamespaces:
34 | icons.append('pg')
35 | return self.GetImageId(icons)
36 |
37 | def GetSchemaOid(self):
38 | return self.GetOid()
39 |
40 |
41 | def GetProperties(self):
42 | if not len(self.properties):
43 |
44 | self.properties = [
45 | (xlt("Name"), self.name),
46 | ( "OID" , self.info['oid']),
47 | (xlt("Owner"), self.info['owner']),
48 | (xlt("ACL"), self.info['nspacl'])
49 | ]
50 |
51 | self.AddProperty(xlt("Description"), self.info['description'])
52 | return self.properties
53 |
54 |
55 | nodeinfo= [ { "class" : Schema, "parents": ["Database"], "sort": 4, "collection": xlt("Schemas"), } ]
56 |
--------------------------------------------------------------------------------
/modPg/Sequence.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/Sequence.png
--------------------------------------------------------------------------------
/modPg/Sequence.py:
--------------------------------------------------------------------------------
1 | # The Admin4 Project
2 | # (c) 2013-2022 Andreas Pflug
3 | #
4 | # Licensed under the Apache License,
5 | # see LICENSE.TXT for conditions of usage
6 |
7 | from ._objects import SchemaObject
8 | from ._pgsql import pgQuery
9 | from wh import xlt
10 | import adm
11 |
12 |
13 |
14 | class Sequence(SchemaObject):
15 | typename=xlt("Sequence")
16 | shortname=xlt("Sequence")
17 | refreshOid="rel.oid"
18 | allGrants="rwU"
19 | favtype='s'
20 | relkind='S'
21 |
22 | @staticmethod
23 | def FindQuery(schemaName, schemaOid, patterns):
24 | sql=pgQuery("pg_class c")
25 | sql.AddCol("relkind as kind")
26 | sql.AddCol("nspname")
27 | sql.AddCol("relname as name")
28 | sql.AddCol("n.oid as nspoid")
29 | sql.AddCol("c.oid")
30 | sql.AddJoin("pg_namespace n ON n.oid=relnamespace")
31 | sql.AddWhere("relkind='S'")
32 | SchemaObject.AddFindRestrictions(sql, schemaName, schemaOid, 'relname', patterns)
33 | return sql
34 |
35 |
36 | def GetSql(self):
37 | if not self.properties:
38 | self.GetProperties()
39 | return """CREATE SEQUENCE %(name)s
40 | MINVALUE %(min)d MAXVALUE %(max)d INCREMENT %(inc)d
41 | CACHE %(cache)d START %(start)d;
42 |
43 | %(grant)s""" % {
44 | 'name': self.NameSql(),
45 | 'tablespace': self.TablespaceSql(),
46 | 'min': self.info['min_value'],
47 | 'max': self.info['max_value'],
48 | 'inc': self.info['increment_by'],
49 | 'cache': self.info['cache_value'],
50 | 'start': self.nextval,
51 | 'grant': self.GrantCommentSql() }
52 |
53 | def GetIcon(self):
54 | icons=[]
55 | icons.append("Sequence")
56 | if self.GetOid() in self.GetDatabase().favourites:
57 | icons.append('fav')
58 | return self.GetImageId(icons)
59 |
60 |
61 | @staticmethod
62 | def InstancesQuery(parentNode):
63 | sql=pgQuery("pg_class rel")
64 | sql.AddCol("rel.oid, relname as name, nspname, ns.oid as nspoid, spcname, pg_get_userbyid(relowner) AS owner, relacl as acl, relkind")
65 | sql.AddCol("description")
66 | sql.AddJoin("pg_namespace ns ON ns.oid=rel.relnamespace")
67 | sql.AddLeft("pg_tablespace ta ON ta.oid=rel.reltablespace")
68 | sql.AddLeft("pg_description des ON (des.objoid=rel.oid AND des.objsubid=0)")
69 | sql.AddWhere("relkind in ('S')")
70 | sql.AddWhere("relnamespace", parentNode.parentNode.GetOid())
71 | sql.AddOrder("CASE WHEN nspname='%s' THEN ' ' else nspname END" % "public")
72 | sql.AddOrder("relname")
73 | if parentNode.GetServer().version >= 10:
74 | sql.AddJoin("pg_sequence seq ON seqrelid=rel.oid")
75 | sql.AddCol("seqincrement AS increment_by, seqstart AS start_value")
76 | sql.AddCol("seqmin AS min_value, seqmax AS max_value, seqcache AS cache_value")
77 | sql.AddCol("seqcycle AS is_cycled")
78 | return sql
79 |
80 | def GetProperties(self):
81 | if not len(self.properties):
82 | row=self.GetCursor().ExecuteRow("SELECT * FROM %s" % self.NameSql())
83 | self.info.update(row.getDict())
84 | self.nextval=self.info['last_value']
85 | if self.info['is_called']:
86 | self.nextval += self.info['increment_by']
87 |
88 | self.properties = [
89 | (xlt("Name"), self.info['name']),
90 | (xlt("Namespace"), self.info['nspname']),
91 | ( "OID" , self.info['oid']),
92 | (xlt("Owner"), self.info['owner']),
93 | (xlt("Tablespace"), self.info['spcname']),
94 | (xlt("ACL"), self.info['acl']),
95 | (xlt("Next Value"), self.nextval),
96 | (xlt("Increment"), self.info['increment_by']),
97 | (xlt("Min Value"), self.info['min_value']),
98 | (xlt("Max Value"), self.info['max_value']),
99 | (xlt("Cache"), self.info['cache_value']),
100 | (xlt("Cycled"), self.info['is_cycled'])
101 | ]
102 |
103 | self.AddProperty(xlt("Description"), self.info['description'])
104 |
105 | return self.properties
106 |
107 |
108 | class Dlg(adm.PropertyDialog):
109 |
110 | def Go(self):
111 | pass
112 |
113 | def Check(self):
114 | ok=True
115 | if not self.node:
116 | pass
117 |
118 | return ok
119 |
120 |
121 | nodeinfo= [ { "class" : Sequence, "parents": ["Schema"], "sort": 70, "collection": "Sequences", "pages": ["SqlPage"] } ]
122 |
--------------------------------------------------------------------------------
/modPg/Sequence.xrc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | wxVERTICAL
6 |
7 |
8 | 2
9 |
10 |
11 | Name
12 | 5,7d
13 |
14 |
15 |
16 |
17 | 50,5d
18 | 80,-1d
19 |
20 |
21 |
22 |
23 | Increment
24 | 5,22d
25 |
26 |
27 |
28 |
29 | 50,20d
30 | 80,-1d
31 |
32 |
33 |
34 |
35 | Minimum
36 |
37 |
38 |
39 |
40 | 80,-1d
41 |
42 |
43 |
44 |
45 | Maximum
46 | 5,37d
47 |
48 |
49 |
50 |
51 | 50,37d
52 |
53 |
54 |
55 |
56 | Cache
57 | 5,52d
58 |
59 |
60 |
61 |
62 | 50,50d
63 | 35,-1d
64 |
65 |
66 |
67 |
68 | Next Value
69 | 5,82d
70 |
71 |
72 |
73 |
74 | 50,80d
75 | 80,-1d
76 |
77 |
78 | 10
79 | 10
80 |
81 | wxALL
82 | 10
83 |
84 |
85 |
86 |
--------------------------------------------------------------------------------
/modPg/Server.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/Server.ico
--------------------------------------------------------------------------------
/modPg/Server.xrc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | PostgreSQL Server
5 |
6 | wxVERTICAL
7 |
8 |
9 | 2
10 |
11 |
12 | Host name
13 | 5,7d
14 |
15 |
16 |
17 |
18 | 50,5d
19 | 80,-1d
20 |
21 |
22 |
23 |
24 | Host address
25 | 5,22d
26 |
27 |
28 |
29 |
30 | 50,20d
31 | 80,-1d
32 |
33 |
34 |
35 |
36 | Maintenance DB
37 |
38 |
39 |
40 |
41 | postgres
42 | 80,-1d
43 |
44 |
45 |
46 |
47 | SSL
48 | 5,37d
49 |
50 |
51 |
52 |
53 | 50,37d
54 |
55 |
56 |
57 |
58 | Port
59 | 5,52d
60 |
61 |
62 |
63 |
64 | 50,50d
65 | 5432
66 | 35,-1d
67 |
68 |
69 |
70 |
71 | User
72 | 5,82d
73 |
74 |
75 |
76 |
77 | 50,80d
78 | postgres
79 | 80,-1d
80 |
81 |
82 |
83 |
84 | Password
85 | 5,97d
86 |
87 |
88 |
89 |
90 | 50,95d
91 | 80,-1d
92 |
93 |
94 |
95 |
96 | Auto connect
97 | 5,112d
98 |
99 |
100 |
101 |
102 |
103 | 1
104 | 50,112d
105 |
106 |
107 | 10
108 | 10
109 |
110 | wxALL
111 | 10
112 |
113 |
114 |
115 | wxHORIZONTAL
116 |
117 | 1
118 | wxEXPAND
119 |
120 |
121 |
122 | Cancel
123 | 40,130d
124 | 45,-1d
125 |
126 | wxRIGHT
127 | 10
128 |
129 |
130 |
131 | OK
132 | 95,130d
133 | 45,-1d
134 |
135 |
136 |
137 | 1
138 | wxTOP|wxBOTTOM|wxRIGHT|wxEXPAND
139 | 10
140 |
141 |
142 |
143 |
--------------------------------------------------------------------------------
/modPg/ServerSetting.xrc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Server settings
5 |
6 |
7 | wxVERTICAL
8 |
9 |
10 | 2
11 |
12 |
13 | Name
14 |
15 | wxALIGN_CENTRE_VERTICAL
16 |
17 |
18 |
19 |
20 |
21 |
22 | 5
23 | 10
24 | 1
25 |
26 |
27 | Setting
28 |
29 | wxALIGN_CENTRE_VERTICAL
30 |
31 |
32 |
33 | wxHORIZONTAL
34 |
35 |
36 | 50,12d
37 |
38 | 1
39 | wxEXPAND
40 | 50,12d
41 |
42 |
43 | 0
44 |
45 |
46 |
47 | Reset
48 |
49 | wxLEFT|wxALIGN_CENTRE_VERTICAL
50 | 10
51 |
52 |
53 | 1
54 | wxTOP|wxBOTTOM|wxEXPAND
55 | 5
56 |
57 |
58 |
59 | Category
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 | Context
70 |
71 | wxBOTTOM
72 | 5
73 |
74 |
75 |
76 |
77 |
78 | wxBOTTOM
79 | 5
80 |
81 |
82 |
83 | Description
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 | wxBOTTOM
97 | 10
98 |
99 |
100 | 0,0
101 |
102 |
103 | 0,0
104 |
105 |
106 | 1
107 | wxTOP|wxLEFT|wxRIGHT|wxEXPAND
108 | 10
109 |
110 |
111 |
112 | wxHORIZONTAL
113 |
114 |
115 | Reload
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 | 1
125 |
126 |
127 |
128 | Cancel
129 |
130 | wxLEFT|wxRIGHT
131 | 10
132 |
133 |
134 |
135 | Ok
136 |
137 |
138 |
139 |
140 | wxTOP|wxBOTTOM|wxLEFT|wxRIGHT|wxGROW
141 | 10
142 |
143 |
144 |
145 | wxEXPAND
146 | 12d
147 |
148 |
149 |
150 |
151 |
--------------------------------------------------------------------------------
/modPg/SettingsPage.xrc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | wxVERTICAL
6 |
7 |
8 | 1
9 | wxBOTTOM|wxRIGHT|wxEXPAND|wxGROW
10 | 5
11 |
12 |
13 |
14 | wxHORIZONTAL
15 |
16 |
17 | Find
18 |
19 | wxLEFT|wxRIGHT|wxALIGN_CENTRE_VERTICAL
20 | 10
21 |
22 |
23 |
24 | 80,-1d
25 |
26 | wxALIGN_CENTRE
27 |
28 |
29 | 1
30 |
31 |
32 |
33 | Apply
34 |
35 | wxBOTTOM|wxLEFT|wxRIGHT|wxALIGN_CENTRE_VERTICAL
36 | 5
37 |
38 |
39 | wxGROW
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/modPg/SqlData.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/SqlData.ico
--------------------------------------------------------------------------------
/modPg/SqlPanel.xrc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/modPg/SqlQuery.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/SqlQuery.ico
--------------------------------------------------------------------------------
/modPg/Table.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/Table.png
--------------------------------------------------------------------------------
/modPg/View.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/View.png
--------------------------------------------------------------------------------
/modPg/View.py:
--------------------------------------------------------------------------------
1 | # The Admin4 Project
2 | # (c) 2013-2025 Andreas Pflug
3 | #
4 | # Licensed under the Apache License,
5 | # see LICENSE.TXT for conditions of usage
6 |
7 | from ._objects import SchemaObject
8 | from ._pgsql import pgQuery
9 | from wh import xlt
10 |
11 |
12 | class View(SchemaObject):
13 | typename=xlt("View")
14 | shortname=xlt("View")
15 | grantTypename='TABLE'
16 | refreshOid="rel.oid"
17 | allGrants='arwdDxt'
18 | favtype='v'
19 | relkind='v'
20 |
21 | @staticmethod
22 | def FindQuery(schemaName, schemaOid, patterns):
23 | sql=pgQuery("pg_class c")
24 | sql.AddCol("relkind as kind")
25 | sql.AddCol("nspname")
26 | sql.AddCol("relname as name")
27 | sql.AddCol("n.oid as nspoid")
28 | sql.AddCol("c.oid")
29 | sql.AddJoin("pg_namespace n ON n.oid=relnamespace")
30 | sql.AddWhere("relkind='v'")
31 | SchemaObject.AddFindRestrictions(sql, schemaName, schemaOid, 'relname', patterns)
32 | return sql
33 |
34 | @staticmethod
35 | def InstancesQuery(parentNode):
36 | sql=pgQuery("pg_class rel")
37 | sql.AddCol("rel.oid, relname as name, nspname, ns.oid as nspoid, spcname, pg_get_userbyid(relowner) AS owner, relacl as acl, relkind")
38 | sql.AddCol("description")
39 | sql.AddJoin("pg_namespace ns ON ns.oid=rel.relnamespace")
40 | sql.AddLeft("pg_tablespace ta ON ta.oid=rel.reltablespace")
41 | sql.AddLeft("pg_description des ON (des.objoid=rel.oid AND des.objsubid=0)")
42 | sql.AddLeft("pg_constraint c ON c.conrelid=rel.oid AND c.contype='p'")
43 | sql.AddWhere("relkind in ('v', 'm')")
44 | sql.AddWhere("relnamespace", parentNode.parentNode.GetOid())
45 | sql.AddOrder("CASE WHEN nspname='%s' THEN ' ' else nspname END" % "public")
46 | sql.AddOrder("relname")
47 | return sql
48 |
49 |
50 | def TypeSql(self):
51 | if self.IsMaterialized():
52 | return "MATERIALIZED VIEW"
53 | else:
54 | return "VIEW"
55 |
56 | def GetIcon(self):
57 | icons=[]
58 | if self.IsMaterialized():
59 | icons.append("MatView")
60 | else:
61 | icons.append("View")
62 | if self.GetOid() in self.GetDatabase().favourites:
63 | icons.append('fav')
64 | return self.GetImageId(icons)
65 |
66 |
67 | def GetSql(self):
68 | definition=self.info.get('definition')
69 | if not definition:
70 | definition=self.GetCursor().ExecuteSingle("SELECT pg_get_viewdef(%d, true)" % self.GetOid())
71 | self.info['definition']=definition
72 | return "CREATE OR REPLACE %(object)s %(name)s %(tablespace)s AS\n%(def)s\n\n%(grant)s" % {
73 | 'object': self.TypeSql(),
74 | 'name': self.NameSql(),
75 | 'tablespace': self.TablespaceSql(),
76 | 'def': definition, 'grant': self.GrantCommentSql() }
77 |
78 |
79 | def GetProperties(self):
80 | if not len(self.properties):
81 | self.info['definition']=None
82 | self.properties = [
83 | (xlt("Name"), self.info['name']),
84 | (xlt("Namespace"), self.info['nspname']),
85 | ( "OID" , self.info['oid']),
86 | (xlt("Owner"), self.info['owner']),
87 | (xlt("Tablespace"), self.info['spcname']),
88 | (xlt("ACL"), self.info['acl'])
89 | ]
90 |
91 | if self.IsMaterialized():
92 | self.AddProperty(xlt("Materialized"), xlt("Yes"))
93 | self.AddProperty(xlt("Description"), self.info['description'])
94 | return self.properties
95 |
96 | def IsMaterialized(self):
97 | return self.info['relkind'] == 'm'
98 |
99 | nodeinfo= [ { "class" : View, "parents": ["Schema"], "sort": 30, "collection": "Views", "pages": ["SqlPage"] } ]
100 |
101 |
102 |
--------------------------------------------------------------------------------
/modPg/__init__.py:
--------------------------------------------------------------------------------
1 | # The Admin4 Project
2 | # (c) 2013-2022 Andreas Pflug
3 | #
4 | # Licensed under the Apache License,
5 | # see LICENSE.TXT for conditions of usage
6 |
7 |
8 | moduleinfo={ 'name': "PostgreSQL Server",
9 | 'modulename': "PostgreSQL",
10 | 'description': "PostgreSQL database server",
11 | 'version': "17.0",
12 | 'revision': "0.9.1",
13 | 'requiredAdmVersion': "3.0.0",
14 | 'testedAdmVersion': "3.0.0",
15 | 'supports': "PostgreSQL 8.1 ... 17 (pre-9.1 with restrictions)",
16 | 'copyright': "(c) 2013-2025 PSE Consulting Andreas Pflug",
17 | 'credits': "psycopg2 from http://initd.org/psycopg using libpq (http://www.postgresql.org)",
18 | }
19 |
20 | import sys
21 | if not hasattr(sys, 'skipSetupInit'):
22 | import adm
23 | import wx
24 | from wh import xlt, floatToTime
25 | from LoggingDialog import LogPanel
26 |
27 |
28 | class SqlPage:
29 | name="SQL"
30 | order=800
31 |
32 | def __init__(self, notebook):
33 | from ._sqledit import SqlEditor
34 | self.control=SqlEditor(notebook)
35 | self.control.SetMarginWidth(1, 2)
36 | self.notebook=notebook
37 | self.lastNode=None
38 |
39 | def GetControl(self):
40 | return self.control
41 |
42 | def Display(self, node, _detached):
43 | if hasattr(node, "GetSql"):
44 | sql=node.GetSql().strip().replace("\n\r", "\n").replace("\r\n", "\n")
45 | else:
46 | sql=xlt("No SQL query available.")
47 | self.control.SetReadOnly(False)
48 | self.control.SetValue(sql)
49 | self.control.SetReadOnly(True)
50 | self.control.SetSelection(0,0)
51 |
52 | moduleinfo['pages'] = [SqlPage]
53 |
54 |
55 | class Preferences(adm.PreferencePanel):
56 | name="PostgreSQL"
57 | configDefaults={ 'AdminNamespace': "Admin4",
58 | 'SettingCategorySort': "Reporting Query" }
59 |
60 | from . import Server
61 |
--------------------------------------------------------------------------------
/modPg/_requires.py:
--------------------------------------------------------------------------------
1 | # The Admin4 Project
2 | # (c) 2013-2022 Andreas Pflug
3 | #
4 | # Licensed under the Apache License,
5 | # see LICENSE.TXT for conditions of usage
6 |
7 |
8 | # http://initd.org/psycopg/docs/install.html#installation
9 |
10 | def GetPrerequisites(info=False):
11 | try:
12 | import psycopg2
13 | if psycopg2.__version__ > "2.4":
14 | return "psycopg2 csv"
15 | else:
16 | if info:
17 | print ("psycopg2 too old")
18 | except:
19 | if info:
20 | print ("psycopg2 missing")
21 | pass
22 | return None
23 |
24 | moreFiles=['kwlist.h']
--------------------------------------------------------------------------------
/modPg/_sqledit.py:
--------------------------------------------------------------------------------
1 | # The Admin4 Project
2 | # (c) 2013-2022 Andreas Pflug
3 | #
4 | # Licensed under the Apache License,
5 | # see LICENSE.TXT for conditions of usage
6 |
7 |
8 | # http://www.scintilla.org/
9 | import wx
10 | import wx.stc as stc
11 | from ._pgsql import getSqlKeywords, colKeywords
12 |
13 |
14 | class SqlEditor(stc.StyledTextCtrl):
15 | def __init__(self, parent):
16 | stc.StyledTextCtrl.__init__(self, parent)
17 | self.MarkerDefine(0, stc.STC_MARK_ARROW)
18 | self.MarkerSetBackground(0, wx.Colour(255,0,0))
19 | self.SetIndent(2)
20 |
21 | pt=parent.GetFont().GetPointSize()
22 | font=wx.Font(pt, wx.TELETYPE, wx.NORMAL, wx.NORMAL)
23 | self.SetFont(font)
24 | for i in range(24):
25 | self.StyleSetFont(i, font)
26 |
27 | # STC_SQL_DEFAULT
28 | # STC_SQL_COMMENT, STC_SQL_COMMENTLINE, STC_SQL_COMMENTDOC - comments
29 | # STC_SQL_WORD, STC_SQL_USER1 STC_SQL_USER2 STC_SQL_USER3 STC_SQL_USER4 - keywordlists 0,4,5,6,7
30 |
31 | # STC_SQL_NUMBER, STC_SQL_CHARACTER, STC_SQL_STRING, STC_SQL_OPERATOR - num, '', "", +-()*/
32 | # STC_SQL_SQLPLUS, STC_SQL_SQLPLUS_PROMPT, STC_SQL_SQLPLUS_COMMENT
33 | # STC_SQL_COMMENTLINEDOC STC_SQL_COMMENTDOCKEYWORD STC_SQL_COMMENTDOCKEYWORDERROR
34 | # STC_SQL_WORD2
35 | # STC_SQL_QUOTEDIDENTIFIER STC_SQL_IDENTIFIER
36 |
37 | commentColor=wx.Colour(128, 128, 128)
38 | keywordColor=wx.Colour(0, 0, 128)
39 | constColor=wx.Colour(0, 96, 0)
40 |
41 | self.SetLexer(stc.STC_LEX_SQL)
42 | self.StyleSetForeground(stc.STC_SQL_DEFAULT, wx.BLACK)
43 |
44 | self.StyleSetForeground(stc.STC_SQL_WORD, keywordColor)
45 | self.StyleSetBold(stc.STC_SQL_WORD, True)
46 | self.StyleSetBold(stc.STC_SQL_USER1, True)
47 |
48 | self.StyleSetForeground(stc.STC_SQL_COMMENT, commentColor)
49 | self.StyleSetForeground(stc.STC_SQL_COMMENTLINE, commentColor)
50 | self.StyleSetForeground(stc.STC_SQL_COMMENTDOC, commentColor)
51 |
52 | self.StyleSetForeground(stc.STC_SQL_NUMBER, constColor)
53 | self.StyleSetForeground(stc.STC_SQL_CHARACTER, constColor)
54 |
55 | self.SetKeyWords(0, ' '.join(getSqlKeywords()))
56 | self.SetKeyWords(4, ' '.join(colKeywords))
57 | self.SetScrollWidth(100)
58 | self.SetScrollWidthTracking(True)
59 |
60 |
61 |
62 | def ShowLineNumbers(self, how):
63 | if how:
64 | w,_h=self.GetTextExtent("1234")
65 | self.SetMarginWidth(0, w+8)
66 | else:
67 | self.SetMarginWidth(0, 0)
68 |
69 | def BindProcs(self, changeProc, updateUiProc):
70 | if changeProc:
71 | self.Bind(stc.EVT_STC_CHANGE, changeProc)
72 | if updateUiProc:
73 | self.Bind(stc.EVT_STC_UPDATEUI, updateUiProc)
74 |
75 | def MarkerDelete(self):
76 | self.MarkerDeleteAll(-1)
77 |
78 |
79 | def GetSelectOffset(self):
80 | a,e=self.GetSelection()
81 | if a == e:
82 | return 0
83 | else:
84 | return self.LineFromPosition(a)
85 |
86 | def MarkerSet(self, line):
87 | self.MarkerAdd(line, 0)
88 |
89 |
90 |
--------------------------------------------------------------------------------
/modPg/admin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/admin.png
--------------------------------------------------------------------------------
/modPg/check.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/check.png
--------------------------------------------------------------------------------
/modPg/clip_copy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/clip_copy.png
--------------------------------------------------------------------------------
/modPg/clip_cut.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/clip_cut.png
--------------------------------------------------------------------------------
/modPg/clip_paste.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/clip_paste.png
--------------------------------------------------------------------------------
/modPg/column.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/column.png
--------------------------------------------------------------------------------
/modPg/data_refresh.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/data_refresh.png
--------------------------------------------------------------------------------
/modPg/data_save.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/data_save.png
--------------------------------------------------------------------------------
/modPg/delete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/delete.png
--------------------------------------------------------------------------------
/modPg/edit_clear.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/edit_clear.png
--------------------------------------------------------------------------------
/modPg/edit_find.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/edit_find.png
--------------------------------------------------------------------------------
/modPg/edit_redo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/edit_redo.png
--------------------------------------------------------------------------------
/modPg/edit_undo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/edit_undo.png
--------------------------------------------------------------------------------
/modPg/ex_aggregate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/ex_aggregate.png
--------------------------------------------------------------------------------
/modPg/ex_append.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/ex_append.png
--------------------------------------------------------------------------------
/modPg/ex_bmp_heap.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/ex_bmp_heap.png
--------------------------------------------------------------------------------
/modPg/ex_bmp_index.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/ex_bmp_index.png
--------------------------------------------------------------------------------
/modPg/ex_group.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/ex_group.png
--------------------------------------------------------------------------------
/modPg/ex_hash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/ex_hash.png
--------------------------------------------------------------------------------
/modPg/ex_index_scan.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/ex_index_scan.png
--------------------------------------------------------------------------------
/modPg/ex_join.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/ex_join.png
--------------------------------------------------------------------------------
/modPg/ex_limit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/ex_limit.png
--------------------------------------------------------------------------------
/modPg/ex_materialize.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/ex_materialize.png
--------------------------------------------------------------------------------
/modPg/ex_merge.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/ex_merge.png
--------------------------------------------------------------------------------
/modPg/ex_nested.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/ex_nested.png
--------------------------------------------------------------------------------
/modPg/ex_result.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/ex_result.png
--------------------------------------------------------------------------------
/modPg/ex_scan.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/ex_scan.png
--------------------------------------------------------------------------------
/modPg/ex_seek.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/ex_seek.png
--------------------------------------------------------------------------------
/modPg/ex_setop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/ex_setop.png
--------------------------------------------------------------------------------
/modPg/ex_sort.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/ex_sort.png
--------------------------------------------------------------------------------
/modPg/ex_subplan.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/ex_subplan.png
--------------------------------------------------------------------------------
/modPg/ex_tid_scan.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/ex_tid_scan.png
--------------------------------------------------------------------------------
/modPg/ex_unique.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/ex_unique.png
--------------------------------------------------------------------------------
/modPg/ex_unknown.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/ex_unknown.png
--------------------------------------------------------------------------------
/modPg/fav.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/fav.png
--------------------------------------------------------------------------------
/modPg/file_open.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/file_open.png
--------------------------------------------------------------------------------
/modPg/file_save.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/file_save.png
--------------------------------------------------------------------------------
/modPg/filter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/filter.png
--------------------------------------------------------------------------------
/modPg/foreignkey.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/foreignkey.png
--------------------------------------------------------------------------------
/modPg/group.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/group.png
--------------------------------------------------------------------------------
/modPg/hints/instrument.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Server %SERVERNAME% is not instrumented
5 |
6 | Server is not instrumented
7 |
8 | $APPNAME implements some advanced features, which require additional procedures and tables in the
9 | maintenance database to work. These advanced features are:
10 |
11 | aborting connections on the connection status page
12 | Favorite objects in the browser tree
13 | SQL code Snippets in the SQL query tool
14 | Filter Presets in the data tool
15 | modifying the server configuration for servers older than 9.4
16 |
17 | Favorites, Snippets and Presets are stored in database tables personal to the user you're using to connect, and are
18 | instantly available on every computer you're connecting from using $APPNAME.
19 |
20 | To prepare the server for improved handling through $APPNAME, execute the instrument
21 | context menu on the server object and close the connection. After re-opening the connection, the instrumentation
22 | state will be detected and the advanced features are available.
23 |
24 | Some instrumentation steps might need preparation before $APPNAME can complete them. Most notably, the adminpack contrib module
25 | must be installed on the server before $APPNAME can register the extension successfully.
26 |
27 | Note: The namespace used for configuration storage is configured in Preferences/PostgreSQL.
28 |
29 |
30 |
--------------------------------------------------------------------------------
/modPg/index.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/index.png
--------------------------------------------------------------------------------
/modPg/key.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/key.png
--------------------------------------------------------------------------------
/modPg/pg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/pg.png
--------------------------------------------------------------------------------
/modPg/primarykey.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/primarykey.png
--------------------------------------------------------------------------------
/modPg/query_cancel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/query_cancel.png
--------------------------------------------------------------------------------
/modPg/query_execfile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/query_execfile.png
--------------------------------------------------------------------------------
/modPg/query_execute.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/query_execute.png
--------------------------------------------------------------------------------
/modPg/query_explain.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/query_explain.png
--------------------------------------------------------------------------------
/modPg/setting.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/setting.png
--------------------------------------------------------------------------------
/modPg/settingChanged.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/settingChanged.png
--------------------------------------------------------------------------------
/modPg/settingInternal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/settingInternal.png
--------------------------------------------------------------------------------
/modPg/snippet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/snippet.png
--------------------------------------------------------------------------------
/modPg/snippet_add.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/snippet_add.png
--------------------------------------------------------------------------------
/modPg/snippet_replace.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/snippet_replace.png
--------------------------------------------------------------------------------
/modPg/snippets.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/snippets.png
--------------------------------------------------------------------------------
/modPg/statistics.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/statistics.png
--------------------------------------------------------------------------------
/modPg/user.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/modPg/user.png
--------------------------------------------------------------------------------
/new.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/new.png
--------------------------------------------------------------------------------
/property.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/property.png
--------------------------------------------------------------------------------
/refresh.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/refresh.png
--------------------------------------------------------------------------------
/requirements-mac.txt:
--------------------------------------------------------------------------------
1 | wxPython==4.2.2
2 | dnspython==2.7.0
3 | python-ldap==3.4.4
4 | psycopg2-binary==2.9.10
5 | docker==7.1.0
6 | GitPython==3.1.44
7 | py2app==0.28.8
8 | setuptools==70.3.0
9 |
--------------------------------------------------------------------------------
/version.py:
--------------------------------------------------------------------------------
1 | # The Admin4 Project
2 | # (c) 2013-2022 Andreas Pflug
3 | #
4 | # Licensed under the Apache License,
5 | # see LICENSE.TXT for conditions of usage
6 |
7 |
8 | import sys
9 | if not hasattr(sys, 'frozen'):
10 | import wx
11 | if wx.VERSION < (4,1,1):
12 | raise Exception("wx Version too old")
13 | try:
14 | from __version import * # @UnusedWildImport
15 | except:
16 | version="3.x-nightly"
17 | modDate=None
18 | revDate=None
19 | tagDate=None
20 | revLocalChange=True
21 | revDirty=True
22 | revOriginChange=True
23 | requiredAdmVersion="3.0"
24 |
25 |
26 | class Version:
27 | def __init__(self, version):
28 | self.version=str(version)
29 |
30 | def str(self):
31 | return self.version
32 |
33 | def __str__(self):
34 | return self.version
35 |
36 | def fullver(self):
37 | ver=[]
38 | if self.version:
39 | for v in self.version.split('.'):
40 | ver.append("%03d" % int(v))
41 | return ".".join(ver)
42 |
43 | def __lt__(self, cmp):
44 | return self.fullver() < cmp.fullver()
45 |
46 | def __le__(self, cmp):
47 | return self.fullver() <= cmp.fullver()
48 |
49 | def __gt__(self, cmp):
50 | return self.fullver() > cmp.fullver()
51 |
52 | def __ge__(self, cmp):
53 | return self.fullver() >= cmp.fullver()
54 |
55 | def __eq__(self, cmp):
56 | return self.fullver() == cmp.fullver()
57 |
58 | def __ne__(self, cmp):
59 | return self.fullver() != cmp.fullver()
60 |
61 |
62 |
63 | requiredAdmVersion=Version(requiredAdmVersion)
64 | libVersion=Version("3.0.0")
65 |
66 | appName="Admin4"
67 | RELEASE_CHECK_URL="https://api.github.com/repos/andreas-p/admin4/releases"
68 | RELEASE_URL="https://github.com/andreas-p/admin4/releases"
69 |
70 | description="""4th generation Administration Tool
71 |
72 | Help and manual: http://www.admin4.org/docs
73 | Releases: %s""" % RELEASE_URL
74 | vendor="PSE"
75 | vendorDisplay="PSE Consulting"
76 | copyright="(c) 2013-2023 PSE Consulting Andreas Pflug"
77 | license="Apache License V2.0"
78 | author="PSE Consulting Andreas Pflug"
79 |
--------------------------------------------------------------------------------
/wxWidgets.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/wxWidgets.ico
--------------------------------------------------------------------------------
/xmlhelp.py:
--------------------------------------------------------------------------------
1 | # The Admin4 Project
2 | # (c) 2013-2022 Andreas Pflug
3 | #
4 | # Licensed under the Apache License,
5 | # see LICENSE.TXT for conditions of usage
6 |
7 |
8 | import xml.dom.minidom as minidom
9 |
10 |
11 | class Element(minidom.Element):
12 | def addElement(self, name):
13 | e=self.ownerDocument.createElement(name)
14 | self.appendChild(e)
15 | return e
16 |
17 | def addElementIfText(self, name, val):
18 | if val != None:
19 | return self.addElementText(name, val)
20 | return None
21 |
22 | def addElementText(self, name, val):
23 | t=minidom.Text()
24 | if val:
25 | t.data=str(val)
26 | else:
27 | t.data=""
28 | t.ownerDocument=self.ownerDocument
29 |
30 | e=self.addElement(name)
31 | e.appendChild(t)
32 | return e
33 |
34 | def addElementTree(self, el):
35 | if isinstance(el, str):
36 | doc=minidom.parseString(el)
37 | el=doc.documentElement
38 | e=self.ownerDocument.importNode(el, True)
39 | self.appendChild(e)
40 | return e
41 |
42 | def setAttribute(self, name, val):
43 | minidom.Element.setAttribute(self, name, val)
44 | return self
45 |
46 | def setAttributes(self, attribs):
47 | for key, val in attribs.items():
48 | self.setAttribute(key, str(val))
49 | return self
50 |
51 | def getText(self):
52 | pt=[]
53 | for node in self.childNodes:
54 | if node.nodeType == node.TEXT_NODE:
55 | pt.append(node.data)
56 | return "".join(pt)
57 |
58 | def getElements(self, name):
59 | return self.getElementsByTagName(name)
60 |
61 | def getElement(self, name):
62 | es=self.getElementsByTagName(name)
63 | if es:
64 | return es[0]
65 | return None
66 |
67 | def getElementText(self, name, default=None):
68 | n=self.getElement(name)
69 | if n:
70 | return n.getText()
71 | return default
72 |
73 | def prettyXml(self):
74 | lines=self.toprettyxml().splitlines(1)
75 | out=[]
76 | for line in lines:
77 | if line.strip():
78 | out.append(line)
79 | return "".join(out)
80 |
81 |
82 |
83 | class DOMImplementation(minidom.DOMImplementation):
84 | def _create_document(self):
85 | return Document()
86 |
87 | class Document(minidom.Document):
88 | implementation=DOMImplementation()
89 |
90 | @staticmethod
91 | def create(rootName):
92 | doc=Document.implementation.createDocument(None, rootName, None)
93 | return doc.documentElement
94 |
95 | @staticmethod
96 | def parseRaw(txt):
97 | doc=minidom.parseString(txt)
98 | return doc.documentElement
99 |
100 | @staticmethod
101 | def parse(txt):
102 | doc=Document.implementation.createDocument(None, "none", None)
103 | rootRaw=Document.parseRaw(txt)
104 | root=doc.importNode(rootRaw, True)
105 | doc.rootElement=root
106 | return root
107 |
108 | @staticmethod
109 | def parseFile(filename):
110 | doc=Document.implementation.createDocument(None, "none", None)
111 | raw=minidom.parse(filename)
112 | root=doc.importNode(raw.documentElement, True)
113 | doc.rootElement=root
114 | return root
115 |
116 | def createElement(self, tagName):
117 | e=Element(tagName)
118 | e.ownerDocument=self
119 | return e
120 |
121 | def createElementNS(self, namespaceURI, qualifiedName):
122 | prefix, _localName = minidom._nssplit(qualifiedName)
123 | e = Element(qualifiedName, namespaceURI, prefix)
124 | e.ownerDocument = self
125 | return e
126 |
--------------------------------------------------------------------------------
/xmlres.py:
--------------------------------------------------------------------------------
1 | # The Admin4 Project
2 | # (c) 2013-2025 Andreas Pflug
3 | #
4 | # Licensed under the Apache License,
5 | # see LICENSE.TXT for conditions of usage
6 |
7 |
8 | import wx.xrc as xrc
9 | import os, importlib
10 |
11 | xmlControlList={}
12 |
13 | def init(loaddir):
14 | names=os.listdir(loaddir)
15 | found=[]
16 | for name in names:
17 | path="%s/%s" % (loaddir, name)
18 | if os.path.isdir(path):
19 | pass
20 | # do not scan for CTL sources everywhere
21 | # If necessary, restrict to modXXX
22 | #init(path)
23 | elif name.startswith("ctl_") and name.endswith( (".py", ".pyc")):
24 | name=name[:name.rfind('.')]
25 | if name not in found:
26 | found.append(name)
27 | mod=importlib.import_module(name, loaddir)
28 | xmlControlList.update(mod.xmlControlList)
29 |
30 |
31 | def getControlClass(name):
32 | return xmlControlList.get(name)
33 |
34 | class XmlResourceHandler(xrc.XmlResourceHandler):
35 | def DoCreateResource(self):
36 | cls=xmlControlList.get(self.GetClass())
37 | ctl=None
38 | if cls:
39 | # self.AddStyle("whEXTRAStyle", 4711)
40 | ctl=cls(self.GetParentAsWindow(), cid=self.GetID(), pos=self.GetPosition(), size=self.GetSize(), style=self.GetStyle())
41 | self.SetupWindow(ctl)
42 | return ctl
43 |
44 | def CanHandle(self, node):
45 | return node.GetAttribute('class', "") in xmlControlList
46 |
47 |
--------------------------------------------------------------------------------
/xrced/XRCed_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/xrced/XRCed_16.png
--------------------------------------------------------------------------------
/xrced/XRCed_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/xrced/XRCed_32.png
--------------------------------------------------------------------------------
/xrced/encode_bitmaps.py:
--------------------------------------------------------------------------------
1 | """
2 | A simple script to encode all the images the XRCed needs into a Python module
3 | """
4 |
5 | import sys, os, glob
6 | from wx.tools import img2py
7 |
8 | def main():
9 | output = 'images.py'
10 |
11 | # get the list of PNG files
12 | files = glob.glob('src-images/*.png')
13 | files.sort()
14 |
15 | # Truncate the inages module
16 | open(output, 'w')
17 |
18 | # call img2py on each file
19 | for file in files:
20 |
21 | # extract the basename to be used as the image name
22 | name = os.path.splitext(os.path.basename(file))[0]
23 |
24 | # encode it
25 | if file == files[0]:
26 | cmd = "-u -i -n %s %s %s" % (name, file, output)
27 | else:
28 | cmd = "-a -u -i -n %s %s %s" % (name, file, output)
29 | img2py.main(cmd.split())
30 |
31 |
32 | if __name__ == "__main__":
33 | main()
34 |
35 |
--------------------------------------------------------------------------------
/xrced/globals.py:
--------------------------------------------------------------------------------
1 | # Name: globals.py
2 | # Purpose: XRC editor, global variables
3 | # Author: Roman Rolinsky
4 | # Created: 02.12.2002
5 | # RCS-ID: $Id: globals.py,v 1.31 2007/03/08 15:49:34 ROL Exp $
6 |
7 | import wx
8 |
9 |
10 | # Global constants
11 | progname = 'XRCed'
12 | version = '0.1.8-4-admin4'
13 | # Minimal wxWidgets version
14 | MinWxVersion = (2,6,0)
15 | if wx.VERSION[:3] < MinWxVersion:
16 | print ('''\
17 | ******************************* WARNING **************************************
18 | This version of XRCed may not work correctly on your version of wxWidgets.
19 | Please upgrade wxWidgets to %d.%d.%d or higher.
20 | ******************************************************************************''' % MinWxVersion)
21 |
22 |
23 |
24 | # Global variables
25 |
26 | class Globals:
27 | panel = None
28 | tree = None
29 | frame = None
30 | tools = None
31 | undoMan = None
32 | testWin = None
33 | testWinPos = wx.DefaultPosition
34 | currentXXX = None
35 |
36 | def _makeFonts(self):
37 | self._sysFont = wx.SystemSettings.GetFont(wx.SYS_SYSTEM_FONT)
38 | self._labelFont = wx.Font(self._sysFont.GetPointSize(), wx.DEFAULT, wx.NORMAL, wx.BOLD)
39 | self._modernFont = wx.Font(self._sysFont.GetPointSize(), wx.MODERN, wx.NORMAL, wx.NORMAL)
40 | self._smallerFont = wx.Font(self._sysFont.GetPointSize()-2, wx.DEFAULT, wx.NORMAL, wx.NORMAL)
41 |
42 | def sysFont(self):
43 | if not hasattr(self, "_sysFont"): self._makeFonts()
44 | return self._sysFont
45 | def labelFont(self):
46 | if not hasattr(self, "_labelFont"): self._makeFonts()
47 | return self._labelFont
48 | def modernFont(self):
49 | if not hasattr(self, "_modernFont"): self._makeFonts()
50 | return self._modernFont
51 | def smallerFont(self):
52 | if not hasattr(self, "_smallerFont"): self._makeFonts()
53 | return self._smallerFont
54 |
55 |
56 | g = Globals()
57 |
--------------------------------------------------------------------------------
/xrced/license.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2002, Roman Rolinsky
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are met:
6 |
7 | * Redistributions of source code must retain the above copyright notice,
8 | this list of conditions and the following disclaimer.
9 | * Redistributions in binary form must reproduce the above copyright notice,
10 | this list of conditions and the following disclaimer in the documentation
11 | and/or other materials provided with the distribution.
12 |
13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
14 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
17 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
23 | POSSIBILITY OF SUCH DAMAGE.
24 |
--------------------------------------------------------------------------------
/xrced/xrced.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreas-p/admin4/129afc9f39daa2f9f16a2ef5d1c10341f7f4e9a3/xrced/xrced.ico
--------------------------------------------------------------------------------