summaryrefslogtreecommitdiffstats
path: root/install/ui
diff options
context:
space:
mode:
Diffstat (limited to 'install/ui')
-rw-r--r--install/ui/FreeWay-Bold.otfbin0 -> 47524 bytes
-rw-r--r--install/ui/FreeWay.otfbin0 -> 38948 bytes
-rw-r--r--install/ui/Mainnav-background.pngbin0 -> 180 bytes
-rw-r--r--install/ui/Mainnav-offtab.pngbin0 -> 189 bytes
-rw-r--r--install/ui/Mainnav-ontab.pngbin0 -> 146 bytes
-rw-r--r--install/ui/Mainnav-seperatorbars.pngbin0 -> 122 bytes
-rw-r--r--install/ui/Makefile.am88
-rw-r--r--install/ui/Subnav-background.pngbin0 -> 141 bytes
-rw-r--r--install/ui/Subnav-offbutton.pngbin0 -> 145 bytes
-rw-r--r--install/ui/Subnav-onbutton.pngbin0 -> 173 bytes
-rw-r--r--install/ui/aci.js876
-rw-r--r--install/ui/add.js122
-rw-r--r--install/ui/associate.js944
-rwxr-xr-xinstall/ui/caution.pngbin0 -> 438 bytes
-rwxr-xr-xinstall/ui/certificate.js785
-rwxr-xr-xinstall/ui/check.pngbin0 -> 3209 bytes
-rw-r--r--install/ui/details.js897
-rw-r--r--install/ui/develop.js6
-rw-r--r--install/ui/entity.js592
-rw-r--r--install/ui/gray-fade-line.pngbin0 -> 2826 bytes
-rw-r--r--install/ui/group.js201
-rw-r--r--install/ui/hbacrule.js989
-rw-r--r--install/ui/hbacsvc.js118
-rw-r--r--install/ui/hbacsvcgroup.js197
-rw-r--r--install/ui/header.pngbin0 -> 2839 bytes
-rw-r--r--install/ui/header_background.pngbin0 -> 211 bytes
-rw-r--r--install/ui/header_logo.pngbin0 -> 13311 bytes
-rw-r--r--install/ui/host.js494
-rw-r--r--install/ui/hostgroup.js67
-rw-r--r--install/ui/index.html66
-rw-r--r--install/ui/ipa.css750
-rw-r--r--install/ui/ipa.js490
-rw-r--r--install/ui/ipa_logo_180x50.pngbin0 -> 12071 bytes
-rw-r--r--install/ui/ipalogo.pngbin0 -> 2492 bytes
-rw-r--r--install/ui/jquery-ui.css572
-rw-r--r--install/ui/jquery-ui.js763
-rw-r--r--install/ui/jquery.ba-bbq.js18
-rw-r--r--install/ui/jquery.cookie.js96
-rw-r--r--install/ui/jquery.js6240
-rw-r--r--install/ui/jsl.conf153
-rw-r--r--install/ui/json2.js482
-rw-r--r--install/ui/layouts/Makefile.am22
-rw-r--r--install/ui/layouts/default/Makefile.am30
-rwxr-xr-xinstall/ui/layouts/default/hbacrule-details-accesstime.html49
-rwxr-xr-xinstall/ui/layouts/default/hbacrule-details-general.html57
-rwxr-xr-xinstall/ui/layouts/default/hbacrule-details-host.html78
-rwxr-xr-xinstall/ui/layouts/default/hbacrule-details-service.html78
-rwxr-xr-xinstall/ui/layouts/default/hbacrule-details-sourcehost.html78
-rwxr-xr-xinstall/ui/layouts/default/hbacrule-details-user.html78
-rwxr-xr-xinstall/ui/layouts/default/sudorule-details-general.html49
-rwxr-xr-xinstall/ui/layouts/default/sudorule-group-dialog.html110
-rwxr-xr-xinstall/ui/layouts/default/sudorule-host-dialog.html110
-rwxr-xr-xinstall/ui/layouts/default/sudorule-hostgroup-dialog.html110
-rwxr-xr-xinstall/ui/layouts/default/sudorule-user-dialog.html110
-rw-r--r--install/ui/modal-background.pngbin0 -> 642 bytes
-rw-r--r--install/ui/navigation.js149
-rw-r--r--install/ui/netgroup.js67
-rw-r--r--install/ui/outer-bg.pngbin0 -> 248 bytes
-rw-r--r--install/ui/panel-background.pngbin0 -> 200 bytes
-rw-r--r--install/ui/policy.js599
-rw-r--r--install/ui/rule.js174
-rw-r--r--install/ui/search.js462
-rw-r--r--install/ui/serverconfig.js43
-rw-r--r--install/ui/service.js499
-rw-r--r--install/ui/spinner_header.gifbin0 -> 2841 bytes
-rw-r--r--install/ui/spinner_large.gifbin0 -> 6030 bytes
-rw-r--r--install/ui/spinner_small.gifbin0 -> 3532 bytes
-rw-r--r--install/ui/sudocmd.js278
-rw-r--r--install/ui/sudocmdgroup.js197
-rw-r--r--install/ui/sudorule.js1127
-rwxr-xr-xinstall/ui/test/README1
-rwxr-xr-xinstall/ui/test/aci_tests.html33
-rw-r--r--install/ui/test/aci_tests.js81
-rw-r--r--install/ui/test/all_tests.html36
-rw-r--r--install/ui/test/association_tests.html23
-rw-r--r--install/ui/test/association_tests.js127
-rwxr-xr-xinstall/ui/test/certificate_tests.html26
-rwxr-xr-xinstall/ui/test/certificate_tests.js81
-rw-r--r--install/ui/test/data/aci_find.json63
-rw-r--r--install/ui/test/data/automountlocation_find.json17
-rw-r--r--install/ui/test/data/automountlocation_show.json14
-rw-r--r--install/ui/test/data/cert_remove_hold.json9
-rw-r--r--install/ui/test/data/cert_request.json17
-rw-r--r--install/ui/test/data/cert_revoke.json9
-rw-r--r--install/ui/test/data/cert_show.json16
-rw-r--r--install/ui/test/data/config_show.json99
-rw-r--r--install/ui/test/data/delegation_find.json35
-rw-r--r--install/ui/test/data/delegation_list.json35
-rw-r--r--install/ui/test/data/delegation_mod.json21
-rw-r--r--install/ui/test/data/delegation_show.json20
-rw-r--r--install/ui/test/data/dns_find.json101
-rw-r--r--install/ui/test/data/dns_find_rr.json110
-rw-r--r--install/ui/test/data/dns_show.json38
-rw-r--r--install/ui/test/data/dnsrecord_add.json21
-rw-r--r--install/ui/test/data/dnsrecord_del.json10
-rw-r--r--install/ui/test/data/dnsrecord_find.json110
-rw-r--r--install/ui/test/data/dnszone_add.json46
-rw-r--r--install/ui/test/data/dnszone_find.json137
-rw-r--r--install/ui/test/data/dnszone_show.json90
-rw-r--r--install/ui/test/data/group_add.json31
-rw-r--r--install/ui/test/data/group_add_member.json25
-rw-r--r--install/ui/test/data/group_find.json75
-rw-r--r--install/ui/test/data/group_member_user.json149
-rw-r--r--install/ui/test/data/group_remove_member.json44
-rw-r--r--install/ui/test/data/group_show.json38
-rw-r--r--install/ui/test/data/hbacrule_add.json27
-rw-r--r--install/ui/test/data/hbacrule_add_accesstime.json7
-rw-r--r--install/ui/test/data/hbacrule_add_host.json56
-rw-r--r--install/ui/test/data/hbacrule_add_service.json56
-rw-r--r--install/ui/test/data/hbacrule_add_sourcehost.json56
-rw-r--r--install/ui/test/data/hbacrule_add_user.json56
-rw-r--r--install/ui/test/data/hbacrule_del.json9
-rw-r--r--install/ui/test/data/hbacrule_find.json54
-rw-r--r--install/ui/test/data/hbacrule_mod.json60
-rw-r--r--install/ui/test/data/hbacrule_remove_accesstime.json7
-rw-r--r--install/ui/test/data/hbacrule_remove_host.json50
-rw-r--r--install/ui/test/data/hbacrule_remove_service.json49
-rw-r--r--install/ui/test/data/hbacrule_remove_sourcehost.json50
-rw-r--r--install/ui/test/data/hbacrule_remove_user.json48
-rw-r--r--install/ui/test/data/hbacrule_show.json76
-rw-r--r--install/ui/test/data/hbacsvc_add.json24
-rw-r--r--install/ui/test/data/hbacsvc_del.json9
-rw-r--r--install/ui/test/data/hbacsvc_find.json101
-rw-r--r--install/ui/test/data/hbacsvc_mod.json31
-rw-r--r--install/ui/test/data/hbacsvc_show.json35
-rw-r--r--install/ui/test/data/hbacsvcgroup_add.json26
-rw-r--r--install/ui/test/data/hbacsvcgroup_add_member.json24
-rw-r--r--install/ui/test/data/hbacsvcgroup_del.json9
-rw-r--r--install/ui/test/data/hbacsvcgroup_find.json24
-rw-r--r--install/ui/test/data/hbacsvcgroup_member_hbacsvc.json57
-rw-r--r--install/ui/test/data/hbacsvcgroup_mod.json39
-rw-r--r--install/ui/test/data/hbacsvcgroup_remove_member.json21
-rw-r--r--install/ui/test/data/hbacsvcgroup_show.json46
-rw-r--r--install/ui/test/data/host_add.json40
-rw-r--r--install/ui/test/data/host_disable_dev.example.com.json9
-rw-r--r--install/ui/test/data/host_find.json91
-rw-r--r--install/ui/test/data/host_mod.json75
-rw-r--r--install/ui/test/data/host_show.json80
-rw-r--r--install/ui/test/data/host_show_dev.example.com.json98
-rw-r--r--install/ui/test/data/host_show_test.example.com.json80
-rw-r--r--install/ui/test/data/hostgroup_add.json27
-rw-r--r--install/ui/test/data/hostgroup_add_member.json37
-rw-r--r--install/ui/test/data/hostgroup_find.json33
-rw-r--r--install/ui/test/data/hostgroup_member_host.json70
-rw-r--r--install/ui/test/data/hostgroup_show.json22
-rw-r--r--install/ui/test/data/i18n_messages.json37
-rw-r--r--install/ui/test/data/ipa_init.json7884
-rw-r--r--install/ui/test/data/json_metadata.json4097
-rw-r--r--install/ui/test/data/krbtpolicy_show.json78
-rw-r--r--install/ui/test/data/netgroup_add.json28
-rw-r--r--install/ui/test/data/netgroup_add_member.json40
-rw-r--r--install/ui/test/data/netgroup_find.json56
-rw-r--r--install/ui/test/data/netgroup_show.json38
-rw-r--r--install/ui/test/data/permission_add.json26
-rw-r--r--install/ui/test/data/permission_del9
-rw-r--r--install/ui/test/data/permission_find.json887
-rw-r--r--install/ui/test/data/permission_show.json41
-rw-r--r--install/ui/test/data/privilege_find.json215
-rw-r--r--install/ui/test/data/privilege_show.json39
-rw-r--r--install/ui/test/data/pwpolicy_find.json72
-rw-r--r--install/ui/test/data/pwpolicy_mod.json56
-rw-r--r--install/ui/test/data/pwpolicy_show.json57
-rw-r--r--install/ui/test/data/role_find.json20
-rw-r--r--install/ui/test/data/role_show.json36
-rw-r--r--install/ui/test/data/rolegroup_add.json22
-rw-r--r--install/ui/test/data/rolegroup_add_member.json27
-rw-r--r--install/ui/test/data/rolegroup_del.json9
-rw-r--r--install/ui/test/data/rolegroup_find.json185
-rw-r--r--install/ui/test/data/rolegroup_remove_member.json24
-rw-r--r--install/ui/test/data/rolegroup_show.json20
-rw-r--r--install/ui/test/data/selfservice_find.json24
-rw-r--r--install/ui/test/data/selfservice_show.json21
-rw-r--r--install/ui/test/data/service_add.json29
-rw-r--r--install/ui/test/data/service_add_host.json21
-rw-r--r--install/ui/test/data/service_del.json9
-rw-r--r--install/ui/test/data/service_disable.json9
-rw-r--r--install/ui/test/data/service_find.json48
-rw-r--r--install/ui/test/data/service_managedby_host.json110
-rw-r--r--install/ui/test/data/service_mod.json21
-rw-r--r--install/ui/test/data/service_remove_host.sh18
-rw-r--r--install/ui/test/data/service_show.json74
-rw-r--r--install/ui/test/data/sudocmd_add.json21
-rw-r--r--install/ui/test/data/sudocmd_del.json9
-rw-r--r--install/ui/test/data/sudocmd_find.json23
-rw-r--r--install/ui/test/data/sudocmd_memberof_add.json53
-rw-r--r--install/ui/test/data/sudocmd_memberof_remove.json50
-rw-r--r--install/ui/test/data/sudocmd_memberof_show.json61
-rw-r--r--install/ui/test/data/sudocmd_mod.json31
-rw-r--r--install/ui/test/data/sudocmd_show.json33
-rw-r--r--install/ui/test/data/sudocmdgroup_add.json26
-rw-r--r--install/ui/test/data/sudocmdgroup_add_member.json26
-rw-r--r--install/ui/test/data/sudocmdgroup_del.json9
-rw-r--r--install/ui/test/data/sudocmdgroup_find.json33
-rw-r--r--install/ui/test/data/sudocmdgroup_member_sudocmd.json57
-rw-r--r--install/ui/test/data/sudocmdgroup_mod.json39
-rw-r--r--install/ui/test/data/sudocmdgroup_remove_member.json22
-rw-r--r--install/ui/test/data/sudocmdgroup_show.json44
-rw-r--r--install/ui/test/data/sudorule_add.json24
-rw-r--r--install/ui/test/data/sudorule_del.json9
-rw-r--r--install/ui/test/data/sudorule_find.json17
-rw-r--r--install/ui/test/data/sudorule_mod.json51
-rw-r--r--install/ui/test/data/sudorule_show.json84
-rw-r--r--install/ui/test/data/taskgroup_find.json554
-rw-r--r--install/ui/test/data/user_add.json49
-rw-r--r--install/ui/test/data/user_disable.json9
-rw-r--r--install/ui/test/data/user_enable.json9
-rw-r--r--install/ui/test/data/user_find.json243
-rw-r--r--install/ui/test/data/user_memberof_group.json64
-rw-r--r--install/ui/test/data/user_mod.json162
-rw-r--r--install/ui/test/data/user_show.json163
-rw-r--r--install/ui/test/data/whoami.json7
-rw-r--r--install/ui/test/details_tests.html25
-rw-r--r--install/ui/test/details_tests.js327
-rw-r--r--install/ui/test/entity_tests.html27
-rw-r--r--install/ui/test/entity_tests.js171
-rw-r--r--install/ui/test/index.html43
-rw-r--r--install/ui/test/ipa_tests.html23
-rw-r--r--install/ui/test/ipa_tests.js297
-rw-r--r--install/ui/test/navigation_tests.html23
-rw-r--r--install/ui/test/navigation_tests.js163
-rw-r--r--install/ui/test/qunit.css155
-rw-r--r--install/ui/test/qunit.js1261
-rw-r--r--install/ui/ui-bg_flat_65_ffffff_40x100.pngbin0 -> 178 bytes
-rw-r--r--install/ui/ui-bg_glass_40_111111_1x400.pngbin0 -> 124 bytes
-rw-r--r--install/ui/ui-bg_glass_55_1c1c1c_1x400.pngbin0 -> 171 bytes
-rw-r--r--install/ui/ui-bg_highlight-hard_100_f9f9f9_1x100.pngbin0 -> 86 bytes
-rw-r--r--install/ui/ui-bg_highlight-hard_40_aaaaaa_1x100.pngbin0 -> 100 bytes
-rw-r--r--install/ui/ui-bg_highlight-soft_50_aaaaaa_1x100.pngbin0 -> 102 bytes
-rw-r--r--install/ui/ui-bg_inset-hard_45_cd0a0a_1x100.pngbin0 -> 123 bytes
-rw-r--r--install/ui/ui-bg_inset-hard_55_ffeb80_1x100.pngbin0 -> 113 bytes
-rw-r--r--install/ui/ui-bg_loop_8_333333_21x21.pngbin0 -> 281 bytes
-rw-r--r--install/ui/ui-icons_222222_256x240.pngbin0 -> 4369 bytes
-rw-r--r--install/ui/ui-icons_4ca300_256x240.pngbin0 -> 4369 bytes
-rw-r--r--install/ui/ui-icons_bbbbbb_256x240.pngbin0 -> 4369 bytes
-rw-r--r--install/ui/ui-icons_ededed_256x240.pngbin0 -> 5355 bytes
-rw-r--r--install/ui/ui-icons_ffcf29_256x240.pngbin0 -> 4369 bytes
-rw-r--r--install/ui/ui-icons_ffffff_256x240.pngbin0 -> 4369 bytes
-rw-r--r--install/ui/user.js298
-rw-r--r--install/ui/webui.js172
-rw-r--r--install/ui/widget.js1319
240 files changed, 44790 insertions, 0 deletions
diff --git a/install/ui/FreeWay-Bold.otf b/install/ui/FreeWay-Bold.otf
new file mode 100644
index 000000000..793185317
--- /dev/null
+++ b/install/ui/FreeWay-Bold.otf
Binary files differ
diff --git a/install/ui/FreeWay.otf b/install/ui/FreeWay.otf
new file mode 100644
index 000000000..ebefcb25e
--- /dev/null
+++ b/install/ui/FreeWay.otf
Binary files differ
diff --git a/install/ui/Mainnav-background.png b/install/ui/Mainnav-background.png
new file mode 100644
index 000000000..37a9dc6a5
--- /dev/null
+++ b/install/ui/Mainnav-background.png
Binary files differ
diff --git a/install/ui/Mainnav-offtab.png b/install/ui/Mainnav-offtab.png
new file mode 100644
index 000000000..997863a29
--- /dev/null
+++ b/install/ui/Mainnav-offtab.png
Binary files differ
diff --git a/install/ui/Mainnav-ontab.png b/install/ui/Mainnav-ontab.png
new file mode 100644
index 000000000..303402f73
--- /dev/null
+++ b/install/ui/Mainnav-ontab.png
Binary files differ
diff --git a/install/ui/Mainnav-seperatorbars.png b/install/ui/Mainnav-seperatorbars.png
new file mode 100644
index 000000000..9d1a9d414
--- /dev/null
+++ b/install/ui/Mainnav-seperatorbars.png
Binary files differ
diff --git a/install/ui/Makefile.am b/install/ui/Makefile.am
new file mode 100644
index 000000000..b8b192db3
--- /dev/null
+++ b/install/ui/Makefile.am
@@ -0,0 +1,88 @@
+AUTOMAKE_OPTIONS = 1.7
+
+NULL =
+
+SUBDIRS = \
+ layouts \
+ $(NULL)
+
+appdir = $(IPA_DATA_DIR)/ui
+app_DATA = \
+ aci.js \
+ add.js \
+ associate.js \
+ caution.png \
+ check.png \
+ ipa_logo_180x50.png \
+ ipa.js \
+ ipa.css \
+ json2.js \
+ jquery.js \
+ jquery-ui.js \
+ jquery.ba-bbq.js \
+ jquery-ui.css \
+ certificate.js \
+ group.js \
+ hbacrule.js \
+ hbacsvc.js \
+ hbacsvcgroup.js \
+ host.js \
+ hostgroup.js \
+ index.html \
+ jquery.cookie.js \
+ navigation.js \
+ netgroup.js \
+ service.js \
+ serverconfig.js \
+ sudorule.js \
+ sudocmd.js \
+ sudocmdgroup.js \
+ policy.js \
+ search.js \
+ rule.js \
+ details.js \
+ entity.js \
+ webui.js \
+ widget.js \
+ user.js \
+ ipalogo.png \
+ gray-fade-line.png \
+ Mainnav-background.png \
+ Mainnav-offtab.png \
+ Mainnav-ontab.png \
+ modal-background.png \
+ outer-bg.png \
+ panel-background.png \
+ Subnav-background.png \
+ Subnav-offbutton.png \
+ Subnav-onbutton.png \
+ ui-bg_flat_65_ffffff_40x100.png \
+ ui-bg_glass_40_111111_1x400.png \
+ ui-bg_glass_55_1c1c1c_1x400.png \
+ ui-bg_highlight-hard_100_f9f9f9_1x100.png \
+ ui-bg_highlight-hard_40_aaaaaa_1x100.png \
+ ui-bg_highlight-soft_50_aaaaaa_1x100.png \
+ ui-bg_inset-hard_45_cd0a0a_1x100.png \
+ ui-bg_inset-hard_55_ffeb80_1x100.png \
+ ui-bg_loop_8_333333_21x21.png \
+ ui-icons_222222_256x240.png \
+ ui-icons_4ca300_256x240.png \
+ ui-icons_bbbbbb_256x240.png \
+ ui-icons_ededed_256x240.png \
+ ui-icons_ffcf29_256x240.png \
+ ui-icons_ffffff_256x240.png \
+ FreeWay.otf \
+ FreeWay-Bold.otf \
+ spinner_header.gif \
+ spinner_large.gif \
+ spinner_small.gif \
+ $(NULL)
+
+EXTRA_DIST = \
+ $(app_DATA) \
+ $(NULL)
+
+MAINTAINERCLEANFILES = \
+ *~ \
+ Makefile.in
+ $(NULL)
diff --git a/install/ui/Subnav-background.png b/install/ui/Subnav-background.png
new file mode 100644
index 000000000..c1baebffe
--- /dev/null
+++ b/install/ui/Subnav-background.png
Binary files differ
diff --git a/install/ui/Subnav-offbutton.png b/install/ui/Subnav-offbutton.png
new file mode 100644
index 000000000..859e5f5ee
--- /dev/null
+++ b/install/ui/Subnav-offbutton.png
Binary files differ
diff --git a/install/ui/Subnav-onbutton.png b/install/ui/Subnav-onbutton.png
new file mode 100644
index 000000000..2cee0a70b
--- /dev/null
+++ b/install/ui/Subnav-onbutton.png
Binary files differ
diff --git a/install/ui/aci.js b/install/ui/aci.js
new file mode 100644
index 000000000..85cfcaa85
--- /dev/null
+++ b/install/ui/aci.js
@@ -0,0 +1,876 @@
+/*jsl:import ipa.js */
+
+/* Authors:
+ * Adam Young <ayoung@redhat.com>
+ *
+ * Copyright (C) 2010 Red Hat
+ * see file 'COPYING' for use and warranty information
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 only
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/* REQUIRES: ipa.js, details.js, search.js, add.js, entity.js */
+
+
+/*TODO Merge this code into the attribtue table widget */
+IPA.populate_attribute_table = function (table, entity){
+ var attr_per_col = 400;
+ var aciattrs = IPA.metadata[entity].aciattrs;
+ var col_span = aciattrs.length / attr_per_col + 1;
+
+ $('tbody tr', table).remove();
+
+ var tbody = $('tbody',table);
+ var td;
+ for (var a = 0; a < aciattrs.length ; a += 1){
+ var aci_tr = $('<tr/>').appendTo(tbody);
+
+ td = $('<td/>').appendTo(aci_tr);
+ td.append($('<input/>',{
+ type:"checkbox",
+ id:'aciattr-'+aciattrs[a].toLowerCase(),
+ "class":'aci-attribute'
+ }));
+ td.append($('<label/>',{
+ text:aciattrs[a].toLowerCase()}));
+ }
+};
+
+IPA.attribute_table_widget= function (spec){
+ var id = spec.name;
+ var that = IPA.widget(spec);
+ var object_type = spec.objecttype || 'user';
+ var table;
+
+ that.create = function(container){
+
+ var dd = $('<dd/>').appendTo(container);
+ table = $('<table/>',{
+ id:id,
+ 'class':'search-table'}).
+ append('<thead/>').
+ append($('<tbody/>',{
+ style:"height:30em; overflow:auto;"
+ })).
+ appendTo(dd);
+
+ $('<tr></tr>').
+ append($('<th/>',{
+ style:"height:2em; vertical-align:bottom;",
+ html:$('<input/>',{
+ type: "checkbox",
+ click: function(){
+ $('.aci-attribute').
+ attr('checked', $(this).attr('checked'));
+ }}).
+ after('<label>Attribute</lable>')
+ })).
+ appendTo($('thead', table));
+ IPA.populate_attribute_table(table, object_type);
+ };
+
+ that.save = function(){
+ var attrs_boxes = $('table#'+id+" td :checked");
+ if (!attrs_boxes.length){
+ return [];
+ }
+ var retval = "";
+ for (var i = 0; i < attrs_boxes.length; i += 1){
+ if (i > 0){
+ retval += ',';
+ }
+ retval += attrs_boxes[i].id.substring("aciattr-".length);
+ }
+
+ return [retval];
+ };
+
+ var attrs = [];
+ that.reset =function(){
+ $('input[type=checkbox]', table).attr('checked','');
+ for (var i = 0; i < attrs.length; i+=1){
+ $(attrs[i], table).attr('checked','checked');
+ }
+ };
+
+ that.load = function(record){
+ if (!record.attrs) return;
+ attrs = [];
+ for (var i = 0; i < record.attrs.length; i+=1){
+ attrs.push('#aciattr-' +record.attrs[i]);
+ }
+ that.reset();
+ };
+
+ return that;
+};
+
+IPA.entity_select_widget = function(spec){
+
+ var that = IPA.widget(spec);
+ var entity = spec.entity || 'group';
+
+ function populate_select(value){
+ var selected = value;
+ function find_success(result){
+ $('option', that.entity_select).remove();
+ var entities = result.result.result;
+ for (var i =0; i < result.result.count; i +=1){
+ var option =
+ that.entity_select.append($('<option/>',{
+ text:entities[i].cn[0],
+ value:entities[i].cn[0]
+ }));
+ if (selected === entities[i].cn[0]){
+ option.attr('selected','selected');
+ }
+ }
+ }
+ function find_error(err){
+ }
+ IPA.command({
+ method: entity+'_find',
+ args:[that.entity_filter.val()],
+ options:{},
+ on_success:find_success,
+ on_error:find_error
+ }).execute();
+ }
+
+ that.create = function(container){
+ var dd = $('<dd/>').appendTo(container);
+
+ that.entity_select = $('<select/>', {
+ id: that.name + '-entity-select',
+ change: function(){
+
+ }
+ }).appendTo(dd);
+
+
+ that.entity_filter = $('<input/>',{
+ size:10,
+ type: 'text',
+ id: 'entity_filter',
+ style: 'display: none;',
+ keypress: function(){
+ populate_select();
+ }
+ }).appendTo(dd);
+
+ $('<a />',{
+ href:"",
+ text: 'filter: ',
+ click:function(){
+ that.entity_filter.css('display','inline');
+ $(this).css('display','none');
+ return false;
+ }
+ }).appendTo(dd);
+ populate_select();
+ };
+ var value = '';
+ that.reset = function(){
+ that.entity_filter.val(value );
+ populate_select(value);
+
+ };
+ that.load = function(record){
+ value = record[that.name];
+ that.reset();
+ };
+
+ that.save = function(){
+ return [$('option:selected', that.entity_select).val()];
+ };
+
+ return that;
+};
+
+IPA.rights_widget = function(spec){
+ var rights = ['write','add','delete'];
+
+ var that = IPA.widget({name:'permissions',label:'Permissions'});
+ that.id = spec.id;
+
+ that.create = function(container){
+ for (var i =0; i < rights.length; i += 1){
+ $("<dd/>").
+ append($('<input/>',{
+ type:'checkbox',
+ 'class':that.entity_name +"_"+ that.name,
+ 'id':rights[i],
+ value:rights[i]
+ })).
+ append($('<label/>',{
+ text:rights[i]
+ })).
+ appendTo(container);
+ }
+
+ };
+ var values = [];
+
+ that.reset = function(){
+ var selector = '.'+ that.entity_name +"_"+ that.name;
+
+ var checkboxes = $(selector);
+
+ for (var i = 0; i < checkboxes.length; i +=1){
+ checkboxes.attr('checked','');
+ }
+
+ for (var j = 0; j < values.length; j +=1){
+ var value = values[j];
+ var cb = $('#'+value+ selector);
+ cb.attr('checked', 'checked');
+ }
+
+ };
+
+ that.load = function(record) {
+ values = record[that.name] || [];
+ that.reset();
+ };
+
+ that.save = function(){
+ var rights_input = $('.'+ that.entity_name +"_"+ that.name);
+ var retval = "";
+ for (var i =0; i < rights_input.length; i+=1){
+ if (i > 0) {
+ retval += ',';
+ }
+ retval += rights_input[i].value;
+ }
+ return [retval];
+ };
+
+ return that;
+};
+
+
+IPA.hidden_widget = function(spec){
+ spec.label = '';
+ var that = IPA.widget(spec);
+ that.id = spec.id;
+ var value = spec.value || '';
+ that.create = function(container){
+ $('<input/>',{
+ type:'hidden',
+ 'id':that.id,
+ value: value
+ }).
+ appendTo(container);
+ };
+
+ that.save = function(){
+ return [value];
+ };
+ that.reset = function(){
+
+ };
+ return that;
+};
+
+
+IPA.rights_section = function () {
+ var spec = {
+ 'name':'rights',
+ 'label': 'Rights'
+ };
+ var that = IPA.details_section(spec);
+ that.add_field(IPA.rights_widget({name:'permissions'}));
+
+ return that;
+};
+
+
+IPA.target_section = function () {
+ var spec = {
+ 'name':'target',
+ 'label': 'Target'
+ };
+
+ var that = IPA.details_section(spec);
+ var groupings = ['aci_by_type', 'aci_by_query', 'aci_by_group',
+ 'aci_by_filter' ];
+ var inputs = ['input', 'select', 'textarea'];
+
+ function disable_inputs(){
+ for (var g = 0; g < groupings.length; g += 1 ){
+ for (var t = 0 ; t < inputs.length; t += 1){
+ $('.' + groupings[g] + ' '+ inputs[t]).
+ attr('disabled', 'disabled');
+ }
+ }
+ }
+ function enable_by(grouping){
+ for (var t = 0 ; t < inputs.length; t += 1){
+ $('.' + grouping + ' '+ inputs[t]).
+ attr('disabled', '');
+ }
+ }
+
+ function display_filter_target(dl){
+ $("<dt/>").
+ append($("<label/>",{
+ text: "Filter" })).
+ append($('<input/>',{
+ type:"radio",
+ name:"type",
+ checked:"true",
+ id:"aci_by_filter"
+ })).
+ appendTo(dl);
+
+ $('<dd/>',{
+ 'class': 'aci_by_filter first'}).
+ append($('<input />',{
+
+ disabled:'true',
+ type:'text',
+ id:'aci_filter'
+ })).
+ appendTo(dl);
+ }
+
+
+ function display_type_target(dl){
+ $("<dt/>").
+ append($("<label/>",{
+ text: "Object By Type " })).
+ append($('<input/>',{
+ type:"radio",
+ name:"type",
+ checked:"true",
+ id:"aci_by_type" })).
+ appendTo(dl);
+
+ var dd = $('<dd/>',{
+ "class":"aci_by_type first" }).
+ appendTo(dl);
+
+ var type_select = $('<select/>', {
+ id: 'object_type_select',
+ change: function(){
+ var attribute_table = $('#aci_attributes_table');
+ IPA.populate_attribute_table(
+ attribute_table, this.options[this.selectedIndex].value);
+ }
+ }).appendTo(dd);
+ var type_params=IPA.get_param_info("permission","type");
+ for (var pc =0; pc < type_params.values.length; pc += 1){
+ type_select.append($('<option/>',{
+ value: type_params.values[pc],
+ text: type_params.values[pc]
+ }));
+ }
+ dd = $('<dd />',{
+ "class":"aci_by_type other"}).appendTo(dl);
+
+ var attribute_table = IPA.attribute_table_widget(
+ {name:'aci_attributes_table',object_type:'user'});
+
+ attribute_table.create(dl);
+
+
+ }
+
+ function display_query_target(dl){
+ $('<dt/>').
+ append($('<label />',{ html: 'By Subtree'} )).
+ append($('<input />',{
+ type:"radio",
+ name:"type",
+ id:"aci_by_query" })).
+ appendTo(dl);
+
+ $("<dd/>",{
+ "class":'aci_by_query first'}).append($('<textarea />',{
+ id: 'aci_query_text',
+ cols:'30',
+ rows:'1'})) .appendTo(dl);
+ }
+
+ function populate_target_group_select(){
+ function find_success(result){
+ var groups = result.result.result;
+ for (var i =0; i < result.result.count; i +=1){
+ var option = groups[i].cn[0];
+ that.group_select.append($('<option/>',{
+ text:groups[i].cn[0],
+ value:groups[i].cn[0]
+ }));
+ }
+ }
+ function find_error(err){
+ }
+
+ $('option', that.group_select).remove();
+ IPA.command({
+ method:'group_find',
+ args:[that.group_filter.val()],
+ options:{},
+ on_success:find_success,
+ on_error:find_error}).execute();
+ }
+
+ function display_group_target(dl){
+ $('<dt/>' ).
+ append($('<label />',{
+ html: 'Target Group'} )).
+ append($('<input />',{
+ type:"radio",
+ name:"type",
+ id:"aci_by_group" })).
+ appendTo(dl);
+
+ that.group_filter = $('<input/>',{
+ type: 'text',
+ id: 'group_filter' });
+ that.group_select = $('<select/>', {
+ id: 'aci_target_group_select',
+ change: function(){
+ }
+ });
+
+ $("<dd/>",{
+ 'class':'aci_by_group first'
+ }).
+ append(that.group_filter).
+ append($('<label>Group Filter</label>')).
+ appendTo(dl);
+
+ $("<dd/>",{
+ 'class':'aci_by_group other'
+ }).
+ append(that.group_select).
+ appendTo(dl);
+ }
+
+
+
+
+ that.create = function(container) {
+ var dl = $('<dl class="entryattrs"/>').appendTo(container);
+
+ display_filter_target(dl);
+ display_query_target(dl);
+ display_group_target(dl);
+ display_type_target(dl);
+
+ $('#aci_by_filter', dl).click(function (){
+ disable_inputs();
+ enable_by(groupings[3]);
+ });
+
+ $('#aci_by_type', dl).click(function (){
+ disable_inputs();
+ enable_by(groupings[0]);
+ });
+
+ $('#aci_by_query', dl).click(function (){
+ disable_inputs();
+ enable_by(groupings[1]);
+ });
+
+ $('#aci_by_group', dl).click(function (){
+ disable_inputs();
+ enable_by(groupings[2]);
+ populate_target_group_select();
+ });
+
+ $('#aci_by_query', dl).click();
+
+
+ };
+
+ that.setup = function(container) {
+ };
+
+ that.load = function(result) {
+ if(result.subtree){
+ $('#aci_query_text').val(result.subtree);
+ $('#aci_by_query').click();
+ }else if(result.type){
+ $('#aci_by_type').click();
+ $('#object_type_select').val(result.type);
+ IPA.populate_attribute_table($('#aci_attributes_table'),
+ result.type);
+ if (result.attrs){
+ for (var a = 0; a < result.attrs.length; a += 1){
+ var cb = $('#aciattr-'+result.attrs[a]);
+ if (!cb.length){
+ alert('unmatched:'+result.attrs[a]);
+ }
+ cb.attr('checked',true);
+ }
+ }
+ }else if (result.targetgroup){
+ var segments = result.targetgroup.split(/,/);
+ var targetgroup=segments[0].split(/=/)[1];
+ that.group_filter.val( targetgroup);
+ $('#aci_by_group').click();
+ }else if (result.filter){
+ $('#aci_by_filter').click();
+ $('#aci_filter').val(result.filter);
+ }else{
+ alert('permission with invalid target specification');
+ }
+ };
+
+ that.reset = function() {
+ };
+
+ that.save = function (record){
+
+ var record_type = $("input[name='type']:checked").attr('id');
+
+ if (record_type === 'aci_by_group'){
+ record.targetgroup =
+ $('#aci_target_group_select option:selected').val();
+ }else if (record_type === 'aci_by_type'){
+ record.type = $('#object_type_select option:selected').val();
+ }else if (record_type === 'aci_by_query'){
+ record.subtree = $('#aci_query_text').val();
+ }else if (record_type === 'aci_by_filter'){
+ var filter = $('#aci_filter').val();
+ record.filter = filter;
+ }
+
+ var attrs = $('.aci-attribute:checked').each(function(){
+ var id = this.id.split('-')[1];
+
+ if (!record.attributes){
+ record.attributes = "";
+ }else{
+ record.attributes += ",";
+ }
+ record.attributes += id;
+ });
+ };
+ return that;
+};
+
+
+IPA.permission = function () {
+
+ var that = IPA.entity({
+ 'name': 'permission'
+ });
+
+ that.init = function() {
+
+ var dialog = IPA.permission_add_dialog({
+ name: 'add',
+ title: 'Add New Permission',
+ entity_name: 'permission'
+ });
+ that.add_dialog(dialog);
+ dialog.init();
+
+ var facet = IPA.permission_search_facet({
+ name: 'search',
+ label: 'Search'
+ });
+ that.add_facet(facet);
+
+ facet = IPA.permission_details_facet();
+ that.add_facet(facet);
+
+ that.entity_init();
+ };
+
+ return that;
+};
+
+
+IPA.add_entity(IPA.permission());
+
+
+
+IPA.permission_add_dialog = function (spec) {
+
+ spec = spec || {};
+
+ var that = IPA.add_dialog(spec);
+
+ that.init = function() {
+
+ that.add_field(IPA.text_widget({
+ name: 'cn',
+ undo: false
+ }));
+
+ that.add_field(IPA.text_widget({
+ name: 'description',
+ undo: false
+ }));
+
+ that.add_field(IPA.rights_widget({name:'permissions'}));
+ that.add_field(IPA.hidden_widget({name:'filter','value':'objectClass=changethisvalue'}));
+ that.add_dialog_init();
+ };
+
+
+ return that;
+};
+
+
+IPA.permission_search_facet = function (spec) {
+
+ spec = spec || {};
+ var that = IPA.search_facet(spec);
+ that.init = function() {
+ that.create_column({name:'cn'});
+ that.create_column({name:'description'});
+ that.search_facet_init();
+ };
+ return that;
+};
+
+
+IPA.permission_details_facet = function () {
+
+ var spec = {
+ name: 'details'
+ };
+ var that = IPA.details_facet(spec);
+
+ that.init = function() {
+
+ var section = that.add_section(IPA.details_list_section({
+ name:'identity',label:'Identity' }));
+ section.create_field({ name: 'cn', 'read_only': true });
+ section.create_field({ name: 'description'});
+
+ that.rights_section = IPA.rights_section();
+ that.add_section(that.rights_section);
+
+ that.target_section = IPA.target_section();
+
+ that.add_section(that.target_section);
+ that.details_facet_init();
+ };
+
+ that.superior_load = that.load;
+
+ that.load = function(result) {
+ that.superior_load(result);
+ };
+
+ that.superior_update = that.update;
+ that.update = function(on_win, on_fail){
+ that.superior_update(on_win, on_fail);
+ };
+ return that;
+};
+
+
+IPA.add_entity( function() {
+ var that = IPA.entity({
+ 'name': 'privilege'
+ });
+ that.init = function() {
+
+ var search_facet = IPA.search_facet({
+ name: 'search',
+ label: 'Search',
+ entity_name: that.name
+ });
+ search_facet.create_column({name:'cn'});
+ search_facet.create_column({name:'description'});
+ that.add_facet(search_facet);
+
+ that.add_facet(function() {
+ var that = IPA.details_facet({name:'details'});
+ that.add_section(
+ IPA.stanza({name:'identity', label:'Privilege Settings'}).
+ input({name:'cn'}).
+ input({name: 'description'}));
+ return that;
+ }());
+
+
+ var dialog = IPA.add_dialog({
+ name: 'add',
+ title: 'Add Privilege',
+ entity_name: that.entity
+ });
+ that.add_dialog(dialog);
+
+ dialog.add_field(IPA.text_widget({ name: 'cn', undo: false}));
+ dialog.add_field(IPA.text_widget({ name: 'description', undo: false}));
+ dialog.init();
+
+ that.create_association_facets();
+ that.entity_init();
+ };
+ return that;
+}());
+
+
+IPA.add_entity( function() {
+ var that = IPA.entity({
+ 'name': 'role'
+ });
+ that.init = function() {
+ var search_facet = IPA.search_facet({
+ name: 'search',
+ label: 'Search',
+ entity_name: that.name
+ });
+ search_facet.create_column({name:'cn'});
+ search_facet.create_column({name:'description'});
+ that.add_facet(search_facet);
+
+ that.add_facet(function() {
+ var that = IPA.details_facet({name:'details'});
+ that.add_section(
+ IPA.stanza({name:'identity', label:'Role Settings'}).
+ input({name:'cn'}).
+ input({name: 'description'}));
+ return that;
+ }());
+
+ var dialog = IPA.add_dialog({
+ name: 'add',
+ title: 'Add Role'
+ });
+ that.add_dialog(dialog);
+
+ dialog.add_field(IPA.text_widget({ name: 'cn', undo: false}));
+ dialog.add_field(IPA.text_widget({ name: 'description', undo: false}));
+ dialog.init();
+
+ that.create_association_facets();
+
+ that.entity_init();
+ };
+ return that;
+}());
+
+
+IPA.add_entity( function() {
+ var that = IPA.entity({
+ 'name': 'selfservice'
+ });
+
+ that.add_facet(function () {
+ var spec = {
+ name: 'search',
+ label: 'Search'
+ };
+ var that = IPA.search_facet(spec);
+ that.init = function() {
+ that.create_column({name:'aciname'});
+ that.search_facet_init();
+ };
+ return that;
+ }());
+
+
+ that.add_facet(function(){
+ var that = IPA.details_facet({'name':'details'});
+
+ that.init = function() {
+ that.add_section(
+ IPA.stanza({name:'general', label:'General'}).
+ input({name:'aciname'}).
+ custom_input(IPA.attribute_table_widget({
+ object_type:'user',
+ name:'attrs'
+ })));
+ };
+ return that;
+ }());
+
+
+ that.parent_init = that.init;
+ that.init = function(){
+ that.parent_init();
+ var dialog = IPA.add_dialog({
+ name: 'add',
+ title: 'Add Self Service Definition'
+ });
+ that.add_dialog(dialog);
+ dialog.add_field(IPA.text_widget({ name: 'aciname', undo: false}));
+ dialog.add_field(IPA.attribute_table_widget({
+ object_type:'user',
+ name:'attrs'
+ }));
+ dialog.init();
+ };
+ return that;
+}());
+
+
+IPA.add_entity( function() {
+ var that = IPA.entity({
+ 'name': 'delegation'
+ });
+
+ that.add_facet(function () {
+ var spec = {
+ name: 'search',
+ label: 'Search'
+ };
+ var that = IPA.search_facet(spec);
+ that.init = function() {
+ that.create_column({name:'aciname'});
+ that.search_facet_init();
+ };
+ return that;
+ }());
+ that.add_facet(function(){
+ var that = IPA.details_facet({'name':'details'});
+ var section =
+ IPA.stanza({name:'general', label:'General'}).
+ input({name:'aciname'}).
+ custom_input(IPA.entity_select_widget(
+ {name:'group', entity:'group'})).
+ custom_input(IPA.entity_select_widget(
+ {name:'memberof', entity:'group'})).
+ custom_input(
+ IPA.rights_widget({
+ id:'delegation_rights'})).
+ custom_input(
+ IPA.attribute_table_widget({
+ name:'attrs'}));
+ that.add_section(section);
+ return that;
+ }());
+
+ that.super_init = that.init;
+ that.init = function(){
+ that.super_init();
+ var dialog = IPA.add_dialog({
+ name: 'add',
+ title: 'Add Delegation',
+ entity_name: that.entity
+ });
+ that.add_dialog(dialog);
+ dialog.add_field(IPA.text_widget({ name: 'aciname', undo: false}));
+ dialog.add_field(IPA.entity_select_widget({name:'group',
+ entity:'group'}));
+ dialog.add_field(IPA.entity_select_widget({name:'memberof',
+ entity:'group'}));
+ dialog.add_field(IPA.attribute_table_widget({ name: 'attrs'}));
+
+ dialog.init();
+ that.create_association_facets();
+ };
+
+ return that;
+}()); \ No newline at end of file
diff --git a/install/ui/add.js b/install/ui/add.js
new file mode 100644
index 000000000..69b1108c3
--- /dev/null
+++ b/install/ui/add.js
@@ -0,0 +1,122 @@
+/*jsl:import ipa.js */
+
+/* Authors:
+ * Pavel Zuna <pzuna@redhat.com>
+ * Endi Sukma Dewata <edewata@redhat.com>
+ *
+ * Copyright (C) 2010 Red Hat
+ * see file 'COPYING' for use and warranty information
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/* REQUIRES: ipa.js */
+
+IPA.add_dialog = function (spec) {
+
+ spec = spec || {};
+
+ var that = IPA.dialog(spec);
+
+ that.name = spec.name;
+ that.title = spec.title;
+ that._entity_name = spec.entity_name;
+
+ that.init = function() {
+
+ that.add_button('Add', function() {
+ var record = that.get_record();
+ that.add(
+ record,
+ function() {
+ var entity = IPA.get_entity(that.entity_name);
+ var facet = entity.get_facet('search');
+ var table = facet.table;
+ table.refresh();
+ that.close();
+ }
+ );
+ });
+
+
+ that.add_button('Add and Add Another', function() {
+ var record = that.get_record();
+ that.add(
+ record,
+ function() {
+ var entity = IPA.get_entity(that.entity_name);
+ var facet = entity.get_facet('search');
+ var table = facet.table;
+ table.refresh();
+ that.reset();
+ }
+ );
+ });
+
+ that.add_button('Add and Edit', function() {
+ var record = that.get_record();
+ that.add(
+ record,
+ function() {
+ that.close();
+
+ var pkey_name = IPA.metadata[that.entity_name].primary_key;
+ var pkey = record[pkey_name];
+
+ var state = {};
+ state[that.entity_name + '-facet'] = 'details';
+ state[that.entity_name + '-pkey'] = pkey;
+ $.bbq.pushState(state);
+ }
+ );
+ });
+
+ that.add_button('Cancel', function() {
+ that.close();
+ });
+
+ that.dialog_init();
+ };
+
+ that.add = function(record, on_success, on_error) {
+
+ var pkey_name = IPA.metadata[that.entity_name].primary_key;
+
+ var command = IPA.command({
+ method: that.entity_name+'_add',
+ on_success: on_success,
+ on_error: on_error
+ });
+
+ for (var i=0; i<that.fields.length; i++) {
+ var field = that.fields[i];
+
+ var value = record[field.name];
+ if (!value) continue;
+
+ if (field.name == pkey_name) {
+ command.add_arg(value);
+ } else {
+ command.set_option(field.name, value);
+ }
+ }
+
+ command.execute();
+ };
+
+ that.add_dialog_init = that.init;
+
+ return that;
+};
+
diff --git a/install/ui/associate.js b/install/ui/associate.js
new file mode 100644
index 000000000..9fc907230
--- /dev/null
+++ b/install/ui/associate.js
@@ -0,0 +1,944 @@
+/*jsl:import ipa.js */
+
+/* Authors:
+ * Adam Young <ayoung@redhat.com>
+ *
+ * Copyright (C) 2010 Red Hat
+ * see file 'COPYING' for use and warranty information
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/* REQUIRES: ipa.js */
+/* CURRENTLY ALSO REQUIRES search.js, because it reuses it's code to create
+ * the AssociationList elements; IT NEEDS IT'S OWN CODE! */
+
+IPA.associator = function (spec) {
+
+ spec = spec || {};
+
+ var that = {};
+
+ that.entity_name = spec.entity_name;
+ that.pkey = spec.pkey;
+
+ that.other_entity = spec.other_entity;
+ that.values = spec.values;
+
+ that.method = spec.method;
+
+ that.on_success = spec.on_success;
+ that.on_error = spec.on_error;
+
+ that.execute = function() {
+ };
+
+ return that;
+};
+
+
+/**
+*This associator is built for the case where each association requires a separate rpc
+*/
+function serial_associator(spec) {
+
+ spec = spec || {};
+
+ var that = IPA.associator(spec);
+
+ that.execute = function() {
+
+ if (!that.values || !that.values.length) {
+ that.on_success();
+ return;
+ }
+
+ var value = that.values.shift();
+ if (!value) {
+ that.on_success();
+ return;
+ }
+
+ var args = [value];
+ var options = {};
+ options[that.entity_name] = that.pkey;
+
+ IPA.cmd(
+ that.method,
+ args,
+ options,
+ that.execute,
+ that.on_error,
+ that.other_entity);
+ };
+
+ return that;
+}
+
+/**
+*This associator is for the common case where all the asociations can be sent
+in a single rpc
+*/
+function bulk_associator(spec) {
+
+ spec = spec || {};
+
+ var that = IPA.associator(spec);
+
+ that.execute = function() {
+
+ if (!that.values || !that.values.length) {
+ that.on_success();
+ return;
+ }
+
+ var value = that.values.shift();
+ if (!value) {
+ that.on_success();
+ return;
+ }
+
+ while (that.values.length > 0) {
+ value += ',' + that.values.shift();
+ }
+
+ var args = [that.pkey];
+ var options = { 'all': true };
+ options[that.other_entity] = value;
+
+ IPA.cmd(
+ that.method,
+ args,
+ options,
+ that.on_success,
+ that.on_error,
+ that.entity_name);
+ };
+
+ return that;
+}
+
+/**
+ * This dialog is used for adding associations between two entities.
+ */
+IPA.association_adder_dialog = function (spec) {
+
+ spec = spec || {};
+
+ var that = IPA.adder_dialog(spec);
+
+ that.entity_name = spec.entity_name;
+ that.pkey = spec.pkey;
+ that.other_entity = spec.other_entity;
+ that.attribute_member = spec.attribute_member;
+
+ that.init = function() {
+ if (!that.columns.length) {
+ var pkey_name = IPA.metadata[that.other_entity].primary_key;
+ that.create_column({
+ name: pkey_name,
+ label: IPA.metadata[that.other_entity].label,
+ primary_key: true,
+ width: '200px'
+ });
+ }
+
+ /* FIXME: event not firing? */
+ $('input[name=hidememb]', that.container).click(that.search);
+
+ that.adder_dialog_init();
+ };
+
+ that.search = function() {
+ function on_success(data, text_status, xhr) {
+ var results = data.result;
+ that.clear_available_values();
+
+ var pkey_attr = IPA.metadata[that.entity_name].primary_key;
+
+ for (var i=0; i<results.count; i++){
+ var result = results.result[i];
+ if (result[pkey_attr] != spec.pkey)
+ that.add_available_value(result);
+ }
+ }
+
+ var hide_checkbox = $('input[name=hidememb]', that.container);
+
+ var options = {'all': true};
+ if (hide_checkbox.attr('checked')) {
+ var relationships = IPA.metadata[that.other_entity].relationships;
+
+ /* TODO: better generic handling of different relationships! */
+ var other_attribute_member = '';
+ if (that.attribute_member == 'member')
+ other_attribute_member = 'memberof';
+ else if (that.attribute_member == 'memberuser')
+ other_attribute_member = 'memberof';
+ else if (that.attribute_member == 'memberhost')
+ other_attribute_member = 'memberof';
+ else if (that.attribute_member == 'memberof')
+ other_attribute_member = 'member';
+
+ var relationship = relationships[other_attribute_member];
+ if (relationship) {
+ var param_name = relationship[2] + that.entity_name;
+ options[param_name] = that.pkey;
+ }
+ }
+
+ IPA.cmd('find', [that.get_filter()], options, on_success, null, that.other_entity);
+ };
+
+ that.association_adder_dialog_init = that.init;
+ that.association_adder_dialog_setup = that.setup;
+
+ return that;
+};
+
+
+/**
+ * This dialog is used for removing associations between two entities.
+ */
+IPA.association_deleter_dialog = function (spec) {
+
+ spec = spec || {};
+
+ var that = IPA.deleter_dialog(spec);
+
+ that.entity_name = spec.entity_name;
+ that.pkey = spec.pkey;
+ that.other_entity = spec.other_entity;
+ that.values = spec.values;
+
+ that.associator = spec.associator;
+ that.method = spec.method || 'remove_member';
+
+ that.on_success = spec.on_success;
+ that.on_error = spec.on_error;
+
+ that.remove = function() {
+
+ var associator = that.associator({
+ 'entity_name': that.entity_name,
+ 'pkey': that.pkey,
+ 'other_entity': that.other_entity,
+ 'values': that.values,
+ 'method': that.method,
+ 'on_success': that.on_success,
+ 'on_error': that.on_error
+ });
+
+ associator.execute();
+ };
+
+ return that;
+};
+
+
+IPA.association_config = function (spec) {
+
+ spec = spec || {};
+
+ var that = {};
+
+ that.name = spec.name;
+ that.associator = spec.associator;
+ that.add_method = spec.add_method;
+ that.remove_method = spec.remove_method;
+
+ return that;
+};
+
+
+IPA.association_table_widget = function (spec) {
+
+ spec = spec || {};
+
+ var that = IPA.table_widget(spec);
+
+ that.other_entity = spec.other_entity;
+ that.attribute_member = spec.attribute_member;
+
+ that.associator = spec.associator || bulk_associator;
+ that.add_method = spec.add_method || 'add_member';
+ that.remove_method = spec.remove_method || 'remove_member';
+
+ that.adder_columns = [];
+ that.adder_columns_by_name = {};
+
+ that.get_adder_column = function(name) {
+ return that.adder_columns_by_name[name];
+ };
+
+ that.add_adder_column = function(column) {
+ that.adder_columns.push(column);
+ that.adder_columns_by_name[column.name] = column;
+ };
+
+ that.create_adder_column = function(spec) {
+ var column = IPA.column(spec);
+ that.add_adder_column(column);
+ return column;
+ };
+
+ that.init = function() {
+
+ var entity = IPA.get_entity(that.entity_name);
+ var association = entity.get_association(that.other_entity);
+ var column;
+ if (association) {
+ if (association.associator) {
+ that.associator = association.associator == 'serial' ? serial_associator : bulk_associator;
+ }
+
+ if (association.add_method) that.add_method = association.add_method;
+ if (association.remove_method) that.remove_method = association.remove_method;
+ }
+
+ // create a column if none defined
+ if (!that.columns.length) {
+ that.create_column({
+ 'name': that.name,
+ 'label': IPA.metadata[that.other_entity].label,
+ 'primary_key': true
+ });
+ }
+
+ for (var i=0; i<that.columns.length; i++) {
+ column = that.columns[i];
+ column.entity_name = that.other_entity;
+ }
+
+ for (var j=0; j<that.adder_columns.length; j++) {
+ column = that.adder_columns[j];
+ column.entity_name = that.other_entity;
+ }
+
+ that.table_init();
+ };
+
+ that.create = function(container) {
+
+ that.table_create(container);
+
+ var buttons = $('span[name=buttons]', container);
+
+ $('<input/>', {
+ 'type': 'button',
+ 'name': 'remove',
+ 'value': 'Remove'
+ }).appendTo(buttons);
+
+ $('<input/>', {
+ 'type': 'button',
+ 'name': 'add',
+ 'value': 'Add'
+ }).appendTo(buttons);
+ };
+
+ that.setup = function(container) {
+
+ that.table_setup(container);
+
+ var button = $('input[name=remove]', container);
+ button.replaceWith(IPA.action_button({
+ 'label': button.val(),
+ 'icon': 'ui-icon-trash',
+ 'click': function() {
+ if ($(this).hasClass('action-button-disabled')) {
+ return false;
+ }
+ that.show_remove_dialog();
+ return false;
+ }
+ }));
+
+ button = $('input[name=add]', container);
+ button.replaceWith(IPA.action_button({
+ 'label': button.val(),
+ 'icon': 'ui-icon-plus',
+ 'click': function() {
+ if ($(this).hasClass('action-button-disabled')) return false;
+ that.show_add_dialog();
+ return false;
+ }
+ }));
+ };
+
+ that.set_enabled = function(enabled) {
+ that.table_set_enabled(enabled);
+ if (enabled) {
+ $('.action-button', that.table).removeClass('action-button-disabled');
+ } else {
+ $('.action-button', that.table).addClass('action-button-disabled');
+ }
+ };
+
+ that.get_records = function(on_success, on_error) {
+
+ if (!that.values.length) return;
+
+ var batch = IPA.batch_command({
+ 'name': that.entity_name+'_'+that.name,
+ 'on_success': on_success,
+ 'on_error': on_error
+ });
+
+ for (var i=0; i<that.values.length; i++) {
+ var value = that.values[i];
+
+ var command = IPA.command({
+ 'method': that.other_entity+'_show',
+ 'args': [value],
+ 'options': {
+ 'all': true,
+ 'rights': true
+ }
+ });
+
+ batch.add_command(command);
+ }
+
+ batch.execute();
+ };
+
+ that.load = function(result) {
+ that.values = result[that.name] || [];
+ that.reset();
+ };
+
+ that.update = function() {
+
+ that.empty();
+
+ if (that.columns.length == 1) { // show pkey only
+ var name = that.columns[0].name;
+ for (var i=0; i<that.values.length; i++) {
+ var record = {};
+ record[name] = that.values[i];
+ that.add_record(record);
+ }
+
+ } else { // get and show additional fields
+ that.get_records(
+ function(data, text_status, xhr) {
+ var results = data.result.results;
+ for (var i=0; i<results.length; i++) {
+ var record = results[i].result;
+ that.add_record(record);
+ }
+ }
+ );
+ }
+ };
+
+ that.create_add_dialog = function() {
+ var pkey = $.bbq.getState(that.entity_name + '-pkey', true) || '';
+ var label = IPA.metadata[that.other_entity].label;
+ var title = 'Add '+label+' to '+that.entity_name+' '+pkey;
+
+ return IPA.association_adder_dialog({
+ 'title': title,
+ 'entity_name': that.entity_name,
+ 'pkey': pkey,
+ 'other_entity': that.other_entity,
+ 'attribute_member': that.attribute_member
+ });
+ };
+
+ that.show_add_dialog = function() {
+
+ var dialog = that.create_add_dialog();
+
+ if (that.adder_columns.length) {
+ dialog.set_columns(that.adder_columns);
+ }
+
+ dialog.execute = function() {
+ that.add(
+ dialog.get_selected_values(),
+ function() {
+ that.refresh();
+ dialog.close();
+ },
+ function() {
+ that.refresh();
+ dialog.close();
+ }
+ );
+ };
+
+ dialog.init();
+
+ dialog.open(that.container);
+ };
+
+ that.add = function(values, on_success, on_error) {
+
+ var pkey = $.bbq.getState(that.entity_name + '-pkey', true) || '';
+
+ var command = IPA.command({
+ 'method': that.entity_name+'_'+that.add_method,
+ 'args': [pkey],
+ 'on_success': on_success,
+ 'on_error': on_error
+ });
+ command.set_option(that.other_entity, values.join(','));
+
+ command.execute();
+ };
+
+ that.show_remove_dialog = function() {
+
+ var selected_values = that.get_selected_values();
+
+ if (!selected_values.length) {
+ alert('Select '+that.label+' to be removed.');
+ return;
+ }
+
+ var pkey = $.bbq.getState(that.entity_name + '-pkey', true) || '';
+ var label = IPA.metadata[that.other_entity].label;
+ var title = 'Remove '+label+' from '+that.entity_name+' '+pkey;
+
+ var dialog = IPA.association_deleter_dialog({
+ 'title': title,
+ 'entity_name': that.entity_name,
+ 'pkey': pkey,
+ 'other_entity': that.other_entity,
+ 'values': selected_values
+ });
+
+ dialog.remove = function() {
+ that.remove(
+ selected_values,
+ function() {
+ that.refresh();
+ dialog.close();
+ },
+ function() {
+ that.refresh();
+ dialog.close();
+ }
+ );
+ };
+
+ dialog.init();
+
+ dialog.open(that.container);
+ };
+
+ that.remove = function(values, on_success, on_error) {
+
+ var pkey = $.bbq.getState(that.entity_name + '-pkey', true) || '';
+
+ var command = IPA.command({
+ 'method': that.entity_name+'_'+that.remove_method,
+ 'args': [pkey],
+ 'on_success': on_success,
+ 'on_error': on_error
+ });
+
+ command.set_option(that.other_entity, values.join(','));
+
+ command.execute();
+ };
+
+ // methods that should be invoked by subclasses
+ that.association_table_widget_init = that.init;
+
+ return that;
+};
+
+
+IPA.association_facet = function (spec) {
+
+ spec = spec || {};
+
+ var that = IPA.facet(spec);
+
+ that.other_entity = spec.other_entity;
+ that.facet_group = spec.facet_group;
+ that.attribute_member = spec.attribute_member;
+
+ that.associator = spec.associator || bulk_associator;
+ that.add_method = spec.add_method || 'add_member';
+ that.remove_method = spec.remove_method || 'remove_member';
+
+ that.columns = [];
+ that.columns_by_name = {};
+
+ that.adder_columns = [];
+ that.adder_columns_by_name = {};
+
+ that.get_column = function(name) {
+ return that.columns_by_name[name];
+ };
+
+ that.add_column = function(column) {
+ that.columns.push(column);
+ that.columns_by_name[column.name] = column;
+ };
+
+ that.create_column = function(spec) {
+ var column = IPA.column(spec);
+ that.add_column(column);
+ return column;
+ };
+
+ that.get_adder_column = function(name) {
+ return that.adder_columns_by_name[name];
+ };
+
+ that.add_adder_column = function(column) {
+ that.adder_columns.push(column);
+ that.adder_columns_by_name[column.name] = column;
+ };
+
+ that.create_adder_column = function(spec) {
+ var column = IPA.column(spec);
+ that.add_adder_column(column);
+ return column;
+ };
+
+ that.init = function() {
+
+ that.facet_init();
+
+ var entity = IPA.get_entity(that.entity_name);
+ var association = entity.get_association(that.other_entity);
+ var column;
+ var i;
+
+ if (association) {
+ if (association.associator) {
+ that.associator = association.associator == 'serial' ? serial_associator : bulk_associator;
+ }
+
+ if (association.add_method) that.add_method = association.add_method;
+ if (association.remove_method) that.remove_method = association.remove_method;
+ }
+
+ var label = IPA.metadata[that.other_entity] ? IPA.metadata[that.other_entity].label : that.other_entity;
+ var pkey_name = IPA.metadata[that.other_entity].primary_key;
+
+ that.table = IPA.table_widget({
+ 'id': that.entity_name+'-'+that.other_entity,
+ 'name': pkey_name,
+ 'label': label,
+ 'entity_name': that.entity_name,
+ 'other_entity': that.other_entity
+ });
+
+ if (that.columns.length) {
+ that.table.set_columns(that.columns);
+
+ } else {
+
+ column = that.table.create_column({
+ name: that.table.name,
+ label: IPA.metadata[that.other_entity].label,
+ primary_key: true
+ });
+
+ column.setup = function(container, record) {
+ container.empty();
+
+ var value = record[column.name];
+ value = value ? value.toString() : '';
+
+ $('<a/>', {
+ 'href': '#'+value,
+ 'html': value,
+ 'click': function (value) {
+ return function() {
+ var state = IPA.tab_state(that.other_entity);
+ state[that.other_entity + '-facet'] = 'details';
+ state[that.other_entity + '-pkey'] = value;
+ $.bbq.pushState(state);
+ return false;
+ };
+ }(value)
+ }).appendTo(container);
+ };
+ }
+
+ for (i=0; i<that.columns.length; i++) {
+ column = that.columns[i];
+ column.entity_name = that.other_entity;
+ }
+
+ for (i=0; i<that.adder_columns.length; i++) {
+ column = that.adder_columns[i];
+ column.entity_name = that.other_entity;
+ }
+
+ that.table.init();
+ };
+
+ that.is_dirty = function() {
+ var pkey = $.bbq.getState(that.entity_name + '-pkey', true) || '';
+ return pkey != that.pkey;
+ };
+
+ that.create = function(container) {
+
+ that.pkey = $.bbq.getState(that.entity_name + '-pkey', true) || '';
+
+ var relationships = IPA.metadata[that.entity_name].relationships;
+ var relationship = relationships[that.attribute_member];
+ if (!relationship)
+ relationship = ['', '', ''];
+
+ /* TODO: I18N and some generic handling of different relationships */
+ var header_message = '';
+ if (relationship[0] == 'Member') {
+ header_message = that.other_entity + '(s) enrolled in ' +
+ that.entity_name + ' ' + that.pkey;
+ } else if (relationship[0] == 'Parent') {
+ header_message = that.entity_name + ' ' + that.pkey +
+ ' is enrolled in the following ' + that.other_entity + '(s)';
+ }
+
+ $('<div/>', {
+ 'id': that.entity_name+'-'+that.other_entity,
+ html: $('<h2/>',{ html: header_message })
+ }).appendTo(container);
+
+ var span = $('<span/>', { 'name': 'association' }).appendTo(container);
+
+ that.table.create(span);
+
+ var action_panel = that.get_action_panel();
+ var li = $('.action-controls', action_panel);
+
+ // creating generic buttons for layout
+ $('<input/>', {
+ 'type': 'button',
+ 'name': 'remove',
+ 'value': IPA.messages.button.remove
+ }).appendTo(li);
+
+ /* TODO: genering handling of different relationships */
+ if ((relationship[0] == 'Member')||(relationship[0] == 'Member Of')) {
+ $('<input/>', {
+ 'type': 'button',
+ 'name': 'add',
+ 'value': IPA.messages.button.enroll
+ }).appendTo(li);
+ }
+ };
+
+ that.setup = function(container) {
+
+ that.facet_setup(container);
+
+ var span = $('span[name=association]', that.container);
+
+ that.table.setup(span);
+
+ // replacing generic buttons with IPA.button and setting click handler
+ var action_panel = that.get_action_panel();
+
+ var button = $('input[name=remove]', action_panel);
+ button.replaceWith(IPA.action_button({
+ 'label': button.val(),
+ 'icon': 'ui-icon-trash',
+ 'click': function() { that.show_remove_dialog(); }
+ }));
+
+ button = $('input[name=add]', action_panel);
+ button.replaceWith(IPA.action_button({
+ 'label': button.val(),
+ 'icon': 'ui-icon-plus',
+ 'click': function() { that.show_add_dialog(); }
+ }));
+ };
+
+ that.show_add_dialog = function() {
+
+ var pkey = $.bbq.getState(that.entity_name + '-pkey', true) || '';
+ var label = IPA.metadata[that.other_entity] ? IPA.metadata[that.other_entity].label : that.other_entity;
+ var title = 'Enroll ' + label + ' in ' + that.entity_name + ' ' + pkey;
+
+ var dialog = IPA.association_adder_dialog({
+ 'title': title,
+ 'entity_name': that.entity_name,
+ 'pkey': pkey,
+ 'other_entity': that.other_entity,
+ 'attribute_member': that.attribute_member
+ });
+
+ if (that.adder_columns.length) {
+ dialog.set_columns(that.adder_columns);
+ }
+
+ dialog.execute = function() {
+
+ var pkey = $.bbq.getState(that.entity_name + '-pkey', true) || '';
+
+ var associator = that.associator({
+ 'entity_name': that.entity_name,
+ 'pkey': pkey,
+ 'other_entity': that.other_entity,
+ 'values': dialog.get_selected_values(),
+ 'method': that.add_method,
+ 'on_success': function() {
+ that.refresh();
+ dialog.close();
+ },
+ 'on_error': function() {
+ that.refresh();
+ dialog.close();
+ }
+ });
+
+ associator.execute();
+ };
+
+ dialog.init();
+
+ dialog.open(that.container);
+ };
+
+ that.show_remove_dialog = function() {
+
+ var label = IPA.metadata[that.other_entity] ? IPA.metadata[that.other_entity].label : that.other_entity;
+ var values = that.table.get_selected_values();
+
+ if (!values.length) {
+ alert('Select '+label+' to be removed.');
+ return;
+ }
+
+ var pkey = $.bbq.getState(that.entity_name + '-pkey', true) || '';
+ var title = 'Remove '+label+' from '+that.entity_name+' '+pkey;
+
+ var dialog = IPA.association_deleter_dialog({
+ 'title': title,
+ 'entity_name': that.entity_name,
+ 'pkey': pkey,
+ 'other_entity': that.other_entity,
+ 'values': values,
+ 'associator': that.associator,
+ 'method': that.remove_method,
+ 'on_success': function() {
+ that.refresh();
+ dialog.close();
+ },
+ 'on_error': function() {
+ that.refresh();
+ dialog.close();
+ }
+ });
+
+ dialog.init();
+
+ dialog.open(that.container);
+ };
+
+ that.get_records = function(pkeys, on_success, on_error) {
+
+ if (!pkeys.length) return;
+
+ var batch = IPA.batch_command({
+ 'name': that.entity_name+'_'+that.name,
+ 'on_success': on_success,
+ 'on_error': on_error
+ });
+
+ for (var i=0; i<pkeys.length; i++) {
+ var pkey = pkeys[i];
+
+ var command = IPA.command({
+ 'method': that.other_entity+'_show',
+ 'args': [pkey],
+ 'options': {
+ 'all': true,
+ 'rights': true
+ }
+ });
+
+ batch.add_command(command);
+ }
+
+ batch.execute();
+ };
+
+ that.refresh = function() {
+
+ function on_success(data, text_status, xhr) {
+
+ that.table.empty();
+
+ var pkeys = data.result.result[that.name];
+ if (!pkeys) return;
+
+ if (that.table.columns.length == 1) { // show pkey only
+ var name = that.table.columns[0].name;
+ for (var i=0; i<pkeys.length; i++) {
+ var record = {};
+ record[name] = pkeys[i];
+ that.table.add_record(record);
+ }
+
+ } else { // get and show additional fields
+ that.get_records(
+ pkeys,
+ function(data, text_status, xhr) {
+ var results = data.result.results;
+ for (var i=0; i<results.length; i++) {
+ var record = results[i].result;
+ that.table.add_record(record);
+ }
+ }
+ );
+ }
+ }
+
+ function on_error(xhr, text_status, error_thrown) {
+ var summary = $('span[name=summary]', that.table.tfoot).empty();
+ summary.append('<p>Error: '+error_thrown.name+'</p>');
+ summary.append('<p>'+error_thrown.title+'</p>');
+ summary.append('<p>'+error_thrown.message+'</p>');
+ }
+
+ var pkey = $.bbq.getState(that.entity_name + '-pkey', true) || '';
+ IPA.cmd('show', [pkey], {'rights': true}, on_success, on_error, that.entity_name);
+ };
+
+ that.association_facet_init = that.init;
+
+ return that;
+};
+
+
+IPA.deleter_dialog_setup = function () {
+
+ var that = this;
+
+ var ul = $('<ul/>');
+ ul.appendTo(that.dialog);
+
+ for (var i=0; i<that.values.length; i++) {
+ $('<li/>',{
+ 'text': that.values[i]
+ }).appendTo(ul);
+ }
+
+ $('<p/>', {
+ 'text': IPA.messages.search.delete_confirm
+ }).appendTo(that.dialog);
+};
diff --git a/install/ui/caution.png b/install/ui/caution.png
new file mode 100755
index 000000000..ce7a68ad9
--- /dev/null
+++ b/install/ui/caution.png
Binary files differ
diff --git a/install/ui/certificate.js b/install/ui/certificate.js
new file mode 100755
index 000000000..b7e5a51d3
--- /dev/null
+++ b/install/ui/certificate.js
@@ -0,0 +1,785 @@
+/*jsl:import ipa.js */
+
+/* Authors:
+ * Endi Sukma Dewata <edewata@redhat.com>
+ *
+ * Copyright (C) 2010 Red Hat
+ * see file 'COPYING' for use and warranty information
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+var BEGIN_CERTIFICATE = '-----BEGIN CERTIFICATE-----';
+var END_CERTIFICATE = '-----END CERTIFICATE-----';
+
+var BEGIN_CERTIFICATE_REQUEST = '-----BEGIN CERTIFICATE REQUEST-----';
+var END_CERTIFICATE_REQUEST = '-----END CERTIFICATE REQUEST-----';
+
+var CRL_REASON = [
+ 'Unspecified',
+ 'Key Compromise',
+ 'CA Compromise',
+ 'Affiliation Changed',
+ 'Superseded',
+ 'Cessation of Operation',
+ 'Certificate Hold',
+ null,
+ 'Remove from CRL',
+ 'Privilege Withdrawn',
+ 'AA Compromise'
+];
+
+var CERTIFICATE_STATUS_MISSING = 0;
+var CERTIFICATE_STATUS_VALID = 1;
+var CERTIFICATE_STATUS_REVOKED = 2;
+
+function certificate_parse_dn(dn) {
+
+ var result = {};
+ if (!dn) return result;
+
+ // TODO: Use proper LDAP DN parser
+ var rdns = dn.split(',');
+ for (var i=0; i<rdns.length; i++) {
+ var rdn = rdns[i];
+ if (!rdn) continue;
+
+ var parts = rdn.split('=');
+ var name = $.trim(parts[0].toLowerCase());
+ var value = $.trim(parts[1]);
+
+ var old_value = result[name];
+ if (!old_value) {
+ result[name] = value;
+ } else if (typeof old_value == "string") {
+ result[name] = [old_value, value];
+ } else {
+ result[name].push(value);
+ }
+ }
+
+ return result;
+}
+
+function certificate_get_dialog(spec) {
+ var that = {};
+ spec = spec || {};
+
+ that.title = spec.title || '';
+ that.usercertificate = spec.usercertificate || '';
+
+ var dialog = $('<div/>', {
+ 'title': that.title
+ });
+
+ var textarea = $('<textarea/>', {
+ readonly: 'yes',
+ style: 'width: 100%; height: 275px;'
+ }).appendTo(dialog);
+
+ textarea.val(
+ BEGIN_CERTIFICATE+'\n'+
+ that.usercertificate+'\n'+
+ END_CERTIFICATE );
+
+ that.open = function() {
+ dialog.dialog({
+ modal: true,
+ width: 500,
+ height: 400,
+ buttons: {
+ 'Close': function() {
+ dialog.dialog('destroy');
+ }
+ }
+ });
+ };
+
+ return that;
+}
+
+function certificate_revoke_dialog(spec) {
+ var that = {};
+ spec = spec || {};
+
+ that.title = spec.title || '';
+ that.revoke = spec.revoke;
+
+ var dialog = $('<div/>', {
+ 'title': that.title
+ });
+
+ var table = $('<table/>').appendTo(dialog);
+
+ var tr = $('<tr/>').appendTo(table);
+
+ var td = $('<td/>').appendTo(tr);
+ td.append('Note:');
+
+ td = $('<td/>').appendTo(tr);
+ td.append(
+ 'To confirm your intention to revoke this certificate, '+
+ 'select a reason from the pull-down list, and click '+
+ 'the "Revoke" button.');
+
+ tr = $('<tr/>').appendTo(table);
+
+ td = $('<td/>').appendTo(tr);
+ td.append('Reason for Revocation:');
+
+ td = $('<td/>').appendTo(tr);
+
+ var select = $('<select/>').appendTo(td);
+ for (var i=0; i<CRL_REASON.length; i++) {
+ if (!CRL_REASON[i]) continue;
+ $('<option/>', {
+ 'value': i,
+ 'html': CRL_REASON[i]
+ }).appendTo(select);
+ }
+
+ that.open = function() {
+ dialog.dialog({
+ modal: true,
+ width: 500,
+ height: 300,
+ buttons: {
+ 'Revoke': function() {
+ var values = {};
+ values['reason'] = select.val();
+ if (that.revoke) {
+ that.revoke(values);
+ }
+ dialog.dialog('destroy');
+ },
+ 'Cancel': function() {
+ dialog.dialog('destroy');
+ }
+ }
+ });
+ };
+
+ return that;
+}
+
+function certificate_restore_dialog(spec) {
+ var that = {};
+ spec = spec || {};
+
+ that.title = spec.title || '';
+ that.restore = spec.restore;
+
+ var dialog = $('<div/>', {
+ 'title': that.title
+ });
+
+ dialog.append(
+ 'To confirm your intention to restore this certificate, '+
+ 'click the "Restore" button.');
+
+ that.open = function() {
+ dialog.dialog({
+ modal: true,
+ width: 400,
+ height: 200,
+ buttons: {
+ 'Restore': function() {
+ var values = {};
+ if (that.restore) {
+ that.restore(values);
+ }
+ dialog.dialog('destroy');
+ },
+ 'Cancel': function() {
+ dialog.dialog('destroy');
+ }
+ }
+ });
+ };
+
+ return that;
+}
+
+function certificate_view_dialog(spec) {
+ var that = {};
+ spec = spec || {};
+
+ that.title = spec.title || '';
+ that.subject = certificate_parse_dn(spec.subject);
+ that.serial_number = spec.serial_number || '';
+ that.issuer = certificate_parse_dn(spec.issuer);
+ that.issued_on = spec.issued_on || '';
+ that.expires_on = spec.expires_on || '';
+ that.md5_fingerprint = spec.md5_fingerprint || '';
+ that.sha1_fingerprint = spec.sha1_fingerprint || '';
+
+ var dialog = $('<div/>', {
+ 'title': that.title
+ });
+
+ var table = $('<table/>').appendTo(dialog);
+
+ var tr = $('<tr/>').appendTo(table);
+ $('<td/>', {
+ 'colspan': 2,
+ 'html': '<h3>Issued To</h3>'
+ }).appendTo(tr);
+
+ tr = $('<tr/>').appendTo(table);
+ $('<td>Common Name:</td>').appendTo(tr);
+ $('<td/>', {
+ 'html': that.subject.cn
+ }).appendTo(tr);
+
+ tr = $('<tr/>').appendTo(table);
+ $('<td>Organization:</td>').appendTo(tr);
+ $('<td/>', {
+ 'html': that.subject.o
+ }).appendTo(tr);
+
+ tr = $('<tr/>').appendTo(table);
+ $('<td>Organizational Unit:</td>').appendTo(tr);
+ $('<td/>', {
+ 'html': that.subject.ou
+ }).appendTo(tr);
+
+ tr = $('<tr/>').appendTo(table);
+ $('<td>Serial Number:</td>').appendTo(tr);
+ $('<td/>', {
+ 'html': that.serial_number
+ }).appendTo(tr);
+
+ tr = $('<tr/>').appendTo(table);
+ $('<td/>', {
+ 'colspan': 2,
+ 'html': '<h3>Issued By</h3>'
+ }).appendTo(tr);
+
+ tr = $('<tr/>').appendTo(table);
+ $('<td>Common Name:</td>').appendTo(tr);
+ $('<td/>', {
+ 'html': that.issuer.cn
+ }).appendTo(tr);
+
+ tr = $('<tr/>').appendTo(table);
+ $('<td>Organization:</td>').appendTo(tr);
+ $('<td/>', {
+ 'html': that.issuer.o
+ }).appendTo(tr);
+
+ tr = $('<tr/>').appendTo(table);
+ $('<td>Organizational Unit:</td>').appendTo(tr);
+ $('<td/>', {
+ 'html': that.issuer.ou
+ }).appendTo(tr);
+
+ tr = $('<tr/>').appendTo(table);
+ $('<td/>', {
+ 'colspan': 2,
+ 'html': '<h3>Validity</h3>'
+ }).appendTo(tr);
+
+ tr = $('<tr/>').appendTo(table);
+ $('<td>Issued On:</td>').appendTo(tr);
+ $('<td/>', {
+ 'html': that.issued_on
+ }).appendTo(tr);
+
+ tr = $('<tr/>').appendTo(table);
+ $('<td>Expires On:</td>').appendTo(tr);
+ $('<td/>', {
+ 'html': that.expires_on
+ }).appendTo(tr);
+
+ tr = $('<tr/>').appendTo(table);
+ $('<td/>', {
+ 'colspan': 2,
+ 'html': '<h3>Fingerprints</h3>'
+ }).appendTo(tr);
+
+ tr = $('<tr/>').appendTo(table);
+ $('<td>SHA1 Fingerprint:</td>').appendTo(tr);
+ $('<td/>', {
+ 'html': that.sha1_fingerprint
+ }).appendTo(tr);
+
+ tr = $('<tr/>').appendTo(table);
+ $('<td>MD5 Fingerprint:</td>').appendTo(tr);
+ $('<td/>', {
+ 'html': that.md5_fingerprint
+ }).appendTo(tr);
+
+ that.open = function() {
+ dialog.dialog({
+ modal: true,
+ width: 600,
+ height: 500,
+ buttons: {
+ 'Close': function() {
+ dialog.dialog('destroy');
+ }
+ }
+ });
+ };
+
+ return that;
+}
+
+function certificate_request_dialog(spec) {
+ var that = {};
+ spec = spec || {};
+
+ that.title = spec.title || '';
+ that.request = spec.request;
+
+ var dialog = $('<div/>', {
+ 'title': that.title
+ });
+
+ dialog.append('Copy and paste the Base64-encoded CSR below:');
+ dialog.append('<br/>');
+ dialog.append('<br/>');
+
+ dialog.append(BEGIN_CERTIFICATE_REQUEST);
+ dialog.append('<br/>');
+
+ var textarea = $('<textarea/>', {
+ style: 'width: 100%; height: 225px;'
+ }).appendTo(dialog);
+
+ dialog.append('<br/>');
+ dialog.append(END_CERTIFICATE_REQUEST);
+
+ that.open = function() {
+ dialog.dialog({
+ modal: true,
+ width: 500,
+ height: 400,
+ buttons: {
+ 'Issue': function() {
+ var values = {};
+ var request = textarea.val();
+ request =
+ BEGIN_CERTIFICATE_REQUEST+'\n'+
+ $.trim(request)+'\n'+
+ END_CERTIFICATE_REQUEST+'\n';
+ values['request'] = request;
+ if (that.request) {
+ that.request(values);
+ }
+ dialog.dialog('destroy');
+ },
+ 'Cancel': function() {
+ dialog.dialog('destroy');
+ }
+ }
+ });
+ };
+
+ return that;
+}
+
+function certificate_status_widget(spec) {
+
+ spec = spec || {};
+
+ var that = IPA.widget(spec);
+
+ that.entity_label = spec.entity_label || that.entity_name;
+
+ that.result = spec.result;
+
+ that.get_entity_pkey = spec.get_entity_pkey;
+ that.get_entity_name = spec.get_entity_name;
+ that.get_entity_principal = spec.get_entity_principal;
+ that.get_entity_certificate = spec.get_entity_certificate;
+
+ that.is_selfsign = function() {
+ return IPA.env.ra_plugin == 'selfsign';
+ };
+
+ that.create = function(container) {
+
+ that.widget_create(container);
+
+ var dd = $('<dd/>', {
+ 'class': 'first'
+ }).appendTo(container);
+
+ var div = $('<div/>', {
+ name: 'certificate-valid'
+ }).appendTo(dd);
+
+ $('<img/>', {
+ src: 'check.png',
+ style: 'float: left;',
+ 'class': 'status-icon'
+ }).appendTo(div);
+
+ var content_div = $('<div/>', {
+ style: 'float: left;'
+ }).appendTo(div);
+
+ content_div.append('<b>Valid Certificate Present:</b>');
+
+ content_div.append(' ');
+
+ $('<input/>', {
+ 'type': 'button',
+ 'name': 'get',
+ 'value': 'Get'
+ }).appendTo(content_div);
+
+ content_div.append(' ');
+
+ if (!that.is_selfsign()) {
+ $('<input/>', {
+ 'type': 'button',
+ 'name': 'revoke',
+ 'value': 'Revoke'
+ }).appendTo(content_div);
+
+ content_div.append(' ');
+ }
+
+ $('<input/>', {
+ 'type': 'button',
+ 'name': 'view',
+ 'value': 'View'
+ }).appendTo(content_div);
+
+ content_div.append(' ');
+
+ $('<input/>', {
+ 'type': 'button',
+ 'name': 'create',
+ 'value': 'New Certificate'
+ }).appendTo(content_div);
+
+ if (!that.is_selfsign()) {
+ div = $('<div/>', {
+ name: 'certificate-revoked'
+ }).appendTo(dd);
+
+ $('<img/>', {
+ src: 'caution.png',
+ style: 'float: left;',
+ 'class': 'status-icon'
+ }).appendTo(div);
+
+ content_div = $('<div/>', {
+ style: 'float: left;'
+ }).appendTo(div);
+
+ content_div.append('<b>Certificate Revoked:</b>');
+
+ content_div.append(' ');
+
+ content_div.append($('<span/>', {
+ 'name': 'revocation_reason'
+ }));
+
+ content_div.append(' ');
+
+ $('<input/>', {
+ 'type': 'button',
+ 'name': 'restore',
+ 'value': 'Restore'
+ }).appendTo(content_div);
+
+ content_div.append(' ');
+
+ $('<input/>', {
+ 'type': 'button',
+ 'name': 'create',
+ 'value': 'New Certificate'
+ }).appendTo(content_div);
+ }
+
+ div = $('<div/>', {
+ name: 'certificate-missing'
+ }).appendTo(dd);
+
+ $('<img/>', {
+ src: 'caution.png',
+ style: 'float: left;',
+ 'class': 'status-icon'
+ }).appendTo(div);
+
+ content_div = $('<div/>', {
+ style: 'float: left;'
+ }).appendTo(div);
+
+ content_div.append('<b>No Valid Certificate:</b>');
+
+ content_div.append(' ');
+
+ $('<input/>', {
+ 'type': 'button',
+ 'name': 'create',
+ 'value': 'New Certificate'
+ }).appendTo(content_div);
+ };
+
+ that.setup = function(container) {
+
+ that.widget_setup(container);
+
+ that.valid = $('div[name=certificate-valid]', that.container);
+ that.revoked = $('div[name=certificate-revoked]', that.container);
+ that.missing = $('div[name=certificate-missing]', that.container);
+
+ var button = $('input[name=get]', that.container);
+ that.get_button = IPA.button({
+ 'label': 'Get',
+ 'click': function() {
+ IPA.cmd(that.entity_name+'_show', [that.pkey], {},
+ function(data, text_status, xhr) {
+ get_certificate(data.result.result);
+ }
+ );
+ }
+ });
+ button.replaceWith(that.get_button);
+
+ button = $('input[name=revoke]', that.container);
+ that.revoke_button = IPA.button({
+ 'label': 'Revoke',
+ 'click': function() {
+ IPA.cmd(that.entity_name+'_show', [that.pkey], {},
+ function(data, text_status, xhr) {
+ revoke_certificate(data.result.result);
+ }
+ );
+ }
+ });
+ button.replaceWith(that.revoke_button);
+
+ button = $('input[name=view]', that.container);
+ that.view_button = IPA.button({
+ 'label': 'View',
+ 'click': function() {
+ IPA.cmd(that.entity_name+'_show', [that.pkey], {},
+ function(data, text_status, xhr) {
+ view_certificate(data.result.result);
+ }
+ );
+ }
+ });
+ button.replaceWith(that.view_button);
+
+ that.revocation_reason = $('span[name=revocation_reason]', that.container);
+
+ button = $('input[name=restore]', that.container);
+ that.restore_button = IPA.button({
+ 'label': 'Restore',
+ 'click': function() {
+ IPA.cmd(that.entity_name+'_show', [that.pkey], {},
+ function(data, text_status, xhr) {
+ restore_certificate(data.result.result);
+ }
+ );
+ }
+ });
+ button.replaceWith(that.restore_button);
+
+ $('input[name=create]', that.container).each(function(index) {
+ button = $(this);
+ that.create_button = IPA.button({
+ 'label': 'New Certificate',
+ 'click': function() {
+ request_certificate(that.result);
+ }
+ });
+ button.replaceWith(that.create_button);
+ });
+ };
+
+ that.load = function(result) {
+
+ that.result = result;
+ that.pkey = that.get_entity_pkey(that.result);
+
+ var entity_certificate = that.get_entity_certificate(that.result);
+ if (entity_certificate) {
+ check_status(that.result.serial_number);
+ } else {
+ set_status(CERTIFICATE_STATUS_MISSING);
+ }
+ };
+
+ function set_status(status, revocation_reason) {
+ that.valid.css('display', status == CERTIFICATE_STATUS_VALID ? 'inline' : 'none');
+ that.missing.css('display', status == CERTIFICATE_STATUS_MISSING ? 'inline' : 'none');
+
+ if (!that.is_selfsign()) {
+ that.revoked.css('display', status == CERTIFICATE_STATUS_REVOKED ? 'inline' : 'none');
+ that.revoke_button.css('visibility', status == CERTIFICATE_STATUS_VALID ? 'visible' : 'hidden');
+ that.revocation_reason.html(revocation_reason == undefined ? '' : CRL_REASON[revocation_reason]);
+ that.restore_button.css('visibility', revocation_reason == 6 ? 'visible' : 'hidden');
+ }
+ }
+
+ function check_status(serial_number) {
+
+ if (that.is_selfsign()) {
+ set_status(CERTIFICATE_STATUS_VALID);
+ return;
+ }
+
+ IPA.cmd(
+ 'cert_show',
+ [serial_number],
+ { },
+ function(data, text_status, xhr) {
+ var revocation_reason = data.result.result.revocation_reason;
+ if (revocation_reason == undefined) {
+ set_status(CERTIFICATE_STATUS_VALID);
+ } else {
+ set_status(CERTIFICATE_STATUS_REVOKED, revocation_reason);
+ }
+ }
+ );
+ }
+
+ function view_certificate(result) {
+
+ var entity_certificate = that.get_entity_certificate(result);
+ if (!entity_certificate) {
+ set_status(CERTIFICATE_STATUS_MISSING);
+ return;
+ }
+
+ var entity_name = that.get_entity_name(result);
+
+ var dialog = certificate_view_dialog({
+ 'title': 'Certificate for '+that.entity_label+' '+entity_name,
+ 'subject': result['subject'],
+ 'serial_number': result['serial_number'],
+ 'issuer': result['issuer'],
+ 'issued_on': result['valid_not_before'],
+ 'expires_on': result['valid_not_after'],
+ 'md5_fingerprint': result['md5_fingerprint'],
+ 'sha1_fingerprint': result['sha1_fingerprint']
+ });
+
+ dialog.open();
+ }
+
+ function get_certificate(result) {
+
+ var entity_certificate = that.get_entity_certificate(result);
+ if (!entity_certificate) {
+ set_status(CERTIFICATE_STATUS_MISSING);
+ return;
+ }
+
+ var entity_name = that.get_entity_name(result);
+
+ var dialog = certificate_get_dialog({
+ 'title': 'Certificate for '+that.entity_label+' '+entity_name,
+ 'usercertificate': entity_certificate
+ });
+
+ dialog.open();
+ }
+
+ function request_certificate(result) {
+
+ var entity_name = that.get_entity_name(result);
+ var entity_principal = that.get_entity_principal(result);
+
+ var dialog = certificate_request_dialog({
+ 'title': 'Issue New Certificate for '+that.entity_label+' '+entity_name,
+ 'request': function(values) {
+ var request = values['request'];
+
+ IPA.cmd(
+ 'cert_request',
+ [request],
+ {
+ 'principal': entity_principal
+ },
+ function(data, text_status, xhr) {
+ check_status(data.result.result.serial_number);
+ }
+ );
+ }
+ });
+
+ dialog.open();
+ }
+
+ function revoke_certificate(result) {
+
+ var entity_certificate = that.get_entity_certificate(result);
+ if (!entity_certificate) {
+ set_status(CERTIFICATE_STATUS_MISSING);
+ return;
+ }
+
+ var entity_name = that.get_entity_name(result);
+ var serial_number = result['serial_number'];
+
+ var dialog = certificate_revoke_dialog({
+ 'title': 'Revoke Certificate for '+that.entity_label+' '+entity_name,
+ 'revoke': function(values) {
+ var reason = values['reason'];
+
+ IPA.cmd(
+ 'cert_revoke',
+ [serial_number],
+ {
+ 'revocation_reason': reason
+ },
+ function(data, text_status, xhr) {
+ check_status(serial_number);
+ }
+ );
+ }
+ });
+
+ dialog.open();
+ }
+
+ function restore_certificate(result) {
+
+ var entity_certificate = that.get_entity_certificate(result);
+ if (!entity_certificate) {
+ set_status(CERTIFICATE_STATUS_MISSING);
+ return;
+ }
+
+ var entity_name = that.get_entity_name(result);
+ var serial_number = result['serial_number'];
+
+ var dialog = certificate_restore_dialog({
+ 'title': 'Restore Certificate for '+that.entity_label+' '+entity_name,
+ 'restore': function(values) {
+ IPA.cmd(
+ 'cert_remove_hold',
+ [serial_number],
+ { },
+ function(data, text_status, xhr) {
+ check_status(serial_number);
+ }
+ );
+ }
+ });
+
+ dialog.open();
+ }
+
+ return that;
+}
diff --git a/install/ui/check.png b/install/ui/check.png
new file mode 100755
index 000000000..c3646db11
--- /dev/null
+++ b/install/ui/check.png
Binary files differ
diff --git a/install/ui/details.js b/install/ui/details.js
new file mode 100644
index 000000000..aad77a9c4
--- /dev/null
+++ b/install/ui/details.js
@@ -0,0 +1,897 @@
+/*jsl:import ipa.js */
+
+/* Authors:
+ * Pavel Zuna <pzuna@redhat.com>
+ * Adam Young <ayoung@redhat.com>
+ * Endi S. Dewata <edewata@redhat.com>
+ *
+ * Copyright (C) 2010 Red Hat
+ * see file 'COPYING' for use and warranty information
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* IPA Object Details - populating definiton lists from entry data */
+
+/* REQUIRES: ipa.js */
+
+IPA.expand_icon = 'ui-icon-minus';
+IPA.collapse_icon = 'ui-icon-plus';
+
+IPA.is_field_writable = function(rights){
+ if (!rights){
+ alert('no right');
+ }
+ return rights.indexOf('w') > -1;
+};
+
+IPA.details_field = function (spec) {
+
+ spec = spec || {};
+
+ var that = IPA.widget(spec);
+
+ that.load = spec.load || load;
+ that.save = spec.save || save;
+
+ function load(record) {
+ that.record = record;
+ that.values = record[that.name];
+ that.reset();
+ }
+
+ that.update = function() {
+
+ if (!that.record) return;
+
+ /* remove all <dd> tags i.e. all attribute values */
+ $('dd', that.container).remove();
+
+ var multivalue = false;
+ var hint_span = null;
+ var dd;
+
+ var param_info = IPA.get_param_info(that.entity_name, that.name);
+ if (param_info) {
+ if (param_info['multivalue'] || param_info['class'] == 'List')
+ multivalue = true;
+ var hint = param_info['doc'];
+ if (hint){
+ hint_span = $('<span />',{
+ 'class': 'attrhint',
+ 'html': 'Hint: ' + hint});
+ }
+ }
+
+ var rights = 'rsc';
+
+ if (that.record.attributelevelrights){
+ rights = that.record.attributelevelrights[this.name] || rights ;
+ }
+
+ if (that.values) {
+ /*
+ Too much logic currently assumes an array.
+ This is true everywhere but ACIs. */
+
+ if (!(that.values instanceof Array)){
+ that.values = [that.values];
+ }
+
+ dd = IPA.create_first_dd(that.name);
+ dd.append(that.create_value(that.values[0], hint_span, rights, 0));
+ dd.appendTo(that.container);
+
+ for (var i = 1; i < that.values.length; ++i) {
+ dd = IPA.create_other_dd(that.name);
+ dd.append(that.create_value(that.values[i], hint_span, rights, i));
+ dd.appendTo(that.container);
+ }
+
+ if (multivalue && IPA.is_field_writable(rights) ) {
+ dd = IPA.create_other_dd(that.name);
+ dd.append(IPA.details_field_create_add_link.call(that, that.name, rights, that.values.length));
+ dd.appendTo(that.container);
+ }
+
+ } else {
+ if (multivalue && IPA.is_field_writable(rights)) {
+ dd = IPA.create_first_dd(that.name);
+ dd.append(IPA.details_field_create_add_link.call(that, that.name, rights, 0));
+ dd.appendTo(that.container);
+
+ } else {
+ dd = IPA.create_first_dd(that.name);
+ dd.append(that.create_value('', hint_span, rights, 0));
+ dd.appendTo(that.container);
+ }
+ }
+ };
+
+ /* create an HTML element for displaying/editing an attribute
+ * arguments:
+ * attr - LDAP attribute name
+ * value - the attributes value */
+ that.create_value = function(value, hint, rights, index) {
+
+ // if field is primary key or non-writable, return a label
+
+ var label = $('<label/>', { html:value.toString() });
+
+ if (!IPA.is_field_writable(rights)) return label;
+
+ var param_info = IPA.get_param_info(that.entity_name, that.name);
+ if (param_info) {
+ if (param_info['primary_key']) return label;
+ if ('no_update' in param_info['flags']) return label;
+ }
+
+ // otherwise, create input field
+
+ var input = that.create_input(value, param_info, rights, index);
+ if (param_info) {
+ if (param_info['multivalue'] || param_info['class'] == 'List') {
+ input.append(_ipa_create_remove_link(that.name, param_info));
+ }
+ }
+
+ if (hint) input.after(hint);
+
+ return input;
+ };
+
+ /* creates a input box for editing a string attribute */
+ that.create_input = function(value, param_info, rights, index) {
+
+ index = index || 0;
+
+ function validate_input(text, param_info, error_link) {
+ if (param_info && param_info.pattern) {
+ var regex = new RegExp( param_info.pattern );
+ if (!text.match(regex)) {
+ error_link.style.display = "block";
+ if (param_info.pattern_errmsg) {
+ error_link.innerHTML = param_info.pattern_errmsg;
+ }
+ } else {
+ error_link.style.display = "none";
+ }
+ }
+ }
+
+ var doc = that.name;
+ if (param_info && param_info.doc) {
+ doc = param_info.doc;
+ }
+ var span = $("<Span />");
+ var input = $("<input/>", {
+ type: "text",
+ name: that.name,
+ value: value.toString(),
+ title: doc,
+ keyup: function(){
+ var undo_link = this.nextElementSibling;
+ undo_link.style.display = "inline";
+ var error_link = undo_link.nextElementSibling;
+
+ var text = $(this).val();
+ validate_input(text, param_info,error_link);
+ }
+ }).appendTo(span) ;
+
+ if (!IPA.is_field_writable(rights)) {
+ input.attr('disabled', 'disabled');
+ }
+
+ span.append($("<a/>", {
+ html:"undo",
+ "class":"ui-state-highlight ui-corner-all undo",
+ style:"display:none",
+ click: function(){
+ var previous_value = that.values || '';
+ if (index >= previous_value.length){
+ previous_value = '';
+ }else{
+ previous_value= previous_value[index];
+ }
+
+ this.previousElementSibling.value = previous_value;
+ this.style.display = "none";
+ var error_link = this.nextElementSibling;
+ validate_input(previous_value, param_info,error_link);
+ }
+ }));
+ span.append($("<span/>", {
+ html:"Does not match pattern",
+ "class":"ui-state-error ui-corner-all",
+ style:"display:none"
+ }));
+ return span;
+ };
+
+ function save() {
+ var values = [];
+
+ $('dd', that.container).each(function () {
+
+ var input = $('input', $(this));
+ if (!input.length) return;
+
+ if (input.is('.strikethrough')) return;
+
+ var value = $.trim(input.val());
+ if (!value) value = '';
+
+ values.push(value);
+ });
+
+ return values;
+ }
+
+ return that;
+};
+
+
+IPA.details_section = function (spec){
+
+ spec = spec || {};
+
+ var that = {};
+
+ that.name = spec.name || '';
+ that.label = spec.label || '';
+ that.template = spec.template;
+ that._entity_name = spec.entity_name;
+
+ that.fields = [];
+ that.fields_by_name = {};
+
+ that.__defineGetter__("entity_name", function(){
+ return that._entity_name;
+ });
+
+ that.__defineSetter__("entity_name", function(entity_name){
+ that._entity_name = entity_name;
+
+ for (var i=0; i<that.fields.length; i++) {
+ that.fields[i].entity_name = entity_name;
+ }
+ });
+
+ that.get_field = function(name) {
+ return that.fields_by_name[name];
+ };
+
+ that.add_field = function(field) {
+ field.entity_name = that.entity_name;
+ that.fields.push(field);
+ that.fields_by_name[field.name] = field;
+ return field;
+ };
+
+ that.create_field = function(spec) {
+
+ //TODO: replace IPA.details_field with class-specific implementation
+ //Valid field classes: Str, IA5Str, Int, Bool and List
+ var field = IPA.details_field(spec);
+ that.add_field(field);
+ return field;
+ };
+
+ that.create_text = function(spec) {
+ var field = IPA.text_widget(spec);
+ that.add_field(field);
+ return field;
+ };
+
+ that.create_radio = function(spec) {
+ var field = IPA.radio_widget(spec);
+ that.add_field(field);
+ return field;
+ };
+
+ that.create_textarea = function(spec) {
+ var field = IPA.textarea_widget(spec);
+ that.add_field(field);
+ return field;
+ };
+
+ that.create_button = function(spec) {
+ var field = IPA.button_widget(spec);
+ that.add_field(field);
+ return field;
+ };
+
+ that.init = function() {
+ for (var i=0; i<that.fields.length; i++) {
+ var field = that.fields[i];
+ field.init();
+ }
+ };
+
+ that.create = function(container) {
+
+ if (that.template) return;
+
+ var fields = that.fields;
+ for (var i = 0; i < fields.length; ++i) {
+ var field = fields[i];
+
+ var span = $('<span/>', { 'name': field.name }).appendTo(container);
+ field.create(span);
+ }
+ };
+
+ that.setup = function(container) {
+
+ that.container = container;
+
+ if (that.template) return;
+
+ var fields = that.fields;
+ for (var i = 0; i < fields.length; ++i) {
+ var field = fields[i];
+
+ var span = $('span[name='+field.name+']', this.container).first();
+ field.setup(span);
+ }
+ };
+
+ that.load = function(record) {
+
+ var fields = that.fields;
+
+ if (that.template) {
+ var template = IPA.get_template(that.template);
+ this.container.load(
+ template,
+ function(data, text_status, xhr) {
+ for (var i = 0; i < fields.length; ++i) {
+ var field = fields[i];
+ var span = $('span[name='+field.name+']', this.container).first();
+ field.setup(span);
+ field.load(record);
+ }
+ }
+ );
+ return;
+ }
+
+ for (var j=0; j<fields.length; j++) {
+ var field = fields[j];
+ var span = $('span[name='+field.name+']', this.container).first();
+ field.load(record);
+ }
+ };
+
+ that.reset = function() {
+ for (var i=0; i<that.fields.length; i++) {
+ var field = that.fields[i];
+ var span = $('span[name='+field.name+']', this.container).first();
+ field.reset();
+ }
+ };
+
+ // methods that should be invoked by subclasses
+ that.section_init = that.init;
+ that.section_create = that.create;
+ that.section_setup = that.setup;
+ that.section_load = that.load;
+
+ return that;
+};
+
+
+/**
+ * This class creates a details section formatted as a list of
+ * attributes names and values. The list is defined using <dl> tag.
+ * The attribute name is defined inside a <dt> tag. The attribute
+ * value is defined using a <dd> tag inside a <span> tag. If the
+ * attribute has multiple values the content inside <span> will
+ * be duplicated to display each value.
+ *
+ * Example:
+ * <dl class="entryattrs">
+ *
+ * <dt title="givenname">First Name:</dt>
+ * <span name="givenname">
+ * <dd><input type="text" size="20"/></dd>
+ * </span>
+ *
+ * <dt title="telephonenumber">Telephone Number:</dt>
+ * <span name="telephonenumber">
+ * <dd><input type="text" size="20"/></dd>
+ * <dd><input type="text" size="20"/></dd>
+ * </span>
+ *
+ * </dl>
+ */
+IPA.details_list_section = function (spec){
+
+ spec = spec || {};
+
+ var that = IPA.details_section(spec);
+
+ that.create = function(container) {
+
+ // do not call section_create() here
+
+ if (that.template) return;
+
+ var dl = $('<dl/>', {
+ 'id': that.name,
+ 'class': 'entryattrs'
+ }).appendTo(container);
+
+ var fields = that.fields;
+ for (var i = 0; i < fields.length; ++i) {
+ var field = fields[i];
+
+ var label = field.label;
+
+ // no need to get i18n label from metadata
+ // because it's already done by field.init()
+
+ if (label !== '') {
+ label += ':';
+ }
+
+ $('<dt/>', {
+ html: label
+ }).appendTo(dl);
+
+ var span = $('<span/>', { 'name': field.name }).appendTo(dl);
+ field.create(span);
+ }
+ };
+
+ return that;
+};
+
+
+/* shorthand notation used for declarative definitions of details pages */
+IPA.stanza = function (spec) {
+
+ spec = spec || {};
+
+ var that = IPA.details_list_section(spec);
+
+ // This is to allow declarative style programming for details
+ that.input = function(spec) {
+ that.create_field(spec);
+ return that;
+ };
+
+ that.custom_input = function(input) {
+ that.add_field(input);
+ return that;
+ };
+
+ return that;
+};
+
+
+IPA.details_facet = function (spec) {
+
+ spec = spec || {};
+
+ var that = IPA.facet(spec);
+
+ that.label = ( IPA.messages && IPA.messages.facets && IPA.messages.facets.details) || spec.label;
+ that.is_dirty = spec.is_dirty || is_dirty;
+ that.create = spec.create || create;
+ that.setup = spec.setup || setup;
+ that.load = spec.load || load;
+ that.update = spec.update || IPA.details_update;
+ that.reset = spec.reset || reset;
+ that.refresh = spec.refresh || IPA.details_refresh;
+
+ that.sections = [];
+ that.sections_by_name = {};
+
+ that.__defineGetter__("entity_name", function(){
+ return that._entity_name;
+ });
+
+ that.__defineSetter__("entity_name", function(entity_name){
+ that._entity_name = entity_name;
+
+ for (var i=0; i<that.sections.length; i++) {
+ that.sections[i].entity_name = entity_name;
+ }
+ });
+
+ that.get_section = function(name) {
+ return that.sections_by_name[name];
+ };
+
+ that.add_section = function(section) {
+ section.entity_name = that.entity_name;
+ that.sections.push(section);
+ that.sections_by_name[section.name] = section;
+ return section;
+ };
+
+ that.create_section = function(spec) {
+ var section = IPA.details_section(spec);
+ that.add_section(section);
+ return section;
+ };
+
+ that.init = function() {
+ for (var i=0; i<that.sections.length; i++) {
+ var section = that.sections[i];
+ section.init();
+ }
+ };
+
+ that.get_primary_key = function() {
+ var pkey_name = IPA.metadata[that.entity_name].primary_key;
+ if (that.record[pkey_name] instanceof Array){
+ return that.record[pkey_name][0];
+ }else{
+ return that.record[pkey_name];
+ }
+ };
+
+ that.get_section_header_prefix = function(visible) {
+ if (visible) {
+ return '<span class="ui-icon '+
+ IPA.collapse_icon +
+ ' section-expand" ></span>';
+ } else {
+ return '<span class="ui-icon '+
+ IPA.expand_icon +
+ ' section-expand" />';
+ }
+ };
+
+ function create(container) {
+
+ container.attr('title', that.entity_name);
+
+ $('<h1/>',{
+ html: "<span id='headerpkey' />"+that.entity_name + ' Settings'
+ }).append(IPA.create_network_spinner()).
+ appendTo(container);
+
+ var details = $('<div/>', {
+ 'class': 'content'
+ }).appendTo(container);
+
+ var action_panel = that.get_action_panel();
+
+ var ul = $('ul', action_panel);
+ var buttons = $('.action-controls',action_panel);
+
+ $('<input/>', {
+ 'type': 'text',
+ 'name': 'reset'
+ }).appendTo(buttons);
+
+ $('<input/>', {
+ 'type': 'text',
+ 'name': 'update'
+ }).appendTo(buttons);
+
+
+ for (var i = 0; i < that.sections.length; ++i) {
+ var section = that.sections[i];
+
+ $('<h2/>', {
+ name: section.name,
+ title: section.label,
+ html: that.get_section_header_prefix(true) + ' ' + section.label
+ }).appendTo(details);
+
+ var div = $('<div/>', {
+ 'id': that.entity_name+'-'+that.name+'-'+section.name,
+ 'class': 'details-section'
+ }).appendTo(details);
+
+ section.create(div);
+
+ details.append('<hr/>');
+ }
+ }
+
+ function setup(container) {
+
+ that.facet_setup(container);
+
+ var button = $('input[name=reset]', that.container);
+ that.reset_button = IPA.action_button({
+ 'label': 'Reset',
+ 'icon': 'ui-icon-refresh',
+ 'class': 'details-reset',
+ 'click': function() {
+ that.reset();
+ return false;
+ }
+ });
+ button.replaceWith(that.reset_button);
+
+ button = $('input[name=update]', that.container);
+ that.update_button = IPA.action_button({
+ 'label': 'Update',
+ 'icon': 'ui-icon-check',
+ 'class': 'details-update',
+ 'click': function() {
+ that.update();
+ return false;
+ }
+ });
+ button.replaceWith(that.update_button);
+
+ for (var i = 0; i < that.sections.length; ++i) {
+ var section = that.sections[i];
+
+ var header = $('h2[name='+section.name+']', that.container);
+
+ var div = $('#'+that.entity_name+'-'+that.name+'-'+section.name,
+ that.container);
+
+ header.click(function(section, header, div) {
+ return function() {
+ var visible = div.is(":visible");
+ header.html(that.get_section_header_prefix(!visible) + ' ' + section.label);
+ div.slideToggle();
+ };
+ }(section, header, div));
+
+ section.setup(div);
+ }
+ }
+
+ function is_dirty() {
+ var pkey = $.bbq.getState(that.entity_name + '-pkey', true) || '';
+ return pkey != that.pkey;
+ }
+
+ function load(record) {
+ that.record = record;
+ for (var i=0; i<that.sections.length; i++) {
+ var section = that.sections[i];
+ section.load(record);
+ }
+ if (that.pkey){
+ $('h1 #headerpkey',that.container).html(that.pkey+": ");
+ }
+ }
+
+ function reset() {
+
+ for (var i=0; i<that.sections.length; i++) {
+ var section = that.sections[i];
+ section.reset();
+ }
+ }
+
+ that.details_facet_init = that.init;
+ that.details_facet_create = that.create;
+ that.details_facet_load = that.load;
+
+ return that;
+};
+
+IPA.action_button = function(spec) {
+ var button = IPA.button(spec);
+ button.removeClass("ui-state-default").addClass("action-button");
+ return button;
+};
+
+IPA.button = function(spec) {
+
+ spec = spec || {};
+
+ var button = $('<a/>', {
+ id: spec.id,
+ html: spec.label,
+ title: spec.title || spec.label,
+ 'class': 'ui-state-default ui-corner-all'
+ });
+
+ if (spec.click) button.click(spec.click);
+ if (spec['class']) button.addClass(spec['class']);
+
+ if (spec.icon) {
+ button.addClass('input_link');
+ button.append('<span class="ui-icon '+spec.icon+'" ></span> ');
+ } else {
+ button.addClass('button-without-icon');
+ }
+
+ return button;
+};
+
+IPA.details_refresh = function () {
+
+ var that = this;
+
+ that.pkey = $.bbq.getState(that.entity_name + '-pkey', true) || '';
+
+ function on_success(data, text_status, xhr) {
+ that.load(data.result.result);
+ }
+
+ function on_failure(xhr, text_status, error_thrown) {
+ var details = $('.details', that.container).empty();
+ details.append('<p>Error: '+error_thrown.name+'</p>');
+ details.append('<p>'+error_thrown.title+'</p>');
+ details.append('<p>'+error_thrown.message+'</p>');
+ }
+
+ var params = [];
+ if (that.pkey) params.push(that.pkey);
+
+ IPA.cmd( 'show', params, {all: true, rights: true}, on_success, on_failure,
+ that.entity_name );
+};
+
+IPA.details_update = function (on_win, on_fail)
+{
+ var that = this;
+ var entity_name = that.entity_name;
+
+ function update_on_win(data, text_status, xhr) {
+ if (on_win)
+ on_win(data, text_status, xhr);
+ if (data.error)
+ return;
+
+ var result = data.result.result;
+ that.load(result);
+ }
+
+ function update_on_fail(xhr, text_status, error_thrown) {
+ if (on_fail)
+ on_fail(xhr, text_status, error_thrown);
+ }
+
+ var values;
+ var modlist = {'all': true, 'setattr': [], 'addattr': [], 'rights': true};
+ var attrs_wo_option = {};
+
+ for (var i=0; i<that.sections.length; i++) {
+ var section = that.sections[i];
+
+ if (section.save){
+ section.save(modlist);
+ continue;
+ }
+
+ var div = $('#'+that.entity_name+'-'+that.name+'-'+section.name, that.container);
+
+ for (var j=0; j<section.fields.length; j++) {
+ var field = section.fields[j];
+
+ var span = $('span[name='+field.name+']', div).first();
+ values = field.save();
+ if (!values) continue;
+
+ var param_info = IPA.get_param_info(entity_name, field.name);
+ if (param_info) {
+ if (param_info['primary_key']) continue;
+ if (values.length === 1) {
+ modlist[field.name] = values[0];
+ }else if (values.length > 1){
+ modlist[field.name] = values;
+ } else if (param_info['multivalue']){
+ modlist[field.name] = [];
+ }
+ } else {
+ if (values.length) attrs_wo_option[field.name] = values;
+ }
+ }
+ }
+
+ for (var attr in attrs_wo_option) {
+ values = attrs_wo_option[attr];
+ modlist['setattr'].push(attr + '=' + values[0]);
+ for (var k = 1; k < values.length; ++k){
+ modlist['addattr'].push(attr + '=' + values[k]);
+ }
+ }
+
+ var pkey = that.get_primary_key() ;
+ if (pkey){
+ pkey = [pkey];
+ }else{
+ pkey = [];
+ }
+
+ IPA.cmd('mod', pkey, modlist, update_on_win, null, entity_name);
+};
+
+
+IPA.create_first_dd = function (field_name, content){
+ var dd = $('<dd/>', {
+ 'class': 'first',
+ 'title': field_name
+ });
+ if (content) dd.append(content);
+ return dd;
+};
+
+IPA.create_other_dd = function (field_name, content){
+ return $('<dd/>', {
+ 'class': 'other',
+ 'title': field_name
+ }).append(content);
+};
+
+
+/* creates a Remove link for deleting attribute values */
+function _ipa_create_remove_link(attr, param_info)
+{
+ if (param_info){
+ /* check if the param is required or of the Password type
+ * if it is, then we don't want people to be able to remove it */
+ if ((param_info['required']) || (param_info['class'] == 'Password')){
+ return ('');
+ }
+ }
+ return $('<a/>',{
+ href:"jslink",
+ click: function (){return (_ipa_remove_on_click(this));},
+ title: attr,
+ text: 'Remove'});
+
+}
+
+IPA.details_field_create_add_link = function (title, rights, index) {
+
+ var that = this;
+
+ var link = $('<a/>', {
+ 'href': 'jslink',
+ 'title': title,
+ 'html': 'Add',
+ 'click': function () {
+
+ var param_info = IPA.get_param_info(that.entity_name, '');
+ var input = that.create_input('', param_info, rights, index);
+
+ link.replaceWith(input);
+ input.focus();
+
+ var dd = IPA.create_other_dd(that.name);
+ dd.append(IPA.details_field_create_add_link.call(that, that.name, rights, index+1));
+ dd.appendTo(that.container);
+
+ return false;
+ }
+ });
+
+ return link;
+};
+
+
+function _ipa_remove_on_click(obj)
+{
+ var jobj = $(obj);
+ var attr = jobj.attr('title');
+ var par = jobj.parent();
+
+ var input = par.find('input');
+
+ if (input.is('.strikethrough')){
+ input.removeClass('strikethrough');
+ jobj.text("Remove");
+ }else{
+ input.addClass('strikethrough');
+ jobj.text("Undo");
+ }
+ return (false);
+}
diff --git a/install/ui/develop.js b/install/ui/develop.js
new file mode 100644
index 000000000..462253500
--- /dev/null
+++ b/install/ui/develop.js
@@ -0,0 +1,6 @@
+/*jsl:import ipa.js */
+
+if (window.location.protocol == 'file:') {
+ IPA.json_url = "test/data";
+ IPA.use_static_files = true;
+}
diff --git a/install/ui/entity.js b/install/ui/entity.js
new file mode 100644
index 000000000..9c58ee3db
--- /dev/null
+++ b/install/ui/entity.js
@@ -0,0 +1,592 @@
+/*jsl:import ipa.js */
+/*jsl:import navigation.js */
+
+/* Authors:
+ * Pavel Zuna <pzuna@redhat.com>
+ * Endi S. Dewata <edewata@redhat.com>
+ * Adam Young <ayoung@redhat.com>
+ *
+ * Copyright (C) 2010 Red Hat
+ * see file 'COPYING' for use and warranty information
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* REQUIRES: ipa.js, details.js, search.js, add.js */
+
+IPA.facet = function (spec) {
+
+ spec = spec || {};
+
+ var that = {};
+ that.display_class = spec.display_class || 'entity-facet';
+ that.name = spec.name;
+ that.label = spec.label;
+ that._entity_name = spec.entity_name;
+
+ that.init = spec.init || init;
+ that.create = spec.create || create;
+ that.setup = spec.setup || setup;
+ that.load = spec.load || load;
+
+ that.__defineGetter__("entity_name", function(){
+ return that._entity_name;
+ });
+
+ that.__defineSetter__("entity_name", function(entity_name){
+ that._entity_name = entity_name;
+ });
+
+ that.create_action_panel = IPA.facet_create_action_panel;
+
+ function init() {
+ }
+
+ function create(container) {
+ }
+
+ function setup(container) {
+ that.container = container;
+ }
+
+ function load() {
+ }
+
+ that.get_client_area = function() {
+ return $('.client', that.container);
+ };
+
+ that.get_action_panel = function() {
+ return $('.action-panel', that.container);
+ };
+
+ that.facet_init = that.init;
+ that.facet_create = that.create;
+ that.facet_setup = that.setup;
+
+ return that;
+};
+
+
+IPA.entity = function (spec) {
+
+ spec = spec || {};
+
+ var that = {};
+ that.name = spec.name;
+ that.label = spec.label;
+
+ that.setup = spec.setup || IPA.entity_setup;
+
+ that.dialogs = [];
+ that.dialogs_by_name = {};
+
+ that.facets = [];
+ that.facets_by_name = {};
+
+ that.facet_name = null;
+
+ that.autogenerate_associations = false;
+
+ that.associations = [];
+ that.associations_by_name = {};
+
+ that.get_dialog = function(name) {
+ return that.dialogs_by_name[name];
+ };
+
+ that.add_dialog = function(dialog) {
+ dialog.entity_name = that.name;
+ that.dialogs.push(dialog);
+ that.dialogs_by_name[dialog.name] = dialog;
+ };
+
+ that.get_facet = function(name) {
+ return that.facets_by_name[name];
+ };
+
+ that.add_facet = function(facet) {
+ facet.entity_name = that.name;
+ that.facets.push(facet);
+ that.facets_by_name[facet.name] = facet;
+ };
+
+ that.get_associations = function() {
+ return that.associations;
+ };
+
+ that.get_association = function(name) {
+ return that.associations_by_name[name];
+ };
+
+ that.add_association = function(config) {
+ that.associations.push(config);
+ that.associations_by_name[config.name] = config;
+ };
+
+ that.create_association = function(spec) {
+ var config = IPA.association_config(spec);
+ that.add_association(config);
+ return config;
+ };
+
+ that.create_association_facet = function(attribute_member, other_entity, label, facet_group) {
+
+ if (!attribute_member) {
+ attribute_member = IPA.get_member_attribute(
+ that.entity_name, other_entity);
+ }
+
+ return IPA.association_facet({
+ 'name': attribute_member+'_'+other_entity,
+ 'label': label,
+ 'other_entity': other_entity,
+ 'facet_group': facet_group,
+ 'attribute_member': attribute_member
+ });
+ };
+
+ that.create_association_facets = function() {
+
+ var attribute_members = IPA.metadata[that.name].attribute_members;
+
+ for (var attribute_member in attribute_members) {
+
+ // skip non-assignable associations
+ if (attribute_member === 'memberindirect') continue;
+ if (attribute_member === 'enrolledby') continue;
+
+ var other_entities = attribute_members[attribute_member];
+
+ for (var j = 0; j < other_entities.length; j++) {
+ var other_entity = other_entities[j];
+ var other_entity_name = IPA.metadata[other_entity].label;
+
+ var label = other_entity_name;
+
+ var relationships = IPA.metadata[that.name].relationships;
+
+ var relationship = relationships[attribute_member];
+ if (!relationship)
+ relationship = ['Member', '', 'no_'];
+ var facet_group = relationship[0];
+
+ var facet = that.create_association_facet(
+ attribute_member, other_entity, label, facet_group);
+
+ if (that.get_facet(facet.name)) continue;
+
+ that.add_facet(facet);
+ }
+ }
+ };
+
+ that.init = function() {
+
+ if (!that.label) {
+ that.label = IPA.metadata[that.name].label;
+ }
+
+ if (that.autogenerate_associations) {
+ that.create_association_facets();
+ }
+
+ for (var i=0; i<that.facets.length; i++) {
+ var facet = that.facets[i];
+ facet.init();
+ }
+ };
+
+ that.entity_init = that.init;
+
+ return that;
+};
+
+
+/* use this to track individual changes between two hashchange events */
+var window_hash_cache = {};
+
+/*renamed to avoid clash with IPA.get_entity*/
+IPA.fetch_entity = function (entity_name) {
+
+ var entity = IPA.get_entity(entity_name);
+ if (entity) return entity;
+
+ entity = IPA.entity({
+ 'name': entity_name
+ });
+
+ IPA.add_entity(entity);
+ return entity;
+};
+
+
+IPA.entity_get_search_facet = function (entity_name) {
+
+ var entity = IPA.fetch_entity(entity_name);
+
+ var facet = entity.get_facet('search');
+ if (facet) return facet;
+
+ facet = IPA.search_facet({
+ 'name': 'search',
+ 'label': 'Search'
+ });
+ entity.add_facet(facet);
+
+ return facet;
+};
+
+
+IPA.entity_set_search_definition = function (entity_name, data) {
+
+ var facet = IPA.entity_get_search_facet(entity_name);
+
+ for (var i=0; i<data.length; i++) {
+ var defn = data[i];
+ facet.create_column({
+ 'name': defn[0],
+ 'label': defn[1],
+ 'setup': defn[2]
+ });
+ }
+};
+
+
+IPA.entity_set_add_definition = function (entity_name, data) {
+
+ var entity = IPA.fetch_entity(entity_name);
+
+ var dialog = IPA.add_dialog({
+ 'name': 'add',
+ 'title': data[1]
+ });
+ entity.add_dialog(dialog);
+
+ for (var i=0; i<data[2].length; i++) {
+ var field = data[2][i];
+ dialog.add_field(IPA.text_widget({
+ name: field[0],
+ label: field[1],
+ setup: field[2],
+ undo: false
+ }));
+ }
+
+ dialog.init();
+};
+
+
+IPA.entity_get_add_dialog = function (entity_name) {
+
+ var entity = IPA.fetch_entity(entity_name);
+ return entity.get_add_dialog();
+};
+
+
+IPA.entity_get_details_facet = function (entity_name) {
+
+ var entity = IPA.fetch_entity(entity_name);
+
+ var facet = entity.get_facet('details');
+ if (facet) return facet;
+
+ facet = IPA.details_facet({
+ 'name': 'details'
+ });
+ entity.add_facet(facet);
+
+ return facet;
+};
+
+
+IPA.entity_set_details_definition = function (entity_name, sections) {
+
+ var facet = IPA.entity_get_details_facet(entity_name);
+
+ for (var i=0; i<sections.length; i++) {
+ var section = sections[i];
+ facet.add_section(section);
+ }
+};
+
+
+IPA.entity_set_association_definition = function (entity_name, data) {
+
+ var entity = IPA.fetch_entity(entity_name);
+
+ entity.autogenerate_associations = true;
+
+ for (var other_entity in data) {
+ var config = data[other_entity];
+ entity.create_association({
+ 'name': other_entity,
+ 'associator': config.associator,
+ 'add_method': config.add_method,
+ 'remove_method': config.remove_method
+ });
+ }
+};
+
+
+IPA.entity_set_facet_definition = function (entity_name, list) {
+
+ var entity = IPA.fetch_entity(entity_name);
+
+ for (var i=0; i<list.length; i++) {
+ var facet = list[i];
+ entity.add_facet(facet);
+ }
+};
+
+
+IPA.current_facet = function (entity){
+ var facet_name = $.bbq.getState(entity.name + '-facet', true);
+ if (!facet_name && entity.facets.length) {
+ facet_name = entity.facets[0].name;
+ }
+ return facet_name;
+};
+
+
+IPA.entity_setup = function (container) {
+
+ var entity = this;
+
+ var facet_name = IPA.current_facet(entity);
+
+
+ var facet = entity.get_facet(facet_name);
+ if (!facet) return;
+
+ if (IPA.entity_name == entity.name) {
+ if (entity.facet_name == facet_name) {
+ if (!facet.is_dirty()) return;
+
+ } else {
+ entity.facet_name = facet_name;
+ }
+ } else {
+ IPA.entity_name = entity.name;
+ }
+
+ container.empty();
+
+ facet.create_action_panel(container);
+ facet.create(container);
+ container.children().last().addClass('client');
+ facet.setup(container);
+ facet.refresh();
+};
+
+
+/*Returns the entity requested, as well as:
+ any nested tabs underneath it or
+ its parent tab and the others nested at the same level*/
+
+IPA.nested_tabs = function(entity_name){
+
+ var siblings = [];
+ var nested_index;
+ var nested_entities;
+
+ if (!IPA.tab_set) {
+ siblings.push(entity_name);
+ return siblings;
+ }
+
+ for (var top_tab_index = 0;
+ top_tab_index < IPA.tab_set.length;
+ top_tab_index += 1){
+ var top_tab = IPA.tab_set[top_tab_index];
+ for (var subtab_index = 0;
+ subtab_index < top_tab.children.length;
+ subtab_index += 1){
+ if(top_tab.children[subtab_index].name){
+ if (top_tab.children[subtab_index].name === entity_name){
+ siblings.push(entity_name);
+ if (top_tab.children[subtab_index].children){
+ nested_entities = top_tab.children[subtab_index].children;
+ for ( nested_index = 0;
+ nested_index < nested_entities.length;
+ nested_index += 1){
+ siblings.push (nested_entities[nested_index].name);
+ }
+ }
+ }else{
+ if (top_tab.children[subtab_index].children){
+ nested_entities = top_tab.children[subtab_index].children;
+ for (nested_index = 0;
+ nested_index < nested_entities.length;
+ nested_index += 1){
+ if (nested_entities[nested_index].name === entity_name){
+ siblings.push(top_tab.children[subtab_index].name);
+ for (var nested_index2 = 0;
+ nested_index2 < nested_entities.length;
+ nested_index2 += 1){
+ siblings.push(nested_entities[nested_index2].name);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return siblings;
+};
+
+IPA.selected_icon = '&#x25B6; ';
+IPA.back_icon = '&#x25C0; ';
+
+IPA. facet_create_action_panel = function(container) {
+
+ var that = this;
+ var entity_name = that.entity_name;
+ var action_panel = $('<div/>', {
+ "class": "action-panel",
+ html: $('<h3>',{
+ text: IPA.metadata[entity_name].label
+ })
+ }).appendTo(container);
+ function build_link(other_facet,label){
+ var li = $('<li/>', {
+ "class" : other_facet.display_class,
+ title: other_facet.name,
+ text: label,
+ click: function(entity_name, other_facet_name) {
+ return function() {
+ if($(this).hasClass('entity-facet-disabled')){
+ return false;
+ }
+ var this_pkey = $('input[id=pkey]', action_panel).val();
+ IPA.switch_and_show_page(
+ entity_name, other_facet_name,
+ this_pkey);
+ return false;
+ };
+ }(entity_name, other_facet_name)
+ });
+ return li;
+ }
+ /*Note, for debugging purposes, it is useful to set var pkey_type = 'text';*/
+ var pkey_type = 'hidden';
+ $('<input/>', {
+ 'type': pkey_type,
+ id:'pkey',
+ name:'pkey'
+ }).appendTo(action_panel);
+ var ul = $('<ul/>', {'class': 'action'}).appendTo(action_panel);
+ var entity = IPA.get_entity(entity_name);
+ var facet_name = IPA.current_facet(entity);
+ var other_facet = entity.facets[0];
+ var other_facet_name = other_facet.name;
+ var nested_tabs = IPA.nested_tabs(entity_name);
+ var main_facet = build_link(other_facet,other_facet.label);
+ for (var nested_index = 0 ;
+ nested_index < nested_tabs.length;
+ nested_index += 1){
+ if (nested_tabs[nested_index] === entity_name){
+ /*assume for now that entities with only a single facet
+ do not have search*/
+ if (entity.facets.length > 0 ){
+ if ( entity.facets[0].name === IPA.current_facet( entity)){
+ ul.append($('<li><span class="action-controls"/></li>'));
+
+ }else{
+ main_facet.html(
+ $('<span />',{
+ "class":"input_link"
+ }).
+ append(IPA.back_icon + ' Back to List '));
+ main_facet.addClass('back-to-search');
+ main_facet.appendTo(ul);
+ }
+ ul.append($('<li><hr/></li>'));
+
+ }
+ var facet_groups = {};
+ var li;
+ for (var i=1; i<entity.facets.length; i++) {
+ other_facet = entity.facets[i];
+ other_facet_name = other_facet.name;
+
+ if (other_facet.facet_group) {
+ var facet_group = other_facet.facet_group;
+ if (!facet_groups[facet_group]) {
+ li = $('<li/>', {
+ 'class': 'entity-facet entity-facet-relation-label',
+ 'text': other_facet.facet_group,
+ 'title': other_facet.facet_group
+ });
+ ul.append(li);
+ facet_groups[facet_group] = li;
+ }
+ li = facet_groups[facet_group];
+ var link = build_link(other_facet, other_facet.label);
+ link.addClass('facet-group-member');
+ li.after(link );
+ /*
+ If we are on the current facet, we make the text black, non-clickable,
+ add an icon and make sure the action controls are positioned underneath it.
+ */
+ if ( other_facet.name === IPA.current_facet( entity)){
+ var text = link.text();
+ link.text('');
+ link.append($('<ul>').
+ append($('<li />',{
+ 'class': 'entity-facet-selected',
+ html: IPA.selected_icon + text
+ })).
+ append($('<li/>',{
+ html:$('<span />',{
+ 'class':"action-controls"
+ })
+ })));
+ }
+ facet_groups[facet_group] = li.next();
+ } else {
+ var innerlist = $('<ul/>').appendTo(ul);
+ var facet_link = build_link(other_facet, other_facet.label);
+ facet_link.addClass('entity-facet-selected');
+ facet_link.prepend(IPA.selected_icon);
+ innerlist.append(facet_link);
+ if ( other_facet.name === IPA.current_facet( entity)){
+
+ innerlist.append($('<li class="entity-facet"><span class="action-controls" /></li>'));
+ }
+ }
+ }
+ }else{
+ $('<li/>', {
+ title: nested_tabs[nested_index],
+ text: IPA.metadata[nested_tabs[nested_index]].label,
+ "class": "search-facet",
+ click: function() {
+ var state = {};
+ state[nested_tabs[0]+'-entity'] =
+ this.title;
+ nav_push_state(state);
+ return false;
+ }
+ }).appendTo(ul);
+ }
+ }
+ /*When we land on the search page, disable all facets
+ that require a pkey until one is selected*/
+ if (facet_name === 'search'){
+ $('.entity-facet', action_panel).addClass('entity-facet-disabled');
+ }
+ return action_panel;
+};
diff --git a/install/ui/gray-fade-line.png b/install/ui/gray-fade-line.png
new file mode 100644
index 000000000..896cfca0e
--- /dev/null
+++ b/install/ui/gray-fade-line.png
Binary files differ
diff --git a/install/ui/group.js b/install/ui/group.js
new file mode 100644
index 000000000..13017ac5a
--- /dev/null
+++ b/install/ui/group.js
@@ -0,0 +1,201 @@
+/*jsl:import ipa.js */
+
+/* Authors:
+ * Pavel Zuna <pzuna@redhat.com>
+ *
+ * Copyright (C) 2010 Red Hat
+ * see file 'COPYING' for use and warranty information
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* REQUIRES: ipa.js, details.js, search.js, add.js, entity.js */
+
+IPA.group = function () {
+
+ var that = IPA.entity({
+ 'name': 'group'
+ });
+
+ that.init = function() {
+
+ that.create_association({
+ name: 'netgroup',
+ associator: 'serial'
+ });
+
+ that.create_association({
+ name: 'rolegroup',
+ associator: 'serial'
+ });
+
+ that.create_association({
+ name: 'taskgroup',
+ associator: 'serial'
+ });
+
+ var dialog = IPA.group_add_dialog({
+ 'name': 'add',
+ 'title': 'Add New Group'
+ });
+ that.add_dialog(dialog);
+ dialog.init();
+
+ var facet = IPA.group_search_facet({
+ 'name': 'search',
+ 'label': 'Search'
+ });
+ that.add_facet(facet);
+
+ facet = IPA.group_details_facet({
+ 'name': 'details'
+ });
+ that.add_facet(facet);
+
+ that.create_association_facets();
+
+ that.entity_init();
+ };
+
+ return that;
+};
+
+
+IPA.add_entity(IPA.group());
+
+
+IPA.group_add_dialog = function (spec) {
+
+ spec = spec || {};
+
+ var that = IPA.add_dialog(spec);
+
+ that.init = function() {
+
+ that.add_field(IPA.text_widget({name:'cn', undo: false}));
+ that.add_field(IPA.text_widget({name:'description', undo: false}));
+ // TODO: Replace with i18n label
+ that.add_field(IPA.checkbox_widget({
+ name:'posix',
+ label:'Is this a POSIX group?',
+ undo: false,
+ checked:'checked'}));
+ that.add_field(IPA.text_widget({name:'gidnumber', undo: false}));
+
+ that.add_dialog_init();
+ };
+
+ return that;
+};
+
+
+IPA.group_search_facet = function (spec) {
+
+ spec = spec || {};
+
+ var that = IPA.search_facet(spec);
+
+ that.init = function() {
+ that.create_column({name:'cn'});
+ that.create_column({name:'gidnumber'});
+ that.create_column({name:'description'});
+ that.search_facet_init();
+ };
+
+ return that;
+};
+
+
+IPA.group_details_facet = function (spec) {
+
+ spec = spec || {};
+
+ var that = IPA.details_facet(spec);
+
+ that.init = function() {
+
+ var section = IPA.details_list_section({
+ name: 'details',
+ label: 'Group Settings'
+ });
+ that.add_section(section);
+
+ section.create_field({name: 'cn' });
+ section.create_field({name: 'description'});
+ section.create_field({name: 'gidnumber' });
+
+ that.details_facet_init();
+ };
+
+ return that;
+};
+
+
+IPA.group_member_user_facet = function (spec) {
+
+ spec = spec || {};
+
+ var that = IPA.association_facet(spec);
+
+ that.init = function() {
+
+ that.create_column({name: 'cn'});
+
+ var column = that.create_column({
+ name: 'uid',
+ primary_key: true
+ });
+
+ column.setup = function(container, record) {
+ container.empty();
+
+ var value = record[column.name];
+ value = value ? value.toString() : '';
+
+ $('<a/>', {
+ 'href': '#'+value,
+ 'html': value,
+ 'click': function (value) {
+ return function() {
+ var state = IPA.tab_state(that.other_entity);
+ state[that.other_entity + '-facet'] = 'details';
+ state[that.other_entity + '-pkey'] = value;
+ $.bbq.pushState(state);
+ return false;
+ };
+ }(value)
+ }).appendTo(container);
+ };
+
+ that.create_column({name: 'uidnumber'});
+ that.create_column({name: 'mail'});
+ that.create_column({name: 'telephonenumber'});
+ that.create_column({name: 'title'});
+
+ that.create_adder_column({
+ name: 'cn',
+ width: '100px'
+ });
+
+ that.create_adder_column({
+ name: 'uid',
+ primary_key: true,
+ width: '100px'
+ });
+
+ that.association_facet_init();
+ };
+
+ return that;
+};
diff --git a/install/ui/hbacrule.js b/install/ui/hbacrule.js
new file mode 100644
index 000000000..455ad4d38
--- /dev/null
+++ b/install/ui/hbacrule.js
@@ -0,0 +1,989 @@
+/*jsl:import ipa.js */
+
+/* Authors:
+ * Endi Sukma Dewata <edewata@redhat.com>
+ *
+ * Copyright (C) 2010 Red Hat
+ * see file 'COPYING' for use and warranty information
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* REQUIRES: ipa.js, details.js, search.js, add.js, entity.js */
+
+IPA.hbacrule = function () {
+
+ var that = IPA.entity({
+ 'name': 'hbacrule'
+ });
+
+ that.init = function() {
+
+ var dialog = IPA.hbacrule_add_dialog({
+ 'name': 'add',
+ 'title': 'Add New Rule'
+ });
+ that.add_dialog(dialog);
+ dialog.init();
+
+ var facet = IPA.hbacrule_search_facet({
+ 'name': 'search',
+ 'label': 'Search'
+ });
+ that.add_facet(facet);
+
+ facet = IPA.hbacrule_details_facet({
+ 'name': 'details'
+ });
+ that.add_facet(facet);
+
+ that.entity_init();
+ };
+
+ return that;
+};
+
+
+IPA.add_entity(IPA.hbacrule());
+
+
+IPA.hbacrule_add_dialog = function (spec) {
+
+ spec = spec || {};
+
+ var that = IPA.add_dialog(spec);
+
+ that.init = function() {
+
+ that.add_field(IPA.text_widget({
+ 'name': 'cn',
+ 'undo': false
+ }));
+
+ that.add_field(IPA.radio_widget({
+ 'name': 'accessruletype',
+ 'options': [
+ { 'value': 'allow', 'label': 'Allow' },
+ { 'value': 'deny', 'label': 'Deny' }
+ ],
+ 'undo': false
+ }));
+
+ that.add_dialog_init();
+ };
+
+ return that;
+};
+
+
+IPA.hbacrule_search_facet = function (spec) {
+
+ spec = spec || {};
+
+ var that = IPA.search_facet(spec);
+
+ that.init = function() {
+
+ that.create_column({name:'cn'});
+ that.create_column({name:'usercategory'});
+ that.create_column({name:'hostcategory'});
+ that.create_column({name:'ipaenabledflag'});
+ that.create_column({name:'servicecategory'});
+ that.create_column({name:'sourcehostcategory'});
+
+ that.search_facet_init();
+ };
+
+ that.create = function(container) {
+
+/*
+ // Not yet implemented
+
+ var left_buttons = $('<span/>', {
+ 'style': 'float: left;'
+ }).appendTo(container);
+
+ left_buttons.append(IPA.button({
+ 'label': 'Troubleshoot Rules'
+ }));
+
+ left_buttons.append(IPA.button({
+ 'label': 'Cull Disabled Rules'
+ }));
+*/
+
+ that.search_facet_create(container);
+
+ };
+
+ return that;
+};
+
+
+IPA.hbacrule_details_facet = function (spec) {
+
+ spec = spec || {};
+
+ var that = IPA.details_facet(spec);
+
+ that.init = function() {
+
+ var section;
+
+ if (IPA.layout) {
+ section = that.create_section({
+ 'name': 'general',
+ 'label': 'General',
+ 'template': 'hbacrule-details-general.html #contents'
+ });
+
+ } else {
+ section = IPA.hbacrule_details_general_section({
+ 'name': 'general',
+ 'label': 'General'
+ });
+ that.add_section(section);
+ }
+
+ section.create_text({ 'name': 'cn', 'label': 'Name', 'read_only': true });
+ section.create_radio({ 'name': 'accessruletype', 'label': 'Rule Type' });
+ section.create_textarea({ 'name': 'description', 'label': 'Description' });
+ section.create_radio({ 'name': 'ipaenabledflag', 'label': 'Enabled' });
+
+ if (IPA.layout) {
+ section = that.create_section({
+ 'name': 'user',
+ 'label': 'Who',
+ 'template': 'hbacrule-details-user.html #contents'
+ });
+
+ } else {
+ section = IPA.rule_details_section({
+ 'name': 'user',
+ 'label': 'Who',
+ 'text': 'Rule applies when access is requested by:',
+ 'field_name': 'usercategory',
+ 'options': [
+ { 'value': 'all', 'label': 'Anyone' },
+ { 'value': '', 'label': 'Specified Users and Groups' }
+ ],
+ 'tables': [
+ { 'field_name': 'memberuser_user' },
+ { 'field_name': 'memberuser_group' }
+ ]
+ });
+ that.add_section(section);
+ }
+
+ var category = section.create_radio({ name: 'usercategory', label: 'User category' });
+ section.add_field(IPA.rule_association_table_widget({
+ 'id': that.entity_name+'-memberuser_user',
+ 'name': 'memberuser_user', 'label': 'Users', 'category': category,
+ 'other_entity': 'user', 'add_method': 'add_user', 'remove_method': 'remove_user'
+ }));
+ section.add_field(IPA.rule_association_table_widget({
+ 'id': that.entity_name+'-memberuser_group',
+ 'name': 'memberuser_group', 'label': 'Groups', 'category': category,
+ 'other_entity': 'group', 'add_method': 'add_user', 'remove_method': 'remove_user'
+ }));
+
+ if (IPA.layout) {
+ section = that.create_section({
+ 'name': 'host',
+ 'label': 'Accessing',
+ 'template': 'hbacrule-details-host.html #contents'
+ });
+
+ } else {
+ section = IPA.rule_details_section({
+ 'name': 'host',
+ 'label': 'Accessing',
+ 'text': 'Rule applies when access is requested to:',
+ 'field_name': 'hostcategory',
+ 'options': [
+ { 'value': 'all', 'label': 'Any Host' },
+ { 'value': '', 'label': 'Specified Hosts and Groups' }
+ ],
+ 'tables': [
+ { 'field_name': 'memberhost_host' },
+ { 'field_name': 'memberhost_hostgroup' }
+ ]
+ });
+ that.add_section(section);
+ }
+
+ category = section.create_radio({ 'name': 'hostcategory', 'label': 'Host category' });
+ section.add_field(IPA.rule_association_table_widget({
+ 'id': that.entity_name+'-memberhost_host',
+ 'name': 'memberhost_host', 'label': 'Hosts', 'category': category,
+ 'other_entity': 'host', 'add_method': 'add_host', 'remove_method': 'remove_host'
+ }));
+ section.add_field(IPA.rule_association_table_widget({
+ 'id': that.entity_name+'-memberhost_hostgroup',
+ 'name': 'memberhost_hostgroup', 'label': 'Host Groups', 'category': category,
+ 'other_entity': 'hostgroup', 'add_method': 'add_host', 'remove_method': 'remove_host'
+ }));
+
+ if (IPA.layout) {
+ section = that.create_section({
+ 'name': 'service',
+ 'label': 'Via Service',
+ 'template': 'hbacrule-details-service.html #contents'
+ });
+
+ } else {
+ section = IPA.rule_details_section({
+ 'name': 'service',
+ 'label': 'Via Service',
+ 'text': 'Rule applies when access is requested via:',
+ 'field_name': 'servicecategory',
+ 'options': [
+ { 'value': 'all', 'label': 'Any Service' },
+ { 'value': '', 'label': 'Specified Services and Groups' }
+ ],
+ 'tables': [
+ { 'field_name': 'memberservice_hbacsvc' },
+ { 'field_name': 'memberservice_hbacsvcgroup' }
+ ]
+ });
+ that.add_section(section);
+ }
+
+ category = section.create_radio({ 'name': 'servicecategory', 'label': 'Service category' });
+ section.add_field(IPA.rule_association_table_widget({
+ 'id': that.entity_name+'-memberservice_hbacsvc',
+ 'name': 'memberservice_hbacsvc', 'label': 'Services', 'category': category,
+ 'other_entity': 'hbacsvc', 'add_method': 'add_service', 'remove_method': 'remove_service'
+ }));
+ section.add_field(IPA.rule_association_table_widget({
+ 'id': that.entity_name+'-memberservice_hbacsvcgroup',
+ 'name': 'memberservice_hbacsvcgroup', 'label': 'Service Groups', 'category': category,
+ 'other_entity': 'hbacsvcgroup', 'add_method': 'add_service', 'remove_method': 'remove_service'
+ }));
+
+ if (IPA.layout) {
+ section = that.create_section({
+ 'name': 'sourcehost',
+ 'label': 'From',
+ 'template': 'hbacrule-details-sourcehost.html #contents'
+ });
+
+ } else {
+ section = IPA.rule_details_section({
+ 'name': 'sourcehost',
+ 'label': 'From',
+ 'text': 'Rule applies when access is being initiated from:',
+ 'field_name': 'sourcehostcategory',
+ 'options': [
+ { 'value': 'all', 'label': 'Any Host' },
+ { 'value': '', 'label': 'Specified Hosts and Groups' }
+ ],
+ 'tables': [
+ { 'field_name': 'sourcehost_host' },
+ { 'field_name': 'sourcehost_hostgroup' }
+ ]
+ });
+ that.add_section(section);
+ }
+
+ category = section.create_radio({ 'name': 'sourcehostcategory', 'label': 'Source host category' });
+ section.add_field(IPA.rule_association_table_widget({
+ 'id': that.entity_name+'-sourcehost_host',
+ 'name': 'sourcehost_host', 'label': 'Host', 'category': category,
+ 'other_entity': 'host', 'add_method': 'add_sourcehost', 'remove_method': 'remove_sourcehost'
+ }));
+ section.add_field(IPA.rule_association_table_widget({
+ 'id': that.entity_name+'-sourcehost_hostgroup',
+ 'name': 'sourcehost_hostgroup', 'label': 'Host Groups', 'category': category,
+ 'other_entity': 'hostgroup', 'add_method': 'add_sourcehost', 'remove_method': 'remove_sourcehost'
+ }));
+/*
+ if (IPA.layout) {
+ section = that.create_section({
+ 'name': 'accesstime',
+ 'label': 'When',
+ 'template': 'hbacrule-details-accesstime.html #contents'
+ });
+
+ } else {
+ section = that.create_section({
+ 'name': 'accesstime',
+ 'label': 'When'
+ });
+ }
+
+ section.add_field(ipa_hbacrule_accesstime_widget({
+ 'id': 'accesstime',
+ 'name': 'accesstime', 'label': 'Access Time',
+ 'text': 'Rule applies when access is being requested at:',
+ 'options': [
+ { 'value': 'all', 'label': 'Any Time' },
+ { 'value': '', 'label': 'Specified Times' }
+ ]
+ }));
+*/
+ that.details_facet_init();
+ };
+
+ that.update = function() {
+
+ var pkey = $.bbq.getState(that.entity_name + '-pkey', true) || '';
+
+ var modify_operation = {
+ 'execute': false,
+ 'command': IPA.command({
+ 'method': that.entity_name+'_mod',
+ 'args': [pkey],
+ 'options': {'all': true, 'rights': true}
+ })
+ };
+
+ var remove_accesstime = {
+ 'template': IPA.command({
+ 'method': that.entity_name+'_remove_accesstime',
+ 'args': [pkey],
+ 'options': {'all': true, 'rights': true}
+ }),
+ 'commands': []
+ };
+
+ var categories = {
+ 'usercategory': {
+ 'remove_values': false
+ },
+ 'hostcategory': {
+ 'remove_values': false
+ },
+ 'servicecategory': {
+ 'remove_values': false
+ },
+ 'sourcehostcategory': {
+ 'remove_values': false
+ }
+ };
+
+ var member_operations = {
+ 'memberuser': {
+ 'category': 'usercategory',
+ 'has_values': false,
+ 'command': IPA.command({
+ 'method': that.entity_name+'_remove_user',
+ 'args': [pkey],
+ 'options': {'all': true, 'rights': true}
+ })
+ },
+ 'memberhost': {
+ 'category': 'hostcategory',
+ 'has_values': false,
+ 'command': IPA.command({
+ 'method': that.entity_name+'_remove_host',
+ 'args': [pkey],
+ 'options': {'all': true, 'rights': true}
+ })
+ },
+ 'memberservice': {
+ 'category': 'servicecategory',
+ 'has_values': false,
+ 'command': IPA.command({
+ 'method': that.entity_name+'_remove_service',
+ 'args': [pkey],
+ 'options': {'all': true, 'rights': true}
+ })
+ },
+ 'sourcehost': {
+ 'category': 'sourcehostcategory',
+ 'has_values': false,
+ 'command': IPA.command({
+ 'method': that.entity_name+'_remove_sourcehost',
+ 'args': [pkey],
+ 'options': {'all': true, 'rights': true}
+ })
+ }
+ };
+
+ var enable_operation = {
+ 'execute': false,
+ 'command': IPA.command({
+ 'method': that.entity_name+'_enable',
+ 'args': [pkey],
+ 'options': {'all': true, 'rights': true}
+ })
+ };
+
+ for (var i=0; i<that.sections.length; i++) {
+ var section = that.sections[i];
+
+ var div = $('#'+that.entity_name+'-'+that.name+'-'+section.name, that.container);
+
+ for (var j=0; j<section.fields.length; j++) {
+ var field = section.fields[j];
+
+ var span = $('span[name='+field.name+']', div).first();
+ var values = field.save();
+ if (!values) continue;
+
+ var param_info = IPA.get_param_info(that.entity_name, field.name);
+
+ // skip primary key
+ if (param_info && param_info['primary_key']) continue;
+
+ var p = field.name.indexOf('_');
+ if (p >= 0) {
+ // prepare command to remove members if needed
+ var attribute = field.name.substring(0, p);
+ var other_entity = field.name.substring(p+1);
+
+ if (values.length) {
+ member_operations[attribute].command.set_option(other_entity, values.join(','));
+ member_operations[attribute].has_values = true;
+ }
+ continue;
+ }
+
+ // skip unchanged field
+ if (!field.is_dirty(span)) continue;
+
+ // check enable/disable
+ if (field.name == 'ipaenabledflag') {
+ if (values[0] == 'FALSE') enable_operation.command.method = that.entity_name+'_disable';
+ enable_operation.execute = true;
+ continue;
+ }
+
+ if (field.name == 'accesstime') {
+ // if accesstime is dirty, it means 'Any Time' is selected,
+ // so existing values have to be removed
+ for (var k=0; k<field.values.length; k++) {
+ var command = IPA.command(remove_accesstime.template);
+ command.set_option(field.name, field.values[k]);
+ remove_accesstime.commands.push(command);
+ }
+ continue;
+ }
+
+ if (categories[field.name]) {
+ if (values[0] == 'all') {
+ categories[field.name].remove_values = true;
+ }
+ }
+
+ // use setattr/addattr if param_info not available
+ if (!param_info) {
+ for (var l=0; l<values.length; l++) {
+ modify_operation.command.set_option(
+ l === 0 ? 'setattr' : 'addattr',
+ field.name+'='+values[l]);
+ modify_operation.execute = true;
+ }
+ continue;
+ }
+
+ // set modify options
+ if (values.length == 1) {
+ modify_operation.command.set_option(field.name, values[0]);
+ } else {
+ modify_operation.command.set_option(field.name, values);
+ }
+ modify_operation.execute = true;
+ }
+ }
+
+ var batch = IPA.batch_command({
+ 'name': 'hbac_details_update',
+ 'on_success': function(data, text_status, xhr) {
+ that.refresh();
+ },
+ 'on_error': function(xhr, text_status, error_thrown) {
+ that.refresh();
+ }
+ });
+
+ for (var member_attribute in member_operations) {
+ var member_operation = member_operations[member_attribute];
+ if (member_operation.has_values &&
+ categories[member_operation.category].remove_values) {
+ batch.add_command(member_operations[member_attribute].command);
+ }
+ }
+
+ batch.add_commands(remove_accesstime.commands);
+
+ if (modify_operation.execute) batch.add_command(modify_operation.command);
+ if (enable_operation.execute) batch.add_command(enable_operation.command);
+
+ if (!batch.commands.length) {
+ that.refresh();
+ return;
+ }
+
+ //alert(JSON.stringify(batch.to_json()));
+
+ batch.execute();
+ };
+
+ that.reset = function() {
+ for (var i=0; i<that.sections.length; i++) {
+ var section = that.sections[i];
+ section.reset();
+ }
+ };
+
+ return that;
+};
+
+
+IPA.hbacrule_details_general_section = function (spec){
+
+ spec = spec || {};
+
+ var that = IPA.details_section(spec);
+
+ that.create = function(container) {
+
+ var table = $('<table/>', {
+ 'style': 'width: 100%;'
+ }).appendTo(container);
+
+ var tr = $('<tr/>').appendTo(table);
+
+ var td = $('<td/>', {
+ 'style': 'width: 100px; text-align: right;',
+ 'html': 'Name:'
+ }).appendTo(tr);
+
+ td = $('<td/>').appendTo(tr);
+
+ var span = $('<span/>', { 'name': 'cn' }).appendTo(td);
+
+ $('<input/>', {
+ 'type': 'text',
+ 'name': 'cn',
+ 'size': 30
+ }).appendTo(span);
+
+ span.append(' ');
+
+ $('<span/>', {
+ 'name': 'undo',
+ 'class': 'ui-state-highlight ui-corner-all',
+ 'style': 'display: none;',
+ 'html': 'undo'
+ }).appendTo(span);
+
+ td = $('<td/>', {
+ 'style': 'text-align: right;'
+ }).appendTo(tr);
+
+ td.append('Rule type:');
+
+ span = $('<span/>', { 'name': 'accessruletype' }).appendTo(td);
+
+ $('<input/>', {
+ 'type': 'radio',
+ 'name': 'accessruletype',
+ 'value': 'allow'
+ }).appendTo(span);
+
+ span.append('Allow');
+
+ $('<input/>', {
+ 'type': 'radio',
+ 'name': 'accessruletype',
+ 'value': 'deny'
+ }).appendTo(span);
+
+ span.append('Deny');
+
+ span.append(' ');
+
+ $('<span/>', {
+ 'name': 'undo',
+ 'class': 'ui-state-highlight ui-corner-all',
+ 'style': 'display: none;',
+ 'html': 'undo'
+ }).appendTo(span);
+
+ tr = $('<tr/>').appendTo(table);
+
+ td = $('<td/>', {
+ 'style': 'text-align: right; vertical-align: top;',
+ 'html': 'Description:'
+ }).appendTo(tr);
+
+ td = $('<td/>', {
+ 'colspan': 2
+ }).appendTo(tr);
+
+ span = $('<span/>', { 'name': 'description' }).appendTo(td);
+
+ $('<textarea/>', {
+ 'name': 'description',
+ 'rows': 5,
+ 'style': 'width: 100%'
+ }).appendTo(span);
+
+ span.append(' ');
+
+ $('<span/>', {
+ 'name': 'undo',
+ 'class': 'ui-state-highlight ui-corner-all',
+ 'style': 'display: none;',
+ 'html': 'undo'
+ }).appendTo(span);
+
+ tr = $('<tr/>').appendTo(table);
+
+ td = $('<td/>', {
+ 'style': 'text-align: right; vertical-align: top;',
+ 'html': 'Rule status:'
+ }).appendTo(tr);
+
+ td = $('<td/>', {
+ 'colspan': 2
+ }).appendTo(tr);
+
+ span = $('<span/>', { 'name': 'ipaenabledflag' }).appendTo(td);
+
+ $('<input/>', {
+ 'type': 'radio',
+ 'name': 'ipaenabledflag',
+ 'value': 'TRUE'
+ }).appendTo(span);
+
+ span.append('Active');
+
+ $('<input/>', {
+ 'type': 'radio',
+ 'name': 'ipaenabledflag',
+ 'value': 'FALSE'
+ }).appendTo(span);
+
+ span.append('Inactive');
+
+ span.append(' ');
+
+ $('<span/>', {
+ 'name': 'undo',
+ 'class': 'ui-state-highlight ui-corner-all',
+ 'style': 'display: none;',
+ 'html': 'undo'
+ }).appendTo(span);
+ };
+
+ return that;
+};
+
+IPA.hbacrule_accesstime_widget = function (spec) {
+
+ spec = spec || {};
+
+ var that = IPA.widget(spec);
+
+ that.text = spec.text;
+ that.options = spec.options || [];
+
+ that.init = function() {
+
+ that.widget_init();
+
+ that.table = IPA.table_widget({
+ 'id': 'accesstime-table',
+ 'name': 'table', 'label': that.label
+ });
+
+ that.table.create_column({
+ 'name': that.name,
+ 'label': that.label,
+ 'primary_key': true
+ });
+
+ that.table.init();
+ };
+
+ that.create = function(container) {
+
+ that.widget_create(container);
+
+ var span = $('<span/>', { 'name': 'text' }).appendTo(container);
+
+ span.append(that.text);
+
+ for (var i=0; i<that.options.length; i++) {
+ var option = that.options[i];
+
+ $('<input/>', {
+ 'type': 'radio',
+ 'name': that.name,
+ 'value': option.value
+ }).appendTo(container);
+
+ container.append(option.label);
+ }
+
+ container.append(' ');
+
+ $('<span/>', {
+ 'name': 'undo',
+ 'class': 'ui-state-highlight ui-corner-all',
+ 'style': 'display: none;',
+ 'html': 'undo'
+ }).appendTo(container);
+
+ container.append('<br/>');
+
+ span = $('<span/>', { 'name': 'table' }).appendTo(container);
+
+ that.table.create(span);
+
+ var buttons = $('span[name=buttons]', span);
+
+ $('<input/>', {
+ 'type': 'button',
+ 'name': 'remove',
+ 'value': 'Remove '+that.label
+ }).appendTo(buttons);
+
+ $('<input/>', {
+ 'type': 'button',
+ 'name': 'add',
+ 'value': 'Add '+that.label
+ }).appendTo(buttons);
+ };
+
+ that.setup = function(container) {
+
+ that.widget_setup(container);
+
+ var span = $('span[name="table"]', that.container);
+ that.table.setup(span);
+
+ var button = $('input[name=remove]', span);
+ button.replaceWith(IPA.button({
+ 'label': button.val(),
+ 'icon': 'ui-icon-trash',
+ 'click': function() { that.remove(that.container); }
+ }));
+
+ button = $('input[name=add]', span);
+ button.replaceWith(IPA.button({
+ 'label': button.val(),
+ 'icon': 'ui-icon-plus',
+ 'click': function() { that.add(that.container); }
+ }));
+
+ var input = $('input[name="'+that.name+'"]', that.container);
+ input.change(function() {
+ that.show_undo();
+ });
+
+ var undo = that.get_undo();
+ undo.click(function() {
+ that.reset();
+ });
+ };
+
+ that.save = function() {
+ var value = $('input[name="'+that.name+'"]:checked', that.container).val();
+ if (value === '') {
+ return that.table.save();
+ } else {
+ return [];
+ }
+ };
+
+ that.load = function(record) {
+
+ that.values = record[that.name] || [];
+ that.reset();
+ };
+
+ that.update = function() {
+
+ that.set_category(that.container, that.values && that.values.length ? '' : 'all');
+
+ that.table.tbody.empty();
+ for (var i=0; that.values && i<that.values.length; i++) {
+ var record = {};
+ record[that.name] = that.values[i];
+ that.table.add_record(record);
+ }
+ };
+
+ that.set_category = function(container, value) {
+ $('input[name="'+that.name+'"][value="'+value+'"]', that.container).get(0).checked = true;
+ };
+
+ that.add = function() {
+
+ var pkey = $.bbq.getState(that.entity_name + '-pkey', true) || '';
+ var title = 'Add '+that.label+' to '+that.entity_name+' '+pkey;
+
+ var dialog = IPA.dialog({
+ 'title': title
+ });
+
+ dialog.add_field(IPA.text_widget({
+ 'name': that.name,
+ 'label': that.label
+ }));
+
+ dialog.create = function() {
+ var table = $('<table/>').appendTo(dialog.container);
+
+ var tr = $('<tr/>').appendTo(table);
+
+ var td = $('<td/>', {
+ 'style': 'vertical-align: top;'
+ }).appendTo(tr);
+ td.append(that.label+': ');
+
+ td = $('<td/>').appendTo(tr);
+
+ var span = $('<span/>', { 'name': that.name }).appendTo(td);
+
+ $('<input/>', {
+ 'type': 'text',
+ 'name': that.name,
+ 'size': 40
+ }).appendTo(span);
+
+ tr = $('<tr/>').appendTo(table);
+
+ td = $('<td/>', {
+ 'style': 'vertical-align: top;'
+ }).appendTo(tr);
+ td.append('Example:');
+
+ td = $('<td/>').appendTo(tr);
+
+ td.append('<b>Every day between 0800 and 1400:</b><br/>');
+ td.append('periodic daily 0800-1400<br/><br/>');
+
+ td.append('<b>December 16, 2010 from 10:32 until 10:33:</b><br/>');
+ td.append('absolute 201012161032 ~ 201012161033<td/>');
+ };
+
+ function add(on_success, on_error) {
+
+ var field = dialog.get_field(that.name);
+ var value = field.save()[0];
+
+ var command = IPA.command({
+ 'method': that.entity_name+'_add_'+that.name,
+ 'args': [pkey],
+ 'on_success': function() {
+ that.refresh();
+ if (on_success) on_success();
+ },
+ 'on_error': function() {
+ that.refresh();
+ if (on_error) on_error();
+ }
+ });
+
+ command.set_option(that.name, value);
+
+ command.execute();
+ }
+
+ dialog.add_button('Add', function() {
+ add(
+ function() { dialog.reset(); }
+ );
+ });
+
+ dialog.add_button('Add and Close', function() {
+ add(
+ function() { dialog.close(); },
+ function() { dialog.close(); }
+ );
+ });
+
+ dialog.add_button('Cancel', function() {
+ dialog.close();
+ });
+
+ dialog.init();
+
+ dialog.open(that.container);
+ };
+
+ that.remove = function() {
+
+ var values = that.table.get_selected_values();
+
+ if (!values.length) {
+ alert('Select '+that.label+' to be removed.');
+ return;
+ }
+
+ var pkey = $.bbq.getState(that.entity_name + '-pkey', true) || '';
+ var title = 'Remove '+that.label+' from '+that.entity_name+' '+pkey;
+
+ var dialog = IPA.deleter_dialog({
+ 'title': title,
+ 'values': values
+ });
+
+ dialog.remove = function() {
+
+ var batch = IPA.batch_command({
+ 'on_success': function() {
+ that.refresh();
+ dialog.close();
+ },
+ 'on_error': function() {
+ that.refresh();
+ dialog.close();
+ }
+ });
+
+ for (var i=0; i<values.length; i++) {
+ var command = IPA.command({
+ 'method': that.entity_name+'_remove_'+that.name,
+ 'args': [pkey]
+ });
+
+ command.set_option(that.name, values[i]);
+
+ batch.add_command(command);
+ }
+
+ batch.execute();
+ };
+
+ dialog.init();
+
+ dialog.open(that.container);
+ };
+
+ that.refresh = function() {
+
+ function on_success(data, text_status, xhr) {
+ that.load(data.result.result);
+ }
+
+ function on_error(xhr, text_status, error_thrown) {
+ var summary = $('span[name=summary]', that.table.tfoot).empty();
+ summary.append('<p>Error: '+error_thrown.name+'</p>');
+ summary.append('<p>'+error_thrown.title+'</p>');
+ summary.append('<p>'+error_thrown.message+'</p>');
+ }
+
+ var pkey = $.bbq.getState(that.entity_name + '-pkey', true) || '';
+ IPA.cmd('show', [pkey], {'rights': true}, on_success, on_error, that.entity_name);
+ };
+
+ return that;
+};
diff --git a/install/ui/hbacsvc.js b/install/ui/hbacsvc.js
new file mode 100644
index 000000000..dc0bc3230
--- /dev/null
+++ b/install/ui/hbacsvc.js
@@ -0,0 +1,118 @@
+/*jsl:import ipa.js */
+
+/* Authors:
+ * Endi Sukma Dewata <edewata@redhat.com>
+ *
+ * Copyright (C) 2010 Red Hat
+ * see file 'COPYING' for use and warranty information
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* REQUIRES: ipa.js, details.js, search.js, add.js, entity.js */
+
+IPA.hbacsvc = function () {
+
+ var that = IPA.entity({
+ 'name': 'hbacsvc'
+ });
+
+ that.init = function() {
+
+ var dialog = IPA.hbacsvc_add_dialog({
+ 'name': 'add',
+ 'title': 'Add New HBAC Service'
+ });
+ that.add_dialog(dialog);
+ dialog.init();
+
+ var facet = IPA.hbacsvc_search_facet({
+ 'name': 'search',
+ 'label': 'Search'
+ });
+ that.add_facet(facet);
+
+ facet = IPA.hbacsvc_details_facet({
+ 'name': 'details'
+ });
+ that.add_facet(facet);
+
+ that.entity_init();
+ };
+
+ return that;
+};
+
+
+IPA.add_entity(IPA.hbacsvc());
+
+
+IPA.hbacsvc_add_dialog = function (spec) {
+
+ spec = spec || {};
+
+ var that = IPA.add_dialog(spec);
+
+ that.init = function() {
+
+ that.add_field(IPA.text_widget({name:'cn', undo: false}));
+ that.add_field(IPA.text_widget({name:'description', undo: false}));
+
+ that.add_dialog_init();
+ };
+
+ return that;
+};
+
+
+IPA.hbacsvc_search_facet = function (spec) {
+
+ spec = spec || {};
+
+ var that = IPA.search_facet(spec);
+
+ that.init = function() {
+
+ that.create_column({name:'cn', primary_key: true});
+ that.create_column({name:'description'});
+
+ that.search_facet_init();
+ };
+
+ return that;
+};
+
+
+IPA.hbacsvc_details_facet = function (spec) {
+
+ spec = spec || {};
+
+ var that = IPA.details_facet(spec);
+
+ that.init = function() {
+
+ var section = IPA.details_list_section({
+ 'name': 'general',
+ 'label': 'General'
+ });
+ that.add_section(section);
+
+ section.create_field({'name': 'cn'});
+ section.create_field({'name': 'description'});
+
+ that.details_facet_init();
+ };
+
+ return that;
+};
diff --git a/install/ui/hbacsvcgroup.js b/install/ui/hbacsvcgroup.js
new file mode 100644
index 000000000..2dd049cbe
--- /dev/null
+++ b/install/ui/hbacsvcgroup.js
@@ -0,0 +1,197 @@
+/*jsl:import ipa.js */
+
+/* Authors:
+ * Endi Sukma Dewata <edewata@redhat.com>
+ *
+ * Copyright (C) 2010 Red Hat
+ * see file 'COPYING' for use and warranty information
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* REQUIRES: ipa.js, details.js, search.js, add.js, entity.js */
+
+IPA.hbacsvcgroup = function () {
+
+ var that = IPA.entity({
+ 'name': 'hbacsvcgroup'
+ });
+
+ that.init = function() {
+
+ that.create_association({
+ 'name': 'hbacsvc',
+ 'add_method': 'add_member',
+ 'remove_method': 'remove_member'
+ });
+
+ var dialog = IPA.hbacsvcgroup_add_dialog({
+ 'name': 'add',
+ 'title': 'Add New HBAC Service Group'
+ });
+ that.add_dialog(dialog);
+ dialog.init();
+
+ var facet = IPA.hbacsvcgroup_search_facet({
+ 'name': 'search',
+ 'label': 'Search'
+ });
+ that.add_facet(facet);
+
+ facet = IPA.hbacsvcgroup_details_facet({
+ 'name': 'details'
+ });
+ that.add_facet(facet);
+
+ that.entity_init();
+ };
+
+ return that;
+};
+
+
+IPA.add_entity(IPA.hbacsvcgroup());
+
+
+IPA.hbacsvcgroup_add_dialog = function (spec) {
+
+ spec = spec || {};
+
+ var that = IPA.add_dialog(spec);
+
+ that.init = function() {
+
+ that.add_field(IPA.text_widget({name:'cn', undo: false}));
+ that.add_field(IPA.text_widget({name:'description', undo: false}));
+
+ that.add_dialog_init();
+ };
+
+ return that;
+};
+
+
+IPA.hbacsvcgroup_search_facet = function (spec) {
+
+ spec = spec || {};
+
+ var that = IPA.search_facet(spec);
+
+ that.init = function() {
+
+ that.create_column({name:'cn', primary_key: true});
+ that.create_column({name:'description'});
+
+ that.search_facet_init();
+ };
+
+
+ return that;
+};
+
+
+IPA.hbacsvcgroup_details_facet = function (spec) {
+
+ spec = spec || {};
+
+ var that = IPA.details_facet(spec);
+
+ that.init = function() {
+
+ var section = IPA.details_list_section({
+ 'name': 'general',
+ 'label': 'General'
+ });
+ that.add_section(section);
+
+ section.create_field({'name': 'cn'});
+ section.create_field({'name': 'description'});
+
+ section = IPA.details_section({
+ 'name': 'services',
+ 'label': 'Services'
+ });
+ that.add_section(section);
+
+ var field = IPA.hbacsvcgroup_member_hbacsvc_table_widget({
+ 'name': 'member_hbacsvc',
+ 'label': 'Services',
+ 'other_entity': 'hbacsvc',
+ 'save_values': false
+ });
+ section.add_field(field);
+
+ that.details_facet_init();
+ };
+
+ return that;
+};
+
+
+IPA.hbacsvcgroup_member_hbacsvc_table_widget = function (spec) {
+
+ spec = spec || {};
+
+ var that = IPA.association_table_widget(spec);
+
+ that.init = function() {
+
+ var column = that.create_column({
+ name: 'cn',
+ primary_key: true,
+ width: '150px'
+ });
+
+ column.setup = function(container, record) {
+ container.empty();
+
+ var value = record[column.name];
+ value = value ? value.toString() : '';
+
+ $('<a/>', {
+ 'href': '#'+value,
+ 'html': value,
+ 'click': function (value) {
+ return function() {
+ var state = IPA.tab_state(that.other_entity);
+ state[that.other_entity + '-facet'] = 'details';
+ state[that.other_entity + '-pkey'] = value;
+ $.bbq.pushState(state);
+ return false;
+ };
+ }(value)
+ }).appendTo(container);
+ };
+
+ that.create_column({
+ name: 'description',
+ width: '350px'
+ });
+
+ that.create_adder_column({
+ name: 'cn',
+ primary_key: true,
+ width: '100px'
+ });
+
+ that.create_adder_column({
+ name: 'description',
+ width: '100px'
+ });
+
+ that.association_table_widget_init();
+ };
+
+ return that;
+};
diff --git a/install/ui/header.png b/install/ui/header.png
new file mode 100644
index 000000000..265d9b404
--- /dev/null
+++ b/install/ui/header.png
Binary files differ
diff --git a/install/ui/header_background.png b/install/ui/header_background.png
new file mode 100644
index 000000000..609a4575c
--- /dev/null
+++ b/install/ui/header_background.png
Binary files differ
diff --git a/install/ui/header_logo.png b/install/ui/header_logo.png
new file mode 100644
index 000000000..2b8e65361
--- /dev/null
+++ b/install/ui/header_logo.png
Binary files differ
diff --git a/install/ui/host.js b/install/ui/host.js
new file mode 100644
index 000000000..c3851ff75
--- /dev/null
+++ b/install/ui/host.js
@@ -0,0 +1,494 @@
+/*jsl:import ipa.js */
+/*jsl:import certificate.js */
+
+/* Authors:
+ * Pavel Zuna <pzuna@redhat.com>
+ * Endi S. Dewata <edewata@redhat.com>
+ *
+ * Copyright (C) 2010 Red Hat
+ * see file 'COPYING' for use and warranty information
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* REQUIRES: ipa.js, details.js, search.js, add.js, entity.js */
+
+IPA.host = function () {
+
+ var that = IPA.entity({
+ 'name': 'host'
+ });
+
+ that.init = function() {
+
+ that.create_association({
+ 'name': 'hostgroup',
+ 'associator': 'serial'
+ });
+
+ that.create_association({
+ 'name': 'rolegroup',
+ 'associator': 'serial'
+ });
+
+ var dialog = IPA.host_add_dialog({
+ 'name': 'add',
+ 'title': 'Add New Host'
+ });
+ that.add_dialog(dialog);
+ dialog.init();
+
+ var facet = IPA.host_search_facet({
+ 'name': 'search',
+ 'label': 'Search'
+ });
+ that.add_facet(facet);
+
+ facet = IPA.host_details_facet({
+ 'name': 'details'
+ });
+ that.add_facet(facet);
+
+ facet = IPA.host_managedby_host_facet({
+ 'name': 'managedby_host',
+ 'label': IPA.messages.association.managedby+' '+IPA.metadata['host'].label,
+ 'other_entity': 'host'
+ });
+ that.add_facet(facet);
+
+ that.create_association_facets();
+
+ that.entity_init();
+ };
+
+ return that;
+};
+
+
+IPA.add_entity(IPA.host());
+
+
+IPA.host_add_dialog = function (spec) {
+
+ spec = spec || {};
+
+ var that = IPA.add_dialog(spec);
+
+ that.init = function() {
+
+ that.add_field(IPA.text_widget({
+ name: 'fqdn',
+ size: 40,
+ undo: false
+ }));
+
+ // TODO: Replace with i18n label
+ that.add_field(IPA.checkbox_widget({
+ name: 'force',
+ label: 'Force',
+ tooltip: 'force host name even if not in DNS',
+ undo: false
+ }));
+
+ that.add_dialog_init();
+ };
+
+ return that;
+};
+
+
+IPA.host_search_facet = function (spec) {
+
+ spec = spec || {};
+
+ var that = IPA.search_facet(spec);
+
+ that.init = function() {
+
+ that.create_column({name:'fqdn'});
+ that.create_column({name:'description'});
+ //TODO use the value of this field to set enrollment status
+ that.create_column({name:'krblastpwdchange', label:'Enrolled?'});
+ that.create_column({name:'nshostlocation'});
+
+ that.search_facet_init();
+ };
+
+ return that;
+};
+
+
+IPA.host_details_facet = function (spec) {
+
+ spec = spec || {};
+
+ var that = IPA.details_facet(spec);
+
+ that.init = function() {
+
+ var section = IPA.details_list_section({
+ 'name': 'details',
+ 'label': 'Host Settings'
+ });
+ that.add_section(section);
+
+ //TODO: use i18n labels
+ section.create_field({
+ name: 'fqdn',
+ label: 'Fully Qualified Host Name'
+ });
+
+ section.create_field({'name': 'krbprincipalname'});
+
+ //TODO: add this to the host plugin
+ //TODO: use i18n labels
+ section.create_field({
+ 'name': 'serverhostname',
+ 'label': 'Host Name'
+ });
+
+ section.create_field({'name': 'description'});
+
+ //TODO: use i18n labels
+ section = IPA.details_list_section({
+ 'name': 'enrollment',
+ 'label': 'Enrollment'
+ });
+ that.add_section(section);
+
+ //TODO add label to messages
+ section.add_field(host_provisioning_status_widget({
+ 'name': 'provisioning_status',
+ 'label': 'Status',
+ 'facet': that
+ }));
+
+ section = IPA.details_list_section({
+ 'name': 'certificate',
+ 'label': 'Host Certificate'
+ });
+ that.add_section(section);
+
+ section.add_field(host_certificate_status_widget({
+ 'name': 'certificate_status',
+ 'label': 'Status'
+ }));
+
+ that.details_facet_init();
+ };
+
+ that.refresh = function() {
+
+ var pkey = $.bbq.getState(that.entity_name + '-pkey', true) || '';
+
+ var command = IPA.command({
+ 'name': that.entity_name+'_show_'+pkey,
+ 'method': that.entity_name+'_show',
+ 'args': [pkey],
+ 'options': { 'all': true, 'rights': true }
+ });
+
+ command.on_success = function(data, text_status, xhr) {
+ that.load(data.result.result);
+ };
+
+ command.on_error = function(xhr, text_status, error_thrown) {
+ var details = $('.details', that.container).empty();
+ details.append('<p>Error: '+error_thrown.name+'</p>');
+ details.append('<p>'+error_thrown.title+'</p>');
+ details.append('<p>'+error_thrown.message+'</p>');
+ };
+
+ command.execute();
+ };
+
+ return that;
+};
+
+
+function host_provisioning_status_widget(spec) {
+
+ spec = spec || {};
+
+ var that = IPA.widget(spec);
+
+ that.facet = spec.facet;
+
+ that.create = function(container) {
+
+ that.widget_create(container);
+
+ var dd = $('<dd/>', {
+ 'class': 'first'
+ }).appendTo(container);
+
+ var div = $('<div/>', {
+ name: 'kerberos-key-valid'
+ }).appendTo(dd);
+
+ $('<img/>', {
+ src: 'check.png',
+ style: 'float: left;',
+ 'class': 'status-icon'
+ }).appendTo(div);
+
+ var content_div = $('<div/>', {
+ style: 'float: left;'
+ }).appendTo(div);
+
+ content_div.append('<b>Kerberos Key Present, Host Provisioned:</b>');
+
+ content_div.append(' ');
+
+ $('<input/>', {
+ 'type': 'button',
+ 'name': 'unprovision',
+ 'value': 'Delete Key, Unprovision'
+ }).appendTo(content_div);
+
+ div = $('<div/>', {
+ name: 'kerberos-key-missing'
+ }).appendTo(dd);
+
+ $('<img/>', {
+ src: 'caution.png',
+ style: 'float: left;',
+ 'class': 'status-icon'
+ }).appendTo(div);
+
+ content_div = $('<div/>', {
+ style: 'float: left;'
+ }).appendTo(div);
+
+ content_div.append('<b>Kerberos Key Not Present</b>');
+
+ content_div.append('<br/>');
+
+ content_div.append('Enroll via One-Time-Password:');
+
+ content_div.append('<br/>');
+ content_div.append('<br/>');
+
+ $('<input/>', {
+ 'type': 'text',
+ 'name': 'otp',
+ 'class': 'otp'
+ }).appendTo(content_div);
+
+ content_div.append(' ');
+
+ $('<input/>', {
+ 'type': 'button',
+ 'name': 'enroll',
+ 'value': 'Set OTP'
+ }).appendTo(content_div);
+ };
+
+ that.setup = function(container) {
+
+ that.widget_setup(container);
+
+ that.valid = $('div[name=kerberos-key-valid]', that.container);
+ that.missing = $('div[name=kerberos-key-missing]', that.container);
+
+ var button = $('input[name=unprovision]', that.container);
+ that.unprovision_button = IPA.button({
+ 'label': 'Delete Key, Unprovision',
+ 'click': that.show_unprovision_dialog
+ });
+ button.replaceWith(that.unprovision_button);
+
+ that.otp_input = $('input[name=otp]', that.container);
+
+ that.enroll_button = $('input[name=enroll]', that.container);
+ button = IPA.button({
+ 'label': 'Set OTP',
+ 'click': that.set_otp
+ });
+
+ that.enroll_button.replaceWith(button);
+ that.enroll_button = button;
+ };
+
+ that.show_unprovision_dialog = function() {
+
+ var label = IPA.metadata[that.entity_name].label;
+ var dialog = IPA.dialog({
+ 'title': 'Unprovisioning '+label
+ });
+
+ dialog.create = function() {
+ dialog.container.append(
+ 'Are you sure you want to unprovision this host?');
+ };
+
+ dialog.add_button('Unprovision', function() {
+ that.unprovision(
+ function(data, text_status, xhr) {
+ set_status('missing');
+ dialog.close();
+ },
+ function(xhr, text_status, error_thrown) {
+ dialog.close();
+ }
+ );
+ });
+
+ dialog.init();
+
+ dialog.open(that.container);
+
+ return false;
+ };
+
+ that.unprovision = function(on_success, on_error) {
+
+ var pkey = that.facet.get_primary_key();
+
+ var command = IPA.command({
+ 'name': that.entity_name+'_disable_'+pkey,
+ 'method': that.entity_name+'_disable',
+ 'args': [pkey],
+ 'options': { 'all': true, 'rights': true },
+ 'on_success': on_success,
+ 'on_error': on_error
+ });
+
+ command.execute();
+ };
+
+ that.set_otp = function() {
+
+ var pkey = that.facet.get_primary_key();
+ var otp = that.otp_input.val();
+ that.otp_input.val('');
+
+ var command = IPA.command({
+ 'method': that.entity_name+'_mod',
+ 'args': [pkey],
+ 'options': {
+ 'all': true,
+ 'rights': true,
+ 'userpassword': otp
+ },
+ 'on_success': function(data, text_status, xhr) {
+ alert('One-Time-Password has been set.');
+ }
+ });
+
+ command.execute();
+ };
+
+ that.load = function(result) {
+ that.result = result;
+ var krblastpwdchange = result['krblastpwdchange'];
+ set_status(krblastpwdchange ? 'valid' : 'missing');
+ };
+
+ function set_status(status) {
+ that.valid.css('display', status == 'valid' ? 'inline' : 'none');
+ that.missing.css('display', status == 'missing' ? 'inline' : 'none');
+ }
+
+ return that;
+}
+
+function host_certificate_status_widget(spec) {
+
+ spec = spec || {};
+
+ var that = certificate_status_widget(spec);
+
+ that.init = function() {
+
+ that.entity_label = IPA.metadata[that.entity_name].label;
+
+ that.get_entity_pkey = function(result) {
+ var values = result['fqdn'];
+ return values ? values[0] : null;
+ };
+
+ that.get_entity_name = function(result) {
+ return that.get_entity_pkey(result);
+ };
+
+ that.get_entity_principal = function(result) {
+ var values = result['krbprincipalname'];
+ return values ? values[0] : null;
+ };
+
+ that.get_entity_certificate = function(result) {
+ var values = result['usercertificate'];
+ return values ? values[0].__base64__ : null;
+ };
+ };
+
+ return that;
+}
+
+IPA.host_managedby_host_facet = function (spec) {
+
+ spec = spec || {};
+
+ var that = IPA.association_facet(spec);
+
+ that.add_method = 'add_managedby';
+ that.remove_method = 'remove_managedby';
+
+ that.init = function() {
+
+ var column = that.create_column({
+ name: 'fqdn',
+ primary_key: true
+ });
+
+ column.setup = function(container, record) {
+ container.empty();
+
+ var value = record[column.name];
+ value = value ? value.toString() : '';
+
+ $('<a/>', {
+ 'href': '#'+value,
+ 'html': value,
+ 'click': function (value) {
+ return function() {
+ var state = IPA.tab_state(that.other_entity);
+ state[that.other_entity + '-facet'] = 'details';
+ state[that.other_entity + '-pkey'] = value;
+ $.bbq.pushState(state);
+ return false;
+ };
+ }(value)
+ }).appendTo(container);
+ };
+
+ that.create_column({name: 'description'});
+
+ that.create_adder_column({
+ name: 'fqdn',
+ primary_key: true,
+ width: '100px'
+ });
+
+ that.create_adder_column({
+ name: 'description',
+ width: '100px'
+ });
+
+ that.association_facet_init();
+ };
+
+ return that;
+};
diff --git a/install/ui/hostgroup.js b/install/ui/hostgroup.js
new file mode 100644
index 000000000..0525c05f2
--- /dev/null
+++ b/install/ui/hostgroup.js
@@ -0,0 +1,67 @@
+/*jsl:import ipa.js */
+
+/* Authors:
+ * Pavel Zuna <pzuna@redhat.com>
+ *
+ * Copyright (C) 2010 Red Hat
+ * see file 'COPYING' for use and warranty information
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* REQUIRES: ipa.js, details.js, search.js, add.js, entity.js */
+
+
+IPA.add_entity( function() {
+ var that = IPA.entity({
+ 'name': 'hostgroup'
+ });
+ that.init = function() {
+ var search_facet = IPA.search_facet({
+ name: 'search',
+ label: 'Search',
+ entity_name: that.name
+ });
+ search_facet.create_column({name:'cn'});
+ search_facet.create_column({name:'description'});
+ that.add_facet(search_facet);
+
+ that.add_facet(function() {
+ var that = IPA.details_facet({name:'details'});
+ that.add_section(
+ IPA.stanza({name:'identity', label:'Hostgroup Settings'}).
+ input({name:'cn'}).
+ input({name: 'description'}));
+ return that;
+ }());
+
+
+ var dialog = IPA.add_dialog({
+ name: 'add',
+ title: 'Add Hostgroup'
+ });
+ that.add_dialog(dialog);
+
+ dialog.add_field(IPA.text_widget({name: 'cn', undo: false}));
+ dialog.add_field(IPA.text_widget({name: 'description', undo: false}));
+ dialog.init();
+
+ that.create_association_facets();
+ that.entity_init();
+ };
+ return that;
+}());
+
+
+
diff --git a/install/ui/index.html b/install/ui/index.html
new file mode 100644
index 000000000..7ee4aa61c
--- /dev/null
+++ b/install/ui/index.html
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+ <title>IPA: Identity Policy Audit</title>
+
+ <script type="text/javascript" src="json2.js"></script>
+ <script type="text/javascript" src="jquery.js"></script>
+ <script type="text/javascript" src="jquery.cookie.js"></script>
+ <script type="text/javascript" src="jquery-ui.js"></script>
+ <script type="text/javascript" src="jquery.ba-bbq.js"></script>
+
+ <script type="text/javascript" src="ipa.js"></script>
+ <script type="text/javascript" src="widget.js"></script>
+ <script type="text/javascript" src="search.js"></script>
+ <script type="text/javascript" src="details.js"></script>
+ <script type="text/javascript" src="add.js"></script>
+ <script type="text/javascript" src="associate.js"></script>
+ <script type="text/javascript" src="entity.js"></script>
+ <script type="text/javascript" src="navigation.js"></script>
+ <script type="text/javascript" src="rule.js"></script>
+
+ <script type="text/javascript" src="certificate.js"></script>
+ <script type="text/javascript" src="user.js"></script>
+ <script type="text/javascript" src="group.js"></script>
+ <script type="text/javascript" src="hbacrule.js"></script>
+ <script type="text/javascript" src="hbacsvc.js"></script>
+ <script type="text/javascript" src="hbacsvcgroup.js"></script>
+ <script type="text/javascript" src="host.js"></script>
+ <script type="text/javascript" src="hostgroup.js"></script>
+ <script type="text/javascript" src="netgroup.js"></script>
+ <script type="text/javascript" src="service.js"></script>
+ <script type="text/javascript" src="serverconfig.js"></script>
+ <script type="text/javascript" src="sudorule.js"></script>
+ <script type="text/javascript" src="sudocmd.js"></script>
+ <script type="text/javascript" src="sudocmdgroup.js"></script>
+ <script type="text/javascript" src="policy.js"></script>
+ <script type="text/javascript" src="aci.js"></script>
+
+
+ <script type="text/javascript" src="develop.js"></script>
+ <script type="text/javascript" src="webui.js"></script>
+
+ <link rel="stylesheet" type="text/css" href="jquery-ui.css" />
+ <link rel="stylesheet" type="text/css" href="ipa.css" />
+</head>
+
+<body>
+ <div class="center-container">
+ <div class="header" >
+ <span class="header-logo">
+ <a href="#"><img src="ipalogo.png" /></a>
+ </span>
+ <span id="header-network-activity-indicator" class="network-activity-indicator">
+ <img src="spinner_header.gif" />
+ </span>
+ <span id="loggedinas" class="header-loggedinas">
+ <a href="#"><span id="login_header">Logged in as</span>: <strong>user@FREEIP.ORG</strong></a>
+ </span>
+ </div>
+ <div id="navigation" class="tabs"></div>
+ </div>
+</body>
+
+</html>
+
diff --git a/install/ui/ipa.css b/install/ui/ipa.css
new file mode 100644
index 000000000..5726ad99c
--- /dev/null
+++ b/install/ui/ipa.css
@@ -0,0 +1,750 @@
+/* Authors:
+ * Pavel Zuna <pzuna@redhat.com>
+ * Adam Young <ayoung@redhat.com>
+ * Endi Sukma Dewata <edewata@redhat.com>
+ * Kyle Baker <kybaker@redhat.com>
+ *
+ * Copyright (C) 2010 Red Hat
+*/
+
+
+@font-face {font-family: "FreeWay"; src:url("FreeWay.otf");}
+@font-face {font-family: "FreeWayBold"; src:url("FreeWay-Bold.otf");}
+
+body{
+ background-image:url('outer-bg.png');
+ background-repeat:repeat-x;
+ background-position:left top;
+ background-color:#F9F9F9;
+ border-width: 0;
+ font-family:"Liberation Sans",Arial,Sans;
+ font-size:11px;
+ margin: 0;
+}
+
+.network-activity-indicator{
+ display:none;
+}
+
+.center-container {
+ margin-left: auto;
+ margin-right: auto;
+ width: 960px;
+}
+
+.ui-widget {
+ font-size: 1em;
+}
+
+.input_link {
+ padding: .4em 1em .4em 2em;
+ text-decoration: none;
+ position: relative;
+ cursor: pointer;
+}
+
+.input_link span.ui-icon {
+ -moz-border-radius: 0.3em;
+ border: 1px solid #B8B8B8;
+ margin: -0.9em 0.4em 0em -0.3em;
+ position: absolute;
+ left: .2em;
+ top: 50%;
+}
+
+.button-without-icon {
+ padding: .4em 1em .4em 1em;
+ text-decoration: none;
+ position: relative;
+ cursor: pointer;
+}
+
+/* ---- Header ---- */
+div.header {
+ background-color:#0C3B00;
+ width: 100%;
+ height: 4em;
+}
+
+div.header a {
+ text-decoration: none;
+}
+
+div.header a:link {
+ text-decoration: none;
+ color: white;
+}
+
+div.header a:visited {
+ text-decoration: none;
+ color: white;
+}
+
+div.header span.header-logo {
+ padding-left: 2em;
+}
+
+div.header span.header-logo a img {
+ border: 0;
+}
+
+div.header span.header-loggedinas {
+ width: 96em;
+ color: #fff;
+ display: block;
+ padding-left: 71em;
+ margin-top: -2.6em;
+ margin-left: auto;
+ margin-right: 27.6em;
+ width: 20em;
+}
+
+/* ---- Navigation ---- */
+div.tabs {
+ overflow: auto;
+ width: 100%;
+ height: 100%;
+ min-height: 40em;
+}
+
+div#content {
+ margin-top: 0;
+ position: relative;
+ width: 100%;
+}
+
+
+ul#viewtype {
+ padding-left: 2em;
+}
+
+ul#viewtype li {
+ color: #656565;
+ display: inline;
+ font-weight: bold;
+ list-style-type: none;
+ padding-right: 2em;
+}
+
+
+ul#viewtype li img {
+ vertical-align: middle;
+}
+
+ul#viewtype li a {
+ font-weight: normal;
+}
+
+div.content div.content-buttons {
+ float: right;
+ margin-right: 1.5em;
+}
+
+div.content div.content-buttons img {
+ border: 0;
+}
+
+
+.entity-container h1{
+ -moz-border-radius: 0.3em;
+ font-family: "FreeWayBold", "Liberation Sans", Arial, sans-serif;
+ color: #333333;
+ margin: 0;
+ background: #EEEEEE;
+ margin-top: 0.5em;
+ padding: .5em;
+ text-transform: uppercase;
+ font-size: 1.2em;
+}
+
+
+h2 {
+ font-family: "FreeWayBold","Liberation Sans", Arial, sans-serif;
+ font-size: 1.5em;
+ font-weight: normal;
+ color: #333333;
+ text-transform: uppercase;
+ margin-left: 1em;
+ margin-bottom: 0;
+ text-align: left;
+}
+
+.section-expand{
+ float:left;
+ -moz-border-radius: 0.3em;
+ background-color: -moz-linear-gradient(top, #959595, #5e5e5e);
+ border: 1px solid #b8b8b8;
+ color: #fff;
+ margin-right: 0.5em;
+ margin-top: 0.1em;
+}
+
+hr {
+ background-color: #EEEEEE;
+ clear: both;
+ color: #FFFFFF;
+ height: 0.1em;
+ margin-left: 1.5em;
+ margin-right: 1.5em;
+ margin-top: 1em;
+}
+
+.details-section {
+ margin-left: 4.5em;
+ margin-right: 1.5em;
+ margin-top: 1.8em;
+ white-space: nowrap;
+ padding-bottom: 1.8em;
+ padding-right: 1.8em;
+}
+
+.undo {
+ cursor:pointer;
+}
+
+dl.entryattrs {
+ clear: both;
+ margin-left: 1.5em;
+ margin-top: 1.8em;
+ white-space: nowrap;
+}
+
+dl.entryattrs dt {
+ clear: left;
+ float: left;
+ padding-bottom: 1.8em;
+ padding-right: 1.8em;
+ text-align: right;
+ width: 16em;
+ margin: 0.5em -0.5em 0 -6em;
+}
+
+dl.entryattrs dd {
+ float: left;
+ padding-bottom: 1.8em;
+}
+
+dl.entryattrs dd.first {
+ margin-left: 0;
+ margin-top: 0.7em;
+}
+
+dl.entryattrs dd.other {
+ clear: both;
+ margin-left: 10.7em;
+}
+
+dl.entryattrs input {
+ margin-right: 0.5em;
+ margin-top: -1.2em;
+ min-width: 27.5em;
+}
+
+dl.entryattrs input.otp {
+ min-width: 15em;
+ width: 15em;
+}
+
+span.attrhint {
+ font-size: 8pt;
+ left: 5em;
+ margin-left: 12.5em;
+ position: absolute;
+ overflow-x: hidden;
+}
+
+
+/*Navigation */
+.tabs1 .ui-tabs-nav{
+ padding-left: 2.5em;
+ padding-top: 2em;
+ margin: 0;
+ border: none;
+ background-image: url(Mainnav-background.png);
+ -moz-border-radius: 0;
+}
+
+.ui-tabs {
+ padding:0;
+}
+
+#the positions for these are in the large icon image,
+#and need to be specified in pixels.
+.ui-icon-plus {
+ background-position: -16px -129px;
+}
+
+.ui-icon-minus {
+ background-position: -48px -129px;
+}
+
+.ui-icon-trash {
+ background-position: -176px -97px;
+}
+
+.ui-widget-content .ui-icon {
+ background-image: url("ui-icons_222222_256x240.png");
+ background-color: #e2e2e2;
+}
+
+.ui-widget-content {
+}
+
+
+.ui-widget-content a {
+ text-decoration: none;
+ color: #1d85d5;
+ font-weight: normal;
+}
+
+.ui-widget-header {
+ background: url("modal-background.png")
+ repeat scroll 50% 50% #1f9123;
+ border: 1px solid #244c16;
+ color: #EEEEEE;
+ font-weight: bold;
+}
+
+.tabs1 .ui-tabs-nav {
+ height: 3em;
+}
+
+.ui-widget input, .ui-widget select,
+.ui-widget textarea, .ui-widget button {
+ font-family: "Liberation Sans", Arial, sans-serif;
+ font-size: 1.3em;
+ margin-right: .1em;
+}
+
+.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default {
+ -moz-border-radius: .3em;
+ background: -moz-linear-gradient(top, #959595, #5e5e5e);
+ border: 1px solid #777777;
+ color: #fff;
+ font-weight: normal;
+}
+
+.tabs1 .ui-tabs-nav li {
+ -moz-border-radius: 0 !important;
+ background-image: url(Mainnav-offtab.png);
+ margin: 0;
+ border-width: 0;
+ text-align: center;
+ vertical-align:baseline;
+ }
+
+.tabs1 .ui-tabs-nav li.ui-tabs-selected {
+ padding: 0 0;
+ background-image: url(Mainnav-ontab.png);
+ text-align: center;
+ margin: 0;
+}
+
+.tabs1 .ui-tabs-nav li a{
+ -moz-border-radius: 0 !important;
+ font-family: "FreeWayBold", "Liberation Sans", Arial, Sans;
+ width:5.5em;
+ padding: none;
+ color: #7E7E7E;
+ margin: 0 auto;
+ text-align:center;
+ font-size:1.5em;
+}
+
+
+.tabs1 .ui-tabs-nav li > a:link, span.main-nav-off > a:visited{
+ color: #7E7E7E;
+}
+
+.tabs1 .ui-tabs-nav li.ui-tabs-selected a{
+ color: #3D752A;
+}
+
+.tabs1 .ui-tabs-panel {
+ display: block;
+ border-width: 0;
+ padding: 0 0 0 0;
+ background: none;
+ overflow-x: hidden;
+}
+
+.tabs2 .ui-tabs-nav {
+ padding: 0.3em 6em 0 4em;
+ margin: 0;
+ height: 2.4em;
+ background-image: url(Subnav-background.png);
+}
+
+.tabs2 .ui-tabs-nav li {
+ width:auto;
+ padding-left: 1em;
+ margin: 0;
+ background: #326122 !important;
+ color: white;
+}
+
+.tabs2 .ui-tabs-nav li.ui-tabs-selected {
+ padding-left: 1em;
+ height: 1em;
+ background: #326122 !important;
+}
+
+
+.tabs2 .ui-tabs-nav li a{
+ width:auto;
+ padding: 0.4em 0.6em ;
+ -moz-border-radius: 2em !important;
+ border-radius: 2em !important;
+ color: white;
+ font-size: 1em;
+ font-family: "Liberation Sans", Arial, Sans;
+}
+
+.tabs2 .ui-tabs-nav li > a:link, span.main-nav-off > a:visited{
+ color:white;
+}
+
+
+.tabs2 .ui-tabs-nav li a:hover{
+ background: none repeat scroll 0 0 #1C3612;
+}
+
+.tabs2 .ui-tabs-nav li.ui-tabs-selected a{
+ background: none repeat scroll 0 0 #1C3612;
+ color: white;
+
+}
+
+span.sub-nav-off > a:link, span.sub-nav-off > a:visited{
+ color:white;
+}
+
+span.main-nav-off > a:link, span.main-nav-off > a:visited{
+ color:white;
+}
+
+span.main-separator{
+ background: #333339;
+ padding:0.1em;
+}
+
+
+
+/* Entity */
+
+.entity-container{
+ position: relative;
+ left: 22em;
+ width: 80%;
+ margin: 0.06em;
+ padding: 0.06em;
+ background: #e8e8e8;
+}
+
+.action-panel {
+ position: fixed;
+ height: 33em;
+ left: auto;
+ border: none;
+ float: none;
+ margin-top: 6.3em;
+ margin-left: -19.5em;
+ margin-right: 0;
+ padding-left: 0;
+ position: fixed;
+ width: 18em;
+ background-image:url('panel-background.png');
+ background-repeat:no-repeat;
+ background-position:right;
+}
+
+.action-panel h3{
+ font-family: "FreeWayBold", "Liberation Sans", Arial, sans-serif;
+ color: #333333;
+ margin: 0;
+ background: #EEEEEE;
+ padding: .5em;
+ border-right: 1px solid #dfdfdf;
+ text-transform: uppercase;
+ font-size: 1.2em;
+}
+
+.action-panel ul {
+ list-style-type:none;
+ padding-left: .5em;
+}
+
+.action-panel h3{
+ margin: 0;
+ background: #e8e8e8;
+}
+
+.action-panel li {
+ font-family: "FreeWayBold", "Liberation Sans", Arial, sans-serif;
+ font-size: 1.1em;
+ color: #1d85d5;
+ list-style-type: none;
+ min-height: 2.1em;
+ padding: none;
+}
+
+.action-panel li.search-facet {
+ font-family: "FreeWayBold", "Liberation Sans", Arial, Sans;
+ color: #1D85D5;
+ cursor: pointer;
+ text-transform: uppercase;
+ font-size: 1.2em;
+}
+
+.action-panel li.back-to-search {
+ margin-left: -1.5em;
+}
+
+.action-panel li.entity-facet {
+ font-family: "Liberation Sans",Arial,sans-serif;
+ color: #1d85d5;
+ cursor: pointer;
+ margin-left:1.2em;
+ text-transform: none;
+}
+
+.action-panel li.entity-facet-selected {
+ font-family: "FreeWayBold", "Liberation Sans", Arial, Sans;
+ color: black;
+ text-transform: uppercase;
+ cursor: pointer;
+}
+
+.action-panel li.entity-facet-disabled {
+ display:none;
+}
+
+.action-panel li.entity-facet-relation-label {
+ font-family: "FreeWayBold", "Liberation Sans", Arial, Sans;
+ color: #8a8a8a;
+ cursor: default;
+ text-transform: uppercase;
+ margin-left:1.8em;
+}
+
+.action-panel li.facet-group-member {
+ margin-left: 2.9em
+}
+
+
+.action-button {
+ background: none;
+ background-image:none;
+ font-family: "Liberation Sans", Arial, sans-serif;
+ font-size: 0.9em;
+}
+
+a.action-button-disabled {
+ color: gray;
+ cursor: default;
+}
+
+.action-controls {
+ position: relative;
+ display:inline;
+}
+
+.client {
+ font-size: 10px;
+ margin-top: 0.4em;
+ float: left;
+ min-width: 70em;
+}
+
+
+/* Search */
+
+.search-controls {
+ -moz-border-radius: .7em .7em 0 0;
+ height:2.5em;
+ background: -moz-linear-gradient(top, #eeeeee, #dfdfdf);
+ position: relative;
+ padding: 1em 1.5em;
+ margin-top: 1.5em;
+}
+
+.search-table > a:link,a:visted{
+ color:black;
+}
+
+.search-table{
+ padding: 0;
+ width:100%;
+ border: none;
+}
+
+.search-table td{
+ padding-left: 0.5em;
+}
+
+.search-table th{
+ padding-left: 0.5em;
+ background-color:#f6f6f6;
+ color:#333333;
+ text-align: left;
+ border: 1px solid #dfdfdf;
+}
+
+.search-table tfoot tr td span{
+ border-top: 1px solid #dfdfdf;
+ padding: 0.9em 0 0 1em;
+ display: block;
+ margin-top: 2em;
+}
+
+.search-table tr:nth-child(even){
+# background-color:#CCC;
+}
+
+.search-table tr:nth-child(odd){
+# background-color:#FFF;
+}
+
+.entity-views{
+ list-style-type:none;
+}
+
+.entity-views li {
+ display:inline;
+ cursor: pointer;
+ padding: 0.4em;
+}
+
+.strikethrough { text-decoration: line-through; }
+
+table.certificate-status {
+ line-height: 2;
+}
+
+table.kerberos-key-status {
+ line-height: 2;
+}
+
+.status-icon {
+ vertical-align: bottom;
+# width: auto;
+# height: 1em;
+# -webkit-border-radius: 0.5em;
+# -moz-border-radius: 0.5em;
+}
+
+.status-valid {
+ background-image:url('check.png');
+ border: 0.2em solid #008000;
+}
+
+.status-valid-active {
+ background-color: #008000;
+}
+
+.status-revoked {
+ border: 0.2em solid #ff0000;
+}
+
+.status-revoked-active {
+ background-color: #ff0000;
+}
+
+.status-missing {
+ border: 0.2em solid #daa520;
+}
+
+.status-missing-active {
+ background-color: #daa520;
+}
+
+dl.modal {
+ clear: both;
+ margin-left: 1em;
+ margin-top: 1em;
+ white-space: nowrap;
+}
+
+dl.modal dt {
+ clear: left;
+ float: left;
+ padding-bottom: 0;
+ padding-right: 0;
+ text-align: right;
+ width: 10em;
+}
+
+dl.modal dd {
+ float: left;
+ padding-bottom: 0;
+ margin-left: 0.8em;
+}
+
+
+
+.ui-widget-content {
+border:0;
+}
+
+table.scrollable thead {
+ display: block;
+}
+
+table.scrollable tbody {
+ display: block;
+ overflow: auto;
+}
+
+.adder-dialog-filter {
+ height: 2.5em;
+}
+
+.adder-dialog-results {
+ position: relative;
+ height: 20.0em;
+}
+
+.adder-dialog-available {
+ border: 1px solid black;
+ position: absolute;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ width: 23.0em;
+}
+
+.adder-dialog-buttons {
+ position: absolute;
+ top: 1.5em;
+ left: 23.35em;
+ right: 25;
+ bottom: 0;
+ text-align: center;
+}
+
+.adder-dialog-selected {
+ border: 1px solid black;
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ width: 23em;
+}
+
+.adder-dialog-internal {
+ border: 1px solid black;
+ position: absolute;
+ top: 0;
+ left: 0;
+ bottom: 4.5em;
+ width: 25em;
+}
+
+.adder-dialog-external {
+ border: 1px solid black;
+ position: absolute;
+ left: 0;
+ bottom: 0;
+ width: 25em;
+ height: 4em;
+}
diff --git a/install/ui/ipa.js b/install/ui/ipa.js
new file mode 100644
index 000000000..48c116a8c
--- /dev/null
+++ b/install/ui/ipa.js
@@ -0,0 +1,490 @@
+/* Authors:
+ * Pavel Zuna <pzuna@redhat.com>
+ * Adam Young <ayoung@redhat.com>
+ * Endi Dewata <edewata@redhat.com>
+ *
+ * Copyright (C) 2010 Red Hat
+ * see file 'COPYING' for use and warranty information
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+
+/*global $:true, location:true */
+
+var IPA = ( function () {
+
+ var that = {
+ jsonrpc_id: 0
+ };
+
+ that.use_static_files = false;
+ that.json_url = '/ipa/json';
+ if (that.use_static_files){
+ that.json_url = 'test/data';
+ }
+
+ that.ajax_options = {
+ type: 'POST',
+ contentType: 'application/json',
+ dataType: 'json',
+ async: true,
+ processData: false
+ };
+
+ that.messages = {};
+ that.metadata = {};
+ that.whoami = {};
+
+
+ that.entities = [];
+ that.entities_by_name = {};
+
+ that.error_dialog = $('<div/>', {
+ id: 'error_dialog'
+ });
+
+ that.layout = $.bbq.getState('layout');
+ that.layouts_dir = 'layouts';
+
+ that.get_template = function(path) {
+ var layout = that.layout || 'default';
+ return that.layouts_dir+'/'+layout+'/'+path;
+ };
+
+ /* initialize the IPA JSON-RPC helper
+ * arguments:
+ * url - JSON-RPC URL to use (optional) */
+ that.init = function (url, use_static_files, on_success, on_error) {
+ if (url) {
+ that.json_url = url;
+ }
+
+ if (use_static_files) {
+ that.use_static_files = use_static_files;
+ }
+
+ $.ajaxSetup(that.ajax_options);
+
+
+ var startup_batch =
+ [
+ {"method":"json_metadata","params":[[],{}]},
+ {"method":"i18n_messages","params":[[],{}]},
+ {"method":"user_find","params":[[],{
+ "whoami":"true","all":"true"}]},
+ {"method":"env","params":[[],{}]}
+ ];
+
+
+ IPA.cmd('batch', startup_batch, {},
+ function (data, text_status, xhr) {
+ that.metadata = data.result.results[0].metadata;
+ that.messages = data.result.results[1].messages;
+ that.whoami = data.result.results[2].result[0];
+ that.env = data.result.results[3].result;
+ if (on_success) {
+ on_success(data, text_status, xhr);
+ }
+ },
+ on_error,
+ null,
+ 'ipa_init');
+ };
+
+ that.get_entities = function () {
+ return that.entities;
+ };
+
+ that.get_entity = function (name) {
+ return that.entities_by_name[name];
+ };
+
+ that.add_entity = function (entity) {
+ that.entities.push(entity);
+ that.entities_by_name[entity.name] = entity;
+ };
+
+
+ that.show_page = function (entity_name, facet_name) {
+
+ var state = {};
+ state[entity_name + '-facet'] = facet_name;
+ $.bbq.pushState(state);
+ };
+
+ that.switch_and_show_page = function (this_entity, facet_name, pkey) {
+ if (!pkey){
+ that.show_page(this_entity, facet_name);
+ return;
+ }
+ var state = {};
+ state[this_entity+'-pkey'] = pkey;
+ state[this_entity + '-facet'] = facet_name;
+ $.bbq.pushState(state);
+ };
+
+ return that;
+}());
+
+IPA.command = function (spec) {
+
+ spec = spec || {};
+
+ var that = {};
+
+ that.name = spec.name;
+ that.method = spec.method;
+
+ that.args = $.merge([], spec.args || []);
+ that.options = $.extend({}, spec.options || {});
+
+ that.on_success = spec.on_success;
+ that.on_error = spec.on_error;
+
+ that.add_arg = function(arg) {
+ that.args.push(arg);
+ };
+
+ that.set_option = function(name, value) {
+ that.options[name] = value;
+ };
+
+ that.get_option = function(name) {
+ return that.options[name];
+ };
+
+ that.execute = function() {
+ IPA.cmd(
+ that.method,
+ that.args,
+ that.options,
+ that.on_success,
+ that.on_error,
+ null,
+ that.name);
+ };
+
+ that.to_json = function() {
+ var json = {};
+
+ json.method = that.method;
+
+ json.params = [];
+ json.params[0] = that.args || [];
+ json.params[1] = that.options || {};
+
+ return json;
+ };
+
+ that.to_string = function() {
+ var string = that.method.replace(/_/g, '-');
+
+ for (var i=0; i<that.args.length; i++) {
+ string += ' '+that.args[i];
+ }
+
+ for (var name in that.options) {
+ string += ' --'+name+'=\''+that.options[name]+'\'';
+ }
+
+ return string;
+ };
+
+ return that;
+};
+
+IPA.batch_command = function (spec) {
+
+ spec = spec || {};
+
+ spec.method = 'batch';
+
+ var that = IPA.command(spec);
+
+ that.commands = [];
+
+ that.add_command = function(command) {
+ that.commands.push(command);
+ that.add_arg(command.to_json());
+ };
+
+ that.add_commands = function(commands) {
+ for (var i=0; i<commands.length; i++) {
+ that.add_command(commands[i]);
+ }
+ };
+
+ that.execute = function() {
+ IPA.cmd(
+ that.method,
+ that.args,
+ that.options,
+ function(data, text_status, xhr) {
+
+ for (var i=0; i<that.commands.length; i++) {
+ var command = that.commands[i];
+ var result = data.result.results[i];
+
+ if (!result) {
+ if (command.on_error) command.on_error(
+ xhr, text_status,
+ {
+ title: 'Internal Error '+xhr.status,
+ message: result ? xhr.statusText : "Internal error"
+ }
+ );
+
+ } else if (result.error) {
+ if (command.on_error) command.on_error(
+ xhr,
+ text_status,
+ {
+ title: 'IPA Error '+result.error.code,
+ message: result.error.message
+ }
+ );
+
+ } else {
+ if (command.on_success) command.on_success(result, text_status, xhr);
+ }
+ }
+ if (that.on_success) that.on_success(data, text_status, xhr);
+ },
+ function(xhr, text_status, error_thrown) {
+ // TODO: undefined behavior
+ if (that.on_error) {
+ that.on_error(xhr, text_status, error_thrown);
+ }
+ },
+ null,
+ that.name);
+ };
+
+ return that;
+};
+
+/* call an IPA command over JSON-RPC
+ * arguments:
+ * name - name of the command or method if objname is set
+ * args - list of positional arguments, e.g. [username]
+ * options - dict of options, e.g. {givenname: 'Pavel'}
+ * win_callback - function to call if the JSON request succeeds
+ * fail_callback - function to call if the JSON request fails
+ * objname - name of an IPA object (optional) */
+IPA.cmd = function (name, args, options, win_callback, fail_callback, objname, command_name)
+{
+ var default_json_url = '/ipa/json';
+
+ var network_call_count = 0;
+ function display_activity_icon(){
+ network_call_count += 1;
+ $('.network-activity-indicator').css('display','inline');
+ }
+
+ function hide_activity_icon(){
+ network_call_count -= 1;
+
+ if (0 === network_call_count){
+ $('.network-activity-indicator').css('display','none');
+ }
+ }
+
+ function dialog_open(xhr, text_status, error_thrown) {
+ var that = this;
+
+ IPA.error_dialog.dialog({
+ modal: true,
+ width: 400,
+ buttons: {
+ 'Retry': function () {
+ IPA.error_dialog.dialog('close');
+ IPA.cmd(name, args, options, win_callback, fail_callback,
+ objname, command_name);
+ },
+ 'Cancel': function () {
+ IPA.error_dialog.dialog('close');
+ if (fail_callback) {
+ fail_callback.call(that, xhr, text_status,
+ error_thrown);
+ }
+ }
+ }
+ });
+ }
+
+ function ajax_error_handler(xhr, text_status, error_thrown) {
+ IPA.error_dialog.empty();
+ IPA.error_dialog.attr('title', error_thrown.title);
+
+ IPA.error_dialog.append('<p>'+error_thrown.message+'</p>');
+
+ dialog_open.call(this, xhr, text_status, error_thrown);
+ }
+
+ function error_handler(xhr, text_status, error_thrown) {
+ hide_activity_icon();
+ if (!error_thrown) {
+ error_thrown = {
+ name: xhr.responseText || 'Unknown Error',
+ message: xhr.statusText || 'Unknown Error'
+ };
+ }
+
+ if (xhr.status === 401) {
+ error_thrown.name = 'Kerberos ticket no longer valid.';
+ if (IPA.messages && IPA.messages.ajax){
+ error_thrown.message = IPA.messages.ajax["401"];
+ } else {
+ error_thrown.message =
+ "Your kerberos ticket no longer valid. "+
+ "Please run kinit and then click 'retry'. "+
+ "If this is your first time running the IPA Web UI "+
+ "<a href='/ipa/config/unauthorized.html'>"+
+ "follow these directions</a> to configure your browser.";
+ }
+ }
+
+ error_thrown.title = 'AJAX Error: '+error_thrown.name;
+ ajax_error_handler.call(this, xhr, text_status, error_thrown);
+ }
+
+
+ function http_error_handler(xhr, text_status, error_thrown) {
+ IPA.error_dialog.empty();
+ IPA.error_dialog.attr('title', error_thrown.title);
+
+ IPA.error_dialog.append('<p>URL: '+this.url+'</p>');
+ IPA.error_dialog.append('<p>'+error_thrown.message+'</p>');
+
+ dialog_open.call(this, xhr, text_status, error_thrown);
+ }
+
+ //Think this should be removed
+ function alt_error_handler(xhr, text_status, error_thrown) {
+ hide_activity_icon();
+ IPA.error_dialog.empty();
+ IPA.error_dialog.attr('title', error_thrown.title);
+
+ IPA.error_dialog.append('<p>'+error_thrown.message+'</p>');
+
+ dialog_open.call(this, xhr, text_status, error_thrown);
+ }
+
+
+ function success_handler(data, text_status, xhr) {
+ hide_activity_icon();
+ if (!data) {
+ var error_thrown = {
+ title: 'HTTP Error '+xhr.status,
+ message: data ? xhr.statusText : "No response"
+ };
+ http_error_handler.call(this, xhr, text_status, error_thrown);
+
+ } else if (data.error) {
+ error_handler.call(this, xhr, text_status, /* error_thrown */ {
+ title: 'IPA Error '+data.error.code,
+ message: data.error.message
+ });
+
+ } else if (win_callback) {
+ win_callback.call(this, data, text_status, xhr);
+ }
+ }
+
+ IPA.jsonrpc_id += 1;
+ var id = IPA.jsonrpc_id;
+
+ var method_name = name;
+
+ if (objname){
+ method_name = objname + '_' + name;
+ }
+
+ var url = IPA.json_url;
+
+ if (IPA.use_static_files){
+ if (command_name) {
+ url += '/' + command_name + '.json';
+ } else {
+ url += '/' + method_name + '.json';
+ }
+ }
+ var data = {
+ method: method_name,
+ params: [args, options],
+ id: id
+ };
+
+ var request = {
+ url: url,
+ data: JSON.stringify(data),
+ success: success_handler,
+ error: error_handler
+ };
+ display_activity_icon();
+ $.ajax(request);
+
+ return (id);
+};
+
+
+/* helper function used to retrieve information about an attribute */
+IPA.get_param_info = function(obj_name, attr)
+{
+ var obj = IPA.metadata[obj_name];
+ if (!obj) {
+ return null;
+ }
+
+ var takes_params = obj.takes_params;
+ if (!takes_params) {
+ return (null);
+
+ }
+ for (var i = 0; i < takes_params.length; i += 1) {
+ if (takes_params[i].name === attr){
+ return (takes_params[i]);
+ }
+ }
+
+ return (null);
+};
+
+/* helper function used to retrieve attr name with members of type `member` */
+IPA.get_member_attribute = function (obj_name, member)
+{
+ var obj = IPA.metadata[obj_name];
+ if (!obj) {
+ return null;
+ }
+ var attribute_members = obj.attribute_members;
+ for (var a in attribute_members) {
+ var objs = attribute_members[a];
+ for (var i = 0; i < objs.length; i += 1) {
+ if (objs[i] === member){
+ return a;
+ }
+ }
+ }
+ return null;
+
+};
+
+
+IPA.create_network_spinner = function(){
+ return $('<span />',{
+ 'class':'network-activity-indicator',
+ html: '<img src="spinner_small.gif" />'});
+};
diff --git a/install/ui/ipa_logo_180x50.png b/install/ui/ipa_logo_180x50.png
new file mode 100644
index 000000000..defa78cfd
--- /dev/null
+++ b/install/ui/ipa_logo_180x50.png
Binary files differ
diff --git a/install/ui/ipalogo.png b/install/ui/ipalogo.png
new file mode 100644
index 000000000..62185c1b0
--- /dev/null
+++ b/install/ui/ipalogo.png
Binary files differ
diff --git a/install/ui/jquery-ui.css b/install/ui/jquery-ui.css
new file mode 100644
index 000000000..01c3ec90e
--- /dev/null
+++ b/install/ui/jquery-ui.css
@@ -0,0 +1,572 @@
+/*
+ * jQuery UI CSS Framework @VERSION
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Theming/API
+ */
+
+/* Layout helpers
+----------------------------------*/
+.ui-helper-hidden { display: none; }
+.ui-helper-hidden-accessible { position: absolute; left: -99999999px; }
+.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
+.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
+.ui-helper-clearfix { display: inline-block; }
+/* required comment for clearfix to work in Opera \*/
+* html .ui-helper-clearfix { height:1%; }
+.ui-helper-clearfix { display:block; }
+/* end clearfix */
+.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
+
+
+/* Interaction Cues
+----------------------------------*/
+.ui-state-disabled { cursor: default !important; }
+
+
+/* Icons
+----------------------------------*/
+
+/* states and images */
+.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
+
+
+/* Misc visuals
+----------------------------------*/
+
+/* Overlays */
+.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
+
+
+/*
+ * jQuery UI CSS Framework @VERSION
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Theming/API
+ *
+ * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana,%20Arial,%20sans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=0px&bgColorHeader=333333&bgTextureHeader=14_loop.png&bgImgOpacityHeader=8&borderColorHeader=a3a3a3&fcHeader=eeeeee&iconColorHeader=bbbbbb&bgColorContent=f9f9f9&bgTextureContent=04_highlight_hard.png&bgImgOpacityContent=100&borderColorContent=cccccc&fcContent=222222&iconColorContent=222222&bgColorDefault=111111&bgTextureDefault=02_glass.png&bgImgOpacityDefault=40&borderColorDefault=777777&fcDefault=e3e3e3&iconColorDefault=ededed&bgColorHover=1c1c1c&bgTextureHover=02_glass.png&bgImgOpacityHover=55&borderColorHover=000000&fcHover=ffffff&iconColorHover=ffffff&bgColorActive=ffffff&bgTextureActive=01_flat.png&bgImgOpacityActive=65&borderColorActive=cccccc&fcActive=222222&iconColorActive=222222&bgColorHighlight=ffeb80&bgTextureHighlight=06_inset_hard.png&bgImgOpacityHighlight=55&borderColorHighlight=ffde2e&fcHighlight=363636&iconColorHighlight=4ca300&bgColorError=cd0a0a&bgTextureError=06_inset_hard.png&bgImgOpacityError=45&borderColorError=9e0505&fcError=ffffff&iconColorError=ffcf29&bgColorOverlay=aaaaaa&bgTextureOverlay=04_highlight_hard.png&bgImgOpacityOverlay=40&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=03_highlight_soft.png&bgImgOpacityShadow=50&opacityShadow=20&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
+ */
+
+
+/* Component containers
+----------------------------------*/
+.ui-widget { font-family: Verdana, Arial, sans-serif; font-size: 1.1em; }
+.ui-widget .ui-widget { font-size: 1em; }
+.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana, Arial, sans-serif; font-size: 1em; }
+.ui-widget-content { border: 1px solid #cccccc; background: #f9f9f9 url(ui-bg_highlight-hard_100_f9f9f9_1x100.png) 50% top repeat-x; color: #222222; }
+.ui-widget-content a { color: #222222; }
+.ui-widget-header { border: 1px solid #a3a3a3; background: #333333 url(ui-bg_loop_8_333333_21x21.png) 50% 50% repeat; color: #eeeeee; font-weight: bold; }
+.ui-widget-header a { color: #eeeeee; }
+
+/* Interaction states
+----------------------------------*/
+.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #777777; background: #111111 url(ui-bg_glass_40_111111_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #e3e3e3; }
+.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #e3e3e3; text-decoration: none; }
+.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #000000; background: #1c1c1c url(ui-bg_glass_55_1c1c1c_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #ffffff; }
+.ui-state-hover a, .ui-state-hover a:hover { color: #ffffff; text-decoration: none; }
+.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #cccccc; background: #ffffff url(ui-bg_flat_65_ffffff_40x100.png) 50% 50% repeat-x; font-weight: normal; color: #222222; }
+.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #222222; text-decoration: none; }
+.ui-widget :active { outline: none; }
+
+/* Interaction Cues
+----------------------------------*/
+.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #ffde2e; background: #ffeb80 url(ui-bg_inset-hard_55_ffeb80_1x100.png) 50% bottom repeat-x; color: #363636; }
+.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; }
+.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #9e0505; background: #cd0a0a url(ui-bg_inset-hard_45_cd0a0a_1x100.png) 50% bottom repeat-x; color: #ffffff; }
+.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #ffffff; }
+.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #ffffff; }
+.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
+.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
+.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
+
+/* Icons
+----------------------------------*/
+
+/* states and images */
+.ui-icon { width: 16px; height: 16px; background-image: url(ui-icons_222222_256x240.png); }
+.ui-widget-content .ui-icon {background-image: url(ui-icons_222222_256x240.png); }
+.ui-widget-header .ui-icon {background-image: url(ui-icons_bbbbbb_256x240.png); }
+.ui-state-default .ui-icon { background-image: url(ui-icons_ededed_256x240.png); }
+.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(ui-icons_ffffff_256x240.png); }
+.ui-state-active .ui-icon {background-image: url(ui-icons_222222_256x240.png); }
+.ui-state-highlight .ui-icon {background-image: url(ui-icons_4ca300_256x240.png); }
+.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(ui-icons_ffcf29_256x240.png); }
+
+/* positioning */
+.ui-icon-carat-1-n { background-position: 0 0; }
+.ui-icon-carat-1-ne { background-position: -16px 0; }
+.ui-icon-carat-1-e { background-position: -32px 0; }
+.ui-icon-carat-1-se { background-position: -48px 0; }
+.ui-icon-carat-1-s { background-position: -64px 0; }
+.ui-icon-carat-1-sw { background-position: -80px 0; }
+.ui-icon-carat-1-w { background-position: -96px 0; }
+.ui-icon-carat-1-nw { background-position: -112px 0; }
+.ui-icon-carat-2-n-s { background-position: -128px 0; }
+.ui-icon-carat-2-e-w { background-position: -144px 0; }
+.ui-icon-triangle-1-n { background-position: 0 -16px; }
+.ui-icon-triangle-1-ne { background-position: -16px -16px; }
+.ui-icon-triangle-1-e { background-position: -32px -16px; }
+.ui-icon-triangle-1-se { background-position: -48px -16px; }
+.ui-icon-triangle-1-s { background-position: -64px -16px; }
+.ui-icon-triangle-1-sw { background-position: -80px -16px; }
+.ui-icon-triangle-1-w { background-position: -96px -16px; }
+.ui-icon-triangle-1-nw { background-position: -112px -16px; }
+.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
+.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
+.ui-icon-arrow-1-n { background-position: 0 -32px; }
+.ui-icon-arrow-1-ne { background-position: -16px -32px; }
+.ui-icon-arrow-1-e { background-position: -32px -32px; }
+.ui-icon-arrow-1-se { background-position: -48px -32px; }
+.ui-icon-arrow-1-s { background-position: -64px -32px; }
+.ui-icon-arrow-1-sw { background-position: -80px -32px; }
+.ui-icon-arrow-1-w { background-position: -96px -32px; }
+.ui-icon-arrow-1-nw { background-position: -112px -32px; }
+.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
+.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
+.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
+.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
+.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
+.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
+.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
+.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
+.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
+.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
+.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
+.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
+.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
+.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
+.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
+.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
+.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
+.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
+.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
+.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
+.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
+.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
+.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
+.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
+.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
+.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
+.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
+.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
+.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
+.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
+.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
+.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
+.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
+.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
+.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
+.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
+.ui-icon-arrow-4 { background-position: 0 -80px; }
+.ui-icon-arrow-4-diag { background-position: -16px -80px; }
+.ui-icon-extlink { background-position: -32px -80px; }
+.ui-icon-newwin { background-position: -48px -80px; }
+.ui-icon-refresh { background-position: -64px -80px; }
+.ui-icon-shuffle { background-position: -80px -80px; }
+.ui-icon-transfer-e-w { background-position: -96px -80px; }
+.ui-icon-transferthick-e-w { background-position: -112px -80px; }
+.ui-icon-folder-collapsed { background-position: 0 -96px; }
+.ui-icon-folder-open { background-position: -16px -96px; }
+.ui-icon-document { background-position: -32px -96px; }
+.ui-icon-document-b { background-position: -48px -96px; }
+.ui-icon-note { background-position: -64px -96px; }
+.ui-icon-mail-closed { background-position: -80px -96px; }
+.ui-icon-mail-open { background-position: -96px -96px; }
+.ui-icon-suitcase { background-position: -112px -96px; }
+.ui-icon-comment { background-position: -128px -96px; }
+.ui-icon-person { background-position: -144px -96px; }
+.ui-icon-print { background-position: -160px -96px; }
+.ui-icon-trash { background-position: -176px -96px; }
+.ui-icon-locked { background-position: -192px -96px; }
+.ui-icon-unlocked { background-position: -208px -96px; }
+.ui-icon-bookmark { background-position: -224px -96px; }
+.ui-icon-tag { background-position: -240px -96px; }
+.ui-icon-home { background-position: 0 -112px; }
+.ui-icon-flag { background-position: -16px -112px; }
+.ui-icon-calendar { background-position: -32px -112px; }
+.ui-icon-cart { background-position: -48px -112px; }
+.ui-icon-pencil { background-position: -64px -112px; }
+.ui-icon-clock { background-position: -80px -112px; }
+.ui-icon-disk { background-position: -96px -112px; }
+.ui-icon-calculator { background-position: -112px -112px; }
+.ui-icon-zoomin { background-position: -128px -112px; }
+.ui-icon-zoomout { background-position: -144px -112px; }
+.ui-icon-search { background-position: -160px -112px; }
+.ui-icon-wrench { background-position: -176px -112px; }
+.ui-icon-gear { background-position: -192px -112px; }
+.ui-icon-heart { background-position: -208px -112px; }
+.ui-icon-star { background-position: -224px -112px; }
+.ui-icon-link { background-position: -240px -112px; }
+.ui-icon-cancel { background-position: 0 -128px; }
+.ui-icon-plus { background-position: -16px -128px; }
+.ui-icon-plusthick { background-position: -32px -128px; }
+.ui-icon-minus { background-position: -48px -128px; }
+.ui-icon-minusthick { background-position: -64px -128px; }
+.ui-icon-close { background-position: -80px -128px; }
+.ui-icon-closethick { background-position: -96px -128px; }
+.ui-icon-key { background-position: -112px -128px; }
+.ui-icon-lightbulb { background-position: -128px -128px; }
+.ui-icon-scissors { background-position: -144px -128px; }
+.ui-icon-clipboard { background-position: -160px -128px; }
+.ui-icon-copy { background-position: -176px -128px; }
+.ui-icon-contact { background-position: -192px -128px; }
+.ui-icon-image { background-position: -208px -128px; }
+.ui-icon-video { background-position: -224px -128px; }
+.ui-icon-script { background-position: -240px -128px; }
+.ui-icon-alert { background-position: 0 -144px; }
+.ui-icon-info { background-position: -16px -144px; }
+.ui-icon-notice { background-position: -32px -144px; }
+.ui-icon-help { background-position: -48px -144px; }
+.ui-icon-check { background-position: -64px -144px; }
+.ui-icon-bullet { background-position: -80px -144px; }
+.ui-icon-radio-off { background-position: -96px -144px; }
+.ui-icon-radio-on { background-position: -112px -144px; }
+.ui-icon-pin-w { background-position: -128px -144px; }
+.ui-icon-pin-s { background-position: -144px -144px; }
+.ui-icon-play { background-position: 0 -160px; }
+.ui-icon-pause { background-position: -16px -160px; }
+.ui-icon-seek-next { background-position: -32px -160px; }
+.ui-icon-seek-prev { background-position: -48px -160px; }
+.ui-icon-seek-end { background-position: -64px -160px; }
+.ui-icon-seek-start { background-position: -80px -160px; }
+/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
+.ui-icon-seek-first { background-position: -80px -160px; }
+.ui-icon-stop { background-position: -96px -160px; }
+.ui-icon-eject { background-position: -112px -160px; }
+.ui-icon-volume-off { background-position: -128px -160px; }
+.ui-icon-volume-on { background-position: -144px -160px; }
+.ui-icon-power { background-position: 0 -176px; }
+.ui-icon-signal-diag { background-position: -16px -176px; }
+.ui-icon-signal { background-position: -32px -176px; }
+.ui-icon-battery-0 { background-position: -48px -176px; }
+.ui-icon-battery-1 { background-position: -64px -176px; }
+.ui-icon-battery-2 { background-position: -80px -176px; }
+.ui-icon-battery-3 { background-position: -96px -176px; }
+.ui-icon-circle-plus { background-position: 0 -192px; }
+.ui-icon-circle-minus { background-position: -16px -192px; }
+.ui-icon-circle-close { background-position: -32px -192px; }
+.ui-icon-circle-triangle-e { background-position: -48px -192px; }
+.ui-icon-circle-triangle-s { background-position: -64px -192px; }
+.ui-icon-circle-triangle-w { background-position: -80px -192px; }
+.ui-icon-circle-triangle-n { background-position: -96px -192px; }
+.ui-icon-circle-arrow-e { background-position: -112px -192px; }
+.ui-icon-circle-arrow-s { background-position: -128px -192px; }
+.ui-icon-circle-arrow-w { background-position: -144px -192px; }
+.ui-icon-circle-arrow-n { background-position: -160px -192px; }
+.ui-icon-circle-zoomin { background-position: -176px -192px; }
+.ui-icon-circle-zoomout { background-position: -192px -192px; }
+.ui-icon-circle-check { background-position: -208px -192px; }
+.ui-icon-circlesmall-plus { background-position: 0 -208px; }
+.ui-icon-circlesmall-minus { background-position: -16px -208px; }
+.ui-icon-circlesmall-close { background-position: -32px -208px; }
+.ui-icon-squaresmall-plus { background-position: -48px -208px; }
+.ui-icon-squaresmall-minus { background-position: -64px -208px; }
+.ui-icon-squaresmall-close { background-position: -80px -208px; }
+.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
+.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
+.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
+.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
+.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
+.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
+
+
+/* Misc visuals
+----------------------------------*/
+
+/* Corner radius */
+.ui-corner-tl { -moz-border-radius-topleft: 0px; -webkit-border-top-left-radius: 0px; border-top-left-radius: 0px; }
+.ui-corner-tr { -moz-border-radius-topright: 0px; -webkit-border-top-right-radius: 0px; border-top-right-radius: 0px; }
+.ui-corner-bl { -moz-border-radius-bottomleft: 0px; -webkit-border-bottom-left-radius: 0px; border-bottom-left-radius: 0px; }
+.ui-corner-br { -moz-border-radius-bottomright: 0px; -webkit-border-bottom-right-radius: 0px; border-bottom-right-radius: 0px; }
+.ui-corner-top { -moz-border-radius-topleft: 0px; -webkit-border-top-left-radius: 0px; border-top-left-radius: 0px; -moz-border-radius-topright: 0px; -webkit-border-top-right-radius: 0px; border-top-right-radius: 0px; }
+.ui-corner-bottom { -moz-border-radius-bottomleft: 0px; -webkit-border-bottom-left-radius: 0px; border-bottom-left-radius: 0px; -moz-border-radius-bottomright: 0px; -webkit-border-bottom-right-radius: 0px; border-bottom-right-radius: 0px; }
+.ui-corner-right { -moz-border-radius-topright: 0px; -webkit-border-top-right-radius: 0px; border-top-right-radius: 0px; -moz-border-radius-bottomright: 0px; -webkit-border-bottom-right-radius: 0px; border-bottom-right-radius: 0px; }
+.ui-corner-left { -moz-border-radius-topleft: 0px; -webkit-border-top-left-radius: 0px; border-top-left-radius: 0px; -moz-border-radius-bottomleft: 0px; -webkit-border-bottom-left-radius: 0px; border-bottom-left-radius: 0px; }
+.ui-corner-all { -moz-border-radius: 0px; -webkit-border-radius: 0px; border-radius: 0px; }
+
+/* Overlays */
+.ui-widget-overlay { background: #aaaaaa url(ui-bg_highlight-hard_40_aaaaaa_1x100.png) 50% top repeat-x; opacity: .30;filter:Alpha(Opacity=30); }
+.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(ui-bg_highlight-soft_50_aaaaaa_1x100.png) 50% top repeat-x; opacity: .20;filter:Alpha(Opacity=20); -moz-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }/*
+ * jQuery UI Resizable @VERSION
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Resizable#theming
+ */
+.ui-resizable { position: relative;}
+.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block;}
+.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
+.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; }
+.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; }
+.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; }
+.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; }
+.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
+.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
+.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
+.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/*
+ * jQuery UI Selectable @VERSION
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Selectable#theming
+ */
+.ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; }
+/*
+ * jQuery UI Accordion @VERSION
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Accordion#theming
+ */
+/* IE/Win - Fix animation bug - #4615 */
+.ui-accordion { width: 100%; }
+.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; }
+.ui-accordion .ui-accordion-li-fix { display: inline; }
+.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; }
+.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em .7em; }
+.ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; }
+.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
+.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; }
+.ui-accordion .ui-accordion-content-active { display: block; }/*
+ * jQuery UI Autocomplete @VERSION
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Autocomplete#theming
+ */
+.ui-autocomplete { position: absolute; cursor: default; }
+
+/* workarounds */
+* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */
+
+/*
+ * jQuery UI Menu @VERSION
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Menu#theming
+ */
+.ui-menu {
+ list-style:none;
+ padding: 2px;
+ margin: 0;
+ display:block;
+ float: left;
+}
+.ui-menu .ui-menu {
+ margin-top: -3px;
+}
+.ui-menu .ui-menu-item {
+ margin:0;
+ padding: 0;
+ zoom: 1;
+ float: left;
+ clear: left;
+ width: 100%;
+}
+.ui-menu .ui-menu-item a {
+ text-decoration:none;
+ display:block;
+ padding:.2em .4em;
+ line-height:1.5;
+ zoom:1;
+}
+.ui-menu .ui-menu-item a.ui-state-hover,
+.ui-menu .ui-menu-item a.ui-state-active {
+ font-weight: normal;
+ margin: -1px;
+}
+/*
+ * jQuery UI Button @VERSION
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Button#theming
+ */
+.ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; text-decoration: none !important; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */
+.ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */
+button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */
+.ui-button-icons-only { width: 3.4em; }
+button.ui-button-icons-only { width: 3.7em; }
+
+/*button text element */
+.ui-button .ui-button-text { display: block; line-height: 1.4; }
+.ui-button-text-only .ui-button-text { padding: .4em 1em; }
+.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; }
+.ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; }
+.ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.1em .4em 1em; }
+.ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; }
+/* no icon support for input elements, provide padding by default */
+input.ui-button { padding: .4em 1em; }
+
+/*button icon element(s) */
+.ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; }
+.ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; }
+.ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; }
+.ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
+.ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
+
+/*button sets*/
+.ui-buttonset { margin-right: 7px; }
+.ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; }
+
+/* workarounds */
+button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */
+/*
+ * jQuery UI Dialog @VERSION
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Dialog#theming
+ */
+.ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; }
+.ui-dialog .ui-dialog-titlebar { padding: .5em 1em .3em; position: relative; }
+.ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .2em 0; }
+.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
+.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
+.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; }
+.ui-dialog .ui-dialog-content { position: relative; border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; }
+.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
+.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; }
+.ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; }
+.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
+.ui-draggable .ui-dialog-titlebar { cursor: move; }
+/*
+ * jQuery UI Slider @VERSION
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Slider#theming
+ */
+.ui-slider { position: relative; text-align: left; }
+.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
+.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; }
+
+.ui-slider-horizontal { height: .8em; }
+.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
+.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
+.ui-slider-horizontal .ui-slider-range-min { left: 0; }
+.ui-slider-horizontal .ui-slider-range-max { right: 0; }
+
+.ui-slider-vertical { width: .8em; height: 100px; }
+.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
+.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
+.ui-slider-vertical .ui-slider-range-min { bottom: 0; }
+.ui-slider-vertical .ui-slider-range-max { top: 0; }/*
+ * jQuery UI Tabs @VERSION
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Tabs#theming
+ */
+.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
+.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; }
+.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; }
+.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; }
+.ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; }
+.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; }
+.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
+.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; }
+.ui-tabs .ui-tabs-hide { display: none !important; }
+/*
+ * jQuery UI Datepicker @VERSION
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Datepicker#theming
+ */
+.ui-datepicker { width: 17em; padding: .2em .2em 0; }
+.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
+.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
+.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
+.ui-datepicker .ui-datepicker-prev { left:2px; }
+.ui-datepicker .ui-datepicker-next { right:2px; }
+.ui-datepicker .ui-datepicker-prev-hover { left:1px; }
+.ui-datepicker .ui-datepicker-next-hover { right:1px; }
+.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; }
+.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
+.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; }
+.ui-datepicker select.ui-datepicker-month-year {width: 100%;}
+.ui-datepicker select.ui-datepicker-month,
+.ui-datepicker select.ui-datepicker-year { width: 49%;}
+.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
+.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; }
+.ui-datepicker td { border: 0; padding: 1px; }
+.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
+.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
+.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
+.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
+
+/* with multiple calendars */
+.ui-datepicker.ui-datepicker-multi { width:auto; }
+.ui-datepicker-multi .ui-datepicker-group { float:left; }
+.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
+.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
+.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
+.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
+.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
+.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
+.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
+.ui-datepicker-row-break { clear:both; width:100%; }
+
+/* RTL support */
+.ui-datepicker-rtl { direction: rtl; }
+.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
+.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
+.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
+.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
+.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
+.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
+.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
+.ui-datepicker-rtl .ui-datepicker-group { float:right; }
+.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
+.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
+
+/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
+.ui-datepicker-cover {
+ display: none; /*sorry for IE5*/
+ display/**/: block; /*sorry for IE5*/
+ position: absolute; /*must have*/
+ z-index: -1; /*must have*/
+ filter: mask(); /*must have*/
+ top: -4px; /*must have*/
+ left: -4px; /*must have*/
+ width: 200px; /*must have*/
+ height: 200px; /*must have*/
+}/*
+ * jQuery UI Progressbar @VERSION
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Progressbar#theming
+ */
+.ui-progressbar { height:2em; text-align: left; }
+.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; } \ No newline at end of file
diff --git a/install/ui/jquery-ui.js b/install/ui/jquery-ui.js
new file mode 100644
index 000000000..b1cac98b6
--- /dev/null
+++ b/install/ui/jquery-ui.js
@@ -0,0 +1,763 @@
+/*!
+ * jQuery UI 1.8.4
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI
+ */
+(function(c,j){function k(a){return!c(a).parents().andSelf().filter(function(){return c.curCSS(this,"visibility")==="hidden"||c.expr.filters.hidden(this)}).length}c.ui=c.ui||{};if(!c.ui.version){c.extend(c.ui,{version:"1.8.4",plugin:{add:function(a,b,d){a=c.ui[a].prototype;for(var e in d){a.plugins[e]=a.plugins[e]||[];a.plugins[e].push([b,d[e]])}},call:function(a,b,d){if((b=a.plugins[b])&&a.element[0].parentNode)for(var e=0;e<b.length;e++)a.options[b[e][0]]&&b[e][1].apply(a.element,d)}},contains:function(a,
+b){return document.compareDocumentPosition?a.compareDocumentPosition(b)&16:a!==b&&a.contains(b)},hasScroll:function(a,b){if(c(a).css("overflow")==="hidden")return false;b=b&&b==="left"?"scrollLeft":"scrollTop";var d=false;if(a[b]>0)return true;a[b]=1;d=a[b]>0;a[b]=0;return d},isOverAxis:function(a,b,d){return a>b&&a<b+d},isOver:function(a,b,d,e,h,i){return c.ui.isOverAxis(a,d,h)&&c.ui.isOverAxis(b,e,i)},keyCode:{ALT:18,BACKSPACE:8,CAPS_LOCK:20,COMMA:188,COMMAND:91,COMMAND_LEFT:91,COMMAND_RIGHT:93,
+CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,MENU:93,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38,WINDOWS:91}});c.fn.extend({_focus:c.fn.focus,focus:function(a,b){return typeof a==="number"?this.each(function(){var d=this;setTimeout(function(){c(d).focus();b&&b.call(d)},a)}):this._focus.apply(this,arguments)},enableSelection:function(){return this.attr("unselectable",
+"off").css("MozUserSelect","")},disableSelection:function(){return this.attr("unselectable","on").css("MozUserSelect","none")},scrollParent:function(){var a;a=c.browser.msie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(c.curCSS(this,"position",1))&&/(auto|scroll)/.test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(c.curCSS(this,
+"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0);return/fixed/.test(this.css("position"))||!a.length?c(document):a},zIndex:function(a){if(a!==j)return this.css("zIndex",a);if(this.length){a=c(this[0]);for(var b;a.length&&a[0]!==document;){b=a.css("position");if(b==="absolute"||b==="relative"||b==="fixed"){b=parseInt(a.css("zIndex"));if(!isNaN(b)&&b!=0)return b}a=a.parent()}}return 0}});c.each(["Width","Height"],function(a,b){function d(f,g,l,m){c.each(e,function(){g-=
+parseFloat(c.curCSS(f,"padding"+this,true))||0;if(l)g-=parseFloat(c.curCSS(f,"border"+this+"Width",true))||0;if(m)g-=parseFloat(c.curCSS(f,"margin"+this,true))||0});return g}var e=b==="Width"?["Left","Right"]:["Top","Bottom"],h=b.toLowerCase(),i={innerWidth:c.fn.innerWidth,innerHeight:c.fn.innerHeight,outerWidth:c.fn.outerWidth,outerHeight:c.fn.outerHeight};c.fn["inner"+b]=function(f){if(f===j)return i["inner"+b].call(this);return this.each(function(){c.style(this,h,d(this,f)+"px")})};c.fn["outer"+
+b]=function(f,g){if(typeof f!=="number")return i["outer"+b].call(this,f);return this.each(function(){c.style(this,h,d(this,f,true,g)+"px")})}});c.extend(c.expr[":"],{data:function(a,b,d){return!!c.data(a,d[3])},focusable:function(a){var b=a.nodeName.toLowerCase(),d=c.attr(a,"tabindex");if("area"===b){b=a.parentNode;d=b.name;if(!a.href||!d||b.nodeName.toLowerCase()!=="map")return false;a=c("img[usemap=#"+d+"]")[0];return!!a&&k(a)}return(/input|select|textarea|button|object/.test(b)?!a.disabled:"a"==
+b?a.href||!isNaN(d):!isNaN(d))&&k(a)},tabbable:function(a){var b=c.attr(a,"tabindex");return(isNaN(b)||b>=0)&&c(a).is(":focusable")}})}})(jQuery);
+;/*!
+ * jQuery UI Widget 1.8.4
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Widget
+ */
+(function(b,j){var k=b.fn.remove;b.fn.remove=function(a,c){return this.each(function(){if(!c)if(!a||b.filter(a,[this]).length)b("*",this).add([this]).each(function(){b(this).triggerHandler("remove")});return k.call(b(this),a,c)})};b.widget=function(a,c,d){var e=a.split(".")[0],f;a=a.split(".")[1];f=e+"-"+a;if(!d){d=c;c=b.Widget}b.expr[":"][f]=function(h){return!!b.data(h,a)};b[e]=b[e]||{};b[e][a]=function(h,g){arguments.length&&this._createWidget(h,g)};c=new c;c.options=b.extend(true,{},c.options);
+b[e][a].prototype=b.extend(true,c,{namespace:e,widgetName:a,widgetEventPrefix:b[e][a].prototype.widgetEventPrefix||a,widgetBaseClass:f},d);b.widget.bridge(a,b[e][a])};b.widget.bridge=function(a,c){b.fn[a]=function(d){var e=typeof d==="string",f=Array.prototype.slice.call(arguments,1),h=this;d=!e&&f.length?b.extend.apply(null,[true,d].concat(f)):d;if(e&&d.substring(0,1)==="_")return h;e?this.each(function(){var g=b.data(this,a),i=g&&b.isFunction(g[d])?g[d].apply(g,f):g;if(i!==g&&i!==j){h=i;return false}}):
+this.each(function(){var g=b.data(this,a);if(g){d&&g.option(d);g._init()}else b.data(this,a,new c(d,this))});return h}};b.Widget=function(a,c){arguments.length&&this._createWidget(a,c)};b.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",options:{disabled:false},_createWidget:function(a,c){b.data(c,this.widgetName,this);this.element=b(c);this.options=b.extend(true,{},this.options,b.metadata&&b.metadata.get(c)[this.widgetName],a);var d=this;this.element.bind("remove."+this.widgetName,function(){d.destroy()});
+this._create();this._init()},_create:function(){},_init:function(){},destroy:function(){this.element.unbind("."+this.widgetName).removeData(this.widgetName);this.widget().unbind("."+this.widgetName).removeAttr("aria-disabled").removeClass(this.widgetBaseClass+"-disabled ui-state-disabled")},widget:function(){return this.element},option:function(a,c){var d=a,e=this;if(arguments.length===0)return b.extend({},e.options);if(typeof a==="string"){if(c===j)return this.options[a];d={};d[a]=c}b.each(d,function(f,
+h){e._setOption(f,h)});return e},_setOption:function(a,c){this.options[a]=c;if(a==="disabled")this.widget()[c?"addClass":"removeClass"](this.widgetBaseClass+"-disabled ui-state-disabled").attr("aria-disabled",c);return this},enable:function(){return this._setOption("disabled",false)},disable:function(){return this._setOption("disabled",true)},_trigger:function(a,c,d){var e=this.options[a];c=b.Event(c);c.type=(a===this.widgetEventPrefix?a:this.widgetEventPrefix+a).toLowerCase();d=d||{};if(c.originalEvent){a=
+b.event.props.length;for(var f;a;){f=b.event.props[--a];c[f]=c.originalEvent[f]}}this.element.trigger(c,d);return!(b.isFunction(e)&&e.call(this.element[0],c,d)===false||c.isDefaultPrevented())}}})(jQuery);
+;/*!
+ * jQuery UI Mouse 1.8.4
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Mouse
+ *
+ * Depends:
+ * jquery.ui.widget.js
+ */
+(function(c){c.widget("ui.mouse",{options:{cancel:":input,option",distance:1,delay:0},_mouseInit:function(){var a=this;this.element.bind("mousedown."+this.widgetName,function(b){return a._mouseDown(b)}).bind("click."+this.widgetName,function(b){if(a._preventClickEvent){a._preventClickEvent=false;b.stopImmediatePropagation();return false}});this.started=false},_mouseDestroy:function(){this.element.unbind("."+this.widgetName)},_mouseDown:function(a){a.originalEvent=a.originalEvent||{};if(!a.originalEvent.mouseHandled){this._mouseStarted&&
+this._mouseUp(a);this._mouseDownEvent=a;var b=this,e=a.which==1,f=typeof this.options.cancel=="string"?c(a.target).parents().add(a.target).filter(this.options.cancel).length:false;if(!e||f||!this._mouseCapture(a))return true;this.mouseDelayMet=!this.options.delay;if(!this.mouseDelayMet)this._mouseDelayTimer=setTimeout(function(){b.mouseDelayMet=true},this.options.delay);if(this._mouseDistanceMet(a)&&this._mouseDelayMet(a)){this._mouseStarted=this._mouseStart(a)!==false;if(!this._mouseStarted){a.preventDefault();
+return true}}this._mouseMoveDelegate=function(d){return b._mouseMove(d)};this._mouseUpDelegate=function(d){return b._mouseUp(d)};c(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate);c.browser.safari||a.preventDefault();return a.originalEvent.mouseHandled=true}},_mouseMove:function(a){if(c.browser.msie&&!a.button)return this._mouseUp(a);if(this._mouseStarted){this._mouseDrag(a);return a.preventDefault()}if(this._mouseDistanceMet(a)&&
+this._mouseDelayMet(a))(this._mouseStarted=this._mouseStart(this._mouseDownEvent,a)!==false)?this._mouseDrag(a):this._mouseUp(a);return!this._mouseStarted},_mouseUp:function(a){c(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate);if(this._mouseStarted){this._mouseStarted=false;this._preventClickEvent=a.target==this._mouseDownEvent.target;this._mouseStop(a)}return false},_mouseDistanceMet:function(a){return Math.max(Math.abs(this._mouseDownEvent.pageX-
+a.pageX),Math.abs(this._mouseDownEvent.pageY-a.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return true}})})(jQuery);
+;/*
+ * jQuery UI Position 1.8.4
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Position
+ */
+(function(c){c.ui=c.ui||{};var m=/left|center|right/,n=/top|center|bottom/,p=c.fn.position,q=c.fn.offset;c.fn.position=function(a){if(!a||!a.of)return p.apply(this,arguments);a=c.extend({},a);var b=c(a.of),d=(a.collision||"flip").split(" "),e=a.offset?a.offset.split(" "):[0,0],g,h,i;if(a.of.nodeType===9){g=b.width();h=b.height();i={top:0,left:0}}else if(a.of.scrollTo&&a.of.document){g=b.width();h=b.height();i={top:b.scrollTop(),left:b.scrollLeft()}}else if(a.of.preventDefault){a.at="left top";g=h=
+0;i={top:a.of.pageY,left:a.of.pageX}}else{g=b.outerWidth();h=b.outerHeight();i=b.offset()}c.each(["my","at"],function(){var f=(a[this]||"").split(" ");if(f.length===1)f=m.test(f[0])?f.concat(["center"]):n.test(f[0])?["center"].concat(f):["center","center"];f[0]=m.test(f[0])?f[0]:"center";f[1]=n.test(f[1])?f[1]:"center";a[this]=f});if(d.length===1)d[1]=d[0];e[0]=parseInt(e[0],10)||0;if(e.length===1)e[1]=e[0];e[1]=parseInt(e[1],10)||0;if(a.at[0]==="right")i.left+=g;else if(a.at[0]==="center")i.left+=
+g/2;if(a.at[1]==="bottom")i.top+=h;else if(a.at[1]==="center")i.top+=h/2;i.left+=e[0];i.top+=e[1];return this.each(function(){var f=c(this),k=f.outerWidth(),l=f.outerHeight(),j=c.extend({},i);if(a.my[0]==="right")j.left-=k;else if(a.my[0]==="center")j.left-=k/2;if(a.my[1]==="bottom")j.top-=l;else if(a.my[1]==="center")j.top-=l/2;j.left=parseInt(j.left);j.top=parseInt(j.top);c.each(["left","top"],function(o,r){c.ui.position[d[o]]&&c.ui.position[d[o]][r](j,{targetWidth:g,targetHeight:h,elemWidth:k,
+elemHeight:l,offset:e,my:a.my,at:a.at})});c.fn.bgiframe&&f.bgiframe();f.offset(c.extend(j,{using:a.using}))})};c.ui.position={fit:{left:function(a,b){var d=c(window);b=a.left+b.elemWidth-d.width()-d.scrollLeft();a.left=b>0?a.left-b:Math.max(0,a.left)},top:function(a,b){var d=c(window);b=a.top+b.elemHeight-d.height()-d.scrollTop();a.top=b>0?a.top-b:Math.max(0,a.top)}},flip:{left:function(a,b){if(b.at[0]!=="center"){var d=c(window);d=a.left+b.elemWidth-d.width()-d.scrollLeft();var e=b.my[0]==="left"?
+-b.elemWidth:b.my[0]==="right"?b.elemWidth:0,g=-2*b.offset[0];a.left+=a.left<0?e+b.targetWidth+g:d>0?e-b.targetWidth+g:0}},top:function(a,b){if(b.at[1]!=="center"){var d=c(window);d=a.top+b.elemHeight-d.height()-d.scrollTop();var e=b.my[1]==="top"?-b.elemHeight:b.my[1]==="bottom"?b.elemHeight:0,g=b.at[1]==="top"?b.targetHeight:-b.targetHeight,h=-2*b.offset[1];a.top+=a.top<0?e+b.targetHeight+h:d>0?e+g+h:0}}}};if(!c.offset.setOffset){c.offset.setOffset=function(a,b){if(/static/.test(c.curCSS(a,"position")))a.style.position=
+"relative";var d=c(a),e=d.offset(),g=parseInt(c.curCSS(a,"top",true),10)||0,h=parseInt(c.curCSS(a,"left",true),10)||0;e={top:b.top-e.top+g,left:b.left-e.left+h};"using"in b?b.using.call(a,e):d.css(e)};c.fn.offset=function(a){var b=this[0];if(!b||!b.ownerDocument)return null;if(a)return this.each(function(){c.offset.setOffset(this,a)});return q.call(this)}}})(jQuery);
+;/*
+ * jQuery UI Draggable 1.8.4
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Draggables
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.mouse.js
+ * jquery.ui.widget.js
+ */
+(function(d){d.widget("ui.draggable",d.ui.mouse,{widgetEventPrefix:"drag",options:{addClasses:true,appendTo:"parent",axis:false,connectToSortable:false,containment:false,cursor:"auto",cursorAt:false,grid:false,handle:false,helper:"original",iframeFix:false,opacity:false,refreshPositions:false,revert:false,revertDuration:500,scope:"default",scroll:true,scrollSensitivity:20,scrollSpeed:20,snap:false,snapMode:"both",snapTolerance:20,stack:false,zIndex:false},_create:function(){if(this.options.helper==
+"original"&&!/^(?:r|a|f)/.test(this.element.css("position")))this.element[0].style.position="relative";this.options.addClasses&&this.element.addClass("ui-draggable");this.options.disabled&&this.element.addClass("ui-draggable-disabled");this._mouseInit()},destroy:function(){if(this.element.data("draggable")){this.element.removeData("draggable").unbind(".draggable").removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled");this._mouseDestroy();return this}},_mouseCapture:function(a){var b=
+this.options;if(this.helper||b.disabled||d(a.target).is(".ui-resizable-handle"))return false;this.handle=this._getHandle(a);if(!this.handle)return false;return true},_mouseStart:function(a){var b=this.options;this.helper=this._createHelper(a);this._cacheHelperProportions();if(d.ui.ddmanager)d.ui.ddmanager.current=this;this._cacheMargins();this.cssPosition=this.helper.css("position");this.scrollParent=this.helper.scrollParent();this.offset=this.positionAbs=this.element.offset();this.offset={top:this.offset.top-
+this.margins.top,left:this.offset.left-this.margins.left};d.extend(this.offset,{click:{left:a.pageX-this.offset.left,top:a.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()});this.originalPosition=this.position=this._generatePosition(a);this.originalPageX=a.pageX;this.originalPageY=a.pageY;b.cursorAt&&this._adjustOffsetFromHelper(b.cursorAt);b.containment&&this._setContainment();if(this._trigger("start",a)===false){this._clear();return false}this._cacheHelperProportions();
+d.ui.ddmanager&&!b.dropBehaviour&&d.ui.ddmanager.prepareOffsets(this,a);this.helper.addClass("ui-draggable-dragging");this._mouseDrag(a,true);return true},_mouseDrag:function(a,b){this.position=this._generatePosition(a);this.positionAbs=this._convertPositionTo("absolute");if(!b){b=this._uiHash();if(this._trigger("drag",a,b)===false){this._mouseUp({});return false}this.position=b.position}if(!this.options.axis||this.options.axis!="y")this.helper[0].style.left=this.position.left+"px";if(!this.options.axis||
+this.options.axis!="x")this.helper[0].style.top=this.position.top+"px";d.ui.ddmanager&&d.ui.ddmanager.drag(this,a);return false},_mouseStop:function(a){var b=false;if(d.ui.ddmanager&&!this.options.dropBehaviour)b=d.ui.ddmanager.drop(this,a);if(this.dropped){b=this.dropped;this.dropped=false}if(!this.element[0]||!this.element[0].parentNode)return false;if(this.options.revert=="invalid"&&!b||this.options.revert=="valid"&&b||this.options.revert===true||d.isFunction(this.options.revert)&&this.options.revert.call(this.element,
+b)){var c=this;d(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){c._trigger("stop",a)!==false&&c._clear()})}else this._trigger("stop",a)!==false&&this._clear();return false},cancel:function(){this.helper.is(".ui-draggable-dragging")?this._mouseUp({}):this._clear();return this},_getHandle:function(a){var b=!this.options.handle||!d(this.options.handle,this.element).length?true:false;d(this.options.handle,this.element).find("*").andSelf().each(function(){if(this==
+a.target)b=true});return b},_createHelper:function(a){var b=this.options;a=d.isFunction(b.helper)?d(b.helper.apply(this.element[0],[a])):b.helper=="clone"?this.element.clone():this.element;a.parents("body").length||a.appendTo(b.appendTo=="parent"?this.element[0].parentNode:b.appendTo);a[0]!=this.element[0]&&!/(fixed|absolute)/.test(a.css("position"))&&a.css("position","absolute");return a},_adjustOffsetFromHelper:function(a){if(typeof a=="string")a=a.split(" ");if(d.isArray(a))a={left:+a[0],top:+a[1]||
+0};if("left"in a)this.offset.click.left=a.left+this.margins.left;if("right"in a)this.offset.click.left=this.helperProportions.width-a.right+this.margins.left;if("top"in a)this.offset.click.top=a.top+this.margins.top;if("bottom"in a)this.offset.click.top=this.helperProportions.height-a.bottom+this.margins.top},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var a=this.offsetParent.offset();if(this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],
+this.offsetParent[0])){a.left+=this.scrollParent.scrollLeft();a.top+=this.scrollParent.scrollTop()}if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&d.browser.msie)a={top:0,left:0};return{top:a.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:a.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var a=this.element.position();return{top:a.top-
+(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:a.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}else return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var a=this.options;if(a.containment==
+"parent")a.containment=this.helper[0].parentNode;if(a.containment=="document"||a.containment=="window")this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,d(a.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(d(a.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(a.containment)&&
+a.containment.constructor!=Array){var b=d(a.containment)[0];if(b){a=d(a.containment).offset();var c=d(b).css("overflow")!="hidden";this.containment=[a.left+(parseInt(d(b).css("borderLeftWidth"),10)||0)+(parseInt(d(b).css("paddingLeft"),10)||0)-this.margins.left,a.top+(parseInt(d(b).css("borderTopWidth"),10)||0)+(parseInt(d(b).css("paddingTop"),10)||0)-this.margins.top,a.left+(c?Math.max(b.scrollWidth,b.offsetWidth):b.offsetWidth)-(parseInt(d(b).css("borderLeftWidth"),10)||0)-(parseInt(d(b).css("paddingRight"),
+10)||0)-this.helperProportions.width-this.margins.left,a.top+(c?Math.max(b.scrollHeight,b.offsetHeight):b.offsetHeight)-(parseInt(d(b).css("borderTopWidth"),10)||0)-(parseInt(d(b).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top]}}else if(a.containment.constructor==Array)this.containment=a.containment},_convertPositionTo:function(a,b){if(!b)b=this.position;a=a=="absolute"?1:-1;var c=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],
+this.offsetParent[0]))?this.offsetParent:this.scrollParent,f=/(html|body)/i.test(c[0].tagName);return{top:b.top+this.offset.relative.top*a+this.offset.parent.top*a-(d.browser.safari&&d.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():f?0:c.scrollTop())*a),left:b.left+this.offset.relative.left*a+this.offset.parent.left*a-(d.browser.safari&&d.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():
+f?0:c.scrollLeft())*a)}},_generatePosition:function(a){var b=this.options,c=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,f=/(html|body)/i.test(c[0].tagName),e=a.pageX,g=a.pageY;if(this.originalPosition){if(this.containment){if(a.pageX-this.offset.click.left<this.containment[0])e=this.containment[0]+this.offset.click.left;if(a.pageY-this.offset.click.top<this.containment[1])g=this.containment[1]+
+this.offset.click.top;if(a.pageX-this.offset.click.left>this.containment[2])e=this.containment[2]+this.offset.click.left;if(a.pageY-this.offset.click.top>this.containment[3])g=this.containment[3]+this.offset.click.top}if(b.grid){g=this.originalPageY+Math.round((g-this.originalPageY)/b.grid[1])*b.grid[1];g=this.containment?!(g-this.offset.click.top<this.containment[1]||g-this.offset.click.top>this.containment[3])?g:!(g-this.offset.click.top<this.containment[1])?g-b.grid[1]:g+b.grid[1]:g;e=this.originalPageX+
+Math.round((e-this.originalPageX)/b.grid[0])*b.grid[0];e=this.containment?!(e-this.offset.click.left<this.containment[0]||e-this.offset.click.left>this.containment[2])?e:!(e-this.offset.click.left<this.containment[0])?e-b.grid[0]:e+b.grid[0]:e}}return{top:g-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(d.browser.safari&&d.browser.version<526&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollTop():f?0:c.scrollTop()),left:e-this.offset.click.left-
+this.offset.relative.left-this.offset.parent.left+(d.browser.safari&&d.browser.version<526&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():f?0:c.scrollLeft())}},_clear:function(){this.helper.removeClass("ui-draggable-dragging");this.helper[0]!=this.element[0]&&!this.cancelHelperRemoval&&this.helper.remove();this.helper=null;this.cancelHelperRemoval=false},_trigger:function(a,b,c){c=c||this._uiHash();d.ui.plugin.call(this,a,[b,c]);if(a=="drag")this.positionAbs=
+this._convertPositionTo("absolute");return d.Widget.prototype._trigger.call(this,a,b,c)},plugins:{},_uiHash:function(){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}});d.extend(d.ui.draggable,{version:"1.8.4"});d.ui.plugin.add("draggable","connectToSortable",{start:function(a,b){var c=d(this).data("draggable"),f=c.options,e=d.extend({},b,{item:c.element});c.sortables=[];d(f.connectToSortable).each(function(){var g=d.data(this,"sortable");
+if(g&&!g.options.disabled){c.sortables.push({instance:g,shouldRevert:g.options.revert});g._refreshItems();g._trigger("activate",a,e)}})},stop:function(a,b){var c=d(this).data("draggable"),f=d.extend({},b,{item:c.element});d.each(c.sortables,function(){if(this.instance.isOver){this.instance.isOver=0;c.cancelHelperRemoval=true;this.instance.cancelHelperRemoval=false;if(this.shouldRevert)this.instance.options.revert=true;this.instance._mouseStop(a);this.instance.options.helper=this.instance.options._helper;
+c.options.helper=="original"&&this.instance.currentItem.css({top:"auto",left:"auto"})}else{this.instance.cancelHelperRemoval=false;this.instance._trigger("deactivate",a,f)}})},drag:function(a,b){var c=d(this).data("draggable"),f=this;d.each(c.sortables,function(){this.instance.positionAbs=c.positionAbs;this.instance.helperProportions=c.helperProportions;this.instance.offset.click=c.offset.click;if(this.instance._intersectsWith(this.instance.containerCache)){if(!this.instance.isOver){this.instance.isOver=
+1;this.instance.currentItem=d(f).clone().appendTo(this.instance.element).data("sortable-item",true);this.instance.options._helper=this.instance.options.helper;this.instance.options.helper=function(){return b.helper[0]};a.target=this.instance.currentItem[0];this.instance._mouseCapture(a,true);this.instance._mouseStart(a,true,true);this.instance.offset.click.top=c.offset.click.top;this.instance.offset.click.left=c.offset.click.left;this.instance.offset.parent.left-=c.offset.parent.left-this.instance.offset.parent.left;
+this.instance.offset.parent.top-=c.offset.parent.top-this.instance.offset.parent.top;c._trigger("toSortable",a);c.dropped=this.instance.element;c.currentItem=c.element;this.instance.fromOutside=c}this.instance.currentItem&&this.instance._mouseDrag(a)}else if(this.instance.isOver){this.instance.isOver=0;this.instance.cancelHelperRemoval=true;this.instance.options.revert=false;this.instance._trigger("out",a,this.instance._uiHash(this.instance));this.instance._mouseStop(a,true);this.instance.options.helper=
+this.instance.options._helper;this.instance.currentItem.remove();this.instance.placeholder&&this.instance.placeholder.remove();c._trigger("fromSortable",a);c.dropped=false}})}});d.ui.plugin.add("draggable","cursor",{start:function(){var a=d("body"),b=d(this).data("draggable").options;if(a.css("cursor"))b._cursor=a.css("cursor");a.css("cursor",b.cursor)},stop:function(){var a=d(this).data("draggable").options;a._cursor&&d("body").css("cursor",a._cursor)}});d.ui.plugin.add("draggable","iframeFix",{start:function(){var a=
+d(this).data("draggable").options;d(a.iframeFix===true?"iframe":a.iframeFix).each(function(){d('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>').css({width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1E3}).css(d(this).offset()).appendTo("body")})},stop:function(){d("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this)})}});d.ui.plugin.add("draggable","opacity",{start:function(a,b){a=d(b.helper);b=d(this).data("draggable").options;
+if(a.css("opacity"))b._opacity=a.css("opacity");a.css("opacity",b.opacity)},stop:function(a,b){a=d(this).data("draggable").options;a._opacity&&d(b.helper).css("opacity",a._opacity)}});d.ui.plugin.add("draggable","scroll",{start:function(){var a=d(this).data("draggable");if(a.scrollParent[0]!=document&&a.scrollParent[0].tagName!="HTML")a.overflowOffset=a.scrollParent.offset()},drag:function(a){var b=d(this).data("draggable"),c=b.options,f=false;if(b.scrollParent[0]!=document&&b.scrollParent[0].tagName!=
+"HTML"){if(!c.axis||c.axis!="x")if(b.overflowOffset.top+b.scrollParent[0].offsetHeight-a.pageY<c.scrollSensitivity)b.scrollParent[0].scrollTop=f=b.scrollParent[0].scrollTop+c.scrollSpeed;else if(a.pageY-b.overflowOffset.top<c.scrollSensitivity)b.scrollParent[0].scrollTop=f=b.scrollParent[0].scrollTop-c.scrollSpeed;if(!c.axis||c.axis!="y")if(b.overflowOffset.left+b.scrollParent[0].offsetWidth-a.pageX<c.scrollSensitivity)b.scrollParent[0].scrollLeft=f=b.scrollParent[0].scrollLeft+c.scrollSpeed;else if(a.pageX-
+b.overflowOffset.left<c.scrollSensitivity)b.scrollParent[0].scrollLeft=f=b.scrollParent[0].scrollLeft-c.scrollSpeed}else{if(!c.axis||c.axis!="x")if(a.pageY-d(document).scrollTop()<c.scrollSensitivity)f=d(document).scrollTop(d(document).scrollTop()-c.scrollSpeed);else if(d(window).height()-(a.pageY-d(document).scrollTop())<c.scrollSensitivity)f=d(document).scrollTop(d(document).scrollTop()+c.scrollSpeed);if(!c.axis||c.axis!="y")if(a.pageX-d(document).scrollLeft()<c.scrollSensitivity)f=d(document).scrollLeft(d(document).scrollLeft()-
+c.scrollSpeed);else if(d(window).width()-(a.pageX-d(document).scrollLeft())<c.scrollSensitivity)f=d(document).scrollLeft(d(document).scrollLeft()+c.scrollSpeed)}f!==false&&d.ui.ddmanager&&!c.dropBehaviour&&d.ui.ddmanager.prepareOffsets(b,a)}});d.ui.plugin.add("draggable","snap",{start:function(){var a=d(this).data("draggable"),b=a.options;a.snapElements=[];d(b.snap.constructor!=String?b.snap.items||":data(draggable)":b.snap).each(function(){var c=d(this),f=c.offset();this!=a.element[0]&&a.snapElements.push({item:this,
+width:c.outerWidth(),height:c.outerHeight(),top:f.top,left:f.left})})},drag:function(a,b){for(var c=d(this).data("draggable"),f=c.options,e=f.snapTolerance,g=b.offset.left,n=g+c.helperProportions.width,m=b.offset.top,o=m+c.helperProportions.height,h=c.snapElements.length-1;h>=0;h--){var i=c.snapElements[h].left,k=i+c.snapElements[h].width,j=c.snapElements[h].top,l=j+c.snapElements[h].height;if(i-e<g&&g<k+e&&j-e<m&&m<l+e||i-e<g&&g<k+e&&j-e<o&&o<l+e||i-e<n&&n<k+e&&j-e<m&&m<l+e||i-e<n&&n<k+e&&j-e<o&&
+o<l+e){if(f.snapMode!="inner"){var p=Math.abs(j-o)<=e,q=Math.abs(l-m)<=e,r=Math.abs(i-n)<=e,s=Math.abs(k-g)<=e;if(p)b.position.top=c._convertPositionTo("relative",{top:j-c.helperProportions.height,left:0}).top-c.margins.top;if(q)b.position.top=c._convertPositionTo("relative",{top:l,left:0}).top-c.margins.top;if(r)b.position.left=c._convertPositionTo("relative",{top:0,left:i-c.helperProportions.width}).left-c.margins.left;if(s)b.position.left=c._convertPositionTo("relative",{top:0,left:k}).left-c.margins.left}var t=
+p||q||r||s;if(f.snapMode!="outer"){p=Math.abs(j-m)<=e;q=Math.abs(l-o)<=e;r=Math.abs(i-g)<=e;s=Math.abs(k-n)<=e;if(p)b.position.top=c._convertPositionTo("relative",{top:j,left:0}).top-c.margins.top;if(q)b.position.top=c._convertPositionTo("relative",{top:l-c.helperProportions.height,left:0}).top-c.margins.top;if(r)b.position.left=c._convertPositionTo("relative",{top:0,left:i}).left-c.margins.left;if(s)b.position.left=c._convertPositionTo("relative",{top:0,left:k-c.helperProportions.width}).left-c.margins.left}if(!c.snapElements[h].snapping&&
+(p||q||r||s||t))c.options.snap.snap&&c.options.snap.snap.call(c.element,a,d.extend(c._uiHash(),{snapItem:c.snapElements[h].item}));c.snapElements[h].snapping=p||q||r||s||t}else{c.snapElements[h].snapping&&c.options.snap.release&&c.options.snap.release.call(c.element,a,d.extend(c._uiHash(),{snapItem:c.snapElements[h].item}));c.snapElements[h].snapping=false}}}});d.ui.plugin.add("draggable","stack",{start:function(){var a=d(this).data("draggable").options;a=d.makeArray(d(a.stack)).sort(function(c,f){return(parseInt(d(c).css("zIndex"),
+10)||0)-(parseInt(d(f).css("zIndex"),10)||0)});if(a.length){var b=parseInt(a[0].style.zIndex)||0;d(a).each(function(c){this.style.zIndex=b+c});this[0].style.zIndex=b+a.length}}});d.ui.plugin.add("draggable","zIndex",{start:function(a,b){a=d(b.helper);b=d(this).data("draggable").options;if(a.css("zIndex"))b._zIndex=a.css("zIndex");a.css("zIndex",b.zIndex)},stop:function(a,b){a=d(this).data("draggable").options;a._zIndex&&d(b.helper).css("zIndex",a._zIndex)}})})(jQuery);
+;/*
+ * jQuery UI Droppable 1.8.4
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Droppables
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.widget.js
+ * jquery.ui.mouse.js
+ * jquery.ui.draggable.js
+ */
+(function(d){d.widget("ui.droppable",{widgetEventPrefix:"drop",options:{accept:"*",activeClass:false,addClasses:true,greedy:false,hoverClass:false,scope:"default",tolerance:"intersect"},_create:function(){var a=this.options,b=a.accept;this.isover=0;this.isout=1;this.accept=d.isFunction(b)?b:function(c){return c.is(b)};this.proportions={width:this.element[0].offsetWidth,height:this.element[0].offsetHeight};d.ui.ddmanager.droppables[a.scope]=d.ui.ddmanager.droppables[a.scope]||[];d.ui.ddmanager.droppables[a.scope].push(this);
+a.addClasses&&this.element.addClass("ui-droppable")},destroy:function(){for(var a=d.ui.ddmanager.droppables[this.options.scope],b=0;b<a.length;b++)a[b]==this&&a.splice(b,1);this.element.removeClass("ui-droppable ui-droppable-disabled").removeData("droppable").unbind(".droppable");return this},_setOption:function(a,b){if(a=="accept")this.accept=d.isFunction(b)?b:function(c){return c.is(b)};d.Widget.prototype._setOption.apply(this,arguments)},_activate:function(a){var b=d.ui.ddmanager.current;this.options.activeClass&&
+this.element.addClass(this.options.activeClass);b&&this._trigger("activate",a,this.ui(b))},_deactivate:function(a){var b=d.ui.ddmanager.current;this.options.activeClass&&this.element.removeClass(this.options.activeClass);b&&this._trigger("deactivate",a,this.ui(b))},_over:function(a){var b=d.ui.ddmanager.current;if(!(!b||(b.currentItem||b.element)[0]==this.element[0]))if(this.accept.call(this.element[0],b.currentItem||b.element)){this.options.hoverClass&&this.element.addClass(this.options.hoverClass);
+this._trigger("over",a,this.ui(b))}},_out:function(a){var b=d.ui.ddmanager.current;if(!(!b||(b.currentItem||b.element)[0]==this.element[0]))if(this.accept.call(this.element[0],b.currentItem||b.element)){this.options.hoverClass&&this.element.removeClass(this.options.hoverClass);this._trigger("out",a,this.ui(b))}},_drop:function(a,b){var c=b||d.ui.ddmanager.current;if(!c||(c.currentItem||c.element)[0]==this.element[0])return false;var e=false;this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function(){var g=
+d.data(this,"droppable");if(g.options.greedy&&!g.options.disabled&&g.options.scope==c.options.scope&&g.accept.call(g.element[0],c.currentItem||c.element)&&d.ui.intersect(c,d.extend(g,{offset:g.element.offset()}),g.options.tolerance)){e=true;return false}});if(e)return false;if(this.accept.call(this.element[0],c.currentItem||c.element)){this.options.activeClass&&this.element.removeClass(this.options.activeClass);this.options.hoverClass&&this.element.removeClass(this.options.hoverClass);this._trigger("drop",
+a,this.ui(c));return this.element}return false},ui:function(a){return{draggable:a.currentItem||a.element,helper:a.helper,position:a.position,offset:a.positionAbs}}});d.extend(d.ui.droppable,{version:"1.8.4"});d.ui.intersect=function(a,b,c){if(!b.offset)return false;var e=(a.positionAbs||a.position.absolute).left,g=e+a.helperProportions.width,f=(a.positionAbs||a.position.absolute).top,h=f+a.helperProportions.height,i=b.offset.left,k=i+b.proportions.width,j=b.offset.top,l=j+b.proportions.height;
+switch(c){case "fit":return i<=e&&g<=k&&j<=f&&h<=l;case "intersect":return i<e+a.helperProportions.width/2&&g-a.helperProportions.width/2<k&&j<f+a.helperProportions.height/2&&h-a.helperProportions.height/2<l;case "pointer":return d.ui.isOver((a.positionAbs||a.position.absolute).top+(a.clickOffset||a.offset.click).top,(a.positionAbs||a.position.absolute).left+(a.clickOffset||a.offset.click).left,j,i,b.proportions.height,b.proportions.width);case "touch":return(f>=j&&f<=l||h>=j&&h<=l||f<j&&h>l)&&(e>=
+i&&e<=k||g>=i&&g<=k||e<i&&g>k);default:return false}};d.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(a,b){var c=d.ui.ddmanager.droppables[a.options.scope]||[],e=b?b.type:null,g=(a.currentItem||a.element).find(":data(droppable)").andSelf(),f=0;a:for(;f<c.length;f++)if(!(c[f].options.disabled||a&&!c[f].accept.call(c[f].element[0],a.currentItem||a.element))){for(var h=0;h<g.length;h++)if(g[h]==c[f].element[0]){c[f].proportions.height=0;continue a}c[f].visible=c[f].element.css("display")!=
+"none";if(c[f].visible){c[f].offset=c[f].element.offset();c[f].proportions={width:c[f].element[0].offsetWidth,height:c[f].element[0].offsetHeight};e=="mousedown"&&c[f]._activate.call(c[f],b)}}},drop:function(a,b){var c=false;d.each(d.ui.ddmanager.droppables[a.options.scope]||[],function(){if(this.options){if(!this.options.disabled&&this.visible&&d.ui.intersect(a,this,this.options.tolerance))c=c||this._drop.call(this,b);if(!this.options.disabled&&this.visible&&this.accept.call(this.element[0],a.currentItem||
+a.element)){this.isout=1;this.isover=0;this._deactivate.call(this,b)}}});return c},drag:function(a,b){a.options.refreshPositions&&d.ui.ddmanager.prepareOffsets(a,b);d.each(d.ui.ddmanager.droppables[a.options.scope]||[],function(){if(!(this.options.disabled||this.greedyChild||!this.visible)){var c=d.ui.intersect(a,this,this.options.tolerance);if(c=!c&&this.isover==1?"isout":c&&this.isover==0?"isover":null){var e;if(this.options.greedy){var g=this.element.parents(":data(droppable):eq(0)");if(g.length){e=
+d.data(g[0],"droppable");e.greedyChild=c=="isover"?1:0}}if(e&&c=="isover"){e.isover=0;e.isout=1;e._out.call(e,b)}this[c]=1;this[c=="isout"?"isover":"isout"]=0;this[c=="isover"?"_over":"_out"].call(this,b);if(e&&c=="isout"){e.isout=0;e.isover=1;e._over.call(e,b)}}}})}}})(jQuery);
+;/*
+ * jQuery UI Resizable 1.8.4
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Resizables
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.mouse.js
+ * jquery.ui.widget.js
+ */
+(function(e){e.widget("ui.resizable",e.ui.mouse,{widgetEventPrefix:"resize",options:{alsoResize:false,animate:false,animateDuration:"slow",animateEasing:"swing",aspectRatio:false,autoHide:false,containment:false,ghost:false,grid:false,handles:"e,s,se",helper:false,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:1E3},_create:function(){var b=this,a=this.options;this.element.addClass("ui-resizable");e.extend(this,{_aspectRatio:!!a.aspectRatio,aspectRatio:a.aspectRatio,originalElement:this.element,
+_proportionallyResizeElements:[],_helper:a.helper||a.ghost||a.animate?a.helper||"ui-resizable-helper":null});if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)){/relative/.test(this.element.css("position"))&&e.browser.opera&&this.element.css({position:"relative",top:"auto",left:"auto"});this.element.wrap(e('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),
+top:this.element.css("top"),left:this.element.css("left")}));this.element=this.element.parent().data("resizable",this.element.data("resizable"));this.elementIsWrapper=true;this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")});this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0});this.originalResizeStyle=
+this.originalElement.css("resize");this.originalElement.css("resize","none");this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"}));this.originalElement.css({margin:this.originalElement.css("margin")});this._proportionallyResize()}this.handles=a.handles||(!e(".ui-resizable-handle",this.element).length?"e,s,se":{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",
+nw:".ui-resizable-nw"});if(this.handles.constructor==String){if(this.handles=="all")this.handles="n,e,s,w,se,sw,ne,nw";var c=this.handles.split(",");this.handles={};for(var d=0;d<c.length;d++){var f=e.trim(c[d]),g=e('<div class="ui-resizable-handle '+("ui-resizable-"+f)+'"></div>');/sw|se|ne|nw/.test(f)&&g.css({zIndex:++a.zIndex});"se"==f&&g.addClass("ui-icon ui-icon-gripsmall-diagonal-se");this.handles[f]=".ui-resizable-"+f;this.element.append(g)}}this._renderAxis=function(h){h=h||this.element;for(var i in this.handles){if(this.handles[i].constructor==
+String)this.handles[i]=e(this.handles[i],this.element).show();if(this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)){var j=e(this.handles[i],this.element),k=0;k=/sw|ne|nw|se|n|s/.test(i)?j.outerHeight():j.outerWidth();j=["padding",/ne|nw|n/.test(i)?"Top":/se|sw|s/.test(i)?"Bottom":/^e$/.test(i)?"Right":"Left"].join("");h.css(j,k);this._proportionallyResize()}e(this.handles[i])}};this._renderAxis(this.element);this._handles=e(".ui-resizable-handle",this.element).disableSelection();
+this._handles.mouseover(function(){if(!b.resizing){if(this.className)var h=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);b.axis=h&&h[1]?h[1]:"se"}});if(a.autoHide){this._handles.hide();e(this.element).addClass("ui-resizable-autohide").hover(function(){e(this).removeClass("ui-resizable-autohide");b._handles.show()},function(){if(!b.resizing){e(this).addClass("ui-resizable-autohide");b._handles.hide()}})}this._mouseInit()},destroy:function(){this._mouseDestroy();var b=function(c){e(c).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};
+if(this.elementIsWrapper){b(this.element);var a=this.element;a.after(this.originalElement.css({position:a.css("position"),width:a.outerWidth(),height:a.outerHeight(),top:a.css("top"),left:a.css("left")})).remove()}this.originalElement.css("resize",this.originalResizeStyle);b(this.originalElement);return this},_mouseCapture:function(b){var a=false;for(var c in this.handles)if(e(this.handles[c])[0]==b.target)a=true;return!this.options.disabled&&a},_mouseStart:function(b){var a=this.options,c=this.element.position(),
+d=this.element;this.resizing=true;this.documentScroll={top:e(document).scrollTop(),left:e(document).scrollLeft()};if(d.is(".ui-draggable")||/absolute/.test(d.css("position")))d.css({position:"absolute",top:c.top,left:c.left});e.browser.opera&&/relative/.test(d.css("position"))&&d.css({position:"relative",top:"auto",left:"auto"});this._renderProxy();c=m(this.helper.css("left"));var f=m(this.helper.css("top"));if(a.containment){c+=e(a.containment).scrollLeft()||0;f+=e(a.containment).scrollTop()||0}this.offset=
+this.helper.offset();this.position={left:c,top:f};this.size=this._helper?{width:d.outerWidth(),height:d.outerHeight()}:{width:d.width(),height:d.height()};this.originalSize=this._helper?{width:d.outerWidth(),height:d.outerHeight()}:{width:d.width(),height:d.height()};this.originalPosition={left:c,top:f};this.sizeDiff={width:d.outerWidth()-d.width(),height:d.outerHeight()-d.height()};this.originalMousePosition={left:b.pageX,top:b.pageY};this.aspectRatio=typeof a.aspectRatio=="number"?a.aspectRatio:
+this.originalSize.width/this.originalSize.height||1;a=e(".ui-resizable-"+this.axis).css("cursor");e("body").css("cursor",a=="auto"?this.axis+"-resize":a);d.addClass("ui-resizable-resizing");this._propagate("start",b);return true},_mouseDrag:function(b){var a=this.helper,c=this.originalMousePosition,d=this._change[this.axis];if(!d)return false;c=d.apply(this,[b,b.pageX-c.left||0,b.pageY-c.top||0]);if(this._aspectRatio||b.shiftKey)c=this._updateRatio(c,b);c=this._respectSize(c,b);this._propagate("resize",
+b);a.css({top:this.position.top+"px",left:this.position.left+"px",width:this.size.width+"px",height:this.size.height+"px"});!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize();this._updateCache(c);this._trigger("resize",b,this.ui());return false},_mouseStop:function(b){this.resizing=false;var a=this.options,c=this;if(this._helper){var d=this._proportionallyResizeElements,f=d.length&&/textarea/i.test(d[0].nodeName);d=f&&e.ui.hasScroll(d[0],"left")?0:c.sizeDiff.height;
+f={width:c.size.width-(f?0:c.sizeDiff.width),height:c.size.height-d};d=parseInt(c.element.css("left"),10)+(c.position.left-c.originalPosition.left)||null;var g=parseInt(c.element.css("top"),10)+(c.position.top-c.originalPosition.top)||null;a.animate||this.element.css(e.extend(f,{top:g,left:d}));c.helper.height(c.size.height);c.helper.width(c.size.width);this._helper&&!a.animate&&this._proportionallyResize()}e("body").css("cursor","auto");this.element.removeClass("ui-resizable-resizing");this._propagate("stop",
+b);this._helper&&this.helper.remove();return false},_updateCache:function(b){this.offset=this.helper.offset();if(l(b.left))this.position.left=b.left;if(l(b.top))this.position.top=b.top;if(l(b.height))this.size.height=b.height;if(l(b.width))this.size.width=b.width},_updateRatio:function(b){var a=this.position,c=this.size,d=this.axis;if(b.height)b.width=c.height*this.aspectRatio;else if(b.width)b.height=c.width/this.aspectRatio;if(d=="sw"){b.left=a.left+(c.width-b.width);b.top=null}if(d=="nw"){b.top=
+a.top+(c.height-b.height);b.left=a.left+(c.width-b.width)}return b},_respectSize:function(b){var a=this.options,c=this.axis,d=l(b.width)&&a.maxWidth&&a.maxWidth<b.width,f=l(b.height)&&a.maxHeight&&a.maxHeight<b.height,g=l(b.width)&&a.minWidth&&a.minWidth>b.width,h=l(b.height)&&a.minHeight&&a.minHeight>b.height;if(g)b.width=a.minWidth;if(h)b.height=a.minHeight;if(d)b.width=a.maxWidth;if(f)b.height=a.maxHeight;var i=this.originalPosition.left+this.originalSize.width,j=this.position.top+this.size.height,
+k=/sw|nw|w/.test(c);c=/nw|ne|n/.test(c);if(g&&k)b.left=i-a.minWidth;if(d&&k)b.left=i-a.maxWidth;if(h&&c)b.top=j-a.minHeight;if(f&&c)b.top=j-a.maxHeight;if((a=!b.width&&!b.height)&&!b.left&&b.top)b.top=null;else if(a&&!b.top&&b.left)b.left=null;return b},_proportionallyResize:function(){if(this._proportionallyResizeElements.length)for(var b=this.helper||this.element,a=0;a<this._proportionallyResizeElements.length;a++){var c=this._proportionallyResizeElements[a];if(!this.borderDif){var d=[c.css("borderTopWidth"),
+c.css("borderRightWidth"),c.css("borderBottomWidth"),c.css("borderLeftWidth")],f=[c.css("paddingTop"),c.css("paddingRight"),c.css("paddingBottom"),c.css("paddingLeft")];this.borderDif=e.map(d,function(g,h){g=parseInt(g,10)||0;h=parseInt(f[h],10)||0;return g+h})}e.browser.msie&&(e(b).is(":hidden")||e(b).parents(":hidden").length)||c.css({height:b.height()-this.borderDif[0]-this.borderDif[2]||0,width:b.width()-this.borderDif[1]-this.borderDif[3]||0})}},_renderProxy:function(){var b=this.options;this.elementOffset=
+this.element.offset();if(this._helper){this.helper=this.helper||e('<div style="overflow:hidden;"></div>');var a=e.browser.msie&&e.browser.version<7,c=a?1:0;a=a?2:-1;this.helper.addClass(this._helper).css({width:this.element.outerWidth()+a,height:this.element.outerHeight()+a,position:"absolute",left:this.elementOffset.left-c+"px",top:this.elementOffset.top-c+"px",zIndex:++b.zIndex});this.helper.appendTo("body").disableSelection()}else this.helper=this.element},_change:{e:function(b,a){return{width:this.originalSize.width+
+a}},w:function(b,a){return{left:this.originalPosition.left+a,width:this.originalSize.width-a}},n:function(b,a,c){return{top:this.originalPosition.top+c,height:this.originalSize.height-c}},s:function(b,a,c){return{height:this.originalSize.height+c}},se:function(b,a,c){return e.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[b,a,c]))},sw:function(b,a,c){return e.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[b,a,c]))},ne:function(b,a,c){return e.extend(this._change.n.apply(this,
+arguments),this._change.e.apply(this,[b,a,c]))},nw:function(b,a,c){return e.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[b,a,c]))}},_propagate:function(b,a){e.ui.plugin.call(this,b,[a,this.ui()]);b!="resize"&&this._trigger(b,a,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}});e.extend(e.ui.resizable,
+{version:"1.8.4"});e.ui.plugin.add("resizable","alsoResize",{start:function(){var b=e(this).data("resizable").options,a=function(c){e(c).each(function(){var d=e(this);d.data("resizable-alsoresize",{width:parseInt(d.width(),10),height:parseInt(d.height(),10),left:parseInt(d.css("left"),10),top:parseInt(d.css("top"),10),position:d.css("position")})})};if(typeof b.alsoResize=="object"&&!b.alsoResize.parentNode)if(b.alsoResize.length){b.alsoResize=b.alsoResize[0];a(b.alsoResize)}else e.each(b.alsoResize,
+function(c){a(c)});else a(b.alsoResize)},resize:function(b,a){var c=e(this).data("resizable");b=c.options;var d=c.originalSize,f=c.originalPosition,g={height:c.size.height-d.height||0,width:c.size.width-d.width||0,top:c.position.top-f.top||0,left:c.position.left-f.left||0},h=function(i,j){e(i).each(function(){var k=e(this),q=e(this).data("resizable-alsoresize"),p={},r=j&&j.length?j:k.parents(a.originalElement[0]).length?["width","height"]:["width","height","top","left"];e.each(r,function(n,o){if((n=
+(q[o]||0)+(g[o]||0))&&n>=0)p[o]=n||null});if(e.browser.opera&&/relative/.test(k.css("position"))){c._revertToRelativePosition=true;k.css({position:"absolute",top:"auto",left:"auto"})}k.css(p)})};typeof b.alsoResize=="object"&&!b.alsoResize.nodeType?e.each(b.alsoResize,function(i,j){h(i,j)}):h(b.alsoResize)},stop:function(){var b=e(this).data("resizable"),a=b.options,c=function(d){e(d).each(function(){var f=e(this);f.css({position:f.data("resizable-alsoresize").position})})};if(b._revertToRelativePosition){b._revertToRelativePosition=
+false;typeof a.alsoResize=="object"&&!a.alsoResize.nodeType?e.each(a.alsoResize,function(d){c(d)}):c(a.alsoResize)}e(this).removeData("resizable-alsoresize")}});e.ui.plugin.add("resizable","animate",{stop:function(b){var a=e(this).data("resizable"),c=a.options,d=a._proportionallyResizeElements,f=d.length&&/textarea/i.test(d[0].nodeName),g=f&&e.ui.hasScroll(d[0],"left")?0:a.sizeDiff.height;f={width:a.size.width-(f?0:a.sizeDiff.width),height:a.size.height-g};g=parseInt(a.element.css("left"),10)+(a.position.left-
+a.originalPosition.left)||null;var h=parseInt(a.element.css("top"),10)+(a.position.top-a.originalPosition.top)||null;a.element.animate(e.extend(f,h&&g?{top:h,left:g}:{}),{duration:c.animateDuration,easing:c.animateEasing,step:function(){var i={width:parseInt(a.element.css("width"),10),height:parseInt(a.element.css("height"),10),top:parseInt(a.element.css("top"),10),left:parseInt(a.element.css("left"),10)};d&&d.length&&e(d[0]).css({width:i.width,height:i.height});a._updateCache(i);a._propagate("resize",
+b)}})}});e.ui.plugin.add("resizable","containment",{start:function(){var b=e(this).data("resizable"),a=b.element,c=b.options.containment;if(a=c instanceof e?c.get(0):/parent/.test(c)?a.parent().get(0):c){b.containerElement=e(a);if(/document/.test(c)||c==document){b.containerOffset={left:0,top:0};b.containerPosition={left:0,top:0};b.parentData={element:e(document),left:0,top:0,width:e(document).width(),height:e(document).height()||document.body.parentNode.scrollHeight}}else{var d=e(a),f=[];e(["Top",
+"Right","Left","Bottom"]).each(function(i,j){f[i]=m(d.css("padding"+j))});b.containerOffset=d.offset();b.containerPosition=d.position();b.containerSize={height:d.innerHeight()-f[3],width:d.innerWidth()-f[1]};c=b.containerOffset;var g=b.containerSize.height,h=b.containerSize.width;h=e.ui.hasScroll(a,"left")?a.scrollWidth:h;g=e.ui.hasScroll(a)?a.scrollHeight:g;b.parentData={element:a,left:c.left,top:c.top,width:h,height:g}}}},resize:function(b){var a=e(this).data("resizable"),c=a.options,d=a.containerOffset,
+f=a.position;b=a._aspectRatio||b.shiftKey;var g={top:0,left:0},h=a.containerElement;if(h[0]!=document&&/static/.test(h.css("position")))g=d;if(f.left<(a._helper?d.left:0)){a.size.width+=a._helper?a.position.left-d.left:a.position.left-g.left;if(b)a.size.height=a.size.width/c.aspectRatio;a.position.left=c.helper?d.left:0}if(f.top<(a._helper?d.top:0)){a.size.height+=a._helper?a.position.top-d.top:a.position.top;if(b)a.size.width=a.size.height*c.aspectRatio;a.position.top=a._helper?d.top:0}a.offset.left=
+a.parentData.left+a.position.left;a.offset.top=a.parentData.top+a.position.top;c=Math.abs((a._helper?a.offset.left-g.left:a.offset.left-g.left)+a.sizeDiff.width);d=Math.abs((a._helper?a.offset.top-g.top:a.offset.top-d.top)+a.sizeDiff.height);f=a.containerElement.get(0)==a.element.parent().get(0);g=/relative|absolute/.test(a.containerElement.css("position"));if(f&&g)c-=a.parentData.left;if(c+a.size.width>=a.parentData.width){a.size.width=a.parentData.width-c;if(b)a.size.height=a.size.width/a.aspectRatio}if(d+
+a.size.height>=a.parentData.height){a.size.height=a.parentData.height-d;if(b)a.size.width=a.size.height*a.aspectRatio}},stop:function(){var b=e(this).data("resizable"),a=b.options,c=b.containerOffset,d=b.containerPosition,f=b.containerElement,g=e(b.helper),h=g.offset(),i=g.outerWidth()-b.sizeDiff.width;g=g.outerHeight()-b.sizeDiff.height;b._helper&&!a.animate&&/relative/.test(f.css("position"))&&e(this).css({left:h.left-d.left-c.left,width:i,height:g});b._helper&&!a.animate&&/static/.test(f.css("position"))&&
+e(this).css({left:h.left-d.left-c.left,width:i,height:g})}});e.ui.plugin.add("resizable","ghost",{start:function(){var b=e(this).data("resizable"),a=b.options,c=b.size;b.ghost=b.originalElement.clone();b.ghost.css({opacity:0.25,display:"block",position:"relative",height:c.height,width:c.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass(typeof a.ghost=="string"?a.ghost:"");b.ghost.appendTo(b.helper)},resize:function(){var b=e(this).data("resizable");b.ghost&&b.ghost.css({position:"relative",
+height:b.size.height,width:b.size.width})},stop:function(){var b=e(this).data("resizable");b.ghost&&b.helper&&b.helper.get(0).removeChild(b.ghost.get(0))}});e.ui.plugin.add("resizable","grid",{resize:function(){var b=e(this).data("resizable"),a=b.options,c=b.size,d=b.originalSize,f=b.originalPosition,g=b.axis;a.grid=typeof a.grid=="number"?[a.grid,a.grid]:a.grid;var h=Math.round((c.width-d.width)/(a.grid[0]||1))*(a.grid[0]||1);a=Math.round((c.height-d.height)/(a.grid[1]||1))*(a.grid[1]||1);if(/^(se|s|e)$/.test(g)){b.size.width=
+d.width+h;b.size.height=d.height+a}else if(/^(ne)$/.test(g)){b.size.width=d.width+h;b.size.height=d.height+a;b.position.top=f.top-a}else{if(/^(sw)$/.test(g)){b.size.width=d.width+h;b.size.height=d.height+a}else{b.size.width=d.width+h;b.size.height=d.height+a;b.position.top=f.top-a}b.position.left=f.left-h}}});var m=function(b){return parseInt(b,10)||0},l=function(b){return!isNaN(parseInt(b,10))}})(jQuery);
+;/*
+ * jQuery UI Selectable 1.8.4
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Selectables
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.mouse.js
+ * jquery.ui.widget.js
+ */
+(function(e){e.widget("ui.selectable",e.ui.mouse,{options:{appendTo:"body",autoRefresh:true,distance:0,filter:"*",tolerance:"touch"},_create:function(){var c=this;this.element.addClass("ui-selectable");this.dragged=false;var f;this.refresh=function(){f=e(c.options.filter,c.element[0]);f.each(function(){var d=e(this),b=d.offset();e.data(this,"selectable-item",{element:this,$element:d,left:b.left,top:b.top,right:b.left+d.outerWidth(),bottom:b.top+d.outerHeight(),startselected:false,selected:d.hasClass("ui-selected"),
+selecting:d.hasClass("ui-selecting"),unselecting:d.hasClass("ui-unselecting")})})};this.refresh();this.selectees=f.addClass("ui-selectee");this._mouseInit();this.helper=e("<div class='ui-selectable-helper'></div>")},destroy:function(){this.selectees.removeClass("ui-selectee").removeData("selectable-item");this.element.removeClass("ui-selectable ui-selectable-disabled").removeData("selectable").unbind(".selectable");this._mouseDestroy();return this},_mouseStart:function(c){var f=this;this.opos=[c.pageX,
+c.pageY];if(!this.options.disabled){var d=this.options;this.selectees=e(d.filter,this.element[0]);this._trigger("start",c);e(d.appendTo).append(this.helper);this.helper.css({left:c.clientX,top:c.clientY,width:0,height:0});d.autoRefresh&&this.refresh();this.selectees.filter(".ui-selected").each(function(){var b=e.data(this,"selectable-item");b.startselected=true;if(!c.metaKey){b.$element.removeClass("ui-selected");b.selected=false;b.$element.addClass("ui-unselecting");b.unselecting=true;f._trigger("unselecting",
+c,{unselecting:b.element})}});e(c.target).parents().andSelf().each(function(){var b=e.data(this,"selectable-item");if(b){var g=!c.metaKey||!b.$element.hasClass("ui-selected");b.$element.removeClass(g?"ui-unselecting":"ui-selected").addClass(g?"ui-selecting":"ui-unselecting");b.unselecting=!g;b.selecting=g;(b.selected=g)?f._trigger("selecting",c,{selecting:b.element}):f._trigger("unselecting",c,{unselecting:b.element});return false}})}},_mouseDrag:function(c){var f=this;this.dragged=true;if(!this.options.disabled){var d=
+this.options,b=this.opos[0],g=this.opos[1],h=c.pageX,i=c.pageY;if(b>h){var j=h;h=b;b=j}if(g>i){j=i;i=g;g=j}this.helper.css({left:b,top:g,width:h-b,height:i-g});this.selectees.each(function(){var a=e.data(this,"selectable-item");if(!(!a||a.element==f.element[0])){var k=false;if(d.tolerance=="touch")k=!(a.left>h||a.right<b||a.top>i||a.bottom<g);else if(d.tolerance=="fit")k=a.left>b&&a.right<h&&a.top>g&&a.bottom<i;if(k){if(a.selected){a.$element.removeClass("ui-selected");a.selected=false}if(a.unselecting){a.$element.removeClass("ui-unselecting");
+a.unselecting=false}if(!a.selecting){a.$element.addClass("ui-selecting");a.selecting=true;f._trigger("selecting",c,{selecting:a.element})}}else{if(a.selecting)if(c.metaKey&&a.startselected){a.$element.removeClass("ui-selecting");a.selecting=false;a.$element.addClass("ui-selected");a.selected=true}else{a.$element.removeClass("ui-selecting");a.selecting=false;if(a.startselected){a.$element.addClass("ui-unselecting");a.unselecting=true}f._trigger("unselecting",c,{unselecting:a.element})}if(a.selected)if(!c.metaKey&&
+!a.startselected){a.$element.removeClass("ui-selected");a.selected=false;a.$element.addClass("ui-unselecting");a.unselecting=true;f._trigger("unselecting",c,{unselecting:a.element})}}}});return false}},_mouseStop:function(c){var f=this;this.dragged=false;e(".ui-unselecting",this.element[0]).each(function(){var d=e.data(this,"selectable-item");d.$element.removeClass("ui-unselecting");d.unselecting=false;d.startselected=false;f._trigger("unselected",c,{unselected:d.element})});e(".ui-selecting",this.element[0]).each(function(){var d=
+e.data(this,"selectable-item");d.$element.removeClass("ui-selecting").addClass("ui-selected");d.selecting=false;d.selected=true;d.startselected=true;f._trigger("selected",c,{selected:d.element})});this._trigger("stop",c);this.helper.remove();return false}});e.extend(e.ui.selectable,{version:"1.8.4"})})(jQuery);
+;/*
+ * jQuery UI Sortable 1.8.4
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Sortables
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.mouse.js
+ * jquery.ui.widget.js
+ */
+(function(d){d.widget("ui.sortable",d.ui.mouse,{widgetEventPrefix:"sort",options:{appendTo:"parent",axis:false,connectWith:false,containment:false,cursor:"auto",cursorAt:false,dropOnEmpty:true,forcePlaceholderSize:false,forceHelperSize:false,grid:false,handle:false,helper:"original",items:"> *",opacity:false,placeholder:false,revert:false,scroll:true,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1E3},_create:function(){this.containerCache={};this.element.addClass("ui-sortable");
+this.refresh();this.floating=this.items.length?/left|right/.test(this.items[0].item.css("float")):false;this.offset=this.element.offset();this._mouseInit()},destroy:function(){this.element.removeClass("ui-sortable ui-sortable-disabled").removeData("sortable").unbind(".sortable");this._mouseDestroy();for(var a=this.items.length-1;a>=0;a--)this.items[a].item.removeData("sortable-item");return this},_setOption:function(a,b){if(a==="disabled"){this.options[a]=b;this.widget()[b?"addClass":"removeClass"]("ui-sortable-disabled")}else d.Widget.prototype._setOption.apply(this,
+arguments)},_mouseCapture:function(a,b){if(this.reverting)return false;if(this.options.disabled||this.options.type=="static")return false;this._refreshItems(a);var c=null,e=this;d(a.target).parents().each(function(){if(d.data(this,"sortable-item")==e){c=d(this);return false}});if(d.data(a.target,"sortable-item")==e)c=d(a.target);if(!c)return false;if(this.options.handle&&!b){var f=false;d(this.options.handle,c).find("*").andSelf().each(function(){if(this==a.target)f=true});if(!f)return false}this.currentItem=
+c;this._removeCurrentsFromItems();return true},_mouseStart:function(a,b,c){b=this.options;var e=this;this.currentContainer=this;this.refreshPositions();this.helper=this._createHelper(a);this._cacheHelperProportions();this._cacheMargins();this.scrollParent=this.helper.scrollParent();this.offset=this.currentItem.offset();this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left};this.helper.css("position","absolute");this.cssPosition=this.helper.css("position");d.extend(this.offset,
+{click:{left:a.pageX-this.offset.left,top:a.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()});this.originalPosition=this._generatePosition(a);this.originalPageX=a.pageX;this.originalPageY=a.pageY;b.cursorAt&&this._adjustOffsetFromHelper(b.cursorAt);this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]};this.helper[0]!=this.currentItem[0]&&this.currentItem.hide();this._createPlaceholder();b.containment&&this._setContainment();
+if(b.cursor){if(d("body").css("cursor"))this._storedCursor=d("body").css("cursor");d("body").css("cursor",b.cursor)}if(b.opacity){if(this.helper.css("opacity"))this._storedOpacity=this.helper.css("opacity");this.helper.css("opacity",b.opacity)}if(b.zIndex){if(this.helper.css("zIndex"))this._storedZIndex=this.helper.css("zIndex");this.helper.css("zIndex",b.zIndex)}if(this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML")this.overflowOffset=this.scrollParent.offset();this._trigger("start",
+a,this._uiHash());this._preserveHelperProportions||this._cacheHelperProportions();if(!c)for(c=this.containers.length-1;c>=0;c--)this.containers[c]._trigger("activate",a,e._uiHash(this));if(d.ui.ddmanager)d.ui.ddmanager.current=this;d.ui.ddmanager&&!b.dropBehaviour&&d.ui.ddmanager.prepareOffsets(this,a);this.dragging=true;this.helper.addClass("ui-sortable-helper");this._mouseDrag(a);return true},_mouseDrag:function(a){this.position=this._generatePosition(a);this.positionAbs=this._convertPositionTo("absolute");
+if(!this.lastPositionAbs)this.lastPositionAbs=this.positionAbs;if(this.options.scroll){var b=this.options,c=false;if(this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"){if(this.overflowOffset.top+this.scrollParent[0].offsetHeight-a.pageY<b.scrollSensitivity)this.scrollParent[0].scrollTop=c=this.scrollParent[0].scrollTop+b.scrollSpeed;else if(a.pageY-this.overflowOffset.top<b.scrollSensitivity)this.scrollParent[0].scrollTop=c=this.scrollParent[0].scrollTop-b.scrollSpeed;if(this.overflowOffset.left+
+this.scrollParent[0].offsetWidth-a.pageX<b.scrollSensitivity)this.scrollParent[0].scrollLeft=c=this.scrollParent[0].scrollLeft+b.scrollSpeed;else if(a.pageX-this.overflowOffset.left<b.scrollSensitivity)this.scrollParent[0].scrollLeft=c=this.scrollParent[0].scrollLeft-b.scrollSpeed}else{if(a.pageY-d(document).scrollTop()<b.scrollSensitivity)c=d(document).scrollTop(d(document).scrollTop()-b.scrollSpeed);else if(d(window).height()-(a.pageY-d(document).scrollTop())<b.scrollSensitivity)c=d(document).scrollTop(d(document).scrollTop()+
+b.scrollSpeed);if(a.pageX-d(document).scrollLeft()<b.scrollSensitivity)c=d(document).scrollLeft(d(document).scrollLeft()-b.scrollSpeed);else if(d(window).width()-(a.pageX-d(document).scrollLeft())<b.scrollSensitivity)c=d(document).scrollLeft(d(document).scrollLeft()+b.scrollSpeed)}c!==false&&d.ui.ddmanager&&!b.dropBehaviour&&d.ui.ddmanager.prepareOffsets(this,a)}this.positionAbs=this._convertPositionTo("absolute");if(!this.options.axis||this.options.axis!="y")this.helper[0].style.left=this.position.left+
+"px";if(!this.options.axis||this.options.axis!="x")this.helper[0].style.top=this.position.top+"px";for(b=this.items.length-1;b>=0;b--){c=this.items[b];var e=c.item[0],f=this._intersectsWithPointer(c);if(f)if(e!=this.currentItem[0]&&this.placeholder[f==1?"next":"prev"]()[0]!=e&&!d.ui.contains(this.placeholder[0],e)&&(this.options.type=="semi-dynamic"?!d.ui.contains(this.element[0],e):true)){this.direction=f==1?"down":"up";if(this.options.tolerance=="pointer"||this._intersectsWithSides(c))this._rearrange(a,
+c);else break;this._trigger("change",a,this._uiHash());break}}this._contactContainers(a);d.ui.ddmanager&&d.ui.ddmanager.drag(this,a);this._trigger("sort",a,this._uiHash());this.lastPositionAbs=this.positionAbs;return false},_mouseStop:function(a,b){if(a){d.ui.ddmanager&&!this.options.dropBehaviour&&d.ui.ddmanager.drop(this,a);if(this.options.revert){var c=this;b=c.placeholder.offset();c.reverting=true;d(this.helper).animate({left:b.left-this.offset.parent.left-c.margins.left+(this.offsetParent[0]==
+document.body?0:this.offsetParent[0].scrollLeft),top:b.top-this.offset.parent.top-c.margins.top+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollTop)},parseInt(this.options.revert,10)||500,function(){c._clear(a)})}else this._clear(a,b);return false}},cancel:function(){var a=this;if(this.dragging){this._mouseUp();this.options.helper=="original"?this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"):this.currentItem.show();for(var b=this.containers.length-1;b>=0;b--){this.containers[b]._trigger("deactivate",
+null,a._uiHash(this));if(this.containers[b].containerCache.over){this.containers[b]._trigger("out",null,a._uiHash(this));this.containers[b].containerCache.over=0}}}this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]);this.options.helper!="original"&&this.helper&&this.helper[0].parentNode&&this.helper.remove();d.extend(this,{helper:null,dragging:false,reverting:false,_noFinalSort:null});this.domPosition.prev?d(this.domPosition.prev).after(this.currentItem):
+d(this.domPosition.parent).prepend(this.currentItem);return this},serialize:function(a){var b=this._getItemsAsjQuery(a&&a.connected),c=[];a=a||{};d(b).each(function(){var e=(d(a.item||this).attr(a.attribute||"id")||"").match(a.expression||/(.+)[-=_](.+)/);if(e)c.push((a.key||e[1]+"[]")+"="+(a.key&&a.expression?e[1]:e[2]))});!c.length&&a.key&&c.push(a.key+"=");return c.join("&")},toArray:function(a){var b=this._getItemsAsjQuery(a&&a.connected),c=[];a=a||{};b.each(function(){c.push(d(a.item||this).attr(a.attribute||
+"id")||"")});return c},_intersectsWith:function(a){var b=this.positionAbs.left,c=b+this.helperProportions.width,e=this.positionAbs.top,f=e+this.helperProportions.height,g=a.left,h=g+a.width,i=a.top,k=i+a.height,j=this.offset.click.top,l=this.offset.click.left;j=e+j>i&&e+j<k&&b+l>g&&b+l<h;return this.options.tolerance=="pointer"||this.options.forcePointerForContainers||this.options.tolerance!="pointer"&&this.helperProportions[this.floating?"width":"height"]>a[this.floating?"width":"height"]?j:g<b+
+this.helperProportions.width/2&&c-this.helperProportions.width/2<h&&i<e+this.helperProportions.height/2&&f-this.helperProportions.height/2<k},_intersectsWithPointer:function(a){var b=d.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,a.top,a.height);a=d.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,a.left,a.width);b=b&&a;a=this._getDragVerticalDirection();var c=this._getDragHorizontalDirection();if(!b)return false;return this.floating?c&&c=="right"||a=="down"?2:1:a&&(a=="down"?
+2:1)},_intersectsWithSides:function(a){var b=d.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,a.top+a.height/2,a.height);a=d.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,a.left+a.width/2,a.width);var c=this._getDragVerticalDirection(),e=this._getDragHorizontalDirection();return this.floating&&e?e=="right"&&a||e=="left"&&!a:c&&(c=="down"&&b||c=="up"&&!b)},_getDragVerticalDirection:function(){var a=this.positionAbs.top-this.lastPositionAbs.top;return a!=0&&(a>0?"down":"up")},
+_getDragHorizontalDirection:function(){var a=this.positionAbs.left-this.lastPositionAbs.left;return a!=0&&(a>0?"right":"left")},refresh:function(a){this._refreshItems(a);this.refreshPositions();return this},_connectWith:function(){var a=this.options;return a.connectWith.constructor==String?[a.connectWith]:a.connectWith},_getItemsAsjQuery:function(a){var b=[],c=[],e=this._connectWith();if(e&&a)for(a=e.length-1;a>=0;a--)for(var f=d(e[a]),g=f.length-1;g>=0;g--){var h=d.data(f[g],"sortable");if(h&&h!=
+this&&!h.options.disabled)c.push([d.isFunction(h.options.items)?h.options.items.call(h.element):d(h.options.items,h.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),h])}c.push([d.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):d(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),this]);for(a=c.length-1;a>=0;a--)c[a][0].each(function(){b.push(this)});return d(b)},_removeCurrentsFromItems:function(){for(var a=
+this.currentItem.find(":data(sortable-item)"),b=0;b<this.items.length;b++)for(var c=0;c<a.length;c++)a[c]==this.items[b].item[0]&&this.items.splice(b,1)},_refreshItems:function(a){this.items=[];this.containers=[this];var b=this.items,c=[[d.isFunction(this.options.items)?this.options.items.call(this.element[0],a,{item:this.currentItem}):d(this.options.items,this.element),this]],e=this._connectWith();if(e)for(var f=e.length-1;f>=0;f--)for(var g=d(e[f]),h=g.length-1;h>=0;h--){var i=d.data(g[h],"sortable");
+if(i&&i!=this&&!i.options.disabled){c.push([d.isFunction(i.options.items)?i.options.items.call(i.element[0],a,{item:this.currentItem}):d(i.options.items,i.element),i]);this.containers.push(i)}}for(f=c.length-1;f>=0;f--){a=c[f][1];e=c[f][0];h=0;for(g=e.length;h<g;h++){i=d(e[h]);i.data("sortable-item",a);b.push({item:i,instance:a,width:0,height:0,left:0,top:0})}}},refreshPositions:function(a){if(this.offsetParent&&this.helper)this.offset.parent=this._getParentOffset();for(var b=this.items.length-1;b>=
+0;b--){var c=this.items[b],e=this.options.toleranceElement?d(this.options.toleranceElement,c.item):c.item;if(!a){c.width=e.outerWidth();c.height=e.outerHeight()}e=e.offset();c.left=e.left;c.top=e.top}if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(b=this.containers.length-1;b>=0;b--){e=this.containers[b].element.offset();this.containers[b].containerCache.left=e.left;this.containers[b].containerCache.top=e.top;this.containers[b].containerCache.width=
+this.containers[b].element.outerWidth();this.containers[b].containerCache.height=this.containers[b].element.outerHeight()}return this},_createPlaceholder:function(a){var b=a||this,c=b.options;if(!c.placeholder||c.placeholder.constructor==String){var e=c.placeholder;c.placeholder={element:function(){var f=d(document.createElement(b.currentItem[0].nodeName)).addClass(e||b.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper")[0];if(!e)f.style.visibility="hidden";return f},
+update:function(f,g){if(!(e&&!c.forcePlaceholderSize)){g.height()||g.height(b.currentItem.innerHeight()-parseInt(b.currentItem.css("paddingTop")||0,10)-parseInt(b.currentItem.css("paddingBottom")||0,10));g.width()||g.width(b.currentItem.innerWidth()-parseInt(b.currentItem.css("paddingLeft")||0,10)-parseInt(b.currentItem.css("paddingRight")||0,10))}}}}b.placeholder=d(c.placeholder.element.call(b.element,b.currentItem));b.currentItem.after(b.placeholder);c.placeholder.update(b,b.placeholder)},_contactContainers:function(a){for(var b=
+null,c=null,e=this.containers.length-1;e>=0;e--)if(!d.ui.contains(this.currentItem[0],this.containers[e].element[0]))if(this._intersectsWith(this.containers[e].containerCache)){if(!(b&&d.ui.contains(this.containers[e].element[0],b.element[0]))){b=this.containers[e];c=e}}else if(this.containers[e].containerCache.over){this.containers[e]._trigger("out",a,this._uiHash(this));this.containers[e].containerCache.over=0}if(b)if(this.containers.length===1){this.containers[c]._trigger("over",a,this._uiHash(this));
+this.containers[c].containerCache.over=1}else if(this.currentContainer!=this.containers[c]){b=1E4;e=null;for(var f=this.positionAbs[this.containers[c].floating?"left":"top"],g=this.items.length-1;g>=0;g--)if(d.ui.contains(this.containers[c].element[0],this.items[g].item[0])){var h=this.items[g][this.containers[c].floating?"left":"top"];if(Math.abs(h-f)<b){b=Math.abs(h-f);e=this.items[g]}}if(e||this.options.dropOnEmpty){this.currentContainer=this.containers[c];e?this._rearrange(a,e,null,true):this._rearrange(a,
+null,this.containers[c].element,true);this._trigger("change",a,this._uiHash());this.containers[c]._trigger("change",a,this._uiHash(this));this.options.placeholder.update(this.currentContainer,this.placeholder);this.containers[c]._trigger("over",a,this._uiHash(this));this.containers[c].containerCache.over=1}}},_createHelper:function(a){var b=this.options;a=d.isFunction(b.helper)?d(b.helper.apply(this.element[0],[a,this.currentItem])):b.helper=="clone"?this.currentItem.clone():this.currentItem;a.parents("body").length||
+d(b.appendTo!="parent"?b.appendTo:this.currentItem[0].parentNode)[0].appendChild(a[0]);if(a[0]==this.currentItem[0])this._storedCSS={width:this.currentItem[0].style.width,height:this.currentItem[0].style.height,position:this.currentItem.css("position"),top:this.currentItem.css("top"),left:this.currentItem.css("left")};if(a[0].style.width==""||b.forceHelperSize)a.width(this.currentItem.width());if(a[0].style.height==""||b.forceHelperSize)a.height(this.currentItem.height());return a},_adjustOffsetFromHelper:function(a){if(typeof a==
+"string")a=a.split(" ");if(d.isArray(a))a={left:+a[0],top:+a[1]||0};if("left"in a)this.offset.click.left=a.left+this.margins.left;if("right"in a)this.offset.click.left=this.helperProportions.width-a.right+this.margins.left;if("top"in a)this.offset.click.top=a.top+this.margins.top;if("bottom"in a)this.offset.click.top=this.helperProportions.height-a.bottom+this.margins.top},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var a=this.offsetParent.offset();if(this.cssPosition==
+"absolute"&&this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],this.offsetParent[0])){a.left+=this.scrollParent.scrollLeft();a.top+=this.scrollParent.scrollTop()}if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&d.browser.msie)a={top:0,left:0};return{top:a.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:a.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition==
+"relative"){var a=this.currentItem.position();return{top:a.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:a.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}else return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.currentItem.css("marginLeft"),10)||0,top:parseInt(this.currentItem.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},
+_setContainment:function(){var a=this.options;if(a.containment=="parent")a.containment=this.helper[0].parentNode;if(a.containment=="document"||a.containment=="window")this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,d(a.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(d(a.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-
+this.margins.top];if(!/^(document|window|parent)$/.test(a.containment)){var b=d(a.containment)[0];a=d(a.containment).offset();var c=d(b).css("overflow")!="hidden";this.containment=[a.left+(parseInt(d(b).css("borderLeftWidth"),10)||0)+(parseInt(d(b).css("paddingLeft"),10)||0)-this.margins.left,a.top+(parseInt(d(b).css("borderTopWidth"),10)||0)+(parseInt(d(b).css("paddingTop"),10)||0)-this.margins.top,a.left+(c?Math.max(b.scrollWidth,b.offsetWidth):b.offsetWidth)-(parseInt(d(b).css("borderLeftWidth"),
+10)||0)-(parseInt(d(b).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,a.top+(c?Math.max(b.scrollHeight,b.offsetHeight):b.offsetHeight)-(parseInt(d(b).css("borderTopWidth"),10)||0)-(parseInt(d(b).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top]}},_convertPositionTo:function(a,b){if(!b)b=this.position;a=a=="absolute"?1:-1;var c=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],this.offsetParent[0]))?
+this.offsetParent:this.scrollParent,e=/(html|body)/i.test(c[0].tagName);return{top:b.top+this.offset.relative.top*a+this.offset.parent.top*a-(d.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():e?0:c.scrollTop())*a),left:b.left+this.offset.relative.left*a+this.offset.parent.left*a-(d.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():e?0:c.scrollLeft())*a)}},_generatePosition:function(a){var b=
+this.options,c=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,e=/(html|body)/i.test(c[0].tagName);if(this.cssPosition=="relative"&&!(this.scrollParent[0]!=document&&this.scrollParent[0]!=this.offsetParent[0]))this.offset.relative=this._getRelativeOffset();var f=a.pageX,g=a.pageY;if(this.originalPosition){if(this.containment){if(a.pageX-this.offset.click.left<this.containment[0])f=this.containment[0]+
+this.offset.click.left;if(a.pageY-this.offset.click.top<this.containment[1])g=this.containment[1]+this.offset.click.top;if(a.pageX-this.offset.click.left>this.containment[2])f=this.containment[2]+this.offset.click.left;if(a.pageY-this.offset.click.top>this.containment[3])g=this.containment[3]+this.offset.click.top}if(b.grid){g=this.originalPageY+Math.round((g-this.originalPageY)/b.grid[1])*b.grid[1];g=this.containment?!(g-this.offset.click.top<this.containment[1]||g-this.offset.click.top>this.containment[3])?
+g:!(g-this.offset.click.top<this.containment[1])?g-b.grid[1]:g+b.grid[1]:g;f=this.originalPageX+Math.round((f-this.originalPageX)/b.grid[0])*b.grid[0];f=this.containment?!(f-this.offset.click.left<this.containment[0]||f-this.offset.click.left>this.containment[2])?f:!(f-this.offset.click.left<this.containment[0])?f-b.grid[0]:f+b.grid[0]:f}}return{top:g-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(d.browser.safari&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollTop():
+e?0:c.scrollTop()),left:f-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+(d.browser.safari&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():e?0:c.scrollLeft())}},_rearrange:function(a,b,c,e){c?c[0].appendChild(this.placeholder[0]):b.item[0].parentNode.insertBefore(this.placeholder[0],this.direction=="down"?b.item[0]:b.item[0].nextSibling);this.counter=this.counter?++this.counter:1;var f=this,g=this.counter;window.setTimeout(function(){g==
+f.counter&&f.refreshPositions(!e)},0)},_clear:function(a,b){this.reverting=false;var c=[];!this._noFinalSort&&this.currentItem[0].parentNode&&this.placeholder.before(this.currentItem);this._noFinalSort=null;if(this.helper[0]==this.currentItem[0]){for(var e in this._storedCSS)if(this._storedCSS[e]=="auto"||this._storedCSS[e]=="static")this._storedCSS[e]="";this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper")}else this.currentItem.show();this.fromOutside&&!b&&c.push(function(f){this._trigger("receive",
+f,this._uiHash(this.fromOutside))});if((this.fromOutside||this.domPosition.prev!=this.currentItem.prev().not(".ui-sortable-helper")[0]||this.domPosition.parent!=this.currentItem.parent()[0])&&!b)c.push(function(f){this._trigger("update",f,this._uiHash())});if(!d.ui.contains(this.element[0],this.currentItem[0])){b||c.push(function(f){this._trigger("remove",f,this._uiHash())});for(e=this.containers.length-1;e>=0;e--)if(d.ui.contains(this.containers[e].element[0],this.currentItem[0])&&!b){c.push(function(f){return function(g){f._trigger("receive",
+g,this._uiHash(this))}}.call(this,this.containers[e]));c.push(function(f){return function(g){f._trigger("update",g,this._uiHash(this))}}.call(this,this.containers[e]))}}for(e=this.containers.length-1;e>=0;e--){b||c.push(function(f){return function(g){f._trigger("deactivate",g,this._uiHash(this))}}.call(this,this.containers[e]));if(this.containers[e].containerCache.over){c.push(function(f){return function(g){f._trigger("out",g,this._uiHash(this))}}.call(this,this.containers[e]));this.containers[e].containerCache.over=
+0}}this._storedCursor&&d("body").css("cursor",this._storedCursor);this._storedOpacity&&this.helper.css("opacity",this._storedOpacity);if(this._storedZIndex)this.helper.css("zIndex",this._storedZIndex=="auto"?"":this._storedZIndex);this.dragging=false;if(this.cancelHelperRemoval){if(!b){this._trigger("beforeStop",a,this._uiHash());for(e=0;e<c.length;e++)c[e].call(this,a);this._trigger("stop",a,this._uiHash())}return false}b||this._trigger("beforeStop",a,this._uiHash());this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
+this.helper[0]!=this.currentItem[0]&&this.helper.remove();this.helper=null;if(!b){for(e=0;e<c.length;e++)c[e].call(this,a);this._trigger("stop",a,this._uiHash())}this.fromOutside=false;return true},_trigger:function(){d.Widget.prototype._trigger.apply(this,arguments)===false&&this.cancel()},_uiHash:function(a){var b=a||this;return{helper:b.helper,placeholder:b.placeholder||d([]),position:b.position,originalPosition:b.originalPosition,offset:b.positionAbs,item:b.currentItem,sender:a?a.element:null}}});
+d.extend(d.ui.sortable,{version:"1.8.4"})})(jQuery);
+;/*
+ * jQuery UI Accordion 1.8.4
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Accordion
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.widget.js
+ */
+(function(c){c.widget("ui.accordion",{options:{active:0,animated:"slide",autoHeight:true,clearStyle:false,collapsible:false,event:"click",fillSpace:false,header:"> li > :first-child,> :not(li):even",icons:{header:"ui-icon-triangle-1-e",headerSelected:"ui-icon-triangle-1-s"},navigation:false,navigationFilter:function(){return this.href.toLowerCase()===location.href.toLowerCase()}},_create:function(){var a=this,b=a.options;a.running=0;a.element.addClass("ui-accordion ui-widget ui-helper-reset").children("li").addClass("ui-accordion-li-fix");
+a.headers=a.element.find(b.header).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all").bind("mouseenter.accordion",function(){b.disabled||c(this).addClass("ui-state-hover")}).bind("mouseleave.accordion",function(){b.disabled||c(this).removeClass("ui-state-hover")}).bind("focus.accordion",function(){b.disabled||c(this).addClass("ui-state-focus")}).bind("blur.accordion",function(){b.disabled||c(this).removeClass("ui-state-focus")});a.headers.next().addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom");
+if(b.navigation){var d=a.element.find("a").filter(b.navigationFilter).eq(0);if(d.length){var f=d.closest(".ui-accordion-header");a.active=f.length?f:d.closest(".ui-accordion-content").prev()}}a.active=a._findActive(a.active||b.active).addClass("ui-state-default ui-state-active").toggleClass("ui-corner-all ui-corner-top");a.active.next().addClass("ui-accordion-content-active");a._createIcons();a.resize();a.element.attr("role","tablist");a.headers.attr("role","tab").bind("keydown.accordion",function(g){return a._keydown(g)}).next().attr("role",
+"tabpanel");a.headers.not(a.active||"").attr({"aria-expanded":"false",tabIndex:-1}).next().hide();a.active.length?a.active.attr({"aria-expanded":"true",tabIndex:0}):a.headers.eq(0).attr("tabIndex",0);c.browser.safari||a.headers.find("a").attr("tabIndex",-1);b.event&&a.headers.bind(b.event.split(" ").join(".accordion ")+".accordion",function(g){a._clickHandler.call(a,g,this);g.preventDefault()})},_createIcons:function(){var a=this.options;if(a.icons){c("<span></span>").addClass("ui-icon "+a.icons.header).prependTo(this.headers);
+this.active.children(".ui-icon").toggleClass(a.icons.header).toggleClass(a.icons.headerSelected);this.element.addClass("ui-accordion-icons")}},_destroyIcons:function(){this.headers.children(".ui-icon").remove();this.element.removeClass("ui-accordion-icons")},destroy:function(){var a=this.options;this.element.removeClass("ui-accordion ui-widget ui-helper-reset").removeAttr("role");this.headers.unbind(".accordion").removeClass("ui-accordion-header ui-accordion-disabled ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top").removeAttr("role").removeAttr("aria-expanded").removeAttr("tabIndex");
+this.headers.find("a").removeAttr("tabIndex");this._destroyIcons();var b=this.headers.next().css("display","").removeAttr("role").removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-accordion-disabled ui-state-disabled");if(a.autoHeight||a.fillHeight)b.css("height","");return c.Widget.prototype.destroy.call(this)},_setOption:function(a,b){c.Widget.prototype._setOption.apply(this,arguments);a=="active"&&this.activate(b);if(a=="icons"){this._destroyIcons();
+b&&this._createIcons()}if(a=="disabled")this.headers.add(this.headers.next())[b?"addClass":"removeClass"]("ui-accordion-disabled ui-state-disabled")},_keydown:function(a){if(!(this.options.disabled||a.altKey||a.ctrlKey)){var b=c.ui.keyCode,d=this.headers.length,f=this.headers.index(a.target),g=false;switch(a.keyCode){case b.RIGHT:case b.DOWN:g=this.headers[(f+1)%d];break;case b.LEFT:case b.UP:g=this.headers[(f-1+d)%d];break;case b.SPACE:case b.ENTER:this._clickHandler({target:a.target},a.target);
+a.preventDefault()}if(g){c(a.target).attr("tabIndex",-1);c(g).attr("tabIndex",0);g.focus();return false}return true}},resize:function(){var a=this.options,b;if(a.fillSpace){if(c.browser.msie){var d=this.element.parent().css("overflow");this.element.parent().css("overflow","hidden")}b=this.element.parent().height();c.browser.msie&&this.element.parent().css("overflow",d);this.headers.each(function(){b-=c(this).outerHeight(true)});this.headers.next().each(function(){c(this).height(Math.max(0,b-c(this).innerHeight()+
+c(this).height()))}).css("overflow","auto")}else if(a.autoHeight){b=0;this.headers.next().each(function(){b=Math.max(b,c(this).height("").height())}).height(b)}return this},activate:function(a){this.options.active=a;a=this._findActive(a)[0];this._clickHandler({target:a},a);return this},_findActive:function(a){return a?typeof a==="number"?this.headers.filter(":eq("+a+")"):this.headers.not(this.headers.not(a)):a===false?c([]):this.headers.filter(":eq(0)")},_clickHandler:function(a,b){var d=this.options;
+if(!d.disabled)if(a.target){a=c(a.currentTarget||b);b=a[0]===this.active[0];d.active=d.collapsible&&b?false:this.headers.index(a);if(!(this.running||!d.collapsible&&b)){this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all").children(".ui-icon").removeClass(d.icons.headerSelected).addClass(d.icons.header);if(!b){a.removeClass("ui-state-default ui-corner-all").addClass("ui-state-active ui-corner-top").children(".ui-icon").removeClass(d.icons.header).addClass(d.icons.headerSelected);
+a.next().addClass("ui-accordion-content-active")}h=a.next();f=this.active.next();g={options:d,newHeader:b&&d.collapsible?c([]):a,oldHeader:this.active,newContent:b&&d.collapsible?c([]):h,oldContent:f};d=this.headers.index(this.active[0])>this.headers.index(a[0]);this.active=b?c([]):a;this._toggle(h,f,g,b,d)}}else if(d.collapsible){this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all").children(".ui-icon").removeClass(d.icons.headerSelected).addClass(d.icons.header);
+this.active.next().addClass("ui-accordion-content-active");var f=this.active.next(),g={options:d,newHeader:c([]),oldHeader:d.active,newContent:c([]),oldContent:f},h=this.active=c([]);this._toggle(h,f,g)}},_toggle:function(a,b,d,f,g){var h=this,e=h.options;h.toShow=a;h.toHide=b;h.data=d;var j=function(){if(h)return h._completed.apply(h,arguments)};h._trigger("changestart",null,h.data);h.running=b.size()===0?a.size():b.size();if(e.animated){d={};d=e.collapsible&&f?{toShow:c([]),toHide:b,complete:j,
+down:g,autoHeight:e.autoHeight||e.fillSpace}:{toShow:a,toHide:b,complete:j,down:g,autoHeight:e.autoHeight||e.fillSpace};if(!e.proxied)e.proxied=e.animated;if(!e.proxiedDuration)e.proxiedDuration=e.duration;e.animated=c.isFunction(e.proxied)?e.proxied(d):e.proxied;e.duration=c.isFunction(e.proxiedDuration)?e.proxiedDuration(d):e.proxiedDuration;f=c.ui.accordion.animations;var i=e.duration,k=e.animated;if(k&&!f[k]&&!c.easing[k])k="slide";f[k]||(f[k]=function(l){this.slide(l,{easing:k,duration:i||700})});
+f[k](d)}else{if(e.collapsible&&f)a.toggle();else{b.hide();a.show()}j(true)}b.prev().attr({"aria-expanded":"false",tabIndex:-1}).blur();a.prev().attr({"aria-expanded":"true",tabIndex:0}).focus()},_completed:function(a){this.running=a?0:--this.running;if(!this.running){this.options.clearStyle&&this.toShow.add(this.toHide).css({height:"",overflow:""});this.toHide.removeClass("ui-accordion-content-active");this._trigger("change",null,this.data)}}});c.extend(c.ui.accordion,{version:"1.8.4",animations:{slide:function(a,
+b){a=c.extend({easing:"swing",duration:300},a,b);if(a.toHide.size())if(a.toShow.size()){var d=a.toShow.css("overflow"),f=0,g={},h={},e;b=a.toShow;e=b[0].style.width;b.width(parseInt(b.parent().width(),10)-parseInt(b.css("paddingLeft"),10)-parseInt(b.css("paddingRight"),10)-(parseInt(b.css("borderLeftWidth"),10)||0)-(parseInt(b.css("borderRightWidth"),10)||0));c.each(["height","paddingTop","paddingBottom"],function(j,i){h[i]="hide";j=(""+c.css(a.toShow[0],i)).match(/^([\d+-.]+)(.*)$/);g[i]={value:j[1],
+unit:j[2]||"px"}});a.toShow.css({height:0,overflow:"hidden"}).show();a.toHide.filter(":hidden").each(a.complete).end().filter(":visible").animate(h,{step:function(j,i){if(i.prop=="height")f=i.end-i.start===0?0:(i.now-i.start)/(i.end-i.start);a.toShow[0].style[i.prop]=f*g[i.prop].value+g[i.prop].unit},duration:a.duration,easing:a.easing,complete:function(){a.autoHeight||a.toShow.css("height","");a.toShow.css({width:e,overflow:d});a.complete()}})}else a.toHide.animate({height:"hide",paddingTop:"hide",
+paddingBottom:"hide"},a);else a.toShow.animate({height:"show",paddingTop:"show",paddingBottom:"show"},a)},bounceslide:function(a){this.slide(a,{easing:a.down?"easeOutBounce":"swing",duration:a.down?1E3:200})}}})})(jQuery);
+;/*
+ * jQuery UI Autocomplete 1.8.4
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Autocomplete
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.widget.js
+ * jquery.ui.position.js
+ */
+(function(e){e.widget("ui.autocomplete",{options:{appendTo:"body",delay:300,minLength:1,position:{my:"left top",at:"left bottom",collision:"none"},source:null},_create:function(){var a=this,b=this.element[0].ownerDocument;this.element.addClass("ui-autocomplete-input").attr("autocomplete","off").attr({role:"textbox","aria-autocomplete":"list","aria-haspopup":"true"}).bind("keydown.autocomplete",function(c){if(!a.options.disabled){var d=e.ui.keyCode;switch(c.keyCode){case d.PAGE_UP:a._move("previousPage",
+c);break;case d.PAGE_DOWN:a._move("nextPage",c);break;case d.UP:a._move("previous",c);c.preventDefault();break;case d.DOWN:a._move("next",c);c.preventDefault();break;case d.ENTER:case d.NUMPAD_ENTER:a.menu.element.is(":visible")&&c.preventDefault();case d.TAB:if(!a.menu.active)return;a.menu.select(c);break;case d.ESCAPE:a.element.val(a.term);a.close(c);break;default:clearTimeout(a.searching);a.searching=setTimeout(function(){if(a.term!=a.element.val()){a.selectedItem=null;a.search(null,c)}},a.options.delay);
+break}}}).bind("focus.autocomplete",function(){if(!a.options.disabled){a.selectedItem=null;a.previous=a.element.val()}}).bind("blur.autocomplete",function(c){if(!a.options.disabled){clearTimeout(a.searching);a.closing=setTimeout(function(){a.close(c);a._change(c)},150)}});this._initSource();this.response=function(){return a._response.apply(a,arguments)};this.menu=e("<ul></ul>").addClass("ui-autocomplete").appendTo(e(this.options.appendTo||"body",b)[0]).mousedown(function(c){var d=a.menu.element[0];
+c.target===d&&setTimeout(function(){e(document).one("mousedown",function(f){f.target!==a.element[0]&&f.target!==d&&!e.ui.contains(d,f.target)&&a.close()})},1);setTimeout(function(){clearTimeout(a.closing)},13)}).menu({focus:function(c,d){d=d.item.data("item.autocomplete");false!==a._trigger("focus",null,{item:d})&&/^key/.test(c.originalEvent.type)&&a.element.val(d.value)},selected:function(c,d){d=d.item.data("item.autocomplete");var f=a.previous;if(a.element[0]!==b.activeElement){a.element.focus();
+a.previous=f}false!==a._trigger("select",c,{item:d})&&a.element.val(d.value);a.close(c);a.selectedItem=d},blur:function(){a.menu.element.is(":visible")&&a.element.val()!==a.term&&a.element.val(a.term)}}).zIndex(this.element.zIndex()+1).css({top:0,left:0}).hide().data("menu");e.fn.bgiframe&&this.menu.element.bgiframe()},destroy:function(){this.element.removeClass("ui-autocomplete-input").removeAttr("autocomplete").removeAttr("role").removeAttr("aria-autocomplete").removeAttr("aria-haspopup");this.menu.element.remove();
+e.Widget.prototype.destroy.call(this)},_setOption:function(a,b){e.Widget.prototype._setOption.apply(this,arguments);a==="source"&&this._initSource();if(a==="appendTo")this.menu.element.appendTo(e(b||"body",this.element[0].ownerDocument)[0])},_initSource:function(){var a,b;if(e.isArray(this.options.source)){a=this.options.source;this.source=function(c,d){d(e.ui.autocomplete.filter(a,c.term))}}else if(typeof this.options.source==="string"){b=this.options.source;this.source=function(c,d){e.getJSON(b,
+c,d)}}else this.source=this.options.source},search:function(a,b){a=a!=null?a:this.element.val();if(a.length<this.options.minLength)return this.close(b);clearTimeout(this.closing);if(this._trigger("search")!==false)return this._search(a)},_search:function(a){this.term=this.element.addClass("ui-autocomplete-loading").val();this.source({term:a},this.response)},_response:function(a){if(a.length){a=this._normalize(a);this._suggest(a);this._trigger("open")}else this.close();this.element.removeClass("ui-autocomplete-loading")},
+close:function(a){clearTimeout(this.closing);if(this.menu.element.is(":visible")){this._trigger("close",a);this.menu.element.hide();this.menu.deactivate()}},_change:function(a){this.previous!==this.element.val()&&this._trigger("change",a,{item:this.selectedItem})},_normalize:function(a){if(a.length&&a[0].label&&a[0].value)return a;return e.map(a,function(b){if(typeof b==="string")return{label:b,value:b};return e.extend({label:b.label||b.value,value:b.value||b.label},b)})},_suggest:function(a){var b=
+this.menu.element.empty().zIndex(this.element.zIndex()+1),c;this._renderMenu(b,a);this.menu.deactivate();this.menu.refresh();this.menu.element.show().position(e.extend({of:this.element},this.options.position));a=b.width("").outerWidth();c=this.element.outerWidth();b.outerWidth(Math.max(a,c))},_renderMenu:function(a,b){var c=this;e.each(b,function(d,f){c._renderItem(a,f)})},_renderItem:function(a,b){return e("<li></li>").data("item.autocomplete",b).append(e("<a></a>").text(b.label)).appendTo(a)},_move:function(a,
+b){if(this.menu.element.is(":visible"))if(this.menu.first()&&/^previous/.test(a)||this.menu.last()&&/^next/.test(a)){this.element.val(this.term);this.menu.deactivate()}else this.menu[a](b);else this.search(null,b)},widget:function(){return this.menu.element}});e.extend(e.ui.autocomplete,{escapeRegex:function(a){return a.replace(/[-[\]{}()*+?.,\\^$|#\s]/g,"\\$&")},filter:function(a,b){var c=new RegExp(e.ui.autocomplete.escapeRegex(b),"i");return e.grep(a,function(d){return c.test(d.label||d.value||
+d)})}})})(jQuery);
+(function(e){e.widget("ui.menu",{_create:function(){var a=this;this.element.addClass("ui-menu ui-widget ui-widget-content ui-corner-all").attr({role:"listbox","aria-activedescendant":"ui-active-menuitem"}).click(function(b){if(e(b.target).closest(".ui-menu-item a").length){b.preventDefault();a.select(b)}});this.refresh()},refresh:function(){var a=this;this.element.children("li:not(.ui-menu-item):has(a)").addClass("ui-menu-item").attr("role","menuitem").children("a").addClass("ui-corner-all").attr("tabindex",-1).mouseenter(function(b){a.activate(b,
+e(this).parent())}).mouseleave(function(){a.deactivate()})},activate:function(a,b){this.deactivate();if(this.hasScroll()){var c=b.offset().top-this.element.offset().top,d=this.element.attr("scrollTop"),f=this.element.height();if(c<0)this.element.attr("scrollTop",d+c);else c>f&&this.element.attr("scrollTop",d+c-f+b.height())}this.active=b.eq(0).children("a").addClass("ui-state-hover").attr("id","ui-active-menuitem").end();this._trigger("focus",a,{item:b})},deactivate:function(){if(this.active){this.active.children("a").removeClass("ui-state-hover").removeAttr("id");
+this._trigger("blur");this.active=null}},next:function(a){this.move("next",".ui-menu-item:first",a)},previous:function(a){this.move("prev",".ui-menu-item:last",a)},first:function(){return this.active&&!this.active.prevAll(".ui-menu-item").length},last:function(){return this.active&&!this.active.nextAll(".ui-menu-item").length},move:function(a,b,c){if(this.active){a=this.active[a+"All"](".ui-menu-item").eq(0);a.length?this.activate(c,a):this.activate(c,this.element.children(b))}else this.activate(c,
+this.element.children(b))},nextPage:function(a){if(this.hasScroll())if(!this.active||this.last())this.activate(a,this.element.children(":first"));else{var b=this.active.offset().top,c=this.element.height(),d=this.element.children("li").filter(function(){var f=e(this).offset().top-b-c+e(this).height();return f<10&&f>-10});d.length||(d=this.element.children(":last"));this.activate(a,d)}else this.activate(a,this.element.children(!this.active||this.last()?":first":":last"))},previousPage:function(a){if(this.hasScroll())if(!this.active||
+this.first())this.activate(a,this.element.children(":last"));else{var b=this.active.offset().top,c=this.element.height();result=this.element.children("li").filter(function(){var d=e(this).offset().top-b+c-e(this).height();return d<10&&d>-10});result.length||(result=this.element.children(":first"));this.activate(a,result)}else this.activate(a,this.element.children(!this.active||this.first()?":last":":first"))},hasScroll:function(){return this.element.height()<this.element.attr("scrollHeight")},select:function(a){this._trigger("selected",
+a,{item:this.active})}})})(jQuery);
+;/*
+ * jQuery UI Button 1.8.4
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Button
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.widget.js
+ */
+(function(a){var g,i=function(b){a(":ui-button",b.target.form).each(function(){var c=a(this).data("button");setTimeout(function(){c.refresh()},1)})},h=function(b){var c=b.name,d=b.form,e=a([]);if(c)e=d?a(d).find("[name='"+c+"']"):a("[name='"+c+"']",b.ownerDocument).filter(function(){return!this.form});return e};a.widget("ui.button",{options:{text:true,label:null,icons:{primary:null,secondary:null}},_create:function(){this.element.closest("form").unbind("reset.button").bind("reset.button",i);this._determineButtonType();
+this.hasTitle=!!this.buttonElement.attr("title");var b=this,c=this.options,d=this.type==="checkbox"||this.type==="radio",e="ui-state-hover"+(!d?" ui-state-active":"");if(c.label===null)c.label=this.buttonElement.html();if(this.element.is(":disabled"))c.disabled=true;this.buttonElement.addClass("ui-button ui-widget ui-state-default ui-corner-all").attr("role","button").bind("mouseenter.button",function(){if(!c.disabled){a(this).addClass("ui-state-hover");this===g&&a(this).addClass("ui-state-active")}}).bind("mouseleave.button",
+function(){c.disabled||a(this).removeClass(e)}).bind("focus.button",function(){a(this).addClass("ui-state-focus")}).bind("blur.button",function(){a(this).removeClass("ui-state-focus")});d&&this.element.bind("change.button",function(){b.refresh()});if(this.type==="checkbox")this.buttonElement.bind("click.button",function(){if(c.disabled)return false;a(this).toggleClass("ui-state-active");b.buttonElement.attr("aria-pressed",b.element[0].checked)});else if(this.type==="radio")this.buttonElement.bind("click.button",
+function(){if(c.disabled)return false;a(this).addClass("ui-state-active");b.buttonElement.attr("aria-pressed",true);var f=b.element[0];h(f).not(f).map(function(){return a(this).button("widget")[0]}).removeClass("ui-state-active").attr("aria-pressed",false)});else{this.buttonElement.bind("mousedown.button",function(){if(c.disabled)return false;a(this).addClass("ui-state-active");g=this;a(document).one("mouseup",function(){g=null})}).bind("mouseup.button",function(){if(c.disabled)return false;a(this).removeClass("ui-state-active")}).bind("keydown.button",
+function(f){if(c.disabled)return false;if(f.keyCode==a.ui.keyCode.SPACE||f.keyCode==a.ui.keyCode.ENTER)a(this).addClass("ui-state-active")}).bind("keyup.button",function(){a(this).removeClass("ui-state-active")});this.buttonElement.is("a")&&this.buttonElement.keyup(function(f){f.keyCode===a.ui.keyCode.SPACE&&a(this).click()})}this._setOption("disabled",c.disabled)},_determineButtonType:function(){this.type=this.element.is(":checkbox")?"checkbox":this.element.is(":radio")?"radio":this.element.is("input")?
+"input":"button";if(this.type==="checkbox"||this.type==="radio"){this.buttonElement=this.element.parents().last().find("label[for="+this.element.attr("id")+"]");this.element.addClass("ui-helper-hidden-accessible");var b=this.element.is(":checked");b&&this.buttonElement.addClass("ui-state-active");this.buttonElement.attr("aria-pressed",b)}else this.buttonElement=this.element},widget:function(){return this.buttonElement},destroy:function(){this.element.removeClass("ui-helper-hidden-accessible");this.buttonElement.removeClass("ui-button ui-widget ui-state-default ui-corner-all ui-state-hover ui-state-active ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only").removeAttr("role").removeAttr("aria-pressed").html(this.buttonElement.find(".ui-button-text").html());
+this.hasTitle||this.buttonElement.removeAttr("title");a.Widget.prototype.destroy.call(this)},_setOption:function(b,c){a.Widget.prototype._setOption.apply(this,arguments);if(b==="disabled")c?this.element.attr("disabled",true):this.element.removeAttr("disabled");this._resetButton()},refresh:function(){var b=this.element.is(":disabled");b!==this.options.disabled&&this._setOption("disabled",b);if(this.type==="radio")h(this.element[0]).each(function(){a(this).is(":checked")?a(this).button("widget").addClass("ui-state-active").attr("aria-pressed",
+true):a(this).button("widget").removeClass("ui-state-active").attr("aria-pressed",false)});else if(this.type==="checkbox")this.element.is(":checked")?this.buttonElement.addClass("ui-state-active").attr("aria-pressed",true):this.buttonElement.removeClass("ui-state-active").attr("aria-pressed",false)},_resetButton:function(){if(this.type==="input")this.options.label&&this.element.val(this.options.label);else{var b=this.buttonElement.removeClass("ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only"),
+c=a("<span></span>").addClass("ui-button-text").html(this.options.label).appendTo(b.empty()).text(),d=this.options.icons,e=d.primary&&d.secondary;if(d.primary||d.secondary){b.addClass("ui-button-text-icon"+(e?"s":d.primary?"-primary":"-secondary"));d.primary&&b.prepend("<span class='ui-button-icon-primary ui-icon "+d.primary+"'></span>");d.secondary&&b.append("<span class='ui-button-icon-secondary ui-icon "+d.secondary+"'></span>");if(!this.options.text){b.addClass(e?"ui-button-icons-only":"ui-button-icon-only").removeClass("ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary");
+this.hasTitle||b.attr("title",c)}}else b.addClass("ui-button-text-only")}}});a.widget("ui.buttonset",{_create:function(){this.element.addClass("ui-buttonset");this._init()},_init:function(){this.refresh()},_setOption:function(b,c){b==="disabled"&&this.buttons.button("option",b,c);a.Widget.prototype._setOption.apply(this,arguments)},refresh:function(){this.buttons=this.element.find(":button, :submit, :reset, :checkbox, :radio, a, :data(button)").filter(":ui-button").button("refresh").end().not(":ui-button").button().end().map(function(){return a(this).button("widget")[0]}).removeClass("ui-corner-all ui-corner-left ui-corner-right").filter(":first").addClass("ui-corner-left").end().filter(":last").addClass("ui-corner-right").end().end()},
+destroy:function(){this.element.removeClass("ui-buttonset");this.buttons.map(function(){return a(this).button("widget")[0]}).removeClass("ui-corner-left ui-corner-right").end().button("destroy");a.Widget.prototype.destroy.call(this)}})})(jQuery);
+;/*
+ * jQuery UI Dialog 1.8.4
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Dialog
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.widget.js
+ * jquery.ui.button.js
+ * jquery.ui.draggable.js
+ * jquery.ui.mouse.js
+ * jquery.ui.position.js
+ * jquery.ui.resizable.js
+ */
+(function(c,j){c.widget("ui.dialog",{options:{autoOpen:true,buttons:{},closeOnEscape:true,closeText:"close",dialogClass:"",draggable:true,hide:null,height:"auto",maxHeight:false,maxWidth:false,minHeight:150,minWidth:150,modal:false,position:{my:"center",at:"center",of:window,collision:"fit",using:function(a){var b=c(this).css(a).offset().top;b<0&&c(this).css("top",a.top-b)}},resizable:true,show:null,stack:true,title:"",width:300,zIndex:1E3},_create:function(){this.originalTitle=this.element.attr("title");
+if(typeof this.originalTitle!=="string")this.originalTitle="";var a=this,b=a.options,d=b.title||a.originalTitle||"&#160;",f=c.ui.dialog.getTitleId(a.element),g=(a.uiDialog=c("<div></div>")).appendTo(document.body).hide().addClass("ui-dialog ui-widget ui-widget-content ui-corner-all "+b.dialogClass).css({zIndex:b.zIndex}).attr("tabIndex",-1).css("outline",0).keydown(function(i){if(b.closeOnEscape&&i.keyCode&&i.keyCode===c.ui.keyCode.ESCAPE){a.close(i);i.preventDefault()}}).attr({role:"dialog","aria-labelledby":f}).mousedown(function(i){a.moveToTop(false,
+i)});a.element.show().removeAttr("title").addClass("ui-dialog-content ui-widget-content").appendTo(g);var e=(a.uiDialogTitlebar=c("<div></div>")).addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix").prependTo(g),h=c('<a href="#"></a>').addClass("ui-dialog-titlebar-close ui-corner-all").attr("role","button").hover(function(){h.addClass("ui-state-hover")},function(){h.removeClass("ui-state-hover")}).focus(function(){h.addClass("ui-state-focus")}).blur(function(){h.removeClass("ui-state-focus")}).click(function(i){a.close(i);
+return false}).appendTo(e);(a.uiDialogTitlebarCloseText=c("<span></span>")).addClass("ui-icon ui-icon-closethick").text(b.closeText).appendTo(h);c("<span></span>").addClass("ui-dialog-title").attr("id",f).html(d).prependTo(e);if(c.isFunction(b.beforeclose)&&!c.isFunction(b.beforeClose))b.beforeClose=b.beforeclose;e.find("*").add(e).disableSelection();b.draggable&&c.fn.draggable&&a._makeDraggable();b.resizable&&c.fn.resizable&&a._makeResizable();a._createButtons(b.buttons);a._isOpen=false;c.fn.bgiframe&&
+g.bgiframe()},_init:function(){this.options.autoOpen&&this.open()},destroy:function(){var a=this;a.overlay&&a.overlay.destroy();a.uiDialog.hide();a.element.unbind(".dialog").removeData("dialog").removeClass("ui-dialog-content ui-widget-content").hide().appendTo("body");a.uiDialog.remove();a.originalTitle&&a.element.attr("title",a.originalTitle);return a},widget:function(){return this.uiDialog},close:function(a){var b=this,d;if(false!==b._trigger("beforeClose",a)){b.overlay&&b.overlay.destroy();b.uiDialog.unbind("keypress.ui-dialog");
+b._isOpen=false;if(b.options.hide)b.uiDialog.hide(b.options.hide,function(){b._trigger("close",a)});else{b.uiDialog.hide();b._trigger("close",a)}c.ui.dialog.overlay.resize();if(b.options.modal){d=0;c(".ui-dialog").each(function(){if(this!==b.uiDialog[0])d=Math.max(d,c(this).css("z-index"))});c.ui.dialog.maxZ=d}return b}},isOpen:function(){return this._isOpen},moveToTop:function(a,b){var d=this,f=d.options;if(f.modal&&!a||!f.stack&&!f.modal)return d._trigger("focus",b);if(f.zIndex>c.ui.dialog.maxZ)c.ui.dialog.maxZ=
+f.zIndex;if(d.overlay){c.ui.dialog.maxZ+=1;d.overlay.$el.css("z-index",c.ui.dialog.overlay.maxZ=c.ui.dialog.maxZ)}a={scrollTop:d.element.attr("scrollTop"),scrollLeft:d.element.attr("scrollLeft")};c.ui.dialog.maxZ+=1;d.uiDialog.css("z-index",c.ui.dialog.maxZ);d.element.attr(a);d._trigger("focus",b);return d},open:function(){if(!this._isOpen){var a=this,b=a.options,d=a.uiDialog;a.overlay=b.modal?new c.ui.dialog.overlay(a):null;d.next().length&&d.appendTo("body");a._size();a._position(b.position);d.show(b.show);
+a.moveToTop(true);b.modal&&d.bind("keypress.ui-dialog",function(f){if(f.keyCode===c.ui.keyCode.TAB){var g=c(":tabbable",this),e=g.filter(":first");g=g.filter(":last");if(f.target===g[0]&&!f.shiftKey){e.focus(1);return false}else if(f.target===e[0]&&f.shiftKey){g.focus(1);return false}}});c(a.element.find(":tabbable").get().concat(d.find(".ui-dialog-buttonpane :tabbable").get().concat(d.get()))).eq(0).focus();a._trigger("open");a._isOpen=true;return a}},_createButtons:function(a){var b=this,d=false,
+f=c("<div></div>").addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"),g=c("<div></div>").addClass("ui-dialog-buttonset").appendTo(f);b.uiDialog.find(".ui-dialog-buttonpane").remove();typeof a==="object"&&a!==null&&c.each(a,function(){return!(d=true)});if(d){c.each(a,function(e,h){e=c('<button type="button"></button>').text(e).click(function(){h.apply(b.element[0],arguments)}).appendTo(g);c.fn.button&&e.button()});f.appendTo(b.uiDialog)}},_makeDraggable:function(){function a(e){return{position:e.position,
+offset:e.offset}}var b=this,d=b.options,f=c(document),g;b.uiDialog.draggable({cancel:".ui-dialog-content, .ui-dialog-titlebar-close",handle:".ui-dialog-titlebar",containment:"document",start:function(e,h){g=d.height==="auto"?"auto":c(this).height();c(this).height(c(this).height()).addClass("ui-dialog-dragging");b._trigger("dragStart",e,a(h))},drag:function(e,h){b._trigger("drag",e,a(h))},stop:function(e,h){d.position=[h.position.left-f.scrollLeft(),h.position.top-f.scrollTop()];c(this).removeClass("ui-dialog-dragging").height(g);
+b._trigger("dragStop",e,a(h));c.ui.dialog.overlay.resize()}})},_makeResizable:function(a){function b(e){return{originalPosition:e.originalPosition,originalSize:e.originalSize,position:e.position,size:e.size}}a=a===j?this.options.resizable:a;var d=this,f=d.options,g=d.uiDialog.css("position");a=typeof a==="string"?a:"n,e,s,w,se,sw,ne,nw";d.uiDialog.resizable({cancel:".ui-dialog-content",containment:"document",alsoResize:d.element,maxWidth:f.maxWidth,maxHeight:f.maxHeight,minWidth:f.minWidth,minHeight:d._minHeight(),
+handles:a,start:function(e,h){c(this).addClass("ui-dialog-resizing");d._trigger("resizeStart",e,b(h))},resize:function(e,h){d._trigger("resize",e,b(h))},stop:function(e,h){c(this).removeClass("ui-dialog-resizing");f.height=c(this).height();f.width=c(this).width();d._trigger("resizeStop",e,b(h));c.ui.dialog.overlay.resize()}}).css("position",g).find(".ui-resizable-se").addClass("ui-icon ui-icon-grip-diagonal-se")},_minHeight:function(){var a=this.options;return a.height==="auto"?a.minHeight:Math.min(a.minHeight,
+a.height)},_position:function(a){var b=[],d=[0,0],f;if(a){if(typeof a==="string"||typeof a==="object"&&"0"in a){b=a.split?a.split(" "):[a[0],a[1]];if(b.length===1)b[1]=b[0];c.each(["left","top"],function(g,e){if(+b[g]===b[g]){d[g]=b[g];b[g]=e}});a={my:b.join(" "),at:b.join(" "),offset:d.join(" ")}}a=c.extend({},c.ui.dialog.prototype.options.position,a)}else a=c.ui.dialog.prototype.options.position;(f=this.uiDialog.is(":visible"))||this.uiDialog.show();this.uiDialog.css({top:0,left:0}).position(a);
+f||this.uiDialog.hide()},_setOption:function(a,b){var d=this,f=d.uiDialog,g=f.is(":data(resizable)"),e=false;switch(a){case "beforeclose":a="beforeClose";break;case "buttons":d._createButtons(b);e=true;break;case "closeText":d.uiDialogTitlebarCloseText.text(""+b);break;case "dialogClass":f.removeClass(d.options.dialogClass).addClass("ui-dialog ui-widget ui-widget-content ui-corner-all "+b);break;case "disabled":b?f.addClass("ui-dialog-disabled"):f.removeClass("ui-dialog-disabled");break;case "draggable":b?
+d._makeDraggable():f.draggable("destroy");break;case "height":e=true;break;case "maxHeight":g&&f.resizable("option","maxHeight",b);e=true;break;case "maxWidth":g&&f.resizable("option","maxWidth",b);e=true;break;case "minHeight":g&&f.resizable("option","minHeight",b);e=true;break;case "minWidth":g&&f.resizable("option","minWidth",b);e=true;break;case "position":d._position(b);break;case "resizable":g&&!b&&f.resizable("destroy");g&&typeof b==="string"&&f.resizable("option","handles",b);!g&&b!==false&&
+d._makeResizable(b);break;case "title":c(".ui-dialog-title",d.uiDialogTitlebar).html(""+(b||"&#160;"));break;case "width":e=true;break}c.Widget.prototype._setOption.apply(d,arguments);e&&d._size()},_size:function(){var a=this.options,b;this.element.css({width:"auto",minHeight:0,height:0});if(a.minWidth>a.width)a.width=a.minWidth;b=this.uiDialog.css({height:"auto",width:a.width}).height();this.element.css(a.height==="auto"?{minHeight:Math.max(a.minHeight-b,0),height:"auto"}:{minHeight:0,height:Math.max(a.height-
+b,0)}).show();this.uiDialog.is(":data(resizable)")&&this.uiDialog.resizable("option","minHeight",this._minHeight())}});c.extend(c.ui.dialog,{version:"1.8.4",uuid:0,maxZ:0,getTitleId:function(a){a=a.attr("id");if(!a){this.uuid+=1;a=this.uuid}return"ui-dialog-title-"+a},overlay:function(a){this.$el=c.ui.dialog.overlay.create(a)}});c.extend(c.ui.dialog.overlay,{instances:[],oldInstances:[],maxZ:0,events:c.map("focus,mousedown,mouseup,keydown,keypress,click".split(","),function(a){return a+".dialog-overlay"}).join(" "),
+create:function(a){if(this.instances.length===0){setTimeout(function(){c.ui.dialog.overlay.instances.length&&c(document).bind(c.ui.dialog.overlay.events,function(d){return c(d.target).zIndex()>=c.ui.dialog.overlay.maxZ})},1);c(document).bind("keydown.dialog-overlay",function(d){if(a.options.closeOnEscape&&d.keyCode&&d.keyCode===c.ui.keyCode.ESCAPE){a.close(d);d.preventDefault()}});c(window).bind("resize.dialog-overlay",c.ui.dialog.overlay.resize)}var b=(this.oldInstances.pop()||c("<div></div>").addClass("ui-widget-overlay")).appendTo(document.body).css({width:this.width(),
+height:this.height()});c.fn.bgiframe&&b.bgiframe();this.instances.push(b);return b},destroy:function(a){this.oldInstances.push(this.instances.splice(c.inArray(a,this.instances),1)[0]);this.instances.length===0&&c([document,window]).unbind(".dialog-overlay");a.remove();var b=0;c.each(this.instances,function(){b=Math.max(b,this.css("z-index"))});this.maxZ=b},height:function(){var a,b;if(c.browser.msie&&c.browser.version<7){a=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight);
+b=Math.max(document.documentElement.offsetHeight,document.body.offsetHeight);return a<b?c(window).height()+"px":a+"px"}else return c(document).height()+"px"},width:function(){var a,b;if(c.browser.msie&&c.browser.version<7){a=Math.max(document.documentElement.scrollWidth,document.body.scrollWidth);b=Math.max(document.documentElement.offsetWidth,document.body.offsetWidth);return a<b?c(window).width()+"px":a+"px"}else return c(document).width()+"px"},resize:function(){var a=c([]);c.each(c.ui.dialog.overlay.instances,
+function(){a=a.add(this)});a.css({width:0,height:0}).css({width:c.ui.dialog.overlay.width(),height:c.ui.dialog.overlay.height()})}});c.extend(c.ui.dialog.overlay.prototype,{destroy:function(){c.ui.dialog.overlay.destroy(this.$el)}})})(jQuery);
+;/*
+ * jQuery UI Slider 1.8.4
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Slider
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.mouse.js
+ * jquery.ui.widget.js
+ */
+(function(d){d.widget("ui.slider",d.ui.mouse,{widgetEventPrefix:"slide",options:{animate:false,distance:0,max:100,min:0,orientation:"horizontal",range:false,step:1,value:0,values:null},_create:function(){var a=this,b=this.options;this._mouseSliding=this._keySliding=false;this._animateOff=true;this._handleIndex=null;this._detectOrientation();this._mouseInit();this.element.addClass("ui-slider ui-slider-"+this.orientation+" ui-widget ui-widget-content ui-corner-all");b.disabled&&this.element.addClass("ui-slider-disabled ui-disabled");
+this.range=d([]);if(b.range){if(b.range===true){this.range=d("<div></div>");if(!b.values)b.values=[this._valueMin(),this._valueMin()];if(b.values.length&&b.values.length!==2)b.values=[b.values[0],b.values[0]]}else this.range=d("<div></div>");this.range.appendTo(this.element).addClass("ui-slider-range");if(b.range==="min"||b.range==="max")this.range.addClass("ui-slider-range-"+b.range);this.range.addClass("ui-widget-header")}d(".ui-slider-handle",this.element).length===0&&d("<a href='#'></a>").appendTo(this.element).addClass("ui-slider-handle");
+if(b.values&&b.values.length)for(;d(".ui-slider-handle",this.element).length<b.values.length;)d("<a href='#'></a>").appendTo(this.element).addClass("ui-slider-handle");this.handles=d(".ui-slider-handle",this.element).addClass("ui-state-default ui-corner-all");this.handle=this.handles.eq(0);this.handles.add(this.range).filter("a").click(function(c){c.preventDefault()}).hover(function(){b.disabled||d(this).addClass("ui-state-hover")},function(){d(this).removeClass("ui-state-hover")}).focus(function(){if(b.disabled)d(this).blur();
+else{d(".ui-slider .ui-state-focus").removeClass("ui-state-focus");d(this).addClass("ui-state-focus")}}).blur(function(){d(this).removeClass("ui-state-focus")});this.handles.each(function(c){d(this).data("index.ui-slider-handle",c)});this.handles.keydown(function(c){var e=true,f=d(this).data("index.ui-slider-handle"),h,g,i;if(!a.options.disabled){switch(c.keyCode){case d.ui.keyCode.HOME:case d.ui.keyCode.END:case d.ui.keyCode.PAGE_UP:case d.ui.keyCode.PAGE_DOWN:case d.ui.keyCode.UP:case d.ui.keyCode.RIGHT:case d.ui.keyCode.DOWN:case d.ui.keyCode.LEFT:e=
+false;if(!a._keySliding){a._keySliding=true;d(this).addClass("ui-state-active");h=a._start(c,f);if(h===false)return}break}i=a.options.step;h=a.options.values&&a.options.values.length?(g=a.values(f)):(g=a.value());switch(c.keyCode){case d.ui.keyCode.HOME:g=a._valueMin();break;case d.ui.keyCode.END:g=a._valueMax();break;case d.ui.keyCode.PAGE_UP:g=a._trimAlignValue(h+(a._valueMax()-a._valueMin())/5);break;case d.ui.keyCode.PAGE_DOWN:g=a._trimAlignValue(h-(a._valueMax()-a._valueMin())/5);break;case d.ui.keyCode.UP:case d.ui.keyCode.RIGHT:if(h===
+a._valueMax())return;g=a._trimAlignValue(h+i);break;case d.ui.keyCode.DOWN:case d.ui.keyCode.LEFT:if(h===a._valueMin())return;g=a._trimAlignValue(h-i);break}a._slide(c,f,g);return e}}).keyup(function(c){var e=d(this).data("index.ui-slider-handle");if(a._keySliding){a._keySliding=false;a._stop(c,e);a._change(c,e);d(this).removeClass("ui-state-active")}});this._refreshValue();this._animateOff=false},destroy:function(){this.handles.remove();this.range.remove();this.element.removeClass("ui-slider ui-slider-horizontal ui-slider-vertical ui-slider-disabled ui-widget ui-widget-content ui-corner-all").removeData("slider").unbind(".slider");
+this._mouseDestroy();return this},_mouseCapture:function(a){var b=this.options,c,e,f,h,g;if(b.disabled)return false;this.elementSize={width:this.element.outerWidth(),height:this.element.outerHeight()};this.elementOffset=this.element.offset();c=this._normValueFromMouse({x:a.pageX,y:a.pageY});e=this._valueMax()-this._valueMin()+1;h=this;this.handles.each(function(i){var j=Math.abs(c-h.values(i));if(e>j){e=j;f=d(this);g=i}});if(b.range===true&&this.values(1)===b.min){g+=1;f=d(this.handles[g])}if(this._start(a,
+g)===false)return false;this._mouseSliding=true;h._handleIndex=g;f.addClass("ui-state-active").focus();b=f.offset();this._clickOffset=!d(a.target).parents().andSelf().is(".ui-slider-handle")?{left:0,top:0}:{left:a.pageX-b.left-f.width()/2,top:a.pageY-b.top-f.height()/2-(parseInt(f.css("borderTopWidth"),10)||0)-(parseInt(f.css("borderBottomWidth"),10)||0)+(parseInt(f.css("marginTop"),10)||0)};this._slide(a,g,c);return this._animateOff=true},_mouseStart:function(){return true},_mouseDrag:function(a){var b=
+this._normValueFromMouse({x:a.pageX,y:a.pageY});this._slide(a,this._handleIndex,b);return false},_mouseStop:function(a){this.handles.removeClass("ui-state-active");this._mouseSliding=false;this._stop(a,this._handleIndex);this._change(a,this._handleIndex);this._clickOffset=this._handleIndex=null;return this._animateOff=false},_detectOrientation:function(){this.orientation=this.options.orientation==="vertical"?"vertical":"horizontal"},_normValueFromMouse:function(a){var b;if(this.orientation==="horizontal"){b=
+this.elementSize.width;a=a.x-this.elementOffset.left-(this._clickOffset?this._clickOffset.left:0)}else{b=this.elementSize.height;a=a.y-this.elementOffset.top-(this._clickOffset?this._clickOffset.top:0)}b=a/b;if(b>1)b=1;if(b<0)b=0;if(this.orientation==="vertical")b=1-b;a=this._valueMax()-this._valueMin();return this._trimAlignValue(this._valueMin()+b*a)},_start:function(a,b){var c={handle:this.handles[b],value:this.value()};if(this.options.values&&this.options.values.length){c.value=this.values(b);
+c.values=this.values()}return this._trigger("start",a,c)},_slide:function(a,b,c){var e;if(this.options.values&&this.options.values.length){e=this.values(b?0:1);if(this.options.values.length===2&&this.options.range===true&&(b===0&&c>e||b===1&&c<e))c=e;if(c!==this.values(b)){e=this.values();e[b]=c;a=this._trigger("slide",a,{handle:this.handles[b],value:c,values:e});this.values(b?0:1);a!==false&&this.values(b,c,true)}}else if(c!==this.value()){a=this._trigger("slide",a,{handle:this.handles[b],value:c});
+a!==false&&this.value(c)}},_stop:function(a,b){var c={handle:this.handles[b],value:this.value()};if(this.options.values&&this.options.values.length){c.value=this.values(b);c.values=this.values()}this._trigger("stop",a,c)},_change:function(a,b){if(!this._keySliding&&!this._mouseSliding){var c={handle:this.handles[b],value:this.value()};if(this.options.values&&this.options.values.length){c.value=this.values(b);c.values=this.values()}this._trigger("change",a,c)}},value:function(a){if(arguments.length){this.options.value=
+this._trimAlignValue(a);this._refreshValue();this._change(null,0)}return this._value()},values:function(a,b){var c,e,f;if(arguments.length>1){this.options.values[a]=this._trimAlignValue(b);this._refreshValue();this._change(null,a)}if(arguments.length)if(d.isArray(arguments[0])){c=this.options.values;e=arguments[0];for(f=0;f<c.length;f+=1){c[f]=this._trimAlignValue(e[f]);this._change(null,f)}this._refreshValue()}else return this.options.values&&this.options.values.length?this._values(a):this.value();
+else return this._values()},_setOption:function(a,b){var c,e=0;if(d.isArray(this.options.values))e=this.options.values.length;d.Widget.prototype._setOption.apply(this,arguments);switch(a){case "disabled":if(b){this.handles.filter(".ui-state-focus").blur();this.handles.removeClass("ui-state-hover");this.handles.attr("disabled","disabled");this.element.addClass("ui-disabled")}else{this.handles.removeAttr("disabled");this.element.removeClass("ui-disabled")}break;case "orientation":this._detectOrientation();
+this.element.removeClass("ui-slider-horizontal ui-slider-vertical").addClass("ui-slider-"+this.orientation);this._refreshValue();break;case "value":this._animateOff=true;this._refreshValue();this._change(null,0);this._animateOff=false;break;case "values":this._animateOff=true;this._refreshValue();for(c=0;c<e;c+=1)this._change(null,c);this._animateOff=false;break}},_value:function(){var a=this.options.value;return a=this._trimAlignValue(a)},_values:function(a){var b,c;if(arguments.length){b=this.options.values[a];
+return b=this._trimAlignValue(b)}else{b=this.options.values.slice();for(c=0;c<b.length;c+=1)b[c]=this._trimAlignValue(b[c]);return b}},_trimAlignValue:function(a){if(a<this._valueMin())return this._valueMin();if(a>this._valueMax())return this._valueMax();var b=this.options.step>0?this.options.step:1,c=a%b;a=a-c;if(Math.abs(c)*2>=b)a+=c>0?b:-b;return parseFloat(a.toFixed(5))},_valueMin:function(){return this.options.min},_valueMax:function(){return this.options.max},_refreshValue:function(){var a=
+this.options.range,b=this.options,c=this,e=!this._animateOff?b.animate:false,f,h={},g,i,j,l;if(this.options.values&&this.options.values.length)this.handles.each(function(k){f=(c.values(k)-c._valueMin())/(c._valueMax()-c._valueMin())*100;h[c.orientation==="horizontal"?"left":"bottom"]=f+"%";d(this).stop(1,1)[e?"animate":"css"](h,b.animate);if(c.options.range===true)if(c.orientation==="horizontal"){if(k===0)c.range.stop(1,1)[e?"animate":"css"]({left:f+"%"},b.animate);if(k===1)c.range[e?"animate":"css"]({width:f-
+g+"%"},{queue:false,duration:b.animate})}else{if(k===0)c.range.stop(1,1)[e?"animate":"css"]({bottom:f+"%"},b.animate);if(k===1)c.range[e?"animate":"css"]({height:f-g+"%"},{queue:false,duration:b.animate})}g=f});else{i=this.value();j=this._valueMin();l=this._valueMax();f=l!==j?(i-j)/(l-j)*100:0;h[c.orientation==="horizontal"?"left":"bottom"]=f+"%";this.handle.stop(1,1)[e?"animate":"css"](h,b.animate);if(a==="min"&&this.orientation==="horizontal")this.range.stop(1,1)[e?"animate":"css"]({width:f+"%"},
+b.animate);if(a==="max"&&this.orientation==="horizontal")this.range[e?"animate":"css"]({width:100-f+"%"},{queue:false,duration:b.animate});if(a==="min"&&this.orientation==="vertical")this.range.stop(1,1)[e?"animate":"css"]({height:f+"%"},b.animate);if(a==="max"&&this.orientation==="vertical")this.range[e?"animate":"css"]({height:100-f+"%"},{queue:false,duration:b.animate})}}});d.extend(d.ui.slider,{version:"1.8.4"})})(jQuery);
+;/*
+ * jQuery UI Tabs 1.8.4
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Tabs
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.widget.js
+ */
+(function(d,p){function u(){return++v}function w(){return++x}var v=0,x=0;d.widget("ui.tabs",{options:{add:null,ajaxOptions:null,cache:false,cookie:null,collapsible:false,disable:null,disabled:[],enable:null,event:"click",fx:null,idPrefix:"ui-tabs-",load:null,panelTemplate:"<div></div>",remove:null,select:null,show:null,spinner:"<em>Loading&#8230;</em>",tabTemplate:"<li><a href='#{href}'><span>#{label}</span></a></li>"},_create:function(){this._tabify(true)},_setOption:function(a,e){if(a=="selected")this.options.collapsible&&
+e==this.options.selected||this.select(e);else{this.options[a]=e;this._tabify()}},_tabId:function(a){return a.title&&a.title.replace(/\s/g,"_").replace(/[^A-Za-z0-9\-_:\.]/g,"")||this.options.idPrefix+u()},_sanitizeSelector:function(a){return a.replace(/:/g,"\\:")},_cookie:function(){var a=this.cookie||(this.cookie=this.options.cookie.name||"ui-tabs-"+w());return d.cookie.apply(null,[a].concat(d.makeArray(arguments)))},_ui:function(a,e){return{tab:a,panel:e,index:this.anchors.index(a)}},_cleanup:function(){this.lis.filter(".ui-state-processing").removeClass("ui-state-processing").find("span:data(label.tabs)").each(function(){var a=
+d(this);a.html(a.data("label.tabs")).removeData("label.tabs")})},_tabify:function(a){function e(g,f){g.css("display","");!d.support.opacity&&f.opacity&&g[0].style.removeAttribute("filter")}var b=this,c=this.options,h=/^#.+/;this.list=this.element.find("ol,ul").eq(0);this.lis=d("li:has(a[href])",this.list);this.anchors=this.lis.map(function(){return d("a",this)[0]});this.panels=d([]);this.anchors.each(function(g,f){var j=d(f).attr("href"),l=j.split("#")[0],q;if(l&&(l===location.toString().split("#")[0]||
+(q=d("base")[0])&&l===q.href)){j=f.hash;f.href=j}if(h.test(j))b.panels=b.panels.add(b._sanitizeSelector(j));else if(j!=="#"){d.data(f,"href.tabs",j);d.data(f,"load.tabs",j.replace(/#.*$/,""));j=b._tabId(f);f.href="#"+j;f=d("#"+j);if(!f.length){f=d(c.panelTemplate).attr("id",j).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").insertAfter(b.panels[g-1]||b.list);f.data("destroy.tabs",true)}b.panels=b.panels.add(f)}else c.disabled.push(g)});if(a){this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all");
+this.list.addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all");this.lis.addClass("ui-state-default ui-corner-top");this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom");if(c.selected===p){location.hash&&this.anchors.each(function(g,f){if(f.hash==location.hash){c.selected=g;return false}});if(typeof c.selected!=="number"&&c.cookie)c.selected=parseInt(b._cookie(),10);if(typeof c.selected!=="number"&&this.lis.filter(".ui-tabs-selected").length)c.selected=
+this.lis.index(this.lis.filter(".ui-tabs-selected"));c.selected=c.selected||(this.lis.length?0:-1)}else if(c.selected===null)c.selected=-1;c.selected=c.selected>=0&&this.anchors[c.selected]||c.selected<0?c.selected:0;c.disabled=d.unique(c.disabled.concat(d.map(this.lis.filter(".ui-state-disabled"),function(g){return b.lis.index(g)}))).sort();d.inArray(c.selected,c.disabled)!=-1&&c.disabled.splice(d.inArray(c.selected,c.disabled),1);this.panels.addClass("ui-tabs-hide");this.lis.removeClass("ui-tabs-selected ui-state-active");
+if(c.selected>=0&&this.anchors.length){this.panels.eq(c.selected).removeClass("ui-tabs-hide");this.lis.eq(c.selected).addClass("ui-tabs-selected ui-state-active");b.element.queue("tabs",function(){b._trigger("show",null,b._ui(b.anchors[c.selected],b.panels[c.selected]))});this.load(c.selected)}d(window).bind("unload",function(){b.lis.add(b.anchors).unbind(".tabs");b.lis=b.anchors=b.panels=null})}else c.selected=this.lis.index(this.lis.filter(".ui-tabs-selected"));this.element[c.collapsible?"addClass":
+"removeClass"]("ui-tabs-collapsible");c.cookie&&this._cookie(c.selected,c.cookie);a=0;for(var i;i=this.lis[a];a++)d(i)[d.inArray(a,c.disabled)!=-1&&!d(i).hasClass("ui-tabs-selected")?"addClass":"removeClass"]("ui-state-disabled");c.cache===false&&this.anchors.removeData("cache.tabs");this.lis.add(this.anchors).unbind(".tabs");if(c.event!=="mouseover"){var k=function(g,f){f.is(":not(.ui-state-disabled)")&&f.addClass("ui-state-"+g)},n=function(g,f){f.removeClass("ui-state-"+g)};this.lis.bind("mouseover.tabs",
+function(){k("hover",d(this))});this.lis.bind("mouseout.tabs",function(){n("hover",d(this))});this.anchors.bind("focus.tabs",function(){k("focus",d(this).closest("li"))});this.anchors.bind("blur.tabs",function(){n("focus",d(this).closest("li"))})}var m,o;if(c.fx)if(d.isArray(c.fx)){m=c.fx[0];o=c.fx[1]}else m=o=c.fx;var r=o?function(g,f){d(g).closest("li").addClass("ui-tabs-selected ui-state-active");f.hide().removeClass("ui-tabs-hide").animate(o,o.duration||"normal",function(){e(f,o);b._trigger("show",
+null,b._ui(g,f[0]))})}:function(g,f){d(g).closest("li").addClass("ui-tabs-selected ui-state-active");f.removeClass("ui-tabs-hide");b._trigger("show",null,b._ui(g,f[0]))},s=m?function(g,f){f.animate(m,m.duration||"normal",function(){b.lis.removeClass("ui-tabs-selected ui-state-active");f.addClass("ui-tabs-hide");e(f,m);b.element.dequeue("tabs")})}:function(g,f){b.lis.removeClass("ui-tabs-selected ui-state-active");f.addClass("ui-tabs-hide");b.element.dequeue("tabs")};this.anchors.bind(c.event+".tabs",
+function(){var g=this,f=d(g).closest("li"),j=b.panels.filter(":not(.ui-tabs-hide)"),l=d(b._sanitizeSelector(g.hash));if(f.hasClass("ui-tabs-selected")&&!c.collapsible||f.hasClass("ui-state-disabled")||f.hasClass("ui-state-processing")||b._trigger("select",null,b._ui(this,l[0]))===false){this.blur();return false}c.selected=b.anchors.index(this);b.abort();if(c.collapsible)if(f.hasClass("ui-tabs-selected")){c.selected=-1;c.cookie&&b._cookie(c.selected,c.cookie);b.element.queue("tabs",function(){s(g,
+j)}).dequeue("tabs");this.blur();return false}else if(!j.length){c.cookie&&b._cookie(c.selected,c.cookie);b.element.queue("tabs",function(){r(g,l)});b.load(b.anchors.index(this));this.blur();return false}c.cookie&&b._cookie(c.selected,c.cookie);if(l.length){j.length&&b.element.queue("tabs",function(){s(g,j)});b.element.queue("tabs",function(){r(g,l)});b.load(b.anchors.index(this))}else throw"jQuery UI Tabs: Mismatching fragment identifier.";d.browser.msie&&this.blur()});this.anchors.bind("click.tabs",
+function(){return false})},_getIndex:function(a){if(typeof a=="string")a=this.anchors.index(this.anchors.filter("[href$="+a+"]"));return a},destroy:function(){var a=this.options;this.abort();this.element.unbind(".tabs").removeClass("ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible").removeData("tabs");this.list.removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all");this.anchors.each(function(){var e=d.data(this,"href.tabs");if(e)this.href=
+e;var b=d(this).unbind(".tabs");d.each(["href","load","cache"],function(c,h){b.removeData(h+".tabs")})});this.lis.unbind(".tabs").add(this.panels).each(function(){d.data(this,"destroy.tabs")?d(this).remove():d(this).removeClass("ui-state-default ui-corner-top ui-tabs-selected ui-state-active ui-state-hover ui-state-focus ui-state-disabled ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide")});a.cookie&&this._cookie(null,a.cookie);return this},add:function(a,e,b){if(b===p)b=this.anchors.length;
+var c=this,h=this.options;e=d(h.tabTemplate.replace(/#\{href\}/g,a).replace(/#\{label\}/g,e));a=!a.indexOf("#")?a.replace("#",""):this._tabId(d("a",e)[0]);e.addClass("ui-state-default ui-corner-top").data("destroy.tabs",true);var i=d("#"+a);i.length||(i=d(h.panelTemplate).attr("id",a).data("destroy.tabs",true));i.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide");if(b>=this.lis.length){e.appendTo(this.list);i.appendTo(this.list[0].parentNode)}else{e.insertBefore(this.lis[b]);
+i.insertBefore(this.panels[b])}h.disabled=d.map(h.disabled,function(k){return k>=b?++k:k});this._tabify();if(this.anchors.length==1){h.selected=0;e.addClass("ui-tabs-selected ui-state-active");i.removeClass("ui-tabs-hide");this.element.queue("tabs",function(){c._trigger("show",null,c._ui(c.anchors[0],c.panels[0]))});this.load(0)}this._trigger("add",null,this._ui(this.anchors[b],this.panels[b]));return this},remove:function(a){a=this._getIndex(a);var e=this.options,b=this.lis.eq(a).remove(),c=this.panels.eq(a).remove();
+if(b.hasClass("ui-tabs-selected")&&this.anchors.length>1)this.select(a+(a+1<this.anchors.length?1:-1));e.disabled=d.map(d.grep(e.disabled,function(h){return h!=a}),function(h){return h>=a?--h:h});this._tabify();this._trigger("remove",null,this._ui(b.find("a")[0],c[0]));return this},enable:function(a){a=this._getIndex(a);var e=this.options;if(d.inArray(a,e.disabled)!=-1){this.lis.eq(a).removeClass("ui-state-disabled");e.disabled=d.grep(e.disabled,function(b){return b!=a});this._trigger("enable",null,
+this._ui(this.anchors[a],this.panels[a]));return this}},disable:function(a){a=this._getIndex(a);var e=this.options;if(a!=e.selected){this.lis.eq(a).addClass("ui-state-disabled");e.disabled.push(a);e.disabled.sort();this._trigger("disable",null,this._ui(this.anchors[a],this.panels[a]))}return this},select:function(a){a=this._getIndex(a);if(a==-1)if(this.options.collapsible&&this.options.selected!=-1)a=this.options.selected;else return this;this.anchors.eq(a).trigger(this.options.event+".tabs");return this},
+load:function(a){a=this._getIndex(a);var e=this,b=this.options,c=this.anchors.eq(a)[0],h=d.data(c,"load.tabs");this.abort();if(!h||this.element.queue("tabs").length!==0&&d.data(c,"cache.tabs"))this.element.dequeue("tabs");else{this.lis.eq(a).addClass("ui-state-processing");if(b.spinner){var i=d("span",c);i.data("label.tabs",i.html()).html(b.spinner)}this.xhr=d.ajax(d.extend({},b.ajaxOptions,{url:h,success:function(k,n){d(e._sanitizeSelector(c.hash)).html(k);e._cleanup();b.cache&&d.data(c,"cache.tabs",
+true);e._trigger("load",null,e._ui(e.anchors[a],e.panels[a]));try{b.ajaxOptions.success(k,n)}catch(m){}},error:function(k,n){e._cleanup();e._trigger("load",null,e._ui(e.anchors[a],e.panels[a]));try{b.ajaxOptions.error(k,n,a,c)}catch(m){}}}));e.element.dequeue("tabs");return this}},abort:function(){this.element.queue([]);this.panels.stop(false,true);this.element.queue("tabs",this.element.queue("tabs").splice(-2,2));if(this.xhr){this.xhr.abort();delete this.xhr}this._cleanup();return this},url:function(a,
+e){this.anchors.eq(a).removeData("cache.tabs").data("load.tabs",e);return this},length:function(){return this.anchors.length}});d.extend(d.ui.tabs,{version:"1.8.4"});d.extend(d.ui.tabs.prototype,{rotation:null,rotate:function(a,e){var b=this,c=this.options,h=b._rotate||(b._rotate=function(i){clearTimeout(b.rotation);b.rotation=setTimeout(function(){var k=c.selected;b.select(++k<b.anchors.length?k:0)},a);i&&i.stopPropagation()});e=b._unrotate||(b._unrotate=!e?function(i){i.clientX&&b.rotate(null)}:
+function(){t=c.selected;h()});if(a){this.element.bind("tabsshow",h);this.anchors.bind(c.event+".tabs",e);h()}else{clearTimeout(b.rotation);this.element.unbind("tabsshow",h);this.anchors.unbind(c.event+".tabs",e);delete this._rotate;delete this._unrotate}return this}})})(jQuery);
+;/*
+ * jQuery UI Datepicker 1.8.4
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Datepicker
+ *
+ * Depends:
+ * jquery.ui.core.js
+ */
+(function(d,G){function L(){this.debug=false;this._curInst=null;this._keyEvent=false;this._disabledInputs=[];this._inDialog=this._datepickerShowing=false;this._mainDivId="ui-datepicker-div";this._inlineClass="ui-datepicker-inline";this._appendClass="ui-datepicker-append";this._triggerClass="ui-datepicker-trigger";this._dialogClass="ui-datepicker-dialog";this._disableClass="ui-datepicker-disabled";this._unselectableClass="ui-datepicker-unselectable";this._currentClass="ui-datepicker-current-day";this._dayOverClass=
+"ui-datepicker-days-cell-over";this.regional=[];this.regional[""]={closeText:"Done",prevText:"Prev",nextText:"Next",currentText:"Today",monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su",
+"Mo","Tu","We","Th","Fr","Sa"],weekHeader:"Wk",dateFormat:"mm/dd/yy",firstDay:0,isRTL:false,showMonthAfterYear:false,yearSuffix:""};this._defaults={showOn:"focus",showAnim:"fadeIn",showOptions:{},defaultDate:null,appendText:"",buttonText:"...",buttonImage:"",buttonImageOnly:false,hideIfNoPrevNext:false,navigationAsDateFormat:false,gotoCurrent:false,changeMonth:false,changeYear:false,yearRange:"c-10:c+10",showOtherMonths:false,selectOtherMonths:false,showWeek:false,calculateWeek:this.iso8601Week,shortYearCutoff:"+10",
+minDate:null,maxDate:null,duration:"fast",beforeShowDay:null,beforeShow:null,onSelect:null,onChangeMonthYear:null,onClose:null,numberOfMonths:1,showCurrentAtPos:0,stepMonths:1,stepBigMonths:12,altField:"",altFormat:"",constrainInput:true,showButtonPanel:false,autoSize:false};d.extend(this._defaults,this.regional[""]);this.dpDiv=d('<div id="'+this._mainDivId+'" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all ui-helper-hidden-accessible"></div>')}function E(a,b){d.extend(a,
+b);for(var c in b)if(b[c]==null||b[c]==G)a[c]=b[c];return a}d.extend(d.ui,{datepicker:{version:"1.8.4"}});var y=(new Date).getTime();d.extend(L.prototype,{markerClassName:"hasDatepicker",log:function(){this.debug&&console.log.apply("",arguments)},_widgetDatepicker:function(){return this.dpDiv},setDefaults:function(a){E(this._defaults,a||{});return this},_attachDatepicker:function(a,b){var c=null;for(var e in this._defaults){var f=a.getAttribute("date:"+e);if(f){c=c||{};try{c[e]=eval(f)}catch(h){c[e]=
+f}}}e=a.nodeName.toLowerCase();f=e=="div"||e=="span";if(!a.id){this.uuid+=1;a.id="dp"+this.uuid}var i=this._newInst(d(a),f);i.settings=d.extend({},b||{},c||{});if(e=="input")this._connectDatepicker(a,i);else f&&this._inlineDatepicker(a,i)},_newInst:function(a,b){return{id:a[0].id.replace(/([^A-Za-z0-9_])/g,"\\\\$1"),input:a,selectedDay:0,selectedMonth:0,selectedYear:0,drawMonth:0,drawYear:0,inline:b,dpDiv:!b?this.dpDiv:d('<div class="'+this._inlineClass+' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>')}},
+_connectDatepicker:function(a,b){var c=d(a);b.append=d([]);b.trigger=d([]);if(!c.hasClass(this.markerClassName)){this._attachments(c,b);c.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).keyup(this._doKeyUp).bind("setData.datepicker",function(e,f,h){b.settings[f]=h}).bind("getData.datepicker",function(e,f){return this._get(b,f)});this._autoSize(b);d.data(a,"datepicker",b)}},_attachments:function(a,b){var c=this._get(b,"appendText"),e=this._get(b,"isRTL");b.append&&
+b.append.remove();if(c){b.append=d('<span class="'+this._appendClass+'">'+c+"</span>");a[e?"before":"after"](b.append)}a.unbind("focus",this._showDatepicker);b.trigger&&b.trigger.remove();c=this._get(b,"showOn");if(c=="focus"||c=="both")a.focus(this._showDatepicker);if(c=="button"||c=="both"){c=this._get(b,"buttonText");var f=this._get(b,"buttonImage");b.trigger=d(this._get(b,"buttonImageOnly")?d("<img/>").addClass(this._triggerClass).attr({src:f,alt:c,title:c}):d('<button type="button"></button>').addClass(this._triggerClass).html(f==
+""?c:d("<img/>").attr({src:f,alt:c,title:c})));a[e?"before":"after"](b.trigger);b.trigger.click(function(){d.datepicker._datepickerShowing&&d.datepicker._lastInput==a[0]?d.datepicker._hideDatepicker():d.datepicker._showDatepicker(a[0]);return false})}},_autoSize:function(a){if(this._get(a,"autoSize")&&!a.inline){var b=new Date(2009,11,20),c=this._get(a,"dateFormat");if(c.match(/[DM]/)){var e=function(f){for(var h=0,i=0,g=0;g<f.length;g++)if(f[g].length>h){h=f[g].length;i=g}return i};b.setMonth(e(this._get(a,
+c.match(/MM/)?"monthNames":"monthNamesShort")));b.setDate(e(this._get(a,c.match(/DD/)?"dayNames":"dayNamesShort"))+20-b.getDay())}a.input.attr("size",this._formatDate(a,b).length)}},_inlineDatepicker:function(a,b){var c=d(a);if(!c.hasClass(this.markerClassName)){c.addClass(this.markerClassName).append(b.dpDiv).bind("setData.datepicker",function(e,f,h){b.settings[f]=h}).bind("getData.datepicker",function(e,f){return this._get(b,f)});d.data(a,"datepicker",b);this._setDate(b,this._getDefaultDate(b),
+true);this._updateDatepicker(b);this._updateAlternate(b)}},_dialogDatepicker:function(a,b,c,e,f){a=this._dialogInst;if(!a){this.uuid+=1;this._dialogInput=d('<input type="text" id="'+("dp"+this.uuid)+'" style="position: absolute; top: -100px; width: 0px; z-index: -10;"/>');this._dialogInput.keydown(this._doKeyDown);d("body").append(this._dialogInput);a=this._dialogInst=this._newInst(this._dialogInput,false);a.settings={};d.data(this._dialogInput[0],"datepicker",a)}E(a.settings,e||{});b=b&&b.constructor==
+Date?this._formatDate(a,b):b;this._dialogInput.val(b);this._pos=f?f.length?f:[f.pageX,f.pageY]:null;if(!this._pos)this._pos=[document.documentElement.clientWidth/2-100+(document.documentElement.scrollLeft||document.body.scrollLeft),document.documentElement.clientHeight/2-150+(document.documentElement.scrollTop||document.body.scrollTop)];this._dialogInput.css("left",this._pos[0]+20+"px").css("top",this._pos[1]+"px");a.settings.onSelect=c;this._inDialog=true;this.dpDiv.addClass(this._dialogClass);this._showDatepicker(this._dialogInput[0]);
+d.blockUI&&d.blockUI(this.dpDiv);d.data(this._dialogInput[0],"datepicker",a);return this},_destroyDatepicker:function(a){var b=d(a),c=d.data(a,"datepicker");if(b.hasClass(this.markerClassName)){var e=a.nodeName.toLowerCase();d.removeData(a,"datepicker");if(e=="input"){c.append.remove();c.trigger.remove();b.removeClass(this.markerClassName).unbind("focus",this._showDatepicker).unbind("keydown",this._doKeyDown).unbind("keypress",this._doKeyPress).unbind("keyup",this._doKeyUp)}else if(e=="div"||e=="span")b.removeClass(this.markerClassName).empty()}},
+_enableDatepicker:function(a){var b=d(a),c=d.data(a,"datepicker");if(b.hasClass(this.markerClassName)){var e=a.nodeName.toLowerCase();if(e=="input"){a.disabled=false;c.trigger.filter("button").each(function(){this.disabled=false}).end().filter("img").css({opacity:"1.0",cursor:""})}else if(e=="div"||e=="span")b.children("."+this._inlineClass).children().removeClass("ui-state-disabled");this._disabledInputs=d.map(this._disabledInputs,function(f){return f==a?null:f})}},_disableDatepicker:function(a){var b=
+d(a),c=d.data(a,"datepicker");if(b.hasClass(this.markerClassName)){var e=a.nodeName.toLowerCase();if(e=="input"){a.disabled=true;c.trigger.filter("button").each(function(){this.disabled=true}).end().filter("img").css({opacity:"0.5",cursor:"default"})}else if(e=="div"||e=="span")b.children("."+this._inlineClass).children().addClass("ui-state-disabled");this._disabledInputs=d.map(this._disabledInputs,function(f){return f==a?null:f});this._disabledInputs[this._disabledInputs.length]=a}},_isDisabledDatepicker:function(a){if(!a)return false;
+for(var b=0;b<this._disabledInputs.length;b++)if(this._disabledInputs[b]==a)return true;return false},_getInst:function(a){try{return d.data(a,"datepicker")}catch(b){throw"Missing instance data for this datepicker";}},_optionDatepicker:function(a,b,c){var e=this._getInst(a);if(arguments.length==2&&typeof b=="string")return b=="defaults"?d.extend({},d.datepicker._defaults):e?b=="all"?d.extend({},e.settings):this._get(e,b):null;var f=b||{};if(typeof b=="string"){f={};f[b]=c}if(e){this._curInst==e&&
+this._hideDatepicker();var h=this._getDateDatepicker(a,true);E(e.settings,f);this._attachments(d(a),e);this._autoSize(e);this._setDateDatepicker(a,h);this._updateDatepicker(e)}},_changeDatepicker:function(a,b,c){this._optionDatepicker(a,b,c)},_refreshDatepicker:function(a){(a=this._getInst(a))&&this._updateDatepicker(a)},_setDateDatepicker:function(a,b){if(a=this._getInst(a)){this._setDate(a,b);this._updateDatepicker(a);this._updateAlternate(a)}},_getDateDatepicker:function(a,b){(a=this._getInst(a))&&
+!a.inline&&this._setDateFromField(a,b);return a?this._getDate(a):null},_doKeyDown:function(a){var b=d.datepicker._getInst(a.target),c=true,e=b.dpDiv.is(".ui-datepicker-rtl");b._keyEvent=true;if(d.datepicker._datepickerShowing)switch(a.keyCode){case 9:d.datepicker._hideDatepicker();c=false;break;case 13:c=d("td."+d.datepicker._dayOverClass,b.dpDiv).add(d("td."+d.datepicker._currentClass,b.dpDiv));c[0]?d.datepicker._selectDay(a.target,b.selectedMonth,b.selectedYear,c[0]):d.datepicker._hideDatepicker();
+return false;case 27:d.datepicker._hideDatepicker();break;case 33:d.datepicker._adjustDate(a.target,a.ctrlKey?-d.datepicker._get(b,"stepBigMonths"):-d.datepicker._get(b,"stepMonths"),"M");break;case 34:d.datepicker._adjustDate(a.target,a.ctrlKey?+d.datepicker._get(b,"stepBigMonths"):+d.datepicker._get(b,"stepMonths"),"M");break;case 35:if(a.ctrlKey||a.metaKey)d.datepicker._clearDate(a.target);c=a.ctrlKey||a.metaKey;break;case 36:if(a.ctrlKey||a.metaKey)d.datepicker._gotoToday(a.target);c=a.ctrlKey||
+a.metaKey;break;case 37:if(a.ctrlKey||a.metaKey)d.datepicker._adjustDate(a.target,e?+1:-1,"D");c=a.ctrlKey||a.metaKey;if(a.originalEvent.altKey)d.datepicker._adjustDate(a.target,a.ctrlKey?-d.datepicker._get(b,"stepBigMonths"):-d.datepicker._get(b,"stepMonths"),"M");break;case 38:if(a.ctrlKey||a.metaKey)d.datepicker._adjustDate(a.target,-7,"D");c=a.ctrlKey||a.metaKey;break;case 39:if(a.ctrlKey||a.metaKey)d.datepicker._adjustDate(a.target,e?-1:+1,"D");c=a.ctrlKey||a.metaKey;if(a.originalEvent.altKey)d.datepicker._adjustDate(a.target,
+a.ctrlKey?+d.datepicker._get(b,"stepBigMonths"):+d.datepicker._get(b,"stepMonths"),"M");break;case 40:if(a.ctrlKey||a.metaKey)d.datepicker._adjustDate(a.target,+7,"D");c=a.ctrlKey||a.metaKey;break;default:c=false}else if(a.keyCode==36&&a.ctrlKey)d.datepicker._showDatepicker(this);else c=false;if(c){a.preventDefault();a.stopPropagation()}},_doKeyPress:function(a){var b=d.datepicker._getInst(a.target);if(d.datepicker._get(b,"constrainInput")){b=d.datepicker._possibleChars(d.datepicker._get(b,"dateFormat"));
+var c=String.fromCharCode(a.charCode==G?a.keyCode:a.charCode);return a.ctrlKey||c<" "||!b||b.indexOf(c)>-1}},_doKeyUp:function(a){a=d.datepicker._getInst(a.target);if(a.input.val()!=a.lastVal)try{if(d.datepicker.parseDate(d.datepicker._get(a,"dateFormat"),a.input?a.input.val():null,d.datepicker._getFormatConfig(a))){d.datepicker._setDateFromField(a);d.datepicker._updateAlternate(a);d.datepicker._updateDatepicker(a)}}catch(b){d.datepicker.log(b)}return true},_showDatepicker:function(a){a=a.target||
+a;if(a.nodeName.toLowerCase()!="input")a=d("input",a.parentNode)[0];if(!(d.datepicker._isDisabledDatepicker(a)||d.datepicker._lastInput==a)){var b=d.datepicker._getInst(a);d.datepicker._curInst&&d.datepicker._curInst!=b&&d.datepicker._curInst.dpDiv.stop(true,true);var c=d.datepicker._get(b,"beforeShow");E(b.settings,c?c.apply(a,[a,b]):{});b.lastVal=null;d.datepicker._lastInput=a;d.datepicker._setDateFromField(b);if(d.datepicker._inDialog)a.value="";if(!d.datepicker._pos){d.datepicker._pos=d.datepicker._findPos(a);
+d.datepicker._pos[1]+=a.offsetHeight}var e=false;d(a).parents().each(function(){e|=d(this).css("position")=="fixed";return!e});if(e&&d.browser.opera){d.datepicker._pos[0]-=document.documentElement.scrollLeft;d.datepicker._pos[1]-=document.documentElement.scrollTop}c={left:d.datepicker._pos[0],top:d.datepicker._pos[1]};d.datepicker._pos=null;b.dpDiv.css({position:"absolute",display:"block",top:"-1000px"});d.datepicker._updateDatepicker(b);c=d.datepicker._checkOffset(b,c,e);b.dpDiv.css({position:d.datepicker._inDialog&&
+d.blockUI?"static":e?"fixed":"absolute",display:"none",left:c.left+"px",top:c.top+"px"});if(!b.inline){c=d.datepicker._get(b,"showAnim");var f=d.datepicker._get(b,"duration"),h=function(){d.datepicker._datepickerShowing=true;var i=d.datepicker._getBorders(b.dpDiv);b.dpDiv.find("iframe.ui-datepicker-cover").css({left:-i[0],top:-i[1],width:b.dpDiv.outerWidth(),height:b.dpDiv.outerHeight()})};b.dpDiv.zIndex(d(a).zIndex()+1);d.effects&&d.effects[c]?b.dpDiv.show(c,d.datepicker._get(b,"showOptions"),f,
+h):b.dpDiv[c||"show"](c?f:null,h);if(!c||!f)h();b.input.is(":visible")&&!b.input.is(":disabled")&&b.input.focus();d.datepicker._curInst=b}}},_updateDatepicker:function(a){var b=this,c=d.datepicker._getBorders(a.dpDiv);a.dpDiv.empty().append(this._generateHTML(a)).find("iframe.ui-datepicker-cover").css({left:-c[0],top:-c[1],width:a.dpDiv.outerWidth(),height:a.dpDiv.outerHeight()}).end().find("button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a").bind("mouseout",function(){d(this).removeClass("ui-state-hover");
+this.className.indexOf("ui-datepicker-prev")!=-1&&d(this).removeClass("ui-datepicker-prev-hover");this.className.indexOf("ui-datepicker-next")!=-1&&d(this).removeClass("ui-datepicker-next-hover")}).bind("mouseover",function(){if(!b._isDisabledDatepicker(a.inline?a.dpDiv.parent()[0]:a.input[0])){d(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover");d(this).addClass("ui-state-hover");this.className.indexOf("ui-datepicker-prev")!=-1&&d(this).addClass("ui-datepicker-prev-hover");
+this.className.indexOf("ui-datepicker-next")!=-1&&d(this).addClass("ui-datepicker-next-hover")}}).end().find("."+this._dayOverClass+" a").trigger("mouseover").end();c=this._getNumberOfMonths(a);var e=c[1];e>1?a.dpDiv.addClass("ui-datepicker-multi-"+e).css("width",17*e+"em"):a.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width("");a.dpDiv[(c[0]!=1||c[1]!=1?"add":"remove")+"Class"]("ui-datepicker-multi");a.dpDiv[(this._get(a,"isRTL")?"add":"remove")+"Class"]("ui-datepicker-rtl");
+a==d.datepicker._curInst&&d.datepicker._datepickerShowing&&a.input&&a.input.is(":visible")&&!a.input.is(":disabled")&&a.input.focus()},_getBorders:function(a){var b=function(c){return{thin:1,medium:2,thick:3}[c]||c};return[parseFloat(b(a.css("border-left-width"))),parseFloat(b(a.css("border-top-width")))]},_checkOffset:function(a,b,c){var e=a.dpDiv.outerWidth(),f=a.dpDiv.outerHeight(),h=a.input?a.input.outerWidth():0,i=a.input?a.input.outerHeight():0,g=document.documentElement.clientWidth+d(document).scrollLeft(),
+k=document.documentElement.clientHeight+d(document).scrollTop();b.left-=this._get(a,"isRTL")?e-h:0;b.left-=c&&b.left==a.input.offset().left?d(document).scrollLeft():0;b.top-=c&&b.top==a.input.offset().top+i?d(document).scrollTop():0;b.left-=Math.min(b.left,b.left+e>g&&g>e?Math.abs(b.left+e-g):0);b.top-=Math.min(b.top,b.top+f>k&&k>f?Math.abs(f+i):0);return b},_findPos:function(a){for(var b=this._get(this._getInst(a),"isRTL");a&&(a.type=="hidden"||a.nodeType!=1);)a=a[b?"previousSibling":"nextSibling"];
+a=d(a).offset();return[a.left,a.top]},_hideDatepicker:function(a){var b=this._curInst;if(!(!b||a&&b!=d.data(a,"datepicker")))if(this._datepickerShowing){a=this._get(b,"showAnim");var c=this._get(b,"duration"),e=function(){d.datepicker._tidyDialog(b);this._curInst=null};d.effects&&d.effects[a]?b.dpDiv.hide(a,d.datepicker._get(b,"showOptions"),c,e):b.dpDiv[a=="slideDown"?"slideUp":a=="fadeIn"?"fadeOut":"hide"](a?c:null,e);a||e();if(a=this._get(b,"onClose"))a.apply(b.input?b.input[0]:null,[b.input?b.input.val():
+"",b]);this._datepickerShowing=false;this._lastInput=null;if(this._inDialog){this._dialogInput.css({position:"absolute",left:"0",top:"-100px"});if(d.blockUI){d.unblockUI();d("body").append(this.dpDiv)}}this._inDialog=false}},_tidyDialog:function(a){a.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar")},_checkExternalClick:function(a){if(d.datepicker._curInst){a=d(a.target);a[0].id!=d.datepicker._mainDivId&&a.parents("#"+d.datepicker._mainDivId).length==0&&!a.hasClass(d.datepicker.markerClassName)&&
+!a.hasClass(d.datepicker._triggerClass)&&d.datepicker._datepickerShowing&&!(d.datepicker._inDialog&&d.blockUI)&&d.datepicker._hideDatepicker()}},_adjustDate:function(a,b,c){a=d(a);var e=this._getInst(a[0]);if(!this._isDisabledDatepicker(a[0])){this._adjustInstDate(e,b+(c=="M"?this._get(e,"showCurrentAtPos"):0),c);this._updateDatepicker(e)}},_gotoToday:function(a){a=d(a);var b=this._getInst(a[0]);if(this._get(b,"gotoCurrent")&&b.currentDay){b.selectedDay=b.currentDay;b.drawMonth=b.selectedMonth=b.currentMonth;
+b.drawYear=b.selectedYear=b.currentYear}else{var c=new Date;b.selectedDay=c.getDate();b.drawMonth=b.selectedMonth=c.getMonth();b.drawYear=b.selectedYear=c.getFullYear()}this._notifyChange(b);this._adjustDate(a)},_selectMonthYear:function(a,b,c){a=d(a);var e=this._getInst(a[0]);e._selectingMonthYear=false;e["selected"+(c=="M"?"Month":"Year")]=e["draw"+(c=="M"?"Month":"Year")]=parseInt(b.options[b.selectedIndex].value,10);this._notifyChange(e);this._adjustDate(a)},_clickMonthYear:function(a){var b=
+this._getInst(d(a)[0]);b.input&&b._selectingMonthYear&&setTimeout(function(){b.input.focus()},0);b._selectingMonthYear=!b._selectingMonthYear},_selectDay:function(a,b,c,e){var f=d(a);if(!(d(e).hasClass(this._unselectableClass)||this._isDisabledDatepicker(f[0]))){f=this._getInst(f[0]);f.selectedDay=f.currentDay=d("a",e).html();f.selectedMonth=f.currentMonth=b;f.selectedYear=f.currentYear=c;this._selectDate(a,this._formatDate(f,f.currentDay,f.currentMonth,f.currentYear))}},_clearDate:function(a){a=
+d(a);this._getInst(a[0]);this._selectDate(a,"")},_selectDate:function(a,b){a=this._getInst(d(a)[0]);b=b!=null?b:this._formatDate(a);a.input&&a.input.val(b);this._updateAlternate(a);var c=this._get(a,"onSelect");if(c)c.apply(a.input?a.input[0]:null,[b,a]);else a.input&&a.input.trigger("change");if(a.inline)this._updateDatepicker(a);else{this._hideDatepicker();this._lastInput=a.input[0];typeof a.input[0]!="object"&&a.input.focus();this._lastInput=null}},_updateAlternate:function(a){var b=this._get(a,
+"altField");if(b){var c=this._get(a,"altFormat")||this._get(a,"dateFormat"),e=this._getDate(a),f=this.formatDate(c,e,this._getFormatConfig(a));d(b).each(function(){d(this).val(f)})}},noWeekends:function(a){a=a.getDay();return[a>0&&a<6,""]},iso8601Week:function(a){a=new Date(a.getTime());a.setDate(a.getDate()+4-(a.getDay()||7));var b=a.getTime();a.setMonth(0);a.setDate(1);return Math.floor(Math.round((b-a)/864E5)/7)+1},parseDate:function(a,b,c){if(a==null||b==null)throw"Invalid arguments";b=typeof b==
+"object"?b.toString():b+"";if(b=="")return null;for(var e=(c?c.shortYearCutoff:null)||this._defaults.shortYearCutoff,f=(c?c.dayNamesShort:null)||this._defaults.dayNamesShort,h=(c?c.dayNames:null)||this._defaults.dayNames,i=(c?c.monthNamesShort:null)||this._defaults.monthNamesShort,g=(c?c.monthNames:null)||this._defaults.monthNames,k=c=-1,l=-1,u=-1,j=false,o=function(p){(p=z+1<a.length&&a.charAt(z+1)==p)&&z++;return p},m=function(p){o(p);p=new RegExp("^\\d{1,"+(p=="@"?14:p=="!"?20:p=="y"?4:p=="o"?
+3:2)+"}");p=b.substring(s).match(p);if(!p)throw"Missing number at position "+s;s+=p[0].length;return parseInt(p[0],10)},n=function(p,w,H){p=o(p)?H:w;for(w=0;w<p.length;w++)if(b.substr(s,p[w].length)==p[w]){s+=p[w].length;return w+1}throw"Unknown name at position "+s;},r=function(){if(b.charAt(s)!=a.charAt(z))throw"Unexpected literal at position "+s;s++},s=0,z=0;z<a.length;z++)if(j)if(a.charAt(z)=="'"&&!o("'"))j=false;else r();else switch(a.charAt(z)){case "d":l=m("d");break;case "D":n("D",f,h);break;
+case "o":u=m("o");break;case "m":k=m("m");break;case "M":k=n("M",i,g);break;case "y":c=m("y");break;case "@":var v=new Date(m("@"));c=v.getFullYear();k=v.getMonth()+1;l=v.getDate();break;case "!":v=new Date((m("!")-this._ticksTo1970)/1E4);c=v.getFullYear();k=v.getMonth()+1;l=v.getDate();break;case "'":if(o("'"))r();else j=true;break;default:r()}if(c==-1)c=(new Date).getFullYear();else if(c<100)c+=(new Date).getFullYear()-(new Date).getFullYear()%100+(c<=e?0:-100);if(u>-1){k=1;l=u;do{e=this._getDaysInMonth(c,
+k-1);if(l<=e)break;k++;l-=e}while(1)}v=this._daylightSavingAdjust(new Date(c,k-1,l));if(v.getFullYear()!=c||v.getMonth()+1!=k||v.getDate()!=l)throw"Invalid date";return v},ATOM:"yy-mm-dd",COOKIE:"D, dd M yy",ISO_8601:"yy-mm-dd",RFC_822:"D, d M y",RFC_850:"DD, dd-M-y",RFC_1036:"D, d M y",RFC_1123:"D, d M yy",RFC_2822:"D, d M yy",RSS:"D, d M y",TICKS:"!",TIMESTAMP:"@",W3C:"yy-mm-dd",_ticksTo1970:(718685+Math.floor(492.5)-Math.floor(19.7)+Math.floor(4.925))*24*60*60*1E7,formatDate:function(a,b,c){if(!b)return"";
+var e=(c?c.dayNamesShort:null)||this._defaults.dayNamesShort,f=(c?c.dayNames:null)||this._defaults.dayNames,h=(c?c.monthNamesShort:null)||this._defaults.monthNamesShort;c=(c?c.monthNames:null)||this._defaults.monthNames;var i=function(o){(o=j+1<a.length&&a.charAt(j+1)==o)&&j++;return o},g=function(o,m,n){m=""+m;if(i(o))for(;m.length<n;)m="0"+m;return m},k=function(o,m,n,r){return i(o)?r[m]:n[m]},l="",u=false;if(b)for(var j=0;j<a.length;j++)if(u)if(a.charAt(j)=="'"&&!i("'"))u=false;else l+=a.charAt(j);
+else switch(a.charAt(j)){case "d":l+=g("d",b.getDate(),2);break;case "D":l+=k("D",b.getDay(),e,f);break;case "o":l+=g("o",(b.getTime()-(new Date(b.getFullYear(),0,0)).getTime())/864E5,3);break;case "m":l+=g("m",b.getMonth()+1,2);break;case "M":l+=k("M",b.getMonth(),h,c);break;case "y":l+=i("y")?b.getFullYear():(b.getYear()%100<10?"0":"")+b.getYear()%100;break;case "@":l+=b.getTime();break;case "!":l+=b.getTime()*1E4+this._ticksTo1970;break;case "'":if(i("'"))l+="'";else u=true;break;default:l+=a.charAt(j)}return l},
+_possibleChars:function(a){for(var b="",c=false,e=function(h){(h=f+1<a.length&&a.charAt(f+1)==h)&&f++;return h},f=0;f<a.length;f++)if(c)if(a.charAt(f)=="'"&&!e("'"))c=false;else b+=a.charAt(f);else switch(a.charAt(f)){case "d":case "m":case "y":case "@":b+="0123456789";break;case "D":case "M":return null;case "'":if(e("'"))b+="'";else c=true;break;default:b+=a.charAt(f)}return b},_get:function(a,b){return a.settings[b]!==G?a.settings[b]:this._defaults[b]},_setDateFromField:function(a,b){if(a.input.val()!=
+a.lastVal){var c=this._get(a,"dateFormat"),e=a.lastVal=a.input?a.input.val():null,f,h;f=h=this._getDefaultDate(a);var i=this._getFormatConfig(a);try{f=this.parseDate(c,e,i)||h}catch(g){this.log(g);e=b?"":e}a.selectedDay=f.getDate();a.drawMonth=a.selectedMonth=f.getMonth();a.drawYear=a.selectedYear=f.getFullYear();a.currentDay=e?f.getDate():0;a.currentMonth=e?f.getMonth():0;a.currentYear=e?f.getFullYear():0;this._adjustInstDate(a)}},_getDefaultDate:function(a){return this._restrictMinMax(a,this._determineDate(a,
+this._get(a,"defaultDate"),new Date))},_determineDate:function(a,b,c){var e=function(h){var i=new Date;i.setDate(i.getDate()+h);return i},f=function(h){try{return d.datepicker.parseDate(d.datepicker._get(a,"dateFormat"),h,d.datepicker._getFormatConfig(a))}catch(i){}var g=(h.toLowerCase().match(/^c/)?d.datepicker._getDate(a):null)||new Date,k=g.getFullYear(),l=g.getMonth();g=g.getDate();for(var u=/([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,j=u.exec(h);j;){switch(j[2]||"d"){case "d":case "D":g+=parseInt(j[1],
+10);break;case "w":case "W":g+=parseInt(j[1],10)*7;break;case "m":case "M":l+=parseInt(j[1],10);g=Math.min(g,d.datepicker._getDaysInMonth(k,l));break;case "y":case "Y":k+=parseInt(j[1],10);g=Math.min(g,d.datepicker._getDaysInMonth(k,l));break}j=u.exec(h)}return new Date(k,l,g)};if(b=(b=b==null?c:typeof b=="string"?f(b):typeof b=="number"?isNaN(b)?c:e(b):b)&&b.toString()=="Invalid Date"?c:b){b.setHours(0);b.setMinutes(0);b.setSeconds(0);b.setMilliseconds(0)}return this._daylightSavingAdjust(b)},_daylightSavingAdjust:function(a){if(!a)return null;
+a.setHours(a.getHours()>12?a.getHours()+2:0);return a},_setDate:function(a,b,c){var e=!b,f=a.selectedMonth,h=a.selectedYear;b=this._restrictMinMax(a,this._determineDate(a,b,new Date));a.selectedDay=a.currentDay=b.getDate();a.drawMonth=a.selectedMonth=a.currentMonth=b.getMonth();a.drawYear=a.selectedYear=a.currentYear=b.getFullYear();if((f!=a.selectedMonth||h!=a.selectedYear)&&!c)this._notifyChange(a);this._adjustInstDate(a);if(a.input)a.input.val(e?"":this._formatDate(a))},_getDate:function(a){return!a.currentYear||
+a.input&&a.input.val()==""?null:this._daylightSavingAdjust(new Date(a.currentYear,a.currentMonth,a.currentDay))},_generateHTML:function(a){var b=new Date;b=this._daylightSavingAdjust(new Date(b.getFullYear(),b.getMonth(),b.getDate()));var c=this._get(a,"isRTL"),e=this._get(a,"showButtonPanel"),f=this._get(a,"hideIfNoPrevNext"),h=this._get(a,"navigationAsDateFormat"),i=this._getNumberOfMonths(a),g=this._get(a,"showCurrentAtPos"),k=this._get(a,"stepMonths"),l=i[0]!=1||i[1]!=1,u=this._daylightSavingAdjust(!a.currentDay?
+new Date(9999,9,9):new Date(a.currentYear,a.currentMonth,a.currentDay)),j=this._getMinMaxDate(a,"min"),o=this._getMinMaxDate(a,"max");g=a.drawMonth-g;var m=a.drawYear;if(g<0){g+=12;m--}if(o){var n=this._daylightSavingAdjust(new Date(o.getFullYear(),o.getMonth()-i[0]*i[1]+1,o.getDate()));for(n=j&&n<j?j:n;this._daylightSavingAdjust(new Date(m,g,1))>n;){g--;if(g<0){g=11;m--}}}a.drawMonth=g;a.drawYear=m;n=this._get(a,"prevText");n=!h?n:this.formatDate(n,this._daylightSavingAdjust(new Date(m,g-k,1)),this._getFormatConfig(a));
+n=this._canAdjustMonth(a,-1,m,g)?'<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery_'+y+".datepicker._adjustDate('#"+a.id+"', -"+k+", 'M');\" title=\""+n+'"><span class="ui-icon ui-icon-circle-triangle-'+(c?"e":"w")+'">'+n+"</span></a>":f?"":'<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+n+'"><span class="ui-icon ui-icon-circle-triangle-'+(c?"e":"w")+'">'+n+"</span></a>";var r=this._get(a,"nextText");r=!h?r:this.formatDate(r,this._daylightSavingAdjust(new Date(m,
+g+k,1)),this._getFormatConfig(a));f=this._canAdjustMonth(a,+1,m,g)?'<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery_'+y+".datepicker._adjustDate('#"+a.id+"', +"+k+", 'M');\" title=\""+r+'"><span class="ui-icon ui-icon-circle-triangle-'+(c?"w":"e")+'">'+r+"</span></a>":f?"":'<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+r+'"><span class="ui-icon ui-icon-circle-triangle-'+(c?"w":"e")+'">'+r+"</span></a>";k=this._get(a,"currentText");r=this._get(a,"gotoCurrent")&&
+a.currentDay?u:b;k=!h?k:this.formatDate(k,r,this._getFormatConfig(a));h=!a.inline?'<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery_'+y+'.datepicker._hideDatepicker();">'+this._get(a,"closeText")+"</button>":"";e=e?'<div class="ui-datepicker-buttonpane ui-widget-content">'+(c?h:"")+(this._isInRange(a,r)?'<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery_'+
+y+".datepicker._gotoToday('#"+a.id+"');\">"+k+"</button>":"")+(c?"":h)+"</div>":"";h=parseInt(this._get(a,"firstDay"),10);h=isNaN(h)?0:h;k=this._get(a,"showWeek");r=this._get(a,"dayNames");this._get(a,"dayNamesShort");var s=this._get(a,"dayNamesMin"),z=this._get(a,"monthNames"),v=this._get(a,"monthNamesShort"),p=this._get(a,"beforeShowDay"),w=this._get(a,"showOtherMonths"),H=this._get(a,"selectOtherMonths");this._get(a,"calculateWeek");for(var M=this._getDefaultDate(a),I="",C=0;C<i[0];C++){for(var N=
+"",D=0;D<i[1];D++){var J=this._daylightSavingAdjust(new Date(m,g,a.selectedDay)),t=" ui-corner-all",x="";if(l){x+='<div class="ui-datepicker-group';if(i[1]>1)switch(D){case 0:x+=" ui-datepicker-group-first";t=" ui-corner-"+(c?"right":"left");break;case i[1]-1:x+=" ui-datepicker-group-last";t=" ui-corner-"+(c?"left":"right");break;default:x+=" ui-datepicker-group-middle";t="";break}x+='">'}x+='<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix'+t+'">'+(/all|left/.test(t)&&C==0?c?
+f:n:"")+(/all|right/.test(t)&&C==0?c?n:f:"")+this._generateMonthYearHeader(a,g,m,j,o,C>0||D>0,z,v)+'</div><table class="ui-datepicker-calendar"><thead><tr>';var A=k?'<th class="ui-datepicker-week-col">'+this._get(a,"weekHeader")+"</th>":"";for(t=0;t<7;t++){var q=(t+h)%7;A+="<th"+((t+h+6)%7>=5?' class="ui-datepicker-week-end"':"")+'><span title="'+r[q]+'">'+s[q]+"</span></th>"}x+=A+"</tr></thead><tbody>";A=this._getDaysInMonth(m,g);if(m==a.selectedYear&&g==a.selectedMonth)a.selectedDay=Math.min(a.selectedDay,
+A);t=(this._getFirstDayOfMonth(m,g)-h+7)%7;A=l?6:Math.ceil((t+A)/7);q=this._daylightSavingAdjust(new Date(m,g,1-t));for(var O=0;O<A;O++){x+="<tr>";var P=!k?"":'<td class="ui-datepicker-week-col">'+this._get(a,"calculateWeek")(q)+"</td>";for(t=0;t<7;t++){var F=p?p.apply(a.input?a.input[0]:null,[q]):[true,""],B=q.getMonth()!=g,K=B&&!H||!F[0]||j&&q<j||o&&q>o;P+='<td class="'+((t+h+6)%7>=5?" ui-datepicker-week-end":"")+(B?" ui-datepicker-other-month":"")+(q.getTime()==J.getTime()&&g==a.selectedMonth&&
+a._keyEvent||M.getTime()==q.getTime()&&M.getTime()==J.getTime()?" "+this._dayOverClass:"")+(K?" "+this._unselectableClass+" ui-state-disabled":"")+(B&&!w?"":" "+F[1]+(q.getTime()==u.getTime()?" "+this._currentClass:"")+(q.getTime()==b.getTime()?" ui-datepicker-today":""))+'"'+((!B||w)&&F[2]?' title="'+F[2]+'"':"")+(K?"":' onclick="DP_jQuery_'+y+".datepicker._selectDay('#"+a.id+"',"+q.getMonth()+","+q.getFullYear()+', this);return false;"')+">"+(B&&!w?"&#xa0;":K?'<span class="ui-state-default">'+q.getDate()+
+"</span>":'<a class="ui-state-default'+(q.getTime()==b.getTime()?" ui-state-highlight":"")+(q.getTime()==J.getTime()?" ui-state-active":"")+(B?" ui-priority-secondary":"")+'" href="#">'+q.getDate()+"</a>")+"</td>";q.setDate(q.getDate()+1);q=this._daylightSavingAdjust(q)}x+=P+"</tr>"}g++;if(g>11){g=0;m++}x+="</tbody></table>"+(l?"</div>"+(i[0]>0&&D==i[1]-1?'<div class="ui-datepicker-row-break"></div>':""):"");N+=x}I+=N}I+=e+(d.browser.msie&&parseInt(d.browser.version,10)<7&&!a.inline?'<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>':
+"");a._keyEvent=false;return I},_generateMonthYearHeader:function(a,b,c,e,f,h,i,g){var k=this._get(a,"changeMonth"),l=this._get(a,"changeYear"),u=this._get(a,"showMonthAfterYear"),j='<div class="ui-datepicker-title">',o="";if(h||!k)o+='<span class="ui-datepicker-month">'+i[b]+"</span>";else{i=e&&e.getFullYear()==c;var m=f&&f.getFullYear()==c;o+='<select class="ui-datepicker-month" onchange="DP_jQuery_'+y+".datepicker._selectMonthYear('#"+a.id+"', this, 'M');\" onclick=\"DP_jQuery_"+y+".datepicker._clickMonthYear('#"+
+a.id+"');\">";for(var n=0;n<12;n++)if((!i||n>=e.getMonth())&&(!m||n<=f.getMonth()))o+='<option value="'+n+'"'+(n==b?' selected="selected"':"")+">"+g[n]+"</option>";o+="</select>"}u||(j+=o+(h||!(k&&l)?"&#xa0;":""));if(h||!l)j+='<span class="ui-datepicker-year">'+c+"</span>";else{g=this._get(a,"yearRange").split(":");var r=(new Date).getFullYear();i=function(s){s=s.match(/c[+-].*/)?c+parseInt(s.substring(1),10):s.match(/[+-].*/)?r+parseInt(s,10):parseInt(s,10);return isNaN(s)?r:s};b=i(g[0]);g=Math.max(b,
+i(g[1]||""));b=e?Math.max(b,e.getFullYear()):b;g=f?Math.min(g,f.getFullYear()):g;for(j+='<select class="ui-datepicker-year" onchange="DP_jQuery_'+y+".datepicker._selectMonthYear('#"+a.id+"', this, 'Y');\" onclick=\"DP_jQuery_"+y+".datepicker._clickMonthYear('#"+a.id+"');\">";b<=g;b++)j+='<option value="'+b+'"'+(b==c?' selected="selected"':"")+">"+b+"</option>";j+="</select>"}j+=this._get(a,"yearSuffix");if(u)j+=(h||!(k&&l)?"&#xa0;":"")+o;j+="</div>";return j},_adjustInstDate:function(a,b,c){var e=
+a.drawYear+(c=="Y"?b:0),f=a.drawMonth+(c=="M"?b:0);b=Math.min(a.selectedDay,this._getDaysInMonth(e,f))+(c=="D"?b:0);e=this._restrictMinMax(a,this._daylightSavingAdjust(new Date(e,f,b)));a.selectedDay=e.getDate();a.drawMonth=a.selectedMonth=e.getMonth();a.drawYear=a.selectedYear=e.getFullYear();if(c=="M"||c=="Y")this._notifyChange(a)},_restrictMinMax:function(a,b){var c=this._getMinMaxDate(a,"min");a=this._getMinMaxDate(a,"max");b=c&&b<c?c:b;return b=a&&b>a?a:b},_notifyChange:function(a){var b=this._get(a,
+"onChangeMonthYear");if(b)b.apply(a.input?a.input[0]:null,[a.selectedYear,a.selectedMonth+1,a])},_getNumberOfMonths:function(a){a=this._get(a,"numberOfMonths");return a==null?[1,1]:typeof a=="number"?[1,a]:a},_getMinMaxDate:function(a,b){return this._determineDate(a,this._get(a,b+"Date"),null)},_getDaysInMonth:function(a,b){return 32-(new Date(a,b,32)).getDate()},_getFirstDayOfMonth:function(a,b){return(new Date(a,b,1)).getDay()},_canAdjustMonth:function(a,b,c,e){var f=this._getNumberOfMonths(a);
+c=this._daylightSavingAdjust(new Date(c,e+(b<0?b:f[0]*f[1]),1));b<0&&c.setDate(this._getDaysInMonth(c.getFullYear(),c.getMonth()));return this._isInRange(a,c)},_isInRange:function(a,b){var c=this._getMinMaxDate(a,"min");a=this._getMinMaxDate(a,"max");return(!c||b.getTime()>=c.getTime())&&(!a||b.getTime()<=a.getTime())},_getFormatConfig:function(a){var b=this._get(a,"shortYearCutoff");b=typeof b!="string"?b:(new Date).getFullYear()%100+parseInt(b,10);return{shortYearCutoff:b,dayNamesShort:this._get(a,
+"dayNamesShort"),dayNames:this._get(a,"dayNames"),monthNamesShort:this._get(a,"monthNamesShort"),monthNames:this._get(a,"monthNames")}},_formatDate:function(a,b,c,e){if(!b){a.currentDay=a.selectedDay;a.currentMonth=a.selectedMonth;a.currentYear=a.selectedYear}b=b?typeof b=="object"?b:this._daylightSavingAdjust(new Date(e,c,b)):this._daylightSavingAdjust(new Date(a.currentYear,a.currentMonth,a.currentDay));return this.formatDate(this._get(a,"dateFormat"),b,this._getFormatConfig(a))}});d.fn.datepicker=
+function(a){if(!d.datepicker.initialized){d(document).mousedown(d.datepicker._checkExternalClick).find("body").append(d.datepicker.dpDiv);d.datepicker.initialized=true}var b=Array.prototype.slice.call(arguments,1);if(typeof a=="string"&&(a=="isDisabled"||a=="getDate"||a=="widget"))return d.datepicker["_"+a+"Datepicker"].apply(d.datepicker,[this[0]].concat(b));if(a=="option"&&arguments.length==2&&typeof arguments[1]=="string")return d.datepicker["_"+a+"Datepicker"].apply(d.datepicker,[this[0]].concat(b));
+return this.each(function(){typeof a=="string"?d.datepicker["_"+a+"Datepicker"].apply(d.datepicker,[this].concat(b)):d.datepicker._attachDatepicker(this,a)})};d.datepicker=new L;d.datepicker.initialized=false;d.datepicker.uuid=(new Date).getTime();d.datepicker.version="1.8.4";window["DP_jQuery_"+y]=d})(jQuery);
+;/*
+ * jQuery UI Progressbar 1.8.4
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Progressbar
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.widget.js
+ */
+(function(b,c){b.widget("ui.progressbar",{options:{value:0},min:0,max:100,_create:function(){this.element.addClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").attr({role:"progressbar","aria-valuemin":this.min,"aria-valuemax":this.max,"aria-valuenow":this._value()});this.valueDiv=b("<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>").appendTo(this.element);this._refreshValue()},destroy:function(){this.element.removeClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow");
+this.valueDiv.remove();b.Widget.prototype.destroy.apply(this,arguments)},value:function(a){if(a===c)return this._value();this._setOption("value",a);return this},_setOption:function(a,d){if(a==="value"){this.options.value=d;this._refreshValue();this._trigger("change")}b.Widget.prototype._setOption.apply(this,arguments)},_value:function(){var a=this.options.value;if(typeof a!=="number")a=0;return Math.min(this.max,Math.max(this.min,a))},_refreshValue:function(){var a=this.value();this.valueDiv.toggleClass("ui-corner-right",
+a===this.max).width(a+"%");this.element.attr("aria-valuenow",a)}});b.extend(b.ui.progressbar,{version:"1.8.4"})})(jQuery);
+;/*
+ * jQuery UI Effects 1.8.4
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/
+ */
+jQuery.effects||function(f,j){function l(c){var a;if(c&&c.constructor==Array&&c.length==3)return c;if(a=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(c))return[parseInt(a[1],10),parseInt(a[2],10),parseInt(a[3],10)];if(a=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(c))return[parseFloat(a[1])*2.55,parseFloat(a[2])*2.55,parseFloat(a[3])*2.55];if(a=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(c))return[parseInt(a[1],
+16),parseInt(a[2],16),parseInt(a[3],16)];if(a=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(c))return[parseInt(a[1]+a[1],16),parseInt(a[2]+a[2],16),parseInt(a[3]+a[3],16)];if(/rgba\(0, 0, 0, 0\)/.exec(c))return m.transparent;return m[f.trim(c).toLowerCase()]}function r(c,a){var b;do{b=f.curCSS(c,a);if(b!=""&&b!="transparent"||f.nodeName(c,"body"))break;a="backgroundColor"}while(c=c.parentNode);return l(b)}function n(){var c=document.defaultView?document.defaultView.getComputedStyle(this,null):this.currentStyle,
+a={},b,d;if(c&&c.length&&c[0]&&c[c[0]])for(var e=c.length;e--;){b=c[e];if(typeof c[b]=="string"){d=b.replace(/\-(\w)/g,function(g,h){return h.toUpperCase()});a[d]=c[b]}}else for(b in c)if(typeof c[b]==="string")a[b]=c[b];return a}function o(c){var a,b;for(a in c){b=c[a];if(b==null||f.isFunction(b)||a in s||/scrollbar/.test(a)||!/color/i.test(a)&&isNaN(parseFloat(b)))delete c[a]}return c}function t(c,a){var b={_:0},d;for(d in a)if(c[d]!=a[d])b[d]=a[d];return b}function k(c,a,b,d){if(typeof c=="object"){d=
+a;b=null;a=c;c=a.effect}if(f.isFunction(a)){d=a;b=null;a={}}if(typeof a=="number"||f.fx.speeds[a]){d=b;b=a;a={}}if(f.isFunction(b)){d=b;b=null}a=a||{};b=b||a.duration;b=f.fx.off?0:typeof b=="number"?b:f.fx.speeds[b]||f.fx.speeds._default;d=d||a.complete;return[c,a,b,d]}f.effects={};f.each(["backgroundColor","borderBottomColor","borderLeftColor","borderRightColor","borderTopColor","color","outlineColor"],function(c,a){f.fx.step[a]=function(b){if(!b.colorInit){b.start=r(b.elem,a);b.end=l(b.end);b.colorInit=
+true}b.elem.style[a]="rgb("+Math.max(Math.min(parseInt(b.pos*(b.end[0]-b.start[0])+b.start[0],10),255),0)+","+Math.max(Math.min(parseInt(b.pos*(b.end[1]-b.start[1])+b.start[1],10),255),0)+","+Math.max(Math.min(parseInt(b.pos*(b.end[2]-b.start[2])+b.start[2],10),255),0)+")"}});var m={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,
+183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,
+165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0],transparent:[255,255,255]},p=["add","remove","toggle"],s={border:1,borderBottom:1,borderColor:1,borderLeft:1,borderRight:1,borderTop:1,borderWidth:1,margin:1,padding:1};f.effects.animateClass=function(c,a,b,d){if(f.isFunction(b)){d=b;b=null}return this.each(function(){var e=f(this),g=e.attr("style")||" ",h=o(n.call(this)),q,u=e.attr("className");f.each(p,function(v,
+i){c[i]&&e[i+"Class"](c[i])});q=o(n.call(this));e.attr("className",u);e.animate(t(h,q),a,b,function(){f.each(p,function(v,i){c[i]&&e[i+"Class"](c[i])});if(typeof e.attr("style")=="object"){e.attr("style").cssText="";e.attr("style").cssText=g}else e.attr("style",g);d&&d.apply(this,arguments)})})};f.fn.extend({_addClass:f.fn.addClass,addClass:function(c,a,b,d){return a?f.effects.animateClass.apply(this,[{add:c},a,b,d]):this._addClass(c)},_removeClass:f.fn.removeClass,removeClass:function(c,a,b,d){return a?
+f.effects.animateClass.apply(this,[{remove:c},a,b,d]):this._removeClass(c)},_toggleClass:f.fn.toggleClass,toggleClass:function(c,a,b,d,e){return typeof a=="boolean"||a===j?b?f.effects.animateClass.apply(this,[a?{add:c}:{remove:c},b,d,e]):this._toggleClass(c,a):f.effects.animateClass.apply(this,[{toggle:c},a,b,d])},switchClass:function(c,a,b,d,e){return f.effects.animateClass.apply(this,[{add:a,remove:c},b,d,e])}});f.extend(f.effects,{version:"1.8.4",save:function(c,a){for(var b=0;b<a.length;b++)a[b]!==
+null&&c.data("ec.storage."+a[b],c[0].style[a[b]])},restore:function(c,a){for(var b=0;b<a.length;b++)a[b]!==null&&c.css(a[b],c.data("ec.storage."+a[b]))},setMode:function(c,a){if(a=="toggle")a=c.is(":hidden")?"show":"hide";return a},getBaseline:function(c,a){var b;switch(c[0]){case "top":b=0;break;case "middle":b=0.5;break;case "bottom":b=1;break;default:b=c[0]/a.height}switch(c[1]){case "left":c=0;break;case "center":c=0.5;break;case "right":c=1;break;default:c=c[1]/a.width}return{x:c,y:b}},createWrapper:function(c){if(c.parent().is(".ui-effects-wrapper"))return c.parent();
+var a={width:c.outerWidth(true),height:c.outerHeight(true),"float":c.css("float")},b=f("<div></div>").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0});c.wrap(b);b=c.parent();if(c.css("position")=="static"){b.css({position:"relative"});c.css({position:"relative"})}else{f.extend(a,{position:c.css("position"),zIndex:c.css("z-index")});f.each(["top","left","bottom","right"],function(d,e){a[e]=c.css(e);if(isNaN(parseInt(a[e],10)))a[e]="auto"});
+c.css({position:"relative",top:0,left:0})}return b.css(a).show()},removeWrapper:function(c){if(c.parent().is(".ui-effects-wrapper"))return c.parent().replaceWith(c);return c},setTransition:function(c,a,b,d){d=d||{};f.each(a,function(e,g){unit=c.cssUnit(g);if(unit[0]>0)d[g]=unit[0]*b+unit[1]});return d}});f.fn.extend({effect:function(c){var a=k.apply(this,arguments);a={options:a[1],duration:a[2],callback:a[3]};var b=f.effects[c];return b&&!f.fx.off?b.call(this,a):this},_show:f.fn.show,show:function(c){if(!c||
+typeof c=="number"||f.fx.speeds[c])return this._show.apply(this,arguments);else{var a=k.apply(this,arguments);a[1].mode="show";return this.effect.apply(this,a)}},_hide:f.fn.hide,hide:function(c){if(!c||typeof c=="number"||f.fx.speeds[c])return this._hide.apply(this,arguments);else{var a=k.apply(this,arguments);a[1].mode="hide";return this.effect.apply(this,a)}},__toggle:f.fn.toggle,toggle:function(c){if(!c||typeof c=="number"||f.fx.speeds[c]||typeof c=="boolean"||f.isFunction(c))return this.__toggle.apply(this,
+arguments);else{var a=k.apply(this,arguments);a[1].mode="toggle";return this.effect.apply(this,a)}},cssUnit:function(c){var a=this.css(c),b=[];f.each(["em","px","%","pt"],function(d,e){if(a.indexOf(e)>0)b=[parseFloat(a),e]});return b}});f.easing.jswing=f.easing.swing;f.extend(f.easing,{def:"easeOutQuad",swing:function(c,a,b,d,e){return f.easing[f.easing.def](c,a,b,d,e)},easeInQuad:function(c,a,b,d,e){return d*(a/=e)*a+b},easeOutQuad:function(c,a,b,d,e){return-d*(a/=e)*(a-2)+b},easeInOutQuad:function(c,
+a,b,d,e){if((a/=e/2)<1)return d/2*a*a+b;return-d/2*(--a*(a-2)-1)+b},easeInCubic:function(c,a,b,d,e){return d*(a/=e)*a*a+b},easeOutCubic:function(c,a,b,d,e){return d*((a=a/e-1)*a*a+1)+b},easeInOutCubic:function(c,a,b,d,e){if((a/=e/2)<1)return d/2*a*a*a+b;return d/2*((a-=2)*a*a+2)+b},easeInQuart:function(c,a,b,d,e){return d*(a/=e)*a*a*a+b},easeOutQuart:function(c,a,b,d,e){return-d*((a=a/e-1)*a*a*a-1)+b},easeInOutQuart:function(c,a,b,d,e){if((a/=e/2)<1)return d/2*a*a*a*a+b;return-d/2*((a-=2)*a*a*a-2)+
+b},easeInQuint:function(c,a,b,d,e){return d*(a/=e)*a*a*a*a+b},easeOutQuint:function(c,a,b,d,e){return d*((a=a/e-1)*a*a*a*a+1)+b},easeInOutQuint:function(c,a,b,d,e){if((a/=e/2)<1)return d/2*a*a*a*a*a+b;return d/2*((a-=2)*a*a*a*a+2)+b},easeInSine:function(c,a,b,d,e){return-d*Math.cos(a/e*(Math.PI/2))+d+b},easeOutSine:function(c,a,b,d,e){return d*Math.sin(a/e*(Math.PI/2))+b},easeInOutSine:function(c,a,b,d,e){return-d/2*(Math.cos(Math.PI*a/e)-1)+b},easeInExpo:function(c,a,b,d,e){return a==0?b:d*Math.pow(2,
+10*(a/e-1))+b},easeOutExpo:function(c,a,b,d,e){return a==e?b+d:d*(-Math.pow(2,-10*a/e)+1)+b},easeInOutExpo:function(c,a,b,d,e){if(a==0)return b;if(a==e)return b+d;if((a/=e/2)<1)return d/2*Math.pow(2,10*(a-1))+b;return d/2*(-Math.pow(2,-10*--a)+2)+b},easeInCirc:function(c,a,b,d,e){return-d*(Math.sqrt(1-(a/=e)*a)-1)+b},easeOutCirc:function(c,a,b,d,e){return d*Math.sqrt(1-(a=a/e-1)*a)+b},easeInOutCirc:function(c,a,b,d,e){if((a/=e/2)<1)return-d/2*(Math.sqrt(1-a*a)-1)+b;return d/2*(Math.sqrt(1-(a-=2)*
+a)+1)+b},easeInElastic:function(c,a,b,d,e){c=1.70158;var g=0,h=d;if(a==0)return b;if((a/=e)==1)return b+d;g||(g=e*0.3);if(h<Math.abs(d)){h=d;c=g/4}else c=g/(2*Math.PI)*Math.asin(d/h);return-(h*Math.pow(2,10*(a-=1))*Math.sin((a*e-c)*2*Math.PI/g))+b},easeOutElastic:function(c,a,b,d,e){c=1.70158;var g=0,h=d;if(a==0)return b;if((a/=e)==1)return b+d;g||(g=e*0.3);if(h<Math.abs(d)){h=d;c=g/4}else c=g/(2*Math.PI)*Math.asin(d/h);return h*Math.pow(2,-10*a)*Math.sin((a*e-c)*2*Math.PI/g)+d+b},easeInOutElastic:function(c,
+a,b,d,e){c=1.70158;var g=0,h=d;if(a==0)return b;if((a/=e/2)==2)return b+d;g||(g=e*0.3*1.5);if(h<Math.abs(d)){h=d;c=g/4}else c=g/(2*Math.PI)*Math.asin(d/h);if(a<1)return-0.5*h*Math.pow(2,10*(a-=1))*Math.sin((a*e-c)*2*Math.PI/g)+b;return h*Math.pow(2,-10*(a-=1))*Math.sin((a*e-c)*2*Math.PI/g)*0.5+d+b},easeInBack:function(c,a,b,d,e,g){if(g==j)g=1.70158;return d*(a/=e)*a*((g+1)*a-g)+b},easeOutBack:function(c,a,b,d,e,g){if(g==j)g=1.70158;return d*((a=a/e-1)*a*((g+1)*a+g)+1)+b},easeInOutBack:function(c,
+a,b,d,e,g){if(g==j)g=1.70158;if((a/=e/2)<1)return d/2*a*a*(((g*=1.525)+1)*a-g)+b;return d/2*((a-=2)*a*(((g*=1.525)+1)*a+g)+2)+b},easeInBounce:function(c,a,b,d,e){return d-f.easing.easeOutBounce(c,e-a,0,d,e)+b},easeOutBounce:function(c,a,b,d,e){return(a/=e)<1/2.75?d*7.5625*a*a+b:a<2/2.75?d*(7.5625*(a-=1.5/2.75)*a+0.75)+b:a<2.5/2.75?d*(7.5625*(a-=2.25/2.75)*a+0.9375)+b:d*(7.5625*(a-=2.625/2.75)*a+0.984375)+b},easeInOutBounce:function(c,a,b,d,e){if(a<e/2)return f.easing.easeInBounce(c,a*2,0,d,e)*0.5+
+b;return f.easing.easeOutBounce(c,a*2-e,0,d,e)*0.5+d*0.5+b}})}(jQuery);
+;/*
+ * jQuery UI Effects Blind 1.8.4
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Blind
+ *
+ * Depends:
+ * jquery.effects.core.js
+ */
+(function(b){b.effects.blind=function(c){return this.queue(function(){var a=b(this),g=["position","top","left"],f=b.effects.setMode(a,c.options.mode||"hide"),d=c.options.direction||"vertical";b.effects.save(a,g);a.show();var e=b.effects.createWrapper(a).css({overflow:"hidden"}),h=d=="vertical"?"height":"width";d=d=="vertical"?e.height():e.width();f=="show"&&e.css(h,0);var i={};i[h]=f=="show"?d:0;e.animate(i,c.duration,c.options.easing,function(){f=="hide"&&a.hide();b.effects.restore(a,g);b.effects.removeWrapper(a);
+c.callback&&c.callback.apply(a[0],arguments);a.dequeue()})})}})(jQuery);
+;/*
+ * jQuery UI Effects Bounce 1.8.4
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Bounce
+ *
+ * Depends:
+ * jquery.effects.core.js
+ */
+(function(e){e.effects.bounce=function(b){return this.queue(function(){var a=e(this),l=["position","top","left"],h=e.effects.setMode(a,b.options.mode||"effect"),d=b.options.direction||"up",c=b.options.distance||20,m=b.options.times||5,i=b.duration||250;/show|hide/.test(h)&&l.push("opacity");e.effects.save(a,l);a.show();e.effects.createWrapper(a);var f=d=="up"||d=="down"?"top":"left";d=d=="up"||d=="left"?"pos":"neg";c=b.options.distance||(f=="top"?a.outerHeight({margin:true})/3:a.outerWidth({margin:true})/
+3);if(h=="show")a.css("opacity",0).css(f,d=="pos"?-c:c);if(h=="hide")c/=m*2;h!="hide"&&m--;if(h=="show"){var g={opacity:1};g[f]=(d=="pos"?"+=":"-=")+c;a.animate(g,i/2,b.options.easing);c/=2;m--}for(g=0;g<m;g++){var j={},k={};j[f]=(d=="pos"?"-=":"+=")+c;k[f]=(d=="pos"?"+=":"-=")+c;a.animate(j,i/2,b.options.easing).animate(k,i/2,b.options.easing);c=h=="hide"?c*2:c/2}if(h=="hide"){g={opacity:0};g[f]=(d=="pos"?"-=":"+=")+c;a.animate(g,i/2,b.options.easing,function(){a.hide();e.effects.restore(a,l);e.effects.removeWrapper(a);
+b.callback&&b.callback.apply(this,arguments)})}else{j={};k={};j[f]=(d=="pos"?"-=":"+=")+c;k[f]=(d=="pos"?"+=":"-=")+c;a.animate(j,i/2,b.options.easing).animate(k,i/2,b.options.easing,function(){e.effects.restore(a,l);e.effects.removeWrapper(a);b.callback&&b.callback.apply(this,arguments)})}a.queue("fx",function(){a.dequeue()});a.dequeue()})}})(jQuery);
+;/*
+ * jQuery UI Effects Clip 1.8.4
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Clip
+ *
+ * Depends:
+ * jquery.effects.core.js
+ */
+(function(b){b.effects.clip=function(e){return this.queue(function(){var a=b(this),i=["position","top","left","height","width"],f=b.effects.setMode(a,e.options.mode||"hide"),c=e.options.direction||"vertical";b.effects.save(a,i);a.show();var d=b.effects.createWrapper(a).css({overflow:"hidden"});d=a[0].tagName=="IMG"?d:a;var g={size:c=="vertical"?"height":"width",position:c=="vertical"?"top":"left"};c=c=="vertical"?d.height():d.width();if(f=="show"){d.css(g.size,0);d.css(g.position,c/2)}var h={};h[g.size]=
+f=="show"?c:0;h[g.position]=f=="show"?0:c/2;d.animate(h,{queue:false,duration:e.duration,easing:e.options.easing,complete:function(){f=="hide"&&a.hide();b.effects.restore(a,i);b.effects.removeWrapper(a);e.callback&&e.callback.apply(a[0],arguments);a.dequeue()}})})}})(jQuery);
+;/*
+ * jQuery UI Effects Drop 1.8.4
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Drop
+ *
+ * Depends:
+ * jquery.effects.core.js
+ */
+(function(c){c.effects.drop=function(d){return this.queue(function(){var a=c(this),h=["position","top","left","opacity"],e=c.effects.setMode(a,d.options.mode||"hide"),b=d.options.direction||"left";c.effects.save(a,h);a.show();c.effects.createWrapper(a);var f=b=="up"||b=="down"?"top":"left";b=b=="up"||b=="left"?"pos":"neg";var g=d.options.distance||(f=="top"?a.outerHeight({margin:true})/2:a.outerWidth({margin:true})/2);if(e=="show")a.css("opacity",0).css(f,b=="pos"?-g:g);var i={opacity:e=="show"?1:
+0};i[f]=(e=="show"?b=="pos"?"+=":"-=":b=="pos"?"-=":"+=")+g;a.animate(i,{queue:false,duration:d.duration,easing:d.options.easing,complete:function(){e=="hide"&&a.hide();c.effects.restore(a,h);c.effects.removeWrapper(a);d.callback&&d.callback.apply(this,arguments);a.dequeue()}})})}})(jQuery);
+;/*
+ * jQuery UI Effects Explode 1.8.4
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Explode
+ *
+ * Depends:
+ * jquery.effects.core.js
+ */
+(function(j){j.effects.explode=function(a){return this.queue(function(){var c=a.options.pieces?Math.round(Math.sqrt(a.options.pieces)):3,d=a.options.pieces?Math.round(Math.sqrt(a.options.pieces)):3;a.options.mode=a.options.mode=="toggle"?j(this).is(":visible")?"hide":"show":a.options.mode;var b=j(this).show().css("visibility","hidden"),g=b.offset();g.top-=parseInt(b.css("marginTop"),10)||0;g.left-=parseInt(b.css("marginLeft"),10)||0;for(var h=b.outerWidth(true),i=b.outerHeight(true),e=0;e<c;e++)for(var f=
+0;f<d;f++)b.clone().appendTo("body").wrap("<div></div>").css({position:"absolute",visibility:"visible",left:-f*(h/d),top:-e*(i/c)}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:h/d,height:i/c,left:g.left+f*(h/d)+(a.options.mode=="show"?(f-Math.floor(d/2))*(h/d):0),top:g.top+e*(i/c)+(a.options.mode=="show"?(e-Math.floor(c/2))*(i/c):0),opacity:a.options.mode=="show"?0:1}).animate({left:g.left+f*(h/d)+(a.options.mode=="show"?0:(f-Math.floor(d/2))*(h/d)),top:g.top+
+e*(i/c)+(a.options.mode=="show"?0:(e-Math.floor(c/2))*(i/c)),opacity:a.options.mode=="show"?1:0},a.duration||500);setTimeout(function(){a.options.mode=="show"?b.css({visibility:"visible"}):b.css({visibility:"visible"}).hide();a.callback&&a.callback.apply(b[0]);b.dequeue();j("div.ui-effects-explode").remove()},a.duration||500)})}})(jQuery);
+;/*
+ * jQuery UI Effects Fold 1.8.4
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Fold
+ *
+ * Depends:
+ * jquery.effects.core.js
+ */
+(function(c){c.effects.fold=function(a){return this.queue(function(){var b=c(this),j=["position","top","left"],d=c.effects.setMode(b,a.options.mode||"hide"),g=a.options.size||15,h=!!a.options.horizFirst,k=a.duration?a.duration/2:c.fx.speeds._default/2;c.effects.save(b,j);b.show();var e=c.effects.createWrapper(b).css({overflow:"hidden"}),f=d=="show"!=h,l=f?["width","height"]:["height","width"];f=f?[e.width(),e.height()]:[e.height(),e.width()];var i=/([0-9]+)%/.exec(g);if(i)g=parseInt(i[1],10)/100*
+f[d=="hide"?0:1];if(d=="show")e.css(h?{height:0,width:g}:{height:g,width:0});h={};i={};h[l[0]]=d=="show"?f[0]:g;i[l[1]]=d=="show"?f[1]:0;e.animate(h,k,a.options.easing).animate(i,k,a.options.easing,function(){d=="hide"&&b.hide();c.effects.restore(b,j);c.effects.removeWrapper(b);a.callback&&a.callback.apply(b[0],arguments);b.dequeue()})})}})(jQuery);
+;/*
+ * jQuery UI Effects Highlight 1.8.4
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Highlight
+ *
+ * Depends:
+ * jquery.effects.core.js
+ */
+(function(b){b.effects.highlight=function(c){return this.queue(function(){var a=b(this),e=["backgroundImage","backgroundColor","opacity"],d=b.effects.setMode(a,c.options.mode||"show"),f={backgroundColor:a.css("backgroundColor")};if(d=="hide")f.opacity=0;b.effects.save(a,e);a.show().css({backgroundImage:"none",backgroundColor:c.options.color||"#ffff99"}).animate(f,{queue:false,duration:c.duration,easing:c.options.easing,complete:function(){d=="hide"&&a.hide();b.effects.restore(a,e);d=="show"&&!b.support.opacity&&
+this.style.removeAttribute("filter");c.callback&&c.callback.apply(this,arguments);a.dequeue()}})})}})(jQuery);
+;/*
+ * jQuery UI Effects Pulsate 1.8.4
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Pulsate
+ *
+ * Depends:
+ * jquery.effects.core.js
+ */
+(function(d){d.effects.pulsate=function(a){return this.queue(function(){var b=d(this),c=d.effects.setMode(b,a.options.mode||"show");times=(a.options.times||5)*2-1;duration=a.duration?a.duration/2:d.fx.speeds._default/2;isVisible=b.is(":visible");animateTo=0;if(!isVisible){b.css("opacity",0).show();animateTo=1}if(c=="hide"&&isVisible||c=="show"&&!isVisible)times--;for(c=0;c<times;c++){b.animate({opacity:animateTo},duration,a.options.easing);animateTo=(animateTo+1)%2}b.animate({opacity:animateTo},duration,
+a.options.easing,function(){animateTo==0&&b.hide();a.callback&&a.callback.apply(this,arguments)});b.queue("fx",function(){b.dequeue()}).dequeue()})}})(jQuery);
+;/*
+ * jQuery UI Effects Scale 1.8.4
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Scale
+ *
+ * Depends:
+ * jquery.effects.core.js
+ */
+(function(c){c.effects.puff=function(b){return this.queue(function(){var a=c(this),e=c.effects.setMode(a,b.options.mode||"hide"),g=parseInt(b.options.percent,10)||150,h=g/100,i={height:a.height(),width:a.width()};c.extend(b.options,{fade:true,mode:e,percent:e=="hide"?g:100,from:e=="hide"?i:{height:i.height*h,width:i.width*h}});a.effect("scale",b.options,b.duration,b.callback);a.dequeue()})};c.effects.scale=function(b){return this.queue(function(){var a=c(this),e=c.extend(true,{},b.options),g=c.effects.setMode(a,
+b.options.mode||"effect"),h=parseInt(b.options.percent,10)||(parseInt(b.options.percent,10)==0?0:g=="hide"?0:100),i=b.options.direction||"both",f=b.options.origin;if(g!="effect"){e.origin=f||["middle","center"];e.restore=true}f={height:a.height(),width:a.width()};a.from=b.options.from||(g=="show"?{height:0,width:0}:f);h={y:i!="horizontal"?h/100:1,x:i!="vertical"?h/100:1};a.to={height:f.height*h.y,width:f.width*h.x};if(b.options.fade){if(g=="show"){a.from.opacity=0;a.to.opacity=1}if(g=="hide"){a.from.opacity=
+1;a.to.opacity=0}}e.from=a.from;e.to=a.to;e.mode=g;a.effect("size",e,b.duration,b.callback);a.dequeue()})};c.effects.size=function(b){return this.queue(function(){var a=c(this),e=["position","top","left","width","height","overflow","opacity"],g=["position","top","left","overflow","opacity"],h=["width","height","overflow"],i=["fontSize"],f=["borderTopWidth","borderBottomWidth","paddingTop","paddingBottom"],k=["borderLeftWidth","borderRightWidth","paddingLeft","paddingRight"],p=c.effects.setMode(a,
+b.options.mode||"effect"),n=b.options.restore||false,m=b.options.scale||"both",l=b.options.origin,j={height:a.height(),width:a.width()};a.from=b.options.from||j;a.to=b.options.to||j;if(l){l=c.effects.getBaseline(l,j);a.from.top=(j.height-a.from.height)*l.y;a.from.left=(j.width-a.from.width)*l.x;a.to.top=(j.height-a.to.height)*l.y;a.to.left=(j.width-a.to.width)*l.x}var d={from:{y:a.from.height/j.height,x:a.from.width/j.width},to:{y:a.to.height/j.height,x:a.to.width/j.width}};if(m=="box"||m=="both"){if(d.from.y!=
+d.to.y){e=e.concat(f);a.from=c.effects.setTransition(a,f,d.from.y,a.from);a.to=c.effects.setTransition(a,f,d.to.y,a.to)}if(d.from.x!=d.to.x){e=e.concat(k);a.from=c.effects.setTransition(a,k,d.from.x,a.from);a.to=c.effects.setTransition(a,k,d.to.x,a.to)}}if(m=="content"||m=="both")if(d.from.y!=d.to.y){e=e.concat(i);a.from=c.effects.setTransition(a,i,d.from.y,a.from);a.to=c.effects.setTransition(a,i,d.to.y,a.to)}c.effects.save(a,n?e:g);a.show();c.effects.createWrapper(a);a.css("overflow","hidden").css(a.from);
+if(m=="content"||m=="both"){f=f.concat(["marginTop","marginBottom"]).concat(i);k=k.concat(["marginLeft","marginRight"]);h=e.concat(f).concat(k);a.find("*[width]").each(function(){child=c(this);n&&c.effects.save(child,h);var o={height:child.height(),width:child.width()};child.from={height:o.height*d.from.y,width:o.width*d.from.x};child.to={height:o.height*d.to.y,width:o.width*d.to.x};if(d.from.y!=d.to.y){child.from=c.effects.setTransition(child,f,d.from.y,child.from);child.to=c.effects.setTransition(child,
+f,d.to.y,child.to)}if(d.from.x!=d.to.x){child.from=c.effects.setTransition(child,k,d.from.x,child.from);child.to=c.effects.setTransition(child,k,d.to.x,child.to)}child.css(child.from);child.animate(child.to,b.duration,b.options.easing,function(){n&&c.effects.restore(child,h)})})}a.animate(a.to,{queue:false,duration:b.duration,easing:b.options.easing,complete:function(){a.to.opacity===0&&a.css("opacity",a.from.opacity);p=="hide"&&a.hide();c.effects.restore(a,n?e:g);c.effects.removeWrapper(a);b.callback&&
+b.callback.apply(this,arguments);a.dequeue()}})})}})(jQuery);
+;/*
+ * jQuery UI Effects Shake 1.8.4
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Shake
+ *
+ * Depends:
+ * jquery.effects.core.js
+ */
+(function(d){d.effects.shake=function(a){return this.queue(function(){var b=d(this),j=["position","top","left"];d.effects.setMode(b,a.options.mode||"effect");var c=a.options.direction||"left",e=a.options.distance||20,l=a.options.times||3,f=a.duration||a.options.duration||140;d.effects.save(b,j);b.show();d.effects.createWrapper(b);var g=c=="up"||c=="down"?"top":"left",h=c=="up"||c=="left"?"pos":"neg";c={};var i={},k={};c[g]=(h=="pos"?"-=":"+=")+e;i[g]=(h=="pos"?"+=":"-=")+e*2;k[g]=(h=="pos"?"-=":"+=")+
+e*2;b.animate(c,f,a.options.easing);for(e=1;e<l;e++)b.animate(i,f,a.options.easing).animate(k,f,a.options.easing);b.animate(i,f,a.options.easing).animate(c,f/2,a.options.easing,function(){d.effects.restore(b,j);d.effects.removeWrapper(b);a.callback&&a.callback.apply(this,arguments)});b.queue("fx",function(){b.dequeue()});b.dequeue()})}})(jQuery);
+;/*
+ * jQuery UI Effects Slide 1.8.4
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Slide
+ *
+ * Depends:
+ * jquery.effects.core.js
+ */
+(function(c){c.effects.slide=function(d){return this.queue(function(){var a=c(this),h=["position","top","left"],e=c.effects.setMode(a,d.options.mode||"show"),b=d.options.direction||"left";c.effects.save(a,h);a.show();c.effects.createWrapper(a).css({overflow:"hidden"});var f=b=="up"||b=="down"?"top":"left";b=b=="up"||b=="left"?"pos":"neg";var g=d.options.distance||(f=="top"?a.outerHeight({margin:true}):a.outerWidth({margin:true}));if(e=="show")a.css(f,b=="pos"?-g:g);var i={};i[f]=(e=="show"?b=="pos"?
+"+=":"-=":b=="pos"?"-=":"+=")+g;a.animate(i,{queue:false,duration:d.duration,easing:d.options.easing,complete:function(){e=="hide"&&a.hide();c.effects.restore(a,h);c.effects.removeWrapper(a);d.callback&&d.callback.apply(this,arguments);a.dequeue()}})})}})(jQuery);
+;/*
+ * jQuery UI Effects Transfer 1.8.4
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Transfer
+ *
+ * Depends:
+ * jquery.effects.core.js
+ */
+(function(e){e.effects.transfer=function(a){return this.queue(function(){var b=e(this),c=e(a.options.to),d=c.offset();c={top:d.top,left:d.left,height:c.innerHeight(),width:c.innerWidth()};d=b.offset();var f=e('<div class="ui-effects-transfer"></div>').appendTo(document.body).addClass(a.options.className).css({top:d.top,left:d.left,height:b.innerHeight(),width:b.innerWidth(),position:"absolute"}).animate(c,a.duration,a.options.easing,function(){f.remove();a.callback&&a.callback.apply(b[0],arguments);
+b.dequeue()})})}})(jQuery);
+; \ No newline at end of file
diff --git a/install/ui/jquery.ba-bbq.js b/install/ui/jquery.ba-bbq.js
new file mode 100644
index 000000000..bcbf24834
--- /dev/null
+++ b/install/ui/jquery.ba-bbq.js
@@ -0,0 +1,18 @@
+/*
+ * jQuery BBQ: Back Button & Query Library - v1.2.1 - 2/17/2010
+ * http://benalman.com/projects/jquery-bbq-plugin/
+ *
+ * Copyright (c) 2010 "Cowboy" Ben Alman
+ * Dual licensed under the MIT and GPL licenses.
+ * http://benalman.com/about/license/
+ */
+(function($,p){var i,m=Array.prototype.slice,r=decodeURIComponent,a=$.param,c,l,v,b=$.bbq=$.bbq||{},q,u,j,e=$.event.special,d="hashchange",A="querystring",D="fragment",y="elemUrlAttr",g="location",k="href",t="src",x=/^.*\?|#.*$/g,w=/^.*\#/,h,C={};function E(F){return typeof F==="string"}function B(G){var F=m.call(arguments,1);return function(){return G.apply(this,F.concat(m.call(arguments)))}}function n(F){return F.replace(/^[^#]*#?(.*)$/,"$1")}function o(F){return F.replace(/(?:^[^?#]*\?([^#]*).*$)?.*/,"$1")}function f(H,M,F,I,G){var O,L,K,N,J;if(I!==i){K=F.match(H?/^([^#]*)\#?(.*)$/:/^([^#?]*)\??([^#]*)(#?.*)/);J=K[3]||"";if(G===2&&E(I)){L=I.replace(H?w:x,"")}else{N=l(K[2]);I=E(I)?l[H?D:A](I):I;L=G===2?I:G===1?$.extend({},I,N):$.extend({},N,I);L=a(L);if(H){L=L.replace(h,r)}}O=K[1]+(H?"#":L||!K[1]?"?":"")+L+J}else{O=M(F!==i?F:p[g][k])}return O}a[A]=B(f,0,o);a[D]=c=B(f,1,n);c.noEscape=function(G){G=G||"";var F=$.map(G.split(""),encodeURIComponent);h=new RegExp(F.join("|"),"g")};c.noEscape(",/");$.deparam=l=function(I,F){var H={},G={"true":!0,"false":!1,"null":null};$.each(I.replace(/\+/g," ").split("&"),function(L,Q){var K=Q.split("="),P=r(K[0]),J,O=H,M=0,R=P.split("]["),N=R.length-1;if(/\[/.test(R[0])&&/\]$/.test(R[N])){R[N]=R[N].replace(/\]$/,"");R=R.shift().split("[").concat(R);N=R.length-1}else{N=0}if(K.length===2){J=r(K[1]);if(F){J=J&&!isNaN(J)?+J:J==="undefined"?i:G[J]!==i?G[J]:J}if(N){for(;M<=N;M++){P=R[M]===""?O.length:R[M];O=O[P]=M<N?O[P]||(R[M+1]&&isNaN(R[M+1])?{}:[]):J}}else{if($.isArray(H[P])){H[P].push(J)}else{if(H[P]!==i){H[P]=[H[P],J]}else{H[P]=J}}}}else{if(P){H[P]=F?i:""}}});return H};function z(H,F,G){if(F===i||typeof F==="boolean"){G=F;F=a[H?D:A]()}else{F=E(F)?F.replace(H?w:x,""):F}return l(F,G)}l[A]=B(z,0);l[D]=v=B(z,1);$[y]||($[y]=function(F){return $.extend(C,F)})({a:k,base:k,iframe:t,img:t,input:t,form:"action",link:k,script:t});j=$[y];function s(I,G,H,F){if(!E(H)&&typeof H!=="object"){F=H;H=G;G=i}return this.each(function(){var L=$(this),J=G||j()[(this.nodeName||"").toLowerCase()]||"",K=J&&L.attr(J)||"";L.attr(J,a[I](K,H,F))})}$.fn[A]=B(s,A);$.fn[D]=B(s,D);b.pushState=q=function(I,F){if(E(I)&&/^#/.test(I)&&F===i){F=2}var H=I!==i,G=c(p[g][k],H?I:{},H?F:2);p[g][k]=G+(/#/.test(G)?"":"#")};b.getState=u=function(F,G){return F===i||typeof F==="boolean"?v(F):v(G)[F]};b.removeState=function(F){var G={};if(F!==i){G=u();$.each($.isArray(F)?F:arguments,function(I,H){delete G[H]})}q(G,2)};e[d]=$.extend(e[d],{add:function(F){var H;function G(J){var I=J[D]=c();J.getState=function(K,L){return K===i||typeof K==="boolean"?l(I,K):l(I,L)[K]};H.apply(this,arguments)}if($.isFunction(F)){H=F;return G}else{H=F.handler;F.handler=G}}})})(jQuery,this);
+/*
+ * jQuery hashchange event - v1.2 - 2/11/2010
+ * http://benalman.com/projects/jquery-hashchange-plugin/
+ *
+ * Copyright (c) 2010 "Cowboy" Ben Alman
+ * Dual licensed under the MIT and GPL licenses.
+ * http://benalman.com/about/license/
+ */
+(function($,i,b){var j,k=$.event.special,c="location",d="hashchange",l="href",f=$.browser,g=document.documentMode,h=f.msie&&(g===b||g<8),e="on"+d in i&&!h;function a(m){m=m||i[c][l];return m.replace(/^[^#]*#?(.*)$/,"$1")}$[d+"Delay"]=100;k[d]=$.extend(k[d],{setup:function(){if(e){return false}$(j.start)},teardown:function(){if(e){return false}$(j.stop)}});j=(function(){var m={},r,n,o,q;function p(){o=q=function(s){return s};if(h){n=$('<iframe src="javascript:0"/>').hide().insertAfter("body")[0].contentWindow;q=function(){return a(n.document[c][l])};o=function(u,s){if(u!==s){var t=n.document;t.open().close();t[c].hash="#"+u}};o(a())}}m.start=function(){if(r){return}var t=a();o||p();(function s(){var v=a(),u=q(t);if(v!==t){o(t=v,u);$(i).trigger(d)}else{if(u!==t){i[c][l]=i[c][l].replace(/#.*/,"")+"#"+u}}r=setTimeout(s,$[d+"Delay"])})()};m.stop=function(){if(!n){r&&clearTimeout(r);r=0}};return m})()})(jQuery,this); \ No newline at end of file
diff --git a/install/ui/jquery.cookie.js b/install/ui/jquery.cookie.js
new file mode 100644
index 000000000..6df1faca2
--- /dev/null
+++ b/install/ui/jquery.cookie.js
@@ -0,0 +1,96 @@
+/**
+ * Cookie plugin
+ *
+ * Copyright (c) 2006 Klaus Hartl (stilbuero.de)
+ * Dual licensed under the MIT and GPL licenses:
+ * http://www.opensource.org/licenses/mit-license.php
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ */
+
+/**
+ * Create a cookie with the given name and value and other optional parameters.
+ *
+ * @example $.cookie('the_cookie', 'the_value');
+ * @desc Set the value of a cookie.
+ * @example $.cookie('the_cookie', 'the_value', { expires: 7, path: '/', domain: 'jquery.com', secure: true });
+ * @desc Create a cookie with all available options.
+ * @example $.cookie('the_cookie', 'the_value');
+ * @desc Create a session cookie.
+ * @example $.cookie('the_cookie', null);
+ * @desc Delete a cookie by passing null as value. Keep in mind that you have to use the same path and domain
+ * used when the cookie was set.
+ *
+ * @param String name The name of the cookie.
+ * @param String value The value of the cookie.
+ * @param Object options An object literal containing key/value pairs to provide optional cookie attributes.
+ * @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object.
+ * If a negative value is specified (e.g. a date in the past), the cookie will be deleted.
+ * If set to null or omitted, the cookie will be a session cookie and will not be retained
+ * when the the browser exits.
+ * @option String path The value of the path atribute of the cookie (default: path of page that created the cookie).
+ * @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie).
+ * @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will
+ * require a secure protocol (like HTTPS).
+ * @type undefined
+ *
+ * @name $.cookie
+ * @cat Plugins/Cookie
+ * @author Klaus Hartl/klaus.hartl@stilbuero.de
+ */
+
+/**
+ * Get the value of a cookie with the given name.
+ *
+ * @example $.cookie('the_cookie');
+ * @desc Get the value of a cookie.
+ *
+ * @param String name The name of the cookie.
+ * @return The value of the cookie.
+ * @type String
+ *
+ * @name $.cookie
+ * @cat Plugins/Cookie
+ * @author Klaus Hartl/klaus.hartl@stilbuero.de
+ */
+jQuery.cookie = function(name, value, options) {
+ if (typeof value != 'undefined') { // name and value given, set cookie
+ options = options || {};
+ if (value === null) {
+ value = '';
+ options.expires = -1;
+ }
+ var expires = '';
+ if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) {
+ var date;
+ if (typeof options.expires == 'number') {
+ date = new Date();
+ date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
+ } else {
+ date = options.expires;
+ }
+ expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE
+ }
+ // CAUTION: Needed to parenthesize options.path and options.domain
+ // in the following expressions, otherwise they evaluate to undefined
+ // in the packed version for some reason...
+ var path = options.path ? '; path=' + (options.path) : '';
+ var domain = options.domain ? '; domain=' + (options.domain) : '';
+ var secure = options.secure ? '; secure' : '';
+ document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
+ } else { // only name given, get cookie
+ var cookieValue = null;
+ if (document.cookie && document.cookie != '') {
+ var cookies = document.cookie.split(';');
+ for (var i = 0; i < cookies.length; i++) {
+ var cookie = jQuery.trim(cookies[i]);
+ // Does this cookie string begin with the name we want?
+ if (cookie.substring(0, name.length + 1) == (name + '=')) {
+ cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
+ break;
+ }
+ }
+ }
+ return cookieValue;
+ }
+}; \ No newline at end of file
diff --git a/install/ui/jquery.js b/install/ui/jquery.js
new file mode 100644
index 000000000..fff677643
--- /dev/null
+++ b/install/ui/jquery.js
@@ -0,0 +1,6240 @@
+/*!
+ * jQuery JavaScript Library v1.4.2
+ * http://jquery.com/
+ *
+ * Copyright 2010, John Resig
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * Includes Sizzle.js
+ * http://sizzlejs.com/
+ * Copyright 2010, The Dojo Foundation
+ * Released under the MIT, BSD, and GPL Licenses.
+ *
+ * Date: Sat Feb 13 22:33:48 2010 -0500
+ */
+(function( window, undefined ) {
+
+// Define a local copy of jQuery
+var jQuery = function( selector, context ) {
+ // The jQuery object is actually just the init constructor 'enhanced'
+ return new jQuery.fn.init( selector, context );
+ },
+
+ // Map over jQuery in case of overwrite
+ _jQuery = window.jQuery,
+
+ // Map over the $ in case of overwrite
+ _$ = window.$,
+
+ // Use the correct document accordingly with window argument (sandbox)
+ document = window.document,
+
+ // A central reference to the root jQuery(document)
+ rootjQuery,
+
+ // A simple way to check for HTML strings or ID strings
+ // (both of which we optimize for)
+ quickExpr = /^[^<]*(<[\w\W]+>)[^>]*$|^#([\w-]+)$/,
+
+ // Is it a simple selector
+ isSimple = /^.[^:#\[\.,]*$/,
+
+ // Check if a string has a non-whitespace character in it
+ rnotwhite = /\S/,
+
+ // Used for trimming whitespace
+ rtrim = /^(\s|\u00A0)+|(\s|\u00A0)+$/g,
+
+ // Match a standalone tag
+ rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/,
+
+ // Keep a UserAgent string for use with jQuery.browser
+ userAgent = navigator.userAgent,
+
+ // For matching the engine and version of the browser
+ browserMatch,
+
+ // Has the ready events already been bound?
+ readyBound = false,
+
+ // The functions to execute on DOM ready
+ readyList = [],
+
+ // The ready event handler
+ DOMContentLoaded,
+
+ // Save a reference to some core methods
+ toString = Object.prototype.toString,
+ hasOwnProperty = Object.prototype.hasOwnProperty,
+ push = Array.prototype.push,
+ slice = Array.prototype.slice,
+ indexOf = Array.prototype.indexOf;
+
+jQuery.fn = jQuery.prototype = {
+ init: function( selector, context ) {
+ var match, elem, ret, doc;
+
+ // Handle $(""), $(null), or $(undefined)
+ if ( !selector ) {
+ return this;
+ }
+
+ // Handle $(DOMElement)
+ if ( selector.nodeType ) {
+ this.context = this[0] = selector;
+ this.length = 1;
+ return this;
+ }
+
+ // The body element only exists once, optimize finding it
+ if ( selector === "body" && !context ) {
+ this.context = document;
+ this[0] = document.body;
+ this.selector = "body";
+ this.length = 1;
+ return this;
+ }
+
+ // Handle HTML strings
+ if ( typeof selector === "string" ) {
+ // Are we dealing with HTML string or an ID?
+ match = quickExpr.exec( selector );
+
+ // Verify a match, and that no context was specified for #id
+ if ( match && (match[1] || !context) ) {
+
+ // HANDLE: $(html) -> $(array)
+ if ( match[1] ) {
+ doc = (context ? context.ownerDocument || context : document);
+
+ // If a single string is passed in and it's a single tag
+ // just do a createElement and skip the rest
+ ret = rsingleTag.exec( selector );
+
+ if ( ret ) {
+ if ( jQuery.isPlainObject( context ) ) {
+ selector = [ document.createElement( ret[1] ) ];
+ jQuery.fn.attr.call( selector, context, true );
+
+ } else {
+ selector = [ doc.createElement( ret[1] ) ];
+ }
+
+ } else {
+ ret = buildFragment( [ match[1] ], [ doc ] );
+ selector = (ret.cacheable ? ret.fragment.cloneNode(true) : ret.fragment).childNodes;
+ }
+
+ return jQuery.merge( this, selector );
+
+ // HANDLE: $("#id")
+ } else {
+ elem = document.getElementById( match[2] );
+
+ if ( elem ) {
+ // Handle the case where IE and Opera return items
+ // by name instead of ID
+ if ( elem.id !== match[2] ) {
+ return rootjQuery.find( selector );
+ }
+
+ // Otherwise, we inject the element directly into the jQuery object
+ this.length = 1;
+ this[0] = elem;
+ }
+
+ this.context = document;
+ this.selector = selector;
+ return this;
+ }
+
+ // HANDLE: $("TAG")
+ } else if ( !context && /^\w+$/.test( selector ) ) {
+ this.selector = selector;
+ this.context = document;
+ selector = document.getElementsByTagName( selector );
+ return jQuery.merge( this, selector );
+
+ // HANDLE: $(expr, $(...))
+ } else if ( !context || context.jquery ) {
+ return (context || rootjQuery).find( selector );
+
+ // HANDLE: $(expr, context)
+ // (which is just equivalent to: $(context).find(expr)
+ } else {
+ return jQuery( context ).find( selector );
+ }
+
+ // HANDLE: $(function)
+ // Shortcut for document ready
+ } else if ( jQuery.isFunction( selector ) ) {
+ return rootjQuery.ready( selector );
+ }
+
+ if (selector.selector !== undefined) {
+ this.selector = selector.selector;
+ this.context = selector.context;
+ }
+
+ return jQuery.makeArray( selector, this );
+ },
+
+ // Start with an empty selector
+ selector: "",
+
+ // The current version of jQuery being used
+ jquery: "1.4.2",
+
+ // The default length of a jQuery object is 0
+ length: 0,
+
+ // The number of elements contained in the matched element set
+ size: function() {
+ return this.length;
+ },
+
+ toArray: function() {
+ return slice.call( this, 0 );
+ },
+
+ // Get the Nth element in the matched element set OR
+ // Get the whole matched element set as a clean array
+ get: function( num ) {
+ return num == null ?
+
+ // Return a 'clean' array
+ this.toArray() :
+
+ // Return just the object
+ ( num < 0 ? this.slice(num)[ 0 ] : this[ num ] );
+ },
+
+ // Take an array of elements and push it onto the stack
+ // (returning the new matched element set)
+ pushStack: function( elems, name, selector ) {
+ // Build a new jQuery matched element set
+ var ret = jQuery();
+
+ if ( jQuery.isArray( elems ) ) {
+ push.apply( ret, elems );
+
+ } else {
+ jQuery.merge( ret, elems );
+ }
+
+ // Add the old object onto the stack (as a reference)
+ ret.prevObject = this;
+
+ ret.context = this.context;
+
+ if ( name === "find" ) {
+ ret.selector = this.selector + (this.selector ? " " : "") + selector;
+ } else if ( name ) {
+ ret.selector = this.selector + "." + name + "(" + selector + ")";
+ }
+
+ // Return the newly-formed element set
+ return ret;
+ },
+
+ // Execute a callback for every element in the matched set.
+ // (You can seed the arguments with an array of args, but this is
+ // only used internally.)
+ each: function( callback, args ) {
+ return jQuery.each( this, callback, args );
+ },
+
+ ready: function( fn ) {
+ // Attach the listeners
+ jQuery.bindReady();
+
+ // If the DOM is already ready
+ if ( jQuery.isReady ) {
+ // Execute the function immediately
+ fn.call( document, jQuery );
+
+ // Otherwise, remember the function for later
+ } else if ( readyList ) {
+ // Add the function to the wait list
+ readyList.push( fn );
+ }
+
+ return this;
+ },
+
+ eq: function( i ) {
+ return i === -1 ?
+ this.slice( i ) :
+ this.slice( i, +i + 1 );
+ },
+
+ first: function() {
+ return this.eq( 0 );
+ },
+
+ last: function() {
+ return this.eq( -1 );
+ },
+
+ slice: function() {
+ return this.pushStack( slice.apply( this, arguments ),
+ "slice", slice.call(arguments).join(",") );
+ },
+
+ map: function( callback ) {
+ return this.pushStack( jQuery.map(this, function( elem, i ) {
+ return callback.call( elem, i, elem );
+ }));
+ },
+
+ end: function() {
+ return this.prevObject || jQuery(null);
+ },
+
+ // For internal use only.
+ // Behaves like an Array's method, not like a jQuery method.
+ push: push,
+ sort: [].sort,
+ splice: [].splice
+};
+
+// Give the init function the jQuery prototype for later instantiation
+jQuery.fn.init.prototype = jQuery.fn;
+
+jQuery.extend = jQuery.fn.extend = function() {
+ // copy reference to target object
+ var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options, name, src, copy;
+
+ // Handle a deep copy situation
+ if ( typeof target === "boolean" ) {
+ deep = target;
+ target = arguments[1] || {};
+ // skip the boolean and the target
+ i = 2;
+ }
+
+ // Handle case when target is a string or something (possible in deep copy)
+ if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
+ target = {};
+ }
+
+ // extend jQuery itself if only one argument is passed
+ if ( length === i ) {
+ target = this;
+ --i;
+ }
+
+ for ( ; i < length; i++ ) {
+ // Only deal with non-null/undefined values
+ if ( (options = arguments[ i ]) != null ) {
+ // Extend the base object
+ for ( name in options ) {
+ src = target[ name ];
+ copy = options[ name ];
+
+ // Prevent never-ending loop
+ if ( target === copy ) {
+ continue;
+ }
+
+ // Recurse if we're merging object literal values or arrays
+ if ( deep && copy && ( jQuery.isPlainObject(copy) || jQuery.isArray(copy) ) ) {
+ var clone = src && ( jQuery.isPlainObject(src) || jQuery.isArray(src) ) ? src
+ : jQuery.isArray(copy) ? [] : {};
+
+ // Never move original objects, clone them
+ target[ name ] = jQuery.extend( deep, clone, copy );
+
+ // Don't bring in undefined values
+ } else if ( copy !== undefined ) {
+ target[ name ] = copy;
+ }
+ }
+ }
+ }
+
+ // Return the modified object
+ return target;
+};
+
+jQuery.extend({
+ noConflict: function( deep ) {
+ window.$ = _$;
+
+ if ( deep ) {
+ window.jQuery = _jQuery;
+ }
+
+ return jQuery;
+ },
+
+ // Is the DOM ready to be used? Set to true once it occurs.
+ isReady: false,
+
+ // Handle when the DOM is ready
+ ready: function() {
+ // Make sure that the DOM is not already loaded
+ if ( !jQuery.isReady ) {
+ // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
+ if ( !document.body ) {
+ return setTimeout( jQuery.ready, 13 );
+ }
+
+ // Remember that the DOM is ready
+ jQuery.isReady = true;
+
+ // If there are functions bound, to execute
+ if ( readyList ) {
+ // Execute all of them
+ var fn, i = 0;
+ while ( (fn = readyList[ i++ ]) ) {
+ fn.call( document, jQuery );
+ }
+
+ // Reset the list of functions
+ readyList = null;
+ }
+
+ // Trigger any bound ready events
+ if ( jQuery.fn.triggerHandler ) {
+ jQuery( document ).triggerHandler( "ready" );
+ }
+ }
+ },
+
+ bindReady: function() {
+ if ( readyBound ) {
+ return;
+ }
+
+ readyBound = true;
+
+ // Catch cases where $(document).ready() is called after the
+ // browser event has already occurred.
+ if ( document.readyState === "complete" ) {
+ return jQuery.ready();
+ }
+
+ // Mozilla, Opera and webkit nightlies currently support this event
+ if ( document.addEventListener ) {
+ // Use the handy event callback
+ document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
+
+ // A fallback to window.onload, that will always work
+ window.addEventListener( "load", jQuery.ready, false );
+
+ // If IE event model is used
+ } else if ( document.attachEvent ) {
+ // ensure firing before onload,
+ // maybe late but safe also for iframes
+ document.attachEvent("onreadystatechange", DOMContentLoaded);
+
+ // A fallback to window.onload, that will always work
+ window.attachEvent( "onload", jQuery.ready );
+
+ // If IE and not a frame
+ // continually check to see if the document is ready
+ var toplevel = false;
+
+ try {
+ toplevel = window.frameElement == null;
+ } catch(e) {}
+
+ if ( document.documentElement.doScroll && toplevel ) {
+ doScrollCheck();
+ }
+ }
+ },
+
+ // See test/unit/core.js for details concerning isFunction.
+ // Since version 1.3, DOM methods and functions like alert
+ // aren't supported. They return false on IE (#2968).
+ isFunction: function( obj ) {
+ return toString.call(obj) === "[object Function]";
+ },
+
+ isArray: function( obj ) {
+ return toString.call(obj) === "[object Array]";
+ },
+
+ isPlainObject: function( obj ) {
+ // Must be an Object.
+ // Because of IE, we also have to check the presence of the constructor property.
+ // Make sure that DOM nodes and window objects don't pass through, as well
+ if ( !obj || toString.call(obj) !== "[object Object]" || obj.nodeType || obj.setInterval ) {
+ return false;
+ }
+
+ // Not own constructor property must be Object
+ if ( obj.constructor
+ && !hasOwnProperty.call(obj, "constructor")
+ && !hasOwnProperty.call(obj.constructor.prototype, "isPrototypeOf") ) {
+ return false;
+ }
+
+ // Own properties are enumerated firstly, so to speed up,
+ // if last one is own, then all properties are own.
+
+ var key;
+ for ( key in obj ) {}
+
+ return key === undefined || hasOwnProperty.call( obj, key );
+ },
+
+ isEmptyObject: function( obj ) {
+ for ( var name in obj ) {
+ return false;
+ }
+ return true;
+ },
+
+ error: function( msg ) {
+ throw msg;
+ },
+
+ parseJSON: function( data ) {
+ if ( typeof data !== "string" || !data ) {
+ return null;
+ }
+
+ // Make sure leading/trailing whitespace is removed (IE can't handle it)
+ data = jQuery.trim( data );
+
+ // Make sure the incoming data is actual JSON
+ // Logic borrowed from http://json.org/json2.js
+ if ( /^[\],:{}\s]*$/.test(data.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, "@")
+ .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, "]")
+ .replace(/(?:^|:|,)(?:\s*\[)+/g, "")) ) {
+
+ // Try to use the native JSON parser first
+ return window.JSON && window.JSON.parse ?
+ window.JSON.parse( data ) :
+ (new Function("return " + data))();
+
+ } else {
+ jQuery.error( "Invalid JSON: " + data );
+ }
+ },
+
+ noop: function() {},
+
+ // Evalulates a script in a global context
+ globalEval: function( data ) {
+ if ( data && rnotwhite.test(data) ) {
+ // Inspired by code by Andrea Giammarchi
+ // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
+ var head = document.getElementsByTagName("head")[0] || document.documentElement,
+ script = document.createElement("script");
+
+ script.type = "text/javascript";
+
+ if ( jQuery.support.scriptEval ) {
+ script.appendChild( document.createTextNode( data ) );
+ } else {
+ script.text = data;
+ }
+
+ // Use insertBefore instead of appendChild to circumvent an IE6 bug.
+ // This arises when a base node is used (#2709).
+ head.insertBefore( script, head.firstChild );
+ head.removeChild( script );
+ }
+ },
+
+ nodeName: function( elem, name ) {
+ return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();
+ },
+
+ // args is for internal usage only
+ each: function( object, callback, args ) {
+ var name, i = 0,
+ length = object.length,
+ isObj = length === undefined || jQuery.isFunction(object);
+
+ if ( args ) {
+ if ( isObj ) {
+ for ( name in object ) {
+ if ( callback.apply( object[ name ], args ) === false ) {
+ break;
+ }
+ }
+ } else {
+ for ( ; i < length; ) {
+ if ( callback.apply( object[ i++ ], args ) === false ) {
+ break;
+ }
+ }
+ }
+
+ // A special, fast, case for the most common use of each
+ } else {
+ if ( isObj ) {
+ for ( name in object ) {
+ if ( callback.call( object[ name ], name, object[ name ] ) === false ) {
+ break;
+ }
+ }
+ } else {
+ for ( var value = object[0];
+ i < length && callback.call( value, i, value ) !== false; value = object[++i] ) {}
+ }
+ }
+
+ return object;
+ },
+
+ trim: function( text ) {
+ return (text || "").replace( rtrim, "" );
+ },
+
+ // results is for internal usage only
+ makeArray: function( array, results ) {
+ var ret = results || [];
+
+ if ( array != null ) {
+ // The window, strings (and functions) also have 'length'
+ // The extra typeof function check is to prevent crashes
+ // in Safari 2 (See: #3039)
+ if ( array.length == null || typeof array === "string" || jQuery.isFunction(array) || (typeof array !== "function" && array.setInterval) ) {
+ push.call( ret, array );
+ } else {
+ jQuery.merge( ret, array );
+ }
+ }
+
+ return ret;
+ },
+
+ inArray: function( elem, array ) {
+ if ( array.indexOf ) {
+ return array.indexOf( elem );
+ }
+
+ for ( var i = 0, length = array.length; i < length; i++ ) {
+ if ( array[ i ] === elem ) {
+ return i;
+ }
+ }
+
+ return -1;
+ },
+
+ merge: function( first, second ) {
+ var i = first.length, j = 0;
+
+ if ( typeof second.length === "number" ) {
+ for ( var l = second.length; j < l; j++ ) {
+ first[ i++ ] = second[ j ];
+ }
+
+ } else {
+ while ( second[j] !== undefined ) {
+ first[ i++ ] = second[ j++ ];
+ }
+ }
+
+ first.length = i;
+
+ return first;
+ },
+
+ grep: function( elems, callback, inv ) {
+ var ret = [];
+
+ // Go through the array, only saving the items
+ // that pass the validator function
+ for ( var i = 0, length = elems.length; i < length; i++ ) {
+ if ( !inv !== !callback( elems[ i ], i ) ) {
+ ret.push( elems[ i ] );
+ }
+ }
+
+ return ret;
+ },
+
+ // arg is for internal usage only
+ map: function( elems, callback, arg ) {
+ var ret = [], value;
+
+ // Go through the array, translating each of the items to their
+ // new value (or values).
+ for ( var i = 0, length = elems.length; i < length; i++ ) {
+ value = callback( elems[ i ], i, arg );
+
+ if ( value != null ) {
+ ret[ ret.length ] = value;
+ }
+ }
+
+ return ret.concat.apply( [], ret );
+ },
+
+ // A global GUID counter for objects
+ guid: 1,
+
+ proxy: function( fn, proxy, thisObject ) {
+ if ( arguments.length === 2 ) {
+ if ( typeof proxy === "string" ) {
+ thisObject = fn;
+ fn = thisObject[ proxy ];
+ proxy = undefined;
+
+ } else if ( proxy && !jQuery.isFunction( proxy ) ) {
+ thisObject = proxy;
+ proxy = undefined;
+ }
+ }
+
+ if ( !proxy && fn ) {
+ proxy = function() {
+ return fn.apply( thisObject || this, arguments );
+ };
+ }
+
+ // Set the guid of unique handler to the same of original handler, so it can be removed
+ if ( fn ) {
+ proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;
+ }
+
+ // So proxy can be declared as an argument
+ return proxy;
+ },
+
+ // Use of jQuery.browser is frowned upon.
+ // More details: http://docs.jquery.com/Utilities/jQuery.browser
+ uaMatch: function( ua ) {
+ ua = ua.toLowerCase();
+
+ var match = /(webkit)[ \/]([\w.]+)/.exec( ua ) ||
+ /(opera)(?:.*version)?[ \/]([\w.]+)/.exec( ua ) ||
+ /(msie) ([\w.]+)/.exec( ua ) ||
+ !/compatible/.test( ua ) && /(mozilla)(?:.*? rv:([\w.]+))?/.exec( ua ) ||
+ [];
+
+ return { browser: match[1] || "", version: match[2] || "0" };
+ },
+
+ browser: {}
+});
+
+browserMatch = jQuery.uaMatch( userAgent );
+if ( browserMatch.browser ) {
+ jQuery.browser[ browserMatch.browser ] = true;
+ jQuery.browser.version = browserMatch.version;
+}
+
+// Deprecated, use jQuery.browser.webkit instead
+if ( jQuery.browser.webkit ) {
+ jQuery.browser.safari = true;
+}
+
+if ( indexOf ) {
+ jQuery.inArray = function( elem, array ) {
+ return indexOf.call( array, elem );
+ };
+}
+
+// All jQuery objects should point back to these
+rootjQuery = jQuery(document);
+
+// Cleanup functions for the document ready method
+if ( document.addEventListener ) {
+ DOMContentLoaded = function() {
+ document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
+ jQuery.ready();
+ };
+
+} else if ( document.attachEvent ) {
+ DOMContentLoaded = function() {
+ // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
+ if ( document.readyState === "complete" ) {
+ document.detachEvent( "onreadystatechange", DOMContentLoaded );
+ jQuery.ready();
+ }
+ };
+}
+
+// The DOM ready check for Internet Explorer
+function doScrollCheck() {
+ if ( jQuery.isReady ) {
+ return;
+ }
+
+ try {
+ // If IE is used, use the trick by Diego Perini
+ // http://javascript.nwbox.com/IEContentLoaded/
+ document.documentElement.doScroll("left");
+ } catch( error ) {
+ setTimeout( doScrollCheck, 1 );
+ return;
+ }
+
+ // and execute any waiting functions
+ jQuery.ready();
+}
+
+function evalScript( i, elem ) {
+ if ( elem.src ) {
+ jQuery.ajax({
+ url: elem.src,
+ async: false,
+ dataType: "script"
+ });
+ } else {
+ jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
+ }
+
+ if ( elem.parentNode ) {
+ elem.parentNode.removeChild( elem );
+ }
+}
+
+// Mutifunctional method to get and set values to a collection
+// The value/s can be optionally by executed if its a function
+function access( elems, key, value, exec, fn, pass ) {
+ var length = elems.length;
+
+ // Setting many attributes
+ if ( typeof key === "object" ) {
+ for ( var k in key ) {
+ access( elems, k, key[k], exec, fn, value );
+ }
+ return elems;
+ }
+
+ // Setting one attribute
+ if ( value !== undefined ) {
+ // Optionally, function values get executed if exec is true
+ exec = !pass && exec && jQuery.isFunction(value);
+
+ for ( var i = 0; i < length; i++ ) {
+ fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );
+ }
+
+ return elems;
+ }
+
+ // Getting an attribute
+ return length ? fn( elems[0], key ) : undefined;
+}
+
+function now() {
+ return (new Date).getTime();
+}
+(function() {
+
+ jQuery.support = {};
+
+ var root = document.documentElement,
+ script = document.createElement("script"),
+ div = document.createElement("div"),
+ id = "script" + now();
+
+ div.style.display = "none";
+ div.innerHTML = " <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
+
+ var all = div.getElementsByTagName("*"),
+ a = div.getElementsByTagName("a")[0];
+
+ // Can't get basic test support
+ if ( !all || !all.length || !a ) {
+ return;
+ }
+
+ jQuery.support = {
+ // IE strips leading whitespace when .innerHTML is used
+ leadingWhitespace: div.firstChild.nodeType === 3,
+
+ // Make sure that tbody elements aren't automatically inserted
+ // IE will insert them into empty tables
+ tbody: !div.getElementsByTagName("tbody").length,
+
+ // Make sure that link elements get serialized correctly by innerHTML
+ // This requires a wrapper element in IE
+ htmlSerialize: !!div.getElementsByTagName("link").length,
+
+ // Get the style information from getAttribute
+ // (IE uses .cssText insted)
+ style: /red/.test( a.getAttribute("style") ),
+
+ // Make sure that URLs aren't manipulated
+ // (IE normalizes it by default)
+ hrefNormalized: a.getAttribute("href") === "/a",
+
+ // Make sure that element opacity exists
+ // (IE uses filter instead)
+ // Use a regex to work around a WebKit issue. See #5145
+ opacity: /^0.55$/.test( a.style.opacity ),
+
+ // Verify style float existence
+ // (IE uses styleFloat instead of cssFloat)
+ cssFloat: !!a.style.cssFloat,
+
+ // Make sure that if no value is specified for a checkbox
+ // that it defaults to "on".
+ // (WebKit defaults to "" instead)
+ checkOn: div.getElementsByTagName("input")[0].value === "on",
+
+ // Make sure that a selected-by-default option has a working selected property.
+ // (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
+ optSelected: document.createElement("select").appendChild( document.createElement("option") ).selected,
+
+ parentNode: div.removeChild( div.appendChild( document.createElement("div") ) ).parentNode === null,
+
+ // Will be defined later
+ deleteExpando: true,
+ checkClone: false,
+ scriptEval: false,
+ noCloneEvent: true,
+ boxModel: null
+ };
+
+ script.type = "text/javascript";
+ try {
+ script.appendChild( document.createTextNode( "window." + id + "=1;" ) );
+ } catch(e) {}
+
+ root.insertBefore( script, root.firstChild );
+
+ // Make sure that the execution of code works by injecting a script
+ // tag with appendChild/createTextNode
+ // (IE doesn't support this, fails, and uses .text instead)
+ if ( window[ id ] ) {
+ jQuery.support.scriptEval = true;
+ delete window[ id ];
+ }
+
+ // Test to see if it's possible to delete an expando from an element
+ // Fails in Internet Explorer
+ try {
+ delete script.test;
+
+ } catch(e) {
+ jQuery.support.deleteExpando = false;
+ }
+
+ root.removeChild( script );
+
+ if ( div.attachEvent && div.fireEvent ) {
+ div.attachEvent("onclick", function click() {
+ // Cloning a node shouldn't copy over any
+ // bound event handlers (IE does this)
+ jQuery.support.noCloneEvent = false;
+ div.detachEvent("onclick", click);
+ });
+ div.cloneNode(true).fireEvent("onclick");
+ }
+
+ div = document.createElement("div");
+ div.innerHTML = "<input type='radio' name='radiotest' checked='checked'/>";
+
+ var fragment = document.createDocumentFragment();
+ fragment.appendChild( div.firstChild );
+
+ // WebKit doesn't clone checked state correctly in fragments
+ jQuery.support.checkClone = fragment.cloneNode(true).cloneNode(true).lastChild.checked;
+
+ // Figure out if the W3C box model works as expected
+ // document.body must exist before we can do this
+ jQuery(function() {
+ var div = document.createElement("div");
+ div.style.width = div.style.paddingLeft = "1px";
+
+ document.body.appendChild( div );
+ jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2;
+ document.body.removeChild( div ).style.display = 'none';
+
+ div = null;
+ });
+
+ // Technique from Juriy Zaytsev
+ // http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/
+ var eventSupported = function( eventName ) {
+ var el = document.createElement("div");
+ eventName = "on" + eventName;
+
+ var isSupported = (eventName in el);
+ if ( !isSupported ) {
+ el.setAttribute(eventName, "return;");
+ isSupported = typeof el[eventName] === "function";
+ }
+ el = null;
+
+ return isSupported;
+ };
+
+ jQuery.support.submitBubbles = eventSupported("submit");
+ jQuery.support.changeBubbles = eventSupported("change");
+
+ // release memory in IE
+ root = script = div = all = a = null;
+})();
+
+jQuery.props = {
+ "for": "htmlFor",
+ "class": "className",
+ readonly: "readOnly",
+ maxlength: "maxLength",
+ cellspacing: "cellSpacing",
+ rowspan: "rowSpan",
+ colspan: "colSpan",
+ tabindex: "tabIndex",
+ usemap: "useMap",
+ frameborder: "frameBorder"
+};
+var expando = "jQuery" + now(), uuid = 0, windowData = {};
+
+jQuery.extend({
+ cache: {},
+
+ expando:expando,
+
+ // The following elements throw uncatchable exceptions if you
+ // attempt to add expando properties to them.
+ noData: {
+ "embed": true,
+ "object": true,
+ "applet": true
+ },
+
+ data: function( elem, name, data ) {
+ if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {
+ return;
+ }
+
+ elem = elem == window ?
+ windowData :
+ elem;
+
+ var id = elem[ expando ], cache = jQuery.cache, thisCache;
+
+ if ( !id && typeof name === "string" && data === undefined ) {
+ return null;
+ }
+
+ // Compute a unique ID for the element
+ if ( !id ) {
+ id = ++uuid;
+ }
+
+ // Avoid generating a new cache unless none exists and we
+ // want to manipulate it.
+ if ( typeof name === "object" ) {
+ elem[ expando ] = id;
+ thisCache = cache[ id ] = jQuery.extend(true, {}, name);
+
+ } else if ( !cache[ id ] ) {
+ elem[ expando ] = id;
+ cache[ id ] = {};
+ }
+
+ thisCache = cache[ id ];
+
+ // Prevent overriding the named cache with undefined values
+ if ( data !== undefined ) {
+ thisCache[ name ] = data;
+ }
+
+ return typeof name === "string" ? thisCache[ name ] : thisCache;
+ },
+
+ removeData: function( elem, name ) {
+ if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {
+ return;
+ }
+
+ elem = elem == window ?
+ windowData :
+ elem;
+
+ var id = elem[ expando ], cache = jQuery.cache, thisCache = cache[ id ];
+
+ // If we want to remove a specific section of the element's data
+ if ( name ) {
+ if ( thisCache ) {
+ // Remove the section of cache data
+ delete thisCache[ name ];
+
+ // If we've removed all the data, remove the element's cache
+ if ( jQuery.isEmptyObject(thisCache) ) {
+ jQuery.removeData( elem );
+ }
+ }
+
+ // Otherwise, we want to remove all of the element's data
+ } else {
+ if ( jQuery.support.deleteExpando ) {
+ delete elem[ jQuery.expando ];
+
+ } else if ( elem.removeAttribute ) {
+ elem.removeAttribute( jQuery.expando );
+ }
+
+ // Completely remove the data cache
+ delete cache[ id ];
+ }
+ }
+});
+
+jQuery.fn.extend({
+ data: function( key, value ) {
+ if ( typeof key === "undefined" && this.length ) {
+ return jQuery.data( this[0] );
+
+ } else if ( typeof key === "object" ) {
+ return this.each(function() {
+ jQuery.data( this, key );
+ });
+ }
+
+ var parts = key.split(".");
+ parts[1] = parts[1] ? "." + parts[1] : "";
+
+ if ( value === undefined ) {
+ var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
+
+ if ( data === undefined && this.length ) {
+ data = jQuery.data( this[0], key );
+ }
+ return data === undefined && parts[1] ?
+ this.data( parts[0] ) :
+ data;
+ } else {
+ return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function() {
+ jQuery.data( this, key, value );
+ });
+ }
+ },
+
+ removeData: function( key ) {
+ return this.each(function() {
+ jQuery.removeData( this, key );
+ });
+ }
+});
+jQuery.extend({
+ queue: function( elem, type, data ) {
+ if ( !elem ) {
+ return;
+ }
+
+ type = (type || "fx") + "queue";
+ var q = jQuery.data( elem, type );
+
+ // Speed up dequeue by getting out quickly if this is just a lookup
+ if ( !data ) {
+ return q || [];
+ }
+
+ if ( !q || jQuery.isArray(data) ) {
+ q = jQuery.data( elem, type, jQuery.makeArray(data) );
+
+ } else {
+ q.push( data );
+ }
+
+ return q;
+ },
+
+ dequeue: function( elem, type ) {
+ type = type || "fx";
+
+ var queue = jQuery.queue( elem, type ), fn = queue.shift();
+
+ // If the fx queue is dequeued, always remove the progress sentinel
+ if ( fn === "inprogress" ) {
+ fn = queue.shift();
+ }
+
+ if ( fn ) {
+ // Add a progress sentinel to prevent the fx queue from being
+ // automatically dequeued
+ if ( type === "fx" ) {
+ queue.unshift("inprogress");
+ }
+
+ fn.call(elem, function() {
+ jQuery.dequeue(elem, type);
+ });
+ }
+ }
+});
+
+jQuery.fn.extend({
+ queue: function( type, data ) {
+ if ( typeof type !== "string" ) {
+ data = type;
+ type = "fx";
+ }
+
+ if ( data === undefined ) {
+ return jQuery.queue( this[0], type );
+ }
+ return this.each(function( i, elem ) {
+ var queue = jQuery.queue( this, type, data );
+
+ if ( type === "fx" && queue[0] !== "inprogress" ) {
+ jQuery.dequeue( this, type );
+ }
+ });
+ },
+ dequeue: function( type ) {
+ return this.each(function() {
+ jQuery.dequeue( this, type );
+ });
+ },
+
+ // Based off of the plugin by Clint Helfers, with permission.
+ // http://blindsignals.com/index.php/2009/07/jquery-delay/
+ delay: function( time, type ) {
+ time = jQuery.fx ? jQuery.fx.speeds[time] || time : time;
+ type = type || "fx";
+
+ return this.queue( type, function() {
+ var elem = this;
+ setTimeout(function() {
+ jQuery.dequeue( elem, type );
+ }, time );
+ });
+ },
+
+ clearQueue: function( type ) {
+ return this.queue( type || "fx", [] );
+ }
+});
+var rclass = /[\n\t]/g,
+ rspace = /\s+/,
+ rreturn = /\r/g,
+ rspecialurl = /href|src|style/,
+ rtype = /(button|input)/i,
+ rfocusable = /(button|input|object|select|textarea)/i,
+ rclickable = /^(a|area)$/i,
+ rradiocheck = /radio|checkbox/;
+
+jQuery.fn.extend({
+ attr: function( name, value ) {
+ return access( this, name, value, true, jQuery.attr );
+ },
+
+ removeAttr: function( name, fn ) {
+ return this.each(function(){
+ jQuery.attr( this, name, "" );
+ if ( this.nodeType === 1 ) {
+ this.removeAttribute( name );
+ }
+ });
+ },
+
+ addClass: function( value ) {
+ if ( jQuery.isFunction(value) ) {
+ return this.each(function(i) {
+ var self = jQuery(this);
+ self.addClass( value.call(this, i, self.attr("class")) );
+ });
+ }
+
+ if ( value && typeof value === "string" ) {
+ var classNames = (value || "").split( rspace );
+
+ for ( var i = 0, l = this.length; i < l; i++ ) {
+ var elem = this[i];
+
+ if ( elem.nodeType === 1 ) {
+ if ( !elem.className ) {
+ elem.className = value;
+
+ } else {
+ var className = " " + elem.className + " ", setClass = elem.className;
+ for ( var c = 0, cl = classNames.length; c < cl; c++ ) {
+ if ( className.indexOf( " " + classNames[c] + " " ) < 0 ) {
+ setClass += " " + classNames[c];
+ }
+ }
+ elem.className = jQuery.trim( setClass );
+ }
+ }
+ }
+ }
+
+ return this;
+ },
+
+ removeClass: function( value ) {
+ if ( jQuery.isFunction(value) ) {
+ return this.each(function(i) {
+ var self = jQuery(this);
+ self.removeClass( value.call(this, i, self.attr("class")) );
+ });
+ }
+
+ if ( (value && typeof value === "string") || value === undefined ) {
+ var classNames = (value || "").split(rspace);
+
+ for ( var i = 0, l = this.length; i < l; i++ ) {
+ var elem = this[i];
+
+ if ( elem.nodeType === 1 && elem.className ) {
+ if ( value ) {
+ var className = (" " + elem.className + " ").replace(rclass, " ");
+ for ( var c = 0, cl = classNames.length; c < cl; c++ ) {
+ className = className.replace(" " + classNames[c] + " ", " ");
+ }
+ elem.className = jQuery.trim( className );
+
+ } else {
+ elem.className = "";
+ }
+ }
+ }
+ }
+
+ return this;
+ },
+
+ toggleClass: function( value, stateVal ) {
+ var type = typeof value, isBool = typeof stateVal === "boolean";
+
+ if ( jQuery.isFunction( value ) ) {
+ return this.each(function(i) {
+ var self = jQuery(this);
+ self.toggleClass( value.call(this, i, self.attr("class"), stateVal), stateVal );
+ });
+ }
+
+ return this.each(function() {
+ if ( type === "string" ) {
+ // toggle individual class names
+ var className, i = 0, self = jQuery(this),
+ state = stateVal,
+ classNames = value.split( rspace );
+
+ while ( (className = classNames[ i++ ]) ) {
+ // check each className given, space seperated list
+ state = isBool ? state : !self.hasClass( className );
+ self[ state ? "addClass" : "removeClass" ]( className );
+ }
+
+ } else if ( type === "undefined" || type === "boolean" ) {
+ if ( this.className ) {
+ // store className if set
+ jQuery.data( this, "__className__", this.className );
+ }
+
+ // toggle whole className
+ this.className = this.className || value === false ? "" : jQuery.data( this, "__className__" ) || "";
+ }
+ });
+ },
+
+ hasClass: function( selector ) {
+ var className = " " + selector + " ";
+ for ( var i = 0, l = this.length; i < l; i++ ) {
+ if ( (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) {
+ return true;
+ }
+ }
+
+ return false;
+ },
+
+ val: function( value ) {
+ if ( value === undefined ) {
+ var elem = this[0];
+
+ if ( elem ) {
+ if ( jQuery.nodeName( elem, "option" ) ) {
+ return (elem.attributes.value || {}).specified ? elem.value : elem.text;
+ }
+
+ // We need to handle select boxes special
+ if ( jQuery.nodeName( elem, "select" ) ) {
+ var index = elem.selectedIndex,
+ values = [],
+ options = elem.options,
+ one = elem.type === "select-one";
+
+ // Nothing was selected
+ if ( index < 0 ) {
+ return null;
+ }
+
+ // Loop through all the selected options
+ for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
+ var option = options[ i ];
+
+ if ( option.selected ) {
+ // Get the specifc value for the option
+ value = jQuery(option).val();
+
+ // We don't need an array for one selects
+ if ( one ) {
+ return value;
+ }
+
+ // Multi-Selects return an array
+ values.push( value );
+ }
+ }
+
+ return values;
+ }
+
+ // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
+ if ( rradiocheck.test( elem.type ) && !jQuery.support.checkOn ) {
+ return elem.getAttribute("value") === null ? "on" : elem.value;
+ }
+
+
+ // Everything else, we just grab the value
+ return (elem.value || "").replace(rreturn, "");
+
+ }
+
+ return undefined;
+ }
+
+ var isFunction = jQuery.isFunction(value);
+
+ return this.each(function(i) {
+ var self = jQuery(this), val = value;
+
+ if ( this.nodeType !== 1 ) {
+ return;
+ }
+
+ if ( isFunction ) {
+ val = value.call(this, i, self.val());
+ }
+
+ // Typecast each time if the value is a Function and the appended
+ // value is therefore different each time.
+ if ( typeof val === "number" ) {
+ val += "";
+ }
+
+ if ( jQuery.isArray(val) && rradiocheck.test( this.type ) ) {
+ this.checked = jQuery.inArray( self.val(), val ) >= 0;
+
+ } else if ( jQuery.nodeName( this, "select" ) ) {
+ var values = jQuery.makeArray(val);
+
+ jQuery( "option", this ).each(function() {
+ this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
+ });
+
+ if ( !values.length ) {
+ this.selectedIndex = -1;
+ }
+
+ } else {
+ this.value = val;
+ }
+ });
+ }
+});
+
+jQuery.extend({
+ attrFn: {
+ val: true,
+ css: true,
+ html: true,
+ text: true,
+ data: true,
+ width: true,
+ height: true,
+ offset: true
+ },
+
+ attr: function( elem, name, value, pass ) {
+ // don't set attributes on text and comment nodes
+ if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
+ return undefined;
+ }
+
+ if ( pass && name in jQuery.attrFn ) {
+ return jQuery(elem)[name](value);
+ }
+
+ var notxml = elem.nodeType !== 1 || !jQuery.isXMLDoc( elem ),
+ // Whether we are setting (or getting)
+ set = value !== undefined;
+
+ // Try to normalize/fix the name
+ name = notxml && jQuery.props[ name ] || name;
+
+ // Only do all the following if this is a node (faster for style)
+ if ( elem.nodeType === 1 ) {
+ // These attributes require special treatment
+ var special = rspecialurl.test( name );
+
+ // Safari mis-reports the default selected property of an option
+ // Accessing the parent's selectedIndex property fixes it
+ if ( name === "selected" && !jQuery.support.optSelected ) {
+ var parent = elem.parentNode;
+ if ( parent ) {
+ parent.selectedIndex;
+
+ // Make sure that it also works with optgroups, see #5701
+ if ( parent.parentNode ) {
+ parent.parentNode.selectedIndex;
+ }
+ }
+ }
+
+ // If applicable, access the attribute via the DOM 0 way
+ if ( name in elem && notxml && !special ) {
+ if ( set ) {
+ // We can't allow the type property to be changed (since it causes problems in IE)
+ if ( name === "type" && rtype.test( elem.nodeName ) && elem.parentNode ) {
+ jQuery.error( "type property can't be changed" );
+ }
+
+ elem[ name ] = value;
+ }
+
+ // browsers index elements by id/name on forms, give priority to attributes.
+ if ( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) ) {
+ return elem.getAttributeNode( name ).nodeValue;
+ }
+
+ // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
+ // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
+ if ( name === "tabIndex" ) {
+ var attributeNode = elem.getAttributeNode( "tabIndex" );
+
+ return attributeNode && attributeNode.specified ?
+ attributeNode.value :
+ rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
+ 0 :
+ undefined;
+ }
+
+ return elem[ name ];
+ }
+
+ if ( !jQuery.support.style && notxml && name === "style" ) {
+ if ( set ) {
+ elem.style.cssText = "" + value;
+ }
+
+ return elem.style.cssText;
+ }
+
+ if ( set ) {
+ // convert the value to a string (all browsers do this but IE) see #1070
+ elem.setAttribute( name, "" + value );
+ }
+
+ var attr = !jQuery.support.hrefNormalized && notxml && special ?
+ // Some attributes require a special call on IE
+ elem.getAttribute( name, 2 ) :
+ elem.getAttribute( name );
+
+ // Non-existent attributes return null, we normalize to undefined
+ return attr === null ? undefined : attr;
+ }
+
+ // elem is actually elem.style ... set the style
+ // Using attr for specific style information is now deprecated. Use style instead.
+ return jQuery.style( elem, name, value );
+ }
+});
+var rnamespaces = /\.(.*)$/,
+ fcleanup = function( nm ) {
+ return nm.replace(/[^\w\s\.\|`]/g, function( ch ) {
+ return "\\" + ch;
+ });
+ };
+
+/*
+ * A number of helper functions used for managing events.
+ * Many of the ideas behind this code originated from
+ * Dean Edwards' addEvent library.
+ */
+jQuery.event = {
+
+ // Bind an event to an element
+ // Original by Dean Edwards
+ add: function( elem, types, handler, data ) {
+ if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
+ return;
+ }
+
+ // For whatever reason, IE has trouble passing the window object
+ // around, causing it to be cloned in the process
+ if ( elem.setInterval && ( elem !== window && !elem.frameElement ) ) {
+ elem = window;
+ }
+
+ var handleObjIn, handleObj;
+
+ if ( handler.handler ) {
+ handleObjIn = handler;
+ handler = handleObjIn.handler;
+ }
+
+ // Make sure that the function being executed has a unique ID
+ if ( !handler.guid ) {
+ handler.guid = jQuery.guid++;
+ }
+
+ // Init the element's event structure
+ var elemData = jQuery.data( elem );
+
+ // If no elemData is found then we must be trying to bind to one of the
+ // banned noData elements
+ if ( !elemData ) {
+ return;
+ }
+
+ var events = elemData.events = elemData.events || {},
+ eventHandle = elemData.handle, eventHandle;
+
+ if ( !eventHandle ) {
+ elemData.handle = eventHandle = function() {
+ // Handle the second event of a trigger and when
+ // an event is called after a page has unloaded
+ return typeof jQuery !== "undefined" && !jQuery.event.triggered ?
+ jQuery.event.handle.apply( eventHandle.elem, arguments ) :
+ undefined;
+ };
+ }
+
+ // Add elem as a property of the handle function
+ // This is to prevent a memory leak with non-native events in IE.
+ eventHandle.elem = elem;
+
+ // Handle multiple events separated by a space
+ // jQuery(...).bind("mouseover mouseout", fn);
+ types = types.split(" ");
+
+ var type, i = 0, namespaces;
+
+ while ( (type = types[ i++ ]) ) {
+ handleObj = handleObjIn ?
+ jQuery.extend({}, handleObjIn) :
+ { handler: handler, data: data };
+
+ // Namespaced event handlers
+ if ( type.indexOf(".") > -1 ) {
+ namespaces = type.split(".");
+ type = namespaces.shift();
+ handleObj.namespace = namespaces.slice(0).sort().join(".");
+
+ } else {
+ namespaces = [];
+ handleObj.namespace = "";
+ }
+
+ handleObj.type = type;
+ handleObj.guid = handler.guid;
+
+ // Get the current list of functions bound to this event
+ var handlers = events[ type ],
+ special = jQuery.event.special[ type ] || {};
+
+ // Init the event handler queue
+ if ( !handlers ) {
+ handlers = events[ type ] = [];
+
+ // Check for a special event handler
+ // Only use addEventListener/attachEvent if the special
+ // events handler returns false
+ if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
+ // Bind the global event handler to the element
+ if ( elem.addEventListener ) {
+ elem.addEventListener( type, eventHandle, false );
+
+ } else if ( elem.attachEvent ) {
+ elem.attachEvent( "on" + type, eventHandle );
+ }
+ }
+ }
+
+ if ( special.add ) {
+ special.add.call( elem, handleObj );
+
+ if ( !handleObj.handler.guid ) {
+ handleObj.handler.guid = handler.guid;
+ }
+ }
+
+ // Add the function to the element's handler list
+ handlers.push( handleObj );
+
+ // Keep track of which events have been used, for global triggering
+ jQuery.event.global[ type ] = true;
+ }
+
+ // Nullify elem to prevent memory leaks in IE
+ elem = null;
+ },
+
+ global: {},
+
+ // Detach an event or set of events from an element
+ remove: function( elem, types, handler, pos ) {
+ // don't do events on text and comment nodes
+ if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
+ return;
+ }
+
+ var ret, type, fn, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType,
+ elemData = jQuery.data( elem ),
+ events = elemData && elemData.events;
+
+ if ( !elemData || !events ) {
+ return;
+ }
+
+ // types is actually an event object here
+ if ( types && types.type ) {
+ handler = types.handler;
+ types = types.type;
+ }
+
+ // Unbind all events for the element
+ if ( !types || typeof types === "string" && types.charAt(0) === "." ) {
+ types = types || "";
+
+ for ( type in events ) {
+ jQuery.event.remove( elem, type + types );
+ }
+
+ return;
+ }
+
+ // Handle multiple events separated by a space
+ // jQuery(...).unbind("mouseover mouseout", fn);
+ types = types.split(" ");
+
+ while ( (type = types[ i++ ]) ) {
+ origType = type;
+ handleObj = null;
+ all = type.indexOf(".") < 0;
+ namespaces = [];
+
+ if ( !all ) {
+ // Namespaced event handlers
+ namespaces = type.split(".");
+ type = namespaces.shift();
+
+ namespace = new RegExp("(^|\\.)" +
+ jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)")
+ }
+
+ eventType = events[ type ];
+
+ if ( !eventType ) {
+ continue;
+ }
+
+ if ( !handler ) {
+ for ( var j = 0; j < eventType.length; j++ ) {
+ handleObj = eventType[ j ];
+
+ if ( all || namespace.test( handleObj.namespace ) ) {
+ jQuery.event.remove( elem, origType, handleObj.handler, j );
+ eventType.splice( j--, 1 );
+ }
+ }
+
+ continue;
+ }
+
+ special = jQuery.event.special[ type ] || {};
+
+ for ( var j = pos || 0; j < eventType.length; j++ ) {
+ handleObj = eventType[ j ];
+
+ if ( handler.guid === handleObj.guid ) {
+ // remove the given handler for the given type
+ if ( all || namespace.test( handleObj.namespace ) ) {
+ if ( pos == null ) {
+ eventType.splice( j--, 1 );
+ }
+
+ if ( special.remove ) {
+ special.remove.call( elem, handleObj );
+ }
+ }
+
+ if ( pos != null ) {
+ break;
+ }
+ }
+ }
+
+ // remove generic event handler if no more handlers exist
+ if ( eventType.length === 0 || pos != null && eventType.length === 1 ) {
+ if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {
+ removeEvent( elem, type, elemData.handle );
+ }
+
+ ret = null;
+ delete events[ type ];
+ }
+ }
+
+ // Remove the expando if it's no longer used
+ if ( jQuery.isEmptyObject( events ) ) {
+ var handle = elemData.handle;
+ if ( handle ) {
+ handle.elem = null;
+ }
+
+ delete elemData.events;
+ delete elemData.handle;
+
+ if ( jQuery.isEmptyObject( elemData ) ) {
+ jQuery.removeData( elem );
+ }
+ }
+ },
+
+ // bubbling is internal
+ trigger: function( event, data, elem /*, bubbling */ ) {
+ // Event object or event type
+ var type = event.type || event,
+ bubbling = arguments[3];
+
+ if ( !bubbling ) {
+ event = typeof event === "object" ?
+ // jQuery.Event object
+ event[expando] ? event :
+ // Object literal
+ jQuery.extend( jQuery.Event(type), event ) :
+ // Just the event type (string)
+ jQuery.Event(type);
+
+ if ( type.indexOf("!") >= 0 ) {
+ event.type = type = type.slice(0, -1);
+ event.exclusive = true;
+ }
+
+ // Handle a global trigger
+ if ( !elem ) {
+ // Don't bubble custom events when global (to avoid too much overhead)
+ event.stopPropagation();
+
+ // Only trigger if we've ever bound an event for it
+ if ( jQuery.event.global[ type ] ) {
+ jQuery.each( jQuery.cache, function() {
+ if ( this.events && this.events[type] ) {
+ jQuery.event.trigger( event, data, this.handle.elem );
+ }
+ });
+ }
+ }
+
+ // Handle triggering a single element
+
+ // don't do events on text and comment nodes
+ if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
+ return undefined;
+ }
+
+ // Clean up in case it is reused
+ event.result = undefined;
+ event.target = elem;
+
+ // Clone the incoming data, if any
+ data = jQuery.makeArray( data );
+ data.unshift( event );
+ }
+
+ event.currentTarget = elem;
+
+ // Trigger the event, it is assumed that "handle" is a function
+ var handle = jQuery.data( elem, "handle" );
+ if ( handle ) {
+ handle.apply( elem, data );
+ }
+
+ var parent = elem.parentNode || elem.ownerDocument;
+
+ // Trigger an inline bound script
+ try {
+ if ( !(elem && elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()]) ) {
+ if ( elem[ "on" + type ] && elem[ "on" + type ].apply( elem, data ) === false ) {
+ event.result = false;
+ }
+ }
+
+ // prevent IE from throwing an error for some elements with some event types, see #3533
+ } catch (e) {}
+
+ if ( !event.isPropagationStopped() && parent ) {
+ jQuery.event.trigger( event, data, parent, true );
+
+ } else if ( !event.isDefaultPrevented() ) {
+ var target = event.target, old,
+ isClick = jQuery.nodeName(target, "a") && type === "click",
+ special = jQuery.event.special[ type ] || {};
+
+ if ( (!special._default || special._default.call( elem, event ) === false) &&
+ !isClick && !(target && target.nodeName && jQuery.noData[target.nodeName.toLowerCase()]) ) {
+
+ try {
+ if ( target[ type ] ) {
+ // Make sure that we don't accidentally re-trigger the onFOO events
+ old = target[ "on" + type ];
+
+ if ( old ) {
+ target[ "on" + type ] = null;
+ }
+
+ jQuery.event.triggered = true;
+ target[ type ]();
+ }
+
+ // prevent IE from throwing an error for some elements with some event types, see #3533
+ } catch (e) {}
+
+ if ( old ) {
+ target[ "on" + type ] = old;
+ }
+
+ jQuery.event.triggered = false;
+ }
+ }
+ },
+
+ handle: function( event ) {
+ var all, handlers, namespaces, namespace, events;
+
+ event = arguments[0] = jQuery.event.fix( event || window.event );
+ event.currentTarget = this;
+
+ // Namespaced event handlers
+ all = event.type.indexOf(".") < 0 && !event.exclusive;
+
+ if ( !all ) {
+ namespaces = event.type.split(".");
+ event.type = namespaces.shift();
+ namespace = new RegExp("(^|\\.)" + namespaces.slice(0).sort().join("\\.(?:.*\\.)?") + "(\\.|$)");
+ }
+
+ var events = jQuery.data(this, "events"), handlers = events[ event.type ];
+
+ if ( events && handlers ) {
+ // Clone the handlers to prevent manipulation
+ handlers = handlers.slice(0);
+
+ for ( var j = 0, l = handlers.length; j < l; j++ ) {
+ var handleObj = handlers[ j ];
+
+ // Filter the functions by class
+ if ( all || namespace.test( handleObj.namespace ) ) {
+ // Pass in a reference to the handler function itself
+ // So that we can later remove it
+ event.handler = handleObj.handler;
+ event.data = handleObj.data;
+ event.handleObj = handleObj;
+
+ var ret = handleObj.handler.apply( this, arguments );
+
+ if ( ret !== undefined ) {
+ event.result = ret;
+ if ( ret === false ) {
+ event.preventDefault();
+ event.stopPropagation();
+ }
+ }
+
+ if ( event.isImmediatePropagationStopped() ) {
+ break;
+ }
+ }
+ }
+ }
+
+ return event.result;
+ },
+
+ props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
+
+ fix: function( event ) {
+ if ( event[ expando ] ) {
+ return event;
+ }
+
+ // store a copy of the original event object
+ // and "clone" to set read-only properties
+ var originalEvent = event;
+ event = jQuery.Event( originalEvent );
+
+ for ( var i = this.props.length, prop; i; ) {
+ prop = this.props[ --i ];
+ event[ prop ] = originalEvent[ prop ];
+ }
+
+ // Fix target property, if necessary
+ if ( !event.target ) {
+ event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either
+ }
+
+ // check if target is a textnode (safari)
+ if ( event.target.nodeType === 3 ) {
+ event.target = event.target.parentNode;
+ }
+
+ // Add relatedTarget, if necessary
+ if ( !event.relatedTarget && event.fromElement ) {
+ event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement;
+ }
+
+ // Calculate pageX/Y if missing and clientX/Y available
+ if ( event.pageX == null && event.clientX != null ) {
+ var doc = document.documentElement, body = document.body;
+ event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
+ event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0);
+ }
+
+ // Add which for key events
+ if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) ) {
+ event.which = event.charCode || event.keyCode;
+ }
+
+ // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
+ if ( !event.metaKey && event.ctrlKey ) {
+ event.metaKey = event.ctrlKey;
+ }
+
+ // Add which for click: 1 === left; 2 === middle; 3 === right
+ // Note: button is not normalized, so don't use it
+ if ( !event.which && event.button !== undefined ) {
+ event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
+ }
+
+ return event;
+ },
+
+ // Deprecated, use jQuery.guid instead
+ guid: 1E8,
+
+ // Deprecated, use jQuery.proxy instead
+ proxy: jQuery.proxy,
+
+ special: {
+ ready: {
+ // Make sure the ready event is setup
+ setup: jQuery.bindReady,
+ teardown: jQuery.noop
+ },
+
+ live: {
+ add: function( handleObj ) {
+ jQuery.event.add( this, handleObj.origType, jQuery.extend({}, handleObj, {handler: liveHandler}) );
+ },
+
+ remove: function( handleObj ) {
+ var remove = true,
+ type = handleObj.origType.replace(rnamespaces, "");
+
+ jQuery.each( jQuery.data(this, "events").live || [], function() {
+ if ( type === this.origType.replace(rnamespaces, "") ) {
+ remove = false;
+ return false;
+ }
+ });
+
+ if ( remove ) {
+ jQuery.event.remove( this, handleObj.origType, liveHandler );
+ }
+ }
+
+ },
+
+ beforeunload: {
+ setup: function( data, namespaces, eventHandle ) {
+ // We only want to do this special case on windows
+ if ( this.setInterval ) {
+ this.onbeforeunload = eventHandle;
+ }
+
+ return false;
+ },
+ teardown: function( namespaces, eventHandle ) {
+ if ( this.onbeforeunload === eventHandle ) {
+ this.onbeforeunload = null;
+ }
+ }
+ }
+ }
+};
+
+var removeEvent = document.removeEventListener ?
+ function( elem, type, handle ) {
+ elem.removeEventListener( type, handle, false );
+ } :
+ function( elem, type, handle ) {
+ elem.detachEvent( "on" + type, handle );
+ };
+
+jQuery.Event = function( src ) {
+ // Allow instantiation without the 'new' keyword
+ if ( !this.preventDefault ) {
+ return new jQuery.Event( src );
+ }
+
+ // Event object
+ if ( src && src.type ) {
+ this.originalEvent = src;
+ this.type = src.type;
+ // Event type
+ } else {
+ this.type = src;
+ }
+
+ // timeStamp is buggy for some events on Firefox(#3843)
+ // So we won't rely on the native value
+ this.timeStamp = now();
+
+ // Mark it as fixed
+ this[ expando ] = true;
+};
+
+function returnFalse() {
+ return false;
+}
+function returnTrue() {
+ return true;
+}
+
+// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
+// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
+jQuery.Event.prototype = {
+ preventDefault: function() {
+ this.isDefaultPrevented = returnTrue;
+
+ var e = this.originalEvent;
+ if ( !e ) {
+ return;
+ }
+
+ // if preventDefault exists run it on the original event
+ if ( e.preventDefault ) {
+ e.preventDefault();
+ }
+ // otherwise set the returnValue property of the original event to false (IE)
+ e.returnValue = false;
+ },
+ stopPropagation: function() {
+ this.isPropagationStopped = returnTrue;
+
+ var e = this.originalEvent;
+ if ( !e ) {
+ return;
+ }
+ // if stopPropagation exists run it on the original event
+ if ( e.stopPropagation ) {
+ e.stopPropagation();
+ }
+ // otherwise set the cancelBubble property of the original event to true (IE)
+ e.cancelBubble = true;
+ },
+ stopImmediatePropagation: function() {
+ this.isImmediatePropagationStopped = returnTrue;
+ this.stopPropagation();
+ },
+ isDefaultPrevented: returnFalse,
+ isPropagationStopped: returnFalse,
+ isImmediatePropagationStopped: returnFalse
+};
+
+// Checks if an event happened on an element within another element
+// Used in jQuery.event.special.mouseenter and mouseleave handlers
+var withinElement = function( event ) {
+ // Check if mouse(over|out) are still within the same parent element
+ var parent = event.relatedTarget;
+
+ // Firefox sometimes assigns relatedTarget a XUL element
+ // which we cannot access the parentNode property of
+ try {
+ // Traverse up the tree
+ while ( parent && parent !== this ) {
+ parent = parent.parentNode;
+ }
+
+ if ( parent !== this ) {
+ // set the correct event type
+ event.type = event.data;
+
+ // handle event if we actually just moused on to a non sub-element
+ jQuery.event.handle.apply( this, arguments );
+ }
+
+ // assuming we've left the element since we most likely mousedover a xul element
+ } catch(e) { }
+},
+
+// In case of event delegation, we only need to rename the event.type,
+// liveHandler will take care of the rest.
+delegate = function( event ) {
+ event.type = event.data;
+ jQuery.event.handle.apply( this, arguments );
+};
+
+// Create mouseenter and mouseleave events
+jQuery.each({
+ mouseenter: "mouseover",
+ mouseleave: "mouseout"
+}, function( orig, fix ) {
+ jQuery.event.special[ orig ] = {
+ setup: function( data ) {
+ jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig );
+ },
+ teardown: function( data ) {
+ jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement );
+ }
+ };
+});
+
+// submit delegation
+if ( !jQuery.support.submitBubbles ) {
+
+ jQuery.event.special.submit = {
+ setup: function( data, namespaces ) {
+ if ( this.nodeName.toLowerCase() !== "form" ) {
+ jQuery.event.add(this, "click.specialSubmit", function( e ) {
+ var elem = e.target, type = elem.type;
+
+ if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) {
+ return trigger( "submit", this, arguments );
+ }
+ });
+
+ jQuery.event.add(this, "keypress.specialSubmit", function( e ) {
+ var elem = e.target, type = elem.type;
+
+ if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) {
+ return trigger( "submit", this, arguments );
+ }
+ });
+
+ } else {
+ return false;
+ }
+ },
+
+ teardown: function( namespaces ) {
+ jQuery.event.remove( this, ".specialSubmit" );
+ }
+ };
+
+}
+
+// change delegation, happens here so we have bind.
+if ( !jQuery.support.changeBubbles ) {
+
+ var formElems = /textarea|input|select/i,
+
+ changeFilters,
+
+ getVal = function( elem ) {
+ var type = elem.type, val = elem.value;
+
+ if ( type === "radio" || type === "checkbox" ) {
+ val = elem.checked;
+
+ } else if ( type === "select-multiple" ) {
+ val = elem.selectedIndex > -1 ?
+ jQuery.map( elem.options, function( elem ) {
+ return elem.selected;
+ }).join("-") :
+ "";
+
+ } else if ( elem.nodeName.toLowerCase() === "select" ) {
+ val = elem.selectedIndex;
+ }
+
+ return val;
+ },
+
+ testChange = function testChange( e ) {
+ var elem = e.target, data, val;
+
+ if ( !formElems.test( elem.nodeName ) || elem.readOnly ) {
+ return;
+ }
+
+ data = jQuery.data( elem, "_change_data" );
+ val = getVal(elem);
+
+ // the current data will be also retrieved by beforeactivate
+ if ( e.type !== "focusout" || elem.type !== "radio" ) {
+ jQuery.data( elem, "_change_data", val );
+ }
+
+ if ( data === undefined || val === data ) {
+ return;
+ }
+
+ if ( data != null || val ) {
+ e.type = "change";
+ return jQuery.event.trigger( e, arguments[1], elem );
+ }
+ };
+
+ jQuery.event.special.change = {
+ filters: {
+ focusout: testChange,
+
+ click: function( e ) {
+ var elem = e.target, type = elem.type;
+
+ if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) {
+ return testChange.call( this, e );
+ }
+ },
+
+ // Change has to be called before submit
+ // Keydown will be called before keypress, which is used in submit-event delegation
+ keydown: function( e ) {
+ var elem = e.target, type = elem.type;
+
+ if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") ||
+ (e.keyCode === 32 && (type === "checkbox" || type === "radio")) ||
+ type === "select-multiple" ) {
+ return testChange.call( this, e );
+ }
+ },
+
+ // Beforeactivate happens also before the previous element is blurred
+ // with this event you can't trigger a change event, but you can store
+ // information/focus[in] is not needed anymore
+ beforeactivate: function( e ) {
+ var elem = e.target;
+ jQuery.data( elem, "_change_data", getVal(elem) );
+ }
+ },
+
+ setup: function( data, namespaces ) {
+ if ( this.type === "file" ) {
+ return false;
+ }
+
+ for ( var type in changeFilters ) {
+ jQuery.event.add( this, type + ".specialChange", changeFilters[type] );
+ }
+
+ return formElems.test( this.nodeName );
+ },
+
+ teardown: function( namespaces ) {
+ jQuery.event.remove( this, ".specialChange" );
+
+ return formElems.test( this.nodeName );
+ }
+ };
+
+ changeFilters = jQuery.event.special.change.filters;
+}
+
+function trigger( type, elem, args ) {
+ args[0].type = type;
+ return jQuery.event.handle.apply( elem, args );
+}
+
+// Create "bubbling" focus and blur events
+if ( document.addEventListener ) {
+ jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
+ jQuery.event.special[ fix ] = {
+ setup: function() {
+ this.addEventListener( orig, handler, true );
+ },
+ teardown: function() {
+ this.removeEventListener( orig, handler, true );
+ }
+ };
+
+ function handler( e ) {
+ e = jQuery.event.fix( e );
+ e.type = fix;
+ return jQuery.event.handle.call( this, e );
+ }
+ });
+}
+
+jQuery.each(["bind", "one"], function( i, name ) {
+ jQuery.fn[ name ] = function( type, data, fn ) {
+ // Handle object literals
+ if ( typeof type === "object" ) {
+ for ( var key in type ) {
+ this[ name ](key, data, type[key], fn);
+ }
+ return this;
+ }
+
+ if ( jQuery.isFunction( data ) ) {
+ fn = data;
+ data = undefined;
+ }
+
+ var handler = name === "one" ? jQuery.proxy( fn, function( event ) {
+ jQuery( this ).unbind( event, handler );
+ return fn.apply( this, arguments );
+ }) : fn;
+
+ if ( type === "unload" && name !== "one" ) {
+ this.one( type, data, fn );
+
+ } else {
+ for ( var i = 0, l = this.length; i < l; i++ ) {
+ jQuery.event.add( this[i], type, handler, data );
+ }
+ }
+
+ return this;
+ };
+});
+
+jQuery.fn.extend({
+ unbind: function( type, fn ) {
+ // Handle object literals
+ if ( typeof type === "object" && !type.preventDefault ) {
+ for ( var key in type ) {
+ this.unbind(key, type[key]);
+ }
+
+ } else {
+ for ( var i = 0, l = this.length; i < l; i++ ) {
+ jQuery.event.remove( this[i], type, fn );
+ }
+ }
+
+ return this;
+ },
+
+ delegate: function( selector, types, data, fn ) {
+ return this.live( types, data, fn, selector );
+ },
+
+ undelegate: function( selector, types, fn ) {
+ if ( arguments.length === 0 ) {
+ return this.unbind( "live" );
+
+ } else {
+ return this.die( types, null, fn, selector );
+ }
+ },
+
+ trigger: function( type, data ) {
+ return this.each(function() {
+ jQuery.event.trigger( type, data, this );
+ });
+ },
+
+ triggerHandler: function( type, data ) {
+ if ( this[0] ) {
+ var event = jQuery.Event( type );
+ event.preventDefault();
+ event.stopPropagation();
+ jQuery.event.trigger( event, data, this[0] );
+ return event.result;
+ }
+ },
+
+ toggle: function( fn ) {
+ // Save reference to arguments for access in closure
+ var args = arguments, i = 1;
+
+ // link all the functions, so any of them can unbind this click handler
+ while ( i < args.length ) {
+ jQuery.proxy( fn, args[ i++ ] );
+ }
+
+ return this.click( jQuery.proxy( fn, function( event ) {
+ // Figure out which function to execute
+ var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i;
+ jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 );
+
+ // Make sure that clicks stop
+ event.preventDefault();
+
+ // and execute the function
+ return args[ lastToggle ].apply( this, arguments ) || false;
+ }));
+ },
+
+ hover: function( fnOver, fnOut ) {
+ return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
+ }
+});
+
+var liveMap = {
+ focus: "focusin",
+ blur: "focusout",
+ mouseenter: "mouseover",
+ mouseleave: "mouseout"
+};
+
+jQuery.each(["live", "die"], function( i, name ) {
+ jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) {
+ var type, i = 0, match, namespaces, preType,
+ selector = origSelector || this.selector,
+ context = origSelector ? this : jQuery( this.context );
+
+ if ( jQuery.isFunction( data ) ) {
+ fn = data;
+ data = undefined;
+ }
+
+ types = (types || "").split(" ");
+
+ while ( (type = types[ i++ ]) != null ) {
+ match = rnamespaces.exec( type );
+ namespaces = "";
+
+ if ( match ) {
+ namespaces = match[0];
+ type = type.replace( rnamespaces, "" );
+ }
+
+ if ( type === "hover" ) {
+ types.push( "mouseenter" + namespaces, "mouseleave" + namespaces );
+ continue;
+ }
+
+ preType = type;
+
+ if ( type === "focus" || type === "blur" ) {
+ types.push( liveMap[ type ] + namespaces );
+ type = type + namespaces;
+
+ } else {
+ type = (liveMap[ type ] || type) + namespaces;
+ }
+
+ if ( name === "live" ) {
+ // bind live handler
+ context.each(function(){
+ jQuery.event.add( this, liveConvert( type, selector ),
+ { data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } );
+ });
+
+ } else {
+ // unbind live handler
+ context.unbind( liveConvert( type, selector ), fn );
+ }
+ }
+
+ return this;
+ }
+});
+
+function liveHandler( event ) {
+ var stop, elems = [], selectors = [], args = arguments,
+ related, match, handleObj, elem, j, i, l, data,
+ events = jQuery.data( this, "events" );
+
+ // Make sure we avoid non-left-click bubbling in Firefox (#3861)
+ if ( event.liveFired === this || !events || !events.live || event.button && event.type === "click" ) {
+ return;
+ }
+
+ event.liveFired = this;
+
+ var live = events.live.slice(0);
+
+ for ( j = 0; j < live.length; j++ ) {
+ handleObj = live[j];
+
+ if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) {
+ selectors.push( handleObj.selector );
+
+ } else {
+ live.splice( j--, 1 );
+ }
+ }
+
+ match = jQuery( event.target ).closest( selectors, event.currentTarget );
+
+ for ( i = 0, l = match.length; i < l; i++ ) {
+ for ( j = 0; j < live.length; j++ ) {
+ handleObj = live[j];
+
+ if ( match[i].selector === handleObj.selector ) {
+ elem = match[i].elem;
+ related = null;
+
+ // Those two events require additional checking
+ if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) {
+ related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0];
+ }
+
+ if ( !related || related !== elem ) {
+ elems.push({ elem: elem, handleObj: handleObj });
+ }
+ }
+ }
+ }
+
+ for ( i = 0, l = elems.length; i < l; i++ ) {
+ match = elems[i];
+ event.currentTarget = match.elem;
+ event.data = match.handleObj.data;
+ event.handleObj = match.handleObj;
+
+ if ( match.handleObj.origHandler.apply( match.elem, args ) === false ) {
+ stop = false;
+ break;
+ }
+ }
+
+ return stop;
+}
+
+function liveConvert( type, selector ) {
+ return "live." + (type && type !== "*" ? type + "." : "") + selector.replace(/\./g, "`").replace(/ /g, "&");
+}
+
+jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
+ "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
+ "change select submit keydown keypress keyup error").split(" "), function( i, name ) {
+
+ // Handle event binding
+ jQuery.fn[ name ] = function( fn ) {
+ return fn ? this.bind( name, fn ) : this.trigger( name );
+ };
+
+ if ( jQuery.attrFn ) {
+ jQuery.attrFn[ name ] = true;
+ }
+});
+
+// Prevent memory leaks in IE
+// Window isn't included so as not to unbind existing unload events
+// More info:
+// - http://isaacschlueter.com/2006/10/msie-memory-leaks/
+if ( window.attachEvent && !window.addEventListener ) {
+ window.attachEvent("onunload", function() {
+ for ( var id in jQuery.cache ) {
+ if ( jQuery.cache[ id ].handle ) {
+ // Try/Catch is to handle iframes being unloaded, see #4280
+ try {
+ jQuery.event.remove( jQuery.cache[ id ].handle.elem );
+ } catch(e) {}
+ }
+ }
+ });
+}
+/*!
+ * Sizzle CSS Selector Engine - v1.0
+ * Copyright 2009, The Dojo Foundation
+ * Released under the MIT, BSD, and GPL Licenses.
+ * More information: http://sizzlejs.com/
+ */
+(function(){
+
+var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
+ done = 0,
+ toString = Object.prototype.toString,
+ hasDuplicate = false,
+ baseHasDuplicate = true;
+
+// Here we check if the JavaScript engine is using some sort of
+// optimization where it does not always call our comparision
+// function. If that is the case, discard the hasDuplicate value.
+// Thus far that includes Google Chrome.
+[0, 0].sort(function(){
+ baseHasDuplicate = false;
+ return 0;
+});
+
+var Sizzle = function(selector, context, results, seed) {
+ results = results || [];
+ var origContext = context = context || document;
+
+ if ( context.nodeType !== 1 && context.nodeType !== 9 ) {
+ return [];
+ }
+
+ if ( !selector || typeof selector !== "string" ) {
+ return results;
+ }
+
+ var parts = [], m, set, checkSet, extra, prune = true, contextXML = isXML(context),
+ soFar = selector;
+
+ // Reset the position of the chunker regexp (start from head)
+ while ( (chunker.exec(""), m = chunker.exec(soFar)) !== null ) {
+ soFar = m[3];
+
+ parts.push( m[1] );
+
+ if ( m[2] ) {
+ extra = m[3];
+ break;
+ }
+ }
+
+ if ( parts.length > 1 && origPOS.exec( selector ) ) {
+ if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
+ set = posProcess( parts[0] + parts[1], context );
+ } else {
+ set = Expr.relative[ parts[0] ] ?
+ [ context ] :
+ Sizzle( parts.shift(), context );
+
+ while ( parts.length ) {
+ selector = parts.shift();
+
+ if ( Expr.relative[ selector ] ) {
+ selector += parts.shift();
+ }
+
+ set = posProcess( selector, set );
+ }
+ }
+ } else {
+ // Take a shortcut and set the context if the root selector is an ID
+ // (but not if it'll be faster if the inner selector is an ID)
+ if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&
+ Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {
+ var ret = Sizzle.find( parts.shift(), context, contextXML );
+ context = ret.expr ? Sizzle.filter( ret.expr, ret.set )[0] : ret.set[0];
+ }
+
+ if ( context ) {
+ var ret = seed ?
+ { expr: parts.pop(), set: makeArray(seed) } :
+ Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML );
+ set = ret.expr ? Sizzle.filter( ret.expr, ret.set ) : ret.set;
+
+ if ( parts.length > 0 ) {
+ checkSet = makeArray(set);
+ } else {
+ prune = false;
+ }
+
+ while ( parts.length ) {
+ var cur = parts.pop(), pop = cur;
+
+ if ( !Expr.relative[ cur ] ) {
+ cur = "";
+ } else {
+ pop = parts.pop();
+ }
+
+ if ( pop == null ) {
+ pop = context;
+ }
+
+ Expr.relative[ cur ]( checkSet, pop, contextXML );
+ }
+ } else {
+ checkSet = parts = [];
+ }
+ }
+
+ if ( !checkSet ) {
+ checkSet = set;
+ }
+
+ if ( !checkSet ) {
+ Sizzle.error( cur || selector );
+ }
+
+ if ( toString.call(checkSet) === "[object Array]" ) {
+ if ( !prune ) {
+ results.push.apply( results, checkSet );
+ } else if ( context && context.nodeType === 1 ) {
+ for ( var i = 0; checkSet[i] != null; i++ ) {
+ if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) {
+ results.push( set[i] );
+ }
+ }
+ } else {
+ for ( var i = 0; checkSet[i] != null; i++ ) {
+ if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
+ results.push( set[i] );
+ }
+ }
+ }
+ } else {
+ makeArray( checkSet, results );
+ }
+
+ if ( extra ) {
+ Sizzle( extra, origContext, results, seed );
+ Sizzle.uniqueSort( results );
+ }
+
+ return results;
+};
+
+Sizzle.uniqueSort = function(results){
+ if ( sortOrder ) {
+ hasDuplicate = baseHasDuplicate;
+ results.sort(sortOrder);
+
+ if ( hasDuplicate ) {
+ for ( var i = 1; i < results.length; i++ ) {
+ if ( results[i] === results[i-1] ) {
+ results.splice(i--, 1);
+ }
+ }
+ }
+ }
+
+ return results;
+};
+
+Sizzle.matches = function(expr, set){
+ return Sizzle(expr, null, null, set);
+};
+
+Sizzle.find = function(expr, context, isXML){
+ var set, match;
+
+ if ( !expr ) {
+ return [];
+ }
+
+ for ( var i = 0, l = Expr.order.length; i < l; i++ ) {
+ var type = Expr.order[i], match;
+
+ if ( (match = Expr.leftMatch[ type ].exec( expr )) ) {
+ var left = match[1];
+ match.splice(1,1);
+
+ if ( left.substr( left.length - 1 ) !== "\\" ) {
+ match[1] = (match[1] || "").replace(/\\/g, "");
+ set = Expr.find[ type ]( match, context, isXML );
+ if ( set != null ) {
+ expr = expr.replace( Expr.match[ type ], "" );
+ break;
+ }
+ }
+ }
+ }
+
+ if ( !set ) {
+ set = context.getElementsByTagName("*");
+ }
+
+ return {set: set, expr: expr};
+};
+
+Sizzle.filter = function(expr, set, inplace, not){
+ var old = expr, result = [], curLoop = set, match, anyFound,
+ isXMLFilter = set && set[0] && isXML(set[0]);
+
+ while ( expr && set.length ) {
+ for ( var type in Expr.filter ) {
+ if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {
+ var filter = Expr.filter[ type ], found, item, left = match[1];
+ anyFound = false;
+
+ match.splice(1,1);
+
+ if ( left.substr( left.length - 1 ) === "\\" ) {
+ continue;
+ }
+
+ if ( curLoop === result ) {
+ result = [];
+ }
+
+ if ( Expr.preFilter[ type ] ) {
+ match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );
+
+ if ( !match ) {
+ anyFound = found = true;
+ } else if ( match === true ) {
+ continue;
+ }
+ }
+
+ if ( match ) {
+ for ( var i = 0; (item = curLoop[i]) != null; i++ ) {
+ if ( item ) {
+ found = filter( item, match, i, curLoop );
+ var pass = not ^ !!found;
+
+ if ( inplace && found != null ) {
+ if ( pass ) {
+ anyFound = true;
+ } else {
+ curLoop[i] = false;
+ }
+ } else if ( pass ) {
+ result.push( item );
+ anyFound = true;
+ }
+ }
+ }
+ }
+
+ if ( found !== undefined ) {
+ if ( !inplace ) {
+ curLoop = result;
+ }
+
+ expr = expr.replace( Expr.match[ type ], "" );
+
+ if ( !anyFound ) {
+ return [];
+ }
+
+ break;
+ }
+ }
+ }
+
+ // Improper expression
+ if ( expr === old ) {
+ if ( anyFound == null ) {
+ Sizzle.error( expr );
+ } else {
+ break;
+ }
+ }
+
+ old = expr;
+ }
+
+ return curLoop;
+};
+
+Sizzle.error = function( msg ) {
+ throw "Syntax error, unrecognized expression: " + msg;
+};
+
+var Expr = Sizzle.selectors = {
+ order: [ "ID", "NAME", "TAG" ],
+ match: {
+ ID: /#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
+ CLASS: /\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
+ NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,
+ ATTR: /\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,
+ TAG: /^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,
+ CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,
+ POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,
+ PSEUDO: /:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/
+ },
+ leftMatch: {},
+ attrMap: {
+ "class": "className",
+ "for": "htmlFor"
+ },
+ attrHandle: {
+ href: function(elem){
+ return elem.getAttribute("href");
+ }
+ },
+ relative: {
+ "+": function(checkSet, part){
+ var isPartStr = typeof part === "string",
+ isTag = isPartStr && !/\W/.test(part),
+ isPartStrNotTag = isPartStr && !isTag;
+
+ if ( isTag ) {
+ part = part.toLowerCase();
+ }
+
+ for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
+ if ( (elem = checkSet[i]) ) {
+ while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}
+
+ checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?
+ elem || false :
+ elem === part;
+ }
+ }
+
+ if ( isPartStrNotTag ) {
+ Sizzle.filter( part, checkSet, true );
+ }
+ },
+ ">": function(checkSet, part){
+ var isPartStr = typeof part === "string";
+
+ if ( isPartStr && !/\W/.test(part) ) {
+ part = part.toLowerCase();
+
+ for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+ var elem = checkSet[i];
+ if ( elem ) {
+ var parent = elem.parentNode;
+ checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;
+ }
+ }
+ } else {
+ for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+ var elem = checkSet[i];
+ if ( elem ) {
+ checkSet[i] = isPartStr ?
+ elem.parentNode :
+ elem.parentNode === part;
+ }
+ }
+
+ if ( isPartStr ) {
+ Sizzle.filter( part, checkSet, true );
+ }
+ }
+ },
+ "": function(checkSet, part, isXML){
+ var doneName = done++, checkFn = dirCheck;
+
+ if ( typeof part === "string" && !/\W/.test(part) ) {
+ var nodeCheck = part = part.toLowerCase();
+ checkFn = dirNodeCheck;
+ }
+
+ checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML);
+ },
+ "~": function(checkSet, part, isXML){
+ var doneName = done++, checkFn = dirCheck;
+
+ if ( typeof part === "string" && !/\W/.test(part) ) {
+ var nodeCheck = part = part.toLowerCase();
+ checkFn = dirNodeCheck;
+ }
+
+ checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML);
+ }
+ },
+ find: {
+ ID: function(match, context, isXML){
+ if ( typeof context.getElementById !== "undefined" && !isXML ) {
+ var m = context.getElementById(match[1]);
+ return m ? [m] : [];
+ }
+ },
+ NAME: function(match, context){
+ if ( typeof context.getElementsByName !== "undefined" ) {
+ var ret = [], results = context.getElementsByName(match[1]);
+
+ for ( var i = 0, l = results.length; i < l; i++ ) {
+ if ( results[i].getAttribute("name") === match[1] ) {
+ ret.push( results[i] );
+ }
+ }
+
+ return ret.length === 0 ? null : ret;
+ }
+ },
+ TAG: function(match, context){
+ return context.getElementsByTagName(match[1]);
+ }
+ },
+ preFilter: {
+ CLASS: function(match, curLoop, inplace, result, not, isXML){
+ match = " " + match[1].replace(/\\/g, "") + " ";
+
+ if ( isXML ) {
+ return match;
+ }
+
+ for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
+ if ( elem ) {
+ if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n]/g, " ").indexOf(match) >= 0) ) {
+ if ( !inplace ) {
+ result.push( elem );
+ }
+ } else if ( inplace ) {
+ curLoop[i] = false;
+ }
+ }
+ }
+
+ return false;
+ },
+ ID: function(match){
+ return match[1].replace(/\\/g, "");
+ },
+ TAG: function(match, curLoop){
+ return match[1].toLowerCase();
+ },
+ CHILD: function(match){
+ if ( match[1] === "nth" ) {
+ // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
+ var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
+ match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" ||
+ !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);
+
+ // calculate the numbers (first)n+(last) including if they are negative
+ match[2] = (test[1] + (test[2] || 1)) - 0;
+ match[3] = test[3] - 0;
+ }
+
+ // TODO: Move to normal caching system
+ match[0] = done++;
+
+ return match;
+ },
+ ATTR: function(match, curLoop, inplace, result, not, isXML){
+ var name = match[1].replace(/\\/g, "");
+
+ if ( !isXML && Expr.attrMap[name] ) {
+ match[1] = Expr.attrMap[name];
+ }
+
+ if ( match[2] === "~=" ) {
+ match[4] = " " + match[4] + " ";
+ }
+
+ return match;
+ },
+ PSEUDO: function(match, curLoop, inplace, result, not){
+ if ( match[1] === "not" ) {
+ // If we're dealing with a complex expression, or a simple one
+ if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) {
+ match[3] = Sizzle(match[3], null, null, curLoop);
+ } else {
+ var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
+ if ( !inplace ) {
+ result.push.apply( result, ret );
+ }
+ return false;
+ }
+ } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
+ return true;
+ }
+
+ return match;
+ },
+ POS: function(match){
+ match.unshift( true );
+ return match;
+ }
+ },
+ filters: {
+ enabled: function(elem){
+ return elem.disabled === false && elem.type !== "hidden";
+ },
+ disabled: function(elem){
+ return elem.disabled === true;
+ },
+ checked: function(elem){
+ return elem.checked === true;
+ },
+ selected: function(elem){
+ // Accessing this property makes selected-by-default
+ // options in Safari work properly
+ elem.parentNode.selectedIndex;
+ return elem.selected === true;
+ },
+ parent: function(elem){
+ return !!elem.firstChild;
+ },
+ empty: function(elem){
+ return !elem.firstChild;
+ },
+ has: function(elem, i, match){
+ return !!Sizzle( match[3], elem ).length;
+ },
+ header: function(elem){
+ return /h\d/i.test( elem.nodeName );
+ },
+ text: function(elem){
+ return "text" === elem.type;
+ },
+ radio: function(elem){
+ return "radio" === elem.type;
+ },
+ checkbox: function(elem){
+ return "checkbox" === elem.type;
+ },
+ file: function(elem){
+ return "file" === elem.type;
+ },
+ password: function(elem){
+ return "password" === elem.type;
+ },
+ submit: function(elem){
+ return "submit" === elem.type;
+ },
+ image: function(elem){
+ return "image" === elem.type;
+ },
+ reset: function(elem){
+ return "reset" === elem.type;
+ },
+ button: function(elem){
+ return "button" === elem.type || elem.nodeName.toLowerCase() === "button";
+ },
+ input: function(elem){
+ return /input|select|textarea|button/i.test(elem.nodeName);
+ }
+ },
+ setFilters: {
+ first: function(elem, i){
+ return i === 0;
+ },
+ last: function(elem, i, match, array){
+ return i === array.length - 1;
+ },
+ even: function(elem, i){
+ return i % 2 === 0;
+ },
+ odd: function(elem, i){
+ return i % 2 === 1;
+ },
+ lt: function(elem, i, match){
+ return i < match[3] - 0;
+ },
+ gt: function(elem, i, match){
+ return i > match[3] - 0;
+ },
+ nth: function(elem, i, match){
+ return match[3] - 0 === i;
+ },
+ eq: function(elem, i, match){
+ return match[3] - 0 === i;
+ }
+ },
+ filter: {
+ PSEUDO: function(elem, match, i, array){
+ var name = match[1], filter = Expr.filters[ name ];
+
+ if ( filter ) {
+ return filter( elem, i, match, array );
+ } else if ( name === "contains" ) {
+ return (elem.textContent || elem.innerText || getText([ elem ]) || "").indexOf(match[3]) >= 0;
+ } else if ( name === "not" ) {
+ var not = match[3];
+
+ for ( var i = 0, l = not.length; i < l; i++ ) {
+ if ( not[i] === elem ) {
+ return false;
+ }
+ }
+
+ return true;
+ } else {
+ Sizzle.error( "Syntax error, unrecognized expression: " + name );
+ }
+ },
+ CHILD: function(elem, match){
+ var type = match[1], node = elem;
+ switch (type) {
+ case 'only':
+ case 'first':
+ while ( (node = node.previousSibling) ) {
+ if ( node.nodeType === 1 ) {
+ return false;
+ }
+ }
+ if ( type === "first" ) {
+ return true;
+ }
+ node = elem;
+ case 'last':
+ while ( (node = node.nextSibling) ) {
+ if ( node.nodeType === 1 ) {
+ return false;
+ }
+ }
+ return true;
+ case 'nth':
+ var first = match[2], last = match[3];
+
+ if ( first === 1 && last === 0 ) {
+ return true;
+ }
+
+ var doneName = match[0],
+ parent = elem.parentNode;
+
+ if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) {
+ var count = 0;
+ for ( node = parent.firstChild; node; node = node.nextSibling ) {
+ if ( node.nodeType === 1 ) {
+ node.nodeIndex = ++count;
+ }
+ }
+ parent.sizcache = doneName;
+ }
+
+ var diff = elem.nodeIndex - last;
+ if ( first === 0 ) {
+ return diff === 0;
+ } else {
+ return ( diff % first === 0 && diff / first >= 0 );
+ }
+ }
+ },
+ ID: function(elem, match){
+ return elem.nodeType === 1 && elem.getAttribute("id") === match;
+ },
+ TAG: function(elem, match){
+ return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match;
+ },
+ CLASS: function(elem, match){
+ return (" " + (elem.className || elem.getAttribute("class")) + " ")
+ .indexOf( match ) > -1;
+ },
+ ATTR: function(elem, match){
+ var name = match[1],
+ result = Expr.attrHandle[ name ] ?
+ Expr.attrHandle[ name ]( elem ) :
+ elem[ name ] != null ?
+ elem[ name ] :
+ elem.getAttribute( name ),
+ value = result + "",
+ type = match[2],
+ check = match[4];
+
+ return result == null ?
+ type === "!=" :
+ type === "=" ?
+ value === check :
+ type === "*=" ?
+ value.indexOf(check) >= 0 :
+ type === "~=" ?
+ (" " + value + " ").indexOf(check) >= 0 :
+ !check ?
+ value && result !== false :
+ type === "!=" ?
+ value !== check :
+ type === "^=" ?
+ value.indexOf(check) === 0 :
+ type === "$=" ?
+ value.substr(value.length - check.length) === check :
+ type === "|=" ?
+ value === check || value.substr(0, check.length + 1) === check + "-" :
+ false;
+ },
+ POS: function(elem, match, i, array){
+ var name = match[2], filter = Expr.setFilters[ name ];
+
+ if ( filter ) {
+ return filter( elem, i, match, array );
+ }
+ }
+ }
+};
+
+var origPOS = Expr.match.POS;
+
+for ( var type in Expr.match ) {
+ Expr.match[ type ] = new RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source );
+ Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, function(all, num){
+ return "\\" + (num - 0 + 1);
+ }));
+}
+
+var makeArray = function(array, results) {
+ array = Array.prototype.slice.call( array, 0 );
+
+ if ( results ) {
+ results.push.apply( results, array );
+ return results;
+ }
+
+ return array;
+};
+
+// Perform a simple check to determine if the browser is capable of
+// converting a NodeList to an array using builtin methods.
+// Also verifies that the returned array holds DOM nodes
+// (which is not the case in the Blackberry browser)
+try {
+ Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;
+
+// Provide a fallback method if it does not work
+} catch(e){
+ makeArray = function(array, results) {
+ var ret = results || [];
+
+ if ( toString.call(array) === "[object Array]" ) {
+ Array.prototype.push.apply( ret, array );
+ } else {
+ if ( typeof array.length === "number" ) {
+ for ( var i = 0, l = array.length; i < l; i++ ) {
+ ret.push( array[i] );
+ }
+ } else {
+ for ( var i = 0; array[i]; i++ ) {
+ ret.push( array[i] );
+ }
+ }
+ }
+
+ return ret;
+ };
+}
+
+var sortOrder;
+
+if ( document.documentElement.compareDocumentPosition ) {
+ sortOrder = function( a, b ) {
+ if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {
+ if ( a == b ) {
+ hasDuplicate = true;
+ }
+ return a.compareDocumentPosition ? -1 : 1;
+ }
+
+ var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1;
+ if ( ret === 0 ) {
+ hasDuplicate = true;
+ }
+ return ret;
+ };
+} else if ( "sourceIndex" in document.documentElement ) {
+ sortOrder = function( a, b ) {
+ if ( !a.sourceIndex || !b.sourceIndex ) {
+ if ( a == b ) {
+ hasDuplicate = true;
+ }
+ return a.sourceIndex ? -1 : 1;
+ }
+
+ var ret = a.sourceIndex - b.sourceIndex;
+ if ( ret === 0 ) {
+ hasDuplicate = true;
+ }
+ return ret;
+ };
+} else if ( document.createRange ) {
+ sortOrder = function( a, b ) {
+ if ( !a.ownerDocument || !b.ownerDocument ) {
+ if ( a == b ) {
+ hasDuplicate = true;
+ }
+ return a.ownerDocument ? -1 : 1;
+ }
+
+ var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange();
+ aRange.setStart(a, 0);
+ aRange.setEnd(a, 0);
+ bRange.setStart(b, 0);
+ bRange.setEnd(b, 0);
+ var ret = aRange.compareBoundaryPoints(Range.START_TO_END, bRange);
+ if ( ret === 0 ) {
+ hasDuplicate = true;
+ }
+ return ret;
+ };
+}
+
+// Utility function for retreiving the text value of an array of DOM nodes
+function getText( elems ) {
+ var ret = "", elem;
+
+ for ( var i = 0; elems[i]; i++ ) {
+ elem = elems[i];
+
+ // Get the text from text nodes and CDATA nodes
+ if ( elem.nodeType === 3 || elem.nodeType === 4 ) {
+ ret += elem.nodeValue;
+
+ // Traverse everything else, except comment nodes
+ } else if ( elem.nodeType !== 8 ) {
+ ret += getText( elem.childNodes );
+ }
+ }
+
+ return ret;
+}
+
+// Check to see if the browser returns elements by name when
+// querying by getElementById (and provide a workaround)
+(function(){
+ // We're going to inject a fake input element with a specified name
+ var form = document.createElement("div"),
+ id = "script" + (new Date).getTime();
+ form.innerHTML = "<a name='" + id + "'/>";
+
+ // Inject it into the root element, check its status, and remove it quickly
+ var root = document.documentElement;
+ root.insertBefore( form, root.firstChild );
+
+ // The workaround has to do additional checks after a getElementById
+ // Which slows things down for other browsers (hence the branching)
+ if ( document.getElementById( id ) ) {
+ Expr.find.ID = function(match, context, isXML){
+ if ( typeof context.getElementById !== "undefined" && !isXML ) {
+ var m = context.getElementById(match[1]);
+ return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : [];
+ }
+ };
+
+ Expr.filter.ID = function(elem, match){
+ var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
+ return elem.nodeType === 1 && node && node.nodeValue === match;
+ };
+ }
+
+ root.removeChild( form );
+ root = form = null; // release memory in IE
+})();
+
+(function(){
+ // Check to see if the browser returns only elements
+ // when doing getElementsByTagName("*")
+
+ // Create a fake element
+ var div = document.createElement("div");
+ div.appendChild( document.createComment("") );
+
+ // Make sure no comments are found
+ if ( div.getElementsByTagName("*").length > 0 ) {
+ Expr.find.TAG = function(match, context){
+ var results = context.getElementsByTagName(match[1]);
+
+ // Filter out possible comments
+ if ( match[1] === "*" ) {
+ var tmp = [];
+
+ for ( var i = 0; results[i]; i++ ) {
+ if ( results[i].nodeType === 1 ) {
+ tmp.push( results[i] );
+ }
+ }
+
+ results = tmp;
+ }
+
+ return results;
+ };
+ }
+
+ // Check to see if an attribute returns normalized href attributes
+ div.innerHTML = "<a href='#'></a>";
+ if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
+ div.firstChild.getAttribute("href") !== "#" ) {
+ Expr.attrHandle.href = function(elem){
+ return elem.getAttribute("href", 2);
+ };
+ }
+
+ div = null; // release memory in IE
+})();
+
+if ( document.querySelectorAll ) {
+ (function(){
+ var oldSizzle = Sizzle, div = document.createElement("div");
+ div.innerHTML = "<p class='TEST'></p>";
+
+ // Safari can't handle uppercase or unicode characters when
+ // in quirks mode.
+ if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
+ return;
+ }
+
+ Sizzle = function(query, context, extra, seed){
+ context = context || document;
+
+ // Only use querySelectorAll on non-XML documents
+ // (ID selectors don't work in non-HTML documents)
+ if ( !seed && context.nodeType === 9 && !isXML(context) ) {
+ try {
+ return makeArray( context.querySelectorAll(query), extra );
+ } catch(e){}
+ }
+
+ return oldSizzle(query, context, extra, seed);
+ };
+
+ for ( var prop in oldSizzle ) {
+ Sizzle[ prop ] = oldSizzle[ prop ];
+ }
+
+ div = null; // release memory in IE
+ })();
+}
+
+(function(){
+ var div = document.createElement("div");
+
+ div.innerHTML = "<div class='test e'></div><div class='test'></div>";
+
+ // Opera can't find a second classname (in 9.6)
+ // Also, make sure that getElementsByClassName actually exists
+ if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) {
+ return;
+ }
+
+ // Safari caches class attributes, doesn't catch changes (in 3.2)
+ div.lastChild.className = "e";
+
+ if ( div.getElementsByClassName("e").length === 1 ) {
+ return;
+ }
+
+ Expr.order.splice(1, 0, "CLASS");
+ Expr.find.CLASS = function(match, context, isXML) {
+ if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
+ return context.getElementsByClassName(match[1]);
+ }
+ };
+
+ div = null; // release memory in IE
+})();
+
+function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
+ for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+ var elem = checkSet[i];
+ if ( elem ) {
+ elem = elem[dir];
+ var match = false;
+
+ while ( elem ) {
+ if ( elem.sizcache === doneName ) {
+ match = checkSet[elem.sizset];
+ break;
+ }
+
+ if ( elem.nodeType === 1 && !isXML ){
+ elem.sizcache = doneName;
+ elem.sizset = i;
+ }
+
+ if ( elem.nodeName.toLowerCase() === cur ) {
+ match = elem;
+ break;
+ }
+
+ elem = elem[dir];
+ }
+
+ checkSet[i] = match;
+ }
+ }
+}
+
+function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
+ for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+ var elem = checkSet[i];
+ if ( elem ) {
+ elem = elem[dir];
+ var match = false;
+
+ while ( elem ) {
+ if ( elem.sizcache === doneName ) {
+ match = checkSet[elem.sizset];
+ break;
+ }
+
+ if ( elem.nodeType === 1 ) {
+ if ( !isXML ) {
+ elem.sizcache = doneName;
+ elem.sizset = i;
+ }
+ if ( typeof cur !== "string" ) {
+ if ( elem === cur ) {
+ match = true;
+ break;
+ }
+
+ } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
+ match = elem;
+ break;
+ }
+ }
+
+ elem = elem[dir];
+ }
+
+ checkSet[i] = match;
+ }
+ }
+}
+
+var contains = document.compareDocumentPosition ? function(a, b){
+ return !!(a.compareDocumentPosition(b) & 16);
+} : function(a, b){
+ return a !== b && (a.contains ? a.contains(b) : true);
+};
+
+var isXML = function(elem){
+ // documentElement is verified for cases where it doesn't yet exist
+ // (such as loading iframes in IE - #4833)
+ var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;
+ return documentElement ? documentElement.nodeName !== "HTML" : false;
+};
+
+var posProcess = function(selector, context){
+ var tmpSet = [], later = "", match,
+ root = context.nodeType ? [context] : context;
+
+ // Position selectors must be done after the filter
+ // And so must :not(positional) so we move all PSEUDOs to the end
+ while ( (match = Expr.match.PSEUDO.exec( selector )) ) {
+ later += match[0];
+ selector = selector.replace( Expr.match.PSEUDO, "" );
+ }
+
+ selector = Expr.relative[selector] ? selector + "*" : selector;
+
+ for ( var i = 0, l = root.length; i < l; i++ ) {
+ Sizzle( selector, root[i], tmpSet );
+ }
+
+ return Sizzle.filter( later, tmpSet );
+};
+
+// EXPOSE
+jQuery.find = Sizzle;
+jQuery.expr = Sizzle.selectors;
+jQuery.expr[":"] = jQuery.expr.filters;
+jQuery.unique = Sizzle.uniqueSort;
+jQuery.text = getText;
+jQuery.isXMLDoc = isXML;
+jQuery.contains = contains;
+
+return;
+
+window.Sizzle = Sizzle;
+
+})();
+var runtil = /Until$/,
+ rparentsprev = /^(?:parents|prevUntil|prevAll)/,
+ // Note: This RegExp should be improved, or likely pulled from Sizzle
+ rmultiselector = /,/,
+ slice = Array.prototype.slice;
+
+// Implement the identical functionality for filter and not
+var winnow = function( elements, qualifier, keep ) {
+ if ( jQuery.isFunction( qualifier ) ) {
+ return jQuery.grep(elements, function( elem, i ) {
+ return !!qualifier.call( elem, i, elem ) === keep;
+ });
+
+ } else if ( qualifier.nodeType ) {
+ return jQuery.grep(elements, function( elem, i ) {
+ return (elem === qualifier) === keep;
+ });
+
+ } else if ( typeof qualifier === "string" ) {
+ var filtered = jQuery.grep(elements, function( elem ) {
+ return elem.nodeType === 1;
+ });
+
+ if ( isSimple.test( qualifier ) ) {
+ return jQuery.filter(qualifier, filtered, !keep);
+ } else {
+ qualifier = jQuery.filter( qualifier, filtered );
+ }
+ }
+
+ return jQuery.grep(elements, function( elem, i ) {
+ return (jQuery.inArray( elem, qualifier ) >= 0) === keep;
+ });
+};
+
+jQuery.fn.extend({
+ find: function( selector ) {
+ var ret = this.pushStack( "", "find", selector ), length = 0;
+
+ for ( var i = 0, l = this.length; i < l; i++ ) {
+ length = ret.length;
+ jQuery.find( selector, this[i], ret );
+
+ if ( i > 0 ) {
+ // Make sure that the results are unique
+ for ( var n = length; n < ret.length; n++ ) {
+ for ( var r = 0; r < length; r++ ) {
+ if ( ret[r] === ret[n] ) {
+ ret.splice(n--, 1);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ return ret;
+ },
+
+ has: function( target ) {
+ var targets = jQuery( target );
+ return this.filter(function() {
+ for ( var i = 0, l = targets.length; i < l; i++ ) {
+ if ( jQuery.contains( this, targets[i] ) ) {
+ return true;
+ }
+ }
+ });
+ },
+
+ not: function( selector ) {
+ return this.pushStack( winnow(this, selector, false), "not", selector);
+ },
+
+ filter: function( selector ) {
+ return this.pushStack( winnow(this, selector, true), "filter", selector );
+ },
+
+ is: function( selector ) {
+ return !!selector && jQuery.filter( selector, this ).length > 0;
+ },
+
+ closest: function( selectors, context ) {
+ if ( jQuery.isArray( selectors ) ) {
+ var ret = [], cur = this[0], match, matches = {}, selector;
+
+ if ( cur && selectors.length ) {
+ for ( var i = 0, l = selectors.length; i < l; i++ ) {
+ selector = selectors[i];
+
+ if ( !matches[selector] ) {
+ matches[selector] = jQuery.expr.match.POS.test( selector ) ?
+ jQuery( selector, context || this.context ) :
+ selector;
+ }
+ }
+
+ while ( cur && cur.ownerDocument && cur !== context ) {
+ for ( selector in matches ) {
+ match = matches[selector];
+
+ if ( match.jquery ? match.index(cur) > -1 : jQuery(cur).is(match) ) {
+ ret.push({ selector: selector, elem: cur });
+ delete matches[selector];
+ }
+ }
+ cur = cur.parentNode;
+ }
+ }
+
+ return ret;
+ }
+
+ var pos = jQuery.expr.match.POS.test( selectors ) ?
+ jQuery( selectors, context || this.context ) : null;
+
+ return this.map(function( i, cur ) {
+ while ( cur && cur.ownerDocument && cur !== context ) {
+ if ( pos ? pos.index(cur) > -1 : jQuery(cur).is(selectors) ) {
+ return cur;
+ }
+ cur = cur.parentNode;
+ }
+ return null;
+ });
+ },
+
+ // Determine the position of an element within
+ // the matched set of elements
+ index: function( elem ) {
+ if ( !elem || typeof elem === "string" ) {
+ return jQuery.inArray( this[0],
+ // If it receives a string, the selector is used
+ // If it receives nothing, the siblings are used
+ elem ? jQuery( elem ) : this.parent().children() );
+ }
+ // Locate the position of the desired element
+ return jQuery.inArray(
+ // If it receives a jQuery object, the first element is used
+ elem.jquery ? elem[0] : elem, this );
+ },
+
+ add: function( selector, context ) {
+ var set = typeof selector === "string" ?
+ jQuery( selector, context || this.context ) :
+ jQuery.makeArray( selector ),
+ all = jQuery.merge( this.get(), set );
+
+ return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?
+ all :
+ jQuery.unique( all ) );
+ },
+
+ andSelf: function() {
+ return this.add( this.prevObject );
+ }
+});
+
+// A painfully simple check to see if an element is disconnected
+// from a document (should be improved, where feasible).
+function isDisconnected( node ) {
+ return !node || !node.parentNode || node.parentNode.nodeType === 11;
+}
+
+jQuery.each({
+ parent: function( elem ) {
+ var parent = elem.parentNode;
+ return parent && parent.nodeType !== 11 ? parent : null;
+ },
+ parents: function( elem ) {
+ return jQuery.dir( elem, "parentNode" );
+ },
+ parentsUntil: function( elem, i, until ) {
+ return jQuery.dir( elem, "parentNode", until );
+ },
+ next: function( elem ) {
+ return jQuery.nth( elem, 2, "nextSibling" );
+ },
+ prev: function( elem ) {
+ return jQuery.nth( elem, 2, "previousSibling" );
+ },
+ nextAll: function( elem ) {
+ return jQuery.dir( elem, "nextSibling" );
+ },
+ prevAll: function( elem ) {
+ return jQuery.dir( elem, "previousSibling" );
+ },
+ nextUntil: function( elem, i, until ) {
+ return jQuery.dir( elem, "nextSibling", until );
+ },
+ prevUntil: function( elem, i, until ) {
+ return jQuery.dir( elem, "previousSibling", until );
+ },
+ siblings: function( elem ) {
+ return jQuery.sibling( elem.parentNode.firstChild, elem );
+ },
+ children: function( elem ) {
+ return jQuery.sibling( elem.firstChild );
+ },
+ contents: function( elem ) {
+ return jQuery.nodeName( elem, "iframe" ) ?
+ elem.contentDocument || elem.contentWindow.document :
+ jQuery.makeArray( elem.childNodes );
+ }
+}, function( name, fn ) {
+ jQuery.fn[ name ] = function( until, selector ) {
+ var ret = jQuery.map( this, fn, until );
+
+ if ( !runtil.test( name ) ) {
+ selector = until;
+ }
+
+ if ( selector && typeof selector === "string" ) {
+ ret = jQuery.filter( selector, ret );
+ }
+
+ ret = this.length > 1 ? jQuery.unique( ret ) : ret;
+
+ if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {
+ ret = ret.reverse();
+ }
+
+ return this.pushStack( ret, name, slice.call(arguments).join(",") );
+ };
+});
+
+jQuery.extend({
+ filter: function( expr, elems, not ) {
+ if ( not ) {
+ expr = ":not(" + expr + ")";
+ }
+
+ return jQuery.find.matches(expr, elems);
+ },
+
+ dir: function( elem, dir, until ) {
+ var matched = [], cur = elem[dir];
+ while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
+ if ( cur.nodeType === 1 ) {
+ matched.push( cur );
+ }
+ cur = cur[dir];
+ }
+ return matched;
+ },
+
+ nth: function( cur, result, dir, elem ) {
+ result = result || 1;
+ var num = 0;
+
+ for ( ; cur; cur = cur[dir] ) {
+ if ( cur.nodeType === 1 && ++num === result ) {
+ break;
+ }
+ }
+
+ return cur;
+ },
+
+ sibling: function( n, elem ) {
+ var r = [];
+
+ for ( ; n; n = n.nextSibling ) {
+ if ( n.nodeType === 1 && n !== elem ) {
+ r.push( n );
+ }
+ }
+
+ return r;
+ }
+});
+var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g,
+ rleadingWhitespace = /^\s+/,
+ rxhtmlTag = /(<([\w:]+)[^>]*?)\/>/g,
+ rselfClosing = /^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,
+ rtagName = /<([\w:]+)/,
+ rtbody = /<tbody/i,
+ rhtml = /<|&#?\w+;/,
+ rnocache = /<script|<object|<embed|<option|<style/i,
+ rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i, // checked="checked" or checked (html5)
+ fcloseTag = function( all, front, tag ) {
+ return rselfClosing.test( tag ) ?
+ all :
+ front + "></" + tag + ">";
+ },
+ wrapMap = {
+ option: [ 1, "<select multiple='multiple'>", "</select>" ],
+ legend: [ 1, "<fieldset>", "</fieldset>" ],
+ thead: [ 1, "<table>", "</table>" ],
+ tr: [ 2, "<table><tbody>", "</tbody></table>" ],
+ td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
+ col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
+ area: [ 1, "<map>", "</map>" ],
+ _default: [ 0, "", "" ]
+ };
+
+wrapMap.optgroup = wrapMap.option;
+wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
+wrapMap.th = wrapMap.td;
+
+// IE can't serialize <link> and <script> tags normally
+if ( !jQuery.support.htmlSerialize ) {
+ wrapMap._default = [ 1, "div<div>", "</div>" ];
+}
+
+jQuery.fn.extend({
+ text: function( text ) {
+ if ( jQuery.isFunction(text) ) {
+ return this.each(function(i) {
+ var self = jQuery(this);
+ self.text( text.call(this, i, self.text()) );
+ });
+ }
+
+ if ( typeof text !== "object" && text !== undefined ) {
+ return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
+ }
+
+ return jQuery.text( this );
+ },
+
+ wrapAll: function( html ) {
+ if ( jQuery.isFunction( html ) ) {
+ return this.each(function(i) {
+ jQuery(this).wrapAll( html.call(this, i) );
+ });
+ }
+
+ if ( this[0] ) {
+ // The elements to wrap the target around
+ var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);
+
+ if ( this[0].parentNode ) {
+ wrap.insertBefore( this[0] );
+ }
+
+ wrap.map(function() {
+ var elem = this;
+
+ while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
+ elem = elem.firstChild;
+ }
+
+ return elem;
+ }).append(this);
+ }
+
+ return this;
+ },
+
+ wrapInner: function( html ) {
+ if ( jQuery.isFunction( html ) ) {
+ return this.each(function(i) {
+ jQuery(this).wrapInner( html.call(this, i) );
+ });
+ }
+
+ return this.each(function() {
+ var self = jQuery( this ), contents = self.contents();
+
+ if ( contents.length ) {
+ contents.wrapAll( html );
+
+ } else {
+ self.append( html );
+ }
+ });
+ },
+
+ wrap: function( html ) {
+ return this.each(function() {
+ jQuery( this ).wrapAll( html );
+ });
+ },
+
+ unwrap: function() {
+ return this.parent().each(function() {
+ if ( !jQuery.nodeName( this, "body" ) ) {
+ jQuery( this ).replaceWith( this.childNodes );
+ }
+ }).end();
+ },
+
+ append: function() {
+ return this.domManip(arguments, true, function( elem ) {
+ if ( this.nodeType === 1 ) {
+ this.appendChild( elem );
+ }
+ });
+ },
+
+ prepend: function() {
+ return this.domManip(arguments, true, function( elem ) {
+ if ( this.nodeType === 1 ) {
+ this.insertBefore( elem, this.firstChild );
+ }
+ });
+ },
+
+ before: function() {
+ if ( this[0] && this[0].parentNode ) {
+ return this.domManip(arguments, false, function( elem ) {
+ this.parentNode.insertBefore( elem, this );
+ });
+ } else if ( arguments.length ) {
+ var set = jQuery(arguments[0]);
+ set.push.apply( set, this.toArray() );
+ return this.pushStack( set, "before", arguments );
+ }
+ },
+
+ after: function() {
+ if ( this[0] && this[0].parentNode ) {
+ return this.domManip(arguments, false, function( elem ) {
+ this.parentNode.insertBefore( elem, this.nextSibling );
+ });
+ } else if ( arguments.length ) {
+ var set = this.pushStack( this, "after", arguments );
+ set.push.apply( set, jQuery(arguments[0]).toArray() );
+ return set;
+ }
+ },
+
+ // keepData is for internal use only--do not document
+ remove: function( selector, keepData ) {
+ for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
+ if ( !selector || jQuery.filter( selector, [ elem ] ).length ) {
+ if ( !keepData && elem.nodeType === 1 ) {
+ jQuery.cleanData( elem.getElementsByTagName("*") );
+ jQuery.cleanData( [ elem ] );
+ }
+
+ if ( elem.parentNode ) {
+ elem.parentNode.removeChild( elem );
+ }
+ }
+ }
+
+ return this;
+ },
+
+ empty: function() {
+ for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
+ // Remove element nodes and prevent memory leaks
+ if ( elem.nodeType === 1 ) {
+ jQuery.cleanData( elem.getElementsByTagName("*") );
+ }
+
+ // Remove any remaining nodes
+ while ( elem.firstChild ) {
+ elem.removeChild( elem.firstChild );
+ }
+ }
+
+ return this;
+ },
+
+ clone: function( events ) {
+ // Do the clone
+ var ret = this.map(function() {
+ if ( !jQuery.support.noCloneEvent && !jQuery.isXMLDoc(this) ) {
+ // IE copies events bound via attachEvent when
+ // using cloneNode. Calling detachEvent on the
+ // clone will also remove the events from the orignal
+ // In order to get around this, we use innerHTML.
+ // Unfortunately, this means some modifications to
+ // attributes in IE that are actually only stored
+ // as properties will not be copied (such as the
+ // the name attribute on an input).
+ var html = this.outerHTML, ownerDocument = this.ownerDocument;
+ if ( !html ) {
+ var div = ownerDocument.createElement("div");
+ div.appendChild( this.cloneNode(true) );
+ html = div.innerHTML;
+ }
+
+ return jQuery.clean([html.replace(rinlinejQuery, "")
+ // Handle the case in IE 8 where action=/test/> self-closes a tag
+ .replace(/=([^="'>\s]+\/)>/g, '="$1">')
+ .replace(rleadingWhitespace, "")], ownerDocument)[0];
+ } else {
+ return this.cloneNode(true);
+ }
+ });
+
+ // Copy the events from the original to the clone
+ if ( events === true ) {
+ cloneCopyEvent( this, ret );
+ cloneCopyEvent( this.find("*"), ret.find("*") );
+ }
+
+ // Return the cloned set
+ return ret;
+ },
+
+ html: function( value ) {
+ if ( value === undefined ) {
+ return this[0] && this[0].nodeType === 1 ?
+ this[0].innerHTML.replace(rinlinejQuery, "") :
+ null;
+
+ // See if we can take a shortcut and just use innerHTML
+ } else if ( typeof value === "string" && !rnocache.test( value ) &&
+ (jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) &&
+ !wrapMap[ (rtagName.exec( value ) || ["", ""])[1].toLowerCase() ] ) {
+
+ value = value.replace(rxhtmlTag, fcloseTag);
+
+ try {
+ for ( var i = 0, l = this.length; i < l; i++ ) {
+ // Remove element nodes and prevent memory leaks
+ if ( this[i].nodeType === 1 ) {
+ jQuery.cleanData( this[i].getElementsByTagName("*") );
+ this[i].innerHTML = value;
+ }
+ }
+
+ // If using innerHTML throws an exception, use the fallback method
+ } catch(e) {
+ this.empty().append( value );
+ }
+
+ } else if ( jQuery.isFunction( value ) ) {
+ this.each(function(i){
+ var self = jQuery(this), old = self.html();
+ self.empty().append(function(){
+ return value.call( this, i, old );
+ });
+ });
+
+ } else {
+ this.empty().append( value );
+ }
+
+ return this;
+ },
+
+ replaceWith: function( value ) {
+ if ( this[0] && this[0].parentNode ) {
+ // Make sure that the elements are removed from the DOM before they are inserted
+ // this can help fix replacing a parent with child elements
+ if ( jQuery.isFunction( value ) ) {
+ return this.each(function(i) {
+ var self = jQuery(this), old = self.html();
+ self.replaceWith( value.call( this, i, old ) );
+ });
+ }
+
+ if ( typeof value !== "string" ) {
+ value = jQuery(value).detach();
+ }
+
+ return this.each(function() {
+ var next = this.nextSibling, parent = this.parentNode;
+
+ jQuery(this).remove();
+
+ if ( next ) {
+ jQuery(next).before( value );
+ } else {
+ jQuery(parent).append( value );
+ }
+ });
+ } else {
+ return this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value );
+ }
+ },
+
+ detach: function( selector ) {
+ return this.remove( selector, true );
+ },
+
+ domManip: function( args, table, callback ) {
+ var results, first, value = args[0], scripts = [], fragment, parent;
+
+ // We can't cloneNode fragments that contain checked, in WebKit
+ if ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === "string" && rchecked.test( value ) ) {
+ return this.each(function() {
+ jQuery(this).domManip( args, table, callback, true );
+ });
+ }
+
+ if ( jQuery.isFunction(value) ) {
+ return this.each(function(i) {
+ var self = jQuery(this);
+ args[0] = value.call(this, i, table ? self.html() : undefined);
+ self.domManip( args, table, callback );
+ });
+ }
+
+ if ( this[0] ) {
+ parent = value && value.parentNode;
+
+ // If we're in a fragment, just use that instead of building a new one
+ if ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) {
+ results = { fragment: parent };
+
+ } else {
+ results = buildFragment( args, this, scripts );
+ }
+
+ fragment = results.fragment;
+
+ if ( fragment.childNodes.length === 1 ) {
+ first = fragment = fragment.firstChild;
+ } else {
+ first = fragment.firstChild;
+ }
+
+ if ( first ) {
+ table = table && jQuery.nodeName( first, "tr" );
+
+ for ( var i = 0, l = this.length; i < l; i++ ) {
+ callback.call(
+ table ?
+ root(this[i], first) :
+ this[i],
+ i > 0 || results.cacheable || this.length > 1 ?
+ fragment.cloneNode(true) :
+ fragment
+ );
+ }
+ }
+
+ if ( scripts.length ) {
+ jQuery.each( scripts, evalScript );
+ }
+ }
+
+ return this;
+
+ function root( elem, cur ) {
+ return jQuery.nodeName(elem, "table") ?
+ (elem.getElementsByTagName("tbody")[0] ||
+ elem.appendChild(elem.ownerDocument.createElement("tbody"))) :
+ elem;
+ }
+ }
+});
+
+function cloneCopyEvent(orig, ret) {
+ var i = 0;
+
+ ret.each(function() {
+ if ( this.nodeName !== (orig[i] && orig[i].nodeName) ) {
+ return;
+ }
+
+ var oldData = jQuery.data( orig[i++] ), curData = jQuery.data( this, oldData ), events = oldData && oldData.events;
+
+ if ( events ) {
+ delete curData.handle;
+ curData.events = {};
+
+ for ( var type in events ) {
+ for ( var handler in events[ type ] ) {
+ jQuery.event.add( this, type, events[ type ][ handler ], events[ type ][ handler ].data );
+ }
+ }
+ }
+ });
+}
+
+function buildFragment( args, nodes, scripts ) {
+ var fragment, cacheable, cacheresults,
+ doc = (nodes && nodes[0] ? nodes[0].ownerDocument || nodes[0] : document);
+
+ // Only cache "small" (1/2 KB) strings that are associated with the main document
+ // Cloning options loses the selected state, so don't cache them
+ // IE 6 doesn't like it when you put <object> or <embed> elements in a fragment
+ // Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache
+ if ( args.length === 1 && typeof args[0] === "string" && args[0].length < 512 && doc === document &&
+ !rnocache.test( args[0] ) && (jQuery.support.checkClone || !rchecked.test( args[0] )) ) {
+
+ cacheable = true;
+ cacheresults = jQuery.fragments[ args[0] ];
+ if ( cacheresults ) {
+ if ( cacheresults !== 1 ) {
+ fragment = cacheresults;
+ }
+ }
+ }
+
+ if ( !fragment ) {
+ fragment = doc.createDocumentFragment();
+ jQuery.clean( args, doc, fragment, scripts );
+ }
+
+ if ( cacheable ) {
+ jQuery.fragments[ args[0] ] = cacheresults ? fragment : 1;
+ }
+
+ return { fragment: fragment, cacheable: cacheable };
+}
+
+jQuery.fragments = {};
+
+jQuery.each({
+ appendTo: "append",
+ prependTo: "prepend",
+ insertBefore: "before",
+ insertAfter: "after",
+ replaceAll: "replaceWith"
+}, function( name, original ) {
+ jQuery.fn[ name ] = function( selector ) {
+ var ret = [], insert = jQuery( selector ),
+ parent = this.length === 1 && this[0].parentNode;
+
+ if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {
+ insert[ original ]( this[0] );
+ return this;
+
+ } else {
+ for ( var i = 0, l = insert.length; i < l; i++ ) {
+ var elems = (i > 0 ? this.clone(true) : this).get();
+ jQuery.fn[ original ].apply( jQuery(insert[i]), elems );
+ ret = ret.concat( elems );
+ }
+
+ return this.pushStack( ret, name, insert.selector );
+ }
+ };
+});
+
+jQuery.extend({
+ clean: function( elems, context, fragment, scripts ) {
+ context = context || document;
+
+ // !context.createElement fails in IE with an error but returns typeof 'object'
+ if ( typeof context.createElement === "undefined" ) {
+ context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
+ }
+
+ var ret = [];
+
+ for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
+ if ( typeof elem === "number" ) {
+ elem += "";
+ }
+
+ if ( !elem ) {
+ continue;
+ }
+
+ // Convert html string into DOM nodes
+ if ( typeof elem === "string" && !rhtml.test( elem ) ) {
+ elem = context.createTextNode( elem );
+
+ } else if ( typeof elem === "string" ) {
+ // Fix "XHTML"-style tags in all browsers
+ elem = elem.replace(rxhtmlTag, fcloseTag);
+
+ // Trim whitespace, otherwise indexOf won't work as expected
+ var tag = (rtagName.exec( elem ) || ["", ""])[1].toLowerCase(),
+ wrap = wrapMap[ tag ] || wrapMap._default,
+ depth = wrap[0],
+ div = context.createElement("div");
+
+ // Go to html and back, then peel off extra wrappers
+ div.innerHTML = wrap[1] + elem + wrap[2];
+
+ // Move to the right depth
+ while ( depth-- ) {
+ div = div.lastChild;
+ }
+
+ // Remove IE's autoinserted <tbody> from table fragments
+ if ( !jQuery.support.tbody ) {
+
+ // String was a <table>, *may* have spurious <tbody>
+ var hasBody = rtbody.test(elem),
+ tbody = tag === "table" && !hasBody ?
+ div.firstChild && div.firstChild.childNodes :
+
+ // String was a bare <thead> or <tfoot>
+ wrap[1] === "<table>" && !hasBody ?
+ div.childNodes :
+ [];
+
+ for ( var j = tbody.length - 1; j >= 0 ; --j ) {
+ if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) {
+ tbody[ j ].parentNode.removeChild( tbody[ j ] );
+ }
+ }
+
+ }
+
+ // IE completely kills leading whitespace when innerHTML is used
+ if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
+ div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );
+ }
+
+ elem = div.childNodes;
+ }
+
+ if ( elem.nodeType ) {
+ ret.push( elem );
+ } else {
+ ret = jQuery.merge( ret, elem );
+ }
+ }
+
+ if ( fragment ) {
+ for ( var i = 0; ret[i]; i++ ) {
+ if ( scripts && jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
+ scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );
+
+ } else {
+ if ( ret[i].nodeType === 1 ) {
+ ret.splice.apply( ret, [i + 1, 0].concat(jQuery.makeArray(ret[i].getElementsByTagName("script"))) );
+ }
+ fragment.appendChild( ret[i] );
+ }
+ }
+ }
+
+ return ret;
+ },
+
+ cleanData: function( elems ) {
+ var data, id, cache = jQuery.cache,
+ special = jQuery.event.special,
+ deleteExpando = jQuery.support.deleteExpando;
+
+ for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
+ id = elem[ jQuery.expando ];
+
+ if ( id ) {
+ data = cache[ id ];
+
+ if ( data.events ) {
+ for ( var type in data.events ) {
+ if ( special[ type ] ) {
+ jQuery.event.remove( elem, type );
+
+ } else {
+ removeEvent( elem, type, data.handle );
+ }
+ }
+ }
+
+ if ( deleteExpando ) {
+ delete elem[ jQuery.expando ];
+
+ } else if ( elem.removeAttribute ) {
+ elem.removeAttribute( jQuery.expando );
+ }
+
+ delete cache[ id ];
+ }
+ }
+ }
+});
+// exclude the following css properties to add px
+var rexclude = /z-?index|font-?weight|opacity|zoom|line-?height/i,
+ ralpha = /alpha\([^)]*\)/,
+ ropacity = /opacity=([^)]*)/,
+ rfloat = /float/i,
+ rdashAlpha = /-([a-z])/ig,
+ rupper = /([A-Z])/g,
+ rnumpx = /^-?\d+(?:px)?$/i,
+ rnum = /^-?\d/,
+
+ cssShow = { position: "absolute", visibility: "hidden", display:"block" },
+ cssWidth = [ "Left", "Right" ],
+ cssHeight = [ "Top", "Bottom" ],
+
+ // cache check for defaultView.getComputedStyle
+ getComputedStyle = document.defaultView && document.defaultView.getComputedStyle,
+ // normalize float css property
+ styleFloat = jQuery.support.cssFloat ? "cssFloat" : "styleFloat",
+ fcamelCase = function( all, letter ) {
+ return letter.toUpperCase();
+ };
+
+jQuery.fn.css = function( name, value ) {
+ return access( this, name, value, true, function( elem, name, value ) {
+ if ( value === undefined ) {
+ return jQuery.curCSS( elem, name );
+ }
+
+ if ( typeof value === "number" && !rexclude.test(name) ) {
+ value += "px";
+ }
+
+ jQuery.style( elem, name, value );
+ });
+};
+
+jQuery.extend({
+ style: function( elem, name, value ) {
+ // don't set styles on text and comment nodes
+ if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
+ return undefined;
+ }
+
+ // ignore negative width and height values #1599
+ if ( (name === "width" || name === "height") && parseFloat(value) < 0 ) {
+ value = undefined;
+ }
+
+ var style = elem.style || elem, set = value !== undefined;
+
+ // IE uses filters for opacity
+ if ( !jQuery.support.opacity && name === "opacity" ) {
+ if ( set ) {
+ // IE has trouble with opacity if it does not have layout
+ // Force it by setting the zoom level
+ style.zoom = 1;
+
+ // Set the alpha filter to set the opacity
+ var opacity = parseInt( value, 10 ) + "" === "NaN" ? "" : "alpha(opacity=" + value * 100 + ")";
+ var filter = style.filter || jQuery.curCSS( elem, "filter" ) || "";
+ style.filter = ralpha.test(filter) ? filter.replace(ralpha, opacity) : opacity;
+ }
+
+ return style.filter && style.filter.indexOf("opacity=") >= 0 ?
+ (parseFloat( ropacity.exec(style.filter)[1] ) / 100) + "":
+ "";
+ }
+
+ // Make sure we're using the right name for getting the float value
+ if ( rfloat.test( name ) ) {
+ name = styleFloat;
+ }
+
+ name = name.replace(rdashAlpha, fcamelCase);
+
+ if ( set ) {
+ style[ name ] = value;
+ }
+
+ return style[ name ];
+ },
+
+ css: function( elem, name, force, extra ) {
+ if ( name === "width" || name === "height" ) {
+ var val, props = cssShow, which = name === "width" ? cssWidth : cssHeight;
+
+ function getWH() {
+ val = name === "width" ? elem.offsetWidth : elem.offsetHeight;
+
+ if ( extra === "border" ) {
+ return;
+ }
+
+ jQuery.each( which, function() {
+ if ( !extra ) {
+ val -= parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0;
+ }
+
+ if ( extra === "margin" ) {
+ val += parseFloat(jQuery.curCSS( elem, "margin" + this, true)) || 0;
+ } else {
+ val -= parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0;
+ }
+ });
+ }
+
+ if ( elem.offsetWidth !== 0 ) {
+ getWH();
+ } else {
+ jQuery.swap( elem, props, getWH );
+ }
+
+ return Math.max(0, Math.round(val));
+ }
+
+ return jQuery.curCSS( elem, name, force );
+ },
+
+ curCSS: function( elem, name, force ) {
+ var ret, style = elem.style, filter;
+
+ // IE uses filters for opacity
+ if ( !jQuery.support.opacity && name === "opacity" && elem.currentStyle ) {
+ ret = ropacity.test(elem.currentStyle.filter || "") ?
+ (parseFloat(RegExp.$1) / 100) + "" :
+ "";
+
+ return ret === "" ?
+ "1" :
+ ret;
+ }
+
+ // Make sure we're using the right name for getting the float value
+ if ( rfloat.test( name ) ) {
+ name = styleFloat;
+ }
+
+ if ( !force && style && style[ name ] ) {
+ ret = style[ name ];
+
+ } else if ( getComputedStyle ) {
+
+ // Only "float" is needed here
+ if ( rfloat.test( name ) ) {
+ name = "float";
+ }
+
+ name = name.replace( rupper, "-$1" ).toLowerCase();
+
+ var defaultView = elem.ownerDocument.defaultView;
+
+ if ( !defaultView ) {
+ return null;
+ }
+
+ var computedStyle = defaultView.getComputedStyle( elem, null );
+
+ if ( computedStyle ) {
+ ret = computedStyle.getPropertyValue( name );
+ }
+
+ // We should always get a number back from opacity
+ if ( name === "opacity" && ret === "" ) {
+ ret = "1";
+ }
+
+ } else if ( elem.currentStyle ) {
+ var camelCase = name.replace(rdashAlpha, fcamelCase);
+
+ ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ];
+
+ // From the awesome hack by Dean Edwards
+ // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
+
+ // If we're not dealing with a regular pixel number
+ // but a number that has a weird ending, we need to convert it to pixels
+ if ( !rnumpx.test( ret ) && rnum.test( ret ) ) {
+ // Remember the original values
+ var left = style.left, rsLeft = elem.runtimeStyle.left;
+
+ // Put in the new values to get a computed value out
+ elem.runtimeStyle.left = elem.currentStyle.left;
+ style.left = camelCase === "fontSize" ? "1em" : (ret || 0);
+ ret = style.pixelLeft + "px";
+
+ // Revert the changed values
+ style.left = left;
+ elem.runtimeStyle.left = rsLeft;
+ }
+ }
+
+ return ret;
+ },
+
+ // A method for quickly swapping in/out CSS properties to get correct calculations
+ swap: function( elem, options, callback ) {
+ var old = {};
+
+ // Remember the old values, and insert the new ones
+ for ( var name in options ) {
+ old[ name ] = elem.style[ name ];
+ elem.style[ name ] = options[ name ];
+ }
+
+ callback.call( elem );
+
+ // Revert the old values
+ for ( var name in options ) {
+ elem.style[ name ] = old[ name ];
+ }
+ }
+});
+
+if ( jQuery.expr && jQuery.expr.filters ) {
+ jQuery.expr.filters.hidden = function( elem ) {
+ var width = elem.offsetWidth, height = elem.offsetHeight,
+ skip = elem.nodeName.toLowerCase() === "tr";
+
+ return width === 0 && height === 0 && !skip ?
+ true :
+ width > 0 && height > 0 && !skip ?
+ false :
+ jQuery.curCSS(elem, "display") === "none";
+ };
+
+ jQuery.expr.filters.visible = function( elem ) {
+ return !jQuery.expr.filters.hidden( elem );
+ };
+}
+var jsc = now(),
+ rscript = /<script(.|\s)*?\/script>/gi,
+ rselectTextarea = /select|textarea/i,
+ rinput = /color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,
+ jsre = /=\?(&|$)/,
+ rquery = /\?/,
+ rts = /(\?|&)_=.*?(&|$)/,
+ rurl = /^(\w+:)?\/\/([^\/?#]+)/,
+ r20 = /%20/g,
+
+ // Keep a copy of the old load method
+ _load = jQuery.fn.load;
+
+jQuery.fn.extend({
+ load: function( url, params, callback ) {
+ if ( typeof url !== "string" ) {
+ return _load.call( this, url );
+
+ // Don't do a request if no elements are being requested
+ } else if ( !this.length ) {
+ return this;
+ }
+
+ var off = url.indexOf(" ");
+ if ( off >= 0 ) {
+ var selector = url.slice(off, url.length);
+ url = url.slice(0, off);
+ }
+
+ // Default to a GET request
+ var type = "GET";
+
+ // If the second parameter was provided
+ if ( params ) {
+ // If it's a function
+ if ( jQuery.isFunction( params ) ) {
+ // We assume that it's the callback
+ callback = params;
+ params = null;
+
+ // Otherwise, build a param string
+ } else if ( typeof params === "object" ) {
+ params = jQuery.param( params, jQuery.ajaxSettings.traditional );
+ type = "POST";
+ }
+ }
+
+ var self = this;
+
+ // Request the remote document
+ jQuery.ajax({
+ url: url,
+ type: type,
+ dataType: "html",
+ data: params,
+ complete: function( res, status ) {
+ // If successful, inject the HTML into all the matched elements
+ if ( status === "success" || status === "notmodified" ) {
+ // See if a selector was specified
+ self.html( selector ?
+ // Create a dummy div to hold the results
+ jQuery("<div />")
+ // inject the contents of the document in, removing the scripts
+ // to avoid any 'Permission Denied' errors in IE
+ .append(res.responseText.replace(rscript, ""))
+
+ // Locate the specified elements
+ .find(selector) :
+
+ // If not, just inject the full result
+ res.responseText );
+ }
+
+ if ( callback ) {
+ self.each( callback, [res.responseText, status, res] );
+ }
+ }
+ });
+
+ return this;
+ },
+
+ serialize: function() {
+ return jQuery.param(this.serializeArray());
+ },
+ serializeArray: function() {
+ return this.map(function() {
+ return this.elements ? jQuery.makeArray(this.elements) : this;
+ })
+ .filter(function() {
+ return this.name && !this.disabled &&
+ (this.checked || rselectTextarea.test(this.nodeName) ||
+ rinput.test(this.type));
+ })
+ .map(function( i, elem ) {
+ var val = jQuery(this).val();
+
+ return val == null ?
+ null :
+ jQuery.isArray(val) ?
+ jQuery.map( val, function( val, i ) {
+ return { name: elem.name, value: val };
+ }) :
+ { name: elem.name, value: val };
+ }).get();
+ }
+});
+
+// Attach a bunch of functions for handling common AJAX events
+jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "), function( i, o ) {
+ jQuery.fn[o] = function( f ) {
+ return this.bind(o, f);
+ };
+});
+
+jQuery.extend({
+
+ get: function( url, data, callback, type ) {
+ // shift arguments if data argument was omited
+ if ( jQuery.isFunction( data ) ) {
+ type = type || callback;
+ callback = data;
+ data = null;
+ }
+
+ return jQuery.ajax({
+ type: "GET",
+ url: url,
+ data: data,
+ success: callback,
+ dataType: type
+ });
+ },
+
+ getScript: function( url, callback ) {
+ return jQuery.get(url, null, callback, "script");
+ },
+
+ getJSON: function( url, data, callback ) {
+ return jQuery.get(url, data, callback, "json");
+ },
+
+ post: function( url, data, callback, type ) {
+ // shift arguments if data argument was omited
+ if ( jQuery.isFunction( data ) ) {
+ type = type || callback;
+ callback = data;
+ data = {};
+ }
+
+ return jQuery.ajax({
+ type: "POST",
+ url: url,
+ data: data,
+ success: callback,
+ dataType: type
+ });
+ },
+
+ ajaxSetup: function( settings ) {
+ jQuery.extend( jQuery.ajaxSettings, settings );
+ },
+
+ ajaxSettings: {
+ url: location.href,
+ global: true,
+ type: "GET",
+ contentType: "application/x-www-form-urlencoded",
+ processData: true,
+ async: true,
+ /*
+ timeout: 0,
+ data: null,
+ username: null,
+ password: null,
+ traditional: false,
+ */
+ // Create the request object; Microsoft failed to properly
+ // implement the XMLHttpRequest in IE7 (can't request local files),
+ // so we use the ActiveXObject when it is available
+ // This function can be overriden by calling jQuery.ajaxSetup
+ xhr: window.XMLHttpRequest && (window.location.protocol !== "file:" || !window.ActiveXObject) ?
+ function() {
+ return new window.XMLHttpRequest();
+ } :
+ function() {
+ try {
+ return new window.ActiveXObject("Microsoft.XMLHTTP");
+ } catch(e) {}
+ },
+ accepts: {
+ xml: "application/xml, text/xml",
+ html: "text/html",
+ script: "text/javascript, application/javascript",
+ json: "application/json, text/javascript",
+ text: "text/plain",
+ _default: "*/*"
+ }
+ },
+
+ // Last-Modified header cache for next request
+ lastModified: {},
+ etag: {},
+
+ ajax: function( origSettings ) {
+ var s = jQuery.extend(true, {}, jQuery.ajaxSettings, origSettings);
+
+ var jsonp, status, data,
+ callbackContext = origSettings && origSettings.context || s,
+ type = s.type.toUpperCase();
+
+ // convert data if not already a string
+ if ( s.data && s.processData && typeof s.data !== "string" ) {
+ s.data = jQuery.param( s.data, s.traditional );
+ }
+
+ // Handle JSONP Parameter Callbacks
+ if ( s.dataType === "jsonp" ) {
+ if ( type === "GET" ) {
+ if ( !jsre.test( s.url ) ) {
+ s.url += (rquery.test( s.url ) ? "&" : "?") + (s.jsonp || "callback") + "=?";
+ }
+ } else if ( !s.data || !jsre.test(s.data) ) {
+ s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?";
+ }
+ s.dataType = "json";
+ }
+
+ // Build temporary JSONP function
+ if ( s.dataType === "json" && (s.data && jsre.test(s.data) || jsre.test(s.url)) ) {
+ jsonp = s.jsonpCallback || ("jsonp" + jsc++);
+
+ // Replace the =? sequence both in the query string and the data
+ if ( s.data ) {
+ s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1");
+ }
+
+ s.url = s.url.replace(jsre, "=" + jsonp + "$1");
+
+ // We need to make sure
+ // that a JSONP style response is executed properly
+ s.dataType = "script";
+
+ // Handle JSONP-style loading
+ window[ jsonp ] = window[ jsonp ] || function( tmp ) {
+ data = tmp;
+ success();
+ complete();
+ // Garbage collect
+ window[ jsonp ] = undefined;
+
+ try {
+ delete window[ jsonp ];
+ } catch(e) {}
+
+ if ( head ) {
+ head.removeChild( script );
+ }
+ };
+ }
+
+ if ( s.dataType === "script" && s.cache === null ) {
+ s.cache = false;
+ }
+
+ if ( s.cache === false && type === "GET" ) {
+ var ts = now();
+
+ // try replacing _= if it is there
+ var ret = s.url.replace(rts, "$1_=" + ts + "$2");
+
+ // if nothing was replaced, add timestamp to the end
+ s.url = ret + ((ret === s.url) ? (rquery.test(s.url) ? "&" : "?") + "_=" + ts : "");
+ }
+
+ // If data is available, append data to url for get requests
+ if ( s.data && type === "GET" ) {
+ s.url += (rquery.test(s.url) ? "&" : "?") + s.data;
+ }
+
+ // Watch for a new set of requests
+ if ( s.global && ! jQuery.active++ ) {
+ jQuery.event.trigger( "ajaxStart" );
+ }
+
+ // Matches an absolute URL, and saves the domain
+ var parts = rurl.exec( s.url ),
+ remote = parts && (parts[1] && parts[1] !== location.protocol || parts[2] !== location.host);
+
+ // If we're requesting a remote document
+ // and trying to load JSON or Script with a GET
+ if ( s.dataType === "script" && type === "GET" && remote ) {
+ var head = document.getElementsByTagName("head")[0] || document.documentElement;
+ var script = document.createElement("script");
+ script.src = s.url;
+ if ( s.scriptCharset ) {
+ script.charset = s.scriptCharset;
+ }
+
+ // Handle Script loading
+ if ( !jsonp ) {
+ var done = false;
+
+ // Attach handlers for all browsers
+ script.onload = script.onreadystatechange = function() {
+ if ( !done && (!this.readyState ||
+ this.readyState === "loaded" || this.readyState === "complete") ) {
+ done = true;
+ success();
+ complete();
+
+ // Handle memory leak in IE
+ script.onload = script.onreadystatechange = null;
+ if ( head && script.parentNode ) {
+ head.removeChild( script );
+ }
+ }
+ };
+ }
+
+ // Use insertBefore instead of appendChild to circumvent an IE6 bug.
+ // This arises when a base node is used (#2709 and #4378).
+ head.insertBefore( script, head.firstChild );
+
+ // We handle everything using the script element injection
+ return undefined;
+ }
+
+ var requestDone = false;
+
+ // Create the request object
+ var xhr = s.xhr();
+
+ if ( !xhr ) {
+ return;
+ }
+
+ // Open the socket
+ // Passing null username, generates a login popup on Opera (#2865)
+ if ( s.username ) {
+ xhr.open(type, s.url, s.async, s.username, s.password);
+ } else {
+ xhr.open(type, s.url, s.async);
+ }
+
+ // Need an extra try/catch for cross domain requests in Firefox 3
+ try {
+ // Set the correct header, if data is being sent
+ if ( s.data || origSettings && origSettings.contentType ) {
+ xhr.setRequestHeader("Content-Type", s.contentType);
+ }
+
+ // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+ if ( s.ifModified ) {
+ if ( jQuery.lastModified[s.url] ) {
+ xhr.setRequestHeader("If-Modified-Since", jQuery.lastModified[s.url]);
+ }
+
+ if ( jQuery.etag[s.url] ) {
+ xhr.setRequestHeader("If-None-Match", jQuery.etag[s.url]);
+ }
+ }
+
+ // Set header so the called script knows that it's an XMLHttpRequest
+ // Only send the header if it's not a remote XHR
+ if ( !remote ) {
+ xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
+ }
+
+ // Set the Accepts header for the server, depending on the dataType
+ xhr.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ?
+ s.accepts[ s.dataType ] + ", */*" :
+ s.accepts._default );
+ } catch(e) {}
+
+ // Allow custom headers/mimetypes and early abort
+ if ( s.beforeSend && s.beforeSend.call(callbackContext, xhr, s) === false ) {
+ // Handle the global AJAX counter
+ if ( s.global && ! --jQuery.active ) {
+ jQuery.event.trigger( "ajaxStop" );
+ }
+
+ // close opended socket
+ xhr.abort();
+ return false;
+ }
+
+ if ( s.global ) {
+ trigger("ajaxSend", [xhr, s]);
+ }
+
+ // Wait for a response to come back
+ var onreadystatechange = xhr.onreadystatechange = function( isTimeout ) {
+ // The request was aborted
+ if ( !xhr || xhr.readyState === 0 || isTimeout === "abort" ) {
+ // Opera doesn't call onreadystatechange before this point
+ // so we simulate the call
+ if ( !requestDone ) {
+ complete();
+ }
+
+ requestDone = true;
+ if ( xhr ) {
+ xhr.onreadystatechange = jQuery.noop;
+ }
+
+ // The transfer is complete and the data is available, or the request timed out
+ } else if ( !requestDone && xhr && (xhr.readyState === 4 || isTimeout === "timeout") ) {
+ requestDone = true;
+ xhr.onreadystatechange = jQuery.noop;
+
+ status = isTimeout === "timeout" ?
+ "timeout" :
+ !jQuery.httpSuccess( xhr ) ?
+ "error" :
+ s.ifModified && jQuery.httpNotModified( xhr, s.url ) ?
+ "notmodified" :
+ "success";
+
+ var errMsg;
+
+ if ( status === "success" ) {
+ // Watch for, and catch, XML document parse errors
+ try {
+ // process the data (runs the xml through httpData regardless of callback)
+ data = jQuery.httpData( xhr, s.dataType, s );
+ } catch(err) {
+ status = "parsererror";
+ errMsg = err;
+ }
+ }
+
+ // Make sure that the request was successful or notmodified
+ if ( status === "success" || status === "notmodified" ) {
+ // JSONP handles its own success callback
+ if ( !jsonp ) {
+ success();
+ }
+ } else {
+ jQuery.handleError(s, xhr, status, errMsg);
+ }
+
+ // Fire the complete handlers
+ complete();
+
+ if ( isTimeout === "timeout" ) {
+ xhr.abort();
+ }
+
+ // Stop memory leaks
+ if ( s.async ) {
+ xhr = null;
+ }
+ }
+ };
+
+ // Override the abort handler, if we can (IE doesn't allow it, but that's OK)
+ // Opera doesn't fire onreadystatechange at all on abort
+ try {
+ var oldAbort = xhr.abort;
+ xhr.abort = function() {
+ if ( xhr ) {
+ oldAbort.call( xhr );
+ }
+
+ onreadystatechange( "abort" );
+ };
+ } catch(e) { }
+
+ // Timeout checker
+ if ( s.async && s.timeout > 0 ) {
+ setTimeout(function() {
+ // Check to see if the request is still happening
+ if ( xhr && !requestDone ) {
+ onreadystatechange( "timeout" );
+ }
+ }, s.timeout);
+ }
+
+ // Send the data
+ try {
+ xhr.send( type === "POST" || type === "PUT" || type === "DELETE" ? s.data : null );
+ } catch(e) {
+ jQuery.handleError(s, xhr, null, e);
+ // Fire the complete handlers
+ complete();
+ }
+
+ // firefox 1.5 doesn't fire statechange for sync requests
+ if ( !s.async ) {
+ onreadystatechange();
+ }
+
+ function success() {
+ // If a local callback was specified, fire it and pass it the data
+ if ( s.success ) {
+ s.success.call( callbackContext, data, status, xhr );
+ }
+
+ // Fire the global callback
+ if ( s.global ) {
+ trigger( "ajaxSuccess", [xhr, s] );
+ }
+ }
+
+ function complete() {
+ // Process result
+ if ( s.complete ) {
+ s.complete.call( callbackContext, xhr, status);
+ }
+
+ // The request was completed
+ if ( s.global ) {
+ trigger( "ajaxComplete", [xhr, s] );
+ }
+
+ // Handle the global AJAX counter
+ if ( s.global && ! --jQuery.active ) {
+ jQuery.event.trigger( "ajaxStop" );
+ }
+ }
+
+ function trigger(type, args) {
+ (s.context ? jQuery(s.context) : jQuery.event).trigger(type, args);
+ }
+
+ // return XMLHttpRequest to allow aborting the request etc.
+ return xhr;
+ },
+
+ handleError: function( s, xhr, status, e ) {
+ // If a local callback was specified, fire it
+ if ( s.error ) {
+ s.error.call( s.context || s, xhr, status, e );
+ }
+
+ // Fire the global callback
+ if ( s.global ) {
+ (s.context ? jQuery(s.context) : jQuery.event).trigger( "ajaxError", [xhr, s, e] );
+ }
+ },
+
+ // Counter for holding the number of active queries
+ active: 0,
+
+ // Determines if an XMLHttpRequest was successful or not
+ httpSuccess: function( xhr ) {
+ try {
+ // IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450
+ return !xhr.status && location.protocol === "file:" ||
+ // Opera returns 0 when status is 304
+ ( xhr.status >= 200 && xhr.status < 300 ) ||
+ xhr.status === 304 || xhr.status === 1223 || xhr.status === 0;
+ } catch(e) {}
+
+ return false;
+ },
+
+ // Determines if an XMLHttpRequest returns NotModified
+ httpNotModified: function( xhr, url ) {
+ var lastModified = xhr.getResponseHeader("Last-Modified"),
+ etag = xhr.getResponseHeader("Etag");
+
+ if ( lastModified ) {
+ jQuery.lastModified[url] = lastModified;
+ }
+
+ if ( etag ) {
+ jQuery.etag[url] = etag;
+ }
+
+ // Opera returns 0 when status is 304
+ return xhr.status === 304 || xhr.status === 0;
+ },
+
+ httpData: function( xhr, type, s ) {
+ var ct = xhr.getResponseHeader("content-type") || "",
+ xml = type === "xml" || !type && ct.indexOf("xml") >= 0,
+ data = xml ? xhr.responseXML : xhr.responseText;
+
+ if ( xml && data.documentElement.nodeName === "parsererror" ) {
+ jQuery.error( "parsererror" );
+ }
+
+ // Allow a pre-filtering function to sanitize the response
+ // s is checked to keep backwards compatibility
+ if ( s && s.dataFilter ) {
+ data = s.dataFilter( data, type );
+ }
+
+ // The filter can actually parse the response
+ if ( typeof data === "string" ) {
+ // Get the JavaScript object, if JSON is used.
+ if ( type === "json" || !type && ct.indexOf("json") >= 0 ) {
+ data = jQuery.parseJSON( data );
+
+ // If the type is "script", eval it in global context
+ } else if ( type === "script" || !type && ct.indexOf("javascript") >= 0 ) {
+ jQuery.globalEval( data );
+ }
+ }
+
+ return data;
+ },
+
+ // Serialize an array of form elements or a set of
+ // key/values into a query string
+ param: function( a, traditional ) {
+ var s = [];
+
+ // Set traditional to true for jQuery <= 1.3.2 behavior.
+ if ( traditional === undefined ) {
+ traditional = jQuery.ajaxSettings.traditional;
+ }
+
+ // If an array was passed in, assume that it is an array of form elements.
+ if ( jQuery.isArray(a) || a.jquery ) {
+ // Serialize the form elements
+ jQuery.each( a, function() {
+ add( this.name, this.value );
+ });
+
+ } else {
+ // If traditional, encode the "old" way (the way 1.3.2 or older
+ // did it), otherwise encode params recursively.
+ for ( var prefix in a ) {
+ buildParams( prefix, a[prefix] );
+ }
+ }
+
+ // Return the resulting serialization
+ return s.join("&").replace(r20, "+");
+
+ function buildParams( prefix, obj ) {
+ if ( jQuery.isArray(obj) ) {
+ // Serialize array item.
+ jQuery.each( obj, function( i, v ) {
+ if ( traditional || /\[\]$/.test( prefix ) ) {
+ // Treat each array item as a scalar.
+ add( prefix, v );
+ } else {
+ // If array item is non-scalar (array or object), encode its
+ // numeric index to resolve deserialization ambiguity issues.
+ // Note that rack (as of 1.0.0) can't currently deserialize
+ // nested arrays properly, and attempting to do so may cause
+ // a server error. Possible fixes are to modify rack's
+ // deserialization algorithm or to provide an option or flag
+ // to force array serialization to be shallow.
+ buildParams( prefix + "[" + ( typeof v === "object" || jQuery.isArray(v) ? i : "" ) + "]", v );
+ }
+ });
+
+ } else if ( !traditional && obj != null && typeof obj === "object" ) {
+ // Serialize object item.
+ jQuery.each( obj, function( k, v ) {
+ buildParams( prefix + "[" + k + "]", v );
+ });
+
+ } else {
+ // Serialize scalar item.
+ add( prefix, obj );
+ }
+ }
+
+ function add( key, value ) {
+ // If value is a function, invoke it and return its value
+ value = jQuery.isFunction(value) ? value() : value;
+ s[ s.length ] = encodeURIComponent(key) + "=" + encodeURIComponent(value);
+ }
+ }
+});
+var elemdisplay = {},
+ rfxtypes = /toggle|show|hide/,
+ rfxnum = /^([+-]=)?([\d+-.]+)(.*)$/,
+ timerId,
+ fxAttrs = [
+ // height animations
+ [ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ],
+ // width animations
+ [ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ],
+ // opacity animations
+ [ "opacity" ]
+ ];
+
+jQuery.fn.extend({
+ show: function( speed, callback ) {
+ if ( speed || speed === 0) {
+ return this.animate( genFx("show", 3), speed, callback);
+
+ } else {
+ for ( var i = 0, l = this.length; i < l; i++ ) {
+ var old = jQuery.data(this[i], "olddisplay");
+
+ this[i].style.display = old || "";
+
+ if ( jQuery.css(this[i], "display") === "none" ) {
+ var nodeName = this[i].nodeName, display;
+
+ if ( elemdisplay[ nodeName ] ) {
+ display = elemdisplay[ nodeName ];
+
+ } else {
+ var elem = jQuery("<" + nodeName + " />").appendTo("body");
+
+ display = elem.css("display");
+
+ if ( display === "none" ) {
+ display = "block";
+ }
+
+ elem.remove();
+
+ elemdisplay[ nodeName ] = display;
+ }
+
+ jQuery.data(this[i], "olddisplay", display);
+ }
+ }
+
+ // Set the display of the elements in a second loop
+ // to avoid the constant reflow
+ for ( var j = 0, k = this.length; j < k; j++ ) {
+ this[j].style.display = jQuery.data(this[j], "olddisplay") || "";
+ }
+
+ return this;
+ }
+ },
+
+ hide: function( speed, callback ) {
+ if ( speed || speed === 0 ) {
+ return this.animate( genFx("hide", 3), speed, callback);
+
+ } else {
+ for ( var i = 0, l = this.length; i < l; i++ ) {
+ var old = jQuery.data(this[i], "olddisplay");
+ if ( !old && old !== "none" ) {
+ jQuery.data(this[i], "olddisplay", jQuery.css(this[i], "display"));
+ }
+ }
+
+ // Set the display of the elements in a second loop
+ // to avoid the constant reflow
+ for ( var j = 0, k = this.length; j < k; j++ ) {
+ this[j].style.display = "none";
+ }
+
+ return this;
+ }
+ },
+
+ // Save the old toggle function
+ _toggle: jQuery.fn.toggle,
+
+ toggle: function( fn, fn2 ) {
+ var bool = typeof fn === "boolean";
+
+ if ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) {
+ this._toggle.apply( this, arguments );
+
+ } else if ( fn == null || bool ) {
+ this.each(function() {
+ var state = bool ? fn : jQuery(this).is(":hidden");
+ jQuery(this)[ state ? "show" : "hide" ]();
+ });
+
+ } else {
+ this.animate(genFx("toggle", 3), fn, fn2);
+ }
+
+ return this;
+ },
+
+ fadeTo: function( speed, to, callback ) {
+ return this.filter(":hidden").css("opacity", 0).show().end()
+ .animate({opacity: to}, speed, callback);
+ },
+
+ animate: function( prop, speed, easing, callback ) {
+ var optall = jQuery.speed(speed, easing, callback);
+
+ if ( jQuery.isEmptyObject( prop ) ) {
+ return this.each( optall.complete );
+ }
+
+ return this[ optall.queue === false ? "each" : "queue" ](function() {
+ var opt = jQuery.extend({}, optall), p,
+ hidden = this.nodeType === 1 && jQuery(this).is(":hidden"),
+ self = this;
+
+ for ( p in prop ) {
+ var name = p.replace(rdashAlpha, fcamelCase);
+
+ if ( p !== name ) {
+ prop[ name ] = prop[ p ];
+ delete prop[ p ];
+ p = name;
+ }
+
+ if ( prop[p] === "hide" && hidden || prop[p] === "show" && !hidden ) {
+ return opt.complete.call(this);
+ }
+
+ if ( ( p === "height" || p === "width" ) && this.style ) {
+ // Store display property
+ opt.display = jQuery.css(this, "display");
+
+ // Make sure that nothing sneaks out
+ opt.overflow = this.style.overflow;
+ }
+
+ if ( jQuery.isArray( prop[p] ) ) {
+ // Create (if needed) and add to specialEasing
+ (opt.specialEasing = opt.specialEasing || {})[p] = prop[p][1];
+ prop[p] = prop[p][0];
+ }
+ }
+
+ if ( opt.overflow != null ) {
+ this.style.overflow = "hidden";
+ }
+
+ opt.curAnim = jQuery.extend({}, prop);
+
+ jQuery.each( prop, function( name, val ) {
+ var e = new jQuery.fx( self, opt, name );
+
+ if ( rfxtypes.test(val) ) {
+ e[ val === "toggle" ? hidden ? "show" : "hide" : val ]( prop );
+
+ } else {
+ var parts = rfxnum.exec(val),
+ start = e.cur(true) || 0;
+
+ if ( parts ) {
+ var end = parseFloat( parts[2] ),
+ unit = parts[3] || "px";
+
+ // We need to compute starting value
+ if ( unit !== "px" ) {
+ self.style[ name ] = (end || 1) + unit;
+ start = ((end || 1) / e.cur(true)) * start;
+ self.style[ name ] = start + unit;
+ }
+
+ // If a +=/-= token was provided, we're doing a relative animation
+ if ( parts[1] ) {
+ end = ((parts[1] === "-=" ? -1 : 1) * end) + start;
+ }
+
+ e.custom( start, end, unit );
+
+ } else {
+ e.custom( start, val, "" );
+ }
+ }
+ });
+
+ // For JS strict compliance
+ return true;
+ });
+ },
+
+ stop: function( clearQueue, gotoEnd ) {
+ var timers = jQuery.timers;
+
+ if ( clearQueue ) {
+ this.queue([]);
+ }
+
+ this.each(function() {
+ // go in reverse order so anything added to the queue during the loop is ignored
+ for ( var i = timers.length - 1; i >= 0; i-- ) {
+ if ( timers[i].elem === this ) {
+ if (gotoEnd) {
+ // force the next step to be the last
+ timers[i](true);
+ }
+
+ timers.splice(i, 1);
+ }
+ }
+ });
+
+ // start the next in the queue if the last step wasn't forced
+ if ( !gotoEnd ) {
+ this.dequeue();
+ }
+
+ return this;
+ }
+
+});
+
+// Generate shortcuts for custom animations
+jQuery.each({
+ slideDown: genFx("show", 1),
+ slideUp: genFx("hide", 1),
+ slideToggle: genFx("toggle", 1),
+ fadeIn: { opacity: "show" },
+ fadeOut: { opacity: "hide" }
+}, function( name, props ) {
+ jQuery.fn[ name ] = function( speed, callback ) {
+ return this.animate( props, speed, callback );
+ };
+});
+
+jQuery.extend({
+ speed: function( speed, easing, fn ) {
+ var opt = speed && typeof speed === "object" ? speed : {
+ complete: fn || !fn && easing ||
+ jQuery.isFunction( speed ) && speed,
+ duration: speed,
+ easing: fn && easing || easing && !jQuery.isFunction(easing) && easing
+ };
+
+ opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
+ jQuery.fx.speeds[opt.duration] || jQuery.fx.speeds._default;
+
+ // Queueing
+ opt.old = opt.complete;
+ opt.complete = function() {
+ if ( opt.queue !== false ) {
+ jQuery(this).dequeue();
+ }
+ if ( jQuery.isFunction( opt.old ) ) {
+ opt.old.call( this );
+ }
+ };
+
+ return opt;
+ },
+
+ easing: {
+ linear: function( p, n, firstNum, diff ) {
+ return firstNum + diff * p;
+ },
+ swing: function( p, n, firstNum, diff ) {
+ return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;
+ }
+ },
+
+ timers: [],
+
+ fx: function( elem, options, prop ) {
+ this.options = options;
+ this.elem = elem;
+ this.prop = prop;
+
+ if ( !options.orig ) {
+ options.orig = {};
+ }
+ }
+
+});
+
+jQuery.fx.prototype = {
+ // Simple function for setting a style value
+ update: function() {
+ if ( this.options.step ) {
+ this.options.step.call( this.elem, this.now, this );
+ }
+
+ (jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );
+
+ // Set display property to block for height/width animations
+ if ( ( this.prop === "height" || this.prop === "width" ) && this.elem.style ) {
+ this.elem.style.display = "block";
+ }
+ },
+
+ // Get the current size
+ cur: function( force ) {
+ if ( this.elem[this.prop] != null && (!this.elem.style || this.elem.style[this.prop] == null) ) {
+ return this.elem[ this.prop ];
+ }
+
+ var r = parseFloat(jQuery.css(this.elem, this.prop, force));
+ return r && r > -10000 ? r : parseFloat(jQuery.curCSS(this.elem, this.prop)) || 0;
+ },
+
+ // Start an animation from one number to another
+ custom: function( from, to, unit ) {
+ this.startTime = now();
+ this.start = from;
+ this.end = to;
+ this.unit = unit || this.unit || "px";
+ this.now = this.start;
+ this.pos = this.state = 0;
+
+ var self = this;
+ function t( gotoEnd ) {
+ return self.step(gotoEnd);
+ }
+
+ t.elem = this.elem;
+
+ if ( t() && jQuery.timers.push(t) && !timerId ) {
+ timerId = setInterval(jQuery.fx.tick, 13);
+ }
+ },
+
+ // Simple 'show' function
+ show: function() {
+ // Remember where we started, so that we can go back to it later
+ this.options.orig[this.prop] = jQuery.style( this.elem, this.prop );
+ this.options.show = true;
+
+ // Begin the animation
+ // Make sure that we start at a small width/height to avoid any
+ // flash of content
+ this.custom(this.prop === "width" || this.prop === "height" ? 1 : 0, this.cur());
+
+ // Start by showing the element
+ jQuery( this.elem ).show();
+ },
+
+ // Simple 'hide' function
+ hide: function() {
+ // Remember where we started, so that we can go back to it later
+ this.options.orig[this.prop] = jQuery.style( this.elem, this.prop );
+ this.options.hide = true;
+
+ // Begin the animation
+ this.custom(this.cur(), 0);
+ },
+
+ // Each step of an animation
+ step: function( gotoEnd ) {
+ var t = now(), done = true;
+
+ if ( gotoEnd || t >= this.options.duration + this.startTime ) {
+ this.now = this.end;
+ this.pos = this.state = 1;
+ this.update();
+
+ this.options.curAnim[ this.prop ] = true;
+
+ for ( var i in this.options.curAnim ) {
+ if ( this.options.curAnim[i] !== true ) {
+ done = false;
+ }
+ }
+
+ if ( done ) {
+ if ( this.options.display != null ) {
+ // Reset the overflow
+ this.elem.style.overflow = this.options.overflow;
+
+ // Reset the display
+ var old = jQuery.data(this.elem, "olddisplay");
+ this.elem.style.display = old ? old : this.options.display;
+
+ if ( jQuery.css(this.elem, "display") === "none" ) {
+ this.elem.style.display = "block";
+ }
+ }
+
+ // Hide the element if the "hide" operation was done
+ if ( this.options.hide ) {
+ jQuery(this.elem).hide();
+ }
+
+ // Reset the properties, if the item has been hidden or shown
+ if ( this.options.hide || this.options.show ) {
+ for ( var p in this.options.curAnim ) {
+ jQuery.style(this.elem, p, this.options.orig[p]);
+ }
+ }
+
+ // Execute the complete function
+ this.options.complete.call( this.elem );
+ }
+
+ return false;
+
+ } else {
+ var n = t - this.startTime;
+ this.state = n / this.options.duration;
+
+ // Perform the easing function, defaults to swing
+ var specialEasing = this.options.specialEasing && this.options.specialEasing[this.prop];
+ var defaultEasing = this.options.easing || (jQuery.easing.swing ? "swing" : "linear");
+ this.pos = jQuery.easing[specialEasing || defaultEasing](this.state, n, 0, 1, this.options.duration);
+ this.now = this.start + ((this.end - this.start) * this.pos);
+
+ // Perform the next step of the animation
+ this.update();
+ }
+
+ return true;
+ }
+};
+
+jQuery.extend( jQuery.fx, {
+ tick: function() {
+ var timers = jQuery.timers;
+
+ for ( var i = 0; i < timers.length; i++ ) {
+ if ( !timers[i]() ) {
+ timers.splice(i--, 1);
+ }
+ }
+
+ if ( !timers.length ) {
+ jQuery.fx.stop();
+ }
+ },
+
+ stop: function() {
+ clearInterval( timerId );
+ timerId = null;
+ },
+
+ speeds: {
+ slow: 600,
+ fast: 200,
+ // Default speed
+ _default: 400
+ },
+
+ step: {
+ opacity: function( fx ) {
+ jQuery.style(fx.elem, "opacity", fx.now);
+ },
+
+ _default: function( fx ) {
+ if ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) {
+ fx.elem.style[ fx.prop ] = (fx.prop === "width" || fx.prop === "height" ? Math.max(0, fx.now) : fx.now) + fx.unit;
+ } else {
+ fx.elem[ fx.prop ] = fx.now;
+ }
+ }
+ }
+});
+
+if ( jQuery.expr && jQuery.expr.filters ) {
+ jQuery.expr.filters.animated = function( elem ) {
+ return jQuery.grep(jQuery.timers, function( fn ) {
+ return elem === fn.elem;
+ }).length;
+ };
+}
+
+function genFx( type, num ) {
+ var obj = {};
+
+ jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice(0,num)), function() {
+ obj[ this ] = type;
+ });
+
+ return obj;
+}
+if ( "getBoundingClientRect" in document.documentElement ) {
+ jQuery.fn.offset = function( options ) {
+ var elem = this[0];
+
+ if ( options ) {
+ return this.each(function( i ) {
+ jQuery.offset.setOffset( this, options, i );
+ });
+ }
+
+ if ( !elem || !elem.ownerDocument ) {
+ return null;
+ }
+
+ if ( elem === elem.ownerDocument.body ) {
+ return jQuery.offset.bodyOffset( elem );
+ }
+
+ var box = elem.getBoundingClientRect(), doc = elem.ownerDocument, body = doc.body, docElem = doc.documentElement,
+ clientTop = docElem.clientTop || body.clientTop || 0, clientLeft = docElem.clientLeft || body.clientLeft || 0,
+ top = box.top + (self.pageYOffset || jQuery.support.boxModel && docElem.scrollTop || body.scrollTop ) - clientTop,
+ left = box.left + (self.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft) - clientLeft;
+
+ return { top: top, left: left };
+ };
+
+} else {
+ jQuery.fn.offset = function( options ) {
+ var elem = this[0];
+
+ if ( options ) {
+ return this.each(function( i ) {
+ jQuery.offset.setOffset( this, options, i );
+ });
+ }
+
+ if ( !elem || !elem.ownerDocument ) {
+ return null;
+ }
+
+ if ( elem === elem.ownerDocument.body ) {
+ return jQuery.offset.bodyOffset( elem );
+ }
+
+ jQuery.offset.initialize();
+
+ var offsetParent = elem.offsetParent, prevOffsetParent = elem,
+ doc = elem.ownerDocument, computedStyle, docElem = doc.documentElement,
+ body = doc.body, defaultView = doc.defaultView,
+ prevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle,
+ top = elem.offsetTop, left = elem.offsetLeft;
+
+ while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {
+ if ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === "fixed" ) {
+ break;
+ }
+
+ computedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle;
+ top -= elem.scrollTop;
+ left -= elem.scrollLeft;
+
+ if ( elem === offsetParent ) {
+ top += elem.offsetTop;
+ left += elem.offsetLeft;
+
+ if ( jQuery.offset.doesNotAddBorder && !(jQuery.offset.doesAddBorderForTableAndCells && /^t(able|d|h)$/i.test(elem.nodeName)) ) {
+ top += parseFloat( computedStyle.borderTopWidth ) || 0;
+ left += parseFloat( computedStyle.borderLeftWidth ) || 0;
+ }
+
+ prevOffsetParent = offsetParent, offsetParent = elem.offsetParent;
+ }
+
+ if ( jQuery.offset.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" ) {
+ top += parseFloat( computedStyle.borderTopWidth ) || 0;
+ left += parseFloat( computedStyle.borderLeftWidth ) || 0;
+ }
+
+ prevComputedStyle = computedStyle;
+ }
+
+ if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" ) {
+ top += body.offsetTop;
+ left += body.offsetLeft;
+ }
+
+ if ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === "fixed" ) {
+ top += Math.max( docElem.scrollTop, body.scrollTop );
+ left += Math.max( docElem.scrollLeft, body.scrollLeft );
+ }
+
+ return { top: top, left: left };
+ };
+}
+
+jQuery.offset = {
+ initialize: function() {
+ var body = document.body, container = document.createElement("div"), innerDiv, checkDiv, table, td, bodyMarginTop = parseFloat( jQuery.curCSS(body, "marginTop", true) ) || 0,
+ html = "<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";
+
+ jQuery.extend( container.style, { position: "absolute", top: 0, left: 0, margin: 0, border: 0, width: "1px", height: "1px", visibility: "hidden" } );
+
+ container.innerHTML = html;
+ body.insertBefore( container, body.firstChild );
+ innerDiv = container.firstChild;
+ checkDiv = innerDiv.firstChild;
+ td = innerDiv.nextSibling.firstChild.firstChild;
+
+ this.doesNotAddBorder = (checkDiv.offsetTop !== 5);
+ this.doesAddBorderForTableAndCells = (td.offsetTop === 5);
+
+ checkDiv.style.position = "fixed", checkDiv.style.top = "20px";
+ // safari subtracts parent border width here which is 5px
+ this.supportsFixedPosition = (checkDiv.offsetTop === 20 || checkDiv.offsetTop === 15);
+ checkDiv.style.position = checkDiv.style.top = "";
+
+ innerDiv.style.overflow = "hidden", innerDiv.style.position = "relative";
+ this.subtractsBorderForOverflowNotVisible = (checkDiv.offsetTop === -5);
+
+ this.doesNotIncludeMarginInBodyOffset = (body.offsetTop !== bodyMarginTop);
+
+ body.removeChild( container );
+ body = container = innerDiv = checkDiv = table = td = null;
+ jQuery.offset.initialize = jQuery.noop;
+ },
+
+ bodyOffset: function( body ) {
+ var top = body.offsetTop, left = body.offsetLeft;
+
+ jQuery.offset.initialize();
+
+ if ( jQuery.offset.doesNotIncludeMarginInBodyOffset ) {
+ top += parseFloat( jQuery.curCSS(body, "marginTop", true) ) || 0;
+ left += parseFloat( jQuery.curCSS(body, "marginLeft", true) ) || 0;
+ }
+
+ return { top: top, left: left };
+ },
+
+ setOffset: function( elem, options, i ) {
+ // set position first, in-case top/left are set even on static elem
+ if ( /static/.test( jQuery.curCSS( elem, "position" ) ) ) {
+ elem.style.position = "relative";
+ }
+ var curElem = jQuery( elem ),
+ curOffset = curElem.offset(),
+ curTop = parseInt( jQuery.curCSS( elem, "top", true ), 10 ) || 0,
+ curLeft = parseInt( jQuery.curCSS( elem, "left", true ), 10 ) || 0;
+
+ if ( jQuery.isFunction( options ) ) {
+ options = options.call( elem, i, curOffset );
+ }
+
+ var props = {
+ top: (options.top - curOffset.top) + curTop,
+ left: (options.left - curOffset.left) + curLeft
+ };
+
+ if ( "using" in options ) {
+ options.using.call( elem, props );
+ } else {
+ curElem.css( props );
+ }
+ }
+};
+
+
+jQuery.fn.extend({
+ position: function() {
+ if ( !this[0] ) {
+ return null;
+ }
+
+ var elem = this[0],
+
+ // Get *real* offsetParent
+ offsetParent = this.offsetParent(),
+
+ // Get correct offsets
+ offset = this.offset(),
+ parentOffset = /^body|html$/i.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();
+
+ // Subtract element margins
+ // note: when an element has margin: auto the offsetLeft and marginLeft
+ // are the same in Safari causing offset.left to incorrectly be 0
+ offset.top -= parseFloat( jQuery.curCSS(elem, "marginTop", true) ) || 0;
+ offset.left -= parseFloat( jQuery.curCSS(elem, "marginLeft", true) ) || 0;
+
+ // Add offsetParent borders
+ parentOffset.top += parseFloat( jQuery.curCSS(offsetParent[0], "borderTopWidth", true) ) || 0;
+ parentOffset.left += parseFloat( jQuery.curCSS(offsetParent[0], "borderLeftWidth", true) ) || 0;
+
+ // Subtract the two offsets
+ return {
+ top: offset.top - parentOffset.top,
+ left: offset.left - parentOffset.left
+ };
+ },
+
+ offsetParent: function() {
+ return this.map(function() {
+ var offsetParent = this.offsetParent || document.body;
+ while ( offsetParent && (!/^body|html$/i.test(offsetParent.nodeName) && jQuery.css(offsetParent, "position") === "static") ) {
+ offsetParent = offsetParent.offsetParent;
+ }
+ return offsetParent;
+ });
+ }
+});
+
+
+// Create scrollLeft and scrollTop methods
+jQuery.each( ["Left", "Top"], function( i, name ) {
+ var method = "scroll" + name;
+
+ jQuery.fn[ method ] = function(val) {
+ var elem = this[0], win;
+
+ if ( !elem ) {
+ return null;
+ }
+
+ if ( val !== undefined ) {
+ // Set the scroll offset
+ return this.each(function() {
+ win = getWindow( this );
+
+ if ( win ) {
+ win.scrollTo(
+ !i ? val : jQuery(win).scrollLeft(),
+ i ? val : jQuery(win).scrollTop()
+ );
+
+ } else {
+ this[ method ] = val;
+ }
+ });
+ } else {
+ win = getWindow( elem );
+
+ // Return the scroll offset
+ return win ? ("pageXOffset" in win) ? win[ i ? "pageYOffset" : "pageXOffset" ] :
+ jQuery.support.boxModel && win.document.documentElement[ method ] ||
+ win.document.body[ method ] :
+ elem[ method ];
+ }
+ };
+});
+
+function getWindow( elem ) {
+ return ("scrollTo" in elem && elem.document) ?
+ elem :
+ elem.nodeType === 9 ?
+ elem.defaultView || elem.parentWindow :
+ false;
+}
+// Create innerHeight, innerWidth, outerHeight and outerWidth methods
+jQuery.each([ "Height", "Width" ], function( i, name ) {
+
+ var type = name.toLowerCase();
+
+ // innerHeight and innerWidth
+ jQuery.fn["inner" + name] = function() {
+ return this[0] ?
+ jQuery.css( this[0], type, false, "padding" ) :
+ null;
+ };
+
+ // outerHeight and outerWidth
+ jQuery.fn["outer" + name] = function( margin ) {
+ return this[0] ?
+ jQuery.css( this[0], type, false, margin ? "margin" : "border" ) :
+ null;
+ };
+
+ jQuery.fn[ type ] = function( size ) {
+ // Get window width or height
+ var elem = this[0];
+ if ( !elem ) {
+ return size == null ? null : this;
+ }
+
+ if ( jQuery.isFunction( size ) ) {
+ return this.each(function( i ) {
+ var self = jQuery( this );
+ self[ type ]( size.call( this, i, self[ type ]() ) );
+ });
+ }
+
+ return ("scrollTo" in elem && elem.document) ? // does it walk and quack like a window?
+ // Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
+ elem.document.compatMode === "CSS1Compat" && elem.document.documentElement[ "client" + name ] ||
+ elem.document.body[ "client" + name ] :
+
+ // Get document width or height
+ (elem.nodeType === 9) ? // is it a document
+ // Either scroll[Width/Height] or offset[Width/Height], whichever is greater
+ Math.max(
+ elem.documentElement["client" + name],
+ elem.body["scroll" + name], elem.documentElement["scroll" + name],
+ elem.body["offset" + name], elem.documentElement["offset" + name]
+ ) :
+
+ // Get or set width or height on the element
+ size === undefined ?
+ // Get width or height on the element
+ jQuery.css( elem, type ) :
+
+ // Set the width or height on the element (default to pixels if value is unitless)
+ this.css( type, typeof size === "string" ? size : size + "px" );
+ };
+
+});
+// Expose jQuery to the global object
+window.jQuery = window.$ = jQuery;
+
+})(window);
diff --git a/install/ui/jsl.conf b/install/ui/jsl.conf
new file mode 100644
index 000000000..1d7190e43
--- /dev/null
+++ b/install/ui/jsl.conf
@@ -0,0 +1,153 @@
+#
+# Configuration File for JavaScript Lint 0.3.0
+# Developed by Matthias Miller (http://www.JavaScriptLint.com)
+#
+# This configuration file can be used to lint a collection of scripts, or to enable
+# or disable warnings for scripts that are linted via the command line.
+#
+
+### Warnings
+# Enable or disable warnings based on requirements.
+# Use "+WarningName" to display or "-WarningName" to suppress.
+#
++no_return_value # function {0} does not always return a value
++duplicate_formal # duplicate formal argument {0}
++equal_as_assign # test for equality (==) mistyped as assignment (=)?{0}
++var_hides_arg # variable {0} hides argument
++redeclared_var # redeclaration of {0} {1}
++anon_no_return_value # anonymous function does not always return a value
++missing_semicolon # missing semicolon
++meaningless_block # meaningless block; curly braces have no impact
++comma_separated_stmts # multiple statements separated by commas (use semicolons?)
++unreachable_code # unreachable code
++missing_break # missing break statement
++missing_break_for_last_case # missing break statement for last case in switch
++comparison_type_conv # comparisons against null, 0, true, false, or an empty string allowing implicit type conversion (use === or !==)
++inc_dec_within_stmt # increment (++) and decrement (--) operators used as part of greater statement
++useless_void # use of the void type may be unnecessary (void is always undefined)
++multiple_plus_minus # unknown order of operations for successive plus (e.g. x+++y) or minus (e.g. x---y) signs
++use_of_label # use of label
+-block_without_braces # block statement without curly braces
++leading_decimal_point # leading decimal point may indicate a number or an object member
++trailing_decimal_point # trailing decimal point may indicate a number or an object member
++octal_number # leading zeros make an octal number
++nested_comment # nested comment
++misplaced_regex # regular expressions should be preceded by a left parenthesis, assignment, colon, or comma
++ambiguous_newline # unexpected end of line; it is ambiguous whether these lines are part of the same statement
++empty_statement # empty statement or extra semicolon
+-missing_option_explicit # the "option explicit" control comment is missing
++partial_option_explicit # the "option explicit" control comment, if used, must be in the first script tag
++dup_option_explicit # duplicate "option explicit" control comment
++useless_assign # useless assignment
++ambiguous_nested_stmt # block statements containing block statements should use curly braces to resolve ambiguity
++ambiguous_else_stmt # the else statement could be matched with one of multiple if statements (use curly braces to indicate intent)
++missing_default_case # missing default case in switch statement
++duplicate_case_in_switch # duplicate case in switch statements
++default_not_at_end # the default case is not at the end of the switch statement
++legacy_cc_not_understood # couldn't understand control comment using /*@keyword@*/ syntax
++jsl_cc_not_understood # couldn't understand control comment using /*jsl:keyword*/ syntax
++useless_comparison # useless comparison; comparing identical expressions
++with_statement # with statement hides undeclared variables; use temporary variable instead
++trailing_comma_in_array # extra comma is not recommended in array initializers
++assign_to_function_call # assignment to a function call
++parseint_missing_radix # parseInt missing radix parameter
+
+
+### Output format
+# Customize the format of the error message.
+# __FILE__ indicates current file path
+# __FILENAME__ indicates current file name
+# __LINE__ indicates current line
+# __ERROR__ indicates error message
+#
+# Visual Studio syntax (default):
++output-format __FILE__(__LINE__): __ERROR__
+# Alternative syntax:
+#+output-format __FILE__:__LINE__: __ERROR__
+
+
+### Context
+# Show the in-line position of the error.
+# Use "+context" to display or "-context" to suppress.
+#
++context
+
+
+### Semicolons
+# By default, assignments of an anonymous function to a variable or
+# property (such as a function prototype) must be followed by a semicolon.
+#
++lambda_assign_requires_semicolon
+
+
+### Control Comments
+# Both JavaScript Lint and the JScript interpreter confuse each other with the syntax for
+# the /*@keyword@*/ control comments and JScript conditional comments. (The latter is
+# enabled in JScript with @cc_on@). The /*jsl:keyword*/ syntax is preferred for this reason,
+# although legacy control comments are enabled by default for backward compatibility.
+#
++legacy_control_comments
+
+
+### JScript Function Extensions
+# JScript allows member functions to be defined like this:
+# function MyObj() { /*constructor*/ }
+# function MyObj.prototype.go() { /*member function*/ }
+#
+# It also allows events to be attached like this:
+# function window::onload() { /*init page*/ }
+#
+# This is a Microsoft-only JavaScript extension. Enable this setting to allow them.
+#
+-jscript_function_extensions
+
+
+### Defining identifiers
+# By default, "option explicit" is enabled on a per-file basis.
+# To enable this for all files, use "+always_use_option_explicit"
+#-always_use_option_explicit
++always_use_option_explicit
+
+# Define certain identifiers of which the lint is not aware.
+# (Use this in conjunction with the "undeclared identifier" warning.)
+#
+# Common uses for webpages might be:
++define window
+#+define document
++define alert
++define $
++define JSON
+
+### Files
+# Specify which files to lint
+# Use "+recurse" to enable recursion (disabled by default).
+# To add a set of files, use "+process FileName", "+process Folder\Path\*.js",
+# or "+process Folder\Path\*.htm".
+#
++process ipa.js
++process widget.js
++process search.js
++process details.js
++process add.js
++process associate.js
++process entity.js
++process navigation.js
++process rule.js
++process certificate.js
++process user.js
++process group.js
++process hbacrule.js
++process hbacsvc.js
++process hbacsvcgroup.js
++process host.js
++process hostgroup.js
++process netgroup.js
++process service.js
++process serverconfig.js
++process sudorule.js
++process sudocmd.js
++process sudocmdgroup.js
++process policy.js
++process aci.js
++process develop.js
++process webui.js
diff --git a/install/ui/json2.js b/install/ui/json2.js
new file mode 100644
index 000000000..0a4cabb39
--- /dev/null
+++ b/install/ui/json2.js
@@ -0,0 +1,482 @@
+/*
+ http://www.JSON.org/json2.js
+ 2010-03-20
+
+ Public Domain.
+
+ NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+
+ See http://www.JSON.org/js.html
+
+
+ This code should be minified before deployment.
+ See http://javascript.crockford.com/jsmin.html
+
+ USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
+ NOT CONTROL.
+
+
+ This file creates a global JSON object containing two methods: stringify
+ and parse.
+
+ JSON.stringify(value, replacer, space)
+ value any JavaScript value, usually an object or array.
+
+ replacer an optional parameter that determines how object
+ values are stringified for objects. It can be a
+ function or an array of strings.
+
+ space an optional parameter that specifies the indentation
+ of nested structures. If it is omitted, the text will
+ be packed without extra whitespace. If it is a number,
+ it will specify the number of spaces to indent at each
+ level. If it is a string (such as '\t' or '&nbsp;'),
+ it contains the characters used to indent at each level.
+
+ This method produces a JSON text from a JavaScript value.
+
+ When an object value is found, if the object contains a toJSON
+ method, its toJSON method will be called and the result will be
+ stringified. A toJSON method does not serialize: it returns the
+ value represented by the name/value pair that should be serialized,
+ or undefined if nothing should be serialized. The toJSON method
+ will be passed the key associated with the value, and this will be
+ bound to the value
+
+ For example, this would serialize Dates as ISO strings.
+
+ Date.prototype.toJSON = function (key) {
+ function f(n) {
+ // Format integers to have at least two digits.
+ return n < 10 ? '0' + n : n;
+ }
+
+ return this.getUTCFullYear() + '-' +
+ f(this.getUTCMonth() + 1) + '-' +
+ f(this.getUTCDate()) + 'T' +
+ f(this.getUTCHours()) + ':' +
+ f(this.getUTCMinutes()) + ':' +
+ f(this.getUTCSeconds()) + 'Z';
+ };
+
+ You can provide an optional replacer method. It will be passed the
+ key and value of each member, with this bound to the containing
+ object. The value that is returned from your method will be
+ serialized. If your method returns undefined, then the member will
+ be excluded from the serialization.
+
+ If the replacer parameter is an array of strings, then it will be
+ used to select the members to be serialized. It filters the results
+ such that only members with keys listed in the replacer array are
+ stringified.
+
+ Values that do not have JSON representations, such as undefined or
+ functions, will not be serialized. Such values in objects will be
+ dropped; in arrays they will be replaced with null. You can use
+ a replacer function to replace those with JSON values.
+ JSON.stringify(undefined) returns undefined.
+
+ The optional space parameter produces a stringification of the
+ value that is filled with line breaks and indentation to make it
+ easier to read.
+
+ If the space parameter is a non-empty string, then that string will
+ be used for indentation. If the space parameter is a number, then
+ the indentation will be that many spaces.
+
+ Example:
+
+ text = JSON.stringify(['e', {pluribus: 'unum'}]);
+ // text is '["e",{"pluribus":"unum"}]'
+
+
+ text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
+ // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
+
+ text = JSON.stringify([new Date()], function (key, value) {
+ return this[key] instanceof Date ?
+ 'Date(' + this[key] + ')' : value;
+ });
+ // text is '["Date(---current time---)"]'
+
+
+ JSON.parse(text, reviver)
+ This method parses a JSON text to produce an object or array.
+ It can throw a SyntaxError exception.
+
+ The optional reviver parameter is a function that can filter and
+ transform the results. It receives each of the keys and values,
+ and its return value is used instead of the original value.
+ If it returns what it received, then the structure is not modified.
+ If it returns undefined then the member is deleted.
+
+ Example:
+
+ // Parse the text. Values that look like ISO date strings will
+ // be converted to Date objects.
+
+ myData = JSON.parse(text, function (key, value) {
+ var a;
+ if (typeof value === 'string') {
+ a =
+/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
+ if (a) {
+ return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
+ +a[5], +a[6]));
+ }
+ }
+ return value;
+ });
+
+ myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
+ var d;
+ if (typeof value === 'string' &&
+ value.slice(0, 5) === 'Date(' &&
+ value.slice(-1) === ')') {
+ d = new Date(value.slice(5, -1));
+ if (d) {
+ return d;
+ }
+ }
+ return value;
+ });
+
+
+ This is a reference implementation. You are free to copy, modify, or
+ redistribute.
+*/
+
+/*jslint evil: true, strict: false */
+
+/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
+ call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
+ getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
+ lastIndex, length, parse, prototype, push, replace, slice, stringify,
+ test, toJSON, toString, valueOf
+*/
+
+
+// Create a JSON object only if one does not already exist. We create the
+// methods in a closure to avoid creating global variables.
+
+if (!this.JSON) {
+ this.JSON = {};
+}
+
+(function () {
+
+ function f(n) {
+ // Format integers to have at least two digits.
+ return n < 10 ? '0' + n : n;
+ }
+
+ if (typeof Date.prototype.toJSON !== 'function') {
+
+ Date.prototype.toJSON = function (key) {
+
+ return isFinite(this.valueOf()) ?
+ this.getUTCFullYear() + '-' +
+ f(this.getUTCMonth() + 1) + '-' +
+ f(this.getUTCDate()) + 'T' +
+ f(this.getUTCHours()) + ':' +
+ f(this.getUTCMinutes()) + ':' +
+ f(this.getUTCSeconds()) + 'Z' : null;
+ };
+
+ String.prototype.toJSON =
+ Number.prototype.toJSON =
+ Boolean.prototype.toJSON = function (key) {
+ return this.valueOf();
+ };
+ }
+
+ var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
+ escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
+ gap,
+ indent,
+ meta = { // table of character substitutions
+ '\b': '\\b',
+ '\t': '\\t',
+ '\n': '\\n',
+ '\f': '\\f',
+ '\r': '\\r',
+ '"' : '\\"',
+ '\\': '\\\\'
+ },
+ rep;
+
+
+ function quote(string) {
+
+// If the string contains no control characters, no quote characters, and no
+// backslash characters, then we can safely slap some quotes around it.
+// Otherwise we must also replace the offending characters with safe escape
+// sequences.
+
+ escapable.lastIndex = 0;
+ return escapable.test(string) ?
+ '"' + string.replace(escapable, function (a) {
+ var c = meta[a];
+ return typeof c === 'string' ? c :
+ '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
+ }) + '"' :
+ '"' + string + '"';
+ }
+
+
+ function str(key, holder) {
+
+// Produce a string from holder[key].
+
+ var i, // The loop counter.
+ k, // The member key.
+ v, // The member value.
+ length,
+ mind = gap,
+ partial,
+ value = holder[key];
+
+// If the value has a toJSON method, call it to obtain a replacement value.
+
+ if (value && typeof value === 'object' &&
+ typeof value.toJSON === 'function') {
+ value = value.toJSON(key);
+ }
+
+// If we were called with a replacer function, then call the replacer to
+// obtain a replacement value.
+
+ if (typeof rep === 'function') {
+ value = rep.call(holder, key, value);
+ }
+
+// What happens next depends on the value's type.
+
+ switch (typeof value) {
+ case 'string':
+ return quote(value);
+
+ case 'number':
+
+// JSON numbers must be finite. Encode non-finite numbers as null.
+
+ return isFinite(value) ? String(value) : 'null';
+
+ case 'boolean':
+ case 'null':
+
+// If the value is a boolean or null, convert it to a string. Note:
+// typeof null does not produce 'null'. The case is included here in
+// the remote chance that this gets fixed someday.
+
+ return String(value);
+
+// If the type is 'object', we might be dealing with an object or an array or
+// null.
+
+ case 'object':
+
+// Due to a specification blunder in ECMAScript, typeof null is 'object',
+// so watch out for that case.
+
+ if (!value) {
+ return 'null';
+ }
+
+// Make an array to hold the partial results of stringifying this object value.
+
+ gap += indent;
+ partial = [];
+
+// Is the value an array?
+
+ if (Object.prototype.toString.apply(value) === '[object Array]') {
+
+// The value is an array. Stringify every element. Use null as a placeholder
+// for non-JSON values.
+
+ length = value.length;
+ for (i = 0; i < length; i += 1) {
+ partial[i] = str(i, value) || 'null';
+ }
+
+// Join all of the elements together, separated with commas, and wrap them in
+// brackets.
+
+ v = partial.length === 0 ? '[]' :
+ gap ? '[\n' + gap +
+ partial.join(',\n' + gap) + '\n' +
+ mind + ']' :
+ '[' + partial.join(',') + ']';
+ gap = mind;
+ return v;
+ }
+
+// If the replacer is an array, use it to select the members to be stringified.
+
+ if (rep && typeof rep === 'object') {
+ length = rep.length;
+ for (i = 0; i < length; i += 1) {
+ k = rep[i];
+ if (typeof k === 'string') {
+ v = str(k, value);
+ if (v) {
+ partial.push(quote(k) + (gap ? ': ' : ':') + v);
+ }
+ }
+ }
+ } else {
+
+// Otherwise, iterate through all of the keys in the object.
+
+ for (k in value) {
+ if (Object.hasOwnProperty.call(value, k)) {
+ v = str(k, value);
+ if (v) {
+ partial.push(quote(k) + (gap ? ': ' : ':') + v);
+ }
+ }
+ }
+ }
+
+// Join all of the member texts together, separated with commas,
+// and wrap them in braces.
+
+ v = partial.length === 0 ? '{}' :
+ gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' +
+ mind + '}' : '{' + partial.join(',') + '}';
+ gap = mind;
+ return v;
+ }
+ }
+
+// If the JSON object does not yet have a stringify method, give it one.
+
+ if (typeof JSON.stringify !== 'function') {
+ JSON.stringify = function (value, replacer, space) {
+
+// The stringify method takes a value and an optional replacer, and an optional
+// space parameter, and returns a JSON text. The replacer can be a function
+// that can replace values, or an array of strings that will select the keys.
+// A default replacer method can be provided. Use of the space parameter can
+// produce text that is more easily readable.
+
+ var i;
+ gap = '';
+ indent = '';
+
+// If the space parameter is a number, make an indent string containing that
+// many spaces.
+
+ if (typeof space === 'number') {
+ for (i = 0; i < space; i += 1) {
+ indent += ' ';
+ }
+
+// If the space parameter is a string, it will be used as the indent string.
+
+ } else if (typeof space === 'string') {
+ indent = space;
+ }
+
+// If there is a replacer, it must be a function or an array.
+// Otherwise, throw an error.
+
+ rep = replacer;
+ if (replacer && typeof replacer !== 'function' &&
+ (typeof replacer !== 'object' ||
+ typeof replacer.length !== 'number')) {
+ throw new Error('JSON.stringify');
+ }
+
+// Make a fake root object containing our value under the key of ''.
+// Return the result of stringifying the value.
+
+ return str('', {'': value});
+ };
+ }
+
+
+// If the JSON object does not yet have a parse method, give it one.
+
+ if (typeof JSON.parse !== 'function') {
+ JSON.parse = function (text, reviver) {
+
+// The parse method takes a text and an optional reviver function, and returns
+// a JavaScript value if the text is a valid JSON text.
+
+ var j;
+
+ function walk(holder, key) {
+
+// The walk method is used to recursively walk the resulting structure so
+// that modifications can be made.
+
+ var k, v, value = holder[key];
+ if (value && typeof value === 'object') {
+ for (k in value) {
+ if (Object.hasOwnProperty.call(value, k)) {
+ v = walk(value, k);
+ if (v !== undefined) {
+ value[k] = v;
+ } else {
+ delete value[k];
+ }
+ }
+ }
+ }
+ return reviver.call(holder, key, value);
+ }
+
+
+// Parsing happens in four stages. In the first stage, we replace certain
+// Unicode characters with escape sequences. JavaScript handles many characters
+// incorrectly, either silently deleting them, or treating them as line endings.
+
+ text = String(text);
+ cx.lastIndex = 0;
+ if (cx.test(text)) {
+ text = text.replace(cx, function (a) {
+ return '\\u' +
+ ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
+ });
+ }
+
+// In the second stage, we run the text against regular expressions that look
+// for non-JSON patterns. We are especially concerned with '()' and 'new'
+// because they can cause invocation, and '=' because it can cause mutation.
+// But just to be safe, we want to reject all unexpected forms.
+
+// We split the second stage into 4 regexp operations in order to work around
+// crippling inefficiencies in IE's and Safari's regexp engines. First we
+// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
+// replace all simple value tokens with ']' characters. Third, we delete all
+// open brackets that follow a colon or comma or that begin the text. Finally,
+// we look to see that the remaining characters are only whitespace or ']' or
+// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
+
+ if (/^[\],:{}\s]*$/.
+test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').
+replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
+replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
+
+// In the third stage we use the eval function to compile the text into a
+// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
+// in JavaScript: it can begin a block or an object literal. We wrap the text
+// in parens to eliminate the ambiguity.
+
+ j = eval('(' + text + ')');
+
+// In the optional fourth stage, we recursively walk the new structure, passing
+// each name/value pair to a reviver function for possible transformation.
+
+ return typeof reviver === 'function' ?
+ walk({'': j}, '') : j;
+ }
+
+// If the text is not JSON parseable, then a SyntaxError is thrown.
+
+ throw new SyntaxError('JSON.parse');
+ };
+ }
+}());
diff --git a/install/ui/layouts/Makefile.am b/install/ui/layouts/Makefile.am
new file mode 100644
index 000000000..711c236f0
--- /dev/null
+++ b/install/ui/layouts/Makefile.am
@@ -0,0 +1,22 @@
+AUTOMAKE_OPTIONS = 1.7
+
+NULL =
+
+SUBDIRS = \
+ default \
+ $(NULL)
+
+appdir = $(IPA_DATA_DIR)/ui/layouts
+app_DATA = \
+ $(NULL)
+
+EXTRA_DIST = \
+ $(app_DATA) \
+ $(NULL)
+
+MAINTAINERCLEANFILES = \
+ *~ \
+ Makefile.in
+ $(NULL)
+
+distclean:
diff --git a/install/ui/layouts/default/Makefile.am b/install/ui/layouts/default/Makefile.am
new file mode 100644
index 000000000..82a58c7f6
--- /dev/null
+++ b/install/ui/layouts/default/Makefile.am
@@ -0,0 +1,30 @@
+AUTOMAKE_OPTIONS = 1.7
+
+NULL =
+
+SUBDIRS = \
+ $(NULL)
+
+appdir = $(IPA_DATA_DIR)/ui/layouts/default
+app_DATA = \
+ hbacrule-details-accesstime.html \
+ hbacrule-details-general.html \
+ hbacrule-details-host.html \
+ hbacrule-details-service.html \
+ hbacrule-details-sourcehost.html \
+ hbacrule-details-user.html \
+ sudorule-details-general.html \
+ sudorule-group-dialog.html \
+ sudorule-host-dialog.html \
+ sudorule-hostgroup-dialog.html \
+ sudorule-user-dialog.html \
+ $(NULL)
+
+EXTRA_DIST = \
+ $(app_DATA) \
+ $(NULL)
+
+MAINTAINERCLEANFILES = \
+ *~ \
+ Makefile.in
+ $(NULL)
diff --git a/install/ui/layouts/default/hbacrule-details-accesstime.html b/install/ui/layouts/default/hbacrule-details-accesstime.html
new file mode 100755
index 000000000..8d5e258b3
--- /dev/null
+++ b/install/ui/layouts/default/hbacrule-details-accesstime.html
@@ -0,0 +1,49 @@
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <title>When</title>
+
+ <link rel="stylesheet" type="text/css" href="jquery-ui.css" />
+ <link rel="stylesheet" type="text/css" href="ipa.css" />
+</head>
+<body>
+<div id="contents">
+ <span name="accesstime">
+ <span name="text">Rule applies when access is being requested at:</span>
+ <input type="radio" name="accesstime" value="all"/>Any Time
+ <input type="radio" name="accesstime" value=""/>Specified Times
+ <span name="undo" class="ui-state-highlight ui-corner-all" style="display: none;">undo</span>
+ <br/>
+
+ <span name="table">
+ <table class="search-table">
+ <thead>
+ <tr>
+ <th style="width: 25px;">
+ <input type="checkbox" name="select"/>
+ </th>
+ <th>
+ <span style="float: left;">Access Time</span>
+ <span name="buttons" style="float: right;">
+ <input type="button" name="remove" value="Remove Access Times"/>
+ <input type="button" name="add" value="Add Access Times"/>
+ </span>
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>
+ <input type="checkbox" name="select" value="time"/>
+ </td>
+ <td>
+ <span name="accesstime">time</span>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </span>
+ </span>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/install/ui/layouts/default/hbacrule-details-general.html b/install/ui/layouts/default/hbacrule-details-general.html
new file mode 100755
index 000000000..978369090
--- /dev/null
+++ b/install/ui/layouts/default/hbacrule-details-general.html
@@ -0,0 +1,57 @@
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <title>General</title>
+
+ <link rel="stylesheet" type="text/css" href="jquery-ui.css" />
+ <link rel="stylesheet" type="text/css" href="ipa.css" />
+</head>
+<body>
+<div id="contents">
+ <table style="width: 100%; border: 0 solid black;">
+ <tr>
+ <td style="width: 100px; text-align: right;">
+ Name:
+ </td>
+ <td>
+ <span name="cn">
+ <input type="text" name="cn" size="30"/>
+ <span name="undo" class="ui-state-highlight ui-corner-all" style="display: none;">undo</span>
+ </span>
+ </td>
+ <td style="text-align: right;">
+ Rule type:
+ <span name="accessruletype">
+ <input type="radio" name="accessruletype" value="allow"/>Allow
+ <input type="radio" name="accessruletype" value="deny"/>Deny
+ <span name="undo" class="ui-state-highlight ui-corner-all" style="display: none;">undo</span>
+ </span>
+ </td>
+ </tr>
+ <tr>
+ <td style="text-align: right; vertical-align: top;">
+ Description:
+ </td>
+ <td colspan="2">
+ <span name="description">
+ <textarea name="description" rows="5" style="width: 100%;" cols="40"></textarea>
+ <span name="undo" class="ui-state-highlight ui-corner-all" style="display: none;">undo</span>
+ </span>
+ </td>
+ </tr>
+ <tr>
+ <td style="text-align: right; vertical-align: top;">
+ Rule status:
+ </td>
+ <td colspan="2">
+ <span name="ipaenabledflag">
+ <input type="radio" name="ipaenabledflag" value="TRUE"/>Active
+ <input type="radio" name="ipaenabledflag" value="FALSE"/>Inactive
+ <span name="undo" class="ui-state-highlight ui-corner-all" style="display: none;">undo</span>
+ </span>
+ </td>
+ </tr>
+ </table>
+</div>
+</body>
+</html>
diff --git a/install/ui/layouts/default/hbacrule-details-host.html b/install/ui/layouts/default/hbacrule-details-host.html
new file mode 100755
index 000000000..1ba386dab
--- /dev/null
+++ b/install/ui/layouts/default/hbacrule-details-host.html
@@ -0,0 +1,78 @@
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <title>Accessing</title>
+
+ <link rel="stylesheet" type="text/css" href="jquery-ui.css" />
+ <link rel="stylesheet" type="text/css" href="ipa.css" />
+</head>
+<body>
+<div id="contents">
+ Rule applies when access is requested to:
+ <span name="hostcategory">
+ <input type="radio" name="hostcategory" value="all"/>Any Host
+ <input type="radio" name="hostcategory" value=""/>Specified Hosts and Groups
+ <span name="undo" class="ui-state-highlight ui-corner-all" style="display: none;">undo</span>
+ </span>
+ <br/>
+
+ <span name="memberhost_host">
+ <table class="search-table">
+ <thead>
+ <tr>
+ <th style="width: 25px;">
+ <input type="checkbox" name="select"/>
+ </th>
+ <th>
+ <span style="float: left;">Host</span>
+ <span name="buttons" style="float: right;">
+ <input type="button" name="remove" value="Remove Hosts"/>
+ <input type="button" name="add" value="Add Hosts"/>
+ </span>
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>
+ <input type="checkbox" name="select" value="host"/>
+ </td>
+ <td>
+ <span name="memberhost_host">host</span>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </span>
+
+ <span name="memberhost_hostgroup">
+ <table class="search-table">
+ <thead>
+ <tr>
+ <th style="width: 25px;">
+ <input type="checkbox" name="select"/>
+ </th>
+ <th>
+ <span style="float: left;">Host Group</span>
+ <span name="buttons" style="float: right;">
+ <input type="button" name="remove" value="Remove Host Groups"/>
+ <input type="button" name="add" value="Add Host Groups"/>
+ </span>
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>
+ <input type="checkbox" name="select" value="hostgroups"/>
+ </td>
+ <td>
+ <span name="memberhost_hostgroup">hostgroups</span>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </span>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/install/ui/layouts/default/hbacrule-details-service.html b/install/ui/layouts/default/hbacrule-details-service.html
new file mode 100755
index 000000000..77e8420d3
--- /dev/null
+++ b/install/ui/layouts/default/hbacrule-details-service.html
@@ -0,0 +1,78 @@
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <title>Via Service</title>
+
+ <link rel="stylesheet" type="text/css" href="jquery-ui.css" />
+ <link rel="stylesheet" type="text/css" href="ipa.css" />
+</head>
+<body>
+<div id="contents">
+ Rule applies when access is requested via:
+ <span name="servicecategory">
+ <input type="radio" name="servicecategory" value="all"/>Any Service
+ <input type="radio" name="servicecategory" value=""/>Specified Services and Groups
+ <span name="undo" class="ui-state-highlight ui-corner-all" style="display: none;">undo</span>
+ </span>
+ <br/>
+
+ <span name="memberservice_hbacsvc">
+ <table class="search-table">
+ <thead>
+ <tr>
+ <th style="width: 25px;">
+ <input type="checkbox" name="select"/>
+ </th>
+ <th>
+ <span style="float: left;">Service</span>
+ <span name="buttons" style="float: right;">
+ <input type="button" name="remove" value="Remove Services"/>
+ <input type="button" name="add" value="Add Services"/>
+ </span>
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>
+ <input type="checkbox" name="select" value="service"/>
+ </td>
+ <td>
+ <span name="memberservice_hbacsvc">service</span>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </span>
+
+ <span name="memberservice_hbacsvcgroup">
+ <table class="search-table">
+ <thead>
+ <tr>
+ <th style="width: 25px;">
+ <input type="checkbox" name="select"/>
+ </th>
+ <th>
+ <span style="float: left;">Service Group</span>
+ <span name="buttons" style="float: right;">
+ <input type="button" name="remove" value="Remove Service Groups"/>
+ <input type="button" name="add" value="Add Service Groups"/>
+ </span>
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>
+ <input type="checkbox" name="select" value="services"/>
+ </td>
+ <td>
+ <span name="memberservice_hbacsvcgroup">services</span>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </span>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/install/ui/layouts/default/hbacrule-details-sourcehost.html b/install/ui/layouts/default/hbacrule-details-sourcehost.html
new file mode 100755
index 000000000..aae1ef380
--- /dev/null
+++ b/install/ui/layouts/default/hbacrule-details-sourcehost.html
@@ -0,0 +1,78 @@
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <title>From</title>
+
+ <link rel="stylesheet" type="text/css" href="jquery-ui.css" />
+ <link rel="stylesheet" type="text/css" href="ipa.css" />
+</head>
+<body>
+<div id="contents">
+ Rule applies when access is being initiated from:
+ <span name="sourcehostcategory">
+ <input type="radio" name="sourcehostcategory" value="all"/>Any Host
+ <input type="radio" name="sourcehostcategory" value=""/>Specified Hosts and Groups
+ <span name="undo" class="ui-state-highlight ui-corner-all" style="display: none;">undo</span>
+ </span>
+ <br/>
+
+ <span name="sourcehost_host">
+ <table class="search-table">
+ <thead>
+ <tr>
+ <th style="width: 25px;">
+ <input type="checkbox" name="select"/>
+ </th>
+ <th>
+ <span style="float: left;">Host</span>
+ <span name="buttons" style="float: right;">
+ <input type="button" name="remove" value="Remove Hosts"/>
+ <input type="button" name="add" value="Add Hosts"/>
+ </span>
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>
+ <input type="checkbox" name="select" value="host"/>
+ </td>
+ <td>
+ <span name="sourcehost_host">host</span>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </span>
+
+ <span name="sourcehost_hostgroup">
+ <table class="search-table">
+ <thead>
+ <tr>
+ <th style="width: 25px;">
+ <input type="checkbox" name="select"/>
+ </th>
+ <th>
+ <span style="float: left;">Host Group</span>
+ <span name="buttons" style="float: right;">
+ <input type="button" name="remove" value="Remove Host Groups"/>
+ <input type="button" name="add" value="Add Host Groups"/>
+ </span>
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>
+ <input type="checkbox" name="select" value="hosts"/>
+ </td>
+ <td>
+ <span name="sourcehost_hostgroup">hosts</span>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </span>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/install/ui/layouts/default/hbacrule-details-user.html b/install/ui/layouts/default/hbacrule-details-user.html
new file mode 100755
index 000000000..1b58848fe
--- /dev/null
+++ b/install/ui/layouts/default/hbacrule-details-user.html
@@ -0,0 +1,78 @@
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <title>Who</title>
+
+ <link rel="stylesheet" type="text/css" href="jquery-ui.css" />
+ <link rel="stylesheet" type="text/css" href="ipa.css" />
+</head>
+<body>
+<div id="contents">
+ Rule applies when access is requested by:
+ <span name="usercategory">
+ <input type="radio" name="usercategory" value="all"/>Anyone
+ <input type="radio" name="usercategory" value=""/>Specified Users and Groups
+ <span name="undo" class="ui-state-highlight ui-corner-all" style="display: none;">undo</span>
+ </span>
+ <br/>
+
+ <span name="memberuser_user">
+ <table class="search-table">
+ <thead>
+ <tr>
+ <th style="width: 25px;">
+ <input type="checkbox" name="select"/>
+ </th>
+ <th>
+ <span style="float: left;">User</span>
+ <span name="buttons" style="float: right;">
+ <input type="button" name="remove" value="Remove Users"/>
+ <input type="button" name="add" value="Add Users"/>
+ </span>
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>
+ <input type="checkbox" name="select" value="user"/>
+ </td>
+ <td>
+ <span name="memberuser_user">user</span>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </span>
+
+ <span name="memberuser_group">
+ <table class="search-table">
+ <thead>
+ <tr>
+ <th style="width: 25px;">
+ <input type="checkbox" name="select"/>
+ </th>
+ <th>
+ <span style="float: left;">User Group</span>
+ <span name="buttons" style="float: right;">
+ <input type="button" name="remove" value="Remove User Groups"/>
+ <input type="button" name="add" value="Add User Groups"/>
+ </span>
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>
+ <input type="checkbox" name="select" value="users"/>
+ </td>
+ <td>
+ <span name="memberuser_group">users</span>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </span>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/install/ui/layouts/default/sudorule-details-general.html b/install/ui/layouts/default/sudorule-details-general.html
new file mode 100755
index 000000000..728ecf11e
--- /dev/null
+++ b/install/ui/layouts/default/sudorule-details-general.html
@@ -0,0 +1,49 @@
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <title>General</title>
+
+ <link rel="stylesheet" type="text/css" href="jquery-ui.css" />
+ <link rel="stylesheet" type="text/css" href="ipa.css" />
+</head>
+<body>
+<div id="contents">
+ <table style="width: 100%; border: 0 solid black;">
+ <tr>
+ <td style="width: 100px; text-align: right;">
+ Name:
+ </td>
+ <td>
+ <span name="cn">
+ <input type="text" name="cn" size="30"/>
+ <span name="undo" class="ui-state-highlight ui-corner-all" style="display: none;">undo</span>
+ </span>
+ </td>
+ </tr>
+ <tr>
+ <td style="text-align: right; vertical-align: top;">
+ Description:
+ </td>
+ <td>
+ <span name="description">
+ <textarea name="description" rows="5" style="width: 100%;" cols="40"></textarea>
+ <span name="undo" class="ui-state-highlight ui-corner-all" style="display: none;">undo</span>
+ </span>
+ </td>
+ </tr>
+ <tr>
+ <td style="text-align: right; vertical-align: top;">
+ Rule status:
+ </td>
+ <td>
+ <span name="ipaenabledflag">
+ <input type="radio" name="ipaenabledflag" value="TRUE"/>Active
+ <input type="radio" name="ipaenabledflag" value="FALSE"/>Inactive
+ <span name="undo" class="ui-state-highlight ui-corner-all" style="display: none;">undo</span>
+ </span>
+ </td>
+ </tr>
+ </table>
+</div>
+</body>
+</html>
diff --git a/install/ui/layouts/default/sudorule-group-dialog.html b/install/ui/layouts/default/sudorule-group-dialog.html
new file mode 100755
index 000000000..d576f1a1f
--- /dev/null
+++ b/install/ui/layouts/default/sudorule-group-dialog.html
@@ -0,0 +1,110 @@
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <title>Adder Dialog</title>
+
+ <link rel="stylesheet" type="text/css" href="../../jquery-ui.css" />
+ <link rel="stylesheet" type="text/css" href="../../ipa.css" />
+</head>
+<body>
+<div id="contents">
+
+ <div class="adder-dialog-filter">
+ <input type="text" name="filter" style="width: 244px">
+ <input type="button" name="find" value="Find">
+ </div>
+
+ <div class="adder-dialog-results">
+
+ <div name="available" class="adder-dialog-internal">
+
+ <div class="ui-widget-header">
+ Available
+ </div>
+
+ <table class="search-table scrollable">
+ <thead>
+ <tr>
+ <th style="width: 22px;">
+ <input type="checkbox" name="select">
+ </th>
+ <th style="width: 216px;">
+ Groups
+ </th>
+ </tr>
+ </thead>
+ <tbody style="height: 106px;">
+ <tr>
+ <td style="width: 22px;">
+ <input type="checkbox" name="select">
+ </td>
+ <td style="width: 200px;">
+ <span name="cn"></span>
+ </td>
+ </tr>
+ </tbody>
+ <tfoot>
+ <tr>
+ <td colspan="2">
+ <span name="summary"></span>
+ </td>
+ </tr>
+ </tfoot>
+ </table>
+ </div>
+
+ <div name="buttons" class="adder-dialog-buttons">
+ <p><input type="button" name="remove" value="<<"></p>
+ <p><input type="button" name="add" value=">>"></p>
+ </div>
+
+ <div name="selected" class="adder-dialog-selected">
+
+ <div class="ui-widget-header">
+ Prospective
+ </div>
+
+ <table class="search-table scrollable">
+ <thead>
+ <tr>
+ <th style="width: 22px;">
+ <input type="checkbox" name="select">
+ </th>
+ <th style="width: 216px;">
+ Groups
+ </th>
+ </tr>
+ </thead>
+ <tbody style="height: 151px;">
+ <tr>
+ <td style="width: 22px;">
+ <input type="checkbox" name="select">
+ </td>
+ <td style="width: 200px;">
+ <span name="cn"></span>
+ </td>
+ </tr>
+ </tbody>
+ <tfoot>
+ <tr>
+ <td colspan="2">
+ <span name="summary"></span>
+ </td>
+ </tr>
+ </tfoot>
+ </table>
+ </div>
+
+ <div name="external" class="adder-dialog-external">
+
+ <div class="ui-widget-header">
+ External
+ </div>
+
+ <input type="text" name="external" style="width: 244px">
+ </div>
+
+ </div>
+</div>
+</body>
+</html>
diff --git a/install/ui/layouts/default/sudorule-host-dialog.html b/install/ui/layouts/default/sudorule-host-dialog.html
new file mode 100755
index 000000000..5eec41868
--- /dev/null
+++ b/install/ui/layouts/default/sudorule-host-dialog.html
@@ -0,0 +1,110 @@
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <title>Adder Dialog</title>
+
+ <link rel="stylesheet" type="text/css" href="../../jquery-ui.css" />
+ <link rel="stylesheet" type="text/css" href="../../ipa.css" />
+</head>
+<body>
+<div id="contents">
+
+ <div class="adder-dialog-filter">
+ <input type="text" name="filter" style="width: 244px">
+ <input type="button" name="find" value="Find">
+ </div>
+
+ <div class="adder-dialog-results">
+
+ <div name="available" class="adder-dialog-internal">
+
+ <div class="ui-widget-header">
+ Available
+ </div>
+
+ <table class="search-table scrollable">
+ <thead>
+ <tr>
+ <th style="width: 22px;">
+ <input type="checkbox" name="select">
+ </th>
+ <th style="width: 216px;">
+ Hosts
+ </th>
+ </tr>
+ </thead>
+ <tbody style="height: 106px;">
+ <tr>
+ <td style="width: 22px;">
+ <input type="checkbox" name="select">
+ </td>
+ <td style="width: 200px;">
+ <span name="fqdn"></span>
+ </td>
+ </tr>
+ </tbody>
+ <tfoot>
+ <tr>
+ <td colspan="2">
+ <span name="summary"></span>
+ </td>
+ </tr>
+ </tfoot>
+ </table>
+ </div>
+
+ <div name="buttons" class="adder-dialog-buttons">
+ <p><input type="button" name="remove" value="<<"></p>
+ <p><input type="button" name="add" value=">>"></p>
+ </div>
+
+ <div name="selected" class="adder-dialog-selected">
+
+ <div class="ui-widget-header">
+ Prospective
+ </div>
+
+ <table class="search-table scrollable">
+ <thead>
+ <tr>
+ <th style="width: 22px;">
+ <input type="checkbox" name="select">
+ </th>
+ <th style="width: 216px;">
+ Hosts
+ </th>
+ </tr>
+ </thead>
+ <tbody style="height: 151px;">
+ <tr>
+ <td style="width: 22px;">
+ <input type="checkbox" name="select">
+ </td>
+ <td style="width: 200px;">
+ <span name="fqdn"></span>
+ </td>
+ </tr>
+ </tbody>
+ <tfoot>
+ <tr>
+ <td colspan="2">
+ <span name="summary"></span>
+ </td>
+ </tr>
+ </tfoot>
+ </table>
+ </div>
+
+ <div name="external" class="adder-dialog-external">
+
+ <div class="ui-widget-header">
+ External
+ </div>
+
+ <input type="text" name="external" style="width: 244px">
+ </div>
+
+ </div>
+</div>
+</body>
+</html>
diff --git a/install/ui/layouts/default/sudorule-hostgroup-dialog.html b/install/ui/layouts/default/sudorule-hostgroup-dialog.html
new file mode 100755
index 000000000..57d72f387
--- /dev/null
+++ b/install/ui/layouts/default/sudorule-hostgroup-dialog.html
@@ -0,0 +1,110 @@
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <title>Adder Dialog</title>
+
+ <link rel="stylesheet" type="text/css" href="../../jquery-ui.css" />
+ <link rel="stylesheet" type="text/css" href="../../ipa.css" />
+</head>
+<body>
+<div id="contents">
+
+ <div class="adder-dialog-filter">
+ <input type="text" name="filter" style="width: 244px">
+ <input type="button" name="find" value="Find">
+ </div>
+
+ <div class="adder-dialog-results">
+
+ <div name="available" class="adder-dialog-internal">
+
+ <div class="ui-widget-header">
+ Available
+ </div>
+
+ <table class="search-table scrollable">
+ <thead>
+ <tr>
+ <th style="width: 22px;">
+ <input type="checkbox" name="select">
+ </th>
+ <th style="width: 216px;">
+ Host Groups
+ </th>
+ </tr>
+ </thead>
+ <tbody style="height: 106px;">
+ <tr>
+ <td style="width: 22px;">
+ <input type="checkbox" name="select">
+ </td>
+ <td style="width: 200px;">
+ <span name="cn"></span>
+ </td>
+ </tr>
+ </tbody>
+ <tfoot>
+ <tr>
+ <td colspan="2">
+ <span name="summary"></span>
+ </td>
+ </tr>
+ </tfoot>
+ </table>
+ </div>
+
+ <div name="buttons" class="adder-dialog-buttons">
+ <p><input type="button" name="remove" value="<<"></p>
+ <p><input type="button" name="add" value=">>"></p>
+ </div>
+
+ <div name="selected" class="adder-dialog-selected">
+
+ <div class="ui-widget-header">
+ Prospective
+ </div>
+
+ <table class="search-table scrollable">
+ <thead>
+ <tr>
+ <th style="width: 22px;">
+ <input type="checkbox" name="select">
+ </th>
+ <th style="width: 216px;">
+ Host Groups
+ </th>
+ </tr>
+ </thead>
+ <tbody style="height: 151px;">
+ <tr>
+ <td style="width: 22px;">
+ <input type="checkbox" name="select">
+ </td>
+ <td style="width: 200px;">
+ <span name="cn"></span>
+ </td>
+ </tr>
+ </tbody>
+ <tfoot>
+ <tr>
+ <td colspan="2">
+ <span name="summary"></span>
+ </td>
+ </tr>
+ </tfoot>
+ </table>
+ </div>
+
+ <div name="external" class="adder-dialog-external">
+
+ <div class="ui-widget-header">
+ External
+ </div>
+
+ <input type="text" name="external" style="width: 244px">
+ </div>
+
+ </div>
+</div>
+</body>
+</html>
diff --git a/install/ui/layouts/default/sudorule-user-dialog.html b/install/ui/layouts/default/sudorule-user-dialog.html
new file mode 100755
index 000000000..78687cead
--- /dev/null
+++ b/install/ui/layouts/default/sudorule-user-dialog.html
@@ -0,0 +1,110 @@
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <title>Adder Dialog</title>
+
+ <link rel="stylesheet" type="text/css" href="../../jquery-ui.css" />
+ <link rel="stylesheet" type="text/css" href="../../ipa.css" />
+</head>
+<body>
+<div id="contents">
+
+ <div class="adder-dialog-filter">
+ <input type="text" name="filter" style="width: 244px">
+ <input type="button" name="find" value="Find">
+ </div>
+
+ <div class="adder-dialog-results">
+
+ <div name="available" class="adder-dialog-internal">
+
+ <div class="ui-widget-header">
+ Available
+ </div>
+
+ <table class="search-table scrollable">
+ <thead style="display: block;">
+ <tr>
+ <th style="width: 22px;">
+ <input type="checkbox" name="select">
+ </th>
+ <th style="width: 216px;">
+ Users
+ </th>
+ </tr>
+ </thead>
+ <tbody style="height: 106px;">
+ <tr>
+ <td style="width: 22px;">
+ <input type="checkbox" name="select">
+ </td>
+ <td style="width: 200px;">
+ <span name="uid"></span>
+ </td>
+ </tr>
+ </tbody>
+ <tfoot>
+ <tr>
+ <td colspan="2">
+ <span name="summary"></span>
+ </td>
+ </tr>
+ </tfoot>
+ </table>
+ </div>
+
+ <div name="buttons" class="adder-dialog-buttons">
+ <p><input type="button" name="remove" value="<<"></p>
+ <p><input type="button" name="add" value=">>"></p>
+ </div>
+
+ <div name="selected" class="adder-dialog-selected">
+
+ <div class="ui-widget-header">
+ Prospective
+ </div>
+
+ <table class="search-table scrollable">
+ <thead>
+ <tr>
+ <th style="width: 22px;">
+ <input type="checkbox" name="select">
+ </th>
+ <th style="width: 216px;">
+ Users
+ </th>
+ </tr>
+ </thead>
+ <tbody style="height: 151px;">
+ <tr>
+ <td style="width: 22px;">
+ <input type="checkbox" name="select">
+ </td>
+ <td style="width: 200px;">
+ <span name="uid"></span>
+ </td>
+ </tr>
+ </tbody>
+ <tfoot>
+ <tr>
+ <td colspan="2">
+ <span name="summary"></span>
+ </td>
+ </tr>
+ </tfoot>
+ </table>
+ </div>
+
+ <div name="external" class="adder-dialog-external">
+
+ <div class="ui-widget-header">
+ External
+ </div>
+
+ <input type="text" name="external" style="width: 244px">
+ </div>
+
+ </div>
+</div>
+</body>
+</html>
diff --git a/install/ui/modal-background.png b/install/ui/modal-background.png
new file mode 100644
index 000000000..605d82207
--- /dev/null
+++ b/install/ui/modal-background.png
Binary files differ
diff --git a/install/ui/navigation.js b/install/ui/navigation.js
new file mode 100644
index 000000000..7ae5b656e
--- /dev/null
+++ b/install/ui/navigation.js
@@ -0,0 +1,149 @@
+/*jsl:import ipa.js */
+
+/* Authors:
+ * Pavel Zuna <pzuna@redhat.com>
+ *
+ * Copyright (C) 2010 Red Hat
+ * see file 'COPYING' for use and warranty information
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+var nav_tabs_lists;
+var nav_container;
+
+function nav_push_state(params)
+{
+ $.bbq.pushState(params);
+}
+
+function nav_get_state(key)
+{
+ return $.bbq.getState(key, true);
+}
+
+function nav_remove_state(key)
+{
+ $.bbq.removeState(key);
+}
+
+function nav_create(nls, container, tabclass)
+{
+ if (!container)
+ container = $('#navigation');
+ if (!tabclass)
+ tabclass = 'tabs';
+
+ nav_tabs_lists = nls;
+ nav_container = container;
+
+ nav_generate_tabs(nls, container, tabclass, 1);
+
+ var tabs = $('.' + tabclass);
+ tabs.tabs({
+ select: function(event, ui) {
+ var panel = $(ui.panel);
+ var parent = panel.parent();
+ var id = parent.attr('id');
+ var state = {};
+ state[id] = ui.index;
+ nav_push_state(state);
+ return true;
+ }
+ });
+
+ nav_update_tabs();
+}
+
+function nav_generate_tabs(nls, container, tabclass, depth)
+{
+ container.addClass(tabclass);
+ container.addClass('tabs'+depth);
+
+ var ul = $('<ul/>');
+ container.append(ul);
+
+ for (var i = 0; i < nls.length; ++i) {
+ var tab = nls[i];
+
+ var label = tab.name;
+ if (tab.entity) {
+ var entity = IPA.get_entity(tab.entity);
+ label = entity.label;
+ }
+
+ var li = nav_create_tab_li(tab.name, label);
+ ul.append(li);
+
+ var div = nav_create_tab_div(tab.name);
+ container.append(div);
+
+ if (tab.entity) {
+ div.addClass('entity-container');
+ }
+
+ if (tab.children && depth === 1) {
+ nav_generate_tabs(tab.children, div, tabclass, depth +1 );
+ }
+ }
+}
+
+function nav_create_tab_li(id, name)
+{
+ return $('<li/>').append($('<a/>', {
+ href: '#'+id,
+ title: id,
+ html: name
+ }));
+}
+
+function nav_create_tab_div(id)
+{
+ return $('<div/>', {
+ id: id
+ });
+}
+
+function nav_update_tabs()
+{
+ _nav_update_tabs(nav_tabs_lists, nav_container,1);
+}
+
+function _nav_update_tabs(nls, container,depth)
+{
+ var id = container.attr('id');
+ var index = nav_get_state(id);
+ if (!index || index >= nls.length) index = 0;
+
+ container.tabs('select', index);
+
+ var tab = nls[index];
+ var container2 = $('#' + tab.name);
+
+ if (tab.children && depth === 1 ) {
+ _nav_update_tabs(tab.children, container2,depth+1);
+
+ } else if (tab.entity) {
+ var entity_name = tab.entity;
+
+ var nested_entity = nav_get_state(entity_name+'-entity');
+
+ if (nested_entity){
+ entity_name = nested_entity;
+ }
+
+ var entity = IPA.get_entity(entity_name);
+ entity.setup(container2);
+ }
+}
diff --git a/install/ui/netgroup.js b/install/ui/netgroup.js
new file mode 100644
index 000000000..205673514
--- /dev/null
+++ b/install/ui/netgroup.js
@@ -0,0 +1,67 @@
+/*jsl:import ipa.js */
+
+/* Authors:
+ * Pavel Zuna <pzuna@redhat.com>
+ *
+ * Copyright (C) 2010 Red Hat
+ * see file 'COPYING' for use and warranty information
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* REQUIRES: ipa.js, details.js, search.js, add.js, entity.js */
+
+IPA.add_entity( function() {
+ var that = IPA.entity({
+ 'name': 'netgroup'
+ });
+ that.init = function() {
+ var search_facet = IPA.search_facet({
+ name: 'search',
+ label: 'Search',
+ entity_name: that.name
+ });
+ search_facet.create_column({name:'cn'});
+ search_facet.create_column({name:'description'});
+ that.add_facet(search_facet);
+
+ that.add_facet(function() {
+ var that = IPA.details_facet({name:'details'});
+ that.add_section(
+ IPA.stanza({name:'identity', label:'Netgroup Settings'}).
+ input({name:'cn'}).
+ input({name: 'description'}).
+ input({name:'nisdomainname'}));
+ return that;
+ }());
+
+
+ var dialog = IPA.add_dialog({
+ name: 'add',
+ title: 'Add Netgroup'
+ });
+ that.add_dialog(dialog);
+
+ dialog.add_field(IPA.text_widget({ name: 'cn', undo: false}));
+ dialog.add_field(IPA.text_widget({ name: 'description', undo: false}));
+ dialog.init();
+
+ that.create_association_facets();
+ that.entity_init();
+ };
+ return that;
+}());
+
+
+
diff --git a/install/ui/outer-bg.png b/install/ui/outer-bg.png
new file mode 100644
index 000000000..a6f81d644
--- /dev/null
+++ b/install/ui/outer-bg.png
Binary files differ
diff --git a/install/ui/panel-background.png b/install/ui/panel-background.png
new file mode 100644
index 000000000..9f9f4d69c
--- /dev/null
+++ b/install/ui/panel-background.png
Binary files differ
diff --git a/install/ui/policy.js b/install/ui/policy.js
new file mode 100644
index 000000000..eeec44e35
--- /dev/null
+++ b/install/ui/policy.js
@@ -0,0 +1,599 @@
+/*jsl:import ipa.js */
+/*jsl:import search.js */
+
+/* Authors:
+ * Adam Young <ayoung@redhat.com>
+ *
+ * Copyright (C) 2010 Red Hat
+ * see file 'COPYING' for use and warranty information
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* REQUIRES: ipa.js, details.js, search.js, add.js, entity.js */
+
+/* DNS */
+
+IPA.add_entity(function (){
+ var that = IPA.entity({
+ name: 'dnszone'
+ });
+
+ that.init = function() {
+ var search_facet = IPA.search_facet({
+ name: 'search',
+ label: 'Search',
+ entity_name: that.name
+ });
+ search_facet.create_column({name:'idnsname'});
+ that.add_facet(search_facet);
+
+ that.add_facet(function() {
+ var that = IPA.details_facet({name:'details'});
+ that.add_section(
+ IPA.stanza({name:'identity', label:'DNS Zone Settings'}).
+ input({name:'idnsname'}).
+ input({name:'idnszoneactive'}).
+ input({name:'idnssoamname'}).
+ input({name:'idnssoarname'}).
+ input({name:'idnssoaserial'}).
+ input({name:'idnssoarefresh'}).
+ input({name:'idnssoaretry'}).
+ input({name:'idnssoaexpire'}).
+ input({name:'idnssoaminimum'}).
+ input({name:'dnsttl'}).
+ input({name:'dnsclass'}).
+ input({name:'idnsallowdynupdate'}).
+ input({name:'idnsupdatepolicy'}));
+
+ return that;
+ }());
+
+ that.add_facet( IPA.records_facet({
+ 'name': 'records',
+ 'label': IPA.metadata.dnsrecord.label
+ }));
+
+ var dialog = IPA.add_dialog({
+ name: 'add',
+ title: 'Add DNS Zone'
+ });
+ that.add_dialog(dialog);
+
+ dialog.add_field(IPA.text_widget({ name: 'idnsname', undo: false}));
+ dialog.add_field(IPA.text_widget({ name: 'idnssoamname', undo: false}));
+ dialog.add_field(IPA.text_widget({ name: 'idnssoarname', undo: false}));
+ dialog.init();
+
+ that.create_association_facets();
+ that.entity_init();
+ };
+
+
+ return that;
+}());
+
+
+IPA.records_facet = function (spec){
+
+ spec = spec || {};
+
+ var that = IPA.facet(spec);
+
+ that.record = null;
+
+ var record_types =[ 'a', 'aaaa', 'dname', 'cname', 'mx', 'ns', 'ptr',
+ 'srv', 'txt', 'a6', 'afsdb', 'cert', 'ds', 'hinfo',
+ 'key', 'kx', 'loc', 'md', 'minfo', 'naptr', 'nsec',
+ 'nxt', 'rrsig', 'sshfp'];
+
+ function create_type_select(id,add_none) {
+ var type_select = $('<select/>',{
+ id: id
+ });
+
+ if (add_none){
+ type_select.append($('<option/>',{
+ text: '(any)',
+ value: ''
+ }));
+ }
+ for (var t = 0 ; t < record_types.length ; t += 1){
+ var record_type = record_types[t].toUpperCase();
+
+ type_select.append($('<option/>',{
+ text: record_type,
+ value: record_type
+ }));
+ }
+ return type_select;
+ }
+
+
+ var entry_attrs = {};
+
+
+ function add_click(){
+
+ var add_dialog = $('<div/>',{
+ id: 'add_dns_resource_record',
+ title: 'Add DNS Resource Record'
+ });
+ var dl = $('<dl></dl>').appendTo(add_dialog);
+ dl.append('<dt>Resource</dt>');
+ dl.append( $('<dd/>').
+ append($('<input type="text" id="dns-record-resource" />')));
+ dl.append('<dt>Type</dt>');
+ dl.append( $('<dd/>').append(create_type_select('dns-record-type')));
+ dl.append('<dt>Data</dt>');
+ dl.append($('<dd/>').append($('<textarea/>',{
+ id: 'dns-record-data',
+ rows:"8",
+ cols:"20"
+ })));
+
+
+ function add(evt, called_from_add_and_edit) {
+ var params = [];
+ var options = {};
+ function add_win(data, text_status, xhr) {
+ reload();
+ }
+
+ function add_fail(data, text_status, xhr) {
+ }
+
+ params.push( $.bbq.getState(that.entity_name+'-pkey', true));
+ params.push(add_dialog.find('#dns-record-resource').val());
+
+ var key = add_dialog.find('#dns-record-type').val().toLowerCase()+
+ "record";
+ var value = add_dialog.find('#dns-record-data').val();
+ options[key] = value;
+
+
+ IPA.cmd('dnsrecord_add', params, options, add_win, add_fail);
+ //add_dialog.dialog('close');
+ }
+
+ function add_and_close(evt) {
+ add(evt, true);
+ add_dialog.dialog('close');
+ }
+
+ function cancel() {
+ add_dialog.dialog('close');
+ }
+
+
+ add_dialog.dialog({
+ modal: true,
+ buttons: {
+ 'Add many': add,
+ 'Add and Close': add_and_close,
+ 'Cancel': cancel
+ }
+ });
+ }
+
+
+ function delete_records(records_table){
+
+ var zone = $.bbq.getState('dnszone-pkey', true);
+
+ var thead = records_table.find('thead');
+ thead.find("INPUT[type='checkbox']").
+ attr('checked', false);
+
+ var i = 0;
+
+ var tbody = records_table.find('tbody');
+
+
+ var delete_dialog = $('<div/>', {
+ title: IPA.messages.button.remove
+ });
+ var to_delete_table =
+ $('<table class="search-table" >'+
+ '<thead><tr><th>Resource</th><th>Type</th></tr></thead>'+
+ '<tbody></tbody></table>').appendTo(delete_dialog);
+
+ var to_delete_body = to_delete_table.find('tbody');
+ var delete_list = [];
+ tbody.find("INPUT[type='checkbox']").each(
+ function(index, box){
+ if (box.checked){
+ var tr = $(box).parents('tr');
+ var resource = $(tr).find('[title="idnsname"]').text();
+ var type = $(tr).find('[title="type"]').
+ text().toLowerCase();
+ var data = $(tr).find('[title="data"]').text();
+ var rectype=type+"record";
+
+ var options = {};
+ options[rectype]=data;
+
+ var command = {
+ "method":"dnsrecord_del",
+ "params":[[zone,resource], options]};
+ delete_list.push(command);
+ to_delete_body.append(
+ $('<tr></tr>').
+ append($('<td></td>',{html:resource}).
+ after($('<td></td>',{html:type}))));
+ }
+ }
+ );
+
+ function delete_on_click() {
+ var delete_count = delete_list.length;
+ function delete_complete(){
+ reload();
+ delete_dialog.dialog('close');
+ }
+
+ IPA.cmd('batch', delete_list, {},
+ delete_complete,delete_complete);
+ }
+
+ function cancel_on_click() {
+ delete_dialog.dialog('close');
+ }
+
+
+ if (delete_list.length === 0){
+ return;
+ }
+ delete_dialog.append($('<P/>',
+ {text: IPA.messages.search.delete_confirm}));
+
+ delete_dialog.dialog({
+ modal: true,
+ buttons: {
+ 'Delete': delete_on_click,
+ 'Cancel': cancel_on_click
+ }
+ });
+
+
+ }
+
+ that.is_dirty = function() {
+ var pkey = $.bbq.getState(that.entity_name + '-pkey', true) || '';
+ var record = $.bbq.getState(that.entity_name + '-record', true) || '';
+ return pkey != that.pkey || record != that.record;
+ };
+
+ function create(container) {
+ var details = $('<div/>', {
+ 'class': 'content'
+ }).appendTo(container);
+ }
+
+ function setup(container){
+
+ that.facet_setup(container);
+
+ that.pkey = $.bbq.getState(that.entity_name + '-pkey', true) || '';
+ that.record = $.bbq.getState(that.entity_name + '-record', true) || '';
+
+ that.container.attr('title', that.entity_name);
+
+ var h2 = $('<h2></h2>',{
+ text: "Records for DNS Zone:" + that.pkey
+ }).appendTo(that.container);
+
+
+ var div = $('<div class="search-controls"></div>').
+ appendTo(that.container);
+
+ var control_span =$('<span class="record-filter"></span>').appendTo(div);
+
+ control_span.append('Resource');
+ control_span.append($('<input />',{
+ type: "text",
+ id: 'dns-record-resource-filter',
+ name: 'search-' + that.entity_name + '-filter'
+ }));
+
+ control_span.append('Type');
+
+ create_type_select('dns-record-type-filter',true).
+ appendTo(control_span);
+ //commented out until data is searchable
+ //control_span.append('Data');
+ //control_span.append($('<input />',{
+ // type: "text",
+ // id: 'dns-record-data-filter',
+ // name: 'search-' + obj_name + '-filter'
+ //}));
+
+
+ IPA.button({
+ 'label': IPA.messages.button.find,
+ 'icon': 'ui-icon-search',
+ 'click': function(){refresh();}
+ }).appendTo(control_span);
+
+ var action_panel_ul = $('.action-panel .entity-facet', that.container).
+ last();
+
+ var action_controls = $('<li/>',{
+ "class":"action-controls"}).appendTo(action_panel_ul);
+
+
+ IPA.button({
+ 'label': IPA.messages.button.add,
+ 'icon': 'ui-icon-plus',
+ 'click': add_click
+ }).appendTo(action_controls);
+
+ IPA.button({
+ 'label': IPA.messages.button.remove,
+ 'icon': 'ui-icon-trash',
+ 'click': function(){delete_records(records_table);}
+ }).appendTo(action_controls);
+
+ div.append('<span class="records-buttons"></span>');
+
+ var records_results = $('<div/>', {
+ 'class': 'records-results'
+ }).appendTo(that.container);
+
+ var records_table = $('<table/>', {
+ 'class': 'search-table'
+ }).appendTo(records_results);
+
+ var thead = $('<thead><tr></tr></thead>').appendTo(records_table);
+ var tbody = $('<tbody></tbody>').appendTo(records_table);
+ var tfoot = $('<tfoot></tfoot>').appendTo(records_table);
+
+ var tr = thead.find('tr');
+ tr.append($('<th style="width: 15px" />').append(
+ $('<input />',{
+ type: 'checkbox',
+ click : function (evt){
+ tbody.find("INPUT[type='checkbox']").
+ attr('checked', this.checked);
+ }
+ })));
+ tr.append($('<th/>',{
+ text: IPA.get_param_info("dnsrecord", "idnsname").label }));
+ tr.append($('<th>Record Type</th>'));
+ tr.append($('<th>Data</th>'));
+
+ refresh();
+ }
+
+
+ function load_on_win(data){
+ display(that.entity_name,data);
+ }
+
+ function load_on_fail(data){
+ display(that.entity_name,data);
+ }
+
+ function reload(){
+ refresh();
+ }
+
+
+ function refresh(){
+
+ var options = {};
+
+ var resource_filter = that.container.
+ find("#dns-record-resource-filter").val();
+ if (resource_filter){
+ options.idnsname = resource_filter;
+ }
+
+ var type_filter = that.container.find("#dns-record-type-filter").val();
+ if (type_filter){
+ options.type = type_filter;
+ }
+
+ var data_filter = that.container.find("#dns-record-data-filter").val();
+ if (data_filter){
+ options.data = data_filter;
+ }
+
+
+ var pkey = $.bbq.getState(that.entity_name + '-pkey', true);
+ IPA.cmd('dnsrecord_find',[pkey],options,load_on_win, load_on_fail);
+
+ }
+
+
+ function generate_tr(thead, tbody, result){
+ var tr = $('<tr></tr>').appendTo(tbody);
+
+ search_generate_checkbox_td(tr, /*pkey_value*/ '');
+
+ //TODO get this fixed on the back end. For now, workaround
+
+ if (result.idnsname){
+ tr.append($('<td/>',{
+ title:'idnsname',
+ text: result.idnsname[0]
+ }));
+ }else{
+ tr.append($('<td/>',{
+ title:'idnsname',
+ text: result.dn.split(',')[0].split('=')[1]
+ }));
+
+ }
+
+ for (var i = 0; i < record_types.length; i += 1){
+ var field_name = record_types[i];
+ var field = result[field_name+'record'];
+ if ( field ){
+ var record_type = field_name;
+ var record_data = field[0];
+ break;
+ }
+ }
+
+ tr.append($('<td/>',{
+ title:'type',
+ text: record_type
+ }));
+ tr.append($('<td/>',{
+ title:'data',
+ text: record_data
+ }));
+ }
+
+ //TODO this is cut and pasted from search, we need to unify
+ function display(obj_name, data){
+ var selector = '.entity-container[title=' + obj_name + ']';
+ var thead = $(selector + ' thead');
+ var tbody = $(selector + ' tbody');
+ var tfoot = $(selector + ' tfoot');
+
+ tbody.find('tr').remove();
+
+ var result = data.result.result;
+ for (var i = 0; i < result.length; ++i){
+ generate_tr(thead, tbody, result[i]);
+ }
+
+ if (data.result.truncated) {
+ tfoot.text(
+ 'Query returned results than configured size limit will show.' +
+ 'First ' + data.result.count + ' results shown.' );
+ } else {
+ tfoot.text(data.result.summary);
+ }
+
+ }
+
+ that.create = create;
+ that.setup = setup;
+ that.refresh = refresh;
+
+ return that;
+};
+
+
+/**Automount*/
+
+IPA.add_entity(function (){
+ var that = IPA.entity({
+ name: 'automountlocation'
+ });
+
+
+ var search_facet = IPA.search_facet({
+ name: 'search',
+ label: 'Search',
+ entity_name: that.name
+ });
+ that.init = function() {
+ search_facet.create_column({name:'cn'});
+ that.add_facet(search_facet);
+
+
+ that.add_facet(function() {
+ var that = IPA.details_facet({name:'details'});
+ that.add_section(
+ IPA.stanza({name:'identity', label:'Automount Location Settings'}).
+ input({name:'cn'}));
+ return that;
+ }());
+
+ var dialog = IPA.add_dialog({
+ name: 'add',
+ title: 'Add Automount Location'
+ });
+ that.add_dialog(dialog);
+
+ dialog.add_field(IPA.text_widget({ name: 'cn', undo: false}));
+ dialog.init();
+
+ that.create_association_facets();
+ that.entity_init();
+
+ };
+ return that;
+}());
+
+
+/**pwpolicy*/
+
+
+IPA.add_entity(function (){
+ var that = IPA.entity({
+ name: 'pwpolicy'
+ });
+
+
+ var search_facet = IPA.search_facet({
+ name: 'search',
+ label: 'Search',
+ entity_name: that.name
+ });
+ that.init = function() {
+ search_facet.create_column({name:'cn'});
+ that.add_facet(search_facet);
+
+
+ that.add_facet(function() {
+ var that = IPA.details_facet({name:'details'});
+ that.add_section(
+
+ IPA.stanza({name:'identity', label:'Password Policy'}).
+ input({name:'krbmaxpwdlife'}).
+ input({name:'krbminpwdlife'}).
+ input({name:'krbpwdhistorylength'}).
+ input({name:'krbpwdmindiffchars'}).
+ input({name:'krbpwdminlength'}));
+ return that;
+ }());
+
+ var dialog = IPA.add_dialog({
+ name: 'add',
+ title: 'Add Password Policy',
+ entity_name:'pwpolicy'
+ });
+ that.add_dialog(dialog);
+
+ dialog.add_field(IPA.text_widget({ name: 'cn', undo: false}));
+ dialog.init();
+
+ that.create_association_facets();
+ that.entity_init();
+
+ };
+ return that;
+}());
+
+
+
+/**
+ krbtpolicy
+ Does not have search
+*/
+
+IPA.entity_set_details_definition('krbtpolicy', [
+ IPA.stanza({name:'identity', label:'Kerberos ticket policy'}).
+ //input({name:'uid',label:' '}).
+ input({name:'krbmaxrenewableage'}).
+ input({name:'krbmaxticketlife'})
+]);
+
+IPA.entity_set_association_definition('krbtpolicy', {
+});
diff --git a/install/ui/rule.js b/install/ui/rule.js
new file mode 100644
index 000000000..f625f8535
--- /dev/null
+++ b/install/ui/rule.js
@@ -0,0 +1,174 @@
+/*jsl:import ipa.js */
+
+/* Authors:
+ * Endi Sukma Dewata <edewata@redhat.com>
+ *
+ * Copyright (C) 2010 Red Hat
+ * see file 'COPYING' for use and warranty information
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* REQUIRES: ipa.js, details.js, search.js, add.js, entity.js */
+
+IPA.rule_details_section = function (spec){
+
+ spec = spec || {};
+
+ var that = IPA.details_section(spec);
+
+ that.text = spec.text;
+ that.field_name = spec.field_name;
+ that.options = spec.options || [];
+ that.tables = spec.tables || [];
+ that.columns = spec.columns;
+
+ that.create = function(container) {
+
+ if (that.template) return;
+
+ if (that.text) container.append(that.text);
+
+ var param_info = IPA.get_param_info(that.entity_name, that.field_name);
+
+ var span = $('<span/>', {
+ name: that.field_name,
+ title: param_info.doc
+ }).appendTo(container);
+
+ if (that.options.length) {
+ for (var i=0; i<that.options.length; i++) {
+ var option = that.options[i];
+
+ $('<input/>', {
+ 'type': 'radio',
+ 'name': that.field_name,
+ 'value': option.value
+ }).appendTo(span);
+
+ span.append(option.label);
+ }
+
+ span.append(' ');
+
+ $('<span/>', {
+ 'name': 'undo',
+ 'class': 'ui-state-highlight ui-corner-all',
+ 'style': 'display: none;',
+ 'html': 'undo'
+ }).appendTo(span);
+
+ span.append('<br/>');
+ }
+
+ for (var j=0; j<that.tables.length; j++) {
+ var table = that.tables[j];
+
+ param_info = IPA.get_param_info(that.entity_name, table.field_name);
+
+ var table_span = $('<span/>', {
+ name: table.field_name,
+ title: param_info ? param_info.doc : table.field_name
+ }).appendTo(span);
+
+ var field = that.get_field(table.field_name);
+ field.create(table_span);
+ }
+ };
+
+ that.setup = function(container) {
+
+ that.section_setup(container);
+
+ function update_tables(value) {
+
+ var enabled = ('' === value);
+
+ for (var i=0; i<that.tables.length; i++) {
+ var table = that.tables[i];
+
+ var field = that.get_field(table.field_name);
+ field.set_enabled(enabled);
+ }
+ }
+
+ var category = that.get_field(that.field_name);
+ category.reset = function() {
+ category.widget_reset();
+ var values = category.save();
+ if (values.length === 0){
+ return;
+ }
+ var value = values[0];
+ update_tables(value);
+ };
+
+ var inputs = $('input[name='+that.field_name+']', container);
+ inputs.change(function() {
+ var input = $(this);
+ var value = input.val();
+ update_tables(value);
+ });
+ };
+
+ return that;
+};
+
+
+IPA.rule_association_table_widget = function (spec) {
+
+ spec = spec || {};
+
+ var that = IPA.association_table_widget(spec);
+
+ that.category = spec.category;
+
+ that.add = function(values, on_success, on_error) {
+
+ var pkey = $.bbq.getState(that.entity_name + '-pkey', true) || '';
+
+ var batch = IPA.batch_command({
+ 'on_success': on_success,
+ 'on_error': on_error
+ });
+
+ var command;
+
+ if (that.category) {
+ command = IPA.command({
+ 'method': that.entity_name+'_mod',
+ 'args': [pkey],
+ 'options': {'all': true, 'rights': true},
+ 'on_success': function() {
+ var record = {};
+ record[that.category.name] = [''];
+ that.category.load(record);
+ }
+ });
+ command.set_option(that.category.name, '');
+ batch.add_command(command);
+ }
+
+ command = IPA.command({
+ 'method': that.entity_name+'_'+that.add_method,
+ 'args': [pkey]
+ });
+ command.set_option(that.other_entity, values.join(','));
+ batch.add_command(command);
+
+ batch.execute();
+ };
+
+ return that;
+};
diff --git a/install/ui/search.js b/install/ui/search.js
new file mode 100644
index 000000000..934000b9f
--- /dev/null
+++ b/install/ui/search.js
@@ -0,0 +1,462 @@
+/*jsl:import ipa.js */
+
+/* Authors:
+ * Pavel Zuna <pzuna@redhat.com>
+ * Adam Young <ayoung@redhat.com>
+ * Endi S. Dewata <edewata@redhat.com>
+ *
+ * Copyright (C) 2010 Red Hat
+ * see file 'COPYING' for use and warranty information
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* REQUIRES: ipa.js */
+
+IPA.search_widget = function (spec) {
+
+ spec = spec || {};
+
+ var that = IPA.table_widget(spec);
+
+ that.facet = spec.facet;
+
+ that.create = function(container) {
+
+ var search_controls = $('<div/>', {
+ 'class': 'search-controls'
+ }).appendTo(container);
+
+ var search_filter = $('<span/>', {
+ 'class': 'search-filter',
+ 'name': 'search-filter'
+ }).appendTo(search_controls);
+
+ search_controls.append(IPA.create_network_spinner());
+
+ this.filter = $('<input/>', {
+ 'type': 'text',
+ 'name': 'search-' + that.entity_name + '-filter'
+ }).appendTo(search_filter);
+
+ $('<input/>', {
+ 'type': 'button',
+ 'name': 'find',
+ 'value': 'Find'
+ }).appendTo(search_filter);
+
+ var action_panel = that.facet.get_action_panel();
+ var li = $('.action-controls', action_panel);
+
+ var search_buttons = $('<span/>', {
+ 'class': 'search-buttons'
+ }).appendTo(li);
+
+ $('<input/>', {
+ 'type': 'button',
+ 'name': 'remove',
+ 'value': 'Remove'
+ }).appendTo(search_buttons);
+
+ $('<input/>', {
+ 'type': 'button',
+ 'name': 'add',
+ 'value': 'Add'
+ }).appendTo(search_buttons);
+
+ $('<div/>', {
+ 'class': 'search-results'
+ }).appendTo(container);
+
+ that.table_create(container);
+ };
+
+ that.setup = function(container) {
+
+ that.table_setup(container);
+
+ var search_filter = $('span[name=search-filter]', that.container);
+
+ var button = $('input[name=find]', search_filter);
+ that.find_button = IPA.button({
+ 'label': IPA.messages.button.find,
+ 'icon': 'ui-icon-search',
+ 'click': function() { that.find(that.container); }
+ });
+ button.replaceWith(that.find_button);
+
+ var action_panel = that.facet.get_action_panel();
+ var search_buttons = $('.search-buttons', action_panel);
+
+ button = $('input[name=remove]', search_buttons);
+ that.remove_button = IPA.action_button({
+ 'label': IPA.messages.button.remove,
+ 'icon': 'ui-icon-trash',
+ 'click': function() { that.remove(that.container); }
+ });
+ button.replaceWith(that.remove_button);
+
+ button = $('input[name=add]', search_buttons);
+ that.add_button = IPA.action_button({
+ 'label': IPA.messages.button.add,
+ 'icon': 'ui-icon-plus',
+ 'click': function() { that.add(that.container); }
+ });
+ button.replaceWith(that.add_button);
+
+ var filter = $.bbq.getState(that.entity_name + '-filter', true) || '';
+ this.filter.val(filter);
+ };
+
+ that.find = function(container) {
+ var filter = this.filter.val();
+ var state = {};
+ state[that.entity_name + '-filter'] = filter;
+ $.bbq.pushState(state);
+ };
+
+ that.add = function(container) {
+
+ var entity = IPA.get_entity(that.entity_name);
+
+ var dialog = entity.get_dialog('add');
+ dialog.open(that.container);
+
+ return false;
+ };
+
+ that.select_changed = function(){
+ var count = 0;
+ var pkey;
+ $('input[name=select]:checked', that.tbody).each(function(input){
+ count += 1;
+ pkey = $(this).val();
+ });
+
+ var action_panel = that.facet.get_action_panel();
+ if(count == 1){
+ $('li.entity-facet', action_panel).
+ removeClass('entity-facet-disabled');
+ var state = {};
+ $('input[id=pkey]', action_panel).val(pkey);
+ }else{
+ $('li.entity-facet', action_panel).
+ addClass('entity-facet-disabled');
+ $('input', action_panel).val(null);
+
+ }
+ return false;
+ };
+
+
+ that.remove = function(container) {
+
+ var values = that.get_selected_values();
+
+ if (!values.length) {
+ alert('Select '+that.label+' to be removed.');
+ return;
+ }
+
+ var title = 'Remove '+that.label;
+
+ var dialog = IPA.deleter_dialog({
+ 'title': title,
+ 'parent': that.container,
+ 'values': values
+ });
+
+ dialog.remove = function() {
+
+ var batch = IPA.batch_command({
+ 'on_success': function() {
+ that.refresh();
+ dialog.close();
+ },
+ 'on_error': function() {
+ that.refresh();
+ dialog.close();
+ }
+ });
+
+ for (var i=0; i<values.length; i++) {
+ var command = IPA.command({
+ 'method': that.entity_name+'_del'
+ });
+ command.add_arg(values[i]);
+ batch.add_command(command);
+ }
+
+ batch.execute();
+ };
+
+ dialog.init();
+
+ dialog.open(that.container);
+ };
+
+ that.refresh = function() {
+
+ function on_success(data, text_status, xhr) {
+
+ var action_panel = that.facet.get_action_panel();
+ $('li.entity-facet', action_panel).
+ addClass('entity-facet-disabled');
+ $('input', action_panel).val(null);
+
+ that.tbody.empty();
+
+ var result = data.result.result;
+ for (var i = 0; i<result.length; i++) {
+ var record = that.get_record(result[i], 0);
+ that.add_record(record);
+ }
+
+ var summary = $('span[name=summary]', that.tfoot);
+ if (data.result.truncated) {
+ summary.text(
+ 'Query returned more results than configured size limit '+
+ 'will show. First ' +
+ data.result.count + ' results shown.');
+ } else {
+ summary.text(data.result.summary);
+ }
+ }
+
+ function on_error(xhr, text_status, error_thrown) {
+ var summary = $('span[name=summary]', that.tfoot).empty();
+ summary.append('<p>Error: '+error_thrown.name+'</p>');
+ summary.append('<p>'+error_thrown.title+'</p>');
+ summary.append('<p>'+error_thrown.message+'</p>');
+ }
+
+ var filter = $.bbq.getState(that.entity_name + '-filter', true) || '';
+ IPA.cmd(
+ 'find', [filter], {all: true}, on_success, on_error,
+ that.entity_name);
+ };
+
+ return that;
+};
+
+IPA.search_facet = function (spec) {
+
+ spec = spec || {};
+
+ spec.display_class = 'search-facet';
+
+ var that = IPA.facet(spec);
+
+ that.init = spec.init || init;
+ that.create = spec.create || create;
+ that.setup = spec.setup || setup;
+ that.refresh = spec.refresh || refresh;
+
+ that.columns = [];
+ that.columns_by_name = {};
+
+ that.__defineGetter__("entity_name", function(){
+ return that._entity_name;
+ });
+
+ that.__defineSetter__("entity_name", function(entity_name){
+ that._entity_name = entity_name;
+
+ for (var i=0; i<that.columns.length; i++) {
+ that.columns[i].entity_name = entity_name;
+ }
+ });
+
+ that.get_columns = function() {
+ return that.columns;
+ };
+
+ that.get_column = function(name) {
+ return that.columns_by_name[name];
+ };
+
+ that.add_column = function(column) {
+ column.entity_name = that.entity_name;
+ that.columns.push(column);
+ that.columns_by_name[column.name] = column;
+ };
+
+ that.create_column = function(spec) {
+ var column = IPA.column(spec);
+ that.add_column(column);
+ return column;
+ };
+
+ that.setup_column = function(column) {
+ column.setup = function(container, record) {
+ container.empty();
+
+ var value = record[column.name];
+ value = value ? value.toString() : '';
+
+ $('<a/>', {
+ 'href': '#'+value,
+ 'html': value,
+ 'click': function (value) {
+ return function() {
+ var state = IPA.tab_state(that.entity_name);
+ state[that.entity_name + '-facet'] = 'details';
+ state[that.entity_name + '-pkey'] = value;
+ $.bbq.pushState(state);
+ return false;
+ };
+ }(value)
+ }).appendTo(container);
+ };
+ };
+
+ function init() {
+
+ that.facet_init();
+
+ that.table = IPA.search_widget({
+ 'id': that.entity_name+'-search',
+ 'name': 'search', 'label': IPA.metadata[that.entity_name].label,
+ 'entity_name': that.entity_name,
+ 'facet': that
+ });
+
+ for (var i=0; i<that.columns.length; i++) {
+ var column = that.columns[i];
+
+ var param_info = IPA.get_param_info(that.entity_name, column.name);
+ column.primary_key = param_info && param_info['primary_key'];
+
+ if (column.primary_key) {
+ that.setup_column(column);
+ }
+
+ that.table.add_column(column);
+ }
+
+ that.table.init();
+ }
+
+ that.is_dirty = function() {
+ var filter = $.bbq.getState(that.entity_name + '-filter', true) || '';
+ return filter != that.filter;
+ };
+
+ function create(container) {
+
+ container.attr('title', that.entity_name);
+
+ var span = $('<span/>', { 'name': 'search' }).appendTo(container);
+
+ that.table.create(span);
+
+ }
+
+ function setup(container) {
+ that.facet_setup(container);
+ var span = $('span[name=search]', that.container);
+ that.table.setup(span);
+ }
+
+ function refresh() {
+ that.filter = $.bbq.getState(that.entity_name + '-filter', true) || '';
+ that.table.refresh();
+ }
+
+ if (spec.columns) {
+ for (var i=0; i<spec.columns.length; i++) {
+ var column = spec.columns[i];
+ column.facet = that;
+ that.add_column(column);
+ }
+ }
+
+ that.search_facet_init = that.init;
+ that.search_facet_create = that.create;
+ that.search_facet_setup = that.setup;
+
+ return that;
+};
+
+function search_generate_tr(thead, tbody, entry_attrs)
+{
+ var obj_name = tbody.closest('.entity-container').attr('title');
+ var pkey = IPA.metadata[obj_name].primary_key;
+ var pkey_value = entry_attrs[pkey];
+
+ var entity = IPA.get_entity(obj_name);
+ var facet = entity ? entity.get_facet('search') : null;
+
+ tbody.append('<tr></tr>');
+ var tr = tbody.children().last();
+ search_generate_checkbox_td(tr, pkey_value);
+
+ var ths = thead.find('th');
+ for (var i = 1; i < ths.length; ++i) {
+ var jobj = $(ths[i]);
+ var attr = jobj.attr('abbr');
+ var value = entry_attrs[attr];
+
+ var column = facet ? facet.get_column(attr) : null;
+ var render_call = window[jobj.attr('title')];
+
+ if (column && column.setup) {
+ column.setup(tr, attr, value, entry_attrs);
+
+ } else if (typeof render_call == 'function') {
+ render_call(tr, attr, value, entry_attrs);
+
+ } else
+ search_generate_td(tr, attr, value, entry_attrs);
+ }
+
+ tbody.find('.search-a-pkey').click(function () {
+ var jobj = $(this);
+
+ var state = {};
+ state[obj_name + '-facet'] = 'details';
+ state[obj_name + '-pkey'] = $(this).text();
+ $.bbq.pushState(state);
+
+ return (false);
+ });
+}
+
+function search_generate_checkbox_td(tr, pkey)
+{
+ var checkbox = $('<input />', {
+ name: pkey,
+ title: pkey,
+ type: 'checkbox',
+ 'class': 'search-selector'
+ });
+ var td = $('<td></td>');
+
+ td.append(checkbox);
+ tr.append(td);
+}
+
+var _search_td_template = '<td title="A">V</td>';
+var _search_a_pkey_template = '<a href="jslink" class="search-a-pkey">V</a>';
+
+function search_generate_td(tr, attr, value, entry_attrs)
+{
+ var obj_name = tr.closest('.entity-container').attr('title');
+
+ var param_info = IPA.get_param_info(obj_name, attr);
+ if (param_info && param_info['primary_key'])
+ value = _search_a_pkey_template.replace('V', value);
+
+ tr.append(_search_td_template.replace('A', attr).replace('V', value));
+}
diff --git a/install/ui/serverconfig.js b/install/ui/serverconfig.js
new file mode 100644
index 000000000..6c0a824b4
--- /dev/null
+++ b/install/ui/serverconfig.js
@@ -0,0 +1,43 @@
+/*jsl:import ipa.js */
+
+/* Authors:
+ * Endi Sukma Dewata <edewata@redhat.com>
+ * Adam Young <ayoung@redhat.com>
+ *
+ * Copyright (C) 2010 Red Hat
+ * see file 'COPYING' for use and warranty information
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* REQUIRES: ipa.js, details.js, search.js, add.js, entity.js */
+
+
+
+/* Configuration */
+IPA.entity_set_details_definition('config',[
+
+ IPA.stanza({name:'ipaserver', label:'Configuration'}).
+ input({name:'cn', label:'Name'}).
+ input({name:'ipacertificatesubjectbase'}).
+ input({name:'ipadefaultloginshell'}).
+ input({name:'ipadefaultprimarygroup'}).
+ input({name:'ipagroupsearchfields'}).
+ input({name:'ipahomesrootdir'}).
+ input({name:'ipamaxusernamelength'}).
+ input({name:'ipamigrationenabled'}).
+ input({name:'ipasearchrecordslimit'}).
+ input({name:'ipasearchtimelimit'}).
+ input({name:'ipausersearchfields'})
+]);
diff --git a/install/ui/service.js b/install/ui/service.js
new file mode 100644
index 000000000..81f00ec77
--- /dev/null
+++ b/install/ui/service.js
@@ -0,0 +1,499 @@
+/*jsl:import ipa.js */
+/*jsl:import certificate.js */
+
+/* Authors:
+ * Endi Sukma Dewata <edewata@redhat.com>
+ *
+ * Copyright (C) 2010 Red Hat
+ * see file 'COPYING' for use and warranty information
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* REQUIRES: ipa.js, details.js, search.js, add.js, entity.js */
+
+IPA.service = function () {
+
+ var that = IPA.entity({
+ 'name': 'service'
+ });
+
+ that.init = function() {
+
+ that.create_association({
+ 'name': 'host',
+ 'add_method': 'add_host',
+ 'remove_method': 'remove_host'
+ });
+
+ var dialog = IPA.service_add_dialog({
+ 'name': 'add',
+ 'title': 'Add New Service'
+ });
+ that.add_dialog(dialog);
+ dialog.init();
+
+ var facet = IPA.service_search_facet({
+ 'name': 'search',
+ 'label': 'Search'
+ });
+ that.add_facet(facet);
+
+ facet = IPA.service_details_facet({
+ 'name': 'details'
+ });
+ that.add_facet(facet);
+
+ facet = IPA.service_managedby_host_facet({
+ 'name': 'managedby_host',
+ 'label': IPA.messages.association.managedby+' '+IPA.metadata['host'].label,
+ 'other_entity': 'host'
+ });
+ that.add_facet(facet);
+
+ that.entity_init();
+ };
+
+ return that;
+};
+
+
+IPA.add_entity(IPA.service());
+
+
+IPA.service_add_dialog = function (spec) {
+
+ spec = spec || {};
+
+ var that = IPA.add_dialog(spec);
+
+ that.init = function() {
+
+ that.add_field(IPA.widget({
+ name: 'krbprincipalname'
+ }));
+
+ // TODO: Replace with i18n label
+ that.add_field(IPA.text_widget({
+ 'name': 'service',
+ 'label': 'Service',
+ 'size': 20,
+ 'undo': false
+ }));
+
+ // TODO: Replace with i18n label
+ that.add_field(IPA.text_widget({
+ 'name': 'host',
+ 'label': 'Host Name',
+ 'size': 40,
+ 'undo': false
+ }));
+
+ // TODO: Replace with i18n label
+ that.add_field(IPA.checkbox_widget({
+ name: 'force',
+ label: 'Force',
+ tooltip: 'force principal name even if not in DNS',
+ undo: false
+ }));
+
+ that.add_dialog_init();
+ };
+
+ that.create = function() {
+
+ var table = $('<table/>').appendTo(that.container);
+
+ var field = that.get_field('service');
+
+ var tr = $('<tr/>').appendTo(table);
+
+ var td = $('<td/>', {
+ style: 'vertical-align: top;',
+ title: field.label
+ }).appendTo(tr);
+ td.append(field.label+': ');
+
+ td = $('<td/>', {
+ 'style': 'vertical-align: top;'
+ }).appendTo(tr);
+
+ var span = $('<span/>', { 'name': 'service' }).appendTo(td);
+ field.create(span);
+
+ field = that.get_field('host');
+
+ tr = $('<tr/>').appendTo(table);
+
+ td = $('<td/>', {
+ style: 'vertical-align: top;',
+ title: field.label
+ }).appendTo(tr);
+ td.append(field.label+': ');
+
+ td = $('<td/>', {
+ 'style': 'vertical-align: top;'
+ }).appendTo(tr);
+
+ span = $('<span/>', { 'name': 'host' }).appendTo(td);
+ field.create(span);
+
+ field = that.get_field('force');
+
+ tr = $('<tr/>').appendTo(table);
+
+ td = $('<td/>', {
+ style: 'vertical-align: top;',
+ title: field.label
+ }).appendTo(tr);
+ td.append(field.label+': ');
+
+ td = $('<td/>', {
+ 'style': 'vertical-align: top;'
+ }).appendTo(tr);
+
+ span = $('<span/>', { 'name': 'force' }).appendTo(td);
+ field.create(span);
+ };
+
+ that.get_record = function() {
+ var record = {};
+
+ var field = that.get_field('service');
+ var service = field.save()[0];
+
+ field = that.get_field('host');
+ var host = field.save()[0];
+
+ record['krbprincipalname'] = service+'/'+host;
+
+ field = that.get_field('force');
+ var force = field.save()[0];
+
+ record['force'] = force;
+
+ return record;
+ };
+
+ return that;
+};
+
+
+IPA.service_search_facet = function (spec) {
+
+ spec = spec || {};
+
+ var that = IPA.search_facet(spec);
+
+ that.init = function() {
+
+ that.create_column({name:'krbprincipalname'});
+ that.search_facet_init();
+ };
+
+ return that;
+};
+
+
+IPA.service_details_facet = function (spec) {
+
+ spec = spec || {};
+
+ var that = IPA.details_facet(spec);
+
+ that.init = function() {
+
+ var section = IPA.details_list_section({
+ name: 'details',
+ label: 'Service Settings'
+ });
+ that.add_section(section);
+
+ section.create_field({
+ name: 'krbprincipalname'
+ });
+
+ // TODO: Replace with i18n label
+ section.create_field({
+ name: 'service',
+ label: 'Service',
+ load: service_service_load
+ });
+
+ // TODO: Replace with i18n label
+ section.create_field({
+ name: 'host',
+ label: 'Host Name',
+ load: service_host_load
+ });
+
+ section = IPA.details_list_section({
+ name: 'provisioning',
+ label: 'Provisioning'
+ });
+ that.add_section(section);
+
+ section.add_field(service_provisioning_status_widget({
+ name: 'provisioning_status',
+ label: 'Status'
+ }));
+
+ section = IPA.details_list_section({
+ name: 'certificate',
+ label: 'Service Certificate'
+ });
+ that.add_section(section);
+
+ section.add_field(service_certificate_status_widget({
+ name: 'certificate_status',
+ label: 'Status'
+ }));
+
+ that.details_facet_init();
+ };
+
+ return that;
+};
+
+
+function service_service_load(result) {
+
+ var that = this;
+
+ $('dd', that.container).remove();
+
+ var dd = IPA.create_first_dd(this.name);
+ dd.appendTo(that.container);
+
+ var krbprincipalname = result['krbprincipalname'][0];
+ var service = krbprincipalname.replace(/\/.*$/, '');
+ dd.append(service);
+}
+
+function service_host_load(result) {
+
+ var that = this;
+
+ $('dd', that.container).remove();
+
+ var dd = IPA.create_first_dd(this.name);
+ dd.appendTo(that.container);
+
+ var krbprincipalname = result['krbprincipalname'][0];
+ var host = krbprincipalname.replace(/^.*\//, '').replace(/@.*$/, '');
+ dd.append(host);
+}
+
+
+function service_provisioning_status_widget(spec) {
+
+ spec = spec || {};
+
+ var that = IPA.widget(spec);
+
+ that.create = function(container) {
+
+ that.widget_create(container);
+
+ var dd = $('<dd/>', {
+ 'class': 'first'
+ }).appendTo(container);
+
+ var div = $('<div/>', {
+ 'class': 'kerberos-key-valid'
+ }).appendTo(dd);
+
+ $('<img/>', {
+ src: 'check.png',
+ style: 'float: left;',
+ 'class': 'status-icon'
+ }).appendTo(div);
+
+ var content_div = $('<div/>', {
+ style: 'float: left;'
+ }).appendTo(div);
+
+ content_div.append('<b>Kerberos Key Present, Service Provisioned:</b>');
+
+ content_div.append(' ');
+
+ $('<input/>', {
+ 'type': 'button',
+ 'name': 'unprovision',
+ 'value': 'Delete Key, Unprovision'
+ }).appendTo(content_div);
+
+ div = $('<div/>', {
+ name: 'kerberos-key-missing'
+ }).appendTo(dd);
+
+ $('<img/>', {
+ src: 'caution.png',
+ style: 'float: left;',
+ 'class': 'status-icon'
+ }).appendTo(div);
+
+ content_div = $('<div/>', {
+ style: 'float: left;'
+ }).appendTo(div);
+
+ content_div.append('<b>Kerberos Key Not Present</b>');
+ };
+
+ that.setup = function(container) {
+
+ that.widget_setup(container);
+
+ that.valid = $('div[name=kerberos-key-valid]', that.container);
+ that.missing = $('div[name=kerberos-key-missing]', that.container);
+
+ var button = $('input[name=unprovision]', that.container);
+ that.unprovision_button = IPA.button({
+ 'label': 'Delete Key, Unprovision',
+ 'click': that.unprovision
+ });
+ button.replaceWith(that.unprovision_button);
+ };
+
+ that.unprovision = function() {
+
+ var label = IPA.metadata[that.entity_name].label;
+ var dialog = IPA.dialog({
+ 'title': 'Unprovisioning '+label
+ });
+
+ dialog.create = function() {
+ dialog.container.append(
+ 'Are you sure you want to unprovision this service?');
+ };
+
+ dialog.add_button('Unprovision', function() {
+ var pkey = that.result['krbprincipalname'][0];
+ IPA.cmd(that.entity_name+'_disable', [pkey], {},
+ function(data, text_status, xhr) {
+ set_status('missing');
+ dialog.close();
+ },
+ function(xhr, text_status, error_thrown) {
+ dialog.close();
+ }
+ );
+ });
+
+ dialog.init();
+
+ dialog.open(that.container);
+
+ return false;
+ };
+
+ that.load = function(result) {
+ that.result = result;
+ var krblastpwdchange = result['krblastpwdchange'];
+ set_status(krblastpwdchange ? 'valid' : 'missing');
+ };
+
+ function set_status(status) {
+ that.valid.css('display', status == 'valid' ? 'inline' : 'none');
+ that.missing.css('display', status == 'missing' ? 'inline' : 'none');
+ }
+
+ return that;
+}
+
+function service_certificate_status_widget(spec) {
+
+ spec = spec || {};
+
+ var that = certificate_status_widget(spec);
+
+ that.init = function() {
+
+ that.entity_label = IPA.metadata[that.entity_name].label;
+
+ that.get_entity_pkey = function(result) {
+ var values = result['krbprincipalname'];
+ return values ? values[0] : null;
+ };
+
+ that.get_entity_name = function(result) {
+ var value = that.get_entity_pkey(result);
+ return value ? value.replace(/@.*$/, '') : null;
+ };
+
+ that.get_entity_principal = function(result) {
+ return that.get_entity_pkey(result);
+ };
+
+ that.get_entity_certificate = function(result) {
+ var values = result['usercertificate'];
+ return values ? values[0].__base64__ : null;
+ };
+ };
+
+ return that;
+}
+
+IPA.service_managedby_host_facet = function (spec) {
+
+ spec = spec || {};
+
+ var that = IPA.association_facet(spec);
+
+ that.init = function() {
+
+ var column = that.create_column({
+ name: 'fqdn',
+ primary_key: true
+ });
+
+ column.setup = function(container, record) {
+ container.empty();
+
+ var value = record[column.name];
+ value = value ? value.toString() : '';
+
+ $('<a/>', {
+ 'href': '#'+value,
+ 'html': value,
+ 'click': function (value) {
+ return function() {
+ var state = IPA.tab_state(that.other_entity);
+ state[that.other_entity + '-facet'] = 'details';
+ state[that.other_entity + '-pkey'] = value;
+ $.bbq.pushState(state);
+ return false;
+ };
+ }(value)
+ }).appendTo(container);
+ };
+
+ that.create_column({name: 'description'});
+
+ that.create_adder_column({
+ name: 'fqdn',
+ primary_key: true,
+ width: '100px'
+ });
+
+ that.create_adder_column({
+ name: 'description',
+ width: '100px'
+ });
+
+ that.association_facet_init();
+ };
+
+ return that;
+};
diff --git a/install/ui/spinner_header.gif b/install/ui/spinner_header.gif
new file mode 100644
index 000000000..ba9fb7818
--- /dev/null
+++ b/install/ui/spinner_header.gif
Binary files differ
diff --git a/install/ui/spinner_large.gif b/install/ui/spinner_large.gif
new file mode 100644
index 000000000..276dd5a77
--- /dev/null
+++ b/install/ui/spinner_large.gif
Binary files differ
diff --git a/install/ui/spinner_small.gif b/install/ui/spinner_small.gif
new file mode 100644
index 000000000..1a2da81c2
--- /dev/null
+++ b/install/ui/spinner_small.gif
Binary files differ
diff --git a/install/ui/sudocmd.js b/install/ui/sudocmd.js
new file mode 100644
index 000000000..e398ae8fa
--- /dev/null
+++ b/install/ui/sudocmd.js
@@ -0,0 +1,278 @@
+/*jsl:import ipa.js */
+
+/* Authors:
+ * Endi Sukma Dewata <edewata@redhat.com>
+ *
+ * Copyright (C) 2010 Red Hat
+ * see file 'COPYING' for use and warranty information
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* REQUIRES: ipa.js, details.js, search.js, add.js, entity.js */
+
+IPA.sudocmd = function () {
+
+ var that = IPA.entity({
+ 'name': 'sudocmd'
+ });
+
+ that.init = function() {
+
+ var dialog = IPA.sudocmd_add_dialog({
+ 'name': 'add',
+ 'title': 'Add New SUDO Command'
+ });
+ that.add_dialog(dialog);
+ dialog.init();
+
+ var facet = IPA.sudocmd_search_facet({
+ 'name': 'search',
+ 'label': 'Search'
+ });
+ that.add_facet(facet);
+
+ facet = IPA.sudocmd_details_facet({
+ 'name': 'details'
+ });
+ that.add_facet(facet);
+
+ that.entity_init();
+ };
+
+ return that;
+};
+
+
+IPA.add_entity(IPA.sudocmd());
+
+
+IPA.sudocmd_add_dialog = function (spec) {
+
+ spec = spec || {};
+
+ var that = IPA.add_dialog(spec);
+
+ that.init = function() {
+
+ that.add_field(IPA.text_widget({name:'sudocmd', undo: false}));
+ that.add_field(IPA.text_widget({name:'description', undo: false}));
+
+ that.add_dialog_init();
+ };
+
+ return that;
+};
+
+
+IPA.sudocmd_search_facet = function (spec) {
+
+ spec = spec || {};
+
+ var that = IPA.search_facet(spec);
+
+ that.init = function() {
+
+ that.create_column({name:'sudocmd', primary_key: true});
+ that.create_column({name:'description'});
+
+ that.search_facet_init();
+ };
+
+ return that;
+};
+
+
+IPA.sudocmd_details_facet = function (spec) {
+
+ spec = spec || {};
+
+ var that = IPA.details_facet(spec);
+
+ that.init = function() {
+
+ var section = IPA.details_list_section({
+ 'name': 'general',
+ 'label': 'General'
+ });
+ that.add_section(section);
+
+ section.create_field({'name': 'sudocmd'});
+ section.create_field({'name': 'description'});
+
+ section = IPA.details_section({
+ 'name': 'groups',
+ 'label': 'Groups'
+ });
+ that.add_section(section);
+
+ var field = IPA.sudocmd_member_sudocmdgroup_table_widget({
+ 'name': 'memberof',
+ 'label': 'Groups',
+ 'other_entity': 'sudocmdgroup',
+ 'save_values': false
+ });
+ section.add_field(field);
+
+ that.details_facet_init();
+ };
+
+ return that;
+};
+
+
+IPA.sudocmd_member_sudocmdgroup_table_widget = function (spec) {
+
+ spec = spec || {};
+
+ var that = IPA.association_table_widget(spec);
+
+ that.init = function() {
+
+ var column = that.create_column({
+ name: 'cn',
+ primary_key: true,
+ width: '150px'
+ });
+
+ column.setup = function(container, record) {
+ container.empty();
+
+ var value = record[column.name];
+ value = value ? value.toString() : '';
+
+ $('<a/>', {
+ 'href': '#'+value,
+ 'click': function (value) {
+ return function() {
+ var state = IPA.tab_state(that.other_entity);
+ state[that.other_entity + '-facet'] = 'details';
+ state[that.other_entity + '-pkey'] = value;
+ $.bbq.pushState(state);
+ return false;
+ };
+ }(value),
+ 'html': value
+ }).appendTo(container);
+ };
+
+ that.create_column({
+ name: 'description',
+ label: 'Description',
+ width: '150px'
+ });
+
+ that.create_adder_column({
+ name: 'cn',
+ primary_key: true,
+ width: '100px'
+ });
+
+ that.create_adder_column({
+ name: 'description',
+ width: '100px'
+ });
+
+ that.association_table_widget_init();
+ };
+
+ that.get_records = function(on_success, on_error) {
+
+ if (!that.values.length) return;
+
+ var batch = IPA.batch_command({
+ 'name': that.entity_name+'_'+that.name+'_show',
+ 'on_success': on_success,
+ 'on_error': on_error
+ });
+
+ for (var i=0; i<that.values.length; i++) {
+ var dn = that.values[i];
+ var j = dn.indexOf('=');
+ var k = dn.indexOf(',');
+ var value = dn.substring(j+1, k);
+
+ var command = IPA.command({
+ 'method': that.other_entity+'_show',
+ 'args': [value],
+ 'options': {
+ 'all': true,
+ 'rights': true
+ }
+ });
+
+ batch.add_command(command);
+ }
+
+ batch.execute();
+ };
+
+ that.add = function(values, on_success, on_error) {
+
+ if (!values.length) return;
+
+ var batch = IPA.batch_command({
+ 'name': that.entity_name+'_'+that.name+'_add',
+ 'on_success': on_success,
+ 'on_error': on_error
+ });
+
+ var pkey = $.bbq.getState(that.entity_name + '-pkey', true) || '';
+
+ for (var i=0; i<values.length; i++) {
+ var value = values[i];
+
+ var command = IPA.command({
+ 'method': that.other_entity+'_add_member',
+ 'args': [value]
+ });
+
+ command.set_option('sudocmd', pkey);
+
+ batch.add_command(command);
+ }
+
+ batch.execute();
+ };
+
+ that.remove = function(values, on_success, on_error) {
+
+ if (!values.length) return;
+
+ var batch = IPA.batch_command({
+ 'name': that.entity_name+'_'+that.name+'_remove',
+ 'on_success': on_success,
+ 'on_error': on_error
+ });
+
+ var pkey = $.bbq.getState(that.entity_name + '-pkey', true) || '';
+
+ for (var i=0; i<values.length; i++) {
+ var value = values[i];
+
+ var command = IPA.command({
+ 'method': that.other_entity+'_remove_member',
+ 'args': [value]
+ });
+
+ command.set_option('sudocmd', pkey);
+
+ batch.add_command(command);
+ }
+
+ batch.execute();
+ };
+
+ return that;
+};
diff --git a/install/ui/sudocmdgroup.js b/install/ui/sudocmdgroup.js
new file mode 100644
index 000000000..6cb2b83dc
--- /dev/null
+++ b/install/ui/sudocmdgroup.js
@@ -0,0 +1,197 @@
+/*jsl:import ipa.js */
+
+/* Authors:
+ * Endi Sukma Dewata <edewata@redhat.com>
+ *
+ * Copyright (C) 2010 Red Hat
+ * see file 'COPYING' for use and warranty information
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* REQUIRES: ipa.js, details.js, search.js, add.js, entity.js */
+
+IPA.sudocmdgroup = function () {
+
+ var that = IPA.entity({
+ 'name': 'sudocmdgroup'
+ });
+
+ that.init = function() {
+
+ that.create_association({
+ 'name': 'sudocmd',
+ 'add_method': 'add_member',
+ 'remove_method': 'remove_member'
+ });
+
+ var dialog = IPA.sudocmdgroup_add_dialog({
+ 'name': 'add',
+ 'title': 'Add New SUDO Command Group'
+ });
+ that.add_dialog(dialog);
+ dialog.init();
+
+ var facet = IPA.sudocmdgroup_search_facet({
+ 'name': 'search',
+ 'label': 'Search'
+ });
+ that.add_facet(facet);
+
+ facet = IPA.sudocmdgroup_details_facet({
+ 'name': 'details'
+ });
+ that.add_facet(facet);
+
+ that.entity_init();
+ };
+
+ return that;
+};
+
+
+IPA.add_entity(IPA.sudocmdgroup());
+
+
+IPA.sudocmdgroup_add_dialog = function (spec) {
+
+ spec = spec || {};
+
+ var that = IPA.add_dialog(spec);
+
+ that.init = function() {
+
+ that.add_field(IPA.text_widget({name:'cn', undo: false}));
+ that.add_field(IPA.text_widget({name:'description', undo: false}));
+
+ that.add_dialog_init();
+ };
+
+ return that;
+};
+
+
+IPA.sudocmdgroup_search_facet = function (spec) {
+
+ spec = spec || {};
+
+ var that = IPA.search_facet(spec);
+
+ that.init = function() {
+
+ that.create_column({name:'cn', primary_key: true});
+ that.create_column({name:'description'});
+
+ that.search_facet_init();
+ };
+
+ return that;
+};
+
+
+IPA.sudocmdgroup_details_facet = function (spec) {
+
+ spec = spec || {};
+
+ var that = IPA.details_facet(spec);
+
+ that.init = function() {
+
+ var section = IPA.details_list_section({
+ 'name': 'general',
+ 'label': 'General'
+ });
+ that.add_section(section);
+
+ section.create_field({'name': 'cn'});
+ section.create_field({'name': 'description'});
+
+ section = IPA.details_section({
+ 'name': 'commands',
+ 'label': 'Commands'
+ });
+ that.add_section(section);
+
+ var field = IPA.sudocmdgroup_member_sudocmd_table_widget({
+ 'name': 'member_sudocmd',
+ 'label': 'Commands',
+ 'other_entity': 'sudocmd',
+ 'save_values': false
+ });
+ section.add_field(field);
+
+ that.details_facet_init();
+ };
+
+ return that;
+};
+
+
+IPA.sudocmdgroup_member_sudocmd_table_widget = function (spec) {
+
+ spec = spec || {};
+
+ var that = IPA.association_table_widget(spec);
+
+ that.init = function() {
+
+ var column = that.create_column({
+ name: 'sudocmd',
+ primary_key: true,
+ width: '150px'
+ });
+
+ column.setup = function(container, record) {
+ container.empty();
+
+ var value = record[column.name];
+ value = value ? value.toString() : '';
+
+ $('<a/>', {
+ 'href': '#'+value,
+ 'html': value,
+ 'click': function (value) {
+ return function() {
+ var state = IPA.tab_state(that.other_entity);
+ state[that.other_entity + '-facet'] = 'details';
+ state[that.other_entity + '-pkey'] = value;
+ $.bbq.pushState(state);
+ return false;
+ };
+ }(value)
+ }).appendTo(container);
+ };
+
+ that.create_column({
+ name: 'description',
+ label: 'Description',
+ width: '150px'
+ });
+
+ that.create_adder_column({
+ name: 'sudocmd',
+ primary_key: true,
+ width: '100px'
+ });
+
+ that.create_adder_column({
+ name: 'description',
+ width: '100px'
+ });
+
+ that.association_table_widget_init();
+ };
+
+ return that;
+};
diff --git a/install/ui/sudorule.js b/install/ui/sudorule.js
new file mode 100644
index 000000000..94f3247b2
--- /dev/null
+++ b/install/ui/sudorule.js
@@ -0,0 +1,1127 @@
+/*jsl:import ipa.js */
+
+/* Authors:
+ * Endi Sukma Dewata <edewata@redhat.com>
+ *
+ * Copyright (C) 2010 Red Hat
+ * see file 'COPYING' for use and warranty information
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* REQUIRES: ipa.js, details.js, search.js, add.js, entity.js */
+
+IPA.sudorule = function () {
+
+ var that = IPA.entity({
+ 'name': 'sudorule'
+ });
+
+ that.init = function() {
+
+ var dialog = IPA.sudorule_add_dialog({
+ 'name': 'add',
+ 'title': 'Add New Rule'
+ });
+ that.add_dialog(dialog);
+ dialog.init();
+
+ var facet = IPA.sudorule_search_facet({
+ 'name': 'search',
+ 'label': 'Search'
+ });
+ that.add_facet(facet);
+
+ facet = IPA.sudorule_details_facet({
+ 'name': 'details'
+ });
+ that.add_facet(facet);
+
+ that.entity_init();
+ };
+
+ return that;
+};
+
+
+IPA.add_entity(IPA.sudorule());
+
+
+IPA.sudorule_add_dialog = function (spec) {
+
+ spec = spec || {};
+
+ var that = IPA.add_dialog(spec);
+
+ that.init = function() {
+
+ that.add_field(IPA.text_widget({name: 'cn', undo: false}));
+
+ that.add_dialog_init();
+ };
+
+ return that;
+};
+
+
+IPA.sudorule_search_facet = function (spec) {
+
+ spec = spec || {};
+
+ var that = IPA.search_facet(spec);
+
+ that.init = function() {
+
+ that.create_column({name:'cn'});
+ that.create_column({name:'description'});
+ that.create_column({name:'cmdcategory'});
+
+ that.search_facet_init();
+ };
+
+ return that;
+};
+
+
+IPA.sudorule_details_facet = function (spec) {
+
+ spec = spec || {};
+
+ var that = IPA.details_facet(spec);
+
+ that.init = function() {
+
+ var section;
+
+ if (IPA.layout) {
+ section = that.create_section({
+ 'name': 'general',
+ 'label': 'General',
+ 'template': 'sudorule-details-general.html #contents'
+ });
+
+ } else {
+ section = IPA.sudorule_details_general_section({
+ 'name': 'general',
+ 'label': 'General'
+ });
+ that.add_section(section);
+ }
+
+ section.create_text({ 'name': 'cn', 'read_only': true });
+ section.create_textarea({ 'name': 'description' });
+ section.create_radio({ 'name': 'ipaenabledflag' });
+
+ section = IPA.rule_details_section({
+ 'name': 'user',
+ 'label': 'Who',
+ 'field_name': 'usercategory',
+ 'options': [
+ { 'value': 'all', 'label': 'Anyone' },
+ { 'value': '', 'label': 'Specified Users and Groups' }
+ ],
+ 'tables': [
+ { 'field_name': 'memberuser_user' },
+ { 'field_name': 'memberuser_group' }
+ ]
+ });
+ that.add_section(section);
+
+ var category = section.create_radio({ name: 'usercategory', label: 'User category' });
+ section.add_field(IPA.sudorule_association_table_widget({
+ 'id': that.entity_name+'-memberuser_user',
+ 'name': 'memberuser_user', 'label': 'Users', 'category': category,
+ 'other_entity': 'user', 'add_method': 'add_user', 'remove_method': 'remove_user',
+ 'external': 'externaluser'
+ }));
+ section.add_field(IPA.sudorule_association_table_widget({
+ 'id': that.entity_name+'-memberuser_group',
+ 'name': 'memberuser_group', 'label': 'Groups', 'category': category,
+ 'other_entity': 'group', 'add_method': 'add_user', 'remove_method': 'remove_user'
+ }));
+
+ section = IPA.rule_details_section({
+ 'name': 'host',
+ 'label': 'Access this host',
+ 'field_name': 'hostcategory',
+ 'options': [
+ { 'value': 'all', 'label': 'Any Host' },
+ { 'value': '', 'label': 'Specified Hosts and Groups' }
+ ],
+ 'tables': [
+ { 'field_name': 'memberhost_host' },
+ { 'field_name': 'memberhost_hostgroup' }
+ ]
+ });
+ that.add_section(section);
+
+ category = section.create_radio({ 'name': 'hostcategory', 'label': 'Host category' });
+ section.add_field(IPA.sudorule_association_table_widget({
+ 'id': that.entity_name+'-memberhost_host',
+ 'name': 'memberhost_host', 'label': 'Host', 'category': category,
+ 'other_entity': 'host', 'add_method': 'add_host', 'remove_method': 'remove_host',
+ 'external': 'externalhost'
+ }));
+ section.add_field(IPA.sudorule_association_table_widget({
+ 'id': that.entity_name+'-memberhost_hostgroup',
+ 'name': 'memberhost_hostgroup', 'label': 'Groups', 'category': category,
+ 'other_entity': 'hostgroup', 'add_method': 'add_host', 'remove_method': 'remove_host'
+ }));
+
+ section = IPA.sudorule_details_command_section({
+ 'name': 'command',
+ 'label': 'Run Commands'
+ });
+ that.add_section(section);
+
+ section = IPA.sudorule_details_runas_section({
+ 'name': 'runas',
+ 'label': 'As Whom'
+ });
+ that.add_section(section);
+
+ that.details_facet_init();
+ };
+
+ that.update = function() {
+
+ var pkey = $.bbq.getState(that.entity_name + '-pkey', true) || '';
+
+ var modify_operation = {
+ 'execute': false,
+ 'command': IPA.command({
+ 'method': that.entity_name+'_mod',
+ 'args': [pkey],
+ 'options': {'all': true, 'rights': true}
+ })
+ };
+
+ var categories = {
+ 'usercategory': {
+ 'remove_values': false
+ },
+ 'hostcategory': {
+ 'remove_values': false
+ },
+ 'cmdcategory': {
+ 'remove_values': false
+ },
+ 'ipasudorunasusercategory': {
+ 'remove_values': false
+ },
+ 'ipasudorunasgroupcategory': {
+ 'remove_values': false
+ }
+ };
+
+ var member_operations = {
+ 'memberuser': {
+ 'category': 'usercategory',
+ 'has_values': false,
+ 'command': IPA.command({
+ 'method': that.entity_name+'_remove_user',
+ 'args': [pkey],
+ 'options': {'all': true, 'rights': true}
+ })
+ },
+ 'memberhost': {
+ 'category': 'hostcategory',
+ 'has_values': false,
+ 'command': IPA.command({
+ 'method': that.entity_name+'_remove_host',
+ 'args': [pkey],
+ 'options': {'all': true, 'rights': true}
+ })
+ },
+ 'memberallowcmd': {
+ 'category': 'cmdcategory',
+ 'has_values': false,
+ 'command': IPA.command({
+ 'method': that.entity_name+'_remove_allow_command',
+ 'args': [pkey],
+ 'options': {'all': true, 'rights': true}
+ })
+ },
+ 'ipasudorunas': {
+ 'category': 'ipasudorunasusercategory',
+ 'has_values': false,
+ 'command': IPA.command({
+ 'method': that.entity_name+'_remove_runasuser',
+ 'args': [pkey],
+ 'options': {'all': true, 'rights': true}
+ })
+ },
+ 'ipasudorunasgroup': {
+ 'category': 'ipasudorunasgroupcategory',
+ 'has_values': false,
+ 'command': IPA.command({
+ 'method': that.entity_name+'_remove_runasgroup',
+ 'args': [pkey],
+ 'options': {'all': true, 'rights': true}
+ })
+ }
+ };
+
+ var enable_operation = {
+ 'execute': false,
+ 'command': IPA.command({
+ 'method': that.entity_name+'_enable',
+ 'args': [pkey],
+ 'options': {'all': true, 'rights': true}
+ })
+ };
+
+ for (var i=0; i<that.sections.length; i++) {
+ var section = that.sections[i];
+
+ var div = $('#'+that.entity_name+'-'+that.name+'-'+section.name, that.container);
+
+ for (var j=0; j<section.fields.length; j++) {
+ var field = section.fields[j];
+
+ var span = $('span[name='+field.name+']', div).first();
+ var values = field.save();
+ if (!values) continue;
+
+ var param_info = IPA.get_param_info(that.entity_name, field.name);
+
+ // skip primary key
+ if (param_info && param_info['primary_key']) continue;
+
+ var p = field.name.indexOf('_');
+ if (p >= 0) {
+ // prepare command to remove members if needed
+ var attribute = field.name.substring(0, p);
+ var other_entity = field.name.substring(p+1);
+
+ if (member_operations[attribute] && values.length) {
+ member_operations[attribute].command.set_option(other_entity, values.join(','));
+ member_operations[attribute].has_values = true;
+ }
+ continue;
+ }
+
+ // skip unchanged field
+ if (!field.is_dirty(span)) continue;
+
+ // check enable/disable
+ if (field.name == 'ipaenabledflag') {
+ if (values[0] == 'FALSE') enable_operation.command.method = that.entity_name+'_disable';
+ enable_operation.execute = true;
+ continue;
+ }
+
+
+ if (categories[field.name] && values[0] == 'all') {
+ categories[field.name].remove_values = true;
+ }
+
+ // use setattr/addattr if param_info not available
+ if (!param_info) {
+ for (var k=0; k<values.length; k++) {
+ modify_operation.command.set_option(
+ k === 0 ? 'setattr' : 'addattr',
+ field.name+'='+values[k]);
+ modify_operation.execute = true;
+ }
+ continue;
+ }
+
+ // set modify options
+ if (values.length == 1) {
+ modify_operation.command.set_option(field.name, values[0]);
+ } else {
+ modify_operation.command.set_option(field.name, values);
+ }
+ modify_operation.execute = true;
+ }
+ }
+
+ var batch = IPA.batch_command({
+ 'name': 'sudorule_details_update',
+ 'on_success': function(data, text_status, xhr) {
+ that.refresh();
+ },
+ 'on_error': function(xhr, text_status, error_thrown) {
+ that.refresh();
+ }
+ });
+
+ for (var member_attribute in member_operations) {
+ var member_operation = member_operations[member_attribute];
+ if (member_operation.has_values &&
+ categories[member_operation.category].remove_values) {
+ batch.add_command(member_operation.command);
+ }
+ }
+
+ if (modify_operation.execute) batch.add_command(modify_operation.command);
+ if (enable_operation.execute) batch.add_command(enable_operation.command);
+
+ if (!batch.commands.length) {
+ that.refresh();
+ return;
+ }
+
+
+ batch.execute();
+ };
+
+ return that;
+};
+
+
+IPA.sudorule_details_general_section = function (spec){
+
+ spec = spec || {};
+
+ var that = IPA.details_section(spec);
+
+ that.create = function(container) {
+
+ var table = $('<table/>', {
+ 'style': 'width: 100%;'
+ }).appendTo(container);
+
+ var param_info = IPA.get_param_info(that.entity_name, 'cn');
+
+ var tr = $('<tr/>').appendTo(table);
+
+ var td = $('<td/>', {
+ style: 'width: 100px; text-align: right;',
+ html: param_info.label+':',
+ title: param_info ? param_info.doc : 'cn'
+ }).appendTo(tr);
+
+ td = $('<td/>').appendTo(tr);
+
+ var span = $('<span/>', {
+ name: 'cn',
+ title: param_info ? param_info.doc : 'cn'
+ }).appendTo(td);
+
+ $('<input/>', {
+ 'type': 'text',
+ 'name': 'cn',
+ 'size': 30
+ }).appendTo(span);
+
+ span.append(' ');
+
+ $('<span/>', {
+ 'name': 'undo',
+ 'class': 'ui-state-highlight ui-corner-all',
+ 'style': 'display: none;',
+ 'html': 'undo'
+ }).appendTo(span);
+
+ param_info = IPA.get_param_info(that.entity_name, 'description');
+
+ tr = $('<tr/>').appendTo(table);
+
+ td = $('<td/>', {
+ style: 'text-align: right; vertical-align: top;',
+ html: param_info.label+':',
+ title: param_info ? param_info.doc : 'description'
+ }).appendTo(tr);
+
+ td = $('<td/>').appendTo(tr);
+
+ span = $('<span/>', {
+ name: 'description',
+ title: param_info ? param_info.doc : 'description'
+ }).appendTo(td);
+
+ $('<textarea/>', {
+ 'name': 'description',
+ 'rows': 5,
+ 'style': 'width: 100%'
+ }).appendTo(span);
+
+ span.append(' ');
+
+ $('<span/>', {
+ 'name': 'undo',
+ 'class': 'ui-state-highlight ui-corner-all',
+ 'style': 'display: none;',
+ 'html': 'undo'
+ }).appendTo(span);
+
+ param_info = IPA.get_param_info(that.entity_name, 'ipaenabledflag');
+
+ tr = $('<tr/>').appendTo(table);
+
+ // TODO: Use i18n label
+ td = $('<td/>', {
+ style: 'text-align: right; vertical-align: top;',
+ html: 'Rule status:',
+ title: 'Rule status'
+ }).appendTo(tr);
+
+ td = $('<td/>').appendTo(tr);
+
+ span = $('<span/>', {
+ name: 'ipaenabledflag',
+ title: 'Rule status'
+ }).appendTo(td);
+
+ $('<input/>', {
+ 'type': 'radio',
+ 'name': 'ipaenabledflag',
+ 'value': 'TRUE'
+ }).appendTo(span);
+
+ span.append('Active');
+
+ $('<input/>', {
+ 'type': 'radio',
+ 'name': 'ipaenabledflag',
+ 'value': 'FALSE'
+ }).appendTo(span);
+
+ span.append('Inactive');
+
+ span.append(' ');
+
+ $('<span/>', {
+ 'name': 'undo',
+ 'class': 'ui-state-highlight ui-corner-all',
+ 'style': 'display: none;',
+ 'html': 'undo'
+ }).appendTo(span);
+ };
+
+ return that;
+};
+
+
+IPA.sudorule_details_command_section = function (spec){
+
+ spec = spec || {};
+
+ var that = IPA.details_section(spec);
+
+ that.init = function() {
+
+ var category = that.create_radio({'name': 'cmdcategory'});
+
+ that.add_field(IPA.sudorule_command_table_widget({
+ 'id': that.entity_name+'-memberallowcmd_sudocmd',
+ 'name': 'memberallowcmd_sudocmd', 'label': 'Command',
+ 'category': category, 'section': that,
+ 'other_entity': 'sudocmd', 'add_method': 'add_allow_command', 'remove_method': 'remove_allow_command'
+ }));
+ that.add_field(IPA.sudorule_command_table_widget({
+ 'id': that.entity_name+'-memberallowcmd_sudocmdgroup',
+ 'name': 'memberallowcmd_sudocmdgroup', 'label': 'Groups',
+ 'category': category, 'section': that,
+ 'other_entity': 'sudocmdgroup', 'add_method': 'add_allow_command', 'remove_method': 'remove_allow_command'
+ }));
+
+ that.add_field(IPA.sudorule_command_table_widget({
+ 'id': that.entity_name+'-memberdenycmd_sudocmd',
+ 'name': 'memberdenycmd_sudocmd', 'label': 'Command',
+ 'section': that,
+ 'other_entity': 'sudocmd', 'add_method': 'add_deny_command', 'remove_method': 'remove_deny_command'
+ }));
+ that.add_field(IPA.sudorule_command_table_widget({
+ 'id': that.entity_name+'-memberdenycmd_sudocmdgroup',
+ 'name': 'memberdenycmd_sudocmdgroup', 'label': 'Groups',
+ 'section': that,
+ 'other_entity': 'sudocmdgroup', 'add_method': 'add_deny_command', 'remove_method': 'remove_deny_command'
+ }));
+
+ that.section_init();
+ };
+
+ that.create = function(container) {
+
+ if (that.template) return;
+
+ var param_info = IPA.get_param_info(that.entity_name, 'cmdcategory');
+
+ var span = $('<span/>', {
+ name: 'cmdcategory',
+ title: param_info ? param_info.doc : 'cmdcategory'
+ }).appendTo(container);
+
+ // TODO: replace with i18n label
+ $('<h3/>', {
+ text: 'Allow',
+ title: 'Allow'
+ }).appendTo(span);
+
+ $('<input/>', {
+ type: 'radio',
+ name: 'cmdcategory',
+ value: 'all'
+ }).appendTo(span);
+
+ // TODO: replace with i18n label
+ span.append('Any Command');
+
+ span.append(' ');
+
+ $('<input/>', {
+ type: 'radio',
+ name: 'cmdcategory',
+ value: ''
+ }).appendTo(span);
+
+ // TODO: replace with i18n label
+ span.append('Specified Commands and Groups');
+
+ span.append(' ');
+
+ var undo = $('<span/>', {
+ 'name': 'undo',
+ 'class': 'ui-state-highlight ui-corner-all',
+ 'style': 'display: none;',
+ 'html': 'undo'
+ }).appendTo(span);
+
+ param_info = IPA.get_param_info(that.entity_name, 'memberallowcmd_sudocmd');
+
+ var table_span = $('<span/>', {
+ name: 'memberallowcmd_sudocmd',
+ title: param_info ? param_info.doc : 'memberallowcmd_sudocmd'
+ }).appendTo(span);
+
+ var field = that.get_field('memberallowcmd_sudocmd');
+ field.create(table_span);
+
+ param_info = IPA.get_param_info(that.entity_name, 'memberallowcmd_sudocmdgroup');
+
+ table_span = $('<span/>', {
+ name: 'memberallowcmd_sudocmdgroup',
+ title: param_info ? param_info.doc : 'memberallowcmd_sudocmdgroup'
+ }).appendTo(span);
+
+ field = that.get_field('memberallowcmd_sudocmdgroup');
+ field.create(table_span);
+
+ // TODO: replace with i18n label
+ $('<h3/>', {
+ text: 'Deny',
+ title: 'Deny'
+ }).appendTo(span);
+
+ param_info = IPA.get_param_info(that.entity_name, 'memberdenycmd_sudocmd');
+
+ table_span = $('<span/>', {
+ name: 'memberdenycmd_sudocmd',
+ title: param_info ? param_info.doc : 'memberdenycmd_sudocmd'
+ }).appendTo(span);
+
+ field = that.get_field('memberdenycmd_sudocmd');
+ field.create(table_span);
+
+ param_info = IPA.get_param_info(that.entity_name, 'memberdenycmd_sudocmdgroup');
+
+ table_span = $('<span/>', {
+ name: 'memberdenycmd_sudocmdgroup',
+ title: param_info ? param_info.doc : 'memberdenycmd_sudocmdgroup'
+ }).appendTo(span);
+
+ field = that.get_field('memberdenycmd_sudocmdgroup');
+ field.create(table_span);
+ };
+
+ that.setup = function(container) {
+
+ that.section_setup(container);
+
+ function update_tables(value) {
+
+ var enabled = ('' === value);
+
+ var field = that.get_field('memberallowcmd_sudocmd');
+ field.set_enabled(enabled);
+
+ field = that.get_field('memberallowcmd_sudocmdgroup');
+ field.set_enabled(enabled);
+ }
+
+ var cmdcategory = that.get_field('cmdcategory');
+ cmdcategory.reset = function() {
+ cmdcategory.widget_reset();
+ var values = cmdcategory.save();
+ if (values.length === 0) return;
+ var value = values[0];
+ update_tables(value);
+ };
+
+ var inputs = $('input[name=cmdcategory]', container);
+ inputs.change(function() {
+ var input = $(this);
+ var value = input.val();
+ update_tables(value);
+ });
+ };
+
+ return that;
+};
+
+
+IPA.sudorule_details_runas_section = function (spec){
+
+ spec = spec || {};
+
+ var that = IPA.details_section(spec);
+
+ that.init = function() {
+
+ var category = that.create_radio({ name: 'ipasudorunasusercategory', label: 'Run as User category' });
+ that.add_field(IPA.sudorule_association_table_widget({
+ 'id': that.entity_name+'-runasruser_user',
+ 'name': 'ipasudorunas_user', 'label': 'Users', 'category': category,
+ 'other_entity': 'user', 'add_method': 'add_runasuser', 'remove_method': 'remove_runasuser'
+ }));
+ that.add_field(IPA.sudorule_association_table_widget({
+ 'id': that.entity_name+'-runasuser_group',
+ 'name': 'ipasudorunas_group', 'label': 'Groups', 'category': category,
+ 'other_entity': 'group', 'add_method': 'add_runasuser', 'remove_method': 'remove_runasuser'
+ }));
+
+ category = that.create_radio({ name: 'ipasudorunasgroupcategory', label: 'Run as Group category' });
+ that.add_field(IPA.sudorule_association_table_widget({
+ 'id': that.entity_name+'-runasgroup_group',
+ 'name': 'ipasudorunasgroup_group', 'label': 'Groups', 'category': category,
+ 'other_entity': 'group', 'add_method': 'add_runasgroup', 'remove_method': 'remove_runasgroup'
+ }));
+
+ that.section_init();
+ };
+
+ that.create = function(container) {
+
+ if (that.template) return;
+
+ var param_info = IPA.get_param_info(that.entity_name, 'ipasudorunasusercategory');
+
+ var span = $('<span/>', {
+ name: 'ipasudorunasusercategory',
+ title: param_info ? param_info.doc : 'ipasudorunasusercategory'
+ }).appendTo(container);
+
+ $('<input/>', {
+ 'type': 'radio',
+ 'name': 'ipasudorunasusercategory',
+ 'value': 'all'
+ }).appendTo(span);
+
+ span.append('Anyone');
+
+ $('<input/>', {
+ 'type': 'radio',
+ 'name': 'ipasudorunasusercategory',
+ 'value': ''
+ }).appendTo(span);
+
+ span.append('Specified Users and Groups');
+
+ span.append(' ');
+
+ $('<span/>', {
+ 'name': 'undo',
+ 'class': 'ui-state-highlight ui-corner-all',
+ 'style': 'display: none;',
+ 'html': 'undo'
+ }).appendTo(span);
+
+ span.append('<br/>');
+
+ param_info = IPA.get_param_info(that.entity_name, 'ipasudorunas_user');
+
+ var table_span = $('<span/>', {
+ name: 'ipasudorunas_user',
+ title: param_info ? param_info.doc : 'ipasudorunas_user'
+ }).appendTo(span);
+
+ var field = that.get_field('ipasudorunas_user');
+ field.create(table_span);
+
+ param_info = IPA.get_param_info(that.entity_name, 'ipasudorunas_group');
+
+ table_span = $('<span/>', {
+ name: 'ipasudorunas_group',
+ title: param_info ? param_info.doc : 'ipasudorunas_group'
+ }).appendTo(span);
+
+ field = that.get_field('ipasudorunas_group');
+ field.create(table_span);
+
+ param_info = IPA.get_param_info(that.entity_name, 'ipasudorunasgroupcategory');
+
+ span = $('<span/>', {
+ name: 'ipasudorunasgroupcategory',
+ title: param_info ? param_info.doc : 'ipasudorunasgroupcategory'
+ }).appendTo(container);
+
+ $('<input/>', {
+ 'type': 'radio',
+ 'name': 'ipasudorunasgroupcategory',
+ 'value': 'all'
+ }).appendTo(span);
+
+ span.append('Any Group');
+
+ $('<input/>', {
+ 'type': 'radio',
+ 'name': 'ipasudorunasgroupcategory',
+ 'value': ''
+ }).appendTo(span);
+
+ span.append('Specified Groups');
+
+ span.append(' ');
+
+ $('<span/>', {
+ 'name': 'undo',
+ 'class': 'ui-state-highlight ui-corner-all',
+ 'style': 'display: none;',
+ 'html': 'undo'
+ }).appendTo(span);
+
+ span.append('<br/>');
+
+ param_info = IPA.get_param_info(that.entity_name, 'ipasudorunasgroup_group');
+
+ table_span = $('<span/>', {
+ name: 'ipasudorunasgroup_group',
+ title: param_info ? param_info.doc : 'ipasudorunasgroup_group'
+ }).appendTo(span);
+
+ field = that.get_field('ipasudorunasgroup_group');
+ field.create(table_span);
+ };
+
+ that.setup = function(container) {
+
+ that.section_setup(container);
+
+ function user_update_tables(value) {
+
+ var enabled = ('' === value);
+
+ var field = that.get_field('ipasudorunas_user');
+ field.set_enabled(enabled);
+
+ field = that.get_field('ipasudorunas_group');
+ field.set_enabled(enabled);
+ }
+
+ var user_category = that.get_field('ipasudorunasusercategory');
+ user_category.reset = function() {
+ user_category.widget_reset();
+ var values = user_category.save();
+ if (values.length === 0) return;
+ var value = values[0];
+ user_update_tables(value);
+ };
+
+ var user_inputs = $('input[name=ipasudorunasusercategory]', container);
+ user_inputs.change(function() {
+ var input = $(this);
+ var value = input.val();
+ user_update_tables(value);
+ });
+
+ function group_update_tables(value) {
+
+ var enabled = ('' === value);
+
+ var field = that.get_field('ipasudorunasgroup_group');
+ field.set_enabled(enabled);
+ }
+
+ var group_category = that.get_field('ipasudorunasgroupcategory');
+ group_category.reset = function() {
+ group_category.widget_reset();
+ var values = group_category.save();
+ if (values.length === 0) return;
+ var value = values[0];
+ group_update_tables(value);
+ };
+
+ var group_inputs = $('input[name=ipasudorunasgroupcategory]', container);
+ group_inputs.change(function() {
+ var input = $(this);
+ var value = input.val();
+ group_update_tables(value);
+ });
+ };
+
+ return that;
+};
+
+
+IPA.sudorule_association_table_widget = function (spec) {
+
+ spec = spec || {};
+
+ var that = IPA.rule_association_table_widget(spec);
+
+ that.external = spec.external;
+
+ that.create_add_dialog = function() {
+ var pkey = $.bbq.getState(that.entity_name + '-pkey', true) || '';
+ var label = IPA.metadata[that.other_entity].label;
+ var title = 'Add '+label+' to '+that.entity_name+' '+pkey;
+
+ var template;
+ if (IPA.layout) {
+ template = 'sudorule-'+that.other_entity+'-dialog.html #contents';
+ }
+
+ return IPA.sudorule_association_adder_dialog({
+ 'title': title,
+ 'entity_name': that.entity_name,
+ 'pkey': pkey,
+ 'other_entity': that.other_entity,
+ 'external': that.external,
+ 'template': template
+ });
+ };
+
+ that.load = function(result) {
+ that.values = result[that.name] || [];
+ if (that.external) {
+ var external_values = result[that.external] || [];
+ $.merge(that.values, external_values);
+ }
+ that.reset();
+ };
+
+ return that;
+};
+
+
+IPA.sudorule_association_adder_dialog = function (spec) {
+
+ spec = spec || {};
+
+ var that = IPA.association_adder_dialog(spec);
+
+ that.external = spec.external;
+
+ that.init = function() {
+
+ if (!that.columns.length) {
+ var pkey_name = IPA.metadata[that.other_entity].primary_key;
+ that.create_column({
+ name: pkey_name,
+ label: IPA.metadata[that.other_entity].label,
+ primary_key: true,
+ width: '200px'
+ });
+ }
+
+ that.available_table = IPA.table_widget({
+ name: 'available'
+ });
+
+ that.available_table.set_columns(that.columns);
+
+ that.available_table.init();
+
+ that.selected_table = IPA.table_widget({
+ name: 'selected'
+ });
+
+ that.selected_table.set_columns(that.columns);
+
+ that.selected_table.init();
+
+ that.association_adder_dialog_init();
+ };
+
+ that.create = function() {
+
+ // do not call that.dialog_create();
+
+ var search_panel = $('<div/>', {
+ 'class': 'adder-dialog-filter'
+ }).appendTo(that.container);
+
+ $('<input/>', {
+ type: 'text',
+ name: 'filter',
+ style: 'width: 244px'
+ }).appendTo(search_panel);
+
+ search_panel.append(' ');
+
+ $('<input/>', {
+ type: 'button',
+ name: 'find',
+ value: 'Find'
+ }).appendTo(search_panel);
+
+ var results_panel = $('<div/>', {
+ 'class': 'adder-dialog-results'
+ }).appendTo(that.container);
+
+ var class_name = that.external ? 'adder-dialog-internal' : 'adder-dialog-available';
+
+ var available_panel = $('<div/>', {
+ name: 'available',
+ 'class': class_name
+ }).appendTo(results_panel);
+
+ $('<div/>', {
+ html: 'Available',
+ 'class': 'ui-widget-header'
+ }).appendTo(available_panel);
+
+ that.available_table.create(available_panel);
+
+ var buttons_panel = $('<div/>', {
+ name: 'buttons',
+ 'class': 'adder-dialog-buttons'
+ }).appendTo(results_panel);
+
+ var p = $('<p/>').appendTo(buttons_panel);
+ $('<input />', {
+ type: 'button',
+ name: 'remove',
+ value: '<<'
+ }).appendTo(p);
+
+ p = $('<p/>').appendTo(buttons_panel);
+ $('<input />', {
+ type: 'button',
+ name: 'add',
+ value: '>>'
+ }).appendTo(p);
+
+ var selected_panel = $('<div/>', {
+ name: 'selected',
+ 'class': 'adder-dialog-selected'
+ }).appendTo(results_panel);
+
+ $('<div/>', {
+ html: 'Prospective',
+ 'class': 'ui-widget-header'
+ }).appendTo(selected_panel);
+
+ that.selected_table.create(selected_panel);
+
+ if (that.external) {
+ var external_panel = $('<div/>', {
+ name: 'external',
+ 'class': 'adder-dialog-external'
+ }).appendTo(results_panel);
+
+ $('<div/>', {
+ html: 'External',
+ 'class': 'ui-widget-header'
+ }).appendTo(external_panel);
+
+ $('<input/>', {
+ type: 'text',
+ name: 'external',
+ style: 'width: 244px'
+ }).appendTo(external_panel);
+ }
+ };
+
+ that.setup = function() {
+ that.association_adder_dialog_setup();
+ if (that.external) that.external_field = $('input[name=external]', that.container);
+ };
+
+ that.add = function() {
+ var rows = that.available_table.remove_selected_rows();
+ that.selected_table.add_rows(rows);
+
+ if (that.external) {
+ var pkey_name = IPA.metadata[that.other_entity].primary_key;
+ var value = that.external_field.val();
+ if (!value) return;
+
+ var record = {};
+ record[pkey_name] = value;
+ that.selected_table.add_record(record);
+ that.external_field.val('');
+ }
+ };
+
+ return that;
+};
+
+
+IPA.sudorule_command_table_widget = function (spec) {
+
+ spec = spec || {};
+
+ var that = IPA.association_table_widget(spec);
+
+ that.category = spec.category;
+ that.section = spec.section;
+
+ that.add = function(values, on_success, on_error) {
+
+ var pkey = $.bbq.getState(that.entity_name + '-pkey', true) || '';
+
+ var batch = IPA.batch_command({
+ 'on_success': on_success,
+ 'on_error': on_error
+ });
+
+ var command;
+
+ if (that.category) {
+ command = IPA.command({
+ 'method': that.entity_name+'_mod',
+ 'args': [pkey],
+ 'options': {'all': true, 'rights': true},
+ 'on_success': function() {
+ var record = {};
+ record[that.category.name] = [''];
+ that.category.load(record);
+ }
+ });
+ command.set_option(that.category.name, '');
+ batch.add_command(command);
+ }
+
+ command = IPA.command({
+ 'method': that.entity_name+'_'+that.add_method,
+ 'args': [pkey]
+ });
+ command.set_option(that.other_entity, values.join(','));
+ batch.add_command(command);
+
+ batch.execute();
+ };
+
+ that.remove = function(values, on_success, on_error) {
+
+ var pkey = $.bbq.getState(that.entity_name + '-pkey', true) || '';
+
+ var command = IPA.command({
+ 'method': that.entity_name+'_'+that.remove_method,
+ 'args': [pkey],
+ 'on_success': on_success,
+ 'on_error': on_error
+ });
+
+ command.set_option(that.other_entity, values.join(','));
+
+ command.execute();
+ };
+
+ return that;
+};
diff --git a/install/ui/test/README b/install/ui/test/README
new file mode 100755
index 000000000..96e7f9e80
--- /dev/null
+++ b/install/ui/test/README
@@ -0,0 +1 @@
+http://www.freeipa.org/page/UI_Unit_Tests
diff --git a/install/ui/test/aci_tests.html b/install/ui/test/aci_tests.html
new file mode 100755
index 000000000..7cdbeffa3
--- /dev/null
+++ b/install/ui/test/aci_tests.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Access Control Interface Test Suite</title>
+ <link rel="stylesheet" href="qunit.css" type="text/css" media="screen">
+ <script type="text/javascript" src="qunit.js"></script>
+
+
+
+ <script type="text/javascript" src="../jquery.js"></script>
+ <script type="text/javascript" src="../jquery.ba-bbq.js"></script>
+ <script type="text/javascript" src="../jquery-ui.js"></script>
+ <script type="text/javascript" src="../ipa.js"></script>
+ <script type="text/javascript" src="../widget.js"></script>
+ <script type="text/javascript" src="../details.js"></script>
+ <script type="text/javascript" src="../search.js"></script>
+ <script type="text/javascript" src="../add.js"></script>
+ <script type="text/javascript" src="../entity.js"></script>
+ <script type="text/javascript" src="../associate.js"></script>
+ <script type="text/javascript" src="../navigation.js"></script>
+ <script type="text/javascript" src="../aci.js"></script>
+
+ <script type="text/javascript" src="aci_tests.js"></script>
+</head>
+<body>
+ <h1 id="qunit-header">Certificate Test Suite</h1>
+ <h2 id="qunit-banner"></h2>
+ <div id="qunit-testrunner-toolbar"></div>
+ <h2 id="qunit-userAgent"></h2>
+ <ol id="qunit-tests"></ol>
+ <div id="qunit-fixture"></div>
+</body>
+</html>
diff --git a/install/ui/test/aci_tests.js b/install/ui/test/aci_tests.js
new file mode 100644
index 000000000..c51b556dc
--- /dev/null
+++ b/install/ui/test/aci_tests.js
@@ -0,0 +1,81 @@
+/* Authors:
+ * Adam Young <ayoung@redhat.com>
+ *
+ * Copyright (C) 2010 Red Hat
+ * see file 'COPYING' for use and warranty information
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 only
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+var target_section;
+var aci_container;
+
+module('aci',{
+ setup: function() {
+ IPA.ajax_options.async = false;
+ IPA.init(
+ "data",
+ true,
+ function(data, text_status, xhr) {
+ ok(true, "ipa_init() succeeded.");
+ },
+ function(xhr, text_status, error_thrown) {
+ ok(false, "ipa_init() failed: "+error_thrown);
+ }
+ );
+ aci_container = $('<div id="aci"/>').appendTo(document.body);
+ target_section = IPA.target_section();
+ target_section.create(aci_container);
+ },
+ teardown: function() {
+ aci_container.remove();
+ }}
+);
+
+
+test("Testing aci grouptarget.", function() {
+ var sample_data_filter_only = {"targetgroup":"ipausers"};
+ target_section.load(sample_data_filter_only);
+ ok($('#aci_by_group')[0].checked, 'aci_by_group control selected');
+ ok ($('#aci_target_group_select option').length > 2,'group select populated');
+
+});
+
+
+
+test("Testing aci object type.", function() {
+ var sample_data_filter_only = {"type":"hostgroup"};
+ target_section.load(sample_data_filter_only);
+ ok($('.aci-attribute', aci_container).length > 4);
+ ok($('#aci_by_type')[0].checked, 'aci_by_type control selected');
+
+});
+
+
+test("Testing aci filter only.", function() {
+
+ var sample_data_filter_only = {"filter":"somevalue"};
+
+ target_section.load(sample_data_filter_only);
+
+ var filter_radio = $('#aci_by_filter');
+
+ ok(filter_radio.length,'find "filter_only_radio" control');
+ ok(filter_radio[0].checked,'filter_only_radio control is checked');
+
+});
+
+
+
diff --git a/install/ui/test/all_tests.html b/install/ui/test/all_tests.html
new file mode 100644
index 000000000..6a29daffa
--- /dev/null
+++ b/install/ui/test/all_tests.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Complete Test Suite</title>
+ <link rel="stylesheet" href="qunit.css" type="text/css" media="screen">
+ <script type="text/javascript" src="qunit.js"></script>
+ <script type="text/javascript" src="../jquery.js"></script>
+ <script type="text/javascript" src="../jquery.ba-bbq.js"></script>
+ <script type="text/javascript" src="../jquery-ui.js"></script>
+ <script type="text/javascript" src="../ipa.js"></script>
+ <script type="text/javascript" src="../widget.js"></script>
+ <script type="text/javascript" src="../details.js"></script>
+ <script type="text/javascript" src="../search.js"></script>
+ <script type="text/javascript" src="../add.js"></script>
+ <script type="text/javascript" src="../entity.js"></script>
+ <script type="text/javascript" src="../associate.js"></script>
+ <script type="text/javascript" src="../navigation.js"></script>
+ <script type="text/javascript" src="../certificate.js"></script>
+ <script type="text/javascript" src="../aci.js"></script>
+ <script type="text/javascript" src="ipa_tests.js"></script>
+ <script type="text/javascript" src="details_tests.js"></script>
+ <script type="text/javascript" src="entity_tests.js"></script>
+ <script type="text/javascript" src="association_tests.js"></script>
+ <script type="text/javascript" src="navigation_tests.js"></script>
+ <script type="text/javascript" src="certificate_tests.js"></script>
+ <script type="text/javascript" src="aci_tests.js"></script>
+</head>
+<body>
+ <h1 id="qunit-header">Complete Test Suite</h1>
+ <h2 id="qunit-banner"></h2>
+ <div id="qunit-testrunner-toolbar"></div>
+ <h2 id="qunit-userAgent"></h2>
+ <ol id="qunit-tests"></ol>
+ <div id="qunit-fixture"></div>
+</body>
+</html>
diff --git a/install/ui/test/association_tests.html b/install/ui/test/association_tests.html
new file mode 100644
index 000000000..40b3c208d
--- /dev/null
+++ b/install/ui/test/association_tests.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Association Test Suite</title>
+ <link rel="stylesheet" href="qunit.css" type="text/css" media="screen">
+ <script type="text/javascript" src="qunit.js"></script>
+ <script type="text/javascript" src="../jquery.js"></script>
+ <script type="text/javascript" src="../ipa.js"></script>
+ <script type="text/javascript" src="../details.js"></script>
+ <script type="text/javascript" src="../search.js"></script>
+ <script type="text/javascript" src="../add.js"></script>
+ <script type="text/javascript" src="../associate.js"></script>
+ <script type="text/javascript" src="association_tests.js"></script>
+</head>
+<body>
+ <h1 id="qunit-header">Association Test Suite</h1>
+ <h2 id="qunit-banner"></h2>
+ <div id="qunit-testrunner-toolbar"></div>
+ <h2 id="qunit-userAgent"></h2>
+ <ol id="qunit-tests"></ol>
+ <div id="qunit-fixture"></div>
+</body>
+</html>
diff --git a/install/ui/test/association_tests.js b/install/ui/test/association_tests.js
new file mode 100644
index 000000000..a65678a7f
--- /dev/null
+++ b/install/ui/test/association_tests.js
@@ -0,0 +1,127 @@
+/* Authors:
+ * Endi Sukma Dewata <edewata@redhat.com>
+ *
+ * Copyright (C) 2010 Red Hat
+ * see file 'COPYING' for use and warranty information
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+module('associate');
+
+
+test("Testing serial_associator().", function() {
+
+ expect(10);
+
+ var orig_ipa_cmd = IPA.cmd;
+
+ var counter = 0;
+
+ var params = {
+ method: "add_member",
+ pkey: "test",
+ entity_name: "user",
+ other_entity: "group"
+ };
+
+ params.values = ['user1', 'user2', 'user3'];
+
+ IPA.cmd = function(name, args, options, win_callback, fail_callback, objname) {
+ counter++;
+
+ equals(
+ name, params.method,
+ "Checking IPA.cmd() parameter: method"
+ );
+
+ equals(
+ objname, params.other_entity,
+ "Checking IPA.cmd() parameter: object name"
+ );
+
+ equals(
+ args[0], "user"+counter,
+ "Checking IPA.cmd() parameter: primary key"
+ );
+
+ var response = {};
+ win_callback(response);
+ return 0;
+ };
+
+ params.on_success = function() {
+ ok(true, "on_success() is invoked.");
+ };
+
+ var associator = serial_associator(params);
+ associator.execute();
+
+ IPA.cmd = orig_ipa_cmd;
+});
+
+test("Testing bulk_associator().", function() {
+
+ expect(5);
+
+ var orig_ipa_cmd = IPA.cmd;
+
+ var counter = 0;
+
+ var params = {
+ method: "add_member",
+ pkey: "test",
+ entity_name: "user",
+ other_entity: "group"
+ };
+
+ params.values = ['user1', 'user2', 'user3'];
+
+ IPA.cmd = function(name, args, options, win_callback, fail_callback, objname) {
+ counter++;
+
+ equals(
+ name, params.method,
+ "Checking IPA.cmd() parameter: method"
+ );
+
+ equals(
+ objname, params.entity_name,
+ "Checking IPA.cmd() parameter: object name"
+ );
+
+ equals(
+ args[0], params.pkey,
+ "Checking IPA.cmd() parameter: primary key"
+ );
+
+ equals(
+ options[params.other_entity], "user1,user2,user3",
+ "Checking IPA.cmd() parameter: options[\""+params.other_entity+"\"]"
+ );
+
+ var response = {};
+ win_callback(response);
+ return 0;
+ };
+
+ params.on_success = function() {
+ ok(true, "on_success() is invoked.");
+ };
+
+ var associator = bulk_associator(params);
+ associator.execute();
+
+ IPA.cmd = orig_ipa_cmd;
+});
diff --git a/install/ui/test/certificate_tests.html b/install/ui/test/certificate_tests.html
new file mode 100755
index 000000000..5b411ff13
--- /dev/null
+++ b/install/ui/test/certificate_tests.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Certificate Test Suite</title>
+ <link rel="stylesheet" href="qunit.css" type="text/css" media="screen">
+ <script type="text/javascript" src="qunit.js"></script>
+ <script type="text/javascript" src="../jquery.js"></script>
+ <script type="text/javascript" src="../jquery.ba-bbq.js"></script>
+ <script type="text/javascript" src="../jquery-ui.js"></script>
+ <script type="text/javascript" src="../ipa.js"></script>
+ <script type="text/javascript" src="../details.js"></script>
+ <script type="text/javascript" src="../search.js"></script>
+ <script type="text/javascript" src="../add.js"></script>
+ <script type="text/javascript" src="../navigation.js"></script>
+ <script type="text/javascript" src="../certificate.js"></script>
+ <script type="text/javascript" src="certificate_tests.js"></script>
+</head>
+<body>
+ <h1 id="qunit-header">Certificate Test Suite</h1>
+ <h2 id="qunit-banner"></h2>
+ <div id="qunit-testrunner-toolbar"></div>
+ <h2 id="qunit-userAgent"></h2>
+ <ol id="qunit-tests"></ol>
+ <div id="qunit-fixture"></div>
+</body>
+</html>
diff --git a/install/ui/test/certificate_tests.js b/install/ui/test/certificate_tests.js
new file mode 100755
index 000000000..c50ec1867
--- /dev/null
+++ b/install/ui/test/certificate_tests.js
@@ -0,0 +1,81 @@
+/* Authors:
+ * Endi Sukma Dewata <edewata@redhat.com>
+ *
+ * Copyright (C) 2010 Red Hat
+ * see file 'COPYING' for use and warranty information
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+module('certificate');
+
+test("Testing certificate_parse_dn().", function() {
+
+ same(
+ certificate_parse_dn(), {},
+ "Checking certificate_parse_dn()"
+ );
+
+ same(
+ certificate_parse_dn(''), {},
+ "Checking certificate_parse_dn('')"
+ );
+
+ same(
+ certificate_parse_dn('c=US'), {'c': 'US'},
+ "Checking certificate_parse_dn('c=US')"
+ );
+
+ same(
+ certificate_parse_dn('st=TX,c=US'), {'st': 'TX','c': 'US'},
+ "Checking certificate_parse_dn('st=TX,c=US')"
+ );
+
+ same(
+ certificate_parse_dn('c=US,st=TX'), {'st': 'TX','c': 'US'},
+ "Checking certificate_parse_dn('c=US,st=TX')"
+ );
+
+ same(
+ certificate_parse_dn(' st = New Mexico , c = US '), {'st': 'New Mexico','c': 'US'},
+ "Checking certificate_parse_dn(' st = New Mexico , c = US ')"
+ );
+
+ same(
+ certificate_parse_dn('ST=TX,C=US'), {'st': 'TX','c': 'US'},
+ "Checking certificate_parse_dn('ST=TX,C=US')"
+ );
+
+ same(
+ certificate_parse_dn('cn=dev.example.com,ou=Engineering,o=Example,l=Austin,ST=TX,C=US'),
+ { 'cn': 'dev.example.com',
+ 'ou': 'Engineering',
+ 'o': 'Example',
+ 'l': 'Austin',
+ 'st': 'TX',
+ 'c': 'US'
+ },
+ "Checking certificate_parse_dn('cn=dev.example.com,ou=Engineering,o=Example,l=Austin,ST=TX,C=US')"
+ );
+
+ same(
+ certificate_parse_dn('cn=John Smith,ou=Developers,ou=Users,dc=example,dc=com'),
+ {
+ 'cn': 'John Smith',
+ 'ou': ['Developers','Users'],
+ 'dc': ['example', 'com']
+ },
+ "Checking certificate_parse_dn('cn=John Smith,ou=Developers,ou=Users,dc=example,dc=com')"
+ );
+});
diff --git a/install/ui/test/data/aci_find.json b/install/ui/test/data/aci_find.json
new file mode 100644
index 000000000..00682ffd2
--- /dev/null
+++ b/install/ui/test/data/aci_find.json
@@ -0,0 +1,63 @@
+{
+ "error": null,
+ "id": 6,
+ "result": {
+ "count": 53,
+ "result": [
+ "(targetattr != \"userPassword || krbPrincipalKey || sambaLMPassword || sambaNTPassword || passwordHistory || krbMKey\")(version 3.0;acl \"Enable Anonymous access\";allow (read,search,compare) userdn = \"ldap:///anyone\";)",
+ "(targetattr != \"userPassword || krbPrincipalKey || sambaLMPassword || sambaNTPassword || passwordHistory || krbMKey || ipaUniqueId || memberOf || serverHostName || enrolledBy\")(version 3.0;acl \"Admin can manage any entry\";allow (all) groupdn = \"ldap:///cn=admins,cn=groups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\";)",
+ "(targetattr = \"userPassword || krbPrincipalKey || sambaLMPassword || sambaNTPassword\")(version 3.0;acl \"Self can write own password\";allow (write) userdn = \"ldap:///self\";)",
+ "(targetattr = \"userPassword || krbPrincipalKey || sambaLMPassword || sambaNTPassword || passwordHistory\")(version 3.0;acl \"Admins can write passwords\";allow (add,delete,write) groupdn = \"ldap:///cn=admins,cn=groups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\";)",
+ "(targetattr = \"userPassword || krbPrincipalKey || sambaLMPassword || sambaNTPassword || passwordHistory\")(version 3.0;acl \"Password change service can read/write passwords\";allow (read,write) userdn = \"ldap:///krbprincipalname=kadmin/changepw@AYOUNG.BOSTON.DEVEL.REDHAT.COM,cn=AYOUNG.BOSTON.DEVEL.REDHAT.COM,cn=kerberos,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\";)",
+ "(targetattr = \"userPassword || krbPrincipalKey || krbPasswordExpiration || sambaLMPassword || sambaNTPassword || passwordHistory\")(version 3.0;acl \"KDC System Account can access passwords\";allow (all) userdn = \"ldap:///uid=kdc,cn=sysaccounts,cn=etc,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\";)",
+ "(targetattr = \"krbLastSuccessfulAuth || krbLastFailedAuth || krbLoginFailedCount\")(version 3.0;acl \"KDC System Account can update some fields\";allow (write) userdn = \"ldap:///uid=kdc,cn=sysaccounts,cn=etc,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\";)",
+ "(targetattr = \"krbPrincipalName || krbCanonicalName || krbUPEnabled || krbMKey || krbTicketPolicyReference || krbPrincipalExpiration || krbPasswordExpiration || krbPwdPolicyReference || krbPrincipalType || krbPwdHistory || krbLastPwdChange || krbPrincipalAliases || krbExtraData || krbLastSuccessfulAuth || krbLastFailedAuth || krbLoginFailedCount\")(version 3.0;acl \"Only the KDC System Account has access to kerberos material\";allow (read,search,compare) userdn = \"ldap:///uid=kdc,cn=sysaccounts,cn=etc,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\";)",
+ "(targetattr = \"krbMaxPwdLife || krbMinPwdLife || krbPwdMinDiffChars || krbPwdMinLength || krbPwdHistoryLength\")(targetfilter = \"(objectClass=krbPwdPolicy)\")(version 3.0;acl \"Admins can write password policies\";allow (read,search,compare,write) groupdn = \"ldap:///cn=admins,cn=groups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\";)",
+ "(targetattr = \"givenName || sn || cn || displayName || title || initials || loginShell || gecos || homePhone || mobile || pager || facsimileTelephoneNumber || telephoneNumber || street || roomNumber || l || st || postalCode || manager || secretary || description || carLicense || labeledURI || inetUserHTTPURL || seeAlso || employeeType || businessCategory || ou\")(version 3.0;acl \"Self service\";allow (write) userdn = \"ldap:///self\";)",
+ "(targetattr = \"objectClass\")(target = \"ldap:///cn=certificate status,cn=virtual operations,cn=etc,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\")(version 3.0;acl \"Get Certificates status from the CA\";allow (write) groupdn = \"ldap:///cn=certificate_status,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\";)",
+ "(target = \"ldap:///uid=*,cn=users,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\")(version 3.0;acl \"Remove Users\";allow (delete) groupdn = \"ldap:///cn=removeusers,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\";)",
+ "(targetattr = \"member\")(target = \"ldap:///cn=*,cn=groups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\")(version 3.0;acl \"Modify group membership\";allow (write) groupdn = \"ldap:///cn=modifygroupmembership,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\";)",
+ "(target = \"ldap:///krbprincipalname=*,cn=services,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\")(version 3.0;acl \"Add Services\";allow (add) groupdn = \"ldap:///cn=addservices,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\";)",
+ "(targetattr = \"userPassword || krbPrincipalKey || sambaLMPassword || sambaNTPassword || passwordHistory\")(version 3.0;acl \"change_password\";allow (write) groupdn = \"ldap:///cn=change_password,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\";)",
+ "(target = \"ldap:///cn=*,cn=groups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\")(version 3.0;acl \"Add Groups\";allow (add) groupdn = \"ldap:///cn=addgroups,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\";)",
+ "(targetattr = \"cn || description\")(target = \"ldap:///cn=*,cn=hostgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\")(version 3.0;acl \"Modify Hostgroups\";allow (write) groupdn = \"ldap:///cn=modifyhostgroups,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\";)",
+ "(targetattr = \"cn || description\")(target = \"ldap:///cn=*,cn=rolegroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\")(version 3.0;acl \"Modify Roles\";allow (write) groupdn = \"ldap:///cn=modifyroles,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\";)",
+ "(targetattr = \"memberhost || externalhost || memberuser || member\")(target = \"ldap:///ipauniqueid=*,cn=ng,cn=alt,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\")(version 3.0;acl \"Modify netgroup membership\";allow (write) groupdn = \"ldap:///cn=modifynetgroupmembership,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\";)",
+ "(targetattr = \"userCertificate\")(target = \"ldap:///krbprincipalname=*,cn=services,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\")(version 3.0;acl \"Modify Services\";allow (write) groupdn = \"ldap:///cn=modifyservices,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\";)",
+ "(target = \"ldap:///cn=*,cn=hostgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\")(version 3.0;acl \"Add Hostgroups\";allow (add) groupdn = \"ldap:///cn=addhostgroups,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\";)",
+ "(target = \"ldap:///automountmapname=*,cn=automount,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\")(version 3.0;acl \"Remove automount maps\";allow (delete) groupdn = \"ldap:///cn=removeautomount,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\";)",
+ "(target = \"ldap:///automountkey=*,automountmapname=*,cn=automount,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\")(version 3.0;acl \"Remove automount keys\";allow (delete) groupdn = \"ldap:///cn=removeautomount,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\";)",
+ "(target = \"ldap:///krbprincipalname=*,cn=services,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\")(version 3.0;acl \"Remove Services\";allow (delete) groupdn = \"ldap:///cn=removeservices,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\";)",
+ "(target = \"ldap:///uid=*,cn=users,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\")(version 3.0;acl \"Add Users\";allow (add) groupdn = \"ldap:///cn=addusers,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\";)",
+ "(targetattr = \"cn || description || l || location || nshardwareplatform || nsosversion\")(target = \"ldap:///fqdn=*,cn=computers,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\")(version 3.0;acl \"Modify Hosts\";allow (write) groupdn = \"ldap:///cn=modifyhosts,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\";)",
+ "(targetattr = \"member\")(target = \"ldap:///cn=ipausers,cn=groups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\")(version 3.0;acl \"Add user to default group\";allow (write) groupdn = \"ldap:///cn=add_user_to_default_group,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\";)",
+ "(target = \"ldap:///cn=*,cn=hostgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\")(version 3.0;acl \"Remove Hostgroups\";allow (delete) groupdn = \"ldap:///cn=removehostgroups,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\";)",
+ "(target = \"ldap:///ipauniqueid=*,cn=entitlements,cn=etc,dc=greyoak,dc=com\")(version 3.0;acl \"Remove entitlement entries\";allow (delete) groupdn = \"ldap:///cn=removeentitlements,cn=taskgroups,cn=accounts,dc=greyoak,dc=com\";)",
+ "(targetattr = \"krbPrincipalName || enrolledBy || objectClass\")(target = \"ldap:///fqdn=*,cn=computers,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\")(version 3.0;acl \"Enroll a host\";allow (write) groupdn = \"ldap:///cn=enroll_host,cn=taskgroups, cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\";)",
+ "(target = \"ldap:///fqdn=*,cn=computers,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\")(version 3.0;acl \"Add Hosts\";allow (add) groupdn = \"ldap:///cn=addhosts,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\";)",
+ "(target = \"ldap:///ipauniqueid=*,cn=ng,cn=alt,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\")(version 3.0;acl \"Remove netgroups\";allow (delete) groupdn = \"ldap:///cn=removenetgroups,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\";)",
+ "(targetattr = \"description\")(target = \"ldap:///ipauniqueid=*,cn=ng,cn=alt,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\")(version 3.0;acl \"Modify netgroups\";allow (write) groupdn = \"ldap:///cn=modifynetgroups,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\";)",
+ "(targetattr = \"member\")(target = \"ldap:///cn=*,cn=rolegroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\")(version 3.0;acl \"Modify role group membership\";allow (write) groupdn = \"ldap:///cn=modifyrolegroupmembership,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\";)",
+ "(targetattr = \"objectClass\")(target = \"ldap:///cn=request certificate,cn=virtual operations,cn=etc,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\")(version 3.0;acl \"Request Certificates from the CA\";allow (write) groupdn = \"ldap:///cn=request_certs,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\";)",
+ "(targetattr = \"userCertificate\")(target = \"ldap:///ipauniqueid=*,cn=entitlements,cn=etc,dc=greyoak,dc=com\")(version 3.0;acl \"Modify entitlements\";allow (write) groupdn = \"ldap:///cn=modifyentitlements,cn=taskgroups,cn=accounts,dc=greyoak,dc=com\";)",
+ "(targetattr = \"member\")(target = \"ldap:///cn=*,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\")(version 3.0;acl \"Modify task group membership\";allow (write) groupdn = \"ldap:///cn=modifytaskgroupmembership,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\";)",
+ "(target = \"ldap:///cn=*,cn=rolegroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\")(version 3.0;acl \"Add Roles\";allow (add) groupdn = \"ldap:///cn=addroles,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\";)",
+ "(targetattr = \"objectClass\")(target = \"ldap:///cn=certificate remove hold,cn=virtual operations,cn=etc,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\")(version 3.0;acl \"Certificate Remove Hold\";allow (write) groupdn = \"ldap:///cn=certificate_remove_hold,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\";)",
+ "(target = \"ldap:///cn=*,cn=rolegroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\")(version 3.0;acl \"Remove Roles\";allow (delete) groupdn = \"ldap:///cn=removeroles,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\";)",
+ "(target = \"ldap:///automountmapname=*,cn=automount,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\")(version 3.0;acl \"Add automount maps\";allow (add) groupdn = \"ldap:///cn=addautomount,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\";)",
+ "(targetattr = \"givenName || sn || cn || displayName || title || initials || loginShell || gecos || homePhone || mobile || pager || facsimileTelephoneNumber || telephoneNumber || street || roomNumber || l || st || postalCode || manager || secretary || description || carLicense || labeledURI || inetUserHTTPURL || seeAlso || employeeType || businessCategory || ou || mepManagedEntry || objectclass\")(target = \"ldap:///uid=*,cn=users,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\")(version 3.0;acl \"Modify Users\";allow (write) groupdn = \"ldap:///cn=modifyusers,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\";)",
+ "(target = \"ldap:///ipauniqueid=*,cn=ng,cn=alt,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\")(version 3.0;acl \"Add netgroups\";allow (add) groupdn = \"ldap:///cn=addnetgroups,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\";)",
+ "(target = \"ldap:///fqdn=*,cn=computers,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\")(version 3.0;acl \"Remove Hosts\";allow (delete) groupdn = \"ldap:///cn=removehosts,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\";)",
+ "(target = \"ldap:///ipauniqueid=*,cn=entitlements,cn=etc,dc=greyoak,dc=com\")(version 3.0;acl \"Add entitlements\";allow (add) groupdn = \"ldap:///cn=addentitlements,cn=taskgroups,cn=accounts,dc=greyoak,dc=com\";)",
+ "(target = \"ldap:///automountkey=*,automountmapname=*,cn=automount,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\")(version 3.0;acl \"Add automount keys\";allow (add) groupdn = \"ldap:///cn=addautomount,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\";)",
+ "(target = \"ldap:///cn=*,cn=groups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\")(version 3.0;acl \"Remove Groups\";allow (delete) groupdn = \"ldap:///cn=removegroups,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\";)",
+ "(targetattr = \"objectClass\")(target = \"ldap:///cn=retrieve certificate,cn=virtual operations,cn=etc,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\")(version 3.0;acl \"Retrieve Certificates from the CA\";allow (write) groupdn = \"ldap:///cn=retrieve_certs,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\";)",
+ "(targetattr = \"objectClass\")(target = \"ldap:///cn=revoke certificate,cn=virtual operations,cn=etc,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\")(version 3.0;acl \"Revoke Certificate\";allow (write) groupdn = \"ldap:///cn=revoke_certificate,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\";)",
+ "(targetattr = \"krbPrincipalKey || krbLastPwdChange\")(target = \"ldap:///fqdn=*,cn=computers,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\")(version 3.0;acl \"Manage host keytab\";allow (write) groupdn = \"ldap:///cn=manage_host_keytab,cn=taskgroups, cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\";)",
+ "(targetattr = \"cn || description || gidnumber || objectclass || mepManagedBy\")(target = \"ldap:///cn=*,cn=groups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\")(version 3.0;acl \"Modify Groups\";allow (write) groupdn = \"ldap:///cn=modifygroups,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\";)",
+ "(targetattr = \"member\")(target = \"ldap:///cn=*,cn=hostgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\")(version 3.0;acl \"Modify host group membership\";allow (write) groupdn = \"ldap:///cn=modifyhostgroupmembership,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\";)",
+ "(targetattr = \"objectClass\")(target = \"ldap:///cn=request certificate different host,cn=virtual operations,cn=etc,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\")(version 3.0;acl \"Request Certificates from a different host\";allow (write) groupdn = \"ldap:///cn=request_cert_different_host,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\";)"
+ ],
+ "summary": "53 ACIs matched"
+ }
+}
diff --git a/install/ui/test/data/automountlocation_find.json b/install/ui/test/data/automountlocation_find.json
new file mode 100644
index 000000000..ea1a54e83
--- /dev/null
+++ b/install/ui/test/data/automountlocation_find.json
@@ -0,0 +1,17 @@
+{
+ "error": null,
+ "id": 6,
+ "result": {
+ "count": 1,
+ "result": [
+ {
+ "cn": [
+ "default"
+ ],
+ "dn": "cn=default,cn=automount,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com"
+ }
+ ],
+ "summary": null,
+ "truncated": false
+ }
+} \ No newline at end of file
diff --git a/install/ui/test/data/automountlocation_show.json b/install/ui/test/data/automountlocation_show.json
new file mode 100644
index 000000000..97ce2624f
--- /dev/null
+++ b/install/ui/test/data/automountlocation_show.json
@@ -0,0 +1,14 @@
+{
+ "error": null,
+ "id": 6,
+ "result": {
+ "result": {
+ "cn": [
+ "default"
+ ],
+ "dn": "cn=default,cn=automount,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com"
+ },
+ "summary": null,
+ "value": "default"
+ }
+} \ No newline at end of file
diff --git a/install/ui/test/data/cert_remove_hold.json b/install/ui/test/data/cert_remove_hold.json
new file mode 100644
index 000000000..12548cb20
--- /dev/null
+++ b/install/ui/test/data/cert_remove_hold.json
@@ -0,0 +1,9 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "result": {
+ "unrevoked": true
+ }
+ }
+}
diff --git a/install/ui/test/data/cert_request.json b/install/ui/test/data/cert_request.json
new file mode 100644
index 000000000..c4410729a
--- /dev/null
+++ b/install/ui/test/data/cert_request.json
@@ -0,0 +1,17 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "result": {
+ "certificate": "MIICAjCCAWugAwIBAgICBAswDQYJKoZIhvcNAQEFBQAwKTEnMCUGA1UEAxMeSVBBIFRlc3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTEwMTAwNzIzMzk0NFoXDTE1MTAwNzIzMzk0NFowKDEMMAoGA1UECgwDSVBBMRgwFgYDVQQDDA9kZXYuZXhhbXBsZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOTXyj8grVB7Rj95RFawgdwn9OYZ03LWHZ+HMYggu2/xCCrUrdThP14YBlVqZumjVJSclj6T4ACjjdPJq9JTTmx7gMizDTReus7IPlS6fCxb5v5whQJZsEksXL04OxUMl25euPRFkYcTK1rdW47+AkG10j1qeNW+B6CpdQGR6eM/AgMBAAGjOjA4MBEGCWCGSAGG+EIBAQQEAwIGQDATBgNVHSUEDDAKBggrBgEFBQcDATAOBgNVHQ8BAf8EBAMCBPAwDQYJKoZIhvcNAQEFBQADgYEASIhq723VL5xP0q51MYXFlGU1boD7pPD1pIQspD/MjCIEupcbH2kAo4wf+EiKsXR0rs+WZkaSgvFqaM4OQ2kWSFTiqmFXFDBEi6EFr68yLg7IpQpNTzVBXERd8B4GwNL9wrRw60jPXlUK29DPBsdGq8fDgX18l39wKkWXv7p1to4=",
+ "issuer": "CN=Certificate Authority,O=IPA",
+ "md5_fingerprint": "08:86:a9:f9:87:af:0d:d7:42:01:e0:5f:12:9b:32:7f",
+ "request_id": "1",
+ "serial_number": "1",
+ "sha1_fingerprint": "b8:4c:4b:79:4f:13:03:79:47:08:fa:6b:52:63:3d:f9:15:8e:7e:dc",
+ "subject": "CN=dev.example.com,O=IPA",
+ "valid_not_after": "Tue Oct 13 01:59:32 2015 UTC",
+ "valid_not_before": "Wed Oct 13 01:59:32 2010 UTC"
+ }
+ }
+}
diff --git a/install/ui/test/data/cert_revoke.json b/install/ui/test/data/cert_revoke.json
new file mode 100644
index 000000000..3fca1ee64
--- /dev/null
+++ b/install/ui/test/data/cert_revoke.json
@@ -0,0 +1,9 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "result": {
+ "revoked": true
+ }
+ }
+}
diff --git a/install/ui/test/data/cert_show.json b/install/ui/test/data/cert_show.json
new file mode 100644
index 000000000..71d895f05
--- /dev/null
+++ b/install/ui/test/data/cert_show.json
@@ -0,0 +1,16 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "result": {
+ "certificate": "MIICAjCCAWugAwIBAgICBAswDQYJKoZIhvcNAQEFBQAwKTEnMCUGA1UEAxMeSVBBIFRlc3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTEwMTAwNzIzMzk0NFoXDTE1MTAwNzIzMzk0NFowKDEMMAoGA1UECgwDSVBBMRgwFgYDVQQDDA9kZXYuZXhhbXBsZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOTXyj8grVB7Rj95RFawgdwn9OYZ03LWHZ+HMYggu2/xCCrUrdThP14YBlVqZumjVJSclj6T4ACjjdPJq9JTTmx7gMizDTReus7IPlS6fCxb5v5whQJZsEksXL04OxUMl25euPRFkYcTK1rdW47+AkG10j1qeNW+B6CpdQGR6eM/AgMBAAGjOjA4MBEGCWCGSAGG+EIBAQQEAwIGQDATBgNVHSUEDDAKBggrBgEFBQcDATAOBgNVHQ8BAf8EBAMCBPAwDQYJKoZIhvcNAQEFBQADgYEASIhq723VL5xP0q51MYXFlGU1boD7pPD1pIQspD/MjCIEupcbH2kAo4wf+EiKsXR0rs+WZkaSgvFqaM4OQ2kWSFTiqmFXFDBEi6EFr68yLg7IpQpNTzVBXERd8B4GwNL9wrRw60jPXlUK29DPBsdGq8fDgX18l39wKkWXv7p1to4=",
+ "issuer": "CN=Certificate Authority,O=IPA",
+ "md5_fingerprint": "08:86:a9:f9:87:af:0d:d7:42:01:e0:5f:12:9b:32:7f",
+ "serial_number": "1",
+ "sha1_fingerprint": "b8:4c:4b:79:4f:13:03:79:47:08:fa:6b:52:63:3d:f9:15:8e:7e:dc",
+ "subject": "CN=dev.example.com,O=IPA",
+ "valid_not_after": "Tue Oct 13 01:59:32 2015 UTC",
+ "valid_not_before": "Wed Oct 13 01:59:32 2010 UTC"
+ }
+ }
+}
diff --git a/install/ui/test/data/config_show.json b/install/ui/test/data/config_show.json
new file mode 100644
index 000000000..e3b6154b9
--- /dev/null
+++ b/install/ui/test/data/config_show.json
@@ -0,0 +1,99 @@
+{
+ "error": null,
+ "id": 4,
+ "result": {
+ "result": {
+ "attributelevelrights": {
+ "aci": "rscwo",
+ "cn": "rscwo",
+ "ipacertificatesubjectbase": "rscwo",
+ "ipaconfigstring": "rscwo",
+ "ipacustomfields": "rscwo",
+ "ipadefaultemaildomain": "rscwo",
+ "ipadefaultloginshell": "rscwo",
+ "ipadefaultprimarygroup": "rscwo",
+ "ipagroupobjectclasses": "rscwo",
+ "ipagroupsearchfields": "rscwo",
+ "ipahomesrootdir": "rscwo",
+ "ipamaxusernamelength": "rscwo",
+ "ipamigrationenabled": "rscwo",
+ "ipapwdexpadvnotify": "rscwo",
+ "ipasearchrecordslimit": "rscwo",
+ "ipasearchtimelimit": "rscwo",
+ "ipauserobjectclasses": "rscwo",
+ "ipausersearchfields": "rscwo",
+ "nsaccountlock": "rscwo",
+ "objectclass": "rscwo"
+ },
+ "cn": [
+ "ipaConfig"
+ ],
+ "dn": "cn=ipaconfig,cn=etc,dc=ipa14,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "ipacertificatesubjectbase": [
+ "O=IPA14.AYOUNG.BOSTON.DEVEL.REDHAT.COM"
+ ],
+ "ipaconfigstring": [
+ "AllowNThash"
+ ],
+ "ipadefaultemaildomain": [
+ "ayoung.boston.devel.redhat.com"
+ ],
+ "ipadefaultloginshell": [
+ "/bin/sh"
+ ],
+ "ipadefaultprimarygroup": [
+ "ipausers"
+ ],
+ "ipagroupobjectclasses": [
+ "top",
+ "groupofnames",
+ "nestedgroup",
+ "ipausergroup",
+ "ipaobject"
+ ],
+ "ipagroupsearchfields": [
+ "cn,description"
+ ],
+ "ipahomesrootdir": [
+ "/home"
+ ],
+ "ipamaxusernamelength": [
+ "32"
+ ],
+ "ipamigrationenabled": [
+ "FALSE"
+ ],
+ "ipapwdexpadvnotify": [
+ "4"
+ ],
+ "ipasearchrecordslimit": [
+ "100"
+ ],
+ "ipasearchtimelimit": [
+ "2"
+ ],
+ "ipauserobjectclasses": [
+ "top",
+ "person",
+ "organizationalperson",
+ "inetorgperson",
+ "inetuser",
+ "posixaccount",
+ "krbprincipalaux",
+ "krbticketpolicyaux",
+ "ipaobject"
+ ],
+ "ipausersearchfields": [
+ "uid,givenname,sn,telephonenumber,ou,title"
+ ],
+ "objectclass": [
+ "nsContainer",
+ "top",
+ "ipaGuiConfig",
+ "ipaConfigObject"
+ ]
+ },
+ "summary": null,
+ "value": ""
+ }
+} \ No newline at end of file
diff --git a/install/ui/test/data/delegation_find.json b/install/ui/test/data/delegation_find.json
new file mode 100644
index 000000000..82b31fc58
--- /dev/null
+++ b/install/ui/test/data/delegation_find.json
@@ -0,0 +1,35 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "count": 2,
+ "result": [
+ {
+ "aciname": "delegme",
+ "attrs": [
+ "cn"
+ ],
+ "filter": "(memberOf=cn=ipausers,cn=groups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com)",
+ "group": "muppets",
+ "membergroup": "cn=ipausers,cn=groups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "permissions": [
+ "write"
+ ]
+ },
+ {
+ "aciname": "m2m",
+ "attrs": [
+ "title"
+ ],
+ "filter": "(memberOf=cn=monsters,cn=groups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com)",
+ "group": "muppets",
+ "membergroup": "cn=monsters,cn=groups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "permissions": [
+ "write"
+ ]
+ }
+ ],
+ "summary": "2 delegations matched",
+ "truncated": false
+ }
+} \ No newline at end of file
diff --git a/install/ui/test/data/delegation_list.json b/install/ui/test/data/delegation_list.json
new file mode 100644
index 000000000..d4d9fc060
--- /dev/null
+++ b/install/ui/test/data/delegation_list.json
@@ -0,0 +1,35 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "count": 2,
+ "result": [
+ {
+ "aciname": "delegme",
+ "attrs": [
+ "cn"
+ ],
+ "filter": "(memberOf=cn=ipausers,cn=groups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com)",
+ "group": "muppets",
+ "membergroup": "cn=ipausers,cn=groups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "permissions": [
+ "write"
+ ]
+ },
+ {
+ "aciname": "m2m",
+ "attrs": [
+ "title"
+ ],
+ "filter": "(memberOf=cn=monsters,cn=groups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com)",
+ "group": "muppets",
+ "membergroup": "cn=monsters,cn=groups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "permissions": [
+ "write"
+ ]
+ }
+ ],
+ "summary": "2 delegations matched",
+ "truncated": false
+ }
+} \ No newline at end of file
diff --git a/install/ui/test/data/delegation_mod.json b/install/ui/test/data/delegation_mod.json
new file mode 100644
index 000000000..9f7da68bf
--- /dev/null
+++ b/install/ui/test/data/delegation_mod.json
@@ -0,0 +1,21 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "result": {
+ "aciname": "m2m",
+ "attrs": [
+ "title"
+ ],
+ "filter": "(memberOf=cn=monsters,cn=groups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com)",
+ "group": "muppets",
+ "membergroup": "cn=monsters,cn=groups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "permissions": [
+ "add",
+ "delete"
+ ]
+ },
+ "summary": "Modified delegation \"m2m\"",
+ "value": "m2m"
+ }
+} \ No newline at end of file
diff --git a/install/ui/test/data/delegation_show.json b/install/ui/test/data/delegation_show.json
new file mode 100644
index 000000000..9444c8750
--- /dev/null
+++ b/install/ui/test/data/delegation_show.json
@@ -0,0 +1,20 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "result": {
+ "aciname": "delegme",
+ "attrs": [
+ "cn"
+ ],
+ "filter": "(memberOf=cn=ipausers,cn=groups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com)",
+ "group": "muppets",
+ "membergroup": "cn=ipausers,cn=groups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "permissions": [
+ "write"
+ ]
+ },
+ "summary": null,
+ "value": "delegme"
+ }
+} \ No newline at end of file
diff --git a/install/ui/test/data/dns_find.json b/install/ui/test/data/dns_find.json
new file mode 100644
index 000000000..c3b49f413
--- /dev/null
+++ b/install/ui/test/data/dns_find.json
@@ -0,0 +1,101 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "count": 3,
+ "result": [
+ {
+ "dn": "idnsname=ayoung.boston.devel.redhat.com,cn=dns,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "idnsname": [
+ "ayoung.boston.devel.redhat.com"
+ ],
+ "idnssoaexpire": [
+ "1209600"
+ ],
+ "idnssoaminimum": [
+ "3600"
+ ],
+ "idnssoamname": [
+ "ipa.ayoung.boston.devel.redhat.com."
+ ],
+ "idnssoarefresh": [
+ "3600"
+ ],
+ "idnssoaretry": [
+ "900"
+ ],
+ "idnssoarname": [
+ "root.ipa.ayoung.boston.devel.redhat.com."
+ ],
+ "idnssoaserial": [
+ "2010061001"
+ ],
+ "idnszoneactive": [
+ "TRUE"
+ ]
+ },
+ {
+ "dn": "idnsname=122.168.192.in-addr.arpa,cn=dns,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "idnsname": [
+ "122.168.192.in-addr.arpa"
+ ],
+ "idnssoaexpire": [
+ "1209600"
+ ],
+ "idnssoaminimum": [
+ "3600"
+ ],
+ "idnssoamname": [
+ "ipa.ayoung.boston.devel.redhat.com."
+ ],
+ "idnssoarefresh": [
+ "3600"
+ ],
+ "idnssoaretry": [
+ "900"
+ ],
+ "idnssoarname": [
+ "root.122.168.192.in-addr.arpa."
+ ],
+ "idnssoaserial": [
+ "2010061001"
+ ],
+ "idnszoneactive": [
+ "TRUE"
+ ]
+ },
+ {
+ "dn": "idnsname=redhat.com,cn=dns,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "idnsname": [
+ "redhat.com"
+ ],
+ "idnssoaexpire": [
+ "1209600"
+ ],
+ "idnssoaminimum": [
+ "3600"
+ ],
+ "idnssoamname": [
+ "127.0.0.1"
+ ],
+ "idnssoarefresh": [
+ "3600"
+ ],
+ "idnssoaretry": [
+ "900"
+ ],
+ "idnssoarname": [
+ "root.redhat.com."
+ ],
+ "idnssoaserial": [
+ "2010061001"
+ ],
+ "idnszoneactive": [
+ "TRUE"
+ ]
+ }
+ ],
+ "summary": null,
+ "truncated": false
+ }
+} \ No newline at end of file
diff --git a/install/ui/test/data/dns_find_rr.json b/install/ui/test/data/dns_find_rr.json
new file mode 100644
index 000000000..4183f703f
--- /dev/null
+++ b/install/ui/test/data/dns_find_rr.json
@@ -0,0 +1,110 @@
+{
+ "error": null,
+ "id": 6,
+ "result": {
+ "count": 11,
+ "result": [
+ {
+ "dn": "idnsname=ayoung.boston.devel.redhat.com,cn=dns,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "idnsname": [
+ "ayoung.boston.devel.redhat.com"
+ ],
+ "nsrecord": [
+ "ipa.ayoung.boston.devel.redhat.com."
+ ]
+ },
+ {
+ "arecord": [
+ "192.168.122.81"
+ ],
+ "dn": "idnsname=ipa,idnsname=ayoung.boston.devel.redhat.com,cn=dns,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "idnsname": [
+ "ipa"
+ ]
+ },
+ {
+ "dn": "idnsname=_ldap._tcp,idnsname=ayoung.boston.devel.redhat.com,cn=dns,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "idnsname": [
+ "_ldap._tcp"
+ ],
+ "srvrecord": [
+ "0 100 389 ipa"
+ ]
+ },
+ {
+ "dn": "idnsname=_kerberos,idnsname=ayoung.boston.devel.redhat.com,cn=dns,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "idnsname": [
+ "_kerberos"
+ ],
+ "txtrecord": [
+ "AYOUNG.BOSTON.DEVEL.REDHAT.COM"
+ ]
+ },
+ {
+ "dn": "idnsname=_kerberos._tcp,idnsname=ayoung.boston.devel.redhat.com,cn=dns,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "idnsname": [
+ "_kerberos._tcp"
+ ],
+ "srvrecord": [
+ "0 100 88 ipa"
+ ]
+ },
+ {
+ "dn": "idnsname=_kerberos._udp,idnsname=ayoung.boston.devel.redhat.com,cn=dns,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "idnsname": [
+ "_kerberos._udp"
+ ],
+ "srvrecord": [
+ "0 100 88 ipa"
+ ]
+ },
+ {
+ "dn": "idnsname=_kerberos-master._tcp,idnsname=ayoung.boston.devel.redhat.com,cn=dns,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "idnsname": [
+ "_kerberos-master._tcp"
+ ],
+ "srvrecord": [
+ "0 100 88 ipa"
+ ]
+ },
+ {
+ "dn": "idnsname=_kerberos-master._udp,idnsname=ayoung.boston.devel.redhat.com,cn=dns,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "idnsname": [
+ "_kerberos-master._udp"
+ ],
+ "srvrecord": [
+ "0 100 88 ipa"
+ ]
+ },
+ {
+ "dn": "idnsname=_kpasswd._tcp,idnsname=ayoung.boston.devel.redhat.com,cn=dns,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "idnsname": [
+ "_kpasswd._tcp"
+ ],
+ "srvrecord": [
+ "0 100 464 ipa"
+ ]
+ },
+ {
+ "dn": "idnsname=_kpasswd._udp,idnsname=ayoung.boston.devel.redhat.com,cn=dns,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "idnsname": [
+ "_kpasswd._udp"
+ ],
+ "srvrecord": [
+ "0 100 464 ipa"
+ ]
+ },
+ {
+ "dn": "idnsname=_ntp._udp,idnsname=ayoung.boston.devel.redhat.com,cn=dns,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "idnsname": [
+ "_ntp._udp"
+ ],
+ "srvrecord": [
+ "0 100 123 ipa"
+ ]
+ }
+ ],
+ "summary": null,
+ "truncated": false
+ }
+} \ No newline at end of file
diff --git a/install/ui/test/data/dns_show.json b/install/ui/test/data/dns_show.json
new file mode 100644
index 000000000..3f3046a51
--- /dev/null
+++ b/install/ui/test/data/dns_show.json
@@ -0,0 +1,38 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "result": {
+ "dn": "idnsname=ayoung.boston.devel.redhat.com,cn=dns,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "idnsname": [
+ "ayoung.boston.devel.redhat.com"
+ ],
+ "idnssoaexpire": [
+ "1209600"
+ ],
+ "idnssoaminimum": [
+ "3600"
+ ],
+ "idnssoamname": [
+ "ipa.ayoung.boston.devel.redhat.com."
+ ],
+ "idnssoarefresh": [
+ "3600"
+ ],
+ "idnssoaretry": [
+ "900"
+ ],
+ "idnssoarname": [
+ "root.ipa.ayoung.boston.devel.redhat.com."
+ ],
+ "idnssoaserial": [
+ "2010061001"
+ ],
+ "idnszoneactive": [
+ "TRUE"
+ ]
+ },
+ "summary": null,
+ "value": "ayoung.boston.devel.redhat.com"
+ }
+} \ No newline at end of file
diff --git a/install/ui/test/data/dnsrecord_add.json b/install/ui/test/data/dnsrecord_add.json
new file mode 100644
index 000000000..968d3f606
--- /dev/null
+++ b/install/ui/test/data/dnsrecord_add.json
@@ -0,0 +1,21 @@
+{
+ "error": null,
+ "id": 12,
+ "result": {
+ "result": {
+ "arecord": [
+ "1.2.3.4"
+ ],
+ "dn": "idnsname=a4,idnsname=henson.ayoung.boston.devel.redhat.com,cn=dns,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "idnsname": [
+ "a4"
+ ],
+ "objectclass": [
+ "top",
+ "idnsrecord"
+ ]
+ },
+ "summary": null,
+ "value": "a4"
+ }
+} \ No newline at end of file
diff --git a/install/ui/test/data/dnsrecord_del.json b/install/ui/test/data/dnsrecord_del.json
new file mode 100644
index 000000000..93a53627c
--- /dev/null
+++ b/install/ui/test/data/dnsrecord_del.json
@@ -0,0 +1,10 @@
+{
+ "error": null,
+ "result": {
+ "idnsname": [
+ "@"
+ ]
+ },
+ "summary": null,
+ "value": "@"
+ }
diff --git a/install/ui/test/data/dnsrecord_find.json b/install/ui/test/data/dnsrecord_find.json
new file mode 100644
index 000000000..1d64b3abb
--- /dev/null
+++ b/install/ui/test/data/dnsrecord_find.json
@@ -0,0 +1,110 @@
+{
+ "error": null,
+ "id": 10,
+ "result": {
+ "count": 11,
+ "result": [
+ {
+ "dn": "idnsname=ayoung.boston.devel.redhat.com,cn=dns,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "idnsname": [
+ "@"
+ ],
+ "nsrecord": [
+ "ipa.ayoung.boston.devel.redhat.com."
+ ]
+ },
+ {
+ "arecord": [
+ "192.168.122.81"
+ ],
+ "dn": "idnsname=ipa,idnsname=ayoung.boston.devel.redhat.com,cn=dns,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "idnsname": [
+ "ipa"
+ ]
+ },
+ {
+ "dn": "idnsname=_ldap._tcp,idnsname=ayoung.boston.devel.redhat.com,cn=dns,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "idnsname": [
+ "_ldap._tcp"
+ ],
+ "srvrecord": [
+ "0 100 389 ipa"
+ ]
+ },
+ {
+ "dn": "idnsname=_kerberos,idnsname=ayoung.boston.devel.redhat.com,cn=dns,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "idnsname": [
+ "_kerberos"
+ ],
+ "txtrecord": [
+ "AYOUNG.BOSTON.DEVEL.REDHAT.COM"
+ ]
+ },
+ {
+ "dn": "idnsname=_kerberos._tcp,idnsname=ayoung.boston.devel.redhat.com,cn=dns,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "idnsname": [
+ "_kerberos._tcp"
+ ],
+ "srvrecord": [
+ "0 100 88 ipa"
+ ]
+ },
+ {
+ "dn": "idnsname=_kerberos._udp,idnsname=ayoung.boston.devel.redhat.com,cn=dns,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "idnsname": [
+ "_kerberos._udp"
+ ],
+ "srvrecord": [
+ "0 100 88 ipa"
+ ]
+ },
+ {
+ "dn": "idnsname=_kerberos-master._tcp,idnsname=ayoung.boston.devel.redhat.com,cn=dns,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "idnsname": [
+ "_kerberos-master._tcp"
+ ],
+ "srvrecord": [
+ "0 100 88 ipa"
+ ]
+ },
+ {
+ "dn": "idnsname=_kerberos-master._udp,idnsname=ayoung.boston.devel.redhat.com,cn=dns,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "idnsname": [
+ "_kerberos-master._udp"
+ ],
+ "srvrecord": [
+ "0 100 88 ipa"
+ ]
+ },
+ {
+ "dn": "idnsname=_kpasswd._tcp,idnsname=ayoung.boston.devel.redhat.com,cn=dns,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "idnsname": [
+ "_kpasswd._tcp"
+ ],
+ "srvrecord": [
+ "0 100 464 ipa"
+ ]
+ },
+ {
+ "dn": "idnsname=_kpasswd._udp,idnsname=ayoung.boston.devel.redhat.com,cn=dns,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "idnsname": [
+ "_kpasswd._udp"
+ ],
+ "srvrecord": [
+ "0 100 464 ipa"
+ ]
+ },
+ {
+ "dn": "idnsname=_ntp._udp,idnsname=ayoung.boston.devel.redhat.com,cn=dns,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "idnsname": [
+ "_ntp._udp"
+ ],
+ "srvrecord": [
+ "0 100 123 ipa"
+ ]
+ }
+ ],
+ "summary": null,
+ "truncated": false
+ }
+} \ No newline at end of file
diff --git a/install/ui/test/data/dnszone_add.json b/install/ui/test/data/dnszone_add.json
new file mode 100644
index 000000000..6870acc5b
--- /dev/null
+++ b/install/ui/test/data/dnszone_add.json
@@ -0,0 +1,46 @@
+{
+ "error": null,
+ "id": 3,
+ "result": {
+ "result": {
+ "dn": "idnsname=henson.ayoung.boston.devel.redhat.com,cn=dns,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "idnsallowdynupdate": [
+ "FALSE"
+ ],
+ "idnsname": [
+ "henson.ayoung.boston.devel.redhat.com"
+ ],
+ "idnssoaexpire": [
+ "1209600"
+ ],
+ "idnssoaminimum": [
+ "3600"
+ ],
+ "idnssoamname": [
+ "ayoung.boston.devel.redhat.com"
+ ],
+ "idnssoarefresh": [
+ "3600"
+ ],
+ "idnssoaretry": [
+ "900"
+ ],
+ "idnssoarname": [
+ "root.henson.ayoung.boston.devel.redhat.com."
+ ],
+ "idnssoaserial": [
+ "2010021201"
+ ],
+ "idnszoneactive": [
+ "TRUE"
+ ],
+ "objectclass": [
+ "top",
+ "idnsrecord",
+ "idnszone"
+ ]
+ },
+ "summary": null,
+ "value": "henson.ayoung.boston.devel.redhat.com"
+ }
+} \ No newline at end of file
diff --git a/install/ui/test/data/dnszone_find.json b/install/ui/test/data/dnszone_find.json
new file mode 100644
index 000000000..b8f76d417
--- /dev/null
+++ b/install/ui/test/data/dnszone_find.json
@@ -0,0 +1,137 @@
+{
+ "error": null,
+ "id": 6,
+ "result": {
+ "count": 3,
+ "result": [
+ {
+ "dn": "idnsname=ayoung.boston.devel.redhat.com,cn=dns,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "idnsallowdynupdate": [
+ "TRUE"
+ ],
+ "idnsname": [
+ "ayoung.boston.devel.redhat.com"
+ ],
+ "idnssoaexpire": [
+ "1209600"
+ ],
+ "idnssoaminimum": [
+ "3600"
+ ],
+ "idnssoamname": [
+ "ipa.ayoung.boston.devel.redhat.com."
+ ],
+ "idnssoarefresh": [
+ "3600"
+ ],
+ "idnssoaretry": [
+ "900"
+ ],
+ "idnssoarname": [
+ "root.ipa.ayoung.boston.devel.redhat.com."
+ ],
+ "idnssoaserial": [
+ "2010021201"
+ ],
+ "idnsupdatepolicy": [
+ "grant AYOUNG.BOSTON.DEVEL.REDHAT.COM krb5-self * A;"
+ ],
+ "idnszoneactive": [
+ "TRUE"
+ ],
+ "nsrecord": [
+ "ipa.ayoung.boston.devel.redhat.com."
+ ],
+ "objectclass": [
+ "top",
+ "idnsrecord",
+ "idnszone"
+ ]
+ },
+ {
+ "dn": "idnsname=122.168.192.in-addr.arpa,cn=dns,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "idnsallowdynupdate": [
+ "TRUE"
+ ],
+ "idnsname": [
+ "122.168.192.in-addr.arpa"
+ ],
+ "idnssoaexpire": [
+ "1209600"
+ ],
+ "idnssoaminimum": [
+ "3600"
+ ],
+ "idnssoamname": [
+ "ipa.ayoung.boston.devel.redhat.com."
+ ],
+ "idnssoarefresh": [
+ "3600"
+ ],
+ "idnssoaretry": [
+ "900"
+ ],
+ "idnssoarname": [
+ "root.122.168.192.in-addr.arpa."
+ ],
+ "idnssoaserial": [
+ "2010021201"
+ ],
+ "idnsupdatepolicy": [
+ "grant AYOUNG.BOSTON.DEVEL.REDHAT.COM krb5-subdomain 122.168.192.in-addr.arpa. PTR;"
+ ],
+ "idnszoneactive": [
+ "TRUE"
+ ],
+ "nsrecord": [
+ "ipa.ayoung.boston.devel.redhat.com."
+ ],
+ "objectclass": [
+ "top",
+ "idnsrecord",
+ "idnszone"
+ ]
+ },
+ {
+ "dn": "idnsname=henson.ayoung.boston.devel.redhat.com,cn=dns,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "idnsallowdynupdate": [
+ "FALSE"
+ ],
+ "idnsname": [
+ "henson.ayoung.boston.devel.redhat.com"
+ ],
+ "idnssoaexpire": [
+ "1209600"
+ ],
+ "idnssoaminimum": [
+ "3600"
+ ],
+ "idnssoamname": [
+ "ayoung.boston.devel.redhat.com"
+ ],
+ "idnssoarefresh": [
+ "3600"
+ ],
+ "idnssoaretry": [
+ "900"
+ ],
+ "idnssoarname": [
+ "root.henson.ayoung.boston.devel.redhat.com."
+ ],
+ "idnssoaserial": [
+ "2010021201"
+ ],
+ "idnszoneactive": [
+ "TRUE"
+ ],
+ "objectclass": [
+ "top",
+ "idnsrecord",
+ "idnszone"
+ ]
+ }
+ ],
+ "summary": null,
+ "truncated": false
+ }
+} \ No newline at end of file
diff --git a/install/ui/test/data/dnszone_show.json b/install/ui/test/data/dnszone_show.json
new file mode 100644
index 000000000..35e507627
--- /dev/null
+++ b/install/ui/test/data/dnszone_show.json
@@ -0,0 +1,90 @@
+{
+ "error": null,
+ "id": 7,
+ "result": {
+ "result": {
+ "attributelevelrights": {
+ "a6record": "rscwo",
+ "aaaarecord": "rscwo",
+ "aci": "rscwo",
+ "afsdbrecord": "rscwo",
+ "arecord": "rscwo",
+ "certrecord": "rscwo",
+ "cn": "rscwo",
+ "cnamerecord": "rscwo",
+ "dnamerecord": "rscwo",
+ "dnsclass": "rscwo",
+ "dnsttl": "rscwo",
+ "dsrecord": "rscwo",
+ "hinforecord": "rscwo",
+ "idnsallowdynupdate": "rscwo",
+ "idnsname": "rscwo",
+ "idnssoaexpire": "rscwo",
+ "idnssoaminimum": "rscwo",
+ "idnssoamname": "rscwo",
+ "idnssoarefresh": "rscwo",
+ "idnssoaretry": "rscwo",
+ "idnssoarname": "rscwo",
+ "idnssoaserial": "rscwo",
+ "idnsupdatepolicy": "rscwo",
+ "idnszoneactive": "rscwo",
+ "keyrecord": "rscwo",
+ "kxrecord": "rscwo",
+ "locrecord": "rscwo",
+ "mdrecord": "rscwo",
+ "minforecord": "rscwo",
+ "mxrecord": "rscwo",
+ "naptrrecord": "rscwo",
+ "nsaccountlock": "rscwo",
+ "nsecrecord": "rscwo",
+ "nsrecord": "rscwo",
+ "nxtrecord": "rscwo",
+ "objectclass": "rscwo",
+ "ptrrecord": "rscwo",
+ "rrsigrecord": "rscwo",
+ "sigrecord": "rscwo",
+ "srvrecord": "rscwo",
+ "sshfprecord": "rscwo",
+ "txtrecord": "rscwo"
+ },
+ "dn": "idnsname=henson.ayoung.boston.devel.redhat.com,cn=dns,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "idnsallowdynupdate": [
+ "FALSE"
+ ],
+ "idnsname": [
+ "henson.ayoung.boston.devel.redhat.com"
+ ],
+ "idnssoaexpire": [
+ "1209600"
+ ],
+ "idnssoaminimum": [
+ "3600"
+ ],
+ "idnssoamname": [
+ "ayoung.boston.devel.redhat.com"
+ ],
+ "idnssoarefresh": [
+ "3600"
+ ],
+ "idnssoaretry": [
+ "900"
+ ],
+ "idnssoarname": [
+ "root.henson.ayoung.boston.devel.redhat.com."
+ ],
+ "idnssoaserial": [
+ "2010021201"
+ ],
+ "idnszoneactive": [
+ "TRUE"
+ ],
+ "objectclass": [
+ "top",
+ "idnsrecord",
+ "idnszone"
+ ]
+ },
+ "summary": null,
+ "value": "henson.ayoung.boston.devel.redhat.com"
+ }
+} \ No newline at end of file
diff --git a/install/ui/test/data/group_add.json b/install/ui/test/data/group_add.json
new file mode 100644
index 000000000..180f5f11c
--- /dev/null
+++ b/install/ui/test/data/group_add.json
@@ -0,0 +1,31 @@
+{
+ "error": null,
+ "id": 12,
+ "result": {
+ "result": {
+ "cn": [
+ "neighbors"
+ ],
+ "description": [
+ "The People in Your Neighborhood"
+ ],
+ "dn": "cn=neighbors,cn=groups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "gidnumber": [
+ "123456"
+ ],
+ "ipauniqueid": [
+ "0dbae87a-b43a-11df-ac8e-525400674dcd"
+ ],
+ "objectclass": [
+ "top",
+ "groupofnames",
+ "nestedgroup",
+ "ipausergroup",
+ "ipaobject",
+ "posixgroup"
+ ]
+ },
+ "summary": null,
+ "value": "neighbors"
+ }
+} \ No newline at end of file
diff --git a/install/ui/test/data/group_add_member.json b/install/ui/test/data/group_add_member.json
new file mode 100644
index 000000000..7f10d1052
--- /dev/null
+++ b/install/ui/test/data/group_add_member.json
@@ -0,0 +1,25 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "completed": 1,
+ "failed": {
+ "member": {
+ "group": [],
+ "user": []
+ }
+ },
+ "result": {
+ "cn": [
+ "testgroup"
+ ],
+ "description": [
+ "testgroup"
+ ],
+ "dn": "cn=testgroup,cn=groups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_user": [
+ "kfrog"
+ ]
+ }
+ }
+} \ No newline at end of file
diff --git a/install/ui/test/data/group_find.json b/install/ui/test/data/group_find.json
new file mode 100644
index 000000000..902689a06
--- /dev/null
+++ b/install/ui/test/data/group_find.json
@@ -0,0 +1,75 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "count": 5,
+ "result": [
+ {
+ "cn": [
+ "admins"
+ ],
+ "description": [
+ "Account administrators group"
+ ],
+ "dn": "cn=admins,cn=groups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "gidnumber": [
+ "1948497956"
+ ],
+ "member_user": [
+ "admin"
+ ]
+ },
+ {
+ "cn": [
+ "ipausers"
+ ],
+ "description": [
+ "Default group for all users"
+ ],
+ "dn": "cn=ipausers,cn=groups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "gidnumber": [
+ "1948497957"
+ ],
+ "member_user": [
+ "kfrog",
+ "moi"
+ ]
+ },
+ {
+ "cn": [
+ "editors"
+ ],
+ "description": [
+ "Limited admins who can edit other users"
+ ],
+ "dn": "cn=editors,cn=groups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "gidnumber": [
+ "1948497958"
+ ]
+ },
+ {
+ "cn": [
+ "deleteme"
+ ],
+ "description": [
+ "This is a group that should go away."
+ ],
+ "dn": "cn=deleteme,cn=groups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com"
+ },
+ {
+ "cn": [
+ "testgroup"
+ ],
+ "description": [
+ "Detlete this if you see it"
+ ],
+ "dn": "cn=testgroup,cn=groups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "gidnumber": [
+ "1948497959"
+ ]
+ }
+ ],
+ "summary": "5 groups matched",
+ "truncated": false
+ }
+} \ No newline at end of file
diff --git a/install/ui/test/data/group_member_user.json b/install/ui/test/data/group_member_user.json
new file mode 100644
index 000000000..971b13d44
--- /dev/null
+++ b/install/ui/test/data/group_member_user.json
@@ -0,0 +1,149 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "count": 2,
+ "results": [
+ {
+ "error": null,
+ "result": {
+ "cn": [
+ "Administrator"
+ ],
+ "dn": "uid=admin,cn=users,cn=accounts,dc=dev,dc=example,dc=com",
+ "gecos": [
+ "Administrator"
+ ],
+ "gidnumber": [
+ "1662072955"
+ ],
+ "homedirectory": [
+ "/home/admin"
+ ],
+ "ipauniqueid": [
+ "ffb8d002-f46c-11df-8cc1-00163e72f2d9"
+ ],
+ "krblastpwdchange": [
+ "20101120061333Z"
+ ],
+ "krbpasswordexpiration": [
+ "20110218061333Z"
+ ],
+ "krbprincipalname": [
+ "admin@DEV.EXAMPLE.COM"
+ ],
+ "loginshell": [
+ "/bin/bash"
+ ],
+ "memberof_group": [
+ "admins",
+ "ipausers"
+ ],
+ "memberof_rolegroup": [
+ "replicaadmin"
+ ],
+ "memberof_taskgroup": [
+ "managereplica",
+ "deletereplica"
+ ],
+ "mepmanagedentry": [
+ "cn=admin,cn=groups,cn=accounts,dc=dev,dc=example,dc=com"
+ ],
+ "nsaccountlock": [
+ "False"
+ ],
+ "objectclass": [
+ "top",
+ "person",
+ "posixaccount",
+ "krbprincipalaux",
+ "krbticketpolicyaux",
+ "inetuser",
+ "ipaobject",
+ "mepOriginEntry"
+ ],
+ "sn": [
+ "Administrator"
+ ],
+ "uid": [
+ "admin"
+ ],
+ "uidnumber": [
+ "1662072955"
+ ]
+ },
+ "summary": null,
+ "value": "admin"
+ },
+ {
+ "error": null,
+ "result": {
+ "cn": [
+ "Test User"
+ ],
+ "dn": "uid=test,cn=users,cn=accounts,dc=dev,dc=example,dc=com",
+ "gecos": [
+ "test"
+ ],
+ "gidnumber": [
+ "1662072958"
+ ],
+ "givenname": [
+ "Test"
+ ],
+ "homedirectory": [
+ "/home/test"
+ ],
+ "ipauniqueid": [
+ "c0724e5e-f472-11df-8186-00163e72f2d9"
+ ],
+ "krbprincipalname": [
+ "test@DEV.EXAMPLE.COM"
+ ],
+ "krbpwdpolicyreference": [
+ "cn=global_policy,cn=DEV.EXAMPLE.COM,cn=kerberos,dc=dev,dc=example,dc=com"
+ ],
+ "loginshell": [
+ "/bin/sh"
+ ],
+ "mail": [
+ "test"
+ ],
+ "memberof_group": [
+ "ipausers",
+ "editors"
+ ],
+ "mepmanagedentry": [
+ "cn=test,cn=groups,cn=accounts,dc=dev,dc=example,dc=com"
+ ],
+ "nsaccountlock": [
+ "False"
+ ],
+ "objectclass": [
+ "top",
+ "person",
+ "organizationalperson",
+ "inetorgperson",
+ "inetuser",
+ "posixaccount",
+ "krbprincipalaux",
+ "krbticketpolicyaux",
+ "ipaobject",
+ "mepOriginEntry"
+ ],
+ "sn": [
+ "User"
+ ],
+ "uid": [
+ "test"
+ ],
+ "uidnumber": [
+ "1662072958"
+ ]
+ },
+ "summary": null,
+ "value": "test"
+ }
+ ]
+ }
+}
diff --git a/install/ui/test/data/group_remove_member.json b/install/ui/test/data/group_remove_member.json
new file mode 100644
index 000000000..0118438af
--- /dev/null
+++ b/install/ui/test/data/group_remove_member.json
@@ -0,0 +1,44 @@
+{
+ "error": null,
+ "id": 6,
+ "result": {
+ "completed": 0,
+ "failed": {
+ "member": {
+ "group": [],
+ "user": []
+ }
+ },
+ "result": {
+ "cn": [
+ "muppets"
+ ],
+ "description": [
+ "Muppets moonlighting for CTW"
+ ],
+ "dn": "cn=muppets,cn=groups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "gidnumber": [
+ "1950316043"
+ ],
+ "ipauniqueid": [
+ "0ee0f096-e36c11df-96f18479-3e1281d2"
+ ],
+ "member_user": [
+ "admin",
+ "kfrog",
+ "count123",
+ "scram",
+ "zoe",
+ "pdawn"
+ ],
+ "objectclass": [
+ "top",
+ "groupofnames",
+ "nestedgroup",
+ "ipausergroup",
+ "ipaobject",
+ "posixgroup"
+ ]
+ }
+ }
+}
diff --git a/install/ui/test/data/group_show.json b/install/ui/test/data/group_show.json
new file mode 100644
index 000000000..536b120ca
--- /dev/null
+++ b/install/ui/test/data/group_show.json
@@ -0,0 +1,38 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "result": {
+ "cn": [
+ "ipausers"
+ ],
+ "description": [
+ "Default group for all users"
+ ],
+ "dn": "cn=ipausers,cn=groups,cn=accounts,dc=idm,dc=lab,dc=bos,dc=redhat,dc=com",
+ "gidnumber": [
+ "1079249048"
+ ],
+ "member": [
+ "uid=gsmile,cn=users,cn=accounts,dc=idm,dc=lab,dc=bos,dc=redhat,dc=com",
+ "uid=kfrog,cn=users,cn=accounts,dc=idm,dc=lab,dc=bos,dc=redhat,dc=com",
+ "uid=count123,cn=users,cn=accounts,dc=idm,dc=lab,dc=bos,dc=redhat,dc=com"
+ ],
+ "member_user": [
+ "gsmile",
+ "kfrog",
+ "count123"
+ ],
+ "memberof": [],
+ "objectclass": [
+ "top",
+ "groupofnames",
+ "nestedgroup",
+ "ipausergroup",
+ "posixgroup"
+ ]
+ },
+ "summary": null,
+ "value": "ipausers"
+ }
+}
diff --git a/install/ui/test/data/hbacrule_add.json b/install/ui/test/data/hbacrule_add.json
new file mode 100644
index 000000000..2a5d251bf
--- /dev/null
+++ b/install/ui/test/data/hbacrule_add.json
@@ -0,0 +1,27 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "result": {
+ "accessruletype": [
+ "allow"
+ ],
+ "cn": [
+ "test"
+ ],
+ "dn": "ipauniqueid=f3e69e82-e3b411df-bfde9b13-2b28c216,cn=hbac,dc=dev,dc=example,dc=com",
+ "ipaenabledflag": [
+ "TRUE"
+ ],
+ "ipauniqueid": [
+ "f3e69e82-e3b411df-bfde9b13-2b28c216"
+ ],
+ "objectclass": [
+ "ipaassociation",
+ "ipahbacrule"
+ ]
+ },
+ "summary": null,
+ "value": "test"
+ }
+} \ No newline at end of file
diff --git a/install/ui/test/data/hbacrule_add_accesstime.json b/install/ui/test/data/hbacrule_add_accesstime.json
new file mode 100644
index 000000000..3c631155b
--- /dev/null
+++ b/install/ui/test/data/hbacrule_add_accesstime.json
@@ -0,0 +1,7 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "result": true
+ }
+}
diff --git a/install/ui/test/data/hbacrule_add_host.json b/install/ui/test/data/hbacrule_add_host.json
new file mode 100644
index 000000000..038d6aea4
--- /dev/null
+++ b/install/ui/test/data/hbacrule_add_host.json
@@ -0,0 +1,56 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "completed": 2,
+ "failed": {
+ "memberhost": {
+ "host": [],
+ "hostgroup": []
+ }
+ },
+ "result": {
+ "accessruletype": [
+ "allow"
+ ],
+ "accesstime": [
+ "periodic daily 0800-1400",
+ "absolute 201012161032 ~ 201012161033"
+ ],
+ "cn": [
+ "test"
+ ],
+ "dn": "ipauniqueid=e8aca082-e64a11df-9864f2e0-e0578392,cn=hbac,dc=dev,dc=example,dc=com",
+ "ipaenabledflag": [
+ "TRUE"
+ ],
+ "memberhost_host": [
+ "dev.example.com"
+ ],
+ "memberhost_hostgroup": [
+ "production"
+ ],
+ "memberservice_hbacsvc": [
+ "ftp",
+ "sshd"
+ ],
+ "memberservice_hbacsvcgroup": [
+ "sudo"
+ ],
+ "memberuser_group": [
+ "admins",
+ "editors"
+ ],
+ "memberuser_user": [
+ "admin",
+ "test"
+ ],
+ "sourcehost_host": [
+ "dev.example.com"
+ ],
+ "sourcehost_hostgroup": [
+ "staging"
+ ]
+ }
+ }
+}
diff --git a/install/ui/test/data/hbacrule_add_service.json b/install/ui/test/data/hbacrule_add_service.json
new file mode 100644
index 000000000..c658fe8b5
--- /dev/null
+++ b/install/ui/test/data/hbacrule_add_service.json
@@ -0,0 +1,56 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "completed": 3,
+ "failed": {
+ "memberservice": {
+ "hbacsvc": [],
+ "hbacsvcgroup": []
+ }
+ },
+ "result": {
+ "accessruletype": [
+ "allow"
+ ],
+ "accesstime": [
+ "periodic daily 0800-1400",
+ "absolute 201012161032 ~ 201012161033"
+ ],
+ "cn": [
+ "test"
+ ],
+ "dn": "ipauniqueid=e8aca082-e64a11df-9864f2e0-e0578392,cn=hbac,dc=dev,dc=example,dc=com",
+ "ipaenabledflag": [
+ "TRUE"
+ ],
+ "memberhost_host": [
+ "dev.example.com"
+ ],
+ "memberhost_hostgroup": [
+ "production"
+ ],
+ "memberservice_hbacsvc": [
+ "ftp",
+ "sshd"
+ ],
+ "memberservice_hbacsvcgroup": [
+ "sudo"
+ ],
+ "memberuser_group": [
+ "admins",
+ "editors"
+ ],
+ "memberuser_user": [
+ "admin",
+ "test"
+ ],
+ "sourcehost_host": [
+ "dev.example.com"
+ ],
+ "sourcehost_hostgroup": [
+ "staging"
+ ]
+ }
+ }
+}
diff --git a/install/ui/test/data/hbacrule_add_sourcehost.json b/install/ui/test/data/hbacrule_add_sourcehost.json
new file mode 100644
index 000000000..a657207f5
--- /dev/null
+++ b/install/ui/test/data/hbacrule_add_sourcehost.json
@@ -0,0 +1,56 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "completed": 2,
+ "failed": {
+ "sourcehost": {
+ "host": [],
+ "hostgroup": []
+ }
+ },
+ "result": {
+ "accessruletype": [
+ "allow"
+ ],
+ "accesstime": [
+ "periodic daily 0800-1400",
+ "absolute 201012161032 ~ 201012161033"
+ ],
+ "cn": [
+ "test"
+ ],
+ "dn": "ipauniqueid=e8aca082-e64a11df-9864f2e0-e0578392,cn=hbac,dc=dev,dc=example,dc=com",
+ "ipaenabledflag": [
+ "TRUE"
+ ],
+ "memberhost_host": [
+ "dev.example.com"
+ ],
+ "memberhost_hostgroup": [
+ "production"
+ ],
+ "memberservice_hbacsvc": [
+ "ftp",
+ "sshd"
+ ],
+ "memberservice_hbacsvcgroup": [
+ "sudo"
+ ],
+ "memberuser_group": [
+ "admins",
+ "editors"
+ ],
+ "memberuser_user": [
+ "admin",
+ "test"
+ ],
+ "sourcehost_host": [
+ "dev.example.com"
+ ],
+ "sourcehost_hostgroup": [
+ "staging"
+ ]
+ }
+ }
+}
diff --git a/install/ui/test/data/hbacrule_add_user.json b/install/ui/test/data/hbacrule_add_user.json
new file mode 100644
index 000000000..0c4c976e4
--- /dev/null
+++ b/install/ui/test/data/hbacrule_add_user.json
@@ -0,0 +1,56 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "completed": 3,
+ "failed": {
+ "memberuser": {
+ "group": [],
+ "user": []
+ }
+ },
+ "result": {
+ "accessruletype": [
+ "allow"
+ ],
+ "accesstime": [
+ "periodic daily 0800-1400",
+ "absolute 201012161032 ~ 201012161033"
+ ],
+ "cn": [
+ "test"
+ ],
+ "dn": "ipauniqueid=e8aca082-e64a11df-9864f2e0-e0578392,cn=hbac,dc=dev,dc=example,dc=com",
+ "ipaenabledflag": [
+ "TRUE"
+ ],
+ "memberhost_host": [
+ "dev.example.com"
+ ],
+ "memberhost_hostgroup": [
+ "production"
+ ],
+ "memberservice_hbacsvc": [
+ "ftp",
+ "sshd"
+ ],
+ "memberservice_hbacsvcgroup": [
+ "sudo"
+ ],
+ "memberuser_group": [
+ "admins",
+ "editors"
+ ],
+ "memberuser_user": [
+ "admin",
+ "test"
+ ],
+ "sourcehost_host": [
+ "dev.example.com"
+ ],
+ "sourcehost_hostgroup": [
+ "staging"
+ ]
+ }
+ }
+}
diff --git a/install/ui/test/data/hbacrule_del.json b/install/ui/test/data/hbacrule_del.json
new file mode 100644
index 000000000..2197a12c2
--- /dev/null
+++ b/install/ui/test/data/hbacrule_del.json
@@ -0,0 +1,9 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "result": true,
+ "summary": null,
+ "value": "test"
+ }
+} \ No newline at end of file
diff --git a/install/ui/test/data/hbacrule_find.json b/install/ui/test/data/hbacrule_find.json
new file mode 100644
index 000000000..fd95d9f57
--- /dev/null
+++ b/install/ui/test/data/hbacrule_find.json
@@ -0,0 +1,54 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "count": 2,
+ "result": [
+ {
+ "accessruletype": [
+ "allow"
+ ],
+ "cn": [
+ "allow_all"
+ ],
+ "description": [
+ "Allow all users to access any host from any host"
+ ],
+ "dn": "ipauniqueid=b7567b5a-e39311df-bfde9b13-2b28c216,cn=hbac,dc=dev,dc=example,dc=com",
+ "hostcategory": [
+ "all"
+ ],
+ "ipaenabledflag": [
+ "TRUE"
+ ],
+ "servicecategory": [
+ "all"
+ ],
+ "sourcehostcategory": [
+ "all"
+ ],
+ "usercategory": [
+ "all"
+ ]
+ },
+ {
+ "accessruletype": [
+ "allow"
+ ],
+ "accesstime": [
+ "periodic daily 0800-1400",
+ "absolute 201012161032 ~ 201012161033"
+ ],
+ "cn": [
+ "test"
+ ],
+ "dn": "ipauniqueid=3b6d2a82-e3b511df-bfde9b13-2b28c216,cn=hbac,dc=dev,dc=example,dc=com",
+ "ipaenabledflag": [
+ "TRUE"
+ ]
+ }
+ ],
+ "summary": null,
+ "truncated": false
+ }
+}
diff --git a/install/ui/test/data/hbacrule_mod.json b/install/ui/test/data/hbacrule_mod.json
new file mode 100644
index 000000000..ea2b4d1e8
--- /dev/null
+++ b/install/ui/test/data/hbacrule_mod.json
@@ -0,0 +1,60 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "result": {
+ "accessruletype": [
+ "allow"
+ ],
+ "attributelevelrights": {
+ "accessruletype": "rscwo",
+ "accesstime": "rscwo",
+ "aci": "rscwo",
+ "cn": "rscwo",
+ "description": "rscwo",
+ "externalhost": "rscwo",
+ "hostcategory": "rscwo",
+ "ipaenabledflag": "rscwo",
+ "ipauniqueid": "rsc",
+ "memberhost": "rscwo",
+ "memberservice": "rscwo",
+ "memberuser": "rscwo",
+ "nsaccountlock": "rscwo",
+ "servicecategory": "rscwo",
+ "sourcehost": "rscwo",
+ "sourcehostcategory": "rscwo",
+ "usercategory": "rscwo"
+ },
+ "cn": [
+ "test"
+ ],
+ "description": [
+ "Test HBAC rule."
+ ],
+ "hostcategory": [
+ "all"
+ ],
+ "ipaenabledflag": [
+ "TRUE"
+ ],
+ "ipauniqueid": [
+ "4ed8b682-edf511df-b3f78f4b-11cc007b"
+ ],
+ "objectclass": [
+ "ipaassociation",
+ "ipahbacrule"
+ ],
+ "servicecategory": [
+ "all"
+ ],
+ "sourcehostcategory": [
+ "all"
+ ],
+ "usercategory": [
+ "all"
+ ]
+ },
+ "summary": null,
+ "value": "test"
+ }
+}
diff --git a/install/ui/test/data/hbacrule_remove_accesstime.json b/install/ui/test/data/hbacrule_remove_accesstime.json
new file mode 100644
index 000000000..3c631155b
--- /dev/null
+++ b/install/ui/test/data/hbacrule_remove_accesstime.json
@@ -0,0 +1,7 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "result": true
+ }
+}
diff --git a/install/ui/test/data/hbacrule_remove_host.json b/install/ui/test/data/hbacrule_remove_host.json
new file mode 100644
index 000000000..02f56ecd6
--- /dev/null
+++ b/install/ui/test/data/hbacrule_remove_host.json
@@ -0,0 +1,50 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "completed": 2,
+ "failed": {
+ "memberhost": {
+ "host": [],
+ "hostgroup": []
+ }
+ },
+ "result": {
+ "accessruletype": [
+ "allow"
+ ],
+ "accesstime": [
+ "periodic daily 0800-1400",
+ "absolute 201012161032 ~ 201012161033"
+ ],
+ "cn": [
+ "test"
+ ],
+ "dn": "ipauniqueid=e8aca082-e64a11df-9864f2e0-e0578392,cn=hbac,dc=dev,dc=example,dc=com",
+ "ipaenabledflag": [
+ "TRUE"
+ ],
+ "memberservice_hbacsvc": [
+ "ftp",
+ "sshd"
+ ],
+ "memberservice_hbacsvcgroup": [
+ "sudo"
+ ],
+ "memberuser_group": [
+ "admins",
+ "editors"
+ ],
+ "memberuser_user": [
+ "admin",
+ "test"
+ ],
+ "sourcehost_host": [
+ "dev.example.com"
+ ],
+ "sourcehost_hostgroup": [
+ "staging"
+ ]
+ }
+ }
+}
diff --git a/install/ui/test/data/hbacrule_remove_service.json b/install/ui/test/data/hbacrule_remove_service.json
new file mode 100644
index 000000000..f8b6b51a5
--- /dev/null
+++ b/install/ui/test/data/hbacrule_remove_service.json
@@ -0,0 +1,49 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "completed": 3,
+ "failed": {
+ "memberservice": {
+ "hbacsvc": [],
+ "hbacsvcgroup": []
+ }
+ },
+ "result": {
+ "accessruletype": [
+ "allow"
+ ],
+ "accesstime": [
+ "periodic daily 0800-1400",
+ "absolute 201012161032 ~ 201012161033"
+ ],
+ "cn": [
+ "test"
+ ],
+ "dn": "ipauniqueid=e8aca082-e64a11df-9864f2e0-e0578392,cn=hbac,dc=dev,dc=example,dc=com",
+ "ipaenabledflag": [
+ "TRUE"
+ ],
+ "memberhost_host": [
+ "dev.example.com"
+ ],
+ "memberhost_hostgroup": [
+ "production"
+ ],
+ "memberuser_group": [
+ "admins",
+ "editors"
+ ],
+ "memberuser_user": [
+ "admin",
+ "test"
+ ],
+ "sourcehost_host": [
+ "dev.example.com"
+ ],
+ "sourcehost_hostgroup": [
+ "staging"
+ ]
+ }
+ }
+}
diff --git a/install/ui/test/data/hbacrule_remove_sourcehost.json b/install/ui/test/data/hbacrule_remove_sourcehost.json
new file mode 100644
index 000000000..da32f76e0
--- /dev/null
+++ b/install/ui/test/data/hbacrule_remove_sourcehost.json
@@ -0,0 +1,50 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "completed": 2,
+ "failed": {
+ "sourcehost": {
+ "host": [],
+ "hostgroup": []
+ }
+ },
+ "result": {
+ "accessruletype": [
+ "allow"
+ ],
+ "accesstime": [
+ "periodic daily 0800-1400",
+ "absolute 201012161032 ~ 201012161033"
+ ],
+ "cn": [
+ "test"
+ ],
+ "dn": "ipauniqueid=e8aca082-e64a11df-9864f2e0-e0578392,cn=hbac,dc=dev,dc=example,dc=com",
+ "ipaenabledflag": [
+ "TRUE"
+ ],
+ "memberhost_host": [
+ "dev.example.com"
+ ],
+ "memberhost_hostgroup": [
+ "production"
+ ],
+ "memberservice_hbacsvc": [
+ "ftp",
+ "sshd"
+ ],
+ "memberservice_hbacsvcgroup": [
+ "sudo"
+ ],
+ "memberuser_group": [
+ "admins",
+ "editors"
+ ],
+ "memberuser_user": [
+ "admin",
+ "test"
+ ]
+ }
+ }
+}
diff --git a/install/ui/test/data/hbacrule_remove_user.json b/install/ui/test/data/hbacrule_remove_user.json
new file mode 100644
index 000000000..f25317e83
--- /dev/null
+++ b/install/ui/test/data/hbacrule_remove_user.json
@@ -0,0 +1,48 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "completed": 3,
+ "failed": {
+ "memberuser": {
+ "group": [],
+ "user": []
+ }
+ },
+ "result": {
+ "accessruletype": [
+ "allow"
+ ],
+ "accesstime": [
+ "periodic daily 0800-1400",
+ "absolute 201012161032 ~ 201012161033"
+ ],
+ "cn": [
+ "test"
+ ],
+ "dn": "ipauniqueid=e8aca082-e64a11df-9864f2e0-e0578392,cn=hbac,dc=dev,dc=example,dc=com",
+ "ipaenabledflag": [
+ "TRUE"
+ ],
+ "memberhost_host": [
+ "dev.example.com"
+ ],
+ "memberhost_hostgroup": [
+ "production"
+ ],
+ "memberservice_hbacsvc": [
+ "ftp",
+ "sshd"
+ ],
+ "memberservice_hbacsvcgroup": [
+ "sudo"
+ ],
+ "sourcehost_host": [
+ "dev.example.com"
+ ],
+ "sourcehost_hostgroup": [
+ "staging"
+ ]
+ }
+ }
+}
diff --git a/install/ui/test/data/hbacrule_show.json b/install/ui/test/data/hbacrule_show.json
new file mode 100644
index 000000000..2c0b64b39
--- /dev/null
+++ b/install/ui/test/data/hbacrule_show.json
@@ -0,0 +1,76 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "result": {
+ "accessruletype": [
+ "deny"
+ ],
+ "accesstime": [
+ "periodic daily 0800-1400",
+ "absolute 201012161032 ~ 201012161033"
+ ],
+ "attributelevelrights": {
+ "accessruletype": "rscwo",
+ "accesstime": "rscwo",
+ "aci": "rscwo",
+ "cn": "rscwo",
+ "description": "rscwo",
+ "externalhost": "rscwo",
+ "hostcategory": "rscwo",
+ "ipaenabledflag": "rscwo",
+ "ipauniqueid": "rsc",
+ "memberhost": "rscwo",
+ "memberservice": "rscwo",
+ "memberuser": "rscwo",
+ "nsaccountlock": "rscwo",
+ "servicecategory": "rscwo",
+ "sourcehost": "rscwo",
+ "sourcehostcategory": "rscwo",
+ "usercategory": "rscwo"
+ },
+ "cn": [
+ "test"
+ ],
+ "dn": "ipauniqueid=4ed8b682-edf511df-b3f78f4b-11cc007b,cn=hbac,dc=dev,dc=example,dc=com",
+ "ipaenabledflag": [
+ "TRUE"
+ ],
+ "ipauniqueid": [
+ "4ed8b682-edf511df-b3f78f4b-11cc007b"
+ ],
+ "memberhost_host": [
+ "dev.example.com"
+ ],
+ "memberhost_hostgroup": [
+ "production"
+ ],
+ "memberservice_hbacsvc": [
+ "ftp",
+ "sshd"
+ ],
+ "memberservice_hbacsvcgroup": [
+ "sudo"
+ ],
+ "memberuser_group": [
+ "editors"
+ ],
+ "memberuser_user": [
+ "admin",
+ "test"
+ ],
+ "objectclass": [
+ "ipaassociation",
+ "ipahbacrule"
+ ],
+ "sourcehost_host": [
+ "dev.example.com"
+ ],
+ "sourcehost_hostgroup": [
+ "staging"
+ ]
+ },
+ "summary": null,
+ "value": "test"
+ }
+}
diff --git a/install/ui/test/data/hbacsvc_add.json b/install/ui/test/data/hbacsvc_add.json
new file mode 100644
index 000000000..87eb51d78
--- /dev/null
+++ b/install/ui/test/data/hbacsvc_add.json
@@ -0,0 +1,24 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "result": {
+ "cn": [
+ "test"
+ ],
+ "description": [
+ "Test Service"
+ ],
+ "dn": "cn=test,cn=hbacservices,cn=hbac,dc=dev,dc=example,dc=com",
+ "ipauniqueid": [
+ "c3302e82-ecfd11df-b3f78f4b-11cc007b"
+ ],
+ "objectclass": [
+ "ipaobject",
+ "ipahbacservice"
+ ]
+ },
+ "summary": "Added service \"test\"",
+ "value": "test"
+ }
+}
diff --git a/install/ui/test/data/hbacsvc_del.json b/install/ui/test/data/hbacsvc_del.json
new file mode 100644
index 000000000..fcfce6259
--- /dev/null
+++ b/install/ui/test/data/hbacsvc_del.json
@@ -0,0 +1,9 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "result": true,
+ "summary": "Deleted service \"test\"",
+ "value": "test"
+ }
+}
diff --git a/install/ui/test/data/hbacsvc_find.json b/install/ui/test/data/hbacsvc_find.json
new file mode 100644
index 000000000..86a9bcaa5
--- /dev/null
+++ b/install/ui/test/data/hbacsvc_find.json
@@ -0,0 +1,101 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "count": 10,
+ "result": [
+ {
+ "cn": [
+ "sshd"
+ ],
+ "description": [
+ "sshd"
+ ],
+ "dn": "cn=sshd,cn=hbacservices,cn=hbac,dc=dev,dc=example,dc=com"
+ },
+ {
+ "cn": [
+ "ftp"
+ ],
+ "description": [
+ "ftp"
+ ],
+ "dn": "cn=ftp,cn=hbacservices,cn=hbac,dc=dev,dc=example,dc=com"
+ },
+ {
+ "cn": [
+ "su"
+ ],
+ "description": [
+ "su"
+ ],
+ "dn": "cn=su,cn=hbacservices,cn=hbac,dc=dev,dc=example,dc=com"
+ },
+ {
+ "cn": [
+ "login"
+ ],
+ "description": [
+ "login"
+ ],
+ "dn": "cn=login,cn=hbacservices,cn=hbac,dc=dev,dc=example,dc=com"
+ },
+ {
+ "cn": [
+ "su-l"
+ ],
+ "description": [
+ "su with login shell"
+ ],
+ "dn": "cn=su-l,cn=hbacservices,cn=hbac,dc=dev,dc=example,dc=com"
+ },
+ {
+ "cn": [
+ "sudo"
+ ],
+ "description": [
+ "sudo"
+ ],
+ "dn": "cn=sudo,cn=hbacservices,cn=hbac,dc=dev,dc=example,dc=com"
+ },
+ {
+ "cn": [
+ "sudo-i"
+ ],
+ "description": [
+ "sudo-i"
+ ],
+ "dn": "cn=sudo-i,cn=hbacservices,cn=hbac,dc=dev,dc=example,dc=com"
+ },
+ {
+ "cn": [
+ "gdm"
+ ],
+ "description": [
+ "gdm"
+ ],
+ "dn": "cn=gdm,cn=hbacservices,cn=hbac,dc=dev,dc=example,dc=com"
+ },
+ {
+ "cn": [
+ "gdm-password"
+ ],
+ "description": [
+ "gdm-password"
+ ],
+ "dn": "cn=gdm-password,cn=hbacservices,cn=hbac,dc=dev,dc=example,dc=com"
+ },
+ {
+ "cn": [
+ "kdm"
+ ],
+ "description": [
+ "kdm"
+ ],
+ "dn": "cn=kdm,cn=hbacservices,cn=hbac,dc=dev,dc=example,dc=com"
+ }
+ ],
+ "summary": null,
+ "truncated": false
+ }
+}
diff --git a/install/ui/test/data/hbacsvc_mod.json b/install/ui/test/data/hbacsvc_mod.json
new file mode 100644
index 000000000..335009a98
--- /dev/null
+++ b/install/ui/test/data/hbacsvc_mod.json
@@ -0,0 +1,31 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "result": {
+ "attributelevelrights": {
+ "aci": "rscwo",
+ "cn": "rscwo",
+ "description": "rscwo",
+ "ipauniqueid": "rsc",
+ "memberof": "rsc",
+ "nsaccountlock": "rscwo"
+ },
+ "cn": [
+ "test"
+ ],
+ "description": [
+ "Test"
+ ],
+ "ipauniqueid": [
+ "9e5aba82-edd411df-b3f78f4b-11cc007b"
+ ],
+ "objectclass": [
+ "ipaobject",
+ "ipahbacservice"
+ ]
+ },
+ "summary": null,
+ "value": "test"
+ }
+}
diff --git a/install/ui/test/data/hbacsvc_show.json b/install/ui/test/data/hbacsvc_show.json
new file mode 100644
index 000000000..8ebfbd7c1
--- /dev/null
+++ b/install/ui/test/data/hbacsvc_show.json
@@ -0,0 +1,35 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "result": {
+ "attributelevelrights": {
+ "aci": "rscwo",
+ "cn": "rscwo",
+ "description": "rscwo",
+ "ipauniqueid": "rsc",
+ "memberof": "rsc",
+ "nsaccountlock": "rscwo"
+ },
+ "cn": [
+ "sudo"
+ ],
+ "description": [
+ "sudo"
+ ],
+ "dn": "cn=sudo,cn=hbacservices,cn=hbac,dc=dev,dc=example,dc=com",
+ "ipauniqueid": [
+ "676e92a1-ec7611df-b3f78f4b-11cc007b"
+ ],
+ "memberof": [
+ "cn=SUDO,cn=hbacservicegroups,cn=hbac,dc=dev,dc=example,dc=com"
+ ],
+ "objectclass": [
+ "ipahbacservice",
+ "ipaobject"
+ ]
+ },
+ "summary": null,
+ "value": "sudo"
+ }
+}
diff --git a/install/ui/test/data/hbacsvcgroup_add.json b/install/ui/test/data/hbacsvcgroup_add.json
new file mode 100644
index 000000000..0dd1e96fe
--- /dev/null
+++ b/install/ui/test/data/hbacsvcgroup_add.json
@@ -0,0 +1,26 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "result": {
+ "cn": [
+ "test"
+ ],
+ "description": [
+ "Test Service Group"
+ ],
+ "dn": "cn=test,cn=hbacservicegroups,cn=hbac,dc=dev,dc=example,dc=com",
+ "ipauniqueid": [
+ "0ab6ba82-ecfe11df-b3f78f4b-11cc007b"
+ ],
+ "objectclass": [
+ "ipaobject",
+ "ipahbacservicegroup",
+ "groupOfNames",
+ "top"
+ ]
+ },
+ "summary": "Added HBAC Service group \"test\"",
+ "value": "test"
+ }
+}
diff --git a/install/ui/test/data/hbacsvcgroup_add_member.json b/install/ui/test/data/hbacsvcgroup_add_member.json
new file mode 100644
index 000000000..8526e1848
--- /dev/null
+++ b/install/ui/test/data/hbacsvcgroup_add_member.json
@@ -0,0 +1,24 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "completed": 1,
+ "failed": {
+ "member": {
+ "hbacsvc": []
+ }
+ },
+ "result": {
+ "cn": [
+ "test"
+ ],
+ "description": [
+ "Test Service Group"
+ ],
+ "dn": "cn=test,cn=hbacservicegroups,cn=hbac,dc=dev,dc=example,dc=com",
+ "member_hbacsvc": [
+ "test"
+ ]
+ }
+ }
+}
diff --git a/install/ui/test/data/hbacsvcgroup_del.json b/install/ui/test/data/hbacsvcgroup_del.json
new file mode 100644
index 000000000..134f7417e
--- /dev/null
+++ b/install/ui/test/data/hbacsvcgroup_del.json
@@ -0,0 +1,9 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "result": true,
+ "summary": "Deleted HBAC Service group \"test\"",
+ "value": "test"
+ }
+}
diff --git a/install/ui/test/data/hbacsvcgroup_find.json b/install/ui/test/data/hbacsvcgroup_find.json
new file mode 100644
index 000000000..797530e37
--- /dev/null
+++ b/install/ui/test/data/hbacsvcgroup_find.json
@@ -0,0 +1,24 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "count": 1,
+ "result": [
+ {
+ "cn": [
+ "SUDO"
+ ],
+ "description": [
+ "Default group of SUDO related services"
+ ],
+ "dn": "cn=sudo,cn=hbacservicegroups,cn=hbac,dc=dev,dc=example,dc=com",
+ "member_hbacsvc": [
+ "sudo",
+ "sudo-i"
+ ]
+ }
+ ],
+ "summary": "1 group matched",
+ "truncated": false
+ }
+}
diff --git a/install/ui/test/data/hbacsvcgroup_member_hbacsvc.json b/install/ui/test/data/hbacsvcgroup_member_hbacsvc.json
new file mode 100644
index 000000000..a407a622f
--- /dev/null
+++ b/install/ui/test/data/hbacsvcgroup_member_hbacsvc.json
@@ -0,0 +1,57 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "count": 2,
+ "results": [
+ {
+ "error": null,
+ "result": {
+ "cn": [
+ "sudo"
+ ],
+ "description": [
+ "sudo"
+ ],
+ "dn": "cn=sudo,cn=hbacservices,cn=hbac,dc=dev,dc=example,dc=com",
+ "ipauniqueid": [
+ "42927a86-f46d-11df-8cc1-00163e72f2d9"
+ ],
+ "memberof": [
+ "cn=SUDO,cn=hbacservicegroups,cn=hbac,dc=dev,dc=example,dc=com"
+ ],
+ "objectclass": [
+ "ipahbacservice",
+ "ipaobject"
+ ]
+ },
+ "summary": null,
+ "value": "sudo"
+ },
+ {
+ "error": null,
+ "result": {
+ "cn": [
+ "sudo-i"
+ ],
+ "description": [
+ "sudo-i"
+ ],
+ "dn": "cn=sudo-i,cn=hbacservices,cn=hbac,dc=dev,dc=example,dc=com",
+ "ipauniqueid": [
+ "42970a6a-f46d-11df-8cc1-00163e72f2d9"
+ ],
+ "memberof": [
+ "cn=SUDO,cn=hbacservicegroups,cn=hbac,dc=dev,dc=example,dc=com"
+ ],
+ "objectclass": [
+ "ipahbacservice",
+ "ipaobject"
+ ]
+ },
+ "summary": null,
+ "value": "sudo-i"
+ }
+ ]
+ }
+}
diff --git a/install/ui/test/data/hbacsvcgroup_mod.json b/install/ui/test/data/hbacsvcgroup_mod.json
new file mode 100644
index 000000000..e0ec916d3
--- /dev/null
+++ b/install/ui/test/data/hbacsvcgroup_mod.json
@@ -0,0 +1,39 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "result": {
+ "attributelevelrights": {
+ "aci": "rscwo",
+ "businesscategory": "rscwo",
+ "cn": "rscwo",
+ "description": "rscwo",
+ "ipauniqueid": "rsc",
+ "member": "rscwo",
+ "nsaccountlock": "rscwo",
+ "o": "rscwo",
+ "objectclass": "rscwo",
+ "ou": "rscwo",
+ "owner": "rscwo",
+ "seealso": "rscwo"
+ },
+ "cn": [
+ "test"
+ ],
+ "description": [
+ "Test"
+ ],
+ "ipauniqueid": [
+ "2d67d284-edd511df-b3f78f4b-11cc007b"
+ ],
+ "objectclass": [
+ "ipaobject",
+ "ipahbacservicegroup",
+ "groupOfNames",
+ "top"
+ ]
+ },
+ "summary": "Modified HBAC Service group \"test\"",
+ "value": "test"
+ }
+}
diff --git a/install/ui/test/data/hbacsvcgroup_remove_member.json b/install/ui/test/data/hbacsvcgroup_remove_member.json
new file mode 100644
index 000000000..cdf413789
--- /dev/null
+++ b/install/ui/test/data/hbacsvcgroup_remove_member.json
@@ -0,0 +1,21 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "completed": 1,
+ "failed": {
+ "member": {
+ "hbacsvc": []
+ }
+ },
+ "result": {
+ "cn": [
+ "test"
+ ],
+ "description": [
+ "Test Service Group"
+ ],
+ "dn": "cn=test,cn=hbacservicegroups,cn=hbac,dc=dev,dc=example,dc=com"
+ }
+ }
+}
diff --git a/install/ui/test/data/hbacsvcgroup_show.json b/install/ui/test/data/hbacsvcgroup_show.json
new file mode 100644
index 000000000..ad3c4253b
--- /dev/null
+++ b/install/ui/test/data/hbacsvcgroup_show.json
@@ -0,0 +1,46 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "result": {
+ "attributelevelrights": {
+ "aci": "rscwo",
+ "businesscategory": "rscwo",
+ "cn": "rscwo",
+ "description": "rscwo",
+ "ipauniqueid": "rsc",
+ "member": "rscwo",
+ "memberof": "rsc",
+ "nsaccountlock": "rscwo",
+ "o": "rscwo",
+ "objectclass": "rscwo",
+ "ou": "rscwo",
+ "owner": "rscwo",
+ "seealso": "rscwo"
+ },
+ "cn": [
+ "SUDO"
+ ],
+ "description": [
+ "Default group of SUDO related services"
+ ],
+ "dn": "cn=sudo,cn=hbacservicegroups,cn=hbac,dc=dev,dc=example,dc=com",
+ "ipauniqueid": [
+ "676e92ab-ec7611df-b3f78f4b-11cc007b"
+ ],
+ "member_hbacsvc": [
+ "sudo",
+ "sudo-i"
+ ],
+ "objectclass": [
+ "ipaobject",
+ "ipahbacservicegroup",
+ "nestedGroup",
+ "groupOfNames",
+ "top"
+ ]
+ },
+ "summary": null,
+ "value": "sudo"
+ }
+}
diff --git a/install/ui/test/data/host_add.json b/install/ui/test/data/host_add.json
new file mode 100644
index 000000000..8b4d8b93a
--- /dev/null
+++ b/install/ui/test/data/host_add.json
@@ -0,0 +1,40 @@
+{
+ "error": null,
+ "id": 14,
+ "result": {
+ "result": {
+ "cn": [
+ "www.pbs.org"
+ ],
+ "dn": "fqdn=www.pbs.org,cn=computers,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "fqdn": [
+ "www.pbs.org"
+ ],
+ "has_keytab": false,
+ "ipauniqueid": [
+ "3ad2e63d-b43a-11df-8dd1-525400674dcd"
+ ],
+ "krbprincipalname": [
+ "host/www.pbs.org@AYOUNG.BOSTON.DEVEL.REDHAT.COM"
+ ],
+ "managedby": [
+ "fqdn=www.pbs.org,cn=computers,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com"
+ ],
+ "objectclass": [
+ "ipaobject",
+ "nshost",
+ "ipahost",
+ "pkiuser",
+ "ipaservice",
+ "krbprincipalaux",
+ "krbprincipal",
+ "top"
+ ],
+ "serverhostname": [
+ "www"
+ ]
+ },
+ "summary": null,
+ "value": "www.pbs.org"
+ }
+} \ No newline at end of file
diff --git a/install/ui/test/data/host_disable_dev.example.com.json b/install/ui/test/data/host_disable_dev.example.com.json
new file mode 100644
index 000000000..06f5aaa99
--- /dev/null
+++ b/install/ui/test/data/host_disable_dev.example.com.json
@@ -0,0 +1,9 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "result": true,
+ "summary": "Removed kerberos key from \"dev.example.com\"",
+ "value": "dev.example.com"
+ }
+}
diff --git a/install/ui/test/data/host_find.json b/install/ui/test/data/host_find.json
new file mode 100644
index 000000000..48b1fcb89
--- /dev/null
+++ b/install/ui/test/data/host_find.json
@@ -0,0 +1,91 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "count": 2,
+ "result": [
+ {
+ "cn": [
+ "dev.example.com"
+ ],
+ "dn": "fqdn=dev.example.com,cn=computers,cn=accounts,dc=dev,dc=example,dc=com",
+ "fqdn": [
+ "dev.example.com"
+ ],
+ "ipauniqueid": [
+ "fc6a6d5a-f388-11df-9c01-00163e72f2d9"
+ ],
+ "krbextradata": [
+ {
+ "__base64__": "AAL+5+VMYWRtaW4vYWRtaW5AREVWLkVYQU1QTEUuQ09NAA=="
+ },
+ {
+ "__base64__": "AAgBAA=="
+ }
+ ],
+ "krblastpwdchange": [
+ "20101119025910Z"
+ ],
+ "krbpasswordexpiration": [
+ "19700101000000Z"
+ ],
+ "krbprincipalname": [
+ "host/dev.example.com@DEV.EXAMPLE.COM"
+ ],
+ "krbticketflags": [
+ "0"
+ ],
+ "managedby": [
+ "fqdn=dev.example.com,cn=computers,cn=accounts,dc=dev,dc=example,dc=com"
+ ],
+ "objectclass": [
+ "top",
+ "ipaobject",
+ "nshost",
+ "ipahost",
+ "ipaservice",
+ "pkiuser",
+ "krbprincipalaux",
+ "krbprincipal",
+ "krbticketpolicyaux"
+ ],
+ "serverhostname": [
+ "dev"
+ ]
+ },
+ {
+ "cn": [
+ "test.example.com"
+ ],
+ "dn": "fqdn=test.example.com,cn=computers,cn=accounts,dc=dev,dc=example,dc=com",
+ "fqdn": [
+ "test.example.com"
+ ],
+ "ipauniqueid": [
+ "ac28dca0-f3b5-11df-879f-00163e72f2d9"
+ ],
+ "krbprincipalname": [
+ "host/test.example.com@DEV.EXAMPLE.COM"
+ ],
+ "managedby": [
+ "fqdn=test.example.com,cn=computers,cn=accounts,dc=dev,dc=example,dc=com"
+ ],
+ "objectclass": [
+ "ipaobject",
+ "nshost",
+ "ipahost",
+ "pkiuser",
+ "ipaservice",
+ "krbprincipalaux",
+ "krbprincipal",
+ "top"
+ ],
+ "serverhostname": [
+ "test"
+ ]
+ }
+ ],
+ "summary": "2 hosts matched",
+ "truncated": false
+ }
+}
diff --git a/install/ui/test/data/host_mod.json b/install/ui/test/data/host_mod.json
new file mode 100644
index 000000000..3cb7d9ec5
--- /dev/null
+++ b/install/ui/test/data/host_mod.json
@@ -0,0 +1,75 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "result": {
+ "attributelevelrights": {
+ "aci": "rscwo",
+ "cn": "rscwo",
+ "description": "rscwo",
+ "enrolledby": "rsc",
+ "fqdn": "rscwo",
+ "ipaclientversion": "rscwo",
+ "ipauniqueid": "rsc",
+ "krbcanonicalname": "rscwo",
+ "krbextradata": "rscwo",
+ "krblastfailedauth": "rscwo",
+ "krblastpwdchange": "rscwo",
+ "krblastsuccessfulauth": "rscwo",
+ "krbloginfailedcount": "rscwo",
+ "krbobjectreferences": "rscwo",
+ "krbpasswordexpiration": "rscwo",
+ "krbprincipalaliases": "rscwo",
+ "krbprincipalexpiration": "rscwo",
+ "krbprincipalkey": "wo",
+ "krbprincipalname": "rscwo",
+ "krbprincipaltype": "rscwo",
+ "krbpwdhistory": "rscwo",
+ "krbpwdpolicyreference": "rscwo",
+ "krbticketpolicyreference": "rscwo",
+ "krbupenabled": "rscwo",
+ "l": "rscwo",
+ "managedby": "rscwo",
+ "memberof": "rsc",
+ "nsaccountlock": "rscwo",
+ "nshardwareplatform": "rscwo",
+ "nshostlocation": "rscwo",
+ "nsosversion": "rscwo",
+ "objectclass": "rscwo",
+ "serverhostname": "rsc",
+ "usercertificate": "rscwo",
+ "userpassword": "wo"
+ },
+ "cn": [
+ "test.example.com"
+ ],
+ "fqdn": [
+ "test.example.com"
+ ],
+ "ipauniqueid": [
+ "ac28dca0-f3b5-11df-879f-00163e72f2d9"
+ ],
+ "krbprincipalname": [
+ "host/test.example.com@DEV.EXAMPLE.COM"
+ ],
+ "managedby": [
+ "fqdn=test.example.com,cn=computers,cn=accounts,dc=dev,dc=example,dc=com"
+ ],
+ "objectclass": [
+ "ipaobject",
+ "nshost",
+ "ipahost",
+ "pkiuser",
+ "ipaservice",
+ "krbprincipalaux",
+ "krbprincipal",
+ "top"
+ ],
+ "serverhostname": [
+ "test"
+ ]
+ },
+ "summary": "Modified host \"test.example.com\"",
+ "value": "test.example.com"
+ }
+}
diff --git a/install/ui/test/data/host_show.json b/install/ui/test/data/host_show.json
new file mode 100644
index 000000000..b87802310
--- /dev/null
+++ b/install/ui/test/data/host_show.json
@@ -0,0 +1,80 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "result": {
+ "attributelevelrights": {
+ "aci": "rscwo",
+ "cn": "rscwo",
+ "description": "rscwo",
+ "enrolledby": "rsc",
+ "fqdn": "rscwo",
+ "ipaclientversion": "rscwo",
+ "ipauniqueid": "rsc",
+ "krbcanonicalname": "rsc",
+ "krbextradata": "rsc",
+ "krblastfailedauth": "rsc",
+ "krblastpwdchange": "rscwo",
+ "krblastsuccessfulauth": "rsc",
+ "krbloginfailedcount": "rsc",
+ "krbmaxrenewableage": "rscwo",
+ "krbmaxticketlife": "rscwo",
+ "krbobjectreferences": "rscwo",
+ "krbpasswordexpiration": "rsc",
+ "krbprincipalaliases": "rsc",
+ "krbprincipalexpiration": "rsc",
+ "krbprincipalkey": "wo",
+ "krbprincipalname": "rsc",
+ "krbprincipaltype": "rsc",
+ "krbpwdhistory": "rsc",
+ "krbpwdpolicyreference": "rsc",
+ "krbticketflags": "rsc",
+ "krbticketpolicyreference": "rsc",
+ "krbupenabled": "rsc",
+ "l": "rscwo",
+ "managedby": "rscwo",
+ "memberof": "rsc",
+ "nsaccountlock": "rscwo",
+ "nshardwareplatform": "rscwo",
+ "nshostlocation": "rscwo",
+ "nsosversion": "rscwo",
+ "objectclass": "rscwo",
+ "serverhostname": "rsc",
+ "usercertificate": "rscwo",
+ "userpassword": "wo"
+ },
+ "cn": [
+ "test.example.com"
+ ],
+ "dn": "fqdn=test.example.com,cn=computers,cn=accounts,dc=dev,dc=example,dc=com",
+ "fqdn": [
+ "test.example.com"
+ ],
+ "has_keytab": false,
+ "ipauniqueid": [
+ "ac28dca0-f3b5-11df-879f-00163e72f2d9"
+ ],
+ "krbprincipalname": [
+ "host/test.example.com@DEV.EXAMPLE.COM"
+ ],
+ "managedby": [
+ "fqdn=test.example.com,cn=computers,cn=accounts,dc=dev,dc=example,dc=com"
+ ],
+ "objectclass": [
+ "ipaobject",
+ "nshost",
+ "ipahost",
+ "pkiuser",
+ "ipaservice",
+ "krbprincipalaux",
+ "krbprincipal",
+ "top"
+ ],
+ "serverhostname": [
+ "test"
+ ]
+ },
+ "summary": null,
+ "value": "test.example.com"
+ }
+}
diff --git a/install/ui/test/data/host_show_dev.example.com.json b/install/ui/test/data/host_show_dev.example.com.json
new file mode 100644
index 000000000..1ee9f445f
--- /dev/null
+++ b/install/ui/test/data/host_show_dev.example.com.json
@@ -0,0 +1,98 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "result": {
+ "attributelevelrights": {
+ "aci": "rscwo",
+ "cn": "rscwo",
+ "description": "rscwo",
+ "enrolledby": "rsc",
+ "fqdn": "rscwo",
+ "ipaclientversion": "rscwo",
+ "ipauniqueid": "rsc",
+ "krbcanonicalname": "rsc",
+ "krbextradata": "rsc",
+ "krblastfailedauth": "rsc",
+ "krblastpwdchange": "rscwo",
+ "krblastsuccessfulauth": "rsc",
+ "krbloginfailedcount": "rsc",
+ "krbmaxrenewableage": "rscwo",
+ "krbmaxticketlife": "rscwo",
+ "krbobjectreferences": "rscwo",
+ "krbpasswordexpiration": "rsc",
+ "krbprincipalaliases": "rsc",
+ "krbprincipalexpiration": "rsc",
+ "krbprincipalkey": "wo",
+ "krbprincipalname": "rsc",
+ "krbprincipaltype": "rsc",
+ "krbpwdhistory": "rsc",
+ "krbpwdpolicyreference": "rsc",
+ "krbticketflags": "rsc",
+ "krbticketpolicyreference": "rsc",
+ "krbupenabled": "rsc",
+ "l": "rscwo",
+ "managedby": "rscwo",
+ "memberof": "rsc",
+ "nsaccountlock": "rscwo",
+ "nshardwareplatform": "rscwo",
+ "nshostlocation": "rscwo",
+ "nsosversion": "rscwo",
+ "objectclass": "rscwo",
+ "serverhostname": "rsc",
+ "usercertificate": "rscwo",
+ "userpassword": "wo"
+ },
+ "cn": [
+ "dev.example.com"
+ ],
+ "dn": "fqdn=dev.example.com,cn=computers,cn=accounts,dc=dev,dc=example,dc=com",
+ "fqdn": [
+ "dev.example.com"
+ ],
+ "has_keytab": true,
+ "ipauniqueid": [
+ "fc6a6d5a-f388-11df-9c01-00163e72f2d9"
+ ],
+ "krbextradata": [
+ {
+ "__base64__": "AAL+5+VMYWRtaW4vYWRtaW5AREVWLkVYQU1QTEUuQ09NAA=="
+ },
+ {
+ "__base64__": "AAgBAA=="
+ }
+ ],
+ "krblastpwdchange": [
+ "20101119025910Z"
+ ],
+ "krbpasswordexpiration": [
+ "19700101000000Z"
+ ],
+ "krbprincipalname": [
+ "host/dev.example.com@DEV.EXAMPLE.COM"
+ ],
+ "krbticketflags": [
+ "0"
+ ],
+ "managedby": [
+ "fqdn=dev.example.com,cn=computers,cn=accounts,dc=dev,dc=example,dc=com"
+ ],
+ "objectclass": [
+ "top",
+ "ipaobject",
+ "nshost",
+ "ipahost",
+ "ipaservice",
+ "pkiuser",
+ "krbprincipalaux",
+ "krbprincipal",
+ "krbticketpolicyaux"
+ ],
+ "serverhostname": [
+ "dev"
+ ]
+ },
+ "summary": null,
+ "value": "dev.example.com"
+ }
+}
diff --git a/install/ui/test/data/host_show_test.example.com.json b/install/ui/test/data/host_show_test.example.com.json
new file mode 100644
index 000000000..b87802310
--- /dev/null
+++ b/install/ui/test/data/host_show_test.example.com.json
@@ -0,0 +1,80 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "result": {
+ "attributelevelrights": {
+ "aci": "rscwo",
+ "cn": "rscwo",
+ "description": "rscwo",
+ "enrolledby": "rsc",
+ "fqdn": "rscwo",
+ "ipaclientversion": "rscwo",
+ "ipauniqueid": "rsc",
+ "krbcanonicalname": "rsc",
+ "krbextradata": "rsc",
+ "krblastfailedauth": "rsc",
+ "krblastpwdchange": "rscwo",
+ "krblastsuccessfulauth": "rsc",
+ "krbloginfailedcount": "rsc",
+ "krbmaxrenewableage": "rscwo",
+ "krbmaxticketlife": "rscwo",
+ "krbobjectreferences": "rscwo",
+ "krbpasswordexpiration": "rsc",
+ "krbprincipalaliases": "rsc",
+ "krbprincipalexpiration": "rsc",
+ "krbprincipalkey": "wo",
+ "krbprincipalname": "rsc",
+ "krbprincipaltype": "rsc",
+ "krbpwdhistory": "rsc",
+ "krbpwdpolicyreference": "rsc",
+ "krbticketflags": "rsc",
+ "krbticketpolicyreference": "rsc",
+ "krbupenabled": "rsc",
+ "l": "rscwo",
+ "managedby": "rscwo",
+ "memberof": "rsc",
+ "nsaccountlock": "rscwo",
+ "nshardwareplatform": "rscwo",
+ "nshostlocation": "rscwo",
+ "nsosversion": "rscwo",
+ "objectclass": "rscwo",
+ "serverhostname": "rsc",
+ "usercertificate": "rscwo",
+ "userpassword": "wo"
+ },
+ "cn": [
+ "test.example.com"
+ ],
+ "dn": "fqdn=test.example.com,cn=computers,cn=accounts,dc=dev,dc=example,dc=com",
+ "fqdn": [
+ "test.example.com"
+ ],
+ "has_keytab": false,
+ "ipauniqueid": [
+ "ac28dca0-f3b5-11df-879f-00163e72f2d9"
+ ],
+ "krbprincipalname": [
+ "host/test.example.com@DEV.EXAMPLE.COM"
+ ],
+ "managedby": [
+ "fqdn=test.example.com,cn=computers,cn=accounts,dc=dev,dc=example,dc=com"
+ ],
+ "objectclass": [
+ "ipaobject",
+ "nshost",
+ "ipahost",
+ "pkiuser",
+ "ipaservice",
+ "krbprincipalaux",
+ "krbprincipal",
+ "top"
+ ],
+ "serverhostname": [
+ "test"
+ ]
+ },
+ "summary": null,
+ "value": "test.example.com"
+ }
+}
diff --git a/install/ui/test/data/hostgroup_add.json b/install/ui/test/data/hostgroup_add.json
new file mode 100644
index 000000000..bc41ee7d8
--- /dev/null
+++ b/install/ui/test/data/hostgroup_add.json
@@ -0,0 +1,27 @@
+{
+ "error": null,
+ "id": 15,
+ "result": {
+ "result": {
+ "cn": [
+ "guest_hosts"
+ ],
+ "description": [
+ "Special Guest Stars"
+ ],
+ "dn": "cn=guest_hosts,cn=hostgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "ipauniqueid": [
+ "7f8c57ae-b43a-11df-8016-525400674dcd"
+ ],
+ "objectclass": [
+ "ipaobject",
+ "ipahostgroup",
+ "nestedGroup",
+ "groupOfNames",
+ "top"
+ ]
+ },
+ "summary": "Added hostgroup \"guest_hosts\"",
+ "value": "guest_hosts"
+ }
+} \ No newline at end of file
diff --git a/install/ui/test/data/hostgroup_add_member.json b/install/ui/test/data/hostgroup_add_member.json
new file mode 100644
index 000000000..a92201751
--- /dev/null
+++ b/install/ui/test/data/hostgroup_add_member.json
@@ -0,0 +1,37 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "completed": 3,
+ "failed": {
+ "member": {
+ "host": [],
+ "hostgroup": []
+ }
+ },
+ "result": {
+ "cn": [
+ "host-live"
+ ],
+ "description": [
+ "Live servers"
+ ],
+ "dn": "cn=host-live,cn=hostgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "ipauniqueid": [
+ "1ba89342-b683-11df-8d5b-525400674dcd"
+ ],
+ "member_host": [
+ "live3.pbs.org",
+ "live2.pbs.org",
+ "live1.pbs.org"
+ ],
+ "objectclass": [
+ "ipaobject",
+ "ipahostgroup",
+ "nestedGroup",
+ "groupOfNames",
+ "top"
+ ]
+ }
+ }
+} \ No newline at end of file
diff --git a/install/ui/test/data/hostgroup_find.json b/install/ui/test/data/hostgroup_find.json
new file mode 100644
index 000000000..6732910c0
--- /dev/null
+++ b/install/ui/test/data/hostgroup_find.json
@@ -0,0 +1,33 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "count": 2,
+ "result": [
+ {
+ "cn": [
+ "host-live"
+ ],
+ "description": [
+ "Live servers"
+ ],
+ "dn": "cn=host-live,cn=hostgroups,cn=accounts,dc=idm,dc=lab,dc=bos,dc=redhat,dc=com",
+ "member": [],
+ "memberof": []
+ },
+ {
+ "cn": [
+ "stage-live"
+ ],
+ "description": [
+ "Staging servers"
+ ],
+ "dn": "cn=stage-live,cn=hostgroups,cn=accounts,dc=idm,dc=lab,dc=bos,dc=redhat,dc=com",
+ "member": [],
+ "memberof": []
+ }
+ ],
+ "summary": "2 hostgroups matched",
+ "truncated": false
+ }
+} \ No newline at end of file
diff --git a/install/ui/test/data/hostgroup_member_host.json b/install/ui/test/data/hostgroup_member_host.json
new file mode 100644
index 000000000..c4c7dfa98
--- /dev/null
+++ b/install/ui/test/data/hostgroup_member_host.json
@@ -0,0 +1,70 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "count": 1,
+ "results": [
+ {
+ "error": null,
+ "result": {
+ "cn": [
+ "dev.example.com"
+ ],
+ "description": [
+ "Development"
+ ],
+ "dn": "fqdn=dev.example.com,cn=computers,cn=accounts,dc=dev,dc=example,dc=com",
+ "fqdn": [
+ "dev.example.com"
+ ],
+ "has_keytab": true,
+ "ipauniqueid": [
+ "0568a298-f46d-11df-9ef8-00163e72f2d9"
+ ],
+ "krbextradata": [
+ {
+ "__base64__": "AAKTZudMYWRtaW4vYWRtaW5AREVWLkVYQU1QTEUuQ09NAA=="
+ },
+ {
+ "__base64__": "AAgBAA=="
+ }
+ ],
+ "krblastpwdchange": [
+ "20101120061131Z"
+ ],
+ "krbpasswordexpiration": [
+ "19700101000000Z"
+ ],
+ "krbprincipalname": [
+ "host/dev.example.com@DEV.EXAMPLE.COM"
+ ],
+ "krbticketflags": [
+ "0"
+ ],
+ "managedby_host": [
+ "dev.example.com"
+ ],
+ "memberof_hostgroup": [
+ "test"
+ ],
+ "objectclass": [
+ "top",
+ "ipaobject",
+ "nshost",
+ "ipahost",
+ "ipaservice",
+ "pkiuser",
+ "krbprincipalaux",
+ "krbprincipal",
+ "krbticketpolicyaux"
+ ],
+ "serverhostname": [
+ "dev"
+ ]
+ },
+ "summary": null,
+ "value": "dev.example.com"
+ }
+ ]
+ }
+}
diff --git a/install/ui/test/data/hostgroup_show.json b/install/ui/test/data/hostgroup_show.json
new file mode 100644
index 000000000..776d446dd
--- /dev/null
+++ b/install/ui/test/data/hostgroup_show.json
@@ -0,0 +1,22 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "result": {
+ "cn": [
+ "host-live"
+ ],
+ "description": [
+ "Live servers"
+ ],
+ "dn": "cn=host-live,cn=hostgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_host": [
+ "live3.pbs.org",
+ "live2.pbs.org",
+ "live1.pbs.org"
+ ]
+ },
+ "summary": null,
+ "value": "host-live"
+ }
+} \ No newline at end of file
diff --git a/install/ui/test/data/i18n_messages.json b/install/ui/test/data/i18n_messages.json
new file mode 100644
index 000000000..6dfb1c645
--- /dev/null
+++ b/install/ui/test/data/i18n_messages.json
@@ -0,0 +1,37 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "messages": {
+ "ajax": {
+ "401": "Your kerberos ticket no longer valid.Please run KInit and then click 'retry'If this is your first time running the IPA Web UI<a href='/ipa/errors/ssbrowser.html'> Follow these directions</a> to configure your browser."
+ },
+ "button": {
+ "add": "Add",
+ "enroll": "Enroll",
+ "find": "Find",
+ "remove": "Delete",
+ "reset": "Reset",
+ "update": "Update"
+ },
+ "details": {
+ "account": "Account Details",
+ "contact": "Contact Details",
+ "employee": " Employee Information",
+ "identity": "Identity Details",
+ "mailing": "Mailing Address",
+ "misc": "Misc. Information",
+ "to_top": "Back to Top"
+ },
+ "login": {
+ "header": "Logged In As"
+ },
+ "search": {
+ "delete_confirm": "Do you really want to delete the selected entries?",
+ "quick_links": "Quick Links",
+ "select_all": "Select All",
+ "unselect_all": "Unselect All"
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/install/ui/test/data/ipa_init.json b/install/ui/test/data/ipa_init.json
new file mode 100644
index 000000000..e0e6053c4
--- /dev/null
+++ b/install/ui/test/data/ipa_init.json
@@ -0,0 +1,7884 @@
+{
+ "error": null,
+ "id": 1,
+ "result": {
+ "count": 4,
+ "results": [
+ {
+ "error": null,
+ "metadata": {
+ "aci": {
+ "__base64__": ""
+ },
+ "automountkey": {
+ "aciattrs": [
+ "automountinformation",
+ "automountkey",
+ "description",
+ "objectclass"
+ ],
+ "attribute_members": {},
+ "bindable": false,
+ "container_dn": "cn=automount",
+ "default_attributes": [
+ "automountkey",
+ "automountinformation",
+ "description"
+ ],
+ "hidden_attributes": [
+ "objectclass",
+ "aci"
+ ],
+ "label": "Automount Keys",
+ "methods": [
+ "add",
+ "del",
+ "find",
+ "mod",
+ "show"
+ ],
+ "name": "automountkey",
+ "object_class": [
+ "automount"
+ ],
+ "object_class_config": null,
+ "object_name": "automount key",
+ "object_name_plural": "automount keys",
+ "parent_object": "automountmap",
+ "primary_key": "automountkey",
+ "rdn_attribute": "",
+ "relationships": {
+ "member": [
+ "Member",
+ "",
+ "no_"
+ ],
+ "memberindirect": [
+ "Indirect Member",
+ null,
+ "no_indirect_"
+ ],
+ "memberof": [
+ "Member Of",
+ "in_",
+ "not_in_"
+ ]
+ },
+ "takes_params": [
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "IA5Str",
+ "cli_name": "key",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Automount key name",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Key",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "automountkey",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": true,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "IA5Str",
+ "cli_name": "info",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Mount information",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Mount information",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "automountinformation",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "desc",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "description",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "description",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "description",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ }
+ ],
+ "uuid_attribute": ""
+ },
+ "automountlocation": {
+ "aciattrs": [
+ "cn",
+ "objectclass"
+ ],
+ "attribute_members": {},
+ "bindable": false,
+ "container_dn": "cn=automount",
+ "default_attributes": [
+ "cn"
+ ],
+ "hidden_attributes": [
+ "objectclass",
+ "aci"
+ ],
+ "label": "Automount",
+ "methods": [
+ "add",
+ "del",
+ "find",
+ "import",
+ "show",
+ "tofiles"
+ ],
+ "name": "automountlocation",
+ "object_class": [
+ "nscontainer"
+ ],
+ "object_class_config": null,
+ "object_name": "automount location",
+ "object_name_plural": "automount locations",
+ "parent_object": "",
+ "primary_key": "cn",
+ "rdn_attribute": "",
+ "relationships": {
+ "member": [
+ "Member",
+ "",
+ "no_"
+ ],
+ "memberindirect": [
+ "Indirect Member",
+ null,
+ "no_indirect_"
+ ],
+ "memberof": [
+ "Member Of",
+ "in_",
+ "not_in_"
+ ]
+ },
+ "takes_params": [
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "location",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Automount location name",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Location",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "cn",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": true,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ }
+ ],
+ "uuid_attribute": ""
+ },
+ "automountmap": {
+ "aciattrs": [
+ "automountmapname",
+ "description",
+ "objectclass"
+ ],
+ "attribute_members": {},
+ "bindable": false,
+ "container_dn": "cn=automount",
+ "default_attributes": [
+ "automountmapname",
+ "description"
+ ],
+ "hidden_attributes": [
+ "objectclass",
+ "aci"
+ ],
+ "label": "Automount Maps",
+ "methods": [
+ "add",
+ "add_indirect",
+ "del",
+ "find",
+ "mod",
+ "show"
+ ],
+ "name": "automountmap",
+ "object_class": [
+ "automountmap"
+ ],
+ "object_class_config": null,
+ "object_name": "automount map",
+ "object_name_plural": "automount maps",
+ "parent_object": "automountlocation",
+ "primary_key": "automountmapname",
+ "rdn_attribute": "",
+ "relationships": {
+ "member": [
+ "Member",
+ "",
+ "no_"
+ ],
+ "memberindirect": [
+ "Indirect Member",
+ null,
+ "no_indirect_"
+ ],
+ "memberof": [
+ "Member Of",
+ "in_",
+ "not_in_"
+ ]
+ },
+ "takes_params": [
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "IA5Str",
+ "cli_name": "map",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Automount map name",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Map",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "automountmapname",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": true,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "desc",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Description",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Description",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "description",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ }
+ ],
+ "uuid_attribute": ""
+ },
+ "config": {
+ "aciattrs": [],
+ "attribute_members": {},
+ "bindable": false,
+ "container_dn": "",
+ "default_attributes": [
+ "ipamaxusernamelength",
+ "ipahomesrootdir",
+ "ipadefaultloginshell",
+ "ipadefaultprimarygroup",
+ "ipadefaultemaildomain",
+ "ipasearchtimelimit",
+ "ipasearchrecordslimit",
+ "ipausersearchfields",
+ "ipagroupsearchfields",
+ "ipamigrationenabled",
+ "ipacertificatesubjectbase"
+ ],
+ "hidden_attributes": [
+ "objectclass",
+ "aci"
+ ],
+ "label": "Configuration",
+ "methods": [
+ "mod",
+ "show"
+ ],
+ "name": "config",
+ "object_class": [],
+ "object_class_config": null,
+ "object_name": "configuration options",
+ "object_name_plural": "entries",
+ "parent_object": "",
+ "rdn_attribute": "",
+ "relationships": {
+ "member": [
+ "Member",
+ "",
+ "no_"
+ ],
+ "memberindirect": [
+ "Indirect Member",
+ null,
+ "no_indirect_"
+ ],
+ "memberof": [
+ "Member Of",
+ "in_",
+ "not_in_"
+ ]
+ },
+ "takes_params": [
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Int",
+ "cli_name": "maxusername",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Max username length",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Max username length",
+ "maxvalue": null,
+ "minvalue": 1,
+ "multivalue": false,
+ "name": "ipamaxusernamelength",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "int"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "IA5Str",
+ "cli_name": "homedirectory",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Default location of home directories",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Home directory base",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "ipahomesrootdir",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "defaultshell",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Default shell for new users",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Default shell",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "ipadefaultloginshell",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "defaultgroup",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Default group for new users",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Default users group",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "ipadefaultprimarygroup",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "emaildomain",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Default e-mail domain new users",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Default e-mail domain",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "ipadefaultemaildomain",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Int",
+ "cli_name": "searchtimelimit",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Max. amount of time (sec.) for a search (-1 is unlimited)",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Search time limit",
+ "maxvalue": null,
+ "minvalue": -1,
+ "multivalue": false,
+ "name": "ipasearchtimelimit",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "int"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Int",
+ "cli_name": "searchrecordslimit",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Max. number of records to search (-1 is unlimited)",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Search size limit",
+ "maxvalue": null,
+ "minvalue": -1,
+ "multivalue": false,
+ "name": "ipasearchrecordslimit",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "int"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "IA5Str",
+ "cli_name": "usersearch",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "A comma-separated list of fields to search when searching for users",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "User search fields",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "ipausersearchfields",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "IA5Str",
+ "cli_name": "groupsearch",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "A comma-separated list of fields to search when searching for groups",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Group search fields",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "ipagroupsearchfields",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Bool",
+ "cli_name": "enable_migration",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Enable migration mode",
+ "exclude": null,
+ "falsehoods": [
+ 0,
+ "0",
+ "false"
+ ],
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Migration mode",
+ "multivalue": false,
+ "name": "ipamigrationenabled",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "truths": [
+ "1",
+ 1,
+ "true"
+ ],
+ "type": "bool"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "subject",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Base for certificate subjects (OU=Test,O=Example)",
+ "exclude": null,
+ "flags": [
+ "no_update"
+ ],
+ "hint": null,
+ "include": null,
+ "label": "Certificate Subject base",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "ipacertificatesubjectbase",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "List",
+ "cli_name": "groupobjectclasses",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Default group objectclassses (comma-separated list)",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Default group objectclasses",
+ "multivalue": true,
+ "name": "ipagroupobjectclasses",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "separator": ",",
+ "skipspace": true,
+ "type": "tuple"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "List",
+ "cli_name": "userobjectclasses",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Default user objectclassses (comma-separated list)",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Default user objectclasses",
+ "multivalue": true,
+ "name": "ipauserobjectclasses",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "separator": ",",
+ "skipspace": true,
+ "type": "tuple"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Int",
+ "cli_name": "pwdexpnotify",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Password Expiration Notification (days)",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Password Expiration Notification",
+ "maxvalue": null,
+ "minvalue": 0,
+ "multivalue": false,
+ "name": "ipapwdexpadvnotify",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "int"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "ipaconfigstring",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Extra hashes to generate in password plugin",
+ "exclude": null,
+ "flags": [
+ "no_update"
+ ],
+ "hint": null,
+ "include": null,
+ "label": "Password plugin features",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "ipaconfigstring",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ }
+ ],
+ "uuid_attribute": ""
+ },
+ "cosentry": {
+ "aciattrs": [
+ "a6record",
+ "aaaarecord",
+ "accessruletype",
+ "accesstime",
+ "accessto",
+ "accountinactivitylimit",
+ "accountunlocktime",
+ "acctpolicysubentry",
+ "aci",
+ "administratorcontactinfo",
+ "adminrole",
+ "adminurl",
+ "afsdbrecord",
+ "aliasedobjectname",
+ "altserver",
+ "arecord",
+ "associateddomain",
+ "associatedname",
+ "attributemap",
+ "attributetypes",
+ "audio",
+ "authenticationmethod",
+ "authorityrevocationlist",
+ "authorizedservice",
+ "automountinformation",
+ "automountkey",
+ "automountmapname",
+ "bindtimelimit",
+ "bootfile",
+ "bootparameter",
+ "buildingname",
+ "businesscategory",
+ "c",
+ "cacertificate",
+ "calcaladruri",
+ "calcaluri",
+ "calcapuri",
+ "calfburl",
+ "calothercaladruris",
+ "calothercaluris",
+ "calothercapuris",
+ "calotherfburls",
+ "carlicense",
+ "certificaterevocationlist",
+ "certrecord",
+ "changelog",
+ "changelogmaximumage",
+ "changelogmaximumconcurrentwrites",
+ "changelogmaximumsize",
+ "changenumber",
+ "changes",
+ "changetime",
+ "changetype",
+ "cirbeginorc",
+ "cirbindcredentials",
+ "cirbinddn",
+ "cirhost",
+ "cirlastupdateapplied",
+ "cirport",
+ "cirreplicaroot",
+ "cirsyncinterval",
+ "cirupdatefailedat",
+ "cirupdateschedule",
+ "cirusepersistentsearch",
+ "cirusessl",
+ "cmdcategory",
+ "cn",
+ "cnamerecord",
+ "co",
+ "connection",
+ "copiedfrom",
+ "copyingfrom",
+ "cosattribute",
+ "cosindirectspecifier",
+ "cospriority",
+ "cosspecifier",
+ "costargettree",
+ "costemplatedn",
+ "createtimestamp",
+ "creatorsname",
+ "credentiallevel",
+ "crosscertificatepair",
+ "dc",
+ "defaultsearchbase",
+ "defaultsearchscope",
+ "defaultserverlist",
+ "deleteoldrdn",
+ "deltarevocationlist",
+ "departmentnumber",
+ "dereferencealiases",
+ "description",
+ "destinationindicator",
+ "dialupaccess",
+ "displayname",
+ "distinguishedname",
+ "ditcontentrules",
+ "ditredirect",
+ "ditstructurerules",
+ "dnamerecord",
+ "dncomp",
+ "dnqualifier",
+ "dnsclass",
+ "dnsttl",
+ "documentauthor",
+ "documentidentifier",
+ "documentlocation",
+ "documentpublisher",
+ "documenttitle",
+ "documentversion",
+ "drink",
+ "dsrecord",
+ "edupersonaffiliation",
+ "edupersonentitlement",
+ "edupersonnickname",
+ "edupersonorgdn",
+ "edupersonorgunitdn",
+ "edupersonprimaryaffiliation",
+ "edupersonprimaryorgunitdn",
+ "edupersonprincipalname",
+ "edupersonscopedaffiliation",
+ "employeenumber",
+ "employeetype",
+ "enhancedsearchguide",
+ "enrolledby",
+ "entrydn",
+ "entryid",
+ "entryusn",
+ "externalhost",
+ "externaluser",
+ "facsimiletelephonenumber",
+ "filterinfo",
+ "followreferrals",
+ "fqdn",
+ "ftpdownloadbandwidth",
+ "ftpdownloadratio",
+ "ftpgid",
+ "ftpquotafiles",
+ "ftpquotambytes",
+ "ftpstatus",
+ "ftpuid",
+ "ftpuploadbandwidth",
+ "ftpuploadratio",
+ "gecos",
+ "generation",
+ "generationqualifier",
+ "gidnumber",
+ "givenname",
+ "governingstructurerule",
+ "hassubordinates",
+ "hinforecord",
+ "homedirectory",
+ "homephone",
+ "homepostaladdress",
+ "host",
+ "hostcapolicy",
+ "hostcategory",
+ "hostmask",
+ "houseidentifier",
+ "idnsallowdynupdate",
+ "idnsname",
+ "idnssoaexpire",
+ "idnssoaminimum",
+ "idnssoamname",
+ "idnssoarefresh",
+ "idnssoaretry",
+ "idnssoarname",
+ "idnssoaserial",
+ "idnsupdatepolicy",
+ "idnszoneactive",
+ "inetdomainbasedn",
+ "inetdomainstatus",
+ "inetsubscriberaccountid",
+ "inetsubscriberchallenge",
+ "inetsubscriberresponse",
+ "inetuserhttpurl",
+ "inetuserstatus",
+ "info",
+ "initials",
+ "installationtimestamp",
+ "internationalisdnnumber",
+ "ipacertificatesubjectbase",
+ "ipaclientversion",
+ "ipaconfigstring",
+ "ipacustomfields",
+ "ipadefaultemaildomain",
+ "ipadefaultloginshell",
+ "ipadefaultprimarygroup",
+ "ipaenabledflag",
+ "ipagroupobjectclasses",
+ "ipagroupsearchfields",
+ "ipahomesrootdir",
+ "ipamaxusernamelength",
+ "ipamigrationenabled",
+ "ipapwdexpadvnotify",
+ "ipasearchrecordslimit",
+ "ipasearchtimelimit",
+ "ipasudoopt",
+ "ipasudorunas",
+ "ipasudorunasextgroup",
+ "ipasudorunasextuser",
+ "ipasudorunasgroup",
+ "ipasudorunasgroupcategory",
+ "ipasudorunasusercategory",
+ "ipauniqueid",
+ "ipauserobjectclasses",
+ "ipausersearchfields",
+ "iphostnumber",
+ "ipnetmasknumber",
+ "ipnetworknumber",
+ "ipprotocolnumber",
+ "ipserviceport",
+ "ipserviceprotocol",
+ "isreplicated",
+ "javaclassname",
+ "javaclassnames",
+ "javacodebase",
+ "javadoc",
+ "javafactory",
+ "javareferenceaddress",
+ "javaserializeddata",
+ "jpegphoto",
+ "keyrecord",
+ "krbadmservers",
+ "krbcanonicalname",
+ "krbdefaultencsalttypes",
+ "krbextradata",
+ "krbhostserver",
+ "krbkdcservers",
+ "krblastfailedauth",
+ "krblastpwdchange",
+ "krblastsuccessfulauth",
+ "krbldapservers",
+ "krbloginfailedcount",
+ "krbmaxpwdlife",
+ "krbmaxrenewableage",
+ "krbmaxticketlife",
+ "krbminpwdlife",
+ "krbmkey",
+ "krbobjectreferences",
+ "krbpasswordexpiration",
+ "krbprinccontainerref",
+ "krbprincipalaliases",
+ "krbprincipalexpiration",
+ "krbprincipalkey",
+ "krbprincipalname",
+ "krbprincipalreferences",
+ "krbprincipaltype",
+ "krbprincnamingattr",
+ "krbpwdfailurecountinterval",
+ "krbpwdhistory",
+ "krbpwdhistorylength",
+ "krbpwdlockoutduration",
+ "krbpwdmaxfailure",
+ "krbpwdmindiffchars",
+ "krbpwdminlength",
+ "krbpwdpolicyreference",
+ "krbpwdservers",
+ "krbrealmreferences",
+ "krbsearchscope",
+ "krbsubtrees",
+ "krbsupportedencsalttypes",
+ "krbticketflags",
+ "krbticketpolicyreference",
+ "krbupenabled",
+ "kxrecord",
+ "l",
+ "labeleduri",
+ "lastlogintime",
+ "lastmodifiedby",
+ "lastmodifiedtime",
+ "ldapschemas",
+ "ldapsyntaxes",
+ "locrecord",
+ "loginshell",
+ "macaddress",
+ "mail",
+ "mailaccessdomain",
+ "mailalternateaddress",
+ "mailautoreplymode",
+ "mailautoreplytext",
+ "maildeliveryoption",
+ "mailenhanceduniquemember",
+ "mailforwardingaddress",
+ "mailhost",
+ "mailmessagestore",
+ "mailprogramdeliveryinfo",
+ "mailquota",
+ "mailroutingaddress",
+ "managedby",
+ "manager",
+ "matchingrules",
+ "matchingruleuse",
+ "mdrecord",
+ "member",
+ "memberallowcmd",
+ "membercertificatedescription",
+ "memberdenycmd",
+ "memberhost",
+ "membernisnetgroup",
+ "memberof",
+ "memberservice",
+ "memberuid",
+ "memberurl",
+ "memberuser",
+ "mepmanagedby",
+ "mepmanagedentry",
+ "mepmappedattr",
+ "meprdnattr",
+ "mepstaticattr",
+ "mgrpaddheader",
+ "mgrpallowedbroadcaster",
+ "mgrpalloweddomain",
+ "mgrpapprovepassword",
+ "mgrpbroadcasterpolicy",
+ "mgrpdeliverto",
+ "mgrperrorsto",
+ "mgrpmoderator",
+ "mgrpmsgmaxsize",
+ "mgrpmsgrejectaction",
+ "mgrpmsgrejecttext",
+ "mgrpnoduplicatechecks",
+ "mgrpremoveheader",
+ "mgrprfc822mailmember",
+ "minforecord",
+ "mobile",
+ "modifiersname",
+ "modifytimestamp",
+ "mozillacustom1",
+ "mozillacustom2",
+ "mozillacustom3",
+ "mozillacustom4",
+ "mozillahomecountryname",
+ "mozillahomelocalityname",
+ "mozillahomepostalcode",
+ "mozillahomestate",
+ "mozillahomestreet",
+ "mozillahomestreet2",
+ "mozillahomeurl",
+ "mozillanickname",
+ "mozillasecondemail",
+ "mozillausehtmlmail",
+ "mozillaworkstreet2",
+ "mozillaworkurl",
+ "multilinedescription",
+ "mxrecord",
+ "name",
+ "nameforms",
+ "namingcontexts",
+ "naptrrecord",
+ "netscapereversiblepassword",
+ "newrdn",
+ "newsuperior",
+ "nisdomain",
+ "nisdomainname",
+ "nismapentry",
+ "nismapname",
+ "nisnetgrouptriple",
+ "nisnetidgroup",
+ "nisnetidhost",
+ "nisnetiduser",
+ "nispublickey",
+ "nissecretkey",
+ "nsaccesslog",
+ "nsaccountlock",
+ "nsadminaccessaddresses",
+ "nsadminaccesshosts",
+ "nsadminaccountinfo",
+ "nsadmincachelifetime",
+ "nsadmincgiwaitpid",
+ "nsadmindomainname",
+ "nsadminenabledsgw",
+ "nsadminenableenduser",
+ "nsadminenduserhtmlindex",
+ "nsadmingroupname",
+ "nsadminoneacldir",
+ "nsadminsiedn",
+ "nsadminusers",
+ "nsaimid",
+ "nsbackendsuffix",
+ "nsbasedn",
+ "nsbinddn",
+ "nsbindpassword",
+ "nsbuildnumber",
+ "nsbuildsecurity",
+ "nscertconfig",
+ "nscertfile",
+ "nsclassname",
+ "nsconfigroot",
+ "nscpentrydn",
+ "nsdefaultacceptlanguage",
+ "nsdefaultobjectclass",
+ "nsdeleteclassname",
+ "nsdirectoryfailoverlist",
+ "nsdirectoryinforef",
+ "nsdirectoryurl",
+ "nsdisplayname",
+ "nsds50ruv",
+ "nsds5beginreplicarefresh",
+ "nsds5debugreplicatimeout",
+ "nsds5flags",
+ "nsds5replconflict",
+ "nsds5replicaautoreferral",
+ "nsds5replicabinddn",
+ "nsds5replicabindmethod",
+ "nsds5replicabusywaittime",
+ "nsds5replicachangecount",
+ "nsds5replicachangessentsincestartup",
+ "nsds5replicacredentials",
+ "nsds5replicahost",
+ "nsds5replicaid",
+ "nsds5replicalastinitend",
+ "nsds5replicalastinitstart",
+ "nsds5replicalastinitstatus",
+ "nsds5replicalastupdateend",
+ "nsds5replicalastupdatestart",
+ "nsds5replicalastupdatestatus",
+ "nsds5replicalegacyconsumer",
+ "nsds5replicaname",
+ "nsds5replicaport",
+ "nsds5replicapurgedelay",
+ "nsds5replicareferral",
+ "nsds5replicaroot",
+ "nsds5replicasessionpausetime",
+ "nsds5replicatedattributelist",
+ "nsds5replicatimeout",
+ "nsds5replicatombstonepurgeinterval",
+ "nsds5replicatransportinfo",
+ "nsds5replicatype",
+ "nsds5replicaupdateinprogress",
+ "nsds5replicaupdateschedule",
+ "nsds5task",
+ "nsds7directoryreplicasubtree",
+ "nsds7dirsynccookie",
+ "nsds7newwingroupsyncenabled",
+ "nsds7newwinusersyncenabled",
+ "nsds7windowsdomain",
+ "nsds7windowsreplicasubtree",
+ "nsecrecord",
+ "nsencryptionalgorithm",
+ "nserrorlog",
+ "nsexecref",
+ "nsexpirationdate",
+ "nsgrouprdncomponent",
+ "nshardwareplatform",
+ "nshelpref",
+ "nshostlocation",
+ "nsidletimeout",
+ "nsindextype",
+ "nsinstalledlocation",
+ "nsjarfilename",
+ "nskeyfile",
+ "nsldapschemaversion",
+ "nslicensedfor",
+ "nslicenseendtime",
+ "nslicensestarttime",
+ "nslogsuppress",
+ "nslookthroughlimit",
+ "nsmatchingrule",
+ "nsmsgdisallowaccess",
+ "nsmsgnummsgquota",
+ "nsnickname",
+ "nsnyr",
+ "nsosversion",
+ "nsparentuniqueid",
+ "nspidlog",
+ "nspreference",
+ "nsproductname",
+ "nsproductversion",
+ "nsrecord",
+ "nsrevisionnumber",
+ "nsrole",
+ "nsroledn",
+ "nsrolefilter",
+ "nsruvreplicalastmodified",
+ "nssaslmapbasedntemplate",
+ "nssaslmapfiltertemplate",
+ "nssaslmapregexstring",
+ "nsschemacsn",
+ "nssecureserverport",
+ "nsserialnumber",
+ "nsserveraddress",
+ "nsservercreationclassname",
+ "nsserverid",
+ "nsservermigrationclassname",
+ "nsserverport",
+ "nsserversecurity",
+ "nssizelimit",
+ "nsslapd-changelogsuffix",
+ "nsslapd-ldapiautodnsuffix",
+ "nsslapd-parent-suffix",
+ "nsslapd-plugindescription",
+ "nsslapd-pluginenabled",
+ "nsslapd-pluginid",
+ "nsslapd-plugininitfunc",
+ "nsslapd-pluginpath",
+ "nsslapd-plugintype",
+ "nsslapd-pluginvendor",
+ "nsslapd-pluginversion",
+ "nsslapd-suffix",
+ "nssnmpcontact",
+ "nssnmpdescription",
+ "nssnmpenabled",
+ "nssnmplocation",
+ "nssnmpmasterhost",
+ "nssnmpmasterport",
+ "nssnmpname",
+ "nssnmporganization",
+ "nsssl2",
+ "nsssl2ciphers",
+ "nsssl3",
+ "nsssl3ciphers",
+ "nsssl3sessiontimeout",
+ "nssslactivation",
+ "nssslclientauth",
+ "nssslpersonalityssl",
+ "nssslsessiontimeout",
+ "nssslsupportedciphers",
+ "nsssltoken",
+ "nsstate",
+ "nssuitespotuser",
+ "nssymmetrickey",
+ "nssynchuniqueattribute",
+ "nssynchuseridformat",
+ "nssystemindex",
+ "nstasklabel",
+ "nstimelimit",
+ "nsuniqueattribute",
+ "nsuniqueid",
+ "nsuseridformat",
+ "nsuserrdncomponent",
+ "nsvaluebin",
+ "nsvalueces",
+ "nsvaluecis",
+ "nsvaluedefault",
+ "nsvaluedescription",
+ "nsvaluedn",
+ "nsvalueflags",
+ "nsvaluehelpurl",
+ "nsvalueint",
+ "nsvaluesyntax",
+ "nsvaluetel",
+ "nsvaluetype",
+ "nsvendor",
+ "nsviewconfiguration",
+ "nsviewfilter",
+ "nswellknownjarfiles",
+ "nswmextendeduserprefs",
+ "ntgroupattributes",
+ "ntgroupcreatenewgroup",
+ "ntgroupdeletegroup",
+ "ntgroupdomainid",
+ "ntgroupid",
+ "ntgrouptype",
+ "ntuniqueid",
+ "ntuseracctexpires",
+ "ntuserauthflags",
+ "ntuserbadpwcount",
+ "ntusercodepage",
+ "ntusercomment",
+ "ntusercountrycode",
+ "ntusercreatenewaccount",
+ "ntuserdeleteaccount",
+ "ntuserdomainid",
+ "ntuserflags",
+ "ntuserhomedir",
+ "ntuserhomedirdrive",
+ "ntuserlastlogoff",
+ "ntuserlastlogon",
+ "ntuserlogonhours",
+ "ntuserlogonserver",
+ "ntusermaxstorage",
+ "ntusernumlogons",
+ "ntuserparms",
+ "ntuserpasswordexpired",
+ "ntuserprimarygroupid",
+ "ntuserpriv",
+ "ntuserprofile",
+ "ntuserscriptpath",
+ "ntuseruniqueid",
+ "ntuserunitsperweek",
+ "ntuserusrcomment",
+ "ntuserworkstations",
+ "numsubordinates",
+ "nxtrecord",
+ "o",
+ "objectclass",
+ "objectclasses",
+ "objectclassmap",
+ "oid",
+ "oncrpcnumber",
+ "onewaysync",
+ "organizationalstatus",
+ "ou",
+ "owner",
+ "pager",
+ "pamexcludesuffix",
+ "pamfallback",
+ "pamidattr",
+ "pamidmapmethod",
+ "pamincludesuffix",
+ "pammissingsuffix",
+ "pamsecure",
+ "pamservice",
+ "parentid",
+ "parentorganization",
+ "passwordallowchangetime",
+ "passwordchange",
+ "passwordchecksyntax",
+ "passwordexp",
+ "passwordexpirationtime",
+ "passwordexpwarned",
+ "passwordgracelimit",
+ "passwordgraceusertime",
+ "passwordhistory",
+ "passwordinhistory",
+ "passwordkeephistory",
+ "passwordlockout",
+ "passwordlockoutduration",
+ "passwordmaxage",
+ "passwordmaxfailure",
+ "passwordmaxrepeats",
+ "passwordmin8bit",
+ "passwordminage",
+ "passwordminalphas",
+ "passwordmincategories",
+ "passwordmindigits",
+ "passwordminlength",
+ "passwordminlowers",
+ "passwordminspecials",
+ "passwordmintokenlength",
+ "passwordminuppers",
+ "passwordmustchange",
+ "passwordresetduration",
+ "passwordresetfailurecount",
+ "passwordretrycount",
+ "passwordstoragescheme",
+ "passwordunlock",
+ "passwordwarning",
+ "personaltitle",
+ "photo",
+ "physicaldeliveryofficename",
+ "postaladdress",
+ "postalcode",
+ "postofficebox",
+ "preferreddeliverymethod",
+ "preferredlanguage",
+ "preferredlocale",
+ "preferredserverlist",
+ "preferredtimezone",
+ "printer-aliases",
+ "printer-charset-configured",
+ "printer-charset-supported",
+ "printer-color-supported",
+ "printer-compression-supported",
+ "printer-copies-supported",
+ "printer-current-operator",
+ "printer-delivery-orientation-supported",
+ "printer-document-format-supported",
+ "printer-finishings-supported",
+ "printer-generated-natural-language-supported",
+ "printer-info",
+ "printer-ipp-versions-supported",
+ "printer-job-k-octets-supported",
+ "printer-job-priority-supported",
+ "printer-location",
+ "printer-make-and-model",
+ "printer-media-local-supported",
+ "printer-media-supported",
+ "printer-more-info",
+ "printer-multiple-document-jobs-supported",
+ "printer-name",
+ "printer-natural-language-configured",
+ "printer-number-up-supported",
+ "printer-output-features-supported",
+ "printer-pages-per-minute",
+ "printer-pages-per-minute-color",
+ "printer-print-quality-supported",
+ "printer-resolution-supported",
+ "printer-service-person",
+ "printer-sides-supported",
+ "printer-stacking-order-supported",
+ "printer-uri",
+ "printer-xri-supported",
+ "profilettl",
+ "ptrrecord",
+ "pwdpolicysubentry",
+ "ref",
+ "registeredaddress",
+ "replicaabandonedchanges",
+ "replicabeginorc",
+ "replicabinddn",
+ "replicabindmethod",
+ "replicacfupdated",
+ "replicacredentials",
+ "replicaentryfilter",
+ "replicahost",
+ "replicalastrelevantchange",
+ "replicanickname",
+ "replicaport",
+ "replicaroot",
+ "replicatedattributelist",
+ "replicaupdatefailedat",
+ "replicaupdatereplayed",
+ "replicaupdateschedule",
+ "replicausessl",
+ "retrycountresettime",
+ "roleoccupant",
+ "roomnumber",
+ "rrsigrecord",
+ "sabayonprofilename",
+ "sabayonprofileurl",
+ "sambaacctflags",
+ "sambaalgorithmicridbase",
+ "sambabadpasswordcount",
+ "sambabadpasswordtime",
+ "sambabooloption",
+ "sambadomainname",
+ "sambaforcelogoff",
+ "sambagrouptype",
+ "sambahomedrive",
+ "sambahomepath",
+ "sambaintegeroption",
+ "sambakickofftime",
+ "sambalmpassword",
+ "sambalockoutduration",
+ "sambalockoutobservationwindow",
+ "sambalockoutthreshold",
+ "sambalogofftime",
+ "sambalogonhours",
+ "sambalogonscript",
+ "sambalogontime",
+ "sambalogontochgpwd",
+ "sambamaxpwdage",
+ "sambaminpwdage",
+ "sambaminpwdlength",
+ "sambamungeddial",
+ "sambanextgrouprid",
+ "sambanextrid",
+ "sambanextuserrid",
+ "sambantpassword",
+ "sambaoptionname",
+ "sambapasswordhistory",
+ "sambaprimarygroupsid",
+ "sambaprofilepath",
+ "sambapwdcanchange",
+ "sambapwdhistorylength",
+ "sambapwdlastset",
+ "sambapwdmustchange",
+ "sambarefusemachinepwdchange",
+ "sambasharename",
+ "sambasid",
+ "sambasidlist",
+ "sambastringlistoption",
+ "sambastringoption",
+ "sambatrustflags",
+ "sambauserworkstations",
+ "searchguide",
+ "searchtimelimit",
+ "secretary",
+ "seealso",
+ "serialnumber",
+ "serverhostname",
+ "serverproductname",
+ "serverroot",
+ "serverversionnumber",
+ "serviceauthenticationmethod",
+ "servicecategory",
+ "servicecredentiallevel",
+ "servicesearchdescriptor",
+ "shadowexpire",
+ "shadowflag",
+ "shadowinactive",
+ "shadowlastchange",
+ "shadowmax",
+ "shadowmin",
+ "shadowwarning",
+ "sigrecord",
+ "sn",
+ "sourcehost",
+ "sourcehostcategory",
+ "srvrecord",
+ "sshfprecord",
+ "st",
+ "street",
+ "structuralobjectclass",
+ "subschemasubentry",
+ "subtreeaci",
+ "sudocmd",
+ "sudocommand",
+ "sudohost",
+ "sudooption",
+ "sudorunas",
+ "sudouser",
+ "supportedalgorithms",
+ "supportedcontrol",
+ "supportedextension",
+ "supportedfeatures",
+ "supportedldapversion",
+ "supportedsaslmechanisms",
+ "targetdn",
+ "telephonenumber",
+ "teletexterminalidentifier",
+ "telexnumber",
+ "title",
+ "trustmodel",
+ "ttl",
+ "txtrecord",
+ "uid",
+ "uidnumber",
+ "uniqueidentifier",
+ "uniquemember",
+ "usercategory",
+ "usercertificate",
+ "userclass",
+ "userpassword",
+ "userpkcs12",
+ "usersmimecertificate",
+ "vacationenddate",
+ "vacationstartdate",
+ "vendorname",
+ "vendorversion",
+ "vlvbase",
+ "vlvenabled",
+ "vlvfilter",
+ "vlvscope",
+ "vlvsort",
+ "vlvuses",
+ "winsyncinterval",
+ "x121address",
+ "x500uniqueidentifier"
+ ],
+ "attribute_members": {},
+ "bindable": false,
+ "container_dn": "cn=costemplates,cn=accounts",
+ "default_attributes": [
+ "cn",
+ "cospriority",
+ "krbpwdpolicyreference"
+ ],
+ "hidden_attributes": [
+ "objectclass",
+ "aci"
+ ],
+ "label": "Entry",
+ "methods": [
+ "add",
+ "del",
+ "find",
+ "mod",
+ "show"
+ ],
+ "name": "cosentry",
+ "object_class": [
+ "top",
+ "costemplate",
+ "extensibleobject",
+ "krbcontainer"
+ ],
+ "object_class_config": null,
+ "object_name": "entry",
+ "object_name_plural": "entries",
+ "parent_object": "",
+ "primary_key": "cn",
+ "rdn_attribute": "",
+ "relationships": {
+ "member": [
+ "Member",
+ "",
+ "no_"
+ ],
+ "memberindirect": [
+ "Indirect Member",
+ null,
+ "no_indirect_"
+ ],
+ "memberof": [
+ "Member Of",
+ "in_",
+ "not_in_"
+ ]
+ },
+ "takes_params": [
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "cn",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "<cn>",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "<cn>",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "cn",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": true,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "krbpwdpolicyreference",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "<krbpwdpolicyreference>",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "<krbpwdpolicyreference>",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "krbpwdpolicyreference",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Int",
+ "cli_name": "cospriority",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "<cospriority>",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "<cospriority>",
+ "maxvalue": null,
+ "minvalue": 0,
+ "multivalue": false,
+ "name": "cospriority",
+ "primary_key": false,
+ "query": false,
+ "required": true,
+ "type": "int"
+ }
+ ],
+ "uuid_attribute": ""
+ },
+ "delegation": {
+ "bindable": false,
+ "label": "Delegation",
+ "methods": [
+ "add",
+ "del",
+ "find",
+ "mod",
+ "show"
+ ],
+ "name": "delegation",
+ "object_name": [
+ "delegation"
+ ],
+ "object_name_plural": [
+ "delegation"
+ ],
+ "primary_key": "aciname",
+ "takes_params": [
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "name",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Delegation name",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Delegation name",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "aciname",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": true,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "List",
+ "cli_name": "permissions",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Comma-separated list of permissions to grant (read, write). Default is write.",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Permissions",
+ "multivalue": true,
+ "name": "permissions",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "separator": ",",
+ "skipspace": true,
+ "type": "tuple"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "List",
+ "cli_name": "attrs",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Comma-separated list of attributes",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Attributes",
+ "multivalue": true,
+ "name": "attrs",
+ "primary_key": false,
+ "query": false,
+ "required": true,
+ "separator": ",",
+ "skipspace": true,
+ "type": "tuple"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "membergroup",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "User group to apply delegation to",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Member user group",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "memberof",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "group",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "User group ACI grants access to",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "User group",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "group",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ }
+ ]
+ },
+ "dns": {
+ "default_attributes": [
+ "idnsname",
+ "idnszoneactive",
+ "idnssoamname",
+ "idnssoarname",
+ "idnssoaserial",
+ "idnssoarefresh",
+ "idnssoaretry",
+ "idnssoaexpire",
+ "idnssoaminimum"
+ ],
+ "label": "DNS",
+ "methods": [
+ "add",
+ "del",
+ "find",
+ "mod",
+ "show"
+ ],
+ "name": "dns",
+ "primary_key": "idnsname",
+ "takes_params": [
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "name",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Zone name (FQDN)",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Zone",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "idnsname",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": true,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "name_server",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Authoritative name server",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Authoritative name server",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "idnssoamname",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "admin_email",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "administrator e-mail address",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "administrator e-mail address",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "idnssoarname",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Int",
+ "cli_name": "serial",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "SOA serial",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "SOA serial",
+ "maxvalue": null,
+ "minvalue": null,
+ "multivalue": false,
+ "name": "idnssoaserial",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "int"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Int",
+ "cli_name": "refresh",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "SOA refresh",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "SOA refresh",
+ "maxvalue": null,
+ "minvalue": null,
+ "multivalue": false,
+ "name": "idnssoarefresh",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "int"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Int",
+ "cli_name": "retry",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "SOA retry",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "SOA retry",
+ "maxvalue": null,
+ "minvalue": null,
+ "multivalue": false,
+ "name": "idnssoaretry",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "int"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Int",
+ "cli_name": "expire",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "SOA expire",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "SOA expire",
+ "maxvalue": null,
+ "minvalue": null,
+ "multivalue": false,
+ "name": "idnssoaexpire",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "int"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Int",
+ "cli_name": "minimum",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "SOA minimum",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "SOA minimum",
+ "maxvalue": null,
+ "minvalue": null,
+ "multivalue": false,
+ "name": "idnssoaminimum",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "int"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Int",
+ "cli_name": "ttl",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "SOA time to live",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "SOA time to live",
+ "maxvalue": null,
+ "minvalue": null,
+ "multivalue": false,
+ "name": "dnsttl",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "int"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "StrEnum",
+ "cli_name": "class",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "SOA class",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "SOA class",
+ "multivalue": false,
+ "name": "dnsclass",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode",
+ "values": [
+ "IN",
+ "CS",
+ "CH",
+ "HS"
+ ]
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": true,
+ "class": "Flag",
+ "cli_name": "allow_dynupdate",
+ "cli_short_name": null,
+ "default": false,
+ "doc": "allow dynamic update?",
+ "exclude": null,
+ "falsehoods": [
+ 0,
+ "0",
+ "false"
+ ],
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "allow dynamic update?",
+ "multivalue": false,
+ "name": "idnsallowdynupdate",
+ "primary_key": false,
+ "query": false,
+ "required": true,
+ "truths": [
+ "1",
+ 1,
+ "true"
+ ],
+ "type": "bool"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "update_policy",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "BIND update policy",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "BIND update policy",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "idnsupdatepolicy",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ }
+ ]
+ },
+ "dnsrecord": {
+ "aciattrs": [
+ "a6record",
+ "aaaarecord",
+ "afsdbrecord",
+ "arecord",
+ "certrecord",
+ "cn",
+ "cnamerecord",
+ "dnamerecord",
+ "dnsclass",
+ "dnsttl",
+ "dsrecord",
+ "hinforecord",
+ "idnsallowdynupdate",
+ "idnsname",
+ "keyrecord",
+ "kxrecord",
+ "locrecord",
+ "mdrecord",
+ "minforecord",
+ "mxrecord",
+ "naptrrecord",
+ "nsecrecord",
+ "nsrecord",
+ "nxtrecord",
+ "objectclass",
+ "ptrrecord",
+ "rrsigrecord",
+ "sigrecord",
+ "srvrecord",
+ "sshfprecord",
+ "txtrecord"
+ ],
+ "attribute_members": {},
+ "bindable": false,
+ "container_dn": "cn=dns",
+ "default_attributes": [
+ "arecord",
+ "aaaarecord",
+ "a6record",
+ "afsdbrecord",
+ "aplrecord",
+ "certrecord",
+ "cnamerecord",
+ "dhcidrecord",
+ "dlvrecord",
+ "dnamerecord",
+ "dnskeyrecord",
+ "dsrecord",
+ "hinforecord",
+ "hiprecord",
+ "ipseckeyrecord",
+ "keyrecord",
+ "kxrecord",
+ "locrecord",
+ "mdrecord",
+ "minforecord",
+ "mxrecord",
+ "naptrrecord",
+ "nsrecord",
+ "nsecrecord",
+ "nsec3record",
+ "nsec3paramrecord",
+ "nxtrecord",
+ "ptrrecord",
+ "rrsigrecord",
+ "rprecord",
+ "sigrecord",
+ "spfrecord",
+ "srvrecord",
+ "sshfprecord",
+ "tarecord",
+ "tkeyrecord",
+ "tsigrecord",
+ "txtrecord",
+ "idnsname"
+ ],
+ "hidden_attributes": [
+ "objectclass",
+ "aci"
+ ],
+ "label": "DNS resource record",
+ "methods": [
+ "add",
+ "add_record",
+ "del",
+ "delentry",
+ "find",
+ "show"
+ ],
+ "name": "dnsrecord",
+ "object_class": [
+ "top",
+ "idnsrecord"
+ ],
+ "object_class_config": null,
+ "object_name": "DNS resource record",
+ "object_name_plural": "DNS resource records",
+ "parent_object": "dnszone",
+ "primary_key": "idnsname",
+ "rdn_attribute": "",
+ "relationships": {
+ "member": [
+ "Member",
+ "",
+ "no_"
+ ],
+ "memberindirect": [
+ "Indirect Member",
+ null,
+ "no_indirect_"
+ ],
+ "memberof": [
+ "Member Of",
+ "in_",
+ "not_in_"
+ ]
+ },
+ "takes_params": [
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "name",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Record name",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Record name",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "idnsname",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": true,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Int",
+ "cli_name": "ttl",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Time to live",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Time to live",
+ "maxvalue": null,
+ "minvalue": null,
+ "multivalue": false,
+ "name": "dnsttl",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "int"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "StrEnum",
+ "cli_name": "class",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "DNS class",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Class",
+ "multivalue": false,
+ "name": "dnsclass",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode",
+ "values": [
+ "IN",
+ "CS",
+ "CH",
+ "HS"
+ ]
+ }
+ ],
+ "uuid_attribute": ""
+ },
+ "dnszone": {
+ "aciattrs": [
+ "a6record",
+ "aaaarecord",
+ "afsdbrecord",
+ "arecord",
+ "certrecord",
+ "cn",
+ "cnamerecord",
+ "dnamerecord",
+ "dnsclass",
+ "dnsttl",
+ "dsrecord",
+ "hinforecord",
+ "idnsallowdynupdate",
+ "idnsname",
+ "idnssoaexpire",
+ "idnssoaminimum",
+ "idnssoamname",
+ "idnssoarefresh",
+ "idnssoaretry",
+ "idnssoarname",
+ "idnssoaserial",
+ "idnsupdatepolicy",
+ "idnszoneactive",
+ "keyrecord",
+ "kxrecord",
+ "locrecord",
+ "mdrecord",
+ "minforecord",
+ "mxrecord",
+ "naptrrecord",
+ "nsecrecord",
+ "nsrecord",
+ "nxtrecord",
+ "objectclass",
+ "ptrrecord",
+ "rrsigrecord",
+ "sigrecord",
+ "srvrecord",
+ "sshfprecord",
+ "txtrecord"
+ ],
+ "attribute_members": {},
+ "bindable": false,
+ "container_dn": "cn=dns",
+ "default_attributes": [
+ "idnsname",
+ "idnszoneactive",
+ "idnssoamname",
+ "idnssoarname",
+ "idnssoaserial",
+ "idnssoarefresh",
+ "idnssoaretry",
+ "idnssoaexpire",
+ "idnssoaminimum",
+ "arecord",
+ "aaaarecord",
+ "a6record",
+ "afsdbrecord",
+ "aplrecord",
+ "certrecord",
+ "cnamerecord",
+ "dhcidrecord",
+ "dlvrecord",
+ "dnamerecord",
+ "dnskeyrecord",
+ "dsrecord",
+ "hinforecord",
+ "hiprecord",
+ "ipseckeyrecord",
+ "keyrecord",
+ "kxrecord",
+ "locrecord",
+ "mdrecord",
+ "minforecord",
+ "mxrecord",
+ "naptrrecord",
+ "nsrecord",
+ "nsecrecord",
+ "nsec3record",
+ "nsec3paramrecord",
+ "nxtrecord",
+ "ptrrecord",
+ "rrsigrecord",
+ "rprecord",
+ "sigrecord",
+ "spfrecord",
+ "srvrecord",
+ "sshfprecord",
+ "tarecord",
+ "tkeyrecord",
+ "tsigrecord",
+ "txtrecord"
+ ],
+ "hidden_attributes": [
+ "objectclass",
+ "aci"
+ ],
+ "label": "DNS",
+ "methods": [
+ "add",
+ "del",
+ "disable",
+ "enable",
+ "find",
+ "mod",
+ "show"
+ ],
+ "name": "dnszone",
+ "object_class": [
+ "top",
+ "idnsrecord",
+ "idnszone"
+ ],
+ "object_class_config": null,
+ "object_name": "DNS zone",
+ "object_name_plural": "DNS zones",
+ "parent_object": "",
+ "primary_key": "idnsname",
+ "rdn_attribute": "",
+ "relationships": {
+ "member": [
+ "Member",
+ "",
+ "no_"
+ ],
+ "memberindirect": [
+ "Indirect Member",
+ null,
+ "no_indirect_"
+ ],
+ "memberof": [
+ "Member Of",
+ "in_",
+ "not_in_"
+ ]
+ },
+ "takes_params": [
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "name",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Zone name (FQDN)",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Zone name",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "idnsname",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": true,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "name_server",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Authoritative name server",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Authoritative name server",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "idnssoamname",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "admin_email",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Administrator e-mail address",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Administrator e-mail address",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "idnssoarname",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": true,
+ "class": "Int",
+ "cli_name": "serial",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "SOA record serial number",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "SOA serial",
+ "maxvalue": null,
+ "minvalue": null,
+ "multivalue": false,
+ "name": "idnssoaserial",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "int"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": true,
+ "class": "Int",
+ "cli_name": "refresh",
+ "cli_short_name": null,
+ "default": 3600,
+ "doc": "SOA record refresh time",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "SOA refresh",
+ "maxvalue": null,
+ "minvalue": null,
+ "multivalue": false,
+ "name": "idnssoarefresh",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "int"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": true,
+ "class": "Int",
+ "cli_name": "retry",
+ "cli_short_name": null,
+ "default": 900,
+ "doc": "SOA record retry time",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "SOA retry",
+ "maxvalue": null,
+ "minvalue": null,
+ "multivalue": false,
+ "name": "idnssoaretry",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "int"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": true,
+ "class": "Int",
+ "cli_name": "expire",
+ "cli_short_name": null,
+ "default": 1209600,
+ "doc": "SOA record expire time",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "SOA expire",
+ "maxvalue": null,
+ "minvalue": null,
+ "multivalue": false,
+ "name": "idnssoaexpire",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "int"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": true,
+ "class": "Int",
+ "cli_name": "minimum",
+ "cli_short_name": null,
+ "default": 3600,
+ "doc": "SOA record minimum value",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "SOA minimum",
+ "maxvalue": null,
+ "minvalue": null,
+ "multivalue": false,
+ "name": "idnssoaminimum",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "int"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Int",
+ "cli_name": "maximum",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "SOA record maximum value",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "SOA maximum",
+ "maxvalue": null,
+ "minvalue": null,
+ "multivalue": false,
+ "name": "idnssoamaximum",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "int"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Int",
+ "cli_name": "ttl",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "SOA record time to live",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "SOA time to live",
+ "maxvalue": null,
+ "minvalue": null,
+ "multivalue": false,
+ "name": "dnsttl",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "int"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "StrEnum",
+ "cli_name": "class",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "SOA record class",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "SOA class",
+ "multivalue": false,
+ "name": "dnsclass",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode",
+ "values": [
+ "IN",
+ "CS",
+ "CH",
+ "HS"
+ ]
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "update_policy",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "BIND update policy",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "BIND update policy",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "idnsupdatepolicy",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": true,
+ "autofill": true,
+ "class": "Flag",
+ "cli_name": "zone_active",
+ "cli_short_name": null,
+ "default": false,
+ "doc": "Is zone active?",
+ "exclude": null,
+ "falsehoods": [
+ 0,
+ "0",
+ "false"
+ ],
+ "flags": [
+ "no_update",
+ "no_create"
+ ],
+ "hint": null,
+ "include": null,
+ "label": "Active zone",
+ "multivalue": false,
+ "name": "idnszoneactive",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "truths": [
+ "1",
+ 1,
+ "true"
+ ],
+ "type": "bool"
+ },
+ {
+ "alwaysask": false,
+ "attribute": true,
+ "autofill": true,
+ "class": "Flag",
+ "cli_name": "allow_dynupdate",
+ "cli_short_name": null,
+ "default": false,
+ "doc": "Allow dynamic update?",
+ "exclude": null,
+ "falsehoods": [
+ 0,
+ "0",
+ "false"
+ ],
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Dynamic update",
+ "multivalue": false,
+ "name": "idnsallowdynupdate",
+ "primary_key": false,
+ "query": false,
+ "required": true,
+ "truths": [
+ "1",
+ 1,
+ "true"
+ ],
+ "type": "bool"
+ }
+ ],
+ "uuid_attribute": ""
+ },
+ "group": {
+ "aciattrs": [
+ "businesscategory",
+ "cn",
+ "description",
+ "gidnumber",
+ "ipauniqueid",
+ "member",
+ "memberof",
+ "memberuid",
+ "mepmanagedby",
+ "o",
+ "objectclass",
+ "ou",
+ "owner",
+ "seealso",
+ "userpassword"
+ ],
+ "attribute_members": {
+ "member": [
+ "user",
+ "group"
+ ],
+ "memberindirect": [
+ "user",
+ "group",
+ "netgroup",
+ "role"
+ ],
+ "memberof": [
+ "group",
+ "netgroup",
+ "role"
+ ]
+ },
+ "bindable": false,
+ "container_dn": "cn=groups,cn=accounts",
+ "default_attributes": [
+ "cn",
+ "description",
+ "gidnumber",
+ "member",
+ "memberof",
+ "memberindirect"
+ ],
+ "hidden_attributes": [
+ "objectclass",
+ "aci"
+ ],
+ "label": "User Groups",
+ "methods": [
+ "add",
+ "add_member",
+ "del",
+ "detach",
+ "find",
+ "mod",
+ "remove_member",
+ "show"
+ ],
+ "name": "group",
+ "object_class": [
+ "ipausergroup"
+ ],
+ "object_class_config": "ipagroupobjectclasses",
+ "object_name": "group",
+ "object_name_plural": "groups",
+ "parent_object": "",
+ "primary_key": "cn",
+ "rdn_attribute": "",
+ "relationships": {
+ "member": [
+ "Member",
+ "",
+ "no_"
+ ],
+ "memberindirect": [
+ "Indirect Member",
+ null,
+ "no_indirect_"
+ ],
+ "memberof": [
+ "Member Of",
+ "in_",
+ "not_in_"
+ ]
+ },
+ "takes_params": [
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "group_name",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Group name",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Group name",
+ "length": null,
+ "maxlength": 255,
+ "minlength": null,
+ "multivalue": false,
+ "name": "cn",
+ "pattern": "^[a-zA-Z0-9_.][a-zA-Z0-9_.-]{0,252}[a-zA-Z0-9_.$-]?$",
+ "pattern_errmsg": "may only include letters, numbers, _, -, . and $",
+ "primary_key": true,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "desc",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Group description",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Description",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "description",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Int",
+ "cli_name": "gid",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "GID (use this option to set it manually)",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "GID",
+ "maxvalue": null,
+ "minvalue": null,
+ "multivalue": false,
+ "name": "gidnumber",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "int"
+ }
+ ],
+ "uuid_attribute": "ipauniqueid"
+ },
+ "hbacrule": {
+ "aciattrs": [
+ "accessruletype",
+ "accesstime",
+ "cn",
+ "description",
+ "externalhost",
+ "hostcategory",
+ "ipaenabledflag",
+ "ipauniqueid",
+ "memberhost",
+ "memberservice",
+ "memberuser",
+ "servicecategory",
+ "sourcehost",
+ "sourcehostcategory",
+ "usercategory"
+ ],
+ "attribute_members": {
+ "memberhost": [
+ "host",
+ "hostgroup"
+ ],
+ "memberservice": [
+ "hbacsvc",
+ "hbacsvcgroup"
+ ],
+ "memberuser": [
+ "user",
+ "group"
+ ],
+ "sourcehost": [
+ "host",
+ "hostgroup"
+ ]
+ },
+ "bindable": false,
+ "container_dn": "cn=hbac",
+ "default_attributes": [
+ "cn",
+ "accessruletype",
+ "ipaenabledflag",
+ "description",
+ "usercategory",
+ "hostcategory",
+ "sourcehostcategory",
+ "servicecategory",
+ "ipaenabledflag",
+ "memberuser",
+ "sourcehost",
+ "memberhost",
+ "memberservice",
+ "memberhostgroup"
+ ],
+ "hidden_attributes": [
+ "objectclass",
+ "aci"
+ ],
+ "label": "HBAC",
+ "methods": [
+ "add",
+ "add_host",
+ "add_service",
+ "add_sourcehost",
+ "add_user",
+ "del",
+ "disable",
+ "enable",
+ "find",
+ "mod",
+ "remove_host",
+ "remove_service",
+ "remove_sourcehost",
+ "remove_user",
+ "show"
+ ],
+ "name": "hbacrule",
+ "object_class": [
+ "ipaassociation",
+ "ipahbacrule"
+ ],
+ "object_class_config": null,
+ "object_name": "HBAC rule",
+ "object_name_plural": "HBAC rules",
+ "parent_object": "",
+ "primary_key": "cn",
+ "rdn_attribute": "ipauniqueid",
+ "relationships": {
+ "member": [
+ "Member",
+ "",
+ "no_"
+ ],
+ "memberindirect": [
+ "Indirect Member",
+ null,
+ "no_indirect_"
+ ],
+ "memberof": [
+ "Member Of",
+ "in_",
+ "not_in_"
+ ]
+ },
+ "takes_params": [
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "name",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Rule name",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Rule name",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "cn",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": true,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "StrEnum",
+ "cli_name": "type",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Rule type (allow or deny)",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Rule type",
+ "multivalue": false,
+ "name": "accessruletype",
+ "primary_key": false,
+ "query": false,
+ "required": true,
+ "type": "unicode",
+ "values": [
+ "allow",
+ "deny"
+ ]
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "StrEnum",
+ "cli_name": "usercat",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "User category the rule applies to",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "User category",
+ "multivalue": false,
+ "name": "usercategory",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode",
+ "values": [
+ "all"
+ ]
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "StrEnum",
+ "cli_name": "hostcat",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Host category the rule applies to",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Host category",
+ "multivalue": false,
+ "name": "hostcategory",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode",
+ "values": [
+ "all"
+ ]
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "StrEnum",
+ "cli_name": "srchostcat",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Source host category the rule applies to",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Source host category",
+ "multivalue": false,
+ "name": "sourcehostcategory",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode",
+ "values": [
+ "all"
+ ]
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "StrEnum",
+ "cli_name": "servicecat",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Service category the rule applies to",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Service category",
+ "multivalue": false,
+ "name": "servicecategory",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode",
+ "values": [
+ "all"
+ ]
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "desc",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Description",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Description",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "description",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": true,
+ "class": "Flag",
+ "cli_name": "ipaenabledflag",
+ "cli_short_name": null,
+ "default": false,
+ "doc": "Enabled",
+ "exclude": null,
+ "falsehoods": [
+ 0,
+ "0",
+ "false"
+ ],
+ "flags": [
+ "no_update",
+ "no_create",
+ "no_search"
+ ],
+ "hint": null,
+ "include": null,
+ "label": "Enabled",
+ "multivalue": false,
+ "name": "ipaenabledflag",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "truths": [
+ "1",
+ 1,
+ "true"
+ ],
+ "type": "bool"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "memberuser_user",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Users",
+ "exclude": null,
+ "flags": [
+ "no_update",
+ "no_create",
+ "no_search"
+ ],
+ "hint": null,
+ "include": null,
+ "label": "Users",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "memberuser_user",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "memberuser_group",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Groups",
+ "exclude": null,
+ "flags": [
+ "no_update",
+ "no_create",
+ "no_search"
+ ],
+ "hint": null,
+ "include": null,
+ "label": "Groups",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "memberuser_group",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "memberhost_host",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Hosts",
+ "exclude": null,
+ "flags": [
+ "no_update",
+ "no_create",
+ "no_search"
+ ],
+ "hint": null,
+ "include": null,
+ "label": "Hosts",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "memberhost_host",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "memberhost_hostgroup",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Host Groups",
+ "exclude": null,
+ "flags": [
+ "no_update",
+ "no_create",
+ "no_search"
+ ],
+ "hint": null,
+ "include": null,
+ "label": "Host Groups",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "memberhost_hostgroup",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "sourcehost_host",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Source hosts",
+ "exclude": null,
+ "flags": [
+ "no_update",
+ "no_create",
+ "no_search"
+ ],
+ "hint": null,
+ "include": null,
+ "label": "Source hosts",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "sourcehost_host",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "memberservice_hbacsvc",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Services",
+ "exclude": null,
+ "flags": [
+ "no_update",
+ "no_create",
+ "no_search"
+ ],
+ "hint": null,
+ "include": null,
+ "label": "Services",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "memberservice_hbacsvc",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "memberservice_hbacsvcgroup",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Service Groups",
+ "exclude": null,
+ "flags": [
+ "no_update",
+ "no_create",
+ "no_search"
+ ],
+ "hint": null,
+ "include": null,
+ "label": "Service Groups",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "memberservice_hbacsvcgroup",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ }
+ ],
+ "uuid_attribute": "ipauniqueid"
+ },
+ "hbacsvc": {
+ "aciattrs": [
+ "cn",
+ "description",
+ "ipauniqueid",
+ "memberof",
+ "objectclass"
+ ],
+ "attribute_members": {},
+ "bindable": false,
+ "container_dn": "cn=hbacservices,cn=hbac",
+ "default_attributes": [
+ "cn",
+ "description",
+ "memberindirect"
+ ],
+ "hidden_attributes": [
+ "objectclass",
+ "aci"
+ ],
+ "label": "HBAC Services",
+ "methods": [
+ "add",
+ "del",
+ "find",
+ "mod",
+ "show"
+ ],
+ "name": "hbacsvc",
+ "object_class": [
+ "ipaobject",
+ "ipahbacservice"
+ ],
+ "object_class_config": null,
+ "object_name": "hbacsvc",
+ "object_name_plural": "hbacsvcs",
+ "parent_object": "",
+ "primary_key": "cn",
+ "rdn_attribute": "",
+ "relationships": {
+ "member": [
+ "Member",
+ "",
+ "no_"
+ ],
+ "memberindirect": [
+ "Indirect Member",
+ null,
+ "no_indirect_"
+ ],
+ "memberof": [
+ "Member Of",
+ "in_",
+ "not_in_"
+ ]
+ },
+ "takes_params": [
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "service",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "HBAC Service",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Service name",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "cn",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": true,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "desc",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Description of service",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Description",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "description",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ }
+ ],
+ "uuid_attribute": "ipauniqueid"
+ },
+ "hbacsvcgroup": {
+ "aciattrs": [
+ "businesscategory",
+ "cn",
+ "description",
+ "ipauniqueid",
+ "member",
+ "o",
+ "objectclass",
+ "ou",
+ "owner",
+ "seealso"
+ ],
+ "attribute_members": {
+ "member": [
+ "hbacsvc"
+ ]
+ },
+ "bindable": false,
+ "container_dn": "cn=hbacservicegroups,cn=hbac",
+ "default_attributes": [
+ "cn",
+ "description",
+ "member"
+ ],
+ "hidden_attributes": [
+ "objectclass",
+ "aci"
+ ],
+ "label": "HBAC Service Groups",
+ "methods": [
+ "add",
+ "add_member",
+ "del",
+ "find",
+ "mod",
+ "remove_member",
+ "show"
+ ],
+ "name": "hbacsvcgroup",
+ "object_class": [
+ "ipaobject",
+ "ipahbacservicegroup"
+ ],
+ "object_class_config": null,
+ "object_name": "hbacsvcgroup",
+ "object_name_plural": "hbacsvcgroups",
+ "parent_object": "",
+ "primary_key": "cn",
+ "rdn_attribute": "",
+ "relationships": {
+ "member": [
+ "Member",
+ "",
+ "no_"
+ ],
+ "memberindirect": [
+ "Indirect Member",
+ null,
+ "no_indirect_"
+ ],
+ "memberof": [
+ "Member Of",
+ "in_",
+ "not_in_"
+ ]
+ },
+ "takes_params": [
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "name",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Service group name",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Service group name",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "cn",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": true,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "desc",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "HBAC service group description",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Description",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "description",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ }
+ ],
+ "uuid_attribute": "ipauniqueid"
+ },
+ "host": {
+ "aciattrs": [
+ "cn",
+ "description",
+ "enrolledby",
+ "fqdn",
+ "ipaclientversion",
+ "ipauniqueid",
+ "l",
+ "managedby",
+ "memberof",
+ "nshardwareplatform",
+ "nshostlocation",
+ "nsosversion",
+ "objectclass",
+ "serverhostname",
+ "usercertificate",
+ "userpassword"
+ ],
+ "attribute_members": {
+ "enrolledby": [
+ "user"
+ ],
+ "managedby": [
+ "host"
+ ],
+ "memberof": [
+ "hostgroup",
+ "netgroup",
+ "role"
+ ]
+ },
+ "bindable": true,
+ "container_dn": "cn=computers,cn=accounts",
+ "default_attributes": [
+ "fqdn",
+ "description",
+ "l",
+ "nshostlocation",
+ "krbprincipalname",
+ "nshardwareplatform",
+ "nsosversion",
+ "usercertificate",
+ "memberof",
+ "krblastpwdchange",
+ "managedby"
+ ],
+ "hidden_attributes": [
+ "objectclass",
+ "aci"
+ ],
+ "label": "Hosts",
+ "methods": [
+ "add",
+ "add_managedby",
+ "del",
+ "disable",
+ "find",
+ "mod",
+ "remove_managedby",
+ "show"
+ ],
+ "name": "host",
+ "object_class": [
+ "ipaobject",
+ "nshost",
+ "ipahost",
+ "pkiuser",
+ "ipaservice"
+ ],
+ "object_class_config": null,
+ "object_name": "host",
+ "object_name_plural": "hosts",
+ "parent_object": "",
+ "primary_key": "fqdn",
+ "rdn_attribute": "",
+ "relationships": {
+ "enrolledby": [
+ "Enrolled by",
+ "enroll_by_",
+ "not_enroll_by_"
+ ],
+ "managedby": [
+ "Managed by",
+ "man_by_",
+ "not_man_by_"
+ ],
+ "memberof": [
+ "Member Of",
+ "in_",
+ "not_in_"
+ ]
+ },
+ "takes_params": [
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "hostname",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Host name",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Host name",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "fqdn",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": true,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "desc",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "A description of this host",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Description",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "description",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "locality",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Host locality (e.g. \"Baltimore, MD\")",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Locality",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "l",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "location",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Host location (e.g. \"Lab 2\")",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Location",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "nshostlocation",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "platform",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Host hardware platform (e.g. \"Lenovo T61\")",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Platform",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "nshardwareplatform",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "os",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Host operating system and version (e.g. \"Fedora 9\")",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Operating system",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "nsosversion",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "password",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Password used in bulk enrollment",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "User password",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "userpassword",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": true,
+ "class": "Flag",
+ "cli_name": "random",
+ "cli_short_name": null,
+ "default": false,
+ "doc": "Generate a random password to be used in bulk enrollment",
+ "exclude": null,
+ "falsehoods": [
+ 0,
+ "0",
+ "false"
+ ],
+ "flags": [
+ "no_search"
+ ],
+ "hint": null,
+ "include": null,
+ "label": "<random>",
+ "multivalue": false,
+ "name": "random",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "truths": [
+ "1",
+ 1,
+ "true"
+ ],
+ "type": "bool"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "randompassword",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Random password",
+ "exclude": null,
+ "flags": [
+ "no_update",
+ "no_create",
+ "no_search"
+ ],
+ "hint": null,
+ "include": null,
+ "label": "Random password",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "randompassword",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Bytes",
+ "cli_name": "certificate",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Base-64 encoded server certificate",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Certificate",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "usercertificate",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "str"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "krbprincipalname",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Principal name",
+ "exclude": null,
+ "flags": [
+ "no_update",
+ "no_create",
+ "no_search"
+ ],
+ "hint": null,
+ "include": null,
+ "label": "Principal name",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "krbprincipalname",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ }
+ ],
+ "uuid_attribute": "ipauniqueid"
+ },
+ "hostgroup": {
+ "aciattrs": [
+ "businesscategory",
+ "cn",
+ "description",
+ "ipauniqueid",
+ "member",
+ "memberof",
+ "o",
+ "objectclass",
+ "ou",
+ "owner",
+ "seealso"
+ ],
+ "attribute_members": {
+ "member": [
+ "host",
+ "hostgroup"
+ ],
+ "memberindirect": [
+ "host",
+ "hostgroup"
+ ],
+ "memberof": [
+ "hostgroup"
+ ]
+ },
+ "bindable": false,
+ "container_dn": "cn=hostgroups,cn=accounts",
+ "default_attributes": [
+ "cn",
+ "description",
+ "member",
+ "memberof",
+ "memberindirect"
+ ],
+ "hidden_attributes": [
+ "objectclass",
+ "aci"
+ ],
+ "label": "Host Groups",
+ "methods": [
+ "add",
+ "add_member",
+ "del",
+ "find",
+ "mod",
+ "remove_member",
+ "show"
+ ],
+ "name": "hostgroup",
+ "object_class": [
+ "ipaobject",
+ "ipahostgroup"
+ ],
+ "object_class_config": null,
+ "object_name": "hostgroup",
+ "object_name_plural": "hostgroups",
+ "parent_object": "",
+ "primary_key": "cn",
+ "rdn_attribute": "",
+ "relationships": {
+ "member": [
+ "Member",
+ "",
+ "no_"
+ ],
+ "memberindirect": [
+ "Indirect Member",
+ null,
+ "no_indirect_"
+ ],
+ "memberof": [
+ "Member Of",
+ "in_",
+ "not_in_"
+ ]
+ },
+ "takes_params": [
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "hostgroup_name",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Name of host-group",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Host-group",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "cn",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": true,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "desc",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "A description of this host-group",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Description",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "description",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ }
+ ],
+ "uuid_attribute": "ipauniqueid"
+ },
+ "krbtpolicy": {
+ "aciattrs": [],
+ "attribute_members": {},
+ "bindable": false,
+ "container_dn": "cn=IPA14.AYOUNG.BOSTON.DEVEL.REDHAT.COM,cn=kerberos",
+ "default_attributes": [
+ "krbmaxticketlife",
+ "krbmaxrenewableage"
+ ],
+ "hidden_attributes": [
+ "objectclass",
+ "aci"
+ ],
+ "label": "Kerberos Ticket Policy",
+ "methods": [
+ "mod",
+ "reset",
+ "show"
+ ],
+ "name": "krbtpolicy",
+ "object_class": [],
+ "object_class_config": null,
+ "object_name": "kerberos ticket policy settings",
+ "object_name_plural": "entries",
+ "parent_object": "",
+ "primary_key": "uid",
+ "rdn_attribute": "",
+ "relationships": {
+ "member": [
+ "Member",
+ "",
+ "no_"
+ ],
+ "memberindirect": [
+ "Indirect Member",
+ null,
+ "no_indirect_"
+ ],
+ "memberof": [
+ "Member Of",
+ "in_",
+ "not_in_"
+ ]
+ },
+ "takes_params": [
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "user",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Manage ticket policy for specific user",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "User name",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "uid",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": true,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Int",
+ "cli_name": "maxlife",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Maximum ticket life (seconds)",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Max life",
+ "maxvalue": null,
+ "minvalue": null,
+ "multivalue": false,
+ "name": "krbmaxticketlife",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "int"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Int",
+ "cli_name": "maxrenew",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Maximum renewable age (seconds)",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Max renew",
+ "maxvalue": null,
+ "minvalue": null,
+ "multivalue": false,
+ "name": "krbmaxrenewableage",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "int"
+ }
+ ],
+ "uuid_attribute": ""
+ },
+ "netgroup": {
+ "aciattrs": [
+ "cn",
+ "description",
+ "externalhost",
+ "hostcategory",
+ "ipaenabledflag",
+ "ipauniqueid",
+ "member",
+ "memberhost",
+ "memberof",
+ "memberuser",
+ "nisdomainname",
+ "usercategory"
+ ],
+ "attribute_members": {
+ "member": [
+ "netgroup"
+ ],
+ "memberhost": [
+ "host",
+ "hostgroup"
+ ],
+ "memberindirect": [
+ "netgroup"
+ ],
+ "memberof": [
+ "netgroup"
+ ],
+ "memberuser": [
+ "user",
+ "group"
+ ]
+ },
+ "bindable": false,
+ "container_dn": "cn=ng,cn=alt",
+ "default_attributes": [
+ "cn",
+ "description",
+ "memberof",
+ "externalhost",
+ "nisdomainname",
+ "memberuser",
+ "memberhost",
+ "member",
+ "memberindirect",
+ "usercategory",
+ "hostcategory"
+ ],
+ "hidden_attributes": [
+ "objectclass",
+ "aci"
+ ],
+ "label": "Net Groups",
+ "methods": [
+ "add",
+ "add_member",
+ "del",
+ "find",
+ "mod",
+ "remove_member",
+ "show"
+ ],
+ "name": "netgroup",
+ "object_class": [
+ "ipaobject",
+ "ipaassociation",
+ "ipanisnetgroup"
+ ],
+ "object_class_config": null,
+ "object_name": "netgroup",
+ "object_name_plural": "netgroups",
+ "parent_object": "",
+ "primary_key": "cn",
+ "rdn_attribute": "ipauniqueid",
+ "relationships": {
+ "member": [
+ "Member",
+ "",
+ "no_"
+ ],
+ "memberhost": [
+ "Member",
+ "",
+ "no_"
+ ],
+ "memberindirect": [
+ "Indirect Member",
+ null,
+ "no_indirect_"
+ ],
+ "memberof": [
+ "Member Of",
+ "in_",
+ "not_in_"
+ ],
+ "memberuser": [
+ "Member",
+ "",
+ "no_"
+ ]
+ },
+ "takes_params": [
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "name",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Netgroup name",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Netgroup name",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "cn",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": true,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "desc",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Netgroup description",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Description",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "description",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "nisdomain",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "NIS domain name",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "NIS domain name",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "nisdomainname",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "uuid",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "IPA unique ID",
+ "exclude": null,
+ "flags": [
+ "no_update",
+ "no_create"
+ ],
+ "hint": null,
+ "include": null,
+ "label": "IPA unique ID",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "ipauniqueid",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "StrEnum",
+ "cli_name": "usercat",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "User category the rule applies to",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "User category",
+ "multivalue": false,
+ "name": "usercategory",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode",
+ "values": [
+ "all"
+ ]
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "StrEnum",
+ "cli_name": "hostcat",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Host category the rule applies to",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Host category",
+ "multivalue": false,
+ "name": "hostcategory",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode",
+ "values": [
+ "all"
+ ]
+ }
+ ],
+ "uuid_attribute": "ipauniqueid"
+ },
+ "permission": {
+ "aciattrs": [
+ "businesscategory",
+ "cn",
+ "description",
+ "member",
+ "o",
+ "objectclass",
+ "ou",
+ "owner",
+ "seealso"
+ ],
+ "attribute_members": {
+ "member": [
+ "privilege"
+ ]
+ },
+ "bindable": false,
+ "container_dn": "cn=permissions,cn=pbac",
+ "default_attributes": [
+ "cn",
+ "description",
+ "member",
+ "memberof",
+ "memberindirect"
+ ],
+ "hidden_attributes": [
+ "objectclass",
+ "aci"
+ ],
+ "label": "Permissions",
+ "methods": [
+ "add",
+ "add_member",
+ "del",
+ "find",
+ "mod",
+ "remove_member",
+ "show"
+ ],
+ "name": "permission",
+ "object_class": [
+ "groupofnames"
+ ],
+ "object_class_config": null,
+ "object_name": "permission",
+ "object_name_plural": "permissions",
+ "parent_object": "",
+ "primary_key": "cn",
+ "rdn_attribute": "",
+ "relationships": {
+ "member": [
+ "Member",
+ "",
+ "no_"
+ ],
+ "memberindirect": [
+ "Indirect Member",
+ null,
+ "no_indirect_"
+ ],
+ "memberof": [
+ "Member Of",
+ "in_",
+ "not_in_"
+ ]
+ },
+ "takes_params": [
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "name",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Permission name",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Permission name",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "cn",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": true,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "desc",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Permission description",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Description",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "description",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "List",
+ "cli_name": "permissions",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Comma-separated list of permissions to grant (read, write, add, delete, all)",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Permissions",
+ "multivalue": true,
+ "name": "permissions",
+ "primary_key": false,
+ "query": false,
+ "required": true,
+ "separator": ",",
+ "skipspace": true,
+ "type": "tuple"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "List",
+ "cli_name": "attrs",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Comma-separated list of attributes",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Attributes",
+ "multivalue": true,
+ "name": "attrs",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "separator": ",",
+ "skipspace": true,
+ "type": "tuple"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "StrEnum",
+ "cli_name": "type",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Type of IPA object (user, group, host, hostgroup, service, netgroup, dns)",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Type",
+ "multivalue": false,
+ "name": "type",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode",
+ "values": [
+ "user",
+ "group",
+ "host",
+ "service",
+ "hostgroup",
+ "netgroup",
+ "dns"
+ ]
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "memberof",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Target members of a group",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Member of group",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "memberof",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "filter",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Legal LDAP filter (e.g. ou=Engineering)",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Filter",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "filter",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "subtree",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Subtree to apply permissions to",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Subtree",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "subtree",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "targetgroup",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "User group to apply permissions to",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Target group",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "targetgroup",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ }
+ ],
+ "uuid_attribute": ""
+ },
+ "pkinit": {
+ "__base64__": ""
+ },
+ "privilege": {
+ "aciattrs": [
+ "businesscategory",
+ "cn",
+ "description",
+ "member",
+ "memberof",
+ "o",
+ "objectclass",
+ "ou",
+ "owner",
+ "seealso"
+ ],
+ "attribute_members": {
+ "member": [
+ "permission",
+ "role"
+ ],
+ "memberof": [
+ "permission"
+ ]
+ },
+ "bindable": false,
+ "container_dn": "cn=privileges,cn=pbac",
+ "default_attributes": [
+ "cn",
+ "description",
+ "member",
+ "memberof",
+ "memberindirect"
+ ],
+ "hidden_attributes": [
+ "objectclass",
+ "aci"
+ ],
+ "label": "Privileges",
+ "methods": [
+ "add",
+ "add_member",
+ "add_permission",
+ "del",
+ "find",
+ "mod",
+ "remove_member",
+ "remove_permission",
+ "show"
+ ],
+ "name": "privilege",
+ "object_class": [
+ "nestedgroup",
+ "groupofnames"
+ ],
+ "object_class_config": null,
+ "object_name": "privilege",
+ "object_name_plural": "privileges",
+ "parent_object": "",
+ "primary_key": "cn",
+ "rdn_attribute": "",
+ "relationships": {
+ "member": [
+ "Member",
+ "",
+ "no_"
+ ],
+ "memberindirect": [
+ "Indirect Member",
+ null,
+ "no_indirect_"
+ ],
+ "memberof": [
+ "Member Of",
+ "in_",
+ "not_in_"
+ ]
+ },
+ "takes_params": [
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "name",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Privilege name",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Privilege name",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "cn",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": true,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "desc",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Privilege description",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Description",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "description",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ }
+ ],
+ "uuid_attribute": ""
+ },
+ "pwpolicy": {
+ "aciattrs": [
+ "cn",
+ "krbmaxpwdlife",
+ "krbminpwdlife",
+ "krbpwdfailurecountinterval",
+ "krbpwdhistorylength",
+ "krbpwdlockoutduration",
+ "krbpwdmaxfailure",
+ "krbpwdmindiffchars",
+ "krbpwdminlength",
+ "objectclass"
+ ],
+ "attribute_members": {},
+ "bindable": false,
+ "container_dn": "cn=IPA14.AYOUNG.BOSTON.DEVEL.REDHAT.COM,cn=kerberos",
+ "default_attributes": [
+ "cn",
+ "cospriority",
+ "krbmaxpwdlife",
+ "krbminpwdlife",
+ "krbpwdhistorylength",
+ "krbpwdmindiffchars",
+ "krbpwdminlength",
+ "krbpwdmaxfailure",
+ "krbpwdfailurecountinterval",
+ "krbpwdlockoutduration"
+ ],
+ "hidden_attributes": [
+ "objectclass",
+ "aci"
+ ],
+ "label": "Password Policy",
+ "methods": [
+ "add",
+ "del",
+ "find",
+ "mod",
+ "show"
+ ],
+ "name": "pwpolicy",
+ "object_class": [
+ "top",
+ "nscontainer",
+ "krbpwdpolicy"
+ ],
+ "object_class_config": null,
+ "object_name": "password policy",
+ "object_name_plural": "password policies",
+ "parent_object": "",
+ "primary_key": "cn",
+ "rdn_attribute": "",
+ "relationships": {
+ "member": [
+ "Member",
+ "",
+ "no_"
+ ],
+ "memberindirect": [
+ "Indirect Member",
+ null,
+ "no_indirect_"
+ ],
+ "memberof": [
+ "Member Of",
+ "in_",
+ "not_in_"
+ ]
+ },
+ "takes_params": [
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "group",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Manage password policy for specific group",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Group",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "cn",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": true,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Int",
+ "cli_name": "maxlife",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Maximum password lifetime (in days)",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Max lifetime (days)",
+ "maxvalue": null,
+ "minvalue": 0,
+ "multivalue": false,
+ "name": "krbmaxpwdlife",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "int"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Int",
+ "cli_name": "minlife",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Minimum password lifetime (in hours)",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Min lifetime (hours)",
+ "maxvalue": null,
+ "minvalue": 0,
+ "multivalue": false,
+ "name": "krbminpwdlife",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "int"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Int",
+ "cli_name": "history",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Password history size",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "History size",
+ "maxvalue": null,
+ "minvalue": 0,
+ "multivalue": false,
+ "name": "krbpwdhistorylength",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "int"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Int",
+ "cli_name": "minclasses",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Minimum number of character classes",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Character classes",
+ "maxvalue": 5,
+ "minvalue": 0,
+ "multivalue": false,
+ "name": "krbpwdmindiffchars",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "int"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Int",
+ "cli_name": "minlength",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Minimum length of password",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Min length",
+ "maxvalue": null,
+ "minvalue": 0,
+ "multivalue": false,
+ "name": "krbpwdminlength",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "int"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Int",
+ "cli_name": "priority",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Priority of the policy (higher number means lower priority",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Priority",
+ "maxvalue": null,
+ "minvalue": 0,
+ "multivalue": false,
+ "name": "cospriority",
+ "primary_key": false,
+ "query": false,
+ "required": true,
+ "type": "int"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Int",
+ "cli_name": "maxfail",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Consecutive failures before lockout",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Max failures",
+ "maxvalue": null,
+ "minvalue": 0,
+ "multivalue": false,
+ "name": "krbpwdmaxfailure",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "int"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Int",
+ "cli_name": "failinterval",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Period after which failure count will be reset (seconds)",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Failure reset interval",
+ "maxvalue": null,
+ "minvalue": 0,
+ "multivalue": false,
+ "name": "krbpwdfailurecountinterval",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "int"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Int",
+ "cli_name": "lockouttime",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Period for which lockout is enforced (seconds)",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Lockout duration",
+ "maxvalue": null,
+ "minvalue": 0,
+ "multivalue": false,
+ "name": "krbpwdlockoutduration",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "int"
+ }
+ ],
+ "uuid_attribute": ""
+ },
+ "role": {
+ "aciattrs": [
+ "businesscategory",
+ "cn",
+ "description",
+ "member",
+ "memberof",
+ "o",
+ "objectclass",
+ "ou",
+ "owner",
+ "seealso"
+ ],
+ "attribute_members": {
+ "member": [
+ "user",
+ "group",
+ "host",
+ "hostgroup"
+ ],
+ "memberof": [
+ "privilege"
+ ]
+ },
+ "bindable": false,
+ "container_dn": "cn=roles,cn=accounts",
+ "default_attributes": [
+ "cn",
+ "description",
+ "member",
+ "memberof",
+ "memberindirect"
+ ],
+ "hidden_attributes": [
+ "objectclass",
+ "aci"
+ ],
+ "label": "Role",
+ "methods": [
+ "add",
+ "add_member",
+ "add_privilege",
+ "del",
+ "find",
+ "mod",
+ "remove_member",
+ "remove_privilege",
+ "show"
+ ],
+ "name": "role",
+ "object_class": [
+ "groupofnames",
+ "nestedgroup"
+ ],
+ "object_class_config": null,
+ "object_name": "role",
+ "object_name_plural": "roles",
+ "parent_object": "",
+ "primary_key": "cn",
+ "rdn_attribute": "",
+ "relationships": {
+ "member": [
+ "Member",
+ "",
+ "no_"
+ ],
+ "memberindirect": [
+ "Indirect Member",
+ null,
+ "no_indirect_"
+ ],
+ "memberof": [
+ "Member Of",
+ "in_",
+ "not_in_"
+ ]
+ },
+ "takes_params": [
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "name",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Role name",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Role name",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "cn",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": true,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "desc",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "A description of this role-group",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Description",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "description",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ }
+ ],
+ "uuid_attribute": ""
+ },
+ "selfservice": {
+ "bindable": false,
+ "label": "Self Service Permissions",
+ "methods": [
+ "add",
+ "del",
+ "find",
+ "mod",
+ "show"
+ ],
+ "name": "selfservice",
+ "object_name": [
+ "selfservice"
+ ],
+ "object_name_plural": [
+ "selfservice"
+ ],
+ "primary_key": "aciname",
+ "takes_params": [
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "name",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Self-Service name",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Self-Service name",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "aciname",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": true,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "List",
+ "cli_name": "permissions",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Comma-separated list of permissions to grant (read, write). Default is write.",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Permissions",
+ "multivalue": true,
+ "name": "permissions",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "separator": ",",
+ "skipspace": true,
+ "type": "tuple"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "List",
+ "cli_name": "attrs",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Comma-separated list of attributes",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Attributes",
+ "multivalue": true,
+ "name": "attrs",
+ "primary_key": false,
+ "query": false,
+ "required": true,
+ "separator": ",",
+ "skipspace": true,
+ "type": "tuple"
+ }
+ ]
+ },
+ "service": {
+ "aciattrs": [
+ "ipauniqueid",
+ "krbcanonicalname",
+ "krbextradata",
+ "krblastfailedauth",
+ "krblastpwdchange",
+ "krblastsuccessfulauth",
+ "krbloginfailedcount",
+ "krbmaxrenewableage",
+ "krbmaxticketlife",
+ "krbobjectreferences",
+ "krbpasswordexpiration",
+ "krbprincipalaliases",
+ "krbprincipalexpiration",
+ "krbprincipalkey",
+ "krbprincipalname",
+ "krbprincipaltype",
+ "krbpwdhistory",
+ "krbpwdpolicyreference",
+ "krbticketflags",
+ "krbticketpolicyreference",
+ "krbupenabled",
+ "managedby",
+ "memberof",
+ "objectclass",
+ "usercertificate"
+ ],
+ "attribute_members": {
+ "managedby": [
+ "host"
+ ]
+ },
+ "bindable": true,
+ "container_dn": "cn=services,cn=accounts",
+ "default_attributes": [
+ "krbprincipalname",
+ "usercertificate",
+ "managedby",
+ "krblastpwdchange"
+ ],
+ "hidden_attributes": [
+ "objectclass",
+ "aci"
+ ],
+ "label": "Services",
+ "methods": [
+ "add",
+ "add_host",
+ "del",
+ "disable",
+ "find",
+ "mod",
+ "remove_host",
+ "show"
+ ],
+ "name": "service",
+ "object_class": [
+ "krbprincipal",
+ "krbprincipalaux",
+ "krbticketpolicyaux",
+ "ipaobject",
+ "ipaservice",
+ "pkiuser"
+ ],
+ "object_class_config": null,
+ "object_name": "service",
+ "object_name_plural": "services",
+ "parent_object": "",
+ "primary_key": "krbprincipalname",
+ "rdn_attribute": "",
+ "relationships": {
+ "member": [
+ "Member",
+ "",
+ "no_"
+ ],
+ "memberindirect": [
+ "Indirect Member",
+ null,
+ "no_indirect_"
+ ],
+ "memberof": [
+ "Member Of",
+ "in_",
+ "not_in_"
+ ]
+ },
+ "takes_params": [
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "principal",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Service principal",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Principal",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "krbprincipalname",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": true,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Bytes",
+ "cli_name": "certificate",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Base-64 encoded server certificate",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Certificate",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "usercertificate",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "str"
+ }
+ ],
+ "uuid_attribute": "ipauniqueid"
+ },
+ "sudocmd": {
+ "aciattrs": [
+ "description",
+ "ipauniqueid",
+ "memberof",
+ "objectclass",
+ "sudocmd"
+ ],
+ "attribute_members": {},
+ "bindable": false,
+ "container_dn": "cn=sudocmds,cn=sudo",
+ "default_attributes": [
+ "sudocmd",
+ "description"
+ ],
+ "hidden_attributes": [
+ "objectclass",
+ "aci"
+ ],
+ "label": "SUDO Commands",
+ "methods": [
+ "add",
+ "del",
+ "find",
+ "mod",
+ "show"
+ ],
+ "name": "sudocmd",
+ "object_class": [
+ "ipaobject",
+ "ipasudocmd"
+ ],
+ "object_class_config": null,
+ "object_name": "sudocmd",
+ "object_name_plural": "sudocmds",
+ "parent_object": "",
+ "primary_key": "sudocmd",
+ "rdn_attribute": "",
+ "relationships": {
+ "member": [
+ "Member",
+ "",
+ "no_"
+ ],
+ "memberindirect": [
+ "Indirect Member",
+ null,
+ "no_indirect_"
+ ],
+ "memberof": [
+ "Member Of",
+ "in_",
+ "not_in_"
+ ]
+ },
+ "takes_params": [
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "command",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Sudo Command",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Sudo Command",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "sudocmd",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": true,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "desc",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "A description of this command",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Description",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "description",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ }
+ ],
+ "uuid_attribute": "ipauniqueid"
+ },
+ "sudocmdgroup": {
+ "aciattrs": [
+ "businesscategory",
+ "cn",
+ "description",
+ "ipauniqueid",
+ "member",
+ "o",
+ "objectclass",
+ "ou",
+ "owner",
+ "seealso"
+ ],
+ "attribute_members": {
+ "member": [
+ "sudocmd",
+ "sudocmdgroup"
+ ],
+ "memberindirect": [
+ "sudocmd",
+ "sudocmdgroup"
+ ],
+ "memberof": [
+ "sudocmdgroup"
+ ]
+ },
+ "bindable": false,
+ "container_dn": "cn=sudocmdgroups,cn=sudo",
+ "default_attributes": [
+ "cn",
+ "description",
+ "member",
+ "memberof",
+ "memberindirect"
+ ],
+ "hidden_attributes": [
+ "objectclass",
+ "aci"
+ ],
+ "label": "SUDO Command Groups",
+ "methods": [
+ "add",
+ "add_member",
+ "del",
+ "find",
+ "mod",
+ "remove_member",
+ "show"
+ ],
+ "name": "sudocmdgroup",
+ "object_class": [
+ "ipaobject",
+ "ipasudocmdgrp"
+ ],
+ "object_class_config": null,
+ "object_name": "sudocmdgroup",
+ "object_name_plural": "sudocmdgroups",
+ "parent_object": "",
+ "primary_key": "cn",
+ "rdn_attribute": "",
+ "relationships": {
+ "member": [
+ "Member",
+ "",
+ "no_"
+ ],
+ "memberindirect": [
+ "Indirect Member",
+ null,
+ "no_indirect_"
+ ],
+ "memberof": [
+ "Member Of",
+ "in_",
+ "not_in_"
+ ]
+ },
+ "takes_params": [
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "sudocmdgroup_name",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Sudo Command Group name",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Sudo Command Group name",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "cn",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": true,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "desc",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Group description",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Description",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "description",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "membercmd_sudocmd",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Commands",
+ "exclude": null,
+ "flags": [
+ "no_update",
+ "no_create",
+ "no_search"
+ ],
+ "hint": null,
+ "include": null,
+ "label": "Commands",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "membercmd_sudocmd",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "membercmd_sudocmdgroup",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Sudo Command Groups",
+ "exclude": null,
+ "flags": [
+ "no_update",
+ "no_create",
+ "no_search"
+ ],
+ "hint": null,
+ "include": null,
+ "label": "Sudo Command Groups",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "membercmd_sudocmdgroup",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ }
+ ],
+ "uuid_attribute": "ipauniqueid"
+ },
+ "sudorule": {
+ "aciattrs": [
+ "cmdcategory",
+ "cn",
+ "description",
+ "externalhost",
+ "externaluser",
+ "hostcategory",
+ "hostmask",
+ "ipaenabledflag",
+ "ipasudoopt",
+ "ipasudorunas",
+ "ipasudorunasextgroup",
+ "ipasudorunasextuser",
+ "ipasudorunasgroup",
+ "ipasudorunasgroupcategory",
+ "ipasudorunasusercategory",
+ "ipauniqueid",
+ "memberallowcmd",
+ "memberdenycmd",
+ "memberhost",
+ "memberuser",
+ "usercategory"
+ ],
+ "attribute_members": {
+ "ipasudorunas": [
+ "user",
+ "group"
+ ],
+ "ipasudorunasgroup": [
+ "group"
+ ],
+ "memberallowcmd": [
+ "sudocmd",
+ "sudocmdgroup"
+ ],
+ "memberdenycmd": [
+ "sudocmd",
+ "sudocmdgroup"
+ ],
+ "memberhost": [
+ "host",
+ "hostgroup"
+ ],
+ "memberuser": [
+ "user",
+ "group"
+ ]
+ },
+ "bindable": false,
+ "container_dn": "cn=sudorules,cn=sudo",
+ "default_attributes": [
+ "cn",
+ "ipaenabledflag",
+ "description",
+ "usercategory",
+ "hostcategory",
+ "cmdcategory",
+ "memberuser",
+ "memberhost",
+ "memberallowcmd",
+ "memberdenycmd"
+ ],
+ "hidden_attributes": [
+ "objectclass",
+ "aci"
+ ],
+ "label": "SUDO",
+ "methods": [
+ "add",
+ "add_allow_command",
+ "add_deny_command",
+ "add_host",
+ "add_option",
+ "add_runasgroup",
+ "add_runasuser",
+ "add_user",
+ "del",
+ "disable",
+ "enable",
+ "find",
+ "mod",
+ "remove_allow_command",
+ "remove_deny_command",
+ "remove_host",
+ "remove_option",
+ "remove_runasgroup",
+ "remove_runasuser",
+ "remove_user",
+ "show"
+ ],
+ "name": "sudorule",
+ "object_class": [
+ "ipaassociation",
+ "ipasudorule"
+ ],
+ "object_class_config": null,
+ "object_name": "Sudo Rule",
+ "object_name_plural": "Sudo Rules",
+ "parent_object": "",
+ "primary_key": "cn",
+ "rdn_attribute": "ipauniqueid",
+ "relationships": {
+ "member": [
+ "Member",
+ "",
+ "no_"
+ ],
+ "memberindirect": [
+ "Indirect Member",
+ null,
+ "no_indirect_"
+ ],
+ "memberof": [
+ "Member Of",
+ "in_",
+ "not_in_"
+ ]
+ },
+ "takes_params": [
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "sudorule_name",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Rule name",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Rule name",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "cn",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": true,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "desc",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Description",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Description",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "description",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": true,
+ "class": "Flag",
+ "cli_name": "ipaenabledflag",
+ "cli_short_name": null,
+ "default": false,
+ "doc": "Enabled",
+ "exclude": null,
+ "falsehoods": [
+ 0,
+ "0",
+ "false"
+ ],
+ "flags": [
+ "no_update",
+ "no_create",
+ "no_search"
+ ],
+ "hint": null,
+ "include": null,
+ "label": "Enabled",
+ "multivalue": false,
+ "name": "ipaenabledflag",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "truths": [
+ "1",
+ 1,
+ "true"
+ ],
+ "type": "bool"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "StrEnum",
+ "cli_name": "usercat",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "User category the rule applies to",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "User category",
+ "multivalue": false,
+ "name": "usercategory",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode",
+ "values": [
+ "all"
+ ]
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "StrEnum",
+ "cli_name": "hostcat",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Host category the rule applies to",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Host category",
+ "multivalue": false,
+ "name": "hostcategory",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode",
+ "values": [
+ "all"
+ ]
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "StrEnum",
+ "cli_name": "cmdcat",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Command category the rule applies to",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Command category",
+ "multivalue": false,
+ "name": "cmdcategory",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode",
+ "values": [
+ "all"
+ ]
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "StrEnum",
+ "cli_name": "runasusercat",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Run As User category the rule applies to",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Run As User category",
+ "multivalue": false,
+ "name": "ipasudorunasusercategory",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode",
+ "values": [
+ "all"
+ ]
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "StrEnum",
+ "cli_name": "runasgroupcat",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Run As Group category the rule applies to",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Run As Group category",
+ "multivalue": false,
+ "name": "ipasudorunasgroupcategory",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode",
+ "values": [
+ "all"
+ ]
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "memberuser_user",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Users",
+ "exclude": null,
+ "flags": [
+ "no_update",
+ "no_create",
+ "no_search"
+ ],
+ "hint": null,
+ "include": null,
+ "label": "Users",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "memberuser_user",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "memberhost_host",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Hosts",
+ "exclude": null,
+ "flags": [
+ "no_update",
+ "no_create",
+ "no_search"
+ ],
+ "hint": null,
+ "include": null,
+ "label": "Hosts",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "memberhost_host",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "memberhost_hostgroup",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Host Groups",
+ "exclude": null,
+ "flags": [
+ "no_update",
+ "no_create",
+ "no_search"
+ ],
+ "hint": null,
+ "include": null,
+ "label": "Host Groups",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "memberhost_hostgroup",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "memberallowcmd_sudocmd",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Sudo Allow Commands",
+ "exclude": null,
+ "flags": [
+ "no_update",
+ "no_create",
+ "no_search"
+ ],
+ "hint": null,
+ "include": null,
+ "label": "Sudo Allow Commands",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "memberallowcmd_sudocmd",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "memberdenycmd_sudocmd",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Sudo Deny Commands",
+ "exclude": null,
+ "flags": [
+ "no_update",
+ "no_create",
+ "no_search"
+ ],
+ "hint": null,
+ "include": null,
+ "label": "Sudo Deny Commands",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "memberdenycmd_sudocmd",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "memberallowcmd_sudocmdgroup",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Sudo Command Groups",
+ "exclude": null,
+ "flags": [
+ "no_update",
+ "no_create",
+ "no_search"
+ ],
+ "hint": null,
+ "include": null,
+ "label": "Sudo Command Groups",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "memberallowcmd_sudocmdgroup",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "memberdenycmd_sudocmdgroup",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Sudo Command Groups",
+ "exclude": null,
+ "flags": [
+ "no_update",
+ "no_create",
+ "no_search"
+ ],
+ "hint": null,
+ "include": null,
+ "label": "Sudo Command Groups",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "memberdenycmd_sudocmdgroup",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "ipasudorunas_user",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Run As User",
+ "exclude": null,
+ "flags": [
+ "no_update",
+ "no_create",
+ "no_search"
+ ],
+ "hint": null,
+ "include": null,
+ "label": "Run As User",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "ipasudorunas_user",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "ipasudorunasgroup_group",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Run As Group",
+ "exclude": null,
+ "flags": [
+ "no_update",
+ "no_create",
+ "no_search"
+ ],
+ "hint": null,
+ "include": null,
+ "label": "Run As Group",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "ipasudorunasgroup_group",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "externaluser",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "External User the rule applies to",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "External User",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "externaluser",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "runasexternaluser",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "External User the commands can run as",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "RunAs External User",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "ipasudorunasextuser",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "runasexternalgroup",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "External Group the commands can run as",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "RunAs External Group",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "ipasudorunasextgroup",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ }
+ ],
+ "uuid_attribute": "ipauniqueid"
+ },
+ "user": {
+ "aciattrs": [
+ "audio",
+ "businesscategory",
+ "carlicense",
+ "cn",
+ "departmentnumber",
+ "description",
+ "destinationindicator",
+ "displayname",
+ "employeenumber",
+ "employeetype",
+ "facsimiletelephonenumber",
+ "gecos",
+ "gidnumber",
+ "givenname",
+ "homedirectory",
+ "homephone",
+ "homepostaladdress",
+ "inetuserhttpurl",
+ "inetuserstatus",
+ "initials",
+ "internationalisdnnumber",
+ "ipauniqueid",
+ "jpegphoto",
+ "krbcanonicalname",
+ "krbextradata",
+ "krblastfailedauth",
+ "krblastpwdchange",
+ "krblastsuccessfulauth",
+ "krbloginfailedcount",
+ "krbmaxrenewableage",
+ "krbmaxticketlife",
+ "krbpasswordexpiration",
+ "krbprincipalaliases",
+ "krbprincipalexpiration",
+ "krbprincipalkey",
+ "krbprincipalname",
+ "krbprincipaltype",
+ "krbpwdhistory",
+ "krbpwdpolicyreference",
+ "krbticketflags",
+ "krbticketpolicyreference",
+ "krbupenabled",
+ "l",
+ "labeleduri",
+ "loginshell",
+ "mail",
+ "manager",
+ "memberof",
+ "mepmanagedentry",
+ "mobile",
+ "o",
+ "objectclass",
+ "ou",
+ "pager",
+ "photo",
+ "physicaldeliveryofficename",
+ "postaladdress",
+ "postalcode",
+ "postofficebox",
+ "preferreddeliverymethod",
+ "preferredlanguage",
+ "registeredaddress",
+ "roomnumber",
+ "secretary",
+ "seealso",
+ "sn",
+ "st",
+ "street",
+ "telephonenumber",
+ "teletexterminalidentifier",
+ "telexnumber",
+ "title",
+ "uid",
+ "uidnumber",
+ "usercertificate",
+ "userpassword",
+ "userpkcs12",
+ "usersmimecertificate",
+ "x121address",
+ "x500uniqueidentifier"
+ ],
+ "attribute_members": {
+ "memberof": [
+ "group",
+ "netgroup",
+ "role"
+ ]
+ },
+ "bindable": true,
+ "container_dn": "cn=users,cn=accounts",
+ "default_attributes": [
+ "uid",
+ "givenname",
+ "sn",
+ "homedirectory",
+ "loginshell",
+ "ou",
+ "telephonenumber",
+ "title",
+ "memberof",
+ "nsaccountlock"
+ ],
+ "hidden_attributes": [
+ "objectclass",
+ "aci"
+ ],
+ "label": "Users",
+ "methods": [
+ "add",
+ "del",
+ "disable",
+ "enable",
+ "find",
+ "mod",
+ "show"
+ ],
+ "name": "user",
+ "object_class": [
+ "posixaccount"
+ ],
+ "object_class_config": "ipauserobjectclasses",
+ "object_name": "user",
+ "object_name_plural": "users",
+ "parent_object": "",
+ "primary_key": "uid",
+ "rdn_attribute": "",
+ "relationships": {
+ "member": [
+ "Member",
+ "",
+ "no_"
+ ],
+ "memberindirect": [
+ "Indirect Member",
+ null,
+ "no_indirect_"
+ ],
+ "memberof": [
+ "Member Of",
+ "in_",
+ "not_in_"
+ ]
+ },
+ "takes_params": [
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "login",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "User login",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "User login",
+ "length": null,
+ "maxlength": 255,
+ "minlength": null,
+ "multivalue": false,
+ "name": "uid",
+ "pattern": "^[a-zA-Z0-9_.][a-zA-Z0-9_.-]{0,252}[a-zA-Z0-9_.$-]?$",
+ "pattern_errmsg": "may only include letters, numbers, _, -, . and $",
+ "primary_key": true,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "first",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "First name",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "First name",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "givenname",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "last",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Last name",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Last name",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "sn",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": true,
+ "class": "Str",
+ "cli_name": "cn",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Full name",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Full name",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "cn",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": true,
+ "class": "Str",
+ "cli_name": "displayname",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Display name",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Display name",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "displayname",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": true,
+ "class": "Str",
+ "cli_name": "initials",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Initials",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Initials",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "initials",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "homedir",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Home directory",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Home directory",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "homedirectory",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": true,
+ "class": "Str",
+ "cli_name": "gecos",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "GECOS field",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "GECOS field",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "gecos",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "shell",
+ "cli_short_name": null,
+ "default": "/bin/sh",
+ "doc": "Login shell",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Login shell",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "loginshell",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": true,
+ "class": "Str",
+ "cli_name": "principal",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Kerberos principal",
+ "exclude": null,
+ "flags": [
+ "no_update"
+ ],
+ "hint": null,
+ "include": null,
+ "label": "Kerberos principal",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "krbprincipalname",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "email",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Email address",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Email address",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": true,
+ "name": "mail",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Password",
+ "cli_name": "password",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Prompt to set the user password",
+ "exclude": [
+ "webui"
+ ],
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Password",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "userpassword",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": true,
+ "class": "Int",
+ "cli_name": "uid",
+ "cli_short_name": null,
+ "default": 999,
+ "doc": "User ID Number (system will assign one if not provided)",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "UID",
+ "maxvalue": null,
+ "minvalue": 1,
+ "multivalue": false,
+ "name": "uidnumber",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "int"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Int",
+ "cli_name": "gidnumber",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Group ID Number",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "GID",
+ "maxvalue": null,
+ "minvalue": null,
+ "multivalue": false,
+ "name": "gidnumber",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "int"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "street",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Street address",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Street address",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "street",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "city",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "City",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "City",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "location",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "state",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "State",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "State",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "state",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Int",
+ "cli_name": "postalcode",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "ZIP",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "ZIP",
+ "maxvalue": null,
+ "minvalue": null,
+ "multivalue": false,
+ "name": "postalcode",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "int"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "phone",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Telephone Number",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Telephone Number",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": true,
+ "name": "telephonenumber",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "mobile",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Mobile Telephone Number",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Mobile Telephone Number",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": true,
+ "name": "mobile",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "pager",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Pager Number",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Pager Number",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": true,
+ "name": "pager",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "fax",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Fax Number",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Fax Number",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": true,
+ "name": "facsimiletelephonenumber",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "orgunit",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Org. Unit",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Org. Unit",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "ou",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "title",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Job Title",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Job Title",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "title",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "manager",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Manager",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Manager",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "manager",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "carlicense",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Car License",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Car License",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "carlicense",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "alwaysask": false,
+ "attribute": false,
+ "autofill": false,
+ "class": "Bool",
+ "cli_name": "nsaccountlock",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Account activation status",
+ "exclude": null,
+ "falsehoods": [
+ 0,
+ "0",
+ "false"
+ ],
+ "flags": [
+ "no_update",
+ "no_create",
+ "no_search"
+ ],
+ "hint": null,
+ "include": null,
+ "label": "Account activation status",
+ "multivalue": false,
+ "name": "nsaccountlock",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "truths": [
+ "1",
+ 1,
+ "true"
+ ],
+ "type": "bool"
+ }
+ ],
+ "uuid_attribute": "ipauniqueid"
+ }
+ }
+ },
+ {
+ "error": null,
+ "messages": {
+ "ajax": {
+ "401": "Your kerberos ticket no longer valid.Please run KInit and then click 'retry'If this is your first time running the IPA Web UI<a href='/ipa/errors/ssbrowser.html'> Follow these directions</a> to configure your browser."
+ },
+ "association": {
+ "managedby": "Managed by",
+ "members": "Members",
+ "membershipin": "Membership in"
+ },
+ "button": {
+ "add": "Add",
+ "enroll": "Enroll",
+ "find": "Find",
+ "remove": "Delete",
+ "reset": "Reset",
+ "update": "Update"
+ },
+ "details": {
+ "account": "Account Settings",
+ "contact": "Contact Settings",
+ "employee": "Employee Information",
+ "identity": "Identity Settings",
+ "mailing": "Mailing Address",
+ "misc": "Misc. Information",
+ "to_top": "Back to Top"
+ },
+ "facets": {
+ "details": "Settings",
+ "search": "Search"
+ },
+ "login": {
+ "header": "Logged In As"
+ },
+ "search": {
+ "delete_confirm": "Do you really want to delete the selected entries?",
+ "quick_links": "Quick Links",
+ "select_all": "Select All",
+ "unselect_all": "Unselect All"
+ }
+ }
+ },
+ {
+ "count": 1,
+ "error": null,
+ "result": [
+ {
+ "cn": [
+ "Administrator"
+ ],
+ "dn": "uid=admin,cn=users,cn=accounts,dc=ipa14,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "gecos": [
+ "Administrator"
+ ],
+ "gidnumber": [
+ "590200000"
+ ],
+ "homedirectory": [
+ "/home/admin"
+ ],
+ "ipauniqueid": [
+ "3f1c60c6-2026-11e0-80c2-52540029a798"
+ ],
+ "krblastpwdchange": [
+ "20110114213748Z"
+ ],
+ "krblastsuccessfulauth": [
+ "20110114213845Z"
+ ],
+ "krbpasswordexpiration": [
+ "20110414213748Z"
+ ],
+ "krbprincipalname": [
+ "admin@IPA14.AYOUNG.BOSTON.DEVEL.REDHAT.COM"
+ ],
+ "loginshell": [
+ "/bin/bash"
+ ],
+ "memberof_group": [
+ "admins"
+ ],
+ "mepmanagedentry": [
+ "cn=admin,cn=groups,cn=accounts,dc=ipa14,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com"
+ ],
+ "nsaccountlock": [
+ "False"
+ ],
+ "objectclass": [
+ "top",
+ "person",
+ "posixaccount",
+ "krbprincipalaux",
+ "krbticketpolicyaux",
+ "inetuser",
+ "ipaobject",
+ "mepOriginEntry"
+ ],
+ "sn": [
+ "Administrator"
+ ],
+ "uid": [
+ "admin"
+ ],
+ "uidnumber": [
+ "590200000"
+ ]
+ }
+ ],
+ "summary": "1 user matched",
+ "truncated": false
+ },
+ {
+ "count": 65,
+ "error": null,
+ "result": {
+ "basedn": "dc=ipa14,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "bin": "/var/www",
+ "ca_agent_port": 9443,
+ "ca_ee_port": 9444,
+ "ca_host": "ipa14.ayoung.boston.devel.redhat.com",
+ "ca_port": 9180,
+ "conf": "/etc/ipa/server.conf",
+ "conf_default": "/etc/ipa/default.conf",
+ "confdir": "/etc/ipa",
+ "config_loaded": true,
+ "container_accounts": "cn=accounts",
+ "container_applications": "cn=applications,cn=configs,cn=policies",
+ "container_automount": "cn=automount",
+ "container_configs": "cn=configs,cn=policies",
+ "container_dns": "cn=dns",
+ "container_group": "cn=groups,cn=accounts",
+ "container_hbac": "cn=hbac",
+ "container_hbacservice": "cn=hbacservices,cn=hbac",
+ "container_hbacservicegroup": "cn=hbacservicegroups,cn=hbac",
+ "container_host": "cn=computers,cn=accounts",
+ "container_hostgroup": "cn=hostgroups,cn=accounts",
+ "container_netgroup": "cn=ng,cn=alt",
+ "container_permission": "cn=permissions,cn=pbac",
+ "container_policies": "cn=policies",
+ "container_policygroups": "cn=policygroups,cn=configs,cn=policies",
+ "container_policylinks": "cn=policylinks,cn=configs,cn=policies",
+ "container_privilege": "cn=privileges,cn=pbac",
+ "container_rolegroup": "cn=roles,cn=accounts",
+ "container_roles": "cn=roles,cn=policies",
+ "container_service": "cn=services,cn=accounts",
+ "container_sudocmd": "cn=sudocmds,cn=sudo",
+ "container_sudocmdgroup": "cn=sudocmdgroups,cn=sudo",
+ "container_sudorule": "cn=sudorules,cn=sudo",
+ "container_user": "cn=users,cn=accounts",
+ "container_virtual": "cn=virtual operations,cn=etc",
+ "context": "server",
+ "debug": false,
+ "domain": "ayoung.boston.devel.redhat.com",
+ "dot_ipa": "/var/www/.ipa",
+ "enable_ra": true,
+ "fallback": true,
+ "home": "/var/www",
+ "host": "ipa14.ayoung.boston.devel.redhat.com",
+ "in_server": true,
+ "in_tree": false,
+ "interactive": true,
+ "ipalib": "/usr/lib/python2.7/site-packages/ipalib",
+ "ldap_uri": "ldapi://%2fvar%2frun%2fslapd-IPA14-AYOUNG-BOSTON-DEVEL-REDHAT-COM.socket",
+ "log": null,
+ "logdir": "/var/log/ipa",
+ "mode": "production",
+ "mount_ipa": "/ipa/",
+ "mount_jsonserver": "json",
+ "mount_xmlserver": "xml",
+ "prompt_all": false,
+ "ra_plugin": "selfsign",
+ "realm": "IPA14.AYOUNG.BOSTON.DEVEL.REDHAT.COM",
+ "rpc_json_uri": "http://localhost:8888/ipa/json",
+ "script": "/var/www/mod_wsgi",
+ "site_packages": "/usr/lib/python2.7/site-packages",
+ "startup_traceback": false,
+ "verbose": 0,
+ "webui_assets_dir": null,
+ "webui_prod": true,
+ "xmlrpc_uri": "https://ipa14.ayoung.boston.devel.redhat.com/ipa/xml"
+ },
+ "summary": "65 variables",
+ "total": 65
+ }
+ ]
+ }
+}
diff --git a/install/ui/test/data/json_metadata.json b/install/ui/test/data/json_metadata.json
new file mode 100644
index 000000000..222a8b65c
--- /dev/null
+++ b/install/ui/test/data/json_metadata.json
@@ -0,0 +1,4097 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "messages": {
+ "ajax": {
+ "401": "Your kerberos ticket no longer valid.Please run KInit and then click 'retry'If this is your first time running the IPA Web UI<a href='/ipa/errors/ssbrowser.html'> Follow these directions</a> to configure your browser."
+ },
+ "button": {
+ "add": "Add",
+ "enroll": "Enroll",
+ "find": "Find",
+ "remove": "Delete",
+ "reset": "Reset",
+ "update": "Update"
+ },
+ "details": {
+ "account": "Account Details",
+ "contact": "Contact Details",
+ "employee": " Employee Information",
+ "identity": "Identity Details",
+ "mailing": "Mailing Address",
+ "misc": "Misc. Information",
+ "to_top": "Back to Top"
+ },
+ "login": {
+ "header": "Logged In As"
+ },
+ "search": {
+ "delete_confirm": "Do you really want to delete the selected entries?",
+ "quick_links": "Quick Links",
+ "select_all": "Select All",
+ "unselect_all": "Unselect All"
+ }
+ },
+ "metadata": {
+ "aci": {
+ "__base64__": ""
+ },
+ "automountkey": {
+ "attribute_members": {},
+ "container_dn": "cn=automount",
+ "default_attributes": [
+ "automountkey",
+ "automountinformation",
+ "description"
+ ],
+ "hidden_attributes": [
+ "objectclass",
+ "aci"
+ ],
+ "label": "Automount Keys",
+ "methods": [
+ "add",
+ "del",
+ "find",
+ "mod",
+ "show"
+ ],
+ "name": "automountkey",
+ "object_class": [
+ "automount"
+ ],
+ "object_class_config": null,
+ "object_name": "automount key",
+ "object_name_plural": "automount keys",
+ "parent_object": "automountmap",
+ "primary_key": "automountkey",
+ "rdn_attribute": "",
+ "takes_params": [
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "key",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Automount key name",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Key",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "automountkey",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": true,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "info",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Mount information",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Mount information",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "automountinformation",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "desc",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "description",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "description",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "description",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ }
+ ],
+ "uuid_attribute": ""
+ },
+ "automountlocation": {
+ "attribute_members": {},
+ "container_dn": "cn=automount",
+ "default_attributes": [
+ "cn"
+ ],
+ "hidden_attributes": [
+ "objectclass",
+ "aci"
+ ],
+ "label": "Automount",
+ "methods": [
+ "add",
+ "del",
+ "find",
+ "import",
+ "show",
+ "tofiles"
+ ],
+ "name": "automountlocation",
+ "object_class": [
+ "nscontainer"
+ ],
+ "object_class_config": null,
+ "object_name": "automount location",
+ "object_name_plural": "automount locations",
+ "parent_object": "",
+ "primary_key": "cn",
+ "rdn_attribute": "",
+ "takes_params": [
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "location",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Automount location name",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Location",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "cn",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": true,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ }
+ ],
+ "uuid_attribute": ""
+ },
+ "automountmap": {
+ "attribute_members": {},
+ "container_dn": "cn=automount",
+ "default_attributes": [
+ "automountmapname",
+ "description"
+ ],
+ "hidden_attributes": [
+ "objectclass",
+ "aci"
+ ],
+ "label": "Automount Maps",
+ "methods": [
+ "add",
+ "add_indirect",
+ "del",
+ "find",
+ "mod",
+ "show"
+ ],
+ "name": "automountmap",
+ "object_class": [
+ "automountmap"
+ ],
+ "object_class_config": null,
+ "object_name": "automount map",
+ "object_name_plural": "automount maps",
+ "parent_object": "automountlocation",
+ "primary_key": "automountmapname",
+ "rdn_attribute": "",
+ "takes_params": [
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "map",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Automount map name",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Map",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "automountmapname",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": true,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "desc",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Description",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Description",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "description",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ }
+ ],
+ "uuid_attribute": ""
+ },
+ "config": {
+ "attribute_members": {},
+ "container_dn": "",
+ "default_attributes": [
+ "ipamaxusernamelength",
+ "ipahomesrootdir",
+ "ipadefaultloginshell",
+ "ipadefaultprimarygroup",
+ "ipadefaultdomain",
+ "ipasearchtimelimit",
+ "ipasearchrecordslimit",
+ "ipausersearchfields",
+ "ipagroupsearchfields",
+ "ipamigrationenabled",
+ "ipacertificatesubjectbase"
+ ],
+ "hidden_attributes": [
+ "objectclass",
+ "aci"
+ ],
+ "label": "Configuration",
+ "methods": [
+ "mod",
+ "show"
+ ],
+ "name": "config",
+ "object_class": [],
+ "object_class_config": null,
+ "object_name": "configuration options",
+ "object_name_plural": "entries",
+ "parent_object": "",
+ "rdn_attribute": "",
+ "takes_params": [
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Int",
+ "cli_name": "maxusername",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Max username length",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Max username length",
+ "maxvalue": null,
+ "minvalue": 1,
+ "multivalue": false,
+ "name": "ipamaxusernamelength",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "int"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "homedirectory",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Default location of home directories",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Home directory base",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "ipahomesrootdir",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "defaultshell",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Default shell for new users",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Default shell",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "ipadefaultloginshell",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "defaultgroup",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Default group for new users",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Default users group",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "ipadefaultprimarygroup",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "emaildomain",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Default e-mail domain new users",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Default e-mail domain",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "ipadefaultemaildomain",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Int",
+ "cli_name": "searchtimelimit",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Max. amount of time (sec.) for a search (-1 is unlimited)",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Search time limit",
+ "maxvalue": null,
+ "minvalue": -1,
+ "multivalue": false,
+ "name": "ipasearchtimelimit",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "int"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Int",
+ "cli_name": "searchrecordslimit",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Max. number of records to search (-1 is unlimited)",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Search size limit",
+ "maxvalue": null,
+ "minvalue": -1,
+ "multivalue": false,
+ "name": "ipasearchrecordslimit",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "int"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "usersearch",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "A comma-separated list of fields to search when searching for users",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "User search fields",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "ipausersearchfields",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "groupsearch",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "A comma-separated list of fields to search when searching for groups",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Group search fields",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "ipagroupsearchfields",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Bool",
+ "cli_name": "enable_migration",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Enable migration mode",
+ "exclude": null,
+ "falsehoods": [
+ 0,
+ "0",
+ "false"
+ ],
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Migration mode",
+ "multivalue": false,
+ "name": "ipamigrationenabled",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "truths": [
+ "1",
+ 1,
+ "true"
+ ],
+ "type": "bool"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "subject",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Base for certificate subjects (OU=Test,O=Example)",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Certificate Subject base",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "ipacertificatesubjectbase",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ }
+ ],
+ "uuid_attribute": ""
+ },
+ "cosentry": {
+ "attribute_members": {},
+ "container_dn": "cn=costemplates,cn=accounts",
+ "default_attributes": [
+ "cn",
+ "cospriority",
+ "krbpwdpolicyreference"
+ ],
+ "hidden_attributes": [
+ "objectclass",
+ "aci"
+ ],
+ "label": "<cosentry.label>",
+ "methods": [
+ "add",
+ "del",
+ "find",
+ "mod",
+ "show"
+ ],
+ "name": "cosentry",
+ "object_class": [
+ "top",
+ "costemplate",
+ "extensibleobject",
+ "krbcontainer"
+ ],
+ "object_class_config": null,
+ "object_name": "entry",
+ "object_name_plural": "entries",
+ "parent_object": "",
+ "primary_key": "cn",
+ "rdn_attribute": "",
+ "takes_params": [
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "cn",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "<cn>",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "<cn>",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "cn",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": true,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "krbpwdpolicyreference",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "<krbpwdpolicyreference>",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "<krbpwdpolicyreference>",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "krbpwdpolicyreference",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Int",
+ "cli_name": "cospriority",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "<cospriority>",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "<cospriority>",
+ "maxvalue": null,
+ "minvalue": 0,
+ "multivalue": false,
+ "name": "cospriority",
+ "primary_key": false,
+ "query": false,
+ "required": true,
+ "type": "int"
+ }
+ ],
+ "uuid_attribute": ""
+ },
+ "dns": {
+ "default_attributes": [
+ "idnsname",
+ "idnszoneactive",
+ "idnssoamname",
+ "idnssoarname",
+ "idnssoaserial",
+ "idnssoarefresh",
+ "idnssoaretry",
+ "idnssoaexpire",
+ "idnssoaminimum"
+ ],
+ "label": "DNS",
+ "methods": [
+ "add",
+ "del",
+ "find",
+ "mod",
+ "show"
+ ],
+ "name": "dns",
+ "primary_key": "idnsname",
+ "takes_params": [
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "name",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Zone name (FQDN)",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Zone",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "idnsname",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": true,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "name_server",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Authoritative name server",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Authoritative name server",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "idnssoamname",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "admin_email",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "administrator e-mail address",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "administrator e-mail address",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "idnssoarname",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Int",
+ "cli_name": "serial",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "SOA serial",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "SOA serial",
+ "maxvalue": null,
+ "minvalue": null,
+ "multivalue": false,
+ "name": "idnssoaserial",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "int"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Int",
+ "cli_name": "refresh",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "SOA refresh",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "SOA refresh",
+ "maxvalue": null,
+ "minvalue": null,
+ "multivalue": false,
+ "name": "idnssoarefresh",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "int"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Int",
+ "cli_name": "retry",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "SOA retry",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "SOA retry",
+ "maxvalue": null,
+ "minvalue": null,
+ "multivalue": false,
+ "name": "idnssoaretry",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "int"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Int",
+ "cli_name": "expire",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "SOA expire",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "SOA expire",
+ "maxvalue": null,
+ "minvalue": null,
+ "multivalue": false,
+ "name": "idnssoaexpire",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "int"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Int",
+ "cli_name": "minimum",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "SOA minimum",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "SOA minimum",
+ "maxvalue": null,
+ "minvalue": null,
+ "multivalue": false,
+ "name": "idnssoaminimum",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "int"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Int",
+ "cli_name": "ttl",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "SOA time to live",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "SOA time to live",
+ "maxvalue": null,
+ "minvalue": null,
+ "multivalue": false,
+ "name": "dnsttl",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "int"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "StrEnum",
+ "cli_name": "class",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "SOA class",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "SOA class",
+ "multivalue": false,
+ "name": "dnsclass",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode",
+ "values": [
+ "IN",
+ "CS",
+ "CH",
+ "HS"
+ ]
+ },
+ {
+ "attribute": false,
+ "autofill": true,
+ "class": "Flag",
+ "cli_name": "allow_dynupdate",
+ "cli_short_name": null,
+ "default": false,
+ "doc": "allow dynamic update?",
+ "exclude": null,
+ "falsehoods": [
+ 0,
+ "0",
+ "false"
+ ],
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "allow dynamic update?",
+ "multivalue": false,
+ "name": "idnsallowdynupdate",
+ "primary_key": false,
+ "query": false,
+ "required": true,
+ "truths": [
+ "1",
+ 1,
+ "true"
+ ],
+ "type": "bool"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "update_policy",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "BIND update policy",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "BIND update policy",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "idnsupdatepolicy",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ }
+ ]
+ },
+ "group": {
+ "attribute_members": {
+ "member": [
+ "user",
+ "group"
+ ],
+ "memberindirect": [
+ "user",
+ "group",
+ "netgroup",
+ "rolegroup",
+ "taskgroup"
+ ],
+ "memberof": [
+ "group",
+ "netgroup",
+ "rolegroup",
+ "taskgroup"
+ ]
+ },
+ "container_dn": "cn=groups,cn=accounts",
+ "default_attributes": [
+ "cn",
+ "description",
+ "gidnumber",
+ "member",
+ "memberof",
+ "memberindirect"
+ ],
+ "hidden_attributes": [
+ "objectclass",
+ "aci"
+ ],
+ "label": "User Groups",
+ "methods": [
+ "add",
+ "add_member",
+ "del",
+ "detach",
+ "find",
+ "mod",
+ "remove_member",
+ "show"
+ ],
+ "name": "group",
+ "object_class": [
+ "ipausergroup"
+ ],
+ "object_class_config": "ipagroupobjectclasses",
+ "object_name": "group",
+ "object_name_plural": "groups",
+ "parent_object": "",
+ "primary_key": "cn",
+ "rdn_attribute": "",
+ "takes_params": [
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "name",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Group name",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Group name",
+ "length": null,
+ "maxlength": 33,
+ "minlength": null,
+ "multivalue": false,
+ "name": "cn",
+ "pattern": "^[a-zA-Z0-9_.][a-zA-Z0-9_.-]{0,30}[a-zA-Z0-9_.$-]?$",
+ "pattern_errmsg": "may only include letters, numbers, _, -, . and $",
+ "primary_key": true,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "desc",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Group description",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Description",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "description",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Int",
+ "cli_name": "gid",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "GID (use this option to set it manually)",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "GID",
+ "maxvalue": null,
+ "minvalue": null,
+ "multivalue": false,
+ "name": "gidnumber",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "int"
+ }
+ ],
+ "uuid_attribute": "ipauniqueid"
+ },
+ "hbac": {
+ "attribute_members": {
+ "memberhost": [
+ "host",
+ "hostgroup"
+ ],
+ "memberservice": [
+ "hbacsvc",
+ "hbacsvcgroup"
+ ],
+ "memberuser": [
+ "user",
+ "group"
+ ],
+ "sourcehost": [
+ "host",
+ "hostgroup"
+ ]
+ },
+ "container_dn": "cn=hbac",
+ "default_attributes": [
+ "cn",
+ "accessruletype",
+ "ipaenabledflag",
+ "accesstime",
+ "description",
+ "usercategory",
+ "hostcategory",
+ "sourcehostcategory",
+ "servicecategory",
+ "ipaenabledflag",
+ "memberuser",
+ "sourcehost",
+ "memberhost",
+ "memberservice",
+ "memberhostgroup"
+ ],
+ "hidden_attributes": [
+ "objectclass",
+ "aci"
+ ],
+ "label": "HBAC",
+ "methods": [
+ "add",
+ "add_accesstime",
+ "add_host",
+ "add_service",
+ "add_sourcehost",
+ "add_user",
+ "del",
+ "disable",
+ "enable",
+ "find",
+ "mod",
+ "remove_accesstime",
+ "remove_host",
+ "remove_service",
+ "remove_sourcehost",
+ "remove_user",
+ "show"
+ ],
+ "name": "hbac",
+ "object_class": [
+ "ipaassociation",
+ "ipahbacrule"
+ ],
+ "object_class_config": null,
+ "object_name": "HBAC rule",
+ "object_name_plural": "HBAC rules",
+ "parent_object": "",
+ "primary_key": "cn",
+ "rdn_attribute": "ipauniqueid",
+ "takes_params": [
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "name",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Rule name",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Rule name",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "cn",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": true,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "StrEnum",
+ "cli_name": "type",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Rule type (allow or deny)",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Rule type",
+ "multivalue": false,
+ "name": "accessruletype",
+ "primary_key": false,
+ "query": false,
+ "required": true,
+ "type": "unicode",
+ "values": [
+ "allow",
+ "deny"
+ ]
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "StrEnum",
+ "cli_name": "usercat",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "User category the rule applies to",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "User category",
+ "multivalue": false,
+ "name": "usercategory",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode",
+ "values": [
+ "all"
+ ]
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "StrEnum",
+ "cli_name": "hostcat",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Host category the rule applies to",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Host category",
+ "multivalue": false,
+ "name": "hostcategory",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode",
+ "values": [
+ "all"
+ ]
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "StrEnum",
+ "cli_name": "srchostcat",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Source host category the rule applies to",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Source host category",
+ "multivalue": false,
+ "name": "sourcehostcategory",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode",
+ "values": [
+ "all"
+ ]
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "StrEnum",
+ "cli_name": "servicecat",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Service category the rule applies to",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Service category",
+ "multivalue": false,
+ "name": "servicecategory",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode",
+ "values": [
+ "all"
+ ]
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "AccessTime",
+ "cli_name": "time",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Access time",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Access time",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "accesstime",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "desc",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Description",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Description",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "description",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": true,
+ "class": "Flag",
+ "cli_name": "ipaenabledflag",
+ "cli_short_name": null,
+ "default": false,
+ "doc": "Enabled",
+ "exclude": null,
+ "falsehoods": [
+ 0,
+ "0",
+ "false"
+ ],
+ "flags": [
+ "no_update",
+ "no_create",
+ "no_search"
+ ],
+ "hint": null,
+ "include": null,
+ "label": "Enabled",
+ "multivalue": false,
+ "name": "ipaenabledflag",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "truths": [
+ "1",
+ 1,
+ "true"
+ ],
+ "type": "bool"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "memberuser_user",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Users",
+ "exclude": null,
+ "flags": [
+ "no_update",
+ "no_create",
+ "no_search"
+ ],
+ "hint": null,
+ "include": null,
+ "label": "Users",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "memberuser_user",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "memberhost_host",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Hosts",
+ "exclude": null,
+ "flags": [
+ "no_update",
+ "no_create",
+ "no_search"
+ ],
+ "hint": null,
+ "include": null,
+ "label": "Hosts",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "memberhost_host",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "memberhost_hostgroup",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Host Groups",
+ "exclude": null,
+ "flags": [
+ "no_update",
+ "no_create",
+ "no_search"
+ ],
+ "hint": null,
+ "include": null,
+ "label": "Host Groups",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "memberhost_hostgroup",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "sourcehost_host",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Source hosts",
+ "exclude": null,
+ "flags": [
+ "no_update",
+ "no_create",
+ "no_search"
+ ],
+ "hint": null,
+ "include": null,
+ "label": "Source hosts",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "sourcehost_host",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "memberservice_service",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Services",
+ "exclude": null,
+ "flags": [
+ "no_update",
+ "no_create",
+ "no_search"
+ ],
+ "hint": null,
+ "include": null,
+ "label": "Services",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "memberservice_service",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "memberservice_servicegroup",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Service Groups",
+ "exclude": null,
+ "flags": [
+ "no_update",
+ "no_create",
+ "no_search"
+ ],
+ "hint": null,
+ "include": null,
+ "label": "Service Groups",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "memberservice_servicegroup",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ }
+ ],
+ "uuid_attribute": "ipauniqueid"
+ },
+ "hbacsvc": {
+ "attribute_members": {},
+ "container_dn": "cn=hbacservices,cn=hbac",
+ "default_attributes": [
+ "cn",
+ "description",
+ "memberindirect"
+ ],
+ "hidden_attributes": [
+ "objectclass",
+ "aci"
+ ],
+ "label": "Services",
+ "methods": [
+ "add",
+ "del",
+ "find",
+ "mod",
+ "show"
+ ],
+ "name": "hbacsvc",
+ "object_class": [
+ "ipaobject",
+ "ipahbacservice"
+ ],
+ "object_class_config": null,
+ "object_name": "hbacsvc",
+ "object_name_plural": "hbacsvcs",
+ "parent_object": "",
+ "primary_key": "cn",
+ "rdn_attribute": "",
+ "takes_params": [
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "service",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "HBAC Service",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Service name",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "cn",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": true,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "desc",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Description of service",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Description",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "description",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ }
+ ],
+ "uuid_attribute": "ipauniqueid"
+ },
+ "hbacsvcgroup": {
+ "attribute_members": {
+ "member": [
+ "hbacsvc"
+ ]
+ },
+ "container_dn": "cn=hbacservicegroups,cn=hbac",
+ "default_attributes": [
+ "cn",
+ "description",
+ "member"
+ ],
+ "hidden_attributes": [
+ "objectclass",
+ "aci"
+ ],
+ "label": "HBAC Service Groups",
+ "methods": [
+ "add",
+ "add_member",
+ "del",
+ "find",
+ "mod",
+ "remove_member",
+ "show"
+ ],
+ "name": "hbacsvcgroup",
+ "object_class": [
+ "ipaobject",
+ "ipahbacservicegroup"
+ ],
+ "object_class_config": null,
+ "object_name": "hbacsvcgroup",
+ "object_name_plural": "hbacsvcgroups",
+ "parent_object": "",
+ "primary_key": "cn",
+ "rdn_attribute": "",
+ "takes_params": [
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "name",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Service group name",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Service group name",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "cn",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": true,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "desc",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "HBAC service group description",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Description",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "description",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ }
+ ],
+ "uuid_attribute": "ipauniqueid"
+ },
+ "host": {
+ "attribute_members": {
+ "enrolledby": [
+ "user"
+ ],
+ "memberof": [
+ "hostgroup",
+ "netgroup",
+ "rolegroup"
+ ]
+ },
+ "container_dn": "cn=computers,cn=accounts",
+ "default_attributes": [
+ "fqdn",
+ "description",
+ "l",
+ "nshostlocation",
+ "krbprincipalname",
+ "nshardwareplatform",
+ "nsosversion",
+ "usercertificate",
+ "memberof",
+ "krblastpwdchange"
+ ],
+ "hidden_attributes": [
+ "objectclass",
+ "aci"
+ ],
+ "label": "Hosts",
+ "methods": [
+ "add",
+ "del",
+ "disable",
+ "find",
+ "mod",
+ "show"
+ ],
+ "name": "host",
+ "object_class": [
+ "ipaobject",
+ "nshost",
+ "ipahost",
+ "pkiuser",
+ "ipaservice"
+ ],
+ "object_class_config": null,
+ "object_name": "host",
+ "object_name_plural": "hosts",
+ "parent_object": "",
+ "primary_key": "fqdn",
+ "rdn_attribute": "",
+ "takes_params": [
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "hostname",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Host name",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Host name",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "fqdn",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": true,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "desc",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "A description of this host",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Description",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "description",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "locality",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Host locality (e.g. \"Baltimore, MD\")",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Locality",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "l",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "location",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Host location (e.g. \"Lab 2\")",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Location",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "nshostlocation",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "platform",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Host hardware platform (e.g. \"Lenovo T61\")",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Platform",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "nshardwareplatform",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "os",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Host operating system and version (e.g. \"Fedora 9\")",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Operating system",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "nsosversion",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "password",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Password used in bulk enrollment",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "User password",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "userpassword",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": true,
+ "class": "Flag",
+ "cli_name": "random",
+ "cli_short_name": null,
+ "default": false,
+ "doc": "Generate a random password to be used in bulk enrollment",
+ "exclude": null,
+ "falsehoods": [
+ 0,
+ "0",
+ "false"
+ ],
+ "flags": [
+ "no_search"
+ ],
+ "hint": null,
+ "include": null,
+ "label": "<random>",
+ "multivalue": false,
+ "name": "random",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "truths": [
+ "1",
+ 1,
+ "true"
+ ],
+ "type": "bool"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "randompassword",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Random password",
+ "exclude": null,
+ "flags": [
+ "no_update",
+ "no_create",
+ "no_search"
+ ],
+ "hint": null,
+ "include": null,
+ "label": "Random password",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "randompassword",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Bytes",
+ "cli_name": "certificate",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Base-64 encoded server certificate",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Certificate",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "usercertificate",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "str"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "krbprincipalname",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Principal name",
+ "exclude": null,
+ "flags": [
+ "no_update",
+ "no_create",
+ "no_search"
+ ],
+ "hint": null,
+ "include": null,
+ "label": "Principal name",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "krbprincipalname",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ }
+ ],
+ "uuid_attribute": "ipauniqueid"
+ },
+ "hostgroup": {
+ "attribute_members": {
+ "member": [
+ "host",
+ "hostgroup"
+ ],
+ "memberindirect": [
+ "host",
+ "hostgroup"
+ ],
+ "memberof": [
+ "hostgroup"
+ ]
+ },
+ "container_dn": "cn=hostgroups,cn=accounts",
+ "default_attributes": [
+ "cn",
+ "description",
+ "member",
+ "memberof",
+ "memberindirect"
+ ],
+ "hidden_attributes": [
+ "objectclass",
+ "aci"
+ ],
+ "label": "Host Groups",
+ "methods": [
+ "add",
+ "add_member",
+ "del",
+ "find",
+ "mod",
+ "remove_member",
+ "show"
+ ],
+ "name": "hostgroup",
+ "object_class": [
+ "ipaobject",
+ "ipahostgroup"
+ ],
+ "object_class_config": null,
+ "object_name": "hostgroup",
+ "object_name_plural": "hostgroups",
+ "parent_object": "",
+ "primary_key": "cn",
+ "rdn_attribute": "",
+ "takes_params": [
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "name",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Name of host-group",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Host-group",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "cn",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": true,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "desc",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "A description of this host-group",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Description",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "description",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ }
+ ],
+ "uuid_attribute": "ipauniqueid"
+ },
+ "krbtpolicy": {
+ "attribute_members": {},
+ "container_dn": "cn=AYOUNG.BOSTON.DEVEL.REDHAT.COM,cn=kerberos",
+ "default_attributes": [
+ "krbmaxticketlife",
+ "krbmaxrenewableage"
+ ],
+ "hidden_attributes": [
+ "objectclass",
+ "aci"
+ ],
+ "label": "Kerberos Ticket Policy",
+ "methods": [
+ "mod",
+ "reset",
+ "show"
+ ],
+ "name": "krbtpolicy",
+ "object_class": [],
+ "object_class_config": null,
+ "object_name": "kerberos ticket policy settings",
+ "object_name_plural": "entries",
+ "parent_object": "",
+ "primary_key": "uid",
+ "rdn_attribute": "",
+ "takes_params": [
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "user",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Manage ticket policy for specific user",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "User name",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "uid",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": true,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Int",
+ "cli_name": "maxlife",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Maximum ticket life (seconds)",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Max life",
+ "maxvalue": null,
+ "minvalue": null,
+ "multivalue": false,
+ "name": "krbmaxticketlife",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "int"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Int",
+ "cli_name": "maxrenew",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Maximum renewable age (seconds)",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Max renew",
+ "maxvalue": null,
+ "minvalue": null,
+ "multivalue": false,
+ "name": "krbmaxrenewableage",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "int"
+ }
+ ],
+ "uuid_attribute": ""
+ },
+ "netgroup": {
+ "attribute_members": {
+ "member": [
+ "netgroup"
+ ],
+ "memberhost": [
+ "host",
+ "hostgroup"
+ ],
+ "memberindirect": [
+ "netgroup"
+ ],
+ "memberof": [
+ "netgroup"
+ ],
+ "memberuser": [
+ "user",
+ "group"
+ ]
+ },
+ "container_dn": "cn=ng,cn=alt",
+ "default_attributes": [
+ "cn",
+ "description",
+ "memberof",
+ "externalhost",
+ "nisdomainname",
+ "memberuser",
+ "memberhost",
+ "member",
+ "memberindirect",
+ "usercategory",
+ "hostcategory"
+ ],
+ "hidden_attributes": [
+ "objectclass",
+ "aci"
+ ],
+ "label": "Net Groups",
+ "methods": [
+ "add",
+ "add_member",
+ "del",
+ "find",
+ "mod",
+ "remove_member",
+ "show"
+ ],
+ "name": "netgroup",
+ "object_class": [
+ "ipaobject",
+ "ipaassociation",
+ "ipanisnetgroup"
+ ],
+ "object_class_config": null,
+ "object_name": "netgroup",
+ "object_name_plural": "netgroups",
+ "parent_object": "",
+ "primary_key": "cn",
+ "rdn_attribute": "ipauniqueid",
+ "takes_params": [
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "name",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Netgroup name",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Netgroup name",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "cn",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": true,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "desc",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Netgroup description",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Description",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "description",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "nisdomain",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "NIS domain name",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "NIS domain name",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "nisdomainname",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "uuid",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "IPA unique ID",
+ "exclude": null,
+ "flags": [
+ "no_update",
+ "no_create"
+ ],
+ "hint": null,
+ "include": null,
+ "label": "IPA unique ID",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "ipauniqueid",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "StrEnum",
+ "cli_name": "usercat",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "User category the rule applies to",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "User category",
+ "multivalue": false,
+ "name": "usercategory",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode",
+ "values": [
+ "all"
+ ]
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "StrEnum",
+ "cli_name": "hostcat",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Host category the rule applies to",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Host category",
+ "multivalue": false,
+ "name": "hostcategory",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode",
+ "values": [
+ "all"
+ ]
+ }
+ ],
+ "uuid_attribute": "ipauniqueid"
+ },
+ "pwpolicy": {
+ "attribute_members": {},
+ "container_dn": "cn=AYOUNG.BOSTON.DEVEL.REDHAT.COM,cn=kerberos",
+ "default_attributes": [
+ "cn",
+ "cospriority",
+ "krbmaxpwdlife",
+ "krbminpwdlife",
+ "krbpwdhistorylength",
+ "krbpwdmindiffchars",
+ "krbpwdminlength",
+ "krbpwdmaxfailure",
+ "krbpwdfailurecountinterval",
+ "krbpwdlockoutduration"
+ ],
+ "hidden_attributes": [
+ "objectclass",
+ "aci"
+ ],
+ "label": "Password Policy",
+ "methods": [
+ "add",
+ "del",
+ "find",
+ "mod",
+ "show"
+ ],
+ "name": "pwpolicy",
+ "object_class": [
+ "top",
+ "nscontainer",
+ "krbpwdpolicy"
+ ],
+ "object_class_config": null,
+ "object_name": "password policy",
+ "object_name_plural": "password policies",
+ "parent_object": "",
+ "primary_key": "cn",
+ "rdn_attribute": "",
+ "takes_params": [
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "group",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Manage password policy for specific group",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Group",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "cn",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": true,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Int",
+ "cli_name": "maxlife",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Maximum password lifetime (in days)",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Max lifetime (days)",
+ "maxvalue": null,
+ "minvalue": 0,
+ "multivalue": false,
+ "name": "krbmaxpwdlife",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "int"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Int",
+ "cli_name": "minlife",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Minimum password lifetime (in hours)",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Min lifetime (hours)",
+ "maxvalue": null,
+ "minvalue": 0,
+ "multivalue": false,
+ "name": "krbminpwdlife",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "int"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Int",
+ "cli_name": "history",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Password history size",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "History size",
+ "maxvalue": null,
+ "minvalue": 0,
+ "multivalue": false,
+ "name": "krbpwdhistorylength",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "int"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Int",
+ "cli_name": "minclasses",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Minimum number of character classes",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Character classes",
+ "maxvalue": 5,
+ "minvalue": 0,
+ "multivalue": false,
+ "name": "krbpwdmindiffchars",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "int"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Int",
+ "cli_name": "minlength",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Minimum length of password",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Min length",
+ "maxvalue": null,
+ "minvalue": 0,
+ "multivalue": false,
+ "name": "krbpwdminlength",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "int"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Int",
+ "cli_name": "priority",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Priority of the policy (higher number means lower priority",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Priority",
+ "maxvalue": null,
+ "minvalue": 0,
+ "multivalue": false,
+ "name": "cospriority",
+ "primary_key": false,
+ "query": false,
+ "required": true,
+ "type": "int"
+ }
+ ],
+ "uuid_attribute": ""
+ },
+ "rolegroup": {
+ "attribute_members": {
+ "member": [
+ "user",
+ "group",
+ "host",
+ "hostgroup"
+ ],
+ "memberindirect": [
+ "user",
+ "group",
+ "host",
+ "hostgroup"
+ ],
+ "memberof": [
+ "taskgroup"
+ ]
+ },
+ "container_dn": "cn=rolegroups,cn=accounts",
+ "default_attributes": [
+ "cn",
+ "description",
+ "member",
+ "memberof",
+ "memberindirect"
+ ],
+ "hidden_attributes": [
+ "objectclass",
+ "aci"
+ ],
+ "label": "Role Groups",
+ "methods": [
+ "add",
+ "add_member",
+ "del",
+ "find",
+ "mod",
+ "remove_member",
+ "show"
+ ],
+ "name": "rolegroup",
+ "object_class": [
+ "groupofnames",
+ "nestedgroup"
+ ],
+ "object_class_config": null,
+ "object_name": "rolegroup",
+ "object_name_plural": "rolegroups",
+ "parent_object": "",
+ "primary_key": "cn",
+ "rdn_attribute": "",
+ "takes_params": [
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "name",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Role-group name",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Role-group name",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "cn",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": true,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "desc",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "A description of this role-group",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Description",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "description",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ }
+ ],
+ "uuid_attribute": ""
+ },
+ "service": {
+ "attribute_members": {
+ "managedby": [
+ "host"
+ ]
+ },
+ "container_dn": "cn=services,cn=accounts",
+ "default_attributes": [
+ "krbprincipalname",
+ "usercertificate",
+ "managedby",
+ "krblastpwdchange"
+ ],
+ "hidden_attributes": [
+ "objectclass",
+ "aci"
+ ],
+ "label": "Services",
+ "methods": [
+ "add",
+ "add_host",
+ "del",
+ "disable",
+ "find",
+ "mod",
+ "remove_host",
+ "show"
+ ],
+ "name": "service",
+ "object_class": [
+ "krbprincipal",
+ "krbprincipalaux",
+ "krbticketpolicyaux",
+ "ipaobject",
+ "ipaservice",
+ "pkiuser"
+ ],
+ "object_class_config": null,
+ "object_name": "service",
+ "object_name_plural": "services",
+ "parent_object": "",
+ "primary_key": "krbprincipalname",
+ "rdn_attribute": "",
+ "takes_params": [
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "principal",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Service principal",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Principal",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "krbprincipalname",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": true,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Bytes",
+ "cli_name": "certificate",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Base-64 encoded server certificate",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Certificate",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "usercertificate",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "str"
+ }
+ ],
+ "uuid_attribute": "ipauniqueid"
+ },
+ "sudocmd": {
+ "attribute_members": {},
+ "container_dn": "cn=sudocmds,cn=sudo",
+ "default_attributes": [
+ "sudocmd",
+ "description"
+ ],
+ "hidden_attributes": [
+ "objectclass",
+ "aci"
+ ],
+ "label": "SudoCmds",
+ "methods": [
+ "add",
+ "del",
+ "find",
+ "mod",
+ "show"
+ ],
+ "name": "sudocmd",
+ "object_class": [
+ "ipaobject",
+ "ipasudocmd"
+ ],
+ "object_class_config": null,
+ "object_name": "sudocmd",
+ "object_name_plural": "sudocmds",
+ "parent_object": "",
+ "primary_key": "sudocmd",
+ "rdn_attribute": "",
+ "takes_params": [
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "command",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Sudo Command",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Sudo Command",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "sudocmd",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": true,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "desc",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "A description of this command",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Description",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "description",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ }
+ ],
+ "uuid_attribute": "ipauniqueid"
+ },
+ "sudocmdgroup": {
+ "attribute_members": {
+ "member": [
+ "sudocmd",
+ "sudocmdgroup"
+ ],
+ "memberindirect": [
+ "sudocmd",
+ "sudocmdgroup"
+ ],
+ "memberof": [
+ "sudocmdgroup"
+ ]
+ },
+ "container_dn": "cn=sudocmdgroups,cn=sudo",
+ "default_attributes": [
+ "cn",
+ "description",
+ "member",
+ "memberof",
+ "memberindirect"
+ ],
+ "hidden_attributes": [
+ "objectclass",
+ "aci"
+ ],
+ "label": "Sudo Command Groups",
+ "methods": [
+ "add",
+ "add_member",
+ "del",
+ "find",
+ "mod",
+ "remove_member",
+ "show"
+ ],
+ "name": "sudocmdgroup",
+ "object_class": [
+ "ipaobject",
+ "ipasudocmdgrp"
+ ],
+ "object_class_config": null,
+ "object_name": "sudocmdgroup",
+ "object_name_plural": "sudocmdgroups",
+ "parent_object": "",
+ "primary_key": "cn",
+ "rdn_attribute": "",
+ "takes_params": [
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "name",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Sudo Command Group name",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Sudo Command Group name",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "cn",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": true,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "desc",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Group description",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Description",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "description",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "membercmd_sudocmd",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Commands",
+ "exclude": null,
+ "flags": [
+ "no_update",
+ "no_create",
+ "no_search"
+ ],
+ "hint": null,
+ "include": null,
+ "label": "Commands",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "membercmd_sudocmd",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "membercmd_sudocmdgroup",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Sudo Command Groups",
+ "exclude": null,
+ "flags": [
+ "no_update",
+ "no_create",
+ "no_search"
+ ],
+ "hint": null,
+ "include": null,
+ "label": "Sudo Command Groups",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "membercmd_sudocmdgroup",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ }
+ ],
+ "uuid_attribute": "ipauniqueid"
+ },
+ "sudorule": {
+ "attribute_members": {
+ "memberallowcmd": [
+ "sudocmd",
+ "sudocmdgroup"
+ ],
+ "memberdenycmd": [
+ "sudocmd",
+ "sudocmdgroup"
+ ],
+ "memberhost": [
+ "host",
+ "hostgroup"
+ ],
+ "memberuser": [
+ "user",
+ "group"
+ ]
+ },
+ "container_dn": "cn=sudorules,cn=sudo",
+ "default_attributes": [
+ "cn",
+ "description"
+ ],
+ "hidden_attributes": [
+ "objectclass",
+ "aci"
+ ],
+ "label": "SudoRule",
+ "methods": [
+ "add",
+ "add_allow_command",
+ "add_deny_command",
+ "add_host",
+ "add_user",
+ "del",
+ "find",
+ "mod",
+ "remove_allow_command",
+ "remove_deny_command",
+ "remove_host",
+ "remove_user",
+ "show"
+ ],
+ "name": "sudorule",
+ "object_class": [
+ "ipaassociation",
+ "ipasudorule"
+ ],
+ "object_class_config": null,
+ "object_name": "Sudo Rule",
+ "object_name_plural": "Sudo Rules",
+ "parent_object": "",
+ "primary_key": "cn",
+ "rdn_attribute": "ipauniqueid",
+ "takes_params": [
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "name",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Rule name",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Rule name",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "cn",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": true,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "desc",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Description",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Description",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "description",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "StrEnum",
+ "cli_name": "cmdcat",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Command category the rule applies to",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Command category",
+ "multivalue": false,
+ "name": "cmdcategory",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode",
+ "values": [
+ "all"
+ ]
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "memberuser_user",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Users",
+ "exclude": null,
+ "flags": [
+ "no_update",
+ "no_create",
+ "no_search"
+ ],
+ "hint": null,
+ "include": null,
+ "label": "Users",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "memberuser_user",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "memberhost_host",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Hosts",
+ "exclude": null,
+ "flags": [
+ "no_update",
+ "no_create",
+ "no_search"
+ ],
+ "hint": null,
+ "include": null,
+ "label": "Hosts",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "memberhost_host",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "memberhost_hostgroup",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Host Groups",
+ "exclude": null,
+ "flags": [
+ "no_update",
+ "no_create",
+ "no_search"
+ ],
+ "hint": null,
+ "include": null,
+ "label": "Host Groups",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "memberhost_hostgroup",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "memberallowcmd_sudocmd",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Sudo Allow Commands",
+ "exclude": null,
+ "flags": [
+ "no_update",
+ "no_create",
+ "no_search"
+ ],
+ "hint": null,
+ "include": null,
+ "label": "Sudo Allow Commands",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "memberallowcmd_sudocmd",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "memberdenycmd_sudocmd",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Sudo Deny Commands",
+ "exclude": null,
+ "flags": [
+ "no_update",
+ "no_create",
+ "no_search"
+ ],
+ "hint": null,
+ "include": null,
+ "label": "Sudo Deny Commands",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "memberdenycmd_sudocmd",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "memberallowcmd_sudocmdgroup",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Sudo Command Groups",
+ "exclude": null,
+ "flags": [
+ "no_update",
+ "no_create",
+ "no_search"
+ ],
+ "hint": null,
+ "include": null,
+ "label": "Sudo Command Groups",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "memberallowcmd_sudocmdgroup",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "memberdenycmd_sudocmdgroup",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Sudo Command Groups",
+ "exclude": null,
+ "flags": [
+ "no_update",
+ "no_create",
+ "no_search"
+ ],
+ "hint": null,
+ "include": null,
+ "label": "Sudo Command Groups",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "memberdenycmd_sudocmdgroup",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ }
+ ],
+ "uuid_attribute": "ipauniqueid"
+ },
+ "taskgroup": {
+ "attribute_members": {
+ "member": [
+ "user",
+ "group",
+ "rolegroup"
+ ],
+ "memberindirect": [
+ "user",
+ "group",
+ "rolegroup"
+ ]
+ },
+ "container_dn": "cn=taskgroups,cn=accounts",
+ "default_attributes": [
+ "cn",
+ "description",
+ "member",
+ "memberof",
+ "memberindirect"
+ ],
+ "hidden_attributes": [
+ "objectclass",
+ "aci"
+ ],
+ "label": "Task Groups",
+ "methods": [
+ "add",
+ "add_member",
+ "del",
+ "find",
+ "mod",
+ "remove_member",
+ "show"
+ ],
+ "name": "taskgroup",
+ "object_class": [
+ "groupofnames"
+ ],
+ "object_class_config": null,
+ "object_name": "taskgroup",
+ "object_name_plural": "taskgroups",
+ "parent_object": "",
+ "primary_key": "cn",
+ "rdn_attribute": "",
+ "takes_params": [
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "name",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Task-group name",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Task-group name",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "cn",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": true,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "desc",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Task-group description",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Description",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "description",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ }
+ ],
+ "uuid_attribute": ""
+ },
+ "user": {
+ "attribute_members": {
+ "memberof": [
+ "group",
+ "netgroup",
+ "rolegroup",
+ "taskgroup"
+ ]
+ },
+ "container_dn": "cn=users,cn=accounts",
+ "default_attributes": [
+ "uid",
+ "givenname",
+ "sn",
+ "homedirectory",
+ "loginshell",
+ "ou",
+ "telephonenumber",
+ "title",
+ "memberof",
+ "nsaccountlock"
+ ],
+ "hidden_attributes": [
+ "objectclass",
+ "aci"
+ ],
+ "label": "Users",
+ "methods": [
+ "add",
+ "del",
+ "disable",
+ "enable",
+ "find",
+ "mod",
+ "show"
+ ],
+ "name": "user",
+ "object_class": [
+ "posixaccount"
+ ],
+ "object_class_config": "ipauserobjectclasses",
+ "object_name": "user",
+ "object_name_plural": "users",
+ "parent_object": "",
+ "primary_key": "uid",
+ "rdn_attribute": "",
+ "takes_params": [
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "login",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "User login",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "User login",
+ "length": null,
+ "maxlength": 33,
+ "minlength": null,
+ "multivalue": false,
+ "name": "uid",
+ "pattern": "^[a-zA-Z0-9_.][a-zA-Z0-9_.-]{0,30}[a-zA-Z0-9_.$-]?$",
+ "pattern_errmsg": "may only include letters, numbers, _, -, . and $",
+ "primary_key": true,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "first",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "First name",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "First name",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "givenname",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "last",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Last name",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Last name",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "sn",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": true,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "homedir",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Home directory",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Home directory",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "homedirectory",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": true,
+ "class": "Str",
+ "cli_name": "gecos",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "GECOS field",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "GECOS field",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "gecos",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "shell",
+ "cli_short_name": null,
+ "default": "/bin/sh",
+ "doc": "Login shell",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Login shell",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "loginshell",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": true,
+ "class": "Str",
+ "cli_name": "principal",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Kerberos principal",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Kerberos principal",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "krbprincipalname",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "email",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Email address",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Email address",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": true,
+ "name": "mail",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Password",
+ "cli_name": "password",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Prompt to set the user password",
+ "exclude": [
+ "webui"
+ ],
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Password",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "userpassword",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": true,
+ "class": "Int",
+ "cli_name": "uid",
+ "cli_short_name": null,
+ "default": 999,
+ "doc": "User ID Number (system will assign one if not provided)",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "UID",
+ "maxvalue": null,
+ "minvalue": null,
+ "multivalue": false,
+ "name": "uidnumber",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "int"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "street",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Street address",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Street address",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "street",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "phone",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Telephone Number",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Telephone Number",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": true,
+ "name": "telephonenumber",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "mobile",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Mobile Telephone Number",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Mobile Telephone Number",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": true,
+ "name": "mobile",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "pager",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Pager Number",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Pager Number",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": true,
+ "name": "pager",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "fax",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Fax Number",
+ "exclude": null,
+ "flags": [],
+ "hint": null,
+ "include": null,
+ "label": "Fax Number",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": true,
+ "name": "facsimiletelephonenumber",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Bool",
+ "cli_name": "nsaccountlock",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Account disabled",
+ "exclude": null,
+ "falsehoods": [
+ 0,
+ "0",
+ "false"
+ ],
+ "flags": [
+ "no_update",
+ "no_create",
+ "no_search"
+ ],
+ "hint": null,
+ "include": null,
+ "label": "Account disabled",
+ "multivalue": false,
+ "name": "nsaccountlock",
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "truths": [
+ "1",
+ 1,
+ "true"
+ ],
+ "type": "bool"
+ }
+ ],
+ "uuid_attribute": "ipauniqueid"
+ }
+ }
+ }
+}
diff --git a/install/ui/test/data/krbtpolicy_show.json b/install/ui/test/data/krbtpolicy_show.json
new file mode 100644
index 000000000..39882e14a
--- /dev/null
+++ b/install/ui/test/data/krbtpolicy_show.json
@@ -0,0 +1,78 @@
+{
+ "error": null,
+ "id": 6,
+ "result": {
+ "result": {
+ "aci": [
+ "(targetattr = \"krbMKey\")(version 3.0; acl \"No external access\"; deny (read,write,search,compare) userdn != \"ldap:///uid=kdc,cn=sysaccounts,cn=etc,dc=ipa14,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com\";)"
+ ],
+ "attributelevelrights": {
+ "aci": "rscwo",
+ "cn": "rscwo",
+ "krbadmservers": "rscwo",
+ "krbdefaultencsalttypes": "rscwo",
+ "krbkdcservers": "rscwo",
+ "krbldapservers": "rscwo",
+ "krbmaxrenewableage": "rscwo",
+ "krbmaxticketlife": "rscwo",
+ "krbmkey": "none",
+ "krbprinccontainerref": "rscwo",
+ "krbprincnamingattr": "rscwo",
+ "krbpwdpolicyreference": "rsc",
+ "krbpwdservers": "rscwo",
+ "krbsearchscope": "rscwo",
+ "krbsubtrees": "rscwo",
+ "krbsupportedencsalttypes": "rscwo",
+ "krbticketflags": "rsc",
+ "krbticketpolicyreference": "rsc",
+ "krbupenabled": "rsc",
+ "nsaccountlock": "rscwo",
+ "objectclass": "rscwo"
+ },
+ "cn": [
+ "IPA14.AYOUNG.BOSTON.DEVEL.REDHAT.COM"
+ ],
+ "dn": "cn=ipa14.ayoung.boston.devel.redhat.com,cn=kerberos,dc=ipa14,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "krbdefaultencsalttypes": [
+ "aes256-cts:special",
+ "aes128-cts:special",
+ "des3-hmac-sha1:special",
+ "arcfour-hmac:special"
+ ],
+ "krbmaxrenewableage": [
+ "604800"
+ ],
+ "krbmaxticketlife": [
+ "86400"
+ ],
+ "krbsearchscope": [
+ "2"
+ ],
+ "krbsubtrees": [
+ "dc=ipa14,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com"
+ ],
+ "krbsupportedencsalttypes": [
+ "aes256-cts:normal",
+ "aes256-cts:special",
+ "aes128-cts:normal",
+ "aes128-cts:special",
+ "des3-hmac-sha1:normal",
+ "des3-hmac-sha1:special",
+ "arcfour-hmac:normal",
+ "arcfour-hmac:special",
+ "des-hmac-sha1:normal",
+ "des-cbc-md5:normal",
+ "des-cbc-crc:normal",
+ "des-cbc-crc:v4",
+ "des-cbc-crc:afs3"
+ ],
+ "objectclass": [
+ "top",
+ "krbrealmcontainer",
+ "krbticketpolicyaux"
+ ]
+ },
+ "summary": null,
+ "value": ""
+ }
+} \ No newline at end of file
diff --git a/install/ui/test/data/netgroup_add.json b/install/ui/test/data/netgroup_add.json
new file mode 100644
index 000000000..989bb5db0
--- /dev/null
+++ b/install/ui/test/data/netgroup_add.json
@@ -0,0 +1,28 @@
+{
+ "error": null,
+ "id": 17,
+ "result": {
+ "result": {
+ "cn": [
+ "butterfly_net"
+ ],
+ "description": [
+ "Butterfly Networks"
+ ],
+ "dn": "ipauniqueid=b16f7240-b43a-11df-89fa-525400674dcd,cn=ng,cn=alt,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "ipauniqueid": [
+ "b16f7240-b43a-11df-89fa-525400674dcd"
+ ],
+ "nisdomainname": [
+ "ayoung.boston.devel.redhat.com"
+ ],
+ "objectclass": [
+ "ipaobject",
+ "ipaassociation",
+ "ipanisnetgroup"
+ ]
+ },
+ "summary": null,
+ "value": "butterfly_net"
+ }
+} \ No newline at end of file
diff --git a/install/ui/test/data/netgroup_add_member.json b/install/ui/test/data/netgroup_add_member.json
new file mode 100644
index 000000000..5fbae9e14
--- /dev/null
+++ b/install/ui/test/data/netgroup_add_member.json
@@ -0,0 +1,40 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "completed": 3,
+ "failed": {
+ "memberhost": {
+ "host": [],
+ "hostgroup": []
+ },
+ "memberuser": {
+ "group": [],
+ "user": []
+ }
+ },
+ "result": {
+ "cn": [
+ "net-live"
+ ],
+ "description": [
+ "live servers"
+ ],
+ "dn": "ipauniqueid=2e08b2c2-baac-11df-a0cf-525400674dcd,cn=ng,cn=alt,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "memberhost_host": [
+ "live3.pbs.org",
+ "live2.pbs.org",
+ "live1.pbs.org"
+ ],
+ "memberhost_hostgroup": [
+ "host-live"
+ ],
+ "memberuser_group": [
+ "muppets"
+ ],
+ "nisdomainname": [
+ "ayoung.boston.devel.redhat.com"
+ ]
+ }
+ }
+} \ No newline at end of file
diff --git a/install/ui/test/data/netgroup_find.json b/install/ui/test/data/netgroup_find.json
new file mode 100644
index 000000000..15626e0b9
--- /dev/null
+++ b/install/ui/test/data/netgroup_find.json
@@ -0,0 +1,56 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "count": 2,
+ "result": [
+ {
+ "cn": [
+ "net-stage"
+ ],
+ "description": [
+ "staging servers"
+ ],
+ "dn": "ipauniqueid=f6ee9f40-9456-11df-973b-00163e26b89e,cn=ng,cn=alt,dc=idm,dc=lab,dc=bos,dc=redhat,dc=com",
+ "memberhost": [],
+ "memberof": [],
+ "memberuser": [
+ "cn=muppets,cn=groups,cn=accounts,dc=idm,dc=lab,dc=bos,dc=redhat,dc=com"
+ ],
+ "memberuser_group": [
+ "muppets"
+ ],
+ "nisdomainname": [
+ "idm.lab.bos.redhat.com"
+ ]
+ },
+ {
+ "cn": [
+ "net-live"
+ ],
+ "description": [
+ "live servers"
+ ],
+ "dn": "ipauniqueid=f763e426-9456-11df-934d-00163e26b89e,cn=ng,cn=alt,dc=idm,dc=lab,dc=bos,dc=redhat,dc=com",
+ "memberhost": [
+ "cn=host-live,cn=hostgroups,cn=accounts,dc=idm,dc=lab,dc=bos,dc=redhat,dc=com"
+ ],
+ "memberhost_hostgroup": [
+ "host-live"
+ ],
+ "memberof": [],
+ "memberuser": [
+ "cn=muppets,cn=groups,cn=accounts,dc=idm,dc=lab,dc=bos,dc=redhat,dc=com"
+ ],
+ "memberuser_group": [
+ "muppets"
+ ],
+ "nisdomainname": [
+ "idm.lab.bos.redhat.com"
+ ]
+ }
+ ],
+ "summary": null,
+ "truncated": false
+ }
+} \ No newline at end of file
diff --git a/install/ui/test/data/netgroup_show.json b/install/ui/test/data/netgroup_show.json
new file mode 100644
index 000000000..aa77e8885
--- /dev/null
+++ b/install/ui/test/data/netgroup_show.json
@@ -0,0 +1,38 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "result": {
+ "cn": [
+ "net-live"
+ ],
+ "description": [
+ "live servers"
+ ],
+ "dn": "ipauniqueid=2e08b2c2-baac-11df-a0cf-525400674dcd,cn=ng,cn=alt,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "memberhost_host": [
+ "live3.pbs.org",
+ "live2.pbs.org",
+ "live1.pbs.org",
+ "www1.pbs.org",
+ "www2.pbs.org",
+ "www3.pbs.org"
+ ],
+ "memberhost_hostgroup": [
+ "host-live"
+ ],
+ "memberuser_group": [
+ "muppets"
+ ],
+ "memberuser_user": [
+ "kfrog",
+ "count123"
+ ],
+ "nisdomainname": [
+ "ayoung.boston.devel.redhat.com"
+ ]
+ },
+ "summary": null,
+ "value": "net-live"
+ }
+} \ No newline at end of file
diff --git a/install/ui/test/data/permission_add.json b/install/ui/test/data/permission_add.json
new file mode 100644
index 000000000..9ea7b226b
--- /dev/null
+++ b/install/ui/test/data/permission_add.json
@@ -0,0 +1,26 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "result": {
+ "cn": [
+ "testperm"
+ ],
+ "description": [
+ "description"
+ ],
+ "dn": "cn=testperm,cn=permissions,cn=pbac,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "objectclass": [
+ "groupofnames",
+ "top"
+ ],
+ "permissions": [
+ "read",
+ "write"
+ ],
+ "targetgroup": "ipausers"
+ },
+ "summary": "Added permission \"testperm\"",
+ "value": "testperm"
+ }
+}
diff --git a/install/ui/test/data/permission_del b/install/ui/test/data/permission_del
new file mode 100644
index 000000000..c11368986
--- /dev/null
+++ b/install/ui/test/data/permission_del
@@ -0,0 +1,9 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "result": true,
+ "summary": "Deleted permission \"testperm\"",
+ "value": "testperm"
+ }
+} \ No newline at end of file
diff --git a/install/ui/test/data/permission_find.json b/install/ui/test/data/permission_find.json
new file mode 100644
index 000000000..cad5f0868
--- /dev/null
+++ b/install/ui/test/data/permission_find.json
@@ -0,0 +1,887 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "count": 47,
+ "result": [
+ {
+ "cn": [
+ "addusers"
+ ],
+ "description": [
+ "Add Users"
+ ],
+ "dn": "cn=addusers,cn=permissions,cn=pbac,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_privilege": [
+ "useradmin"
+ ],
+ "permissions": [
+ "add"
+ ],
+ "type": "user"
+ },
+ {
+ "attrs": [
+ "userPassword",
+ "krbPrincipalKey",
+ "sambaLMPassword",
+ "sambaNTPassword",
+ "passwordHistory"
+ ],
+ "cn": [
+ "change_password"
+ ],
+ "description": [
+ "Change a user password"
+ ],
+ "dn": "cn=change_password,cn=permissions,cn=pbac,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_privilege": [
+ "useradmin"
+ ],
+ "permissions": [
+ "write"
+ ]
+ },
+ {
+ "attrs": [
+ "member"
+ ],
+ "cn": [
+ "add_user_to_default_group"
+ ],
+ "description": [
+ "Add user to default group"
+ ],
+ "dn": "cn=add_user_to_default_group,cn=permissions,cn=pbac,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_privilege": [
+ "useradmin"
+ ],
+ "permissions": [
+ "write"
+ ],
+ "targetgroup": "ldap:///cn=ipausers,cn=groups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com"
+ },
+ {
+ "cn": [
+ "removeusers"
+ ],
+ "description": [
+ "Remove Users"
+ ],
+ "dn": "cn=removeusers,cn=permissions,cn=pbac,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_privilege": [
+ "useradmin"
+ ],
+ "permissions": [
+ "delete"
+ ],
+ "type": "user"
+ },
+ {
+ "attrs": [
+ "givenName",
+ "sn",
+ "cn",
+ "displayName",
+ "title",
+ "initials",
+ "loginShell",
+ "gecos",
+ "homePhone",
+ "mobile",
+ "pager",
+ "facsimileTelephoneNumber",
+ "telephoneNumber",
+ "street",
+ "roomNumber",
+ "l",
+ "st",
+ "postalCode",
+ "manager",
+ "secretary",
+ "description",
+ "carLicense",
+ "labeledURI",
+ "inetUserHTTPURL",
+ "seeAlso",
+ "employeeType",
+ "businessCategory",
+ "ou",
+ "mepManagedEntry",
+ "objectclass"
+ ],
+ "cn": [
+ "modifyusers"
+ ],
+ "description": [
+ "Modify Users"
+ ],
+ "dn": "cn=modifyusers,cn=permissions,cn=pbac,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_privilege": [
+ "useradmin"
+ ],
+ "permissions": [
+ "write"
+ ],
+ "type": "user"
+ },
+ {
+ "cn": [
+ "addgroups"
+ ],
+ "description": [
+ "Add Groups"
+ ],
+ "dn": "cn=addgroups,cn=permissions,cn=pbac,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_privilege": [
+ "groupadmin"
+ ],
+ "permissions": [
+ "add"
+ ],
+ "type": "group"
+ },
+ {
+ "cn": [
+ "removegroups"
+ ],
+ "description": [
+ "Remove Groups"
+ ],
+ "dn": "cn=removegroups,cn=permissions,cn=pbac,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_privilege": [
+ "groupadmin"
+ ],
+ "permissions": [
+ "delete"
+ ],
+ "type": "group"
+ },
+ {
+ "attrs": [
+ "cn",
+ "description",
+ "gidnumber",
+ "objectclass",
+ "mepManagedBy",
+ "ipaUniqueId"
+ ],
+ "cn": [
+ "modifygroups"
+ ],
+ "description": [
+ "Modify Groups"
+ ],
+ "dn": "cn=modifygroups,cn=permissions,cn=pbac,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_privilege": [
+ "groupadmin"
+ ],
+ "permissions": [
+ "write"
+ ],
+ "type": "group"
+ },
+ {
+ "attrs": [
+ "member"
+ ],
+ "cn": [
+ "modifygroupmembership"
+ ],
+ "description": [
+ "Modify Group membership"
+ ],
+ "dn": "cn=modifygroupmembership,cn=permissions,cn=pbac,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_privilege": [
+ "groupadmin"
+ ],
+ "permissions": [
+ "write"
+ ],
+ "type": "group"
+ },
+ {
+ "cn": [
+ "addhosts"
+ ],
+ "description": [
+ "Add Hosts"
+ ],
+ "dn": "cn=addhosts,cn=permissions,cn=pbac,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_privilege": [
+ "hostadmin"
+ ],
+ "permissions": [
+ "add"
+ ],
+ "type": "host"
+ },
+ {
+ "cn": [
+ "removehosts"
+ ],
+ "description": [
+ "Remove Hosts"
+ ],
+ "dn": "cn=removehosts,cn=permissions,cn=pbac,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_privilege": [
+ "hostadmin"
+ ],
+ "permissions": [
+ "delete"
+ ],
+ "type": "host"
+ },
+ {
+ "attrs": [
+ "description",
+ "l",
+ "nshostlocation",
+ "nshardwareplatform",
+ "nsosversion"
+ ],
+ "cn": [
+ "modifyhosts"
+ ],
+ "description": [
+ "Modify Hosts"
+ ],
+ "dn": "cn=modifyhosts,cn=permissions,cn=pbac,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_privilege": [
+ "hostadmin"
+ ],
+ "permissions": [
+ "write"
+ ],
+ "type": "host"
+ },
+ {
+ "cn": [
+ "addhostgroups"
+ ],
+ "description": [
+ "Add Hostgroups"
+ ],
+ "dn": "cn=addhostgroups,cn=permissions,cn=pbac,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_privilege": [
+ "hostgroupadmin"
+ ],
+ "permissions": [
+ "add"
+ ],
+ "type": "hostgroup"
+ },
+ {
+ "cn": [
+ "removehostgroups"
+ ],
+ "description": [
+ "Remove Hostgroups"
+ ],
+ "dn": "cn=removehostgroups,cn=permissions,cn=pbac,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_privilege": [
+ "hostgroupadmin"
+ ],
+ "permissions": [
+ "delete"
+ ],
+ "type": "hostgroup"
+ },
+ {
+ "attrs": [
+ "cn",
+ "description"
+ ],
+ "cn": [
+ "modifyhostgroups"
+ ],
+ "description": [
+ "Modify Hostgroups"
+ ],
+ "dn": "cn=modifyhostgroups,cn=permissions,cn=pbac,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_privilege": [
+ "hostgroupadmin"
+ ],
+ "permissions": [
+ "write"
+ ],
+ "type": "hostgroup"
+ },
+ {
+ "attrs": [
+ "member"
+ ],
+ "cn": [
+ "modifyhostgroupmembership"
+ ],
+ "description": [
+ "Modify Hostgroup membership"
+ ],
+ "dn": "cn=modifyhostgroupmembership,cn=permissions,cn=pbac,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_privilege": [
+ "hostgroupadmin"
+ ],
+ "permissions": [
+ "write"
+ ],
+ "type": "hostgroup"
+ },
+ {
+ "cn": [
+ "addservices"
+ ],
+ "description": [
+ "Add Services"
+ ],
+ "dn": "cn=addservices,cn=permissions,cn=pbac,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_privilege": [
+ "serviceadmin"
+ ],
+ "permissions": [
+ "add"
+ ],
+ "type": "service"
+ },
+ {
+ "cn": [
+ "removeservices"
+ ],
+ "description": [
+ "Remove Services"
+ ],
+ "dn": "cn=removeservices,cn=permissions,cn=pbac,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_privilege": [
+ "serviceadmin"
+ ],
+ "permissions": [
+ "delete"
+ ],
+ "type": "service"
+ },
+ {
+ "attrs": [
+ "userCertificate"
+ ],
+ "cn": [
+ "modifyservices"
+ ],
+ "description": [
+ "Modify Services"
+ ],
+ "dn": "cn=modifyservices,cn=permissions,cn=pbac,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_privilege": [
+ "serviceadmin"
+ ],
+ "permissions": [
+ "write"
+ ],
+ "type": "service"
+ },
+ {
+ "cn": [
+ "addroles"
+ ],
+ "description": [
+ "Add Roles"
+ ],
+ "dn": "cn=addroles,cn=permissions,cn=pbac,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_privilege": [
+ "delegationadmin"
+ ],
+ "permissions": [
+ "add"
+ ],
+ "subtree": "ldap:///cn=*,cn=roles,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com"
+ },
+ {
+ "cn": [
+ "removeroles"
+ ],
+ "description": [
+ "Remove Roles"
+ ],
+ "dn": "cn=removeroles,cn=permissions,cn=pbac,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_privilege": [
+ "delegationadmin"
+ ],
+ "permissions": [
+ "delete"
+ ],
+ "subtree": "ldap:///cn=*,cn=roles,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com"
+ },
+ {
+ "attrs": [
+ "cn",
+ "description"
+ ],
+ "cn": [
+ "modifyroles"
+ ],
+ "description": [
+ "Modify Roles"
+ ],
+ "dn": "cn=modifyroles,cn=permissions,cn=pbac,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_privilege": [
+ "delegationadmin"
+ ],
+ "permissions": [
+ "write"
+ ],
+ "subtree": "ldap:///cn=*,cn=roles,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com"
+ },
+ {
+ "attrs": [
+ "member"
+ ],
+ "cn": [
+ "modifyrolemembership"
+ ],
+ "description": [
+ "Modify Role Group membership"
+ ],
+ "dn": "cn=modifyrolemembership,cn=permissions,cn=pbac,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_privilege": [
+ "delegationadmin"
+ ],
+ "permissions": [
+ "write"
+ ],
+ "subtree": "ldap:///cn=*,cn=roles,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com"
+ },
+ {
+ "attrs": [
+ "member"
+ ],
+ "cn": [
+ "modifyprivilegemembership"
+ ],
+ "description": [
+ "Modify privilege membership"
+ ],
+ "dn": "cn=modifyprivilegemembership,cn=permissions,cn=pbac,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_privilege": [
+ "delegationadmin"
+ ],
+ "permissions": [
+ "write"
+ ],
+ "subtree": "ldap:///cn=*,cn=permissions,cn=pbac,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com"
+ },
+ {
+ "cn": [
+ "addautomountmaps"
+ ],
+ "description": [
+ "Add Automount maps"
+ ],
+ "dn": "cn=addautomountmaps,cn=permissions,cn=pbac,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_privilege": [
+ "automountadmin"
+ ],
+ "permissions": [
+ "add"
+ ],
+ "subtree": "ldap:///automountmapname=*,cn=automount,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com"
+ },
+ {
+ "cn": [
+ "removeautomountmaps"
+ ],
+ "description": [
+ "Remove Automount maps"
+ ],
+ "dn": "cn=removeautomountmaps,cn=permissions,cn=pbac,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_privilege": [
+ "automountadmin"
+ ],
+ "permissions": [
+ "delete"
+ ],
+ "subtree": "ldap:///automountmapname=*,cn=automount,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com"
+ },
+ {
+ "cn": [
+ "addautomountkeys"
+ ],
+ "description": [
+ "Add Automount keys"
+ ],
+ "dn": "cn=addautomountkeys,cn=permissions,cn=pbac,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_privilege": [
+ "automountadmin"
+ ],
+ "permissions": [
+ "add"
+ ],
+ "subtree": "ldap:///automountkey=*,automountmapname=*,cn=automount,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com"
+ },
+ {
+ "cn": [
+ "removeautomountkeys"
+ ],
+ "description": [
+ "Remove Automount keys"
+ ],
+ "dn": "cn=removeautomountkeys,cn=permissions,cn=pbac,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_privilege": [
+ "automountadmin"
+ ],
+ "permissions": [
+ "delete"
+ ],
+ "subtree": "ldap:///automountkey=*,automountmapname=*,cn=automount,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com"
+ },
+ {
+ "cn": [
+ "addnetgroups"
+ ],
+ "description": [
+ "Add netgroups"
+ ],
+ "dn": "cn=addnetgroups,cn=permissions,cn=pbac,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_privilege": [
+ "netgroupadmin"
+ ],
+ "permissions": [
+ "add"
+ ],
+ "type": "netgroup"
+ },
+ {
+ "cn": [
+ "removenetgroups"
+ ],
+ "description": [
+ "Remove netgroups"
+ ],
+ "dn": "cn=removenetgroups,cn=permissions,cn=pbac,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_privilege": [
+ "netgroupadmin"
+ ],
+ "permissions": [
+ "delete"
+ ],
+ "type": "netgroup"
+ },
+ {
+ "attrs": [
+ "description"
+ ],
+ "cn": [
+ "modifynetgroups"
+ ],
+ "description": [
+ "Modify netgroups"
+ ],
+ "dn": "cn=modifynetgroups,cn=permissions,cn=pbac,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_privilege": [
+ "netgroupadmin"
+ ],
+ "permissions": [
+ "write"
+ ],
+ "type": "netgroup"
+ },
+ {
+ "attrs": [
+ "memberhost",
+ "externalhost",
+ "memberuser",
+ "member"
+ ],
+ "cn": [
+ "modifynetgroupmembership"
+ ],
+ "description": [
+ "Modify netgroup membership"
+ ],
+ "dn": "cn=modifynetgroupmembership,cn=permissions,cn=pbac,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_privilege": [
+ "netgroupadmin"
+ ],
+ "permissions": [
+ "write"
+ ],
+ "type": "netgroup"
+ },
+ {
+ "attrs": [
+ "krbPrincipalKey",
+ "krbLastPwdChange"
+ ],
+ "cn": [
+ "manage_host_keytab"
+ ],
+ "description": [
+ "Manage host keytab"
+ ],
+ "dn": "cn=manage_host_keytab,cn=permissions,cn=pbac,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_privilege": [
+ "hostadmin",
+ "enrollhost"
+ ],
+ "permissions": [
+ "write"
+ ],
+ "type": "host"
+ },
+ {
+ "attrs": [
+ "krbPrincipalKey",
+ "krbLastPwdChange"
+ ],
+ "cn": [
+ "manage_service_keytab"
+ ],
+ "description": [
+ "Manage service keytab"
+ ],
+ "dn": "cn=manage_service_keytab,cn=permissions,cn=pbac,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_privilege": [
+ "serviceadmin",
+ "admins"
+ ],
+ "permissions": [
+ "write"
+ ],
+ "type": "service"
+ },
+ {
+ "attrs": [
+ "enrolledBy",
+ "objectClass"
+ ],
+ "cn": [
+ "enroll_host"
+ ],
+ "description": [
+ "Enroll a host"
+ ],
+ "dn": "cn=enroll_host,cn=permissions,cn=pbac,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_privilege": [
+ "hostadmin",
+ "enrollhost"
+ ],
+ "permissions": [
+ "write"
+ ],
+ "type": "host"
+ },
+ {
+ "cn": [
+ "managereplica"
+ ],
+ "description": [
+ "Manage Replication Agreements"
+ ],
+ "dn": "cn=managereplica,cn=permissions,cn=pbac,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_privilege": [
+ "replicaadmin"
+ ],
+ "memberindirect": [
+ "uid=admin,cn=users,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "cn=admins,cn=groups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com"
+ ]
+ },
+ {
+ "cn": [
+ "deletereplica"
+ ],
+ "description": [
+ "Delete Replication Agreements"
+ ],
+ "dn": "cn=deletereplica,cn=permissions,cn=pbac,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_privilege": [
+ "replicaadmin"
+ ],
+ "memberindirect": [
+ "uid=admin,cn=users,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "cn=admins,cn=groups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com"
+ ]
+ },
+ {
+ "cn": [
+ "addentitlements"
+ ],
+ "description": [
+ "Add Entitlements"
+ ],
+ "dn": "cn=addentitlements,cn=permissions,cn=pbac,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_privilege": [
+ "entitlementadmin"
+ ],
+ "permissions": [
+ "add"
+ ],
+ "subtree": "ldap:///ipauniqueid=*,cn=entitlements,cn=etc,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com"
+ },
+ {
+ "cn": [
+ "removeentitlements"
+ ],
+ "description": [
+ "Remove Entitlements"
+ ],
+ "dn": "cn=removeentitlements,cn=permissions,cn=pbac,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_privilege": [
+ "entitlementadmin"
+ ],
+ "permissions": [
+ "delete"
+ ],
+ "subtree": "ldap:///ipauniqueid=*,cn=entitlements,cn=etc,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com"
+ },
+ {
+ "attrs": [
+ "userCertificate"
+ ],
+ "cn": [
+ "modifyentitlements"
+ ],
+ "description": [
+ "Modify Entitlements"
+ ],
+ "dn": "cn=modifyentitlements,cn=permissions,cn=pbac,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_privilege": [
+ "entitlementadmin"
+ ],
+ "permissions": [
+ "write"
+ ],
+ "subtree": "ldap:///ipauniqueid=*,cn=entitlements,cn=etc,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com"
+ },
+ {
+ "attrs": [
+ "objectClass"
+ ],
+ "cn": [
+ "retrieve_certs"
+ ],
+ "description": [
+ "Retrieve Certificates from the CA"
+ ],
+ "dn": "cn=retrieve_certs,cn=permissions,cn=pbac,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_privilege": [
+ "certadmin"
+ ],
+ "permissions": [
+ "write"
+ ],
+ "subtree": "ldap:///cn=retrieve certificate,cn=virtual operations,cn=etc,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com"
+ },
+ {
+ "attrs": [
+ "objectClass"
+ ],
+ "cn": [
+ "request_certs"
+ ],
+ "description": [
+ "Request Certificates from the CA"
+ ],
+ "dn": "cn=request_certs,cn=permissions,cn=pbac,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_privilege": [
+ "certadmin"
+ ],
+ "permissions": [
+ "write"
+ ],
+ "subtree": "ldap:///cn=request certificate,cn=virtual operations,cn=etc,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com"
+ },
+ {
+ "attrs": [
+ "objectClass"
+ ],
+ "cn": [
+ "request_cert_different_host"
+ ],
+ "description": [
+ "Request Certificates from a different host"
+ ],
+ "dn": "cn=request_cert_different_host,cn=permissions,cn=pbac,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_privilege": [
+ "certadmin"
+ ],
+ "permissions": [
+ "write"
+ ],
+ "subtree": "ldap:///cn=request certificate different host,cn=virtual operations,cn=etc,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com"
+ },
+ {
+ "attrs": [
+ "objectClass"
+ ],
+ "cn": [
+ "certificate_status"
+ ],
+ "description": [
+ "Get Certificates status from the CA"
+ ],
+ "dn": "cn=certificate_status,cn=permissions,cn=pbac,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_privilege": [
+ "certadmin"
+ ],
+ "permissions": [
+ "write"
+ ],
+ "subtree": "ldap:///cn=certificate status,cn=virtual operations,cn=etc,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com"
+ },
+ {
+ "attrs": [
+ "objectClass"
+ ],
+ "cn": [
+ "revoke_certificate"
+ ],
+ "description": [
+ "Revoke Certificate"
+ ],
+ "dn": "cn=revoke_certificate,cn=permissions,cn=pbac,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_privilege": [
+ "certadmin"
+ ],
+ "permissions": [
+ "write"
+ ],
+ "subtree": "ldap:///cn=revoke certificate,cn=virtual operations,cn=etc,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com"
+ },
+ {
+ "attrs": [
+ "objectClass"
+ ],
+ "cn": [
+ "certificate_remove_hold"
+ ],
+ "description": [
+ "Certificate Remove Hold"
+ ],
+ "dn": "cn=certificate_remove_hold,cn=permissions,cn=pbac,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_privilege": [
+ "certadmin"
+ ],
+ "permissions": [
+ "write"
+ ],
+ "subtree": "ldap:///cn=certificate remove hold,cn=virtual operations,cn=etc,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com"
+ },
+ {
+ "cn": [
+ "update_dns"
+ ],
+ "description": [
+ "DNS Servers Updates"
+ ],
+ "dn": "cn=update_dns,cn=permissions,cn=pbac,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_privilege": [
+ "dnsadmin",
+ "dnsserver"
+ ],
+ "memberindirect": [
+ "krbprincipalname=dns/ipa.ayoung.boston.devel.redhat.com@ayoung.boston.devel.redhat.com,cn=services,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com"
+ ]
+ }
+ ],
+ "summary": "47 permissions matched",
+ "truncated": false
+ }
+}
diff --git a/install/ui/test/data/permission_show.json b/install/ui/test/data/permission_show.json
new file mode 100644
index 000000000..d823061d5
--- /dev/null
+++ b/install/ui/test/data/permission_show.json
@@ -0,0 +1,41 @@
+{
+ "error": null,
+ "id": 6,
+ "result": {
+ "result": {
+ "attributelevelrights": {
+ "aci": "rscwo",
+ "businesscategory": "rscwo",
+ "cn": "rscwo",
+ "description": "rscwo",
+ "member": "rscwo",
+ "nsaccountlock": "rscwo",
+ "o": "rscwo",
+ "objectclass": "rscwo",
+ "ou": "rscwo",
+ "owner": "rscwo",
+ "seealso": "rscwo"
+ },
+ "cn": [
+ "addusers"
+ ],
+ "description": [
+ "Add Users"
+ ],
+ "dn": "cn=addusers,cn=permissions,cn=hbac,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member": [
+ "cn=useradmin,cn=privileges,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com"
+ ],
+ "objectclass": [
+ "top",
+ "groupofnames"
+ ],
+ "permissions": [
+ "add"
+ ],
+ "type": "user"
+ },
+ "summary": null,
+ "value": "addusers"
+ }
+}
diff --git a/install/ui/test/data/privilege_find.json b/install/ui/test/data/privilege_find.json
new file mode 100644
index 000000000..c48c4a0e8
--- /dev/null
+++ b/install/ui/test/data/privilege_find.json
@@ -0,0 +1,215 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "count": 14,
+ "result": [
+ {
+ "cn": [
+ "useradmin"
+ ],
+ "description": [
+ "User Administrators"
+ ],
+ "dn": "cn=useradmin,cn=privileges,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "memberof_permission": [
+ "addusers",
+ "change_password",
+ "add_user_to_default_group",
+ "removeusers",
+ "modifyusers"
+ ]
+ },
+ {
+ "cn": [
+ "groupadmin"
+ ],
+ "description": [
+ "Group Administrators"
+ ],
+ "dn": "cn=groupadmin,cn=privileges,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "memberof_permission": [
+ "addgroups",
+ "removegroups",
+ "modifygroups",
+ "modifygroupmembership"
+ ]
+ },
+ {
+ "cn": [
+ "hostadmin"
+ ],
+ "description": [
+ "Host Administrators"
+ ],
+ "dn": "cn=hostadmin,cn=privileges,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "memberof_permission": [
+ "addhosts",
+ "removehosts",
+ "modifyhosts",
+ "manage_host_keytab",
+ "enroll_host"
+ ]
+ },
+ {
+ "cn": [
+ "hostgroupadmin"
+ ],
+ "description": [
+ "Host Group Administrators"
+ ],
+ "dn": "cn=hostgroupadmin,cn=privileges,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "memberof_permission": [
+ "addhostgroups",
+ "removehostgroups",
+ "modifyhostgroups",
+ "modifyhostgroupmembership"
+ ]
+ },
+ {
+ "cn": [
+ "delegationadmin"
+ ],
+ "description": [
+ "Role administration"
+ ],
+ "dn": "cn=delegationadmin,cn=privileges,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "memberof_permission": [
+ "addroles",
+ "removeroles",
+ "modifyroles",
+ "modifyrolemembership",
+ "modifyprivilegemembership"
+ ]
+ },
+ {
+ "cn": [
+ "serviceadmin"
+ ],
+ "description": [
+ "Service Administrators"
+ ],
+ "dn": "cn=serviceadmin,cn=privileges,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "memberof_permission": [
+ "addservices",
+ "removeservices",
+ "modifyservices",
+ "manage_service_keytab"
+ ]
+ },
+ {
+ "cn": [
+ "automountadmin"
+ ],
+ "description": [
+ "Automount Administrators"
+ ],
+ "dn": "cn=automountadmin,cn=privileges,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "memberof_permission": [
+ "addautomountmaps",
+ "removeautomountmaps",
+ "addautomountkeys",
+ "removeautomountkeys"
+ ]
+ },
+ {
+ "cn": [
+ "netgroupadmin"
+ ],
+ "description": [
+ "Netgroups Administrators"
+ ],
+ "dn": "cn=netgroupadmin,cn=privileges,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "memberof_permission": [
+ "addnetgroups",
+ "removenetgroups",
+ "modifynetgroups",
+ "modifynetgroupmembership"
+ ]
+ },
+ {
+ "cn": [
+ "certadmin"
+ ],
+ "description": [
+ "Certificate Administrators"
+ ],
+ "dn": "cn=certadmin,cn=privileges,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "memberof_permission": [
+ "retrieve_certs",
+ "request_certs",
+ "request_cert_different_host",
+ "certificate_status",
+ "revoke_certificate",
+ "certificate_remove_hold"
+ ]
+ },
+ {
+ "cn": [
+ "replicaadmin"
+ ],
+ "description": [
+ "Replication Administrators"
+ ],
+ "dn": "cn=replicaadmin,cn=privileges,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "memberindirect": [
+ "uid=admin,cn=users,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com"
+ ],
+ "memberof_permission": [
+ "managereplica",
+ "deletereplica"
+ ]
+ },
+ {
+ "cn": [
+ "enrollhost"
+ ],
+ "description": [
+ "Host Enrollment"
+ ],
+ "dn": "cn=enrollhost,cn=privileges,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "memberof_permission": [
+ "manage_host_keytab",
+ "enroll_host"
+ ]
+ },
+ {
+ "cn": [
+ "entitlementadmin"
+ ],
+ "description": [
+ "Entitlement Administrators"
+ ],
+ "dn": "cn=entitlementadmin,cn=privileges,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "memberof_permission": [
+ "addentitlements",
+ "removeentitlements",
+ "modifyentitlements"
+ ]
+ },
+ {
+ "cn": [
+ "dnsadmin"
+ ],
+ "description": [
+ "DNS Administrators"
+ ],
+ "dn": "cn=dnsadmin,cn=privileges,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com"
+ },
+ {
+ "cn": [
+ "dnsserver"
+ ],
+ "description": [
+ "DNS Servers"
+ ],
+ "dn": "cn=dnsserver,cn=privileges,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "memberindirect": [
+ "krbprincipalname=dns/ipa.ayoung.boston.devel.redhat.com@ayoung.boston.devel.redhat.com,cn=services,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com"
+ ]
+ }
+ ],
+ "summary": "14 privileges matched",
+ "truncated": false
+ }
+} \ No newline at end of file
diff --git a/install/ui/test/data/privilege_show.json b/install/ui/test/data/privilege_show.json
new file mode 100644
index 000000000..7d9328aa0
--- /dev/null
+++ b/install/ui/test/data/privilege_show.json
@@ -0,0 +1,39 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "result": {
+ "attributelevelrights": {
+ "aci": "rscwo",
+ "businesscategory": "rscwo",
+ "cn": "rscwo",
+ "description": "rscwo",
+ "member": "rscwo",
+ "memberof": "rsc",
+ "nsaccountlock": "rscwo",
+ "o": "rscwo",
+ "objectclass": "rscwo",
+ "ou": "rscwo",
+ "owner": "rscwo",
+ "seealso": "rscwo"
+ },
+ "cn": [
+ "dnsserver"
+ ],
+ "description": [
+ "DNS Servers"
+ ],
+ "dn": "cn=dnsserver,cn=privileges,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "memberindirect": [
+ "krbprincipalname=dns/ipa.ayoung.boston.devel.redhat.com@ayoung.boston.devel.redhat.com,cn=services,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com"
+ ],
+ "objectclass": [
+ "top",
+ "groupofnames",
+ "nestedgroup"
+ ]
+ },
+ "summary": null,
+ "value": "dnsserver"
+ }
+} \ No newline at end of file
diff --git a/install/ui/test/data/pwpolicy_find.json b/install/ui/test/data/pwpolicy_find.json
new file mode 100644
index 000000000..629ebfc90
--- /dev/null
+++ b/install/ui/test/data/pwpolicy_find.json
@@ -0,0 +1,72 @@
+{
+ "error": null,
+ "id": 6,
+ "result": {
+ "count": 3,
+ "result": [
+ {
+ "cn": "GLOBAL",
+ "dn": "cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "krbmaxpwdlife": [
+ "90"
+ ],
+ "krbminpwdlife": [
+ "1"
+ ],
+ "krbpwdhistorylength": [
+ "0"
+ ],
+ "krbpwdmindiffchars": [
+ "0"
+ ],
+ "krbpwdminlength": [
+ "8"
+ ]
+ },
+ {
+ "cn": [
+ "testgroup12"
+ ],
+ "cospriority": [
+ "1"
+ ],
+ "dn": "cn=testgroup12,cn=ayoung.boston.devel.redhat.com,cn=kerberos,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "krbmaxpwdlife": [
+ "40"
+ ],
+ "krbminpwdlife": [
+ "50"
+ ],
+ "krbpwdhistorylength": [
+ "5"
+ ],
+ "krbpwdminlength": [
+ "6"
+ ]
+ },
+ {
+ "cn": [
+ "testgroup22"
+ ],
+ "cospriority": [
+ "2"
+ ],
+ "dn": "cn=testgroup22,cn=ayoung.boston.devel.redhat.com,cn=kerberos,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "krbmaxpwdlife": [
+ "60"
+ ],
+ "krbminpwdlife": [
+ "40"
+ ],
+ "krbpwdhistorylength": [
+ "8"
+ ],
+ "krbpwdminlength": [
+ "9"
+ ]
+ }
+ ],
+ "summary": null,
+ "truncated": false
+ }
+} \ No newline at end of file
diff --git a/install/ui/test/data/pwpolicy_mod.json b/install/ui/test/data/pwpolicy_mod.json
new file mode 100644
index 000000000..44d589519
--- /dev/null
+++ b/install/ui/test/data/pwpolicy_mod.json
@@ -0,0 +1,56 @@
+{
+ "error": null,
+ "id": 3,
+ "result": {
+ "result": {
+ "attributelevelrights": {
+ "aci": "rscwo",
+ "cn": "rscwo",
+ "krbmaxpwdlife": "rscwo",
+ "krbminpwdlife": "rscwo",
+ "krbpwdfailurecountinterval": "rscwo",
+ "krbpwdhistorylength": "rscwo",
+ "krbpwdlockoutduration": "rscwo",
+ "krbpwdmaxfailure": "rscwo",
+ "krbpwdmindiffchars": "rscwo",
+ "krbpwdminlength": "rscwo",
+ "nsaccountlock": "rscwo",
+ "objectclass": "rscwo"
+ },
+ "cn": [
+ "global_policy"
+ ],
+ "krbmaxpwdlife": [
+ "90"
+ ],
+ "krbminpwdlife": [
+ "1"
+ ],
+ "krbpwdfailurecountinterval": [
+ "60"
+ ],
+ "krbpwdhistorylength": [
+ "0"
+ ],
+ "krbpwdlockoutduration": [
+ "10"
+ ],
+ "krbpwdmaxfailure": [
+ "3"
+ ],
+ "krbpwdmindiffchars": [
+ "0"
+ ],
+ "krbpwdminlength": [
+ "8"
+ ],
+ "objectclass": [
+ "top",
+ "nsContainer",
+ "krbPwdPolicy"
+ ]
+ },
+ "summary": null,
+ "value": "global_policy"
+ }
+} \ No newline at end of file
diff --git a/install/ui/test/data/pwpolicy_show.json b/install/ui/test/data/pwpolicy_show.json
new file mode 100644
index 000000000..e91f52efa
--- /dev/null
+++ b/install/ui/test/data/pwpolicy_show.json
@@ -0,0 +1,57 @@
+{
+ "error": null,
+ "id": 8,
+ "result": {
+ "result": {
+ "attributelevelrights": {
+ "aci": "rscwo",
+ "cn": "rscwo",
+ "krbmaxpwdlife": "rscwo",
+ "krbminpwdlife": "rscwo",
+ "krbpwdfailurecountinterval": "rscwo",
+ "krbpwdhistorylength": "rscwo",
+ "krbpwdlockoutduration": "rscwo",
+ "krbpwdmaxfailure": "rscwo",
+ "krbpwdmindiffchars": "rscwo",
+ "krbpwdminlength": "rscwo",
+ "nsaccountlock": "rscwo",
+ "objectclass": "rscwo"
+ },
+ "cn": [
+ "global_policy"
+ ],
+ "dn": "cn=global_policy,cn=ipa14.ayoung.boston.devel.redhat.com,cn=kerberos,dc=ipa14,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "krbmaxpwdlife": [
+ "90"
+ ],
+ "krbminpwdlife": [
+ "1"
+ ],
+ "krbpwdfailurecountinterval": [
+ "60"
+ ],
+ "krbpwdhistorylength": [
+ "0"
+ ],
+ "krbpwdlockoutduration": [
+ "10"
+ ],
+ "krbpwdmaxfailure": [
+ "3"
+ ],
+ "krbpwdmindiffchars": [
+ "0"
+ ],
+ "krbpwdminlength": [
+ "8"
+ ],
+ "objectclass": [
+ "top",
+ "nsContainer",
+ "krbPwdPolicy"
+ ]
+ },
+ "summary": null,
+ "value": "global_policy"
+ }
+} \ No newline at end of file
diff --git a/install/ui/test/data/role_find.json b/install/ui/test/data/role_find.json
new file mode 100644
index 000000000..af013803c
--- /dev/null
+++ b/install/ui/test/data/role_find.json
@@ -0,0 +1,20 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "count": 1,
+ "result": [
+ {
+ "cn": [
+ "helpdesk"
+ ],
+ "description": [
+ "Helpdesk"
+ ],
+ "dn": "cn=helpdesk,cn=roles,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com"
+ }
+ ],
+ "summary": "1 role matched",
+ "truncated": false
+ }
+} \ No newline at end of file
diff --git a/install/ui/test/data/role_show.json b/install/ui/test/data/role_show.json
new file mode 100644
index 000000000..9ad8dd689
--- /dev/null
+++ b/install/ui/test/data/role_show.json
@@ -0,0 +1,36 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "result": {
+ "attributelevelrights": {
+ "aci": "rscwo",
+ "businesscategory": "rscwo",
+ "cn": "rscwo",
+ "description": "rscwo",
+ "member": "rscwo",
+ "memberof": "rsc",
+ "nsaccountlock": "rscwo",
+ "o": "rscwo",
+ "objectclass": "rscwo",
+ "ou": "rscwo",
+ "owner": "rscwo",
+ "seealso": "rscwo"
+ },
+ "cn": [
+ "helpdesk"
+ ],
+ "description": [
+ "Helpdesk"
+ ],
+ "dn": "cn=helpdesk,cn=roles,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "objectclass": [
+ "top",
+ "groupofnames",
+ "nestedgroup"
+ ]
+ },
+ "summary": null,
+ "value": "helpdesk"
+ }
+} \ No newline at end of file
diff --git a/install/ui/test/data/rolegroup_add.json b/install/ui/test/data/rolegroup_add.json
new file mode 100644
index 000000000..54e2c2832
--- /dev/null
+++ b/install/ui/test/data/rolegroup_add.json
@@ -0,0 +1,22 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "result": {
+ "cn": [
+ "test"
+ ],
+ "description": [
+ "Test role"
+ ],
+ "dn": "cn=test,cn=rolegroups,cn=accounts,dc=dev,dc=example,dc=com",
+ "objectclass": [
+ "groupofnames",
+ "nestedgroup",
+ "top"
+ ]
+ },
+ "summary": "Added rolegroup \"test\"",
+ "value": "test"
+ }
+}
diff --git a/install/ui/test/data/rolegroup_add_member.json b/install/ui/test/data/rolegroup_add_member.json
new file mode 100644
index 000000000..e68ecc28b
--- /dev/null
+++ b/install/ui/test/data/rolegroup_add_member.json
@@ -0,0 +1,27 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "completed": 1,
+ "failed": {
+ "member": {
+ "group": [],
+ "host": [],
+ "hostgroup": [],
+ "user": []
+ }
+ },
+ "result": {
+ "cn": [
+ "test"
+ ],
+ "description": [
+ "Test role"
+ ],
+ "dn": "cn=test,cn=rolegroups,cn=accounts,dc=dev,dc=example,dc=com",
+ "member_user": [
+ "admin"
+ ]
+ }
+ }
+}
diff --git a/install/ui/test/data/rolegroup_del.json b/install/ui/test/data/rolegroup_del.json
new file mode 100644
index 000000000..8af1e6306
--- /dev/null
+++ b/install/ui/test/data/rolegroup_del.json
@@ -0,0 +1,9 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "result": true,
+ "summary": "Deleted rolegroup \"test\"",
+ "value": "test"
+ }
+}
diff --git a/install/ui/test/data/rolegroup_find.json b/install/ui/test/data/rolegroup_find.json
new file mode 100644
index 000000000..8ed2a76b7
--- /dev/null
+++ b/install/ui/test/data/rolegroup_find.json
@@ -0,0 +1,185 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "count": 15,
+ "result": [
+ {
+ "cn": [
+ "helpdesk"
+ ],
+ "description": [
+ "Helpdesk"
+ ],
+ "dn": "cn=helpdesk,cn=rolegroups,cn=accounts,dc=dev,dc=example,dc=com",
+ "member_user": [
+ "edewata"
+ ]
+ },
+ {
+ "cn": [
+ "useradmin"
+ ],
+ "description": [
+ "User Administrators"
+ ],
+ "dn": "cn=useradmin,cn=rolegroups,cn=accounts,dc=dev,dc=example,dc=com"
+ },
+ {
+ "cn": [
+ "groupadmin"
+ ],
+ "description": [
+ "Group Administrators"
+ ],
+ "dn": "cn=groupadmin,cn=rolegroups,cn=accounts,dc=dev,dc=example,dc=com"
+ },
+ {
+ "cn": [
+ "hostadmin"
+ ],
+ "description": [
+ "Host Administrators"
+ ],
+ "dn": "cn=hostadmin,cn=rolegroups,cn=accounts,dc=dev,dc=example,dc=com",
+ "memberof_taskgroup": [
+ "addhosts",
+ "removehosts",
+ "modifyhosts",
+ "manage_host_keytab",
+ "enroll_host"
+ ]
+ },
+ {
+ "cn": [
+ "hostgroupadmin"
+ ],
+ "description": [
+ "Host Group Administrators"
+ ],
+ "dn": "cn=hostgroupadmin,cn=rolegroups,cn=accounts,dc=dev,dc=example,dc=com"
+ },
+ {
+ "cn": [
+ "delegationadmin"
+ ],
+ "description": [
+ "Role administration"
+ ],
+ "dn": "cn=delegationadmin,cn=rolegroups,cn=accounts,dc=dev,dc=example,dc=com"
+ },
+ {
+ "cn": [
+ "serviceadmin"
+ ],
+ "description": [
+ "Service Administrators"
+ ],
+ "dn": "cn=serviceadmin,cn=rolegroups,cn=accounts,dc=dev,dc=example,dc=com",
+ "memberof_taskgroup": [
+ "addservices",
+ "removeservices",
+ "modifyservices"
+ ]
+ },
+ {
+ "cn": [
+ "automountadmin"
+ ],
+ "description": [
+ "Automount Administrators"
+ ],
+ "dn": "cn=automountadmin,cn=rolegroups,cn=accounts,dc=dev,dc=example,dc=com"
+ },
+ {
+ "cn": [
+ "netgroupadmin"
+ ],
+ "description": [
+ "Netgroups Administrators"
+ ],
+ "dn": "cn=netgroupadmin,cn=rolegroups,cn=accounts,dc=dev,dc=example,dc=com"
+ },
+ {
+ "cn": [
+ "dnsadmin"
+ ],
+ "description": [
+ "DNS Administrators"
+ ],
+ "dn": "cn=dnsadmin,cn=rolegroups,cn=accounts,dc=dev,dc=example,dc=com"
+ },
+ {
+ "cn": [
+ "dnsserver"
+ ],
+ "description": [
+ "DNS Servers"
+ ],
+ "dn": "cn=dnsserver,cn=rolegroups,cn=accounts,dc=dev,dc=example,dc=com"
+ },
+ {
+ "cn": [
+ "certadmin"
+ ],
+ "description": [
+ "Certificate Administrators"
+ ],
+ "dn": "cn=certadmin,cn=rolegroups,cn=accounts,dc=dev,dc=example,dc=com",
+ "memberof_taskgroup": [
+ "retrieve_certs",
+ "request_certs",
+ "request_cert_different_host",
+ "certificate_status",
+ "revoke_certificate",
+ "certificate_remove_hold"
+ ]
+ },
+ {
+ "cn": [
+ "replicaadmin"
+ ],
+ "description": [
+ "Replication Administrators"
+ ],
+ "dn": "cn=replicaadmin,cn=rolegroups,cn=accounts,dc=dev,dc=example,dc=com",
+ "member_user": [
+ "admin"
+ ],
+ "memberof_taskgroup": [
+ "managereplica",
+ "deletereplica"
+ ]
+ },
+ {
+ "cn": [
+ "enrollhost"
+ ],
+ "description": [
+ "Host Enrollment"
+ ],
+ "dn": "cn=enrollhost,cn=rolegroups,cn=accounts,dc=dev,dc=example,dc=com",
+ "memberof_taskgroup": [
+ "manage_host_keytab",
+ "enroll_host"
+ ]
+ },
+ {
+ "cn": [
+ "entitlementadmin"
+ ],
+ "description": [
+ "Entitlement Administrators"
+ ],
+ "dn": "cn=entitlementadmin,cn=rolegroups,cn=accounts,dc=dev,dc=example,dc=com",
+ "memberof_taskgroup": [
+ "addentitlements",
+ "removeentitlements",
+ "modifyentitlements"
+ ]
+ }
+ ],
+ "summary": "15 rolegroups matched",
+ "truncated": false
+ }
+}
diff --git a/install/ui/test/data/rolegroup_remove_member.json b/install/ui/test/data/rolegroup_remove_member.json
new file mode 100644
index 000000000..d42bb6016
--- /dev/null
+++ b/install/ui/test/data/rolegroup_remove_member.json
@@ -0,0 +1,24 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "completed": 1,
+ "failed": {
+ "member": {
+ "group": [],
+ "host": [],
+ "hostgroup": [],
+ "user": []
+ }
+ },
+ "result": {
+ "cn": [
+ "test"
+ ],
+ "description": [
+ "Test role"
+ ],
+ "dn": "cn=test,cn=rolegroups,cn=accounts,dc=dev,dc=example,dc=com"
+ }
+ }
+}
diff --git a/install/ui/test/data/rolegroup_show.json b/install/ui/test/data/rolegroup_show.json
new file mode 100644
index 000000000..4652fb2cd
--- /dev/null
+++ b/install/ui/test/data/rolegroup_show.json
@@ -0,0 +1,20 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "result": {
+ "cn": [
+ "test"
+ ],
+ "description": [
+ "Test role"
+ ],
+ "dn": "cn=test,cn=rolegroups,cn=accounts,dc=dev,dc=example,dc=com",
+ "member_user": [
+ "admin"
+ ]
+ },
+ "summary": null,
+ "value": "test"
+ }
+}
diff --git a/install/ui/test/data/selfservice_find.json b/install/ui/test/data/selfservice_find.json
new file mode 100644
index 000000000..91db6e40b
--- /dev/null
+++ b/install/ui/test/data/selfservice_find.json
@@ -0,0 +1,24 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "count": 1,
+ "result": [
+ {
+ "aciname": "Self can write own password",
+ "attrs": [
+ "userPassword",
+ "krbPrincipalKey",
+ "sambaLMPassword",
+ "sambaNTPassword"
+ ],
+ "permissions": [
+ "write"
+ ],
+ "selfaci": true
+ }
+ ],
+ "summary": "1 selfservice matched",
+ "truncated": false
+ }
+} \ No newline at end of file
diff --git a/install/ui/test/data/selfservice_show.json b/install/ui/test/data/selfservice_show.json
new file mode 100644
index 000000000..358e65924
--- /dev/null
+++ b/install/ui/test/data/selfservice_show.json
@@ -0,0 +1,21 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "result": {
+ "aciname": "Self can write own password",
+ "attrs": [
+ "userPassword",
+ "krbPrincipalKey",
+ "sambaLMPassword",
+ "sambaNTPassword"
+ ],
+ "permissions": [
+ "write"
+ ],
+ "selfaci": true
+ },
+ "summary": null,
+ "value": "Self can write own password"
+ }
+} \ No newline at end of file
diff --git a/install/ui/test/data/service_add.json b/install/ui/test/data/service_add.json
new file mode 100644
index 000000000..4275d9bba
--- /dev/null
+++ b/install/ui/test/data/service_add.json
@@ -0,0 +1,29 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "result": {
+ "dn": "krbprincipalname=test/dev.example.com@dev.example.com,cn=services,cn=accounts,dc=dev,dc=example,dc=com",
+ "ipauniqueid": [
+ "5b314ad9-bae4-11df-b82f-00163e72f2d9"
+ ],
+ "krbprincipalname": [
+ "test/dev.example.com@DEV.EXAMPLE.COM"
+ ],
+ "managedby_host": [
+ "dev.example.com"
+ ],
+ "objectclass": [
+ "krbprincipal",
+ "krbprincipalaux",
+ "krbticketpolicyaux",
+ "ipaobject",
+ "ipaservice",
+ "pkiuser",
+ "top"
+ ]
+ },
+ "summary": "Added service \"test/dev.example.com@DEV.EXAMPLE.COM\"",
+ "value": "test/dev.example.com@DEV.EXAMPLE.COM"
+ }
+}
diff --git a/install/ui/test/data/service_add_host.json b/install/ui/test/data/service_add_host.json
new file mode 100644
index 000000000..cb199e310
--- /dev/null
+++ b/install/ui/test/data/service_add_host.json
@@ -0,0 +1,21 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "completed": 1,
+ "failed": {
+ "managedby": {
+ "host": []
+ }
+ },
+ "result": {
+ "dn": "krbprincipalname=test/dev.example.com@dev.example.com,cn=services,cn=accounts,dc=dev,dc=example,dc=com",
+ "krbprincipalname": [
+ "test/dev.example.com@DEV.EXAMPLE.COM"
+ ],
+ "managedby_host": [
+ "dev.example.com"
+ ]
+ }
+ }
+}
diff --git a/install/ui/test/data/service_del.json b/install/ui/test/data/service_del.json
new file mode 100644
index 000000000..053b0ad99
--- /dev/null
+++ b/install/ui/test/data/service_del.json
@@ -0,0 +1,9 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "result": true,
+ "summary": "Deleted service \"test/dev.example.com@DEV.EXAMPLE.COM\"",
+ "value": "test/dev.example.com@DEV.EXAMPLE.COM"
+ }
+}
diff --git a/install/ui/test/data/service_disable.json b/install/ui/test/data/service_disable.json
new file mode 100644
index 000000000..d62c05472
--- /dev/null
+++ b/install/ui/test/data/service_disable.json
@@ -0,0 +1,9 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "result": true,
+ "summary": "Removed kerberos key from \"test/dev.example.com@DEV.EXAMPLE.COM\"",
+ "value": "test/dev.example.com@DEV.EXAMPLE.COM"
+ }
+}
diff --git a/install/ui/test/data/service_find.json b/install/ui/test/data/service_find.json
new file mode 100644
index 000000000..b71ea9e31
--- /dev/null
+++ b/install/ui/test/data/service_find.json
@@ -0,0 +1,48 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "count": 3,
+ "result": [
+ {
+ "dn": "krbprincipalname=ldap/dev.example.com@dev.example.com,cn=services,cn=accounts,dc=dev,dc=example,dc=com",
+ "has_keytab": true,
+ "krbprincipalname": [
+ "ldap/dev.example.com@DEV.EXAMPLE.COM"
+ ],
+ "managedby_host": [
+ "dev.example.com"
+ ],
+ "usercertificate": [
+ {
+ "__base64__": "MIICbjCCAdegAwIBAgICA+0wDQYJKoZIhvcNAQEFBQAwKTEnMCUGA1UEAxMeSVBBIFRlc3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTEwMDkwMjA2NTYzMloXDTIwMDkwMjA2NTYzMlowKDEMMAoGA1UEChMDSVBBMRgwFgYDVQQDEw9kZXYuZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDc63RjpqUCI84j9kjn0XYmpAOjkYbLddT9F0UUanASg1iIhscwWjvp/Mf5ZIzEYoB+dloI9gvEUWb8CU/x42QZr4lgEK4m/vCSDA0CkAnWvU/DHdtcAgpdZeBOQ1CMynyvNvN/ajyaA8dPwRcs9yJDrWXMa7LzMuw+ct5HA7HRdDdvUeIFr8YZEd/Mt1N96BmlVf3GA3P89cWfCKr1iVnmyewanjKuwcws1GCxawCnp0w1GHbKct4PPhB3k6EN8ZipFDGZmSeDVsa3gF7y2reLAYTS1/RwWPAHNeQ0cpOMe155cF3uHGSoX+RWtgo0BZ1+wgLMU5sf9W3ZMln3WmoFAgMBAAGjIjAgMBEGCWCGSAGG+EIBAQQEAwIGQDALBgNVHQ8EBAMCBSAwDQYJKoZIhvcNAQEFBQADgYEAbSYTU+IQvfppQE7setcpO/PiFNnMaZ3Ss7UGjm6XoPem9X0ktQOfWhBuhfH/7MbPdg2zn+55soaRpd8rOThr187G40GAMM5I3Jr+8386Q4zwCvED7B09pzBhQd/4ecVTIYFc82EytsM6I1aBrG9cLLuT+RL2dK5efOymCf/zjsw="
+ }
+ ]
+ },
+ {
+ "dn": "krbprincipalname=http/dev.example.com@dev.example.com,cn=services,cn=accounts,dc=dev,dc=example,dc=com",
+ "has_keytab": true,
+ "krbprincipalname": [
+ "HTTP/dev.example.com@DEV.EXAMPLE.COM"
+ ],
+ "usercertificate": [
+ {
+ "__base64__": "MIICbjCCAdegAwIBAgICA+4wDQYJKoZIhvcNAQEFBQAwKTEnMCUGA1UEAxMeSVBBIFRlc3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTEwMDkwMjA2NTY1MFoXDTIwMDkwMjA2NTY1MFowKDEMMAoGA1UEChMDSVBBMRgwFgYDVQQDEw9kZXYuZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC2g0DTtC0f7StYfbVqc3bZ6niWHCBZp9SVEgD1lGY9+efQnO1Z6dqbUxLI+oUcVqA2aoeWVSTQ1KZLglF0pYUJcMVfUAQaFbwhY05rLtKya0+6DgYbnJ187fSHNOLQ71v/6pFt9THyLFICFJgKX64ouQYxV7+UY/vyqaKCjonWBJznJHaw07cEYj6tFkQxwNIhQRWZP2yLrSEay1cDLtA7Rm6AYRKIhiBKwFVewi4VEo6HbgfKpeZRZ2G8w1UErxTuPom2WymByoOg1Z8Xn23OiW+CkcrwRFhDYyp3LRiIT+86fPYkF4TBqO9lWbxKy4ZtcHXfMcGBmQSc3yjN+IctAgMBAAGjIjAgMBEGCWCGSAGG+EIBAQQEAwIGQDALBgNVHQ8EBAMCBSAwDQYJKoZIhvcNAQEFBQADgYEAi1vdSKmUUPdkwxv6tnabo6sEpTCdyV33Jops5hMkdtIKsvOG+CeXuvPYIwZpvwozAppL3tcXsh6t35YklpjeoX8qX5gYTZvuusCUAQHfJC4H/ggU+TrjQW5GnGOLTpgew/NtLKj7LACp/YrwMNA5ktdsBbj2kESIEVlokLvITy4="
+ }
+ ]
+ },
+ {
+ "dn": "krbprincipalname=test/dev.example.com@dev.example.com,cn=services,cn=accounts,dc=dev,dc=example,dc=com",
+ "has_keytab": false,
+ "krbprincipalname": [
+ "test/dev.example.com@DEV.EXAMPLE.COM"
+ ],
+ "managedby_host": [
+ "dev.example.com"
+ ]
+ }
+ ],
+ "summary": "3 services matched",
+ "truncated": false
+ }
+}
diff --git a/install/ui/test/data/service_managedby_host.json b/install/ui/test/data/service_managedby_host.json
new file mode 100644
index 000000000..181fc5b96
--- /dev/null
+++ b/install/ui/test/data/service_managedby_host.json
@@ -0,0 +1,110 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "count": 1,
+ "results": [
+ {
+ "error": null,
+ "result": {
+ "attributelevelrights": {
+ "aci": "rscwo",
+ "cn": "rscwo",
+ "description": "rscwo",
+ "enrolledby": "rsc",
+ "fqdn": "rscwo",
+ "ipaclientversion": "rscwo",
+ "ipauniqueid": "rscwo",
+ "krbcanonicalname": "rscwo",
+ "krbextradata": "rscwo",
+ "krblastfailedauth": "rscwo",
+ "krblastpwdchange": "rscwo",
+ "krblastsuccessfulauth": "rscwo",
+ "krbloginfailedcount": "rscwo",
+ "krbmaxrenewableage": "rscwo",
+ "krbmaxticketlife": "rscwo",
+ "krbobjectreferences": "rscwo",
+ "krbpasswordexpiration": "rscwo",
+ "krbprincipalaliases": "rscwo",
+ "krbprincipalexpiration": "rscwo",
+ "krbprincipalkey": "wo",
+ "krbprincipalname": "rscwo",
+ "krbprincipaltype": "rscwo",
+ "krbpwdhistory": "rscwo",
+ "krbpwdpolicyreference": "rscwo",
+ "krbticketflags": "rscwo",
+ "krbticketpolicyreference": "rscwo",
+ "krbupenabled": "rscwo",
+ "l": "rscwo",
+ "managedby": "rscwo",
+ "memberof": "rsc",
+ "nsaccountlock": "rscwo",
+ "nshardwareplatform": "rscwo",
+ "nshostlocation": "rscwo",
+ "nsosversion": "rscwo",
+ "objectclass": "rscwo",
+ "serverhostname": "rsc",
+ "usercertificate": "rscwo",
+ "userpassword": "wo"
+ },
+ "cn": [
+ "dev.example.com"
+ ],
+ "description": [
+ "Development"
+ ],
+ "dn": "fqdn=dev.example.com,cn=computers,cn=accounts,dc=dev,dc=example,dc=com",
+ "fqdn": [
+ "dev.example.com"
+ ],
+ "has_keytab": true,
+ "ipauniqueid": [
+ "0568a298-f46d-11df-9ef8-00163e72f2d9"
+ ],
+ "krbextradata": [
+ {
+ "__base64__": "AAKTZudMYWRtaW4vYWRtaW5AREVWLkVYQU1QTEUuQ09NAA=="
+ },
+ {
+ "__base64__": "AAgBAA=="
+ }
+ ],
+ "krblastpwdchange": [
+ "20101120061131Z"
+ ],
+ "krbpasswordexpiration": [
+ "19700101000000Z"
+ ],
+ "krbprincipalname": [
+ "host/dev.example.com@DEV.EXAMPLE.COM"
+ ],
+ "krbticketflags": [
+ "0"
+ ],
+ "managedby_host": [
+ "dev.example.com"
+ ],
+ "memberof_hostgroup": [
+ "test"
+ ],
+ "objectclass": [
+ "top",
+ "ipaobject",
+ "nshost",
+ "ipahost",
+ "ipaservice",
+ "pkiuser",
+ "krbprincipalaux",
+ "krbprincipal",
+ "krbticketpolicyaux"
+ ],
+ "serverhostname": [
+ "dev"
+ ]
+ },
+ "summary": null,
+ "value": "dev.example.com"
+ }
+ ]
+ }
+}
diff --git a/install/ui/test/data/service_mod.json b/install/ui/test/data/service_mod.json
new file mode 100644
index 000000000..f56186466
--- /dev/null
+++ b/install/ui/test/data/service_mod.json
@@ -0,0 +1,21 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "result": {
+ "krbprincipalname": [
+ "test/dev.example.com@DEV.EXAMPLE.COM"
+ ],
+ "managedby_host": [
+ "dev.example.com"
+ ],
+ "usercertificate": [
+ {
+ "__base64__": "MIICAjCCAWugAwIBAgICBAswDQYJKoZIhvcNAQEFBQAwKTEnMCUGA1UEAxMeSVBBIFRlc3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTEwMTAwNzIzMzk0NFoXDTE1MTAwNzIzMzk0NFowKDEMMAoGA1UECgwDSVBBMRgwFgYDVQQDDA9kZXYuZXhhbXBsZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOTXyj8grVB7Rj95RFawgdwn9OYZ03LWHZ+HMYggu2/xCCrUrdThP14YBlVqZumjVJSclj6T4ACjjdPJq9JTTmx7gMizDTReus7IPlS6fCxb5v5whQJZsEksXL04OxUMl25euPRFkYcTK1rdW47+AkG10j1qeNW+B6CpdQGR6eM/AgMBAAGjOjA4MBEGCWCGSAGG+EIBAQQEAwIGQDATBgNVHSUEDDAKBggrBgEFBQcDATAOBgNVHQ8BAf8EBAMCBPAwDQYJKoZIhvcNAQEFBQADgYEASIhq723VL5xP0q51MYXFlGU1boD7pPD1pIQspD/MjCIEupcbH2kAo4wf+EiKsXR0rs+WZkaSgvFqaM4OQ2kWSFTiqmFXFDBEi6EFr68yLg7IpQpNTzVBXERd8B4GwNL9wrRw60jPXlUK29DPBsdGq8fDgX18l39wKkWXv7p1to4="
+ }
+ ]
+ },
+ "summary": "Modified service \"test/dev.example.com@DEV.EXAMPLE.COM\"",
+ "value": "test/dev.example.com@DEV.EXAMPLE.COM"
+ }
+} \ No newline at end of file
diff --git a/install/ui/test/data/service_remove_host.sh b/install/ui/test/data/service_remove_host.sh
new file mode 100644
index 000000000..15234f4d0
--- /dev/null
+++ b/install/ui/test/data/service_remove_host.sh
@@ -0,0 +1,18 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "completed": 1,
+ "failed": {
+ "managedby": {
+ "host": []
+ }
+ },
+ "result": {
+ "dn": "krbprincipalname=test/dev.example.com@dev.example.com,cn=services,cn=accounts,dc=dev,dc=example,dc=com",
+ "krbprincipalname": [
+ "test/dev.example.com@DEV.EXAMPLE.COM"
+ ]
+ }
+ }
+}
diff --git a/install/ui/test/data/service_show.json b/install/ui/test/data/service_show.json
new file mode 100644
index 000000000..9cb11d535
--- /dev/null
+++ b/install/ui/test/data/service_show.json
@@ -0,0 +1,74 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "result": {
+ "attributelevelrights": {
+ "aci": "rscwo",
+ "ipauniqueid": "rsc",
+ "krbcanonicalname": "rscwo",
+ "krbextradata": "rscwo",
+ "krblastfailedauth": "rscwo",
+ "krblastpwdchange": "rscwo",
+ "krblastsuccessfulauth": "rscwo",
+ "krbloginfailedcount": "rscwo",
+ "krbmaxrenewableage": "rscwo",
+ "krbmaxticketlife": "rscwo",
+ "krbobjectreferences": "rscwo",
+ "krbpasswordexpiration": "rscwo",
+ "krbprincipalaliases": "rscwo",
+ "krbprincipalexpiration": "rscwo",
+ "krbprincipalkey": "wo",
+ "krbprincipalname": "rscwo",
+ "krbprincipaltype": "rscwo",
+ "krbpwdhistory": "rscwo",
+ "krbpwdpolicyreference": "rscwo",
+ "krbticketflags": "rscwo",
+ "krbticketpolicyreference": "rscwo",
+ "krbupenabled": "rscwo",
+ "managedby": "rscwo",
+ "memberof": "rsc",
+ "nsaccountlock": "rscwo",
+ "objectclass": "rscwo",
+ "usercertificate": "rscwo"
+ },
+ "dn": "krbprincipalname=test/dev.example.com@dev.example.com,cn=services,cn=accounts,dc=dev,dc=example,dc=com",
+ "has_keytab": true,
+ "issuer": "CN=IPA Test Certificate Authority",
+ "ipauniqueid": [
+ "c0298f70-f396-11df-a2aa-00163e72f2d9"
+ ],
+ "krblastpwdchange": [
+ "20101119101837Z"
+ ],
+ "krbprincipalname": [
+ "test/dev.example.com@DEV.EXAMPLE.COM"
+ ],
+ "managedby_host": [
+ "dev.example.com"
+ ],
+ "md5_fingerprint": "08:86:a9:f9:87:af:0d:d7:42:01:e0:5f:12:9b:32:7f",
+ "serial_number": "1",
+ "sha1_fingerprint": "b8:4c:4b:79:4f:13:03:79:47:08:fa:6b:52:63:3d:f9:15:8e:7e:dc",
+ "subject": "CN=dev.example.com,O=IPA",
+ "usercertificate": [
+ {
+ "__base64__": "MIICAjCCAWugAwIBAgICBAswDQYJKoZIhvcNAQEFBQAwKTEnMCUGA1UEAxMeSVBBIFRlc3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTEwMTAwNzIzMzk0NFoXDTE1MTAwNzIzMzk0NFowKDEMMAoGA1UECgwDSVBBMRgwFgYDVQQDDA9kZXYuZXhhbXBsZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOTXyj8grVB7Rj95RFawgdwn9OYZ03LWHZ+HMYggu2/xCCrUrdThP14YBlVqZumjVJSclj6T4ACjjdPJq9JTTmx7gMizDTReus7IPlS6fCxb5v5whQJZsEksXL04OxUMl25euPRFkYcTK1rdW47+AkG10j1qeNW+B6CpdQGR6eM/AgMBAAGjOjA4MBEGCWCGSAGG+EIBAQQEAwIGQDATBgNVHSUEDDAKBggrBgEFBQcDATAOBgNVHQ8BAf8EBAMCBPAwDQYJKoZIhvcNAQEFBQADgYEASIhq723VL5xP0q51MYXFlGU1boD7pPD1pIQspD/MjCIEupcbH2kAo4wf+EiKsXR0rs+WZkaSgvFqaM4OQ2kWSFTiqmFXFDBEi6EFr68yLg7IpQpNTzVBXERd8B4GwNL9wrRw60jPXlUK29DPBsdGq8fDgX18l39wKkWXv7p1to4="
+ }
+ ],
+ "valid_not_after": "Tue Oct 13 01:59:32 2015 UTC",
+ "valid_not_before": "Wed Oct 13 01:59:32 2010 UTC",
+ "objectclass": [
+ "krbprincipal",
+ "krbprincipalaux",
+ "krbticketpolicyaux",
+ "ipaobject",
+ "ipaservice",
+ "pkiuser",
+ "top"
+ ]
+ },
+ "summary": null,
+ "value": "test/dev.example.com@DEV.EXAMPLE.COM"
+ }
+}
diff --git a/install/ui/test/data/sudocmd_add.json b/install/ui/test/data/sudocmd_add.json
new file mode 100644
index 000000000..6fb4a5fc1
--- /dev/null
+++ b/install/ui/test/data/sudocmd_add.json
@@ -0,0 +1,21 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "result": {
+ "dn": "sudocmd=/usr/bin/less,cn=sudocmds,cn=sudo,dc=dev,dc=example,dc=com",
+ "ipauniqueid": [
+ "09e4ab26-f456-11df-bb95-00163e72f2d9"
+ ],
+ "objectclass": [
+ "ipaobject",
+ "ipasudocmd"
+ ],
+ "sudocmd": [
+ "/usr/bin/less"
+ ]
+ },
+ "summary": "Added sudo command \"/usr/bin/less\"",
+ "value": "/usr/bin/less"
+ }
+}
diff --git a/install/ui/test/data/sudocmd_del.json b/install/ui/test/data/sudocmd_del.json
new file mode 100644
index 000000000..d6bc5ad00
--- /dev/null
+++ b/install/ui/test/data/sudocmd_del.json
@@ -0,0 +1,9 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "result": true,
+ "summary": "Deleted sudo command \"/usr/bin/less\"",
+ "value": "/usr/bin/less"
+ }
+}
diff --git a/install/ui/test/data/sudocmd_find.json b/install/ui/test/data/sudocmd_find.json
new file mode 100644
index 000000000..f7f5a23ef
--- /dev/null
+++ b/install/ui/test/data/sudocmd_find.json
@@ -0,0 +1,23 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "count": 2,
+ "result": [
+ {
+ "dn": "sudocmd=/usr/bin/more,cn=sudocmds,cn=sudo,dc=dev,dc=example,dc=com",
+ "sudocmd": [
+ "/usr/bin/more"
+ ]
+ },
+ {
+ "dn": "sudocmd=/usr/bin/less,cn=sudocmds,cn=sudo,dc=dev,dc=example,dc=com",
+ "sudocmd": [
+ "/usr/bin/less"
+ ]
+ }
+ ],
+ "summary": "2 sudo command matched",
+ "truncated": false
+ }
+}
diff --git a/install/ui/test/data/sudocmd_memberof_add.json b/install/ui/test/data/sudocmd_memberof_add.json
new file mode 100644
index 000000000..fc45ef4e2
--- /dev/null
+++ b/install/ui/test/data/sudocmd_memberof_add.json
@@ -0,0 +1,53 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "count": 2,
+ "results": [
+ {
+ "completed": 1,
+ "error": null,
+ "failed": {
+ "member": {
+ "sudocmd": [],
+ "sudocmdgroup": []
+ }
+ },
+ "result": {
+ "cn": [
+ "group1"
+ ],
+ "description": [
+ "Group 1"
+ ],
+ "dn": "cn=group1,cn=sudocmdgroups,cn=sudo,dc=ipa",
+ "member_sudocmd": [
+ "/usr/bin/less"
+ ]
+ }
+ },
+ {
+ "completed": 1,
+ "error": null,
+ "failed": {
+ "member": {
+ "sudocmd": [],
+ "sudocmdgroup": []
+ }
+ },
+ "result": {
+ "cn": [
+ "group2"
+ ],
+ "description": [
+ "Group 2"
+ ],
+ "dn": "cn=group2,cn=sudocmdgroups,cn=sudo,dc=ipa",
+ "member_sudocmd": [
+ "/usr/bin/more"
+ ]
+ }
+ }
+ ]
+ }
+}
diff --git a/install/ui/test/data/sudocmd_memberof_remove.json b/install/ui/test/data/sudocmd_memberof_remove.json
new file mode 100644
index 000000000..c5e031b86
--- /dev/null
+++ b/install/ui/test/data/sudocmd_memberof_remove.json
@@ -0,0 +1,50 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "count": 2,
+ "results": [
+ {
+ "completed": 1,
+ "error": null,
+ "failed": {
+ "member": {
+ "sudocmd": [],
+ "sudocmdgroup": []
+ }
+ },
+ "result": {
+ "cn": [
+ "group1"
+ ],
+ "description": [
+ "Group 1"
+ ],
+ "dn": "cn=group1,cn=sudocmdgroups,cn=sudo,dc=ipa"
+ }
+ },
+ {
+ "completed": 1,
+ "error": null,
+ "failed": {
+ "member": {
+ "sudocmd": [],
+ "sudocmdgroup": []
+ }
+ },
+ "result": {
+ "cn": [
+ "group2"
+ ],
+ "description": [
+ "Group 2"
+ ],
+ "dn": "cn=group2,cn=sudocmdgroups,cn=sudo,dc=ipa",
+ "memberindirect_sudocmd": [
+ "/usr/bin/more"
+ ]
+ }
+ }
+ ]
+ }
+}
diff --git a/install/ui/test/data/sudocmd_memberof_show.json b/install/ui/test/data/sudocmd_memberof_show.json
new file mode 100644
index 000000000..279dc6c96
--- /dev/null
+++ b/install/ui/test/data/sudocmd_memberof_show.json
@@ -0,0 +1,61 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "count": 2,
+ "results": [
+ {
+ "error": null,
+ "result": {
+ "cn": [
+ "group1"
+ ],
+ "description": [
+ "Group 1"
+ ],
+ "dn": "cn=group1,cn=sudocmdgroups,cn=sudo,dc=ipa",
+ "ipauniqueid": [
+ "fc775d2e-1d56-11e0-b7cd-00163e2fe6de"
+ ],
+ "member_sudocmd": [
+ "/usr/bin/less"
+ ],
+ "objectclass": [
+ "ipaobject",
+ "ipasudocmdgrp",
+ "groupOfNames",
+ "top"
+ ]
+ },
+ "summary": null,
+ "value": "group1"
+ },
+ {
+ "error": null,
+ "result": {
+ "cn": [
+ "group2"
+ ],
+ "description": [
+ "Group 2"
+ ],
+ "dn": "cn=group2,cn=sudocmdgroups,cn=sudo,dc=ipa",
+ "ipauniqueid": [
+ "b90c1930-1d5b-11e0-ac89-00163e2fe6de"
+ ],
+ "member_sudocmd": [
+ "/usr/bin/more"
+ ],
+ "objectclass": [
+ "ipaobject",
+ "ipasudocmdgrp",
+ "groupOfNames",
+ "top"
+ ]
+ },
+ "summary": null,
+ "value": "group2"
+ }
+ ]
+ }
+}
diff --git a/install/ui/test/data/sudocmd_mod.json b/install/ui/test/data/sudocmd_mod.json
new file mode 100644
index 000000000..82919cd2d
--- /dev/null
+++ b/install/ui/test/data/sudocmd_mod.json
@@ -0,0 +1,31 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "result": {
+ "attributelevelrights": {
+ "aci": "rscwo",
+ "description": "rscwo",
+ "ipauniqueid": "rsc",
+ "memberof": "rsc",
+ "nsaccountlock": "rscwo",
+ "sudocmd": "rscwo"
+ },
+ "description": [
+ "opposite of more"
+ ],
+ "ipauniqueid": [
+ "06708d0e-f454-11df-9273-00163e72f2d9"
+ ],
+ "objectclass": [
+ "ipaobject",
+ "ipasudocmd"
+ ],
+ "sudocmd": [
+ "/usr/bin/less"
+ ]
+ },
+ "summary": "Modified sudo command \"/usr/bin/less\"",
+ "value": "/usr/bin/less"
+ }
+}
diff --git a/install/ui/test/data/sudocmd_show.json b/install/ui/test/data/sudocmd_show.json
new file mode 100644
index 000000000..b27c832f3
--- /dev/null
+++ b/install/ui/test/data/sudocmd_show.json
@@ -0,0 +1,33 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "result": {
+ "attributelevelrights": {
+ "aci": "rscwo",
+ "description": "rscwo",
+ "ipauniqueid": "rsc",
+ "memberof": "rsc",
+ "nsaccountlock": "rscwo",
+ "sudocmd": "rscwo"
+ },
+ "dn": "sudocmd=/usr/bin/less,cn=sudocmds,cn=sudo,dc=dev,dc=example,dc=com",
+ "ipauniqueid": [
+ "06708d0e-f454-11df-9273-00163e72f2d9"
+ ],
+ "memberof": [
+ "cn=group1,cn=sudocmdgroups,cn=sudo,dc=dev,dc=example,dc=com",
+ "cn=group2,cn=sudocmdgroups,cn=sudo,dc=dev,dc=example,dc=com"
+ ],
+ "objectclass": [
+ "ipaobject",
+ "ipasudocmd"
+ ],
+ "sudocmd": [
+ "/usr/bin/less"
+ ]
+ },
+ "summary": null,
+ "value": "/usr/bin/less"
+ }
+}
diff --git a/install/ui/test/data/sudocmdgroup_add.json b/install/ui/test/data/sudocmdgroup_add.json
new file mode 100644
index 000000000..ce389f564
--- /dev/null
+++ b/install/ui/test/data/sudocmdgroup_add.json
@@ -0,0 +1,26 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "result": {
+ "cn": [
+ "group1"
+ ],
+ "description": [
+ "Group 1"
+ ],
+ "dn": "cn=group1,cn=sudocmdgroups,cn=sudo,dc=dev,dc=example,dc=com",
+ "ipauniqueid": [
+ "1a8f4852-f459-11df-815c-00163e72f2d9"
+ ],
+ "objectclass": [
+ "ipaobject",
+ "ipasudocmdgrp",
+ "groupOfNames",
+ "top"
+ ]
+ },
+ "summary": "Added sudo command group \"group1\"",
+ "value": "group1"
+ }
+}
diff --git a/install/ui/test/data/sudocmdgroup_add_member.json b/install/ui/test/data/sudocmdgroup_add_member.json
new file mode 100644
index 000000000..254746e65
--- /dev/null
+++ b/install/ui/test/data/sudocmdgroup_add_member.json
@@ -0,0 +1,26 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "completed": 2,
+ "failed": {
+ "member": {
+ "sudocmd": [],
+ "sudocmdgroup": []
+ }
+ },
+ "result": {
+ "cn": [
+ "group1"
+ ],
+ "description": [
+ "SUDO Group 1"
+ ],
+ "dn": "cn=group1,cn=sudocmdgroups,cn=sudo,dc=dev,dc=example,dc=com",
+ "member_sudocmd": [
+ "/usr/bin/more",
+ "/usr/bin/less"
+ ]
+ }
+ }
+}
diff --git a/install/ui/test/data/sudocmdgroup_del.json b/install/ui/test/data/sudocmdgroup_del.json
new file mode 100644
index 000000000..24c7ab692
--- /dev/null
+++ b/install/ui/test/data/sudocmdgroup_del.json
@@ -0,0 +1,9 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "result": true,
+ "summary": "Deleted sudo command group \"group1\"",
+ "value": "group1"
+ }
+}
diff --git a/install/ui/test/data/sudocmdgroup_find.json b/install/ui/test/data/sudocmdgroup_find.json
new file mode 100644
index 000000000..d640e35bd
--- /dev/null
+++ b/install/ui/test/data/sudocmdgroup_find.json
@@ -0,0 +1,33 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "count": 2,
+ "result": [
+ {
+ "cn": [
+ "group1"
+ ],
+ "description": [
+ "Group 1"
+ ],
+ "dn": "cn=group1,cn=sudocmdgroups,cn=sudo,dc=dev,dc=example,dc=com",
+ "member_sudocmd": [
+ "/usr/bin/more",
+ "/usr/bin/less"
+ ]
+ },
+ {
+ "cn": [
+ "group2"
+ ],
+ "description": [
+ "Group 2"
+ ],
+ "dn": "cn=group2,cn=sudocmdgroups,cn=sudo,dc=dev,dc=example,dc=com"
+ }
+ ],
+ "summary": "2 sudo command groups matched",
+ "truncated": false
+ }
+}
diff --git a/install/ui/test/data/sudocmdgroup_member_sudocmd.json b/install/ui/test/data/sudocmdgroup_member_sudocmd.json
new file mode 100644
index 000000000..7871a4684
--- /dev/null
+++ b/install/ui/test/data/sudocmdgroup_member_sudocmd.json
@@ -0,0 +1,57 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "count": 2,
+ "results": [
+ {
+ "error": null,
+ "result": {
+ "description": [
+ "more"
+ ],
+ "dn": "sudocmd=/usr/bin/more,cn=sudocmds,cn=sudo,dc=dev,dc=example,dc=com",
+ "ipauniqueid": [
+ "a9138c9a-fc0c-11df-8584-00163e72f2d9"
+ ],
+ "memberof": [
+ "cn=test,cn=sudocmdgroups,cn=sudo,dc=dev,dc=example,dc=com"
+ ],
+ "objectclass": [
+ "ipaobject",
+ "ipasudocmd"
+ ],
+ "sudocmd": [
+ "/usr/bin/more"
+ ]
+ },
+ "summary": null,
+ "value": "/usr/bin/more"
+ },
+ {
+ "error": null,
+ "result": {
+ "description": [
+ "less"
+ ],
+ "dn": "sudocmd=/usr/bin/less,cn=sudocmds,cn=sudo,dc=dev,dc=example,dc=com",
+ "ipauniqueid": [
+ "44ce29ee-fc38-11df-b995-00163e72f2d9"
+ ],
+ "memberof": [
+ "cn=test,cn=sudocmdgroups,cn=sudo,dc=dev,dc=example,dc=com"
+ ],
+ "objectclass": [
+ "ipaobject",
+ "ipasudocmd"
+ ],
+ "sudocmd": [
+ "/usr/bin/less"
+ ]
+ },
+ "summary": null,
+ "value": "/usr/bin/less"
+ }
+ ]
+ }
+}
diff --git a/install/ui/test/data/sudocmdgroup_mod.json b/install/ui/test/data/sudocmdgroup_mod.json
new file mode 100644
index 000000000..d0eb3226b
--- /dev/null
+++ b/install/ui/test/data/sudocmdgroup_mod.json
@@ -0,0 +1,39 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "result": {
+ "attributelevelrights": {
+ "aci": "rscwo",
+ "businesscategory": "rscwo",
+ "cn": "rscwo",
+ "description": "rscwo",
+ "ipauniqueid": "rsc",
+ "member": "rscwo",
+ "nsaccountlock": "rscwo",
+ "o": "rscwo",
+ "objectclass": "rscwo",
+ "ou": "rscwo",
+ "owner": "rscwo",
+ "seealso": "rscwo"
+ },
+ "cn": [
+ "group1"
+ ],
+ "description": [
+ "SUDO Group 1"
+ ],
+ "ipauniqueid": [
+ "1a8f4852-f459-11df-815c-00163e72f2d9"
+ ],
+ "objectclass": [
+ "ipaobject",
+ "ipasudocmdgrp",
+ "groupOfNames",
+ "top"
+ ]
+ },
+ "summary": "Modified sudo command group \"group1\"",
+ "value": "group1"
+ }
+}
diff --git a/install/ui/test/data/sudocmdgroup_remove_member.json b/install/ui/test/data/sudocmdgroup_remove_member.json
new file mode 100644
index 000000000..22353c314
--- /dev/null
+++ b/install/ui/test/data/sudocmdgroup_remove_member.json
@@ -0,0 +1,22 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "completed": 2,
+ "failed": {
+ "member": {
+ "sudocmd": [],
+ "sudocmdgroup": []
+ }
+ },
+ "result": {
+ "cn": [
+ "group1"
+ ],
+ "description": [
+ "SUDO Group 1"
+ ],
+ "dn": "cn=group1,cn=sudocmdgroups,cn=sudo,dc=dev,dc=example,dc=com"
+ }
+ }
+}
diff --git a/install/ui/test/data/sudocmdgroup_show.json b/install/ui/test/data/sudocmdgroup_show.json
new file mode 100644
index 000000000..1478ba265
--- /dev/null
+++ b/install/ui/test/data/sudocmdgroup_show.json
@@ -0,0 +1,44 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "result": {
+ "attributelevelrights": {
+ "aci": "rscwo",
+ "businesscategory": "rscwo",
+ "cn": "rscwo",
+ "description": "rscwo",
+ "ipauniqueid": "rsc",
+ "member": "rscwo",
+ "nsaccountlock": "rscwo",
+ "o": "rscwo",
+ "objectclass": "rscwo",
+ "ou": "rscwo",
+ "owner": "rscwo",
+ "seealso": "rscwo"
+ },
+ "cn": [
+ "group1"
+ ],
+ "description": [
+ "Group 1"
+ ],
+ "dn": "cn=group1,cn=sudocmdgroups,cn=sudo,dc=dev,dc=example,dc=com",
+ "ipauniqueid": [
+ "d99989a6-f459-11df-9273-00163e72f2d9"
+ ],
+ "member_sudocmd": [
+ "/usr/bin/more",
+ "/usr/bin/less"
+ ],
+ "objectclass": [
+ "ipaobject",
+ "ipasudocmdgrp",
+ "groupOfNames",
+ "top"
+ ]
+ },
+ "summary": null,
+ "value": "group1"
+ }
+}
diff --git a/install/ui/test/data/sudorule_add.json b/install/ui/test/data/sudorule_add.json
new file mode 100644
index 000000000..396b4935c
--- /dev/null
+++ b/install/ui/test/data/sudorule_add.json
@@ -0,0 +1,24 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "result": {
+ "cn": [
+ "test"
+ ],
+ "description": [
+ "test"
+ ],
+ "dn": "ipauniqueid=94ef3550-f443-11df-a2aa-00163e72f2d9,cn=sudorules,cn=sudo,dc=dev,dc=example,dc=com",
+ "ipauniqueid": [
+ "94ef3550-f443-11df-a2aa-00163e72f2d9"
+ ],
+ "objectclass": [
+ "ipaassociation",
+ "ipasudorule"
+ ]
+ },
+ "summary": "Added sudo rule \"test\"",
+ "value": "test"
+ }
+}
diff --git a/install/ui/test/data/sudorule_del.json b/install/ui/test/data/sudorule_del.json
new file mode 100644
index 000000000..c30979892
--- /dev/null
+++ b/install/ui/test/data/sudorule_del.json
@@ -0,0 +1,9 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "result": true,
+ "summary": null,
+ "value": "test"
+ }
+}
diff --git a/install/ui/test/data/sudorule_find.json b/install/ui/test/data/sudorule_find.json
new file mode 100644
index 000000000..a843b2a5b
--- /dev/null
+++ b/install/ui/test/data/sudorule_find.json
@@ -0,0 +1,17 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "count": 1,
+ "result": [
+ {
+ "cn": [
+ "test"
+ ],
+ "dn": "ipauniqueid=4fc57a02-f23311df-b268e50e-a3b3ef71,cn=sudorules,cn=sudo,dc=dev,dc=example,dc=com"
+ }
+ ],
+ "summary": null,
+ "truncated": false
+ }
+}
diff --git a/install/ui/test/data/sudorule_mod.json b/install/ui/test/data/sudorule_mod.json
new file mode 100644
index 000000000..7785f5f5e
--- /dev/null
+++ b/install/ui/test/data/sudorule_mod.json
@@ -0,0 +1,51 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "result": {
+ "attributelevelrights": {
+ "aci": "rscwo",
+ "cmdcategory": "rscwo",
+ "cn": "rscwo",
+ "description": "rscwo",
+ "externalhost": "rscwo",
+ "externaluser": "rscwo",
+ "hostcategory": "rscwo",
+ "hostmask": "rscwo",
+ "ipaenabledflag": "rscwo",
+ "ipasudoopt": "rscwo",
+ "ipasudorunas": "rscwo",
+ "ipasudorunasextgroup": "rscwo",
+ "ipasudorunasextuser": "rscwo",
+ "ipasudorunasgroup": "rscwo",
+ "ipasudorunasgroupcategory": "rscwo",
+ "ipasudorunasusercategory": "rscwo",
+ "ipauniqueid": "rsc",
+ "memberallowcmd": "rscwo",
+ "memberdenycmd": "rscwo",
+ "memberhost": "rscwo",
+ "memberuser": "rscwo",
+ "nsaccountlock": "rscwo",
+ "usercategory": "rscwo"
+ },
+ "cmdcategory": [
+ "all"
+ ],
+ "cn": [
+ "test"
+ ],
+ "description": [
+ "Test Rule"
+ ],
+ "ipauniqueid": [
+ "94ef3550-f443-11df-a2aa-00163e72f2d9"
+ ],
+ "objectclass": [
+ "ipaassociation",
+ "ipasudorule"
+ ]
+ },
+ "summary": null,
+ "value": "test"
+ }
+}
diff --git a/install/ui/test/data/sudorule_show.json b/install/ui/test/data/sudorule_show.json
new file mode 100644
index 000000000..51f83af70
--- /dev/null
+++ b/install/ui/test/data/sudorule_show.json
@@ -0,0 +1,84 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "result": {
+ "attributelevelrights": {
+ "aci": "rscwo",
+ "cmdcategory": "rscwo",
+ "cn": "rscwo",
+ "description": "rscwo",
+ "externalhost": "rscwo",
+ "externaluser": "rscwo",
+ "hostcategory": "rscwo",
+ "hostmask": "rscwo",
+ "ipaenabledflag": "rscwo",
+ "ipasudoopt": "rscwo",
+ "ipasudorunas": "rscwo",
+ "ipasudorunasextgroup": "rscwo",
+ "ipasudorunasextuser": "rscwo",
+ "ipasudorunasgroup": "rscwo",
+ "ipasudorunasgroupcategory": "rscwo",
+ "ipasudorunasusercategory": "rscwo",
+ "ipauniqueid": "rsc",
+ "memberallowcmd": "rscwo",
+ "memberdenycmd": "rscwo",
+ "memberhost": "rscwo",
+ "memberuser": "rscwo",
+ "nsaccountlock": "rscwo",
+ "usercategory": "rscwo"
+ },
+ "cn": [
+ "test"
+ ],
+ "dn": "ipauniqueid=4fc57a02-f23311df-b268e50e-a3b3ef71,cn=sudorules,cn=sudo,dc=dev,dc=example,dc=com",
+ "externalhost": [
+ "external.example.com"
+ ],
+ "externaluser": [
+ "external"
+ ],
+ "ipasudorunas_user": [
+ "admin"
+ ],
+ "ipasudorunasgroup_group": [
+ "admins"
+ ],
+ "ipauniqueid": [
+ "4fc57a02-f23311df-b268e50e-a3b3ef71"
+ ],
+ "memberallowcmd_sudocmd": [
+ "/usr/bin/less"
+ ],
+ "memberallowcmd_sudocmdgroup": [
+ "group1"
+ ],
+ "memberdenycmd_sudocmd": [
+ "/usr/bin/more"
+ ],
+ "memberdenycmd_sudocmdgroup": [
+ "group1",
+ "group2"
+ ],
+ "memberhost_host": [
+ "dev.example.com"
+ ],
+ "memberhost_hostgroup": [
+ "production",
+ "staging"
+ ],
+ "memberuser_group": [
+ "editors"
+ ],
+ "memberuser_user": [
+ "test"
+ ],
+ "objectclass": [
+ "ipaassociation",
+ "ipasudorule"
+ ]
+ },
+ "summary": null,
+ "value": "test"
+ }
+}
diff --git a/install/ui/test/data/taskgroup_find.json b/install/ui/test/data/taskgroup_find.json
new file mode 100644
index 000000000..fa5c46250
--- /dev/null
+++ b/install/ui/test/data/taskgroup_find.json
@@ -0,0 +1,554 @@
+{
+ "error": null,
+ "id": 6,
+ "result": {
+ "count": 45,
+ "result": [
+ {
+ "cn": [
+ "addusers"
+ ],
+ "description": [
+ "Add Users"
+ ],
+ "dn": "cn=addusers,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_rolegroup": [
+ "useradmin"
+ ]
+ },
+ {
+ "cn": [
+ "change_password"
+ ],
+ "description": [
+ "Change a user password"
+ ],
+ "dn": "cn=change_password,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_rolegroup": [
+ "useradmin"
+ ]
+ },
+ {
+ "cn": [
+ "add_user_to_default_group"
+ ],
+ "description": [
+ "Add user to default group"
+ ],
+ "dn": "cn=add_user_to_default_group,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_rolegroup": [
+ "useradmin"
+ ]
+ },
+ {
+ "cn": [
+ "removeusers"
+ ],
+ "description": [
+ "Remove Users"
+ ],
+ "dn": "cn=removeusers,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_rolegroup": [
+ "useradmin"
+ ]
+ },
+ {
+ "cn": [
+ "modifyusers"
+ ],
+ "description": [
+ "Modify Users"
+ ],
+ "dn": "cn=modifyusers,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_rolegroup": [
+ "useradmin"
+ ]
+ },
+ {
+ "cn": [
+ "addgroups"
+ ],
+ "description": [
+ "Add Groups"
+ ],
+ "dn": "cn=addgroups,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_rolegroup": [
+ "groupadmin"
+ ]
+ },
+ {
+ "cn": [
+ "removegroups"
+ ],
+ "description": [
+ "Remove Groups"
+ ],
+ "dn": "cn=removegroups,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_rolegroup": [
+ "groupadmin"
+ ]
+ },
+ {
+ "cn": [
+ "modifygroups"
+ ],
+ "description": [
+ "Modify Groups"
+ ],
+ "dn": "cn=modifygroups,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_rolegroup": [
+ "groupadmin"
+ ]
+ },
+ {
+ "cn": [
+ "modifygroupmembership"
+ ],
+ "description": [
+ "Modify Group membership"
+ ],
+ "dn": "cn=modifygroupmembership,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_rolegroup": [
+ "groupadmin"
+ ]
+ },
+ {
+ "cn": [
+ "addhosts"
+ ],
+ "description": [
+ "Add Hosts"
+ ],
+ "dn": "cn=addhosts,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_rolegroup": [
+ "hostadmin"
+ ]
+ },
+ {
+ "cn": [
+ "removehosts"
+ ],
+ "description": [
+ "Remove Hosts"
+ ],
+ "dn": "cn=removehosts,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_rolegroup": [
+ "hostadmin"
+ ]
+ },
+ {
+ "cn": [
+ "modifyhosts"
+ ],
+ "description": [
+ "Modify Hosts"
+ ],
+ "dn": "cn=modifyhosts,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_rolegroup": [
+ "hostadmin"
+ ]
+ },
+ {
+ "cn": [
+ "addhostgroups"
+ ],
+ "description": [
+ "Add Host Groups"
+ ],
+ "dn": "cn=addhostgroups,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_rolegroup": [
+ "hostgroupadmin"
+ ]
+ },
+ {
+ "cn": [
+ "removehostgroups"
+ ],
+ "description": [
+ "Remove Host Groups"
+ ],
+ "dn": "cn=removehostgroups,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_rolegroup": [
+ "hostgroupadmin"
+ ]
+ },
+ {
+ "cn": [
+ "modifyhostgroups"
+ ],
+ "description": [
+ "Modify Host Groups"
+ ],
+ "dn": "cn=modifyhostgroups,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_rolegroup": [
+ "hostgroupadmin"
+ ]
+ },
+ {
+ "cn": [
+ "modifyhostgroupmembership"
+ ],
+ "description": [
+ "Modify Host Group membership"
+ ],
+ "dn": "cn=modifyhostgroupmembership,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_rolegroup": [
+ "hostgroupadmin"
+ ]
+ },
+ {
+ "cn": [
+ "addservices"
+ ],
+ "description": [
+ "Add Services"
+ ],
+ "dn": "cn=addservices,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_rolegroup": [
+ "serviceadmin"
+ ]
+ },
+ {
+ "cn": [
+ "removeservices"
+ ],
+ "description": [
+ "Remove Services"
+ ],
+ "dn": "cn=removeservices,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_rolegroup": [
+ "serviceadmin"
+ ]
+ },
+ {
+ "cn": [
+ "addhrole",
+ "addroles"
+ ],
+ "description": [
+ "Add Roles"
+ ],
+ "dn": "cn=addroles,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_rolegroup": [
+ "delegationadmin"
+ ]
+ },
+ {
+ "cn": [
+ "removeroles"
+ ],
+ "description": [
+ "Remove Roles"
+ ],
+ "dn": "cn=removeroles,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_rolegroup": [
+ "delegationadmin"
+ ]
+ },
+ {
+ "cn": [
+ "modifyroles"
+ ],
+ "description": [
+ "Modify Roles"
+ ],
+ "dn": "cn=modifyroles,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_rolegroup": [
+ "delegationadmin"
+ ]
+ },
+ {
+ "cn": [
+ "modifyrolegroupmembership"
+ ],
+ "description": [
+ "Modify Role Group membership"
+ ],
+ "dn": "cn=modifyrolegroupmembership,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_rolegroup": [
+ "delegationadmin"
+ ]
+ },
+ {
+ "cn": [
+ "modifytaskgroupmembership"
+ ],
+ "description": [
+ "Modify Task Group membership"
+ ],
+ "dn": "cn=modifytaskgroupmembership,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_rolegroup": [
+ "delegationadmin"
+ ]
+ },
+ {
+ "cn": [
+ "addautomount"
+ ],
+ "description": [
+ "Add Automount maps/keys"
+ ],
+ "dn": "cn=addautomount,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_rolegroup": [
+ "automountadmin"
+ ]
+ },
+ {
+ "cn": [
+ "removeautomount"
+ ],
+ "description": [
+ "Remove Automount maps/keys"
+ ],
+ "dn": "cn=removeautomount,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_rolegroup": [
+ "automountadmin"
+ ]
+ },
+ {
+ "cn": [
+ "addnetgroups"
+ ],
+ "description": [
+ "Add netgroups"
+ ],
+ "dn": "cn=addnetgroups,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_rolegroup": [
+ "netgroupadmin"
+ ]
+ },
+ {
+ "cn": [
+ "removenetgroups"
+ ],
+ "description": [
+ "Remove netgroups"
+ ],
+ "dn": "cn=removenetgroups,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_rolegroup": [
+ "netgroupadmin"
+ ]
+ },
+ {
+ "cn": [
+ "modifynetgroups"
+ ],
+ "description": [
+ "Modify netgroups"
+ ],
+ "dn": "cn=modifynetgroups,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_rolegroup": [
+ "netgroupadmin"
+ ]
+ },
+ {
+ "cn": [
+ "modifynetgroupmembership"
+ ],
+ "description": [
+ "Modify netgroup membership"
+ ],
+ "dn": "cn=modifynetgroupmembership,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_rolegroup": [
+ "netgroupadmin"
+ ]
+ },
+ {
+ "cn": [
+ "manage_host_keytab"
+ ],
+ "description": [
+ "Manage host keytab"
+ ],
+ "dn": "cn=manage_host_keytab,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_rolegroup": [
+ "hostadmin",
+ "enrollhost"
+ ]
+ },
+ {
+ "cn": [
+ "manage_host_keytab",
+ "update_dns",
+ "update_sn"
+ ],
+ "description": [
+ "Updates DNS"
+ ],
+ "dn": "cn=update_dns,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_rolegroup": [
+ "dnsadmin",
+ "dnsserver"
+ ]
+ },
+ {
+ "cn": [
+ "modifyservices"
+ ],
+ "description": [
+ "Modify Services"
+ ],
+ "dn": "cn=modifyservices,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_rolegroup": [
+ "serviceadmin"
+ ]
+ },
+ {
+ "cn": [
+ "enroll_host"
+ ],
+ "description": [
+ "Enroll a host"
+ ],
+ "dn": "cn=enroll_host,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_rolegroup": [
+ "hostadmin",
+ "enrollhost"
+ ]
+ },
+ {
+ "cn": [
+ "retrieve_certs"
+ ],
+ "description": [
+ "Retrieve SSL Certificates"
+ ],
+ "dn": "cn=retrieve_certs,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_rolegroup": [
+ "certadmin"
+ ]
+ },
+ {
+ "cn": [
+ "request_certs"
+ ],
+ "description": [
+ "Request a SSL Certificate"
+ ],
+ "dn": "cn=request_certs,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_rolegroup": [
+ "certadmin"
+ ]
+ },
+ {
+ "cn": [
+ "request_cert_different_host"
+ ],
+ "description": [
+ "Request a SSL Certificate from a different host"
+ ],
+ "dn": "cn=request_cert_different_host,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_rolegroup": [
+ "certadmin"
+ ]
+ },
+ {
+ "cn": [
+ "certificate_status"
+ ],
+ "description": [
+ "Status of cert request"
+ ],
+ "dn": "cn=certificate_status,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_rolegroup": [
+ "certadmin"
+ ]
+ },
+ {
+ "cn": [
+ "revoke_certificate"
+ ],
+ "description": [
+ "Revoke Certificate"
+ ],
+ "dn": "cn=revoke_certificate,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_rolegroup": [
+ "certadmin"
+ ]
+ },
+ {
+ "cn": [
+ "certificate_remove_hold"
+ ],
+ "description": [
+ "Certificate Remove Hold"
+ ],
+ "dn": "cn=certificate_remove_hold,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_rolegroup": [
+ "certadmin"
+ ]
+ },
+ {
+ "cn": [
+ "managereplica"
+ ],
+ "description": [
+ "Manage Replication Agreements"
+ ],
+ "dn": "cn=managereplica,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_rolegroup": [
+ "replicaadmin"
+ ]
+ },
+ {
+ "cn": [
+ "deletereplica"
+ ],
+ "description": [
+ "Delete Replication Agreements"
+ ],
+ "dn": "cn=deletereplica,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_rolegroup": [
+ "replicaadmin"
+ ]
+ },
+ {
+ "cn": [
+ "addentitlements"
+ ],
+ "description": [
+ "Add Entitlements"
+ ],
+ "dn": "cn=addentitlements,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_rolegroup": [
+ "entitlementadmin"
+ ]
+ },
+ {
+ "cn": [
+ "removeentitlements"
+ ],
+ "description": [
+ "Remove Entitlements"
+ ],
+ "dn": "cn=removeentitlements,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_rolegroup": [
+ "entitlementadmin"
+ ]
+ },
+ {
+ "cn": [
+ "modifyentitlements"
+ ],
+ "description": [
+ "Modify Entitlements"
+ ],
+ "dn": "cn=modifyentitlements,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "member_rolegroup": [
+ "entitlementadmin"
+ ]
+ },
+ {
+ "cn": [
+ "testtaskgroup"
+ ],
+ "description": [
+ "test1"
+ ],
+ "dn": "cn=testtaskgroup,cn=taskgroups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com"
+ }
+ ],
+ "summary": "45 grupos de tarea coincidentes",
+ "truncated": false
+ }
+} \ No newline at end of file
diff --git a/install/ui/test/data/user_add.json b/install/ui/test/data/user_add.json
new file mode 100644
index 000000000..e6a98b5c2
--- /dev/null
+++ b/install/ui/test/data/user_add.json
@@ -0,0 +1,49 @@
+{
+ "error": null,
+ "id": 10,
+ "result": {
+ "result": {
+ "dn": "uid=snuffy,cn=users,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "gecos": [
+ "snuffy"
+ ],
+ "givenname": [
+ "Aloysius"
+ ],
+ "homedirectory": [
+ "/home/snuffy"
+ ],
+ "ipauniqueid": [
+ "a4ce7d19-b439-11df-a9ae-525400674dcd"
+ ],
+ "krbprincipalname": [
+ "snuffy@AYOUNG.BOSTON.DEVEL.REDHAT.COM"
+ ],
+ "loginshell": [
+ "/bin/sh"
+ ],
+ "objectclass": [
+ "top",
+ "person",
+ "organizationalperson",
+ "inetorgperson",
+ "inetuser",
+ "posixaccount",
+ "krbprincipalaux",
+ "krbticketpolicyaux",
+ "ipaobject"
+ ],
+ "sn": [
+ "Snuffleupagus"
+ ],
+ "uid": [
+ "snuffy"
+ ],
+ "uidnumber": [
+ "1869788865"
+ ]
+ },
+ "summary": "Added user \"snuffy\"",
+ "value": "snuffy"
+ }
+}
diff --git a/install/ui/test/data/user_disable.json b/install/ui/test/data/user_disable.json
new file mode 100644
index 000000000..75a71fdf6
--- /dev/null
+++ b/install/ui/test/data/user_disable.json
@@ -0,0 +1,9 @@
+{
+ "error": null,
+ "id": 6,
+ "result": {
+ "result": true,
+ "summary": "Disabled user account \"rfrank\"",
+ "value": "rfrank"
+ }
+} \ No newline at end of file
diff --git a/install/ui/test/data/user_enable.json b/install/ui/test/data/user_enable.json
new file mode 100644
index 000000000..c596c81da
--- /dev/null
+++ b/install/ui/test/data/user_enable.json
@@ -0,0 +1,9 @@
+{
+ "error": null,
+ "id": 6,
+ "result": {
+ "result": true,
+ "summary": "Enabled user account \"rfrank\"",
+ "value": "rfrank"
+ }
+} \ No newline at end of file
diff --git a/install/ui/test/data/user_find.json b/install/ui/test/data/user_find.json
new file mode 100644
index 000000000..8a4094712
--- /dev/null
+++ b/install/ui/test/data/user_find.json
@@ -0,0 +1,243 @@
+
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "count": 4,
+ "result": [
+ {
+ "cn": [
+ "Administrator"
+ ],
+ "dn": "uid=admin,cn=users,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "gecos": [
+ "Administrator"
+ ],
+ "gidnumber": [
+ "444194797"
+ ],
+ "homedirectory": [
+ "/home/admin"
+ ],
+ "krblastpwdchange": [
+ "20100614200400Z"
+ ],
+ "krbpasswordexpiration": [
+ "20100912200400Z"
+ ],
+ "krbprincipalname": [
+ "admin@AYOUNG.BOSTON.DEVEL.REDHAT.COM"
+ ],
+ "loginshell": [
+ "/bin/bash"
+ ],
+ "memberof_group": [
+ "admins"
+ ],
+ "memberof_rolegroup": [
+ "replicaadmin"
+ ],
+ "memberof_taskgroup": [
+ "managereplica",
+ "deletereplica"
+ ],
+ "objectclass": [
+ "top",
+ "person",
+ "posixaccount",
+ "krbprincipalaux",
+ "krbticketpolicyaux",
+ "inetuser"
+ ],
+ "sn": [
+ "Administrator"
+ ],
+ "uid": [
+ "admin"
+ ],
+ "uidnumber": [
+ "444194797"
+ ]
+ },
+ {
+ "cn": [
+ "Kermit Frog"
+ ],
+ "dn": "uid=kfrog,cn=users,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "gecos": [
+ "Some of my best friends are Geckos"
+ ],
+ "gidnumber": [
+ "444194798"
+ ],
+ "givenname": [
+ "Kermit"
+ ],
+ "homedirectory": [
+ "/home/kfrog"
+ ],
+ "ipauniqueid": [
+ "89dc1f68-77f3-11df-afb7-525400ed2d11"
+ ],
+ "krbprincipalname": [
+ "kfrog"
+ ],
+ "loginshell": [
+ "/bin/sh"
+ ],
+ "mail": [
+ "kfrog@pbs.org"
+ ],
+ "memberof_group": [
+ "ipausers"
+ ],
+ "objectclass": [
+ "top",
+ "person",
+ "organizationalperson",
+ "inetorgperson",
+ "inetuser",
+ "posixaccount",
+ "krbprincipalaux",
+ "krbticketpolicyaux",
+ "ipaobject"
+ ],
+ "sn": [
+ "Frog"
+ ],
+ "street": [
+ "55 Seasame Street"
+ ],
+ "title": [
+ "Reporter"
+ ],
+ "uid": [
+ "kfrog"
+ ],
+ "uidnumber": [
+ "444194798"
+ ]
+ },
+ {
+ "cn": [
+ "Oscar Grouch"
+ ],
+ "dn": "uid=scram,cn=users,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "gecos": [
+ "scram"
+ ],
+ "gidnumber": [
+ "444194798"
+ ],
+ "givenname": [
+ "Oscar"
+ ],
+ "homedirectory": [
+ "/home/trash"
+ ],
+ "ipauniqueid": [
+ "adba909c-77f3-11df-ae3f-525400ed2d11"
+ ],
+ "krbprincipalname": [
+ "scram"
+ ],
+ "loginshell": [
+ "/bin/sh"
+ ],
+ "mail": [
+ "oscar@pbs.org"
+ ],
+ "memberof_group": [
+ "ipausers"
+ ],
+ "objectclass": [
+ "top",
+ "person",
+ "organizationalperson",
+ "inetorgperson",
+ "inetuser",
+ "posixaccount",
+ "krbprincipalaux",
+ "krbticketpolicyaux",
+ "ipaobject"
+ ],
+ "sn": [
+ "Grouch"
+ ],
+ "street": [
+ "123a Sesame Street"
+ ],
+ "title": [
+ "Sys Admin"
+ ],
+ "uid": [
+ "scram"
+ ],
+ "uidnumber": [
+ "444194799"
+ ]
+ },
+ {
+ "cn": [
+ "Sid Monster"
+ ],
+ "dn": "uid=cookie,cn=users,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "gecos": [
+ "cookie"
+ ],
+ "gidnumber": [
+ "444194798"
+ ],
+ "givenname": [
+ "Sid"
+ ],
+ "homedirectory": [
+ "cookie"
+ ],
+ "ipauniqueid": [
+ "c7d10507-77f3-11df-ac53-525400ed2d11"
+ ],
+ "krbprincipalname": [
+ "cookie"
+ ],
+ "loginshell": [
+ "/bin/sh"
+ ],
+ "mail": [
+ "cookie@pbs.org"
+ ],
+ "memberof_group": [
+ "ipausers"
+ ],
+ "objectclass": [
+ "top",
+ "person",
+ "organizationalperson",
+ "inetorgperson",
+ "inetuser",
+ "posixaccount",
+ "krbprincipalaux",
+ "krbticketpolicyaux",
+ "ipaobject"
+ ],
+ "sn": [
+ "Monster"
+ ],
+ "street": [
+ "123 Sesame Street"
+ ],
+ "title": [
+ "Chef"
+ ],
+ "uid": [
+ "cookie"
+ ],
+ "uidnumber": [
+ "444194800"
+ ]
+ }
+ ],
+ "summary": "4 users matched",
+ "truncated": false
+ }
+}
diff --git a/install/ui/test/data/user_memberof_group.json b/install/ui/test/data/user_memberof_group.json
new file mode 100644
index 000000000..e8f7a8fa5
--- /dev/null
+++ b/install/ui/test/data/user_memberof_group.json
@@ -0,0 +1,64 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "count": 2,
+ "results": [
+ {
+ "error": null,
+ "result": {
+ "cn": [
+ "ipausers"
+ ],
+ "description": [
+ "Default group for all users"
+ ],
+ "dn": "cn=ipausers,cn=groups,cn=accounts,dc=dev,dc=example,dc=com",
+ "gidnumber": [
+ "1662072956"
+ ],
+ "member_user": [
+ "test",
+ "admin"
+ ],
+ "objectclass": [
+ "top",
+ "groupofnames",
+ "nestedgroup",
+ "ipausergroup",
+ "posixgroup"
+ ]
+ },
+ "summary": null,
+ "value": "ipausers"
+ },
+ {
+ "error": null,
+ "result": {
+ "cn": [
+ "editors"
+ ],
+ "description": [
+ "Limited admins who can edit other users"
+ ],
+ "dn": "cn=editors,cn=groups,cn=accounts,dc=dev,dc=example,dc=com",
+ "gidnumber": [
+ "1662072957"
+ ],
+ "member_user": [
+ "test"
+ ],
+ "objectclass": [
+ "top",
+ "groupofnames",
+ "posixgroup",
+ "ipausergroup",
+ "nestedGroup"
+ ]
+ },
+ "summary": null,
+ "value": "editors"
+ }
+ ]
+ }
+}
diff --git a/install/ui/test/data/user_mod.json b/install/ui/test/data/user_mod.json
new file mode 100644
index 000000000..c77012c14
--- /dev/null
+++ b/install/ui/test/data/user_mod.json
@@ -0,0 +1,162 @@
+{
+ "error": null,
+ "id": 6,
+ "result": {
+ "result": {
+ "attributelevelrights": {
+ "aci": "rscwo",
+ "audio": "rscwo",
+ "businesscategory": "rscwo",
+ "carlicense": "rscwo",
+ "cn": "rscwo",
+ "departmentnumber": "rscwo",
+ "description": "rscwo",
+ "destinationindicator": "rscwo",
+ "dialupaccess": "rscwo",
+ "displayname": "rscwo",
+ "employeenumber": "rscwo",
+ "employeetype": "rscwo",
+ "facsimiletelephonenumber": "rscwo",
+ "gecos": "rscwo",
+ "gidnumber": "rscwo",
+ "givenname": "rscwo",
+ "homedirectory": "rscwo",
+ "homephone": "rscwo",
+ "homepostaladdress": "rscwo",
+ "inetuserhttpurl": "rscwo",
+ "inetuserstatus": "rscwo",
+ "initials": "rscwo",
+ "internationalisdnnumber": "rscwo",
+ "ipauniqueid": "rsc",
+ "jpegphoto": "rscwo",
+ "krbcanonicalname": "rscwo",
+ "krbextradata": "rscwo",
+ "krblastfailedauth": "rscwo",
+ "krblastpwdchange": "rscwo",
+ "krblastsuccessfulauth": "rscwo",
+ "krbloginfailedcount": "rscwo",
+ "krbmaxrenewableage": "rscwo",
+ "krbmaxticketlife": "rscwo",
+ "krbpasswordexpiration": "rscwo",
+ "krbprincipalaliases": "rscwo",
+ "krbprincipalexpiration": "rscwo",
+ "krbprincipalkey": "wo",
+ "krbprincipalname": "rscwo",
+ "krbprincipaltype": "rscwo",
+ "krbpwdhistory": "rscwo",
+ "krbpwdpolicyreference": "rscwo",
+ "krbticketflags": "rscwo",
+ "krbticketpolicyreference": "rscwo",
+ "krbupenabled": "rscwo",
+ "l": "rscwo",
+ "labeleduri": "rscwo",
+ "loginshell": "rscwo",
+ "mail": "rscwo",
+ "manager": "rscwo",
+ "memberof": "rsc",
+ "mepmanagedentry": "rscwo",
+ "mobile": "rscwo",
+ "nsaccountlock": "rscwo",
+ "o": "rscwo",
+ "objectclass": "rscwo",
+ "ou": "rscwo",
+ "pager": "rscwo",
+ "photo": "rscwo",
+ "physicaldeliveryofficename": "rscwo",
+ "postaladdress": "rscwo",
+ "postalcode": "rscwo",
+ "postofficebox": "rscwo",
+ "preferreddeliverymethod": "rscwo",
+ "preferredlanguage": "rscwo",
+ "registeredaddress": "rscwo",
+ "roomnumber": "rscwo",
+ "secretary": "rscwo",
+ "seealso": "rscwo",
+ "sn": "rscwo",
+ "st": "rscwo",
+ "street": "rscwo",
+ "telephonenumber": "rscwo",
+ "teletexterminalidentifier": "rscwo",
+ "telexnumber": "rscwo",
+ "title": "rscwo",
+ "uid": "rscwo",
+ "uidnumber": "rscwo",
+ "usercertificate": "rscwo",
+ "userpassword": "wo",
+ "userpkcs12": "rscwo",
+ "usersmimecertificate": "rscwo",
+ "x121address": "rscwo",
+ "x500uniqueidentifier": "rscwo"
+ },
+ "cn": [
+ "Kermit The Frog"
+ ],
+ "gecos": [
+ "kfrog"
+ ],
+ "gidnumber": [
+ "953553261"
+ ],
+ "givenname": [
+ "Kermit"
+ ],
+ "homedirectory": [
+ "/home/kfrog"
+ ],
+ "ipauniqueid": [
+ "a2854798-e7d811df-b69ad8ca-cb44a24c"
+ ],
+ "krblastpwdchange": [
+ "20101105172205Z"
+ ],
+ "krbpasswordexpiration": [
+ "20101105172205Z"
+ ],
+ "krbprincipalname": [
+ "kfrog@AYOUNG.BOSTON.DEVEL.REDHAT.COM"
+ ],
+ "krbpwdpolicyreference": [
+ "cn=global_policy,cn=AYOUNG.BOSTON.DEVEL.REDHAT.COM,cn=kerberos,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com"
+ ],
+ "loginshell": [
+ "/bin/sh"
+ ],
+ "mail": [
+ "kermit@muppets.com"
+ ],
+ "memberof_group": [
+ "ipausers",
+ "muppets"
+ ],
+ "mepmanagedentry": [
+ "cn=kfrog,cn=groups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com"
+ ],
+ "nsaccountlock": [
+ "False"
+ ],
+ "objectclass": [
+ "top",
+ "person",
+ "organizationalperson",
+ "inetorgperson",
+ "inetuser",
+ "posixaccount",
+ "krbprincipalaux",
+ "krbticketpolicyaux",
+ "ipaobject",
+ "mepOriginEntry"
+ ],
+ "sn": [
+ "Frog"
+ ],
+ "uid": [
+ "kfrog"
+ ],
+ "uidnumber": [
+ "953553261"
+ ]
+ },
+ "summary": "Modified user \"kfrog\"",
+ "value": "kfrog"
+ }
+}
diff --git a/install/ui/test/data/user_show.json b/install/ui/test/data/user_show.json
new file mode 100644
index 000000000..33893d77b
--- /dev/null
+++ b/install/ui/test/data/user_show.json
@@ -0,0 +1,163 @@
+{
+ "error": null,
+ "id": 6,
+ "result": {
+ "result": {
+ "attributelevelrights": {
+ "aci": "rscwo",
+ "audio": "rscwo",
+ "businesscategory": "rscwo",
+ "carlicense": "rscwo",
+ "cn": "rscwo",
+ "departmentnumber": "rscwo",
+ "description": "rscwo",
+ "destinationindicator": "rscwo",
+ "dialupaccess": "rscwo",
+ "displayname": "rscwo",
+ "employeenumber": "rscwo",
+ "employeetype": "rscwo",
+ "facsimiletelephonenumber": "rscwo",
+ "gecos": "rscwo",
+ "gidnumber": "rscwo",
+ "givenname": "rscwo",
+ "homedirectory": "rscwo",
+ "homephone": "rscwo",
+ "homepostaladdress": "rscwo",
+ "inetuserhttpurl": "rscwo",
+ "inetuserstatus": "rscwo",
+ "initials": "rscwo",
+ "internationalisdnnumber": "rscwo",
+ "ipauniqueid": "rsc",
+ "jpegphoto": "rscwo",
+ "krbcanonicalname": "rscwo",
+ "krbextradata": "rscwo",
+ "krblastfailedauth": "rscwo",
+ "krblastpwdchange": "rscwo",
+ "krblastsuccessfulauth": "rscwo",
+ "krbloginfailedcount": "rscwo",
+ "krbmaxrenewableage": "rscwo",
+ "krbmaxticketlife": "rscwo",
+ "krbpasswordexpiration": "rscwo",
+ "krbprincipalaliases": "rscwo",
+ "krbprincipalexpiration": "rscwo",
+ "krbprincipalkey": "wo",
+ "krbprincipalname": "rscwo",
+ "krbprincipaltype": "rscwo",
+ "krbpwdhistory": "rscwo",
+ "krbpwdpolicyreference": "rscwo",
+ "krbticketflags": "rscwo",
+ "krbticketpolicyreference": "rscwo",
+ "krbupenabled": "rscwo",
+ "l": "rscwo",
+ "labeleduri": "rscwo",
+ "loginshell": "rscwo",
+ "mail": "rscwo",
+ "manager": "rscwo",
+ "memberof": "rsc",
+ "mepmanagedentry": "rscwo",
+ "mobile": "rscwo",
+ "nsaccountlock": "rscwo",
+ "o": "rscwo",
+ "objectclass": "rscwo",
+ "ou": "rscwo",
+ "pager": "rscwo",
+ "photo": "rscwo",
+ "physicaldeliveryofficename": "rscwo",
+ "postaladdress": "rscwo",
+ "postalcode": "rscwo",
+ "postofficebox": "rscwo",
+ "preferreddeliverymethod": "rscwo",
+ "preferredlanguage": "rscwo",
+ "registeredaddress": "rscwo",
+ "roomnumber": "rscwo",
+ "secretary": "rscwo",
+ "seealso": "rscwo",
+ "sn": "rscwo",
+ "st": "rscwo",
+ "street": "rscwo",
+ "telephonenumber": "rscwo",
+ "teletexterminalidentifier": "rscwo",
+ "telexnumber": "rscwo",
+ "title": "rscwo",
+ "uid": "rscwo",
+ "uidnumber": "rscwo",
+ "usercertificate": "rscwo",
+ "userpassword": "wo",
+ "userpkcs12": "rscwo",
+ "usersmimecertificate": "rscwo",
+ "x121address": "rscwo",
+ "x500uniqueidentifier": "rscwo"
+ },
+ "cn": [
+ "Kermit The Frog"
+ ],
+ "dn": "uid=kfrog,cn=users,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com",
+ "gecos": [
+ "kfrog"
+ ],
+ "gidnumber": [
+ "953553261"
+ ],
+ "givenname": [
+ "Kermit"
+ ],
+ "homedirectory": [
+ "/home/kfrog"
+ ],
+ "ipauniqueid": [
+ "a2854798-e7d811df-b69ad8ca-cb44a24c"
+ ],
+ "krblastpwdchange": [
+ "20101105172205Z"
+ ],
+ "krbpasswordexpiration": [
+ "20101105172205Z"
+ ],
+ "krbprincipalname": [
+ "kfrog@AYOUNG.BOSTON.DEVEL.REDHAT.COM"
+ ],
+ "krbpwdpolicyreference": [
+ "cn=global_policy,cn=AYOUNG.BOSTON.DEVEL.REDHAT.COM,cn=kerberos,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com"
+ ],
+ "loginshell": [
+ "/bin/sh"
+ ],
+ "mail": [
+ "kermit@muppets.com"
+ ],
+ "memberof_group": [
+ "ipausers",
+ "muppets"
+ ],
+ "mepmanagedentry": [
+ "cn=kfrog,cn=groups,cn=accounts,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com"
+ ],
+ "nsaccountlock": [
+ "False"
+ ],
+ "objectclass": [
+ "top",
+ "person",
+ "organizationalperson",
+ "inetorgperson",
+ "inetuser",
+ "posixaccount",
+ "krbprincipalaux",
+ "krbticketpolicyaux",
+ "ipaobject",
+ "mepOriginEntry"
+ ],
+ "sn": [
+ "Frog"
+ ],
+ "uid": [
+ "kfrog"
+ ],
+ "uidnumber": [
+ "953553261"
+ ]
+ },
+ "summary": null,
+ "value": "kfrog"
+ }
+}
diff --git a/install/ui/test/data/whoami.json b/install/ui/test/data/whoami.json
new file mode 100644
index 000000000..a922d3720
--- /dev/null
+++ b/install/ui/test/data/whoami.json
@@ -0,0 +1,7 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "summary": "admin@AYOUNG.BOSTON.DEVEL.REDHAT.COM"
+ }
+}
diff --git a/install/ui/test/details_tests.html b/install/ui/test/details_tests.html
new file mode 100644
index 000000000..3cb20c562
--- /dev/null
+++ b/install/ui/test/details_tests.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Details Test Suite</title>
+ <link rel="stylesheet" href="qunit.css" type="text/css" media="screen">
+ <script type="text/javascript" src="qunit.js"></script>
+ <script type="text/javascript" src="../jquery.js"></script>
+ <script type="text/javascript" src="../jquery.ba-bbq.js"></script>
+ <script type="text/javascript" src="../jquery-ui.js"></script>
+ <script type="text/javascript" src="../ipa.js"></script>
+ <script type="text/javascript" src="../widget.js"></script>
+ <script type="text/javascript" src="../details.js"></script>
+ <script type="text/javascript" src="../entity.js"></script>
+
+ <script type="text/javascript" src="details_tests.js"></script>
+</head>
+<body>
+ <h1 id="qunit-header">Details Test Suite</h1>
+ <h2 id="qunit-banner"></h2>
+ <div id="qunit-testrunner-toolbar"></div>
+ <h2 id="qunit-userAgent"></h2>
+ <ol id="qunit-tests"></ol>
+ <div id="qunit-fixture"></div>
+</body>
+</html>
diff --git a/install/ui/test/details_tests.js b/install/ui/test/details_tests.js
new file mode 100644
index 000000000..d832bd26d
--- /dev/null
+++ b/install/ui/test/details_tests.js
@@ -0,0 +1,327 @@
+/* Authors:
+ * Adam Young <ayoung@redhat.com>
+ *
+ * Copyright (C) 2010 Red Hat
+ * see file 'COPYING' for use and warranty information
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+module('details');
+
+test("Testing IPA.details_section.create().", function() {
+
+ IPA.ajax_options.async = false;
+
+ IPA.init(
+ "data",
+ true,
+ function(data, text_status, xhr) {
+ ok(true, "ipa_init() succeeded.");
+ },
+ function(xhr, text_status, error_thrown) {
+ ok(false, "ipa_init() failed: "+error_thrown);
+ }
+ );
+
+ var section = IPA.stanza({name:'IDIDID', label:'NAMENAMENAME'}).
+ input({name:'cn'}).
+ input({name:'description'}).
+ input({name:'number'});
+
+
+ var fields = section.fields;
+ var container = $("<div/>");
+ section.create(container);
+
+ var dl = $('dl', container);
+
+ same(
+ dl.length, 1,
+ 'Checking dl tag'
+ );
+
+ same(
+ dl.attr('id'), section.name,
+ 'Checking section name'
+ );
+
+ var dts = $('dt', dl);
+ same(
+ dts.length, fields.length, // each field generates dt & dd
+ 'Checking number of children'
+ );
+
+ for (var i=0; i<fields.length; i++) {
+ var field = fields[i];
+
+ var dt = dts.get(i);
+ same(
+ dt.innerHTML, field.label+':',
+ 'Checking field '+field.name+'\'s label'
+ );
+
+ var span = $('span[name='+field.name+']', dl);
+
+ ok(
+ span.length,
+ 'Checking span tag for field '+field.name
+ );
+
+ var dd = $('dd', span);
+
+ ok(
+ dd.length == 0,
+ 'Checking dd tag for field '+field.name
+ );
+ }
+});
+
+
+
+test("Testing details lifecycle: create, setup, load.", function(){
+
+ IPA.ajax_options.async = false;
+
+ IPA.init(
+ "data",
+ true,
+ function(data, text_status, xhr) {
+ ok(true, "ipa_init() succeeded.");
+ },
+ function(xhr, text_status, error_thrown) {
+ ok(false, "ipa_init() failed: "+error_thrown);
+ }
+ );
+
+ var result = {};
+
+ IPA.cmd(
+ 'user_show',
+ ['kfrog'],
+ {},
+ function(data, text_status, xhr) {
+ result = data.result.result;
+ ok(true, "IPA.cmd() succeeded.");
+ },
+ function(xhr, text_status, error_thrown) {
+ ok(false, "IPA.cmd() failed: "+error_thrown);
+ }
+ );
+
+ var setup_status_called = false;
+ var save_password_called= false;
+ var load_manager_called = false;
+ var load_success_called = false;
+ var load_failure_called = false;
+ var update_success_called = false;
+ var update_failure_called = false;
+
+ function setup_status(){
+ setup_status_called = true;
+ }
+
+ function save_password(){
+ save_password_called = true;
+ return [];
+ }
+
+ function load_manager(){
+ load_manager_called = true;
+ }
+
+ function setup_st(){
+ }
+
+ var container = $("<div/>");
+ var obj_name = 'user';
+ IPA.entity_set_details_definition(obj_name, [
+ IPA.stanza({name:'identity', label:'Identity Details'}).
+ input({name:'title'}).
+ input({name:'givenname'}).
+ input({name:'sn'}).
+ input({name:'cn'}).
+ input({name:'displayname'}).
+ input({name:'initials'}),
+ IPA.stanza({name:'account', label:'Account Details'}).
+ input({name:'status', setup: setup_status}).
+ input({name:'uid'}).
+ input({name:'userpassword', save: save_password}).
+ input({name:'uidnumber'}).
+ input({name:'gidnumber'}).
+ input({name:'homedirectory'}),
+ IPA.stanza({name:'contact', label:'Contact Details'}).
+ input({name:'mail'}).
+ input({name:'telephonenumber'}),
+ IPA.stanza({name:'address'}).
+ input({name:'street'}).
+ input({name:'location'}).
+ input({name:'state', setup: setup_st}).
+ input({name:'postalcode'}),
+ IPA.stanza({name:'employee', label:'Employee Information'}).
+ input({name:'ou'}).
+ input({name:'manager', load: load_manager}),
+ IPA.stanza({name:'misc', label:'Misc. Information'}).
+ input({name:'carlicense'})
+ ]);
+
+ var entity = IPA.fetch_entity(obj_name);
+ var facet = entity.get_facet('details');
+ facet.create(container);
+ facet.setup(container);
+ facet.load(result);
+
+ var contact = container.find('dl#contact.entryattrs');
+
+ ok(
+ contact,
+ 'dl tag for contact is created'
+ );
+
+ var identity = container.find('dl#identity.entryattrs');
+
+ ok(
+ identity,
+ 'dl tag for identity is created'
+ );
+
+ var dts = identity.find('dt');
+
+ same(
+ dts.length, 6,
+ 'Checking dt tags for identity'
+ );
+
+ container.attr('id','user');
+
+ ok (
+ setup_status_called,
+ 'Setup status called'
+ );
+
+ ok (load_manager_called, 'load manager called');
+
+ facet.update(
+ function(){update_success_called = true},
+ function(){update_failure_called = true}
+ );
+
+ ok (update_success_called,'update success called');
+ ok (!update_failure_called,'update failure not called');
+ ok (save_password_called, 'save password called');
+
+});
+
+
+test("Testing create_input().", function() {
+
+ var field = IPA.details_field({
+ 'name': "name"
+ });
+
+ var name = "name";
+ var value="value";
+ var rights = 'rscwo'
+ var input = field.create_input(value, null, rights);
+ ok(input,"input not null");
+
+ var text = input.find('input');
+ ok(text);
+
+ same(text[0].name,name );
+ same(text[0].value,value );
+ same(text[0].type,"text" );
+});
+
+test("Testing create_input() read only .", function() {
+
+ var field = IPA.details_field({
+ 'name': "name"
+ });
+
+ var name = "name";
+ var value="value";
+ var rights = 'rsc'
+ var input = field.create_input(value, null, rights);
+ ok(input,"input not null");
+
+ var text = input.find('input');
+ ok(text);
+
+ same(text[0].name,name );
+ same(text[0].value,value );
+ same(text[0].type,"text" );
+ ok(text[0].disabled);
+
+});
+
+
+
+
+test("Testing IPA.details_section_setup again()",function(){
+
+ var section = IPA.stanza({name: 'IDIDID', label: 'NAMENAMENAME'}).
+ input({name:'cn', label:'Entity Name'}).
+ input({name:'description', label:'Description'}).
+ input({name:'number', label:'Entity ID'});
+ var fields = section.fields;
+ var container = $("<div title='entity'/>");
+ var details = $("<div/>");
+ container.append(details);
+
+ var result = {};
+
+ section.create(container);
+ section.setup(container);
+ section.load(result);
+
+ //var h2= container.find('h2');
+ //ok(h2);
+ //ok(h2[0].innerHTML.indexOf(section.label) > 1,"find name in html");
+
+ var dl = $('dl', container);
+ ok(
+ dl.length,
+ 'dl is created'
+ );
+
+ var dt = $('dt', dl);
+ same(
+ dt.length, 3,
+ '3 dt'
+ );
+
+ var span = dt.next();
+ same(
+ span.length, 3,
+ '3 span'
+ );
+
+ same(
+ dl[0].id, section.name,
+ 'checking section name'
+ );
+
+ same(
+ dt[0].innerHTML, fields[0].label+":",
+ 'inner HTML matches label'
+ );
+
+ var dd = $('dd', span[0]);
+ same(
+ dd.length, 1,
+ '1 dd'
+ );
+});
diff --git a/install/ui/test/entity_tests.html b/install/ui/test/entity_tests.html
new file mode 100644
index 000000000..cd6b64095
--- /dev/null
+++ b/install/ui/test/entity_tests.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Entity Test Suite</title>
+ <link rel="stylesheet" href="qunit.css" type="text/css" media="screen">
+ <script type="text/javascript" src="qunit.js"></script>
+ <script type="text/javascript" src="../jquery.js"></script>
+ <script type="text/javascript" src="../jquery.ba-bbq.js"></script>
+ <script type="text/javascript" src="../ipa.js"></script>
+ <script type="text/javascript" src="../widget.js"></script>
+ <script type="text/javascript" src="../details.js"></script>
+ <script type="text/javascript" src="../search.js"></script>
+ <script type="text/javascript" src="../add.js"></script>
+ <script type="text/javascript" src="../associate.js"></script>
+ <script type="text/javascript" src="../navigation.js"></script>
+ <script type="text/javascript" src="../entity.js"></script>
+ <script type="text/javascript" src="entity_tests.js"></script>
+</head>
+<body>
+ <h1 id="qunit-header">Entity Test Suite</h1>
+ <h2 id="qunit-banner"></h2>
+ <div id="qunit-testrunner-toolbar"></div>
+ <h2 id="qunit-userAgent"></h2>
+ <ol id="qunit-tests"></ol>
+ <div id="qunit-fixture"></div>
+</body>
+</html>
diff --git a/install/ui/test/entity_tests.js b/install/ui/test/entity_tests.js
new file mode 100644
index 000000000..21fff48f8
--- /dev/null
+++ b/install/ui/test/entity_tests.js
@@ -0,0 +1,171 @@
+/* Authors:
+ * Endi Sukma Dewata <edewata@redhat.com>
+ *
+ * Copyright (C) 2010 Red Hat
+ * see file 'COPYING' for use and warranty information
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+module('entity');
+
+test('Testing IPA.entity_set_search_definition().', function() {
+
+ var uid_callback = function() {
+ return true;
+ };
+
+ IPA.entity_set_search_definition('user', [
+ ['uid', 'Login', uid_callback]
+ ]);
+
+ var facet = IPA.entity_get_search_facet('user');
+ ok(
+ facet,
+ 'IPA.entity_get_search_facet(\'user\') is not null'
+ );
+
+ var column = facet.get_columns()[0];
+ ok(
+ column,
+ 'column is not null'
+ );
+
+ equals(
+ column.name, 'uid',
+ 'column.name'
+ );
+
+ equals(
+ column.label, 'Login',
+ 'column.label'
+ );
+
+ ok(
+ column.setup,
+ 'column.setup not null'
+ );
+
+ ok(
+ column.setup(),
+ 'column.setup() works'
+ );
+});
+
+test('Testing ipa_facet_setup_views().', function() {
+
+ var orig_switch_and_show_page = IPA.switch_and_show_page;
+ IPA.ajax_options.async = false;
+
+ IPA.init(
+ 'data',
+ true,
+ function(data, text_status, xhr) {
+ ok(true, 'ipa_init() succeeded.');
+ },
+ function(xhr, text_status, error_thrown) {
+ ok(false, 'ipa_init() failed: '+error_thrown);
+ }
+ );
+
+ var entity = IPA.entity({
+ 'name': 'user'
+ });
+
+ IPA.add_entity(entity);
+
+ var facet = IPA.search_facet({
+ 'name': 'search',
+ 'label': 'Search'
+ });
+ entity.add_facet(facet);
+
+ entity.create_association_facets();
+
+ var container = $('<div/>');
+
+ entity.init();
+ entity.setup(container);
+
+ var counter = 0;
+ IPA.switch_and_show_page = function(entity_name, facet_name, pkey) {
+ counter++;
+ };
+
+ //Container now has two divs, one for the action panel one for content
+ var action_panel = facet.get_action_panel();
+ ok(action_panel.length, 'action panel exists');
+
+ var ul = $('ul', action_panel);
+
+ var views = ul.children();
+
+ /*6 Views:
+ one for each of 3 associations
+ one for search
+ one for details
+ a blank one for the action controls*/
+ equals(
+ views.length, 6,
+ 'Checking number of views'
+ );
+
+ var li = views.first();
+ ok( li.children().first().hasClass('action-controls'),
+ 'Checking that first item in list is placement for controls'
+ );
+
+ li = li.next(); // skip action controls
+ li = li.next(); // skip the header line for Member of
+
+ var attribute_members = IPA.metadata['user'].attribute_members;
+ for (var attribute_member in attribute_members) {
+ var objects = attribute_members[attribute_member];
+ for (var i = 0; i < objects.length; i++) {
+ var object = objects[i];
+ var title = attribute_member+'_'+object;
+
+ li = li.next();
+ var value = li.attr('title');
+ equals(
+ value, title,
+ 'Checking the '+title+' facet'
+ );
+ }
+ }
+
+ var pkey_input = $('input[name=pkey]', action_panel);
+ ok(pkey_input.length,'pkey input exists');
+ var search_facets = $('li.search-facet', action_panel);
+ equals(search_facets.length,0,'search facet should not show up in action panel');
+ var entity_facets = $('li.entity-facet', action_panel);
+ /*No longer automatically adding details, so ony the assoc. facets */
+ equals(entity_facets.length,4,'4 hidden entity facets in action panel');
+ entity_facets.each(function() {
+ ok( $(this).hasClass('entity-facet-disabled'),
+ 'entity facets are disabled');
+ });
+
+ for ( var entity_facet = entity_facets.first();
+ entity_facet.length;
+ entity_facet = entity_facet.next()){
+ entity_facet.click();
+ }
+
+ equals(counter, 0, 'links are disabled');
+
+ IPA.switch_and_show_page = orig_switch_and_show_page;
+});
+
+
diff --git a/install/ui/test/index.html b/install/ui/test/index.html
new file mode 100644
index 000000000..78b41e9b5
--- /dev/null
+++ b/install/ui/test/index.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>IPA Test Suite</title>
+ <link rel="stylesheet" href="qunit.css" type="text/css" media="screen">
+ <style type="text/css">
+#content {
+ font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial;
+ font-size: smaller;
+
+ border-bottom: 1px solid #fff;
+ padding: 0.5em 0.5em 0.5em 2.5em;
+
+ color: #2b81af;
+ background-color: #D2E0E6;
+}
+ </style>
+</head>
+<body>
+ <h1 id="qunit-header">IPA Test Suite</h1>
+
+ <h2 id="qunit-banner" class="qunit-pass"></h2>
+
+ <div id="content">
+ <a href="all_tests.html">Complete Test Suite</a>
+ <ul>
+ <li><a href="ipa_tests.html">Core Test Suite</a>
+ <li><a href="entity_tests.html">Entity Test Suite</a>
+ <li><a href="details_tests.html">Details Test Suite</a>
+ <li><a href="association_tests.html">Association Test Suite</a>
+ <li><a href="navigation_tests.html">Navigation Test Suite</a>
+ <li><a href="certificate_tests.html">Certificate Test Suite</a>
+ <li><a href="aci_tests.html">Access Control Interface Test Suite</a>
+
+ </ul>
+ </div>
+
+ <div id="qunit-testresult">
+ <br>
+ </div>
+
+</body>
+</html>
diff --git a/install/ui/test/ipa_tests.html b/install/ui/test/ipa_tests.html
new file mode 100644
index 000000000..903e71545
--- /dev/null
+++ b/install/ui/test/ipa_tests.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Core Test Suite</title>
+ <link rel="stylesheet" href="qunit.css" type="text/css" media="screen">
+ <link rel="stylesheet" type="text/css" href="../jquery-ui.css" />
+
+ <script type="text/javascript" src="qunit.js"></script>
+ <script type="text/javascript" src="../jquery.js"></script>
+ <script type="text/javascript" src="../jquery.ba-bbq.js"></script>
+ <script type="text/javascript" src="../jquery-ui.js"></script>
+ <script type="text/javascript" src="../ipa.js"></script>
+ <script type="text/javascript" src="ipa_tests.js"></script>
+</head>
+<body>
+ <h1 id="qunit-header">Core Test Suite</h1>
+ <h2 id="qunit-banner"></h2>
+ <div id="qunit-testrunner-toolbar"></div>
+ <h2 id="qunit-userAgent"></h2>
+ <ol id="qunit-tests"></ol>
+ <div id="qunit-fixture"></div>
+</body>
+</html>
diff --git a/install/ui/test/ipa_tests.js b/install/ui/test/ipa_tests.js
new file mode 100644
index 000000000..4fa0d1ea2
--- /dev/null
+++ b/install/ui/test/ipa_tests.js
@@ -0,0 +1,297 @@
+/* Authors:
+ * Endi Sukma Dewata <edewata@redhat.com>
+ *
+ * Copyright (C) 2010 Red Hat
+ * see file 'COPYING' for use and warranty information
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+module('ipa');
+
+test("Testing ipa_init().", function() {
+
+ expect(1);
+
+ IPA.ajax_options.async = false;
+
+ IPA.init(
+ "data",
+ true,
+ function(data, text_status, xhr) {
+ ok(true, "ipa_init() succeeded.");
+ },
+ function(xhr, text_status, error_thrown) {
+ ok(false, "ipa_init() failed: "+error_thrown);
+ }
+ );
+});
+
+test("Testing IPA.get_param_info().", function() {
+
+ var param_info = IPA.get_param_info("user", "uid");
+ ok(
+ param_info,
+ "IPA.get_param_info(\"user\", \"uid\") not null"
+ );
+
+ equals(
+ param_info["label"], "User login",
+ "IPA.get_param_info(\"user\", \"uid\")[\"label\"]"
+ );
+
+ equals(
+ IPA.get_param_info("user", "wrong_attribute"), null,
+ "IPA.get_param_info(\"user\", \"wrong_attribute\")"
+ );
+
+ equals(
+ IPA.get_param_info("user", null), null,
+ "IPA.get_param_info(\"user\", null)"
+ );
+
+ equals(
+ IPA.get_param_info("wrong_entity", "uid"), null,
+ "IPA.get_param_info(\"wrong_entity\", \"uid\")"
+ );
+
+ equals(
+ IPA.get_param_info(null, "uid"), null,
+ "IPA.get_param_info(null, \"uid\")"
+ );
+});
+
+test("Testing IPA.get_member_attribute().", function() {
+
+ equals(
+ IPA.get_member_attribute("user", "group"), "memberof",
+ "IPA.get_member_attribute(\"user\", \"group\")"
+ );
+
+ equals(
+ IPA.get_member_attribute("user", "host"), null,
+ "IPA.get_member_attribute(\"user\", \"host\")"
+ );
+
+ equals(
+ IPA.get_member_attribute("user", null), null,
+ "IPA.get_member_attribute(\"user\", null)"
+ );
+
+ equals(
+ IPA.get_member_attribute(null, "group"), null,
+ "IPA.get_member_attribute(null, \"group\")"
+ );
+});
+
+test("Testing successful IPA.cmd().", function() {
+
+ var method = 'method';
+ var args = ['arg1', 'arg2', 'arg3'];
+ var options = {
+ opt1: 'val1',
+ opt2: 'val2',
+ opt3: 'val3'
+ };
+ var object = 'object';
+
+ var success_handler_counter = 0;
+ var error_handler_counter = 0;
+
+ function success_handler(data, status, xhr) {
+ success_handler_counter++;
+ }
+
+ function error_handler(xhr, text_status, error_thrown) {
+ error_handler_counter++;
+ }
+
+ var orig = $.ajax;
+
+ var xhr = {};
+ var text_status = null;
+ var error_thrown = {name:'ERROR', message:'An error has occured'};
+
+ var ajax_counter = 0;
+
+ $.ajax = function(request) {
+ ajax_counter++;
+
+ equals(
+ request.url, "data/"+object+"_"+method+".json",
+ "Checking request.url"
+ );
+
+ var data = JSON.parse(request.data);
+
+ equals(
+ data.method, object+'_'+method,
+ "Checking method"
+ );
+
+ same(
+ data.params, [args, options],
+ "Checking parameters"
+ );
+
+ request.success(xhr, text_status, error_thrown);
+ };
+
+ IPA.cmd(method, args, options, success_handler, error_handler, object);
+
+ equals(
+ ajax_counter, 1,
+ "Checking ajax invocation counter"
+ );
+
+ var dialog = IPA.error_dialog.parent('.ui-dialog');
+
+ ok(
+ !dialog.length,
+ "The dialog box is not created."
+ );
+
+ ok(
+ success_handler_counter == 1 && error_handler_counter == 0,
+ "Only the success handler is called."
+ );
+
+ $.ajax = orig;
+});
+
+test("Testing unsuccessful IPA.cmd().", function() {
+
+ var method = 'method';
+ var args = ['arg1', 'arg2', 'arg3'];
+ var options = {
+ opt1: 'val1',
+ opt2: 'val2',
+ opt3: 'val3'
+ };
+ var object = 'object';
+
+ var success_handler_counter = 0;
+ var error_handler_counter = 0;
+
+ function success_handler(data, status, xhr) {
+ success_handler_counter++;
+ }
+
+ function error_handler(xhr, text_status, error_thrown) {
+ error_handler_counter++;
+ }
+
+ var orig = $.ajax;
+
+ var xhr = {};
+ var text_status = null;
+ var error_thrown = {name:'ERROR', message:'An error has occured'};
+
+ var ajax_counter = 0;
+
+ $.ajax = function(request) {
+ ajax_counter++;
+
+ equals(
+ request.url, "data/"+object+"_"+method+".json",
+ "Checking request.url"
+ );
+
+ var data = JSON.parse(request.data);
+
+ equals(
+ data.method, object+'_'+method,
+ "Checking method"
+ );
+
+ same(
+ data.params, [args, options],
+ "Checking parameters"
+ );
+
+ request.error(xhr, text_status, error_thrown);
+ };
+
+ IPA.cmd(method, args, options, success_handler, error_handler, object);
+
+ var dialog = IPA.error_dialog.parent('.ui-dialog');
+
+ equals(
+ ajax_counter, 1,
+ "Checking ajax invocation counter"
+ );
+
+ ok(
+ dialog.length == 1 && IPA.error_dialog.dialog('isOpen'),
+ "The dialog box is created and open."
+ );
+
+ ok(
+ success_handler_counter == 0 && error_handler_counter == 0,
+ "Initially none of the handlers are called."
+ );
+
+ // search the retry button from the beginning
+ var retry = $('button', dialog).first();
+ retry.trigger('click');
+
+ equals(
+ ajax_counter, 2,
+ "Checking ajax invocation counter"
+ );
+
+ ok(
+ success_handler_counter == 0 && error_handler_counter == 0,
+ "After 1st retry, none of the handlers are called."
+ );
+
+ // search the retry button from the beginning again because the dialog
+ // has been recreated
+ dialog = IPA.error_dialog.parent('.ui-dialog');
+ retry = $('button', dialog).first();
+ retry.trigger('click');
+
+ equals(
+ ajax_counter, 3,
+ "Checking ajax invocation counter"
+ );
+
+ ok(
+ success_handler_counter == 0 && error_handler_counter == 0,
+ "After 2nd retry, none of the handlers are called."
+ );
+
+ // search the cancel button from the beginning because the dialog has
+ // been recreated
+ dialog = IPA.error_dialog.parent('.ui-dialog');
+ var cancel = $('button', dialog).first().next();
+ cancel.trigger('click');
+
+ equals(
+ ajax_counter, 3,
+ "Checking ajax invocation counter"
+ );
+
+ ok(
+ !IPA.error_dialog.dialog('isOpen'),
+ "After cancel, the dialog box is closed."
+ );
+
+ ok(
+ success_handler_counter == 0 && error_handler_counter == 1,
+ "Only the error handler is called."
+ );
+
+ $.ajax = orig;
+});
diff --git a/install/ui/test/navigation_tests.html b/install/ui/test/navigation_tests.html
new file mode 100644
index 000000000..16d095aca
--- /dev/null
+++ b/install/ui/test/navigation_tests.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Navigation Test Suite</title>
+ <link rel="stylesheet" href="qunit.css" type="text/css" media="screen">
+ <script type="text/javascript" src="qunit.js"></script>
+ <script type="text/javascript" src="../jquery.js"></script>
+ <script type="text/javascript" src="../jquery.ba-bbq.js"></script>
+ <script type="text/javascript" src="../jquery-ui.js"></script>
+ <script type="text/javascript" src="../ipa.js"></script>
+ <script type="text/javascript" src="../entity.js"></script>
+ <script type="text/javascript" src="../navigation.js"></script>
+ <script type="text/javascript" src="navigation_tests.js"></script>
+</head>
+<body>
+ <h1 id="qunit-header">Navigation Test Suite</h1>
+ <h2 id="qunit-banner"></h2>
+ <div id="qunit-testrunner-toolbar"></div>
+ <h2 id="qunit-userAgent"></h2>
+ <ol id="qunit-tests"></ol>
+ <div id="qunit-fixture"></div>
+</body>
+</html>
diff --git a/install/ui/test/navigation_tests.js b/install/ui/test/navigation_tests.js
new file mode 100644
index 000000000..bc198ac0c
--- /dev/null
+++ b/install/ui/test/navigation_tests.js
@@ -0,0 +1,163 @@
+/* Authors:
+ * Adam Young <ayoung@redhat.com>
+ *
+ * Copyright (C) 2010 Red Hat
+ * see file 'COPYING' for use and warranty information
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+module('navigation');
+
+test("Testing nav_create().", function() {
+
+ var mock_tabs_lists =
+ [
+ { name:'identity', label:'IDENTITY', children: [
+ {name:'user', entity:'user'},
+ {name:'group', entity:'group'}
+ ]}];
+
+ var entity = IPA.entity({name: 'user'});
+ entity.setup = function(container){
+ user_mock_called = true;
+ same(container[0].id,'user','user id');
+ same(container[0].nodeName,'DIV','user div');
+ };
+ IPA.add_entity(entity);
+
+ entity = IPA.entity({name: 'group'});
+ entity.setup = function(container){
+ group_mock_called = true;
+ same(container[0].id,'group','group id');
+ same(container[0].nodeName,'DIV','group Div');
+ };
+ IPA.add_entity(entity);
+
+ IPA.metadata = {};
+ var navigation = $('<div id="navigation"/>').appendTo(document.body);
+ var user_mock_called = false;
+ var group_mock_called = false;
+ nav_create(mock_tabs_lists, navigation, 'tabs');
+ ok(user_mock_called, "mock user setup was called");
+ ok(!group_mock_called, "mock group setup was not called because the tab is inactive");
+ same( navigation[0].children.length, 2, "Two Child tabs");
+ same( navigation[0].children[1].id, 'identity', "Identity Tab");
+ same( navigation[0].children[1].children[1].id, 'user', "User Tab");
+ same( navigation[0].children[1].children[2].id, 'group', "User Tab");
+ navigation.remove();
+});
+
+test("Testing nav_update_tabs() with valid index.", function() {
+
+ var orig_push_state = nav_push_state;
+ var orig_get_state = nav_get_state;
+ var orig_remove_state = nav_remove_state;
+
+ var state = {};
+
+ nav_push_state = function(params) {
+ $.extend(state, params);
+ };
+ nav_get_state = function(key) {
+ return state[key];
+ };
+ nav_remove_state = function(key) {
+ delete state[key];
+ };
+
+ var mock_tabs_lists =
+ [
+ { name:'identity', label:'IDENTITY', children: [
+ {name:'one', label:'One', setup: function (){}},
+ {name:'two', label:'Two', setup: function (){}}
+ ]}];
+
+ var navigation = $('<div id="navigation"/>').appendTo(document.body);
+
+ nav_create(mock_tabs_lists, navigation, 'tabs');
+
+ nav_push_state({"identity":1});
+ nav_update_tabs();
+
+ same(
+ navigation.tabs('option', 'selected'), 0,
+ "Active tab at level 1"
+ );
+
+ same(
+ $('#identity').tabs('option', 'selected'), 1,
+ "Active tab at level 2"
+ );
+
+ nav_remove_state("identity");
+
+ navigation.remove();
+
+ nav_push_state = orig_push_state;
+ nav_get_state = orig_get_state;
+ nav_remove_state = orig_remove_state;
+});
+
+test("Testing nav_update_tabs() with out-of-range index.", function() {
+
+ var orig_push_state = nav_push_state;
+ var orig_get_state = nav_get_state;
+ var orig_remove_state = nav_remove_state;
+
+ var state = {};
+
+ nav_push_state = function(params) {
+ $.extend(state, params);
+ };
+ nav_get_state = function(key) {
+ return state[key];
+ };
+ nav_remove_state = function(key) {
+ delete state[key];
+ };
+
+ var mock_tabs_lists =
+ [
+ { name:'identity', label:'IDENTITY', children: [
+ {name:'one', label:'One', setup: function (){}},
+ {name:'two', label:'Two', setup: function (){}}
+ ]}];
+
+ var navigation = $('<div id="navigation"/>').appendTo(document.body);
+
+ nav_create(mock_tabs_lists, navigation, 'tabs');
+
+ nav_push_state({"identity":2});
+ nav_update_tabs();
+
+ same(
+ navigation.tabs('option', 'selected'), 0,
+ "Active tab at level 1"
+ );
+
+ same(
+ $('#identity').tabs('option', 'selected'), 0,
+ "Active tab at level 2"
+ );
+
+ nav_remove_state("identity");
+
+ navigation.remove();
+
+ nav_push_state = orig_push_state;
+ nav_get_state = orig_get_state;
+ nav_remove_state = orig_remove_state;
+});
diff --git a/install/ui/test/qunit.css b/install/ui/test/qunit.css
new file mode 100644
index 000000000..e9404f598
--- /dev/null
+++ b/install/ui/test/qunit.css
@@ -0,0 +1,155 @@
+/** Font Family and Sizes */
+
+#qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult {
+ font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial;
+}
+
+#qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; }
+#qunit-tests { font-size: smaller; }
+
+
+/** Resets */
+
+#qunit-tests, #qunit-tests ol, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult {
+ margin: 0;
+ padding: 0;
+}
+
+
+/** Header */
+
+#qunit-header {
+ padding: 0.5em 0 0.5em 1em;
+
+ color: #fff;
+ text-shadow: rgba(0, 0, 0, 0.5) 4px 4px 1px;
+ background-color: #0d3349;
+
+ border-radius: 15px 15px 0 0;
+ -moz-border-radius: 15px 15px 0 0;
+ -webkit-border-top-right-radius: 15px;
+ -webkit-border-top-left-radius: 15px;
+}
+
+#qunit-header a {
+ text-decoration: none;
+ color: white;
+}
+
+#qunit-banner {
+ height: 5px;
+}
+
+#qunit-testrunner-toolbar {
+ padding: 0em 0 0.5em 2em;
+}
+
+#qunit-userAgent {
+ padding: 0.5em 0 0.5em 2.5em;
+ background-color: #2b81af;
+ color: #fff;
+ text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;
+}
+
+
+/** Tests: Pass/Fail */
+
+#qunit-tests {
+ list-style-position: inside;
+}
+
+#qunit-tests li {
+ padding: 0.4em 0.5em 0.4em 2.5em;
+ border-bottom: 1px solid #fff;
+ list-style-position: inside;
+}
+
+#qunit-tests li strong {
+ cursor: pointer;
+}
+
+#qunit-tests ol {
+ margin-top: 0.5em;
+ padding: 0.5em;
+
+ background-color: #fff;
+
+ border-radius: 15px;
+ -moz-border-radius: 15px;
+ -webkit-border-radius: 15px;
+
+ box-shadow: inset 0px 2px 13px #999;
+ -moz-box-shadow: inset 0px 2px 13px #999;
+ -webkit-box-shadow: inset 0px 2px 13px #999;
+}
+
+/*** Test Counts */
+
+#qunit-tests b.counts { color: black; }
+#qunit-tests b.passed { color: #5E740B; }
+#qunit-tests b.failed { color: #710909; }
+
+#qunit-tests li li {
+ margin: 0.5em;
+ padding: 0.4em 0.5em 0.4em 0.5em;
+ background-color: #fff;
+ border-bottom: none;
+ list-style-position: inside;
+}
+
+/*** Passing Styles */
+
+#qunit-tests li li.pass {
+ color: #5E740B;
+ background-color: #fff;
+ border-left: 26px solid #C6E746;
+}
+
+#qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; }
+#qunit-tests .pass .test-name { color: #366097; }
+
+#qunit-tests .pass .test-actual,
+#qunit-tests .pass .test-expected { color: #999999; }
+
+#qunit-banner.qunit-pass { background-color: #C6E746; }
+
+/*** Failing Styles */
+
+#qunit-tests li li.fail {
+ color: #710909;
+ background-color: #fff;
+ border-left: 26px solid #EE5757;
+}
+
+#qunit-tests .fail { color: #000000; background-color: #EE5757; }
+#qunit-tests .fail .test-name,
+#qunit-tests .fail .module-name { color: #000000; }
+
+#qunit-tests .fail .test-actual { color: #EE5757; }
+#qunit-tests .fail .test-expected { color: green; }
+
+#qunit-banner.qunit-fail,
+#qunit-testrunner-toolbar { background-color: #EE5757; }
+
+
+/** Footer */
+
+#qunit-testresult {
+ padding: 0.5em 0.5em 0.5em 2.5em;
+
+ color: #2b81af;
+ background-color: #D2E0E6;
+
+ border-radius: 0 0 15px 15px;
+ -moz-border-radius: 0 0 15px 15px;
+ -webkit-border-bottom-right-radius: 15px;
+ -webkit-border-bottom-left-radius: 15px;
+}
+
+/** Fixture */
+
+#qunit-fixture {
+ position: absolute;
+ top: -10000px;
+ left: -10000px;
+}
diff --git a/install/ui/test/qunit.js b/install/ui/test/qunit.js
new file mode 100644
index 000000000..0b8173a80
--- /dev/null
+++ b/install/ui/test/qunit.js
@@ -0,0 +1,1261 @@
+/*
+ * QUnit - A JavaScript Unit Testing Framework
+ *
+ * http://docs.jquery.com/QUnit
+ *
+ * Copyright (c) 2009 John Resig, Jörn Zaefferer
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ */
+
+(function(window) {
+
+var QUnit = {
+
+ // call on start of module test to prepend name to all tests
+ module: function(name, testEnvironment) {
+ config.currentModule = name;
+
+ synchronize(function() {
+ if ( config.currentModule ) {
+ QUnit.moduleDone( config.currentModule, config.moduleStats.bad, config.moduleStats.all );
+ }
+
+ config.currentModule = name;
+ config.moduleTestEnvironment = testEnvironment;
+ config.moduleStats = { all: 0, bad: 0 };
+
+ QUnit.moduleStart( name, testEnvironment );
+ });
+ },
+
+ asyncTest: function(testName, expected, callback) {
+ if ( arguments.length === 2 ) {
+ callback = expected;
+ expected = 0;
+ }
+
+ QUnit.test(testName, expected, callback, true);
+ },
+
+ test: function(testName, expected, callback, async) {
+ var name = '<span class="test-name">' + testName + '</span>', testEnvironment, testEnvironmentArg;
+
+ if ( arguments.length === 2 ) {
+ callback = expected;
+ expected = null;
+ }
+ // is 2nd argument a testEnvironment?
+ if ( expected && typeof expected === 'object') {
+ testEnvironmentArg = expected;
+ expected = null;
+ }
+
+ if ( config.currentModule ) {
+ name = '<span class="module-name">' + config.currentModule + "</span>: " + name;
+ }
+
+ if ( !validTest(config.currentModule + ": " + testName) ) {
+ return;
+ }
+
+ synchronize(function() {
+
+ testEnvironment = extend({
+ setup: function() {},
+ teardown: function() {}
+ }, config.moduleTestEnvironment);
+ if (testEnvironmentArg) {
+ extend(testEnvironment,testEnvironmentArg);
+ }
+
+ QUnit.testStart( testName, testEnvironment );
+
+ // allow utility functions to access the current test environment
+ QUnit.current_testEnvironment = testEnvironment;
+
+ config.assertions = [];
+ config.expected = expected;
+
+ var tests = id("qunit-tests");
+ if (tests) {
+ var b = document.createElement("strong");
+ b.innerHTML = "Running " + name;
+ var li = document.createElement("li");
+ li.appendChild( b );
+ li.id = "current-test-output";
+ tests.appendChild( li )
+ }
+
+ try {
+ if ( !config.pollution ) {
+ saveGlobal();
+ }
+
+ testEnvironment.setup.call(testEnvironment);
+ } catch(e) {
+ QUnit.ok( false, "Setup failed on " + name + ": " + e.message );
+ }
+ });
+
+ synchronize(function() {
+ if ( async ) {
+ QUnit.stop();
+ }
+
+ try {
+ callback.call(testEnvironment);
+ } catch(e) {
+ fail("Test " + name + " died, exception and test follows", e, callback);
+ QUnit.ok( false, "Died on test #" + (config.assertions.length + 1) + ": " + e.message );
+ // else next test will carry the responsibility
+ saveGlobal();
+
+ // Restart the tests if they're blocking
+ if ( config.blocking ) {
+ start();
+ }
+ }
+ });
+
+ synchronize(function() {
+ try {
+ checkPollution();
+ testEnvironment.teardown.call(testEnvironment);
+ } catch(e) {
+ QUnit.ok( false, "Teardown failed on " + name + ": " + e.message );
+ }
+ });
+
+ synchronize(function() {
+ try {
+ QUnit.reset();
+ } catch(e) {
+ fail("reset() failed, following Test " + name + ", exception and reset fn follows", e, reset);
+ }
+
+ if ( config.expected && config.expected != config.assertions.length ) {
+ QUnit.ok( false, "Expected " + config.expected + " assertions, but " + config.assertions.length + " were run" );
+ }
+
+ var good = 0, bad = 0,
+ tests = id("qunit-tests");
+
+ config.stats.all += config.assertions.length;
+ config.moduleStats.all += config.assertions.length;
+
+ if ( tests ) {
+ var ol = document.createElement("ol");
+
+ for ( var i = 0; i < config.assertions.length; i++ ) {
+ var assertion = config.assertions[i];
+
+ var li = document.createElement("li");
+ li.className = assertion.result ? "pass" : "fail";
+ li.innerHTML = assertion.message || "(no message)";
+ ol.appendChild( li );
+
+ if ( assertion.result ) {
+ good++;
+ } else {
+ bad++;
+ config.stats.bad++;
+ config.moduleStats.bad++;
+ }
+ }
+ if (bad == 0) {
+ ol.style.display = "none";
+ }
+
+ var b = document.createElement("strong");
+ b.innerHTML = name + " <b class='counts'>(<b class='failed'>" + bad + "</b>, <b class='passed'>" + good + "</b>, " + config.assertions.length + ")</b>";
+
+ addEvent(b, "click", function() {
+ var next = b.nextSibling, display = next.style.display;
+ next.style.display = display === "none" ? "block" : "none";
+ });
+
+ addEvent(b, "dblclick", function(e) {
+ var target = e && e.target ? e.target : window.event.srcElement;
+ if ( target.nodeName.toLowerCase() == "span" || target.nodeName.toLowerCase() == "b" ) {
+ target = target.parentNode;
+ }
+ if ( window.location && target.nodeName.toLowerCase() === "strong" ) {
+ window.location.search = "?" + encodeURIComponent(getText([target]).replace(/\(.+\)$/, "").replace(/(^\s*|\s*$)/g, ""));
+ }
+ });
+
+ var li = id("current-test-output");
+ li.id = "";
+ li.className = bad ? "fail" : "pass";
+ li.removeChild( li.firstChild );
+ li.appendChild( b );
+ li.appendChild( ol );
+
+ if ( bad ) {
+ var toolbar = id("qunit-testrunner-toolbar");
+ if ( toolbar ) {
+ toolbar.style.display = "block";
+ id("qunit-filter-pass").disabled = null;
+ id("qunit-filter-missing").disabled = null;
+ }
+ }
+
+ } else {
+ for ( var i = 0; i < config.assertions.length; i++ ) {
+ if ( !config.assertions[i].result ) {
+ bad++;
+ config.stats.bad++;
+ config.moduleStats.bad++;
+ }
+ }
+ }
+
+ QUnit.testDone( testName, bad, config.assertions.length );
+
+ if ( !window.setTimeout && !config.queue.length ) {
+ done();
+ }
+ });
+
+ synchronize( done );
+ },
+
+ /**
+ * Specify the number of expected assertions to gurantee that failed test (no assertions are run at all) don't slip through.
+ */
+ expect: function(asserts) {
+ config.expected = asserts;
+ },
+
+ /**
+ * Asserts true.
+ * @example ok( "asdfasdf".length > 5, "There must be at least 5 chars" );
+ */
+ ok: function(a, msg) {
+ msg = escapeHtml(msg);
+ QUnit.log(a, msg);
+
+ config.assertions.push({
+ result: !!a,
+ message: msg
+ });
+ },
+
+ /**
+ * Checks that the first two arguments are equal, with an optional message.
+ * Prints out both actual and expected values.
+ *
+ * Prefered to ok( actual == expected, message )
+ *
+ * @example equal( format("Received {0} bytes.", 2), "Received 2 bytes." );
+ *
+ * @param Object actual
+ * @param Object expected
+ * @param String message (optional)
+ */
+ equal: function(actual, expected, message) {
+ push(expected == actual, actual, expected, message);
+ },
+
+ notEqual: function(actual, expected, message) {
+ push(expected != actual, actual, expected, message);
+ },
+
+ deepEqual: function(actual, expected, message) {
+ push(QUnit.equiv(actual, expected), actual, expected, message);
+ },
+
+ notDeepEqual: function(actual, expected, message) {
+ push(!QUnit.equiv(actual, expected), actual, expected, message);
+ },
+
+ strictEqual: function(actual, expected, message) {
+ push(expected === actual, actual, expected, message);
+ },
+
+ notStrictEqual: function(actual, expected, message) {
+ push(expected !== actual, actual, expected, message);
+ },
+
+ raises: function(fn, message) {
+ try {
+ fn();
+ ok( false, message );
+ }
+ catch (e) {
+ ok( true, message );
+ }
+ },
+
+ start: function() {
+ // A slight delay, to avoid any current callbacks
+ if ( window.setTimeout ) {
+ window.setTimeout(function() {
+ if ( config.timeout ) {
+ clearTimeout(config.timeout);
+ }
+
+ config.blocking = false;
+ process();
+ }, 13);
+ } else {
+ config.blocking = false;
+ process();
+ }
+ },
+
+ stop: function(timeout) {
+ config.blocking = true;
+
+ if ( timeout && window.setTimeout ) {
+ config.timeout = window.setTimeout(function() {
+ QUnit.ok( false, "Test timed out" );
+ QUnit.start();
+ }, timeout);
+ }
+ }
+
+};
+
+// Backwards compatibility, deprecated
+QUnit.equals = QUnit.equal;
+QUnit.same = QUnit.deepEqual;
+
+// Maintain internal state
+var config = {
+ // The queue of tests to run
+ queue: [],
+
+ // block until document ready
+ blocking: true
+};
+
+// Load paramaters
+(function() {
+ var location = window.location || { search: "", protocol: "file:" },
+ GETParams = location.search.slice(1).split('&');
+
+ for ( var i = 0; i < GETParams.length; i++ ) {
+ GETParams[i] = decodeURIComponent( GETParams[i] );
+ if ( GETParams[i] === "noglobals" ) {
+ GETParams.splice( i, 1 );
+ i--;
+ config.noglobals = true;
+ } else if ( GETParams[i].search('=') > -1 ) {
+ GETParams.splice( i, 1 );
+ i--;
+ }
+ }
+
+ // restrict modules/tests by get parameters
+ config.filters = GETParams;
+
+ // Figure out if we're running the tests from a server or not
+ QUnit.isLocal = !!(location.protocol === 'file:');
+})();
+
+// Expose the API as global variables, unless an 'exports'
+// object exists, in that case we assume we're in CommonJS
+if ( typeof exports === "undefined" || typeof require === "undefined" ) {
+ extend(window, QUnit);
+ window.QUnit = QUnit;
+} else {
+ extend(exports, QUnit);
+ exports.QUnit = QUnit;
+}
+
+// define these after exposing globals to keep them in these QUnit namespace only
+extend(QUnit, {
+ config: config,
+
+ // Initialize the configuration options
+ init: function() {
+ extend(config, {
+ stats: { all: 0, bad: 0 },
+ moduleStats: { all: 0, bad: 0 },
+ started: +new Date,
+ updateRate: 1000,
+ blocking: false,
+ autostart: true,
+ autorun: false,
+ assertions: [],
+ filters: [],
+ queue: []
+ });
+
+ var tests = id("qunit-tests"),
+ banner = id("qunit-banner"),
+ result = id("qunit-testresult");
+
+ if ( tests ) {
+ tests.innerHTML = "";
+ }
+
+ if ( banner ) {
+ banner.className = "";
+ }
+
+ if ( result ) {
+ result.parentNode.removeChild( result );
+ }
+ },
+
+ /**
+ * Resets the test setup. Useful for tests that modify the DOM.
+ */
+ reset: function() {
+ if ( window.jQuery ) {
+ jQuery("#main, #qunit-fixture").html( config.fixture );
+ }
+ },
+
+ /**
+ * Trigger an event on an element.
+ *
+ * @example triggerEvent( document.body, "click" );
+ *
+ * @param DOMElement elem
+ * @param String type
+ */
+ triggerEvent: function( elem, type, event ) {
+ if ( document.createEvent ) {
+ event = document.createEvent("MouseEvents");
+ event.initMouseEvent(type, true, true, elem.ownerDocument.defaultView,
+ 0, 0, 0, 0, 0, false, false, false, false, 0, null);
+ elem.dispatchEvent( event );
+
+ } else if ( elem.fireEvent ) {
+ elem.fireEvent("on"+type);
+ }
+ },
+
+ // Safe object type checking
+ is: function( type, obj ) {
+ return QUnit.objectType( obj ) == type;
+ },
+
+ objectType: function( obj ) {
+ if (typeof obj === "undefined") {
+ return "undefined";
+
+ // consider: typeof null === object
+ }
+ if (obj === null) {
+ return "null";
+ }
+
+ var type = Object.prototype.toString.call( obj )
+ .match(/^\[object\s(.*)\]$/)[1] || '';
+
+ switch (type) {
+ case 'Number':
+ if (isNaN(obj)) {
+ return "nan";
+ } else {
+ return "number";
+ }
+ case 'String':
+ case 'Boolean':
+ case 'Array':
+ case 'Date':
+ case 'RegExp':
+ case 'Function':
+ return type.toLowerCase();
+ }
+ if (typeof obj === "object") {
+ return "object";
+ }
+ return undefined;
+ },
+
+ // Logging callbacks
+ begin: function() {},
+ done: function(failures, total) {},
+ log: function(result, message) {},
+ testStart: function(name, testEnvironment) {},
+ testDone: function(name, failures, total) {},
+ moduleStart: function(name, testEnvironment) {},
+ moduleDone: function(name, failures, total) {}
+});
+
+if ( typeof document === "undefined" || document.readyState === "complete" ) {
+ config.autorun = true;
+}
+
+addEvent(window, "load", function() {
+ QUnit.begin();
+
+ // Initialize the config, saving the execution queue
+ var oldconfig = extend({}, config);
+ QUnit.init();
+ extend(config, oldconfig);
+
+ config.blocking = false;
+
+ var userAgent = id("qunit-userAgent");
+ if ( userAgent ) {
+ userAgent.innerHTML = navigator.userAgent;
+ }
+ var banner = id("qunit-header");
+ if ( banner ) {
+ banner.innerHTML = '<a href="' + location.href + '">' + banner.innerHTML + '</a>';
+ }
+
+ var toolbar = id("qunit-testrunner-toolbar");
+ if ( toolbar ) {
+ toolbar.style.display = "none";
+
+ var filter = document.createElement("input");
+ filter.type = "checkbox";
+ filter.id = "qunit-filter-pass";
+ filter.disabled = true;
+ addEvent( filter, "click", function() {
+ var li = document.getElementsByTagName("li");
+ for ( var i = 0; i < li.length; i++ ) {
+ if ( li[i].className.indexOf("pass") > -1 ) {
+ li[i].style.display = filter.checked ? "none" : "";
+ }
+ }
+ });
+ toolbar.appendChild( filter );
+
+ var label = document.createElement("label");
+ label.setAttribute("for", "qunit-filter-pass");
+ label.innerHTML = "Hide passed tests";
+ toolbar.appendChild( label );
+
+ var missing = document.createElement("input");
+ missing.type = "checkbox";
+ missing.id = "qunit-filter-missing";
+ missing.disabled = true;
+ addEvent( missing, "click", function() {
+ var li = document.getElementsByTagName("li");
+ for ( var i = 0; i < li.length; i++ ) {
+ if ( li[i].className.indexOf("fail") > -1 && li[i].innerHTML.indexOf('missing test - untested code is broken code') > - 1 ) {
+ li[i].parentNode.parentNode.style.display = missing.checked ? "none" : "block";
+ }
+ }
+ });
+ toolbar.appendChild( missing );
+
+ label = document.createElement("label");
+ label.setAttribute("for", "qunit-filter-missing");
+ label.innerHTML = "Hide missing tests (untested code is broken code)";
+ toolbar.appendChild( label );
+ }
+
+ var main = id('main') || id('qunit-fixture');
+ if ( main ) {
+ config.fixture = main.innerHTML;
+ }
+
+ if (config.autostart) {
+ QUnit.start();
+ }
+});
+
+function done() {
+ if ( config.doneTimer && window.clearTimeout ) {
+ window.clearTimeout( config.doneTimer );
+ config.doneTimer = null;
+ }
+
+ if ( config.queue.length ) {
+ config.doneTimer = window.setTimeout(function(){
+ if ( !config.queue.length ) {
+ done();
+ } else {
+ synchronize( done );
+ }
+ }, 13);
+
+ return;
+ }
+
+ config.autorun = true;
+
+ // Log the last module results
+ if ( config.currentModule ) {
+ QUnit.moduleDone( config.currentModule, config.moduleStats.bad, config.moduleStats.all );
+ }
+
+ var banner = id("qunit-banner"),
+ tests = id("qunit-tests"),
+ html = ['Tests completed in ',
+ +new Date - config.started, ' milliseconds.<br/>',
+ '<span class="passed">', config.stats.all - config.stats.bad, '</span> tests of <span class="total">', config.stats.all, '</span> passed, <span class="failed">', config.stats.bad,'</span> failed.'].join('');
+
+ if ( banner ) {
+ banner.className = (config.stats.bad ? "qunit-fail" : "qunit-pass");
+ }
+
+ if ( tests ) {
+ var result = id("qunit-testresult");
+
+ if ( !result ) {
+ result = document.createElement("p");
+ result.id = "qunit-testresult";
+ result.className = "result";
+ tests.parentNode.insertBefore( result, tests.nextSibling );
+ }
+
+ result.innerHTML = html;
+ }
+
+ QUnit.done( config.stats.bad, config.stats.all );
+}
+
+function validTest( name ) {
+ var i = config.filters.length,
+ run = false;
+
+ if ( !i ) {
+ return true;
+ }
+
+ while ( i-- ) {
+ var filter = config.filters[i],
+ not = filter.charAt(0) == '!';
+
+ if ( not ) {
+ filter = filter.slice(1);
+ }
+
+ if ( name.indexOf(filter) !== -1 ) {
+ return !not;
+ }
+
+ if ( not ) {
+ run = true;
+ }
+ }
+
+ return run;
+}
+
+function escapeHtml(s) {
+ s = s === null ? "" : s + "";
+ return s.replace(/[\&"<>\\]/g, function(s) {
+ switch(s) {
+ case "&": return "&amp;";
+ case "\\": return "\\\\";
+ case '"': return '\"';
+ case "<": return "&lt;";
+ case ">": return "&gt;";
+ default: return s;
+ }
+ });
+}
+
+function push(result, actual, expected, message) {
+ message = escapeHtml(message) || (result ? "okay" : "failed");
+ message = '<span class="test-message">' + message + "</span>";
+ expected = escapeHtml(QUnit.jsDump.parse(expected));
+ actual = escapeHtml(QUnit.jsDump.parse(actual));
+ var output = message + ', expected: <span class="test-expected">' + expected + '</span>';
+ if (actual != expected) {
+ output += ' result: <span class="test-actual">' + actual + '</span>, diff: ' + QUnit.diff(expected, actual);
+ }
+
+ // can't use ok, as that would double-escape messages
+ QUnit.log(result, output);
+ config.assertions.push({
+ result: !!result,
+ message: output
+ });
+}
+
+function synchronize( callback ) {
+ config.queue.push( callback );
+
+ if ( config.autorun && !config.blocking ) {
+ process();
+ }
+}
+
+function process() {
+ var start = (new Date()).getTime();
+
+ while ( config.queue.length && !config.blocking ) {
+ if ( config.updateRate <= 0 || (((new Date()).getTime() - start) < config.updateRate) ) {
+ config.queue.shift()();
+
+ } else {
+ setTimeout( process, 13 );
+ break;
+ }
+ }
+}
+
+function saveGlobal() {
+ config.pollution = [];
+
+ if ( config.noglobals ) {
+ for ( var key in window ) {
+ config.pollution.push( key );
+ }
+ }
+}
+
+function checkPollution( name ) {
+ var old = config.pollution;
+ saveGlobal();
+
+ var newGlobals = diff( old, config.pollution );
+ if ( newGlobals.length > 0 ) {
+ ok( false, "Introduced global variable(s): " + newGlobals.join(", ") );
+ config.expected++;
+ }
+
+ var deletedGlobals = diff( config.pollution, old );
+ if ( deletedGlobals.length > 0 ) {
+ ok( false, "Deleted global variable(s): " + deletedGlobals.join(", ") );
+ config.expected++;
+ }
+}
+
+// returns a new Array with the elements that are in a but not in b
+function diff( a, b ) {
+ var result = a.slice();
+ for ( var i = 0; i < result.length; i++ ) {
+ for ( var j = 0; j < b.length; j++ ) {
+ if ( result[i] === b[j] ) {
+ result.splice(i, 1);
+ i--;
+ break;
+ }
+ }
+ }
+ return result;
+}
+
+function fail(message, exception, callback) {
+ if ( typeof console !== "undefined" && console.error && console.warn ) {
+ console.error(message);
+ console.error(exception);
+ console.warn(callback.toString());
+
+ } else if ( window.opera && opera.postError ) {
+ opera.postError(message, exception, callback.toString);
+ }
+}
+
+function extend(a, b) {
+ for ( var prop in b ) {
+ a[prop] = b[prop];
+ }
+
+ return a;
+}
+
+function addEvent(elem, type, fn) {
+ if ( elem.addEventListener ) {
+ elem.addEventListener( type, fn, false );
+ } else if ( elem.attachEvent ) {
+ elem.attachEvent( "on" + type, fn );
+ } else {
+ fn();
+ }
+}
+
+function id(name) {
+ return !!(typeof document !== "undefined" && document && document.getElementById) &&
+ document.getElementById( name );
+}
+
+// Test for equality any JavaScript type.
+// Discussions and reference: http://philrathe.com/articles/equiv
+// Test suites: http://philrathe.com/tests/equiv
+// Author: Philippe Rathé <prathe@gmail.com>
+QUnit.equiv = function () {
+
+ var innerEquiv; // the real equiv function
+ var callers = []; // stack to decide between skip/abort functions
+ var parents = []; // stack to avoiding loops from circular referencing
+
+ // Call the o related callback with the given arguments.
+ function bindCallbacks(o, callbacks, args) {
+ var prop = QUnit.objectType(o);
+ if (prop) {
+ if (QUnit.objectType(callbacks[prop]) === "function") {
+ return callbacks[prop].apply(callbacks, args);
+ } else {
+ return callbacks[prop]; // or undefined
+ }
+ }
+ }
+
+ var callbacks = function () {
+
+ // for string, boolean, number and null
+ function useStrictEquality(b, a) {
+ if (b instanceof a.constructor || a instanceof b.constructor) {
+ // to catch short annotaion VS 'new' annotation of a declaration
+ // e.g. var i = 1;
+ // var j = new Number(1);
+ return a == b;
+ } else {
+ return a === b;
+ }
+ }
+
+ return {
+ "string": useStrictEquality,
+ "boolean": useStrictEquality,
+ "number": useStrictEquality,
+ "null": useStrictEquality,
+ "undefined": useStrictEquality,
+
+ "nan": function (b) {
+ return isNaN(b);
+ },
+
+ "date": function (b, a) {
+ return QUnit.objectType(b) === "date" && a.valueOf() === b.valueOf();
+ },
+
+ "regexp": function (b, a) {
+ return QUnit.objectType(b) === "regexp" &&
+ a.source === b.source && // the regex itself
+ a.global === b.global && // and its modifers (gmi) ...
+ a.ignoreCase === b.ignoreCase &&
+ a.multiline === b.multiline;
+ },
+
+ // - skip when the property is a method of an instance (OOP)
+ // - abort otherwise,
+ // initial === would have catch identical references anyway
+ "function": function () {
+ var caller = callers[callers.length - 1];
+ return caller !== Object &&
+ typeof caller !== "undefined";
+ },
+
+ "array": function (b, a) {
+ var i, j, loop;
+ var len;
+
+ // b could be an object literal here
+ if ( ! (QUnit.objectType(b) === "array")) {
+ return false;
+ }
+
+ len = a.length;
+ if (len !== b.length) { // safe and faster
+ return false;
+ }
+
+ //track reference to avoid circular references
+ parents.push(a);
+ for (i = 0; i < len; i++) {
+ loop = false;
+ for(j=0;j<parents.length;j++){
+ if(parents[j] === a[i]){
+ loop = true;//dont rewalk array
+ }
+ }
+ if (!loop && ! innerEquiv(a[i], b[i])) {
+ parents.pop();
+ return false;
+ }
+ }
+ parents.pop();
+ return true;
+ },
+
+ "object": function (b, a) {
+ var i, j, loop;
+ var eq = true; // unless we can proove it
+ var aProperties = [], bProperties = []; // collection of strings
+
+ // comparing constructors is more strict than using instanceof
+ if ( a.constructor !== b.constructor) {
+ return false;
+ }
+
+ // stack constructor before traversing properties
+ callers.push(a.constructor);
+ //track reference to avoid circular references
+ parents.push(a);
+
+ for (i in a) { // be strict: don't ensures hasOwnProperty and go deep
+ loop = false;
+ for(j=0;j<parents.length;j++){
+ if(parents[j] === a[i])
+ loop = true; //don't go down the same path twice
+ }
+ aProperties.push(i); // collect a's properties
+
+ if (!loop && ! innerEquiv(a[i], b[i])) {
+ eq = false;
+ break;
+ }
+ }
+
+ callers.pop(); // unstack, we are done
+ parents.pop();
+
+ for (i in b) {
+ bProperties.push(i); // collect b's properties
+ }
+
+ // Ensures identical properties name
+ return eq && innerEquiv(aProperties.sort(), bProperties.sort());
+ }
+ };
+ }();
+
+ innerEquiv = function () { // can take multiple arguments
+ var args = Array.prototype.slice.apply(arguments);
+ if (args.length < 2) {
+ return true; // end transition
+ }
+
+ return (function (a, b) {
+ if (a === b) {
+ return true; // catch the most you can
+ } else if (a === null || b === null || typeof a === "undefined" || typeof b === "undefined" || QUnit.objectType(a) !== QUnit.objectType(b)) {
+ return false; // don't lose time with error prone cases
+ } else {
+ return bindCallbacks(a, callbacks, [b, a]);
+ }
+
+ // apply transition with (1..n) arguments
+ })(args[0], args[1]) && arguments.callee.apply(this, args.splice(1, args.length -1));
+ };
+
+ return innerEquiv;
+
+}();
+
+/**
+ * jsDump
+ * Copyright (c) 2008 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com
+ * Licensed under BSD (http://www.opensource.org/licenses/bsd-license.php)
+ * Date: 5/15/2008
+ * @projectDescription Advanced and extensible data dumping for Javascript.
+ * @version 1.0.0
+ * @author Ariel Flesler
+ * @link {http://flesler.blogspot.com/2008/05/jsdump-pretty-dump-of-any-javascript.html}
+ */
+QUnit.jsDump = (function() {
+ function quote( str ) {
+ return '"' + str.toString().replace(/"/g, '\\"') + '"';
+ };
+ function literal( o ) {
+ return o + '';
+ };
+ function join( pre, arr, post ) {
+ var s = jsDump.separator(),
+ base = jsDump.indent(),
+ inner = jsDump.indent(1);
+ if ( arr.join )
+ arr = arr.join( ',' + s + inner );
+ if ( !arr )
+ return pre + post;
+ return [ pre, inner + arr, base + post ].join(s);
+ };
+ function array( arr ) {
+ var i = arr.length, ret = Array(i);
+ this.up();
+ while ( i-- )
+ ret[i] = this.parse( arr[i] );
+ this.down();
+ return join( '[', ret, ']' );
+ };
+
+ var reName = /^function (\w+)/;
+
+ var jsDump = {
+ parse:function( obj, type ) { //type is used mostly internally, you can fix a (custom)type in advance
+ var parser = this.parsers[ type || this.typeOf(obj) ];
+ type = typeof parser;
+
+ return type == 'function' ? parser.call( this, obj ) :
+ type == 'string' ? parser :
+ this.parsers.error;
+ },
+ typeOf:function( obj ) {
+ var type;
+ if ( obj === null ) {
+ type = "null";
+ } else if (typeof obj === "undefined") {
+ type = "undefined";
+ } else if (QUnit.is("RegExp", obj)) {
+ type = "regexp";
+ } else if (QUnit.is("Date", obj)) {
+ type = "date";
+ } else if (QUnit.is("Function", obj)) {
+ type = "function";
+ } else if (obj.setInterval && obj.document && !obj.nodeType) {
+ type = "window";
+ } else if (obj.nodeType === 9) {
+ type = "document";
+ } else if (obj.nodeType) {
+ type = "node";
+ } else if (typeof obj === "object" && typeof obj.length === "number" && obj.length >= 0) {
+ type = "array";
+ } else {
+ type = typeof obj;
+ }
+ return type;
+ },
+ separator:function() {
+ return this.multiline ? this.HTML ? '<br />' : '\n' : this.HTML ? '&nbsp;' : ' ';
+ },
+ indent:function( extra ) {// extra can be a number, shortcut for increasing-calling-decreasing
+ if ( !this.multiline )
+ return '';
+ var chr = this.indentChar;
+ if ( this.HTML )
+ chr = chr.replace(/\t/g,' ').replace(/ /g,'&nbsp;');
+ return Array( this._depth_ + (extra||0) ).join(chr);
+ },
+ up:function( a ) {
+ this._depth_ += a || 1;
+ },
+ down:function( a ) {
+ this._depth_ -= a || 1;
+ },
+ setParser:function( name, parser ) {
+ this.parsers[name] = parser;
+ },
+ // The next 3 are exposed so you can use them
+ quote:quote,
+ literal:literal,
+ join:join,
+ //
+ _depth_: 1,
+ // This is the list of parsers, to modify them, use jsDump.setParser
+ parsers:{
+ window: '[Window]',
+ document: '[Document]',
+ error:'[ERROR]', //when no parser is found, shouldn't happen
+ unknown: '[Unknown]',
+ 'null':'null',
+ undefined:'undefined',
+ 'function':function( fn ) {
+ var ret = 'function',
+ name = 'name' in fn ? fn.name : (reName.exec(fn)||[])[1];//functions never have name in IE
+ if ( name )
+ ret += ' ' + name;
+ ret += '(';
+
+ ret = [ ret, this.parse( fn, 'functionArgs' ), '){'].join('');
+ return join( ret, this.parse(fn,'functionCode'), '}' );
+ },
+ array: array,
+ nodelist: array,
+ arguments: array,
+ object:function( map ) {
+ var ret = [ ];
+ this.up();
+ for ( var key in map )
+ ret.push( this.parse(key,'key') + ': ' + this.parse(map[key]) );
+ this.down();
+ return join( '{', ret, '}' );
+ },
+ node:function( node ) {
+ var open = this.HTML ? '&lt;' : '<',
+ close = this.HTML ? '&gt;' : '>';
+
+ var tag = node.nodeName.toLowerCase(),
+ ret = open + tag;
+
+ for ( var a in this.DOMAttrs ) {
+ var val = node[this.DOMAttrs[a]];
+ if ( val )
+ ret += ' ' + a + '=' + this.parse( val, 'attribute' );
+ }
+ return ret + close + open + '/' + tag + close;
+ },
+ functionArgs:function( fn ) {//function calls it internally, it's the arguments part of the function
+ var l = fn.length;
+ if ( !l ) return '';
+
+ var args = Array(l);
+ while ( l-- )
+ args[l] = String.fromCharCode(97+l);//97 is 'a'
+ return ' ' + args.join(', ') + ' ';
+ },
+ key:quote, //object calls it internally, the key part of an item in a map
+ functionCode:'[code]', //function calls it internally, it's the content of the function
+ attribute:quote, //node calls it internally, it's an html attribute value
+ string:quote,
+ date:quote,
+ regexp:literal, //regex
+ number:literal,
+ 'boolean':literal
+ },
+ DOMAttrs:{//attributes to dump from nodes, name=>realName
+ id:'id',
+ name:'name',
+ 'class':'className'
+ },
+ HTML:false,//if true, entities are escaped ( <, >, \t, space and \n )
+ indentChar:' ',//indentation unit
+ multiline:false //if true, items in a collection, are separated by a \n, else just a space.
+ };
+
+ return jsDump;
+})();
+
+// from Sizzle.js
+function getText( elems ) {
+ var ret = "", elem;
+
+ for ( var i = 0; elems[i]; i++ ) {
+ elem = elems[i];
+
+ // Get the text from text nodes and CDATA nodes
+ if ( elem.nodeType === 3 || elem.nodeType === 4 ) {
+ ret += elem.nodeValue;
+
+ // Traverse everything else, except comment nodes
+ } else if ( elem.nodeType !== 8 ) {
+ ret += getText( elem.childNodes );
+ }
+ }
+
+ return ret;
+};
+
+/*
+ * Javascript Diff Algorithm
+ * By John Resig (http://ejohn.org/)
+ * Modified by Chu Alan "sprite"
+ *
+ * Released under the MIT license.
+ *
+ * More Info:
+ * http://ejohn.org/projects/javascript-diff-algorithm/
+ *
+ * Usage: QUnit.diff(expected, actual)
+ *
+ * QUnit.diff("the quick brown fox jumped over", "the quick fox jumps over") == "the quick <del>brown </del> fox <del>jumped </del><ins>jumps </ins> over"
+ */
+QUnit.diff = (function() {
+ function diff(o, n){
+ var ns = new Object();
+ var os = new Object();
+
+ for (var i = 0; i < n.length; i++) {
+ if (ns[n[i]] == null)
+ ns[n[i]] = {
+ rows: new Array(),
+ o: null
+ };
+ ns[n[i]].rows.push(i);
+ }
+
+ for (var i = 0; i < o.length; i++) {
+ if (os[o[i]] == null)
+ os[o[i]] = {
+ rows: new Array(),
+ n: null
+ };
+ os[o[i]].rows.push(i);
+ }
+
+ for (var i in ns) {
+ if (ns[i].rows.length == 1 && typeof(os[i]) != "undefined" && os[i].rows.length == 1) {
+ n[ns[i].rows[0]] = {
+ text: n[ns[i].rows[0]],
+ row: os[i].rows[0]
+ };
+ o[os[i].rows[0]] = {
+ text: o[os[i].rows[0]],
+ row: ns[i].rows[0]
+ };
+ }
+ }
+
+ for (var i = 0; i < n.length - 1; i++) {
+ if (n[i].text != null && n[i + 1].text == null && n[i].row + 1 < o.length && o[n[i].row + 1].text == null &&
+ n[i + 1] == o[n[i].row + 1]) {
+ n[i + 1] = {
+ text: n[i + 1],
+ row: n[i].row + 1
+ };
+ o[n[i].row + 1] = {
+ text: o[n[i].row + 1],
+ row: i + 1
+ };
+ }
+ }
+
+ for (var i = n.length - 1; i > 0; i--) {
+ if (n[i].text != null && n[i - 1].text == null && n[i].row > 0 && o[n[i].row - 1].text == null &&
+ n[i - 1] == o[n[i].row - 1]) {
+ n[i - 1] = {
+ text: n[i - 1],
+ row: n[i].row - 1
+ };
+ o[n[i].row - 1] = {
+ text: o[n[i].row - 1],
+ row: i - 1
+ };
+ }
+ }
+
+ return {
+ o: o,
+ n: n
+ };
+ }
+
+ return function(o, n){
+ o = o.replace(/\s+$/, '');
+ n = n.replace(/\s+$/, '');
+ var out = diff(o == "" ? [] : o.split(/\s+/), n == "" ? [] : n.split(/\s+/));
+
+ var str = "";
+
+ var oSpace = o.match(/\s+/g);
+ if (oSpace == null) {
+ oSpace = [" "];
+ }
+ else {
+ oSpace.push(" ");
+ }
+ var nSpace = n.match(/\s+/g);
+ if (nSpace == null) {
+ nSpace = [" "];
+ }
+ else {
+ nSpace.push(" ");
+ }
+
+ if (out.n.length == 0) {
+ for (var i = 0; i < out.o.length; i++) {
+ str += '<del>' + out.o[i] + oSpace[i] + "</del>";
+ }
+ }
+ else {
+ if (out.n[0].text == null) {
+ for (n = 0; n < out.o.length && out.o[n].text == null; n++) {
+ str += '<del>' + out.o[n] + oSpace[n] + "</del>";
+ }
+ }
+
+ for (var i = 0; i < out.n.length; i++) {
+ if (out.n[i].text == null) {
+ str += '<ins>' + out.n[i] + nSpace[i] + "</ins>";
+ }
+ else {
+ var pre = "";
+
+ for (n = out.n[i].row + 1; n < out.o.length && out.o[n].text == null; n++) {
+ pre += '<del>' + out.o[n] + oSpace[n] + "</del>";
+ }
+ str += " " + out.n[i].text + nSpace[i] + pre;
+ }
+ }
+ }
+
+ return str;
+ }
+})();
+
+})(this);
diff --git a/install/ui/ui-bg_flat_65_ffffff_40x100.png b/install/ui/ui-bg_flat_65_ffffff_40x100.png
new file mode 100644
index 000000000..ac8b229af
--- /dev/null
+++ b/install/ui/ui-bg_flat_65_ffffff_40x100.png
Binary files differ
diff --git a/install/ui/ui-bg_glass_40_111111_1x400.png b/install/ui/ui-bg_glass_40_111111_1x400.png
new file mode 100644
index 000000000..1ec812773
--- /dev/null
+++ b/install/ui/ui-bg_glass_40_111111_1x400.png
Binary files differ
diff --git a/install/ui/ui-bg_glass_55_1c1c1c_1x400.png b/install/ui/ui-bg_glass_55_1c1c1c_1x400.png
new file mode 100644
index 000000000..93db02b0f
--- /dev/null
+++ b/install/ui/ui-bg_glass_55_1c1c1c_1x400.png
Binary files differ
diff --git a/install/ui/ui-bg_highlight-hard_100_f9f9f9_1x100.png b/install/ui/ui-bg_highlight-hard_100_f9f9f9_1x100.png
new file mode 100644
index 000000000..2cb80364b
--- /dev/null
+++ b/install/ui/ui-bg_highlight-hard_100_f9f9f9_1x100.png
Binary files differ
diff --git a/install/ui/ui-bg_highlight-hard_40_aaaaaa_1x100.png b/install/ui/ui-bg_highlight-hard_40_aaaaaa_1x100.png
new file mode 100644
index 000000000..a7aeeb0ae
--- /dev/null
+++ b/install/ui/ui-bg_highlight-hard_40_aaaaaa_1x100.png
Binary files differ
diff --git a/install/ui/ui-bg_highlight-soft_50_aaaaaa_1x100.png b/install/ui/ui-bg_highlight-soft_50_aaaaaa_1x100.png
new file mode 100644
index 000000000..a0ffd222d
--- /dev/null
+++ b/install/ui/ui-bg_highlight-soft_50_aaaaaa_1x100.png
Binary files differ
diff --git a/install/ui/ui-bg_inset-hard_45_cd0a0a_1x100.png b/install/ui/ui-bg_inset-hard_45_cd0a0a_1x100.png
new file mode 100644
index 000000000..718aa1176
--- /dev/null
+++ b/install/ui/ui-bg_inset-hard_45_cd0a0a_1x100.png
Binary files differ
diff --git a/install/ui/ui-bg_inset-hard_55_ffeb80_1x100.png b/install/ui/ui-bg_inset-hard_55_ffeb80_1x100.png
new file mode 100644
index 000000000..0286bb1d7
--- /dev/null
+++ b/install/ui/ui-bg_inset-hard_55_ffeb80_1x100.png
Binary files differ
diff --git a/install/ui/ui-bg_loop_8_333333_21x21.png b/install/ui/ui-bg_loop_8_333333_21x21.png
new file mode 100644
index 000000000..a6e1a3e1c
--- /dev/null
+++ b/install/ui/ui-bg_loop_8_333333_21x21.png
Binary files differ
diff --git a/install/ui/ui-icons_222222_256x240.png b/install/ui/ui-icons_222222_256x240.png
new file mode 100644
index 000000000..b273ff111
--- /dev/null
+++ b/install/ui/ui-icons_222222_256x240.png
Binary files differ
diff --git a/install/ui/ui-icons_4ca300_256x240.png b/install/ui/ui-icons_4ca300_256x240.png
new file mode 100644
index 000000000..fadab6000
--- /dev/null
+++ b/install/ui/ui-icons_4ca300_256x240.png
Binary files differ
diff --git a/install/ui/ui-icons_bbbbbb_256x240.png b/install/ui/ui-icons_bbbbbb_256x240.png
new file mode 100644
index 000000000..146dbd10b
--- /dev/null
+++ b/install/ui/ui-icons_bbbbbb_256x240.png
Binary files differ
diff --git a/install/ui/ui-icons_ededed_256x240.png b/install/ui/ui-icons_ededed_256x240.png
new file mode 100644
index 000000000..608e09d69
--- /dev/null
+++ b/install/ui/ui-icons_ededed_256x240.png
Binary files differ
diff --git a/install/ui/ui-icons_ffcf29_256x240.png b/install/ui/ui-icons_ffcf29_256x240.png
new file mode 100644
index 000000000..c066ff2a0
--- /dev/null
+++ b/install/ui/ui-icons_ffcf29_256x240.png
Binary files differ
diff --git a/install/ui/ui-icons_ffffff_256x240.png b/install/ui/ui-icons_ffffff_256x240.png
new file mode 100644
index 000000000..42f8f992c
--- /dev/null
+++ b/install/ui/ui-icons_ffffff_256x240.png
Binary files differ
diff --git a/install/ui/user.js b/install/ui/user.js
new file mode 100644
index 000000000..1b499a824
--- /dev/null
+++ b/install/ui/user.js
@@ -0,0 +1,298 @@
+/*jsl:import ipa.js */
+
+/* Authors:
+ * Pavel Zuna <pzuna@redhat.com>
+ *
+ * Copyright (C) 2010 Red Hat
+ * see file 'COPYING' for use and warranty information
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* REQUIRES: ipa.js, details.js, search.js, add.js, entity.js */
+
+IPA.user = function (){
+
+ var that = IPA.entity({
+ name: 'user'
+ });
+
+ that.init = function() {
+
+ that.create_association({
+ 'name': 'group',
+ 'associator': 'serial'
+ });
+
+ that.create_association({
+ 'name': 'netgroup',
+ 'associator': 'serial'
+ });
+
+ var search_facet = IPA.search_facet({
+ 'name': 'search',
+ 'label': 'Search',
+ entity_name: that.name
+ });
+ that.add_facet(search_facet);
+
+ search_facet.create_column({name:'cn'});
+ search_facet.create_column({name:'uid'});
+ search_facet.create_column({name:'uidnumber'});
+ search_facet.create_column({name:'mail'});
+ search_facet.create_column({name:'telephonenumber'});
+ search_facet.create_column({name:'title'});
+
+ that.add_facet(details_facet({name:'details'}));
+
+ var dialog = IPA.add_dialog({
+ 'name': 'add',
+ 'title': 'Add User'
+ });
+ that.add_dialog(dialog);
+
+ dialog.add_field(IPA.text_widget({ name: 'uid', undo: false }));
+ dialog.add_field(IPA.text_widget({ name: 'givenname', undo: false }));
+ dialog.add_field(IPA.text_widget({ name: 'sn', undo: false }));
+ dialog.init();
+
+ /*eventually, we need to call
+ entity.create_association_facets();
+ but we are currently defining the associator using the global
+ function after the registration of the entity */
+ that.create_association_facets();
+
+ that.entity_init();
+ };
+
+ function details_facet(spec) {
+ spec = spec || {};
+ var that = IPA.details_facet(spec);
+
+ var sections =[
+ IPA.stanza({name:'identity', label:IPA.messages.details.identity}).
+ input({name:'title'}).
+ input({name:'givenname'}).
+ input({name:'sn'}).
+ input({name:'cn'}).
+ input({name:'displayname'}).
+ input({name:'initials'}),
+ IPA.stanza({name:'account', label:IPA.messages.details.account}).
+ custom_input(user_status_widget({name:'nsaccountlock'})).
+ input({name:'uid'}).
+ input({name:'userpassword', load: user_password_load}).
+ input({name:'uidnumber'}).
+ input({name:'gidnumber'}).
+ input({name:'loginshell'}).
+ input({name:'homedirectory'}),
+ IPA.stanza({name:'contact', label:IPA.messages.details.contact}).
+ input({name:'mail'}).
+ input({name:'telephonenumber'}).
+ input({name:'pager'}).
+ input({name:'mobile'}).
+ input({name:'facsimiletelephonenumber'}),
+ IPA.stanza({name:'address', label: IPA.messages.details.mailing}).
+ input({name:'street'}).
+ input({name:'location'}).
+ input({name:'state', load:user_state_load}).
+ input({name:'postalcode'}),
+ IPA.stanza({name:'employee', label:IPA.messages.details.employee}).
+ input({name:'ou', label:'Org. Unit'}).
+ input({name:'manager'}),
+ IPA.stanza({name:'misc', label:IPA.messages.details.misc}).
+ input({name:'carlicense'})
+ ];
+ for (var i = 0; i < sections.length; i += 1){
+ that.add_section(sections[i]);
+ }
+ return that;
+ }
+ return that;
+};
+
+
+IPA.add_entity(IPA.user());
+
+/* ATTRIBUTE CALLBACKS */
+
+
+function user_status_widget(spec) {
+
+ spec = spec || {};
+
+ var that = IPA.widget(spec);
+
+ that.update = function() {
+
+ if (!that.record) return;
+
+ $('dd', that.container).remove();
+
+ var dd = IPA.create_first_dd(this.name);
+ dd.appendTo(that.container);
+
+ var lock_field = 'nsaccountlock';
+
+ var locked = that.record[lock_field] &&
+ that.record[lock_field][0].toLowerCase() === 'true';
+ var title = "Active";
+ var text = "Active: Click to Deactivate";
+ if (locked) {
+ title = "Inactive";
+ text = "Inactive: Click to Activate";
+ }
+
+ function on_lock_win(data, textStatus, xhr){
+ var entity = IPA.get_entity(that.entity_name);
+ var facet = entity.get_facet('details');
+ facet.refresh();
+ return false;
+ }
+
+ function on_lock_fail(data, textStatus, xhr){
+ $("#userstatuslink").text = "Error changing account status";
+ return false;
+ }
+
+ var status_field =
+ $('<a/>',
+ {
+ id: 'userstatuslink',
+ title: title,
+ href: "jslink",
+ text: text,
+ click: function() {
+ var jobj = $(this);
+ var val = jobj.attr('title');
+ var pkey = $.bbq.getState('user-pkey');
+ var command = 'user_enable';
+ if (val == 'Active') {
+ command = 'user_disable';
+ }
+ IPA.cmd(command, [pkey], {}, on_lock_win,on_lock_fail);
+
+ return (false);
+ }
+ });
+ status_field.appendTo(dd);
+ };
+
+ return that;
+}
+
+function resetpwd_on_click(){
+
+ function reset_password(new_password){
+ var dialog = resetpwd_dialog;
+
+ var user_pkey = $.bbq.getState('user-pkey');
+ var pw_pkey;
+ if (user_pkey === IPA.whoami.uid[0]){
+ pw_pkey = [];
+ }else{
+ pw_pkey = [user_pkey];
+ }
+
+ IPA.cmd('passwd',
+ pw_pkey, {"password":new_password},
+ function(){
+ alert("Password change complete");
+ dialog.dialog("close");
+ },
+ function(){});
+ }
+
+
+ var resetpwd_dialog =
+ $('<div ><dl class="modal">'+
+ '<dt>New Password</dt>'+
+ '<dd class="first" ><input id="password_1" type="password"/></dd>'+
+ '<dt>Repeat Password</dt>'+
+ '<dd class="first"><input id="password_2" type="password"/></dd>'+
+ '</dl></div>');
+ resetpwd_dialog.dialog(
+ { modal: true,
+ minWidth:400,
+ buttons: {
+ 'Reset Password': function(){
+ var p1 = $("#password_1").val();
+ var p2 = $("#password_2").val();
+ if (p1 != p2){
+ alert("passwords must match");
+ return;
+ }
+ reset_password(p1);
+ },
+ 'Cancel':function(){
+ resetpwd_dialog.dialog('close');
+ }
+ }});
+ return false;
+}
+
+function user_password_load(result) {
+
+ var that = this;
+
+ $('dd', that.container).remove();
+
+ var dd = IPA.create_first_dd(this.name);
+ dd.appendTo(that.container);
+
+ var link = $('<a/>',{
+ href:"jslink",
+ click:resetpwd_on_click,
+ title:'userpassword',
+ text: 'reset password'
+ });
+ link.appendTo(dd);
+
+}
+
+var select_temp = '<select title="st"></select>';
+var option_temp = '<option value="V">V</option>';
+var states = [
+ 'AL', 'AK', 'AS', 'AZ', 'AR', 'CA', 'CO', 'CT', 'DE', 'DC', 'FM',
+ 'FL', 'GA', 'GU', 'HI', 'ID', 'IL', 'IN', 'IA', 'KS', 'KY', 'LA',
+ 'ME', 'MH', 'MD', 'MA', 'MI', 'MN', 'MS', 'MO', 'MT', 'NE', 'NV',
+ 'NH', 'NJ', 'NM', 'NY', 'NC', 'ND', 'MP', 'OH', 'OK', 'OR', 'PW',
+ 'PA', 'PR', 'RI', 'SC', 'SD', 'TN', 'TX', 'UT', 'VT', 'VI', 'VA',
+ 'WA', 'WV', 'WI', 'WY', ''
+];
+function user_state_load(result) {
+
+ var that = this;
+
+ $('dd', that.container).remove();
+
+ //var next = dt.next();
+ //next.css('clear', 'none');
+ //next.css('width', '70px');
+
+ var dd = IPA.create_first_dd(this.name);
+ dd.append(select_temp);
+ dd.appendTo(that.container);
+
+ var sel = dd.children().first();
+ for (var i = 0; i < states.length; ++i)
+ sel.append(option_temp.replace(/V/g, states[i]));
+
+ var st = result['st'];
+ if (st)
+ sel.val(st);
+ else
+ sel.val('');
+}
+
+
diff --git a/install/ui/webui.js b/install/ui/webui.js
new file mode 100644
index 000000000..1f45f0b1e
--- /dev/null
+++ b/install/ui/webui.js
@@ -0,0 +1,172 @@
+/*jsl:import ipa.js */
+/*jsl:import navigation.js */
+
+/* Authors:
+ * Pavel Zuna <pzuna@redhat.com>
+ *
+ * Copyright (C) 2010 Red Hat
+ * see file 'COPYING' for use and warranty information
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* REQUIRES: everything, this file puts it all togheter */
+
+/* tabs definition for IPA webUI */
+
+
+var admin_tab_set = [
+ {name:'identity', children:[
+ {name:'user', entity:'user'},
+ {name:'group', entity:'group'},
+ {name:'host', entity:'host'},
+ {name:'hostgroup', entity:'hostgroup'},
+ {name:'netgroup', entity:'netgroup'},
+ {name:'service', entity:'service'}
+ ]},
+ {name:'policy', children:[
+ {name:'dnszone', entity:'dnszone'},
+ {name:'hbacrule', entity:'hbacrule', children:[
+ {name:'hbacsvc', entity:'hbacsvc'},
+ {name:'hbacsvcgroup', entity:'hbacsvcgroup'}
+ ]},
+ {name:'sudorule', entity:'sudorule',children:[
+ {name:'sudocmd', entity:'sudocmd'},
+ {name:'sudocmdgroup', entity:'sudocmdgroup'}
+ ]},
+ {name:'pwpolicy', entity:'pwpolicy'},
+ {name:'krbtpolicy', entity:'krbtpolicy'}
+ ]},
+ {name:'ipaserver', children: [
+ {name:'role',entity:'role' ,children:[
+ {name:'privilege',entity:'privilege' },
+ {name:'permission', entity:'permission'}
+ ]},
+ {name:'selfservice' ,entity:'selfservice'},
+ {name:'delegation' ,entity:'delegation'},
+ {name:'config', entity:'config'}
+ ]}
+];
+
+var self_serv_tab_set =
+ [
+ { name:'identity', children: [
+ {name:'user', entity:'user'}]}];
+
+
+IPA.tab_state = function(entity_name){
+
+ var state = {};
+
+ for (var top_tab_index = 0;
+ top_tab_index < IPA.tab_set.length;
+ top_tab_index += 1){
+ var top_tab = IPA.tab_set[top_tab_index];
+ for (var subtab_index = 0;
+ subtab_index < top_tab.children.length;
+ subtab_index += 1){
+ if(top_tab.children[subtab_index].name){
+ if (top_tab.children[subtab_index].name === entity_name){
+ state.navigation = top_tab_index;
+ state[top_tab.name] = subtab_index;
+ return state;
+ }else if (top_tab.children[subtab_index].children){
+ var nested_entities = top_tab.children[subtab_index].children;
+ for (var nested_index = 0;
+ nested_index < nested_entities.length;
+ nested_index += 1){
+ if (nested_entities[nested_index].name === entity_name){
+ state.navigation = top_tab_index;
+ state[top_tab.name] = subtab_index;
+ state[ top_tab.children[subtab_index].name+'-entity'] = entity_name;
+ return state;
+ }
+ }
+ }
+ }
+ }
+ }
+ /*should never reach here*/
+ return null;
+};
+
+
+/* main (document onready event handler) */
+$(function() {
+
+ function should_show_all_ui(){
+ var whoami = IPA.whoami;
+
+ if (whoami.hasOwnProperty('memberof_group') &&
+ whoami.memberof_group.indexOf('admins') !== -1) return true;
+
+ return whoami.hasOwnProperty('memberof_rolegroup') &&
+ whoami.memberof_rolegroup.length > 0;
+ }
+
+
+ function init_on_win(data, text_status, xhr) {
+ $(window).bind('hashchange', window_hashchange);
+
+ var whoami = IPA.whoami;
+ IPA.whoami_pkey=whoami.uid[0];
+ $('#loggedinas').find('strong').text(whoami.cn[0]);
+ $('#loggedinas a').fragment(
+ {'user-facet':'details', 'user-pkey':IPA.whoami_pkey},2);
+
+ for (var i=0; i<IPA.entities.length; i++) {
+ var entity = IPA.entities[i];
+ entity.init();
+ }
+
+ var navigation = $('#navigation');
+
+ if (should_show_all_ui()){
+ IPA.tab_set = admin_tab_set;
+ nav_create(admin_tab_set, navigation, 'tabs');
+ } else {
+ IPA.tab_set = self_serv_tab_set;
+ nav_create(self_serv_tab_set, navigation, 'tabs');
+
+ var state = {'user-pkey':IPA.whoami_pkey ,
+ 'user-facet': $.bbq.getState('user-facet') ||
+ 'details'};
+ $.bbq.pushState(state);
+ }
+
+
+ $('#login_header').html(IPA.messages.login.header);
+ }
+
+
+ function init_on_error(xhr, text_status, error_thrown) {
+ var navigation = $('#navigation').empty();
+ navigation.append('<p>Error: '+error_thrown.name+'</p>');
+ navigation.append('<p>'+error_thrown.title+'</p>');
+ navigation.append('<p>'+error_thrown.message+'</p>');
+ }
+
+ IPA.init(null, null, init_on_win, init_on_error);
+});
+
+/* main loop (hashchange event handler) */
+function window_hashchange(evt){
+ nav_update_tabs();
+}
+
+/* builder function for unimplemented tab content */
+function unimplemented_tab(jobj){
+ jobj.text('Not implemented yet!');
+}
+
diff --git a/install/ui/widget.js b/install/ui/widget.js
new file mode 100644
index 000000000..576eef77b
--- /dev/null
+++ b/install/ui/widget.js
@@ -0,0 +1,1319 @@
+/*jsl:import ipa.js */
+/* Authors:
+ * Endi Sukma Dewata <edewata@redhat.com>
+ *
+ * Copyright (C) 2010 Red Hat
+ * see file 'COPYING' for use and warranty information
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* REQUIRES: ipa.js */
+
+IPA.widget = function(spec) {
+
+ spec = spec || {};
+
+ var that = {};
+
+ that.id = spec.id;
+ that.name = spec.name;
+ that.label = spec.label;
+ that.tooltip = spec.tooltip;
+ that.read_only = spec.read_only;
+ that._entity_name = spec.entity_name;
+
+ that.width = spec.width;
+ that.height = spec.height;
+
+ that.undo = typeof spec.undo == 'undefined' ? true : spec.undo;
+
+ that.init = spec.init || init;
+ that.create = spec.create || create;
+ that.setup = spec.setup || setup;
+ that.load = spec.load || load;
+ that.save = spec.save || save;
+ that.update = spec.update || update;
+ that.validate_input = spec.validate_input || validate_input;
+ that.param_info = spec.param_info;
+
+ that.__defineGetter__("entity_name", function(){
+ return that._entity_name;
+ });
+
+ that.__defineSetter__("entity_name", function(entity_name){
+ that._entity_name = entity_name;
+ });
+
+ /*returns true and clears the error message if the field value passes
+ the validation pattern. If the field value does not pass validation,
+ displays the error message and returns false. */
+ function validate_input(text) {
+ if (!(that.param_info && that.param_info.pattern)) {
+ return true;
+ }
+ var error_link = that.get_error_link();
+ if (!error_link) {
+ return true;
+ }
+ var regex = new RegExp( that.param_info.pattern );
+ //If the field is empty, don't validate
+ if ( !text || text.match(regex) ) {
+ error_link.css('display', 'none');
+ return true;
+ }else{
+ error_link.css('display', 'block');
+ if (that.param_info.pattern_errmsg) {
+ error_link.html(that.param_info.pattern_errmsg);
+ }
+ return false;
+ }
+ }
+
+ function init() {
+ if (that.entity_name) {
+ that.param_info = IPA.get_param_info(that.entity_name, that.name);
+
+ if (that.param_info) {
+
+ if (that.label === undefined) {
+ that.label = that.param_info.label;
+ }
+
+ if (that.tooltip === undefined) {
+ that.tooltip = that.param_info.doc;
+ }
+ }
+ }
+ }
+
+ function create(container) {
+ }
+
+ function setup(container) {
+ that.container = container;
+ }
+
+ function load(record) {
+ that.record = record;
+ that.reset();
+ }
+
+ that.reset = function() {
+ that.hide_undo();
+ that.update();
+ };
+
+ function update() {
+ }
+
+ function save() {
+ return [];
+ }
+
+ that.is_dirty = function() {
+
+ var values = that.save();
+ if (!values && !that.values) return false;
+ if (!values || !that.values) return true;
+
+ if (values.length != that.values.length) return true;
+ for (var i=0; i<values.length; i++) {
+ if (values[i] != that.values[i]) return true;
+ }
+
+ return false;
+ };
+
+ that.get_undo = function() {
+ return $('span[name="undo"]', that.container);
+ };
+
+ that.show_undo = function() {
+ var undo = that.get_undo();
+ undo.css('display', 'inline');
+ };
+
+ that.hide_undo = function() {
+ var undo = that.get_undo();
+ undo.css('display', 'none');
+ };
+
+ that.get_error_link = function() {
+ return $('span[name="error_link"]', that.container);
+ };
+
+ that.show_error_link = function() {
+ var error_link = that.get_error_link();
+ error_link.css('display', 'inline');
+ };
+
+ that.hide_error_link = function() {
+ var error_link = that.get_error_link();
+ error_link.css('display', 'none');
+ };
+
+ that.set_enabled = function() {
+ };
+
+ that.refresh = function() {
+ };
+
+ // methods that should be invoked by subclasses
+ that.widget_init = that.init;
+ that.widget_create = that.create;
+ that.widget_setup = that.setup;
+ that.widget_reset = that.reset;
+
+ return that;
+};
+
+
+IPA.text_widget = function(spec) {
+
+ spec = spec || {};
+
+ var that = IPA.widget(spec);
+
+ that.size = spec.size || 30;
+
+ that.create = function(container) {
+
+ $('<input/>', {
+ type: 'text',
+ name: that.name,
+ size: that.size,
+ title: that.tooltip
+ }).appendTo(container);
+
+ $('<span/>', {
+ 'name': 'undo',
+ 'style': 'display: none;',
+ 'html': 'undo'
+ }).appendTo(container);
+
+ $("<span/>",{
+ name:'error_link',
+ html:"Text does not match field pattern",
+ "class":"ui-state-error ui-corner-all",
+ style:"display:none"
+ }).appendTo(container);
+ };
+
+ that.setup = function(container) {
+
+ this.widget_setup(container);
+
+ var input = $('input[name="'+that.name+'"]', that.container);
+ input.keyup(function() {
+ if(that.undo){
+ that.show_undo();
+ }
+ var value = $('input[name="'+that.name+'"]', that.container).val();
+ that.validate_input(value);
+ });
+
+ var undo = that.get_undo();
+ undo.click(function() {
+ that.reset();
+ });
+ };
+
+ that.load = function(record) {
+
+ that.values = record[that.name] || [''];
+
+ if (that.read_only) {
+ var input = $('input[name="'+that.name+'"]', that.container);
+ var label = $('<label/>', {
+ 'name': that.name,
+ 'html': that.values[0]
+ });
+ input.replaceWith(label);
+
+ } else {
+ that.reset();
+ }
+ };
+
+ that.save = function() {
+ if (that.read_only) {
+ return that.values;
+ } else {
+ var value = $('input[name="'+that.name+'"]', that.container).val();
+ return [value];
+ }
+ };
+
+ that.update = function() {
+ var value = that.values && that.values.length ? that.values[0] : '';
+ if (that.read_only) {
+ $('label[name="'+that.name+'"]', that.container).val(value);
+ } else {
+ $('input[name="'+that.name+'"]', that.container).val(value);
+ }
+ };
+
+ return that;
+};
+
+IPA.checkbox_widget = function (spec) {
+
+ spec = spec || {};
+ var is_checked = spec.checked || '';
+ var that = IPA.widget(spec);
+
+ that.create = function(container) {
+
+ $('<input/>', {
+ type: 'checkbox',
+ name: that.name,
+ checked : is_checked,
+ title: that.tooltip
+ }).appendTo(container);
+
+ if (that.undo) {
+ $('<span/>', {
+ 'name': 'undo',
+ 'style': 'display: none;',
+ 'html': 'undo'
+ }).appendTo(container);
+ }
+ };
+
+ that.setup = function(container) {
+
+ that.widget_setup(container);
+
+ var input = $('input[name="'+that.name+'"]', that.container);
+ input.change(function() {
+ that.show_undo();
+ });
+
+ var undo = that.get_undo();
+ undo.click(function() {
+ that.reset();
+ });
+ };
+
+ that.load = function(record) {
+ that.values = record[that.name] || [false];
+ that.reset();
+ };
+
+ that.save = function() {
+ var value = $('input[name="'+that.name+'"]', that.container).is(':checked');
+ return [value];
+ };
+
+ that.update = function() {
+ var value = that.values && that.values.length ? that.values[0] : false;
+ $('input[name="'+that.name+'"]', that.container).get(0).checked = value;
+ };
+
+ return that;
+};
+
+IPA.radio_widget = function(spec) {
+
+ spec = spec || {};
+
+ var that = IPA.widget(spec);
+
+ that.options = spec.options;
+
+ that.create = function(container) {
+
+ for (var i=0; i<that.options.length; i++) {
+ var option = that.options[i];
+
+ $('<input/>', {
+ 'type': 'radio',
+ 'name': that.name,
+ 'value': option.value
+ }).appendTo(container);
+
+ container.append(option.label);
+ }
+
+ if (that.undo) {
+ $('<span/>', {
+ 'name': 'undo',
+ 'style': 'display: none;',
+ 'html': 'undo'
+ }).appendTo(container);
+ }
+ };
+
+ that.setup = function(container) {
+
+ that.widget_setup(container);
+
+ var input = $('input[name="'+that.name+'"]', that.container);
+ input.change(function() {
+ that.show_undo();
+ });
+
+ var undo = that.get_undo();
+ undo.click(function() {
+ that.reset();
+ });
+ };
+
+ that.load = function(record) {
+ that.values = record[that.name] || [''];
+ that.reset();
+ };
+
+ that.save = function() {
+ var input = $('input[name="'+that.name+'"]:checked', that.container);
+ if (!input.length) return [];
+ return [input.val()];
+ };
+
+ that.update = function() {
+ if (that.values && that.values.length) {
+ var input = $('input[name="'+that.name+'"][value="'+that.values[0]+'"]', that.container);
+ if (input.length) {
+ input.get(0).checked = true;
+ return;
+ }
+ }
+
+ $('input[name="'+that.name+'"]', that.container).each(function() {
+ var input = this;
+ input.checked = false;
+ });
+ };
+
+ // methods that should be invoked by subclasses
+ that.radio_save = that.save;
+
+ return that;
+};
+
+IPA.textarea_widget = function (spec) {
+
+ spec = spec || {};
+
+ var that = IPA.widget(spec);
+
+ that.rows = spec.rows || 5;
+ that.cols = spec.cols || 40;
+
+ that.create = function(container) {
+
+ $('<textarea/>', {
+ rows: that.rows,
+ cols: that.cols,
+ name: that.name,
+ title: that.tooltip
+ }).appendTo(container);
+
+ if (that.undo) {
+ $('<span/>', {
+ 'name': 'undo',
+ 'style': 'display: none;',
+ 'html': 'undo'
+ }).appendTo(container);
+ }
+ };
+
+ that.setup = function(container) {
+
+ that.widget_setup(container);
+
+ var input = $('textarea[name="'+that.name+'"]', that.container);
+ input.keyup(function() {
+ undo.css('display', 'inline');
+ });
+
+ var undo = that.get_undo();
+ undo.click(function() {
+ that.reset();
+ });
+ };
+
+ that.load = function(record) {
+ that.values = record[that.name] || [''];
+ that.reset();
+ };
+
+ that.save = function() {
+ var value = $('textarea[name="'+that.name+'"]', that.container).val();
+ return [value];
+ };
+
+ that.update = function() {
+ var value = that.values && that.values.length ? that.values[0] : '';
+ $('textarea[name="'+that.name+'"]', that.container).val(value);
+ };
+
+ return that;
+};
+
+IPA.button_widget = function (spec) {
+
+ spec = spec || {};
+
+ spec.setup = spec.setup || setup;
+ spec.load = spec.load || load;
+ spec.save = spec.save || save;
+
+ var that = IPA.widget(spec);
+
+ that.click = spec.click;
+
+ function setup(container) {
+
+ that.widget_setup(container);
+
+ var input = $('[name="'+that.name+'"]', that.container);
+ input.replaceWith(IPA.button({ 'label': that.label, 'click': that.click }));
+ }
+
+ function load(record) {
+ }
+
+ function save() {
+ return [];
+ }
+
+ return that;
+};
+
+IPA.column = function (spec) {
+
+ spec = spec || {};
+
+ var that = {};
+
+ that.name = spec.name;
+ that.label = spec.label;
+ that.primary_key = spec.primary_key;
+ that.width = spec.width;
+ that.entity_name = spec.entity_name;
+
+ that.setup = spec.setup || setup;
+
+ that.init = function() {
+ if (that.entity_name && !that.label) {
+ var param_info = IPA.get_param_info(that.entity_name, that.name);
+ if (param_info) that.label = param_info.label;
+ }
+ };
+
+ function setup(container, record) {
+
+ container.empty();
+
+ var value = record[that.name];
+ value = value ? value.toString() : '';
+
+ container.append(value);
+ }
+
+ return that;
+};
+
+IPA.table_widget = function (spec) {
+
+ spec = spec || {};
+
+ var that = IPA.widget(spec);
+
+ that.scrollable = spec.scrollable;
+ that.save_values = typeof spec.save_values == 'undefined' ? true : spec.save_values;
+
+ that.columns = [];
+ that.columns_by_name = {};
+
+ that.get_columns = function() {
+ return that.columns;
+ };
+
+ that.get_column = function(name) {
+ return that.columns_by_name[name];
+ };
+
+ that.add_column = function(column) {
+ that.columns.push(column);
+ that.columns_by_name[column.name] = column;
+ };
+
+ that.set_columns = function(columns) {
+ that.clear_columns();
+ for (var i=0; i<columns.length; i++) {
+ that.add_column(columns[i]);
+ }
+ };
+
+ that.clear_columns = function() {
+ that.columns = [];
+ that.columns_by_name = {};
+ };
+
+ that.create_column = function(spec) {
+ var column = IPA.column(spec);
+ that.add_column(column);
+ return column;
+ };
+
+ that.init = function() {
+ that.widget_init();
+
+ for (var i=0; i<that.columns.length; i++) {
+ var column = that.columns[i];
+ column.init();
+ }
+ };
+
+ that.create = function(container) {
+
+ var table = $('<table/>', {
+ 'class': 'search-table'
+ }).appendTo(container);
+
+ if (that.scrollable) {
+ table.addClass('scrollable');
+ }
+
+ var thead = $('<thead/>').appendTo(table);
+
+ var tr = $('<tr/>').appendTo(thead);
+
+ var th = $('<th/>', {
+ 'style': 'width: 22px;'
+ }).appendTo(tr);
+
+ $('<input/>', {
+ 'type': 'checkbox',
+ 'name': 'select'
+ }).appendTo(th);
+
+ for (var i=0; i<that.columns.length; i++) {
+ var column = that.columns[i];
+
+ th = $('<th/>').appendTo(tr);
+
+ if (that.scrollable && (i == that.columns.length-1)) {
+ if (column.width) {
+ var width = parseInt(column.width.substring(0, column.width.length-2),10);
+ width += 16;
+ th.css('width', width+'px');
+ }
+ } else {
+ if (column.width) {
+ th.css('width', column.width);
+ }
+ }
+
+ var label = column.label;
+
+ $('<span/>', {
+ 'style': 'float: left;',
+ 'html': label
+ }).appendTo(th);
+
+ if (i == that.columns.length-1) {
+ $('<span/>', {
+ 'name': 'buttons',
+ 'style': 'float: right;'
+ }).appendTo(th);
+ }
+ }
+
+ var tbody = $('<tbody/>').appendTo(table);
+
+ if (that.height) {
+ tbody.css('height', that.height);
+ }
+
+ tr = $('<tr/>').appendTo(tbody);
+
+ var td = $('<td/>', {
+ 'style': 'width: 22px;'
+ }).appendTo(tr);
+
+ $('<input/>', {
+ 'type': 'checkbox',
+ 'name': 'select',
+ 'value': 'user'
+ }).appendTo(td);
+
+ for (/* var */ i=0; i<that.columns.length; i++) {
+ /* var */ column = that.columns[i];
+
+ td = $('<td/>').appendTo(tr);
+ if (column.width) {
+ td.css('width', column.width);
+ }
+
+ $('<span/>', {
+ 'name': column.name
+ }).appendTo(td);
+ }
+
+ var tfoot = $('<tfoot/>').appendTo(table);
+
+ tr = $('<tr/>').appendTo(tfoot);
+
+ td = $('<td/>', { colspan: that.columns.length+1 }).appendTo(tr);
+
+ $('<span/>', {
+ 'name': 'summary'
+ }).appendTo(td);
+ };
+
+
+ that.select_changed = function(){
+ };
+
+
+ that.setup = function(container) {
+
+ that.widget_setup(container);
+
+ that.table = $('table', that.container);
+ that.thead = $('thead', that.table);
+ that.tbody = $('tbody', that.table);
+ that.tfoot = $('tfoot', that.table);
+
+ var select_all_checkbox = $('input[name=select]', that.thead);
+ select_all_checkbox.attr('title', 'Select All');
+
+ select_all_checkbox.change(function() {
+ var checked = select_all_checkbox.is(':checked');
+ select_all_checkbox.attr('title', checked ? 'Unselect All' : 'Select All');
+ var checkboxes = $('input[name=select]', that.tbody).get();
+ for (var i=0; i<checkboxes.length; i++) {
+ checkboxes[i].checked = checked;
+ }
+ that.select_changed();
+ return false;
+ });
+
+ that.row = that.tbody.children().first();
+ that.row.detach();
+ };
+
+ that.empty = function() {
+ that.tbody.empty();
+ };
+
+ that.load = function(result) {
+
+ that.empty();
+
+ that.values = result[that.name];
+ if (!that.values) return;
+
+ for (var i=0; i<that.values.length; i++) {
+ var record = that.get_record(result, i);
+ that.add_record(record);
+ }
+ };
+
+ that.save = function() {
+ if (that.save_values) {
+ var values = [];
+
+ $('input[name="select"]', that.tbody).each(function() {
+ values.push($(this).val());
+ });
+
+ return values;
+
+ } else {
+ return null;
+ }
+ };
+
+ that.get_selected_values = function() {
+ var values = [];
+
+ $('input[name="select"]:checked', that.tbody).each(function() {
+ values.push($(this).val());
+ });
+
+ return values;
+ };
+
+ that.get_record = function(result, index) {
+ var record = {};
+ for (var i=0; i<that.columns.length; i++){
+ var name = that.columns[i].name;
+ var values = result[name];
+ if (!values) continue;
+ if (values instanceof Array){
+ record[name] = values[index];
+ }else{
+ record[name] = values;
+ }
+ }
+ return record;
+ };
+
+ that.add_record = function(record) {
+
+ var tr = that.row.clone();
+ tr.appendTo(that.tbody);
+
+ for (var i=0; i<that.columns.length; i++){
+ var column = that.columns[i];
+
+ var value = record[column.name];
+ value = value ? value.toString() : '';
+
+ if (column.primary_key) {
+ // set checkbox value
+ $('input[name="select"]', tr).val(value);
+
+ $('input[name="select"]', tr).click(function(){
+ that.select_changed();
+ });
+
+ }
+
+ var span = $('span[name="'+column.name+'"]', tr);
+
+ column.setup(span, record);
+ }
+ };
+
+ that.add_rows = function(rows) {
+ for (var i=0; i<rows.length; i++) {
+ that.tbody.append(rows[i]);
+ }
+ };
+
+ that.remove_selected_rows = function() {
+ var rows = [];
+ that.tbody.children().each(function() {
+ var tr = $(this);
+ if (!$('input[name="select"]', tr).get(0).checked) return;
+ tr.detach();
+ rows.push(tr);
+ });
+ return rows;
+ };
+
+ that.set_enabled = function(enabled) {
+ if (enabled) {
+ $('input[name="select"]', that.table).attr('disabled', false);
+ } else {
+ $('input[name="select"]', that.table).attr('disabled', true);
+ }
+ };
+
+ that.refresh = function() {
+
+ function on_success(data, text_status, xhr) {
+ that.load(data.result.result);
+ }
+
+ function on_error(xhr, text_status, error_thrown) {
+ var summary = $('span[name=summary]', that.tfoot).empty();
+ summary.append('<p>Error: '+error_thrown.name+'</p>');
+ summary.append('<p>'+error_thrown.title+'</p>');
+ summary.append('<p>'+error_thrown.message+'</p>');
+ }
+
+ var pkey = $.bbq.getState(that.entity_name + '-pkey', true) || '';
+ IPA.cmd('show', [pkey], {'all': true, 'rights': true}, on_success, on_error, that.entity_name);
+ };
+
+ if (spec.columns) {
+ for (var i=0; i<spec.columns; i++) {
+ that.create_column(spec.columns[i]);
+ }
+ }
+
+ // methods that should be invoked by subclasses
+ that.table_init = that.init;
+ that.table_create = that.create;
+ that.table_setup = that.setup;
+ that.table_set_enabled = that.set_enabled;
+
+ return that;
+};
+
+/**
+ * This is a base class for dialog boxes.
+ */
+IPA.dialog = function(spec) {
+
+ spec = spec || {};
+
+ var that = {};
+
+ that.name = spec.name;
+ that.title = spec.title;
+ that.template = spec.template;
+ that._entity_name = spec.entity_name;
+
+ that.width = spec.width || 400;
+
+ that.buttons = {};
+
+ that.fields = [];
+ that.fields_by_name = {};
+
+ that.__defineGetter__("entity_name", function(){
+ return that._entity_name;
+ });
+
+ that.__defineSetter__("entity_name", function(entity_name){
+ that._entity_name = entity_name;
+
+ for (var i=0; i<that.fields.length; i++) {
+ that.fields[i].entity_name = entity_name;
+ }
+ });
+
+ that.add_button = function(name, handler) {
+ that.buttons[name] = handler;
+ };
+
+ that.get_field = function(name) {
+ return that.fields_by_name[name];
+ };
+
+ that.add_field = function(field) {
+ that.fields.push(field);
+ that.fields_by_name[field.name] = field;
+ };
+
+ that.init = function() {
+ for (var i=0; i<that.fields.length; i++) {
+ var field = that.fields[i];
+ field.entity_name = that.entity_name;
+ field.init();
+ }
+ };
+
+ /**
+ * Create content layout
+ */
+ that.create = function() {
+
+ var table = $('<table/>').appendTo(that.container);
+
+ for (var i=0; i<that.fields.length; i++) {
+ var field = that.fields[i];
+
+ var tr = $('<tr/>').appendTo(table);
+
+ var td = $('<td/>', {
+ style: 'vertical-align: top;',
+ title: field.label
+ }).appendTo(tr);
+ td.append(field.label+': ');
+
+ td = $('<td/>', {
+ style: 'vertical-align: top;'
+ }).appendTo(tr);
+
+ var span = $('<span/>', { 'name': field.name }).appendTo(td);
+ field.create(span);
+ }
+ };
+
+ /**
+ * Setup behavior
+ */
+ that.setup = function() {
+ for (var i=0; i<that.fields.length; i++) {
+ var field = that.fields[i];
+
+ var span = $('span[name="'+field.name+'"]', that.container);
+ field.setup(span);
+ }
+ };
+
+ /**
+ * Open dialog
+ */
+ that.open = function(container) {
+
+ that.container = $('<div/>').appendTo(container);
+
+ if (that.template) {
+ var template = IPA.get_template(that.template);
+ that.container.load(
+ template,
+ function(data, text_status, xhr) {
+ that.setup();
+ that.container.dialog({
+ 'title': that.title,
+ 'modal': true,
+ 'width': that.width,
+ 'height': that.height,
+ 'buttons': that.buttons
+ });
+ }
+ );
+
+ } else {
+ that.create();
+ that.setup();
+
+ that.container.dialog({
+ 'title': that.title,
+ 'modal': true,
+ 'width': that.width,
+ 'height': that.height,
+ 'buttons': that.buttons
+ });
+ }
+ };
+
+ that.option = function(name, value) {
+ that.container.dialog('option', name, value);
+ };
+
+ that.get_record = function() {
+ var record = {};
+ for (var i=0; i<that.fields.length; i++) {
+ var field = that.fields[i];
+ var values = field.save();
+ record[field.name] = values[0];
+ }
+ return record;
+ };
+
+ that.close = function() {
+ that.container.dialog('destroy');
+ that.container.remove();
+ };
+
+ that.reset = function() {
+ for (var i=0; i<that.fields.length; i++) {
+ var field = that.fields[i];
+ field.reset();
+ }
+ };
+
+ that.dialog_init = that.init;
+ that.dialog_create = that.create;
+ that.dialog_setup = that.setup;
+ that.dialog_open = that.open;
+
+ return that;
+};
+
+/**
+ * This dialog provides an interface for searching and selecting
+ * values from the available results.
+ */
+IPA.adder_dialog = function (spec) {
+
+ spec = spec || {};
+
+ var that = IPA.dialog(spec);
+
+ that.width = spec.width || '600px';
+
+ that.columns = [];
+ that.columns_by_name = {};
+
+ that.get_column = function(name) {
+ return that.columns_by_name[name];
+ };
+
+ that.add_column = function(column) {
+ that.columns.push(column);
+ that.columns_by_name[column.name] = column;
+ };
+
+ that.set_columns = function(columns) {
+ that.clear_columns();
+ for (var i=0; i<columns.length; i++) {
+ that.add_column(columns[i]);
+ }
+ };
+
+ that.clear_columns = function() {
+ that.columns = [];
+ that.columns_by_name = {};
+ };
+
+ that.create_column = function(spec) {
+ var column = IPA.column(spec);
+ that.add_column(column);
+ return column;
+ };
+
+ that.init = function() {
+ that.available_table = IPA.table_widget({
+ name: 'available',
+ scrollable: true,
+ height: '151px'
+ });
+
+ that.available_table.set_columns(that.columns);
+
+ that.available_table.init();
+
+ that.selected_table = IPA.table_widget({
+ name: 'selected',
+ scrollable: true,
+ height: '151px'
+ });
+
+ that.selected_table.set_columns(that.columns);
+
+ that.selected_table.init();
+
+ that.dialog_init();
+ };
+
+ that.create = function() {
+
+ // do not call that.dialog_create();
+
+ var search_panel = $('<div/>', {
+ 'class': 'adder-dialog-filter'
+ }).appendTo(that.container);
+
+ $('<input/>', {
+ type: 'text',
+ name: 'filter',
+ style: 'width: 244px'
+ }).appendTo(search_panel);
+
+ search_panel.append(' ');
+
+ $('<input/>', {
+ type: 'button',
+ name: 'find',
+ value: 'Find'
+ }).appendTo(search_panel);
+
+ $('<input/>', {
+ type: 'checkbox',
+ name: 'hidememb',
+ id: 'hidememb',
+ checked: 'checked',
+ style: 'margin-left: 5px; vertical-align: middle'
+ }).appendTo(search_panel);
+
+ var label = $('<label/>', {
+ 'for': 'hidememb',
+ style: 'margin-left: 3px'
+ });
+
+ label.text('Hide already enrolled.');
+
+ label.appendTo(search_panel);
+
+ search_panel.append(IPA.create_network_spinner());
+
+ var results_panel = $('<div/>', {
+ 'class': 'adder-dialog-results'
+ }).appendTo(that.container);
+
+ var available_panel = $('<div/>', {
+ name: 'available',
+ 'class': 'adder-dialog-available'
+ }).appendTo(results_panel);
+
+ $('<div/>', {
+ html: 'Available',
+ 'class': 'ui-widget-header'
+ }).appendTo(available_panel);
+
+ that.available_table.create(available_panel);
+
+ var buttons_panel = $('<div/>', {
+ name: 'buttons',
+ 'class': 'adder-dialog-buttons'
+ }).appendTo(results_panel);
+
+ var p = $('<p/>').appendTo(buttons_panel);
+ $('<input />', {
+ type: 'button',
+ name: 'remove',
+ value: '<<'
+ }).appendTo(p);
+
+ p = $('<p/>').appendTo(buttons_panel);
+ $('<input />', {
+ type: 'button',
+ name: 'add',
+ value: '>>'
+ }).appendTo(p);
+
+ var selected_panel = $('<div/>', {
+ name: 'selected',
+ 'class': 'adder-dialog-selected'
+ }).appendTo(results_panel);
+
+ $('<div/>', {
+ html: 'Prospective',
+ 'class': 'ui-widget-header'
+ }).appendTo(selected_panel);
+
+ that.selected_table.create(selected_panel);
+ };
+
+ that.setup = function() {
+
+ // do not call that.dialog_setup();
+
+ var available_panel = $('div[name=available]', that.container);
+ that.available_table.setup(available_panel);
+
+ var selected_panel = $('div[name=selected]', that.container);
+ that.selected_table.setup(selected_panel);
+
+ that.filter_field = $('input[name=filter]', that.container);
+
+ var button = $('input[name=find]', that.container);
+ that.find_button = IPA.button({
+ 'label': button.val(),
+ 'icon': 'ui-icon-search',
+ 'click': function() { that.search(); }
+ });
+ button.replaceWith(that.find_button);
+
+ button = $('input[name=remove]', that.container);
+ that.remove_button = IPA.button({
+ 'label': button.val(),
+ 'icon': 'ui-icon-trash',
+ 'click': function() {
+ that.remove();
+ }
+ });
+ button.replaceWith(that.remove_button);
+
+ button = $('input[name=add]', that.container);
+ that.add_button = IPA.button({
+ 'label': button.val(),
+ 'icon': 'ui-icon-plus',
+ 'click': function() {
+ that.add();
+ }
+ });
+ button.replaceWith(that.add_button);
+
+ that.search();
+ };
+
+ that.open = function(container) {
+ that.buttons = {
+ 'Enroll': function() {
+ that.execute();
+ },
+ 'Cancel': function() {
+ that.close();
+ }
+ };
+
+ that.dialog_open(container);
+ };
+
+ that.add = function() {
+ var rows = that.available_table.remove_selected_rows();
+ that.selected_table.add_rows(rows);
+ };
+
+ that.remove = function() {
+ var rows = that.selected_table.remove_selected_rows();
+ that.available_table.add_rows(rows);
+ };
+
+ that.get_filter = function() {
+ return that.filter_field.val();
+ };
+
+ that.get_hide_checkbox = function() {
+ return that.hide_checkbox.checked;
+ };
+
+ that.clear_available_values = function() {
+ that.available_table.empty();
+ };
+
+ that.clear_selected_values = function() {
+ that.selected_table.empty();
+ };
+
+ that.add_available_value = function(record) {
+ that.available_table.add_record(record);
+ };
+
+ that.get_selected_values = function() {
+ return that.selected_table.save();
+ };
+
+ that.close = function() {
+ that.container.dialog('close');
+ };
+
+ that.adder_dialog_init = that.init;
+ that.adder_dialog_create = that.create;
+ that.adder_dialog_setup = that.setup;
+
+ return that;
+};
+
+/**
+ * This dialog displays the values to be deleted.
+ */
+IPA.deleter_dialog = function (spec) {
+
+ spec = spec || {};
+
+ var that = IPA.dialog(spec);
+
+ that.title = spec.title || IPA.messages.button.remove;
+ that.remove = spec.remove;
+
+ that.values = spec.values || [];
+
+ that.add_value = function(value) {
+ that.values.push(value);
+ };
+
+ that.set_values = function(values) {
+ that.values = that.values.concat(values);
+ };
+
+ that.create = function() {
+ var ul = $('<ul/>');
+ ul.appendTo(that.container);
+
+ for (var i=0; i<that.values.length; i++) {
+ $('<li/>',{
+ 'text': that.values[i]
+ }).appendTo(ul);
+ }
+
+ $('<p/>', {
+ 'text': IPA.messages.search.delete_confirm
+ }).appendTo(that.container);
+ };
+
+ that.open = function(container) {
+ that.buttons = {
+ 'Delete': that.remove,
+ 'Cancel': that.close
+ };
+
+ that.dialog_open(container);
+ };
+
+ return that;
+};