From c98521571432a52064e7df43c89c1b88457ffb0b Mon Sep 17 00:00:00 2001 From: Timothy J Warren Date: Fri, 8 Feb 2019 13:44:52 -0500 Subject: [PATCH] First commit, 'forked' from https://sourceforge.net/projects/phpldapadmin/ --- .gitignore | 3 + INSTALL | 23 + LICENSE | 341 ++ VERSION | 1 + config/config.php.example | 576 +++ doc/README-translation.txt | 2 + doc/certs/ca-bundle.crt | 4567 +++++++++++++++++ doc/certs/slapd.crt | 17 + doc/certs/slapd.key | 15 + doc/demo-reset.sh | 18 + doc/ldif-Flintstones | 992 ++++ doc/ldif-Simpsons | 496 ++ doc/ldif-example-com | 139 + doc/ldif-example.com | 165 + doc/phpldapadmin-demo.conf | 107 + doc/pla-test-i18n.ldif | 66 + doc/uidpool.schema | 11 + hooks/classes/README | 3 + hooks/functions/README | 1 + hooks/functions/example.php | 402 ++ htdocs/add_attr_form.php | 185 + htdocs/add_oclass_form.php | 117 + htdocs/add_value_form.php | 173 + htdocs/cmd.php | 79 + htdocs/collapse.php | 27 + htdocs/common.php | 14 + htdocs/compare.php | 188 + htdocs/compare_form.php | 65 + htdocs/copy.php | 209 + htdocs/copy_form.php | 103 + htdocs/create.php | 104 + htdocs/create_confirm.php | 143 + htdocs/css/default/style.css | 925 ++++ htdocs/css/tango/style.css | 952 ++++ htdocs/delete.php | 40 + htdocs/delete_attr.php | 49 + htdocs/delete_form.php | 157 + htdocs/download_binary_attr.php | 49 + htdocs/draw_tree_node.php | 61 + htdocs/entry_chooser.php | 135 + htdocs/expand.php | 27 + htdocs/export.php | 40 + htdocs/export_form.php | 213 + htdocs/images/INFO | 6 + htdocs/images/ajax-progress.gif | Bin 0 -> 7685 bytes htdocs/images/ajax-spinner.gif | Bin 0 -> 2037 bytes htdocs/images/countries/af.png | Bin 0 -> 1042 bytes htdocs/images/countries/al.png | Bin 0 -> 1040 bytes htdocs/images/countries/am.png | Bin 0 -> 1042 bytes htdocs/images/countries/an.png | Bin 0 -> 1041 bytes htdocs/images/countries/ao.png | Bin 0 -> 1041 bytes htdocs/images/countries/ar.png | Bin 0 -> 1043 bytes htdocs/images/countries/at.png | Bin 0 -> 1041 bytes htdocs/images/countries/au.png | Bin 0 -> 1043 bytes htdocs/images/countries/aw.png | Bin 0 -> 1043 bytes htdocs/images/countries/az.png | Bin 0 -> 1042 bytes htdocs/images/countries/ba.png | Bin 0 -> 1043 bytes htdocs/images/countries/bb.png | Bin 0 -> 1043 bytes htdocs/images/countries/bd.png | Bin 0 -> 1040 bytes htdocs/images/countries/be.png | Bin 0 -> 1039 bytes htdocs/images/countries/bf.png | Bin 0 -> 1042 bytes htdocs/images/countries/bg.png | Bin 0 -> 1041 bytes htdocs/images/countries/bh.png | Bin 0 -> 1031 bytes htdocs/images/countries/bi.png | Bin 0 -> 1043 bytes htdocs/images/countries/bj.png | Bin 0 -> 1042 bytes htdocs/images/countries/bm.png | Bin 0 -> 1036 bytes htdocs/images/countries/bn.png | Bin 0 -> 1043 bytes htdocs/images/countries/bo.png | Bin 0 -> 1042 bytes htdocs/images/countries/br.png | Bin 0 -> 1043 bytes htdocs/images/countries/bs.png | Bin 0 -> 1042 bytes htdocs/images/countries/bt.png | Bin 0 -> 1043 bytes htdocs/images/countries/bw.png | Bin 0 -> 1032 bytes htdocs/images/countries/by.png | Bin 0 -> 1043 bytes htdocs/images/countries/bz.png | Bin 0 -> 1043 bytes htdocs/images/countries/ca.png | Bin 0 -> 1043 bytes htdocs/images/countries/cf.png | Bin 0 -> 1043 bytes htdocs/images/countries/cg.png | Bin 0 -> 1040 bytes htdocs/images/countries/ch.png | Bin 0 -> 1031 bytes htdocs/images/countries/ci.png | Bin 0 -> 1040 bytes htdocs/images/countries/ck.png | Bin 0 -> 1043 bytes htdocs/images/countries/cl.png | Bin 0 -> 253 bytes htdocs/images/countries/cm.png | Bin 0 -> 1043 bytes htdocs/images/countries/cn.png | Bin 0 -> 624 bytes htdocs/images/countries/co.png | Bin 0 -> 1030 bytes htdocs/images/countries/cr.png | Bin 0 -> 1043 bytes htdocs/images/countries/cu.png | Bin 0 -> 1043 bytes htdocs/images/countries/cv.png | Bin 0 -> 1041 bytes htdocs/images/countries/cy.png | Bin 0 -> 1041 bytes htdocs/images/countries/cz.png | Bin 0 -> 1042 bytes htdocs/images/countries/de.png | Bin 0 -> 1038 bytes htdocs/images/countries/dk.png | Bin 0 -> 1037 bytes htdocs/images/countries/dz.png | Bin 0 -> 1037 bytes htdocs/images/countries/ec.png | Bin 0 -> 1042 bytes htdocs/images/countries/ee.png | Bin 0 -> 1041 bytes htdocs/images/countries/eg.png | Bin 0 -> 1041 bytes htdocs/images/countries/er.png | Bin 0 -> 1043 bytes htdocs/images/countries/es.png | Bin 0 -> 1043 bytes htdocs/images/countries/et.png | Bin 0 -> 1043 bytes htdocs/images/countries/fi.png | Bin 0 -> 1040 bytes htdocs/images/countries/fj.png | Bin 0 -> 1043 bytes htdocs/images/countries/fo.png | Bin 0 -> 1041 bytes htdocs/images/countries/fr.png | Bin 0 -> 1041 bytes htdocs/images/countries/ga.png | Bin 0 -> 1043 bytes htdocs/images/countries/gb.png | Bin 0 -> 1043 bytes htdocs/images/countries/ge.png | Bin 0 -> 628 bytes htdocs/images/countries/gi.png | Bin 0 -> 1039 bytes htdocs/images/countries/gl.png | Bin 0 -> 1038 bytes htdocs/images/countries/gp.png | Bin 0 -> 1030 bytes htdocs/images/countries/gr.png | Bin 0 -> 1043 bytes htdocs/images/countries/gt.png | Bin 0 -> 1043 bytes htdocs/images/countries/gu.png | Bin 0 -> 1043 bytes htdocs/images/countries/gy.png | Bin 0 -> 1041 bytes htdocs/images/countries/hk.png | Bin 0 -> 1041 bytes htdocs/images/countries/hr.png | Bin 0 -> 1041 bytes htdocs/images/countries/ht.png | Bin 0 -> 1043 bytes htdocs/images/countries/hu.png | Bin 0 -> 1042 bytes htdocs/images/countries/id.png | Bin 0 -> 1041 bytes htdocs/images/countries/ie.png | Bin 0 -> 1042 bytes htdocs/images/countries/il.png | Bin 0 -> 1042 bytes htdocs/images/countries/in.png | Bin 0 -> 1043 bytes htdocs/images/countries/iq.png | Bin 0 -> 1042 bytes htdocs/images/countries/ir.png | Bin 0 -> 1043 bytes htdocs/images/countries/is.png | Bin 0 -> 1043 bytes htdocs/images/countries/it.png | Bin 0 -> 1040 bytes htdocs/images/countries/jm.png | Bin 0 -> 1042 bytes htdocs/images/countries/jo.png | Bin 0 -> 1042 bytes htdocs/images/countries/jp.png | Bin 0 -> 648 bytes htdocs/images/countries/ke.png | Bin 0 -> 1039 bytes htdocs/images/countries/kg.png | Bin 0 -> 1041 bytes htdocs/images/countries/kh.png | Bin 0 -> 1043 bytes htdocs/images/countries/ki.png | Bin 0 -> 1042 bytes htdocs/images/countries/kp.png | Bin 0 -> 1043 bytes htdocs/images/countries/kr.png | Bin 0 -> 1040 bytes htdocs/images/countries/ky.png | Bin 0 -> 1041 bytes htdocs/images/countries/kz.png | Bin 0 -> 1042 bytes htdocs/images/countries/lb.png | Bin 0 -> 1042 bytes htdocs/images/countries/lc.png | Bin 0 -> 1043 bytes htdocs/images/countries/lk.png | Bin 0 -> 1043 bytes htdocs/images/countries/lt.png | Bin 0 -> 646 bytes htdocs/images/countries/lu.png | Bin 0 -> 1041 bytes htdocs/images/countries/lv.png | Bin 0 -> 1032 bytes htdocs/images/countries/ly.png | Bin 0 -> 623 bytes htdocs/images/countries/ma.png | Bin 0 -> 1175 bytes htdocs/images/countries/mc.png | Bin 0 -> 1040 bytes htdocs/images/countries/md.png | Bin 0 -> 1041 bytes htdocs/images/countries/mg.png | Bin 0 -> 1041 bytes htdocs/images/countries/mn.png | Bin 0 -> 1043 bytes htdocs/images/countries/mo.png | Bin 0 -> 1041 bytes htdocs/images/countries/mp.png | Bin 0 -> 1042 bytes htdocs/images/countries/ms.png | Bin 0 -> 1043 bytes htdocs/images/countries/mt.png | Bin 0 -> 873 bytes htdocs/images/countries/mx.png | Bin 0 -> 1042 bytes htdocs/images/countries/my.png | Bin 0 -> 1043 bytes htdocs/images/countries/mz.png | Bin 0 -> 1043 bytes htdocs/images/countries/na.png | Bin 0 -> 1043 bytes htdocs/images/countries/nc.png | Bin 0 -> 1043 bytes htdocs/images/countries/nf.png | Bin 0 -> 1041 bytes htdocs/images/countries/nl.png | Bin 0 -> 1041 bytes htdocs/images/countries/no.png | Bin 0 -> 1041 bytes htdocs/images/countries/np.png | Bin 0 -> 730 bytes htdocs/images/countries/nr.png | Bin 0 -> 1038 bytes htdocs/images/countries/nz.png | Bin 0 -> 1042 bytes htdocs/images/countries/om.png | Bin 0 -> 1041 bytes htdocs/images/countries/pa.png | Bin 0 -> 1041 bytes htdocs/images/countries/pe.png | Bin 0 -> 1043 bytes htdocs/images/countries/pf.png | Bin 0 -> 1043 bytes htdocs/images/countries/ph.png | Bin 0 -> 1043 bytes htdocs/images/countries/pk.png | Bin 0 -> 1041 bytes htdocs/images/countries/pl.png | Bin 0 -> 1040 bytes htdocs/images/countries/pm.png | Bin 0 -> 1043 bytes htdocs/images/countries/pr.png | Bin 0 -> 1043 bytes htdocs/images/countries/pt.png | Bin 0 -> 1036 bytes htdocs/images/countries/py.png | Bin 0 -> 1041 bytes htdocs/images/countries/qa.png | Bin 0 -> 647 bytes htdocs/images/countries/ro.png | Bin 0 -> 1042 bytes htdocs/images/countries/ru.png | Bin 0 -> 1041 bytes htdocs/images/countries/sa.png | Bin 0 -> 1042 bytes htdocs/images/countries/sb.png | Bin 0 -> 1043 bytes htdocs/images/countries/sd.png | Bin 0 -> 1041 bytes htdocs/images/countries/se.png | Bin 0 -> 1041 bytes htdocs/images/countries/sg.png | Bin 0 -> 1041 bytes htdocs/images/countries/si.png | Bin 0 -> 1042 bytes htdocs/images/countries/sk.png | Bin 0 -> 1042 bytes htdocs/images/countries/sl.png | Bin 0 -> 1042 bytes htdocs/images/countries/so.png | Bin 0 -> 1033 bytes htdocs/images/countries/sr.png | Bin 0 -> 899 bytes htdocs/images/countries/sy.png | Bin 0 -> 920 bytes htdocs/images/countries/tc.png | Bin 0 -> 1040 bytes htdocs/images/countries/tg.png | Bin 0 -> 1043 bytes htdocs/images/countries/th.png | Bin 0 -> 1043 bytes htdocs/images/countries/tn.png | Bin 0 -> 1041 bytes htdocs/images/countries/to.png | Bin 0 -> 649 bytes htdocs/images/countries/tp.png | Bin 0 -> 1043 bytes htdocs/images/countries/tr.png | Bin 0 -> 1029 bytes htdocs/images/countries/tt.png | Bin 0 -> 1043 bytes htdocs/images/countries/tv.png | Bin 0 -> 1043 bytes htdocs/images/countries/tw.png | Bin 0 -> 633 bytes htdocs/images/countries/tz.png | Bin 0 -> 1040 bytes htdocs/images/countries/ua.png | Bin 0 -> 1041 bytes htdocs/images/countries/ug.png | Bin 0 -> 1043 bytes htdocs/images/countries/us.png | Bin 0 -> 1043 bytes htdocs/images/countries/uy.png | Bin 0 -> 1043 bytes htdocs/images/countries/va.png | Bin 0 -> 1042 bytes htdocs/images/countries/ve.png | Bin 0 -> 1043 bytes htdocs/images/countries/vg.png | Bin 0 -> 1043 bytes htdocs/images/countries/vi.png | Bin 0 -> 1043 bytes htdocs/images/countries/vn.png | Bin 0 -> 1038 bytes htdocs/images/countries/ws.png | Bin 0 -> 1027 bytes htdocs/images/countries/ye.png | Bin 0 -> 1041 bytes htdocs/images/countries/yu.png | Bin 0 -> 1042 bytes htdocs/images/countries/za.png | Bin 0 -> 1043 bytes htdocs/images/countries/zw.png | Bin 0 -> 1043 bytes htdocs/images/default/add.png | Bin 0 -> 528 bytes htdocs/images/default/address-book.png | Bin 0 -> 1302 bytes htdocs/images/default/bug-big.png | Bin 0 -> 928 bytes htdocs/images/default/bug.png | Bin 0 -> 278 bytes htdocs/images/default/calendar.png | Bin 0 -> 478 bytes htdocs/images/default/catalog.png | Bin 0 -> 1302 bytes htdocs/images/default/children.png | Bin 0 -> 342 bytes htdocs/images/default/compare.png | Bin 0 -> 662 bytes htdocs/images/default/country.png | Bin 0 -> 707 bytes htdocs/images/default/create.png | Bin 0 -> 700 bytes htdocs/images/default/cut.png | Bin 0 -> 340 bytes htdocs/images/default/debug-cache.png | Bin 0 -> 661 bytes htdocs/images/default/device.png | Bin 0 -> 500 bytes htdocs/images/default/disabled.png | Bin 0 -> 692 bytes htdocs/images/default/document.png | Bin 0 -> 856 bytes htdocs/images/default/door.png | Bin 0 -> 364 bytes htdocs/images/default/error-big.png | Bin 0 -> 1891 bytes htdocs/images/default/error.png | Bin 0 -> 796 bytes htdocs/images/default/export-big.png | Bin 0 -> 1121 bytes htdocs/images/default/export.png | Bin 0 -> 1121 bytes htdocs/images/default/files.png | Bin 0 -> 1165 bytes htdocs/images/default/find.png | Bin 0 -> 1428 bytes htdocs/images/default/folder.png | Bin 0 -> 1217 bytes htdocs/images/default/forum-big.png | Bin 0 -> 738 bytes htdocs/images/default/hard-drive.png | Bin 0 -> 1308 bytes htdocs/images/default/help-big.png | Bin 0 -> 1615 bytes htdocs/images/default/help.png | Bin 0 -> 738 bytes htdocs/images/default/home-big.png | Bin 0 -> 1084 bytes htdocs/images/default/home.png | Bin 0 -> 1105 bytes htdocs/images/default/host.png | Bin 0 -> 844 bytes htdocs/images/default/import-big.png | Bin 0 -> 1296 bytes htdocs/images/default/index.php | 51 + htdocs/images/default/info-big.png | Bin 0 -> 966 bytes htdocs/images/default/info.png | Bin 0 -> 510 bytes htdocs/images/default/invalid.png | Bin 0 -> 692 bytes htdocs/images/default/key.png | Bin 0 -> 519 bytes htdocs/images/default/ldap-alias.png | Bin 0 -> 440 bytes htdocs/images/default/ldap-dc.png | Bin 0 -> 1140 bytes htdocs/images/default/ldap-default.png | Bin 0 -> 1297 bytes htdocs/images/default/ldap-o.png | Bin 0 -> 1305 bytes htdocs/images/default/ldap-ou.png | Bin 0 -> 1330 bytes htdocs/images/default/ldap-server.png | Bin 0 -> 1084 bytes htdocs/images/default/ldap-uid.png | Bin 0 -> 654 bytes htdocs/images/default/ldap-uniquegroup.png | Bin 0 -> 1356 bytes htdocs/images/default/ldap-user.png | Bin 0 -> 773 bytes htdocs/images/default/light-big.png | Bin 0 -> 1950 bytes htdocs/images/default/light.png | Bin 0 -> 733 bytes htdocs/images/default/locality.png | Bin 0 -> 751 bytes htdocs/images/default/lock.png | Bin 0 -> 1256 bytes htdocs/images/default/login.png | Bin 0 -> 654 bytes htdocs/images/default/logo-small.png | Bin 0 -> 7053 bytes htdocs/images/default/logo.png | Bin 0 -> 42594 bytes htdocs/images/default/logout-big.png | Bin 0 -> 829 bytes htdocs/images/default/mail.png | Bin 0 -> 899 bytes htdocs/images/default/mail_account.png | Bin 0 -> 993 bytes htdocs/images/default/mail_alias.png | Bin 0 -> 938 bytes htdocs/images/default/minus.png | Bin 0 -> 98 bytes htdocs/images/default/monitorserver-big.png | Bin 0 -> 1084 bytes htdocs/images/default/move.png | Bin 0 -> 483 bytes htdocs/images/default/n.png | Bin 0 -> 408 bytes htdocs/images/default/network.png | Bin 0 -> 1107 bytes htdocs/images/default/nogo.png | Bin 0 -> 243 bytes htdocs/images/default/nt_machine.png | Bin 0 -> 1060 bytes htdocs/images/default/nt_user.png | Bin 0 -> 971 bytes htdocs/images/default/paypal-donate.png | Bin 0 -> 730 bytes htdocs/images/default/phone.png | Bin 0 -> 878 bytes htdocs/images/default/photo.png | Bin 0 -> 572 bytes htdocs/images/default/plus.png | Bin 0 -> 102 bytes htdocs/images/default/process.png | Bin 0 -> 438 bytes htdocs/images/default/refresh-big.png | Bin 0 -> 1072 bytes htdocs/images/default/refresh.png | Bin 0 -> 785 bytes htdocs/images/default/rename.png | Bin 0 -> 418 bytes htdocs/images/default/request-feature-big.png | Bin 0 -> 1095 bytes htdocs/images/default/rfc.png | Bin 0 -> 637 bytes htdocs/images/default/save.png | Bin 0 -> 658 bytes htdocs/images/default/schema-big.png | Bin 0 -> 514 bytes htdocs/images/default/search-big.png | Bin 0 -> 1128 bytes htdocs/images/default/server-settings.png | Bin 0 -> 1149 bytes htdocs/images/default/server-small.png | Bin 0 -> 818 bytes htdocs/images/default/server.png | Bin 0 -> 1424 bytes htdocs/images/default/smile-big.png | Bin 0 -> 1332 bytes htdocs/images/default/smile.png | Bin 0 -> 852 bytes htdocs/images/default/switch.png | Bin 0 -> 1302 bytes htdocs/images/default/terminal.png | Bin 0 -> 851 bytes htdocs/images/default/timeout.png | Bin 0 -> 661 bytes htdocs/images/default/tools-no.png | Bin 0 -> 798 bytes htdocs/images/default/tools.png | Bin 0 -> 503 bytes htdocs/images/default/trash-big.png | Bin 0 -> 1282 bytes htdocs/images/default/trash.png | Bin 0 -> 678 bytes htdocs/images/default/tree_collapse.png | Bin 0 -> 196 bytes .../images/default/tree_collapse_corner.png | Bin 0 -> 196 bytes .../default/tree_collapse_corner_first.png | Bin 0 -> 189 bytes htdocs/images/default/tree_collapse_first.png | Bin 0 -> 194 bytes htdocs/images/default/tree_corner.png | Bin 0 -> 160 bytes htdocs/images/default/tree_expand.png | Bin 0 -> 204 bytes htdocs/images/default/tree_expand_corner.png | Bin 0 -> 204 bytes .../default/tree_expand_corner_first.png | Bin 0 -> 197 bytes htdocs/images/default/tree_expand_first.png | Bin 0 -> 202 bytes htdocs/images/default/tree_folder_closed.png | Bin 0 -> 247 bytes htdocs/images/default/tree_folder_open.png | Bin 0 -> 278 bytes htdocs/images/default/tree_leaf.png | Bin 0 -> 207 bytes htdocs/images/default/tree_space.png | Bin 0 -> 150 bytes htdocs/images/default/tree_split.png | Bin 0 -> 160 bytes htdocs/images/default/tree_split_first.png | Bin 0 -> 160 bytes htdocs/images/default/tree_vertline.png | Bin 0 -> 156 bytes htdocs/images/default/unknown.png | Bin 0 -> 924 bytes htdocs/images/default/up.png | Bin 0 -> 382 bytes htdocs/images/default/warn-big.png | Bin 0 -> 2293 bytes htdocs/images/favicon.ico | Bin 0 -> 902 bytes htdocs/images/tango/INFO | 2 + htdocs/images/tango/add-big.png | Bin 0 -> 601 bytes htdocs/images/tango/add.png | Bin 0 -> 323 bytes htdocs/images/tango/address-book.png | Bin 0 -> 796 bytes htdocs/images/tango/bug-big.png | Bin 0 -> 1390 bytes htdocs/images/tango/bug.png | Bin 0 -> 564 bytes htdocs/images/tango/children-big.png | Bin 0 -> 517 bytes htdocs/images/tango/children.png | Bin 0 -> 317 bytes htdocs/images/tango/compare-big.png | Bin 0 -> 1636 bytes htdocs/images/tango/compare.png | Bin 0 -> 617 bytes htdocs/images/tango/create-big.png | Bin 0 -> 1008 bytes htdocs/images/tango/create.png | Bin 0 -> 477 bytes htdocs/images/tango/cut-big.png | Bin 0 -> 2087 bytes htdocs/images/tango/cut.png | Bin 0 -> 807 bytes htdocs/images/tango/disabled-big.png | Bin 0 -> 1927 bytes htdocs/images/tango/disabled.png | Bin 0 -> 820 bytes htdocs/images/tango/error-big.png | Bin 0 -> 1645 bytes htdocs/images/tango/error.png | Bin 0 -> 653 bytes htdocs/images/tango/export-big.png | Bin 0 -> 1338 bytes htdocs/images/tango/export.png | Bin 0 -> 720 bytes htdocs/images/tango/forum-big.png | Bin 0 -> 783 bytes htdocs/images/tango/forum.png | Bin 0 -> 422 bytes htdocs/images/tango/help-big.png | Bin 0 -> 2113 bytes htdocs/images/tango/help.png | Bin 0 -> 873 bytes htdocs/images/tango/import-big.png | Bin 0 -> 1837 bytes htdocs/images/tango/import.png | Bin 0 -> 866 bytes htdocs/images/tango/index.php | 51 + htdocs/images/tango/info-big.png | Bin 0 -> 2231 bytes htdocs/images/tango/info.png | Bin 0 -> 932 bytes htdocs/images/tango/key.png | Bin 0 -> 830 bytes htdocs/images/tango/ldap-alias-big.png | Bin 0 -> 1219 bytes htdocs/images/tango/ldap-alias.png | Bin 0 -> 676 bytes htdocs/images/tango/ldap-dc.png | Bin 0 -> 517 bytes htdocs/images/tango/ldap-default.png | Bin 0 -> 629 bytes htdocs/images/tango/ldap-o.png | Bin 0 -> 928 bytes htdocs/images/tango/ldap-ou.png | Bin 0 -> 911 bytes htdocs/images/tango/ldap-uid.png | Bin 0 -> 628 bytes htdocs/images/tango/ldap-uniquegroup.png | Bin 0 -> 911 bytes htdocs/images/tango/ldap-user.png | Bin 0 -> 757 bytes htdocs/images/tango/light-big.png | Bin 0 -> 1910 bytes htdocs/images/tango/light.png | Bin 0 -> 863 bytes htdocs/images/tango/login-big.png | Bin 0 -> 1390 bytes htdocs/images/tango/login.png | Bin 0 -> 628 bytes htdocs/images/tango/logo-small.png | Bin 0 -> 7053 bytes htdocs/images/tango/logo.png | Bin 0 -> 42594 bytes htdocs/images/tango/logout-big.png | Bin 0 -> 1725 bytes htdocs/images/tango/logout.png | Bin 0 -> 799 bytes htdocs/images/tango/mail-big.png | Bin 0 -> 1492 bytes htdocs/images/tango/mail.png | Bin 0 -> 693 bytes htdocs/images/tango/minus.png | Bin 0 -> 247 bytes htdocs/images/tango/monitorserver-big.png | Bin 0 -> 1886 bytes htdocs/images/tango/monitorserver.png | Bin 0 -> 611 bytes htdocs/images/tango/plus.png | Bin 0 -> 323 bytes htdocs/images/tango/refresh-big.png | Bin 0 -> 2024 bytes htdocs/images/tango/refresh.png | Bin 0 -> 912 bytes htdocs/images/tango/remove-big.png | Bin 0 -> 317 bytes htdocs/images/tango/remove.png | Bin 0 -> 247 bytes htdocs/images/tango/rename-big.png | Bin 0 -> 2223 bytes htdocs/images/tango/rename.png | Bin 0 -> 937 bytes htdocs/images/tango/request-feature-big.png | Bin 0 -> 1686 bytes htdocs/images/tango/request-feature.png | Bin 0 -> 740 bytes htdocs/images/tango/save-big.png | Bin 0 -> 1971 bytes htdocs/images/tango/save.png | Bin 0 -> 911 bytes htdocs/images/tango/schema-big.png | Bin 0 -> 1759 bytes htdocs/images/tango/schema.png | Bin 0 -> 709 bytes htdocs/images/tango/search-big.png | Bin 0 -> 2215 bytes htdocs/images/tango/search.png | Bin 0 -> 935 bytes htdocs/images/tango/server-big.png | Bin 0 -> 847 bytes htdocs/images/tango/server.png | Bin 0 -> 642 bytes htdocs/images/tango/smile-big.png | Bin 0 -> 2566 bytes htdocs/images/tango/smile.png | Bin 0 -> 986 bytes htdocs/images/tango/switch-big.png | Bin 0 -> 1797 bytes htdocs/images/tango/switch.png | Bin 0 -> 592 bytes htdocs/images/tango/timeout-big.png | Bin 0 -> 2399 bytes htdocs/images/tango/timeout.png | Bin 0 -> 897 bytes htdocs/images/tango/tools-big.png | Bin 0 -> 2129 bytes htdocs/images/tango/tools.png | Bin 0 -> 611 bytes htdocs/images/tango/trash-big.png | Bin 0 -> 1788 bytes htdocs/images/tango/trash.png | Bin 0 -> 655 bytes htdocs/images/tango/tree_collapse.png | Bin 0 -> 196 bytes htdocs/images/tango/tree_collapse_corner.png | Bin 0 -> 196 bytes .../tango/tree_collapse_corner_first.png | Bin 0 -> 189 bytes htdocs/images/tango/tree_collapse_first.png | Bin 0 -> 194 bytes htdocs/images/tango/tree_corner.png | Bin 0 -> 160 bytes htdocs/images/tango/tree_expand.png | Bin 0 -> 204 bytes htdocs/images/tango/tree_expand_corner.png | Bin 0 -> 204 bytes .../images/tango/tree_expand_corner_first.png | Bin 0 -> 197 bytes htdocs/images/tango/tree_expand_first.png | Bin 0 -> 202 bytes htdocs/images/tango/tree_folder_closed.png | Bin 0 -> 247 bytes htdocs/images/tango/tree_folder_open.png | Bin 0 -> 278 bytes htdocs/images/tango/tree_leaf.png | Bin 0 -> 207 bytes htdocs/images/tango/tree_space.png | Bin 0 -> 150 bytes htdocs/images/tango/tree_split.png | Bin 0 -> 160 bytes htdocs/images/tango/tree_split_first.png | Bin 0 -> 160 bytes htdocs/images/tango/tree_vertline.png | Bin 0 -> 156 bytes htdocs/images/tango/warn-big.png | Bin 0 -> 1391 bytes htdocs/images/tango/warn.png | Bin 0 -> 603 bytes htdocs/import.php | 111 + htdocs/import_form.php | 48 + htdocs/index.php | 148 + htdocs/js/CheckAll.js | 22 + htdocs/js/TemplateRender.js | 84 + htdocs/js/ajax_functions.js | 253 + htdocs/js/ajax_tree.js | 170 + htdocs/js/date_selector.js | 75 + htdocs/js/dnChooserPopup.js | 6 + htdocs/js/form_field_toggle_enable.js | 51 + htdocs/js/jscalendar/README | 33 + htdocs/js/jscalendar/calendar-blue.css | 232 + htdocs/js/jscalendar/calendar-setup.js | 200 + htdocs/js/jscalendar/calendar.js | 1806 +++++++ htdocs/js/jscalendar/lang/calendar-af.js | 39 + htdocs/js/jscalendar/lang/calendar-al.js | 101 + htdocs/js/jscalendar/lang/calendar-bg.js | 124 + .../js/jscalendar/lang/calendar-big5-utf8.js | 123 + htdocs/js/jscalendar/lang/calendar-big5.js | 123 + htdocs/js/jscalendar/lang/calendar-br.js | 108 + htdocs/js/jscalendar/lang/calendar-ca.js | 123 + htdocs/js/jscalendar/lang/calendar-cs-utf8.js | 65 + htdocs/js/jscalendar/lang/calendar-cs-win.js | 65 + htdocs/js/jscalendar/lang/calendar-da.js | 123 + htdocs/js/jscalendar/lang/calendar-de.js | 124 + htdocs/js/jscalendar/lang/calendar-du.js | 45 + htdocs/js/jscalendar/lang/calendar-el.js | 89 + htdocs/js/jscalendar/lang/calendar-en.js | 127 + htdocs/js/jscalendar/lang/calendar-es.js | 129 + htdocs/js/jscalendar/lang/calendar-fi.js | 98 + htdocs/js/jscalendar/lang/calendar-fr.js | 125 + htdocs/js/jscalendar/lang/calendar-he-utf8.js | 123 + htdocs/js/jscalendar/lang/calendar-hr-utf8.js | 49 + htdocs/js/jscalendar/lang/calendar-hr.js | Bin 0 -> 3088 bytes htdocs/js/jscalendar/lang/calendar-hu.js | 124 + htdocs/js/jscalendar/lang/calendar-it.js | 124 + htdocs/js/jscalendar/lang/calendar-jp.js | 45 + htdocs/js/jscalendar/lang/calendar-ko-utf8.js | 120 + htdocs/js/jscalendar/lang/calendar-ko.js | 120 + htdocs/js/jscalendar/lang/calendar-lt-utf8.js | 114 + htdocs/js/jscalendar/lang/calendar-lt.js | 114 + htdocs/js/jscalendar/lang/calendar-lv.js | 123 + htdocs/js/jscalendar/lang/calendar-nl.js | 73 + htdocs/js/jscalendar/lang/calendar-no.js | 114 + htdocs/js/jscalendar/lang/calendar-pl-utf8.js | 93 + htdocs/js/jscalendar/lang/calendar-pl.js | 56 + htdocs/js/jscalendar/lang/calendar-pt.js | 123 + htdocs/js/jscalendar/lang/calendar-ro.js | 66 + htdocs/js/jscalendar/lang/calendar-ru.js | 123 + htdocs/js/jscalendar/lang/calendar-ru_win_.js | 123 + htdocs/js/jscalendar/lang/calendar-si.js | 94 + htdocs/js/jscalendar/lang/calendar-sk.js | 99 + htdocs/js/jscalendar/lang/calendar-sp.js | 110 + htdocs/js/jscalendar/lang/calendar-sv.js | 93 + htdocs/js/jscalendar/lang/calendar-tr.js | 58 + htdocs/js/jscalendar/lang/calendar-zh.js | 119 + htdocs/js/jscalendar/lang/cn_utf8.js | 123 + htdocs/js/jscalendar/menuarrow.gif | Bin 0 -> 68 bytes htdocs/js/jscalendar/skins/aqua/active-bg.gif | Bin 0 -> 89 bytes htdocs/js/jscalendar/skins/aqua/dark-bg.gif | Bin 0 -> 85 bytes htdocs/js/jscalendar/skins/aqua/hover-bg.gif | Bin 0 -> 89 bytes htdocs/js/jscalendar/skins/aqua/menuarrow.gif | Bin 0 -> 49 bytes htdocs/js/jscalendar/skins/aqua/normal-bg.gif | Bin 0 -> 110 bytes .../js/jscalendar/skins/aqua/rowhover-bg.gif | Bin 0 -> 110 bytes htdocs/js/jscalendar/skins/aqua/status-bg.gif | Bin 0 -> 116 bytes htdocs/js/jscalendar/skins/aqua/theme.css | 236 + htdocs/js/jscalendar/skins/aqua/title-bg.gif | Bin 0 -> 116 bytes htdocs/js/jscalendar/skins/aqua/today-bg.gif | Bin 0 -> 1122 bytes htdocs/js/layersmenu-browser_detection.js | 46 + htdocs/js/modify_member.js | 89 + htdocs/js/toAscii.js | 80 + htdocs/login.php | 37 + htdocs/login_form.php | 98 + htdocs/logout.php | 29 + htdocs/mass_delete.php | 147 + htdocs/mass_edit.php | 133 + htdocs/mass_update.php | 175 + htdocs/modify_member_form.php | 178 + htdocs/monitor.php | 259 + htdocs/password_checker.php | 88 + htdocs/purge_cache.php | 33 + htdocs/query_engine.php | 19 + htdocs/rdelete.php | 89 + htdocs/refresh.php | 46 + htdocs/rename.php | 64 + htdocs/rename_form.php | 40 + htdocs/schema.php | 640 +++ htdocs/server_info.php | 89 + htdocs/show_cache.php | 101 + htdocs/template_engine.php | 57 + htdocs/update.php | 78 + htdocs/update_confirm.php | 253 + htdocs/view_jpeg_photo.php | 77 + htdocs/welcome.php | 29 + index.php | 11 + lib/AJAXTree.php | 307 ++ lib/Attribute.php | 917 ++++ lib/AttributeFactory.php | 188 + lib/BinaryAttribute.php | 60 + lib/DateAttribute.php | 17 + lib/DnAttribute.php | 17 + lib/GidAttribute.php | 17 + lib/HTMLTree.php | 587 +++ lib/JpegAttribute.php | 17 + lib/MassRender.php | 48 + lib/MultiLineAttribute.php | 35 + lib/ObjectClassAttribute.php | 17 + lib/PageRender.php | 1244 +++++ lib/PasswordAttribute.php | 17 + lib/Query.php | 283 + lib/QueryRender.php | 557 ++ lib/RandomPasswordAttribute.php | 17 + lib/SambaPasswordAttribute.php | 17 + lib/SelectionAttribute.php | 71 + lib/ShadowAttribute.php | 19 + lib/Template.php | 1571 ++++++ lib/TemplateRender.php | 2533 +++++++++ lib/Tree.php | 351 ++ lib/TreeItem.php | 312 ++ lib/Visitor.php | 99 + lib/blowfish.php | 480 ++ lib/common.php | 335 ++ lib/config_default.php | 808 +++ lib/createlm.php | 381 ++ lib/ds.php | 731 +++ lib/ds_ldap.php | 2413 +++++++++ lib/ds_ldap_pla.php | 659 +++ lib/emuhash_functions.php | 112 + lib/export_functions.php | 643 +++ lib/functions.php | 3209 ++++++++++++ lib/hooks.php | 201 + lib/import_functions.php | 609 +++ lib/ldap_error_codes.txt | 94 + lib/ldap_supported_oids.txt | 187 + lib/page.php | 519 ++ lib/query_functions.php | 22 + lib/schema_functions.php | 1539 ++++++ lib/session_functions.php | 176 + lib/syslog.php | 88 + lib/template_functions.php | 23 + lib/xml2array.php | 144 + lib/xmlTemplates.php | 496 ++ locale/ca_ES/LC_MESSAGES/messages.mo | Bin 0 -> 9706 bytes locale/cs_CZ/LC_MESSAGES/messages.mo | Bin 0 -> 21326 bytes locale/da_DK/LC_MESSAGES/messages.mo | Bin 0 -> 26102 bytes locale/de_DE/LC_MESSAGES/messages.mo | Bin 0 -> 38343 bytes locale/es_ES/LC_MESSAGES/messages.mo | Bin 0 -> 64477 bytes locale/fi_FI/LC_MESSAGES/messages.mo | Bin 0 -> 62050 bytes locale/fr_FR/LC_MESSAGES/messages.mo | Bin 0 -> 43010 bytes locale/gn_PY/LC_MESSAGES/messages.mo | Bin 0 -> 472 bytes locale/hu_HU/LC_MESSAGES/messages.mo | Bin 0 -> 22125 bytes locale/it_IT/LC_MESSAGES/messages.mo | Bin 0 -> 54867 bytes locale/ja_JP/LC_MESSAGES/messages.mo | Bin 0 -> 45111 bytes locale/nb_NO/LC_MESSAGES/messages.mo | Bin 0 -> 44164 bytes locale/nl_BE/LC_MESSAGES/messages.mo | Bin 0 -> 9021 bytes locale/oc_FR/LC_MESSAGES/messages.mo | Bin 0 -> 3562 bytes locale/pl_PL/LC_MESSAGES/messages.mo | Bin 0 -> 64280 bytes locale/pt_BR/LC_MESSAGES/messages.mo | Bin 0 -> 62930 bytes locale/ru_RU/LC_MESSAGES/messages.mo | Bin 0 -> 56058 bytes locale/sk_SK/LC_MESSAGES/messages.mo | Bin 0 -> 9031 bytes locale/sv_FI/LC_MESSAGES/messages.mo | Bin 0 -> 9337 bytes locale/tr_TR/LC_MESSAGES/messages.mo | Bin 0 -> 63764 bytes locale/uk_UA/LC_MESSAGES/messages.mo | Bin 0 -> 12624 bytes locale/zh_CN/LC_MESSAGES/messages.mo | Bin 0 -> 21304 bytes locale/zh_TW/LC_MESSAGES/messages.mo | Bin 0 -> 14356 bytes queries/SambaUsers.xml | 32 + queries/UserList.xml | 42 + queries/query.dtd | 35 + templates/creation/alias.xml | 32 + templates/creation/courierMailAccount.xml | 91 + templates/creation/courierMailAlias.xml | 42 + templates/creation/dNSDomain.xml | 32 + templates/creation/example.xml | 38 + templates/creation/inetOrgPerson.xml | 96 + templates/creation/kolabPerson.xml | 109 + templates/creation/mozillaOrgPerson.xml | 161 + templates/creation/organizationalRole.xml | 77 + templates/creation/ou.xml | 27 + templates/creation/posixAccount.xml | 95 + templates/creation/posixGroup.xml | 42 + templates/creation/sambaDomain.xml | 33 + templates/creation/sambaGroupMapping.xml | 70 + templates/creation/sambaMachine.xml | 67 + templates/creation/sambaSamAccount.xml | 133 + templates/creation/sendmailMTAAliasObject.xml | 48 + templates/creation/sendmailMTAClass.xml | 42 + templates/creation/sendmailMTACluster.xml | 26 + templates/creation/sendmailMTAMapObject.xml | 53 + templates/creation/sendmailVirtualDomain.xml | 42 + templates/creation/sendmailVirtualUser.xml | 54 + templates/creation/simpleSecurityObject.xml | 37 + templates/modification/inetOrgPerson.xml | 85 + templates/modification/posixGroup.xml | 43 + templates/template.dtd | 71 + tools/po/Makefile | 65 + tools/po/messages.header | 15 + tools/unserialize.php | 26 + 615 files changed, 47872 insertions(+) create mode 100644 .gitignore create mode 100644 INSTALL create mode 100644 LICENSE create mode 100644 VERSION create mode 100644 config/config.php.example create mode 100644 doc/README-translation.txt create mode 100644 doc/certs/ca-bundle.crt create mode 100644 doc/certs/slapd.crt create mode 100644 doc/certs/slapd.key create mode 100644 doc/demo-reset.sh create mode 100644 doc/ldif-Flintstones create mode 100644 doc/ldif-Simpsons create mode 100644 doc/ldif-example-com create mode 100644 doc/ldif-example.com create mode 100644 doc/phpldapadmin-demo.conf create mode 100644 doc/pla-test-i18n.ldif create mode 100644 doc/uidpool.schema create mode 100644 hooks/classes/README create mode 100644 hooks/functions/README create mode 100644 hooks/functions/example.php create mode 100644 htdocs/add_attr_form.php create mode 100644 htdocs/add_oclass_form.php create mode 100644 htdocs/add_value_form.php create mode 100644 htdocs/cmd.php create mode 100644 htdocs/collapse.php create mode 100644 htdocs/common.php create mode 100644 htdocs/compare.php create mode 100644 htdocs/compare_form.php create mode 100644 htdocs/copy.php create mode 100644 htdocs/copy_form.php create mode 100644 htdocs/create.php create mode 100644 htdocs/create_confirm.php create mode 100644 htdocs/css/default/style.css create mode 100644 htdocs/css/tango/style.css create mode 100644 htdocs/delete.php create mode 100644 htdocs/delete_attr.php create mode 100644 htdocs/delete_form.php create mode 100644 htdocs/download_binary_attr.php create mode 100644 htdocs/draw_tree_node.php create mode 100644 htdocs/entry_chooser.php create mode 100644 htdocs/expand.php create mode 100644 htdocs/export.php create mode 100644 htdocs/export_form.php create mode 100644 htdocs/images/INFO create mode 100644 htdocs/images/ajax-progress.gif create mode 100644 htdocs/images/ajax-spinner.gif create mode 100644 htdocs/images/countries/af.png create mode 100644 htdocs/images/countries/al.png create mode 100644 htdocs/images/countries/am.png create mode 100644 htdocs/images/countries/an.png create mode 100644 htdocs/images/countries/ao.png create mode 100644 htdocs/images/countries/ar.png create mode 100644 htdocs/images/countries/at.png create mode 100644 htdocs/images/countries/au.png create mode 100644 htdocs/images/countries/aw.png create mode 100644 htdocs/images/countries/az.png create mode 100644 htdocs/images/countries/ba.png create mode 100644 htdocs/images/countries/bb.png create mode 100644 htdocs/images/countries/bd.png create mode 100644 htdocs/images/countries/be.png create mode 100644 htdocs/images/countries/bf.png create mode 100644 htdocs/images/countries/bg.png create mode 100644 htdocs/images/countries/bh.png create mode 100644 htdocs/images/countries/bi.png create mode 100644 htdocs/images/countries/bj.png create mode 100644 htdocs/images/countries/bm.png create mode 100644 htdocs/images/countries/bn.png create mode 100644 htdocs/images/countries/bo.png create mode 100644 htdocs/images/countries/br.png create mode 100644 htdocs/images/countries/bs.png create mode 100644 htdocs/images/countries/bt.png create mode 100644 htdocs/images/countries/bw.png create mode 100644 htdocs/images/countries/by.png create mode 100644 htdocs/images/countries/bz.png create mode 100644 htdocs/images/countries/ca.png create mode 100644 htdocs/images/countries/cf.png create mode 100644 htdocs/images/countries/cg.png create mode 100644 htdocs/images/countries/ch.png create mode 100644 htdocs/images/countries/ci.png create mode 100644 htdocs/images/countries/ck.png create mode 100644 htdocs/images/countries/cl.png create mode 100644 htdocs/images/countries/cm.png create mode 100644 htdocs/images/countries/cn.png create mode 100644 htdocs/images/countries/co.png create mode 100644 htdocs/images/countries/cr.png create mode 100644 htdocs/images/countries/cu.png create mode 100644 htdocs/images/countries/cv.png create mode 100644 htdocs/images/countries/cy.png create mode 100644 htdocs/images/countries/cz.png create mode 100644 htdocs/images/countries/de.png create mode 100644 htdocs/images/countries/dk.png create mode 100644 htdocs/images/countries/dz.png create mode 100644 htdocs/images/countries/ec.png create mode 100644 htdocs/images/countries/ee.png create mode 100644 htdocs/images/countries/eg.png create mode 100644 htdocs/images/countries/er.png create mode 100644 htdocs/images/countries/es.png create mode 100644 htdocs/images/countries/et.png create mode 100644 htdocs/images/countries/fi.png create mode 100644 htdocs/images/countries/fj.png create mode 100644 htdocs/images/countries/fo.png create mode 100644 htdocs/images/countries/fr.png create mode 100644 htdocs/images/countries/ga.png create mode 100644 htdocs/images/countries/gb.png create mode 100644 htdocs/images/countries/ge.png create mode 100644 htdocs/images/countries/gi.png create mode 100644 htdocs/images/countries/gl.png create mode 100644 htdocs/images/countries/gp.png create mode 100644 htdocs/images/countries/gr.png create mode 100644 htdocs/images/countries/gt.png create mode 100644 htdocs/images/countries/gu.png create mode 100644 htdocs/images/countries/gy.png create mode 100644 htdocs/images/countries/hk.png create mode 100644 htdocs/images/countries/hr.png create mode 100644 htdocs/images/countries/ht.png create mode 100644 htdocs/images/countries/hu.png create mode 100644 htdocs/images/countries/id.png create mode 100644 htdocs/images/countries/ie.png create mode 100644 htdocs/images/countries/il.png create mode 100644 htdocs/images/countries/in.png create mode 100644 htdocs/images/countries/iq.png create mode 100644 htdocs/images/countries/ir.png create mode 100644 htdocs/images/countries/is.png create mode 100644 htdocs/images/countries/it.png create mode 100644 htdocs/images/countries/jm.png create mode 100644 htdocs/images/countries/jo.png create mode 100644 htdocs/images/countries/jp.png create mode 100644 htdocs/images/countries/ke.png create mode 100644 htdocs/images/countries/kg.png create mode 100644 htdocs/images/countries/kh.png create mode 100644 htdocs/images/countries/ki.png create mode 100644 htdocs/images/countries/kp.png create mode 100644 htdocs/images/countries/kr.png create mode 100644 htdocs/images/countries/ky.png create mode 100644 htdocs/images/countries/kz.png create mode 100644 htdocs/images/countries/lb.png create mode 100644 htdocs/images/countries/lc.png create mode 100644 htdocs/images/countries/lk.png create mode 100644 htdocs/images/countries/lt.png create mode 100644 htdocs/images/countries/lu.png create mode 100644 htdocs/images/countries/lv.png create mode 100644 htdocs/images/countries/ly.png create mode 100644 htdocs/images/countries/ma.png create mode 100644 htdocs/images/countries/mc.png create mode 100644 htdocs/images/countries/md.png create mode 100644 htdocs/images/countries/mg.png create mode 100644 htdocs/images/countries/mn.png create mode 100644 htdocs/images/countries/mo.png create mode 100644 htdocs/images/countries/mp.png create mode 100644 htdocs/images/countries/ms.png create mode 100644 htdocs/images/countries/mt.png create mode 100644 htdocs/images/countries/mx.png create mode 100644 htdocs/images/countries/my.png create mode 100644 htdocs/images/countries/mz.png create mode 100644 htdocs/images/countries/na.png create mode 100644 htdocs/images/countries/nc.png create mode 100644 htdocs/images/countries/nf.png create mode 100644 htdocs/images/countries/nl.png create mode 100644 htdocs/images/countries/no.png create mode 100644 htdocs/images/countries/np.png create mode 100644 htdocs/images/countries/nr.png create mode 100644 htdocs/images/countries/nz.png create mode 100644 htdocs/images/countries/om.png create mode 100644 htdocs/images/countries/pa.png create mode 100644 htdocs/images/countries/pe.png create mode 100644 htdocs/images/countries/pf.png create mode 100644 htdocs/images/countries/ph.png create mode 100644 htdocs/images/countries/pk.png create mode 100644 htdocs/images/countries/pl.png create mode 100644 htdocs/images/countries/pm.png create mode 100644 htdocs/images/countries/pr.png create mode 100644 htdocs/images/countries/pt.png create mode 100644 htdocs/images/countries/py.png create mode 100644 htdocs/images/countries/qa.png create mode 100644 htdocs/images/countries/ro.png create mode 100644 htdocs/images/countries/ru.png create mode 100644 htdocs/images/countries/sa.png create mode 100644 htdocs/images/countries/sb.png create mode 100644 htdocs/images/countries/sd.png create mode 100644 htdocs/images/countries/se.png create mode 100644 htdocs/images/countries/sg.png create mode 100644 htdocs/images/countries/si.png create mode 100644 htdocs/images/countries/sk.png create mode 100644 htdocs/images/countries/sl.png create mode 100644 htdocs/images/countries/so.png create mode 100644 htdocs/images/countries/sr.png create mode 100644 htdocs/images/countries/sy.png create mode 100644 htdocs/images/countries/tc.png create mode 100644 htdocs/images/countries/tg.png create mode 100644 htdocs/images/countries/th.png create mode 100644 htdocs/images/countries/tn.png create mode 100644 htdocs/images/countries/to.png create mode 100644 htdocs/images/countries/tp.png create mode 100644 htdocs/images/countries/tr.png create mode 100644 htdocs/images/countries/tt.png create mode 100644 htdocs/images/countries/tv.png create mode 100644 htdocs/images/countries/tw.png create mode 100644 htdocs/images/countries/tz.png create mode 100644 htdocs/images/countries/ua.png create mode 100644 htdocs/images/countries/ug.png create mode 100644 htdocs/images/countries/us.png create mode 100644 htdocs/images/countries/uy.png create mode 100644 htdocs/images/countries/va.png create mode 100644 htdocs/images/countries/ve.png create mode 100644 htdocs/images/countries/vg.png create mode 100644 htdocs/images/countries/vi.png create mode 100644 htdocs/images/countries/vn.png create mode 100644 htdocs/images/countries/ws.png create mode 100644 htdocs/images/countries/ye.png create mode 100644 htdocs/images/countries/yu.png create mode 100644 htdocs/images/countries/za.png create mode 100644 htdocs/images/countries/zw.png create mode 100644 htdocs/images/default/add.png create mode 100644 htdocs/images/default/address-book.png create mode 100644 htdocs/images/default/bug-big.png create mode 100644 htdocs/images/default/bug.png create mode 100644 htdocs/images/default/calendar.png create mode 100644 htdocs/images/default/catalog.png create mode 100644 htdocs/images/default/children.png create mode 100644 htdocs/images/default/compare.png create mode 100644 htdocs/images/default/country.png create mode 100644 htdocs/images/default/create.png create mode 100644 htdocs/images/default/cut.png create mode 100644 htdocs/images/default/debug-cache.png create mode 100644 htdocs/images/default/device.png create mode 100644 htdocs/images/default/disabled.png create mode 100644 htdocs/images/default/document.png create mode 100644 htdocs/images/default/door.png create mode 100644 htdocs/images/default/error-big.png create mode 100644 htdocs/images/default/error.png create mode 100644 htdocs/images/default/export-big.png create mode 100644 htdocs/images/default/export.png create mode 100644 htdocs/images/default/files.png create mode 100644 htdocs/images/default/find.png create mode 100644 htdocs/images/default/folder.png create mode 100644 htdocs/images/default/forum-big.png create mode 100644 htdocs/images/default/hard-drive.png create mode 100644 htdocs/images/default/help-big.png create mode 100644 htdocs/images/default/help.png create mode 100644 htdocs/images/default/home-big.png create mode 100644 htdocs/images/default/home.png create mode 100644 htdocs/images/default/host.png create mode 100644 htdocs/images/default/import-big.png create mode 100644 htdocs/images/default/index.php create mode 100644 htdocs/images/default/info-big.png create mode 100644 htdocs/images/default/info.png create mode 100644 htdocs/images/default/invalid.png create mode 100644 htdocs/images/default/key.png create mode 100644 htdocs/images/default/ldap-alias.png create mode 100644 htdocs/images/default/ldap-dc.png create mode 100644 htdocs/images/default/ldap-default.png create mode 100644 htdocs/images/default/ldap-o.png create mode 100644 htdocs/images/default/ldap-ou.png create mode 100644 htdocs/images/default/ldap-server.png create mode 100644 htdocs/images/default/ldap-uid.png create mode 100644 htdocs/images/default/ldap-uniquegroup.png create mode 100644 htdocs/images/default/ldap-user.png create mode 100644 htdocs/images/default/light-big.png create mode 100644 htdocs/images/default/light.png create mode 100644 htdocs/images/default/locality.png create mode 100644 htdocs/images/default/lock.png create mode 100644 htdocs/images/default/login.png create mode 100644 htdocs/images/default/logo-small.png create mode 100644 htdocs/images/default/logo.png create mode 100644 htdocs/images/default/logout-big.png create mode 100644 htdocs/images/default/mail.png create mode 100644 htdocs/images/default/mail_account.png create mode 100644 htdocs/images/default/mail_alias.png create mode 100644 htdocs/images/default/minus.png create mode 100644 htdocs/images/default/monitorserver-big.png create mode 100644 htdocs/images/default/move.png create mode 100644 htdocs/images/default/n.png create mode 100644 htdocs/images/default/network.png create mode 100644 htdocs/images/default/nogo.png create mode 100644 htdocs/images/default/nt_machine.png create mode 100644 htdocs/images/default/nt_user.png create mode 100644 htdocs/images/default/paypal-donate.png create mode 100644 htdocs/images/default/phone.png create mode 100644 htdocs/images/default/photo.png create mode 100644 htdocs/images/default/plus.png create mode 100644 htdocs/images/default/process.png create mode 100644 htdocs/images/default/refresh-big.png create mode 100644 htdocs/images/default/refresh.png create mode 100644 htdocs/images/default/rename.png create mode 100644 htdocs/images/default/request-feature-big.png create mode 100644 htdocs/images/default/rfc.png create mode 100644 htdocs/images/default/save.png create mode 100644 htdocs/images/default/schema-big.png create mode 100644 htdocs/images/default/search-big.png create mode 100644 htdocs/images/default/server-settings.png create mode 100644 htdocs/images/default/server-small.png create mode 100644 htdocs/images/default/server.png create mode 100644 htdocs/images/default/smile-big.png create mode 100644 htdocs/images/default/smile.png create mode 100644 htdocs/images/default/switch.png create mode 100644 htdocs/images/default/terminal.png create mode 100644 htdocs/images/default/timeout.png create mode 100644 htdocs/images/default/tools-no.png create mode 100644 htdocs/images/default/tools.png create mode 100644 htdocs/images/default/trash-big.png create mode 100644 htdocs/images/default/trash.png create mode 100644 htdocs/images/default/tree_collapse.png create mode 100644 htdocs/images/default/tree_collapse_corner.png create mode 100644 htdocs/images/default/tree_collapse_corner_first.png create mode 100644 htdocs/images/default/tree_collapse_first.png create mode 100644 htdocs/images/default/tree_corner.png create mode 100644 htdocs/images/default/tree_expand.png create mode 100644 htdocs/images/default/tree_expand_corner.png create mode 100644 htdocs/images/default/tree_expand_corner_first.png create mode 100644 htdocs/images/default/tree_expand_first.png create mode 100644 htdocs/images/default/tree_folder_closed.png create mode 100644 htdocs/images/default/tree_folder_open.png create mode 100644 htdocs/images/default/tree_leaf.png create mode 100644 htdocs/images/default/tree_space.png create mode 100644 htdocs/images/default/tree_split.png create mode 100644 htdocs/images/default/tree_split_first.png create mode 100644 htdocs/images/default/tree_vertline.png create mode 100644 htdocs/images/default/unknown.png create mode 100644 htdocs/images/default/up.png create mode 100644 htdocs/images/default/warn-big.png create mode 100644 htdocs/images/favicon.ico create mode 100644 htdocs/images/tango/INFO create mode 100644 htdocs/images/tango/add-big.png create mode 100644 htdocs/images/tango/add.png create mode 100644 htdocs/images/tango/address-book.png create mode 100644 htdocs/images/tango/bug-big.png create mode 100644 htdocs/images/tango/bug.png create mode 100644 htdocs/images/tango/children-big.png create mode 100644 htdocs/images/tango/children.png create mode 100644 htdocs/images/tango/compare-big.png create mode 100644 htdocs/images/tango/compare.png create mode 100644 htdocs/images/tango/create-big.png create mode 100644 htdocs/images/tango/create.png create mode 100644 htdocs/images/tango/cut-big.png create mode 100644 htdocs/images/tango/cut.png create mode 100644 htdocs/images/tango/disabled-big.png create mode 100644 htdocs/images/tango/disabled.png create mode 100644 htdocs/images/tango/error-big.png create mode 100644 htdocs/images/tango/error.png create mode 100644 htdocs/images/tango/export-big.png create mode 100644 htdocs/images/tango/export.png create mode 100644 htdocs/images/tango/forum-big.png create mode 100644 htdocs/images/tango/forum.png create mode 100644 htdocs/images/tango/help-big.png create mode 100644 htdocs/images/tango/help.png create mode 100644 htdocs/images/tango/import-big.png create mode 100644 htdocs/images/tango/import.png create mode 100644 htdocs/images/tango/index.php create mode 100644 htdocs/images/tango/info-big.png create mode 100644 htdocs/images/tango/info.png create mode 100644 htdocs/images/tango/key.png create mode 100644 htdocs/images/tango/ldap-alias-big.png create mode 100644 htdocs/images/tango/ldap-alias.png create mode 100644 htdocs/images/tango/ldap-dc.png create mode 100644 htdocs/images/tango/ldap-default.png create mode 100644 htdocs/images/tango/ldap-o.png create mode 100644 htdocs/images/tango/ldap-ou.png create mode 100644 htdocs/images/tango/ldap-uid.png create mode 100644 htdocs/images/tango/ldap-uniquegroup.png create mode 100644 htdocs/images/tango/ldap-user.png create mode 100644 htdocs/images/tango/light-big.png create mode 100644 htdocs/images/tango/light.png create mode 100644 htdocs/images/tango/login-big.png create mode 100644 htdocs/images/tango/login.png create mode 100644 htdocs/images/tango/logo-small.png create mode 100644 htdocs/images/tango/logo.png create mode 100644 htdocs/images/tango/logout-big.png create mode 100644 htdocs/images/tango/logout.png create mode 100644 htdocs/images/tango/mail-big.png create mode 100644 htdocs/images/tango/mail.png create mode 100644 htdocs/images/tango/minus.png create mode 100644 htdocs/images/tango/monitorserver-big.png create mode 100644 htdocs/images/tango/monitorserver.png create mode 100644 htdocs/images/tango/plus.png create mode 100644 htdocs/images/tango/refresh-big.png create mode 100644 htdocs/images/tango/refresh.png create mode 100644 htdocs/images/tango/remove-big.png create mode 100644 htdocs/images/tango/remove.png create mode 100644 htdocs/images/tango/rename-big.png create mode 100644 htdocs/images/tango/rename.png create mode 100644 htdocs/images/tango/request-feature-big.png create mode 100644 htdocs/images/tango/request-feature.png create mode 100644 htdocs/images/tango/save-big.png create mode 100644 htdocs/images/tango/save.png create mode 100644 htdocs/images/tango/schema-big.png create mode 100644 htdocs/images/tango/schema.png create mode 100644 htdocs/images/tango/search-big.png create mode 100644 htdocs/images/tango/search.png create mode 100644 htdocs/images/tango/server-big.png create mode 100644 htdocs/images/tango/server.png create mode 100644 htdocs/images/tango/smile-big.png create mode 100644 htdocs/images/tango/smile.png create mode 100644 htdocs/images/tango/switch-big.png create mode 100644 htdocs/images/tango/switch.png create mode 100644 htdocs/images/tango/timeout-big.png create mode 100644 htdocs/images/tango/timeout.png create mode 100644 htdocs/images/tango/tools-big.png create mode 100644 htdocs/images/tango/tools.png create mode 100644 htdocs/images/tango/trash-big.png create mode 100644 htdocs/images/tango/trash.png create mode 100644 htdocs/images/tango/tree_collapse.png create mode 100644 htdocs/images/tango/tree_collapse_corner.png create mode 100644 htdocs/images/tango/tree_collapse_corner_first.png create mode 100644 htdocs/images/tango/tree_collapse_first.png create mode 100644 htdocs/images/tango/tree_corner.png create mode 100644 htdocs/images/tango/tree_expand.png create mode 100644 htdocs/images/tango/tree_expand_corner.png create mode 100644 htdocs/images/tango/tree_expand_corner_first.png create mode 100644 htdocs/images/tango/tree_expand_first.png create mode 100644 htdocs/images/tango/tree_folder_closed.png create mode 100644 htdocs/images/tango/tree_folder_open.png create mode 100644 htdocs/images/tango/tree_leaf.png create mode 100644 htdocs/images/tango/tree_space.png create mode 100644 htdocs/images/tango/tree_split.png create mode 100644 htdocs/images/tango/tree_split_first.png create mode 100644 htdocs/images/tango/tree_vertline.png create mode 100644 htdocs/images/tango/warn-big.png create mode 100644 htdocs/images/tango/warn.png create mode 100644 htdocs/import.php create mode 100644 htdocs/import_form.php create mode 100644 htdocs/index.php create mode 100644 htdocs/js/CheckAll.js create mode 100644 htdocs/js/TemplateRender.js create mode 100644 htdocs/js/ajax_functions.js create mode 100644 htdocs/js/ajax_tree.js create mode 100644 htdocs/js/date_selector.js create mode 100644 htdocs/js/dnChooserPopup.js create mode 100644 htdocs/js/form_field_toggle_enable.js create mode 100644 htdocs/js/jscalendar/README create mode 100644 htdocs/js/jscalendar/calendar-blue.css create mode 100644 htdocs/js/jscalendar/calendar-setup.js create mode 100644 htdocs/js/jscalendar/calendar.js create mode 100644 htdocs/js/jscalendar/lang/calendar-af.js create mode 100644 htdocs/js/jscalendar/lang/calendar-al.js create mode 100644 htdocs/js/jscalendar/lang/calendar-bg.js create mode 100644 htdocs/js/jscalendar/lang/calendar-big5-utf8.js create mode 100644 htdocs/js/jscalendar/lang/calendar-big5.js create mode 100644 htdocs/js/jscalendar/lang/calendar-br.js create mode 100644 htdocs/js/jscalendar/lang/calendar-ca.js create mode 100644 htdocs/js/jscalendar/lang/calendar-cs-utf8.js create mode 100644 htdocs/js/jscalendar/lang/calendar-cs-win.js create mode 100644 htdocs/js/jscalendar/lang/calendar-da.js create mode 100644 htdocs/js/jscalendar/lang/calendar-de.js create mode 100644 htdocs/js/jscalendar/lang/calendar-du.js create mode 100644 htdocs/js/jscalendar/lang/calendar-el.js create mode 100644 htdocs/js/jscalendar/lang/calendar-en.js create mode 100644 htdocs/js/jscalendar/lang/calendar-es.js create mode 100644 htdocs/js/jscalendar/lang/calendar-fi.js create mode 100644 htdocs/js/jscalendar/lang/calendar-fr.js create mode 100644 htdocs/js/jscalendar/lang/calendar-he-utf8.js create mode 100644 htdocs/js/jscalendar/lang/calendar-hr-utf8.js create mode 100644 htdocs/js/jscalendar/lang/calendar-hr.js create mode 100644 htdocs/js/jscalendar/lang/calendar-hu.js create mode 100644 htdocs/js/jscalendar/lang/calendar-it.js create mode 100644 htdocs/js/jscalendar/lang/calendar-jp.js create mode 100644 htdocs/js/jscalendar/lang/calendar-ko-utf8.js create mode 100644 htdocs/js/jscalendar/lang/calendar-ko.js create mode 100644 htdocs/js/jscalendar/lang/calendar-lt-utf8.js create mode 100644 htdocs/js/jscalendar/lang/calendar-lt.js create mode 100644 htdocs/js/jscalendar/lang/calendar-lv.js create mode 100644 htdocs/js/jscalendar/lang/calendar-nl.js create mode 100644 htdocs/js/jscalendar/lang/calendar-no.js create mode 100644 htdocs/js/jscalendar/lang/calendar-pl-utf8.js create mode 100644 htdocs/js/jscalendar/lang/calendar-pl.js create mode 100644 htdocs/js/jscalendar/lang/calendar-pt.js create mode 100644 htdocs/js/jscalendar/lang/calendar-ro.js create mode 100644 htdocs/js/jscalendar/lang/calendar-ru.js create mode 100644 htdocs/js/jscalendar/lang/calendar-ru_win_.js create mode 100644 htdocs/js/jscalendar/lang/calendar-si.js create mode 100644 htdocs/js/jscalendar/lang/calendar-sk.js create mode 100644 htdocs/js/jscalendar/lang/calendar-sp.js create mode 100644 htdocs/js/jscalendar/lang/calendar-sv.js create mode 100644 htdocs/js/jscalendar/lang/calendar-tr.js create mode 100644 htdocs/js/jscalendar/lang/calendar-zh.js create mode 100644 htdocs/js/jscalendar/lang/cn_utf8.js create mode 100644 htdocs/js/jscalendar/menuarrow.gif create mode 100644 htdocs/js/jscalendar/skins/aqua/active-bg.gif create mode 100644 htdocs/js/jscalendar/skins/aqua/dark-bg.gif create mode 100644 htdocs/js/jscalendar/skins/aqua/hover-bg.gif create mode 100644 htdocs/js/jscalendar/skins/aqua/menuarrow.gif create mode 100644 htdocs/js/jscalendar/skins/aqua/normal-bg.gif create mode 100644 htdocs/js/jscalendar/skins/aqua/rowhover-bg.gif create mode 100644 htdocs/js/jscalendar/skins/aqua/status-bg.gif create mode 100644 htdocs/js/jscalendar/skins/aqua/theme.css create mode 100644 htdocs/js/jscalendar/skins/aqua/title-bg.gif create mode 100644 htdocs/js/jscalendar/skins/aqua/today-bg.gif create mode 100644 htdocs/js/layersmenu-browser_detection.js create mode 100644 htdocs/js/modify_member.js create mode 100644 htdocs/js/toAscii.js create mode 100644 htdocs/login.php create mode 100644 htdocs/login_form.php create mode 100644 htdocs/logout.php create mode 100644 htdocs/mass_delete.php create mode 100644 htdocs/mass_edit.php create mode 100644 htdocs/mass_update.php create mode 100644 htdocs/modify_member_form.php create mode 100644 htdocs/monitor.php create mode 100644 htdocs/password_checker.php create mode 100644 htdocs/purge_cache.php create mode 100644 htdocs/query_engine.php create mode 100644 htdocs/rdelete.php create mode 100644 htdocs/refresh.php create mode 100644 htdocs/rename.php create mode 100644 htdocs/rename_form.php create mode 100644 htdocs/schema.php create mode 100644 htdocs/server_info.php create mode 100644 htdocs/show_cache.php create mode 100644 htdocs/template_engine.php create mode 100644 htdocs/update.php create mode 100644 htdocs/update_confirm.php create mode 100644 htdocs/view_jpeg_photo.php create mode 100644 htdocs/welcome.php create mode 100644 index.php create mode 100644 lib/AJAXTree.php create mode 100644 lib/Attribute.php create mode 100644 lib/AttributeFactory.php create mode 100644 lib/BinaryAttribute.php create mode 100644 lib/DateAttribute.php create mode 100644 lib/DnAttribute.php create mode 100644 lib/GidAttribute.php create mode 100644 lib/HTMLTree.php create mode 100644 lib/JpegAttribute.php create mode 100644 lib/MassRender.php create mode 100644 lib/MultiLineAttribute.php create mode 100644 lib/ObjectClassAttribute.php create mode 100644 lib/PageRender.php create mode 100644 lib/PasswordAttribute.php create mode 100644 lib/Query.php create mode 100644 lib/QueryRender.php create mode 100644 lib/RandomPasswordAttribute.php create mode 100644 lib/SambaPasswordAttribute.php create mode 100644 lib/SelectionAttribute.php create mode 100644 lib/ShadowAttribute.php create mode 100644 lib/Template.php create mode 100644 lib/TemplateRender.php create mode 100644 lib/Tree.php create mode 100644 lib/TreeItem.php create mode 100644 lib/Visitor.php create mode 100644 lib/blowfish.php create mode 100644 lib/common.php create mode 100644 lib/config_default.php create mode 100644 lib/createlm.php create mode 100644 lib/ds.php create mode 100644 lib/ds_ldap.php create mode 100644 lib/ds_ldap_pla.php create mode 100644 lib/emuhash_functions.php create mode 100644 lib/export_functions.php create mode 100644 lib/functions.php create mode 100644 lib/hooks.php create mode 100644 lib/import_functions.php create mode 100644 lib/ldap_error_codes.txt create mode 100644 lib/ldap_supported_oids.txt create mode 100644 lib/page.php create mode 100644 lib/query_functions.php create mode 100644 lib/schema_functions.php create mode 100644 lib/session_functions.php create mode 100644 lib/syslog.php create mode 100644 lib/template_functions.php create mode 100644 lib/xml2array.php create mode 100644 lib/xmlTemplates.php create mode 100644 locale/ca_ES/LC_MESSAGES/messages.mo create mode 100644 locale/cs_CZ/LC_MESSAGES/messages.mo create mode 100644 locale/da_DK/LC_MESSAGES/messages.mo create mode 100644 locale/de_DE/LC_MESSAGES/messages.mo create mode 100644 locale/es_ES/LC_MESSAGES/messages.mo create mode 100644 locale/fi_FI/LC_MESSAGES/messages.mo create mode 100644 locale/fr_FR/LC_MESSAGES/messages.mo create mode 100644 locale/gn_PY/LC_MESSAGES/messages.mo create mode 100644 locale/hu_HU/LC_MESSAGES/messages.mo create mode 100644 locale/it_IT/LC_MESSAGES/messages.mo create mode 100644 locale/ja_JP/LC_MESSAGES/messages.mo create mode 100644 locale/nb_NO/LC_MESSAGES/messages.mo create mode 100644 locale/nl_BE/LC_MESSAGES/messages.mo create mode 100644 locale/oc_FR/LC_MESSAGES/messages.mo create mode 100644 locale/pl_PL/LC_MESSAGES/messages.mo create mode 100644 locale/pt_BR/LC_MESSAGES/messages.mo create mode 100644 locale/ru_RU/LC_MESSAGES/messages.mo create mode 100644 locale/sk_SK/LC_MESSAGES/messages.mo create mode 100644 locale/sv_FI/LC_MESSAGES/messages.mo create mode 100644 locale/tr_TR/LC_MESSAGES/messages.mo create mode 100644 locale/uk_UA/LC_MESSAGES/messages.mo create mode 100644 locale/zh_CN/LC_MESSAGES/messages.mo create mode 100644 locale/zh_TW/LC_MESSAGES/messages.mo create mode 100644 queries/SambaUsers.xml create mode 100644 queries/UserList.xml create mode 100644 queries/query.dtd create mode 100644 templates/creation/alias.xml create mode 100644 templates/creation/courierMailAccount.xml create mode 100644 templates/creation/courierMailAlias.xml create mode 100644 templates/creation/dNSDomain.xml create mode 100644 templates/creation/example.xml create mode 100644 templates/creation/inetOrgPerson.xml create mode 100644 templates/creation/kolabPerson.xml create mode 100644 templates/creation/mozillaOrgPerson.xml create mode 100644 templates/creation/organizationalRole.xml create mode 100644 templates/creation/ou.xml create mode 100644 templates/creation/posixAccount.xml create mode 100644 templates/creation/posixGroup.xml create mode 100644 templates/creation/sambaDomain.xml create mode 100644 templates/creation/sambaGroupMapping.xml create mode 100644 templates/creation/sambaMachine.xml create mode 100644 templates/creation/sambaSamAccount.xml create mode 100644 templates/creation/sendmailMTAAliasObject.xml create mode 100644 templates/creation/sendmailMTAClass.xml create mode 100644 templates/creation/sendmailMTACluster.xml create mode 100644 templates/creation/sendmailMTAMapObject.xml create mode 100644 templates/creation/sendmailVirtualDomain.xml create mode 100644 templates/creation/sendmailVirtualUser.xml create mode 100644 templates/creation/simpleSecurityObject.xml create mode 100644 templates/modification/inetOrgPerson.xml create mode 100644 templates/modification/posixGroup.xml create mode 100644 templates/template.dtd create mode 100644 tools/po/Makefile create mode 100644 tools/po/messages.header create mode 100644 tools/unserialize.php diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ac7db53 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +config/config.php +queries/custom_* +templates/*/custom_* diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..e079b12 --- /dev/null +++ b/INSTALL @@ -0,0 +1,23 @@ +For install instructions in non-English languages, see the wiki: + http://phpldapadmin.sourceforge.net + +* Requirements + + phpLDAPadmin requires the following: + a. A web server (Apache, IIS, etc). + b. PHP 5.0.0 or newer (with LDAP support) + +* To install + + 1. Unpack the archive (if you're reading this, you already did that). + 2. Put the resulting 'phpldapadmin' directory somewhere in your webroot. + 3. Copy 'config.php.example' to 'config.php' and edit to taste (this is in the config/ directory). + 4. Then, point your browser to the phpldapadmin directory. + +* For additional help + + See the wiki: + http://phpldapadmin.sourceforge.net + + Join our mailing list: + https://lists.sourceforge.net/lists/listinfo/phpldapadmin-devel diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..022e560 --- /dev/null +++ b/LICENSE @@ -0,0 +1,341 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. + diff --git a/VERSION b/VERSION new file mode 100644 index 0000000..e0a90a8 --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +RELEASE-1.2.3 diff --git a/config/config.php.example b/config/config.php.example new file mode 100644 index 0000000..5b6fdb8 --- /dev/null +++ b/config/config.php.example @@ -0,0 +1,576 @@ +custom variable to do so. + * For example, the default for defining the language in config_default.php + * + * $this->default->appearance['language'] = array( + * 'desc'=>'Language', + * 'default'=>'auto'); + * + * to override this, use $config->custom->appearance['language'] = 'en_EN'; + * + * This file is also used to configure your LDAP server connections. + * + * You must specify at least one LDAP server there. You may add + * as many as you like. You can also specify your language, and + * many other options. + * + * NOTE: Commented out values in this file prefixed by //, represent the + * defaults that have been defined in config_default.php. + * Commented out values prefixed by #, dont reflect their default value, you can + * check config_default.php if you want to see what the default is. + * + * DONT change config_default.php, you changes will be lost by the next release + * of PLA. Instead change this file - as it will NOT be replaced by a new + * version of phpLDAPadmin. + */ + +/********************************************* + * Useful important configuration overrides * + *********************************************/ + +/* If you are asked to put PLA in debug mode, this is how you do it: */ +# $config->custom->debug['level'] = 255; +# $config->custom->debug['syslog'] = true; +# $config->custom->debug['file'] = '/tmp/pla_debug.log'; + +/* phpLDAPadmin can encrypt the content of sensitive cookies if you set this + to a big random string. */ +// $config->custom->session['blowfish'] = null; + +/* If your auth_type is http, you can override your HTTP Authentication Realm. */ +// $config->custom->session['http_realm'] = sprintf('%s %s',app_name(),'login'); + +/* The language setting. If you set this to 'auto', phpLDAPadmin will attempt + to determine your language automatically. + If PLA doesnt show (all) strings in your language, then you can do some + translation at http://translations.launchpad.net/phpldapadmin and download + the translation files, replacing those provided with PLA. + (We'll pick up the translations before making the next release too!) */ +// $config->custom->appearance['language'] = 'auto'; + +/* The temporary storage directory where we will put jpegPhoto data + This directory must be readable and writable by your web server. */ +// $config->custom->jpeg['tmpdir'] = '/tmp'; // Example for Unix systems +# $config->custom->jpeg['tmpdir'] = 'c:\\temp'; // Example for Windows systems + +/* Set this to (bool)true if you do NOT want a random salt used when + calling crypt(). Instead, use the first two letters of the user's + password. This is insecure but unfortunately needed for some older + environments. */ +# $config->custom->password['no_random_crypt_salt'] = true; + +/* PHP script timeout control. If php runs longer than this many seconds then + PHP will stop with an Maximum Execution time error. Increase this value from + the default if queries to your LDAP server are slow. The default is either + 30 seconds or the setting of max_exection_time if this is null. */ +// $config->custom->session['timelimit'] = 30; + +/* Our local timezone + This is to make sure that when we ask the system for the current time, we + get the right local time. If this is not set, all time() calculations will + assume UTC if you have not set PHP date.timezone. */ +// $config->custom->appearance['timezone'] = null; +# $config->custom->appearance['timezone'] = 'Australia/Melbourne'; + +/********************************************* + * Commands * + *********************************************/ + +/* Command availability ; if you don't authorize a command the command + links will not be shown and the command action will not be permitted. + For better security, set also ACL in your ldap directory. */ +/* +$config->custom->commands['cmd'] = array( + 'entry_internal_attributes_show' => true, + 'entry_refresh' => true, + 'oslinks' => true, + 'switch_template' => true +); + +$config->custom->commands['script'] = array( + 'add_attr_form' => true, + 'add_oclass_form' => true, + 'add_value_form' => true, + 'collapse' => true, + 'compare' => true, + 'compare_form' => true, + 'copy' => true, + 'copy_form' => true, + 'create' => true, + 'create_confirm' => true, + 'delete' => true, + 'delete_attr' => true, + 'delete_form' => true, + 'draw_tree_node' => true, + 'expand' => true, + 'export' => true, + 'export_form' => true, + 'import' => true, + 'import_form' => true, + 'login' => true, + 'logout' => true, + 'login_form' => true, + 'mass_delete' => true, + 'mass_edit' => true, + 'mass_update' => true, + 'modify_member_form' => true, + 'monitor' => true, + 'purge_cache' => true, + 'query_engine' => true, + 'rename' => true, + 'rename_form' => true, + 'rdelete' => true, + 'refresh' => true, + 'schema' => true, + 'server_info' => true, + 'show_cache' => true, + 'template_engine' => true, + 'update_confirm' => true, + 'update' => true +); +*/ + +/********************************************* + * Appearance * + *********************************************/ + +/* If you want to choose the appearance of the tree, specify a class name which + inherits from the Tree class. */ +// $config->custom->appearance['tree'] = 'AJAXTree'; +# $config->custom->appearance['tree'] = 'HTMLTree'; + +/* Just show your custom templates. */ +// $config->custom->appearance['custom_templates_only'] = false; + +/* Disable the default template. */ +// $config->custom->appearance['disable_default_template'] = false; + +/* Hide the warnings for invalid objectClasses/attributes in templates. */ +// $config->custom->appearance['hide_template_warning'] = false; + +/* Set to true if you would like to hide header and footer parts. */ +// $config->custom->appearance['minimalMode'] = false; + +/* Configure what objects are shown in left hand tree */ +// $config->custom->appearance['tree_filter'] = '(objectclass=*)'; + +/* The height and width of the tree. If these values are not set, then + no tree scroll bars are provided. */ +// $config->custom->appearance['tree_height'] = null; +# $config->custom->appearance['tree_height'] = 600; +// $config->custom->appearance['tree_width'] = null; +# $config->custom->appearance['tree_width'] = 250; + +/* Confirm create and update operations, allowing you to review the changes + and optionally skip attributes during the create/update operation. */ +// $config->custom->confirm['create'] = true; +// $config->custom->confirm['update'] = true; + +/* Confirm copy operations, and treat them like create operations. This allows + you to edit the attributes (thus changing any that might conflict with + uniqueness) before creating the new entry. */ +// $config->custom->confirm['copy'] = true; + +/********************************************* + * User-friendly attribute translation * + *********************************************/ + +/* Use this array to map attribute names to user friendly names. For example, if + you don't want to see "facsimileTelephoneNumber" but rather "Fax". */ +// $config->custom->appearance['friendly_attrs'] = array(); +$config->custom->appearance['friendly_attrs'] = array( + 'facsimileTelephoneNumber' => 'Fax', + 'gid' => 'Group', + 'mail' => 'Email', + 'telephoneNumber' => 'Telephone', + 'uid' => 'User Name', + 'userPassword' => 'Password' +); + +/********************************************* + * Hidden attributes * + *********************************************/ + +/* You may want to hide certain attributes from being edited. If you want to + hide attributes from the user, you should use your LDAP servers ACLs. + NOTE: The user must be able to read the hide_attrs_exempt entry to be + excluded. */ +// $config->custom->appearance['hide_attrs'] = array(); +# $config->custom->appearance['hide_attrs'] = array('objectClass'); + +/* Members of this list will be exempt from the hidden attributes. */ +// $config->custom->appearance['hide_attrs_exempt'] = null; +# $config->custom->appearance['hide_attrs_exempt'] = 'cn=PLA UnHide,ou=Groups,c=AU'; + +/********************************************* + * Read-only attributes * + *********************************************/ + +/* You may want to phpLDAPadmin to display certain attributes as read only, + meaning that users will not be presented a form for modifying those + attributes, and they will not be allowed to be modified on the "back-end" + either. You may configure this list here: + NOTE: The user must be able to read the readonly_attrs_exempt entry to be + excluded. */ +// $config->custom->appearance['readonly_attrs'] = array(); + +/* Members of this list will be exempt from the readonly attributes. */ +// $config->custom->appearance['readonly_attrs_exempt'] = null; +# $config->custom->appearance['readonly_attrs_exempt'] = 'cn=PLA ReadWrite,ou=Groups,c=AU'; + +/********************************************* + * Group attributes * + *********************************************/ + +/* Add "modify group members" link to the attribute. */ +// $config->custom->modify_member['groupattr'] = array('member','uniqueMember','memberUid'); + +/* Configure filter for member search. This only applies to "modify group members" feature */ +// $config->custom->modify_member['filter'] = '(objectclass=Person)'; + +/* Attribute that is added to the group member attribute. */ +// $config->custom->modify_member['attr'] = 'dn'; + +/* For Posix attributes */ +// $config->custom->modify_member['posixattr'] = 'uid'; +// $config->custom->modify_member['posixfilter'] = '(uid=*)'; +// $config->custom->modify_member['posixgroupattr'] = 'memberUid'; + +/********************************************* + * Support for attrs display order * + *********************************************/ + +/* Use this array if you want to have your attributes displayed in a specific + order. You can use default attribute names or their fridenly names. + For example, "sn" will be displayed right after "givenName". All the other + attributes that are not specified in this array will be displayed after in + alphabetical order. */ +// $config->custom->appearance['attr_display_order'] = array(); +# $config->custom->appearance['attr_display_order'] = array( +# 'givenName', +# 'sn', +# 'cn', +# 'displayName', +# 'uid', +# 'uidNumber', +# 'gidNumber', +# 'homeDirectory', +# 'mail', +# 'userPassword' +# ); + +/********************************************* + * Define your LDAP servers in this section * + *********************************************/ + +$servers = new Datastore(); + +/* $servers->NewServer('ldap_pla') must be called before each new LDAP server + declaration. */ +$servers->newServer('ldap_pla'); + +/* A convenient name that will appear in the tree viewer and throughout + phpLDAPadmin to identify this LDAP server to users. */ +$servers->setValue('server','name','My LDAP Server'); + +/* Examples: + 'ldap.example.com', + 'ldaps://ldap.example.com/', + 'ldapi://%2fusr%local%2fvar%2frun%2fldapi' + (Unix socket at /usr/local/var/run/ldap) */ +// $servers->setValue('server','host','127.0.0.1'); + +/* The port your LDAP server listens on (no quotes). 389 is standard. */ +// $servers->setValue('server','port',389); + +/* Array of base DNs of your LDAP server. Leave this blank to have phpLDAPadmin + auto-detect it for you. */ +// $servers->setValue('server','base',array('')); + +/* Five options for auth_type: + 1. 'cookie': you will login via a web form, and a client-side cookie will + store your login dn and password. + 2. 'session': same as cookie but your login dn and password are stored on the + web server in a persistent session variable. + 3. 'http': same as session but your login dn and password are retrieved via + HTTP authentication. + 4. 'config': specify your login dn and password here in this config file. No + login will be required to use phpLDAPadmin for this server. + 5. 'sasl': login will be taken from the webserver's kerberos authentication. + Currently only GSSAPI has been tested (using mod_auth_kerb). + + Choose wisely to protect your authentication information appropriately for + your situation. If you choose 'cookie', your cookie contents will be + encrypted using blowfish and the secret your specify above as + session['blowfish']. */ +// $servers->setValue('login','auth_type','session'); + +/* The DN of the user for phpLDAPadmin to bind with. For anonymous binds or + 'cookie','session' or 'sasl' auth_types, LEAVE THE LOGIN_DN AND LOGIN_PASS + BLANK. If you specify a login_attr in conjunction with a cookie or session + auth_type, then you can also specify the bind_id/bind_pass here for searching + the directory for users (ie, if your LDAP server does not allow anonymous + binds. */ +// $servers->setValue('login','bind_id',''); +# $servers->setValue('login','bind_id','cn=Manager,dc=example,dc=com'); + +/* Your LDAP password. If you specified an empty bind_id above, this MUST also + be blank. */ +// $servers->setValue('login','bind_pass',''); +# $servers->setValue('login','bind_pass','secret'); + +/* Use TLS (Transport Layer Security) to connect to the LDAP server. */ +// $servers->setValue('server','tls',false); + +/************************************ + * SASL Authentication * + ************************************/ + +/* Enable SASL authentication LDAP SASL authentication requires PHP 5.x + configured with --with-ldap-sasl=DIR. If this option is disabled (ie, set to + false), then all other sasl options are ignored. */ +// $servers->setValue('login','auth_type','sasl'); + +/* SASL auth mechanism */ +// $servers->setValue('sasl','mech','GSSAPI'); + +/* SASL authentication realm name */ +// $servers->setValue('sasl','realm',''); +# $servers->setValue('sasl','realm','EXAMPLE.COM'); + +/* SASL authorization ID name + If this option is undefined, authorization id will be computed from bind DN, + using authz_id_regex and authz_id_replacement. */ +// $servers->setValue('sasl','authz_id', null); + +/* SASL authorization id regex and replacement + When authz_id property is not set (default), phpLDAPAdmin will try to + figure out authorization id by itself from bind distinguished name (DN). + + This procedure is done by calling preg_replace() php function in the + following way: + + $authz_id = preg_replace($sasl_authz_id_regex,$sasl_authz_id_replacement, + $bind_dn); + + For info about pcre regexes, see: + - pcre(3), perlre(3) + - http://www.php.net/preg_replace */ +// $servers->setValue('sasl','authz_id_regex',null); +// $servers->setValue('sasl','authz_id_replacement',null); +# $servers->setValue('sasl','authz_id_regex','/^uid=([^,]+)(.+)/i'); +# $servers->setValue('sasl','authz_id_replacement','$1'); + +/* SASL auth security props. + See http://beepcore-tcl.sourceforge.net/tclsasl.html#anchor5 for explanation. */ +// $servers->setValue('sasl','props',null); + +/* Default password hashing algorithm. One of md5, ssha, sha, md5crpyt, smd5, + blowfish, crypt or leave blank for now default algorithm. */ +// $servers->setValue('appearance','password_hash','md5'); + +/* If you specified 'cookie' or 'session' as the auth_type above, you can + optionally specify here an attribute to use when logging in. If you enter + 'uid' and login as 'dsmith', phpLDAPadmin will search for (uid=dsmith) + and log in as that user. + Leave blank or specify 'dn' to use full DN for logging in. Note also that if + your LDAP server requires you to login to perform searches, you can enter the + DN to use when searching in 'bind_id' and 'bind_pass' above. */ +// $servers->setValue('login','attr','dn'); + +/* Base DNs to used for logins. If this value is not set, then the LDAP server + Base DNs are used. */ +// $servers->setValue('login','base',array()); + +/* If 'login,attr' is used above such that phpLDAPadmin will search for your DN + at login, you may restrict the search to a specific objectClasses. EG, set this + to array('posixAccount') or array('inetOrgPerson',..), depending upon your + setup. */ +// $servers->setValue('login','class',array()); + +/* If you specified something different from 'dn', for example 'uid', as the + login_attr above, you can optionally specify here to fall back to + authentication with dn. + This is useful, when users should be able to log in with their uid, but + the ldap administrator wants to log in with his root-dn, that does not + necessarily have the uid attribute. + When using this feature, login_class is ignored. */ +// $servers->setValue('login','fallback_dn',false); + +/* Specify true If you want phpLDAPadmin to not display or permit any + modification to the LDAP server. */ +// $servers->setValue('server','read_only',false); + +/* Specify false if you do not want phpLDAPadmin to draw the 'Create new' links + in the tree viewer. */ +// $servers->setValue('appearance','show_create',true); + +/* Set to true if you would like to initially open the first level of each tree. */ +// $servers->setValue('appearance','open_tree',false); + +/* This feature allows phpLDAPadmin to automatically determine the next + available uidNumber for a new entry. */ +// $servers->setValue('auto_number','enable',true); + +/* The mechanism to use when finding the next available uidNumber. Two possible + values: 'uidpool' or 'search'. + The 'uidpool' mechanism uses an existing uidPool entry in your LDAP server to + blindly lookup the next available uidNumber. The 'search' mechanism searches + for entries with a uidNumber value and finds the first available uidNumber + (slower). */ +// $servers->setValue('auto_number','mechanism','search'); + +/* The DN of the search base when the 'search' mechanism is used above. */ +# $servers->setValue('auto_number','search_base','ou=People,dc=example,dc=com'); + +/* The minimum number to use when searching for the next available number + (only when 'search' is used for auto_number. */ +// $servers->setValue('auto_number','min',array('uidNumber'=>1000,'gidNumber'=>500)); + +/* If you set this, then phpldapadmin will bind to LDAP with this user ID when + searching for the uidnumber. The idea is, this user id would have full + (readonly) access to uidnumber in your ldap directory (the logged in user + may not), so that you can be guaranteed to get a unique uidnumber for your + directory. */ +// $servers->setValue('auto_number','dn',null); + +/* The password for the dn above. */ +// $servers->setValue('auto_number','pass',null); + +/* Enable anonymous bind login. */ +// $servers->setValue('login','anon_bind',true); + +/* Use customized page with prefix when available. */ +# $servers->setValue('custom','pages_prefix','custom_'); + +/* If you set this, then only these DNs are allowed to log in. This array can + contain individual users, groups or ldap search filter(s). Keep in mind that + the user has not authenticated yet, so this will be an anonymous search to + the LDAP server, so make your ACLs allow these searches to return results! */ +# $servers->setValue('login','allowed_dns',array( +# 'uid=stran,ou=People,dc=example,dc=com', +# '(&(gidNumber=811)(objectClass=groupOfNames))', +# '(|(uidNumber=200)(uidNumber=201))', +# 'cn=callcenter,ou=Group,dc=example,dc=com')); + +/* Set this if you dont want this LDAP server to show in the tree */ +// $servers->setValue('server','visible',true); + +/* Set this if you want to hide the base DNs that dont exist instead of + displaying the message "The base entry doesnt exist, create it?" +// $servers->setValue('server','hide_noaccess_base',false); +# $servers->setValue('server','hide_noaccess_base',true); + +/* This is the time out value in minutes for the server. After as many minutes + of inactivity you will be automatically logged out. If not set, the default + value will be ( session_cache_expire()-1 ) */ +# $servers->setValue('login','timeout',30); + +/* Set this if you want phpldapadmin to perform rename operation on entry which + has children. Certain servers are known to allow it, certain are not. */ +// $servers->setValue('server','branch_rename',false); + +/* If you set this, then phpldapadmin will show these attributes as + internal attributes, even if they are not defined in your schema. */ +// $servers->setValue('server','custom_sys_attrs',array('')); +# $servers->setValue('server','custom_sys_attrs',array('passwordExpirationTime','passwordAllowChangeTime')); + +/* If you set this, then phpldapadmin will show these attributes on + objects, even if they are not defined in your schema. */ +// $servers->setValue('server','custom_attrs',array('')); +# $servers->setValue('server','custom_attrs',array('nsRoleDN','nsRole','nsAccountLock')); + +/* These attributes will be forced to MAY attributes and become option in the + templates. If they are not defined in the templates, then they wont appear + as per normal template processing. You may want to do this because your LDAP + server may automatically calculate a default value. + In Fedora Directory Server using the DNA Plugin one could ignore uidNumber, + gidNumber and sambaSID. */ +// $servers->setValue('server','force_may',array('')); +# $servers->setValue('server','force_may',array('uidNumber','gidNumber','sambaSID')); + +/********************************************* + * Unique attributes * + *********************************************/ + +/* You may want phpLDAPadmin to enforce some attributes to have unique values + (ie: not belong to other entries in your tree. This (together with + 'unique','dn' and 'unique','pass' option will not let updates to + occur with other attributes have the same value. */ +# $servers->setValue('unique','attrs',array('mail','uid','uidNumber')); + +/* If you set this, then phpldapadmin will bind to LDAP with this user ID when + searching for attribute uniqueness. The idea is, this user id would have full + (readonly) access to your ldap directory (the logged in user may not), so + that you can be guaranteed to get a unique uidnumber for your directory. */ +// $servers->setValue('unique','dn',null); + +/* The password for the dn above. */ +// $servers->setValue('unique','pass',null); + +/************************************************************************** + * If you want to configure additional LDAP servers, do so below. * + * Remove the commented lines and use this section as a template for all * + * your other LDAP servers. * + **************************************************************************/ + +/* +$servers->newServer('ldap_pla'); +$servers->setValue('server','name','LDAP Server'); +$servers->setValue('server','host','127.0.0.1'); +$servers->setValue('server','port',389); +$servers->setValue('server','base',array('')); +$servers->setValue('login','auth_type','cookie'); +$servers->setValue('login','bind_id',''); +$servers->setValue('login','bind_pass',''); +$servers->setValue('server','tls',false); + +# SASL auth +$servers->setValue('login','auth_type','sasl'); +$servers->setValue('sasl','mech','GSSAPI'); +$servers->setValue('sasl','realm','EXAMPLE.COM'); +$servers->setValue('sasl','authz_id',null); +$servers->setValue('sasl','authz_id_regex','/^uid=([^,]+)(.+)/i'); +$servers->setValue('sasl','authz_id_replacement','$1'); +$servers->setValue('sasl','props',null); + +$servers->setValue('appearance','password_hash','md5'); +$servers->setValue('login','attr','dn'); +$servers->setValue('login','fallback_dn',false); +$servers->setValue('login','class',null); +$servers->setValue('server','read_only',false); +$servers->setValue('appearance','show_create',true); + +$servers->setValue('auto_number','enable',true); +$servers->setValue('auto_number','mechanism','search'); +$servers->setValue('auto_number','search_base',null); +$servers->setValue('auto_number','min',array('uidNumber'=>1000,'gidNumber'=>500)); +$servers->setValue('auto_number','dn',null); +$servers->setValue('auto_number','pass',null); + +$servers->setValue('login','anon_bind',true); +$servers->setValue('custom','pages_prefix','custom_'); +$servers->setValue('unique','attrs',array('mail','uid','uidNumber')); +$servers->setValue('unique','dn',null); +$servers->setValue('unique','pass',null); + +$servers->setValue('server','visible',true); +$servers->setValue('login','timeout',30); +$servers->setValue('server','branch_rename',false); +$servers->setValue('server','custom_sys_attrs',array('passwordExpirationTime','passwordAllowChangeTime')); +$servers->setValue('server','custom_attrs',array('nsRoleDN','nsRole','nsAccountLock')); +$servers->setValue('server','force_may',array('uidNumber','gidNumber','sambaSID')); +*/ +?> diff --git a/doc/README-translation.txt b/doc/README-translation.txt new file mode 100644 index 0000000..3bf340a --- /dev/null +++ b/doc/README-translation.txt @@ -0,0 +1,2 @@ +Please see http://phpldapadmin.sourceforge.net/Translate now for information on +translating PLA. diff --git a/doc/certs/ca-bundle.crt b/doc/certs/ca-bundle.crt new file mode 100644 index 0000000..dea4c9f --- /dev/null +++ b/doc/certs/ca-bundle.crt @@ -0,0 +1,4567 @@ +## +## Extracted from the mod_ssl-2.7.1-1.3.14 source tree 25 October 2000. +## +## ca-bundle.crt -- Bundle of CA Root Certificates +## Last Modified: Thu Mar 2 09:32:46 CET 2000 +## +## This is a bundle of X.509 certificates of public +## Certificate Authorities (CA). These were automatically +## extracted from Netscape Communicator 4.72's certificate database +## (the file `cert7.db'). It contains the certificates in both +## plain text and PEM format and therefore can be directly used +## with an Apache+mod_ssl webserver for SSL client authentication. +## Just configure this file as the SSLCACertificateFile. +## +## (SKIPME) +## + +ABAecom (sub., Am. Bankers Assn.) Root CA +========================================= +MD5 Fingerprint: 82:12:F7:89:E1:0B:91:60:A4:B6:22:9F:94:68:11:92 +PEM Data: +-----BEGIN CERTIFICATE----- +MIID+DCCAuCgAwIBAgIRANAeQJAAACdLAAAAAQAAAAQwDQYJKoZIhvcNAQEFBQAw +gYwxCzAJBgNVBAYTAlVTMQ0wCwYDVQQIEwRVdGFoMRcwFQYDVQQHEw5TYWx0IExh +a2UgQ2l0eTEYMBYGA1UEChMPWGNlcnQgRVogYnkgRFNUMRgwFgYDVQQDEw9YY2Vy +dCBFWiBieSBEU1QxITAfBgkqhkiG9w0BCQEWEmNhQGRpZ3NpZ3RydXN0LmNvbTAe +Fw05OTA3MTQxNjE0MThaFw0wOTA3MTExNjE0MThaMIGMMQswCQYDVQQGEwJVUzEN +MAsGA1UECBMEVXRhaDEXMBUGA1UEBxMOU2FsdCBMYWtlIENpdHkxGDAWBgNVBAoT +D1hjZXJ0IEVaIGJ5IERTVDEYMBYGA1UEAxMPWGNlcnQgRVogYnkgRFNUMSEwHwYJ +KoZIhvcNAQkBFhJjYUBkaWdzaWd0cnVzdC5jb20wggEiMA0GCSqGSIb3DQEBAQUA +A4IBDwAwggEKAoIBAQCtVBjetL/3reh0qu2LfI/C1HUa1YS5tmL8ie/kl2GS+x24 +4VpHNJ6eBiL70+o4y7iLB/caoBd3B1owHNQpOCDXJ0DYUJNDv9IYoil2BXKqa7Zp +mKt5Hhxl9WqL/MUWqqJy2mDtTm4ZJXoKHTDjUJtCPETrobAgHtsCfv49H7/QAIrb +QHamGKUVp1e2UsIBF5h3j4qBxhq0airmr6nWAKzP2BVJfNsbof6B+of505DBAsD5 +0ELpkWglX8a/hznplQBgKL+DLMDnXrbXNhbnYId26OcnsiUNi3rlqh3lWc3OCw5v +xsic4xDZhTnTt5v6xrp8dNJddVardKSiUb9SfO5xAgMBAAGjUzBRMA8GA1UdEwEB +/wQFMAMBAf8wHwYDVR0jBBgwFoAUCCBsZuuBCmxc1bWmPEHdHJaRJ3cwHQYDVR0O +BBYEFAggbGbrgQpsXNW1pjxB3RyWkSd3MA0GCSqGSIb3DQEBBQUAA4IBAQBah1iP +Lat2IWtUDNnxQfZOzSue4x+boy1/2St9WMhnpCn16ezVvZY/o3P4xFs2fNBjLDQ5 +m0i4PW/2FMWeY+anNG7T6DOzxzwYbiOuQ5KZP5jFaTDxNjutuTCC1rZZFpYCCykS +YbQRifcML5SQhZgonFNsfmPdc/QZ/0qB0bJSI/08SjTOWhvgUIrtT4GV2GDn5MQN +u1g+WPdOaG8+Z8nLepcWJ+xCYRR2uwDF6wg9FX9LtiJdhzuQ9PPA/jez6dliDMDD +Wa9gvR8N26E0HzDEPYutsB0Ek+1f1eS/IDAE9EjpMwHRLpAnUrOb3jocq6mXf5vr +wo3CbezcE9NGxXl8 +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: + d0:1e:40:90:00:00:27:4b:00:00:00:01:00:00:00:04 + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, ST=Utah, L=Salt Lake City, O=Xcert EZ by DST, CN=Xcert EZ by DST/Email=ca@digsigtrust.com + Validity + Not Before: Jul 14 16:14:18 1999 GMT + Not After : Jul 11 16:14:18 2009 GMT + Subject: C=US, ST=Utah, L=Salt Lake City, O=Xcert EZ by DST, CN=Xcert EZ by DST/Email=ca@digsigtrust.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:ad:54:18:de:b4:bf:f7:ad:e8:74:aa:ed:8b:7c: + 8f:c2:d4:75:1a:d5:84:b9:b6:62:fc:89:ef:e4:97: + 61:92:fb:1d:b8:e1:5a:47:34:9e:9e:06:22:fb:d3: + ea:38:cb:b8:8b:07:f7:1a:a0:17:77:07:5a:30:1c: + d4:29:38:20:d7:27:40:d8:50:93:43:bf:d2:18:a2: + 29:76:05:72:aa:6b:b6:69:98:ab:79:1e:1c:65:f5: + 6a:8b:fc:c5:16:aa:a2:72:da:60:ed:4e:6e:19:25: + 7a:0a:1d:30:e3:50:9b:42:3c:44:eb:a1:b0:20:1e: + db:02:7e:fe:3d:1f:bf:d0:00:8a:db:40:76:a6:18: + a5:15:a7:57:b6:52:c2:01:17:98:77:8f:8a:81:c6: + 1a:b4:6a:2a:e6:af:a9:d6:00:ac:cf:d8:15:49:7c: + db:1b:a1:fe:81:fa:87:f9:d3:90:c1:02:c0:f9:d0: + 42:e9:91:68:25:5f:c6:bf:87:39:e9:95:00:60:28: + bf:83:2c:c0:e7:5e:b6:d7:36:16:e7:60:87:76:e8: + e7:27:b2:25:0d:8b:7a:e5:aa:1d:e5:59:cd:ce:0b: + 0e:6f:c6:c8:9c:e3:10:d9:85:39:d3:b7:9b:fa:c6: + ba:7c:74:d2:5d:75:56:ab:74:a4:a2:51:bf:52:7c: + ee:71 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Authority Key Identifier: + keyid:08:20:6C:66:EB:81:0A:6C:5C:D5:B5:A6:3C:41:DD:1C:96:91:27:77 + + X509v3 Subject Key Identifier: + 08:20:6C:66:EB:81:0A:6C:5C:D5:B5:A6:3C:41:DD:1C:96:91:27:77 + Signature Algorithm: sha1WithRSAEncryption + 5a:87:58:8f:2d:ab:76:21:6b:54:0c:d9:f1:41:f6:4e:cd:2b: + 9e:e3:1f:9b:a3:2d:7f:d9:2b:7d:58:c8:67:a4:29:f5:e9:ec: + d5:bd:96:3f:a3:73:f8:c4:5b:36:7c:d0:63:2c:34:39:9b:48: + b8:3d:6f:f6:14:c5:9e:63:e6:a7:34:6e:d3:e8:33:b3:c7:3c: + 18:6e:23:ae:43:92:99:3f:98:c5:69:30:f1:36:3b:ad:b9:30: + 82:d6:b6:59:16:96:02:0b:29:12:61:b4:11:89:f7:0c:2f:94: + 90:85:98:28:9c:53:6c:7e:63:dd:73:f4:19:ff:4a:81:d1:b2: + 52:23:fd:3c:4a:34:ce:5a:1b:e0:50:8a:ed:4f:81:95:d8:60: + e7:e4:c4:0d:bb:58:3e:58:f7:4e:68:6f:3e:67:c9:cb:7a:97: + 16:27:ec:42:61:14:76:bb:00:c5:eb:08:3d:15:7f:4b:b6:22: + 5d:87:3b:90:f4:f3:c0:fe:37:b3:e9:d9:62:0c:c0:c3:59:af: + 60:bd:1f:0d:db:a1:34:1f:30:c4:3d:8b:ad:b0:1d:04:93:ed: + 5f:d5:e4:bf:20:30:04:f4:48:e9:33:01:d1:2e:90:27:52:b3: + 9b:de:3a:1c:ab:a9:97:7f:9b:eb:c2:8d:c2:6d:ec:dc:13:d3: + 46:c5:79:7c + +ANX Network CA by DST +===================== +MD5 Fingerprint: A8:ED:DE:EB:93:88:66:D8:2F:C3:BD:1D:BE:45:BE:4D +PEM Data: +-----BEGIN CERTIFICATE----- +MIIDTTCCAragAwIBAgIENm6ibzANBgkqhkiG9w0BAQUFADBSMQswCQYDVQQGEwJV +UzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMR0wGwYDVQQL +ExREU1QgKEFOWCBOZXR3b3JrKSBDQTAeFw05ODEyMDkxNTQ2NDhaFw0xODEyMDkx +NjE2NDhaMFIxCzAJBgNVBAYTAlVTMSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVy +ZSBUcnVzdCBDby4xHTAbBgNVBAsTFERTVCAoQU5YIE5ldHdvcmspIENBMIGdMA0G +CSqGSIb3DQEBAQUAA4GLADCBhwKBgQC0SBGAWKDVpZkP9jcsRLZu0XzzKmueEbaI +IwRccSWeahJ3EW6/aDllqPay9qIYsokVoGe3eowiSGv2hDQftsr3G3LL8ltI04ce +InYTBLSsbJZ/5w4IyTJRMC3VgOghZ7rzXggkLAdZnZAa7kbJtaQelrRBkdR/0o04 +JrBvQ24JfQIBA6OCATAwggEsMBEGCWCGSAGG+EIBAQQEAwIABzB0BgNVHR8EbTBr +MGmgZ6BlpGMwYTELMAkGA1UEBhMCVVMxJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0 +dXJlIFRydXN0IENvLjEdMBsGA1UECxMURFNUIChBTlggTmV0d29yaykgQ0ExDTAL +BgNVBAMTBENSTDEwKwYDVR0QBCQwIoAPMTk5ODEyMDkxNTQ2NDhagQ8yMDE4MTIw +OTE1NDY0OFowCwYDVR0PBAQDAgEGMB8GA1UdIwQYMBaAFIwWVXDMFgpTZMKlhKqz +ZBdDP4I2MB0GA1UdDgQWBBSMFlVwzBYKU2TCpYSqs2QXQz+CNjAMBgNVHRMEBTAD +AQH/MBkGCSqGSIb2fQdBAAQMMAobBFY0LjADAgSQMA0GCSqGSIb3DQEBBQUAA4GB +AEklyWCxDF+pORDTxTRVfc95wynr3vnCQPnoVsXwL+z02exIUbhjOF6TbhiWhbnK +UJykuOpmJmiThW9vTHHQvnoLPDG5975pnhDX0UDorBZxq66rOOFwscqSFuBdhaYY +gAYAnOGmGEJRp2hoWe8mlF+tMQz+KR4XAYQ3W+gSMqNd +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: 913220207 (0x366ea26f) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=Digital Signature Trust Co., OU=DST (ANX Network) CA + Validity + Not Before: Dec 9 15:46:48 1998 GMT + Not After : Dec 9 16:16:48 2018 GMT + Subject: C=US, O=Digital Signature Trust Co., OU=DST (ANX Network) CA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:b4:48:11:80:58:a0:d5:a5:99:0f:f6:37:2c:44: + b6:6e:d1:7c:f3:2a:6b:9e:11:b6:88:23:04:5c:71: + 25:9e:6a:12:77:11:6e:bf:68:39:65:a8:f6:b2:f6: + a2:18:b2:89:15:a0:67:b7:7a:8c:22:48:6b:f6:84: + 34:1f:b6:ca:f7:1b:72:cb:f2:5b:48:d3:87:1e:22: + 76:13:04:b4:ac:6c:96:7f:e7:0e:08:c9:32:51:30: + 2d:d5:80:e8:21:67:ba:f3:5e:08:24:2c:07:59:9d: + 90:1a:ee:46:c9:b5:a4:1e:96:b4:41:91:d4:7f:d2: + 8d:38:26:b0:6f:43:6e:09:7d + Exponent: 3 (0x3) + X509v3 extensions: + Netscape Cert Type: + SSL CA, S/MIME CA, Object Signing CA + X509v3 CRL Distribution Points: + DirName:/C=US/O=Digital Signature Trust Co./OU=DST (ANX Network) CA/CN=CRL1 + + X509v3 Private Key Usage Period: + Not Before: Dec 9 15:46:48 1998 GMT, Not After: Dec 9 15:46:48 2018 GMT + X509v3 Key Usage: + Certificate Sign, CRL Sign + X509v3 Authority Key Identifier: + keyid:8C:16:55:70:CC:16:0A:53:64:C2:A5:84:AA:B3:64:17:43:3F:82:36 + + X509v3 Subject Key Identifier: + 8C:16:55:70:CC:16:0A:53:64:C2:A5:84:AA:B3:64:17:43:3F:82:36 + X509v3 Basic Constraints: + CA:TRUE + 1.2.840.113533.7.65.0: + 0 +..V4.0.... + Signature Algorithm: sha1WithRSAEncryption + 49:25:c9:60:b1:0c:5f:a9:39:10:d3:c5:34:55:7d:cf:79:c3: + 29:eb:de:f9:c2:40:f9:e8:56:c5:f0:2f:ec:f4:d9:ec:48:51: + b8:63:38:5e:93:6e:18:96:85:b9:ca:50:9c:a4:b8:ea:66:26: + 68:93:85:6f:6f:4c:71:d0:be:7a:0b:3c:31:b9:f7:be:69:9e: + 10:d7:d1:40:e8:ac:16:71:ab:ae:ab:38:e1:70:b1:ca:92:16: + e0:5d:85:a6:18:80:06:00:9c:e1:a6:18:42:51:a7:68:68:59: + ef:26:94:5f:ad:31:0c:fe:29:1e:17:01:84:37:5b:e8:12:32: + a3:5d + +American Express CA +=================== +MD5 Fingerprint: 1C:D5:8E:82:BE:70:55:8E:39:61:DF:AD:51:DB:6B:A0 +PEM Data: +-----BEGIN CERTIFICATE----- +MIICkDCCAfkCAgCNMA0GCSqGSIb3DQEBBAUAMIGPMQswCQYDVQQGEwJVUzEnMCUG +A1UEChMeQW1lcmljYW4gRXhwcmVzcyBDb21wYW55LCBJbmMuMSYwJAYDVQQLEx1B +bWVyaWNhbiBFeHByZXNzIFRlY2hub2xvZ2llczEvMC0GA1UEAxMmQW1lcmljYW4g +RXhwcmVzcyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNOTgwODE0MjIwMTAwWhcN +MDYwODE0MjM1OTAwWjCBjzELMAkGA1UEBhMCVVMxJzAlBgNVBAoTHkFtZXJpY2Fu +IEV4cHJlc3MgQ29tcGFueSwgSW5jLjEmMCQGA1UECxMdQW1lcmljYW4gRXhwcmVz +cyBUZWNobm9sb2dpZXMxLzAtBgNVBAMTJkFtZXJpY2FuIEV4cHJlc3MgQ2VydGlm +aWNhdGUgQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDJ8kmS +hcr9FSm1BrZE7PyIo/KGzv8UTyQckvnCI8HOQ99dNMi4FOzVKnCRSZXXVs2U8amT +0Ggi3E19oApyKkfqJfCFAF82VGHPC/k3Wmed6R/pZD9wlWGn0DAC3iYopGYDBOkw ++48zB/lvYYeictvzaHhjZlmpybdm4RWySDYs+QIDAQABMA0GCSqGSIb3DQEBBAUA +A4GBAGgXYrhzi0xs60qlPqvlnS7SzYoHV/PGWZd2Fxf4Uo4nk9hY2Chs9KIEeorC +diSxArTfKPL386infiNIYYj0EWiuJl32oUtTJWrYKhQCDuCHIG6eGVxzkAsj4jGX +Iz/VIqLTBnvaN/XXtUFEF3pFAtmFRWbWjsfwegyZYiJpW+3S +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 1 (0x0) + Serial Number: 141 (0x8d) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=US, O=American Express Company, Inc., OU=American Express Technologies, CN=American Express Certificate Authority + Validity + Not Before: Aug 14 22:01:00 1998 GMT + Not After : Aug 14 23:59:00 2006 GMT + Subject: C=US, O=American Express Company, Inc., OU=American Express Technologies, CN=American Express Certificate Authority + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:c9:f2:49:92:85:ca:fd:15:29:b5:06:b6:44:ec: + fc:88:a3:f2:86:ce:ff:14:4f:24:1c:92:f9:c2:23: + c1:ce:43:df:5d:34:c8:b8:14:ec:d5:2a:70:91:49: + 95:d7:56:cd:94:f1:a9:93:d0:68:22:dc:4d:7d:a0: + 0a:72:2a:47:ea:25:f0:85:00:5f:36:54:61:cf:0b: + f9:37:5a:67:9d:e9:1f:e9:64:3f:70:95:61:a7:d0: + 30:02:de:26:28:a4:66:03:04:e9:30:fb:8f:33:07: + f9:6f:61:87:a2:72:db:f3:68:78:63:66:59:a9:c9: + b7:66:e1:15:b2:48:36:2c:f9 + Exponent: 65537 (0x10001) + Signature Algorithm: md5WithRSAEncryption + 68:17:62:b8:73:8b:4c:6c:eb:4a:a5:3e:ab:e5:9d:2e:d2:cd: + 8a:07:57:f3:c6:59:97:76:17:17:f8:52:8e:27:93:d8:58:d8: + 28:6c:f4:a2:04:7a:8a:c2:76:24:b1:02:b4:df:28:f2:f7:f3: + a8:a7:7e:23:48:61:88:f4:11:68:ae:26:5d:f6:a1:4b:53:25: + 6a:d8:2a:14:02:0e:e0:87:20:6e:9e:19:5c:73:90:0b:23:e2: + 31:97:23:3f:d5:22:a2:d3:06:7b:da:37:f5:d7:b5:41:44:17: + 7a:45:02:d9:85:45:66:d6:8e:c7:f0:7a:0c:99:62:22:69:5b: + ed:d2 + +American Express Global CA +========================== +MD5 Fingerprint: 63:1B:66:93:8C:F3:66:CB:3C:79:57:DC:05:49:EA:DB +PEM Data: +-----BEGIN CERTIFICATE----- +MIIEBDCCAuygAwIBAgICAIUwDQYJKoZIhvcNAQEFBQAwgZYxCzAJBgNVBAYTAlVT +MScwJQYDVQQKEx5BbWVyaWNhbiBFeHByZXNzIENvbXBhbnksIEluYy4xJjAkBgNV +BAsTHUFtZXJpY2FuIEV4cHJlc3MgVGVjaG5vbG9naWVzMTYwNAYDVQQDEy1BbWVy +aWNhbiBFeHByZXNzIEdsb2JhbCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNOTgw +ODE0MTkwNjAwWhcNMTMwODE0MjM1OTAwWjCBljELMAkGA1UEBhMCVVMxJzAlBgNV +BAoTHkFtZXJpY2FuIEV4cHJlc3MgQ29tcGFueSwgSW5jLjEmMCQGA1UECxMdQW1l +cmljYW4gRXhwcmVzcyBUZWNobm9sb2dpZXMxNjA0BgNVBAMTLUFtZXJpY2FuIEV4 +cHJlc3MgR2xvYmFsIENlcnRpZmljYXRlIEF1dGhvcml0eTCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBAPAkJmYu++tKc3FTiUfLJjxTkpRMysKFtQ34w1e9 +Lyofahi3V68MABb6oLaQpvcaoS5mJsdoo4qTaWa1RlYtHYLqkAwKIsKJUI0F89Sr +c0HwzxKsKLRvFJSWWUuekHWG3+JH6+HpT0N+h8onGGaetcFAZX38YW+tm3LPqV7Y +8/nabpEQ+ky16n4g3qk5L/WI5IpvNcYgnCuGRjMK/DFVpWusFkDpzTVZbzIEw3u1 +D3t3cPNIuypSgs6vKW3xEW9t5gcAAe+a8yYNpnkTZ6/4qxx1rJG1a75AsN6cDLFp +hRlxkRNFyt/R/eayypaDedvFuKpbepALeFY+xteflEgR9a0CAwEAAaNaMFgwEgYD +VR0TAQH/BAgwBgEB/wIBBTAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgoq +hkiG+Q8KAQUBMBkGA1UdDgQSBBBXRzV7NicRqAj8L0Yl6yRpMA0GCSqGSIb3DQEB +BQUAA4IBAQDHYUWoinG5vjTpIXshzVYTmNUwY+kYqkuSFb8LHbvskmnFLsNhi+gw +RcsQRsFzOFyLGdIr80DrfHKzLh4n43WVihybLsSVBYZy0FX0oZJSeVzb9Pjc5dcS +sUDHPIbkMWVKyjfG3nZXGWlMRmn8Kq0WN3qTrPchSy3766lQy8HRQAjaA2mHpzde +VcHF7cTjjgwml5tcV0ty4/IDBdACOyYDQJCevgtbSQx48dVMVSng9v1MA6lUAjLR +V1qFrEPtWzsWX6C/NdtLnnvo/+cNPDuom0lBRvVzTv+SZSGDE1Vx60k8f4gawhIo +JaFGS0E3l3/sjvHUoZbCILZerakcHhGg +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: 133 (0x85) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=American Express Company, Inc., OU=American Express Technologies, CN=American Express Global Certificate Authority + Validity + Not Before: Aug 14 19:06:00 1998 GMT + Not After : Aug 14 23:59:00 2013 GMT + Subject: C=US, O=American Express Company, Inc., OU=American Express Technologies, CN=American Express Global Certificate Authority + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:f0:24:26:66:2e:fb:eb:4a:73:71:53:89:47:cb: + 26:3c:53:92:94:4c:ca:c2:85:b5:0d:f8:c3:57:bd: + 2f:2a:1f:6a:18:b7:57:af:0c:00:16:fa:a0:b6:90: + a6:f7:1a:a1:2e:66:26:c7:68:a3:8a:93:69:66:b5: + 46:56:2d:1d:82:ea:90:0c:0a:22:c2:89:50:8d:05: + f3:d4:ab:73:41:f0:cf:12:ac:28:b4:6f:14:94:96: + 59:4b:9e:90:75:86:df:e2:47:eb:e1:e9:4f:43:7e: + 87:ca:27:18:66:9e:b5:c1:40:65:7d:fc:61:6f:ad: + 9b:72:cf:a9:5e:d8:f3:f9:da:6e:91:10:fa:4c:b5: + ea:7e:20:de:a9:39:2f:f5:88:e4:8a:6f:35:c6:20: + 9c:2b:86:46:33:0a:fc:31:55:a5:6b:ac:16:40:e9: + cd:35:59:6f:32:04:c3:7b:b5:0f:7b:77:70:f3:48: + bb:2a:52:82:ce:af:29:6d:f1:11:6f:6d:e6:07:00: + 01:ef:9a:f3:26:0d:a6:79:13:67:af:f8:ab:1c:75: + ac:91:b5:6b:be:40:b0:de:9c:0c:b1:69:85:19:71: + 91:13:45:ca:df:d1:fd:e6:b2:ca:96:83:79:db:c5: + b8:aa:5b:7a:90:0b:78:56:3e:c6:d7:9f:94:48:11: + f5:ad + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE, pathlen:5 + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Certificate Policies: + Policy: 1.2.840.113807.10.1.5.1 + + X509v3 Subject Key Identifier: + 57:47:35:7B:36:27:11:A8:08:FC:2F:46:25:EB:24:69 + Signature Algorithm: sha1WithRSAEncryption + c7:61:45:a8:8a:71:b9:be:34:e9:21:7b:21:cd:56:13:98:d5: + 30:63:e9:18:aa:4b:92:15:bf:0b:1d:bb:ec:92:69:c5:2e:c3: + 61:8b:e8:30:45:cb:10:46:c1:73:38:5c:8b:19:d2:2b:f3:40: + eb:7c:72:b3:2e:1e:27:e3:75:95:8a:1c:9b:2e:c4:95:05:86: + 72:d0:55:f4:a1:92:52:79:5c:db:f4:f8:dc:e5:d7:12:b1:40: + c7:3c:86:e4:31:65:4a:ca:37:c6:de:76:57:19:69:4c:46:69: + fc:2a:ad:16:37:7a:93:ac:f7:21:4b:2d:fb:eb:a9:50:cb:c1: + d1:40:08:da:03:69:87:a7:37:5e:55:c1:c5:ed:c4:e3:8e:0c: + 26:97:9b:5c:57:4b:72:e3:f2:03:05:d0:02:3b:26:03:40:90: + 9e:be:0b:5b:49:0c:78:f1:d5:4c:55:29:e0:f6:fd:4c:03:a9: + 54:02:32:d1:57:5a:85:ac:43:ed:5b:3b:16:5f:a0:bf:35:db: + 4b:9e:7b:e8:ff:e7:0d:3c:3b:a8:9b:49:41:46:f5:73:4e:ff: + 92:65:21:83:13:55:71:eb:49:3c:7f:88:1a:c2:12:28:25:a1: + 46:4b:41:37:97:7f:ec:8e:f1:d4:a1:96:c2:20:b6:5e:ad:a9: + 1c:1e:11:a0 + +BelSign Object Publishing CA +============================ +MD5 Fingerprint: 8A:02:F8:DF:B8:E1:84:9F:5A:C2:60:24:65:D1:73:FB +PEM Data: +-----BEGIN CERTIFICATE----- +MIIDAzCCAmygAwIBAgIBATANBgkqhkiG9w0BAQQFADCBuzELMAkGA1UEBhMCQkUx +ETAPBgNVBAcTCEJydXNzZWxzMRMwEQYDVQQKEwpCZWxTaWduIE5WMTgwNgYDVQQL +Ey9CZWxTaWduIE9iamVjdCBQdWJsaXNoaW5nIENlcnRpZmljYXRlIEF1dGhvcml0 +eTElMCMGA1UEAxMcQmVsU2lnbiBPYmplY3QgUHVibGlzaGluZyBDQTEjMCEGCSqG +SIb3DQEJARYUd2VibWFzdGVyQGJlbHNpZ24uYmUwHhcNOTcwOTE5MjIwMzAwWhcN +MDcwOTE5MjIwMzAwWjCBuzELMAkGA1UEBhMCQkUxETAPBgNVBAcTCEJydXNzZWxz +MRMwEQYDVQQKEwpCZWxTaWduIE5WMTgwNgYDVQQLEy9CZWxTaWduIE9iamVjdCBQ +dWJsaXNoaW5nIENlcnRpZmljYXRlIEF1dGhvcml0eTElMCMGA1UEAxMcQmVsU2ln +biBPYmplY3QgUHVibGlzaGluZyBDQTEjMCEGCSqGSIb3DQEJARYUd2VibWFzdGVy +QGJlbHNpZ24uYmUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMQuH7a/7oJA +3fm3LkHVngWxWtAmfGJVA5v8y2HeS+/+6Jn+h7mIz5DaDwk8dt8Xl7bLPyVF/bS8 +WAC+sFq2FIeP7mdkrR2Ig7tnn2VhAFgIgFCfgMkx9iqQHC33SmwQ9iNDXTgJYIhX +As0WbBj8zfuSKnfQnpOjXYhk0Mj4XVRRAgMBAAGjFTATMBEGCWCGSAGG+EIBAQQE +AwIABzANBgkqhkiG9w0BAQQFAAOBgQBjdhd8lvBTpV0BHFPOKcJ+daxMDaIIc7Rq +Mf0CBhSZ3FQEpL/IloafMUMyJVf2hfYluze+oXkjyVcGJXFrRU/49AJAFoIir1Tq +Mij2De6ZuksIUQ9uhiMhTC0liIHELg7xEyw4ipUCJMM6lWPkk45IuwhHcl+u5jpa +R9Zxxp6aUg== +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=BE, L=Brussels, O=BelSign NV, OU=BelSign Object Publishing Certificate Authority, CN=BelSign Object Publishing CA/Email=webmaster@belsign.be + Validity + Not Before: Sep 19 22:03:00 1997 GMT + Not After : Sep 19 22:03:00 2007 GMT + Subject: C=BE, L=Brussels, O=BelSign NV, OU=BelSign Object Publishing Certificate Authority, CN=BelSign Object Publishing CA/Email=webmaster@belsign.be + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:c4:2e:1f:b6:bf:ee:82:40:dd:f9:b7:2e:41:d5: + 9e:05:b1:5a:d0:26:7c:62:55:03:9b:fc:cb:61:de: + 4b:ef:fe:e8:99:fe:87:b9:88:cf:90:da:0f:09:3c: + 76:df:17:97:b6:cb:3f:25:45:fd:b4:bc:58:00:be: + b0:5a:b6:14:87:8f:ee:67:64:ad:1d:88:83:bb:67: + 9f:65:61:00:58:08:80:50:9f:80:c9:31:f6:2a:90: + 1c:2d:f7:4a:6c:10:f6:23:43:5d:38:09:60:88:57: + 02:cd:16:6c:18:fc:cd:fb:92:2a:77:d0:9e:93:a3: + 5d:88:64:d0:c8:f8:5d:54:51 + Exponent: 65537 (0x10001) + X509v3 extensions: + Netscape Cert Type: + SSL CA, S/MIME CA, Object Signing CA + Signature Algorithm: md5WithRSAEncryption + 63:76:17:7c:96:f0:53:a5:5d:01:1c:53:ce:29:c2:7e:75:ac: + 4c:0d:a2:08:73:b4:6a:31:fd:02:06:14:99:dc:54:04:a4:bf: + c8:96:86:9f:31:43:32:25:57:f6:85:f6:25:bb:37:be:a1:79: + 23:c9:57:06:25:71:6b:45:4f:f8:f4:02:40:16:82:22:af:54: + ea:32:28:f6:0d:ee:99:ba:4b:08:51:0f:6e:86:23:21:4c:2d: + 25:88:81:c4:2e:0e:f1:13:2c:38:8a:95:02:24:c3:3a:95:63: + e4:93:8e:48:bb:08:47:72:5f:ae:e6:3a:5a:47:d6:71:c6:9e: + 9a:52 + +BelSign Secure Server CA +======================== +MD5 Fingerprint: 3D:5E:82:C6:D9:AD:D9:8B:93:6B:0C:10:B9:49:0A:B1 +PEM Data: +-----BEGIN CERTIFICATE----- +MIIC8zCCAlygAwIBAgIBATANBgkqhkiG9w0BAQQFADCBszELMAkGA1UEBhMCQkUx +ETAPBgNVBAcTCEJydXNzZWxzMRMwEQYDVQQKEwpCZWxTaWduIE5WMTQwMgYDVQQL +EytCZWxTaWduIFNlY3VyZSBTZXJ2ZXIgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MSEw +HwYDVQQDExhCZWxTaWduIFNlY3VyZSBTZXJ2ZXIgQ0ExIzAhBgkqhkiG9w0BCQEW +FHdlYm1hc3RlckBiZWxzaWduLmJlMB4XDTk3MDcxNjIyMDA1NFoXDTA3MDcxNjIy +MDA1NFowgbMxCzAJBgNVBAYTAkJFMREwDwYDVQQHEwhCcnVzc2VsczETMBEGA1UE +ChMKQmVsU2lnbiBOVjE0MDIGA1UECxMrQmVsU2lnbiBTZWN1cmUgU2VydmVyIENl +cnRpZmljYXRlIEF1dGhvcml0eTEhMB8GA1UEAxMYQmVsU2lnbiBTZWN1cmUgU2Vy +dmVyIENBMSMwIQYJKoZIhvcNAQkBFhR3ZWJtYXN0ZXJAYmVsc2lnbi5iZTCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1gESeJL4BEJ/yccig/x8R3AwK0kLPjZA +kCjaIXODU/LE0RZAwFP/rqbGJLMnbaWzPTl3XagG9ubpvGMRTgZlcAqdk/miQIt/ +SoQOjRax1swIZBIM4ChLyKWEkBf7EUYu1qeFGMsYrmOasFgG9ADP+MQJGjUMofnu +Sv1t3v4mpTsCAwEAAaMVMBMwEQYJYIZIAYb4QgEBBAQDAgCgMA0GCSqGSIb3DQEB +BAUAA4GBAGw9mcMF4h3K5S2qaIWLQDEgZhNo5lg6idCNdbLFYth9go/32TKBd/Y1 +W4UpzmeyubwrGXjP84f9RvGVdbIJVwMwwXrNckdxgMp9ncllPEcRIn36BwsoeKGT +6AVFSOIyMko96FMcELfHc4wHUOH5yStTQfWDjeUJOUqOA2KqQGOL +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=BE, L=Brussels, O=BelSign NV, OU=BelSign Secure Server Certificate Authority, CN=BelSign Secure Server CA/Email=webmaster@belsign.be + Validity + Not Before: Jul 16 22:00:54 1997 GMT + Not After : Jul 16 22:00:54 2007 GMT + Subject: C=BE, L=Brussels, O=BelSign NV, OU=BelSign Secure Server Certificate Authority, CN=BelSign Secure Server CA/Email=webmaster@belsign.be + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:d6:01:12:78:92:f8:04:42:7f:c9:c7:22:83:fc: + 7c:47:70:30:2b:49:0b:3e:36:40:90:28:da:21:73: + 83:53:f2:c4:d1:16:40:c0:53:ff:ae:a6:c6:24:b3: + 27:6d:a5:b3:3d:39:77:5d:a8:06:f6:e6:e9:bc:63: + 11:4e:06:65:70:0a:9d:93:f9:a2:40:8b:7f:4a:84: + 0e:8d:16:b1:d6:cc:08:64:12:0c:e0:28:4b:c8:a5: + 84:90:17:fb:11:46:2e:d6:a7:85:18:cb:18:ae:63: + 9a:b0:58:06:f4:00:cf:f8:c4:09:1a:35:0c:a1:f9: + ee:4a:fd:6d:de:fe:26:a5:3b + Exponent: 65537 (0x10001) + X509v3 extensions: + Netscape Cert Type: + SSL Client, S/MIME + Signature Algorithm: md5WithRSAEncryption + 6c:3d:99:c3:05:e2:1d:ca:e5:2d:aa:68:85:8b:40:31:20:66: + 13:68:e6:58:3a:89:d0:8d:75:b2:c5:62:d8:7d:82:8f:f7:d9: + 32:81:77:f6:35:5b:85:29:ce:67:b2:b9:bc:2b:19:78:cf:f3: + 87:fd:46:f1:95:75:b2:09:57:03:30:c1:7a:cd:72:47:71:80: + ca:7d:9d:c9:65:3c:47:11:22:7d:fa:07:0b:28:78:a1:93:e8: + 05:45:48:e2:32:32:4a:3d:e8:53:1c:10:b7:c7:73:8c:07:50: + e1:f9:c9:2b:53:41:f5:83:8d:e5:09:39:4a:8e:03:62:aa:40: + 63:8b + +Deutsche Telekom AG Root CA +=========================== +MD5 Fingerprint: 77:DE:04:94:77:D0:0C:5F:A7:B1:F4:30:18:87:FB:55 +PEM Data: +-----BEGIN CERTIFICATE----- +MIICjjCCAfegAwIBAgIBBjANBgkqhkiG9w0BAQQFADBtMQswCQYDVQQGEwJERTEc +MBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEdMBsGA1UECxMUVGVsZVNlYyBU +cnVzdCBDZW50ZXIxITAfBgNVBAMTGERldXRzY2hlIFRlbGVrb20gUm9vdCBDQTAe +Fw05ODEyMDkwOTExMDBaFw0wNDEyMDkyMzU5MDBaMG0xCzAJBgNVBAYTAkRFMRww +GgYDVQQKExNEZXV0c2NoZSBUZWxla29tIEFHMR0wGwYDVQQLExRUZWxlU2VjIFRy +dXN0IENlbnRlcjEhMB8GA1UEAxMYRGV1dHNjaGUgVGVsZWtvbSBSb290IENBMIGf +MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDdBSz5BbO5EtdpcffqVjAIVxRDe7sa +nG0vV2HX4vVEa+42QZb2ZM7hwbK5pBQEmFDocPiONZp9ScFhHVmu2gYYlX2tzuyp +vtEYD0CRdiqj5f3+iRX0V/fgVdp1rQD0LME1zLRDJlViRC4BJZyKW/DB0AA1eP41 +3pRAZHiDocw5iQIDAQABoz4wPDAPBgNVHRMECDAGAQH/AgEFMA4GA1UdDwEB/wQE +AwIBBjAZBgNVHQ4EEgQQLIdZH4sTgLL5hp0+En5YljANBgkqhkiG9w0BAQQFAAOB +gQAP/nO1B4hvoAuJ6spQH5TelCsLJ15P9RyVJtqMllStGZE3Q12ryYuzzW+YOT3t +3TXjcbftE5OD6IblKTMTE7w1e/0oL3BZ1dO0jSgTWTvI1XT5RcIHYKq4GFT5pWj/ +1wXVj7YFMS5BSvQQH2BHGguLGU2SVyDS71AZ6M3QcLy8Ng== +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: 6 (0x6) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=DE, O=Deutsche Telekom AG, OU=TeleSec Trust Center, CN=Deutsche Telekom Root CA + Validity + Not Before: Dec 9 09:11:00 1998 GMT + Not After : Dec 9 23:59:00 2004 GMT + Subject: C=DE, O=Deutsche Telekom AG, OU=TeleSec Trust Center, CN=Deutsche Telekom Root CA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:dd:05:2c:f9:05:b3:b9:12:d7:69:71:f7:ea:56: + 30:08:57:14:43:7b:bb:1a:9c:6d:2f:57:61:d7:e2: + f5:44:6b:ee:36:41:96:f6:64:ce:e1:c1:b2:b9:a4: + 14:04:98:50:e8:70:f8:8e:35:9a:7d:49:c1:61:1d: + 59:ae:da:06:18:95:7d:ad:ce:ec:a9:be:d1:18:0f: + 40:91:76:2a:a3:e5:fd:fe:89:15:f4:57:f7:e0:55: + da:75:ad:00:f4:2c:c1:35:cc:b4:43:26:55:62:44: + 2e:01:25:9c:8a:5b:f0:c1:d0:00:35:78:fe:35:de: + 94:40:64:78:83:a1:cc:39:89 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:TRUE, pathlen:5 + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + 2C:87:59:1F:8B:13:80:B2:F9:86:9D:3E:12:7E:58:96 + Signature Algorithm: md5WithRSAEncryption + 0f:fe:73:b5:07:88:6f:a0:0b:89:ea:ca:50:1f:94:de:94:2b: + 0b:27:5e:4f:f5:1c:95:26:da:8c:96:54:ad:19:91:37:43:5d: + ab:c9:8b:b3:cd:6f:98:39:3d:ed:dd:35:e3:71:b7:ed:13:93: + 83:e8:86:e5:29:33:13:13:bc:35:7b:fd:28:2f:70:59:d5:d3: + b4:8d:28:13:59:3b:c8:d5:74:f9:45:c2:07:60:aa:b8:18:54: + f9:a5:68:ff:d7:05:d5:8f:b6:05:31:2e:41:4a:f4:10:1f:60: + 47:1a:0b:8b:19:4d:92:57:20:d2:ef:50:19:e8:cd:d0:70:bc: + bc:36 + +Digital Signature Trust Co. Global CA 1 +======================================= +MD5 Fingerprint: 25:7A:BA:83:2E:B6:A2:0B:DA:FE:F5:02:0F:08:D7:AD +PEM Data: +-----BEGIN CERTIFICATE----- +MIIDKTCCApKgAwIBAgIENnAVljANBgkqhkiG9w0BAQUFADBGMQswCQYDVQQGEwJV +UzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMREwDwYDVQQL +EwhEU1RDQSBFMTAeFw05ODEyMTAxODEwMjNaFw0xODEyMTAxODQwMjNaMEYxCzAJ +BgNVBAYTAlVTMSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4x +ETAPBgNVBAsTCERTVENBIEUxMIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCg +bIGpzzQeJN3+hijM3oMv+V7UQtLodGBmE5gGHKlREmlvMVW5SXIACH7TpWJENySZ +j9mDSI+ZbZUTu0M7LklOiDfBu1h//uG9+LthzfNHwJmm8fOR6Hh8AMthyUQncWlV +Sn5JTe2io74CTADKAqjuAQIxZA9SLRN0dja1erQtcQIBA6OCASQwggEgMBEGCWCG +SAGG+EIBAQQEAwIABzBoBgNVHR8EYTBfMF2gW6BZpFcwVTELMAkGA1UEBhMCVVMx +JDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjERMA8GA1UECxMI +RFNUQ0EgRTExDTALBgNVBAMTBENSTDEwKwYDVR0QBCQwIoAPMTk5ODEyMTAxODEw +MjNagQ8yMDE4MTIxMDE4MTAyM1owCwYDVR0PBAQDAgEGMB8GA1UdIwQYMBaAFGp5 +fpFpRhgTCgJ3pVlbYJglDqL4MB0GA1UdDgQWBBRqeX6RaUYYEwoCd6VZW2CYJQ6i ++DAMBgNVHRMEBTADAQH/MBkGCSqGSIb2fQdBAAQMMAobBFY0LjADAgSQMA0GCSqG +SIb3DQEBBQUAA4GBACIS2Hod3IEGtgllsofIH160L+nEHvI8wbsEkBFKg05+k7lN +QseSJqBcNJo4cvj9axY+IO6CizEqkzaFI4iKPANo08kJD038bKTaKHKTDomAsH3+ +gG9lbRgzl4vCa4nuYD3Im+9/KzJic5PLPON74nZ4RbyhkwS7hp86W0N6w4pl +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: 913315222 (0x36701596) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=Digital Signature Trust Co., OU=DSTCA E1 + Validity + Not Before: Dec 10 18:10:23 1998 GMT + Not After : Dec 10 18:40:23 2018 GMT + Subject: C=US, O=Digital Signature Trust Co., OU=DSTCA E1 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:a0:6c:81:a9:cf:34:1e:24:dd:fe:86:28:cc:de: + 83:2f:f9:5e:d4:42:d2:e8:74:60:66:13:98:06:1c: + a9:51:12:69:6f:31:55:b9:49:72:00:08:7e:d3:a5: + 62:44:37:24:99:8f:d9:83:48:8f:99:6d:95:13:bb: + 43:3b:2e:49:4e:88:37:c1:bb:58:7f:fe:e1:bd:f8: + bb:61:cd:f3:47:c0:99:a6:f1:f3:91:e8:78:7c:00: + cb:61:c9:44:27:71:69:55:4a:7e:49:4d:ed:a2:a3: + be:02:4c:00:ca:02:a8:ee:01:02:31:64:0f:52:2d: + 13:74:76:36:b5:7a:b4:2d:71 + Exponent: 3 (0x3) + X509v3 extensions: + Netscape Cert Type: + SSL CA, S/MIME CA, Object Signing CA + X509v3 CRL Distribution Points: + DirName:/C=US/O=Digital Signature Trust Co./OU=DSTCA E1/CN=CRL1 + + X509v3 Private Key Usage Period: + Not Before: Dec 10 18:10:23 1998 GMT, Not After: Dec 10 18:10:23 2018 GMT + X509v3 Key Usage: + Certificate Sign, CRL Sign + X509v3 Authority Key Identifier: + keyid:6A:79:7E:91:69:46:18:13:0A:02:77:A5:59:5B:60:98:25:0E:A2:F8 + + X509v3 Subject Key Identifier: + 6A:79:7E:91:69:46:18:13:0A:02:77:A5:59:5B:60:98:25:0E:A2:F8 + X509v3 Basic Constraints: + CA:TRUE + 1.2.840.113533.7.65.0: + 0 +..V4.0.... + Signature Algorithm: sha1WithRSAEncryption + 22:12:d8:7a:1d:dc:81:06:b6:09:65:b2:87:c8:1f:5e:b4:2f: + e9:c4:1e:f2:3c:c1:bb:04:90:11:4a:83:4e:7e:93:b9:4d:42: + c7:92:26:a0:5c:34:9a:38:72:f8:fd:6b:16:3e:20:ee:82:8b: + 31:2a:93:36:85:23:88:8a:3c:03:68:d3:c9:09:0f:4d:fc:6c: + a4:da:28:72:93:0e:89:80:b0:7d:fe:80:6f:65:6d:18:33:97: + 8b:c2:6b:89:ee:60:3d:c8:9b:ef:7f:2b:32:62:73:93:cb:3c: + e3:7b:e2:76:78:45:bc:a1:93:04:bb:86:9f:3a:5b:43:7a:c3: + 8a:65 + +Digital Signature Trust Co. Global CA 2 +======================================= +MD5 Fingerprint: 6C:C9:A7:6E:47:F1:0C:E3:53:3B:78:4C:4D:C2:6A:C5 +PEM Data: +-----BEGIN CERTIFICATE----- +MIID2DCCAsACEQDQHkCLAAACfAAAAAIAAAABMA0GCSqGSIb3DQEBBQUAMIGpMQsw +CQYDVQQGEwJ1czENMAsGA1UECBMEVXRhaDEXMBUGA1UEBxMOU2FsdCBMYWtlIENp +dHkxJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjERMA8GA1UE +CxMIRFNUQ0EgWDExFjAUBgNVBAMTDURTVCBSb290Q0EgWDExITAfBgkqhkiG9w0B +CQEWEmNhQGRpZ3NpZ3RydXN0LmNvbTAeFw05ODEyMDExODE4NTVaFw0wODExMjgx +ODE4NTVaMIGpMQswCQYDVQQGEwJ1czENMAsGA1UECBMEVXRhaDEXMBUGA1UEBxMO +U2FsdCBMYWtlIENpdHkxJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0 +IENvLjERMA8GA1UECxMIRFNUQ0EgWDExFjAUBgNVBAMTDURTVCBSb290Q0EgWDEx +ITAfBgkqhkiG9w0BCQEWEmNhQGRpZ3NpZ3RydXN0LmNvbTCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBANLGJrbnpT3BxGjVUG9TxW9JEwm4ryxIjRRqoxdf +WvnTLnUv2Chi0ZMv/E3Uq4flCMeZ55I/db3rJbQVwZsZPdJEjdd0IG03Ao9pk1uK +xBmd9LIO/BZsubEFkoPRhSxglD5FVaDZqwgh5mDoO3TymVBRaNADLbGAvqPYUrBE +zUNKcI5YhZXhTizWLUFv1oTnyJhEykfbLCSlaSbPa7gnYsP0yXqSI+0TZ4KuRS5F +5X5yP4WdlGIQ5jyRoa13AOAV7POEgHJ6jm5gl8ckWRA0g1vhpaRptlc1HHhZxtMv +OnNn7pTKBBMFYgZwI7P0fO5F2WQLW0mqpEPOJsREEmy43XkCAwEAATANBgkqhkiG +9w0BAQUFAAOCAQEAojeyP2n714Z5VEkxlTMr89EJFEliYIalsBHiUMIdBlc+Legz +ZL6bqq1fG03UmZWii5rJYnK1aerZWKs17RWiQ9a2vAd5ZWRzfdd5ynvVWlHG4VME +lo04z6MXrDlxawHDi1M8Y+nuecDkvpIyZHqzH5eUYr3qsiAVlfuX8ngvYzZAOONG +Dx3drJXK50uQe7FLqdTF65raqtWjlBRGjS0f8zrWkzr2Pnn86Oawde3uPclwx12q +gUtGJRzHbBXjlU4PqjI3lAoXJJIThFjSY28r9+ZbYgsTF7ANUkz+/m9c4pFuHf2k +Ytdo+o56T9II2pPc8JIRetDccpMMc5NihWjQ9A== +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 1 (0x0) + Serial Number: + d0:1e:40:8b:00:00:02:7c:00:00:00:02:00:00:00:01 + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=us, ST=Utah, L=Salt Lake City, O=Digital Signature Trust Co., OU=DSTCA X1, CN=DST RootCA X1/Email=ca@digsigtrust.com + Validity + Not Before: Dec 1 18:18:55 1998 GMT + Not After : Nov 28 18:18:55 2008 GMT + Subject: C=us, ST=Utah, L=Salt Lake City, O=Digital Signature Trust Co., OU=DSTCA X1, CN=DST RootCA X1/Email=ca@digsigtrust.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:d2:c6:26:b6:e7:a5:3d:c1:c4:68:d5:50:6f:53: + c5:6f:49:13:09:b8:af:2c:48:8d:14:6a:a3:17:5f: + 5a:f9:d3:2e:75:2f:d8:28:62:d1:93:2f:fc:4d:d4: + ab:87:e5:08:c7:99:e7:92:3f:75:bd:eb:25:b4:15: + c1:9b:19:3d:d2:44:8d:d7:74:20:6d:37:02:8f:69: + 93:5b:8a:c4:19:9d:f4:b2:0e:fc:16:6c:b9:b1:05: + 92:83:d1:85:2c:60:94:3e:45:55:a0:d9:ab:08:21: + e6:60:e8:3b:74:f2:99:50:51:68:d0:03:2d:b1:80: + be:a3:d8:52:b0:44:cd:43:4a:70:8e:58:85:95:e1: + 4e:2c:d6:2d:41:6f:d6:84:e7:c8:98:44:ca:47:db: + 2c:24:a5:69:26:cf:6b:b8:27:62:c3:f4:c9:7a:92: + 23:ed:13:67:82:ae:45:2e:45:e5:7e:72:3f:85:9d: + 94:62:10:e6:3c:91:a1:ad:77:00:e0:15:ec:f3:84: + 80:72:7a:8e:6e:60:97:c7:24:59:10:34:83:5b:e1: + a5:a4:69:b6:57:35:1c:78:59:c6:d3:2f:3a:73:67: + ee:94:ca:04:13:05:62:06:70:23:b3:f4:7c:ee:45: + d9:64:0b:5b:49:aa:a4:43:ce:26:c4:44:12:6c:b8: + dd:79 + Exponent: 65537 (0x10001) + Signature Algorithm: sha1WithRSAEncryption + a2:37:b2:3f:69:fb:d7:86:79:54:49:31:95:33:2b:f3:d1:09: + 14:49:62:60:86:a5:b0:11:e2:50:c2:1d:06:57:3e:2d:e8:33: + 64:be:9b:aa:ad:5f:1b:4d:d4:99:95:a2:8b:9a:c9:62:72:b5: + 69:ea:d9:58:ab:35:ed:15:a2:43:d6:b6:bc:07:79:65:64:73: + 7d:d7:79:ca:7b:d5:5a:51:c6:e1:53:04:96:8d:38:cf:a3:17: + ac:39:71:6b:01:c3:8b:53:3c:63:e9:ee:79:c0:e4:be:92:32: + 64:7a:b3:1f:97:94:62:bd:ea:b2:20:15:95:fb:97:f2:78:2f: + 63:36:40:38:e3:46:0f:1d:dd:ac:95:ca:e7:4b:90:7b:b1:4b: + a9:d4:c5:eb:9a:da:aa:d5:a3:94:14:46:8d:2d:1f:f3:3a:d6: + 93:3a:f6:3e:79:fc:e8:e6:b0:75:ed:ee:3d:c9:70:c7:5d:aa: + 81:4b:46:25:1c:c7:6c:15:e3:95:4e:0f:aa:32:37:94:0a:17: + 24:92:13:84:58:d2:63:6f:2b:f7:e6:5b:62:0b:13:17:b0:0d: + 52:4c:fe:fe:6f:5c:e2:91:6e:1d:fd:a4:62:d7:68:fa:8e:7a: + 4f:d2:08:da:93:dc:f0:92:11:7a:d0:dc:72:93:0c:73:93:62: + 85:68:d0:f4 + +Digital Signature Trust Co. Global CA 3 +======================================= +MD5 Fingerprint: 93:C2:8E:11:7B:D4:F3:03:19:BD:28:75:13:4A:45:4A +PEM Data: +-----BEGIN CERTIFICATE----- +MIIDKTCCApKgAwIBAgIENm7TzjANBgkqhkiG9w0BAQUFADBGMQswCQYDVQQGEwJV +UzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMREwDwYDVQQL +EwhEU1RDQSBFMjAeFw05ODEyMDkxOTE3MjZaFw0xODEyMDkxOTQ3MjZaMEYxCzAJ +BgNVBAYTAlVTMSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4x +ETAPBgNVBAsTCERTVENBIEUyMIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQC/ +k48Xku8zExjrEH9OFr//Bo8qhbxe+SSmJIi2A7fBw18DW9Fvrn5C6mYjuGODVvso +LeE4i7TuqAHhzhy2iCoiRoX7n6dwqUcUP87eZfCocfdPJmyMvMa1795JJ/9IKn3o +TQPMx7JSxhcxEzu1TdvIxPbDDyQq2gyd55FbgM2UnQIBA6OCASQwggEgMBEGCWCG +SAGG+EIBAQQEAwIABzBoBgNVHR8EYTBfMF2gW6BZpFcwVTELMAkGA1UEBhMCVVMx +JDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjERMA8GA1UECxMI +RFNUQ0EgRTIxDTALBgNVBAMTBENSTDEwKwYDVR0QBCQwIoAPMTk5ODEyMDkxOTE3 +MjZagQ8yMDE4MTIwOTE5MTcyNlowCwYDVR0PBAQDAgEGMB8GA1UdIwQYMBaAFB6C +TShlgDzJQW6sNS5ay97u+DlbMB0GA1UdDgQWBBQegk0oZYA8yUFurDUuWsve7vg5 +WzAMBgNVHRMEBTADAQH/MBkGCSqGSIb2fQdBAAQMMAobBFY0LjADAgSQMA0GCSqG +SIb3DQEBBQUAA4GBAEeNg61i8tuwnkUiBbmi1gMOOHLnnvx75pO2mqWilMg0HZHR +xdf0CiUPPXiBng+xZ8SQTGPdXqfiup/1902lMXucKS1M/mQ+7LZT/uqb7YLbdHVL +B3luHtgZg3Pe9T7Qtd7nS2h9Qy4qIOF+oHhEngj1mPnHfxsb1gYgAlihw6ID +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: 913232846 (0x366ed3ce) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=Digital Signature Trust Co., OU=DSTCA E2 + Validity + Not Before: Dec 9 19:17:26 1998 GMT + Not After : Dec 9 19:47:26 2018 GMT + Subject: C=US, O=Digital Signature Trust Co., OU=DSTCA E2 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:bf:93:8f:17:92:ef:33:13:18:eb:10:7f:4e:16: + bf:ff:06:8f:2a:85:bc:5e:f9:24:a6:24:88:b6:03: + b7:c1:c3:5f:03:5b:d1:6f:ae:7e:42:ea:66:23:b8: + 63:83:56:fb:28:2d:e1:38:8b:b4:ee:a8:01:e1:ce: + 1c:b6:88:2a:22:46:85:fb:9f:a7:70:a9:47:14:3f: + ce:de:65:f0:a8:71:f7:4f:26:6c:8c:bc:c6:b5:ef: + de:49:27:ff:48:2a:7d:e8:4d:03:cc:c7:b2:52:c6: + 17:31:13:3b:b5:4d:db:c8:c4:f6:c3:0f:24:2a:da: + 0c:9d:e7:91:5b:80:cd:94:9d + Exponent: 3 (0x3) + X509v3 extensions: + Netscape Cert Type: + SSL CA, S/MIME CA, Object Signing CA + X509v3 CRL Distribution Points: + DirName:/C=US/O=Digital Signature Trust Co./OU=DSTCA E2/CN=CRL1 + + X509v3 Private Key Usage Period: + Not Before: Dec 9 19:17:26 1998 GMT, Not After: Dec 9 19:17:26 2018 GMT + X509v3 Key Usage: + Certificate Sign, CRL Sign + X509v3 Authority Key Identifier: + keyid:1E:82:4D:28:65:80:3C:C9:41:6E:AC:35:2E:5A:CB:DE:EE:F8:39:5B + + X509v3 Subject Key Identifier: + 1E:82:4D:28:65:80:3C:C9:41:6E:AC:35:2E:5A:CB:DE:EE:F8:39:5B + X509v3 Basic Constraints: + CA:TRUE + 1.2.840.113533.7.65.0: + 0 +..V4.0.... + Signature Algorithm: sha1WithRSAEncryption + 47:8d:83:ad:62:f2:db:b0:9e:45:22:05:b9:a2:d6:03:0e:38: + 72:e7:9e:fc:7b:e6:93:b6:9a:a5:a2:94:c8:34:1d:91:d1:c5: + d7:f4:0a:25:0f:3d:78:81:9e:0f:b1:67:c4:90:4c:63:dd:5e: + a7:e2:ba:9f:f5:f7:4d:a5:31:7b:9c:29:2d:4c:fe:64:3e:ec: + b6:53:fe:ea:9b:ed:82:db:74:75:4b:07:79:6e:1e:d8:19:83: + 73:de:f5:3e:d0:b5:de:e7:4b:68:7d:43:2e:2a:20:e1:7e:a0: + 78:44:9e:08:f5:98:f9:c7:7f:1b:1b:d6:06:20:02:58:a1:c3: + a2:03 + +Digital Signature Trust Co. Global CA 4 +======================================= +MD5 Fingerprint: CD:3B:3D:62:5B:09:B8:09:36:87:9E:12:2F:71:64:BA +PEM Data: +-----BEGIN CERTIFICATE----- +MIID2DCCAsACEQDQHkCLAAB3bQAAAAEAAAAEMA0GCSqGSIb3DQEBBQUAMIGpMQsw +CQYDVQQGEwJ1czENMAsGA1UECBMEVXRhaDEXMBUGA1UEBxMOU2FsdCBMYWtlIENp +dHkxJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjERMA8GA1UE +CxMIRFNUQ0EgWDIxFjAUBgNVBAMTDURTVCBSb290Q0EgWDIxITAfBgkqhkiG9w0B +CQEWEmNhQGRpZ3NpZ3RydXN0LmNvbTAeFw05ODExMzAyMjQ2MTZaFw0wODExMjcy +MjQ2MTZaMIGpMQswCQYDVQQGEwJ1czENMAsGA1UECBMEVXRhaDEXMBUGA1UEBxMO +U2FsdCBMYWtlIENpdHkxJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0 +IENvLjERMA8GA1UECxMIRFNUQ0EgWDIxFjAUBgNVBAMTDURTVCBSb290Q0EgWDIx +ITAfBgkqhkiG9w0BCQEWEmNhQGRpZ3NpZ3RydXN0LmNvbTCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBANx18IzAdZaawGIfJvfE4Zrq4FZzW5nNAUSoCLbV +p9oaBBg5kkp4o4HC9Xd6ULRw/5qrxsfKboNPQpj7Jgva3G3WqZlVUmfpKAOS3OWw +BZoPFflrWXJW8vo5/Kpo7g8fEIMv/J36F5bdguPmRX3AS4BEH+0s4IT9kVySVGkl +5WJp3OXuAFK9MwutdQKFp2RQLcUZGTDAJtvJ0/0uma1ZtQtN1EGuhUhDWdy3qOKi +3sOP17ihYqZoUFLkzzGnlIXan0YyF1bl8utmPRL/Q9uY73fPy4GNNLHGUEom0eQ+ +QVCvbK4iNC7Va26Dunm4dmVI2gkpZGMiuftHdoWMhkTLCdsCAwEAATANBgkqhkiG +9w0BAQUFAAOCAQEAtTYOXeFhKFoRZcA/gwN5Tb4opgsHAlKFzfiR0BBstWogWxyQ +2TA8xkieil5k+aFxd+8EJx8H6+Qm93N0yUQYGmbT4EOvkTvRyyzYdFQ6HE3K1GjN +I3wdEJ5F6fYAbqbNGf9PLCmPV03Ed5K+4EwJ+11EhmYhqLkyolbV6YyDfFk/xPEL +553snr2cGA4+wjl5KLcDDQjLxufZATdQEOzMYRZA1K8xdHv8PzGn0EdzMzkbzE5q +10mDEQb+64JYMzJM8FasHpwvVpp7wUocpf1VNs78lk30sPDst2yC7S8xmUJMqbIN +uBVd8d+6ybVK1GSYsyapMMj9puyrliGtf8J4tg== +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 1 (0x0) + Serial Number: + d0:1e:40:8b:00:00:77:6d:00:00:00:01:00:00:00:04 + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=us, ST=Utah, L=Salt Lake City, O=Digital Signature Trust Co., OU=DSTCA X2, CN=DST RootCA X2/Email=ca@digsigtrust.com + Validity + Not Before: Nov 30 22:46:16 1998 GMT + Not After : Nov 27 22:46:16 2008 GMT + Subject: C=us, ST=Utah, L=Salt Lake City, O=Digital Signature Trust Co., OU=DSTCA X2, CN=DST RootCA X2/Email=ca@digsigtrust.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:dc:75:f0:8c:c0:75:96:9a:c0:62:1f:26:f7:c4: + e1:9a:ea:e0:56:73:5b:99:cd:01:44:a8:08:b6:d5: + a7:da:1a:04:18:39:92:4a:78:a3:81:c2:f5:77:7a: + 50:b4:70:ff:9a:ab:c6:c7:ca:6e:83:4f:42:98:fb: + 26:0b:da:dc:6d:d6:a9:99:55:52:67:e9:28:03:92: + dc:e5:b0:05:9a:0f:15:f9:6b:59:72:56:f2:fa:39: + fc:aa:68:ee:0f:1f:10:83:2f:fc:9d:fa:17:96:dd: + 82:e3:e6:45:7d:c0:4b:80:44:1f:ed:2c:e0:84:fd: + 91:5c:92:54:69:25:e5:62:69:dc:e5:ee:00:52:bd: + 33:0b:ad:75:02:85:a7:64:50:2d:c5:19:19:30:c0: + 26:db:c9:d3:fd:2e:99:ad:59:b5:0b:4d:d4:41:ae: + 85:48:43:59:dc:b7:a8:e2:a2:de:c3:8f:d7:b8:a1: + 62:a6:68:50:52:e4:cf:31:a7:94:85:da:9f:46:32: + 17:56:e5:f2:eb:66:3d:12:ff:43:db:98:ef:77:cf: + cb:81:8d:34:b1:c6:50:4a:26:d1:e4:3e:41:50:af: + 6c:ae:22:34:2e:d5:6b:6e:83:ba:79:b8:76:65:48: + da:09:29:64:63:22:b9:fb:47:76:85:8c:86:44:cb: + 09:db + Exponent: 65537 (0x10001) + Signature Algorithm: sha1WithRSAEncryption + b5:36:0e:5d:e1:61:28:5a:11:65:c0:3f:83:03:79:4d:be:28: + a6:0b:07:02:52:85:cd:f8:91:d0:10:6c:b5:6a:20:5b:1c:90: + d9:30:3c:c6:48:9e:8a:5e:64:f9:a1:71:77:ef:04:27:1f:07: + eb:e4:26:f7:73:74:c9:44:18:1a:66:d3:e0:43:af:91:3b:d1: + cb:2c:d8:74:54:3a:1c:4d:ca:d4:68:cd:23:7c:1d:10:9e:45: + e9:f6:00:6e:a6:cd:19:ff:4f:2c:29:8f:57:4d:c4:77:92:be: + e0:4c:09:fb:5d:44:86:66:21:a8:b9:32:a2:56:d5:e9:8c:83: + 7c:59:3f:c4:f1:0b:e7:9d:ec:9e:bd:9c:18:0e:3e:c2:39:79: + 28:b7:03:0d:08:cb:c6:e7:d9:01:37:50:10:ec:cc:61:16:40: + d4:af:31:74:7b:fc:3f:31:a7:d0:47:73:33:39:1b:cc:4e:6a: + d7:49:83:11:06:fe:eb:82:58:33:32:4c:f0:56:ac:1e:9c:2f: + 56:9a:7b:c1:4a:1c:a5:fd:55:36:ce:fc:96:4d:f4:b0:f0:ec: + b7:6c:82:ed:2f:31:99:42:4c:a9:b2:0d:b8:15:5d:f1:df:ba: + c9:b5:4a:d4:64:98:b3:26:a9:30:c8:fd:a6:ec:ab:96:21:ad: + 7f:c2:78:b6 + +Entrust Worldwide by DST +======================== +MD5 Fingerprint: B4:65:22:0A:7C:AD:DF:41:B7:D5:44:D5:AD:FA:9A:75 +PEM Data: +-----BEGIN CERTIFICATE----- +MIIDRzCCArCgAwIBAgIENm3FGDANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJV +UzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRswGQYDVQQL +ExJEU1QtRW50cnVzdCBHVEkgQ0EwHhcNOTgxMjA5MDAwMjI0WhcNMTgxMjA5MDAz +MjI0WjBQMQswCQYDVQQGEwJVUzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUg +VHJ1c3QgQ28uMRswGQYDVQQLExJEU1QtRW50cnVzdCBHVEkgQ0EwgZ0wDQYJKoZI +hvcNAQEBBQADgYsAMIGHAoGBALYd90uNDxPjEvUJ/gYyDq9MQfV91Ec9KgrfgwXe +3n3mAxb2UTrLRxpKrX7E/R20vnSKeN0Lg460hBPE+/htKa6h4Q8PQ+O1XmBp+oOU +/Hnm3Hbt0UQrjv0Su/4XdxcMie2n71F9xO04wzujevviTaBgtfL9E2XTxuw/vjWc +PSLvAgEDo4IBLjCCASowEQYJYIZIAYb4QgEBBAQDAgAHMHIGA1UdHwRrMGkwZ6Bl +oGOkYTBfMQswCQYDVQQGEwJVUzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUg +VHJ1c3QgQ28uMRswGQYDVQQLExJEU1QtRW50cnVzdCBHVEkgQ0ExDTALBgNVBAMT +BENSTDEwKwYDVR0QBCQwIoAPMTk5ODEyMDkwMDAyMjRagQ8yMDE4MTIwOTAwMDIy +NFowCwYDVR0PBAQDAgEGMB8GA1UdIwQYMBaAFJOaRMrQeFOAKUkE38evMz+ZdV+u +MB0GA1UdDgQWBBSTmkTK0HhTgClJBN/HrzM/mXVfrjAMBgNVHRMEBTADAQH/MBkG +CSqGSIb2fQdBAAQMMAobBFY0LjADAgSQMA0GCSqGSIb3DQEBBQUAA4GBAGSJzAOn +3AryWCDn/RegKHLNh7DNmLUkR2MzMRAQsu+KV3KuTAPgZ5+sYEOEIsGpo+Wxp94J +1M8NeEYjW49Je/4TIpeU6nJI4SwgeJbpZkUZywllY2E/0UmYsXYQVdVjSmZLpAdr +3nt/ueaTWxoCW4AO3Y0Y1Iqjwmjxo+AY0U5M +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: 913163544 (0x366dc518) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=Digital Signature Trust Co., OU=DST-Entrust GTI CA + Validity + Not Before: Dec 9 00:02:24 1998 GMT + Not After : Dec 9 00:32:24 2018 GMT + Subject: C=US, O=Digital Signature Trust Co., OU=DST-Entrust GTI CA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:b6:1d:f7:4b:8d:0f:13:e3:12:f5:09:fe:06:32: + 0e:af:4c:41:f5:7d:d4:47:3d:2a:0a:df:83:05:de: + de:7d:e6:03:16:f6:51:3a:cb:47:1a:4a:ad:7e:c4: + fd:1d:b4:be:74:8a:78:dd:0b:83:8e:b4:84:13:c4: + fb:f8:6d:29:ae:a1:e1:0f:0f:43:e3:b5:5e:60:69: + fa:83:94:fc:79:e6:dc:76:ed:d1:44:2b:8e:fd:12: + bb:fe:17:77:17:0c:89:ed:a7:ef:51:7d:c4:ed:38: + c3:3b:a3:7a:fb:e2:4d:a0:60:b5:f2:fd:13:65:d3: + c6:ec:3f:be:35:9c:3d:22:ef + Exponent: 3 (0x3) + X509v3 extensions: + Netscape Cert Type: + SSL CA, S/MIME CA, Object Signing CA + X509v3 CRL Distribution Points: + DirName:/C=US/O=Digital Signature Trust Co./OU=DST-Entrust GTI CA/CN=CRL1 + + X509v3 Private Key Usage Period: + Not Before: Dec 9 00:02:24 1998 GMT, Not After: Dec 9 00:02:24 2018 GMT + X509v3 Key Usage: + Certificate Sign, CRL Sign + X509v3 Authority Key Identifier: + keyid:93:9A:44:CA:D0:78:53:80:29:49:04:DF:C7:AF:33:3F:99:75:5F:AE + + X509v3 Subject Key Identifier: + 93:9A:44:CA:D0:78:53:80:29:49:04:DF:C7:AF:33:3F:99:75:5F:AE + X509v3 Basic Constraints: + CA:TRUE + 1.2.840.113533.7.65.0: + 0 +..V4.0.... + Signature Algorithm: sha1WithRSAEncryption + 64:89:cc:03:a7:dc:0a:f2:58:20:e7:fd:17:a0:28:72:cd:87: + b0:cd:98:b5:24:47:63:33:31:10:10:b2:ef:8a:57:72:ae:4c: + 03:e0:67:9f:ac:60:43:84:22:c1:a9:a3:e5:b1:a7:de:09:d4: + cf:0d:78:46:23:5b:8f:49:7b:fe:13:22:97:94:ea:72:48:e1: + 2c:20:78:96:e9:66:45:19:cb:09:65:63:61:3f:d1:49:98:b1: + 76:10:55:d5:63:4a:66:4b:a4:07:6b:de:7b:7f:b9:e6:93:5b: + 1a:02:5b:80:0e:dd:8d:18:d4:8a:a3:c2:68:f1:a3:e0:18:d1: + 4e:4c + +Entrust.net Premium 2048 Secure Server CA +========================================= +MD5 Fingerprint: BA:21:EA:20:D6:DD:DB:8F:C1:57:8B:40:AD:A1:FC:FC +PEM Data: +-----BEGIN CERTIFICATE----- +MIIEXDCCA0SgAwIBAgIEOGO5ZjANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChML +RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBp +bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5 +IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENlcnRp +ZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQxNzUwNTFaFw0xOTEy +MjQxODIwNTFaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3 +LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxp +YWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEG +A1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQq +K0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQe +sYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuX +MlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVT +XTzWnLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/ +HoZdenoVve8AjhUiVBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH +4QIDAQABo3QwcjARBglghkgBhvhCAQEEBAMCAAcwHwYDVR0jBBgwFoAUVeSB0RGA +vtiJuQijMfmhJAkWuXAwHQYDVR0OBBYEFFXkgdERgL7YibkIozH5oSQJFrlwMB0G +CSqGSIb2fQdBAAQQMA4bCFY1LjA6NC4wAwIEkDANBgkqhkiG9w0BAQUFAAOCAQEA +WUesIYSKF8mciVMeuoCFGsY8Tj6xnLZ8xpJdGGQC49MGCBFhfGPjK50xA3B20qMo +oPS7mmNz7W3lKtvtFKkrxjYR0CvrB4ul2p5cGZ1WEvVUKcgF7bISKo30Axv/55IQ +h7A6tcOdBTcSo8f0FbnVpDkWm1M6I5HxqIKiaohowXkCIryqptau37AUX7iH0N18 +f3v/rxzP5tsHrV7bhZ3QKw0z2wTR5klAEyt2+z7pnIkPFc4YsIV4IU9rTw76NmfN +B/L/CNDi3tm/Kq+4h4YhPATKt5Rof8886ZjXOP/swNlQ8C5LWK5Gb9Auw2DaclVy +vUxFnmG6v4SBkgPR0ml8xQ== +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: 946059622 (0x3863b966) + Signature Algorithm: sha1WithRSAEncryption + Issuer: O=Entrust.net, OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.), OU=(c) 1999 Entrust.net Limited, CN=Entrust.net Certification Authority (2048) + Validity + Not Before: Dec 24 17:50:51 1999 GMT + Not After : Dec 24 18:20:51 2019 GMT + Subject: O=Entrust.net, OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.), OU=(c) 1999 Entrust.net Limited, CN=Entrust.net Certification Authority (2048) + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:ad:4d:4b:a9:12:86:b2:ea:a3:20:07:15:16:64: + 2a:2b:4b:d1:bf:0b:4a:4d:8e:ed:80:76:a5:67:b7: + 78:40:c0:73:42:c8:68:c0:db:53:2b:dd:5e:b8:76: + 98:35:93:8b:1a:9d:7c:13:3a:0e:1f:5b:b7:1e:cf: + e5:24:14:1e:b1:81:a9:8d:7d:b8:cc:6b:4b:03:f1: + 02:0c:dc:ab:a5:40:24:00:7f:74:94:a1:9d:08:29: + b3:88:0b:f5:87:77:9d:55:cd:e4:c3:7e:d7:6a:64: + ab:85:14:86:95:5b:97:32:50:6f:3d:c8:ba:66:0c: + e3:fc:bd:b8:49:c1:76:89:49:19:fd:c0:a8:bd:89: + a3:67:2f:c6:9f:bc:71:19:60:b8:2d:e9:2c:c9:90: + 76:66:7b:94:e2:af:78:d6:65:53:5d:3c:d6:9c:b2: + cf:29:03:f9:2f:a4:50:b2:d4:48:ce:05:32:55:8a: + fd:b2:64:4c:0e:e4:98:07:75:db:7f:df:b9:08:55: + 60:85:30:29:f9:7b:48:a4:69:86:e3:35:3f:1e:86: + 5d:7a:7a:15:bd:ef:00:8e:15:22:54:17:00:90:26: + 93:bc:0e:49:68:91:bf:f8:47:d3:9d:95:42:c1:0e: + 4d:df:6f:26:cf:c3:18:21:62:66:43:70:d6:d5:c0: + 07:e1 + Exponent: 65537 (0x10001) + X509v3 extensions: + Netscape Cert Type: + SSL CA, S/MIME CA, Object Signing CA + X509v3 Authority Key Identifier: + keyid:55:E4:81:D1:11:80:BE:D8:89:B9:08:A3:31:F9:A1:24:09:16:B9:70 + + X509v3 Subject Key Identifier: + 55:E4:81:D1:11:80:BE:D8:89:B9:08:A3:31:F9:A1:24:09:16:B9:70 + 1.2.840.113533.7.65.0: + 0...V5.0:4.0.... + Signature Algorithm: sha1WithRSAEncryption + 59:47:ac:21:84:8a:17:c9:9c:89:53:1e:ba:80:85:1a:c6:3c: + 4e:3e:b1:9c:b6:7c:c6:92:5d:18:64:02:e3:d3:06:08:11:61: + 7c:63:e3:2b:9d:31:03:70:76:d2:a3:28:a0:f4:bb:9a:63:73: + ed:6d:e5:2a:db:ed:14:a9:2b:c6:36:11:d0:2b:eb:07:8b:a5: + da:9e:5c:19:9d:56:12:f5:54:29:c8:05:ed:b2:12:2a:8d:f4: + 03:1b:ff:e7:92:10:87:b0:3a:b5:c3:9d:05:37:12:a3:c7:f4: + 15:b9:d5:a4:39:16:9b:53:3a:23:91:f1:a8:82:a2:6a:88:68: + c1:79:02:22:bc:aa:a6:d6:ae:df:b0:14:5f:b8:87:d0:dd:7c: + 7f:7b:ff:af:1c:cf:e6:db:07:ad:5e:db:85:9d:d0:2b:0d:33: + db:04:d1:e6:49:40:13:2b:76:fb:3e:e9:9c:89:0f:15:ce:18: + b0:85:78:21:4f:6b:4f:0e:fa:36:67:cd:07:f2:ff:08:d0:e2: + de:d9:bf:2a:af:b8:87:86:21:3c:04:ca:b7:94:68:7f:cf:3c: + e9:98:d7:38:ff:ec:c0:d9:50:f0:2e:4b:58:ae:46:6f:d0:2e: + c3:60:da:72:55:72:bd:4c:45:9e:61:ba:bf:84:81:92:03:d1: + d2:69:7c:c5 + +Entrust.net Secure Personal CA +============================== +MD5 Fingerprint: 0C:41:2F:13:5B:A0:54:F5:96:66:2D:7E:CD:0E:03:F4 +PEM Data: +-----BEGIN CERTIFICATE----- +MIIE7TCCBFagAwIBAgIEOAOR7jANBgkqhkiG9w0BAQQFADCByTELMAkGA1UEBhMC +VVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MUgwRgYDVQQLFD93d3cuZW50cnVzdC5u +ZXQvQ2xpZW50X0NBX0luZm8vQ1BTIGluY29ycC4gYnkgcmVmLiBsaW1pdHMgbGlh +Yi4xJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNV +BAMTKkVudHJ1c3QubmV0IENsaWVudCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe +Fw05OTEwMTIxOTI0MzBaFw0xOTEwMTIxOTU0MzBaMIHJMQswCQYDVQQGEwJVUzEU +MBIGA1UEChMLRW50cnVzdC5uZXQxSDBGBgNVBAsUP3d3dy5lbnRydXN0Lm5ldC9D +bGllbnRfQ0FfSW5mby9DUFMgaW5jb3JwLiBieSByZWYuIGxpbWl0cyBsaWFiLjEl +MCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMq +RW50cnVzdC5uZXQgQ2xpZW50IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGdMA0G +CSqGSIb3DQEBAQUAA4GLADCBhwKBgQDIOpleMRffrCdvkHvkGf9FozTC28GoT/Bo +6oT9n3V5z8GKUZSvx1cDR2SerYIbWtp/N3hHuzeYEpbOxhN979IMMFGpOZ5V+Pux +5zDeg7K6PvHViTs7hbqqdCz+PzFur5GVbgbUB01LLFZHGARS2g4Qk79jkJvh34zm +AqTmT173iwIBA6OCAeAwggHcMBEGCWCGSAGG+EIBAQQEAwIABzCCASIGA1UdHwSC +ARkwggEVMIHkoIHhoIHepIHbMIHYMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRW50 +cnVzdC5uZXQxSDBGBgNVBAsUP3d3dy5lbnRydXN0Lm5ldC9DbGllbnRfQ0FfSW5m +by9DUFMgaW5jb3JwLiBieSByZWYuIGxpbWl0cyBsaWFiLjElMCMGA1UECxMcKGMp +IDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5uZXQg +Q2xpZW50IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMCyg +KqAohiZodHRwOi8vd3d3LmVudHJ1c3QubmV0L0NSTC9DbGllbnQxLmNybDArBgNV +HRAEJDAigA8xOTk5MTAxMjE5MjQzMFqBDzIwMTkxMDEyMTkyNDMwWjALBgNVHQ8E +BAMCAQYwHwYDVR0jBBgwFoAUxPucKXuXzUyW/O5bs8qZdIuV6kwwHQYDVR0OBBYE +FMT7nCl7l81MlvzuW7PKmXSLlepMMAwGA1UdEwQFMAMBAf8wGQYJKoZIhvZ9B0EA +BAwwChsEVjQuMAMCBJAwDQYJKoZIhvcNAQEEBQADgYEAP66K8ddmAwWePvrqHEa7 +pFuPeJoSSJn59DXeDDYHAmsQOokUgZwxpnyyQbJq5wcBoUv5nyU7lsqZwz6hURzz +wy5E97BnRqqS5TvaHBkUODDV4qIxJS7x7EU47fgGWANzYrAQMY9Av2TgXD7FTx/a +EkP/TOYGJqibGapEPHayXOw= +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: 939758062 (0x380391ee) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=US, O=Entrust.net, OU=www.entrust.net/Client_CA_Info/CPS incorp. by ref. limits liab., OU=(c) 1999 Entrust.net Limited, CN=Entrust.net Client Certification Authority + Validity + Not Before: Oct 12 19:24:30 1999 GMT + Not After : Oct 12 19:54:30 2019 GMT + Subject: C=US, O=Entrust.net, OU=www.entrust.net/Client_CA_Info/CPS incorp. by ref. limits liab., OU=(c) 1999 Entrust.net Limited, CN=Entrust.net Client Certification Authority + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:c8:3a:99:5e:31:17:df:ac:27:6f:90:7b:e4:19: + ff:45:a3:34:c2:db:c1:a8:4f:f0:68:ea:84:fd:9f: + 75:79:cf:c1:8a:51:94:af:c7:57:03:47:64:9e:ad: + 82:1b:5a:da:7f:37:78:47:bb:37:98:12:96:ce:c6: + 13:7d:ef:d2:0c:30:51:a9:39:9e:55:f8:fb:b1:e7: + 30:de:83:b2:ba:3e:f1:d5:89:3b:3b:85:ba:aa:74: + 2c:fe:3f:31:6e:af:91:95:6e:06:d4:07:4d:4b:2c: + 56:47:18:04:52:da:0e:10:93:bf:63:90:9b:e1:df: + 8c:e6:02:a4:e6:4f:5e:f7:8b + Exponent: 3 (0x3) + X509v3 extensions: + Netscape Cert Type: + SSL CA, S/MIME CA, Object Signing CA + X509v3 CRL Distribution Points: + DirName:/C=US/O=Entrust.net/OU=www.entrust.net/Client_CA_Info/CPS incorp. by ref. limits liab./OU=(c) 1999 Entrust.net Limited/CN=Entrust.net Client Certification Authority/CN=CRL1 + URI:http://www.entrust.net/CRL/Client1.crl + + X509v3 Private Key Usage Period: + Not Before: Oct 12 19:24:30 1999 GMT, Not After: Oct 12 19:24:30 2019 GMT + X509v3 Key Usage: + Certificate Sign, CRL Sign + X509v3 Authority Key Identifier: + keyid:C4:FB:9C:29:7B:97:CD:4C:96:FC:EE:5B:B3:CA:99:74:8B:95:EA:4C + + X509v3 Subject Key Identifier: + C4:FB:9C:29:7B:97:CD:4C:96:FC:EE:5B:B3:CA:99:74:8B:95:EA:4C + X509v3 Basic Constraints: + CA:TRUE + 1.2.840.113533.7.65.0: + 0 +..V4.0.... + Signature Algorithm: md5WithRSAEncryption + 3f:ae:8a:f1:d7:66:03:05:9e:3e:fa:ea:1c:46:bb:a4:5b:8f: + 78:9a:12:48:99:f9:f4:35:de:0c:36:07:02:6b:10:3a:89:14: + 81:9c:31:a6:7c:b2:41:b2:6a:e7:07:01:a1:4b:f9:9f:25:3b: + 96:ca:99:c3:3e:a1:51:1c:f3:c3:2e:44:f7:b0:67:46:aa:92: + e5:3b:da:1c:19:14:38:30:d5:e2:a2:31:25:2e:f1:ec:45:38: + ed:f8:06:58:03:73:62:b0:10:31:8f:40:bf:64:e0:5c:3e:c5: + 4f:1f:da:12:43:ff:4c:e6:06:26:a8:9b:19:aa:44:3c:76:b2: + 5c:ec + +Entrust.net Secure Server CA +============================ +MD5 Fingerprint: DF:F2:80:73:CC:F1:E6:61:73:FC:F5:42:E9:C5:7C:EE +PEM Data: +-----BEGIN CERTIFICATE----- +MIIE2DCCBEGgAwIBAgIEN0rSQzANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMC +VVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5u +ZXQvQ1BTIGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMc +KGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDE6MDgGA1UEAxMxRW50cnVzdC5u +ZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05OTA1 +MjUxNjA5NDBaFw0xOTA1MjUxNjM5NDBaMIHDMQswCQYDVQQGEwJVUzEUMBIGA1UE +ChMLRW50cnVzdC5uZXQxOzA5BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5j +b3JwLiBieSByZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBF +bnRydXN0Lm5ldCBMaW1pdGVkMTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUg +U2VydmVyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGdMA0GCSqGSIb3DQEBAQUA +A4GLADCBhwKBgQDNKIM0VBuJ8w+vN5Ex/68xYMmo6LIQaO2f55M28Qpku0f1BBc/ +I0dNxScZgSYMVHINiC3ZH5oSn7yzcdOAGT9HZnuMNSjSuQrfJNqc1lB5gXpa0zf3 +wkrYKZImZNHkmGw6AIr1NJtl+O3jEP/9uElY3KDegjlrgbEWGWG5VLbmQwIBA6OC +AdcwggHTMBEGCWCGSAGG+EIBAQQEAwIABzCCARkGA1UdHwSCARAwggEMMIHeoIHb +oIHYpIHVMIHSMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRW50cnVzdC5uZXQxOzA5 +BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5jb3JwLiBieSByZWYuIChsaW1p +dHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBFbnRydXN0Lm5ldCBMaW1pdGVk +MTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENlcnRpZmljYXRp +b24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMCmgJ6AlhiNodHRwOi8vd3d3LmVu +dHJ1c3QubmV0L0NSTC9uZXQxLmNybDArBgNVHRAEJDAigA8xOTk5MDUyNTE2MDk0 +MFqBDzIwMTkwNTI1MTYwOTQwWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAU8Bdi +E1U9s/8KAGv7UISX8+1i0BowHQYDVR0OBBYEFPAXYhNVPbP/CgBr+1CEl/PtYtAa +MAwGA1UdEwQFMAMBAf8wGQYJKoZIhvZ9B0EABAwwChsEVjQuMAMCBJAwDQYJKoZI +hvcNAQEFBQADgYEAkNwwAvpkdMKnCqV8IY00F6j7Rw7/JXyNEwr75Ji174z4xRAN +95K+8cPV1ZVqBLssziY2ZcgxxufuP+NXdYR6Ee9GTxj005i7qIcyunL2POI9n9cd +2cNgQ4xYDiKWL2KjLB+6rQXvqzJ4h6BUcxm1XAX5Uj5tLUUL9wqT6u0G+bI= +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: 927650371 (0x374ad243) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=Entrust.net, OU=www.entrust.net/CPS incorp. by ref. (limits liab.), OU=(c) 1999 Entrust.net Limited, CN=Entrust.net Secure Server Certification Authority + Validity + Not Before: May 25 16:09:40 1999 GMT + Not After : May 25 16:39:40 2019 GMT + Subject: C=US, O=Entrust.net, OU=www.entrust.net/CPS incorp. by ref. (limits liab.), OU=(c) 1999 Entrust.net Limited, CN=Entrust.net Secure Server Certification Authority + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:cd:28:83:34:54:1b:89:f3:0f:af:37:91:31:ff: + af:31:60:c9:a8:e8:b2:10:68:ed:9f:e7:93:36:f1: + 0a:64:bb:47:f5:04:17:3f:23:47:4d:c5:27:19:81: + 26:0c:54:72:0d:88:2d:d9:1f:9a:12:9f:bc:b3:71: + d3:80:19:3f:47:66:7b:8c:35:28:d2:b9:0a:df:24: + da:9c:d6:50:79:81:7a:5a:d3:37:f7:c2:4a:d8:29: + 92:26:64:d1:e4:98:6c:3a:00:8a:f5:34:9b:65:f8: + ed:e3:10:ff:fd:b8:49:58:dc:a0:de:82:39:6b:81: + b1:16:19:61:b9:54:b6:e6:43 + Exponent: 3 (0x3) + X509v3 extensions: + Netscape Cert Type: + SSL CA, S/MIME CA, Object Signing CA + X509v3 CRL Distribution Points: + DirName:/C=US/O=Entrust.net/OU=www.entrust.net/CPS incorp. by ref. (limits liab.)/OU=(c) 1999 Entrust.net Limited/CN=Entrust.net Secure Server Certification Authority/CN=CRL1 + URI:http://www.entrust.net/CRL/net1.crl + + X509v3 Private Key Usage Period: + Not Before: May 25 16:09:40 1999 GMT, Not After: May 25 16:09:40 2019 GMT + X509v3 Key Usage: + Certificate Sign, CRL Sign + X509v3 Authority Key Identifier: + keyid:F0:17:62:13:55:3D:B3:FF:0A:00:6B:FB:50:84:97:F3:ED:62:D0:1A + + X509v3 Subject Key Identifier: + F0:17:62:13:55:3D:B3:FF:0A:00:6B:FB:50:84:97:F3:ED:62:D0:1A + X509v3 Basic Constraints: + CA:TRUE + 1.2.840.113533.7.65.0: + 0 +..V4.0.... + Signature Algorithm: sha1WithRSAEncryption + 90:dc:30:02:fa:64:74:c2:a7:0a:a5:7c:21:8d:34:17:a8:fb: + 47:0e:ff:25:7c:8d:13:0a:fb:e4:98:b5:ef:8c:f8:c5:10:0d: + f7:92:be:f1:c3:d5:d5:95:6a:04:bb:2c:ce:26:36:65:c8:31: + c6:e7:ee:3f:e3:57:75:84:7a:11:ef:46:4f:18:f4:d3:98:bb: + a8:87:32:ba:72:f6:3c:e2:3d:9f:d7:1d:d9:c3:60:43:8c:58: + 0e:22:96:2f:62:a3:2c:1f:ba:ad:05:ef:ab:32:78:87:a0:54: + 73:19:b5:5c:05:f9:52:3e:6d:2d:45:0b:f7:0a:93:ea:ed:06: + f9:b2 + +Equifax Premium CA +================== +MD5 Fingerprint: A9:E9:A8:9D:0E:73:E3:B1:2F:37:0D:E8:48:3F:86:ED +PEM Data: +-----BEGIN CERTIFICATE----- +MIIDIzCCAoygAwIBAgIENeHvHjANBgkqhkiG9w0BAQUFADBPMQswCQYDVQQGEwJV +UzEQMA4GA1UEChMHRXF1aWZheDEuMCwGA1UECxMlRXF1aWZheCBQcmVtaXVtIENl +cnRpZmljYXRlIEF1dGhvcml0eTAeFw05ODA4MjQyMjU0MjNaFw0xODA4MjQyMjU0 +MjNaME8xCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFcXVpZmF4MS4wLAYDVQQLEyVF +cXVpZmF4IFByZW1pdW0gQ2VydGlmaWNhdGUgQXV0aG9yaXR5MIGfMA0GCSqGSIb3 +DQEBAQUAA4GNADCBiQKBgQDOoQaOBswIC8GGqN4g1Q0O0Q3En+pq2bPCMkdAb4qI +pAm9OCwd5svmpPM269rrvPxkswf2Lbyqzp8ZSGhK/PWiRX4JEPWPs0lcIwY56hOL +uAvNkR12X9k3oUT7X5DyZ7PNGJlDH3YSawLylYM4Q8L2YjTKyXhdX9LYupr/vhBg +WwIDAQABo4IBCjCCAQYwcQYDVR0fBGowaDBmoGSgYqRgMF4xCzAJBgNVBAYTAlVT +MRAwDgYDVQQKEwdFcXVpZmF4MS4wLAYDVQQLEyVFcXVpZmF4IFByZW1pdW0gQ2Vy +dGlmaWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIw +MTgwODI0MjI1NDIzWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUFe6yKFmrbuX4 +z4uB9CThrj91G5gwHQYDVR0OBBYEFBXusihZq27l+M+LgfQk4a4/dRuYMAwGA1Ud +EwQFMAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEB +BQUAA4GBAL0LnCepA9so3JipS9DRjqeoGlqR4Jzx9xh8LiKeNh/JqLXNRkpu+jUH +G4YI65/iqPmdQS06rlxctl80BOv8KmCw+3TkhellOJbuFcfGd2MSvYpoH6tsfdrK +XBPO6snrCVzFc+cSAdXZUwee4A+W8Iu0u0VIn4bFGVWgy5bFA/xI +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: 903999262 (0x35e1ef1e) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=Equifax, OU=Equifax Premium Certificate Authority + Validity + Not Before: Aug 24 22:54:23 1998 GMT + Not After : Aug 24 22:54:23 2018 GMT + Subject: C=US, O=Equifax, OU=Equifax Premium Certificate Authority + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:ce:a1:06:8e:06:cc:08:0b:c1:86:a8:de:20:d5: + 0d:0e:d1:0d:c4:9f:ea:6a:d9:b3:c2:32:47:40:6f: + 8a:88:a4:09:bd:38:2c:1d:e6:cb:e6:a4:f3:36:eb: + da:eb:bc:fc:64:b3:07:f6:2d:bc:aa:ce:9f:19:48: + 68:4a:fc:f5:a2:45:7e:09:10:f5:8f:b3:49:5c:23: + 06:39:ea:13:8b:b8:0b:cd:91:1d:76:5f:d9:37:a1: + 44:fb:5f:90:f2:67:b3:cd:18:99:43:1f:76:12:6b: + 02:f2:95:83:38:43:c2:f6:62:34:ca:c9:78:5d:5f: + d2:d8:ba:9a:ff:be:10:60:5b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 CRL Distribution Points: + DirName:/C=US/O=Equifax/OU=Equifax Premium Certificate Authority/CN=CRL1 + + X509v3 Private Key Usage Period: + Not After: Aug 24 22:54:23 2018 GMT + X509v3 Key Usage: + Certificate Sign, CRL Sign + X509v3 Authority Key Identifier: + keyid:15:EE:B2:28:59:AB:6E:E5:F8:CF:8B:81:F4:24:E1:AE:3F:75:1B:98 + + X509v3 Subject Key Identifier: + 15:EE:B2:28:59:AB:6E:E5:F8:CF:8B:81:F4:24:E1:AE:3F:75:1B:98 + X509v3 Basic Constraints: + CA:TRUE + 1.2.840.113533.7.65.0: + 0...V3.0c.... + Signature Algorithm: sha1WithRSAEncryption + bd:0b:9c:27:a9:03:db:28:dc:98:a9:4b:d0:d1:8e:a7:a8:1a: + 5a:91:e0:9c:f1:f7:18:7c:2e:22:9e:36:1f:c9:a8:b5:cd:46: + 4a:6e:fa:35:07:1b:86:08:eb:9f:e2:a8:f9:9d:41:2d:3a:ae: + 5c:5c:b6:5f:34:04:eb:fc:2a:60:b0:fb:74:e4:85:e9:65:38: + 96:ee:15:c7:c6:77:63:12:bd:8a:68:1f:ab:6c:7d:da:ca:5c: + 13:ce:ea:c9:eb:09:5c:c5:73:e7:12:01:d5:d9:53:07:9e:e0: + 0f:96:f0:8b:b4:bb:45:48:9f:86:c5:19:55:a0:cb:96:c5:03: + fc:48 + +Equifax Secure CA +================= +MD5 Fingerprint: 67:CB:9D:C0:13:24:8A:82:9B:B2:17:1E:D1:1B:EC:D4 +PEM Data: +-----BEGIN CERTIFICATE----- +MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV +UzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2Vy +dGlmaWNhdGUgQXV0aG9yaXR5MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1 +MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0VxdWlmYXgxLTArBgNVBAsTJEVx +dWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCBnzANBgkqhkiG9w0B +AQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPRfM6f +BeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+A +cJkVV5MW8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kC +AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQ +MA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlm +aWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTgw +ODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvSspXXR9gj +IBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQF +MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA +A4GBAFjOKer89961zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y +7qj/WsjTVbJmcVfewCHrPSqnI0kBBIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh +1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee9570+sB3c4 +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: 903804111 (0x35def4cf) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=Equifax, OU=Equifax Secure Certificate Authority + Validity + Not Before: Aug 22 16:41:51 1998 GMT + Not After : Aug 22 16:41:51 2018 GMT + Subject: C=US, O=Equifax, OU=Equifax Secure Certificate Authority + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:c1:5d:b1:58:67:08:62:ee:a0:9a:2d:1f:08:6d: + 91:14:68:98:0a:1e:fe:da:04:6f:13:84:62:21:c3: + d1:7c:ce:9f:05:e0:b8:01:f0:4e:34:ec:e2:8a:95: + 04:64:ac:f1:6b:53:5f:05:b3:cb:67:80:bf:42:02: + 8e:fe:dd:01:09:ec:e1:00:14:4f:fc:fb:f0:0c:dd: + 43:ba:5b:2b:e1:1f:80:70:99:15:57:93:16:f1:0f: + 97:6a:b7:c2:68:23:1c:cc:4d:59:30:ac:51:1e:3b: + af:2b:d6:ee:63:45:7b:c5:d9:5f:50:d2:e3:50:0f: + 3a:88:e7:bf:14:fd:e0:c7:b9 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 CRL Distribution Points: + DirName:/C=US/O=Equifax/OU=Equifax Secure Certificate Authority/CN=CRL1 + + X509v3 Private Key Usage Period: + Not After: Aug 22 16:41:51 2018 GMT + X509v3 Key Usage: + Certificate Sign, CRL Sign + X509v3 Authority Key Identifier: + keyid:48:E6:68:F9:2B:D2:B2:95:D7:47:D8:23:20:10:4F:33:98:90:9F:D4 + + X509v3 Subject Key Identifier: + 48:E6:68:F9:2B:D2:B2:95:D7:47:D8:23:20:10:4F:33:98:90:9F:D4 + X509v3 Basic Constraints: + CA:TRUE + 1.2.840.113533.7.65.0: + 0...V3.0c.... + Signature Algorithm: sha1WithRSAEncryption + 58:ce:29:ea:fc:f7:de:b5:ce:02:b9:17:b5:85:d1:b9:e3:e0: + 95:cc:25:31:0d:00:a6:92:6e:7f:b6:92:63:9e:50:95:d1:9a: + 6f:e4:11:de:63:85:6e:98:ee:a8:ff:5a:c8:d3:55:b2:66:71: + 57:de:c0:21:eb:3d:2a:a7:23:49:01:04:86:42:7b:fc:ee:7f: + a2:16:52:b5:67:67:d3:40:db:3b:26:58:b2:28:77:3d:ae:14: + 77:61:d6:fa:2a:66:27:a0:0d:fa:a7:73:5c:ea:70:f1:94:21: + 65:44:5f:fa:fc:ef:29:68:a9:a2:87:79:ef:79:ef:4f:ac:07: + 77:38 + +GTE CyberTrust Global Root +========================== +MD5 Fingerprint: CA:3D:D3:68:F1:03:5C:D0:32:FA:B8:2B:59:E8:5A:DB +PEM Data: +-----BEGIN CERTIFICATE----- +MIICWjCCAcMCAgGlMA0GCSqGSIb3DQEBBAUAMHUxCzAJBgNVBAYTAlVTMRgwFgYD +VQQKEw9HVEUgQ29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRydXN0IFNv +bHV0aW9ucywgSW5jLjEjMCEGA1UEAxMaR1RFIEN5YmVyVHJ1c3QgR2xvYmFsIFJv +b3QwHhcNOTgwODEzMDAyOTAwWhcNMTgwODEzMjM1OTAwWjB1MQswCQYDVQQGEwJV +UzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQLEx5HVEUgQ3liZXJU +cnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBDeWJlclRydXN0IEds +b2JhbCBSb290MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVD6C28FCc6HrH +iM3dFw4usJTQGz0O9pTAipTHBsiQl8i4ZBp6fmw8U+E3KHNgf7KXUwefU/ltWJTS +r41tiGeA5u2ylc9yMcqlHHK6XALnZELn+aks1joNrI1CqiQBOeacPwGFVw1Yh0X4 +04Wqk2kmhXBIgD8SFcd5tB8FLztimQIDAQABMA0GCSqGSIb3DQEBBAUAA4GBAG3r +GwnpXtlR22ciYaQqPEh346B8pt5zohQDhT37qw4wxYMWM4ETCJ57NE7fQMh017l9 +3PR2VX2bY1QY6fDq81yx2YtCHrnAlU66+tXifPVoYb+O7AWXX1uw16OFNMQkpw0P +lZPvy5TYnh+dXIVtx6quTx8itc2VrbqnzPmrC3p/ +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 1 (0x0) + Serial Number: 421 (0x1a5) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=US, O=GTE Corporation, OU=GTE CyberTrust Solutions, Inc., CN=GTE CyberTrust Global Root + Validity + Not Before: Aug 13 00:29:00 1998 GMT + Not After : Aug 13 23:59:00 2018 GMT + Subject: C=US, O=GTE Corporation, OU=GTE CyberTrust Solutions, Inc., CN=GTE CyberTrust Global Root + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:95:0f:a0:b6:f0:50:9c:e8:7a:c7:88:cd:dd:17: + 0e:2e:b0:94:d0:1b:3d:0e:f6:94:c0:8a:94:c7:06: + c8:90:97:c8:b8:64:1a:7a:7e:6c:3c:53:e1:37:28: + 73:60:7f:b2:97:53:07:9f:53:f9:6d:58:94:d2:af: + 8d:6d:88:67:80:e6:ed:b2:95:cf:72:31:ca:a5:1c: + 72:ba:5c:02:e7:64:42:e7:f9:a9:2c:d6:3a:0d:ac: + 8d:42:aa:24:01:39:e6:9c:3f:01:85:57:0d:58:87: + 45:f8:d3:85:aa:93:69:26:85:70:48:80:3f:12:15: + c7:79:b4:1f:05:2f:3b:62:99 + Exponent: 65537 (0x10001) + Signature Algorithm: md5WithRSAEncryption + 6d:eb:1b:09:e9:5e:d9:51:db:67:22:61:a4:2a:3c:48:77:e3: + a0:7c:a6:de:73:a2:14:03:85:3d:fb:ab:0e:30:c5:83:16:33: + 81:13:08:9e:7b:34:4e:df:40:c8:74:d7:b9:7d:dc:f4:76:55: + 7d:9b:63:54:18:e9:f0:ea:f3:5c:b1:d9:8b:42:1e:b9:c0:95: + 4e:ba:fa:d5:e2:7c:f5:68:61:bf:8e:ec:05:97:5f:5b:b0:d7: + a3:85:34:c4:24:a7:0d:0f:95:93:ef:cb:94:d8:9e:1f:9d:5c: + 85:6d:c7:aa:ae:4f:1f:22:b5:cd:95:ad:ba:a7:cc:f9:ab:0b: + 7a:7f + + +GTE CyberTrust Root 2 +===================== +MD5 Fingerprint: BA:ED:17:57:9A:4B:FF:7C:F9:C9:1F:A2:CD:1A:D6:87 +PEM Data: +-----BEGIN CERTIFICATE----- +MIICUDCCAbkCAgGbMA0GCSqGSIb3DQEBBAUAMHAxCzAJBgNVBAYTAlVTMRgwFgYD +VQQKEw9HVEUgQ29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRydXN0IFNv +bHV0aW9ucywgSW5jLjEeMBwGA1UEAxMVR1RFIEN5YmVyVHJ1c3QgUm9vdCAyMB4X +DTk4MDgxMTExMzUwN1oXDTA4MDgxMTExMjIxNlowcDELMAkGA1UEBhMCVVMxGDAW +BgNVBAoTD0dURSBDb3Jwb3JhdGlvbjEnMCUGA1UECxMeR1RFIEN5YmVyVHJ1c3Qg +U29sdXRpb25zLCBJbmMuMR4wHAYDVQQDExVHVEUgQ3liZXJUcnVzdCBSb290IDIw +gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANksTE4vaRoj41a6886EwAnAefFE +XzMfFZF/iogouCRFzI8YzR900bWPcUzWMfZzloSUQMWpg2Akfa9vNLdLTMIJgDtF +BJ7EPMQndXsADKFkR7UUXYJLUTpYu0RMPdPlBjjoYVyYeLuAs5zacoJioN+cX+v5 +T3fCzGAYAGs0giWzAgMBAAEwDQYJKoZIhvcNAQEEBQADgYEAo2SRbxDt526iQkCU +eM74FAjR+kOF60bNkhTQ7y4tNjkY2brJJ4gp6UgXb/jBqshhbS39QC11QzCXOfgU +ZL1v72OoK0LfsloNJex7N9jOkSmCFvnoYqLhdsQCfd0li5jh9g1gjPZZkEBRRNHC ++xkkHhc5a3QhFTPWVdeCHnAsJ6g= +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 1 (0x0) + Serial Number: 411 (0x19b) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=US, O=GTE Corporation, OU=GTE CyberTrust Solutions, Inc., CN=GTE CyberTrust Root 2 + Validity + Not Before: Aug 11 11:35:07 1998 GMT + Not After : Aug 11 11:22:16 2008 GMT + Subject: C=US, O=GTE Corporation, OU=GTE CyberTrust Solutions, Inc., CN=GTE CyberTrust Root 2 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:d9:2c:4c:4e:2f:69:1a:23:e3:56:ba:f3:ce:84: + c0:09:c0:79:f1:44:5f:33:1f:15:91:7f:8a:88:28: + b8:24:45:cc:8f:18:cd:1f:74:d1:b5:8f:71:4c:d6: + 31:f6:73:96:84:94:40:c5:a9:83:60:24:7d:af:6f: + 34:b7:4b:4c:c2:09:80:3b:45:04:9e:c4:3c:c4:27: + 75:7b:00:0c:a1:64:47:b5:14:5d:82:4b:51:3a:58: + bb:44:4c:3d:d3:e5:06:38:e8:61:5c:98:78:bb:80: + b3:9c:da:72:82:62:a0:df:9c:5f:eb:f9:4f:77:c2: + cc:60:18:00:6b:34:82:25:b3 + Exponent: 65537 (0x10001) + Signature Algorithm: md5WithRSAEncryption + a3:64:91:6f:10:ed:e7:6e:a2:42:40:94:78:ce:f8:14:08:d1: + fa:43:85:eb:46:cd:92:14:d0:ef:2e:2d:36:39:18:d9:ba:c9: + 27:88:29:e9:48:17:6f:f8:c1:aa:c8:61:6d:2d:fd:40:2d:75: + 43:30:97:39:f8:14:64:bd:6f:ef:63:a8:2b:42:df:b2:5a:0d: + 25:ec:7b:37:d8:ce:91:29:82:16:f9:e8:62:a2:e1:76:c4:02: + 7d:dd:25:8b:98:e1:f6:0d:60:8c:f6:59:90:40:51:44:d1:c2: + fb:19:24:1e:17:39:6b:74:21:15:33:d6:55:d7:82:1e:70:2c: + 27:a8 + +GTE CyberTrust Root 3 +===================== +MD5 Fingerprint: DB:81:96:57:AE:64:61:EF:77:A7:83:C4:51:24:3C:87 +PEM Data: +-----BEGIN CERTIFICATE----- +MIICUDCCAbkCAgGXMA0GCSqGSIb3DQEBBQUAMHAxCzAJBgNVBAYTAlVTMRgwFgYD +VQQKEw9HVEUgQ29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRydXN0IFNv +bHV0aW9ucywgSW5jLjEeMBwGA1UEAxMVR1RFIEN5YmVyVHJ1c3QgUm9vdCAzMB4X +DTk4MDgxMDE5NTkwOFoXDTA4MDgxMDE5MzYzOVowcDELMAkGA1UEBhMCVVMxGDAW +BgNVBAoTD0dURSBDb3Jwb3JhdGlvbjEnMCUGA1UECxMeR1RFIEN5YmVyVHJ1c3Qg +U29sdXRpb25zLCBJbmMuMR4wHAYDVQQDExVHVEUgQ3liZXJUcnVzdCBSb290IDMw +gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOHzsSsLztwU2TSXYlASVmOETFP6 +wIXP+sHdD955E39T+6oOYN3iYr/G7k6ZNKpoQzWZ+KP982O9AVRqnrI6lix7eCjG +WrWNGhUY/eOMLqJQCVtx1g21GB8ZjgQpk5N4q18U53NC8gMMV6IbUDsLu1ngoDoD +7icbWky5sAjKuRqJAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAheutlCAG6bKiazvy +ZuvjS7gSJgXl9JGo3IfcmPSUwfRhvdWcbFFzlV7QvdfmRdw8z0aE1ee57ORnY24A +KHdxXUoF6bl8hszCRLveKUja6t29F58dUQGo6BResVf3/9qPzpX+Le0yEnf/fGph +la4xcgYI8PnzDY7i76hTXZEDg94= +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 1 (0x0) + Serial Number: 407 (0x197) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=GTE Corporation, OU=GTE CyberTrust Solutions, Inc., CN=GTE CyberTrust Root 3 + Validity + Not Before: Aug 10 19:59:08 1998 GMT + Not After : Aug 10 19:36:39 2008 GMT + Subject: C=US, O=GTE Corporation, OU=GTE CyberTrust Solutions, Inc., CN=GTE CyberTrust Root 3 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:e1:f3:b1:2b:0b:ce:dc:14:d9:34:97:62:50:12: + 56:63:84:4c:53:fa:c0:85:cf:fa:c1:dd:0f:de:79: + 13:7f:53:fb:aa:0e:60:dd:e2:62:bf:c6:ee:4e:99: + 34:aa:68:43:35:99:f8:a3:fd:f3:63:bd:01:54:6a: + 9e:b2:3a:96:2c:7b:78:28:c6:5a:b5:8d:1a:15:18: + fd:e3:8c:2e:a2:50:09:5b:71:d6:0d:b5:18:1f:19: + 8e:04:29:93:93:78:ab:5f:14:e7:73:42:f2:03:0c: + 57:a2:1b:50:3b:0b:bb:59:e0:a0:3a:03:ee:27:1b: + 5a:4c:b9:b0:08:ca:b9:1a:89 + Exponent: 65537 (0x10001) + Signature Algorithm: sha1WithRSAEncryption + 85:eb:ad:94:20:06:e9:b2:a2:6b:3b:f2:66:eb:e3:4b:b8:12: + 26:05:e5:f4:91:a8:dc:87:dc:98:f4:94:c1:f4:61:bd:d5:9c: + 6c:51:73:95:5e:d0:bd:d7:e6:45:dc:3c:cf:46:84:d5:e7:b9: + ec:e4:67:63:6e:00:28:77:71:5d:4a:05:e9:b9:7c:86:cc:c2: + 44:bb:de:29:48:da:ea:dd:bd:17:9f:1d:51:01:a8:e8:14:5e: + b1:57:f7:ff:da:8f:ce:95:fe:2d:ed:32:12:77:ff:7c:6a:61: + 95:ae:31:72:06:08:f0:f9:f3:0d:8e:e2:ef:a8:53:5d:91:03: + 83:de + +GTE CyberTrust Root 4 +===================== +MD5 Fingerprint: 33:43:02:B1:B9:E0:73:B1:B1:20:CA:CB:C7:84:03:50 +PEM Data: +-----BEGIN CERTIFICATE----- +MIIDVTCCAj0CAgGoMA0GCSqGSIb3DQEBBQUAMHAxCzAJBgNVBAYTAlVTMRgwFgYD +VQQKEw9HVEUgQ29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRydXN0IFNv +bHV0aW9ucywgSW5jLjEeMBwGA1UEAxMVR1RFIEN5YmVyVHJ1c3QgUm9vdCA0MB4X +DTk4MDgxMzEzNTEwMFoXDTEzMDgxMzIzNTkwMFowcDELMAkGA1UEBhMCVVMxGDAW +BgNVBAoTD0dURSBDb3Jwb3JhdGlvbjEnMCUGA1UECxMeR1RFIEN5YmVyVHJ1c3Qg +U29sdXRpb25zLCBJbmMuMR4wHAYDVQQDExVHVEUgQ3liZXJUcnVzdCBSb290IDQw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6nSJuf9pmPDlCsaMqb9P3 +vK6sMVrXEZBHuZ0ZLvnzGyKgw+GnusT8XgqUS5haSybkH/Tc8/6OiNxsLXx3hyZQ +wF5OqCih6hdpT03GAQ7amg0GViYVtqRdejWvje14Uob5OKuzAdPaBZaxtlCrwKGu +F1P6QzkgcWUj223Etu2YRYPX0vbiqWv7+XXM78WrcZY16N+OkZuoEHUft84Tjmuz +lneXGpEvxyxpmfAPKmgAmHZEG4wo0uuO9IO0f6QlXmw72cZo1WG41F4xB7VbkDVS +V3sXIO0tuB6OiDk+Usvf8FyxZbulErSQY79xnTLB2r9QSpW+BjrEK+vNmHZETQvl +AgMBAAEwDQYJKoZIhvcNAQEFBQADggEBAEOvHIfJSbpliTRJPOoHO0eiedSgO5Bs +3n+oVMPoTEAyvMjsHOXZrEC6/Iw/wnOc9GTq36ntTlvIAWDuOW1DJ/N/qgjS/k5v +FDJNfeQ0gKU1xNZGULQ7oC1lH09lfjQoLcCndn0xyQ0zFvYgGSARULsDzHBtlrfv +TKfaNhXPu03UltyITWyY7blz/ihXoO1k+AqBKXP29pcyhzm0ge/ZTRoHNPe6QjXe +V9xc1vfF6wonDIGmwtBoTv2SW0iD9haKjzZb7TFsP0F6cfeSPzGkCkBM84biYcE8 +SYEtpbjvupcPvCsdm4ny0o4eTYbywqv2LZnAGyoNobZP+SxYTT19Nwo= +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 1 (0x0) + Serial Number: 424 (0x1a8) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=GTE Corporation, OU=GTE CyberTrust Solutions, Inc., CN=GTE CyberTrust Root 4 + Validity + Not Before: Aug 13 13:51:00 1998 GMT + Not After : Aug 13 23:59:00 2013 GMT + Subject: C=US, O=GTE Corporation, OU=GTE CyberTrust Solutions, Inc., CN=GTE CyberTrust Root 4 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:ba:9d:22:6e:7f:da:66:3c:39:42:b1:a3:2a:6f: + d3:f7:bc:ae:ac:31:5a:d7:11:90:47:b9:9d:19:2e: + f9:f3:1b:22:a0:c3:e1:a7:ba:c4:fc:5e:0a:94:4b: + 98:5a:4b:26:e4:1f:f4:dc:f3:fe:8e:88:dc:6c:2d: + 7c:77:87:26:50:c0:5e:4e:a8:28:a1:ea:17:69:4f: + 4d:c6:01:0e:da:9a:0d:06:56:26:15:b6:a4:5d:7a: + 35:af:8d:ed:78:52:86:f9:38:ab:b3:01:d3:da:05: + 96:b1:b6:50:ab:c0:a1:ae:17:53:fa:43:39:20:71: + 65:23:db:6d:c4:b6:ed:98:45:83:d7:d2:f6:e2:a9: + 6b:fb:f9:75:cc:ef:c5:ab:71:96:35:e8:df:8e:91: + 9b:a8:10:75:1f:b7:ce:13:8e:6b:b3:96:77:97:1a: + 91:2f:c7:2c:69:99:f0:0f:2a:68:00:98:76:44:1b: + 8c:28:d2:eb:8e:f4:83:b4:7f:a4:25:5e:6c:3b:d9: + c6:68:d5:61:b8:d4:5e:31:07:b5:5b:90:35:52:57: + 7b:17:20:ed:2d:b8:1e:8e:88:39:3e:52:cb:df:f0: + 5c:b1:65:bb:a5:12:b4:90:63:bf:71:9d:32:c1:da: + bf:50:4a:95:be:06:3a:c4:2b:eb:cd:98:76:44:4d: + 0b:e5 + Exponent: 65537 (0x10001) + Signature Algorithm: sha1WithRSAEncryption + 43:af:1c:87:c9:49:ba:65:89:34:49:3c:ea:07:3b:47:a2:79: + d4:a0:3b:90:6c:de:7f:a8:54:c3:e8:4c:40:32:bc:c8:ec:1c: + e5:d9:ac:40:ba:fc:8c:3f:c2:73:9c:f4:64:ea:df:a9:ed:4e: + 5b:c8:01:60:ee:39:6d:43:27:f3:7f:aa:08:d2:fe:4e:6f:14: + 32:4d:7d:e4:34:80:a5:35:c4:d6:46:50:b4:3b:a0:2d:65:1f: + 4f:65:7e:34:28:2d:c0:a7:76:7d:31:c9:0d:33:16:f6:20:19: + 20:11:50:bb:03:cc:70:6d:96:b7:ef:4c:a7:da:36:15:cf:bb: + 4d:d4:96:dc:88:4d:6c:98:ed:b9:73:fe:28:57:a0:ed:64:f8: + 0a:81:29:73:f6:f6:97:32:87:39:b4:81:ef:d9:4d:1a:07:34: + f7:ba:42:35:de:57:dc:5c:d6:f7:c5:eb:0a:27:0c:81:a6:c2: + d0:68:4e:fd:92:5b:48:83:f6:16:8a:8f:36:5b:ed:31:6c:3f: + 41:7a:71:f7:92:3f:31:a4:0a:40:4c:f3:86:e2:61:c1:3c:49: + 81:2d:a5:b8:ef:ba:97:0f:bc:2b:1d:9b:89:f2:d2:8e:1e:4d: + 86:f2:c2:ab:f6:2d:99:c0:1b:2a:0d:a1:b6:4f:f9:2c:58:4d: + 3d:7d:37:0a + +GTE CyberTrust Root 5 +===================== +MD5 Fingerprint: 7D:6C:86:E4:FC:4D:D1:0B:00:BA:22:BB:4E:7C:6A:8E +PEM Data: +-----BEGIN CERTIFICATE----- +MIIDtjCCAp6gAwIBAgICAbYwDQYJKoZIhvcNAQEFBQAwcDELMAkGA1UEBhMCVVMx +GDAWBgNVBAoTD0dURSBDb3Jwb3JhdGlvbjEnMCUGA1UECxMeR1RFIEN5YmVyVHJ1 +c3QgU29sdXRpb25zLCBJbmMuMR4wHAYDVQQDExVHVEUgQ3liZXJUcnVzdCBSb290 +IDUwHhcNOTgwODE0MTQ1MDAwWhcNMTMwODE0MjM1OTAwWjBwMQswCQYDVQQGEwJV +UzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQLEx5HVEUgQ3liZXJU +cnVzdCBTb2x1dGlvbnMsIEluYy4xHjAcBgNVBAMTFUdURSBDeWJlclRydXN0IFJv +b3QgNTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALwSbj+KfHqXAewe +uzlaAvR4RKJIG457SVJ6uHtHs6+Um2+7lvoramVcuByUc76/iQoigO5X/IwFu3Cf +lzkE2qOHXKjlyq/AM5rVN1xLrOSA0KYjYPv9ci6UncfOwgQy73hgXe2thw9FZR48 +mgqavl0dmezn8tHGehfZrZtUln/EfGC/haoVNR1A2hG87FQhKC0joajwzy3N3fx+ +D17hZQdWywe00lboXjHMGGPEhtIthc+Tkqtt/mg5+95zvYb45EZ66p8My/QZ/mO8 +0Sx7iDM29uThnAxTgWAc2i6rlqkWiBNQmbK9Vd8VMH7o5Zj7cH5stQf8/Ea30O03 +ln4y/iECAwEAAaNaMFgwEgYDVR0TAQH/BAgwBgEB/wIBBTAOBgNVHQ8BAf8EBAMC +AQYwFwYDVR0gBBAwDjAMBgoqhkiG+GMBAgEDMBkGA1UdDgQSBBB2CkkhOEyf3vjE +ScdxcZGdMA0GCSqGSIb3DQEBBQUAA4IBAQBBOtQYW9q43iEc4Y4J5fFoNP/elvQH +9ac886xKsZv6kvqb7eYyIapKdsXcTzjl39WG5NXIdn2Y17HNj021kSNsi4rr6nzv +FJTExvAfSi0ycWMrY5EmAgm2gB3t4sy4f9uHY8jh0GwmsTUdQGYQG82VVBgzYewT +T9oT95mvPtDPjqZyorPDBZrJJ32SzH5SjbOrcG2eiZ9N6xp1wpiq1QIW1wyKvyXk +6y28mOlYOBl8uTf+2+KZCHMGx5eDan0QAS8yuRcFSmXmL86+XlOmgumaUwqEdC2D +ysiUFnZflGEo8IWnObvXi9moshMdVAk0JH0ggX1mfqKQdFwQxr3sqxvC +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: 438 (0x1b6) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=GTE Corporation, OU=GTE CyberTrust Solutions, Inc., CN=GTE CyberTrust Root 5 + Validity + Not Before: Aug 14 14:50:00 1998 GMT + Not After : Aug 14 23:59:00 2013 GMT + Subject: C=US, O=GTE Corporation, OU=GTE CyberTrust Solutions, Inc., CN=GTE CyberTrust Root 5 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:bc:12:6e:3f:8a:7c:7a:97:01:ec:1e:bb:39:5a: + 02:f4:78:44:a2:48:1b:8e:7b:49:52:7a:b8:7b:47: + b3:af:94:9b:6f:bb:96:fa:2b:6a:65:5c:b8:1c:94: + 73:be:bf:89:0a:22:80:ee:57:fc:8c:05:bb:70:9f: + 97:39:04:da:a3:87:5c:a8:e5:ca:af:c0:33:9a:d5: + 37:5c:4b:ac:e4:80:d0:a6:23:60:fb:fd:72:2e:94: + 9d:c7:ce:c2:04:32:ef:78:60:5d:ed:ad:87:0f:45: + 65:1e:3c:9a:0a:9a:be:5d:1d:99:ec:e7:f2:d1:c6: + 7a:17:d9:ad:9b:54:96:7f:c4:7c:60:bf:85:aa:15: + 35:1d:40:da:11:bc:ec:54:21:28:2d:23:a1:a8:f0: + cf:2d:cd:dd:fc:7e:0f:5e:e1:65:07:56:cb:07:b4: + d2:56:e8:5e:31:cc:18:63:c4:86:d2:2d:85:cf:93: + 92:ab:6d:fe:68:39:fb:de:73:bd:86:f8:e4:46:7a: + ea:9f:0c:cb:f4:19:fe:63:bc:d1:2c:7b:88:33:36: + f6:e4:e1:9c:0c:53:81:60:1c:da:2e:ab:96:a9:16: + 88:13:50:99:b2:bd:55:df:15:30:7e:e8:e5:98:fb: + 70:7e:6c:b5:07:fc:fc:46:b7:d0:ed:37:96:7e:32: + fe:21 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE, pathlen:5 + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Certificate Policies: + Policy: 1.2.840.113763.1.2.1.3 + + X509v3 Subject Key Identifier: + 76:0A:49:21:38:4C:9F:DE:F8:C4:49:C7:71:71:91:9D + Signature Algorithm: sha1WithRSAEncryption + 41:3a:d4:18:5b:da:b8:de:21:1c:e1:8e:09:e5:f1:68:34:ff: + de:96:f4:07:f5:a7:3c:f3:ac:4a:b1:9b:fa:92:fa:9b:ed:e6: + 32:21:aa:4a:76:c5:dc:4f:38:e5:df:d5:86:e4:d5:c8:76:7d: + 98:d7:b1:cd:8f:4d:b5:91:23:6c:8b:8a:eb:ea:7c:ef:14:94: + c4:c6:f0:1f:4a:2d:32:71:63:2b:63:91:26:02:09:b6:80:1d: + ed:e2:cc:b8:7f:db:87:63:c8:e1:d0:6c:26:b1:35:1d:40:66: + 10:1b:cd:95:54:18:33:61:ec:13:4f:da:13:f7:99:af:3e:d0: + cf:8e:a6:72:a2:b3:c3:05:9a:c9:27:7d:92:cc:7e:52:8d:b3: + ab:70:6d:9e:89:9f:4d:eb:1a:75:c2:98:aa:d5:02:16:d7:0c: + 8a:bf:25:e4:eb:2d:bc:98:e9:58:38:19:7c:b9:37:fe:db:e2: + 99:08:73:06:c7:97:83:6a:7d:10:01:2f:32:b9:17:05:4a:65: + e6:2f:ce:be:5e:53:a6:82:e9:9a:53:0a:84:74:2d:83:ca:c8: + 94:16:76:5f:94:61:28:f0:85:a7:39:bb:d7:8b:d9:a8:b2:13: + 1d:54:09:34:24:7d:20:81:7d:66:7e:a2:90:74:5c:10:c6:bd: + ec:ab:1b:c2 + +GTE CyberTrust Root CA +====================== +MD5 Fingerprint: C4:D7:F0:B2:A3:C5:7D:61:67:F0:04:CD:43:D3:BA:58 +PEM Data: +-----BEGIN CERTIFICATE----- +MIIB+jCCAWMCAgGjMA0GCSqGSIb3DQEBBAUAMEUxCzAJBgNVBAYTAlVTMRgwFgYD +VQQKEw9HVEUgQ29ycG9yYXRpb24xHDAaBgNVBAMTE0dURSBDeWJlclRydXN0IFJv +b3QwHhcNOTYwMjIzMjMwMTAwWhcNMDYwMjIzMjM1OTAwWjBFMQswCQYDVQQGEwJV +UzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMRwwGgYDVQQDExNHVEUgQ3liZXJU +cnVzdCBSb290MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC45k+625h8cXyv +RLfTD0bZZOWTwUKOx7pJjTUteueLveUFMVnGsS8KDPufpz+iCWaEVh43KRuH6X4M +ypqfpX/1FZSj1aJGgthoTNE3FQZor734sLPwKfWVWgkWYXcKIiXUT0Wqx73llt/5 +1KiOQswkwB6RJ0q1bQaAYznEol44AwIDAQABMA0GCSqGSIb3DQEBBAUAA4GBABKz +dcZfHeFhVYAA1IFLezEPI2PnPfMD+fQ2qLvZ46WXTeorKeDWanOB5sCJo9Px4KWl +IjeaY8JIILTbcuPI9tl8vrGvU9oUtCG41tWW4/5ODFlitppK+ULdjG+BqXH/9Apy +bW1EDp3zdHSo1TRJ6V6e6bR64eVaH4QwnNOfpSXY +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 1 (0x0) + Serial Number: 419 (0x1a3) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=US, O=GTE Corporation, CN=GTE CyberTrust Root + Validity + Not Before: Feb 23 23:01:00 1996 GMT + Not After : Feb 23 23:59:00 2006 GMT + Subject: C=US, O=GTE Corporation, CN=GTE CyberTrust Root + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:b8:e6:4f:ba:db:98:7c:71:7c:af:44:b7:d3:0f: + 46:d9:64:e5:93:c1:42:8e:c7:ba:49:8d:35:2d:7a: + e7:8b:bd:e5:05:31:59:c6:b1:2f:0a:0c:fb:9f:a7: + 3f:a2:09:66:84:56:1e:37:29:1b:87:e9:7e:0c:ca: + 9a:9f:a5:7f:f5:15:94:a3:d5:a2:46:82:d8:68:4c: + d1:37:15:06:68:af:bd:f8:b0:b3:f0:29:f5:95:5a: + 09:16:61:77:0a:22:25:d4:4f:45:aa:c7:bd:e5:96: + df:f9:d4:a8:8e:42:cc:24:c0:1e:91:27:4a:b5:6d: + 06:80:63:39:c4:a2:5e:38:03 + Exponent: 65537 (0x10001) + Signature Algorithm: md5WithRSAEncryption + 12:b3:75:c6:5f:1d:e1:61:55:80:00:d4:81:4b:7b:31:0f:23: + 63:e7:3d:f3:03:f9:f4:36:a8:bb:d9:e3:a5:97:4d:ea:2b:29: + e0:d6:6a:73:81:e6:c0:89:a3:d3:f1:e0:a5:a5:22:37:9a:63: + c2:48:20:b4:db:72:e3:c8:f6:d9:7c:be:b1:af:53:da:14:b4: + 21:b8:d6:d5:96:e3:fe:4e:0c:59:62:b6:9a:4a:f9:42:dd:8c: + 6f:81:a9:71:ff:f4:0a:72:6d:6d:44:0e:9d:f3:74:74:a8:d5: + 34:49:e9:5e:9e:e9:b4:7a:e1:e5:5a:1f:84:30:9c:d3:9f:a5: + 25:d8 + +GlobalSign Partners CA +====================== +MD5 Fingerprint: 3C:75:CD:4C:BD:A9:D0:8A:79:4F:50:16:37:84:F4:2B +PEM Data: +-----BEGIN CERTIFICATE----- +MIIDnjCCAoagAwIBAgILAgAAAAAA1ni50a8wDQYJKoZIhvcNAQEEBQAwVzELMAkG +A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv +b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05OTAxMjgxMjAw +MDBaFw0wOTAxMjgxMjAwMDBaMF8xCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i +YWxTaWduIG52LXNhMRQwEgYDVQQLEwtQYXJ0bmVycyBDQTEfMB0GA1UEAxMWR2xv +YmFsU2lnbiBQYXJ0bmVycyBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBANIs+DKsShJ6N8gpkaWujG4eDsA0M4jlM3EWHHiEaMMYNFAuFj6xlIJPsZqf +APjGETXGaXuYAq0ABohs50wzKACIJ0Yfh7NxdWO8MruI3mYYDlAGk7T2vBQ3MD0i +3z3/dX7ZChrFn7P80KyzCHqJ0wHoAFznSgs9TXsmordiBovaRt2TFz8/WwJLC7aI +IBGSAK27xy7U40Wu9YlafI2krYVkMsAnjMbyioCShiRWWY10aKKDQrOePVBBhm8g +bvb9ztMZ4zLMj+2aXm0fKPVSrG4YXvg90ZLlumwBiEsK8i3eZTMFQqBMqjF2vv2/ +gXj5cRxGXi0VlS0wWY5MQdFiqz0CAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgAGMB0G +A1UdDgQWBBRDJI1wFQhiVZxPDEAXXYZeD6JM+zAfBgNVHSMEGDAWgBRge2YaRQ2X +yolQL30EzTSo//z9SzAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBAUAA4IB +AQBm7bSIaRGZgiGDrKFti5uErQ8tyB6Mynt+rarUjt4H1p5Fx6W4nAc5YCVVGsBP +GeXPFylJiRg1ZuXrKEBOV8mvs+S4IAWjO5VQkUmUKX0s5YhBpUWIXp2CJ/fS71u1 +T5++/jVlLFVkn+FR2iJhd7pYTo/GeVlZbjCAok+QbiELrdBoOZAQm+0iZW8eETjm +f4zS8zltR9Uh6Op1OkHRrfYWnV0LIb3zH2MGJR3BHzVxLOsgGdXBsOw95W/tAgc/ +E3tmktZEwZj3X1CLelvCb22w0fjldKBAN6MlD+Q9ymQxk5BcMHu5OTGaXkzNuUFP +UOQ9OK7IZtnHO11RR6ybq/Kt +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: + 02:00:00:00:00:00:d6:78:b9:d1:af + Signature Algorithm: md5WithRSAEncryption + Issuer: C=BE, O=GlobalSign nv-sa, OU=Root CA, CN=GlobalSign Root CA + Validity + Not Before: Jan 28 12:00:00 1999 GMT + Not After : Jan 28 12:00:00 2009 GMT + Subject: C=BE, O=GlobalSign nv-sa, OU=Partners CA, CN=GlobalSign Partners CA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:d2:2c:f8:32:ac:4a:12:7a:37:c8:29:91:a5:ae: + 8c:6e:1e:0e:c0:34:33:88:e5:33:71:16:1c:78:84: + 68:c3:18:34:50:2e:16:3e:b1:94:82:4f:b1:9a:9f: + 00:f8:c6:11:35:c6:69:7b:98:02:ad:00:06:88:6c: + e7:4c:33:28:00:88:27:46:1f:87:b3:71:75:63:bc: + 32:bb:88:de:66:18:0e:50:06:93:b4:f6:bc:14:37: + 30:3d:22:df:3d:ff:75:7e:d9:0a:1a:c5:9f:b3:fc: + d0:ac:b3:08:7a:89:d3:01:e8:00:5c:e7:4a:0b:3d: + 4d:7b:26:a2:b7:62:06:8b:da:46:dd:93:17:3f:3f: + 5b:02:4b:0b:b6:88:20:11:92:00:ad:bb:c7:2e:d4: + e3:45:ae:f5:89:5a:7c:8d:a4:ad:85:64:32:c0:27: + 8c:c6:f2:8a:80:92:86:24:56:59:8d:74:68:a2:83: + 42:b3:9e:3d:50:41:86:6f:20:6e:f6:fd:ce:d3:19: + e3:32:cc:8f:ed:9a:5e:6d:1f:28:f5:52:ac:6e:18: + 5e:f8:3d:d1:92:e5:ba:6c:01:88:4b:0a:f2:2d:de: + 65:33:05:42:a0:4c:aa:31:76:be:fd:bf:81:78:f9: + 71:1c:46:5e:2d:15:95:2d:30:59:8e:4c:41:d1:62: + ab:3d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + 43:24:8D:70:15:08:62:55:9C:4F:0C:40:17:5D:86:5E:0F:A2:4C:FB + X509v3 Authority Key Identifier: + keyid:60:7B:66:1A:45:0D:97:CA:89:50:2F:7D:04:CD:34:A8:FF:FC:FD:4B + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: md5WithRSAEncryption + 66:ed:b4:88:69:11:99:82:21:83:ac:a1:6d:8b:9b:84:ad:0f: + 2d:c8:1e:8c:ca:7b:7e:ad:aa:d4:8e:de:07:d6:9e:45:c7:a5: + b8:9c:07:39:60:25:55:1a:c0:4f:19:e5:cf:17:29:49:89:18: + 35:66:e5:eb:28:40:4e:57:c9:af:b3:e4:b8:20:05:a3:3b:95: + 50:91:49:94:29:7d:2c:e5:88:41:a5:45:88:5e:9d:82:27:f7: + d2:ef:5b:b5:4f:9f:be:fe:35:65:2c:55:64:9f:e1:51:da:22: + 61:77:ba:58:4e:8f:c6:79:59:59:6e:30:80:a2:4f:90:6e:21: + 0b:ad:d0:68:39:90:10:9b:ed:22:65:6f:1e:11:38:e6:7f:8c: + d2:f3:39:6d:47:d5:21:e8:ea:75:3a:41:d1:ad:f6:16:9d:5d: + 0b:21:bd:f3:1f:63:06:25:1d:c1:1f:35:71:2c:eb:20:19:d5: + c1:b0:ec:3d:e5:6f:ed:02:07:3f:13:7b:66:92:d6:44:c1:98: + f7:5f:50:8b:7a:5b:c2:6f:6d:b0:d1:f8:e5:74:a0:40:37:a3: + 25:0f:e4:3d:ca:64:31:93:90:5c:30:7b:b9:39:31:9a:5e:4c: + cd:b9:41:4f:50:e4:3d:38:ae:c8:66:d9:c7:3b:5d:51:47:ac: + 9b:ab:f2:ad + +GlobalSign Primary Class 1 CA +============================= +MD5 Fingerprint: 5C:AC:59:01:A4:86:53:CB:10:66:B5:D6:D6:71:FF:01 +PEM Data: +-----BEGIN CERTIFICATE----- +MIIDrDCCApSgAwIBAgILAgAAAAAA1ni4N88wDQYJKoZIhvcNAQEEBQAwVzELMAkG +A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv +b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MTUxMjAw +MDBaFw0wOTAxMjgxMjAwMDBaMG0xCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i +YWxTaWduIG52LXNhMRswGQYDVQQLExJQcmltYXJ5IENsYXNzIDEgQ0ExJjAkBgNV +BAMTHUdsb2JhbFNpZ24gUHJpbWFyeSBDbGFzcyAxIENBMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAvSA1R9Eo1gijEjkjRw29cCFSDlcxlaY0V2vsfkN5 +wwZSSM28taGZvdgfMrzP125ybS53IpCCTkuPmgwBQprZcFm2nR/mY9EMrR1O+IWB ++a7vn6ZSYUR5GnVF4GFWRW1CjD1yy6akErea9dZg0GBQs46mpuy09BLNf6jO77Ph +hTD+csTm53eznlhB1lGDiAfGtmlPNt7RC0g/vdafIXRkbycGPkv9Dqabv6RIV4yQ +7okYCwKBGL5n/lNgiCe6o3M0S1pWtN5zBe2Yll3sSudA/EsJYuvQ4zFPhdF6q1ln +K/uID+uqg701/WEn7GYOQlf3acIM7/xqwm5J2o9BOK5IqQIDAQABo2MwYTAOBgNV +HQ8BAf8EBAMCAAYwHQYDVR0OBBYEFPzgZvZaNZnrQB7SuB5DvJiOH4rDMB8GA1Ud +IwQYMBaAFGB7ZhpFDZfKiVAvfQTNNKj//P1LMA8GA1UdEwEB/wQFMAMBAf8wDQYJ +KoZIhvcNAQEEBQADggEBAJujCETO8pCdcfMyswVqterPKZjeVT6gFn0GekTWr9L6 +E1iM+BzHqx20G+9paJhcCDmP4Pf7SMwh57gz2wWqNCRsSuXpe2Deg7MfCr5BdfzM +MEi3wSYdBDOqtnjtKsu6VpcybvcxlS5G8hTuJ8f3Yom5XFrTOIpk9Te08bM0ctXV +IT1L13iT1zFmNR6j2EdJbxyt4YB/+JgkbHOsDsIadwKjJge3x2tdvILVKkgdY89Q +Mqb7HBhHFQpbDFw4JJoEmKgISF98NIdjqy2NTAB3lBt2uvUWGKMVry+U9ikAdsEV +F9PpN0121MtLKVkkrNpKoOpj3l9Usfrz0UXLxWS0cyE= +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: + 02:00:00:00:00:00:d6:78:b8:37:cf + Signature Algorithm: md5WithRSAEncryption + Issuer: C=BE, O=GlobalSign nv-sa, OU=Root CA, CN=GlobalSign Root CA + Validity + Not Before: Sep 15 12:00:00 1998 GMT + Not After : Jan 28 12:00:00 2009 GMT + Subject: C=BE, O=GlobalSign nv-sa, OU=Primary Class 1 CA, CN=GlobalSign Primary Class 1 CA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:bd:20:35:47:d1:28:d6:08:a3:12:39:23:47:0d: + bd:70:21:52:0e:57:31:95:a6:34:57:6b:ec:7e:43: + 79:c3:06:52:48:cd:bc:b5:a1:99:bd:d8:1f:32:bc: + cf:d7:6e:72:6d:2e:77:22:90:82:4e:4b:8f:9a:0c: + 01:42:9a:d9:70:59:b6:9d:1f:e6:63:d1:0c:ad:1d: + 4e:f8:85:81:f9:ae:ef:9f:a6:52:61:44:79:1a:75: + 45:e0:61:56:45:6d:42:8c:3d:72:cb:a6:a4:12:b7: + 9a:f5:d6:60:d0:60:50:b3:8e:a6:a6:ec:b4:f4:12: + cd:7f:a8:ce:ef:b3:e1:85:30:fe:72:c4:e6:e7:77: + b3:9e:58:41:d6:51:83:88:07:c6:b6:69:4f:36:de: + d1:0b:48:3f:bd:d6:9f:21:74:64:6f:27:06:3e:4b: + fd:0e:a6:9b:bf:a4:48:57:8c:90:ee:89:18:0b:02: + 81:18:be:67:fe:53:60:88:27:ba:a3:73:34:4b:5a: + 56:b4:de:73:05:ed:98:96:5d:ec:4a:e7:40:fc:4b: + 09:62:eb:d0:e3:31:4f:85:d1:7a:ab:59:67:2b:fb: + 88:0f:eb:aa:83:bd:35:fd:61:27:ec:66:0e:42:57: + f7:69:c2:0c:ef:fc:6a:c2:6e:49:da:8f:41:38:ae: + 48:a9 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + FC:E0:66:F6:5A:35:99:EB:40:1E:D2:B8:1E:43:BC:98:8E:1F:8A:C3 + X509v3 Authority Key Identifier: + keyid:60:7B:66:1A:45:0D:97:CA:89:50:2F:7D:04:CD:34:A8:FF:FC:FD:4B + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: md5WithRSAEncryption + 9b:a3:08:44:ce:f2:90:9d:71:f3:32:b3:05:6a:b5:ea:cf:29: + 98:de:55:3e:a0:16:7d:06:7a:44:d6:af:d2:fa:13:58:8c:f8: + 1c:c7:ab:1d:b4:1b:ef:69:68:98:5c:08:39:8f:e0:f7:fb:48: + cc:21:e7:b8:33:db:05:aa:34:24:6c:4a:e5:e9:7b:60:de:83: + b3:1f:0a:be:41:75:fc:cc:30:48:b7:c1:26:1d:04:33:aa:b6: + 78:ed:2a:cb:ba:56:97:32:6e:f7:31:95:2e:46:f2:14:ee:27: + c7:f7:62:89:b9:5c:5a:d3:38:8a:64:f5:37:b4:f1:b3:34:72: + d5:d5:21:3d:4b:d7:78:93:d7:31:66:35:1e:a3:d8:47:49:6f: + 1c:ad:e1:80:7f:f8:98:24:6c:73:ac:0e:c2:1a:77:02:a3:26: + 07:b7:c7:6b:5d:bc:82:d5:2a:48:1d:63:cf:50:32:a6:fb:1c: + 18:47:15:0a:5b:0c:5c:38:24:9a:04:98:a8:08:48:5f:7c:34: + 87:63:ab:2d:8d:4c:00:77:94:1b:76:ba:f5:16:18:a3:15:af: + 2f:94:f6:29:00:76:c1:15:17:d3:e9:37:4d:76:d4:cb:4b:29: + 59:24:ac:da:4a:a0:ea:63:de:5f:54:b1:fa:f3:d1:45:cb:c5: + 64:b4:73:21 + +GlobalSign Primary Class 2 CA +============================= +MD5 Fingerprint: A9:A9:42:59:7E:BE:5A:94:E4:2C:C6:8B:1C:2A:44:B6 +PEM Data: +-----BEGIN CERTIFICATE----- +MIIDrDCCApSgAwIBAgILAgAAAAAA1ni4jY0wDQYJKoZIhvcNAQEEBQAwVzELMAkG +A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv +b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05OTAxMjgxMjAw +MDBaFw0wOTAxMjgxMjAwMDBaMG0xCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i +YWxTaWduIG52LXNhMRswGQYDVQQLExJQcmltYXJ5IENsYXNzIDIgQ0ExJjAkBgNV +BAMTHUdsb2JhbFNpZ24gUHJpbWFyeSBDbGFzcyAyIENBMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAkoz+7/RFjhdBbvzYvyFvqwadUsEsAJ0/joW4f0qP +vaBjKspJJ65agvR04lWS/8LRqnmitvrVnYIET8ayxl5jpzq62O7rim+ftrsoQcAi ++05IGgaS17/Xz7nZvThPOw1EblVB/vwJ29i/844h8egStfYTpdPGTJMisAL/7h0M +xKhrT3VoVujcKBJQ96gknS4kOfsJBd7lo2RJIdBofnEwkbFg4Dn0UPh6TZgAa3x5 +uk7OSuK6Nh23xTYVlZxkQupfxLr1QAW+4TpZvYSnGbjeTVNQzgfR0lHT7w2BbObn +bctdfD98zOxPgycl/3BQ9oNZdYQGZlgs3omNAKZJ+aVDdwIDAQABo2MwYTAOBgNV +HQ8BAf8EBAMCAAYwHQYDVR0OBBYEFHznsrEs3rGna+l2DOGj/U5sx7n2MB8GA1Ud +IwQYMBaAFGB7ZhpFDZfKiVAvfQTNNKj//P1LMA8GA1UdEwEB/wQFMAMBAf8wDQYJ +KoZIhvcNAQEEBQADggEBAGPdWc6KeaqYnU7FiWQ3foqTZy8Q6m8nw413bfJcVpQZ +GmlgMEZdj/JtRTyONZd8L7hR4uiJvYjPJxwINFyIwWgk25GF5M/7+0ON6CUBG8QO +9wBCSIYfJAhYWoyN8mtHLGiRsWlC/Q2NySbmkoamZG6Sxc4+PH1x4yOkq8fVqKnf +gqc76IbVw08Y40TQ4NzzxWgu/qUvBYTIfkdCU2uHSv4y/14+cIy3qBXMF8L/RuzQ +7C20bhIoqflA6evUZpdTqWlVwKmqsi7N0Wn0vvi7fGnuVKbbnvtapj7+mu+UUUt1 +7tjU4ZrxAlYTiQ6nQouWi4UMG4W+Jq6rppm8IvFz30I= +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: + 02:00:00:00:00:00:d6:78:b8:8d:8d + Signature Algorithm: md5WithRSAEncryption + Issuer: C=BE, O=GlobalSign nv-sa, OU=Root CA, CN=GlobalSign Root CA + Validity + Not Before: Jan 28 12:00:00 1999 GMT + Not After : Jan 28 12:00:00 2009 GMT + Subject: C=BE, O=GlobalSign nv-sa, OU=Primary Class 2 CA, CN=GlobalSign Primary Class 2 CA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:92:8c:fe:ef:f4:45:8e:17:41:6e:fc:d8:bf:21: + 6f:ab:06:9d:52:c1:2c:00:9d:3f:8e:85:b8:7f:4a: + 8f:bd:a0:63:2a:ca:49:27:ae:5a:82:f4:74:e2:55: + 92:ff:c2:d1:aa:79:a2:b6:fa:d5:9d:82:04:4f:c6: + b2:c6:5e:63:a7:3a:ba:d8:ee:eb:8a:6f:9f:b6:bb: + 28:41:c0:22:fb:4e:48:1a:06:92:d7:bf:d7:cf:b9: + d9:bd:38:4f:3b:0d:44:6e:55:41:fe:fc:09:db:d8: + bf:f3:8e:21:f1:e8:12:b5:f6:13:a5:d3:c6:4c:93: + 22:b0:02:ff:ee:1d:0c:c4:a8:6b:4f:75:68:56:e8: + dc:28:12:50:f7:a8:24:9d:2e:24:39:fb:09:05:de: + e5:a3:64:49:21:d0:68:7e:71:30:91:b1:60:e0:39: + f4:50:f8:7a:4d:98:00:6b:7c:79:ba:4e:ce:4a:e2: + ba:36:1d:b7:c5:36:15:95:9c:64:42:ea:5f:c4:ba: + f5:40:05:be:e1:3a:59:bd:84:a7:19:b8:de:4d:53: + 50:ce:07:d1:d2:51:d3:ef:0d:81:6c:e6:e7:6d:cb: + 5d:7c:3f:7c:cc:ec:4f:83:27:25:ff:70:50:f6:83: + 59:75:84:06:66:58:2c:de:89:8d:00:a6:49:f9:a5: + 43:77 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + 7C:E7:B2:B1:2C:DE:B1:A7:6B:E9:76:0C:E1:A3:FD:4E:6C:C7:B9:F6 + X509v3 Authority Key Identifier: + keyid:60:7B:66:1A:45:0D:97:CA:89:50:2F:7D:04:CD:34:A8:FF:FC:FD:4B + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: md5WithRSAEncryption + 63:dd:59:ce:8a:79:aa:98:9d:4e:c5:89:64:37:7e:8a:93:67: + 2f:10:ea:6f:27:c3:8d:77:6d:f2:5c:56:94:19:1a:69:60:30: + 46:5d:8f:f2:6d:45:3c:8e:35:97:7c:2f:b8:51:e2:e8:89:bd: + 88:cf:27:1c:08:34:5c:88:c1:68:24:db:91:85:e4:cf:fb:fb: + 43:8d:e8:25:01:1b:c4:0e:f7:00:42:48:86:1f:24:08:58:5a: + 8c:8d:f2:6b:47:2c:68:91:b1:69:42:fd:0d:8d:c9:26:e6:92: + 86:a6:64:6e:92:c5:ce:3e:3c:7d:71:e3:23:a4:ab:c7:d5:a8: + a9:df:82:a7:3b:e8:86:d5:c3:4f:18:e3:44:d0:e0:dc:f3:c5: + 68:2e:fe:a5:2f:05:84:c8:7e:47:42:53:6b:87:4a:fe:32:ff: + 5e:3e:70:8c:b7:a8:15:cc:17:c2:ff:46:ec:d0:ec:2d:b4:6e: + 12:28:a9:f9:40:e9:eb:d4:66:97:53:a9:69:55:c0:a9:aa:b2: + 2e:cd:d1:69:f4:be:f8:bb:7c:69:ee:54:a6:db:9e:fb:5a:a6: + 3e:fe:9a:ef:94:51:4b:75:ee:d8:d4:e1:9a:f1:02:56:13:89: + 0e:a7:42:8b:96:8b:85:0c:1b:85:be:26:ae:ab:a6:99:bc:22: + f1:73:df:42 + +GlobalSign Primary Class 3 CA +============================= +MD5 Fingerprint: 98:12:A3:4B:95:A9:96:64:94:E7:50:8C:3E:E1:83:5A +PEM Data: +-----BEGIN CERTIFICATE----- +MIIDrDCCApSgAwIBAgILAgAAAAAA1ni41sMwDQYJKoZIhvcNAQEEBQAwVzELMAkG +A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv +b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05OTAxMjgxMjAw +MDBaFw0wOTAxMjgxMjAwMDBaMG0xCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i +YWxTaWduIG52LXNhMRswGQYDVQQLExJQcmltYXJ5IENsYXNzIDMgQ0ExJjAkBgNV +BAMTHUdsb2JhbFNpZ24gUHJpbWFyeSBDbGFzcyAzIENBMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAkV5WZdbAwAScv0fEXHt6MQH5WJaZ4xyEL9xWj631 +WYHVQ2ZdWpOMdcqp5xHBURAUYMks1HuvxneGq3onrm+VuQvKtkb7fhr0DRRt0slO +sq7wVPZcQEw2SHToVIxlZhCnvSu3II0FSa14fdIkI1Dj8LR5mwE5/6870y3u4UmN +jS88akFFL5vjPeES5JF1ns+gPjySgW+KLhjc4PKMjP2H2Qf0QJTJTk9D32dWb70D +UHyZZ6S5PJFsAm6E1vxG98xvGD4X8O8LZBZX5qyG8UiqQ8HJJ3hzREXihX26/7Ph ++xsFpEs7mRIlAVAUaq9d6sgM7uTa7EuLXGgTldzDtTA61wIDAQABo2MwYTAOBgNV +HQ8BAf8EBAMCAAYwHQYDVR0OBBYEFMw2zBe0RZEv7c87MEh3+7UUmb7jMB8GA1Ud +IwQYMBaAFGB7ZhpFDZfKiVAvfQTNNKj//P1LMA8GA1UdEwEB/wQFMAMBAf8wDQYJ +KoZIhvcNAQEEBQADggEBAFeyVMy9lRdkYIm2U5EMRZLDPahsw8yyGPV4QXTYfaMn +r3cNWT6UHWn6idMMvRoB9D/o4Hcagiha5mLXt+M2yQ6feuPC08xZiQzvFovwNnci +yqS2t8FCZwFAY8znOGSHWxSWZnstFO69SW3/d9DiTlvTgMJND8q4nYGXpzRux+Oc +SOW0qkX19mVMSPISwtKTjMIVJPMrUv/jCK64btYsEs85yxIq56l7X5g9o+HMpmOJ +XH0xdfnV1l3y0NQ9355xqA7c5CCXeOZ/U6QNUU+OOwOuow1aTcN55zVYcELJXqFe +tNkio0RTNaTQz3OAxc+fVph2+RRMd4eCydx+XTTVNnU= +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: + 02:00:00:00:00:00:d6:78:b8:d6:c3 + Signature Algorithm: md5WithRSAEncryption + Issuer: C=BE, O=GlobalSign nv-sa, OU=Root CA, CN=GlobalSign Root CA + Validity + Not Before: Jan 28 12:00:00 1999 GMT + Not After : Jan 28 12:00:00 2009 GMT + Subject: C=BE, O=GlobalSign nv-sa, OU=Primary Class 3 CA, CN=GlobalSign Primary Class 3 CA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:91:5e:56:65:d6:c0:c0:04:9c:bf:47:c4:5c:7b: + 7a:31:01:f9:58:96:99:e3:1c:84:2f:dc:56:8f:ad: + f5:59:81:d5:43:66:5d:5a:93:8c:75:ca:a9:e7:11: + c1:51:10:14:60:c9:2c:d4:7b:af:c6:77:86:ab:7a: + 27:ae:6f:95:b9:0b:ca:b6:46:fb:7e:1a:f4:0d:14: + 6d:d2:c9:4e:b2:ae:f0:54:f6:5c:40:4c:36:48:74: + e8:54:8c:65:66:10:a7:bd:2b:b7:20:8d:05:49:ad: + 78:7d:d2:24:23:50:e3:f0:b4:79:9b:01:39:ff:af: + 3b:d3:2d:ee:e1:49:8d:8d:2f:3c:6a:41:45:2f:9b: + e3:3d:e1:12:e4:91:75:9e:cf:a0:3e:3c:92:81:6f: + 8a:2e:18:dc:e0:f2:8c:8c:fd:87:d9:07:f4:40:94: + c9:4e:4f:43:df:67:56:6f:bd:03:50:7c:99:67:a4: + b9:3c:91:6c:02:6e:84:d6:fc:46:f7:cc:6f:18:3e: + 17:f0:ef:0b:64:16:57:e6:ac:86:f1:48:aa:43:c1: + c9:27:78:73:44:45:e2:85:7d:ba:ff:b3:e1:fb:1b: + 05:a4:4b:3b:99:12:25:01:50:14:6a:af:5d:ea:c8: + 0c:ee:e4:da:ec:4b:8b:5c:68:13:95:dc:c3:b5:30: + 3a:d7 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + CC:36:CC:17:B4:45:91:2F:ED:CF:3B:30:48:77:FB:B5:14:99:BE:E3 + X509v3 Authority Key Identifier: + keyid:60:7B:66:1A:45:0D:97:CA:89:50:2F:7D:04:CD:34:A8:FF:FC:FD:4B + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: md5WithRSAEncryption + 57:b2:54:cc:bd:95:17:64:60:89:b6:53:91:0c:45:92:c3:3d: + a8:6c:c3:cc:b2:18:f5:78:41:74:d8:7d:a3:27:af:77:0d:59: + 3e:94:1d:69:fa:89:d3:0c:bd:1a:01:f4:3f:e8:e0:77:1a:82: + 28:5a:e6:62:d7:b7:e3:36:c9:0e:9f:7a:e3:c2:d3:cc:59:89: + 0c:ef:16:8b:f0:36:77:22:ca:a4:b6:b7:c1:42:67:01:40:63: + cc:e7:38:64:87:5b:14:96:66:7b:2d:14:ee:bd:49:6d:ff:77: + d0:e2:4e:5b:d3:80:c2:4d:0f:ca:b8:9d:81:97:a7:34:6e:c7: + e3:9c:48:e5:b4:aa:45:f5:f6:65:4c:48:f2:12:c2:d2:93:8c: + c2:15:24:f3:2b:52:ff:e3:08:ae:b8:6e:d6:2c:12:cf:39:cb: + 12:2a:e7:a9:7b:5f:98:3d:a3:e1:cc:a6:63:89:5c:7d:31:75: + f9:d5:d6:5d:f2:d0:d4:3d:df:9e:71:a8:0e:dc:e4:20:97:78: + e6:7f:53:a4:0d:51:4f:8e:3b:03:ae:a3:0d:5a:4d:c3:79:e7: + 35:58:70:42:c9:5e:a1:5e:b4:d9:22:a3:44:53:35:a4:d0:cf: + 73:80:c5:cf:9f:56:98:76:f9:14:4c:77:87:82:c9:dc:7e:5d: + 34:d5:36:75 + +GlobalSign Root CA +================== +MD5 Fingerprint: AB:BF:EA:E3:6B:29:A6:CC:A6:78:35:99:EF:AD:2B:80 +PEM Data: +-----BEGIN CERTIFICATE----- +MIIDdTCCAl2gAwIBAgILAgAAAAAA1ni3lAUwDQYJKoZIhvcNAQEEBQAwVzELMAkG +A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv +b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw +MDBaFw0xNDAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i +YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT +aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ +jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp +xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp +1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG +snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ +U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8 +9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIABjAdBgNVHQ4EFgQU +YHtmGkUNl8qJUC99BM00qP/8/UswDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0B +AQQFAAOCAQEArqqf/LfSyx9fOSkoGJ40yWxPbxrwZKJwSk8ThptgKJ7ogUmYfQq7 +5bCdPTbbjwVR/wkxKh/diXeeDy5slQTthsu0AD+EAk2AaioteAuubyuig0SDH81Q +gkwkr733pbTIWg/050deSY43lv6aiAU62cDbKYfmGZZHpzqmjIs8d/5GY6dT2iHR +rH5Jokvmw2dZL7OKDrssvamqQnw1wdh/1acxOk5jQzmvCLBhNIzTmKlDNPYPhyk7 +ncJWWJh3w/cbrPad+D6qp1RF8PX51TFl/mtYnHGzHtdS6jIX/EBgHcl5JLL2bP2o +Zg6C3ZjL2sJETy6ge/L3ayx2EYRGinij4w== +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: + 02:00:00:00:00:00:d6:78:b7:94:05 + Signature Algorithm: md5WithRSAEncryption + Issuer: C=BE, O=GlobalSign nv-sa, OU=Root CA, CN=GlobalSign Root CA + Validity + Not Before: Sep 1 12:00:00 1998 GMT + Not After : Jan 28 12:00:00 2014 GMT + Subject: C=BE, O=GlobalSign nv-sa, OU=Root CA, CN=GlobalSign Root CA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:da:0e:e6:99:8d:ce:a3:e3:4f:8a:7e:fb:f1:8b: + 83:25:6b:ea:48:1f:f1:2a:b0:b9:95:11:04:bd:f0: + 63:d1:e2:67:66:cf:1c:dd:cf:1b:48:2b:ee:8d:89: + 8e:9a:af:29:80:65:ab:e9:c7:2d:12:cb:ab:1c:4c: + 70:07:a1:3d:0a:30:cd:15:8d:4f:f8:dd:d4:8c:50: + 15:1c:ef:50:ee:c4:2e:f7:fc:e9:52:f2:91:7d:e0: + 6d:d5:35:30:8e:5e:43:73:f2:41:e9:d5:6a:e3:b2: + 89:3a:56:39:38:6f:06:3c:88:69:5b:2a:4d:c5:a7: + 54:b8:6c:89:cc:9b:f9:3c:ca:e5:fd:89:f5:12:3c: + 92:78:96:d6:dc:74:6e:93:44:61:d1:8d:c7:46:b2: + 75:0e:86:e8:19:8a:d5:6d:6c:d5:78:16:95:a2:e9: + c8:0a:38:eb:f2:24:13:4f:73:54:93:13:85:3a:1b: + bc:1e:34:b5:8b:05:8c:b9:77:8b:b1:db:1f:20:91: + ab:09:53:6e:90:ce:7b:37:74:b9:70:47:91:22:51: + 63:16:79:ae:b1:ae:41:26:08:c8:19:2b:d1:46:aa: + 48:d6:64:2a:d7:83:34:ff:2c:2a:c1:6c:19:43:4a: + 07:85:e7:d3:7c:f6:21:68:ef:ea:f2:52:9f:7f:93: + 90:cf + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + 60:7B:66:1A:45:0D:97:CA:89:50:2F:7D:04:CD:34:A8:FF:FC:FD:4B + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: md5WithRSAEncryption + ae:aa:9f:fc:b7:d2:cb:1f:5f:39:29:28:18:9e:34:c9:6c:4f: + 6f:1a:f0:64:a2:70:4a:4f:13:86:9b:60:28:9e:e8:81:49:98: + 7d:0a:bb:e5:b0:9d:3d:36:db:8f:05:51:ff:09:31:2a:1f:dd: + 89:77:9e:0f:2e:6c:95:04:ed:86:cb:b4:00:3f:84:02:4d:80: + 6a:2a:2d:78:0b:ae:6f:2b:a2:83:44:83:1f:cd:50:82:4c:24: + af:bd:f7:a5:b4:c8:5a:0f:f4:e7:47:5e:49:8e:37:96:fe:9a: + 88:05:3a:d9:c0:db:29:87:e6:19:96:47:a7:3a:a6:8c:8b:3c: + 77:fe:46:63:a7:53:da:21:d1:ac:7e:49:a2:4b:e6:c3:67:59: + 2f:b3:8a:0e:bb:2c:bd:a9:aa:42:7c:35:c1:d8:7f:d5:a7:31: + 3a:4e:63:43:39:af:08:b0:61:34:8c:d3:98:a9:43:34:f6:0f: + 87:29:3b:9d:c2:56:58:98:77:c3:f7:1b:ac:f6:9d:f8:3e:aa: + a7:54:45:f0:f5:f9:d5:31:65:fe:6b:58:9c:71:b3:1e:d7:52: + ea:32:17:fc:40:60:1d:c9:79:24:b2:f6:6c:fd:a8:66:0e:82: + dd:98:cb:da:c2:44:4f:2e:a0:7b:f2:f7:6b:2c:76:11:84:46: + 8a:78:a3:e3 + +National Retail Federation by DST +================================= +MD5 Fingerprint: AD:8E:0F:9E:01:6B:A0:C5:74:D5:0C:D3:68:65:4F:1E +PEM Data: +-----BEGIN CERTIFICATE----- +MIIEAjCCAuoCEQDQHkCKAAACfAAAAAMAAAABMA0GCSqGSIb3DQEBBQUAMIG+MQsw +CQYDVQQGEwJ1czENMAsGA1UECBMEVXRhaDEXMBUGA1UEBxMOU2FsdCBMYWtlIENp +dHkxJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjEjMCEGA1UE +CxMaTmF0aW9uYWwgUmV0YWlsIEZlZGVyYXRpb24xGTAXBgNVBAMTEERTVCAoTlJG +KSBSb290Q0ExITAfBgkqhkiG9w0BCQEWEmNhQGRpZ3NpZ3RydXN0LmNvbTAeFw05 +ODEyMTExNjE0MTZaFw0wODEyMDgxNjE0MTZaMIG+MQswCQYDVQQGEwJ1czENMAsG +A1UECBMEVXRhaDEXMBUGA1UEBxMOU2FsdCBMYWtlIENpdHkxJDAiBgNVBAoTG0Rp +Z2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjEjMCEGA1UECxMaTmF0aW9uYWwgUmV0 +YWlsIEZlZGVyYXRpb24xGTAXBgNVBAMTEERTVCAoTlJGKSBSb290Q0ExITAfBgkq +hkiG9w0BCQEWEmNhQGRpZ3NpZ3RydXN0LmNvbTCCASIwDQYJKoZIhvcNAQEBBQAD +ggEPADCCAQoCggEBANmsm3f6UNPM3LlArLlyagCHI/wPliHQJq/k4rVf+tOmfSEw +LswXgo+YdPxnpKbfiJeiQin1p9sRk/teIzDCqrwi50Eb5e0l3sg/295XRXhARoOy +1Ro93w9FbdVjAnXYL8Zuq5WRdDcNy00JXNHUWzra3Q7Ia5nY1TnM34VVxJJTAqPh +94DJcKPa3DPEf6JHCBw1lh+hAxwwg/TEzP+Yw7BGRKLAv63b0oH2TJgsp14k84bK +Y9W6ffCawErQG1ju7Klnz2kCbCLAYCws0cgg6sgt+92cu8tRTNznVwQ7VJsRpTJ0 +7HQB85AVWy98LJNluWZntIGINeWekRh/gahByMsCAwEAATANBgkqhkiG9w0BAQUF +AAOCAQEAhF4LO+ygjRyb0DwdcWnkGn9kvoFlYcWMatd8AHTgemJV7SR84GHj8t0U +5hFugw7h6qmegK2aIL/gV37V0LWEYy3ZGOS9GzUsXq5hdqpnhTs44TGBHzF/5tf4 +W9K7Y3mGxIzF3gqu19H8AXT/trYNYoFnHLsm+CSA4Fxe2KSKOo99y/+So/18qTJp +B1hYYUKZUgOxOD3GcW9s8uh9BqrBfFPLGi2IT8mpp6xpb/ekH9h0gfVKv7FVt9N3 +OKdvwkrI4nOJ01dy4UMvcjz2H7f4BEpuwemUF+SXF/QOE4ZvjavoXy20/2zWorQf +7LmUaqoSTxrd9Xe1JYzyigrx/FJbWA== +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 1 (0x0) + Serial Number: + d0:1e:40:8a:00:00:02:7c:00:00:00:03:00:00:00:01 + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=us, ST=Utah, L=Salt Lake City, O=Digital Signature Trust Co., OU=National Retail Federation, CN=DST (NRF) RootCA/Email=ca@digsigtrust.com + Validity + Not Before: Dec 11 16:14:16 1998 GMT + Not After : Dec 8 16:14:16 2008 GMT + Subject: C=us, ST=Utah, L=Salt Lake City, O=Digital Signature Trust Co., OU=National Retail Federation, CN=DST (NRF) RootCA/Email=ca@digsigtrust.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:d9:ac:9b:77:fa:50:d3:cc:dc:b9:40:ac:b9:72: + 6a:00:87:23:fc:0f:96:21:d0:26:af:e4:e2:b5:5f: + fa:d3:a6:7d:21:30:2e:cc:17:82:8f:98:74:fc:67: + a4:a6:df:88:97:a2:42:29:f5:a7:db:11:93:fb:5e: + 23:30:c2:aa:bc:22:e7:41:1b:e5:ed:25:de:c8:3f: + db:de:57:45:78:40:46:83:b2:d5:1a:3d:df:0f:45: + 6d:d5:63:02:75:d8:2f:c6:6e:ab:95:91:74:37:0d: + cb:4d:09:5c:d1:d4:5b:3a:da:dd:0e:c8:6b:99:d8: + d5:39:cc:df:85:55:c4:92:53:02:a3:e1:f7:80:c9: + 70:a3:da:dc:33:c4:7f:a2:47:08:1c:35:96:1f:a1: + 03:1c:30:83:f4:c4:cc:ff:98:c3:b0:46:44:a2:c0: + bf:ad:db:d2:81:f6:4c:98:2c:a7:5e:24:f3:86:ca: + 63:d5:ba:7d:f0:9a:c0:4a:d0:1b:58:ee:ec:a9:67: + cf:69:02:6c:22:c0:60:2c:2c:d1:c8:20:ea:c8:2d: + fb:dd:9c:bb:cb:51:4c:dc:e7:57:04:3b:54:9b:11: + a5:32:74:ec:74:01:f3:90:15:5b:2f:7c:2c:93:65: + b9:66:67:b4:81:88:35:e5:9e:91:18:7f:81:a8:41: + c8:cb + Exponent: 65537 (0x10001) + Signature Algorithm: sha1WithRSAEncryption + 84:5e:0b:3b:ec:a0:8d:1c:9b:d0:3c:1d:71:69:e4:1a:7f:64: + be:81:65:61:c5:8c:6a:d7:7c:00:74:e0:7a:62:55:ed:24:7c: + e0:61:e3:f2:dd:14:e6:11:6e:83:0e:e1:ea:a9:9e:80:ad:9a: + 20:bf:e0:57:7e:d5:d0:b5:84:63:2d:d9:18:e4:bd:1b:35:2c: + 5e:ae:61:76:aa:67:85:3b:38:e1:31:81:1f:31:7f:e6:d7:f8: + 5b:d2:bb:63:79:86:c4:8c:c5:de:0a:ae:d7:d1:fc:01:74:ff: + b6:b6:0d:62:81:67:1c:bb:26:f8:24:80:e0:5c:5e:d8:a4:8a: + 3a:8f:7d:cb:ff:92:a3:fd:7c:a9:32:69:07:58:58:61:42:99: + 52:03:b1:38:3d:c6:71:6f:6c:f2:e8:7d:06:aa:c1:7c:53:cb: + 1a:2d:88:4f:c9:a9:a7:ac:69:6f:f7:a4:1f:d8:74:81:f5:4a: + bf:b1:55:b7:d3:77:38:a7:6f:c2:4a:c8:e2:73:89:d3:57:72: + e1:43:2f:72:3c:f6:1f:b7:f8:04:4a:6e:c1:e9:94:17:e4:97: + 17:f4:0e:13:86:6f:8d:ab:e8:5f:2d:b4:ff:6c:d6:a2:b4:1f: + ec:b9:94:6a:aa:12:4f:1a:dd:f5:77:b5:25:8c:f2:8a:0a:f1: + fc:52:5b:58 + +TC TrustCenter, Germany, Class 1 CA +=================================== +MD5 Fingerprint: 64:3F:F8:3E:52:14:4A:59:BA:93:56:04:0B:23:02:D1 +PEM Data: +-----BEGIN CERTIFICATE----- +MIIENTCCA56gAwIBAgIBAjANBgkqhkiG9w0BAQQFADCBvDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxEDAOBgNVBAcTB0hhbWJ1cmcxOjA4BgNVBAoTMVRD +IFRydXN0Q2VudGVyIGZvciBTZWN1cml0eSBpbiBEYXRhIE5ldHdvcmtzIEdtYkgx +IjAgBgNVBAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDEgQ0ExKTAnBgkqhkiG9w0B +CQEWGmNlcnRpZmljYXRlQHRydXN0Y2VudGVyLmRlMB4XDTk4MDMwOTEzNTYzM1oX +DTA1MTIzMTEzNTYzM1owgbwxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1idXJn +MRAwDgYDVQQHEwdIYW1idXJnMTowOAYDVQQKEzFUQyBUcnVzdENlbnRlciBmb3Ig +U2VjdXJpdHkgaW4gRGF0YSBOZXR3b3JrcyBHbWJIMSIwIAYDVQQLExlUQyBUcnVz +dENlbnRlciBDbGFzcyAxIENBMSkwJwYJKoZIhvcNAQkBFhpjZXJ0aWZpY2F0ZUB0 +cnVzdGNlbnRlci5kZTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAsCnrtHaz +rte2W7Re573jsZxJBFdboavZfxMb/bphq9jncd8tAJRdUUh9I+91YoSQPAofWRF0 +L46Apf0wAj0pUs1yGkkhnLzLUo5IoWOWyBCFMGlXdEXAWobG1T3gaFd9MWokjUWX +PjF+aGYybiRt7DI2yUHK8DFEyKNhyhugNh8CAwEAAaOCAUMwggE/MEAGCWCGSAGG ++EIBAwQzFjFodHRwczovL3d3dy50cnVzdGNlbnRlci5kZS9jZ2ktYmluL2NoZWNr +LXJldi5jZ2k/MEAGCWCGSAGG+EIBBAQzFjFodHRwczovL3d3dy50cnVzdGNlbnRl +ci5kZS9jZ2ktYmluL2NoZWNrLXJldi5jZ2k/MDwGCWCGSAGG+EIBBwQvFi1odHRw +czovL3d3dy50cnVzdGNlbnRlci5kZS9jZ2ktYmluL1JlbmV3LmNnaT8wPgYJYIZI +AYb4QgEIBDEWL2h0dHA6Ly93d3cudHJ1c3RjZW50ZXIuZGUvZ3VpZGVsaW5lcy9p +bmRleC5odG1sMCgGCWCGSAGG+EIBDQQbFhlUQyBUcnVzdENlbnRlciBDbGFzcyAx +IENBMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG9w0BAQQFAAOBgQAFQlImpAwn +AUSsXCUowkRCVAi5HcU+bFlmxLNOUKf4+JZ1oZZ16BY4oM1dbvp5pxt7HR7DALlm +vlrWYg/n8nu470zgwD9Zrjm3hAmeq/GpLmtp4q3M8up4CQUgOEJxGH7Hspfm1QIF +BlajX/GqwsRP/vfvFg+d7KqFzz0pJPEEzQ== +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: 2 (0x2) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=DE, ST=Hamburg, L=Hamburg, O=TC TrustCenter for Security in Data Networks GmbH, OU=TC TrustCenter Class 1 CA/Email=certificate@trustcenter.de + Validity + Not Before: Mar 9 13:56:33 1998 GMT + Not After : Dec 31 13:56:33 2005 GMT + Subject: C=DE, ST=Hamburg, L=Hamburg, O=TC TrustCenter for Security in Data Networks GmbH, OU=TC TrustCenter Class 1 CA/Email=certificate@trustcenter.de + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:b0:29:eb:b4:76:b3:ae:d7:b6:5b:b4:5e:e7:bd: + e3:b1:9c:49:04:57:5b:a1:ab:d9:7f:13:1b:fd:ba: + 61:ab:d8:e7:71:df:2d:00:94:5d:51:48:7d:23:ef: + 75:62:84:90:3c:0a:1f:59:11:74:2f:8e:80:a5:fd: + 30:02:3d:29:52:cd:72:1a:49:21:9c:bc:cb:52:8e: + 48:a1:63:96:c8:10:85:30:69:57:74:45:c0:5a:86: + c6:d5:3d:e0:68:57:7d:31:6a:24:8d:45:97:3e:31: + 7e:68:66:32:6e:24:6d:ec:32:36:c9:41:ca:f0:31: + 44:c8:a3:61:ca:1b:a0:36:1f + Exponent: 65537 (0x10001) + X509v3 extensions: + Netscape Revocation Url: + https://www.trustcenter.de/cgi-bin/check-rev.cgi? + Netscape CA Revocation Url: + https://www.trustcenter.de/cgi-bin/check-rev.cgi? + Netscape Renewal Url: + https://www.trustcenter.de/cgi-bin/Renew.cgi? + Netscape CA Policy Url: + http://www.trustcenter.de/guidelines/index.html + Netscape Comment: + TC TrustCenter Class 1 CA + Netscape Cert Type: + SSL CA, S/MIME CA, Object Signing CA + Signature Algorithm: md5WithRSAEncryption + 05:42:52:26:a4:0c:27:01:44:ac:5c:25:28:c2:44:42:54:08: + b9:1d:c5:3e:6c:59:66:c4:b3:4e:50:a7:f8:f8:96:75:a1:96: + 75:e8:16:38:a0:cd:5d:6e:fa:79:a7:1b:7b:1d:1e:c3:00:b9: + 66:be:5a:d6:62:0f:e7:f2:7b:b8:ef:4c:e0:c0:3f:59:ae:39: + b7:84:09:9e:ab:f1:a9:2e:6b:69:e2:ad:cc:f2:ea:78:09:05: + 20:38:42:71:18:7e:c7:b2:97:e6:d5:02:05:06:56:a3:5f:f1: + aa:c2:c4:4f:fe:f7:ef:16:0f:9d:ec:aa:85:cf:3d:29:24:f1: + 04:cd + +TC TrustCenter, Germany, Class 2 CA +=================================== +MD5 Fingerprint: E1:E9:96:53:77:E1:F0:38:A0:02:AB:94:C6:95:7B:FC +PEM Data: +-----BEGIN CERTIFICATE----- +MIIENTCCA56gAwIBAgIBAzANBgkqhkiG9w0BAQQFADCBvDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxEDAOBgNVBAcTB0hhbWJ1cmcxOjA4BgNVBAoTMVRD +IFRydXN0Q2VudGVyIGZvciBTZWN1cml0eSBpbiBEYXRhIE5ldHdvcmtzIEdtYkgx +IjAgBgNVBAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDIgQ0ExKTAnBgkqhkiG9w0B +CQEWGmNlcnRpZmljYXRlQHRydXN0Y2VudGVyLmRlMB4XDTk4MDMwOTEzNTc0NFoX +DTA1MTIzMTEzNTc0NFowgbwxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1idXJn +MRAwDgYDVQQHEwdIYW1idXJnMTowOAYDVQQKEzFUQyBUcnVzdENlbnRlciBmb3Ig +U2VjdXJpdHkgaW4gRGF0YSBOZXR3b3JrcyBHbWJIMSIwIAYDVQQLExlUQyBUcnVz +dENlbnRlciBDbGFzcyAyIENBMSkwJwYJKoZIhvcNAQkBFhpjZXJ0aWZpY2F0ZUB0 +cnVzdGNlbnRlci5kZTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA2jjo7TIA +KXGDAQ2/jAHc2satOaSpii/Vi1xoX1DGYvVmvcqRIuyqHVHXPbNRsoNOXctJsPBM +VeVrLceFCzAckk6C1MoC7fdvvtzg4xS4BVPymvRWi1qehZPRtIJWrk27qEtXFrz+ ++Fie+CmNsHvNeMlPrItnDPGc+/xXm1dcTw0CAwEAAaOCAUMwggE/MEAGCWCGSAGG ++EIBAwQzFjFodHRwczovL3d3dy50cnVzdGNlbnRlci5kZS9jZ2ktYmluL2NoZWNr +LXJldi5jZ2k/MEAGCWCGSAGG+EIBBAQzFjFodHRwczovL3d3dy50cnVzdGNlbnRl +ci5kZS9jZ2ktYmluL2NoZWNrLXJldi5jZ2k/MDwGCWCGSAGG+EIBBwQvFi1odHRw +czovL3d3dy50cnVzdGNlbnRlci5kZS9jZ2ktYmluL1JlbmV3LmNnaT8wPgYJYIZI +AYb4QgEIBDEWL2h0dHA6Ly93d3cudHJ1c3RjZW50ZXIuZGUvZ3VpZGVsaW5lcy9p +bmRleC5odG1sMCgGCWCGSAGG+EIBDQQbFhlUQyBUcnVzdENlbnRlciBDbGFzcyAy +IENBMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG9w0BAQQFAAOBgQCJG/Tv6Tji +bAz2zW9JzinM+6YP+Y0+lUbW/EcyibLIBmF60ucNEwKUC9mLVkf0u+fFX3v0Y0yu +fDTqDaKpsyyF8+P+J1QQkrCPksGYQhhwSNtOLOsNJGjk0fe+Cakph7vo2tw+o4hC +MfXR43+u2I4AWnSYsE/G/yN7XHMAeMnbTg== +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: 3 (0x3) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=DE, ST=Hamburg, L=Hamburg, O=TC TrustCenter for Security in Data Networks GmbH, OU=TC TrustCenter Class 2 CA/Email=certificate@trustcenter.de + Validity + Not Before: Mar 9 13:57:44 1998 GMT + Not After : Dec 31 13:57:44 2005 GMT + Subject: C=DE, ST=Hamburg, L=Hamburg, O=TC TrustCenter for Security in Data Networks GmbH, OU=TC TrustCenter Class 2 CA/Email=certificate@trustcenter.de + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:da:38:e8:ed:32:00:29:71:83:01:0d:bf:8c:01: + dc:da:c6:ad:39:a4:a9:8a:2f:d5:8b:5c:68:5f:50: + c6:62:f5:66:bd:ca:91:22:ec:aa:1d:51:d7:3d:b3: + 51:b2:83:4e:5d:cb:49:b0:f0:4c:55:e5:6b:2d:c7: + 85:0b:30:1c:92:4e:82:d4:ca:02:ed:f7:6f:be:dc: + e0:e3:14:b8:05:53:f2:9a:f4:56:8b:5a:9e:85:93: + d1:b4:82:56:ae:4d:bb:a8:4b:57:16:bc:fe:f8:58: + 9e:f8:29:8d:b0:7b:cd:78:c9:4f:ac:8b:67:0c:f1: + 9c:fb:fc:57:9b:57:5c:4f:0d + Exponent: 65537 (0x10001) + X509v3 extensions: + Netscape Revocation Url: + https://www.trustcenter.de/cgi-bin/check-rev.cgi? + Netscape CA Revocation Url: + https://www.trustcenter.de/cgi-bin/check-rev.cgi? + Netscape Renewal Url: + https://www.trustcenter.de/cgi-bin/Renew.cgi? + Netscape CA Policy Url: + http://www.trustcenter.de/guidelines/index.html + Netscape Comment: + TC TrustCenter Class 2 CA + Netscape Cert Type: + SSL CA, S/MIME CA, Object Signing CA + Signature Algorithm: md5WithRSAEncryption + 89:1b:f4:ef:e9:38:e2:6c:0c:f6:cd:6f:49:ce:29:cc:fb:a6: + 0f:f9:8d:3e:95:46:d6:fc:47:32:89:b2:c8:06:61:7a:d2:e7: + 0d:13:02:94:0b:d9:8b:56:47:f4:bb:e7:c5:5f:7b:f4:63:4c: + ae:7c:34:ea:0d:a2:a9:b3:2c:85:f3:e3:fe:27:54:10:92:b0: + 8f:92:c1:98:42:18:70:48:db:4e:2c:eb:0d:24:68:e4:d1:f7: + be:09:a9:29:87:bb:e8:da:dc:3e:a3:88:42:31:f5:d1:e3:7f: + ae:d8:8e:00:5a:74:98:b0:4f:c6:ff:23:7b:5c:73:00:78:c9: + db:4e + +TC TrustCenter, Germany, Class 3 CA +=================================== +MD5 Fingerprint: 62:AB:B6:15:4A:B4:B0:16:77:FF:AE:CF:16:16:2B:8C +PEM Data: +-----BEGIN CERTIFICATE----- +MIIENTCCA56gAwIBAgIBBDANBgkqhkiG9w0BAQQFADCBvDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxEDAOBgNVBAcTB0hhbWJ1cmcxOjA4BgNVBAoTMVRD +IFRydXN0Q2VudGVyIGZvciBTZWN1cml0eSBpbiBEYXRhIE5ldHdvcmtzIEdtYkgx +IjAgBgNVBAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDMgQ0ExKTAnBgkqhkiG9w0B +CQEWGmNlcnRpZmljYXRlQHRydXN0Y2VudGVyLmRlMB4XDTk4MDMwOTEzNTg0OVoX +DTA1MTIzMTEzNTg0OVowgbwxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1idXJn +MRAwDgYDVQQHEwdIYW1idXJnMTowOAYDVQQKEzFUQyBUcnVzdENlbnRlciBmb3Ig +U2VjdXJpdHkgaW4gRGF0YSBOZXR3b3JrcyBHbWJIMSIwIAYDVQQLExlUQyBUcnVz +dENlbnRlciBDbGFzcyAzIENBMSkwJwYJKoZIhvcNAQkBFhpjZXJ0aWZpY2F0ZUB0 +cnVzdGNlbnRlci5kZTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAtrTBNQUu +DY3soEBqHA4nplCSa1AbB94u53bM4Nr8hKhejGNqK03ZTgJ2EcEL8o15ygC28bAO +1/ukFz2vq2l6lie/rzOhmipZqsS1NwjyEqUxtkP1MpZxKCirjSiG37vu4wx9MNbD +UquPXSeca8Cj5wVrV0lEs27qZM/SjnpQd3cCAwEAAaOCAUMwggE/MEAGCWCGSAGG ++EIBAwQzFjFodHRwczovL3d3dy50cnVzdGNlbnRlci5kZS9jZ2ktYmluL2NoZWNr +LXJldi5jZ2k/MEAGCWCGSAGG+EIBBAQzFjFodHRwczovL3d3dy50cnVzdGNlbnRl +ci5kZS9jZ2ktYmluL2NoZWNrLXJldi5jZ2k/MDwGCWCGSAGG+EIBBwQvFi1odHRw +czovL3d3dy50cnVzdGNlbnRlci5kZS9jZ2ktYmluL1JlbmV3LmNnaT8wPgYJYIZI +AYb4QgEIBDEWL2h0dHA6Ly93d3cudHJ1c3RjZW50ZXIuZGUvZ3VpZGVsaW5lcy9p +bmRleC5odG1sMCgGCWCGSAGG+EIBDQQbFhlUQyBUcnVzdENlbnRlciBDbGFzcyAz +IENBMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG9w0BAQQFAAOBgQCEhlBieaAn +4SW6CbE0DxMJ7S3Ko+aV+TCszRelzj2Xnex8jyZ/wGHKIveR3Tw2WZqbdfe85Mjt +7AK2IqfzLPHIknhttu7FKOyAIE+5awjnL6eGHn2xCJ9UuQA3PKDYGsiWHPQyFJw5 +lbfu8ENJwl7oy3lvU7/7SYos2EvZVfIScA== +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: 4 (0x4) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=DE, ST=Hamburg, L=Hamburg, O=TC TrustCenter for Security in Data Networks GmbH, OU=TC TrustCenter Class 3 CA/Email=certificate@trustcenter.de + Validity + Not Before: Mar 9 13:58:49 1998 GMT + Not After : Dec 31 13:58:49 2005 GMT + Subject: C=DE, ST=Hamburg, L=Hamburg, O=TC TrustCenter for Security in Data Networks GmbH, OU=TC TrustCenter Class 3 CA/Email=certificate@trustcenter.de + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:b6:b4:c1:35:05:2e:0d:8d:ec:a0:40:6a:1c:0e: + 27:a6:50:92:6b:50:1b:07:de:2e:e7:76:cc:e0:da: + fc:84:a8:5e:8c:63:6a:2b:4d:d9:4e:02:76:11:c1: + 0b:f2:8d:79:ca:00:b6:f1:b0:0e:d7:fb:a4:17:3d: + af:ab:69:7a:96:27:bf:af:33:a1:9a:2a:59:aa:c4: + b5:37:08:f2:12:a5:31:b6:43:f5:32:96:71:28:28: + ab:8d:28:86:df:bb:ee:e3:0c:7d:30:d6:c3:52:ab: + 8f:5d:27:9c:6b:c0:a3:e7:05:6b:57:49:44:b3:6e: + ea:64:cf:d2:8e:7a:50:77:77 + Exponent: 65537 (0x10001) + X509v3 extensions: + Netscape Revocation Url: + https://www.trustcenter.de/cgi-bin/check-rev.cgi? + Netscape CA Revocation Url: + https://www.trustcenter.de/cgi-bin/check-rev.cgi? + Netscape Renewal Url: + https://www.trustcenter.de/cgi-bin/Renew.cgi? + Netscape CA Policy Url: + http://www.trustcenter.de/guidelines/index.html + Netscape Comment: + TC TrustCenter Class 3 CA + Netscape Cert Type: + SSL CA, S/MIME CA, Object Signing CA + Signature Algorithm: md5WithRSAEncryption + 84:86:50:62:79:a0:27:e1:25:ba:09:b1:34:0f:13:09:ed:2d: + ca:a3:e6:95:f9:30:ac:cd:17:a5:ce:3d:97:9d:ec:7c:8f:26: + 7f:c0:61:ca:22:f7:91:dd:3c:36:59:9a:9b:75:f7:bc:e4:c8: + ed:ec:02:b6:22:a7:f3:2c:f1:c8:92:78:6d:b6:ee:c5:28:ec: + 80:20:4f:b9:6b:08:e7:2f:a7:86:1e:7d:b1:08:9f:54:b9:00: + 37:3c:a0:d8:1a:c8:96:1c:f4:32:14:9c:39:95:b7:ee:f0:43: + 49:c2:5e:e8:cb:79:6f:53:bf:fb:49:8a:2c:d8:4b:d9:55:f2: + 12:70 + +TC TrustCenter, Germany, Class 4 CA +=================================== +MD5 Fingerprint: BF:AF:EC:C4:DA:F9:30:F9:CA:35:CA:25:E4:3F:8D:89 +PEM Data: +-----BEGIN CERTIFICATE----- +MIIENTCCA56gAwIBAgIBBTANBgkqhkiG9w0BAQQFADCBvDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxEDAOBgNVBAcTB0hhbWJ1cmcxOjA4BgNVBAoTMVRD +IFRydXN0Q2VudGVyIGZvciBTZWN1cml0eSBpbiBEYXRhIE5ldHdvcmtzIEdtYkgx +IjAgBgNVBAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDQgQ0ExKTAnBgkqhkiG9w0B +CQEWGmNlcnRpZmljYXRlQHRydXN0Y2VudGVyLmRlMB4XDTk4MDMwOTE0MDAyMFoX +DTA1MTIzMTE0MDAyMFowgbwxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1idXJn +MRAwDgYDVQQHEwdIYW1idXJnMTowOAYDVQQKEzFUQyBUcnVzdENlbnRlciBmb3Ig +U2VjdXJpdHkgaW4gRGF0YSBOZXR3b3JrcyBHbWJIMSIwIAYDVQQLExlUQyBUcnVz +dENlbnRlciBDbGFzcyA0IENBMSkwJwYJKoZIhvcNAQkBFhpjZXJ0aWZpY2F0ZUB0 +cnVzdGNlbnRlci5kZTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAvy9j1jZ7 +sg3TVfVkbOYlXca0yBS6JTiD61ZipVWpZaP0I5nCS7nQzVRnpqOgo6kzK3bkva13 +su1cEnTDxbYPUppyk0OQYmYVD0Wl3eDduG9AblfBeXKjYKq6dh0SiVNa/AK+4QkT +xUov3D2LGa3XiyRF+0z0zVw1HSlMUfPybFUCAwEAAaOCAUMwggE/MEAGCWCGSAGG ++EIBAwQzFjFodHRwczovL3d3dy50cnVzdGNlbnRlci5kZS9jZ2ktYmluL2NoZWNr +LXJldi5jZ2k/MEAGCWCGSAGG+EIBBAQzFjFodHRwczovL3d3dy50cnVzdGNlbnRl +ci5kZS9jZ2ktYmluL2NoZWNrLXJldi5jZ2k/MDwGCWCGSAGG+EIBBwQvFi1odHRw +czovL3d3dy50cnVzdGNlbnRlci5kZS9jZ2ktYmluL1JlbmV3LmNnaT8wPgYJYIZI +AYb4QgEIBDEWL2h0dHA6Ly93d3cudHJ1c3RjZW50ZXIuZGUvZ3VpZGVsaW5lcy9p +bmRleC5odG1sMCgGCWCGSAGG+EIBDQQbFhlUQyBUcnVzdENlbnRlciBDbGFzcyA0 +IENBMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG9w0BAQQFAAOBgQCUaBQbJZ4p +mbGyI9JEs5Wf0Z5VBN3jL4IzVZZ3GZ0rnmUc+orjx48l/LEeVUYPj/9PNy+kdlmm +ZOvVFnC93ZUzDKQNJOtkULRDEfJDvg1xmCLsAa/s98dcccN1kVgZ6N2g9LTxvBBK +85O0Bkm7H2bSvXRH4Zr569erbR+64R0s2g== +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: 5 (0x5) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=DE, ST=Hamburg, L=Hamburg, O=TC TrustCenter for Security in Data Networks GmbH, OU=TC TrustCenter Class 4 CA/Email=certificate@trustcenter.de + Validity + Not Before: Mar 9 14:00:20 1998 GMT + Not After : Dec 31 14:00:20 2005 GMT + Subject: C=DE, ST=Hamburg, L=Hamburg, O=TC TrustCenter for Security in Data Networks GmbH, OU=TC TrustCenter Class 4 CA/Email=certificate@trustcenter.de + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:bf:2f:63:d6:36:7b:b2:0d:d3:55:f5:64:6c:e6: + 25:5d:c6:b4:c8:14:ba:25:38:83:eb:56:62:a5:55: + a9:65:a3:f4:23:99:c2:4b:b9:d0:cd:54:67:a6:a3: + a0:a3:a9:33:2b:76:e4:bd:ad:77:b2:ed:5c:12:74: + c3:c5:b6:0f:52:9a:72:93:43:90:62:66:15:0f:45: + a5:dd:e0:dd:b8:6f:40:6e:57:c1:79:72:a3:60:aa: + ba:76:1d:12:89:53:5a:fc:02:be:e1:09:13:c5:4a: + 2f:dc:3d:8b:19:ad:d7:8b:24:45:fb:4c:f4:cd:5c: + 35:1d:29:4c:51:f3:f2:6c:55 + Exponent: 65537 (0x10001) + X509v3 extensions: + Netscape Revocation Url: + https://www.trustcenter.de/cgi-bin/check-rev.cgi? + Netscape CA Revocation Url: + https://www.trustcenter.de/cgi-bin/check-rev.cgi? + Netscape Renewal Url: + https://www.trustcenter.de/cgi-bin/Renew.cgi? + Netscape CA Policy Url: + http://www.trustcenter.de/guidelines/index.html + Netscape Comment: + TC TrustCenter Class 4 CA + Netscape Cert Type: + SSL CA, S/MIME CA, Object Signing CA + Signature Algorithm: md5WithRSAEncryption + 94:68:14:1b:25:9e:29:99:b1:b2:23:d2:44:b3:95:9f:d1:9e: + 55:04:dd:e3:2f:82:33:55:96:77:19:9d:2b:9e:65:1c:fa:8a: + e3:c7:8f:25:fc:b1:1e:55:46:0f:8f:ff:4f:37:2f:a4:76:59: + a6:64:eb:d5:16:70:bd:dd:95:33:0c:a4:0d:24:eb:64:50:b4: + 43:11:f2:43:be:0d:71:98:22:ec:01:af:ec:f7:c7:5c:71:c3: + 75:91:58:19:e8:dd:a0:f4:b4:f1:bc:10:4a:f3:93:b4:06:49: + bb:1f:66:d2:bd:74:47:e1:9a:f9:eb:d7:ab:6d:1f:ba:e1:1d: + 2c:da + +Thawte Personal Basic CA +======================== +MD5 Fingerprint: E6:0B:D2:C9:CA:2D:88:DB:1A:71:0E:4B:78:EB:02:41 +PEM Data: +-----BEGIN CERTIFICATE----- +MIIDITCCAoqgAwIBAgIBADANBgkqhkiG9w0BAQQFADCByzELMAkGA1UEBhMCWkEx +FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMRowGAYD +VQQKExFUaGF3dGUgQ29uc3VsdGluZzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBT +ZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UEAxMYVGhhd3RlIFBlcnNvbmFsIEJhc2lj +IENBMSgwJgYJKoZIhvcNAQkBFhlwZXJzb25hbC1iYXNpY0B0aGF3dGUuY29tMB4X +DTk2MDEwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgcsxCzAJBgNVBAYTAlpBMRUw +EwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEaMBgGA1UE +ChMRVGhhd3RlIENvbnN1bHRpbmcxKDAmBgNVBAsTH0NlcnRpZmljYXRpb24gU2Vy +dmljZXMgRGl2aXNpb24xITAfBgNVBAMTGFRoYXd0ZSBQZXJzb25hbCBCYXNpYyBD +QTEoMCYGCSqGSIb3DQEJARYZcGVyc29uYWwtYmFzaWNAdGhhd3RlLmNvbTCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAvLyTU23AUE+CFeZIlDWmWr5vQvoPR+53 +dXLdjUmbllegeNTKP1GzaQuRdhciB5dqxFGTS+CN7zeVoQxN2jSQHReJl+A1OFdK +wPQIcOk8RHtQfmGakOMj04gRRif1CwcOu93RfyAKiLlWCy4cgNrx454p7xS9CkT7 +G1sY0b8jkyECAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQQF +AAOBgQAt4plrsD16iddZopQBHyvdEktTwq1/qqcAXJFAVyVKOKqEcLnZgA+le1z7 +c8a914phXAPjLSeoF+CEhULcXpvGt7Jtu3Sv5D/Lp7ew4F2+eIMllNLbgQ95B21P +9DkVWlIBe94y1k049hJcBlDfBVu9FEuh3ym6O0GN92NWod8isQ== +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: 0 (0x0) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting, OU=Certification Services Division, CN=Thawte Personal Basic CA/Email=personal-basic@thawte.com + Validity + Not Before: Jan 1 00:00:00 1996 GMT + Not After : Dec 31 23:59:59 2020 GMT + Subject: C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting, OU=Certification Services Division, CN=Thawte Personal Basic CA/Email=personal-basic@thawte.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:bc:bc:93:53:6d:c0:50:4f:82:15:e6:48:94:35: + a6:5a:be:6f:42:fa:0f:47:ee:77:75:72:dd:8d:49: + 9b:96:57:a0:78:d4:ca:3f:51:b3:69:0b:91:76:17: + 22:07:97:6a:c4:51:93:4b:e0:8d:ef:37:95:a1:0c: + 4d:da:34:90:1d:17:89:97:e0:35:38:57:4a:c0:f4: + 08:70:e9:3c:44:7b:50:7e:61:9a:90:e3:23:d3:88: + 11:46:27:f5:0b:07:0e:bb:dd:d1:7f:20:0a:88:b9: + 56:0b:2e:1c:80:da:f1:e3:9e:29:ef:14:bd:0a:44: + fb:1b:5b:18:d1:bf:23:93:21 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: md5WithRSAEncryption + 2d:e2:99:6b:b0:3d:7a:89:d7:59:a2:94:01:1f:2b:dd:12:4b: + 53:c2:ad:7f:aa:a7:00:5c:91:40:57:25:4a:38:aa:84:70:b9: + d9:80:0f:a5:7b:5c:fb:73:c6:bd:d7:8a:61:5c:03:e3:2d:27: + a8:17:e0:84:85:42:dc:5e:9b:c6:b7:b2:6d:bb:74:af:e4:3f: + cb:a7:b7:b0:e0:5d:be:78:83:25:94:d2:db:81:0f:79:07:6d: + 4f:f4:39:15:5a:52:01:7b:de:32:d6:4d:38:f6:12:5c:06:50: + df:05:5b:bd:14:4b:a1:df:29:ba:3b:41:8d:f7:63:56:a1:df: + 22:b1 + +Thawte Personal Freemail CA +=========================== +MD5 Fingerprint: 1E:74:C3:86:3C:0C:35:C5:3E:C2:7F:EF:3C:AA:3C:D9 +PEM Data: +-----BEGIN CERTIFICATE----- +MIIDLTCCApagAwIBAgIBADANBgkqhkiG9w0BAQQFADCB0TELMAkGA1UEBhMCWkEx +FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMRowGAYD +VQQKExFUaGF3dGUgQ29uc3VsdGluZzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBT +ZXJ2aWNlcyBEaXZpc2lvbjEkMCIGA1UEAxMbVGhhd3RlIFBlcnNvbmFsIEZyZWVt +YWlsIENBMSswKQYJKoZIhvcNAQkBFhxwZXJzb25hbC1mcmVlbWFpbEB0aGF3dGUu +Y29tMB4XDTk2MDEwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgdExCzAJBgNVBAYT +AlpBMRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEa +MBgGA1UEChMRVGhhd3RlIENvbnN1bHRpbmcxKDAmBgNVBAsTH0NlcnRpZmljYXRp +b24gU2VydmljZXMgRGl2aXNpb24xJDAiBgNVBAMTG1RoYXd0ZSBQZXJzb25hbCBG +cmVlbWFpbCBDQTErMCkGCSqGSIb3DQEJARYccGVyc29uYWwtZnJlZW1haWxAdGhh +d3RlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1GnX1LCUZFtx6UfY +DFG26nKRsIRefS0Nj3sS34UldSh0OkIsYyeflXtL734Zhx2G6qPduc6WZBrCFG5E +rHzmj+hND3EfQDimAKOHePb5lIZererAXnbr2RSjXW56fAylS1V/Bhkpf56aJtVq +uzgkCGqYx7Hao5iR/Xnb5VrEHLkCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zAN +BgkqhkiG9w0BAQQFAAOBgQDH7JJ+Tvj1lqVnYiqk8E0RYNBvjWBYYawmu1I1XAjP +MPuoSpaKH2JCI4wXD/S6ZJwXrEcp352YXtJsYHFcoqzceePnbgBHH7UNKOgCneSa +/RP0ptl8sfjcXyMmCZGAc9AUG95DqYMl8uacLxXK/qarigd1iwzdUYRr5PjRznei +gQ== +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: 0 (0x0) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting, OU=Certification Services Division, CN=Thawte Personal Freemail CA/Email=personal-freemail@thawte.com + Validity + Not Before: Jan 1 00:00:00 1996 GMT + Not After : Dec 31 23:59:59 2020 GMT + Subject: C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting, OU=Certification Services Division, CN=Thawte Personal Freemail CA/Email=personal-freemail@thawte.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:d4:69:d7:d4:b0:94:64:5b:71:e9:47:d8:0c:51: + b6:ea:72:91:b0:84:5e:7d:2d:0d:8f:7b:12:df:85: + 25:75:28:74:3a:42:2c:63:27:9f:95:7b:4b:ef:7e: + 19:87:1d:86:ea:a3:dd:b9:ce:96:64:1a:c2:14:6e: + 44:ac:7c:e6:8f:e8:4d:0f:71:1f:40:38:a6:00:a3: + 87:78:f6:f9:94:86:5e:ad:ea:c0:5e:76:eb:d9:14: + a3:5d:6e:7a:7c:0c:a5:4b:55:7f:06:19:29:7f:9e: + 9a:26:d5:6a:bb:38:24:08:6a:98:c7:b1:da:a3:98: + 91:fd:79:db:e5:5a:c4:1c:b9 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: md5WithRSAEncryption + c7:ec:92:7e:4e:f8:f5:96:a5:67:62:2a:a4:f0:4d:11:60:d0: + 6f:8d:60:58:61:ac:26:bb:52:35:5c:08:cf:30:fb:a8:4a:96: + 8a:1f:62:42:23:8c:17:0f:f4:ba:64:9c:17:ac:47:29:df:9d: + 98:5e:d2:6c:60:71:5c:a2:ac:dc:79:e3:e7:6e:00:47:1f:b5: + 0d:28:e8:02:9d:e4:9a:fd:13:f4:a6:d9:7c:b1:f8:dc:5f:23: + 26:09:91:80:73:d0:14:1b:de:43:a9:83:25:f2:e6:9c:2f:15: + ca:fe:a6:ab:8a:07:75:8b:0c:dd:51:84:6b:e4:f8:d1:ce:77: + a2:81 + +Thawte Personal Premium CA +========================== +MD5 Fingerprint: 3A:B2:DE:22:9A:20:93:49:F9:ED:C8:D2:8A:E7:68:0D +PEM Data: +-----BEGIN CERTIFICATE----- +MIIDKTCCApKgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBzzELMAkGA1UEBhMCWkEx +FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMRowGAYD +VQQKExFUaGF3dGUgQ29uc3VsdGluZzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBT +ZXJ2aWNlcyBEaXZpc2lvbjEjMCEGA1UEAxMaVGhhd3RlIFBlcnNvbmFsIFByZW1p +dW0gQ0ExKjAoBgkqhkiG9w0BCQEWG3BlcnNvbmFsLXByZW1pdW1AdGhhd3RlLmNv +bTAeFw05NjAxMDEwMDAwMDBaFw0yMDEyMzEyMzU5NTlaMIHPMQswCQYDVQQGEwJa +QTEVMBMGA1UECBMMV2VzdGVybiBDYXBlMRIwEAYDVQQHEwlDYXBlIFRvd24xGjAY +BgNVBAoTEVRoYXd0ZSBDb25zdWx0aW5nMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9u +IFNlcnZpY2VzIERpdmlzaW9uMSMwIQYDVQQDExpUaGF3dGUgUGVyc29uYWwgUHJl +bWl1bSBDQTEqMCgGCSqGSIb3DQEJARYbcGVyc29uYWwtcHJlbWl1bUB0aGF3dGUu +Y29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDJZtn4B0TPuYwu8KHvE0Vs +Bd/eJxZRNkERbGw77f4QfRKe5ZtCmv5gMcNmt3M6SK5O0DI3lIi1DbbZ8/JE2dWI +Et12TfIa/G8jHnrx2JhFTgcQ7xZC0EN1bUre4qrJMf8fAHB8Zs8QJQi6+u4A6UYD +ZicRFTuqW/KY3TZCstqIdQIDAQABoxMwETAPBgNVHRMBAf8EBTADAQH/MA0GCSqG +SIb3DQEBBAUAA4GBAGk2ifc0KjNyL2071CKyuG+axTZmDhs8obF1Wub9NdP4qPIH +b4Vnjt4rueIXsDqg8A6iAJrf8xQVbrvIhVqYgPn/vnQdPfP+MCXRNzRn+qVxeTBh +KXLA4CxM+1bkOqhv5TJZUtt1KFBZDPgLGeSs2a+WjS9Q2wfD6h+rM+D1KzGJ +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: 0 (0x0) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting, OU=Certification Services Division, CN=Thawte Personal Premium CA/Email=personal-premium@thawte.com + Validity + Not Before: Jan 1 00:00:00 1996 GMT + Not After : Dec 31 23:59:59 2020 GMT + Subject: C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting, OU=Certification Services Division, CN=Thawte Personal Premium CA/Email=personal-premium@thawte.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:c9:66:d9:f8:07:44:cf:b9:8c:2e:f0:a1:ef:13: + 45:6c:05:df:de:27:16:51:36:41:11:6c:6c:3b:ed: + fe:10:7d:12:9e:e5:9b:42:9a:fe:60:31:c3:66:b7: + 73:3a:48:ae:4e:d0:32:37:94:88:b5:0d:b6:d9:f3: + f2:44:d9:d5:88:12:dd:76:4d:f2:1a:fc:6f:23:1e: + 7a:f1:d8:98:45:4e:07:10:ef:16:42:d0:43:75:6d: + 4a:de:e2:aa:c9:31:ff:1f:00:70:7c:66:cf:10:25: + 08:ba:fa:ee:00:e9:46:03:66:27:11:15:3b:aa:5b: + f2:98:dd:36:42:b2:da:88:75 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: md5WithRSAEncryption + 69:36:89:f7:34:2a:33:72:2f:6d:3b:d4:22:b2:b8:6f:9a:c5: + 36:66:0e:1b:3c:a1:b1:75:5a:e6:fd:35:d3:f8:a8:f2:07:6f: + 85:67:8e:de:2b:b9:e2:17:b0:3a:a0:f0:0e:a2:00:9a:df:f3: + 14:15:6e:bb:c8:85:5a:98:80:f9:ff:be:74:1d:3d:f3:fe:30: + 25:d1:37:34:67:fa:a5:71:79:30:61:29:72:c0:e0:2c:4c:fb: + 56:e4:3a:a8:6f:e5:32:59:52:db:75:28:50:59:0c:f8:0b:19: + e4:ac:d9:af:96:8d:2f:50:db:07:c3:ea:1f:ab:33:e0:f5:2b: + 31:89 + +Thawte Premium Server CA +======================== +MD5 Fingerprint: 06:9F:69:79:16:66:90:02:1B:8C:8C:A2:C3:07:6F:3A +PEM Data: +-----BEGIN CERTIFICATE----- +MIIDJzCCApCgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBzjELMAkGA1UEBhMCWkEx +FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYD +VQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlv +biBTZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UEAxMYVGhhd3RlIFByZW1pdW0gU2Vy +dmVyIENBMSgwJgYJKoZIhvcNAQkBFhlwcmVtaXVtLXNlcnZlckB0aGF3dGUuY29t +MB4XDTk2MDgwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgc4xCzAJBgNVBAYTAlpB +MRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEdMBsG +A1UEChMUVGhhd3RlIENvbnN1bHRpbmcgY2MxKDAmBgNVBAsTH0NlcnRpZmljYXRp +b24gU2VydmljZXMgRGl2aXNpb24xITAfBgNVBAMTGFRoYXd0ZSBQcmVtaXVtIFNl +cnZlciBDQTEoMCYGCSqGSIb3DQEJARYZcHJlbWl1bS1zZXJ2ZXJAdGhhd3RlLmNv +bTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0jY2aovXwlue2oFBYo847kkE +VdbQ7xwblRZH7xhINTpS9CtqBo87L+pW46+GjZ4X9560ZXUCTe/LCaIhUdib0GfQ +ug2SBhRz1JPLlyoAnFxODLz6FVL88kRu2hFKbgifLy3j+ao6hnO2RlNYyIkFvYMR +uHM/qgeN9EJN50CdHDcCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG +9w0BAQQFAAOBgQAmSCwWwlj66BZ0DKqqX1Q/8tfJeGBeXm43YyJ3Nn6yF8Q0ufUI +hfzJATj/Tb7yFkJD57taRvvBxhEf8UqwKEbJw8RCfbz6q1lu1bdRiBHjpIUZa4JM +pAwSremkrj/xw0llmozFyD4lt5SZu5IycQfwhl7tUCemDaYj+bvLpgcUQg== +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting cc, OU=Certification Services Division, CN=Thawte Premium Server CA/Email=premium-server@thawte.com + Validity + Not Before: Aug 1 00:00:00 1996 GMT + Not After : Dec 31 23:59:59 2020 GMT + Subject: C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting cc, OU=Certification Services Division, CN=Thawte Premium Server CA/Email=premium-server@thawte.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:d2:36:36:6a:8b:d7:c2:5b:9e:da:81:41:62:8f: + 38:ee:49:04:55:d6:d0:ef:1c:1b:95:16:47:ef:18: + 48:35:3a:52:f4:2b:6a:06:8f:3b:2f:ea:56:e3:af: + 86:8d:9e:17:f7:9e:b4:65:75:02:4d:ef:cb:09:a2: + 21:51:d8:9b:d0:67:d0:ba:0d:92:06:14:73:d4:93: + cb:97:2a:00:9c:5c:4e:0c:bc:fa:15:52:fc:f2:44: + 6e:da:11:4a:6e:08:9f:2f:2d:e3:f9:aa:3a:86:73: + b6:46:53:58:c8:89:05:bd:83:11:b8:73:3f:aa:07: + 8d:f4:42:4d:e7:40:9d:1c:37 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: md5WithRSAEncryption + 26:48:2c:16:c2:58:fa:e8:16:74:0c:aa:aa:5f:54:3f:f2:d7: + c9:78:60:5e:5e:6e:37:63:22:77:36:7e:b2:17:c4:34:b9:f5: + 08:85:fc:c9:01:38:ff:4d:be:f2:16:42:43:e7:bb:5a:46:fb: + c1:c6:11:1f:f1:4a:b0:28:46:c9:c3:c4:42:7d:bc:fa:ab:59: + 6e:d5:b7:51:88:11:e3:a4:85:19:6b:82:4c:a4:0c:12:ad:e9: + a4:ae:3f:f1:c3:49:65:9a:8c:c5:c8:3e:25:b7:94:99:bb:92: + 32:71:07:f0:86:5e:ed:50:27:a6:0d:a6:23:f9:bb:cb:a6:07: + 14:42 + +Thawte Server CA +================ +MD5 Fingerprint: C5:70:C4:A2:ED:53:78:0C:C8:10:53:81:64:CB:D0:1D +PEM Data: +-----BEGIN CERTIFICATE----- +MIIDEzCCAnygAwIBAgIBATANBgkqhkiG9w0BAQQFADCBxDELMAkGA1UEBhMCWkEx +FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYD +VQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlv +biBTZXJ2aWNlcyBEaXZpc2lvbjEZMBcGA1UEAxMQVGhhd3RlIFNlcnZlciBDQTEm +MCQGCSqGSIb3DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5jb20wHhcNOTYwODAx +MDAwMDAwWhcNMjAxMjMxMjM1OTU5WjCBxDELMAkGA1UEBhMCWkExFTATBgNVBAgT +DFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3 +dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNl +cyBEaXZpc2lvbjEZMBcGA1UEAxMQVGhhd3RlIFNlcnZlciBDQTEmMCQGCSqGSIb3 +DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQAD +gY0AMIGJAoGBANOkUG7I/1Zr5s9dtuoMaHVHoqrC2oQl/Kj0R1HahbUgdJSGHg91 +yekIYfUGbTBuFRkC6VLAYttNmZ7iagxEOM3+vuNkCXDF/rFrKbYvScg71CcEJRCX +L+eQbcAoQpnXTEPew/UhbVSfXcNY4cDk2VuwuNy0e982OsK1ZiIS1ocNAgMBAAGj +EzARMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAB/pMaVz7lcxG +7oWDTSEwjsrZqG9JGubaUeNgcGyEYRGhGshIPllDfU+VPaGLtwtimHp1it2ITk6e +QNuozDJ0uW8NxuOzRAvZim+aKZuZGCg70eNAKJpaPNW15yAbi8qkq43pUdniTCxZ +qdq5snUb9kLy78fyGPmJvKP/iiMucEc= +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting cc, OU=Certification Services Division, CN=Thawte Server CA/Email=server-certs@thawte.com + Validity + Not Before: Aug 1 00:00:00 1996 GMT + Not After : Dec 31 23:59:59 2020 GMT + Subject: C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting cc, OU=Certification Services Division, CN=Thawte Server CA/Email=server-certs@thawte.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:d3:a4:50:6e:c8:ff:56:6b:e6:cf:5d:b6:ea:0c: + 68:75:47:a2:aa:c2:da:84:25:fc:a8:f4:47:51:da: + 85:b5:20:74:94:86:1e:0f:75:c9:e9:08:61:f5:06: + 6d:30:6e:15:19:02:e9:52:c0:62:db:4d:99:9e:e2: + 6a:0c:44:38:cd:fe:be:e3:64:09:70:c5:fe:b1:6b: + 29:b6:2f:49:c8:3b:d4:27:04:25:10:97:2f:e7:90: + 6d:c0:28:42:99:d7:4c:43:de:c3:f5:21:6d:54:9f: + 5d:c3:58:e1:c0:e4:d9:5b:b0:b8:dc:b4:7b:df:36: + 3a:c2:b5:66:22:12:d6:87:0d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: md5WithRSAEncryption + 07:fa:4c:69:5c:fb:95:cc:46:ee:85:83:4d:21:30:8e:ca:d9: + a8:6f:49:1a:e6:da:51:e3:60:70:6c:84:61:11:a1:1a:c8:48: + 3e:59:43:7d:4f:95:3d:a1:8b:b7:0b:62:98:7a:75:8a:dd:88: + 4e:4e:9e:40:db:a8:cc:32:74:b9:6f:0d:c6:e3:b3:44:0b:d9: + 8a:6f:9a:29:9b:99:18:28:3b:d1:e3:40:28:9a:5a:3c:d5:b5: + e7:20:1b:8b:ca:a4:ab:8d:e9:51:d9:e2:4c:2c:59:a9:da:b9: + b2:75:1b:f6:42:f2:ef:c7:f2:18:f9:89:bc:a3:ff:8a:23:2e: + 70:47 + +Thawte Universal CA Root +======================== +MD5 Fingerprint: 17:AF:71:16:52:7B:73:65:22:05:29:28:84:71:9D:13 +PEM Data: +-----BEGIN CERTIFICATE----- +MIIRIjCCCQoCAQAwDQYJKoZIhvcNAQEFBQAwVzEPMA0GA1UEChMGVGhhd3RlMSEw +HwYDVQQLExhUaGF3dGUgVW5pdmVyc2FsIENBIFJvb3QxITAfBgNVBAMTGFRoYXd0 +ZSBVbml2ZXJzYWwgQ0EgUm9vdDAeFw05OTEyMDUxMzU2MDVaFw0zNzA0MDMxMzU2 +MDVaMFcxDzANBgNVBAoTBlRoYXd0ZTEhMB8GA1UECxMYVGhhd3RlIFVuaXZlcnNh +bCBDQSBSb290MSEwHwYDVQQDExhUaGF3dGUgVW5pdmVyc2FsIENBIFJvb3Qwgggi +MA0GCSqGSIb3DQEBAQUAA4IIDwAwgggKAoIIAQDiiQVtw3+tpok6/7vHzZ03seHS +IR6bYSoV53tXT1U80Lv52T0+przstK1TmhYC6wty/Yryj0QFxevT5b22RDnm+0e/ +ap4KlRjiaOLWltYhrYj99Rf109pCpZDtKZWWdTrah6HU9dOH3gVipuNmdJLPpby7 +32j/cXVWQVk16zNaZlHy0qMKwYzOc1wRby2MlYyRsf3P5a1WlcyFkoOQVUHJwnft ++aN0QgpoCPPQ0WX9Zyw0/yR/53nIBzslV92kDJg9vuDMGWXb8lSir0LUneKuhCMl +CTMStWoedsSL2UkAbF66H/Ib2mfKJ6qjRCMbg4LO8qsz7VSk3MmrWWXROA7BPhtn +j9Z1AeBVIt12d+yO3fTPeSJtuVcD9ZkIpzw+NPvEF64jWM0k8yPKagIolAGBNLRs +a66LGsOj0gk8FlT1Nl8k459KoeJkxhbDpoF6JDZHjsFeDvv5FXgE1g5Z2Z1YZmLS +lCkyMsh4uWb2tVbhbMYUS5ZSWZECJGpVR9c/tiMaYHeXLuJAr54EV56tEcXJQ3Dv +SLRerBxpLi6C1VuLvoK+GRRe5w0ix1Eb/x6b8TCPcTEGszQnj196ZoJPii0Tq0LP +IVael45mNg+Wm+Ur9AKpKmqMLMTDuHAsLSkeP1B3Hm0qVORVCpE4ocW1ZqJ2Wu4P +v7Rn4ShuD+E2oYLRv9R34cRnMpN4yOdUU/4jeeZozCaQ9hBjXSpvkS2kczJRIfK7 +Fd+qJAhIBt6hnia/uoO/fKTIoIy90v+8hGknEyQYxEUYIyZeGBTKLoiHYqNT5iG3 +uIV7moW7FSZy+Ln3anQPST+SvqkFt5knv78JF0uZTK0REHzfdDH2jyZfqoiuOFfI +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 +yJTuQFv5QgLC/7DYLOsof17JJgGZpw== +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 1 (0x0) + Serial Number: 0 (0x0) + Signature Algorithm: sha1WithRSAEncryption + Issuer: O=Thawte, OU=Thawte Universal CA Root, CN=Thawte Universal CA Root + Validity + Not Before: Dec 5 13:56:05 1999 GMT + Not After : Apr 3 13:56:05 2037 GMT + Subject: O=Thawte, OU=Thawte Universal CA Root, CN=Thawte Universal CA Root + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (16384 bit) + Modulus (16384 bit): + 00:e2:89:05:6d:c3:7f:ad:a6:89:3a:ff:bb:c7:cd: + 9d:37:b1:e1:d2:21:1e:9b:61:2a:15:e7:7b:57:4f: + 55:3c:d0:bb:f9:d9:3d:3e:a6:bc:ec:b4:ad:53:9a: + 16:02:eb:0b:72:fd:8a:f2:8f:44:05:c5:eb:d3:e5: + bd:b6:44:39:e6:fb:47:bf:6a:9e:0a:95:18:e2:68: + e2:d6:96:d6:21:ad:88:fd:f5:17:f5:d3:da:42:a5: + 90:ed:29:95:96:75:3a:da:87:a1:d4:f5:d3:87:de: + 05:62:a6:e3:66:74:92:cf:a5:bc:bb:df:68:ff:71: + 75:56:41:59:35:eb:33:5a:66:51:f2:d2:a3:0a:c1: + 8c:ce:73:5c:11:6f:2d:8c:95:8c:91:b1:fd:cf:e5: + ad:56:95:cc:85:92:83:90:55:41:c9:c2:77:ed:f9: + a3:74:42:0a:68:08:f3:d0:d1:65:fd:67:2c:34:ff: + 24:7f:e7:79:c8:07:3b:25:57:dd:a4:0c:98:3d:be: + e0:cc:19:65:db:f2:54:a2:af:42:d4:9d:e2:ae:84: + 23:25:09:33:12:b5:6a:1e:76:c4:8b:d9:49:00:6c: + 5e:ba:1f:f2:1b:da:67:ca:27:aa:a3:44:23:1b:83: + 82:ce:f2:ab:33:ed:54:a4:dc:c9:ab:59:65:d1:38: + 0e:c1:3e:1b:67:8f:d6:75:01:e0:55:22:dd:76:77: + ec:8e:dd:f4:cf:79:22:6d:b9:57:03:f5:99:08:a7: + 3c:3e:34:fb:c4:17:ae:23:58:cd:24:f3:23:ca:6a: + 02:28:94:01:81:34:b4:6c:6b:ae:8b:1a:c3:a3:d2: + 09:3c:16:54:f5:36:5f:24:e3:9f:4a:a1:e2:64:c6: + 16:c3:a6:81:7a:24:36:47:8e:c1:5e:0e:fb:f9:15: + 78:04:d6:0e:59:d9:9d:58:66:62:d2:94:29:32:32: + c8:78:b9:66:f6:b5:56:e1:6c:c6:14:4b:96:52:59: + 91:02:24:6a:55:47:d7:3f:b6:23:1a:60:77:97:2e: + e2:40:af:9e:04:57:9e:ad:11:c5:c9:43:70:ef:48: + b4:5e:ac:1c:69:2e:2e:82:d5:5b:8b:be:82:be:19: + 14:5e:e7:0d:22:c7:51:1b:ff:1e:9b:f1:30:8f:71: + 31:06:b3:34:27:8f:5f:7a:66:82:4f:8a:2d:13:ab: + 42:cf:21:56:9e:97:8e:66:36:0f:96:9b:e5:2b:f4: + 02:a9:2a:6a:8c:2c:c4:c3:b8:70:2c:2d:29:1e:3f: + 50:77:1e:6d:2a:54:e4:55:0a:91:38:a1:c5:b5:66: + a2:76:5a:ee:0f:bf:b4:67:e1:28:6e:0f:e1:36:a1: + 82:d1:bf:d4:77:e1:c4:67:32:93:78:c8:e7:54:53: + fe:23:79:e6:68:cc:26:90:f6:10:63:5d:2a:6f:91: + 2d:a4:73:32:51:21:f2:bb:15:df:aa:24:08:48:06: + de:a1:9e:26:bf:ba:83:bf:7c:a4:c8:a0:8c:bd:d2: + ff:bc:84:69:27:13:24:18:c4:45:18:23:26:5e:18: + 14:ca:2e:88:87:62:a3:53:e6:21:b7:b8:85:7b:9a: + 85:bb:15:26:72:f8:b9:f7:6a:74:0f:49:3f:92:be: + a9:05:b7:99:27:bf:bf:09:17:4b:99:4c:ad:11:10: + 7c:df:74:31:f6:8f:26:5f:aa:88:ae:38:57:c8:55: + 2d:d3:fb:d8:1b:51:99:be:25:1b:3a:ba:c0:7d:1b: + ed:ce:d2:49:b9:cf:f3:c5:7d:89:90:81:d8:69:48: + 20:10:a3:f8:ef:92:51:18:32:8b:11:18:c0:3f:1b: + 85:56:ce:57:c9:f2:82:64:c6:df:02:09:2e:4a:11: + 2f:b1:27:6d:37:52:f0:f0:16:61:f1:67:8d:df:87: + 72:af:87:da:cf:fb:50:94:6e:d4:94:85:eb:8a:2c: + ea:21:f5:96:4a:44:d5:e0:ce:6a:74:44:4d:d0:05: + d3:87:15:ed:36:d0:a4:8b:66:55:70:93:ee:47:06: + c1:7e:2e:a5:18:79:67:f3:28:85:f1:70:f7:0e:83: + a4:7e:54:9e:5a:76:32:cb:65:1b:b8:cd:fb:c8:28: + 03:d2:54:91:d1:a7:c5:85:43:08:17:76:a5:e6:2f: + 67:08:d8:a1:a2:82:2d:0c:f8:c1:af:63:d4:50:77: + 6d:6b:46:4a:41:85:d5:90:5f:79:2d:c4:ec:d7:11: + 87:40:8a:e1:68:e2:64:f8:55:32:fb:6f:93:2c:da: + 77:d9:21:c1:17:e5:36:2c:4e:7e:90:7f:ac:94:2b: + 32:67:be:38:50:76:b8:ae:41:b9:d7:21:c5:09:4c: + 60:c8:a3:51:c4:34:9b:57:37:df:cb:c9:33:57:8b: + eb:fb:76:9f:19:4d:c5:6a:1f:2a:45:ae:2b:ed:2f: + 8d:a7:a5:00:cb:04:fa:25:62:2e:74:48:1b:ca:2a: + 8c:ba:db:b6:7e:f6:bb:02:7c:a9:c3:db:58:78:a1: + bf:f0:fe:1a:10:55:11:ce:e8:69:4e:96:65:c6:17: + 03:d6:07:68:8c:54:82:ae:1c:22:55:3f:f1:f4:09: + 97:28:c0:46:f7:4e:0b:25:1d:f7:07:d7:09:1d:3a: + 18:57:38:3b:e8:33:06:e7:8f:78:46:1e:5b:f5:06: + b6:ec:b8:a6:0d:f1:ba:13:4b:d6:18:20:dd:69:33: + 4a:33:15:ae:b8:c8:98:8a:27:2c:93:bc:2d:fb:ee: + 33:bf:66:e6:4d:ba:b6:9b:06:55:60:97:4b:bc:44: + cd:7e:f4:a1:d8:aa:2f:c0:02:28:21:16:62:78:db: + 08:54:f2:fc:f4:34:e3:c6:8f:1c:43:57:ce:90:1a: + 4b:dc:2e:3b:28:91:89:3f:7a:da:35:1d:8e:2c:ee: + 49:ec:f4:33:ad:c9:53:a8:8c:9f:04:53:3e:24:1c: + 52:c9:12:f9:62:57:a3:bc:ee:2c:eb:40:7c:20:23: + 70:2b:95:f9:73:17:8a:d1:c1:1c:69:a6:b7:38:9a: + 67:f7:70:1d:7a:5a:0c:40:cf:62:0f:85:3c:c2:02: + 4e:7e:b5:f6:c5:2a:29:84:b3:1f:37:2a:e1:aa:72: + 42:c4:ed:6b:1a:8f:92:1c:5d:be:d1:f2:5b:f2:ab: + aa:a9:d2:f5:b8:a4:41:2b:2b:91:6e:12:48:ca:98: + d8:37:8d:c8:ed:00:30:b5:b6:04:4e:7e:9c:da:84: + ec:c0:fa:7b:e5:1d:88:a4:53:46:b0:94:e4:5c:1b: + a1:25:2c:0f:48:52:77:97:09:6c:ec:5b:18:33:83: + 02:e5:82:7e:cd:85:21:30:11:fd:27:4f:cf:e4:1e: + ec:3f:a5:57:6c:e9:2a:30:19:2a:88:e5:c3:69:38: + ab:6f:39:71:7f:84:e1:41:c3:e1:cc:2a:89:20:52: + 2e:83:0f:6c:39:3f:4b:2d:16:ac:2d:f0:24:ac:00: + 73:f4:9b:b3:06:3f:05:b8:14:85:1f:ab:9e:5c:3c: + 9e:62:9d:0e:6d:3b:80:09:fc:02:ea:a2:97:74:ca: + c7:f9:e3:56:e1:c3:ca:a5:a6:9a:c0:90:e0:24:12: + 53:d2:c2:8b:da:be:ed:02:43:5e:67:e1:89:98:79: + ee:cb:aa:ca:c3:1b:dc:e7:a5:46:a5:7c:6b:16:87: + b6:5a:28:d7:db:27:3c:5e:a5:bd:b6:51:dd:1f:43: + cf:3b:26:c8:3a:8d:25:61:c1:49:f4:3c:1b:c9:44: + ea:af:1c:c2:2b:94:01:2a:0e:30:d1:5b:8b:2b:47: + e5:c3:d1:04:03:9b:0e:39:2c:d6:27:d4:e6:70:5a: + d9:75:cf:2a:d8:c9:00:05:e4:13:88:ec:c3:39:fb: + 87:61:30:36:43:03:c8:9e:9c:a2:06:c2:2f:c5:fc: + f0:80:63:b1:54:04:a0:4c:a9:2e:c6:f5:76:7a:d8: + d0:e4:d4:94:11:e5:15:b5:78:06:dc:b8:80:8f:99: + a9:20:33:3d:10:85:4c:65:09:ca:3e:58:5e:60:93: + 9a:aa:62:5d:c0:51:06:1c:5d:60:a0:0d:9c:4b:43: + f6:a7:16:21:a4:87:aa:f2:c1:2e:ee:92:30:b8:9e: + df:df:10:01:8b:86:09:70:d8:6c:a8:b7:50:1e:16: + 96:b4:f7:67:fd:35:3a:21:90:2a:32:c7:00:7b:4d: + 07:10:09:b9:2f:73:d8:18:7e:67:99:04:4f:06:fc: + 50:c7:85:9b:9d:40:9d:b3:96:37:fa:a5:dc:b2:72: + 4e:ef:4e:09:2c:fd:91:fd:4d:f7:bb:a6:a1:3e:ab: + 7b:a2:03:40:a6:a9:55:27:e2:fa:f9:19:ce:87:75: + aa:f1:75:36:f3:f3:b8:91:f8:91:c3:8b:75:13:8e: + 4c:65:9a:16:39:6a:e5:34:e8:7a:96:59:7f:35:b0: + 00:fd:5b:69:fc:43:26:fa:f5:28:6e:fe:87:d9:7e: + 24:fb:b4:a0:82:6e:54:a2:ff:ae:bf:62:b4:f4:72: + 01:c2:cb:98:47:98:e1:4c:b5:17:80:80:ce:8f:a6: + 28:ee:1e:45:6a:fb:df:f1:1d:fc:5a:3b:d6:ea:f4: + 6c:1d:62:49:57:3b:8a:8f:86:ea:f0:53:04:ce:9c: + 16:68:ff:ba:b9:fc:88:0f:47:f7:02:44:72:40:b8: + ca:3b:2d:53:9d:dc:3c:56:8c:59:7b:68:1a:2c:8d: + 71:bb:6c:00:c7:1a:ce:6f:40:92:b1:a3:2f:0f:d9: + 44:f2:a3:70:2e:9e:ee:0e:ae:32:d0:3b:3e:8b:07: + ea:e6:79:b3:5c:29:e2:7d:6b:a8:5e:f9:5a:31:e8: + 08:96:a2:8c:03:98:46:f1:b8:7d:90:54:26:ed:76: + 62:fe:9e:e9:9a:6e:5e:c9:49:c7:5c:34:53:29:54: + d9:ec:e4:46:e1:80:3b:75:d9:df:fb:79:d5:87:f1: + ba:9e:eb:19:ce:4c:52:73:e6:5b:87:ae:25:4f:39: + 79:cc:c6:b8:f9:10:7b:ec:f0:9b:71:a4:05:a0:d3: + 29:d3:4e:7f:1f:f4:2d:28:78:cc:55:95:7b:1e:91: + 2f:cc:56:18:73:8b:b2:db:bc:69:07:e6:d0:d8:4f: + ed:a2:ff:58:85:a3:6d:e0:4a:53:b7:67:7d:8d:0c: + 5c:5b:7b:77:28:02:35:44:7a:04:d3:28:43:c8:6b: + 30:17:5d:32:b8:29:35:ba:76:da:3b:14:4a:76:18: + 58:a4:f8:92:3c:9e:4d:33:6f:46:6b:08:d9:31:48: + 68:dd:f4:fb:24:56:34:b2:cf:69:66:be:48:d2:8a: + 66:22:cd:f2:69:cd:c2:53:13:45:29:41:22:d6:5d: + 98:1f:b6:a4:b2:a3:c2:ee:02:2f:51:1b:dc:83:a4: + ec:70:25:a8:d4:08:61:32:6f:e4:a1:81:2e:7c:63: + 72:fa:29:65:bc:70:44:cf:5d + Exponent: 65537 (0x10001) + Signature Algorithm: sha1WithRSAEncryption + 55:9a:34:6a:22:06:69:09:45:33:c7:ae:a9:5c:c7:09:4e:9b: + 86:bc:41:90:d4:94:52:f6:cd:23:29:94:4b:22:cd:e8:bd:fe: + 9d:cd:52:f2:bd:ed:ab:87:c9:ab:ab:46:04:b4:bd:a2:3f:22: + 30:47:50:c0:4b:8c:76:0f:03:f5:92:d2:b1:2d:c4:7a:35:9c: + c9:73:87:eb:a6:9f:de:0f:73:8d:d3:7f:99:d8:ba:8f:6f:c4: + f3:be:1a:ae:8b:a2:94:36:90:e2:e5:eb:8d:05:f4:fc:65:df: + 95:f1:c4:94:4d:17:56:d7:9f:3c:8f:50:3c:e7:77:bf:95:86: + 26:64:fb:6a:ff:c6:da:e9:8c:ae:42:bb:69:e5:33:c6:d8:e9: + 0d:c6:55:21:49:c1:0c:b4:a3:f9:9b:4b:5c:de:83:4f:41:03: + ce:2a:79:68:38:7d:f0:54:49:20:f5:b6:10:ff:08:dc:33:66: + 96:9b:ff:06:de:00:9e:d7:ce:56:43:9a:51:fc:70:cd:f6:f0: + 51:a3:b7:cd:b4:5c:85:62:cd:71:b7:c6:2b:23:2b:dd:c3:6e: + 40:42:fa:37:ff:37:1c:f6:7a:57:94:87:85:23:d7:d4:c9:c7: + 5f:c1:4d:2f:c9:0d:d7:5c:ec:9c:25:ee:9e:30:82:91:96:72: + b8:75:1d:f8:09:68:57:97:b2:2d:4b:ee:25:ec:7a:24:29:ee: + 72:d4:9c:13:db:ab:dc:03:0a:d8:4a:14:c9:08:57:44:5d:a1: + b5:53:80:34:f2:14:97:cf:52:de:a2:0e:8a:10:e9:14:ef:d0: + 60:be:61:a1:f1:25:5d:d5:18:73:3f:93:10:ca:96:ee:b3:40: + d2:db:a3:55:cf:57:5a:a5:0e:4f:75:47:df:ea:f7:90:9a:6d: + f5:70:2e:1d:14:1c:37:64:04:59:50:b0:dc:72:86:6f:9c:37: + 3d:5d:28:af:73:55:ef:d2:ee:24:74:74:13:ef:dc:db:31:49: + fb:3f:63:f5:d3:08:3e:33:a5:e7:9d:0a:de:53:2c:51:8e:67: + db:9b:41:65:41:50:bd:d4:a4:96:6c:87:bc:12:e0:94:c7:d3: + c0:e4:cb:73:58:00:83:e1:ac:27:85:d6:9d:53:9d:5c:bd:0a: + 3e:03:43:9c:0c:91:f5:6d:7b:f8:40:72:75:ab:11:76:91:2b: + e1:c6:aa:1f:70:69:76:70:15:09:fe:93:d0:d6:2d:b7:15:6a: + 9b:67:5c:b4:69:9f:25:a6:7d:8a:fb:7d:22:a9:71:f2:ce:4e: + 8c:b8:21:2d:de:fe:41:71:0d:ff:9d:ec:73:a6:bb:07:4f:88: + 0e:58:47:2e:7e:a9:c2:c7:78:dd:ba:7a:9e:4e:e0:30:4e:63: + 6f:85:d4:20:41:e9:fa:fe:43:45:e7:fb:af:7a:b2:ce:a4:05: + 1d:22:9a:58:86:df:e4:ce:4c:a9:fe:d8:16:a5:6f:fb:d8:ce: + 56:7b:f5:d6:20:ef:e4:47:cd:63:24:ff:b9:be:f1:48:a3:c1: + 01:72:e6:bd:c0:ad:ed:26:0d:ca:34:9f:fc:02:2d:20:4f:05: + 20:ae:21:3d:0c:c2:20:3c:3f:f0:04:84:dc:cf:89:fd:b9:25: + 91:8e:d0:43:e6:b3:20:ab:5c:2d:d5:40:9e:a0:4b:d8:f4:b2: + cc:7d:f1:58:0a:8e:87:ed:88:ac:36:96:e4:56:a0:11:8a:f2: + 9a:d0:b3:57:a3:34:bb:19:ab:38:e1:74:6b:22:c4:31:ce:01: + d5:1b:36:e3:1e:38:4c:33:93:df:40:e3:59:57:4e:ac:6e:7b: + 1e:5a:3d:c5:1d:5b:ac:c8:10:82:35:02:22:b2:fc:75:e8:10: + 91:8d:c4:7d:78:93:47:9e:1c:9d:ac:6b:62:02:58:8c:d6:1c: + 23:d6:af:78:c2:80:9c:a4:aa:24:54:14:b5:14:98:c6:f8:2b: + 1a:24:cb:71:32:0a:e2:9b:0e:69:6b:dd:7e:8c:64:d1:2e:63: + ef:0e:7f:b1:3e:88:4c:9d:55:e5:c9:6e:17:04:b7:41:ff:bd: + 8a:41:cb:25:31:6f:44:77:3f:47:b1:fc:81:88:07:8e:05:49: + 20:b7:11:d9:69:03:2a:03:9d:b9:33:84:9a:df:df:7a:e3:46: + 73:a3:d8:a2:8c:53:19:88:55:4c:74:b8:f6:44:84:2b:d1:14: + 2d:4e:39:2e:92:68:ff:69:fc:85:62:1b:eb:55:4f:ef:25:84: + 62:45:99:d6:d8:4e:6f:3f:53:08:7d:1d:06:95:81:80:7f:4f: + 4e:74:36:98:b5:e2:87:70:98:dc:d7:f5:dc:52:15:e6:c6:d6: + 79:96:39:7f:8f:95:cf:ab:80:53:ad:1b:0b:45:40:0e:d4:18: + bd:2c:de:8a:77:76:fd:f2:44:47:c6:21:d0:e4:74:f0:d8:18: + 05:c8:7c:30:72:c7:df:f1:bb:fc:02:30:a9:f4:42:26:59:0d: + 93:05:82:a1:73:ed:34:e5:38:5d:cd:50:90:fe:94:fc:13:bc: + bd:fc:a8:a2:88:a7:73:c4:b2:a8:d1:5d:88:c4:02:a2:7a:f1: + 04:c9:fe:8c:74:c9:ef:1d:64:41:9f:ac:1e:96:67:64:ac:ab: + 28:41:c7:9d:f7:c0:98:1b:6e:07:c2:64:7d:5a:83:66:56:28: + 36:9c:e7:fb:1c:77:0e:28:a0:c4:f7:6b:79:39:04:20:84:c7: + 57:93:bc:1b:a0:ea:bc:eb:42:e5:a8:11:fe:fc:ac:65:cc:fd: + f8:28:88:f4:a5:9a:e5:73:51:e0:a8:9b:0d:03:77:4e:e5:e0: + 98:b3:88:da:7d:e6:c6:9e:7c:14:66:c1:2e:53:4a:92:07:37: + a0:7e:e9:3d:09:e4:15:7c:cf:fd:b8:41:a5:ef:9e:66:9d:c4: + 5e:07:1d:87:f8:41:ad:ea:e7:2f:d2:41:63:18:37:f9:14:e3: + 4d:d0:e5:f7:43:fd:15:e3:f9:36:73:06:26:df:01:4f:a9:c3: + 4e:de:20:46:77:98:b4:7a:24:2b:3b:75:2b:4e:58:8d:9b:5d: + a4:c7:16:a0:bc:32:88:3f:a1:83:f3:00:c8:f8:d8:58:e9:63: + 5d:4c:2b:b5:f0:72:41:d8:ab:77:37:d6:72:74:ae:b6:36:9c: + c8:a6:83:49:4b:e0:c9:56:0b:29:be:00:30:cb:dd:d6:c8:42: + 8a:00:d9:ec:15:d1:34:71:f2:5b:64:87:f6:27:d2:b7:eb:86: + b0:90:bf:29:db:21:9e:36:8c:e3:20:2f:95:23:51:6c:1b:c2: + a4:d5:e6:d8:02:43:67:a0:fe:9b:50:03:44:7f:bb:e4:72:d5: + d1:e4:da:8f:92:14:64:fb:5d:14:10:12:4a:95:06:c9:65:08: + 29:ca:21:a3:26:38:11:c9:27:df:70:67:04:fd:ca:48:32:7f: + 63:b2:45:74:31:50:4f:87:d9:20:70:d2:21:70:b1:d6:10:9d: + 33:5d:78:83:91:6d:55:82:ec:da:e4:62:63:c7:81:46:d7:19: + 65:72:2a:43:19:90:b8:d7:23:4d:4c:1c:e0:44:a9:66:67:ac: + ee:71:79:27:26:78:6d:72:0e:f5:5d:4b:23:b5:7c:7c:65:e9: + 17:c6:3a:0b:0d:dd:5e:1e:51:c3:86:b8:ec:7f:c7:27:4a:a5: + 46:e8:6a:2d:19:c1:87:a3:cb:99:93:87:64:a2:55:14:4c:b7: + 43:a5:93:d7:e7:d2:4e:79:40:ca:65:99:46:3d:3f:7a:80:7a: + 88:6a:cc:1e:e5:6b:33:46:f4:50:c0:d5:1f:09:b8:cd:8a:2e: + a1:27:eb:5d:73:a7:e8:6b:0a:e5:57:82:2a:b0:fc:e2:54:52: + 56:f0:ab:a9:12:c6:23:96:07:24:9c:e0:bc:46:a5:b4:20:04: + da:09:93:63:e5:d4:2e:c2:7e:c5:31:ed:b5:15:74:86:17:b9: + b3:f3:26:8a:1d:02:6a:da:1a:3f:e8:ba:f1:04:6d:94:51:54: + e2:5a:b4:59:83:1d:60:d0:2d:73:cc:07:b5:26:8c:f9:d7:c6: + 88:91:ef:80:cf:5d:0f:a1:60:cb:45:d4:42:22:d1:b1:70:1d: + fd:d0:b7:30:90:3a:c6:48:6d:67:e5:32:da:8f:db:e3:a8:e3: + 1d:20:25:a2:1c:e1:4c:b9:a4:f6:c6:3f:5c:58:0d:bb:c6:b2: + 77:01:16:91:9f:17:06:0d:b7:40:3e:cc:8f:8e:9c:4b:e0:9d: + 7e:9b:1e:05:ab:88:22:fa:d3:28:1b:57:14:64:4a:3e:24:2c: + 38:4d:21:69:00:73:2e:d0:55:2d:74:f2:15:e8:94:43:3e:40: + 2a:c6:c6:b9:6a:5b:de:a2:cc:18:50:54:5d:4e:2a:85:6c:f6: + 92:8b:29:19:7e:e7:ea:4a:e0:22:2b:25:bc:f7:66:cf:77:9a: + 41:74:f2:3c:14:0d:74:69:f5:50:83:cd:cd:2f:21:db:22:46: + 8a:d0:f7:51:1a:95:57:f2:05:8b:1a:19:ed:3b:45:e8:36:c2: + 6e:7e:fb:57:22:00:1f:06:53:a9:ae:93:c6:8f:71:2a:31:45: + 92:e7:8e:6d:e6:99:22:c0:83:fc:ef:dc:57:66:77:4f:a2:36: + 31:fb:a1:13:8d:e5:ca:a3:95:7d:01:0c:64:70:3b:53:42:68: + 80:c7:bb:9d:a8:00:35:69:98:0c:a8:67:d8:43:e5:aa:cf:95: + e0:51:95:a4:17:3f:42:9d:b8:04:ce:d3:79:79:c8:d3:8a:16: + 32:92:e0:d7:a2:ee:d7:37:4c:2f:ac:b8:7b:be:45:f6:f1:18: + 33:9c:7b:37:a6:24:d9:bc:40:ab:00:e9:c3:37:8b:ab:d8:b6: + f3:5e:81:4e:b0:14:6b:07:3e:1f:ec:c2:f6:44:22:95:bb:b3: + e6:6f:d6:f9:70:65:ba:0a:83:65:aa:0e:13:2f:83:13:23:53: + 8b:40:16:fa:ce:2f:fc:4d:04:f8:eb:d8:ac:c5:36:c2:15:57: + 48:38:ec:55:b3:b4:1e:ba:ad:d2:42:06:17:0d:73:c8:57:a6: + be:96:4d:a9:f2:c0:fb:7a:21:1c:f5:c9:70:a9:82:90:b5:f1: + 0c:d4:79:10:be:81:a6:e9:5c:61:9c:77:79:9a:a4:c3:37:26: + 57:37:c9:52:2c:fa:08:ff:d0:5f:c6:61:c0:f4:76:be:fc:de: + 4e:cf:ab:51:99:71:c7:df:7e:f4:d6:cf:06:56:19:13:53:0b: + 6d:74:59:48:19:9b:53:05:2d:9d:32:54:d3:e5:2c:53:8b:64: + 3e:d4:64:7b:e3:80:09:14:cc:fe:16:46:63:6b:71:69:f8:f9: + cb:27:f6:88:54:bc:45:b3:ce:02:c8:94:ee:40:5b:f9:42:02: + c2:ff:b0:d8:2c:eb:28:7f:5e:c9:26:01:99:a7 + +UPS Document Exchange by DST +============================ +MD5 Fingerprint: 78:A5:FB:10:4B:E4:63:2E:D2:6B:FB:F2:B6:C2:4B:8E +PEM Data: +-----BEGIN CERTIFICATE----- +MIID+DCCAuACEQDQHkCLAAACfAAAAAcAAAABMA0GCSqGSIb3DQEBBQUAMIG5MQsw +CQYDVQQGEwJ1czENMAsGA1UECBMEVXRhaDEXMBUGA1UEBxMOU2FsdCBMYWtlIENp +dHkxJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjEeMBwGA1UE +CxMVVW5pdGVkIFBhcmNlbCBTZXJ2aWNlMRkwFwYDVQQDExBEU1QgKFVQUykgUm9v +dENBMSEwHwYJKoZIhvcNAQkBFhJjYUBkaWdzaWd0cnVzdC5jb20wHhcNOTgxMjEw +MDAyNTQ2WhcNMDgxMjA3MDAyNTQ2WjCBuTELMAkGA1UEBhMCdXMxDTALBgNVBAgT +BFV0YWgxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MSQwIgYDVQQKExtEaWdpdGFs +IFNpZ25hdHVyZSBUcnVzdCBDby4xHjAcBgNVBAsTFVVuaXRlZCBQYXJjZWwgU2Vy +dmljZTEZMBcGA1UEAxMQRFNUIChVUFMpIFJvb3RDQTEhMB8GCSqGSIb3DQEJARYS +Y2FAZGlnc2lndHJ1c3QuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEA7xfsrynm2SsnwNt7JJ9m9ASjwq0KyrDNhCuqN/OAoWDvQo/lXXdfV0JU3Svb +YbJxXpN7b1/rJCvnpPLr8XOzC431Wdcy36yQjk4xuiVNtgym8eWvDOHlb1IDFcHf +vn5KpqYYRnA/76dNqNz1dNlhekA8oZQo6sKUiMs3FQUZPJViuhwt+yiM0ciekjxb +EVQ7eNlHO5stSuY+e2vf9PYFzyj2upg2AJ48N4UKnN63pIXFY/23YhRtFx7MioCF +QjIRsCHinXfJgBZBnuvlFIl/t8O8T8Gfh5uW7GP2+ZBWDpWjIwqMZNqbuxx3sExd +5sjo9X15LVckP8zjPSyYzxKfFwIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQC7OI4E +IiZYDiFEVsy9WXwpaMtcD8iGVD+BeKetj8xG9xxUuHktW3IFaugh0OwdHf6kNFG+ +7u3OzJwWaOJddXMIQzGRahArEMJLafjJrZio/bjv9qvwXyHvy4VrCe0vSGa1YHLA +6KDHmNsO9xtzjTQICnvFd2KqMCObsB6LgJhU3AWHs6liWfyLtxWarETszzUa9w8u +XZJLAch77qA37eQdgg2ZQUMXrdTVyuP5fReiAdAwD0C53LkEgmmDtvkP+gaS96j0 +1hcc8F5/xCnI5uHi/zZoIVGu/6m6hJKtinsz2JDSwXltMzM5dKwbOHGfLAeQ6h3g +04lfy+8UjSdUpb1G +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 1 (0x0) + Serial Number: + d0:1e:40:8b:00:00:02:7c:00:00:00:07:00:00:00:01 + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=us, ST=Utah, L=Salt Lake City, O=Digital Signature Trust Co., OU=United Parcel Service, CN=DST (UPS) RootCA/Email=ca@digsigtrust.com + Validity + Not Before: Dec 10 00:25:46 1998 GMT + Not After : Dec 7 00:25:46 2008 GMT + Subject: C=us, ST=Utah, L=Salt Lake City, O=Digital Signature Trust Co., OU=United Parcel Service, CN=DST (UPS) RootCA/Email=ca@digsigtrust.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:ef:17:ec:af:29:e6:d9:2b:27:c0:db:7b:24:9f: + 66:f4:04:a3:c2:ad:0a:ca:b0:cd:84:2b:aa:37:f3: + 80:a1:60:ef:42:8f:e5:5d:77:5f:57:42:54:dd:2b: + db:61:b2:71:5e:93:7b:6f:5f:eb:24:2b:e7:a4:f2: + eb:f1:73:b3:0b:8d:f5:59:d7:32:df:ac:90:8e:4e: + 31:ba:25:4d:b6:0c:a6:f1:e5:af:0c:e1:e5:6f:52: + 03:15:c1:df:be:7e:4a:a6:a6:18:46:70:3f:ef:a7: + 4d:a8:dc:f5:74:d9:61:7a:40:3c:a1:94:28:ea:c2: + 94:88:cb:37:15:05:19:3c:95:62:ba:1c:2d:fb:28: + 8c:d1:c8:9e:92:3c:5b:11:54:3b:78:d9:47:3b:9b: + 2d:4a:e6:3e:7b:6b:df:f4:f6:05:cf:28:f6:ba:98: + 36:00:9e:3c:37:85:0a:9c:de:b7:a4:85:c5:63:fd: + b7:62:14:6d:17:1e:cc:8a:80:85:42:32:11:b0:21: + e2:9d:77:c9:80:16:41:9e:eb:e5:14:89:7f:b7:c3: + bc:4f:c1:9f:87:9b:96:ec:63:f6:f9:90:56:0e:95: + a3:23:0a:8c:64:da:9b:bb:1c:77:b0:4c:5d:e6:c8: + e8:f5:7d:79:2d:57:24:3f:cc:e3:3d:2c:98:cf:12: + 9f:17 + Exponent: 65537 (0x10001) + Signature Algorithm: sha1WithRSAEncryption + bb:38:8e:04:22:26:58:0e:21:44:56:cc:bd:59:7c:29:68:cb: + 5c:0f:c8:86:54:3f:81:78:a7:ad:8f:cc:46:f7:1c:54:b8:79: + 2d:5b:72:05:6a:e8:21:d0:ec:1d:1d:fe:a4:34:51:be:ee:ed: + ce:cc:9c:16:68:e2:5d:75:73:08:43:31:91:6a:10:2b:10:c2: + 4b:69:f8:c9:ad:98:a8:fd:b8:ef:f6:ab:f0:5f:21:ef:cb:85: + 6b:09:ed:2f:48:66:b5:60:72:c0:e8:a0:c7:98:db:0e:f7:1b: + 73:8d:34:08:0a:7b:c5:77:62:aa:30:23:9b:b0:1e:8b:80:98: + 54:dc:05:87:b3:a9:62:59:fc:8b:b7:15:9a:ac:44:ec:cf:35: + 1a:f7:0f:2e:5d:92:4b:01:c8:7b:ee:a0:37:ed:e4:1d:82:0d: + 99:41:43:17:ad:d4:d5:ca:e3:f9:7d:17:a2:01:d0:30:0f:40: + b9:dc:b9:04:82:69:83:b6:f9:0f:fa:06:92:f7:a8:f4:d6:17: + 1c:f0:5e:7f:c4:29:c8:e6:e1:e2:ff:36:68:21:51:ae:ff:a9: + ba:84:92:ad:8a:7b:33:d8:90:d2:c1:79:6d:33:33:39:74:ac: + 1b:38:71:9f:2c:07:90:ea:1d:e0:d3:89:5f:cb:ef:14:8d:27: + 54:a5:bd:46 + +ValiCert Class 1 VA +=================== +MD5 Fingerprint: 65:58:AB:15:AD:57:6C:1E:A8:A7:B5:69:AC:BF:FF:EB +PEM Data: +-----BEGIN CERTIFICATE----- +MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0 +IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz +BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDEgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y +aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG +9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNTIyMjM0OFoXDTE5MDYy +NTIyMjM0OFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y +azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs +YXNzIDEgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw +Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl +cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDYWYJ6ibiWuqYvaG9Y +LqdUHAZu9OqNSLwxlBfw8068srg1knaw0KWlAdcAAxIiGQj4/xEjm84H9b9pGib+ +TunRf50sQB1ZaG6m+FiwnRqP0z/x3BkGgagO4DrdyFNFCQbmD3DD+kCmDuJWBQ8Y +TfwggtFzVXSNdnKgHZ0dwN0/cQIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFBoPUn0 +LBwGlN+VYH+Wexf+T3GtZMjdd9LvWVXoP+iOBSoh8gfStadS/pyxtuJbdxdA6nLW +I8sogTLDAHkY7FkXicnGah5xyf23dKUlRWnFSKsZ4UWKJWsZ7uW7EvV/96aNUcPw +nXS3qT6gpf+2SQMT2iLM7XGCK5nPOrf1LXLI +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 1 (0x0) + Serial Number: 1 (0x1) + Signature Algorithm: sha1WithRSAEncryption + Issuer: L=ValiCert Validation Network, O=ValiCert, Inc., OU=ValiCert Class 1 Policy Validation Authority, CN=http://www.valicert.com//Email=info@valicert.com + Validity + Not Before: Jun 25 22:23:48 1999 GMT + Not After : Jun 25 22:23:48 2019 GMT + Subject: L=ValiCert Validation Network, O=ValiCert, Inc., OU=ValiCert Class 1 Policy Validation Authority, CN=http://www.valicert.com//Email=info@valicert.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:d8:59:82:7a:89:b8:96:ba:a6:2f:68:6f:58:2e: + a7:54:1c:06:6e:f4:ea:8d:48:bc:31:94:17:f0:f3: + 4e:bc:b2:b8:35:92:76:b0:d0:a5:a5:01:d7:00:03: + 12:22:19:08:f8:ff:11:23:9b:ce:07:f5:bf:69:1a: + 26:fe:4e:e9:d1:7f:9d:2c:40:1d:59:68:6e:a6:f8: + 58:b0:9d:1a:8f:d3:3f:f1:dc:19:06:81:a8:0e:e0: + 3a:dd:c8:53:45:09:06:e6:0f:70:c3:fa:40:a6:0e: + e2:56:05:0f:18:4d:fc:20:82:d1:73:55:74:8d:76: + 72:a0:1d:9d:1d:c0:dd:3f:71 + Exponent: 65537 (0x10001) + Signature Algorithm: sha1WithRSAEncryption + 50:68:3d:49:f4:2c:1c:06:94:df:95:60:7f:96:7b:17:fe:4f: + 71:ad:64:c8:dd:77:d2:ef:59:55:e8:3f:e8:8e:05:2a:21:f2: + 07:d2:b5:a7:52:fe:9c:b1:b6:e2:5b:77:17:40:ea:72:d6:23: + cb:28:81:32:c3:00:79:18:ec:59:17:89:c9:c6:6a:1e:71:c9: + fd:b7:74:a5:25:45:69:c5:48:ab:19:e1:45:8a:25:6b:19:ee: + e5:bb:12:f5:7f:f7:a6:8d:51:c3:f0:9d:74:b7:a9:3e:a0:a5: + ff:b6:49:03:13:da:22:cc:ed:71:82:2b:99:cf:3a:b7:f5:2d: + 72:c8 + +ValiCert Class 2 VA +=================== +MD5 Fingerprint: A9:23:75:9B:BA:49:36:6E:31:C2:DB:F2:E7:66:BA:87 +PEM Data: +-----BEGIN CERTIFICATE----- +MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0 +IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz +BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y +aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG +9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMTk1NFoXDTE5MDYy +NjAwMTk1NFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y +azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs +YXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw +Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl +cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOOnHK5avIWZJV16vY +dA757tn2VUdZZUcOBVXc65g2PFxTXdMwzzjsvUGJ7SVCCSRrCl6zfN1SLUzm1NZ9 +WlmpZdRJEy0kTRxQb7XBhVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7RfZHM047QS +v4dk+NoS/zcnwbNDu+97bi5p9wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBADt/UG9v +UJSZSWI4OB9L+KXIPqeCgfYrx+jFzug6EILLGACOTb2oWH+heQC1u+mNr0HZDzTu +IYEZoDJJKPTEjlbVUjP9UNV+mWwD5MlM/Mtsq2azSiGM5bUMMj4QssxsodyamEwC +W/POuZ6lcg5Ktz885hZo+L7tdEy8W9ViH0Pd +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 1 (0x0) + Serial Number: 1 (0x1) + Signature Algorithm: sha1WithRSAEncryption + Issuer: L=ValiCert Validation Network, O=ValiCert, Inc., OU=ValiCert Class 2 Policy Validation Authority, CN=http://www.valicert.com//Email=info@valicert.com + Validity + Not Before: Jun 26 00:19:54 1999 GMT + Not After : Jun 26 00:19:54 2019 GMT + Subject: L=ValiCert Validation Network, O=ValiCert, Inc., OU=ValiCert Class 2 Policy Validation Authority, CN=http://www.valicert.com//Email=info@valicert.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:ce:3a:71:ca:e5:ab:c8:59:92:55:d7:ab:d8:74: + 0e:f9:ee:d9:f6:55:47:59:65:47:0e:05:55:dc:eb: + 98:36:3c:5c:53:5d:d3:30:cf:38:ec:bd:41:89:ed: + 25:42:09:24:6b:0a:5e:b3:7c:dd:52:2d:4c:e6:d4: + d6:7d:5a:59:a9:65:d4:49:13:2d:24:4d:1c:50:6f: + b5:c1:85:54:3b:fe:71:e4:d3:5c:42:f9:80:e0:91: + 1a:0a:5b:39:36:67:f3:3f:55:7c:1b:3f:b4:5f:64: + 73:34:e3:b4:12:bf:87:64:f8:da:12:ff:37:27:c1: + b3:43:bb:ef:7b:6e:2e:69:f7 + Exponent: 65537 (0x10001) + Signature Algorithm: sha1WithRSAEncryption + 3b:7f:50:6f:6f:50:94:99:49:62:38:38:1f:4b:f8:a5:c8:3e: + a7:82:81:f6:2b:c7:e8:c5:ce:e8:3a:10:82:cb:18:00:8e:4d: + bd:a8:58:7f:a1:79:00:b5:bb:e9:8d:af:41:d9:0f:34:ee:21: + 81:19:a0:32:49:28:f4:c4:8e:56:d5:52:33:fd:50:d5:7e:99: + 6c:03:e4:c9:4c:fc:cb:6c:ab:66:b3:4a:21:8c:e5:b5:0c:32: + 3e:10:b2:cc:6c:a1:dc:9a:98:4c:02:5b:f3:ce:b9:9e:a5:72: + 0e:4a:b7:3f:3c:e6:16:68:f8:be:ed:74:4c:bc:5b:d5:62:1f: + 43:dd + +ValiCert Class 3 VA +=================== +MD5 Fingerprint: A2:6F:53:B7:EE:40:DB:4A:68:E7:FA:18:D9:10:4B:72 +PEM Data: +-----BEGIN CERTIFICATE----- +MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0 +IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz +BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDMgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y +aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG +9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMjIzM1oXDTE5MDYy +NjAwMjIzM1owgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y +azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs +YXNzIDMgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw +Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl +cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDjmFGWHOjVsQaBalfD +cnWTq8+epvzzFlLWLU2fNUSoLgRNB0mKOCn1dzfnt6td3zZxFJmP3MKS8edgkpfs +2Ejcv8ECIMYkpChMMFp2bbFc893enhBxoYjHW5tBbcqwuI4V7q0zK89HBFx1cQqY +JJgpp0lZpd34t0NiYfPT4tBVPwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFa7AliE +Zwgs3x/be0kz9dNnnfS0ChCzycUs4pJqcXgn8nCDQtM+z6lU9PHYkhaM0QTLS6vJ +n0WuPIqpsHEzXcjFV9+vqDWzf4mH6eglkrh/hXqu1rweN1gqZ8mRzyqBPu3GOd/A +PhmcGcwTTYJBtYze4D1gCCAPRX5ron+jjBXu +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 1 (0x0) + Serial Number: 1 (0x1) + Signature Algorithm: sha1WithRSAEncryption + Issuer: L=ValiCert Validation Network, O=ValiCert, Inc., OU=ValiCert Class 3 Policy Validation Authority, CN=http://www.valicert.com//Email=info@valicert.com + Validity + Not Before: Jun 26 00:22:33 1999 GMT + Not After : Jun 26 00:22:33 2019 GMT + Subject: L=ValiCert Validation Network, O=ValiCert, Inc., OU=ValiCert Class 3 Policy Validation Authority, CN=http://www.valicert.com//Email=info@valicert.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:e3:98:51:96:1c:e8:d5:b1:06:81:6a:57:c3:72: + 75:93:ab:cf:9e:a6:fc:f3:16:52:d6:2d:4d:9f:35: + 44:a8:2e:04:4d:07:49:8a:38:29:f5:77:37:e7:b7: + ab:5d:df:36:71:14:99:8f:dc:c2:92:f1:e7:60:92: + 97:ec:d8:48:dc:bf:c1:02:20:c6:24:a4:28:4c:30: + 5a:76:6d:b1:5c:f3:dd:de:9e:10:71:a1:88:c7:5b: + 9b:41:6d:ca:b0:b8:8e:15:ee:ad:33:2b:cf:47:04: + 5c:75:71:0a:98:24:98:29:a7:49:59:a5:dd:f8:b7: + 43:62:61:f3:d3:e2:d0:55:3f + Exponent: 65537 (0x10001) + Signature Algorithm: sha1WithRSAEncryption + 56:bb:02:58:84:67:08:2c:df:1f:db:7b:49:33:f5:d3:67:9d: + f4:b4:0a:10:b3:c9:c5:2c:e2:92:6a:71:78:27:f2:70:83:42: + d3:3e:cf:a9:54:f4:f1:d8:92:16:8c:d1:04:cb:4b:ab:c9:9f: + 45:ae:3c:8a:a9:b0:71:33:5d:c8:c5:57:df:af:a8:35:b3:7f: + 89:87:e9:e8:25:92:b8:7f:85:7a:ae:d6:bc:1e:37:58:2a:67: + c9:91:cf:2a:81:3e:ed:c6:39:df:c0:3e:19:9c:19:cc:13:4d: + 82:41:b5:8c:de:e0:3d:60:08:20:0f:45:7e:6b:a2:7f:a3:8c: + 15:ee + +VeriSign Class 4 Primary CA +=========================== +MD5 Fingerprint: 1B:D1:AD:17:8B:7F:22:13:24:F5:26:E2:5D:4E:B9:10 +PEM Data: +-----BEGIN CERTIFICATE----- +MIICMTCCAZoCBQKmAAABMA0GCSqGSIb3DQEBAgUAMF8xCzAJBgNVBAYTAlVTMRcw +FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE3MDUGA1UECxMuQ2xhc3MgNCBQdWJsaWMg +UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05NjAxMjkwMDAwMDBa +Fw05OTEyMzEyMzU5NTlaMF8xCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2ln +biwgSW5jLjE3MDUGA1UECxMuQ2xhc3MgNCBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZp +Y2F0aW9uIEF1dGhvcml0eTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0LJ1 +9njQrlpQ9OlQqZ+M1++RlHDo0iSQdomF1t+s5gEXMoDwnZNHvJplnR+Xrr/phnVj +IIm9gFidBAydqMEk6QvlMXi9/C0MN2qeeIDpRnX57aP7E3vIwUzSo+/1PLBij0pd +O92VZ48TucE81qcmm+zDO3rZTbxtm+gVAePwR6kCAwEAATANBgkqhkiG9w0BAQIF +AAOBgQBT3dPwnCR+QKri/AAa19oM/DJhuBUNlvP6Vxt/M3yv6ZiaYch6s7f/sdyZ +g9ysEvxwyR84Qu1E9oAuW2szaayc01znX1oYx7EteQSWQZGZQbE8DbqEOcY7l/Am +yY7uvcxClf8exwI/VAx49byqYHwCaejcrOICdmHEPgPq0ook0Q== +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 1 (0x0) + Serial Number: + 02:a6:00:00:01 + Signature Algorithm: md2WithRSAEncryption + Issuer: C=US, O=VeriSign, Inc., OU=Class 4 Public Primary Certification Authority + Validity + Not Before: Jan 29 00:00:00 1996 GMT + Not After : Dec 31 23:59:59 1999 GMT + Subject: C=US, O=VeriSign, Inc., OU=Class 4 Public Primary Certification Authority + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:d0:b2:75:f6:78:d0:ae:5a:50:f4:e9:50:a9:9f: + 8c:d7:ef:91:94:70:e8:d2:24:90:76:89:85:d6:df: + ac:e6:01:17:32:80:f0:9d:93:47:bc:9a:65:9d:1f: + 97:ae:bf:e9:86:75:63:20:89:bd:80:58:9d:04:0c: + 9d:a8:c1:24:e9:0b:e5:31:78:bd:fc:2d:0c:37:6a: + 9e:78:80:e9:46:75:f9:ed:a3:fb:13:7b:c8:c1:4c: + d2:a3:ef:f5:3c:b0:62:8f:4a:5d:3b:dd:95:67:8f: + 13:b9:c1:3c:d6:a7:26:9b:ec:c3:3b:7a:d9:4d:bc: + 6d:9b:e8:15:01:e3:f0:47:a9 + Exponent: 65537 (0x10001) + Signature Algorithm: md2WithRSAEncryption + 53:dd:d3:f0:9c:24:7e:40:aa:e2:fc:00:1a:d7:da:0c:fc:32: + 61:b8:15:0d:96:f3:fa:57:1b:7f:33:7c:af:e9:98:9a:61:c8: + 7a:b3:b7:ff:b1:dc:99:83:dc:ac:12:fc:70:c9:1f:38:42:ed: + 44:f6:80:2e:5b:6b:33:69:ac:9c:d3:5c:e7:5f:5a:18:c7:b1: + 2d:79:04:96:41:91:99:41:b1:3c:0d:ba:84:39:c6:3b:97:f0: + 26:c9:8e:ee:bd:cc:42:95:ff:1e:c7:02:3f:54:0c:78:f5:bc: + aa:60:7c:02:69:e8:dc:ac:e2:02:76:61:c4:3e:03:ea:d2:8a: + 24:d1 + +Verisign Class 1 Public Primary Certification Authority +======================================================= +MD5 Fingerprint: 97:60:E8:57:5F:D3:50:47:E5:43:0C:94:36:8A:B0:62 +PEM Data: +-----BEGIN CERTIFICATE----- +MIICPTCCAaYCEQDNun9W8N/kvFT+IqyzcqpVMA0GCSqGSIb3DQEBAgUAMF8xCzAJ +BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE3MDUGA1UECxMuQ2xh +c3MgMSBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05 +NjAxMjkwMDAwMDBaFw0yODA4MDEyMzU5NTlaMF8xCzAJBgNVBAYTAlVTMRcwFQYD +VQQKEw5WZXJpU2lnbiwgSW5jLjE3MDUGA1UECxMuQ2xhc3MgMSBQdWJsaWMgUHJp +bWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCBnzANBgkqhkiG9w0BAQEFAAOB +jQAwgYkCgYEA5Rm/baNWYS2ZSHH2Z965jeu3noaACpEO+jglr0aIguVzqKCbJF0N +H8xlbgyw0FaEGIeaBpsQoXPftFg5a27B9hXVqKg/qhIGjTGsf7A01480Z4gJzRQR +4k5FVmkfeAKA2txHkSm7NsljXMXg1y2He6G3MrB7MLoqLzGq7qNn2tsCAwEAATAN +BgkqhkiG9w0BAQIFAAOBgQBMP7iLxmjf7kMzDl3ppssHhE16M/+SG/Q2rdiVIjZo +EWx8QszznC7EBz8UsA9P/5CSdvnivErpj82ggAr3xSnxgiJduLHdgSOjeyUVRjB5 +FvjqBUuUfx3CHMjjt/QQQDwTw18fU+hI5Ia0e6E1sHslurjTjqs/OJ0ANACY89Fx +lA== +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 1 (0x0) + Serial Number: + cd:ba:7f:56:f0:df:e4:bc:54:fe:22:ac:b3:72:aa:55 + Signature Algorithm: md2WithRSAEncryption + Issuer: C=US, O=VeriSign, Inc., OU=Class 1 Public Primary Certification Authority + Validity + Not Before: Jan 29 00:00:00 1996 GMT + Not After : Aug 1 23:59:59 2028 GMT + Subject: C=US, O=VeriSign, Inc., OU=Class 1 Public Primary Certification Authority + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:e5:19:bf:6d:a3:56:61:2d:99:48:71:f6:67:de: + b9:8d:eb:b7:9e:86:80:0a:91:0e:fa:38:25:af:46: + 88:82:e5:73:a8:a0:9b:24:5d:0d:1f:cc:65:6e:0c: + b0:d0:56:84:18:87:9a:06:9b:10:a1:73:df:b4:58: + 39:6b:6e:c1:f6:15:d5:a8:a8:3f:aa:12:06:8d:31: + ac:7f:b0:34:d7:8f:34:67:88:09:cd:14:11:e2:4e: + 45:56:69:1f:78:02:80:da:dc:47:91:29:bb:36:c9: + 63:5c:c5:e0:d7:2d:87:7b:a1:b7:32:b0:7b:30:ba: + 2a:2f:31:aa:ee:a3:67:da:db + Exponent: 65537 (0x10001) + Signature Algorithm: md2WithRSAEncryption + 4c:3f:b8:8b:c6:68:df:ee:43:33:0e:5d:e9:a6:cb:07:84:4d: + 7a:33:ff:92:1b:f4:36:ad:d8:95:22:36:68:11:6c:7c:42:cc: + f3:9c:2e:c4:07:3f:14:b0:0f:4f:ff:90:92:76:f9:e2:bc:4a: + e9:8f:cd:a0:80:0a:f7:c5:29:f1:82:22:5d:b8:b1:dd:81:23: + a3:7b:25:15:46:30:79:16:f8:ea:05:4b:94:7f:1d:c2:1c:c8: + e3:b7:f4:10:40:3c:13:c3:5f:1f:53:e8:48:e4:86:b4:7b:a1: + 35:b0:7b:25:ba:b8:d3:8e:ab:3f:38:9d:00:34:00:98:f3:d1: + 71:94 + +Verisign Class 1 Public Primary Certification Authority - G2 +============================================================ +MD5 Fingerprint: F2:7D:E9:54:E4:A3:22:0D:76:9F:E7:0B:BB:B3:24:2B +PEM Data: +-----BEGIN CERTIFICATE----- +MIIDAjCCAmsCEDnKVIn+UCIy/jLZ2/sbhBkwDQYJKoZIhvcNAQEFBQAwgcExCzAJ +BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh +c3MgMSBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy +MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp +emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X +DTk4MDUxODAwMDAwMFoXDTE4MDUxODIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw +FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMSBQdWJsaWMg +UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo +YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5 +MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB +AQUAA4GNADCBiQKBgQCq0Lq+Fi24g9TK0g+8djHKlNgdk4xWArzZbxpvUjZudVYK +VdPfQ4chEWWKfo+9Id5rMj8bhDSVBZ1BNeuS65bdqlk/AVNtmU/t5eIqWpDBucSm +Fc/IReumXY6cPvBkJHalzasab7bYe1FhbqZ/h8jit+U03EGI6glAvnOSPWvndQID +AQABMA0GCSqGSIb3DQEBBQUAA4GBAIv3GhDOdlwHq4OZ3BeAbzQ5XZg+a3Is4cei +e0ApuXiIukzFo2penm574/ICQQxmvq37rqIUzpLzojSLtLK2JPLl1eDI5WJthHvL +vrsDi3xXyvA3qZCviu4Dvh0onNkmdqDNxJ1O8K4HFtW+r1cIatCgQkJCHvQgzKV4 +gpUmOIpH +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 1 (0x0) + Serial Number: + 39:ca:54:89:fe:50:22:32:fe:32:d9:db:fb:1b:84:19 + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=VeriSign, Inc., OU=Class 1 Public Primary Certification Authority - G2, OU=(c) 1998 VeriSign, Inc. - For authorized use only, OU=VeriSign Trust Network + Validity + Not Before: May 18 00:00:00 1998 GMT + Not After : May 18 23:59:59 2018 GMT + Subject: C=US, O=VeriSign, Inc., OU=Class 1 Public Primary Certification Authority - G2, OU=(c) 1998 VeriSign, Inc. - For authorized use only, OU=VeriSign Trust Network + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:aa:d0:ba:be:16:2d:b8:83:d4:ca:d2:0f:bc:76: + 31:ca:94:d8:1d:93:8c:56:02:bc:d9:6f:1a:6f:52: + 36:6e:75:56:0a:55:d3:df:43:87:21:11:65:8a:7e: + 8f:bd:21:de:6b:32:3f:1b:84:34:95:05:9d:41:35: + eb:92:eb:96:dd:aa:59:3f:01:53:6d:99:4f:ed:e5: + e2:2a:5a:90:c1:b9:c4:a6:15:cf:c8:45:eb:a6:5d: + 8e:9c:3e:f0:64:24:76:a5:cd:ab:1a:6f:b6:d8:7b: + 51:61:6e:a6:7f:87:c8:e2:b7:e5:34:dc:41:88:ea: + 09:40:be:73:92:3d:6b:e7:75 + Exponent: 65537 (0x10001) + Signature Algorithm: sha1WithRSAEncryption + 8b:f7:1a:10:ce:76:5c:07:ab:83:99:dc:17:80:6f:34:39:5d: + 98:3e:6b:72:2c:e1:c7:a2:7b:40:29:b9:78:88:ba:4c:c5:a3: + 6a:5e:9e:6e:7b:e3:f2:02:41:0c:66:be:ad:fb:ae:a2:14:ce: + 92:f3:a2:34:8b:b4:b2:b6:24:f2:e5:d5:e0:c8:e5:62:6d:84: + 7b:cb:be:bb:03:8b:7c:57:ca:f0:37:a9:90:af:8a:ee:03:be: + 1d:28:9c:d9:26:76:a0:cd:c4:9d:4e:f0:ae:07:16:d5:be:af: + 57:08:6a:d0:a0:42:42:42:1e:f4:20:cc:a5:78:82:95:26:38: + 8a:47 + +Verisign Class 1 Public Primary Certification Authority - G3 +============================================================ +MD5 Fingerprint: B1:47:BC:18:57:D1:18:A0:78:2D:EC:71:E8:2A:95:73 +PEM Data: +-----BEGIN CERTIFICATE----- +MIIEGjCCAwICEQCLW3VWhFSFCwDPrzhIzrGkMA0GCSqGSIb3DQEBBQUAMIHKMQsw +CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl +cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu +LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT +aWduIENsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp +dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD +VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT +aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ +bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu +IENsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg +LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN2E1Lm0+afY8wR4 +nN493GwTFtl63SRRZsDHJlkNrAYIwpTRMx/wgzUfbhvI3qpuFU5UJ+/EbRrsC+MO +8ESlV8dAWB6jRx9x7GD2bZTIGDnt/kIYVt/kTEkQeE4BdjVjEjbdZrwBBDajVWjV +ojYJrKshJlQGrT/KFOCsyq0GHZXi+J3x4GD/wn91K0zM2v6HmSHquv4+VNfSWXjb +PG7PoBMAGrgnoeS+Z5bKoMWznN3JdZ7rMJpfo83ZrngZPyPpXNspva1VyBtUjGP2 +6KbqxzcSXKMpHgLZ2x87tNcPVkeBFQRKr4Mn0cVYiMHd9qqnoxjaaKptEVHhv2Vr +n5Z20T0CAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAq2aN17O6x5q25lXQBfGfMY1a +qtmqRiYPce2lrVNWYgFHKkTp/j90CxObufRNG7LRX7K20ohcs5/Ny9Sn2WCVhDr4 +wTcdYcrnsMXlkdpUpqwxga6X3s0IrLjAl4B/bnKk52kTlWUfxJM8/XmPBNQ+T+r3 +ns7NZ3xPZQL/kYVUc8f/NveGLezQXk//EZ9yBta4GvFMDSZl4kSAHsef493oCtrs +pSCAaWihT37ha88HQfqDjrw43bAuEbFrskLMmrz5SCJ5ShkPshw+IHTZasO+8ih4 +E1Z5T21Q6huwtVexN2ZYI/PcD98Kh8TvhgXVOBRgmaNL3gaWcSzy27YfpO8/7g== +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 1 (0x0) + Serial Number: + 8b:5b:75:56:84:54:85:0b:00:cf:af:38:48:ce:b1:a4 + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 1999 VeriSign, Inc. - For authorized use only, CN=VeriSign Class 1 Public Primary Certification Authority - G3 + Validity + Not Before: Oct 1 00:00:00 1999 GMT + Not After : Jul 16 23:59:59 2036 GMT + Subject: C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 1999 VeriSign, Inc. - For authorized use only, CN=VeriSign Class 1 Public Primary Certification Authority - G3 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:dd:84:d4:b9:b4:f9:a7:d8:f3:04:78:9c:de:3d: + dc:6c:13:16:d9:7a:dd:24:51:66:c0:c7:26:59:0d: + ac:06:08:c2:94:d1:33:1f:f0:83:35:1f:6e:1b:c8: + de:aa:6e:15:4e:54:27:ef:c4:6d:1a:ec:0b:e3:0e: + f0:44:a5:57:c7:40:58:1e:a3:47:1f:71:ec:60:f6: + 6d:94:c8:18:39:ed:fe:42:18:56:df:e4:4c:49:10: + 78:4e:01:76:35:63:12:36:dd:66:bc:01:04:36:a3: + 55:68:d5:a2:36:09:ac:ab:21:26:54:06:ad:3f:ca: + 14:e0:ac:ca:ad:06:1d:95:e2:f8:9d:f1:e0:60:ff: + c2:7f:75:2b:4c:cc:da:fe:87:99:21:ea:ba:fe:3e: + 54:d7:d2:59:78:db:3c:6e:cf:a0:13:00:1a:b8:27: + a1:e4:be:67:96:ca:a0:c5:b3:9c:dd:c9:75:9e:eb: + 30:9a:5f:a3:cd:d9:ae:78:19:3f:23:e9:5c:db:29: + bd:ad:55:c8:1b:54:8c:63:f6:e8:a6:ea:c7:37:12: + 5c:a3:29:1e:02:d9:db:1f:3b:b4:d7:0f:56:47:81: + 15:04:4a:af:83:27:d1:c5:58:88:c1:dd:f6:aa:a7: + a3:18:da:68:aa:6d:11:51:e1:bf:65:6b:9f:96:76: + d1:3d + Exponent: 65537 (0x10001) + Signature Algorithm: sha1WithRSAEncryption + ab:66:8d:d7:b3:ba:c7:9a:b6:e6:55:d0:05:f1:9f:31:8d:5a: + aa:d9:aa:46:26:0f:71:ed:a5:ad:53:56:62:01:47:2a:44:e9: + fe:3f:74:0b:13:9b:b9:f4:4d:1b:b2:d1:5f:b2:b6:d2:88:5c: + b3:9f:cd:cb:d4:a7:d9:60:95:84:3a:f8:c1:37:1d:61:ca:e7: + b0:c5:e5:91:da:54:a6:ac:31:81:ae:97:de:cd:08:ac:b8:c0: + 97:80:7f:6e:72:a4:e7:69:13:95:65:1f:c4:93:3c:fd:79:8f: + 04:d4:3e:4f:ea:f7:9e:ce:cd:67:7c:4f:65:02:ff:91:85:54: + 73:c7:ff:36:f7:86:2d:ec:d0:5e:4f:ff:11:9f:72:06:d6:b8: + 1a:f1:4c:0d:26:65:e2:44:80:1e:c7:9f:e3:dd:e8:0a:da:ec: + a5:20:80:69:68:a1:4f:7e:e1:6b:cf:07:41:fa:83:8e:bc:38: + dd:b0:2e:11:b1:6b:b2:42:cc:9a:bc:f9:48:22:79:4a:19:0f: + b2:1c:3e:20:74:d9:6a:c3:be:f2:28:78:13:56:79:4f:6d:50: + ea:1b:b0:b5:57:b1:37:66:58:23:f3:dc:0f:df:0a:87:c4:ef: + 86:05:d5:38:14:60:99:a3:4b:de:06:96:71:2c:f2:db:b6:1f: + a4:ef:3f:ee + +Verisign Class 2 Public Primary Certification Authority +======================================================= +MD5 Fingerprint: B3:9C:25:B1:C3:2E:32:53:80:15:30:9D:4D:02:77:3E +PEM Data: +-----BEGIN CERTIFICATE----- +MIICPDCCAaUCEC0b/EoXjaOR6+f/9YtFvgswDQYJKoZIhvcNAQECBQAwXzELMAkG +A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz +cyAyIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2 +MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV +BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAyIFB1YmxpYyBQcmlt +YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQC2WoujDWojg4BrzzmH9CETMwZMJaLtVRKXxaeAufqDwSCg+i8VDXyh +YGt+eSz6Bg86rvYbb7HS/y8oUl+DfUvEerf4Zh+AVPy3wo5ZShRXRtGak75BkQO7 +FYCTXOvnzAhsPz6zSvz/S2wj1VCCJkQZjiPDceoZJEcEnnW/yKYAHwIDAQABMA0G +CSqGSIb3DQEBAgUAA4GBAIobK/o5wXTXXtgZZKJYSi034DNHD6zt96rbHuSLBlxg +J8pFUs4W7z8GZOeUaHxgMxURaa+dYo2jA1Rrpr7l7gUYYAS/QoD90KioHgE796Nc +r6Pc5iaAIzy4RHT3Cq5Ji2F4zCS/iIqnDupzGUH9TQPwiNHleI2lKk/2lw0Xd8rY +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 1 (0x0) + Serial Number: + 2d:1b:fc:4a:17:8d:a3:91:eb:e7:ff:f5:8b:45:be:0b + Signature Algorithm: md2WithRSAEncryption + Issuer: C=US, O=VeriSign, Inc., OU=Class 2 Public Primary Certification Authority + Validity + Not Before: Jan 29 00:00:00 1996 GMT + Not After : Aug 1 23:59:59 2028 GMT + Subject: C=US, O=VeriSign, Inc., OU=Class 2 Public Primary Certification Authority + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:b6:5a:8b:a3:0d:6a:23:83:80:6b:cf:39:87:f4: + 21:13:33:06:4c:25:a2:ed:55:12:97:c5:a7:80:b9: + fa:83:c1:20:a0:fa:2f:15:0d:7c:a1:60:6b:7e:79: + 2c:fa:06:0f:3a:ae:f6:1b:6f:b1:d2:ff:2f:28:52: + 5f:83:7d:4b:c4:7a:b7:f8:66:1f:80:54:fc:b7:c2: + 8e:59:4a:14:57:46:d1:9a:93:be:41:91:03:bb:15: + 80:93:5c:eb:e7:cc:08:6c:3f:3e:b3:4a:fc:ff:4b: + 6c:23:d5:50:82:26:44:19:8e:23:c3:71:ea:19:24: + 47:04:9e:75:bf:c8:a6:00:1f + Exponent: 65537 (0x10001) + Signature Algorithm: md2WithRSAEncryption + 8a:1b:2b:fa:39:c1:74:d7:5e:d8:19:64:a2:58:4a:2d:37:e0: + 33:47:0f:ac:ed:f7:aa:db:1e:e4:8b:06:5c:60:27:ca:45:52: + ce:16:ef:3f:06:64:e7:94:68:7c:60:33:15:11:69:af:9d:62: + 8d:a3:03:54:6b:a6:be:e5:ee:05:18:60:04:bf:42:80:fd:d0: + a8:a8:1e:01:3b:f7:a3:5c:af:a3:dc:e6:26:80:23:3c:b8:44: + 74:f7:0a:ae:49:8b:61:78:cc:24:bf:88:8a:a7:0e:ea:73:19: + 41:fd:4d:03:f0:88:d1:e5:78:8d:a5:2a:4f:f6:97:0d:17:77: + ca:d8 + +Verisign Class 2 Public Primary Certification Authority - G2 +============================================================ +MD5 Fingerprint: 2D:BB:E5:25:D3:D1:65:82:3A:B7:0E:FA:E6:EB:E2:E1 +PEM Data: +-----BEGIN CERTIFICATE----- +MIIDAzCCAmwCEQC5L2DMiJ+hekYJuFtwbIqvMA0GCSqGSIb3DQEBBQUAMIHBMQsw +CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xPDA6BgNVBAsTM0Ns +YXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBH +MjE6MDgGA1UECxMxKGMpIDE5OTggVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9y +aXplZCB1c2Ugb25seTEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazAe +Fw05ODA1MTgwMDAwMDBaFw0yODA4MDEyMzU5NTlaMIHBMQswCQYDVQQGEwJVUzEX +MBUGA1UEChMOVmVyaVNpZ24sIEluYy4xPDA6BgNVBAsTM0NsYXNzIDIgUHVibGlj +IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjE6MDgGA1UECxMx +KGMpIDE5OTggVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25s +eTEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazCBnzANBgkqhkiG9w0B +AQEFAAOBjQAwgYkCgYEAp4gBIXQs5xoD8JjhlzwPIQjxnNuX6Zr8wgQGE75fUsjM +HiwSViy4AWkszJkfrbCWrnkE8hM5wXuYuggs6MKEEyyqaekJ9MepAqRCwiNPStjw +DqL7MWzJ5m+ZJwf15vRMeJ5t60aG+rmGyVTyssSv1EYcWskVMP8NbPUtDm3Of3cC +AwEAATANBgkqhkiG9w0BAQUFAAOBgQByLvl/0fFx+8Se9sVeUYpAmLho+Jscg9ji +nb3/7aHmZuovCfTK1+qlK5X2JGCGTUQug6XELaDTrnhpb3LabK4I8GOSN+a7xDAX +rXfMSTWqz9iP0b63GJZHc2pUIjRkLbYWm1lbtFFZOrMLFPQS32eg9K0yZF6xRnIn +jBJ7xUS0rg== +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 1 (0x0) + Serial Number: + b9:2f:60:cc:88:9f:a1:7a:46:09:b8:5b:70:6c:8a:af + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=VeriSign, Inc., OU=Class 2 Public Primary Certification Authority - G2, OU=(c) 1998 VeriSign, Inc. - For authorized use only, OU=VeriSign Trust Network + Validity + Not Before: May 18 00:00:00 1998 GMT + Not After : Aug 1 23:59:59 2028 GMT + Subject: C=US, O=VeriSign, Inc., OU=Class 2 Public Primary Certification Authority - G2, OU=(c) 1998 VeriSign, Inc. - For authorized use only, OU=VeriSign Trust Network + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:a7:88:01:21:74:2c:e7:1a:03:f0:98:e1:97:3c: + 0f:21:08:f1:9c:db:97:e9:9a:fc:c2:04:06:13:be: + 5f:52:c8:cc:1e:2c:12:56:2c:b8:01:69:2c:cc:99: + 1f:ad:b0:96:ae:79:04:f2:13:39:c1:7b:98:ba:08: + 2c:e8:c2:84:13:2c:aa:69:e9:09:f4:c7:a9:02:a4: + 42:c2:23:4f:4a:d8:f0:0e:a2:fb:31:6c:c9:e6:6f: + 99:27:07:f5:e6:f4:4c:78:9e:6d:eb:46:86:fa:b9: + 86:c9:54:f2:b2:c4:af:d4:46:1c:5a:c9:15:30:ff: + 0d:6c:f5:2d:0e:6d:ce:7f:77 + Exponent: 65537 (0x10001) + Signature Algorithm: sha1WithRSAEncryption + 72:2e:f9:7f:d1:f1:71:fb:c4:9e:f6:c5:5e:51:8a:40:98:b8: + 68:f8:9b:1c:83:d8:e2:9d:bd:ff:ed:a1:e6:66:ea:2f:09:f4: + ca:d7:ea:a5:2b:95:f6:24:60:86:4d:44:2e:83:a5:c4:2d:a0: + d3:ae:78:69:6f:72:da:6c:ae:08:f0:63:92:37:e6:bb:c4:30: + 17:ad:77:cc:49:35:aa:cf:d8:8f:d1:be:b7:18:96:47:73:6a: + 54:22:34:64:2d:b6:16:9b:59:5b:b4:51:59:3a:b3:0b:14:f4: + 12:df:67:a0:f4:ad:32:64:5e:b1:46:72:27:8c:12:7b:c5:44: + b4:ae + +Verisign Class 2 Public Primary Certification Authority - G3 +============================================================ +MD5 Fingerprint: F8:BE:C4:63:22:C9:A8:46:74:8B:B8:1D:1E:4A:2B:F6 +PEM Data: +-----BEGIN CERTIFICATE----- +MIIEGTCCAwECEGFwy0mMX5hFKeewptlQW3owDQYJKoZIhvcNAQEFBQAwgcoxCzAJ +BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVy +aVNpZ24gVHJ1c3QgTmV0d29yazE6MDgGA1UECxMxKGMpIDE5OTkgVmVyaVNpZ24s +IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTFFMEMGA1UEAxM8VmVyaVNp +Z24gQ2xhc3MgMiBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0 +eSAtIEczMB4XDTk5MTAwMTAwMDAwMFoXDTM2MDcxNjIzNTk1OVowgcoxCzAJBgNV +BAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVyaVNp +Z24gVHJ1c3QgTmV0d29yazE6MDgGA1UECxMxKGMpIDE5OTkgVmVyaVNpZ24sIElu +Yy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTFFMEMGA1UEAxM8VmVyaVNpZ24g +Q2xhc3MgMiBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAt +IEczMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArwoNwtUs22e5LeWU +J92lvuCwTY+zYVY81nzD9M0+hsuiiOLh2KRpxbXiv8GmR1BeRjmL1Za6tW8UvxDO +JxOeBUebMXoT2B/Z0wI3i60sR/COgQanDTAM6/c8DyAd3HJG7qUCyFvDyVZpTMUY +wZF7C9UTAJu878NIPkZgIIUq1ZC2zYugzDLdt/1AVbJQHFauzI13TccgTacxdu9o +koqQHgiBVrKtaaNS0MscxCM9H5n+TOgWY47GCI72MfbS+uV23bUckqNJzc0BzWjN +qWm6o+sdDZykIKbBoMXRRkwXbdKsZj+WjOCE1Db/IlnF+RFgqF8EffIa9iVCYQ/E +Srg+iQIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQA0JhU8wI1NQ0kdvekhktdmnLfe +xbjQ5F1fdiLAJvmEOjr5jLX77GDx6M4EsMjdpwOPMPOY36TmpDHf0xwLRtxyID+u +7gU8pDM/CzmscHhzS5kr3zDCVLCoO1Wh/hYozUK9dG6A2ydEp85EXdQbkJgNHkKU +sQAsBNB0owIFImNjzYO1+8FtYmtpdf1dcEG59b98377BMnMiIYtYgXsVkXq642RI +sH/7NiXaldDxJBQX3RiAa0YjOVT1jmIJBB2UkKab5iXiQkWquJCtvgiPqQtCGJTP +cjnhsUPgKM+351psE2tJs//jGHyJizNdrDPXp/naOlXJWBD5qu9ats9LS98q +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 1 (0x0) + Serial Number: + 61:70:cb:49:8c:5f:98:45:29:e7:b0:a6:d9:50:5b:7a + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 1999 VeriSign, Inc. - For authorized use only, CN=VeriSign Class 2 Public Primary Certification Authority - G3 + Validity + Not Before: Oct 1 00:00:00 1999 GMT + Not After : Jul 16 23:59:59 2036 GMT + Subject: C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 1999 VeriSign, Inc. - For authorized use only, CN=VeriSign Class 2 Public Primary Certification Authority - G3 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:af:0a:0d:c2:d5:2c:db:67:b9:2d:e5:94:27:dd: + a5:be:e0:b0:4d:8f:b3:61:56:3c:d6:7c:c3:f4:cd: + 3e:86:cb:a2:88:e2:e1:d8:a4:69:c5:b5:e2:bf:c1: + a6:47:50:5e:46:39:8b:d5:96:ba:b5:6f:14:bf:10: + ce:27:13:9e:05:47:9b:31:7a:13:d8:1f:d9:d3:02: + 37:8b:ad:2c:47:f0:8e:81:06:a7:0d:30:0c:eb:f7: + 3c:0f:20:1d:dc:72:46:ee:a5:02:c8:5b:c3:c9:56: + 69:4c:c5:18:c1:91:7b:0b:d5:13:00:9b:bc:ef:c3: + 48:3e:46:60:20:85:2a:d5:90:b6:cd:8b:a0:cc:32: + dd:b7:fd:40:55:b2:50:1c:56:ae:cc:8d:77:4d:c7: + 20:4d:a7:31:76:ef:68:92:8a:90:1e:08:81:56:b2: + ad:69:a3:52:d0:cb:1c:c4:23:3d:1f:99:fe:4c:e8: + 16:63:8e:c6:08:8e:f6:31:f6:d2:fa:e5:76:dd:b5: + 1c:92:a3:49:cd:cd:01:cd:68:cd:a9:69:ba:a3:eb: + 1d:0d:9c:a4:20:a6:c1:a0:c5:d1:46:4c:17:6d:d2: + ac:66:3f:96:8c:e0:84:d4:36:ff:22:59:c5:f9:11: + 60:a8:5f:04:7d:f2:1a:f6:25:42:61:0f:c4:4a:b8: + 3e:89 + Exponent: 65537 (0x10001) + Signature Algorithm: sha1WithRSAEncryption + 34:26:15:3c:c0:8d:4d:43:49:1d:bd:e9:21:92:d7:66:9c:b7: + de:c5:b8:d0:e4:5d:5f:76:22:c0:26:f9:84:3a:3a:f9:8c:b5: + fb:ec:60:f1:e8:ce:04:b0:c8:dd:a7:03:8f:30:f3:98:df:a4: + e6:a4:31:df:d3:1c:0b:46:dc:72:20:3f:ae:ee:05:3c:a4:33: + 3f:0b:39:ac:70:78:73:4b:99:2b:df:30:c2:54:b0:a8:3b:55: + a1:fe:16:28:cd:42:bd:74:6e:80:db:27:44:a7:ce:44:5d:d4: + 1b:90:98:0d:1e:42:94:b1:00:2c:04:d0:74:a3:02:05:22:63: + 63:cd:83:b5:fb:c1:6d:62:6b:69:75:fd:5d:70:41:b9:f5:bf: + 7c:df:be:c1:32:73:22:21:8b:58:81:7b:15:91:7a:ba:e3:64: + 48:b0:7f:fb:36:25:da:95:d0:f1:24:14:17:dd:18:80:6b:46: + 23:39:54:f5:8e:62:09:04:1d:94:90:a6:9b:e6:25:e2:42:45: + aa:b8:90:ad:be:08:8f:a9:0b:42:18:94:cf:72:39:e1:b1:43: + e0:28:cf:b7:e7:5a:6c:13:6b:49:b3:ff:e3:18:7c:89:8b:33: + 5d:ac:33:d7:a7:f9:da:3a:55:c9:58:10:f9:aa:ef:5a:b6:cf: + 4b:4b:df:2a + +Verisign Class 3 Public Primary Certification Authority +======================================================= +MD5 Fingerprint: 10:FC:63:5D:F6:26:3E:0D:F3:25:BE:5F:79:CD:67:67 +PEM Data: +-----BEGIN CERTIFICATE----- +MIICPDCCAaUCEHC65B0Q2Sk0tjjKewPMur8wDQYJKoZIhvcNAQECBQAwXzELMAkG +A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz +cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2 +MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV +BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmlt +YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhE +BarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/is +I19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0G +CSqGSIb3DQEBAgUAA4GBALtMEivPLCYATxQT3ab7/AoRhIzzKBxnki98tsX63/Do +lbwdj2wsqFHMc9ikwFPwTtYmwHYBV4GSXiHx0bH/59AhWM1pF+NEHJwZRDmJXNyc +AA9WjQKZ7aKQRUzkuxCkPfAyAw7xzvjoyVGM5mKf5p/AfbdynMk2OmufTqj/ZA1k +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 1 (0x0) + Serial Number: + 70:ba:e4:1d:10:d9:29:34:b6:38:ca:7b:03:cc:ba:bf + Signature Algorithm: md2WithRSAEncryption + Issuer: C=US, O=VeriSign, Inc., OU=Class 3 Public Primary Certification Authority + Validity + Not Before: Jan 29 00:00:00 1996 GMT + Not After : Aug 1 23:59:59 2028 GMT + Subject: C=US, O=VeriSign, Inc., OU=Class 3 Public Primary Certification Authority + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:c9:5c:59:9e:f2:1b:8a:01:14:b4:10:df:04:40: + db:e3:57:af:6a:45:40:8f:84:0c:0b:d1:33:d9:d9: + 11:cf:ee:02:58:1f:25:f7:2a:a8:44:05:aa:ec:03: + 1f:78:7f:9e:93:b9:9a:00:aa:23:7d:d6:ac:85:a2: + 63:45:c7:72:27:cc:f4:4c:c6:75:71:d2:39:ef:4f: + 42:f0:75:df:0a:90:c6:8e:20:6f:98:0f:f8:ac:23: + 5f:70:29:36:a4:c9:86:e7:b1:9a:20:cb:53:a5:85: + e7:3d:be:7d:9a:fe:24:45:33:dc:76:15:ed:0f:a2: + 71:64:4c:65:2e:81:68:45:a7 + Exponent: 65537 (0x10001) + Signature Algorithm: md2WithRSAEncryption + bb:4c:12:2b:cf:2c:26:00:4f:14:13:dd:a6:fb:fc:0a:11:84: + 8c:f3:28:1c:67:92:2f:7c:b6:c5:fa:df:f0:e8:95:bc:1d:8f: + 6c:2c:a8:51:cc:73:d8:a4:c0:53:f0:4e:d6:26:c0:76:01:57: + 81:92:5e:21:f1:d1:b1:ff:e7:d0:21:58:cd:69:17:e3:44:1c: + 9c:19:44:39:89:5c:dc:9c:00:0f:56:8d:02:99:ed:a2:90:45: + 4c:e4:bb:10:a4:3d:f0:32:03:0e:f1:ce:f8:e8:c9:51:8c:e6: + 62:9f:e6:9f:c0:7d:b7:72:9c:c9:36:3a:6b:9f:4e:a8:ff:64: + 0d:64 + +Verisign Class 3 Public Primary Certification Authority - G2 +============================================================ +MD5 Fingerprint: A2:33:9B:4C:74:78:73:D4:6C:E7:C1:F3:8D:CB:5C:E9 +PEM Data: +-----BEGIN CERTIFICATE----- +MIIDAjCCAmsCEH3Z/gfPqB63EHln+6eJNMYwDQYJKoZIhvcNAQEFBQAwgcExCzAJ +BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh +c3MgMyBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy +MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp +emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X +DTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw +FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMyBQdWJsaWMg +UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo +YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5 +MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB +AQUAA4GNADCBiQKBgQDMXtERXVxp0KvTuWpMmR9ZmDCOFoUgRm1HP9SFIIThbbP4 +pO0M8RcPO/mn+SXXwc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71lSk8UOg0 +13gfqLptQ5GVj0VXXn7F+8qkBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZwID +AQABMA0GCSqGSIb3DQEBBQUAA4GBAFFNzb5cy5gZnBWyATl4Lk0PZ3BwmcYQWpSk +U01UbSuvDV1Ai2TT1+7eVmGSX6bEHRBhNtMsJzzoKQm5EWR0zLVznxxIqbxhAe7i +F6YM40AIOw7n60RzKprxaZLvcRTDOaxxp5EJb+RxBrO6WVcmeQD2+A2iMzAo1KpY +oJ2daZH9 +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 1 (0x0) + Serial Number: + 7d:d9:fe:07:cf:a8:1e:b7:10:79:67:fb:a7:89:34:c6 + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=VeriSign, Inc., OU=Class 3 Public Primary Certification Authority - G2, OU=(c) 1998 VeriSign, Inc. - For authorized use only, OU=VeriSign Trust Network + Validity + Not Before: May 18 00:00:00 1998 GMT + Not After : Aug 1 23:59:59 2028 GMT + Subject: C=US, O=VeriSign, Inc., OU=Class 3 Public Primary Certification Authority - G2, OU=(c) 1998 VeriSign, Inc. - For authorized use only, OU=VeriSign Trust Network + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:cc:5e:d1:11:5d:5c:69:d0:ab:d3:b9:6a:4c:99: + 1f:59:98:30:8e:16:85:20:46:6d:47:3f:d4:85:20: + 84:e1:6d:b3:f8:a4:ed:0c:f1:17:0f:3b:f9:a7:f9: + 25:d7:c1:cf:84:63:f2:7c:63:cf:a2:47:f2:c6:5b: + 33:8e:64:40:04:68:c1:80:b9:64:1c:45:77:c7:d8: + 6e:f5:95:29:3c:50:e8:34:d7:78:1f:a8:ba:6d:43: + 91:95:8f:45:57:5e:7e:c5:fb:ca:a4:04:eb:ea:97: + 37:54:30:6f:bb:01:47:32:33:cd:dc:57:9b:64:69: + 61:f8:9b:1d:1c:89:4f:5c:67 + Exponent: 65537 (0x10001) + Signature Algorithm: sha1WithRSAEncryption + 51:4d:cd:be:5c:cb:98:19:9c:15:b2:01:39:78:2e:4d:0f:67: + 70:70:99:c6:10:5a:94:a4:53:4d:54:6d:2b:af:0d:5d:40:8b: + 64:d3:d7:ee:de:56:61:92:5f:a6:c4:1d:10:61:36:d3:2c:27: + 3c:e8:29:09:b9:11:64:74:cc:b5:73:9f:1c:48:a9:bc:61:01: + ee:e2:17:a6:0c:e3:40:08:3b:0e:e7:eb:44:73:2a:9a:f1:69: + 92:ef:71:14:c3:39:ac:71:a7:91:09:6f:e4:71:06:b3:ba:59: + 57:26:79:00:f6:f8:0d:a2:33:30:28:d4:aa:58:a0:9d:9d:69: + 91:fd + +Verisign Class 3 Public Primary Certification Authority - G3 +============================================================ +MD5 Fingerprint: CD:68:B6:A7:C7:C4:CE:75:E0:1D:4F:57:44:61:92:09 +PEM Data: +-----BEGIN CERTIFICATE----- +MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQsw +CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl +cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu +LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT +aWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp +dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD +VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT +aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ +bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu +IENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg +LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMu6nFL8eB8aHm8b +N3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1EUGO+i2t +KmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGu +kxUccLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBm +CC+Vk7+qRy+oRpfwEuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJ +Xwzw3sJ2zq/3avL6QaaiMxTJ5Xpj055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWu +imi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAERSWwauSCPc/L8my/uRan2Te +2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5fj267Cz3qWhMe +DGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC +/Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565p +F4ErWjfJXir0xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGt +TxzhT5yvDwyd93gN2PQ1VoDat20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ== +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 1 (0x0) + Serial Number: + 9b:7e:06:49:a3:3e:62:b9:d5:ee:90:48:71:29:ef:57 + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 1999 VeriSign, Inc. - For authorized use only, CN=VeriSign Class 3 Public Primary Certification Authority - G3 + Validity + Not Before: Oct 1 00:00:00 1999 GMT + Not After : Jul 16 23:59:59 2036 GMT + Subject: C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 1999 VeriSign, Inc. - For authorized use only, CN=VeriSign Class 3 Public Primary Certification Authority - G3 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:cb:ba:9c:52:fc:78:1f:1a:1e:6f:1b:37:73:bd: + f8:c9:6b:94:12:30:4f:f0:36:47:f5:d0:91:0a:f5: + 17:c8:a5:61:c1:16:40:4d:fb:8a:61:90:e5:76:20: + c1:11:06:7d:ab:2c:6e:a6:f5:11:41:8e:fa:2d:ad: + 2a:61:59:a4:67:26:4c:d0:e8:bc:52:5b:70:20:04: + 58:d1:7a:c9:a4:69:bc:83:17:64:ad:05:8b:bc:d0: + 58:ce:8d:8c:f5:eb:f0:42:49:0b:9d:97:27:67:32: + 6e:e1:ae:93:15:1c:70:bc:20:4d:2f:18:de:92:88: + e8:6c:85:57:11:1a:e9:7e:e3:26:11:54:a2:45:96: + 55:83:ca:30:89:e8:dc:d8:a3:ed:2a:80:3f:7f:79: + 65:57:3e:15:20:66:08:2f:95:93:bf:aa:47:2f:a8: + 46:97:f0:12:e2:fe:c2:0a:2b:51:e6:76:e6:b7:46: + b7:e2:0d:a6:cc:a8:c3:4c:59:55:89:e6:e8:53:5c: + 1c:ea:9d:f0:62:16:0b:a7:c9:5f:0c:f0:de:c2:76: + ce:af:f7:6a:f2:fa:41:a6:a2:33:14:c9:e5:7a:63: + d3:9e:62:37:d5:85:65:9e:0e:e6:53:24:74:1b:5e: + 1d:12:53:5b:c7:2c:e7:83:49:3b:15:ae:8a:68:b9: + 57:97 + Exponent: 65537 (0x10001) + Signature Algorithm: sha1WithRSAEncryption + 11:14:96:c1:ab:92:08:f7:3f:2f:c9:b2:fe:e4:5a:9f:64:de: + db:21:4f:86:99:34:76:36:57:dd:d0:15:2f:c5:ad:7f:15:1f: + 37:62:73:3e:d4:e7:5f:ce:17:03:db:35:fa:2b:db:ae:60:09: + 5f:1e:5f:8f:6e:bb:0b:3d:ea:5a:13:1e:0c:60:6f:b5:c0:b5: + 23:22:2e:07:0b:cb:a9:74:cb:47:bb:1d:c1:d7:a5:6b:cc:2f: + d2:42:fd:49:dd:a7:89:cf:53:ba:da:00:5a:28:bf:82:df:f8: + ba:13:1d:50:86:82:fd:8e:30:8f:29:46:b0:1e:3d:35:da:38: + 62:16:18:4a:ad:e6:b6:51:6c:de:af:62:eb:01:d0:1e:24:fe: + 7a:8f:12:1a:12:68:b8:fb:66:99:14:14:45:5c:ae:e7:ae:69: + 17:81:2b:5a:37:c9:5e:2a:f4:c6:e2:a1:5c:54:9b:a6:54:00: + cf:f0:f1:c1:c7:98:30:1a:3b:36:16:db:a3:6e:ea:fd:ad:b2: + c2:da:ef:02:47:13:8a:c0:f1:b3:31:ad:4f:1c:e1:4f:9c:af: + 0f:0c:9d:f7:78:0d:d8:f4:35:56:80:da:b7:6d:17:8f:9d:1e: + 81:64:e1:fe:c5:45:ba:ad:6b:b9:0a:7a:4e:4f:4b:84:ee:4b: + f1:7d:dd:11 + +Verisign Class 4 Public Primary Certification Authority - G2 +============================================================ +MD5 Fingerprint: 26:6D:2C:19:98:B6:70:68:38:50:54:19:EC:90:34:60 +PEM Data: +-----BEGIN CERTIFICATE----- +MIIDAjCCAmsCEDKIjprS9esTR/h/xCA3JfgwDQYJKoZIhvcNAQEFBQAwgcExCzAJ +BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh +c3MgNCBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy +MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp +emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X +DTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw +FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgNCBQdWJsaWMg +UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo +YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5 +MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB +AQUAA4GNADCBiQKBgQC68OTP+cSuhVS5B1f5j8V/aBH4xBewRNzjMHPVKmIquNDM +HO0oW369atyzkSTKQWI8/AIBvxwWMZQFl3Zuoq29YRdsTjCG8FE3KlDHqGKB3FtK +qsGgtG7rL+VXxbErQHDbWk2hjh+9Ax/YA9SPTJlxvOKCzFjomDqG04Y48wApHwID +AQABMA0GCSqGSIb3DQEBBQUAA4GBAIWMEsGnuVAVess+rLhDityq3RS6iYF+ATwj +cSGIL4LcY/oCRaxFWdcqWERbt5+BO5JoPeI3JPV7bI92NZYJqFmduc4jq3TWg/0y +cyfYaT5DdPauxYma51N86Xv2S/PBZYPejYqcPIiNOVn8qj8ijaHBZlCBckztImRP +T8qAkbYp +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 1 (0x0) + Serial Number: + 32:88:8e:9a:d2:f5:eb:13:47:f8:7f:c4:20:37:25:f8 + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=VeriSign, Inc., OU=Class 4 Public Primary Certification Authority - G2, OU=(c) 1998 VeriSign, Inc. - For authorized use only, OU=VeriSign Trust Network + Validity + Not Before: May 18 00:00:00 1998 GMT + Not After : Aug 1 23:59:59 2028 GMT + Subject: C=US, O=VeriSign, Inc., OU=Class 4 Public Primary Certification Authority - G2, OU=(c) 1998 VeriSign, Inc. - For authorized use only, OU=VeriSign Trust Network + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:ba:f0:e4:cf:f9:c4:ae:85:54:b9:07:57:f9:8f: + c5:7f:68:11:f8:c4:17:b0:44:dc:e3:30:73:d5:2a: + 62:2a:b8:d0:cc:1c:ed:28:5b:7e:bd:6a:dc:b3:91: + 24:ca:41:62:3c:fc:02:01:bf:1c:16:31:94:05:97: + 76:6e:a2:ad:bd:61:17:6c:4e:30:86:f0:51:37:2a: + 50:c7:a8:62:81:dc:5b:4a:aa:c1:a0:b4:6e:eb:2f: + e5:57:c5:b1:2b:40:70:db:5a:4d:a1:8e:1f:bd:03: + 1f:d8:03:d4:8f:4c:99:71:bc:e2:82:cc:58:e8:98: + 3a:86:d3:86:38:f3:00:29:1f + Exponent: 65537 (0x10001) + Signature Algorithm: sha1WithRSAEncryption + 85:8c:12:c1:a7:b9:50:15:7a:cb:3e:ac:b8:43:8a:dc:aa:dd: + 14:ba:89:81:7e:01:3c:23:71:21:88:2f:82:dc:63:fa:02:45: + ac:45:59:d7:2a:58:44:5b:b7:9f:81:3b:92:68:3d:e2:37:24: + f5:7b:6c:8f:76:35:96:09:a8:59:9d:b9:ce:23:ab:74:d6:83: + fd:32:73:27:d8:69:3e:43:74:f6:ae:c5:89:9a:e7:53:7c:e9: + 7b:f6:4b:f3:c1:65:83:de:8d:8a:9c:3c:88:8d:39:59:fc:aa: + 3f:22:8d:a1:c1:66:50:81:72:4c:ed:22:64:4f:4f:ca:80:91: + b6:29 + +Verisign Class 4 Public Primary Certification Authority - G3 +============================================================ +MD5 Fingerprint: DB:C8:F2:27:2E:B1:EA:6A:29:23:5D:FE:56:3E:33:DF +PEM Data: +-----BEGIN CERTIFICATE----- +MIIEGjCCAwICEQDsoKeLbnVqAc/EfMwvlF7XMA0GCSqGSIb3DQEBBQUAMIHKMQsw +CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl +cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu +LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT +aWduIENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp +dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD +VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT +aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ +bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu +IENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg +LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK3LpRFpxlmr8Y+1 +GQ9Wzsy1HyDkniYlS+BzZYlZ3tCD5PUPtbut8XzoIfzk6AzufEUiGXaStBO3IFsJ ++mGuqPKljYXCKtbeZjbSmwL0qJJgfJxptI8kHtCGUvYynEFYHiK9zUVilQhu0Gbd +U6LM8BDcVHOLBKFGMzNcF0C5nk3T875Vg+ixiY5afJqWIpA7iCXy0lOIAgwLePLm +NxdLMEYH5IBtptiWLugs+BGzOA1mppvqySNb247i8xOOGlktqgLw7KSHZtzBP/XY +ufTsgsbSPZUd5cBPhMnZo0QoBmrXRazwa2rvTl/4EYIeOGM0ZlDUPpNz+jDDZq3/ +ky2X7wMCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAj/ola09b5KROJ1WrIhVZPMq1 +CtRK26vdoV9TxaBXOcLORyu+OshWv8LZJxA6sQU8wHcxuzrTBXttmhwwjIDLk5Mq +g6sFUYICABFna/OIYUdfA5PVWw3g8dShMjWFsjrbsIKr0csKvE+MW8VLADsfKoKm +fjaF3H48ZwC15DtS4KjrXRX5xm3wrR0OhbepmnMUWluPQSjA1egtTaRezarZ7c7c +2NU8Qh0XwRJdRTjDOPP8hS6DRkiy1yBfkjaP53kPmF6Z6PDQpLv1U70qzlmwr25/ +bLvSHgCwIe34QWKCudiyxLtGUPMxxY8BqHTr9Xgn2uf3ZkPznoM+IKrDNWCRzg== +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 1 (0x0) + Serial Number: + ec:a0:a7:8b:6e:75:6a:01:cf:c4:7c:cc:2f:94:5e:d7 + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 1999 VeriSign, Inc. - For authorized use only, CN=VeriSign Class 4 Public Primary Certification Authority - G3 + Validity + Not Before: Oct 1 00:00:00 1999 GMT + Not After : Jul 16 23:59:59 2036 GMT + Subject: C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 1999 VeriSign, Inc. - For authorized use only, CN=VeriSign Class 4 Public Primary Certification Authority - G3 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:ad:cb:a5:11:69:c6:59:ab:f1:8f:b5:19:0f:56: + ce:cc:b5:1f:20:e4:9e:26:25:4b:e0:73:65:89:59: + de:d0:83:e4:f5:0f:b5:bb:ad:f1:7c:e8:21:fc:e4: + e8:0c:ee:7c:45:22:19:76:92:b4:13:b7:20:5b:09: + fa:61:ae:a8:f2:a5:8d:85:c2:2a:d6:de:66:36:d2: + 9b:02:f4:a8:92:60:7c:9c:69:b4:8f:24:1e:d0:86: + 52:f6:32:9c:41:58:1e:22:bd:cd:45:62:95:08:6e: + d0:66:dd:53:a2:cc:f0:10:dc:54:73:8b:04:a1:46: + 33:33:5c:17:40:b9:9e:4d:d3:f3:be:55:83:e8:b1: + 89:8e:5a:7c:9a:96:22:90:3b:88:25:f2:d2:53:88: + 02:0c:0b:78:f2:e6:37:17:4b:30:46:07:e4:80:6d: + a6:d8:96:2e:e8:2c:f8:11:b3:38:0d:66:a6:9b:ea: + c9:23:5b:db:8e:e2:f3:13:8e:1a:59:2d:aa:02:f0: + ec:a4:87:66:dc:c1:3f:f5:d8:b9:f4:ec:82:c6:d2: + 3d:95:1d:e5:c0:4f:84:c9:d9:a3:44:28:06:6a:d7: + 45:ac:f0:6b:6a:ef:4e:5f:f8:11:82:1e:38:63:34: + 66:50:d4:3e:93:73:fa:30:c3:66:ad:ff:93:2d:97: + ef:03 + Exponent: 65537 (0x10001) + Signature Algorithm: sha1WithRSAEncryption + 8f:fa:25:6b:4f:5b:e4:a4:4e:27:55:ab:22:15:59:3c:ca:b5: + 0a:d4:4a:db:ab:dd:a1:5f:53:c5:a0:57:39:c2:ce:47:2b:be: + 3a:c8:56:bf:c2:d9:27:10:3a:b1:05:3c:c0:77:31:bb:3a:d3: + 05:7b:6d:9a:1c:30:8c:80:cb:93:93:2a:83:ab:05:51:82:02: + 00:11:67:6b:f3:88:61:47:5f:03:93:d5:5b:0d:e0:f1:d4:a1: + 32:35:85:b2:3a:db:b0:82:ab:d1:cb:0a:bc:4f:8c:5b:c5:4b: + 00:3b:1f:2a:82:a6:7e:36:85:dc:7e:3c:67:00:b5:e4:3b:52: + e0:a8:eb:5d:15:f9:c6:6d:f0:ad:1d:0e:85:b7:a9:9a:73:14: + 5a:5b:8f:41:28:c0:d5:e8:2d:4d:a4:5e:cd:aa:d9:ed:ce:dc: + d8:d5:3c:42:1d:17:c1:12:5d:45:38:c3:38:f3:fc:85:2e:83: + 46:48:b2:d7:20:5f:92:36:8f:e7:79:0f:98:5e:99:e8:f0:d0: + a4:bb:f5:53:bd:2a:ce:59:b0:af:6e:7f:6c:bb:d2:1e:00:b0: + 21:ed:f8:41:62:82:b9:d8:b2:c4:bb:46:50:f3:31:c5:8f:01: + a8:74:eb:f5:78:27:da:e7:f7:66:43:f3:9e:83:3e:20:aa:c3: + 35:60:91:ce + +Verisign/RSA Commercial CA +========================== +MD5 Fingerprint: 5A:0B:DD:42:9E:B2:B4:62:97:32:7F:7F:0A:AA:9A:39 +PEM Data: +-----BEGIN CERTIFICATE----- +MIICIzCCAZACBQJBAAAWMA0GCSqGSIb3DQEBAgUAMFwxCzAJBgNVBAYTAlVTMSAw +HgYDVQQKExdSU0EgRGF0YSBTZWN1cml0eSwgSW5jLjErMCkGA1UECxMiQ29tbWVy +Y2lhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05NDExMDQxODU4MzRaFw05 +OTExMDMxODU4MzRaMFwxCzAJBgNVBAYTAlVTMSAwHgYDVQQKExdSU0EgRGF0YSBT +ZWN1cml0eSwgSW5jLjErMCkGA1UECxMiQ29tbWVyY2lhbCBDZXJ0aWZpY2F0aW9u +IEF1dGhvcml0eTCBmzANBgkqhkiG9w0BAQEFAAOBiQAwgYUCfgCk+4Fie84QJ93o +975sbsZwmdu41QUDaSiCnHJ/lj+O7Kwpkj+KFPhCdr69XQO5kNTQvAayUTNfxMK/ +touPmbZiImDd298ggrTKoi8tUO2UMt7gVY3UaOLgTNLNBRYulWZcYVI4HlGogqHE +7yXpCuaLK44xZtn42f29O2nZ6wIDAQABMA0GCSqGSIb3DQEBAgUAA34AdrW2EP4j +9/dZYkuwX5zBaLxJu7NJbyFHXSudVMQAKD+YufKKg5tgf+tQx6sFEC097TgCwaVI +0v5loMC86qYjFmZsGySp8+x5NRhPJsjjr1BKx6cxa9B8GJ1Qv6km+iYrRpwUqbtb +MJhCKLVLU7tDCZJAuqiqWqTGtotXTcU= +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 1 (0x0) + Serial Number: + 02:41:00:00:16 + Signature Algorithm: md2WithRSAEncryption + Issuer: C=US, O=RSA Data Security, Inc., OU=Commercial Certification Authority + Validity + Not Before: Nov 4 18:58:34 1994 GMT + Not After : Nov 3 18:58:34 1999 GMT + Subject: C=US, O=RSA Data Security, Inc., OU=Commercial Certification Authority + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1000 bit) + Modulus (1000 bit): + 00:a4:fb:81:62:7b:ce:10:27:dd:e8:f7:be:6c:6e: + c6:70:99:db:b8:d5:05:03:69:28:82:9c:72:7f:96: + 3f:8e:ec:ac:29:92:3f:8a:14:f8:42:76:be:bd:5d: + 03:b9:90:d4:d0:bc:06:b2:51:33:5f:c4:c2:bf:b6: + 8b:8f:99:b6:62:22:60:dd:db:df:20:82:b4:ca:a2: + 2f:2d:50:ed:94:32:de:e0:55:8d:d4:68:e2:e0:4c: + d2:cd:05:16:2e:95:66:5c:61:52:38:1e:51:a8:82: + a1:c4:ef:25:e9:0a:e6:8b:2b:8e:31:66:d9:f8:d9: + fd:bd:3b:69:d9:eb + Exponent: 65537 (0x10001) + Signature Algorithm: md2WithRSAEncryption + 76:b5:b6:10:fe:23:f7:f7:59:62:4b:b0:5f:9c:c1:68:bc:49: + bb:b3:49:6f:21:47:5d:2b:9d:54:c4:00:28:3f:98:b9:f2:8a: + 83:9b:60:7f:eb:50:c7:ab:05:10:2d:3d:ed:38:02:c1:a5:48: + d2:fe:65:a0:c0:bc:ea:a6:23:16:66:6c:1b:24:a9:f3:ec:79: + 35:18:4f:26:c8:e3:af:50:4a:c7:a7:31:6b:d0:7c:18:9d:50: + bf:a9:26:fa:26:2b:46:9c:14:a9:bb:5b:30:98:42:28:b5:4b: + 53:bb:43:09:92:40:ba:a8:aa:5a:a4:c6:b6:8b:57:4d:c5 + +Verisign/RSA Secure Server CA +============================= +MD5 Fingerprint: 74:7B:82:03:43:F0:00:9E:6B:B3:EC:47:BF:85:A5:93 +PEM Data: +-----BEGIN CERTIFICATE----- +MIICNDCCAaECEAKtZn5ORf5eV288mBle3cAwDQYJKoZIhvcNAQECBQAwXzELMAkG +A1UEBhMCVVMxIDAeBgNVBAoTF1JTQSBEYXRhIFNlY3VyaXR5LCBJbmMuMS4wLAYD +VQQLEyVTZWN1cmUgU2VydmVyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk0 +MTEwOTAwMDAwMFoXDTEwMDEwNzIzNTk1OVowXzELMAkGA1UEBhMCVVMxIDAeBgNV +BAoTF1JTQSBEYXRhIFNlY3VyaXR5LCBJbmMuMS4wLAYDVQQLEyVTZWN1cmUgU2Vy +dmVyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGbMA0GCSqGSIb3DQEBAQUAA4GJ +ADCBhQJ+AJLOesGugz5aqomDV6wlAXYMra6OLDfO6zV4ZFQD5YRAUcm/jwjiioII +0haGN1XpsSECrXZogZoFokvJSyVmIlZsiAeP94FZbYQHZXATcXY+m3dM41CJVphI +uR2nKRoTLkoRWZweFdVJVCxzOmmCsZc5nG1wZ0jl3S3WyB57AgMBAAEwDQYJKoZI +hvcNAQECBQADfgBl3X7hsuyw4jrg7HFGmhkRuNPHoLQDQCYCPgmc4RKz0Vr2N6W3 +YQO2WxZpO8ZECAyIUwxrl0nHPjXcbLm7qt9cuzovk2C2qUtN8iD3zV9/ZHuO3ABc +1/p3yjkWWW8O6tO1g39NTUJWdrTJXwT4OPjr0l91X817/OWOgHz8UA== +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 1 (0x0) + Serial Number: + 02:ad:66:7e:4e:45:fe:5e:57:6f:3c:98:19:5e:dd:c0 + Signature Algorithm: md2WithRSAEncryption + Issuer: C=US, O=RSA Data Security, Inc., OU=Secure Server Certification Authority + Validity + Not Before: Nov 9 00:00:00 1994 GMT + Not After : Jan 7 23:59:59 2010 GMT + Subject: C=US, O=RSA Data Security, Inc., OU=Secure Server Certification Authority + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1000 bit) + Modulus (1000 bit): + 00:92:ce:7a:c1:ae:83:3e:5a:aa:89:83:57:ac:25: + 01:76:0c:ad:ae:8e:2c:37:ce:eb:35:78:64:54:03: + e5:84:40:51:c9:bf:8f:08:e2:8a:82:08:d2:16:86: + 37:55:e9:b1:21:02:ad:76:68:81:9a:05:a2:4b:c9: + 4b:25:66:22:56:6c:88:07:8f:f7:81:59:6d:84:07: + 65:70:13:71:76:3e:9b:77:4c:e3:50:89:56:98:48: + b9:1d:a7:29:1a:13:2e:4a:11:59:9c:1e:15:d5:49: + 54:2c:73:3a:69:82:b1:97:39:9c:6d:70:67:48:e5: + dd:2d:d6:c8:1e:7b + Exponent: 65537 (0x10001) + Signature Algorithm: md2WithRSAEncryption + 65:dd:7e:e1:b2:ec:b0:e2:3a:e0:ec:71:46:9a:19:11:b8:d3: + c7:a0:b4:03:40:26:02:3e:09:9c:e1:12:b3:d1:5a:f6:37:a5: + b7:61:03:b6:5b:16:69:3b:c6:44:08:0c:88:53:0c:6b:97:49: + c7:3e:35:dc:6c:b9:bb:aa:df:5c:bb:3a:2f:93:60:b6:a9:4b: + 4d:f2:20:f7:cd:5f:7f:64:7b:8e:dc:00:5c:d7:fa:77:ca:39: + 16:59:6f:0e:ea:d3:b5:83:7f:4d:4d:42:56:76:b4:c9:5f:04: + f8:38:f8:eb:d2:5f:75:5f:cd:7b:fc:e5:8e:80:7c:fc:50 + + +UTN-USERFirst-Network Applications +================================== +MD5 Fingerprint: BF:60:59:A3:5B:BA:F6:A7:76:42:DA:6F:1A:7B:50:CF +PEM Data: +-----BEGIN CERTIFICATE----- +MIIEZDCCA0ygAwIBAgIQRL4Mi1AAJLQR0zYwS8AzdzANBgkqhkiG9w0BAQUFADCB +ozELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug +Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho +dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xKzApBgNVBAMTIlVUTi1VU0VSRmlyc3Qt +TmV0d29yayBBcHBsaWNhdGlvbnMwHhcNOTkwNzA5MTg0ODM5WhcNMTkwNzA5MTg1 +NzQ5WjCBozELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0 +IExha2UgQ2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYD +VQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xKzApBgNVBAMTIlVUTi1VU0VS +Rmlyc3QtTmV0d29yayBBcHBsaWNhdGlvbnMwggEiMA0GCSqGSIb3DQEBAQUAA4IB +DwAwggEKAoIBAQCz+5Gh5DZVhawGNFugmliy+LUPBXeDrjKxdpJo7CNKyXY/45y2 +N3kDuatpjQclthln5LAbGHNhSuh+zdMvZOOmfAz6F4CjDUeJT1FxL+78P/m4FoCH +iZMlIJpDgmkkdihZNaEdwH+DBmQWICzTSaSFtMBhf1EI+GgVkYDLpdXuOzr0hARe +YFmnjDRy7rh4xdE7EkpvfmUnuaRVxblvQ6TFHSyZwFKkeEwVs0CYCGtDxgGwenv1 +axwiP8vv/6jQOkt2FZ7S0cYu49tXGzKiuG/ohqY/cKvlcJKrRB5AUPuco2LkbG6g +yN7igEL66S/ozjIEj3yNtxyjNTwV3Z7DrpelAgMBAAGjgZEwgY4wCwYDVR0PBAQD +AgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFPqGydvguul49Uuo1hXf8NPh +ahQ8ME8GA1UdHwRIMEYwRKBCoECGPmh0dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9V +VE4tVVNFUkZpcnN0LU5ldHdvcmtBcHBsaWNhdGlvbnMuY3JsMA0GCSqGSIb3DQEB +BQUAA4IBAQCk8yXM0dSRgyLQzDKrm5ZONJFUICU0YV8qAhXhi6r/fWRRzwr/vH3Y +IWp4yy9Rb/hCHTO967V7lMPDqaAt39EpHx3+jz+7qEUqf9FuVSTiuwL7MT++6Lzs +QCv4AdRWOOTKRIK1YSAhZ2X28AvnNPilwpyjXEAfhZOVBt5P1CeptqX8Fs1zMT+4 +ZSfP1FMa8Kxun08FDAOBp4QpxFq9ZFdyrTvPNximmMatBrTcCKME1SmklpoSZ0qM +YEWd8SOasACcaLWYUNPvji6SZbFIPiG+FTAqDbUMo2s/rn9X9R+WfN9v3YIwLGUb +QErNaLly7HF27FSOH4UMAWr6pjisH8SE +-----END CERTIFICATE----- +Certificate Ingredients: + Data: + Version: 3 (0x2) + Serial Number: + 44:be:0c:8b:50:00:24:b4:11:d3:36:30:4b:c0:33:77 + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, ST=UT, L=Salt Lake City, O=The USERTRUST Network, OU=http://www.usertrust.com, CN=UTN-USERFirst-Network Applications + Validity + Not Before: Jul 9 18:48:39 1999 GMT + Not After : Jul 9 18:57:49 2019 GMT + Subject: C=US, ST=UT, L=Salt Lake City, O=The USERTRUST Network, OU=http://www.usertrust.com, CN=UTN-USERFirst-Network Applications + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:b3:fb:91:a1:e4:36:55:85:ac:06:34:5b:a0:9a: + 58:b2:f8:b5:0f:05:77:83:ae:32:b1:76:92:68:ec: + 23:4a:c9:76:3f:e3:9c:b6:37:79:03:b9:ab:69:8d: + 07:25:b6:19:67:e4:b0:1b:18:73:61:4a:e8:7e:cd: + d3:2f:64:e3:a6:7c:0c:fa:17:80:a3:0d:47:89:4f: + 51:71:2f:ee:fc:3f:f9:b8:16:80:87:89:93:25:20: + 9a:43:82:69:24:76:28:59:35:a1:1d:c0:7f:83:06: + 64:16:20:2c:d3:49:a4:85:b4:c0:61:7f:51:08:f8: + 68:15:91:80:cb:a5:d5:ee:3b:3a:f4:84:04:5e:60: + 59:a7:8c:34:72:ee:b8:78:c5:d1:3b:12:4a:6f:7e: + 65:27:b9:a4:55:c5:b9:6f:43:a4:c5:1d:2c:99:c0: + 52:a4:78:4c:15:b3:40:98:08:6b:43:c6:01:b0:7a: + 7b:f5:6b:1c:22:3f:cb:ef:ff:a8:d0:3a:4b:76:15: + 9e:d2:d1:c6:2e:e3:db:57:1b:32:a2:b8:6f:e8:86: + a6:3f:70:ab:e5:70:92:ab:44:1e:40:50:fb:9c:a3: + 62:e4:6c:6e:a0:c8:de:e2:80:42:fa:e9:2f:e8:ce: + 32:04:8f:7c:8d:b7:1c:a3:35:3c:15:dd:9e:c3:ae: + 97:a5 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + FA:86:C9:DB:E0:BA:E9:78:F5:4B:A8:D6:15:DF:F0:D3:E1:6A:14:3C + X509v3 CRL Distribution Points: + URI:http://crl.usertrust.com/UTN-USERFirst-NetworkApplications.crl + + Signature Algorithm: sha1WithRSAEncryption + a4:f3:25:cc:d1:d4:91:83:22:d0:cc:32:ab:9b:96:4e:34:91: + 54:20:25:34:61:5f:2a:02:15:e1:8b:aa:ff:7d:64:51:cf:0a: + ff:bc:7d:d8:21:6a:78:cb:2f:51:6f:f8:42:1d:33:bd:eb:b5: + 7b:94:c3:c3:a9:a0:2d:df:d1:29:1f:1d:fe:8f:3f:bb:a8:45: + 2a:7f:d1:6e:55:24:e2:bb:02:fb:31:3f:be:e8:bc:ec:40:2b: + f8:01:d4:56:38:e4:ca:44:82:b5:61:20:21:67:65:f6:f0:0b: + e7:34:f8:a5:c2:9c:a3:5c:40:1f:85:93:95:06:de:4f:d4:27: + a9:b6:a5:fc:16:cd:73:31:3f:b8:65:27:cf:d4:53:1a:f0:ac: + 6e:9f:4f:05:0c:03:81:a7:84:29:c4:5a:bd:64:57:72:ad:3b: + cf:37:18:a6:98:c6:ad:06:b4:dc:08:a3:04:d5:29:a4:96:9a: + 12:67:4a:8c:60:45:9d:f1:23:9a:b0:00:9c:68:b5:98:50:d3: + ef:8e:2e:92:65:b1:48:3e:21:be:15:30:2a:0d:b5:0c:a3:6b: + 3f:ae:7f:57:f5:1f:96:7c:df:6f:dd:82:30:2c:65:1b:40:4a: + cd:68:b9:72:ec:71:76:ec:54:8e:1f:85:0c:01:6a:fa:a6:38: + ac:1f:c4:84 +# +# RHNS CA certificate. Appended to the ca-bundle at package build-time. +# +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 0 (0x0) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=US, ST=North Carolina, L=Research Triangle Park, O=Red Hat, Inc., OU=Red Hat Network Services, CN=RHNS Certificate Authority/Email=rhns@redhat.com + Validity + Not Before: Aug 23 22:45:55 2000 GMT + Not After : Aug 28 22:45:55 2003 GMT + Subject: C=US, ST=North Carolina, L=Research Triangle Park, O=Red Hat, Inc., OU=Red Hat Network Services, CN=RHNS Certificate Authority/Email=rhns@redhat.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:c0:68:2b:12:30:e2:21:2d:22:c6:72:71:5b:bf: + 17:a0:93:10:e9:9b:e3:c9:8d:3b:2d:ac:c4:bb:95: + 3b:e0:ca:55:32:dc:95:c2:10:b3:04:b2:51:fb:e8: + 85:61:16:34:a5:b4:1d:67:5c:a7:77:f4:f0:92:da: + b4:8b:af:95:93:62:f3:66:29:ae:c0:88:b7:64:84: + 0e:48:90:60:f8:60:3e:00:7f:54:dd:17:a6:ac:18: + e0:42:de:7c:be:90:81:f7:f4:05:85:0a:08:cc:d5: + f2:9f:fc:24:8b:77:a5:3d:e9:48:a9:ef:0f:3b:63: + a3:fe:a6:83:4c:e8:dc:0b:77 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 54:15:CD:9F:2C:F7:EC:0D:1F:D2:A8:BE:4C:07:AC:88:3E:FB:9B:0A + X509v3 Authority Key Identifier: + keyid:54:15:CD:9F:2C:F7:EC:0D:1F:D2:A8:BE:4C:07:AC:88:3E:FB:9B:0A + DirName:/C=US/ST=North Carolina/L=Research Triangle Park/O=Red Hat, Inc./OU=Red Hat Network Services/CN=RHNS Certificate Authority/Email=rhns@redhat.com + serial:00 + + X509v3 Basic Constraints: + CA:TRUE + Signature Algorithm: md5WithRSAEncryption + 93:01:88:88:67:67:91:8c:9e:d0:12:14:90:71:12:87:55:0a: + f2:52:1b:ad:f2:d3:07:1d:af:70:99:bb:b0:cd:80:23:c9:ed: + 2b:73:e9:63:b1:d0:b3:8c:60:c5:42:64:a6:c1:95:56:90:c5: + 35:06:03:58:f5:8e:2b:d9:f9:a9:a0:10:a9:99:f7:15:42:92: + a5:50:d7:11:07:f1:02:d5:e0:70:e4:55:6e:2a:ce:25:f8:5d: + cd:0b:2f:10:61:f8:f6:20:42:cc:c3:89:f8:8a:4f:82:24:12: + cf:39:7f:21:a8:2c:8d:52:97:52:c5:f7:5f:42:a5:87:09:66: + b0:cc +-----BEGIN CERTIFICATE----- +MIIEMDCCA5mgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBxzELMAkGA1UEBhMCVVMx +FzAVBgNVBAgTDk5vcnRoIENhcm9saW5hMR8wHQYDVQQHExZSZXNlYXJjaCBUcmlh +bmdsZSBQYXJrMRYwFAYDVQQKEw1SZWQgSGF0LCBJbmMuMSEwHwYDVQQLExhSZWQg +SGF0IE5ldHdvcmsgU2VydmljZXMxIzAhBgNVBAMTGlJITlMgQ2VydGlmaWNhdGUg +QXV0aG9yaXR5MR4wHAYJKoZIhvcNAQkBFg9yaG5zQHJlZGhhdC5jb20wHhcNMDAw +ODIzMjI0NTU1WhcNMDMwODI4MjI0NTU1WjCBxzELMAkGA1UEBhMCVVMxFzAVBgNV +BAgTDk5vcnRoIENhcm9saW5hMR8wHQYDVQQHExZSZXNlYXJjaCBUcmlhbmdsZSBQ +YXJrMRYwFAYDVQQKEw1SZWQgSGF0LCBJbmMuMSEwHwYDVQQLExhSZWQgSGF0IE5l +dHdvcmsgU2VydmljZXMxIzAhBgNVBAMTGlJITlMgQ2VydGlmaWNhdGUgQXV0aG9y +aXR5MR4wHAYJKoZIhvcNAQkBFg9yaG5zQHJlZGhhdC5jb20wgZ8wDQYJKoZIhvcN +AQEBBQADgY0AMIGJAoGBAMBoKxIw4iEtIsZycVu/F6CTEOmb48mNOy2sxLuVO+DK +VTLclcIQswSyUfvohWEWNKW0HWdcp3f08JLatIuvlZNi82YprsCIt2SEDkiQYPhg +PgB/VN0XpqwY4ELefL6Qgff0BYUKCMzV8p/8JIt3pT3pSKnvDztjo/6mg0zo3At3 +AgMBAAGjggEoMIIBJDAdBgNVHQ4EFgQUVBXNnyz37A0f0qi+TAesiD77mwowgfQG +A1UdIwSB7DCB6YAUVBXNnyz37A0f0qi+TAesiD77mwqhgc2kgcowgccxCzAJBgNV +BAYTAlVTMRcwFQYDVQQIEw5Ob3J0aCBDYXJvbGluYTEfMB0GA1UEBxMWUmVzZWFy +Y2ggVHJpYW5nbGUgUGFyazEWMBQGA1UEChMNUmVkIEhhdCwgSW5jLjEhMB8GA1UE +CxMYUmVkIEhhdCBOZXR3b3JrIFNlcnZpY2VzMSMwIQYDVQQDExpSSE5TIENlcnRp +ZmljYXRlIEF1dGhvcml0eTEeMBwGCSqGSIb3DQEJARYPcmhuc0ByZWRoYXQuY29t +ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAkwGIiGdnkYye0BIU +kHESh1UK8lIbrfLTBx2vcJm7sM2AI8ntK3PpY7HQs4xgxUJkpsGVVpDFNQYDWPWO +K9n5qaAQqZn3FUKSpVDXEQfxAtXgcORVbirOJfhdzQsvEGH49iBCzMOJ+IpPgiQS +zzl/IagsjVKXUsX3X0KlhwlmsMw= +-----END CERTIFICATE----- + +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 0 (0x0) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=US, ST=North Carolina, L=Raleigh, O=Red Hat, Inc., OU=Red Hat Network, CN=RHN Certificate Authority/Email=rhn-noc@redhat.com + Validity + Not Before: Sep 5 20:45:16 2002 GMT + Not After : Sep 9 20:45:16 2007 GMT + Subject: C=US, ST=North Carolina, L=Raleigh, O=Red Hat, Inc., OU=Red Hat Network, CN=RHN Certificate Authority/Email=rhn-noc@redhat.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:b3:16:b7:c5:f5:b9:69:51:1f:cd:b4:3d:70:cf: + 60:57:85:a4:2a:a7:5d:28:22:0e:ec:19:e2:92:f7: + 48:97:a6:a6:1f:51:95:83:11:8f:9a:98:a2:90:e0: + cb:4a:24:19:94:a8:8a:4b:88:b4:06:6c:ce:77:d7: + 15:3b:3c:cd:66:83:cf:23:1d:0d:bc:0a:0c:cb:1f: + cb:40:fb:f3:d9:fe:2a:b4:85:2c:7b:c9:a1:fe:f3: + 8f:68:1d:f2:12:b1:a4:16:19:ce:0f:b8:9a:9c:d9: + bc:5f:49:62:b2:95:93:ce:5d:2e:dd:79:3c:f1:5b: + a6:b7:a2:b5:39:0d:8e:12:31 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 7F:1B:64:A1:2E:02:C5:A8:7D:B8:D1:B1:8B:06:9D:A3:A9:50:63:92 + X509v3 Authority Key Identifier: + keyid:7F:1B:64:A1:2E:02:C5:A8:7D:B8:D1:B1:8B:06:9D:A3:A9:50:63:92 + DirName:/C=US/ST=North Carolina/L=Raleigh/O=Red Hat, Inc./OU=Red Hat Network/CN=RHN Certificate Authority/Email=rhn-noc@redhat.com + serial:00 + + X509v3 Basic Constraints: + CA:TRUE + Signature Algorithm: md5WithRSAEncryption + 28:4d:42:e5:34:22:dd:c6:86:63:04:75:52:67:17:45:72:f2: + 3b:21:2b:45:59:72:73:f7:59:36:9d:57:43:c6:dc:94:0f:0e: + ff:13:5c:4f:50:37:85:b2:e4:c2:1f:35:9f:74:f4:e7:53:fb: + a1:06:b8:39:ce:e4:0a:86:7b:5f:28:5d:c7:11:9e:12:a5:d6: + b9:6c:e9:18:09:d5:f0:42:e7:54:b5:91:9e:23:ad:12:7a:aa: + 72:7c:39:3c:83:f8:75:a4:7b:03:92:ff:2a:d4:c5:76:19:12: + fa:b4:3b:b0:89:2c:95:8c:01:90:0d:d8:ba:06:05:61:00:ac: + 95:da +-----BEGIN CERTIFICATE----- +MIID7jCCA1egAwIBAgIBADANBgkqhkiG9w0BAQQFADCBsTELMAkGA1UEBhMCVVMx +FzAVBgNVBAgTDk5vcnRoIENhcm9saW5hMRAwDgYDVQQHEwdSYWxlaWdoMRYwFAYD +VQQKEw1SZWQgSGF0LCBJbmMuMRgwFgYDVQQLEw9SZWQgSGF0IE5ldHdvcmsxIjAg +BgNVBAMTGVJITiBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxITAfBgkqhkiG9w0BCQEW +EnJobi1ub2NAcmVkaGF0LmNvbTAeFw0wMjA5MDUyMDQ1MTZaFw0wNzA5MDkyMDQ1 +MTZaMIGxMQswCQYDVQQGEwJVUzEXMBUGA1UECBMOTm9ydGggQ2Fyb2xpbmExEDAO +BgNVBAcTB1JhbGVpZ2gxFjAUBgNVBAoTDVJlZCBIYXQsIEluYy4xGDAWBgNVBAsT +D1JlZCBIYXQgTmV0d29yazEiMCAGA1UEAxMZUkhOIENlcnRpZmljYXRlIEF1dGhv +cml0eTEhMB8GCSqGSIb3DQEJARYScmhuLW5vY0ByZWRoYXQuY29tMIGfMA0GCSqG +SIb3DQEBAQUAA4GNADCBiQKBgQCzFrfF9blpUR/NtD1wz2BXhaQqp10oIg7sGeKS +90iXpqYfUZWDEY+amKKQ4MtKJBmUqIpLiLQGbM531xU7PM1mg88jHQ28CgzLH8tA ++/PZ/iq0hSx7yaH+849oHfISsaQWGc4PuJqc2bxfSWKylZPOXS7deTzxW6a3orU5 +DY4SMQIDAQABo4IBEjCCAQ4wHQYDVR0OBBYEFH8bZKEuAsWofbjRsYsGnaOpUGOS +MIHeBgNVHSMEgdYwgdOAFH8bZKEuAsWofbjRsYsGnaOpUGOSoYG3pIG0MIGxMQsw +CQYDVQQGEwJVUzEXMBUGA1UECBMOTm9ydGggQ2Fyb2xpbmExEDAOBgNVBAcTB1Jh +bGVpZ2gxFjAUBgNVBAoTDVJlZCBIYXQsIEluYy4xGDAWBgNVBAsTD1JlZCBIYXQg +TmV0d29yazEiMCAGA1UEAxMZUkhOIENlcnRpZmljYXRlIEF1dGhvcml0eTEhMB8G +CSqGSIb3DQEJARYScmhuLW5vY0ByZWRoYXQuY29tggEAMAwGA1UdEwQFMAMBAf8w +DQYJKoZIhvcNAQEEBQADgYEAKE1C5TQi3caGYwR1UmcXRXLyOyErRVlyc/dZNp1X +Q8bclA8O/xNcT1A3hbLkwh81n3T051P7oQa4Oc7kCoZ7XyhdxxGeEqXWuWzpGAnV +8ELnVLWRniOtEnqqcnw5PIP4daR7A5L/KtTFdhkS+rQ7sIkslYwBkA3YugYFYQCs +ldo= +-----END CERTIFICATE----- + +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 0 (0x0) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=US, ST=North Carolina, L=Raleigh, O=Red Hat, Inc., OU=Red Hat Network, CN=RHN Certificate Authority/emailAddress=rhn-noc@redhat.com + Validity + Not Before: Aug 29 02:10:55 2003 GMT + Not After : Aug 26 02:10:55 2013 GMT + Subject: C=US, ST=North Carolina, L=Raleigh, O=Red Hat, Inc., OU=Red Hat Network, CN=RHN Certificate Authority/emailAddress=rhn-noc@redhat.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:bf:61:63:eb:3d:8b:2b:45:48:e6:c2:fb:7c:d2: + 21:21:b8:ec:90:93:41:30:7c:2c:8d:79:d5:14:e9: + 0e:7e:3f:ef:d6:0a:9b:0a:a6:02:52:01:2d:26:96: + a4:ed:bd:a9:9e:aa:08:03:c1:61:0a:41:80:ea:ae: + 74:cc:61:26:d0:05:91:55:3e:66:14:a2:20:b3:d6: + 9d:71:0c:ab:77:cc:f4:f0:11:b5:25:33:8a:4e:22: + 9a:10:36:67:fa:11:6d:48:76:3a:1f:d2:e3:44:7b: + 89:66:be:b4:85:fb:2f:a6:aa:13:fa:9a:6d:c9:bb: + 18:c4:04:af:4f:15:69:89:9b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 69:44:27:05:DC:2E:ED:A5:F4:81:C4:D7:78:45:E7:44:5D:F8:87:47 + X509v3 Authority Key Identifier: + keyid:69:44:27:05:DC:2E:ED:A5:F4:81:C4:D7:78:45:E7:44:5D:F8:87:47 + DirName:/C=US/ST=North Carolina/L=Raleigh/O=Red Hat, Inc./OU=Red Hat Network/CN=RHN Certificate Authority/emailAddress=rhn-noc@redhat.com + serial:00 + + X509v3 Basic Constraints: + CA:TRUE + Signature Algorithm: md5WithRSAEncryption + 23:c9:ca:07:9f:5e:96:39:83:e0:4e:da:dd:47:84:30:ca:d4: + d5:38:86:f9:de:88:83:ca:2c:47:26:36:ab:f4:14:1e:28:29: + de:7d:10:4a:5e:91:3e:5a:99:07:0c:a9:2e:e3:fb:78:44:49: + c5:32:d6:e8:7a:97:ff:29:d0:33:ae:26:ba:76:06:7e:79:97: + 17:0c:4f:2d:2a:8b:8a:ac:41:59:ae:e9:c4:55:2d:b9:88:df: + 9b:7b:41:f8:32:2e:ee:c9:c0:59:e2:30:57:5e:37:47:29:c0: + 2d:78:33:d3:ce:a3:2b:dc:84:da:bf:3b:2e:4b:b6:b3:b6:4e: + 9e:80 +-----BEGIN CERTIFICATE----- +MIID7jCCA1egAwIBAgIBADANBgkqhkiG9w0BAQQFADCBsTELMAkGA1UEBhMCVVMx +FzAVBgNVBAgTDk5vcnRoIENhcm9saW5hMRAwDgYDVQQHEwdSYWxlaWdoMRYwFAYD +VQQKEw1SZWQgSGF0LCBJbmMuMRgwFgYDVQQLEw9SZWQgSGF0IE5ldHdvcmsxIjAg +BgNVBAMTGVJITiBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxITAfBgkqhkiG9w0BCQEW +EnJobi1ub2NAcmVkaGF0LmNvbTAeFw0wMzA4MjkwMjEwNTVaFw0xMzA4MjYwMjEw +NTVaMIGxMQswCQYDVQQGEwJVUzEXMBUGA1UECBMOTm9ydGggQ2Fyb2xpbmExEDAO +BgNVBAcTB1JhbGVpZ2gxFjAUBgNVBAoTDVJlZCBIYXQsIEluYy4xGDAWBgNVBAsT +D1JlZCBIYXQgTmV0d29yazEiMCAGA1UEAxMZUkhOIENlcnRpZmljYXRlIEF1dGhv +cml0eTEhMB8GCSqGSIb3DQEJARYScmhuLW5vY0ByZWRoYXQuY29tMIGfMA0GCSqG +SIb3DQEBAQUAA4GNADCBiQKBgQC/YWPrPYsrRUjmwvt80iEhuOyQk0EwfCyNedUU +6Q5+P+/WCpsKpgJSAS0mlqTtvameqggDwWEKQYDqrnTMYSbQBZFVPmYUoiCz1p1x +DKt3zPTwEbUlM4pOIpoQNmf6EW1Idjof0uNEe4lmvrSF+y+mqhP6mm3JuxjEBK9P +FWmJmwIDAQABo4IBEjCCAQ4wHQYDVR0OBBYEFGlEJwXcLu2l9IHE13hF50Rd+IdH +MIHeBgNVHSMEgdYwgdOAFGlEJwXcLu2l9IHE13hF50Rd+IdHoYG3pIG0MIGxMQsw +CQYDVQQGEwJVUzEXMBUGA1UECBMOTm9ydGggQ2Fyb2xpbmExEDAOBgNVBAcTB1Jh +bGVpZ2gxFjAUBgNVBAoTDVJlZCBIYXQsIEluYy4xGDAWBgNVBAsTD1JlZCBIYXQg +TmV0d29yazEiMCAGA1UEAxMZUkhOIENlcnRpZmljYXRlIEF1dGhvcml0eTEhMB8G +CSqGSIb3DQEJARYScmhuLW5vY0ByZWRoYXQuY29tggEAMAwGA1UdEwQFMAMBAf8w +DQYJKoZIhvcNAQEEBQADgYEAI8nKB59eljmD4E7a3UeEMMrU1TiG+d6Ig8osRyY2 +q/QUHigp3n0QSl6RPlqZBwypLuP7eERJxTLW6HqX/ynQM64munYGfnmXFwxPLSqL +iqxBWa7pxFUtuYjfm3tB+DIu7snAWeIwV143RynALXgz086jK9yE2r87Lku2s7ZO +noA= +-----END CERTIFICATE----- diff --git a/doc/certs/slapd.crt b/doc/certs/slapd.crt new file mode 100644 index 0000000..f7a511d --- /dev/null +++ b/doc/certs/slapd.crt @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE----- +MIICtTCCAh6gAwIBAgIBADANBgkqhkiG9w0BAQQFADBMMQswCQYDVQQGEwJHQjES +MBAGA1UECBMJQmVya3NoaXJlMRAwDgYDVQQHEwdOZXdidXJ5MRcwFQYDVQQKEw5N +eSBDb21wYW55IEx0ZDAeFw0wNTA5MTUwMjAyMTNaFw0yMTA3MjYxNjM2NTNaMEwx +CzAJBgNVBAYTAkdCMRIwEAYDVQQIEwlCZXJrc2hpcmUxEDAOBgNVBAcTB05ld2J1 +cnkxFzAVBgNVBAoTDk15IENvbXBhbnkgTHRkMIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQCr6PfdngYTUobwJDwIqY7ywDCWd/IJ+SL2hbe46558oVI7Vw2GbqWn +VZ1fJa0wV2pcy/e10HzZX+RpIwKOZUQvbH1jHJyZ/0bt7on8jmI5o+p+rLVspci5 +yVNcgu1tQttpyKnTrDSDkLVbQ6VX8FKLnKnZ7+dk8SNibt0KbzKnOQIDAQABo4Gm +MIGjMB0GA1UdDgQWBBQ4xLvszjgfXgWht8V6s1eRAZS/OjB0BgNVHSMEbTBrgBQ4 +xLvszjgfXgWht8V6s1eRAZS/OqFQpE4wTDELMAkGA1UEBhMCR0IxEjAQBgNVBAgT +CUJlcmtzaGlyZTEQMA4GA1UEBxMHTmV3YnVyeTEXMBUGA1UEChMOTXkgQ29tcGFu +eSBMdGSCAQAwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQQFAAOBgQAgzaIKI03l +lZmX7IpLN3vqC/PL6QQTUQkdDRXJYGH+DdURx7v0nE/kkb3R3X92BpNxe5jywhHg +A5NaUhjAR76+F3Guk/4XFaWPctJ2PvfJWolS/VrY+KGc3N4zz9A2i8B6SHBzE6V8 +EHkcGJtGXkFvCVp1ZbCyejJhw4PUEYawsQ== +-----END CERTIFICATE----- diff --git a/doc/certs/slapd.key b/doc/certs/slapd.key new file mode 100644 index 0000000..4edd557 --- /dev/null +++ b/doc/certs/slapd.key @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICWwIBAAKBgQCr6PfdngYTUobwJDwIqY7ywDCWd/IJ+SL2hbe46558oVI7Vw2G +bqWnVZ1fJa0wV2pcy/e10HzZX+RpIwKOZUQvbH1jHJyZ/0bt7on8jmI5o+p+rLVs +pci5yVNcgu1tQttpyKnTrDSDkLVbQ6VX8FKLnKnZ7+dk8SNibt0KbzKnOQIDAQAB +AoGAdfKYpag3WOiFhpwFyJe1aV5tt79CBI+36lZicHDQw4fXqLkYoYSnCYFXQSHT +ithfNJ4JLeiG0InXaD9KELLwLU2C7rr7mgOBczzmVBGCYUDNuV3bMcNDOQk/drum +GLGqHhxU6W0dlCUnoBZoEHK6dvtDZnxCa+cUBozvFbuLOTUCQQDZJf+Mz7vc78nn +Cc7nnHFfO+79NQi9h0ydW6kb2LLSGB/f3oqwary8eqCs7RVinG21PMWbjrh0lGOJ +DjYP6dLDAkEAyqrs8pgxcxSTcJiaU4/sxGCeaS4fvoeCbYvKLlS5k5Km6DmA3nY+ +KwxQyLHg64g1ImDSuLy3P/E2lZGCPhZGUwJAMVUxpqL3Mi2D+CpBSFtBYnpyRDJN +Rwm6/TD6zWnAznxOmYSsi4HkWQmfAUpnhly1i+w/lKSrAUlJB7Uj0R+1EwJAOADv +pUIFOCXRcGXbD4hQBxwj6jDCuOW9VwQwBImJFoyJ7tYlFFRcbYzjrfHpk2x6MlvL +Hx2XDeZcDQy+juWc3QJAHOpmlHuWqS07i5UIXVl5ohhoWkFd9Qs7/TowyFQF3zpO +BqnwfHZRpySjSUlNE0QpoJRJQPq7p3BWtS3PWMj0/A== +-----END RSA PRIVATE KEY----- diff --git a/doc/demo-reset.sh b/doc/demo-reset.sh new file mode 100644 index 0000000..a23ad5b --- /dev/null +++ b/doc/demo-reset.sh @@ -0,0 +1,18 @@ +#!/bin/sh + +for i in $(grep directory phpldapadmin-demo.conf|awk '{print $2}'); do + if [ -d $i ]; then + rm -f $i/*.dbb $i/*.bdb $i/__db.??? $i/alock $i/log.* + else + mkdir $i + fi +done + +slapadd -b "dc=example.com" -l ldif-example.com +slapadd -b "dc=example,dc=com" -l ldif-example-com +slapadd -b "o=Simpsons" -l ldif-Simpsons +slapadd -b "o=Flintstones" -l ldif-Flintstones + +for i in $(grep directory phpldapadmin-demo.conf|awk '{print $2}'); do + chown -R ldap:ldap $i +done diff --git a/doc/ldif-Flintstones b/doc/ldif-Flintstones new file mode 100644 index 0000000..9453690 --- /dev/null +++ b/doc/ldif-Flintstones @@ -0,0 +1,992 @@ +# LDIF Export for o=Flintstones +# Server: C5: OpenLDAP 2.3.27: config (c5dev.leenooks.vpn) +# Search Scope: sub +# Search Filter: (objectClass=*) +# Total Entries: 12 +# +# Generated by phpLDAPadmin (http://phpldapadmin.sourceforge.net) on April 26, 2011 9:03 pm +# Version: 1.2.0.5 + +#version: 1 + +# Entry 1: o=Flintstones +dn: o=Flintstones +o: Flintstones +objectclass: organization +objectclass: top + +# Entry 2: cn=Flintstones-PG,o=Flintstones +dn: cn=Flintstones-PG,o=Flintstones +cn: flintstones-pg +gidnumber: 1001 +objectclass: posixGroup +objectclass: top + +# Entry 3: ou=People,o=Flintstones +dn: ou=People,o=Flintstones +objectclass: organizationalUnit +objectclass: top +ou: People + +# Entry 4: cn=Bamm Bamm Rubble,ou=People,o=Flintstones +dn: cn=Bamm Bamm Rubble,ou=People,o=Flintstones +cn: Bamm Bamm Rubble +gidnumber: 1001 +givenname: Bamm Bamm +homedirectory: /home/users/flintstones/bammbamm +jpegphoto:: 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 + s9UUUV6eBRRRQH/9k= +l: Bedrock +loginshell: /bin/sh +objectclass: inetOrgPerson +objectclass: posixAccount +objectclass: top +sn: Rubble +uid: bammbamm +uidnumber: 1105 +userpassword: bammbamm + +# Entry 5: cn=Barney Rubble,ou=People,o=Flintstones +dn: cn=Barney Rubble,ou=People,o=Flintstones +cn: Barney Rubble +gidnumber: 1001 +givenname: Barney +homedirectory: /home/users/flintstones/barney +jpegphoto:: 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 +l: Bedrock +loginshell: /bin/sh +objectclass: inetOrgPerson +objectclass: posixAccount +objectclass: top +sn: Rubble +uid: barney +uidnumber: 1102 + +# Entry 6: cn=Betty Rubble,ou=People,o=Flintstones +dn: cn=Betty Rubble,ou=People,o=Flintstones +cn: Betty Rubble +gidnumber: 1001 +givenname: Betty +homedirectory: /home/users/flintstones/betty +jpegphoto:: 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 +l: Bedrock +loginshell: /bin/sh +objectclass: inetOrgPerson +objectclass: posixAccount +objectclass: top +sn: Rubble +uid: betty +uidnumber: 1103 + +# Entry 7: cn=Fred Flintstone,ou=People,o=Flintstones +dn: cn=Fred Flintstone,ou=People,o=Flintstones +cn: Fred Flintstone +gidnumber: 1001 +givenname: Fred +homedirectory: /home/users/flintstones/fred +jpegphoto:: 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 + EFZAKtieQxViUpTVjGsGGjRQnOLjkpSlK9LC/9k= +l: Bedrock +loginshell: /bin/sh +objectclass: inetOrgPerson +objectclass: posixAccount +objectclass: top +sn: Flintstone +st: 345 Stonecave Road +uid: fred +uidnumber: 1100 +userpassword: yabbadabbado + +# Entry 8: cn=Pebbles Flintstone,ou=People,o=Flintstones +dn: cn=Pebbles Flintstone,ou=People,o=Flintstones +cn: Pebbles Flintstone +gidnumber: 1001 +givenname: Pebbles +homedirectory: /home/users/flintstones/pebbles +jpegphoto:: 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 +l: Bedrock +loginshell: /bin/sh +objectclass: inetOrgPerson +objectclass: posixAccount +objectclass: top +sn: Flintstone +st: 345 Stonecave Road +uid: pebbles +uidnumber: 1104 + +# Entry 9: cn=Wilma Flintstone,ou=People,o=Flintstones +dn: cn=Wilma Flintstone,ou=People,o=Flintstones +cn: Wilma Flintstone +gidnumber: 1001 +givenname: Wilma +homedirectory: /home/users/flintstones/wilma +jpegphoto:: /9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBhQSERQUEhMWFBUUGRkXGRUXGRcf + FhseFSIZJR0YGxwXGyweGxsvJR0jHzMgIycrLTgsGB4xNjAqPCcrLCkBCQoKDgwOGg8PGi8lHiQ + tLioqLTU1LDU1KjQvMTAsNSouLCwpKiwuLDArLzUsKSw0LCwvLCo1LSw1LCkpKSwsMP/AABEIAM + sAUAMBIgACEQEDEQH/xAAcAAEAAgMBAQEAAAAAAAAAAAAABQYDBAcCAQj/xABBEAACAQIEBAMDB + woFBQAAAAABAgMAEQQSITEFBhNBIlFhMoGRByQzQmJxsRQjUmNygqGywfA0Q3Oi0VOTo7Ph/8QA + GgEAAwEBAQEAAAAAAAAAAAAAAAQFAwIGAf/EAC4RAAEDAgQBDAMBAAAAAAAAAAEAAgMEERIhMUE + TBSIzUWFxgZGhseHwMsHRI//aAAwDAQACEQMRAD8A7jSlVnEfKLg1kydRm1tnRGaMa2vmAsR3uL + 6Vy57W/kbLRkb5DZgJ7lZqVhwmLSVFkjYOjC4YbEVmrpZ6JWnxXi8WGj6kzhV2HmT5ADUnTb0rD + zBxxMJA0r6nZUuAWY7KPxv2AJ7VxXjPGZMRKZJDmkbt9VR2AHZR8T66mlKmpEWQzKp0HJ7qo4jk + 0b9fYFdeJfKs1x0IVVe5lOp9LIbD4n3VZeTebPy1HDLlkjy5gL5CHzZSpP7JFj5eori5jABJ1IG + 5/oO1XL5LP8a3n0H/AJ4aSpqmR8oDjkVXr+T4IqZzmNsRbPxtmusUpSrC8qqB8qPMDIEw0dx1AX + kINrpqFTXsxuTY7IR9aualyNdfuO/uI/Cr18qeEcYiOS3gaMID9pGckHy0YEedm8jVIb1qBWvJm + IOy9vyRE1tK1zdTe6uvIXOawZ4sRJaIIXjudQVOqKLXa4a4H2TYa6S2P+VaIfQwvJtq5CC3e2jN + f0Kgetcyiit/fbyr3Q2sexgY3bdD+SYZZTLJvtspTmPm6bFsvWyqiA5QgYLc7lrsbm1gDppm8zU + K+uocC/3E6ev/AMrJFnZ2VI3cqAxygbHQHU3OotXp8DIAScPIABcllRQAO5LMAB61i4vecTtUww + wQt4bSABssIAOg2vqfO341075KuFERy4hh9IQiaC+WO+Zgd7Fja36sHWufvwuRFWWZT0gVZ1j8T + dIFeoxZTZRlJIylmPbzrvUUQVQqgKqiwAFgANgANhT9DDnjOyicrVzXM4LN9T+gvdKUqsvNrW4j + w5J42jlXMrCxHf7wexG4Nc+5r+TyDD4LEyp1ZWADKGNwgDKTYIovYd2voD610qsONwayxvG4uki + sjDzDAgjT0NZuja7MjNbx1EkYs1xtuOtfnuVvGgPct7yB/Z91eZ8XlOxsACx8gSRf12v6Cs3F+F + vBI8Lay4dtDtnA9lvuZT8SR2rDFZiWGqso/hmuCK865mE2dtkvesl4gxMP5Zjy/uvet/hWI6eIi + cd2yN6rJp+Nj7quXFeHddVQ2KZ0Z1OzKpvlPmLgaVzmJisJ11QEX/0zp+ArqdfDzfBT6toc6/WA + VRcZzm+IwOMOFQxS4ZgCuh8AbVgLW2Ugi3Y1035NuLGbBRIws8SRjL3yMoMbW8reG/mja3Bqu4D + gEUDzSQrkec5nOpBIvqAdBqSffXvhuMkhfrks3Sdlew1ki7+EWBZTdl07Nb2jd6nqGMdYCwP33U + Ooge9tybkffZdKpXiKUMoZSGVgCCDcEHYgjcV7qyo6UpShCr3N3KKYxLiyTIDkk7fsPbdD8QdR3 + B4xjcDJBK6MhVwfHEbA3/TU7EHz2P33FfoiozjvLcGMVVnTNkN1YEqy+dmXUA9xsbC+1KT0wlzG + RVSi5RdTc05t9R3fxcFEBZMmxlbKB5GRgLaffXUaw4n5OTh3WaAticg+icoHBN7urABWa1gFYDd + jmvYV9w+LVyV1V19qNwVkX9pTrbyOx7E1JmgfGOcFVdWR1DuYdBbPVRHGuNmOQQllw4cXGJkBZN + N1VUBJk/asO+u1fOWMeWilkaRpfzxVWIChgCqoEW9gTcC1/aJFTOLRMv5wKVuNGFxc6AAWNzc2A + AuSbCpTl3l7qBJp4yiobxQMBYWtlkdMvhkGpC3sAQbBttIIxMAwNt1lKTzCG5Jz2H0ftTPLfD3g + wsUchuyrr5C5JyjU6C+UeijbapOlKujJQTmlKUoQlKV4mmCKWYhVUEliQAANySdAPWhC0uN4npx + 5mJVAwMjDsmuYnuF8yNt6p0uGw8vEIfyeU5JYpFkkSQsG6dmjjRyxs3iZiF7fwzTznEkyyi6nWO + Jh4VW91LKdDIbBiT7OwtY3T4dXFnUMN7MAdRsRfY+oqZLWtvhw3CoxUbrYr2KxY3h8OHx0XVxEi + wpG0gzN9G7EKM8ltFILEZu4bW2lWjlzFiQS5JTNGshVHJU7BcwzL7VmuLnXtra9VbD8PV5Y4EUW + ciSS+pyREXzZtTc5U17E+VYsFmwc8xg2imKyRAaPG1mGUD/MVX8JG4UIdLZdo52hmLDZpNvnzWU + kJLsN7kBdGpWDA45Jo1kiYOji6sNiP77Vnp1JpSlKEJVb5wxYbp4bcynO4/VxEE3+9iq+8+RqyV + ScXN1MTNJpYERKRb2Yr31H22b4W7UtVScOMnryTNNHjkA8Vr4/FZEJFixIVQe7MbAfHX7gaxS40 + 5hFGpmnI0jXf9tztGn2j7gdqjeNG8sErJLJBHP0mSJWLM8kb6gqb2XRdN2dhuutq5a4/hG/Nwp0 + CxtlKgZmtsWUkF7DZjm9KQgow4Bzza/qnpqotJDBot/l/gn5OrM7Z5pSDI4vl02RAdkXYD1JOpN + VvHYgDiGJQ3BYRsLjRsqKGynYkXW43Fwe9XTGYtYkZ3vlUXNgST6ADUsdgBqSQKgMdhEGC+cydG + V3aVGIDSJI5YqFUe2wXwlV3AYba1SnhD4iwZKfDKWSYzmtbl/GnDz9OxMOIa4A2jlNydAL5X330 + Zftm10rm+GdporTRGPMuozC9/TKbqRuDuNO4q58u8U60VmN5Ij05NLeIAG+wGoIaw0Ga3alaKYu + HDdqExWQhpxt0KlaUpVBILU4tj+hDJLbNkUkLe2Y9lv2ubD31RheGEDV2UBQL6u7EAC57sx3+1e + rJzdiNIogfpHzML65IrE6W1GYovb2hUNhAhlzzZRBhh1HZhcZz9GoHdh7Vt7mO2pqdUjiytj21K + oUx4UTpPALY5miXBcMDM6q0LRyZyCVMgYEsQBcgkk2+4aVWkUyDr4hHyTDpmYgaa+FWkBzKQdmA + VQwsDoDV7xmHbGRFHDRQuPEhA6ri4Nje4RbCxBBbX6ttZFoFKlCoKkZcpAy28rbW7WpuSDiC17B + KxzYDe11RcbjcXKsUbOiCJgzTEBmly3ynIRlU6hiTfxLoLVqx4yLq2VmxGIe40PUlawuRf2UXS9 + rqNNqn4eWIsLJI/Q68UjXIN3aFbKMqxtcNHdS3h8QzWANWnCBMi9LLksMuS2Sx2y5dLfdWDqZ8m + Ur8uoLdtQyPo259qrfDuXJZDeb80hAsim8lze4ZrWX9y5v9YWsbHg8EkSBI1CqLmw9dSfU+tZ6U + xHCyIWaEvJK+Q3cUpVL5+4kVaOKOSfrSghYo8uUgalm8BYnSwAPYm3nDK2Iw8JlnWWzEWDSkNts + A7iwtqdEtY32rmSYs0bddRwhwzNlKcax2bETSEErCBEoAJYkWLZR3LMVUW3KLW3wjhT9WOOYqwg + UTMo1+cTF99fZRR4R3LhrXAt84HwcyujshWFDnW+mdzqDlIuVFy1zYlrHtrK8MT5zjD5yR/wijr + inYS4yOGZ9l3O8ACNpyHupSlKU8lEqNwMxjxTwm3TdOrFYAWIa0y6drsji+t5G8tJKorjIyy4SQ + AXE2TbXLKrA/wAQD7q5KFN0pSuV9StfEcPjd0d0VmjvkJFyt8t7eXsg+4VsUoQlVfHPNh8RNNYf + k5MckjWJYjLkYLY3GQIJCSDowA7kWilCFU+Mc2tBiFHTD4bRJJFJLq7KXGVR7aBBc218QtfaprG + cTRMO84IdEjaUEEWYKpNwRpY23qB5i4VFhoI4oUIMuIRhdmNjH4ibk6AImVV2ACi1VrmPBMMHiU + jlaOJo3Z4gAVOUE+C+sdyBe2h10ub0vJUiN+F26ZjpzIzE3ZXLlzmgYiySIYZ8oYxE3BB+tG1hn + XsdAQdwNL/OF8PMhE6SmzSuzxtqh6buuZLaq1gBuVsu1/EIThWBSfGxCVA4EEri/wBVi0AzAjZr + Ei48z51eMDglhjSOMWRFCgXJNh5k6k+pruCQyRhx1XE8YjeWhZ6UpWqxSlKUISlKUIVW5sc/lGH + W/hyTvb7SmBQfg7D96q3zIL4WYfpLk/7hC/1qx81n5zh/9LEfzYWq9xptIU/6k0Y9y3c/y1Eq+n + 8lapeg81PcvR/OgfKKQfFof+KttU7gE3z1V/USt/vgH/NXGn6LoR4pCs6YpSlKcSiUpShCUpShC + rvNkQzQPbxZnQH0ZSSPii/Cqri2vioF/RWWQ/7UX+c/CrTzg9jhR5yuP/FLVOhnvxGVey4eP4l3 + J/EVGrB/qT2fCr0h/wAwO35Vn5WiBxUzfWSKJRrsJGlJFv3F+FW2q5ydD/iH0s0oAPe0aIpB/eB + +PrVjqjTC0TR2KfUG8rj2pSlKYWCUpShCUpShCrfOQ1wvpK3/AKpaq2GhInL2FnbEa97RjBqAfe + G09amOKz9XGSHtABCuvdsrSHbf2B+561rcO4NNIBNGFYHrLlZrf5u4sDuL32+jHnpLlBlkeGjQW + 9VTitHGwuO9/RWHlRoxGyK4L52d1uCQZCSNOwt/XyqdqjTcJnJGfDPddVeN0JU+YbMrKdO1TfLc + 2LuUxEQEaiySM46rWy6Mq3B7nNcbAZfrFqnkdYMc0iyVnY25c1wN1PUpSmkslKUoQlKUoQqfx3g + 80U7zxLnicZnjUEuH8ILBVF2uoA9Dc7HSxcE4f0II4yblV8RF7FjqxF9bFiT763qVm2NrXFw3Wj + pHOaGnZKUpWizSlKUIX//Z +l: Bedrock +loginshell: /bin/sh +objectclass: inetOrgPerson +objectclass: posixAccount +objectclass: top +sn: Flintstone +st: 345 Stonecave Road +uid: wilma +uidnumber: 1101 +userpassword: pebble + +# Entry 10: ou=Pets,o=Flintstones +dn: ou=Pets,o=Flintstones +objectclass: organizationalUnit +objectclass: top +ou: Pets + +# Entry 11: cn=Baby Puss Flintstone,ou=Pets,o=Flintstones +dn: cn=Baby Puss Flintstone,ou=Pets,o=Flintstones +cn: Baby Puss Flintstone +gidnumber: 1001 +givenname: Baby Puss +homedirectory: /home/users/flintstones/babypuss +jpegphoto:: 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 + zklF+QxU4BWaKltZeIooor1C//9k= +l: Bedrock +loginshell: /bin/sh +objectclass: inetOrgPerson +objectclass: posixAccount +objectclass: top +sn: Flintstone +uid: babypuss +uidnumber: 1010 + +# Entry 12: cn=Hoppy Rubble,ou=Pets,o=Flintstones +dn: cn=Hoppy Rubble,ou=Pets,o=Flintstones +cn: Hoppy Rubble +gidnumber: 1001 +givenname: Hoppy +homedirectory: /home/users/flintstones/hoppy +jpegphoto:: /9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBhQSEBUTEhIWExUWGBkaFhYXGBkX + FxcZFhcZFhgbFhwbGyYhHBwkGxgZIy8gJCcpLi4tGiAyNTEqOCYrMCkBCQoKDgwOGg8PGi8kHyU + 1LDI2Li4sKSwqLS80LTAsKSoxLDA2NDA1KiotLCkwLC8sLio0NTUsMi8sNSspLDQvNP/AABEIAL + cAeAMBIgACEQEDEQH/xAAcAAEAAgMBAQEAAAAAAAAAAAAABgcDBAUCAQj/xABEEAACAQMCBAMFB + AUICwEAAAABAgMABBESIQUGEzFBUWEHIjJxgRQjkaEzQlJykyU0Q1NisrPRFmNkc3SCkqKxwcIV + /8QAGgEBAAIDAQAAAAAAAAAAAAAAAAQFAgMGAf/EAC8RAAEDAgMFBwQDAAAAAAAAAAEAAgMEERI + hMQVBUWFxEyKBkaHB8DKx0fEUI0L/2gAMAwEAAhEDEQA/ALxpSlESlKURKUpREpSolzHzFK0xtL + RgjqAZ5yA3TDbqiKdjIRvvsowSDkCtcsjImGR5sAsmtLjYKW0qMcgcWaaCZXkaVobiWLW+nLBSC + vwgDs2Ow7VGuEc6unFZllOYZpjAuy/dtGxSM5CglWYMMEnBYY8a9D24Wuv9VreIuFg4hpseisyl + KVmvUpSlESlKURKUpREpSlESlKURKq9OKhbSe6B1GSSZ1J7ktKYogfkAg+Qq0KpvjKiK2FuBp6d + 3JHjucK8kyZ+alTvVLtpuKBg3YhfpYrfFJ2Ye/gCur7LOICGS6iZjoEcc2T2GnVHIx8ckKhPyP1 + hKgyw5Y+9KC5J76pCZM/MM2fpWZ+ImHXhivWhlg285dOn+6d6+y5Awi6mJCoo/WdjpRR8yRUaaY + yQQtb9XuDYKje8uYwDVXRypxM3FjbzHOZIkZs99WkavzzXWrm8t8K+zWkEH9XGinfO4UZ/PNdKu + ldqVapSlKxRKUpREpSlESlKURKUpRF5dwASSAAMknYADuTVN858XimuWNqeqjmN3ce6gkTMbYJA + 1aoyM4zuo+jmrm1+ISMqMVs1JCqD/ADjBwXfzj/ZXx7muO8qqBkhR2GSB9BVLtGsZYwNFzvPDpz + +ZqFNU2uxme5a3ENLFYyW1E6lKd107asnYDfH1rm3vDekVkLSSqGGsMQdKnYsCVIGAfFSPTapHw + a5szdRfayGiLaQB7ytKSqosmP1RqZsHb3a7HGrOwteJG2uEIhm0JCEOOlJLpGc5GkDcjuBntitV + DDIzBKw79D8+arXDG4AOBUi9nRKs66ABj3gjFVib3W0yQFmVWOSRJGSrip5UP9l1wr2CnAMkf3D + v4sISenk+WhwQN8Bu9TCujkeHuxBWKUpStaJSlKIlKUoiUpSiJUT9qF40fDJQhwZWjiJGchZXCM + Rjx0k1LK5vMfAkvLaS3clQ42Yd1YHUrD1DAH6Uz3Gy8OmSpVECgADAAwB5AbAVIuUbb7qWVQplL + siknYBMADIGQM5JA7/hjgXtpLbzG3uF0yjsR8Eq/txHxHmO6nY11+UuIiOVoW2Eh1xnw1gAOvzI + AYeeG9M8JVxSRhzHDMeo/G9RtmWjqbP1sfNZuV5ouI2iTTqkkgdtR0gGN0bYKR7wwNJGST23Ndi + Tg1uOo8iK2reR5TrJC75ZnJwB9O3pVZ3Qn4PezyxYeF2LtC2waNjkFCP1lJIzjb1zU84PztaXcQ + bXoDe6VmGgE+K5b3W+QJrXVQyt78JJjOeV8t9rcl0zQBbtBn9937W/a8EtwpMQKq51ZilkUMdhn + 3HAOwAz6V4sLno8Qt0iuJTqfpyxvI8qMrRSOMaycODGDkHOO/evR4pa26H72KNSc4DAkk+QBJZv + kCa6HKPBHkuDeSxGBAGEETLpkYvgPNKPBiFCqp3AznGanbGFVJOHYnYBxJt0+dVHqezay1hdTal + KV2Kq0pSlESlKURKUpREpSlEWjxjgsN1EYp4xImc4PcEdmUjdWGdiN6rXmX2dS20Zkhka4iXcqc + CeMLvqVwQHIwT2DdsZ7VbFYL3X0n6WOppbRntqwdOfTOK1yQsmGF4v7eKwcwO1VLy8WiurfpXsZ + lUj3ZohvgjvgbqxHfTkHyHYfOFcIAhWz4WWmaMvOTMoAOwTADqFZgXBAIxkDJqPT3ssMzxyhEkL + szxv90UZiWOkDI0E7jAxv3rb4Bx25W8jNoydYkRiIe+sgZlJDnAIQBc5GMYJztVFS0hhqg3PCDe + 26+djbrwyU8Q1pHfALbHvXGlr8dfBdnhHMU9lcMJIY5HjOHR4oY5ASucRyxKBqx4EHue1XLw+/S + aJJYzqR1DKfQjO/kfTwqqfaNyp9nuFnilGLiQ5iI3jJHUkeMjuDpIIPYuMHfFS/wBlh/k5fSWfH + 8Z6uY3P7R0bzcDMcbc/nmFWMLg4tKl9KUqQt6UpSiJSlKIlKUoiUrW4jxBIInlkOlEGWOCdvQDc + n0FRPjvP0iW8rQWc5YIxRnVNOQM5Zepqx6Yz6Vg+SNlsbgL8SAsg1ztApfe3axRvI+dKKzNgZOF + BY4HjsKr3mfnab7MBNbSW6u8YLxTK7aS2WQ6dLBiBgac9zuO9Qu7uZbgE3FzLMHG41skRB3wEQh + dP4/WsDcPQkEqTg5GWY4PmMt3qnqNqC9otM73Gfhnl4hQ/5sbb5ErLgszu+cuc4Zi5UDZU1MSSF + H55rNw/iMdrc2075CRy5bSpY+9G6bKNycsBtXitXifwA+Txn/vA/wDdVMMzhM2Q5m6r2yEyYzqu + vxzjj3k5nkBRQNMUZOemnc58NbEAtjyA3xk2N7NbUpwyHV+vrkH7srtIuf8AlYVVaWL3EiW0X6S + YlQf2Vx945x2AXO/mQPGr3tbdY0VFGFVQqjyCjA/IVfbPL5Mc7/8AVh4D208lOpsTryO3rLSlKs + 1MSlKURKUpREpSotxvmOb7Q9tbhEKIjPLIC/6TXgIgK5I05JZvoa1yyshYZJDYD9LJrS82Cy8+/ + wA1TyNxb6vl1l7/AFxUM5n5mMbGCAjq4y7ndYVPp4uRuFOw7nbAOTnHiV0towe6DlyqovRQanJB + XBBBGCNWd8BT3qGXVs5jYK+ZGOpnOxdictqI7Z7bdhjyrma+SCreyVjrgXGh4657l7PUOpGdmMn + H0C0ophp6SS7N+ibOGz8Whs4Iz4bdj6DPSs2BQEFt/wBoktnsQc+IIxXNsbtVOjQ3UUaQjAFgPA + CQDdPUnb8q6dtDpXB3JJJx2ydzj0qPNll8PNUUiy1p8YXMLYOD7pB74IdSK3K1OLH7lvmo/F1FY + 0wvMwcx91hH9YVycq8kQWWWUtLM3xTSYL4291cABUyM6R5+NSKvgr7XaaCwV4BbRKUpRepSlKIl + KUoiVD+YbXp3yy4GmeMRk+PUhLOo+sbv/D9RUwqu+Z+MT3XWSJYYo7eUgPKZOoHhwxcBQAq42wc + 6lJPY1B2iI3Uz2yusDlfPXUacwt0GIPBaovzPe9W7K59y3XT6dRxqc/RNI+rVG5L2N3CyShFb4I + 9WlpAezN44PgPHvvnA3LYmWPXIPemzI49ZDqx8gCF+QrhX3LYN011K46SYfSM59wDY+m1c5TsY3 + uONrDLry6lVE0ommc8np7LDwqdGDtcrFArNiH3RG4wTkggatttz41IuHTlkwxy6Eqx8yvj9Rg/W + ove2K8SlWSKTCqAsitsy7k5A7b5/KpJw5NLzKOwZAP4SVIqg0jgdSOG713+a1TAW58OC3q8opa4 + tUUElrq32G5wsqyMfoEJ+leq6/IHCzc8TV/6OzGpj5zSKVRfohYn5isNnxGSobyz8lhTtxSBXJS + lK6xXKUpSiJSlKIlKUoiVVXtOuRHLcC3Da3gUXIyAmmUmGN18eqNxsMEYyQQKtWoP7W7BDY9Ur9 + 4kkKqw2Ol54wynzU7HB8QD3rVMztI3Ny8eRv+ua9DsOarwDG1cSLgOmeaaSQukisNGD8JG+fPA2 + GK7dK41kjmXtvVA15bouZwTgMVsD0yW14JZiDkDtjAAxvWxw/fqN+1I2PkuEH92vvDjiMA/qll+ + isQPyxWzbctXf/wCabogQxrH1FJw0khkYMNK9lB1/Ed9tl7VMjglqXOtmcrk/OS3Bj5CV9tbaS4 + nFtbANMwySfhiTsZJPQZGB3Y4Aq5eV+XI7G2WCMlsZZ3PxSO27O3qT+AwPCq79lduEv5Aq7fZzk + 9yS0oyWJOT8NW1V5s+FscIc3/X5IU+mY0MuN6UpSp6kpSlKIlKUoiUpSiJUP9rA/kuT/eQf48dT + CoF7UuMxmJbNSGkZ0dwP1ERtYLepZQAPmfCsXuDGFx0AKxeQ1pJUBrHczhEZz2UE/PHgPU9qyVt + 8CsPtF9bQkZXX1XH9iD399twX0DHjk1x1NF20rWcftv8ARUsbMbg1cee0kginSbHUTqa8ds6NZA + +WcfSrS5jjI4AFGxEFuPziFV7zsfv+JfvS/wCAtWdxvhzz8HEcSa3MUJVQQCSvTbYkgdge5roqV + gBnwjf+VYxCxeAor7L2/lGYf7Mn+M/+VWpVBG7a2lLF5rSQqFOrXASuSwB1AA7k4xmvSTyEfzm4 + Yf8AESn/AO61RVzKeJscrXAgcOZ4kLBlQI2BrgVfTMB3OK415zrYxDL3kA9OqhO/kqkk/hVNTQB + /0mZMduozSYz5aycdh+FfYoFX4VVf3QB/4FYO2vGNGE+NvyvDWjcFb9lz7YStpS7iz5M2jOPLXj + P0rv1+fZm1BlKhiMEK24YHt37diPnU59lPMLFntHkLroWW21ElhH8Lx5J3Ce4QO+H9KlUtc2oOE + ix63ut0NR2hsRZWTSlKnqStPjEsy28jW6LJMEYxoxwrNjYE+Wfl8x3qpBz5xIkj7TGCpwytbAMr + DYhhryCD4Grnrgcw8kW14dbho5RsJYiEfHkcghh+8DWqVsjm/wBbsJ6Aj19vVa5GuI7psq2m5u4 + g4w95pH+qiSM/idRH0IrkxxBc47k5YkksxPcsTuT6mpNe+zO9jP3UkFwvm5aF/DvgMpPftitb/Q + PiP9RCPnPt+UdUdRT10ps/MciLeWX2UCSKd2RzXFqa+yfhOrq3pzhvuYe2DGhBdx4+9JkeGyDvk + Y1+FeyeWQg30yhNswwZGrzDyNvp9FAz51ZVtbLGioihEUAKqjAUDYAAdhU2goTAS+TXhw+clvp6 + csOJ2qojjzNLLfZ3LTXCjw7Exr+QAqwOEe0y1S3iRhOXWNFYdFx7yqAdyAO4865nHfZndCWWS1l + ikV3Z+nLlGBkYswDqCCMk4yuceNRq44JeRHTLYz584lE6nfGQYyT+IB9K8P8AJgfI5jA4ON/vuG + e9Y/2xucQL3U0uPalC4K/YpnX+30gDg7HBc1E+KcXgmDEcKtY3bGW6jKfX9EinOPHNceTiCKSHP + TIOCJFaMgjuCHAOdq8Di8J/po/+tf8AOor9o1YywW8D7rU6om4ei8XFnIx9xhD5BXlkA/ikmtnl + zhpnuEgku2Tq5EcirFIpdQToOUGCQDjcjbFaB4nEsi6ZVYPnUobWQcZBUDJ3xjA8xUz5M5BnluF + uLhGghjlWSNGGmV3QDBKke6moE77nPh47KTtZpQZGNLd92NHtqsog57swLdAuxb+x9dRMl9O22B + oSGM987nQ1d7ln2eWti/Uj6kkmCoeVy5VTjKqAAoBwOwzUmryxO2Bnf8B51ctjY091oHQAKeGNb + oF6pSlZLJKUpREpSlESlKURKUpRF5ZARg7g9x4VqPwSA94Ij840/wAqUr25CL1bcJhjOqOGND5q + iqfxArbpSvESlKURKUpRF//Z +l: Bedrock +loginshell: /bin/sh +objectclass: inetOrgPerson +objectclass: posixAccount +objectclass: top +sn: Rubble +uid: hoppy +uidnumber: 1009 diff --git a/doc/ldif-Simpsons b/doc/ldif-Simpsons new file mode 100644 index 0000000..8b6735f --- /dev/null +++ b/doc/ldif-Simpsons @@ -0,0 +1,496 @@ +# LDIF Export for o=Simpsons +# Server: C5: OpenLDAP 2.3.27: config (c5dev.leenooks.vpn) +# Search Scope: sub +# Search Filter: (objectClass=*) +# Total Entries: 11 +# +# Generated by phpLDAPadmin (http://phpldapadmin.sourceforge.net) on April 26, 2011 9:05 pm +# Version: 1.2.0.5 + +#version: 1 + +# Entry 1: o=Simpsons +dn: o=Simpsons +o: Simpsons +objectclass: organization +objectclass: top + +# Entry 2: cn=Simpsons-GOUN,o=Simpsons +dn: cn=Simpsons-GOUN,o=Simpsons +cn: simpsons-goun +objectclass: groupOfUniqueNames +objectclass: top +uniquemember: cn=Bart Simpson,ou=People,o=Simpsons +uniquemember: cn=Homer Simpson,ou=People,o=Simpsons +uniquemember: cn=Lisa Simpson,ou=People,o=Simpsons +uniquemember: cn=Maggie Simpson,ou=People,o=Simpsons +uniquemember: cn=Marge Simpson,ou=People,o=Simpsons + +# Entry 3: cn=Simpsons-PG,o=Simpsons +dn: cn=Simpsons-PG,o=Simpsons +cn: simpsons-pg +gidnumber: 1000 +memberuid: maggie +memberuid: marg +memberuid: lisa +memberuid: homer +memberuid: bart +objectclass: posixGroup +objectclass: top + +# Entry 4: ou=People,o=Simpsons +dn: ou=People,o=Simpsons +objectclass: organizationalUnit +objectclass: top +ou: People + +# Entry 5: cn=Bart Simpson,ou=People,o=Simpsons +dn: cn=Bart Simpson,ou=People,o=Simpsons +cn: Bart Simpson +gidnumber: 1000 +givenname: Bart +homedirectory: /home/users/simpsons/bart +jpegphoto:: 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 +l: Springfield +mail: bart.simpson@example.com +o: The Simpsons +objectclass: inetOrgPerson +objectclass: posixAccount +objectclass: top +objectclass: shadowAccount +sn: Simpson +st: 742 Evergreen Terrace +telephonenumber: +1 939 555 3126 +uid: bart +uidnumber: 1000 +userpassword: eatmyshorts + +# Entry 6: cn=Homer Simpson,ou=People,o=Simpsons +dn: cn=Homer Simpson,ou=People,o=Simpsons +cn: Homer Simpson +gidnumber: 1000 +givenname: Homer +homedirectory: /home/users/simpsons/homer +jpegphoto:: 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 +l: Springfield +mail: homer.simpson@example.com +o: The Simpsons +objectclass: inetOrgPerson +objectclass: posixAccount +objectclass: top +objectclass: shadowAccount +sn: Simpson +st: 742 Evergreen Terrace +telephonenumber: +1 939 555 3126 +uid: homer +uidnumber: 1001 +userpassword: mmm.beer + +# Entry 7: cn=Lisa Simpson,ou=People,o=Simpsons +dn: cn=Lisa Simpson,ou=People,o=Simpsons +cn: Lisa Simpson +gidnumber: 1000 +givenname: Lisa +homedirectory: /home/users/simpsons/lisa +jpegphoto:: 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 + zt1Zj1J/wDtsTcHQxCJtll8Rr3105kOg4DkF//Z +l: Springfield +mail: lisa.simpson@example.com +o: The Simpsons +objectclass: inetOrgPerson +objectclass: posixAccount +objectclass: top +objectclass: shadowAccount +sn: Simpson +st: 742 Evergreen Terrace +telephonenumber: +1 939 555 3126 +uid: lisa +uidnumber: 1002 +userpassword: brains + +# Entry 8: cn=Maggie Simpson,ou=People,o=Simpsons +dn: cn=Maggie Simpson,ou=People,o=Simpsons +cn: Maggie Simpson +gidnumber: 1000 +givenname: Maggie +homedirectory: /home/users/simpsons/maggie +jpegphoto:: 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 +l: Springfield +mail: maggie.simpson@example.com +o: The Simpsons +objectclass: inetOrgPerson +objectclass: posixAccount +objectclass: top +objectclass: shadowAccount +sn: Simpson +st: 742 Evergreen Terrace +telephonenumber: +1 939 555 3126 +uid: maggie +uidnumber: 1003 +userpassword: dummy + +# Entry 9: cn=Marge Simpson,ou=People,o=Simpsons +dn: cn=Marge Simpson,ou=People,o=Simpsons +cn: Marge Simpson +gidnumber: 1000 +givenname: Marge +homedirectory: /home/users/simpsons/marge +jpegphoto:: R0lGODlhhABwAIcAAAAAAAICBQIEAgUFAQUFBAICCwYICw4EBAsJAgkJCAgJDQ4N + CA0NDQECEgEDGwsMEA4QDhMEAhILAhANARANBBYODhwCARoJARMQAhIQBBURARQRBBcVAhIQCBE + QDRQSDhgSABkUARwTARwVAB0YARISERsbGwIEIgIEKgEENAAEPAQINAQIOiMBASwCAiIbATUDAz + 0CAicgAiogASsjBCskAS0jAS0kAS4oBTEnATQqAjkuATswAz0xATwxBj80BCIiIikpKS8vLzQ0N + Dk5OT09PQIFQwEGTAQJRAMITQEFUQEGWwMIUwMIWgIIYwIIbAAGcQAGfwEIdAEIfEICAksBAVIB + AV8AAEAzAUE1AUU2AUU3BEU4AUw8AVA+AWEBAWsCAnIBAXwBAU5ABFRDAlhGAVxHAltJAWFNAWB + NBGJQBGVRAmpUAW1YAW1YBHFZAHFaBHFcAnRaAnVdAXVeBHleAHdgAntiAURERElJSU1NTVJSUl + lZWV1dXWFhYWVlZWxsbHJycnV1dXt7ewAIg4QBAYwBAZIAAJsCAqICAqsCArQDA7sCAoFlAYRpA + ohqAIptAIxuAo1wApN0AZZ5Bph3AJp7AaB/AYF/f8ECAssBAdMEBNwBAeICAuwBAfIBAf4AAJ6A + AqGAAaODBKaCAKSCBKaEAKqGAayHAK2JAbKMAraRAruTAcKZAcOaBMadAMidAMqgAsugBM2hAc6 + iBM6kAtGlAdOoAdqsAdyuAd6wAOCuAOCxAOK0AOS1AOi3AOm5AO27AO+9AIKCgoWFhYuLi42NjZ + KSkpycnIyapI6cpZCdp5GfqJajrJyosKOjo6qqqqWwt6WwuK23vrS0tLm5ub6+vrnCyLzEysPDw + 8DHzcjIyM3NzcTL0MXM0cjO08nQ1NPT09DW2tfb39fc39jY2N3d3dzg497i5d/k5uHh4eDj5uDk + 5uXl5eHl6OTn6eXo6ufq7Onp6ers7uzs7Ovt8O3u8O3w8fHx8fHz9PP19vX19ff4+Pn5+f39/QA + AACH5BAAAAP8ALAAAAACEAHAAAAj/AAEIHEiwoMGDCBMqXMiwocOHDf1JnEixosWL/p41mEKoo8 + ePIEOKHEmyZEgUgzCqXIlRIMuXF/2gMEmzpk2TUhjQg8nzosuePPGVcHKzqNGaKI4BXervJ9OV+ + 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 + lBDxlFAZlVI5lVIZEAA7 +l: Springfield +mail: marge.simpson@example.com +o: The Simpsons +objectclass: inetOrgPerson +objectclass: posixAccount +objectclass: top +objectclass: shadowAccount +sn: Simpson +st: 742 Evergreen Terrace +telephonenumber: +1 939 555 3126 +uid: marge +uidnumber: 1004 +userpassword: homie + +# Entry 10: ou=Pets,o=Simpsons +dn: ou=Pets,o=Simpsons +objectclass: organizationalUnit +objectclass: top +ou: Pets + +# Entry 11: cn=Santas Little Helper,ou=Pets,o=Simpsons +dn: cn=Santas Little Helper,ou=Pets,o=Simpsons +cn: Santas Little Helper +givenname: Santas Little Helper +jpegphoto:: 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 + 0rJcGRsMDnOT1q10pXgAAwJ6SScmf//Z +l: Springfield +o: The Simpsons +objectclass: inetOrgPerson +objectclass: top +sn: Simpson +st: 742 Evergreen Terrace +telephonenumber: +1 939 555 3126 diff --git a/doc/ldif-example-com b/doc/ldif-example-com new file mode 100644 index 0000000..043136a --- /dev/null +++ b/doc/ldif-example-com @@ -0,0 +1,139 @@ +# LDIF Export for dc=example,dc=com +# Server: C5: OpenLDAP 2.3.27: config (c5dev.leenooks.vpn) +# Search Scope: sub +# Search Filter: (objectClass=*) +# Total Entries: 15 +# +# Generated by phpLDAPadmin (http://phpldapadmin.sourceforge.net) on April 26, 2011 9:25 pm +# Version: 1.2.0.5 + +#version: 1 + +# Entry 1: dc=example,dc=com +dn: dc=example,dc=com +dc: example +objectclass: dNSDomain + +# Entry 2: c=AU,dc=example,dc=com +dn: c=AU,dc=example,dc=com +c: AU +description: Australia +objectclass: country +objectclass: top + +# Entry 3: c=CN,dc=example,dc=com +dn: c=CN,dc=example,dc=com +c: CN +objectclass: country +objectclass: top + +# Entry 4: cn=你好,c=CN,dc=example,dc=com +dn:: Y2495L2g5aW9LGM9Q04sZGM9ZXhhbXBsZSxkYz1jb20= +cn:: 5L2g5aW9 +gidnumber: 200 +objectclass: posixGroup +objectclass: top + +# Entry 5: c=DE,dc=example,dc=com +dn: c=DE,dc=example,dc=com +c: DE +description: Germany +objectclass: country +objectclass: top + +# Entry 6: c=ES,dc=example,dc=com +dn: c=ES,dc=example,dc=com +c: ES +objectclass: country +objectclass: top + +# Entry 7: c=FR,dc=example,dc=com +dn: c=FR,dc=example,dc=com +c: FR +description: France +objectclass: country +objectclass: top + +# Entry 8: c=GB,dc=example,dc=com +dn: c=GB,dc=example,dc=com +c: GB +description: Great Britain +objectclass: country +objectclass: top + +# Entry 9: c=IT,dc=example,dc=com +dn: c=IT,dc=example,dc=com +c: IT +objectclass: country +objectclass: top + +# Entry 10: c=NO,dc=example,dc=com +dn: c=NO,dc=example,dc=com +c: NO +description: Norway +objectclass: country +objectclass: top + +# Entry 11: c=RU,dc=example,dc=com +dn: c=RU,dc=example,dc=com +c: RU +objectclass: country +objectclass: top + +# Entry 12: cn=Человеки,c=RU,dc=example,dc=com +dn:: Y2490KfQtdC70L7QstC10LrQuCxjPVJVLGRjPWV4YW1wbGUsZGM9Y29t +cn:: 0KfQtdC70L7QstC10LrQuA== +objectclass: inetOrgPerson +objectclass: top +sn:: 0KfQtdC70L7QstC10LrQuA== + +# Entry 13: cn=Дед Логопед,cn=Человеки,c=RU,dc=example,... +dn:: Y2490JTQtdC0INCb0L7Qs9C+0L/QtdC0LGNuPdCn0LXQu9C+0LLQtdC60LgsYz1SVSxkYz1 + leGFtcGxlLGRjPWNvbQ== +cn:: 0JTQtdC0INCb0L7Qs9C+0L/QtdC0 +givenname:: 0JTQtdC0 +jpegphoto:: /9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgMCAgMDAwMEAwMEBQgFBQQEBQoH + BwYIDAoMDAsKCwsNDhIQDQ4RDgsLEBYQERMUFRUVDA8XGBYUGBIUFRT/2wBDAQMEBAUEBQkFBQk + UDQsNFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBT/wA + ARCAAwAEADASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAA + gEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcY + GRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipK + TlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8v + P09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFB + AQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygp + KjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJm + aoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9 + oADAMBAAIRAxEAPwD9A/gj8Nx8IvhN4V8KPKsr6PpkNnJIv3WZV+Y/QnNc/wCINDutR1Q/Mux2y + xHTFeTaP+17d+IfDN94w02ODW/ANsF+0apZKZHtHOMxyKPmDDK8Ed69G8IfEHR/ij4aTxD4cv47 + 60VMkxEjacdGBAKn2IoA5Txn4KuIzO0v+rToyDjmvlL486HBb2jhdzEdNvrzXtvxB+NsNjeXdpF + M7JFlQpbv6GvlD4qfE6/1Ca4nktWkgI24Tkd+goA+b/ESSRXkoJIwejCuWuZFfOQAfUV1HiC9vN + VuGmj064RJOjvC4HHpxXGXwntZT50Tp6FlIoAy9UQLE5A7VzDJ5h/Guj1aUi1ZvXisTyTGuDwR1 + oA/cX/gnT8CPFfwl/Z21nR/Gugpo9/rOpSXS6df7XdrdoUQCZATtJKt8p5xjPWvefh98HdE8D3d + 3qcNnb2lzPGYXisVaO2EI6IIySOPWvRulYXjjWYvD/hLVdQmfy4oLd3ZvQAUAfjx+0H42kHxR8T + Lajybdb2VY4lPAAY4FefeGbx9Q1yzlu7f+0rbdmSEt8x9QAeK1PiQi614n1LUlbi4neXn3Ymud0 + m9l0G6jlVC6E5OOoPqKAIPFPhq88O+Mr7V9J1i/trC4kMyWaiRHyf4Sn3BjpnJGKpT6yNe0lk1W + 0jN2DgTBAN49T716NqOrXXiC1807dm3rIcV5j4mb7KrZYbsHkUAeW+JIEt7hIYwCqtvwPb/ACKw + XBySec1v39nPc3DTshCNwmR1HrVGfT2jIJHFAH9GkfxQspdds7KKOWaGZtr3CITHEMcMzdAM4/O + uR/aP1qLXPhtqOiaVdQzXV4hQ/PhQMcknFeXeAdRnSzRxG88UxGx9mVJPTnHGcGuk1+4h1LSnij + RHkYlVjk4kVvQHHrQB+f8A4m/Zy8Y380kOnapokEZGS91cvk+wAQ1zq/svfEC5/cp4i0O2KHaR5 + UzsT/3yM19ea9aW8R3y3ElndKSWhdBtkB6HBxj6g1w+tarcxRRXLxS3mmxuE3ohCA9SNwwwP1oA + 8Ksv2WvHGAl143s40xjba6cznn/eYVFrX7LRuYUjbxa817nkTWB2MPqrEj9a9jXxZqt4DEkqoVb + 93DKN3b+8MEHjjI9Kq6j421mwSNL64ESSqytuYOj+gYdvqKAPAvF/wOv9EtR5z2tyEG3fDuX9GU + YryPXfB15axs62ryxhtu+Ebxn6rmvpXW9cilF00+piYDO17cOVK9Mc9vqO1eQ+LNVSOd3g3NAvJ + MmUJ+vP9aAP/9k= +objectclass: inetOrgPerson +objectclass: top +sn:: 0JvQvtCz0L7Qv9C10LQ= + +# Entry 14: c=SE,dc=example,dc=com +dn: c=SE,dc=example,dc=com +c: SE +objectclass: country +objectclass: top + +# Entry 15: c=US,dc=example,dc=com +dn: c=US,dc=example,dc=com +c: US +description: United States of America +objectclass: country +objectclass: top diff --git a/doc/ldif-example.com b/doc/ldif-example.com new file mode 100644 index 0000000..8c6cdfb --- /dev/null +++ b/doc/ldif-example.com @@ -0,0 +1,165 @@ +# LDIF Export for dc=example.com +# Server: C5: OpenLDAP 2.3.27: config (c5dev.leenooks.vpn) +# Search Scope: sub +# Search Filter: (objectClass=*) +# Total Entries: 23 +# +# Generated by phpLDAPadmin (http://phpldapadmin.sourceforge.net) on April 26, 2011 9:13 pm +# Version: 1.2.0.5 + +#version: 1 + +# Entry 1: dc=example.com +dn: dc=example.com +dc: example.com +objectclass: dNSDomain + +# Entry 2: cn=group,dc=example.com +dn: cn=group,dc=example.com +cn: group +gidnumber: 100 +objectclass: posixGroup +objectclass: top + +# Entry 3: ou=Bad DNs,dc=example.com +dn: ou=Bad DNs,dc=example.com +objectclass: organizationalUnit +ou: Bad DNs + +# Entry 4: c=double plus \2B\2B,ou=Bad DNs,dc=example.com +dn: c=double plus \2B\2B,ou=Bad DNs,dc=example.com +c: double plus ++ +objectclass: country + +# Entry 5: c=end dollar$,ou=Bad DNs,dc=example.com +dn: c=end dollar$,ou=Bad DNs,dc=example.com +c: end dollar$ +objectclass: country + +# Entry 6: sn=sign@at+uid=multi-mixed,ou=Bad DNs,dc=example.com +dn: sn=sign@at+uid=multi-mixed,ou=Bad DNs,dc=example.com +cn: Test +objectclass: inetOrgPerson +sn: sign@at +uid: multi-mixed + +# Entry 7: uid=angle\3Cleft,ou=Bad DNs,dc=example.com +dn: uid=angle\3Cleft,ou=Bad DNs,dc=example.com +cn: Test +objectclass: inetOrgPerson +sn: Test +uid: angleright + +# Entry 9: uid=brace(left,ou=Bad DNs,dc=example.com +dn: uid=brace(left,ou=Bad DNs,dc=example.com +cn: Test +objectclass: inetOrgPerson +sn: Test +uid: brace(left + +# Entry 10: uid=brace)right,ou=Bad DNs,dc=example.com +dn: uid=brace)right,ou=Bad DNs,dc=example.com +cn: Test +objectclass: inetOrgPerson +sn: Test +uid: brace)right + +# Entry 11: uid=colon:full,ou=Bad DNs,dc=example.com +dn: uid=colon:full,ou=Bad DNs,dc=example.com +cn: Test +objectclass: inetOrgPerson +sn: Test +uid: colon:full + +# Entry 12: uid=colon\3Bsemi,ou=Bad DNs,dc=example.com +dn: uid=colon\3Bsemi,ou=Bad DNs,dc=example.com +cn: Test +objectclass: inetOrgPerson +sn: Test +uid: colon;semi + +# Entry 13: uid=multi+uid=sign@at,ou=Bad DNs,dc=example.com +dn: uid=multi+uid=sign@at,ou=Bad DNs,dc=example.com +cn: Test +objectclass: inetOrgPerson +sn: Test +uid: multi +uid: sign@at + +# Entry 14: uid=multi+uid=value,ou=Bad DNs,dc=example.com +dn: uid=multi+uid=value,ou=Bad DNs,dc=example.com +cn: Test +objectclass: inetOrgPerson +sn: Test +uid: multi +uid: value + +# Entry 15: uid=quote\22double,ou=Bad DNs,dc=example.com +dn: uid=quote\22double,ou=Bad DNs,dc=example.com +cn: Test +objectclass: inetOrgPerson +sn: Test +uid: quote"double + +# Entry 16: uid=quote'single,ou=Bad DNs,dc=example.com +dn: uid=quote'single,ou=Bad DNs,dc=example.com +cn: Test +objectclass: inetOrgPerson +sn: Test +uid: quote'single + +# Entry 17: uid=sign%percent,ou=Bad DNs,dc=example.com +dn: uid=sign%percent,ou=Bad DNs,dc=example.com +cn: Test +objectclass: inetOrgPerson +sn: Test +uid: sign%percent + +# Entry 18: uid=sign\2Bplus,ou=Bad DNs,dc=example.com +dn: uid=sign\2Bplus,ou=Bad DNs,dc=example.com +cn: Test +objectclass: inetOrgPerson +sn: Test +uid: sign+plus + +# Entry 19: uid=sign\2Ccomma,ou=Bad DNs,dc=example.com +dn: uid=sign\2Ccomma,ou=Bad DNs,dc=example.com +cn: Test +objectclass: inetOrgPerson +sn: Test +uid: sign,comma + +# Entry 20: uid=sign\3Bsemicolon@at,ou=Bad DNs,dc=example.com +dn: uid=sign\3Bsemicolon@at,ou=Bad DNs,dc=example.com +cn: Test +objectclass: inetOrgPerson +sn: Test +uid: sign;semicolon@at + +# Entry 21: uid=sign\3Dequal,ou=Bad DNs,dc=example.com +dn: uid=sign\3Dequal,ou=Bad DNs,dc=example.com +cn: Test +objectclass: inetOrgPerson +sn: Test +uid: sign=equal + +# Entry 22: uid=sign?question,ou=Bad DNs,dc=example.com +dn: uid=sign?question,ou=Bad DNs,dc=example.com +cn: Test +objectclass: inetOrgPerson +sn: Test +uid: sign?question + +# Entry 23: uid=sign@at,ou=Bad DNs,dc=example.com +dn: uid=sign@at,ou=Bad DNs,dc=example.com +cn: Test +objectclass: inetOrgPerson +sn: Test +uid: sign@at diff --git a/doc/phpldapadmin-demo.conf b/doc/phpldapadmin-demo.conf new file mode 100644 index 0000000..3ed4063 --- /dev/null +++ b/doc/phpldapadmin-demo.conf @@ -0,0 +1,107 @@ +include /etc/openldap/schema/uidpool.schema +include /etc/openldap/schema/sudo.schema +include /etc/openldap/schema/autofs.schema + +TLSCACertificateFile /etc/openldap/pla/ca-bundle.crt +TLSCertificateFile /etc/openldap/pla/slapd.crt +TLSCertificateKeyFile /etc/openldap/pla/slapd.key + +access to dn.regex="o=Simpsons$" attrs=userpassword + by anonymous auth + by self write + by * none + +access to dn.base="" by * read +access to dn.regex="dc=example.com$" + by dn.regex="o=Flintstones$" none + by dn.regex="o=Simpsons$" none + by * write +access to dn.regex="dc=example,dc=com$" + by dn.regex="o=Flintstones$" none + by dn.regex="o=Simpsons$" none + by * write +access to dn.regex="o=Flintstones$" + by dn.regex="o=Simpsons$" none + by self write + by dn.regex="cn=.*,ou=People,o=Flintstones" write + by * read +access to dn.regex="o=Simpsons$" + by dn.regex="o=Flintstones$" none + by self write + by dn.regex="cn=.*,ou=People,o=Simpsons" write + by * read +access to * + by * read + +authz-policy any + +database ldbm +suffix "dc=example.com" +rootdn "cn=Manager,dc=example.com" +rootpw NotAllowed +directory /var/lib/ldap/base-example.com +dirtyread +cachesize 2000 +checkpoint 32 1 +# Indices to maintain for this database +index objectClass eq,pres +index ou,cn,mail,surname,givenname eq,pres,sub +index uidNumber,gidNumber,loginShell eq,pres +index uid,memberUid eq,pres,sub +index nisMapName,nisMapEntry eq,pres,sub + +database ldbm +suffix "dc=example,dc=com" +rootdn "cn=Manager,dc=example,dc=com" +rootpw NotAllowed +directory /var/lib/ldap/base-example-com +dirtyread +cachesize 2000 +checkpoint 32 1 +# Indices to maintain for this database +index objectClass eq,pres +index ou,cn,mail,surname,givenname eq,pres,sub +index uidNumber,gidNumber,loginShell eq,pres +index uid,memberUid eq,pres,sub +index nisMapName,nisMapEntry eq,pres,sub + +database ldbm +suffix "o=Simpsons" +rootdn "cn=Manager,o=Simpsons" +rootpw NotAllowed +directory /var/lib/ldap/base-simpsons +dirtyread +cachesize 2000 +checkpoint 32 1 +# Indices to maintain for this database +index objectClass eq,pres +index ou,cn,mail,surname,givenname eq,pres,sub +index uidNumber,gidNumber,loginShell eq,pres +index uid,memberUid eq,pres,sub +index nisMapName,nisMapEntry eq,pres,sub + +sasl-regexp uid=(.*),cn=(.*),cn=gssapi,cn=auth + ldap:///dc=example.com??sub?(&(uid=$1)(objectClass=inetOrgPerson)) + +database bdb +suffix "o=Flintstones" +rootdn "cn=Manager,o=Flintstones" +rootpw NotAllowed +directory /var/lib/ldap/base-flintstones +dirtyread +cachesize 2000 +checkpoint 32 1 +# Indices to maintain for this database +index objectClass eq,pres +index ou,cn,mail,surname,givenname eq,pres,sub +index uidNumber,gidNumber,loginShell eq,pres +index uid,memberUid eq,pres,sub +index nisMapName,nisMapEntry eq,pres,sub + +database monitor +access to * by * read + +database config +access to * by * read +rootdn cn=admin,cn=config +rootpw password diff --git a/doc/pla-test-i18n.ldif b/doc/pla-test-i18n.ldif new file mode 100644 index 0000000..1c9e76f --- /dev/null +++ b/doc/pla-test-i18n.ldif @@ -0,0 +1,66 @@ +# This is a Test-File for characters / encoding +# 1. Change the +# ,dc=example,dc=com +# to avalue for your organisation +# 2. Import it with phpldapadmin +# +# pla-i18n, example.com +# +dn: ou=pla-i18n,dc=example,dc=com +ou: pla-i18n +objectClass: top +objectClass: organizationalUnit + +# pl, pla-i18n, example.com +dn: ou=pl,ou=pla-i18n,dc=example,dc=com +description:: IGRvcMOza2k= +description:: xITFu8WaxbnEhsWDxYHDk8SYIMSFxbzFm8W6xIfFhMWCw7PEmQ== +description:: V3NrYXrDs3drYQ== +objectClass: top +objectClass: organizationalUnit +ou: pl + +# ru, pla-i18n, example.com +dn: ou=ru,ou=pla-i18n,dc=example,dc=com +description:: 0LfQstGD0YfQuNGCINC/0L7QtNC+0LHQvdC+ +description:: 0J/RgNC+0YHRgtCw0Y8g0YTQvtGA0LzQsCDQv9C+0LjRgdC6 +objectClass: top +objectClass: organizationalUnit +ou: ru + +# jp, pla-i18n, example.com +dn: ou=jp,ou=pla-i18n,dc=example,dc=com +ou: jp +objectClass: top +objectClass: organizationalUnit +description:: SVNPLTIwMjItSlDjga7lpJrlm73nsY3oqIDoqp7jgbjjga7mi6HlvLXmgKc= + +# pt-br, pla-i18n, example.com +dn: ou=pt-br,ou=pla-i18n,dc=example,dc=com +ou: pt-br +objectClass: top +objectClass: organizationalUnit +description:: VmVyIGFzIHJlcXVpc2nDp8O1ZXMgZW0gYWJlcnRv + +# de, pla-i18n, example.com +dn: ou=de,ou=pla-i18n,dc=example,dc=com +ou: de +objectClass: top +objectClass: organizationalUnit +description:: U29uZGVyemVpY2hlbiDDtsOkw7zDnyDDlsOEw5w= +description:: w5bDliDDnMOcIMOEw4Q= + +# sv, pla-i18n, example.com +dn: ou=sv,ou=pla-i18n,dc=example,dc=com +ou: sv +objectClass: top +objectClass: organizationalUnit +description:: U8O2a29tZsOlbmc= +description:: bMOldGVyIHNvbQ== + +# ca, pla-i18n, example.com +dn: ou=ca,ou=pla-i18n,dc=example,dc=com +ou: ca +objectClass: top +objectClass: organizationalUnit +description:: RXMgdGluZHLDoSBxdWUgY29uZmlybWFyIGFxdWVzdGEgZGVjaXNpw7M= diff --git a/doc/uidpool.schema b/doc/uidpool.schema new file mode 100644 index 0000000..7154740 --- /dev/null +++ b/doc/uidpool.schema @@ -0,0 +1,11 @@ +## +## Used for storing the next gid and next uid in the the directory +## +objectclass ( 1.3.6.1.4.1.7165.1.2.2.3 NAME 'uidPool' SUP top AUXILIARY + DESC 'Pool for allocating UNIX uids' + MUST ( uidNumber $ cn ) ) + + +objectclass ( 1.3.6.1.4.1.7165.1.2.2.4 NAME 'gidPool' SUP top AUXILIARY + DESC 'Pool for allocating UNIX gids' + MUST ( gidNumber $ cn ) ) diff --git a/hooks/classes/README b/hooks/classes/README new file mode 100644 index 0000000..1a0f343 --- /dev/null +++ b/hooks/classes/README @@ -0,0 +1,3 @@ +Put your hook class files here. + +A file wich contains "class MyClass" definition must be called "MyClass.php". diff --git a/hooks/functions/README b/hooks/functions/README new file mode 100644 index 0000000..e5b29d7 --- /dev/null +++ b/hooks/functions/README @@ -0,0 +1 @@ +Put your hook function files here. \ No newline at end of file diff --git a/hooks/functions/example.php b/hooks/functions/example.php new file mode 100644 index 0000000..1ba34da --- /dev/null +++ b/hooks/functions/example.php @@ -0,0 +1,402 @@ +sprintf('Hook called [%s]',__METHOD__), + 'body'=>sprintf('Global Vars: %s',join('| ',array_keys($GLOBALS))), + 'type'=>'info','special'=>true)); + + return true; +} +add_hook('post_session_init','example_post_session_init'); + +/** + * This pre_connect function is called before making a connection to the LDAP server. + * While PLA makes many calls to connect to the LDAP server, this is called only once + * when caching is turned on. + * + * Arguments available are: + * @param int Server ID of the server to be connected to + * @param string Method. The user connection method, normally 'user'. + * @see post_connect + */ +function example_pre_connect() { + $args = func_get_args(); + + system_message(array( + 'title'=>sprintf('Hook called [%s]',__METHOD__), + 'body'=>sprintf('Arguments:
  • Server ID: %s
  • Method: %s
',$args[0],$args[1]), + 'type'=>'info','special'=>true)); + + return true; +} +add_hook('pre_connect','example_pre_connect'); + +/** + * This post_connect function is called after making a connection to the LDAP server. + * While PLA makes many calls to connect to the LDAP server, this is called only once + * when caching is turned on. + * + * Arguments available are: + * @param int Server ID of the server to be connected to + * @param string Method. The user connection method, normally 'user'. + * @param string User ID of the user who successfully made the connection. + * @see pre_connect + */ +function example_post_connect() { + $args = func_get_args(); + + system_message(array( + 'title'=>sprintf('Hook called [%s]',__METHOD__), + 'body'=>sprintf('Arguments:
  • Server ID: %s
  • Method: %s
  • User DN: %s
',$args[0],$args[1],$args[2]), + 'type'=>'info','special'=>true)); + + return true; +} +add_hook('post_connect','example_post_connect'); + +/** + * This pre_entry_create function is called before an entry is created in ds_ldap_pla::add(). + * + * Arguments available are: + * @param int Server ID of the server to be connected to + * @param string Method. The user connection method, normally 'user'. + * @param string DN of the entry created + * @param array Attributes for the new DN + * @see post_entry_create + */ +function example_pre_entry_create() { + $args = func_get_args(); + + system_message(array( + 'title'=>sprintf('Hook called [%s]',__METHOD__), + 'body'=>sprintf('Arguments:
  • Server ID: %s
  • Method: %s
  • DN: %s
  • Attributes: %s
',$args[0],$args[1],$args[2],join(',',(array_keys($args[3])))), + 'type'=>'info','special'=>true)); + + return true; +} +add_hook('pre_entry_create','example_pre_entry_create'); + +/** + * This post_entry_create function is called after an entry is created in ds_ldap_pla::add(). + * + * Arguments available are: + * @param int Server ID of the server to be connected to + * @param string Method. The user connection method, normally 'user'. + * @param string DN of the entry created + * @param array Attributes for the new DN + * @see pre_entry_create + */ +function example_post_entry_create() { + $args = func_get_args(); + + system_message(array( + 'title'=>sprintf('Hook called [%s]',__METHOD__), + 'body'=>sprintf('Arguments:
  • Server ID: %s
  • Method: %s
  • DN: %s
  • Attributes: %s
',$args[0],$args[1],$args[2],join(',',(array_keys($args[3])))), + 'type'=>'info','special'=>true)); + + return true; +} +add_hook('post_entry_create','example_post_entry_create'); + +/** + * This pre_entry_delete function is called before an entry is deleted in ds_ldap_pla::delete(). + * + * Arguments available are: + * @param int Server ID of the server to be connected to + * @param string Method. The user connection method, normally 'user'. + * @param string DN of the entry deleted + * @see post_entry_delete + */ +function example_pre_entry_delete() { + $args = func_get_args(); + + system_message(array( + 'title'=>sprintf('Hook called [%s]',__METHOD__), + 'body'=>sprintf('Arguments:
  • Server ID: %s
  • Method: %s
  • DN: %s
',$args[0],$args[1],$args[2]), + 'type'=>'info','special'=>true)); + + return true; +} +add_hook('pre_entry_delete','example_pre_entry_delete'); + +/** + * This post_entry_delete function is called after an entry is deleted in ds_ldap_pla::delete(). + * + * Arguments available are: + * @param int Server ID of the server to be connected to + * @param string Method. The user connection method, normally 'user'. + * @param string DN of the entry deleted + * @see pre_entry_delete + */ +function example_post_entry_delete() { + $args = func_get_args(); + + system_message(array( + 'title'=>sprintf('Hook called [%s]',__METHOD__), + 'body'=>sprintf('Arguments:
  • Server ID: %s
  • Method: %s
  • DN: %s
',$args[0],$args[1],$args[2]), + 'type'=>'info','special'=>true)); + + return true; +} +add_hook('post_entry_delete','example_post_entry_delete'); + +/** + * This pre_entry_rename function is called before an entry is renamed in ds_ldap_pla::rename(). + * + * Arguments available are: + * @param int Server ID of the server to be connected to + * @param string Method. The user connection method, normally 'user'. + * @param string Old DN of the entry to be renamed + * @param string New RDN for the new entry + * @param string Container for the new entry + * @see post_entry_rename + */ +function example_pre_entry_rename() { + $args = func_get_args(); + + system_message(array( + 'title'=>sprintf('Hook called [%s]',__METHOD__), + 'body'=>sprintf('Arguments:
  • Server ID: %s
  • Method: %s
  • DN: %s
  • New RDN: %s
  • New Container: %s
',$args[0],$args[1],$args[2],$args[3],$args[4]), + 'type'=>'info','special'=>true)); + + return true; +} +add_hook('pre_entry_rename','example_pre_entry_rename'); + +/** + * This post_entry_rename function is called after an entry is renamed in ds_ldap_pla::rename(). + * + * Arguments available are: + * @param int Server ID of the server to be connected to + * @param string Method. The user connection method, normally 'user'. + * @param string Old DN of the entry to be renamed + * @param string New RDN for the new entry + * @param string Container for the new entry + * @see pre_entry_rename + */ +function example_post_entry_rename() { + $args = func_get_args(); + + system_message(array( + 'title'=>sprintf('Hook called [%s]',__METHOD__), + 'body'=>sprintf('Arguments:
  • Server ID: %s
  • Method: %s
  • DN: %s
  • New RDN: %s
  • New Container: %s
',$args[0],$args[1],$args[2],$args[3],$args[4]), + 'type'=>'info','special'=>true)); + + return true; +} +add_hook('post_entry_rename','example_post_entry_rename'); + +/** + * This pre_entry_modify function is called before an entry is modified in ds_ldap_pla::modify(). + * + * Arguments available are: + * @param int Server ID of the server to be connected to + * @param string Method. The user connection method, normally 'user'. + * @param string DN of the entry to be modified + * @param array Attributes to be modified + * @see post_entry_modify + */ +function example_pre_entry_modify() { + $args = func_get_args(); + + system_message(array( + 'title'=>sprintf('Hook called [%s]',__METHOD__), + 'body'=>sprintf('Arguments:
  • Server ID: %s
  • Method: %s
  • DN: %s
  • Attributes: %s
',$args[0],$args[1],$args[2],join('|',array_keys($args[3]))), + 'type'=>'info','special'=>true)); + + return true; +} +add_hook('pre_entry_modify','example_pre_entry_modify'); + +/** + * This post_entry_modify function is called after an entry is modified in ds_ldap_pla::modify(). + * + * Arguments available are: + * @param int Server ID of the server to be connected to + * @param string Method. The user connection method, normally 'user'. + * @param string DN of the entry to be modified + * @param array Attributes to be modified + * @see pre_entry_modify + */ +function example_post_entry_modify() { + $args = func_get_args(); + + system_message(array( + 'title'=>sprintf('Hook called [%s]',__METHOD__), + 'body'=>sprintf('Arguments:
  • Server ID: %s
  • Method: %s
  • DN: %s
  • Attributes: %s
',$args[0],$args[1],$args[2],join('|',array_keys($args[3]))), + 'type'=>'info','special'=>true)); + + return true; +} +add_hook('post_entry_modify','example_post_entry_modify'); + +// pre_attr_add +// post_attr_add +/** + * This pre_attr_add function is called before an attribute is deleted in ds_ldap_pla::modify(). + * + * Arguments available are: + * @param int Server ID of the server to be connected to + * @param string Method. The user connection method, normally 'user'. + * @param string DN of the attribute to be deleted + * @param string Attribute to be deleted + * @param array Old values + * @see post_attr_add + */ +function example_pre_attr_add() { + $args = func_get_args(); + + system_message(array( + 'title'=>sprintf('Hook called [%s]',__METHOD__), + 'body'=>sprintf('Arguments:
  • Server ID: %s
  • Method: %s
  • DN: %s
  • Attribute: %s
  • New Values: %s
',$args[0],$args[1],$args[2],$args[3],join('|',$args[4])), + 'type'=>'info','special'=>true)); + + return true; +} +add_hook('pre_attr_add','example_pre_attr_add'); + +/** + * This post_attr_add function is called after an attribute is added in ds_ldap_pla::modify(). + * + * Arguments available are: + * @param int Server ID of the server to be connected to + * @param string Method. The user connection method, normally 'user'. + * @param string DN of the attribute to be added + * @param string Attribute to be added + * @param array New values + * @see pre_attr_add + */ +function example_post_attr_add() { + $args = func_get_args(); + + system_message(array( + 'title'=>sprintf('Hook called [%s]',__METHOD__), + 'body'=>sprintf('Arguments:
  • Server ID: %s
  • Method: %s
  • DN: %s
  • Attribute: %s
  • New Values: %s
',$args[0],$args[1],$args[2],$args[3],join('|',$args[4])), + 'type'=>'info','special'=>true)); + + return true; +} +add_hook('post_attr_add','example_post_attr_add'); + +// pre_attr_modify +// post_attr_modify +/** + * This pre_attr_modify function is called before an attribute is modified in ds_ldap_pla::modify(). + * + * Arguments available are: + * @param int Server ID of the server to be connected to + * @param string Method. The user connection method, normally 'user'. + * @param string DN of the attribute to be modified + * @param string Attribute to be modified + * @param array New values + * @see post_attr_modify + */ +function example_pre_attr_modify() { + $args = func_get_args(); + + system_message(array( + 'title'=>sprintf('Hook called [%s]',__METHOD__), + 'body'=>sprintf('Arguments:
  • Server ID: %s
  • Method: %s
  • DN: %s
  • Attribute: %s
  • Old Values: %s
  • New Values: %s
',$args[0],$args[1],$args[2],$args[3],join('|',$args[4]),join('|',$args[5])), + 'type'=>'info','special'=>true)); + + return true; +} +add_hook('pre_attr_modify','example_pre_attr_modify'); + +/** + * This post_attr_modify function is called after an attribute is deleted in ds_ldap_pla::modify(). + * + * Arguments available are: + * @param int Server ID of the server to be connected to + * @param string Method. The user connection method, normally 'user'. + * @param string DN of the attribute to be deleted + * @param string Attribute to be deleted + * @param array Old values + * @see pre_attr_modify + */ +function example_post_attr_modify() { + $args = func_get_args(); + + system_message(array( + 'title'=>sprintf('Hook called [%s]',__METHOD__), + 'body'=>sprintf('Arguments:
  • Server ID: %s
  • Method: %s
  • DN: %s
  • Attribute: %s
  • Old Values: %s
  • New Values: %s
',$args[0],$args[1],$args[2],$args[3],join('|',$args[4]),join('|',$args[5])), + 'type'=>'info','special'=>true)); + + return true; +} +add_hook('post_attr_modify','example_post_attr_modify'); + +/** + * This pre_attr_delete function is called before an attribute is deleted in ds_ldap_pla::modify(). + * + * Arguments available are: + * @param int Server ID of the server to be connected to + * @param string Method. The user connection method, normally 'user'. + * @param string DN of the attribute to be deleted + * @param string Attribute to be deleted + * @param array Old values + * @see post_attr_delete + */ +function example_pre_attr_delete() { + $args = func_get_args(); + + system_message(array( + 'title'=>sprintf('Hook called [%s]',__METHOD__), + 'body'=>sprintf('Arguments:
  • Server ID: %s
  • Method: %s
  • DN: %s
  • Attribute: %s
  • Old Values: %s
',$args[0],$args[1],$args[2],$args[3],join('|',$args[4])), + 'type'=>'info','special'=>true)); + + return true; +} +add_hook('pre_attr_delete','example_pre_attr_delete'); + +/** + * This post_attr_delete function is called after an attribute is deleted in ds_ldap_pla::modify(). + * + * Arguments available are: + * @param int Server ID of the server to be connected to + * @param string Method. The user connection method, normally 'user'. + * @param string DN of the attribute to be deleted + * @param string Attribute to be deleted + * @param array Old values + * @see pre_attr_delete + */ +function example_post_attr_delete() { + $args = func_get_args(); + + system_message(array( + 'title'=>sprintf('Hook called [%s]',__METHOD__), + 'body'=>sprintf('Arguments:
  • Server ID: %s
  • Method: %s
  • DN: %s
  • Attribute: %s
  • Old Values: %s
',$args[0],$args[1],$args[2],$args[3],join('|',$args[4])), + 'type'=>'info','special'=>true)); + + return true; +} +add_hook('post_attr_delete','example_post_attr_delete'); +?> diff --git a/htdocs/add_attr_form.php b/htdocs/add_attr_form.php new file mode 100644 index 0000000..7f72841 --- /dev/null +++ b/htdocs/add_attr_form.php @@ -0,0 +1,185 @@ +dnExists($request['dn'])) + error(sprintf(_('The entry (%s) does not exist.'),$request['dn']),'error','index.php'); + +$request['page'] = new TemplateRender($app['server']->getIndex(),get_request('template','REQUEST',false,null)); +$request['page']->setDN($request['dn']); +$request['page']->accept(true); +$request['template'] = $request['page']->getTemplate(); + +# Render the form +if (get_request('meth','REQUEST') != 'ajax') { + $request['page']->drawTitle(sprintf('%s %s',_('Add new attribute'),get_rdn($request['dn']))); + $request['page']->drawSubTitle(); + + echo '
'; + if (count($request['template']->getAvailAttrs())) { + # If we have more than the configured entries, we'll separate our input to the old ways. + if (count($request['template']->getAvailAttrs()) > $_SESSION[APPCONFIG]->getValue('appearance','max_add_attrs')) { + $attr = array(); + $attr['avail'] = array(); + $attr['binary'] = array(); + + foreach ($request['template']->getAvailAttrs() as $attribute) + if ($app['server']->isAttrBinary($attribute->getName())) + array_push($attr['binary'],$attribute); + else + array_push($attr['avail'],$attribute); + + if (count($attr['avail']) > 0) { + echo '
'; + echo _('Add new attribute'); + echo '
'; + echo '
'; + + echo '
'; + echo '
'; + + if ($_SESSION[APPCONFIG]->getValue('confirm','update')) + echo ''; + else + echo ''; + + printf('',$app['server']->getIndex()); + printf('',htmlspecialchars($request['dn'])); + + echo ''; + + echo ''; + printf('',_('Add')); + echo '
'; + echo '
'; + + } else { + echo '
'; + printf('(%s)',_('no new attributes available for this entry')); + } + + if (count($attr['binary']) > 0) { + echo '
'; + echo _('Add new binary attribute'); + echo '
'; + echo '
'; + + echo ''; + echo '
'; + echo '
'; + + if ($_SESSION[APPCONFIG]->getValue('confirm','update')) + echo ''; + else + echo ''; + + printf('',$app['server']->getIndex()); + printf('',$request['dn']); + echo ''; + + echo ''; + + echo ''; + printf('',_('Add')); + + if (! ini_get('file_uploads')) + printf('
%s
', + _('Your PHP configuration has disabled file uploads. Please check php.ini before proceeding.')); + + else + printf('
%s: %s
',_('Maximum file size'),ini_get('upload_max_filesize')); + + echo '
'; + echo '
'; + + } else { + echo '
'; + printf('(%s)',_('no new binary attributes available for this entry')); + } + + } else { + echo '
'; + + $request['page']->drawFormStart(); + printf('',$app['server']->getIndex()); + printf('',htmlspecialchars($request['dn'])); + + echo ''; + + foreach ($request['template']->getAvailAttrs() as $attribute) + $request['page']->draw('Template',$attribute); + + $request['page']->drawFormSubmitButton(); + echo '
'; + + $request['page']->drawFormEnd(); + } + + } else { + printf('(%s)',_('no new attributes available for this entry')); + } + + echo '
'; + +# The ajax addition (it is going into an existing TemplateRendered page +} else { + # Put our DIV there for the callback + echo '
'; + printf('%s',_('Add Attribute')); + echo '
'; + echo ''; + echo ''; + echo '
'; + + printf(''; + + echo '
'; + echo '
'; + echo '
'; +} +?> diff --git a/htdocs/add_oclass_form.php b/htdocs/add_oclass_form.php new file mode 100644 index 0000000..d2353c9 --- /dev/null +++ b/htdocs/add_oclass_form.php @@ -0,0 +1,117 @@ +dnExists($request['dn'])) + error(sprintf(_('The entry (%s) does not exist.'),$request['dn']),'error','index.php'); + +$request['page'] = new TemplateRender($app['server']->getIndex(),get_request('template','REQUEST',false,null)); +$request['page']->setDN($request['dn']); +$request['page']->accept(true); +$request['template'] = $request['page']->getTemplate(); + +$attribute_factory = new AttributeFactory(); + +# Grab the required attributes for the new objectClass +$ldap = array(); +$ldap['attrs']['must'] = array(); + +foreach ($request['template']->getAttribute('objectclass')->getValues() as $oclass_name) { + # Exclude "top" if its there. + if (! strcasecmp('top',$oclass_name)) + continue; + + if ($soc = $app['server']->getSchemaObjectClass($oclass_name)) + $ldap['attrs']['must'] = array_merge($ldap['attrs']['must'],$soc->getMustAttrNames(true)); +} + +$ldap['attrs']['must'] = array_unique($ldap['attrs']['must']); + +/* Build a list of the attributes that this new objectClass requires, + * but that the object does not currently contain */ +$ldap['attrs']['need'] = array(); +foreach ($ldap['attrs']['must'] as $attr) + if (is_null($request['template']->getAttribute($attr))) + array_push($ldap['attrs']['need'],$attribute_factory->newAttribute($attr,array('values'=>array()),$app['server']->getIndex())); + +# Mark all the need attributes as shown +foreach ($ldap['attrs']['need'] as $index => $values) + $ldap['attrs']['need'][$index]->show(); + +if (count($ldap['attrs']['need']) > 0) { + $request['page']->drawTitle(sprintf('%s %s',_('Add new objectClass to'),get_rdn($request['dn']))); + $request['page']->drawSubTitle(); + + echo '
'; + printf('%s: %s %s %s %s', + _('Instructions'), + _('In order to add these objectClass(es) to this entry, you must specify'), + count($ldap['attrs']['need']),_('new attributes'), + _('that this objectClass requires.')); + + echo '

'; + + echo '
'; + echo '
'; + + if ($_SESSION[APPCONFIG]->getValue('confirm','update')) + echo ''; + else + echo ''; + + printf('',$app['server']->getIndex()); + printf('',htmlspecialchars($request['dn'])); + echo '
'; + + echo ''; + printf('',_('New Required Attributes')); + + $counter = 0; + echo ''; + + foreach ($ldap['attrs']['need'] as $count => $attr) + $request['page']->draw('Template',$attr); + + echo '
%s
'; + foreach ($request['template']->getAttribute('objectclass')->getValues() as $value) + $request['page']->draw('HiddenValue',$request['template']->getAttribute('objectclass'),$counter++); + echo '
'; + + printf('

',_('Add ObjectClass and Attributes')); + echo '
'; + echo '
'; + +# There are no other required attributes, so we just need to add the objectclass to the DN. +} else { + $result = $app['server']->modify($request['dn'],$request['template']->getLDAPmodify()); + + if ($result) { + $href = sprintf('cmd.php?cmd=template_engine&server_id=%s&dn=%s&modified_attrs[]=objectclass', + $app['server']->getIndex(),rawurlencode($request['dn'])); + + if (get_request('meth','REQUEST') == 'ajax') + $href .= '&meth=ajax'; + + header(sprintf('Location: %s',$href)); + die(); + } +} +?> diff --git a/htdocs/add_value_form.php b/htdocs/add_value_form.php new file mode 100644 index 0000000..c30f348 --- /dev/null +++ b/htdocs/add_value_form.php @@ -0,0 +1,173 @@ +dnExists($request['dn'])) + error(sprintf(_('The entry (%s) does not exist.'),$request['dn']),'error','index.php'); + +$request['page'] = new TemplateRender($app['server']->getIndex(),get_request('template','REQUEST',false,null)); +$request['page']->setDN($request['dn']); +$request['page']->accept(true); +$request['template'] = $request['page']->getTemplate(); + +/* +if ($request['attribute']->isReadOnly()) + error(sprintf(_('The attribute (%s) is in readonly mode.'),$request['attr']),'error','index.php'); +*/ + +# Render the form +if (! strcasecmp($request['attr'],'objectclass') || get_request('meth','REQUEST') != 'ajax') { + # Render the form. + $request['page']->drawTitle(sprintf('%s %s %s %s',_('Add new'),htmlspecialchars($request['attr']),_('value to'),htmlspecialchars(get_rdn($request['dn'])))); + $request['page']->drawSubTitle(); + + if (! strcasecmp($request['attr'],'objectclass')) { + echo '
'; + echo '
'; + echo ''; + + } else { + echo ''; + echo '
'; + if ($_SESSION[APPCONFIG]->getValue('confirm','update')) + echo ''; + else + echo ''; + } + + printf('',$app['server']->getIndex()); + printf('',htmlspecialchars($request['dn'])); + echo '
'; + + echo ''; + echo ''; + + $request['attribute'] = $request['template']->getAttribute($request['attr']); + $request['count'] = $request['attribute']->getValueCount(); + + if ($request['count']) { + printf('', + _('Current list of'),$request['count'],_('values for attribute'),$request['attribute']->getFriendlyName()); + + echo ''; + + } else { + printf('', + _('No current value for attribute'),$request['attribute']->getFriendlyName()); + echo ''; + } + + echo ''; + + echo ''; + printf('',_('Enter the value(s) you would like to add:')); + echo ''; + echo ''; + + if ($_SESSION[APPCONFIG]->getValue('appearance','show_hints')) + printf('', + IMGDIR,_('Note: You may be required to enter new attributes that these objectClass(es) require')); + + echo '
%s %s %s %s:'; + + # Display current attribute values + echo '
'; + for ($i=0;$i<$request['count'];$i++) { + if ($i > 0) + echo '
'; + $request['page']->draw('CurrentValue',$request['attribute'],$i); + $request['page']->draw('HiddenValue',$request['attribute'],$i); + } + echo '
'; + + echo '
%s %s.

%s'; + + if (! strcasecmp($request['attr'],'objectclass')) { + # If our attr is an objectClass, fetch all available objectClasses and remove those from the list that are already defined in the entry + $socs = $app['server']->SchemaObjectClasses(); + + foreach ($request['attribute']->getValues() as $oclass) + unset($socs[strtolower($oclass)]); + + # Draw objectClass selection + echo ''; + echo '
'; + echo ''; + echo '
'; + + echo '
'; + printf('', + _('Add new ObjectClass'), + (isAjaxEnabled() ? sprintf('onclick="return ajSUBMIT(\'BODY\',document.getElementById(\'entry_form\'),\'%s\');"',_('Updating Object')) : '')); + echo '
'; + echo '

Hint%s
'; + echo ''; + + } else { + # Draw a blank field + echo '
'; + $request['page']->draw('FormValue',$request['attribute'],$request['count']); + echo '
'; + + $sattr = $app['server']->getSchemaAttribute($request['attr']); + + if ($sattr->getDescription()) + printf('%s: %s
',_('Description'),$sattr->getDescription()); + + if ($sattr->getType()) + printf('%s: %s
',_('Syntax'),$sattr->getType()); + + if ($sattr->getMaxLength()) + printf('%s: %s %s
', + _('Maximum Length'),number_format($sattr->getMaxLength()),_('characters')); + + echo '
'; + printf('',_('Add New Value')); + echo '
'; + + echo ''; + echo ''; + echo ''; + } + +} else { + if (is_null($attribute = $request['template']->getAttribute($request['attr']))) { + $request['template']->addAttribute($request['attr'],array('values'=>array())); + $attribute = $request['template']->getAttribute($request['attr']); + $attribute->show(); + + echo ''; + $request['page']->draw('Template',$attribute); + $request['page']->draw('Javascript',$attribute); + echo '
'; + + } else { + $request['count'] = $attribute->getValueCount(); + $request['page']->draw('FormReadWriteValue',$attribute,$request['count']); + } +} +?> diff --git a/htdocs/cmd.php b/htdocs/cmd.php new file mode 100644 index 0000000..0ddf004 --- /dev/null +++ b/htdocs/cmd.php @@ -0,0 +1,79 @@ +getIndex()); + +# See if we can render the command +if (trim($www['cmd'])) { + # If this is a READ-WRITE operation, the LDAP server must not be in READ-ONLY mode. + if ($app['server']->isReadOnly() && ! in_array(get_request('cmd','REQUEST'),$app['readwrite_cmds'])) + error(_('You cannot perform updates while server is in read-only mode'),'error','index.php'); + + # If this command has been disabled by the config. + if (! $_SESSION[APPCONFIG]->isCommandAvailable('script',$www['cmd'])) { + system_message(array('title'=>_('Command disabled by the server configuration'), + _('Error'),'body'=>sprintf('%s: %s.',_('The command could not be run'),htmlspecialchars($www['cmd'])),'type'=>'error'),'index.php'); + + $app['script_cmd'] = null; + } +} + +if ($app['script_cmd']) + include $app['script_cmd']; + +# Refresh a frame - this is so that one frame can trigger another frame to be refreshed. +if (isAjaxEnabled() && get_request('refresh','REQUEST') && get_request('refresh','REQUEST') != get_request('frame','REQUEST')) { + echo ''; +} + +# Capture the output and put into the body of the page. +$www['body'] = new block(); +$www['body']->SetBody(ob_get_contents()); +$www['page']->block_add('body',$www['body']); +ob_end_clean(); + +if ($www['meth'] == 'ajax') + $www['page']->show(get_request('frame','REQUEST',false,'BODY'),true,get_request('raw','REQUEST',false,false)); +else + $www['page']->display(); +?> diff --git a/htdocs/collapse.php b/htdocs/collapse.php new file mode 100644 index 0000000..8fb2731 --- /dev/null +++ b/htdocs/collapse.php @@ -0,0 +1,27 @@ +getIndex(),'tree'); +$entry = $tree->getEntry($dn); +$entry->close(); +set_cached_item($app['server']->getIndex(),'tree','null',$tree); + +header(sprintf('Location:index.php?server_id=%s&junk=%s#%s%s', + $app['server']->getIndex(),random_junk(),htmlid($app['server']->getIndex(),$dn),app_session_param())); +die(); +?> diff --git a/htdocs/common.php b/htdocs/common.php new file mode 100644 index 0000000..de4122c --- /dev/null +++ b/htdocs/common.php @@ -0,0 +1,14 @@ + diff --git a/htdocs/compare.php b/htdocs/compare.php new file mode 100644 index 0000000..47a80db --- /dev/null +++ b/htdocs/compare.php @@ -0,0 +1,188 @@ +getServer(get_request('server_id_src')); +$ldap['DST'] = $_SESSION[APPCONFIG]->getServer(get_request('server_id_dst')); + +if (! $ldap['SRC']->dnExists($request['dnSRC'])) + error(sprintf('%s (%s)',_('No such entry.'),pretty_print_dn($request['dnSRC'])),'error','index.php'); + +if (! $ldap['DST']->dnExists($request['dnDST'])) + error(sprintf('%s (%s)',_('No such entry.'),pretty_print_dn($request['dnDST'])),'error','index.php'); + +$request['pageSRC'] = new PageRender($ldap['SRC']->getIndex(),get_request('template','REQUEST',false,'none')); +$request['pageSRC']->setDN($request['dnSRC']); +$request['pageSRC']->accept(); +$request['templateSRC'] = $request['pageSRC']->getTemplate(); + +$request['pageDST'] = new PageRender($ldap['DST']->getIndex(),get_request('template','REQUEST',false,'none')); +$request['pageDST']->setDN($request['dnDST']); +$request['pageDST']->accept(); +$request['templateDST'] = $request['pageDST']->getTemplate(); + +# Get a list of all attributes. +$attrs_all = array_unique(array_merge($request['templateSRC']->getAttributeNames(),$request['templateDST']->getAttributeNames())); + +$request['pageSRC']->drawTitle(_('Comparing the following DNs')); + +echo '
'; + +echo ''; +echo ''; + +$href = sprintf('cmd.php?cmd=template_engine&server_id=%s&dn=%s', + $ldap['SRC']->getIndex(),rawurlencode($request['dnSRC'])); +printf('', + _('Server'),$ldap['SRC']->getName(),_('Distinguished Name'), + htmlspecialchars($href),$request['dnSRC']); + +$href = sprintf('cmd.php?cmd=template_engine&server_id=%s&dn=%s', + $ldap['DST']->getIndex(),rawurlencode($request['dnDST'])); +printf('', + _('Server'),$ldap['DST']->getName(),_('Distinguished Name'), + htmlspecialchars($href),$request['dnDST']); + +echo ''; + +echo ''; +echo ''; +echo ''; + +if (! is_array($attrs_all) || ! count($attrs_all)) { + printf('',_('This entry has no attributes')); + print '
%s: %s
%s: %s
%s: %s
%s: %s
'; +echo '
'; +echo '
'; +printf('',$app['server']->getIndex()); +printf('',$ldap['DST']->getIndex()); +printf('',$ldap['SRC']->getIndex()); +printf('',htmlspecialchars($request['dnDST'])); +printf('',htmlspecialchars($request['dnSRC'])); +printf('',_('Switch Entry')); +echo '
'; +echo '
'; +echo '
(%s)
'; + + return; +} + +sort($attrs_all); + +# Work through each of the attributes. +foreach ($attrs_all as $attr) { + # Has the config.php specified that this attribute is to be hidden or shown? + if ($ldap['SRC']->isAttrHidden($attr) || $ldap['DST']->isAttrHidden($attr)) + continue; + + $attributeSRC = $request['templateSRC']->getAttribute($attr); + $attributeDST = $request['templateDST']->getAttribute($attr); + + # Get the values and see if they are the same. + if ($attributeSRC && $attributeDST && ($attributeSRC->getValues() == $attributeDST->getValues())) + echo ''; + else + echo ''; + + foreach (array('src','dst') as $side) { + # If we are on the source side, show the attribute name. + switch ($side) { + case 'src': + if ($attributeSRC) { + echo ''; + $request['pageSRC']->draw('Name',$attributeSRC); + echo ''; + + if ($request['pageSRC']->getServerID() == $request['pageDST']->getServerID()) + echo ' '; + + else { + echo ''; + $request['pageSRC']->draw('Notes',$attributeSRC); + echo ''; + } + + } else { + echo ' '; + } + + break; + + case 'dst': + if ($attributeDST) { + if ($attributeSRC && ($request['pageSRC']->getServerID() == $request['pageDST']->getServerID())) + echo ' '; + + else { + echo ''; + $request['pageDST']->draw('Name',$attributeDST); + echo ''; + } + + echo ''; + $request['pageDST']->draw('Notes',$attributeDST); + echo ''; + + } else { + echo ' '; + } + + break; + } + } + + echo ''; + echo "\n\n"; + + # Get the values and see if they are the same. + if ($attributeSRC && $attributeDST && ($attributeSRC->getValues() == $attributeDST->getValues())) + echo ''; + else + echo ''; + + foreach (array('src','dst') as $side) { + echo ''; + echo ''; + echo '
'; + + switch ($side) { + case 'src': + + if ($attributeSRC && count($attributeSRC->getValues())) + $request['pageSRC']->draw('CurrentValues',$attributeSRC); + else + echo ' '; + + break; + + case 'dst': + if ($attributeDST && count($attributeDST->getValues())) + $request['pageDST']->draw('CurrentValues',$attributeDST); + else + echo ' '; + + break; + } + + echo '
'; + } + + echo ''; +} +echo ''; +?> diff --git a/htdocs/compare_form.php b/htdocs/compare_form.php new file mode 100644 index 0000000..56962bd --- /dev/null +++ b/htdocs/compare_form.php @@ -0,0 +1,65 @@ +dnExists($request['dn'])) + error(sprintf(_('The entry (%s) does not exist.'),$request['dn']),'error','index.php'); + +$request['page'] = new PageRender($app['server']->getIndex(),get_request('template','REQUEST',false,'none')); +$request['page']->setDN($request['dn']); +$request['page']->accept(); + +# Render the form +$request['page']->drawTitle(sprintf('%s %s',_('Compare another DN with'),get_rdn($request['dn']))); +$request['page']->drawSubTitle(); + +printf('',JSDIR); +echo '
'; +printf('%s %s %s
',_('Compare'),get_rdn($request['dn']),_('with ')); +echo '
'; + +echo '
'; +echo '
'; +echo ''; +printf('',$app['server']->getIndex()); +printf('',$app['server']->getIndex()); +printf('',htmlspecialchars($request['dn'])); +echo '
'; +echo "\n"; + +echo ''; + +echo ''; +printf('', + _('Compare this DN with another'),_('Destination DN')); +echo ''; +echo ''; +echo "\n"; + +printf('',_('Destination Server'),server_select_list($app['server']->getIndex(),true,'server_id_dst')); +echo "\n"; + +printf('',_('Compare')); +echo "\n"; + +echo '
%s:'; +echo ''; +draw_chooser_link('compare_form','dn_dst','true',''); +echo '
%s:%s
'; +echo '
'; +?> diff --git a/htdocs/copy.php b/htdocs/copy.php new file mode 100644 index 0000000..34d1512 --- /dev/null +++ b/htdocs/copy.php @@ -0,0 +1,209 @@ +getServer(get_request('server_id_src')); +$ldap['DST'] = $_SESSION[APPCONFIG]->getServer(get_request('server_id_dst')); + +# Error checking +if (! trim($request['dnDST'])) + error(_('You left the destination DN blank.'),'error','index.php'); + +if ($ldap['DST']->isReadOnly()) + error(_('Destination server is currently READ-ONLY.'),'error','index.php'); + +if ($ldap['DST']->dnExists($request['dnDST'])) + error(sprintf(_('The destination entry (%s) already exists.'),pretty_print_dn($request['dnDST'])),'error','index.php'); + +if (! $ldap['DST']->dnExists($ldap['DST']->getContainer($request['dnDST']))) + error(sprintf(_('The destination container (%s) does not exist.'), + pretty_print_dn($ldap['DST']->getContainer($request['dnDST']))),'error','index.php'); + +if (pla_compare_dns($request['dnSRC'],$request['dnDST']) == 0 && $ldap['SRC']->getIndex() == $ldap['DST']->getIndex()) + error(_('The source and destination DN are the same.'),'error','index.php'); + +$request['recursive'] = (get_request('recursive') == 'on') ? true : false; +$request['remove'] = (get_request('remove') == 'yes') ? true : false; + +if ($request['recursive']) { + $filter = get_request('filter','POST',false,'(objectClass=*)'); + + # Build a tree similar to that of the tree browser to give to r_copy_dn + $ldap['tree'] = array(); + printf('

%s%s

',_('Copying '),$request['dnSRC']); + printf('

%s

',_('Recursive copy progress')); + print '

'; + + print ''; + printf ('%s...',_('Building snapshot of tree to copy')); + + $ldap['tree'] = build_tree($ldap['SRC'],$request['dnSRC'],array(),$filter); + printf('%s
',_('Success')); + + # Prevent script from bailing early on a long delete + @set_time_limit(0); + + $copy_result = r_copy_dn($ldap['SRC'],$ldap['DST'],$ldap['tree'],$request['dnSRC'],$request['dnDST'],$request['remove']); + $copy_message = $copy_result; + print '
'; + +} else { + if ($_SESSION[APPCONFIG]->getValue('confirm','copy')) { + $request['pageSRC'] = new TemplateRender($ldap['SRC']->getIndex(),get_request('template','REQUEST',false,null)); + $request['pageSRC']->setDN($request['dnSRC']); + $request['pageSRC']->accept(true); + + $request['pageDST'] = new TemplateRender($ldap['DST']->getIndex(),get_request('template','REQUEST',false,'none')); + $request['pageDST']->setContainer($app['server']->getContainer($request['dnDST'])); + $request['pageDST']->accept(true); + + $request['templateSRC'] = $request['pageSRC']->getTemplate(); + $request['templateDST'] = $request['pageDST']->getTemplate(); + + $request['templateDST']->copy($request['templateSRC'],get_rdn($request['dnDST']),true); + + # Set all attributes with a values as shown, and remove the add value options + foreach ($request['templateDST']->getAttributes(true) as $sattribute) + if ($sattribute->getValues() && ! $sattribute->isInternal()) { + $sattribute->show(); + $sattribute->setMaxValueCount(count($sattribute->getValues())); + } + + $request['pageDST']->accept(); + + return; + + } else { + $copy_result = copy_dn($ldap['SRC'],$ldap['DST'],$request['dnSRC'],$request['dnDST'],$request['remove']); + + if ($copy_result) + $copy_message = sprintf('%s %s: %s %s', + $request['remove'] ? _('Move successful') : _('Copy successful'), + _('DN'),$request['dnDST'],_('has been created.')); + else + $copy_message = sprintf('%s %s: %s %s', + $request['remove'] ? _('Move NOT successful') : _('Copy NOT successful'), + _('DN'),$request['dnDST'],_('has NOT been created.')); + } +} + +if ($copy_result) { + $redirect_url = sprintf('cmd.php?cmd=template_engine&server_id=%s&dn=%s&refresh=SID_%s_nodes&noheader=1', + $ldap['DST']->getIndex(),rawurlencode($request['dnDST']),$ldap['DST']->getIndex()); + + system_message(array( + 'title'=>_('Copy Entry'), + 'body'=>$copy_message, + 'type'=>'info'), + $redirect_url); +} + +function r_copy_dn($serverSRC,$serverDST,$snapshottree,$dnSRC,$dnDST,$remove) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $copy_message = array(); + + $children = isset($snapshottree[$dnSRC]) ? $snapshottree[$dnSRC] : null; + + # If we have children, then we need to copy, then delete for a move + if (is_array($children) && count($children)) { + + $copy_result = copy_dn($serverSRC,$serverDST,$dnSRC,$dnDST,false); + + if (! $copy_result) + return false; + + array_push($copy_message,sprintf('%s %s: %s %s',_('Copy successful'),_('DN'),$dnDST,_('has been created.'))); + + $hadError = false; + foreach ($children as $child_dn) { + $dnDST_new = sprintf('%s,%s',get_rdn($child_dn),$dnDST); + $copy_result = r_copy_dn($serverSRC,$serverDST,$snapshottree,$child_dn,$dnDST_new,$remove); + $copy_message = array_merge($copy_message,array_values($copy_result)); + + if (! $copy_result) + $hadError = true; + } + + if (! $hadError && $remove) { + $delete_result = $serverSRC->delete($dnSRC); + + if ($delete_result) + array_push($copy_message,sprintf('%s %s: %s %s',_('Delete successful'),_('DN'),$dnDST,_('has been deleted.'))); + } + + } else { + $copy_result = copy_dn($serverSRC,$serverDST,$dnSRC,$dnDST,$remove); + + if ($copy_result) + array_push($copy_message,sprintf('%s %s: %s %s', + $remove ? _('Move successful') : _('Copy successful'), + _('DN'),$dnDST,_('has been created.'))); + else + array_push($copy_message,sprintf('%s %s: %s %s', + $remove ? _('Move NOT successful') : _('Copy NOT successful'), + _('DN'),$dnDST,_('has NOT been created.'))); + } + + return $copy_message; +} + +function copy_dn($serverSRC,$serverDST,$dnSRC,$dnDST,$remove) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $request = array(); + $request['pageSRC'] = new PageRender($serverSRC->getIndex(),get_request('template','REQUEST',false,'none')); + $request['pageSRC']->setDN($dnSRC); + $request['pageSRC']->accept(); + + $request['pageDST'] = new PageRender($serverDST->getIndex(),get_request('template','REQUEST',false,'none')); + $request['pageDST']->setContainer($serverDST->getContainer($dnDST)); + $request['pageDST']->accept(); + + $request['templateSRC'] = $request['pageSRC']->getTemplate(); + $request['templateDST'] = $request['pageDST']->getTemplate(); + $request['templateDST']->copy($request['pageSRC']->getTemplate(),get_rdn($dnDST,0)); + + # Create of move the entry + if ($remove) + return $serverDST->rename($request['templateSRC']->getDN(),$request['templateDST']->getRDN(),$serverDST->getContainer($dnDST),true); + else + return $serverDST->add($request['templateDST']->getDN(),$request['templateDST']->getLDAPadd()); +} + +function build_tree($server,$dn,$buildtree) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # We search all children, not only the visible children in the tree + $children = $server->getContainerContents($dn,null,0); + + if (count($children)) { + $buildtree[$dn] = $children; + foreach ($children as $child_dn) + $buildtree = build_tree($server,$child_dn,$buildtree); + } + + if (DEBUG_ENABLED) + debug_log('Returning (%s)',1,0,__FILE__,__LINE__,__METHOD__,$buildtree); + + return $buildtree; +} +?> diff --git a/htdocs/copy_form.php b/htdocs/copy_form.php new file mode 100644 index 0000000..749b78e --- /dev/null +++ b/htdocs/copy_form.php @@ -0,0 +1,103 @@ +dnExists($request['dn'])) + error(sprintf(_('The entry (%s) does not exist.'),$request['dn']),'error','index.php'); + +$request['page'] = new PageRender($app['server']->getIndex(),get_request('template','REQUEST',false,'none')); +$request['page']->setDN($request['dn']); +$request['page']->accept(); + +# Render the form +$request['page']->drawTitle(sprintf('%s %s',_('Copy'),get_rdn($request['dn']))); +$request['page']->drawSubTitle(); + +printf('',JSDIR); +echo '
'; +printf('%s %s %s:

',_('Copy'),get_rdn($request['dn']),_('to a new object')); +echo '
'; + +echo '
'; +echo '
'; +echo ''; +printf('',$app['server']->getIndex()); +printf('',$app['server']->getIndex()); +printf('',htmlspecialchars($request['dn'])); +echo '
'; +echo "\n"; + +echo ''; + +echo ''; +printf('', + _('The full DN of the new entry to be created when copying the source entry'),_('Destination DN')); +echo ''; +echo ''; +echo "\n"; + +printf('',_('Destination Server'),server_select_list($app['server']->getIndex(),true,'server_id_dst')); +echo "\n"; + +# We search all children, not only the visible children in the tree +$request['children'] = $app['server']->getContainerContents($request['dn']); + +if (count($request['children']) > 0) { + echo ''; + printf('',_('Recursive copy')); + echo '',_('Recursively copy all children of this object as well.')); + echo ''; + echo "\n"; + + echo ''; + printf('', + _('When performing a recursive copy, only copy those entries which match this filter'),_('Filter')); + echo ''; + echo "\n"; + + echo ''; + printf('',_('Delete after copy (move):')); + echo ''; + echo "\n"; + +} else { + printf('',_('Delete after copy (move):')); +} +echo "\n"; + +printf('',_('Copy ')); +echo "\n"; + +echo '
%s:'; +printf('',htmlspecialchars($request['dn'])); +draw_chooser_link('copy_form','dn_dst','true',get_rdn($request['dn'])); +echo '
%s:%s
:'; + printf('(%s)
%s:'; + echo '
%s'; + printf('(%s)',_('Make sure your filter (above) will select all child records.')); + echo '
%s
'; +echo '
'; + +if ($_SESSION[APPCONFIG]->getValue('appearance','show_hints')) + printf('
Light%s
', + IMGDIR,_('Hint: Copying between different servers only works if there are no schema violations')); + + +# Draw the javascrpt to enable/disable the filter field if this may be a recursive copy +if (count($request['children']) > 0) + printf('',JSDIR); +?> diff --git a/htdocs/create.php b/htdocs/create.php new file mode 100644 index 0000000..0ed5a3c --- /dev/null +++ b/htdocs/create.php @@ -0,0 +1,104 @@ +getIndex(),get_request('template','REQUEST',false,'none')); +$request['page']->setContainer(get_request('container','REQUEST',true)); +$request['page']->accept(); +$request['template'] = $request['page']->getTemplate(); + +if ((! $request['template']->getContainer() || ! $app['server']->dnExists($request['template']->getContainer())) && ! get_request('create_base')) + error(sprintf(_('The container you specified (%s) does not exist. Please try again.'),$request['template']->getContainer()),'error','index.php'); + +# Check if the container is a leaf - we shouldnt really return a hit here, the template engine shouldnt have allowed a user to attempt to create an entry... +$tree = get_cached_item($app['server']->getIndex(),'tree'); + +$request['container'] = $tree->getEntry($request['template']->getContainer()); +if (! $request['container'] && ! get_request('create_base')) { + $tree->addEntry($request['template']->getContainer()); + $request['container'] = $tree->getEntry($request['template']->getContainer()); +} + +# Check our RDN +if (! count($request['template']->getRDNAttrs())) + error(_('The were no attributes marked as an RDN attribute.'),'error','index.php'); +if (! $request['template']->getRDN()) + error(_('The RDN field is empty?'),'error','index.php'); + +# Some other attribute checking... +foreach ($request['template']->getAttributes() as $attribute) { + # Check that our Required Attributes have a value - we shouldnt really return a hit here, the template engine shouldnt have allowed this to slip through. + # @todo this isIgnoredAttr() function is missing? + if ($attribute->isRequired() && ! count($attribute->getValues()) && ! $app['server']->isIgnoredAttr($attr->getName())) + error(sprintf(_('You left the value blank for required attribute (%s).'), + $attribute->getName(false)),'error','index.php'); +} + +# Create the entry +$add_result = $app['server']->add($request['template']->getDN(),$request['template']->getLDAPadd()); + +if ($add_result) { + $action_number = $_SESSION[APPCONFIG]->getValue('appearance','action_after_creation'); + $href = sprintf('cmd=template_engine&server_id=%s',$app['server']->getIndex()); + + if ($request['redirect']) + $redirect_url = $request['redirect']; + + else if ($action_number == 2) + $redirect_url = sprintf('cmd.php?%s&template=%s&container=%s', + $href,'default',$request['template']->getContainerEncode()); + + else + $redirect_url = sprintf('cmd.php?%s&template=%s&dn=%s', + $href,'default',$request['template']->getDNEncode()); + + if ($action_number == 1 || $action_number == 2) + printf('',$redirect_url); + + if ($action_number == 1 || $action_number == 2) { + $create_message = sprintf('%s %s: %s %s', + _('Creation successful!'),_('DN'),$request['template']->getDN(),_('has been created.')); + + if (isAjaxEnabled()) + $redirect_url .= sprintf('&refresh=SID_%s_nodes&noheader=1',$app['server']->getIndex()); + + system_message(array( + 'title'=>_('Create Entry'), + 'body'=>$create_message, + 'type'=>'info'), + $redirect_url); + + } else { + $request['page']->drawTitle(_('Entry created')); + $request['page']->drawSubTitle(sprintf('%s: %s   %s: %s', + _('Server'),$app['server']->getName(),_('Distinguished Name'),$request['template']->getDN())); + + echo '
'; + echo '
'; + printf('%s.', + htmlspecialchars($href),rawurlencode($request['template']->getDN()),_('Display the new created entry')); + echo '
'; + printf('%s.', + htmlspecialchars($href),rawurlencode($request['template']->getContainer()),_('Create another entry')); + echo '
'; + } +} +?> diff --git a/htdocs/create_confirm.php b/htdocs/create_confirm.php new file mode 100644 index 0000000..6727fb1 --- /dev/null +++ b/htdocs/create_confirm.php @@ -0,0 +1,143 @@ +getIndex(),get_request('template','REQUEST',false,'none')); +$request['page']->setContainer(get_request('container','REQUEST',true)); +$request['page']->accept(); +$request['template'] = $request['page']->getTemplate(); + +if (! $request['template']->getContainer() || ! $app['server']->dnExists($request['template']->getContainer())) + error(sprintf(_('The container you specified (%s) does not exist. Please try again.'),$request['template']->getContainer()),'error','index.php'); + +# Check if the container is a leaf - we shouldnt really return a hit here, the template engine shouldnt have allowed a user to attempt to create an entry... +$tree = get_cached_item($app['server']->getIndex(),'tree'); + +$request['container'] = $tree->getEntry($request['template']->getContainer()); +if (! $request['container']) { + $tree->addEntry($request['template']->getContainer()); + $request['container'] = $tree->getEntry($request['template']->getContainer()); +} + +# Check our RDN +if (! count($request['template']->getRDNAttrs())) + error(_('The were no attributes marked as an RDN attribute.'),'error','index.php'); +if (! $request['template']->getRDN()) + error(_('The RDN field is empty?'),'error','index.php'); + +# Some other attribute checking... +foreach ($request['template']->getAttributes() as $attribute) { + # Check that our Required Attributes have a value - we shouldnt really return a hit here, the template engine shouldnt have allowed this to slip through. + # @todo this isIgnoredAttr() function is missing? + if ($attribute->isRequired() && ! count($attribute->getValues()) && ! $app['server']->isIgnoredAttr($attr->getName())) + error(sprintf(_('You left the value blank for required attribute (%s).'), + $attribute->getName(false)),'error','index.php'); +} + +# Check for unique attributes +$app['server']->checkUniqueAttrs($request['template']->getDN(),$request['template']->getLDAPadd()); + +$request['page']->drawTitle(_('Create LDAP Entry')); +$request['page']->drawSubTitle(sprintf('%s: %s   %s: %s', + _('Server'),$app['server']->getName(),_('Container'),$request['template']->getContainer())); + +# Confirm the creation +if (count($request['template']->getLDAPadd(true))) { + echo '
'; + echo _('Do you want to create this entry?'); + echo '

'; + echo '
'; + + echo "\n\n"; + echo '
'; + echo '
'; + echo ''; + printf('',$app['server']->getIndex()); + printf('',$request['template']->getContainerEncode(false)); + printf('',$request['template']->getID()); + foreach ($request['template']->getRDNAttrs() as $rdn) + printf('',htmlspecialchars($rdn)); + echo "\n"; + + $request['page']->drawHiddenAttributes(); + echo '
'; + + echo ''; + echo "\n"; + + printf('', + _('Attribute'),_('New Value'),_('Skip')); + echo "\n\n"; + + $counter = 0; + printf('',$counter%2 ? 'even' : 'odd',htmlspecialchars($request['template']->getDN())); + + foreach ($request['template']->getLDAPadd(true) as $attribute) { + $counter++; + + printf('',$counter%2 ? 'even' : 'odd'); + printf('',$attribute->getFriendlyName()); + + # Show NEW Values + echo ''; + + # Show SKIP Option + $input_disabled = ''; + $input_onclick = ''; + + if ($attribute->isRequired()) + $input_disabled = 'disabled="disabled"'; + + printf('', + htmlspecialchars($attribute->getName()),htmlspecialchars($attribute->getName()),$input_disabled,$input_onclick); + echo ''; + echo "\n\n"; + } + + echo '
%s%s%s
%s
%s'; + $request['page']->draw('CurrentValues',$attribute); + echo '
'; + + echo '
'; + echo '
'; + + printf('', + _('Commit'), + (isAjaxEnabled() ? sprintf('onclick="return ajSUBMIT(\'BODY\',document.getElementById(\'create_form\'),\'%s\');"',_('Updating Object')) : '')); + + printf('', + _('Cancel'), + (isAjaxEnabled() ? sprintf('onclick="return ajDISPLAY(\'BODY\',\'cmd=template_engine&server_id=%s&container=%s\',\'%s\');"',$app['server']->getIndex(),$request['template']->getContainer(),_('Retrieving DN')) : '')); + + echo '
'; + echo '
'; + echo '
'; + +} else { + $href = sprintf('cmd=template_engine&server_id=%s&dn=%s', + $app['server']->getIndex(),$request['template']->getDNEncode()); + + echo '
'; + echo _('You made no changes'); + + if (isAjaxEnabled()) + printf(' %s.', + htmlspecialchars($href),htmlspecialchars($href),_('Retrieving DN'),_('Go back')); + else + printf(' %s.',htmlspecialchars($href),_('Go back')); + + echo '
'; +} +?> diff --git a/htdocs/css/default/style.css b/htdocs/css/default/style.css new file mode 100644 index 0000000..7b2a369 --- /dev/null +++ b/htdocs/css/default/style.css @@ -0,0 +1,925 @@ +/* $Header$ */ + +/* Global Page */ +table.page { + font-weight: normal; + color: #000000; + + font-family: "bitstream vera sans","luxi sans",verdana,geneva,arial,helvetica,sans-serif; + background-color: #FFFFFF; + font-size: 13px; + empty-cells: hide; +} + +/* Global Page - Defaults */ +/* A HREF Links */ +table.page a { + color: #0000AA; + text-decoration: none; +} + +table.page a:hover { + text-decoration: none; +} + +table.page a img { + border: 0px; +} + +/* Global Page - Logo & Title */ +table.page tr.head { + text-align: center; + color: #FFFFFF; + background-color: #001188; + font-weight: bold; + font-size: 11px; + height: 25px; +} + +table.page tr.head img.logo { + vertical-align: middle; + text-align: center; + + width: 100px; + height: 60px; +} + +table.page tr.pagehead { +} + +table.page tr.pagehead td.imagetop { + width: 100%; + vertical-align: bottom; + text-align: right; +} + +/* Global Page - Control Line */ +table.page tr.control td { + border-top: 1px solid #AAAACC; + border-bottom: 1px solid #AAAACC; +} + +/* Global Page - Control Line Menu Items */ +table.page table.control { + table-layout: fixed; + width: 100%; +} + +table.page table.control td { + border-top: 0px; + border-bottom: 0px; + padding: 0px; + padding-top: 2px; + padding-bottom: 2px; + text-align: left; + vertical-align: top; + font-size: 11px; + font-weight: bold; +} + +table.page table.control img { + width: 24px; + height: 24px; +} + +table.page table.control a { + color: #000000; +} + +table.page table.control a:hover { + text-decoration: none; + background-color: #FFFFFF; + color: #0000AA; +} + +table.page table.control td.spacer { + width: 20%; +} + +table.page table.control td.logo { + text-align: right; + width: 10%; +} + +table.page table.control td.logo img.logo { + vertical-align: middle; + text-align: right; + + width: 100px; + height: 50px; +} + +/* Global Page - LDAP Tree */ +table.page td.tree { + border-right: 1px solid #AAAACC; + vertical-align: top; + background-color: #FCFCFE; + width: 10%; +} + +/* Global Page - Main Body */ +table.page td.body { + vertical-align: top; + width: 100%; + background-color: #FCFCFE; +} + +/* Global Page - Main Body System Message */ +table.page table.sysmsg { + border-bottom: 2px solid #AAAACC; + width: 100%; +} + +table.page table.sysmsg td.head { + font-size: small; + text-align: left; + font-weight: bold; +} + +table.page table.sysmsg td.body { + font-weight: normal; +} + +table.page table.sysmsg td.icon { + text-align: center; + vertical-align: top; +} + +/* Global Page - Main Body */ +table.page table.body { + font-weight: normal; + background-color: #FCFCFE; + width: 100%; +} + +table.page table.body h3.title { + text-align: center; + margin: 0px; + padding: 10px; + color: #FFFFFF; + background-color: #000088; + border: 1px solid #000000; + font-weight: normal; + font-size: 150%; +} + +table.page table.body h3.subtitle { + text-align: center; + margin: 0px; + margin-bottom: 15px; + font-size: 75%; + color: #FFFFFF; + border-bottom: 1px solid #000000; + border-left: 1px solid #000000; + border-right: 1px solid #000000; + background: #000088; + padding: 4px; + font-weight: normal; +} + +table.page table.body td.spacer { + border-top: 2px solid #AAAACC; + padding: 0px; + font-size: 5px; +} + +table.page table.body td.head { + font-weight: bold; +} + +table.page table.body td.foot { + font-size: small; + border-top: 1px solid #AAAACC; + border-bottom: 1px solid #AAAACC; +} + +/* Global Page Footer */ +table.page tr.foot td { + border-top: 1px solid #AAAACC; + font-weight: bold; + font-size: 12px; + text-align: right; +} + +/* Global Page - Other Layouts */ +/* Server Select */ +table.page table.server_select { + font-weight: bold; + font-size: 13px; + color: #000000; +} + +/* Individual table layouts */ +/* LDAP Tree */ +table.tree { +} + +table.tree tr.server td.icon { + vertical-align: top; +} + +table.tree tr.server td.name { + padding-right: 10px; + vertical-align: top; +} + +table.tree tr.server td { + padding-top: 5px; + font-size: 18px; + text-align: left; + padding-right: 0px; + white-space: nowrap; +} + +table.tree td { + white-space: nowrap; +} + +table.tree td.server_links { + vertical-align: top; + text-align: center; + padding-top: 0px; + padding-bottom: 0px; + padding-left: 3px; + padding-right: 3px; +} + +table.tree td.server_links img { + height: 22px; + width: 22px; +} + +table.tree td.server_links a { + color: #000000; + text-decoration: none; + font-size: 11px; +} + +table.tree td.server_links a:hover { + text-decoration: none; + background-color: #FFFFFF; + color: #000000; +} + +table.tree tr.option td.expander { + text-align: center; + width: 22px; + max-width: 22px; + min-width: 22px; + white-space: nowrap; +} + +table.tree tr.option td.icon { + text-align: center; + width: 22px; + max-width: 22px; + min-width: 22px; + white-space: nowrap; +} + +table.tree td.rdn a { + font-size: 13px; + color: #000000; +} + +table.tree td.rdn a:hover { + font-size: 13px; + color: #841212; + background-color: #FFF0C0; + text-decoration: none; +} + +table.tree td.rdn span.count { + font-size: 13px; + color: #000000; +} + +table.tree td.links a { + color: #0000AA; + text-align: center; +} + +table.tree td.link a { + font-size: 13px; + color: #000000; +} + +table.tree td.link a:hover { + font-size: 13px; + color: #841212; + background-color: #FFF0C0; + text-decoration: none; +} + +table.tree td.links a:hover { + text-decoration: none; + color: blue; +} + +table.tree td.links a img { + width: 22px; + height: 22px; +} + +table.tree td.blank { + font-size: 1px; +} + +table.tree td.spacer { + width: 22px; +} + +table.tree td.logged_in { + font-size: 10px; + white-space: nowrap; +} + +table.tree td.logged_in a { + font-size: 11px; +} + +table.tree td.logged_in a:hover { + color: #841212; + background-color: #FFF0C0; + text-decoration: none; +} + +/* Tree Global Defaults */ +table.tree tr td { + padding: 0px; +} + +table.tree a { + text-decoration: none; + color: #000000; +} + +table.tree a:hover { + text-decoration: underline; + color: blue; +} + +table.tree span.dnicon img { + width: 16px; + padding-bottom: 0px; +} + +/* Tree */ +table.tree .treemenudiv { + display: block; + white-space: nowrap; + padding-top: 1px; + padding-bottom: 1px; +} + +table.tree .phplmnormal { + font-family: bitstream vera sans, luxi sans, verdana, geneva, arial, helvetica, sans-serif; + font-size: 13px; + color: #000000; + text-decoration: none; +} + +table.tree a.phplmnormal:hover { + font-family: bitstream vera sans, luxi sans, verdana, geneva, arial, helvetica, sans-serif; + font-size: 13px; + color: #000000; + background-color: #fff0c0; + text-decoration: none; +} + +table.tree a.phplm:link { + font-family: bitstream vera sans, luxi sans, verdana, geneva, arial, helvetica, sans-serif; + font-size: 13px; + color: #000000; + text-decoration: none; +} + +table.tree a.phplm:visited { + font-family: bitstream vera sans, luxi sans, verdana, geneva, arial, helvetica, sans-serif; + font-size: 13px; + color: #000000; + text-decoration: none; +} + +table.tree a.phplm:hover { + font-family: bitstream vera sans, luxi sans, verdana, geneva, arial, helvetica, sans-serif; + font-size: 13px; + color: #841212; + background-color: #fff0c0; + text-decoration: none; +} + +table.tree a.phplm:active { + font-family: bitstream vera sans, luxi sans, verdana, geneva, arial, helvetica, sans-serif; + font-size: 13px; + color: #ff0000; + text-decoration: none; +} + +table.tree a.phplmselected:link { + font-family: bitstream vera sans, luxi sans, verdana, geneva, arial, helvetica, sans-serif; + font-size: 13px; + color: #dd0000; + background-color: #ffdd76; + text-decoration: none; +} + +table.tree a.phplmselected:visited { + font-family: bitstream vera sans, luxi sans, verdana, geneva, arial, helvetica, sans-serif; + font-size: 13px; + color: #dd0000; + background-color: #ffdd76; + text-decoration: none; +} + +table.tree a.phplmselected:hover { + font-family: bitstream vera sans, luxi sans, verdana, geneva, arial, helvetica, sans-serif; + font-size: 13px; + color: #841212; + background-color: #fff0c0; + text-decoration: none; +} + +table.tree a.phplmselected:active { + font-family: bitstream vera sans, luxi sans, verdana, geneva, arial, helvetica, sans-serif; + font-size: 13px; + color: #ff0000; + text-decoration: none; +} + +/* Standard Form */ +table.forminput { + background-color: #F9F9FA; + padding: 10px; + border: 1px solid #AAAACC; +} + +table.forminput td.title { + text-align: center; + font-weight: bold; +} + +table.forminput td.subtitle { + text-align: center; + font-weight: normal; + font-size: small; +} + +table.forminput tr td.heading { + font-weight: bold; +} + +table.forminput td.small { + font-size: 80%; +} + +table.forminput td.top { + vertical-align: top; +} + +table.forminput input.val { + width: 350px; + border: 1px solid #AAAACC; +} + +table.forminput input.roval { + width: 350px; + border: none; +} + +table.forminput td.icon { + width: 16px; + text-align: center; +} + +table.forminput td.icon img { + border: 0px; +} + +table.forminput td.label { + text-align: left; + font-size: 13px; +} + +/* Menu on top of entry form */ +table.menu { + font-size: 14px; +} + +table.menu td.icon { + width: 16px; + text-align: center; +} + +/* Edit DN */ +div.add_value { + font-size: 12px; + margin: 0px; + padding: 0px; +} + +/* Edit Entry */ +table.entry { + border-collapse: collapse; + border-spacing: 0px; + empty-cells: show; +} + +table.entry input { + margin: 1px; +} + +table.entry input.value { + color: #000000; + font-size: 14px; + width: 350px; + background-color: #FFFFFF; +} + +table.entry div.helper { + text-align: left; + white-space: nowrap; + background-color: #FFFFFF; + color: #888; + font-size: 14px; + font-weight: normal; +} + +table.entry input.roval { + font-size: 14px; + width: 350px; + background-color: #FFFFFF; + color: #000000; + border: none; +} + +table.entry textarea.value { + font-size: 14px; + width: 350px; + background-color: #FFFFFF; + color: #000000; +} + +table.entry textarea.roval { + font-size: 14px; + width: 350px; + background-color: #FFFFFF; + color: #000000; + border: none; +} + +table.entry tr td { + padding: 4px; + padding-right: 0px; +} + +table.entry tr td.heading { + border-top: 3px solid #C0C0C0; + font-weight: bold; +} + +table.entry tr td.note { + text-align: right; + background-color: #E0E0E0; +} + +table.entry tr td.title { + background-color: #E0E0E0; + vertical-align: top; + font-weight: bold; +} + +table.entry tr td.title a { + text-decoration: none; + color: #000000; +} + +table.entry tr td.title a:hover { + text-decoration: underline; + color: #016; +} + +table.entry tr td.value { + text-align: left; + vertical-align: middle; + padding-bottom: 10px; + padding-left: 50px; +} + +/** When an attr is updated, it is highlighted to indicate such */ +table.entry tr.updated td.title { + border-top: 1px dashed #AAAA88; + border-left: 1px dashed #AAAA88; + background-color: #999988; +} + +table.entry tr.updated td.note { + border-top: 1px dashed #AAAA88; + border-right: 1px dashed #AAAA88; + background-color: #999988; +} + +/** An extra row that sits at the bottom of recently modified attrs to encase them in dashes */ +table.entry tr.updated td.bottom { + border-top: 1px dashed #AAAA88; +} + +/** Formatting for the value cell when it is the attribute that has been recently modified */ +table.entry tr.updated td.value { + border-left: 1px dashed #AAAA88; + border-right: 1px dashed #AAAA88; +} + +/* Need to prevent sub-tables (like the one in which jpegPhotos are displayed) + * from drawing borders as well. */ +table.entry tr.updated td table td { + border: 0px; +} + +table.entry tr.noinput { + background: #E0E0E0; +} + +span.hint { + font-size: small; + font-weight: normal; + color: #888; +} + +/* Login Box */ +#login { + background: url('../../images/default/ldap-uid.png') no-repeat 0 1px; + background-color: #FAFAFF; + color: #000000; + padding-left: 17px; +} + +#login:focus { + background-color: #F0F0FF; + color: #000000; +} + +#login:disabled { + background-color: #DDDDFF; + color: #000000; +} + +#password { + background: url('../../images/default/key.png') no-repeat 0 1px; + background-color: #FAFAFF; + color: #000000; + padding-left: 17px; +} + +#password:focus { + background-color: #F0F0FF; + color: #000000; +} + +#password:disabled { + background-color: #DDDDFF; + color: #000000; +} + +#generic { + background-color: #FAFAFF; + color: #000000; + padding-left: 17px; +} +#generic:focus { + background-color: #F0F0FF; + color: #000000; +} + +#generic:disabled { + background-color: #DDDDFF; + color: #000000; +} + +/* After input results */ +div.execution_time { + font-size: 75%; + font-weight: normal; + text-align: left; +} + +table.result { + width: 100%; + vertical-align: top; + empty-cells: show; + border: 1px solid #AAAACC; + border-spacing: 0px; + background-color: #F2F2FF; +} + +table.result tr.heading { + vertical-align: top; +} + +table.result tr.list_title { + background-color: #FFFFFF; +} + +table.result tr.list_title td.icon { + text-align: center; + vertical-align: top; +} + +table.result tr.list_item { + background-color: #FFFFFF; +} + +table.result tr.list_item td.blank { + width: 25px; +} + +table.result tr.list_item td.heading { + vertical-align: top; + color: gray; + width: 10%; + font-size: 12px; +} + +table.result tr.list_item td.value { + color: #000000; + font-size: 12px; +} + +table.result_box { + border: 1px solid #AAAACC; + border-collapse: collapse; + empty-cells: show; +} + +table.result_table { + border: 1px solid #AAAACC; + border-collapse: collapse; + empty-cells: show; +} + +table.result_table td { + font-size: 12px; + vertical-align: top; + border: 1px solid #AAAACC; + padding: 4px; +} + +table.result_table th { + border: 1px solid #AAAACC; + padding: 10px; + padding-left: 20px; + padding-right: 20px; +} + +table.result_table tr.highlight { + background-color: #EEEBBB; +} + +table.result_table tr.highlight td { + border: 1px solid #AAAACC; + font-weight: bold; + padding-top: 5px; + padding-bottom: 5px; + padding-left: 10px; + padding-right: 10px; +} + +table.result_table td.heading { + color: #FFFFFF; + background-color: #000088; + font-size: 12px; +} + +table.result_table td.value { + color: #000000; + background-color: #E0E0E0; +} + +table.result_table tr.heading { + color: #FFFFFF; + background-color: #000088; + font-size: 12px; + font-weight: bold; +} + +table.result_table tr.heading a { + color: #FFFFFF; + font-size: 12px; + font-weight: bold; +} + +table.result_table tr.heading td { + border: 1px solid #AAAACC; + font-weight: normal; + padding-top: 5px; + padding-bottom: 5px; + padding-left: 10px; + padding-right: 10px; +} + +table.result_table tr.even { + background-color: #E0E0E0; +} + +table.result_table tr.even td { + border: 1px solid #AAAACC; + font-weight: normal; + padding-top: 5px; + padding-bottom: 5px; + padding-left: 10px; + padding-right: 10px; +} + +table.result_table tr.even td.title { + font-weight: bold; +} + +table.result_table tr.odd { + background-color: #F0F0F0; +} + +table.result_table tr.odd td { + border: 1px solid #AAAACC; + font-weight: normal; + padding-top: 5px; + padding-bottom: 5px; + padding-left: 10px; + padding-right: 10px; +} + +table.result_table tr.odd td.title { + font-weight: bold; +} + +table.result_table ul.list { + margin: 5px; + margin-left: 0px; + padding-left: 20px; +} + +table.result_table ul.list li { + margin-left: 0px; + padding-left: 0px; +} + +table.result_table ul.list li small { + font-size: 75%; + color: #707070; +} + +table.result_table ul.list li small a { + color: #7070C0; +} + +/* Error Dialog Box */ +table.error { + width: 500px; + border: 1px solid #AA0000; + background-color: #FFF0F0; +} + +table.error th { + background-color: #AA0000; + border: 0px; + color: #FFFFFF; + font-size: 14px; + font-weight: bold; + text-align: center; + vertical-align: middle; + width: 100%; +} + +table.error th.img { + vertical-align: middle; + text-align: center; +} + +table.error td { + border: 0px; + background-color: #FFF0F0; + padding: 2px; + text-align: left; + vertical-align: top; +} + +/* Popup Window */ +div.popup h3.subtitle { + text-align: center; + margin: 0px; + margin-bottom: 15px; + color: #FFFFFF; + border-bottom: 1px solid #000000; + border-left: 1px solid #000000; + border-right: 1px solid #000000; + background: #000088; + padding: 4px; + font-weight: normal; +} + +span.good { + color: green; +} + +span.bad { + color: red; +} diff --git a/htdocs/css/tango/style.css b/htdocs/css/tango/style.css new file mode 100644 index 0000000..fb84aa4 --- /dev/null +++ b/htdocs/css/tango/style.css @@ -0,0 +1,952 @@ +/* $Header$ */ + +/* Global Page */ +table.page { + font-weight: normal; + color: #2E3436; + + font-family: "bitstream vera sans","luxi sans",verdana,geneva,arial,helvetica,sans-serif; + background-color: #FFFFFF; + font-size: 13px; + empty-cells: hide; +} + +/* Global Page - Defaults */ +/* A HREF Links */ +table.page a { + color: #204A87; + text-decoration: none; +} + +table.page a:hover { + text-decoration: none; +} + +table.page a img { + border: 0px; +} + +/* Global Page - Logo & Title */ +table.page tr.head { + text-align: center; + color: #FFFFFF; + background-color: #3465A4; + font-weight: bold; + font-size: 11px; + height: 25px; +} + +table.page tr.head img.logo { + vertical-align: middle; + text-align: center; + + width: 100px; + height: 60px; +} + +table.page tr.pagehead { +} + +table.page tr.pagehead td.imagetop { + width: 100%; + vertical-align: bottom; + text-align: right; +} + +/* Global Page - Control Line */ +table.page tr.control td { + border-top: 1px solid #BABDB6; + border-bottom: 1px solid #BABDB6; +} + +/* Global Page - Control Line Menu Items */ +table.page table.control { + table-layout: fixed; + width: 100%; +} + +table.page table.control td { + border-top: 0px; + border-bottom: 0px; + padding: 0px; + padding-top: 5px; + text-align: left; + vertical-align: top; + font-size: 11px; +} + +table.page table.control img { + width: 24px; + height: 24px; +} + +table.page table.control a { + color: #2E3436; +} + +table.page table.control a:hover { + text-decoration: none; + background-color: #EEEEEC; + color: #CC0000; +} + +table.page table.control td.spacer { + width: 20%; +} + +table.page table.control td.logo { + text-align: right; + width: 10%; +} + +table.page table.control td.logo img.logo { + vertical-align: middle; + text-align: right; + + width: 100px; + height: 60px; +} + +/* Global Page - LDAP Tree */ +table.page td.tree { + border-right: 1px solid #BABDB6; + vertical-align: top; + background-color: #FFFFFF; + width: 10%; +} + +/* Global Page - Main Body */ +table.page td.body { + vertical-align: top; + width: 100%; + background-color: #FFFFFF; +} + +/* Global Page - Main Body System Message */ +table.page table.sysmsg { + border-bottom: 2px solid #BABDB6; + width: 100%; +} + +table.page table.sysmsg td.head { + font-size: small; + text-align: left; + font-weight: bold; +} + +table.page table.sysmsg td.body { + font-weight: normal; +} + +table.page table.sysmsg td.icon { + text-align: center; + vertical-align: top; +} + +/* Global Page - Main Body */ +table.page table.body { + font-weight: normal; + background-color: #FFFFFF; + width: 100%; +} + +table.page table.body h3.title { + text-align: center; + margin: 0px; + padding: 10px; + color: #FFFFFF; + background-color: #3465A4; + border: 1px solid #EEEEEC; + font-weight: normal; + font-size: 150%; +} + +table.page table.body h3.subtitle { + text-align: center; + margin: 0px; + margin-bottom: 15px; + font-size: 75%; + color: #FFFFFF; + border-bottom: 1px solid #EEEEEC; + border-left: 1px solid #EEEEEC; + border-right: 1px solid #EEEEEC; + background: #3465A4; + padding: 4px; + font-weight: normal; +} + +table.page table.body td.spacer { + border-top: 2px solid #BABDB6; + padding: 0px; + font-size: 5px; +} + +table.page table.body td.head { + font-weight: bold; +} + +table.page table.body td.foot { + font-size: small; + border-top: 1px solid #BABDB6; + border-bottom: 1px solid #BABDB6; +} + +/* Global Page Footer */ +table.page tr.foot td { + border-top: 1px solid #BABDB6; + font-weight: bold; + font-size: 12px; + text-align: right; +} + +/* Global Page - Other Layouts */ +/* Server Select */ +table.page table.server_select { + font-weight: bold; + font-size: 13px; + color: #2E3436; +} + +/* Individual table layouts */ +/* LDAP Tree */ +table.tree { +} + +table.tree tr.server td.icon { + vertical-align: top; +} + +table.tree tr.server td.name { + padding-right: 10px; + vertical-align: top; +} + +table.tree tr.server td { + padding-top: 5px; + font-size: 18px; + text-align: left; + padding-right: 0px; + white-space: nowrap; +} + +table.tree td { + white-space: nowrap; +} + +table.tree td.server_links { + vertical-align: top; + text-align: center; + padding-top: 0px; + padding-bottom: 0px; + padding-left: 3px; + padding-right: 3px; +} + +table.tree td.server_links img { + height: 22px; + width: 22px; +} + +table.tree td.server_links a { + color: #2E3436; + text-decoration: none; + font-size: 11px; +} + +table.tree td.server_links a:hover { + text-decoration: none; + background-color: #EEEEEC; + color: #CC0000; +} + +table.tree tr.option td.expander { + text-align: center; + width: 22px; + max-width: 22px; + min-width: 22px; + white-space: nowrap; +} + +table.tree tr.option td.icon { + text-align: center; + width: 22px; + max-width: 22px; + min-width: 22px; + white-space: nowrap; +} + +table.tree td.rdn a { + font-size: 13px; + color: #2E3436; +} + +table.tree td.rdn a:hover { + font-size: 13px; + color: #CC0000; + background-color: #EEEEEC; +} + +table.tree td.rdn span.count { + font-size: 13px; + color: #2E3436; +} + +table.tree td.links a { + color: #204A87; + text-align: center; +} + +table.tree td.link a { + font-size: 13px; + color: #2E3436; +} + +table.tree td.link a:hover { + font-size: 13px; + color: #CC0000; + background-color: #EEEEEC; + text-decoration: none; +} + +table.tree td.rdn a:hover { + font-size: 13px; + color: #CC0000; + background-color: #EEEEEC; + text-decoration: none; +} + +table.tree td.links a:hover { + text-decoration: none; + color: #204A87; +} + +table.tree td.links a img { + width: 22px; + height: 22px; +} + +table.tree td.blank { + font-size: 1px; +} + +table.tree td.spacer { + width: 22px; +} + +table.tree td.logged_in { + font-size: 10px; + white-space: nowrap; +} + +table.tree td.logged_in a { + font-size: 11px; +} + +table.tree td.logged_in a:hover { + color: #CC0000; + background-color: #EEEEEC; + text-decoration: none; +} + +/* Tree Global Defaults */ +table.tree tr td { + padding: 0px; +} + +table.tree a { + text-decoration: none; + color: #2E3436; +} + +table.tree a:hover { + text-decoration: underline; + color: #204A87; +} + +/* Tree */ +table.tree .treemenudiv { + display: block; + white-space: nowrap; + padding-top: 1px; + padding-bottom: 1px; +} + +table.tree .phplmnormal { + font-family: bitstream vera sans, luxi sans, verdana, geneva, arial, helvetica, sans-serif; + font-size: 13px; + color: #000000; + text-decoration: none; +} + +table.tree a.phplmnormal:hover { + font-family: bitstream vera sans, luxi sans, verdana, geneva, arial, helvetica, sans-serif; + font-size: 13px; + color: #000000; + background-color: #fff0c0; + text-decoration: none; +} + +table.tree a.phplm:link { + font-family: bitstream vera sans, luxi sans, verdana, geneva, arial, helvetica, sans-serif; + font-size: 13px; + color: #000000; + text-decoration: none; +} + +table.tree a.phplm:visited { + font-family: bitstream vera sans, luxi sans, verdana, geneva, arial, helvetica, sans-serif; + font-size: 13px; + color: #000000; + text-decoration: none; +} + +table.tree a.phplm:hover { + font-family: bitstream vera sans, luxi sans, verdana, geneva, arial, helvetica, sans-serif; + font-size: 13px; + color: #841212; + background-color: #fff0c0; + text-decoration: none; +} + +table.tree a.phplm:active { + font-family: bitstream vera sans, luxi sans, verdana, geneva, arial, helvetica, sans-serif; + font-size: 13px; + color: #ff0000; + text-decoration: none; +} + +table.tree a.phplmselected:link { + font-family: bitstream vera sans, luxi sans, verdana, geneva, arial, helvetica, sans-serif; + font-size: 13px; + color: #dd0000; + background-color: #ffdd76; + text-decoration: none; +} + +table.tree a.phplmselected:visited { + font-family: bitstream vera sans, luxi sans, verdana, geneva, arial, helvetica, sans-serif; + font-size: 13px; + color: #dd0000; + background-color: #ffdd76; + text-decoration: none; +} + +table.tree a.phplmselected:hover { + font-family: bitstream vera sans, luxi sans, verdana, geneva, arial, helvetica, sans-serif; + font-size: 13px; + color: #841212; + background-color: #fff0c0; + text-decoration: none; +} + +table.tree a.phplmselected:active { + font-family: bitstream vera sans, luxi sans, verdana, geneva, arial, helvetica, sans-serif; + font-size: 13px; + color: #ff0000; + text-decoration: none; +} + +/* Standard Form */ +table.forminput { + background-color: #EEEEEC; + padding: 10px; + border: 1px solid #BABDB6; +} + +table.forminput td.title { + text-align: center; + font-weight: bold; +} + +table.forminput td.subtitle { + text-align: center; + font-weight: normal; + font-size: small; +} + +table.forminput tr td.heading { + font-weight: bold; +} + +table.forminput td.small { + font-size: 80%; +} + +table.forminput td.top { + vertical-align: top; +} + +table.forminput input.val { + width: 350px; + border: 1px solid #BABDB6; +} + +table.forminput input.roval { + width: 350px; + border: none; +} + +table.forminput td.icon { + width: 16px; + text-align: center; +} + +table.forminput td.icon img { + border: 0px; +} + +table.forminput td.label { + text-align: left; + font-size: 13px; +} + +/* Menu on top of entry form */ +table.menu { + font-size: 14px; +} + +table.menu td.icon { + width: 16px; + text-align: center; +} + +/* Edit DN */ +div.add_value { + font-size: 12px; + margin: 0px; + padding: 0px; +} + +/* Edit Entry */ +table.entry { + border-collapse: collapse; + border-spacing: 0px; + empty-cells: show; +} + +table.entry input { + margin: 1px; +} + +table.entry input.value { + font-size: 14px; + width: 350px; + background-color: #FFFFFF; +} + +table.entry div.helper { + text-align: left; + white-space: nowrap; + background-color: #FFFFFF; + font-size: 14px; + font-weight: normal; + color: #888; +} + +table.entry input.roval { + font-size: 14px; + width: 350px; + background-color: #FFFFFF; + border: none; +} + +table.entry textarea.value { + font-size: 14px; + width: 350px; + background-color: #FFFFFF; +} + +table.entry textarea.roval { + font-size: 14px; + width: 350px; + background-color: #FFFFFF; + border: none; +} + +table.entry tr td { + padding: 4px; + padding-right: 0px; +} + +table.entry tr td.heading { + border-top: 3px solid #D3D7CF; + font-weight: bold; +} + +table.entry tr td.note { + text-align: right; + background-color: #EEEEEC; +} + +table.entry tr td.title { + background-color: #EEEEEC; + vertical-align: top; + font-weight: bold; +} + +table.entry tr td.title a { + text-decoration: none; + color: #2E3436; +} + +table.entry tr td.title a:hover { + text-decoration: underline; + color: #204A87; +} + +table.entry tr td.value { + text-align: left; + vertical-align: middle; + padding-bottom: 10px; + padding-left: 50px; +} + +/** When an attr is updated, it is highlighted to indicate such */ +table.entry tr.updated td.title { + border-top: 1px dashed #BABDB6; + border-left: 1px dashed #BABDB6; + background-color: #888A85; +} + +table.entry tr.updated td.note { + border-top: 1px dashed #BABDB6; + border-right: 1px dashed #BABDB6; + background-color: #888A85; +} + +/** An extra row that sits at the bottom of recently modified attrs to encase them in dashes */ +table.entry tr.updated td.bottom { + border-top: 1px dashed #BABDB6; +} + +/** Formatting for the value cell when it is the attribute that has been recently modified */ +table.entry tr.updated td.value { + border-left: 1px dashed #BABDB6; + border-right: 1px dashed #BABDB6; +} + +/* Need to prevent sub-tables (like the one in which jpegPhotos are displayed) + * from drawing borders as well. */ +table.entry tr.updated td table td { + border: 0px; +} + +table.entry tr.noinput { + background: #EEEEEC; +} + +span.hint { + font-size: small; + font-weight: normal; + color: #888; +} + +/* Edit DN - EntryWriter2 */ +table.entry tr.spacer { + background-color: #D3D7CF; +} + +table.entry tr td.ew2_icon { + vertical-align: top; +} + +table.entry tr td.ew2_attr { + vertical-align: top; + text-align: right; + font-size: 75%; + background-color: #FFFFFF; + font-weight: bold; +} + +table.entry tr td.ew2_attr a { + text-decoration: none; + color: #2E3436; +} + +table.entry tr td.ew2_attr a:hover { + text-decoration: underline; + color: #204A87; +} + +table.entry tr td.ew2_val { + text-align: left; + vertical-align: top; + padding-bottom: 10px; + padding-left: 50px; +} + +table.entry tr.updated td.ew2_attr { + text-align: right; + font-size: 75%; + border-top: 1px dashed green; + border-left: 1px dashed green; + border-bottom: 1px dashed green; + background-color: #ded; +} + +table.entry tr.updated td.ew2_val { + border-top: 1px dashed green; + border-left: 1px dashed green; + border-right: 1px dashed green; + border-bottom: 1px dashed green; +} + +/* Login Box */ +#login { + background: url('../../images/tango/ldap-uid.png') no-repeat 0 1px; + background-color: #FFFFFF; + padding-left: 17px; +} + +#login:focus { + background-color: #EEEEEC; +} + +#login:disabled { + background-color: #D3D7CF; +} + +#password { + background: url('../../images/tango/key.png') no-repeat 0 1px; + background-color: #FFFFFF; + padding-left: 17px; +} + +#password:focus { + background-color: #EEEEEC; +} + +#password:disabled { + background-color: #D3D7CF; +} + +#generic { + background-color: #FFFFFF; + padding-left: 17px; +} +#generic:focus { + background-color: #EEEEEC; +} + +#generic:disabled { + background-color: #D3D7CF; +} + +/* After input results */ +div.execution_time { + font-size: 75%; + font-weight: normal; + text-align: center; +} + +table.result { + width: 100%; + vertical-align: top; + empty-cells: show; + border: 1px solid #BABDB6; + border-spacing: 0px; + background-color: #EEEEEC; +} + +table.result tr.heading { + vertical-align: top; +} + +table.result tr.list_title { + background-color: #FFFFFF; +} + +table.result tr.list_title td.icon { + text-align: center; + vertical-align: top; +} + +table.result tr.list_item { + background-color: #FFFFFF; +} + +table.result tr.list_item td.blank { + width: 25px; +} + +table.result tr.list_item td.heading { + vertical-align: top; + color: gray; + width: 10%; + font-size: 12px; +} + +table.result tr.list_item td.value { + color: #2E3436; + font-size: 12px; +} + +table.result_table { + border: 1px solid #BABDB6; + border-collapse: collapse; + empty-cells: show; +} + +table.result_table td { + vertical-align: top; + border: 1px solid #BABDB6; + padding: 4px; +} + +table.result_table th { + border: 1px solid #BABDB6; + padding: 10px; + padding-left: 20px; + padding-right: 20px; +} + +table.result_table tr.highlight { + background-color: #FCE94F; +} + +table.result_table tr.highlight td { + border: 1px solid #BABDB6; + font-weight: bold; + padding-top: 5px; + padding-bottom: 5px; + padding-left: 10px; + padding-right: 10px; +} + +table.result_table td.heading { + color: #FFFFFF; + background-color: #3465A4; + font-size: 15px; +} + +table.result_table td.value { + color: #2E3436; + background-color: #EEEEEC; +} + +table.result_table tr.heading { + color: #FFFFFF; + background-color: #3465A4; + font-size: 15px; +} + +table.result_table tr.heading a { + color: #FFFFFF; + font-size: 20px; +} + +table.result_table tr.heading td { + border: 1px solid #BABDB6; + font-weight: normal; + padding-top: 5px; + padding-bottom: 5px; + padding-left: 10px; + padding-right: 10px; +} + +table.result_table tr.even { + background-color: #EEEEEC; +} + +table.result_table tr.even td { + border: 1px solid #BABDB6; + font-weight: normal; + padding-top: 5px; + padding-bottom: 5px; + padding-left: 10px; + padding-right: 10px; +} + +table.result_table tr.even td.title { + font-weight: bold; +} + +table.result_table tr.odd { + background-color: #EEEEEC; +} + +table.result_table tr.odd td { + border: 1px solid #BABDB6; + font-weight: normal; + padding-top: 5px; + padding-bottom: 5px; + padding-left: 10px; + padding-right: 10px; +} + +table.result_table tr.odd td.title { + font-weight: bold; +} + +table.result_table ul.list { + margin: 5px; + margin-left: 0px; + padding-left: 20px; +} + +table.result_table ul.list li { + margin-left: 0px; + padding-left: 0px; +} + +table.result_table ul.list li small { + font-size: 75%; + color: #707070; +} + +table.result_table ul.list li small a { + color: #7070C0; +} + +/* Error Dialog Box */ +table.error { + width: 500px; + border: 1px solid #AA0000; + background-color: #FFF0F0; +} + +table.error th { + background-color: #AA0000; + border: 0px; + color: #FFFFFF; + font-size: 14px; + font-weight: bold; + text-align: center; + vertical-align: middle; + width: 100%; +} + +table.error th.img { + vertical-align: middle; + text-align: center; +} + +table.error td { + border: 0px; + background-color: #FFF0F0; + padding: 2px; + text-align: left; + vertical-align: top; +} + +/* Popup Window */ +div.popup h3.subtitle { + text-align: center; + margin: 0px; + margin-bottom: 15px; + color: #FFFFFF; + border-bottom: 1px solid #2E3436; + border-left: 1px solid #2E3436; + border-right: 1px solid #2E3436; + background: #3465A4; + padding: 4px; + font-weight: normal; +} + +span.good { + color: green; +} + +span.bad { + color: red; +} diff --git a/htdocs/delete.php b/htdocs/delete.php new file mode 100644 index 0000000..137055c --- /dev/null +++ b/htdocs/delete.php @@ -0,0 +1,40 @@ +dnExists($request['dn'])) + error(sprintf('%s (%s)',_('No such entry.'),''.pretty_print_dn($request['dn']).''),'error','index.php'); + +# Delete the entry. +$result = $app['server']->delete($request['dn']); + +if ($result) { + $redirect_url = ''; + + if (isAjaxEnabled()) + $redirect_url .= sprintf('&refresh=SID_%s_nodes&noheader=1',$app['server']->getIndex()); + + system_message(array( + 'title'=>_('Delete DN'), + 'body'=>_('Successfully deleted DN ').sprintf('%s',$request['dn']), + 'type'=>'info'), + sprintf('index.php?server_id=%s%s',$app['server']->getIndex(),$redirect_url)); +} else + system_message(array( + 'title'=>_('Could not delete the entry.').sprintf(' (%s)',pretty_print_dn($request['dn'])), + 'body'=>ldap_error_msg($app['server']->getErrorMessage(null),$app['server']->getErrorNum(null)), + 'type'=>'error')); +?> diff --git a/htdocs/delete_attr.php b/htdocs/delete_attr.php new file mode 100644 index 0000000..ad323fa --- /dev/null +++ b/htdocs/delete_attr.php @@ -0,0 +1,49 @@ +isAttrReadOnly($request['attr'])) + error(sprintf(_('The attribute "%s" is flagged as read-only in the phpLDAPadmin configuration.'),$request['attr']),'error','index.php'); + +$update_array = array(); +$update_array[$request['attr']] = $app['server']->getDNAttrValue($request['dn'],$request['attr']); + +$redirect_url = sprintf('cmd.php?cmd=template_engine&server_id=%s&dn=%s', + $app['server']->getIndex(),rawurlencode($request['dn'])); + +if (! isset($update_array[$request['attr']][$request['index']])) + system_message(array( + 'title'=>_('Could not delete attribute value.'), + 'body'=>sprintf('%s. %s/%s',_('The attribute value does not exist'),$request['attr'],$request['index']), + 'type'=>'warn'),$redirect_url); + +else { + unset($update_array[$request['attr']][$request['index']]); + foreach ($update_array as $key => $values) + $update_array[$key] = array_values($values); + + $result = $app['server']->modify($request['dn'],$update_array); + + if ($result) { + foreach ($update_array as $attr => $junk) + $redirect_url .= sprintf('&modified_attrs[]=%s',$attr); + + header("Location: $redirect_url"); + die(); + } +} +?> diff --git a/htdocs/delete_form.php b/htdocs/delete_form.php new file mode 100644 index 0000000..3f0d44c --- /dev/null +++ b/htdocs/delete_form.php @@ -0,0 +1,157 @@ +getIndex(),get_request('template','REQUEST',false,'none')); +$request['page']->setDN($request['dn']); +$request['page']->accept(); +$request['template'] = $request['page']->getTemplate(); + +# Check if the entry exists. +if (! $request['dn'] || ! $app['server']->dnExists($request['dn'])) + system_message(array( + 'title'=>_('Entry does not exist'), + 'body'=>sprintf('%s (%s)',_('The entry does not exist'),$request['dn']), + 'type'=>'error'),'index.php'); + +# We search all children, not only the visible children in the tree +$request['children'] = $app['server']->getContainerContents($request['dn'],null,0,'(objectClass=*)',LDAP_DEREF_NEVER); + +printf('

%s %s

',_('Delete'),htmlspecialchars(get_rdn($request['dn']))); +printf('

%s: %s     %s: %s

', + _('Server'),$app['server']->getName(),_('Distinguished Name'),$request['dn']); +echo "\n"; + +echo '
'; + +if (count($request['children'])) { + printf('%s

',_('Permanently delete all children also?')); + + $search['href'] = htmlspecialchars(sprintf('cmd.php?cmd=query_engine&server_id=%s&filter=%s&base=%s&scope=sub&query=none&format=list', + $app['server']->getIndex(),rawurlencode('objectClass=*'),rawurlencode($request['dn']))); + + $query = array(); + $query['base'] = $request['dn']; + $query['scope'] = 'sub'; + $query['attrs'] = array('dn'); + $query['size_limit'] = 0; + $query['deref'] = LDAP_DEREF_NEVER; + $request['search'] = $app['server']->query($query,null); + + echo ''; + echo ''; + echo ''; + + echo ''; + + printf('', + sprintf(_('phpLDAPadmin can recursively delete this entry and all %s of its children. See below for a list of all the entries that this action will delete. Do you want to do this?'),count($request['search']))); + + echo ''; + + printf('', + _('Note: this is potentially very dangerous and you do this at your own risk. This operation cannot be undone. Take into consideration aliases, referrals, and other things that may cause problems.')); + echo "\n"; + + echo ''; + echo ''; + + echo ''; + echo ''; + echo "\n"; + + echo '
'; + printf(_('This entry is the root of a sub-tree containing %s entries.'),count($request['search'])); + printf(' (%s)', + $search['href'],_('view entries')); + echo '
 
%s
 
%s
'; + echo '
'; + echo ''; + printf('',$app['server']->getIndex()); + printf('',$request['template']->getDNEncode(false)); + //@todo need to refresh the tree after a delete + printf('', + sprintf(_('Delete all %s objects'),count($request['search'])), + (isAjaxEnabled() ? sprintf('onclick="return ajSUBMIT(\'BODY\',document.getElementById(\'delete_form\'),\'%s\');"',_('Deleting Object(s)')) : '')); + echo '
'; + echo '
'; + echo '
'; + echo ''; + printf('',$app['server']->getIndex()); + printf('',$request['template']->getDNEncode(false)); + printf('', + _('Cancel'), + (isAjaxEnabled() ? sprintf('onclick="return ajDISPLAY(\'BODY\',\'cmd=template_engine&server_id=%s&dn=%s\',\'%s\');"',$app['server']->getIndex(),$request['template']->getDNEncode(),_('Retrieving DN')) : '')); + echo '
'; + echo '
'; + echo "\n"; + + echo '

'; + echo _('List of entries to be deleted:'); + echo '
'; + + $i = 0; + printf(''; + echo "\n"; + +} else { + echo ''; + + printf('',_('Are you sure you want to permanently delete this object?')); + echo ''; + + printf('',_('Server'),$app['server']->getName()); + printf('', + _('Distinguished Name'),_('DN'),$request['dn']); + echo ''; + echo "\n"; + + echo ''; + echo ''; + echo ''; + echo ''; + echo '
%s
 
%s:%s
%s%s
 
'; + echo '
'; + echo ''; + printf('',$app['server']->getIndex()); + printf('',$request['template']->getDNEncode(false)); + //@todo need to refresh the tree after a delete + printf('', + _('Delete'), + (isAjaxEnabled() ? sprintf('onclick="return ajSUBMIT(\'BODY\',document.getElementById(\'delete_form\'),\'%s\');"',_('Deleting Object(s)')) : '')); + echo '
'; + + echo '
'; + + echo '
'; + echo ''; + printf('',$app['server']->getIndex()); + printf('',$request['template']->getDNEncode(false)); + printf('', + _('Cancel'), + (isAjaxEnabled() ? sprintf('onclick="return ajDISPLAY(\'BODY\',\'cmd=template_engine&server_id=%s&dn=%s\',\'%s\');"',$app['server']->getIndex(),$request['template']->getDNEncode(),_('Retrieving DN')) : '')); + echo '
'; + + echo '
'; + echo "\n"; +} + +echo '
'; +echo '
'; +?> diff --git a/htdocs/download_binary_attr.php b/htdocs/download_binary_attr.php new file mode 100644 index 0000000..251f2de --- /dev/null +++ b/htdocs/download_binary_attr.php @@ -0,0 +1,49 @@ +dnExists($request['dn'])) + error(sprintf(_('The entry (%s) does not exist.'),$request['dn']),'error','index.php'); + +$search = $app['server']->getDNAttrValues($request['dn'],null,LDAP_DEREF_NEVER,array($request['attr'])); + +# Dump the binary data to the browser +$obStatus = ob_get_status(); +if (isset($obStatus['type']) && $obStatus['type'] && $obStatus['status']) + ob_end_clean(); + +if (! isset($search[$request['attr']][$request['index']])) { + # We cant display an error, but we can set a system message, which will be display on the next page render. + system_message(array( + 'title'=>_('No binary data available'), + 'body'=>sprintf(_('Could not fetch binary data from LDAP server for attribute [%s].'),$request['attr']), + 'type'=>'warn')); + + die(); +} + +header(sprintf('Content-type: %s',$request['type'])); +header(sprintf('Content-disposition: attachment; filename="%s"',$request['filename'])); +header(sprintf('Expires: Mon, 26 Jul 1997 05:00:00 GMT',gmdate('r'))); +header(sprintf('Last-Modified: %s',gmdate('r'))); +echo $search[$request['attr']][$request['index']]; +die(); +?> diff --git a/htdocs/draw_tree_node.php b/htdocs/draw_tree_node.php new file mode 100644 index 0000000..7311e2d --- /dev/null +++ b/htdocs/draw_tree_node.php @@ -0,0 +1,61 @@ +getEntry($request['dn']); + + if (! $dnentry) { + $tree->addEntry($request['dn']); + $dnentry = $tree->getEntry($request['dn']); + $treesave = true; + } + + switch ($request['action']) { + case 0: + $dnentry->close(); + + break; + + case 2: + default: + if ($dnentry->isSizeLimited()) { + $tree->readChildren($request['dn'],true); + + $treesave = true; + } + + $dnentry->open(); + } +} + +if ($treesave) + set_cached_item($app['server']->getIndex(),'tree','null',$tree); + +if ($request['dn']) + echo $tree->draw_children($dnentry,$request['code']); +else + $tree->draw($request['noheader']); + +die(); +?> diff --git a/htdocs/entry_chooser.php b/htdocs/entry_chooser.php new file mode 100644 index 0000000..16a4eb6 --- /dev/null +++ b/htdocs/entry_chooser.php @@ -0,0 +1,135 @@ +'; +printf('

%s

',_('Entry Chooser')); + +echo ''; + +echo ''; +if ($request['container']) { + printf('',_('Server'),$app['server']->getName()); + printf('',_('Looking in'),$request['container']); + echo ''; +} + +# Has the user already begun to descend into a specific server tree? +if (isset($app['server']) && ! is_null($request['container'])) { + $tree = get_cached_item($app['server']->getIndex(),'tree'); + + $request['children'] = $app['server']->getContainerContents($request['container'],null,0,'(objectClass=*)',$_SESSION[APPCONFIG]->getValue('deref','tree')); + sort($request['children']); + + foreach ($app['server']->getBaseDN() as $base) { + if (DEBUG_ENABLED) + debug_log('Comparing BaseDN [%s] with container [%s]',64,0,__FILE__,__LINE__,__METHOD__,$base,$request['container']); + + if (! pla_compare_dns($request['container'],$base)) { + $parent_container = false; + $href['up'] = sprintf('entry_chooser.php?form=%s&element=%s&rdn=%s',$request['form'],$request['element'],rawurlencode($request['rdn'])); + break; + + } else { + $parent_container = $app['server']->getContainer($request['container']); + $href['up'] = sprintf('entry_chooser.php?form=%s&element=%s&rdn=%s&server_id=%s&container=%s', + $request['form'],$request['element'],$request['rdn'],$app['server']->getIndex(),rawurlencode($parent_container)); + } + } + + echo ''; + echo ''; + printf('',$href['up'],IMGDIR); + printf('',$href['up'],_('Back Up')); + echo ''; + + if (! count($request['children'])) + printf('',_('no entries')); + + else + foreach ($request['children'] as $dn) { + $href['return'] = sprintf("javascript:returnDN('%s%s')",($request['rdn'] ? sprintf('%s,',$request['rdn']) : ''),str_replace('\\','\\\\',$dn)); + $href['expand'] = sprintf('entry_chooser.php?server_id=%s&form=%s&element=%s&rdn=%s&container=%s', + $app['server']->getIndex(),$request['form'],$request['element'],$request['rdn'],rawurlencode($dn)); + + echo ''; + echo ''; + printf('',$href['expand'],IMGDIR); + + $entry = $tree->getEntry($dn); + if (is_null($entry)) { + $tree->addEntry($dn); + $entry = $tree->getEntry($dn); + } + + if ($entry) + $item = draw_formatted_dn($app['server'], $entry); + else + $item = $dn; + + printf('',$href['return'], $item ); + echo ''; + echo "\n\n"; + } + +# Draw the root of the selection tree (ie, list all the servers) +} else { + foreach ($_SESSION[APPCONFIG]->getServerList() as $index => $server) { + if ($server->isLoggedIn(null)) { + printf('',_('Server'),$server->getName()); + foreach ($server->getBaseDN() as $dn) { + if (! $dn) { + printf('',_('Could not determine base DN')); + + } else { + $href['return'] = sprintf("javascript:returnDN('%s%s')",($request['rdn'] ? sprintf('%s,',$request['rdn']) : ''),rawurlencode($dn)); + $href['expand'] = htmlspecialchars(sprintf('entry_chooser.php?server_id=%s&form=%s&element=%s&rdn=%s&container=%s', + $server->getIndex(),$request['form'],$request['element'],$request['rdn'],rawurlencode($dn))); + + echo ''; + echo ''; + printf('',$href['expand'],IMGDIR); + printf('',$href['return'],$dn); + } + } + + echo ''; + } + } +} + +echo '
%s:%s
%s:%s
 
 Up%s...
 (%s)
 Plus%s
%s:%s
 (%s)
 Plus%s
 
'; +echo '
'; + +# Capture the output and put into the body of the page. +$www['body'] = new block(); +$www['body']->SetBody(ob_get_contents()); +$www['page']->block_add('body',$www['body']); +ob_end_clean(); + +# Render the popup. +$www['page']->display(array('CONTROL'=>false,'FOOT'=>false,'HEAD'=>false,'TREE'=>false)); +?> diff --git a/htdocs/expand.php b/htdocs/expand.php new file mode 100644 index 0000000..d0647d0 --- /dev/null +++ b/htdocs/expand.php @@ -0,0 +1,27 @@ +getIndex(),'tree'); +$entry = $tree->getEntry($dn); +$entry->open(); +set_cached_item($app['server']->getIndex(),'tree','null',$tree); + +header(sprintf('Location:index.php?server_id=%s&junk=%s#%s%s', + $app['server']->getIndex(),random_junk(),htmlid($app['server']->getIndex(),$dn),app_session_param())); +die(); +?> diff --git a/htdocs/export.php b/htdocs/export.php new file mode 100644 index 0000000..cc1096b --- /dev/null +++ b/htdocs/export.php @@ -0,0 +1,40 @@ +getIndex(),get_request('exporter_id','REQUEST')); +$request['export'] = $request['exporter']->getTemplate(); +$types = $request['export']->getType(); + +# send the header +if ($request['file']) { + $obStatus = ob_get_status(); + if (isset($obStatus['type']) && $obStatus['type'] && $obStatus['status']) + ob_end_clean(); + + header('Content-type: application/download'); + header(sprintf('Content-Disposition: inline; filename="%s.%s"','export',$types['extension'].($request['export']->isCompressed() ? '.gz' : ''))); + echo $request['export']->export(); + die(); + +} else { + print '
';
+	echo htmlspecialchars($request['export']->export());
+	print '
'; +} +?> diff --git a/htdocs/export_form.php b/htdocs/export_form.php new file mode 100644 index 0000000..326184e --- /dev/null +++ b/htdocs/export_form.php @@ -0,0 +1,213 @@ + 'Macintosh', + 'unix' => 'UNIX (Linux, BSD)', + 'win' => 'Windows' +); + +$available_scopes = array( + 'base' => _('Base (base dn only)'), + 'one' => _('One (one level beneath base)'), + 'sub' => _('Sub (entire subtree)') +); + +$request['page'] = new PageRender($app['server']->getIndex(),get_request('template','REQUEST',false,'none')); +$request['page']->drawTitle(sprintf('%s',_('Export'))); + +printf('',JSDIR); +printf('',JSDIR); + +echo '
'; +echo '
'; +echo '
'; +echo ''; +printf('',$app['server']->getIndex()); + +echo ''; +echo ''; +echo ''; +echo ''; +echo ''; +echo ''; + +echo ''; + +printf('', + htmlspecialchars(_('Proceed >>'))); + +echo '
'; + +echo '
'; +printf('%s',_('Export')); + +echo ''; +printf('',_('Server'),$app['server']->getName()); + +echo ''; +printf('',_('Base DN')); +echo ''; +echo ''; + +echo ''; +printf('',_('Search Scope')); + +echo ''; + +echo ''; + +printf('', + _('Search Filter'),htmlspecialchars($request['filter'])); + +printf('', + _('Show Attributtes'),htmlspecialchars($request['attr'])); + +printf('', + $request['sys_attr'] ? 'checked="checked" ' : '',_('Include system attributes')); + +printf('', + _('Save as file')); + +printf('', + _('Compress')); + +echo '
%s%s
%s'; +printf(' ',htmlspecialchars($request['dn'])); +draw_chooser_link('export_form','dn'); +echo '
%s'; + +foreach ($available_scopes as $id => $desc) + printf('
', + htmlspecialchars($id),$id,($id == $request['scope']) ? 'checked="checked"' : '', + htmlspecialchars($id),$desc); + +echo '
%s
%s
 
 
 
'; +echo '
'; +echo '
'; + +echo ''; +echo ''; + +echo ''; + +echo ''; +echo '
'; +echo '
'; + +printf('%s',_('Export format')); + +foreach (Exporter::types() as $index => $exporter) { + printf('', + htmlspecialchars($exporter['type']),htmlspecialchars($exporter['type']),($exporter['type'] === $request['exporter_id']) ? ' checked="checked"' : ''); + + printf('
', + htmlspecialchars($exporter['type']),$exporter['type']); +} + +echo '
'; +echo '
'; +echo '
'; + +printf('%s',_('Line ends')); +foreach ($available_formats as $id => $desc) + printf('
', + htmlspecialchars($id),htmlspecialchars($id),($request['format']==$id) ? ' checked="checked"' : '', + htmlspecialchars($id),$desc); + +echo '
'; +echo '
'; +echo '
'; + +echo '
'; +echo '
'; + +/** + * Helper function for fetching the line end format. + * + * @return String 'win', 'unix', or 'mac' based on the user's browser.. + */ +function get_line_end_format() { + if (is_browser('win')) + return 'win'; + elseif (is_browser('unix')) + return 'unix'; + elseif (is_browser('mac')) + return 'mac'; + else + return 'unix'; +} + +/** + * Gets the USER_AGENT string from the $_SERVER array, all in lower case in + * an E_NOTICE safe manner. + * + * @return string|false The user agent string as reported by the browser. + */ +function get_user_agent_string() { + if (isset($_SERVER['HTTP_USER_AGENT'])) + return strtolower($_SERVER['HTTP_USER_AGENT']); + else + return ''; +} + +/** + * Determine the OS for the browser + */ +function is_browser($type) { + $agents = array(); + + $agents['unix'] = array( + 'sunos','sunos 4','sunos 5', + 'i86', + 'irix','irix 5','irix 6','irix6', + 'hp-ux','09.','10.', + 'aix','aix 1','aix 2','aix 3','aix 4', + 'inux', + 'sco', + 'unix_sv','unix_system_v','ncr','reliant','dec','osf1', + 'dec_alpha','alphaserver','ultrix','alphastation', + 'sinix', + 'freebsd','bsd', + 'x11','vax','openvms' + ); + + $agents['win'] = array( + 'win','win95','windows 95', + 'win16','windows 3.1','windows 16-bit','windows','win31','win16','winme', + 'win2k','winxp', + 'win98','windows 98','win9x', + 'winnt','windows nt','win32', + '32bit' + ); + + $agents['mac'] = array( + 'mac','68000','ppc','powerpc' + ); + + if (isset($agents[$type])) + return in_array(get_user_agent_string(),$agents[$type]); + else + return false; +} +?> diff --git a/htdocs/images/INFO b/htdocs/images/INFO new file mode 100644 index 0000000..fb46310 --- /dev/null +++ b/htdocs/images/INFO @@ -0,0 +1,6 @@ +PLA's icons come from http://jimmac.musichall.cz/ikony.php3, or the projects that +he drew them for. + +They are open source, either licensed under the GPL or a CC license. + +They are great icons so be sure to let Jakub know :) diff --git a/htdocs/images/ajax-progress.gif b/htdocs/images/ajax-progress.gif new file mode 100644 index 0000000000000000000000000000000000000000..994bfab65524de391b10d7e2c9fc1115a154b43a GIT binary patch literal 7685 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 TRS@nf!FPIzm+~vs(zpKy%_B!@ literal 0 HcmV?d00001 diff --git a/htdocs/images/ajax-spinner.gif b/htdocs/images/ajax-spinner.gif new file mode 100644 index 0000000000000000000000000000000000000000..1ed786f2ece49ec5db07dee13a56ef38025b628c GIT binary patch literal 2037 zcmY*ZcTf|19{+AO8xjIZfItFCFrkL3BodGwflvety+|>T03uy{D35o<4X`9Q3=bSU zojZMs3Qw_)j=f_!)B!!mUKqwc>ezd^4c;H{$Ifr|uTTHRC8&buXgI)uM*u&6{`~Rd zM}L3+_wV1IK7G1x-@ebEKY#i1<^B8j-@bj@wr$&s7cWknII(;8?sMnPJ$(4^-Me>t z_wN1p@#D#pCr3v|A3b`6qUeJM5ANT;KRi7A^5x65YuBDSb?WNXs}mCwVPRo|gM+(v z?RxX(&Gzlv_w3no`}XavTesf4dGq@9>xT~?_VDnybm`KK8#fLfJh*P%x(gRB?AWp6 z>({T(pFdAaOMCY0SzBA%hYueT6BF;;xnpHzb@}q;O`A4(d3im4{J5Z?;ONn#0|NsW zFJ9cgfB);(ugAv5a&vP_OG`&aMz(C(^6J&A@$vBk2M!!Re*DRkCvV@rJ%9duQ&ZFC z&6|%MJC>4?a{Bb?vuDqqIdg`~z*4Ws1>(;I2=4ORL zQCC-|R4OYgD_5;rwQSk44I4IW+_=%t&(GD>Rj=1yxpHM_Xh`ytnG&0k9<5Zz%KT@c z2mnYvQ>hsF`jQ_R5(mKIydH2saldkg!Gzlvi9nFeu<gyfnCs8|SGO1R0M3N~Sp zx@MoynP5Rh(303ldPHFemMT%$+lXy}A1JR?IwL6=E`apW=@Z-0R!QO^@j_&{6#;i|5R1o$ zJ1J~xCDQ$1cs9`DW9Z!)D)^+%&Ug81908UkMXX;jkp>#b+SE}d{`0S>>Ef(`Ns6oa zB~H-LX25y1!BDgW%?nC0$RettYz8zsuz>9Z!g8TH$kU;rwYWrSTkjuYCH9utgFU6b z*wzBKaG6IjEXYSpAo5j4&c(t zwi-c(Q6YX2N-v2q(mgN`>wuCTV&XSRUA4h-f8g+uV2k_=o;2wb`7N)&+7T-C+CT_Bu4KrjWmK>x0AbH2rmR&7+q6fX+R0o&}V!t?TP+g0{x`8PSP{7CvnEPL^Hzx^T2Eus2 zi$U6ZM7}+l%$}afWn#%|+MPTsC236GKi9-ad*Z9;Ymg?jSO$L1s$w4BvDzu_kH9>z zTWC{K?jx4~H3oGGt3}I}LWNw@H)C>9GF4^|x(5n#+Va}kr_cb>{a+K%>B+@JNrC8? zJOUkD3fe*NdA-rJupqo?FfRK}k zOm!l7Dj$dsL|kS`3FL3^@^7axrU9d*@79yf!+bu3kXbziU!v&TO3p#w{y_lYG5ZPzDh;giB_lkGp((nqZ12&%LTrgm4vY= z{ffd0B$DiUKReJ9>?{#_KVrMyhiu_A8fNd!&DWTZ4+9S|1lJHkLv-^}a0IC{WI9N! zQTY-}db!%OH^;l2ZeajnA&Q6Uv=#0KZB9;^^lzMOi^0~bS~m!&K#e6hia79(ItV9M SXP~*+AU!zMlD%~Wg#Hic*k=_0 literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/af.png b/htdocs/images/countries/af.png new file mode 100644 index 0000000000000000000000000000000000000000..cda88b08594d89da861bd1773275d8bde166cc6b GIT binary patch literal 1042 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFzk22B@ngr8 zl$Aq5L$6%Dx?|@~hG+%`O9loD2G#^tfh++*Z$a4-Ss@Q0#Y#oVP)Yq3ebX*ei%v_6 z77M2-PDc4gZZqACa*Q0i9IdLXJ*RsH%n$IN>mM*XAbfFn@XX+#=|SQ1!lM^Q$1RRa zU6z`)HY;&nV(!{pc?J3Ti|2p-@%hEu7uRlIyLA21mmgnVym@iv!kKSBzePqxUbuKc zAcI#rN5Z<^Tp*5BK25-+P+mVwYlC=&Z0G`riT_Kc9sY2TvBaqX=-Gszi-bD12qv}TgB8s zoyiq$YkGnvR|jmLle2AZ{`Q3xS9bS3Jw1ER@}}dPdfwgKm>%c1Z{5Tv*AG0sb@afT z_}#P8b}cBY%nH1@f6A*%s~?uU9Pft%vOG`sTLs3ytR#sM8T3SLvf}fwCmzS4^hli7s zla-Z~nVA_Fo4`071w@8G`xHAlCQOcs``ORr9K zJ*#WEqmrdXHKoxhX3wLnRYBMM&h@3$I3*Q*a!{=EkMw$_$ruNIVK6?I)OVcW!w z3-@iGp1YuZ|L(@Vb#eh6GdFJ9r)aEbzh1+9`I=437&Sto-krK8B0P7-JgNC1foHGq zh^$(box|zb*>kqzwBKse(qwk7nLB)DS=nAOzoV|uy>;#4)#4ggEK}7EpE+c(zhlLd zrg!@|g&Uosj3v^1Kl9|}>uU17dYL}6=d3lu#7zd)C(m`v28DsAtDnm{r-UW|r0YS$ literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/al.png b/htdocs/images/countries/al.png new file mode 100644 index 0000000000000000000000000000000000000000..5925b279c5a3aabb86b23c877b7197384bc4e780 GIT binary patch literal 1040 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFziMiB+{*fY zdImcq!x;vK6ATRV85rsr7|IwJVi*`C7#KD(GOl4{Jjcv@hM75pkD=$}6+^ME^*Fb-dhDM=;#3xhJ{aRW_bafBv=)>$LN zhZYuB%}g(un4C8@{%&V?*TSMwUfxYe=$DhzEi0?tMn(}563-nS9@yLcadUg+7SR^6DOx;HMLi6Zbz-H|NHvB^Ynb<;ql+!|DV7ADpS)L`uhI@0zUcp{0$8J6Auv!OH5Ao7=muk(&BHE9*yA*4xz76&@bj0|P_U)TDWN z%dM=o#Ki?@Yg;KQ>dDGVh=>RX2(YrUGBYy+BMumSqkxhSXyGpS1k}%%;hk_iPq8xK=m)2$7IrPcx8Dr;82SwNI zvzC2x3srP1jaHw(V@}0_38{?Uo~{2=!lrXxY@PTrbD@LcvuQ=~!m9H;g?~$R1sN;v zX>dAwRgtYIMkw~L=GLz}4Sm)*EZoHs9BCK#^1;1Tn;!jeD0g2Fuy1P@!|o}5>E&ha zVJo&biw2xFiL~FTplp2V^vz>D8cWnq9@Af(D>rY7^y8OV`H4Metr_lr)@#|J RcGd|LES|1@F6*2UngEvD2oV4P literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/am.png b/htdocs/images/countries/am.png new file mode 100644 index 0000000000000000000000000000000000000000..45cd7495779aecb815fb80f7494da52acfa230ae GIT binary patch literal 1042 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFKgh^?fRXnE zm)K!mi54!QOA;#Q)Q#?Io2}9^dTZzT)i?Z!XYeDBppSvk4~JAG`(GeeWvpzF0oMC1@$I5zvmGulK z=UHCfYXSl{BqT1$%05(7d?K%KRbT&|sp%&JgHsk356w)knwVU2a{A@w_Q%ojnUm8~ zYpdgKZm<0P{|5y8^Yi-_5b!fR{99byue8+fSy}(jR4|_@W4}s1%KNZaBZg7=k?*AH^seJ9dn>q;An-|ks5{N z+4B4A^{!5|`nAU6)gq5qOT7PY3H`Y-^u@}EGYky%3=HR(nL)l~Wj)Kud5xF%hJe5& z35h9!f)8b7pC~F`k(ZwX#eGjr{SWl#|Np?q9R>J9V0T)|DxeC+ByV>Yh7ML)4Fb0^Pk zpD(VVqPTvAf~J;^ijtb1s*w#Cw`NF6&W^rm zRsE~N;udo&&)2J=Q>TVpG1*ee`=w-yNu!f$?1CGltyREt6IOkx%-WLJ8p9k!C6tw$k-2SHt2cKsgeHFd<(5eF`SM5J>?fE;V z#!Z6#2ZTDdiFIvPm~&cw!XB-K=hgbR>&!T0IDMab`831HI}Ijo)9+qyyYa61{NpCm z_nJ-J>A3Qu-GXCIE6!U_+TynCwBPpoLHl3$ZoJ{Q>1NQjJHgxUMjUt^zWYJ=&ig)# z4u|i!n|AO?*74VQC*KsEep7hz_5MpY7i`$JdiTMt$Ie`P@&4$wJC`57yz%Vy%kO_4 ze)xLp`RnIjeq4Y2{MEN#3)ieacKrCJ&6}@Wy>j*Hl^e$nJimVF+tY`4T~y9Gsyq(0 z_?aL4z99U;*^`H57!D}29#iKys=|3do%6Vf#1<>H_i;|&;@z%CIDEr%#{W zy?gic>C-1qo;-Z`@WzcB*REZ=bm`KC3m49vJ9qZ%*)wO(oH}*t`0?ZW_wV1cXV324 zyEkmuuzdOQxpU`EnKGrmz8)Blz}OrGB!xiVtLTS74U9?N?k)@+tg;?J&VEl9$B>F! z$q5IT($35fI~ox*Ve-V-+ZV6J#Ip;{vfH^*(N0s_cJqq8OB*)|Y8(-iloLD>6Bst@ zw1|X|j2M^5rQ(kTqCwBa#GYI<+EiGwfr%?}mvyHHN5Lzp&sNo*kbsO;IYHV4Jj{4!P7Yo}Jdk`nvRU>`5PAfP%t zKE6CAsj|+?Df@bhXK;g);oe%?xtS*`TUQ?4_*Z!G@}$pv3@>&Ydatr-NB{+dr>mdK II;Vst07svX+W-In literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/ao.png b/htdocs/images/countries/ao.png new file mode 100644 index 0000000000000000000000000000000000000000..9463d243050a0294dd54f0ad4c8c76bedd92734a GIT binary patch literal 1041 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzF-)Ck0KRv_V z)J#cPSzAX(UO}Fnn^9PdOG%Y6EZjFEM>``&qN&v`Cs%FiG%q0`hWdK;hzOCcE~`ls zolHy=Jv~js!kki4{6s_qtgKAK!vnp&-GYMyjEoEo4D{{o?K)eS>&o@du4jnx;T7R$ zxH6aPOee$prKT_1)ovGvoDF3>CcfhliV+o0F51m6er+g@uWUiLtS<0Wj?J_4V}h zbai#Lw6rudG}P7A)zs7!6%}P=Wu>L1B_t$-goJo`c{w>bSy@?`nVEr635?KDKzsuTLLtvgTe~DWM4f@aPG5 literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/ar.png b/htdocs/images/countries/ar.png new file mode 100644 index 0000000000000000000000000000000000000000..bd7338260065431f8d086d8035843360ee82791f GIT binary patch literal 1043 zcmeH^`%6=C7{-rERF;*cKNwk*WZ4BPMH94iDs$y!%8ZP>bklC$qO>4#CfyiTm=H#@ zrJEXU(=9X2VjR(0;1OKNG{ASa)DoN**+e; zzhU@5(`c|jagYZNw- z73^?UBVB5Wu9Yx=<@n1F>4T<(Cg~YqVRU2Ex83wsG)0Ug3&1(KJw*Ug__B-R&Ws-H z1gA5+l$G9wGQ?w<1BT3geXhcORprd=p3K(}`5OERYCZK{dR<}5l^M^7M{>F}H?+hJ zEnYlsD}d)NNtCzM_7a7)aA+ojExxB-&Z_Sy)2tNtY4ZgAk1(P_y;S&Vgry_Ok@*VL zbXPj{REJk$jw+ptrLt72%q(QKM(;BJUYa({B#Pj~7LY0$R%x|kC<;bKCZ?wB4hJfi z0~l6n)a{+kUk4<7;S0?~pY;2u){ljaJYQznb{_ZOo7yx0WCp`e0EQk^tmf37(qXFE z8U4!gGLGX;r_*k?+iW(g)oQU=j7Fngug5S9K@b>*0r@GDk!_Nl{-1wLAhOD_kvw%f zf07ypJznLXKteAqE{1VieIcjEoy%KtZ4U7N=);|6+yqgvOiJC=s&rG@%)5YY_Bj}H7ijmgYd;uGtc;Rpa zCb2j87}=v)5%u-&-|_O?b^Sq!ADEQ0*XOsrPWP%@(jM^TM~2)fr$m^`OTvUPsWiU~ z)$HI}QS{Dr=``=P@m?2J@5nB_77`G}c`mG~=8N0jQHw4!SzmZh+`<+i2!Rhh3lwds P`x^o+J~>WE$+`arQpLFE literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/at.png b/htdocs/images/countries/at.png new file mode 100644 index 0000000000000000000000000000000000000000..2a58c49b1ed44161fdd633e81adb53af479bc081 GIT binary patch literal 1041 zcmeHE>rYZ~0R7n=EiIPzNfReh?N_9Lr^2QKJrn`T4kZJK2%$-r@2+yTDfYu z`JrsHTxC|PS!v~q?ghjv7mAq=P!thOOx|8ByZsA&?ri6roe$^BIdzCsOb^)@0sx@r zWDD~t-#~HQ8i>*oE%O!t5I`h_SyWtES;4o&YL#CsBcsg^n@Eor)o6Sqx#)JAEtV0J z$zU|<42D6y9w&$aolY|_pz80(G@8J#U*z(#$LDif=<`b>4wly zJUo0LJiIsci%gkcwH%F2(l=ZdJv>tAZSZZcNG;4?U6W( zi@U|5h0;<_Sy{hSN*+Brd+^{)S=q?G(j~dvRbK9s%LA2_4!PWa@}xtduqqV(swyLn zW8K|oSJx0hd^Z?0N~OB5Pu1It_4F*cTz;o>!ESfV%*@+tqei0v$JI(D>G8~3tuvF8 z*75Pr9UWe$^BY0vv|8#x>c{{1hXuAfTb@$2pu@YxLQqR%W>cXnN0?byHGJey_bLu& zenZl!8j1VsnVZRMEmN>VbOHkM2y3O9~I<7X>FM zd9U9+ezEsM#hu)hd%*>PIOyuLHxPq4T65Qx`#foP$f<4B@RcXzYzJCo%6nR|_0gpV tcn0ePv^ROz>4sNIw?Fi9)Ym zjG1S=12*Yd)+uW2GO;T+u{@Pour)M!!{ikaRssF#-ILP$&uuwV>{vdtdfxeMw~A8Q zHY`05=h1d(%k70zcSQu}v{f8TiE9gXpV8NLC?{oEan7pwGcSp7*6XPB73Ci2XgRrS z=P^O{!3J*`7aD|7vO+=_uRHR>CZi1r1G*y+^`g&8{-Bvp}&JXb4Z(dRds^Ae3_2UVgrNa`UZ;( z4VN1lE>l&lRa37wHC?Tx)ox+A*2rj%wsxzP)p`SiUVDeFCZQw zkB>hT9I`kg<9K?;k=)!9r%s*b5$IA<>$b6*6`y$6*k$$W(xM}Nejiejf260c^Y@$L z?e(I%dUtmA^WGj{%mU+g6yOPgl?gUVKxxJ#Z+91l4pvzYAm^Z`i(^Q|t>lCQOckn2 zmv?jD@Vi=8aBaHonf2^kh3Dp-K4aA19ewtmcEHUgn;12Y*kzwPletDFr)ynZ;>o2^ zS`LbWat|dJIVDZLQ=_!`)GL$R2B#XSARnWHf0}kZ*F=W~#7gVW8bqE)u@ z7&}$Zn$8uPwlUCQp@O)qbNv4qOq;)TDZSqELLlcJBg4;yMv^i1*EWJY?&<31vd$@? F2>_&xHE{p{ literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/aw.png b/htdocs/images/countries/aw.png new file mode 100644 index 0000000000000000000000000000000000000000..411977eb78646383292f19ff9cbb0af162fc77f6 GIT binary patch literal 1043 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFU*+ihtFifc zcYkM0d|g1;-uWv}uHTy&o4NbQwXLTfdBo&RShh1|!O4szXR;Qb&R=yod&#M~?e{A; zTDl$(-e9vzMOAT5>XL@v*|y7xPw}E?j+~eB<@94Ofd+o-N;awPxGxvNh)` z)?KXIcB^vT`IbEoTlYR}+xM{d=!^biFQ=Y)Km9Dw#*1?^HE-+iog{mwOaUMxI!bM?)qTkpRtUb&@c#pc>gdo%l{)hu1tx^8>zk~Is@ zUfcNK)!JK+OIL30+%O9y3uc|Y-n-+#ikpunY_C{$a#H)otnRIOU7K^K?yFdI zs;z!bcGrrMO*f`Z*<3q!Z`=MSOV^#BcI5f0z4w<++~PNBi~qEpAv1SIEj*I2{$fGj zinvuL3TJFi+jqZl(cb)xXKPNq>^uEx(&76(hwk<5HZpn{8TqTQ5E!|@C>{m4LLh>< z?FUefG0EHAg`tC0)&s~n=;`7ZQgJIe;Q-U2MUj<@pUC*Mgk1fqb0l_8qmxZeapVrA zvs*+$N_^MK)-pFZ&GGsCY_t1|6)Ur(BX3r-RWi07YMyDC#4}~836E~>-M@eCHaN*G zymRi@tgctTo|*aCHLfdjP^`QuAjoJ}=a?AinJKBsX}BPuEXFITCdVnLD9bG@Evkw! zAmiK=&f2|yh1Gp$TV{Xjc^RzE-1;g@`nB||S+}irSMRdA6&>B+B$~R@vhr!Dsp`_B hS6f}D{=Bh=nZfP8;h%^g_xB)Qd%F6$taD0e0sv9vu517R literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/az.png b/htdocs/images/countries/az.png new file mode 100644 index 0000000000000000000000000000000000000000..ced5af010f8fbd23e0dbe18e5b6513cab8c0823b GIT binary patch literal 1042 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzF|Mm5oq2)eX z=bh4O8UDCP;1;kTz<-{<-)z5tIRR#MrhcuKwgrj_UG^Fw4BBBVLB%EolLIXhgk6%= zgUSuOvvuQ}>~kmh>W8xDP4p_B68P!>dj@gJ`c9lKr zp>*C`{alE_y(GI`K_$cl!ly2 z^LbYl|FtFkb7$_asa5Coc@J32o$}J3?V$4{-TOw0_oY;y_azZeiX#ukdp|CVJ&_Ug zsk`Leo=pccqYw3U0Am&yzoP(82+TCjaso;-CV9KNFm$lWdH^{GJY5_^DsCkw9AI*B z5i$8vI%Vn6)}u?FOu4ef!O3V<)vi~cgbpp5w5dyL)-4A`K0QW9JFzmwFtaqjJh{5K z1s9e?Zcg8JeujDZp(C1;mzVm_=MvFcyZ-D+A3vXy8J-zB>vT@CbAA0LlDc$z+1Kr7 z6JNd7d4GbL>uPA~@}*`frc*=BuZM_;Jz;7+q;%N1DVdqM>CvO)Mb3+r8l2XNsj(e< z7Um~+Z{NJUb9~zz6tjb!m5sft%jNC$>&4xzrE~5vG6e8wmBtC$?QB-*uJi~b3KDzIfGsqgNzrW zemS#2C9^>Vt5G$pQ6;-c4X0@}uT>+jMJ+lQ%(94^WfnQfDSMrL(p>la4UTCGozoUtNA`H;uJXuT?wB+!pnQ8k*;dDd zNdaY>eGAtFm2YuNn;B5D)+x3lu3<+?+un@M{b_Bxvbqn%l+LT1cBFpx$?B;G8|R$p zTXk#t`m2*xo^7ACW8v0odrvET86edVAcZed!0*#hu=nesN#+nRyIn<};jK zz<6dM>)Az|*H-f0SS@gSy~w>y5|>s=Jlrb#`hfPQ6Q*BJTRq%s@#B)+pDS+vZ}@+@ z;Pd-N;PlCQOfz_de;U1B=Jz6N{_W^F>F?P@gaSWzbD!3F`EJH#B(2gT(NDzyFh4^FxC=;Y<>C|TVGC&zz$ zQg5OZ@2q?(YMd3F#LV$aZnci3n?rkL`|*Y%D37CnV@CB^jis5Nc*xWNlU8?^l(Pz921i zZh(JfRAg&He0OHXWCjL51_oaS215o017_wxX667^)&NeMY3TrU^(;ljaDDwsMa2*`wO9>}1XI&m1A_uBtt4IDG(Eix1A}Y> zgDfqrSQC>%3yVq3dr-LO#W;Tek` z51l^WbxVqrDa=s(_uT*CdAENr0=_>C`1~N?&MD8+yIi^(^q*f1e0MwK)%B>UT~>~^ zvhk7H6}j5Lm<7h~D8Lf}KL6jh0;L&~yxmm%N1H4AFrC0`OPtL zK6C0!fVjqzl^VLo@87y;ocJlkuXr*`Zq7YM2G2;tTc=MvD*}1k)78&qol`;+0GNj! AE&u=k literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/bd.png b/htdocs/images/countries/bd.png new file mode 100644 index 0000000000000000000000000000000000000000..56bba0b9d316e9039dfb2e07efadf45753e0bb8c GIT binary patch literal 1040 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFm-kXoa#Ggz z)v=1SX3%F~&}CqdVPH03X4YqBHDYBoWaTvB(@FZ1`z^$aKv@G121EA|U44-6;`a7%LwCdG<*(>Dq+G>bH~Pqwp9vU5yzNNY`XNptkh^^kRtFbvb?)o10@VerXxlC>6y zF7}Ve_mMZ}&Cm6V@zHlsWXv{~?+mia)ssk(=ggL3UYZivWvM>TKyivF`=MaBB`OkU zqXSMv`QMEQT*u0=RDkogmFX)lw=)b3#~B%pF)*BEWIV&jc#4_%1T*s)R@PIjtY_HS zuW)f)03u%AbG*El1q99u3EdVExh^7dQ$pgltn7V7#TRO7PqnpQ>g#_pHT`U5_1Vtu zmy^>!FR%Z;zQFhb#@Z;LN(gM5Wg!bRh%w3A-G!lpRn`N@+2`rv7*cU7IpF}4g@sDQ z-dGc-!#8)Z9u?uub#zktHE-R)PS&3*H!j+=>slW$eUz5>Px#XIY16GY2D!!T(hDZc znLItYCfL=}*V}#4#^zXtfD@N)yPED?wPn}Fz1F9%-E-mA5P2eYVoFd<4pRC%$i@82s^W~gqgWM_CaS109$KhGsl_;|YdxvXg;S04x$F<&kGJXHm>f0Z; zOV^!`onbh2hT-^G#$#s~Pn=^ueUACm8RnB`ShwzCJ$;e=_*u?#SGX=-;o7p3bLT#; z3)grr-4M8TTjb_#ksJ3U&R>$a{ZRJ)6U9qc(_t( zU;hHW{tS5fBJ%7xULGFC$4?aBz0-gA&_YCnOG1KISy|H3(x9j)%fLY2(b3_=A+FQM z1TUYHxpPD7`6G)DuiYNq^ZfQP;O)zxFYiMSn#i57*ShR$aW~rSV35PJ^x%u}zAy8l z?q-HR&5xa?t1{16Yk{fGa!dV{)`qwJ9M{+yud_GZ=xDaZ$zrFQ^>!DleV%r^-E9we zIXsH;JL>Q9JU-}jh{uI+pDWP;FH$0I#s$Afi+Y_A^B^VSZc_O3^q8mVF;CK>&sykR zbG6>?X!Ri2bDx{t=|GR?@u4?kf?uRWKTeKHOHIwn%1TX5O-V_Ki;Ihlj0_JC4+seG z@bGYRbF;9pFfuaI($Z2_S65V2l$4Z|kdP1(5)u>?vS)L*q#TX?b1KQ0+d*ma zuGtnYrJ_fc#QZ&d`LlPUQgBt&?3=8*DykxPnY4<%KQ%bj&OP&%?~l=)Pp{rJnjUqH zbWmJ&Y@1$nYGItIZ2yB@hu(-R2ypH;?$+(!vT9pndPc2Zlu^Knor}wjmd}~AY~RB2 zid?rKn}8K}Gar?Bi}EriCg0!i>Pkz-f`IESnLIHyVNOcR>=Z*g4JSG%Zd=K7`R$iA ly*_95G-*9rq_m-ujbV9{zSx@m&3T}Z@O1TaS?83{1OV&nJD&gm literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/bf.png b/htdocs/images/countries/bf.png new file mode 100644 index 0000000000000000000000000000000000000000..1019379aaaf013a54b573b5a5e46d6c370bd8de3 GIT binary patch literal 1042 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzF|C^q{5XHb4 z!^j-N%pA?k8pp~S%gUa>&Kb|io65_Z%qx%~Ae1U3k}V>UB_UfZt5~imUm!0XA+1)a zre3D5l%%W}uc+Uwua>T+k*Q(YVXB?4qm`|tTcE2~q-RiKU^m&$s>{l_!q}qO!lcT? zX|j`5la<>vH>WNqubE!Hb9~+U+&m|HdQ9~2pX2W{)hA$1fZq(iz`20|vjPHU1f;A? z;YsH*sL?knH#Dm;wQsdEYSGrtR^SU^5R7CNi{i8@FmR|a^Xql;X>$nda*LkfA3ZG~ zV_sbT;#93F3CA}5%H_QC4#-}aFL1P;^@6?PHZg`X((EUB8Fuin?w6OiXJvZ9&f>6@ z$tz#CD;`ce?XBO22Rse&dm0=5AwTOl14AtXLk$DN2}Z`_jEtw4nNKh?pJrt}0Ysdf z=eW2o@baGIoPc6MK#oOT!)J+Qa?;pXMDB|LEiMCm`TYVBq(_z;6Kom)+bx1O$8v5C0k$_cSu{M@q`))YRWuS-=Pd zM(ZdbCIn{gm3;$L$C%{p?!wT)D(eB{9Po5;45_%4oN$0?(j@I&Y5v(-=X}nb&|jTD zpFzY+FLSQx-o-ZBhPKPMY+IUd6ri!b@YtDqtL|Kx@@CPiXYV|19Tv{g^a*~=b;+rT zTU**n{o8iN)+C`v%7>hqnf@>zUYzuJk#eI`+`M&Vec$-@)!FI2lgm5j=b%_zYbYls z#+@InDl2Tus~x#u!c0|pX=C;MD>iNGT-e*SMUvFQtr-?)7}%`2B)t<90G_UXF6*2UngIG<3-|y4 literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/bg.png b/htdocs/images/countries/bg.png new file mode 100644 index 0000000000000000000000000000000000000000..0f64f7db4033db1c49b5379dd3cf5495560e9725 GIT binary patch literal 1041 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFKX&~1$#W-; zoIL#Q^V{>6&pmwlVD-9HUw?eDX;L_J{J`N82OmDWub9uEn9ZPE$gG;rs+z~DQOv1Z z$!kz4U{)nz(=O}Sq3AbVKX`_zXNy7bL<|2OvxH?%(X$+4W;i9xa|>*-&R*xAvnC*W zbwK7azk=1_<(uMax1=`h$Z~8^u+P!-Yd1+*=9aS9HF>5-@%qq;P0?x7{IA@&^zGM| z&)+{jd-deWi$|^PE&9bgh9&%_6~eYPvO$v!!zWl4tqdz&71_0?KtG+)wMN3fK|QQn z+qYaNW42vfmsRO9-`rUqZ5vVyG8irLxh(T|LmLe9=Xh2u4?MulaDbQjs37|h8KLuX zB6kebHt4Bcve4gcs{6{>>X^0hHFvwu!Co&yeLhD8zK9ICVrhDYiQzO0!x?tw3+$|C zI9N~fa$XVSy&)`cNm}B*qU;l8#mma_%VecDC@H=**59b6yhlspley_$9j)UAdMAwy z9$HykGBf$<=JdzY?Wv2?OHa3dLH_@O0=@gab@z=jNO{a^s?P z;j1g2wYGD0&nhgGynHKqx4O?vtDXC|ub#S*S0m-*!E>1hj~zODIOovmtgJLXkxPbU zMO(IS-L~oCw#()wMFtF9nwcw4cW{2>?(*_@xpIZ(3#L{R(Fb=F y8(Qh97@%QqY^tlheZ{VQEA@6RTC;;;b~(ekD#OxQ!7D)iV(@hJb6Mw<&;$VS5?F-* literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/bh.png b/htdocs/images/countries/bh.png new file mode 100644 index 0000000000000000000000000000000000000000..236693dc1b92deb2e29a708a50747a1b9dd8b7d0 GIT binary patch literal 1031 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFzhG*1*V5|9 z;Uk?LolBN1{q_6L$IqXiK7an`$&*uO&Ky5^^754{7cO4hv2*9F*|U!`FdS!OIKjwx zoRRSaGxG@+mSZd|r&(D~v9g|EWj)5qdWN0-1SjV?F0OMtJQsL*FAE5qm`R3&G)ye6qmDOcy>mP1z-`(8q*xTK;8#GvJ0G8qettg!1HT6behmot5)kk$Fz~Xk?-_spEpt_io&{ap}^fvuDqqIB{a#x^)vK zOsK7`t*NO2Mh!56Mgi?YAdpWf8fZFWlDE4HLkFv@2avPX)5S5Q;#P9P0VXRe)>WT^ zXI@>(qAIdgr&h_)>FuAVtS^6UYFfl4b!?vCM+e1gX6H7|QBf64veP9=w@m2SG|xF8XN!D5$I@AgEzDhGf&y=!GS^bOz^V}vd^~hgqTaFvoF*EIQ%-Vf zgxo$5Juy>ZJ(G!s;hEDH*)&4#ABmkYcMY4_iThX2iD+E8aVU7ov$f2IC$1gh(71Bv pR@5xfglB?s@^5nTa~E}=wPx58to=%@Ro@L1R-UeYF6*2Ung9Y_KuiDt literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/bi.png b/htdocs/images/countries/bi.png new file mode 100644 index 0000000000000000000000000000000000000000..7fa236af37a1686488bcdc52cc6485d928cf0daf GIT binary patch literal 1043 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFzjWZ>_c!m} zJ$icP^qI>yZrr$i`{bE3kDol*w0ZNTt5;56ICt>Okq)`K0m$t=9WQ) zf>*c2`h%-%8q`yk1YCG_a@N8b*7;g~-BxKU0y0(xrY{dnTO3fcC8Ka|(u4Q6ZHm>L ziVU(>2j(sdtC*KLX-9L-x2sC(rjRSRPrtByRGNx+#Yn z>K5hiys=u|m&+nU(XB?uyU8G+!z8H7EPAS4{7k3dR_o-sZprgJGMD;fFZYX|% z#fSgPN_=0O^{^o8cT?4w%;ZNEMQ6*4e$JYDaYE1Kg9rY-e|LtR;fx5+HBtU|=K2rq zES`HfKXG@u;A;OZ$nTV!!_V-5V_`vO%8U1Rw0+#M?eFQ6_qJ@hv31KCHr8tbyf=ge zZion6l90G+VfxF>>3@*_|E#RJ#YJb({TZU%!6(^y$r;H?Lp6 ze(~bP`Sa(`o;`c!%$eiIkMG{SyS~027_Gp_9R>J9p!9@i22cfKlDE4HLkFv@2at2n z)5S5Q;#P9P0j4d_zg_#bWNPUa5!EfBCO#odTrYo|Nj#_RfA*}O*2$EaDbLtMjHX`_ zm~%@;S~T{8iSG%Qa|{|O4;L+XX5Fl;GpBafv{h>+>js>-cRExh;hK(|**VR7M(4_| zIVk#<*C!tRw`0PO84AgT?9$o`CbTb}VOL+^l8~V?zh&W;`KkdPao49zH?2SPq|<)t`~bIedc3$aM0+I Sh!|%l$nT!6elF{r5}E)3J%dgF literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/bj.png b/htdocs/images/countries/bj.png new file mode 100644 index 0000000000000000000000000000000000000000..290016a5149d8bac81237a7440ae4be67b898fdc GIT binary patch literal 1042 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFx2m*eh-YAk zVqmajV6b3dOk`w?Vq}hCW{zfNjbmkvWo3gJ{7046da^@0B6%tAi zlE{(}^cIw@kd-fxm(N#_43ShXRaY-iSBz2AO4G7vwyS_Y<0A*u=beX5ildb zt<^1HdO-Nx@bH=8af{+2XGEqfPsv!7k-9WBYfVMVmAeS>O!$4-Z|WvQ+W%)TwW z(f#rT3oV>08BU*NID3Kp+D(y1&(z+3wz_lQ?&n{xcOQLz{0Tg9oZVb-1#aAsxO73{&TZKT4-}t1(|-9<|Lt4T&!6qS zes%is!|m5E-&e0ZfBo|R{X5|M_rR}T1Hytt65|x}vh{u3x$d7=d~?_I+(DD?FWf#p z_B*$S^~zy^hnJmxy$-k{$$M8*_NBG{F)M=$_GVxGoSp`_{fhGc5*2V)LgJa4+7fB$ z=i1t96cyJiD{oU%+o7TH!PIoOmexKUox^&12Xu8mT3H=8FgR&sc+t%CoQcV4W8=?u zcE6mQu3B0BbaT6HZ}-s2>8F?1GdH(izP_(KJ^%Ro{|X3r=i~Fy&+kWI;MahFZ-Ifp zs02pnC?GxrPG;3N164C7dAqwXbg;^L067OdT^vIyZY3uiV2Zf8WG2rR9p=3;wtt%s zD`D0 z+PQldZ=TE?;Bhn{II!osma(>~sja%QHLpg>s$8X`=ikhoJv}}oC@Lm`LF7{CRKX_+ z{(7t5%&{mAD$fS$I_uHW-KxKE&(8W^SMK#KlUgvLNrInydq7g``6-#TZ+o|fIw*S9 qiTN>hE?IZdSZ&MJE8*b@pZOT}`si&H3g+|!1%s!npUXO@geCyf4=`*1 literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/bm.png b/htdocs/images/countries/bm.png new file mode 100644 index 0000000000000000000000000000000000000000..96fb4dcd4f42df3dd8f0a306b7b527d68709a947 GIT binary patch literal 1036 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFKfu6vkd5;+ z2j>+b;p1A`$My6-MMQmwPk51-{4O=)dv?y@@Q8OMrLTMYDrMxi+c}=~^xb4&-fU#H z*4_92wHq%E9eKEHZL+!j!i=JM*=3nNA)7m~rYFlDjt^=n7(+}wBVS1YSi1_tk}tsh!gTs1SjWMcBe&hD3!(*?(|NZ@^80h^A2>9mb_bWK?XF$MHZ|{2^9v=e&en&?=j12#q zlJYw*?^Aa6?ufAG`MH}S!d^Bv0%HmoU!#DEA+Yz$L_eT$j7i?^E({&4vK~OrE>9Q7 zkcwN$2?v-|QcWsFRi=dOnPbzWblLlLqZ3o4Dj%B-W%)d9W}vp)9HxgD|Rwy961{) zDtqFHjLgK8^sL07Im{xjR(Nt06n^9F*57i?_`>$HOk7)+we7I3Y(JJZ-CXL`tn_6J zt)C9rF4W6fu_4jln}y5ur^U{nt}3Ee%|f3&PfbP0 Hl+XkKn;S5i literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/bn.png b/htdocs/images/countries/bn.png new file mode 100644 index 0000000000000000000000000000000000000000..53460dc3677a5e6a0b0845dd30dbd033106f01ce GIT binary patch literal 1043 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFKNB7MZsMea zV$yd`olZ+kn$$nx&xfDZR@U`(^;fT4{qyVZ^{Y3&e);zL^&5Ewg|p|*9XP@I=(Ya) zA5PjjykCC%fA|q_;4t&i6RgKiN?f@n`|z>-nRB*JpS#5;D4#y-pPA)!=n%t!{S5o} zGaNj~ylWTp;lr#453(LSz4ZG-S@KnTKoRmQ3y2<1A_?z<9;WYGr(Q1SjJmW3>wj zp*vzjrUm;Z^K%u-NwhoJz1h8Eetzz(yqq`&h9m6k>%~QMIXDzKIVWmsKlJjNY+-&o zCel($YFS|5h0(J@R@d6&XzVvLdIC{hKvp7R5kIB@~txH;6j~scbT!;3bfs^4s^M?qfpboFyt=akR{0B3Q0-~a#s literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/bo.png b/htdocs/images/countries/bo.png new file mode 100644 index 0000000000000000000000000000000000000000..5025e7fb8de78e3fab3d412491f170977216e977 GIT binary patch literal 1042 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFXNX~7h-6@n zV`hzIWsPCwOyuNE=M_j7kjRvfEtQoolvgZMl#Y^CN>NsfSJZFQ*UHt>$j~tDFx4y6 zGblB%XtFS=G;x~hp>buwJ`n4NJO|{F};GMbDCx3ll&hmh`1y%_~Zi%@rExqog6?!L6Gaf(1 zc=9yw<*Vv@_v>7}VfEsb$M;`>KYpd0IL>zVEa#<55?8J&oH}K2@|5AjhZdJEnOwbM z_WZfSpFeI-pE?~sX8r1w+yDRmKfe3EdhPk|U%pQD|-@QJ)@%i{V;L3ToBYPN@FI2pHRsZoVvj;cr{(cMm|083; zB(4c9LW?HwKD*?+ZMpN5QnnTSx--(vY8}|lsxh8XX1t=#^*b~0oCa^V4A(tliPx^$ zH|*6n*=qd=xBH*!`!2!rO}xj;+{nL`DQ6fM>KPc$F*9FaWj({ndX|&(8ZYk+0f9>r z5>o^PAIi!;QB=GlFF#jO@}0i^CsWgh78bvpoOT--{c&@9?&x^T+WNo0|G$8Mp8)~i z!oz>X#eGjr{hyTuiq=s;Ca1erHGlUwY9>+QbkNc^GW(| zwx2t!nOooF=;)p~yUEA5=ughywXtg&oY-cqI_0I6^{Q>xuPUosQBn?yg?eUbVSaIf znwFKBoPmjq3k3MBg}K?cFIci>PS2tl0`~G|?->|4Y>mWz{9UgG^1P?3pUXO@geCx~ C%|9pr literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/br.png b/htdocs/images/countries/br.png new file mode 100644 index 0000000000000000000000000000000000000000..734ace94ba415e56b7bfa16a257b38ef6ed732cf GIT binary patch literal 1043 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFkEmG2XpqgQ zpT%uas20+%7T95xInN}bDY_mdN&PES5QnK@Cd&6|QM5ag`JKopS}8 za)jKAg+0o&Lo0PcD~%&69P_3G)-9F|u2l^x)roEPtDKe6Jlm?$njwmT0q6`%1_lcT z<``zyXjaa6PTmAwE@v)*6ak4W2|;f`#R^6F0(r?0N$Ch_r6gs=cty1|HT_zB#Rx@> zObycxQ>|<*?Q9)`5(B+_J>6_wtz<2WW($*26Q@Z|MtMeV)7?BLdHT=s511PeFe@Nn zdO+ax!0_4ODT`CGR%WFxOf@LiH!C-_Z?cP;9@({`lPjK8xkNT}uCHvSP|zf|-sK(6 zb;dQ*N{iRT#ZPo|?T|GtV=YJ_u+&m8{!^Lp^m>D5cOckev^{q_I*H{jb> zzqjvvzkLh%_%Yzyx9}g|2B}Gm zt2<`wF)4p_=jG(=MkhN@Uty`AM^i;pc4(z-Ssu;YYV-H-=Uv8?H!Xe$Jr{AkIg_bX zro=Sl(QD~N&8uez%jD|%G&r%%I`t}Q;m%rPZe^yNH9fr>D%lxoUmKOJ-YsPY^0KF^ KpUXO@geCwmOgTyb literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/bs.png b/htdocs/images/countries/bs.png new file mode 100644 index 0000000000000000000000000000000000000000..36c4cbe069fe12f67740fe4240e297448e8f26bc GIT binary patch literal 1042 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFx3;p*NY7wk z=4WQ*Rdn3oSMn_-qm04e472e$PV=+8HrE6kZg47Qu?m>TdOuY3dm`_3ML*`9hSwg` zgim^b$4w$GIpzIwEBND>`P?b}sei@)fQo+s6+eyak{L{nGZ-IZ(3s628q92Qj!8P1 z)%pUf#c5WH6TA)=1)MKSxSx~tyR8`fK+<}ywA~UV_x1YmuS`?lYWeRr2tQ_#eAg`Q zqEo>)x6&V0@yFfrpZQn+4ygSVQ1vyu{!?7XFVB?CS^d9L+a60euaR_KtLVL1FJhl# z=9%ECTZwItV(PA>c0AAwT(9oG#5QGLWX%cplp5A1S_lqyO-c-mTlZ@86rAIAO4Jm)?a7CYLUm9XV?9{kzlKcaFb) zxm~?j}@0$F!{Z3QY~O!9VjVd!9$^#F1Xc)B=-RNP8VIKUJ!<*SbD zTc53_B3HJS^y=g|BpE-M`(|m&4$GYtEG?=jPa2dqt9>uB`0>+X_l{jVt1GIi8C#e6 zrM!FZ(c$TN_FR8&zF!YBmtpBw-&tnrnwGlD7cAPgZk2?_m7ABPOlL3DRo33VX4%4B zO9V8o*e0Gj^XpHaVt+Tkh z)?&v*qeq(^56`wfJjeRQPLJKw?A{#+c)LH~!V0%fN5elJ4gY#F?(3Z*x_+zvGb8dK|5#oT|TvK+xi8&x34=jP5b$|Svyuw`Ly2WU@Y(4 zwyMLc=dYMM<9k!Ui9OqQsTI3l|O^H~@@XU=)u6Tp^GdZzc(pV@&dP zcVXyYmGuB}4tlychE&{2PB_5ygLR3i&esr?mex5>Q$(5%H99d(TJ@|gD@ds?Y~SZv zCa-jc)+1AUd`wbZS!4J9neqJWT0I7?ldosJ)VOi8`{u9D=VnGmPGT1c+I}It@WZo5 z+xSv@-}dLt;1V%1EhxVDXpYV7&emk7+`v4sfD<6m3jB_=~K}`lN+4;4ssTr{b;&(?oZ3ywV5Y7 cZ|q@auz70un|6c z`x!cWSMJd_r5Ar^?|+)J?{VDHV+Ds_)Li{nd*yHK)xXsjepFxlQF-o5{e>^xSH4ZS z{kM4e{*vYUiR~5c35-UcJcYZT`$7+z4l*!!+rYBuq}6zPk!}Zc*JAUrm)rL zlXu-Oy7I5|>i@js?+Qd=jD}l4GNjVxsah)5{9-fH4J(uTen75V)}7Z3oae#w2fd7lsa2 zSq~s*o2QFoNX4z>gab@BZXDU-(<9QlBf|2BOUl)+4o*$0j#Wx6x}!74=1`E96`RAt zjwN$qw%#asCQx=yV&;}LB?~45GXyW#+&gn+>)O5D%hzvb4_L8w$BI2W_ifv^a_gF1 zyH{@((719vI`Gnkxa&89qCzhR-wb3B;rdj##ccbQO~nPDKYcDgU(U*vdfdI0t=-j4 zeMwr{5*77hjIAQ94SJ8*cX?b72=|BFz8fkR?RE#+6D?8 MPgg&ebxsLQ0Jmviwg3PC literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/by.png b/htdocs/images/countries/by.png new file mode 100644 index 0000000000000000000000000000000000000000..8f5b8499089ec901f1704cfe84af05a0e34b181e GIT binary patch literal 1043 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFzoKV&)zs{v zjqP(s=S~aDUp>7aX3b$Z!@zuone{9y??qmLs{*ojWECGON-vgHT&t+GURnQ@zQ!&M z)Ay!YyS4O=>KPm}FuQ1Ka>2yuo0HowH>XEVZqMBOfBOgg4)FWz7w|QJ^$-KcQD&aw z?2;EnwC<^CZBjGbt84e#%KW&o({($)uU-MKd_unl^6g_4ILM{EU3iHq<6>3D)w*2E z4S2U%OC0glUhJl`*4OY-yxq<)tJ^ugXVN@xha}v0Gp1pqbVg28QE6#K>@r zf#C!r<8emDbIi;qn3<0;GuJXPon~b{#mahumGw9)>lt?Tvz(kKI62R8ab4r(y}-+R zl9%_gfWRpsp=%-{wLCmGBqYvBNSu|Bcqj|>w``4ozyn3a`-+NJ6coemOaPb#nUQ=Jwsq z?Y6z$BS*)FPEI?_%zk=#y>fFqY;FC^*Z04_|0_?=7aktJ{QZ9g1ibU{`56%K(a-Nk zVBq(_z%Ky-Zvz63xVnA{5C0e)^))W;X;jpYl$6h@slPHae`jT_^Ywj}mGP~#^lNF! z@9OF$p`jP@^MTO{jNDOxKLnO6&6@;N!IFlW1l)hadGurByMGfkS*PaCHC1(37-<|C+#I{-kWkU7 zSyr!RayL4?F_t;w)8l(qcTMiww>fKc8l7bN+_X-u%6b*G>sOW4tyxkIiel-`etB_q zfs(AQk(z~qjtc}PPi7S7pTA+to=J0-w9J^mVD_GYVM3A-SJA_T&p>|nboFyt=akR{ E0D1v1E&u=k literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/bz.png b/htdocs/images/countries/bz.png new file mode 100644 index 0000000000000000000000000000000000000000..fb1bd5aed004286949a0fea90b081202fcf23607 GIT binary patch literal 1043 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFZ&XWc(nxO6 zP3tkrndn$rY!ch?~efDVMa+r+Z7rf;oX*8)D|{$XHUXnBHboyk_;9)$@O+gq?0Ey)&ct ztC_|b8@)632IutEx;<>p``TZP4}2Zzd&Avsd2;B(0JoiqVRs_@jwFU%iVHqdl=dSz z;%a&Jzx3E!)p`Gl(%O_;~C|OL!g~eyKG7TW;o+>hdR@t>2d{_$Mz@Z=!#} zNbii9(HUEd8(wY?4fLkOM!pLUIGz~$FhBcORK&U9z}*=sPbecHY3+03bDx@H}lm_IA+=+|AlpRAp=tNY}cjC5( z^mK6yskoJ#aDb_zg5`*dN{Yx6RoBX&tu03zoiZ(5HB&!&mVRx$cylMK>QV>AvjzVd zet(*_?%Xjh*1$)}uD2+@c4eNHwfkm+1py7a*R>VBZn;^kR<02lIirQCwT5Twm8(v-eyMGB zx4i8lA<5ACDcQ*Q(&kChS;4~H!k-=`H9F|thDm1)Ft SK1gmK$k(2(elF{r5}E)I+kQs? literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/ca.png b/htdocs/images/countries/ca.png new file mode 100644 index 0000000000000000000000000000000000000000..d06843f5f8e6dcb8f23724980d792bebede9219f GIT binary patch literal 1043 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFzk2n`x6hxR zJh*>q_l`?DHeWt`;G8V$DHWazD!kV<1uyAIJT#HL>!N?eUU!p~)>#+B|0({T5`2EA z23`qwyOthyA}QodQQEnZjK33`&Q;_*>2H28qwiQ(t&KCW5( zbIY2)JJ$a{e&ElkBVW#*_;vZ**^TQ?2{F`jF`N@&zNaQ}MPGiohV*MI?O*;*$33k7 z#RohO^M0Ngf2F7OEFa?;0oL;}LN^T6KiQccH`hCFWBkj<>6WwAZY!hbUJkGP-TsI9 z{*4O!7Vh^gA^c@xIe%-iw_3xiQ zZ(hHC{_NTB-@kwT`t|eY&u`zpefsq2-Me?MU%!6!>ebVyPai&fc<gab^EuDpIK zQLVOd<(V0FuFDSE@oFqt7ry4o)r0S{R+yDeieEUvIKU%(f!3Z{uO7FsXHWh$7zw&B zn6NSD$(_av*#?5 z3d>676!}zeYU;d&ITI%2Xy2C%QpsQxDSCK%;ta#H=67RPtqtGSaGysb<>=(M#(SqO zUAC*WGAUr+PQd_;z}i2Y z@1MVZe(Bn!U3+(NWw09+8y2lD3|kb)9m~KM$E=sB7COTxa#nzBhLB~QzFCp3O_i}n zhux>IANQXZc<|b9(=LW>`&hT^X5D>AV%}oKmFqRO?9$tR#N^B+i;LHt&YWU6dz$&o zDbA}`cpp5Jy>eMTB7%4MQt3?_mG|w{I(5R}$`#X>uiVnobUZyxl9HkyJh*>7NAY#7 z{b7^ z%X?Ws;GTrUB?*a#va&DK)Lv_Azcn@eYGw7+$?1oi+b@6rgZ_RuVq;H*hu=;~x_jr& zzkmP!{{8#)>(@`8K7IW7@x_Z5SFT(+fByXP<;#Il42IR`ym978H@B_|wUs@U8;Wr^yI-O&-1KUiB_jx;#c990cEwJPT=uZ~vJp+%1- zIVk!`M!K?=K6|F7#%r3VXIZ)6!l9os#pyaTuH7&zz4vD3=4VrwT5Xi)*v>IozNO6X z`lYhs@($vcy1sjT8=M>!5B{r* z3*9T6Rm*(%uoH8G)5*e(7Y!$-{++C~IB1fP@S{ej$d@ZKC1*YrRu2~ud-DA0vxLul Y4B93}ALU|qf-*aUr>mdKI;Vst0KUjx?EnA( literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/cg.png b/htdocs/images/countries/cg.png new file mode 100644 index 0000000000000000000000000000000000000000..f2db5185056bfb0948fb6585b194b4a5e02e9a64 GIT binary patch literal 1040 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFzhG*{P|Ltj z!@zoimGd|!?@3;+4lbcnLK5dBB+g0*P7sv8pdf!b?0@2sp}S+2(!+>SH4A7l1B&gy-f)9)m2&?%wtvl1~Eppr?0i2KG%NvPXFa={kQK;KmV}%`pfCZAGhPj8IB!eIB|mU_;JP) zCzy{NV?KSF_0%cWTp-_1~;EeZS7?>lUZ) z+ueTd^!l|Y;PVE%U%PyN?elhaQhuV4PYPu<*Jd3yfx_x}~>|0^KiS5Uw^ zAD@qYem?>Oe*^`74-Whi5bz~1;9FoIFs6X}nB?v5!qCAg>jC8K z^K@|xskoJ#aDZt>_AQmiGnMbS(9(3a{1;@bC(bn-YE9QcvTM#oD!t*U4xs zS*3Aq^>dNe`Dv4HUAlZCgiR!9n%IT%-jBRnPvyMGUZtnY#C4KOa))~*d-Rek<=d`@ zO?krH>cX>kkuCGt$=OkjY@*^%m|A;k7Tx*dGkMjlYANm0T%U_JRI)QnF40}TIx*)Y PD3m;1{an^LB{Ts58K*xV literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/ch.png b/htdocs/images/countries/ch.png new file mode 100644 index 0000000000000000000000000000000000000000..9899d788cf85c09a246452fb558f94b4dfbca4db GIT binary patch literal 1031 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LD#y>j*VvEv619on>c z^OdVt9z3{z_wJpuXV08IcJ%SRyT9JQ{qXX|vC6{JhYxKOW#1~zyGe?7g(S~*If1Qm z0-NOo_b3W)l^0qmC%8{p^st)59(BnbYLff3WY=oS?$A@*rLTP4Oyh)^<^dD+bJn^C z%(PlH6)!oNo_8|cVPkmH(|U)!$u%##osMQpY>dwPIP7$>TH|Q`ILz~$uhT(KyW>8N zyF6@9`#B%*vcDMUw%N_*Zlv$o5RaRYzI%P07duRngko6d%}y{)g8%soAS z_R-nXkIkL=^~iza3+DX1aOVBvM_UEipGF1#`2PL>|NsB~{rmg(@1H+^e*gac>({TJ zKYxDx`t{SNPai*ieE06%n>TM>zkdDV#fzs;pFVu}@ZP<9H*VaxcJ11gD_1UEx^(g4 z#S0fMoI7{!EHDnvoH=#s)R7}c_UzfSbLY-Yn>KCOuwnV~F(~XudfG2XCtD??m7_2Kl1>y%fm z$P5l(6Pa~IT>9-Ykt;VJYOhRt5gf!SGV8(|fea<_Q}?76=cURA9pn;8(&;epdi*pa z`^l4YU%sr*X5@N0-D*`z={EDL;ZxJ9s|`ySTf0`7F4^i+DU}s8S;#i$=FA4CsX3bt z)$C;4`t)Swx@*(!?sZuBORTWYu=9k>IuUjDW~!{(j)^ggpJ c5MX0qFx(!X${YN2Hz+_nUHx3vIVCg!0Q{wHRsaA1 literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/ci.png b/htdocs/images/countries/ci.png new file mode 100644 index 0000000000000000000000000000000000000000..d536e9baa2bbf15348baefe4c6fa25022fd29975 GIT binary patch literal 1040 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFfA;p-`>*fs zJi4RNt7tY;->lWZs@ueMsh!IVyMT3G{!2W=HwJ{Q4Nz;7Rmzk$nxLsssHjzH%d|Q^oiOO7`DbQYGYvJ`hcj7K_QELlD0?1tqV`t8e`RI zcJ z*ID5|7sS1o7Wr>w*3V@br$ZRdhB2QGV?G({TJKY#xC@#E{)ub)1BdiU<#>({Seym;~C$&-f-5O}M{R0A}NG0EHAg`tC0 z)&t1d=jq}YQgJIe;Q&)iOwi^o?WkS9e(U~>JUV5oqm$jt){E!n*8bfq)|A5)#pbYZ zNyCXfF~{%y+viuD>Bn2^yC9${!qIO+@c!6x>29v=>-vNOG_193l-DlVzkKh^lM}-I zL-{m9LfGmD(!|Jd!X^ExMY%~rFgfhLn#xLSXyA6K>5VtO?+ zYG%PnuMUP*roDHQY`kW_UagheW3j}gwZUoMyLB7mp7LJpG2NE+=FuUh8+(`;Y9AS# T$=WP?9~4BMu6{1-oD!M<0m5V} literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/ck.png b/htdocs/images/countries/ck.png new file mode 100644 index 0000000000000000000000000000000000000000..271f568bc7772a041538c31346458c4556b9b82d GIT binary patch literal 1043 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFpJZvZwyq(` z(PdUv!R+Qq=eD1iTH7Dw;J<42%GTVr!hrI z#NTcYn z%+=*ZJIV^Tl^1O-$={HgIHRUwcU9Sz*2euQi4%G{4mH+osi|C1QMxEAy>I%IV;!xV zD$C~0nR&9YZdqb{&D>ch=FB`|VcOvC(i0IfFFSK-R{H$fs@+WuI~(h^cC>9T%%4(O zK6lBY)4JMqHr8!fnUkXv7o2Uau8#^myJ*hon&M^kRrfcnS{D&`wXS@5YW&&yipy;c z6N3GB=A_SXuuId@0>&&ben$bG5QvKX`v)k^nB?v5!qCAg>jC5(^mK6yskoJ#aDd6; zXI47LN3L(yCr_+YJ@#6Pxivz~Z>DLfkn!r4;1#8wv4wmA8Ta0BURL*?eOl#O#4V9^ z*YEO)2t7@jfAYNAg$I{}gr+0~C9sM-5|}to`OfLHi?7H`osc>$icMrwhN(dKmbVk9 zyz($Iy59eWiA!`@cGZbnyQ_b1eVU$rEbBXCYfr|uDMXhz4 z&dsxnvTFM}wQ`ynql02;Wh6Um=>Hu&m$%GXb&i8K=N==2&IH5WvUFz~kjFh;{an^L HB{Ts5ayCn| literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/cl.png b/htdocs/images/countries/cl.png new file mode 100644 index 0000000000000000000000000000000000000000..97db9ec04d443290ff3354a602bc22fa97000df9 GIT binary patch literal 253 zcmeAS@N?(olHy`uVBq!ia0vp^q98U0GmtFwxe5|U2=EDUWnj3)!0_MF;+~n=|7wOF zFZcgZk^j#zFuVkcGB7-^tZrfGTq@DiQu%-HzGGXr{oi~1|Nq|Zo40OWyZ!$?5PS!M z_y55FXe1_x*q$o^6lF~Ec6X6y;g^i;#IIKSRD?duixpnbRB#40;UU)d6^+{X1k`m5+) Y=EOa`AxVwb-hyoQboFyt=akR{05V-;mH+?% literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/cm.png b/htdocs/images/countries/cm.png new file mode 100644 index 0000000000000000000000000000000000000000..febecadf56703f724528fbcdd5bd88a636354857 GIT binary patch literal 1043 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFx5~9<@L*tY zXJF7}V9;S;_GV`GVrKPX<@Dj?4dmrA=MoAQl8BTLv=fw1P>_$8mvom@Pf=G4P}GXl zvM8~zD7G+4GP2IL_Gt77=nQZxcMI+~DL% z!*l0MPMh)cpQ;S(Iw+LKt;=S!7 zdt8a(j2QbVUWU^GtQRDBZzxMV(pP(9XZpp*>8Zcl&v4(5;eJ1&15Yq89A{wI&BSnm zk?}Yq<6aiV)9lQrn3+#7GoNH--NVXyfRp_MC+9^ju5(;mXLxx}2n*a45xFKJazIq* zri8?K35kpHvX2xM?<*=^l9zv^ruI}@`;?~oTYdeP`ucB7P2XEtJ+QF&Y-jh)$?3bB z+fOgAo6e5E{r!Ih1bht$coh*2j9g$8j{;mFFm=yuYoHuslDE4HLkFuYFc&Z!^mK6y zskoJ#aDXY|X3GqdXa28OX`k&gD*D39$hGmKx5mr!@3M7PpY1gJ#@ENf^|9lW_6y&f zm1{E2^%`<_a4>Oop3v}?F1wPFvhBHQWJ~)m##WWkl%qVaHU|Y&e}25?&>!0dr&mQ; zOjb{?X1<)vEwqMt@0|vxuAoDAqC$P=3NI5^jrz62nz?mJXr-lz^sQgZ&uMv@eJ|O{ z&ei$3&?tNRH=mi7+b!;0IeJh`L*>NLL+ftaW*(bU*}759ugvVm9%hEua||zDf5N>3 O zbge0cg1e_1z1$J`ttq@-h@oD9;j9wp87by&ajx?!LjTJ%zL%w*5n(+i&wE8z{tOqx zTm{L$xhZEj7|(DrE>~6j7!q*B+wFgT)>%e|GYkx8m>B9A7|t>>o@HV@$IN_&nfU@M z>ls$oi|p)YIXTbra$e!$y2i_Uj*s_-fWUbnq1z%N_ar1PNk}}Dm3^Y9ctt_}ii*Mu zHMQl^(yz6(Z>XzpP*i-UufIuId8eA%U48w#2Ksw6G(MS{?$^>fqN{sQN9VYn-d8KD zQw9cSjSL@JSUj|}xN2s4$;9NmvGET(yI)RDx2&w5J32hDxBKJf_T16&sgu(`FRxc_ zZpW;x|NHvB^Ynb<;ql+!|6f4BCm)}`fq~!r{C)=p{tO8C7!dF+Jp5N&+~1UxAE~MT zv$BBU1`It4L8o!jMW7LkN#5=*3>~bp9zf1KPZ!6Kid)GE2be@GT$NKS_V8SN5>nbL z+nn6!6tgCWX{F+!Sw*LAxn28b=;@#sCswvG!&|Y?RhOB2|A`|S3nnZv**`^AzJJZG zeKVsYYGMQeIxLlsUJeLgNeXaU!5^SuYkFZyv|Ltz#boOM4c%Ko?oOOp0S)ck0U9^s z{9XCdCamAA8*oDSozeowb$nqCio(1zx)1HWJ2&Ud#!7aE55JV}ocDX*3-YKn{8vpD7Mx!l%npQqPG7uRbMQHO(qZzU#Qic4TrZe>(%;nMEr z)$Nq9oUZONQ`>u)wo8wZ_f)&styUomeY5s^ByaLe*&LX=Kc)5LSql8(j zlvR(8_iSyadegue_HnC?ygDobC%VKf@Xy^In6n|QXlH2t#^n4ux3G+|)~O|p6B_&H zHT2HunzqEsJI2O0&LJQ%B&9U9v@JTLG{3gHfA;dAq{6dn8P2R_zPO3~{3fB>dqrNH zQoDOd|LYB_2gmLHJ@)!^)93Hwz>hZquIzU^vznnko8jzQ#xrXe&#h&?u%7kI8rHLG zIj?Nyy0(q?+?v!9<#W#)8xl3yI*&mb}u#hbKmXx8ONumosMs?KDNR7|0CabS3KWb^7#MQ z|KFp4Z@2w^KM4GJFW}pq@Lvz(US5j)`y}Q6^NjBgQvW~CI>OIzOo;iYIOjPT-kaL8 zXLaQlsYFp zZ?KM@@0GLFK5D9S?9}kWm9F6pu|@M!t5!74ILWDBCt}qlW8bOjHABWU(;{YtP2^PTJGL>7OYhH|dUxj3Hc^3X@{;>h<&J8r95>b5X{vw8$!4de>0TT2Ywix~>@3fE zyB_d#xftSiKG=7Qr_0sI;44ufH)F%E$ArB|iF=$9H_OH0XNcLURRbp zEiZagUv(@e<3oS<$yqb5uUc_t@xmv&ckWY?zp!Z0zkmP!{Q2|k+qX}jK0ST<^vRPa z4#LN9V)J6%)rsHf+BP0f|&<~viTe(COhIAzMaIdeYD zp8amwvd=45UfQy6FYZaI)42A)vIqFJot9>=#2*t zzFxcbikb6FZ{O-8N8iktx&7j$@B8*YNX!u_wL>J_wVQ5zdwHe{`U3jhj;H@K6r5Z_U&soZd^Wc>C`J_S!i8Omy5ACpYh& z-9N^I3mq2zTX}cx=h@z;yt-FwYoB^8)!;Na&G76)t*(B54<9c-Pj7!#u8n7AThEPk z2#brneBjp6s|T4hj+`>9PLkh0rD@f+m2)TeZd45DsC@Q>^G;=5qvFFyf^H}vZt$`%Q~loCIB`GhL8XN literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/cv.png b/htdocs/images/countries/cv.png new file mode 100644 index 0000000000000000000000000000000000000000..6204e60b5a09994abd317624451ab7c747b2602a GIT binary patch literal 1041 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFKe}Vr;hnpm z-n{eu^}8EqFI+i!=GFa2kFMYP`s(eb6|47d-gaW&!A~z#AyW?zc*9BfK^PFru0=<{`dCW04&I|IH zA0D{E$+j*gbbW~5f~b%+_SWTIZXIq;4N0+^(-XG``%TVH-JO@QFFI^)pl?s0Z&y<6 zvXZ<*nJF78ijHQdZHNk+QeSztru<}e+3~`hZDob~lH=z!R-dk~JYH3Lu&MS;bM2YR zl6{RerFk_-{oLFOM<=y379QTw^X&He zqkHD<*)aFi-qp9xAAJ&SdMU#AxP$z4Z@rVzuE)(~j+x4wwNu#}Z2vhw>}rbNubPxs zC2=o`W53m<|LCaz#wjpnM*+bQaPU$#1u9}p@^*J&=wOxg0CM(wx;TbZ+)7S3z%*s* zTIS$nn;z3CS9sUR{5|C0q;^k}^WQWpudFJgZ}S!gIw)#hKk|gZIMy{ZSK0def)fP` zCghd`?U}P=;k2%Ot&{UzI>ZB3?AWs}a-Y>&C1vgPE7omU#-MTJ{Pjzk8V9f3J*9L+ z>x||h9+6qbtJl|mTB0djwfyW1+u~nGRyrs$e*30p82E7>pPn9{S)5$nf`G)dD(BR) zpu$j5A zhcqgif@@BP;Sj{Q_j0+w<-#zi7>_vw@g(AL5C8y$B9S1@cq|r+Mx&un zC>RXlI35TD{C>aB=fg0}?RL9dE~nGEv9aNBI93U9cDv1Hvs$edi^XIz>GgUPMYUS3 zTCGM91cqUyQV9_cfPWbja=Bb8l}aQMu~;k;iKeHgCnhF@LLr~e=ka)beSKUmx4pfc z&1MrR5Lx`Mf9$|zt*OsTIZqmsBg^UDb^N2gL)ZA&-mq&xD4+>Fu@eM@f-K3Tms zU)oV}AvAC)4;rC;r_EY*S;JZ9hoAEJ&F8LXr({tMUA%UGtL;5g@T{$4O5D#G_}KgM z$<4;I%+VsIY6VqU4X~`Xpy=4q+=85g!^q~{+xIrTP9Xd3>koT!$Q7W2bvh8%_BXug z`ElyRF7lm*1I=Ke@_4}*M{#R?uqK703-nZ&j5Vw?SL-ucDhg*hN{VR|PH|)9xaw86 fS+?IeWtvST$y-n6A5jZB|5!<(_6v@=lA4Kg239l}Bu{f#o^|j#xhNBtfY{HN(XL z(Z?7>7BGs=<&>VyD?gu0EK5jrsf6|_3C)G-7ONC>TMZo6Ynk;~c zKUcQz->~KAvE#=dJh*@M?3qu`pPgf7zQD?Qj-CBHFYgrrf!iV?_ar24%gWwUR9q}A z{YXvinYQ+7Ma38T`soN z#N?E*@h3aG3udNYoSd#&S$%VJyKQfG)Y9^SlhY3`uM76}Pu<*p`ucwH^?m8-`P1M3 zXF$M5Kfkv=K0g8jzXSw)3k-Y$6pW1g5*792=FO+KZ~y!9<2rasK?JlPCZE z`}gr;{Qmv>*RNkcfByXOa z@7=q1`}XY{H*Q?JcJ0cQE0-=^x_I&8g$ozXojZ3H7zAg|%$++I7;(Vp8wHevK#lx{ zB%prAByV>Yh7ML)4;rmYZ0N0B0?f&rmHjG z&a}vMDz6UaP1X(Y@R}HYe?s-4C7rgiXG?po`Z_39mdXY)`f|VCcWzo+*C{vc1rt`y zYulvLKd~}$p|59QW}sz&N4WRV2&bO@xt2Pn`xW#x^j!%qSnkNf3-mu*D>u6evS_}KHDyCK!iy1kxF?$wWE}pd5 f>F?gV8!Fiu#9kOAiATIi0R@bwtDnm{r-UW|l|EDw literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/de.png b/htdocs/images/countries/de.png new file mode 100644 index 0000000000000000000000000000000000000000..67e1bd53a66ef6f37921aaabad1102d8d82b0b59 GIT binary patch literal 1038 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFzhG*1+{*fS zdWMy?^|1*I$0xB~o+og2j>MWa#W%Z5?`^a=x5VW8akmq_3@7`UPfcMxF@f{qbly8l zWbdz5yfjaKNsaWY&HC%xly^+f*gZk(@GQNHOH98Vbb7ee>DhL--zWTkoeubT#P9el zgRe&dj<+xzYh^yu#eS+s=-O0~M~l_AwW{4%pnsrW_x)z8(=&{3FSq---|O9WpC1PU z-|Y-I!NYi*hw+>U*GX~Sn@SRw4b-2SYVR}FIca71+1>7{lhv;<-&cX2F9JNiMFsxM zPC3oMaGZf*EhEDTX6Cib%;#BI&#T(`s(WLc6J6@S^*v&p}xM6fq?;@o(YkW*(oVmSy`#6sc~^};o;!{0RjI0{%&q= zPEJmaj*b=<7N(}AMn*>Z`ud8Bit_UEva+(0l9Cb<5`uz)0s;cOyu6&8oUE*@%*@Qd zs02pnC?Gxr_AOp;45*qh$=lt9p@UV{1IXFq>EaktaVt6D0GHZEv#n+R^9~v$XVv?= zOM9evl}8@siEd3*FvVTu}zy29&+{CRp!=3+!3FWoA=n%G%E{j z{#IR$$2@j6-b@qLU2gvgwTo8M2u8wr>mdKI;Vst0D!L}H2?qr literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/dk.png b/htdocs/images/countries/dk.png new file mode 100644 index 0000000000000000000000000000000000000000..9404cf0bebc31e10e9102c799d797e52b4626771 GIT binary patch literal 1037 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFzbGj5Lf_zj zUjE;_{Nua#oH}~s|IZ)KA3iwC$Z&>%p`L-^EFl!cb4FQ2}F0S)JLgz$9?@379lajn7Au&Zz@S&{iZ8^Coii%eh85nHR(ps*e@!Hbz zp@qd&Gt)~ZCg+Wff7sdma&p>jWc1b9`GLLNA2+vyW@b;Foc?)vowc=j<>q$G+WNn* z?+!k74Ro8)n~;#-v9VYD{9Z;z{!K~wo|<|lF78}>{FR)X+l7T!3JRXo)I4lxc-Pr^rlsXV zd;7J%zB8SjcNZ;svuV?>Lx=vKJb7XN{u?JxKDm1J)8oevFJJ!i?%mTHH!dAJ_V44z zZ!cf||NQyPp+ncsoqKre*46Xpubeyg>&us)pFjWj^y%G;7q6Z?xpemIxl^ako;vmI z+qdV>pFe!~@WzcB7cX8sfByX0vuDqoIRlI-V0?`NDu%%HbB9j>jblvmc6VXuV3qX% za&~*VIEGZ*N=`VyR8cV{=JT!K)RrBrM@35B>~(P3WLCISw)4=PKZ}Z9U7OeFpjh~L z#*I1aSnT2iHAA(xGw?5%;A!HWQRZ(WKG|k-Za_tcd_c$AO^bFcU9Yu&!G;w}_AJ`M zqj4qTeB||O*P~)Dhn&B7A?7rnNK&uKlryh zcI2x}rq(kJdZ%7^G448X{i0KRG_S@Ij*`H%bg2ujde7W;Non2K!_1&RN&B?;)#+8B OAo6teb6Mw<&;$Uc)mrTU literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/dz.png b/htdocs/images/countries/dz.png new file mode 100644 index 0000000000000000000000000000000000000000..26919b18c061aa593554808378053d2ab17d41a1 GIT binary patch literal 1037 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFf9LM;P}Vk9__8owrhfHA_gLSlMfiFGDN?Lkt6h zB?EIDGiw4XYdkAwA}4P;FK-I3K#l;H3zty3kVKAzppT$zsjOnPqI`+Ge6fOjp}b_M zqtfE%BmPMO|MXQBHvxQNCkzRWvHp4I1?g>hvAE9nzMk@+Gp1#BwTUNJvI< zsl*Ehw%I*+aR2JnD`(H1xpd)7sreDQ3h0Q2#w6PAc@J=(tI3qg3YuBz_x^(Hng$w7;pFeZv%&AkSjvqgMjC8K_H=O!skoJ#aDd6hCFE=FnG%+YS6N!8 zxi%X)IDOg`_N>ZFF7RdOQ&-ELoeqkUzTDo<)&FM{OxyCv=GYsh1rypjw{C2XpJP2e zKg-cAZJ~I;i37(%PU~7uus2ejXsf(`i)lQf7Qa}s*`VWY=VN&K?~iTF#%6v0`Cei?=@6kYh!TE z&g8JC{Z)2`BdIBmb26_oGM?e&Jj2U-PD$yKy7~=mokK=OXN--HSy|n(w7BTv{K(Vu zorlL8PmgB-0Y4KGzNMu6&B*wYy=HUTzMXbc8yzY$X3n0K)SNYW))Z?$tEfEx)WX=< zln4(W*L4T$mu#unakws{NG2#ky`x|K%qfO*XIajk=DK#3_sS)O<;xZC-qC;k(&oVf zyXQ|G|NZkSEmi*X$>;Ciz>gmTu3T~Z|1YDn!|}{9hWcuT3ny969Amw4Nuax(>(W_? zDH8-A-jRKBPjT){$#*aGAKulOJW=k`8`Dkev^K5RdU(g;$7j1=U!3;tGTOb}=+Aez z$rH4X9kTxa)A!v=&)3g9{{Qs<_cP%4x4@rY0+uf|pE}9#+sE+bi|u}Wi+lMb^6!t7 z@1Ilu|H|69F67kl^aH!25ARQ2wJiMd`GPywORrume{iRxr$u>EU(kXnx|yj?E9Ny# zE{SNUE}v7Ed!;?@M5xB(_U7l=K}*|OK6tq`<>s7WU^vUne3p~*8ZYlLDai-2vR4%3 zmrF};QdWLvV6b0H>y&}PRWs99Zf;*gf`E|=jN(y%D+DAyt@H)TF(!GtyD)UH%6b4f z2RvOILn>}1Cmdj6VqR>d)g^SeiMh#1>G7o^N2iA?pQ^s|<172tCwTFsh|r^r2|%M+qiJojmr`7=Qr$JwQt=r zA&n(#S1M`erX?*{ovgWX;kq>(BA0?DPo8L$`_|yq<_Q6zK@-@yI6FRYc7Fcl{~~j< zkcjY8aW<~P%^Qt2`@GG2|K`=xhmW2luygs&w<)|dC3Ewy=f-DeTc>|JBY9&FGsBex VqoC3+&7fS*;OXk;vd$@?2>`c^Y`*{i literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/ee.png b/htdocs/images/countries/ee.png new file mode 100644 index 0000000000000000000000000000000000000000..e0a902ee770989ef2a3606a2a8d5b8d74bc583d4 GIT binary patch literal 1041 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFx3;o2Gd0W3 z&Uy6c@$us)eEfoyR5T2Y%^jTFf;709=MXkERPN$`&{`>du&!0cPe*OCS^XIp3-#&f%^zPle zH*em&diCn*)2C0KJbCo!(Zh!iZ``gCIqXJuu@#l=NMMTLilhlPa&1_lNM z1o->=`}z5~ySux&xj8vGSy)(@nwpxJm>3%y8yFbq>+35iDJd!{%F4=0NJxl_i;IYe z2nY!9^78WV@NjZ+va+%=GcyCD2^d+UfVv?txk&yM&_u>0Z+91l4pvzYAZNd)i(^Q| zt>lCQOf0Nddt}#?PEl!9c@naP$G6c*iHohw%xzWBp+`oiX6;f-b5N|zjjs0QjWi6* zbSrKfK?y1A{|MSa=xCycF0 zLP0@7$%~zsnVpn`FKsGnbc#Ev=~-x)=-6{maNkPFcRz3JVP;tUK`->o#1E%IA?4}n K=d#Wzp$PzQ5j9c( literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/eg.png b/htdocs/images/countries/eg.png new file mode 100644 index 0000000000000000000000000000000000000000..f81b276995aca76d17859f9bef3d41e1c5bf9b78 GIT binary patch literal 1041 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFKP(}2R8p#4 zQtH^g{a4SOkBp2qGc!MQ=%|~!=htsPGBUG{pE~pA!>8{*f1Nyi=J3&DO3KRLfBpLS z<;%H?7tda}@cZxIUw{5QeEj(C{rmC?@+VH7ICgBSnVG4tuaCRCTU1o!$rA_f-#&8r zXzQt+#cy9fx_o@r-@~0IQXGuyPQ&xVduYXlf@2#onT?>n^PEI?F zjDEPeU9`4-v!+-w# z`TqU;w{PFRe*OCC)2HXppFe&2^vRPaj~_q2bm`K?ixdrx%?Plao`!6yOmMK`79*pdeGx@XU^$sF>*~k zX)!!)ljwZ5uSH}ZM&de!=MD^_J@WWHzO^7K!bapnHqnBd4j-RoDh dt~8&uW?1`F@9xZyrU#&)@pScbS?83{1OO3URu}*P literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/er.png b/htdocs/images/countries/er.png new file mode 100644 index 0000000000000000000000000000000000000000..f96b315c7ec6618f81fd772ba56bbd71e2f22431 GIT binary patch literal 1043 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFpJr&XCLrWQ zS@q7Ms_79)<-U1SOQtOEUfEtaAt85J^Q2Rala3{pE{m<+Y9H0(U$Dw8af(OEbf1j5 ze%bQ_auVTJ4GZF#H99d<>t?~G;txHe~JywI6y)7J}+hX>bAPr*F_(xo=?w`%>*=Q?b&;o54)bEhKUNpsw-riAmwVS8MZ4*D8wi*S0~ zma|!dXSoK?v*z5Z&RS2SoR0fjEpRq^pB|7W%D!8bcY_lD7IlH+hEn?sWsjPx9JW^7 zWu|i6M)QoL?nzgp%bup!{H#w0J3mVBdzBILDm&s~dHQxKw!Ly(`63)!75FwQ3G7r6 z+NvVBOH*u*j#Rar&@n^B-A0Nns*+R9wC)Bu-i`LU8R`8xJNiy$)Pww_msNQsf*e~E z1P>^S?oyX}8y|c(J^EEe{yJxy1Ad;sC>{tu`k(Vy zGjp=&qelx?Rnadyn0R5r8_G%@8vlx zeDk2-yvF`X^H%L@TXyUu_ss?;^Qp%BMZ^NqqPu zG+>fABiGgNb6J^h)1N(<7#8?MTwIiiD^x_(cw_NtP4APZJiIzMxf4F~F-WT!ea!j) Q_8iE+p00i_>zopr0NT_=82|tP literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/es.png b/htdocs/images/countries/es.png new file mode 100644 index 0000000000000000000000000000000000000000..c85447dc230b9cf527b07b0c0fbc27e79c871d89 GIT binary patch literal 1043 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFuZ~S<&n#cH zLu1Qf?RziO-hZ{ac+>dQdE+1dyiS~AICX~k%sKXJH$)yiReSbAd+ScMGv{;<9MOIM z$?En4yF2&ne*X4)`^o3W-@qTg0^fcNxOmy^=kJuCe=@#&Oa1jH_xKUU<3|}!onk$E zhU>z4-jm09FJBhew@>8eO^F-VByQi4y?0|AeFZGu!RebZ-bl*OmW5*5Fta$xzAg2RkY&EM$?12dbjH=?zK97 zpB``|nCViYK)?x;3HwKT(VJ?3LZoafDX z`*j6xxyhb$lYbGR|0UCDyT8$+6vv+>{$EN0zOPJgergc;_CAIQzAb%IJu@?{mN=8s@i&V>C>s9 zTT2}j#VVGETt&B4XNnzf<9cXHafx%Sn^wyd12p7fcI YK|a;!^;3BYt7Wi*|oXr+aqTdl&x=0oRh~8Ex?%|mN+LfcX^p?iHdH8 zzEy=aLlgsp1p|XQ19J>BYaAK$tduz^9S1w~GPHu{`G(IA zjGG;qxiW>{mCL9}+jWwi|6~vUDW1hEb80r1PMM>4?7aS+XI3XK**$shb^D3W)Axb5 zp9CB@>Gtwd#`k|=r_S;`eeU?;mD{gBem{Q2ojJ{T_6*;pOHx;^DqO#&aqxi7nbSrm zPZ>UZXmRP1>6I&HH*Z)yed>JtnDx6ip08hd{`(j3?VI1vp8>yq27UV${`*(z_wQ-{ z|7V>sV7MEh{~*QgQ?bv-vVb#&%;)Wdc6z8C3D7+sZoJo6>RDO(83u-P%*+>9S;y{K;V*u#6wxxD+=<^wi1em7CjtfB$cOem?^OfRPJ~;!%Jr1fC!Mw+tx9nB?v5!qCAg>jC5(^mK6y zskoJ#aDd6g#OKPKH)p?=UfKG!=ggX%MyFY9)B5c`|`Wv0(%6w%W5@bwCL#9bgbN$2EwPk&~vt6^8Khnj6J{Jd%Vl@N1NGlte> z-%GY^D>vS_!RY*K+u~PGI2{)5J9ll{x_h0QpPid;oP2AF=ieK9m>F)KGK!6ub?N}f N*PgC^F6*2UngHUKN2~w< literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/fi.png b/htdocs/images/countries/fi.png new file mode 100644 index 0000000000000000000000000000000000000000..d408743df26fae9ebfb34208456ecaef616fae24 GIT binary patch literal 1040 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFKYQlf!Gp(+ z9zFT-yZ3J0x_$QSxkHBzZ{NOyRWMONI$Kev($v1o z!l~87w%RRVrjvJ%wNq6<)O^42S>XxuvWnJL)i0VnW7n*CJ6Ekc%`TcMt6d?hU2f)B z@95JT5Hl}4X+d1(vb2Jgb?v*-a;LU*t;s3q*s%4=@--(nZNIwr;B8jXWNzs+UYTqG z`CJj@97&B_8O?kJ{c?HTVg=n|b(2aB(@I^NW_`O3EsIJ6n{sQfey4!x7A|#mULB5p z-A?{JZb1|MV-^HNPl(T27#iPORJ*C7d0YF${fk$goHlzii&!#?SQ5KLDyMWRk8C=R zOe()(jgHzI^%g>C-1qo;-Z`@ZP<9H*VaxcJ11gD_1UEx^&^fg>&c5ojrT@%$YN%PMtb_ z{P_O;`}geGvwQdMO`A4t*sx*w^5t{q&Yd!4N_Tg6eSJMJzJRed3aAnSp_|t22O7kf zrYYv7{*UoTO+HL)Vj>A58ZRCb#b*?tA_KMHMGo@W;mCC8fFSci8wR^X9C_3 zfn#ul0|h^QecK`KPz@T6&x4T@Z)u3GiM=yU%<&-Omge($&UeI8s$jbDS=iU9y% zO=1ELAI=ToiCh&C_RFKu^#Bk7Tu4ce3**w#l8D3A@Wt|a!Hj*ZiQPa*$uukULI$5r ztg<3~pb)%qHGjn7vKs7_#QK+xnF^`|?ijg6;RxFtByuhOQWO4)pqQaIILGt&O6`j` zDvzHiL`ZGg0+Eg?H5IpaA)aZ(=A`MJ6v#{#BZXq*zSVmRM5=p6%VfqDm%pyhRonuV zv_c~HTdGje=0w|vC*|YsJH4~4PQ7X(SRsPpv3ITgBTZ@}MKef}nhGRHfmmA%nQlt; zMUNgAfx0qfZwX|ifCy7RL|0k34wRvNLJ`QTjdqq{D6h7W-Q#Q+@D%YS4OTZ@im)_& zO+(&0U>8lStkL!}6~+okCwVb*zsn*U^S9XC9NiPx_g?hOt40IhbD#EAQ0|%TbWa&y ze>6B;WDue2hsqS)bhx`hZK>7|FuN>;-1bVPsjhoajs|)C!!R09qJbi*PBS{*uGV;F zrV)c=*rghTul1UBe(3aP-MM~?X-Y{(od!4kKu}CjbxIv-SxCkYvdcovtal*4H~xs{ zTJpC_a)?2CTA2NXUH*nu(n!b*s6aR)Y3^R(9P9Q3jo4Ge_|dJg#vfxI-1Ur8Tbh($ zxI?qcq~VIgMgP~o9|)bynhI~15t8F^K<&!tgfQ3=ac9zLleswq%h7WCF3iGw^6&{2 zObRv2mRASP3yu=MkC(5$I~OCE`~;;i&z8tbzn%Xe^r~)-_$EE*^;Osn{v46b6|-H_ zkacmw_Zl0CC9K~h+PlN{98zRuPQBu7!C-k@V{8VmdH=#9{-gMmVE4K`ja=TB){ETP z^_$bOr_-Xgt;HrC@V!K+i@w8&F=^TPQ3L?H&sCa1U5Gpwo1DsdSQoo*1!iOZakKeX ljXm@7&Yifp6+d$q*8&}156!Q{|IYn;Z(>|3PIES=>JNm|q@Dl( literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/fo.png b/htdocs/images/countries/fo.png new file mode 100644 index 0000000000000000000000000000000000000000..1e123760d5a3c910bf4856f627b4749c0f4568be GIT binary patch literal 1041 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFKgz**h?DDp zu;@V<#Z%e_`*n@>=$qcOb=qNVf7sFWsei~7pMdLuVXvbTp2Z}*$jp6FP_ji?Ymct! zNn6+J0pWYR15XARXo^SZ^?Q-0Tsw+QMa4|NQ;4apU?we|~@c`sL%t4-X$cxOeaF?c2A`ojZH>?3u%d5AEE! zqr1E7_pcvkPMcqdle}4b^`Tg71cW>Xkdimnzi|2Rm+`fG2;`wuDk25fwW@J3h z%6f*K{jz|-86lxNva(my)gL=Lehv@6bNlv*U@-@API@}*0cE?&HN;lhP;V0WB8efq=+knY2W5AWW+d&iC) z>({SevSi7G2@`5-Yinw1fKdsI&{05q2uR&iNCT>7O!9VjVd!9$^#F4Ad%8G=RNP8V zIKY&4W)1(vl|kG6XWzJg^WLQ!3_`Qw#8*YHOqpr7aQUvSD;IKVOc9zXy)JxV&eR$6 zr%#?baTc%0rcyI56OG`4k6*TJEB^Ail!43h^l8rm5o7M|jxNtrC%ihDTU%HvZ$@&> zjJRo0`GfVxj-3roW^u><{c`PEm#3EYOl+ClJBNicel!`p6%w8QqGQF39W6^z76iD* z`%Va3xhi;>TXD|&C7Nvx3)gX)9-Q?wi&4@y_wLro%l!^NlVxb#X83Wt{Myx^Q1Ep1 Kb6Mw<&;$U#{H);s literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/fr.png b/htdocs/images/countries/fr.png new file mode 100644 index 0000000000000000000000000000000000000000..39bed1abd448a0c8c9bc7895e20ca63578959231 GIT binary patch literal 1041 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFzhG+i?(Ihg zhT{wj#~2uDn3+#9GaqARJao57)j*-z0OUqM^j*qOY4_jLu_V9S&=5{e4;B9#L zM?b%-adBTGBcGgTL1AmeFe<>!``AIFcMK79E2p+m>6U%!3+ z{N;1!F5SEL@Yu1F@85s8ef!R@zyHo%zI@{B*<+_qzkK)Z=ik3yfByXZ{rmmLkFVXj z_4L`ZOP9`Hym;>P=@TbU9((iV)x(GPZ``gXKS(>tK63-sGbBg10`2IovnP8%D4wzK={ z8cQ?1&_I4L+Y#ur}{q*ws@jsQGVN+wXIBwFU!Mr&jjr6_HiG^B&xqFfTf8601ni zmEft=E~>f zE8`Uk6_jh1Rj89Un5^%-$jP|MC}6dJ;EI5>jj3#T3|6yD?c1#Lc4e`+GO)NXa2K)i z6tIfb2*}k)sCOyKCP>;&w(wcu7Pc-RW=*(qHKTGBqjnRQZUe7EIG1Iggv&&AuesU| z)mpJ@?XtG}Ca>~HS?!s-J+N?nWbOWx14kJ4A7(ysg8j&Gp>vl+?%Y?KzfkegRsEN5 zt*+g)`~1!8#cQ8W-vUpcb9??O;Omc!lP4IC9%VXwnCbK>=Cfy5Po88wb&~V+X|Btc zc#j?9yLv_7+BM1Z=Opgkm3{a?@zOJ=S^sTL1k!)7^V?PMk2fc){fUJ&R+< zj4oX?`|!c;`*)|ym#u#NbbIpH;n5?fqerZtKXd!@$N&3xzdyeNo<8;b{K@b6bFXh- z1HOC-`usWk`}er--&4PRP5t{P3mCt^SRMsfL*U4i)mwlPj7i?^E({&4vK~OrK~ERQ zkcwN$2?v<&+^LO?Vg9?vcCO8ynmK=&8=TyxmG!9|yY_5Znpl|Gwr_k63pcE2IdY@p z!h;19KAdxN2phFx4nhi0zK QIRNsqr>mdKI;Vst0PFHlDF6Tf literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/gb.png b/htdocs/images/countries/gb.png new file mode 100644 index 0000000000000000000000000000000000000000..30035dd8cccc376ee92ab66d1d92883f08c44ee8 GIT binary patch literal 1043 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzF-;zS>vao*?ZyWY`br<>nKXRi%z-Z|R(2mC^h1V>$rPP!7CdNDTj zTy*keFaPU>6?e;OFBg`bs%?BWcj383OP?J*eqzVYS$q<61Z8FmO3xFPog*weS6p$a zwCW0Z&Be+(^OdxhsT*$8Hr=XkxkAVEfQ{Q`OQ$2Qe&_rnE`-D$@DE?^>T@_K>Pk%N z#pLX3Sw#mIEPi+L%;Q5xk1SvH>eSh}USZQ>Qjb)%6*+irm@)V4<{hsu-)f)~hU9)Ze(yO}<-8yjm*_q47Ht%?I<6d1v!K{Xf{kd&h7jE?RuU@oxOHgQu ztY(2*K#!)LS9rp#l*WMux!nVMJta7CQMDvozO91otb-WOwPjG@|m5J zwgab@ZmY0@=q=^+4K6w_B{&Vv=cCJ(w4xJbJ8c$R7b^NcS zWaqJPZT+T_=|A_5y5c;cQ~MKws(Ax6bZq>>-BYHu?%Xh;KfvA|g^RAyFqGQ6nKyAtBKuE8C{1SgRnPA}!serq-ve z-KegfrJ#@v6x7g|q_5wkrIo9!T%@MfX`o-Cp)t+Wv|d-YTuZA)SGP`2uUc2PQb%W& zl~t3GVS|A|i?Q(p3yTgj(>4>6d3JV-oSb^Ctd_dDO|rLJ;^sEZ$!WQlSDl5$Y&W-+ zzP_{E+*bMf&-3)0 zO3S+_Xpi9Z30qdRMmOv?4$x4WrmSTZd!m? literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/gi.png b/htdocs/images/countries/gi.png new file mode 100644 index 0000000000000000000000000000000000000000..afb539b3a51743292da6d117ddba2a6f930dc483 GIT binary patch literal 1039 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFuM`r#WoCZ9 zps?T1|Np=LSFc<>e(d0u+%X>pW zU?MN?4k4lS!ors%Bp%Aju9uK_qNsR9L4Jp{^m1wG1Bwb86cuO4%AVKIc&D$wNm+S| zs_GsMjs03$(-akt>*=-1%bzkZcxYj9)y(vgiOB(D;|==yPo11zxw-ud2>9mbcgM}G zPfzz}K)@U`vkn9OGeLoWGBf|=<-N?wIg^pGB{A_rN%4l%)V`pgkG(xR^YibvwH~Rc zIN#X#puhj)!UdPQySGlCzJ9@iA78)z{`vFA_wRS_+&O>l+`oVS{{H>@=g*(tzkmPw z_3I~4>IYEr`?qi3zJC4s>C>l=A3wf(_wLP`H?Lp6e)a0r%a<>oKY#x8>C-1qo;-Z` z@YbzcH*VaxcJ11gD_1UEx^&^fg>&c5ojG&n)TvXuckkY`Y18uM%jeFWJ7vn0?(XjT z`g&lD0OMs8&>;kN+veE-tzk^^c6VXuV3qX%a`t+vSa|K&q9=b|C}^99oowPccEx5vK(J_Zp3{O! zyH*#~qmX9O%-zJ+OWYkf>mn5SughFx#}?90w!S1%|wXz!h{S59NfocKWP z6|0x!zkek?J6!Jow@4RH>c`JUNn)a(zj5|)@N+YA-OM=QeR5?6cc;Z}i(8SiBpF&u rM3$yZG3{+ty)!pw?OES18!FiuCfVsqU-%ui3>0{tu6{1-oD!M<@5o!p literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/gl.png b/htdocs/images/countries/gl.png new file mode 100644 index 0000000000000000000000000000000000000000..66cd000ebff6be325db2af8f781aed5c991a1e4f GIT binary patch literal 1038 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzF{}~W?H8|wj zy7kA7AAj)R{>zIO&N4EbVPH7R$asd4@feS@OnCS~QFYHD}&_3s+! z@6piMucdWFSNEWf&T&1xQw9cSjSL@JSX?zTy<}o?-q`q-mDM#Xt4}V@5A5xpJ32mf za(d2y?fK9 zP0N=rpF4N%lqplXySwY_>w&QYjH6LNqY&^=kNpEQnlZ`S-G!lpRn`N@+2iTr7*cU7 zIpF})u3fhxgBSm8o;+JROUvt1k%N=0E~nfwBc~w7ty7n>_Ov=IJQr3b?#(Kgr+4wf zCZ%J4f))fs&z;}fC86Kmu%oujFOO3?KtuazXn52N{{W|R7Mkk1w#*t&-ipe}iwd3; z5*B~`?9Guk3?fBac(QZyR;||3_S&-5;L1f7uA3`vnVMe@pDzCVN5o8t3=QVi64jq~ zjUDy4Hkn<%9u&;Nb&{*_lf=(9mMWu}uQOL`pG^MD$8f_$&sf1olob?Sp00i_>zopr E0CiPi5dZ)H literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/gp.png b/htdocs/images/countries/gp.png new file mode 100644 index 0000000000000000000000000000000000000000..e4a6159dcf0391cc939d279440e372605277a4ae GIT binary patch literal 1030 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFziMiB+{*fY zdPcpq&6)Vbb4kf(Q_`+w=S=bQe^^mK^t@{Ih7;(<#&ctyuGG*@|zAmwjKc`b=8(h0KC8>3KIwDlfHk zcJyF*9y1VIhZ^ygI^>;eDo==|nanY5l3TO9n zKD=acX}ZLjddBCA9KLN1KUd28adyCsBK0#7tp9tn&L}gS6=b|?uYX=z=vR8&88(Kq zj0|TOfF$D?M#gh2%x9RHFR-#+WM{v^#dVFB_Z% z@Ml24$AEwYh7ML)4ihBa`!H&Ye9qO->FAmrR;>Z`qob z6CFFQoat)ob6XJLXWs1}P*f6;9cqBP1Fo+_b*$zcN>q!74b(e zA4v&_&Yu>0^G@XX5FU|Nxu3p%<7klz360_qd3B1rkFQ-aByIw?$Rv@lpnwoD!O4>* zP7a$WAkNAaIZJBws+G~VU%#@vm32EKE8#OAgLaz%zw08O$)K?DboFyt=akR{0FuZ& A0{{R3 literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/gr.png b/htdocs/images/countries/gr.png new file mode 100644 index 0000000000000000000000000000000000000000..1fb9d5233714f4d45d55ec008f86399685e405f2 GIT binary patch literal 1043 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzF?`WUp=&;z! zbBDFnr0A%X6DM3{Ufqt&=P5~myqa|km!_>njkAXQ$=N#zW#D^ z^OXh$Qw$BK>gsk{SS&U%ndIcO-OOy7o?eZ$^*m+eSOmFxRc`Ley1M<9mD?&Rwv?5v4-T&G>$}+7 zd%mh_Q-A-twzh+{wOcwm4mUJx&CZ@ackZo{l7-Wzoo{d7HGB5e88a?Um~d>ugd=Tj z+v@68FIjSL-n?temff8;?fBHG$JVTQxN6n?rAx2RnR9B*nme;+@0dGx*SvW^v~$_A zLkkw{Ua{ivf(5%aZ92PU%ejLG@2p*Wbj_M0hY#PGG->I%b1&x3-FV@`%jL^=U%mS7 z;>DMjF1_5i@#yvI?~We5wRi8){rivY*>kw5sr}Tci${)}-nMPe{`~#u(G&OYKYa4!X+`D6B}?zTc=`VMi+5+wU0$_%Eiit8u{;W}hJbSZA2Xl? zW0JSK3quF1tOt;D(9^{+q~ca`!T~0WC$q2e>LlB~S(`hz#%a;x1}Cp|mz(Yie-4@) zd}(uW_o-8jPG7mxeCG?P95{SdUFX!IrK@>GCVhQpm{>OR;@zv3g>mnn{9Eau81`)^ z*PkS@XJLKw{!I*AxX(dx`;wV%tBf8MWmUB;OFNeH%VFWPZEd%9%{tci?b^M4oS)TA z8Cy$KSa(`fwz@0{H8Gtcx>TjXDRHxG&YL-VnVug}KhomP@`JJU)8gh5eSr6Ku+-`A*+sS2e?X;#Q~nd2TI>y?fSrv@Z*qzAJpe5x>55K~uJRcPtB^ zy+2{irRc@SgC=eA?OG8uaYM$oyFvZy!lrJGnzbur!n(MHhx}R>BrQ1_Gizt&+6!qb zP9`rolDGLr!S-84JMR>3zg@WFcHZWznX670Y`K=Z;bQTQ+r`^&=B>X_w(VN!mdg!? z9@p-@Tf6&K?%FudwPspi|JwA8 zS7YYw%isGrd+W{g)o1cIUrCy?BWuO6vzM;ePgv_cW3zGRGLx?5=Dn-zrf!Z|y038C z*_PvXdM`YG`tsHJYu8R*xN!0M_4`ks-hTM-$KSu_E?oHf?c0g7r?>9hzW3O{h3l5S z{rGP4(e0BKPF=ELSyppS-Q>C>mk#H&CDrzoE!aFGy3o6@Eh)Dl{@}^oTMjMno>f!X zlv7w6-_-8EZbSXeo7ayXJ#ykm#IYkSlPA@$U%lYpzkh%J{Q33k*Uz6nKYjZ2?%lg5 zPo6w{`0&b=E0-=^x_I&8xpU{vo;`c!%o$*u0%LX*5DbAddz0fpMT|+_?k)@+tg;?J z&OuKX$B>F!$q5ITB5t~rT;g7Kc80Nfe1L+3wT#9QwVW4ory19Nn-jTlQscsDVh)P; z67!b zGmQdH9KP#evTn)R_1pK&JbEr9oKxdTmiF1{5jSoHguZ?+wo+V)Uu09@gXdl+UgfOP zJ6p_oIcOpymnK(Xu}Z4nT$_dW_1&C}J(x69P8>ctZ;o}U(&HsO$(E6thB@~b8QQB2 U)n=|;r33Q5r>mdKI;Vst0Erfp%>V!Z literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/gu.png b/htdocs/images/countries/gu.png new file mode 100644 index 0000000000000000000000000000000000000000..42824383950a9aeb0d589503c4a2e70328ae0ef5 GIT binary patch literal 1043 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFZ?34CQri*a z5mgY^9_f`A?pN#QnURy)=joEBs~#5~)Ma57@9f$jARZy9lB}qcE25YXlC(frEsa4U zmQ^lE-M-N-sKeT?kx4FvO(B6@A%R0Nky9y&TQ!A8J)K82nO`GSSSOoT&Qn-BL);)w z!XR75yj;$-K*_pN)uvR(xysP9RoA&n#VpCxw^P?X&(y2YDyUo6KFdCQlCfKvk!y)f zaF?ZTy@gM$xmT4-^i=ownPwiv_Q9=o0d;QCeJ&AQ?lJuVY4hD<`n=;Ohh#4b&RpP^ zJl!{GYGB%|u$)D~8FNFk=7;Aj49%PqQ?M|xY(-Mp^7NW@vH5c|YSv`dtjVcgpINgi zuWmK%808FVBhk+rP={2418n#+#Cy@>70|vSJ(cmwqSzmq(xiyL>XCUZ(F~5>C8mtfECLY qEm^Z^*GBDHr~LG2?^;>2_Y4dd&l)Zj^PW};^1i35pUXO@geCw-eh`BI literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/gy.png b/htdocs/images/countries/gy.png new file mode 100644 index 0000000000000000000000000000000000000000..a5d0e8e52036101ebe941d1bc624d73b20e46c7d GIT binary patch literal 1041 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFH_tV5t#WZI zbdBkZPMMPIl;aTG78qFTA3q^Bd19h|u$F0*fqATvb)uPViiKl_O>9SaVo!A1q=c0I zxQr=D_Gy*@jh=4#4$fJ&9tBR`C9YmYF1}^%vAtn|)!vB{BEuT|qgsN~rzT`gPtKf{ zlr=5cHODTa+b*C)C8o}xY`RZot83%Jh_cB+9m^9M=f`v`OFFZj@7zX#GaCfXZVxD0F7QL`u^vX8z zvm3;&?U1^>P3p#Wx$_(3?;TXVv`yvVVXX%Tv|gMxetOdQ`Yz+w=PW*5b^LnM?bm(( zKM#YSo%Z?vB>Lxr=&!dE_Z#r-H{?HLDs;eH?1YWfF&CAK5!Mg$gWor2eC;jSD=oZF zPVBIb$}wZ@^G?=Ryqs?ZdB4m^yqA&mrZm5lmt&6@U!#QZK{fd$V^>r@0x$Jgx zc@i7_p&;*dVLmWUfiXJ@2!_ByYfe9)BE}?dcNc~ZR#^`qXTPV5V@SoVn!Wn>C;uBS$?$N&L~>3f}6S3 zs!IKwR-fTlzO7!D9tMeqGI5pqubLewk|UFn`Fh21wM9D2B3Uoi&y9PKEhPE=LDB(T z6?IOLSr;zb>7GAtV|Mi9-HuSlC;^Qt;dhNp&CggFp1pc{LU34@yhccHq@AVxEj`o2 zhlA(4IyZ=GgoIu+S!!@l(N_Dm@ATL?{p_>L8D@nUb}orq%ntIrr>mdKI;Vst0IY6E Av;Y7A literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/hk.png b/htdocs/images/countries/hk.png new file mode 100644 index 0000000000000000000000000000000000000000..e5fa24f60040eaf5ab12fe407889ef8fa9807abf GIT binary patch literal 1041 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFzj*TK=^dNS z&g$E*$goe5p;q03r>}<2u|Yb$L(d@*dLRZI<>rcy{PZ6M=&!U=o@b`G z!A|XxxBg}ajiPlM~h7T1C;PWqXg@H08;WBew@ z?v%gjX@9f#2~O`4oGye|ZT2wwkm7bH+TmKH-N$72JJF7}W1RK{TJH_C{*vi?Kf&!u zisz#wk1yH&pR@g6r1`u^_xYR?@H)fqb*A5^+`x~yf$y>c-em{8%L#a%6>vJ%?M-3$ z>w@qP<#7)RB0txpysu4tSDX5+DeG%f*0-fo&UDv)xO8T}0^<<_v5RIBXC2k=yK8?= z@p_f!_cbf{LuTN&ypWS|UMJ$cUl&Dxt4Q%}>wE++3ooX!V3e@^oMoE&hw zuJ~GG#iPY@F3y_#bj`B6D;EAad;Ii{ZTrMn4@hxd*HyfE`qY`-yU(0C1B^jnJdOe~ zLZIyLf+(Oi#w2fd7lsa2Sq~s*zo(01NX4z>gab@BZa$5Dq}+2#ebdJdkIY-Ynp%$J zCMnA<&3?6$MP-VPZF8g3p{l@(a+ynoyM6{=J{!Y)x6x@;B5P=CrRW)-Ue}qDjCS7~ z6rb<-aO%~{%MrVFO%}5HGuNlV$#7!XrpZx7x2>e3Zad%6;c0NXD97b=Qq#6}t8eMe zch`RHa#$Ep8hCEf5zW0n|61Prw#+KaLDAVTF6`Z=lV|xN>->)0lIn6$l(Y-ubM#Er kUaw$Y%&aSFnRAbk;oT{{t~4e-PEc@oy85}Sb4q9e04S46K>z>% literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/hr.png b/htdocs/images/countries/hr.png new file mode 100644 index 0000000000000000000000000000000000000000..fda732810a411de2c34b57f12b931a98886e2924 GIT binary patch literal 1041 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzF-{a`KH#UBa zhtI(!OV7IaOypNs=o{Z`>bYdW!XoSNNNL+RQO9G;_Jpc?yQu~=CG-TD#Z(m?aCcnI zz|hLd+R4h=&d%P>$=S)z-z^|8NmzK2gv3N;<@u_rGZhu<<>f0hG&)R7*Qu*F>FG_< z)9bOYSYcu^+thTLvGGJ}>-kPjYwYZ21Oyxo3OeHFx69jmQ)uV`Pp|%n$dv(s(^FD6 zsH!j3H=Jl_JkiB%pI_j?@W_QlB?n6@j+R%SIeP5)+fSd)UcC78&!6wVetrD%<=n-K zr_P@J{rB&$KYt!Reth@-{UgVY{rvUo%h#`mj~v;vZ|~(RmoHwrc;e)VCr=(-x^&^s zpWolVfBW|B>+|Q&E?v5K{P?lk*RLHtu>Z~N8z-yEjxSsCq&WZi%H?Mm80r}qY8e>L zva+6GWxc@5dsRSSf}r3TNy)pivJVv%XG==H)YtEnk$G=w`q0ASs;TK$C#M}oM!($L zp1Qgmv9|u@@Bb$t;A=p@S{s{h;o%>{!hXcX{Y*)D9Uu2HA>ngs>YuEvuNfIF! z$q5ITf`UG4MP+qwx;*)^Q8D-FRSr&(OV57Ine%7Q8%fKbs#C8zENq(ft&>luP|hx~I@(w|IC;T@ zU2Ar%n6YJN$JTj`eQm2IF$H+Uc{v5S`Q7xoekd7O*u953$$Ufz>jTpa=emn9@_NJyL$6r3O{ds|WQfxP^ANy%C2 z>X)^(pDHRY*Vlh(pnu!c^sSZEXDzLD78ZBy>^?g=eKj)L;pX1{l{wX;0SzO%L$jGNDDL*pO z|E8vX&dU0&p?z-7+-ntGJL1!;D<|!muwiTC%vsrGMWJzi+c!)+wr^o(lK-nq$Br(Z z4)N771_p?ijxjTzVr4zf%6f)_1L(1fyu4?5c`pkHoDvc`DhYiS+S(K)QAcR*M7jFI7S1B1I378lJ- z&zYEbslUZF{?iPEOC<+}?V6zV`6=4fJF{z&jtGUx9%i{rtWL1pEjJ zdK(b%Cne=iV?8i(fl)jPaD~7w6R$R)9AlEVy9+}HtE>l*bI{YpF{I*Fa>4j8O!NA{GHdIu%wz#^yo`1mv zSBHuPp;MfEVoEmju3o?0IKU&yFU}{#$-*oUm>1o`yks;~G!7g*du-l>DN^T;o;-j2 zG_%Mo^R3G)c5B&Ms^+)~CIeB-k?$@g~_AoQ7K5F=7%}<42AYXgB`njxgN@xNA D(U(1^ literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/hu.png b/htdocs/images/countries/hu.png new file mode 100644 index 0000000000000000000000000000000000000000..dc4eef1c4f20f9e722f62b37b96f857a0befad07 GIT binary patch literal 1042 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzF|M%_tvIPsT zUb%Yw*zqe@uQKE_Fyt^W7csLIu(IZ}a+YxNR`Ci{2}o2+$acueH_Iz_C`zYGD-|lM zH>fM-DC*D9*KE+#ZPnE%)6lBcGM#CvSFdN#Vqnr?Vlm0WX}Oc-1S_)+Gq>e#PBWa` z=DYc?_YYVT;J4h*YrdCLlT*O#fY^1hfl~ux7sux8%E{i6UAVU}Z)@J?Z=avNe0KBB z&Euzz|Ni^?=kK52e|~@U=GBW=FRtCVcIDcY^B2#bJbiNCfqiDZre58ir_P*w{`}b% z28PWH4228~1q=*ZnVEO6vTkE#-O9p0NvTdk;<~>6NnPFBrl#jCES@+ytu`{cW^aGg%IdkB+a*WGZPwPW{QX}C1T40& zcp4D!Brxzvc=(%ygy(T_w<9C(Mn}I)PJWh}`YtQ$Rz}8~l9Drr4qZ5Y{QR+Frw<*v zbNTYEixec15XMcSE{_o$vKY#xG`t|GQ&!6AE zef#w3)4O-?UcGwt^y$+lPo6w{`0&P!8`rK~yL9Q&g$ozXojZ5-?AbGC&YU`R3K)IB zNE`*^g}_9utR|pN#w2fd7lsa2Sq~uRfTxRNNX4z>gab@AHiv?_HYYLH+}ZQjIeF5h z2B&!kKeAe$Ox*V_u1+zqaHXWf!V_N>J-TzGW5Iz9FIvvL`D3#{pjbIL)-|%yGc&a` z)Hm1JHlSnb#=Yf-rf3TPuCj`nb$houL+h-l*qdtpGq2pgee=|fYe$VlHBvH@pC`Rb z$WO~kN=(gt{eVNn=vv@3fvF*vE}0q_UAbO-jg3q5LveAzN6wQgGBQ@3I_=fT*ve9Q q!?Kd~i0D<*D|4PKac$XH$QfOi*czo^D+a@ z)ka*)jCj_W@~$x9U1=`3++1**gG80K;4T;0%}z2KT;$igDR1>wKN6^YB20gOpzbtR zt;@-FSJR!&B|9weGdh~&xIN1DP?FPyOwZc|zNa%i?iBf7$o9Ea9C))haC@TLu`Hi^ z)zR0=BW~5kohggFQI~M9Ddkpk>f^qm%V$qtI&PWc7-3+&b z(RS-XtZ!y}-6{yURTy|NFJMEo^X-!Gr>$8JnlnxxIdt#()i+Nc=ZZ4)n=3xf54dvX z)VB}s|NZ;-_wV07fByXb{rlIiUq65T{PE+*w{PFRe*OCC)2ELgKfZhS?#-JwuV24@ z_3G7&7cZVZefs3dlZOu<-n)12_U+rZZr!?Zb9G z+uensgH_f8$l34d;uunKD>>l+)1=rxhaV?7*W8_ZXU`ud=io*sy-QNpp3N#c^v5a5 z$SdpDL|tiua6tdw3SNmjpfK`u^>bP0l+XkKa(8vz literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/ie.png b/htdocs/images/countries/ie.png new file mode 100644 index 0000000000000000000000000000000000000000..1943e6b80d1e79de42b390089a40b19bec3808e5 GIT binary patch literal 1042 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFXQ*aiC}&{s zWnl1OV6J9nu4HDdW#z2rSg5Ggqov)g zt=F%oRikCtXJ|3c!gQLc#cT_sRwJuEYrE-o)_v9ozAZd%cUgDrqUp{^M@b2E7Ti32!x^Vv7@<8bg5sI6l zm3PLg?Mc-5RByUJS?frK?!h#j<5_yAatzMq8D1(hIbUFWwb<-em(z`M%Ucyz4{GiH z^tnB4bb8h5_J5M^yH3xC4X*zu`~RC7@Tu45@07rA{eHhE2mYKC@VYnX>x_h}?V*1b z=RBR7{C`F9rv-VxSCl--QhZmYe=5`9Ql80=Cc6h!cK>?3-nDuDn;7u3FW~>*KYxG! z`t{@ci>FWi{rmUl&!1nve*OIU^T&@LU%!6+^y$;Pckf=me*NObiziQ>Jbd`@-o1Ob zZ{NOgvvC0Jb(BC0ef}f*;5>od6U=1M$MZ(o7?O?1A{QL V!SlaQ9Y2D?$kWx&Wt~$(69DhlWjz1@ literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/il.png b/htdocs/images/countries/il.png new file mode 100644 index 0000000000000000000000000000000000000000..a9161bbb8e38f8fb0cdbcf2533e101aea993da2c GIT binary patch literal 1042 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&MLS-~X#ut{y*j zyrsSS@bS}Me*D>X=H7`L&o&=8&FosnRk)A8WS>ygaiP-vA{B>3BD$5EPAJzMlnJab zY&oc1w9K^ikZJ1yoBlIqwVSM3_qZ>7YFIGOb;ebPzT=L4$1ST?`OLlPKH->S%hrhX zAA%R$jNSYxYV9lkX{X{hy$_vxId1LqxK)p17hlib^(AZDyVNxg%J+ZiI`OS>&6%c^ z$0qH#w)*nN*;`M{-F9-#;VY{TUOI9A<>2XKr_ZlixAE(*f19@Lym9CL z#j7_?oH_sM-ADGK{UYW2=0)diCI;L(iW-d+^}?*|TSUeE)v;&Yge%{{8*?_s^d{zkmP!_3PKq zpFh8S`}Xzg*H525ef;?G-Me>h-n@DB>ebVyPai&fc>DJ4TeoiAxN+mkl`EGnT{?H} z+*zPOXU?2Db!z$Y<-j-uM&&3VH3U|Qoz(&AVNCLNcVXyYmGuB}4tTmahE&{2PB_5i z;_@h{C-|#~OLLRz)RIZP4NiBOf;>3|o&MO!)!b`L3^a653_Gs$E$I45v1!8GpEl3! z@@{attZr0#<>pK`t=Wa!u9|NNXKsyAfU!WWAVWP`PSt=eC8FZo%pGzN!H$_FQPx)n2ZDcbVPwyGPfakx)5zxBY$ zHy=O!`uFeDnKM_eUOj&1^!MMtUcGz!;?3(TH?E&Nd*;{QKl=_HxOVHtsdHyeo;{tn zB{^wTaO<%$*GUH6)6Iis+J{f@%vv3hu{ff1Q%cL>;_fq5?vsq7mbfO&4CpvrYCl2V zvQ#m6u7yfDgJun@W)-V(JFiKrfMu(M(-c{k$%>|h(sotKZY^3)bsFJIOg%gF0w$Qm zFLX*><(9uKAbW$KMh$~j9kYG|XUGzLzdnPIX{KqLoH91K74Gsc*cR~o`Li=Y4E4qg z7s6Q2gtFd95V#V@e=b4jNxtG-Kgk;f+OMnhAJ$lGO49k!<@l%H?O3t(|7ijLrUks~ z^?B3d{d;=I-^JBEN)FI~EH_UzeHr%nMQ6d0|efS3@lcIrI=RL7X)?e4R`O(F}_Qt{S?%~*ov?;UV$p^l zI%R%&b$n*WG%rV_F}FThk}9H_(ptHr#YJ_g$do6IPOGA%er3I4(>mo=wae;O+bjpg z;B0Q=V(sYV4CVac;_2?f3npybzI^)9-v0W83A5*~Z{90w_MU-Z^+H48^HXQ0f`1AMQ$JA3dg|tbFd`#Yaz`JbL{2+pnMRK7Dxf^68$#`;J{Xx#!mY#oL!I z+qvS{?Gt^QC+5#DN|>6EF*RfQuIUSpEo@udHhc5za}UoQzj1v1?)5tk?s)m(rM!at z?gP7De|Y`s?W2Qhu+GNjQ+W8-xVT>_ zDX-$=U&O_IPEGxuk?}h#>uFBTvHkn6o;!Ey$dM)U=f8XL;{MH>7tWmd@#Dw0Z{J?L zc=7Dnvx^rm9y@ky&z?Qy<>f_1MFj-~iHV6JAt3<)0sj8}etv$wzP@g5ZmzDbPEJl% zR#p}k7N(}ACMG7v#>NH)2KxH?dU|?VT3Q+!8j6aFva+($($W$V5&{AOyu7@eoSdwz ztjx^Jz<314<|rU31iVu=&H!p)O!9VjVd!9$^#F1Xc)B=-RNP8VIKVV#4)fzplMe5_ zBNJ=;*Lkr}gVVWt6D2h-GQR86le1G4{MhNBxNJ$zv@bUj?C&qwAo1+V8IuJ8b%N~t z;c|y>NZ{>b0sl%pyX% z+UqwM7;c|rXl$grb=!ItuF&gSKYl9x*v-Kea`g(A=~jl;Tk8JlGwf2G+>2|Iv(xkc wvn-hK(WFf>SpC};vn%GeOTT;i9eO6q@HgCG-Zt&I?4XeFboFyt=akR{0Kk`6=Kufz literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/ir.png b/htdocs/images/countries/ir.png new file mode 100644 index 0000000000000000000000000000000000000000..a6f49031fac803d9bc3ac2e60aa3d29b21380f83 GIT binary patch literal 1043 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzF{}mW?x}@}S zbl6pedieeD)b+qcT4%i&vztKNnT|oGT@VKpUp|e9%x2I<9%LHf}x9Sbhcd-dkU#mncvef{$N z>z51X&K^H{kUa zbGo(l?fm&aR<3xzXwi?=tKTkN`gG~i>&uot+_UHBw{LG=zI^rk`H7=P7cX4+_Vw%A zH*fy>`SZv3@6Vq-yL{==$rC3|96$c;+qbJ%ukPKu7Z|_5SRMsfLqPn={TDz9#w2fd z7lsa2Sz!8PIOyr(7*cU7IpF|PNNDexId6PQO{bcc@c8JgX>`h}de--CT3eLXt6RU0 zrI~GWQ1q9-u3#^ouIkFJpCA9f!C}FLD<3*1JKeEST72hblk?$azU*8d3p|R8J2x3^ z_7O;Y{`Bz^b}r72lU?2%M@_D{aG&-*$>GJ+ns#oMt$9*cO#S>rJ(ZK6pO0h^d6kp9 zYW?cmoOkbDz07@`kXMWv(+xwXPZxQX%Gi2oa?<0;mp6H9uh#0~Dk?VG bSjo;1`Om2IOK9Ojke5AO{an^LB{Ts5@sf(A literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/is.png b/htdocs/images/countries/is.png new file mode 100644 index 0000000000000000000000000000000000000000..9ce986449682806ee8b44740aa210a91a86b64a3 GIT binary patch literal 1043 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFzgn*sw51P1O42-q1KdN?fXNLbk6(9i?H!FwVj zcT`vJC@)`HU%!6Yvb(cqpIf%XlMrIqV?N*yx_IGt3n>hLG ztl3vOyLPW!^&qckLwWTsd!Hq)K`Vpew{aL&EI4|#6Ma5Iv8W&xhj|K%DkBK@H zANQc5>|JNa`Rd9?JzYmCD}K+N^J(S`VEh7Oc@$s`0ns+?k3b2=ByV>Yh7ML)4gs|% zH9J+#!b;v+>-7xz3jz{dmnJj^MCQfSIR+MHdRhi#+*{J=6TIyFjGOk^-&%fhKRd_B z_4V5p-`O@>x2@Z^aqH&QirMrrwG zdHE&<$s|eD7FG2Qb;T@2tx_$EsTLNKEsW}ntlF%t+pRqoc?7HsaGT;5usk4qU3kdy zkhslpkt-rocBG_iOUc-kk-8-{Yj;-Wj?9t+C5KKOI(YKnzGM6L9^HHC)}@mdPwqRq z@ARe9w;tYl_2HF4zrM{BYsWbbX;U6v6woLH-c3o>0UFJiM>7Xc=$*XJnxo_RMX*TaC?D$f# zV8WD5+q$+UPLGXNE_Nx&@=^)#a10L(JG5r?-j#axnueBI92zOB^OV&x?p%zCkDW17 z?6e4j$fb}ePo5cPWv*DMaiWj^^LIur&B%|%AEZpKg-sJlb!Gd#lesme#Uhf`=k+Qt z?=EAeTHBZgr$sS3ZW%V#3*2}M7z9gLg^F24OE^{PB&=uZJIpb4o@(K{!YOE#TjU1+sI>u!>%wI# zdEL6KrE9p1`xTXHnT@(dJbDdMw|W^hGgx-Aw;zcMo+F#ISfXUJcKCGG)*Vhwng;M@OMQf816q*Z=?D_stuRT|2EleeyZD z-|qFRfTALeBS-uzD@|9f43v`MojAcaGSWCZ+bJzAKtn^($;l!(*we_!(7-_7-rmm9 z(P7s%h7D_&uU=Gq_So*@yOfC&A`{}h`1u&pQd6_CvQkn~;^N}M!@~mu0|NpA{Qdp? z{QP`;d^|lpJv=$dCrAV@&dPcVXyYmGuB}4tTmahE&{2PB_4{$42)GYlvvdQq`pu zCc2Z28l8FtIs4fDJTjWJ=uR8o$D4T$3nPPHzYaQkb%%xNnMGNjZ&x=s8UKptn&kZU z%a^x@FH7Cpt=-_{b2e8voh|%l`;{kON=v@_GjW-24cm0?+d4k3ZrwL;UL?=s5y^Tv zciQvUk8@Jq%$gK!wXla*<4WMX7ta&do;|%Vd-l9QgH)@46)I{6PPzm{#Cf`$xT31J vT0%oaGGpmcJ+AE((Bi6 zF5kSf_vq0(4Qi-zuY<-Oy4bugtT6J1_t$GIS1}1$b zPOF^U*10*&cXC_o=D*25U~_=qTEBqx0d5oA?aS>W7exAX`em%m$XK3{w;@kiOIcD% z^8JVR2M--In_%kR;1)GKk}r!v&q&+R)h;GJGBG7CH6uwvT0~JrHaN^*Qd-10h||T3 zBO@cVQkOL=z*~%&VY9CMG9l(HbE8NWhI1Jy`wH_IpfQlHCyxm2Gz%=c-GoFEL^hY#)oyB!Rdx)W?JSJ)$4m`=66r_{=qhKXLMwtee6=NHE}ugqcLp)(x$ro6h$ z#@gA%!pgO>3j#`3bgkO8Y~ISHy{+vV7p^lid(Xh|eVY}&z?D;$gp3L;h-|}VO7>68tf-^ zdCwRMT(Xe3Vk3LQQSrW)_9H+2H!*hK-oD;1$9!Cq>x2f+IYW`dhGM5uf?igqe`zoN z)>rd=V#AHr@`F;02P7ExOE4ZWlDTc8cH36%sh8=CK&y9=PRDZ-zD{g9UX^#Yq4Y#! z`GW=1er;QQbEzvImEMYs3w-Y?3qUyAjdhRCOAug`J5C#Uvb-nISHt5-L! zT>0_+`@etx{{H>@=g*(tzkmPw_3P))pFe&8g};CM_U+TBPai*ieE06%n>TM>zkdDd z)vK2;Up{~S{OQxDPo6w^`0(MaTeoi9xN+^;wJTSyT)K4W!i5Xx&!0bc?%Y|R|IeH` zb?VgdhRd z2wft&3aE%N$=lt9p@UV{1IXFt>EaktaVt6D08>}jr<)Rg7e5LP5=v5Hwz=!*#2Q(5 z@8P*+$F6M*biCJN=dke59E1J@ZdYC3%C7?PZtE2m1jNY%FX-K-vwuTV-_+gi4CVnH ztQiwJ=Qd1O(K2u1?s^xSfD>nDcVE2_7T^+d%Hgc~6iZQ!CxSAQpDa;SSJQl(At`e9 zIG+gD6Hgz{z)jb$mIstR^z%8-#?=`6Bx~84Bt2ol`O{`{i#+o2^K9CoF~!`pS($%! ZIm3t9>d&p({)4>3;OXk;vd$@?2>=XvP167X literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/ke.png b/htdocs/images/countries/ke.png new file mode 100644 index 0000000000000000000000000000000000000000..7bc38588be8e29bb7f0546bee5df4d59ff1600ea GIT binary patch literal 1039 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFpDZT6OW)vt zso6nWyDe7MyF9&~*Ve6wjXSPycEZyBvVZ7azn~MLQCH)WU*?y5uc-Z4UbENG;(2cI zkG39WCT4p(`--}{+QvpJYwH!aw&kvlL^*O|iqmWm$yRf>?td$H4U|@f-3|XXWQlEt_|8nPP)M`mBP&1(j`^dMoDF zH?HhhaB4Y2jsR=Es6@58VvdeRnXz8Il}U%A#U$6*)tUV}rm_|YInD5$K7HEk#)K99 z`Lojkj!dZ!^z&WJz+lI~u$Yx~D<`K3GxIb-!95ZZdlVG5tEnweQaWR5y4%ojtARnZ zgv4nJi@hc$`z$S*{?7vf5)>8h`}sWz2sq>6@gO{W zkC)eOFRx%l#hX!)Pvhct`};phO?{n}btNTbfsfDCjEuMC<+pNkuNM_X>g#`PX?fMy z_@$%cY)Q$>mX;;4vEOIRkd}~eu(b^h3d%@LEiNpaHg)QvMT@3PnbOnK)7910+1XiM zUY?bem71EGn3xzB7Z(r^;P3D6=H}+)Y$8e8Cpvh(eC6aj&DZPc*W1s;_4N5M)}NKXjn$_dS6iyOsfD@K#kFF` z&X$>%if^>Cu>Sa2(dZ<$Ozqe&Be|tA^DeddJxgPAP-M^6_D)xpH7~by7q7OCmR>Mn s(VjJPnwE7mdKI;Vst0HbUq8vppj<4M!g za~MzcGhdp{^?9$=nQq3@eXQsE+0Rbqy*XFp&H{;V`|VD3GMsE>c)CRGbR*-HUfxG@ z6<@E?KUvLiwq5A%6xkPxw102&`m@vbR3-DpX0E5R)NVA3Tuc@?6~THjUj1v6+m8Ue#Gw)YsKCH@mSdI07D(gWF&QrR)E%IDv3)x7$s3 zhl|cZPlJ^XT8F(2uZLKi_BTE0XL8iX_)U!6X@9f#2~HP6tTuZXeN1t?6YX#<((ZPQ z)4o9KFPXj%65Q@5xIIbne3azzCENdNPQZ(FpVygwpK=4=X9s-D4SbOu@H{i%bgbLk zg77zm;UCK59u!1=sZIG@lk&bc^<8c1x2CKE@(las7!E43p3>qyq{VwiPvE$b#7Rqq z`|jG;11+uxS-g*Rx)bI2Io0b)lINp%kFOd2FH(IzX9T=X^Lw8e@U=eUU0MJz5`j@U z3P=rsoFfyvfqEE|yxm7D!N+crIw-cEcy)`@>yD1hCaJj}XR2B{DE|MHnR@Ke8m1VVqN-X~ z)=Ym(C71J$O!yvZr(uy9t)`Y>iivp7$? z%)kGZtSDFzkhx%T=;B#>6n0N}wq(nW4GaqcwrpNI(|7j5zHKL`e7SK!A%DSy-E&ti p-Mc#f{E?NBhJuQA^KR^6X803j5M#Jtq7o=9JYD@<);T3K0RX|@LUsTE literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/kh.png b/htdocs/images/countries/kh.png new file mode 100644 index 0000000000000000000000000000000000000000..9c94193159614b98f5bcc94cef4e7314a7c5f485 GIT binary patch literal 1043 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFKP)8H!Y6P* zRQ!mz^d)Keb6UFh4NW#^>s~T7-)&^FO3&b}i`&<;ug5fN}SI{1tr z*K{AZ?V`eS>}=QYaL;7tNaW#}#V;^dP-w2CYEs~0D(#m~GIy3dH&zL$~&@x_PV71=D`LLP&4kzE6Zb5gfoY%Pp zobivm9}xW@AnI0l;;pRWCs+2Y|MBG3*)?-tUq1Q&)x&!Sx1E{Ub8ha$hg(-)TeJAx z!5zOYojTK0a${=O@3o6QZC-WO!{TC?+nKcJ3k~Jx^%Y;ZS)6gPe3BYd7#eWJ+wD(W#J8C6UrBL)GgAKNWcWP8tH$vvwCQ4@h>RgXF$L;KR;mP0;6~o;0ghYz!N4wImRS!cNc~ZR#^`q=b)#H zV@SoVJ2rovl^dO+*rt_j3v+ul%c`nPP3)SPgJPOoq99}0 zvX{mxH!LcCvixjx3f()oDoxby?Ah62CcBre-pr|S#cFB2pKDs7W0XOu_M~*)8 zE-GefJ@d76Yv@x^k*Oh5u9}?j>1}k1)BD!9POeT-F!15QM#g=1H})_yEYC91pUEtC P9OP?HS3j3^P6Mb>-NZWeZl#n6YBsk|V3u9STqEnzML+NYbQ){KbvEyX#u#cTZfgZO^5E z*!IHeIa3xKZRlEAR5_t*(%Shejx=`6Teh>wyDw^iZT6T2BrZaV|({~@eJ7fNa{JI5|?aQ-D`-82mKeIh@Y|_2^{g*EB-n}EcX&J-r0ejvZMy!W584fG4zRd_fCdztHlIygZ#0@u#JN}M$4Ap+-Wu3}Q zt7TxQVPH7U$J@!pbwNbnxQNgVNr`h35)%Xk@5sqMP*gmxpfF2P@~XP}Gi~jc`ua;0 z6>sY6pVHNNYijzz%4(gK)?EvW^Cl*r?d-lfIqfhq`r+pG-OcTez1?GHr-x2XKfSyT zTU-C~^?mB*_R7=qg@?y4fB)YB0lxwQ-ud`^^z-`>82CLf@M}Q8+kk)zZf+mL!!P;y zeT|QM8X5U5De*^2%IDP7-&t9|YODYCbp4nz2^hb?SRMsfLqPY~oGCyF#w2fd7lsa2 zSq~uRfTxRNNX4z>gab^ME_L4uP7)S=v?zHKmzH$3qf;esahi(jkKaGso=v~@-G_}U zHSGMHyRmZw#bo9O2VFN@$*mD$Hnq~LvaF&ZKA`5ZWpJN5-Szp@3$2;lp57Tuts%Z96;D*AF5S_h%X_8AH*`ZKJHx4U VM%z9=T=E#?V^3E4K z-W#2^JGcBet9UDiWE-!1hoDlQqR|{>ld0;)^`@??^{qRtJ?5M~ckb!)XJ=+kdA)se zw-C>3bG@CqYUizuAGq253-7V>ST4w)L@f=)>%`-OO_^A zt;~LTIQ{T+yk%$gz{&29kK0psr&r!??|eP~hx-2u3-}b^^EWc^Td?1|V4v6i-oHZw ze})FU%uM;#-SKa7bn)ZIkLS*v14b?|ibnyi5cvAG^CnP^G0EHAg`tC0)&s~n z=;`7ZQgJIe;Q&)e$QGWnXG=`4ObNYeTFT?o;AG^Lq$G4`(WanFMW47Hbxm?m+&<-0 z!u16&CS3U7@!d!Mf6#(}==XOjFF!xevAR3s-HTV6r`Wg*L$CYg&W*WzUtsEl;D|}H z*+gcAJhfT6?|i0Ha*Ug!Yh0C4Kt|HdH#0XcJDZvH@{Qj4^Io~^TtAN-dvof->rNL=inAo&yX5W4tTjthR#aDLg#vW#d{M|<3 TztlCZgM97j>gTe~DWM4fHNs_W literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/kr.png b/htdocs/images/countries/kr.png new file mode 100644 index 0000000000000000000000000000000000000000..0df561a99300dac225fc795d0d099c72ce9fe77f GIT binary patch literal 1040 zcmeH^-A_^h7{-sG)3J1#ZkZcf&0K{m>!z(W3=s!nQ_PQbQ&Z_C$+cn2Vm2KE12GK& z3rUBLlg*X#bs@<@S$+cwoiiLw5Ytp71qK*;lurLdSH0WwKKot0@193MFQp`7v#SPiI-FMBnP5{6F^xKt1D8^#3)v{_Z^;&;<{o8Z2`xs(>*Gt)EN zs$Lqo=PXVxd*i@jyD~F-b93M4<*D=Y)fDR3O~S|5-OFu!grq^9{#<*Z(dk9K0ZD=IzkZS z;NTz{jYcAoP$(1(1_ObB-|yeu-Szo=Uaxm!V`F`N-Q)4N-ENo5wX(9}bUGmjvfJ%8 zn{8=nX>oDUYPDL>C(P#g`T5z|S)yyjnGMP*&l}aQMu~;k;iG)I-Kp^1pcw8=*!{M~HwzjmiG&eW1+3cpK zCKij;(9pnSG8qg8jYcahEF=&JXbWf;|K}ek@Fam^LQlrkl~Bk4KLJNY;Y%^Opz@iM zQ8RG@kJm_7?jfYXL6fP%fcsTIik^u+ubmW?r`5t?PluH_FbKU{Bi+c(E!hF!VBO_1 z1)Z&WJfeH0SIc+9>;D$+N9oK9V zp)hk{d}K#a_M+0EAF=~>Bb8d)VosWA_Oju`X{PY0tazD?K)c9#x$+Pn_7KH~j6l5-p z32)2Gn3odQUs1R!FJpFT{?d%(NfkxQbJC_&m#!?%om-GStFm}$N#4BL@>Mlu%e&h) zcQmi>YF%$;kY}o&W1^R3ZkX%gRF@Px&ELB+HK`#jrPA8G*xJ0v-MONveqC3`awmt1 z;-aqR<{9y6(`GJQuxS1AooBZ!*fnw8(b?1Hx1Cs2vvbyjSIxQ4yUIT|WUq?!-j^Bu zvbpG8NBP9Wh;Q51JYKb6yR-2DZ;J*))${Sb*9#JNw$>JTxE}6k*;rTzj7MN>jslWG z;5@U_2cQPVByV>Yh7ML)4;a6qP(T z%_g8DG9srdLDaf^YVpDh@9Z3v0FBj7)8eD_-GdHVEA3twrzN8?W#*g6Y3liL4@5?HVG+5+yTS01`PQ!-z8=$8>xF$}=W?~4@q#&4L}>cFSsIVU*YJoGZM|T=rR2-S k3)egY!+AfI9)2dv;Qmto6*nv2b5KBdy85}Sb4q9e00cWbkN^Mx literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/kz.png b/htdocs/images/countries/kz.png new file mode 100644 index 0000000000000000000000000000000000000000..eb7b9bef2b99b95be3d669c6023dbb4346b97e36 GIT binary patch literal 1042 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFXJ|Xa(0+!o z;|x>BY39yz%w6Z0JI=6nUtsMz!`^+7v+FGH zZT}y~_0R2B-nUU+4ssj}B`UtHQF8=ss#hltl3UQY8lJ8#mPq?OzvTCcbSy=TmbyB#;xO7Y$; z2VsqnTS6y}&k7BmKRYBaBYn|QCXrR|cpfA?JC~V}_qx;gdT=-cm#Fzq<3g?ujiV{Y z*j{I8oMLJ{^*iE5W$V*k*}FMBrlF}S8!FiuR=4Rn1~>bgfx^Pm)z4*}Q$iB}7Y%K= literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/lb.png b/htdocs/images/countries/lb.png new file mode 100644 index 0000000000000000000000000000000000000000..44f9e1bfe35f515ed50884a0b725bd16b14ccad3 GIT binary patch literal 1042 zcmeH^+e=dc9LG=2VO|Eq3N#zJrjk?9C~w3l$DB@=F40_SVTGV#P@rj2iGf|MK<%ZA z*m@Y13murZl{(GKJUd4Zn=UW4*_p06kDb-7Zaba+gx>qX_xI)d@O}Aw?~C%XXhHjf z005u~vUvrhhms1}O(DM+WIP4{3Lp{|W|EO02=E|NeVE;IIM$lU_nZ;?N=oOIW zU;lxkPKRT4WyR<7dA(kb$FsAu<954UE|=YIx7ln~s};v_48trIi`i^8nM_8b(O@tv zEiLJEI*mqyAP5Y@5Co}7d?2V&siaaVIU+gb|NB=0EN4kK+1Yh5H;V_{qcXC|Fe>0> z6gDhfDj)T0ZGFLN`|ha`(oV%Q6kJI&*ZwK6>dpNOP?(3^I*kirPcl2@X6xI6^L3Xo zW!swMK~C4)@4y>deeDzb_VI>FH_gk(nz??h2_N@FS3K=77VS5eG{*R~R6jfBFP+YQ z^L9pXG^HNTrvz#1?fIQ-_N&)%F)O-xX|(@d_B14f^?GD+b`6AQk4#g8T86~WOTP^E z%6q3i-=PNd04)d9A&(MjIDV{4O7Bet=Ungg0ASUf=zu?MoBqNOWajbSbIWi40lScu Apa1{> literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/lc.png b/htdocs/images/countries/lc.png new file mode 100644 index 0000000000000000000000000000000000000000..6b0389ae921c2e79846e8acd31ab30ff7fb3d215 GIT binary patch literal 1043 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzF5B3kNDep;& ztqBf{4GYPfG-0`=X@#|UxwCz}gH5H6M_Y2-{P2)Yf1j#^m`TwQ9YuL7(o<&SX3fve zn3J6`D=EG=KWBbYd{0T?vf_fp$q7C6)tl<7H`G?Ht14ezTeYUSVRK*i?(EFoiG6#g zOgu1o!v2`3vhvayM*3ySik>P;UiLP1wpLXRwpDJLWsXJlu-oV`oH1Oz`q3b#uu}PMnjO zwkSDaMqJFKkf5djznbvS*07M~_}KoKsIJ8LiKRtr(^F@b7OlxlpIuqDAuVNUL|8*& ze0O8rj+)91WhE=>YqvDiZYeEZ)>yZ-w0LQK?WVe#jSY31n;JGYHEif;+ul&Oy02$X zU(e3o?j4gS?oUZBGd3)Ca%}eVEzizc92?VaKLr6r}M1d|gZo@`Tmu|sX^M1`-%tzI2+`*$T^-$KWS8)WBJ zimYsrc(+S`-wf?vC!9{N@{$nc^>nkFS0?ajx9Oh~ZvW2t|2!3NVws8*Ln79;jfapOq`#l=lLPhFyC{$eY1PFK9SL}I~& z=#8ruiStM2#_HuKmUJ~q1ZV`=hTfR6KIz^a%S^|@PeT737OpAb%#Q7y)oHx?=He$y zm{}X0W`6AZH7#^=)i1TsRi3Tv70j((EIt-q(z~N?shLde6#My+xwYx6#pju7=KeEp z877ylSl=%kaH1``d+FBI+v{(A`R13#9&Vj;kC9>a0>j<6o_?$VdEC?0&t;ucLK6Uu CQan5W literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/lk.png b/htdocs/images/countries/lk.png new file mode 100644 index 0000000000000000000000000000000000000000..2f2c48bc7dc9166b06424a7bc52183eeec7395d1 GIT binary patch literal 1043 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFXLDwd2ouz7 zk{2!J%-fzK62PTeC!w9CXw#=}QmW-L#lp4CI&`5&%!+`(DQ=mY;|jK>mhH|G4`2}Y zXE^iF^vD&pPe1Iw{BrvJ+xP!}|7XuUfBpUTpB%Gr{54!MHPv!;j31yuLo;S|{(lg;vuGjdnHZ9WE1i zFxPEcGQ;*%#_j2>yEEB$=LsFDRzKEa{dkVw^96wit4vme^FHafn-(JdVrsy%sR3sq zm^TNoo{Q(blB4jj!Q$hTfHPqX=OUQ5`Lq9BlJb2)>PA<_CoNvj+5*h)IS%czfzm=dY0c(Nrq*ztQ*t?*62%YGM7K&V|pXj zZG{x;9uvj&vbP*Yo=qqD-mV7-aS zB^Rd)PELF5?Jl{w9d&a%>FIgH-~XDw{}~@2U=#x*dK6%Wfa;sYh7ML) z4+>D&TVc>|MJ>~npPT%r!cnO z*!lKxZ>`!h^{i8oEK9eZVdg62vT%{E`o8ptW~a4k>Xq|sTpzh^yGmA+wJ%@QxwG|G z=@|wtPR?5{uXcZDo2BjHb^27eKRegPkCARKs(em_O`C9OLSW83Hjziqjkqs=oHb=~ z=G*-jyjJIF1$49@HgP*&T6BBPlcsYF(~pHM5a3?zxn{A~yEQ*!i*L`)TF#REnUBGD WqtVADQ|vWC{`GYAb6Mw<&;$U#XhtCb literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/lt.png b/htdocs/images/countries/lt.png new file mode 100644 index 0000000000000000000000000000000000000000..c6252cea6650cdd9568da3a6183bcca6dcfbb315 GIT binary patch literal 646 zcmbu5>q}Ds7{;ID+2+~hY&ut&VXdO5bSj9~K8U60K*h|!g3!#x0#{~7^iyO?VC2-6 zScFtW8i6-72_w*`=u;mmLwBDEDS4?Cshiu|@o(ti$Md|rA6{Obw$hRUUJ<7Nz#9wm z%Ea8ZHFK=!SBj>^1#`W$s65~0gvSlH8!i{@PWZfV*zw^#0vlW~Ag8c89MTYN4+XVL z3k;ExLJ|r_5XmVZ`?Y{sikc<$3~6SFw-fK7XeX(C6yu_(k89Ef5@7|B2o!OZWCE${ zNYg;NdWxy>bNg1YcLn-Y>{-UnMZ_;-*AHmikZmF|1a1>LLi8qL2-+|r{Yaftrq0RJ z=J~XFW%@T|rdOKoM7Bqo;gK1>pr=#S)2ZyXD!Q$5n^k4&&~|m`tX5syEp1CH{~`%v z280Z$LZ$1`3PygYnrc$9F+5s<1jWU7EvvBt9N5)sK?R{E2XEHYSN zFb8-Ucp_kD@L8<#zZGuowTnmY8S`?>o9t(&PHNd)9VT};#x0Il8Z@+uNLGPjift6h&F((cxa?!Y()VREZY5T4 zES++>WA*2jWv^@J-S1larFGfstkyk6eaAajy=$0rZSv+X{cB!M-}+_Zx)*29Up{{F z?9bo-K7ILq^wYm8XBcq3wmcN{wb{iROGB*0-?*81- z@rS49F>CAp{{H_01Ahht{Evuu6BP6=IQUz5`0tpQUvY8YQ&azEWxY&F`kR}3cHh2> zhYz3Gx9|4Zv*!;TdU5O4-3u4~ef;?K#ft}5uKfM@@zb+sS5BS!|K-caXU~3o|Niga zzdwKe{QC9l=g*(tzJ2@j>C?M+?_Rxn_4Mh}Cr_R{eE9IjjT_glUAuJY(uE5b&Ye4V z_Uzd+XU?1gn(+TWFe*m@sUaZQod--O42((M?k)@+tg;?J&VEl9$B>F!$q5IT_UuWz z)cr}wsdn$orbRP?jU1g6JzH5@$>cuZ6CO_esCtrI-oAbgQ=)C`mGdFIg@ z-E$gD{I+@*EOkqt<(RNDuymPM)}GMH)&BXLL(4XXl&lXf-WE|g%PVbPZ2h*Vs%60i zCyFNQnzQWaicOcc?mxU{%j*j_-(9);{QUKgw;na|m^JfTv3s|-b+jNN9wTjyI z$+-5(x^~IBOjPjbR&blFu^A z$0=#4M`pKe2Vxuc$2RPau00UfxHqUeC6z!vu949 z`SC>lAo;(SRAYe3&0$PNCoWovupt+1m-tI089jvk*K+ZN#7srr_TgeFrm?9$Q z3VRnjz4hs}&|&?%=(3~JpFmYsL%$feH_w>jf;1%^6y-J^N~%oE6La>n3;$@5YPn#7 z`?jcQ{i3rQJGV~A$XT_>Bw&S`|Mp3qd-pgwPmYXUzRQbS<4VBwJJ&8=y?5(U#O=uY zSFZ7jXr1OS-mrC}IH&(<-BZD#UF=*dE21S{NPo6sJEfxT!uE4FbF0b&y;D=B@_Z|0 t=CUl5+%%gpcFL560)j#hUN)VzW{CNu747x;N);%WJYD@<);T3K0RWHSH=6(e literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/ly.png b/htdocs/images/countries/ly.png new file mode 100644 index 0000000000000000000000000000000000000000..8741c4c76fe3c2370a9beaa901c133c98a7429f6 GIT binary patch literal 623 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcX*_=LCux&QzFXDEwL!m| z>0DpaIlcycZrXMBTGh6CO-{NE4qBzwRttly76cizx)`*$m~?v@ce>jx3A32$XV&ZG zv^>gclAlqXi`%L=$2np4(}SJngnO+`v}*UYZuj+FpW?P4+IL-w=aM*&MX~-HQvEli z`L9n4*pTkCJSlKPy5Fjl!1d_?YtsVOqz0@>3s{*Nup-rMN@V!D?6@sOahr=GS7fK` zs7T#fk+G{fZEHo=?pmXE*OVRQpunLeaNqw{2WUQHlDE4HLkFv@2aq$@)5S5Q;#P9P z0j7wEC9+A*XOHZdVbQ8$x@NC~)1$D!M6)29GjIL~d5OvWb5L~L+fiX|$rxs47g!lA zZXdp2LXk(whGhoq+S@yN_U)a&T{qx_VBUmXTc@v|YZ#!RCX+Xzx?%H9#Q+VV90C0c z3hMUZr!90B1WcG^z;1j&fw@{fKUz3ebb-JjSBK`35Ya{_gJv7%xo3N~h^B0;WM{bg WS!%{rcd4(SQ1Nv2b6Mw<&;$TXT)2?{ literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/ma.png b/htdocs/images/countries/ma.png new file mode 100644 index 0000000000000000000000000000000000000000..a5d9234e3b0308311a709755fc6ab8a44484c980 GIT binary patch literal 1175 zcmb7C`CpWE5PrVj?|UpSys#{+94agdCXsmHg@(%Q60Af}c58xRrKXX1q?Tz#_i1Gp z-M3+#!4=Z7j!)P;!Up0KK@gJX7{8|1iN%BEc8F+s4n z)2<+CV1@rclFpRmTNNkOrD@CJRc-71y7fK-(Z1G5@8N`?fko4-0-S`{2^}Kn0VaV_ zpkFyhM(b?UE#*sNSaB@57=_cpC=NkKj9kBjHZ5ePVD$N6l*c3`6O{FXI0+^NOof@r*cQ=p#(yGXVP{#2b6GWAZ7c5*9v3SYSWy>R1ti;Vxt5&axj){$nPe@#=Pr4;J z#jq|Fx2D~eo^ksf>+ihl?tAXN@BR%NAJ}BbMAqg9v$s6-@FQEdZGUvf&c|{d-<7+2 z5BBbRV*i1IPd;_%>BC2!dG@(|S$TO%_xTrIeCg#^UVZKLH{N{f=-cnSd+fdUKll*G zKFa_2lTSbU{EIKY`udx1zx)39t{)2a;KYd^fBN~CUw=DUkpKIsKmPpdbnYfYA&SnN z{k!;|l5?f!3;r#;aPd-k`Q?gAR8`Naxl&uVr#`Zw(P(J8YA^;jx1hDH-DK|Q>{54I zdU~zuy_vR^ef?~cP WJ|#8saAe4JHuUj^xZ^P!4*drhPK;;( literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/mc.png b/htdocs/images/countries/mc.png new file mode 100644 index 0000000000000000000000000000000000000000..8dd6d29069c525374decf238a9f6e74ca403baac GIT binary patch literal 1040 zcmeH^>q}Ds0LAZh40SnDo8hCSgHTg!AimJFwzj!zQ?JgjiHVet6br%+`Kd^dj3O<> zib_I;iugiBG>5NNlX>r6+>JeQI@{8=HE`hC=C<4Qf9PWe&N-Z~zw->PD5X*oDF6Ua zAwH*?=vcy05hNmSBJ`I4KmuSv4VRcWj>|3=df~#ygoK0CR7Yl}J}u3~WR5Zz+f1fAH`iTI za8y`0n~`BDDDak)_}OerQIRG;e>ppQ_ex2C$J=MILSMo3gqN4wxLg+mIr)6N zvN8n2Zh;_JRdrld<%8jnQ0Rf-Lm0+*JWp+{MRU z!>CxSo0zaHE@IQuE}2X|KJLe`eW?^T8hu)=eRI=qFnA4yP$(1(1_Ob>@$s?W@Avt9 zUa!~V@f;l;x!vx=!$X(L<#ak74u{=tKR7tB*=$y;)nc)j&1RFyWHcJ}dc97k!!S&v z(WupGl}e>lDisO^N`OWXxm+%j$)r;0>guXQB3W8mnwgmy9UUb;BA)uMe@?)h^7Mo( zc>8)O2k0f!`NUX(IINm3tLRJPtskT@ww&F z&{c-$$687&y$yT>aqkJkPp5tAA7ak+t$c{?86!PXl0ob_uJd1Ce!6DNcz}b3z=f;%v+epY6q<&Ben-Q z3lG5_xudQwaeT|I5q6e2jD^cj*iJO7Jl95k_d@iwev;l%te230a6wim_h*OUgcZcC K;7qX_yZ-{kOl?X4 literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/md.png b/htdocs/images/countries/md.png new file mode 100644 index 0000000000000000000000000000000000000000..9d9d27807a03b0334b2def2613917d0a04ec0193 GIT binary patch literal 1041 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFziMj6AU?&y zdvie2(Uj853<6QiQq!2Frt&J!kT+SZXw={sw#~|Wfwj-P$n5K#H_-9nn35(aYwmGY#FCdr#GkTL3()GAlETWa98O3S9p z!f%6-%M{zdg&whc+#**8q#g>-IUZMZCM0cZR_*1?s-q>XXEf|4m(~ZBRvXTm&$V(L z|FIKXo40cBJs^1ctkkJ92DNo|XU;I3JI8$H4C~pmoQDqaUb-X^70LbNiQ<(j@;i4) zU%sOD?w$U_hZetnIsO0d|L9;q2 z@1F%;IK+DGB=7CB5*H4sy}IwVVx~wzhRCBUPOtC!UOMJAwbwH>iaE%GvoV{YIhVbo zOnpw5byc2YnkPd;xZ*M!){X80efqN{sQN9VYn-YElvvqpxOOia!j8~?Dg z`{m?x%gXA3z1<%-x2H}{|Gd0jxw-xK^?m2*`QP9FUqHYoAD_R0f#3Z6eg_8r3>l+(~X-`fABEd&V7@sd`kOO zwOVt_lPj$}e_~~G-YRjgwpKsOz~#AuYs1S(Yc}?o?xLkWGwcL4jx1I^v+CirIkUvX zWAB)kdYK1w#K*TEJ)xtmZf@Y})+tq$1L|wGtlhbeOJj+G q-YLcR?;bvVD;<34Qb2I$S!;%>U_*|H`F%;Cfbewnb6Mw<&;$S^Iy)}_ literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/mg.png b/htdocs/images/countries/mg.png new file mode 100644 index 0000000000000000000000000000000000000000..e93f20e0a095bb44add8d01e4c9c19c25a878f09 GIT binary patch literal 1041 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&MLS-~Z#sj$gTY z_1N*_SFc^Ya`lROEtg4)i2po&w>BNWUQ_E{3CDg#-#Oa8y@v6t?ZReQg-*1}+2)(J z$}@JRQ~uUK^L%OVX==8miuM)C&b4YTbsFwXT9J!Py;^nSmRSY%8KwQ zvsc=3x56y}Ict21wg%>{_sd%9@6)d5-)#^&#WZ+=N!%Q}qV4`gTLbj+nC+@~eL7_0 zX6T2t8HBeP$Ml%xFL%nF?^dq$ulAG1gu#SqHe74~p{Mwzv5I@87SV zKYx7x{^s@TyLawfx_I&L-@m_p{rdj>`?qi3K7Rc8=FOXzFJC@<`0&P!8&|Gexpe8$ z`Sa(`ojZ5-?AbGC&YV7ddiU<#n>KA)zI^%IxpSvXnbO_eU0+`hj5=TpjsmhnVA|FB zO+d|zN#5=*3>~bp9zf21PZ!6Kid)GE2bh-m%sdel7$7J6Mpi^{_KaDKLbI-14~Pts zcqT0&H+jOOx$Gjd?%WRwkBt#~ATK34f6mPLtRk~6oVyYd9P&z7NOJm=d9x?8i6o`v z*+qZ5;L^8C#nss|uRi#D6Pgd6>uB|LP z8l8Ok=GxjGnlq^@D{5Ao7nhO4!fSo==J^@gRf;C(hBC)SYAz6{F83Fo%{P71#I{}g g=FQo{V)mYa;q4#8ew%4CtwDj}>FVdQ&MBb@0N0yLi~s-t literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/mn.png b/htdocs/images/countries/mn.png new file mode 100644 index 0000000000000000000000000000000000000000..9ce7bc9043112f1151cb3016a53e846b4452eef9 GIT binary patch literal 1043 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzF_itPg(7ZCF zeQi+7%9#GGQ}^DE>Ry*VYhTukoeir`2J~zWo47q;)`8rmrz$sIZQXsZ_t2B3O&9wQ zKknXh$9B>|n~4XUrX6*ha>#x5Nw0Zl0_L3zTX8jR{hg%E_Y3yDtT_7Ke9954smH9Q z9kZHx#Cqyc>xuhqChm8fbH;J@X{VXT9i|?3nsUH<$z|^)m%`WI4O)6JeBGVE#b;A? zJx|&BEPMB}^euM_k9?>;^R4>C$A)v?>rQ=YI`idtr~2)s9+xLr9G~d+W@GBv7X2sl z1KzHP`>;Oc)258Q2@J){NEE_cCY$y%RRW^K$edO0Kf z?xe`QIo2m4j+uxaH2Ykp3c$*n;J<;oan*WD_ zh$q>hZwjN{R;GMy$*&M#Xp!RjT9)#mJaxXl;;V!JU=#x*dK6%WK!L}f*FaImByV>Y zh7ML)4oXRX^Yf49u35eA*zJjd z*DkP$%#xO{%9onHt!;)_e7b*bwrxO0 z8R9c7gP}m3xk!t-P?Nbpo3%uTwOEI>P=~WbkF!{xx7wJu%7iOWS)k6GzuZ`;%3P$< zLZZ$_Fj7mR)>gK|NwLRWzS&7S-Auj1Q>n;KG2cdiMu=jTwOYB8Mx~2Ef1v4{NbNcg zt!g*DCU4yaFRfA+gH}I-7C)2jAmh$Ji>VP7QzI>=M4I)6I4w^zs`GVQmFYM;(P>Vi z*V*(U_+75@*KZad4cPT0@fA;tjrHsk?%Go zDSTaN+?JZS%{3`I8dJA6X6$Os-qW77yN$t3g0)18tyr74)IhewLB7dBsm)n3$;fC% zh*7)0-I7GBNfC~766~kP+E0sio|9>l+6BDzt4zmrfO2v&GElWatWgVR!sqKqP^Vw=UhiMYm zv2W`f6dl)^$hYt6d)H}Nd*-5<-ZlqCSAP5NmriAgUHdf6jaz)V#exZ;4a*bLnd7f7 zc`}K!@7%Lp4hwnS-!QniYT31uU*ATuUUR$UpeS#BQ{dq<&Aqw7zq>yrFS^p;l&7U6 zbFkC$W~=DVl^?5Sc{wQ78s=?V@Zrm*M~}|1#PX(AE|_4VFKu0)k~Ct@S1vo7%1cg@~uCpUXO@geCxkpCoVq literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/mp.png b/htdocs/images/countries/mp.png new file mode 100644 index 0000000000000000000000000000000000000000..9523df6e0170499ec84f630f6a4584bae54c2297 GIT binary patch literal 1042 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzF-?we=mepIX zU$}AX@TrXG*7}O6nTb8Q>FvE8i+650=V)CQ?AM-}*r}mhp{x+*?ldJNU{Y?z*07-7 zqP*?x%?D@C*e@Knka$NM{wB+^iF^e-(Hzp@6PmEg>8q^aTH8VeZYfk3I z^pur_x!VhJHy7q@iI1IJTeYvIa#u;wx{9*RmF1foYInCb9c--Iotr(Wt7B(x_wJIS z=`*GsShnP(vSOv0O0AkorLK0ZjnxEet5RE=3SaN;@X$FCVRHif`@=(L#6&Id@oq^> zSP>gDFC%SrcINuR{2hh)Tk~?(7Zz+yOqg9(;%ePF*^D_~hQbhw=(mlvi%Z&0Cn1-0JAs85P^+>07*G=b;s= zcdlH$Y2wV))g9A|`&PEiSrm|&ckuX$>Fby5yS;zv`r3wxS*LDpUAeex*MCcWA&IR`vl978H@ zB_|wUTC&tMrfF~X534IlA}qWzu8vMxl8#qnHmCc|Ju10A_x(#&5g~)`-`~zWbnVtT z!^N)mb@in+mV`z`8Pqnp)fMdnT_wxU2|9{VBfy2 zZt;$`s=KRBp7q-n=CDwR|Lmr?Z=Zhl&b%Y6eL2Uc(dlPf*Q7n4m3Hku^1MxbdDIKW z)}Se=$%|`e%#4Usx~zNFN2tMRRnZ@#PhM7ufsAENp2s?0-Pps-a7DoInVi9&{UA?! My85}Sb4q9e0579g>;M1& literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/ms.png b/htdocs/images/countries/ms.png new file mode 100644 index 0000000000000000000000000000000000000000..f92b84d512d29c18ca4e190413dead45da6d8cf4 GIT binary patch literal 1043 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzF-;`ajZtC)Q zkLbDeGwvL{xnueENk!An?YP(&-kBDiwSD!Wy0q!1_dVRa`eaVr5(mRc5nl7Bbzh!6 z>0(L#L_4D?0j`UjESCj&uC=#pi3#58=FlA;us9-cNlfU<)VOVF@!N{CkJOZ&GtiuF zVX)9lZ>Fi<3{$=7ruwtY^ke&OKCLaizBGVrB7}+VYFF<>#wPPQ*se>}Rjo4hMIb5lkA z;ik?ry;II_J#&BB>YX#U9zON*+n(zW58QsV?aIyNhj%XDxw?Puq{Fw4_bscOv@EH2 zM*M^s2~($aZQ7pvy1n>CU-hKez>8@iUz&0c<;8#KEPvfry0fwT`=+Ijm&{ll8+b6l zsnJyTT1om&PrDLVr^EGiz?cQb?~bp9zf1PPZ!6Kid)GE z2bdyubgO?X{4_m%#Y?H%)on)^Tc3UNpKFu*%SO%6H~9F16BVfoF07HP6|Po4Ge>zv zRA6{?@Ddggq15!*hYp{Ko}n3d^UAG=WgH?&qGB_30}dQa%?l2_e+-Vm^(L}%Ej_v`Wo5Qx)NZyXUrS1sRWP?s`n$H|3a`%GX5~q{c7NJy)8NFl z?Uz)Q7+>SVPR^T_`|6Aw6xEe^bA_$HUyyjZLcmhqTr=k$Bg5`{hRuN`=Q=&TSx!^ literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/mt.png b/htdocs/images/countries/mt.png new file mode 100644 index 0000000000000000000000000000000000000000..7f35e8201b8640e8d95036895af592f1820dcd56 GIT binary patch literal 873 zcmeH@KT8BL5XA@9LJkl70}6s*p&)|jS5S7m=nTj?Tm5Ox=5V+;6iYSo^vl`pfoTZI1fSusSp4uL&lMF6awQ!DXc22Yt$Nz zL2J=D^d3V%jO!C73H&R8owt`!Jg}ChyZy`0a(t6qZ4~3zg{N%k@oRB*|9E}#_Id99 YG})d4_}&_xU91+(!#wMzqrKw#2W(=X7ytkO literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/mx.png b/htdocs/images/countries/mx.png new file mode 100644 index 0000000000000000000000000000000000000000..5d481f0678645656e39e71a886a35062c5f42230 GIT binary patch literal 1042 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFziMjsXWI1N zv*$i|_3GJ+7ssxhJACSxP?e#2hYLfoB7?gKbAcjju_|Y|26u@jZ>bhynpB;+e7lW&leJ{Bo^rFjVz!w&o%Oh75r0lFo+g_Wot08qub=K~tg8l6bd2$RM!py~r zR_*>N+p5yG*S!1op{S+o;HksAj_$d5`*P>(o+%5bUB7qZ^`|#m_HI3K;pDM%$G-pg z?w{tJS)EeXTAh#{(=)X$Dba5K?hPpc@>!9FiIMJM0WP(rIXA9eiZu{iw`}3zHOn@w zT+vfq^+Zu|xwP~KMa6ge`kR!McdDuF(a`v0YPw%b>xi!IK^>jrdU~e}49*%EUNSK` zZ*2U-&hD3!(=98j2ljS<+}xfzIsNnUdgbQ!-`Dq@r{{lv|9=4ipL~4&1_plf^ZOkb z_%k5jMq1j#f`ZpIHD9~Bu2xk&ZEycHY101%3vS-H@$cWizkmP!`Sa)3uU|iZ{`~gs z+ow;T-o1PG>eZ_!Po6w{`0(Dnd)KaAyK?2qrAwDCT)1%V+_|%7&z?DR1{i(7NE`*^ zg}|Mpt&f2^8I!!-T^Kr8Wj%nL1D-C9Ar-fh6Am!>R4zH&JGV;RZ?4r!EhEM4EE-3Y z*X68uZ;^QF%E`Z14I__Ebx=&KjOEsyesbYM;a^!s+}d3YPMf6IW_ii%t5X!r+4?he zsilKrsB*5WWO}~*e}}MVlRoV!SukN~U)PkDy}R3&i&rP7G6rh}c=-2v2b{QOrEub4 z*HR5@T}h24ddE*{CtMa0dvop5gvk>{*hPW_9vcf5zI~aK`)-B5e`h}%m*=PA*`2pa lw;FCMzrIxMm|Nm!J_cb0gBd*14}OD!#M9N!Wt~$(69A7VSGE8E literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/my.png b/htdocs/images/countries/my.png new file mode 100644 index 0000000000000000000000000000000000000000..9fa6f816e8c91234bf7e537e740ffddc0eeef878 GIT binary patch literal 1043 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzF|2lo<5m(Q{ zuAZlS1I`78U5k!8oSJzkJ^P4H(3866L&X(m<1>y|HC$i0E+uNFiF&srPo1THmy}>j zZrZ-m+yf%q^^vh>jVu>r6y6n*npxJq~S2l8bdd^-Uq4nL}cJ9uzSI$h! zPgu8mNp@M}mOcF*ej2gKmh+b8u3Q(qajVmtHy-Emvd@xzwJ z+l_VStICg8l)aeHd%LUS$)x_f{XOsI&i=Q0<caLxl~wirKIRvTkEZgvVYxO%VVOS)Yaarss2B4!n=<4cb)B<(o#31ru?2f@j_L_ z{`|a8{k?ng^IrFKovJ9m+E90+x$)PG=?^Xc7Qmwa8h z;sH?c)-8XxZ~L@v-Mf8zudZ41>-6bY2loHJbn)l8v%n|@M)WAa3;{Wxm8?Kf#w2fd z7lsa2Sq~uRpr?ytNX4z>gab@d*7lf~T)q0FGUoK_nq@4l46QtCRln-=hCa2BopWba zl{za!tIrt~o;PnpmRL^WUKRaI{WoLlm)s>Kxw;}LKlZ5m&9}_{#I?>bH<9B9#&bwE6*Sd>@@?0yg-m&p b_?eHP*2d`L-gC2rLH_l0^>bP0l+XkKY(9gV literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/mz.png b/htdocs/images/countries/mz.png new file mode 100644 index 0000000000000000000000000000000000000000..5e6e87b417d124d4deec8324b2bcade831036f7d GIT binary patch literal 1043 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFH#0TMD=tdU z&d4puoiTex)z0FottEP?>dJZiss)1T1;ScI;yNV~`jyglZQ6E?I_^Ct0n==Kdu$@- zxQ9-5NnGk5JIg0?Re0{Y=$zFtMH>?{=0_E+O{&!Q)ahz$IP_!j*1N=gb^S{kNInNV1mH+AZymX^i^ z3+B$BKWEQ2)};%TH?Gmzv)$m>LDMrQt!`X)egD$`>4UKCo4pS03;OgnXkL=++wol;v3E4}h6lYJ9UOZRv?lt{&D>NS5Fx|OX@5o-0SC5@u zKXJQu-s$#Lw|CD2p56C*^*CVvuDU&|IQPtC-QUhNrPS@_6x&@L9(QK?pQzIPurTA& zq_kKSmi2z(r(@->&Z*m-?s(ioqFPVnc3ITEw(>Ux0d4YJ#|(rvIcl9Wk*E`7xZIR`ym978H@B_|wU z()wa)y2bSB6w%5bQ(9b9QyZLeOU2%N5^CBLbLS7!p+`ZN92PE{R#nXx87eAhSZb-u z8Y{aXz`rmuo!PjXarHvO*(*C|3I?pWV6}b4*8aqEYb1l!zWUFx5!DFE&5OKz*Sh@M znU|B*zxXH3ViVEQ*IfJN(&nO)qHhJ|rNsq|T&CO1#c%xj$==rD?$*-E#?IJkmG$|p zP4c5jmp5-R4ho(m)Zi3aX%={KV`nC#<;;C{_u@X@*u%^)`@NBRSo^VqAisOM`njxg HN@xNAK*&TS literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/na.png b/htdocs/images/countries/na.png new file mode 100644 index 0000000000000000000000000000000000000000..83d63cfcdf5a989e515629d55d65580f6882d719 GIT binary patch literal 1043 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFKf}RuQ9$IO zqRItrqkBdcpL_!U$EW-(seISa{I8>bWqH$~Df8CVb*-AXbaK^%-u8tC`i<6Bb!n-q z85rUi7@`>&ZCF`TI5|^!dDDc1G9)Al&0xeoD&9tgH=;EXgsk(+djMYU@U8>-v_KFOZNc_4J>?C!Q}VUm`4K=ENPi zw-?X37#s3_>HLqYmtL?lxfkep#?SpzR^r3Hj&oeBw`Il8$V*((Q-5b=ay~NT_LPZd z7#PknGM-^&J;T9zmXq@e7uPjj-Wvh}PZSleD9FE1Q+utg{ng6qhn?LoC#OGdZvXxL z{{;k`iHNwFk#V@E8yK^|_#Fj!LLmO5n+H&uG0EHAg`tC07Q{K|>EaktaVt6D0MilQ zuc2E)o~Ej}sIIA$PCv)S6*+BMwtK=$0+%-y-D(_6@3-E{tcRqNbXL;Tum2b0Rw$Bh)Frj1Dq+SQ-&n#l= zoUZq@Y*1J*VcEpDd#=5!+osii$H;KL)`&fC<>}`jk9)fMxvXZV`K?q;q2iPo+78b(9m>)i^sme(8B?t#~6wkm!*8cqJMoWZPur z+vTORq!mjQl}eN~>NWJI=xfz!>2>H?%&{<;XkyTA;Iz`oZMB=zA}6=SZUNf@{5Sji zZS)J+5MVaJRH=zIVY6xOG_TURfrZloT+`Kj3v@#&j1yb!@~8SJ8Vba>>sKzbQZQuA zoyyR@TygC_p&R$r&Rk%8Riown740dwzXw6H)q_r zlPe^I_1rn${Reo{(m3zklem0YVaXEd8#mNTN+i6!h3?<8Xl+%0@gktQTL16gl&xDm z{{PEZupn;VzLI_Ws!L1bmn@l^7{_q?nuxm#`_(N1clXPFza01XYSxQY+9z7LUQG8m z)9Cp~UGcT4{(Do?-8woa3=A%sm>f4Ud~av>-O1^)wbd^-x5rLS$E>ZNySe@F^Zn!R z|H8}jPe8yIKfiB4GAQtSO3JsiRA3YXBYG5IhQP%~YUw~x#w2fd7lsa2Sq~uRpr?yt zNX4z>gab?}OP@?Ny&~$GsXy~6Dz;w^ii!_sb)CBO zhDk6_F3zsbk#T`Qc6exHWnokjyD_&kySTb_Kt@%xlV@O9P)>3A`zw~k%Y7NRbaQ&o zpZE3a&3-x4Ci@=GvbqHqn$8`X^QGs^o^PJU&(F^@+Q_f*L|$y}r3+Uigx|du7m^W? zU=Z14{v?&rdAUNk1nLBY>V!mEMT8rKCE6q;S|kKx z1!cQr=xTOt#PuNW@Xf9 zUcGqn;`#IE4CTTe?*@+o~z;TVirC x!r7HkL*?ArL-Xtws_$R0dHcbD*f^=#?25PFDZ` literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/nl.png b/htdocs/images/countries/nl.png new file mode 100644 index 0000000000000000000000000000000000000000..99b5e139e4c930df1497829b3999920c8bc3a454 GIT binary patch literal 1041 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzF@8;vbdgbcz zW5-XNJbUc;>2KeEKYjM<#?8AYPM+Dj@8FN0e_ptsxD&V|L!hN%1&|$^E?J^D%lmj-X25!&{-Kyd>+c5dOhVNq2luOz{ z%k)Cm8bxn4OWbb~v%@HAqeb!&my$bfCHI`NPr4VK52$+-Q1j5Q;$~p&UHkYYzQsq} zGuB5o-SR8g8C82SZ^}~^t2J^#2h0<9xfPztnD8W{_jY#wt+VGZA3u5a=kI@?zI?xO z_3HEI&mNpOeujaeo`K;UGxG&j)-yoF!Eu(8^BOPj4FQ2Gf`aEnL@r54Oc4}(C@XtU zUjB)q;uU%MxssCa^!0D(>b^EI`ebVQ(86MqzTPhv!-n;kw z=FKlopT2wO(DKQXzuvt0@A2cmj~{=!dGq7Vn^*Sl|Nr8}kMH0A{rmUl&!1nve*OIU z^V_#?pFVwh_wL=RSFfHvefs3dlZOu<-nen&+O=z!E?v5C;ljCd=gyuzd*;lUQ>RV= zqYoH~qky~+Q17mt1k}lx&=gJK-&Iyovu^KJXK0-jbvH)cf993@w{M=haqXy$sK$}Q>IY6e zdvfCB!$)V%oj!k*SER@waPs7-;oD6&Z{D)qz}%FLE7P-!tJA|n^R-)_+&rhFwdh*Pd>$kq$xzDJQ)IDw0vJHpWwKD}w3WZGaWF2bM zJ?b3eCxw?RnYv&TtA1w3jCJi(S4>;FYr*=%3b_tzpcAt~NWlqiz8b%$JEVFYF}A6 zbz4fy!i@H%`F*RKmL4gcv}WR_i>-_ImGmy1zWwT?jpt@;I=TGN?Nx_vZa#H?`nC&a zn`=KFJ9KW(?z1))XCgw+MTehBi2gcx!m*0de+%Yb>FW5tbkP|GhI$5uvy6=An3*rI zvYugOJq}0ueG%| zC@Q|w*WaY9yhlUhld0)`Ev@5vdOLNrzgk(HGBDVrrFGZL^o*&|Lko+mW~P@+On%te z9Wgfg<>a*6$mqPKV|duh$jBF&X`c%6E+!}bs;#}@u3Wlx?%pvjjU_7=E>qIiUcP2^dcu;t6|49~ z9z9Gdy8dYDoP%c$9XxyT+%YbZS6V$E&4eesJDL6N&5HF}=UKT#kGEFN;y(2y%zW#W zDbG@tF}6-R#JpFhW$G{K+gaY9HX8?RsAOk&%W24CFqwA&C?Gst{an^LB{Ts5U}9e} literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/np.png b/htdocs/images/countries/np.png new file mode 100644 index 0000000000000000000000000000000000000000..254744a23b4524efd4a080f12b70b43892eb619f GIT binary patch literal 730 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcX*_=LCux&QzFKhDMd%F5=X zvB_~O>z95(7u5{^zkajH!1``n#u7&11q{NQ^c>m41JCr>&vWy+al%g(M{`}gL} z3kMILIdS6S$B*aFpFeZv3@{9VAxQ=}-|M#=s4cG~$S)XZ2>k%V0#+Mipv{a)-tI08 z9jvk*Ku({hi(^Q|t>lCQOgcYZrkWNDGN`0Hmp-eyrb*|C+_V{aStkzZE?B@Q{K@Ot ziAl!ATQ+P;6%T3R*m&%i%ZIMh-lsi0yH2jkddbwf=n!+vj0%yj6VG(@czbyp8a@hl z=4hRj{``r=4@*Ptm4{n;9tRs63)$HIX};;QMbU}xn%TN@-}3An6&vr(5wfbfv4@!< Xs6jW%Ir-59P`G-!`njxgN@xNAqWfLi literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/nr.png b/htdocs/images/countries/nr.png new file mode 100644 index 0000000000000000000000000000000000000000..7f452297903402732194a6feb0be6f9d33181a52 GIT binary patch literal 1038 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzF=TPnAQt#u_ znJj5CP1<6foLQ%$WskUeoUZ2@Rm(avzvT`wdt74H*@w)v51JB`wLiSzgm=Qqu-pT2 zB?l5p_vSWT;MHsq&~6vh1)?@#y%rvsAQAmmQT@uCK55eq zS@RwRtA2TlE@j(Est(gMoMvge%#hVf({h@i?>R@?x!1&ZzJdD`1CJ?Y0ZTNj%B(_G zs+s56hAp@7pQYzeYvA1A7`58its0Hq$L;v2*xr|MYDham!pI=Y(YMv=8hK&)?&lv^=tCe?=)vBg->$(c^ zok~mGi;LXqY6I)*LVLOsr%uW5?#h@myL|PkmiD%c4eLAi?4GrFlKj#siaS?YtzTeu zVu#P_dG1$_#U0)nadLOuowJ#@&Xz8lslCQOev|lNnOQ%zfMh^vZZIvp-YZVRgSKe57n}a zxTM&&HEP~;Q1m#w%3fWpGl)z4*}Q$iB}zaTH3 literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/nz.png b/htdocs/images/countries/nz.png new file mode 100644 index 0000000000000000000000000000000000000000..841bb9732770e1e4ba4ec6969deddee9b4b39898 GIT binary patch literal 1042 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzF-;!IfucYHp z@3J|W?Y9qIkMoG0T{C@o-;(Xiwl#;h%`aFysdU6t%V>-*$e6FL_A{W~w?hY%QZRUA8ul8_SyW6gIHeV>n>oql;V_~wu!g!XA z`4T&;W$w;v+@1R}QjSN3Eziw3QC4)ZvgA@#>BZ8bGfnlEEKC=>Ixh|mT$G=8F*0HM z>yF|Vebrx@au4RlzwfMgym-d&wr=x(#5coWEuPIO|W0JSK3quF1tOt;Dz|+Msq~ca`!U3imtX@?|ek`#% z#p^4g$}F_G(aBid|K;2FvyU#x3sF2Jb3cGVWR}^+)w_!iU6JI{4UMzPT(#3du~KiF zr_&szYpFtyOuuUBNI59-S#Eu4w06&(sef$V-mKbW=&N! zE0T3<*Y=xe6f(;^ZJSHs-axw!VaIN9p9%6IGc-JFH3Hl8(^l9-_M4{8btv89Q?kyl zYJ0F_Ip^!gkB(Uw9^qg(!pV4ym-VC&*Evz%s|pg2jJ0AZKfyX0W?J;e7}fam9k zz%vXCr76dWMztEGOqRUfy%Oyf*{{&I<`$l8`tnDe+KN_KdXjB^j9~ zii%eh({TJKYxDu^y%HZcTb)?dHC?*jT<+vUAuPW%9Tr(E?u~A;oP}%XV0EJbLI>% z5`j@U3P=rsmIM|SpdQ8~Z+91l4pvzYAZNd)i(^Q|t>lCQOhrzgPjgHEQum*4m+BPn zpUxhjv2@8MlkKIKw!92h|MtDiu#CC2Yt<_4Nm)|avtPY7iJEo$R-@CJqdBRHcI(c~ zt2@K_@@8bF!@?&`A!6pz#o6rN8#-?6IFYa*AkJ;a^tC&e&h5^R@Tn0ARtV5AzIFSa zQ*`+K11FB0xe{?%Kx4{__Zdr<>M1W@v1r+ rs$}53H2LY2DMEsi1jL0!jy{uRV6fDGX%rIR0}2aIS3j3^P69bE?ex@|6efIkE#yw|`p1VD7$=bd94}Jaqi_0Wm#Gy*nuQ{b{)BN>EFW-K4 z;MlqMpT0eR^^Q?Lli4_j)ijUYynxptpWmiX$i76vsYKDYRo%Z)GoVpFYNA18r&IPE zkK8$ag|joeHy2LWI&ahII}e^R7-lgWXS15-a$4l^+Lj79RPfsrNVrzW`ZURV*Xo8g z8^=wsNbL8oSRPQmc;BI8Z{L4Bb>`gNd-wMpJiPDd$%BUuZQ8tf@{}oO&z`w;^Tvt& z`_^-_ZWHF+Atta+gnzxL;Ce}seR2{9m1U2rE1ogbK5n3W!BqdUmFX=PySpAvSKS=% z`?&3PvVRohd&ST5aj5^Juz&~Qf%ifK9)<^>4fK7I5OX&+@p2qsabLYH0f9}HW zU8|TF*03^f;^EpUBC<(B?1ZM;ZawX5wpKe#OpZF*J@ECq?(g$3B=GjKr6*Ue+_iM+ z>HYgp?b~_OE_ zm&51HojN%@A|`}Ee+qQ1plzxhrqu1M`ho7A*bH(bJrzB5l7=>TGdM*6=4yIO? zP|+nvkN#xYa!VpwDrSysgVVHAo2+gH{YgtY+q=?psjqN@(=)eSwmdKI;Vst0FY;L9smFU literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/pe.png b/htdocs/images/countries/pe.png new file mode 100644 index 0000000000000000000000000000000000000000..41794a019c0181602055cb9a89efde71833b6f09 GIT binary patch literal 1043 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFKh4W`Nk;yr zk?{pnvm;j4pOR93rDyyoE&G#K^1rm|%$)gG*RDTv^3<(sH%^~C{qF6%KY#!I`u*qB z=`;21y(i9|yZ_|Lt9S1%T)A@Z;lr=rzu&xl`^2eJKYsqqoY{Kn!r9sl-Ej*t`%X-s zd}QYKw|n+H+7~cAVByV$_wL^-nvl10*V0vcmRz`TwtH2@_a9%&Tf!$!seSwQ&B6&8 zi@GWnXL&z+@_6Iq_9OFW9q@NpKY8K_28Lq{40Q|)wG0d=nVF9>GamzzEG)-aSx>RE zpWx&?$;*3@pTCof>y(htSqX^=f`She6)!2spI1YU^)FxFr*3YqJUw4{c>MDB z{}T}KD#MSu;B8F6?Zmne6(-h=L;8pe*gaQ z{rd~&&YeGZ?&OIRzkmP!_U#)mT7i)}3h;-3%5SF%pbEw$Z+91l4pvzYAm^Z`i(^Q| zt>lCQOgV4=aQ|NBd3KiW>FIBUXNK~LZ2EleP3C+pO$7y`%~lqB*T`u+5xjpf^r-f- z#cL1TpA{Ao&LqN>`z#}AW5AT_K^If?SFAn5%C+(9b`|5<8l6%vG7CblJXy}ry6bk) zpBZPa`s((E?v(C|6mE2yyR~Dfx&B|;Y{u1!{#8r Nd%F6$taD0e0s!cTaC`s& literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/pf.png b/htdocs/images/countries/pf.png new file mode 100644 index 0000000000000000000000000000000000000000..cf744fae21b27c2bf023aa410ecd7c6c95443cd1 GIT binary patch literal 1043 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFKNc2#B0Bbb zX4d1yOJA+ouzl+E!&RNr(>u#NtJ~9OO)6j9RlhSOdf}9wla(cl7tOo8WXaNf2cEa| zT%5OPcWLvfZ3kX|`TAqg`t#p^{=Rwp&bf=1-hcV}?eE`XXU;r*{rbked#BEy|Mma> zkH3FE|M+qF#*Gta&Kx*$WZkAs-+%vp_3qt^H*cQ4e0lo(`E5IQzW?;;-N%oe-QDLe zUi|g@_s?Iye*FA-;o`;f7cSg>aR0{LJ0CxNymR-?)oWLe9Y6Nt=l8Q`Po6$~^5n@A zrw?p9v3tw;mV`rjUZ?hK-;?S0Y~7sw^Cmwyy60e^(dF{Q{nL7mIO^`7(D``&tW(X6 z$D10i^mQNZ>$$sV!NcWC|LouMdB?UB3=GE^7-|_9Y8V(!GBclMWjz5zoSYYVc`pkH zoRg5aEi3y#QSqXJ{47byCDPKb^!3*(E59{0-L0i{+`!|2rVyYe2xK@bDT#!{1q1C&R)nL`P3>ak-P3@v^GwYggB!#)cgk8NVh^{yJ&m z*V(g<)z^KVH}7mu_nNB89WBl0rcc{9efsZTzkdDv`R(i1uV20#IeZw%12R8;{P^zO zySH!OzIyfQ#fukDpFVx`=+VQ65AWW+d-?L^3l}b&J9iEkH2e1L14c10qDKK{2xKz< zo(~jdO!9VjVd!9$^#F1Xdb&7r=4MqQ{dj7j>O#aGJW+_wCwV zoijdHO-sM>p4D|wRQ8P(l{FRL&yeoQ8k(w`yI{hEohMB)%gyEM!}BA9H?K5vSlGGu zT5-xAn;X?NwoBD~XWGhZm?VDE;bv#l^ONIq?EE+L^P2{zTH|MW1tL!$KYJ>^ZGPVC zEdm-T8B0~x=jmvwDe0vrtX#g3Uxe#5M;(F?{`H^l_P*?i!GPJzf1=);T3K0RUUjs}ukL literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/ph.png b/htdocs/images/countries/ph.png new file mode 100644 index 0000000000000000000000000000000000000000..24007ab8bd4d406430886344699d5b2c5a0d7a27 GIT binary patch literal 1043 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFKdY>I*3;|s zsv>^>$zE z<~%htaAlC+Vg`mRM#daQ#%xB$EN12$X68&*);w0$9Cr3XPR=|ot|DIEQeNId0f7o3 zp%M|1S_z3d35g0>*(OEBHhKA4HMJf|$tZ2@K6Uj*ef>$Mrqivg=2%!vu(O-z&i^e);T*Ws4_1KOgq%Vaoqk4c{JB zpV``ZW#6VV3=HR(nJ=)iUSwy#!o_usm-mK%z!^co+aeg4p#%j=b!+kao*cb=aA{r&$11bp)G`5PGc&Cl<5VBpVy zfHPrXryJ@&e*F0G;loRpE_HWz10xq0#iIaM2n29nP65g>CV9KNFm$lWdH^{GJzX3_ zDsCkw9AMhB=j)ogvA!lxRiA`x?L8yg=p^{hPA+enRhN*_si?NJZF&w1e?DZK$H%61 zDacFe*D|wnWey9UEP0V&ZyM>zS{j?ItzON&AfP6yDkNor{{Dsq6FO$>SYZ&Lp=hdV zXwuv~wRi69>HY29!Wtsd;=)G`O$m>=Xjyn{$-8TA3ogu=u;FIwPS@14e=jflR$_96 zq4n9h*;A(m2Si=BPOXZs4$f5#(3otgZM}cVs_ai^ICFKsUVVCF4>QC1y+%emnY)5P OzV>wWb6Mw<&;$VZKSPHA literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/pk.png b/htdocs/images/countries/pk.png new file mode 100644 index 0000000000000000000000000000000000000000..ff220ee22c62f438b177051a0846c0eadecc1e94 GIT binary patch literal 1041 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&MLS-~Z#sj(__2 z`O39xyAJLxf6kNI)n+NF+!^#9u@#OiUs| zQX*7B++SQaR#w7SLN-QLF-cKAMqV*dQQAXVJxN_LKv6$WUq4r0EnH1MLti6O!?f5` zD_YC6&{Q{8*C5$IFHX;*z``WM#2~@IEX&L=!O*F}$*JDSvC7e{$<49C(W%18t=i4M z%ipiV&%e{(v)SV&`7#_Wb#?yLa#W`2PLx-@m_p{rdLp+sBU|-@JMA z^5x5i4IMm?(VLyuLnjZ zFiuASks+{e)A~a|rHo15?k)@+tg;?J&VEl9$B>F!$q5IT($3C`n>PDt`od)kvQpj) zit!80GF+;qe#h^0ko)yxsuo&;8YabA{;6Gy<0dTFSDBGk;-nLh5oI6j+Prbfj*iYP z0`6`x!T}vKH*UTXHMjfhnS0ItO4f(uHLhH{7_?^XiNmK}ipfltk$k}{lJ)+bc2J<$ zx>Rvr@9B@%PG{vR-Rh?ka>?Xu@=87ZiQ*s1Sh>FX&6u-3G2`{o^RddB&tAV{5m`0c qWaohcrz}-8x9&7N5PXbrb~%G1gQ26+t>r18AnXINP;va_G%ux^(Fx(B2Cd&YwSj?%cVvpb$T^d-v{5n>H<9zI^W7 zxl^W0>F(~XudfG24KRX60qsJ-&9Y+!&~(NmZ+91l4pvzYAZMSai(^Q|t>lCQOjg#n zBP2GT&YCsrm6msL@MK4)w`U_?s$T8&eC^gV_Rw# z1Z0~Q#|702N9Vd0`W1QUX$N#@TInfj+1Tiq7%7>l>DdWthzPw&U#g+IIO*9dX$g@B zk9kEtm4^sCdLke&*?jBwf(-^27`ZA}b{A~^+r>mdKI;Vst09(*x AvH$=8 literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/pm.png b/htdocs/images/countries/pm.png new file mode 100644 index 0000000000000000000000000000000000000000..6f9bf9076d8039c6005227fd73f2df272271ca92 GIT binary patch literal 1043 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFpIu!usjmLf zg-f?~?48v;LC==I#>%Qx92tcE@CI zh)!RmW;Ipada9P)6iu6cU5Ck*{%f5>m$^r+af?_LlC~u_e@A-dshqlV@ph&S z-{d*-=BMNpuG_nJ>a1B;Z``6|iu)(lHZ zonPP9p4r=1zG+j#x^+{gOmbYjFt)M5yR$uT`n0q~3rlxwZ(p(4cKu41##-|UJ)YaQ zH!-c9&#`l@=#^v2@9yiryk&Z5o8F22)<53{ynE>P^k%@LYyN%h z#utwHG*;^$-sSP~UgX`&q1~-!tCzSvx|w)zNAS}5o=fKWb+-B*+*5J>fa=sPh3D5z zx31Lv{@iZOLZkId%#QAIo78D?_E4~ezT}!(iSGK8LsKm_#;~r8FwIFWbxAr=hrAHoZY>9@3w8gCfeCfMyuiSi6+QMV~=j-7Ha-9y?FHHB0&emX{^OJOO9$?US;)q@+l?h$BjQxkP4}B!1E<>%R8w(wYTFb{$GfTyWuv=H;|vkM@w1Z(mEwzfN17 b@R^Tc`z51~7d@2XLH_l0^>bP0l+XkKz=d;p literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/pr.png b/htdocs/images/countries/pr.png new file mode 100644 index 0000000000000000000000000000000000000000..0671638e9f51e57e45e4bf5d6afa3fb9bc4b5153 GIT binary patch literal 1043 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzF-ytG;%G7Lg zYTA4;^$q1s?L1oUg1RTR9SG3yoK-t5%b_gRzBbsZ)=ay4-po_lYEhy7Q!9(Nlof8M zELq>*b!__NV;;`^E)Jz_jfaa17FSm+eEQ^*i$ix*_=3LfLpQF!3JIFy>RJ~Yw@gYl z#6M`}^x4N&tUvtm``-r-?w?pCr`LCXXbHsh6)zOBfK1^ElofAd43KL zejO5UG&1a5e9Y&0v%f4}aJHlE`jkme7BBp`X~UIya~`Z*zP6?L?T&3b`g@Peoc`nJ z;fGr`{XTW#)8T`smMuNMdezNsTR&a8c<EaktaVt6D0FwpJUzvr9pXI~$`U_#HD9X9gW69Q9WW_7NN zOympja0m=(nr~~MV`aE|$Cd_5W(^fJC6(iAlXH`^uV1>Bb^i{Fh)`J2mdKI;Vst0GQT%_5c6? literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/pt.png b/htdocs/images/countries/pt.png new file mode 100644 index 0000000000000000000000000000000000000000..8d32759e8c04d837012bcde1f68112d541ce23f9 GIT binary patch literal 1036 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 literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/ru.png b/htdocs/images/countries/ru.png new file mode 100644 index 0000000000000000000000000000000000000000..2b7093c18881dad7c86953ff272a5bfb738a1c3e GIT binary patch literal 1041 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFU&AZ0MnGz# zh}eDZUyv=$gn+$UoS(L60nRU~@|767M>s$Aq*s|~V@e4Pu+~+%FYZWW@=`|iPsz0QjFu|m1i$(JRv$`E_({H-= zUvTO=YF)X;p<%mQ*P(#9cl>5t4Vr&9VB)Fpxz~I;cV(@4n7RCJ-nz#(AHI10{@acF zPhWrf!4S8cIbkJh+)~cum7Iyoc{4ZhBrTUM-zQtNO}==Ge)}2I&NBw(>&+YYI8DFl zH0hFK?+LewXZ#o3514x^c-G~JMR&vJT#j3MH*Mv;?FUaDK6Cll@#AM07)~%SoMdLc zz{+}tmGuNC=S5!L8v+8CBqZ+0%05w4yrdw%L|S@-qT(xk{q@Sqdo(mYnVRm_(mJlE zcih0>p@qdI6O)T(rr(^L{B5Bz=gyrwd-m*^GiP@1 z-aU8j+$mG0)YsPoqY@aQqk#Ajkb9>p3{=gS~e#=$6VtGf%kwK+5a3!?RTLGL z=jmIUoSPb1$QYoZudHfnynMs1g)7&s+OtJNes(#7D}!O_Im5EapiuC1^>bP0l+XkK D+FWGp literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/sa.png b/htdocs/images/countries/sa.png new file mode 100644 index 0000000000000000000000000000000000000000..f7982cc0282ece208059d5c7b989f4cb34b934ae GIT binary patch literal 1042 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFZ(iHNP{P1a z%)sEuz~I5aSjfm+#>`y8%v!<9TE@y&!Nyj`#$L+KS;5Iw!Npz9&0EjQTg%H^#misI z&lSui&?F#KD*}@Y>9^|} zbQoxrYZIA&nlmQ4FUe^`~x=z z2CNV8TjdwHKG1EtTfmxtkc}b!O9Fi6`S>sP58oIbz9BqzTWtLH__%Fx@mt~}S48?v z_Dk8F62BonVM9Xdj?}DuSsA-Cq8CSp&j}Bi9+I&=qhx zUzMM~B0pnpM(c^zwi9i6i}G?8=60OuC|FX^xVy1zd0EGSj>@H#jcXehTv@Q@{F=?z zHycdUH|jJr>o;|r=U_j}&VGhn^!BK<9jUonbCw-m3XDErB#r{|LZF9(nGdLwG0EHA zg`tC0)&s~n;OXKRQgJIe;Q&*_&5*sHCcjPDF>~jUsXcd^8=Z1Ct*gwO_i9qpoowV^J!hzqg!o@4o&Mh;9w zrm4Aezh0EP=CJVO%fDHlnt~P;`3X*bR4c2~;B@n!l+v3wOqXW$Ei`o0+k4Dm;SM=Y zKfB`hEpsj{yVGg5?3aULv}B%`oGbJ88CNE$R2w_zE|_3sZ`?j%PG7M{h{OD;ozu9? b-ZL=VT%db;d(BsQP>^`K`njxgN@xNAZx08$EjKll>xasi&{3dOY)5fgb!fDVfWYHyQn6BwP!zz51RcOCQ z#s+nZSdX-oewmBIOSZa1_Z0OUODbO)l+<1``B>M23$+vXF5Pr)$I(YDIt^@kwcJMa zJcc!VCJjR7P15$A+CCHHjUp`~=c-z#yQD7jNLw0Jz9qR~Z+h#&%+~$6od;8@S1jCo zQ_jB1HoDg*t<`(I5j@6F2kUXH*ZsbYrmrB6t(zecInGK6P8+~t#K;a?4PsB z$E{D+Do5I(L@{oWsc*ARP?tgY1e3@~W@!t73cRwGx|MA4E!*l}x;3zTYhclOzvA_N z_U!`BWy(?W^xbRJJnJ;P8?^jebpzY=LV65?I}O76j3XzRMocitUh5P$-70^BTk>4H zyC2)v)4=PJ7ro?XTD$=!_7Os6DHVh-kh*;9sBAP)~623E}N%tW)H*Jy^Lq}vR*sN zd*h_QrllfRj>*5cq4wgA)vvcscQ4o++strgC-d1|oR<$uKe?cIbgR)>WhA zH0PDZ0Up;vZaFx$g|98jim!KFQLPrxaoi`!ea7uwYpbJjC)QRp$OoLb5zv2lPhMVl z_RiJOjuZCl2b}N-Ik9Yca-8qN;DS28szv+(9j7-H7F8F|TgTe~ HDWM4f7Su+F literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/sd.png b/htdocs/images/countries/sd.png new file mode 100644 index 0000000000000000000000000000000000000000..32398df2f3519f1e7b78df488bbb44c1b2121316 GIT binary patch literal 1041 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFzh>uf=I}8~ zGt0{tFDof4fB*ICVVWN=_$ zwr1u`;$+og<;~>fOXlNp=Mu^llE{^i$dQmQQ;<)W=al7CuU1z~P}I!V)XLSe=&`Wq zu&}PR_L%AsFgL)h(=A|jK=`8YxaDyvYf>`SXJl>2YF*r_qM@>Ihn?X#1H%bs=F_aK zCxD2P^8zpLWdVV65)y|cB#uf--jS7kps09WUVg5mAf{Iy=!6d z)ye6Ho7*Et$HUgvzx@4w2LyZ#2>1{j{3$&AM_ke;hDK7M@v;>Fu%&u(A6`sdG|@87?F`}XbAr%$h6zkdGw`O~LQ@7=q1 z?b@|Vmo8nrc=5=QBfEC(Dl9BaPft%wObiGJ@b~xk^Ye3ab8~WXvbVRlv$HcbH8n9Y zF)%RD*Vot6)6>$@($LUQR8*9em6ev377!5N<>h5%Wo2e&2F4vQ21fzeAy6ZxD+bie znB?v5!qCAg>jC8K_jGX#skoJ#aDXXi4)fy6!iVUZxM6O4^K@yAl$FVP+FFSLfpI|*0U=SDTq2i3!v(^PlGZ*j*VNHly=omJSLO`Q zPKixhOs`#+x_;CA=2oWGkdz}5YW{Ds^Yb#YUcPwumYM71Nn@XxSMFcEbmKzK?VE?q b7-yF=NU$2nuG9J21_~5US3j3^P6uW49e>nl{Yf0Y~<3}#-&gp zVRb;w{fxHHIW5Pzc5!#yQXg3bZT8K6;-B+0Ap2HI&5P99#|+}xjH+u`)Yq|UZeZ0| z&!)MSU3&|M_6km&Wn4Pz_zbrRn(P!bS|Mh+N78DmkY>Gv`64-oLrN~k6dZOa*soWx zTOnoGq3(H7#$=+R)huP(IR-%&lq@G{I4?B~zoO-`T;FTGb<7PzpG~HLyDYj=rDMyL*G*BmwoUKQ za)XUCbkA=xJG;qx=OWu1dp++R_Mg>Zy?l!6yUQsjHiayh;IVFA__CSto0g=X+Fh|@ zRsMo0iN|-=oZ8!T?c^k2oC0HZ6c7vn_9B(PKt+s6-tI089jvk*K+b+o7srr_TgeFr zm_$U+E)`buGYSn2x@frVI~N^+`;a`(CVVH=;`BKR;Dbiu18f< zo&Gd9Z3{Fknz%N1)~hNpzkLrA?>Q`-S)ArS`@)S2_LW{=zs!m>UdGg_rS0`;^{ZFK zpSikDpYrbJYIO3H%-mzS_3X{gm64h+XJ(#sP?QTxTXtg^pJAC_o*ti_nb?8}tM^Im zPxRj29ulykzkBgq(SQ>!-kvAc>@^QCJ9Pi-&4aguW|uQO(l+>UwY=^f$n&1AelF{r G5}E*)olWlm literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/sg.png b/htdocs/images/countries/sg.png new file mode 100644 index 0000000000000000000000000000000000000000..51dc5a83e797ce924d32b253f423aaa39dad0a54 GIT binary patch literal 1041 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFKX~ZSrp=qL zT)pz(!Tq~;?_9llhYte_U``q>c!#eqObF(oZGYO+L1#)o<4qf;oP%pSKi&b^Xt`%?uPoayLY|1 zee3&+=l}lw`}_CrpFe+o|Ni~!*RP*HfByLK2A{`~oK z=gyr42K|{cr%s(Ze*E~6BS-e{-@j+io}D{)ZrHG4`SRt!$O1;$D4B=`jj&O1he=E(n-WK4Jdqg?-!BO`N%P@8o8tfD^h$u3tOi z;D7%{%(aWIcW?4(Op%)}G4GYI^z;c+)`(6O6XX;*rL!_SH$QuY-r3|cdh4DhFmZ`) z+`47E`PC`nDJf!`wv~KkYF#CD`}XYDTHKqBK50u?SO02o(#d_h_G{=-%buO7Z)ESD d`FmpzGs7k?{l$x_vKl~P=i$gAM=y literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/si.png b/htdocs/images/countries/si.png new file mode 100644 index 0000000000000000000000000000000000000000..e8f874309f6218bb9a1e7d743d1cbfe3d421f2ef GIT binary patch literal 1042 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzF@9vtraN(Ai zxYDJ|_g=buN6RoUyJ%8z&FoiiKF?XQC$(Z(dFRID^n5w%0tU4-R_!cS?MyDcbOEyx zQS&@SwbUgMgv|2fU8?o`8;pF*EJEt-VmsZ^XGN4Ri>g?>bo)gHy=-QKJWkU> zUaN9h&ldftDF(rfW|5sv*^4bAS}Y@5+_L8Qm#q#cUE!S6kZ_JO{cE7tEl|LViH=g*(*lH%Gf&AU&If47{#4q1U6N}|U#r4Fb|9x_lm zW2Sl8O8bzx_6%K>#YP(It@LksST8o!dFW%e%gJoLt?^|)$Dw(a~ODXZUvr;dnC)HF`bhNbm`}gn9pFh8U|Niys*Uz6nfBg9I?c29cpFX{N z_wM!U*H4~2dHC?*y?gg=+_-V=+O;cJu3Wlw>B5Bz=gyrwd-m*^GiU1S>wz%{jK@(x zMhL|C=G_KrV@&dPcVXyYmGuB}4tTmahE&{2PB_4{>|+EGl>=7H zi|uQ_nty1@%E`a0t)eBO8=ZJ{?2etOoxI#{=7rl=kKMS#DH4?YDfMx|rp;H&&5AyM z_*BBqb@Fpj@h5Ihj;;<*4{fcJUW~0Vu_;^5`uLpH)yb8SdAoLPgVQT5t3|U8MLn9t zcB*X^SJf_ug}b^YEjsk*(xy{Qw`RRs^`~e-KvBhn`h<)Wr>Zi)G_Rx_o&XIk6$J|& lB|T+xeQjM+O*^UCBuvHR%b`zJ8yLqOnF|A6DZ{-;7h&m^TB;T1ViQhsL3)(uk1 z-wqwUyl?;0OP7B>dp?_Ac8;>~R?moeS~i_p_FbOIE2}2-$5m8^mirh-#|M`My5wfX zv{z(LuF9LzQM({Nr6Vr1DnGT`*EJ)=C*Q$5$<-;x(Yx9%sIj%JgUh(cGC{h}=a)Y-rfy|O;k44}2R?uO z{_Mr86KBq^Uc2t$lc&dyAOHU8V z4`pSqD9B$>Q9P@txLjI#gQDU)ef>?!%6l|4KAD={HZa()rFC3S?~ zJ9o;IDfRXBz}N)F=_nvF1Y~x6^93qpO!9VjVd!9$^#F1Xc)B=-RNP8VIKY&4c9!7b z8^(#BwqypYefwTk*3gpX*FRN2TsUvORi;zCc(QrG2@S2NEmNo4Pu0J4?%FXc8zzk> zQc`O1x(ZWtMPIyl`B+?tN5p9RrVx$X?$eVv4GceTD==r}`uTg8hOzf4u2Za*)fGD} zEg4!(OhTu8dDF`)5_3=h{CMxD=3JPis1Pgg&ebxsLQ0GD-I AMgRZ+ literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/sl.png b/htdocs/images/countries/sl.png new file mode 100644 index 0000000000000000000000000000000000000000..beafb9ff4c972eed4b2e969e3b4b20b86067142d GIT binary patch literal 1042 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFzk22B@ngqN zo;v&c&%d9){=9nq_R7`kr%sj>%jFB#Dwb`Rj_Ob^Sgsh~uUWWUw{(q0#w^qJV|s;43`$p6H0?I2 zTxZ#^-K=u0+q6qgo%{Xg-3XX-&2Rd7uL(z-%I5|2?eS_@5xd}0V8^D|X@_#w+|6Eo zxp4hmhM4)xaSJ#T7s{4yRZ5wx-*!YRcdl98MyIJ4-6k9jm~%OA<&_t&USGR$^UBq$ zi}C-{&gDzI=094?o72PWl;8Hur6n|ujF)T;Pq+{_o^2+jS&p)l?`l{ z4{DdUPm>I4RZ5wwA3s?)dy#4B8mIh4_GweCA{vd7d#t1CEE+ZjHm{59-JQ^~KDuvr za?hrWS%*rj%NSI>7#ylu?JHTmS_J%BB%&rMT1H7^&a$Z9;MTk~pmlTj)B{;ZPaOLB z`}>=Bug+gQd+H1@ERP*Me(1-quit-udH3PMCGTS690 z$WE;+PA>J03=MX!&5do94(OP=YF{nkw3Y3d zyVu9K!70a2W{!V=x%EonQ0j+%bXl6tn6GHyI{hm9UT)k%vjR2 zYudK9u0?xz0z3{KIumo{(k;Ks2k(WQJm$qUyPUynsiF0ivsaWsA>rxj=d#Wzp$Pyv Cse)$! literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/so.png b/htdocs/images/countries/so.png new file mode 100644 index 0000000000000000000000000000000000000000..d087512609669ae913df487b21cd822f22cc075b GIT binary patch literal 1033 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFKYQuAdhTki zyw$n|YxD|M>ldyuEZt;KwAP?-jZw*Z@RWx2oQ%9$0Q$x5Kt-qjSqX zy~ui}x-Fg^2Yq{vdNl8_N}p(+)Zy2$Cv3_Y|BgN0O`9F^XF3mFq- zIA6N{QQ3yaX)}(LZ+KL;{z3Wr2PG@7S8saMu=zp5mIrM+p42bc)4AgC_RFsiojCjO z;lpd!t^p$j7&W7S)*;}qrspKk4#p&JcNc~ZR#^`qXS=71V@SoVKg>)i%5u9Lm6z p`e9>Z?2|_?bCOmp)M!0x&2VOcX7sl!<%OUy^K|udS?83{1OSMRQjP!s literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/sr.png b/htdocs/images/countries/sr.png new file mode 100644 index 0000000000000000000000000000000000000000..e06354f741ce2a2a9d016bc65715d3069bb3af19 GIT binary patch literal 899 zcmeAS@N?(olHy`uVBq!ia0vp^oIuRS!3-o%c^#X@z`)E9;1lA?!0>+*jE2C74S{02 zskeYxf~h3PFZe&h)9nUcKpta~x4X;#rR<-M0y)Z_E{-7;w~`YWnA`*s5*iF8B@%Mj mEQGncBN|-w+j0}c85r1;7^LNAC*K4rXYh3Ob6Mw<&;$Tur5rr~ literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/sy.png b/htdocs/images/countries/sy.png new file mode 100644 index 0000000000000000000000000000000000000000..be08e92cec7ca2243b3445bf1df271f57527278c GIT binary patch literal 920 zcmeAS@N?(olHy`uVBq!ia0vp^VjwmLGmxBBofpW!z|0Wf6XFWwGW=(7a&l_<-_rBH zXX*c?YyYp^`+x7T|HsaqD?SGV|Ib|mg8$dsvqNYGYce$QgLs1*6hlT-sG}F^Vgry0` zRb*^iTvWRjqhCw=pK`NS2CYDhuhFK<#SvHPUK7my}o?S7CLpg<0C6!YtkxM0w zS3O-oD@#Z_Lqso6(x^znAV=1$RMDzZ-n>v+H%iUER^7H-+oeg#G)2)kQQy5y-=j^< zGDE{U+sL!k)VIsPtyar6SKBV%DyYxExzsLfl7(N3nOCh- zo?z==;}JW_HL}MuZgN2SeE-yW{%Q04Qf39F&kIPM6OcB?H)&cx>dch#m0@|ads-9M zuV`C2Gj!kTv==8+9~{ZjC8K^K@|xskoJ#aDd4r#k4|n$a#|)r`L>EyZmOGT)ix(u_QNOdCD5eRauEQ@7eENe~eG#O62UMC-2iUrbVr} zfBE*>a0ZcAC%XB*aCUm?ttt9A>qXvVRuQdE?r&^6S1ek1^X4@xYgvsc67Pg1BJ3e;yGF*(UEPk`*gXsg`W7AYEk5B_amky4!v8I847m&p*$mA2%&Zlxtof{* zg`B+gyu1~>0+j+1^%Aljva+qR@{RI}9g5Ov(nvcZvGqm-R8Rauk{aD8xXK2AYfI1V6A|1x1wpciCMR)$0|4H z*-nA$1N>L|#Z_6EhqC0Z;3-`v(6m!w(g~wgcY;>j2+mr}Y!<|nvy^SoRoBvG%$2J+ z%2#kUZxL?ZAU*MbO7S%1+J#yR&s(&wHkftTx__(ry4#-fkGpKS7rgFzz~a-gQ+Kg0 zJubQVy212K`V01$9(v-m`lQ|IH-Y=^`ks0jI(rY#<||r#xF3IM*-Fl;JA9_2T+1B$=lt9p@UV{1IRh( z>EaktaVt6D08`bj-4(BlTO; z&zhXrpRBD%mrmW)bu<){~ix7KVN@uMy|q7p9?k`S#nEDYR`;}m^GWB zHO*(X&BFE9qkOy^osT<2$BJrPxq0#4wOf+}#UzEN3&=~$vWlEKefH$3GkRJpS7feO zzfMb^nTxfea>vftpuIkHsL^ea!P@6{mdKI;Vst0Lep48~^|S literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/th.png b/htdocs/images/countries/th.png new file mode 100644 index 0000000000000000000000000000000000000000..5e15d0e26318254090e78c9acaabf1e625507bcc GIT binary patch literal 1043 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFH`Q3~X|vnc zX>D5cvHFsGT@4T0YwuJP>};&sw|v3lwuWtUr(amR{L%WAk5t8%sE9Atm0zVJzeHDI zsh;9;J;kMZN=prtmm8?8Fi=@)thUNZcbk>&dTafS_C{N+^;bKXuJf@!;%2qQ+kRhw z^I;F$O|CXe?9BS2{7%IMT?+Nu9UF8e)O%-A*u^lPEkT}ZV}lMv`ftlgxSbMtIy>Qd zTJ)K`q??K12lJ9|7N*@vjXoL~uqG?vR9W`jqV%f;sh7&K@04ZVNR8Q9oO!7-|5`)& zosPOk6@@!%%l36No|r!2T21+ysr_gAIuCAM`*z!gw-?TRI(hv0&Fep}U;TFH){hm- z&MsYiq9DKh)X66c7aU(O|JdeDHx3?nx@qI(Qzu_enX>lWxszwlo;Y*nczu1%&!1l& zKD=}7+QlhTCjS5b``52;@7}$7{`~QkD;IX}-tqnWml_q}YGvW0mhvZURgT)KT=dXC z<70X^+U2b@R^I+zsjvoZTbdf0`$m=DeQx2v-*l&39;3;H>^ zVO>V_%bu!Tg(=6XaxOHNe4X9(bZXnLB~!jEob>PCzdwKeeEat8)2B~QpFVx^J9z;Sz_Bv1uolDE4HLkFv@2at2n z)5S5Q;#P9P0VXak?N_&Etvcn^)#ZI!d-dx^Cr!!9pOKb3Jx_MN%)A*nbEU(=j+PS_ z7VP-&V#S6THx4|QP_bY_+veTf+nRQCY}vDF-qgj-tN|z5?p_TD^oj`bb3K0N;=L$& zjUx|_tvaTnrg(ZyX4dnR>=Xu(B;!CaQ4xVjftQT7nOsf{Was+$yQs3Ds;aX1H~WW= zzdrt8XkB)8hH3V*FDoaj`^_*(J@&@3xY0?M*K}*|Sy|iKzkBb-&V9S~#vW#d7q5*1 T7P)&|0Que1)z4*}Q$iB}W;&0} literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/tn.png b/htdocs/images/countries/tn.png new file mode 100644 index 0000000000000000000000000000000000000000..f05f1342769f31e70908c574c88dda3ab067c558 GIT binary patch literal 1041 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFKXd%V0R@Hw ziVXV|87f2>4k()t8)aD1FvNeYv^fDl6s3e)^C6^yix^Zm?6kc7FuD~S=+2a_0VX(oTkMgL`>)#tQ; z4{3qNGo!E72&n6SuyUwI^Nu>bulzlyZW!@U0F4WtZTnYb6}?`f$vU-f znbj-@Mg7!7zGoe;IQR1IoH?yc%F98~Hc&21@8F~(SGsbtnM*|@7fevm=eC}|qo!zA j``&%iX3a4%d(XhI_^0kE+ta@UK_TMl>gTe~DWM4f8{1AX literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/to.png b/htdocs/images/countries/to.png new file mode 100644 index 0000000000000000000000000000000000000000..b53e46f1afe262aba5a6a7a0844af71e26adf1f2 GIT binary patch literal 649 zcmV;40(Sk0P)K8Vb-H4bUA8&m9fM8x7JR5Xm7D)g%;#5faUQqE{PVHDs?O9CtUs3d3Q1o6< z_Fqx#T~P68UD0b}eoII8zq;MY$NJ>r#ti|+5Cg~;4agb|$tD`lD<9J_C&)1-kRuzd zGb`LfIEgJN&`Ch&QAoH;Lwz(a8g-OfA0$JyKnC={t9%?~t4&D0|_#LdP;8z^M2Ajl4Kkt@(3D`Q;^ppY`qMG`=R j{K7mPEDW?%uz3dnqM;>sG^aEs00000NkvXXu0mjfCgBt| literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/tp.png b/htdocs/images/countries/tp.png new file mode 100644 index 0000000000000000000000000000000000000000..f8b4dca6c48b06feb0776fc3406f6330db5fd46e GIT binary patch literal 1043 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFpKfl`UEffZ zmFs5fxM<#jHLF&;Iyhgwa!r-L%UK;(vf3}>bX?Bmyq4E(J+I3e z0k2IGfjcDp*2#wMR*c#&AF@R|>6m`nDbwt;7Fmbwimy18Uw5m%>DzF}v*Mh8s zcx~_gecyh5fBNDXLkR;z5d(7xGiwDaYZ)tN87D_N2S*wQZ!NDtoq$A>glw0rM1h22 zx1xNDymY3tQn9jPo}&INeT_;D(>bPEwOV>jdIoI<7Bei&CYqacnK-RjMJT1^BJ>vv0DGTo>s#)h~2GXvVILj4c^?d-JZ|xcckQug_mU zuU)_P)$3Q6uUuAbR59x_b?<@>@Oq~B`bToupl`q%GuU-N^fsS zKtOSRet&oOmQ9;BtY81{-@iY9{`~s&>*vp(-@bkO^y$;Pckf=kdiC__(C%M@7tWnKcjnBQQ>RV=BNrIOqX1V3m|9$043uL`@^*J&=wOxg0CEm` zx;TbZ+)7S3z~nV+#;PvUr$<Ztm>H&iGTifC RgX0v)*PgC^F6*2UngGKSUiSb1 literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/tr.png b/htdocs/images/countries/tr.png new file mode 100644 index 0000000000000000000000000000000000000000..0ecd06c99662602110314937b765fed83de71f0d GIT binary patch literal 1029 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFzhG*1*vk6X z?mZvBeS7r$*$D=Q<3Pm7aEyVWmVu#$f#C!r<8emDlg!K~n3<2Uu$*RPJ;lm;f|d0+ zE9)6{_7j|($2mFAadBPb<-Nemdy<#8gNy63fWS2okyBz~Hzg!)NJyNMkT@$LF+ou9 zn55(#S=rmNvJVs$?<*=^P>??_FF#9Ca*4F`BQ>=Xs;W=5wNI$4uTfNdrLX@|Uw^%_ z@)AYGGuqnQ)YNVm=8q2|RV%9UikZ8@bvr?9{x2h?rCJ?&yh z&KJ$i#|sM1S5@7eG2_OxX_pr-KDlq-+ZQi@Q2>mHQ9%C?aOHQ91=`A(9Bx(L}>`)=6HCDf2_`2jnQMp>09Q@Xq-b$Jiz@SZaiIAbVq#8Bv>xx_IuiK{lUw;dHv+sdDHQNQn{ z{n$_ck)Qs2bHxp|YL~qAUxt|OaM5`gZgtSp;INnBjS!2IekN~X>`wcey-#rZoZ@yT z+TmKH-RE?#+c8f21FgSg`aVhVe3azzJvZP>w*QNCpU*h~uQUBVzP2-XhC&TwCzEt>Otwg}qL??_-?Sx*Fe)cRL;J z_NyTBb#D0C^pLY@q08fgKlRm~Zz(@qTkvjn@54#0d#ds){XPC~SafIplyg(Nf9%=V zmy`Bp_ojPW)*O^zIHAII+Cbuph5YM4%S*mipJUzbM!9}S4fs``bGtVG$i&X~d$-=R zR$FPHICbL0;=;nz)YQ1RxWK?bKR-WTUtcdTFAon7CnqO6J39jd18r?>b#--FSy@R* zNg*L2US3{SR#s+aW?;+$<98I`34zd1DpeW z^;a%z%0DE+`RrYYv7{*c8)|jp3uv%pwTEkkOtPiyuTRBWEbyjX>t28j3$`FS-EKRgnDyGH& z6LkW@0Texoif{k{xp-1R6h%=`!#jB0TDMt7|3H61&-OmgetSQ??^BhO7;_AH28lo* zj>W}dANVuGKfy`J{AQ#)EqgSrR*}ip0As#R z>n6DsY8Z47TGbqQnW3HK*|tamEv3WEggwpUo50joy~$nF+QYG|2prpzx&1nEUqPF^ zkk?x`(vR0}rbp}UP4ToWN zk{SRatF2+g#jz~CSB*7UmiSX^O#P(9>FaXucFb;q?wziApV;mpiXf60qJa8x#VAz{ zSM(aIG}dnw8hE;WwvR(qW@O5m#P@{gSTV!Bbyr6xz z+eag8)>4=msq39wZ4zeUMbeiFLdTPY1xn^_b@6uyG!W9ZXhqPwGF?2T{Mu#m-Mju~ z{r&#eKR$49JRj{}2jK3-U=fu^!eafPkHg+hrp)2fb%8f1(OJm7y?d}|R`nw%^lKn( zE#V`k)QrtUW3GI=HGN>d%C)&9zaIWXk2ebPmfP-6yYNU<2oB$BvJ8a-%|xzaQjigh z!iAn}L|?Lg5_(RB<^s>21)>-q*mf3+IWii2y^fx;K?p*wqB5N5bpW7Y!!JJWOF11# zV_eXjleS>q$O^qG)YT~X;3e*g%^u(JRF literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/tw.png b/htdocs/images/countries/tw.png new file mode 100644 index 0000000000000000000000000000000000000000..2e82e66c8f9a0bd5ad2351ae364a009ba55f0a52 GIT binary patch literal 633 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcX*_=LCux&QzFKg7s`D&hvu8_hsd-nwp(-cDtXEwUUK%B`f!8Zh>tAqFa>I?kA+Ydhv3{+U>@I7TP=} zh9XvT`WM)!c&YK4ty#XYw`;kI9ddWaH~lR>g&jPIavDTCbbx8dhoNWs7km;1{9cTh59&W_qHvT z7IOOf^~)IshO>-}XBZjJF*BcGX1>76dWMztB0Kw8PR=V_T-SJc&++o!5D+*oBy?Lu zknZ+?Ei0|S2s1bhq#_?waf3}Ik6V+D7; z3YP;V7?Zr+T^Kr8Wj%nL<(@8%Ar-fh6Amz4+4?nP$yeW_kveZ<_8z|cxzVYuD@e@A zOKp*l*||7J%}P}VMOj@>N5fEM!8CRL|4-gLl36gJapTNov)1ioS-m^oCoR!YD!{`p zE;7u`(Rl`MNjbROF+Xth7FSk4R*Xo%3X>~muU%ry z3J6N!2++89S?-n60>_JqjSh}6@GtI|@J>*}T$8)uuE=2}`7SzDLb+LqhfS2{V>IyzRnxHP!C zx45}Ad3kksdbUN!EC>mil#;q8JbYSo^sL0h#VILEgF=_Nx_5*}t_lpE9TGM#A$fg5 z@;X2NUQU0-$VoXmS@v0TDpixsLwi#L+T%pRR5U}4g>0mi6AUC>loWlmyc@%u3w{0T zBGYFV6)vjIn^#e^xVCt4Er+3iQM|Qtm7jHnOX8I5q>0(N^ULka+~gJH)nX;1+I*}t zm3!8f2ImNO&+#j+QIL|7$j#y@&gWmgAfUZYp*)d&VwDmP7jsbrtFF4p+8KeJl*v(MATF{I*Fa>4@WwxiQAzA&+6R=?sLEp>TKLn9p&ovqc=ZFTwgADMLR*sV(~B?~4r z?p(UA+dm`DKRP(pt;SF~;KZ4z%eDq9_iSIh(@v>3GEz`uN$x}0IcG0izd1=V`oKaZ zJtmP)JRO>E-oO9U>zx`jIYeBTg{$@Xw(o{tT3p39u0G}2$@Q7B^;A@~WYyxJh$%~+ zrmD33sBCarcb7+T;?Ff)b7D3r|tZy#0d%_Pgg&ebxsLQ097UT ANB{r; literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/ua.png b/htdocs/images/countries/ua.png new file mode 100644 index 0000000000000000000000000000000000000000..db85d97e7382372366f5e5ed666876e46e0e0cf4 GIT binary patch literal 1041 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFcUXPKarGIe z)n{DRo^#u9(QW+&*EMH6)}Hm=e8q3uHShK30(RU8+I8D^!+Ddk?udQ&LbhD8uAdTf z@L|HyCrKw>L~Xy~(lIyV%xkZS%To{BDZKotVex%OCHEeYJ9bw2;tiu? zXHD)ubJ=&q@x(dzH=n|8-4D9^IO5~?q&FXv-hR%1^Re{IF^01z7|$GMJa?S=%rWK* zr&!M%W4(Bq{p@khE9bbbo##DwlJ~|Xf%7MYZeJC-cT?ihS&4_YWuM$rymDUt#Ur)l zi=-g4Z~8Ed-QmI(!%IDP*5-J2Kh9XxsT>fzhR zFY{`Mh)YWfy^t3Wk&zOV6&96a6PabaQ%BoSQF;BA;zwsZ@9Oe8EWCNu^5nLMw6XObm?*RRI!i}-FVdQ&MBb@0QNhZpa1{> literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/ug.png b/htdocs/images/countries/ug.png new file mode 100644 index 0000000000000000000000000000000000000000..5c87b921b79ec50e75223ac536704a22b497025f GIT binary patch literal 1043 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFKR##P-iGFr z2TrVAzINNDZ98`F(=pKT3-%2P545(o^78Za^z}&1NMYt+!8vFImRCbvygo^}JiR3+>t?QduRqexv-g8-`1ksU1J5f8?0{`i;7` z@7e6!ZG7^y-GYTikDhqlzU%Y!dEl+P0oQH>+`1ii>vrmyGYpHDFtD&NFflQlJ;QkB z4C93htY^-!Ub(`xbQ$NlbG$ch2y}OI-Mc4o>5{~gCyG0F$-aKAedC7uh7F2)_Gohuxn)Zcm>&{r~U#?w#kGHy&57IsN+=@a>!5@85w(k2&7H z*15S^YgR7aJ173a z+|(m!>WhOEujT2#tFyXYY4@YY>rJQ6_X&Y-x&zKvxgB90kX&&w3l;G)}9Tboq z99W(hUz?Gp!Of|`%N^t7)KyXfj9Fm(jsiR(uuMndDo~m+$=lt9p@UV{1IRh(>Eakt zaVt6D08>wI@}x<^j~6NRC@C#|oGjen^r%ScSC!(YX>F4(@p&;W+~uGs{e440y}EX= zFn6@O{`~~|1p#i3-gRl2RasGyp<#Y;d1e7CcJE)mckR^9si}`z&fS~0j&H$*H8X?N z&(1r1?wC#fyDyTLm-(=9ef-G9_2F|j*Yb{nqK^gKg$%7FQ&LrqEJ+a!G2OcL%GD5& zMkl$lXKZQLzOB30=x8@DPw$+=!mdY$7ESu}s%_b`W50IYn&p*qkCB1#yWwgVS=CP< Ok9)fMxvXk?Dmb@g7Xs=L>M?vWN)|mlvGlYOwbXm5Spd0X4I!lDyt>5B`ib}U_U zf5rL-3EAsJL&6l zIxz5AeEike*iQuo=aZ5i<>r2`uKrY2b)%r*eSQ7e{QPGP4Y#YRe)ROb?d-f(U46Q& z^v8q=hl>i&RaSnQFyTUN?c?t5@3Urpnm&DZY3bdbp55i;#~bQD%$|LvyX$CE)2q32 zek@ydrnB>CYs=y0=9hElzL-1rOn3K}<;#z>x1H(j{km$^wW(9@&zbXM!-n^(R$ZSx z>+zB$XQoa$K5^o)i4zx;mY$kAbxnQ!$IY9cu3B|r&g>(TChh3#ygYB-**UX6?cDKW z@7@<1H-6o_=h6Cg_t&iXcHqFrJ$v5l-u?Z=@n5G;1LGGM%cB5m2xu}qEd)w1CV9KN zFm$lWdH^{GJzX3_DsCkw9ANsQyJpLol2G-s((isVZS(&zEts%#>DrZ>rQ!<`0z5KY zLULpRJZ_(KJn!LtbpM)7I~UjgIwR?zm~HKzEX})d!-o?yTBh_|Nm(#qVdvgujk}7f z{1PjJv!lIb15VsMd->|&R(mTuO>2F7b8TS_kq6ITKYluQ#7#5LLiRpp~ zNolE%pF9+O`b_Hq0~e=vx3`za$rGHK8eJMExlb{*T1l^3Ep=PnXSQ+qwJV;Je^+g& aWM|-rYYv7{(!MYtH)6Ty2>j%Ccq4t^8E0mQE)qHP@WeR<3ewX|diP{?x_FOc!i9m=TWKpuy!WasLzB^Y9My$R=-qnloB=a)8_dSD) zn0}~qGv!T^+ICqRfHn8PPiWoE-7+z{${fIiT8{|vG61#0xb~?R?&hdj1E^3jtv0%O z0=-BzGda7#{;J08eh{(CVH9_rFVE7H*=+kJ-dwZLN^(N}NsSDkSLV=4a#@{a zT`k1{r`$cKnKO^|Hzc-DPmZ*n-^L!B`1u>AGVjF8fcf3L@D`*|nM@`cjTUY;-0y$= z;{%8HylqQ`clQZfXM$1VRI%4ew7Nu(v zEJPFqS_p|hrr96u>bO{;Q3>$PgZLNCE9ZxtPg#z&!ldbYBPCI9D7;t(qqaJQDvqao zjB&Y^PPw_Whu9yYqLD;WKj|tL)$+y@8abyEcSnkjYl?se_gzq)Io^_YLKRVqWGITM z)Rh$_w+M-gE23AY+$65#U;dqu%qcp0DggnHTsc~B>&&A|`P7Q!JLxgR%%rM^b|S%B Wa2DvR$=mz)aB|wU)V`G4HGcr5;n(f} literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/va.png b/htdocs/images/countries/va.png new file mode 100644 index 0000000000000000000000000000000000000000..0fc5b5fe82cbf8195013621fc5180a83a5f3cf85 GIT binary patch literal 1042 zcmeHE>rYZ~0KG;mWiiv7y{2W4`IyUPTO-|?I!s+=tTdyQbEVmIxwe|sGMV<$X+Elz zMdTwLDrrQ{1g}7aTn9fcmmA=nPV*Y5fRa*CGLYzB=yPW~=j?nqU(TsvWu?(+TWJsk z(KFJS$9*2`<9dIJPfvlcdI+LGtjz3GU-Wvt{aoH)Uq7zHd%An&awUf8XJ$-V92dQN z*CP;oHIsLq6b(uRm_hlpl`{Z$l;3C9K0VRWU3%lzdC~i3rRuE`kt@|L<5RF2efHV# zUJb+=jhrCVZugQ-H)^wyBuU^nX16aI40=r4q*reTFvKZ?IM*OlO3@4l7?t$eN*aJS zkh(D5!!1+VNPJ|E{YxC57eN{r2%M-KN_5$eEzhz%%LTs|3xQe+)UuyH=Dn-m!5{?0 z5a%kSk@x|zA1a}MK?)F4uwg2YP<7IE8cBd&PD6+2C`>1m8#HjBb~soo4W2+kFxf`U z@Fx7j=Ev1R#*u9%U4;JAcD-T;fkaM%xOrl~s56GtF-V*-^d{ahlQK7!G&h#KFqytQ z!_p&%opZU)`COMR&oaUG*bBT%7k^m`z01X3NAcUPD&7mOWquAz`%e|DCG0`zWaP9{>Q&9P*W3X^fmp?9Z6$C)zq+bUyx@ole4dnpU;=C z=|5W+TYKf<(S@6mgz@LLlFF3RP0@G7mVIQ|ByX{hUiTm=!lQuQbqo&WU|GN+zl!jj z)<*Wpbj-Fw(*Hd{px5!DAeuQ~&cUhe7@^z~R;)`rA4ER{KFby+!Gmx>E5 uTn06&qfOBLs_0^|nIPJYiIpWW2fjg2dPUq62rAwCcan_MEM{Lye$^kEC!mx7 literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/ve.png b/htdocs/images/countries/ve.png new file mode 100644 index 0000000000000000000000000000000000000000..0a90e4733a304618e8c9b7457afdf835420d1859 GIT binary patch literal 1043 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFKWyl{c+#b~ ztZP{%chd^5aY!x{R+=KFI#o)0skG)y8SUAM1}jvIml(Mm(X-p2Y0~HzaM;oRfR+1d z*N_7qp_@XJPbcQz2}?d4op~lY{YY@!nzF{r%BCw43vV7fA$;Zx!?|JNPUAxA6yEAp2vE53WD|LK$IxpVsWADBFR zXz}Zp)1NUtncD!^(P=lk*xc?+pQgOA-rBg@X*5Is+s8}6O&&~PJi6o zo;o?ba&!Cd@Bc3#;G3V{&wzlqIH2wSfl)jPaD_kz$EG(xImRS!cNc~ZR#^`q=b)#H zV@SoVF3p6n}rTHJ1=@P$++lKgVV>WTc5VB zG@K~t=$UzwRrRQYV!C~Oym_>Cwl%wYxxaiq|AGmVcCOsh)3$e8Uw32E#;%2O0VfWf z2|cZLASm{-;f2#jJmSSQmS`!etLUieYAdO&R9m-3gG)pxB`G;EE%o_>XTlGjKYjR! zh08ZHKQANe^&Erbb9ZK5R{Q#$p>8!nbV-GV!{RyMyP033( PgM97j>gTe~DWM4fPtHn3 literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/vg.png b/htdocs/images/countries/vg.png new file mode 100644 index 0000000000000000000000000000000000000000..1ff7ca119ffbf7a822ff05d53171546b6ec93ffb GIT binary patch literal 1043 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFzq4S`-jL`y zfnisRE3VZvc7;csShixhiS3=@niCoM>yt9C*EGLazGg#H+X`#<0(Je{^&Pu9CY)Qp zCDqAmMQwYEi_g}X3+884%uOtslV7)M?uN5lj!v!WO^r(0v}og=O(*n~BPMojhz_fD zu*t6|@6a(ww{f5JfTcGPursr60;8JB3G}+9n(J5k;oB)w2b(@`bc> zMD&W~%}bR`)Ac<%4O}WsJR23M&*!YnS`oi2HRp

1b@MzhPNv&yI5c<^e`t}B;rJ)U;x z?d-*?BNjfY*!g+sxvvZN-PnEWN7IxgJI_7Zd;CJq@*8DqZl_M!ojv<-``%amOSfNs z_HFZ_^G{yAPo28EeC@^kXRaPUb^6rB%cswr*|d4{wo4cD8|s&y+J5==^+zwBKK=M| z)1hsvuWVAAWbC^vkYPH5*km#JK7}h+uk^0(E?g16;^f?8XO7I;-PFA$XZeAWeP?Dp zetBu-x@i+u=*(YdyKQg#v-h13pG|rDaqaYZ!t^X95`k^BX zEp38VZkm4h67c%1@2fZddk;7qKIXT2jobAbQLo>oJbjT;Qfl?+ap|kKHTNHszkbto zn|TUehw)xL01|La$Wckk^!ee`+!#N+PWxPu4V zs;W{RK0N&O>#b|oPJaCO^4z)OA3wgGGiT=AyLY~RidnI|xT-Q_-+HaR8yz>Uh<*3= z@w2PFmoA>&H_N5FtMkf=#*J~3mlFI>g#~~6_U+@xj}IR{ym8~kwQJX|T)A@T(xnR* zE}TDq{@l59XV0EJbLPycQ>Ts}KYrxMk^TGk@7c3w=gyrQHf&hFd^s?3fl)jPaD~7D zp8L)~ImRS!cNc~ZR#^`q=b)#HV@SoVuM??kZLLUK~1=m8tcS^PI0$+H`sE;;GB?qp=D`LpL&C2L&PBnL%S z&fw_(IbmgHeaj4(1ruEtOqeuf?o{6>_2BaG?u|3%tg#C4aJ_Kv(wV)DGnXz7^N$Pm zmejZseK<4k;j~LPp1pj##5VO>%z}XXOJ1t=@ts>($N5NVt?~0S%v_QFv+YWo76yi8 jwf4N~xw-4}#!7aE-`|Wp*g8J#2l?95)z4*}Q$iB}HYKov literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/vn.png b/htdocs/images/countries/vn.png new file mode 100644 index 0000000000000000000000000000000000000000..31af3d543ee3d420db534b3efc4d8e70f3a41ddb GIT binary patch literal 1038 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFzhG*1*vk4> zdd7uoyf^Pj+)nPcSnd10r_j)2ytg zSXoc7vK|MLoSetGIL~o$UEt+C$;;cp#dTRg;FOTi4GD>J5)x-6Bqj(7-jS8PEi3y# zQSpL;{CRo#^9l;HBqbM1OJ7!3f2ys$Mp5ylzWzF8VPy2f&F#CJ z+apJZ+xB*k933AzIsNqVI&5wI%h&g*o7*c-&lesZzx@4w1praNJ0G8qettg!1HT6b zehCQp78v+8AmDq;zhB3+8-G!lpRn`N@+2iTr7*cU7IpF})moIxi-+J|E?wL}bw|5U;@@{ncrI)#u z_vXB;Rc>bM7&VWEIwf+uZV8BgFzb zcCNLH^Xr&D+1nvt*A^RfMvW_%CcI2lJ$?ApIo;5p&;uguB3VpQDH#gKjww!xkDVbU z%_*{qv(VsL;KQjC9tP{3_Uhqd<2q^`{bH8p$@X*&ttTojt-qLCZFEX|a_%_jX?gT@ eb9_1YOqOAqi*7;Ukpudmu=8~Fb6Mw<&;$VDeHhXJ literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/ws.png b/htdocs/images/countries/ws.png new file mode 100644 index 0000000000000000000000000000000000000000..654b8420e391c68e142439e0da4ad6e794ca5463 GIT binary patch literal 1027 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFza=Yo!PIO! z1K$ot{vE8sd)P(y^2#0+kh|#U_be{!S!&^C2Ei@NBAYoScPi*hvTo#I+{w?nTbOf~ zlEgt(>4Q#IyAvay7iE1+i@n6fu$Pl@Pj%HN28LP&h8kw(GrYWKxwtyy?gTft%VA+Jyu5a#r2KIASeKFYH#75VX6EPG+TX>+Ps__6)zlsq5akGxKRy)>Evk$5~m=u(O}wuTxgus-||sK!1mZ##>XRe$w6yl>=p5G5JD{uk-pcBvk>N1| zgS!?M=S)ma8ykPNv%6qs`qjzls+H9bH@EL@Zny329y&Sw^z!=U>-*ZnB*B&AD+~!t~YgLY?_6+Ry8<%lDftA>)0tJoo(+JFIGY%6^t1PP<>Z%xKzW>CWOS`xhOqjK7-p-jTn|OAYS44T{mI?-V!~{8c`9wrbFxJ?( zVbwAVZjB>{&#E3cfBN`A7NZq&ESWW~gor&%On&={+hoN;C3{;*jVlt*Q}bWGVK&sT zHWkyD^74Jk(-)FVh8n7NTpA*;k}{vmahPeCD{HFp%r0lhxTO1o)yJv}6nLJlelF{r G5}E+2sQB&x literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/ye.png b/htdocs/images/countries/ye.png new file mode 100644 index 0000000000000000000000000000000000000000..4c547ccc92f7be42b12f4f5cfe6ec302b79e3531 GIT binary patch literal 1041 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFzk22B@ngr8 zl$Ebsy?XG_A$bM)+Pd1N<|Z>U)7;#g=g*&=J$vTIWjSmD`zfJY} zo)hq{ApB`g$fNAwkEJm`nzA00Cw*zj`}_IhpHCk?K7ab}>*tRzp6!=qs1jkQ5Mnr} zz$kMTUCWmTFO82(tjW0wAsz*PK4u^4FC5T0bh$EKa|A1 zt4h6aVq#)oV4$zBucxP{rKP2zp`oa#C@U)~EiEk} zAt4|jz{|_a$;rve%F4{l42&aSOpOAnhrpvf&rN`aGA4PuyD)UH%6b4f`#oJ8Ln>}1 zCmdkvXlG0dmsXb}OHxEb8=cg``102EZA)`o_Uu~OH@|ZZiqfjNvb>g_+=bqf zm7?Olr3)skZ)n_SzQ29J?&Z__*UeLu59pX_sH3N9{zp(T&X-=9uHEPxl*4_3k?mQ_Uw58SWP+)nw`njxg HN@xNAc4R~g literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/yu.png b/htdocs/images/countries/yu.png new file mode 100644 index 0000000000000000000000000000000000000000..9947f62dce77cf45cdcccd9d66464376dd59192e GIT binary patch literal 1042 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzFzk22B@ngsD zJo>a`&HmkouW#LR_R5|2XD&ZsP_JT;@L|!aWznkP)T`q$YT;3dkae1*8#vz~d7Wdz z690l7-dStCGFJx_Yz;2nk=k@%?y}vBRv%cq?NmqKoLvVmUcLM7%;m=nnpF&vKFnG* zth)8Ay0yF}t^6iU0u~(-wjF|6@lp=`iXPMCow_BBGc>&?>4z*djasJdT4ND4&naz# zk#CDz_GYW_e*eN90mVDR%eKYU?2aniklMH>tNrlFOHViNI&tOd)#uNj-MDu3z`ngp zG#Qp^GcPmXTxZI=(?xcJi+s1a^fU+M6Jh!b-L=;E8*B|Ty_)WHGTrS?k^l9=fYq_C zXHK5@_5Ito&!67Ddinar^Ow(_E>dAwrpdZQlXZiMz#2=5JuZr?928eMDNnLeT<@ka z&q?ESnCS{ny`4cO8+;8n1(@s)v$&q_b|l{Ec(Uv5{D3RjehWhE_NRGYEs5Bg;&Zex z;(l}bwTAQu?YY;Qvo4)Gd-mjsGbfIpK7Q=qub+2s-nf4G^6wu%etiG_@87>afByXX z_3P))pWnWH`}FD4yLaziy?XWZ>C-1qo;-Z`@WzcB*REZ=bm`KC3m49v0~&Pp%$YN% zPMrcqA}}gP0jVM2z4V+HP!D60x4R2N2dk_HkaNJ(#WAGfR&v4trYTdu>b_a)yXDH1 z5Yy7$Giw{1?%YZ%GgGRniP3u1)V6Gzkb@#)a(;VweoS0jw^&>I&NWL-sxP-rcIUrbvLK+i zBsjM=);HNF#o1+w_YUoV6}wcdRV{T_FW9nZ)uufkFe&*; zM%KN8qSuX0KPFE4KWE;%$y0yNop-jp>f4p8)>hX0j{V!d?~_y9_khe_2^GIf+TKl> zdw$Q+zl!E-HSBljxg9p~J?|9r&_CywU&g1#uASXejx1VpfAii?(xyw4?AB|!?Kbc| zW)^bME%jMI{?`M?ZeO|ayrQ@1%*{)!v->A4pEYCE{B;MnZalnW(YBQywIFp-e8l~uG;l(&+X)Rk0sRM+>^Hw`p3@i8&-Ffwp8a7%J?igEHt z@i6l?bBb~b$O`aF_j8MJ^H28=NDqiBi%YFdO{q-Txpya{EQ64~psba&jJ1TZpT2K~ zr(?Jkk2YgwS>m*1z0;TVHBYMSp50i}RopwfrKmo$x}#|4{w)QKk@{||4q-yJAq?7< z3=>l+)0(w^&TOfiq5k#z7vDKXxyN)C1T0N2aN1KSWFGv!k^K*DbvR3K(@_aYH zI_vPEQ^(F7JjyBZDl31D*Y^#+W*0A-UNJYg#LV^a-0O_B+M5dszH{>QcJ=Wvah;95 zaPv|?;`3*+0%FqQ!h%d9v+m!GnVkCg)zpdeCr3vFOaYp_T7SEFx!>8#PlQ7!h)wrHL*IuU8XIpORioG37s-kWMd^eL-0SNjsr}46+mA0 MboFyt=akR{0B%Aqw*UYD literal 0 HcmV?d00001 diff --git a/htdocs/images/countries/zw.png b/htdocs/images/countries/zw.png new file mode 100644 index 0000000000000000000000000000000000000000..7e69c9e7815cb4c447de09047067031c8bc29dab GIT binary patch literal 1043 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3-oL&dByLFfcO&_=LCux&QzF-zTH6MpDj4 zOZ(A*Lq`kBPdD}KUbkUq$HXO5roTCG?)Q(M=B8%1uHWkE>D|6-&&hM=JG;C0A3L0q zlPc{bY8WS}SI8PY(==+5MfvLRj-6RrxeR*wtd`XRcGVJ|or*cj-6GnoOV$PyO>!)o z&0M>fw`;v@X0!CHefq_H%C$4K+7=u1tubAB+G*hdw~d$l*PRPEa(s93bcP2n!dI8kROkM4$M66BKm80?z24!=uekk(%ieuR zy>VUO$z#P0>lF9w*7)?n^!PEoOBYT4{C0c##OdGPfNx*?R;-xt{{6cPr&v!NU^ucb z{_TtPM|Nl4xm}6&?&d$Dui|e9@$bJb4MOM~(YHDY-wO?CVt zuU=k80s^mme7*z*KKAv!;_3MyFwjX+@k~i^h^eW+iAk!PTbz?qUO+&WpP!+=zMQPA zi<6U~fx*{Lp8^8{0{s2m-P|5Nd{|#!Z*FeR%gYOlVqip%0?ZIN{o1M@D9V`R?e4$8TR4xHwl!tX{P;`<0}`tJkkGvNIDt Z^D(T|H~N_WUh_Q2zn-psF6*2UngBd(Whwvw literal 0 HcmV?d00001 diff --git a/htdocs/images/default/add.png b/htdocs/images/default/add.png new file mode 100644 index 0000000000000000000000000000000000000000..7c04bad6a1f88c88918c37781b8d1378a054216b GIT binary patch literal 528 zcmV+r0`L8aP)ct=6WrA)4!Hdj;H&6Z};-QC94_&1uZPunWrtz?@GxW!N;e{6--Ve|B`SM6W z#Ns1y!I6L{ismyUNxBd+1+?4km|)vB-ENn3I=vKcDZFn9ypq za9x*PuSd07UFc%!U_2hj1k17rf`D?l{I83daHoJU3}b*op#Z?co!4w$&9j!a_|g)y zTt0(orMP+LI-0JMGIcVx$?mNhKqN0(&y{QIXu8UZn!qrU04TDItVpQ3%({Jfc?O1I zpePEJ8`BWk+O7cb?)fKDrhX1+G#b?F^%%hIcxbxH=MP^|WSOn)3Lp2s;17ljya2yH zItLVs#hDR~f4Eo~gFiuttekGm9}F4!A)|iCiPv9T79oV$Y&N~8yZhuf*N`Vk1*3@H zen`*hQ#-hKT9+j~i2&~3enIw9j-;V6I2rP@bIjh+UP)4pXFCHvZDpV>$L9qlRL?K1g)MO(yP2)ywlQecW|6H^0ZFb-8 zo9UseX#L+?2ZmvIGr#X|zB9k?_rd?YiDz8b1gr$!20j2BAP2k(c+U$eP19W4-rl~u zv9a-}ZQB{sH1m7+?)7_mdIHyV1JCpPiHV76$8pX+_mM)O(81>B=HkA6`-1c5&#Pjw zSW!v^T5Iijp6=`G)9G|t&&hG7^;DM_c( z2qCCcDtMk3D5aiCaVVKgZl9Z*JEfGW357x-fMhaxZ$W*1J?-u796EG}SS-f;{5-i_ z4k@Ju@=v|wEnBuM9yxNv)>+adLYZs?apAPQsHv zZLFGF28V{4J=a~me*JpGaU3x+GSXU8Q}bnOYb)2TUDNjfGMP-pb=}^9fq|*%>FIY8 ziGPLf!9+%C*g9k~c)A)Xw3uk)RSQqE?$PhpbSg6($ z_W>vau%(n|PMkOqcO0kAG)<(G4+K_9aqir?#jdWd8{^~SGaVfru|jrMhBQpf&0rcb zU(q@RgsZGPP=La=?H9x0@K7`wz1h^%l>PqLG51O;rElN9t&7E?zI5qQ(9qD30d`3# zx3smjy}RelZ9O~JC-kQJl{zeqf`GSxRX`)K45$Unf0w!i^hFFa*|DZA5?{H3O|NZM zLjwbgH+~*GDq;9`#rJbTx%A=A-TQw{T}f1wVrX^>L&)!Z6?_9^t8^8Cf_Q{}55Cd7 zZi6j^sPoI7p;VnMq;9h8Akf+?DRpO2E6?gothsvSm#AAVQC0z0=d)T0@rC+_s^5V* zARl^2s}YMEHmn=mzWMdd;X<)~axf(qGFgI3B_x%yOheX1q(I9MrJ#b+no6K(jV@DD zh5XCD4i@e!WokM-=+cs)ZH-ze-OY zD2eCrZdnDZ0qTHAHJ}Fs)$ghbP^ykf{Kp@K`zz6?&Se$oZr1>R126Y5vM0>T^Z)<= M07*qoM6N<$f{EdFd;kCd literal 0 HcmV?d00001 diff --git a/htdocs/images/default/bug-big.png b/htdocs/images/default/bug-big.png new file mode 100644 index 0000000000000000000000000000000000000000..0758a85529421df9045a6d866f7a2a8b3bab744b GIT binary patch literal 928 zcmV;R17G}!P)>=r{{DUqGC4Wf-rnxFAt0r6m$*mPAnrc5aHoFZPXX!tIW#Fkh-@}1 zgcunaIdE;Q)w-{*uc@iYd$HDLGMSl~nJ}5cMx2Ab0?2uvK5<5XZ4IbS9y%Yc`wJT07%ZDz#lGybn3JqSRL~ z0UMA74b4&(;i^(TLHHouW@2KZv$OMExB)%z3;YY;Loal|6x@ch@X6Si?-HL4j@D=l zeuOzN@HzCtAbbO5cnohq+|yIjbjFy_Ph%X%fYJIiybU2dgwNm{+<-yYgcaC>^-^hI zU_eS41c9}7c6JumZ^`EVsK0+4wqYKC3+K=OaORAut5fhdT!DJ9)^2Za*F-0SAOIR0 z8@s!^fxX>b;4yp%z}&riy}2BhE=kyhKVc7q5G^e&9UUE+OvblfsFVuBuu`cws9wq? zSc40vPR(7r_U6`>U0-Ks2awfe0uWa2VGs(+I&9m+vkw8USUYBzkBrPwS0PwY4>8<_XtR z?QyfF^}_so6h-NDI*OvUwl-_+^wd-oMXzJg!&ysCO%38{Fr7}nPRAG{+`UUx;q}6|pRv$CJeep*C0000;M1%g<09=OqmiK5U_xi z%~(e#hK2QymewaGmNyR`yzukcvT0LGcFv!+mOuagyx6hhPg=^-iV6FG+8IlN{DK)A zp4~_Tagw~{XE)7O>#GCL0&ySDp}Eqj1M zF`h1tAr*6K{XO{(IB-ZQ1zmdj|9FI$D^$*mcfRH4m;Ud_tQ{ zWfmlE_E!x~nG*kHC2ymRj@w6p4ZdsztlSmz)||R9?dy&c?r+Zg`S(%Gs_aB9;}V;{ S8oPk@FnGH9xvXxp#diF-0gO0wOY#8YPCu(m;08N&*uTGut5+6l*{Fh zwn89;KuU>W7~xpgbw;BRj^m)~dg%B2eO%WKYlIM_(`f)}1&^j_;l$-;pS?|W3xA>5 z;-%N?0T2WMQpztQ+7{CgQKeE*aQMEDWmyW2!C*itl~U^3?KYn0DRqfNVinQywlz(Q z#1ZAKAd*sscsAj%E7u&|-l$%-zys&eh-$T(l7#VijN>>8j`+nH?&XQHNT+m9{OV4r zvu%47(Yhq8!?yNB?Sjbn{m8`F*#eYQL{HfQkBvq&qI$iqBw;ull1wHQY@JRA&+`-< z&1REKCZo(XO>;A%r~|ZX+7v|F`0k?^Fau73<2kaQ(hD$KTsX!7e%mwP_3z)w@3TO; UdX3#eDgXcg07*qoM6N<$f@_Q1TL1t6 literal 0 HcmV?d00001 diff --git a/htdocs/images/default/catalog.png b/htdocs/images/default/catalog.png new file mode 100644 index 0000000000000000000000000000000000000000..907d939ad048efcc4ab31795444bccea409d6ac3 GIT binary patch literal 1302 zcmV+x1?l>UP)4pXFCHvZDpV>$L9qlRL?K1g)MO(yP2)ywlQecW|6H^0ZFb-8 zo9UseX#L+?2ZmvIGr#X|zB9k?_rd?YiDz8b1gr$!20j2BAP2k(c+U$eP19W4-rl~u zv9a-}ZQB{sH1m7+?)7_mdIHyV1JCpPiHV76$8pX+_mM)O(81>B=HkA6`-1c5&#Pjw zSW!v^T5Iijp6=`G)9G|t&&hG7^;DM_c( z2qCCcDtMk3D5aiCaVVKgZl9Z*JEfGW357x-fMhaxZ$W*1J?-u796EG}SS-f;{5-i_ z4k@Ju@=v|wEnBuM9yxNv)>+adLYZs?apAPQsHv zZLFGF28V{4J=a~me*JpGaU3x+GSXU8Q}bnOYb)2TUDNjfGMP-pb=}^9fq|*%>FIY8 ziGPLf!9+%C*g9k~c)A)Xw3uk)RSQqE?$PhpbSg6($ z_W>vau%(n|PMkOqcO0kAG)<(G4+K_9aqir?#jdWd8{^~SGaVfru|jrMhBQpf&0rcb zU(q@RgsZGPP=La=?H9x0@K7`wz1h^%l>PqLG51O;rElN9t&7E?zI5qQ(9qD30d`3# zx3smjy}RelZ9O~JC-kQJl{zeqf`GSxRX`)K45$Unf0w!i^hFFa*|DZA5?{H3O|NZM zLjwbgH+~*GDq;9`#rJbTx%A=A-TQw{T}f1wVrX^>L&)!Z6?_9^t8^8Cf_Q{}55Cd7 zZi6j^sPoI7p;VnMq;9h8Akf+?DRpO2E6?gothsvSm#AAVQC0z0=d)T0@rC+_s^5V* zARl^2s}YMEHmn=mzWMdd;X<)~axf(qGFgI3B_x%yOheX1q(I9MrJ#b+no6K(jV@DD zh5XCD4i@e!WokM-=+cs)ZH-ze-OY zD2eCrZdnDZ0qTHAHJ}Fs)$ghbP^ykf{Kp@K`zz6?&Se$oZr1>R126Y5vM0>T^Z)<= M07*qoM6N<$f{EdFd;kCd literal 0 HcmV?d00001 diff --git a/htdocs/images/default/children.png b/htdocs/images/default/children.png new file mode 100644 index 0000000000000000000000000000000000000000..6fdc884244c2fc8853003865a8ca6e8e81b5750d GIT binary patch literal 342 zcmV-c0jd6pP)L+c(U z#T3T}XVye(K*0u35u#dv^!o$Z*N<}~Yd}B>ECwtL9|9Yxl)|bATn{1wBJu`=uI6W$ zK|xh*h?dtP`|Ul{H#V`R)?t{zV$iv~SO`YR8?Mh^O1|G;pu?>e?jLTE7decWQo7A- z>wua&N6?R5FdKvvRhnHT(rKfOVf>8DWR+$gWVg93p40Y+_yn}7(B)m6vL0$APx#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FZT01FZU(%pXi00007bV*G`2iOb@ z2r(b{**&BH00I_CL_t(I%axI_OB-Pr#(&t0NWnqDrOO2eH*bkkmm-8rUHTt%=n&}Q z;3C*n{{aUV!9he3>aL5+Wyu!O+q60LJQ8Z)YA)vD-S>34NP}rhA9#lM{a$|W!}r3t z)`2>Z*VA_l}bf9Xz_1=`u6s=q9~FvM#dOrS*A2i z)#-G!wzf8cywEFP-Eo|cl}ZKQ_whUr&-0j{pJ#Sfqquk13LNyR9Tilq88dosQBpmGApHIy%zz z^|gk>p@JY#{;^}40+56x00x5r&1RFkyE_&Z7I0mc(aa=G0ga1`i)YB(+#Hr=kt7LG z6g~Gn&jV;of_yEP%L;-(aU84P?<^L=0t9>k>|(L_P%IXEKp%*Jw_||Y+gsh-+&ugI{Core zuz?@dYV~PlW#utX(+6w|z;#`cWcHa1>QPfr(Wwc6w8{d2x) wl0W^%v~v%t)#{UN+fP7`|I`Q)0vYh`7kxx({SNCR3jhEB07*qoM6N<$f_KU=cK`qY literal 0 HcmV?d00001 diff --git a/htdocs/images/default/country.png b/htdocs/images/default/country.png new file mode 100644 index 0000000000000000000000000000000000000000..7640da3a463dff20a3023b866374eb01475ef018 GIT binary patch literal 707 zcmV;!0zCbRP)UHRJX6Pk=*48fo?kC#-L=iL^ez(?v>jOiywj_z4xe5Y;S`BKo+=rS8 z#xE`caPHw#04f!an`JN>X<$H>8RFQxSF(hxR$*lY!Y~(1b3p-I2l(^k0pN3bJ?Qr# zjy1*@k_4;;6_rrsDl9Mi#L1*EuKb7D1kks=pw_Un0|y6Sj3rIITNMey@C-zCD3`t1 zXjDKBkE*Y(t^zO~dogP*)@GzBgtCNEO9Vj!)LEZ29Qt((dG>L0^fdK&kYTMR2n9-& z34-$=s^FaOI2`)qBT;aeqqkbS(}po|GN8Y|gp}1ORSLU37z|)Cq3ce5{Z9KxTwUZa pN53|;sPfqyJ1>g(M63Tr`~`0e5lx=!z@`8I002ovPDHLkV1n}tIR5|u literal 0 HcmV?d00001 diff --git a/htdocs/images/default/create.png b/htdocs/images/default/create.png new file mode 100644 index 0000000000000000000000000000000000000000..458c7304b98342f88215e5ccd0f30b12fea2b985 GIT binary patch literal 700 zcmV;t0z>_YP)`C>4?IXf6hSeiXrVT#6+*NTNhgYh zf{ivRYL!OBqYymM7?%X&6%E8S8#eCd-|N5s@3Y9Ek&SOL%{$M`Ff+h^ z=~Li_2d3z#jrSp_cB&-d6$abu!k+IP*TTvkH7Hq<;R8V}6XVVBrVl}SV2sejiYYhu zv{g^+{rNXcV|Ut8OBJiHQ4>cQ2PY^JBmfx_Bmg1^C01eat^J5?xr$_0g&8d)06+kc zx!1lviQMIw;qN9U07;ONKupf1KoS8g0vL%&n0L_s@4mZw2d-r2v2!IsF%%RYFKtMUyGeDJG=m>QPP(u-`qd7pn@`9 zN!5H`Ua5*Od!*-CFlTH&@w)oz)~;)?5k^$!LIAB*c+(6(IR7MdzHWgAZl)W!DEC@{ i?$|PZao_1j^YCwW_X9iEQV`7m0000{XE)7O>#GAj#{7}L9VcR=bMdb&7mhhEH%g7>!R&t^By@nXt2 zQ?txWVxH3~rLM(JON5vhJePi`_2@|Yrn+TOfvtGtEXV65GJWhnF1fG2eYj|ANcX=- zJvB3@WnO$Co!UE1KzqUmRu{GDE#FQoOO3j-Zu=VHHO4FUZWdrtkyd;rb3mg{YgO)? zg})Nt3w+;g`_yHcPFM2kxCf6vmxi4EGV9PrSsr$0me~vp4|-&G%=<0yqr14KZ)&%% ht?H5IF=x{EFor~0O%K}qbSu!a44$rjF6*2Ung9^Ui@X2; literal 0 HcmV?d00001 diff --git a/htdocs/images/default/debug-cache.png b/htdocs/images/default/debug-cache.png new file mode 100644 index 0000000000000000000000000000000000000000..61ae9ef87917302ff0e5787bfab2c18515f7f92f GIT binary patch literal 661 zcmV;G0&4wPx#24YJ`L;(K){{a7>y{D4^000SaNLh0L01sgR01sgSs6VG^00007bV*G`2iOb@ z2r&S4(J)Z}00I?BL_t(Y$F-JCi_<_D$A6*SL+D|1C}ru{OZyG>wtfQ(%ihIHE#k7u z3X6D9a4#!}9$dwPcMskkfWS$K3%>U(? zi6W)kyD)yvJG#xU4s7O`xR!93JhW9u=SsAcRO=bvPVSDwO~#iv%A&p7Z_3Cjf3A+>OM7alAb{e}oVMAzc3{ z5c3(2?>~=DJUrT$hB1irW$f2t>>~h>uIozEG!wh7>(Zxji6GsQ^Teo>$ug*_x+=0S zUL}S~&#Hr@1gfesnM|T8uW>;oA=U=ubUMXxoR!5poeqUUfoio1P|dGN&`$ecnkKni z4gkk-uq?|ztIG6xy%hwT_&SVs(>hopFpL43R?PHt2$7OPUv?$Gc=ZGT*LDAN$Kk=f zv+$H%z+6XP5^QN019o=Q6<2h--9WH)w5>-lpU)#Uvn-3zXhi&INTDq|L9w`(xs#_a zkD1sulc^m)3c|FdCWwos&t@}h+Yav5NMZH+{Tm(EZGSfajK^a<&%^V)NI?M$+Wy)_ vVW^s>ZSTT4e)}!*>+=r literal 0 HcmV?d00001 diff --git a/htdocs/images/default/device.png b/htdocs/images/default/device.png new file mode 100644 index 0000000000000000000000000000000000000000..eb153a33d13bb21e935456d533388f8baaf5bef9 GIT binary patch literal 500 zcmVel8&MR7pNSL6bdnSz31V6q6H69Zw3N83NEXFiz`u}1 z|AL?!v(cT)F6u7`>8fV$CWO)^x>0MuiKJ!B$F!gnbs)y;B0A3a5eRtTa5;zjp7Wmj zo+~lD31=V;3$9cuc92S?kcUCX<8d2!OF+I)X^`oXt7|nPVL`wz7z?Q+64Us6KBpQ&2Ds||=k+TSfcg2ijE+v)kJd3I zB4I%=D43g@v6~o%K{Oiek8pP0Bb!aTSaeK@blOWKEcmkVk7~6_F82|`I0m3tECMhB zti)pzG+Qc~b|;9c_8lM)c!Q>m^R@5|O?yY7P_PTwvjF0+xha0_mqn+Ycb(2V`FvhD zrT5(EDFJxBA+~ppP?Q9_dj^V<;86cPaBE$g*l7Hr-EO1T6N+@YjJY{101#-I{SF?5i90BrrjbLi>c(*kasZjOX=$m;%=I&cck#@>f z3+dbQ3_r}$)08CBYA}(qEMN+tPB1>!86rv{k`O%%h^G#7bY`CZd++Gz=|e|i7zPT( zXr~1*-bgUm7x4&?SZ%JoL8!gW*A*;(_!;5}g>qX--griHJb}HE!(Pb|>m6WldX9s! zI6}g5NdPQ263o5cQaAzvsSyLh{00006nP)vK$IycYfJkR&X5x@)l&pGte{_}3aK2W>8 z^-1ZE@C)D$unHgs1_t!p+}uNjwOWnMUzT|Py;pcdl{oRi3W@A2p66Z5=ksp^-&%u% zgDfm8U>F95VRXb=Yx4O#+sQQ^e>BO`*()Rljxj$!Pdc4GSg+U57K_DKjr#>!YoaJ3 z3_~iF3gxx0$W1*-^VbXHR~?SNJcDIfEG{l0gvh2+sgkuP28g1lbKh9|nR}IW_Pe7L zu2%430qA zl8K24W@e6)$z&b`>^UeD3cU4vliozgm&GfP9%XiR7Kji+6NVCKIsKP|-Q8U-FMrAt zW6$yD#&=v;33=z;lQbG0zVB17*YSNH&+~|)h)xZZk|?EEUjCZVK|wmM`D|sKzJoc2 zhKA5u69f_|n*@QR(eTk)w*Y&um&;|;_9c$J_zcz6bA0og!_ng};W#!sJ3BO+4T3-d z0^e_R0a`}{LBPhD3$eWy7y1|)C2IJ$;QmItf+PaD7d03W3GMU76UE=XLrfGDGC}qI!H*WFcb%V?6 zRdoCS+3YY1)y6oGR zYzu9K&`2pe!v+rknoLbia`^BV{r&y)_4VPp32fWJvP^^!9Z?j8fJTTm0Kl>wPMtbQ z7)F?;XfKxj$DXu@#}FtLbtCwGgKD+fwx;j1_;7$}n$&7Flv0SEo*q3iGJ@}W|M{V` ic-`DWi1yUpKJhmX37afwuiEDT0000IS@C4*({TfjOl$aNYd)qT}6#gN(1PO_$Zg=Ot-Ms_;raJ(2T_;(`D9WPj zrfoJ)n=sW5hXa73C~Rk0c6@&WuwJhv0SJ?+D2o2Decm2Fj#HTDD*)N`C=|~_iNE-m z_%!%pjMs(aS_VM305^C{0BQKcy96Y7dU)rrssiv?RR9(bi@toSPXIy)qINI4p>NZ+ z`6^#7A0r~orfX;Sv##sPvW$ph-(HkNQR+leR9Tku`Mk%6eo|4kNZFQUiq`9X?{TNl z?{O{L=i3ATq$Y+$%ZX{^iSj^^lzh*HkFrVGH%(`KWywIqKlKg!$p=c0nGEv)0000< KMNUMnLSTX}zm|0X literal 0 HcmV?d00001 diff --git a/htdocs/images/default/error-big.png b/htdocs/images/default/error-big.png new file mode 100644 index 0000000000000000000000000000000000000000..0539ce8304f1b20c076c135fc6c629e5c252694f GIT binary patch literal 1891 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 literal 0 HcmV?d00001 diff --git a/htdocs/images/default/find.png b/htdocs/images/default/find.png new file mode 100644 index 0000000000000000000000000000000000000000..ed5c07eb76dfe1a6e18714081f8775a8f43bbffc GIT binary patch literal 1428 zcmV;F1#9|=P)rArEY0$OWD%xZD%jt-I>{$@u5SwgoqD5`g@vl=J)-6 z=X=ha?}7j81ttB9o>E{vuoQRz6#fh0xxlt)G`jDTk9Xcbbl^v&?aHNGH2Tt6pbQWJ z8CdP}`99ma^_|v=ii*zx2OvC2^k^Uhjlk;7o8R2DVtG@|;zd#a>`0|sEo8Aw6IpiC z(?1;B@cJ8PeLi3Mtu323u35cm#^OcMKsucfc73(GfB%7l&9+PRS%G)=?)hfd;)VqQ zw@Y;7vI>GIAqpa*C?E(T76LidU|dm6pSMIP5Bmg362P)hRh_HXJJk2y|L{{_50C^* zY)b$sL!Xc(R7Xb1PLczr2$%xn$s~#K6rw|?r@L2t`0zfKC9<+v9Q+pBkcu&vQF@`7bq2$Sx)*xE*BVuYcG z8r!yQXF+{Ev**mgDf;N`@1(oCmleyFAv>LT{Q>8JpMMzzt^ql~5`jA4qq_Okuim(I z#}EV&%QP?z165TSPbwTccADnqX8e9HveSX=aIm1hp32Jkq|yTVSV#! zfDdp2I2s$Gd$(-f*f^0*yM~7ba4oDwQ}cjHAzz^HejmBKipNue!yzGwPAt>FFF6SX zr=lnx(y0_7zYlL|32WD^jGR2xvIH0gRPp8?9bJR*0jZGBbNhA&q9kKk7KTxzpsEN6 zl$Vt-7?0b_X5#nzaeLhO{a!LD695YVS$45>Nn>eU?YxbE7my^&qBk)zzG?QXnZb#P z9OdOx2?xFCnnt0Zp=kzVN`juA9z1S86%~~vl@zB=og|%&k;}SS+SEiS97YgD(uzV? zPp`YHtNRF$k$_Apm2r98B};<=uWSN!weu(xvJ{I&^kR|ZxXMI+gxhzn(RS@TfAw}U zo{ZCaxq}&1KKgnSl)4=pKlYpU)BeLs%b81UrfIeTiew*%?$NR2ibz#uRWg|r)~;Je zEz`+^$mm!BP-YeDUSCqeo9%KHS?M|G_lPOF#-3 zmjDaUbiMdMEfhACmxa8MNQ8jTgK4NZBqvU}1li?dO8GQGp%7+KqrLr>arw&i{Dq6x z9@N%Wc^A}Id1A5tPE9k<0uO-%kbZOyEMQnkWdfmqzo9G~a@N$$MU)))!_x=^!kDJU zy{j-5CczuDe(E|t!<=(^bxi}fe#>Sjk88meEpcklj?sv1Y_xX_;zFo3&> zk+G)ovcSw0E0>E!El*-7&hKYh^zXhukoxub`PQDk!6W&Cb_i$(27siln~BcOzTujh zNbS(jU^Jc9zXq~^^<=aPfD32}hl9I!?s$9d-Mg`T>-Em~Kz#TD&<2bGd3${oo5TfF z0keP_``tcZ1Tdb;ZYFcy3#TvjW(F zATR?6*d!^NIBSa*?Z5AlbJ@m}+4Bh-V?Iv+CS%-V0}b1OZa-Vk=@;w|lkKtg54}%; iM4q_$!g7TnZ3{T_&dvjw6Tdj$#2e_`Tgee zyUy70`1+}*r{^PCmOB_@>zy6#E3dxt@_9*$A2UsJn@m%Wn?L=;o=|?&`~iVeILK^(*H*ca+5%8XD$3 z9*-{)iF`|nPyBxWhrPYM%x1Ge*L6grQA8u#(A6}W>p0g+dzhKKhd|(A>b-NPo7F;& z-~Ve}`*SJ0v9J&dyMOfB*ASQ&alr?c2s@pMP3=_Uzlt>8v8Xts)GD zVIm$+AhfXtJtv{nqoKWl!)4dNjS?)Qh}-coNNu6nv4`WWCaP>2fA{h=%skkv zryjA6OBdhYy86u(8?+qbrV4JAP{?Jm5spAs((p7p(Aiakre-%Bj%sp1jvz7;yA$() z5W0-N(d5?n$#Y+(Vu@^vgNhy<8Sy_2VW@C9Oq}d)0?Zm@vROofX{_ZV zfZM{cZYSDWDf)62PH>(_GM%9e6fVixyW|aaamnU#O|SL7^v;Q6ZH!UGmPv3DQ9EuH zMT%&u;pl1v+Nw+>H*=W1ub}%x5EhSPW4(yvmW-jvCHNP&`v~b5-2s*3$AN*LEoL*h zXaWTAh*)$l9Esgd8NJY=qmkasQwD~yhGHQNIho;i?uDpK7!b@dn98yB+t|#!lHBE- zz}zfUgq%>sLc}wabwzTZ(^PQ8VoqqPM*Xl*C}{|8$x)i`-9xar*;6tDzR_usI>G-f zgK#7wJ$MGw5a#fDEJSx)C}fH#<~gKIbv~O41L#c3~P3#6NDlZ>67f& zTbwC!i=dTnwVs-oS7;QO1yg5O3Q9ub6D+X~!JNaG4J=JZCCL(X7ELSfm1t=O51|wU z9MpEE*U^mA!DM_joZ!@}>3wWvDh>{sZaf&DUN|MEmDa{uyTe;gBW0&TuoZKL zSjvf7Zv@MW^|(1QFByjQJ1J{O(&ceG0Mnj`Co|to2Uf4%99vW;=Y#E~l2+f{7+hxqnXqXEu`$<1eLiK^?NiaPtuR@`uPlR^TU-@Q(zg!<ZdP zC2r$$UJqQ=4w_#uJNXD_RNNZeKzJ*5gWlXGc}TMUG;o<-xx|aAF}xIvUm2QS^WU0$ zRJ|Taw>NoQ)tz29ySrM4!QnY8lg)ii_9GnJY(i5b*a|{viz&fDK@p;)lY?EeSqdF8xKuX>ow^r?;1CFf z(zR|ajxHHoN*y~$Kok)|(xfU$Ufz4TdmVg9W2)lN@ATui?}z*SJNQo$J@Gvt2|T`| zw+4I%8h}w9U^<!n|*(9aPSGJcR;dQt!9$R zQzhr+``n9vO!`$2)nM?+y6vh~|))-^1+*iGjcDvoJl`#fm z45?I#v9U3<)_9(W)*8oga9#IiP_x;*JX8wHvJgU0tJP?=T1-z*<2VkE<6zr1wryjK z`4{AQ-tSVWL?jX+6bf}=OG`^wmPMn{!1KH==;-K(dcE!d2Jkx|Q>)cJtgo*>4~N4~ zrIe!6-o?em@cjHdo12^Z?Ch+iweC!I`SkR3J6MswpklH3qgX7y0v-i>Ct|VKlgY`+ zFO^D#-QC@vp!2P}-<4$@3db%707*qoM6N<$g2Gft=>Px# literal 0 HcmV?d00001 diff --git a/htdocs/images/default/hard-drive.png b/htdocs/images/default/hard-drive.png new file mode 100644 index 0000000000000000000000000000000000000000..f3da3d2ccd0c4e6b4eadfc1dde88701435fa2062 GIT binary patch literal 1308 zcmV+%1>^dOP)`DgOWf1gS|x zK~#90m6c0xTSXX#pE(y_Vmr3u=29naLfxbn)F4tyl~TGaD}4EwTrSSi!Pc5HVs5c8@FkjrZ|`8<|K`8$3D5(KK2ZY2IQncfmfQv=$v_<`M!Ba zBiO0-w$_%f8+;9?cv)4;vTo;c*5^QNd(=y9j~z00%|CtXT>shg=T291xjdRCFbspL za0;`gUSILP6yINjZGDwQ%fZu~+flL-KQz$h@j4XJ5${z58+OPE-z zX}pGy#pE;6x#!GmxXEpm7`}CnM&|&>dyaA9Se&ErRwf>el1L;N8yf=%0Ih%r&~~4J zKq(e-DYn8UiRm#0?%rl9HH#iPfnHMts}Uk?5l;1;;P{bdW~T1(@ct0#bQ(?5kW%V^ zYujAZ0|a1Ht2GvqDeexA;nn@q3Zm237`p$Cielzx;cHmpZ@-SLXANxP6bUkL_%)nXA_K!-skbtc`6*D zwKdJjlPAe!GP@JH0{}p+RwJEG6OYHac<~~BuaD*BWs3O}0Z*Qx@ma7t*HKlzX&@oplK z2-T`XI2_{6ogvoN*7gSoA&5q!n1(@WDMdIOCKL=2>^?{Il{38UauEtQ;qiFUG=Z*b zbai%;NF*qi%lo!S2_f+Ld=&C|%9Rp@f<-XcNNcp6#f5p&YtNaPnZh((#13^53WZTX zLxT^;arOl4xCcrpq^wbuHFQHqB0-0OmFLQpAGmz^63=F57#{wEWHL#iSfE@f5eWG3 z`~CY?@HYq3G|>$mm&>G7+M-h4BGMEl+!Urzu*m1L6pI$+atV|RA;ilzd$mX@g+kF3 zX~OMxqiGtoT8+ua4{2#Rz}Yizva~dZ?((1n*mjXkP3PI%9Hwdhw+aeYfmp1ASjQox zlvFAeRwKDz>E-ca0bM(azhCx?X zCk+h^WP7u0Zfziy1SHvfmIsLkRLXlF@SXs}FnIXr5gxCHo}M1uE)%cUM{|q7=l5gV zMK(6p$>y@$9=L^F+@SCEH?ZyT{Q*iT9LJ$jDKj!M!u0eM(da?i+uKn1DC@?ws zgk*AxN~y}JzSBe^5wh9r{(zO0m5rM>Z~DAmFM&XSrKKfCNAF^q2AZxRYZA+{ux%T+ z+f7^BLDtvT$z(Fvwk>(_$m~#kzJw6sBTdsj6GDW5e`2AO+AD{uKAuv_=TgewfIopD zU=46~FZ2R2;4l!b+rYmEeWyy>#uGpRsO?^;13sW}8}@$yiWe=~0P=tXsJ{R|KLSzf SPxwOs00008wQ zK~#9!m6mI4Tt^jvzx(p8?W`ZM<2X%>A4%&+OyZ~&;Hs^Ks6b6xf`Wq5{sDyeL4Op1 z_yMSdN7WS61|lJ70il9gMWD1zDhP$Rv~KH~*p1`HapTx=yz$yzuOGW!@8iDa&b|EL zx>!M|%8{;SG@5h1d*+-uXB2KtlnwLXRuyiRO$}}PTB<5zPnDIG-60*b!gU-~Hw@p` zqWN@Y^_pv2k1xirOaW`R1ZZg6x2JYX-E;Td)7|~hg9oUqsU}uYNoi>*bEzfP3Kq%a z0x!REhSB#g4z6XEA4|_(8wTV@0y;j?^Yv0yKKM&x=qzPT zG+k#UXHs+}uJBMbm8w`7mhG~A$2L0mbQ!}J-n+kOiBm7oB{15U_PX zjm2Vj8<7Za42)1;SIba;A7k&Fpt`Od#0r7$BC_vdxXaYnYWT92=Z_!aiRVu6%NI|R z%bOG|7t6AVltch!FHiwwbwKev*<4w@1(_={HMfMKsA$pKu(KabC77@McJ_np{t;@YydML3k3+lW4j| zHkZej9zhUzfDWiS5cr-OFJxEt=_L_tSJ1Qn5W1$J=_fS15wd|R@Fq&@o|K}b;HkbC@f6O z0AoNN@YVsN>FGRKB++W%|%T6ooeTwh=RtyC(t zzWz7hPhrgRKqfSr4x!@a*M{;DFAfce0MT$<_gIGB+F@hy!gT*1`8P&w9Xc2aXUzZr N002ovPDHLkV1f>g7GVGY literal 0 HcmV?d00001 diff --git a/htdocs/images/default/help.png b/htdocs/images/default/help.png new file mode 100644 index 0000000000000000000000000000000000000000..674a8e92b7f20890210e7f9e52c3bc44733dffa8 GIT binary patch literal 738 zcmV<80v-K{P)nJY(i5b*a|{viz&fDK@p;)lY?EeSqdF8xKuX>ow^r?;1CFf z(zR|ajxHHoN*y~$Kok)|(xfU$Ufz4TdmVg9W2)lN@ATui?}z*SJNQo$J@Gvt2|T`| zw+4I%8h}w9U^<!n|*(9aPSGJcR;dQt!9$R zQzhr+``n9vO!`$2)nM?+y6vh~|))-^1+*iGjcDvoJl`#fm z45?I#v9U3<)_9(W)*8oga9#IiP_x;*JX8wHvJgU0tJP?=T1-z*<2VkE<6zr1wryjK z`4{AQ-tSVWL?jX+6bf}=OG`^wmPMn{!1KH==;-K(dcE!d2Jkx|Q>)cJtgo*>4~N4~ zrIe!6-o?em@cjHdo12^Z?Ch+iweC!I`SkR3J6MswpklH3qgX7y0v-i>Ct|VKlgY`+ zFO^D#-QC@vp!2P}-<4$@3db%707*qoM6N<$g2Gft=>Px# literal 0 HcmV?d00001 diff --git a/htdocs/images/default/home-big.png b/htdocs/images/default/home-big.png new file mode 100644 index 0000000000000000000000000000000000000000..d40900d98abae5328e1c2700891e8d7e902097a4 GIT binary patch literal 1084 zcmV-C1jGA@P)WFU8GbZ8({Xk{QrNlj1+3MgYKATls8GayP~Yjt8ECu(VJ zZDC_4AX9W@X>Mh5Co}I@000AjNklFZBx>O9&-t_^ipF8m|jYaF(Ot?Kvbn*dD~bk zMX%kp_uYebRjpQSlN>rQush$*{O3P2-)soKoCXSgHZEU&pBIsP_rAF(^atPH-zS|; z1K>CgSFc{-#`OBZ@z-v-Ri~n#~qxPiGk$9VPR|5`Ub zPXz%0QmGWGss>nia{taPS{i&Gh1+-UcZ?1!FTdUWeqwThCx3{80aR6`*=*uCPS+t4 ziFD6jdj(!j*;JIU&u?vQz5ATWoa9(49t1E=lUOWRyrg z-~R-_vP>>qSnN=7)c{3{2A`m&@_twMzgz_~LJ$TrM|o>bzq40D4Q)+XGo{bL-{}KD)V! zLvXU{Ppbi&qIOt^dgGT$B?LjB(P-c}4yI|cxw%Q9@aRQX#T6gG!NGwqd($-0G>u3k z;$!4E4zXAaQ50ENSm;mGC%zKdw#~-I2BIi3Jv~h}n`LBVq|2yR4-XG%wOaqlBG7|! zxlA^jWqW&@+1XiItrnsv`j|P6Ln4tN6bd~*z|71HTU%SKtgH}^$4MrW3=a2w-h*GZ?-G@DHf z!@x96EX(STWBn6@s0ZK$k4B^Dy3Wzj5td~k%QCvIqpE5*ux;DD7dP~842}cT>vbxX z&JJlb8Yqf_q9|0WRb*MFR;!_D8ufY|S(ba_i~==48C0qSFavz*9zL&r;{MOaykY5; zkgEwG1;pKV!EL6f{n^x!XSQwL-PNVi zbh9XpIoc=^3TZ^rX~rj7G{XbEwTj!nKIQ*#DO;{R!07k~n@rsd9DI7q#us! zOW)1n*K2t71}#(wb}}+jfRoF?d7Nb{OzwR1?APj*jGHAd3d!tik+db6lCm*hST#rnbke~oY!c?AEC1&iS2}VY+x%s#tUQT z&t#Oo{%xlxuKI7zPTwHjp2SY1P<5MXGsGXi6p3#broDR&$#jZ~C7pF?hrXDKrfDde z!ED7MH-2`fvSH|rq@H+mSD6fxqti&QjMAoa>E9AY*A6m0kCRG7u*?7hDUFQYL<$Hy z7K);fomrsaw@#=4nM{gRnSQ1wyErp>5&P;4-D`(v@7YK)5ylFd2q{sU;JQU@+eXvW zyEy|_S^bF$5DXfuUDHX>vB~Aql!^<)*7mU~VPgjkgre}x@$a~B;Ua~?0tXK4qkq#z zR7Ij`%TiSD2})HJ!eN_0po{!}5n}NuAxA?6|Ep{g1Jfmm^15}3&6=a1dFc^h3_rYQu=9fiCL zkm!bi?KoJLjiM-b$=t6bkAC)EVQ#MY?(e70eSLi@>jm3Xq!iq9098{l3?18cutN?~ zQ2>GOH)%Fo_eVSY@jGQ;@BWXDGT?iA(j94}6d(jrDo7#G)BsWoplUw1@W*8uUY)tZ67vg7l)N?^Ge{!oFn(?3*ojl4V~%Cg zo(j?18PAD_AJo1Nzl;P;{g9~}!(m6q)K#k0#;2p>H-G9#$4JHvETe5=$Lp^YR^t8# X9hhd(3{BE{00000NkvXXu0mjf`NS5_ literal 0 HcmV?d00001 diff --git a/htdocs/images/default/host.png b/htdocs/images/default/host.png new file mode 100644 index 0000000000000000000000000000000000000000..87426e700532fcf0bd453f520ad5c5152dd7e44b GIT binary patch literal 844 zcmV-S1GD^zP)VW z`~@jeCAM2dG$|CagkZ6=Ou)k6N3byO?99$MbMHMj#eBHBuCNchyzk59{O)zL&JFV(GRACgZf-sWY5-CHAPmFu^78WV?(Qy^mzURyL<9r`0R#~M;qjw~ zG+V9DfiHlc0fILRlO*BS?QNPG6Aq0qJv~jsM#Py>h=!S*oaDiS0);|>LLtu|&!5w} zae2fISsCK1wN=6(;Mv|wviW|V>&!1j^n$5$*Vf2=l>B%fCSxKJ)o+1 zuUKnws(4ihdmC_b-v! z0pxPIPYw;QP>N=%ko4=25n}xt;U8-gh6i zop#*zL7@w7?(4bXx&Hs_e_z*q!CkiE(IN>*{s&WPs!HX^KgXs4_5e{p2UI}0@5t9q zy`5KET_%SIf0x6T-j{$}yeKA@J(4e@k>E7oy{?x4O#!H>DwRim+>adjHA9`h`iD4q z?i#Hf-}C&sdb--*z^7|qTcD^Q#pJH2INktVKOCceOB=(ZcX(y(GJvpF_1HrB)4_d6 za{z+nGYCLgX_&Io0*VTA*wpeBD|E@zk5}MB;HFFzB+}y{IW~?IE+bAZy_b49ceZDm zV@MN15dZv5RxG?eOFBI(4_~C1HMOfbu(ye=+rJ?i%AsQMgV-sDtXPy};s%Nor2J95 ziWke42$@zv*Lr#fl`fFm8)H-#Pl8mmjRUY_^9V~G{F}PfBP@Bi7J%W(8kV=U5ekLS zG%bVBk@j{}RYf>fx^Ps0p5DRyuJ1-Uf1_ynh?bTXc6U4c(qr-Gg^QFeiUBYF48}Yj*imP(?d8MM%Q%| zWwLt5#>S>J@nD+PEC3sz{o}*D)x4Te$V*L44I4LZBp#2GU%rY@_Z} z$p8R|$KwDqB|@FrC4f&2u(str%FCCtVZ#Q3!5{!twJX`V`zTFKO?bUtd_Er@k0&Ge zv`HzE!kv`?0FJJaU%ZIAx;py%`)O!s;6(g&_J4aCfTc^9(%08VB9Xx7^JM@ShLQGj zG-qxAj~D!!Mrvq?hK2^Zzu3x|^Viw6=Vw}5TWM}?CK`xe6%rHX+yK&+ zn5Ij1ZV56{%sZd0BsnpGjX)rXBUN&;gXt1gRTbNDDe`+snKqh7#WClRNVP#A z7#>TaC<^Bee+g0{CnuLkUI9`{gm4%T65%>XB(`CaFkHmQE!MoSjfaY2Agp;Z&_TE^ zNS7skNIb7-1|KM+Jw6r_|)jNjq*=m?gP;(X6pj-I;0M6`mdS1(glu?!*R zxdV_mt^-1l93N-hQ|k!?1H8LyC%0}U0Qm5uPKJkXVWyH8sU+34b$os34}v8H*p5L! zlemUGs}Cj{M1qvy^-O;I13?0TUr%9(xOxCr4Q zT!E2FB3u{ScDR|ife@3=g=HBC*CCXZO@846`29f~$HpTqgsYH9NqovYcW~kOQFL@B z9D!|_q>@RJ$t14hrmMy@QshP#kXKNI&*#T94TNy9ObcB|gpf#g?oO`x=s8KUpXWlX~$3lFYkV5tK6-}shy z%eCr0=Wlu~sd{qSe;Fv8+3O160fJLYpK*S#CZ}HLiGKmxku4hGgXow50000 + + + + +

phpLDAPadmin icons

+
+
+The " . count( $files ) . " icons used by phpLDAPadmin
"; +echo ""; +echo ""; +foreach( $files as $file ) { + if( $counter % 6 == 0 ) { + echo "\n"; + flush(); + echo ""; + } + $counter++; + echo '\n"; +} + +?> + + + diff --git a/htdocs/images/default/info-big.png b/htdocs/images/default/info-big.png new file mode 100644 index 0000000000000000000000000000000000000000..5a2cd96561a20969638d15a41f0793c5372f750b GIT binary patch literal 966 zcmV;%13CPOP)`p6q|=l^@Q%_i>9JO0byUz;;B<7}|~`+1^D*XJ=D>Wock7zjAeFxGDjSorj;e z{N_6!bh*J6^2IW$BBB@04|DcZ4`)yHaP?;DpYM)PM4J<|CE}r_%>1((#q}#d+4n;C zLluo4>>d~#dRmVjVzs!1lxkOLsFb2)IwTJFl59V6LJt^&Km;%<0d=u>>ub??8>TJx zmG5Os(9wO8#-_+=APUq0n&AV2^$kZK>wbpC+-6mQ&%XTjp^&zYqZo$K0)#w(=>ueQ zYw}niU{u|B;r#HfU`i>JBn|}q`}ISlqw)A7w*_58GXi};y$8^IfY224wd!s+;Q=s= zdXValC$3j|pmbd~rEng}gHo}85N_5>QTeYl&1Dzoq+O<=-q@G8a2+zUf8jdT0$};Y z<^$YvsdRCA;uf(3jp&-TCvl||#X^pmiQCxb_HSNKaw|O$nT7kKm%qC-?{4O32-fWh z;5s&$nF$Kn%%qfJ#;arpP?blm1NzUrJp9cYZ+{qGEJ`ffMM(LdC*LX+N#7gi_RrrJ zm+s&D6u1k_0&9S~v)L`rO{Er=S62Fak9P-S%`I4tKnPhi=3C_rQe)Q{zwy)hQhMqO z;7?%D6L)qtJLTQ}%!Bmo=u|3ox;~&{P2n(+NCc!{+q7_Oi_P^_($jYszd6F)Th}I6 zvzgC=Pq0UKU=irvm+-4hG~jg{r^6_M}+%?e?; opT7#-v(qc={b3=!Rdaa!4VPn!l#>T{V*mgE07*qoM6N<$f`q}@Qvd(} literal 0 HcmV?d00001 diff --git a/htdocs/images/default/info.png b/htdocs/images/default/info.png new file mode 100644 index 0000000000000000000000000000000000000000..092335a20299050cd5361fae7397177a953b9a0c GIT binary patch literal 510 zcmVpBOJxYwKVqHA9Jzp}L5ZV}}l<=%|P~se_?T z{tb2$f7Vh{+jMYH5C>60HbrR{ClTTza*M$jH8F{QnB<;wn-1Q4xi`0)^n=6s;k@tn ze&>4+{D<%Xb3hExj1e==eC3xtW%~gjG%*uWUN;5sRCv*)PC9$dub(??t$q=}Fz~|! zcRQpDmh7JNTzZmQdu%L_f)^EBhdENn@*@54|lmUVBfC52dEp{`^v%b z8CSVmq?CM}>Ia~AGK7>8DJ6yc1JUoF1mFiwD-43*;P|`)ETpugnP4FVB|Nmg>s5fD zT|sPdZM*qUy|BQtYzQH&wN@;!yE1nOv{V`dffvn@ zlDOhLon>=j!r`#?t}!Efo`dK&tBrOi4!mmchd=ai_@% literal 0 HcmV?d00001 diff --git a/htdocs/images/default/invalid.png b/htdocs/images/default/invalid.png new file mode 100644 index 0000000000000000000000000000000000000000..1c427c04cee9218d5dba5fc95c2d45d16641c82c GIT binary patch literal 692 zcmV;l0!#ggP)N+@YjJY{101#-I{SF?5i90BrrjbLi>c(*kasZjOX=$m;%=I&cck#@>f z3+dbQ3_r}$)08CBYA}(qEMN+tPB1>!86rv{k`O%%h^G#7bY`CZd++Gz=|e|i7zPT( zXr~1*-bgUm7x4&?SZ%JoL8!gW*A*;(_!;5}g>qX--griHJb}HE!(Pb|>m6WldX9s! zI6}g5NdPQ263o5cQaAzvsSyLh{00006nzXdEwY9aAlarX3n6k36o}QksudlecxR;lgsHmu} zuCBJWwwalkot>Snt*x-Iu&1Y|qN1YK*4Dzp!lk99prD|eo14GCzq-1*p`oGG)z!PZ zyQ-z%gf8z+1cac5qobqj z?CjCe(a_M)E0p>R00001bW%=J06^y0W&i*HrAb6VRCwBD&)XV8Koo{yVoEASDWpNh zprV~k+4 zFuhy}>|)2|&HUHTl0vy2h~8_7C_m5Ls6Zqm2Ln002ov JPDHLkV1kZM49@@n literal 0 HcmV?d00001 diff --git a/htdocs/images/default/ldap-alias.png b/htdocs/images/default/ldap-alias.png new file mode 100644 index 0000000000000000000000000000000000000000..78dfcf833710eccf9ad7b4e58542e23f6de06908 GIT binary patch literal 440 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 Hu0mjfxy5A^ literal 0 HcmV?d00001 diff --git a/htdocs/images/default/ldap-o.png b/htdocs/images/default/ldap-o.png new file mode 100644 index 0000000000000000000000000000000000000000..dfb89eb506b1b236e7f91e1351368a88278dae5b GIT binary patch literal 1305 zcmV+!1?KvRP)RxWJLW5g}9|p#tJk zpsGZrwu#!bv`u2yj$iwjotd2n2U^r3zW3kf_#^mF8@)~J?d*_Ve~T)W2XV^F=i~Fx z8sjm>lmX!}7wK%i(67!;tPu&|?7w^VHnz6W!%`*mwl_EH8@*n?TCE;9LJv*`<88@B zDe%4NjLV~=XQ%h3seMHJ@C+(T;fRGb?}8s39H7-&4ce=#TbD0g{;a>V^TqP=^7U%1 zQ5!CDFNry!dFt*SK9@&hoT4ay@yp5gjN-RkBqJlahO_^Gg|G}un7`Uxzi{>H`(JNg zyz*tM+uP0I7lu5?Oaqb@u$U+0ctT4tY3|T4ZPl8(uTy^|K0m!>WHtm~7ywjO+O)FT zYd6+*zi995e-(DN`Y|o|QJTYA56wma^9ArIF-SGgs8>mqb!#H>ZoGOasiX54p7;TV zFTB=9AKMrAOS_k^ezJSz;G53o&VFOL9@NSO)XP3rssTF7Aw;ghbAti{0;f>)9hiq; zI!_ydb6718Ve&D%cKsUJ*xGIM_b%OB?X2x5ngz2&p;IqlDP$-x55`&)0w1mAGG4qK z;P}}9DNg~LAt;5_LaBUHr|h-{p0MU>n>L%R&U&}|VY~ZYZIWojsYK{GFcjbw2@cO< z{QBn$m@Gw{X2^4e@n`~@XDAgcDTQHMF#jV>aGPo42p6)&rP`(*qgG2~nZm+p_)6ks zX7JPDIqn|~kd9Ab`8gDiL9_s0Od*_vGcqt*@4>kSgS8|Rvhr${*8Ou1og2VfB;26k z2hheKP6g69!RTy=JRX8Li6R5EuMth>(77QdS9RxXh0W)4_@%Oj)yg@CFkoN-!STx( z0-s`Qt&Y!`kA8#Uju+wKgBc_jU``j zU#!%Nf#+dwy#`7N)*A&BsKX+PFpnZo;?QnZ;HnNm;K6tkETUNor;h+PV}Ct8b}lH5 z8lAN}-CqC3R&{CHXFfgHZKKEl3X4S);qHScc<}f+gh-GrViY|KpLwuW<*?Zk*!(`6 zoq4&GP)ce-J*_P1u%NWrs8xzS1tBotoMSedA&nyFJcAS|M&~n}497S<8=2|g^h_qx zTh53d0Xy&jKnd>RC`r>yD(BJGQmxXe6oW$OQ)0D*$}&)=5ikcr91!@3d8#MF!ALB| zKifR{4laKPAoTzM&OvLLJ8LFN@|jZ7H#)CbtwJs&5lWF%WQcj@=1Jm);}Ji3di-=g zd~w^z=v!EI55N?FA#eX7WdSYMYPD8p?dp1O>(kzP_v2!@e1SOE%7pNvIOXS)$#8IX zb~HLU{ev&2zdNIj05=7Y190zvuOr0si?x+zW4Y1T3`$`S&bIPgl|-gQ#?vuRq8BRT zr_SgJfDC{E-~izNz}G6JEC`s#eBU`6IBPv?t+U4D)*1!pasc)X^rpW7(S*2YTA$q9 P00000NkvXXu0mjfsIg_f literal 0 HcmV?d00001 diff --git a/htdocs/images/default/ldap-ou.png b/htdocs/images/default/ldap-ou.png new file mode 100644 index 0000000000000000000000000000000000000000..3e767c7cebd18c77a3e8b98b3c5cded70444d3f5 GIT binary patch literal 1330 zcmV-21DN3OWEw!cV%(OGp>D-yQ+vktoLd8gYlaqWmH{W;8 zdCz-Z_;1KSSPd4u6Pgt2y{jy!t3fpZJOtzeE zR%CB~=fEo9FDJx=_}`F#1(U;NV%x?CMcv8;B2-ZCw4KBvkMj8O&1x8^aJ4Yx>>Pg1|RROM^*g@1QHTPCV@WE z&%wjLCf{#}?9g%?12Rq$dz>rj`OWpxdv9*%n?tWtou8u6duvAPRxV=u)63}U=tR%i z7&!^kFhSS=Jht5LD-TK!00F?~&@GLtMXsqVDH=&>i>k^)p~vf&Q&nC}cVCpjSb}Yv z))FWP(9)6M!k>fGhG*e&xk03`jZxwQU83RSNKaDZEMPie-K^Z}aTk__iqw3+m)!@y zVBwsp?0I<$TQ{tsQ1!ET?ksLZEUGGMIosI9*TG0YfkLP9JV3rF zq4H3$YR)}1m1UtKwys}8k(!U+>mifVIq=C*)^6EFP|c@q(Jbc8oJ`$)bCKmBXa0zD zu3gecG};_lx*6Lad0dK8MQMO zZ*9NO)f*ugD7ZQ7uAT^n-4d;p#lRH>9Q$`-2@E}w@06DFIqCh^q12IlF9Y-x2o!u8FOO_@e3TS|?*uz7`u6T5_ zXRw>a2qyKmBZhksKwUb`{HX>Xc4)+Epek(RE9@Xz{ABt}40 zr=z+Y(FxoR_u27*Mq95o@3I9aB&3Wf1eOqtST;kx0CH*Nm{Bm6G-rSzz>+{W!Rsx> z5)zV(jzk0)0CE6w)vE_=MN3^OcDr7YB=MOA2~&U&fZ|5DePd@F^(td>$eEy9UMdJv#unm9pkA^qOw+jOp}IX*wJjW1azWP2oRcN# zQwli74LX^CfB5;_Q$4+n_fPsWFU8GbZ8({Xk{QrNlj1+3MgYKATls8GayP~Yjt8ECu(VJ zZDC_4AX9W@X>Mh5Co}I@000AjNklFZBx>O9&-t_^ipF8m|jYaF(Ot?Kvbn*dD~bk zMX%kp_uYebRjpQSlN>rQush$*{O3P2-)soKoCXSgHZEU&pBIsP_rAF(^atPH-zS|; z1K>CgSFc{-#`OBZ@z-v-Ri~n#~qxPiGk$9VPR|5`Ub zPXz%0QmGWGss>nia{taPS{i&Gh1+-UcZ?1!FTdUWeqwThCx3{80aR6`*=*uCPS+t4 ziFD6jdj(!j*;JIU&u?vQz5ATWoa9(49t1E=lUOWRyrg z-~R-_vP>>qSnN=7)c{3{2A`m&@_twMzgz_~LJ$TrM|o>bzq40D4Q)+XGo{bL-{}KD)V! zLvXU{Ppbi&qIOt^dgGT$B?LjB(P-c}4yI|cxw%Q9@aRQX#T6gG!NGwqd($-0G>u3k z;$!4E4zXAaQ50ENSm;mGC%zKdw#~-I2BIi3Jv~h}n`LBVq|2yR4-XG%wOaqlBG7|! zxlA^jWqW&@+1XiItrnsv`j|P6Ln4tN6bd~*z|71HTU%SKtgH}^$4MrW3=a2w-h*GZ?-G@DHf z!@x96EX(STWBn6@s0ZK$k4B^Dy3Wzj5td~k%QCvIqpE5*ux;DD7dP~842}cT>vbxX z&JJlb8Yqf_q9|0WRb*MFR;!_D8ufY|S(ba_i~==48C0qSFavz*9zL&r;{MOaykY5; zkgEwG1;pKV!ELjL%;Pn)6~ zp+z7;99L)q8&6i(@;pDhvS!nc7x4PcUW2hXn?r(7S4e~~4wNS)&tLR1=iDr~xz%s_ zpCYEMNeNI9QX-`U1SCOHp6#ty*-X@(cLimD^%ZdQkQYW-ZbURRu<80K^-R;In0T@uAMdL%H@{m-*2~J%XyJ%VN zE@#($GnW&I^uH7h;s`cp6e}0&OCWbNaqnkKr2DFgq@H3 zGts7?ud1dvE>`|~(zIvbA{ONS6{SQaYpg6)B3o60TPim(N oN=PK6hSf)_xH~Spv5tS$Z>|sW3LxX?DF6Tf07*qoM6N<$f^GL0UH||9 literal 0 HcmV?d00001 diff --git a/htdocs/images/default/ldap-uniquegroup.png b/htdocs/images/default/ldap-uniquegroup.png new file mode 100644 index 0000000000000000000000000000000000000000..c86d4a133b0357c7fb51d42a9cad7f9641a52246 GIT binary patch literal 1356 zcmV-S1+)5zP)1$yWwj7!DoX?^F;SxkqLD}tjFI?(XxxGe ziF`no7>uX^qftZ9)L?=bC7=*dOo5`5Zg#Py?X)w~cBa#Lv%Hyi{m^MC7>Or2A8zis zXZ!!px$xg218&us@vf`T)jK868CRWZ0JtAW2NXcM!+VrF+~orMa@{%4u3W!DExx;0 zkxjDI)7ifg_&cRylKyXzfQ6;*Jh64d8d1Gsp>P#s3rUj39n}JEAPcahs{EIjZae1y zJApF5S(NYMnGH4c`G$CL&r$qBpxRB$n_*vSmf|0&c3E%k)(^M#=;weqU`(!Ja?f1A z?j@_%Jw1EDQd_{+Pj6>475OsHKlK1j9ld<@-6>w%u?&YJ13eN#Bs7lKUhsTS+qW^K z8J7VaNT!0^be@x)xzl1!+n;7qD40=6OT!fgy&eE;Rx`_&%;Mv{HK?i`fj~k+j|7O1 zcsO+A=ivLb-W^(ulRzXD#2D|Dv~5$3^xm7>`R4HJ6sL#CwBE#M-HJ-KKe>#q_DP`ojosYX3Jx%$yDtuo?FfhZ<3;dGA`D4@%70jw1^u+S-{!)SZp{<6Oft8JPnX1 zD3tGV7FEnFnVRRyV$1r~WU1-ctrjA&I0rvD!P?EcaH{E4SC%t>b}7~O%te-+{QAc* zb!}37M58rDOEY8hBac&2D#&$`ZnMzT)=gQ-R16^qjD%V2ceARkl&~7+t`aw+;RwE= zAZ5h`3b z`K9$Ix_Z4h9T^i~clCJD?a5gw5cNrP6iVljy)HEzIN)q=d}5&CI`u;uag&Jw|1hmr z8fd<9je$iSfr5p*(`E`l#7aqX(_hIfH2w3X#sCI{C!_Ev8K>!GNmgrB|8%UBxRMVeGu3dqh(N_ zL?CSn=mxwsvtYvJvkExg=mCK_)%)l;puU#Ird@{MjD!?P2tnI^g-Co1u#RKX#uf#T z5D?Qr7w~eEXTs*WMlX^~90@Pb55xfEqE`-EL;gGtm*;|&6DS-7{3$Bl`jcE+UQ}qn8bgT3wWO%gow-cO%B1CV z9jB9m*ybpX0)ZhQVSqLY(@QJsx(2U){^>yCq;Y`G$^LHH=X1~Z^w!^7_@#g!Bq&ca z5;gHqaEW1v8A#-KdmfS_2{CBN{I=bi!6n7Q=~yCi%_N&V#(_kP+vFd*mKm&c?b7!E O00002-8;Lr;ae?SlX0o?d^xWXUM zbK66O5SJ=ZLM5VBDoxs$lGyR$c)c?_!@+iB5Pi~DPkQq{@6EiKfq$CVDJubp}{;aS!@;H zD)60A;^vJjMrN@hjs#N&S2D%rrly@KMrF`G5P*lksh-0tQqZ}zVf?qBWgsM_3;Z?q zTw0ODT0rpp@bk#;zOFhxumZ4v34R|Fyjy^ax^EtLUgxwA@*XtbLWe8AcogqY1V03m>f zc2klX(OArC0T+qprNm!%*5Rd~_Dc^yg7*Q5C(*nFie>nCI0;V&u3@q7>w&MoP?*q@$#8Zc8~1iy}m8Vs^(zec(h+qInSg0l7oSxtZMf9w%9$g zkAai(&e}w`L)uz<(l_Jog|kdkQ#sGuV&+dLHOCXdlm3NqNbQ<-!`seQzlz@7FCPM2 zZ08?H-Ds~4clBEF8~aCR7zMV58yhL7s~=LdK6c(s`zQUw-vRXJ_rCc8AYHx4WNP{I zAg4I$;@uv{Zx3l+&MB^aM7nX4>znWEq+#;2;v@&q&Gr2JZzRgIe)T=L)aI*uU!$rK zb(FF9#}J~FBwa-+Npn2`Ku^l)3>6X~1UiZ-t)-oJx!c>~m!0QqzZw%qF}AJ=&Jn`w z9%WTos>)*ROd)urHf%q8K^-L9&t4$4Aq0P(vta%KGq5k;G0U|e00000NkvXXu0mjf D-(YCl literal 0 HcmV?d00001 diff --git a/htdocs/images/default/light-big.png b/htdocs/images/default/light-big.png new file mode 100644 index 0000000000000000000000000000000000000000..d22f5e954d3a5af6d5a7ba0649b450130d66423c GIT binary patch literal 1950 zcmV;P2VwY$P)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iOb@ z2rnlDn!4ox00$mPL_t(o!@ZY(h+J0{$G_*^H*enj-rd>V*<^Q{MmLE~)4D|zByXwxd?bj6bN1rY8aU>ks*l~)&; z@t!gKniuN*O*fgq8jRX;8mKr=644{ydg8}pgVzm3xm;&saB#4|%$S-w@4i2A%9)sW zr}*|;N4K9oed^f@wdflF>emd=-|K86!Y`lr!B5j<{SWCGe9YC9l8I($NqNb zU3YgBi=`x=w{Ng4(Z$TIIMy|-Is8`v4H!|ZBc)_>c=+bhy7dG8*c-3j)AEzU02bE- zFi>%R^yP;h$=rM2u5vb;t2<6=KnN-kK`Ui0B#EgT19NHh%z!cc&wFC{zFr#Iv@vty z#JFnKXK(ZZJqEyCEtgnD`oiWdTOZrC`+*ImQkQGnR)z?HF+8m`Pc!pHA&8|UAp{92 zA%uXCf&>wW!C+#L%r8Is_3xXMMfW*ru?aw`Ed@$>>!CegecTxy{)8ZsRm&nGf=5IR zW7q|tiO2%5a*+j)1R#t73~Ml$W2K{>?rwXjz7U>0b28_L`fUKMt11BC&W{d%+)|1r z0cZdo5rt9;NJ%Lns3;|M+P3JlZQ12GvMZalIx`uoXgeY!QzAtY0)n9-gIh;-cv8}> z0P?FTV6F1(rd+N#4uF}NjDawQ(}2k^BP#^iM6ie;hzQ0IgkVDirP)Z$0tQ-Z!|Vmo za9fz=cMGec_zk%87kLa?+f+AIV)0K`fS2xdkqCD<5atJn{S ztUw5ou$TbCN|&H3H9c#UC#wL;5m6ohd_S4iT6G(i zLbKK^jbQ?V3}6WJ^D`-CxB!y2enSB7j2$~#RZ5f6npL7rtdiKkitCL=M;x1a9P0~V zq^5!}nMx8J2YxF`49~`i3KS(VTiUP$LjZwWU#AUE1BlxNIQ;k1$8*v$eUXaTQ<3(f zIA{gYRHNzDydb_9glfqTlUfj}S`e$`V!e^^qOk6B)QqGGv}H6vY#CE<-HU^X=3@Z7 zwg8y%v*&;Q%x&+TI-zXKE=5KeUq{MUaaic?_8QF#c{hrdy)bID!l>Z}v3q`YPWn1( zMKTGKlu=ADdEu0n=BL+9PMjKaz2v~7W@6S~|d zz)UrKJPsS%UO69z=BZ*L8Q)fmF!faS{Y`onT(EgvZWbQ4JjBf7%hoPIzRO4 z%YUdG9Q~EGuoV9gz}%X5!$Qt_{jYDm{_ynl?CkK(!^J|nWVaeiY2WvYvA?`AMgD-) z%Nr6+j*eT>7EX|(Y)%Go<)z>Kw(sdDzgc#D{XnG5iOa42ssqXT9_J<^{6?hmAMD-x zi~e*<48@u=DN7)o7RWdRB8D*xX=mJ)r>pz-?ModT-DkPJez@f&e+E#!=8>$w*Lg|^ z`r6Sy9Uwn;V30!;`VbVs5&^(5KA1d?`@iy2gpoc}tH<8~Fb$w~wb-H^fZ2ucQ7J`| za{>(ZS=juMt=QPF&|8>AhGvksXRt6o1tQ{FJ$`;g@>)BwMZ44M&Ye47&K5rm&yO&3 z_6;ml=difgz)~ZCmK9Vg{isyRO#tR{UGJIzMn^|?c#R34>YcTo`A%*~a5kNP9V*viL k(sJwgKU*3=_F4k`17^w7J@ISX{Qv*}07*qoM6N<$f`Gl4U;qFB literal 0 HcmV?d00001 diff --git a/htdocs/images/default/light.png b/htdocs/images/default/light.png new file mode 100644 index 0000000000000000000000000000000000000000..88598999024753b36ef90492ff2c5e78dd963df1 GIT binary patch literal 733 zcmV<30wVp1P)LnxVyTa%M7lDe+V0@wuLmL4WM%%0)lyH|UAZ=8=r8YSE2FinnBDn-Y~AEu_J zUOoqq0pJu3ti()5M#g$ZN5{It;Si(rH(Lk+pT9<&K65FUh=1$MWD+v~3frdQP+#8= z?d!XKvAWtrs;VUF@i19Ym@LaomKbGJqPTVYev_goX8|Z>fd2l0{Y_0#iBjT`Boa{+ zw#(;}S_1*4+3%O@s0^ujPn&)C$cY00yxV~lvxr8UYaPd>j^p|nqaCtL0*o;#%S?B; zlan2)am#T+p>Pm@yb~be@gJIDID%4e%d)7~>&p{DyoO@(&kD4aPGi$0h?2prU~1&{(9X?0P#IOr<#@tP2Ga3=}4qk z)&OYu6WqTQux0Z;?rGJtke2(PGL1YHC3RagPg P00000NkvXXu0mjf$~;YF literal 0 HcmV?d00001 diff --git a/htdocs/images/default/locality.png b/htdocs/images/default/locality.png new file mode 100644 index 0000000000000000000000000000000000000000..c80540b027830140c9638ac71fea175e604e4eb7 GIT binary patch literal 751 zcmVrK2$G&+uqi6(eYcU5)I!kZZ9DsC+J8oK-A$43>F0g0bi+4Pa7 z{=I=K=HT*zfq|#&*s+^|8C>38yc;kr$$OpmVuZ+RncIW8Yvn^B1L0-G7uUCBefb`-TS`kK>_gUS(QDTyJ`C{ zLdqP!pBTcC5lKW#jMko@s)!mU%G=RlybrWha`tXr$-=2Ct6n;h#)4Un207s4c~xTAaf3gq-2zzO2{2pB#0oTM=hd3zeodD?>?q?K_|cVOtnHE zJgnl13Wck1>e?g?o18Jkn0WoXimHJoG%D}LYM2;rB`_$;)!VTZx@p5o&fhVruVG?p zl8)}K8N>Tmb$(f~8jA^2;r-YP7IbtXBA5z(;%~NYT*Lj#|AQVo`;m`+KDo<~AozwS z%Q8|*NDx99u$YKRQSpQjFcHj*_PGVy`P)r9 zhw1|+h6gY~6JAIJwDH0C0vHk#eUKNE_5qABH1z?ArlN%y5~2->E>tL8?55joyGzS< z+u7MavvYmu&UUx0z)4PK=HA@%o%5aV-a85v_VD4u8dg~-6v~xem5O0m@~4_`0fllSvL9JV-j7CY4Iz_xp)NBJ}t716%=ET3X`H zojU;E1Kq1Z)&R`S&AkM0`t)h_>eZ`OFc@U}_U-K0v4gE!w-OGA^SgKNrmwHByk>TG zmIn_W01N^xmHn#XZF+iISzKJaI59E7$jAssjvR4q*s$S4uh%>3^ZDZOc)X*hr>8F( zjndTARFzn3Yb(H~tHiLj0syyrrAm*-bHAmfW%TILqZ8-OoxA*hYB_%VIKT`rU8%6D z3dYCB1%PRq@zWnHecZToJ^Z^VG4w6VDoCf~3I>NDI$EdAc$wk+7E?v6B;lqb70=I#G z9GVnogM~sNGZh~tKR=1N_=tSQAe&iW@o@?>lL0`}H1rxb!lk0QYuMG(ODq;6kx0kFNuoZh*a}tCQpeQIp!L}u@pZbB%J~@dHg1WjoR8@7t zYyz}(RRj_#B}j>sMPf54#wKPlGg$=CP+!ZYjd1o#oJb^s5Q0pJzQ)EzhKGmg>gu`- zybAmYpGh^ zZ)Rj{C+>@&z}eQ3utha6qH>iNI_LpRF?~(x@h!y5m^rzw~bv= zcV|}@hGC#63fs1AL)Z1?>J_E@?Ck7xQr=kI1KUCtG8A%)G#V|BJD@=QsvamvRYM3jE=?!6v4L7uVw&zM!8w6Kp%B0qfNXAVJ~cTx ziJ~av^ZEZd?20y$BC=S(DipACxl&IoWYGfPm!Y9D9RP>kXg_)4?VYEb9c@__LqkK( z^g`7=`|~#+Gx6^@*@YxoGfOU)C7;bwu!;y2YCJlFqb{ypyM|#HXqrYa7z7{|i=pc} zV`F3N-@hN=J>bVOz{`I9g};;esb@LO_U_%wz`y{uy>kAA!(pV9ba!_H^a4KtcPlGU z02RGkH`2mS!=0XgL<$v$b`1vCHwpw8jEbm`0k7Qlbjm-bPI SUk9fE0000jL%;Pn)6~ zp+z7;99L)q8&6i(@;pDhvS!nc7x4PcUW2hXn?r(7S4e~~4wNS)&tLR1=iDr~xz%s_ zpCYEMNeNI9QX-`U1SCOHp6#ty*-X@(cLimD^%ZdQkQYW-ZbURRu<80K^-R;In0T@uAMdL%H@{m-*2~J%XyJ%VN zE@#($GnW&I^uH7h;s`cp6e}0&OCWbNaqnkKr2DFgq@H3 zGts7?ud1dvE>`|~(zIvbA{ONS6{SQaYpg6)B3o60TPim(N oN=PK6hSf)_xH~Spv5tS$Z>|sW3LxX?DF6Tf07*qoM6N<$f^GL0UH||9 literal 0 HcmV?d00001 diff --git a/htdocs/images/default/logo-small.png b/htdocs/images/default/logo-small.png new file mode 100644 index 0000000000000000000000000000000000000000..6fcdbf9118efc3c68439dc60d168859b47631be1 GIT binary patch literal 7053 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ΜIY1%$PA_VnIQ{ zBYwZ1g%D&IhNDzdefyVSGY+q${L80U2jj9RCpX)5jPnKn)G4KoDBp^Px({Su35(A@`)m^cEX!)C!4MI?`s%BdnVFgH zs3o-q{PwsYgy3jt;Ak=6-)$i%E-L;`GdGZ+8M(PRi;luV{?5z=Y>){c?&tbH|NQf~ z`|i8VpX)bw?p!QbumCT={Bjco-)u2?d3m?=>eXx0k|j&pgtE<6)W+@A)YSAUDJj|e zpX%BUb(Hi6L1G6p*BzyWJV``XGxOlX>3{d#cOUlLLx&EU2thGDEHBCWMXdV0Ds zd-iPf@8AFWZr!@MTUq3u)YMdeU0vNk$8n-SYkvIk#|N)f6zwePD5Z;)R{p%a>?3|! rsc7e}R4JraDMfktxx4XOJM8wqo`@$A2&IMu00000NkvXXu0mjf-X(=D literal 0 HcmV?d00001 diff --git a/htdocs/images/default/logo.png b/htdocs/images/default/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..a95539ed7e943e90e624d5579415eae32785149e GIT binary patch literal 42594 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', + IMGDIR,$this->getDepth()+3-3,pretty_print_dn($base->getDN())); + + $this->javascript .= sprintf('
',$server->getIndex(),$javascript_id); + $this->javascript .= '
'; + $this->javascript .= ''; + $this->javascript .= sprintf('',$server->getIndex()); + $this->javascript .= sprintf('',htmlspecialchars($server->getContainer($base->getDN()))); + $this->javascript .= sprintf('',get_rdn($base->getDN())); + $this->javascript .= sprintf('',$rdn[0]); + $this->javascript .= sprintf('',$rdn[0],$rdn[1]); + $this->javascript .= ''; + $this->javascript .= ''; + $this->javascript .= '
'; + $this->javascript .= sprintf(''); + + if (preg_match('/,/',$base->getDN())) + printf('
', + $this->getDepth()+3-3,_('This base cannot be created with PLA.')); + else + printf('', + $this->getDepth()+3-3,_('This base entry does not exist.'),$server->getIndex(),$javascript_id,_('Create it?')); + + } else { + $this->draw_item($base->getDN(),-1); + } + } + + echo '

'; + echo "$file
bB! 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 literal 0 HcmV?d00001 diff --git a/htdocs/images/default/logout-big.png b/htdocs/images/default/logout-big.png new file mode 100644 index 0000000000000000000000000000000000000000..393598b9f30951de2b8d48f569104eb6c69ebd65 GIT binary patch literal 829 zcmV-D1H$}?P)QQFHeTbIxjvNAl}x>?!!$)qY<>uMc3Zm!KqUxb0S(0u`n&OWR~W7 zs%7cbQ{ru{G&dh1olfV+j~_pg1BiuMS(>s-^kFj1v*C}cQ-(j%77WtTa*XTOJLv80 zqr1C{&dx4G2}%o=SS2%%_164dpg)nIr>6_Qe+%8+U3r^w6xz`n2SkB>;Le@f1OnU1 zWZWXVQi9S7Q568a(I|6&h&sT&74e%uBr-@%O%1M_DLv5)1H%BzGO@%e1ze6qN}SFW zh(CV(kYI2puDe)vhTp&aK(v5iAWAT;-?<~FFCHz)q^lPOvLApx;Q8}W>g(&vM*gcU zFE8f~J;T5h6H&7E9`vnz8yXsLUAM&Ux-O|yiiL#*w5_lmjcqGzTVt&U0PF|emJ^P} zVvLQwXK>^J^O+QZ+U-T0}x3> zK~#90g_PS$BUu!NzpC1asjApY3MVE+8H^GGf*=ax6srE`v7b0fB)-XY;JD;QLR=#d!C1BnrN*_@a_J4 zXsu^#Fc@%mcXxh!d;6P|@#6CX)$q9Ag*;p69W#vBB!ubU=WN&W| zAq11jgj6cU!omWUWf4UY0Jd%8I1cG_no_BR)|ytUMY&v_sd*u#q}goZ`#xJ+Thr`^ zVK@zz$z)JUp|!>|&8gl(2y(d`qtS@d(^H+AG-J(N;Yy+@-F zQp)LF9LG}~lO$P|g=v~Jn@wu9+9Zmi5ugmmaeiN1T>RCx?X=d~{BSgqq$W(iA3jO* zd_16oAfVsxKPaXC1a1uAXW%Db9!ULgQ2aj>Fao{+UyP4{E-(iq6>j{y?+>9rOaen- Z^f!rg&agD@m!kjx002ovPDHLkV1liGn!x}7 literal 0 HcmV?d00001 diff --git a/htdocs/images/default/mail_account.png b/htdocs/images/default/mail_account.png new file mode 100644 index 0000000000000000000000000000000000000000..6d0dc922a0dc4496c8c26f3621ff5d936229beb7 GIT binary patch literal 993 zcmV<710MW|P)T5Edo{`z`ot*@ZbXt1}pSGJ19B8!WQtgNg&TwGkFSS*sy z=l>!4{^8zUDTPuBDJ4=$n$0HL+uH;|P_%Nn9Ajf+^tf8BqLgBMeEeTs_E<_uyWQsO z?2Jc`9#OB?aU4e&mSs^W6zK8T*cjzmB5aJ39!{|c@(RUk$A&(zFCJaMHM@P|G z3&S)`T-T+?Q&UrvN+s6T)~MBLeRo2LD~_d~MU1OuOC2wrzah$93KQTUc6a zMlxppi;vQLweSHc$3z1t&Bh-QE0t4*hK5*OU8URYk|YU22y(d`Gcz+xOiZx9zfYl1 zAeBlXr9^9urIh044KuiR%fUh;5`_?;mFCuCi0`Wu8U<^n5Ib_#{jsli|2Vb zjzghPKx@tJ?k>~Q(*RgfN{&MH%k#eyGLB^Jd56Fe+#R=R#)ACEpOa3fiQ|}bI*n2a ztu=;W^y_U|7TIi;R;$I<))sHxyuqqgs~mO%@23}m8n8oS?{$|U-(bXt-_LJw9EFJ0 zRb1CaDMgYbBuUb5yE@&X-25%qd~Uwrf3j~7jlXd36o+_~u^k`B)fTR6cW zY1aib-+uk&yV3g(VKka8no*mMlwhSGm0|YICnRPXg&=CRX*65^M-zaz1~tv5y!k_h P00000NkvXXu0mjf;yKpm literal 0 HcmV?d00001 diff --git a/htdocs/images/default/mail_alias.png b/htdocs/images/default/mail_alias.png new file mode 100644 index 0000000000000000000000000000000000000000..4edbee4527385866b777d4b26bb1e10f196fa090 GIT binary patch literal 938 zcmV;b16BNqP)^c8&?#?e{bg5^^6Td9uW4(bYY|#x23B#i)KSqbycaWO4(GEsOl=IRH+Np z@(I#!fW(qr$p`47K`n}8L2H5pPGX_{F)=ha;1HNGW6XHwb&-w*RCJLmU7hz9@4R!* zyZ4ESi3y6uBDGrWhhnjK)3PiyO+zU~6zA8MLn(D3+wC@6TU)=%LZLvZRAPR9{${CE zqEIMc+xCA*&mWHVVHgsIA-?b9`#vWpC#|En@W z-}gB^J>}@=h_$sfT-PNYj|)voNiLTo!fZCn^71mS>mr1>kea6TQwY&l>o^YU>+3j< zLnf0!DJ3*r*D(x(2=npkv#e}`tXiRXEEo=3ag#&MiJ>Gt+EBO@aihCwo! z#57HGT}KDJ+h5)OPH1rN=X)&uvV?BvTzmf-1EVP(Jo=6DQkl2jd>bJIolXbWb*WaX zv|243$6JY@I9E2#V-r^Cw13I_)V2ta*u>thaD&n}SJ`B4yxy?TS+%Ppp-r;$<; z1OY)1^v65uZ(Y~XG>y&8P0HnRO8{R-WT{l@RxB2i?RMM#=*t_a!@VYt%8h5Q>E;#? zUjCTQ56{0BD9`h7UAKN!^>;t~^c@w8>pubmS93VS!P@cil)z4*}Q$iB}d>0za literal 0 HcmV?d00001 diff --git a/htdocs/images/default/monitorserver-big.png b/htdocs/images/default/monitorserver-big.png new file mode 100644 index 0000000000000000000000000000000000000000..d40900d98abae5328e1c2700891e8d7e902097a4 GIT binary patch literal 1084 zcmV-C1jGA@P)WFU8GbZ8({Xk{QrNlj1+3MgYKATls8GayP~Yjt8ECu(VJ zZDC_4AX9W@X>Mh5Co}I@000AjNklFZBx>O9&-t_^ipF8m|jYaF(Ot?Kvbn*dD~bk zMX%kp_uYebRjpQSlN>rQush$*{O3P2-)soKoCXSgHZEU&pBIsP_rAF(^atPH-zS|; z1K>CgSFc{-#`OBZ@z-v-Ri~n#~qxPiGk$9VPR|5`Ub zPXz%0QmGWGss>nia{taPS{i&Gh1+-UcZ?1!FTdUWeqwThCx3{80aR6`*=*uCPS+t4 ziFD6jdj(!j*;JIU&u?vQz5ATWoa9(49t1E=lUOWRyrg z-~R-_vP>>qSnN=7)c{3{2A`m&@_twMzgz_~LJ$TrM|o>bzq40D4Q)+XGo{bL-{}KD)V! zLvXU{Ppbi&qIOt^dgGT$B?LjB(P-c}4yI|cxw%Q9@aRQX#T6gG!NGwqd($-0G>u3k z;$!4E4zXAaQ50ENSm;mGC%zKdw#~-I2BIi3Jv~h}n`LBVq|2yR4-XG%wOaqlBG7|! zxlA^jWqW&@+1XiItrnsv`j|P6Ln4tN6bd~*z|71HTU%SKtgH}^$4MrW3=a2w-h*GZ?-G@DHf z!@x96EX(STWBn6@s0ZK$k4B^Dy3Wzj5td~k%QCvIqpE5*ux;DD7dP~842}cT>vbxX z&JJlb8Yqf_q9|0WRb*MFR;!_D8ufY|S(ba_i~==48C0qSFavz*9zL&r;{MOaykY5; zkgEwG1;pKV!EL=4TLHZ&p-oKrThFZNQjs=G~@rjbXVZ$&C z_yZrU=a%Lgo7wZc0BFCok+Cysoruk>JTZj?uS%;p+*uOa^lv!1m<07L?4?q`!g3HZ z^0tTlp}b{!vuIS^qTGQg*NWC);jGMc-5>DPq+vBn`@3rzC~FVXzroQH2d}L#C;~|R z`RB=W0%1z;ooyW7`?z^%BX^Wj+rcOkixR`ePbs@;s4}T=UI<>9BInga8+luVs&yaE znFG@_kzP+j^f@f~Nch9oN)>F48RQf^1%l!ZV002ovPDHLkV1kMU$^`%b literal 0 HcmV?d00001 diff --git a/htdocs/images/default/n.png b/htdocs/images/default/n.png new file mode 100644 index 0000000000000000000000000000000000000000..a035c343c36c323fe292cead8ab5acd3cddf2f23 GIT binary patch literal 408 zcmeAS@N?(olHy`uVBq!ia0vp^LO?9S!3HE7rssMADYhhUcNd2LAh=-f^2tCE&H|6f zVg?3oK@euFPl=xh6l5>)^mS#w!on$PCbV|FS$#=GvOEa4?2#5M4 zCL|;@8tynZ=lA&o2M+u=d!%E5+KMPPAULMp<;CN4h>54iVEszV>c92klE;8b4*XD4 zWn8YPR4n#KJZfK8BM>}{O_5M$W@bJ-dkRa)dPmVe;xjilM93dxbd#8vEphFD+Hr$9 z8`ZYdh%z6)n*BeO>$F5&&40&zjyymRGku)_5c~;Wxk@=hBCL7e%a;>!fbFVdQ&MBb@0H1D`bpQYW literal 0 HcmV?d00001 diff --git a/htdocs/images/default/network.png b/htdocs/images/default/network.png new file mode 100644 index 0000000000000000000000000000000000000000..008b03fb2953db89433c0835d7ae7d5eb1a1f67c GIT binary patch literal 1107 zcmV-Z1g!gsP)$S zK~xyios(TmTV))^pZ7g)d-~n-A+R+R!WiJjG>8LDVWVTTqSL6D$%REPoH4u5MH81L z3KiYdF`UsDP4of>8eK9+GLy*`-HNhJ5gE9y(Bb4m3basYOIuD4J;w{fj9wV@xqb3~ z^5psFNAN#%*!6lvXem@dDEa)@+wJoJ!2Op1*CCgFPyL>HyQA*pu3fttG+NE$yh6eK zGBh;J0KoN9ix~i0J0OIBQaba>8_h`ocb!$oS3Y!-pLov;b%YfYLilyR}N4?aI~*NMFcD&$$7Z zGopCE;|nrexA$8M3ek0`d%tgd>@Vc$HM+cLG-@Xxh^|CB`z{049R{wO~` z<3Zn?A1aZesCW~`Z%n^KnNeV~q1n9v5DBStKm2&+E=iUkW9d=~tE>NHEi6X#C%*m} zCvzDvG=qk`LTr&`jz>g$i!VW1Sq9MiZ_w&F9?6sfi710QCl@5k1Th$fQlfu>x*n;L z5^Uy7RHvID2?PeC37&8iVFnvnZ^%*Cn>kFwpZDJMmeLd;5e`&ZMN&**^qOb=jbe#J zrNg$Pw4(AJPzmsidU4L(gW9SZjE#<9-HqODe=q-Z_vxNgDpe%QGLm8v;AC(d2fyEc Z>JN%ZjYwq0u5|za002ovPDHLkV1g3I08{_~ literal 0 HcmV?d00001 diff --git a/htdocs/images/default/nogo.png b/htdocs/images/default/nogo.png new file mode 100644 index 0000000000000000000000000000000000000000..cf1a2034f0be5f4d6ceeb0f6279b9a3a4fd413f1 GIT binary patch literal 243 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt^DJY5_^ zDsHU}cH}yuz%$3=zM_ukr@mhW|2HNG{_*&hQth1F=a& zK~#90os(N=TvZf?zkMzG_A{HzyDTD;kJO#WF2;@;AMXGrc z!6GR3MGJxwpHvWhC{+xk6eeJ-5=thWU}}=)(pWn=<~EZ#`{F|~Gl>B~f7o#LhV|{W z|MM@wt_B7MI@;UYzfnq6^B)uh!N|pn7heSa+I#MlK5W|_>gwvM9vvN}P$=vx7D9jk zfdB+T00>STf0V6!{tR#q_s#=a5Il_i?aJ@Qks!1dgw6rwS z+}uoabDW>X$I1Vri31&%Bt;dk_4Z&}7FW|#MB+7U3xSe~`7Mx2;kiX#$$vsuB8*%f z;nJ(;z8d`e2l21q&HOgkZ)PzDa%*|C5oo25QlXS0kO95=QzG|o!Li2)e#_GKz~bdM zpD`wEad+xIqu*x50kAfPa3}&P+bF3v$oyQE!Pa{Vvu*eMBQkmhR0HM89X#N^`tL z<5ml_5IneDf6!xN%+3-9VRoP;P0!4s;%^hGOK|Fhz|R$!Uer8!I89{rAvVUri%2$p zPVNVXLLttdega1?BQyj-!1ng`&V|5=OcEhVqEQe8;QzUaC}ud{y3Em34OMkEo@;o2 zG_en?tHM?E_q|@W1+hC4I}^cMAOC_1ENYx}X6M5Axg{QJPt#Ou(NdqM;Sh{XHu2Gw z>y=cDjg4K3L?V}4TU%4MZCBuXbovp1&oJ6>>*g$uY~WbUG7Yr?&jT!&U#SHuIX>Rm z+4;rUvu7Kk(I~cUBZMe}jj1@TwZ<63ndc2!YuKu3c^cbM+%^iLsBybUOQ~4UE|BO339-(i>Y5D#Hn2rP zVu4`C0d7xejjS*Kh@&E z+d$nxZjqZt8g8`VF>-6qAz8U@f0=RSlVEK8^G?9fL2?R zQjk6UjIFO-@<2%Z(D1mS=}k&pOMuaQK2g&%>&>h-B#*1`2jIHIKrgQK9BwZ%YMd4T_SVwsc#Z3u!0glO&30LFlZOiJ>@`&ZnU6Z<9HJ>Zi`!#iJmFP;Rf$1Rp6`a~Fn zXeo&FpGiuB)`rV3jFMQLhEt;i_ZB$0Eg5_3k})yK>iibt-z<MJXh>M8D&9&m4QpQSE`j_wdQ9iWmmb|0Bm%a-k& zHHmcRPi4DN=-T%zBATIQtKQP`g?G7KcBwhn=}qKW-&`T+{f>s5;B;1FCk0vvw(oRe z6)#@70nnYvKP#;`4&)j?dzn=0g7jiAsUJ zNr)#x_I}M{y?pic%K(XvZVnCu9zD!c-z=cRS+=*oOvV?==@Wz~7G9HY9k z&Y7VJx;rG<&I8gt@bhdpAAfdBSO@-L3nwH(2rS3N4+1jz0vC%z+@8KqdUXyr`8BnD z#q!i7R+#2gYJ+r#ARcd>$4a@Q^$(lPpmj2`1r!3LWmB48;{3=krTHbKWn+vc2sGJ| tvt+bpcB&64Y=#H-m|E!JgHKBW;1Au4U;D2T`V;^F002ovPDHLkV1jDC#4P{- literal 0 HcmV?d00001 diff --git a/htdocs/images/default/paypal-donate.png b/htdocs/images/default/paypal-donate.png new file mode 100644 index 0000000000000000000000000000000000000000..10d56284259d1fcf356dc542bfeec9dac40dd9dc GIT binary patch literal 730 zcmV<00ww*4P)>6E9vA~sC`008Ru{Qv*|onT$#0006tNkl!SVF!!F;MjhwHHd_2o3tnRhiC*X^48dSKA+Ej z-LJ`ur5*^+SIda4%FWfh9duW`PHJN#BIYWKhOWsOakDtejacHOvSo!6?-IRG&0Wln zTOcbQXpG52HkO6~8fF_cvrNTeDZ<3gq_9~3jEu;jakQu_pIKiWqZPBc$-zTbN!34q0wZuC3R$}cbEU8yfk`QTkPNwI6 zlKmhzj5zNT4Y8AyS)ylrt3v2%2&NV;n~du!SZ=1FRlV+l!LEw~?-RwP2*zbJ7+6ap zHc|s4xnY^CSzH_1ie*v#gy@t+TXas|r;x&EPV!2Ud5dLpi1S{Dv`IZ7dXOWiDvam( zOMR}jPnvKkD|g^)^aarYlw(B4^@Qjm+8)x)Yum<`+v6b7Wo_5~av$H@QKGfo`t^5% zoOgi^5%B``U7`mcebCJF|M=*8QIk*C>yPC$06P8W=bGLC;O$rR4x;M9>Wq;++W-In M07*qoM6N<$f_JoQM*si- literal 0 HcmV?d00001 diff --git a/htdocs/images/default/phone.png b/htdocs/images/default/phone.png new file mode 100644 index 0000000000000000000000000000000000000000..f319d1a62b9cd97892f9a19bc27ce5e739c86092 GIT binary patch literal 878 zcmV-!1CjiRP)J$}mwW&K0{cls zK~#90MUc&I97Pm`zpDP3nV!kac))*=42s4fN*34)oIn(TH@pTbHtg~W?0F6rY!R!x z01^rth-1kSLfFatxINvTo}TLJs_J6l7_M|T_vq@J^9gQ7Jo)^K;r@91;PmwL>qVB` z^}Z2t9AAHO|Ne`U)6q34<9~ye)Rb0n=ijQ9y#ZP5CUthU#*tk z#qIXbl~O;vd;9iJzyt>e2i=3i!*8EHd-i-|^x;rzEw;8c+1MB&Wgv`eTKnVi*jX1( zr;|UFQrE%p@$u%z_wIc^9`D~N`KonYQr4S;HqmZ4=5xs80?#?Dk zRWvr_v%^PJbV#~M7)4PB2tx0@5CQ@zi9|>%j;QMzr4$HHyWIlcqShLYSW#sL8)(AFv0Q4(Qjzpq;JH~K zEZ1w{nugw;K9$x)0n}b%oj}`$xH~{;gE5AxQa4Y|I$tactTF8F-o@4>8>0`1<2Gp= z5yV|4lL^z=3}Y<-(l;JmY2HmHESJ}WQJeL;=ISaVj60NN$#gnpSuAOq=Elk6g|0PO zo+A(x#fpBvPaq{#rKz++DTTH6|4st$z4usasg0&s6;xG45Ckl;j8+^|mL=Xb|B(or z#tUaHc+X%kU|p{1CLMwxK#u($hkJ2=yX*{Z`2*ZHYszg_c zvMjOII%7-&ATQIjDpsr4LO_xvbd!Wu9FcT7wBndvuZ#Dd*=#nsoX=Chg?YBf(#y-A zUcUVOqn(}YLA%`+08&cox~4XUlUJ|QY&QK>YkdaP;raRb3ivV4GZ#hCQ}2D>gM1$! z=bT<#U7gM6^Iw27z>4>p1p2@hkN~%L00$I63Y0+eFX~95*JqCT+yDRo07*qoM6N<$ Ef(E3R;s5{u literal 0 HcmV?d00001 diff --git a/htdocs/images/default/photo.png b/htdocs/images/default/photo.png new file mode 100644 index 0000000000000000000000000000000000000000..f9574048bee0d664b73ee2cc800474bed183e759 GIT binary patch literal 572 zcmV-C0>k}@P)!DUf6tbscxxEkU^_yD|v%N?&K#CRt$@nO7ZLW16m zxP+KxTv%pydV0F5+JoQy%RYa6KiRJ~pH9lW0*nATL-L(S9Ga%Nzh5pE3#h7U@8!Ny z%6l&<4HTKh7^9TRvTSGP`DipkP??CFpMSWz`k}IDUFkz`b}fd^dq15{$Kx^lA4K$U z{}_q4wqG0_9g%S8`);*DojHq`sZl+)K#Cwm3B9fG#(P%9)(?B6F++AJQf9K(LrBn*OFAK+!lrS)pwN`6QL|SW3 zsjh2dH2^TPwKgdR4LRz{U{)4Sx;D)J+`KzGJ2`o?>XyEX8ImN8k_k!7v>JvXGF@JN zpU;;7W#1){fti&e)CTh0Hcc~|&7N&-`Yv2te45?-^q!MS8VqQKM8ruZdy`kkwpw!{ z^7Y#nYvJ(lKq)B8atMMc>D-m4r*DaJV-;Eqt3J{yh15RA#^24Z=a4DweK3ec;SfP_ zaHX}VHIj8YrNo@DZQFW&ho-S+ouwC{q34w15d89?@8e_Jw*LUW78*~2H{1CD0000< KMNUMnLSTZjEB@vH literal 0 HcmV?d00001 diff --git a/htdocs/images/default/plus.png b/htdocs/images/default/plus.png new file mode 100644 index 0000000000000000000000000000000000000000..f66b1a80934c34bf818efa50824d96bc138f8e04 GIT binary patch literal 102 zcmeAS@N?(olHy`uVBq!ia0vp^oFL4^3?%3Nf7cA+1o(uwUbyq1uDc(|YY$R;1f(Q9 vT^vIyZY6W@mL@P9X5;u4)tJz%5Fp1e;Rpx2`?oLpKs5}Wu6{1-oD!M<eb9CPl4OP;RS3Qq*fTku|cbLIUzj z0s!*+6wGESMMtG$?TEcr695o$fnX4jrSaCK$84r%f+OSt?p22Xiy;0g|ItsuM#$VV zL8-ZPHb+vA_?W{vJ4d7Zvnw+H5ixR>rG@<)57B)Wv6#WBdnDr=9)LfGn7&OBJ=_87 zQvXN*02bW=vza2Jc!Wl|sBVW``;u34@&57zKN6_67t5_&dZeNO%w|d^31Trrwf&FC gqhScA?xm4`11O4oV#)QVVgLXD07*qoM6N<$f+^Co%K!iX literal 0 HcmV?d00001 diff --git a/htdocs/images/default/refresh-big.png b/htdocs/images/default/refresh-big.png new file mode 100644 index 0000000000000000000000000000000000000000..22fabff9ed8de6e17693d7eb7066db8ae5b27365 GIT binary patch literal 1072 zcmV-01kd}4P)XVg?~q@p~S*`P98Hr=|G zqWoNdATSH0B$%gxqk?f4a7lu5`~upStCe(zy+KJnlRV5JmVYfM9<74(lyvF*`HM3Y&` zu=vMcd`m}X56yM80CxbRK*|K}-%wRUP31-a+PeA~7z<|vlE_U%qm*LwQixLxdjP6| zTwq>KQC9oZmhiE*3pCdOum$)MNNeEm*5_)eC=b$fx|6<x0&Zx9Qi{P)w+H?J zupm7R*uWe>ZXk=TyY>To3KRfYCcvHRZ=$Pzj97euzXmUIrfL5b<#&E`l)>IE+CQ)J zz+=EP5C-x@OdG(^iksJ!d#~mLF%5A0x-!o74ik??Jn$XBy#T}gJy!#t6p&)6^hW^F zj!SMJ%OfxWLjzcL8YgXY;=ro_?*P9@gtRv91Gvu*-aYUKK7wkXz3J4?xUP%iI7>>v z1UT0_Oj${>xA232&B(Yyo-@GY`OpZZ#rfXeet?#ai{xaR%*-tijVG5BnhEgZ`7Wxf z?(ya>i-1X>P{gu6Jp=;g=?tJr?>leZ`j zuJYy_$qq+IVnF!B_dS#p<`GXMnV6m>JTpfm7AG8=XDS*eG(672qQy}6cK~Mu!_`0s zKuc=}?=^k{&?Ba13Q3~=_*u$U7m~8=ARE z@fI4LKd_Q1Ku#j*TO_OE4oCy}`-AD|_HSdu~4eU%0z0bH@=5=j*OZ#UY1A<6dK qQk*og?6m)j!2eTV$hWqywefG_nus=Ft-~Gw0000GzA9e2YRW7ghxrDu zu(!FQSRJvP2VNPHQ_H<$YEpM+M>KG9N6sP8NCX$Fk*y;N@%~BN)_xPv48*7-mR!KL z$&gZBcK>nGqx)qw*yyNnFm5YE)3)mFfC!0Fz$(~TZ`M&$qXFyZ$`|e2R^rEDp zZvj4-o%EWWn1=@GtSWVR?1Lph1EBmGB?MRotN_9RZ7@8SjD;m4YK=hvbwDkU39JO> z^V_Y+!A6?kTLQwO))-2|!XpHb7!*d%iuard<7b?g^Pd+g1%J_AcY%qJWzCi P00000NkvXXu0mjfRzhEt literal 0 HcmV?d00001 diff --git a/htdocs/images/default/rename.png b/htdocs/images/default/rename.png new file mode 100644 index 0000000000000000000000000000000000000000..320d2e5f174cf3af7c1b5559a86e483253a7f01e GIT binary patch literal 418 zcmV;T0bTxyP)F^cdONE`KCSRK6_m1ODkBGErh`4&LLa7 zM|s>@yS#!{tF@qbwOZwD`;F84^&H?nssm66p`db>WokB?ves%m9&0ojX*e8eFc_%c z?<-AH)$4TuGQaisGrn=Y0l?$&W8oJ51hm_204kNrf<}d>?7hc(Usx=c%lX`U&%@CJ z03iebN~O{lpxf<|BnigMHBFL)EXx)$O2Qa}wU$n&13*tZti#T z|DFH;ocmq)k4vm(QAPa+&ml;gpYZS;tilBSO-xG;MK5?9T=ezp?)HJs#u_QZ1 zH2OtDZTYr!xtVM!Euh4fgQ`j#E)N|)U88qk{QT(IH)?ASwJAL6qS*=*TJ0Z9Z>2vjLB85JxU3O!d`yx;osP(bASl`l6TTxYRFCst3L|L(wijq9aigGAimx(b$#S@58m}kM`3+6-%pV)cn)S)kz zYsqvGDMHpYJYI=G6>KZbry$RaK~)e!U{Dooxn{Q8t$2fR4)3qQVlh6ol1^H{daE%W zPwHq1m0_2U*?EmvJc+LB#NtW30gchgIaE~=(V`fQYW7MxYC3>Hl_P;rwAw5*;hBe< zP7i%UPK5aD*s3ZwP*#$UswnvVVG8v9{Q0JAaU+`x^g%XfWIq?AWWP^>>I3P8{>S|c^U6~@c7NnH(hH2063@p zZ9o1tN={amF3{0+oeKlE*z>?<@(fW1N2c}RKfHKm1MTTF{sE{y*uMDj{eI@?U;?#e z#4#<3bK)ezv+UdD#zYWBXlTAZ5s4*VcAR^AarX~3w~JMcimJxejKQ|1*y$5n-?CXe zA1y4FB8d<>BEyCrb2H|*A31nz@ZY(4b6^MDKzO;6bbt&X3n<+Ch}?0!Irpn{8P+v<_X0D(6yOIE zOCk3H6aa-lrhQB0k@{!%Jw56eXY7^>EfW5Ie01alpaCA>HsAx|s{u&B2xJ5KKwc{6 zg&&j-B!L(Z0A^E=P|CqQZ_xroO`U}$^%zpUg&4GyXc&krkLQ1>KLK_xgU+LC1OWg5 N002ovPDHLkV1lZ2^SA&2 literal 0 HcmV?d00001 diff --git a/htdocs/images/default/rfc.png b/htdocs/images/default/rfc.png new file mode 100644 index 0000000000000000000000000000000000000000..531caeefdfe241f01d9cb2cf688ef5c2afb90892 GIT binary patch literal 637 zcmV-@0)qXCP)miGn%i`6aDa%gzrVj0c@c98 zL$78*_yHm$;%Aw_Xp8CG8-ELO_9S(;Y1c3tD@Aq{)9xI?>7%HGq6lomCnj}ea z#wVa%x~O1xUAI(padAPX)1lYvl~wlpeU6Wh%S!9@dZl%z6ig-)bzN6I&r{Fy6wtw7 zFg1opqfxm&Jw4Sh4E6ExQKKkQK$9fVG)*jf1De@+x!)>@)@;hBtQT-fGhc7HK3l8z2bS10WmNEVwst&^33YXyH(^r XTu25@-HTn700000NkvXXu0mjfCl4p} literal 0 HcmV?d00001 diff --git a/htdocs/images/default/save.png b/htdocs/images/default/save.png new file mode 100644 index 0000000000000000000000000000000000000000..a7811a44fec7051d9c4e797fdc6a7cfb806e606f GIT binary patch literal 658 zcmV;D0&V??P)O(Ei9UoiK zTc;9b3QfR;IZ{gXCioVhzE;PBI~DLl22vETNf~0K)+$hvavo#$`YjVd#x8u=!cQEywyMlD{FPEEuE}Pxbm1GTR^$=*wRW<4lxa zRV^%2i%gLtQ1Q%IG2FApi)tD=NfAaNJkLXYtB-nZ5&a>_@Hlh4lN*({J7K`H4;xr~ zvZ2A8bI@}X(ICRRJqFj7otKVdf&?c;Q=ZF&fL?HA!=%P4R-FP+G@Yy|G(n@;knT^y zu9Pdfki}A(??|eTWLf{nUolwnMHQwlO^vJfR}q6CunhR=@{Ck-bap#B4X5N_QWEfk s0O4188=p)+6w>DmMWSQ+he_dZ-#s}df;1F`LP1?crfDW>{uM404Ce7~NP0}`EF-jqg8f*k(tu|?! zP)iA@H8u*3J}9(rZG9;CrVkY<7@w*b8p;Z#{ws(r6fD#vV7FkkO&||_vm{tZ)1+qa z&EDNRGd^sxO_S|5DtIo3bLTRAXTI;unYr*k+M9s+hyD=|SZx9`Ha2El*EJ6_&-2WU z8#hdEZ?6G{fG{A+fiC@MT-PNQi>+!knM?-DvIvDjG&eT`!~k!BS;^$mK_zfwOet!u z@jQ=2B0)n#0|NsC0P{d}ITQI%-4+0~R`TZ_xA(1%ah2}121)j z<2Xbj5diAy>ged`Ae~MFd<#U%)x;QMjMmyHrHto}K30 zxgX8E>zKj8!AiU9Lm;%G$i^6y@-YU^p8cNV$B%LF;M=seK854BT)A?MGiQF_=+O`8 z>g-~AdK$;cGBG*Htv_#Z{rV`*+!OE z`1oZU$0eI}X=r$aix)?jnwmlifoig(}$3XdtZQI(&WPYQm=`UP&9>;M> zChKWzY+}cb7s=&vc%DZ-?;)i`YfZeS2FtQoRUdSB?>A5C6oaOTPfn*7iI{4j(gxB{0vgc zBBN!bWZ5DsMJN;^9npC&*^AD5by{5Jf;Kiz*5sN--P`lT0S) zXy3+@&6~*Oa?IYnOI1~MWd;)y6C`RZj4>E6c=*kQ-mw(0z3k0Gh69}}?h|*{=vB38W6bc2rypI%u$v*=8er@!Dcgy~Nap^zE u4+HC#AJ=l>1gu$j7ysc8B?rs`xxWG5F)-)yDuv$w0000=MH literal 0 HcmV?d00001 diff --git a/htdocs/images/default/server-settings.png b/htdocs/images/default/server-settings.png new file mode 100644 index 0000000000000000000000000000000000000000..4d8f1a1e6acb5cb1bd7138f30be7f5772188806a GIT binary patch literal 1149 zcmV-@1cLjCP)RP%G!BQHE)NWj~ zMXAsRDK6X6MK=|)h?}mYDcXe=L5kIwk{A^&n1PH*W+o=@&%LLM%nUJoNzH-7d+)w; zzwdtceD6L*a72M7U|0G1Prw0|*Qwuh3<1CO?B6Hbw>Jy$Bk%zb+bmFMo$;@K`2M^8 z_O|URo!(8dW=r?fy$5r^7%NI%IP8G2FEW`-|HB89a_g_#)YsM1*49cQ5kJ<^kv^78 zCaZ;7Yi4FFeu5L@>tSx-KIl zBk!F(dp7*&(W7^Qu&jWwpGHSVZ;27Ttue*Ie4g8P#z}X+LVbNbg+hTsp+K=%#Bm%B z9y~}Ym3n(KTl5gP^7)rv(cIj$w^S<8($Y#IkzjCekeZsU?AX!5p+ko_dh{q-Ym`#! z;Rh-JI0>BGxpNmMPJGDe)29iC!@SX(<>QY|U@6V;@HgDQf1kz0MT{|TM_+cr<1J|&;e)7aR^nKNf_T^A9lrssKx2-$3w zR4OIL7y-oheepa`+m|n2UKWvY-~sSEumwmwdGcgmXJ_ZPckkZC^E^tW5?x(gLX<5$8l(CYQk}x zN|T-P!k+8+hBk$j6LV>4iRI;GM1)u@MkEqhnQU2WE&3ljZAef#HH|TZLLq$Luaau5 z@qHhybwxqoffPibSosk}Dg+`@-4@q%tBNY`$`L8gdyXiGAOs|UOy$rEqF$YW~utOSM{ST-PNMiBv%y#~~C7k z2HpiaRw-4h5>}e3fvdo;z%#)AKLW~tq4KKiRds8x!ivRRz$@QB=cIoDmJ8@U{kAEW P00000NkvXXu0mjf?X@7& literal 0 HcmV?d00001 diff --git a/htdocs/images/default/server-small.png b/htdocs/images/default/server-small.png new file mode 100644 index 0000000000000000000000000000000000000000..3d1e0f6f2d001067cbcea1886ebdbc288166253b GIT binary patch literal 818 zcmV-21I_%2P)4Q_ zK~#90wU#|g96=bzf46TJJzv-h1Y;XWagBwQkeEmy`Vp-C0M<6aGTk*6rm^)igg`3G zkm|rngMx$@WIb1J?{;@)pA^n6yXSerK?a7~nc4gQ{?9Yd3=99c)t*?lflp)BkAUx! z!tH~DgCniAD5WGx5{ctj`u)B{Q6#-yPxkls1^76T`p(YIky1*OQj(@=0T>Jh6-c|? z7U08UI?iJYmSw#;J3GU5-C{1wG5|z`EX&YZv%0zp@RmnX^(X+q^E|GvuM5E}%Mg)b z97Pdxb93V)#sktcErf@~%g~7cBErqh4O;6$c(^;xSbt9gn$0Fjl2qK6dmP84X*wAI zKq*BK1Y`HW_x;Huh@yyIuUE-?`8kRr=I7@p2l&2^@B4*Y+qNqpfUB#k$p8SIPKS$& z3w+iX#5b7uYVc} z))ubok|ar`n#%Pbh9R4qn*d)H78Wjn-@qyGt5&Q1agL9VyTC1Q!u{>(0M7dQ`fi^4 zQQ}%_9LGUK2!fyud=7#@0UAgF1!xDbjIal|z%yVDKx>WGx^kk+XJC4II*-HyW{hxR zGME9GlatJXZC;u!yG@ehL5U_wLcLzk0XEPFZj7E7fH-DQ-aQ9slp|0|Jva+-92c8x zqMk9S&P*@F@>VlWT)-*Ux^3G4m21MbZ9LB-j^iBA1VWR6!t^k}GS5+`(>dMS+k2Hm zM%_gK=jZ1Dzs&zVV^Wnx^JW?MQ$xLO=3VnnIi+G8_klYT!JXMp83o8Is#Y53bC#JO w-m{GRBFT*Nyl5UokdH@wX$;TFm~mz8AC;p_HNj{qe*gdg07*qoM6N<$f&eym5C8xG literal 0 HcmV?d00001 diff --git a/htdocs/images/default/server.png b/htdocs/images/default/server.png new file mode 100644 index 0000000000000000000000000000000000000000..4f6c2a4db51da67c2ceab8c2c37fdc5d87658d0b GIT binary patch literal 1424 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 M07*qoM6N<$f{EdFd;kCd literal 0 HcmV?d00001 diff --git a/htdocs/images/default/terminal.png b/htdocs/images/default/terminal.png new file mode 100644 index 0000000000000000000000000000000000000000..8f072967cab9c40bde1c7a89ff4602266c15c6b1 GIT binary patch literal 851 zcmV-Z1FZasP)32-t&mbu=9tKQfP!V#iL=o&XO^5_qYdH)9K6ru; z1o4EZG_GZRv}Uzf5^pyFNGZ|u2PQvJbHu7DF(z_~Y`1?ijw7WMOxv)!v%)${R3&Oe zM4&N<22A6q7?KJ;cx(uPAVN%$>+5S)s};^UR?7u#+tPI%(K)0Qj4`B?aGj%R8XD7} zs;KA;q$&g-7{?J~4BcWeTcByEwPLL$+f36m7-OJ9tze8nL{Js1A1A!`q@4Nst8aL9 z^NP)8gQ`$Vq1M?~r4(X}#2CprQ%a`Pj7BAh&`iUC_nunemnTnHE>}Ey_=xq8m?1UnoCLJ&li^Ye3dyB$A2e$36yOU};DI6gjRzu$9t zc}d^*jN`~OO{gj*XHtr&Ds~tLBm_i+i;D|VN?2<#rsBQFImbATY`0rtj5CM`UJ@}S zQq05{v11V4d3VkIdmn+B#Vw^^N+FLEnhQB+j$B7+9qVpM$_mv`KX{L>b6^a17zRXy z_uqc&R@50N)|p9F$vKnroVAjnR7cl2j4|x{E!2uV91a|Y0V;r@mO?J&zu}xSDQC*- zz7%Rns79u7!Z}Nf8S~~Fcli9XPdPdLusY{hE>|qNj?OLSY{mJ7L{&s}HlY50wX3V= d=Gn6={so}?UiTi4LoWaT002ovPDHLkV1nwJbo~GT literal 0 HcmV?d00001 diff --git a/htdocs/images/default/timeout.png b/htdocs/images/default/timeout.png new file mode 100644 index 0000000000000000000000000000000000000000..529d8a4b9454b65ae33fd79c747451cc64e0de96 GIT binary patch literal 661 zcmV;G0&4wPx#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iOb@ z2r?vM|A#{W00I?BL_t(I%bk-yOCwPf#eXw{7JdP@NF%HZ5+MnsND3P*1PlAE{1AQv z8}SS1t{{kol^}?VNh5ZP4EPTeT(NKnlEz|$88gXy?`)F{$tt_B2M%1`yXV~VcwBgo z8n6Z21KmFF`)4)&fvvf@IbB^{DM=D_yIo~jrZ|puetxccy{^8|hiL5Y?<-AHWm%?P zucx=SH=UiGsnh8wNfO0zteu@50gZQ)cXxM{B#Anmj=J5hdcB^EF*-gzR+eQ-(^Rjo zuX=fT(dOpnNRnE$T2&m!Bh!sBGRA0odpl1sFle{iDwoRwYCf>CzP^s{`*|GC^YS{1 zqP&)r*K2EQ04qK)KRY{%q>+Xo2y%nrJLepdC>DzV^FA;&Ha12WhIykTj4?>!>FJ5P zyE`Odtwj=-mzRu>j{{8kgJ_a)&S9;^7=yJIYb_fa8!Rm?5r$zteK?T^+_ze-FB20J z_`aWW0OuTG7_zXiK(pDTR4QSuB~4SNr>B4U!0FA+4c6K`!Jn*DDm0r-78e(B&f%Qn z_VyOw)B|djO6BLt$q7La;CWuo;kX0gz;tiKR+`$IXNO;U0rPgUq4)?a=EOdqa!^& vJ}QbLMNy=OhX)-V9;#F-{dJlCYn^`sc%HeG7(1mS00000NkvXXu0mjfo+B5! literal 0 HcmV?d00001 diff --git a/htdocs/images/default/tools-no.png b/htdocs/images/default/tools-no.png new file mode 100644 index 0000000000000000000000000000000000000000..96a04d1cab952df906da9a7c824290c60524b51f GIT binary patch literal 798 zcmV+(1L6FMP))%Q5fn%!4!42+UDGb5N)zE?_QiOr03lY&vkw8=i<2%|2x6G zn2u@4#Xl&1EJFn@VhEE_jzx#qk|Of6p#P|of;D@H z&h=~KS>k0@1w}!AP!>Ga#?EHq_mwOEo=ybGn88y)I(YFuqPP3cNC=F-4w6hHI-8o} zGop>1L9SNn(^$QwjL3=R&) zxihE63?3R?bJKF-@WhG7g3p89!JeQo8Q}E;>|C<@FU!qjh9i?1_VZ6ilDF12 zSW#HmR?Xt-{{Ex$Ie`JRqZ$Q*r-#^EkR_fUB}d1O_v7n|ifAF)^7GFJn}hnGFqje;wzwtx6o^wNPsWb)_COSq z%CI`v8@xRZJ&iPOs9h*EuSV011#XyBs9@$?mrtL7+h$i*{&BhYlJ1@!-+uT}S07tT z=)%#Qgx~5nZI+r}>-hN|Wg{bwA3mrfD~8S>r?j}lOZV5=y6|q_@a{z}pe+X~)<5rH zCQp9B1T&j=srvE*UD=eUL^hwg0UBB!Ut!UVJB(CSnMZlTP%h?_%(`dx>EUboE}V7t z*F)Z9e-XE1>1Zn#jAvRMU#)9ze_+q0O9uEM_%XpVSdJ%P7fWBuw(nL9kA9pYbf7cg c`1SSw7dy%o^hCoiNdN!<07*qoM6N<$f=ecQasU7T literal 0 HcmV?d00001 diff --git a/htdocs/images/default/tools.png b/htdocs/images/default/tools.png new file mode 100644 index 0000000000000000000000000000000000000000..b391a0e8392aef528db3450a6ad70708d75d5d3b GIT binary patch literal 503 zcmV1`c4jv^a zu)KIs0uh982M-p41cI_d5ez+97Y~(+G@b3&N~ib-oK89ga~VEee(#XE7Dn&!{eIr( zectZ_|GBOJ07{$Zcb85i)w3YEs6X~r2D|T+by^3oD0C2zYQ6za5yYL zvmZa`;e!tAU#vRZ**C1DlU2`9T!0#z0|0W;X+0b0H<5-)PSiU%s-%-ucWhiwM<&(S z9MJKY_w##t()q|lyf%0iP;6v^n>VgAG4-B0? z{vz+5^Bq7*C#&9}xcXmC>u!6OZK*AD>9KU8(WrnPbMX4j+xdIDxg0y67ML81;okY9 tOrQwVTnz;6w9-G^2VNaZpy@PO{{}M@%mpE#!`A=+002ovPDHLkV1kCO?yig}MS2qJkk7#Rdd9 zfd=H@*?7~K;8ibPZQ{X%lP4lVh!<1D;2)?lsS=>ImC7!amMwO-v;VrgGt=3b@!)Q= zr6q#C=c`~80JJMi!A7~njlzsdh-5-`%!)8m{vb;?;-Sa2pMC!MQTuR0?m zBhKN&hZ~UZfbEYedI0#mvBN{J4mp=Do^j^pW}RZO;A9pToKh+0WHV{!#~;3SP8@&D zId=45^NBtKo^2Ksn#OMc=e{`e2^}3_TrQFM`TLCjGC`=dlN&dF$1timw#l~bJ2-Lt z7=^+dqoY?icwisp$})?KOT7Eu#{dU`Zvk9QfT=Ifeo9||KZ-v@AP}LnY~%6xxqNwy z+qaVl2&ig~iODJM-c6B6^dU)Y#N$t3)pQhp3qwQCF*R{$YvIa#kvTGLrhL2+4s^5ESIuKvV`01CK&LqiTNr( z*LA#JKU=o!BAuSaG%cdhO^Bk4fq_1>>N2XDLBK>eDijMPx;AxSu2gZkL=+`JHk%`p z$!!b(xOwweQg;>@9zK8|2&}B=SeAgMm+^Wc_**1w+oD*^(i#dN$v)cJqG(!;TrS78 zYZFwe8o=y2KqL~mp3i4?Ns`3)_|J5A$ME|VHf@e0iXtH3*cO&;VHi5PR;F0Ykxu`~ z)YK&N^K(?I8fvZpkY5K-RdsA^?Aor~yG_dFDwXnI#N$s>DlMUFRVq~j+gd@>3RpFh z^uj#(oQmx@h=PD9ir6+Rmvn&h4c+D{TAY}edD}4D_AQS$>3e_=fcp>L0{~~wo*mq}HAmv9Exf#cKTpPE z6pL9BiLGe*3Wm1Cz4RhpkIdw6NlME#QmGWzuTQXTTOU(XDS%d>xGu>6d-v`n9*>dD z=DBd;9HuF-va&)touSi6@)d<$84>D7Z4i&1&D5R0>^Rw3!obaH2`iP0K@>Q z|9A-=kN2@vD;2FVjMh)#Y9!ZJCz8#s+6b0qJ+ingOX#|>>i*41uGKF_7I^>k>GRZT z1~W5%P%alKl}Z!}B}7p~6kV(hqk(PPEG^|R%^GLVUIh3MSgvoN(=-7X9UW`%egeJ%#_K+G5730Bf3s8%RZG3hUI$(Q sg22#2B6A6t2F8FHz^+F_1q{IX8}k$aK5&K;&;S4c07*qoM6N<$f{T1sjsO4v literal 0 HcmV?d00001 diff --git a/htdocs/images/default/trash.png b/htdocs/images/default/trash.png new file mode 100644 index 0000000000000000000000000000000000000000..d88ddbb1777a0eb32967518df5ddb02c3e28ce93 GIT binary patch literal 678 zcmV;X0$KfuP)8WMLequ_ndpVhjTL=fyfF|o-bny zo1~YZwI=)=0%VSIM=*eS@_5ngb-$UtUtQDf{xF}K@6E!kiW&7s zKwcIQr);V>uCns7v1El`LS)`UWF?SNns*6`B@!K@b%)NbMmi1%L8>*a;k}FlOZiEg z%cb+!6E3zT$W7!ZoR;J#rsL+ijFnW_YUFL2w?%1 zAa2JQ3&70^79ZZ@`HN**N|E*wuxz582nHYo1jQ0*s!4PL9GEo~}~gT23M>{xy* zfh`2S?}HFHjtiDJMjHwTpp^Po6c3Q}(!YiM0W?20S$@5O+E6e!B$LH z^f0UYcN&1ol`_?v*U-BO%{4_3__SJzH03{EG8|w;R+v%EA73%TZvimbGjNT37XSbN M07*qoM6N<$f;&MVQ2+n{ literal 0 HcmV?d00001 diff --git a/htdocs/images/default/tree_collapse.png b/htdocs/images/default/tree_collapse.png new file mode 100644 index 0000000000000000000000000000000000000000..1c9be7591474dec5e8badf0d285f8f38007dd5fc GIT binary patch literal 196 zcmeAS@N?(olHy`uVBq!ia0vp^0zfRp!VDxAh&o3CDgFST5ZC|z|IeO1yQQV2uC5L! z_ISgNdq9e@B*-tA!Qt7BG!Q4r+uensgH_f8$l)yTh%9Dc;1&X5#!GkW{s0BpOFVsD z*)KD(2{8%X{ISLpD5U4<;uumfCpm$EiIJ_OA=oAI=7|#wM;HXTcmkMwj~qREaDw1| isZ<36g#>XH28NnYmWOM7ZafF-WbkzLb6Mw<&;$TqC^qE) literal 0 HcmV?d00001 diff --git a/htdocs/images/default/tree_collapse_corner.png b/htdocs/images/default/tree_collapse_corner.png new file mode 100644 index 0000000000000000000000000000000000000000..b3328adcc2ab423fed5cc45a7105588b19028efe GIT binary patch literal 196 zcmeAS@N?(olHy`uVBq!ia0vp^0zfRp!VDxAh&o3CDgFST5ZC|z|IeO1yQQV2uC5L! z_ISgNdq9e@B*-tA!Qt7BG!Q4r+uensgH_f8$l)yTh%9Dc;1&X5#!GkW{s0BpOFVsD z*)KD(2{CDAe0I$R3h8;eIEGZrNlsv3Vq`062zH6QdEx}a5e7jno&YA_BS()OoFKSg iDpkSYzy=m+28PP1EC&ljIDP?jGI+ZBxvX2CMB#UP^@JYD@<);T3K0RR*AE~fwh literal 0 HcmV?d00001 diff --git a/htdocs/images/default/tree_collapse_first.png b/htdocs/images/default/tree_collapse_first.png new file mode 100644 index 0000000000000000000000000000000000000000..5c4387616c2c3514ea9edccef686a72d427ccf2a GIT binary patch literal 194 zcmeAS@N?(olHy`uVBq!ia0vp^0zfRp!VDxAh&o3CDgFST5ZC|z|IeO1yQQV2uC5L! z_ISgNdq9e@B*-tA!Qt7BG!Q4r+uensgH_f8$l)yTh%9Dc;1&d7#`=`_i9kX25>H=O z_RFkHLK;RJ_H(}j3h8*dIEGZrNlsAU)zFrflx&btaB5`qTF|*;hlPaEqwvK%ENlYG ftOh!cf{YAFt}Gkl=B@Vz>SOS9^>bP0l+XkK0535l literal 0 HcmV?d00001 diff --git a/htdocs/images/default/tree_corner.png b/htdocs/images/default/tree_corner.png new file mode 100644 index 0000000000000000000000000000000000000000..541c5b3bafea8a3e2599b173cd5b56d7887ca711 GIT binary patch literal 160 zcmeAS@N?(olHy`uVBq!ia0vp^0zfRp$P6SizMjzpQfvV}A+G=b|DQd3cHo=2ML-e8 zk|4ie28U-i(myGkCiCxvXF#WAE}PI3YR6C+zmL$FKa%@ZdWjxY#v@gy8-WYl`ZAX->h qXprI}=(wWsRS+8!GgFx(1H*|>)`yP{9O?&}z~JfX=d#Wzp$Py%F#WAE}PI3YR6C+zmL$FKa%@ZdWjxY#v@gy8-WYl`ZAX->h qXprI}=(wWsRS+8!GmrNMMuwwPSr4X~T-E`az~JfX=d#Wzp$PyIl{lLK literal 0 HcmV?d00001 diff --git a/htdocs/images/default/tree_expand_corner_first.png b/htdocs/images/default/tree_expand_corner_first.png new file mode 100644 index 0000000000000000000000000000000000000000..5de11a6ba812abd5d1a8b43033263a0567f18899 GIT binary patch literal 197 zcmeAS@N?(olHy`uVBq!ia0vp^0zfRp!VDxAh&o3CDgFST5LZhEhL)C=y1F``!0g$x z+xe!10$GeDL4Lsu4$p3+fjCLt?k)@+tg;?J4rhT!WHAE+w-5+3UbH=O z_RFkHLRws_x-WhL3YmDiIEGZrNlsAU)zFrflx&btaB5`qu`qCOm06&qr^naUqoKrM n8W4NRA%Vd#h~co1h#3p^r=85p>QK$!8; z-MT+OLG}_)Usv|aOl(3T92QIuo&be{JY5_^D&{07I575b1+*DVIhY}&!68^+XqKAb z;jL{_Sjd@>@OqBkn@5jM9hhJ!%(9GGa;icATZ#{RVw&)78&qol`;+0GE79%K!iX literal 0 HcmV?d00001 diff --git a/htdocs/images/default/tree_folder_open.png b/htdocs/images/default/tree_folder_open.png new file mode 100644 index 0000000000000000000000000000000000000000..4190b969845fba00d0ac6ca0c5a889818eebbeea GIT binary patch literal 278 zcmeAS@N?(olHy`uVBq!ia0vp^0zfRp!VDxAh&o3CDa8Pv5ZC`8a0bXTo;j1Dp+QMW zDJ|^`P-y1N{|62nICJLzF{Y2Ffzpg6L4Lsu4$p3+fjCLt?k)@+tg;?J4rhT!WHAE+ zw-5+3Ub*oF%FT1tLu>VJeJQnH(d+g`BG_ z1$>ygHk39sh)pnLW@(xvAz|dGwAPD9;A*CWpqi>dgEc2Zp{e4eYkN}4fi^REy85}S Ib4q9e0B@C3i2wiq literal 0 HcmV?d00001 diff --git a/htdocs/images/default/tree_leaf.png b/htdocs/images/default/tree_leaf.png new file mode 100644 index 0000000000000000000000000000000000000000..6f999fba427b8c3f54b5bb6fea272b44eb821bb3 GIT binary patch literal 207 zcmeAS@N?(olHy`uVBq!ia0vp^0zfRp!VDxAh&o3CDgFST5ZC|z|1$tlLjzEtp`pPo z#jzL2Vk`;r3ubV5b|VeMN%D4gVd!9$^#F1>3p^r=85p>QK$!8;-MT+OLG}_)Usv|a zOl(4Oa%Pr$?SVp;o-U3d6?2jk99WqGW(9Jd5(o-v;L^}^WSuf4k%=vZOG4UOb2kHH qz=@MA9@Y$!=MuP17!*1d3Nj=-;}V*1`l>L{5C%_IKbLh*2~7aI8#Iyt literal 0 HcmV?d00001 diff --git a/htdocs/images/default/tree_space.png b/htdocs/images/default/tree_space.png new file mode 100644 index 0000000000000000000000000000000000000000..fbdfa6a8e1e456ea42a1d39969b15e295a06cc75 GIT binary patch literal 150 zcmeAS@N?(olHy`uVBq!ia0vp^0zfRp$P6SizMjzpQp^E9A+G=b|6hJY`UH^6SQ6wH z%;50sMjD8d?NMQuI!hYn1v)PS~ujE l0fl%xT^vIy<|HR5umgE!42;`KcIpCI44$rjF6*2UngHK-BHI7} literal 0 HcmV?d00001 diff --git a/htdocs/images/default/tree_split.png b/htdocs/images/default/tree_split.png new file mode 100644 index 0000000000000000000000000000000000000000..1a49fab4550598ae110fe90c7fb77c4b098a911f GIT binary patch literal 160 zcmeAS@N?(olHy`uVBq!ia0vp^0zfRp$P6SizMjzpQfvV}A+G=b|DQd3cHo=2ML-e8 zk|4ie28U-i(mcdx@v7EBj?09tKvO8Q=NrfI<^XTq8=H^K)}k^GX;(^7C_&5{q<; zGpkZl6f%?Z^SEr002h}=vZjKOfq}7tS7LT)l7f0xW^Qg`vbsWWNor@#vd1gt5LP^Gzxl){mM<(URAA$D%Z=e61 z=T6uDdeDkbR`SWizv+AC)j7xK+aLVZ=45(OZ=J_k;hWz4`Yl}>CZ79HSJwA!o1T-e zt_4e}p8oO~A?ykf^Va&8%_3Y=2#I(As@WqW? z^Ov>eP3~A*^!OIb=HmR7Yk7ZpK8WqxvB~S6oWdRfHL3p4lDzDz{k?PF|6ncXcfT!=~FWKb(Kd&s%=E+VWGM9x&4|c)I$ztaD0e0sx=`fSUjS literal 0 HcmV?d00001 diff --git a/htdocs/images/default/up.png b/htdocs/images/default/up.png new file mode 100644 index 0000000000000000000000000000000000000000..865ec1551b0b7e030fe25b5ddd76dbb4584f33e3 GIT binary patch literal 382 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 Kym$XYmcei1+zI6X literal 0 HcmV?d00001 diff --git a/htdocs/images/tango/INFO b/htdocs/images/tango/INFO new file mode 100644 index 0000000..f1426a3 --- /dev/null +++ b/htdocs/images/tango/INFO @@ -0,0 +1,2 @@ +This icons have been sourced from the Tango Icon Library at http://tango.freedesktop.org/Tango_Icon_Library +Please be sure to ackowledge the artists for their great icons :) diff --git a/htdocs/images/tango/add-big.png b/htdocs/images/tango/add-big.png new file mode 100644 index 0000000000000000000000000000000000000000..2acdd8f514c199a37b7b14f53081467f88ef7bff GIT binary patch literal 601 zcmV-f0;c_mP)i&hw@usRe0Hlp%^VXF!>2}-I+fVC+BCh2Xu(H}= zWwkR-i17&Q1@?r1slIQmGmt?bz+``iz=_N4nTEMJnWp6PdlDi4$xDysihSSRJ^#HD zfm0WkcL*Ezw|WjD;wX`Y@`OQ$i> zk~|wHA%P^W-+NY=qm+O%@!?CCIP&DpgbAGaz)s%w=F2r6?z` z-r3~+=g{XtaVheZEby-7%X^w2a;hK35HfD6NN^I8P7V;(0mQ@Z@*Wtm@8FfUzLwkFPvfh|u~3@f)V nN>6CzLo>o}j6Z`3{#X10^GpxssPJ~100000NkvXXu0mjfzW5Zm literal 0 HcmV?d00001 diff --git a/htdocs/images/tango/add.png b/htdocs/images/tango/add.png new file mode 100644 index 0000000000000000000000000000000000000000..1aa7f095c6c282262390748ab2e596a3fc15c228 GIT binary patch literal 323 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE7hmi)!cT|6FkAON{jSt(_u!Lq7!B=^4B;IBq%dL`6}O%gpGjO3}J1 z4Y?KfzQ;%l3Rp(0FF*F|EI&io>j^)N99Xu9ZE@HjcqrgTrepSr)S!;v7$d z7#j|r*sm7k|1`qSzwL6X$#3JGkN$s>{Cx9Ec6v|es;&OpMC)hUh7@^ocW)~11Nx1@ M)78&qol`;+0M{XYA^-pY literal 0 HcmV?d00001 diff --git a/htdocs/images/tango/address-book.png b/htdocs/images/tango/address-book.png new file mode 100644 index 0000000000000000000000000000000000000000..2098cfdf361b358ac382bea61a1d3cf8a66bdb65 GIT binary patch literal 796 zcmV+%1LOROP);y z08cd6u?+wK010qNS#tmY3ljhU3ljkVnw%H_000McNliru)d>#=G96HDdo}<705x<) zSad^gZEa<4bO0!0DIhX1Ff<@aVQY0_AX9W@X>Mh53JODVWnpw>WFU8GbZ8({Xk{Qr zNlj3Y*^6%g00L-9L_t(I%axMNOH@%9#((GBd*;I#XGR@o)TU^xB$Ft@irNS5gf>A) z+wd<4Tqw9Of)+s#v=8^9+jc>Vz>THp7|dAeI5VR2eVzN&;^xPc1U+yz2hQ(2&-1>* z+8tA`7w*4_1Y6H4O&=Ti9;yvLE`on(W^Q(T8bG{w_v-D#oB4@rSMPzIqPVw4rZ~jT zK_@N}DLv2;u5Prb>@4#1&Lq*^vFExjor$4KBj}+AAOa-f8m00Qx#A%HTn*Jc#8Dcx zzBtWzlw@~^3J~obqgo|+PvC~bl+D$JXux){57bs^U>?a1$S|*9*4O}7EznmiSqX6k7L7#a7Fl~*hJBm@x zQ!1jIsR?zp?I3$1&UdOJ`ysJHBu>vwKAC(!4NUPLnwuRL a0KWk6OYuZdhej;`0000eA@*oMurG& z0fAC_cF~Hkp;H9iFZt%=oagtP=kt3xFOL|8!OJx5rLO*e0MJ)E@i&n`8h!?pf?e+z z#?T7|NQ?YXxpU`M41-&zPyYhEx|;i}sstS(ZO&+P8<`9M&SV4gLAP3uc8b{69UuhqQ@gh;Lm#Ejvz3y&ofdFQ=dtbXqaNPhjI9AfyYQA^j0xqTSI~@2O4qTeX zSa&zx)>f0i@pS>{5ZP`E1a^q7lN=nRskC%)tf{n=L@b7umxs;o-_{}0wx$4`B6*_g z-+7vw89jH7YNr!tK|%HnpcGDs@5U{M_rpX6~qSyC?70Ab6?x6#^}c0xxrq1o(^ypnN?|C4kpnQMr$N_2DMTrn z{C?v7{g_=YEMD)9c9Az$1#nhGH$=WKZffHG<;(b7E?h-Li;c(hbT$Kt#G`9UQCw7n z&+TTsx0m9E21Mj|r%2v21Kfe#How0Jeq|M7?MXDapPVK^s%=STS65xwToi z0G~BZOza!$?zR~46uDl#Nfu=?mfh4W2;cyUa>snKjVY`>h>_Dg@Bl~vaRE$#IVThF wu%*`n0AL{pF$c^&j8t2qbuB>-B=b;z13BE6%htL|`Tzg`07*qoM6N<$f=Wb%$N&HU literal 0 HcmV?d00001 diff --git a/htdocs/images/tango/bug.png b/htdocs/images/tango/bug.png new file mode 100644 index 0000000000000000000000000000000000000000..433945d700d4e22f7793a51c2a1e481155df890f GIT binary patch literal 564 zcmV-40?Yl0P)aJ$MuJ z;6I2U2!aRygcs}4LlLAsx~Qec_S8eD|G`r!wr9hp5GWXY9S_mf+9WC+c!zoO&CK_` zk4LJC^8}x(`)>o@F}F5FUX8=hC?5w_LK6(p;e`3!t z$cXNH#w=Y=5(6RtKpe-o9LH9epO2N05s4V{W~te{K)(NrrL|aWHp>8>W<)b12QbmI zi$QQHsn?;t4?Q@5?(ajbMJWt1m!_U4^7{9l!p4lKYK%F&ySyAs1i_$MsQ@BCuLl5d zCnwlyw~xQ}`wv>G?Nbay-YlXtG9DGl|y5IiU!*h(l{5vjS?9HU za(3EkwblTRf6{eVm7D9^H1!z_A4>E2`~Y|l0mxb|zpV=kAt)4zfKbNwtSfC17ef3# zt8-chYzhYff|VM86!mly0*pqFR$w}v%VYq(-c@W7)ozeo3-JeApoT0Aka!E?2&W2Q zBLlfyjz*(F@cWMipv%Dau2l!TclFsAKqnp))!S_uAf9Ln0JbtvtJTZ_gb;MQU7|aU z?|{))5Z~%(fW&8kDL{C?Edh+jPufMMRj=1E%76rDx7$Q_8qWdaKcRmM;){j>7$K+tS9BRk!0x7u}L2X=|-L#8`|6NGS= zs4iqW2NH!a`lyW#nY9qw>e@dqYc`wZg8)U~SPqs-B`vL`%1o!zb081ANq{_15b$!} zzbmJyE(9No#UcX~K)oIB14qCio+Gv|EiSMIzVI%lpTOn^MJv=M<|l)h00000NkvXX Hu0mjfS<~1A literal 0 HcmV?d00001 diff --git a/htdocs/images/tango/children.png b/htdocs/images/tango/children.png new file mode 100644 index 0000000000000000000000000000000000000000..663cbadddefa3c7f74f35faa702b752eb251f599 GIT binary patch literal 317 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`EX7WqAsj$Z!;#VfERCM0c#WBR9cj@HUTulxFt>;%oC#+8w zH~lQC^g^)d-50K`+%I@_UxOQru7OTDilRQ zQ4}o8!m=!+l$fSjv|VpZ2(hH=`qz4Ud;1{ld`fhbX`Y?hk_NhIXT56 zf&yUMHo;&J!!QEt0@${ln=I@3{igvaHC`0JvaF&3g%FI7k7Jr<(Fu!aGh=Y#D?QjE#+9nr6{}r4$HEDqI36I zT3SR(iK3{Kmz7glSw&5CEsCPxa5&hyb?cJ@*tU%j;*pXJhr^^&%Uu84HC!$iUq1L6 zwY5QdAv&~6XiW_b8B4jq1jmgZLa|2jh7 z`=2r~vq*iFmxFs6Ir(ZQ&+pjDZ-4h2ni^Z!|KdxJRX`~PP*?>*2&V7ep}YHaeEwRF zy!R*mb>HBdZ*}m??{)K?x4%Tjc5>{@6{eyoPM-J*lT#Bcr-^x^jFT2SK04f!&Rq>fXk8-~X7!w8g%CFY?JJg9st8ZF}PY z#iSaW80CfCd-&j^5q7q3qH}u_s>6Y*s%Q=ePEEt@a#2(1=fK_&KfN@>wyoQlm>fq+ zx$z~)zMQqJ3bWBD-ZC%!H)hxw3L;GlLt5z4L|PVLqX?T7L()`R!R^ThET=P61_I2@ z&y`$)bvL4{W%LZXo?&`^2~*FoluV&(3Jyg859R&O{TK@iNeoNi(FAwyE#Pu{Fm$~n zK*<~cxOwv?it_LkO><&MgJ8hRq7JI&#GyHHx?Q;49!%jNP+3XaGmSKDswX4CwhR^% z37k&nBY{gQAf?Q$RaaLR`YL^WT|Md43NJqw;N#nOP-U8Ow~7N3VH>EzMp}?D1=9-# z)#V!1eiw6dbJW$JAp-D175*xM^$oPPwh<16*s`Ua zs$c`xM;`F4H$zNKO_4|>n4OJoT!B&>(WZt?+_-U#`MD_PzP+D!e*7UL6Ei&D>Z7_s z#V{;J@1?l;&j-Bs_HH6=HH?iV=-AUq&$%8BA9`bB3gj@A@h!6iVKq5BFuh@_z{JEDiP#e9bcPqcu!sKs%V-h2G_WASYiN#_FA&^qy^?ET)laY}TR#wuC|9gz8sw%qnb`h+tLvuPYrAaLQfKNZW z#lXM-;ZTI8#ulWMM59qOO=EmwjL-iu{0A)Mza?GQNu^ROFE5i!CP^d` zBoYbY@i?heilax~VsqQG{Q1fsu`H9O=0;jJH`3YJ3GfQ6t%3@mc6xgHN2gAm`o0jt zQ~2fC3v2dZDfXPNM%Gn_!lk}T96NT5R(A`7gM(PMeHBpibHD`zfodSI+E)u0)I3*K zUCnDnp4))6>gl#;+gf*Q-+sd7c1A4A{3s+x200004+SOttuFuo0rp8m zK~y-)osvy!6Hyq2pF7DUO`2wgN>U06wOwc$MHIn>xD*Oicj6|$z;CJaABeUjK|~aE zS$9RDeGK5zq#vnP18H_P9en3BbiKg914X(U4?fX zv=3%78D?M10+5(X0MN8+cL(3TuaZiqIeKc0ZN-aeE4XBZ)ck8EZr_Z=qW7OQ{wVDZ zG+iT=PIKtw7@rGX1_uI+90*bpKD5zs{F**C6zm9u?EJ zQ5_2JmL<2Flg761XDbP7v)0}Ku5Shi%_G^x}q%2kVgpPOH0wIvBfN{N(qOE7M? z3xuFtwW!u4n_D&9s)POg9;6U0U2p=nX__rgY-58pql(|7qW8J5Es5XbtmWcc6+03YVxryf3dbXat2*wyQorvicCWHaaM z^${Ko^E;cZ_ht1ff`3FT9+eG|{}KR{SUhS0lnsNw28{O8e>3MU00000NkvXXu0mjf D_c;L2 literal 0 HcmV?d00001 diff --git a/htdocs/images/tango/create-big.png b/htdocs/images/tango/create-big.png new file mode 100644 index 0000000000000000000000000000000000000000..e6d64bb90b32dfec83232de6478afc1a6b335b8f GIT binary patch literal 1008 zcmV9&7>1-t%; zZoBM??ke>U^dD4er7kL=hDJeZLn7jm5(v08gqI)OnbXC!k+JW?xKusTXl69mbH4MM z@xcEq@?UJK$`~hw1@dkN7mNd7!v<|zXR5g`LOT&)eSQ72TrT&mh?I;m7-R6>>yxk%nY!jFra=|`UYN$jJFw$o6!Q~hf9-+XQxm0cZ zJOI$ON<^+(?>q^>$`OG*B(MkM>^|0nAkF)!0Ktc~6Mw%ewATx-0 z2=>Fy#)6oaAmto-RYqh2Z%eTNabbvae=k5%Xre;9nY`Cxo3Q|K&2t~+0bbw5`9+*Bg4+i7q|>%JJZgfrw$XMK(PuKxMWP1) zmY0{W>pwdb1w8NJv=RMSizu_;qj``kQ{8>c()+Ea(0)p>xdkyNp>qyZjjXz5Nh%eb zJ_06CKaG(SAOf&5#fzQa`ScU_6UFA1NR%C^9_W{0asp;?Orsp*IYRUtB#$=>{POGf z$mGS7-aUt|f-L1XOD{mFpjwHh3d#hRje(RK4xrbrCP4qK*Ol9z4QaP$ zB0w01u}ZUm;sE+(Xb;3G&N>H11xP%I05&!@FlI1uh6OanWah@e?qL{S$7*F|CG}!T zQk>+WI7tmb|J9u4iTE=iTT(+XjMA*NEST6TNGiioz`DnJl8oemyOdkq1z9qR=SBkP zt&A)XRZRu!2Phk3PF1yBE|(FB-UUGr{Oh~`$mjECz&vmawE6)`KxJ=l@5|NI)h|Rk zFN(X9=I-w9SHJ>bfdjzz`fv=G1MUG+ow>a$ literal 0 HcmV?d00001 diff --git a/htdocs/images/tango/create.png b/htdocs/images/tango/create.png new file mode 100644 index 0000000000000000000000000000000000000000..4c3efdd6fa334616f87698708e73b2a5111c3278 GIT binary patch literal 477 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 RSE&F1002ovPDHLkV1jK^+$sP7 literal 0 HcmV?d00001 diff --git a/htdocs/images/tango/cut.png b/htdocs/images/tango/cut.png new file mode 100644 index 0000000000000000000000000000000000000000..dc9eb9a7ad3e9500991938d0da531c06f90fea85 GIT binary patch literal 807 zcmV+?1K9kDP) z1Hh-$q?nqWnZ{11 z1JXGjGT#nH5JGSEt3`W-F{81UPnb`417>0bwH3tCzhB0pcmY+{X4F+L%h_RSnk|a_^$fF6B>ZO8Zd4#b& zIcbiYQS<4l$&8G?%anG5EK?xFunXWgL9J9WU-R-}CY`QnUJ$&B%*-pvkEGQ$e0RAv z4j($yFl({I2&EV>4gdf!007lmt}-!W5XkX| l!x~>C;!~(p=dGgX{tck>ItSb|!8`x}002ovPDHLkV1ju0W~TrE literal 0 HcmV?d00001 diff --git a/htdocs/images/tango/disabled-big.png b/htdocs/images/tango/disabled-big.png new file mode 100644 index 0000000000000000000000000000000000000000..e7a8d1722f328be5fa649f774e2fa6bcf049ebef GIT binary patch literal 1927 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 literal 0 HcmV?d00001 diff --git a/htdocs/images/tango/error.png b/htdocs/images/tango/error.png new file mode 100644 index 0000000000000000000000000000000000000000..3bbbb4a0d3dc2f6bfb653bd25e80169e96c6c833 GIT binary patch literal 653 zcmV;80&@L{P)&6kU&^O z2QZQrnrLJAuq31{O{kZd49Zz&wx!#=YkfunsI` zVC#CnxgmZ#911N=CX)oiVSEDvs4AVaGtSFpiiHBzW;2_C#oquqcsHF)z8smE;c|N$ z=kydD2USH3SVMR5Pfb$Y-Q`oUxSD}i0KTsCbTaw+UMxm?a}#YeKm=7mML`5$&hffQ81ak$9mc{~;YnD+zeVE8^iK72$)87qJ1PqlB~L8>(Z z4<7-f{lK`@KZuGO*xyP-QSD%Q0s!L{aFzDI0Py-$1pq%#>eSCB6oab6myr>-LBzdL zH#|30MBN~@*#an8!20>g3C13}BL5=pI*KP&!5SQ-U8@1CTfox(-X4K?+$GC(kvBT+ zPD4;*@JAw)4i5pAtPE_`TCHrQkf&$rsSCO0ig&9h7(-7qM&sasdb^#?z?KhS8CITG zDzmoF7ad3>a2gHdqJ8xf6)<*)-uMKKa+$*M@oEO%+`3G5U*E!$(NO}njp^-0MR1x; nI`ukVkB+*|i??p$|E%**!bfHvxmb3000000NkvXXu0mjfWCIe6 literal 0 HcmV?d00001 diff --git a/htdocs/images/tango/export-big.png b/htdocs/images/tango/export-big.png new file mode 100644 index 0000000000000000000000000000000000000000..bf2e8c89fbc45b0d26a699b5a26b1542c4ac8575 GIT binary patch literal 1338 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 literal 0 HcmV?d00001 diff --git a/htdocs/images/tango/help.png b/htdocs/images/tango/help.png new file mode 100644 index 0000000000000000000000000000000000000000..2a63ceeadeb658748129cc9785ffa2d7afd81d52 GIT binary patch literal 873 zcmV-v1D5=WP)Mh53JODVWnpw>WFU8GbZ8({Xk{Qr zNlj3Y*^6%g00Om1L_t(I%YBf~Yg}a*g`e-o%w;AM)8tNVCQN2Rr(3aYlGcD=T#9bA zpc~PZ6-C4@3hoT(#$9Q;RzxUT+Dh>suviihghXr7peCub(_kjaOeb@j@6Ns7>tZAk z#XigTJ;FIhlBA4` zl=yR_jm=b9TApLHT;|l|GhF`aGUF#sQmt0d`v%%FR;{wSw#t)-4>MXWW3*2v__iN|~2tKi~T zH5v^7oO1xwA3UH~ECP_pW-!)JsZ?+-Ch5j(?d;IsS2!3EV0wC*R;$I-)YL!EY;W(- zY_^D^N2FrosI22MlTH6=yK5PRpI5@z67#zT8(=#X(`q=y~on3Bxdjl8800|W5YejnogQRf&kAw6ru-H~|Vtq)@O46<|mV0o#}a z?Bi~Ix4Sdb57<}RkYbvk{-x2*>^*wschAiHH4Fb|i8}>Uu6VIt8?jCb(+DDnAZ3(3 zj1jMP@7wb3Jp(9P(pG5O?jNF&oH?^uKz#9J|QnC2i$pz7d-u^^Q*QNeL*9V;K*9TLtcVE65K6Ade@_~wyfE}>N zxQb-jqcA^0EE)=bcbCAthFs{B{S`oCF(q*mw)`19~~b3d&SaUK3P~4 z{q6ddb8@fW$lxoDF@}=DD8GB{aN?7}p}BXv6ms;yx{;n`gt_Qz_4xS70lNRT^^e!C z4gKkCcfYbNiRWuFo+dTq@wG2kL@msQyO|uuRiJ$N_Ep-5nul{w>^8={90&v!Se7*g za?pz~H0ePWHOA??mc&;#_d+Nr+5N^_d_C_B#+YopQc8KA_nPB4>-X*3ml+RWj~-}k zU6k7Yr`Gz{>(;GX*xcNVlro#p7(>#@@aX1OkP=*9qqX72kVi>jKGKe`bLUQsF{7Kc zYuBzP+S}XT2VVNG02xnToL%+t4RKA(Uc7iQe}21@@3p;oOWAB&B80&86j~d!G2{d+ zQfZeNtA8~n_8ar7dA4;K?d|QGfE|DtlWX*#|G@KCf|FK#tLd@F3N6c`entsD**KS1 z-sogu!&eB0f>=^uTM_}do<*i%hDKG}!>-dP?zN>uqn={GJ&!@Jwwps|W zaL=AS2R;*ESR0ovT}m>U#Pd9s)K}1d&0+7+fAQ!ewe$}R;iP>G24ik6i<9wr{opyA zj8D9}1m8__@^m-9`Tjz*@=2vqELyaPQ>RXS2N(k|W`nI-wd(%j;^KuD2#;|xRD{@ zxF~&dNlS}zsk|?b14lpL2W#V0-j|0l1|bB-7(CCTsi`R#2n06V7GS}G1-204>3BR& zGMU7-ZHzG}rSN?p<$L^e!)$_hobSHOLo=oj4BRx*yl9YzYD#$P=m#{|lU1G5qb#-->9UUEuZvhZO ze0#}~B_t9F0DRxa7?Vw6j6rKnz%u-NL!7hcFLG@l!HP#J>H4Ub#K0iWG*{!gE}rM% zc^Gap~2Q#Z-ikV5JIet$KxD1a)geK4t(Ed zqFNt^uFfNLb>2DFwr%R_>Zq@;XaD~FPXWIeF`_TUVlj>%KhBypYsksTnJ~cJD3i&s zd-rY{8XC}AKLG!6!W`Fi(ONTU(j*QZJUF3*^XJc}w6v6-o}LNChr?mC*7WuDW%o(e zibu*GjYhHU+d1^DibkVjo)guTD_64p>`Ws>xw*Ln0)Yu7%FWFk^PH$g=7Lc^F!~a4 zucegA_QzCU#4?+koByX|caq~cNGZouAPboNU1wGq1=d5(WSI$uvu4_fOpK*%00%@23%*zuB-vh1Gx^>I>4 zUFz@ee*p-N+=@fMWS{`Z1A@TBj>5#{a`Qtd4J3f8z}3;$asfn#TZr3yHGNL`!z~RY bhk^JvK%sGhfx2y<00000NkvXXu0mjf^huI9 literal 0 HcmV?d00001 diff --git a/htdocs/images/tango/import.png b/htdocs/images/tango/import.png new file mode 100644 index 0000000000000000000000000000000000000000..9bed1436efffee1a483904588473674318598b1f GIT binary patch literal 866 zcmV-o1D*VdP)UFWod3@ax5SUXmoUNIxjD3X>Dy`V=irVb7^B}VQg$JV|oe-V{&C- zbY)~9cWHEJAarPDAV*0}P%H{)baZe!FE4j@cP?jXZE!Aca%X3X$43AF0#`{yK~y-) zosv&TlVKdkKkwW8GjsCJ;cHs9iJC|qA~d!H4G(FMMByQX#3HCzjd|)|VIB-21Mwh5 zhom5c6$M4zBB6t3c_^}jnrK;u`YN**_QtOTUJ`MufOw3D}O<$@%J>jc9glCx%%Yp!W_TTZru}!8;pKg ziIreduQu~|jz3q2r))jc$I(uWGxwCOmnKd+iq~);5l0swcK8o_Q>AwF0Fa+$sjC1L1r-H%nUmZ19?@7`$l=NgGB#(d76639 zVRT)`nOBmOcy<+0;@U>{org457jm@9jjroNqtWCOEdZuz5{X0r&~+VM*XccPrR92n z<(R?A+A^9C9Y9r8LZJ|mNCcbBmiPxgzgH^C_adwe_&*qa^)k`Gv&$^mj1Hi7? sSDjmaE$V6yvJn)Y-+LKoV`H@c1eLz@t3P|Tod5s;07*qoM6N<$f{Xxk=>Px# literal 0 HcmV?d00001 diff --git a/htdocs/images/tango/index.php b/htdocs/images/tango/index.php new file mode 100644 index 0000000..0d4445f --- /dev/null +++ b/htdocs/images/tango/index.php @@ -0,0 +1,51 @@ + + + + + +

phpLDAPadmin icons

+
+
+The " . count( $files ) . " icons used by phpLDAPadmin
"; +echo ""; +echo ""; +foreach( $files as $file ) { + if( $counter % 6 == 0 ) { + echo "\n"; + flush(); + echo ""; + } + $counter++; + echo '\n"; +} + +?> + + + diff --git a/htdocs/images/tango/info-big.png b/htdocs/images/tango/info-big.png new file mode 100644 index 0000000000000000000000000000000000000000..d60425f7ec65f748d6e5d2a61d5a3cf6da8d6ee3 GIT binary patch literal 2231 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 KMNUMnLSTZVNH5j^ literal 0 HcmV?d00001 diff --git a/htdocs/images/tango/ldap-dc.png b/htdocs/images/tango/ldap-dc.png new file mode 100644 index 0000000000000000000000000000000000000000..5c140d838d18bbddd135d5e7ac28ad2de3320674 GIT binary patch literal 517 zcmV+g0{Z=lP)B2g5DKj9&4ziGxQYh@Ldz<{JPSh!3**yOS0wxei~V2Vi*{{dOM4Kovv zRNE}5wbi6ZySwNHF_?j=wRkX2iu@qzOg6WChjZTj?!6fRDP;?=Nv~7Kan6ziA*E~; zi$&Ws%~bbbFt7oVLIhx&rb!rvxURcpE))usN+tUJz6~S>kj-XsU6F|KJuzcTlfn5QxTCLW^`TZ@rZV?1Q zDwbgwc%EkqfH;m5e|e2{eSHJK{{9~A_Bn=Otk0lYtg zPbu|D(==+e8UU7MZ3QhBi^MJkaA8^2TSo*y``2A+fZgeIh@yz;bc&{F)a!MCRIGBj zynYAs`J5mKST2`@VTe)+-}ljVokpXPwnhLlJ3AkLR4QM-Zs=X$8~?9vCh1j58E;|% zOeT|;qs!;>G@H#wgrwTU0#Hhk%jFP4FdmN|5mGw%{$7L!q*k&!+xe}P00000NkvXX Hu0mjfZMxp| literal 0 HcmV?d00001 diff --git a/htdocs/images/tango/ldap-default.png b/htdocs/images/tango/ldap-default.png new file mode 100644 index 0000000000000000000000000000000000000000..259ed26dd000fcfb81b2c312980765a181a65486 GIT binary patch literal 629 zcmV-*0*d{KP)i103CEi zSad^gZEa<4bO1wgWnpw>WFU8GbZ8({Xk{QrNlj4iWF>9@00G%aL_t(I%f*vTYZGA< zg`a6_gEXBqBcUckH-X08gk(ZUidc0eHCc%W6$Bw<{y`C3bs>l=5jQRU1EnnpL$Xl} zSV57z`Iw@D+a#2UG$mQIh#zrbXGq(0)rEI;dC%o=?>Xm%bCz@#@buY}zSBQidVJ>G znA6<7cPFFkaT7p@N){lWGgw_)Ifk7ia|v`kZsv0amSq8$p`c33ZV(Eppkt)Fl@Owm{qp(iw__VPf`x)A0JU1JXWQRj2~pit6y>TUjXqq++zL47=z84M zV#Hy}=L}+rf2;a@KDpU!Zf>k^nVnAOy)1hJ&N=yE|O=HjAr(hPT zmg@ji%XJE7kv)6g$-!_9j#TZtNz^ej(-{i8MJJi&$4?(lCGp&U;s4iPvstez0t~w? P00000NkvXXu0mjf3(pax literal 0 HcmV?d00001 diff --git a/htdocs/images/tango/ldap-o.png b/htdocs/images/tango/ldap-o.png new file mode 100644 index 0000000000000000000000000000000000000000..ac5957ad62d73408cd754a27453b4ce601a2b042 GIT binary patch literal 928 zcmV;R17G}!P)Mh53JODVWnpw>WFU8GbZ8({Xk{Qr zNlj3Y*^6%g00QhuL_t(I%dL}LXj^3*hoASH_nc#sG-;dWqm6CW(4s83b+X9Bt0|~3 z6mOI%-9=?M5O0K`ptn*G#rs`|6-PnD>5WW=H?uIcvzCo^E3WHYKeL=HA5C(SbCR6b z3)#f&*5~^FdoKR`eu4)${@&~<;4NLs{R%AQ`wgX7&~)wW+|1M$58jLW!S}zMGrL#P4P+<|J^kR=q!LjUR<=1mzj7BLp1miL0MTgZr{|x^iYGDyl!|!#OL6OV`f;PXlOge)!c#$#{SGXl@)s^XbSCXaYk@OhXc|B#CG* zL-81~z96~mqojuij=b@~*=YbR90{B}oE@c7E^@~W5Fg%$Qs65I} literal 0 HcmV?d00001 diff --git a/htdocs/images/tango/ldap-ou.png b/htdocs/images/tango/ldap-ou.png new file mode 100644 index 0000000000000000000000000000000000000000..9d2d500813c206d6735ea53e47ff2c56428ea0a6 GIT binary patch literal 911 zcmV;A191F_P)Mh53JODVWnpw>WFU8GbZ8({Xk{Qr zNlj3Y*^6%g00P@dL_t(I%YBneXk2v^#(($TnR}B-G7U*PrUTYAO-$_~)`SY0g;DBQ zQSd=%U5p#0rCSRvf-7|?=t|wWF(@ulNPHHB5F!+#1Fo1C&nVpwJw|91JDi>Ji-p;#bS}#``x~kI z0s;lstrNJr$VQoFb(`U*UZQL8VVrsiYbTG9I;!@JK0XF~w9jh^tV?~3ribfmSd|S@ zO_SvPLkQO<-ZKQ6fxU4Py?-DMJbITvW^y8%sEzc`E!r50LR{};2bE@{iYVQ}EG*$w zmXWBqZes(pJ{Y;Tw|dLX z?scdEpq)6?|Lf^thfpc=!0`u(^(oXto%ZEX3jb6XN~;9PV|d0fYE`NHIA7G)c8{jh zhcnTwt=xRe1Cf?h+U7~?Gb*x+d~*;%Qp-Pm4X#hWojr5O zP%@Jf(dl6a(_IC?UU->DuDr$<3!A7~oHw6MGxPD6oI5{G*xtbhKWq{Pf{_z_1lOnU zxKMYy5W)f7;sqQGbN<|;A_P_@?OsKBdB%N^wYXy?z{hX9B|AAm%qhztbZF0Qk@v5O2m zI%*||rg7igS9h|o2VVr@J>%<{ ls{n0#&7ONiSw`}me*w>=TB^eO7GMAX002ovPDHLkV1j#Olc4|r literal 0 HcmV?d00001 diff --git a/htdocs/images/tango/ldap-uid.png b/htdocs/images/tango/ldap-uid.png new file mode 100644 index 0000000000000000000000000000000000000000..46573fff69011e6e19afcc5e8161da333af7b298 GIT binary patch literal 628 zcmV-)0*n2LP)Jed}|-^E>z4Yp9T&OuxanN3r9* zrs~v5#G6scEjUz8JyvYgga>b#sU`QrO0c#1IjBdV1*Y?%o|m1Xaa#U4T8o)0t7;6{=WyK2NB)L*Ce=qaEn8 z5r(ckWNB#$RRusq=s>kl&-TwhzOqN;ro6$MQv?uP|$bz0attPv$2^i3u?kqEXzh!i9{l( zYWW_FF+qWdVB0ozhmP%kM5Mh53JODVWnpw>WFU8GbZ8({Xk{Qr zNlj3Y*^6%g00P@dL_t(I%YBneXk2v^#(($TnR}B-G7U*PrUTYAO-$_~)`SY0g;DBQ zQSd=%U5p#0rCSRvf-7|?=t|wWF(@ulNPHHB5F!+#1Fo1C&nVpwJw|91JDi>Ji-p;#bS}#``x~kI z0s;lstrNJr$VQoFb(`U*UZQL8VVrsiYbTG9I;!@JK0XF~w9jh^tV?~3ribfmSd|S@ zO_SvPLkQO<-ZKQ6fxU4Py?-DMJbITvW^y8%sEzc`E!r50LR{};2bE@{iYVQ}EG*$w zmXWBqZes(pJ{Y;Tw|dLX z?scdEpq)6?|Lf^thfpc=!0`u(^(oXto%ZEX3jb6XN~;9PV|d0fYE`NHIA7G)c8{jh zhcnTwt=xRe1Cf?h+U7~?Gb*x+d~*;%Qp-Pm4X#hWojr5O zP%@Jf(dl6a(_IC?UU->DuDr$<3!A7~oHw6MGxPD6oI5{G*xtbhKWq{Pf{_z_1lOnU zxKMYy5W)f7;sqQGbN<|;A_P_@?OsKBdB%N^wYXy?z{hX9B|AAm%qhztbZF0Qk@v5O2m zI%*||rg7igS9h|o2VVr@J>%<{ ls{n0#&7ONiSw`}me*w>=TB^eO7GMAX002ovPDHLkV1j#Olc4|r literal 0 HcmV?d00001 diff --git a/htdocs/images/tango/ldap-user.png b/htdocs/images/tango/ldap-user.png new file mode 100644 index 0000000000000000000000000000000000000000..fbea772caec3b4f9120bc7ece1a7057f32bc2ebe GIT binary patch literal 757 zcmVbY*F7WpWA%Lvm$dbY)~9cWHEJAXI2&AV*0}P>|V+ZvX%SQ%OWYR5;6R zkj+a}VHm}K@B7|QXB=lno$+JP6e9z5r)UPXXd$_3(LyqU{)&Q%D9BZ9+O_Bd`wJ?9 zc5Niu^+n>4W~OGM_?6B$_rCXS5tiva%frL(Ip+utXz;?FnT0jcM!cTRzPx&IzhND` zSXdKn!>2k;L#|fnFrX4f>{K+L=Qb%$PLBfdfPs;*_e&e5$6zS5w21q6?-6JN2*7Y| zWR&709638?x(j0B`GYGb0puQFy<~bu&YvNj@R(ZMq_4jZCs~hEoui|>mld6)wY`>EpQ;>sw_CT>}ga522)FVXe&T4@=m#VmC0vR>)LA%C~6Br%@8- zmpAw}@s^rko0Y;bT-QS=NqMLIAK-6=e9GXM3P(E%{QO#^usTC_c^3D_cN$jbn46lS zA(x?4D#a&gO2hF&HMR)IXL^}__5xd!5S~P?F4BMEG(n|IAS?vtFd*eaW5y+_xTHOp z@k6{?8xcu%1A{9yLPj`JV5yh{Qh==>A2LYuDRKf^@K?;GeB#vXDtq3PFG-f?Q z9Z{1>(_SC5!B!b|D;lj0LJ6dhShj`G8cS(>M`4VlKJ8JPh^bHtKqJZJ^Z2gw$J~1) zpsp^9j$GdzRlmsPh(luGaFktJ~GLN1-WZzz|_{WZwymj-oE`FKW naXr^=YiYKx-MDT6`rzSj;egEtd1;)W literal 0 HcmV?d00001 diff --git a/htdocs/images/tango/light-big.png b/htdocs/images/tango/light-big.png new file mode 100644 index 0000000000000000000000000000000000000000..2ac57475c3b36e46ff4c4ea0506892e2fe884fd7 GIT binary patch literal 1910 zcmV-+2Z{KJP)W~QdMmlr4dytt0lBR3q?&; zsf}7ieW{ceqQ0~w%0ngR(l(+>6RT|+k)U#E5K0IT8=Mf^q}b(RJRV=>K69@7oZW{E z6%PeG5mk@0w56kc*8i=4U(N#l&kxlzdElw1LXir#G9KKfp!(p+CIA4}as(RoJ?ph< z1O7I&f4_Oh0lvTIXM4f;uUc2F*Hc}+k+#-Wgu^;CM({lsi;Ii6bn(1#X=2n?p8Ult zFa3J(jsOe{JflYw)=*=zShA`mbU-k=^sX0S3bG^fyY9h&Y0*p?-h1EjYvd&-0xsN}5e{ec8zp`u9n(Vo=?+@1vuxr;( zdmq{sySgZ`X-yEFtvWOgk1=u?K@veSA{RswfCnfq-Vjh%=E~LCoS`1w+!r}> z`egsc4Sj>7qo=I@ro(Oqz;w2~xpQOK_66FLgqDN`0whSeMC33|HYc(f!R7=@<79G1 zR#?~UctgM_n@*u@OS`XsbC~ID`%QIj>OTwYZ0%eZ%2h0^Y}4Vx_lPN%Kn_7UM6fv{ zi!o+0P8Ja?jWdIDG6RBDf;y{S&XkIM_uZ#~={xJ+gud6+5RKznriy?F03ZoPF5|En zk;92O#FS(p7l7|GQp#7bUC(1g#h|W*3RRm{G^d)Oyw!CBDCI>pp}|u&OviJALUW1W z5XfPSY{p=J20;=aPXl~c`BbR53&8+ajL0`#54zx_d_P(@05PouWhWVvm|mz_@rdpL z%pro!h%5%OI3t@Fa~VM@U-?0l0G~0c*1ZRa_*l7=MN?FF77CV; zEm~y&Hi2x;$YdNQ=VWLM6-Ror^Ck1VCFRVT6^W*xu2q7Jnai8PTCP~O7}F-}2Jk%d zx7RL?mRB}6dR!yt@?tf=@vcNFq!Z7Tt#q;MPAyjKiMhNvTru2n!C5w9&wr&dH~DBl zXojvc;|pzxI6l^@7iZ|Y^bJcm^55Je(FYX)}8FA}7hJYg1-a35r zueOloU{^~#GCY|bHykfJezouxm?|xcg}XZ2k`E^1(H;)UgKOs^&36r^nqq64qWZ=c zo_~(p(%U&WIB0zCpV5vzKj{tWp?`dH$8JN3$mEKqfFjN_hUtt&LRvl?;3b_4Ly)_H zc+f9d648MEqka3H6{TYF$yZ+d&7W_TpWP1N)t8?C*mbS%o_zO+NH&HNnVfaiHVO$w zN(#;#oeP7QYhS!Lk#s%h(}sZPo){lDi-q#w?ZlS^0089E>ACc^SXl6oRGyWdnJs7M z(n(@WGF`dv9Xr~do}Hc4HBsTj+OAxgCIxwRDY=&f@bb(1b5i;r&s>|KWevgAhEs`s z^x?6uUHa#H+b(``bm!Rk$tPB?jOqkRaAG~DPJIy589rD_Zf&U@k?op$|ML2Q6W`mj zV^yjpsV__mICk-FrhqlwD-exEzvwzub@1)O*BsXwdU5c%**o47Zr}0v!C0c_v4^*8 zK~K+GG)5!fTmvH@n_Iv;Zy(0^_{8P;jK1#Bp%?5s>Hq+=Hs>GOve|~O7~Xi}PslEm z;7Sh-4FL$vK|VL-<*a9NcX#vCnx=$dOrcyhK}f5*DU#?W3N0#5)c%sGQnK9pimif5HF z4xc%b`Q`k4vHV$+3KxK^jqc}hKnD=0MR0n$WKK?IhdVoaWpi_P-|pQ%*EVf>1k=-H zJDsi^IC5m<)oRriweP65#MgsrP)i1&8>;`03jjjtbb7j@qvM{jv9Z?C(NRC2&yO8H ze*BM~=Xn79n$UFzRPCK#bEB>$pqi*&8$}I72M}m)Z*TT}pJy_eVoksWVAn#{!U162 wYzgYQ39nnK)ttN0UffXS^-8b1am$VPZ%s-(_>=>Px# literal 0 HcmV?d00001 diff --git a/htdocs/images/tango/light.png b/htdocs/images/tango/light.png new file mode 100644 index 0000000000000000000000000000000000000000..8851b99ba1060109ab8387fd9254870480e9284c GIT binary patch literal 863 zcmV-l1EBngP)Mh53JODVWnpw>WFU8GbZ8({Xk{Qr zNlj3Y*^6%g00OH?L_t(I%axK#NK|nY#=rmEJLA1N*GDEB)OrZasDZh+oSvYeh-b)!X&wkCqi5%=xUSx|_F{6#zu1AgWFc?@DNvi{=o` zb31h=C3AB8Z6^Sj!X$=0S8gvrAf%45EJH13#vp`HP#BtSD3rqJ8l3DdD$D`Ha;MgE zVZf?F;{_`ZSZ+ivaM`C+Z(3 zy#C(dnS~`$HdpLVs~B>P!OCIcuN!O=LdQG1`sJDF`RueL>!EAy12@kc&bs9OG9O}C zlIXN&Rr?p0a@>O>s=)e6!>h0VgJY)~t7IxXFDosw6duS%G|xfRb@-M=47tYf&NZUN zanj`{?Kd7o1OPy7T|;7sZgB-3|fr;X0czA^&R5dAdz!r1Ht08mwZ p@_LOR#2;B$Sa_Y67yBrZ={HtPHeP&+9RvUX002ovPDHLkV1i2wZan}1 literal 0 HcmV?d00001 diff --git a/htdocs/images/tango/login-big.png b/htdocs/images/tango/login-big.png new file mode 100644 index 0000000000000000000000000000000000000000..8b10c1e9a28c7d590d3f229f2ad82548c731e724 GIT binary patch literal 1390 zcmV-!1(EuRP)`oG91P?{L3Kv2t~iC~l{VMEdY z32EFBH@F~5bYnt*Ay8-tQIv&BV%(^hKqM6tsL@JF2ST(+t>e&AXn_`n8QPim&T#=9 z>0dP3xX_cF+?RLnIp24_d+yD9@GqO0%H(>B8D#lGs51xAEG$W)a*dqSC1Xef_@)f} z9_6HiPoY_r7+(p7EYQ0cH%7t~s}6l@42dZrptqPoI#`Vrcn$*9sDD0ImLDBTLi%S6 z)46M07(6vK3ON49AgdArOE4vs*iSlWt_6KrNNY7n3ba>mI}sm1V`JkY$8kOrkp;GG zTYne-_^EcvODd10IGT)T0ca6uF}Ab=LqIlYKPufA-xBV`2MyWW z71q+;q3COid-;(8v6qRNBuzW4O>(9+UEEEXd_KcDvY zc2=%jNlQx$D^{#v_3G6K%V|4*o_O44aPTfgg?aqad5xFWti$oGA$jl9vCC&kOodHNO_Y_D5eNkEJdbtj*3sA3M@>x)*RNj(;JfeJ_$6Az zZ{5|LZF`J!7Z%YGUBRHc224Q)Ym5S4HGM?e^>!W)PUFijK0!Pol{1~bScJ2!CwaR1 zd3NvKjjFP0)vAmtwY9Y)`rzQfgX8vyh>pM;K|n+}eB=!lR+i&RFK(XTy2|{DMa=3? za_GI+dGBBwot>Qw4i07#KMauBLRB2cp}f3&Ov6q{Ae~Op-+u!`hVigvoqD0+wY{S`s4q>u)Tqtj6#61K_%8e!6slSu^u7#-g*clcAxZ zG2oL`{-+3t2-~+E<(-{%eDn2b{#a`$DlBLFwhvKNDk>@-eHVyKI5!~yRi&(SA@4S} zJ~HuSl0Ry0gzBRe*tv5js!Bsc1G{$ZLPRoSI2V07Y#14lR9cuB{L9Zm92 zDNt8ehlr3!B-pTF1Ic8PjT<)t(A(QfeSJNBeSK`+yqST40YrrQ`g#(H1e-Q(!nSSV z@i^<(uO~Y@drajMDlkms;>C*?V@M`F-W3)Wj))6|LK(0vTee`^_Hdz^A>jA>f9&e&swyolHO5TompURsG#XXQ zvf6=M9}sMAZhkGDP9Fj0F~$E1fV!^Rb>hT{w}IIPuz|b>J_E=GvZe?;#r*=4z#X9H w;c9Kb;r_NbQ$)Z6Tp;~`%-E~(fBVnb?@!n4x%5A|9{>OV07*qoM6N<$f))6TnE(I) literal 0 HcmV?d00001 diff --git a/htdocs/images/tango/login.png b/htdocs/images/tango/login.png new file mode 100644 index 0000000000000000000000000000000000000000..46573fff69011e6e19afcc5e8161da333af7b298 GIT binary patch literal 628 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ΜIY1%$PA_VnIQ{ zBYwZ1g%D&IhNDzdefyVSGY+q${L80U2jj9RCpX)5jPnKn)G4KoDBp^Px({Su35(A@`)m^cEX!)C!4MI?`s%BdnVFgH zs3o-q{PwsYgy3jt;Ak=6-)$i%E-L;`GdGZ+8M(PRi;luV{?5z=Y>){c?&tbH|NQf~ z`|i8VpX)bw?p!QbumCT={Bjco-)u2?d3m?=>eXx0k|j&pgtE<6)W+@A)YSAUDJj|e zpX%BUb(Hi6L1G6p*BzyWJV``XGxOlX>3{d#cOUlLLx&EU2thGDEHBCWMXdV0Ds zd-iPf@8AFWZr!@MTUq3u)YMdeU0vNk$8n-SYkvIk#|N)f6zwePD5Z;)R{p%a>?3|! rsc7e}R4JraDMfktxx4XOJM8wqo`@$A2&IMu00000NkvXXu0mjf-X(=D literal 0 HcmV?d00001 diff --git a/htdocs/images/tango/logo.png b/htdocs/images/tango/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..a95539ed7e943e90e624d5579415eae32785149e GIT binary patch literal 42594 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 containing navigation buttons */ + background: #778; + color: #fff; +} + +.calendar thead .daynames { /* Row containing the day names */ + background: #bdf; +} + +.calendar thead .name { /* Cells in footer (only one right now) */ + text-align: center; + background: #556; + color: #fff; +} + +.calendar tfoot .ttip { /* Tooltip (status bar) cell containing navigation buttons */ +} + +.calendar thead .name { /* Cells containing the day names */ + background: url("dark-bg.gif"); +} + +/* The body part -- contains all the days in month. */ + +.calendar tbody .day { /* Cells in footer (only one right now) */ + text-align: center; + background: #565; + color: #fff; +} + +.calendar tfoot .ttip { /* Tooltip (status bar) cell '; + } + + /** + * Expand and draw a child entry, when it is clicked on. This is using AJAX just to render this section of the tree. + */ + public function draw_children($parent_entry,$code) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $children = array(); + + foreach ($parent_entry->getChildren() as $child) { + if (! $this->getEntry($child)) + $this->addEntry($child); + + array_push($children,$this->getEntry($child)); + } + + $first_child = $this->create_before_child($parent_entry,$code); + $last_child = $this->create_after_child($parent_entry,$code); + + # If compression is on, we need to compress this output - but only if called by draw_tree_node + if (function_exists('isCompress') && isCompress() && get_request('cmd','REQUEST') == 'draw_tree_node') + ob_start(); + + echo $first_child; + + for ($i=0; $idraw_item($children[$i]->getDN(),$code,$first,$last); + else + echo '
problem getting DN entry from ldap'; + + echo "\n"; + } + + echo $last_child; + + # If compression is on, we need to compress this output + if (function_exists('isCompress') && isCompress() && get_request('cmd','REQUEST') == 'draw_tree_node') { + $output = ob_get_clean(); + echo gzencode($output); + } + } + + /** + * Return the indentation before a node + * + * @param $code a string of 0 and 1 ; $code == "000101" will return " | |" + */ + protected function get_indentation($code) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $indent = ''; + + for ($i=0; $i',IMGDIR); + break; + + case '1': + $indent .= sprintf('| ',IMGDIR); + break; + } + } + + return $indent; + } + + /** + * Draw the javascript to support the tree. + */ + protected function draw_javascript() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + parent::draw_javascript(); + printf('',JSDIR); + printf('',JSDIR); + } + + /** + * Draw the "Create New Entry" item before the children. + */ + private function create_before_child($entry,$level) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (strlen($level) == 0) + return ''; + + $server = $this->getServer(); + $output = ''; + + if (! $server->isReadOnly() && ! $entry->isLeaf() && (count($entry->getChildren()) > 10) && $this->getServer()->isShowCreateEnabled() + && $_SESSION[APPCONFIG]->getValue('appearance','show_top_create')) + $output = $this->draw_create_new_entry($entry,$level,IMGDIR.'/tree_split.png'); + + return $output; + } + + /** + * Draw the "Create New Entry" item after the children. + */ + private function create_after_child($entry,$level) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (strlen($level) == 0) + return ''; + + $server = $this->getServer(); + $output = ''; + + if (! $server->isReadOnly() && ! $entry->isLeaf() && $this->getServer()->isShowCreateEnabled()) + $output = $this->draw_create_new_entry($entry,$level,IMGDIR.'/tree_corner.png'); + + return $output; + } + + /** + * Draw the "Create New Entry" item. + */ + private function draw_create_new_entry($entry,$level,$img) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $output = ''; + + $href = sprintf('cmd=template_engine&server_id=%s&container=%s',$this->getServerID(),$entry->getDNEncode()); + + $output .= $this->get_indentation($level); + $output .= sprintf('--',$img); + $output .= sprintf('',htmlspecialchars($href),$entry->getDN()); + $output .= sprintf('->',IMGDIR); + $output .= ''; + $output .= ' '; + + if (isAjaxEnabled()) + $output .= sprintf('', + htmlspecialchars($href),_('Create new entry here'), + htmlspecialchars($href),_('Loading')); + else + $output .= sprintf('',htmlspecialchars($href),_('Create new entry here')); + + $output .= _('Create new entry here'); + $output .= ''; + + return $output; + } + + /** + * List the items in the tree that are open + * + * @return array List of open nodes + */ + public function listOpenItems() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $result = array(); + + foreach ($this->entries as $dn => $value) + if ($value->isOpened()) + array_push($result,$value->getDN()); + + return $result; + } +} +?> diff --git a/lib/Attribute.php b/lib/Attribute.php new file mode 100644 index 0000000..9c4ef98 --- /dev/null +++ b/lib/Attribute.php @@ -0,0 +1,917 @@ +getServer($server_id); + + $sattr = $server->getSchemaAttribute($name); + if ($sattr) { + $this->name = $sattr->getName(false); + $this->setLDAPdetails($sattr); + + } else + $this->name = $name; + + $this->source = $source; + + # XML attributes are shown by default + switch ($source) { + case 'XML': $this->show(); + $this->setXML($values); + + break; + + default: + if (! isset($values['values'])) + debug_dump_backtrace('no index "values"',1); + + $this->initValue($values['values']); + } + + # Should this attribute be hidden + if ($server->isAttrHidden($this->name)) + $this->forcehide = true; + + # Should this attribute value be read only + if ($server->isAttrReadOnly($this->name)) + $this->readonly = true; + + # Should this attribute value be unique + if ($server->isAttrUnique($this->name)) + $this->unique = true; + } + + /** + * Return the name of the attribute. + * + * @param boolean $lower - Return the attribute in normal or lower case (default lower) + * @param boolean $real - Return the real attribute name (with ;binary, or just the name) + * @return string Attribute name + */ + public function getName($lower=true,$real=false) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs,$this->name); + + if ($real) + return $lower ? strtolower($this->name) : $this->name; + else + return $lower ? strtolower($this->real_attr_name()) : $this->real_attr_name(); + } + + public function getValues() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->values); + + return $this->values; + } + + public function getOldValues() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->oldvalues); + + return $this->oldvalues; + } + + public function getValueCount() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs,$this->values); + + return count($this->values); + } + + public function getSource() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->source); + + return $this->source; + } + + /** + * Autovalue is called after the attribute is initialised, and thus the values from the ldap server will be set. + */ + public function autoValue($new_val) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if ($this->values) + return; + + $this->values = $new_val; + } + + public function initValue($new_val) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if ($this->values || $this->oldvalues) { + debug_dump(array('new_val'=>$new_val,'this'=>$this)); + debug_dump_backtrace('new and/or old values are set',1); + } + + $this->values = $new_val; + } + + public function clearValue() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->values = array(); + } + + public function setOldValue($val) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->oldvalues = $val; + } + + public function setValue($new_val) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if ($this->values) { + if ($this->values == $new_val) + return; + + if ($this->oldvalues) { + debug_dump($this); + debug_dump_backtrace('old values are set',1); + } else + $this->oldvalues = $this->values; + } + + if ($new_val == $this->values) + return; + + $this->values = $new_val; + $this->justModified(); + } + + public function addValue($new_val,$i=-1) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if ($i < 0) + $i = $this->getValueCount(); + + $old_val = $this->getValue($i); + if (is_null($old_val) || ($old_val != $new_val)) + $this->justModified(); + + $this->values[$i] = $new_val; + } + + public function delValue($i=-1) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if ($i < 0) + $this->setValue(array()); + + if (! $this->hasBeenModified()) + $this->oldvalues = $this->values; + + if (isset($this->values[$i])) { + unset($this->values[$i]); + $this->values = array_values($this->values); + $this->justModified(); + } + } + + public function getValue($i) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (isset($this->values[$i])) + return $this->values[$i]; + else + return null; + } + + public function getOldValue($i) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (isset($this->oldvalues[$i])) + return $this->oldvalues[$i]; + else + return null; + } + + public function getMinValueCount() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->min_value_count); + + return $this->min_value_count; + } + + public function setMinValueCount($min) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->min_value_count = $min; + } + + public function getMaxValueCount() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->max_value_count); + + return $this->max_value_count; + } + + public function setMaxValueCount($max) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->max_value_count = $max; + } + + public function haveMoreValues() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if ($this->getMaxValueCount() < 0 || ($this->getValueCount() < $this->getMaxValueCount())) + return true; + else + return false; + } + + public function justModified() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->modified = true; + } + + public function hasBeenModified() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->modified); + + return $this->modified; + } + + public function isForceDelete() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->forcedelete); + + return $this->forcedelete; + } + + public function setForceDelete() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->forcedelete = true; + $this->oldvalues = $this->values; + $this->values = array(); + $this->justModified(); + } + + public function isInternal() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->internal); + + return $this->internal; + } + + public function setInternal() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->internal = true; + } + + public function isRequired() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if ($this->getMinValueCount() > 0) + return true; + elseif ($this->ldaptype == 'must') + return true; + elseif ($this->isRDN()) + return true; + else + return false; + } + + public function isMay() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (($this->ldaptype == 'may') && ! $this->isRequired()) + return true; + else + return false; + } + + public function setType($type) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->type = strtolower($type); + } + + public function getType() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->type); + + return $this->type; + } + + public function setLDAPtype($type) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->ldaptype = strtolower($type); + } + + public function getLDAPtype() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->ldaptype); + + return $this->ldaptype; + } + + public function setProperties($properties) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + foreach ($properties as $index => $value) { + if ($index == 'maxvalnb') { + $this->setMaxValueCount($value); + continue; + + } elseif ($index == 'minvalnb') { + $this->setMinValueCount($value); + continue; + + } elseif ($index == 'maxlength') { + $this->setMinValueCount($value); + continue; + + } elseif ($index == 'hidden') { + $this->visible = $value; + continue; + + } elseif (in_array($index,array('cols','rows'))) { + # @todo To be implemented + continue; + } + + if (isset($this->$index)) + $this->$index = $value; + else { + debug_dump($this); + debug_dump_backtrace(sprintf('Unknown property (%s) with value (%s) for (%s)',$index,$value,$this->getName()),1); + } + } + } + + public function setRequired() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if ($this->getMinValueCount() <= 0) + $this->setMinValueCount(1); + } + + public function setOptional() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->setMinValueCount(0); + } + + public function isReadOnly() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->readonly); + + return $this->readonly; + } + + public function setReadOnly() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->readonly = true; + } + + public function isMultiple() { + return false; + } + + public function isVisible() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + return $this->visible && (! $this->forcehide); + } + + public function hide() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->visible = false; + } + + public function show() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->visible = true; + } + + public function haveFriendlyName() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + return $_SESSION[APPCONFIG]->haveFriendlyName($this); + } + + public function getFriendlyName() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->display); + + if ($this->display) + return $this->display; + else + return $_SESSION[APPCONFIG]->getFriendlyName($this); + } + + public function setDescription($description) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->description = $description; + } + + public function getDescription() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->description); + + return $this->description; + } + + public function setIcon($icon) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->icon = $icon; + } + + public function getIcon() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->icon); + + return $this->icon ? sprintf('%s/%s',IMGDIR,$this->icon) : ''; + } + + public function getHint() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->hint); + + return $this->hint; + } + + public function setHint($hint) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->hint = $hint; + } + + public function getMaxLength() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->maxlength); + + return $this->maxlength; + } + + public function setMaxLength($maxlength) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->maxlength = $maxlength; + } + + public function getSize() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->size); + + return $this->size; + } + + public function setSize($size) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->size = $size; + } + + public function getSpacer() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->spacer); + + return $this->spacer; + } + + public function getPage() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->page); + + return $this->page; + } + public function setPage($page) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->page = $page; + } + + public function getOnChange() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->onchange); + + return $this->onchange; + } + + public function getHelper() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->helper); + + return $this->helper; + } + + public function getHelperValue() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->helpervalue); + + return $this->helpervalue; + } + + public function getVerify() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->verify); + + return $this->verify; + } + + public function setRDN($rdn) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->rdn = $rdn; + } + + /** + * Return if this attribute is an RDN attribute + * + * @return boolean + */ + public function isRDN() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs,$this->rdn); + + return $this->rdn; + } + + /** + * Capture all the LDAP details we are interested in + * + * @param sattr Schema Attribute + */ + private function setLDAPdetails($sattr) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # By default, set this as a MAY attribute, later processing should make it a MUST attribute if it is. + if (! $this->ldaptype) + $this->ldaptype = 'may'; + + # Store our Aliases + foreach ($sattr->getAliases() as $alias) + array_push($this->aliases,strtolower($alias)); + + if ($sattr->getIsSingleValue()) + $this->setMaxValueCount(1); + } + + /** + * Return a list of aliases for this Attribute (as defined by the schema) + * This list will be lowercase. + */ + public function getAliases() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->aliases); + + return $this->aliases; + } + + public function getAutoValue() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->autovalue); + + return $this->autovalue; + } + + public function getPostValue() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->postvalue); + + return $this->postvalue; + } + + public function setPostValue($postvalue) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->postvalue = $postvalue; + } + + public function setXML($values) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # Mostly all the time, this should be an array + if (is_array($values)) + foreach ($values as $index => $value) + switch ($index) { + # Helpers should be accompanied with a attribute. + case 'helper': + if (! isset($values['post']) && ! $_SESSION[APPCONFIG]->getValue('appearance','hide_template_warning')) + system_message(array( + 'title'=>sprintf('%s [%s]',_('Missing [post] setting in XML file'),$index), + 'body'=>_('[helper] needs an accompanying [post] action.'), + 'type'=>'warn')); + + if (isset($value['value']) && ! is_array($value['value']) && preg_match('/^=php\.(\w+)\((.*)\)$/',$value['value'],$matches)) { + $this->helpervalue['function'] = $matches[1]; + $this->helpervalue['args'] = $matches[2]; + + unset ($value['value']); + } + + foreach ($value as $i => $detail) { + if (! in_array($i,array('default','display','id','value'))) { + if (! $_SESSION[APPCONFIG]->getValue('appearance','hide_template_warning')) + system_message(array( + 'title'=>sprintf('%s [%s]',_('Unknown XML setting'),$i), + 'body'=>sprintf('%s [%s]',_('Unknown XML type setting for helper will be ignored.'),$detail), + 'type'=>'warn')); + + unset($value[$i]); + } + } + + $this->$index = $value; + + break; + + case 'hidden': $value ? $this->visible = false : $this->visible = true; + break; + + case 'spacer': $value ? $this->$index = true : $this->$index = false; + break; + + # Essentially, we ignore type, it is used to select an Attribute type in the Factory. But we'll generated a warning if there is an unknown type. + case 'type': + if (! in_array($value,array('password','multiselect','select','textarea')) && ! $_SESSION[APPCONFIG]->getValue('appearance','hide_template_warning')) + system_message(array( + 'title'=>sprintf('%s [%s]',_('Unknown XML setting'),$index), + 'body'=>sprintf('%s [%s]',_('Unknown XML type setting will be ignored.'),$value), + 'type'=>'warn')); + + break; + + case 'post': + if (preg_match('/^=php\.(\w+)\((.*)\)$/',$value,$matches)) { + $this->postvalue['function'] = $matches[1]; + $this->postvalue['args'] = $matches[2]; + + } else + if (! $_SESSION[APPCONFIG]->getValue('appearance','hide_template_warning')) + system_message(array( + 'title'=>sprintf('%s [%s]',_('Unknown XML setting'),$index), + 'body'=>sprintf('%s [%s]',_('Unknown XML type setting will be ignored.'),$value), + 'type'=>'warn')); + + case 'value': + if (is_array($value)) + foreach ($value as $x => $y) { + if (! $this->haveMoreValues()) { + system_message(array( + 'title'=>_('Automatically removed attribute values from template'), + 'body'=>sprintf('%s [%s]',_('Template defines more values than can be accepted by attribute.'),$this->getName(true)), + 'type'=>'warn')); + + $this->clearValue(); + + break; + + } else + $this->addValue($x,$y); + } + + else + # Check to see if the value is auto generated. + if (preg_match('/^=php\.(\w+)\((.*)\)$/',$value,$matches)) { + $this->autovalue['function'] = $matches[1]; + $this->autovalue['args'] = $matches[2]; + + # We'll add a hint too + if (! $this->hint) + $this->hint = _('Automatically determined'); + + } else + $this->addValue($value); + + break; + + # Queries + case 'ordersort': + + # Creation/Editing Templates + case 'cols': + case 'default': + case 'display': + case 'hint': + case 'icon': + case 'maxlength': + case 'onchange': + case 'order': + case 'page': + case 'readonly': + case 'rows': + case 'size': + case 'values': + case 'verify': $this->$index = $value; + break; + + case 'max': + if ($this->getMaxValueCount() == -1) + $this->setMaxValueCount($value); + + default: + if (! $_SESSION[APPCONFIG]->getValue('appearance','hide_template_warning')) + system_message(array( + 'title'=>sprintf('%s [%s]',_('Unknown XML setting'),$index), + 'body'=>sprintf('%s [%s]',_('Unknown attribute setting will be ignored.'),serialize($value)), + 'type'=>'warn')); + } + + elseif (is_string($values) && (strlen($values) > 0)) + $this->values = array($values); + } + + /** + * Display the values removed in an attribute. + */ + public function getRemovedValues() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + return array_diff($this->getOldValues(),$this->getValues()); + } + + /** + * Display the values removed in an attribute. + */ + public function getAddedValues() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + return array_diff($this->getValues(),$this->getOldValues()); + } + + /** + * Prunes off anything after the ";" in an attr name. This is useful for + * attributes that may have ";binary" appended to their names. With + * real_attr_name(), you can more easily fetch these attributes' schema + * with their "real" attribute name. + * + * @param string $attr_name The name of the attribute to examine. + * @return string + */ + private function real_attr_name() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->name); + + return preg_replace('/;.*$/U','',$this->name); + } + + /** + * Does this attribute need supporting JS + */ + public function needJS($type=null) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (is_null($type)) { + foreach (array('focus','blur','validate') as $type) + if ($this->needJS($type)) + return true; + + return false; + + } elseif ($type == 'focus') { + # We dont have any focus javascript routines. + return false; + + } elseif ($type == 'blur') { + if ($this->onchange || $this->isRequired()) + return true; + else + return false; + + } elseif ($type == 'validate') { + if ($this->isRequired()) + return true; + else + return false; + + } else + debug_dump_backtrace(sprintf('Unknown JS request %s',$type),1); + } +} +?> diff --git a/lib/AttributeFactory.php b/lib/AttributeFactory.php new file mode 100644 index 0000000..82cf562 --- /dev/null +++ b/lib/AttributeFactory.php @@ -0,0 +1,188 @@ +getValue('appearance','hide_template_warning')) + system_message(array( + 'title'=>sprintf('%s [%s]',_('Unknown template [post] function'),$matches[1]), + 'body'=>sprintf('%s [%s]',_('The template function is not known and will be ignored.'),$values['post']), + 'type'=>'warn')); + + unset($values['post']); + } + } + } + + # Check our helper functions exists + if (isset($values['helper']['value']) && ! is_array($values['helper']['value'])) + if (preg_match('/^=php\.(\w+)\((.*)\)$/',$values['helper']['value'],$matches)) + if (! in_array($matches[1],array('GetNextNumber','PasswordEncryptionTypes'))) { + if (! $_SESSION[APPCONFIG]->getValue('appearance','hide_template_warning')) + system_message(array( + 'title'=>sprintf('%s [%s]',_('Unknown template helper function'),$matches[1]), + 'body'=>sprintf('%s [%s]',_('The template helper function is not known and will be ignored.'),$values['helper']['value']), + 'type'=>'warn')); + + unset($values['helper']['value']); + } + + # Check to see if the value is auto generated, our attribute type is dependant on the function called. + if (isset($values['value']) && ! is_array($values['value'])) { + if (preg_match('/^=php\.(\w+)\((.*)\)$/',$values['value'],$matches)) { + switch ($matches[1]) { + case 'MultiList': + if (! isset($values['type'])) + $values['type'] = 'multiselect'; + + case 'PickList': + return $this->newSelectionAttribute($name,$values,$server_id,$source); + + case 'RandomPassword': + return $this->newRandomPasswordAttribute($name,$values,$server_id,$source); + + # Fall through and determine the attribute using other methods. + case 'GetNextNumber': + case 'Function' : + break; + + default: + if (! $_SESSION[APPCONFIG]->getValue('appearance','hide_template_warning')) + system_message(array( + 'title'=>sprintf('%s [%s]',_('Unknown template function'),$matches[1]), + 'body'=>sprintf('%s [%s]',_('The template function is not known and will be ignored.'),$values['value']), + 'type'=>'warn')); + + unset($values['value']); + } + } + } + + if (isset($values['type'])) + switch ($values['type']) { + case 'password': + if (! strcasecmp($name,'sambaLMPassword') || ! strcasecmp($name,'sambaNTPassword')) + return $this->newSambaPasswordAttribute($name,$values,$server_id,$source); + else + return $this->newPasswordAttribute($name,$values,$server_id,$source); + + case 'multiselect': + case 'select': + return $this->newSelectionAttribute($name,$values,$server_id,$source); + + case 'textarea': + return $this->newMultiLineAttribute($name,$values,$server_id,$source); + } + + if (! strcasecmp($name,'objectClass')) { + return $this->newObjectClassAttribute($name,$values,$server_id,$source); + + } elseif ($app['server']->isJpegPhoto($name) || in_array($name,$app['server']->getValue('server','jpeg_attributes'))) { + return $this->newJpegAttribute($name,$values,$server_id,$source); + + } elseif ($app['server']->isAttrBinary($name)) { + return $this->newBinaryAttribute($name,$values,$server_id,$source); + + } elseif (! strcasecmp($name,'userPassword')) { + return $this->newPasswordAttribute($name,$values,$server_id,$source); + + } elseif (! strcasecmp($name,'sambaLMPassword') || ! strcasecmp($name,'sambaNTPassword')) { + return $this->newSambaPasswordAttribute($name,$values,$server_id,$source); + + } elseif (in_array(strtolower($name),array_keys(array_change_key_case($_SESSION[APPCONFIG]->getValue('appearance','date_attrs'))))) { + return $this->newDateAttribute($name,$values,$server_id,$source); + + } elseif (in_array(strtolower($name),array('shadowlastchange','shadowmin','shadowmax','shadowexpire','shadowwarning','shadowinactive'))) { + return $this->newShadowAttribute($name,$values,$server_id,$source); + + } elseif ($app['server']->isAttrBoolean($name)) { + $attribute = $this->newSelectionAttribute($name,$values,$server_id,$source); + $attribute->addOption('TRUE',_('true')); + $attribute->addOption('FALSE',_('false')); + return $attribute; + + } elseif ($app['server']->isDNAttr($name)) { + return $this->newDnAttribute($name,$values,$server_id,$source); + + } elseif ($app['server']->isMultiLineAttr($name)) { + return $this->newMultiLineAttribute($name,$values,$server_id,$source); + + } elseif (! strcasecmp($name,'gidNumber')) { + return $this->newGidAttribute($name,$values,$server_id,$source); + + } else { + return new Attribute($name,$values,$server_id,$source); + } + } + + private function newJpegAttribute($name,$values,$server_id,$source) { + return new JpegAttribute($name,$values,$server_id,$source); + } + + private function newBinaryAttribute($name,$values,$server_id,$source) { + return new BinaryAttribute($name,$values,$server_id,$source); + } + + private function newPasswordAttribute($name,$values,$server_id,$source) { + return new PasswordAttribute($name,$values,$server_id,$source); + } + + private function newSambaPasswordAttribute($name,$values,$server_id,$source) { + return new SambaPasswordAttribute($name,$values,$server_id,$source); + } + + private function newRandomPasswordAttribute($name,$values,$server_id,$source) { + return new RandomPasswordAttribute($name,$values,$server_id,$source); + } + + private function newShadowAttribute($name,$values,$server_id,$source) { + return new ShadowAttribute($name,$values,$server_id,$source); + } + + private function newSelectionAttribute($name,$values,$server_id,$source) { + return new SelectionAttribute($name,$values,$server_id,$source); + } + + private function newMultiLineAttribute($name,$values,$server_id,$source) { + return new MultiLineAttribute($name,$values,$server_id,$source); + } + + private function newDateAttribute($name,$values,$server_id,$source) { + return new DateAttribute($name,$values,$server_id,$source); + } + + private function newObjectClassAttribute($name,$values,$server_id,$source) { + return new ObjectClassAttribute($name,$values,$server_id,$source); + } + + private function newDnAttribute($name,$values,$server_id,$source) { + return new DnAttribute($name,$values,$server_id,$source); + } + + private function newGidAttribute($name,$values,$server_id,$source) { + return new GidAttribute($name,$values,$server_id,$source); + } +} +?> diff --git a/lib/BinaryAttribute.php b/lib/BinaryAttribute.php new file mode 100644 index 0000000..6b5053b --- /dev/null +++ b/lib/BinaryAttribute.php @@ -0,0 +1,60 @@ +filepaths = array(); + $this->filenames = array(); + } + + public function getFileNames() { + return $this->filenames; + } + + public function getFileName($i) { + if (isset($this->filenames[$i])) return $this->filenames[$i]; + else return null; + } + + public function addFileName($name, $i = -1) { + if ($i < 0) { + $this->filenames[] = $name; + } else { + $this->filenames[$i] = $name; + } + } + + public function getFilePaths() { + return $this->filepaths; + } + + public function getFilePath($i) { + if (isset($this->filepaths[$i])) return $this->filepaths[$i]; + else return null; + } + + public function addFilePath($path, $i = -1) { + if ($i < 0) { + $this->filepaths[] = $path; + } else { + $this->filepaths[$i] = $path; + } + } +} +?> diff --git a/lib/DateAttribute.php b/lib/DateAttribute.php new file mode 100644 index 0000000..e1a687f --- /dev/null +++ b/lib/DateAttribute.php @@ -0,0 +1,17 @@ + diff --git a/lib/DnAttribute.php b/lib/DnAttribute.php new file mode 100644 index 0000000..1f5c02f --- /dev/null +++ b/lib/DnAttribute.php @@ -0,0 +1,17 @@ + diff --git a/lib/GidAttribute.php b/lib/GidAttribute.php new file mode 100644 index 0000000..7442a07 --- /dev/null +++ b/lib/GidAttribute.php @@ -0,0 +1,17 @@ + diff --git a/lib/HTMLTree.php b/lib/HTMLTree.php new file mode 100644 index 0000000..90861cb --- /dev/null +++ b/lib/HTMLTree.php @@ -0,0 +1,587 @@ +getServer(); + + echo '

'; + echo "$file
bB! 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 literal 0 HcmV?d00001 diff --git a/htdocs/images/tango/logout-big.png b/htdocs/images/tango/logout-big.png new file mode 100644 index 0000000000000000000000000000000000000000..fddbc2bce1a6b3742bba65b0fa950659873db5ab GIT binary patch literal 1725 zcmV;u215CXP)@Zvc|T?kRczL0SQE%p*r{ang#Is zmDhe5MbWkIxJawjB8nn{ARr7wq9{s79LGp0u`G*Xp}^IvR~a8ah7h6?6wq4Zc^>cm`ubJi z?T+(-QLxer%fd8GEXzVlnO-ZUP)d=c$}kKZ$Dv%Vkk98ZO$#AJ2civ7DwP-+sRERM zW`}M#fa5q=mW6HGNGZ`;ca6lf);Nwsu~@{i+MzcLBNG7yK&ey$$kAONg8^LE#c>>@ zl-RZnkSf<&rz*A9*tU)1I2eYJQ7<|(8Gy!V&tYaB33TiN8Gkbm5OeoEsW} zB$S3>V45bb>!$Y-V2Cf^gqS@n+r28R}4 z{fjS3x8Hi}uT!tQGLt`ctZy-P0c0Kb0wvXMnr5c*VNi_;&*QWC`A@$0>Z{X}SFTut zXsxc7G7!B$uIn;2HO1cE9^2d7nf&j!aBGYFudegt%P-eYy!4W(c6UK3<4;07>iOw6 z`vCf>PjYYDHb;*h<;amEG@Hr#l6@ci^$k9o`vKE)bBv!qZ+bUxQaE>xxp&{SF$^26 zL2Gmz^S3wNC>|Jr?BDOkjT=-d6=r8=ab0(xa(``&PoIB*<1;fHJAE3j(LhVd&gY*a z%ytQAr67(eU$`(h1-;8Q{ePNE;^fX6Loub)jfRtca zZRbhND20|1<$3!7dZW;rj!LD%*|TR^Sy}1SK}Y%ODt|x!9JR?wj*N}5_vM$M6vDQ_ zG!dqWjv};D7_K`UV32y-wwalkVRLhng@pxbwc2C#4;~P1ZQ)K#5G*Ybt*#<03mpU~ z&qFqw=pbkdv@DE5f&A&yZGVFz(5rrWdYU+nX*3$?YMI!`%nY-?`-H`>zM}Q$5oWne zu(CpU?;i2yX6hV3$1!qehj?S7KR|C9gb;%x^)Z7vdHCf={k_4p?2{iXFvX! ze=RTLM-llmXVSvMF!l`{Mg3EdO+)hOc^(T33uvv$=kr*Wl|D<%_k9k%_##hz_#t=R ze3QwsF^Xr-(E9poiqAfaa2zlULWx3{pyNHyV))L%YY-!+`+(iZKgfnkGw2%hc<2s?};I741E+JUh$1 z*M5Zf{U7`%q9|9Im_TVAUWW64544goa69XDnzU$1GoqBjYkBPM?hwaOdy}%0=PtqI zDc0xaezCm1?rkkCCC$Pvu-AbIfW4sr*$pV^3mnHG3`2x~Vxd5(R7$(1v{TOKFin%< z<;#u#)M`KZ@AkGw9BbeaumfxX+gj_WZwj&iiE<$X4Sdk!K)i_kC(^7%Y#>udNek9xh%$&)83 zSIW4KivXf1Ox^-CN@-*q;|D&~YSo{gpAYf~f6 zLC(!#**02fq9`PavK?Rd^jd4AlK8C_Ku9||2Lk|%j2!0v>bI23C7$~JlQ^z}VOqpe z5-Zhq+F5+Eoj}*@TBDSr<);8c51%Q(`o=0s$Bd3vJ4FX^6d~id?eL%m@UefCQUvYw zKRKKZ2e57X?T>!@(Y1cN;6culW~CcKW83yS91wm0(dT&H+w6Zg>D{I?W2pTPhRcoT TV_b!o00000NkvXXu0mjf;6OQF literal 0 HcmV?d00001 diff --git a/htdocs/images/tango/logout.png b/htdocs/images/tango/logout.png new file mode 100644 index 0000000000000000000000000000000000000000..0010931e2c2c35eda774f972dad5f305ff7b6766 GIT binary patch literal 799 zcmV+)1K|9LP)#yLz&Ndx##4AnMLxFXBZ(g%HuJ zXi&qdfM(p}?71_;z-a>z1OY)1kR%Cdn$l{uaL%E% z20$r|G3H}0Xl>|O*#nSQ0Qr2LFbv7%a)e>nxm#-iK?Fn;rO}H#*uEVR!P*eOn08KU zEzY@4ZV^E#g$TGTkl0Q5yTko z96r1hp-s`2)|%YZ6svCDq_A@*KN&-G|2`-NL;2>{ay<)mpM1>)Xl?vJ194<}C>UEMz1(#)? z2-^S9HcD2kVCu*bayPCMH=C^7umK&0EG{h2Qi}O%6`Yd}!S|+-h9S4NY{31bkNg24I=4Iksz%a>Tzznj;k653ieJ|1K8_%QpT zsQ-%yp65||Q^JNmza1DLpU)yz5Kkbm-p{$%*@Oz8Th_`>gu&CBehx;5n=4n*f;C^bvfq< dg5VDz{U1L){aup)rDXsB002ovPDHLkV1hluXGs76 literal 0 HcmV?d00001 diff --git a/htdocs/images/tango/mail-big.png b/htdocs/images/tango/mail-big.png new file mode 100644 index 0000000000000000000000000000000000000000..3f248dc3a2e476629d3ec18c6d30ceeabc4d6869 GIT binary patch literal 1492 zcmV;_1uOcAP)b0cu%&C1tbk>qTJ>iuwW3^7 zsihTaFRB))y+A;VkPrwV1QH+w66LN1TK1-tt;7XgeoG50s?`=HHEEJ%*PGq^87FoU zkL?+cXXc#4MQqE7o!ubREBZ-CGe_Ud_de(SX3l~C$Co{{=E>8~JSheS5=z%}v6GjT zQkTuO%dV^}hkkR#JO|lFbt!uc>UVE^7=}*!f2XC zHk&09i4YEl(RA(d005Clgh(VpCX>N1jLSOFeDC`{QYt`i*j_G|F-?3YG&GmkMni z2(}a7x`6-&1xmRHL=2dIm?p37o(kaQzr6hh zgp^dOg8u$~IyyS&?(X5KXP*ho!sC&L#47|+nK2hkN)vr{OZTwW>0(n?fBS^$Au-6s^?R61+FjgYyW)62oQ}JEY2_U?7g=V zjYjKQy}&A37oE%i~)2YV0Qc6D^< z<`cUOIa8a55YY1z60L5mNEqsR^W#7E0!Q$9%J# zojzgC{Ov5@)P~h8T#t4RY!@9s7^30f@7?oIba&4$zJ53vv0cfo&Jch9V4S&=4;-q& zyR}hm5^wwAv^|Wri7HS8tFZ9y;|~?rmhbxD^rT&N93@0!VQauTVAihdKxsSi&kFz> z7FGc>^UtSV@TGGsHGN@ic0TLr8^>@KSYhJ>vuJJQ7Y5iA3nw4>NR#^5!ou>5+&DWV uZTkE_0|2;m^8Rd4MQ#R;f6-cB&iD-U+TB6hs=z=10000UTuL>Xl;KT0w}3p7GEL7SF^n-FX(tptm{(Al(fBT}n& zG9j%pn`yE|F)mzXQH^HV$0Q5`ZGn)tP19t2{4qxx8(9-r0i=`wR903|RUIZC8^^LNEXyJg2yh?}z_Kjv-haUHrY1^*rL6xFq*pY10i@#q zpp>GbqJm&B$ivYnPCgEhUiC=M3eKO+`J*qFajeE1Kx0puXDKeWXlrc&;LFkm zcLv4)$Y!%l&#&<+^#QT5zI6l-kN5B1GMkzy6t83?mj}k^@9hSl^VSn?4^MEe?F7op zkFcrlU%ydTSI?pHasWOptkKyQsUH^qRlHy3)AgqT1ie$72;)~@Cb0t*v-Xlb^?%kbbU*WZ#RJCy-TmlLg5zR b#rE892t`wcq{hbX00000NkvXXu0mjfX%#W& literal 0 HcmV?d00001 diff --git a/htdocs/images/tango/minus.png b/htdocs/images/tango/minus.png new file mode 100644 index 0000000000000000000000000000000000000000..00b654e8ca567c380fa477d4b32f808c3b5500d3 GIT binary patch literal 247 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkEZLFV~EA+w-YyVHU|i_?Pt%tbHGab z1&5^a+FUmdNd@kXwZ%tROFFJ>Q*!zI&R_A==FP^f@-i~)|I20A*?&KNrgrv}l!w`~ zS-W;DV_2Rr!zN$cO_)z&Zy0B$7WFVdQ&MBb@09MjczW@LL literal 0 HcmV?d00001 diff --git a/htdocs/images/tango/monitorserver-big.png b/htdocs/images/tango/monitorserver-big.png new file mode 100644 index 0000000000000000000000000000000000000000..b62959e4f3d7871c986f24c6f112153561912ea8 GIT binary patch literal 1886 zcmV-k2ch_hP)-U0|+Dp3WA0}6@ieFRyc7|mpHW@J5HSS{_yVJ zJ2Qued%e4^od}^Y(&(O4AIEWY$i^<`y(gKDE}g8M^PBd1 z*U9K*rQiPM*KYwQLucKyVLS5y-m+t7r**DU;pAUve_)o`z*kQfIH{eHM)(1dq)$dsb8~Mp?@G? zdD)>Pf=Pv|Ch_*^fmffz-z#1f^&amPF^1V0kBGtdcybfs9D;T0b^#&`^a;Z|GAu4R zTpFEq9-3P30X%plS$m%dwCRh(%rK3Qv2R13-RfwEoy%IY`LfAQ;XJ}iVd?CQP#M*3DiPwdvLaY~@ zcGt0kR^*vqu5)Ll(N&|x=zTFY}!JB^}L>6u2XM%3WY4Cz6_I3m*_8t1P01wgZHpw z7!K?W`RGPWwc%+;j&@{eMV4mU5=C(ue+Lp^0zrMk--vm%2bz)6uCy@Kn888Aj^RA3 z%~ez(S8Q?n{wmKrU*L&d1+t|YvonGK17%OPpk(rbY6kB->P=FHttX1%USjFiSs)0R zjGn8$o33%VW<*uAH~x4$(^K9d84zzE|z3jAa0KFzk}xr0M|ZZc$aD9_dD z2OQd8=IApqr;iso^3)J!Gp0M^UOh{p&paB0B0?b-(3cItBsu=^T!mZnZ5l0j;kkf) zPxR4hd9K`0_U-bVd8wb#p+5e0^*&QGEz~QDPm7X*_gL@n*3w$@X&OERgtNES_|e-H zkPwjoF#*N|m>^)^lTdG34nEn(?Zp;1Z{@f;)8h1zK|Z)r=v=BX{5=N1yR!;;bGbAv{bKxGWR3r9J6uCKPX*6^EbIPK+%AYT1S*~PJ zJc>g_5OIhoNC2WBn%*JiAs(Pxsgh|hVh|G`#?WdT7VcWcwtH?b3Z5MEiy3N-kdL5TB)%4!}l9-{(S zR1Kn<-lTpbKQAd{`k;uJH0mfEG=ElL-luo1B74cZ0WIwlei$8p5c z^3n#yItr*N%~q4x##kF;W80x)Yq2)QIoJ6xj$`6>M4{N1A{$!GCdLT4d_FNMwzQ*& zLLrYa-7=jCGab6K>%C7}XxrOPTdZ?Qi@ia(<v$v^N>)f3Fm?-LotrvvG7}Jhzj1hygiNHq*2WZsl3=Iu&^ysmU^$Hw5e3;3} zN$T|mjYfn1{y~l%JB|^_T4Y--n0ArB4)p}F8qJ} zoT{p|*3C{|pZ>vx3xE0}u()3T4A2jhfE-)2YL8*~B&Ni`Do_KQZ1G~Za6kUht;y;5 Y4{P?sxg-E8IRF3v07*qoM6N<$g5g<-#{d8T literal 0 HcmV?d00001 diff --git a/htdocs/images/tango/monitorserver.png b/htdocs/images/tango/monitorserver.png new file mode 100644 index 0000000000000000000000000000000000000000..8734e777a1799c9a9d0293d692b3549f2506f418 GIT binary patch literal 611 zcmV-p0-XJcP){lZ-v(r|Lj~5OgyaOZ2LJfeicB?^@C`JZr?Az7B z%cTZg`BR8Uk|Z%vq7ZR}iq)SDP7c%v1Bu8L;M*)gFoKYRtH+LS+(amWlo3J-J~!s*-9O61 z*EP)dJ6L0}#{PPO-3oZ}uA3-Ts8|uj3L!smu=5$dStASro-Xy${E-2R?G0dc-WEsb z9nLu}J?g;u9cXRPR%3Ci1{(odXN(OGaBuF_CfwpYz>BthSnKb xD?=NN)@$d68cm~7Ux!IxdUEo{_J8C5<|lAN08`nh^nm~X002ovPDHLkV1lX$`TPI? literal 0 HcmV?d00001 diff --git a/htdocs/images/tango/plus.png b/htdocs/images/tango/plus.png new file mode 100644 index 0000000000000000000000000000000000000000..1aa7f095c6c282262390748ab2e596a3fc15c228 GIT binary patch literal 323 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE7hmi)!cT|6FkAON{jSt(_u!Lq7!B=^4B;IBq%dL`6}O%gpGjO3}J1 z4Y?KfzQ;%l3Rp(0FF*F|EI&io>j^)N99Xu9ZE@HjcqrgTrepSr)S!;v7$d z7#j|r*sm7k|1`qSzwL6X$#3JGkN$s>{Cx9Ec6v|es;&OpMC)hUh7@^ocW)~11Nx1@ M)78&qol`;+0M{XYA^-pY literal 0 HcmV?d00001 diff --git a/htdocs/images/tango/refresh-big.png b/htdocs/images/tango/refresh-big.png new file mode 100644 index 0000000000000000000000000000000000000000..606ea9eba46b82eea04678e64369b97e595f9da5 GIT binary patch literal 2024 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 literal 0 HcmV?d00001 diff --git a/htdocs/images/tango/rename-big.png b/htdocs/images/tango/rename-big.png new file mode 100644 index 0000000000000000000000000000000000000000..fd43de3d27e5350e637309df9ee5964ab8e1921b GIT binary patch literal 2223 zcmV;g2vGNlP)HmpGSz8WHpYw|>rxc9pgZmHEhwZ+e`fH6&K2zfzy*(m!{H>Q6p%pC#3G$(jyJmt zda3%t6MlboPNvsKq?Blg)C!B0M-n)C!LWiQbJN?%MAeFFRYmTlX* zloGl9@|eQZ$uF%doz_wJ;)^c^C?PLRzGsSua}G)g%8nm1EXg0fIc6`PvNo&Vgq+Oa zL;{H01B5~$VH?IHhmRaeGDczBHl`L&bLooyw@@ggq;(FL`s$d`g*s&0?=QYQl>)GF z#nKgDcZ_%JE!;~r$Gkyf7dm9}Adc^vetQ4_SiXGK2`faWn1e|jeO}y7d2z~yA7hVXenznUn@eHSBSx^*)BS#Mo&z^62rh7P_b zHAYGoEehS(cus6XKLYyaf(d_ca-#y=xQ2MN8TB<`NWmcl$M~6>I>lDHWb4K}@9tQp zOq`5Ey|Uo_@O`wNJp<>ptHkB&^%Q_t06izpL%ojwT+@UyKAMU-ug$JCiIDC97ebnU* z6b1&&RE+4qAcc*(>Pt4atv%k946BiqmTd)u5Fh}Au)43n7GRq0 zbiQAZn;S?ZlV)W&TywFu_D_}J%MnQka(um{lE7&IsE+bq)wVQoqEJMVF|%qw*#1V3 zqb6F9(K-33+Y~|M1Eb}tL#$877o0);>ZE z{2AvZwvg)#)0DcyK^01e06++^y;4uukVsfDb^Q9LlyPqtA+XSkGuJL)L~tNl|Eal? zKgEs1N827CFyg-Fx&ly2SLXWtSxLj-@l@*QFNBz14A=mmQ~CoZ-9Jv_*eD&N;2+k30YLKpCtM=m6+9r># z69D%BfJ{Gxf}`SSX;%OOxCj8tw%J^u7JzddFilt0{bLIXvaUy?iAE{6Ee4zba!Ti8 zj+l+%UpLhu;Ld>R1<$wc@d zE;Q94HX)9_zx9GKKuQ2o;#&9u03iKcaO1;d2c-)bV@oJwOb9`Q5apG&{d@?hYOfT1 zWeH{!{7#y+pVn}|P0t16>+vs(_3ptN?0V3NT0!T&)%Lo8e1Dhq0zANYU0@&NrVYdwl!0K@Y&<3jk(A!(JLz{Mn|L(3FZF`B;!OeD0 xwzu|o0l3*ndotSIPkY*A2XCJbNc_Lqe*kuA<%vrkd>a4&002ovPDHLkV1iQs5V!yU literal 0 HcmV?d00001 diff --git a/htdocs/images/tango/rename.png b/htdocs/images/tango/rename.png new file mode 100644 index 0000000000000000000000000000000000000000..c8d899cff2a5d6cfabb70db4cc39c300914069ac GIT binary patch literal 937 zcmV;a16KTrP)~s5J7JDPHfNEe|jA6@tsBpG4bKa)0S=9 zi&w|44DR@szZ%UP>gnwRaObh`%K*OK1t_J=d-JpW#PPl!rPO`^7{2tyE79g?q*&Tu zTI=qra698-k}=`g1#r$w3k(0iGz?ZQm*ZE*t_(^kuf<|9tUOrJTI>1ku*HSA-qHPO zPgozywY?U5?v&{kC!yU90FMFAo=N=1IsbNcE~P`E5Hb%k zL`37y*C(Fxcx%shb`SX7(ljbti_ppjh`_1=6XEcvOLWrB=S{dSo(?x5O?oqU(DuG? zX+TQ8hGOmp4AX=+^agJKlu!ZyCL)o+BbCbaPRr^J2_cnosq8wa3)HYi)9@I}CjWJK z3ZBLsvRii%YHR}cwqy1F&%}R>M&EUExuMQ*SkEjiT`O#DI{Cr|_Z`+PLNfeomr#hA zXm6-TGBJnzltjgGpxrVE1nxS{@V?eoN-Zy6IHpu@t?5(3=TnWZ^Y8!8tRNT+ApT_o z@-MBqd!rF5-taX=fWPX+>)JyM#&Lcwpf9|%3W2Y!;cH}n_G zSGOb>FyrPtSATz4FqXT-w&T0C?39fNZZjD{y+MC*`V$Re99;E`7$ zK5`JgNDM>_j~@O>tm;Ab0l3AOG==m#00BhXQ`$W>?bJk2%J%&S5vFrO$L{Z{00000 LNkvXXu0mjfs=~K$ literal 0 HcmV?d00001 diff --git a/htdocs/images/tango/request-feature-big.png b/htdocs/images/tango/request-feature-big.png new file mode 100644 index 0000000000000000000000000000000000000000..aadcb91292d0e5ad5ae38b4965a9a87b6229992a GIT binary patch literal 1686 zcmV;H25I?;P)w3S*^VjfVCT2v$`ky7;rNrYvGq>ck2 z4m5UbC%&xL-rbpo&^&udHFs0FLN~0Sg#Q&W@-vPd3W*R!pOhf0%E*}1}NKx#75PCg|QZpGJm>(n=`0j0vDMC1)O^@ZG? z&sut-AAsB^KV#+3_3!K3FAfSr)=SBqnUF1JrlAt~#f0)JKUlK@TJVOH1RW24+X+1n zZ({V;(%7ZW*^!Gu%Z}TU!W&1=i~=B%&3x?6dy}KR$G)H5aHHksS`E8tJ*MqAXAb?m ztR%+J;#92zZ+~6vM2K$7b~m@~*=xJ?Y1HV_Z8UGW7qPDOYF|wa5}jLEtX#i~ zQog{@TgSbiTskk%2ev=2`&K1zs!OD_o)G#Xjbryz8-L1bqCzKeNJ5Br}MHHY%RarIWp0IbWDY>8|ZB=p(Qw2Mjn3^ps~y zqMV-utwCB4MRUh(-q5jCX-Y5ikLF@%jhD~k7t2BmdNAl;p}>6W?GpD%_CB8Ut|&Yty36BC69zP0O+er1V5 z)spbc*F;@lb5INU-CWxyBfFtls>}UXS1y}3W9@zbVc84Vl@dYEi>QhB=X_eWGC6W3 z8XLTzgjT^bDQyL$5JFWWQM*9Q-E#IhZUV~F3yGx^s5sI5B0>KV@QZWblv?of z3OG(eO2Ovi`-1x*DG(Ghu<8kaIO4QtfCYL*sNwX9Q!!7zIx zROojnJx&bfIbHDKZgu%*nTAbRP6mKLNydk-s6V}{ew<1aMMqhRHBY{|JK;;<{KSk+?~CyN9uAOR#}a2v2UHIO;{W%0)w+H#Em7YD~Czw&3j zf2hDLPyxI}R*s()AOx;02V$lX5X7><+#ZG(rl|b&1O3A<8dshLIC4S%XsEzg>|a@A zer#bprk5YZnuTbQ3X-{FWW|K%pXNUv5YK20`wr_zV{$463uEHJqQ0s|p!TIyYb}IO zu@dvagLq{UFkU*VABhwK$g{A&QS2Knde_y!S5=^j8q2L#5xWYw8t|G3EF%I7IWhmf gJcuSn{;-(;1^C<-LPUa-MF0Q*07*qoM6N<$f^RS!m;e9( literal 0 HcmV?d00001 diff --git a/htdocs/images/tango/request-feature.png b/htdocs/images/tango/request-feature.png new file mode 100644 index 0000000000000000000000000000000000000000..ab8d494bb3367bae188d0c31dc7a05e86d83a87a GIT binary patch literal 740 zcmVEh306QPEcFidJh)h*{a}$Ny`_LyWBA zwsW56H_SZqh?y~}nsxaS7^^jGc2tjy0yOKgLA+~$i>=6a)*ANwKLO3Ud;^q$Yrrk> z?#HoDCTD{3I$4^(dRYsd0`>s=fl{qu=Kz8s*atqYoN-Y}^KKg#me_pYi%`60`Tm{5 z)_vLYm8!#3@?PicnrIks&4p1mK7FE;_WNj-;?gB35_TS$j>LPyN|^_9zjX6n=lAyk zZe-ndn7&*h=sg58{Gsmv2!Hz?Oi`Jjzxb>ITwN2n*ZY4cPR{$Nq`K0^k^#E>2#Kml zR7IB`VS^R&&N4w<%A9vUHS4k&KyDuAgovCS+qym6wENT835Ud(KD1>pw? z@qH5pP8uridAC!U4$FdZyoV{)vU_~anizw&FuffGy-yr)i|FY)$PyKrkN=j13{7l$sh8kRr(E5NL&1 z>!1#!rDOlGGqnS){h%GE){$|>KiZj6XZnZJPIa)3EiIJ}(L#$lXqBKHAfN#Qq>Cn- z&Ayl2_ujp?e}sKa0!SU{^vs-j_v_vB+jGu6cOU$pMOFv+#AIiFq4h=gm^qo0he(dDAnKv}nMC^z~ z(Np9LKIv4PWTLG6z5b!=v%P7w7n6c*34cds7n=9Ua))@1PNF=hvvaAV^ z!+xC6Yi?xu;&uiG^8{)v7s{fNXJ34oFH|1G7!$5nN-5v>pLbpN-aUKv6ek1N<2zbg zr=<@5p|$?mrcIlcc6N3mr3^PT#*lZ5+_vRuqy#U}Xl)o7^{GjxkanD%J9lD?8L!qe z&pdNycX#(2z!M(}Q1tcb`Ar{;h(R%b#flaD;gue~`Q%F%xy`mELI^xxp|wF9Lo8z9 z6g*~cd}_klFMY9@hq_kN-QE2Fumdm?_8Q;G?0e*2(Q7t*b=mE=r!C8(V|ESSzkd-= zzu3dlg`cIoEQ%!swj~jO=WDbvXl*b8wryFBlmcVm^~3LTZs0uM`0`v*sT6H(ZOuZ6 zrMq_R+ILxi3v&OeRjbJ7^Z35c%8o`dgD$%d{*&8oX(N*z#VrIF491Lw#VrQB@YfT# z#enwa8UnAtk)wV5{98-WD!_3ZmM>qKJC_@qt9kXUV@$0oM;SvlUu57Thxg77bLM=WY`#cSZHh7*{{H4M9(!;x=~Nsk zC8MLGG&eU>QBkpe-MV!(mjw_)Jg{-&M&Y_{sgKqgr4$d}-NCd}j91?}K{{DRcBDwo z^-y{&q_x!*%)G9WeFxv++jqA!^SVlmF$f_r#^C!t%a$#RMk0~Tmjqa{WQi?=xUapv zoqRrzZQB@QP)ZR50V?qM!RGly@j2OdhMQ(jBN`biq?L&%H?`F8^1*lLTrh)PE z!qX$A#C2UdIywNhY~Q|JUIdU%r`If6w5T=`iBKpMkWvx^0iNekEEXvii)a<_=mR&C z%MNpP;3MYGo<_VZ!mV@bdF}09>Z@biaqEn5z2|uZL4a-Bc%DZxnPkqKIWrF*KD^>0 z03pQJR<2x0E|&u!2m*{T;U>lywAMr{!;dz%bNu9K2D3TV-ZGQk_s@~b4)b7VGoI(+ z`#!$!69fTLN|aJ)t#MtK#fukXS=N>b0PEJRtF5lCUe(ahfa5qQrO4;=0F;-Phs8)K zg;I*ja>)I7TwnnTagQ*8Z8 z8&j(iM59sS@i@t3l4LT8=Xp4egOm~}C6P!3r4$PnF0{4Q_rrxcAcVNPy}cdRb*Zhb zC7aDMGBSb?f*=UOwq;o)lSyFg{NJ2T^ShrkP*H9pr9^9u)_N>ov<}~qQj$ugsIIQ2 zzrUZ3jt=(j-Fpx4<5D5|Ofs2dWMqW1XV0RwM#{1Duq-PysI?CBq12Dr;QRgr&&6Uf zg!s=rXN)1A&*L}_T5G0EnS$2(hR_2*%=0{K+YVnGe*u-AC8*2IkDn{)__!Lx;nJhw6?b5c^)k-Effj`nwy((9EYZ+ zCUUtPsZ^?T)QKKi3?iBCBB+Ir34qW0OT(K@o!k3U4Q?i+IRo}002ovPDHLk FV1jL*$BzI2 literal 0 HcmV?d00001 diff --git a/htdocs/images/tango/save.png b/htdocs/images/tango/save.png new file mode 100644 index 0000000000000000000000000000000000000000..22ff49571020a2b520d34f622673bea031cbbf2d GIT binary patch literal 911 zcmV;A191F_P)UFWod3@ax5SUXmoUNIxjD3X>Dy`V=irVb7^B}VQg$JV|oe-V{&C- zbY)~9cWHEJAarPDAV*0}P%H{)baZe!FE4j@cP?jXZE!Aca%X3X$43AF0)$CKK~y-) zosvyRRACf`pSj)f=Fj9z;I%Q$k+M;2QBgD|6u8J1MHDVVC@g}Csliq)D#}F>R1gMI zv?vN9uqY^MThJnjM2er z*tjzZQ~_IohM*?d(88ZT78%aXyXViH;2#P!cXaKIt*nn#mz#sDYsxyRBZX^i&nNvY z!|UGX>ciJj;*mGYx;yU-{}qrteZJeB8awQX#;6}=+9+dz9;B^hBg-ombNT)Y{GmQ# z1>=94?<9FFC0|AcL_}oZb6R@S1CqM-L=p!tNYAS;()IMMw4S;y?*@nEcUhJtsg9)R zhVHYpJjTSt1mTi$w7?{V;sDV1aTK#e=lghu_XD3;vZxRO075}Q0RXz^f+)dPitQ(E z%-gYda01u!x!CiPi#;y^czkvr$ZTH&P@+)2qU%s20PVYX(wJDs%#2Mmq|uaE&)(MU z0PJaAf$|k1G6xV5B9Sl^Wic)tSjWw~4~WOA&hFy#?;glwrvv%h2{W;VNh9FnHS!gh7CNsvH<|wws9PX>FMctA?pDB z{r$MEo7eC>4_()D?>`lZMDjE6Jdbob&B(|InM?)|K}0YNgQ1}zLZMKuT9$=nS@~B` zN>N-~L@*f4eG&lIbrCfS6E%B2<@@;-!r?HbrKLopQ2?^pEI=;pcwHQ&6!E$`lu|5- lMst<}sgC3s;57fI&R>%|GfdSYVr>8b002ovPDHLkV1jlggmVA@ literal 0 HcmV?d00001 diff --git a/htdocs/images/tango/schema-big.png b/htdocs/images/tango/schema-big.png new file mode 100644 index 0000000000000000000000000000000000000000..a896697d78043cf2ed044a1a6cdcae86e736cca3 GIT binary patch literal 1759 zcmV<51|a!~P)iBq@y|K%-Qq(=Kp=?vhe?I!upOgXU=@d<#P1_K}nJjMG@P! zu`H`lOw%kpi|bqU0g7pwC;R&P&KCP~Z6FeamrtEK688o;uw5I`&zLl6Wk%OVg6kjv%rfC$1P;fm{}+If(=x;k>XTxk8f4FHbg6rAKI zTVF5r+|2n$*#-dHw%0f|3<$tz|*Z(pc#x7%b;f{{Y_FC+Ir7pXZM5XMA#&-@bH#bgCR4 zZvO=mX+6Nvqeo94KYkolRS^UM$8m7G-8hcJ#KZ&(3k$sR>Luov3|{=jDJ;ii;@&(t z6Lfi*!CQCnl-H1RBs4`KD5iP(z%DwwTlrvUo?u{~cXnproxDGBs}QVD!nU?H48uok zM&*}3KS^vhj*-jKROP3>p@Bf%URw9HQ&ro5Pso9(5?_*Wd)zcPhWY7_PEZl9>h13C z{miBSt0z}U8ymaDi)Y^8g%`ez-{<9Eq=h}r4b0q+qo)KF8 zR+1Kj4z?5CRDrx5IdX(-Hd{~t$KlQco$0ttxD0$*8%-0?%Nt0#Bt*cpYyz3|nmHZE z!88pT!$DrVG)APYz3^_+5ajE{VW_AIvaqa>mTFi~RK9aOiX=%~xHQ1Brv=+_Fbs=K z#?Snlmr1N>eD(QfaJwXQU8kxtfM!UjDa}L_k|jg1{x~kSolPM|$L>+?k*M;TNYcZ7 z?DNlc5e=@OEZt{C(OJ<<#^h>Z**Yff%%G|&>2#XcFJ2=Us%K_yQ3U=~5+I)grB1mo zJb##5AC6P$mza*L7{;SmcN~mjq~=K~8Y_xUO4X6m89p4JMV4h0MIo`0rZF5~dgOKn z%lgx%3Y0oD04gdRQt=1e8lNE?uH{#+yoD^wXqrYgnsoFmoAFsT4D_ z_X$##p4)w0|NDxEERGek=H^EKGCMna9vB3s0J|8#4b%f+Ahb%k;l8kL ze3dAAs+*b)b%v_<9`braJ6)3K1u!i;qwC8Ll1sNo=jVq9Z969ecY#S@8c^3OkT(zD zU3IXXi@vxzJ^=Vvefq#HTtFrvrY!+YtrY0(hb{NEx9zYRiRMGt~$xpLen%X%K|_MvGY{57DC{1x$t_u4wM}O%d&_> zB905S5<)OAFtBSDx%SZC-~V5Ne@U)wtR<-G^IC?buUWE&McJ}(%Mwzloy&KgU43zH z>WPD(udi>%;QQuJ9==*2(55nZ<`@S%n`uxK(s_fG*cOY+vB#HgKfUfSh(@CTBvJ;i z7dALQKFn~hpLE_}HTnhF9L^m6C;rbpTZhG-+so&ddOuo%CZL}L7gPyuCr-SWPA+@0e>rs z;@+LY+r^KZ80{jHPLebm@pp7!+h79-31OM6rz{p%mhjcv&J@DoFbPekyWPipbdzAO zAIpYnF8NG~<0FFzA+T+m`1%IY-vkA-jH0-aJbp6y0$Vu~y;vcqo0$16$6mCxHvb_| zRrU8`$P(G@0*!?qcw~jm?G}=CZpsylLaNM2sYJ18(&TAG*LB3q%*>l)GI_3Q6t@m> z_T(@}dsKo40(^_b`LJSO;>IYJ$!1b0qQZ^IAv8^6*M45R`}}@;K)pFNG0NfYRshnO rEDzqTQNhJ_!Nf33ZcTKO%jNh5gZdd1q4stt00000NkvXXu0mjfZID5< literal 0 HcmV?d00001 diff --git a/htdocs/images/tango/search-big.png b/htdocs/images/tango/search-big.png new file mode 100644 index 0000000000000000000000000000000000000000..950d792af54b114e3ba6ea4cc39577aea7fb71e5 GIT binary patch literal 2215 zcmV;Y2w3-tP)|JW_w48Qt z%aMty&C8EGxNh*FdjtNqW>?7N5FENm&1|t+x|l4cu3XJeo*zqY{LatMB!2tC&edIA zT}Y);{zM}2Jb>4h0^k>nqeqWAWm!Jm-QA7Z*;%~)-o&M}N`+nFb>m;(5n6w5(9`0P zMOolDUf?-icJR`w2BqGkNSq}|SCZ*MTNUs;an_RjdDq7Vf%#Lul;rEi2dg6iMMZ!b<`#@H`sc()!yKD zIRuAI8KaDurcHImPz6xsL8=^qPB@|$G$YS(oYfTYUi(e|SWXm0tXQ!EjIk&07y!T) zNs?gOHqKA0?nb{W)9QD6Oxw0?N_Ep@Wz%MwO`$Q$%9NoDpiEt0i+c0d(t0A z^P+9r@cDcI(6tmm?ME0Qgn&|tvQFKy%c0eYyl7GAoCOL{%2C)HM=Z*i$-qp;U|mQS z#z2S;FzQsqj9M`j!!Y1a~8+J;utf*VAzyd zSJG;9a#l@(LE#7?1jGs8=79x(E(hQ<+qN47L4eE2Yh_heawQ`#3Y-MM1f>Qi@POehsA4v!+~j4`oNsQ^H7IRJm3pP%2@($azl+UqfqQ3IE+ z7RERNr_U`x7J0+c?R>FnPM?n#MpN^e${1vha2y5d2w=|UiYvn%4I%(!G8tHwHFU=S zjIsAFU%q^>t*s5ud||ck`Cp76lMjsKipC5D@&NK2P_ThK81e+n28c+(Yyi}>DPJh4 z_wC=c*f$DE88WB?)u!ZS+vi=)$D*|#m|YV=4*r_+eVVv~|2{pF4UB9VweDgE)_;2;3t zN8i}yYIKs|$hp{KR>gEt0*Qb)U=xKWoQDUzAVjGeRqx29*tb_TI@bU2sm zX0CYmR5H_@n9h86&z9DfSHHDgn4im`uC5MVuNT#7wK*D%?g|Ej@5f>>Z83m(% z`T~L=e6(T1hBaHaZiUb1!}wGd?+jkHhsUy3u2dBOMjAa1d&j00;i;YXl12r{<#KR1 z9Eiu`ICt(G{C+=FRmF)DCnf>(_V@Q+x+4GpICA7jBc=3sb93{~&dyFWH8nv|6o{e- zp66lPHZ03Rxm<>(X-KEjIDPswcJJPeL?VG|wTe_K1)t9c#u(mx_uWFJQhDZs4?Z~g zxg}VTlP6D>AAb1ZW4f+S#pCg=OeW(kl}b=m6~$r^`FtMfbQ|IeMd*fQ{iwJ7rY*vUyqkpa41-TKFs{vTBxnswUt=hC{Q=8Z8UF~!_n+PGYZQF*f>)E-vx#Z~R zX#Bu|191Qh01b!3+X8{W@AmKC?^P59lu~qbbU>0M%*@Q-l~-Q5+TY*b%H0xtL4_I> zySuyHEiEmrZnt}#%jLSy<#O$)udm{paN5 z3O85rw6%Q4sX5n7P8sw%O8IDVc%jUShN&3 z)-611{aKCH!ce!{&2QVb?fZftJj)of0Q@=}4!;qJMCf8&P#cWL;(>1kxE;tsHWrlC p_$<2(Z}nNQYhTK4Gxz^1{{l@K_Ij~~K-~ZU002ovPDHLkV1i1lMwtKr literal 0 HcmV?d00001 diff --git a/htdocs/images/tango/search.png b/htdocs/images/tango/search.png new file mode 100644 index 0000000000000000000000000000000000000000..fd7f0b07a558cb6d59af96bebb672bf1abe96c88 GIT binary patch literal 935 zcmV;Y16cftP)&ujZZ2vcpl1 zMZ@GK2apA{PG?ddXEM`!?RHyZ=kcza{{|ocz_G78)~3_xTfzOGVc*@!;z&{~D4M34 z#HCy|oAJK^O5@u;x%xm;z_nWd04$M+pY+%HrNI}599Zr)1O{&1Fr9gQ zRx^nN(=^?Ylb_Xc3crTMTm|}8W6tGCdm-gHU zoivEbfP*V-h@Y#f29hN4c>od3S|m}D80SwWrl%O%n5zs-y=aEVV!4n`6c;!WFs{rR zhNug$8$G1gD4`4AaS<H7=eg9>uBL$90I_nW$UopHtf^aCQMJwQhI406Q(#?y zO-@ZpM5e?TYiVd$*M}u5U8hd09vd6~!{hc8oX&FDU*~sLS6AD5dV3x{dHP7z^Tsz$ zm;I-vElqH5_&#iSZzKKk>qUmIhNJ7$iG2Xj914Xt0)Xc8`7QxKZ+qL(^TA-S6B++< zPs?7gTFc=3v)=)}CSYu?u#}a#&H(^gTU%RH&GN(C?nC&$dI>wJW|L@7q6Gi|002ov JPDHLkV1n1##MS@+ literal 0 HcmV?d00001 diff --git a/htdocs/images/tango/server-big.png b/htdocs/images/tango/server-big.png new file mode 100644 index 0000000000000000000000000000000000000000..1d38e4f9c807e24f3c6ec1d169464bc4c77b5d01 GIT binary patch literal 847 zcmV-V1F-ywP)?uTqbzX*P&AH z*4EaZ`M#eU96)Q$=;$cx>+8N!>TMq1&Q$~|l?qo^S7cdcLMMtM%H^^V*T?|C{{Frx z6@Xf;_Ou270QlW@ZM@^NhGk8J}N&E|`K>o!26(Ri68$t&O+rPT9}^98_;qNqoHOc72`Pk-BLwcal+E&Xa)Rw^Q? zZQFl3j`O?YIQzDUsDp!pqUU*85CmE&rIRF4TI*t(rta3()}7GM!2zbGrqt2V(fIuQ zyzRPfQY;p`p68Ke*%#N>*MY5+l3K0S5s@rOl7fghmSx#WDa*1fH8L^+fQa-&+wC@I zXJ>tbx~|K_!~_5*Cnut{zS`K>P$E(g5gSO0#o~3LP>5`R-QC>}z=wy#!Z7>+;PmvA z^Ye2ml?tU&3E%e_8ymaF?{qq(Y1;cfK0bc$d0uUAZ|{$X^o_gV^74||*;!hx)`Nlj zVR?D^&7gH-1LNc4v|2677sqjo zgFec@9Yh4BRIe!8?KV*qk!4wLUMWSXR5H>tK8QpF5uwxRpp?2dYOS#>%jnkh*#>}t z<3C&W$qd|~+wEdm*1&NX3~fMb-P`hh<5L>AcL8{Wfv<*g^a;KW!!Y+T(hp%63h)x> z+oO4HSOBQk>z|W^!+-}+-rea--~}+sfGql;3)})1z=Qt*69aq<{+!_pwhKhS4bZnQ Z{{n0Bt;F1FCQ$$Y002ovPDHLkV1l6;naKbE literal 0 HcmV?d00001 diff --git a/htdocs/images/tango/server.png b/htdocs/images/tango/server.png new file mode 100644 index 0000000000000000000000000000000000000000..068ffebee274d5b48b36a68670e191a7ed4cbf06 GIT binary patch literal 642 zcmV-|0)737P)WFU8GbZ8({Xk{QrNlj1+3MgYKATls8GayP~Yjt8ECu(VJ zZDC_4AX9W@X>Mh5Co}I@0005SNkl)(8U!C>$i_{ANvESF31eP4Xv7tiy=bzN~?SBx=YjFItpELv*;zFx7l)^a|d zugLcVPN$RX_xn%;>rzB1#b`A8$N{ZZD~hf6kEhd#a=HAFJe^K4#{3h|T7Ln)hZo6Y z5@QS^f`||V0V0C$`+o_RMGyp`?Vnb++XbN4>j7{)9+}VQ0EkGGDU3rQfKI0~vqEBs zMxzmZ3M)`bAtD%Kh{xk7r2y#n`%l(jFn9%Cwbo);7Q^9?)oMjPpQltRvE6R*eLt!| zM95~d;XZtey>F7^I24OTX0sVeDdO=sg+d`ZmlkfOAR-hB1tyaT?RFd6wsBpT#bOav zVB0o_!{PB5>-9R-YBlP7E|~=c< zHk%EJM1u8tO)M6RHa6V5D+`CiflMX?K&4V4l}gcUHc6#Y)M_=->GVyaOM&N?mzN*> cKb`^p0DMpp{`zwTlK=n!07*qoM6N<$f&;Gw9smFU literal 0 HcmV?d00001 diff --git a/htdocs/images/tango/smile-big.png b/htdocs/images/tango/smile-big.png new file mode 100644 index 0000000000000000000000000000000000000000..a52e44d04b5fb8fcb3ed29377094a58435581bff GIT binary patch literal 2566 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 IM6N<$g5yxd?f?J) literal 0 HcmV?d00001 diff --git a/htdocs/images/tango/switch-big.png b/htdocs/images/tango/switch-big.png new file mode 100644 index 0000000000000000000000000000000000000000..d09995ab96c785eefa4eaeb4751f3e76843d1528 GIT binary patch literal 1797 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 RQpNxP002ovPDHLkV1kVygbx4! literal 0 HcmV?d00001 diff --git a/htdocs/images/tango/timeout.png b/htdocs/images/tango/timeout.png new file mode 100644 index 0000000000000000000000000000000000000000..18b7c6781edadc1d075728dd41546f7010ee7037 GIT binary patch literal 897 zcmV-{1AhF8P)#>It74)E>!>k0}e?< zK~y-)Ws*xwTxA@^f8TfSyqLLnU?K?8$|G1EY%rF-;-axT+?a~Nx*!@hCPY`YH6|=g zV;Ucc#zal5HL;66@DWW+qb{%oO;sobI#?^(5$Q~)%nZZKy~7N5zR!(qD4yi(&N=@_ zj$jjx92gnWk{1QyVU!LCLwZ_@8&$P_=AF-8e`T{?Y%um{_;mNaM|-yS#tBEl2mx9{ zaka$ERDw&F=F@}2=Z^I}k_sYql2G!rxxsv4aCpEj8;Vt*gDAdsXNui%jCkNd8aq?X zjm?!eJ-u_)(7&t*w_Qm9jXpj&JYe5gE71N>h-mfgyVkVpEw*lJp?7bNXu~dpz`G5| zr=!3QdE~&z(C&RZc9yh9TUR43TjHC~L`sPe0y7XpvP7kH0;e<+1pR{q2DbOcSuSU3 zZEdEI|A+YFr$}dgcRx!ADqbI+=qHt|a`M9ms(A98snL7Fkua7QLMesMXHj;Ggz79t zUfPD=-pg}sIc(cP$QaUp5W~C4!qmsnp%?mt5~vpfnwlEO7xE~js40!(6gm3d??htV zOiWCmltOETVH%i*1f>PgWdbW&6Dzw_Iy%~^RMt>RQ7jhe?(XL0!>@Af+Er?`8d6HM zQfLiGG_W8A;-XV>So}MUQVP%W@H~%0hYpiSB*QJv%5E8_kF0oOuSo0O-88Yi?mS`RxAv zkNN-nW071T&;4y%2nK=#gCYFB05|{2kiWjd$q&xz*`?X{r{;f}1F{CdOmaH!H~m+Z zu4eW$HN>KAEv->#4UcH#K>>F>S)(m+mZ=t@1%`Q)zt z=kL2`>r-|9x)v#bCe_ X$s}Y37Q!~)00000NkvXXu0mjf?g64A literal 0 HcmV?d00001 diff --git a/htdocs/images/tango/tools-big.png b/htdocs/images/tango/tools-big.png new file mode 100644 index 0000000000000000000000000000000000000000..6e52db7cfd482e228dae640a7717ea1dcaf523e8 GIT binary patch literal 2129 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 literal 0 HcmV?d00001 diff --git a/htdocs/images/tango/tree_collapse.png b/htdocs/images/tango/tree_collapse.png new file mode 100644 index 0000000000000000000000000000000000000000..1c9be7591474dec5e8badf0d285f8f38007dd5fc GIT binary patch literal 196 zcmeAS@N?(olHy`uVBq!ia0vp^0zfRp!VDxAh&o3CDgFST5ZC|z|IeO1yQQV2uC5L! z_ISgNdq9e@B*-tA!Qt7BG!Q4r+uensgH_f8$l)yTh%9Dc;1&X5#!GkW{s0BpOFVsD z*)KD(2{8%X{ISLpD5U4<;uumfCpm$EiIJ_OA=oAI=7|#wM;HXTcmkMwj~qREaDw1| isZ<36g#>XH28NnYmWOM7ZafF-WbkzLb6Mw<&;$TqC^qE) literal 0 HcmV?d00001 diff --git a/htdocs/images/tango/tree_collapse_corner.png b/htdocs/images/tango/tree_collapse_corner.png new file mode 100644 index 0000000000000000000000000000000000000000..b3328adcc2ab423fed5cc45a7105588b19028efe GIT binary patch literal 196 zcmeAS@N?(olHy`uVBq!ia0vp^0zfRp!VDxAh&o3CDgFST5ZC|z|IeO1yQQV2uC5L! z_ISgNdq9e@B*-tA!Qt7BG!Q4r+uensgH_f8$l)yTh%9Dc;1&X5#!GkW{s0BpOFVsD z*)KD(2{CDAe0I$R3h8;eIEGZrNlsv3Vq`062zH6QdEx}a5e7jno&YA_BS()OoFKSg iDpkSYzy=m+28PP1EC&ljIDP?jGI+ZBxvX2CMB#UP^@JYD@<);T3K0RR*AE~fwh literal 0 HcmV?d00001 diff --git a/htdocs/images/tango/tree_collapse_first.png b/htdocs/images/tango/tree_collapse_first.png new file mode 100644 index 0000000000000000000000000000000000000000..5c4387616c2c3514ea9edccef686a72d427ccf2a GIT binary patch literal 194 zcmeAS@N?(olHy`uVBq!ia0vp^0zfRp!VDxAh&o3CDgFST5ZC|z|IeO1yQQV2uC5L! z_ISgNdq9e@B*-tA!Qt7BG!Q4r+uensgH_f8$l)yTh%9Dc;1&d7#`=`_i9kX25>H=O z_RFkHLK;RJ_H(}j3h8*dIEGZrNlsAU)zFrflx&btaB5`qTF|*;hlPaEqwvK%ENlYG ftOh!cf{YAFt}Gkl=B@Vz>SOS9^>bP0l+XkK0535l literal 0 HcmV?d00001 diff --git a/htdocs/images/tango/tree_corner.png b/htdocs/images/tango/tree_corner.png new file mode 100644 index 0000000000000000000000000000000000000000..541c5b3bafea8a3e2599b173cd5b56d7887ca711 GIT binary patch literal 160 zcmeAS@N?(olHy`uVBq!ia0vp^0zfRp$P6SizMjzpQfvV}A+G=b|DQd3cHo=2ML-e8 zk|4ie28U-i(myGkCiCxvXF#WAE}PI3YR6C+zmL$FKa%@ZdWjxY#v@gy8-WYl`ZAX->h qXprI}=(wWsRS+8!GgFx(1H*|>)`yP{9O?&}z~JfX=d#Wzp$Py%F#WAE}PI3YR6C+zmL$FKa%@ZdWjxY#v@gy8-WYl`ZAX->h qXprI}=(wWsRS+8!GmrNMMuwwPSr4X~T-E`az~JfX=d#Wzp$PyIl{lLK literal 0 HcmV?d00001 diff --git a/htdocs/images/tango/tree_expand_corner_first.png b/htdocs/images/tango/tree_expand_corner_first.png new file mode 100644 index 0000000000000000000000000000000000000000..5de11a6ba812abd5d1a8b43033263a0567f18899 GIT binary patch literal 197 zcmeAS@N?(olHy`uVBq!ia0vp^0zfRp!VDxAh&o3CDgFST5LZhEhL)C=y1F``!0g$x z+xe!10$GeDL4Lsu4$p3+fjCLt?k)@+tg;?J4rhT!WHAE+w-5+3UbH=O z_RFkHLRws_x-WhL3YmDiIEGZrNlsAU)zFrflx&btaB5`qu`qCOm06&qr^naUqoKrM n8W4NRA%Vd#h~co1h#3p^r=85p>QK$!8; z-MT+OLG}_)Usv|aOl(3T92QIuo&be{JY5_^D&{07I575b1+*DVIhY}&!68^+XqKAb z;jL{_Sjd@>@OqBkn@5jM9hhJ!%(9GGa;icATZ#{RVw&)78&qol`;+0GE79%K!iX literal 0 HcmV?d00001 diff --git a/htdocs/images/tango/tree_folder_open.png b/htdocs/images/tango/tree_folder_open.png new file mode 100644 index 0000000000000000000000000000000000000000..4190b969845fba00d0ac6ca0c5a889818eebbeea GIT binary patch literal 278 zcmeAS@N?(olHy`uVBq!ia0vp^0zfRp!VDxAh&o3CDa8Pv5ZC`8a0bXTo;j1Dp+QMW zDJ|^`P-y1N{|62nICJLzF{Y2Ffzpg6L4Lsu4$p3+fjCLt?k)@+tg;?J4rhT!WHAE+ zw-5+3Ub*oF%FT1tLu>VJeJQnH(d+g`BG_ z1$>ygHk39sh)pnLW@(xvAz|dGwAPD9;A*CWpqi>dgEc2Zp{e4eYkN}4fi^REy85}S Ib4q9e0B@C3i2wiq literal 0 HcmV?d00001 diff --git a/htdocs/images/tango/tree_leaf.png b/htdocs/images/tango/tree_leaf.png new file mode 100644 index 0000000000000000000000000000000000000000..6f999fba427b8c3f54b5bb6fea272b44eb821bb3 GIT binary patch literal 207 zcmeAS@N?(olHy`uVBq!ia0vp^0zfRp!VDxAh&o3CDgFST5ZC|z|1$tlLjzEtp`pPo z#jzL2Vk`;r3ubV5b|VeMN%D4gVd!9$^#F1>3p^r=85p>QK$!8;-MT+OLG}_)Usv|a zOl(4Oa%Pr$?SVp;o-U3d6?2jk99WqGW(9Jd5(o-v;L^}^WSuf4k%=vZOG4UOb2kHH qz=@MA9@Y$!=MuP17!*1d3Nj=-;}V*1`l>L{5C%_IKbLh*2~7aI8#Iyt literal 0 HcmV?d00001 diff --git a/htdocs/images/tango/tree_space.png b/htdocs/images/tango/tree_space.png new file mode 100644 index 0000000000000000000000000000000000000000..fbdfa6a8e1e456ea42a1d39969b15e295a06cc75 GIT binary patch literal 150 zcmeAS@N?(olHy`uVBq!ia0vp^0zfRp$P6SizMjzpQp^E9A+G=b|6hJY`UH^6SQ6wH z%;50sMjD8d?NMQuI!hYn1v)PS~ujE l0fl%xT^vIy<|HR5umgE!42;`KcIpCI44$rjF6*2UngHK-BHI7} literal 0 HcmV?d00001 diff --git a/htdocs/images/tango/tree_split.png b/htdocs/images/tango/tree_split.png new file mode 100644 index 0000000000000000000000000000000000000000..1a49fab4550598ae110fe90c7fb77c4b098a911f GIT binary patch literal 160 zcmeAS@N?(olHy`uVBq!ia0vp^0zfRp$P6SizMjzpQfvV}A+G=b|DQd3cHo=2ML-e8 zk|4ie28U-i(m}piCG~<@Tj_&{ee%V|SZW{gB8?y>5~HGEkRU`Q5xgR16NK8$#%7av&gnyv zB_>9ji%*39&LbK3qFu zI7(%ZZ%;}2Gqh=wf?-g1;X+qD8r}8{{PEcV%0X!tqH%6yq(DC>&`hf#DjvXW3(1702fiEY= zF5vsm0&oGwD!P6+uzb1JdigTStXXLJ`Pjl?)VXtsUA;>7;>9+ps^67D`lthR!lCrM zJiGbuAzhIO`u_b0*{$vea+<+#n+u)TG0)=^W&Y8i0fonJZU{&O3K7Vlni6`w*i02KV;P{rfRu zG0etBGUm-QC7c=+fU_{mF@F3e|CA|e+x6?%3JOrCPscC}T3cI*Mx&UfiIS0lW6Kua z*4E+=1XR`QT~P`vMhu|BsqFlGD_&EBWm!0O?*~ty__PKSBsxE>~io%jH4{flNukRa8X# z{rjXQCrg{pH?0i59u|NFLJ0B8)HQ2(TUCW{yU};B)sYgKfwF=i#fQ*|T%prYYO&>#^_Jg-l9HIC3}~D2jrjDCoMLxDnFn#I<)X9Z#O% zl~TASP4c~kT|)vm3aV6;lT*TB*>>d$((gwvEKE2_WWLjh)9HL~UI>A6!v?geQ)#cO zBP%CIQ>6UickujYfDG8-Td-iF{q<|n@$@N&XN+4a)1MXii!#xt%)zy89UYGz zG12e0NnI~2gPDT@C~$aEUY=^+y^GP-hO?w((CCB^XqtxXDMlUN#ETcC z1p+4hp6CQXDP-AvzM{13Y_09qE$nO8qUGca8odyL^73*nUc5M{b0Gw_%uGDnx6}FT z856u-Rdc(;WsuwJSM3x1@yun*tghR)G2?Oc_3NRv6|2V>LcBLlv~F)$efs`;+#5F% zJ#z;0`E&f~>DJ4JhLgbjz5vpKd|!698oPE4fasPj{qtqSV!U}nQhK`b970DyKML_) z0Ovbsj@-OC=8MgnrPMUAEG)wS)5J22?y+HDnPzw2Z#-bF|D0)J#^W@J2V5SdEtMnl9PhCxc2Fa&}~V}o=Tx)35=bmuS|@d;cT zbY;Loz(q+`1+A}82tI&NTm%Y*7F^UoNilyn))L6H_Q1W1%i%j`bA(=?F!-5EVN!MFB_9*XAp~_l%n771CUH65fQk#;c9J-59jBDOQ<*CorDm33|CLV znm<0~VYP}<3Z)daS`C19yN!q-BK$Z#V4_~XOaDE<2tY)*Zne1F+TuNYlS3Fj19`yz=_l|J pl>P}02k>Sh;xD3f4Z|KZe*u@?eFz-1;S&G=002ovPDHLkV1mMw_G175 literal 0 HcmV?d00001 diff --git a/htdocs/import.php b/htdocs/import.php new file mode 100644 index 0000000..22d7ee2 --- /dev/null +++ b/htdocs/import.php @@ -0,0 +1,111 @@ +getIndex(),'LDIF'); +$request['import'] = $request['importer']->getTemplate(); + +$request['continuous_mode'] = get_request('continuous_mode') ? true : false; + +$type = $request['import']->getType(); + +# Set our timelimit in case we have a lot of importing to do +@set_time_limit(0); + +# String associated to the operation on the ldap server +$actionString = array( + 'add' => _('Adding'), + 'delete' => _('Deleting'), + 'modrdn' => _('Renaming'), + 'moddn' => _('Renaming'), + 'modify' => _('Modifying') + ); + +# String associated with error +$actionErrorMsg = array( + 'add' => _('Could not add object'), + 'delete' => _('Could not delete object'), + 'modrdn' => _('Could not rename object'), + 'moddn' => _('Could not rename object'), + 'modify' => _('Could not modify object') + ); + +$request['page'] = new PageRender($app['server']->getIndex(),get_request('template','REQUEST',false,'none')); +$request['page']->drawTitle(sprintf('%s',_('Import'))); +$request['page']->drawSubTitle(sprintf('%s: %s %s: %s %s %s (%s)', + _('Server'),$app['server']->getName(), + _('File'),$request['import']->getSource('name'),number_format($request['import']->getSource('size')),_('bytes'),$type['description'])); + +echo '
'; + +# @todo When renaming DNs, the hotlink should point to the new entry on success, or the old entry on failure. +while (! $request['import']->eof()) { + while ($request['template'] = $request['import']->readEntry()) { + + $edit_href = sprintf('cmd.php?cmd=template_engine&server_id=%s&dn=%s',$app['server']->getIndex(), + rawurlencode($request['template']->getDN())); + + $changetype = $request['template']->getType(); + printf('%s %s',$actionString[$changetype],$edit_href,$request['template']->getDN()); + + if ($request['import']->LDAPimport()) + printf(' %s
',_('Success')); + + else { + printf(' %s

',_('Failed')); + $errormsg = sprintf('%s %s',$actionErrorMsg[$changetype],$request['template']->getDN()); + $errormsg .= ldap_error_msg($app['server']->getErrorMessage(null),$app['server']->getErrorNum(null)); + + system_message(array( + 'title'=>_('LDIF text import'), + 'body'=>$errormsg, + 'type'=>'warn')); + } + } + + if ($request['import']->error) { + printf('%s: %s
', + _('Error'),$request['import']->error['message']); + + echo '
'; + + display_pla_parse_error($request['import']); + } + + if (! $request['continuous_mode']) + break; +} + +function display_pla_parse_error($request) { + $type = $request->getType(); + + echo '
'; + echo ''; + echo ''; + printf('',IMGDIR,'error-big.png'); + + printf('',$type['description'],_('Parse Error')); + echo ''; + + printf('',_('Description'),$request->error['message']); + printf('',_('Line'),$request->error['line']); + printf('',_('Data')); + + foreach ($request->error['data'] as $line) + printf('',$line); + + echo '

%s %s

%s:%s
%s:%s
%s:
 %s
'; + echo '
'; +} +?> diff --git a/htdocs/import_form.php b/htdocs/import_form.php new file mode 100644 index 0000000..9c6bbbb --- /dev/null +++ b/htdocs/import_form.php @@ -0,0 +1,48 @@ +getIndex(),get_request('template','REQUEST',false,'none')); +$request['page']->drawTitle(sprintf('%s',_('Import'))); +$request['page']->drawSubTitle(sprintf('%s: %s',_('Server'),$app['server']->getName())); + +echo '
'; +echo '
'; +printf('',$app['server']->getIndex()); +echo ''; +echo '
'; + +echo ''; + +echo ''; +echo ''; +printf('',_('Select an LDIF file')); +echo ''; + +printf('',_('Maximum file size'),ini_get('upload_max_filesize')); + +echo ''; +printf('',_('Or paste your LDIF here')); +echo ''; +echo ''; +printf('', + _("Don't stop on errors")); +printf('',_('Proceed >>')); +echo '
 
%s'; +echo ''; +echo '
 %s %s
 
%s
 
 %s
 
'; +echo '
'; +?> diff --git a/htdocs/index.php b/htdocs/index.php new file mode 100644 index 0000000..f72840c --- /dev/null +++ b/htdocs/index.php @@ -0,0 +1,148 @@ + + +If you are seeing this in your browser, +PHP is not installed on your web server!!! + + +*******************************************/ + +/** + * We will perform some sanity checking here, since this file is normally loaded first when users + * first access the application. + */ + +# The index we will store our config in $_SESSION +define('APPCONFIG','plaConfig'); + +define('LIBDIR',sprintf('%s/',realpath('../lib/'))); +ini_set('display_errors',1); +error_reporting(-1); + +# General functions needed to proceed. +ob_start(); +if (! file_exists(LIBDIR.'functions.php')) { + if (ob_get_level()) ob_end_clean(); + die(sprintf("Fatal error: Required file '%sfunctions.php' does not exist.",LIBDIR)); +} + +if (! is_readable(LIBDIR.'functions.php')) { + if (ob_get_level()) ob_end_clean(); + die(sprintf("Cannot read the file '%sfunctions.php' its permissions may be too strict.",LIBDIR)); +} + +if (ob_get_level()) + ob_end_clean(); + +# Make sure this PHP install has pcre +if (! extension_loaded('pcre')) + die('

Your install of PHP appears to be missing PCRE support.

Please install PCRE support before using phpLDAPadmin.
(Dont forget to restart your web server afterwards)

'); + +require LIBDIR.'functions.php'; +spl_autoload_register("autoload"); + +# Define the path to our configuration file. +if (defined('CONFDIR')) + $app['config_file'] = CONFDIR.'config.php'; +else + $app['config_file'] = 'config.php'; + +# Make sure this PHP install has session support +if (! extension_loaded('session')) + error('

Your install of PHP appears to be missing php-session support.

Please install php-session support before using phpLDAPadmin.
(Dont forget to restart your web server afterwards)

','error',null,true); + +# Make sure this PHP install has gettext, we use it for language translation +if (! extension_loaded('gettext')) + system_message(array( + 'title'=>_('Missing required extension'), + 'body'=>'Your install of PHP appears to be missing GETTEXT support.

GETTEXT is used for language translation.

Please install GETTEXT support before using phpLDAPadmin.
(Dont forget to restart your web server afterwards)', + 'type'=>'error')); + +# Make sure this PHP install has all our required extensions +if (! extension_loaded('ldap')) + system_message(array( + 'title'=>_('Missing required extension'), + 'body'=>'Your install of PHP appears to be missing LDAP support.

Please install LDAP support before using phpLDAPadmin.
(Dont forget to restart your web server afterwards)', + 'type'=>'error')); + +# Make sure that we have php-xml loaded. +if (! function_exists('xml_parser_create')) + system_message(array( + 'title'=>_('Missing required extension'), + 'body'=>'Your install of PHP appears to be missing XML support.

Please install XML support before using phpLDAPadmin.
(Dont forget to restart your web server afterwards)', + 'type'=>'error')); + +/** + * Helper functions. + * Our required helper functions are defined in functions.php + */ +if (isset($app['function_files']) && is_array($app['function_files'])) + foreach ($app['function_files'] as $file_name ) { + if (! file_exists($file_name)) + error(sprintf('Fatal error: Required file "%s" does not exist.',$file_name),'error',null,true); + + if (! is_readable($file_name)) + error(sprintf('Fatal error: Cannot read the file "%s", its permissions may be too strict.',$file_name),'error',null,true); + + ob_start(); + require $file_name; + if (ob_get_level()) ob_end_clean(); + } + +# Configuration File check +if (! file_exists($app['config_file'])) { + error(sprintf(_('You need to configure %s. Edit the file "%s" to do so. An example config file is provided in "%s.example".'),app_name(),$app['config_file'],$app['config_file']),'error',null,true); + +} elseif (! is_readable($app['config_file'])) { + error(sprintf('Fatal error: Cannot read your configuration file "%s", its permissions may be too strict.',$app['config_file']),'error',null,true); +} + +# If our config file fails the sanity check, then stop now. +if (! $config = check_config($app['config_file'])) { + $www['page'] = new page(); + $www['body'] = new block(); + $www['page']->block_add('body',$www['body']); + $www['page']->display(); + exit; + +} else { + app_session_start(); + $_SESSION[APPCONFIG] = $config; +} + +if ($uri = get_request('URI','GET')) + header(sprintf('Location: cmd.php?%s',base64_decode($uri))); + +if (! preg_match('/^([0-9]+\.?)+/',app_version())) { + system_message(array( + 'title'=>_('This is a development version of phpLDAPadmin'), + 'body'=>'This is a development version of phpLDAPadmin! You should NOT use it in a production environment (although we dont think it should do any damage).', + 'type'=>'info','special'=>true)); + + if (count($_SESSION[APPCONFIG]->untested())) + system_message(array( + 'title'=>'Untested configuration paramaters', + 'body'=>sprintf('The following parameters have not been tested. If you have configured these parameters, and they are working as expected, please let the developers know, so that they can be removed from this message.
%s',implode(', ',$_SESSION[APPCONFIG]->untested())), + 'type'=>'info','special'=>true)); + + $server = $_SESSION[APPCONFIG]->getServer(get_request('server_id','REQUEST')); + if (count($server->untested())) + system_message(array( + 'title'=>'Untested server configuration paramaters', + 'body'=>sprintf('The following parameters have not been tested. If you have configured these parameters, and they are working as expected, please let the developers know, so that they can be removed from this message.
%s',implode(', ',$server->untested())), + 'type'=>'info','special'=>true)); +} + +include './cmd.php'; +?> diff --git a/htdocs/js/CheckAll.js b/htdocs/js/CheckAll.js new file mode 100644 index 0000000..0f91f10 --- /dev/null +++ b/htdocs/js/CheckAll.js @@ -0,0 +1,22 @@ +function CheckAll(setbgcolor,form,index) { + htmlform = document.getElementById(form+index); + + for (var i=0;i= 0) return component.options[component.selectedIndex].value; + } else if (component.type == "select-multiple") { + if (component.selectedIndex >= 0) return component.options[component.selectedIndex].value; + } else if (component.type == undefined) { // option + if (component.selected) return component.value; + } else { + return component.value; + } + return ""; +} + +function pla_setComponentValue(component,value) { + if (component.type == "checkbox") { + if (component.value == value) component.checked = true; + else component.checked = false; + } else if (component.type == "select-one") { + for (var i = 0; i < component.options.length; i++) { + if (component.options[i].value == value) component.options[i].selected = true; + } + } else if (component.type == "select-multiple") { + for (var i = 0; i < component.options.length; i++) { + if (component.options[i].value == value) component.options[i].selected = true; + } + } else if (component.type == undefined) { // option + if (component.value == value) component.selected = true; + else component.selected = false; + } else { + component.value = value; + } +} + +function getAttributeComponents(prefix,name) { + var components = new Array(); + var i = 0; + var j = 0; + var c = pla_getComponentsByName(prefix + "_values[" + name + "][" + j + "]"); + while (c && (c.length > 0)) { + for (var k = 0; k < c.length; k++) { + components[i++] = c[k]; + } + ++j; + c = pla_getComponentsByName(prefix + "_values[" + name + "][" + j + "]"); + } + c = pla_getComponentsByName(prefix + "_values[" + name + "][]"); + if (c && (c.length > 0)) { + for (var k = 0; k < c.length; k++) { + components[i++] = c[k]; + } + } + return components; +} + +function getAttributeValues(prefix,name) { + var components = getAttributeComponents(prefix,name); + var values = new Array(); + for (var k = 0; k < components.length; k++) { + var val = pla_getComponentValue(components[k]); + if (val) values[values.length] = val; + } + return values; +} + +function submitForm(form) { + for (var i = 0; i < form.elements.length; i++) { + form.elements[i].blur(); + } + return validateForm(true); +} + +function alertError(err,silence) { + if (!silence) alert(err); +} diff --git a/htdocs/js/ajax_functions.js b/htdocs/js/ajax_functions.js new file mode 100644 index 0000000..a812b45 --- /dev/null +++ b/htdocs/js/ajax_functions.js @@ -0,0 +1,253 @@ +/** + * @package phpLDAPadmin + * @author The phpLDAPadmin development team + * @author Xavier Bruyet + */ + +// current request +var http_div = ''; +var http_request = null; +var http_request_success_callback = ''; +var http_request_error_callback = ''; + +function ajSUBMIT(div,obj,display) { + var pageDiv = getDiv(div); + + window.scrollTo(0,95); + + makeHttpRequest('cmd.php',getParameters(obj.parentNode)+'meth=ajax','POST','alertAJ','cancelAJ',div); + + if (pageDiv) + includeHTML(pageDiv,'
'+display+'...'); + else + return true; + + return false; +} + +function ajDISPLAY(div,urlParameters,display,ns) { + var pageDiv = getDiv(div); + + if (! ns) + window.scrollTo(0,95); + + makeHttpRequest('cmd.php',urlParameters+'&meth=ajax','GET','alertAJ','cancelAJ',div); + + if (pageDiv) + includeHTML(pageDiv,'
'+display+'...'); + else + return true; + + return false; +} + +function ajJUMP(url,title,index,prefix) { + var attr = prefix ? document.getElementById(prefix+index).value : index; + + if (attr) + url += '&viewvalue='+attr; + + return ajDISPLAY('BODY',url,'Loading '+title); +} + +function ajSHOWTHIS(key,except,ctl) { + select = document.getElementById(key+except); + + if (select.style.display == '') + return false; + + hideall(key,except,ctl); + + return false; +}; + +function ajSHOWSCHEMA(type,key,value) { + select = document.getElementById(type); + + if (value != null) { + except = value; + select.value = value; + } else { + except = select.value; + } + + if (! except) { + showall(key); + } else { + objectclass = document.getElementById(key+except); + objectclass.style.display = ''; + hideall(key,except); + }; + + return false; +}; + +function hideall(key,except,ctl) { + items = items(); + + for (x in items) { + if (! isNaN(x) && except != items[x]) { + item = document.getElementById(key+items[x]); + item.style.display = 'none'; + + if (ctl && (item = document.getElementById(ctl+items[x]))) { + item.style.background = '#E0E0E0'; + } + + } else if (! isNaN(x) && except == items[x]) { + item = document.getElementById(key+items[x]); + item.style.display = ''; + + if (ctl && (item = document.getElementById(ctl+items[x]))) { + item.style.background = '#F0F0F0'; + } + } + } +} + +function showall(key) { + items = items(); + + for (x in items) { + if (! isNaN(x)) { + item = document.getElementById(key+items[x]); + item.style.display = ''; + } + } +} + +// include html into a component +function includeHTML(component,html) { + if (typeof(component) != 'object' || typeof(html) != 'string') return; + component.innerHTML = html; + + var scripts = component.getElementsByTagName('script'); + if (!scripts) return; + + // load scripts + for (var i = 0; i < scripts.length; i++) { + var scriptclone = document.createElement('script'); + if (scripts[i].attributes.length > 0) { + for (var j in scripts[i].attributes) { + if (typeof(scripts[i].attributes[j]) != 'undefined' + && typeof(scripts[i].attributes[j].nodeName) != 'undefined' + && scripts[i].attributes[j].nodeValue != null + && scripts[i].attributes[j].nodeValue != '') { + scriptclone.setAttribute(scripts[i].attributes[j].nodeName,scripts[i].attributes[j].nodeValue); + } + } + } + scriptclone.text = scripts[i].text; + scripts[i].parentNode.replaceChild(scriptclone,scripts[i]); + eval(scripts[i].innerHTML); + } +} + +// callback function +function alertHttpRequest() { + if (http_request && (http_request.readyState == 4)) { + if (http_request.status == 200 || http_request.status == 401) { + response = http_request.responseText; + http_request = null; + //alert(response); + if (http_request_success_callback) { + eval(http_request_success_callback + '(response,http_div)'); + } + } else { + alert('There was a problem with the request.'); + cancelHttpRequest(); + } + } +} + +function cancelHttpRequest() { + if (http_request) { + http_request = null; + if (http_request_error_callback) { + eval(http_request_error_callback + '(http_div)'); + } + } +} + +function makeHttpRequest(url,parameters,meth,successCallbackFunctionName,errorCallbackFunctionName,div) { + cancelHttpRequest(div); + + http_request_success_callback = successCallbackFunctionName; + http_request_error_callback = errorCallbackFunctionName; + http_div = div; + + if (window.XMLHttpRequest) { // Mozilla, Safari,... + http_request = new XMLHttpRequest(); + if (http_request.overrideMimeType) { + http_request.overrideMimeType('text/html'); + } + + } else if (window.ActiveXObject) { // IE + try { + http_request = new ActiveXObject('Msxml2.XMLHTTP'); + } catch (e) { + try { + http_request = new ActiveXObject('Microsoft.XMLHTTP'); + } catch (e) {} + } + } + + if (!http_request) { + alert('Cannot create XMLHTTP instance.'); + return false; + } + + http_request.onreadystatechange = window['alertHttpRequest']; + if (meth == 'GET') url = url + '?' + parameters; + http_request.open(meth,url,true); + + http_request.setRequestHeader('Content-type','application/x-www-form-urlencoded'); + // http_request.setRequestHeader('Content-length',parameters.length); + // http_request.setRequestHeader('Connection','close'); + + if (meth == 'GET') parameters = null; + http_request.send(parameters); +} + +function getParameters(obj) { + var elements = ['input','select','textarea']; + var getstr = ''; + + for (var j in elements) { + for (i=0; i expand ; (action = 2) => collapse + if (oldimg.indexOf(imgdir+'/tree_expand.png') > -1) { + newimg = imgdir+'/tree_collapse.png'; + action = 1; + } else if (oldimg.indexOf(imgdir+'/tree_expand_first.png') > -1) { + newimg = imgdir+'/tree_collapse_first.png'; + action = 1; + } else if (oldimg.indexOf(imgdir+'/tree_expand_corner.png') > -1) { + newimg = imgdir+'/tree_collapse_corner.png'; + action = 1; + } else if (oldimg.indexOf(imgdir+'/tree_expand_corner_first.png') > -1) { + newimg = imgdir+'/tree_collapse_corner_first.png'; + action = 1; + } else if (oldimg.indexOf(imgdir+'/tree_collapse.png') > -1) { + newimg = imgdir+'/tree_expand.png'; + action = 2; + } else if (oldimg.indexOf(imgdir+'/tree_collapse_first.png') > -1) { + newimg = imgdir+'/tree_expand_first.png'; + action = 2; + } else if (oldimg.indexOf(imgdir+'/tree_collapse_corner.png') > -1) { + newimg = imgdir+'/tree_expand_corner.png'; + action = 2; + } else if (oldimg.indexOf(imgdir+'/tree_collapse_corner_first.png') > -1) { + newimg = imgdir+'/tree_expand_corner_first.png'; + action = 2; + } + nodeLayer.src = 'images/ajax-spinner.gif'; + + // perform action + if (action == 2) { + newstyle = 'none'; + updateNewStyle(); + addCollapsedNode(nodeid); + } else if (action == 1) { + newstyle = 'block'; + if (sonLayer.innerHTML == '') { + makeHttpRequest('cmd.php',params+'&cmd=draw_tree_node&action=1','GET','alertTreeNodeContents','cancelNewStyle'); + } else { + updateNewStyle(); + } + delCollapsedNode(nodeid); + } + return false; +} + +function getDiv(div) { + if (!IE4) { + return document.getElementById('aj'+div); + } else { + return document.all('aj'+div); + } +} + +function alertAJ(html,div) { + var pageDiv = getDiv(div); + if (pageDiv) includeHTML(pageDiv, html); +} + +function cancelAJ(div) { + var pageDiv = getDiv(div); + if (pageDiv) includeHTML(pageDiv, ''); +} + +// close initial collapsed nodes +// Cant figure out why, but this runs twice in AJAX mode when using "refresh". +// Causing the collapsedNodes to be incorrect. +readCollapsedNodes(); +for (k = 0; k < collapsedNodes.length; k++) { + opencloseTreeNode(collapsedNodes[k],'#','images/default'); +} + +var current; + +function tree_unhide(whichLayer,old) { + if (current == null) current = old; + + var oldtree = document.getElementById('ajSID_'+current).style; + oldtree.display = 'none'; + + if (document.getElementById) { + // this is the way the standards work + var newtree = document.getElementById(whichLayer).value; + var newtree_div = document.getElementById('ajSID_'+newtree).style; + newtree_div.display = 'block'; + } + + current = newtree; +} diff --git a/htdocs/js/date_selector.js b/htdocs/js/date_selector.js new file mode 100644 index 0000000..eed89d6 --- /dev/null +++ b/htdocs/js/date_selector.js @@ -0,0 +1,75 @@ +function dateSelector(id) { + var el = document.getElementById('new_values_'+id); + var format = gettype(el.id); + var epoch; + var parse = false; + + var cal = new Calendar(0, null, onSelect, onClose); + + if (defaults['f_time_'+id]) { + cal.showsTime = true; + } else { + cal.showsTime = false; + } + + cal.weekNumbers = true; + cal.showsOtherMonths = true; + cal.create(); + + // convert to milliseconds (Epoch is usually expressed in seconds, but Javascript uses Milliseconds) + switch (format) { + case '%es' : epoch = el.value * 86400 * 1000; + format = '%s'; + parse = true; + break; + case '%s' : epoch = el.value * 1000; + parse = true; + break; + } + + // Convert the value to the date so that the calendar will display it + if (parse) { + var dDate = new Date(); + dDate.setTime(epoch); + cal.setDateFormat('%a, %d %b %Y'); // set the specified date format + cal.parseDate(dDate.toString()); // try to parse the text in field + cal.setDateFormat(format); // set the specified date format + } else { + cal.setDateFormat(format); // set the specified date format + cal.parseDate(el.value); // try to parse the text in field + } + + cal.sel = el; // inform it what input field we use + cal.showAtElement(el, 'BR'); // show the calendar +} + +function onSelect(calendar,date) { + switch (gettype(calendar.sel.id)) { + case '%es' : date = Math.round(date / 86400); + break; + } + + calendar.sel.value = date; + if (calendar.dateClicked) + onClose(calendar); +} + +function onClose(calendar,date) { + calendar.hide(); +} + +function gettype(attr) { + if (typeof defaults == "undefined") { + return '%s'; + } + + if (typeof defaults[attr] == "undefined") { + if (typeof default_date_format == "undefined") { + return '%s'; + } else { + return default_date_format; + } + } else { + return defaults[attr]; + } +} diff --git a/htdocs/js/dnChooserPopup.js b/htdocs/js/dnChooserPopup.js new file mode 100644 index 0000000..d95b48a --- /dev/null +++ b/htdocs/js/dnChooserPopup.js @@ -0,0 +1,6 @@ +function dnChooserPopup(form,element,rdn) +{ + mywindow=open('entry_chooser.php','myname','resizable=no,width=600,height=370,scrollbars=1'); + mywindow.location.href = 'entry_chooser.php?form=' + form + '&element=' + element + '&rdn=' + rdn; + if (mywindow.opener == null) mywindow.opener = self; +} diff --git a/htdocs/js/form_field_toggle_enable.js b/htdocs/js/form_field_toggle_enable.js new file mode 100644 index 0000000..f26d1eb --- /dev/null +++ b/htdocs/js/form_field_toggle_enable.js @@ -0,0 +1,51 @@ +/** + * This function will provide a enable/disable toggle for a HTML form field + */ +function form_field_toggle_enable(field,disable,focus,rev) { + var i; + var result; + var element; + + switch (field.type) { + case 'checkbox': + if (field.checked) + result = rev ? false : true; + else + result = rev ? true : false; + + for (i=0;i + http://dynarch.com/mishoo/ + + This program is free software published under the + terms of the GNU Lesser General Public License. + + For the entire license text please refer to + http://www.gnu.org/licenses/lgpl.html + +Contents +--------- + + calendar.js -- the main program file + lang/*.js -- internalization files + *.css -- color themes + cal.html -- example usage file + doc/ -- documentation, in PDF and HTML + simple-1.html -- quick setup examples [popup calendars] + simple-2.html -- quick setup example for flat calendar + calendar.php -- PHP wrapper + test.php -- test file for the PHP wrapper + +Homepage +--------- + + For details and latest versions please refer to calendar + homepage, located on my website: + + http://dynarch.com/mishoo/calendar.epl + diff --git a/htdocs/js/jscalendar/calendar-blue.css b/htdocs/js/jscalendar/calendar-blue.css new file mode 100644 index 0000000..ca33cde --- /dev/null +++ b/htdocs/js/jscalendar/calendar-blue.css @@ -0,0 +1,232 @@ +/* The main calendar widget. DIV containing a table. */ + +div.calendar { position: relative; } + +.calendar, .calendar table { + border: 1px solid #556; + font-size: 11px; + color: #000; + cursor: default; + background: #eef; + font-family: tahoma,verdana,sans-serif; +} + +/* Header part -- contains navigation buttons and day names. */ + +.calendar .button { /* "<<", "<", ">", ">>" buttons have this class */ + text-align: center; /* They are the navigation buttons */ + padding: 2px; /* Make the buttons seem like they're pressing */ +} + +.calendar .nav { + background: #778 url(menuarrow.gif) no-repeat 100% 100%; +} + +.calendar thead .title { /* This holds the current "month, year" */ + font-weight: bold; /* Pressing it will take you to the current date */ + text-align: center; + background: #fff; + color: #000; + padding: 2px; +} + +.calendar thead .headrow { /* Row

containing the day names */ + border-bottom: 1px solid #556; + padding: 2px; + text-align: center; + color: #000; +} + +.calendar thead .weekend { /* How a weekend day name shows in header */ + color: #a66; +} + +.calendar thead .hilite { /* How do the buttons in header appear when hover */ + background-color: #aaf; + color: #000; + border: 1px solid #04f; + padding: 1px; +} + +.calendar thead .active { /* Active (pressed) buttons in header */ + background-color: #77c; + padding: 2px 0px 0px 2px; +} + +/* The body part -- contains all the days in month. */ + +.calendar tbody .day { /* Cells containing month days dates */ + width: 2em; + color: #456; + text-align: right; + padding: 2px 4px 2px 2px; +} +.calendar tbody .day.othermonth { + font-size: 80%; + color: #bbb; +} +.calendar tbody .day.othermonth.oweekend { + color: #fbb; +} + +.calendar table .wn { + padding: 2px 3px 2px 2px; + border-right: 1px solid #000; + background: #bdf; +} + +.calendar tbody .rowhilite td { + background: #def; +} + +.calendar tbody .rowhilite td.wn { + background: #eef; +} + +.calendar tbody td.hilite { /* Hovered cells */ + background: #def; + padding: 1px 3px 1px 1px; + border: 1px solid #bbb; +} + +.calendar tbody td.active { /* Active (pressed) cells */ + background: #cde; + padding: 2px 2px 0px 2px; +} + +.calendar tbody td.selected { /* Cell showing today date */ + font-weight: bold; + border: 1px solid #000; + padding: 1px 3px 1px 1px; + background: #fff; + color: #000; +} + +.calendar tbody td.weekend { /* Cells showing weekend days */ + color: #a66; +} + +.calendar tbody td.today { /* Cell showing selected date */ + font-weight: bold; + color: #00f; +} + +.calendar tbody .disabled { color: #999; } + +.calendar tbody .emptycell { /* Empty cells (the best is to hide them) */ + visibility: hidden; +} + +.calendar tbody .emptyrow { /* Empty row (some months need less than 6 rows) */ + display: none; +} + +/* The footer part -- status bar and "Close" button */ + +.calendar tfoot .footrow { /* The
*/ + background: #fff; + color: #445; + border-top: 1px solid #556; + padding: 1px; +} + +.calendar tfoot .hilite { /* Hover style for buttons in footer */ + background: #aaf; + border: 1px solid #04f; + color: #000; + padding: 1px; +} + +.calendar tfoot .active { /* Active (pressed) style for buttons in footer */ + background: #77c; + padding: 2px 0px 0px 2px; +} + +/* Combo boxes (menus that display months/years for direct selection) */ + +.calendar .combo { + position: absolute; + display: none; + top: 0px; + left: 0px; + width: 4em; + cursor: default; + border: 1px solid #655; + background: #def; + color: #000; + font-size: 90%; + z-index: 100; +} + +.calendar .combo .label, +.calendar .combo .label-IEfix { + text-align: center; + padding: 1px; +} + +.calendar .combo .label-IEfix { + width: 4em; +} + +.calendar .combo .hilite { + background: #acf; +} + +.calendar .combo .active { + border-top: 1px solid #46a; + border-bottom: 1px solid #46a; + background: #eef; + font-weight: bold; +} + +.calendar td.time { + border-top: 1px solid #000; + padding: 1px 0px; + text-align: center; + background-color: #f4f0e8; +} + +.calendar td.time .hour, +.calendar td.time .minute, +.calendar td.time .ampm { + padding: 0px 3px 0px 4px; + border: 1px solid #889; + font-weight: bold; + background-color: #fff; +} + +.calendar td.time .ampm { + text-align: center; +} + +.calendar td.time .colon { + padding: 0px 2px 0px 3px; + font-weight: bold; +} + +.calendar td.time span.hilite { + border-color: #000; + background-color: #667; + color: #fff; +} + +.calendar td.time span.active { + border-color: #f00; + background-color: #000; + color: #0f0; +} diff --git a/htdocs/js/jscalendar/calendar-setup.js b/htdocs/js/jscalendar/calendar-setup.js new file mode 100644 index 0000000..c269f7d --- /dev/null +++ b/htdocs/js/jscalendar/calendar-setup.js @@ -0,0 +1,200 @@ +/* Copyright Mihai Bazon, 2002, 2003 | http://dynarch.com/mishoo/ + * --------------------------------------------------------------------------- + * + * The DHTML Calendar + * + * Details and latest version at: + * http://dynarch.com/mishoo/calendar.epl + * + * This script is distributed under the GNU Lesser General Public License. + * Read the entire license text here: http://www.gnu.org/licenses/lgpl.html + * + * This file defines helper functions for setting up the calendar. They are + * intended to help non-programmers get a working calendar on their site + * quickly. This script should not be seen as part of the calendar. It just + * shows you what one can do with the calendar, while in the same time + * providing a quick and simple method for setting it up. If you need + * exhaustive customization of the calendar creation process feel free to + * modify this code to suit your needs (this is recommended and much better + * than modifying calendar.js itself). + */ + +// $Id$ + +/** + * This function "patches" an input field (or other element) to use a calendar + * widget for date selection. + * + * The "params" is a single object that can have the following properties: + * + * prop. name | description + * ------------------------------------------------------------------------------------------------- + * inputField | the ID of an input field to store the date + * displayArea | the ID of a DIV or other element to show the date + * button | ID of a button or other element that will trigger the calendar + * eventName | event that will trigger the calendar, without the "on" prefix (default: "click") + * ifFormat | date format that will be stored in the input field + * daFormat | the date format that will be used to display the date in displayArea + * singleClick | (true/false) wether the calendar is in single click mode or not (default: true) + * firstDay | numeric: 0 to 6. "0" means display Sunday first, "1" means display Monday first, etc. + * align | alignment (default: "Br"); if you don't know what's this see the calendar documentation + * range | array with 2 elements. Default: [1900, 2999] -- the range of years available + * weekNumbers | (true/false) if it's true (default) the calendar will display week numbers + * flat | null or element ID; if not null the calendar will be a flat calendar having the parent with the given ID + * flatCallback | function that receives a JS Date object and returns an URL to point the browser to (for flat calendar) + * disableFunc | function that receives a JS Date object and should return true if that date has to be disabled in the calendar + * onSelect | function that gets called when a date is selected. You don't _have_ to supply this (the default is generally okay) + * onClose | function that gets called when the calendar is closed. [default] + * onUpdate | function that gets called after the date is updated in the input field. Receives a reference to the calendar. + * date | the date that the calendar will be initially displayed to + * showsTime | default: false; if true the calendar will include a time selector + * timeFormat | the time format; can be "12" or "24", default is "12" + * electric | if true (default) then given fields/date areas are updated for each move; otherwise they're updated only on close + * step | configures the step of the years in drop-down boxes; default: 2 + * position | configures the calendar absolute position; default: null + * cache | if "true" (but default: "false") it will reuse the same calendar object, where possible + * showOthers | if "true" (but default: "false") it will show days from other months too + * + * None of them is required, they all have default values. However, if you + * pass none of "inputField", "displayArea" or "button" you'll get a warning + * saying "nothing to setup". + */ +Calendar.setup = function (params) { + function param_default(pname, def) { if (typeof params[pname] == "undefined") { params[pname] = def; } }; + + param_default("inputField", null); + param_default("displayArea", null); + param_default("button", null); + param_default("eventName", "click"); + param_default("ifFormat", "%Y/%m/%d"); + param_default("daFormat", "%Y/%m/%d"); + param_default("singleClick", true); + param_default("disableFunc", null); + param_default("dateStatusFunc", params["disableFunc"]); // takes precedence if both are defined + param_default("dateText", null); + param_default("firstDay", null); + param_default("align", "Br"); + param_default("range", [1900, 2999]); + param_default("weekNumbers", true); + param_default("flat", null); + param_default("flatCallback", null); + param_default("onSelect", null); + param_default("onClose", null); + param_default("onUpdate", null); + param_default("date", null); + param_default("showsTime", false); + param_default("timeFormat", "24"); + param_default("electric", true); + param_default("step", 2); + param_default("position", null); + param_default("cache", false); + param_default("showOthers", false); + param_default("multiple", null); + + var tmp = ["inputField", "displayArea", "button"]; + for (var i in tmp) { + if (typeof params[tmp[i]] == "string") { + params[tmp[i]] = document.getElementById(params[tmp[i]]); + } + } + if (!(params.flat || params.multiple || params.inputField || params.displayArea || params.button)) { + alert("Calendar.setup:\n Nothing to setup (no fields found). Please check your code"); + return false; + } + + function onSelect(cal) { + var p = cal.params; + var update = (cal.dateClicked || p.electric); + if (update && p.inputField) { + p.inputField.value = cal.date.print(p.ifFormat); + if (typeof p.inputField.onchange == "function") + p.inputField.onchange(); + } + if (update && p.displayArea) + p.displayArea.innerHTML = cal.date.print(p.daFormat); + if (update && typeof p.onUpdate == "function") + p.onUpdate(cal); + if (update && p.flat) { + if (typeof p.flatCallback == "function") + p.flatCallback(cal); + } + if (update && p.singleClick && cal.dateClicked) + cal.callCloseHandler(); + }; + + if (params.flat != null) { + if (typeof params.flat == "string") + params.flat = document.getElementById(params.flat); + if (!params.flat) { + alert("Calendar.setup:\n Flat specified but can't find parent."); + return false; + } + var cal = new Calendar(params.firstDay, params.date, params.onSelect || onSelect); + cal.showsOtherMonths = params.showOthers; + cal.showsTime = params.showsTime; + cal.time24 = (params.timeFormat == "24"); + cal.params = params; + cal.weekNumbers = params.weekNumbers; + cal.setRange(params.range[0], params.range[1]); + cal.setDateStatusHandler(params.dateStatusFunc); + cal.getDateText = params.dateText; + if (params.ifFormat) { + cal.setDateFormat(params.ifFormat); + } + if (params.inputField && typeof params.inputField.value == "string") { + cal.parseDate(params.inputField.value); + } + cal.create(params.flat); + cal.show(); + return false; + } + + var triggerEl = params.button || params.displayArea || params.inputField; + triggerEl["on" + params.eventName] = function() { + var dateEl = params.inputField || params.displayArea; + var dateFmt = params.inputField ? params.ifFormat : params.daFormat; + var mustCreate = false; + var cal = window.calendar; + if (dateEl) + params.date = Date.parseDate(dateEl.value || dateEl.innerHTML, dateFmt); + if (!(cal && params.cache)) { + window.calendar = cal = new Calendar(params.firstDay, + params.date, + params.onSelect || onSelect, + params.onClose || function(cal) { cal.hide(); }); + cal.showsTime = params.showsTime; + cal.time24 = (params.timeFormat == "24"); + cal.weekNumbers = params.weekNumbers; + mustCreate = true; + } else { + if (params.date) + cal.setDate(params.date); + cal.hide(); + } + if (params.multiple) { + cal.multiple = {}; + for (var i = params.multiple.length; --i >= 0;) { + var d = params.multiple[i]; + var ds = d.print("%Y%m%d"); + cal.multiple[ds] = d; + } + } + cal.showsOtherMonths = params.showOthers; + cal.yearStep = params.step; + cal.setRange(params.range[0], params.range[1]); + cal.params = params; + cal.setDateStatusHandler(params.dateStatusFunc); + cal.getDateText = params.dateText; + cal.setDateFormat(dateFmt); + if (mustCreate) + cal.create(); + cal.refresh(); + if (!params.position) + cal.showAtElement(params.button || params.displayArea || params.inputField, params.align); + else + cal.showAt(params.position[0], params.position[1]); + return false; + }; + + return cal; +}; diff --git a/htdocs/js/jscalendar/calendar.js b/htdocs/js/jscalendar/calendar.js new file mode 100644 index 0000000..f6c1398 --- /dev/null +++ b/htdocs/js/jscalendar/calendar.js @@ -0,0 +1,1806 @@ +/* Copyright Mihai Bazon, 2002-2005 | www.bazon.net/mishoo + * ----------------------------------------------------------- + * + * The DHTML Calendar, version 1.0 "It is happening again" + * + * Details and latest version at: + * www.dynarch.com/projects/calendar + * + * This script is developed by Dynarch.com. Visit us at www.dynarch.com. + * + * This script is distributed under the GNU Lesser General Public License. + * Read the entire license text here: http://www.gnu.org/licenses/lgpl.html + */ + +// $Id$ + +/** The Calendar object constructor. */ +Calendar = function (firstDayOfWeek, dateStr, onSelected, onClose) { + // member variables + this.activeDiv = null; + this.currentDateEl = null; + this.getDateStatus = null; + this.getDateToolTip = null; + this.getDateText = null; + this.timeout = null; + this.onSelected = onSelected || null; + this.onClose = onClose || null; + this.dragging = false; + this.hidden = false; + this.minYear = 1970; + this.maxYear = 2050; + this.dateFormat = Calendar._TT["DEF_DATE_FORMAT"]; + this.ttDateFormat = Calendar._TT["TT_DATE_FORMAT"]; + this.isPopup = true; + this.weekNumbers = true; + this.firstDayOfWeek = typeof firstDayOfWeek == "number" ? firstDayOfWeek : Calendar._FD; // 0 for Sunday, 1 for Monday, etc. + this.showsOtherMonths = false; + this.dateStr = dateStr; + this.ar_days = null; + this.showsTime = false; + this.time24 = true; + this.yearStep = 2; + this.hiliteToday = true; + this.multiple = null; + // HTML elements + this.table = null; + this.element = null; + this.tbody = null; + this.firstdayname = null; + // Combo boxes + this.monthsCombo = null; + this.yearsCombo = null; + this.hilitedMonth = null; + this.activeMonth = null; + this.hilitedYear = null; + this.activeYear = null; + // Information + this.dateClicked = false; + + // one-time initializations + if (typeof Calendar._SDN == "undefined") { + // table of short day names + if (typeof Calendar._SDN_len == "undefined") + Calendar._SDN_len = 3; + var ar = new Array(); + for (var i = 8; i > 0;) { + ar[--i] = Calendar._DN[i].substr(0, Calendar._SDN_len); + } + Calendar._SDN = ar; + // table of short month names + if (typeof Calendar._SMN_len == "undefined") + Calendar._SMN_len = 3; + ar = new Array(); + for (var i = 12; i > 0;) { + ar[--i] = Calendar._MN[i].substr(0, Calendar._SMN_len); + } + Calendar._SMN = ar; + } +}; + +// ** constants + +/// "static", needed for event handlers. +Calendar._C = null; + +/// detect a special case of "web browser" +Calendar.is_ie = ( /msie/i.test(navigator.userAgent) && + !/opera/i.test(navigator.userAgent) ); + +Calendar.is_ie5 = ( Calendar.is_ie && /msie 5\.0/i.test(navigator.userAgent) ); + +/// detect Opera browser +Calendar.is_opera = /opera/i.test(navigator.userAgent); + +/// detect KHTML-based browsers +Calendar.is_khtml = /Konqueror|Safari|KHTML/i.test(navigator.userAgent); + +// BEGIN: UTILITY FUNCTIONS; beware that these might be moved into a separate +// library, at some point. + +Calendar.getAbsolutePos = function(el) { + var SL = 0, ST = 0; + var is_div = /^div$/i.test(el.tagName); + if (is_div && el.scrollLeft) + SL = el.scrollLeft; + if (is_div && el.scrollTop) + ST = el.scrollTop; + var r = { x: el.offsetLeft - SL, y: el.offsetTop - ST }; + if (el.offsetParent) { + var tmp = this.getAbsolutePos(el.offsetParent); + r.x += tmp.x; + r.y += tmp.y; + } + return r; +}; + +Calendar.isRelated = function (el, evt) { + var related = evt.relatedTarget; + if (!related) { + var type = evt.type; + if (type == "mouseover") { + related = evt.fromElement; + } else if (type == "mouseout") { + related = evt.toElement; + } + } + while (related) { + if (related == el) { + return true; + } + related = related.parentNode; + } + return false; +}; + +Calendar.removeClass = function(el, className) { + if (!(el && el.className)) { + return; + } + var cls = el.className.split(" "); + var ar = new Array(); + for (var i = cls.length; i > 0;) { + if (cls[--i] != className) { + ar[ar.length] = cls[i]; + } + } + el.className = ar.join(" "); +}; + +Calendar.addClass = function(el, className) { + Calendar.removeClass(el, className); + el.className += " " + className; +}; + +// FIXME: the following 2 functions totally suck, are useless and should be replaced immediately. +Calendar.getElement = function(ev) { + var f = Calendar.is_ie ? window.event.srcElement : ev.currentTarget; + while (f.nodeType != 1 || /^div$/i.test(f.tagName)) + f = f.parentNode; + return f; +}; + +Calendar.getTargetElement = function(ev) { + var f = Calendar.is_ie ? window.event.srcElement : ev.target; + while (f.nodeType != 1) + f = f.parentNode; + return f; +}; + +Calendar.stopEvent = function(ev) { + ev || (ev = window.event); + if (Calendar.is_ie) { + ev.cancelBubble = true; + ev.returnValue = false; + } else { + ev.preventDefault(); + ev.stopPropagation(); + } + return false; +}; + +Calendar.addEvent = function(el, evname, func) { + if (el.attachEvent) { // IE + el.attachEvent("on" + evname, func); + } else if (el.addEventListener) { // Gecko / W3C + el.addEventListener(evname, func, true); + } else { + el["on" + evname] = func; + } +}; + +Calendar.removeEvent = function(el, evname, func) { + if (el.detachEvent) { // IE + el.detachEvent("on" + evname, func); + } else if (el.removeEventListener) { // Gecko / W3C + el.removeEventListener(evname, func, true); + } else { + el["on" + evname] = null; + } +}; + +Calendar.createElement = function(type, parent) { + var el = null; + if (document.createElementNS) { + // use the XHTML namespace; IE won't normally get here unless + // _they_ "fix" the DOM2 implementation. + el = document.createElementNS("http://www.w3.org/1999/xhtml", type); + } else { + el = document.createElement(type); + } + if (typeof parent != "undefined") { + parent.appendChild(el); + } + return el; +}; + +// END: UTILITY FUNCTIONS + +// BEGIN: CALENDAR STATIC FUNCTIONS + +/** Internal -- adds a set of events to make some element behave like a button. */ +Calendar._add_evs = function(el) { + with (Calendar) { + addEvent(el, "mouseover", dayMouseOver); + addEvent(el, "mousedown", dayMouseDown); + addEvent(el, "mouseout", dayMouseOut); + if (is_ie) { + addEvent(el, "dblclick", dayMouseDblClick); + el.setAttribute("unselectable", true); + } + } +}; + +Calendar.findMonth = function(el) { + if (typeof el.month != "undefined") { + return el; + } else if (typeof el.parentNode.month != "undefined") { + return el.parentNode; + } + return null; +}; + +Calendar.findYear = function(el) { + if (typeof el.year != "undefined") { + return el; + } else if (typeof el.parentNode.year != "undefined") { + return el.parentNode; + } + return null; +}; + +Calendar.showMonthsCombo = function () { + var cal = Calendar._C; + if (!cal) { + return false; + } + var cal = cal; + var cd = cal.activeDiv; + var mc = cal.monthsCombo; + if (cal.hilitedMonth) { + Calendar.removeClass(cal.hilitedMonth, "hilite"); + } + if (cal.activeMonth) { + Calendar.removeClass(cal.activeMonth, "active"); + } + var mon = cal.monthsCombo.getElementsByTagName("div")[cal.date.getMonth()]; + Calendar.addClass(mon, "active"); + cal.activeMonth = mon; + var s = mc.style; + s.display = "block"; + if (cd.navtype < 0) + s.left = cd.offsetLeft + "px"; + else { + var mcw = mc.offsetWidth; + if (typeof mcw == "undefined") + // Konqueror brain-dead techniques + mcw = 50; + s.left = (cd.offsetLeft + cd.offsetWidth - mcw) + "px"; + } + s.top = (cd.offsetTop + cd.offsetHeight) + "px"; +}; + +Calendar.showYearsCombo = function (fwd) { + var cal = Calendar._C; + if (!cal) { + return false; + } + var cal = cal; + var cd = cal.activeDiv; + var yc = cal.yearsCombo; + if (cal.hilitedYear) { + Calendar.removeClass(cal.hilitedYear, "hilite"); + } + if (cal.activeYear) { + Calendar.removeClass(cal.activeYear, "active"); + } + cal.activeYear = null; + var Y = cal.date.getFullYear() + (fwd ? 1 : -1); + var yr = yc.firstChild; + var show = false; + for (var i = 12; i > 0; --i) { + if (Y >= cal.minYear && Y <= cal.maxYear) { + yr.innerHTML = Y; + yr.year = Y; + yr.style.display = "block"; + show = true; + } else { + yr.style.display = "none"; + } + yr = yr.nextSibling; + Y += fwd ? cal.yearStep : -cal.yearStep; + } + if (show) { + var s = yc.style; + s.display = "block"; + if (cd.navtype < 0) + s.left = cd.offsetLeft + "px"; + else { + var ycw = yc.offsetWidth; + if (typeof ycw == "undefined") + // Konqueror brain-dead techniques + ycw = 50; + s.left = (cd.offsetLeft + cd.offsetWidth - ycw) + "px"; + } + s.top = (cd.offsetTop + cd.offsetHeight) + "px"; + } +}; + +// event handlers + +Calendar.tableMouseUp = function(ev) { + var cal = Calendar._C; + if (!cal) { + return false; + } + if (cal.timeout) { + clearTimeout(cal.timeout); + } + var el = cal.activeDiv; + if (!el) { + return false; + } + var target = Calendar.getTargetElement(ev); + ev || (ev = window.event); + Calendar.removeClass(el, "active"); + if (target == el || target.parentNode == el) { + Calendar.cellClick(el, ev); + } + var mon = Calendar.findMonth(target); + var date = null; + if (mon) { + date = new Date(cal.date); + if (mon.month != date.getMonth()) { + date.setMonth(mon.month); + cal.setDate(date); + cal.dateClicked = false; + cal.callHandler(); + } + } else { + var year = Calendar.findYear(target); + if (year) { + date = new Date(cal.date); + if (year.year != date.getFullYear()) { + date.setFullYear(year.year); + cal.setDate(date); + cal.dateClicked = false; + cal.callHandler(); + } + } + } + with (Calendar) { + removeEvent(document, "mouseup", tableMouseUp); + removeEvent(document, "mouseover", tableMouseOver); + removeEvent(document, "mousemove", tableMouseOver); + cal._hideCombos(); + _C = null; + return stopEvent(ev); + } +}; + +Calendar.tableMouseOver = function (ev) { + var cal = Calendar._C; + if (!cal) { + return; + } + var el = cal.activeDiv; + var target = Calendar.getTargetElement(ev); + if (target == el || target.parentNode == el) { + Calendar.addClass(el, "hilite active"); + Calendar.addClass(el.parentNode, "rowhilite"); + } else { + if (typeof el.navtype == "undefined" || (el.navtype != 50 && (el.navtype == 0 || Math.abs(el.navtype) > 2))) + Calendar.removeClass(el, "active"); + Calendar.removeClass(el, "hilite"); + Calendar.removeClass(el.parentNode, "rowhilite"); + } + ev || (ev = window.event); + if (el.navtype == 50 && target != el) { + var pos = Calendar.getAbsolutePos(el); + var w = el.offsetWidth; + var x = ev.clientX; + var dx; + var decrease = true; + if (x > pos.x + w) { + dx = x - pos.x - w; + decrease = false; + } else + dx = pos.x - x; + + if (dx < 0) dx = 0; + var range = el._range; + var current = el._current; + var count = Math.floor(dx / 10) % range.length; + for (var i = range.length; --i >= 0;) + if (range[i] == current) + break; + while (count-- > 0) + if (decrease) { + if (--i < 0) + i = range.length - 1; + } else if ( ++i >= range.length ) + i = 0; + var newval = range[i]; + el.innerHTML = newval; + + cal.onUpdateTime(); + } + var mon = Calendar.findMonth(target); + if (mon) { + if (mon.month != cal.date.getMonth()) { + if (cal.hilitedMonth) { + Calendar.removeClass(cal.hilitedMonth, "hilite"); + } + Calendar.addClass(mon, "hilite"); + cal.hilitedMonth = mon; + } else if (cal.hilitedMonth) { + Calendar.removeClass(cal.hilitedMonth, "hilite"); + } + } else { + if (cal.hilitedMonth) { + Calendar.removeClass(cal.hilitedMonth, "hilite"); + } + var year = Calendar.findYear(target); + if (year) { + if (year.year != cal.date.getFullYear()) { + if (cal.hilitedYear) { + Calendar.removeClass(cal.hilitedYear, "hilite"); + } + Calendar.addClass(year, "hilite"); + cal.hilitedYear = year; + } else if (cal.hilitedYear) { + Calendar.removeClass(cal.hilitedYear, "hilite"); + } + } else if (cal.hilitedYear) { + Calendar.removeClass(cal.hilitedYear, "hilite"); + } + } + return Calendar.stopEvent(ev); +}; + +Calendar.tableMouseDown = function (ev) { + if (Calendar.getTargetElement(ev) == Calendar.getElement(ev)) { + return Calendar.stopEvent(ev); + } +}; + +Calendar.calDragIt = function (ev) { + var cal = Calendar._C; + if (!(cal && cal.dragging)) { + return false; + } + var posX; + var posY; + if (Calendar.is_ie) { + posY = window.event.clientY + document.body.scrollTop; + posX = window.event.clientX + document.body.scrollLeft; + } else { + posX = ev.pageX; + posY = ev.pageY; + } + cal.hideShowCovered(); + var st = cal.element.style; + st.left = (posX - cal.xOffs) + "px"; + st.top = (posY - cal.yOffs) + "px"; + return Calendar.stopEvent(ev); +}; + +Calendar.calDragEnd = function (ev) { + var cal = Calendar._C; + if (!cal) { + return false; + } + cal.dragging = false; + with (Calendar) { + removeEvent(document, "mousemove", calDragIt); + removeEvent(document, "mouseup", calDragEnd); + tableMouseUp(ev); + } + cal.hideShowCovered(); +}; + +Calendar.dayMouseDown = function(ev) { + var el = Calendar.getElement(ev); + if (el.disabled) { + return false; + } + var cal = el.calendar; + cal.activeDiv = el; + Calendar._C = cal; + if (el.navtype != 300) with (Calendar) { + if (el.navtype == 50) { + el._current = el.innerHTML; + addEvent(document, "mousemove", tableMouseOver); + } else + addEvent(document, Calendar.is_ie5 ? "mousemove" : "mouseover", tableMouseOver); + addClass(el, "hilite active"); + addEvent(document, "mouseup", tableMouseUp); + } else if (cal.isPopup) { + cal._dragStart(ev); + } + if (el.navtype == -1 || el.navtype == 1) { + if (cal.timeout) clearTimeout(cal.timeout); + cal.timeout = setTimeout("Calendar.showMonthsCombo()", 250); + } else if (el.navtype == -2 || el.navtype == 2) { + if (cal.timeout) clearTimeout(cal.timeout); + cal.timeout = setTimeout((el.navtype > 0) ? "Calendar.showYearsCombo(true)" : "Calendar.showYearsCombo(false)", 250); + } else { + cal.timeout = null; + } + return Calendar.stopEvent(ev); +}; + +Calendar.dayMouseDblClick = function(ev) { + Calendar.cellClick(Calendar.getElement(ev), ev || window.event); + if (Calendar.is_ie) { + document.selection.empty(); + } +}; + +Calendar.dayMouseOver = function(ev) { + var el = Calendar.getElement(ev); + if (Calendar.isRelated(el, ev) || Calendar._C || el.disabled) { + return false; + } + if (el.ttip) { + if (el.ttip.substr(0, 1) == "_") { + el.ttip = el.caldate.print(el.calendar.ttDateFormat) + el.ttip.substr(1); + } + el.calendar.tooltips.innerHTML = el.ttip; + } + if (el.navtype != 300) { + Calendar.addClass(el, "hilite"); + if (el.caldate) { + Calendar.addClass(el.parentNode, "rowhilite"); + } + } + return Calendar.stopEvent(ev); +}; + +Calendar.dayMouseOut = function(ev) { + with (Calendar) { + var el = getElement(ev); + if (isRelated(el, ev) || _C || el.disabled) + return false; + removeClass(el, "hilite"); + if (el.caldate) + removeClass(el.parentNode, "rowhilite"); + if (el.calendar) + el.calendar.tooltips.innerHTML = _TT["SEL_DATE"]; + return stopEvent(ev); + } +}; + +/** + * A generic "click" handler :) handles all types of buttons defined in this + * calendar. + */ +Calendar.cellClick = function(el, ev) { + var cal = el.calendar; + var closing = false; + var newdate = false; + var date = null; + if (typeof el.navtype == "undefined") { + if (cal.currentDateEl) { + Calendar.removeClass(cal.currentDateEl, "selected"); + Calendar.addClass(el, "selected"); + closing = (cal.currentDateEl == el); + if (!closing) { + cal.currentDateEl = el; + } + } + cal.date.setDateOnly(el.caldate); + date = cal.date; + var other_month = !(cal.dateClicked = !el.otherMonth); + if (!other_month && !cal.currentDateEl) + cal._toggleMultipleDate(new Date(date)); + else + newdate = !el.disabled; + // a date was clicked + if (other_month) + cal._init(cal.firstDayOfWeek, date); + } else { + if (el.navtype == 200) { + Calendar.removeClass(el, "hilite"); + cal.callCloseHandler(); + return; + } + date = new Date(cal.date); + if (el.navtype == 0) + date.setDateOnly(new Date()); // TODAY + // unless "today" was clicked, we assume no date was clicked so + // the selected handler will know not to close the calenar when + // in single-click mode. + // cal.dateClicked = (el.navtype == 0); + cal.dateClicked = false; + var year = date.getFullYear(); + var mon = date.getMonth(); + function setMonth(m) { + var day = date.getDate(); + var max = date.getMonthDays(m); + if (day > max) { + date.setDate(max); + } + date.setMonth(m); + }; + switch (el.navtype) { + case 400: + Calendar.removeClass(el, "hilite"); + var text = Calendar._TT["ABOUT"]; + if (typeof text != "undefined") { + text += cal.showsTime ? Calendar._TT["ABOUT_TIME"] : ""; + } else { + // FIXME: this should be removed as soon as lang files get updated! + text = "Help and about box text is not translated into this language.\n" + + "If you know this language and you feel generous please update\n" + + "the corresponding file in \"lang\" subdir to match calendar-en.js\n" + + "and send it back to to get it into the distribution ;-)\n\n" + + "Thank you!\n" + + "http://dynarch.com/mishoo/calendar.epl\n"; + } + alert(text); + return; + case -2: + if (year > cal.minYear) { + date.setFullYear(year - 1); + } + break; + case -1: + if (mon > 0) { + setMonth(mon - 1); + } else if (year-- > cal.minYear) { + date.setFullYear(year); + setMonth(11); + } + break; + case 1: + if (mon < 11) { + setMonth(mon + 1); + } else if (year < cal.maxYear) { + date.setFullYear(year + 1); + setMonth(0); + } + break; + case 2: + if (year < cal.maxYear) { + date.setFullYear(year + 1); + } + break; + case 100: + cal.setFirstDayOfWeek(el.fdow); + return; + case 50: + var range = el._range; + var current = el.innerHTML; + for (var i = range.length; --i >= 0;) + if (range[i] == current) + break; + if (ev && ev.shiftKey) { + if (--i < 0) + i = range.length - 1; + } else if ( ++i >= range.length ) + i = 0; + var newval = range[i]; + el.innerHTML = newval; + cal.onUpdateTime(); + return; + case 0: + // TODAY will bring us here + if ((typeof cal.getDateStatus == "function") && + cal.getDateStatus(date, date.getFullYear(), date.getMonth(), date.getDate())) { + return false; + } + break; + } + if (!date.equalsTo(cal.date)) { + cal.setDate(date); + newdate = true; + } else if (el.navtype == 0) + newdate = closing = true; + } + if (newdate) { + ev && cal.callHandler(); + } + if (closing) { + Calendar.removeClass(el, "hilite"); + ev && cal.callCloseHandler(); + } +}; + +// END: CALENDAR STATIC FUNCTIONS + +// BEGIN: CALENDAR OBJECT FUNCTIONS + +/** + * This function creates the calendar inside the given parent. If _par is + * null than it creates a popup calendar inside the BODY element. If _par is + * an element, be it BODY, then it creates a non-popup calendar (still + * hidden). Some properties need to be set before calling this function. + */ +Calendar.prototype.create = function (_par) { + var parent = null; + if (! _par) { + // default parent is the document body, in which case we create + // a popup calendar. + parent = document.getElementsByTagName("body")[0]; + this.isPopup = true; + } else { + parent = _par; + this.isPopup = false; + } + this.date = this.dateStr ? new Date(this.dateStr) : new Date(); + + var table = Calendar.createElement("table"); + this.table = table; + table.cellSpacing = 0; + table.cellPadding = 0; + table.calendar = this; + Calendar.addEvent(table, "mousedown", Calendar.tableMouseDown); + + var div = Calendar.createElement("div"); + this.element = div; + div.className = "calendar"; + if (this.isPopup) { + div.style.position = "absolute"; + div.style.display = "none"; + } + div.appendChild(table); + + var thead = Calendar.createElement("thead", table); + var cell = null; + var row = null; + + var cal = this; + var hh = function (text, cs, navtype) { + cell = Calendar.createElement("td", row); + cell.colSpan = cs; + cell.className = "button"; + if (navtype != 0 && Math.abs(navtype) <= 2) + cell.className += " nav"; + Calendar._add_evs(cell); + cell.calendar = cal; + cell.navtype = navtype; + cell.innerHTML = "
" + text + "
"; + return cell; + }; + + row = Calendar.createElement("tr", thead); + var title_length = 6; + (this.isPopup) && --title_length; + (this.weekNumbers) && ++title_length; + + hh("?", 1, 400).ttip = Calendar._TT["INFO"]; + this.title = hh("", title_length, 300); + this.title.className = "title"; + if (this.isPopup) { + this.title.ttip = Calendar._TT["DRAG_TO_MOVE"]; + this.title.style.cursor = "move"; + hh("×", 1, 200).ttip = Calendar._TT["CLOSE"]; + } + + row = Calendar.createElement("tr", thead); + row.className = "headrow"; + + this._nav_py = hh("«", 1, -2); + this._nav_py.ttip = Calendar._TT["PREV_YEAR"]; + + this._nav_pm = hh("‹", 1, -1); + this._nav_pm.ttip = Calendar._TT["PREV_MONTH"]; + + this._nav_now = hh(Calendar._TT["TODAY"], this.weekNumbers ? 4 : 3, 0); + this._nav_now.ttip = Calendar._TT["GO_TODAY"]; + + this._nav_nm = hh("›", 1, 1); + this._nav_nm.ttip = Calendar._TT["NEXT_MONTH"]; + + this._nav_ny = hh("»", 1, 2); + this._nav_ny.ttip = Calendar._TT["NEXT_YEAR"]; + + // day names + row = Calendar.createElement("tr", thead); + row.className = "daynames"; + if (this.weekNumbers) { + cell = Calendar.createElement("td", row); + cell.className = "name wn"; + cell.innerHTML = Calendar._TT["WK"]; + } + for (var i = 7; i > 0; --i) { + cell = Calendar.createElement("td", row); + if (!i) { + cell.navtype = 100; + cell.calendar = this; + Calendar._add_evs(cell); + } + } + this.firstdayname = (this.weekNumbers) ? row.firstChild.nextSibling : row.firstChild; + this._displayWeekdays(); + + var tbody = Calendar.createElement("tbody", table); + this.tbody = tbody; + + for (i = 6; i > 0; --i) { + row = Calendar.createElement("tr", tbody); + if (this.weekNumbers) { + cell = Calendar.createElement("td", row); + } + for (var j = 7; j > 0; --j) { + cell = Calendar.createElement("td", row); + cell.calendar = this; + Calendar._add_evs(cell); + } + } + + if (this.showsTime) { + row = Calendar.createElement("tr", tbody); + row.className = "time"; + + cell = Calendar.createElement("td", row); + cell.className = "time"; + cell.colSpan = 2; + cell.innerHTML = Calendar._TT["TIME"] || " "; + + cell = Calendar.createElement("td", row); + cell.className = "time"; + cell.colSpan = this.weekNumbers ? 4 : 3; + + (function(){ + function makeTimePart(className, init, range_start, range_end) { + var part = Calendar.createElement("span", cell); + part.className = className; + part.innerHTML = init; + part.calendar = cal; + part.ttip = Calendar._TT["TIME_PART"]; + part.navtype = 50; + part._range = []; + if (typeof range_start != "number") + part._range = range_start; + else { + for (var i = range_start; i <= range_end; ++i) { + var txt; + if (i < 10 && range_end >= 10) txt = '0' + i; + else txt = '' + i; + part._range[part._range.length] = txt; + } + } + Calendar._add_evs(part); + return part; + }; + var hrs = cal.date.getHours(); + var mins = cal.date.getMinutes(); + var t12 = !cal.time24; + var pm = (hrs > 12); + if (t12 && pm) hrs -= 12; + var H = makeTimePart("hour", hrs, t12 ? 1 : 0, t12 ? 12 : 23); + var span = Calendar.createElement("span", cell); + span.innerHTML = ":"; + span.className = "colon"; + var M = makeTimePart("minute", mins, 0, 59); + var AP = null; + cell = Calendar.createElement("td", row); + cell.className = "time"; + cell.colSpan = 2; + if (t12) + AP = makeTimePart("ampm", pm ? "pm" : "am", ["am", "pm"]); + else + cell.innerHTML = " "; + + cal.onSetTime = function() { + var pm, hrs = this.date.getHours(), + mins = this.date.getMinutes(); + if (t12) { + pm = (hrs >= 12); + if (pm) hrs -= 12; + if (hrs == 0) hrs = 12; + AP.innerHTML = pm ? "pm" : "am"; + } + H.innerHTML = (hrs < 10) ? ("0" + hrs) : hrs; + M.innerHTML = (mins < 10) ? ("0" + mins) : mins; + }; + + cal.onUpdateTime = function() { + var date = this.date; + var h = parseInt(H.innerHTML, 10); + if (t12) { + if (/pm/i.test(AP.innerHTML) && h < 12) + h += 12; + else if (/am/i.test(AP.innerHTML) && h == 12) + h = 0; + } + var d = date.getDate(); + var m = date.getMonth(); + var y = date.getFullYear(); + date.setHours(h); + date.setMinutes(parseInt(M.innerHTML, 10)); + date.setFullYear(y); + date.setMonth(m); + date.setDate(d); + this.dateClicked = false; + this.callHandler(); + }; + })(); + } else { + this.onSetTime = this.onUpdateTime = function() {}; + } + + var tfoot = Calendar.createElement("tfoot", table); + + row = Calendar.createElement("tr", tfoot); + row.className = "footrow"; + + cell = hh(Calendar._TT["SEL_DATE"], this.weekNumbers ? 8 : 7, 300); + cell.className = "ttip"; + if (this.isPopup) { + cell.ttip = Calendar._TT["DRAG_TO_MOVE"]; + cell.style.cursor = "move"; + } + this.tooltips = cell; + + div = Calendar.createElement("div", this.element); + this.monthsCombo = div; + div.className = "combo"; + for (i = 0; i < Calendar._MN.length; ++i) { + var mn = Calendar.createElement("div"); + mn.className = Calendar.is_ie ? "label-IEfix" : "label"; + mn.month = i; + mn.innerHTML = Calendar._SMN[i]; + div.appendChild(mn); + } + + div = Calendar.createElement("div", this.element); + this.yearsCombo = div; + div.className = "combo"; + for (i = 12; i > 0; --i) { + var yr = Calendar.createElement("div"); + yr.className = Calendar.is_ie ? "label-IEfix" : "label"; + div.appendChild(yr); + } + + this._init(this.firstDayOfWeek, this.date); + parent.appendChild(this.element); +}; + +/** keyboard navigation, only for popup calendars */ +Calendar._keyEvent = function(ev) { + var cal = window._dynarch_popupCalendar; + if (!cal || cal.multiple) + return false; + (Calendar.is_ie) && (ev = window.event); + var act = (Calendar.is_ie || ev.type == "keypress"), + K = ev.keyCode; + if (ev.ctrlKey) { + switch (K) { + case 37: // KEY left + act && Calendar.cellClick(cal._nav_pm); + break; + case 38: // KEY up + act && Calendar.cellClick(cal._nav_py); + break; + case 39: // KEY right + act && Calendar.cellClick(cal._nav_nm); + break; + case 40: // KEY down + act && Calendar.cellClick(cal._nav_ny); + break; + default: + return false; + } + } else switch (K) { + case 32: // KEY space (now) + Calendar.cellClick(cal._nav_now); + break; + case 27: // KEY esc + act && cal.callCloseHandler(); + break; + case 37: // KEY left + case 38: // KEY up + case 39: // KEY right + case 40: // KEY down + if (act) { + var prev, x, y, ne, el, step; + prev = K == 37 || K == 38; + step = (K == 37 || K == 39) ? 1 : 7; + function setVars() { + el = cal.currentDateEl; + var p = el.pos; + x = p & 15; + y = p >> 4; + ne = cal.ar_days[y][x]; + };setVars(); + function prevMonth() { + var date = new Date(cal.date); + date.setDate(date.getDate() - step); + cal.setDate(date); + }; + function nextMonth() { + var date = new Date(cal.date); + date.setDate(date.getDate() + step); + cal.setDate(date); + }; + while (1) { + switch (K) { + case 37: // KEY left + if (--x >= 0) + ne = cal.ar_days[y][x]; + else { + x = 6; + K = 38; + continue; + } + break; + case 38: // KEY up + if (--y >= 0) + ne = cal.ar_days[y][x]; + else { + prevMonth(); + setVars(); + } + break; + case 39: // KEY right + if (++x < 7) + ne = cal.ar_days[y][x]; + else { + x = 0; + K = 40; + continue; + } + break; + case 40: // KEY down + if (++y < cal.ar_days.length) + ne = cal.ar_days[y][x]; + else { + nextMonth(); + setVars(); + } + break; + } + break; + } + if (ne) { + if (!ne.disabled) + Calendar.cellClick(ne); + else if (prev) + prevMonth(); + else + nextMonth(); + } + } + break; + case 13: // KEY enter + if (act) + Calendar.cellClick(cal.currentDateEl, ev); + break; + default: + return false; + } + return Calendar.stopEvent(ev); +}; + +/** + * (RE)Initializes the calendar to the given date and firstDayOfWeek + */ +Calendar.prototype._init = function (firstDayOfWeek, date) { + var today = new Date(), + TY = today.getFullYear(), + TM = today.getMonth(), + TD = today.getDate(); + this.table.style.visibility = "hidden"; + var year = date.getFullYear(); + if (year < this.minYear) { + year = this.minYear; + date.setFullYear(year); + } else if (year > this.maxYear) { + year = this.maxYear; + date.setFullYear(year); + } + this.firstDayOfWeek = firstDayOfWeek; + this.date = new Date(date); + var month = date.getMonth(); + var mday = date.getDate(); + var no_days = date.getMonthDays(); + + // calendar voodoo for computing the first day that would actually be + // displayed in the calendar, even if it's from the previous month. + // WARNING: this is magic. ;-) + date.setDate(1); + var day1 = (date.getDay() - this.firstDayOfWeek) % 7; + if (day1 < 0) + day1 += 7; + date.setDate(-day1); + date.setDate(date.getDate() + 1); + + var row = this.tbody.firstChild; + var MN = Calendar._SMN[month]; + var ar_days = this.ar_days = new Array(); + var weekend = Calendar._TT["WEEKEND"]; + var dates = this.multiple ? (this.datesCells = {}) : null; + for (var i = 0; i < 6; ++i, row = row.nextSibling) { + var cell = row.firstChild; + if (this.weekNumbers) { + cell.className = "day wn"; + cell.innerHTML = date.getWeekNumber(); + cell = cell.nextSibling; + } + row.className = "daysrow"; + var hasdays = false, iday, dpos = ar_days[i] = []; + for (var j = 0; j < 7; ++j, cell = cell.nextSibling, date.setDate(iday + 1)) { + iday = date.getDate(); + var wday = date.getDay(); + cell.className = "day"; + cell.pos = i << 4 | j; + dpos[j] = cell; + var current_month = (date.getMonth() == month); + if (!current_month) { + if (this.showsOtherMonths) { + cell.className += " othermonth"; + cell.otherMonth = true; + } else { + cell.className = "emptycell"; + cell.innerHTML = " "; + cell.disabled = true; + continue; + } + } else { + cell.otherMonth = false; + hasdays = true; + } + cell.disabled = false; + cell.innerHTML = this.getDateText ? this.getDateText(date, iday) : iday; + if (dates) + dates[date.print("%Y%m%d")] = cell; + if (this.getDateStatus) { + var status = this.getDateStatus(date, year, month, iday); + if (this.getDateToolTip) { + var toolTip = this.getDateToolTip(date, year, month, iday); + if (toolTip) + cell.title = toolTip; + } + if (status === true) { + cell.className += " disabled"; + cell.disabled = true; + } else { + if (/disabled/i.test(status)) + cell.disabled = true; + cell.className += " " + status; + } + } + if (!cell.disabled) { + cell.caldate = new Date(date); + cell.ttip = "_"; + if (!this.multiple && current_month + && iday == mday && this.hiliteToday) { + cell.className += " selected"; + this.currentDateEl = cell; + } + if (date.getFullYear() == TY && + date.getMonth() == TM && + iday == TD) { + cell.className += " today"; + cell.ttip += Calendar._TT["PART_TODAY"]; + } + if (weekend.indexOf(wday.toString()) != -1) + cell.className += cell.otherMonth ? " oweekend" : " weekend"; + } + } + if (!(hasdays || this.showsOtherMonths)) + row.className = "emptyrow"; + } + this.title.innerHTML = Calendar._MN[month] + ", " + year; + this.onSetTime(); + this.table.style.visibility = "visible"; + this._initMultipleDates(); + // PROFILE + // this.tooltips.innerHTML = "Generated in " + ((new Date()) - today) + " ms"; +}; + +Calendar.prototype._initMultipleDates = function() { + if (this.multiple) { + for (var i in this.multiple) { + var cell = this.datesCells[i]; + var d = this.multiple[i]; + if (!d) + continue; + if (cell) + cell.className += " selected"; + } + } +}; + +Calendar.prototype._toggleMultipleDate = function(date) { + if (this.multiple) { + var ds = date.print("%Y%m%d"); + var cell = this.datesCells[ds]; + if (cell) { + var d = this.multiple[ds]; + if (!d) { + Calendar.addClass(cell, "selected"); + this.multiple[ds] = date; + } else { + Calendar.removeClass(cell, "selected"); + delete this.multiple[ds]; + } + } + } +}; + +Calendar.prototype.setDateToolTipHandler = function (unaryFunction) { + this.getDateToolTip = unaryFunction; +}; + +/** + * Calls _init function above for going to a certain date (but only if the + * date is different than the currently selected one). + */ +Calendar.prototype.setDate = function (date) { + if (!date.equalsTo(this.date)) { + this._init(this.firstDayOfWeek, date); + } +}; + +/** + * Refreshes the calendar. Useful if the "disabledHandler" function is + * dynamic, meaning that the list of disabled date can change at runtime. + * Just * call this function if you think that the list of disabled dates + * should * change. + */ +Calendar.prototype.refresh = function () { + this._init(this.firstDayOfWeek, this.date); +}; + +/** Modifies the "firstDayOfWeek" parameter (pass 0 for Synday, 1 for Monday, etc.). */ +Calendar.prototype.setFirstDayOfWeek = function (firstDayOfWeek) { + this._init(firstDayOfWeek, this.date); + this._displayWeekdays(); +}; + +/** + * Allows customization of what dates are enabled. The "unaryFunction" + * parameter must be a function object that receives the date (as a JS Date + * object) and returns a boolean value. If the returned value is true then + * the passed date will be marked as disabled. + */ +Calendar.prototype.setDateStatusHandler = Calendar.prototype.setDisabledHandler = function (unaryFunction) { + this.getDateStatus = unaryFunction; +}; + +/** Customization of allowed year range for the calendar. */ +Calendar.prototype.setRange = function (a, z) { + this.minYear = a; + this.maxYear = z; +}; + +/** Calls the first user handler (selectedHandler). */ +Calendar.prototype.callHandler = function () { + if (this.onSelected) { + this.onSelected(this, this.date.print(this.dateFormat)); + } +}; + +/** Calls the second user handler (closeHandler). */ +Calendar.prototype.callCloseHandler = function () { + if (this.onClose) { + this.onClose(this); + } + this.hideShowCovered(); +}; + +/** Removes the calendar object from the DOM tree and destroys it. */ +Calendar.prototype.destroy = function () { + var el = this.element.parentNode; + el.removeChild(this.element); + Calendar._C = null; + window._dynarch_popupCalendar = null; +}; + +/** + * Moves the calendar element to a different section in the DOM tree (changes + * its parent). + */ +Calendar.prototype.reparent = function (new_parent) { + var el = this.element; + el.parentNode.removeChild(el); + new_parent.appendChild(el); +}; + +// This gets called when the user presses a mouse button anywhere in the +// document, if the calendar is shown. If the click was outside the open +// calendar this function closes it. +Calendar._checkCalendar = function(ev) { + var calendar = window._dynarch_popupCalendar; + if (!calendar) { + return false; + } + var el = Calendar.is_ie ? Calendar.getElement(ev) : Calendar.getTargetElement(ev); + for (; el != null && el != calendar.element; el = el.parentNode); + if (el == null) { + // calls closeHandler which should hide the calendar. + window._dynarch_popupCalendar.callCloseHandler(); + return Calendar.stopEvent(ev); + } +}; + +/** Shows the calendar. */ +Calendar.prototype.show = function () { + var rows = this.table.getElementsByTagName("tr"); + for (var i = rows.length; i > 0;) { + var row = rows[--i]; + Calendar.removeClass(row, "rowhilite"); + var cells = row.getElementsByTagName("td"); + for (var j = cells.length; j > 0;) { + var cell = cells[--j]; + Calendar.removeClass(cell, "hilite"); + Calendar.removeClass(cell, "active"); + } + } + this.element.style.display = "block"; + this.hidden = false; + if (this.isPopup) { + window._dynarch_popupCalendar = this; + Calendar.addEvent(document, "keydown", Calendar._keyEvent); + Calendar.addEvent(document, "keypress", Calendar._keyEvent); + Calendar.addEvent(document, "mousedown", Calendar._checkCalendar); + } + this.hideShowCovered(); +}; + +/** + * Hides the calendar. Also removes any "hilite" from the class of any TD + * element. + */ +Calendar.prototype.hide = function () { + if (this.isPopup) { + Calendar.removeEvent(document, "keydown", Calendar._keyEvent); + Calendar.removeEvent(document, "keypress", Calendar._keyEvent); + Calendar.removeEvent(document, "mousedown", Calendar._checkCalendar); + } + this.element.style.display = "none"; + this.hidden = true; + this.hideShowCovered(); +}; + +/** + * Shows the calendar at a given absolute position (beware that, depending on + * the calendar element style -- position property -- this might be relative + * to the parent's containing rectangle). + */ +Calendar.prototype.showAt = function (x, y) { + var s = this.element.style; + s.left = x + "px"; + s.top = y + "px"; + this.show(); +}; + +/** Shows the calendar near a given element. */ +Calendar.prototype.showAtElement = function (el, opts) { + var self = this; + var p = Calendar.getAbsolutePos(el); + if (!opts || typeof opts != "string") { + this.showAt(p.x, p.y + el.offsetHeight); + return true; + } + function fixPosition(box) { + if (box.x < 0) + box.x = 0; + if (box.y < 0) + box.y = 0; + var cp = document.createElement("div"); + var s = cp.style; + s.position = "absolute"; + s.right = s.bottom = s.width = s.height = "0px"; + document.body.appendChild(cp); + var br = Calendar.getAbsolutePos(cp); + document.body.removeChild(cp); + if (Calendar.is_ie) { + br.y += document.body.scrollTop; + br.x += document.body.scrollLeft; + } else { + br.y += window.scrollY; + br.x += window.scrollX; + } + var tmp = box.x + box.width - br.x; + if (tmp > 0) box.x -= tmp; + tmp = box.y + box.height - br.y; + if (tmp > 0) box.y -= tmp; + }; + this.element.style.display = "block"; + Calendar.continuation_for_the_fucking_khtml_browser = function() { + var w = self.element.offsetWidth; + var h = self.element.offsetHeight; + self.element.style.display = "none"; + var valign = opts.substr(0, 1); + var halign = "l"; + if (opts.length > 1) { + halign = opts.substr(1, 1); + } + // vertical alignment + switch (valign) { + case "T": p.y -= h; break; + case "B": p.y += el.offsetHeight; break; + case "C": p.y += (el.offsetHeight - h) / 2; break; + case "t": p.y += el.offsetHeight - h; break; + case "b": break; // already there + } + // horizontal alignment + switch (halign) { + case "L": p.x -= w; break; + case "R": p.x += el.offsetWidth; break; + case "C": p.x += (el.offsetWidth - w) / 2; break; + case "l": p.x += el.offsetWidth - w; break; + case "r": break; // already there + } + p.width = w; + p.height = h + 40; + self.monthsCombo.style.display = "none"; + fixPosition(p); + self.showAt(p.x, p.y); + }; + if (Calendar.is_khtml) + setTimeout("Calendar.continuation_for_the_fucking_khtml_browser()", 10); + else + Calendar.continuation_for_the_fucking_khtml_browser(); +}; + +/** Customizes the date format. */ +Calendar.prototype.setDateFormat = function (str) { + this.dateFormat = str; +}; + +/** Customizes the tooltip date format. */ +Calendar.prototype.setTtDateFormat = function (str) { + this.ttDateFormat = str; +}; + +/** + * Tries to identify the date represented in a string. If successful it also + * calls this.setDate which moves the calendar to the given date. + */ +Calendar.prototype.parseDate = function(str, fmt) { + if (!fmt) + fmt = this.dateFormat; + this.setDate(Date.parseDate(str, fmt)); +}; + +Calendar.prototype.hideShowCovered = function () { + if (!Calendar.is_ie && !Calendar.is_opera) + return; + function getVisib(obj){ + var value = obj.style.visibility; + if (!value) { + if (document.defaultView && typeof (document.defaultView.getComputedStyle) == "function") { // Gecko, W3C + if (!Calendar.is_khtml) + value = document.defaultView. + getComputedStyle(obj, "").getPropertyValue("visibility"); + else + value = ''; + } else if (obj.currentStyle) { // IE + value = obj.currentStyle.visibility; + } else + value = ''; + } + return value; + }; + + var tags = new Array("applet", "iframe", "select"); + var el = this.element; + + var p = Calendar.getAbsolutePos(el); + var EX1 = p.x; + var EX2 = el.offsetWidth + EX1; + var EY1 = p.y; + var EY2 = el.offsetHeight + EY1; + + for (var k = tags.length; k > 0; ) { + var ar = document.getElementsByTagName(tags[--k]); + var cc = null; + + for (var i = ar.length; i > 0;) { + cc = ar[--i]; + + p = Calendar.getAbsolutePos(cc); + var CX1 = p.x; + var CX2 = cc.offsetWidth + CX1; + var CY1 = p.y; + var CY2 = cc.offsetHeight + CY1; + + if (this.hidden || (CX1 > EX2) || (CX2 < EX1) || (CY1 > EY2) || (CY2 < EY1)) { + if (!cc.__msh_save_visibility) { + cc.__msh_save_visibility = getVisib(cc); + } + cc.style.visibility = cc.__msh_save_visibility; + } else { + if (!cc.__msh_save_visibility) { + cc.__msh_save_visibility = getVisib(cc); + } + cc.style.visibility = "hidden"; + } + } + } +}; + +/** Internal function; it displays the bar with the names of the weekday. */ +Calendar.prototype._displayWeekdays = function () { + var fdow = this.firstDayOfWeek; + var cell = this.firstdayname; + var weekend = Calendar._TT["WEEKEND"]; + for (var i = 0; i < 7; ++i) { + cell.className = "day name"; + var realday = (i + fdow) % 7; + if (i) { + cell.ttip = Calendar._TT["DAY_FIRST"].replace("%s", Calendar._DN[realday]); + cell.navtype = 100; + cell.calendar = this; + cell.fdow = realday; + Calendar._add_evs(cell); + } + if (weekend.indexOf(realday.toString()) != -1) { + Calendar.addClass(cell, "weekend"); + } + cell.innerHTML = Calendar._SDN[(i + fdow) % 7]; + cell = cell.nextSibling; + } +}; + +/** Internal function. Hides all combo boxes that might be displayed. */ +Calendar.prototype._hideCombos = function () { + this.monthsCombo.style.display = "none"; + this.yearsCombo.style.display = "none"; +}; + +/** Internal function. Starts dragging the element. */ +Calendar.prototype._dragStart = function (ev) { + if (this.dragging) { + return; + } + this.dragging = true; + var posX; + var posY; + if (Calendar.is_ie) { + posY = window.event.clientY + document.body.scrollTop; + posX = window.event.clientX + document.body.scrollLeft; + } else { + posY = ev.clientY + window.scrollY; + posX = ev.clientX + window.scrollX; + } + var st = this.element.style; + this.xOffs = posX - parseInt(st.left); + this.yOffs = posY - parseInt(st.top); + with (Calendar) { + addEvent(document, "mousemove", calDragIt); + addEvent(document, "mouseup", calDragEnd); + } +}; + +// BEGIN: DATE OBJECT PATCHES + +/** Adds the number of days array to the Date object. */ +Date._MD = new Array(31,28,31,30,31,30,31,31,30,31,30,31); + +/** Constants used for time computations */ +Date.SECOND = 1000 /* milliseconds */; +Date.MINUTE = 60 * Date.SECOND; +Date.HOUR = 60 * Date.MINUTE; +Date.DAY = 24 * Date.HOUR; +Date.WEEK = 7 * Date.DAY; + +Date.parseDate = function(str, fmt) { + var today = new Date(); + var y = 0; + var m = -1; + var d = 0; + var a = str.split(/\W+/); + var b = fmt.match(/%./g); + var i = 0, j = 0; + var hr = 0; + var min = 0; + for (i = 0; i < a.length; ++i) { + if (!a[i]) + continue; + switch (b[i]) { + case "%d": + case "%e": + d = parseInt(a[i], 10); + break; + + case "%m": + m = parseInt(a[i], 10) - 1; + break; + + case "%Y": + case "%y": + y = parseInt(a[i], 10); + (y < 100) && (y += (y > 29) ? 1900 : 2000); + break; + + case "%b": + case "%B": + for (j = 0; j < 12; ++j) { + if (Calendar._MN[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) { m = j; break; } + } + break; + + case "%H": + case "%I": + case "%k": + case "%l": + hr = parseInt(a[i], 10); + break; + + case "%P": + case "%p": + if (/pm/i.test(a[i]) && hr < 12) + hr += 12; + else if (/am/i.test(a[i]) && hr >= 12) + hr -= 12; + break; + + case "%M": + min = parseInt(a[i], 10); + break; + } + } + if (isNaN(y)) y = today.getFullYear(); + if (isNaN(m)) m = today.getMonth(); + if (isNaN(d)) d = today.getDate(); + if (isNaN(hr)) hr = today.getHours(); + if (isNaN(min)) min = today.getMinutes(); + if (y != 0 && m != -1 && d != 0) + return new Date(y, m, d, hr, min, 0); + y = 0; m = -1; d = 0; + for (i = 0; i < a.length; ++i) { + if (a[i].search(/[a-zA-Z]+/) != -1) { + var t = -1; + for (j = 0; j < 12; ++j) { + if (Calendar._MN[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) { t = j; break; } + } + if (t != -1) { + if (m != -1) { + d = m+1; + } + m = t; + } + } else if (parseInt(a[i], 10) <= 12 && m == -1) { + m = a[i]-1; + } else if (parseInt(a[i], 10) > 31 && y == 0) { + y = parseInt(a[i], 10); + (y < 100) && (y += (y > 29) ? 1900 : 2000); + } else if (d == 0) { + d = a[i]; + } + } + if (y == 0) + y = today.getFullYear(); + if (m != -1 && d != 0) + return new Date(y, m, d, hr, min, 0); + return today; +}; + +/** Returns the number of days in the current month */ +Date.prototype.getMonthDays = function(month) { + var year = this.getFullYear(); + if (typeof month == "undefined") { + month = this.getMonth(); + } + if (((0 == (year%4)) && ( (0 != (year%100)) || (0 == (year%400)))) && month == 1) { + return 29; + } else { + return Date._MD[month]; + } +}; + +/** Returns the number of day in the year. */ +Date.prototype.getDayOfYear = function() { + var now = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0); + var then = new Date(this.getFullYear(), 0, 0, 0, 0, 0); + var time = now - then; + return Math.floor(time / Date.DAY); +}; + +/** Returns the number of the week in year, as defined in ISO 8601. */ +Date.prototype.getWeekNumber = function() { + var d = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0); + var DoW = d.getDay(); + d.setDate(d.getDate() - (DoW + 6) % 7 + 3); // Nearest Thu + var ms = d.valueOf(); // GMT + d.setMonth(0); + d.setDate(4); // Thu in Week 1 + return Math.round((ms - d.valueOf()) / (7 * 864e5)) + 1; +}; + +/** Checks date and time equality */ +Date.prototype.equalsTo = function(date) { + return ((this.getFullYear() == date.getFullYear()) && + (this.getMonth() == date.getMonth()) && + (this.getDate() == date.getDate()) && + (this.getHours() == date.getHours()) && + (this.getMinutes() == date.getMinutes())); +}; + +/** Set only the year, month, date parts (keep existing time) */ +Date.prototype.setDateOnly = function(date) { + var tmp = new Date(date); + this.setDate(1); + this.setFullYear(tmp.getFullYear()); + this.setMonth(tmp.getMonth()); + this.setDate(tmp.getDate()); +}; + +/** Prints the date in a string according to the given format. */ +Date.prototype.print = function (str) { + var m = this.getMonth(); + var d = this.getDate(); + var y = this.getFullYear(); + var wn = this.getWeekNumber(); + var w = this.getDay(); + var s = {}; + var hr = this.getHours(); + var pm = (hr >= 12); + var ir = (pm) ? (hr - 12) : hr; + var dy = this.getDayOfYear(); + if (ir == 0) + ir = 12; + var min = this.getMinutes(); + var sec = this.getSeconds(); + s["%a"] = Calendar._SDN[w]; // abbreviated weekday name [FIXME: I18N] + s["%A"] = Calendar._DN[w]; // full weekday name + s["%b"] = Calendar._SMN[m]; // abbreviated month name [FIXME: I18N] + s["%B"] = Calendar._MN[m]; // full month name + // FIXME: %c : preferred date and time representation for the current locale + s["%C"] = 1 + Math.floor(y / 100); // the century number + s["%d"] = (d < 10) ? ("0" + d) : d; // the day of the month (range 01 to 31) + s["%e"] = d; // the day of the month (range 1 to 31) + // FIXME: %D : american date style: %m/%d/%y + // FIXME: %E, %F, %G, %g, %h (man strftime) + s["%H"] = (hr < 10) ? ("0" + hr) : hr; // hour, range 00 to 23 (24h format) + s["%I"] = (ir < 10) ? ("0" + ir) : ir; // hour, range 01 to 12 (12h format) + s["%j"] = (dy < 100) ? ((dy < 10) ? ("00" + dy) : ("0" + dy)) : dy; // day of the year (range 001 to 366) + s["%k"] = hr; // hour, range 0 to 23 (24h format) + s["%l"] = ir; // hour, range 1 to 12 (12h format) + s["%m"] = (m < 9) ? ("0" + (1+m)) : (1+m); // month, range 01 to 12 + s["%M"] = (min < 10) ? ("0" + min) : min; // minute, range 00 to 59 + s["%n"] = "\n"; // a newline character + s["%p"] = pm ? "PM" : "AM"; + s["%P"] = pm ? "pm" : "am"; + // FIXME: %r : the time in am/pm notation %I:%M:%S %p + // FIXME: %R : the time in 24-hour notation %H:%M + s["%s"] = Math.floor(this.getTime() / 1000); + s["%S"] = (sec < 10) ? ("0" + sec) : sec; // seconds, range 00 to 59 + s["%t"] = "\t"; // a tab character + // FIXME: %T : the time in 24-hour notation (%H:%M:%S) + s["%U"] = s["%W"] = s["%V"] = (wn < 10) ? ("0" + wn) : wn; + s["%u"] = w + 1; // the day of the week (range 1 to 7, 1 = MON) + s["%w"] = w; // the day of the week (range 0 to 6, 0 = SUN) + // FIXME: %x : preferred date representation for the current locale without the time + // FIXME: %X : preferred time representation for the current locale without the date + s["%y"] = ('' + y).substr(2, 2); // year without the century (range 00 to 99) + s["%Y"] = y; // year with the century + s["%%"] = "%"; // a literal '%' character + + var re = /%./g; + if (!Calendar.is_ie5 && !Calendar.is_khtml) + return str.replace(re, function (par) { return s[par] || par; }); + + var a = str.match(re); + for (var i = 0; i < a.length; i++) { + var tmp = s[a[i]]; + if (tmp) { + re = new RegExp(a[i], 'g'); + str = str.replace(re, tmp); + } + } + + return str; +}; + +Date.prototype.__msh_oldSetFullYear = Date.prototype.setFullYear; +Date.prototype.setFullYear = function(y) { + var d = new Date(this); + d.__msh_oldSetFullYear(y); + if (d.getMonth() != this.getMonth()) + this.setDate(28); + this.__msh_oldSetFullYear(y); +}; + +// END: DATE OBJECT PATCHES + + +// global object that remembers the calendar +window._dynarch_popupCalendar = null; diff --git a/htdocs/js/jscalendar/lang/calendar-af.js b/htdocs/js/jscalendar/lang/calendar-af.js new file mode 100644 index 0000000..aeda581 --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-af.js @@ -0,0 +1,39 @@ +// ** I18N Afrikaans +Calendar._DN = new Array +("Sondag", + "Maandag", + "Dinsdag", + "Woensdag", + "Donderdag", + "Vrydag", + "Saterdag", + "Sondag"); +Calendar._MN = new Array +("Januarie", + "Februarie", + "Maart", + "April", + "Mei", + "Junie", + "Julie", + "Augustus", + "September", + "Oktober", + "November", + "Desember"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["TOGGLE"] = "Verander eerste dag van die week"; +Calendar._TT["PREV_YEAR"] = "Vorige jaar (hou vir keuselys)"; +Calendar._TT["PREV_MONTH"] = "Vorige maand (hou vir keuselys)"; +Calendar._TT["GO_TODAY"] = "Gaan na vandag"; +Calendar._TT["NEXT_MONTH"] = "Volgende maand (hou vir keuselys)"; +Calendar._TT["NEXT_YEAR"] = "Volgende jaar (hou vir keuselys)"; +Calendar._TT["SEL_DATE"] = "Kies datum"; +Calendar._TT["DRAG_TO_MOVE"] = "Sleep om te skuif"; +Calendar._TT["PART_TODAY"] = " (vandag)"; +Calendar._TT["MON_FIRST"] = "Vertoon Maandag eerste"; +Calendar._TT["SUN_FIRST"] = "Display Sunday first"; +Calendar._TT["CLOSE"] = "Close"; +Calendar._TT["TODAY"] = "Today"; diff --git a/htdocs/js/jscalendar/lang/calendar-al.js b/htdocs/js/jscalendar/lang/calendar-al.js new file mode 100644 index 0000000..4f701cf --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-al.js @@ -0,0 +1,101 @@ +// Calendar ALBANIAN language +//author Rigels Gordani rige@hotmail.com + +// ditet +Calendar._DN = new Array +("E Diele", +"E Hene", +"E Marte", +"E Merkure", +"E Enjte", +"E Premte", +"E Shtune", +"E Diele"); + +//ditet shkurt +Calendar._SDN = new Array +("Die", +"Hen", +"Mar", +"Mer", +"Enj", +"Pre", +"Sht", +"Die"); + +// muajt +Calendar._MN = new Array +("Janar", +"Shkurt", +"Mars", +"Prill", +"Maj", +"Qeshor", +"Korrik", +"Gusht", +"Shtator", +"Tetor", +"Nentor", +"Dhjetor"); + +// muajte shkurt +Calendar._SMN = new Array +("Jan", +"Shk", +"Mar", +"Pri", +"Maj", +"Qes", +"Kor", +"Gus", +"Sht", +"Tet", +"Nen", +"Dhj"); + +// ndihmesa +Calendar._TT = {}; +Calendar._TT["INFO"] = "Per kalendarin"; + +Calendar._TT["ABOUT"] = +"Zgjedhes i ores/dates ne DHTML \n" + +"\n\n" +"Zgjedhja e Dates:\n" + +"- Perdor butonat \xab, \xbb per te zgjedhur vitin\n" + +"- Perdor butonat" + String.fromCharCode(0x2039) + ", " + +String.fromCharCode(0x203a) + +" per te zgjedhur muajin\n" + +"- Mbani shtypur butonin e mousit per nje zgjedje me te shpejte."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Zgjedhja e kohes:\n" + +"- Kliko tek ndonje nga pjeset e ores per ta rritur ate\n" + +"- ose kliko me Shift per ta zvogeluar ate\n" + +"- ose cliko dhe terhiq per zgjedhje me te shpejte."; + +Calendar._TT["PREV_YEAR"] = "Viti i shkuar (prit per menune)"; +Calendar._TT["PREV_MONTH"] = "Muaji i shkuar (prit per menune)"; +Calendar._TT["GO_TODAY"] = "Sot"; +Calendar._TT["NEXT_MONTH"] = "Muaji i ardhshem (prit per menune)"; +Calendar._TT["NEXT_YEAR"] = "Viti i ardhshem (prit per menune)"; +Calendar._TT["SEL_DATE"] = "Zgjidh daten"; +Calendar._TT["DRAG_TO_MOVE"] = "Terhiqe per te levizur"; +Calendar._TT["PART_TODAY"] = " (sot)"; + +// "%s" eshte dita e pare e javes +// %s do te zevendesohet me emrin e dite +Calendar._TT["DAY_FIRST"] = "Trego te %s te paren"; + + +Calendar._TT["WEEKEND"] = "0,6"; + +Calendar._TT["CLOSE"] = "Mbyll"; +Calendar._TT["TODAY"] = "Sot"; +Calendar._TT["TIME_PART"] = "Kliko me (Shift-)ose terhiqe per te ndryshuar +vleren"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d"; +Calendar._TT["TT_DATE_FORMAT"] = "%a, %b %e"; + +Calendar._TT["WK"] = "Java"; +Calendar._TT["TIME"] = "Koha:"; + diff --git a/htdocs/js/jscalendar/lang/calendar-bg.js b/htdocs/js/jscalendar/lang/calendar-bg.js new file mode 100644 index 0000000..5eb73ec --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-bg.js @@ -0,0 +1,124 @@ +// ** I18N + +// Calendar BG language +// Author: Mihai Bazon, +// Translator: Valentin Sheiretsky, +// Encoding: Windows-1251 +// Distributed under the same terms as the calendar itself. + +// For translators: please use UTF-8 if possible. We strongly believe that +// Unicode is the answer to a real internationalized world. Also please +// include your contact information in the header, as can be seen above. + +// full day names +Calendar._DN = new Array +("Íåäåëÿ", + "Ïîíåäåëíèê", + "Âòîðíèê", + "Ñðÿäà", + "×åòâúðòúê", + "Ïåòúê", + "Ñúáîòà", + "Íåäåëÿ"); + +// Please note that the following array of short day names (and the same goes +// for short month names, _SMN) isn't absolutely necessary. We give it here +// for exemplification on how one can customize the short day names, but if +// they are simply the first N letters of the full name you can simply say: +// +// Calendar._SDN_len = N; // short day name length +// Calendar._SMN_len = N; // short month name length +// +// If N = 3 then this is not needed either since we assume a value of 3 if not +// present, to be compatible with translation files that were written before +// this feature. + +// short day names +Calendar._SDN = new Array +("Íåä", + "Ïîí", + "Âòî", + "Ñðÿ", + "×åò", + "Ïåò", + "Ñúá", + "Íåä"); + +// full month names +Calendar._MN = new Array +("ßíóàðè", + "Ôåâðóàðè", + "Ìàðò", + "Àïðèë", + "Ìàé", + "Þíè", + "Þëè", + "Àâãóñò", + "Ñåïòåìâðè", + "Îêòîìâðè", + "Íîåìâðè", + "Äåêåìâðè"); + +// short month names +Calendar._SMN = new Array +("ßíó", + "Ôåâ", + "Ìàð", + "Àïð", + "Ìàé", + "Þíè", + "Þëè", + "Àâã", + "Ñåï", + "Îêò", + "Íîå", + "Äåê"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "Èíôîðìàöèÿ çà êàëåíäàðà"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"For latest version visit: http://www.dynarch.com/projects/calendar/\n" + +"Distributed under GNU LGPL. See http://gnu.org/licenses/lgpl.html for details." + +"\n\n" + +"Date selection:\n" + +"- Use the \xab, \xbb buttons to select year\n" + +"- Use the " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " buttons to select month\n" + +"- Hold mouse button on any of the above buttons for faster selection."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Time selection:\n" + +"- Click on any of the time parts to increase it\n" + +"- or Shift-click to decrease it\n" + +"- or click and drag for faster selection."; + +Calendar._TT["PREV_YEAR"] = "Ïðåäíà ãîäèíà (çàäðúæòå çà ìåíþ)"; +Calendar._TT["PREV_MONTH"] = "Ïðåäåí ìåñåö (çàäðúæòå çà ìåíþ)"; +Calendar._TT["GO_TODAY"] = "Èçáåðåòå äíåñ"; +Calendar._TT["NEXT_MONTH"] = "Ñëåäâàù ìåñåö (çàäðúæòå çà ìåíþ)"; +Calendar._TT["NEXT_YEAR"] = "Ñëåäâàùà ãîäèíà (çàäðúæòå çà ìåíþ)"; +Calendar._TT["SEL_DATE"] = "Èçáåðåòå äàòà"; +Calendar._TT["DRAG_TO_MOVE"] = "Ïðåìåñòâàíå"; +Calendar._TT["PART_TODAY"] = " (äíåñ)"; + +// the following is to inform that "%s" is to be the first day of week +// %s will be replaced with the day name. +Calendar._TT["DAY_FIRST"] = "%s êàòî ïúðâè äåí"; + +// This may be locale-dependent. It specifies the week-end days, as an array +// of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1 +// means Monday, etc. +Calendar._TT["WEEKEND"] = "0,6"; + +Calendar._TT["CLOSE"] = "Çàòâîðåòå"; +Calendar._TT["TODAY"] = "Äíåñ"; +Calendar._TT["TIME_PART"] = "(Shift-)Click èëè drag çà äà ïðîìåíèòå ñòîéíîñòòà"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d"; +Calendar._TT["TT_DATE_FORMAT"] = "%A - %e %B %Y"; + +Calendar._TT["WK"] = "Ñåäì"; +Calendar._TT["TIME"] = "×àñ:"; diff --git a/htdocs/js/jscalendar/lang/calendar-big5-utf8.js b/htdocs/js/jscalendar/lang/calendar-big5-utf8.js new file mode 100644 index 0000000..14e0d5d --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-big5-utf8.js @@ -0,0 +1,123 @@ +// ** I18N + +// Calendar big5-utf8 language +// Author: Gary Fu, +// Encoding: utf8 +// Distributed under the same terms as the calendar itself. + +// For translators: please use UTF-8 if possible. We strongly believe that +// Unicode is the answer to a real internationalized world. Also please +// include your contact information in the header, as can be seen above. + +// full day names +Calendar._DN = new Array +("星期日", + "星期一", + "星期二", + "星期三", + "星期四", + "星期五", + "星期六", + "星期日"); + +// Please note that the following array of short day names (and the same goes +// for short month names, _SMN) isn't absolutely necessary. We give it here +// for exemplification on how one can customize the short day names, but if +// they are simply the first N letters of the full name you can simply say: +// +// Calendar._SDN_len = N; // short day name length +// Calendar._SMN_len = N; // short month name length +// +// If N = 3 then this is not needed either since we assume a value of 3 if not +// present, to be compatible with translation files that were written before +// this feature. + +// short day names +Calendar._SDN = new Array +("æ—¥", + "一", + "二", + "三", + "å››", + "五", + "å…­", + "æ—¥"); + +// full month names +Calendar._MN = new Array +("一月", + "二月", + "三月", + "四月", + "五月", + "六月", + "七月", + "八月", + "ä¹æœˆ", + "å月", + "å一月", + "å二月"); + +// short month names +Calendar._SMN = new Array +("一月", + "二月", + "三月", + "四月", + "五月", + "六月", + "七月", + "八月", + "ä¹æœˆ", + "å月", + "å一月", + "å二月"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "關於"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"For latest version visit: http://www.dynarch.com/projects/calendar/\n" + +"Distributed under GNU LGPL. See http://gnu.org/licenses/lgpl.html for details." + +"\n\n" + +"日期é¸æ“‡æ–¹æ³•:\n" + +"- 使用 \xab, \xbb 按鈕å¯é¸æ“‡å¹´ä»½\n" + +"- 使用 " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " 按鈕å¯é¸æ“‡æœˆä»½\n" + +"- 按ä½ä¸Šé¢çš„按鈕å¯ä»¥åŠ å¿«é¸å–"; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"時間é¸æ“‡æ–¹æ³•:\n" + +"- 點擊任何的時間部份å¯å¢žåŠ å…¶å€¼\n" + +"- åŒæ™‚按Shiftéµå†é»žæ“Šå¯æ¸›å°‘其值\n" + +"- 點擊並拖曳å¯åŠ å¿«æ”¹è®Šçš„值"; + +Calendar._TT["PREV_YEAR"] = "上一年 (按ä½é¸å–®)"; +Calendar._TT["PREV_MONTH"] = "下一年 (按ä½é¸å–®)"; +Calendar._TT["GO_TODAY"] = "到今日"; +Calendar._TT["NEXT_MONTH"] = "上一月 (按ä½é¸å–®)"; +Calendar._TT["NEXT_YEAR"] = "下一月 (按ä½é¸å–®)"; +Calendar._TT["SEL_DATE"] = "é¸æ“‡æ—¥æœŸ"; +Calendar._TT["DRAG_TO_MOVE"] = "拖曳"; +Calendar._TT["PART_TODAY"] = " (今日)"; + +// the following is to inform that "%s" is to be the first day of week +// %s will be replaced with the day name. +Calendar._TT["DAY_FIRST"] = "å°‡ %s 顯示在å‰"; + +// This may be locale-dependent. It specifies the week-end days, as an array +// of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1 +// means Monday, etc. +Calendar._TT["WEEKEND"] = "0,6"; + +Calendar._TT["CLOSE"] = "關閉"; +Calendar._TT["TODAY"] = "今日"; +Calendar._TT["TIME_PART"] = "點擊or拖曳å¯æ”¹è®Šæ™‚é–“(åŒæ™‚按Shift為減)"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d"; +Calendar._TT["TT_DATE_FORMAT"] = "%a, %b %e"; + +Calendar._TT["WK"] = "週"; +Calendar._TT["TIME"] = "Time:"; diff --git a/htdocs/js/jscalendar/lang/calendar-big5.js b/htdocs/js/jscalendar/lang/calendar-big5.js new file mode 100644 index 0000000..a589358 --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-big5.js @@ -0,0 +1,123 @@ +// ** I18N + +// Calendar big5 language +// Author: Gary Fu, +// Encoding: big5 +// Distributed under the same terms as the calendar itself. + +// For translators: please use UTF-8 if possible. We strongly believe that +// Unicode is the answer to a real internationalized world. Also please +// include your contact information in the header, as can be seen above. + +// full day names +Calendar._DN = new Array +("¬P´Á¤é", + "¬P´Á¤@", + "¬P´Á¤G", + "¬P´Á¤T", + "¬P´Á¥|", + "¬P´Á¤­", + "¬P´Á¤»", + "¬P´Á¤é"); + +// Please note that the following array of short day names (and the same goes +// for short month names, _SMN) isn't absolutely necessary. We give it here +// for exemplification on how one can customize the short day names, but if +// they are simply the first N letters of the full name you can simply say: +// +// Calendar._SDN_len = N; // short day name length +// Calendar._SMN_len = N; // short month name length +// +// If N = 3 then this is not needed either since we assume a value of 3 if not +// present, to be compatible with translation files that were written before +// this feature. + +// short day names +Calendar._SDN = new Array +("¤é", + "¤@", + "¤G", + "¤T", + "¥|", + "¤­", + "¤»", + "¤é"); + +// full month names +Calendar._MN = new Array +("¤@¤ë", + "¤G¤ë", + "¤T¤ë", + "¥|¤ë", + "¤­¤ë", + "¤»¤ë", + "¤C¤ë", + "¤K¤ë", + "¤E¤ë", + "¤Q¤ë", + "¤Q¤@¤ë", + "¤Q¤G¤ë"); + +// short month names +Calendar._SMN = new Array +("¤@¤ë", + "¤G¤ë", + "¤T¤ë", + "¥|¤ë", + "¤­¤ë", + "¤»¤ë", + "¤C¤ë", + "¤K¤ë", + "¤E¤ë", + "¤Q¤ë", + "¤Q¤@¤ë", + "¤Q¤G¤ë"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "Ãö©ó"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"For latest version visit: http://www.dynarch.com/projects/calendar/\n" + +"Distributed under GNU LGPL. See http://gnu.org/licenses/lgpl.html for details." + +"\n\n" + +"¤é´Á¿ï¾Ü¤èªk:\n" + +"- ¨Ï¥Î \xab, \xbb «ö¶s¥i¿ï¾Ü¦~¥÷\n" + +"- ¨Ï¥Î " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " «ö¶s¥i¿ï¾Ü¤ë¥÷\n" + +"- «ö¦í¤W­±ªº«ö¶s¥i¥H¥[§Ö¿ï¨ú"; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"®É¶¡¿ï¾Ü¤èªk:\n" + +"- ÂIÀ»¥ô¦óªº®É¶¡³¡¥÷¥i¼W¥[¨ä­È\n" + +"- ¦P®É«öShiftÁä¦AÂIÀ»¥i´î¤Ö¨ä­È\n" + +"- ÂIÀ»¨Ã©ì¦²¥i¥[§Ö§ïÅܪº­È"; + +Calendar._TT["PREV_YEAR"] = "¤W¤@¦~ («ö¦í¿ï³æ)"; +Calendar._TT["PREV_MONTH"] = "¤U¤@¦~ («ö¦í¿ï³æ)"; +Calendar._TT["GO_TODAY"] = "¨ì¤µ¤é"; +Calendar._TT["NEXT_MONTH"] = "¤W¤@¤ë («ö¦í¿ï³æ)"; +Calendar._TT["NEXT_YEAR"] = "¤U¤@¤ë («ö¦í¿ï³æ)"; +Calendar._TT["SEL_DATE"] = "¿ï¾Ü¤é´Á"; +Calendar._TT["DRAG_TO_MOVE"] = "©ì¦²"; +Calendar._TT["PART_TODAY"] = " (¤µ¤é)"; + +// the following is to inform that "%s" is to be the first day of week +// %s will be replaced with the day name. +Calendar._TT["DAY_FIRST"] = "±N %s Åã¥Ü¦b«e"; + +// This may be locale-dependent. It specifies the week-end days, as an array +// of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1 +// means Monday, etc. +Calendar._TT["WEEKEND"] = "0,6"; + +Calendar._TT["CLOSE"] = "Ãö³¬"; +Calendar._TT["TODAY"] = "¤µ¤é"; +Calendar._TT["TIME_PART"] = "ÂIÀ»or©ì¦²¥i§ïÅܮɶ¡(¦P®É«öShift¬°´î)"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d"; +Calendar._TT["TT_DATE_FORMAT"] = "%a, %b %e"; + +Calendar._TT["WK"] = "¶g"; +Calendar._TT["TIME"] = "Time:"; diff --git a/htdocs/js/jscalendar/lang/calendar-br.js b/htdocs/js/jscalendar/lang/calendar-br.js new file mode 100644 index 0000000..bfb0747 --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-br.js @@ -0,0 +1,108 @@ +// ** I18N + +// Calendar pt-BR language +// Author: Fernando Dourado, +// Encoding: any +// Distributed under the same terms as the calendar itself. + +// For translators: please use UTF-8 if possible. We strongly believe that +// Unicode is the answer to a real internationalized world. Also please +// include your contact information in the header, as can be seen above. + +// full day names +Calendar._DN = new Array +("Domingo", + "Segunda", + "Terça", + "Quarta", + "Quinta", + "Sexta", + "Sabádo", + "Domingo"); + +// Please note that the following array of short day names (and the same goes +// for short month names, _SMN) isn't absolutely necessary. We give it here +// for exemplification on how one can customize the short day names, but if +// they are simply the first N letters of the full name you can simply say: +// +// Calendar._SDN_len = N; // short day name length +// Calendar._SMN_len = N; // short month name length +// +// If N = 3 then this is not needed either since we assume a value of 3 if not +// present, to be compatible with translation files that were written before +// this feature. + +// short day names +// [No changes using default values] + +// full month names +Calendar._MN = new Array +("Janeiro", + "Fevereiro", + "Março", + "Abril", + "Maio", + "Junho", + "Julho", + "Agosto", + "Setembro", + "Outubro", + "Novembro", + "Dezembro"); + +// short month names +// [No changes using default values] + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "Sobre o calendário"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"For latest version visit: http://www.dynarch.com/projects/calendar/\n" + +"Distributed under GNU LGPL. See http://gnu.org/licenses/lgpl.html for details." + +"\n\n" + +"Translate to portuguese Brazil (pt-BR) by Fernando Dourado (fernando.dourado@ig.com.br)\n" + +"Tradução para o português Brasil (pt-BR) por Fernando Dourado (fernando.dourado@ig.com.br)" + +"\n\n" + +"Selecionar data:\n" + +"- Use as teclas \xab, \xbb para selecionar o ano\n" + +"- Use as teclas " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " para selecionar o mês\n" + +"- Clique e segure com o mouse em qualquer botão para selecionar rapidamente."; + +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Selecionar hora:\n" + +"- Clique em qualquer uma das partes da hora para aumentar\n" + +"- ou Shift-clique para diminuir\n" + +"- ou clique e arraste para selecionar rapidamente."; + +Calendar._TT["PREV_YEAR"] = "Ano anterior (clique e segure para menu)"; +Calendar._TT["PREV_MONTH"] = "Mês anterior (clique e segure para menu)"; +Calendar._TT["GO_TODAY"] = "Ir para a data atual"; +Calendar._TT["NEXT_MONTH"] = "Próximo mês (clique e segure para menu)"; +Calendar._TT["NEXT_YEAR"] = "Próximo ano (clique e segure para menu)"; +Calendar._TT["SEL_DATE"] = "Selecione uma data"; +Calendar._TT["DRAG_TO_MOVE"] = "Clique e segure para mover"; +Calendar._TT["PART_TODAY"] = " (hoje)"; + +// the following is to inform that "%s" is to be the first day of week +// %s will be replaced with the day name. +Calendar._TT["DAY_FIRST"] = "Exibir %s primeiro"; + +// This may be locale-dependent. It specifies the week-end days, as an array +// of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1 +// means Monday, etc. +Calendar._TT["WEEKEND"] = "0,6"; + +Calendar._TT["CLOSE"] = "Fechar"; +Calendar._TT["TODAY"] = "Hoje"; +Calendar._TT["TIME_PART"] = "(Shift-)Clique ou arraste para mudar o valor"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%d/%m/%Y"; +Calendar._TT["TT_DATE_FORMAT"] = "%d de %B de %Y"; + +Calendar._TT["WK"] = "sem"; +Calendar._TT["TIME"] = "Hora:"; + diff --git a/htdocs/js/jscalendar/lang/calendar-ca.js b/htdocs/js/jscalendar/lang/calendar-ca.js new file mode 100644 index 0000000..a2121bc --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-ca.js @@ -0,0 +1,123 @@ +// ** I18N + +// Calendar CA language +// Author: Mihai Bazon, +// Encoding: any +// Distributed under the same terms as the calendar itself. + +// For translators: please use UTF-8 if possible. We strongly believe that +// Unicode is the answer to a real internationalized world. Also please +// include your contact information in the header, as can be seen above. + +// full day names +Calendar._DN = new Array +("Diumenge", + "Dilluns", + "Dimarts", + "Dimecres", + "Dijous", + "Divendres", + "Dissabte", + "Diumenge"); + +// Please note that the following array of short day names (and the same goes +// for short month names, _SMN) isn't absolutely necessary. We give it here +// for exemplification on how one can customize the short day names, but if +// they are simply the first N letters of the full name you can simply say: +// +// Calendar._SDN_len = N; // short day name length +// Calendar._SMN_len = N; // short month name length +// +// If N = 3 then this is not needed either since we assume a value of 3 if not +// present, to be compatible with translation files that were written before +// this feature. + +// short day names +Calendar._SDN = new Array +("Diu", + "Dil", + "Dmt", + "Dmc", + "Dij", + "Div", + "Dis", + "Diu"); + +// full month names +Calendar._MN = new Array +("Gener", + "Febrer", + "Març", + "Abril", + "Maig", + "Juny", + "Juliol", + "Agost", + "Setembre", + "Octubre", + "Novembre", + "Desembre"); + +// short month names +Calendar._SMN = new Array +("Gen", + "Feb", + "Mar", + "Abr", + "Mai", + "Jun", + "Jul", + "Ago", + "Set", + "Oct", + "Nov", + "Des"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "Sobre el calendari"; + +Calendar._TT["ABOUT"] = +"DHTML Selector de Data/Hora\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"For latest version visit: http://www.dynarch.com/projects/calendar/\n" + +"Distributed under GNU LGPL. See http://gnu.org/licenses/lgpl.html for details." + +"\n\n" + +"Sel.lecció de Dates:\n" + +"- Fes servir els botons \xab, \xbb per sel.leccionar l'any\n" + +"- Fes servir els botons " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " per se.lecciconar el mes\n" + +"- Manté el ratolí apretat en qualsevol dels anteriors per sel.lecció ràpida."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Time selection:\n" + +"- claca en qualsevol de les parts de la hora per augmentar-les\n" + +"- o Shift-click per decrementar-la\n" + +"- or click and arrastra per sel.lecció ràpida."; + +Calendar._TT["PREV_YEAR"] = "Any anterior (Mantenir per menu)"; +Calendar._TT["PREV_MONTH"] = "Mes anterior (Mantenir per menu)"; +Calendar._TT["GO_TODAY"] = "Anar a avui"; +Calendar._TT["NEXT_MONTH"] = "Mes següent (Mantenir per menu)"; +Calendar._TT["NEXT_YEAR"] = "Any següent (Mantenir per menu)"; +Calendar._TT["SEL_DATE"] = "Sel.leccionar data"; +Calendar._TT["DRAG_TO_MOVE"] = "Arrastrar per moure"; +Calendar._TT["PART_TODAY"] = " (avui)"; + +// the following is to inform that "%s" is to be the first day of week +// %s will be replaced with the day name. +Calendar._TT["DAY_FIRST"] = "Mostra %s primer"; + +// This may be locale-dependent. It specifies the week-end days, as an array +// of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1 +// means Monday, etc. +Calendar._TT["WEEKEND"] = "0,6"; + +Calendar._TT["CLOSE"] = "Tanca"; +Calendar._TT["TODAY"] = "Avui"; +Calendar._TT["TIME_PART"] = "(Shift-)Click a arrastra per canviar el valor"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d"; +Calendar._TT["TT_DATE_FORMAT"] = "%a, %b %e"; + +Calendar._TT["WK"] = "st"; +Calendar._TT["TIME"] = "Hora:"; diff --git a/htdocs/js/jscalendar/lang/calendar-cs-utf8.js b/htdocs/js/jscalendar/lang/calendar-cs-utf8.js new file mode 100644 index 0000000..f6bbbeb --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-cs-utf8.js @@ -0,0 +1,65 @@ +/* + calendar-cs-win.js + language: Czech + encoding: windows-1250 + author: Lubos Jerabek (xnet@seznam.cz) + Jan Uhlir (espinosa@centrum.cz) +*/ + +// ** I18N +Calendar._DN = new Array('NedÄ›le','PondÄ›lí','Úterý','StÅ™eda','ÄŒtvrtek','Pátek','Sobota','NedÄ›le'); +Calendar._SDN = new Array('Ne','Po','Út','St','ÄŒt','Pá','So','Ne'); +Calendar._MN = new Array('Leden','Únor','BÅ™ezen','Duben','KvÄ›ten','ÄŒerven','ÄŒervenec','Srpen','Září','Říjen','Listopad','Prosinec'); +Calendar._SMN = new Array('Led','Úno','BÅ™e','Dub','KvÄ›','ÄŒrv','ÄŒvc','Srp','Zář','Říj','Lis','Pro'); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "O komponentÄ› kalendář"; +Calendar._TT["TOGGLE"] = "ZmÄ›na prvního dne v týdnu"; +Calendar._TT["PREV_YEAR"] = "PÅ™edchozí rok (pÅ™idrž pro menu)"; +Calendar._TT["PREV_MONTH"] = "PÅ™edchozí mÄ›síc (pÅ™idrž pro menu)"; +Calendar._TT["GO_TODAY"] = "DneÅ¡ní datum"; +Calendar._TT["NEXT_MONTH"] = "Další mÄ›síc (pÅ™idrž pro menu)"; +Calendar._TT["NEXT_YEAR"] = "Další rok (pÅ™idrž pro menu)"; +Calendar._TT["SEL_DATE"] = "Vyber datum"; +Calendar._TT["DRAG_TO_MOVE"] = "ChyÅ¥ a táhni, pro pÅ™esun"; +Calendar._TT["PART_TODAY"] = " (dnes)"; +Calendar._TT["MON_FIRST"] = "Ukaž jako první PondÄ›lí"; +//Calendar._TT["SUN_FIRST"] = "Ukaž jako první NedÄ›li"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"For latest version visit: http://www.dynarch.com/projects/calendar/\n" + +"Distributed under GNU LGPL. See http://gnu.org/licenses/lgpl.html for details." + +"\n\n" + +"VýbÄ›r datumu:\n" + +"- Use the \xab, \xbb buttons to select year\n" + +"- Použijte tlaÄítka " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " k výbÄ›ru mÄ›síce\n" + +"- Podržte tlaÄítko myÅ¡i na jakémkoliv z tÄ›ch tlaÄítek pro rychlejší výbÄ›r."; + +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"VýbÄ›r Äasu:\n" + +"- KliknÄ›te na jakoukoliv z Äástí výbÄ›ru Äasu pro zvýšení.\n" + +"- nebo Shift-click pro snížení\n" + +"- nebo kliknÄ›te a táhnÄ›te pro rychlejší výbÄ›r."; + +// the following is to inform that "%s" is to be the first day of week +// %s will be replaced with the day name. +Calendar._TT["DAY_FIRST"] = "Zobraz %s první"; + +// This may be locale-dependent. It specifies the week-end days, as an array +// of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1 +// means Monday, etc. +Calendar._TT["WEEKEND"] = "0,6"; + +Calendar._TT["CLOSE"] = "Zavřít"; +Calendar._TT["TODAY"] = "Dnes"; +Calendar._TT["TIME_PART"] = "(Shift-)Klikni nebo táhni pro zmÄ›nu hodnoty"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "d.m.yy"; +Calendar._TT["TT_DATE_FORMAT"] = "%a, %b %e"; + +Calendar._TT["WK"] = "wk"; +Calendar._TT["TIME"] = "ÄŒas:"; diff --git a/htdocs/js/jscalendar/lang/calendar-cs-win.js b/htdocs/js/jscalendar/lang/calendar-cs-win.js new file mode 100644 index 0000000..140dff3 --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-cs-win.js @@ -0,0 +1,65 @@ +/* + calendar-cs-win.js + language: Czech + encoding: windows-1250 + author: Lubos Jerabek (xnet@seznam.cz) + Jan Uhlir (espinosa@centrum.cz) +*/ + +// ** I18N +Calendar._DN = new Array('Nedìle','Pondìlí','Úterý','Støeda','Ètvrtek','Pátek','Sobota','Nedìle'); +Calendar._SDN = new Array('Ne','Po','Út','St','Èt','Pá','So','Ne'); +Calendar._MN = new Array('Leden','Únor','Bøezen','Duben','Kvìten','Èerven','Èervenec','Srpen','Záøí','Øíjen','Listopad','Prosinec'); +Calendar._SMN = new Array('Led','Úno','Bøe','Dub','Kvì','Èrv','Èvc','Srp','Záø','Øíj','Lis','Pro'); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "O komponentì kalendáø"; +Calendar._TT["TOGGLE"] = "Zmìna prvního dne v týdnu"; +Calendar._TT["PREV_YEAR"] = "Pøedchozí rok (pøidrž pro menu)"; +Calendar._TT["PREV_MONTH"] = "Pøedchozí mìsíc (pøidrž pro menu)"; +Calendar._TT["GO_TODAY"] = "Dnešní datum"; +Calendar._TT["NEXT_MONTH"] = "Další mìsíc (pøidrž pro menu)"; +Calendar._TT["NEXT_YEAR"] = "Další rok (pøidrž pro menu)"; +Calendar._TT["SEL_DATE"] = "Vyber datum"; +Calendar._TT["DRAG_TO_MOVE"] = "Chy a táhni, pro pøesun"; +Calendar._TT["PART_TODAY"] = " (dnes)"; +Calendar._TT["MON_FIRST"] = "Ukaž jako první Pondìlí"; +//Calendar._TT["SUN_FIRST"] = "Ukaž jako první Nedìli"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"For latest version visit: http://www.dynarch.com/projects/calendar/\n" + +"Distributed under GNU LGPL. See http://gnu.org/licenses/lgpl.html for details." + +"\n\n" + +"Výbìr datumu:\n" + +"- Use the \xab, \xbb buttons to select year\n" + +"- Použijte tlaèítka " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " k výbìru mìsíce\n" + +"- Podržte tlaèítko myši na jakémkoliv z tìch tlaèítek pro rychlejší výbìr."; + +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Výbìr èasu:\n" + +"- Kliknìte na jakoukoliv z èástí výbìru èasu pro zvýšení.\n" + +"- nebo Shift-click pro snížení\n" + +"- nebo kliknìte a táhnìte pro rychlejší výbìr."; + +// the following is to inform that "%s" is to be the first day of week +// %s will be replaced with the day name. +Calendar._TT["DAY_FIRST"] = "Zobraz %s první"; + +// This may be locale-dependent. It specifies the week-end days, as an array +// of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1 +// means Monday, etc. +Calendar._TT["WEEKEND"] = "0,6"; + +Calendar._TT["CLOSE"] = "Zavøít"; +Calendar._TT["TODAY"] = "Dnes"; +Calendar._TT["TIME_PART"] = "(Shift-)Klikni nebo táhni pro zmìnu hodnoty"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "d.m.yy"; +Calendar._TT["TT_DATE_FORMAT"] = "%a, %b %e"; + +Calendar._TT["WK"] = "wk"; +Calendar._TT["TIME"] = "Èas:"; diff --git a/htdocs/js/jscalendar/lang/calendar-da.js b/htdocs/js/jscalendar/lang/calendar-da.js new file mode 100644 index 0000000..a99b598 --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-da.js @@ -0,0 +1,123 @@ +// ** I18N + +// Calendar DA language +// Author: Michael Thingmand Henriksen, +// Encoding: any +// Distributed under the same terms as the calendar itself. + +// For translators: please use UTF-8 if possible. We strongly believe that +// Unicode is the answer to a real internationalized world. Also please +// include your contact information in the header, as can be seen above. + +// full day names +Calendar._DN = new Array +("Søndag", +"Mandag", +"Tirsdag", +"Onsdag", +"Torsdag", +"Fredag", +"Lørdag", +"Søndag"); + +// Please note that the following array of short day names (and the same goes +// for short month names, _SMN) isn't absolutely necessary. We give it here +// for exemplification on how one can customize the short day names, but if +// they are simply the first N letters of the full name you can simply say: +// +// Calendar._SDN_len = N; // short day name length +// Calendar._SMN_len = N; // short month name length +// +// If N = 3 then this is not needed either since we assume a value of 3 if not +// present, to be compatible with translation files that were written before +// this feature. + +// short day names +Calendar._SDN = new Array +("Søn", +"Man", +"Tir", +"Ons", +"Tor", +"Fre", +"Lør", +"Søn"); + +// full month names +Calendar._MN = new Array +("Januar", +"Februar", +"Marts", +"April", +"Maj", +"Juni", +"Juli", +"August", +"September", +"Oktober", +"November", +"December"); + +// short month names +Calendar._SMN = new Array +("Jan", +"Feb", +"Mar", +"Apr", +"Maj", +"Jun", +"Jul", +"Aug", +"Sep", +"Okt", +"Nov", +"Dec"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "Om Kalenderen"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"For den seneste version besøg: http://www.dynarch.com/projects/calendar/\n"; + +"Distribueret under GNU LGPL. Se http://gnu.org/licenses/lgpl.html for detajler." + +"\n\n" + +"Valg af dato:\n" + +"- Brug \xab, \xbb knapperne for at vælge Ã¥r\n" + +"- Brug " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " knapperne for at vælge mÃ¥ned\n" + +"- Hold knappen pÃ¥ musen nede pÃ¥ knapperne ovenfor for hurtigere valg."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Valg af tid:\n" + +"- Klik pÃ¥ en vilkÃ¥rlig del for større værdi\n" + +"- eller Shift-klik for for mindre værdi\n" + +"- eller klik og træk for hurtigere valg."; + +Calendar._TT["PREV_YEAR"] = "Ét Ã¥r tilbage (hold for menu)"; +Calendar._TT["PREV_MONTH"] = "Én mÃ¥ned tilbage (hold for menu)"; +Calendar._TT["GO_TODAY"] = "GÃ¥ til i dag"; +Calendar._TT["NEXT_MONTH"] = "Én mÃ¥ned frem (hold for menu)"; +Calendar._TT["NEXT_YEAR"] = "Ét Ã¥r frem (hold for menu)"; +Calendar._TT["SEL_DATE"] = "Vælg dag"; +Calendar._TT["DRAG_TO_MOVE"] = "Træk vinduet"; +Calendar._TT["PART_TODAY"] = " (i dag)"; + +// the following is to inform that "%s" is to be the first day of week +// %s will be replaced with the day name. +Calendar._TT["DAY_FIRST"] = "Vis %s først"; + +// This may be locale-dependent. It specifies the week-end days, as an array +// of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1 +// means Monday, etc. +Calendar._TT["WEEKEND"] = "0,6"; + +Calendar._TT["CLOSE"] = "Luk"; +Calendar._TT["TODAY"] = "I dag"; +Calendar._TT["TIME_PART"] = "(Shift-)klik eller træk for at ændre værdi"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%d-%m-%Y"; +Calendar._TT["TT_DATE_FORMAT"] = "%a, %b %e"; + +Calendar._TT["WK"] = "Uge"; +Calendar._TT["TIME"] = "Tid:"; diff --git a/htdocs/js/jscalendar/lang/calendar-de.js b/htdocs/js/jscalendar/lang/calendar-de.js new file mode 100644 index 0000000..4bc1137 --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-de.js @@ -0,0 +1,124 @@ +// ** I18N + +// Calendar DE language +// Author: Jack (tR), +// Encoding: any +// Distributed under the same terms as the calendar itself. + +// For translators: please use UTF-8 if possible. We strongly believe that +// Unicode is the answer to a real internationalized world. Also please +// include your contact information in the header, as can be seen above. + +// full day names +Calendar._DN = new Array +("Sonntag", + "Montag", + "Dienstag", + "Mittwoch", + "Donnerstag", + "Freitag", + "Samstag", + "Sonntag"); + +// Please note that the following array of short day names (and the same goes +// for short month names, _SMN) isn't absolutely necessary. We give it here +// for exemplification on how one can customize the short day names, but if +// they are simply the first N letters of the full name you can simply say: +// +// Calendar._SDN_len = N; // short day name length +// Calendar._SMN_len = N; // short month name length +// +// If N = 3 then this is not needed either since we assume a value of 3 if not +// present, to be compatible with translation files that were written before +// this feature. + +// short day names +Calendar._SDN = new Array +("So", + "Mo", + "Di", + "Mi", + "Do", + "Fr", + "Sa", + "So"); + +// full month names +Calendar._MN = new Array +("Januar", + "Februar", + "M\u00e4rz", + "April", + "Mai", + "Juni", + "Juli", + "August", + "September", + "Oktober", + "November", + "Dezember"); + +// short month names +Calendar._SMN = new Array +("Jan", + "Feb", + "M\u00e4r", + "Apr", + "May", + "Jun", + "Jul", + "Aug", + "Sep", + "Okt", + "Nov", + "Dez"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "\u00DCber dieses Kalendarmodul"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this ;-) +"For latest version visit: http://www.dynarch.com/projects/calendar/\n" + +"Distributed under GNU LGPL. See http://gnu.org/licenses/lgpl.html for details." + +"\n\n" + +"Datum ausw\u00e4hlen:\n" + +"- Benutzen Sie die \xab, \xbb Buttons um das Jahr zu w\u00e4hlen\n" + +"- Benutzen Sie die " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " Buttons um den Monat zu w\u00e4hlen\n" + +"- F\u00fcr eine Schnellauswahl halten Sie die Maustaste \u00fcber diesen Buttons fest."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Zeit ausw\u00e4hlen:\n" + +"- Klicken Sie auf die Teile der Uhrzeit, um diese zu erh\u00F6hen\n" + +"- oder klicken Sie mit festgehaltener Shift-Taste um diese zu verringern\n" + +"- oder klicken und festhalten f\u00fcr Schnellauswahl."; + +Calendar._TT["TOGGLE"] = "Ersten Tag der Woche w\u00e4hlen"; +Calendar._TT["PREV_YEAR"] = "Voriges Jahr (Festhalten f\u00fcr Schnellauswahl)"; +Calendar._TT["PREV_MONTH"] = "Voriger Monat (Festhalten f\u00fcr Schnellauswahl)"; +Calendar._TT["GO_TODAY"] = "Heute ausw\u00e4hlen"; +Calendar._TT["NEXT_MONTH"] = "N\u00e4chst. Monat (Festhalten f\u00fcr Schnellauswahl)"; +Calendar._TT["NEXT_YEAR"] = "N\u00e4chst. Jahr (Festhalten f\u00fcr Schnellauswahl)"; +Calendar._TT["SEL_DATE"] = "Datum ausw\u00e4hlen"; +Calendar._TT["DRAG_TO_MOVE"] = "Zum Bewegen festhalten"; +Calendar._TT["PART_TODAY"] = " (Heute)"; + +// the following is to inform that "%s" is to be the first day of week +// %s will be replaced with the day name. +Calendar._TT["DAY_FIRST"] = "Woche beginnt mit %s "; + +// This may be locale-dependent. It specifies the week-end days, as an array +// of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1 +// means Monday, etc. +Calendar._TT["WEEKEND"] = "0,6"; + +Calendar._TT["CLOSE"] = "Schlie\u00dfen"; +Calendar._TT["TODAY"] = "Heute"; +Calendar._TT["TIME_PART"] = "(Shift-)Klick oder Festhalten und Ziehen um den Wert zu \u00e4ndern"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%d.%m.%Y"; +Calendar._TT["TT_DATE_FORMAT"] = "%a, %b %e"; + +Calendar._TT["WK"] = "wk"; +Calendar._TT["TIME"] = "Zeit:"; diff --git a/htdocs/js/jscalendar/lang/calendar-du.js b/htdocs/js/jscalendar/lang/calendar-du.js new file mode 100644 index 0000000..2200448 --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-du.js @@ -0,0 +1,45 @@ +// ** I18N +Calendar._DN = new Array +("Zondag", + "Maandag", + "Dinsdag", + "Woensdag", + "Donderdag", + "Vrijdag", + "Zaterdag", + "Zondag"); +Calendar._MN = new Array +("Januari", + "Februari", + "Maart", + "April", + "Mei", + "Juni", + "Juli", + "Augustus", + "September", + "Oktober", + "November", + "December"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["TOGGLE"] = "Toggle startdag van de week"; +Calendar._TT["PREV_YEAR"] = "Vorig jaar (indrukken voor menu)"; +Calendar._TT["PREV_MONTH"] = "Vorige month (indrukken voor menu)"; +Calendar._TT["GO_TODAY"] = "Naar Vandaag"; +Calendar._TT["NEXT_MONTH"] = "Volgende Maand (indrukken voor menu)"; +Calendar._TT["NEXT_YEAR"] = "Volgend jaar (indrukken voor menu)"; +Calendar._TT["SEL_DATE"] = "Selecteer datum"; +Calendar._TT["DRAG_TO_MOVE"] = "Sleep om te verplaatsen"; +Calendar._TT["PART_TODAY"] = " (vandaag)"; +Calendar._TT["MON_FIRST"] = "Toon Maandag eerst"; +Calendar._TT["SUN_FIRST"] = "Toon Zondag eerst"; +Calendar._TT["CLOSE"] = "Sluiten"; +Calendar._TT["TODAY"] = "Vandaag"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "y-mm-dd"; +Calendar._TT["TT_DATE_FORMAT"] = "D, M d"; + +Calendar._TT["WK"] = "wk"; diff --git a/htdocs/js/jscalendar/lang/calendar-el.js b/htdocs/js/jscalendar/lang/calendar-el.js new file mode 100644 index 0000000..43a9b2c --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-el.js @@ -0,0 +1,89 @@ +// ** I18N +Calendar._DN = new Array +("ΚυÏιακή", + "ΔευτέÏα", + "ΤÏίτη", + "ΤετάÏτη", + "Πέμπτη", + "ΠαÏασκευή", + "Σάββατο", + "ΚυÏιακή"); + +Calendar._SDN = new Array +("Κυ", + "Δε", + "TÏ", + "Τε", + "Πε", + "Πα", + "Σα", + "Κυ"); + +Calendar._MN = new Array +("ΙανουάÏιος", + "ΦεβÏουάÏιος", + "ΜάÏτιος", + "ΑπÏίλιος", + "Μάϊος", + "ΙοÏνιος", + "ΙοÏλιος", + "ΑÏγουστος", + "ΣεπτέμβÏιος", + "ΟκτώβÏιος", + "ÎοέμβÏιος", + "ΔεκέμβÏιος"); + +Calendar._SMN = new Array +("Ιαν", + "Φεβ", + "ΜαÏ", + "ΑπÏ", + "Μαι", + "Ιουν", + "Ιουλ", + "Αυγ", + "Σεπ", + "Οκτ", + "Îοε", + "Δεκ"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "Για το ημεÏολόγιο"; + +Calendar._TT["ABOUT"] = +"Επιλογέας ημεÏομηνίας/ÏŽÏας σε DHTML\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"Για τελευταία έκδοση: http://www.dynarch.com/projects/calendar/\n" + +"Distributed under GNU LGPL. See http://gnu.org/licenses/lgpl.html for details." + +"\n\n" + +"Επιλογή ημεÏομηνίας:\n" + +"- ΧÏησιμοποιείστε τα κουμπιά \xab, \xbb για επιλογή έτους\n" + +"- ΧÏησιμοποιείστε τα κουμπιά " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " για επιλογή μήνα\n" + +"- ΚÏατήστε κουμπί Ï€Î¿Î½Ï„Î¹ÎºÎ¿Ï Ï€Î±Ï„Î·Î¼Î­Î½Î¿ στα παÏαπάνω κουμπιά για πιο γÏήγοÏη επιλογή."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Επιλογή ÏŽÏας:\n" + +"- Κάντε κλικ σε ένα από τα μέÏη της ÏŽÏας για αÏξηση\n" + +"- ή Shift-κλικ για μείωση\n" + +"- ή κλικ και μετακίνηση για πιο γÏήγοÏη επιλογή."; +Calendar._TT["TOGGLE"] = "ΜπάÏα Ï€Ïώτης ημέÏας της εβδομάδας"; +Calendar._TT["PREV_YEAR"] = "ΠÏοηγ. έτος (κÏατήστε για το μενοÏ)"; +Calendar._TT["PREV_MONTH"] = "ΠÏοηγ. μήνας (κÏατήστε για το μενοÏ)"; +Calendar._TT["GO_TODAY"] = "ΣήμεÏα"; +Calendar._TT["NEXT_MONTH"] = "Επόμενος μήνας (κÏατήστε για το μενοÏ)"; +Calendar._TT["NEXT_YEAR"] = "Επόμενο έτος (κÏατήστε για το μενοÏ)"; +Calendar._TT["SEL_DATE"] = "Επιλέξτε ημεÏομηνία"; +Calendar._TT["DRAG_TO_MOVE"] = "ΣÏÏτε για να μετακινήσετε"; +Calendar._TT["PART_TODAY"] = " (σήμεÏα)"; +Calendar._TT["MON_FIRST"] = "Εμφάνιση ΔευτέÏας Ï€Ïώτα"; +Calendar._TT["SUN_FIRST"] = "Εμφάνιση ΚυÏιακής Ï€Ïώτα"; +Calendar._TT["CLOSE"] = "Κλείσιμο"; +Calendar._TT["TODAY"] = "ΣήμεÏα"; +Calendar._TT["TIME_PART"] = "(Shift-)κλικ ή μετακίνηση για αλλαγή"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "dd-mm-y"; +Calendar._TT["TT_DATE_FORMAT"] = "D, d M"; + +Calendar._TT["WK"] = "εβδ"; + diff --git a/htdocs/js/jscalendar/lang/calendar-en.js b/htdocs/js/jscalendar/lang/calendar-en.js new file mode 100644 index 0000000..0dbde79 --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-en.js @@ -0,0 +1,127 @@ +// ** I18N + +// Calendar EN language +// Author: Mihai Bazon, +// Encoding: any +// Distributed under the same terms as the calendar itself. + +// For translators: please use UTF-8 if possible. We strongly believe that +// Unicode is the answer to a real internationalized world. Also please +// include your contact information in the header, as can be seen above. + +// full day names +Calendar._DN = new Array +("Sunday", + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday", + "Saturday", + "Sunday"); + +// Please note that the following array of short day names (and the same goes +// for short month names, _SMN) isn't absolutely necessary. We give it here +// for exemplification on how one can customize the short day names, but if +// they are simply the first N letters of the full name you can simply say: +// +// Calendar._SDN_len = N; // short day name length +// Calendar._SMN_len = N; // short month name length +// +// If N = 3 then this is not needed either since we assume a value of 3 if not +// present, to be compatible with translation files that were written before +// this feature. + +// short day names +Calendar._SDN = new Array +("Sun", + "Mon", + "Tue", + "Wed", + "Thu", + "Fri", + "Sat", + "Sun"); + +// First day of the week. "0" means display Sunday first, "1" means display +// Monday first, etc. +Calendar._FD = 0; + +// full month names +Calendar._MN = new Array +("January", + "February", + "March", + "April", + "May", + "June", + "July", + "August", + "September", + "October", + "November", + "December"); + +// short month names +Calendar._SMN = new Array +("Jan", + "Feb", + "Mar", + "Apr", + "May", + "Jun", + "Jul", + "Aug", + "Sep", + "Oct", + "Nov", + "Dec"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "About the calendar"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"For latest version visit: http://www.dynarch.com/projects/calendar/\n" + +"Distributed under GNU LGPL. See http://gnu.org/licenses/lgpl.html for details." + +"\n\n" + +"Date selection:\n" + +"- Use the \xab, \xbb buttons to select year\n" + +"- Use the " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " buttons to select month\n" + +"- Hold mouse button on any of the above buttons for faster selection."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Time selection:\n" + +"- Click on any of the time parts to increase it\n" + +"- or Shift-click to decrease it\n" + +"- or click and drag for faster selection."; + +Calendar._TT["PREV_YEAR"] = "Prev. year (hold for menu)"; +Calendar._TT["PREV_MONTH"] = "Prev. month (hold for menu)"; +Calendar._TT["GO_TODAY"] = "Go Today"; +Calendar._TT["NEXT_MONTH"] = "Next month (hold for menu)"; +Calendar._TT["NEXT_YEAR"] = "Next year (hold for menu)"; +Calendar._TT["SEL_DATE"] = "Select date"; +Calendar._TT["DRAG_TO_MOVE"] = "Drag to move"; +Calendar._TT["PART_TODAY"] = " (today)"; + +// the following is to inform that "%s" is to be the first day of week +// %s will be replaced with the day name. +Calendar._TT["DAY_FIRST"] = "Display %s first"; + +// This may be locale-dependent. It specifies the week-end days, as an array +// of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1 +// means Monday, etc. +Calendar._TT["WEEKEND"] = "0,6"; + +Calendar._TT["CLOSE"] = "Close"; +Calendar._TT["TODAY"] = "Today"; +Calendar._TT["TIME_PART"] = "(Shift-)Click or drag to change value"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d"; +Calendar._TT["TT_DATE_FORMAT"] = "%a, %b %e"; + +Calendar._TT["WK"] = "wk"; +Calendar._TT["TIME"] = "Time:"; diff --git a/htdocs/js/jscalendar/lang/calendar-es.js b/htdocs/js/jscalendar/lang/calendar-es.js new file mode 100644 index 0000000..19c1b30 --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-es.js @@ -0,0 +1,129 @@ +// ** I18N + +// Calendar ES (spanish) language +// Author: Mihai Bazon, +// Updater: Servilio Afre Puentes +// Updated: 2004-06-03 +// Encoding: utf-8 +// Distributed under the same terms as the calendar itself. + +// For translators: please use UTF-8 if possible. We strongly believe that +// Unicode is the answer to a real internationalized world. Also please +// include your contact information in the header, as can be seen above. + +// full day names +Calendar._DN = new Array +("Domingo", + "Lunes", + "Martes", + "Miércoles", + "Jueves", + "Viernes", + "Sábado", + "Domingo"); + +// Please note that the following array of short day names (and the same goes +// for short month names, _SMN) isn't absolutely necessary. We give it here +// for exemplification on how one can customize the short day names, but if +// they are simply the first N letters of the full name you can simply say: +// +// Calendar._SDN_len = N; // short day name length +// Calendar._SMN_len = N; // short month name length +// +// If N = 3 then this is not needed either since we assume a value of 3 if not +// present, to be compatible with translation files that were written before +// this feature. + +// short day names +Calendar._SDN = new Array +("Dom", + "Lun", + "Mar", + "Mié", + "Jue", + "Vie", + "Sáb", + "Dom"); + +// First day of the week. "0" means display Sunday first, "1" means display +// Monday first, etc. +Calendar._FD = 1; + +// full month names +Calendar._MN = new Array +("Enero", + "Febrero", + "Marzo", + "Abril", + "Mayo", + "Junio", + "Julio", + "Agosto", + "Septiembre", + "Octubre", + "Noviembre", + "Diciembre"); + +// short month names +Calendar._SMN = new Array +("Ene", + "Feb", + "Mar", + "Abr", + "May", + "Jun", + "Jul", + "Ago", + "Sep", + "Oct", + "Nov", + "Dic"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "Acerca del calendario"; + +Calendar._TT["ABOUT"] = +"Selector DHTML de Fecha/Hora\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"Para conseguir la última versión visite: http://www.dynarch.com/projects/calendar/\n" + +"Distribuido bajo licencia GNU LGPL. Visite http://gnu.org/licenses/lgpl.html para más detalles." + +"\n\n" + +"Selección de fecha:\n" + +"- Use los botones \xab, \xbb para seleccionar el año\n" + +"- Use los botones " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " para seleccionar el mes\n" + +"- Mantenga pulsado el ratón en cualquiera de estos botones para una selección rápida."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Selección de hora:\n" + +"- Pulse en cualquiera de las partes de la hora para incrementarla\n" + +"- o pulse las mayúsculas mientras hace clic para decrementarla\n" + +"- o haga clic y arrastre el ratón para una selección más rápida."; + +Calendar._TT["PREV_YEAR"] = "Año anterior (mantener para menú)"; +Calendar._TT["PREV_MONTH"] = "Mes anterior (mantener para menú)"; +Calendar._TT["GO_TODAY"] = "Ir a hoy"; +Calendar._TT["NEXT_MONTH"] = "Mes siguiente (mantener para menú)"; +Calendar._TT["NEXT_YEAR"] = "Año siguiente (mantener para menú)"; +Calendar._TT["SEL_DATE"] = "Seleccionar fecha"; +Calendar._TT["DRAG_TO_MOVE"] = "Arrastrar para mover"; +Calendar._TT["PART_TODAY"] = " (hoy)"; + +// the following is to inform that "%s" is to be the first day of week +// %s will be replaced with the day name. +Calendar._TT["DAY_FIRST"] = "Hacer %s primer día de la semana"; + +// This may be locale-dependent. It specifies the week-end days, as an array +// of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1 +// means Monday, etc. +Calendar._TT["WEEKEND"] = "0,6"; + +Calendar._TT["CLOSE"] = "Cerrar"; +Calendar._TT["TODAY"] = "Hoy"; +Calendar._TT["TIME_PART"] = "(Mayúscula-)Clic o arrastre para cambiar valor"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%d/%m/%Y"; +Calendar._TT["TT_DATE_FORMAT"] = "%A, %e de %B de %Y"; + +Calendar._TT["WK"] = "sem"; +Calendar._TT["TIME"] = "Hora:"; diff --git a/htdocs/js/jscalendar/lang/calendar-fi.js b/htdocs/js/jscalendar/lang/calendar-fi.js new file mode 100644 index 0000000..328eabb --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-fi.js @@ -0,0 +1,98 @@ +// ** I18N + +// Calendar FI language (Finnish, Suomi) +// Author: Jarno Käyhkö, +// Encoding: UTF-8 +// Distributed under the same terms as the calendar itself. + +// full day names +Calendar._DN = new Array +("Sunnuntai", + "Maanantai", + "Tiistai", + "Keskiviikko", + "Torstai", + "Perjantai", + "Lauantai", + "Sunnuntai"); + +// short day names +Calendar._SDN = new Array +("Su", + "Ma", + "Ti", + "Ke", + "To", + "Pe", + "La", + "Su"); + +// full month names +Calendar._MN = new Array +("Tammikuu", + "Helmikuu", + "Maaliskuu", + "Huhtikuu", + "Toukokuu", + "Kesäkuu", + "Heinäkuu", + "Elokuu", + "Syyskuu", + "Lokakuu", + "Marraskuu", + "Joulukuu"); + +// short month names +Calendar._SMN = new Array +("Tam", + "Hel", + "Maa", + "Huh", + "Tou", + "Kes", + "Hei", + "Elo", + "Syy", + "Lok", + "Mar", + "Jou"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "Tietoja kalenterista"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"Uusin versio osoitteessa: http://www.dynarch.com/projects/calendar/\n" + +"Julkaistu GNU LGPL lisenssin alaisuudessa. Lisätietoja osoitteessa http://gnu.org/licenses/lgpl.html" + +"\n\n" + +"Päivämäärä valinta:\n" + +"- Käytä \xab, \xbb painikkeita valitaksesi vuosi\n" + +"- Käytä " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " painikkeita valitaksesi kuukausi\n" + +"- Pitämällä hiiren painiketta minkä tahansa yllä olevan painikkeen kohdalla, saat näkyviin valikon nopeampaan siirtymiseen."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Ajan valinta:\n" + +"- Klikkaa kellonajan numeroita lisätäksesi aikaa\n" + +"- tai pitämällä Shift-näppäintä pohjassa saat aikaa taaksepäin\n" + +"- tai klikkaa ja pidä hiiren painike pohjassa sekä liikuta hiirtä muuttaaksesi aikaa nopeasti eteen- ja taaksepäin."; + +Calendar._TT["PREV_YEAR"] = "Edell. vuosi (paina hetki, näet valikon)"; +Calendar._TT["PREV_MONTH"] = "Edell. kuukausi (paina hetki, näet valikon)"; +Calendar._TT["GO_TODAY"] = "Siirry tähän päivään"; +Calendar._TT["NEXT_MONTH"] = "Seur. kuukausi (paina hetki, näet valikon)"; +Calendar._TT["NEXT_YEAR"] = "Seur. vuosi (paina hetki, näet valikon)"; +Calendar._TT["SEL_DATE"] = "Valitse päivämäärä"; +Calendar._TT["DRAG_TO_MOVE"] = "Siirrä kalenterin paikkaa"; +Calendar._TT["PART_TODAY"] = " (tänään)"; +Calendar._TT["MON_FIRST"] = "Näytä maanantai ensimmäisenä"; +Calendar._TT["SUN_FIRST"] = "Näytä sunnuntai ensimmäisenä"; +Calendar._TT["CLOSE"] = "Sulje"; +Calendar._TT["TODAY"] = "Tänään"; +Calendar._TT["TIME_PART"] = "(Shift-) Klikkaa tai liikuta muuttaaksesi aikaa"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%d.%m.%Y"; +Calendar._TT["TT_DATE_FORMAT"] = "%d.%m.%Y"; + +Calendar._TT["WK"] = "Vko"; diff --git a/htdocs/js/jscalendar/lang/calendar-fr.js b/htdocs/js/jscalendar/lang/calendar-fr.js new file mode 100644 index 0000000..2a9e0b2 --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-fr.js @@ -0,0 +1,125 @@ +// ** I18N + +// Calendar EN language +// Author: Mihai Bazon, +// Encoding: any +// Distributed under the same terms as the calendar itself. + +// For translators: please use UTF-8 if possible. We strongly believe that +// Unicode is the answer to a real internationalized world. Also please +// include your contact information in the header, as can be seen above. + +// Translator: David Duret, from previous french version + +// full day names +Calendar._DN = new Array +("Dimanche", + "Lundi", + "Mardi", + "Mercredi", + "Jeudi", + "Vendredi", + "Samedi", + "Dimanche"); + +// Please note that the following array of short day names (and the same goes +// for short month names, _SMN) isn't absolutely necessary. We give it here +// for exemplification on how one can customize the short day names, but if +// they are simply the first N letters of the full name you can simply say: +// +// Calendar._SDN_len = N; // short day name length +// Calendar._SMN_len = N; // short month name length +// +// If N = 3 then this is not needed either since we assume a value of 3 if not +// present, to be compatible with translation files that were written before +// this feature. + +// short day names +Calendar._SDN = new Array +("Dim", + "Lun", + "Mar", + "Mar", + "Jeu", + "Ven", + "Sam", + "Dim"); + +// full month names +Calendar._MN = new Array +("Janvier", + "Février", + "Mars", + "Avril", + "Mai", + "Juin", + "Juillet", + "Août", + "Septembre", + "Octobre", + "Novembre", + "Décembre"); + +// short month names +Calendar._SMN = new Array +("Jan", + "Fev", + "Mar", + "Avr", + "Mai", + "Juin", + "Juil", + "Aout", + "Sep", + "Oct", + "Nov", + "Dec"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "A propos du calendrier"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Heure Selecteur\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"Pour la derniere version visitez : http://www.dynarch.com/projects/calendar/\n" + +"Distribué par GNU LGPL. Voir http://gnu.org/licenses/lgpl.html pour les details." + +"\n\n" + +"Selection de la date :\n" + +"- Utiliser les bouttons \xab, \xbb pour selectionner l\'annee\n" + +"- Utiliser les bouttons " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " pour selectionner les mois\n" + +"- Garder la souris sur n'importe quels boutons pour une selection plus rapide"; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Selection de l\'heure :\n" + +"- Cliquer sur heures ou minutes pour incrementer\n" + +"- ou Maj-clic pour decrementer\n" + +"- ou clic et glisser-deplacer pour une selection plus rapide"; + +Calendar._TT["PREV_YEAR"] = "Année préc. (maintenir pour menu)"; +Calendar._TT["PREV_MONTH"] = "Mois préc. (maintenir pour menu)"; +Calendar._TT["GO_TODAY"] = "Atteindre la date du jour"; +Calendar._TT["NEXT_MONTH"] = "Mois suiv. (maintenir pour menu)"; +Calendar._TT["NEXT_YEAR"] = "Année suiv. (maintenir pour menu)"; +Calendar._TT["SEL_DATE"] = "Sélectionner une date"; +Calendar._TT["DRAG_TO_MOVE"] = "Déplacer"; +Calendar._TT["PART_TODAY"] = " (Aujourd'hui)"; + +// the following is to inform that "%s" is to be the first day of week +// %s will be replaced with the day name. +Calendar._TT["DAY_FIRST"] = "Afficher %s en premier"; + +// This may be locale-dependent. It specifies the week-end days, as an array +// of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1 +// means Monday, etc. +Calendar._TT["WEEKEND"] = "0,6"; + +Calendar._TT["CLOSE"] = "Fermer"; +Calendar._TT["TODAY"] = "Aujourd'hui"; +Calendar._TT["TIME_PART"] = "(Maj-)Clic ou glisser pour modifier la valeur"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%d/%m/%Y"; +Calendar._TT["TT_DATE_FORMAT"] = "%a, %b %e"; + +Calendar._TT["WK"] = "Sem."; +Calendar._TT["TIME"] = "Heure :"; diff --git a/htdocs/js/jscalendar/lang/calendar-he-utf8.js b/htdocs/js/jscalendar/lang/calendar-he-utf8.js new file mode 100644 index 0000000..7861217 --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-he-utf8.js @@ -0,0 +1,123 @@ +// ** I18N + +// Calendar EN language +// Author: Idan Sofer, +// Encoding: UTF-8 +// Distributed under the same terms as the calendar itself. + +// For translators: please use UTF-8 if possible. We strongly believe that +// Unicode is the answer to a real internationalized world. Also please +// include your contact information in the header, as can be seen above. + +// full day names +Calendar._DN = new Array +("ר×שון", + "שני", + "שלישי", + "רביעי", + "חמישי", + "שישי", + "שבת", + "ר×שון"); + +// Please note that the following array of short day names (and the same goes +// for short month names, _SMN) isn't absolutely necessary. We give it here +// for exemplification on how one can customize the short day names, but if +// they are simply the first N letters of the full name you can simply say: +// +// Calendar._SDN_len = N; // short day name length +// Calendar._SMN_len = N; // short month name length +// +// If N = 3 then this is not needed either since we assume a value of 3 if not +// present, to be compatible with translation files that were written before +// this feature. + +// short day names +Calendar._SDN = new Array +("×", + "ב", + "×’", + "ד", + "×”", + "ו", + "ש", + "×"); + +// full month names +Calendar._MN = new Array +("ינו×ר", + "פברו×ר", + "מרץ", + "×פריל", + "מ××™", + "יוני", + "יולי", + "×וגוסט", + "ספטמבר", + "×וקטובר", + "נובמבר", + "דצמבר"); + +// short month names +Calendar._SMN = new Array +("×™× ×", + "פבר", + "מרץ", + "×פר", + "מ××™", + "יונ", + "יול", + "×וג", + "ספט", + "×וק", + "נוב", + "דצמ"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "×ודות השנתון"; + +Calendar._TT["ABOUT"] = +"בחרן ת×ריך/שעה DHTML\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"×”×’×™×¨×¡× ×”×חרונה זמינה ב: http://www.dynarch.com/projects/calendar/\n" + +"מופץ תחת זיכיון ×” GNU LGPL. עיין ב http://gnu.org/licenses/lgpl.html ×œ×¤×¨×˜×™× × ×•×¡×¤×™×." + +"\n\n" + +בחירת ת×ריך:\n" + +"- השתמש ×‘×›×¤×ª×•×¨×™× \xab, \xbb לבחירת שנה\n" + +"- השתמש ×‘×›×¤×ª×•×¨×™× " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " לבחירת חודש\n" + +"- החזק העכבר לחוץ מעל ×”×›×¤×ª×•×¨×™× ×”×ž×•×–×›×¨×™× ×œ×¢×™×œ לבחירה מהירה יותר."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"בחירת זמן:\n" + +"- לחץ על כל ×חד מחלקי הזמן כדי להוסיף\n" + +"- ×ו shift בשילוב ×¢× ×œ×—×™×¦×” כדי להחסיר\n" + +"- ×ו לחץ וגרור לפעולה מהירה יותר."; + +Calendar._TT["PREV_YEAR"] = "שנה קודמת - החזק לקבלת תפריט"; +Calendar._TT["PREV_MONTH"] = "חודש ×§×•×“× - החזק לקבלת תפריט"; +Calendar._TT["GO_TODAY"] = "עבור להיו×"; +Calendar._TT["NEXT_MONTH"] = "חודש ×”×‘× - החזק לתפריט"; +Calendar._TT["NEXT_YEAR"] = "שנה הב××” - החזק לתפריט"; +Calendar._TT["SEL_DATE"] = "בחר ת×ריך"; +Calendar._TT["DRAG_TO_MOVE"] = "גרור להזזה"; +Calendar._TT["PART_TODAY"] = " )היו×("; + +// the following is to inform that "%s" is to be the first day of week +// %s will be replaced with the day name. +Calendar._TT["DAY_FIRST"] = "הצג %s קוד×"; + +// This may be locale-dependent. It specifies the week-end days, as an array +// of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1 +// means Monday, etc. +Calendar._TT["WEEKEND"] = "6"; + +Calendar._TT["CLOSE"] = "סגור"; +Calendar._TT["TODAY"] = "היו×"; +Calendar._TT["TIME_PART"] = "(שיפט-)לחץ וגרור כדי לשנות ערך"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d"; +Calendar._TT["TT_DATE_FORMAT"] = "%a, %b %e"; + +Calendar._TT["WK"] = "wk"; +Calendar._TT["TIME"] = "שעה::"; diff --git a/htdocs/js/jscalendar/lang/calendar-hr-utf8.js b/htdocs/js/jscalendar/lang/calendar-hr-utf8.js new file mode 100644 index 0000000..d569cfd --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-hr-utf8.js @@ -0,0 +1,49 @@ +/* Croatian language file for the DHTML Calendar version 0.9.2 +* Author Krunoslav Zubrinic , June 2003. +* Feel free to use this script under the terms of the GNU Lesser General +* Public License, as long as you do not remove or alter this notice. +*/ +Calendar._DN = new Array +("Nedjelja", + "Ponedjeljak", + "Utorak", + "Srijeda", + "ÄŒetvrtak", + "Petak", + "Subota", + "Nedjelja"); +Calendar._MN = new Array +("SijeÄanj", + "VeljaÄa", + "Ožujak", + "Travanj", + "Svibanj", + "Lipanj", + "Srpanj", + "Kolovoz", + "Rujan", + "Listopad", + "Studeni", + "Prosinac"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["TOGGLE"] = "Promjeni dan s kojim poÄinje tjedan"; +Calendar._TT["PREV_YEAR"] = "Prethodna godina (dugi pritisak za meni)"; +Calendar._TT["PREV_MONTH"] = "Prethodni mjesec (dugi pritisak za meni)"; +Calendar._TT["GO_TODAY"] = "Idi na tekući dan"; +Calendar._TT["NEXT_MONTH"] = "Slijedeći mjesec (dugi pritisak za meni)"; +Calendar._TT["NEXT_YEAR"] = "Slijedeća godina (dugi pritisak za meni)"; +Calendar._TT["SEL_DATE"] = "Izaberite datum"; +Calendar._TT["DRAG_TO_MOVE"] = "Pritisni i povuci za promjenu pozicije"; +Calendar._TT["PART_TODAY"] = " (today)"; +Calendar._TT["MON_FIRST"] = "Prikaži ponedjeljak kao prvi dan"; +Calendar._TT["SUN_FIRST"] = "Prikaži nedjelju kao prvi dan"; +Calendar._TT["CLOSE"] = "Zatvori"; +Calendar._TT["TODAY"] = "Danas"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "dd-mm-y"; +Calendar._TT["TT_DATE_FORMAT"] = "DD, dd.mm.y"; + +Calendar._TT["WK"] = "Tje"; \ No newline at end of file diff --git a/htdocs/js/jscalendar/lang/calendar-hr.js b/htdocs/js/jscalendar/lang/calendar-hr.js new file mode 100644 index 0000000000000000000000000000000000000000..6c27f60c4f8d416145e316bdb92e455a04a26fc4 GIT binary patch literal 3088 zcmcJRZEq4$5QV3oOpN^xn|@MLX``QvFOd|BwX`K&TD8VBv|!x=g_MG!Mt{2coVhHp zKpTvj4cxc6GiS~{b9aCJT(gH3*@j(O+p2bD3I7+&G`&5u9_^Xcnfc6GbJ%NRA7TB) z#|3+172C0rd#bwCh1J+8t3EcD)@66wJ+E8Np7MLl+OpmC_<7>UTkyM$eGl6lj3p>PheZ0=Ww2=H?b(l|o^zMwpyIsrK|Sp&cKx5sS&@!9bLPe8y!ma|m&W@1t~03i zVNK_Gk(rhME=;!FTP?E|GvDK^rJ*FVQYO0UUUgnYdn=YQt!h}~kw)7*(yTJ*-gpib zZl$2fZ}$C`^OD_1B2{e9iaaHI&FIr`ue2#lE!UXvs;0s%sav4I+Bvf=`W^bqOTsRd z3#r;*y|Ms;vh5T5kb3$+n`bnQL#ow1S#y3O?q>A^Tan$T-(yY~JD^USqb_J0%v{q( z;0&xk!1v7>PB|GP+JT*2IC^s{CPfZR>2^A0^zShhL2~S;Re+-p89ZCghHfF{s#~oA zBX>BH^wbu~dKdQJ6XBS*+Pth|)R*2l^`ZCwo%I;gJZ(%PQuhB_8!;@E{O-@gRkmif zTx}=tA5^GnP#vi5TMH?#fco=PV>sz>5{FY!RGF#9LuCf#>z3-FK8=FvRSn}B)_YO4 zdX0swRHcjPqU<#(UFfcuRiD(Z+ew)YxVaYb85DMGo3=&9F`lPuK0(7(ZvHg4+4rPw zp(=4h)$5DrPt+dsC9+FSiy_EH7n6SzdjkdSk#$x*N3ImTX>`7eusHub3i#1Y&>i_0 zzeR!?rOVGAr{ytkf1BtnQ2^`agzClH9w)bhHnL||LkEvgdyD_U2*JFsr}VZ}t8b}L hPd9rmV52WTMaX%C+(ZQBcw3Zrwhfx``>it4|8LNz+ +// Encoding: any +// Distributed under the same terms as the calendar itself. + +// For translators: please use UTF-8 if possible. We strongly believe that +// Unicode is the answer to a real internationalized world. Also please +// include your contact information in the header, as can be seen above. + +// full day names +Calendar._DN = new Array +("Vasárnap", + "Hétfõ", + "Kedd", + "Szerda", + "Csütörtök", + "Péntek", + "Szombat", + "Vasárnap"); + +// Please note that the following array of short day names (and the same goes +// for short month names, _SMN) isn't absolutely necessary. We give it here +// for exemplification on how one can customize the short day names, but if +// they are simply the first N letters of the full name you can simply say: +// +// Calendar._SDN_len = N; // short day name length +// Calendar._SMN_len = N; // short month name length +// +// If N = 3 then this is not needed either since we assume a value of 3 if not +// present, to be compatible with translation files that were written before +// this feature. + +// short day names +Calendar._SDN = new Array +("v", + "h", + "k", + "sze", + "cs", + "p", + "szo", + "v"); + +// full month names +Calendar._MN = new Array +("január", + "február", + "március", + "április", + "május", + "június", + "július", + "augusztus", + "szeptember", + "október", + "november", + "december"); + +// short month names +Calendar._SMN = new Array +("jan", + "feb", + "már", + "ápr", + "máj", + "jún", + "júl", + "aug", + "sze", + "okt", + "nov", + "dec"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "A kalendáriumról"; + +Calendar._TT["ABOUT"] = +"DHTML dátum/idõ kiválasztó\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"a legfrissebb verzió megtalálható: http://www.dynarch.com/projects/calendar/\n" + +"GNU LGPL alatt terjesztve. Lásd a http://gnu.org/licenses/lgpl.html oldalt a részletekhez." + +"\n\n" + +"Dátum választás:\n" + +"- használja a \xab, \xbb gombokat az év kiválasztásához\n" + +"- használja a " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " gombokat a hónap kiválasztásához\n" + +"- tartsa lenyomva az egérgombot a gyors választáshoz."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Idõ választás:\n" + +"- kattintva növelheti az idõt\n" + +"- shift-tel kattintva csökkentheti\n" + +"- lenyomva tartva és húzva gyorsabban kiválaszthatja."; + +Calendar._TT["PREV_YEAR"] = "Elõzõ év (tartsa nyomva a menühöz)"; +Calendar._TT["PREV_MONTH"] = "Elõzõ hónap (tartsa nyomva a menühöz)"; +Calendar._TT["GO_TODAY"] = "Mai napra ugrás"; +Calendar._TT["NEXT_MONTH"] = "Köv. hónap (tartsa nyomva a menühöz)"; +Calendar._TT["NEXT_YEAR"] = "Köv. év (tartsa nyomva a menühöz)"; +Calendar._TT["SEL_DATE"] = "Válasszon dátumot"; +Calendar._TT["DRAG_TO_MOVE"] = "Húzza a mozgatáshoz"; +Calendar._TT["PART_TODAY"] = " (ma)"; + +// the following is to inform that "%s" is to be the first day of week +// %s will be replaced with the day name. +Calendar._TT["DAY_FIRST"] = "%s legyen a hét elsõ napja"; + +// This may be locale-dependent. It specifies the week-end days, as an array +// of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1 +// means Monday, etc. +Calendar._TT["WEEKEND"] = "0,6"; + +Calendar._TT["CLOSE"] = "Bezár"; +Calendar._TT["TODAY"] = "Ma"; +Calendar._TT["TIME_PART"] = "(Shift-)Klikk vagy húzás az érték változtatásához"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d"; +Calendar._TT["TT_DATE_FORMAT"] = "%b %e, %a"; + +Calendar._TT["WK"] = "hét"; +Calendar._TT["TIME"] = "idõ:"; diff --git a/htdocs/js/jscalendar/lang/calendar-it.js b/htdocs/js/jscalendar/lang/calendar-it.js new file mode 100644 index 0000000..7f84cde --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-it.js @@ -0,0 +1,124 @@ +// ** I18N + +// Calendar EN language +// Author: Mihai Bazon, +// Translator: Fabio Di Bernardini, +// Encoding: any +// Distributed under the same terms as the calendar itself. + +// For translators: please use UTF-8 if possible. We strongly believe that +// Unicode is the answer to a real internationalized world. Also please +// include your contact information in the header, as can be seen above. + +// full day names +Calendar._DN = new Array +("Domenica", + "Lunedì", + "Martedì", + "Mercoledì", + "Giovedì", + "Venerdì", + "Sabato", + "Domenica"); + +// Please note that the following array of short day names (and the same goes +// for short month names, _SMN) isn't absolutely necessary. We give it here +// for exemplification on how one can customize the short day names, but if +// they are simply the first N letters of the full name you can simply say: +// +// Calendar._SDN_len = N; // short day name length +// Calendar._SMN_len = N; // short month name length +// +// If N = 3 then this is not needed either since we assume a value of 3 if not +// present, to be compatible with translation files that were written before +// this feature. + +// short day names +Calendar._SDN = new Array +("Dom", + "Lun", + "Mar", + "Mer", + "Gio", + "Ven", + "Sab", + "Dom"); + +// full month names +Calendar._MN = new Array +("Gennaio", + "Febbraio", + "Marzo", + "Aprile", + "Maggio", + "Giugno", + "Luglio", + "Augosto", + "Settembre", + "Ottobre", + "Novembre", + "Dicembre"); + +// short month names +Calendar._SMN = new Array +("Gen", + "Feb", + "Mar", + "Apr", + "Mag", + "Giu", + "Lug", + "Ago", + "Set", + "Ott", + "Nov", + "Dic"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "Informazioni sul calendario"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"Per gli aggiornamenti: http://www.dynarch.com/projects/calendar/\n" + +"Distribuito sotto licenza GNU LGPL. Vedi http://gnu.org/licenses/lgpl.html per i dettagli." + +"\n\n" + +"Selezione data:\n" + +"- Usa \xab, \xbb per selezionare l'anno\n" + +"- Usa " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " per i mesi\n" + +"- Tieni premuto a lungo il mouse per accedere alle funzioni di selezione veloce."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Selezione orario:\n" + +"- Clicca sul numero per incrementarlo\n" + +"- o Shift+click per decrementarlo\n" + +"- o click e sinistra o destra per variarlo."; + +Calendar._TT["PREV_YEAR"] = "Anno prec.(clicca a lungo per il menù)"; +Calendar._TT["PREV_MONTH"] = "Mese prec. (clicca a lungo per il menù)"; +Calendar._TT["GO_TODAY"] = "Oggi"; +Calendar._TT["NEXT_MONTH"] = "Pross. mese (clicca a lungo per il menù)"; +Calendar._TT["NEXT_YEAR"] = "Pross. anno (clicca a lungo per il menù)"; +Calendar._TT["SEL_DATE"] = "Seleziona data"; +Calendar._TT["DRAG_TO_MOVE"] = "Trascina per spostarlo"; +Calendar._TT["PART_TODAY"] = " (oggi)"; + +// the following is to inform that "%s" is to be the first day of week +// %s will be replaced with the day name. +Calendar._TT["DAY_FIRST"] = "Mostra prima %s"; + +// This may be locale-dependent. It specifies the week-end days, as an array +// of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1 +// means Monday, etc. +Calendar._TT["WEEKEND"] = "0,6"; + +Calendar._TT["CLOSE"] = "Chiudi"; +Calendar._TT["TODAY"] = "Oggi"; +Calendar._TT["TIME_PART"] = "(Shift-)Click o trascina per cambiare il valore"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%d-%m-%Y"; +Calendar._TT["TT_DATE_FORMAT"] = "%a:%b:%e"; + +Calendar._TT["WK"] = "set"; +Calendar._TT["TIME"] = "Ora:"; diff --git a/htdocs/js/jscalendar/lang/calendar-jp.js b/htdocs/js/jscalendar/lang/calendar-jp.js new file mode 100644 index 0000000..3bca7eb --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-jp.js @@ -0,0 +1,45 @@ +// ** I18N +Calendar._DN = new Array +("“ú", + "ŒŽ", + "‰Î", + "…", + "–Ø", + "‹à", + "“y", + "“ú"); +Calendar._MN = new Array +("1ŒŽ", + "2ŒŽ", + "3ŒŽ", + "4ŒŽ", + "5ŒŽ", + "6ŒŽ", + "7ŒŽ", + "8ŒŽ", + "9ŒŽ", + "10ŒŽ", + "11ŒŽ", + "12ŒŽ"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["TOGGLE"] = "T‚Ìʼn‚Ì—j“ú‚ðØ‚è‘Ö‚¦"; +Calendar._TT["PREV_YEAR"] = "‘O”N"; +Calendar._TT["PREV_MONTH"] = "‘OŒŽ"; +Calendar._TT["GO_TODAY"] = "¡“ú"; +Calendar._TT["NEXT_MONTH"] = "—‚ŒŽ"; +Calendar._TT["NEXT_YEAR"] = "—‚”N"; +Calendar._TT["SEL_DATE"] = "“ú•t‘I‘ð"; +Calendar._TT["DRAG_TO_MOVE"] = "ƒEƒBƒ“ƒhƒE‚̈ړ®"; +Calendar._TT["PART_TODAY"] = " (¡“ú)"; +Calendar._TT["MON_FIRST"] = "ŒŽ—j“ú‚ð擪‚É"; +Calendar._TT["SUN_FIRST"] = "“ú—j“ú‚ð擪‚É"; +Calendar._TT["CLOSE"] = "•Â‚¶‚é"; +Calendar._TT["TODAY"] = "¡“ú"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "y-mm-dd"; +Calendar._TT["TT_DATE_FORMAT"] = "%mŒŽ %d“ú (%a)"; + +Calendar._TT["WK"] = "T"; diff --git a/htdocs/js/jscalendar/lang/calendar-ko-utf8.js b/htdocs/js/jscalendar/lang/calendar-ko-utf8.js new file mode 100644 index 0000000..035dd74 --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-ko-utf8.js @@ -0,0 +1,120 @@ +// ** I18N + +// Calendar EN language +// Author: Mihai Bazon, +// Translation: Yourim Yi +// Encoding: EUC-KR +// lang : ko +// Distributed under the same terms as the calendar itself. + +// For translators: please use UTF-8 if possible. We strongly believe that +// Unicode is the answer to a real internationalized world. Also please +// include your contact information in the header, as can be seen above. + +// full day names + +Calendar._DN = new Array +("ì¼ìš”ì¼", + "월요ì¼", + "화요ì¼", + "수요ì¼", + "목요ì¼", + "금요ì¼", + "토요ì¼", + "ì¼ìš”ì¼"); + +// Please note that the following array of short day names (and the same goes +// for short month names, _SMN) isn't absolutely necessary. We give it here +// for exemplification on how one can customize the short day names, but if +// they are simply the first N letters of the full name you can simply say: +// +// Calendar._SDN_len = N; // short day name length +// Calendar._SMN_len = N; // short month name length +// +// If N = 3 then this is not needed either since we assume a value of 3 if not +// present, to be compatible with translation files that were written before +// this feature. + +// short day names +Calendar._SDN = new Array +("ì¼", + "ì›”", + "í™”", + "수", + "목", + "금", + "토", + "ì¼"); + +// full month names +Calendar._MN = new Array +("1ì›”", + "2ì›”", + "3ì›”", + "4ì›”", + "5ì›”", + "6ì›”", + "7ì›”", + "8ì›”", + "9ì›”", + "10ì›”", + "11ì›”", + "12ì›”"); + +// short month names +Calendar._SMN = new Array +("1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "10", + "11", + "12"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "calendar ì— ëŒ€í•´ì„œ"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"\n"+ +"최신 ë²„ì „ì„ ë°›ìœ¼ì‹œë ¤ë©´ http://www.dynarch.com/projects/calendar/ ì— ë°©ë¬¸í•˜ì„¸ìš”\n" + +"\n"+ +"GNU LGPL ë¼ì´ì„¼ìŠ¤ë¡œ ë°°í¬ë©ë‹ˆë‹¤. \n"+ +"ë¼ì´ì„¼ìŠ¤ì— 대한 ìžì„¸í•œ ë‚´ìš©ì€ http://gnu.org/licenses/lgpl.html ì„ ì½ìœ¼ì„¸ìš”." + +"\n\n" + +"날짜 ì„ íƒ:\n" + +"- ì—°ë„를 ì„ íƒí•˜ë ¤ë©´ \xab, \xbb ë²„íŠ¼ì„ ì‚¬ìš©í•©ë‹ˆë‹¤\n" + +"- ë‹¬ì„ ì„ íƒí•˜ë ¤ë©´ " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " ë²„íŠ¼ì„ ëˆ„ë¥´ì„¸ìš”\n" + +"- ê³„ì† ëˆ„ë¥´ê³  있으면 위 ê°’ë“¤ì„ ë¹ ë¥´ê²Œ ì„ íƒí•˜ì‹¤ 수 있습니다."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"시간 ì„ íƒ:\n" + +"- 마우스로 누르면 ì‹œê°„ì´ ì¦ê°€í•©ë‹ˆë‹¤\n" + +"- Shift 키와 함께 누르면 ê°ì†Œí•©ë‹ˆë‹¤\n" + +"- 누른 ìƒíƒœì—ì„œ 마우스를 움ì§ì´ë©´ 좀 ë” ë¹ ë¥´ê²Œ ê°’ì´ ë³€í•©ë‹ˆë‹¤.\n"; + +Calendar._TT["PREV_YEAR"] = "지난 í•´ (길게 누르면 목ë¡)"; +Calendar._TT["PREV_MONTH"] = "지난 달 (길게 누르면 목ë¡)"; +Calendar._TT["GO_TODAY"] = "오늘 날짜로"; +Calendar._TT["NEXT_MONTH"] = "ë‹¤ìŒ ë‹¬ (길게 누르면 목ë¡)"; +Calendar._TT["NEXT_YEAR"] = "ë‹¤ìŒ í•´ (길게 누르면 목ë¡)"; +Calendar._TT["SEL_DATE"] = "날짜를 ì„ íƒí•˜ì„¸ìš”"; +Calendar._TT["DRAG_TO_MOVE"] = "마우스 드래그로 ì´ë™ 하세요"; +Calendar._TT["PART_TODAY"] = " (오늘)"; +Calendar._TT["MON_FIRST"] = "월요ì¼ì„ í•œ ì£¼ì˜ ì‹œìž‘ ìš”ì¼ë¡œ"; +Calendar._TT["SUN_FIRST"] = "ì¼ìš”ì¼ì„ í•œ ì£¼ì˜ ì‹œìž‘ ìš”ì¼ë¡œ"; +Calendar._TT["CLOSE"] = "닫기"; +Calendar._TT["TODAY"] = "오늘"; +Calendar._TT["TIME_PART"] = "(Shift-)í´ë¦­ ë˜ëŠ” 드래그 하세요"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d"; +Calendar._TT["TT_DATE_FORMAT"] = "%b/%e [%a]"; + +Calendar._TT["WK"] = "주"; diff --git a/htdocs/js/jscalendar/lang/calendar-ko.js b/htdocs/js/jscalendar/lang/calendar-ko.js new file mode 100644 index 0000000..8cddf58 --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-ko.js @@ -0,0 +1,120 @@ +// ** I18N + +// Calendar EN language +// Author: Mihai Bazon, +// Translation: Yourim Yi +// Encoding: EUC-KR +// lang : ko +// Distributed under the same terms as the calendar itself. + +// For translators: please use UTF-8 if possible. We strongly believe that +// Unicode is the answer to a real internationalized world. Also please +// include your contact information in the header, as can be seen above. + +// full day names + +Calendar._DN = new Array +("ÀÏ¿äÀÏ", + "¿ù¿äÀÏ", + "È­¿äÀÏ", + "¼ö¿äÀÏ", + "¸ñ¿äÀÏ", + "±Ý¿äÀÏ", + "Åä¿äÀÏ", + "ÀÏ¿äÀÏ"); + +// Please note that the following array of short day names (and the same goes +// for short month names, _SMN) isn't absolutely necessary. We give it here +// for exemplification on how one can customize the short day names, but if +// they are simply the first N letters of the full name you can simply say: +// +// Calendar._SDN_len = N; // short day name length +// Calendar._SMN_len = N; // short month name length +// +// If N = 3 then this is not needed either since we assume a value of 3 if not +// present, to be compatible with translation files that were written before +// this feature. + +// short day names +Calendar._SDN = new Array +("ÀÏ", + "¿ù", + "È­", + "¼ö", + "¸ñ", + "±Ý", + "Åä", + "ÀÏ"); + +// full month names +Calendar._MN = new Array +("1¿ù", + "2¿ù", + "3¿ù", + "4¿ù", + "5¿ù", + "6¿ù", + "7¿ù", + "8¿ù", + "9¿ù", + "10¿ù", + "11¿ù", + "12¿ù"); + +// short month names +Calendar._SMN = new Array +("1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "10", + "11", + "12"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "calendar ¿¡ ´ëÇؼ­"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"\n"+ +"ÃֽŠ¹öÀüÀ» ¹ÞÀ¸½Ã·Á¸é http://www.dynarch.com/projects/calendar/ ¿¡ ¹æ¹®Çϼ¼¿ä\n" + +"\n"+ +"GNU LGPL ¶óÀ̼¾½º·Î ¹èÆ÷µË´Ï´Ù. \n"+ +"¶óÀ̼¾½º¿¡ ´ëÇÑ ÀÚ¼¼ÇÑ ³»¿ëÀº http://gnu.org/licenses/lgpl.html À» ÀÐÀ¸¼¼¿ä." + +"\n\n" + +"³¯Â¥ ¼±ÅÃ:\n" + +"- ¿¬µµ¸¦ ¼±ÅÃÇÏ·Á¸é \xab, \xbb ¹öÆ°À» »ç¿ëÇÕ´Ï´Ù\n" + +"- ´ÞÀ» ¼±ÅÃÇÏ·Á¸é " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " ¹öÆ°À» ´©¸£¼¼¿ä\n" + +"- °è¼Ó ´©¸£°í ÀÖÀ¸¸é À§ °ªµéÀ» ºü¸£°Ô ¼±ÅÃÇÏ½Ç ¼ö ÀÖ½À´Ï´Ù."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"½Ã°£ ¼±ÅÃ:\n" + +"- ¸¶¿ì½º·Î ´©¸£¸é ½Ã°£ÀÌ Áõ°¡ÇÕ´Ï´Ù\n" + +"- Shift Å°¿Í ÇÔ²² ´©¸£¸é °¨¼ÒÇÕ´Ï´Ù\n" + +"- ´©¸¥ »óÅ¿¡¼­ ¸¶¿ì½º¸¦ ¿òÁ÷À̸é Á» ´õ ºü¸£°Ô °ªÀÌ º¯ÇÕ´Ï´Ù.\n"; + +Calendar._TT["PREV_YEAR"] = "Áö³­ ÇØ (±æ°Ô ´©¸£¸é ¸ñ·Ï)"; +Calendar._TT["PREV_MONTH"] = "Áö³­ ´Þ (±æ°Ô ´©¸£¸é ¸ñ·Ï)"; +Calendar._TT["GO_TODAY"] = "¿À´Ã ³¯Â¥·Î"; +Calendar._TT["NEXT_MONTH"] = "´ÙÀ½ ´Þ (±æ°Ô ´©¸£¸é ¸ñ·Ï)"; +Calendar._TT["NEXT_YEAR"] = "´ÙÀ½ ÇØ (±æ°Ô ´©¸£¸é ¸ñ·Ï)"; +Calendar._TT["SEL_DATE"] = "³¯Â¥¸¦ ¼±ÅÃÇϼ¼¿ä"; +Calendar._TT["DRAG_TO_MOVE"] = "¸¶¿ì½º µå·¡±×·Î À̵¿ Çϼ¼¿ä"; +Calendar._TT["PART_TODAY"] = " (¿À´Ã)"; +Calendar._TT["MON_FIRST"] = "¿ù¿äÀÏÀ» ÇÑ ÁÖÀÇ ½ÃÀÛ ¿äÀÏ·Î"; +Calendar._TT["SUN_FIRST"] = "ÀÏ¿äÀÏÀ» ÇÑ ÁÖÀÇ ½ÃÀÛ ¿äÀÏ·Î"; +Calendar._TT["CLOSE"] = "´Ý±â"; +Calendar._TT["TODAY"] = "¿À´Ã"; +Calendar._TT["TIME_PART"] = "(Shift-)Ŭ¸¯ ¶Ç´Â µå·¡±× Çϼ¼¿ä"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d"; +Calendar._TT["TT_DATE_FORMAT"] = "%b/%e [%a]"; + +Calendar._TT["WK"] = "ÁÖ"; diff --git a/htdocs/js/jscalendar/lang/calendar-lt-utf8.js b/htdocs/js/jscalendar/lang/calendar-lt-utf8.js new file mode 100644 index 0000000..d39653b --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-lt-utf8.js @@ -0,0 +1,114 @@ +// ** I18N + +// Calendar LT language +// Author: Martynas Majeris, +// Encoding: UTF-8 +// Distributed under the same terms as the calendar itself. + +// For translators: please use UTF-8 if possible. We strongly believe that +// Unicode is the answer to a real internationalized world. Also please +// include your contact information in the header, as can be seen above. + +// full day names +Calendar._DN = new Array +("Sekmadienis", + "Pirmadienis", + "Antradienis", + "TreÄiadienis", + "Ketvirtadienis", + "Pentadienis", + "Å eÅ¡tadienis", + "Sekmadienis"); + +// Please note that the following array of short day names (and the same goes +// for short month names, _SMN) isn't absolutely necessary. We give it here +// for exemplification on how one can customize the short day names, but if +// they are simply the first N letters of the full name you can simply say: +// +// Calendar._SDN_len = N; // short day name length +// Calendar._SMN_len = N; // short month name length +// +// If N = 3 then this is not needed either since we assume a value of 3 if not +// present, to be compatible with translation files that were written before +// this feature. + +// short day names +Calendar._SDN = new Array +("Sek", + "Pir", + "Ant", + "Tre", + "Ket", + "Pen", + "Å eÅ¡", + "Sek"); + +// full month names +Calendar._MN = new Array +("Sausis", + "Vasaris", + "Kovas", + "Balandis", + "Gegužė", + "Birželis", + "Liepa", + "RugpjÅ«tis", + "RugsÄ—jis", + "Spalis", + "Lapkritis", + "Gruodis"); + +// short month names +Calendar._SMN = new Array +("Sau", + "Vas", + "Kov", + "Bal", + "Geg", + "Bir", + "Lie", + "Rgp", + "Rgs", + "Spa", + "Lap", + "Gru"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "Apie kalendorių"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"NaujausiÄ… versijÄ… rasite: http://www.dynarch.com/projects/calendar/\n" + +"Platinamas pagal GNU LGPL licencijÄ…. Aplankykite http://gnu.org/licenses/lgpl.html" + +"\n\n" + +"Datos pasirinkimas:\n" + +"- Metų pasirinkimas: \xab, \xbb\n" + +"- MÄ—nesio pasirinkimas: " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + "\n" + +"- Nuspauskite ir laikykite pelÄ—s klaviÅ¡Ä… greitesniam pasirinkimui."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Laiko pasirinkimas:\n" + +"- Spustelkite ant valandų arba minuÄių - skaiÄius padidÄ—s vienetu.\n" + +"- Jei spausite kartu su Shift, skaiÄius sumažės.\n" + +"- Greitam pasirinkimui spustelkite ir pajudinkite pelÄ™."; + +Calendar._TT["PREV_YEAR"] = "Ankstesni metai (laikykite, jei norite meniu)"; +Calendar._TT["PREV_MONTH"] = "Ankstesnis mÄ—nuo (laikykite, jei norite meniu)"; +Calendar._TT["GO_TODAY"] = "Pasirinkti Å¡iandienÄ…"; +Calendar._TT["NEXT_MONTH"] = "Kitas mÄ—nuo (laikykite, jei norite meniu)"; +Calendar._TT["NEXT_YEAR"] = "Kiti metai (laikykite, jei norite meniu)"; +Calendar._TT["SEL_DATE"] = "Pasirinkite datÄ…"; +Calendar._TT["DRAG_TO_MOVE"] = "Tempkite"; +Calendar._TT["PART_TODAY"] = " (Å¡iandien)"; +Calendar._TT["MON_FIRST"] = "Pirma savaitÄ—s diena - pirmadienis"; +Calendar._TT["SUN_FIRST"] = "Pirma savaitÄ—s diena - sekmadienis"; +Calendar._TT["CLOSE"] = "Uždaryti"; +Calendar._TT["TODAY"] = "Å iandien"; +Calendar._TT["TIME_PART"] = "Spustelkite arba tempkite jei norite pakeisti"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d"; +Calendar._TT["TT_DATE_FORMAT"] = "%A, %Y-%m-%d"; + +Calendar._TT["WK"] = "sav"; diff --git a/htdocs/js/jscalendar/lang/calendar-lt.js b/htdocs/js/jscalendar/lang/calendar-lt.js new file mode 100644 index 0000000..43b93d6 --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-lt.js @@ -0,0 +1,114 @@ +// ** I18N + +// Calendar LT language +// Author: Martynas Majeris, +// Encoding: Windows-1257 +// Distributed under the same terms as the calendar itself. + +// For translators: please use UTF-8 if possible. We strongly believe that +// Unicode is the answer to a real internationalized world. Also please +// include your contact information in the header, as can be seen above. + +// full day names +Calendar._DN = new Array +("Sekmadienis", + "Pirmadienis", + "Antradienis", + "Treèiadienis", + "Ketvirtadienis", + "Pentadienis", + "Ðeðtadienis", + "Sekmadienis"); + +// Please note that the following array of short day names (and the same goes +// for short month names, _SMN) isn't absolutely necessary. We give it here +// for exemplification on how one can customize the short day names, but if +// they are simply the first N letters of the full name you can simply say: +// +// Calendar._SDN_len = N; // short day name length +// Calendar._SMN_len = N; // short month name length +// +// If N = 3 then this is not needed either since we assume a value of 3 if not +// present, to be compatible with translation files that were written before +// this feature. + +// short day names +Calendar._SDN = new Array +("Sek", + "Pir", + "Ant", + "Tre", + "Ket", + "Pen", + "Ðeð", + "Sek"); + +// full month names +Calendar._MN = new Array +("Sausis", + "Vasaris", + "Kovas", + "Balandis", + "Geguþë", + "Birþelis", + "Liepa", + "Rugpjûtis", + "Rugsëjis", + "Spalis", + "Lapkritis", + "Gruodis"); + +// short month names +Calendar._SMN = new Array +("Sau", + "Vas", + "Kov", + "Bal", + "Geg", + "Bir", + "Lie", + "Rgp", + "Rgs", + "Spa", + "Lap", + "Gru"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "Apie kalendoriø"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"Naujausià versijà rasite: http://www.dynarch.com/projects/calendar/\n" + +"Platinamas pagal GNU LGPL licencijà. Aplankykite http://gnu.org/licenses/lgpl.html" + +"\n\n" + +"Datos pasirinkimas:\n" + +"- Metø pasirinkimas: \xab, \xbb\n" + +"- Mënesio pasirinkimas: " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + "\n" + +"- Nuspauskite ir laikykite pelës klaviðà greitesniam pasirinkimui."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Laiko pasirinkimas:\n" + +"- Spustelkite ant valandø arba minuèiø - skaièus padidës vienetu.\n" + +"- Jei spausite kartu su Shift, skaièius sumaþës.\n" + +"- Greitam pasirinkimui spustelkite ir pajudinkite pelæ."; + +Calendar._TT["PREV_YEAR"] = "Ankstesni metai (laikykite, jei norite meniu)"; +Calendar._TT["PREV_MONTH"] = "Ankstesnis mënuo (laikykite, jei norite meniu)"; +Calendar._TT["GO_TODAY"] = "Pasirinkti ðiandienà"; +Calendar._TT["NEXT_MONTH"] = "Kitas mënuo (laikykite, jei norite meniu)"; +Calendar._TT["NEXT_YEAR"] = "Kiti metai (laikykite, jei norite meniu)"; +Calendar._TT["SEL_DATE"] = "Pasirinkite datà"; +Calendar._TT["DRAG_TO_MOVE"] = "Tempkite"; +Calendar._TT["PART_TODAY"] = " (ðiandien)"; +Calendar._TT["MON_FIRST"] = "Pirma savaitës diena - pirmadienis"; +Calendar._TT["SUN_FIRST"] = "Pirma savaitës diena - sekmadienis"; +Calendar._TT["CLOSE"] = "Uþdaryti"; +Calendar._TT["TODAY"] = "Ðiandien"; +Calendar._TT["TIME_PART"] = "Spustelkite arba tempkite jei norite pakeisti"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d"; +Calendar._TT["TT_DATE_FORMAT"] = "%A, %Y-%m-%d"; + +Calendar._TT["WK"] = "sav"; diff --git a/htdocs/js/jscalendar/lang/calendar-lv.js b/htdocs/js/jscalendar/lang/calendar-lv.js new file mode 100644 index 0000000..407699d --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-lv.js @@ -0,0 +1,123 @@ +// ** I18N + +// Calendar LV language +// Author: Juris Valdovskis, +// Encoding: cp1257 +// Distributed under the same terms as the calendar itself. + +// For translators: please use UTF-8 if possible. We strongly believe that +// Unicode is the answer to a real internationalized world. Also please +// include your contact information in the header, as can be seen above. + +// full day names +Calendar._DN = new Array +("Svçtdiena", + "Pirmdiena", + "Otrdiena", + "Treðdiena", + "Ceturdiena", + "Piektdiena", + "Sestdiena", + "Svçtdiena"); + +// Please note that the following array of short day names (and the same goes +// for short month names, _SMN) isn't absolutely necessary. We give it here +// for exemplification on how one can customize the short day names, but if +// they are simply the first N letters of the full name you can simply say: +// +// Calendar._SDN_len = N; // short day name length +// Calendar._SMN_len = N; // short month name length +// +// If N = 3 then this is not needed either since we assume a value of 3 if not +// present, to be compatible with translation files that were written before +// this feature. + +// short day names +Calendar._SDN = new Array +("Sv", + "Pr", + "Ot", + "Tr", + "Ce", + "Pk", + "Se", + "Sv"); + +// full month names +Calendar._MN = new Array +("Janvâris", + "Februâris", + "Marts", + "Aprîlis", + "Maijs", + "Jûnijs", + "Jûlijs", + "Augusts", + "Septembris", + "Oktobris", + "Novembris", + "Decembris"); + +// short month names +Calendar._SMN = new Array +("Jan", + "Feb", + "Mar", + "Apr", + "Mai", + "Jûn", + "Jûl", + "Aug", + "Sep", + "Okt", + "Nov", + "Dec"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "Par kalendâru"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"For latest version visit: http://www.dynarch.com/projects/calendar/\n" + +"Distributed under GNU LGPL. See http://gnu.org/licenses/lgpl.html for details." + +"\n\n" + +"Datuma izvçle:\n" + +"- Izmanto \xab, \xbb pogas, lai izvçlçtos gadu\n" + +"- Izmanto " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + "pogas, lai izvçlçtos mçnesi\n" + +"- Turi nospiestu peles pogu uz jebkuru no augstâk minçtajâm pogâm, lai paâtrinâtu izvçli."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Laika izvçle:\n" + +"- Uzklikðíini uz jebkuru no laika daïâm, lai palielinâtu to\n" + +"- vai Shift-klikðíis, lai samazinâtu to\n" + +"- vai noklikðíini un velc uz attiecîgo virzienu lai mainîtu âtrâk."; + +Calendar._TT["PREV_YEAR"] = "Iepr. gads (turi izvçlnei)"; +Calendar._TT["PREV_MONTH"] = "Iepr. mçnesis (turi izvçlnei)"; +Calendar._TT["GO_TODAY"] = "Ðodien"; +Calendar._TT["NEXT_MONTH"] = "Nâkoðais mçnesis (turi izvçlnei)"; +Calendar._TT["NEXT_YEAR"] = "Nâkoðais gads (turi izvçlnei)"; +Calendar._TT["SEL_DATE"] = "Izvçlies datumu"; +Calendar._TT["DRAG_TO_MOVE"] = "Velc, lai pârvietotu"; +Calendar._TT["PART_TODAY"] = " (ðodien)"; + +// the following is to inform that "%s" is to be the first day of week +// %s will be replaced with the day name. +Calendar._TT["DAY_FIRST"] = "Attçlot %s kâ pirmo"; + +// This may be locale-dependent. It specifies the week-end days, as an array +// of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1 +// means Monday, etc. +Calendar._TT["WEEKEND"] = "1,7"; + +Calendar._TT["CLOSE"] = "Aizvçrt"; +Calendar._TT["TODAY"] = "Ðodien"; +Calendar._TT["TIME_PART"] = "(Shift-)Klikðíis vai pârvieto, lai mainîtu"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%d-%m-%Y"; +Calendar._TT["TT_DATE_FORMAT"] = "%a, %e %b"; + +Calendar._TT["WK"] = "wk"; +Calendar._TT["TIME"] = "Laiks:"; diff --git a/htdocs/js/jscalendar/lang/calendar-nl.js b/htdocs/js/jscalendar/lang/calendar-nl.js new file mode 100644 index 0000000..a1dea94 --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-nl.js @@ -0,0 +1,73 @@ +// ** I18N +Calendar._DN = new Array +("Zondag", + "Maandag", + "Dinsdag", + "Woensdag", + "Donderdag", + "Vrijdag", + "Zaterdag", + "Zondag"); + +Calendar._SDN_len = 2; + +Calendar._MN = new Array +("Januari", + "Februari", + "Maart", + "April", + "Mei", + "Juni", + "Juli", + "Augustus", + "September", + "Oktober", + "November", + "December"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "Info"; + +Calendar._TT["ABOUT"] = +"DHTML Datum/Tijd Selector\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + +"Ga voor de meest recente versie naar: http://www.dynarch.com/projects/calendar/\n" + +"Verspreid onder de GNU LGPL. Zie http://gnu.org/licenses/lgpl.html voor details." + +"\n\n" + +"Datum selectie:\n" + +"- Gebruik de \xab \xbb knoppen om een jaar te selecteren\n" + +"- Gebruik de " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " knoppen om een maand te selecteren\n" + +"- Houd de muis ingedrukt op de genoemde knoppen voor een snellere selectie."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Tijd selectie:\n" + +"- Klik op een willekeurig onderdeel van het tijd gedeelte om het te verhogen\n" + +"- of Shift-klik om het te verlagen\n" + +"- of klik en sleep voor een snellere selectie."; + +//Calendar._TT["TOGGLE"] = "Selecteer de eerste week-dag"; +Calendar._TT["PREV_YEAR"] = "Vorig jaar (ingedrukt voor menu)"; +Calendar._TT["PREV_MONTH"] = "Vorige maand (ingedrukt voor menu)"; +Calendar._TT["GO_TODAY"] = "Ga naar Vandaag"; +Calendar._TT["NEXT_MONTH"] = "Volgende maand (ingedrukt voor menu)"; +Calendar._TT["NEXT_YEAR"] = "Volgend jaar (ingedrukt voor menu)"; +Calendar._TT["SEL_DATE"] = "Selecteer datum"; +Calendar._TT["DRAG_TO_MOVE"] = "Klik en sleep om te verplaatsen"; +Calendar._TT["PART_TODAY"] = " (vandaag)"; +//Calendar._TT["MON_FIRST"] = "Toon Maandag eerst"; +//Calendar._TT["SUN_FIRST"] = "Toon Zondag eerst"; + +Calendar._TT["DAY_FIRST"] = "Toon %s eerst"; + +Calendar._TT["WEEKEND"] = "0,6"; + +Calendar._TT["CLOSE"] = "Sluiten"; +Calendar._TT["TODAY"] = "(vandaag)"; +Calendar._TT["TIME_PART"] = "(Shift-)Klik of sleep om de waarde te veranderen"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%d-%m-%Y"; +Calendar._TT["TT_DATE_FORMAT"] = "%a, %e %b %Y"; + +Calendar._TT["WK"] = "wk"; +Calendar._TT["TIME"] = "Tijd:"; \ No newline at end of file diff --git a/htdocs/js/jscalendar/lang/calendar-no.js b/htdocs/js/jscalendar/lang/calendar-no.js new file mode 100644 index 0000000..d9297d1 --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-no.js @@ -0,0 +1,114 @@ +// ** I18N + +// Calendar NO language +// Author: Daniel Holmen, +// Encoding: UTF-8 +// Distributed under the same terms as the calendar itself. + +// For translators: please use UTF-8 if possible. We strongly believe that +// Unicode is the answer to a real internationalized world. Also please +// include your contact information in the header, as can be seen above. + +// full day names +Calendar._DN = new Array +("Søndag", + "Mandag", + "Tirsdag", + "Onsdag", + "Torsdag", + "Fredag", + "Lørdag", + "Søndag"); + +// Please note that the following array of short day names (and the same goes +// for short month names, _SMN) isn't absolutely necessary. We give it here +// for exemplification on how one can customize the short day names, but if +// they are simply the first N letters of the full name you can simply say: +// +// Calendar._SDN_len = N; // short day name length +// Calendar._SMN_len = N; // short month name length +// +// If N = 3 then this is not needed either since we assume a value of 3 if not +// present, to be compatible with translation files that were written before +// this feature. + +// short day names +Calendar._SDN = new Array +("Søn", + "Man", + "Tir", + "Ons", + "Tor", + "Fre", + "Lør", + "Søn"); + +// full month names +Calendar._MN = new Array +("Januar", + "Februar", + "Mars", + "April", + "Mai", + "Juni", + "Juli", + "August", + "September", + "Oktober", + "November", + "Desember"); + +// short month names +Calendar._SMN = new Array +("Jan", + "Feb", + "Mar", + "Apr", + "Mai", + "Jun", + "Jul", + "Aug", + "Sep", + "Okt", + "Nov", + "Des"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "Om kalenderen"; + +Calendar._TT["ABOUT"] = +"DHTML Dato-/Tidsvelger\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"For nyeste versjon, gÃ¥ til: http://www.dynarch.com/projects/calendar/\n" + +"Distribuert under GNU LGPL. Se http://gnu.org/licenses/lgpl.html for detaljer." + +"\n\n" + +"Datovalg:\n" + +"- Bruk knappene \xab og \xbb for Ã¥ velge Ã¥r\n" + +"- Bruk knappene " + String.fromCharCode(0x2039) + " og " + String.fromCharCode(0x203a) + " for Ã¥ velge mÃ¥ned\n" + +"- Hold inne musknappen eller knappene over for raskere valg."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Tidsvalg:\n" + +"- Klikk pÃ¥ en av tidsdelene for Ã¥ øke den\n" + +"- eller Shift-klikk for Ã¥ senke verdien\n" + +"- eller klikk-og-dra for raskere valg.."; + +Calendar._TT["PREV_YEAR"] = "Forrige. Ã¥r (hold for meny)"; +Calendar._TT["PREV_MONTH"] = "Forrige. mÃ¥ned (hold for meny)"; +Calendar._TT["GO_TODAY"] = "GÃ¥ til idag"; +Calendar._TT["NEXT_MONTH"] = "Neste mÃ¥ned (hold for meny)"; +Calendar._TT["NEXT_YEAR"] = "Neste Ã¥r (hold for meny)"; +Calendar._TT["SEL_DATE"] = "Velg dato"; +Calendar._TT["DRAG_TO_MOVE"] = "Dra for Ã¥ flytte"; +Calendar._TT["PART_TODAY"] = " (idag)"; +Calendar._TT["MON_FIRST"] = "Vis mandag først"; +Calendar._TT["SUN_FIRST"] = "Vis søndag først"; +Calendar._TT["CLOSE"] = "Lukk"; +Calendar._TT["TODAY"] = "Idag"; +Calendar._TT["TIME_PART"] = "(Shift-)Klikk eller dra for Ã¥ endre verdi"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%d.%m.%Y"; +Calendar._TT["TT_DATE_FORMAT"] = "%a, %b %e"; + +Calendar._TT["WK"] = "uke"; \ No newline at end of file diff --git a/htdocs/js/jscalendar/lang/calendar-pl-utf8.js b/htdocs/js/jscalendar/lang/calendar-pl-utf8.js new file mode 100644 index 0000000..6b8ca67 --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-pl-utf8.js @@ -0,0 +1,93 @@ +// ** I18N + +// Calendar PL language +// Author: Dariusz Pietrzak, +// Author: Janusz Piwowarski, +// Encoding: utf-8 +// Distributed under the same terms as the calendar itself. + +Calendar._DN = new Array +("Niedziela", + "PoniedziaÅ‚ek", + "Wtorek", + "Åšroda", + "Czwartek", + "PiÄ…tek", + "Sobota", + "Niedziela"); +Calendar._SDN = new Array +("Nie", + "Pn", + "Wt", + "Åšr", + "Cz", + "Pt", + "So", + "Nie"); +Calendar._MN = new Array +("StyczeÅ„", + "Luty", + "Marzec", + "KwiecieÅ„", + "Maj", + "Czerwiec", + "Lipiec", + "SierpieÅ„", + "WrzesieÅ„", + "Październik", + "Listopad", + "GrudzieÅ„"); +Calendar._SMN = new Array +("Sty", + "Lut", + "Mar", + "Kwi", + "Maj", + "Cze", + "Lip", + "Sie", + "Wrz", + "Paź", + "Lis", + "Gru"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "O kalendarzu"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"Aby pobrać najnowszÄ… wersjÄ™, odwiedź: http://www.dynarch.com/projects/calendar/\n" + +"DostÄ™pny na licencji GNU LGPL. Zobacz szczegóły na http://gnu.org/licenses/lgpl.html." + +"\n\n" + +"Wybór daty:\n" + +"- Użyj przycisków \xab, \xbb by wybrać rok\n" + +"- Użyj przycisków " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " by wybrać miesiÄ…c\n" + +"- Przytrzymaj klawisz myszy nad jednym z powyższych przycisków dla szybszego wyboru."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Wybór czasu:\n" + +"- Kliknij na jednym z pól czasu by zwiÄ™kszyć jego wartość\n" + +"- lub kliknij trzymajÄ…c Shift by zmiejszyć jego wartość\n" + +"- lub kliknij i przeciÄ…gnij dla szybszego wyboru."; + +//Calendar._TT["TOGGLE"] = "ZmieÅ„ pierwszy dzieÅ„ tygodnia"; +Calendar._TT["PREV_YEAR"] = "Poprzedni rok (przytrzymaj dla menu)"; +Calendar._TT["PREV_MONTH"] = "Poprzedni miesiÄ…c (przytrzymaj dla menu)"; +Calendar._TT["GO_TODAY"] = "Idź do dzisiaj"; +Calendar._TT["NEXT_MONTH"] = "NastÄ™pny miesiÄ…c (przytrzymaj dla menu)"; +Calendar._TT["NEXT_YEAR"] = "NastÄ™pny rok (przytrzymaj dla menu)"; +Calendar._TT["SEL_DATE"] = "Wybierz datÄ™"; +Calendar._TT["DRAG_TO_MOVE"] = "PrzeciÄ…gnij by przesunąć"; +Calendar._TT["PART_TODAY"] = " (dzisiaj)"; +Calendar._TT["MON_FIRST"] = "WyÅ›wietl poniedziaÅ‚ek jako pierwszy"; +Calendar._TT["SUN_FIRST"] = "WyÅ›wietl niedzielÄ™ jako pierwszÄ…"; +Calendar._TT["CLOSE"] = "Zamknij"; +Calendar._TT["TODAY"] = "Dzisiaj"; +Calendar._TT["TIME_PART"] = "(Shift-)Kliknij lub przeciÄ…gnij by zmienić wartość"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d"; +Calendar._TT["TT_DATE_FORMAT"] = "%e %B, %A"; + +Calendar._TT["WK"] = "ty"; diff --git a/htdocs/js/jscalendar/lang/calendar-pl.js b/htdocs/js/jscalendar/lang/calendar-pl.js new file mode 100644 index 0000000..76e0551 --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-pl.js @@ -0,0 +1,56 @@ +// ** I18N +// Calendar PL language +// Author: Artur Filipiak, +// January, 2004 +// Encoding: UTF-8 +Calendar._DN = new Array +("Niedziela", "PoniedziaÅ‚ek", "Wtorek", "Åšroda", "Czwartek", "PiÄ…tek", "Sobota", "Niedziela"); + +Calendar._SDN = new Array +("N", "Pn", "Wt", "Åšr", "Cz", "Pt", "So", "N"); + +Calendar._MN = new Array +("StyczeÅ„", "Luty", "Marzec", "KwiecieÅ„", "Maj", "Czerwiec", "Lipiec", "SierpieÅ„", "WrzesieÅ„", "Październik", "Listopad", "GrudzieÅ„"); + +Calendar._SMN = new Array +("Sty", "Lut", "Mar", "Kwi", "Maj", "Cze", "Lip", "Sie", "Wrz", "Paź", "Lis", "Gru"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "O kalendarzu"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"For latest version visit: http://www.dynarch.com/projects/calendar/\n" + +"Distributed under GNU LGPL. See http://gnu.org/licenses/lgpl.html for details." + +"\n\n" + +"Wybór daty:\n" + +"- aby wybrać rok użyj przycisków \xab, \xbb\n" + +"- aby wybrać miesiÄ…c użyj przycisków " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + "\n" + +"- aby przyspieszyć wybór przytrzymaj wciÅ›niÄ™ty przycisk myszy nad ww. przyciskami."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Wybór czasu:\n" + +"- aby zwiÄ™kszyć wartość kliknij na dowolnym elemencie selekcji czasu\n" + +"- aby zmniejszyć wartość użyj dodatkowo klawisza Shift\n" + +"- możesz również poruszać myszkÄ™ w lewo i prawo wraz z wciÅ›niÄ™tym lewym klawiszem."; + +Calendar._TT["PREV_YEAR"] = "Poprz. rok (przytrzymaj dla menu)"; +Calendar._TT["PREV_MONTH"] = "Poprz. miesiÄ…c (przytrzymaj dla menu)"; +Calendar._TT["GO_TODAY"] = "Pokaż dziÅ›"; +Calendar._TT["NEXT_MONTH"] = "Nast. miesiÄ…c (przytrzymaj dla menu)"; +Calendar._TT["NEXT_YEAR"] = "Nast. rok (przytrzymaj dla menu)"; +Calendar._TT["SEL_DATE"] = "Wybierz datÄ™"; +Calendar._TT["DRAG_TO_MOVE"] = "PrzesuÅ„ okienko"; +Calendar._TT["PART_TODAY"] = " (dziÅ›)"; +Calendar._TT["MON_FIRST"] = "Pokaż PoniedziaÅ‚ek jako pierwszy"; +Calendar._TT["SUN_FIRST"] = "Pokaż NiedzielÄ™ jako pierwszÄ…"; +Calendar._TT["CLOSE"] = "Zamknij"; +Calendar._TT["TODAY"] = "DziÅ›"; +Calendar._TT["TIME_PART"] = "(Shift-)klik | drag, aby zmienić wartość"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%Y.%m.%d"; +Calendar._TT["TT_DATE_FORMAT"] = "%a, %b %e"; + +Calendar._TT["WK"] = "wk"; \ No newline at end of file diff --git a/htdocs/js/jscalendar/lang/calendar-pt.js b/htdocs/js/jscalendar/lang/calendar-pt.js new file mode 100644 index 0000000..deee8a1 --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-pt.js @@ -0,0 +1,123 @@ +// ** I18N + +// Calendar pt_BR language +// Author: Adalberto Machado, +// Encoding: any +// Distributed under the same terms as the calendar itself. + +// For translators: please use UTF-8 if possible. We strongly believe that +// Unicode is the answer to a real internationalized world. Also please +// include your contact information in the header, as can be seen above. + +// full day names +Calendar._DN = new Array +("Domingo", + "Segunda", + "Terca", + "Quarta", + "Quinta", + "Sexta", + "Sabado", + "Domingo"); + +// Please note that the following array of short day names (and the same goes +// for short month names, _SMN) isn't absolutely necessary. We give it here +// for exemplification on how one can customize the short day names, but if +// they are simply the first N letters of the full name you can simply say: +// +// Calendar._SDN_len = N; // short day name length +// Calendar._SMN_len = N; // short month name length +// +// If N = 3 then this is not needed either since we assume a value of 3 if not +// present, to be compatible with translation files that were written before +// this feature. + +// short day names +Calendar._SDN = new Array +("Dom", + "Seg", + "Ter", + "Qua", + "Qui", + "Sex", + "Sab", + "Dom"); + +// full month names +Calendar._MN = new Array +("Janeiro", + "Fevereiro", + "Marco", + "Abril", + "Maio", + "Junho", + "Julho", + "Agosto", + "Setembro", + "Outubro", + "Novembro", + "Dezembro"); + +// short month names +Calendar._SMN = new Array +("Jan", + "Fev", + "Mar", + "Abr", + "Mai", + "Jun", + "Jul", + "Ago", + "Set", + "Out", + "Nov", + "Dez"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "Sobre o calendario"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"Ultima versao visite: http://www.dynarch.com/projects/calendar/\n" + +"Distribuido sobre GNU LGPL. Veja http://gnu.org/licenses/lgpl.html para detalhes." + +"\n\n" + +"Selecao de data:\n" + +"- Use os botoes \xab, \xbb para selecionar o ano\n" + +"- Use os botoes " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " para selecionar o mes\n" + +"- Segure o botao do mouse em qualquer um desses botoes para selecao rapida."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Selecao de hora:\n" + +"- Clique em qualquer parte da hora para incrementar\n" + +"- ou Shift-click para decrementar\n" + +"- ou clique e segure para selecao rapida."; + +Calendar._TT["PREV_YEAR"] = "Ant. ano (segure para menu)"; +Calendar._TT["PREV_MONTH"] = "Ant. mes (segure para menu)"; +Calendar._TT["GO_TODAY"] = "Hoje"; +Calendar._TT["NEXT_MONTH"] = "Prox. mes (segure para menu)"; +Calendar._TT["NEXT_YEAR"] = "Prox. ano (segure para menu)"; +Calendar._TT["SEL_DATE"] = "Selecione a data"; +Calendar._TT["DRAG_TO_MOVE"] = "Arraste para mover"; +Calendar._TT["PART_TODAY"] = " (hoje)"; + +// the following is to inform that "%s" is to be the first day of week +// %s will be replaced with the day name. +Calendar._TT["DAY_FIRST"] = "Mostre %s primeiro"; + +// This may be locale-dependent. It specifies the week-end days, as an array +// of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1 +// means Monday, etc. +Calendar._TT["WEEKEND"] = "0,6"; + +Calendar._TT["CLOSE"] = "Fechar"; +Calendar._TT["TODAY"] = "Hoje"; +Calendar._TT["TIME_PART"] = "(Shift-)Click ou arraste para mudar valor"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%d/%m/%Y"; +Calendar._TT["TT_DATE_FORMAT"] = "%a, %e %b"; + +Calendar._TT["WK"] = "sm"; +Calendar._TT["TIME"] = "Hora:"; diff --git a/htdocs/js/jscalendar/lang/calendar-ro.js b/htdocs/js/jscalendar/lang/calendar-ro.js new file mode 100644 index 0000000..116e358 --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-ro.js @@ -0,0 +1,66 @@ +// ** I18N +Calendar._DN = new Array +("Duminică", + "Luni", + "MarÅ£i", + "Miercuri", + "Joi", + "Vineri", + "Sâmbătă", + "Duminică"); +Calendar._SDN_len = 2; +Calendar._MN = new Array +("Ianuarie", + "Februarie", + "Martie", + "Aprilie", + "Mai", + "Iunie", + "Iulie", + "August", + "Septembrie", + "Octombrie", + "Noiembrie", + "Decembrie"); + +// tooltips +Calendar._TT = {}; + +Calendar._TT["INFO"] = "Despre calendar"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"Pentru ultima versiune vizitaÅ£i: http://www.dynarch.com/projects/calendar/\n" + +"Distribuit sub GNU LGPL. See http://gnu.org/licenses/lgpl.html for details." + +"\n\n" + +"SelecÅ£ia datei:\n" + +"- FolosiÅ£i butoanele \xab, \xbb pentru a selecta anul\n" + +"- FolosiÅ£i butoanele " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " pentru a selecta luna\n" + +"- TineÅ£i butonul mouse-ului apăsat pentru selecÅ£ie mai rapidă."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"SelecÅ£ia orei:\n" + +"- Click pe ora sau minut pentru a mări valoarea cu 1\n" + +"- Sau Shift-Click pentru a micÅŸora valoarea cu 1\n" + +"- Sau Click ÅŸi drag pentru a selecta mai repede."; + +Calendar._TT["PREV_YEAR"] = "Anul precedent (lung pt menu)"; +Calendar._TT["PREV_MONTH"] = "Luna precedentă (lung pt menu)"; +Calendar._TT["GO_TODAY"] = "Data de azi"; +Calendar._TT["NEXT_MONTH"] = "Luna următoare (lung pt menu)"; +Calendar._TT["NEXT_YEAR"] = "Anul următor (lung pt menu)"; +Calendar._TT["SEL_DATE"] = "Selectează data"; +Calendar._TT["DRAG_TO_MOVE"] = "Trage pentru a miÅŸca"; +Calendar._TT["PART_TODAY"] = " (astăzi)"; +Calendar._TT["DAY_FIRST"] = "AfiÅŸează %s prima zi"; +Calendar._TT["WEEKEND"] = "0,6"; +Calendar._TT["CLOSE"] = "ÃŽnchide"; +Calendar._TT["TODAY"] = "Astăzi"; +Calendar._TT["TIME_PART"] = "(Shift-)Click sau drag pentru a selecta"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%d-%m-%Y"; +Calendar._TT["TT_DATE_FORMAT"] = "%A, %d %B"; + +Calendar._TT["WK"] = "spt"; +Calendar._TT["TIME"] = "Ora:"; diff --git a/htdocs/js/jscalendar/lang/calendar-ru.js b/htdocs/js/jscalendar/lang/calendar-ru.js new file mode 100644 index 0000000..9f75a6a --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-ru.js @@ -0,0 +1,123 @@ +// ** I18N + +// Calendar RU language +// Translation: Sly Golovanov, http://golovanov.net, +// Encoding: any +// Distributed under the same terms as the calendar itself. + +// For translators: please use UTF-8 if possible. We strongly believe that +// Unicode is the answer to a real internationalized world. Also please +// include your contact information in the header, as can be seen above. + +// full day names +Calendar._DN = new Array +("воÑкреÑенье", + "понедельник", + "вторник", + "Ñреда", + "четверг", + "пÑтница", + "Ñуббота", + "воÑкреÑенье"); + +// Please note that the following array of short day names (and the same goes +// for short month names, _SMN) isn't absolutely necessary. We give it here +// for exemplification on how one can customize the short day names, but if +// they are simply the first N letters of the full name you can simply say: +// +// Calendar._SDN_len = N; // short day name length +// Calendar._SMN_len = N; // short month name length +// +// If N = 3 then this is not needed either since we assume a value of 3 if not +// present, to be compatible with translation files that were written before +// this feature. + +// short day names +Calendar._SDN = new Array +("вÑк", + "пон", + "втр", + "Ñрд", + "чет", + "пÑÑ‚", + "Ñуб", + "вÑк"); + +// full month names +Calendar._MN = new Array +("Ñнварь", + "февраль", + "март", + "апрель", + "май", + "июнь", + "июль", + "авгуÑÑ‚", + "ÑентÑбрь", + "октÑбрь", + "ноÑбрь", + "декабрь"); + +// short month names +Calendar._SMN = new Array +("Ñнв", + "фев", + "мар", + "апр", + "май", + "июн", + "июл", + "авг", + "Ñен", + "окт", + "ноÑ", + "дек"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "О календаре..."; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"For latest version visit: http://www.dynarch.com/projects/calendar/\n" + +"Distributed under GNU LGPL. See http://gnu.org/licenses/lgpl.html for details." + +"\n\n" + +"Как выбрать дату:\n" + +"- При помощи кнопок \xab, \xbb можно выбрать год\n" + +"- При помощи кнопок " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " можно выбрать меÑÑц\n" + +"- Подержите Ñти кнопки нажатыми, чтобы поÑвилоÑÑŒ меню быÑтрого выбора."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Как выбрать времÑ:\n" + +"- При клике на чаÑах или минутах они увеличиваютÑÑ\n" + +"- при клике Ñ Ð½Ð°Ð¶Ð°Ñ‚Ð¾Ð¹ клавишей Shift они уменьшаютÑÑ\n" + +"- еÑли нажать и двигать мышкой влево/вправо, они будут менÑÑ‚ÑŒÑÑ Ð±Ñ‹Ñтрее."; + +Calendar._TT["PREV_YEAR"] = "Ðа год назад (удерживать Ð´Ð»Ñ Ð¼ÐµÐ½ÑŽ)"; +Calendar._TT["PREV_MONTH"] = "Ðа меÑÑц назад (удерживать Ð´Ð»Ñ Ð¼ÐµÐ½ÑŽ)"; +Calendar._TT["GO_TODAY"] = "СегоднÑ"; +Calendar._TT["NEXT_MONTH"] = "Ðа меÑÑц вперед (удерживать Ð´Ð»Ñ Ð¼ÐµÐ½ÑŽ)"; +Calendar._TT["NEXT_YEAR"] = "Ðа год вперед (удерживать Ð´Ð»Ñ Ð¼ÐµÐ½ÑŽ)"; +Calendar._TT["SEL_DATE"] = "Выберите дату"; +Calendar._TT["DRAG_TO_MOVE"] = "ПеретаÑкивайте мышкой"; +Calendar._TT["PART_TODAY"] = " (ÑегоднÑ)"; + +// the following is to inform that "%s" is to be the first day of week +// %s will be replaced with the day name. +Calendar._TT["DAY_FIRST"] = "Первый день недели будет %s"; + +// This may be locale-dependent. It specifies the week-end days, as an array +// of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1 +// means Monday, etc. +Calendar._TT["WEEKEND"] = "0,6"; + +Calendar._TT["CLOSE"] = "Закрыть"; +Calendar._TT["TODAY"] = "СегоднÑ"; +Calendar._TT["TIME_PART"] = "(Shift-)клик или нажать и двигать"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d"; +Calendar._TT["TT_DATE_FORMAT"] = "%e %b, %a"; + +Calendar._TT["WK"] = "нед"; +Calendar._TT["TIME"] = "ВремÑ:"; diff --git a/htdocs/js/jscalendar/lang/calendar-ru_win_.js b/htdocs/js/jscalendar/lang/calendar-ru_win_.js new file mode 100644 index 0000000..de455af --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-ru_win_.js @@ -0,0 +1,123 @@ +// ** I18N + +// Calendar RU language +// Translation: Sly Golovanov, http://golovanov.net, +// Encoding: any +// Distributed under the same terms as the calendar itself. + +// For translators: please use UTF-8 if possible. We strongly believe that +// Unicode is the answer to a real internationalized world. Also please +// include your contact information in the header, as can be seen above. + +// full day names +Calendar._DN = new Array +("âîñêðåñåíüå", + "ïîíåäåëüíèê", + "âòîðíèê", + "ñðåäà", + "÷åòâåðã", + "ïÿòíèöà", + "ñóááîòà", + "âîñêðåñåíüå"); + +// Please note that the following array of short day names (and the same goes +// for short month names, _SMN) isn't absolutely necessary. We give it here +// for exemplification on how one can customize the short day names, but if +// they are simply the first N letters of the full name you can simply say: +// +// Calendar._SDN_len = N; // short day name length +// Calendar._SMN_len = N; // short month name length +// +// If N = 3 then this is not needed either since we assume a value of 3 if not +// present, to be compatible with translation files that were written before +// this feature. + +// short day names +Calendar._SDN = new Array +("âñê", + "ïîí", + "âòð", + "ñðä", + "÷åò", + "ïÿò", + "ñóá", + "âñê"); + +// full month names +Calendar._MN = new Array +("ÿíâàðü", + "ôåâðàëü", + "ìàðò", + "àïðåëü", + "ìàé", + "èþíü", + "èþëü", + "àâãóñò", + "ñåíòÿáðü", + "îêòÿáðü", + "íîÿáðü", + "äåêàáðü"); + +// short month names +Calendar._SMN = new Array +("ÿíâ", + "ôåâ", + "ìàð", + "àïð", + "ìàé", + "èþí", + "èþë", + "àâã", + "ñåí", + "îêò", + "íîÿ", + "äåê"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "Î êàëåíäàðå..."; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"For latest version visit: http://www.dynarch.com/projects/calendar/\n" + +"Distributed under GNU LGPL. See http://gnu.org/licenses/lgpl.html for details." + +"\n\n" + +"Êàê âûáðàòü äàòó:\n" + +"- Ïðè ïîìîùè êíîïîê \xab, \xbb ìîæíî âûáðàòü ãîä\n" + +"- Ïðè ïîìîùè êíîïîê " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " ìîæíî âûáðàòü ìåñÿö\n" + +"- Ïîäåðæèòå ýòè êíîïêè íàæàòûìè, ÷òîáû ïîÿâèëîñü ìåíþ áûñòðîãî âûáîðà."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Êàê âûáðàòü âðåìÿ:\n" + +"- Ïðè êëèêå íà ÷àñàõ èëè ìèíóòàõ îíè óâåëè÷èâàþòñÿ\n" + +"- ïðè êëèêå ñ íàæàòîé êëàâèøåé Shift îíè óìåíüøàþòñÿ\n" + +"- åñëè íàæàòü è äâèãàòü ìûøêîé âëåâî/âïðàâî, îíè áóäóò ìåíÿòüñÿ áûñòðåå."; + +Calendar._TT["PREV_YEAR"] = "Íà ãîä íàçàä (óäåðæèâàòü äëÿ ìåíþ)"; +Calendar._TT["PREV_MONTH"] = "Íà ìåñÿö íàçàä (óäåðæèâàòü äëÿ ìåíþ)"; +Calendar._TT["GO_TODAY"] = "Ñåãîäíÿ"; +Calendar._TT["NEXT_MONTH"] = "Íà ìåñÿö âïåðåä (óäåðæèâàòü äëÿ ìåíþ)"; +Calendar._TT["NEXT_YEAR"] = "Íà ãîä âïåðåä (óäåðæèâàòü äëÿ ìåíþ)"; +Calendar._TT["SEL_DATE"] = "Âûáåðèòå äàòó"; +Calendar._TT["DRAG_TO_MOVE"] = "Ïåðåòàñêèâàéòå ìûøêîé"; +Calendar._TT["PART_TODAY"] = " (ñåãîäíÿ)"; + +// the following is to inform that "%s" is to be the first day of week +// %s will be replaced with the day name. +Calendar._TT["DAY_FIRST"] = "Ïåðâûé äåíü íåäåëè áóäåò %s"; + +// This may be locale-dependent. It specifies the week-end days, as an array +// of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1 +// means Monday, etc. +Calendar._TT["WEEKEND"] = "0,6"; + +Calendar._TT["CLOSE"] = "Çàêðûòü"; +Calendar._TT["TODAY"] = "Ñåãîäíÿ"; +Calendar._TT["TIME_PART"] = "(Shift-)êëèê èëè íàæàòü è äâèãàòü"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d"; +Calendar._TT["TT_DATE_FORMAT"] = "%e %b, %a"; + +Calendar._TT["WK"] = "íåä"; +Calendar._TT["TIME"] = "Âðåìÿ:"; diff --git a/htdocs/js/jscalendar/lang/calendar-si.js b/htdocs/js/jscalendar/lang/calendar-si.js new file mode 100644 index 0000000..cb3dfb9 --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-si.js @@ -0,0 +1,94 @@ +/* Slovenian language file for the DHTML Calendar version 0.9.2 +* Author David Milost , January 2004. +* Feel free to use this script under the terms of the GNU Lesser General +* Public License, as long as you do not remove or alter this notice. +*/ + // full day names +Calendar._DN = new Array +("Nedelja", + "Ponedeljek", + "Torek", + "Sreda", + "ÄŒetrtek", + "Petek", + "Sobota", + "Nedelja"); + // short day names + Calendar._SDN = new Array +("Ned", + "Pon", + "Tor", + "Sre", + "ÄŒet", + "Pet", + "Sob", + "Ned"); +// short month names +Calendar._SMN = new Array +("Jan", + "Feb", + "Mar", + "Apr", + "Maj", + "Jun", + "Jul", + "Avg", + "Sep", + "Okt", + "Nov", + "Dec"); + // full month names +Calendar._MN = new Array +("Januar", + "Februar", + "Marec", + "April", + "Maj", + "Junij", + "Julij", + "Avgust", + "September", + "Oktober", + "November", + "December"); + +// tooltips +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "O koledarju"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"Za zadnjo verzijo pojdine na naslov: http://www.dynarch.com/projects/calendar/\n" + +"Distribuirano pod GNU LGPL. Poglejte http://gnu.org/licenses/lgpl.html za podrobnosti." + +"\n\n" + +"Izbor datuma:\n" + +"- Uporabite \xab, \xbb gumbe za izbor leta\n" + +"- Uporabite " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " gumbe za izbor meseca\n" + +"- Zadržite klik na kateremkoli od zgornjih gumbov za hiter izbor."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Izbor ćasa:\n" + +"- Kliknite na katerikoli del ćasa za poveć. le-tega\n" + +"- ali Shift-click za zmanj. le-tega\n" + +"- ali kliknite in povlecite za hiter izbor."; + +Calendar._TT["TOGGLE"] = "Spremeni dan s katerim se prićne teden"; +Calendar._TT["PREV_YEAR"] = "Predhodnje leto (dolg klik za meni)"; +Calendar._TT["PREV_MONTH"] = "Predhodnji mesec (dolg klik za meni)"; +Calendar._TT["GO_TODAY"] = "Pojdi na tekoći dan"; +Calendar._TT["NEXT_MONTH"] = "Naslednji mesec (dolg klik za meni)"; +Calendar._TT["NEXT_YEAR"] = "Naslednje leto (dolg klik za meni)"; +Calendar._TT["SEL_DATE"] = "Izberite datum"; +Calendar._TT["DRAG_TO_MOVE"] = "Pritisni in povleci za spremembo pozicije"; +Calendar._TT["PART_TODAY"] = " (danes)"; +Calendar._TT["MON_FIRST"] = "Prikaži ponedeljek kot prvi dan"; +Calendar._TT["SUN_FIRST"] = "Prikaži nedeljo kot prvi dan"; +Calendar._TT["CLOSE"] = "Zapri"; +Calendar._TT["TODAY"] = "Danes"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d"; +Calendar._TT["TT_DATE_FORMAT"] = "%a, %b %e"; + +Calendar._TT["WK"] = "Ted"; \ No newline at end of file diff --git a/htdocs/js/jscalendar/lang/calendar-sk.js b/htdocs/js/jscalendar/lang/calendar-sk.js new file mode 100644 index 0000000..4fe6a3c --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-sk.js @@ -0,0 +1,99 @@ +// ** I18N + +// Calendar SK language +// Author: Peter Valach (pvalach@gmx.net) +// Encoding: utf-8 +// Last update: 2003/10/29 +// Distributed under the same terms as the calendar itself. + +// full day names +Calendar._DN = new Array +("NedeÄľa", + "Pondelok", + "Utorok", + "Streda", + "Ĺ tvrtok", + "Piatok", + "Sobota", + "NedeÄľa"); + +// short day names +Calendar._SDN = new Array +("Ned", + "Pon", + "Uto", + "Str", + "Ĺ tv", + "Pia", + "Sob", + "Ned"); + +// full month names +Calendar._MN = new Array +("Január", + "Február", + "Marec", + "AprĂ­l", + "Máj", + "JÄ‚ÅŸn", + "JÄ‚ÅŸl", + "August", + "September", + "OktÄ‚Å‚ber", + "November", + "December"); + +// short month names +Calendar._SMN = new Array +("Jan", + "Feb", + "Mar", + "Apr", + "Máj", + "JÄ‚ÅŸn", + "JÄ‚ÅŸl", + "Aug", + "Sep", + "Okt", + "Nov", + "Dec"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "O kalendári"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + +"PoslednÄ‚ÅŸ verziu nájdete na: http://www.dynarch.com/projects/calendar/\n" + +"DistribuovanĂ© pod GNU LGPL. ViÄŹ http://gnu.org/licenses/lgpl.html pre detaily." + +"\n\n" + +"VÄ‚Ëber dátumu:\n" + +"- PouĹľite tlaÄŤidlá \xab, \xbb pre vÄ‚Ëber roku\n" + +"- PouĹľite tlaÄŤidlá " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " pre vÄ‚Ëber mesiaca\n" + +"- Ak ktorĂ©koÄľvek z tÄ‚Ëchto tlaÄŤidiel podržíte dlhšie, zobrazĂ­ sa rÄ‚Ëchly vÄ‚Ëber."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"VÄ‚Ëber ÄŤasu:\n" + +"- Kliknutie na niektorÄ‚ÅŸ poloĹľku ÄŤasu ju zvÄ‚Ëši\n" + +"- Shift-klik ju znĂ­Ĺľi\n" + +"- Ak podržíte tlaÄŤĂ­tko stlaÄŤenĂ©, posÄ‚ÅŸvanĂ­m menĂ­te hodnotu."; + +Calendar._TT["PREV_YEAR"] = "PredošlÄ‚Ë rok (podrĹľte pre menu)"; +Calendar._TT["PREV_MONTH"] = "PredošlÄ‚Ë mesiac (podrĹľte pre menu)"; +Calendar._TT["GO_TODAY"] = "PrejsĹĄ na dnešok"; +Calendar._TT["NEXT_MONTH"] = "Nasl. mesiac (podrĹľte pre menu)"; +Calendar._TT["NEXT_YEAR"] = "Nasl. rok (podrĹľte pre menu)"; +Calendar._TT["SEL_DATE"] = "ZvoÄľte dátum"; +Calendar._TT["DRAG_TO_MOVE"] = "PodrĹľanĂ­m tlaÄŤĂ­tka zmenĂ­te polohu"; +Calendar._TT["PART_TODAY"] = " (dnes)"; +Calendar._TT["MON_FIRST"] = "ZobraziĹĄ pondelok ako prvÄ‚Ë"; +Calendar._TT["SUN_FIRST"] = "ZobraziĹĄ nedeÄľu ako prvÄ‚ÅŸ"; +Calendar._TT["CLOSE"] = "ZavrieĹĄ"; +Calendar._TT["TODAY"] = "Dnes"; +Calendar._TT["TIME_PART"] = "(Shift-)klik/ĹĄahanie zmenĂ­ hodnotu"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "$d. %m. %Y"; +Calendar._TT["TT_DATE_FORMAT"] = "%a, %e. %b"; + +Calendar._TT["WK"] = "tÄ‚ËĹľ"; diff --git a/htdocs/js/jscalendar/lang/calendar-sp.js b/htdocs/js/jscalendar/lang/calendar-sp.js new file mode 100644 index 0000000..239d1b3 --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-sp.js @@ -0,0 +1,110 @@ +// ** I18N + +// Calendar SP language +// Author: Rafael Velasco +// Encoding: any +// Distributed under the same terms as the calendar itself. + +// For translators: please use UTF-8 if possible. We strongly believe that +// Unicode is the answer to a real internationalized world. Also please +// include your contact information in the header, as can be seen above. + +// full day names +Calendar._DN = new Array +("Domingo", + "Lunes", + "Martes", + "Miercoles", + "Jueves", + "Viernes", + "Sabado", + "Domingo"); + +Calendar._SDN = new Array +("Dom", + "Lun", + "Mar", + "Mie", + "Jue", + "Vie", + "Sab", + "Dom"); + +// full month names +Calendar._MN = new Array +("Enero", + "Febrero", + "Marzo", + "Abril", + "Mayo", + "Junio", + "Julio", + "Agosto", + "Septiembre", + "Octubre", + "Noviembre", + "Diciembre"); + +// short month names +Calendar._SMN = new Array +("Ene", + "Feb", + "Mar", + "Abr", + "May", + "Jun", + "Jul", + "Ago", + "Sep", + "Oct", + "Nov", + "Dic"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "Información del Calendario"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"Nuevas versiones en: http://www.dynarch.com/projects/calendar/\n" + +"Distribuida bajo licencia GNU LGPL. Para detalles vea http://gnu.org/licenses/lgpl.html ." + +"\n\n" + +"Selección de Fechas:\n" + +"- Use \xab, \xbb para seleccionar el año\n" + +"- Use " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " para seleccionar el mes\n" + +"- Mantenga presionado el botón del ratón en cualquiera de las opciones superiores para un acceso rapido ."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Selección del Reloj:\n" + +"- Seleccione la hora para cambiar el reloj\n" + +"- o presione Shift-click para disminuirlo\n" + +"- o presione click y arrastre del ratón para una selección rapida."; + +Calendar._TT["PREV_YEAR"] = "Año anterior (Presione para menu)"; +Calendar._TT["PREV_MONTH"] = "Mes Anterior (Presione para menu)"; +Calendar._TT["GO_TODAY"] = "Ir a Hoy"; +Calendar._TT["NEXT_MONTH"] = "Mes Siguiente (Presione para menu)"; +Calendar._TT["NEXT_YEAR"] = "Año Siguiente (Presione para menu)"; +Calendar._TT["SEL_DATE"] = "Seleccione fecha"; +Calendar._TT["DRAG_TO_MOVE"] = "Arrastre y mueva"; +Calendar._TT["PART_TODAY"] = " (Hoy)"; + +// the following is to inform that "%s" is to be the first day of week +// %s will be replaced with the day name. +Calendar._TT["DAY_FIRST"] = "Mostrar %s primero"; + +// This may be locale-dependent. It specifies the week-end days, as an array +// of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1 +// means Monday, etc. +Calendar._TT["WEEKEND"] = "0,6"; + +Calendar._TT["CLOSE"] = "Cerrar"; +Calendar._TT["TODAY"] = "Hoy"; +Calendar._TT["TIME_PART"] = "(Shift-)Click o arrastra para cambar el valor"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%dd-%mm-%yy"; +Calendar._TT["TT_DATE_FORMAT"] = "%A, %e de %B de %Y"; + +Calendar._TT["WK"] = "Sm"; +Calendar._TT["TIME"] = "Hora:"; diff --git a/htdocs/js/jscalendar/lang/calendar-sv.js b/htdocs/js/jscalendar/lang/calendar-sv.js new file mode 100644 index 0000000..db1f4b8 --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-sv.js @@ -0,0 +1,93 @@ +// ** I18N + +// Calendar SV language (Swedish, svenska) +// Author: Mihai Bazon, +// Translation team: +// Translator: Leonard Norrgård +// Last translator: Leonard Norrgård +// Encoding: iso-latin-1 +// Distributed under the same terms as the calendar itself. + +// For translators: please use UTF-8 if possible. We strongly believe that +// Unicode is the answer to a real internationalized world. Also please +// include your contact information in the header, as can be seen above. + +// full day names +Calendar._DN = new Array +("söndag", + "måndag", + "tisdag", + "onsdag", + "torsdag", + "fredag", + "lördag", + "söndag"); + +// Please note that the following array of short day names (and the same goes +// for short month names, _SMN) isn't absolutely necessary. We give it here +// for exemplification on how one can customize the short day names, but if +// they are simply the first N letters of the full name you can simply say: +// +// Calendar._SDN_len = N; // short day name length +// Calendar._SMN_len = N; // short month name length +// +// If N = 3 then this is not needed either since we assume a value of 3 if not +// present, to be compatible with translation files that were written before +// this feature. +Calendar._SDN_len = 2; +Calendar._SMN_len = 3; + +// full month names +Calendar._MN = new Array +("januari", + "februari", + "mars", + "april", + "maj", + "juni", + "juli", + "augusti", + "september", + "oktober", + "november", + "december"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "Om kalendern"; + +Calendar._TT["ABOUT"] = +"DHTML Datum/tid-väljare\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"För senaste version gå till: http://www.dynarch.com/projects/calendar/\n" + +"Distribueras under GNU LGPL. Se http://gnu.org/licenses/lgpl.html för detaljer." + +"\n\n" + +"Val av datum:\n" + +"- Använd knapparna \xab, \xbb för att välja år\n" + +"- Använd knapparna " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " för att välja månad\n" + +"- Håll musknappen nedtryckt på någon av ovanstående knappar för snabbare val."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Val av tid:\n" + +"- Klicka på en del av tiden för att öka den delen\n" + +"- eller skift-klicka för att minska den\n" + +"- eller klicka och drag för snabbare val."; + +Calendar._TT["PREV_YEAR"] = "Föregående år (håll för menu)"; +Calendar._TT["PREV_MONTH"] = "Föregående månad (håll för menu)"; +Calendar._TT["GO_TODAY"] = "Gå till dagens datum"; +Calendar._TT["NEXT_MONTH"] = "Följande månad (håll för menu)"; +Calendar._TT["NEXT_YEAR"] = "Följande år (håll för menu)"; +Calendar._TT["SEL_DATE"] = "Välj datum"; +Calendar._TT["DRAG_TO_MOVE"] = "Drag för att flytta"; +Calendar._TT["PART_TODAY"] = " (idag)"; +Calendar._TT["MON_FIRST"] = "Visa måndag först"; +Calendar._TT["SUN_FIRST"] = "Visa söndag först"; +Calendar._TT["CLOSE"] = "Stäng"; +Calendar._TT["TODAY"] = "Idag"; +Calendar._TT["TIME_PART"] = "(Skift-)klicka eller drag för att ändra tid"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d"; +Calendar._TT["TT_DATE_FORMAT"] = "%A %d %b %Y"; + +Calendar._TT["WK"] = "vecka"; diff --git a/htdocs/js/jscalendar/lang/calendar-tr.js b/htdocs/js/jscalendar/lang/calendar-tr.js new file mode 100644 index 0000000..2164687 --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-tr.js @@ -0,0 +1,58 @@ +////////////////////////////////////////////////////////////////////////////////////////////// +// Turkish Translation by Nuri AKMAN +// Location: Ankara/TURKEY +// e-mail : nuriakman@hotmail.com +// Date : April, 9 2003 +// +// Note: if Turkish Characters does not shown on you screen +// please include falowing line your html code: +// +// +// +////////////////////////////////////////////////////////////////////////////////////////////// + +// ** I18N +Calendar._DN = new Array +("Pazar", + "Pazartesi", + "Salý", + "Çarþamba", + "Perþembe", + "Cuma", + "Cumartesi", + "Pazar"); +Calendar._MN = new Array +("Ocak", + "Þubat", + "Mart", + "Nisan", + "Mayýs", + "Haziran", + "Temmuz", + "Aðustos", + "Eylül", + "Ekim", + "Kasým", + "Aralýk"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["TOGGLE"] = "Haftanýn ilk gününü kaydýr"; +Calendar._TT["PREV_YEAR"] = "Önceki Yýl (Menü için basýlý tutunuz)"; +Calendar._TT["PREV_MONTH"] = "Önceki Ay (Menü için basýlý tutunuz)"; +Calendar._TT["GO_TODAY"] = "Bugün'e git"; +Calendar._TT["NEXT_MONTH"] = "Sonraki Ay (Menü için basýlý tutunuz)"; +Calendar._TT["NEXT_YEAR"] = "Sonraki Yýl (Menü için basýlý tutunuz)"; +Calendar._TT["SEL_DATE"] = "Tarih seçiniz"; +Calendar._TT["DRAG_TO_MOVE"] = "Taþýmak için sürükleyiniz"; +Calendar._TT["PART_TODAY"] = " (bugün)"; +Calendar._TT["MON_FIRST"] = "Takvim Pazartesi gününden baþlasýn"; +Calendar._TT["SUN_FIRST"] = "Takvim Pazar gününden baþlasýn"; +Calendar._TT["CLOSE"] = "Kapat"; +Calendar._TT["TODAY"] = "Bugün"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "dd-mm-y"; +Calendar._TT["TT_DATE_FORMAT"] = "d MM y, DD"; + +Calendar._TT["WK"] = "Hafta"; diff --git a/htdocs/js/jscalendar/lang/calendar-zh.js b/htdocs/js/jscalendar/lang/calendar-zh.js new file mode 100644 index 0000000..4a0feb6 --- /dev/null +++ b/htdocs/js/jscalendar/lang/calendar-zh.js @@ -0,0 +1,119 @@ +// ** I18N + +// Calendar ZH language +// Author: muziq, +// Encoding: GB2312 or GBK +// Distributed under the same terms as the calendar itself. + +// full day names +Calendar._DN = new Array +("ÐÇÆÚÈÕ", + "ÐÇÆÚÒ»", + "ÐÇÆÚ¶þ", + "ÐÇÆÚÈý", + "ÐÇÆÚËÄ", + "ÐÇÆÚÎå", + "ÐÇÆÚÁù", + "ÐÇÆÚÈÕ"); + +// Please note that the following array of short day names (and the same goes +// for short month names, _SMN) isn't absolutely necessary. We give it here +// for exemplification on how one can customize the short day names, but if +// they are simply the first N letters of the full name you can simply say: +// +// Calendar._SDN_len = N; // short day name length +// Calendar._SMN_len = N; // short month name length +// +// If N = 3 then this is not needed either since we assume a value of 3 if not +// present, to be compatible with translation files that were written before +// this feature. + +// short day names +Calendar._SDN = new Array +("ÈÕ", + "Ò»", + "¶þ", + "Èý", + "ËÄ", + "Îå", + "Áù", + "ÈÕ"); + +// full month names +Calendar._MN = new Array +("Ò»ÔÂ", + "¶þÔÂ", + "ÈýÔÂ", + "ËÄÔÂ", + "ÎåÔÂ", + "ÁùÔÂ", + "ÆßÔÂ", + "°ËÔÂ", + "¾ÅÔÂ", + "Ê®ÔÂ", + "ʮһÔÂ", + "Ê®¶þÔÂ"); + +// short month names +Calendar._SMN = new Array +("Ò»ÔÂ", + "¶þÔÂ", + "ÈýÔÂ", + "ËÄÔÂ", + "ÎåÔÂ", + "ÁùÔÂ", + "ÆßÔÂ", + "°ËÔÂ", + "¾ÅÔÂ", + "Ê®ÔÂ", + "ʮһÔÂ", + "Ê®¶þÔÂ"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "°ïÖú"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"For latest version visit: http://www.dynarch.com/projects/calendar/\n" + +"Distributed under GNU LGPL. See http://gnu.org/licenses/lgpl.html for details." + +"\n\n" + +"Ñ¡ÔñÈÕÆÚ:\n" + +"- µã»÷ \xab, \xbb °´Å¥Ñ¡ÔñÄê·Ý\n" + +"- µã»÷ " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " °´Å¥Ñ¡ÔñÔ·Ý\n" + +"- ³¤°´ÒÔÉÏ°´Å¥¿É´Ó²Ëµ¥ÖпìËÙÑ¡ÔñÄê·Ý»òÔ·Ý"; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Ñ¡Ôñʱ¼ä:\n" + +"- µã»÷Сʱ»ò·ÖÖÓ¿Éʹ¸ÄÊýÖµ¼ÓÒ»\n" + +"- °´×¡Shift¼üµã»÷Сʱ»ò·ÖÖÓ¿Éʹ¸ÄÊýÖµ¼õÒ»\n" + +"- µã»÷Í϶¯Êó±ê¿É½øÐпìËÙÑ¡Ôñ"; + +Calendar._TT["PREV_YEAR"] = "ÉÏÒ»Äê (°´×¡³ö²Ëµ¥)"; +Calendar._TT["PREV_MONTH"] = "ÉÏÒ»Ô (°´×¡³ö²Ëµ¥)"; +Calendar._TT["GO_TODAY"] = "תµ½½ñÈÕ"; +Calendar._TT["NEXT_MONTH"] = "ÏÂÒ»Ô (°´×¡³ö²Ëµ¥)"; +Calendar._TT["NEXT_YEAR"] = "ÏÂÒ»Äê (°´×¡³ö²Ëµ¥)"; +Calendar._TT["SEL_DATE"] = "Ñ¡ÔñÈÕÆÚ"; +Calendar._TT["DRAG_TO_MOVE"] = "Í϶¯"; +Calendar._TT["PART_TODAY"] = " (½ñÈÕ)"; + +// the following is to inform that "%s" is to be the first day of week +// %s will be replaced with the day name. +Calendar._TT["DAY_FIRST"] = "×î×ó±ßÏÔʾ%s"; + +// This may be locale-dependent. It specifies the week-end days, as an array +// of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1 +// means Monday, etc. +Calendar._TT["WEEKEND"] = "0,6"; + +Calendar._TT["CLOSE"] = "¹Ø±Õ"; +Calendar._TT["TODAY"] = "½ñÈÕ"; +Calendar._TT["TIME_PART"] = "(Shift-)µã»÷Êó±ê»òÍ϶¯¸Ä±äÖµ"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d"; +Calendar._TT["TT_DATE_FORMAT"] = "%A, %b %eÈÕ"; + +Calendar._TT["WK"] = "ÖÜ"; +Calendar._TT["TIME"] = "ʱ¼ä:"; diff --git a/htdocs/js/jscalendar/lang/cn_utf8.js b/htdocs/js/jscalendar/lang/cn_utf8.js new file mode 100644 index 0000000..a0ef7c6 --- /dev/null +++ b/htdocs/js/jscalendar/lang/cn_utf8.js @@ -0,0 +1,123 @@ +// ** I18N + +// Calendar EN language +// Author: Mihai Bazon, +// Encoding: any +// Translator : Niko +// Distributed under the same terms as the calendar itself. + +// For translators: please use UTF-8 if possible. We strongly believe that +// Unicode is the answer to a real internationalized world. Also please +// include your contact information in the header, as can be seen above. + +// full day names +Calendar._DN = new Array +("\u5468\u65e5",//\u5468\u65e5 + "\u5468\u4e00",//\u5468\u4e00 + "\u5468\u4e8c",//\u5468\u4e8c + "\u5468\u4e09",//\u5468\u4e09 + "\u5468\u56db",//\u5468\u56db + "\u5468\u4e94",//\u5468\u4e94 + "\u5468\u516d",//\u5468\u516d + "\u5468\u65e5");//\u5468\u65e5 + +// Please note that the following array of short day names (and the same goes +// for short month names, _SMN) isn't absolutely necessary. We give it here +// for exemplification on how one can customize the short day names, but if +// they are simply the first N letters of the full name you can simply say: +// +// Calendar._SDN_len = N; // short day name length +// Calendar._SMN_len = N; // short month name length +// +// If N = 3 then this is not needed either since we assume a value of 3 if not +// present, to be compatible with translation files that were written before +// this feature. + +// short day names +Calendar._SDN = new Array +("\u5468\u65e5", + "\u5468\u4e00", + "\u5468\u4e8c", + "\u5468\u4e09", + "\u5468\u56db", + "\u5468\u4e94", + "\u5468\u516d", + "\u5468\u65e5"); + +// full month names +Calendar._MN = new Array +("\u4e00\u6708", + "\u4e8c\u6708", + "\u4e09\u6708", + "\u56db\u6708", + "\u4e94\u6708", + "\u516d\u6708", + "\u4e03\u6708", + "\u516b\u6708", + "\u4e5d\u6708", + "\u5341\u6708", + "\u5341\u4e00\u6708", + "\u5341\u4e8c\u6708"); + +// short month names +Calendar._SMN = new Array +("\u4e00\u6708", + "\u4e8c\u6708", + "\u4e09\u6708", + "\u56db\u6708", + "\u4e94\u6708", + "\u516d\u6708", + "\u4e03\u6708", + "\u516b\u6708", + "\u4e5d\u6708", + "\u5341\u6708", + "\u5341\u4e00\u6708", + "\u5341\u4e8c\u6708"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "\u5173\u4e8e"; + +Calendar._TT["ABOUT"] = +" DHTML \u65e5\u8d77/\u65f6\u95f4\u9009\u62e9\u63a7\u4ef6\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"For latest version visit: \u6700\u65b0\u7248\u672c\u8bf7\u767b\u9646http://www.dynarch.com/projects/calendar/\u5bdf\u770b\n" + +"\u9075\u5faaGNU LGPL. \u7ec6\u8282\u53c2\u9605 http://gnu.org/licenses/lgpl.html" + +"\n\n" + +"\u65e5\u671f\u9009\u62e9:\n" + +"- \u70b9\u51fb\xab(\xbb)\u6309\u94ae\u9009\u62e9\u4e0a(\u4e0b)\u4e00\u5e74\u5ea6.\n" + +"- \u70b9\u51fb" + String.fromCharCode(0x2039) + "(" + String.fromCharCode(0x203a) + ")\u6309\u94ae\u9009\u62e9\u4e0a(\u4e0b)\u4e2a\u6708\u4efd.\n" + +"- \u957f\u65f6\u95f4\u6309\u7740\u6309\u94ae\u5c06\u51fa\u73b0\u66f4\u591a\u9009\u62e9\u9879."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"\u65f6\u95f4\u9009\u62e9:\n" + +"-\u5728\u65f6\u95f4\u90e8\u5206(\u5206\u6216\u8005\u79d2)\u4e0a\u5355\u51fb\u9f20\u6807\u5de6\u952e\u6765\u589e\u52a0\u5f53\u524d\u65f6\u95f4\u90e8\u5206(\u5206\u6216\u8005\u79d2)\n" + +"-\u5728\u65f6\u95f4\u90e8\u5206(\u5206\u6216\u8005\u79d2)\u4e0a\u6309\u4f4fShift\u952e\u540e\u5355\u51fb\u9f20\u6807\u5de6\u952e\u6765\u51cf\u5c11\u5f53\u524d\u65f6\u95f4\u90e8\u5206(\u5206\u6216\u8005\u79d2)."; + +Calendar._TT["PREV_YEAR"] = "\u4e0a\u4e00\u5e74"; +Calendar._TT["PREV_MONTH"] = "\u4e0a\u4e2a\u6708"; +Calendar._TT["GO_TODAY"] = "\u5230\u4eca\u5929"; +Calendar._TT["NEXT_MONTH"] = "\u4e0b\u4e2a\u6708"; +Calendar._TT["NEXT_YEAR"] = "\u4e0b\u4e00\u5e74"; +Calendar._TT["SEL_DATE"] = "\u9009\u62e9\u65e5\u671f"; +Calendar._TT["DRAG_TO_MOVE"] = "\u62d6\u52a8"; +Calendar._TT["PART_TODAY"] = " (\u4eca\u5929)"; + +// the following is to inform that "%s" is to be the first day of week +// %s will be replaced with the day name. +Calendar._TT["DAY_FIRST"] = "%s\u4e3a\u8fd9\u5468\u7684\u7b2c\u4e00\u5929"; + +// This may be locale-dependent. It specifies the week-end days, as an array +// of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1 +// means Monday, etc. +Calendar._TT["WEEKEND"] = "0,6"; + +Calendar._TT["CLOSE"] = "\u5173\u95ed"; +Calendar._TT["TODAY"] = "\u4eca\u5929"; +Calendar._TT["TIME_PART"] = "(\u6309\u7740Shift\u952e)\u5355\u51fb\u6216\u62d6\u52a8\u6539\u53d8\u503c"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d"; +Calendar._TT["TT_DATE_FORMAT"] = "%a, %b %e\u65e5"; + +Calendar._TT["WK"] = "\u5468"; +Calendar._TT["TIME"] = "\u65f6\u95f4:"; diff --git a/htdocs/js/jscalendar/menuarrow.gif b/htdocs/js/jscalendar/menuarrow.gif new file mode 100644 index 0000000000000000000000000000000000000000..ed2dee0e6368d201bf5d32833884c7c1da6c7424 GIT binary patch literal 68 zcmZ?wbhEHbWM^Py_{hZ2(9rPi-LwDy|1&T!DE?$&WME)o&;ha;K=KSsqAVN&i(DE6 VRJ~d>0vEY-3aNTcS;53$4FHxP5xxKb literal 0 HcmV?d00001 diff --git a/htdocs/js/jscalendar/skins/aqua/active-bg.gif b/htdocs/js/jscalendar/skins/aqua/active-bg.gif new file mode 100644 index 0000000000000000000000000000000000000000..d608c54698e081a3deae0f1b9b827484deaeacce GIT binary patch literal 89 zcmZ?wbhEHb3xI7cXAAbm`*d3l}e6x_tTajT<-q|NpP}lZBCift^8z p0SG{98JMLwcHQ}C;N`q}uj=cwv(saC#4b@4SZ=W5%`PM literal 0 HcmV?d00001 diff --git a/htdocs/js/jscalendar/skins/aqua/hover-bg.gif b/htdocs/js/jscalendar/skins/aqua/hover-bg.gif new file mode 100644 index 0000000000000000000000000000000000000000..fbf94fc2c1891ff891f2d3c3208cf431c35a4628 GIT binary patch literal 89 zcmZ?wbhEHb-E$->CMz|NrfPt>_6 zHL)Z$MWH;iBts!2BUQoO(>H)Y2dIbvWC#PZ6vwVR9}T>mSMODQeRg(w%#PS4t~~0B LE8grwc6hbmm72G|20~mA|fB", ">>" buttons have this class */ + text-align: center; /* They are the navigation buttons */ + padding: 2px; /* Make the buttons seem like they're pressing */ + background: url("title-bg.gif") repeat-x 0 100%; color: #000; + font-weight: bold; +} + +.calendar .nav { + font-family: verdana,tahoma,sans-serif; +} + +.calendar .nav div { + background: transparent url("menuarrow.gif") no-repeat 100% 100%; +} + +.calendar thead tr { background: url("title-bg.gif") repeat-x 0 100%; color: #000; } + +.calendar thead .title { /* This holds the current "month, year" */ + font-weight: bold; /* Pressing it will take you to the current date */ + text-align: center; + padding: 2px; + background: url("title-bg.gif") repeat-x 0 100%; color: #000; +} + +.calendar thead .headrow { /* Row
containing the day names */ + border-bottom: 1px solid #797979; + padding: 2px; + text-align: center; + color: #000; +} + +.calendar thead .weekend { /* How a weekend day name shows in header */ + color: #c44; +} + +.calendar thead .hilite { /* How do the buttons in header appear when hover */ + background: url("hover-bg.gif"); + border-bottom: 1px solid #797979; + padding: 2px 2px 1px 2px; +} + +.calendar thead .active { /* Active (pressed) buttons in header */ + background: url("active-bg.gif"); color: #fff; + padding: 3px 1px 0px 3px; + border-bottom: 1px solid #797979; +} + +.calendar thead .daynames { /* Row
containing month days dates */ + font-family: verdana,tahoma,sans-serif; + width: 2em; + color: #000; + text-align: right; + padding: 2px 4px 2px 2px; +} +.calendar tbody .day.othermonth { + font-size: 80%; + color: #999; +} +.calendar tbody .day.othermonth.oweekend { + color: #f99; +} + +.calendar table .wn { + padding: 2px 3px 2px 2px; + border-right: 1px solid #797979; + background: url("dark-bg.gif"); +} + +.calendar tbody .rowhilite td, +.calendar tbody .rowhilite td.wn { + background: url("rowhover-bg.gif"); +} + +.calendar tbody td.today { font-weight: bold; /* background: url("today-bg.gif") no-repeat 70% 50%; */ } + +.calendar tbody td.hilite { /* Hovered cells */ + background: url("hover-bg.gif"); + padding: 1px 3px 1px 1px; + border: 1px solid #bbb; +} + +.calendar tbody td.active { /* Active (pressed) cells */ + padding: 2px 2px 0px 2px; +} + +.calendar tbody td.weekend { /* Cells showing weekend days */ + color: #c44; +} + +.calendar tbody td.selected { /* Cell showing selected date */ + font-weight: bold; + border: 1px solid #797979; + padding: 1px 3px 1px 1px; + background: url("active-bg.gif"); color: #fff; +} + +.calendar tbody .disabled { color: #999; } + +.calendar tbody .emptycell { /* Empty cells (the best is to hide them) */ + visibility: hidden; +} + +.calendar tbody .emptyrow { /* Empty row (some months need less than 6 rows) */ + display: none; +} + +/* The footer part -- status bar and "Close" button */ + +.calendar tfoot .footrow { /* The
*/ + padding: 2px; + background: url("status-bg.gif") repeat-x 0 0; color: #000; +} + +.calendar tfoot .hilite { /* Hover style for buttons in footer */ + background: #afa; + border: 1px solid #084; + color: #000; + padding: 1px; +} + +.calendar tfoot .active { /* Active (pressed) style for buttons in footer */ + background: #7c7; + padding: 2px 0px 0px 2px; +} + +/* Combo boxes (menus that display months/years for direct selection) */ + +.calendar .combo { + position: absolute; + display: none; + top: 0px; + left: 0px; + width: 4em; + cursor: default; + border-width: 0 1px 1px 1px; + border-style: solid; + border-color: #797979; + background: url("normal-bg.gif"); color: #000; + z-index: 100; + font-size: 90%; +} + +.calendar .combo .label, +.calendar .combo .label-IEfix { + text-align: center; + padding: 1px; +} + +.calendar .combo .label-IEfix { + width: 4em; +} + +.calendar .combo .hilite { + background: url("hover-bg.gif"); color: #000; +} + +.calendar .combo .active { + background: url("active-bg.gif"); color: #fff; + font-weight: bold; +} + +.calendar td.time { + border-top: 1px solid #797979; + padding: 1px 0px; + text-align: center; + background: url("dark-bg.gif"); +} + +.calendar td.time .hour, +.calendar td.time .minute, +.calendar td.time .ampm { + padding: 0px 5px 0px 6px; + font-weight: bold; + background: url("normal-bg.gif"); color: #000; +} + +.calendar td.time .hour, +.calendar td.time .minute { + font-family: monospace; +} + +.calendar td.time .ampm { + text-align: center; +} + +.calendar td.time .colon { + padding: 0px 2px 0px 3px; + font-weight: bold; +} + +.calendar td.time span.hilite { + background: url("hover-bg.gif"); color: #000; +} + +.calendar td.time span.active { + background: url("active-bg.gif"); color: #fff; +} diff --git a/htdocs/js/jscalendar/skins/aqua/title-bg.gif b/htdocs/js/jscalendar/skins/aqua/title-bg.gif new file mode 100644 index 0000000000000000000000000000000000000000..6a541b3bc1e4bbee3268e8a5b431e2c7e067b3b9 GIT binary patch literal 116 zcmZ?wbhEHbWMmLyc+AI8Sy_4e_U#7`9z1*Y?D_NOFJ8QO`}Xa-ckkZ6fB*UO=PzHr zeEwc6hbmm72G|20~mA|fBtHB8VX&K*sP!FEoV37-@-w z0R<@%0vdJ3g^a|I?Pj7#(uKh`L|Finie4=6J7+yFJ!?;2&hK|#eqYx=!aJTkdGdK~ zpXAvT*|;uzpq}wF^XC|f7Hy%(3T3cCne7xg0NE&VQse^UpvX;;2at=R3KMyuTq^;2 zC|Y8oD$05(`vPTsz*a#S0tVY?u&+|C9=JNny<&2Wlxxu0Hl1B<&bOHJt%U0!T(_BC zgSodcw-fkw;8z2`7Wg+!zQf>qKnNTBb`ZKuVKa!`hOo;JcIVTBAiY~i59ZSeL+aC| z!@BeVWcDfiw+cT5^1&QG406AoIcj8%=$U~We@)9obve2q{HDt%A^V9eOz8`!W#PUo z{Glyegxu${_yBUTjF`%Z|48DTBtDfyM6y>wiIePzB&H=%lq8Adt`lWUQ^v6JD^_ko zVMxpW0>xpRzl-zJT46#fEanU@Jl2Z$aN#etkRrv0xcG#WQfd*YMOH0xfG5?`f?CQG zRZvSM70ars5}YAe!5FKgv{(qnpg$pmfIbJN473Ck12uqBc&`6pfd*o?R4~A_FpDaG zf^k#kwtL0q(ctCQJ>$_C|68Xo9Y5B%<>HN|rPXUc)#iLZ4#(@;I^sWF!BdIIrn4`- z_ReJJ%ebfY&*2}GiP+Mnwl{8s9^RRq>F%t|b=gjA`^L{W-2=&FGRjoj?dL}ulChUN ztGti>UrgEp&DJF~TgO`%XJ0rw;D5cjZkdINhI+^4JxpY(BDmw(Y^2$Dw;%8S`6J8C z+7+J0mD495S)75uciVQyzK?~28yvw)3bIF5-kaz;!0dbQmF@mI-kmt>7+F`d+N zt#PY&(k@T!8mH}j>(;M_TI-IV)AU=8{=a)`lc$<@jm#z)SE${(>{g=Z!tz!BW;gbH Q9Q54|91Yd -1) ? 1 : 0; +// We need to detect Konqueror 2.2 as it does not handle the window.onresize event +var Konqueror22 = (navigator.userAgent.indexOf('Konqueror 2.2') > -1 || navigator.userAgent.indexOf('Konqueror/2.2') > -1) ? 1 : 0; +var Konqueror30 = + ( + navigator.userAgent.indexOf('Konqueror 3.0') > -1 + || navigator.userAgent.indexOf('Konqueror/3.0') > -1 + || navigator.userAgent.indexOf('Konqueror 3;') > -1 + || navigator.userAgent.indexOf('Konqueror/3;') > -1 + || navigator.userAgent.indexOf('Konqueror 3)') > -1 + || navigator.userAgent.indexOf('Konqueror/3)') > -1 + ) + ? 1 : 0; +var Konqueror31 = (navigator.userAgent.indexOf('Konqueror 3.1') > -1 || navigator.userAgent.indexOf('Konqueror/3.1') > -1) ? 1 : 0; +// We need to detect Konqueror 3.2 and 3.3 as they are affected by the see-through effect only for 2 form elements +var Konqueror32 = (navigator.userAgent.indexOf('Konqueror 3.2') > -1 || navigator.userAgent.indexOf('Konqueror/3.2') > -1) ? 1 : 0; +var Konqueror33 = (navigator.userAgent.indexOf('Konqueror 3.3') > -1 || navigator.userAgent.indexOf('Konqueror/3.3') > -1) ? 1 : 0; + +var Opera = (navigator.userAgent.indexOf('Opera') > -1) ? 1 : 0; +var Opera5 = (navigator.userAgent.indexOf('Opera 5') > -1 || navigator.userAgent.indexOf('Opera/5') > -1) ? 1 : 0; +var Opera6 = (navigator.userAgent.indexOf('Opera 6') > -1 || navigator.userAgent.indexOf('Opera/6') > -1) ? 1 : 0; +var Opera56 = Opera5 || Opera6; +var Opera7 = (navigator.userAgent.indexOf('Opera 7') > -1 || navigator.userAgent.indexOf('Opera/7') > -1) ? 1 : 0; +var Opera8 = (navigator.userAgent.indexOf('Opera 8') > -1 || navigator.userAgent.indexOf('Opera/8') > -1) ? 1 : 0; +var Opera9 = (navigator.userAgent.indexOf('Opera 9') > -1 || navigator.userAgent.indexOf('Opera/9') > -1) ? 1 : 0; + +var IE = (navigator.userAgent.indexOf('MSIE') > -1) ? 1 : 0; +IE = IE && !Opera; +var IE5 = IE && DOM; +var IE4 = (document.all) ? 1 : 0; +IE4 = IE4 && IE && !DOM; diff --git a/htdocs/js/modify_member.js b/htdocs/js/modify_member.js new file mode 100644 index 0000000..a601ccb --- /dev/null +++ b/htdocs/js/modify_member.js @@ -0,0 +1,89 @@ +var m1 = document.getElementById('member').notmembers; +var m2 = document.getElementById('member').members; + +/* This function generates hidden input array from new group members + * when submit button is pressed. + * see modify_member_form.php +*/ +function update_new_values(memberattr) { + el = document.getElementById("dnu"); + + for (i=0;i"; + } +} + + +/* This function moves members from left select box to right one + * see modify_member_form.php + */ +function one2two() { + m1len = m1.length ; + + for (i=0;i=0;i--){ + if (m1.options[i].selected == true) { + m1.options[i] = null; + } + } +} + +/* This function moves members from right select box to left one + * see modify_member_form.php + */ +function two2one() { + m2len = m2.length ; + + for (i=0;i=0;i--) { + if (m2.options[i].selected == true) { + m2.options[i] = null; + } + } +} + +/* This function moves all members from left select box to right one + * see modify_member_form.php + */ +function all2two() { + m1len = m1.length ; + + for (i=0;i=0;i--) { + m1.options[i] = null; + } +} + +/* This function moves all members from right select box to left one + * see modify_member_form.php + */ +function all2one() { + m2len = m2.length ; + + for (i=0;i=0;i--) { + m2.options[i] = null; + } +} diff --git a/htdocs/js/toAscii.js b/htdocs/js/toAscii.js new file mode 100644 index 0000000..287ff65 --- /dev/null +++ b/htdocs/js/toAscii.js @@ -0,0 +1,80 @@ +// +// Purpose of this file is to remap characters as ASCII characters +// +// + +var to_ascii_array = new Array(); +to_ascii_array['à'] = 'a'; +to_ascii_array['á'] = 'a'; +to_ascii_array['â'] = 'a'; +to_ascii_array['À'] = 'a'; +to_ascii_array['ã'] = 'a'; +to_ascii_array['Ã¥'] = 'a'; +to_ascii_array['À'] = 'A'; +to_ascii_array['ÃÂ'] = 'A'; +to_ascii_array['Ä'] = 'A'; +to_ascii_array['Â'] = 'A'; +to_ascii_array['Ã'] = 'A'; +to_ascii_array['Å'] = 'A'; +to_ascii_array['é'] = 'e'; +to_ascii_array['Ú'] = 'e'; +to_ascii_array['ë'] = 'e'; +to_ascii_array['ê'] = 'e'; +to_ascii_array['€'] = 'E'; +to_ascii_array['ï'] = 'i'; +to_ascii_array['î'] = 'i'; +to_ascii_array['ì'] = 'i'; +to_ascii_array['í'] = 'i'; +to_ascii_array['ÃÂ'] = 'I'; +to_ascii_array['Î'] = 'I'; +to_ascii_array['Ì'] = 'I'; +to_ascii_array['ÃÂ'] = 'I'; +to_ascii_array['ò'] = 'o'; +to_ascii_array['ó'] = 'o'; +to_ascii_array['ÃŽ'] = 'o'; +to_ascii_array['õ'] = 'o'; +to_ascii_array['ö'] = 'o'; +to_ascii_array['Þ'] = 'o'; +to_ascii_array['Ò'] = 'O'; +to_ascii_array['Ó'] = 'O'; +to_ascii_array['Ô'] = 'O'; +to_ascii_array['Õ'] = 'O'; +to_ascii_array['Ö'] = 'O'; +to_ascii_array['Ø'] = 'O'; +to_ascii_array['ù'] = 'u'; +to_ascii_array['ú'] = 'u'; +to_ascii_array['ÃŒ'] = 'u'; +to_ascii_array['û'] = 'u'; +to_ascii_array['Ù'] = 'U'; +to_ascii_array['Ú'] = 'U'; +to_ascii_array['Ü'] = 'U'; +to_ascii_array['Û'] = 'U'; +to_ascii_array['Ê'] = 'ae'; +to_ascii_array['Æ'] = 'AE'; +to_ascii_array['Ãœ'] = 'y'; +to_ascii_array['ÿ'] = 'y'; +to_ascii_array['ß'] = 'SS'; +to_ascii_array['Ç'] = 'C'; +to_ascii_array['ç'] = 'c'; +to_ascii_array['Ñ'] = 'N'; +to_ascii_array['ñ'] = 'n'; +to_ascii_array['¢'] = 'c'; +to_ascii_array['©'] = '(C)'; +to_ascii_array['®'] = '(R)'; +to_ascii_array['«'] = '<<'; +to_ascii_array['»'] = '>>'; + +function toAscii(text) { + //var text = field.value; + var position = 0; + var output = ""; + for (position = 0 ; position < text.length ; position++) { + var tmp = text.substring(position,position+1); + if (to_ascii_array[tmp] != undefined) { + tmp = to_ascii_array[tmp]; + } + output = output + tmp; + } + return output; +} + diff --git a/htdocs/login.php b/htdocs/login.php new file mode 100644 index 0000000..48f9e2e --- /dev/null +++ b/htdocs/login.php @@ -0,0 +1,37 @@ +_('Authenticate to server'), + 'body'=>_('You left the password blank.'), + 'type'=>'warn'), + sprintf('cmd.php?cmd=login_form&server_id=%s',get_request('server_id','REQUEST'))); + +if ($app['server']->login($user['login'],$user['password'],'user')) + system_message(array( + 'title'=>_('Authenticate to server'), + 'body'=>_('Successfully logged into server.'), + 'type'=>'info'), + sprintf('cmd.php?server_id=%s',get_request('server_id','REQUEST'))); +else + system_message(array( + 'title'=>_('Failed to Authenticate to server'), + 'body'=>_('Invalid Username or Password.'), + 'type'=>'error'), + sprintf('cmd.php?cmd=login_form&server_id=%s',get_request('server_id','REQUEST'))); +?> diff --git a/htdocs/login_form.php b/htdocs/login_form.php new file mode 100644 index 0000000..f16bdbf --- /dev/null +++ b/htdocs/login_form.php @@ -0,0 +1,98 @@ +%s %s',_('Authenticate to server'),$app['server']->getName()); +echo '
'; + +# Check for a secure connection +if (! isset($_SERVER['HTTPS']) || strtolower($_SERVER['HTTPS']) != 'on') { + echo '
'; + printf('%s: %s.', + _('You are not using \'https\'. Web browser will transmit login information in clear text.'), + _('Warning'),_('This web connection is unencrypted')); + echo '
'; + + echo '
'; +} + +# HTTP Basic Auth Form. +if ($app['server']->getAuthType() == 'http') { + ob_end_clean(); + + # When we pop up the basic athentication, we come back to this script, so try the login again. + if ($app['server']->isLoggedIn('user')) { + system_message(array( + 'title'=>_('Authenticate to server'), + 'body'=>_('Successfully logged into server.'), + 'type'=>'info'), + sprintf('cmd.php?server_id=%s&refresh=SID_%s',$app['server']->getIndex(),$app['server']->getIndex())); + + die(); + } + + header(sprintf('WWW-Authenticate: Basic realm="%s"',$_SESSION[APPCONFIG]->getValue('session','http_realm'))); + + if ($_SERVER['SERVER_PROTOCOL'] == 'HTTP/1.0') + header('HTTP/1.0 401 Unauthorized'); // http 1.0 method + else + header('Status: 401 Unauthorized'); // http 1.1 method + + return; + +# HTML Login Form +} else { + echo '
'; + echo '
'; + echo ''; + printf('',$app['server']->getIndex()); + echo ''; + + if (get_request('redirect','GET',false,false)) + printf('',rawurlencode(get_request('redirect','GET'))); + + echo '
'; + + echo ''; + + printf('', + $app['server']->getValue('login','auth_text') ? $app['server']->getValue('login','auth_text') : + ($app['server']->getValue('login','attr') == 'dn' ? _('Login DN') : $_SESSION[APPCONFIG]->getFriendlyName($app['server']->getValue('login','attr')))); + + printf('', + $app['server']->getValue('login','attr',false) == 'dn' ? $app['server']->getValue('login','bind_id') : ''); + + echo ''; + printf('',_('Password')); + echo ''; + echo ''; + + # If Anon bind allowed, then disable the form if the user choose to bind anonymously. + if ($app['server']->isAnonBindAllowed()) + printf('', + _('Anonymous')); + + printf('', + _('Authenticate')); + + echo '
%s:
 
%s:
 
%s
'; + echo '
'; + + echo '
'; + + echo ''; + + if ($app['server']->isAnonBindAllowed()) + printf('',JSDIR); +} +?> diff --git a/htdocs/logout.php b/htdocs/logout.php new file mode 100644 index 0000000..3c0e5eb --- /dev/null +++ b/htdocs/logout.php @@ -0,0 +1,29 @@ +logout()) { + unset($_SESSION['ACTIVITY'][$app['server']->getIndex()]); + + system_message(array( + 'title'=>_('Logout from Server'), + 'body'=>_('Successfully logged out of server.'), + 'type'=>'info'), + sprintf('index.php?server_id=%s',$app['server']->getIndex())); + +} else + system_message(array( + 'title'=>_('Failed to Logout of server'), + 'body'=>_('Please report this error to the admins.'), + 'type'=>'error'), + sprintf('index.php?server_id=%s',$app['server']->getIndex())); +?> diff --git a/htdocs/mass_delete.php b/htdocs/mass_delete.php new file mode 100644 index 0000000..4f91ae4 --- /dev/null +++ b/htdocs/mass_delete.php @@ -0,0 +1,147 @@ +_('No entry selected'), + 'body'=>_('No entry was selected to delete'), + 'type'=>'warn'),'index.php'); + +if (! is_array($request['dn'])) + $request['dn'] = array($request['dn']); + +$request['children'] = array(); +$request['parent'] = array(); +foreach ($request['dn'] as $dn) { + # Check if the entry exists. + if (! $dn || ! $app['server']->dnExists($dn)) + system_message(array( + 'title'=>_('Entry does not exist'), + 'body'=>sprintf('%s (%s/%s)',_('The entry does not exist and will be ignored'),$dn), + 'type'=>'error')); + + # We search all children, not only the visible children in the tree + if (! in_array_ignore_case($dn,$request['children'])) { + $request['children'] = array_merge($request['children'],$app['server']->getContainerContents($dn,null,0,'(objectClass=*)',LDAP_DEREF_NEVER)); + array_push($request['parent'],$dn); + } +} + +printf('

%s

',_('Mass Delete')); +printf('

%s: %s

',_('Server'),$app['server']->getName()); +echo "\n"; + +echo '
'; +echo ''; + +if (count($request['parent']) == 1) + printf('',_('Are you sure you want to permanently delete this object?')); +else + printf('',_('Are you sure you want to permanently delete these objects?')); + +echo ''; +printf('',_('Server'),$app['server']->getName()); + +foreach ($request['parent'] as $dn) + printf('', + _('Distinguished Name'),_('DN'),$dn); + +echo ''; + +$request['delete'] = $request['parent']; + +if (count($request['children'])) { + printf('',_('Permanently delete all children also?')); + echo ''; + + # We need to see if the children have children + $query = array(); + $query['scope'] = 'sub'; + $query['attrs'] = array('dn'); + $query['size_limit'] = 0; + $query['deref'] = LDAP_DEREF_NEVER; + + $request['search'] = array(); + foreach ($request['children'] as $dn) { + $query['base'] = $dn; + $request['search'] = array_merge($request['search'],$app['server']->query($query,null)); + } + + foreach ($request['search'] as $value) + array_push($request['delete'],$value['dn']); + + echo ''; + echo ''; + + printf('', + sprintf(_('phpLDAPadmin can also recursively delete all %s of the child entries. See below for a list of all the entries that this action will delete. Do you want to do this?'),count($request['children']))); + + echo ''; + + printf('', + _('Note: this is potentially very dangerous and you do this at your own risk. This operation cannot be undone. Take into consideration aliases, referrals, and other things that may cause problems.')); + echo "\n"; + + echo ''; + + echo "\n"; + + printf('',_('List of entries to be deleted:')); + echo ''; + + $i = 0; + echo ''; + echo "\n"; + + echo ''; +} + +echo ''; +echo ''; + +echo ''; +echo ''; +echo "\n"; + +echo '
%s
%s
 
%s:%s
%s%s
 
%s
 
'; + printf(_('This request also includes %s children entries.'),count($request['children'])); + echo '
%s
 
%s
 
%s
 
'; + printf(''; + echo '
 
'; +echo '
'; +echo ''; +printf('',$app['server']->getIndex()); +foreach ($request['parent'] as $dn) + printf('',htmlspecialchars($dn)); +printf('',sprintf(_('Delete all %s objects'),count($request['delete']))); +echo '
'; +echo '
'; + +echo '
'; +echo ''; +printf('',$app['server']->getIndex()); +printf('',_('Cancel')); +echo '
'; + +echo '
'; +echo '
'; + +echo '
'; +?> diff --git a/htdocs/mass_edit.php b/htdocs/mass_edit.php new file mode 100644 index 0000000..1ea7001 --- /dev/null +++ b/htdocs/mass_edit.php @@ -0,0 +1,133 @@ +dnExists($dn)) { + system_message(array( + 'title'=>_('Entry does not exist'), + 'body'=>sprintf('%s (%s/%s)',_('The entry does not exist and will be ignored'),$dn), + 'type'=>'error')); + + continue; + } + + $request['page'][$counter] = new MassRender($app['server']->getIndex(),'none'); + $request['page'][$counter]->setDN($dn); + $request['page'][$counter]->accept(true); + + $template = $request['page'][$counter]->getTemplate(); + + # Mark our attributes to edit as shown. + foreach ($template->getAttributes(true) as $attribute) { + if ($attribute->isInternal()) + continue; + + if (in_array_ignore_case($attribute->getName(),$request['attrs']) || in_array('*',$request['attrs'])) { + $attribute->show(); + + # Get a list of our columns (we are not interested in these attribute values) + if (! isset($attrcols[$attribute->getName()])) + $attrcols[$attribute->getName()] = $attribute; + } + } + + $counter++; +} + +usort($attrcols,'sortAttrs'); + +if (! count($request['page'])) + header('Location: index.php'); + +# We'll render this forms Title with the first DN's object. +$request['page'][0]->drawTitle(_('Bulk edit the following DNs')); +$request['page'][0]->drawSubTitle(sprintf('%s: %s',_('Server'),$app['server']->getName())); + +echo '
'; +echo '
'; +echo ''; +printf('',$app['server']->getIndex()); + +foreach ($request['page'] as $j => $page) + printf('',$j,$page->getTemplate()->getDN()); + +echo '
'; + +echo ''; +echo ''; +echo ''; + +foreach ($attrcols as $attribute) { + echo ''; +} + +echo ''; + +$counter = 0; +foreach ($request['page'] as $j => $page) { + $template = $page->getTemplate(); + + printf('',$counter++%2==0?'even':'odd'); + printf('', + $template->getDN(),substr($template->getDN(),0,20)); + + foreach ($attrcols as $attrcol) { + $attribute = $template->getAttribute($attrcol->getName()); + + echo ''; + } + + echo ''; +} + +echo '
DN'; + $request['page'][0]->draw('Name',$attribute); + echo '
%s...'; + if ($attribute) { + foreach ($attribute->getValues() as $i => $val) + $page->draw('MassFormReadWriteValue',$attribute,$i,$j); + + # The attribute doesnt exist. If it is available by the shema, we can draw an empty input box. + } else { + $match = false; + + foreach ($template->getAvailAttrs() as $attribute) { + if ($attrcol->getName() == $attribute->getName()) { + $page->draw('MassFormReadWriteValue',$attribute,0,$j); + $match = true; + + break; + } + } + + if (! $match) + printf('
%s
', _('Attribute not available')); + } + + echo '
'; +echo '
'; +echo '
'; +printf('',_('Update Values')); +echo '
'; +echo '
'; +?> diff --git a/htdocs/mass_update.php b/htdocs/mass_update.php new file mode 100644 index 0000000..8a9dd01 --- /dev/null +++ b/htdocs/mass_update.php @@ -0,0 +1,175 @@ + $dn) { + # Check if the entry exists. + if (! $dn || ! $app['server']->dnExists($dn)) { + system_message(array( + 'title'=>_('Entry does not exist'), + 'body'=>sprintf('%s (%s/%s)',_('The entry does not exist and will be ignored'),$dn), + 'type'=>'error')); + + continue; + } + + # Simulate the requirements for *Render->accept() + if (! isset($request['mass_values'][$index])) + continue; + + $_REQUEST['new_values'] = $request['mass_values'][$index]; + + $render = new MassRender($app['server']->getIndex(),'none'); + $render->setDN($dn); + $render->accept(true); + + if ($render->getTemplate()->getLDAPmodify(false,$index)) + $request['update'][$index] = $render; +} + +# We can use the $render to give us a title +$render->drawTitle(_('Bulk update the following DNs')); +$render->drawSubTitle(sprintf('%s: %s',_('Server'),$app['server']->getName())); + +if (count($request['update'])) { + if (get_request('confirm','REQUEST')) { + foreach ($request['update'] as $index => $page) { + $template = $page->getTemplate(); + + # Perform the modification + $result = $app['server']->modify($template->getDN(),$template->getLDAPmodify(false,$index)); + + if ($result) + printf('%s: %s
',$template->getDN(),_('Modification successful!')); + else + printf('%s: %s
',$template->getDN(),_('Modification NOT successful!')); + } + + } else { + echo '
'; + echo ''; + printf('',$app['server']->getIndex()); + echo ''; + + foreach ($request['update'] as $j => $page) + printf('',$j,$page->getTemplate()->getDN()); + + echo ''; + echo ''; + echo '
'; + + echo '
'; + + echo ''; + echo ''; + echo '
'; + printf(_('There will be %s updates done with this mass update'),sprintf('%s',count($request['update']))); + echo '
'; + + echo '
'; + + foreach ($request['update'] as $index => $page) { + $template = $page->getTemplate(); + + echo ''; + echo ''; + printf('',IMGDIR,get_icon($app['server']->getIndex(),$template->getDN())); + + printf('', + $app['server']->getIndex(),rawurlencode(dn_unescape($template->getDN())),htmlspecialchars(get_rdn($template->getDN()))); + echo ''; + + printf('', + htmlspecialchars(dn_unescape($template->getDN())),_('Old Value')); + + foreach ($template->getLDAPmodify(true,$index) as $attribute) { + echo ''; + echo ''; + + echo ''; + + # Show NEW Values + echo ''; + + # Show OLD Values + echo ''; + + echo ''; + } + + echo '
icon%s
 dn%s%s
 '; + $page->draw('Name',$attribute); + echo ''; + + if (! $attribute->getValueCount() || $attribute->isForceDelete()) { + printf('[%s]',_('attribute deleted')); + printf('',$index,$attribute->getName(),0,''); + } + + foreach ($attribute->getValues() as $key => $value) { + # For multiple values, we'll highlight the changed ones + if ((count($attribute->getValues()) > 5) && in_array($value,$attribute->getAddedValues())) + echo ''; + + $page->draw('CurrentValue',$attribute,$key); + + # For multiple values, close the highlighting + if ((count($attribute->getValues()) > 5) && in_array($value,$attribute->getAddedValues())) + echo ''; + + echo '
'; + printf('',$index,$attribute->getName(),$key,$value); + } + + echo '
'; + + if (! $attribute->getOldValues()) + printf('[%s]',_('attribute doesnt exist')); + + foreach ($attribute->getOldValues() as $key => $value) { + # For multiple values, we'll highlight the changed ones + if ((count($attribute->getOldValues()) > 5) && in_array($value,$attribute->getRemovedValues()) && count($attribute->getValues())) + echo ''; + + $page->draw('OldValue',$attribute,$key); + + # For multiple values, close the highlighting + if ((count($attribute->getOldValues()) > 5) && in_array($value,$attribute->getRemovedValues()) && count($attribute->getValues())) + echo ''; + + echo '
'; + } + + echo '
'; + + echo '
'; + } + + echo '
'; + printf('',_('Update Values')); + echo '
'; + } + +} else { + echo '
'; + echo _('You made no changes'); + echo '
'; +} +?> diff --git a/htdocs/modify_member_form.php b/htdocs/modify_member_form.php new file mode 100644 index 0000000..208b9ef --- /dev/null +++ b/htdocs/modify_member_form.php @@ -0,0 +1,178 @@ +getIndex(),get_request('template','REQUEST',false,null)); +$request['page']->setDN($request['dn']); +$request['page']->accept(true); +$request['template'] = $request['page']->getTemplate(); + +if (! is_null($request['dn'])) + $rdn = get_rdn($request['dn']); +else + $rdn = null; + +# Get all current group members +$current_members = $app['server']->getDNAttrValue($request['dn'],$request['attr']); +usort($current_members,'pla_compare_dns'); + +# Loop through all base dn's and search possible member entries +$query = array(); + +# Get all entries that can be added to the group +if (preg_match("/^".$request['attr']."$/i",$_SESSION[APPCONFIG]->getValue('modify_member','posixgroupattr'))) { + $query['filter'] = $_SESSION[APPCONFIG]->getValue('modify_member','posixfilter'); + $attr = $_SESSION[APPCONFIG]->getValue('modify_member','posixattr'); + +} else { + $query['filter'] = $_SESSION[APPCONFIG]->getValue('modify_member','filter'); + $attr = $_SESSION[APPCONFIG]->getValue('modify_member','attr'); +} + +$query['attrs'] = array($attr); + +$possible_values = array(); +foreach ($app['server']->getBaseDN() as $base) { + $query['base'] = $base; + + $possible_values = array_merge($possible_values,$app['server']->query($query,null)); +} + +usort($possible_values,'pla_compare_dns'); + +$request['page']->drawTitle(sprintf('%s %s',_('Modify group'),get_rdn($request['dn']))); +$request['page']->drawSubTitle(); + +printf('%s %s %s %s:', + _('There are'),count($current_members),_('members in group'),htmlspecialchars(get_rdn($request['dn']))); + +$possible_members = array(); +for ($i=0;$igetValue('modify_member','posixgroupattr'))) + $possible_members[$i] = $possible_values[$i][$_SESSION[APPCONFIG]->getValue('modify_member','posixattr')][0]; + else + $possible_members[$i] = $possible_values[$i][$_SESSION[APPCONFIG]->getValue('modify_member','attr')]; +} + +# Show only user that are not already in group. +$possible_members = array_diff($possible_members,$current_members); +usort($possible_members,'pla_compare_dns'); + +/* Draw form with select boxes, left for all possible members and + * right one for those that belong to group */ + +# Modifications will be sent to update_confirm which takes care of rest of the processing +echo '
'; +echo '
'; + +echo '
'; +echo '
'; +if ($_SESSION[APPCONFIG]->getValue('confirm','update')) + echo ''; +else + echo ''; +echo '
'; + +echo ''; + +echo ''; +printf('',IMGDIR,_('Available members')); +printf('',IMGDIR,_('Group members')); +echo ''; + +# Generate select box from all possible members +echo ''; +echo ''; + +# Generate select box from all current members +echo ''; + +echo ''; + +# Show buttons which move users from left to right and vice versa +echo ''; +echo ''; +echo ''; +echo ''; + +echo ''; + +echo '
Users %sMembers %s
'; +echo ''; +echo ''; +echo ''; +echo '
'; +printf(' ', + _('Add selected'),_('Add all')); +echo ''; +printf(' ', + _('Remove selected'),('Remove all')); +echo '
'; + +# Hidden attributes for update_confirm.php +printf('',$app['server']->getIndex()); +printf('',rawurlencode($request['dn'])); +printf('',$request['attr']); + +/* Generate array of input text boxes from current members. + * update_confirm.php will see this as old_values[member-attribute][item] */ +for ($i=0; $i', + htmlspecialchars($request['attr']),$i,htmlspecialchars($current_members[$i])); + +/* Javascript generates array of input text boxes from new members. + * update_confirm.php will see this as new_values[member-attribute][item] + * Input text boxes will be generated to div=dnu */ +echo '
'; +printf('',htmlspecialchars($request['attr'])); +echo '
'; + +# Submit values to update_confirm.php and when clicked, run addSelected +printf('',_('Save changes'),$request['attr']); +echo '
'; +echo '
'; +printf('',JSDIR); +?> diff --git a/htdocs/monitor.php b/htdocs/monitor.php new file mode 100644 index 0000000..51ac392 --- /dev/null +++ b/htdocs/monitor.php @@ -0,0 +1,259 @@ +getRootDSE(); + +$query = array(); +$query['base'] = $attrs['monitorcontext'][0]; +$query['scope'] = 'sub'; +$query['attrs'] = array('+','*'); +$results = $app['server']->query($query,null); + +if (! isset($attrs['monitorcontext']) || ! count($results)) + system_message(array( + 'title'=>_('Monitoring context does not exist'), + 'body'=>sprintf('%s: %s',_('Could not obtain the monitor context for this server'),$app['server']->getName()), + 'type'=>'warn'),'index.php'); + +printf('

%s%s

',_('Monitor info for: '),$app['server']->getName()); +printf('

%s

',_('Server reports the following information about itself')); + +echo ''; + +# cn=Monitor +printf('',_('LDAP Server')); +printf(''; + +foreach (array( + 'cn=Backends,cn=Monitor' => 'cn=Backend %s,%s', + 'cn=Overlays,cn=Monitor' => 'cn=Overlay %s,%s' + ) as $dn => $child) { + + if (isset($results[$dn]['description'])) { + $description = implode(' ',$results[$dn]['description']); + + $description = preg_replace('/"/','\'',$description); + } else { + $description = ''; + } + + printf('',$description,$dn); + echo ''; +} + +# cn=Connections,cn=Monitor +printf('',$results['cn=Connections,cn=Monitor']['description'],_('LDAP Connections')); +printf(''; + +foreach (array( + 'cn=Listeners,cn=Monitor', + 'cn=Log,cn=Monitor', + 'cn=Operations,cn=Monitor', + 'cn=SASL,cn=Monitor', + 'cn=TLS,cn=Monitor', + 'cn=Statistics,cn=Monitor', + 'cn=Threads,cn=Monitor', + 'cn=Time,cn=Monitor', + 'cn=Waiters,cn=Monitor' + ) as $dn ) { + + $description = implode(' ',$results[$dn]['description']); + $description = preg_replace('/"/','\'',$description); + + printf('',$description,$dn); + echo ''; +} + +echo '
%s
'); + +echo ''; +printf('',$results[$attrs['monitorcontext'][0]]['monitoredinfo'][0]); +echo '
%s
'; + +echo '
%s
'; + echo ''; + echo '
'; + echo ''; + + $attrs = array( + 'monitorruntimeconfig', + 'supportedcontrol' + ); + + echo ''; + printf('',_('Type'),'namingContext'); + + foreach ($attrs as $attr) + printf('',$attr); + + echo ''; + + $counter = 0; + foreach ($results[$dn]['monitoredinfo'] as $index => $backend) { + printf('',$counter++%2==0?'even':'odd'); + printf('',$backend); + + $key = sprintf($child,$index,$dn); + + echo ''; + + foreach ($attrs as $attr) { + echo ''; + } + echo ''; + } + + echo '
%s%s%s
%s'; + if (isset($results[$key]['seealso'])) { + $seealso = is_array($results[$key]['seealso']) ? $results[$key]['seealso'] : array($results[$key]['seealso']); + + foreach ($seealso as $db) + if (isset($results[$db]['namingcontexts'])) + printf('%s
', + isset($results[$db]['labeleduri']) ? implode(' ',$results[$db]['labeleduri']) : _('Internal'), + implode(' ',$results[$db]['namingcontexts'])); + else + printf('%s ',implode(' ',$results[$db]['monitoredinfo'])); + + } else { + echo ' '; + } + echo '
'; + if (isset($results[$key][$attr])) { + if (! is_array($results[$key][$attr])) + $sc = array($results[$key][$attr]); + else + $sc = $results[$key][$attr]; + + if (strcasecmp('supportedcontrol',$attr) == 0) + foreach ($sc as $control) { + $oidtotext = support_oid_to_text($control); + + printf('%s
', + $control,$oidtotext['title']); + } + + else + printf('%s ',implode('
',$sc)); + + } else { + echo ' '; + } + + echo '
'; + echo '
%s
'); +echo ''; +echo '
'; +echo ''; + +printf('', + _('Total Connections'),$results['cn=Total,cn=Connections,cn=Monitor']['monitorcounter']); +printf('', + _('Current Connections'),$results['cn=Current,cn=Connections,cn=Monitor']['monitorcounter']); + +# Look for some connections +foreach ($results as $key => $value) { + if (preg_match('/^cn=Connection.*,cn=Connections,cn=Monitor$/',$key)) { + echo ''; + printf('',$results[$key]['cn'][0]); + + echo ''; + echo ''; + } +} + +echo '
%s%s
%s%s
%s'; + echo ''; + + $counter = 0; + foreach (array( + 'monitorconnectionactivitytime', + 'monitorconnectionauthzdn', + 'monitorconnectionget', + 'monitorconnectionlistener', + 'monitorconnectionlocaladdress', + 'monitorconnectionmask', + 'monitorconnectionnumber', + 'monitorconnectionopscompleted', + 'monitorconnectionopsexecuting', + 'monitorconnectionopspending', + 'monitorconnectionopsreceived', + 'monitorconnectionpeeraddress', + 'monitorconnectionpeerdomain', + 'monitorconnectionprotocol', + 'monitorconnectionread', + 'monitorconnectionstarttime', + 'monitorconnectionwrite' + ) as $metric) { + + printf('',$counter++%2==0?'even':'odd'); + + printf('', + $metric,isset($results[$key][$metric]) ? $results[$key][$metric][0] : ' '); + echo ''; + } + + echo '
%s%s
'; + echo '
'; +echo '
%s
'; + echo ''; + echo '
'; + echo ''; + + if (isset($results[$dn]['monitoropinitiated'])) + printf('', + 'monitorOpInitiated',$results[$dn]['monitoropinitiated'][0]); + if (isset($results[$dn]['monitoropcompleted'])) + printf('', + 'monitorOpCompleted',$results[$dn]['monitoropcompleted'][0]); + if (isset($results[$dn]['monitoredinfo'])) + printf('', + 'monitoredInfo',$results[$dn]['monitoredinfo'][0]); + + # Look for some connecitons + foreach ($results as $key => $value) { + if (preg_match('/^.*,'.$dn.'$/',$key)) { + echo ''; + printf('',$results[$key]['cn'][0]); + + echo ''; + echo ''; + } + } + echo '
%s%s
%s%s
%s%s
%s'; + echo ''; + + foreach (array( + 'labeleduri', + 'monitorconnectionlocaladdress', + 'monitoredinfo', + 'monitorcounter', + 'monitoropinitiated', + 'monitoropcompleted', + 'monitortimestamp' + ) as $metric) { + + if (isset($results[$key][$metric])) { + printf('',$counter++%2==0?'even':'odd'); + + printf('', + $metric,$results[$key][$metric][0]); + + echo ''; + } + } + + echo '
%s%s
'; + echo '
'; + echo '
'; +?> diff --git a/htdocs/password_checker.php b/htdocs/password_checker.php new file mode 100644 index 0000000..c616e2e --- /dev/null +++ b/htdocs/password_checker.php @@ -0,0 +1,88 @@ +%s',_('Password Checker Tool')); + +echo '
'; +echo ''; +printf('',$request['attribute']); + +echo ''; + +echo ''; +printf('',_('Compare')); +printf('', + (obfuscate_password_display($request['enc_type']) ? 'password' : 'text'),htmlspecialchars($request['hash'])); +echo ''; + +echo ''; +printf('',_('To')); +printf('', + htmlspecialchars($request['password'])); +echo ''; + +echo ''; +echo ''; + +echo ''; +echo ''; +echo '
%s
%s
 '; + +if ($request['action'] == 'compare') { + echo '    '; + + if (password_check($request['hash'],$request['password'],$request['attribute'])) + printf('%s',_('Passwords match!')); + else + printf('%s',_('Passwords do not match!')); + + echo ''; +} + +echo '
'; +echo '
'; + +# Pull our password from the form that opened this window. +if ($request['componentid']) { + echo ''; +} + +# Capture the output and put into the body of the page. +$www['body'] = new block(); +$www['body']->SetBody(ob_get_contents()); +$www['page']->block_add('body',$www['body']); +ob_end_clean(); + +# Render the popup. +$www['page']->display(array('CONTROL'=>false,'FOOT'=>false,'HEAD'=>false,'TREE'=>false)); +?> diff --git a/htdocs/purge_cache.php b/htdocs/purge_cache.php new file mode 100644 index 0000000..339fe73 --- /dev/null +++ b/htdocs/purge_cache.php @@ -0,0 +1,33 @@ +_('Purge cache'), + 'body'=>$body, + 'type'=>'info'), + get_request('meth','REQUEST') == 'ajax' ? null : 'index.php'); +?> diff --git a/htdocs/query_engine.php b/htdocs/query_engine.php new file mode 100644 index 0000000..a94fedd --- /dev/null +++ b/htdocs/query_engine.php @@ -0,0 +1,19 @@ +getIndex(),get_request('query','REQUEST',false,null)); +$request['page']->accept(); +?> diff --git a/htdocs/rdelete.php b/htdocs/rdelete.php new file mode 100644 index 0000000..bb864a9 --- /dev/null +++ b/htdocs/rdelete.php @@ -0,0 +1,89 @@ +dnExists($dn)) + system_message(array( + 'title'=>_('Entry does not exist'), + 'body'=>sprintf('%s (%s)',_('Unable to delete entry, it does not exist'),$dn), + 'type'=>'error')); + else + array_push($request['parent'],$dn); + +printf('

%s

',_('Delete LDAP entries')); +printf('

%s

',_('Recursive delete progress')); + +# Prevent script from bailing early on a long delete +@set_time_limit(0); + +foreach ($request['parent'] as $dn) { + echo '

'; + echo ''; + $result = pla_rdelete($app['server'],$dn); + echo '
'; + + if ($result) { + printf(_('Entry %s and sub-tree deleted successfully.'),''.$dn.''); + + } else { + system_message(array( + 'title'=>_('Could not delete the entry.').sprintf(' (%s)',pretty_print_dn($request['dn'])), + 'body'=>ldap_error_msg($app['server']->getErrorMessage(null),$app['server']->getErrorNum(null)), + 'type'=>'error')); + } +} + +function pla_rdelete($server,$dn) { + # We delete all children, not only the visible children in the tree + $children = $server->getContainerContents($dn,null,0,'(objectClass=*)',LDAP_DEREF_NEVER); + + if (! is_array($children) || count($children) == 0) { + printf('%s %s...',_('Deleting'),$dn); + + if ($server->delete($dn)) { + printf(' %s
',_('Success')); + return true; + + } else { + system_message(array( + 'title'=>_('Could not delete the entry.').sprintf(' (%s)',pretty_print_dn($dn)), + 'body'=>ldap_error_msg($server->getErrorMessage(null),$server->getErrorNum(null)), + 'type'=>'error')); + } + + } else { + foreach ($children as $child_dn) + pla_rdelete($server,$child_dn); + + printf('%s %s...',_('Deleting'),$dn); + + if ($server->delete($dn)) { + printf(' %s
',_('Success')); + return true; + + } else { + system_message(array( + 'title'=>_('Could not delete the entry.').sprintf(' (%s)',pretty_print_dn($dn)), + 'body'=>ldap_error_msg($server->getErrorMessage(null),$server->getErrorNum(null)), + 'type'=>'error')); + } + } +} +?> diff --git a/htdocs/refresh.php b/htdocs/refresh.php new file mode 100644 index 0000000..385c4c6 --- /dev/null +++ b/htdocs/refresh.php @@ -0,0 +1,46 @@ +getIndex(),'tree'); + del_cached_item($app['server']->getIndex(),'tree'); + + if ($tree) + $openDNs = $tree->listOpenItems(); + else + $openDNs = array(); + + $tree = Tree::getInstance($app['server']->getIndex()); + + foreach ($openDNs as $value) { + $entry = $tree->getEntry($value); + if (! $entry) { + $tree->addEntry($value); + $entry = $tree->getEntry($value); + } + + $tree->readChildren($value,true); + $entry->open(); + } + + set_cached_item($app['server']->getIndex(),'tree','null',$tree); +} + +if (get_request('meth','REQUEST') == 'ajax') + header(sprintf('Location: cmd.php?cmd=draw_tree_node&noheader=%s&server_id=%s&meth=ajax&frame=TREE',get_request('noheader','REQUEST',false,0),$app['server']->getIndex())); +else + header(sprintf('Location: cmd.php?server_id=%s',$app['server']->getIndex())); + +die(); +?> diff --git a/htdocs/rename.php b/htdocs/rename.php new file mode 100644 index 0000000..96c2e33 --- /dev/null +++ b/htdocs/rename.php @@ -0,0 +1,64 @@ +getContainer($request['dnSRC']); + +# Error checking +if (! $app['server']->isBranchRenameEnabled()) { + # We search all children, not only the visible children in the tree + $children = $app['server']->getContainerContents($request['dnSRC'],null,0,'(objectClass=*)',LDAP_DEREF_NEVER); + + if (count($children) > 0) + error(_('You cannot rename an entry which has children entries (eg, the rename operation is not allowed on non-leaf entries)'),'error','index.php'); +} + +$request['dnDST'] = sprintf('%s,%s',$request['rdnDST'],$request['container']); + +if ($request['dnDST'] == $request['dnSRC']) + error(_('You did not change the RDN'),'error','index.php'); + +$rdnattr = array(); +$rdnattr['SRC'] = explode('=',$request['dnSRC']); +$rdnattr['SRC'] = $rdnattr['SRC'][0]; + +$new_dn_value = explode('=',$request['rdnDST'],2); +$rdnattr['DST'] = $new_dn_value[0]; + +if (count($new_dn_value) != 2 || ! isset($new_dn_value[1])) + error(_('Invalid RDN value'),'error','index.php'); + +$deleteoldrdn = $rdnattr['SRC'] == $rdnattr['DST']; +$success = $app['server']->rename($request['dnSRC'],$request['rdnDST'],$request['container'],$deleteoldrdn); + +if ($success) { + $rename_message = sprintf('%s',_('Rename successful!')); + $redirect_url = sprintf('cmd.php?cmd=template_engine&server_id=%s&dn=%s&template=%s', + $app['server']->getIndex(),rawurlencode($request['dnDST']),get_request('template','REQUEST')); + + system_message(array( + 'title'=>_('Rename Entry'), + 'body'=>$rename_message, + 'type'=>'info'), + $redirect_url); + +} else { + system_message(array( + 'title'=>_('Could not rename the entry.'), + 'body'=>ldap_error_msg($app['server']->getErrorMessage(null),$app['server']->getErrorNum(null)), + 'type'=>'error')); +} +?> diff --git a/htdocs/rename_form.php b/htdocs/rename_form.php new file mode 100644 index 0000000..aebc5fb --- /dev/null +++ b/htdocs/rename_form.php @@ -0,0 +1,40 @@ +getIndex(),get_request('template','REQUEST',false,'none')); +$request['page']->setDN($request['dn']); +$request['page']->accept(); + +# Render the form +$request['page']->drawTitle(sprintf('%s %s',_('Rename'),get_rdn($request['dn']))); +$request['page']->drawSubTitle(); + +echo '
'; +printf('%s %s %s:

',_('Rename'),get_rdn($request['dn']),_('to a new object')); + +echo '
'; +printf('',$app['server']->getIndex()); +printf('',rawurlencode($request['dn'])); +printf('',$request['template']); +printf('',get_rdn($request['dn'])); +printf('',_('Rename')); +echo '
'; + +echo '
'; +echo "\n"; +?> diff --git a/htdocs/schema.php b/htdocs/schema.php new file mode 100644 index 0000000..aa4a749 --- /dev/null +++ b/htdocs/schema.php @@ -0,0 +1,640 @@ +%s.

%s
  • %s
  • %s
  • %s
  • %s
', + _('Could not retrieve schema from'),$app['server']->getName(), + _('This could happen for several reasons, the most probable of which are:'),_('The server does not fully support the LDAP protocol.'), + _('Your version of PHP does not correctly perform the query.'),_('phpLDAPadmin doesn\'t know how to fetch the schema for your server.'), + _('Or lastly, your LDAP server doesnt provide this information.')); + +printf('

%s %s

',_('Schema for server'),$app['server']->getName()); + +$entry['schema_types'] = array( + 'objectclasses'=>_('ObjectClasses'), + 'attributes'=>_('Attribute Types'), + 'syntaxes'=>_('Syntaxes'), + 'matching_rules'=>_('Matching Rules')); + +echo '
'; +echo '
'; + +$counter = 0; +foreach ($entry['schema_types'] as $item => $value) { + if ($counter++) + echo ' | '; + + $entry['href'][$item] = sprintf('cmd=schema&server_id=%s&view=%s',$app['server']->getIndex(),$item); + + if ($entry['view'] == $item) { + echo _($value); + + } else { + if (isAjaxEnabled()) + printf('%s', + htmlspecialchars($entry['href'][$item]),htmlspecialchars($entry['href'][$item]),$value,$value,$value); + else + printf('%s',htmlspecialchars($entry['href'][$item]),_($value)); + } +} + +echo '
'; +echo '
'; + +switch($entry['view']) { + case 'syntaxes': + $highlight_oid = get_request('highlight_oid','GET',false,false); + + echo ''; + printf('',_('Syntax OID'),_('Description')); + + $counter = 1; + + $schema_syntaxes = $app['server']->SchemaSyntaxes(); + if (! $schema_syntaxes) + error($schema_error_str,'error','index.php'); + + foreach ($schema_syntaxes as $syntax) { + $counter++; + $oid = $syntax->getOID(); + $desc = $syntax->getDescription(); + + if ($highlight_oid && $highlight_oid == $oid) + echo ''; + + else + printf('',$counter%2==0?'even':'odd'); + + printf('',$oid,$desc); + } + + echo '
%s%s
%s%s
'; + break; + + case 'attributes': + $entry['attr_types'] = array( + 'desc' => _('Description'), + 'obsolete' => _('Obsolete'), + 'inherits' => _('Inherits from'), + 'equality' => _('Equality'), + 'ordering' => _('Ordering'), + 'substring_rule' => _('Substring Rule'), + 'syntax' => _('Syntax'), + 'single_valued' => _('Single Valued'), + 'collective' => _('Collective'), + 'user_modification' => _('User Modification'), + 'usage' => _('Usage'), + 'maximum_length' => _('Maximum Length'), + 'aliases' => _('Aliases'), + 'used_by_objectclasses' => _('Used by objectClasses'), + 'force_as_may' => _('Force as MAY by config') + ); + + $sattrs = $app['server']->SchemaAttributes(); + + if (! $sattrs || ! $app['server']->SchemaObjectClasses()) + error($schema_error_str,'error','index.php'); + + printf('%s:',_('Jump to an attribute type')); + echo '
'; + echo '
'; + echo ''; + printf('',$entry['view']); + printf('',$app['server']->getIndex()); + + if (isAjaxEnabled()) { + drawJSItems($sattrs); + echo ''; + + echo ''; + foreach ($sattrs as $name => $attr) + printf('', + $name,$name == $entry['value'] ? 'selected="selected" ': '',$attr->getName(false)); + echo ''; + + if (isAjaxEnabled()) + printf('',_('Go')); + else + printf('',_('Go')); + echo '
'; + echo '
'; + echo '
'; + + foreach ($sattrs as $attr) { + if (isAjaxEnabled() || (is_null($entry['value']) || ! trim($entry['value']) || $entry['value']==$attr->getName())) { + if ((! is_null($entry['value']) && $entry['value']==$attr->getName()) || ! trim($entry['value'])) + $entry['viewed'] = true; + + if (isAjaxEnabled() && $entry['value']) + printf('
',$attr->getName(),strcasecmp($entry['value'],$attr->getName()) ? 'none' : 'block'); + else + printf('
',$attr->getName()); + + echo ''; + printf('', + $attr->getName(),$attr->getName(false)); + + $counter = 0; + + foreach ($entry['attr_types'] as $item => $value) { + + printf('',++$counter%2 ? 'odd' : 'even'); + printf('',$value); + + switch ($item) { + case 'desc': + printf('', + is_null($attr->getDescription()) ? + '('._('no description').')' : $attr->getDescription()); + + echo ''; + printf('',++$counter%2 ? 'odd' : 'even'); + echo ''; + printf('',$attr->getOID()); + + break; + + case 'obsolete': + printf('',$attr->getIsObsolete() ? ''._('Yes').'' : _('No')); + break; + + case 'inherits': + echo ''; + break; + + case 'equality': + echo ''; + break; + + case 'ordering': + printf('', + is_null($attr->getOrdering()) ? '('._('not specified').')' : $attr->getOrdering()); + break; + + case 'substring_rule': + printf('', + is_null($attr->getSubstr()) ? '('._('not specified').')' : $attr->getSubstr()); + break; + + case 'syntax': + echo ''; + break; + + case 'single_valued': + printf('',$attr->getIsSingleValue() ? _('Yes') : _('No')); + break; + + case 'collective': + printf('',$attr->getIsCollective() ? _('Yes') : _('No')); + break; + + case 'user_modification': + printf('',$attr->getIsNoUserModification() ? _('No') : _('Yes')); + break; + + case 'usage': + printf('',$attr->getUsage() ? $attr->getUsage() : '('._('not specified').')'); + break; + + case 'maximum_length': + echo ''; + break; + + case 'aliases': + echo ''; + break; + + case 'used_by_objectclasses': + echo ''; + break; + + case 'force_as_may': + printf('',$attr->isForceMay() ? _('Yes') : _('No')); + break; + + } + echo ''; + } + echo '
%s
%s%s
OID%s%s'; + + if (is_null($attr->getSupAttribute())) + printf('(%s)',_('none')); + + else { + $href = htmlspecialchars(sprintf('%s&viewvalue=%s',$entry['href']['attributes'],strtolower($attr->getSupAttribute()))); + if (isAjaxEnabled()) + printf('%s', + $href,strtolower($attr->getSupAttribute()),$attr->getSupAttribute()); + else + printf('%s',$href,$attr->getSupAttribute()); + } + + echo ''; + + if (is_null($attr->getEquality())) + printf('(%s)',_('not specified')); + + else { + $href = htmlspecialchars(sprintf('%s&viewvalue=%s',$entry['href']['matching_rules'],$attr->getEquality())); + if (isAjaxEnabled()) + printf('%s', + $href,$href,_('Matching Rules'),$attr->getEquality(),$attr->getEquality()); + else + printf('%s',$href,$attr->getEquality()); + } + + echo '%s%s'; + + if (is_null($attr->getType())) { + echo $attr->getSyntaxOID(); + + } else { + $href = htmlspecialchars(sprintf('%s&highlight_oid=%s',$entry['href']['syntaxes'],$attr->getSyntaxOID())); + if (isAjaxEnabled()) + printf('%s (%s)', + $href,$href,_('Syntaxes'),'',$attr->getType(),$attr->getSyntaxOID()); + else + printf('%s (%s)',$href,$attr->getType(),$attr->getSyntaxOID()); + } + + echo '%s%s%s%s'; + + if ( is_null($attr->getMaxLength())) + echo '('._('not applicable').')'; + + else + printf('%s %s',number_format($attr->getMaxLength()), + $attr->getMaxLength()>1 ? _('characters') : _('character')); + + echo ''; + + if (count($attr->getAliases()) == 0) + printf('(%s)',_('none')); + + else + foreach ($attr->getAliases() as $alias) { + $href = htmlspecialchars(sprintf('%s&viewvalue=%s',$entry['href']['attributes'],strtolower($alias))); + if (isAjaxEnabled()) + printf('%s', + $href,strtolower($alias),$alias); + else + printf('%s',$href,$alias); + } + + echo ''; + + if (count($attr->getUsedInObjectClasses()) == 0) + printf('(%s)',_('none')); + + else + foreach ($attr->getUsedInObjectClasses() as $objectclass) { + $href = htmlspecialchars(sprintf('%s&viewvalue=%s',$entry['href']['objectclasses'],strtolower($objectclass))); + if (isAjaxEnabled()) + printf('%s ', + $href,$href,_('ObjectClasses'),strtolower($objectclass),$objectclass); + else + printf('%s ',$href,$objectclass); + } + + echo '%s
'; + echo '
'; + echo '
'; + } + } + + break; + + case 'matching_rules': + $schema_matching_rules = $app['server']->MatchingRules(); + if (! $schema_matching_rules) + error($schema_error_str,'error','index.php'); + + printf('%s
',_('Jump to a matching rule')); + + echo '
'; + echo '
'; + echo ''; + printf('',$app['server']->getIndex()); + echo ''; + + if (isAjaxEnabled()) { + drawJSItems($schema_matching_rules); + echo ''; + + echo ''; + foreach ($schema_matching_rules as $rule) + printf('', + $rule->getName(), + ($rule->getName() == $entry['value'] ? 'selected="selected"': ''), + $rule->getName(false)); + + echo ''; + + if (isAjaxEnabled()) + printf('',_('Go')); + else + printf('',_('Go')); + echo '
'; + echo '
'; + echo '
'; + + echo ''; + printf('', + _('Matching Rule OID'),_('Name'),_('Used by Attributes')); + + $counter = 1; + + foreach ($schema_matching_rules as $rule) { + $counter++; + $oid = $rule->getOID(); + $desc = $rule->getName(false); + + if (isAjaxEnabled() || (is_null($entry['value']) || ! trim($entry['value']) || $entry['value']==$rule->getName())) { + if ((! is_null($entry['value']) && $entry['value']==$rule->getName()) || ! trim($entry['value'])) + $entry['viewed'] = true; + + if (null != $rule->getDescription()) + $desc .= sprintf(' (%s)',$rule->getDescription()); + + if ( $rule->getIsObsolete()) + $desc .= sprintf(' %s',_('Obsolete')); + + if (isAjaxEnabled() && $entry['value']) + printf('',$counter%2 ? 'odd' : 'even',$rule->getName(), + strcasecmp($entry['value'],$rule->getName()) ? 'none' : ''); + else + printf('',$counter%2 ? 'odd' : 'even',$rule->getName()); + printf('',$oid); + printf('',$desc); + + echo ''; + echo ''; + } + } + + echo '
%s%s%s
%s%s'; + + if (count($rule->getUsedByAttrs()) == 0) { + printf('
(%s)


',_('none')); + + } else { + echo '
'; + echo '
'; + echo '
'; + echo ''; + printf('',$app['server']->getIndex()); + echo ''; + + printf('
'; + + if (isAjaxEnabled()) + printf('', + _('Go'),$app['server']->getIndex(),_('Attributes'),$rule->getName()); + else + printf('',_('Go')); + echo '
'; + echo '
'; + echo '
'; + } + echo '
'; + break; + + case 'objectclasses': + $socs = $app['server']->SchemaObjectClasses(); + if (! $socs) + error($schema_error_str,'error','index.php'); + + printf('%s:',_('Jump to an objectClass')); + + echo '
'; + echo '
'; + echo ''; + printf('',$entry['view']); + printf('',$app['server']->getIndex()); + + if (isAjaxEnabled()) { + drawJSItems($socs); + echo ''; + + echo ''; + foreach ($socs as $name => $oclass) + printf('', + $name,$name == $entry['value'] ? 'selected="selected" ': '',$oclass->getName(false)); + + echo ''; + + if (isAjaxEnabled()) + printf('',_('Go')); + else + printf('',_('Go')); + echo '
'; + echo '
'; + echo '
'; + + foreach ($socs as $name => $oclass) { + if (isAjaxEnabled() || (is_null($entry['value']) || ! trim($entry['value']) || $entry['value']==$oclass->getName())) { + if ((! is_null($entry['value']) && $entry['value']==$oclass->getName()) || ! trim($entry['value'])) + $entry['viewed'] = true; + + if (isAjaxEnabled() && $entry['value']) + printf('
',$oclass->getName(),strcasecmp($entry['value'],$oclass->getName()) ? 'none' : ''); + else + printf('
',$oclass->getName()); + + echo ''; + printf('',$name,$oclass->getName(false)); + printf('',_('OID'),$oclass->getOID()); + + if ($oclass->getDescription()) + printf('',_('Description'),$oclass->getDescription()); + + printf('',_('Type'),$oclass->getType()); + + if ($oclass->getIsObsolete()) + printf('',_('This objectClass is obsolete.')); + + printf(''; + + printf(''; + + printf('', + _('Required Attributes'),_('Optional Attributes')); + + echo ''; + echo ''; + echo ''; + echo ''; + echo '
%s
%s: %s
%s: %s
%s: %s
%s
%s: ',_('Inherits from')); + if (count($oclass->getSupClasses()) == 0) + printf('(%s)',_('none')); + + else + foreach ($oclass->getSupClasses() as $i => $object_class) { + $href = htmlspecialchars(sprintf('%s&viewvalue=%s',$entry['href']['objectclasses'],strtolower($object_class))); + if (isAjaxEnabled()) + printf('%s', + $href,strtolower($object_class),$object_class); + else + printf('%s', + $href,$object_class,_('Jump to this objectClass definition'),$object_class); + + if ($i < count($oclass->getSupClasses()) - 1) + echo ', '; + } + echo '
%s: ',_('Parent to')); + if (strcasecmp($oclass->getName(),'top') == 0) { + $href = htmlspecialchars($entry['href']['objectclasses']); + if (isAjaxEnabled()) + printf('all', + $href); + else + printf('(all)',$href); + + } elseif (count($oclass->getChildObjectClasses()) == 0) + printf('(%s)',_('none')); + + else + foreach ($oclass->getChildObjectClasses() as $i => $object_class) { + $href = htmlspecialchars(sprintf('%s&viewvalue=%s',$entry['href']['objectclasses'],strtolower($object_class))); + if (isAjaxEnabled()) + printf('%s', + $href,_('Jump to this objectClass definition'),strtolower($object_class),$object_class); + else + printf('%s',$href,_('Jump to this objectClass definition'),$object_class); + + if ( $i < count($oclass->getChildObjectClasses()) - 1) + echo ', '; + } + echo '
 %s%s 
'; + + if ($attrs = $oclass->getMustAttrs(true)) { + echo '
    '; + + foreach ($attrs as $attr) { + echo '
  • '; + $href = htmlspecialchars(sprintf('%s&viewvalue=%s',$entry['href']['attributes'],$attr->getName())); + if (isAjaxEnabled()) + printf('%s', + $href,$href,_('Attributes'),$attr->getName(),$attr->getName(false)); + else + printf('%s',$href,$attr->getName(false)); + + if ($attr->getSource() != $oclass->getName(false)) { + echo '
    '; + $href = htmlspecialchars(sprintf('%s&viewvalue=%s',$entry['href']['objectclasses'],strtolower($attr->getSource()))); + printf('(%s ',_('Inherited from')); + if (isAjaxEnabled()) + printf('%s', + $href,_('Jump to this objectClass definition'),strtolower($attr->getSource()),$attr->getSource()); + else + printf('%s',$href,$attr->getSource()); + echo ')'; + } + echo '
  • '; + } + echo '
'; + + } else + printf('(%s)',_('none')); + + echo '
'; + + if ($attrs = $oclass->getMayAttrs(true)) { + echo '
    '; + + foreach ($attrs as $attr) { + echo '
  • '; + $href = htmlspecialchars(sprintf('%s&viewvalue=%s',$entry['href']['attributes'],$attr->getName())); + if (isAjaxEnabled()) + printf('%s', + $href,$href,_('Attributes'),$attr->getName(),$attr->getName(false)); + else + printf('%s',$href,$attr->getName(false)); + + if ($attr->getSource() != $oclass->getName(false)) { + echo '
    '; + $href = htmlspecialchars(sprintf('%s&viewvalue=%s',$entry['href']['objectclasses'],strtolower($attr->getSource()))); + printf('(%s ',_('Inherited from')); + if (isAjaxEnabled()) + printf('%s', + $href,_('Jump to this objectClass definition'),strtolower($attr->getSource()),$attr->getSource()); + else + printf('%s',$href,$attr->getSource()); + echo ')'; + } + + if ($oclass->isForceMay($attr->getName())) { + echo '
    '; + printf('%s',_('This attribute has been forced as a MAY attribute by the configuration')); + } + echo '
  • '; + } + echo '
'; + + } else + printf('(%s)',_('none')); + + echo '
'; + echo '
'; + echo '
'; + } + } + break; +} + +if (! is_null($entry['value']) && ! $entry['viewed']) + error(sprintf(_('No such schema item: "%s"'),$entry['value']),'error','index.php'); + +function drawJSItems($object) { + echo ''; +} +?> diff --git a/htdocs/server_info.php b/htdocs/server_info.php new file mode 100644 index 0000000..222b912 --- /dev/null +++ b/htdocs/server_info.php @@ -0,0 +1,89 @@ +getRootDSE(); + +printf('

%s%s

',_('Server info for: '),$app['server']->getName()); +printf('

%s

',_('Server reports the following information about itself')); + +if (! count($attrs)) { + echo '

'; + printf('
%s
',_('This server has nothing to report.')); + return; +} + +echo ''; +foreach ($attrs as $key => $values) { + if ($key == 'dn') + continue; + + echo ''; + + echo ''; +} +echo '
'; + + $sattr = $app['server']->getSchemaAttribute($key); + + if ($sattr && $_SESSION[APPCONFIG]->isCommandAvailable('script','schema') && $_SESSION[APPCONFIG]->getValue('appearance','show_schema_link')) { + $href = sprintf('cmd.php?cmd=schema&server_id=%s&view=attributes&viewvalue=%s',$app['server']->getIndex(),$sattr->getName()); + printf('%s', + $href,_('Click to view the schema definition for attribute type'),$sattr->getName(false),$sattr->getName(false)); + + } else + echo $key; + + echo '
 '; + echo ''; + + if (is_array($values)) + foreach ($values as $value) { + $oidtext = ''; + print ''; + + if (preg_match('/^[0-9]+\.[0-9]+/',$value)) { + printf('', + IMGDIR,$value,htmlspecialchars($value)); + + if ($oidtext = support_oid_to_text($value)) + if (isset($oidtext['ref'])) + printf('',$oidtext['ref'],$oidtext['title']); + else + printf('',$oidtext['title']); + + else + if (strlen($value) > 0) + printf('',$value); + + } else { + printf('',$value); + } + + print ''; + + if (isset($oidtext['desc']) && trim($oidtext['desc'])) + printf('',$oidtext['desc']); + else + echo ''; + + if ($oidtext) + echo ''; + } + + else + printf('',$values); + + + echo '
%s%s%s%s%s
%s
 
 
%s 
'; + echo '
'; +?> diff --git a/htdocs/show_cache.php b/htdocs/show_cache.php new file mode 100644 index 0000000..5ce6cd3 --- /dev/null +++ b/htdocs/show_cache.php @@ -0,0 +1,101 @@ +getValue('appearance','hide_debug_info')) { + echo '
    '; + + foreach (array_keys($request['dumpvar']) as $key) { + if ((in_array($key,array('cache'))) && is_array($request['dumpvar'][$key])) + foreach (array_keys($request['dumpvar'][$key]) as $server) { + foreach (array_keys($request['dumpvar'][$key][$server]) as $x) { + $index = sprintf('%s:%s',$server,$x); + + printf('
  • %s
  • ', + $key.$index,$key,$index,$key.'.'.$index,$key.$index,$key.$index); + } + } + else + printf('
  • %s
  • ', + $key,$key,$key,$key); + } + echo '
'; +} +?> + + diff --git a/htdocs/template_engine.php b/htdocs/template_engine.php new file mode 100644 index 0000000..1cfaba9 --- /dev/null +++ b/htdocs/template_engine.php @@ -0,0 +1,57 @@ +getIndex(),get_request('template','REQUEST',false,null)); + +# If we have a DN, then this is to edit the entry. +if ($request['dn']) { + $app['server']->dnExists($request['dn']) + or error(sprintf('%s (%s)',_('No such entry'),pretty_print_dn($request['dn'])),'error','index.php'); + + $request['page']->setDN($request['dn']); + $request['page']->accept(); + +} else { + if ($app['server']->isReadOnly()) + error(_('You cannot perform updates while server is in read-only mode'),'error','index.php'); + + $request['page']->setContainer(get_request('container','REQUEST')); + $request['page']->accept(); +} +?> diff --git a/htdocs/update.php b/htdocs/update.php new file mode 100644 index 0000000..45762cf --- /dev/null +++ b/htdocs/update.php @@ -0,0 +1,78 @@ +getIndex(),rawurlencode($request['dn']))); + + die(); +} + +if (! $request['dn'] || ! $app['server']->dnExists($request['dn'])) + error(sprintf(_('The entry (%s) does not exist.'),$request['dn']),'error','index.php'); + +$request['page'] = new PageRender($app['server']->getIndex(),get_request('template','REQUEST',false,'none')); +$request['page']->setDN($request['dn']); +$request['page']->accept(); +$request['template'] = $request['page']->getTemplate(); + +# Perform the modification +$result = $app['server']->modify($request['dn'],$request['template']->getLDAPmodify()); + +if ($result) { + # Fire the post modification event to the user's custom callback function. + $mustRelogin = false; + + foreach ($request['template']->getLDAPmodify() as $attr_name => $val) { + /* Was this a user's password modification who is currently + * logged in? If so, they need to logout and log back in + * with the new password. */ + if (($attr_name == 'userpassword') && + in_array($app['server']->getValue('login','auth_type'),array('cookie','session')) && + pla_compare_dns($app['server']->getLogin(),$request['dn']) === 0) + + $mustRelogin = true; + } + + # If the user password was changed, not tell the to relogin. + if ($mustRelogin) { + $app['server']->logout('user'); + unset($_SESSION['ACTIVITY'][$app['server']->getIndex()]); + + system_message(array( + 'title'=>_('Modification successful!'), + 'body'=>_('Since you changed your password, you must now login again with your new password.'), + 'type'=>'info'), + sprintf('cmd.php?cmd=login_form&server_id=%s',$app['server']->getIndex())); + + exit; + } + + $redirect_url = sprintf('cmd.php?cmd=template_engine&server_id=%s&dn=%s', + $app['server']->getIndex(),$request['template']->getDNEncode()); + + foreach ($request['template']->getLDAPmodify() as $attr => $junk) + $redirect_url .= sprintf('&modified_attrs[]=%s',$attr); + + if (get_request('meth','REQUEST') == 'ajax') + $redirect_url .= '&meth=ajax'; + + header("Location: $redirect_url"); + die(); +} +?> diff --git a/htdocs/update_confirm.php b/htdocs/update_confirm.php new file mode 100644 index 0000000..037b91d --- /dev/null +++ b/htdocs/update_confirm.php @@ -0,0 +1,253 @@ +dnExists($request['dn'])) + error(sprintf(_('The entry (%s) does not exist.'),$request['dn']),'error','index.php'); + +$request['page'] = new PageRender($app['server']->getIndex(),get_request('template','REQUEST',false,'none')); +$request['page']->setDN($request['dn']); +$request['page']->accept(); +$request['template'] = $request['page']->getTemplate(); + +$request['page']->drawTitle(get_rdn($request['template']->getDN())); +$request['page']->drawSubTitle(); + +# Confirm the updates +if (count($request['template']->getLDAPmodify(true))) { + echo '
'; + echo _('Do you want to make these changes?'); + echo '

'; + echo '
'; + + echo "\n\n"; + echo '
'; + echo '
'; + echo ''; + printf('',$app['server']->getIndex()); + printf('',$request['template']->getDNEncode(false)); + echo "\n"; + + $request['page']->drawHiddenAttributes(); + echo '
'; + + echo ''; + echo "\n"; + + printf('', + _('Attribute'),_('Old Value'),_('New Value'),_('Skip')); + echo "\n\n"; + + # If we skip objectclass changes, but there are new must/may attrs provided by the new objectclass, they need to be skip. + $mustattrs = getMustAttrs($request['template']->getAttribute('objectclass')->getValues()); + + $counter = 0; + foreach ($request['template']->getLDAPmodify(true) as $attribute) { + $counter++; + + printf('',$counter%2 ? 'even' : 'odd'); + printf('',$attribute->getFriendlyName()); + + # Show OLD Values + echo ''; + + # Show NEW Values + echo ''; + + # Show SKIP Option + $input_disabled = ''; + $input_onclick = ''; + + if ($attribute->isForceDelete() || (in_array($attribute->getName(),$mustattrs)) && $request['template']->getAttribute('objectclass')->justModified()) + $input_disabled = 'disabled="disabled"'; + + if ($attribute->getName() == 'objectclass') { + $input_onclick = ''; + + # If there are attributes being force deleted... + if (count($request['template']->getForceDeleteAttrs()) > 0) { + $input_onclick = 'onclick="if (this.checked) {'; + + # And this OC is being skipped, then these attributes can be optionally deleted. + foreach ($request['template']->getForceDeleteAttrs() as $ad_name) { + # Only if it is not a must attr by this objectclass now staying + if (! in_array($ad_name->getName(),getMustAttrs($attribute->getOldValues()))) + $input_onclick .= sprintf("document.getElementById('skip_array_%s').disabled = false;",$ad_name->getName()); + + $input_onclick .= sprintf("document.getElementById('skip_array_%s').checked = true;",$ad_name->getName()); + $input_onclick .= "\n"; + } + + $input_onclick .= '} else {'; + + # Otherwise the attributes must be deleted. + foreach ($request['template']->getForceDeleteAttrs() as $ad_name) { + $input_onclick .= sprintf("document.getElementById('skip_array_%s').checked = false;",$ad_name->getName()); + $input_onclick .= sprintf("document.getElementById('skip_array_%s').disabled = true;",$ad_name->getName()); + $input_onclick .= "\n"; + } + + $input_onclick .= '};'; + } + + # If the attributes arent force deleted... + if ($input_onclick) + $input_onclick .= 'if (this.checked) {'; + else + $input_onclick = 'onclick="if (this.checked) {'; + + # IE: There are new objectclasses that result in new values. + foreach ($request['template']->getLDAPmodify(true) as $skipattr) { + if (! $skipattr->getOldValues()) { + if (! in_array($skipattr->getName(),$mustattrs)) + $input_onclick .= sprintf("document.getElementById('skip_array_%s').disabled = true;",$skipattr->getName()); + + $input_onclick .= sprintf("document.getElementById('skip_array_%s').checked = true;",$skipattr->getName()); + $input_onclick .= "\n"; + } + } + + $input_onclick .= '} else {'; + + foreach ($request['template']->getLDAPmodify(true) as $skipattr) { + if (! $skipattr->getOldValues()) { + if (! in_array($skipattr->getName(),$mustattrs)) + $input_onclick .= sprintf("document.getElementById('skip_array_%s').disabled = false;",$skipattr->getName()); + + $input_onclick .= sprintf("document.getElementById('skip_array_%s').checked = false;",$skipattr->getName()); + $input_onclick .= "\n"; + } + } + + $input_onclick .= '};"'; + } + + printf('', + htmlspecialchars($attribute->getName()),htmlspecialchars($attribute->getName()),$input_disabled,$input_onclick); + echo ''; + echo "\n\n"; + } + + echo '
%s%s%s%s
%s'; + + if (! $attribute->getOldValues()) + printf('[%s]',_('attribute doesnt exist')); + + $dv = $attribute->getRemovedValues(); + foreach ($attribute->getOldValues() as $key => $value) { + # For multiple values, we'll highlight the changed ones + if ($x = ((count($attribute->getOldValues()) > 5) && count($attribute->getValues()) && in_array($value,$dv))) + echo ''; + + $request['page']->draw('OldValue',$attribute,$key); + + # For multiple values, close the highlighting + if ($x) + echo ''; + + echo '
'; + } + + echo '
'; + + if (! $attribute->getValueCount() || $attribute->isForceDelete()) + printf('[%s]',_('attribute deleted')); + + $dv = $attribute->getAddedValues(); + foreach ($attribute->getValues() as $key => $value) { + # For multiple values, we'll highlight the changed ones + if ($x = ((count($attribute->getValues()) > 5) && count($attribute->getOldValues()) && in_array($value,$dv))) + echo ''; + + $request['page']->draw('CurrentValue',$attribute,$key); + + # For multiple values, close the highlighting + if ($x) + echo ''; + + echo '
'; + } + + echo '
'; + + echo '
'; + echo '
'; + // @todo cant use AJAX here, it affects file uploads. + printf('', + _('Update Object')); + + printf('', + _('Cancel'), + (isAjaxEnabled() ? sprintf('onclick="return ajDISPLAY(\'BODY\',\'cmd=template_engine&dn=%s\',\'%s\');"',htmlspecialchars($request['dn']),_('Retrieving DN')) : '')); + + echo '
'; + echo '
'; + echo '
'; + + if (count($request['template']->getForceDeleteAttrs()) > 0) { + echo ''; + printf('',_('The deletion of objectClass(es)')); + printf('',implode(', ',$request['template']->getAttribute('objectclass')->getRemovedValues())); + echo ''; + printf('',_('will delete the attribute(s)')); + echo '
%s:%s
%s:'; + + $i = 0; + foreach ($request['template']->getForceDeleteAttrs() as $attribute) { + if ($i++ != 0) + echo ', '; + + echo $_SESSION[APPCONFIG]->getFriendlyHTML($attribute); + } + echo '
'; + } + +} else { + $href = sprintf('cmd=template_engine&server_id=%s&dn=%s', + $app['server']->getIndex(),$request['template']->getDNEncode()); + + echo '
'; + echo _('You made no changes'); + + if (isAjaxEnabled()) + printf(' %s.', + htmlspecialchars($href),htmlspecialchars($href),_('Retrieving DN'),_('Go back')); + else + printf(' %s.',htmlspecialchars($href),_('Go back')); + + echo '
'; +} + +function getMustAttrs($oclasses) { + global $app; + + $mustattrs = array(); + + foreach ($oclasses as $value) { + $soc = $app['server']->getSchemaObjectClass($value); + + if ($soc) + foreach ($soc->getMustAttrs() as $sma) + array_push($mustattrs,$sma->getName()); + } + + return $mustattrs; +} +?> diff --git a/htdocs/view_jpeg_photo.php b/htdocs/view_jpeg_photo.php new file mode 100644 index 0000000..d52501c --- /dev/null +++ b/htdocs/view_jpeg_photo.php @@ -0,0 +1,77 @@ +getDNAttrValues($request['dn'],null,LDAP_DEREF_NEVER,array($request['attr'])); + + break; +} + +if (! isset($jpeg_data[$request['attr']][$request['index']])) { + if (function_exists('imagecreate')) { + $im = imagecreate(160,30); + if (is_resource($im)) { + header('Content-type: image/png'); + + # Set the background + imagecolorallocatealpha($im,0xFC,0xFC,0xFE,127); + $text_color = imagecolorallocate($im,0,0,0); + imagestring($im,4,3,5,_('Image not available'),$text_color); + imagepng($im); + imagedestroy($im); + + die(); + } + } + + # We cant display an error, but we can set a system message, which will be display on the next page render. + system_message(array( + 'title'=>_('No image available'), + 'body'=>sprintf(_('Could not fetch jpeg data from LDAP server for attribute [%s].'),$request['attr']), + 'type'=>'warn')); + + die(); +} + +if (! is_array($jpeg_data[$request['attr']])) + $jpeg_data[$request['attr']] = array($jpeg_data[$request['attr']]); + +$obStatus = ob_get_status(); +if (isset($obStatus['type']) && $obStatus['type'] && $obStatus['status']) + ob_end_clean(); + +header(sprintf('Content-type: %s',$request['type'])); +header(sprintf('Content-disposition: inline; filename="%s"',$request['filename'])); +echo $jpeg_data[$request['attr']][$request['index']]; +die(); +?> diff --git a/htdocs/welcome.php b/htdocs/welcome.php new file mode 100644 index 0000000..e427281 --- /dev/null +++ b/htdocs/welcome.php @@ -0,0 +1,29 @@ +'; +echo '

'; +printf('%s',IMGDIR,_('phpLDAPadmin logo'),_('phpLDAPadmin logo')); +echo '

'; +echo _('Use the menu to the left to navigate'); +echo '

'; + +if ($_SESSION[APPCONFIG]->isCommandAvailable('cmd','oslinks')) { + printf('%s',get_href('credits'),_('Credits')); + printf(' | %s',get_href('documentation'),_('Documentation')); + printf(' | %s',get_href('donate'),_('Donate')); + echo '

'; +} + +echo '
'; +?> diff --git a/index.php b/index.php new file mode 100644 index 0000000..716e607 --- /dev/null +++ b/index.php @@ -0,0 +1,11 @@ + diff --git a/lib/AJAXTree.php b/lib/AJAXTree.php new file mode 100644 index 0000000..300a976 --- /dev/null +++ b/lib/AJAXTree.php @@ -0,0 +1,307 @@ +" + * @param boolean $first_child is the first child entry, which is normally the "Create New Entry" option + * @param boolean $last_child is the last child entry, which is normally the "Create New Entry" option + */ + protected function draw_item($item,$level,$first_child=true,$last_child=true) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $server = $this->getServer(); + + # Level pre-treatment + $code = ''; + if (is_string($level)) { + for ($i=0; $i 0) + $code = '0' * $level; + + $level = strlen($code); + + # Get entry to display as node + $entry = $this->getEntry($item); + + # If the entry doesnt exist, we'll add it. + if (! $entry) { + $this->addEntry($item); + $entry = $this->getEntry($item); + } + + # If the entry doesnt exist in the server, then return here with an empty string. + if (! $entry) + return ''; + + # Get our children. + $child_count = $this->readChildrenNumber($entry->getDN()); + + $nb = 0; + if ($first_child) + $nb += 1; + if ($last_child) + $nb += 2; + + $imgs['expand'] = array('tree_expand.png','tree_expand.png','tree_expand_corner.png', + ($level > 0) ? 'tree_expand_corner.png' : 'tree_expand_corner_first.png'); + + $imgs['collapse'] = array('tree_collapse.png','tree_collapse.png','tree_collapse_corner.png', + ($level > 0) ? 'tree_collapse_corner.png' : 'tree_collapse_corner_first.png'); + + $imgs['tree'] = array('tree_split.png','tree_split.png','tree_corner.png','tree_corner.png'); + + /** Information on array[$nb] + * nb == 1 => the node is the first child + * nb == 2 => the node is the last child + * nb == 3 => the node is the unique child + * nb == 0 => the node is a child */ + $new_code = array('1','1','0','0'); + + # Links + $parms['openclose'] = htmlspecialchars(sprintf('server_id=%s&dn=%s&code=%s%s',$this->getServerID(),$entry->getDNEncode(),$code,$new_code[$nb])); + $parms['edit'] = htmlspecialchars(sprintf('cmd=template_engine&server_id=%s&dn=%s',$this->getServerID(),$entry->getDNEncode())); + $href = sprintf('cmd.php?%s',$parms['edit']); + + # Each node has a unique id based on dn + $node_id = sprintf('node%s',base64_encode(sprintf('%s-%s',$server->getIndex(),$entry->getDN()))); + $node_id = str_replace('=','_',$node_id); + + if ($level == 0) + printf('
',$this->getDepth()+3-1); + + printf(''; + + printf('
',$node_id,($entry->isOpened() ? 'block' : 'none')); + if ($entry->isOpened()) + $this->draw_children($entry,$code.$new_code[$nb]); + + echo '
'; + + if ($level == 0) + echo '
'; + if (! $onlytree) + $this->draw_server_name(); + + $this->javascript = ''; + $javascript_id = 0; + + /* Do we have what it takes to authenticate here, or do we need to + * present the user with a login link (for 'cookie' and 'session' auth_types)? + */ + if ($server->isLoggedIn(null)) { + if (! $onlytree) { + $this->draw_menu(); + + if ($server->getAuthType() != 'config') + $this->draw_logged_in_user(); + else + printf('',$this->getDepth()+3); + + if ($server->isReadOnly()) + printf('',$this->getDepth()+3-1,_('read only')); + else + printf('',$this->getDepth()+3); + + printf(''; + + echo '
 
(%s)
 
 
', + $_SESSION[APPCONFIG]->getValue('appearance','tree_width') ? sprintf('width: %spx; ',$_SESSION[APPCONFIG]->getValue('appearance','tree_width')) : '', + $_SESSION[APPCONFIG]->getValue('appearance','tree_height') ? sprintf('height: %spx; ',$_SESSION[APPCONFIG]->getValue('appearance','tree_height')) : '', + $server->getIndex()); + } + + echo ''; + + if (! count($this->getBaseEntries())) { + # We didnt get any baseDN entries in our tree? + printf('', + $this->getDepth()+3-2, + _('Could not determine the root of your LDAP tree.'), + _('It appears that the LDAP server has been configured to not reveal its root.'), + _('Please specify it in config.php')); + + echo '
%s
%s
%s
'; + + if (! $onlytree) + echo '
'; + return; + } + + /** + * Check if the LDAP server is not yet initialized + * (ie, the base DN configured in config.php does not exist) + */ + foreach ($this->getBaseEntries() as $base) { + if (! $base->isInLDAP()) { + $js_drawn = false; + $javascript_id++; + + $rdn = explode('=',get_rdn($base->getDN())); + printf('
%s
%s
%s %s
'; + + if (! $onlytree) + echo ''; + + # We are not logged in, draw a login... link. + } else { + switch ($server->getAuthType()) { + case 'cookie': + case 'http': + case 'session': + $this->draw_login_link(); + break; + + case 'config': + case 'proxy': + case 'sasl': + break; + + default: + die(sprintf('Error: %s hasnt been configured for auth_type %s',__METHOD__,$server->getAuthType())); + } + } + + # Tree Footer. + echo ''; + echo "\n\n"; + + if (! $js_drawn) { + $this->draw_javascript(); + $js_drawn = true; + } + } + + /** + * Draw the server name + */ + protected function draw_server_name() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $server = $this->getServer(); + + echo ''; + printf('%s',IMGDIR,_('Server')); + printf('',$this->getDepth()+3-1); + printf('%s',$server->getName()); + + if (! is_null($server->inactivityTime())) { + $m = sprintf(_('Inactivity will log you off at %s'), + strftime('%H:%M',$server->inactivityTime())); + printf(' %s',IMGDIR,$m,'Timeout'); + } + echo ''; + } + + /** + * Draw the tree menu options + */ + protected function draw_menu() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $links = ''; + + if (is_array($_SESSION[APPCONFIG]->getValue('menu','session'))) + foreach ($_SESSION[APPCONFIG]->getValue('menu','session') as $link => $title) { + if ($this->get_menu_item($link)) + $links .= sprintf('%s',$this->get_menu_item($link)); + } + + # Finally add our logout link. + $links .= sprintf('%s',$this->get_logout_menu_item()); + + # Draw the quick-links below the server name: + if ($links) { + printf('',$this->getDepth()+3-1); + printf('%s
',$links); + echo ''; + } + } + + /** + * Get the HTML for each tree menu option + */ + protected function get_menu_item($item) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $server = $this->getServer(); + $menu = array(); + + switch($item) { + case 'schema': + if (! $_SESSION[APPCONFIG]->isCommandAvailable('script','schema')) + return ''; + + $menu['cmd'] = 'schema'; + $menu['ajax'] = _('Loading Schema'); + $menu['div'] = 'BODY'; + $menu['title'] = _('View schema for'); + $menu['img'] = 'schema-big.png'; + $menu['name'] = _('schema'); + + break; + + case 'search': + if (! $_SESSION[APPCONFIG]->isCommandAvailable('script','query_engine')) + return ''; + + $menu['cmd'] = 'query_engine'; + $menu['ajax'] = _('Loading Search'); + $menu['div'] = 'BODY'; + $menu['title'] = _('Search'); + $menu['img'] = 'search-big.png'; + $menu['name'] = _('search'); + + break; + + case 'refresh': + if (! $_SESSION[APPCONFIG]->isCommandAvailable('script','refresh')) + return ''; + + $menu['cmd'] = 'refresh'; + $menu['href'] = '&noheader=1&purge=1'; + $menu['ajax'] = _('Refreshing Tree'); + $menu['div'] = sprintf('SID_%s_nodes',$server->getIndex()); + $menu['title'] = _('Refresh'); + $menu['img'] = 'refresh-big.png'; + $menu['name'] = _('refresh'); + + break; + + case 'server_info': + if (! $_SESSION[APPCONFIG]->isCommandAvailable('script','server_info')) + return ''; + + $menu['cmd'] = 'server_info'; + $menu['ajax'] = _('Loading Info'); + $menu['div'] = 'BODY'; + $menu['title'] = _('Info'); + $menu['img'] = 'info-big.png'; + $menu['name'] = _('info'); + + break; + + case 'monitor': + if (! $_SESSION[APPCONFIG]->isCommandAvailable('script','monitor')) + return ''; + + $attrs = $server->getRootDSE(); + if (! $attrs || ! isset($attrs['monitorcontext'])) + return ''; + + $menu['cmd'] = 'monitor'; + $menu['ajax'] = _('Loading Monitor Info'); + $menu['div'] = 'BODY'; + $menu['title'] = _('Monitor'); + $menu['img'] = 'monitorserver-big.png'; + $menu['name'] = _('monitor'); + + break; + + case 'import': + if (! $_SESSION[APPCONFIG]->isCommandAvailable('script','import_form') || ! $_SESSION[APPCONFIG]->isCommandAvailable('script','import') || $server->isReadOnly()) + return ''; + + $menu['cmd'] = 'import_form'; + $menu['ajax'] = _('Loading Import'); + $menu['div'] = 'BODY'; + $menu['title'] = _('Import'); + $menu['img'] = 'import-big.png'; + $menu['name'] = _('import'); + + break; + + case 'export': + if (! $_SESSION[APPCONFIG]->isCommandAvailable('script','export_form') || ! $_SESSION[APPCONFIG]->isCommandAvailable('script','export')) + return ''; + + $menu['cmd'] = 'export_form'; + $menu['ajax'] = _('Loading Export'); + $menu['div'] = 'BODY'; + $menu['title'] = _('Export'); + $menu['img'] = 'export-big.png'; + $menu['name'] = _('export'); + + break; + + default: + return false; + } + + $href_parms = htmlspecialchars(sprintf('cmd=%s&server_id=%s%s',$menu['cmd'],$server->getIndex(),isset($menu['href']) ? $menu['href'] : '')); + + if (isAjaxEnabled()) + return sprintf('
%s
%s
', + $href_parms,$menu['div'],$href_parms,$menu['ajax'],$menu['title'],$server->getName(),IMGDIR,$menu['img'],$menu['name'],$menu['name']); + else + return sprintf('%s
%s
', + $href_parms,$menu['title'],$server->getName(),IMGDIR,$menu['img'],$menu['name'],$menu['name']); + } + + protected function get_logout_menu_item() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $server = $this->getServer(); + $href = sprintf('cmd.php?cmd=logout&server_id=%s',$server->getIndex()); + + if (! $_SESSION[APPCONFIG]->isCommandAvailable('script','logout') || in_array($server->getAuthType(),array('config','http','proxy','sasl'))) + return ''; + else + return sprintf('%s
%s
', + htmlspecialchars($href),_('Logout of this server'),IMGDIR,'logout-big.png',_('logout'),_('logout')); + } + + /** + * Draw the Logged in User + */ + protected function draw_logged_in_user() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $server = $this->getServer(); + + $logged_in_dn = $server->getLogin(null); + echo ''; + echo ''; + printf('%s: ',$this->getDepth()+3-1,_('Logged in as')); + + if ($server->getContainerTop($logged_in_dn) == $logged_in_dn) { + $logged_in_branch = ''; + $logged_in_dn_array = array(); + + } else { + $logged_in_branch = preg_replace('/,'.$server->getContainerTop($logged_in_dn).'$/','',$logged_in_dn); + $logged_in_dn_array = pla_explode_dn($logged_in_branch); + } + + $bases = $server->getContainerTop($logged_in_dn); + if (is_array($bases) && count($bases)) + array_push($logged_in_dn_array,$bases); + + $rdn = $logged_in_dn; + + # Some sanity checking here, in case our DN doesnt look like a DN + if (! is_array($logged_in_dn_array)) + $logged_in_dn_array = array($logged_in_dn); + + if (trim($logged_in_dn)) { + if ($server->dnExists($logged_in_dn)) + foreach ($logged_in_dn_array as $rdn_piece) { + $href = sprintf('cmd.php?cmd=template_engine&server_id=%s&dn=%s',$server->getIndex(),rawurlencode($rdn)); + printf('%s',htmlspecialchars($href),pretty_print_dn($rdn_piece)); + + if ($rdn_piece != end($logged_in_dn_array)) + echo ','; + + $rdn = substr($rdn,(1 + strpos($rdn,','))); + } + + else + echo $logged_in_dn; + + } else { + echo 'Anonymous'; + } + + echo ''; + echo ''; + } + + /** + * Recursively descend on the given dn and draw the tree in html + * + * @param dn $dn Current dn. + * @param int $level Level to start drawing (start to -1) + */ + protected function draw_item($item,$level) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $server = $this->getServer(); + + # Get entry to display as node + $entry = $this->getEntry($item); + + # If the entry doesnt exist, we'll add it. + if (! $entry) { + $this->addEntry($item); + $entry = $this->getEntry($item); + } + + # If the entry doesnt exist in the server, then return here with an empty string. + if (! $entry) + return; + + # Get our children. + $child_count = $this->readChildrenNumber($item); + + $rdn = get_rdn($item); + $dnENCODE = rawurlencode($item); + $href['expand'] = htmlspecialchars(sprintf('cmd.php?cmd=expand&server_id=%s&dn=%s',$server->getIndex(),$dnENCODE)); + $href['collapse'] = htmlspecialchars(sprintf('cmd.php?cmd=collapse&server_id=%s&dn=%s',$server->getIndex(),$dnENCODE)); + $href['edit'] = htmlspecialchars(sprintf('cmd.php?cmd=template_engine&server_id=%s&dn=%s',$server->getIndex(),$dnENCODE)); + + echo ''; + printf('',$level+2); + + # Is this node expanded? (deciding whether to draw "+" or "-") + if ($entry->isOpened()) + if (! $child_count && ! $this->getServer()->isShowCreateEnabled()) + printf('-',IMGDIR); + else + printf('-',$href['collapse'],IMGDIR); + else + if (($child_count !== false) && (! $child_count) && (! $this->getServer()->isShowCreateEnabled())) + printf('-',IMGDIR); + else + printf('+',$href['expand'],IMGDIR); + + printf('img', + $href['edit'],$server->getIndex(),preg_replace('/=/','_',base64_encode($item)),IMGDIR,$entry->getIcon()); + + printf('',$this->getDepth()+3-$level); + printf('%s',$href['edit'],$this->get_formatted_dn($entry,$level)); + + if ($child_count) + printf(' (%s)',$child_count); + + echo ''; + + if ($entry->isOpened()) { + /* Draw the "create new" link at the top of the tree list if there are more than 10 + * entries in the listing for this node. + */ + if (!$server->isReadOnly() && (count($entry->getChildren()) > 10) + && $this->getServer()->isShowCreateEnabled()) { + + $this->draw_create_link($rdn,$level,$dnENCODE); + } + + foreach ($entry->getChildren() as $dnChildEntry) + $this->draw_item($dnChildEntry,$level+1); + + # Always draw the "create new" link at the bottom of the listing + if (! $server->isReadOnly() && ! $entry->isLeaf() && $this->getServer()->isShowCreateEnabled()) { + $this->draw_create_link($rdn,$level,$dnENCODE); + } + } + + if (DEBUG_ENABLED) + debug_log('Leaving (%s,%s)',33,0,__FILE__,__LINE__,__METHOD__,$item,$level); + } + + protected function get_formatted_dn($entry,$level) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if ($level < 0) + return pretty_print_dn($entry->getDN()); + else + return draw_formatted_dn($this->getServer(),$entry); + } + + /** + * Print the HTML to show the "create new entry here". + * + * @param dn $rdn + * @param int $level + * @param dn $encoded_dn + */ + protected function draw_create_link($rdn,$level,$encoded_dn) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # print the "Create New object" link. + $href = htmlspecialchars(sprintf('cmd.php?cmd=template_engine&server_id=%s&container=%s',$this->getServerID(),$encoded_dn)); + + echo ''; + printf('',$level+3); + printf('%s',$href,IMGDIR,_('new')); + printf('%s', + $this->getDepth()+3-$level,$href,_('Create a new entry in'),$rdn,_('Create new entry here')); + echo ''; + } + + /** + * Draw login link + */ + protected function draw_login_link() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $server = $this->getServer(); + $href_parm = htmlspecialchars(sprintf('cmd=%s&server_id=%s',get_custom_file($server->getIndex(),'login_form',''),$server->getIndex())); + + echo ''; + + if (isAjaxEnabled()) { + printf('%s', + $href_parm,$href_parm,_('Loading Login'),_('Login to'),$server->getName(),IMGDIR,'login.png',_('login')); + printf('%s', + $this->getDepth()+3-2,$href_parm,$href_parm,_('Loading Login'),_('Login to'),$server->getName(),_('login')); + + } else { + printf('%s',$href_parm,IMGDIR,'login.png',_('login')); + printf('%s...',$this->getDepth()+3-2,$href_parm,_('Login')); + } + + echo ''; + + printf(' ',$this->getDepth()+3); + printf(' ',$this->getDepth()+3); + } + + /** + * If there is javascript, draw it + */ + protected function draw_javascript() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if ($this->javascript) { + echo "\n"; + echo $this->javascript; + echo "\n"; + $this->javascript = ''; + } + } + + /** + * Work out how deep the "opened" tree is. + */ + public function getDepth() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $server = $this->getServer(); + + # If we are not logged in + if (! $server->isLoggedIn(null)) + return 0; + + static $depths = array(); + + if (! isset($depths[$server->getIndex()])) { + $max = 0; # BaseDN are open, so we start at 1. + + foreach ($this->entries as $dn) { + $basedepth = count(pla_explode_dn($server->getContainerPath($dn->getDN(),'/'))); + $depth = 0; + + $depth = count(pla_explode_dn($dn->getDN()))+1-$basedepth; + + if ($depth > $max) + $max = $depth; + } + + $depths[$server->getIndex()] = $max; + } + + return $depths[$server->getIndex()]; + } +} +?> diff --git a/lib/JpegAttribute.php b/lib/JpegAttribute.php new file mode 100644 index 0000000..d440048 --- /dev/null +++ b/lib/JpegAttribute.php @@ -0,0 +1,17 @@ + diff --git a/lib/MassRender.php b/lib/MassRender.php new file mode 100644 index 0000000..f0bf67e --- /dev/null +++ b/lib/MassRender.php @@ -0,0 +1,48 @@ +%s
',__METHOD__); + + $val = $attribute->getValue($i); + + if ($attribute->getHelper()) + echo '
'; + + printf('', + $j,htmlspecialchars($attribute->getName()),$i, + $j,htmlspecialchars($attribute->getName()),$i, + htmlspecialchars($val), + $attribute->needJS('focus') ? sprintf('onfocus="focus_%s(this);" ',$attribute->getName()) : '', + $attribute->needJS('blur') ? sprintf('onblur="blur_%s(this);" ',$attribute->getName()) : '', + ($attribute->getSize() > 0) ? sprintf('size="%s"',$attribute->getSize()) : '', + ($attribute->getMaxLength() > 0) ? sprintf('maxlength="%s"',$attribute->getMaxLength()) : ''); + + if ($attribute->getHelper()) { + echo ''; + $this->draw('AttributeHelper',$attribute,$i); + echo '
'; + } + } + + protected function drawMassFormReadWriteValueBinaryAttribute($attribute,$i,$j) { + $this->drawFormReadWriteValueBinaryAttribute($attribute,$i); + } + + protected function drawMassFormReadWriteValueJpegAttribute($attribute,$i,$j) { + $this->drawFormReadOnlyValueJpegAttribute($attribute,$i); + } +} +?> diff --git a/lib/MultiLineAttribute.php b/lib/MultiLineAttribute.php new file mode 100644 index 0000000..b6d0eb5 --- /dev/null +++ b/lib/MultiLineAttribute.php @@ -0,0 +1,35 @@ +rows; + } + + public function setRows($rows) { + $this->rows = $rows; + } + + public function getCols() { + return $this->cols; + } + + public function setCols($cols) { + $this->cols = $cols; + } +} +?> diff --git a/lib/ObjectClassAttribute.php b/lib/ObjectClassAttribute.php new file mode 100644 index 0000000..939094d --- /dev/null +++ b/lib/ObjectClassAttribute.php @@ -0,0 +1,17 @@ + diff --git a/lib/PageRender.php b/lib/PageRender.php new file mode 100644 index 0000000..7d86a54 --- /dev/null +++ b/lib/PageRender.php @@ -0,0 +1,1244 @@ +server_id = $server_id; + $this->template_id = $template_id; + } + + /** + * Dummy method... + */ + protected function visitAttribute() {} + + /** + * Get our templates applicable for this object + */ + protected function getTemplates() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + return new Templates($this->server_id); + } + + public function getTemplate() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + return $this->template; + } + + public function getTemplateID() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + return $this->template->getID(); + } + + /** + * Initialise the PageRender + */ + public function accept() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s:%s
',time(),__METHOD__); + + if ($this->template_id) { + $templates = $this->getTemplates(); + $this->template = $templates->getTemplate($this->template_id); + + if ($this->dn) + $this->template->setDN($this->dn); + elseif ($this->container) + $this->template->setContainer($this->container); + + $this->template->accept(); + + # Process our actions + if (get_request('post_value','REQUEST')) + foreach (get_request('post_value','REQUEST') as $attr => $values) { + $attribute = $this->template->getAttribute($attr); + + if (! $attribute) + debug_dump_backtrace(sprintf('There was a post_value for an attribute [%s], but it doesnt exist?',$attr),1); + + foreach ($values as $index) + if ($attribute->getPostValue()) + $this->get('Post',$attribute,$index); + else + $this->get('AutoPost',$attribute,$index); + } + + foreach ($this->template->getAttributes(true) as $attribute) { + if (DEBUGTMP||DEBUGTMPSUB) printf('* %s [Accept:%s]
',__METHOD__,get_class($attribute)); + + $this->visit('',$attribute); + } + + // Sort our attribute values for display, if we are the custom template. + if ($this->template->getID() == 'none') + $this->template->sort(); + } + } + + public function drawTitle($title='Title') { + printf('

%s

',$title); + } + + public function drawSubTitle($subtitle=null) { + if (is_null($subtitle)) + $subtitle = sprintf('%s: %s   %s: %s', + _('Server'),$this->getServer()->getName(),_('Distinguished Name'),$this->dn); + + printf('

%s

',$subtitle); + } + + public function setDN($dn) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if ($this->container) + system_message(array( + 'title'=>__METHOD__, + 'body'=>'CONTAINER set while setting DN', + 'type'=>'info')); + + $this->dn = $dn; + } + + public function setContainer($dn) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if ($this->dn) + system_message(array( + 'title'=>__METHOD__, + 'body'=>'DN set while setting CONTAINER', + 'type'=>'info')); + + $this->container = $dn; + } + + /** + * May be overloaded in other classes + */ + protected function getMode() {} + protected function getModeContainer() {} + + /** + * Process our arguments from the templates + */ + protected function getPostAttribute($attribute,$i) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $autovalue = $attribute->getPostValue(); + $args = explode(';',$autovalue['args']); + $server = $this->getServer(); + $vals = $attribute->getValues(); + + switch ($autovalue['function']) { + /** + * Join will concatenate values with a string, similiar to explode() + * eg: =php.Join(-;%sambaSID%,%sidsuffix%) + * + * * arg 0 + * - character to use when joining the attributes + * + * * arg 1 + * - values to concatenate together. we'll explode %attr% values. + */ + case 'Join': + preg_match_all('/%(\w+)(\|.+)?(\/[lU])?%/U',$args[1],$matchall); + $matchattrs = $matchall[1]; + $char = $args[0]; + + $values = array(); + $blank = 0; + foreach ($matchattrs as $joinattr) { + $attribute2 = $this->template->getAttribute($joinattr); + + if (! $attribute2) { + if (($pv = get_request(strtolower($joinattr),'REQUEST')) && isset($pv[$attribute->getName()][$i])) { + array_push($values,$pv[$attribute->getName()][$i]); + + if (! $pv[$attribute->getName()][$i]) + $blank++; + + } else { + array_push($values,''); + $blank++; + } + + } elseif (count($attribute2->getValues()) == 0) { + return; + + } elseif (count($attribute2->getValues()) != 1) { + array_push($values,''); + $blank++; + + system_message(array( + 'title'=>_('Invalid value count for [post] processing'), + 'body'=>sprintf('%s (%s [%s])',_('Function() variable expansion can only handle 1 value'), + $attribute->getName(false),count($attribute->getValues())), + 'type'=>'warn')); + + } else + array_push($values,$attribute2->getValue(0)); + } + + # If all our value expansion results in blanks, we'll return no value + if (count($matchattrs) == $blank) + if (count($vals) > 1) + $vals[$i] = null; + else + $vals = null; + + else + $vals[$i] = implode($char,$values); + + break; + + /** + * PasswordEncrypt will encrypt a password + * eg: =php.PasswordEncrypt(%enc%;%userPassword%) + * + * This function will encrypt the users password "userPassword" using the "enc" method. + */ + case 'PasswordEncrypt': + if (count($args) != 2) { + system_message(array( + 'title'=>_('Invalid argument count for PasswordEncrypt'), + 'body'=>sprintf('%s (%s)',_('PasswordEncrypt() only accepts two arguments'),$autovalue['args']), + 'type'=>'warn')); + + return; + } + + if (! $attribute->hasBeenModified()) + return; + + # Get the attribute. + if (preg_match_all('/%(\w+)(\|.+)?(\/[lU])?%/U',strtolower($args[1]),$matchall)) { + if (count($matchall[1]) != 1) + system_message(array( + 'title'=>_('Invalid value count for PasswordEncrypt'), + 'body'=>sprintf('%s (%s)',_('Unable to get the attribute value for PasswordEncrypt()'),count($matchall[1])), + 'type'=>'warn')); + + $passwordattr = $matchall[1][0]; + $passwordvalue = $_REQUEST['new_values'][$passwordattr][$i]; + + } else + $passwordvalue = $args[1]; + + if (! trim($passwordvalue) || in_array($passwordvalue,$attribute->getOldValues())) + return; + + # Get the encoding + if ($passwordattr && preg_match_all('/%(\w+)(\|.+)?(\/[lU])?%/U',strtolower($args[0]),$matchall)) { + if (count($matchall[1]) != 1) + system_message(array( + 'title'=>_('Invalid value count for PasswordEncrypt'), + 'body'=>sprintf('%s (%s)',_('Unable to get the attribute value for PasswordEncrypt()'),count($matchall[1])), + 'type'=>'warn')); + + $enc = $_REQUEST[$matchall[1][0]][$passwordattr][$i]; + + } else + $enc = $args[0]; + + $enc = strtolower($enc); + + switch ($enc) { + case 'lm': + $sambapassword = new smbHash; + $vals[$i] = $sambapassword->lmhash($passwordvalue); + + break; + + case 'nt': + $sambapassword = new smbHash; + $vals[$i] = $sambapassword->nthash($passwordvalue); + + break; + + default: + $vals[$i] = password_hash($passwordvalue,$enc); + } + + $vals = array_unique($vals); + + break; + + default: + $vals = $this->get('AutoPost',$attribute,$i); + } + + if (! $vals || $vals == $attribute->getValues()) + return; + + $attribute->clearValue(); + + if (! is_array($vals)) + $attribute->setValue(array($vals)); + else + $attribute->setValue($vals); + } + + /** + * This function is invoked if we dont know which template we should be using. + * + * @return string Template ID to be used or null if the user was presented with a list. + */ + protected function getTemplateChoice() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + # First work out our template + $templates = $this->getTemplates(); + $template = $templates->getTemplate($this->template_id); + + # If the template we asked for is available + if ($this->template_id === $template->getID()) { + if (DEBUGTMP) printf('%s:%s
',__METHOD__,'Choosing the SELECTED template'); + + return $this->template_id; + + # If there are no defined templates + } elseif (count($templates->getTemplates($this->getMode(),$this->getModeContainer(),false)) <= 0) { + if (DEBUGTMP) printf('%s:%s
',__METHOD__,'Choosing the DEFAULT template, no other template applicable'); + + # Since getTemplate() returns a default template if the one we want doesnt exist, we can return $templates->getID(), it should be the default. + if ($_SESSION[APPCONFIG]->getValue('appearance','disable_default_template') AND $this->getMode() == 'creation') { + + system_message(array( + 'title'=>_('No available templates'), + 'body'=>_('There are no available active templates for this container.'), + 'type'=>'warn')); + + return 'invalid'; + + } else + return $template->getID(); + + # If there is only 1 defined template, and no default available, then that is our template. + } elseif ((count($templates->getTemplates($this->getMode(),$this->getModeContainer(),true)) == 1) && ! $this->haveDefaultTemplate()) { + if (DEBUGTMP) printf('%s:%s
',__METHOD__,'AUTOMATIC choosing a template, only 1 template applicable'); + + $template = $templates->getTemplates($this->getMode(),$this->getModeContainer(),true); + $template = array_shift($template); + + # Dont render the only available template if it is invalid. + if (! $template->isInvalid()) + return $template->getID(); + else + $this->drawTemplateChoice(); + + } else { + if (DEBUGTMP) printf('%s:%s
',__METHOD__,'SELECT a template to use.'); + + # Propose the template choice + $this->drawTemplateChoice(); + } + + # If we got here, then there wasnt a template. + return null; + } + + /** DRAW ATTRIBUTE NAME **/ + + final protected function drawNameAttribute($attribute) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + $href = sprintf('cmd.php?cmd=schema&server_id=%s&view=attributes&viewvalue=%s', + $this->getServerID(),$attribute->getName()); + + if (! $_SESSION[APPCONFIG]->getValue('appearance','show_schema_link') || !$_SESSION[APPCONFIG]->isCommandAvailable('script','schema')) + printf('%s',_($attribute->getFriendlyName())); + + elseif ($attribute->getLDAPtype()) + printf('%s', + htmlspecialchars($href), + _('Click to view the schema definition for attribute type'),$attribute->getName(false),_($attribute->getFriendlyName())); + else + printf('%s',_('This attribute is not defined in the LDAP schema'),_($attribute->getFriendlyName())); + + if (DEBUGTMPSUB) printf(' [%s]',get_class($attribute)); + } + + /** ATTRIBUTE NOTES */ + + protected function drawNotesAttribute($attribute) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + $attr_note = ''; + + foreach (array('NoteAlias','NoteRequired','NoteRDN','NoteHint','NoteRO') as $note) { + $alias_note = $this->get($note,$attribute); + + if ($alias_note) { + if (trim($attr_note)) + $attr_note .= ', '; + + $attr_note .= $alias_note; + } + } + + if ($attr_note) + printf('%s',$attr_note); + } + + protected function getNoteAliasAttribute($attribute) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + # Is there a user-friendly translation available for this attribute? + $friendly_name = $attribute->getFriendlyName(); + + if (strtolower($friendly_name) != $attribute->getName()) + return sprintf('%s', + _('Note'),$friendly_name,_('is an alias for'),$attribute->getName(false),_('alias')); + else + return ''; + } + + #@todo this function shouldnt re-calculate requiredness, it should be known in the template already - need to set the ldaptype when initiating the attribute. + protected function getNoteRequiredAttribute($attribute) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + $required_by = ''; + $sattr_required = ''; + + # Is this attribute required by an objectClass ? + $sattr = $this->getServer()->getSchemaAttribute($attribute->getName()); + if ($sattr) + $sattr_required = $sattr->getRequiredByObjectClasses(); + + if ($sattr_required) { + $oc = $this->template->getAttribute('objectclass'); + + if ($oc) + foreach ($oc->getValues() as $objectclass) { + # If this objectclass is in our required list + if (in_array_ignore_case($objectclass,$sattr_required)) { + $required_by .= sprintf('%s ',$objectclass); + continue; + } + + # If not, see if it is in our parent. + $sattr = $this->getServer()->getSchemaObjectClass($objectclass); + + if (array_intersect($sattr->getParents(),$sattr_required)) + $required_by .= sprintf('%s ',$objectclass); + } + + else + debug_dump_backtrace('How can there be no objectclasses?',1); + } + + if ($required_by) + return sprintf('%s',_('Required attribute for objectClass(es)'),$required_by,_('required')); + else + return ''; + } + + protected function getNoteRDNAttribute($attribute) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + # Is this attribute required because its the RDN + if ($attribute->isRDN()) + return sprintf('rdn',_('This attribute is required for the RDN.')); + else + return ''; + } + + protected function getNoteHintAttribute($attribute) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + # Is there a hint for this attribute + if ($attribute->getHint()) + return sprintf('%s',_($attribute->getHint()),_('hint')); + else + return ''; + } + + protected function getNoteROAttribute($attribute) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + # Is this attribute is readonly + if ($attribute->isReadOnly()) + return sprintf('ro',_('This attribute has been marked as Read Only.')); + else + return ''; + } + /** DRAW HIDDEN VALUES **/ + + /** + * Draw all hidden attributes + */ + final public function drawHiddenAttributes() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + foreach ($this->template->getAttributes(true) as $attribute) + if ($attribute->hasbeenModified()) { + if ($attribute->getValues()) + foreach ($attribute->getValues() as $index => $details) + $this->draw('HiddenValue',$attribute,$index); + + # We are deleting this attribute, so we need to display an empty value + else + $this->draw('HiddenValue',$attribute,0); + } + } + + /** + * Draw specific hidden attribute + */ + final protected function drawHiddenValueAttribute($attribute,$i) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + $val = $attribute->getValue($i); + + printf('', + htmlspecialchars($attribute->getName()),$i,htmlspecialchars($attribute->getName()),$i, + htmlspecialchars($val)); + } + + /** DRAW DISPLAYED OLD VALUES **/ + protected function drawOldValuesAttribute($attribute) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + foreach ($attribute->getValues() as $index => $details) + $this->draw('OldValue',$attribute,$index); + } + + final protected function drawOldValueAttribute($attribute,$i) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + echo $attribute->getOldValue($i); + } + + /** DRAW DISPLAYED CURRENT VALUES **/ + + protected function drawCurrentValuesAttribute($attribute) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + for ($i=0;$i<$attribute->getValueCount();$i++) { + if ($i > 0) + echo '
'; + + $this->draw('CurrentValue',$attribute,$i); + } + } + + /** + * Draw the current specific value of an attribute + */ + final protected function drawCurrentValueAttribute($attribute,$i) { + if (DEBUGTMP) printf('%s
',__METHOD__); + if (DEBUGTMPSUB) printf(' [%s]',__METHOD__); + + echo htmlspecialchars($attribute->getValue($i)); + } + + /** + * Draw a input value for an attribute - used in a form. + */ + protected function drawFormValueAttribute($attribute,$i) { + if (DEBUGTMP) printf('%s
',__METHOD__); + if (DEBUGTMPSUB) printf(' [%s]',__METHOD__); + + if ($this->getServer()->isReadOnly() || $attribute->isReadOnly() + || ($attribute->isRDN() && $this->template->getType() != 'creation' && $i < count($attribute->getValues()))) + + $this->draw('FormReadOnlyValue',$attribute,$i); + else + $this->draw('FormReadWriteValue',$attribute,$i); + + # Show the ADDVALUE DIV if the attribute can have more values, and we have rendered the last value + if ($attribute->haveMoreValues() && $attribute->getValueCount() == $i+1) + printf('
',$attribute->getName()); + + if ($attribute->getPostValue()) + printf('',$attribute->getName(),$i); + } + + protected function drawFormReadOnlyValueAttribute($attribute,$i) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + $val = $attribute->getValue($i); + + printf('', + htmlspecialchars($attribute->getName()),$i,htmlspecialchars($attribute->getName()),$i,htmlspecialchars($val)); + } + + protected function drawFormReadWriteValueAttribute($attribute,$i) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + $val = $attribute->getValue($i); + + if ($attribute->getHelper() || $attribute->getVerify()) + echo ''; + + } elseif ($attribute->getVerify()) + echo ''; + + if ($attribute->getVerify()) { + printf(''; + } + + if ($attribute->getHelper() || $attribute->getVerify()) + echo '
'; + + printf('', + htmlspecialchars($attribute->getName()),$i, + htmlspecialchars($attribute->getName()),$i, + htmlspecialchars($val), + $attribute->needJS('focus') ? sprintf('onfocus="focus_%s(this);" ',$attribute->getName()) : '', + $attribute->needJS('blur') ? sprintf('onblur="blur_%s(this);" ',$attribute->getName()) : '', + ($attribute->getSize() > 0) ? sprintf('size="%s"',$attribute->getSize()) : '', + ($attribute->getMaxLength() > 0) ? sprintf('maxlength="%s"',$attribute->getMaxLength()) : ''); + + if ($attribute->getHelper()) { + echo ''; + $this->draw('AttributeHelper',$attribute,$i); + echo '
', + htmlspecialchars($attribute->getName()),$i, + htmlspecialchars($attribute->getName()),$i, + ($attribute->getSize() > 0) ? sprintf('size="%s"',$attribute->getSize()) : '', + ($attribute->getMaxLength() > 0) ? sprintf('maxlength="%s"',$attribute->getMaxLength()) : ''); + + echo ''; + printf('(%s)',_('confirm')); + echo '
'; + } + + /** + * Draw specific hidden binary attribute + */ + final protected function drawHiddenValueBinaryAttribute($attribute,$i) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + $val = $attribute->getValue($i); + + printf('', + htmlspecialchars($attribute->getName()),$i,base64_encode($val)); + } + + final protected function drawOldValueBinaryAttribute($attribute,$i) { + # If we dont have a value, we'll just return; + if (! $attribute->getOldValue($i)) + return; + + printf('[%s]',_('Binary Value')); + } + + final protected function drawCurrentValueBinaryAttribute($attribute,$i) { + printf('[%s]',_('Binary Value')); + + if (in_array($attribute->getName(),array('objectsid'))) + printf(' (%s)', binSIDtoText($attribute->getValue(0))); + } + + protected function drawFormReadOnlyValueBinaryAttribute($attribute,$i) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + $this->draw('CurrentValue',$attribute,$i); + echo '

'; + + $href = sprintf('download_binary_attr.php?server_id=%s&dn=%s&attr=%s&index=%s', + $this->getServerID(),rawurlencode($this->template->getDN()),$attribute->getName(),$i); + + printf('Save %s', + htmlspecialchars($href),IMGDIR,_('download value')); + + echo '
'; + } + + protected function drawFormReadWriteValueBinaryAttribute($attribute,$i) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + if ($attribute->getValue($i)) { + $this->draw('FormReadOnlyValue',$attribute,$i); + + if (! $attribute->isReadOnly() && $_SESSION[APPCONFIG]->isCommandAvailable('script','delete_attr')) + printf('Trash %s', + $attribute->getName(),$attribute->getFriendlyName(),$i,IMGDIR,_('delete attribute')); + + } else { + printf('
', + htmlspecialchars($attribute->getName()),$i, + htmlspecialchars($attribute->getName()),$i, + $attribute->needJS('focus') ? sprintf('onfocus="focus_%s(this);" ',$attribute->getName()) : '', + $attribute->needJS('blur') ? sprintf('onblur="blur_%s(this);" ',$attribute->getName()) : '', + ($attribute->getSize() > 0) ? 'size="'.$attribute->getSize().'"' : '', + ($attribute->getMaxLength() > 0) ? 'maxlength="'.$attribute->getMaxLength().'"' : ''); + } + } + + protected function drawFormReadWriteValueDateAttribute($attribute,$i) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + $val = $attribute->getValue($i); + + echo ''; + printf(' ', + $attribute->getName(),$i, + htmlspecialchars($attribute->getName()),$i,htmlspecialchars($val), + $attribute->needJS('focus') ? sprintf('onfocus="focus_%s(this);" ',$attribute->getName()) : '', + $attribute->needJS('blur') ? sprintf('onblur="blur_%s(this);" ',$attribute->getName()) : '', + ($attribute->getSize() > 0) ? sprintf('size="%s"',$attribute->getSize()) : '', + ($attribute->getMaxLength() > 0) ? sprintf('maxlength="%s"',$attribute->getMaxLength()) : ''); + + $this->draw('SelectorPopup',$attribute,$i); + echo ''."\n"; + } + + protected function drawFormReadWriteValueDnAttribute($attribute,$i) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + $val = $attribute->getValue($i); + + if ($attribute->getHelper()) + echo '
'; + + $input_name = sprintf('new_values[%s][%s]',htmlspecialchars($attribute->getName()),$i); + $id = sprintf('new_values_%s_%s',htmlspecialchars($attribute->getName()),$i); + + printf(' ', + $input_name,$id,htmlspecialchars($val), + $attribute->needJS('focus') ? sprintf('onfocus="focus_%s(this);" ',$attribute->getName()) : '', + $attribute->needJS('blur') ? sprintf('onblur="blur_%s(this);" ',$attribute->getName()) : '', + ($attribute->getSize() > 0) ? 'size="'.$attribute->getSize().'"' : '', + ($attribute->getMaxLength() > 0) ? 'maxlength="'.$attribute->getMaxLength().'"' : ''); + + # Draw a link for popping up the entry browser if this is the type of attribute that houses DNs. + draw_chooser_link('entry_form',$id,false); + echo ''; + + if ($attribute->getHelper()) { + echo ''; + $this->draw('Helper',$attribute,$i); + echo '
'; + } + + echo "\n"; + } + + protected function drawFormReadWriteValueGidAttribute($attribute,$i) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + $this->drawFormReadWriteValueAttribute($attribute,$i); + + $server = $this->getServer(); + $val = $attribute->getValue($i); + + # If this is a gidNumber on a non-PosixGroup entry, lookup its name and description for convenience + if ($this->template->getDN() && ! in_array_ignore_case('posixGroup',$this->getServer()->getDNAttrValue($this->template->getDN(),'objectclass'))) { + $query['filter'] = sprintf('(&(objectClass=posixGroup)(gidNumber=%s))',$val); + $query['attrs'] = array('dn','description'); + + # Reorganise our base, so that our base is first + $bases = array_unique(array_merge(array($server->getContainerTop($this->template->getDN())),$server->getBaseDN())); + + # Search our bases, until we find a match. + foreach ($bases as $base) { + $query['base'] = $base; + $group = $this->getServer()->query($query,null); + + if (count($group) > 0) { + echo '
'; + + $group = array_pop($group); + $group_dn = $group['dn']; + $group_name = explode('=',get_rdn($group_dn)); + $group_name = $group_name[1]; + $href = sprintf('cmd.php?cmd=template_engine&server_id=%s&dn=%s', + $this->getServerID(),rawurlencode($group_dn)); + + echo ''; + printf('%s',htmlspecialchars($href),$group_name); + + $description = isset($group['description']) ? $group['description'] : null; + + if (is_array($description)) + foreach ($description as $item) + printf(' (%s)',$item); + else + printf(' (%s)',$description); + + echo ''; + + break; + } + } + } + } + + /** + * Draw a Jpeg Attribute + */ + final protected function drawOldValueJpegAttribute($attribute,$i) { + if (DEBUGTMP) printf('%s
',__METHOD__); + if (DEBUGTMPSUB) printf(' [%s]',__METHOD__); + + # If we dont have a value, we'll just return; + if (! $attribute->getOldValue($i)) + return; + + draw_jpeg_photo($this->getServer(),$this->template->getDN(),$attribute->getName(),$i,false,false); + } + + /** + * Draw a Jpeg Attribute + */ + final protected function drawCurrentValueJpegAttribute($attribute,$i) { + if (DEBUGTMP) printf('%s
',__METHOD__); + if (DEBUGTMPSUB) printf(' [%s]',__METHOD__); + + # If we dont have a value, we'll just return; + if (! $attribute->getValue($i)) + return; + + # If the attribute is modified, the new value needs to be stored in a session variable for the draw_jpeg_photo callback. + if ($attribute->hasBeenModified()) { + $_SESSION['tmp'][$attribute->getName()][$i] = $attribute->getValue($i); + draw_jpeg_photo(null,$this->template->getDN(),$attribute->getName(),$i,false,false); + } else + draw_jpeg_photo($this->getServer(),$this->template->getDN(),$attribute->getName(),$i,false,false); + } + + protected function drawFormReadOnlyValueJpegAttribute($attribute,$i) { + $this->draw('HiddenValue',$attribute,$i); + $_SESSION['tmp'][$attribute->getName()][$i] = $attribute->getValue($i); + + draw_jpeg_photo(null,$this->template->getDN(),$attribute->getName(),$i,false,false); + } + + protected function drawFormReadOnlyValueMultiLineAttribute($attribute,$i) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + $val = $attribute->getValue($i); + + printf('', + ($attribute->getRows() > 0) ? $attribute->getRows() : 5, + ($attribute->getCols() > 0) ? $attribute->getCols() : 100, + htmlspecialchars($attribute->getName()),$i, + htmlspecialchars($attribute->getName()),$i, + $val); + } + + protected function drawFormReadWriteValueMultiLineAttribute($attribute,$i) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + $val = $attribute->getValue($i); + + printf('', + ($attribute->getRows() > 0) ? $attribute->getRows() : 5, + ($attribute->getCols() > 0) ? $attribute->getCols() : 100, + htmlspecialchars($attribute->getName()),$i, + htmlspecialchars($attribute->getName()),$i, + $attribute->needJS('focus') ? sprintf('onfocus="focus_%s(this);" ',$attribute->getName()) : '', + $attribute->needJS('blur') ? sprintf('onblur="blur_%s(this);" ',$attribute->getName()) : '', + $val); + } + + protected function drawFormValueObjectClassAttribute($attribute,$i) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + $val = $attribute->getValue($i); + + /* It seems that openLDAP allows us to remove additional structural objectclasses + however other LDAP servers, dont remove them (even if we ask them to). */ + # Do we have our internal attributes. + $internal = $this->template->getAttribute('structuralobjectclass'); + + if ($internal) { + $structural = in_array_ignore_case($val,$internal->getValues()); + + # We'll work it out the traditional way. + } else { + # If this schema structural? + $schema_object = ($val) ? $this->getServer()->getSchemaObjectClass($val) : false; + $structural = (is_object($schema_object) && $schema_object->getType() == 'structural'); + } + + if ($structural) { + $this->draw('FormReadOnlyValue',$attribute,$i); + + printf(' (%s)', + _('This is a structural ObjectClass and cannot be removed.'), + _('structural')); + + } else + $this->draw('FormReadWriteValue',$attribute,$i); + } + + protected function getAutoPostPasswordAttribute($attribute,$i) { + # If the password is already encoded, then we'll return + if (preg_match('/^\{.+\}.+/',$attribute->getValue($i))) + return; + + $attribute->setPostValue(array('function'=>'PasswordEncrypt','args'=>sprintf('%%enc%%;%%%s%%',$attribute->getName()))); + $this->get('Post',$attribute,$i); + } + + protected function drawOldValuePasswordAttribute($attribute,$i) { + if (DEBUGTMP) printf('%s
',__METHOD__); + if (DEBUGTMPSUB) printf(' [%s]',__METHOD__); + + $val = $attribute->getOldValue($i); + + if (obfuscate_password_display(get_enc_type($val))) + echo str_repeat('*',16); + else + echo nl2br(htmlspecialchars($attribute->getOldValue($i))); + } + + final protected function drawCurrentValuePasswordAttribute($attribute,$i) { + if (DEBUGTMP) printf('%s
',__METHOD__); + if (DEBUGTMPSUB) printf(' [%s]',__METHOD__); + + $val = $attribute->getValue($i); + + if (obfuscate_password_display(get_enc_type($val))) + echo str_repeat('*',16); + else + echo nl2br(htmlspecialchars($attribute->getValue($i))); + } + + protected function drawFormReadOnlyValuePasswordAttribute($attribute,$i) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + $server = $this->getServer(); + $val = $attribute->getValue($i); + + if (trim($val)) + $enc_type = get_enc_type($val); + else + $enc_type = $server->getValue('appearance','password_hash'); + + $obfuscate_password = obfuscate_password_display($enc_type); + + printf('
', + ($obfuscate_password ? 'password' : 'text'), + htmlspecialchars($attribute->getName()),$i,htmlspecialchars($attribute->getName()), + $i,htmlspecialchars($val),($attribute->getSize() > 0) ? 'size="'.$attribute->getSize().'"' : ''); + + if (trim($val)) + $this->draw('CheckLink',$attribute,'new_values_'.htmlspecialchars($attribute->getName()).'_'.$i); + } + + protected function drawFormReadWriteValuePasswordAttribute($attribute,$i) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + $server = $this->getServer(); + $val = $attribute->getValue($i); + + $enc_type = get_enc_type($val); + + # Set the default hashing type if the password is blank (must be newly created) + if (trim($val)) + $enc_type = get_enc_type($val); + else + $enc_type = $server->getValue('appearance','password_hash'); + + echo '
'; + + $obfuscate_password = obfuscate_password_display($enc_type); + $id = sprintf('new_values_%s_%s',htmlspecialchars($attribute->getName()),$i); + + printf('', + ($obfuscate_password ? 'password' : 'text'), + htmlspecialchars($attribute->getName()),$i,$id, + htmlspecialchars($val), + $attribute->needJS('focus') ? sprintf('onfocus="focus_%s(this);" ',$attribute->getName()) : '', + $attribute->needJS('blur') ? sprintf('onblur="blur_%s(this);" ',$attribute->getName()) : '', + ($attribute->getSize() > 0) ? sprintf('size="%s"',$attribute->getSize()) : '', + ($attribute->getMaxLength() > 0) ? sprintf('maxlength="%s"',$attribute->getMaxLength()) : ''); + + echo ''; + + if ($attribute->getHelper()) + $this->draw('Helper',$attribute,$i); + else + $this->draw('DefaultHelper',$attribute,$i); + + echo '
'; + + if ($attribute->getVerify() && $obfuscate_password) { + printf('', + htmlspecialchars($attribute->getName()),$i, + htmlspecialchars($attribute->getName()),$i, + ($attribute->getSize() > 0) ? sprintf('size="%s"',$attribute->getSize()) : '', + ($attribute->getMaxLength() > 0) ? sprintf('maxlength="%s"',$attribute->getMaxLength()) : ''); + + echo ''; + printf('(%s)',_('confirm')); + echo '
'; + } + + $this->draw('CheckLink',$attribute,$id); + echo '
'; + } + + protected function drawFormReadWriteValueSelectionAttribute($attribute,$i) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + if ($attribute->isMultiple()) { + # For multiple selection, we draw the component only one time + if ($i > 0) + return; + + $selected = array(); + $vals = $attribute->getValues(); + $j = 0; + + if (! $vals && ! is_null($attribute->getDefault()) && ! is_array($vals = $attribute->getDefault())) + $vals = array($attribute->getDefault()); + + if (($attribute->getSize() > 0) && ($attribute->getSize() < $attribute->getOptionCount())) { + + printf(''; + + } else { + echo ''; + + // For checkbox items, we need to render a blank entry, so that we detect an all-unselect situation + printf('', + htmlspecialchars($attribute->getName()),$j++, + htmlspecialchars($attribute->getName()),''); + + foreach ($attribute->getSelection() as $value => $description) { + if (in_array($value,$vals)) + $selected[$value] = true; + + printf('', + htmlspecialchars($attribute->getName()),$j++, + htmlspecialchars($attribute->getName()),$value, + $attribute->needJS('focus') ? sprintf('onfocus="focus_%s(this);" ',$attribute->getName()) : '', + $attribute->needJS('blur') ? sprintf('onblur="blur_%s(this);" ',$attribute->getName()) : '', + isset($selected[$value]) ? 'checked="checked"' : '', + $description); + } + + foreach ($vals as $val) + if (! isset($selected[$val])) + printf('', + htmlspecialchars($attribute->getName()),$j++, + htmlspecialchars($attribute->getName()),$val, + $attribute->needJS('focus') ? sprintf('onfocus="focus_%s(this);" ',$attribute->getName()) : '', + $attribute->needJS('blur') ? sprintf('onblur="blur_%s(this);" ',$attribute->getName()) : '', + $val); + + echo '
 %s
 %s
'; + } + + # This is a single value attribute + } else { + $val = $attribute->getValue($i) ? $attribute->getValue($i) : $attribute->getDefault(); + + if ($attribute->getHelper()) + echo '
'; + + $found = false; + $empty_value = false; + + # If we are a required attribute, and the selection is blank, then the user cannot submit this form. + if ($attribute->isRequired() && ! count($attribute->getSelection())) + system_message(array( + 'title'=>_('Template Value Error'), + 'body'=>sprintf('This template uses a selection list for attribute [%s], however the selection list is empty.
You may need to create some dependancy entries in your LDAP server so that this attribute renders with values. Alternatively, you may be able to define the appropriate selection values in the template file.',$attribute->getName(false)), + 'type'=>'warn')); + + printf(''; + + if ($attribute->getHelper()) { + echo '
'; + $this->draw('Helper',$attribute,$i); + echo '
'; + } + } + } + + /** + * Takes a shadow* attribute and returns the date as an integer. + * + * @param array Attribute objects + * @param string A shadow attribute name + */ + private function shadow_date($attribute) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $shadowattr = array(); + $shadowattr['lastchange'] = $this->template->getAttribute('shadowlastchange'); + $shadowattr['max'] = $this->template->getAttribute('shadowmax'); + + $shadow = array(); + $shadow['lastchange'] = $shadowattr['lastchange'] ? $shadowattr['lastchange']->getValue(0) : null; + $shadow['max'] = $shadowattr['max'] ? $shadowattr['max']->getValue(0) : null; + + if (($attribute->getName() == 'shadowlastchange') && $shadow['lastchange']) + $shadow_date = $shadow['lastchange']; + + elseif (($attribute->getName() == 'shadowmax') && ($shadow['max'] > 0) && $shadow['lastchange']) + $shadow_date = $shadow['lastchange']+$shadow['max']; + + elseif (($attribute->getName() == 'shadowwarning') && ($attribute->getValue(0) > 0) + && $shadow['lastchange'] && $shadow['max'] && $shadow['max'] > 0) + $shadow_date = $shadow['lastchange']+$shadow['max']-$attribute->getValue(0); + + elseif (($attribute->getName() == 'shadowinactive') && ($attribute->getValue(0) > 0) + && $shadow['lastchange'] && $shadow['max'] && $shadow['max'] > 0) + $shadow_date = $shadow['lastchange']+$shadow['max']+$attribute->getValue(0); + + elseif (($attribute->getName() == 'shadowmin') && ($attribute->getValue(0) > 0) && $shadow['lastchange']) + $shadow_date = $shadow['lastchange']+$attribute->getValue(0); + + elseif (($attribute->getName() == 'shadowexpire') && ($attribute->getValue(0) > 0)) + $shadow_date = $shadowattr->getValue(0); + + # Couldn't interpret the shadow date (could be 0 or -1 or something) + else + return false; + + return $shadow_date*24*3600; + } + + protected function drawShadowDateShadowAttribute($attribute) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + $shadow_before_today_attrs = arrayLower($attribute->shadow_before_today_attrs); + $shadow_after_today_attrs = arrayLower($attribute->shadow_after_today_attrs); + $shadow_date = $this->shadow_date($attribute); + + if (! $shadow_date) + return; + + $today = date('U'); + + echo '
'; + if (($today < $shadow_date) && in_array(strtolower($attribute->getName()),$shadow_before_today_attrs)) + printf('(%s)', + strftime($_SESSION[APPCONFIG]->getValue('appearance','date'),$shadow_date)); + + elseif (($today > $shadow_date) && in_array(strtolower($attribute->getName()),$shadow_after_today_attrs)) + printf('(%s)', + strftime($_SESSION[APPCONFIG]->getValue('appearance','date'),$shadow_date)); + + else + printf('(%s)', + strftime($_SESSION[APPCONFIG]->getValue('appearance','date'),$shadow_date)); + + echo '
'; + } + + protected function drawFormReadOnlyValueShadowAttribute($attribute,$i) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + $this->drawFormReadOnlyValueAttribute($attribute,$i); + $this->draw('ShadowDate',$attribute); + } + + protected function drawFormReadWriteValueShadowAttribute($attribute,$i) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + $this->drawFormReadWriteValueAttribute($attribute,$i); + $this->draw('ShadowDate',$attribute); + } +} +?> diff --git a/lib/PasswordAttribute.php b/lib/PasswordAttribute.php new file mode 100644 index 0000000..2667197 --- /dev/null +++ b/lib/PasswordAttribute.php @@ -0,0 +1,17 @@ + diff --git a/lib/Query.php b/lib/Query.php new file mode 100644 index 0000000..62a3d2b --- /dev/null +++ b/lib/Query.php @@ -0,0 +1,283 @@ +getServer(); + + foreach ($xmldata['query'] as $xml_key => $xml_value) { + if (DEBUG_ENABLED) + debug_log('Foreach loop Key [%s] Value [%s]',4,0,__FILE__,__LINE__,__METHOD__,$xml_key,is_array($xml_value)); + + switch ($xml_key) { + + # Build our attribute list from the DN and Template. + case ('attributes'): + if (DEBUG_ENABLED) + debug_log('Case [%s]',4,0,__FILE__,__LINE__,__METHOD__,$xml_key); + + if (is_array($xmldata['query'][$xml_key])) { + foreach ($xmldata['query'][$xml_key] as $tattrs) { + foreach ($tattrs as $index => $details) { + + if (DEBUG_ENABLED) + debug_log('Foreach tattrs Key [%s] Value [%s]',4,0,__FILE__,__LINE__,__METHOD__, + $index,$details); + + # If there is no schema definition for the attribute, it will be ignored. + if ($sattr = $server->getSchemaAttribute($index)) { + if (is_null($attribute = $this->getAttribute($sattr->getName()))) + $attribute = $this->addAttribute($sattr->getName(false),array('values'=>array())); + + $attribute->show(); + $attribute->setXML($details); + } + } + } + } + + break; + + # Build our bases list from the DN and Template. + case ('bases'): + if (isset($xmldata['query'][$xml_key]['base'])) + if (is_array($xmldata['query'][$xml_key]['base'])) + $this->base = $xmldata['query'][$xml_key]['base']; + else + $this->base = array($xmldata['query'][$xml_key]['base']); + else + error(sprintf(_('In the XML file (%s), [%s] contains an unknown key.'), + $this->filename,$xml_key),'error','index.php'); + + $this->base = array_unique($this->base); + break; + + default: + if (DEBUG_ENABLED) + debug_log('Case [%s]',4,0,__FILE__,__LINE__,__METHOD__,$xml_key); + + # Some key definitions need to be an array, some must not be: + $allowed_arrays = array(''); + $storelower = array(''); + $storearray = array(''); + + # Items that must be stored lowercase + if (in_array($xml_key,$storelower)) + if (is_array($xml_value)) + foreach ($xml_value as $index => $value) + $xml_value[$index] = strtolower($value); + else + $xml_value = strtolower($xml_value); + + # Items that must be stored as arrays + if (in_array($xml_key,$storearray) && ! is_array($xml_value)) + $xml_value = array($xml_value); + + # Items that should not be an array + if (! in_array($xml_key,$allowed_arrays) && is_array($xml_value)) { + debug_dump(array(__METHOD__,'key'=>$xml_key,'value'=>$xml_value)); + error(sprintf(_('In the XML file (%s), [%s] is an array, it must be a string.'), + $this->filename,$xml_key),'error'); + } + + $this->$xml_key = $xml_value; + } + } + + # Check we have some manditory items. + foreach (array() as $key) { + if (! isset($this->$key) + || (! is_array($this->$key) && ! trim($this->$key))) { + + $this->setInvalid(sprintf(_('Missing %s in the XML file.'),$key)); + break; + } + } + } + + /** + * Accept will run the query and store the results in results() + */ + public function accept() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $server = $this->getServer(); + + $query = array(); + $query['size_limit'] = get_request('size_limit','REQUEST',false,$_SESSION[APPCONFIG]->getValue('search','size_limit')); + $query['format'] = get_request('format','REQUEST',false,$_SESSION[APPCONFIG]->getValue('search','display')); + $query['orderby'] = get_request('orderby','REQUEST',false,'dn'); + + # If this is a custom search, we need to populate are paramters + if ($this->getID() == 'none') { + $bases = get_request('base','REQUEST',false,null); + $query['filter'] = get_request('filter','REQUEST',false,'objectClass=*'); + $query['scope'] = get_request('scope','REQUEST',false,'sub'); + $attrs = get_request('display_attrs','REQUEST'); + + $attrs = preg_replace('/\s+/','',$attrs); + if ($attrs) + $query['attrs'] = explode(',',$attrs); + else + $query['attrs'] = array('*'); + + } else { + $bases = $this->base; + $query['filter'] = $this->filter; + $query['scope'] = $this->scope; + $query['attrs'] = $this->getAttributeNames(); + } + + if (! $bases) + $bases = $server->getBaseDN(); + elseif (! is_array($bases)) + $bases = explode('|',$bases); + + foreach ($bases as $base) { + $query['base'] = $base; + + $time_start = utime(); + $this->results[$base] = $server->query($query,null); + $time_end = utime(); + + $this->resultsdata[$base]['time'] = round($time_end-$time_start,2); + $this->resultsdata[$base]['scope'] = $query['scope']; + $this->resultsdata[$base]['filter'] = $query['filter']; + $this->resultsdata[$base]['attrs'] = $query['attrs']; + + if ($this->getAttrSortOrder() == 'dn') + usort($this->results[$base],'pla_compare_dns'); + elseif ($this->getAttrSortOrder()) + masort($this->results[$base],$this->getAttrSortOrder()); + } + } + + /** + * This is temporary to get around objects that use a DN for rendering, for example jpegPhoto + */ + public function setDN($dn) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->dn = $dn; + } + + /** + * This is temporary to get around objects that use a DN for rendering, for example jpegPhoto + */ + public function getDN() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->dn); + + return $this->dn; + } + + public function getDNEncode($url=true) { + // @todo Be nice to do all this in 1 location + if ($url) + return urlencode(preg_replace('/%([0-9a-fA-F]+)/',"%25\\1",$this->dn)); + else + return preg_replace('/%([0-9a-fA-F]+)/',"%25\\1",$this->dn); + } + + public function getAttrSortOrder() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $result = array(); + + if (count($this->attributes)) { + masort($this->attributes,'ordersort'); + + foreach ($this->attributes as $attribute) + array_push($result,$attribute->getName()); + + } else { + $display = preg_replace('/,\s+/',',',get_request('orderby','REQUEST',false,'dn')); + + if (trim($display)) + $result = explode(',',$display); + } + + return implode(',',$result); + } + + public function getAttrDisplayOrder() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $result = array(); + + if (count($this->attributes)) { + masort($this->attributes,'order'); + + foreach ($this->attributes as $attribute) + array_push($result,$attribute->getName()); + + } else { + $display = preg_replace('/,\s+/',',',get_request('display_attrs','REQUEST',false,'')); + + if (trim($display)) + $result = explode(',',$display); + } + + # If our display order is empty, then dynamically build it + if (! count($result)) { + foreach ($this->results as $details) + foreach ($details as $attrs) + $result = array_merge($result,array_keys(array_change_key_case($attrs))); + + $result = array_unique($result); + sort($result); + } + + # Put the DN first + array_unshift($result,'dn'); + $result = array_unique($result); + + return implode(',',$result); + } + + /** + * Test if the template is visible + * + * @return boolean + */ + public function isVisible() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->visible); + + return $this->visible; + } + + public function getDescription() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->description); + + return $this->description; + } +} +?> diff --git a/lib/QueryRender.php b/lib/QueryRender.php new file mode 100644 index 0000000..16660bc --- /dev/null +++ b/lib/QueryRender.php @@ -0,0 +1,557 @@ +%s
',__METHOD__); + if (DEBUGTMP||DEBUGTMPSUB) printf('* %s [GETquery:%s]
',__METHOD__,get_request('query','REQUEST')); + if (DEBUGTMP||DEBUGTMPSUB) printf('* %s [Page:%s]
',__METHOD__,get_request('page','REQUEST')); + + $this->template_id = $this->getTemplateChoice(); + $this->page = get_request('page','REQUEST',false,1); + + # If we are the default template, make sure we pressed search + if ($this->template_id == 'none' && ! get_request('search','REQUEST')) + $this->drawTemplateChoice(); + + elseif ($this->template_id) { + $templates = $this->getTemplates(); + $this->template = $templates->getTemplate($this->template_id); + $this->template->accept(); + + $this->visitStart(); + $this->visitEnd(); + } + } + + /** + * Get our templates applicable for this object + */ + protected function getTemplates() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + return new Queries($this->server_id); + } + + /** + * Are default queries enabled? + */ + protected function haveDefaultTemplate() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $server = $this->getServer(); + + if ($server->getValue('query','disable_default')) + return false; + else + return true; + } + + protected function drawTemplateChoice() { + if (DEBUGTMP) printf('%s
',__METHOD__); + + $server = $this->getServer(); + + $this->drawTitle(_('Search')); + $this->drawSubTitle(); + + echo "\n"; + + $baseDNs = $server->getBaseDN(); + + printf('',JSDIR); + echo '
'; + echo '
'; + echo ''; + printf('',$server->getIndex()); + echo '
'; + + echo ''; + echo ''; + + $templates = $this->getTemplates(); + + if (count($templates->getTemplates())) { + echo ''; + printf('',_('Run a predefined query'),_('Predefined Query')); + echo ''; + echo ''; + } + + echo ''; + printf('',_('The format to show the query results'),_('Display Format')); + echo ''; + echo ''; + + echo ''; + printf('',_('Entries to show per page'),_('Show Results')); + echo ''; + echo ''; + + echo ''; + + echo ''; + echo ''; + + printf('',_('Search')); + + echo '
 
%s'; + echo ''; + echo '
%s'; + echo ''; + echo '
%s'; + echo ''; + echo '
'; + printf('
','block'); + echo '
'; + echo '
'; + printf('%s',_('Custom Query')); + echo ''; + + printf('',_('Base DN')); + printf(''; + echo ''; + + echo ''; + printf('',_('The scope in which to search'),_('Search Scope')); + + echo ''; + echo ''; + + echo ''; + printf('', + htmlspecialchars(_('Standard LDAP search filter. Example: (&(sn=Smith)(givenName=David))')),_('Search Filter')); + + printf('', + 'objectClass=*'); + + echo ''; + + echo ''; + printf('', + _('A list of attributes to display in the results (comma-separated)'),_('Show Attributes')); + + printf('', + implode(', ',$_SESSION[APPCONFIG]->getValue('search','result_attributes'))); + echo ''; + + echo ''; + printf('',_('Order by'),_('Order by')); + printf('',''); + echo ''; + + echo ''; + printf('',_('Set the search results to 0 to retrieve all available records'),_('Search Results')); + printf('',$_SESSION[APPCONFIG]->getValue('search','size_limit')); + echo ''; + + echo '
%s',count($baseDNs) == 1 ? $baseDNs[0] : ''); + + draw_chooser_link('advanced_search_form','base'); + + echo '
%s'; + echo ''; + echo '
%s
%s
%s
%s
'; + echo '
'; + echo '
'; + echo '

'; + echo '
'; + } + + private function visitStart() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->drawTitle(_('Search Results')); + $this->drawSubTitle(); + echo '
'; + } + + private function visitEnd() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $server = $this->getServer(); + $afattrs = $this->getAFAttrs(); + + # If Mass Actions Enabled + if ($_SESSION[APPCONFIG]->getValue('mass','enabled')) { + $mass_actions = array( + _('delete') => 'mass_delete', + _('edit') => 'mass_edit' + ); + } + + $this->drawBaseTabs(); + $ado = $this->template->getAttrDisplayOrder(); + $counter = 0; + $j = 0; + + foreach ($this->template->results as $base => $results) { + $counter++; + + if (! $show = get_request('show','REQUEST')) + $show = ($counter === 1 ? $this->getAjaxRef($base) : null); + + printf('
', + $this->getAjaxRef($base), ($show == $this->getAjaxRef($base) ? 'block' : 'none')); + + echo ''; + echo ''; + echo '
'; + echo '
'; + echo '
'; + + $this->drawResultsTable($base,count($results)); + + echo '
'; + echo '
'; + + switch(get_request('format','REQUEST',false,$_SESSION[APPCONFIG]->getValue('search','display'))) { + case 'list': + foreach ($results as $dndetails) { + $dndetails = array_change_key_case($dndetails); + + # Temporarily set our DN, for rendering that leverages our DN (eg: JpegPhoto) + $this->template->setDN($dndetails['dn']); + + echo ''; + + echo ''; + printf('',IMGDIR,get_icon($server->getIndex(),$dndetails['dn'])); + + printf('', + $server->getIndex(),$this->template->getDNEncode(),htmlspecialchars(get_rdn($dndetails['dn']))); + echo ''; + + printf('', + htmlspecialchars(dn_unescape($dndetails['dn']))); + + # Iterate over each attribute for this entry + foreach (explode(',',$ado) as $attr) { + $attr = strtolower($attr); + + # Ignore DN, we've already displayed it. + if ($attr == 'dn') + continue 2; + + if (! isset($dndetails[$attr])) + continue 2; + + # Set our object with our values + $afattrs[$attr]->clearValue(); + + if (is_array($dndetails[$attr])) + $afattrs[$attr]->initValue($dndetails[$attr]); + else + $afattrs[$attr]->initValue(array($dndetails[$attr])); + + echo ''; + echo ''; + + echo ''; + + echo ''; + echo ''; + } + + echo '
icon%s
 dn%s
 '; + $this->draw('Name',$afattrs[$attr]); + echo ''; + $this->draw('CurrentValues',$afattrs[$attr]); + echo '
'; + echo '
'; + } + + break; + + # Display the results. + case 'table': + if (! $results) { + echo _('Search returned no results'); + + continue 2; + } + + printf('
',$counter); + echo '
'; + printf('',$server->getIndex()); + + foreach ($this->template->resultsdata[$base]['attrs'] as $attr) + printf('',$attr); + + echo '
'; + + echo ''; + + echo ''; + echo ''; + echo ''; + echo ''; + + foreach (explode(',',$ado) as $attr) { + echo ''; + } + + echo ''; + echo ''; + + echo ''; + foreach ($results as $dndetails) { + $j++; + $dndetails = array_change_key_case($dndetails); + + # Temporarily set our DN, for rendering that leverages our DN (eg: JpegPhoto) + $this->template->setDN($dndetails['dn']); + + printf('', + $j%2 ? 'even' : 'odd',$j,$j); + + # Is mass action enabled. + if ($_SESSION[APPCONFIG]->getValue('mass','enabled')) + printf('',$j,$dndetails['dn']); + + $href = sprintf('cmd=template_engine&server_id=%s&dn=%s',$server->getIndex(),$this->template->getDNEncode()); + printf('', + htmlspecialchars($href), + IMGDIR,get_icon($server->getIndex(),$dndetails['dn'])); + + # We'll clone our attribute factory attributes, since we need to add the values to them for rendering. + foreach (explode(',',$ado) as $attr) { + # If the entry is blank, we'll draw an empty box and continue. + if (! isset($dndetails[$attr])) { + echo ''; + continue; + } + + # Special case for DNs + if ($attr == 'dn') { + $dn_display = strlen($dndetails['dn']) > 40 + ? sprintf('%s...',htmlspecialchars($dndetails['dn']),htmlspecialchars(substr($dndetails['dn'],0,40))) + : htmlspecialchars($dndetails['dn']); + + printf('',htmlspecialchars($href),$dn_display); + continue; + } + + # Set our object with our values + $afattrs[$attr]->clearValue(); + if (is_array($dndetails[$attr])) + $afattrs[$attr]->initValue($dndetails[$attr]); + else + $afattrs[$attr]->initValue(array($dndetails[$attr])); + + echo ''; + } + + echo ''; + } + + # Is mass action enabled. + if ($_SESSION[APPCONFIG]->getValue('mass','enabled')) { + printf('',++$j%2 ? 'odd' : 'even'); + printf('',$counter); + printf(''; + echo ''; + } + + echo ''; + echo '
  '; + $this->draw('Name',$afattrs[$attr]); + echo '
icon %s'; + $this->draw('CurrentValues',$afattrs[$attr]); + echo '
',2+count(explode(',',$ado))); + + foreach ($mass_actions as $display => $action) + printf('  ',$action,$display); + + echo '
'; + echo '
'; + echo "\n\n"; + + break; + + default: + printf('Have ID [%s], run this query for page [%s]',$this->template_id,$this->page); + } + + echo '
'; + echo '
'; + echo "\n\n"; + } + + if (get_request('format','REQUEST',false,'table') == 'table') + printf('',JSDIR); + } + + public function drawSubTitle($subtitle=null) { + if (is_null($subtitle)) { + $server = $this->getServer(); + + $subtitle = sprintf('%s: %s',_('Server'),$server->getName()); + + if ($this->template) { + $subtitle .= '
'; + $subtitle .= sprintf('%s: %s',('Query'),$this->template->getID() != 'none' ? $this->template->getTitle() : _('Default')); + if ($this->template->getName()) + $subtitle .= sprintf(' (%s)',$this->template->getName(false)); + } + } + + parent::drawSubTitle($subtitle); + } + + private function getAFattrs() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $attribute_factory = new AttributeFactory(); + $results = array(); + + foreach (explode(',',$this->template->getAttrDisplayOrder()) as $attr) + $results[strtolower($attr)] = $attribute_factory->newAttribute($attr,array('values'=>array()),$this->getServerID()); + + return $results; + } + + private function getAjaxRef($dn) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + return preg_replace('/=/','.',base64_encode($dn)); + } + + private function drawBaseTabs() { + # Setup the Javascript to show/hide our DIVs. + echo ''; + echo "\n\n"; + + echo ''; + echo ''; + $counter = 0; + foreach ($this->template->results as $base => $results) { + if (! $show = get_request('show','REQUEST')) + $show = ($counter++ === 0 ? $this->getAjaxRef($base) : null); + + printf('', + $this->getAjaxRef($base), + $this->getAjaxRef($base), + ($show == $this->getAjaxRef($base) ? '#F0F0F0' : '#E0E0E0'), + htmlspecialchars($base)); + } + echo ''; + echo '
%s
'; + echo "\n\n"; + } + + private function drawResultsTable($base,$results) { + $server = $this->getServer(); + + echo ''; + + echo ''; + printf('',_('Entries found'), + number_format($results),$this->template->resultsdata[$base]['time'],_('seconds')); + + if ($_SESSION[APPCONFIG]->isCommandAvailable('script','export') && $_SESSION[APPCONFIG]->isCommandAvailable('script','export_form')) { + $href = htmlspecialchars(sprintf('cmd.php?cmd=export_form&server_id=%s&scope=%s&dn=%s&filter=%s&attributes=%s', + $server->getIndex(),$this->template->resultsdata[$base]['scope'], + $base,rawurlencode($this->template->resultsdata[$base]['filter']), + rawurlencode(implode(', ',$this->template->resultsdata[$base]['attrs'])))); + + printf(''; + echo ''; + echo '
%s: %s

(%s %s)
[ Save %s ]', + $href,IMGDIR,_('export results')); + } + + printf('[ rename %s:',IMGDIR,_('Format')); + + foreach (array('list','table') as $f) { + echo ' '; + + if (get_request('format','REQUEST',false,$_SESSION[APPCONFIG]->getValue('search','display')) == $f) { + printf('%s',_($f)); + + } else { + $query_string = htmlspecialchars(sprintf('%s&format=%s&show=%s&focusbase=%s',array_to_query_string($_GET,array('format','meth')),$f,$this->getAjaxRef($base),$base)); + + if (isAjaxEnabled()) + printf('%s', + $query_string,$query_string,_('Loading Search'),_($f)); + else + printf('%s',$query_string,_($f)); + } + } + + echo ' ]'; + + echo '
'; + printf('%s: %s',_('Base DN'),htmlspecialchars($base)); + + echo '
'; + printf('%s: %s',_('Filter performed'),htmlspecialchars($this->template->resultsdata[$base]['filter'])); + + echo '
'; + } +} +?> diff --git a/lib/RandomPasswordAttribute.php b/lib/RandomPasswordAttribute.php new file mode 100644 index 0000000..ca11f8d --- /dev/null +++ b/lib/RandomPasswordAttribute.php @@ -0,0 +1,17 @@ + diff --git a/lib/SambaPasswordAttribute.php b/lib/SambaPasswordAttribute.php new file mode 100644 index 0000000..35c1a08 --- /dev/null +++ b/lib/SambaPasswordAttribute.php @@ -0,0 +1,17 @@ + diff --git a/lib/SelectionAttribute.php b/lib/SelectionAttribute.php new file mode 100644 index 0000000..5f1c8bb --- /dev/null +++ b/lib/SelectionAttribute.php @@ -0,0 +1,71 @@ +source == 'XML' && $this->values) { + $this->selection = $this->values; + $this->values = array(); + } + + if (isset($values['type']) && $values['type'] == 'multiselect') + $this->multiple = true; + else + $this->multiple = false; + } + + public function addOption($value,$description) { + $this->selection[$value] = $description; + } + + public function addValue($new_val,$i=-1) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->addOption($new_val,$i); + } + + public function getOptionCount() { + return count($this->selection); + } + + public function getSelection() { + return $this->selection; + } + + public function autoValue($value) { + $this->selection = $value; + } + + public function getDefault() { + return $this->default; + } + + public function isMultiple() { + return $this->multiple; + } + + public function setMultiple() { + $this->multiple = true; + } +} +?> diff --git a/lib/ShadowAttribute.php b/lib/ShadowAttribute.php new file mode 100644 index 0000000..eeb7cd1 --- /dev/null +++ b/lib/ShadowAttribute.php @@ -0,0 +1,19 @@ + diff --git a/lib/Template.php b/lib/Template.php new file mode 100644 index 0000000..a9f7a17 --- /dev/null +++ b/lib/Template.php @@ -0,0 +1,1571 @@ +noleaf = $_SESSION[APPCONFIG]->getValue('appearance','disable_default_leaf'); + } + + public function __clone() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # We need to clone our attributes, when passing back a template with getTemplate + foreach ($this->attributes as $key => $value) + $this->attributes[$key] = clone $value; + } + + /** + * Main processing to store the template. + * + * @param xmldata Parsed xmldata from xml2array object + */ + protected function storeTemplate($xmldata) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $server = $this->getServer(); + $objectclasses = array(); + + foreach ($xmldata['template'] as $xml_key => $xml_value) { + if (DEBUG_ENABLED) + debug_log('Foreach loop Key [%s] Value [%s]',4,0,__FILE__,__LINE__,__METHOD__,$xml_key,is_array($xml_value)); + + switch ($xml_key) { + # Build our object Classes from the DN and Template. + case ('objectclasses'): + if (DEBUG_ENABLED) + debug_log('Case [%s]',4,0,__FILE__,__LINE__,__METHOD__,$xml_key); + + if (isset($xmldata['template'][$xml_key]['objectclass'])) + if (is_array($xmldata['template'][$xml_key]['objectclass'])) { + foreach ($xmldata['template'][$xml_key]['objectclass'] as $index => $details) { + + # XML files with only 1 objectClass dont have a numeric index. + $soc = $server->getSchemaObjectClass(strtolower($details)); + + # If we havent recorded this objectclass already, do so now. + if (is_object($soc) && ! in_array($soc->getName(),$objectclasses)) + array_push($objectclasses,$soc->getName(false)); + + elseif (! is_object($soc) && ! $_SESSION[APPCONFIG]->getValue('appearance','hide_template_warning')) + system_message(array( + 'title'=>_('Automatically removed objectClass from template'), + 'body'=>sprintf('%s: %s %s',$this->getTitle(),$details,_('removed from template as it is not defined in the schema')), + 'type'=>'warn')); + } + + } else { + # XML files with only 1 objectClass dont have a numeric index. + $soc = $server->getSchemaObjectClass(strtolower($xmldata['template'][$xml_key]['objectclass'])); + + # If we havent recorded this objectclass already, do so now. + if (is_object($soc) && ! in_array($soc->getName(),$objectclasses)) + array_push($objectclasses,$soc->getName(false)); + } + + break; + + # Build our attribute list from the DN and Template. + case ('attributes'): + if (DEBUG_ENABLED) + debug_log('Case [%s]',4,0,__FILE__,__LINE__,__METHOD__,$xml_key); + + if (is_array($xmldata['template'][$xml_key])) { + foreach ($xmldata['template'][$xml_key] as $tattrs) + foreach ($tattrs as $index => $details) { + if (DEBUG_ENABLED) + debug_log('Foreach tattrs Key [%s] Value [%s]',4,0,__FILE__,__LINE__,__METHOD__, + $index,$details); + + # If there is no schema definition for the attribute, it will be ignored. + if ($sattr = $server->getSchemaAttribute($index)) + if (is_null($this->getAttribute($sattr->getName()))) + $this->addAttribute($sattr->getName(),$details,'XML'); + } + + masort($this->attributes,'order'); + } + + break; + + default: + if (DEBUG_ENABLED) + debug_log('Case [%s]',4,0,__FILE__,__LINE__,__METHOD__,$xml_key); + + # Some key definitions need to be an array, some must not be: + $allowed_arrays = array('rdn'); + $storelower = array('rdn'); + $storearray = array('rdn'); + + # Items that must be stored lowercase + if (in_array($xml_key,$storelower)) + if (is_array($xml_value)) + foreach ($xml_value as $index => $value) + $xml_value[$index] = strtolower($value); + else + $xml_value = strtolower($xml_value); + + # Items that must be stored as arrays + if (in_array($xml_key,$storearray) && ! is_array($xml_value)) + $xml_value = array($xml_value); + + # Items that should not be an array + if (! in_array($xml_key,$allowed_arrays) && is_array($xml_value)) { + debug_dump(array(__METHOD__,'key'=>$xml_key,'value'=>$xml_value)); + error(sprintf(_('In the XML file (%s), [%s] is an array, it must be a string.'), + $this->filename,$xml_key),'error'); + } + + $this->$xml_key = $xml_value; + + if ($xml_key == 'invalid' && $xml_value) + $this->setInvalid(_('Disabled by XML configuration'),true); + } + } + + if (! count($objectclasses)) { + $this->setInvalid(_('ObjectClasses in XML dont exist in LDAP server.')); + return; + + } else { + $attribute = $this->addAttribute('objectClass',array('values'=>$objectclasses),'XML'); + $attribute->justModified(); + $attribute->setRequired(); + $attribute->hide(); + } + + $this->rebuildTemplateAttrs(); + + # Check we have some manditory items. + foreach (array('rdn','structural_oclass','visible') as $key) { + if (! isset($this->$key) + || (! is_array($this->$key) && ! trim($this->$key))) { + + $this->setInvalid(sprintf(_('Missing %s in the XML file.'),$key)); + break; + } + } + + # Mark our RDN attributes as RDN + $counter = 1; + foreach ($this->rdn as $key) { + if ((is_null($attribute = $this->getAttribute($key))) && (in_array_ignore_case('extensibleobject',$this->getObjectClasses()))) { + $attribute = $this->addAttribute($key,array('values'=>array())); + $attribute->show(); + } + + if (! is_null($attribute)) + $attribute->setRDN($counter++); + elseif ($this->isType('creation')) + $this->setInvalid(sprintf(_('Missing RDN attribute %s in the XML file.'),$key)); + } + } + + /** + * Is default templates enabled? + * This will disable the default template from the engine. + * + * @return boolean + */ + protected function hasDefaultTemplate() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if ($_SESSION[APPCONFIG]->getValue('appearance','disable_default_template')) + return false; + else + return true; + } + + /** + * Return the templates of type (creation/modification) + * + * @param $string type - creation/modification + * @return array - Array of templates of that type + */ + protected function readTemplates($type) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $template_xml = new Templates($this->server_id); + return $template_xml->getTemplates($type); + } + + /** + * This function will perform the following intialisation steps: + * + If a DN is set, query the ldap and load the object + * + Read our $_REQUEST variable and set the values + * After this action, the template should self describe as to whether it is an update, create + * or delete. + * (OLD values are IGNORED, we will have got them when we build this object from the LDAP server DN.) + */ + public function accept($makeVisible=false,$nocache=false) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $server = $this->getServer(); + + # If a DN is set, then query the LDAP server for the details. + if ($this->dn) { + if (! $server->dnExists($this->dn)) + system_message(array( + 'title'=>__METHOD__, + 'body'=>sprintf('DN (%s) didnt exist in LDAP?',$this->dn), + 'type'=>'info')); + + $rdnarray = rdn_explode(strtolower(get_rdn(dn_escape($this->dn)))); + + $counter = 1; + foreach ($server->getDNAttrValues($this->dn,null,LDAP_DEREF_NEVER,array_merge(array('*'),$server->getValue('server','custom_attrs')),$nocache) as $attr => $values) { + # We ignore DNs. + if ($attr == 'dn') + continue; + + $attribute = $this->getAttribute($attr); + + if (is_null($attribute)) + $attribute = $this->addAttribute($attr,array('values'=>$values)); + else + if ($attribute->getValues()) { + # Override values to those that are defined in the XML file. + if ($attribute->getSource() != 'XML') + $attribute->setValue(array_values($values)); + else + $attribute->setOldValue(array_values($values)); + + } else + $attribute->initValue(array_values($values)); + + # Work out the RDN attributes + foreach ($attribute->getValues() as $index => $value) + if (in_array(sprintf('%s=%s', + $attribute->getName(),strtolower($attribute->getValue($index))),$rdnarray)) + $attribute->setRDN($counter++); + + if ($makeVisible) + $attribute->show(); + } + + # Get the Internal Attributes + foreach ($server->getDNAttrValues($this->dn,null,LDAP_DEREF_NEVER,array_merge(array('+'),$server->getValue('server','custom_sys_attrs'))) as $attr => $values) { + $attribute = $this->getAttribute($attr); + + if (is_null($attribute)) + $attribute = $this->addAttribute($attr,array('values'=>$values)); + else + if ($attribute->getValues()) + $attribute->setValue(array_values($values)); + else + $attribute->initValue(array_values($values)); + + if (! in_array_ignore_case($attribute->getName(),$server->getValue('server','custom_attrs'))) + $attribute->setInternal(); + } + + # If this is the default template, and our $_REQUEST has defined our objectclass, then query the schema to get the attributes + } elseif ($this->container) { + if ($this->isType('default') && ! count($this->getAttributes(true)) && isset($_REQUEST['new_values']['objectclass'])) { + $attribute = $this->addAttribute('objectclass',array('values'=>$_REQUEST['new_values']['objectclass'])); + $attribute->justModified(); + $this->rebuildTemplateAttrs(); + unset($_REQUEST['new_values']['objectclass']); + } + + } elseif (get_request('create_base')) { + if (get_request('rdn')) { + $rdn = explode('=',get_request('rdn')); + $attribute = $this->addAttribute($rdn[0],array('values'=>array($rdn[1]))); + $attribute->setRDN(1); + } + + } else { + debug_dump_backtrace('No DN or CONTAINER?',1); + } + + # Read in our new values. + foreach (array('new_values') as $key) { + if (isset($_REQUEST[$key])) + foreach ($_REQUEST[$key] as $attr => $values) { + # If it isnt an array, silently ignore it. + if (! is_array($values)) + continue; + + # If _REQUEST['skip_array'] with this attr set, we'll ignore this new_value + if (isset($_REQUEST['skip_array'][$attr]) && $_REQUEST['skip_array'][$attr] == 'on') + continue; + + # Prune out entries with a blank value. + foreach ($values as $index => $value) + if (! strlen(trim($value))) + unset($values[$index]); + + $attribute = $this->getAttribute($attr); + # If the attribute is null, then no attribute exists, silently ignore it (unless this is the default template) + if (is_null($attribute) && (! $this->isType('default') && ! $this->isType(null))) + continue; + + # If it is a binary attribute, the post should have base64 encoded the value, we'll need to reverse that + if ($server->isAttrBinary($attr)) + foreach ($values as $index => $value) + $values[$index] = base64_decode($value); + + if (is_null($attribute)) { + $attribute = $this->addAttribute($attr,array('values'=>$values)); + + if (count($values)) + $attribute->justModified(); + + } else + $attribute->setValue(array_values($values)); + } + + # Read in our new binary values + if (isset($_FILES[$key]['name'])) + foreach ($_FILES[$key]['name'] as $attr => $values) { + $new_values = array(); + + foreach ($values as $index => $details) { + # Ignore empty files + if (! $_FILES[$key]['size'][$attr][$index]) + continue; + + if (! is_uploaded_file($_FILES[$key]['tmp_name'][$attr][$index])) { + if (isset($_FILES[$key]['error'][$attr][$index])) + switch($_FILES[$key]['error'][$attr][$index]) { + + # No error; possible file attack! + case 0: + $msg = _('Security error: The file being uploaded may be malicious.'); + break; + + # Uploaded file exceeds the upload_max_filesize directive in php.ini + case 1: + $msg = _('The file you uploaded is too large. Please check php.ini, upload_max_size setting'); + break; + + # Uploaded file exceeds the MAX_FILE_SIZE directive specified in the html form + case 2: + $msg = _('The file you uploaded is too large. Please check php.ini, upload_max_size setting'); + break; + + # Uploaded file was only partially uploaded + case 3: + $msg = _('The file you selected was only partially uploaded, likley due to a network error.'); + break; + + # No file was uploaded + case 4: + $msg = _('You left the attribute value blank. Please go back and try again.'); + break; + + # A default error, just in case! :) + default: + $msg = _('Security error: The file being uploaded may be malicious.'); + break; + } + + else + $msg = _('Security error: The file being uploaded may be malicious.'); + + system_message(array( + 'title'=>_('Upload Binary Attribute Error'),'body'=>$msg,'type'=>'warn')); + + } else { + $binaryfile = array(); + $binaryfile['name'] = $_FILES[$key]['tmp_name'][$attr][$index]; + $binaryfile['handle'] = fopen($binaryfile['name'],'r'); + $binaryfile['data'] = fread($binaryfile['handle'],filesize($binaryfile['name'])); + fclose($binaryfile['handle']); + + $new_values[$index] = $binaryfile['data']; + } + } + + if (count($new_values)) { + $attribute = $this->getAttribute($attr); + + if (is_null($attribute)) + $attribute = $this->addAttribute($attr,array('values'=>$new_values)); + else + foreach ($new_values as $value) + $attribute->addValue($value); + + $attribute->justModified(); + } + } + } + + # If there are any single item additions (from the add_attr form for example) + if (isset($_REQUEST['single_item_attr'])) { + if (isset($_REQUEST['single_item_value'])) { + if (! is_array($_REQUEST['single_item_value'])) + $values = array($_REQUEST['single_item_value']); + else + $values = $_REQUEST['single_item_value']; + + } elseif (isset($_REQUEST['binary'])) { + /* Special case for binary attributes (like jpegPhoto and userCertificate): + * we must go read the data from the file and override $_REQUEST['single_item_value'] with the + * binary data. Secondly, we must check if the ";binary" option has to be appended to the name + * of the attribute. */ + + if ($_FILES['single_item_value']['size'] === 0) + system_message(array( + 'title'=>_('Upload Binary Attribute Error'), + 'body'=>sprintf('%s %s',_('The file you chose is either empty or does not exist.'),_('Please go back and try again.')), + 'type'=>'warn')); + + else { + if (! is_uploaded_file($_FILES['single_item_value']['tmp_name'])) { + if (isset($_FILES['single_item_value']['error'])) + switch($_FILES['single_item_value']['error']) { + + # No error; possible file attack! + case 0: + $msg = _('Security error: The file being uploaded may be malicious.'); + break; + + # Uploaded file exceeds the upload_max_filesize directive in php.ini + case 1: + $msg = _('The file you uploaded is too large. Please check php.ini, upload_max_size setting'); + break; + + # Uploaded file exceeds the MAX_FILE_SIZE directive specified in the html form + case 2: + $msg = _('The file you uploaded is too large. Please check php.ini, upload_max_size setting'); + break; + + # Uploaded file was only partially uploaded + case 3: + $msg = _('The file you selected was only partially uploaded, likley due to a network error.'); + break; + + # No file was uploaded + case 4: + $msg = _('You left the attribute value blank. Please go back and try again.'); + break; + + # A default error, just in case! :) + default: + $msg = _('Security error: The file being uploaded may be malicious.'); + break; + } + + else + $msg = _('Security error: The file being uploaded may be malicious.'); + + system_message(array( + 'title'=>_('Upload Binary Attribute Error'),'body'=>$msg,'type'=>'warn'),'index.php'); + } + + $binaryfile = array(); + $binaryfile['name'] = $_FILES['single_item_value']['tmp_name']; + $binaryfile['handle'] = fopen($binaryfile['name'],'r'); + $binaryfile['data'] = fread($binaryfile['handle'],filesize($binaryfile['name'])); + fclose($binaryfile['handle']); + + $values = array($binaryfile['data']); + } + } + + if (count($values)) { + $attribute = $this->getAttribute($_REQUEST['single_item_attr']); + + if (is_null($attribute)) + $attribute = $this->addAttribute($_REQUEST['single_item_attr'],array('values'=>$values)); + else + $attribute->setValue(array_values($values)); + + $attribute->justModified(); + } + } + + # If this is the default creation template, we need to set some additional values + if ($this->isType('default') && $this->getContext() == 'create') { + # Load our schema, based on the objectclasses that may have already been defined. + if (! get_request('create_base')) + $this->rebuildTemplateAttrs(); + + # Set the RDN attribute + $counter = 1; + foreach (get_request('rdn_attribute','REQUEST',false,array()) as $key => $value) { + $attribute = $this->getAttribute($value); + + if (! is_null($attribute)) + $attribute->setRDN($counter++); + + else { + system_message(array( + 'title'=>_('No RDN attribute'), + 'body'=>_('No RDN attribute was selected'), + 'type'=>'warn'),'index.php'); + + die(); + } + } + } + } + + /** + * Set the DN for this template, if we are editing entries + * + * @param dn The DN of the entry + */ + public function setDN($dn) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (isset($this->container)) + system_message(array( + 'title'=>__METHOD__, + 'body'=>'CONTAINER set while setting DN', + 'type'=>'info')); + + $this->dn = $dn; + } + + /** + * Set the RDN attributes + * Given an RDN, mark the attributes as RDN attributes. If there is no defined attribute, + * then the remaining RDNs will be returned. + * + * @param RDN + * @return RDN attributes not processed + */ + public function setRDNAttributes($rdn) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # Setup to work out our RDN. + $rdnarray = rdn_explode($rdn); + + $counter = 1; + foreach ($this->getAttributes(true) as $attribute) + foreach ($rdnarray as $index => $rdnattr) { + list($attr,$value) = explode('=',$rdnattr); + + if (strtolower($attr) == $attribute->getName()) { + $attribute->setRDN($counter++); + unset($rdnarray[$index]); + } + } + + return $rdnarray; + } + + /** + * Display the DN for this template entry. If the DN is not set (creating a new entry), then + * a generated DN will be produced, taken from the RDN and the CONTAINER details. + * + * @return dn + */ + public function getDN() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs,$this->dn); + + if ($this->dn) + return $this->dn; + + # If DN is not set, our DN will be made from our RDN and Container. + elseif ($this->getRDN() && $this->getContainer()) + return sprintf('%s,%s',$this->getRDN(),$this->GetContainer()); + + # If container is not set, we're probably creating the base + elseif ($this->getRDN() && get_request('create_base')) + return $this->getRDN(); + } + + public function getDNEncode($url=true) { + // @todo Be nice to do all this in 1 location + if ($url) + return urlencode(preg_replace('/%([0-9a-fA-F]+)/',"%25\\1",$this->getDN())); + else + return preg_replace('/%([0-9a-fA-F]+)/',"%25\\1",$this->getDN()); + } + + /** + * Set the container for this template, if we are creating entries + * + * @param dn The DN of the container + * @todo Trigger a query to the LDAP server and generate an error if the container doesnt exist + */ + public function setContainer($container) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (isset($this->dn)) + system_message(array( + 'title'=>__METHOD__, + 'body'=>'DN set while setting CONTAINER', + 'type'=>'info')); + + $this->container = $container; + } + + /** + * Get the DN of the container for this entry + * + * @return dn DN of the container + */ + public function getContainer() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->container); + + return $this->container; + } + + public function getContainerEncode($url=true) { + // @todo Be nice to do all this in 1 location + if ($url) + return urlencode(preg_replace('/%([0-9a-fA-F]+)/',"%25\\1",$this->container)); + else + return preg_replace('/%([0-9a-fA-F]+)/',"%25\\1",$this->container); + } + + /** + * Copy a DN + */ + public function copy($template,$rdn,$asnew=false) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $rdnarray = rdn_explode($rdn); + + $counter = 1; + foreach ($template->getAttributes(true) as $sattribute) { + $attribute = $this->addAttribute($sattribute->getName(false),array('values'=>$sattribute->getValues())); + + # Set our new RDN, and its values + if (is_null($attribute)) { + debug_dump_backtrace('Attribute is null, it probably doesnt exist in the destination server?'); + + } else { + + # Mark our internal attributes. + if ($sattribute->isInternal()) + $attribute->setInternal(); + + $modified = false; + foreach ($rdnarray as $index => $rdnattr) { + list($attr,$value) = explode('=',$rdnattr); + if (strtolower($attr) == $attribute->getName()) { + + # If this is already marked as an RDN, then this multivalue RDN was updated on a previous loop + if (! $modified) { + $attribute->setValue(array($value)); + $attribute->setRDN($counter++); + $modified = true; + + } else { + $attribute->addValue($value); + } + + # This attribute has been taken care of, we'll drop it from our list. + unset($rdnarray[$index]); + } + } + } + + // @todo If this is a Jpeg Attribute, we need to mark it read only, since it cant be deleted like text attributes can + if (strcasecmp(get_class($attribute),'jpegAttribute') == 0) + $attribute->setReadOnly(); + } + + # If we have any RDN values left over, there werent in the original entry and need to be added. + foreach ($rdnarray as $rdnattr) { + list($attr,$value) = explode('=',$rdnattr); + + $attribute = $this->addAttribute($attr,array('values'=>array($value))); + + if (is_null($attribute)) + debug_dump_backtrace('Attribute is null, it probably doesnt exist in the destination server?'); + else + $attribute->setRDN($counter++); + } + + # If we are copying into a new entry, we need to discard all the "old values" + if ($asnew) + foreach ($this->getAttributes(true) as $sattribute) + $sattribute->setOldValue(array()); + } + + /** + * Get Attributes by LDAP type + * This function will return a list of attributes by LDAP type (MUST,MAY). + * + * @return array Array of attributes. + */ + function getAttrbyLdapType($type) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $result = array(); + + foreach ($this->attributes as $index => $attribute) { + if ($attribute->getLDAPtype() == strtolower($type)) + array_push($result,$attribute->getName()); + } + + return $result; + } + + /** + * Return true if this is a MUST,MAY attribute + */ + function isAttrType($attr,$type) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (in_array(strtolower($attr),$this->getAttrbyLdapType($type))) + return true; + else + return false; + } + + /** + * Return the attributes that comprise the RDN. + * + * @return array Array of RDN objects + */ + private function getRDNObjects() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $return = array(); + + foreach ($this->attributes as $attribute) + if ($attribute->isRDN()) + array_push($return,$attribute); + + masort($return,'rdn'); + return $return; + } + + /** + * Get all the RDNs for this template, in RDN order. + * + * @return array RDNs in order. + */ + public function getRDNAttrs() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $return = array(); + + foreach ($this->getRDNObjects() as $attribute) { + # We'll test if two RDN's have the same number (we cant test anywhere else) + if (isset($return[$attribute->isRDN()]) && $this->getType() == 'creation') + system_message(array( + 'title'=>_('RDN attribute sequence already defined'), + 'body'=>sprintf('%s %s', + sprintf(_('There is a problem in template [%s].'),$this->getName()), + sprintf(_('RDN attribute sequence [%s] is already used by attribute [%s] and cant be used by attribute [%s] also.'), + $attribute->isRDN(),$return[$attribute->isRDN()],$attribute->getName())), + 'type'=>'error'),'index.php'); + + $return[$attribute->isRDN()] = $attribute->getName(); + } + + return $return; + } + + /** + * Return the RDN for this template. If the DN is already defined, then the RDN will be calculated from it. + * If the DN is not set, then the RDN will be calcuated from the template attribute definitions + * + * @return rdn RDN for this template + */ + public function getRDN() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # If the DN is set, then the RDN will be calculated from it. + if ($this->dn) + return get_rdn($this->dn); + + $rdn = ''; + + foreach ($this->getRDNObjects() as $attribute) { + $vals = $attribute->getValues(); + + # If an RDN attribute has no values, return with an empty string. The calling script should handle this. + if (! count($vals)) + return ''; + + foreach ($vals as $val) + $rdn .= sprintf('%s=%s+',$attribute->getName(false),$val); + } + + # Chop the last plus sign off when returning + return preg_replace('/\+$/','',$rdn); + } + + /** + * Return the attribute name part of the RDN + */ + public function getRDNAttributeName() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $attr = array(); + + if ($this->getDN()) { + $i = strpos($this->getDN(),','); + if ($i !== false) { + $attrs = explode('\+',substr($this->getDN(),0,$i)); + foreach ($attrs as $id => $attr) { + list ($name,$value) = explode('=',$attr); + $attrs[$id] = $name; + } + + $attr = array_unique($attrs); + } + } + + return $attr; + } + + /** + * Determine the type of template this is + */ + public function getContext() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if ($this->getContainer() && get_request('cmd','REQUEST') == 'copy') + return 'copyasnew'; + elseif ($this->getContainer() || get_request('create_base')) + return 'create'; + elseif ($this->getDN()) + return 'edit'; + else + return 'unknown'; + } + + /** + * Test if the template is visible + * + * @return boolean + */ + public function isVisible() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->visible); + + return $this->visible; + } + + public function setVisible() { + $this->visible = true; + } + + public function setInvisible() { + $this->visible = false; + } + + public function getRegExp() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->regexp); + + return $this->regexp; + } + + /** + * Test if this template has been marked as a read-only template + */ + public function isReadOnly() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if ((($this->getContext() == 'edit') && $this->readonly) || $this->getServer()->isReadOnly()) + return true; + else + return false; + } + + /** + * Get the attribute entries + * + * @param boolean Include the optional attributes + * @return array Array of attributes + */ + public function getAttributes($optional=false) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if ($optional) + return $this->attributes; + + $result = array(); + foreach ($this->attributes as $attribute) { + if (! $attribute->isRequired()) + continue; + + array_push($result,$attribute); + } + + return $result; + } + + /** + * Return a list of attributes that should be shown + */ + public function getAttributesShown() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $result = array(); + + foreach ($this->attributes as $attribute) + if ($attribute->isVisible()) + array_push($result,$attribute); + + return $result; + } + + /** + * Return a list of the internal attributes + */ + public function getAttributesInternal() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $result = array(); + + foreach ($this->attributes as $attribute) + if ($attribute->isInternal()) + array_push($result,$attribute); + + return $result; + } + + /** + * Return the objectclasses defined in this template + * + * @return array Array of Objects + */ + public function getObjectClasses() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $attribute = $this->getAttribute('objectclass'); + if ($attribute) + return $attribute->getValues(); + else + return array(); + } + + /** + * Get template icon + */ + public function getIcon() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->icon); + + return isset($this->icon) ? sprintf('%s/%s',IMGDIR,$this->icon) : ''; + } + + /** + * Return the template description + * + * @return string Description + */ + public function getDescription() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->description); + + return $this->description; + } + + /** + * Set a template as invalid + * + * @param string Message indicating the reason the template has been invalidated + */ + public function setInvalid($msg,$admin=false) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->invalid = true; + $this->invalid_reason = $msg; + $this->invalid_admin = $admin; + } + + /** + * Get the template validity or the reason it is invalid + * + * @return string Invalid reason, or false if not invalid + */ + public function isInValid() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if ($this->invalid) + return $this->invalid_reason; + else + return false; + } + + public function isAdminDisabled() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->invalid_admin); + + return $this->invalid_admin; + } + + /** + * Set the minimum number of values for an attribute + * + * @param object Attribute + * @param int + */ + private function setMinValueCount($attr,$value) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $attribute = $this->getAttribute($attr); + + if (! is_null($attribute)) + $attribute->setMinValueCount($value); + } + + /** + * Set the LDAP type property for an attribute + * + * @param object Attribute + * @param string (MUST,MAY,OPTIONAL) + */ + private function setAttrLDAPtype($attr,$value) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $attribute = $this->getAttribute($attr); + + if (is_null($attribute)) + $attribute = $this->addAttribute($attr,array('values'=>array())); + + $attribute->setLDAPtype($value); + } + + /** + * OnChangeAdd javascript processing + */ + public function OnChangeAdd($origin,$value) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $attribute = $this->getAttribute($origin); + + if (preg_match('/^=(\w+)\((.*)\)$/',$value,$matches)) { + $command = $matches[1]; + $arg = $matches[2]; + } else + return; + + switch ($command) { + /* + autoFill:string + string is a literal string, and may contain many fields like %attr|start-end/flags% + to substitute values read from other fields. + |start-end is optional, but must be present if the k flag is used. + /flags is optional. + + flags may be: + T: Read display text from selection item (drop-down list), otherwise, read the value of the field + For fields that aren't selection items, /T shouldn't be used, and the field value will always be read. + k: Tokenize: + If the "k" flag is not given: + A |start-end instruction will perform a sub-string operation upon + the value of the attr, passing character positions start-end through. + start can be 0 for first character, or any other integer. + end can be 0 for last character, or any other integer for a specific position. + If the "k" flag is given: + The string read will be split into fields, using : as a delimiter + "start" indicates which field number to pass through. + K: The string read will be split into fields, using ' ' as a delimiter "start" indicates which field number to pass through. + l: Make the result lower case. + U: Make the result upper case. + */ + case 'autoFill': + if (! preg_match('/;/',$arg)) { + system_message(array( + 'title'=>_('Problem with autoFill() in template'), + 'body'=>sprintf('%s (%s)',_('There is only 1 argument, when there should be two'),$attribute->getName(false)), + 'type'=>'warn')); + + return; + } + + list($attr,$string) = preg_split('(([^,]+);(.*))',$arg,-1,PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); + preg_match_all('/%(\w+)(\|[0-9]*-[0-9]*)?(\/[KklTUA]+)?%/U',$string,$matchall); + //print"
";print_r($matchall); //0 = highlevel match, 1 = attr, 2 = subst, 3 = mod
+
+				if (! isset($attribute->js['autoFill']))
+					$attribute->js['autoFill'] = '';
+
+				$formula = $string;
+				$formula = preg_replace('/^([^%])/','\'$1',$formula);
+				$formula = preg_replace('/([^%])$/','$1\'',$formula);
+
+				# Check that our attributes match our schema attributes.
+				foreach ($matchall[1] as $index => $checkattr) {
+					$sattr = $this->getServer()->getSchemaAttribute($checkattr);
+
+					# If the attribute is the same as in the XML file, then dont need to do anything.
+					if (! $sattr || ! strcasecmp($sattr->getName(),$checkattr))
+						continue;
+
+					$formula = preg_replace("/$checkattr/",$sattr->getName(),$formula);
+					$matchall[1][$index] = $sattr->getName();
+				}
+
+				$elem_id = 0;
+
+				foreach ($matchall[0] as $index => $null) {
+					$match_attr = strtolower($matchall[1][$index]);
+					$match_subst = $matchall[2][$index];
+					$match_mod = $matchall[3][$index];
+
+					$substrarray = array();
+
+					if (! isset($varcount[$match_attr]))
+						$varcount[$match_attr] = 0;
+					else
+						$varcount[$match_attr]++;
+
+					$js_match_attr = $match_attr;
+					$match_attr = $js_match_attr.'xx'.$varcount[$match_attr];
+
+					$formula = preg_replace('/%'.$js_match_attr.'([|\/%])/i','%'.$match_attr.'$1',$formula,1);
+
+					$attribute->js['autoFill'] .= sprintf("  var %s;\n",$match_attr);
+					$attribute->js['autoFill'] .= sprintf(
+							"  var elem$elem_id = document.getElementById(pre+'%s'+suf);\n".
+							"  if (!elem$elem_id) return;\n", $js_match_attr);
+
+					if (strstr($match_mod,'T')) {
+						$attribute->js['autoFill'] .= sprintf("  %s = elem$elem_id.options[elem$elem_id.selectedIndex].text;\n",
+							$match_attr);
+					} else {
+						$attribute->js['autoFill'] .= sprintf("  %s = elem$elem_id.value;\n",$match_attr);
+					}
+
+					$elem_id++;
+
+					if (strstr($match_mod,'k')) {
+						preg_match_all('/([0-9]+)/',trim($match_subst),$substrarray);
+						if (isset($substrarray[1][0])) {
+							$tok_idx = $substrarray[1][0];
+						} else {
+							$tok_idx = '0';
+						}
+						$attribute->js['autoFill'] .= sprintf("   %s = %s.split(':')[%s];\n",$match_attr,$match_attr,$tok_idx);
+
+					} elseif (strstr($match_mod,'K')) {
+						preg_match_all('/([0-9]+)/',trim($match_subst),$substrarray); 
+						if (isset($substrarray[1][0])) { 
+							$tok_idx = $substrarray[1][0]; 
+						} else { 
+							$tok_idx = '0'; 
+						} 
+						$attribute->js['autoFill'] .= sprintf("   %s = %s.split(' ')[%s];\n",$match_attr,$match_attr,$tok_idx); 
+
+					} else {
+						preg_match_all('/([0-9]*)-([0-9]*)/',trim($match_subst),$substrarray);
+						if ((isset($substrarray[1][0]) && $substrarray[1][0]) || (isset($substrarray[2][0]) && $substrarray[2][0])) {
+							$attribute->js['autoFill'] .= sprintf("   %s = %s.substr(%s,%s);\n",
+								$match_attr,$match_attr,
+								$substrarray[1][0] ? $substrarray[1][0] : '0',
+								$substrarray[2][0] ? $substrarray[2][0] : sprintf('%s.length',$match_attr));
+						}
+					}
+
+					if (strstr($match_mod,'l')) {
+						$attribute->js['autoFill'] .= sprintf("   %s = %s.toLowerCase();\n",$match_attr,$match_attr);
+					}
+					if (strstr($match_mod,'U')) {
+						$attribute->js['autoFill'] .= sprintf("   %s = %s.toUpperCase();\n",$match_attr,$match_attr);
+					}
+					if (strstr($match_mod,'A')) {
+						$attribute->js['autoFill'] .= sprintf("   %s = toAscii(%s);\n",$match_attr,$match_attr);
+					}
+
+					# Matchfor only entry without modifiers.
+					$formula = preg_replace('/^%('.$match_attr.')%$/U','$1 + \'\'',$formula);
+					# Matchfor only entry with modifiers.
+					$formula = preg_replace('/^%('.$match_attr.')(\|[0-9]*-[0-9]*)?(\/[KklTUA]+)?%$/U','$1 + \'\'',$formula);
+					# Matchfor begining entry.
+					$formula = preg_replace('/^%('.$match_attr.')(\|[0-9]*-[0-9]*)?(\/[KklTUA]+)?%/U','$1 + \'',$formula);
+					# Matchfor ending entry.
+					$formula = preg_replace('/%('.$match_attr.')(\|[0-9]*-[0-9]*)?(\/[KklTUA]+)?%$/U','\' + $1 ',$formula);
+					# Match for entries not at begin/end.
+					$formula = preg_replace('/%('.$match_attr.')(\|[0-9]*-[0-9]*)?(\/[:lTUA]+)?%/U','\' + $1 + \'',$formula);
+					$attribute->js['autoFill'] .= "\n";
+				}
+
+				$attribute->js['autoFill'] .= sprintf(" fillRec(pre+'%s'+suf, %s); // %s\n",strtolower($attr),$formula,$string);
+				$attribute->js['autoFill'] .= "\n";
+				break;
+
+			default: $return = '';
+		}
+	}
+
+	/**
+	 * This functions main purpose is to discover our MUST attributes based on objectclass
+	 * definitions in the template file and to discover which of the objectclasses are
+	 * STRUCTURAL - without one, creating an entry will just product an LDAP error.
+	 */
+	private function rebuildTemplateAttrs() {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		$server = $this->getServer();
+
+		# Collect our structural, MUST & MAY attributes.
+		$oclass_processed = array();
+		$superclasslist = array();
+		$allattrs = array('objectclass');
+
+		foreach ($this->getObjectClasses() as $oclass) {
+			# If we get some superclasses - then we'll need to go through them too.
+			$supclass = true;
+			$inherited = false;
+
+			while ($supclass) {
+				$soc = $server->getSchemaObjectClass($oclass);
+
+				if ($soc->getType() == 'structural' && (! $inherited))
+					array_push($this->structural_oclass,$oclass);
+
+				# Make sure our MUST attributes are marked as such for this template.
+				if ($soc->getMustAttrs())
+					foreach ($soc->getMustAttrs() as $index => $details) {
+						$objectclassattr = $details->getName();
+
+						# We add the 'objectClass' attribute, only if it's explicitly in the template attribute list
+						if ((strcasecmp('objectClass',$objectclassattr) != 0) ||
+								((strcasecmp('objectClass',$objectclassattr) == 0) && (! is_null($this->getAttribute($objectclassattr))))) {
+
+							# Go through the aliases, and ignore any that are already defined.
+							$ignore = false;
+							$sattr = $server->getSchemaAttribute($objectclassattr);
+							foreach ($sattr->getAliases() as $alias) {
+								if ($this->isAttrType($alias,'must')) {
+									$ignore = true;
+									break;
+								}
+							}
+
+							if ($ignore)
+								continue;
+
+							$this->setAttrLDAPtype($sattr->getName(),'must');
+							$this->setMinValueCount($sattr->getName(),1);
+
+							# We need to mark the attributes as show, except for the objectclass attribute.
+							if (strcasecmp('objectClass',$objectclassattr) != 0) {
+								$attribute = $this->getAttribute($sattr->getName());
+								$attribute->show();
+							}
+						}
+
+						if (! in_array($objectclassattr,$allattrs))
+							array_push($allattrs,$objectclassattr);
+					}
+
+				if ($soc->getMayAttrs())
+					foreach ($soc->getMayAttrs() as $index => $details) {
+						$objectclassattr = $details->getName();
+						$sattr = $server->getSchemaAttribute($objectclassattr);
+
+						# If it is a MUST attribute, skip to the next one.
+						if ($this->isAttrType($objectclassattr,'must'))
+							continue;
+
+						if (! $this->isAttrType($objectclassattr,'may'))
+							$this->setAttrLDAPtype($sattr->getName(false),'may');
+
+						if (! in_array($objectclassattr,$allattrs))
+							array_push($allattrs,$objectclassattr);
+					}
+
+				# Keep a list to objectclasses we have processed, so we dont get into a loop.
+				array_push($oclass_processed,$oclass);
+				$supoclasses = $soc->getSupClasses();
+
+				if (count($supoclasses) || count($superclasslist)) {
+					foreach ($supoclasses as $supoclass) {
+						if (! in_array($supoclass,$oclass_processed))
+							$superclasslist[] = $supoclass;
+					}
+
+					$oclass = array_shift($superclasslist);
+					if ($oclass)
+						$inherited = true;
+					else
+						$supclass = false;
+
+				} else {
+					$supclass = false;
+				}
+			}
+		}
+
+		# Check that attributes are defined by an ObjectClass
+		foreach ($this->getAttributes(true) as $index => $attribute)
+			if (! in_array($attribute->getName(),$allattrs) && (! array_intersect($attribute->getAliases(),$allattrs))
+				&& (! in_array_ignore_case('extensibleobject',$this->getObjectClasses()))
+				&& (! in_array_ignore_case($attribute->getName(),$server->getValue('server','custom_attrs')))) {
+				unset($this->attributes[$index]);
+
+				if (! $_SESSION[APPCONFIG]->getValue('appearance','hide_template_warning'))
+					system_message(array(
+						'title'=>_('Automatically removed attribute from template'),
+						'body'=>sprintf('%s: %s %s',$this->getTitle(),$attribute->getName(false),_('removed from template as it is not defined by an ObjectClass')),
+						'type'=>'warn'));
+			}
+	}
+
+	/**
+	 * Return an array, that can be passed to ldap_add().
+	 * Attributes with empty values will be excluded.
+	 */
+	public function getLDAPadd($attrsOnly=false) {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		$return = array();
+		$returnattrs = array();
+
+		if ($attrsOnly && count($returnattrs))
+			return $returnattrs;
+
+		foreach ($this->getAttributes(true) as $attribute)
+			if (! $attribute->isInternal() && count($attribute->getValues())) {
+				$return[$attribute->getName()] = $attribute->getValues();
+				$returnattrs[$attribute->getName()] = $attribute;
+			}
+
+		# Ensure that our objectclasses has "top".
+		if (isset($return['objectclass']) && ! in_array('top',$return['objectclass']))
+			array_push($return['objectclass'],'top');
+
+		if ($attrsOnly)
+			return $returnattrs;
+
+		return $return;
+	}
+
+	/**
+	 * Return an array, that can be passed to ldap_mod_replace().
+	 * Only attributes that have changed their value will be returned.
+	 *
+	 * This function will cache its results, so that it can be called with count() to see
+	 * if there are changes, and if they are, the 2nd call will just return the results
+	 *
+	 * @param boolean Return the attribute objects (useful for a confirmation process), or the modification array for ldap_modify()
+	 */
+	public function getLDAPmodify($attrsOnly=false,$index=0) {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		static $return = array();
+		static $returnattrs = array();
+
+		if ($attrsOnly && isset($returnattrs[$index]) && count($returnattrs[$index]))
+			return $returnattrs[$index];
+
+		$returnattrs[$index] = array();
+		$return[$index] = array();
+
+		# If an objectclass is being modified, we need to remove all the orphan attributes that would result.
+		if ($this->getAttribute('objectclass')->hasBeenModified()) {
+			$attr_to_keep = array();
+			$server = $this->getServer();
+
+			# Make sure that there will be a structural object class remaining.
+			$haveStructural = false;
+			foreach ($this->getAttribute('objectclass')->getValues() as $value) {
+				$soc = $server->getSchemaObjectClass($value);
+
+				if ($soc) {
+					if ($soc->isStructural())
+						$haveStructural = true;
+
+					# While we are looping, workout which attributes these objectclasses define.
+					foreach ($soc->getMustAttrs(true) as $value)
+						if (! in_array($value->getName(),$attr_to_keep))
+							array_push($attr_to_keep,$value->getName());
+
+					foreach ($soc->getMayAttrs(true) as $value)
+						if (! in_array($value->getName(),$attr_to_keep))
+							array_push($attr_to_keep,$value->getName());
+				}
+			}
+
+			if (! $haveStructural)
+				error(_('An entry should have one structural objectClass.'),'error','index.php');
+
+			# Work out the attributes to delete.
+			foreach ($this->getAttribute('objectclass')->getRemovedValues() as $value) {
+				$soc = $server->getSchemaObjectClass($value);
+
+				foreach ($soc->getMustAttrs() as $value) {
+					$attribute = $this->getAttribute($value->getName());
+
+					if ($attribute && (! in_array($value->getName(),$attr_to_keep)) && ($value->getName() != 'objectclass'))
+						#array_push($attr_to_delete,$value->getName(false));
+						$attribute->setForceDelete();
+				}
+
+				foreach ($soc->getMayAttrs() as $value) {
+					$attribute = $this->getAttribute($value->getName());
+
+					if ($attribute && (! in_array($value->getName(),$attr_to_keep)) && ($value->getName() != 'objectclass'))
+						$attribute->setForceDelete();
+				}
+			}
+		}
+
+		foreach ($this->getAttributes(true) as $attribute)
+			if ($attribute->hasBeenModified()
+				&& (count(array_diff($attribute->getValues(),$attribute->getOldValues())) || ! count($attribute->getValues())
+					|| $attribute->isForceDelete() || (count($attribute->getValues()) != count($attribute->getOldValues()))))
+				$returnattrs[$index][$attribute->getName()] = $attribute;
+
+		if ($attrsOnly)
+			return $returnattrs[$index];
+
+		foreach ($returnattrs[$index] as $attribute)
+			$return[$index][$attribute->getName()] = $attribute->getValues();
+
+		return $return[$index];
+	}
+
+	/**
+	 * Get the attributes that are marked as force delete
+	 * We'll cache this result in the event of multiple calls.
+	 */
+	public function getForceDeleteAttrs() {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		static $result = array();
+
+		if (count($result))
+			return $result;
+
+		foreach ($this->attributes as $attribute)
+			if ($attribute->isForceDelete())
+				array_push($result,$attribute);
+
+		return $result;
+	}
+
+	/**
+	 * Get available attributes
+	 */
+	public function getAvailAttrs() {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		$attributes = array();
+		$server = $this->getServer();
+
+		# Initialise the Attribute Factory.
+		$attribute_factory = new AttributeFactory();
+
+		if (in_array_ignore_case('extensibleobject',$this->getObjectClasses())) {
+			foreach ($server->SchemaAttributes() as $sattr) {
+				$attribute = $attribute_factory->newAttribute($sattr->getName(),array('values'=>array()),$server->getIndex(),null);
+				array_push($attributes,$attribute);
+			}
+
+		} else {
+			$attrs = array();
+
+			foreach ($this->getObjectClasses() as $oc) {
+				$soc = $server->getSchemaObjectClass($oc);
+				$attrs = array_merge($attrs,$soc->getMustAttrNames(true),$soc->getMayAttrNames(true));
+				$attrs = array_unique($attrs);
+			}
+
+			foreach ($attrs as $attr)
+				if (is_null($this->getAttribute($attr))) {
+					$attribute = $attribute_factory->newAttribute($attr,array('values'=>array()),$server->getIndex(),null);
+					array_push($attributes,$attribute);
+				}
+		}
+
+		masort($attributes,'name');
+		return $attributes;
+	}
+
+	public function isNoLeaf() {
+		return $this->noleaf;
+	}
+
+	public function sort() {
+		usort($this->attributes,'sortAttrs');
+	}
+}
+?>
diff --git a/lib/TemplateRender.php b/lib/TemplateRender.php
new file mode 100644
index 0000000..f761b86
--- /dev/null
+++ b/lib/TemplateRender.php
@@ -0,0 +1,2533 @@
+%s:%s
',time(),__METHOD__); + if (DEBUGTMP||DEBUGTMPSUB) printf('* %s [Visit-Start:%s]
',__METHOD__,get_class($this)); + + $tree = get_cached_item($this->server_id,'tree'); + if (! $tree) + $tree = Tree::getInstance($this->server_id); + + $treeitem = $tree->getEntry($this->dn); + + # If we have a DN, and no template_id, see if the tree has one from last time + if ($this->dn && is_null($this->template_id) && $treeitem && $treeitem->getTemplate()) + $this->template_id = $treeitem->getTemplate(); + + # Check that we have a valid template, or present a selection + # @todo change this so that the modification templates rendered are the ones for the objectclass of the dn. + if (! $this->template_id) + $this->template_id = $this->getTemplateChoice(); + + if ($treeitem) + $treeitem->setTemplate($this->template_id); + + $this->page = get_request('page','REQUEST',false,1); + + if ($this->template_id AND $this->template_id != 'invalid') { + if (! $this->template) + parent::accept(); + + $this->url_base = sprintf('server_id=%s&dn=%s', + $this->getServerID(),$this->template->getDNEncode()); + $this->layout['hint'] = sprintf('%s%%s', + IMGDIR,_('Hint')); + $this->layout['action'] = '%s%s'; + $this->layout['actionajax'] = '%s%s'; + + # If we dont want to render this template automatically, we'll return here. + if ($norender) + return; + + $this->visitStart(); + + foreach ($this->template->getAttributes(true) as $attribute) { + # Evaluate our defaults + if ($attribute->getAutoValue()) + $this->get('Default',$attribute, + $this->template->getContainer() ? $this->template->getContainer() : $this->getServer()->getContainerPath($this->template->getDN()), + 'autovalue'); + + # If this is the default template, we should mark all our attributes to show(). + if (($this->template->getID() == 'none') && (! $attribute->isInternal()) + && (($this->template->getContext() == 'edit' && $this->template->getID() == 'none') + || ($this->template->getContext() == 'create' && $attribute->getName() != 'objectclass'))) + $attribute->show(); + } + + if (DEBUGTMP||DEBUGTMPSUB) printf('* %s [Visit-End:%s]
',__METHOD__,get_class($this)); + + $this->visitEnd(); + } + } + + protected function getDefaultAttribute($attribute,$container,$type) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + switch ($type) { + case 'autovalue': + $autovalue = $attribute->getAutoValue(); + + break; + + case 'helpervalue': + $autovalue = $attribute->getHelperValue(); + + break; + + default: + system_message(array( + 'title'=>_('Unknown Default Attribute context'), + 'body'=>sprintf('%s (%s)',_('A call was made to getDefaultAttribute() with an unkown context'),$type), + 'type'=>'warn')); + + return; + } + + $args = explode(';',$autovalue['args']); + $server = $this->getServer(); + $vals = ''; + + switch ($autovalue['function']) { + /** + * Function enables normal PHP functions to be called to evaluate a value. + * eg: =php.Function(date;dmY) + * + * All arguments will be passed to the function, and its value returned. + * If this used used in a POST context, the attribute values can be used as arguments. + * + * Mandatory Arguments: + * * arg 0 + * - php Function to call + * + * Additional arguments will be passed to the function. + */ + case 'Function': + $function = array_shift($args); + + if (count($args) && count($args) > 1) { + system_message(array( + 'title'=>_('Too many arguments'), + 'body'=>sprintf('%s (%s)',_('Function() only takes two arguments and more than two were specified'),count($args)), + 'type'=>'warn')); + + return; + } + + $function_args = explode(',',$args[0]); + + if (function_exists($function)) + $vals = call_user_func_array($function,$function_args); + + else + system_message(array( + 'title'=>_('Function doesnt exist'), + 'body'=>sprintf('%s (%s)',_('An attempt was made to call a function that doesnt exist'),$function), + 'type'=>'warn')); + + break; + + /** + * GetNextNumber will query the LDAP server and calculate the next number based on the query + * eg: + * + * Mandatory Arguments: + * * arg 0 + * - "$" => 'auto_number','search_base' in config file + * - "/",".",".." => get container parent as usual + * + * * arg 1 + * - attribute to query for + * + * Optional Arguments: + * * arg 2 (pool mechanism only) + * - "true" increments attribute by 1 + * - "false" do nothing + * + * * arg 3 (pool mechanism only) + * - ldap filter (must match one entry only in container) + * + * * arg 4 + * - calculus on number, eg: + * - *2,+1000 => number = (2*number) + 1000 + * + * * arg 5 + * - Min number + */ + case 'GetNextNumber': + # If the attribute already has values, we'll return + if ($type == 'autovalue' && $attribute->getValues()) + return; + + if ($args[0] == '$') + $args[0] = $server->getValue($this->server_id,'auto_number','search_base'); + + $container = $server->getContainerPath($container,$args[0]); + + $vals = get_next_number($container,$args[1], + (! empty($args[2]) && ($args[2] == 'false')) ? false : true, + (! empty($args[3])) ? $args[3] : false, + (! empty($args[5])) ? $args[5] : null); + + # Operate calculus on next number. + if (! empty($args[4])) { + $mod = explode(',',$args[4]); + $next_number = $vals; + + foreach ($mod as $calc) { + $operand = $calc{0}; + $operator = substr ($calc,1); + + switch ($operand) { + case '*': + $next_number = $next_number * $operator; + break; + + case '+': + $next_number = $next_number + $operator; + break; + + case '-': + $next_number = $next_number - $operator; + break; + + case '/': + $next_number = $next_number / $operator; + break; + } + } + + $vals = $next_number; + } + + break; + + /** + * PickList will query the LDAP server and provide a select list of values + * MultiList will query the LDAP server and provide a multi select list of values + * eg: + * + * eg: cn=root,nobody => cn=nobody;gidNumber;10)]]> + * + * Mandatory Arguments: + * * arg 0 + * - container, to query from current position + * - "/",".",".." => get container parent as usual + * + * * arg 1 + * - LDAP filter. May include '%attr%', it will be expanded. + * + * * arg2 + * - list attribute key + * + * Optional Arguments: + * * arg3 + * - select display (plus modifier /C: Capitalize) + * - replaced by %arg 2% if not given + * + * * arg 4 + * - the value furnished in output - must be attribute id. replaced by arg 2 if not given + * + * * arg 5 + * - container override + * + * * arg 6 + * - csv list (, separator) of added values. syntax: key => display_attribute=value, key... + * + * * arg 7 + * - csv list (, separator) of sort attributes (less to more important) + * + * * arg 8 (for MultiList) + * - size of displayed list (default: 10 lines) + */ + case 'MultiList': + case 'PickList': + # arg5 overrides our container + if (empty($args[5])) + $container = $server->getContainerPath($container,$args[0]); + else + $container = $args[5]; + + # Process filter (arg 1), eventually replace %attr% by it's value set in a previous page. + preg_match_all('/%(\w+)(\|.+)?(\/[lUC])?%/U',$args[1],$filtermatchall); + //print_r($matchall); // -1 = highlevel match, 1 = attr, 2 = subst, 3 = mod + + if (isset($_REQUEST['form'])) { + $formvalues = array_change_key_case($_REQUEST['form']); + + foreach ($filtermatchall[1] as $arg) { + $value = $formvalues[strtolower($arg)]; + $args[1] = preg_replace("/%($arg)(\|.+)?(\/[lU])?%/U",$value,$args[1]); + } + } + + if (empty($args[3])) + $args[3] = "%{$args[2]}%"; + + preg_match_all('/%(\w+)(\|.+)?(\/[lUC])?%/U',$args[3],$matchall); + //print_r($matchall); // -1 = highlevel match, 1 = attr, 2 = subst, 3 = mod + + $attrs = array_unique(array_merge($matchall[1],array($args[2]))); + + # arg7 is sort attributes + if (isset($args[7])) { + $sort_attrs = explode(',',$args[7]); + $attrs = array_unique(array_merge($attrs,$sort_attrs)); + } + + $picklistvalues = return_ldap_hash($container,$args[1],$args[2],$attrs,(isset($args[7]) && ($args[7])) ? $sort_attrs : false); + + # arg6 is a set of fixed values to add to search result + if (isset($args[6])) { + $fixedvalues = explode(',',$args[6]); + + foreach ($fixedvalues as $fixedvalue) { + if (empty($fixedvalue)) + continue; + + $fixedvalue = preg_split('/=\>/',$fixedvalue); + $displayvalue = explode('=',$fixedvalue[1]); + + $newvalue[trim($fixedvalue[0])] = array($args[2]=>trim($fixedvalue[0]),trim($displayvalue[0])=>trim($displayvalue[1])); + + $picklistvalues = array_merge($picklistvalues,$newvalue); + } + } + + $vals = array(); + + foreach ($picklistvalues as $key => $values) { + $display = $args[3]; + + foreach ($matchall[1] as $key => $arg) { + if (isset($values[$arg])) + $disp_val = $values[$arg]; + else + $disp_val = ''; + + if (is_array($disp_val)) + $disp_val = $disp_val[0]; + + if ($matchall[3][$key]) + switch ($matchall[3][$key]) { + case '/l': + # lowercase + if (function_exists('mb_convert_case')) + $disp_val = mb_convert_case($disp_val,MB_CASE_LOWER,'utf-8'); + else + $disp_val = strtolower($disp_val); + + break; + + case '/U': + # uppercase + if (function_exists('mb_convert_case')) + $disp_val = mb_convert_case($disp_val,MB_CASE_UPPER,'utf-8'); + else + $disp_val = strtoupper($disp_val); + + break; + + case '/C': + # capitalize + if (function_exists('mb_convert_case')) + $disp_val = mb_convert_case($disp_val,MB_CASE_TITLE,'utf-8'); + else + $disp_val = ucfirst($disp_val); + + break; + + default: + break; + } + + # make value a substring of + preg_match_all('/^\|([0-9]*)-([0-9]*)$/',trim($matchall[2][$key]),$substrarray); + + if ((isset($substrarray[1][0]) && $substrarray[1][0]) || (isset($substrarray[2][0]) && $substrarray[2][0])) { + $begin = $substrarray[1][0] ? $substrarray[1][0] : '0'; + $end = $substrarray[2][0] ? $substrarray[2][0] : strlen($disp_val); + + if (function_exists('mb_substr')) + $disp_val = mb_substr($disp_val,$begin,$end,'utf-8'); + else + $disp_val = substr($disp_val,$begin,$end); + } + + $display = preg_replace("/%($arg)(\|.+)?(\/[lUC])?%/U",$disp_val,$display); + } + + if (! isset($picklist[$values[$args[2]]])) { + $vals[$values[$args[2]]] = $display; + $picklist[$values[$args[2]]] = true; + } + } + + break; + + /** + * PasswordEncryptionTypes will return a list of our support password encryption types + * eg: =php.PasswordEncryptionTypes() + * + * This function doesnt use any arguments + */ + case 'PasswordEncryptionTypes': + $vals = password_types(); + + break; + + /** + * RandomPassword will create a random password for the value. + * eg: =php.RandomPassword() + * + * When calling the attribute Javascript it will generate a random password. + * + * This function doesnt use any arguments + */ + case 'RandomPassword': + break; + } + + switch ($type) { + case 'autovalue': + if (! is_array($vals)) + $attribute->autoValue(array($vals)); + else + $attribute->autoValue($vals); + + break; + + case 'helpervalue': + return $vals; + } + } + + /** + * Set the mode of the TemplateRender + * Applicable modes are "create" or "edit" + */ + protected function getMode() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if ($this->dn) + return 'modification'; + elseif ($this->container) + return 'creation'; + elseif (get_request('create_base')) + return 'creation'; + else + debug_dump_backtrace(sprintf('Unknown mode for %s',__METHOD__),1); + } + + /** + * Return the container for this mode + */ + protected function getModeContainer() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + switch ($this->getMode()) { + case 'creation': + return $this->container; + break; + + case 'modification': + return $this->dn; + break; + + default: + return null; + } + } + + /** + * Is the default template enabled? + */ + protected function haveDefaultTemplate() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if ($_SESSION[APPCONFIG]->getValue('appearance','disable_default_template')) + return false; + else + return true; + } + + /** + * Present a list of available templates for creating and editing LDAP entries + */ + protected function drawTemplateChoice() { + if (DEBUGTMP) printf('%s
',__METHOD__); + + $this->drawTitle(); + $this->drawSubTitle(); + echo "\n"; + + switch ($this->getMode()) { + case 'creation': + $msg = _('Select a template for the creation process'); + break; + + case 'modification': + $msg = _('Select a template to edit the entry'); + break; + } + + $avail_templates = $this->getTemplates(); + $templates = $avail_templates->getTemplates($this->getMode(),$this->getModeContainer()); + printf('

%s

',$msg); + + $href_parms = array_to_query_string($_GET,array('meth')); + printf('
',htmlspecialchars($href_parms)); + echo "\n\n"; + + if (count($_POST)) { + echo '
'; + foreach ($_POST as $p => $v) + printf('',$p,$v); + echo '
'; + echo "\n\n"; + } + + echo ''; + echo ''; + printf('',_('Templates')); + echo ''; + + echo '
%s:'; + echo ''; + + $i = -1; + $nb_templates = count($templates); + + if ($this->haveDefaultTemplate()) + $nb_templates++; + + foreach ($templates as $name => $details) { + $i++; + + $isInValid = $details->isInValid(); + + # Balance the columns properly + if (($nb_templates % 2 == 0 && $i == intval($nb_templates / 2)) || + ($nb_templates % 2 == 1 && $i == intval($nb_templates / 2) + 1)) { + echo '
'; + } + + echo "\n"; + echo ''; + + if ($isInValid) + printf('',IMGDIR); + + else { + if (isAjaxEnabled()) + printf('', + htmlspecialchars($details->getID()),htmlspecialchars($details->getID()),htmlspecialchars($href_parms),$details->getID(),str_replace('\'','\\\'',_('Retrieving DN'))); + else + printf('', + htmlspecialchars($details->getID()),htmlspecialchars($details->getID())); + } + + printf('', + htmlspecialchars($details->getID()),$details->getIcon()); + printf(''; + echo ''; + } + echo "\n"; + + # Default template + if ($this->haveDefaultTemplate()) { + $i++; + + # Balance the columns properly + if (($nb_templates % 2 == 0 && $i == intval($nb_templates / 2)) || + ($nb_templates % 2 == 1 && $i == intval($nb_templates / 2) + 1)) { + echo '
Disabled
'; + } + + echo ''; + if (isAjaxEnabled()) + printf('', + htmlspecialchars($href_parms),'none',str_replace('\'','\\\'',_('Retrieving DN'))); + else + echo ''; + + printf('',IMGDIR); + printf('',_('Default')); + echo ''; + } + + echo '
'; + echo '
'; + echo '
'; + } + + /** VISIT METHODS **/ + + /** + * This function will setup our template object (read LDAP for current values, read $_REQUEST for new values, etc) + * so that it can be rendered. + */ + private function visitStart() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + # If we have a DN, then we are an editing template + if ($this->dn) + $this->template->setDN($this->dn); + + # Else if we have a container, we are a creating template + elseif ($this->container || get_request('create_base')) + $this->template->setContainer($this->container); + + else + debug_dump_backtrace('Dont know what type of template we are - no DN or CONTAINER?',1); + + # Header + $this->drawHeader(); + } + + private function visitEnd() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + foreach ($this->template->getAttributesShown() as $attribute) + if ($attribute->getPage() > $this->pagelast) + $this->pagelast = $attribute->getPage(); + echo "\n\n"; + + if ($this->template->getContext() == 'create') { + $this->drawStepTitle($this->page); + $this->drawStepFormStart($this->page); + $this->drawStepForm($this->page); + $this->drawStepFormEnd(); + + } elseif ($this->template->getContext() == 'copyasnew') { + $this->drawStepFormStart($this->page); + printf('',$this->template->getContainer(false)); + echo '
'; + $this->drawRDNChooser(); + echo '
'; + $this->drawForm(true); + $this->drawStepFormSubmitButton($this->page); + + } else { + # Draw internal attributes + if (get_request('show_internal_attrs','REQUEST')) { + echo ''; + $this->drawInternalAttributes(); + echo '

'; + echo "\n"; + } + + $this->drawFormStart(); + + # To support our AJAX add Attribute + printf('
','none'); + + $this->drawForm(); + $this->drawStepFormEnd(); + } + } + + /** PAGE DRAWING METHODS **/ + + private function drawHeader() { + if (DEBUGTMP) printf('%s
',__METHOD__); + + # Title + $this->drawTitle(); + if (get_request('create_base')) + $this->drawSubTitle(sprintf('%s: %s',_('Creating Base DN'),$this->template->getDN())); + else + $this->drawSubTitle(); + echo "\n"; + + # Menu + $this->drawMenu(); + } + + public function drawTitle($title=null) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + if (is_null($title)) + switch ($this->getMode()) { + case 'creation': + $title = _('Create Object'); + break; + + case 'modification': + $title = htmlspecialchars(get_rdn($this->dn)); + break; + + default: + $title = 'Title'; + } + + parent::drawTitle($title); + } + + public function drawSubTitle($subtitle=null) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + if ($subtitle) + return parent::drawSubTitle($subtitle); + + switch ($this->getMode()) { + case 'creation': + $subtitle = sprintf('%s: %s   %s: %s', + _('Server'),$this->getServer()->getName(), + _('Container'),htmlspecialchars($this->container)); + + if ($this->template_id) { + $subtitle .= '
'; + $subtitle .= sprintf('%s: %s',_('Template'),$this->template->getID() != 'none' ? $this->template->getTitle() : _('Default')); + if ($this->template->getName()) + $subtitle .= sprintf(' (%s)',$this->template->getName(false)); + } + + break; + + case 'modification': + $subtitle = sprintf('%s: %s   %s: %s', + _('Server'),$this->getServer()->getName(), + _('Distinguished Name'),htmlspecialchars($this->dn)); + + if ($this->template_id) { + $subtitle .= '
'; + $subtitle .= sprintf('%s: %s',_('Template'),$this->template->getID() != 'none' ? $this->template->getTitle() : _('Default')); + if ($this->template->getName()) + $subtitle .= sprintf(' (%s)',$this->template->getName(false)); + } + + break; + } + + parent::drawSubTitle($subtitle); + } + + /** PAGE ENTRY MENU **/ + + private function drawMenu() { + if (DEBUGTMP) printf('%s
',__METHOD__); + + # We only have a menu for editing entries. + if ($this->template->getContext() == 'edit') { + + echo ''; + echo ''; + $menuitem_number = 0; + + foreach (array('entryrefresh','showinternal','switchtemplate','entryexport','entrycopy','entrydelete','entryrename','entrycompare','childcreate','addattr','msgdel','childview','childexport','msgschema','msgro','msgmodattr') as $item) { + $item = $this->getMenuItem($item); + + if ($item) { + $endofrow = false; + $start = true; + $it = ''; // menu item + $ms = ''; // item message + + if (is_array($item) && count($item) > 0) { + $it = $item[0]; + + if (count($item) > 1) + $ms = $item[1]; + + } else { + $it = $item; + } + + if ($it) { + $menuitem_number++; + echo $it; + + if ($ms) { + if (($menuitem_number % 2) == 1) { + $menuitem_number++; + echo ''; + $endofrow = false; + $start = false; + } + + if ($endofrow) + print $ms; + else + echo "$ms"; + + echo ''; + $endofrow = true; + $start = false; + + } else { + if ($menuitem_number > 1 && ($menuitem_number % 2) == 0) { + echo ''; + $endofrow = true; + $start = false; + } + } + + } elseif ($ms) { + if (($menuitem_number % 2) == 1) { + $menuitem_number++; + echo ''; + $endofrow = false; + $start = false; + } + + if ($endofrow || $start) + print $ms; + else + echo "$ms"; + + echo ''; + $endofrow = true; + $start = false; + } + + echo "\n"; + } + } + + if (($menuitem_number % 2) == 1) + echo ''; + else + echo ''; + + echo ''; + echo ''; + } + } + + /** PAGE ENTRY MENU ITEMS **/ + + private function getMenuItem($i) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s (%s)
',__METHOD__,$i); + + switch ($i) { + case 'entryrefresh': + if ($_SESSION[APPCONFIG]->isCommandAvailable('cmd','entry_refresh')) + return $this->getMenuItemRefresh(); + else + return ''; + + case 'switchtemplate': + if ($_SESSION[APPCONFIG]->isCommandAvailable('cmd','switch_template')) + return $this->getMenuItemSwitchTemplate(); + else + return ''; + + case 'entryexport': + if ($_SESSION[APPCONFIG]->isCommandAvailable('script','export_form') && $_SESSION[APPCONFIG]->isCommandAvailable('script','export')) + return $this->getMenuItemExportBase(); + else + return ''; + + case 'entrycopy': + if ($_SESSION[APPCONFIG]->isCommandAvailable('script','copy_form') && $_SESSION[APPCONFIG]->isCommandAvailable('script','copy') && ! $this->template->isReadOnly()) + return $this->getMenuItemMove(); + else + return ''; + + case 'showinternal': + if ($_SESSION[APPCONFIG]->isCommandAvailable('cmd','entry_internal_attributes_show')) + return $this->getMenuItemInternalAttributes(); + else + return ''; + + case 'entrydelete': + if ($_SESSION[APPCONFIG]->isCommandAvailable('script','delete_form') && $_SESSION[APPCONFIG]->isCommandAvailable('script','delete') && ! $this->template->isReadOnly()) + return $this->getMenuItemDelete(); + else + return ''; + + case 'entryrename': + if ($_SESSION[APPCONFIG]->isCommandAvailable('script','rename_form') && $_SESSION[APPCONFIG]->isCommandAvailable('script','rename') && ! $this->template->isReadOnly()) { + + # Check if any of the RDN's are read only. + $rdnro = false; + foreach ($this->template->getRDNAttributeName() as $attr) { + $attribute = $this->template->getAttribute($attr); + + if ($attribute && $attribute->isVisible() && ! $attribute->isReadOnly()) { + $rdnro = true; + break; + } + } + + if (! $rdnro) + return $this->getMenuItemRename(); + } + + return ''; + + case 'msgdel': + if ($_SESSION[APPCONFIG]->getValue('appearance','show_hints') + && $_SESSION[APPCONFIG]->isCommandAvailable('script','delete_form') && $_SESSION[APPCONFIG]->isCommandAvailable('script','delete') && ! $this->template->isReadOnly()) + return array('',$this->getDeleteAttributeMessage()); + else + return ''; + + case 'entrycompare': + if ($_SESSION[APPCONFIG]->isCommandAvailable('script','compare_form') && $_SESSION[APPCONFIG]->isCommandAvailable('script','compare') && ! $this->template->isReadOnly()) + return $this->getMenuItemCompare(); + else + return ''; + + case 'childcreate': + if ($_SESSION[APPCONFIG]->isCommandAvailable('script','create') && ! $this->template->isReadOnly() && ! $this->template->isNoLeaf()) + return $this->getMenuItemCreate(); + else + return ''; + + case 'addattr': + if ($_SESSION[APPCONFIG]->isCommandAvailable('script','add_attr_form') && ! $this->template->isReadOnly()) + return $this->getMenuItemAddAttribute(); + else + return ''; + + case 'childview': + case 'childexport': + static $children_count = false; + static $more_children = false; + + $tree = get_cached_item($this->getServerID(),'tree'); + $tree_item = $tree->getEntry($this->template->getDN()); + + if (! $tree_item) { + $tree->addEntry($this->template->getDN()); + $tree_item = $tree->getEntry($this->template->getDN()); + } + + if ($children_count === false) { + # Visible children in the tree + $children_count = count($tree_item->getChildren()); + # Is there filtered children ? + $more_children = $tree_item->isSizeLimited(); + + if (! $children_count || ! $more_children) { + # All children in ldap + $all_children = $this->getServer()->getContainerContents( + $this->template->getDN(),null,$children_count+1,'(objectClass=*)',$_SESSION[APPCONFIG]->getValue('deref','view'),null); + + $more_children = (count($all_children) > $children_count); + } + } + + if ($children_count > 0 || $more_children) { + if ($children_count <= 0) + $children_count = ''; + if ($more_children) + $children_count .= '+'; + + if ($i == 'childview') + return $this->getMenuItemShowChildren($children_count); + elseif ($i == 'childexport' && $_SESSION[APPCONFIG]->isCommandAvailable('script','export_form') && $_SESSION[APPCONFIG]->isCommandAvailable('script','export')) + return $this->getMenuItemExportSub(); + else + return ''; + + } else + return ''; + + case 'msgschema': + if ($_SESSION[APPCONFIG]->getValue('appearance','show_hints') && $_SESSION[APPCONFIG]->isCommandAvailable('script','schema')) + return array('',$this->getViewSchemaMessage()); + else + return array(); + + case 'msgro': + if ($this->template->isReadOnly()) + return array('',$this->getReadOnlyMessage()); + else + return array(); + + case 'msgmodattr': + $modified_attrs = array(); + $modified = get_request('modified_attrs','REQUEST',false,array()); + + foreach ($this->template->getAttributes(true) as $attribute) + if (in_array($attribute->getName(),$modified)) + array_push($modified_attrs,$attribute->getFriendlyName()); + + if (count($modified_attrs)) + return array('',$this->getModifiedAttributesMessage($modified_attrs)); + else + return array(); + + default: + return false; + } + } + + protected function getDeleteAttributeMessage() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + if ($_SESSION[APPCONFIG]->isCommandAvailable('script','delete_attr') && ! $this->template->isReadOnly()) + return sprintf($this->layout['hint'],_('Hint: To delete an attribute, empty the text field and click save.')); + else + return ''; + } + + protected function getModifiedAttributesMessage(&$modified_attributes) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + return sprintf($this->layout['hint'], + (count($modified_attributes) == 1) ? + sprintf(_('An attribute (%s) was modified and is highlighted below.'),implode('',$modified_attributes)) : + sprintf(_('Some attributes (%s) were modified and are highlighted below.'),implode(', ',$modified_attributes))); + } + + protected function getReadOnlyMessage() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + return sprintf($this->layout['hint'],_('Viewing entry in read-only mode.')); + } + + protected function getViewSchemaMessage() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + return sprintf($this->layout['hint'],_('Hint: To view the schema for an attribute, click the attribute name.')); + } + + /** PAGE ENTRY MENU ITEMS DETAILS **/ + + private function getMenuItemRefresh() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + $href = sprintf('cmd=template_engine&%s&junk=%s',$this->url_base,random_junk()); + + if (isAjaxEnabled()) + return sprintf($this->layout['actionajax'],IMGDIR,'refresh.png',_('Refresh'), + htmlspecialchars($href),_('Refresh this entry'),htmlspecialchars($href),str_replace('\'','\\\'',_('Reloading')),_('Refresh')); + else + return sprintf($this->layout['action'],IMGDIR,'refresh.png',_('Refresh'), + htmlspecialchars($href),_('Refresh this entry'),_('Refresh')); + } + + protected function getMenuItemSwitchTemplate() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $href = sprintf('cmd=template_engine&%s&template=',$this->url_base); + + if (isAjaxEnabled()) + return sprintf($this->layout['actionajax'],IMGDIR,'switch.png',_('Switch Template'), + htmlspecialchars($href),_('Change to another template'),htmlspecialchars($href),str_replace('\'','\\\'',_('Loading')),_('Switch Template')); + else + return sprintf($this->layout['action'],IMGDIR,'switch.png',_('Switch Template'), + htmlspecialchars($href),_('Change to another template'),_('Switch Template')); + } + + protected function getMenuItemExportBase() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + $href = sprintf('cmd=export_form&%s&scope=base',$this->url_base); + + if (isAjaxEnabled()) + return sprintf($this->layout['actionajax'],IMGDIR,'export.png',_('Export'), + htmlspecialchars($href),_('Save a dump of this object'),htmlspecialchars($href),str_replace('\'','\\\'',_('Loading')),_('Export')); + else + return sprintf($this->layout['action'],IMGDIR,'export.png',_('Export'), + htmlspecialchars($href),_('Save a dump of this object'),_('Export')); + } + + private function getMenuItemMove() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + $href = sprintf('cmd=copy_form&%s',$this->url_base); + + if (isAjaxEnabled()) + return sprintf($this->layout['actionajax'],IMGDIR,'cut.png',_('Cut'), + htmlspecialchars($href),_('Copy this object to another location, a new DN, or another server'), + htmlspecialchars($href),str_replace('\'','\\\'',_('Loading')),_('Copy or move this entry')); + else + return sprintf($this->layout['action'],IMGDIR,'cut.png',_('Cut'), + htmlspecialchars($href),_('Copy this object to another location, a new DN, or another server'), + _('Copy or move this entry')); + } + + protected function getMenuItemInternalAttributes() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + if (get_request('show_internal_attrs','REQUEST')) { + $href = sprintf('cmd=template_engine&%s&junk=',$this->url_base,random_junk()); + + return sprintf($this->layout['action'],IMGDIR,'tools-no.png',_('Hide'), + htmlspecialchars($href),'',_('Hide internal attributes')); + + } else { + $href = sprintf('cmd=template_engine&show_internal_attrs=true&%s',$this->url_base); + + return sprintf($this->layout['action'],IMGDIR,'tools.png',_('Show'), + htmlspecialchars($href),'',_('Show internal attributes')); + } + } + + private function getMenuItemDelete() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + $href = sprintf('cmd=delete_form&%s',$this->url_base); + + if (isAjaxEnabled()) + return sprintf($this->layout['actionajax'],IMGDIR,'trash.png',_('Trash'), + htmlspecialchars($href),_('You will be prompted to confirm this decision'), + htmlspecialchars($href),str_replace('\'','\\\'',_('Loading')),_('Delete this entry')); + else + return sprintf($this->layout['action'],IMGDIR,'trash.png',_('Trash'), + htmlspecialchars($href),_('You will be prompted to confirm this decision'),_('Delete this entry')); + } + + protected function getMenuItemRename() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + $href = sprintf('cmd=rename_form&%s&template=%s',$this->url_base,$this->template->getID()); + + if (isAjaxEnabled()) + return sprintf($this->layout['actionajax'],IMGDIR,'rename.png',_('Rename'), + htmlspecialchars($href),_('Rename this entry'),htmlspecialchars($href),str_replace('\'','\\\'',_('Loading')),_('Rename')); + else + return sprintf($this->layout['action'],IMGDIR,'rename.png',_('Rename'), + htmlspecialchars($href),_('Rename this entry'),_('Rename')); + } + + protected function getMenuItemCompare() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + $href = sprintf('cmd=compare_form&%s',$this->url_base); + + if (isAjaxEnabled()) + return sprintf($this->layout['actionajax'],IMGDIR,'compare.png',_('Compare'), + htmlspecialchars($href),_('Compare this entry with another'), + htmlspecialchars($href),str_replace('\'','\\\'',_('Loading')),_('Compare with another entry')); + else + return sprintf($this->layout['action'],IMGDIR,'compare.png',_('Compare'), + htmlspecialchars($href),_('Compare this entry with another'),_('Compare with another entry')); + } + + protected function getMenuItemCreate() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + $href = sprintf('cmd=template_engine&server_id=%s&container=%s',$this->getServerID(),$this->template->getDNEncode()); + + if (isAjaxEnabled()) + return sprintf($this->layout['actionajax'],IMGDIR,'create.png',_('Create'), + htmlspecialchars($href),_('Create a child entry'), + htmlspecialchars($href),str_replace('\'','\\\'',_('Loading')),_('Create a child entry')); + else + return sprintf($this->layout['action'],IMGDIR,'create.png',_('Create'), + htmlspecialchars($href),_('Create a child entry'),_('Create a child entry')); + } + + protected function getMenuItemAddAttribute() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + if (! $this->template->getAvailAttrs()) + return ''; + + $href = sprintf('cmd=add_attr_form&%s',$this->url_base); + $layout = '%s%s'; + + if (isAjaxEnabled()) + return sprintf($layout,IMGDIR,'add.png',_('Add'), + htmlspecialchars($href),_('Add new attribute to this object'), + htmlspecialchars($href),str_replace('\'','\\\'',_('Add new attribute')),_('Add new attribute')); + else + return sprintf($this->layout['action'],IMGDIR,'add.png',_('Add'), + htmlspecialchars($href),_('Add new attribute to this object'),_('Add new attribute')); + } + + protected function getMenuItemShowChildren($children_count) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + $href = sprintf('cmd=query_engine&server_id=%s&filter=%s&base=%s&scope=one&query=none&size_limit=0&search=true', + $this->getServerID(),rawurlencode('objectClass=*'),$this->template->getDNEncode()); + + if (isAjaxEnabled()) + return sprintf($this->layout['actionajax'],IMGDIR,'children.png',_('Children'), + htmlspecialchars($href),_('View the children of this object'), + htmlspecialchars($href),str_replace('\'','\\\'',_('Loading')), + ($children_count == 1) ? _('View 1 child') : sprintf(_('View %s children'),$children_count)); + else + return sprintf($this->layout['action'],IMGDIR,'children.png',_('Children'), + htmlspecialchars($href),_('View the children of this object'), + ($children_count == 1) ? _('View 1 child') : sprintf(_('View %s children'),$children_count)); + } + + protected function getMenuItemExportSub() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + $href = sprintf('cmd=export_form&%s&scope=%s',$this->url_base,'sub'); + + if (isAjaxEnabled()) + return sprintf($this->layout['actionajax'],IMGDIR,'export.png',_('Save'), + htmlspecialchars($href),_('Save a dump of this object and all of its children'), + htmlspecialchars($href),str_replace('\'','\\\'',_('Loading')),_('Export subtree')); + else + return sprintf($this->layout['action'],IMGDIR,'export.png',_('Save'), + htmlspecialchars($href),_('Save a dump of this object and all of its children'),_('Export subtree')); + } + + /** CHOOSERS **/ + + /** + * RDN Chooser + */ + protected function drawRDNChooser() { + if (DEBUGTMP) printf('%s
',__METHOD__); + + if (! count($this->template->getRDNAttrs())) { + printf('%s','RDN'); + + echo ''; + + } else { + echo ''; + foreach ($this->template->getRDNAttrs() as $rdn) + printf('',htmlspecialchars($rdn)); + + if (get_request('create_base')) + echo ''; + + echo ''; + } + } + + /** + * Container Chooser + */ + protected function drawContainerChooser($default_container) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + echo ''; + printf('%s',_('Container')); + echo ''; + if (get_request('create_base')) + printf('%s',$default_container,htmlspecialchars($default_container)); + else { + printf('',htmlspecialchars($default_container)); + draw_chooser_link('entry_form','container'); + } + echo ''; + echo ''; + } + + /** + * Object Class Chooser + */ + protected function drawObjectClassChooser() { + if (DEBUGTMP) printf('%s
',__METHOD__); + + $socs = $this->getServer()->SchemaObjectClasses(); + if (! $socs) + $socs = array(); + + echo ''; + printf('%s',_('ObjectClasses')); + echo ''; + echo ''; + echo ''; + + if ($_SESSION[APPCONFIG]->getValue('appearance','show_hints')) { + printf(' Hint',IMGDIR); + echo _('Hint: You must choose exactly one structural objectClass (shown in bold above)'); + echo '
'; + } + } + + /** INTERNAL ATTRIBUTES **/ + + protected function drawInternalAttributes() { + if ($this->template->getAttributesInternal()) + foreach ($this->template->getAttributesInternal() as $attribute) + $this->draw('Internal',$attribute); + else + printf('(%s)
',_('No internal attributes')); + + echo "\n"; + } + + protected function drawInternalAttribute($attribute) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + $this->draw('Template',$attribute); + } + + /** FORM METHODS **/ + + public function drawFormStart() { + echo '
'; + + echo '
'; + if ($_SESSION[APPCONFIG]->getValue('confirm','update')) + echo ''; + else + echo ''; + echo '
'; + } + + protected function drawForm($nosubmit=false) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + echo '
'; + printf('',$this->getServerID()); + printf('',$this->template->getDNEncode(false)); + printf('',$this->template->getID()); + echo '
'; + + echo ''; + + $this->drawShownAttributes(); + if (! $nosubmit) + $this->drawFormSubmitButton(); + + echo '
'; + + echo '
 '; + $this->drawHiddenAttributes(); + echo '
'; + } + + public function drawFormEnd() { + if (DEBUGTMP) printf('%s
',__METHOD__); + + # Include the RDN details to support creating the base + if (get_request('create_base')) { + if (get_request('rdn')) { + $rdn = explode('=',get_request('rdn')); + echo '
'; + printf('',$rdn[0],$rdn[1]); + printf('',$rdn[0]); + echo '
'; + } + } + + echo '
'; + + # Javascript + $this->drawJavascript(); + + # For debugging, show the template object. + if (! $_SESSION[APPCONFIG]->getValue('appearance','hide_debug_info') && get_request('debug','GET')) { + echo "\n\n"; + printf('Plus',IMGDIR); + echo ''; + } + } + + public function drawFormSubmitButton() { + if (DEBUGTMP) printf('%s
',__METHOD__); + + if (! $this->template->isReadOnly()) + // @todo cant use AJAX here, it affects file uploads. + printf('', + _('Update Object')); + } + + /** STEP FORM METHODS **/ + + private function drawStepTitle($page) { + if (DEBUGTMP) printf('%s
',__METHOD__); + if (DEBUGTMP||DEBUGTMPSUB) printf('* %s [templateNAME:%s]
',__METHOD__,$this->template->getName()); + + # The default template needs to ask the user for objectClasses. + if ($this->template->isType('default')) { + # The default template only uses 2 pages + $this->pagelast = 2; + + echo '

'; + printf('%s: ',sprintf(_('Step %s of %s'),$page,$this->pagelast)); + + if ($page == 1) + echo _('Container and ObjectClass(es)'); + else + echo _('Specify attributes and values'); + + echo '

'; + + } elseif ($this->template->getDescription()) + printf('

%s (%s)

', + _($this->template->getDescription()), + sprintf(_('Step %s of %s'),$page,$this->pagelast)); + } + + private function drawStepFormStart($page) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + if (($this->template->isType('default') && $this->template->getContext() == 'create' && $page == 1) || $page < $this->pagelast) { + echo '
'; + echo '
'; + + } else { + echo ''; + echo '
'; + + if ($_SESSION[APPCONFIG]->getValue('confirm','create') && ! get_request('create_base')) + echo ''; + else + echo ''; + } + } + + protected function drawStepForm($page) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + printf('',$this->getServerID()); + printf('',$this->template->getID()); + printf('',$page+1); + if (get_request('create_base')) + echo ''; + + $this->drawHiddenAttributes(); + + if ($this->template->isType('default') && $page == 1) { + echo '
'; + + echo ''; + + $this->drawContainerChooser($this->template->getContainer()); + $this->drawObjectClassChooser(); + + } else { + printf('',$this->template->getContainerEncode(false)); + echo ''; + + echo '
'; + + $this->drawRDNChooser(); + + if ($this->template->isType('default') && $this->template->getContext() == 'create') + $this->drawStepFormDefaultAttributes(); + else + $this->drawShownAttributes(); + } + + $this->drawStepFormSubmitButton($page); + + echo '
'; + } + + private function drawStepFormEnd() { + if (DEBUGTMP) printf('%s
',__METHOD__); + + $this->drawFormEnd(); + } + + private function drawStepFormSubmitButton($page) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + echo ''; + if ($page < $this->pagelast) + printf(' ',_('Proceed >>')); + else + // @todo cant use AJAX here, it affects file uploads. + printf('', + _('Create Object')); + echo ''; + } + + /** + * Given our known objectClass in the template, this will render the required MAY and optional MUST attributes + */ + private function drawStepFormDefaultAttributes() { + if (DEBUGTMP) printf('%s
',__METHOD__); + + # Put required attributes first + $attrs = array(); + $attrs['required'] = array(); + $attrs['optional'] = array(); + foreach ($this->template->getAttributes(true) as $attribute) { + # Skip the objectclass attribute, we already know it in a default creation form. + if ($attribute->getName() == 'objectclass') + continue; + + if ($attribute->isRequired()) + array_push($attrs['required'],$attribute); + + elseif (! $attribute->getValues()) + array_push($attrs['optional'],$attribute); + } + + printf('%s',_('Required Attributes')); + if (count($attrs['required'])) + foreach ($attrs['required'] as $attribute) + $this->draw('Template',$attribute); + + else + printf('(%s)',_('none')); + + printf('%s',_('Optional Attributes')); + if (count($attrs['optional'])) + foreach ($attrs['optional'] as $attribute) + $this->draw('Template',$attribute); + + else + printf('(%s)',_('none')); + + echo "\n"; + } + + /** DRAW ATTRIBUTES **/ + + private function drawShownAttributes() { + if (DEBUGTMP) printf('%s
',__METHOD__); + + foreach ($this->template->getAttributesShown() as $attribute) + if (($attribute->getPage() == $this->page) && ($attribute->isRequired() || $attribute->isMay())) { + $this->draw('Template',$attribute); + echo "\n"; + } + } + + /** DRAW PAGE JAVACRIPT */ + + protected function drawJavascript() { + if (DEBUGTMP) printf('%s
',__METHOD__); + + echo "\n"; + printf('',__METHOD__); + echo "\n"; + + printf('',JSDIR); + printf('',JSDIR); + printf('',JSDIR); + echo "\n"; + + printf('',__METHOD__); + echo ' +'; + echo "\n"; + printf('',__METHOD__); + echo "\n"; + + $this->drawTemplateJavascript(); + + # For DateAttributes, we need to set some defaults for the js_calendar. + echo ''."\n"; + echo ''."\n"; + echo ''."\n"; + echo "\n"; + + foreach ($this->template->getAttributesShown() as $attribute) + $this->draw('Javascript',$attribute); + + // @todo We need to sleep here a little bit, because our JS may not have loaded yet. + echo ''."\n"; + printf('',__METHOD__); + echo "\n"; + } + + /** + * Javascript Functions + */ + private function drawTemplateJavascript() { + printf('',__METHOD__); + echo "\n"; + foreach ($this->template->getAttributes(true) as $attribute) + if ($onchange = $attribute->getOnChange()) + if (is_array($onchange)) + foreach ($onchange as $value) + $this->template->OnChangeAdd($attribute->getName(),$value); + else + $this->template->OnChangeAdd($attribute->getName(),$onchange); + printf('',__METHOD__); + echo "\n"; + + printf('',__METHOD__); + + echo ' +'; + echo "\n"; + printf('',__METHOD__); + echo "\n"; + } + + /** ATTRIBUTE TITLE **/ + + protected function drawTitleAttribute($attribute) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + if (($this->template->getContext() == 'edit') + && ($attribute->hasBeenModified() || in_array($attribute->getName(),get_request('modified_attrs','REQUEST',false,array())))) + echo ''; + else + echo ''; + + echo ''; + $this->draw('Name',$attribute); + echo ''; + + echo ''; + + # Setup the $attr_note, which will be displayed to the right of the attr name (if any) + if ($_SESSION[APPCONFIG]->getValue('appearance','show_attribute_notes')) + $this->draw('Notes',$attribute); + + echo ''; + echo ''; + } + + /** ATTRIBUTE LINE **/ + + protected function drawStartValueLineAttribute($attribute) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + if (($this->template->getContext() == 'edit') + && ($attribute->hasBeenModified() || in_array($attribute->getName(),get_request('modified_attrs','REQUEST',false,array())))) + echo ''; + else + echo ''; + + echo ''; + } + + protected function drawEndValueLineAttribute($attribute) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + echo ''; + echo ''; + + if ($attribute->getSpacer()) + echo ' '; + + if (($this->template->getContext() == 'edit') + && ($attribute->hasBeenModified() || in_array($attribute->getName(),get_request('modified_attrs','REQUEST',false,array())))) + echo ''; + } + + protected function drawTemplateAttribute($attribute) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + $this->draw('Title',$attribute); + $this->draw('TemplateValues',$attribute); + } + + protected function drawTemplateValuesAttribute($attribute) { + if (DEBUGTMP) printf('%s:%s
',time(),__METHOD__); + + $this->draw('StartValueLine',$attribute); + + # Draws values + $value_count = $attribute->getValueCount(); + for ($i=0;$i<$value_count;$i++) + $this->draw('Value',$attribute,$i); + + if (! $attribute->isInternal()) { + $blankvalue_count = $attribute->getMaxValueCount(); + if ($blankvalue_count < 0) + $blankvalue_count = 1; + + $blankvalue_count -= $value_count; + + for ($j=0;$j<$blankvalue_count;$j++) + $this->draw('Value',$attribute,$i+$j); + + if (($value_count == $blankvalue_count) || ($value_count && $blankvalue_count < 1)) + $this->draw('Menu',$attribute); + } + + $this->draw('EndValueLine',$attribute); + echo "\n"; + } + + /** DRAW ICONS FOR ATTRIBUTES VALUES **/ + + protected function drawIconAttribute($attribute,$val) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + if (is_dn_string($val) || $this->getServer()->isDNAttr($attribute->getName())) + $this->draw('DnValueIcon',$attribute,$val); + elseif (is_mail_string($val)) + $this->draw('MailValueIcon',$attribute,$val); + elseif (is_url_string($val)) + $this->draw('UrlValueIcon',$attribute,$val); + + else { + if ($icon = $attribute->getIcon()) + printf('Icon ',$icon); + } + } + + protected function drawDnValueIconAttribute($attribute,$val) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + if (strlen($val) <= 0) + printf('Go ',IMGDIR); + elseif ($this->getServer()->dnExists($val)) + printf('Go ', + $this->getServerID(),rawurlencode($val),_('Go to'),$val,IMGDIR); + else + printf('Go ',_('DN not available'),$val,IMGDIR); + } + + protected function drawMailValueIconAttribute($attribute,$val) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + $img = sprintf('%s',IMGDIR,_('Mail')); + if (strlen($val) <= 0) + echo $img; + else + printf('%s',htmlspecialchars($val),$img); + echo ' '; + } + + protected function drawUrlValueIconAttribute($attribute,$val) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + $img = sprintf('%s',IMGDIR,_('URL')); + $url = explode(' +',$val,2); + + if (strlen($val) <= 0) + echo $img; + else + printf('%s',htmlspecialchars($url[0]),$img); + echo ' '; + } + + /** DEFAULT ATTRIBUTE RENDERING **/ + + /** javacript */ + + protected function drawJavascriptAttribute($attribute) { + if (! $attribute->needJS()) { + printf('',$attribute->getName()); + echo "\n"; + return; + } + + printf('',__METHOD__,$attribute->getName()); + echo "\n"; + + echo ''."\n"; + + printf('',__METHOD__,$attribute->getName()); + echo "\n"; + } + + protected function getFocusJavascriptAttribute($attribute,$component) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + return ''; + } + + protected function getBlurJavascriptAttribute($attribute,$component) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + $j = "\t".'fill('.$component.'.id,pla_getComponentValue('.$component.'));'."\n"; + $j .= "\t".'validate_'.$attribute->getName().'('.$component.',false);'."\n"; + + return $j; + } + + protected function drawFocusJavascriptAttribute($attribute,$component) { + echo $this->get('FocusJavascript',$attribute,$component); + } + + protected function drawBlurJavascriptAttribute($attribute,$component) { + echo $this->get('BlurJavascript',$attribute,$component); + } + + protected function drawFillJavascriptAttribute($attribute,$component_id,$component_value) { + if ($attribute->needJS('validate')) + printf("\tvalidate_%s(pla_getComponentById(%s),true);\n",$attribute->getName(),$component_id); + } + + protected function drawValidateJavascriptAttribute($attribute,$component,$silence,$var_valid) { + printf('var vals = getAttributeValues("new","%s");',$attribute->getName()); + echo 'if (vals.length <= 0) {'; + printf('%s = false;',$var_valid); + printf('alertError("%s: %s",%s);',_('This attribute is required'),$attribute->getFriendlyName(),$silence); + echo '}'; + echo "\n"; + + printf('var comp = getAttributeComponents("new","%s");',$attribute->getName()); + echo 'for (var i = 0; i < comp.length; i++) {'; + printf('comp[i].style.backgroundColor = "%s";',$var_valid ? 'white' : '#FFFFA0'); + echo '}'; + } + + /** ATTRIBUTE MENU **/ + + protected function drawMenuAttribute($attribute) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + $result = ''; + $item = ''; + + foreach (array('add','modify','rename') as $action) + if ($item = $this->get('MenuItem',$attribute,$action)) + $result .= sprintf('
%s
',$item); + + if (! $result) + return; + + echo ''; + printf('',$result); + echo ''; + echo '
 %s
'; + } + + protected function getMenuItemAttribute($attribute,$action) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + # If there is no DN, then this is a creating entry. + if (($this->template->getContext() == 'create') || $this->template->isReadOnly()) + return false; + + switch ($action) { + case 'add': + if ($attribute->isVisible() && ! $attribute->isReadOnly() + && $_SESSION[APPCONFIG]->isCommandAvailable('script','add_value_form')) { + + if ($attribute->haveMoreValues()) + return $this->get('AddValueMenuItem',$attribute); + } + + return ''; + + case 'modify': + if (in_array($attribute->getName(),arrayLower($_SESSION[APPCONFIG]->getValue('modify_member','groupattr')))) { + if ($attribute->isVisible() && ! $attribute->isReadOnly() && ! $attribute->isRDN() + && $_SESSION[APPCONFIG]->isCommandAvailable('script','modify_member_form')) + return $this->get('ModifyMemberMenuItem',$attribute); + } + + return ''; + + case 'rename': + if ($attribute->isVisible() && $attribute->isRDN() && ! $attribute->isReadOnly() + && $_SESSION[APPCONFIG]->isCommandAvailable('script','rename_form') + && $_SESSION[APPCONFIG]->isCommandAvailable('script','rename')) + return $this->get('RenameMenuItem',$attribute); + + return ''; + + default: + return false; + } + } + + protected function getAddValueMenuItemAttribute($attribute) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + $href_parm = htmlspecialchars(sprintf('cmd=add_value_form&server_id=%s&dn=%s&attr=%s', + $this->getServerID(),$this->template->getDNEncode(),rawurlencode($attribute->getName(false)))); + + if (isAjaxEnabled()) + return sprintf('(%s)', + $href_parm,_('Add an additional value to attribute'),$attribute->getName(false),$attribute->getName(), + $href_parm,str_replace('\'','\\\'',_('Add Value to Attribute')),_('add value')); + else + return sprintf('(%s)', + $href_parm,_('Add an additional value to attribute'),$attribute->getName(false),_('add value')); + } + + protected function getAddValueMenuItemObjectClassAttribute($attribute) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + $href_parm = htmlspecialchars(sprintf('cmd=add_value_form&server_id=%s&dn=%s&attr=%s', + $this->getServerID(),$this->template->getDNEncode(),rawurlencode($attribute->getName(false)))); + + if (isAjaxEnabled()) + return sprintf('(%s)', + $href_parm,_('Add an additional value to attribute'),$attribute->getName(false), + $href_parm,str_replace('\'','\\\'',_('Add Value to Attribute')),_('add value')); + else + return sprintf('(%s)', + $href_parm,_('Add an additional value to attribute'),$attribute->getName(false),_('add value')); + } + + protected function getModifyMemberMenuItemAttribute($attribute) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + $href = sprintf('cmd=modify_member_form&server_id=%s&dn=%s&attr=%s', + $this->getServerID(),$this->template->getDNEncode(),rawurlencode($attribute->getName())); + + if (isAjaxEnabled()) + return sprintf('(%s)', + htmlspecialchars($href),_('Modify members for'),$this->template->getDN(), + htmlspecialchars($href),str_replace('\'','\\\'',_('Modify group membership')), + _('modify group members')); + else + return sprintf('(%s)', + htmlspecialchars($href),_('Modify members for'),$this->template->getDN(),_('modify group members')); + } + + protected function getRenameMenuItemAttribute($attribute) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + $href = sprintf('cmd.php?cmd=rename_form&server_id=%s&dn=%s&template=%s', + $this->getServerID(),$this->template->getDNEncode(),$this->template->getID()); + + return sprintf('(%s)',htmlspecialchars($href),_('rename')); + } + + /** values **/ + + protected function drawValueAttribute($attribute,$i) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + if ($attribute->isMultiple() && $i > 0) + return; + + $val = $attribute->getValue($i); + + if ($attribute->isVisible()) { + echo ''; + + echo ''; + + echo '
'; + $this->draw('Icon',$attribute,$val); + echo ''; + } + + if ($attribute->isInternal()) + $this->draw('FormReadOnlyValue',$attribute,$i); + else + $this->draw('FormValue',$attribute,$i); + + if ($attribute->isVisible()) { + echo ''; + $this->draw('RequiredSymbol',$attribute); + echo '
'; + } + echo "\n"; + } + + # @todo for userPasswords, we need to capture the default value of select lists, without specifying + protected function drawHelperAttribute($attribute,$i) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + $params = $attribute->getHelper(); + + # We take the first only + $id = isset($params['id']) ? $params['id'] : ''; + if (is_array($id)) { + system_message(array( + 'title'=>_('Too many arguments'), + 'body'=>sprintf('%s (%s)',_('Helper attribute has too many ID values, only the first one is used'),count($id)), + 'type'=>'warn')); + + $id = $id[0]; + } + + # We take the first only + $display = isset($params['display']) ? $params['display'] : ''; + if (is_array($display)) { + system_message(array( + 'title'=>_('Too many arguments'), + 'body'=>sprintf('%s (%s)',_('Helper attribute has too many DISPLAY values, only the first one is used'),count($display)), + 'type'=>'warn')); + + $display = $display[0]; + } + + # We take the first only + $default = isset($params['default']) ? $params['default'] : ''; + if (is_array($default)) { + system_message(array( + 'title'=>_('Too many arguments'), + 'body'=>sprintf('%s (%s)',_('Helper attribute has too many DISPLAY values, only the first one is used'),count($default)), + 'type'=>'warn')); + + $default = $default[0]; + } + + if ($attribute->getHelperValue()) + $vals = $this->get('Default',$attribute, + $this->template->getContainer() ? $this->template->getContainer() : $this->getServer()->getContainerPath($this->template->getDN()), + 'helpervalue'); + else + $vals = isset($params['value']) ? $params['value'] : ''; + + if ($this->template->getContext() == 'create') + $dn = $this->template->getContainer(); + else + $dn = $this->template->getDN(); + + if (is_array($vals) && count($vals) > 0) { + $found = false; + + printf(''; + + } else { + # Vals must be an empty array. + if (is_array($vals)) + $vals = ''; + + printf('', + $id,htmlspecialchars($attribute->getName()),$i, + $id,htmlspecialchars($attribute->getName()),$i, + htmlspecialchars($vals)); + } + + if ($display) { + echo '
'; + printf('%s',$display); + echo '
'; + } + } + + protected function drawRequiredSymbolAttribute($attribute) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + if ($attribute->isRequired() && ! $attribute->isReadOnly()) + echo '*'; + } + + /** BINARY ATTRIBUTE RENDERING **/ + + #@todo do we need a $this->drawJavascriptAttribute($attribute) here too ? + protected function drawJavascriptBinaryAttribute($attribute) { + # If there are no values, then this javascript doesnt need to be drawn. + if (! $attribute->getValues()) + return; + + static $drawn = false; + + # This JS may have been rendered by multiple Binary attributes + if ($drawn) + return; + else + $drawn = true; + + printf('',__METHOD__,$attribute->getName()); + echo "\n"; + + echo ''; + echo ''; + printf('',$this->getServerID()); + printf('',$this->template->getDNEncode(false)); + printf('',$this->template->getID()); + echo ''; + echo ''; + echo ''; + + echo ' +'; + echo "\n"; + + printf('',__METHOD__,$attribute->getName()); + echo "\n"; + } + + /** DATE ATTRIBUTE RENDERING **/ + + protected function drawJavaScriptDateAttribute($attribute) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + printf('',__METHOD__,$attribute->getName()); + echo "\n"; + + $this->drawJavaScriptAttribute($attribute); + + static $drawn = false; + + # This JS may have been rendered by multiple Date attributes + if (! $drawn) { + printf('',JSDIR); + printf('',JSDIR); + printf('',JSDIR); + + $drawn = true; + } + + $config = array(); + $config['date'] = array_change_key_case($_SESSION[APPCONFIG]->getValue('appearance','date_attrs')); + $config['time'] = array_change_key_case($_SESSION[APPCONFIG]->getValue('appearance','date_attrs_showtime')); + $config['format'] = $_SESSION[APPCONFIG]->getValue('appearance','date'); + + if (isset($config['date'][$attribute->getName()])) + $config['format'] = $config['date'][$attribute->getName()]; + + for ($i=0;$i<=$attribute->getValueCount();$i++) { + printf('',$attribute->getName(),$i,$config['format']); + + if (in_array_ignore_case($attribute->getName(),array_keys($config['time'])) && ($config['time'][$attribute->getName()])) + printf('',$attribute->getName(),$i,'true'); + + echo "\n"; + } + + printf('',__METHOD__,$attribute->getName()); + echo "\n"; + } + + /** + * Draws an HTML date selector button which, when clicked, pops up a date selector dialog. + */ + protected function drawSelectorPopupDateAttribute($attribute,$i) { + printf('Calendar', + $attribute->getName(),$i,_('Click to popup a dialog to select a date graphically'),IMGDIR,$attribute->getName(),$i); + } + + /** DN ATTRIBUTES **/ + + protected function drawIconDnAttribute($attribute,$val) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + $this->draw('DnValueIcon',$attribute,$val); + } + + /** OBJECT CLASS ATTRIBUTE **/ + + protected function drawIconObjectClassAttribute($attribute,$val) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + if (! $_SESSION[APPCONFIG]->getValue('appearance','show_schema_link') || !$_SESSION[APPCONFIG]->isCommandAvailable('script','schema')) + return; + + if (strlen($val) > 0) { + $href = sprintf('cmd.php?cmd=schema&server_id=%s&view=objectclasses&viewvalue=%s', + $this->getServerID(),$val); + printf('Info ', + htmlspecialchars($href),_('View the schema description for this objectClass'),IMGDIR); + } + } + + /** PASSWORD ATTRIBUTES **/ + + protected function drawJavascriptPasswordAttribute($attribute) { + static $drawn = array(); + + # This JS may have been rendered by multiple Binary attributes + if (isset($drawn[$attribute->getName()]) && $drawn[$attribute->getName()]) + return; + else + $drawn[$attribute->getName()] = true; + + printf('',__METHOD__,$attribute->getName()); + echo "\n"; + + $this->drawJavascriptAttribute($attribute); + + # Add the javascript so we can call check password later. + echo ' +'; + echo "\n"; + + printf('',__METHOD__,$attribute->getName()); + echo "\n"; + } + + protected function drawCheckLinkPasswordAttribute($attribute,$component_id) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + printf('%s...
', + $component_id,$attribute->getName(),_('Check password')); + } + + /** RANDOM PASSWORD **/ + + /** + * This will draw the javascript that displays to the user the random password generated + * + * @todo This function doesnt work well if there are more than 1 RandomPasswordAttributes on the form for the same attribute (unlikely situation) + */ + protected function drawJavascriptRandomPasswordAttribute($attribute) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + printf("\n\n",__METHOD__); + $this->drawJavascriptPasswordAttribute($attribute); + + $pwd = password_generate(); + $pwd = str_replace("\\","\\\\",$pwd); + $pwd = str_replace("'","\\'",$pwd); + + printf("\n\n",__METHOD__); + echo ''; + printf("\n\n",__METHOD__); + } + + protected function drawDefaultHelperPasswordAttribute($attribute,$i) { + $id = 'enc'; + + if ($val = $attribute->getValue($i)) + $default = get_enc_type($val); + else + $default = $this->getServer()->getValue('appearance','password_hash'); + + if (! $attribute->getPostValue()) + printf('',$attribute->getName(),$i); + + printf(''; + } + + protected function drawDefaultHelperSambaPasswordAttribute($attribute,$i) { + $id = 'enc'; + + if (! $attribute->getPostValue()) + printf('',$attribute->getName(),$i); + + switch ($attribute->getName()) { + case 'sambalmpassword' : $enc = 'lm'; break; + case 'sambantpassword' : $enc = 'nt'; break; + + default: + return ''; + } + + printf('', + $id,htmlspecialchars($attribute->getName()),$i, + $id,htmlspecialchars($attribute->getName()),$i,$enc); + } + + /** SELECTION ATTRIBUTE RENDERING **/ + + protected function drawIconSelectionAttribute($attribute,$val) { + if (DEBUGTMP) printf('%s
',__METHOD__); + + if (! $attribute->isMultiple() || $attribute->isReadOnly()) + $this->drawIconAttribute($attribute,$val); + } + + protected function getMenuItemSelectionAttribute($attribute,$i) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (DEBUGTMP) printf('%s
',__METHOD__); + + switch ($i) { + case 'add': + if (! $attribute->isMultiple()) + return $this->getMenuItemAttribute($attribute,$i); + else + return ''; + + case 'modify': + return ''; + + default: + return $this->getMenuItemAttribute($attribute,$i); + } + } +} +?> diff --git a/lib/Tree.php b/lib/Tree.php new file mode 100644 index 0000000..e7542fc --- /dev/null +++ b/lib/Tree.php @@ -0,0 +1,351 @@ +server_id = $server_id; + } + + /** + * Create an instance of the tree - this is used when we call this class directly + * Tree::getInstance($index) + * + * @return object Tree + */ + static public function getInstance($server_id) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $tree = get_cached_item($server_id,'tree'); + + if (! $tree) { + $server = $_SESSION[APPCONFIG]->getServer($server_id); + + if (! $server) + return null; + + $treeclass = $_SESSION[APPCONFIG]->getValue('appearance','tree'); + $tree = new $treeclass($server_id); + + # If we are not logged in, just return the empty tree. + if (is_null($server->getLogin(null))) + return $tree; + + foreach ($server->getBaseDN(null) as $base) { + if ($base) { + $tree->addEntry($base); + + if ($server->getValue('appearance','open_tree')) { + $baseEntry = $tree->getEntry($base); + $baseEntry->open(); + } + } + } + + set_cached_item($server_id,'tree','null',$tree); + } + + return $tree; + } + + /** + * Get the Server ID for this tree + * + * @return int Server ID that this tree is for + */ + protected function getServerID() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->server_id); + + return $this->server_id; + } + + /** + * Get the server Object for this tree + * + * @return object Server Object for this tree + */ + protected function getServer() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + return $_SESSION[APPCONFIG]->getServer($this->server_id); + } + + /** + * Get the entries that are BaseDN entries. + * + * @return array Base DN entries + */ + public function getBaseEntries() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $return = array(); + + foreach ($this->entries as $details) + if ($details->isBaseDN() AND ((! $this->getServer()->getValue('server','hide_noaccess_base')) OR $details->isInLdap())) + array_push($return,$details); + + return $return; + } + + /** + * This function will take the DN, convert it to lowercase and strip unnessary + * commas. This result will be used as the index for the tree object. + * Any display of a DN should use the object->dn entry, not the index. + * The reason we need to do this is because: + * uid=User A,ou=People,c=AU and + * uid=User B, ou=PeOpLe, c=au + * are infact in the same branch, but PLA will show them inconsistently. + * + * @param dn DN to clean + * @return dn Lowercase clean DN + */ + private function indexDN($dn) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $index = strtolower(implode(',',pla_explode_dn($dn))); + + if (DEBUG_ENABLED) + debug_log('Result (%s)',1,0,__FILE__,__LINE__,__METHOD__,$index); + + return $index; + } + + /** + * Get a tree entry + * + * @param dn DN to retrieve + * @return object Tree DN object + */ + public function getEntry($dn) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $dnlower = $this->indexDN($dn); + + if (isset($this->entries[$dnlower])) + return $this->entries[$dnlower]; + else + return null; + } + + /** + * Add an entry in the tree view ; the entry is added in the + * children array of its parent + * + * @param dn DN to add + * @param string $dn the dn of the entry to create + */ + public function addEntry($dn) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $server = $this->getServer(); + $dnlower = $this->indexDN($dn); + + # @todo Temporarily removed, some non-ascii char DNs that do exist, fail here for some reason? + #if (! ($server->dnExists($dn))) + # return; + + if (isset($this->entries[$dnlower])) + debug_dump_backtrace('Calling add entry to an entry that ALREADY exists?',1); + + if (DEBUG_ENABLED) + debug_log('New ENTRY (%s).',64,0,__FILE__,__LINE__,__METHOD__,$dn); + + $tree_factory = new TreeItem($server->getIndex(),$dn); + $tree_factory->setObjectClasses($server->getDNAttrValue($dn,'objectClass')); + + if ((($isleaf = $server->getDNAttrValue($dn,'hassubordinates')) && ! strcasecmp($isleaf[0],'false'))) + $tree_factory->setLeaf(); + + $this->entries[$dnlower] = $tree_factory; + + # Is this entry in a base entry? + if (in_array_ignore_case($dn,$server->getBaseDN(null))) { + $this->entries[$dnlower]->setBase(); + + # If the parent entry is not in the tree, we add it. This routine will in itself + # recall this method until we get to the top of the tree (the base). + } else { + $parent_dn = $server->getContainer($dn); + + if (DEBUG_ENABLED) + debug_log('Parent DNs (%s)',64,0,__FILE__,__LINE__,__METHOD__,$parent_dn); + + if ($parent_dn) { + $parent_entry = $this->getEntry($parent_dn); + + if (! $parent_entry) { + $this->addEntry($parent_dn); + $parent_entry = $this->getEntry($parent_dn); + } + + # Update this DN's parent's children list as well. + $parent_entry->addChild($dn); + } + } + } + + /** + * Delete an entry from the tree view ; the entry is deleted from the + * children array of its parent + * + * @param dn DN to remote + */ + public function delEntry($dn) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $server = $this->getServer(); + $dnlower = $this->indexDN($dn); + + if (isset($this->entries[$dnlower])) + unset($this->entries[$dnlower]); + + # Delete entry from parent's children as well. + $parent_dn = $server->getContainer($dn); + $parent_entry = $this->getEntry($parent_dn); + + if ($parent_entry) + $parent_entry->delChild($dn); + } + + /** + * Rename an entry in the tree + * + * @param dn Old DN + * @param dn New DN + */ + public function renameEntry($dnOLD,$dnNEW) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $server = $this->getServer(); + $dnlowerOLD = $this->indexDN($dnOLD); + $dnlowerNEW = $this->indexDN($dnNEW); + + $this->entries[$dnlowerNEW] = $this->entries[$dnlowerOLD]; + if ($dnlowerOLD != $dnlowerNEW) + unset($this->entries[$dnlowerOLD]); + $this->entries[$dnlowerNEW]->rename($dnNEW); + + # Update the parent's children + $parentNEW = $server->getContainer($dnNEW); + $parentOLD = $server->getContainer($dnOLD); + + $parent_entry = $this->getEntry($parentNEW); + if ($parent_entry) + $parent_entry->addChild($dnNEW); + + $parent_entry = $this->getEntry($parentOLD); + if ($parent_entry) + $parent_entry->delChild($dnOLD); + } + + /** + * Read the children of a tree entry + * + * @param dn DN of the entry + * @param boolean LDAP Size Limit + */ + public function readChildren($dn,$nolimit=false) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $server = $this->getServer(); + $dnlower = $this->indexDN($dn); + + if (! isset($this->entries[$dnlower])) + debug_dump_backtrace('Reading children on an entry that isnt set? '.$dnlower,true); + + $ldap['child_limit'] = $nolimit ? 0 : $_SESSION[APPCONFIG]->getValue('search','size_limit'); + $ldap['filter'] = $_SESSION[APPCONFIG]->getValue('appearance','tree_filter'); + $ldap['deref'] = $_SESSION[APPCONFIG]->getValue('deref','tree'); + + # Perform the query to get the children. + $ldap['children'] = $server->getContainerContents($dn,null,$ldap['child_limit'],$ldap['filter'],$ldap['deref']); + + if (! count($ldap['children'])) { + $this->entries[$dnlower]->unsetSizeLimited(); + + return; + } + + if (DEBUG_ENABLED) + debug_log('Children of (%s) are (%s)',64,0,__FILE__,__LINE__,__METHOD__,$dn,$ldap['children']); + + # Relax our execution time, it might take some time to load this + if ($nolimit) + @set_time_limit($_SESSION[APPCONFIG]->getValue('search','time_limit')); + + $this->entries[$dnlower]->readingChildren(true); + + foreach ($ldap['children'] as $child) { + if (DEBUG_ENABLED) + debug_log('Adding (%s)',64,0,__FILE__,__LINE__,__METHOD__,$child); + + if (! in_array($child,$this->entries[$dnlower]->getChildren())) + $this->entries[$dnlower]->addChild($child); + } + + $this->entries[$dnlower]->readingChildren(false); + + if (count($this->entries[$dnlower]->getChildren()) == $ldap['child_limit']) + $this->entries[$dnlower]->setSizeLimited(); + else + $this->entries[$dnlower]->unsetSizeLimited(); + } + + /** + * Return the number of children an entry has. Optionally autoread the child entry. + * + * @param dn DN of the entry + * @param boolean LDAP Size Limit + */ + protected function readChildrenNumber($dn,$nolimit=false) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $dnlower = $this->indexDN($dn); + + if (! isset($this->entries[$dnlower])) + debug_dump_backtrace('Reading children on an entry that isnt set?',true); + + # Read the entry if we havent got it yet. + if (! $this->entries[$dnlower]->isLeaf() && ! $this->entries[$dnlower]->getChildren()) + $this->readChildren($dn,$nolimit); + + return count($this->entries[$dnlower]->getChildren()); + } +} +?> diff --git a/lib/TreeItem.php b/lib/TreeItem.php new file mode 100644 index 0000000..8c95ad8 --- /dev/null +++ b/lib/TreeItem.php @@ -0,0 +1,312 @@ +server_id = $server_id; + $this->dn = $dn; + } + + /** + * Get the DN of this tree item. + * + * @return DN The DN of this item. + */ + public function getDN() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->dn); + + return $this->dn; + } + + public function getDNEncode() { + return urlencode(preg_replace('/%([0-9a-fA-F]+)/',"%25\\1",$this->dn)); + } + + /** + * Get the RDN of this tree items DN. + * + * @return RDN The RDN of this items DN. + */ + public function getRDN() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + return get_rdn($this->getDn(),0,true); + } + + /** + * Set this item as a LDAP base DN item. + */ + public function setBase() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->base_entry = true; + } + + /** + * Return if this item is a base DN item. + */ + public function isBaseDN() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->base_entry); + + return $this->base_entry; + } + + public function setObjectClasses($oc) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->objectclasses = $oc; + } + + public function getObjectClasses() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->objectclasses); + + return $this->objectclasses; + } + + public function isInLDAP() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + return count($this->objectclasses) ? true : false; + } + + /** + * Returns null if the children have never be defined + * or an array of the dn of the children + */ + public function getChildren() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->children); + + if ($this->childsort && ! $this->reading_children) { + usort($this->children,'pla_compare_dns'); + $this->childsort = false; + } + + return $this->children; + } + + public function readingChildren($bool) { + $this->reading_children = $bool; + } + + /** + * Do the children require resorting + */ + public function isChildSorted() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->childsort); + + return $this->childsort; + } + + /** + * Mark the children as sorted + */ + public function childSorted() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->childsort = false; + } + + /** + * Add a child to this DN entry. + * + * @param DN The DN to add. + */ + public function addChild($dn) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (in_array($dn,$this->children)) + return; + + array_push($this->children,$dn); + $this->childsort = true; + } + + /** + * Delete a child from this DN entry. + * + * @param DN The DN to add. + */ + public function delChild($dn) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if ($this->children) { + # If the parent hasnt been opened in the tree, then there wont be any children. + $index = array_search($dn,$this->children); + + if ($index !== false) + unset($this->children[$index]); + } + } + + /** + * Rename this DN. + * + * @param DN The DN to rename to. + */ + public function rename($dn) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->dn = $dn; + } + + /** + * Return if this item has been opened. + */ + public function isOpened() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->open); + + return $this->open; + } + + /** + * Mark this node as closed. + */ + public function close() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->open = false; + } + + /** + * Opens the node ; the children of the node must have been defined + */ + public function open() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->open = true; + } + + /** + * Mark this node as a leaf. + */ + public function setLeaf() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->leaf = true; + } + + /** + * Return if this node is a leaf. + */ + public function isLeaf() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->leaf); + + return $this->leaf; + } + + /** + * Returns the path of the icon file used to represent this node ; + * If the icon hasnt been set, it will call get_icon() + */ + public function getIcon() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->icon); + + if (! $this->icon) + $this->icon = get_icon($this->server_id,$this->dn,$this->objectclasses); + + return $this->icon; + } + + /** + * Mark this node as a size limited (it wont have all its children). + */ + public function setSizeLimited() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->size_limited = true; + } + + /** + * Clear the size limited flag. + */ + public function unsetSizeLimited() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->size_limited = false; + } + + /** + * Return if this node has hit an LDAP size limit (and thus doesnt have all its children). + */ + public function isSizeLimited() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + return $this->size_limited; + } + + public function setTemplate($template) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->template = $template; + } + + public function getTemplate() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',33,0,__FILE__,__LINE__,__METHOD__,$fargs); + + return $this->template; + } +} +?> diff --git a/lib/Visitor.php b/lib/Visitor.php new file mode 100644 index 0000000..fca5099 --- /dev/null +++ b/lib/Visitor.php @@ -0,0 +1,99 @@ +Class (%s): Method doesnt exist (%s,%s)
',$class,get_class($this),$call); + + $class = get_parent_class($class); + $call = "$method$fnct$class"; + array_push($methods,$call); + } + + if (defined('DEBUGTMP') && DEBUGTMP) + printf('Calling Methods: %s
',implode('|',$methods)); + + if (defined('DEBUGTMP') && DEBUGTMP && method_exists($this,$call)) + printf('Method Exists: %s::%s (%s)
',get_class($this),$call,$args); + + if (method_exists($this,$call)) { + $r = call_user_func_array(array($this,$call),$args); + + if (isset($r)) + return $r; + else + return; + + } elseif (DEBUG_ENABLED) { + debug_log('Doesnt exist param (%s,%s)',1,0,__FILE__,__LINE__,__METHOD__,$method,$fnct); + } + + printf('NO Methods: %s
',implode('|',$methods)); + } + + /** + * Return the LDAP server ID + * + * @return int Server ID + */ + public function getServerID() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->server_id); + + if (isset($this->server_id)) + return $this->server_id; + else + return null; + } + + /** + * Return this LDAP Server object + * + * @return object DataStore Server + */ + protected function getServer() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + return $_SESSION[APPCONFIG]->getServer($this->getServerID()); + } +} +?> diff --git a/lib/blowfish.php b/lib/blowfish.php new file mode 100644 index 0000000..1c69aa9 --- /dev/null +++ b/lib/blowfish.php @@ -0,0 +1,480 @@ + + * + * See the enclosed file COPYING for license information (LGPL). If you + * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html. + * + * @author Mike Cochrane + * @version $Revision$ + * @since Horde 2.2 + * @package horde.cipher + */ +/** + * @package horde.cipher + */ + +// Change for phpMyAdmin by lem9: +//class Horde_Cipher_blowfish extends Horde_Cipher { +class Horde_Cipher_blowfish { + + /* Pi Array */ + public $p = array( + 0x243F6A88, 0x85A308D3, 0x13198A2E, 0x03707344, + 0xA4093822, 0x299F31D0, 0x082EFA98, 0xEC4E6C89, + 0x452821E6, 0x38D01377, 0xBE5466CF, 0x34E90C6C, + 0xC0AC29B7, 0xC97C50DD, 0x3F84D5B5, 0xB5470917, + 0x9216D5D9, 0x8979FB1B); + + /* S Boxes */ + public $s1 = array( + 0xD1310BA6, 0x98DFB5AC, 0x2FFD72DB, 0xD01ADFB7, + 0xB8E1AFED, 0x6A267E96, 0xBA7C9045, 0xF12C7F99, + 0x24A19947, 0xB3916CF7, 0x0801F2E2, 0x858EFC16, + 0x636920D8, 0x71574E69, 0xA458FEA3, 0xF4933D7E, + 0x0D95748F, 0x728EB658, 0x718BCD58, 0x82154AEE, + 0x7B54A41D, 0xC25A59B5, 0x9C30D539, 0x2AF26013, + 0xC5D1B023, 0x286085F0, 0xCA417918, 0xB8DB38EF, + 0x8E79DCB0, 0x603A180E, 0x6C9E0E8B, 0xB01E8A3E, + 0xD71577C1, 0xBD314B27, 0x78AF2FDA, 0x55605C60, + 0xE65525F3, 0xAA55AB94, 0x57489862, 0x63E81440, + 0x55CA396A, 0x2AAB10B6, 0xB4CC5C34, 0x1141E8CE, + 0xA15486AF, 0x7C72E993, 0xB3EE1411, 0x636FBC2A, + 0x2BA9C55D, 0x741831F6, 0xCE5C3E16, 0x9B87931E, + 0xAFD6BA33, 0x6C24CF5C, 0x7A325381, 0x28958677, + 0x3B8F4898, 0x6B4BB9AF, 0xC4BFE81B, 0x66282193, + 0x61D809CC, 0xFB21A991, 0x487CAC60, 0x5DEC8032, + 0xEF845D5D, 0xE98575B1, 0xDC262302, 0xEB651B88, + 0x23893E81, 0xD396ACC5, 0x0F6D6FF3, 0x83F44239, + 0x2E0B4482, 0xA4842004, 0x69C8F04A, 0x9E1F9B5E, + 0x21C66842, 0xF6E96C9A, 0x670C9C61, 0xABD388F0, + 0x6A51A0D2, 0xD8542F68, 0x960FA728, 0xAB5133A3, + 0x6EEF0B6C, 0x137A3BE4, 0xBA3BF050, 0x7EFB2A98, + 0xA1F1651D, 0x39AF0176, 0x66CA593E, 0x82430E88, + 0x8CEE8619, 0x456F9FB4, 0x7D84A5C3, 0x3B8B5EBE, + 0xE06F75D8, 0x85C12073, 0x401A449F, 0x56C16AA6, + 0x4ED3AA62, 0x363F7706, 0x1BFEDF72, 0x429B023D, + 0x37D0D724, 0xD00A1248, 0xDB0FEAD3, 0x49F1C09B, + 0x075372C9, 0x80991B7B, 0x25D479D8, 0xF6E8DEF7, + 0xE3FE501A, 0xB6794C3B, 0x976CE0BD, 0x04C006BA, + 0xC1A94FB6, 0x409F60C4, 0x5E5C9EC2, 0x196A2463, + 0x68FB6FAF, 0x3E6C53B5, 0x1339B2EB, 0x3B52EC6F, + 0x6DFC511F, 0x9B30952C, 0xCC814544, 0xAF5EBD09, + 0xBEE3D004, 0xDE334AFD, 0x660F2807, 0x192E4BB3, + 0xC0CBA857, 0x45C8740F, 0xD20B5F39, 0xB9D3FBDB, + 0x5579C0BD, 0x1A60320A, 0xD6A100C6, 0x402C7279, + 0x679F25FE, 0xFB1FA3CC, 0x8EA5E9F8, 0xDB3222F8, + 0x3C7516DF, 0xFD616B15, 0x2F501EC8, 0xAD0552AB, + 0x323DB5FA, 0xFD238760, 0x53317B48, 0x3E00DF82, + 0x9E5C57BB, 0xCA6F8CA0, 0x1A87562E, 0xDF1769DB, + 0xD542A8F6, 0x287EFFC3, 0xAC6732C6, 0x8C4F5573, + 0x695B27B0, 0xBBCA58C8, 0xE1FFA35D, 0xB8F011A0, + 0x10FA3D98, 0xFD2183B8, 0x4AFCB56C, 0x2DD1D35B, + 0x9A53E479, 0xB6F84565, 0xD28E49BC, 0x4BFB9790, + 0xE1DDF2DA, 0xA4CB7E33, 0x62FB1341, 0xCEE4C6E8, + 0xEF20CADA, 0x36774C01, 0xD07E9EFE, 0x2BF11FB4, + 0x95DBDA4D, 0xAE909198, 0xEAAD8E71, 0x6B93D5A0, + 0xD08ED1D0, 0xAFC725E0, 0x8E3C5B2F, 0x8E7594B7, + 0x8FF6E2FB, 0xF2122B64, 0x8888B812, 0x900DF01C, + 0x4FAD5EA0, 0x688FC31C, 0xD1CFF191, 0xB3A8C1AD, + 0x2F2F2218, 0xBE0E1777, 0xEA752DFE, 0x8B021FA1, + 0xE5A0CC0F, 0xB56F74E8, 0x18ACF3D6, 0xCE89E299, + 0xB4A84FE0, 0xFD13E0B7, 0x7CC43B81, 0xD2ADA8D9, + 0x165FA266, 0x80957705, 0x93CC7314, 0x211A1477, + 0xE6AD2065, 0x77B5FA86, 0xC75442F5, 0xFB9D35CF, + 0xEBCDAF0C, 0x7B3E89A0, 0xD6411BD3, 0xAE1E7E49, + 0x00250E2D, 0x2071B35E, 0x226800BB, 0x57B8E0AF, + 0x2464369B, 0xF009B91E, 0x5563911D, 0x59DFA6AA, + 0x78C14389, 0xD95A537F, 0x207D5BA2, 0x02E5B9C5, + 0x83260376, 0x6295CFA9, 0x11C81968, 0x4E734A41, + 0xB3472DCA, 0x7B14A94A, 0x1B510052, 0x9A532915, + 0xD60F573F, 0xBC9BC6E4, 0x2B60A476, 0x81E67400, + 0x08BA6FB5, 0x571BE91F, 0xF296EC6B, 0x2A0DD915, + 0xB6636521, 0xE7B9F9B6, 0xFF34052E, 0xC5855664, + 0x53B02D5D, 0xA99F8FA1, 0x08BA4799, 0x6E85076A); + public $s2 = array( + 0x4B7A70E9, 0xB5B32944, 0xDB75092E, 0xC4192623, + 0xAD6EA6B0, 0x49A7DF7D, 0x9CEE60B8, 0x8FEDB266, + 0xECAA8C71, 0x699A17FF, 0x5664526C, 0xC2B19EE1, + 0x193602A5, 0x75094C29, 0xA0591340, 0xE4183A3E, + 0x3F54989A, 0x5B429D65, 0x6B8FE4D6, 0x99F73FD6, + 0xA1D29C07, 0xEFE830F5, 0x4D2D38E6, 0xF0255DC1, + 0x4CDD2086, 0x8470EB26, 0x6382E9C6, 0x021ECC5E, + 0x09686B3F, 0x3EBAEFC9, 0x3C971814, 0x6B6A70A1, + 0x687F3584, 0x52A0E286, 0xB79C5305, 0xAA500737, + 0x3E07841C, 0x7FDEAE5C, 0x8E7D44EC, 0x5716F2B8, + 0xB03ADA37, 0xF0500C0D, 0xF01C1F04, 0x0200B3FF, + 0xAE0CF51A, 0x3CB574B2, 0x25837A58, 0xDC0921BD, + 0xD19113F9, 0x7CA92FF6, 0x94324773, 0x22F54701, + 0x3AE5E581, 0x37C2DADC, 0xC8B57634, 0x9AF3DDA7, + 0xA9446146, 0x0FD0030E, 0xECC8C73E, 0xA4751E41, + 0xE238CD99, 0x3BEA0E2F, 0x3280BBA1, 0x183EB331, + 0x4E548B38, 0x4F6DB908, 0x6F420D03, 0xF60A04BF, + 0x2CB81290, 0x24977C79, 0x5679B072, 0xBCAF89AF, + 0xDE9A771F, 0xD9930810, 0xB38BAE12, 0xDCCF3F2E, + 0x5512721F, 0x2E6B7124, 0x501ADDE6, 0x9F84CD87, + 0x7A584718, 0x7408DA17, 0xBC9F9ABC, 0xE94B7D8C, + 0xEC7AEC3A, 0xDB851DFA, 0x63094366, 0xC464C3D2, + 0xEF1C1847, 0x3215D908, 0xDD433B37, 0x24C2BA16, + 0x12A14D43, 0x2A65C451, 0x50940002, 0x133AE4DD, + 0x71DFF89E, 0x10314E55, 0x81AC77D6, 0x5F11199B, + 0x043556F1, 0xD7A3C76B, 0x3C11183B, 0x5924A509, + 0xF28FE6ED, 0x97F1FBFA, 0x9EBABF2C, 0x1E153C6E, + 0x86E34570, 0xEAE96FB1, 0x860E5E0A, 0x5A3E2AB3, + 0x771FE71C, 0x4E3D06FA, 0x2965DCB9, 0x99E71D0F, + 0x803E89D6, 0x5266C825, 0x2E4CC978, 0x9C10B36A, + 0xC6150EBA, 0x94E2EA78, 0xA5FC3C53, 0x1E0A2DF4, + 0xF2F74EA7, 0x361D2B3D, 0x1939260F, 0x19C27960, + 0x5223A708, 0xF71312B6, 0xEBADFE6E, 0xEAC31F66, + 0xE3BC4595, 0xA67BC883, 0xB17F37D1, 0x018CFF28, + 0xC332DDEF, 0xBE6C5AA5, 0x65582185, 0x68AB9802, + 0xEECEA50F, 0xDB2F953B, 0x2AEF7DAD, 0x5B6E2F84, + 0x1521B628, 0x29076170, 0xECDD4775, 0x619F1510, + 0x13CCA830, 0xEB61BD96, 0x0334FE1E, 0xAA0363CF, + 0xB5735C90, 0x4C70A239, 0xD59E9E0B, 0xCBAADE14, + 0xEECC86BC, 0x60622CA7, 0x9CAB5CAB, 0xB2F3846E, + 0x648B1EAF, 0x19BDF0CA, 0xA02369B9, 0x655ABB50, + 0x40685A32, 0x3C2AB4B3, 0x319EE9D5, 0xC021B8F7, + 0x9B540B19, 0x875FA099, 0x95F7997E, 0x623D7DA8, + 0xF837889A, 0x97E32D77, 0x11ED935F, 0x16681281, + 0x0E358829, 0xC7E61FD6, 0x96DEDFA1, 0x7858BA99, + 0x57F584A5, 0x1B227263, 0x9B83C3FF, 0x1AC24696, + 0xCDB30AEB, 0x532E3054, 0x8FD948E4, 0x6DBC3128, + 0x58EBF2EF, 0x34C6FFEA, 0xFE28ED61, 0xEE7C3C73, + 0x5D4A14D9, 0xE864B7E3, 0x42105D14, 0x203E13E0, + 0x45EEE2B6, 0xA3AAABEA, 0xDB6C4F15, 0xFACB4FD0, + 0xC742F442, 0xEF6ABBB5, 0x654F3B1D, 0x41CD2105, + 0xD81E799E, 0x86854DC7, 0xE44B476A, 0x3D816250, + 0xCF62A1F2, 0x5B8D2646, 0xFC8883A0, 0xC1C7B6A3, + 0x7F1524C3, 0x69CB7492, 0x47848A0B, 0x5692B285, + 0x095BBF00, 0xAD19489D, 0x1462B174, 0x23820E00, + 0x58428D2A, 0x0C55F5EA, 0x1DADF43E, 0x233F7061, + 0x3372F092, 0x8D937E41, 0xD65FECF1, 0x6C223BDB, + 0x7CDE3759, 0xCBEE7460, 0x4085F2A7, 0xCE77326E, + 0xA6078084, 0x19F8509E, 0xE8EFD855, 0x61D99735, + 0xA969A7AA, 0xC50C06C2, 0x5A04ABFC, 0x800BCADC, + 0x9E447A2E, 0xC3453484, 0xFDD56705, 0x0E1E9EC9, + 0xDB73DBD3, 0x105588CD, 0x675FDA79, 0xE3674340, + 0xC5C43465, 0x713E38D8, 0x3D28F89E, 0xF16DFF20, + 0x153E21E7, 0x8FB03D4A, 0xE6E39F2B, 0xDB83ADF7); + public $s3 = array( + 0xE93D5A68, 0x948140F7, 0xF64C261C, 0x94692934, + 0x411520F7, 0x7602D4F7, 0xBCF46B2E, 0xD4A20068, + 0xD4082471, 0x3320F46A, 0x43B7D4B7, 0x500061AF, + 0x1E39F62E, 0x97244546, 0x14214F74, 0xBF8B8840, + 0x4D95FC1D, 0x96B591AF, 0x70F4DDD3, 0x66A02F45, + 0xBFBC09EC, 0x03BD9785, 0x7FAC6DD0, 0x31CB8504, + 0x96EB27B3, 0x55FD3941, 0xDA2547E6, 0xABCA0A9A, + 0x28507825, 0x530429F4, 0x0A2C86DA, 0xE9B66DFB, + 0x68DC1462, 0xD7486900, 0x680EC0A4, 0x27A18DEE, + 0x4F3FFEA2, 0xE887AD8C, 0xB58CE006, 0x7AF4D6B6, + 0xAACE1E7C, 0xD3375FEC, 0xCE78A399, 0x406B2A42, + 0x20FE9E35, 0xD9F385B9, 0xEE39D7AB, 0x3B124E8B, + 0x1DC9FAF7, 0x4B6D1856, 0x26A36631, 0xEAE397B2, + 0x3A6EFA74, 0xDD5B4332, 0x6841E7F7, 0xCA7820FB, + 0xFB0AF54E, 0xD8FEB397, 0x454056AC, 0xBA489527, + 0x55533A3A, 0x20838D87, 0xFE6BA9B7, 0xD096954B, + 0x55A867BC, 0xA1159A58, 0xCCA92963, 0x99E1DB33, + 0xA62A4A56, 0x3F3125F9, 0x5EF47E1C, 0x9029317C, + 0xFDF8E802, 0x04272F70, 0x80BB155C, 0x05282CE3, + 0x95C11548, 0xE4C66D22, 0x48C1133F, 0xC70F86DC, + 0x07F9C9EE, 0x41041F0F, 0x404779A4, 0x5D886E17, + 0x325F51EB, 0xD59BC0D1, 0xF2BCC18F, 0x41113564, + 0x257B7834, 0x602A9C60, 0xDFF8E8A3, 0x1F636C1B, + 0x0E12B4C2, 0x02E1329E, 0xAF664FD1, 0xCAD18115, + 0x6B2395E0, 0x333E92E1, 0x3B240B62, 0xEEBEB922, + 0x85B2A20E, 0xE6BA0D99, 0xDE720C8C, 0x2DA2F728, + 0xD0127845, 0x95B794FD, 0x647D0862, 0xE7CCF5F0, + 0x5449A36F, 0x877D48FA, 0xC39DFD27, 0xF33E8D1E, + 0x0A476341, 0x992EFF74, 0x3A6F6EAB, 0xF4F8FD37, + 0xA812DC60, 0xA1EBDDF8, 0x991BE14C, 0xDB6E6B0D, + 0xC67B5510, 0x6D672C37, 0x2765D43B, 0xDCD0E804, + 0xF1290DC7, 0xCC00FFA3, 0xB5390F92, 0x690FED0B, + 0x667B9FFB, 0xCEDB7D9C, 0xA091CF0B, 0xD9155EA3, + 0xBB132F88, 0x515BAD24, 0x7B9479BF, 0x763BD6EB, + 0x37392EB3, 0xCC115979, 0x8026E297, 0xF42E312D, + 0x6842ADA7, 0xC66A2B3B, 0x12754CCC, 0x782EF11C, + 0x6A124237, 0xB79251E7, 0x06A1BBE6, 0x4BFB6350, + 0x1A6B1018, 0x11CAEDFA, 0x3D25BDD8, 0xE2E1C3C9, + 0x44421659, 0x0A121386, 0xD90CEC6E, 0xD5ABEA2A, + 0x64AF674E, 0xDA86A85F, 0xBEBFE988, 0x64E4C3FE, + 0x9DBC8057, 0xF0F7C086, 0x60787BF8, 0x6003604D, + 0xD1FD8346, 0xF6381FB0, 0x7745AE04, 0xD736FCCC, + 0x83426B33, 0xF01EAB71, 0xB0804187, 0x3C005E5F, + 0x77A057BE, 0xBDE8AE24, 0x55464299, 0xBF582E61, + 0x4E58F48F, 0xF2DDFDA2, 0xF474EF38, 0x8789BDC2, + 0x5366F9C3, 0xC8B38E74, 0xB475F255, 0x46FCD9B9, + 0x7AEB2661, 0x8B1DDF84, 0x846A0E79, 0x915F95E2, + 0x466E598E, 0x20B45770, 0x8CD55591, 0xC902DE4C, + 0xB90BACE1, 0xBB8205D0, 0x11A86248, 0x7574A99E, + 0xB77F19B6, 0xE0A9DC09, 0x662D09A1, 0xC4324633, + 0xE85A1F02, 0x09F0BE8C, 0x4A99A025, 0x1D6EFE10, + 0x1AB93D1D, 0x0BA5A4DF, 0xA186F20F, 0x2868F169, + 0xDCB7DA83, 0x573906FE, 0xA1E2CE9B, 0x4FCD7F52, + 0x50115E01, 0xA70683FA, 0xA002B5C4, 0x0DE6D027, + 0x9AF88C27, 0x773F8641, 0xC3604C06, 0x61A806B5, + 0xF0177A28, 0xC0F586E0, 0x006058AA, 0x30DC7D62, + 0x11E69ED7, 0x2338EA63, 0x53C2DD94, 0xC2C21634, + 0xBBCBEE56, 0x90BCB6DE, 0xEBFC7DA1, 0xCE591D76, + 0x6F05E409, 0x4B7C0188, 0x39720A3D, 0x7C927C24, + 0x86E3725F, 0x724D9DB9, 0x1AC15BB4, 0xD39EB8FC, + 0xED545578, 0x08FCA5B5, 0xD83D7CD3, 0x4DAD0FC4, + 0x1E50EF5E, 0xB161E6F8, 0xA28514D9, 0x6C51133C, + 0x6FD5C7E7, 0x56E14EC4, 0x362ABFCE, 0xDDC6C837, + 0xD79A3234, 0x92638212, 0x670EFA8E, 0x406000E0); + public $s4 = array( + 0x3A39CE37, 0xD3FAF5CF, 0xABC27737, 0x5AC52D1B, + 0x5CB0679E, 0x4FA33742, 0xD3822740, 0x99BC9BBE, + 0xD5118E9D, 0xBF0F7315, 0xD62D1C7E, 0xC700C47B, + 0xB78C1B6B, 0x21A19045, 0xB26EB1BE, 0x6A366EB4, + 0x5748AB2F, 0xBC946E79, 0xC6A376D2, 0x6549C2C8, + 0x530FF8EE, 0x468DDE7D, 0xD5730A1D, 0x4CD04DC6, + 0x2939BBDB, 0xA9BA4650, 0xAC9526E8, 0xBE5EE304, + 0xA1FAD5F0, 0x6A2D519A, 0x63EF8CE2, 0x9A86EE22, + 0xC089C2B8, 0x43242EF6, 0xA51E03AA, 0x9CF2D0A4, + 0x83C061BA, 0x9BE96A4D, 0x8FE51550, 0xBA645BD6, + 0x2826A2F9, 0xA73A3AE1, 0x4BA99586, 0xEF5562E9, + 0xC72FEFD3, 0xF752F7DA, 0x3F046F69, 0x77FA0A59, + 0x80E4A915, 0x87B08601, 0x9B09E6AD, 0x3B3EE593, + 0xE990FD5A, 0x9E34D797, 0x2CF0B7D9, 0x022B8B51, + 0x96D5AC3A, 0x017DA67D, 0xD1CF3ED6, 0x7C7D2D28, + 0x1F9F25CF, 0xADF2B89B, 0x5AD6B472, 0x5A88F54C, + 0xE029AC71, 0xE019A5E6, 0x47B0ACFD, 0xED93FA9B, + 0xE8D3C48D, 0x283B57CC, 0xF8D56629, 0x79132E28, + 0x785F0191, 0xED756055, 0xF7960E44, 0xE3D35E8C, + 0x15056DD4, 0x88F46DBA, 0x03A16125, 0x0564F0BD, + 0xC3EB9E15, 0x3C9057A2, 0x97271AEC, 0xA93A072A, + 0x1B3F6D9B, 0x1E6321F5, 0xF59C66FB, 0x26DCF319, + 0x7533D928, 0xB155FDF5, 0x03563482, 0x8ABA3CBB, + 0x28517711, 0xC20AD9F8, 0xABCC5167, 0xCCAD925F, + 0x4DE81751, 0x3830DC8E, 0x379D5862, 0x9320F991, + 0xEA7A90C2, 0xFB3E7BCE, 0x5121CE64, 0x774FBE32, + 0xA8B6E37E, 0xC3293D46, 0x48DE5369, 0x6413E680, + 0xA2AE0810, 0xDD6DB224, 0x69852DFD, 0x09072166, + 0xB39A460A, 0x6445C0DD, 0x586CDECF, 0x1C20C8AE, + 0x5BBEF7DD, 0x1B588D40, 0xCCD2017F, 0x6BB4E3BB, + 0xDDA26A7E, 0x3A59FF45, 0x3E350A44, 0xBCB4CDD5, + 0x72EACEA8, 0xFA6484BB, 0x8D6612AE, 0xBF3C6F47, + 0xD29BE463, 0x542F5D9E, 0xAEC2771B, 0xF64E6370, + 0x740E0D8D, 0xE75B1357, 0xF8721671, 0xAF537D5D, + 0x4040CB08, 0x4EB4E2CC, 0x34D2466A, 0x0115AF84, + 0xE1B00428, 0x95983A1D, 0x06B89FB4, 0xCE6EA048, + 0x6F3F3B82, 0x3520AB82, 0x011A1D4B, 0x277227F8, + 0x611560B1, 0xE7933FDC, 0xBB3A792B, 0x344525BD, + 0xA08839E1, 0x51CE794B, 0x2F32C9B7, 0xA01FBAC9, + 0xE01CC87E, 0xBCC7D1F6, 0xCF0111C3, 0xA1E8AAC7, + 0x1A908749, 0xD44FBD9A, 0xD0DADECB, 0xD50ADA38, + 0x0339C32A, 0xC6913667, 0x8DF9317C, 0xE0B12B4F, + 0xF79E59B7, 0x43F5BB3A, 0xF2D519FF, 0x27D9459C, + 0xBF97222C, 0x15E6FC2A, 0x0F91FC71, 0x9B941525, + 0xFAE59361, 0xCEB69CEB, 0xC2A86459, 0x12BAA8D1, + 0xB6C1075E, 0xE3056A0C, 0x10D25065, 0xCB03A442, + 0xE0EC6E0E, 0x1698DB3B, 0x4C98A0BE, 0x3278E964, + 0x9F1F9532, 0xE0D392DF, 0xD3A0342B, 0x8971F21E, + 0x1B0A7441, 0x4BA3348C, 0xC5BE7120, 0xC37632D8, + 0xDF359F8D, 0x9B992F2E, 0xE60B6F47, 0x0FE3F11D, + 0xE54CDA54, 0x1EDAD891, 0xCE6279CF, 0xCD3E7E6F, + 0x1618B166, 0xFD2C1D05, 0x848FD2C5, 0xF6FB2299, + 0xF523F357, 0xA6327623, 0x93A83531, 0x56CCCD02, + 0xACF08162, 0x5A75EBB5, 0x6E163697, 0x88D273CC, + 0xDE966292, 0x81B949D0, 0x4C50901B, 0x71C65614, + 0xE6C6C7BD, 0x327A140A, 0x45E1D006, 0xC3F27B9A, + 0xC9AA53FD, 0x62A80F00, 0xBB25BFE2, 0x35BDD2F6, + 0x71126905, 0xB2040222, 0xB6CBCF7C, 0xCD769C2B, + 0x53113EC0, 0x1640E3D3, 0x38ABBD60, 0x2547ADF0, + 0xBA38209C, 0xF746CE76, 0x77AFA1C5, 0x20756060, + 0x85CBFE4E, 0x8AE88DD8, 0x7AAAF9B0, 0x4CF9AA7E, + 0x1948C25C, 0x02FB8A8C, 0x01C36AE4, 0xD6EBE1F9, + 0x90D4F869, 0xA65CDEA0, 0x3F09252D, 0xC208E69F, + 0xB74E6132, 0xCE77E25B, 0x578FDFE3, 0x3AC372E6); + + /* The number of rounds to do */ + public $_rounds = 16; + + /* Constructor */ + function Cipher_blowfish($params = null) + { + } + + /** + * Set the key to be used for en/decryption + * + * @param String $key The key to use + */ + function setKey($key) + { + $key = $this->_formatKey($key); + $keyPos = $keyXor = 0; + + $iMax = count($this->p); + $keyLen = count($key); + for ($i = 0; $i < $iMax; $i++) { + for ($t = 0; $t < 4; $t++) { + $keyXor = ($keyXor << 8) | (($key[$keyPos]) & 0x0ff); + if (++$keyPos == $keyLen) { + $keyPos = 0; + } + } + $this->p[$i] = $this->p[$i] ^ $keyXor; + } + + $encZero = array('L' => 0, 'R' => 0); + for ($i = 0; $i + 1 < $iMax; $i += 2) { + $encZero = $this->_encryptBlock($encZero['L'], $encZero['R']); + $this->p[$i] = $encZero['L']; + $this->p[$i + 1] = $encZero['R']; + } + + $iMax = count($this->s1); + for ($i = 0; $i < $iMax; $i += 2) { + $encZero = $this->_encryptBlock($encZero['L'], $encZero['R']); + $this->s1[$i] = $encZero['L']; + $this->s1[$i + 1] = $encZero['R']; + } + + $iMax = count($this->s2); + for ($i = 0; $i < $iMax; $i += 2) { + $encZero = $this->_encryptBlock($encZero['L'], $encZero['R']); + $this->s2[$i] = $encZero['L']; + $this->s2[$i + 1] = $encZero['R']; + } + + $iMax = count($this->s3); + for ($i = 0; $i < $iMax; $i += 2) { + $encZero = $this->_encryptBlock($encZero['L'], $encZero['R']); + $this->s3[$i] = $encZero['L']; + $this->s3[$i + 1] = $encZero['R']; + } + + $iMax = count($this->s4); + for ($i = 0; $i < $iMax; $i += 2) { + $encZero = $this->_encryptBlock($encZero['L'], $encZero['R']); + $this->s4[$i] = $encZero['L']; + $this->s4[$i + 1] = $encZero['R']; + } + + } + + /** + * Return the size of the blocks that this cipher needs + * + * @return Integer The number of characters per block + */ + function getBlockSize() + { + return 8; + } + + /** + * Encrypt a block on data. + * + * @param String $block The data to encrypt + * @param optional String $key The key to use + * + * @return String the encrypted output + */ + function encryptBlock($block, $key = null) + { + if (!is_null($key)) { + $this->setKey($key); + } + + list($L, $R) = array_values(unpack('N*', $block)); + $parts = $this->_encryptBlock($L, $R); + return pack("NN", $parts['L'], $parts['R']); + } + + /** + * Encrypt a block on data. + * + * @param String $L The data to encrypt. + * @param String $R The data to encrypt. + * + * @return String The encrypted output. + */ + function _encryptBlock($L, $R) + { + $L ^= $this->p[0]; + $R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[1]; + $L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[2]; + $R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[3]; + $L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[4]; + $R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[5]; + $L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[6]; + $R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[7]; + $L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[8]; + $R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[9]; + $L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[10]; + $R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[11]; + $L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[12]; + $R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[13]; + $L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[14]; + $R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[15]; + $L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[16]; + $R ^= $this->p[17]; + + return array('L' => $R, 'R' => $L); + } + + /** + * Decrypt a block on data. + * + * @param String $block The data to decrypt + * @param optional String $key The key to use + * + * @return String the decrypted output + */ + function decryptBlock($block, $key = null) + { + if (!is_null($key)) { + $this->setKey($key); + } + + $unpack = unpack('N*', $block); + + if (! is_array($unpack)) + error( + sprintf('BLOWFISH: decryptBock()
We expected unpack to produce an array, but instead it produced [%s]. This function was entered with (%s,%s). If you think that this is a bug, then please tell the PLA developers how you got here. You are using PLA [%s,%s]', + serialize($unpack),$block,$key,app_version(),phpversion()),'error','index.php'); + + list($L, $R) = array_values($unpack); + + $L ^= $this->p[17]; + $R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[16]; + $L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[15]; + $R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[14]; + $L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[13]; + $R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[12]; + $L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[11]; + $R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[10]; + $L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[9]; + $R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[8]; + $L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[7]; + $R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[6]; + $L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[5]; + $R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[4]; + $L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[3]; + $R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[2]; + $L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[1]; + + $decrypted = pack("NN", $R ^ $this->p[0], $L); + return $decrypted; + } + + /** + * Converts a text key into an array. + * + * @return array The key. + */ + function _formatKey($key) + { + return array_values(unpack('C*', $key)); + } + +} +?> diff --git a/lib/common.php b/lib/common.php new file mode 100644 index 0000000..b5aaff8 --- /dev/null +++ b/lib/common.php @@ -0,0 +1,335 @@ +getValue('appearance','theme')))) + && is_file(realpath(sprintf('css/%s/%s',$_SESSION[APPCONFIG]->getValue('appearance','theme'),$_SESSION[APPCONFIG]->getValue('appearance','stylesheet'))))) + + $app['theme'] = $_SESSION[APPCONFIG]->getValue('appearance','theme'); + +define('CSSDIR',sprintf('css/%s',$app['theme'])); +define('IMGDIR',sprintf('images/%s',$app['theme'])); + +# Initialise the hooks +if (file_exists(LIBDIR.'hooks.php')) + require_once LIBDIR.'hooks.php'; + +# If we get here, and $_SESSION[APPCONFIG] is not set, then redirect the user to the index. +if (isset($_SERVER['SERVER_SOFTWARE']) && ! isset($_SESSION[APPCONFIG])) { + if ($_SERVER['QUERY_STRING']) + header(sprintf('Location: index.php?URI=%s',base64_encode($_SERVER['QUERY_STRING']))); + else + header('Location: index.php'); + + die(); + +} else { + # SF Bug #1903987 + if (! method_exists($_SESSION[APPCONFIG],'CheckCustom')) + error('Unknown situation, $_SESSION[APPCONFIG] exists, but method CheckCustom() does not','error',null,true,true); + + # Check our custom variables. + # @todo Change this so that we dont process a cached session. + $_SESSION[APPCONFIG]->CheckCustom(); +} + +# Check for safe mode. +if (@ini_get('safe_mode') && ! get_request('cmd','GET')) + system_message(array( + 'title'=>_('PHP Safe Mode'), + 'body'=>_('You have PHP Safe Mode enabled. This application may work unexpectedly in Safe Mode.'), + 'type'=>'info')); + +# Set our timezone, if it is specified in config.php +if ($_SESSION[APPCONFIG]->getValue('appearance','timezone')) + date_default_timezone_set($_SESSION[APPCONFIG]->getValue('appearance','timezone')); + +# If we are here, $_SESSION is set - so enabled DEBUGing if it has been configured. +if (($_SESSION[APPCONFIG]->getValue('debug','syslog') || $_SESSION[APPCONFIG]->getValue('debug','file')) + && $_SESSION[APPCONFIG]->getValue('debug','level')) + define('DEBUG_ENABLED',1); +else + define('DEBUG_ENABLED',0); + +if (DEBUG_ENABLED) + debug_log('Application (%s) initialised and starting with (%s).',1,0,__FILE__,__LINE__,__METHOD__, + app_version(),$_REQUEST); + +# Set our PHP timelimit. +if ($_SESSION[APPCONFIG]->getValue('session','timelimit') && ! @ini_get('safe_mode')) + set_time_limit($_SESSION[APPCONFIG]->getValue('session','timelimit')); + +# If debug mode is set, increase the time_limit, since we probably need it. +if (DEBUG_ENABLED && $_SESSION[APPCONFIG]->getValue('session','timelimit') && ! @ini_get('safe_mode')) + set_time_limit($_SESSION[APPCONFIG]->getValue('session','timelimit') * 5); + +/** + * Language configuration. Auto or specified? + * Shall we attempt to auto-determine the language? + */ +# If we are in safe mode, and LANG is not in the allowed vars, display an error. +if (@ini_get('safe_mode') && ! in_array('LANG',explode(',',@ini_get('safe_mode_allowed_env_vars')))) + error('You are running in SAFE_MODE, but LANG is not in the safe_mode_allowed_env_vars. Please add LANG to safe_mode_allowed_env_vars','error',true,false); + +$app['language'] = $_SESSION[APPCONFIG]->getValue('appearance','language'); + +if ($app['language'] == 'auto') { + + # Make sure their browser correctly reports language. If not, skip this. + if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) { + + # Get the languages which are spetcified in the HTTP header + $app['lang_http'] = preg_split ('/[;,]+/',$_SERVER['HTTP_ACCEPT_LANGUAGE']); + foreach ($app['lang_http'] as $key => $value) { + if (substr($value,0,2) == 'q=') { + unset($app['lang_http'][$key]); + continue; + } + + $value = preg_split('/[-]+/',$value); + if (sizeof($value) == 2) + $app['lang_http'][$key] = strtolower($value[0]).'_'.strtoupper($value[1]); + else + $app['lang_http'][$key] = auto_lang(strtolower($value[0])); + } + + $app['lang_http'] = array_unique($app['lang_http']); + + foreach ($app['lang_http'] as $lang) { + $app['language_dir'] = LANGDIR.$lang; + + if ((substr($lang,0,2) == 'en') || + (file_exists($app['language_dir']) && is_readable($app['language_dir']))) { + + # Set language + putenv('LANG='.$lang); # e.g. LANG=de_DE + $lang .= '.UTF-8'; + setlocale(LC_ALL,$lang); # set LC_ALL to de_DE + bindtextdomain('messages',LANGDIR); + bind_textdomain_codeset('messages','UTF-8'); + textdomain('messages'); + header('Content-type: text/html; charset=UTF-8',true); + break; + } + } + #todo Generate an error if language doesnt exist. + } + +} else { + # Grab the language file configured in config.php + #todo Generate an error if language doesnt exist. + if ($app['language'] != null) { + if (strcmp($app['language'],'english') == 0) + $app['language'] = 'en_GB'; + + # Set language + putenv('LANG='.$app['language']); # e.g. LANG=de_DE + $app['language'] .= '.UTF-8'; + setlocale(LC_ALL,$app['language']); # set LC_ALL to de_DE + bindtextdomain('messages',LANGDIR); + bind_textdomain_codeset('messages','UTF-8'); + textdomain('messages'); + header('Content-type: text/html; charset=UTF-8',true); + } +} + +/** + * Strip slashes from GET, POST, and COOKIE variables if this + * PHP install is configured to automatically addslashes() + */ +if (@get_magic_quotes_gpc() && (! isset($slashes_stripped) || ! $slashes_stripped)) { + array_stripslashes($_REQUEST); + array_stripslashes($_GET); + array_stripslashes($_POST); + array_stripslashes($_COOKIE); + $slashes_stripped = true; +} + +# Create our application repository variable. +$app['server'] = $_SESSION[APPCONFIG]->getServer(get_request('server_id','REQUEST')); + +/** + * Look/evaluate our timeout + */ +if (! $app['server']->isSessionValid()) { + system_message(array( + 'title'=>_('Session Timed Out'), + 'body'=>sprintf('%s %s %s', + _('Your Session timed out after'),$app['server']->getValue('login','timeout'), + _('min. of inactivity. You have been automatically logged out.')), + 'type'=>'info'),sprintf('index.php?server_id=%s&refresh=SID_%s',$app['server']->getIndex(),$app['server']->getIndex())); + + die(); +} + +# If syslog is enabled, we need to include the supporting file. +if ($_SESSION[APPCONFIG]->getValue('debug','syslog')) + require LIBDIR.'syslog.php'; + +/** + * At this point we have read all our additional function PHP files and our configuration. + * If we are using hooks, run the session_init hook. + */ +if (function_exists('run_hook')) + run_hook('post_session_init',array()); +?> diff --git a/lib/config_default.php b/lib/config_default.php new file mode 100644 index 0000000..b0c05ca --- /dev/null +++ b/lib/config_default.php @@ -0,0 +1,808 @@ +custom = new stdClass; + $this->default = new stdClass; + + /* + * What to do after entry creation : + * 2 : display the creation form again + * 1 : display the new created entry + * 0 : display the choice between 1 and 2 + */ + $this->default->appearance['action_after_creation'] = array( + 'desc'=>'Display the new created entry', + 'default'=>1); + + ## Appearance Attributes + /** Anonymous implies read only + * Set to true if you want LDAP data to be displayed read-only (without input fields) + * when a user logs in to a server anonymously + */ + $this->default->appearance['anonymous_bind_implies_read_only'] = array( + 'desc'=>'Display as read only if user logs in with anonymous bind', + 'default'=>true); + + $this->default->appearance['attr_display_order'] = array( + 'desc'=>'Custom order to display attributes', + 'default'=>array()); + + /* + * @todo Compression is not working, + * purge_cache shows blank, + * tree refresh shows blank - and if view_tree_node is modified to compress output, then previously opened items show up as compressed data. + */ + $this->default->appearance['compress'] = array( + 'desc'=>'Compress Output', + 'untested'=>true, + 'default'=>false); + + $this->default->appearance['control_icons'] = array( + 'desc'=>'Show the control as icons or text', + 'default'=>false); + + $this->default->appearance['custom_templates_only'] = array( + 'desc'=>'Only display the custom templates.', + 'default'=>false); + + $this->default->appearance['date'] = array( + 'desc'=>'Date format whenever dates are shown', + 'default'=>'%A %e %B %Y'); + + $this->default->appearance['date_attrs'] = array( + 'desc'=>'Array of attributes that should show a jscalendar', + 'default'=>array('shadowExpire'=>'%es','shadowLastChange'=>'%es')); + + $this->default->appearance['date_attrs_showtime'] = array( + 'desc'=>'Array of attributes that should show a the time when showing the jscalendar', + 'default'=>array('')); + + $this->default->appearance['disable_default_template'] = array( + 'desc'=>'Disabled the Default Template', + 'default'=>false); + + $this->default->appearance['disable_default_leaf'] = array( + 'desc'=>'Disabled creating leaf entries in the Default Template', + 'default'=>false); + + $this->default->appearance['friendly_attrs'] = array( + 'desc'=>'Friendly names for attributes', + 'default'=>array()); + + $this->default->appearance['hide_attrs'] = array( + 'desc'=>'Hide attributes from display', + 'default'=>array()); + + $this->default->appearance['hide_attrs_exempt'] = array( + 'desc'=>'Group DN, where membership will exempt the users from hide_attrs', + 'default'=>null); + + $this->default->appearance['hide_debug_info'] = array( + 'desc'=>'Hide the features that may provide sensitive debugging information to the browser', + 'default'=>true); + + $this->default->appearance['hide_template_regexp'] = array( + 'desc'=>'Templates that are disabled by their regex are not shown', + 'default'=>false); + + $this->default->appearance['hide_template_warning'] = array( + 'desc'=>'Hide template errors from being displayed', + 'default'=>false); + + /** Language + * The language setting. If you set this to 'auto', phpLDAPadmin will + * attempt to determine your language automatically. Otherwise, set + * this to your applicable language in xx_XX format. + * Localization is not complete yet, but most strings have been translated. + * Please help by writing language files. + */ + $this->default->appearance['language'] = array( + 'desc'=>'Language', + 'default'=>'auto'); + + $this->default->appearance['max_add_attrs'] = array( + 'desc'=>'Maximum number of attrs to show in the add attr form', + 'default'=>10); + + /** + * If you want certain attributes to be editable as multi-line, include them in this list + * A multi-line textarea will be drawn instead of a single-line text field + */ + $this->default->appearance['multi_line_attributes'] = array( + 'desc'=>'Attributes to show as multiline attributes', + 'default'=>array('postalAddress','homePostalAddress','personalSignature','description','mailReplyText')); + + /** + * A list of syntax OIDs which support multi-line attribute values: + */ + $this->default->appearance['multi_line_syntax_oids'] = array( + 'desc'=>'Attributes to show as multiline attributes', + 'default'=>array( + // octet string syntax OID: + '1.3.6.1.4.1.1466.115.121.1.40', + // postal address syntax OID: + '1.3.6.1.4.1.1466.115.121.1.41')); + + /** Obfuscate Password + * If true, display all password hash values as "******". Note that clear-text + * passwords will always be displayed as "******", regardless of this setting. + */ + $this->default->appearance['obfuscate_password_display'] = array( + 'desc'=>'Obfuscate the display of passwords', + 'default'=>true); + + $this->default->appearance['page_title'] = array( + 'desc'=>'Change the page title to this text', + 'default'=>''); + + $this->default->appearance['rdn_all_attrs'] = array( + 'desc'=>'Whether to show all attributes in the RDN chooser, or just the required ones', + 'default'=>true); + + $this->default->appearance['readonly_attrs'] = array( + 'desc'=>'Mark these attributes as readonly', + 'default'=>array()); + + $this->default->appearance['readonly_attrs_exempt'] = array( + 'desc'=>'Group DN, where membership will exempt the users from readonly attrs', + 'default'=>null); + + $this->default->appearance['remoteurls'] = array( + 'desc'=>'Whether to include renders for remote URLs', + 'default'=>true); + + $this->default->appearance['show_clear_password'] = array( + 'desc'=>'Whether to show clear passwords if we dont obfuscate them', + 'default'=>false); + + $this->default->appearance['show_hints'] = array( + 'desc'=>'Show helpful hints', + 'default'=>true); + + $this->default->appearance['show_top_create'] = array( + 'desc'=>'Show a additional create link on the top of the list if there are more than 10 entries', + 'default'=>true); + + $this->default->appearance['show_schema_link'] = array( + 'desc'=>'Show the schema link for each attribute', + 'default'=>true); + + $this->default->appearance['show_attribute_notes'] = array( + 'desc'=>'Show notes for each attribute', + 'default'=>true); + + $this->default->appearance['stylesheet'] = array( + 'desc'=>'Style sheet to use', + 'default'=>'style.css'); + + $this->default->appearance['theme'] = array( + 'desc'=>'Which theme to use', + 'default'=>'default'); + + $this->default->appearance['timezone'] = array( + 'desc'=>'Define our timezone, if not defined in php.ini', + 'default'=>null); + + $this->default->appearance['tree'] = array( + 'desc'=>'Class name which inherits from Tree class and implements the draw() method', + 'default'=>'AJAXTree'); + + /** Tree display + * An array of format strings used to display enties in the + * tree viewer (left-hand side). The first format string that + * is completely defined (i.e., does not reference attributes + * that are not defined the object). If there is no format + * string that is completely defined, the last one is used. + * + * You can use special tokens to draw the entries as you wish. + * You can even mix in HTML to format the string. + * Here are all the tokens you can use: + * %rdn - draw the RDN of the entry (ie, "cn=Dave") + * %dn - draw the DN of the entry (ie, "cn=Dave,ou=People,dc=example,dc=com" + * %rdnValue - draw the value of the RDN (ie, instead of "cn=Dave", just draw "Dave") + * %[attrname]- draw the value (or values) of the specified attribute. + * example: %gidNumber + * + * Any multivalued attributes will be displayed as a comma separated list. + * + * Examples: + * + * To draw the gidNumber and uidNumber to the right of the RDN in a small, gray font: + * '%rdn ( %gidNumber / %uidNumber )' + * To draw the full DN of each entry: + * '%dn' + * To draw the objectClasses to the right in parenthesis: + * '%rdn ( %objectClass )' + * To draw the user-friendly RDN value (ie, instead of "cn=Dave", just draw "Dave"): + * '%rdnValue' + */ + $this->default->appearance['tree_display_format'] = array( + 'desc'=>'LDAP attribute to show in the tree', + 'default'=>array('%rdn')); + + $this->default->appearance['tree_height'] = array( + 'desc'=>'Pixel height of the tree browser', + 'default'=>null); + + $this->default->appearance['tree_width'] = array( + 'desc'=>'Pixel width of the tree browser', + 'default'=>null); + + /** Tree display filter + * LDAP filter used to search entries for the tree viewer (left-hand side) + */ + $this->default->appearance['tree_filter'] = array( + 'desc'=>'LDAP search filter for the tree entries', + 'default'=>'(objectClass=*)'); + + # PLA will not display the header and footer parts in minimal mode. + $this->default->appearance['minimalMode'] = array( + 'desc'=>'Minimal mode hides header and footer parts', + 'default'=>false); + + ## Caching + $this->default->cache['schema'] = array( + 'desc'=>'Cache Schema Activity', + 'default'=>true); + + $this->default->cache['query'] = array( + 'desc'=>'Cache Query Configuration', + 'default'=>true); + + $this->default->cache['query_time'] = array( + 'desc'=>'Cache the query configuration for atleast this amount of time in seconds', + 'default'=>5); + + $this->default->cache['template'] = array( + 'desc'=>'Cache Template Configuration', + 'default'=>true); + + $this->default->cache['template_time'] = array( + 'desc'=>'Cache the template configuration for atleast this amount of time in seconds', + 'default'=>60); + + $this->default->cache['tree'] = array( + 'desc'=>'Cache Browser Tree', + 'default'=>true); + + /** Confirm actions + */ + $this->default->confirm['copy'] = array( + 'desc'=>'Confirm copy actions', + 'default'=>true); + + $this->default->confirm['create'] = array( + 'desc'=>'Confirm creation actions', + 'default'=>true); + + $this->default->confirm['update'] = array( + 'desc'=>'Confirm update actions', + 'default'=>true); + + /** Commands + * Define command availability ; if the value of a command is true, + * the command will be available. + */ + $this->default->commands['cmd'] = array( + 'desc'=>'Define command availability', + 'default'=> array( + 'entry_internal_attributes_show' => true, + 'entry_refresh' => true, + 'oslinks' => true, + 'switch_template' => true + )); + + $this->default->commands['script'] = array( + 'desc'=>'Define scripts availability', + 'default'=> array( + 'add_attr_form' => true, + 'add_oclass_form' => true, + 'add_value_form' => true, + 'collapse' => true, + 'compare' => true, + 'compare_form' => true, + 'copy' => true, + 'copy_form' => true, + 'create' => true, + 'create_confirm' => true, + 'delete' => true, + 'delete_attr' => true, + 'delete_form' => true, + 'draw_tree_node' => true, + 'expand' => true, + 'export' => true, + 'export_form' => true, + 'import' => true, + 'import_form' => true, + 'login' => true, + 'logout' => true, + 'login_form' => true, + 'mass_delete' => true, + 'mass_edit' => true, + 'mass_update' => true, + 'modify_member_form' => true, + 'monitor' => true, + 'purge_cache' => true, + 'query_engine' => true, + 'rename' => true, + 'rename_form' => true, + 'rdelete' => true, + 'refresh' => true, + 'schema' => true, + 'server_info' => true, + 'show_cache' => true, + 'template_engine' => true, + 'update_confirm' => true, + 'update' => true + )); + + /** Aliases and Referrrals + * Similar to ldapsearch's -a option, the following options allow you to configure + * how phpLDAPadmin will treat aliases and referrals in the LDAP tree. + * For the following four settings, avaialable options include: + * + * LDAP_DEREF_NEVER - aliases are never dereferenced (eg, the contents of + * the alias itself are shown and not the referenced entry). + * LDAP_DEREF_SEARCHING - aliases should be dereferenced during the search but + * not when locating the base object of the search. + * LDAP_DEREF_FINDING - aliases should be dereferenced when locating the base + * object but not during the search. + * LDAP_DEREF_ALWAYS - aliases should be dereferenced always (eg, the contents + * of the referenced entry is shown and not the aliasing entry) + * We superceed these definitions with @ to suppress the error if php-ldap is + * not installed. + */ + @$this->default->deref['export'] = array( + 'desc'=>'', + 'default'=>LDAP_DEREF_NEVER); + + @$this->default->deref['search'] = array( + 'desc'=>'', + 'default'=>LDAP_DEREF_ALWAYS); + + @$this->default->deref['tree'] = array( + 'desc'=>'', + 'default'=>LDAP_DEREF_NEVER); + + @$this->default->deref['view'] = array( + 'desc'=>'', + 'default'=>LDAP_DEREF_NEVER); + + ## Debug Attributes + $this->default->debug['level'] = array( + 'desc'=>'Debug level verbosity', + 'default'=>0); + + $this->default->debug['syslog'] = array( + 'desc'=>'Whether to send debug messages to syslog', + 'default'=>false); + + $this->default->debug['file'] = array( + 'desc'=>'Name of file to send debug output to', + 'default'=>null); + + $this->default->debug['addr'] = array( + 'desc'=>'IP address of client to provide debugging info.', + 'default'=>null); + + $this->default->debug['append'] = array( + 'desc'=>'Whether to append to the debug file, or create it fresh each time', + 'default'=>true); + + ## Temp Directories + /** JPEG TMPDir + * This directory must be readable and writable by your web server + */ + $this->default->jpeg['tmpdir'] = array( + 'desc'=>'Temporary directory for jpegPhoto data', + 'default'=>'/tmp'); + + ## Mass update commands + $this->default->mass['enabled'] = array( + 'desc'=>'Are mass update commands enabled', + 'default'=>true); + + ## Modify members feature + /** + * Search filter setting for new members. This is used to search possible members that can be added + * to the group. See modify_member_form.php + */ + $this->default->modify_member['filter'] = array( + 'desc'=>'Search filter for member searches', + 'default'=>'(objectclass=Person)'); + + /** + * Group attributes. When these attributes are seen in template_engine.php, add "modify group members" + * link to the attribute + * See template_engine.php + */ + $this->default->modify_member['groupattr'] = array( + 'desc'=>'Group member attributes', + 'default'=>array('member','uniqueMember','memberUid')); + + /** + * Attribute that is added to the group member attribute. For groupOfNames or groupOfUniqueNames this is dn, + * for posixGroup it's uid. See modify_member_form.php + */ + $this->default->modify_member['attr'] = array( + 'desc'=>'Default attribute that is added to the group member attribute', + 'default'=>'dn'); + + /** + * Attribute that is added to the group member attribute. + * For posixGroup it's uid. See modify_member_form.php + */ + $this->default->modify_member['posixattr'] = array( + 'desc'=>'Contents of the group member attribute', + 'default'=>'uid'); + + /** + * Search filter setting for new members to group. This is used to search possible members that can be added + * to the posixGroup. See modify_member_form.php + */ + $this->default->modify_member['posixfilter'] = array( + 'desc'=>'Search filter for posixmember searches', + 'default'=>'(uid=*)'); + + /** + * posixGroup attribute. When this attribute are seen in modify_member_form.php, only posixGroup members are shown + * See modify_member_form.php + */ + $this->default->modify_member['posixgroupattr'] = array( + 'desc'=>'posixGroup member attribute', + 'default'=>'memberUid'); + + ## Session Attributes + /** Cookie Encryption + * phpLDAPadmin can encrypt the content of sensitive cookies if you set this to a big random string. + */ + $this->default->session['blowfish'] = array( + 'desc'=>'Blowfish key to encrypt cookie details', + 'default'=>null); + + /** Cookie Time + * If you used auth_type 'form' in the servers list, you can adjust how long the cookie will last + * (default is 0 seconds, which expires when you close the browser) + */ + $this->default->session['cookie_time'] = array( + 'desc'=>'Time in seconds for the life of cookies', + 'default'=>0); + + $this->default->session['http_realm'] = array( + 'desc'=>'HTTP Authentication Realm', + 'default'=>sprintf('%s %s',app_name(),_('login'))); + + $this->default->session['memorylimit'] = array( + 'desc'=>'Set the PHP memorylimit warning threshold.', + 'default'=>24); + + $this->default->session['timelimit'] = array( + 'desc'=>'Set the PHP timelimit.', + 'default'=>30); + + /** + * Session Menu + */ + $this->default->menu['session'] = array( + 'desc'=>'Menu items when logged in.', + 'default'=>array( + 'schema'=>true, + 'search'=>true, + 'refresh'=>true, + 'server_info'=>true, + 'monitor'=>true, + 'import'=>true, + 'export'=>true + )); + + ## Password Generation + $this->default->password['length'] = array( + 'desc'=>'Length of autogenerated password', + 'default'=>8); + + $this->default->password['numbers'] = array( + 'desc'=>'Number of numbers required in the password', + 'default'=>2); + + $this->default->password['lowercase'] = array( + 'desc'=>'Number of lowercase letters required in the password', + 'default'=>2); + + $this->default->password['uppercase'] = array( + 'desc'=>'Number of uppercase letters required in the password', + 'default'=>2); + + $this->default->password['punctuation'] = array( + 'desc'=>'Number of punctuation letters required in the password', + 'default'=>2); + + $this->default->password['use_similar'] = array( + 'desc'=>'Whether to use similiar characters', + 'default'=>true); + + $this->default->password['no_random_crypt_salt'] = array( + 'desc'=>'Disable random salt for crypt()', + 'default'=>false); + + /** Search display + * By default, when searching you may display a list or a table of results. + * Set this to 'table' to see table formatted results. + * Set this to 'list' to see "Google" style formatted search results. + */ + $this->default->search['display'] = array( + 'desc'=>'Display a list or table of search results', + 'default'=>'list'); + + $this->default->search['size_limit'] = array( + 'desc'=>'Limit the size of searchs on the search page', + 'default'=>50); + + /** + * The list of attributes to display in each search result entry. + * Note that you can add * to the list to display all attributes + */ + $this->default->search['result_attributes'] = array( + 'desc'=>'List of attributes to display in each search result entry', + 'default'=>array('cn','sn','uid','postalAddress','telephoneNumber')); + + $this->default->search['time_limit'] = array( + 'desc'=>'Maximum time to allow unlimited size_limit searches to the ldap server', + 'default'=>120); + } + + /** + * Access the configuration, taking into account the defaults and the customisations + */ + private function getConfigArray($usecache=true) { + static $CACHE = array(); + + if ($usecache && count($CACHE)) + return $CACHE; + + foreach ($this->default as $key => $vals) + $CACHE[$key] = $vals; + + foreach ($this->custom as $key => $vals) + foreach ($vals as $index => $val) + $CACHE[$key][$index]['value'] = $val; + + return $CACHE; + } + + /** + * Get a configuration value. + */ + public function getValue($key,$index,$fatal=true) { + $config = $this->getConfigArray(); + + if (! isset($config[$key])) + if ($fatal) + error(sprintf('A call was made in [%s] to getValue requesting [%s] that isnt predefined.', + basename($_SERVER['PHP_SELF']),$key),'error',null,true); + else + return ''; + + if (! isset($config[$key][$index])) + if ($fatal) + error(sprintf('Requesting an index [%s] in key [%s] that isnt predefined.',$index,$key),'error',null,true); + else + return ''; + + return isset($config[$key][$index]['value']) ? $config[$key][$index]['value'] : $config[$key][$index]['default']; + } + + /** + * Return the untested config items + */ + public function untested() { + $result = array(); + + foreach ($this->default as $option => $details) + foreach ($details as $param => $values) + if (isset($values['untested']) && $values['untested']) + array_push($result,sprintf('%s.%s',$option,$param)); + + return $result; + } + + /** + * Function to check and warn about any unusual defined variables. + */ + public function CheckCustom() { + if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',3,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (isset($this->custom)) { + foreach ($this->custom as $masterkey => $masterdetails) { + + if (isset($this->default->$masterkey)) { + + if (! is_array($masterdetails)) + error(sprintf('Error in configuration file, [%s] should be an ARRAY.',$masterdetails),'error',null,true); + + foreach ($masterdetails as $key => $value) { + # Test that the key is correct. + if (! in_array($key,array_keys($this->default->$masterkey))) + error(sprintf('Error in configuration file, [%s] has not been defined as a configurable variable.',$key),'error',null,true); + + # Test if its should be an array or not. + if (is_array($this->default->{$masterkey}[$key]['default']) && ! is_array($value)) + error(sprintf('Error in configuration file, %s[\'%s\'] SHOULD be an array of values.',$masterkey,$key),'error',null,true); + + if (! is_array($this->default->{$masterkey}[$key]['default']) && is_array($value)) + error(sprintf('Error in configuration file, %s[\'%s\'] should NOT be an array of values.',$masterkey,$key),'error',null,true); + } + + } else { + error(sprintf('Error in configuration file, [%s] has not been defined as a MASTER configurable variable.',$masterkey),'error',null,true); + } + } + } + } + + /** + * Get a list of available commands. + */ + public function getCommandList() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',3,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $config = $this->getConfigArray(false); + + masort($config['command'],'summary'); + + if (isset($config['command']) && is_array($config['command'])) + return $config['command']; + else + return array(); + } + + /** + * Simple ACL to see if commands can be run + */ + public function isCommandAvailable($index='cmd') { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',3,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $a = func_get_args(); + array_shift($a); + $a = $a[0]; + + # Command availability list + $cmd = $this->getValue('commands',$index); + + if (! is_string($a) || ! isset($cmd[$a])) + return false; + else + return $cmd[$a]; + } + + public function configDefinition($key,$index,$config) { + if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',3,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (! is_array($config) || ! array_key_exists('desc',$config) || ! array_key_exists('default',$config)) + return; + + if (isset($this->default->$key)) + $definition = $this->default->$key; + + $definition[$index] = $config; + $this->default->$key = $definition; + } + + /** + * Return the friendly attributes names + */ + private function getFriendlyAttrs() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',3,0,__FILE__,__LINE__,__METHOD__,$fargs); + + return array_change_key_case($this->getValue('appearance','friendly_attrs')); + } + + /** + * This function will return the friendly name of an attribute, if it exists. + * If the friendly name doesnt exist, the attribute name will be returned. + * + * @param attribute + * @return string friendly name|attribute + */ + public function getFriendlyName($attr) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',3,0,__FILE__,__LINE__,__METHOD__,$fargs); + + static $friendly_attrs; + + if (! $friendly_attrs) + $friendly_attrs = $this->getFriendlyAttrs(); + + if (! is_object($attr)) + if (isset($friendly_attrs[$attr])) + return $friendly_attrs[$attr]; + else + return $attr; + + if (isset($friendly_attrs[$attr->getName()])) + return $friendly_attrs[$attr->getName()]; + else + return $attr->getName(false); + } + + /** + * This function will return true if a friendly name exists for an attribute. + * If the friendly name doesnt exist, it will return false. + * + * @param attribute + * @return boolean true|false + */ + public function haveFriendlyName($attr) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',3,0,__FILE__,__LINE__,__METHOD__,$fargs); + + return $attr->getName(false) != $this->getFriendlyName($attr); + } + + /** + * This function will return the html for a friendly name attribute. + * + * @param attribute + * @return string html for the friendly name. + */ + public function getFriendlyHTML($attr) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',3,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if ($this->haveFriendlyName($attr)) + return sprintf('%s', + _('Alias for'),$attr->getName(false),$this->getFriendlyName($attr)); + else + return $attr->getName(false); + } + + public function setServers($servers) { + $this->servers = $servers; + } + + public function getServer($index=null) { + return $this->servers->Instance($index); + } + + /** + * Return a list of our servers + * @param boolean $visible - Only return visible servers + */ + public function getServerList($visible=true) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',3,0,__FILE__,__LINE__,__METHOD__,$fargs); + + return $this->servers->getServerList($visible); + } +} +?> diff --git a/lib/createlm.php b/lib/createlm.php new file mode 100644 index 0000000..3dc4bb1 --- /dev/null +++ b/lib/createlm.php @@ -0,0 +1,381 @@ +permute($key, $this->perm1, 56); + + $c = array(); + $d = array(); + for ($i = 0; $i < 28; $i++) { + $c[$i] = $pk1[$i]; + $d[$i] = $pk1[28 + $i]; + } + + for ($i = 0; $i < 16; $i++) { + $c = $this->lshift($this->sc[$i], $c); + $d = $this->lshift($this->sc[$i], $d); + + $cd = $c; + for ($k = 0; $k < sizeof($d); $k++) $cd[] = $d[$k]; + $ki[$i] = $this->permute($cd, $this->perm2, 48); + } + + $pd1 = $this->permute($in, $this->perm3, 64); + + $l = array(); + $r = array(); + for ($i = 0; $i < 32; $i++) { + $l[$i] = $pd1[$i]; + $r[$i] = $pd1[32 + $i]; + } + + for ($i = 0; $i < 16; $i++) { + $er = $this->permute($r, $this->perm4, 48); + if ($forw) $erk = $this->mxor($er, $ki[$i]); + else $erk = $this->mxor($er, $ki[15 - $i]); + + for ($j = 0; $j < 8; $j++) { + for ($k = 0; $k < 6; $k++) { + $b[$j][$k] = $erk[($j * 6) + $k]; + } + } + for ($j = 0; $j < 8; $j++) { + $m = array(); + $n = array(); + $m = ($b[$j][0] << 1) | $b[$j][5]; + $n = ($b[$j][1] << 3) | ($b[$j][2] << 2) | ($b[$j][3] << 1) | $b[$j][4]; + + for ($k = 0; $k < 4; $k++) { + $b[$j][$k]=($this->sbox[$j][$m][$n] & (1 << (3-$k)))?1:0; + } + } + + for ($j = 0; $j < 8; $j++) { + for ($k = 0; $k < 4; $k++) { + $cb[($j * 4) + $k] = $b[$j][$k]; + } + } + $pcb = $this->permute($cb, $this->perm5, 32); + $r2 = $this->mxor($l, $pcb); + for ($k = 0; $k < 32; $k++) $l[$k] = $r[$k]; + for ($k = 0; $k < 32; $k++) $r[$k] = $r2[$k]; + } + $rl = $r; + for ($i = 0; $i < sizeof($l); $i++) $rl[] = $l[$i]; + return $this->permute($rl, $this->perm6, 64); + } + + /** + * str_to_key + * + * @param string $str + * @return string key + */ + private function str_to_key($str) { + $key[0] = $this->unsigned_shift_r($str[0], 1); + $key[1] = (($str[0]&0x01)<<6) | $this->unsigned_shift_r($str[1], 2); + $key[2] = (($str[1]&0x03)<<5) | $this->unsigned_shift_r($str[2], 3); + $key[3] = (($str[2]&0x07)<<4) | $this->unsigned_shift_r($str[3], 4); + $key[4] = (($str[3]&0x0F)<<3) | $this->unsigned_shift_r($str[4], 5); + $key[5] = (($str[4]&0x1F)<<2) | $this->unsigned_shift_r($str[5], 6); + $key[6] = (($str[5]&0x3F)<<1) | $this->unsigned_shift_r($str[6], 7); + $key[7] = $str[6]&0x7F; + for ($i = 0; $i < 8; $i++) { + $key[$i] = ($key[$i] << 1); + } + return $key; + } + + /** + * smb_hash + * + * @param unknown_type $in + * @param unknown_type $key + * @param unknown_type $forw + * @return unknown + */ + private function smb_hash($in, $key, $forw){ + $key2 = $this->str_to_key($key); + + for ($i = 0; $i < 64; $i++) { + $inb[$i] = ($in[$i/8] & (1<<(7-($i%8)))) ? 1:0; + $keyb[$i] = ($key2[$i/8] & (1<<(7-($i%8)))) ? 1:0; + $outb[$i] = 0; + } + $outb = $this->doHash($inb, $keyb, $forw); + for ($i = 0; $i < 8; $i++) { + $out[$i] = 0; + } + for ($i = 0; $i < 64; $i++) { + if ( $outb[$i] ) { + $out[$i/8] |= (1<<(7-($i%8))); + } + } + return $out; + } + + /** + * E_P16 + * + * @param unknown_type $in + * @return unknown + */ + private function E_P16($in) { + $p14 = array_values(unpack("C*",$in)); + $sp8 = array(0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25); + $p14_1 = array(); + $p14_2 = array(); + for ($i = 0; $i < 7; $i++) { + $p14_1[$i] = $p14[$i]; + $p14_2[$i] = $p14[$i + 7]; + } + $p16_1 = $this->smb_hash($sp8, $p14_1, true); + $p16_2 = $this->smb_hash($sp8, $p14_2, true); + $p16 = $p16_1; + for ($i = 0; $i < sizeof($p16_2); $i++) { + $p16[] = $p16_2[$i]; + } + return $p16; + } + + /** + * Calculates the LM hash of a given password. + * + * @param string $password password + * @return string hash value + */ + public function lmhash($password = "") { + $password = strtoupper($password); + $password = substr($password,0,14); + $password = str_pad($password, 14, chr(0)); + $p16 = $this->E_P16($password); + for ($i = 0; $i < sizeof($p16); $i++) { + $p16[$i] = sprintf("%02X", $p16[$i]); + } + return join("", $p16); + } + + /** + * Calculates the NT hash of a given password. + * + * @param string $password password + * @return string hash value + */ + public function nthash($password = "") { + if (function_exists('mhash')) + if (defined('MHASH_MD4')) + return strtoupper(bin2hex(mhash(MHASH_MD4,iconv('UTF-8','UTF-16LE',$password)))); + else + return strtoupper(hash('md4', iconv("UTF-8","UTF-16LE",$password))); + else + error(_('Your PHP install does not have the mhash() function. Cannot do hashes.'),'error','index.php'); + } + + /** + * Unsigned shift operation for 32bit values. + * + * PHP 4 only supports signed shifts by default. + */ + private function unsigned_shift_r($a, $b) { + $z = 0x80000000; + if ($z & $a) { + $a = ($a >> 1); + $a &= (~$z); + $a |= 0x40000000; + $a = ($a >> ($b - 1)); + } + else { + $a = ($a >> $b); + } + return $a; + } + +} + +?> diff --git a/lib/ds.php b/lib/ds.php new file mode 100644 index 0000000..e7f4589 --- /dev/null +++ b/lib/ds.php @@ -0,0 +1,731 @@ +', any custom extra connection to ds. + */ + abstract public function login($user=null,$pass=null,$method=null); + + /** + * Query the datasource + */ + abstract public function query($query,$method,$index=null,$debug=false); + + /** + * Return error details from previous operation + */ + abstract protected function getErrorMessage(); + abstract protected function getErrorNum(); + + /** + * Functions that set and verify object configuration details + */ + public function setDefaults($defaults) { + foreach ($defaults as $key => $details) + foreach ($details as $setting => $value) + $this->default->{$key}[$setting] = $value; + } + + public function isDefaultKey($key) { + return isset($this->default->$key); + } + + public function isDefaultSetting($key,$setting) { + return array_key_exists($setting,$this->default->{$key}); + } + + /** + * Return a configuration value + */ + public function getValue($key,$setting,$fatal=true) { + if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,1,__FILE__,__LINE__,__METHOD__,$fargs); + + if (isset($this->custom->{$key}[$setting])) + return $this->custom->{$key}[$setting]; + + elseif (isset($this->default->{$key}[$setting]) && array_key_exists('default',$this->default->{$key}[$setting])) + return $this->default->{$key}[$setting]['default']; + + elseif ($fatal) + debug_dump_backtrace("Error trying to get a non-existant value ($key,$setting)",1); + + else + return null; + } + + /** + * Set a configuration value + */ + public function setValue($key,$setting,$value) { + if (isset($this->custom->{$key}[$setting])) + system_message(array( + 'title'=>_('Configuration setting already defined.'), + 'body'=>sprintf('A call has been made to reset a configuration value (%s,%s,%s)', + $key,$setting,$value), + 'type'=>'info')); + + $this->custom->{$key}[$setting] = $value; + } + + /** + * Return the untested config items + */ + public function untested() { + $result = array(); + + foreach ($this->default as $option => $details) + foreach ($details as $param => $values) + if (isset($values['untested']) && $values['untested']) + array_push($result,sprintf('%s.%s',$option,$param)); + + return $result; + } + + /** + * Get the name of this datastore + */ + public function getName() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + return $this->getValue('server','name'); + } + + /** + * Functions that enable login and logout of the application + */ + /** + * Return the authentication type for this object + */ + public function getAuthType() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + switch ($this->getValue('login','auth_type')) { + case 'cookie': + case 'config': + case 'http': + case 'proxy': + case 'session': + case 'sasl': + return $this->getValue('login','auth_type'); + + default: + die(sprintf('Error: %s hasnt been configured for auth_type %s',__METHOD__, + $this->getValue('login','auth_type'))); + } + } + + /** + * Get the login name of the user logged into this datastore's connection method + * If this returns null, we are not logged in. + * If this returns '', we are logged in with anonymous + */ + public function getLogin($method=null) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $method = $this->getMethod($method); + + # For anonymous binds + if ($method == 'anon') + if (isset($_SESSION['USER'][$this->index][$method]['name'])) + return ''; + else + return null; + + switch ($this->getAuthType()) { + case 'cookie': + if (! isset($_COOKIE[$method.'-USER'])) + # If our bind_id is set, we'll pass that back for logins. + return (! is_null($this->getValue('login','bind_id')) && $method == 'login') ? $this->getValue('login','bind_id') : null; + else + return blowfish_decrypt($_COOKIE[$method.'-USER']); + + case 'config': + if (! isset($_SESSION['USER'][$this->index][$method]['name'])) + return $this->getValue('login','bind_id'); + else + return blowfish_decrypt($_SESSION['USER'][$this->index][$method]['name']); + + case 'proxy': + if (! isset($_SESSION['USER'][$this->index][$method]['proxy'])) + return $this->getValue('login','bind_id'); + else + return blowfish_decrypt($_SESSION['USER'][$this->index][$method]['proxy']); + + case 'http': + case 'session': + case 'sasl': + if (! isset($_SESSION['USER'][$this->index][$method]['name'])) + # If our bind_id is set, we'll pass that back for logins. + return (! is_null($this->getValue('login','bind_id')) && $method == 'login') ? $this->getValue('login','bind_id') : null; + else + return blowfish_decrypt($_SESSION['USER'][$this->index][$method]['name']); + + default: + die(sprintf('Error: %s hasnt been configured for auth_type %s',__METHOD__,$this->getAuthType())); + } + } + + /** + * Set the login details of the user logged into this datastore's connection method + */ + protected function setLogin($user,$pass,$method=null) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $method = $this->getMethod($method); + + switch ($this->getAuthType()) { + case 'cookie': + set_cookie($method.'-USER',blowfish_encrypt($user),NULL,'/'); + set_cookie($method.'-PASS',blowfish_encrypt($pass),NULL,'/'); + return true; + + case 'config': + return true; + + case 'proxy': + if (isset($_SESSION['USER'][$this->index][$method]['proxy'])) + unset($_SESSION['USER'][$this->index][$method]['proxy']); + + case 'http': + case 'session': + case 'sasl': + $_SESSION['USER'][$this->index][$method]['name'] = blowfish_encrypt($user); + $_SESSION['USER'][$this->index][$method]['pass'] = blowfish_encrypt($pass); + + return true; + + default: + die(sprintf('Error: %s hasnt been configured for auth_type %s',__METHOD__,$this->getAuthType())); + } + } + + /** + * Get the login password of the user logged into this datastore's connection method + */ + protected function getPassword($method=null) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $method = $this->getMethod($method); + + # For anonymous binds + if ($method == 'anon') + if (isset($_SESSION['USER'][$this->index][$method]['name'])) + return ''; + else + return null; + + switch ($this->getAuthType()) { + case 'cookie': + if (! isset($_COOKIE[$method.'-PASS'])) + # If our bind_id is set, we'll pass that back for logins. + return (! is_null($this->getValue('login','bind_pass')) && $method == 'login') ? $this->getValue('login','bind_pass') : null; + else + return blowfish_decrypt($_COOKIE[$method.'-PASS']); + + case 'config': + case 'proxy': + if (! isset($_SESSION['USER'][$this->index][$method]['pass'])) + return $this->getValue('login','bind_pass'); + else + return blowfish_decrypt($_SESSION['USER'][$this->index][$method]['pass']); + + case 'http': + case 'session': + case 'sasl': + if (! isset($_SESSION['USER'][$this->index][$method]['pass'])) + # If our bind_pass is set, we'll pass that back for logins. + return (! is_null($this->getValue('login','bind_pass')) && $method == 'login') ? $this->getValue('login','bind_pass') : null; + else + return blowfish_decrypt($_SESSION['USER'][$this->index][$method]['pass']); + + default: + die(sprintf('Error: %s hasnt been configured for auth_type %s',__METHOD__,$this->getAuthType())); + } + } + + /** + * Return if this datastore's connection method has been logged into + */ + public function isLoggedIn($method=null) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + static $CACHE = array(); + + $method = $this->getMethod($method); + + if (isset($CACHE[$this->index][$method]) && ! is_null($CACHE[$this->index][$method])) + return $CACHE[$this->index][$method]; + + $CACHE[$this->index][$method] = null; + + # For some authentication types, we need to do the login here + switch ($this->getAuthType()) { + case 'config': + if (! $CACHE[$this->index][$method] = $this->login($this->getLogin($method),$this->getPassword($method),$method)) + system_message(array( + 'title'=>_('Unable to login.'), + 'body'=>_('Your configuration file has authentication set to CONFIG based authentication, however, the userid/password failed to login'), + 'type'=>'error')); + + break; + + case 'http': + # If our auth vars are not set, throw up a login box. + if (! isset($_SERVER['PHP_AUTH_USER'])) { + # If this server is not in focus, skip the basic auth prompt. + if (get_request('server_id','REQUEST') != $this->getIndex()) { + $CACHE[$this->index][$method] = false; + break; + } + + header(sprintf('WWW-Authenticate: Basic realm="%s %s"',app_name(),_('login'))); + + if ($_SERVER['SERVER_PROTOCOL'] == 'HTTP/1.0') + header('HTTP/1.0 401 Unauthorized'); // http 1.0 method + else + header('Status: 401 Unauthorized'); // http 1.1 method + + # If we still dont have login details... + if (! isset($_SERVER['PHP_AUTH_USER'])) { + system_message(array( + 'title'=>_('Unable to login.'), + 'body'=>_('Your configuration file has authentication set to HTTP based authentication, however, there was none presented'), + 'type'=>'error')); + + $CACHE[$this->index][$method] = false; + } + + # Check our auth vars are valid. + } else { + if (! $this->login($_SERVER['PHP_AUTH_USER'],$_SERVER['PHP_AUTH_PW'],$method)) { + system_message(array( + 'title'=>_('Unable to login.'), + 'body'=>_('Your HTTP based authentication is not accepted by the LDAP server'), + 'type'=>'error')); + + $CACHE[$this->index][$method] = false; + + } else + $CACHE[$this->index][$method] = true; + } + + break; + + case 'proxy': + $CACHE[$this->index][$method] = $this->login($this->getValue('login','bind_id'),$this->getValue('login','bind_pass'),$method); + + break; + + case 'sasl': + # Propogate any given Kerberos credential cache location + if (isset($_ENV['REDIRECT_KRB5CCNAME'])) + putenv(sprintf('KRB5CCNAME=%s',$_ENV['REDIRECT_KRB5CCNAME'])); + elseif (isset($_SERVER['KRB5CCNAME'])) + putenv(sprintf('KRB5CCNAME=%s',$_SERVER['KRB5CCNAME'])); + + # Map the SASL auth ID to a DN + $regex = $this->getValue('login', 'sasl_dn_regex'); + $replacement = $this->getValue('login', 'sasl_dn_replacement'); + + if ($regex && $replacement) { + $userDN = preg_replace($regex, $replacement, $_SERVER['REMOTE_USER']); + + $CACHE[$this->index][$method] = $this->login($userDN, '', $method); + + # Otherwise, use the user name as is + # For GSSAPI Authentication + mod_auth_kerb and Basic Authentication + } else + $CACHE[$this->index][$method] = $this->login(isset($_SERVER['REMOTE_USER']) ? $_SERVER['REMOTE_USER'] : '', '', $method); + + break; + + default: + $CACHE[$this->index][$method] = is_null($this->getLogin($method)) ? false : true; + } + + return $CACHE[$this->index][$method]; + } + + /** + * Logout of this datastore's connection method + */ + public function logout($method=null) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $method = $this->getMethod($method); + + unset ($_SESSION['cache'][$this->index]); + + switch ($this->getAuthType()) { + case 'cookie': + set_cookie($method.'-USER','',time()-3600,'/'); + set_cookie($method.'-PASS','',time()-3600,'/'); + + case 'config': + return true; + + case 'http': + case 'proxy': + case 'session': + case 'sasl': + if (isset($_SESSION['USER'][$this->index][$method])) + unset($_SESSION['USER'][$this->index][$method]); + + return true; + + default: + die(sprintf('Error: %s hasnt been configured for auth_type %s',__METHOD__,$this->getAuthType())); + } + } + + /** + * Functions that return the condition of the datasource + */ + public function isVisible() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + return $this->getValue('server','visible'); + } + + public function isReadOnly() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (! trim($this->getLogin(null)) && $_SESSION[APPCONFIG]->getValue('appearance','anonymous_bind_implies_read_only')) + return true; + else + return $this->getValue('server','read_only'); + } + + public function getIndex() { + if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->index); + + return $this->index; + } + + /** + * Work out which connection method to use. + * If a method is passed, then it will be passed back. If no method is passed, then we'll + * check to see if the user is logged in. If they are, then 'user' is used, otherwise + * 'anon' is used. + * + * @param int Server ID + * @return string Connection Method + */ + protected function getMethod($method=null) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + static $CACHE = array(); + + # Immediately return if method is set. + if (! is_null($method)) + return $method; + + # If we have been here already, then return our result + if (isset($CACHE[$this->index]) && ! is_null($CACHE)) + return $CACHE[$this->index]; + + $CACHE[$this->index] = 'anon'; + + if ($this->isLoggedIn('user')) + $CACHE[$this->index] = 'user'; + + return $CACHE[$this->index]; + } + + /** + * This method should be overridden in application specific ds files + */ + public function isSessionValid() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,1,__FILE__,__LINE__,__METHOD__,$fargs,true); + + return true; + } + + /** + * Return the time left in seconds until this connection times out. If there is not timeout, + * this function will return null. + */ + public function inactivityTime() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if ($this->isLoggedIn() && ! in_array($this->getAuthType(),array('config','http'))) + return time()+($this->getValue('login','timeout')*60); + else + return null; + } +} + +/** + * The list of database sources + * + * @package phpLDAPadmin + * @subpackage DataStore + */ +class Datastore { + # Out DS index id + private $index; + # List of all the objects + private $objects = array(); + # Default settings + private $default; + + public function __construct() { + $this->default = new StdClass; + + $this->default->server['id'] = array( + 'desc'=>'Server ID', + 'default'=>null); + + $this->default->server['name'] = array( + 'desc'=>'Server name', + 'default'=>null); + + # Connectivity Info + $this->default->server['host'] = array( + 'desc'=>'Host Name', + 'default'=>'127.0.0.1'); + + $this->default->server['port'] = array( + 'desc'=>'Port Number', + 'default'=>null); + + # Read or write only access + $this->default->server['read_only'] = array( + 'desc'=>'Server is in READ ONLY mode', + 'default'=>false); + + $this->default->server['visible'] = array( + 'desc'=>'Whether this server is visible', + 'default'=>true); + + $this->default->server['hide_noaccess_base'] = array( + 'desc'=>'If base DNs are not accessible, hide them instead of showing create', + 'default'=>false); + + # Authentication Information + $this->default->login['auth_type'] = array( + 'desc'=>'Authentication Type', + 'default'=>'session'); + +/* + /* ID to login to this application, this assumes that there is + * application authentication on top of authentication required to + * access the data source ** + $this->default->login['auth_id'] = array( + 'desc'=>'User Login ID to login to this DS', + 'untested'=>true, + 'default'=>null); + + $this->default->login['auth_pass'] = array( + 'desc'=>'User Login Password to login to this DS', + 'untested'=>true, + 'default'=>null); +*/ + + $this->default->login['auth_text'] = array( + 'desc'=>'Text to show at the login prompt', + 'default'=>null); + + $this->default->login['bind_id'] = array( + 'desc'=>'User Login ID to bind to this DS', + 'default'=>null); + + $this->default->login['bind_pass'] = array( + 'desc'=>'User Login Password to bind to this DS', + 'default'=>null); + + $this->default->login['timeout'] = array( + 'desc'=>'Session timout in seconds', + 'default'=>session_cache_expire()-1); + + $this->default->login['sasl_dn_regex'] = array( + 'desc'=>'SASL authorization id to user dn PCRE regular expression', + 'untested'=>true, + 'default'=>null); + + $this->default->login['sasl_dn_replacement'] = array( + 'desc'=>'SASL authorization id to user dn PCRE regular expression replacement string', + 'untested'=>true, + 'default'=>null); + + # Prefix for custom pages + $this->default->custom['pages_prefix'] = array( + 'desc'=>'Prefix name for custom pages', + 'default'=>'custom_'); + } + + /** + * Create a new database object + */ + public function newServer($type) { + if (class_exists($type)) { + $this->index = count($this->objects)+1; + $this->objects[$this->index] = new $type($this->index); + + $this->objects[$this->index]->setDefaults($this->default); + return $this->index; + + } else { + printf('ERROR: Class [%s] doesnt exist',$type); + die(); + } + } + + /** + * Set values for a database object. + */ + public function setValue($key,$setting,$value) { + if (! $this->objects[$this->index]->isDefaultKey($key)) + error("ERROR: Setting a key [$key] that isnt predefined.",'error',true); + + if (! $this->objects[$this->index]->isDefaultSetting($key,$setting)) + error("ERROR: Setting a index [$key,$setting] that isnt predefined.",'error',true); + + # Test if its should be an array or not. + if (is_array($this->objects[$this->index]->getValue($key,$setting)) && ! is_array($value)) + error("Error in configuration file, {$key}['$setting'] SHOULD be an array of values.",'error',true); + + if (! is_array($this->objects[$this->index]->getValue($key,$setting)) && is_array($value)) + error("Error in configuration file, {$key}['$setting'] should NOT be an array of values.",'error',true); + + # Store the value in the object. + $this->objects[$this->index]->setValue($key,$setting,$value); + } + + /** + * Get a list of all the configured servers. + * + * @param boolean Only show visible servers. + * @return array list of all configured servers. + */ + public function getServerList($isVisible=true) { + if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + static $CACHE; + + if (isset($CACHE[$isVisible])) + return $CACHE[$isVisible]; + + $CACHE[$isVisible] = array(); + + # Debugging incase objects is not set. + if (! $this->objects) { + print "
";
+			debug_print_backtrace();
+			die();
+		}
+
+		foreach ($this->objects as $id => $server)
+			if (! $isVisible || ($isVisible && $server->getValue('server','visible')))
+				$CACHE[$isVisible][$id] = $server;
+
+		masort($CACHE[$isVisible],'name');
+
+		return $CACHE[$isVisible];
+	}
+
+	/**
+	 * Return an object Instance of a configured database.
+	 *
+	 * @param int Index
+	 * @return object Datastore instance object.
+	 */
+	public function Instance($index=null) {
+		if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		# If no index defined, then pick the lowest one.
+		if (is_null($index) || ! trim($index) || ! is_numeric($index))
+			$index = min($this->GetServerList())->getIndex();
+
+		if (! isset($this->objects[$index]))
+			debug_dump_backtrace(sprintf('Error: Datastore instance [%s] doesnt exist?',htmlspecialchars($index)),1);
+
+		if (defined('DEBUG_ENABLED') && DEBUG_ENABLED)
+			debug_log('Returning instance of database (%s)',3,0,__FILE__,__LINE__,__METHOD__,$index);
+
+		return $this->objects[$index];
+	}
+
+	/**
+	 * Return an object Instance of a configured database.
+	 *
+	 * @param string Name of the instance to retrieve
+	 * @return object Datastore instance object.
+	 */
+	public function InstanceName($name=null) {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		foreach ($this->getServerList(false) as $index)
+			if ($this->objects[$index]->getName() == $name)
+				return $this->objects[$index];
+
+		# If we get here, then no object with the name exists.
+		return null;
+	}
+
+	/**
+	 * Return an object Instance of a configured database.
+	 *
+	 * @param string ID of the instance to retrieve
+	 * @return object Datastore instance object.
+	 */
+	public function InstanceId($id=null) {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		foreach ($this->getServerList(false) as $index)
+			if ($this->objects[$index->getIndex()]->getValue('server','id') == $id)
+				return $this->objects[$index->getIndex()];
+
+		# If we get here, then no object with the name exists.
+		return null;
+	}
+}
+?>
diff --git a/lib/ds_ldap.php b/lib/ds_ldap.php
new file mode 100644
index 0000000..c3d4267
--- /dev/null
+++ b/lib/ds_ldap.php
@@ -0,0 +1,2413 @@
+index = $index;
+		$this->type = 'ldap';
+
+		# Additional values that can go in our config.php
+		$this->custom = new StdClass;
+		$this->default = new StdClass;
+
+/*
+ * Not used by PLA
+		# Database Server Variables
+		$this->default->server['db'] = array(
+			'desc'=>'Database Name',
+			'untested'=>true,
+			'default'=>null);
+*/
+
+		/* This was created for IDS - since it doesnt present STRUCTURAL against objectClasses
+		 * definitions when reading the schema.*/
+		$this->default->server['schema_oclass_default'] = array(
+			'desc'=>'When reading the schema, and it doesnt specify objectClass type, default it to this',
+			'default'=>null);
+
+		$this->default->server['base'] = array(
+			'desc'=>'LDAP Base DNs',
+			'default'=>array());
+
+		$this->default->server['tls'] = array(
+			'desc'=>'Connect using TLS',
+			'default'=>false);
+
+		# Login Details
+		$this->default->login['attr'] = array(
+			'desc'=>'Attribute to use to find the users DN',
+			'default'=>'dn');
+
+		$this->default->login['anon_bind'] = array(
+			'desc'=>'Enable anonymous bind logins',
+			'default'=>true);
+
+		$this->default->login['allowed_dns'] = array(
+			'desc'=>'Limit logins to users who match any of the following LDAP filters',
+			'default'=>array());
+
+		$this->default->login['base'] = array(
+			'desc'=>'Limit logins to users who are in these base DNs',
+			'default'=>array());
+
+		$this->default->login['class'] = array(
+			'desc'=>'Strict login to users containing a specific objectClasses',
+			'default'=>array());
+
+		$this->default->proxy['attr'] = array(
+			'desc'=>'Attribute to use to find the users DN for proxy based authentication',
+			'default'=>array());
+
+		# SASL configuration
+		$this->default->sasl['mech'] = array(
+			'desc'=>'SASL mechanism used while binding LDAP server',
+			'default'=>'GSSAPI');
+
+		$this->default->sasl['realm'] = array(
+			'desc'=>'SASL realm name',
+			'untested'=>true,
+			'default'=>null);
+
+		$this->default->sasl['authz_id'] = array(
+			'desc'=>'SASL authorization id',
+			'untested'=>true,
+			'default'=>null);
+
+		$this->default->sasl['authz_id_regex'] = array(
+			'desc'=>'SASL authorization id PCRE regular expression',
+			'untested'=>true,
+			'default'=>null);
+
+		$this->default->sasl['authz_id_replacement'] = array(
+			'desc'=>'SASL authorization id PCRE regular expression replacement string',
+			'untested'=>true,
+			'default'=>null);
+
+		$this->default->sasl['props'] = array(
+			'desc'=>'SASL properties',
+			'untested'=>true,
+			'default'=>null);
+	}
+
+	/**
+	 * Required ABSTRACT functions
+	 */
+	/**
+	 * Connect and Bind to the Database
+	 *
+	 * @param string Which connection method resource to use
+	 * @return resource|null Connection resource if successful, null if not.
+	 */
+	protected function connect($method,$debug=false,$new=false) {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		static $CACHE = array();
+
+		$method = $this->getMethod($method);
+		$bind = array();
+
+		if (isset($CACHE[$this->index][$method]) && $CACHE[$this->index][$method])
+			return $CACHE[$this->index][$method];
+
+		# Check if we have logged in and therefore need to use those details as our bind.
+		$bind['id'] = is_null($this->getLogin($method)) && $method != 'anon' ? $this->getLogin('user') : $this->getLogin($method);
+		$bind['pass'] = is_null($this->getPassword($method)) && $method != 'anon' ? $this->getPassword('user') : $this->getPassword($method);
+
+		# If our bind id is still null, we are not logged in.
+		if (is_null($bind['id']) && ! in_array($method,array('anon','login')))
+			return null;
+
+		# If we bound to the LDAP server with these details for a different connection, return that resource
+		if (isset($CACHE[$this->index]) && ! $new)
+			foreach ($CACHE[$this->index] as $cachedmethod => $resource) {
+				if (($this->getLogin($cachedmethod) == $bind['id']) && ($this->getPassword($cachedmethod) == $bind['pass'])) {
+					$CACHE[$this->index][$method] = $resource;
+
+					return $CACHE[$this->index][$method];
+				}
+			}
+
+		$CACHE[$this->index][$method] = null;
+
+		# No identifiable connection exists, lets create a new one.
+		if (DEBUG_ENABLED)
+			debug_log('Creating NEW connection [%s] for index [%s]',16,0,__FILE__,__LINE__,__METHOD__,
+				$method,$this->index);
+
+		if (function_exists('run_hook'))
+			run_hook('pre_connect',array('server_id'=>$this->index,'method'=>$method));
+
+		if ($this->getValue('server','port'))
+			$resource = ldap_connect($this->getValue('server','host'),$this->getValue('server','port'));
+		else
+			$resource = ldap_connect($this->getValue('server','host'));
+
+		$CACHE[$this->index][$method] = $resource;
+
+		if (DEBUG_ENABLED)
+			debug_log('LDAP Resource [%s], Host [%s], Port [%s]',16,0,__FILE__,__LINE__,__METHOD__,
+				$resource,$this->getValue('server','host'),$this->getValue('server','port'));
+
+		if (! is_resource($resource))
+			debug_dump_backtrace('UNHANDLED, $resource is not a resource',1);
+
+		# Go with LDAP version 3 if possible (needed for renaming and Novell schema fetching)
+		ldap_set_option($resource,LDAP_OPT_PROTOCOL_VERSION,3);
+
+		/* Disabling this makes it possible to browse the tree for Active Directory, and seems
+		 * to not affect other LDAP servers (tested with OpenLDAP) as phpLDAPadmin explicitly
+		 * specifies deref behavior for each ldap_search operation. */
+		ldap_set_option($resource,LDAP_OPT_REFERRALS,0);
+
+		# Try to fire up TLS is specified in the config
+		if ($this->isTLSEnabled())
+			$this->startTLS($resource);
+
+		# If SASL has been configured for binding, then start it now.
+		if ($this->isSASLEnabled())
+			$bind['result'] = $this->startSASL($resource,$method);
+
+		# Normal bind...
+		else
+			$bind['result'] = @ldap_bind($resource,$bind['id'],$bind['pass']);
+
+		if ($debug)
+			debug_dump(array('method'=>$method,'bind'=>$bind,'USER'=>$_SESSION['USER']));
+
+		if (DEBUG_ENABLED)
+			debug_log('Resource [%s], Bind Result [%s]',16,0,__FILE__,__LINE__,__METHOD__,$resource,$bind);
+
+		if (! $bind['result']) {
+			if (DEBUG_ENABLED)
+				debug_log('Leaving with FALSE, bind FAILed',16,0,__FILE__,__LINE__,__METHOD__);
+
+			$this->noconnect = true;
+
+			system_message(array(
+				'title'=>sprintf('%s %s',_('Unable to connect to LDAP server'),$this->getName()),
+				'body'=>sprintf('%s: %s (%s) for %s',_('Error'),$this->getErrorMessage($method),$this->getErrorNum($method),$method),
+				'type'=>'error'));
+
+			$CACHE[$this->index][$method] = null;
+
+		} else {
+			$this->noconnect = false;
+
+			# If this is a proxy session, we need to switch to the proxy user
+			if ($this->isProxyEnabled() && $bind['id'] && $method != 'anon')
+				if (! $this->startProxy($resource,$method)) {
+					$this->noconnect = true;
+					$CACHE[$this->index][$method] = null;
+				}
+		}
+
+		if (function_exists('run_hook'))
+			run_hook('post_connect',array('server_id'=>$this->index,'method'=>$method,'id'=>$bind['id']));
+
+		if ($debug)
+			debug_dump(array($method=>$CACHE[$this->index][$method]));
+
+		return $CACHE[$this->index][$method];
+	}
+
+	/**
+	 * Login to the database with the application user/password
+	 *
+	 * @return boolean true|false for successful login.
+	 */
+	public function login($user=null,$pass=null,$method=null,$new=false) {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		$userDN = null;
+
+		# Get the userDN from the username.
+		if (! is_null($user)) {
+			# If login,attr is set to DN, then user should be a DN
+			if (($this->getValue('login','attr') == 'dn') || $method != 'user')
+				$userDN = $user;
+			else
+				$userDN = $this->getLoginID($user,'login');
+
+			if (! $userDN && $this->getValue('login','fallback_dn'))
+				$userDN = $user;
+
+			if (! $userDN)
+				return false;
+
+		} else {
+			if (in_array($method,array('user','anon'))) {
+				$method = 'anon';
+				$userDN = '';
+				$pass = '';
+
+			} else {
+				$userDN = $this->getLogin('user');
+				$pass = $this->getPassword('user');
+			}
+		}
+
+		if (! $this->isAnonBindAllowed() && ! trim($userDN))
+			return false;
+
+		# Temporarily set our user details
+		$this->setLogin($userDN,$pass,$method);
+
+		$connect = $this->connect($method,false,$new);
+
+		# If we didnt log in...
+		if (! is_resource($connect) || $this->noconnect || ! $this->userIsAllowedLogin($userDN)) {
+			$this->logout($method);
+
+			return false;
+
+		} else
+			return true;
+	}
+
+	/**
+	 * Perform a query to the Database
+	 *
+	 * @param string query to perform
+	 *	$query['base']
+	 *	$query['filter']
+	 *	$query['scope']
+	 *	$query['attrs'] = array();
+	 *	$query['deref']
+	 * @param string Which connection method resource to use
+	 * @param string Index items according to this key
+	 * @param boolean Enable debugging output
+	 * @return array|null Results of query.
+	 */
+	public function query($query,$method,$index=null,$debug=false) {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		$attrs_only = 0;
+
+		# Defaults
+		if (! isset($query['attrs']))
+			$query['attrs'] = array();
+		else
+			# Re-index the attrs, PHP throws an error if the keys are not sequential from 0.
+			$query['attrs'] = array_values($query['attrs']);
+
+		if (! isset($query['base'])) {
+			$bases = $this->getBaseDN();
+			$query['base'] = array_shift($bases);
+		}
+
+		if (! isset($query['deref']))
+			$query['deref'] = $_SESSION[APPCONFIG]->getValue('deref','search');
+		if (! isset($query['filter']))
+			$query['filter'] = '(&(objectClass=*))';
+		if (! isset($query['scope']))
+			$query['scope'] = 'sub';
+		if (! isset($query['size_limit']))
+			$query['size_limit'] = 0;
+		if (! isset($query['time_limit']))
+			$query['time_limit'] = 0;
+
+		if ($query['scope'] == 'base' && ! isset($query['baseok']))
+			system_message(array(
+				'title'=>sprintf('Dont call %s',__METHOD__),
+				'body'=>sprintf('Use getDNAttrValues for base queries [%s]',$query['base']),
+				'type'=>'info'));
+
+		if (is_array($query['base'])) {
+			system_message(array(
+				'title'=>_('Invalid BASE for query'),
+				'body'=>_('The query was cancelled because of an invalid base.'),
+				'type'=>'error'));
+
+			return array();
+		}
+
+		if (DEBUG_ENABLED)
+			debug_log('%s search PREPARE.',16,0,__FILE__,__LINE__,__METHOD__,$query['scope']);
+
+		if ($debug)
+			debug_dump(array('query'=>$query,'server'=>$this->getIndex(),'con'=>$this->connect($method)));
+
+		$resource = $this->connect($method,$debug);
+
+		switch ($query['scope']) {
+			case 'base':
+				$search = @ldap_read($resource,$query['base'],$query['filter'],$query['attrs'],$attrs_only,$query['size_limit'],$query['time_limit'],$query['deref']);
+				break;
+
+			case 'one':
+				$search = @ldap_list($resource,$query['base'],$query['filter'],$query['attrs'],$attrs_only,$query['size_limit'],$query['time_limit'],$query['deref']);
+				break;
+
+			case 'sub':
+			default:
+				$search = @ldap_search($resource,$query['base'],$query['filter'],$query['attrs'],$attrs_only,$query['size_limit'],$query['time_limit'],$query['deref']);
+				break;
+		}
+
+		if ($debug)
+			debug_dump(array('method'=>$method,'search'=>$search,'error'=>$this->getErrorMessage()));
+
+		if (DEBUG_ENABLED)
+			debug_log('Search scope [%s] base [%s] filter [%s] attrs [%s] COMPLETE (%s).',16,0,__FILE__,__LINE__,__METHOD__,
+				$query['scope'],$query['base'],$query['filter'],$query['attrs'],is_null($search));
+
+		if (! $search)
+			return array();
+
+		$return = array();
+
+		# Get the first entry identifier
+		if ($entries = ldap_get_entries($resource,$search)) {
+			# Remove the count
+			if (isset($entries['count']))
+				unset($entries['count']);
+
+			# Iterate over the entries
+			foreach ($entries as $a => $entry) {
+				if (! isset($entry['dn']))
+					debug_dump_backtrace('No DN?',1);
+
+				# Remove the none entry references.
+				if (! is_array($entry)) {
+					unset($entries[$a]);
+					continue;
+				}
+
+				$dn = $entry['dn'];
+				unset($entry['dn']);
+
+				# Iterate over the attributes
+				foreach ($entry as $b => $attrs) {
+					# Remove the none entry references.
+					if (! is_array($attrs)) {
+						unset($entry[$b]);
+						continue;
+					}
+
+					# Remove the count
+					if (isset($entry[$b]['count']))
+						unset($entry[$b]['count']);
+				}
+
+				# Our queries always include the DN (the only value not an array).
+				$entry['dn'] = $dn;
+				$return[$dn] = $entry;
+			}
+
+			# Sort our results
+			foreach ($return as $key=> $values)
+				ksort($return[$key]);
+		}
+
+		if (DEBUG_ENABLED)
+			debug_log('Returning (%s)',17,0,__FILE__,__LINE__,__METHOD__,$return);
+
+		return $return;
+	}
+
+	/**
+	 * Get the last error string
+	 *
+	 * @param string Which connection method resource to use
+	 */
+	public function getErrorMessage($method=null) {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		return ldap_error($this->connect($method));
+	}
+
+	/**
+	 * Get the last error number
+	 *
+	 * @param string Which connection method resource to use
+	 */
+	public function getErrorNum($method=null) {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		return ldap_errno($this->connect($method));
+	}
+
+	/**
+	 * Additional functions
+	 */
+	/**
+	 * Get a user ID
+	 *
+	 * @param string Which connection method resource to use
+	 */
+	public function getLoginID($user,$method=null) {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		$query['filter'] = sprintf('(&(%s=%s)%s)',
+			$this->getValue('login','attr'),$user,
+			$this->getLoginClass() ? sprintf('(objectclass=%s)',join(')(objectclass=',$this->getLoginClass())) : '');
+		$query['attrs'] = array('dn');
+
+		$result = array();
+		foreach ($this->getLoginBaseDN() as $base) {
+			$query['base'] = $base;
+			$result = $this->query($query,$method);
+
+			if (count($result) == 1)
+				break;
+		}
+
+		if (count($result) != 1)
+			return null;
+
+		$detail = array_shift($result);
+
+		if (! isset($detail['dn']))
+			die('ERROR: DN missing?');
+		else
+			return $detail['dn'];
+	}
+
+	/**
+	 * Return the login base DNs
+	 * If no login base DNs are defined, then the LDAP server Base DNs are used.
+	 */
+	private function getLoginBaseDN() {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',17,1,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		if ($this->getValue('login','base'))
+			return $this->getValue('login','base');
+		else
+			return $this->getBaseDN();
+	}
+
+	/**
+	 * Return the login classes that a user must have to login
+	 */
+	private function getLoginClass() {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',17,1,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		return $this->getValue('login','class');
+	}
+
+	/**
+	 * Return if anonymous bind is allowed in the configuration
+	 */
+	public function isAnonBindAllowed() {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		return $this->getValue('login','anon_bind');
+	}
+
+	/**
+	 * Fetches whether TLS has been configured for use with a certain server.
+	 *
+	 * Users may configure phpLDAPadmin to use TLS in config,php thus:
+	 * 
+	 *	$servers->setValue('server','tls',true|false);
+	 * 
+	 *
+	 * @return boolean
+	 */
+	private function isTLSEnabled() {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		if ($this->getValue('server','tls') && ! function_exists('ldap_start_tls')) {
+				error(_('TLS has been enabled in your config, but your PHP install does not support TLS. TLS will be disabled.'),'warn');
+			return false;
+
+		} else
+			return $this->getValue('server','tls');
+	}
+
+	/**
+	 * If TLS is configured, then start it
+	 */
+	private function startTLS($resource) {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		if (! $this->getValue('server','tls') || (function_exists('ldap_start_tls') && ! @ldap_start_tls($resource))) {
+			system_message(array(
+				'title'=>sprintf('%s (%s)',_('Could not start TLS.'),$this->getName()),
+				'body'=>sprintf('%s: %s',_('Error'),_('Could not start TLS. Please check your LDAP server configuration.')),
+				'type'=>'error'));
+
+			return false;
+
+		} else
+			return true;
+	}
+
+	/**
+	 * Fetches whether SASL has been configured for use with a certain server.
+	 *
+	 * Users may configure phpLDAPadmin to use SASL in config,php thus:
+	 * 
+	 *	$servers->setValue('login','auth_type','sasl');
+	 * 
+	 *
+	 * @return boolean
+	 */
+	private function isSASLEnabled() {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		if ($this->getValue('login','auth_type') != 'sasl')
+			return false;
+
+		if (! function_exists('ldap_sasl_bind')) {
+			error(_('SASL has been enabled in your config, but your PHP install does not support SASL. SASL will be disabled.'),'warn');
+
+			return false;
+		}
+
+		# If we get here, SASL must be configured.
+		return true;
+	}
+
+	/**
+	 * If SASL is configured, then start it
+	 * To be able to use SASL, PHP should have been compliled with --with-ldap-sasl=DIR
+	 *
+	 * @todo This has not been tested, please let the developers know if this function works as expected.
+	 */
+	private function startSASL($resource,$method) {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		static $CACHE = array();
+
+		# We shouldnt be doing SASL binds for anonymous queries?
+		if ($method == 'anon')
+			return false;
+
+		# At the moment, we have only implemented GSSAPI
+		if (! in_array(strtolower($this->getValue('sasl','mech')),array('gssapi'))) {
+			system_message(array(
+				'title'=>_('SASL Method not implemented'),
+				'body'=>sprintf('%s: %s %s',_('Error'),$this->getValue('sasl','mech'),_('has not been implemented yet')),
+				'type'=>'error'));
+
+			return false;
+		}
+
+		if (! isset($CACHE['login_dn']))
+			$CACHE['login_dn'] = is_null($this->getLogin($method)) ? $this->getLogin('user') : $this->getLogin($method);
+
+		$CACHE['authz_id'] = '';
+
+		/*
+		# Do we need to rewrite authz_id?
+		if (! isset($CACHE['authz_id']))
+			if (! trim($this->getValue('sasl','authz_id')) && strtolower($this->getValue('sasl','mech')) != 'gssapi') {
+				if (DEBUG_ENABLED)
+					debug_log('Rewriting bind DN [%s] -> authz_id with regex [%s] and replacement [%s].',9,0,__FILE__,__LINE__,__METHOD__,
+						$CACHE['login_dn'],
+						$this->getValue('sasl','authz_id_regex'),
+						$this->getValue('sasl','authz_id_replacement'));
+
+				$CACHE['authz_id'] = @preg_replace($this->getValue('sasl','authz_id_regex'),
+					$this->getValue('sasl','authz_id_replacement'),$CACHE['login_dn']);
+
+				# Invalid regex?
+				if (is_null($CACHE['authz_id']))
+					error(sprintf(_('It seems that sasl_authz_id_regex "%s" contains invalid PCRE regular expression. The error is "%s".'),
+						$this->getValue('sasl','authz_id_regex'),(isset($php_errormsg) ? $php_errormsg : '')),
+						'error','index.php');
+
+				if (DEBUG_ENABLED)
+					debug_log('Resource [%s], SASL OPTIONS: mech [%s], realm [%s], authz_id [%s], props [%s]',9,0,__FILE__,__LINE__,__METHOD__,
+						$resource,
+						$this->getValue('sasl','mech'),
+						$this->getValue('sasl','realm'),
+						$CACHE['authz_id'],
+						$this->getValue('sasl','props'));
+
+			} else
+				$CACHE['authz_id'] = $this->getValue('sasl','authz_id');
+		*/
+
+		# @todo this function is different in PHP5.1 and PHP5.2
+		return @ldap_sasl_bind($resource,NULL,'',
+			$this->getValue('sasl','mech'),
+			$this->getValue('sasl','realm'),
+			$CACHE['authz_id'],
+			$this->getValue('sasl','props'));
+	}
+
+	/**
+	 * Fetches whether PROXY AUTH has been configured for use with a certain server.
+	 *
+	 * Users may configure phpLDAPadmin to use PROXY AUTH in config,php thus:
+	 * 
+	 *	$servers->setValue('login','auth_type','proxy');
+	 * 
+	 *
+	 * @return boolean
+	 */
+	private function isProxyEnabled() {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		return $this->getValue('login','auth_type') == 'proxy' ? true : false;
+	}
+
+	/**
+	 * If PROXY AUTH is configured, then start it
+	 */
+	private function startProxy($resource,$method) {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		$rootdse = $this->getRootDSE();
+
+		if (! (isset($rootdse['supportedcontrol']) && in_array('2.16.840.1.113730.3.4.18',$rootdse['supportedcontrol']))) {
+			system_message(array(
+				'title'=>sprintf('%s %s',_('Unable to start proxy connection'),$this->getName()),
+				'body'=>sprintf('%s: %s',_('Error'),_('Your LDAP server doesnt seem to support this control')),
+				'type'=>'error'));
+
+			return false;
+		}
+
+		$filter = '(&';
+		$dn = '';
+
+		$missing = false;
+		foreach ($this->getValue('proxy','attr') as $attr => $var) {
+			if (! isset($_SERVER[$var])) {
+				system_message(array(
+					'title'=>sprintf('%s %s',_('Unable to start proxy connection'),$this->getName()),
+					'body'=>sprintf('%s: %s (%s)',_('Error'),_('Attribute doesnt exist'),$var),
+					'type'=>'error'));
+
+				$missing = true;
+
+			} else {
+				if ($attr == 'dn') {
+					$dn = $var;
+
+					break;
+
+				} else
+					$filter .= sprintf('(%s=%s)',$attr,$_SERVER[$var]);
+			}
+		}
+
+		if ($missing)
+			return false;
+
+		$filter .= ')';
+
+		if (! $dn) {
+			$query['filter'] = $filter;
+
+			foreach ($this->getBaseDN() as $base) {
+				$query['base'] = $base;
+
+				if ($search = $this->query($query,$method))
+					break;
+			}
+
+			if (count($search) != 1) {
+				system_message(array(
+					'title'=>sprintf('%s %s',_('Unable to start proxy connection'),$this->getName()),
+					'body'=>sprintf('%s: %s (%s)',_('Error'),_('Search for DN returned the incorrect number of results'),count($search)),
+					'type'=>'error'));
+
+				return false;
+			}
+
+			$search = array_pop($search);
+			$dn = $search['dn'];
+		}
+
+		$ctrl = array(
+			'oid'=>'2.16.840.1.113730.3.4.18',
+			'value'=>sprintf('dn:%s',$dn),
+			'iscritical' => true);
+
+		if (! ldap_set_option($resource,LDAP_OPT_SERVER_CONTROLS,array($ctrl))) {
+			system_message(array(
+				'title'=>sprintf('%s %s',_('Unable to start proxy connection'),$this->getName()),
+				'body'=>sprintf('%s: %s (%s) for %s',_('Error'),$this->getErrorMessage($method),$this->getErrorNum($method),$method),
+				'type'=>'error'));
+
+			return false;
+		}
+
+		$_SESSION['USER'][$this->index][$method]['proxy'] = blowfish_encrypt($dn);
+
+		return true;
+	}
+
+	/**
+	 * Modify attributes of a DN
+	 */
+	public function modify($dn,$attrs,$method=null) {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		# We need to supress the error here - programming should detect and report it.
+		return @ldap_mod_replace($this->connect($method),$dn,$attrs);
+	}
+
+	/**
+	 * Gets the root DN of the specified LDAPServer, or null if it
+	 * can't find it (ie, the server won't give it to us, or it isnt
+	 * specified in the configuration file).
+	 *
+	 * Tested with OpenLDAP 2.0, Netscape iPlanet, and Novell eDirectory 8.7 (nldap.com)
+	 * Please report any and all bugs!!
+	 *
+	 * Please note: On FC systems, it seems that php_ldap uses /etc/openldap/ldap.conf in
+	 * the search base if it is blank - so edit that file and comment out the BASE line.
+	 *
+	 * @param string Which connection method resource to use
+	 * @return array dn|null The root DN of the server on success (string) or null on error.
+	 * @todo Sort the entries, so that they are in the correct DN order.
+	 */
+	public function getBaseDN($method=null) {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		static $CACHE;
+
+		$method = $this->getMethod($method);
+		$result = array();
+
+		if (isset($CACHE[$this->index][$method]))
+			return $CACHE[$this->index][$method];
+
+		# If the base is set in the configuration file, then just return that.
+		if (count($this->getValue('server','base'))) {
+			if (DEBUG_ENABLED)
+				debug_log('Return BaseDN from Config [%s]',17,0,__FILE__,__LINE__,__METHOD__,implode('|',$this->getValue('server','base')));
+
+			$CACHE[$this->index][$method] = $this->getValue('server','base');
+
+		# We need to figure it out.
+		} else {
+			if (DEBUG_ENABLED)
+				debug_log('Connect to LDAP to find BaseDN',80,0,__FILE__,__LINE__,__METHOD__);
+
+			# Set this to empty, in case we loop back here looking for the baseDNs
+			$CACHE[$this->index][$method] = array();
+
+			$results = $this->getDNAttrValues('',$method);
+
+			if (isset($results['namingcontexts'])) {
+				if (DEBUG_ENABLED)
+					debug_log('LDAP Entries:%s',80,0,__FILE__,__LINE__,__METHOD__,implode('|',$results['namingcontexts']));
+
+				$result = $results['namingcontexts'];
+			}
+
+			$CACHE[$this->index][$method] = $result;
+		}
+
+		return $CACHE[$this->index][$method];
+	}
+
+	/**
+	 * Gets whether an entry exists based on its DN. If the entry exists,
+	 * returns true. Otherwise returns false.
+	 *
+	 * @param string The DN of the entry of interest.
+	 * @param string Which connection method resource to use
+	 * @return boolean
+	 */
+	public function dnExists($dn,$method=null) {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		$results = $this->getDNAttrValues($dn,$method);
+
+		if ($results)
+			return $results;
+		else
+			return false;
+	}
+
+	/**
+	 * Given a DN string, this returns the top container portion of the string.
+	 *
+	 * @param string The DN whose container string to return.
+	 * @return string The container
+	 */
+	public function getContainerTop($dn) {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		$return = $dn;
+
+		foreach ($this->getBaseDN() as $base) {
+			if (preg_match("/${base}$/i",$dn)) {
+				$return = $base;
+				break;
+			}
+		}
+
+		if (DEBUG_ENABLED)
+			debug_log('Returning (%s)',17,0,__FILE__,__LINE__,__METHOD__,$return);
+
+		return $return;
+	}
+
+	/**
+	 * Given a DN string and a path like syntax, this returns the parent container portion of the string.
+	 *
+	 * @param string The DN whose container string to return.
+	 * @param string Either '/', '.' or something like '../../'
+	 * @return string The container
+	 */
+	public function getContainerPath($dn,$path='..') {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		$top = $this->getContainerTop($dn);
+
+		if ($path[0] == '/') {
+			$dn = $top;
+			$path = substr($path,1);
+
+		} elseif ($path == '.') {
+			return $dn;
+		}
+
+		$parenttree = explode('/',$path);
+
+		foreach ($parenttree as $key => $value) {
+			if ($value == '..') {
+				if ($this->getContainer($dn))
+					$dn = $this->getContainer($dn);
+
+				if ($dn == $top)
+					break;
+
+			} elseif($value)
+				$dn = sprintf('%s,%s',$value,$dn);
+
+			else
+				break;
+		}
+
+		if (! $dn) {
+			debug_dump(array(__METHOD__,'dn'=>$dn,'path'=>$path));
+			debug_dump_backtrace('Container is empty?',1);
+		}
+
+		return $dn;
+	}
+
+	/**
+	 * Given a DN string, this returns the parent container portion of the string.
+	 * For example. given 'cn=Manager,dc=example,dc=com', this function returns
+	 * 'dc=example,dc=com'.
+	 *
+	 * @param string The DN whose container string to return.
+	 * @return string The container
+	 */
+	public function getContainer($dn) {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		$parts = $this->explodeDN($dn);
+
+		if (count($parts) <= 1)
+			$return = null;
+
+		else {
+			$return = $parts[1];
+
+			for ($i=2;$i
+	 *	dc=example,dc=com
+	 *		ou=People
+	 *			cn=Dave
+	 *			cn=Fred
+	 *			cn=Joe
+	 *		ou=More People
+	 *			cn=Mark
+	 *			cn=Bob
+	 * 
+	 *
+	 * Calling getContainerContents("ou=people,dc=example,dc=com")
+	 * would return the following list:
+	 *
+	 * 
+	 *	cn=Dave
+	 *	cn=Fred
+	 *	cn=Joe
+	 *	ou=More People
+	 * 
+	 *
+	 * @param string The DN of the entry whose children to return.
+	 * @param string Which connection method resource to use
+	 * @param int (optional) The maximum number of entries to return.
+	 *            If unspecified, no limit is applied to the number of entries in the returned.
+	 * @param string (optional) An LDAP filter to apply when fetching children, example: "(objectClass=inetOrgPerson)"
+	 * @param constant (optional) The LDAP deref setting to use in the query
+	 * @return array An array of DN strings listing the immediate children of the specified entry.
+	 */
+	public function getContainerContents($dn,$method=null,$size_limit=0,$filter='(objectClass=*)',$deref=LDAP_DEREF_NEVER) {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		$return = array();
+
+		$query = array();
+		$query['base'] = $this->escapeDN($dn);
+		$query['attrs'] = array('dn');
+		$query['filter'] = $filter;
+		$query['deref'] = $deref;
+		$query['scope'] = 'one';
+		$query['size_limit'] = $size_limit;
+		$results = $this->query($query,$method);
+
+		if ($results) {
+			foreach ($results as $index => $entry) {
+				$child_dn = $entry['dn'];
+				array_push($return,$child_dn);
+			}
+		}
+
+		if (DEBUG_ENABLED)
+			debug_log('Returning (%s)',17,0,__FILE__,__LINE__,__METHOD__,$return);
+
+		# Sort the results
+		asort($return);
+
+		return $return;
+	}
+
+	/**
+	 * Explode a DN into an array of its RDN parts.
+	 *
+	 * @param string The DN to explode.
+	 * @param int (optional) Whether to include attribute names (see http://php.net/ldap_explode_dn for details)
+	 *
+	 * @return array An array of RDN parts of this format:
+	 * 
+	 *	Array
+	 *		(
+	 *			[0] => uid=ppratt
+	 *			[1] => ou=People
+	 *			[2] => dc=example
+	 *			[3] => dc=com
+	 *		)
+	 * 
+	 *
+	 * NOTE: When a multivalue RDN is passed to ldap_explode_dn, the results returns with 'value + value';
+	 */
+	private function explodeDN($dn,$with_attributes=0) {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		static $CACHE;
+
+		if (isset($CACHE['explode'][$dn][$with_attributes])) {
+			if (DEBUG_ENABLED)
+				debug_log('Return CACHED result (%s) for (%s)',1,0,__FILE__,__LINE__,__METHOD__,
+					$CACHE['explode'][$dn][$with_attributes],$dn);
+
+			return $CACHE['explode'][$dn][$with_attributes];
+		}
+
+		$dn = addcslashes($dn,'<>+";');
+
+		# split the dn
+		$result[0] = ldap_explode_dn($this->escapeDN($dn),0);
+		$result[1] = ldap_explode_dn($this->escapeDN($dn),1);
+		if (! $result[$with_attributes]) {
+			if (DEBUG_ENABLED)
+				debug_log('Returning NULL - NO result.',1,0,__FILE__,__LINE__,__METHOD__);
+
+			return array();
+		}
+
+		# Remove our count value that ldap_explode_dn returns us.
+		unset($result[0]['count']);
+		unset($result[1]['count']);
+
+		# Record the forward and reverse entries in the cache.
+		foreach ($result as $key => $value) {
+			# translate hex code into ascii for display
+			$result[$key] = $this->unescapeDN($value);
+
+			$CACHE['explode'][implode(',',$result[0])][$key] = $result[$key];
+			$CACHE['explode'][implode(',',array_reverse($result[0]))][$key] = array_reverse($result[$key]);
+		}
+
+		if (DEBUG_ENABLED)
+			debug_log('Returning (%s)',17,0,__FILE__,__LINE__,__METHOD__,$result[$with_attributes]);
+
+		return $result[$with_attributes];
+	}
+
+	/**
+	 * Parse a DN and escape any special characters
+	 */
+	protected function escapeDN($dn) {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		if (! trim($dn))
+			return $dn;
+
+		# Check if the RDN has a comma and escape it.
+		while (preg_match('/([^\\\\]),(\s*[^=]*\s*),/',$dn))
+			$dn = preg_replace('/([^\\\\]),(\s*[^=]*\s*),/','$1\\\\2C$2,',$dn);
+
+		$dn = preg_replace('/([^\\\\]),(\s*[^=]*\s*)([^,])$/','$1\\\\2C$2$3',$dn);
+
+		if (DEBUG_ENABLED)
+			debug_log('Returning (%s)',17,0,__FILE__,__LINE__,__METHOD__,$dn);
+
+		return $dn;
+	}
+
+	/**
+	 * Parse a DN and unescape any special characters
+	 */
+	private function unescapeDN($dn) {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		$unescape = function ($input) {
+			return preg_replace_callback('/\\\([0-9A-Fa-f]{2})/', function ($match) {
+				return "'" . chr(hexdec($match[1])) . "'";
+			}, $input);
+		};
+
+		if (is_array($dn)) {
+			$a = array();
+
+			foreach ($dn as $key => $rdn)
+				$a[$key] = $unescape($rdn);
+				// $a[$key] = preg_replace('/\\\([0-9A-Fa-f]{2})/e',"''.chr(hexdec('\\1')).''",$rdn);
+
+			return $a;
+
+		} else {
+			return $unescape($dn);
+			// return preg_replace('/\\\([0-9A-Fa-f]{2})/e',"''.chr(hexdec('\\1')).''",$dn);
+		}
+	}
+
+	public function getRootDSE($method=null) {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		$query = array();
+		$query['base'] = '';
+		$query['scope'] = 'base';
+		$query['attrs'] = $this->getValue('server','root_dse_attributes');
+		$query['baseok'] = true;
+		$results = $this->query($query,$method);
+
+		if (is_array($results) && count($results) == 1)
+			return array_change_key_case(array_pop($results));
+		else
+			return array();
+	}
+
+	/** Schema Methods **/
+	/**
+	 * This function will query the ldap server and request the subSchemaSubEntry which should be the Schema DN.
+	 *
+	 * If we cant connect to the LDAP server, we'll return false.
+	 * If we can connect but cant get the entry, then we'll return null.
+	 *
+	 * @param string Which connection method resource to use
+	 * @param dn The DN to use to obtain the schema
+	 * @return array|false Schema if available, null if its not or false if we cant connect.
+	 */
+	private function getSchemaDN($method=null,$dn='') {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',25,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		# If we already got the SchemaDN, then return it.
+		if ($this->_schemaDN)
+			return $this->_schemaDN;
+
+		if (! $this->connect($method))
+			return false;
+
+		$search = @ldap_read($this->connect($method),$dn,'objectclass=*',array('subschemaSubentry'),false,0,10,LDAP_DEREF_NEVER);
+
+		if (DEBUG_ENABLED)
+			debug_log('Search returned (%s)',24,0,__FILE__,__LINE__,__METHOD__,is_resource($search));
+
+		# Fix for broken ldap.conf configuration.
+		if (! $search && ! $dn) {
+			if (DEBUG_ENABLED)
+				debug_log('Trying to find the DN for "broken" ldap.conf',80,0,__FILE__,__LINE__,__METHOD__);
+
+			if (isset($this->_baseDN)) {
+				foreach ($this->_baseDN as $base) {
+					$search = @ldap_read($this->connect($method),$base,'objectclass=*',array('subschemaSubentry'),false,0,10,LDAP_DEREF_NEVER);
+
+					if (DEBUG_ENABLED)
+						debug_log('Search returned (%s) for base (%s)',24,0,__FILE__,__LINE__,__METHOD__,
+							is_resource($search),$base);
+
+					if ($search)
+						break;
+				}
+			}
+		}
+
+		if (! $search)
+			return null;
+
+		if (! @ldap_count_entries($this->connect($method),$search)) {
+			if (DEBUG_ENABLED)
+				debug_log('Search returned 0 entries. Returning NULL',25,0,__FILE__,__LINE__,__METHOD__);
+
+			return null;
+		}
+
+		$entries = @ldap_get_entries($this->connect($method),$search);
+
+		if (DEBUG_ENABLED)
+			debug_log('Search returned [%s]',24,0,__FILE__,__LINE__,__METHOD__,$entries);
+
+		if (! $entries || ! is_array($entries))
+			return null;
+
+		$entry = isset($entries[0]) ? $entries[0] : false;
+		if (! $entry) {
+			if (DEBUG_ENABLED)
+				debug_log('Entry is false, Returning NULL',80,0,__FILE__,__LINE__,__METHOD__);
+
+			return null;
+		}
+
+		$sub_schema_sub_entry = isset($entry[0]) ? $entry[0] : false;
+		if (! $sub_schema_sub_entry) {
+			if (DEBUG_ENABLED)
+				debug_log('Sub Entry is false, Returning NULL',80,0,__FILE__,__LINE__,__METHOD__);
+
+			return null;
+		}
+
+		$this->_schemaDN = isset($entry[$sub_schema_sub_entry][0]) ? $entry[$sub_schema_sub_entry][0] : false;
+
+		if (DEBUG_ENABLED)
+			debug_log('Returning (%s)',25,0,__FILE__,__LINE__,__METHOD__,$this->_schemaDN);
+
+		return $this->_schemaDN;
+	}
+
+	/**
+	 * Fetches the raw schema array for the subschemaSubentry of the server. Note,
+	 * this function has grown many hairs to accomodate more LDAP servers. It is
+	 * needfully complicated as it now supports many popular LDAP servers that
+	 * don't necessarily expose their schema "the right way".
+	 *
+	 * Please note: On FC systems, it seems that php_ldap uses /etc/openldap/ldap.conf in
+	 * the search base if it is blank - so edit that file and comment out the BASE line.
+	 *
+	 * @param string Which connection method resource to use
+	 * @param string A string indicating which type of schema to
+	 *		fetch. Five valid values: 'objectclasses', 'attributetypes',
+	 *		'ldapsyntaxes', 'matchingruleuse', or 'matchingrules'.
+	 *		Case insensitive.
+	 * @param dn (optional) This paremeter is the DN of the entry whose schema you
+	 * 		would like to fetch. Entries have the option of specifying
+	 * 		their own subschemaSubentry that points to the DN of the system
+	 * 		schema entry which applies to this attribute. If unspecified,
+	 *		this will try to retrieve the schema from the RootDSE subschemaSubentry.
+	 *		Failing that, we use some commonly known schema DNs. Default
+	 *		value is the Root DSE DN (zero-length string)
+	 * @return array an array of strings of this form:
+	 *	Array (
+	 *		[0] => "(1.3.6.1.4.1.7165.1.2.2.4 NAME 'gidPool' DESC 'Pool ...
+	 *		[1] => "(1.3.6.1.4.1.7165.2.2.3 NAME 'sambaAccount' DESC 'Sa ...
+	 *	etc.
+	 */
+	private function getRawSchema($method,$schema_to_fetch,$dn='') {
+		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
+			debug_log('Entered (%%)',25,0,__FILE__,__LINE__,__METHOD__,$fargs);
+
+		$valid_schema_to_fetch = array('objectclasses','attributetypes','ldapsyntaxes','matchingrules','matchingruleuse');
+
+		if (! $this->connect($method) || $this->noconnect)
+			return false;
+
+		# error checking
+		$schema_to_fetch = strtolower($schema_to_fetch);
+
+		if (! is_null($this->_schema_entries) && isset($this->_schema_entries[$schema_to_fetch])) {
+			$schema = $this->_schema_entries[$schema_to_fetch];
+
+			if (DEBUG_ENABLED)
+				debug_log('Returning CACHED (%s)',25,0,__FILE__,__LINE__,__METHOD__,$schema);
+
+			return $schema;
+		}
+
+		# This error message is not localized as only developers should ever see it
+		if (! in_array($schema_to_fetch,$valid_schema_to_fetch))
+			error(sprintf('Bad parameter provided to function to %s::getRawSchema(). "%s" is not valid for the schema_to_fetch parameter.',
+					get_class($this),$schema_to_fetch),'error','index.php');
+
+		# Try to get the schema DN from the specified entry.
+		$schema_dn = $this->getSchemaDN($method,$dn);
+
+		# Do we need to try again with the Root DSE?
+		if (! $schema_dn && trim($dn))
+			$schema_dn = $this->getSchemaDN($method,'');
+
+		# Store the eventual schema retrieval in $schema_search
+		$schema_search = null;
+
+		if ($schema_dn) {
+			if (DEBUG_ENABLED)
+				debug_log('Using Schema DN (%s)',24,0,__FILE__,__LINE__,__METHOD__,$schema_dn);
+
+			foreach (array('(objectClass=*)','(objectClass=subschema)') as $schema_filter) {
+				if (DEBUG_ENABLED)
+					debug_log('Looking for schema with Filter (%s)',24,0,__FILE__,__LINE__,__METHOD__,$schema_filter);
+
+				$schema_search = @ldap_read($this->connect($method),$schema_dn,$schema_filter,array($schema_to_fetch),false,0,10,LDAP_DEREF_NEVER);
+
+				if (is_null($schema_search))
+					continue;
+
+				$schema_entries = @ldap_get_entries($this->connect($method),$schema_search);
+
+				if (DEBUG_ENABLED)
+					debug_log('Search returned [%s]',24,0,__FILE__,__LINE__,__METHOD__,$schema_entries);
+
+				if (is_array($schema_entries) && isset($schema_entries['count']) && $schema_entries['count']) {
+					if (DEBUG_ENABLED)
+						debug_log('Found schema with (DN:%s) (FILTER:%s) (ATTR:%s)',24,0,__FILE__,__LINE__,__METHOD__,
+							$schema_dn,$schema_filter,$schema_to_fetch);
+
+					break;
+				}
+
+				if (DEBUG_ENABLED)
+					debug_log('Didnt find schema with filter (%s)',24,0,__FILE__,__LINE__,__METHOD__,$schema_filter);
+
+				unset($schema_entries);
+				$schema_search = null;
+			}
+		}
+
+		/* Second chance: If the DN or Root DSE didn't give us the subschemaSubentry, ie $schema_search
+		 * is still null, use some common subSchemaSubentry DNs as a work-around. */
+		if (is_null($schema_search)) {
+			if (DEBUG_ENABLED)
+				debug_log('Attempting work-arounds for "broken" LDAP servers...',24,0,__FILE__,__LINE__,__METHOD__);
+
+			foreach ($this->getBaseDN() as $base) {
+				$ldap['W2K3 AD'][expand_dn_with_base($base,'cn=Aggregate,cn=Schema,cn=configuration,')] = '(objectClass=*)';
+				$ldap['W2K AD'][expand_dn_with_base($base,'cn=Schema,cn=configuration,')] = '(objectClass=*)';
+				$ldap['W2K AD'][expand_dn_with_base($base,'cn=Schema,ou=Admin,')] = '(objectClass=*)';
+			}
+
+			# OpenLDAP and Novell
+			$ldap['OpenLDAP']['cn=subschema'] = '(objectClass=*)';
+
+			foreach ($ldap as $ldap_server_name => $ldap_options) {
+				foreach ($ldap_options as $ldap_dn => $ldap_filter) {
+					if (DEBUG_ENABLED)
+						debug_log('Attempting [%s] (%s) (%s)
',24,0,__FILE__,__LINE__,__METHOD__, + $ldap_server_name,$ldap_dn,$ldap_filter); + + $schema_search = @ldap_read($this->connect($method),$ldap_dn,$ldap_filter,array($schema_to_fetch),false,0,10,LDAP_DEREF_NEVER); + if (is_null($schema_search)) + continue; + + $schema_entries = @ldap_get_entries($this->connect($method),$schema_search); + + if (DEBUG_ENABLED) + debug_log('Search returned [%s]',24,0,__FILE__,__LINE__,__METHOD__,$schema_entries); + + if ($schema_entries && isset($schema_entries[0][$schema_to_fetch])) { + if (DEBUG_ENABLED) + debug_log('Found schema with filter of (%s)',24,0,__FILE__,__LINE__,__METHOD__,$ldap_filter); + + break; + } + + if (DEBUG_ENABLED) + debug_log('Didnt find schema with filter (%s)',24,0,__FILE__,__LINE__,__METHOD__,$ldap_filter); + + unset($schema_entries); + $schema_search = null; + } + if ($schema_search) + break; + } + } + + # Option 3: try cn=config + $olc_schema = 'olc'.$schema_to_fetch; + $olc_schema_found = false; + if (is_null($schema_search)) { + if (DEBUG_ENABLED) + debug_log('Attempting cn=config work-around...',24,0,__FILE__,__LINE__,__METHOD__); + + $ldap_dn = 'cn=schema,cn=config'; + $ldap_filter = '(objectClass=*)'; + + $schema_search = @ldap_search($this->connect($method),$ldap_dn,$ldap_filter,array($olc_schema),false,0,10,LDAP_DEREF_NEVER); + + if (! is_null($schema_search)) { + $schema_entries = @ldap_get_entries($this->connect($method),$schema_search); + + if (DEBUG_ENABLED) + debug_log('Search returned [%s]',24,0,__FILE__,__LINE__,__METHOD__,$schema_entries); + + if ($schema_entries) { + if (DEBUG_ENABLED) + debug_log('Found schema with filter of (%s) and attribute filter (%s)',24,0,__FILE__,__LINE__,__METHOD__,$ldap_filter,$olc_schema); + + $olc_schema_found = true; + + } else { + if (DEBUG_ENABLED) + debug_log('Didnt find schema with filter (%s) and attribute filter (%s)',24,0,__FILE__,__LINE__,__METHOD__,$ldap_filter,$olc_schema); + + unset($schema_entries); + $schema_search = null; + } + } + } + + if (is_null($schema_search)) { + /* Still cant find the schema, try with the RootDSE + * Attempt to pull schema from Root DSE with scope "base", or + * Attempt to pull schema from Root DSE with scope "one" (work-around for Isode M-Vault X.500/LDAP) */ + foreach (array('base','one') as $ldap_scope) { + if (DEBUG_ENABLED) + debug_log('Attempting to find schema with scope (%s), filter (objectClass=*) and a blank base.',24,0,__FILE__,__LINE__,__METHOD__, + $ldap_scope); + + switch ($ldap_scope) { + case 'base': + $schema_search = @ldap_read($this->connect($method),'','(objectClass=*)',array($schema_to_fetch),false,0,10,LDAP_DEREF_NEVER); + break; + + case 'one': + $schema_search = @ldap_list($this->connect($method),'','(objectClass=*)',array($schema_to_fetch),false,0,10,LDAP_DEREF_NEVER); + break; + } + + if (is_null($schema_search)) + continue; + + $schema_entries = @ldap_get_entries($this->connect($method),$schema_search); + if (DEBUG_ENABLED) + debug_log('Search returned [%s]',24,0,__FILE__,__LINE__,__METHOD__,$schema_entries); + + if ($schema_entries && isset($schema_entries[0][$schema_to_fetch])) { + if (DEBUG_ENABLED) + debug_log('Found schema with filter of (%s)',24,0,__FILE__,__LINE__,__METHOD__,'(objectClass=*)'); + + break; + } + + if (DEBUG_ENABLED) + debug_log('Didnt find schema with filter (%s)',24,0,__FILE__,__LINE__,__METHOD__,'(objectClass=*)'); + + unset($schema_entries); + $schema_search = null; + } + } + + $schema_error_message = 'Please contact the phpLDAPadmin developers and let them know:
  • Which LDAP server you are running, including which version
  • What OS it is running on
  • Which version of PHP
  • As well as a link to some documentation that describes how to obtain the SCHEMA information

We\'ll then add support for your LDAP server in an upcoming release.'; + $schema_error_message_array = array('objectclasses','attributetypes'); + + # Shall we just give up? + if (is_null($schema_search)) { + # We need to have objectclasses and attribues, so display an error, asking the user to get us this information. + if (in_array($schema_to_fetch,$schema_error_message_array)) + system_message(array( + 'title'=>sprintf('%s (%s)',_('Our attempts to find your SCHEMA have failed'),$schema_to_fetch), + 'body'=>sprintf('%s: %s',_('Error'),$schema_error_message), + 'type'=>'error')); + else + if (DEBUG_ENABLED) + debug_log('Returning because schema_search is NULL ()',25,0,__FILE__,__LINE__,__METHOD__); + + # We'll set this, so if we return here our cache will return the known false. + $this->_schema_entries[$schema_to_fetch] = false; + return false; + } + + if (! $schema_entries) { + $return = false; + if (DEBUG_ENABLED) + debug_log('Returning false since ldap_get_entries() returned false.',25,0,__FILE__,__LINE__,__METHOD__,$return); + + return $return; + } + + if ($olc_schema_found) { + unset ($schema_entries['count']); + + foreach ($schema_entries as $entry) { + if (isset($entry[$olc_schema])) { + unset($entry[$olc_schema]['count']); + + foreach ($entry[$olc_schema] as $schema_definition) + /* Schema definitions in child nodes prefix the schema entries with "{n}" + the preg_replace call strips out this prefix. */ + $schema[] = preg_replace('/^\{\d*\}\(/','(',$schema_definition); + } + } + + if (isset($schema)) { + $this->_schema_entries[$olc_schema] = $schema; + + if (DEBUG_ENABLED) + debug_log('Returning (%s)',25,0,__FILE__,__LINE__,__METHOD__,$schema); + + return $schema; + + } else + return null; + } + + if (! isset($schema_entries[0][$schema_to_fetch])) { + if (in_array($schema_to_fetch,$schema_error_message_array)) { + error(sprintf('Our attempts to find your SCHEMA for "%s" have return UNEXPECTED results.

(We expected a "%s" in the $schema array but it wasnt there.)

%s

Dump of $schema_search:
%s
', + $schema_to_fetch,gettype($schema_search),$schema_error_message,serialize($schema_entries)),'error','index.php'); + + } else { + $return = false; + + if (DEBUG_ENABLED) + debug_log('Returning because (%s) isnt in the schema array. (%s)',25,0,__FILE__,__LINE__,__METHOD__,$schema_to_fetch,$return); + + return $return; + } + } + + /* Make a nice array of this form: + Array ( + [0] => "(1.3.6.1.4.1.7165.1.2.2.4 NAME 'gidPool' DESC 'Pool ...)" + [1] => "(1.3.6.1.4.1.7165.2.2.3 NAME 'sambaAccount' DESC 'Sa ...)" + etc.) */ + + $schema = $schema_entries[0][$schema_to_fetch]; + unset($schema['count']); + $this->_schema_entries[$schema_to_fetch] = $schema; + + if (DEBUG_ENABLED) + debug_log('Returning (%s)',25,0,__FILE__,__LINE__,__METHOD__,$schema); + + return $schema; + } + + /** + * Gets a single ObjectClass object specified by name. + * + * @param string $oclass_name The name of the objectClass to fetch. + * @param string $dn (optional) It is easier to fetch schema if a DN is provided + * which defines the subschemaSubEntry attribute (all entries should). + * + * @return ObjectClass The specified ObjectClass object or false on error. + * + * @see ObjectClass + * @see SchemaObjectClasses + */ + public function getSchemaObjectClass($oclass_name,$method=null,$dn='') { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',25,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $oclass_name = strtolower($oclass_name); + $socs = $this->SchemaObjectClasses($method,$dn); + + # Default return value + $return = false; + + if (isset($socs[$oclass_name])) + $return = $socs[$oclass_name]; + + if (DEBUG_ENABLED) + debug_log('Returning (%s)',25,0,__FILE__,__LINE__,__METHOD__,$return); + + return $return; + } + + /** + * Gets a single AttributeType object specified by name. + * + * @param string $oclass_name The name of the AttributeType to fetch. + * @param string $dn (optional) It is easier to fetch schema if a DN is provided + * which defines the subschemaSubEntry attribute (all entries should). + * + * @return AttributeType The specified AttributeType object or false on error. + * + * @see AttributeType + * @see SchemaAttributes + */ + public function getSchemaAttribute($attr_name,$method=null,$dn='') { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',25,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $attr_name = strtolower($attr_name); + $sattrs = $this->SchemaAttributes($method,$dn); + + # Default return value + $return = false; + + if (isset($sattrs[$attr_name])) + $return = $sattrs[$attr_name]; + + if (DEBUG_ENABLED) + debug_log('Returning (%s)',25,0,__FILE__,__LINE__,__METHOD__,$return); + + return $return; + } + + /** + * Gets an associative array of ObjectClass objects for the specified + * server. Each array entry's key is the name of the objectClass + * in lower-case and the value is an ObjectClass object. + * + * @param string $dn (optional) It is easier to fetch schema if a DN is provided + * which defines the subschemaSubEntry attribute (all entries should). + * + * @return array An array of ObjectClass objects. + * + * @see ObjectClass + * @see getSchemaObjectClass + */ + public function SchemaObjectClasses($method=null,$dn='') { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',25,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # Set default return + $return = null; + + if ($return = get_cached_item($this->index,'schema','objectclasses')) { + if (DEBUG_ENABLED) + debug_log('Returning CACHED [%s] (%s)',25,0,__FILE__,__LINE__,__METHOD__,$this->index,'objectclasses'); + + return $return; + } + + $raw = $this->getRawSchema($method,'objectclasses',$dn); + + if ($raw) { + # Build the array of objectClasses + $return = array(); + + foreach ($raw as $line) { + if (is_null($line) || ! strlen($line)) + continue; + + $object_class = new ObjectClass($line,$this); + $return[$object_class->getName()] = $object_class; + } + + # Now go through and reference the parent/child relationships + foreach ($return as $oclass) + foreach ($oclass->getSupClasses() as $parent_name) + if (isset($return[strtolower($parent_name)])) + $return[strtolower($parent_name)]->addChildObjectClass($oclass->getName(false)); + + ksort($return); + + # cache the schema to prevent multiple schema fetches from LDAP server + set_cached_item($this->index,'schema','objectclasses',$return); + } + + if (DEBUG_ENABLED) + debug_log('Returning (%s)',25,0,__FILE__,__LINE__,__METHOD__,$return); + + return $return; + } + + /** + * Gets an associative array of AttributeType objects for the specified + * server. Each array entry's key is the name of the attributeType + * in lower-case and the value is an AttributeType object. + * + * @param string $dn (optional) It is easier to fetch schema if a DN is provided + * which defines the subschemaSubEntry attribute (all entries should). + * + * @return array An array of AttributeType objects. + */ + public function SchemaAttributes($method=null,$dn='') { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',25,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # Set default return + $return = null; + + if ($return = get_cached_item($this->index,'schema','attributes')) { + if (DEBUG_ENABLED) + debug_log('(): Returning CACHED [%s] (%s)',25,0,__FILE__,__LINE__,__METHOD__,$this->index,'attributes'); + + return $return; + } + + $raw = $this->getRawSchema($method,'attributeTypes',$dn); + + if ($raw) { + # build the array of attribueTypes + $syntaxes = $this->SchemaSyntaxes($method,$dn); + $attrs = array(); + + /** + * bug 856832: create two arrays - one indexed by name (the standard + * $attrs array above) and one indexed by oid (the new $attrs_oid array + * below). This will help for directory servers, like IBM's, that use OIDs + * in their attribute definitions of SUP, etc + */ + $attrs_oid = array(); + foreach ($raw as $line) { + if (is_null($line) || ! strlen($line)) + continue; + + $attr = new AttributeType($line); + if (isset($syntaxes[$attr->getSyntaxOID()])) { + $syntax = $syntaxes[$attr->getSyntaxOID()]; + $attr->setType($syntax->getDescription()); + } + $attrs[$attr->getName()] = $attr; + + /** + * bug 856832: create an entry in the $attrs_oid array too. This + * will be a ref to the $attrs entry for maintenance and performance + * reasons + */ + $attrs_oid[$attr->getOID()] = &$attrs[$attr->getName()]; + } + + # go back and add data from aliased attributeTypes + foreach ($attrs as $name => $attr) { + $aliases = $attr->getAliases(); + + if (is_array($aliases) && count($aliases) > 0) { + /* foreach of the attribute's aliases, create a new entry in the attrs array + * with its name set to the alias name, and all other data copied.*/ + foreach ($aliases as $alias_attr_name) { + $new_attr = clone $attr; + + $new_attr->setName($alias_attr_name); + $new_attr->addAlias($attr->getName(false)); + $new_attr->removeAlias($alias_attr_name); + $new_attr_key = strtolower($alias_attr_name); + $attrs[$new_attr_key] = $new_attr; + } + } + } + + # go back and add any inherited descriptions from parent attributes (ie, cn inherits name) + foreach ($attrs as $key => $attr) { + $sup_attr_name = $attr->getSupAttribute(); + $sup_attr = null; + + if (trim($sup_attr_name)) { + + /* This loop really should traverse infinite levels of inheritance (SUP) for attributeTypes, + * but just in case we get carried away, stop at 100. This shouldn't happen, but for + * some weird reason, we have had someone report that it has happened. Oh well.*/ + $i = 0; + while ($i++<100 /** 100 == INFINITY ;) */) { + + if (isset($attrs_oid[$sup_attr_name])) { + $attr->setSupAttribute($attrs_oid[$sup_attr_name]->getName()); + $sup_attr_name = $attr->getSupAttribute(); + } + + if (! isset($attrs[strtolower($sup_attr_name)])){ + error(sprintf('Schema error: attributeType "%s" inherits from "%s", but attributeType "%s" does not exist.', + $attr->getName(),$sup_attr_name,$sup_attr_name),'error','index.php'); + return; + } + + $sup_attr = $attrs[strtolower($sup_attr_name)]; + $sup_attr_name = $sup_attr->getSupAttribute(); + + # Does this superior attributeType not have a superior attributeType? + if (is_null($sup_attr_name) || strlen(trim($sup_attr_name)) == 0) { + + /* Since this attribute's superior attribute does not have another superior + * attribute, clone its properties for this attribute. Then, replace + * those cloned values with those that can be explicitly set by the child + * attribute attr). Save those few properties which the child can set here:*/ + $tmp_name = $attr->getName(false); + $tmp_oid = $attr->getOID(); + $tmp_sup = $attr->getSupAttribute(); + $tmp_aliases = $attr->getAliases(); + $tmp_single_val = $attr->getIsSingleValue(); + $tmp_desc = $attr->getDescription(); + + /* clone the SUP attributeType and populate those values + * that were set by the child attributeType */ + $attr = clone $sup_attr; + + $attr->setOID($tmp_oid); + $attr->setName($tmp_name); + $attr->setSupAttribute($tmp_sup); + $attr->setAliases($tmp_aliases); + $attr->setDescription($tmp_desc); + + /* only overwrite the SINGLE-VALUE property if the child explicitly sets it + * (note: All LDAP attributes default to multi-value if not explicitly set SINGLE-VALUE) */ + if ($tmp_single_val) + $attr->setIsSingleValue(true); + + /* replace this attribute in the attrs array now that we have populated + new values therein */ + $attrs[$key] = $attr; + + # very important: break out after we are done with this attribute + $sup_attr_name = null; + $sup_attr = null; + break; + } + } + } + } + + ksort($attrs); + + # Add the used in and required_by values. + $socs = $this->SchemaObjectClasses($method); + if (! is_array($socs)) + return array(); + + foreach ($socs as $object_class) { + $must_attrs = $object_class->getMustAttrNames(); + $may_attrs = $object_class->getMayAttrNames(); + $oclass_attrs = array_unique(array_merge($must_attrs,$may_attrs)); + + # Add Used In. + foreach ($oclass_attrs as $attr_name) + if (isset($attrs[strtolower($attr_name)])) + $attrs[strtolower($attr_name)]->addUsedInObjectClass($object_class->getName(false)); + + # Add Required By. + foreach ($must_attrs as $attr_name) + if (isset($attrs[strtolower($attr_name)])) + $attrs[strtolower($attr_name)]->addRequiredByObjectClass($object_class->getName(false)); + + # Force May + foreach ($object_class->getForceMayAttrs() as $attr_name) + if (isset($attrs[strtolower($attr_name->name)])) + $attrs[strtolower($attr_name->name)]->setForceMay(); + } + + $return = $attrs; + + # cache the schema to prevent multiple schema fetches from LDAP server + set_cached_item($this->index,'schema','attributes',$return); + } + + if (DEBUG_ENABLED) + debug_log('Returning (%s)',25,0,__FILE__,__LINE__,__METHOD__,$return); + + return $return; + } + + /** + * Returns an array of MatchingRule objects for the specified server. + * The key of each entry is the OID of the matching rule. + */ + public function MatchingRules($method=null,$dn='') { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',25,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # Set default return + $return = null; + + if ($return = get_cached_item($this->index,'schema','matchingrules')) { + if (DEBUG_ENABLED) + debug_log('Returning CACHED [%s] (%s).',25,0,__FILE__,__LINE__,__METHOD__,$this->index,'matchingrules'); + + return $return; + } + + # build the array of MatchingRule objects + $raw = $this->getRawSchema($method,'matchingRules',$dn); + + if ($raw) { + $rules = array(); + + foreach ($raw as $line) { + if (is_null($line) || ! strlen($line)) + continue; + + $rule = new MatchingRule($line); + $key = $rule->getName(); + $rules[$key] = $rule; + } + + ksort($rules); + + /* For each MatchingRuleUse entry, add the attributes who use it to the + * MatchingRule in the $rules array.*/ + $raw = $this->getRawSchema($method,'matchingRuleUse'); + + if ($raw != false) { + foreach ($raw as $line) { + if (is_null($line) || ! strlen($line)) + continue; + + $rule_use = new MatchingRuleUse($line); + $key = $rule_use->getName(); + + if (isset($rules[$key])) + $rules[$key]->setUsedByAttrs($rule_use->getUsedByAttrs()); + } + + } else { + /* No MatchingRuleUse entry in the subschema, so brute-forcing + * the reverse-map for the "$rule->getUsedByAttrs()" data.*/ + $sattrs = $this->SchemaAttributes($method,$dn); + if (is_array($sattrs)) + foreach ($sattrs as $attr) { + $rule_key = strtolower($attr->getEquality()); + + if (isset($rules[$rule_key])) + $rules[$rule_key]->addUsedByAttr($attr->getName(false)); + } + } + + $return = $rules; + + # cache the schema to prevent multiple schema fetches from LDAP server + set_cached_item($this->index,'schema','matchingrules',$return); + } + + if (DEBUG_ENABLED) + debug_log('Returning (%s)',25,0,__FILE__,__LINE__,__METHOD__,$return); + + return $return; + } + + /** + * Returns an array of Syntax objects that this LDAP server uses mapped to + * their descriptions. The key of each entry is the OID of the Syntax. + */ + public function SchemaSyntaxes($method=null,$dn='') { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',25,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # Set default return + $return = null; + + if ($return = get_cached_item($this->index,'schema','syntaxes')) { + if (DEBUG_ENABLED) + debug_log('Returning CACHED [%s] (%s).',25,0,__FILE__,__LINE__,__METHOD__,$this->index,'syntaxes'); + + return $return; + } + + $raw = $this->getRawSchema($method,'ldapSyntaxes',$dn); + + if ($raw) { + # build the array of attributes + $return = array(); + + foreach ($raw as $line) { + if (is_null($line) || ! strlen($line)) + continue; + + $syntax = new Syntax($line); + $key = strtolower(trim($syntax->getOID())); + + if (! $key) + continue; + + $return[$key] = $syntax; + } + + ksort($return); + + # cache the schema to prevent multiple schema fetches from LDAP server + set_cached_item($this->index,'schema','syntaxes',$return); + } + + if (DEBUG_ENABLED) + debug_log('Returning (%s)',25,0,__FILE__,__LINE__,__METHOD__,$return); + + return $return; + } + + /** + * This function determines if the specified attribute is contained in the force_may list + * as configured in config.php. + * + * @return boolean True if the specified attribute is configured to be force as a may attribute + */ + function isForceMay($attr_name) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + return in_array($attr_name,unserialize(strtolower(serialize($this->getValue('server','force_may'))))); + } + + /** + * Much like getDNAttrValues(), but only returns the values for + * one attribute of an object. Example calls: + * + * + * print_r(getDNAttrValue('cn=Bob,ou=people,dc=example,dc=com','sn')); + * Array ( + * [0] => Smith + * ) + * + * print_r(getDNAttrValue('cn=Bob,ou=people,dc=example,dc=com','objectClass')); + * Array ( + * [0] => top + * [1] => person + * ) + * + * + * @param string The distinguished name (DN) of the entry whose attributes/values to fetch. + * @param string The attribute whose value(s) to return (ie, "objectClass", "cn", "userPassword") + * @param string Which connection method resource to use + * @param constant For aliases and referrals, this parameter specifies whether to + * follow references to the referenced DN or to fetch the attributes for + * the referencing DN. See http://php.net/ldap_search for the 4 valid + * options. + * @return array + * @see getDNAttrValues + * @todo Caching these values may be problematic with multiple calls and different deref values. + */ + public function getDNAttrValue($dn,$attr,$method=null,$deref=LDAP_DEREF_NEVER) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # Ensure our attr is in lowercase + $attr = strtolower($attr); + + $values = $this->getDNAttrValues($dn,$method,$deref); + + if (isset($values[$attr])) + return $values[$attr]; + else + return array(); + } + + /** + * Gets the attributes/values of an entry. Returns an associative array whose + * keys are attribute value names and whose values are arrays of values for + * said attribute. + * + * Optionally, callers may specify true for the parameter + * $lower_case_attr_names to force all keys in the associate array (attribute + * names) to be lower case. + * + * Example of its usage: + * + * print_r(getDNAttrValues('cn=Bob,ou=pepole,dc=example,dc=com') + * Array ( + * [objectClass] => Array ( + * [0] => person + * [1] => top + * ) + * [cn] => Array ( + * [0] => Bob + * ) + * [sn] => Array ( + * [0] => Jones + * ) + * [dn] => Array ( + * [0] => cn=Bob,ou=pepole,dc=example,dc=com + * ) + * ) + * + * + * @param string The distinguished name (DN) of the entry whose attributes/values to fetch. + * @param string Which connection method resource to use + * @param constant For aliases and referrals, this parameter specifies whether to + * follow references to the referenced DN or to fetch the attributes for + * the referencing DN. See http://php.net/ldap_search for the 4 valid + * options. + * @return array + * @see getDNSysAttrs + * @see getDNAttrValue + */ + public function getDNAttrValues($dn,$method=null,$deref=LDAP_DEREF_NEVER,$attrs=array('*','+'),$nocache=false) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + static $CACHE; + + $cacheindex = null; + $method = $this->getMethod($method); + + if (in_array('*',$attrs) && in_array('+',$attrs)) + $cacheindex = '&'; + elseif (in_array('+',$attrs)) + $cacheindex = '+'; + elseif (in_array('*',$attrs)) + $cacheindex = '*'; + + if (! $nocache && ! is_null($cacheindex) && isset($CACHE[$this->index][$method][$dn][$cacheindex])) { + $results = $CACHE[$this->index][$method][$dn][$cacheindex]; + + if (DEBUG_ENABLED) + debug_log('Returning (%s)',17,0,__FILE__,__LINE__,__METHOD__,$results); + + } else { + $query = array(); + $query['base'] = $this->escapeDN($dn); + $query['scope'] = 'base'; + $query['deref'] = $deref; + $query['attrs'] = $attrs; + $query['baseok'] = true; + $results = $this->query($query,$method); + + if (count($results)) + $results = array_pop($results); + + $results = array_change_key_case($results); + + # Covert all our result key values to an array + foreach ($results as $key => $values) + if (! is_array($results[$key])) + $results[$key] = array($results[$key]); + + # Finally sort the results + ksort($results); + + if (! is_null($cacheindex) && count($results)) + $CACHE[$this->index][$method][$dn][$cacheindex] = $results; + } + + return $results; + } + + /** + * Returns true if the attribute specified is required to take as input a DN. + * Some examples include 'distinguishedName', 'member' and 'uniqueMember'. + * + * @param string $attr_name The name of the attribute of interest (case insensitive) + * @return boolean + */ + function isDNAttr($attr_name,$method=null) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # Simple test first + $dn_attrs = array('aliasedObjectName'); + foreach ($dn_attrs as $dn_attr) + if (strcasecmp($attr_name,$dn_attr) == 0) + return true; + + # Now look at the schema OID + $sattr = $this->getSchemaAttribute($attr_name); + if (! $sattr) + return false; + + $syntax_oid = $sattr->getSyntaxOID(); + if ('1.3.6.1.4.1.1466.115.121.1.12' == $syntax_oid) + return true; + if ('1.3.6.1.4.1.1466.115.121.1.34' == $syntax_oid) + return true; + + $syntaxes = $this->SchemaSyntaxes($method); + if (! isset($syntaxes[$syntax_oid])) + return false; + + $syntax_desc = $syntaxes[ $syntax_oid ]->getDescription(); + if (strpos(strtolower($syntax_desc),'distinguished name')) + return true; + + return false; + } + + /** + * Used to determine if the specified attribute is indeed a jpegPhoto. If the + * specified attribute is one that houses jpeg data, true is returned. Otherwise + * this function returns false. + * + * @param string $attr_name The name of the attribute to test. + * @return boolean + * @see draw_jpeg_photo + */ + function isJpegPhoto($attr_name) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # easy quick check + if (! strcasecmp($attr_name,'jpegPhoto') || ! strcasecmp($attr_name,'photo')) + return true; + + # go to the schema and get the Syntax OID + $sattr = $this->getSchemaAttribute($attr_name); + if (! $sattr) + return false; + + $oid = $sattr->getSyntaxOID(); + $type = $sattr->getType(); + + if (! strcasecmp($type,'JPEG') || ($oid == '1.3.6.1.4.1.1466.115.121.1.28')) + return true; + + return false; + } + + /** + * Given an attribute name and server ID number, this function returns + * whether the attrbiute contains boolean data. This is useful for + * developers who wish to display the contents of a boolean attribute + * with a drop-down. + * + * @param string $attr_name The name of the attribute to test. + * @return boolean + */ + function isAttrBoolean($attr_name) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $type = ($sattr = $this->getSchemaAttribute($attr_name)) ? $sattr->getType() : null; + + if (! strcasecmp('boolean',$type) || + ! strcasecmp('isCriticalSystemObject',$attr_name) || + ! strcasecmp('showInAdvancedViewOnly',$attr_name)) + return true; + + else + return false; + } + + /** + * Given an attribute name and server ID number, this function returns + * whether the attribute may contain binary data. This is useful for + * developers who wish to display the contents of an arbitrary attribute + * but don't want to dump binary data on the page. + * + * @param string $attr_name The name of the attribute to test. + * @return boolean + * + * @see isJpegPhoto + */ + function isAttrBinary($attr_name) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + /** + * Determining if an attribute is binary can be an expensive operation. + * We cache the results for each attr name on each server in the $attr_cache + * to speed up subsequent calls. The $attr_cache looks like this: + * + * Array + * 0 => Array + * 'objectclass' => false + * 'cn' => false + * 'usercertificate' => true + * 1 => Array + * 'jpegphoto' => true + * 'cn' => false + */ + + static $attr_cache; + + $attr_name = strtolower($attr_name); + + if (isset($attr_cache[$this->index][$attr_name])) + return $attr_cache[$this->index][$attr_name]; + + if ($attr_name == 'userpassword') { + $attr_cache[$this->index][$attr_name] = false; + return false; + } + + # Quick check: If the attr name ends in ";binary", then it's binary. + if (strcasecmp(substr($attr_name,strlen($attr_name) - 7),';binary') == 0) { + $attr_cache[$this->index][$attr_name] = true; + return true; + } + + # See what the server schema says about this attribute + $sattr = $this->getSchemaAttribute($attr_name); + if (! is_object($sattr)) { + + /* Strangely, some attributeTypes may not show up in the server + * schema. This behavior has been observed in MS Active Directory.*/ + $type = null; + $syntax = null; + + } else { + $type = $sattr->getType(); + $syntax = $sattr->getSyntaxOID(); + } + + if (strcasecmp($type,'Certificate') == 0 || + strcasecmp($type,'Binary') == 0 || + strcasecmp($attr_name,'usercertificate') == 0 || + strcasecmp($attr_name,'usersmimecertificate') == 0 || + strcasecmp($attr_name,'networkaddress') == 0 || + strcasecmp($attr_name,'objectGUID') == 0 || + strcasecmp($attr_name,'objectSID') == 0 || + strcasecmp($attr_name,'auditingPolicy') == 0 || + strcasecmp($attr_name,'jpegPhoto') == 0 || + strcasecmp($attr_name,'krbExtraData') == 0 || + strcasecmp($attr_name,'krbPrincipalKey') == 0 || + $syntax == '1.3.6.1.4.1.1466.115.121.1.10' || + $syntax == '1.3.6.1.4.1.1466.115.121.1.28' || + $syntax == '1.3.6.1.4.1.1466.115.121.1.5' || + $syntax == '1.3.6.1.4.1.1466.115.121.1.8' || + $syntax == '1.3.6.1.4.1.1466.115.121.1.9' + ) { + + $attr_cache[$this->index][$attr_name] = true; + return true; + + } else { + $attr_cache[$this->index][$attr_name] = false; + return false; + } + } + + /** + * This function will test if a user is a member of a group. + * + * Inputs: + * @param string $user membership value that is being checked + * @param dn $group DN to see if user is a member + * @return bool true|false + */ + function userIsMember($user,$group) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $user = strtolower($user); + $group = $this->getDNAttrValues($group); + + # If you are using groupOfNames objectClass + if (array_key_exists('member',$group) && ! is_array($group['member'])) + $group['member'] = array($group['member']); + + if (array_key_exists('member',$group) && + in_array($user,arrayLower($group['member']))) + + return true; + + # If you are using groupOfUniqueNames objectClass + if (array_key_exists('uniquemember',$group) && ! is_array($group['uniquemember'])) + $group['uniquemember'] = array($group['uniquemember']); + + if (array_key_exists('uniquemember',$group) && + in_array($user,arrayLower($group['uniquemember']))) + + return true; + + return false; + } + + /** + * This function will determine if the user is allowed to login based on a filter + */ + protected function userIsAllowedLogin($dn) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $dn = trim(strtolower($dn)); + + if (! $this->getValue('login','allowed_dns')) + return true; + + foreach ($this->getValue('login','allowed_dns') as $login_allowed_dn) { + if (DEBUG_ENABLED) + debug_log('Working through (%s)',80,0,__FILE__,__LINE__,__METHOD__,$login_allowed_dn); + + /* Check if $login_allowed_dn is an ldap search filter + * Is first occurence of 'filter=' (case ensitive) at position 0 ? */ + if (preg_match('/^\([&|]\(/',$login_allowed_dn)) { + $query = array(); + $query['filter'] = $login_allowed_dn; + $query['attrs'] = array('dn'); + + foreach($this->getBaseDN() as $base_dn) { + $query['base'] = $base_dn; + + $results = $this->query($query,null); + + if (DEBUG_ENABLED) + debug_log('Search, Filter [%s], BaseDN [%s] Results [%s]',16,0,__FILE__,__LINE__,__METHOD__, + $query['filter'],$query['base'],$results); + + if ($results) { + $dn_array = array(); + + foreach ($results as $result) + array_push($dn_array,$result['dn']); + + $dn_array = array_unique($dn_array); + + if (count($dn_array)) + foreach ($dn_array as $result_dn) { + if (DEBUG_ENABLED) + debug_log('Comparing with [%s]',80,0,__FILE__,__LINE__,__METHOD__,$result_dn); + + # Check if $result_dn is a user DN + if (strcasecmp($dn,trim(strtolower($result_dn))) == 0) + return true; + + # Check if $result_dn is a group DN + if ($this->userIsMember($dn,$result_dn)) + return true; + } + } + } + } + + # Check if $login_allowed_dn is a user DN + if (strcasecmp($dn,trim(strtolower($login_allowed_dn))) == 0) + return true; + + # Check if $login_allowed_dn is a group DN + if ($this->userIsMember($dn,$login_allowed_dn)) + return true; + } + + return false; + } +} +?> diff --git a/lib/ds_ldap_pla.php b/lib/ds_ldap_pla.php new file mode 100644 index 0000000..7ece393 --- /dev/null +++ b/lib/ds_ldap_pla.php @@ -0,0 +1,659 @@ +default->appearance['password_hash'] = array( + 'desc'=>'Default HASH to use for passwords', + 'default'=>'md5'); + + $this->default->appearance['show_create'] = array( + 'desc'=>'Whether to show the "Create new Entry here" in the tree browser', + 'default'=>true); + + $this->default->appearance['open_tree'] = array( + 'desc'=>'Whether to initially open each tree', + 'default'=>false); + + $this->default->login['fallback_dn'] = array( + 'desc'=>'If the attribute base login fails, see if a DN was entered', + 'default'=>false); + + $this->default->query['disable_default'] = array( + 'desc'=>'Configuration to disable the default query template', + 'default'=>false); + + $this->default->query['custom_only'] = array( + 'desc'=>'Configuration to force the usage of custom query templates', + 'default'=>false); + + $this->default->server['branch_rename'] = array( + 'desc'=>'Enable renaming of branches', + 'default'=>false); + + $this->default->server['custom_attrs'] = array( + 'desc'=>'Custom operational attributes to be treated as regular attributes', + 'default'=>array('')); + + $this->default->server['custom_sys_attrs'] = array( + 'desc'=>'Custom operational attributes to be treated as internal attributes', + 'default'=>array('+')); + + $this->default->server['jpeg_attributes'] = array( + 'desc'=>'Additional attributes to treat as Jpeg Attributes', + 'default'=>array()); + + # This was added in case the LDAP server doesnt provide them with a base +,* query. + $this->default->server['root_dse_attributes'] = array( + 'desc'=>'RootDSE attributes for use when displaying server info', + 'default'=>array( + 'namingContexts', + 'subschemaSubentry', + 'altServer', + 'supportedExtension', + 'supportedControl', + 'supportedSASLMechanisms', + 'supportedLDAPVersion', + 'currentTime', + 'dsServiceName', + 'defaultNamingContext', + 'schemaNamingContext', + 'configurationNamingContext', + 'rootDomainNamingContext', + 'supportedLDAPPolicies', + 'highestCommittedUSN', + 'dnsHostName', + 'ldapServiceName', + 'serverName', + 'supportedCapabilities', + 'changeLog', + 'tlsAvailableCipherSuites', + 'tlsImplementationVersion', + 'supportedSASLMechanisms', + 'dsaVersion', + 'myAccessPoint', + 'dseType', + '+', + '*' + )); + + $this->default->server['force_may'] = array( + 'desc'=>'Force server MUST attributes as MAY attributes', + 'default'=>array( + )); + + # Settings for auto_number + $this->default->auto_number['enable'] = array( + 'desc'=>'Enable the AUTO UID feature', + 'default'=>true); + + $this->default->auto_number['mechanism'] = array( + 'desc'=>'Mechanism to use to search for automatic numbers', + 'default'=>'search'); + + $this->default->auto_number['search_base'] = array( + 'desc'=>'Base DN to use for search mechanisms', + 'default'=>null); + + $this->default->auto_number['min'] = array( + 'desc'=>'Minimum number to start with', + 'default'=>array('uidNumber'=>1000,'gidNumber'=>500)); + + $this->default->auto_number['dn'] = array( + 'desc'=>'DN to use when evaluating numbers', + 'default'=>null); + + $this->default->auto_number['pass'] = array( + 'desc'=>'Password for DN to use when evaluating numbers', + 'default'=>null); + + $this->default->unique['attrs'] = array( + 'desc'=>'Attributes to check for uniqueness before allowing updates', + 'default'=>array('mail','uid','uidNumber')); + + $this->default->unique['dn'] = array( + 'desc'=>'DN to use when evaluating attribute uniqueness', + 'default'=>null); + + $this->default->unique['pass'] = array( + 'desc'=>'Password for DN to use when evaluating attribute uniqueness', + 'default'=>null); + } + + public function __get($key) { + switch ($key) { + case 'name': + return $this->getValue('server','name'); + + default: + system_message(array( + 'title'=>_('Unknown request for Object value.'), + 'body'=>sprintf(_('Attempt to obtain value %s from %s'),$key,get_class($this)), + 'type'=>'error')); + } + } + + /** + * Gets whether the admin has configured phpLDAPadmin to show the "Create New" link in the tree viewer. + * + * $servers->setValue('appearance','show_create',true|false); + * + * If NOT set, then default to show the Create New item. + * If IS set, then return the value (it should be true or false). + * + * The entry creation command must be available. + * + * $config->custom->commands['script'] = array('create' => true); + * + * + * @return boolean true if the feature is enabled and false otherwise. + */ + function isShowCreateEnabled() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (! $_SESSION[APPCONFIG]->isCommandAvailable('script','create')) + return false; + else + return $this->getValue('appearance','show_create'); + } + + /** + * Fetch whether the user has configured a certain server login to be non anonymous + * + * + * $servers->setValue('login','anon_bind',true|false); + * + * + * @return boolean + */ + public function isAnonBindAllowed() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # If only_login_allowed_dns is set, then we cant have anonymous. + if (count($this->getValue('login','allowed_dns')) > 0) + $return = false; + else + $return = $this->getValue('login','anon_bind'); + + if (DEBUG_ENABLED) + debug_log('Returning (%s)',17,0,__FILE__,__LINE__,__METHOD__,$return); + + return $return; + } + + /** + * Returns true if the user has configured the specified server to enable branch (non-leaf) renames. + * + * This is configured in config.php thus: + * + * $servers->setValue('server','branch_rename',true|false); + * + * + * @return boolean + */ + function isBranchRenameEnabled() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + return $this->getValue('server','branch_rename'); + } + + /** + * Determines if an attribute's value can contain multiple lines. Attributes that fall + * in this multi-line category may be configured in config.php. Hence, this function + * accesses the global variable $_SESSION[APPCONFIG]->custom->appearance['multi_line_attributes']; + * + * Usage example: + * + * if ($ldapserver->isMultiLineAttr('postalAddress')) + * echo ''; + * else + * echo ''; + * + * + * @param string The name of the attribute of interested (case insensivite) + * @param string (optional) The current value of the attribute (speeds up the process by searching for carriage returns already in the attribute value) + * @return boolean + */ + function isMultiLineAttr($attr_name,$val=null) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # Set default return + $return = false; + + # First, check the optional val param for a \n or a \r + if (! is_null($val) && (strpos($val,"\n") || strpos($val,"\r"))) + $return = true; + + # Next, compare strictly by name first + else + foreach ($_SESSION[APPCONFIG]->getValue('appearance','multi_line_attributes') as $multi_line_attr_name) + if (strcasecmp($multi_line_attr_name,$attr_name) == 0) { + $return = true; + break; + } + + # If unfound, compare by syntax OID + if (! $return) { + $sattr = $this->getSchemaAttribute($attr_name); + + if ($sattr) { + $syntax_oid = $sattr->getSyntaxOID(); + + if ($syntax_oid) + foreach ($_SESSION[APPCONFIG]->getValue('appearance','multi_line_syntax_oids') as $multi_line_syntax_oid) + if ($multi_line_syntax_oid == $syntax_oid) { + $return = true; + break; + } + } + } + + if (DEBUG_ENABLED) + debug_log('Returning (%s)',17,0,__FILE__,__LINE__,__METHOD__,$return); + + return $return; + } + + /** + * Returns true if the specified attribute is configured according to + * the test enabled in config.php + * + * @param string The name of the attribute to test. + * @param array The attributes to test against. + * @param dn A DN that is exempt from these tests. + * @return boolean + */ + private function isAttrTest($attr,$attrs,$except_dn) { + $attr = trim($attr); + if (! trim($attr) || ! count($attrs)) + return false; + + # Is the user excluded? + if ($except_dn && $this->userIsMember($this->getLogin(),$except_dn)) + return false; + + foreach ($attrs as $attr_name) + if (strcasecmp($attr,trim($attr_name)) == 0) + return true; + + return false; + } + + /** + * Returns true if the specified attribute is configured as read only + * in config.php. + * Attributes are configured as read-only in config.php thus: + * + * $config->custom->appearance['readonly_attrs'] = array('objectClass'); + * + * + * @param string The name of the attribute to test. + * @return boolean + */ + public function isAttrReadOnly($attr) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $attrs = $_SESSION[APPCONFIG]->getValue('appearance','readonly_attrs'); + $except_dn = $_SESSION[APPCONFIG]->getValue('appearance','readonly_attrs_exempt'); + + return $this->isAttrTest($attr,$attrs,$except_dn); + } + + /** + * Returns true if the specified attribute is configured as hidden + * in config.php. + * Attributes are configured as hidden in config.php thus: + * + * $config->custom->appearance['hide_attrs'] = array('objectClass'); + * + * + * @param string The name of the attribute to test. + * @return boolean + */ + public function isAttrHidden($attr) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $attrs = $_SESSION[APPCONFIG]->getValue('appearance','hide_attrs'); + $except_dn = $_SESSION[APPCONFIG]->getValue('appearance','hide_attrs_exempt'); + + return $this->isAttrTest($attr,$attrs,$except_dn); + } + + /** + * Add objects + */ + public function add($dn,$entry_array,$method=null) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + foreach ($entry_array as $attr => $val) + $entry_array[$attr] = dn_unescape($val); + + $result = false; + + # Check our unique attributes. + if (! $this->checkUniqueAttrs($dn,$entry_array)) + return false; + + if (run_hook('pre_entry_create',array('server_id'=>$this->index,'method'=>$method,'dn'=>$dn,'attrs'=>$entry_array))) { + $result = @ldap_add($this->connect($method),dn_escape($dn),$entry_array); + + if ($result) { + # Update the tree + $tree = get_cached_item($this->index,'tree'); + + # If we created the base, delete it, then add it back + if (get_request('create_base')) + $tree->delEntry($dn); + + $tree->addEntry($dn); + + set_cached_item($this->index,'tree','null',$tree); + + run_hook('post_entry_create',array('server_id'=>$this->index,'method'=>$method,'dn'=>$dn,'attrs'=>$entry_array)); + + } else { + system_message(array( + 'title'=>_('Could not add the object to the LDAP server.'), + 'body'=>ldap_error_msg($this->getErrorMessage(null),$this->getErrorNum(null)), + 'type'=>'error')); + } + } + + return $result; + } + + /** + * Delete objects + */ + public function delete($dn,$method=null) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $result = false; + + if (run_hook('pre_entry_delete',array('server_id'=>$this->index,'method'=>$method,'dn'=>$dn))) { + $result = @ldap_delete($this->connect($method),dn_escape($dn)); + + if ($result) { + # Update the tree + $tree = get_cached_item($this->index,'tree'); + $tree->delEntry($dn); + + set_cached_item($this->index,'tree','null',$tree); + + run_hook('post_entry_delete',array('server_id'=>$this->index,'method'=>$method,'dn'=>$dn)); + } + } + + return $result; + } + + /** + * Rename objects + */ + public function rename($dn,$new_rdn,$container,$deleteoldrdn,$method=null) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $result = false; + + if (run_hook('pre_entry_rename',array('server_id'=>$this->index,'method'=>$method,'dn'=>$dn,'rdn'=>$new_rdn,'container'=>$container))) { + $result = @ldap_rename($this->connect($method),$dn,$new_rdn,$container,$deleteoldrdn); + + if ($result) { + # Update the tree + $tree = get_cached_item($this->index,'tree'); + $newdn = sprintf('%s,%s',$new_rdn,$container); + $tree->renameEntry($dn,$newdn); + + set_cached_item($this->index,'tree','null',$tree); + + run_hook('post_entry_rename',array('server_id'=>$this->index,'method'=>$method,'dn'=>$dn,'rdn'=>$new_rdn,'container'=>$container)); + } + } + + return $result; + } + + /** + * Modify objects + */ + public function modify($dn,$attrs,$method=null) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # Check our unique attributes. + if (! $this->checkUniqueAttrs($dn,$attrs)) + return false; + + $result = false; + $summary = array(); + $current_attrs = $this->getDNAttrValues($dn,$method,LDAP_DEREF_NEVER,array('*')); + + # Go through our attributes and call our hooks for each attribute changing its value + foreach ($attrs as $attr => $values) { + # For new attributes + if (count($values) && ! isset($current_attrs[$attr])) { + if (! run_hook('pre_attr_add', + array('server_id'=>$this->index,'method'=>$method,'dn'=>$dn,'attr'=>$attr,'newvalue'=>$values))) { + + unset($attrs[$attr]); + system_message(array( + 'title'=>_('Attribute not added'), + 'body'=>sprintf('%s (%s)',_('Hook pre_attr_add prevented attribute from being added'),$attr), + 'type'=>'warn')); + + } else + $summary['add'][$attr]['new'] = $values; + + # For modify attributes + } elseif (count($values)) { + if (! run_hook('pre_attr_modify', + array('server_id'=>$this->index,'method'=>$method,'dn'=>$dn,'attr'=>$attr,'oldvalue'=>$current_attrs[$attr],'newvalue'=>$values))) { + + unset($attrs[$attr]); + system_message(array( + 'title'=>_('Attribute not modified'), + 'body'=>sprintf('%s (%s)',_('Hook pre_attr_modify prevented attribute from being modified'),$attr), + 'type'=>'warn')); + + } else { + $summary['modify'][$attr]['new'] = $values; + $summary['modify'][$attr]['old'] = $current_attrs[$attr]; + } + + # For delete attributes + } else { + if (! run_hook('pre_attr_delete', + array('server_id'=>$this->index,'method'=>$method,'dn'=>$dn,'attr'=>$attr,'oldvalue'=>$current_attrs[$attr]))) { + + unset($attrs[$attr]); + system_message(array( + 'title'=>_('Attribute not deleted'), + 'body'=>sprintf('%s (%s)',_('Hook pre_attr_delete prevented attribute from being deleted'),$attr), + 'type'=>'warn')); + + } else + $summary['delete'][$attr]['old'] = $current_attrs[$attr]; + } + } + + if (! count($attrs)) + return false; + + if (run_hook('pre_entry_modify',array('server_id'=>$this->index,'method'=>$method,'dn'=>$dn,'attrs'=>$attrs))) { + $result = @ldap_modify($this->connect($method),$dn,$attrs); + + if ($result) { + run_hook('post_entry_modify',array('server_id'=>$this->index,'method'=>$method,'dn'=>$dn,'attrs'=>$attrs)); + + foreach (array('add','modify','delete') as $mode) + if (isset($summary[$mode])) + foreach ($summary[$mode] as $attr => $values) + switch ($mode) { + case 'add': + run_hook(sprintf('post_attr_%s',$mode), + array('server_id'=>$this->index,'method'=>$method,'dn'=>$dn,'attr'=>$attr,'newvalue'=>$values['new'])); + break; + + case 'modify': + run_hook(sprintf('post_attr_%s',$mode), + array('server_id'=>$this->index,'method'=>$method,'dn'=>$dn,'attr'=>$attr,'oldvalue'=>$values['old'],'newvalue'=>$values['new'])); + break; + + case 'delete': + run_hook(sprintf('post_attr_%s',$mode), + array('server_id'=>$this->index,'method'=>$method,'dn'=>$dn,'attr'=>$attr,'oldvalue'=>$values['old'])); + break; + + default: + debug_dump_backtrace(sprintf('Unkown mode %s',$mode),1); + } + } else { + system_message(array( + 'title'=>_('Could not perform ldap_modify operation.'), + 'body'=>ldap_error_msg($this->getErrorMessage($method),$this->getErrorNum($method)), + 'type'=>'error')); + } + } + + return $result; + } + + /** + * Returns true if the specified attribute is configured as unique + * in config.php. + * Attributes are configured as hidden in config.php thus: + * + * $servers->setValue('unique','attrs',array('mail','uid','uidNumber')); + * + * + * @param string $attr The name of the attribute to test. + * @return boolean + */ + public function isAttrUnique($attr) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # Should this attribute value be unique + if (in_array_ignore_case($attr,$this->getValue('unique','attrs'))) + return true; + else + return false; + } + + /** + * This function will check whether the value for an attribute being changed + * is already assigned to another DN. + * + * Returns the bad value, or null if all values are OK + * + * @param dn DN that is being changed + * @param string Attribute being changed + * @param string|array New values for the attribute + */ + public function checkUniqueAttrs($dn,$attrs) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # If none of the attributes are defined unique, we'll return immediately; + if (! $checkattrs = array_intersect(arrayLower($this->getValue('unique','attrs')),array_keys(array_change_key_case($attrs)))) + return true; + + # Check see and use our alternate uid_dn and password if we have it. + if (! $this->login($this->getValue('unique','dn'),$this->getValue('unique','pass'),'unique')) { + system_message(array( + 'title'=>_('UNIQUE invalid login/password'), + 'body'=>sprintf('%s (%s)',_('Unable to connect to LDAP server with the unique login/password, please check your configuration.'), + $this->getName()), + 'type'=>'warn')); + + return false; + } + + $query = array(); + + # Build our search filter to double check each attribute. + $query['filter'] = '(|'; + foreach ($checkattrs as $attr) + foreach ($attrs[$attr] as $val) + if ($val) + $query['filter'] .= sprintf('(%s=%s)',$attr,$val); + $query['filter'] .= ')'; + + $query['attrs'] = $checkattrs; + + # Search through our bases and see if we have match + foreach ($this->getBaseDN() as $base) { + $query['base'] = $base; + + # Do the search + $results = $this->query($query,'unique'); + + # If we have a match. + if (count($results)) + foreach ($results as $values) + # If one of the attributes is owned to somebody else, then we may as well die here. + if ($values['dn'] != $dn) { + $href = sprintf('cmd.php?cmd=query_engine&server_id=%s&filter=%s&scope=sub&query=none&format=list&search=true',$this->index,$query['filter']); + + system_message(array( + 'title'=>_('Attribute value would not be unique'), + 'body'=>sprintf('%s (%s)', + _('This update has been or will be cancelled, it would result in an attribute value not being unique. You might like to search the LDAP server for the offending entry.'), + htmlspecialchars($href), + _('Search')), + 'type'=>'warn')); + + return false; + } + } + + # If we get here, then it must be OK? + return true; + } + + /** + * Check if the session timeout has occured for this LDAP server. + */ + public function isSessionValid() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # If inactiveTime() returns a value, we need to check that it has not expired. + if (is_null($this->inactivityTime()) || ! $this->isLoggedIn()) + return true; + + # If session has expired + if ((isset($_SESSION['ACTIVITY'][$this->getIndex()])) && ($_SESSION['ACTIVITY'][$this->getIndex()] < time())) { + $this->logout(); + unset($_SESSION['ACTIVITY'][$this->getIndex()]); + + return false; + } + + $_SESSION['ACTIVITY'][$this->getIndex()] = $this->inactivityTime(); + return true; + } +} +?> diff --git a/lib/emuhash_functions.php b/lib/emuhash_functions.php new file mode 100644 index 0000000..7818f7f --- /dev/null +++ b/lib/emuhash_functions.php @@ -0,0 +1,112 @@ + + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + ******************************************************************************/ + +/******************************************************************************/ +/* Do we have builtin mhash support in this PHP version ? */ +/******************************************************************************/ + +if (! function_exists('mhash') && ! function_exists('mhash_keygen_s2k')) { + $emuhash_emu = array(); + + if (! isset($emuhash_emu['openssl'])) + $emuhash_emu['openssl'] = '/usr/bin/openssl'; + + # Don't create mhash functions if we don't have a working openssl + if (! file_exists($emuhash_emu['openssl'])) + unset($emuhash_emu['openssl']); + + elseif (function_exists('is_executable') && ! is_executable($emuhash_emu['openssl'])) + unset($emuhash_emu['openssl']); + + else { + if (! isset($emuhash_emu['tmpdir'])) + $emuhash_emu['tmpdir'] = '/tmp'; + +/******************************************************************************/ +/* Define constants used in the mhash emulation code. */ +/******************************************************************************/ + + define('MHASH_MD5','md5'); + define('MHASH_SHA1','sha1'); + define('MHASH_RIPEMD160','rmd160'); + +/******************************************************************************/ +/* Functions to emulate parts of php-mash. */ +/******************************************************************************/ + + function openssl_hash($openssl_hash_id,$password_clear) { + global $emuhash_emu; + + if (PHP_VERSION < 6) { + $current_magic_quotes = @get_magic_quotes_runtime(); + @set_magic_quotes_runtime(0); + } + + $tmpfile = tempnam($emuhash_emu['tmpdir'],'emuhash'); + $pwhandle = fopen($tmpfile,'w'); + + if (! $pwhandle) + error(sprintf('Unable to create a temporary file %s to create hashed password',$tmpfile) ,'error','index.php'); + + fwrite($pwhandle,$password_clear); + fclose($pwhandle); + $cmd = sprintf('%s %s -binary <%s',$emuhash_emu['openssl'],$openssl_hash_id,$tmpfile); + $prog = popen($cmd,'r'); + $pass = fread($prog,1024); + pclose($prog); + unlink($tmpfile); + + if (PHP_VERSION < 6) + @set_magic_quotes_runtime($current_magic_quotes); + + return $pass; + } + + function mhash($hash_id,$password_clear) { + switch($hash_id) { + case MHASH_MD5: + $emuhash = openssl_hash(MHASH_MD5,$password_clear); + break; + + case MHASH_SHA1: + $emuhash = openssl_hash(MHASH_SHA1,$password_clear); + break; + + case MHASH_RIPEMD160: + $emuhash = openssl_hash(MHASH_RIPEMD160,$password_clear); + break; + + default: + $emuhash = FALSE; + } + + return $emuhash; + } + + function mhash_keygen_s2k($hash_id,$password_clear,$salt,$bytes) { + return substr(pack('H*',bin2hex(mhash($hash_id,($salt.$password_clear)))),0,$bytes); + } + } +} +?> diff --git a/lib/export_functions.php b/lib/export_functions.php new file mode 100644 index 0000000..d98df2c --- /dev/null +++ b/lib/export_functions.php @@ -0,0 +1,643 @@ +server_id = $server_id; + $this->template_id = $template_id; + + $this->accept(); + } + + static function types() { + $type = array(); + + $details = ExportCSV::getType(); + $type[$details['type']] = $details; + $details = ExportDSML::getType(); + $type[$details['type']] = $details; + $details = ExportLDIF::getType(); + $type[$details['type']] = $details; + $details = ExportVCARD::getType(); + $type[$details['type']] = $details; + + return $type; + } + + private function accept() { + switch($this->template_id) { + case 'CSV': + $this->template = new ExportCSV(); + break; + + case 'DSML': + $this->template = new ExportDSML(); + break; + + case 'LDIF': + $this->template = new ExportLDIF(); + break; + + case 'VCARD': + $this->template = new ExportVCARD(); + break; + + default: + system_message(array( + 'title'=>sprintf('%s %s',_('Unknown Export Type'),$this->template_id), + 'body'=>_('phpLDAPadmin has not been configured for that export type'), + 'type'=>'warn'),'index.php'); + die(); + } + + $this->template->accept(); + } + + public function getTemplate() { + return $this->template; + } +} + +/** + * Export Class + * + * This abstract classes provides all the common methods and variables for the + * custom export classes. + * + * @package phpLDAPadmin + * @subpackage Export + */ +abstract class Export { + # Line Break + protected $br; + # Compress the output + protected $compress; + # Export Results + protected $results; + protected $resultsdata; + protected $items = 0; + + /** + * Return this LDAP Server object + * + * @return object DataStore Server + */ + protected function getServer() { + return $_SESSION[APPCONFIG]->getServer($this->getServerID()); + } + + /** + * Return the LDAP server ID + * + * @return int Server ID + */ + protected function getServerID() { + return get_request('server_id','REQUEST'); + } + + public function accept() { + $server = $this->getServer(); + + # Get the data to be exported + $query = array(); + $base = get_request('dn','REQUEST'); + $query['baseok'] = true; + $query['filter'] = get_request('filter','REQUEST',false,'objectclass=*'); + $query['scope'] = get_request('scope','REQUEST',false,'base'); + $query['deref'] = $_SESSION[APPCONFIG]->getValue('deref','export'); + $query['size_limit'] = 0; + $attrs = get_request('attributes','REQUEST'); + + $attrs = preg_replace('/\s+/','',$attrs); + if ($attrs) + $query['attrs'] = explode(',',$attrs); + else + $query['attrs'] = array('*'); + + if (get_request('sys_attr')) { + if (! in_array('*',$query['attrs'])) + array_push($query['attrs'],'*'); + array_push($query['attrs'],'+'); + } + + if (! $base) + $bases = $server->getBaseDN(); + else + $bases = array($base); + + foreach ($bases as $base) { + $query['base'] = $base; + + $time_start = utime(); + $this->results[$base] = $server->query($query,null); + $time_end = utime(); + + usort($this->results[$base],'pla_compare_dns'); + $this->resultsdata[$base]['time'] = round($time_end-$time_start,2); + + # If no result, there is a something wrong + if (! $this->results[$base] && $server->getErrorNum(null)) + system_message(array( + 'title'=>_('Encountered an error while performing search.'), + 'body'=>ldap_error_msg($server->getErrorMessage(null),$server->getErrorNum(null)), + 'type'=>'error')); + + $this->items += count($this->results[$base]); + } + + $this->resultsdata['scope'] = $query['scope']; + $this->resultsdata['filter'] = $query['filter']; + $this->resultsdata['attrs'] = $query['attrs']; + + # Other settings + switch (get_request('format','POST',false,'unix')) { + case 'win': + $this->br = "\r\n"; + break; + + case 'mac': + $this->br = "\r"; + break; + + case 'unix': + default: + $this->br = "\n"; + } + + if (get_request('compress','REQUEST') == 'on') + $this->compress = true; + } + + public function isCompressed() { + return $this->compress; + } + + protected function getHeader() { + $server = $this->getServer(); + $type = $this->getType(); + + $output = ''; + + $output .= sprintf('# %s %s %s%s',$type['description'],_('for'),implode('|',array_keys($this->results)),$this->br); + $output .= sprintf('# %s: %s (%s)%s',_('Server'),$server->getName(),$server->getValue('server','host'),$this->br); + $output .= sprintf('# %s: %s%s',_('Search Scope'),$this->resultsdata['scope'],$this->br); + $output .= sprintf('# %s: %s%s',_('Search Filter'),$this->resultsdata['filter'],$this->br); + $output .= sprintf('# %s: %s%s',_('Total Entries'),$this->items,$this->br); + $output .= sprintf('#%s',$this->br); + $output .= sprintf('# Generated by %s (%s) on %s%s',app_name(),get_href('web'),date('F j, Y g:i a'),$this->br); + $output .= sprintf('# Version: %s%s',app_version(),$this->br); + + $output .= $this->br; + + return $output; + } + + /** + * Helper method to check if the attribute value should be base 64 encoded. + * + * @param The string to check. + * @return boolean true if the string is safe ascii, false otherwise. + */ + protected function isSafeAscii($str) { + for ($i=0;$i 127) + return false; + + return true; + } +} + +/** + * Export entries to CSV + * + * @package phpLDAPadmin + * @subpackage Export + */ +class ExportCSV extends Export { + private $separator = ','; + private $qualifier = '"'; + private $multivalue_separator = ' | '; + private $escapeCode = '"'; + + static public function getType() { + return array('type'=>'CSV','description' => 'CSV (Spreadsheet)','extension'=>'csv'); + } + + function export() { + $server = $this->getServer(); + + /* Go thru and find all the attribute names first. This is needed, because, otherwise we have + * no idea as to which search attributes were actually populated with data */ + $headers = array('dn'); + $entries = array(); + foreach ($this->results as $base => $results) { + foreach ($results as $dndetails) { + array_push($entries,$dndetails); + + unset($dndetails['dn']); + foreach (array_keys($dndetails) as $key) + if (! in_array($key,$headers)) + array_push($headers,$key); + + } + } + + $output = ''; + $num_headers = count($headers); + + # Print out the headers + for ($i=0; $i<$num_headers; $i++) { + $output .= sprintf('%s%s%s',$this->qualifier,$headers[$i],$this->qualifier); + + if ($i < $num_headers-1) + $output .= $this->separator; + } + + # Drop out our DN header. + array_shift($headers); + $num_headers--; + + $output .= $this->br; + + # Loop on every entry + foreach ($entries as $index => $entry) { + $dn = $entry['dn']; + unset($entry['dn']); + $output .= sprintf('%s%s%s%s',$this->qualifier,$this->LdapEscape($dn),$this->qualifier,$this->separator); + + # Print the attributes + for ($j=0; $j<$num_headers; $j++) { + $attr = $headers[$j]; + $output .= $this->qualifier; + + if (array_key_exists($attr,$entry)) { + $binary_attribute = $server->isAttrBinary($attr) ? 1 : 0; + + if (! is_array($entry[$attr])) + $attr_values = array($entry[$attr]); + else + $attr_values = $entry[$attr]; + + $num_attr_values = count($attr_values); + + for ($i=0; $i<$num_attr_values; $i++) { + if ($binary_attribute) + $output .= base64_encode($attr_values[$i]); + else + $output .= $this->LdapEscape($attr_values[$i]); + + if ($i < $num_attr_values-1) + $output .= $this->multivalue_separator; + } + } + + $output .= $this->qualifier; + + if ($j < $num_headers-1) + $output .= $this->separator; + } + + $output .= $this->br; + } + + if ($this->compress) + return gzencode($output); + else + return $output; + } + + /** + * Function to escape data, where the qualifier happens to also + * be in the data. + */ + private function LdapEscape ($var) { + return str_replace($this->qualifier,$this->escapeCode.$this->qualifier,$var); + } +} + +/** + * Export entries to DSML v.1 + * + * @package phpLDAPadmin + * @subpackage Export + */ +class ExportDSML extends Export { + static public function getType() { + return array('type'=>'DSML','description' => _('DSML V.1 Export'),'extension'=>'xml'); + } + + /** + * Export entries to DSML format + */ + function export() { + $server = $this->getServer(); + + # Not very elegant, but do the job for the moment as we have just 4 level + $indent = array(); + $indent['dir'] = ' '; + $indent['ent'] = ' '; + $indent['att'] = ' '; + $indent['val'] = ' '; + + # Print declaration + $output = sprintf('%s',$this->br); + + # Print root element + $output .= sprintf('%s',$this->br); + + # Print info related to this export + $output .= sprintf('%s',$this->br); + $output .= $this->br; + + $output .= sprintf('%s%s',$indent['dir'],$this->br); + + # Sift through the entries. + $counter = 0; + foreach ($this->results as $base => $results) { + foreach ($results as $dndetails) { + $counter++; + + $dn = $dndetails['dn']; + unset($dndetails['dn']); + ksort($dndetails); + + # Display DN + $output .= sprintf('%s%s',$indent['ent'],htmlspecialchars($dn),$this->br); + + # Display the objectClass attributes first + if (isset($dndetails['objectClass'])) { + if (! is_array($dndetails['objectClass'])) + $dndetails['objectClass'] = array($dndetails['objectClass']); + + $output .= sprintf('%s%s',$indent['att'],$this->br); + + foreach ($dndetails['objectClass'] as $ocValue) + $output .= sprintf('%s%s%s',$indent['val'],$ocValue,$this->br); + + $output .= sprintf('%s%s',$indent['att'],$this->br); + unset($dndetails['objectClass']); + } + + # Display the attributes + foreach ($dndetails as $key => $attr) { + if (! is_array($attr)) + $attr = array($attr); + + $output .= sprintf('%s%s',$indent['att'],$key,$this->br); + + # If the attribute is binary, set the flag $binary_mode to true + $binary_mode = $server->isAttrBinary($key) ? 1 : 0; + + foreach ($attr as $value) + $output .= sprintf('%s%s%s', + $indent['val'],($binary_mode ? base64_encode($value) : htmlspecialchars($value)),$this->br); + + $output .= sprintf('%s%s',$indent['att'],$this->br); + } + + $output .= sprintf('%s%s',$indent['ent'],$this->br); + } + } + + $output .= sprintf('%s%s',$indent['dir'],$this->br); + $output .= sprintf('%s',$this->br); + + if ($this->compress) + return gzencode($output); + else + return $output; + } +} + +/** + * Export from LDAP using an LDIF format + * + * @package phpLDAPadmin + * @subpackage Export + */ +class ExportLDIF extends Export { + # The maximum length of the ldif line + private $line_length = 76; + + static public function getType() { + return array('type'=>'LDIF','description' => _('LDIF Export'),'extension'=>'ldif'); + } + + /** + * Export entries to LDIF format + */ + public function export() { + if (! $this->results) { + echo _('Nothing to export'); + return; + } + + $server = $this->getServer(); + + $output = $this->getHeader(); + + # Add our version. + $output .= 'version: 1'; + $output .= $this->br; + $output .= $this->br; + + # Sift through the entries. + $counter = 0; + foreach ($this->results as $base => $results) { + foreach ($results as $dndetails) { + $counter++; + + $dn = $dndetails['dn']; + unset($dndetails['dn']); + ksort($dndetails); + + $title_string = sprintf('# %s %s: %s%s',_('Entry'),$counter,$dn,$this->br); + + if (strlen($title_string) > $this->line_length-3) + $title_string = substr($title_string,0,$this->line_length-3).'...'.$this->br; + + $output .= $title_string; + + # Display dn + if ($this->isSafeAscii($dn)) + $output .= $this->multiLineDisplay(sprintf('dn: %s',$dn)); + else + $output .= $this->multiLineDisplay(sprintf('dn:: %s',base64_encode($dn))); + + # display the attributes + foreach ($dndetails as $key => $attr) { + if (! is_array($attr)) + $attr = array($attr); + + foreach ($attr as $value) + if (! $this->isSafeAscii($value) || $server->isAttrBinary($key)) + $output .= $this->multiLineDisplay(sprintf('%s:: %s',$key,base64_encode($value))); + else + $output .= $this->multiLineDisplay(sprintf('%s: %s',$key,$value)); + } + + $output .= $this->br; + } + } + + if ($this->compress) + return gzencode($output); + else + return $output; + } + + /** + * Helper method to wrap ldif lines + * + * @param The line to be wrapped if needed. + */ + private function multiLineDisplay($str) { + $length_string = strlen($str); + $length_max = $this->line_length; + + $output = ''; + while ($length_string > $length_max) { + $output .= substr($str,0,$length_max).$this->br.' '; + $str = substr($str,$length_max,$length_string); + $length_string = strlen($str); + + /* Need to do minus one to align on the right + * the first line with the possible following lines + * as these will have an extra space. */ + $length_max = $this->line_length-1; + } + + $output .= $str.$this->br; + + return $output; + } +} + +/** + * Export entries to VCARD v2.1 + * + * @package phpLDAPadmin + * @subpackage Export + */ +class ExportVCARD extends Export { + static public function getType() { + return array('type'=>'VCARD','description' => _('VCARD 2.1 Export'),'extension'=>'vcf'); + } + + # Mappping one to one attribute + private $mapping = array( + 'cn' => 'FN', + 'title' => 'TITLE', + 'homephone' => 'TEL;HOME', + 'mobile' => 'TEL;CELL', + 'mail' => 'EMAIL;Internet', + 'labeleduri' =>'URL', + 'o' => 'ORG', + 'audio' => 'SOUND', + 'facsmiletelephoneNumber' =>'TEL;WORK;HOME;VOICE;FAX', + 'jpegphoto' => 'PHOTO;ENCODING=BASE64', + 'businesscategory' => 'ROLE', + 'description' => 'NOTE' + ); + + private $deliveryAddress = array( + 'postofficebox', + 'street', + 'l', + 'st', + 'postalcode', + 'c'); + + /** + * Export entries to VCARD format + */ + function export() { + $server = $this->getServer(); + $output = ''; + + # Sift through the entries. + foreach ($this->results as $base => $results) { + foreach ($results as $dndetails) { + $dndetails = array_change_key_case($dndetails); + + # Check the attributes needed for the delivery address field + $addr = 'ADR:'; + foreach ($this->deliveryAddress as $attr) { + if (isset($dndetails[$attr])) { + $addr .= $dndetails[$attr]; + unset($dndetails[$attr]); + } + + $addr .= ';'; + } + + $output .= sprintf('BEGIN:VCARD%s',$this->br); + + # Loop for the attributes + foreach ($dndetails as $key => $attr) { + if (! is_array($attr)) + $attr = array($attr); + + # If an attribute of the ldap entry exist in the mapping array for vcard + if (isset($this->mapping[$key])) { + + # Case of organisation. Need to append the possible ou attribute + if ($key == 'o') { + $output .= sprintf('%s:%s',$this->mapping[$key],$attr[0]); + + if (isset($entry['ou'])) + foreach ($entry['ou'] as $ou_value) + $output .= sprintf(';%s',$ou_value); + + # The attribute is binary. (to do : need to fold the line) + } elseif (in_array($key,array('audio','jpegphoto'))) { + $output .= $this->mapping[$key].':'.$this->br; + $output .= ' '.base64_encode($attr[0]); + + } else { + $output .= $this->mapping[$key].':'.$attr[0]; + } + + $output .= $this->br; + } + } + + $output .= sprintf('UID:%s%s',isset($dndetails['entryUUID']) ? $dndetails['entryUUID'] : $dndetails['dn'],$this->br); + $output .= sprintf('VERSION:2.1%s',$this->br); + $output .= sprintf('%s%s',$addr,$this->br); + $output .= sprintf('END:VCARD%s',$this->br); + } + } + + if ($this->compress) + return gzencode($output); + else + return $output; + } +} +?> diff --git a/lib/functions.php b/lib/functions.php new file mode 100644 index 0000000..13ce4ca --- /dev/null +++ b/lib/functions.php @@ -0,0 +1,3209 @@ +_('Generic Error'), + 'body'=>sprintf('%s: %s [%s]', + __METHOD__,_('Called to load a class that cant be found'),$className), + 'type'=>'error')); +} + +/** + * Strips all slashes from the specified array in place (pass by ref). + * @param Array The array to strip slashes from, typically one of + * $_GET, $_POST, or $_COOKIE. + */ +function array_stripslashes(&$array) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (is_array($array)) + while (list($key) = each($array)) + if (is_array($array[$key]) && $key != $array) + array_stripslashes($array[$key]); + else + $array[$key] = stripslashes($array[$key]); +} + +/** + * Compatibility Functions + * These functions exist, so that a standard function can be used in new applications, and they + * map to already defined functions in older applications. + */ + +/** + * If gettext is not available in PHP, then this will provide compatibility for it. + */ +if (! function_exists('_')) { + function _($msg) { + return $msg; + } +} + +/** + * Generic Utility Functions + */ + +/** + * Custom error handling function. + * When a PHP error occurs, PHP will call this function rather than printing + * the typical PHP error string. This provides the application the ability to + * format an error message so that it looks better. + * Optionally, it can present a link so that a user can search/submit bugs. + * This function is not to be called directly. It is exclusively for the use of + * PHP internally. If this function is called by PHP from within a context + * where error handling has been disabled (ie, from within a function called + * with "@" prepended), then this function does nothing. + * + * @param int The PHP error number that occurred (ie, E_ERROR, E_WARNING, E_PARSE, etc). + * @param string The PHP error string provided (ie, "Warning index "foo" is undefined) + * @param string The file in which the PHP error ocurred. + * @param int The line number on which the PHP error ocurred + * @see set_error_handler + */ +function app_error_handler($errno,$errstr,$file,$lineno) { + if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + /** + * error_reporting will be 0 if the error context occurred + * within a function call with '@' preprended (ie, @ldap_bind() ); + * So, don't report errors if the caller has specifically + * disabled them with '@' + */ + if (ini_get('error_reporting') == 0 || error_reporting() == 0) + return; + + $file = basename($file); + $caller = basename($_SERVER['PHP_SELF']); + $errtype = ''; + + switch ($errno) { + case E_STRICT: $errtype = 'E_STRICT'; break; + case E_ERROR: $errtype = 'E_ERROR'; break; + case E_WARNING: $errtype = 'E_WARNING'; break; + case E_PARSE: $errtype = 'E_PARSE'; break; + case E_NOTICE: $errtype = 'E_NOTICE'; break; + case E_CORE_ERROR: $errtype = 'E_CORE_ERROR'; break; + case E_CORE_WARNING: $errtype = 'E_CORE_WARNING'; break; + case E_COMPILE_ERROR: $errtype = 'E_COMPILE_ERROR'; break; + case E_COMPILE_WARNING: $errtype = 'E_COMPILE_WARNING'; break; + case E_USER_ERROR: $errtype = 'E_USER_ERROR'; break; + case E_USER_WARNING: $errtype = 'E_USER_WARNING'; break; + case E_USER_NOTICE: $errtype = 'E_USER_NOTICE'; break; + case E_ALL: $errtype = 'E_ALL'; break; + + default: $errtype = sprintf('%s: %s',_('Unrecognized error number'),$errno); + } + + # Take out extra spaces in error strings. + $errstr = preg_replace('/\s+/',' ',$errstr); + + if ($errno == E_NOTICE) { + return; + /* $body = ''; + $body .= sprintf('',_('Error'),$errstr,$errtype); + $body .= sprintf('', + _('File'),$file,_('line'),$lineno,_('caller'),$caller); + $body .= sprintf('', + app_version(),phpversion(),php_sapi_name()); + $body .= sprintf('',isset($_SERVER['SERVER_SOFTWARE']) ? $_SERVER['SERVER_SOFTWARE'] : 'SCRIPT'); + + if (function_exists('get_href')) + $body .= sprintf('', + get_href('search_bug',"&summary_keyword=".rawurlencode($errstr)), + _('Please check and see if this bug has been reported')); + $body .= '
%s:%s (%s)
%s:%s %s %s, %s %s
Versions:PLA: %s, PHP: %s, SAPI: %s
Web server:%s
%s.
'; + + system_message(array( + 'title'=>_('You found a non-fatal phpLDAPadmin bug!'), + 'body'=>$body, + 'type'=>'error')); + + return; */ + } + + # If this is a more serious error, call the error call. + error(sprintf('%s: %s',$errtype,$errstr),'error',null,true,true); +} + +/** + * Returns the application name. + */ +function app_name() { + return 'phpLDAPadmin'; +} + +/** + * Returns the application version currently running. The version + * is read from the file named VERSION. + * + * @return string The current version as read from the VERSION file. + */ +function app_version() { + static $CACHE = null; + + if ($CACHE) + return $CACHE; + + $version_file = realpath(LIBDIR.'../VERSION'); + if (! file_exists($version_file)) + $CACHE = 'UNKNOWN'; + + else { + $version = rtrim(file_get_contents($version_file)); + + $CACHE = preg_replace('/^RELEASE-([0-9\.]+(-.*)*)$/','$1',$version); + + # Check if we are a CVS copy. + if (preg_match('/^(DEVEL)?$/',$CACHE)) + $CACHE = 'DEVEL'; + + # Check if we are special DEVEL version + elseif (preg_match('/^DEVEL-([0-9\.]+)+$/',$CACHE)) {} + + # If return is still the same as version, then the tag is not one we expect. + elseif ($CACHE == $version) + $CACHE = 'UNKNOWN'; + } + + return $CACHE; +} + +/** + * This function will convert the browser two character language into the + * default 5 character language, where the country portion should NOT be + * assumed to be upper case characters of the first two characters. + */ +function auto_lang($lang) { + switch ($lang) { + case 'ja': return 'ja_JP'; + case 'cs': return 'cs_CZ'; + default: return sprintf('%s_%s',$lang,strtoupper($lang)); + } +} + +/** + * Makes sure that the config file is properly setup. + */ +function check_config($config_file) { + # Read in config_default.php + require_once LIBDIR.'config_default.php'; + + # Make sure their PHP version is current enough + if (strcmp(phpversion(),REQUIRED_PHP_VERSION) < 0) + system_message(array( + 'title'=>_('Incorrect version of PHP'), + 'body'=>sprintf('phpLDAPadmin requires PHP version %s or greater.
(You are using %s)', + REQUIRED_PHP_VERSION,phpversion()), + 'type'=>'error')); + + $config = new Config; + + if (file_exists(LIBDIR.'config_custom.php') && is_readable(LIBDIR.'config_custom.php')) + include LIBDIR.'config_custom.php'; + + ob_start(); + require $config_file; + $str = ''; + if (ob_get_level()) { + $str = ob_get_contents(); + ob_end_clean(); + } + + if ($str) { + $str = strip_tags($str); + $matches = array(); + preg_match('/(.*):\s+(.*):.*\s+on line (\d+)/',$str,$matches); + + if (isset($matches[1]) && isset($matches[2]) && isset($matches[3])) { + $error_type = $matches[1]; + $error = $matches[2]; + $line_num = $matches[3]; + + $file = file($config_file); + + $body = '

Config file ERROR

'; + $body .= sprintf('

%s (%s) on line %s

',$error_type,$error,$line_num); + + $body .= '
'; + $body .= sprintf('Looks like your config file has an ERROR on line %s.
',$line_num); + $body .= 'Here is a snippet around that line
'; + $body .= '
'."\n"; + + $body .= '
'; + + for ($i = $line_num-9; $i<$line_num+5; $i++) { + if ($i+1 == $line_num) + $body .= '
'; + + if ($i < 0) + continue; + + $body .= sprintf('%s: %s
',$i+1,$file[$i]); + + if ($i+1 == $line_num) + $body .= '
'; + } + + $body .= '
'; + $body .= '
'; + $body .= 'Hint: Sometimes these errors are caused by lines preceding the line reported.'; + $body .= '
'; + + $block = new block(); + $block->SetBody($body); + $www['page'] = new page(); + $www['page']->block_add('body',$block); + $www['page']->display(); + + die(); + } + } + + # Check for server definitions. + if (! isset($servers) || count($servers->GetServerList()) == 0) + error(_('Your config.php is missing Server Definitions. Please see the sample file config/config.php.example.'),'error','index.php',true); + + $config->setServers($servers); + + # Check the memory limit parameter. + if ((ini_get('memory_limit') > -1) && ini_get('memory_limit') < $config->getValue('session','memorylimit')) + system_message(array( + 'title'=>_('Memory Limit low.'), + 'body'=>sprintf('Your php memory limit is low - currently %s, you should increase it to atleast %s. This is normally controlled in /etc/php.ini.', + ini_get('memory_limit'),$config->getValue('session','memorylimit')), + 'type'=>'error')); + + return $config; +} + +/** + * Commands available in the control_panel of the page + * + * @return array + */ +function cmd_control_pane($type) { + if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + switch ($type) { + case 'main' : + return array( + 'home'=>array( + 'title'=>_('Home'), + 'enable'=>true, + 'link'=>sprintf('href="index.php" title="%s"',_('Home')), + 'image'=>sprintf('%s',IMGDIR,_('Home'))), + + 'purge'=>array( + 'title'=>_('Purge caches'), + 'enable'=>isset($_SESSION[APPCONFIG]) ? $_SESSION[APPCONFIG]->isCommandAvailable('script','purge_cache') : false, + 'link'=>sprintf('href="cmd.php?cmd=purge_cache" onclick="return ajDISPLAY(\'BODY\',\'cmd=purge_cache\',\'%s\');" title="%s"', + _('Clearing cache'),_('Purge caches')), + 'image'=>sprintf('%s',IMGDIR,_('Purge caches'))), + + 'hide_debug_info'=>array( + 'title'=>_('Show Cache'), + 'enable'=>isset($_SESSION[APPCONFIG]) ? $_SESSION[APPCONFIG]->isCommandAvailable('script','show_cache') : false, + 'link'=>sprintf('href="cmd.php?cmd=show_cache" onclick="return ajDISPLAY(\'BODY\',\'cmd=show_cache\',\'%s\');" title="%s"', + _('Loading'),_('Show Cache'),_('Show Cache')), + 'image'=>sprintf('%s',IMGDIR,_('Show Cache'))), + ); + + break; + + case 'top' : + return array( + 'forum'=>array( + 'title'=>_('Forum'), + 'enable'=>isset($_SESSION[APPCONFIG]) ? $_SESSION[APPCONFIG]->isCommandAvailable('cmd','oslinks') : true, + 'link'=>sprintf('href="%s" title="%s" onclick="target=\'_blank\';"',get_href('forum'),_('Forum')), + 'image'=>sprintf('%s',IMGDIR,_('Forum'))), + + 'feature'=>array( + 'title'=>_('Request feature'), + 'enable'=>isset($_SESSION[APPCONFIG]) ? $_SESSION[APPCONFIG]->isCommandAvailable('cmd','oslinks') : true, + 'link'=>sprintf('href="%s" title="%s" onclick="target=\'_blank\';"',get_href('add_rfe'),_('Request feature')), + 'image'=>sprintf('%s',IMGDIR,_('Request feature'))), + + 'bug'=>array( + 'title'=>_('Report a bug'), + 'enable'=>isset($_SESSION[APPCONFIG]) ? $_SESSION[APPCONFIG]->isCommandAvailable('cmd','oslinks') : true, + 'link'=>sprintf('href="%s" title="%s" onclick="target=\'_blank\';"',get_href('add_bug'),_('Report a bug')), + 'image'=>sprintf('%s',IMGDIR,_('Report a bug'))), + + 'donation'=>array( + 'title'=>_('Donate'), + 'enable'=>isset($_SESSION[APPCONFIG]) ? $_SESSION[APPCONFIG]->isCommandAvailable('cmd','oslinks') : true, + 'link'=>sprintf('href="%s" title="%s" onclick="target=\'_blank\';"',get_href('donate'),_('Donate')), + 'image'=>sprintf('%s',IMGDIR,_('Donate'))), + + 'help'=>array( + 'title'=>_('Help'), + 'enable'=>isset($_SESSION[APPCONFIG]) ? $_SESSION[APPCONFIG]->isCommandAvailable('cmd','oslinks') : true, + 'link'=>sprintf('href="%s" title="%s" onclick="target=\'_blank\';"',get_href('documentation'),_('Help')), + 'image'=>sprintf('%s',IMGDIR,_('Help'))) + ); + + break; + } +} + +/** + * This function dumps the $variable for debugging purposes + * + * @param string|array Variable to dump + * @param boolean Whether to stop execution or not. + */ +function debug_dump($variable,$die=false,$onlydebugaddr=false) { + if ($onlydebugaddr && + isset($_SESSION[APPCONFIG]) && $_SESSION[APPCONFIG]->getValue('debug','addr') && + $_SERVER['HTTP_X_FORWARDED_FOR'] != $_SESSION[APPCONFIG]->getValue('debug','addr') && + $_SERVER['REMOTE_ADDR'] != $_SESSION[APPCONFIG]->getValue('debug','addr')) + return; + + $backtrace = debug_backtrace(); + $caller['class'] = isset($backtrace[0]['class']) ? $backtrace[0]['class'] : 'N/A'; + $caller['function'] = isset($backtrace[0]['function']) ? $backtrace[0]['function'] : 'N/A'; + $caller['file'] = isset($backtrace[0]['file']) ? $backtrace[0]['file'] : 'N/A'; + $caller['line'] = isset($backtrace[0]['line']) ? $backtrace[0]['line'] : 'N/A'; + $caller['debug'] = $variable; + + print '
';
+	print_r($caller);
+	print '
'; + + if ($die) + die(); +} + +/** + * This function generates a backtrace + * + * @param boolean Whether to stop execution or not. + */ +function debug_dump_backtrace($msg='Calling BackTrace',$die=false) { + error($msg,'note',null,$die,true); +} + +/** + * Send a debug as a sys message + */ +function debug_sysmsg($msg) { + system_message(array('title'=>_('Debug'),'body'=>$msg,'type'=>'debug')); +} + +/** + * Debug Logging + * + * The global debug level is turned on in your configuration file by setting: + * + * $config->custom->debug['level'] = 255; + * + * together with atleast one output direction (currently file and syslog are supported). + * + * $config->custom->debug['file'] = '/tmp/app_debug.log'; + * $config->custom->debug['syslog'] = true; + * + * + * The debug level is turned into binary, then if the message levels bit is on + * the message will be sent to the debug log. (Thus setting your debug level to 255, + * all bits on, will results in all messages being printed.) + * + * The message level bits are defined here. + * 0( 1) = Entry/Return results from function calls. + * 1( 2) = Configuration Processing + * 2( 4) = Template Processing + * 3( 8) = Schema Processing + * 4( 16) = LDAP Server Communication + * 5( 32) = Tree Processing + * 7( 64) = Other non generic messages + * 8(128) = Page Processing + * 9(256) = Hooks Processing + * @param string Message to send to syslog + * @param int Log bit number for this message. + * @see syslog.php + */ +function debug_log($msg,$level,$indent) { + static $debug_file; + + # In case we are called before we are fully initialised or if debugging is not set. + if (! isset($_SESSION[APPCONFIG]) + || ! ($_SESSION[APPCONFIG]->getValue('debug','file') || $_SESSION[APPCONFIG]->getValue('debug','syslog'))) + return; + + $debug_level = $_SESSION[APPCONFIG]->getValue('debug','level'); + if (! $debug_level || (! ($level & $debug_level))) + return; + + if ($_SESSION[APPCONFIG]->getValue('debug','addr')) + if (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && $_SERVER['HTTP_X_FORWARDED_FOR'] == $_SESSION[APPCONFIG]->getValue('debug','addr')) + $debugaddr = true; + elseif ($_SERVER['REMOTE_ADDR'] == $_SESSION[APPCONFIG]->getValue('debug','addr')) + $debugaddr = true; + else + $debugaddr = false; + + else + $debugaddr = true; + + if (! $debugaddr) + return; + + # If we are limiting debug to a browser, then check that + $caller = basename($_SERVER['PHP_SELF']); + + $args = func_get_args(); + # Discard our first three arguments. + array_shift($args); + array_shift($args); + array_shift($args); + + # Pull the file/line/method + if (is_string($args[0]) && preg_match('/.php$/',$args[0])) { + $file = preg_replace('/.php$/','',array_shift($args)); + $line = array_shift($args); + $method = array_shift($args); + + } else { + $file = 'UNKNOWN'; + $line = 'UNKNOWN'; + $method = 'UNKNOWN'; + } + + # TEMP: New debuglog format + if (preg_match('/%%/',$msg) && $args[0] != 'NOARGS') + $args = array_shift($args); + + $fargs = array(); + foreach ($args as $key) { + if (is_array($key)) + array_push($fargs,serialize($key)); + elseif (is_object($key)) + array_push($fargs,sprintf('OBJECT:%s',get_class($key))); + else + array_push($fargs,$key); + } + + if (preg_match('/%%/',$msg)) + $msg = preg_replace('/%%/',join('|',$fargs),$msg); + else + $msg = vsprintf($msg,array_values($fargs)); + + if (function_exists('stopwatch')) + $timer = stopwatch(); + else + $timer = null; + + $debug_message = sprintf('[%2.3f] %15s(%04s-%03s): %s%s: %s',$timer,basename($file),$line,$level,str_repeat('.',$indent),$method,substr($msg,0,200)); + + if ($debug_file || $_SESSION[APPCONFIG]->getValue('debug','file')) { + if (! $debug_file) + $debug_file = fopen($_SESSION[APPCONFIG]->getValue('debug','file'), + $_SESSION[APPCONFIG]->getValue('debug','append') ? 'a' : 'w'); + + fwrite($debug_file,$debug_message."\n"); + } + + if ($_SESSION[APPCONFIG]->getValue('debug','syslog') && function_exists('syslog_notice')) + syslog_notice($debug_message); +} + +/** + * Display an error message in the system message panel of the page. + */ +function error($msg,$type='note',$redirect=null,$fatal=false,$backtrace=false) { + global $www; + static $counter; + + # Just a check to see that we are called right. + if (! isset($www['page']) && ! $fatal) + die("Function error called incorrectly [$msg]"); + + # If the error is fatal, we'll need to stop here. + if (! isset($www['page'])) + $www['page'] = new page(); + + if ($fatal) + $www['page']->setsysmsg(array('title'=>_('Error'),'body'=>$msg,'type'=>$type)); + else + system_message(array('title'=>_('Error'),'body'=>$msg,'type'=>$type),$redirect); + + # Spin loop detection + if ($counter++ > 20) { + debug_dump('Spin loop detection.'); + debug_dump(array('msg'=>$msg,'session'=>$_SESSION['sysmsg'],'www'=>$www),1); + } + + # Do we have a backtrace to display? + if ($backtrace) { + $backtraceblock = new block(); + $backtraceblock->SetTitle('PHP Debug Backtrace'); + + $body = ''; + $body .= "\n"; + + foreach (debug_backtrace() as $error => $line) { + $_SESSION['backtrace'][$error]['file'] = isset($line['file']) ? $line['file'] : 'unknown'; + $_SESSION['backtrace'][$error]['line'] = isset($line['line']) ? $line['line'] : 'unknown'; + $body .= sprintf('', + _('File'),isset($line['file']) ? $line['file'] : $last['file'],isset($line['line']) ? $line['line'] : ''); + + $_SESSION['backtrace'][$error]['function'] = $line['function']; + $body .= sprintf(''; + $body .= "\n"; + + if (isset($line['file'])) + $last['file'] = $line['file']; + } + + $body .= '
%s%s (%s)
 %s%s', + _('Function'),$line['function']); + + if (isset($line['args'])) { + $display = print_r($line['args'], TRUE);/* strlen(serialize($line['args'])) < 50 ? htmlspecialchars(serialize($line['args'])) : htmlspecialchars(substr(serialize($line['args']),0,50)).'...'; */ + $_SESSION['backtrace'][$error]['args'] = $line['args']; + if (file_exists(LIBDIR.'../tools/unserialize.php')) + $body .= sprintf(' (%s)', + '../tools/unserialize.php',$error,$display); + else + $body .= sprintf(' (%s)',$display); + } + $body .= '
'; + $body .= "\n"; + $backtraceblock->SetBody($body); + + $www['page']->block_add('body',$backtraceblock); + } + + if ($fatal) { + $www['page']->display(array('tree'=>false)); + die(); + } +} + +/** + * Return the result of a form variable, with optional default + * + * @return The form GET/REQUEST/SESSION/POST variable value or its default + */ +function get_request($attr,$type='POST',$die=false,$default=null) { + switch($type) { + case 'GET': + $value = isset($_GET[$attr]) ? (is_array($_GET[$attr]) ? $_GET[$attr] : (empty($_GET['nodecode'][$attr]) ? rawurldecode($_GET[$attr]) : $_GET[$attr])) : $default; + break; + + case 'REQUEST': + $value = isset($_REQUEST[$attr]) ? (is_array($_REQUEST[$attr]) ? $_REQUEST[$attr] : (empty($_REQUEST['nodecode'][$attr]) ? rawurldecode($_REQUEST[$attr]) : $_REQUEST[$attr])) : $default; + break; + + case 'SESSION': + $value = isset($_SESSION[$attr]) ? (is_array($_SESSION[$attr]) ? $_SESSION[$attr] : (empty($_SESSION['nodecode'][$attr]) ? rawurldecode($_SESSION[$attr]) : $_SESSION[$attr])) : $default; + break; + + case 'POST': + default: + $value = isset($_POST[$attr]) ? (is_array($_POST[$attr]) ? $_POST[$attr] : (empty($_POST['nodecode'][$attr]) ? rawurldecode($_POST[$attr]) : $_POST[$attr])) : $default; + break; + } + + if ($die && is_null($value)) + system_message(array( + 'title'=>_('Generic Error'), + 'body'=>sprintf('%s: Called "%s" without "%s" using "%s"', + basename($_SERVER['PHP_SELF']),get_request('cmd','REQUEST'),$attr,$type), + 'type'=>'error'), + 'index.php'); + + return $value; +} + +/** + * Record a system message. + * This function can be used as an alternative to generate a system message, if page hasnt yet been defined. + */ +function system_message($msg,$redirect=null) { + if (! is_array($msg)) + return null; + + if (! isset($msg['title']) && ! isset($msg['body'])) + return null; + + if (! isset($msg['type'])) + $msg['type'] = 'info'; + + if (! isset($_SESSION['sysmsg']) || ! is_array($_SESSION['sysmsg'])) + $_SESSION['sysmsg'] = array(); + + # Try and detect if we are in a redirect loop + if (get_request('redirect','GET') && $msg['type'] != 'debug') { + foreach ($_SESSION['sysmsg'] as $detail) { + if ($msg == $detail && ! isset($detail['special'])) { + debug_dump(array('Incoming MSG'=>$msg,'existing'=>$_SESSION['sysmsg'])); + debug_dump_backtrace('Redirect Loop Detected',true); + } + } + } + + array_push($_SESSION['sysmsg'],$msg); + + if ($redirect) { + if (preg_match('/\?/',$redirect)) + $redirect .= '&'; + else + $redirect .= '?'; + $redirect .= 'redirect=true'; + + # Check if we were an ajax request, and only render the ajax message + if (get_request('meth','REQUEST') == 'ajax') + $redirect .= '&meth=ajax'; + + header("Location: $redirect"); + die(); + } +} + +/** + * Other Functions + */ + +/** + * Encryption using blowfish algorithm + * + * @param string Original data + * @param string The secret + * @return string The encrypted result + * @author lem9 (taken from the phpMyAdmin source) + */ +function blowfish_encrypt($data,$secret=null) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # If our secret is null or blank, get the default. + if ($secret === null || ! trim($secret)) + $secret = $_SESSION[APPCONFIG]->getValue('session','blowfish') ? $_SESSION[APPCONFIG]->getValue('session','blowfish') : session_id(); + + # If the secret isnt set, then just return the data. + if (! trim($secret)) + return $data; + + if (function_exists('mcrypt_module_open') && ! empty($data)) { + $td = mcrypt_module_open(MCRYPT_BLOWFISH,'',MCRYPT_MODE_ECB,''); + $iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td),MCRYPT_DEV_URANDOM); + mcrypt_generic_init($td,substr($secret,0,mcrypt_enc_get_key_size($td)),$iv); + $encrypted_data = base64_encode(mcrypt_generic($td,$data)); + mcrypt_generic_deinit($td); + + return $encrypted_data; + } + + if (file_exists(LIBDIR.'blowfish.php')) + require_once LIBDIR.'blowfish.php'; + else + return $data; + + $pma_cipher = new Horde_Cipher_blowfish; + $encrypt = ''; + + for ($i=0; $iencryptBlock($block, $secret); + } + + return base64_encode($encrypt); +} + +/** + * Decryption using blowfish algorithm + * + * @param string Encrypted data + * @param string The secret + * @return string Original data + * @author lem9 (taken from the phpMyAdmin source) + */ +function blowfish_decrypt($encdata,$secret=null) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # This cache gives major speed up for stupid callers :) + static $CACHE = array(); + + if (isset($CACHE[$encdata])) + return $CACHE[$encdata]; + + # If our secret is null or blank, get the default. + if ($secret === null || ! trim($secret)) + $secret = $_SESSION[APPCONFIG]->getValue('session','blowfish') ? $_SESSION[APPCONFIG]->getValue('session','blowfish') : session_id(); + + # If the secret isnt set, then just return the data. + if (! trim($secret)) + return $encdata; + + if (function_exists('mcrypt_module_open') && ! empty($encdata)) { + $td = mcrypt_module_open(MCRYPT_BLOWFISH,'',MCRYPT_MODE_ECB,''); + $iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td),MCRYPT_DEV_URANDOM); + mcrypt_generic_init($td,substr($secret,0,mcrypt_enc_get_key_size($td)),$iv); + $decrypted_data = trim(mdecrypt_generic($td,base64_decode($encdata))); + mcrypt_generic_deinit($td); + + return $decrypted_data; + } + + if (file_exists(LIBDIR.'blowfish.php')) + require_once LIBDIR.'blowfish.php'; + else + return $encdata; + + $pma_cipher = new Horde_Cipher_blowfish; + $decrypt = ''; + $data = base64_decode($encdata); + + for ($i=0; $idecryptBlock(substr($data, $i, 8), $secret); + + // Strip off our \0's that were added. + $return = preg_replace("/\\0*$/",'',$decrypt); + $CACHE[$encdata] = $return; + return $return; +} + +/** + * String padding + * + * @param string Input string + * @param integer Length of the result + * @param string The filling string + * @param integer Padding mode + * @return string The padded string + */ +function full_str_pad($input,$pad_length,$pad_string='',$pad_type=0) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $str = ''; + $length = $pad_length - strlen($input); + + if ($length > 0) { // str_repeat doesn't like negatives + if ($pad_type == STR_PAD_RIGHT) { // STR_PAD_RIGHT == 1 + $str = $input.str_repeat($pad_string, $length); + } elseif ($pad_type == STR_PAD_BOTH) { // STR_PAD_BOTH == 2 + $str = str_repeat($pad_string, floor($length/2)); + $str .= $input; + $str .= str_repeat($pad_string, ceil($length/2)); + } else { // defaults to STR_PAD_LEFT == 0 + $str = str_repeat($pad_string, $length).$input; + } + + } else { // if $length is negative or zero we don't need to do anything + $str = $input; + } + return $str; +} + +/** + * Returns the cached array of LDAP resources. + * + * Note that internally, this function utilizes a two-layer cache, + * one in memory using a static variable for multiple calls within + * the same page load, and one in a session for multiple calls within + * the same user session (spanning multiple page loads). + * + * @return Returns the cached attributed requested, + * or null if there is nothing cached.. + */ +function get_cached_item($index,$item,$subitem='null') { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # Set default return + $return = null; + + # Check config to make sure session-based caching is enabled. + if ($_SESSION[APPCONFIG]->getValue('cache',$item) && isset($_SESSION['cache'][$index][$item][$subitem])) + $return = $_SESSION['cache'][$index][$item][$subitem]; + + if (DEBUG_ENABLED) + debug_log('Returning (%s)',1,0,__FILE__,__LINE__,__METHOD__,$return); + + return $return; +} + +/** + * Caches the specified $item for the specified $index. + * + * Returns true on success of false on failure. + */ +function set_cached_item($index,$item,$subitem='null',$data) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # Check config to make sure session-based caching is enabled. + if ($_SESSION[APPCONFIG]->getValue('cache',$item)) { + global $CACHE; + + $CACHE[$index][$item][$subitem] = $data; + $_SESSION['cache'][$index][$item][$subitem] = $data; + + return true; + + } else + return false; +} + +/** + * Deletes the cache for a specified $item for the specified $index + */ +function del_cached_item($index,$item,$subitem='null') { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + global $CACHE; + + # Check config to make sure session-based caching is enabled. + if (isset($_SESSION['cache'][$index][$item][$subitem])) + unset($_SESSION['cache'][$index][$item][$subitem]); + + if (isset($CACHE[$index][$item][$subitem])) + unset($CACHE[$index][$item][$subitem]); +} + +/** + * Utility wrapper for setting cookies, which takes into consideration + * application configuration values. On success, true is returned. On + * failure, false is returned. + * + * @param string The name of the cookie to set. + * @param string The value of the cookie to set. + * @param int (optional) The duration in seconds of this cookie. If unspecified, $cookie_time is used from config.php + * @param string (optional) The directory value of this cookie (see php.net/setcookie) + * @return boolean + */ +function set_cookie($name,$val,$expire=null,$dir=null) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # Set default return + $return = false; + + if ($expire == null) { + $cookie_time = $_SESSION[APPCONFIG]->getValue('session','cookie_time'); + $expire = $cookie_time == 0 ? null : time() + $cookie_time; + } + + if ($dir == null) + $dir = dirname($_SERVER['PHP_SELF']); + + if (@setcookie($name,$val,$expire,$dir)) { + $_COOKIE[$name] = $val; + $return = true; + } + + if (DEBUG_ENABLED) + debug_log('Returning (%s)',1,0,__FILE__,__LINE__,__METHOD__,$return); + + return $return; +} + +/** + * Get a customized file for a server + * We don't need any caching, because it's done by PHP + * + * @param int The ID of the server + * @param string The requested filename + * + * @return string The customized filename, if exists, or the standard one + */ +function get_custom_file($index,$filename,$path) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # Set default return + $return = $path.$filename; + $server = $_SESSION[APPCONFIG]->getServer($index); + + $custom = $server->getValue('custom','pages_prefix'); + if (! is_null($custom) && is_file(realpath($path.$custom.$filename))) + $return = $path.$custom.$filename; + + if (DEBUG_ENABLED) + debug_log('Returning (%s)',1,0,__FILE__,__LINE__,__METHOD__,$return); + + return $return; +} + +/** + * Sort a multi dimensional array. + * + * @param array Multi demension array passed by reference + * @param string Comma delimited string of sort keys. + * @param boolean Whether to reverse sort. + * @return array Sorted multi demension array. + */ +function masort(&$data,$sortby,$rev=0) { + if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # if the array to sort is null or empty, or if we have some nasty chars + if (! preg_match('/^[a-zA-Z0-9_]+(\([a-zA-Z0-9_,]*\))?$/',$sortby) || ! $data) + return; + + static $CACHE = array(); + + + + if (empty($CACHE[$sortby])) { + /* $code = "\$c=0;\n"; + + foreach (explode(',',$sortby) as $key) { + $code .= "if (is_object(\$a) || is_object(\$b)) {\n"; + + $code .= " if (is_array(\$a->$key)) {\n"; + $code .= " asort(\$a->$key);\n"; + $code .= " \$aa = array_shift(\$a->$key);\n"; + $code .= " } else\n"; + $code .= " \$aa = \$a->$key;\n"; + + $code .= " if (is_array(\$b->$key)) {\n"; + $code .= " asort(\$b->$key);\n"; + $code .= " \$bb = array_shift(\$b->$key);\n"; + $code .= " } else\n"; + $code .= " \$bb = \$b->$key;\n"; + + $code .= " if (\$aa != \$bb)"; + if ($rev) + $code .= " return (\$aa < \$bb ? 1 : -1);\n"; + else + $code .= " return (\$aa > \$bb ? 1 : -1);\n"; + + $code .= "} else {\n"; + + $code .= " \$a = array_change_key_case(\$a);\n"; + $code .= " \$b = array_change_key_case(\$b);\n"; + + $key = strtolower($key); + + $code .= " if ((! isset(\$a['$key'])) && isset(\$b['$key'])) return 1;\n"; + $code .= " if (isset(\$a['$key']) && (! isset(\$b['$key']))) return -1;\n"; + + $code .= " if ((isset(\$a['$key'])) && (isset(\$b['$key']))) {\n"; + $code .= " if (is_array(\$a['$key'])) {\n"; + $code .= " asort(\$a['$key']);\n"; + $code .= " \$aa = array_shift(\$a['$key']);\n"; + $code .= " } else\n"; + $code .= " \$aa = \$a['$key'];\n"; + + $code .= " if (is_array(\$b['$key'])) {\n"; + $code .= " asort(\$b['$key']);\n"; + $code .= " \$bb = array_shift(\$b['$key']);\n"; + $code .= " } else\n"; + $code .= " \$bb = \$b['$key'];\n"; + + $code .= " if (\$aa != \$bb)\n"; + $code .= " if (is_numeric(\$aa) && is_numeric(\$bb)) {\n"; + + if ($rev) + $code .= " return (\$aa < \$bb ? 1 : -1);\n"; + else + $code .= " return (\$aa > \$bb ? 1 : -1);\n"; + + $code .= " } else {\n"; + + if ($rev) + $code .= " if ( (\$c = strcasecmp(\$bb,\$aa)) != 0 ) return \$c;\n"; + else + $code .= " if ( (\$c = strcasecmp(\$aa,\$bb)) != 0 ) return \$c;\n"; + + $code .= " }\n"; + $code .= " }\n"; + $code .= "}\n"; + } + + $code .= 'return $c;'; */ + + $CACHE[$sortby] = function ($a, $b) use ($rev) { + $c = 0; + + foreach (explode(',',$sortby) as $key) { + if (is_object($a) || is_object($b)) { + if (is_array($a->$key)) { + asort($a->$key); + $aa = array_shift($a->$key); + } else { + $aa = $a->$key; + } + + if (is_array($b->$key)) { + asort($b->$key); + $bb = array_shift($b->$key); + } else { + $bb = $b->$key; + } + + if ($aa != $bb) { + if ($rev) { + return ($aa < $bb) ? 1 : -1; + } + + return ($aa > $bb) ? 1 : -1; + } else { + $a = array_change_key_case((array)$a); + $b = array_change_key_case((array)$b); + + $key = strtolower($key); + + if ((! isset($a[$key])) && isset($b[$key])) return 1; + if (isset($a[$key]) && (! isset($b[$key]))) return -1; + + if ((isset($a[$key])) && (isset($b[$key]))) { + if (is_array($a[$key])) { + asort($a[$key]); + $aa = array_shift($a[$key]); + } else { + $aa = $a[$key]; + } + + if (is_array($b[$key])) { + asort($b[$key]); + $bb = array_shift($b[$key]); + } else { + $bb = $b[$key]; + } + + if ($aa !== $bb) { + if (is_numeric($aa) && is_numeric($bb)) { + if ($rev) { + return ($aa < $bb) ? 1 : -1; + } + + return ($aa > $bb) ? 1 : -1; + } else { + if (($c = strcasecmp($bb, $aa)) != 0) return $c; + if (($c = strcasecmp($aa, $bb)) != 0) return $c; + } + } + } + } + } + } + + return $c; + };// masort_function($a, $b, $rev);//create_function('$a, $b',$code); + } + + uasort($data,$CACHE[$sortby]); +} + +/** + * Is compression enabled for output + */ +function isCompress() { + return (isset($_SESSION[APPCONFIG]) && $_SESSION[APPCONFIG]->getValue('appearance','compress') + && ! ini_get('zlib.output_compression') + && preg_match('/gzip/',$_SERVER['HTTP_ACCEPT_ENCODING'])); +} + +/** + * PLA specific Functions + */ + +/** + * Fetches whether the user has configured phpLDAPadmin to obfuscate passwords + * with "*********" when displaying them. + * + * This is configured in config.php thus: + * + * $config->custom->appearance['obfuscate_password_display'] = true; + * + * + * Or if it is OK to show encrypted passwords but not clear text passwords + * + * $config->custom->appearance['show_clear_password'] = false; + * + * + * @param string Password encoding type + * @return boolean + */ +function obfuscate_password_display($enc=null) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if ($_SESSION[APPCONFIG]->getValue('appearance','obfuscate_password_display')) + $return = true; + + elseif (! $_SESSION[APPCONFIG]->getValue('appearance','show_clear_password') && (is_null($enc) || $enc == 'clear')) + $return = true; + + else + $return = false; + + if (DEBUG_ENABLED) + debug_log('Returning (%s)',1,0,__FILE__,__LINE__,__METHOD__,$return); + + return $return; +} + +/** + * Returns an HTML-beautified version of a DN. + * Internally, this function makes use of pla_explode_dn() to break the + * the DN into its components. It then glues them back together with + * "pretty" HTML. The returned HTML is NOT to be used as a real DN, but + * simply displayed. + * + * @param string The DN to pretty-print. + * @return string + */ +function pretty_print_dn($dn) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $dn_save = $dn; + $dn = pla_explode_dn($dn); + + if (! $dn) + return $dn_save; + + foreach ($dn as $i => $element) { + $element = htmlspecialchars($element); + $element = explode('=',$element,2); + $element = implode('=',$element); + $dn[$i] = $element; + } + + $dn = implode(',',$dn); + + return $dn; +} + +/** + * Given a string, this function returns true if the string has the format + * of a DN (ie, looks like "cn=Foo,dc=example,dc=com"). Returns false otherwise. + * The purpose of this function is so that developers can examine a string and + * know if it looks like a DN, and draw a hyperlink as needed. + * + * (See unit_test.php for test cases) + * + * @param string The attribute to examine for "DNness" + * @return boolean + */ +function is_dn_string($str) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + /* Try to break the string into its component parts if it can be done + ie, "uid=Manager" "dc=example" and "dc=com" */ + $parts = pla_explode_dn($str); + if (! is_array($parts) || ! count($parts)) + return false; + + /* Foreach of the "parts", look for an "=" character, + and make sure neither the left nor the right is empty */ + foreach ($parts as $part) { + if (! strpos($part,"=")) + return false; + + $sub_parts = explode('=',$part,2); + $left = $sub_parts[0]; + $right = $sub_parts[1]; + + if ( ! strlen(trim($left)) || ! strlen(trim($right))) + return false; + + if (strpos($left,'#') !== false) + return false; + } + + # We survived the above rigor. This is a bonified DN string. + return true; +} + +/** + * Get whether a string looks like an email address (user@example.com). + * + * @param string The string to analyze. + * @return boolean Returns true if the specified string looks like an email address or false otherwise. + */ +function is_mail_string($str) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $mail_regex = "/^[_A-Za-z0-9-]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9-]+(\\.[A-Za-z0-9-]+)*$/"; + + if (preg_match($mail_regex,$str)) + return true; + else + return false; +} + +/** + * Get whether a string looks like a web URL (http://www.example.com/) + * + * @param string The string to analyze. + * @return boolean Returns true if the specified string looks like a web URL or false otherwise. + */ +function is_url_string($str) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $url_regex = '/^(ftp|https?):\/\/+[\w\.\-\/\?\=\&]*\w+/'; + + if (preg_match($url_regex,$str)) + return true; + else + return false; +} + +/** + * Compares 2 DNs. If they are equivelant, returns 0, otherwise, + * returns their sorting order (similar to strcmp()): + * Returns < 0 if dn1 is less than dn2. + * Returns > 0 if dn1 is greater than dn2. + * + * The comparison is performed starting with the top-most element + * of the DN. Thus, the following list: + * + * ou=people,dc=example,dc=com + * cn=Admin,ou=People,dc=example,dc=com + * cn=Joe,ou=people,dc=example,dc=com + * dc=example,dc=com + * cn=Fred,ou=people,dc=example,dc=org + * cn=Dave,ou=people,dc=example,dc=org + * + * Will be sorted thus using usort( $list, "pla_compare_dns" ): + * + * dc=com + * dc=example,dc=com + * ou=people,dc=example,dc=com + * cn=Admin,ou=People,dc=example,dc=com + * cn=Joe,ou=people,dc=example,dc=com + * cn=Dave,ou=people,dc=example,dc=org + * cn=Fred,ou=people,dc=example,dc=org + * + * + * @param string The first of two DNs to compare + * @param string The second of two DNs to compare + * @return int + */ +function pla_compare_dns($dn1,$dn2) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # If pla_compare_dns is passed via a tree, then we'll just get the DN part. + if (is_array($dn1)) + if (isset($dn1['dn'])) + $dn1 = $dn1['dn']; + else + $dn1 = implode('+',$dn1); + if (is_array($dn2)) + if (isset($dn2['dn'])) + $dn2 = $dn2['dn']; + else + $dn2 = implode('+',$dn2); + + # If they are obviously the same, return immediately + if (! strcasecmp($dn1,$dn2)) + return 0; + + $dn1_parts = pla_explode_dn(pla_reverse_dn($dn1)); + $dn2_parts = pla_explode_dn(pla_reverse_dn($dn2)); + assert(is_array($dn1_parts)); + assert(is_array($dn2_parts)); + + # Foreach of the "parts" of the smaller DN + for ($i=0; $i < count($dn1_parts) && $i < count($dn2_parts); $i++) { + /* dnX_part is of the form: "cn=joe" or "cn = joe" or "dc=example" + ie, one part of a multi-part DN. */ + $dn1_part = $dn1_parts[$i]; + $dn2_part = $dn2_parts[$i]; + + /* Each "part" consists of two sub-parts: + 1. the attribute (ie, "cn" or "o") + 2. the value (ie, "joe" or "example") */ + $dn1_sub_parts = explode('=',$dn1_part,2); + $dn2_sub_parts = explode('=',$dn2_part,2); + + $dn1_sub_part_attr = trim($dn1_sub_parts[0]); + $dn2_sub_part_attr = trim($dn2_sub_parts[0]); + + if (0 != ($cmp = strcasecmp($dn1_sub_part_attr,$dn2_sub_part_attr))) + return $cmp; + + $dn1_sub_part_val = trim($dn1_sub_parts[1]); + $dn2_sub_part_val = trim($dn2_sub_parts[1]); + if (0 != ($cmp = strcasecmp($dn1_sub_part_val,$dn2_sub_part_val))) + return $cmp; + } + + /* If we iterated through all entries in the smaller of the two DNs + (ie, the one with fewer parts), and the entries are different sized, + then, the smaller of the two must be "less than" than the larger. */ + if (count($dn1_parts) > count($dn2_parts)) { + return 1; + + } elseif (count($dn2_parts) > count($dn1_parts)) { + return -1; + + } else { + return 0; + } +} + +/** + * For LDAP servers with auto_number enabled, this function will get the next + * available number using the host's preferred mechanism (pool or search). + * + * This is configured in config.php by server: + * + * + * $servers->setValue('auto_number','enable',true|false); + * + * + * The available mechanisms are: + * pool: + * The pool mechanism uses a user-configured entry in the LDAP server to + * store the last used "number". This mechanism simply fetches and increments + * and returns that value. + * + * search: + * The search mechanism will search the LDAP server that has the attribute + * set. It will then find the smallest value and "fills in the gaps" by + * incrementing the smallest attribute until an unused value is found. + * + * NOTE: Both mechanisms do NOT prevent race conditions or toe-stomping, so + * care must be taken when actually creating the entry to check that the number + * returned here has not been used in the mean time. Note that the two different + * mechanisms may (will!) return different values as they use different algorithms + * to arrive at their result. Do not be alarmed if (when!) this is the case. + * + * See config.php.example for more notes on the two mechanisms. + * + * @param string Base to start the search from + * @param string Attribute to query + * @param boolean Increment the result (for pool searches) + * @param string LDAP filter to use (for pool searches) + * @return int + */ +function get_next_number($base,$attr,$increment=false,$filter=false,$startmin=null) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $server = $_SESSION[APPCONFIG]->getServer(get_request('server_id','REQUEST')); + $attr = strtolower($attr); + $query = array(); + + if (! $server->getValue('auto_number','enable')) { + system_message(array( + 'title'=>_('AUTO_NUMBER is disabled for this server'), + 'body'=>sprintf('%s (%s)',_('A call was made to get_next_number(), however, it is disabled for this server'),$attr), + 'type'=>'warn')); + + return false; + } + + # Check see and use our alternate uid_dn and password if we have it. + if (! $server->login($server->getValue('auto_number','dn'),$server->getValue('auto_number','pass'),'auto_number')) { + system_message(array( + 'title'=>_('AUTO_NUMBER invalid login/password'), + 'body'=>sprintf('%s (%s)',_('Unable to connect to LDAP server with the auto_number login/password, please check your configuration.'), + $server->getName()), + 'type'=>'warn')); + + return false; + } + + # Some error checking + if (! $base) { + $query['base'] = $server->getValue('auto_number','search_base'); + + if (! trim($query['base'])) { + system_message(array( + 'title'=>_('No AUTO_NUMBER search_base configured for this server'), + 'body'=>_('A call was made to get_next_number(), however, the base to search is empty.'), + 'type'=>'warn')); + + return false; + } + + } else + $query['base'] = $base; + + if (! $server->dnExists($query['base'])) { + system_message(array( + 'title'=>_('No AUTO_NUMBER search_base exists for this server'), + 'body'=>sprintf('%s (%s)',_('A call was made to get_next_number(), however, the base to search does not exist for this server.'),$query['base']), + 'type'=>'warn')); + + return false; + } + + if (! is_string($attr) || ! $server->getSchemaAttribute($attr)) { + system_message(array( + 'title'=>_('AUTO_NUMBER search attribute invalid'), + 'body'=>sprintf('%s (%s)',_('The search attribute for AUTO_NUMBER is invalid, expecting a single valid attribute.'),$attr), + 'type'=>'warn')); + + return false; + } + + $query['attrs'] = array($attr); + + # Based on the configured mechanism, go get the next available uidNumber! + switch ($server->getValue('auto_number','mechanism')) { + case 'search': + $query['filter'] = sprintf('(%s=*)',$attr); + $search = $server->query($query,'auto_number'); + + # Construct a list of used numbers + $autonum = array(0); + + foreach ($search as $dn => $values) { + $values = array_change_key_case($values); + foreach ($values[$attr] as $value) + array_push($autonum,$value); + } + + $autonum = array_unique($autonum); + sort($autonum); + + # Start with the least existing autoNumber and add 1 + $minNumber = is_null($startmin) ? intval($autonum[0])+1 : $startmin; + + # Override our minNumber by the configuration if it exists. + if (count($server->getValue('auto_number','min'))) { + $min = array_change_key_case($server->getValue('auto_number','min')); + + if (isset($min[$attr])) + $minNumber = $min[$attr] > $minNumber ? $min[$attr] : $minNumber; + } + + for ($i=0;$i $num+1) + return $autonum[$i] >= $num ? $num+1 : $num; + } + + # If we didnt find a suitable gap and are all above the minNumber, we'll just return the $minNumber + return $minNumber; + + break; + + case 'pool': + switch ($attr) { + case 'gidnumber': + $query['filter'] = '(objectClass=gidPool)'; + + break; + + case 'uidnumber': + $query['filter'] = '(objectClass=uidPool)'; + + break; + } + + # If we are called with a filter, we'll use the one from the configuration. + if (! empty($filter)) + $query['filter'] = $filter; + + $search = $server->query($query,'auto_number'); + + switch (count($search)) { + case '1': + break; + + case '0': + system_message(array( + 'title'=>_('AUTO_NUMBER pool filter didnt return any DNs'), + 'body'=>sprintf('%s (%s)',_('Please change your filter parameter, or check your auto_number,search_base configuration'),$query['filter']), + 'type'=>'warn')); + + return false; + + default: + system_message(array( + 'title'=>_('AUTO_NUMBER pool filter returned too many DNs'), + 'body'=>sprintf('%s (%s)',_('Please change your filter parameter, or check your auto_number,search_base configuration'),$query['filter']), + 'type'=>'warn')); + + return false; + } + + # This should only iterate once. + foreach ($search as $dn => $values) { + $values = array_change_key_case($values); + + $autonum = $values[$attr][0]; + $poolDN = $values['dn']; + } + + if ($increment) { + $updatedattr = array($attr=>$autonum+1); + $server->modify($poolDN,$updatedattr); + } + + return $autonum; + + # No other cases allowed. The user has an error in the configuration + default: + system_message(array( + 'title'=>_('Invalid AUTO_NUMBER mechanism'), + 'body'=>sprintf('%s (%s)',_('Your config file specifies an unknown AUTO_NUMBER search mechanism.'),$server->getValue('auto_number','mechanism')), + 'type'=>'warn')); + + return false; + } +} + +/** + * Given a DN and server ID, this function reads the DN's objectClasses and + * determines which icon best represents the entry. The results of this query + * are cached in a session variable so it is not run every time the tree + * browser changes, just when exposing new DNs that were not displayed + * previously. That means we can afford a little bit of inefficiency here + * in favor of coolness. :) + * + * This function returns a string like "country.png". All icon files are assumed + * to be contained in the /images/ directory of phpLDAPadmin. + * + * Developers are encouraged to add new icons to the images directory and modify + * this function as needed to suit their types of LDAP entries. If the modifications + * are general to an LDAP audience, the phpLDAPadmin team will gladly accept them + * as a patch. + * + * @param string The DN of the entry whose icon you wish to fetch. + * @return string + */ +function get_icon($server_id,$dn,$object_classes=array()) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $server = $_SESSION[APPCONFIG]->getServer($server_id); + + # Fetch and lowercase all the objectClasses in an array + if (! count($object_classes)) + $object_classes = $server->getDNAttrValue($dn,'objectClass'); + + foreach ($object_classes as $index => $value) + $object_classes[$index] = strtolower($value); + + $rdn = get_rdn($dn); + $rdn_parts = explode('=',$rdn,2); + $rdn_value = isset($rdn_parts[0]) ? $rdn_parts[0] : null; + $rdn_attr = isset($rdn_parts[1]) ? $rdn_parts[1] : null; + unset($rdn_parts); + + # Return icon filename based upon objectClass value + if (in_array('sambaaccount',$object_classes) && + '$' == $rdn{ strlen($rdn) - 1 }) + return 'nt_machine.png'; + + if (in_array('sambaaccount',$object_classes)) + return 'nt_user.png'; + + elseif (in_array('person',$object_classes) || + in_array('organizationalperson',$object_classes) || + in_array('inetorgperson',$object_classes) || + in_array('account',$object_classes) || + in_array('posixaccount',$object_classes)) + + return 'ldap-user.png'; + + elseif (in_array('organization',$object_classes)) + return 'ldap-o.png'; + + elseif (in_array('organizationalunit',$object_classes)) + return 'ldap-ou.png'; + + elseif (in_array('organizationalrole',$object_classes)) + return 'ldap-uid.png'; + + elseif (in_array('dcobject',$object_classes) || + in_array('domainrelatedobject',$object_classes) || + in_array('domain',$object_classes) || + in_array('builtindomain',$object_classes)) + + return 'ldap-dc.png'; + + elseif (in_array('alias',$object_classes)) + return 'ldap-alias.png'; + + elseif (in_array('room',$object_classes)) + return 'door.png'; + + elseif (in_array('iphost',$object_classes)) + return 'host.png'; + + elseif (in_array('device',$object_classes)) + return 'device.png'; + + elseif (in_array('document',$object_classes)) + return 'document.png'; + + elseif (in_array('country',$object_classes)) { + $tmp = pla_explode_dn($dn); + $cval = explode('=',$tmp[0],2); + $cval = isset($cval[1]) ? $cval[1] : false; + if ($cval && false === strpos($cval,'..') && + file_exists(realpath(sprintf('%s/../countries/%s.png',IMGDIR,strtolower($cval))))) + + return sprintf('../countries/%s.png',strtolower($cval)); + + else + return 'country.png'; + } + + elseif (in_array('jammvirtualdomain',$object_classes)) + return 'mail.png'; + + elseif (in_array('locality',$object_classes)) + return 'locality.png'; + + elseif (in_array('posixgroup',$object_classes) || + in_array('groupofnames',$object_classes) || + in_array('group',$object_classes)) + + return 'ldap-ou.png'; + + elseif (in_array('applicationprocess',$object_classes)) + return 'process.png'; + + elseif (in_array('groupofuniquenames',$object_classes)) + return 'ldap-uniquegroup.png'; + + elseif (in_array('nlsproductcontainer',$object_classes)) + return 'n.png'; + + elseif (in_array('ndspkikeymaterial',$object_classes)) + return 'lock.png'; + + elseif (in_array('server',$object_classes)) + return 'server-small.png'; + + elseif (in_array('volume',$object_classes)) + return 'hard-drive.png'; + + elseif (in_array('ndscatcatalog',$object_classes)) + return 'catalog.png'; + + elseif (in_array('resource',$object_classes)) + return 'n.png'; + + elseif (in_array('ldapgroup',$object_classes)) + return 'ldap-server.png'; + + elseif (in_array('ldapserver',$object_classes)) + return 'ldap-server.png'; + + elseif (in_array('nisserver',$object_classes)) + return 'ldap-server.png'; + + elseif (in_array('rbscollection',$object_classes)) + return 'ldap-ou.png'; + + elseif (in_array('dfsconfiguration',$object_classes)) + return 'nt_machine.png'; + + elseif (in_array('applicationsettings',$object_classes)) + return 'server-settings.png'; + + elseif (in_array('aspenalias',$object_classes)) + return 'mail.png'; + + elseif (in_array('container',$object_classes)) + return 'folder.png'; + + elseif (in_array('ipnetwork',$object_classes)) + return 'network.png'; + + elseif (in_array('samserver',$object_classes)) + return 'server-small.png'; + + elseif (in_array('lostandfound',$object_classes)) + return 'find.png'; + + elseif (in_array('infrastructureupdate',$object_classes)) + return 'server-small.png'; + + elseif (in_array('filelinktracking',$object_classes)) + return 'files.png'; + + elseif (in_array('automountmap',$object_classes) || + in_array('automount',$object_classes)) + + return 'hard-drive.png'; + + elseif (strpos($rdn_value,'ipsec') === 0 || + strcasecmp($rdn_value,'IP Security') == 0|| + strcasecmp($rdn_value,'MSRADIUSPRIVKEY Secret') == 0 || + strpos($rdn_value,'BCKUPKEY_') === 0) + + return 'lock.png'; + + elseif (strcasecmp($rdn_value,'MicrosoftDNS') == 0) + return 'ldap-dc.png'; + + # Oh well, I don't know what it is. Use a generic icon. + else + return 'ldap-default.png'; +} + +/** + * Appends a servers base to a "sub" dn or returns the base. + * + * @param string The baseDN to be added if the DN is relative + * @param string The DN to be made absolute + * @return string|null Returns null if both base is null and sub_dn is null or empty + */ +function expand_dn_with_base($base,$sub_dn) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $empty_str = (is_null($sub_dn) || (($len=strlen(trim($sub_dn))) == 0)); + + if ($empty_str) + return $base; + + # If we have a string which doesn't need a base + elseif ($sub_dn[$len-1] != ',') + return $sub_dn; + + else + return sprintf('%s%s',$sub_dn,$base); +} + +/** + * Used to generate a random salt for crypt-style passwords. Salt strings are used + * to make pre-built hash cracking dictionaries difficult to use as the hash algorithm uses + * not only the user's password but also a randomly generated string. The string is + * stored as the first N characters of the hash for reference of hashing algorithms later. + * + * @param int The length of the salt string to generate. + * @return string The generated salt string. + */ +function random_salt($length) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $possible = '0123456789'. + 'abcdefghijklmnopqrstuvwxyz'. + 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'. + './'; + $str = ''; + mt_srand((double)microtime() * 1000000); + + while (strlen($str) < $length) + $str .= substr($possible,(rand()%strlen($possible)),1); + + return $str; +} + +/** + * Given a DN string, this returns the 'RDN' portion of the string. + * For example. given 'cn=Manager,dc=example,dc=com', this function returns + * 'cn=Manager' (it is really the exact opposite of ds_ldap::getContainer()). + * + * @param string The DN whose RDN to return. + * @param boolean If true, include attributes in the RDN string. See http://php.net/ldap_explode_dn for details + * @return string The RDN + */ +function get_rdn($dn,$include_attrs=0,$decode=false) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (is_null($dn)) + return null; + + $rdn = pla_explode_dn($dn,$include_attrs); + if (! count($rdn) || ! isset($rdn[0])) + return $dn; + + if ($decode) + $rdn = dn_unescape($rdn[0]); + else + $rdn = $rdn[0]; + + return $rdn; +} + +/** + * Split an RDN into its attributes + */ +function rdn_explode($rdn) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # Setup to work out our RDN. + $rdnarray = explode('\+',$rdn); + + # Capture items that have +, but are not an attribute + foreach ($rdnarray as $index => $val) { + if (preg_match('/=/',$val)) + $validindex = $index; + + if (! preg_match('/=/',$val)) { + $rdnarray[$validindex] .= '+'.$val; + unset($rdnarray[$index]); + } + } + + return $rdnarray; +} + +/** + * Given an LDAP error number, returns a verbose description of the error. + * This function parses ldap_error_codes.txt and looks up the specified + * ldap error number, and returns the verbose message defined in that file. + * + * + * Array ( + * [title] => "Invalid Credentials" + * [description] => "An invalid username and/or password was supplied to the LDAP server." + * ) + * + * + * @param string The hex error number (ie, "0x42") of the LDAP error of interest. + * @return array An associative array contianing the error title and description like so: + */ +function pla_verbose_error($key) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + static $CACHE = array(); + + if (! count($CACHE)) { + $source_file = LIBDIR.'ldap_error_codes.txt'; + + if (! file_exists($source_file) || ! is_readable($source_file) || ! ($f = fopen($source_file,'r'))) + return false; + + $contents = fread($f,filesize($source_file)); + fclose($f); + $entries = array(); + preg_match_all("/0x[A-Fa-f0-9][A-Za-z0-9]\s+[0-9A-Za-z_]+\s+\"[^\"]*\"\n/", + $contents,$entries); + + foreach ($entries[0] as $values) { + $entry = array(); + preg_match("/(0x[A-Za-z0-9][A-Za-z0-9])\s+([0-9A-Za-z_]+)\s+\"([^\"]*)\"/",$values,$entry); + + $hex_code = isset($entry[1]) ? $entry[1] : null; + $title = isset($entry[2]) ? $entry[2] : null; + $desc = isset($entry[3]) ? $entry[3] : null; + $desc = preg_replace('/\s+/',' ',$desc); + $CACHE[$hex_code] = array('title'=>$title,'desc'=>$desc); + } + } + + if (isset($CACHE[$key])) + return $CACHE[$key]; + else + return array('title' => null,'desc' => null); +} + +/** + * Given an LDAP OID number, returns a verbose description of the OID. + * This function parses ldap_supported_oids.txt and looks up the specified + * OID, and returns the verbose message defined in that file. + * + * + * Array ( + * [title] => All Operational Attribute + * [ref] => RFC 3673 + * [desc] => An LDAP extension which clients may use to request the return of all operational attributes. + * ) + * + * + * @param string The OID number (ie, "1.3.6.1.4.1.4203.1.5.1") of the OID of interest. + * @return array An associative array contianing the OID title and description like so: + */ +function support_oid_to_text($key) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + static $CACHE = array(); + + $unknown = array(); + $unknown['desc'] = 'We have no description for this OID, if you know what this OID provides, please let us know. Please also include an RFC reference if it is available.'; + $unknown['title'] = 'Can you help with this OID info?'; + + if (! count($CACHE)) { + $source_file = LIBDIR.'ldap_supported_oids.txt'; + + if (! file_exists($source_file) || ! is_readable($source_file) || ! ($f = fopen($source_file,'r'))) + return false; + + $contents = fread($f,filesize($source_file)); + fclose($f); + $entries = array(); + preg_match_all("/[0-9]\..+\s+\"[^\"]*\"\n/",$contents,$entries); + + foreach ($entries[0] as $values) { + $entry = array(); + preg_match("/([0-9]\.([0-9]+\.)*[0-9]+)(\s+\"([^\"]*)\")?(\s+\"([^\"]*)\")?(\s+\"([^\"]*)\")?/",$values,$entry); + $oid_id = isset($entry[1]) ? $entry[1] : null; + + if ($oid_id) { + $CACHE[$oid_id]['title'] = isset($entry[4]) ? $entry[4] : null; + $CACHE[$oid_id]['ref'] = isset($entry[6]) ? $entry[6] : null; + $desc = isset($entry[8]) ? $entry[8] : sprintf('%s',$unknown['desc'],$unknown['title']); + $CACHE[$oid_id]['desc'] = preg_replace('/\s+/',' ',$desc); + } + } + } + + if (isset($CACHE[$key])) + return $CACHE[$key]; + else + return array( + 'title'=>$key, + 'ref'=>null, + 'desc'=>sprintf('%s',$unknown['desc'],$unknown['title'])); +} + +/** + * Print an LDAP error message + */ +function ldap_error_msg($msg,$errnum) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $body = ''; + + $errnum = ('0x'.str_pad(dechex($errnum),2,0,STR_PAD_LEFT)); + $verbose_error = pla_verbose_error($errnum); + + $body .= sprintf('',_('LDAP said'),$msg); + + if ($verbose_error) { + $body .= sprintf('',_('Error number'),$errnum,$verbose_error['title']); + $body .= sprintf('',_('Description'),$verbose_error['desc']); + + } else { + $body .= sprintf('',_('Error number'),$errnum); + $body .= sprintf('',_('Description'),_('no description available')); + } + + $body .= '
%s:%s
%s:%s (%s)
%s:%s
%s:%s
%s:(%s)
'; + + return $body; +} + +/** + * Draw the jpegPhoto image(s) for an entry wrapped in HTML. Many options are available to + * specify how the images are to be displayed. + * + * Usage Examples: + * + * draw_jpeg_photo(0,'cn=Bob,ou=People,dc=example,dc=com',"jpegPhoto",0,true,array('img_opts'=>"border: 1px; width: 150px")); + * draw_jpeg_photo(1,'cn=Fred,ou=People,dc=example,dc=com',null,1); + * + * + * @param object The Server to get the image from. + * @param string The DN of the entry that contains the jpeg attribute you want to draw. + * @param string The name of the attribute containing the jpeg data (usually 'jpegPhoto'). + * @param int Index of the attribute to draw + * @param boolean If true, draws a button beneath the image titled 'Delete' allowing the user + * to delete the jpeg attribute by calling JavaScript function deleteAttribute() provided + * in the default modification template. + * @param array Specifies optional image and CSS style attributes for the table tag. Supported keys are + * fixed_width, fixed_height, img_opts. + */ +function draw_jpeg_photo($server,$dn,$attr_name='jpegphoto',$index,$draw_delete_buttons=false,$options=array()) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $fixed = array(); + $fixed['width'] = isset($options['fixed_width']) ? $options['fixed_width'] : false; + $fixed['height'] = isset($options['fixed_height']) ? $options['fixed_height'] : false; + + if (is_null($server)) + $jpeg_data = $_SESSION['tmp']; + else + $jpeg_data = $server->getDNAttrValues($dn,null,LDAP_DEREF_NEVER,array($attr_name)); + + if (! isset($jpeg_data[$attr_name][$index]) || ! $jpeg_data[$attr_name][$index]) { + system_message(array( + 'title'=>_('Unable to retrieve image'), + 'body'=>sprintf('%s %s', + _('Could not fetch jpeg data for attribute'),$attr_name), + 'type'=>'warn')); + + # This should atleast generate some text that says "Image not available" + printf('Photo',$attr_name); + + return; + } + + $width = 0; + $height = 0; + + if (function_exists('getimagesize')) { + $jpeg_temp_dir = realpath($_SESSION[APPCONFIG]->getValue('jpeg','tmpdir').'/'); + if (! is_writable($jpeg_temp_dir)) + system_message(array( + 'title'=>_('Unable to write to jpeg tmp directory'), + 'body'=>_('Please set jpeg,tmpdir to a writable directory in the phpLDAPadmin config.php'), + 'type'=>'warn')); + + else { + # We have an image to display + $jpeg_filename = tempnam($jpeg_temp_dir.'/','pla'); + $outjpeg = @file_put_contents($jpeg_filename,$jpeg_data[$attr_name][$index]); + + if (! $outjpeg) { + system_message(array( + 'title'=>_('Error writing to jpeg tmp directory'), + 'body'=>sprintf(_('Please check jpeg,tmpdir is a writable directory in the phpLDAPadmin config.php'),$jpeg_temp_dir), + 'type'=>'warn')); + + } elseif ($outjpeg < 6) { + system_message(array( + 'title'=>sprintf('%s %s',$attr_name,_('contains errors')), + 'body'=>_('It appears that the jpeg image may not be a jpeg image'), + 'type'=>'warn')); + + } else { + $jpeg_dimensions = getimagesize($jpeg_filename); + $width = $jpeg_dimensions[0]; + $height = $jpeg_dimensions[1]; + } + + unlink($jpeg_filename); + } + } + + if ($width > 300) { + $scale_factor = 300 / $width; + $img_width = 300; + $img_height = intval($height * $scale_factor); + + } else { + $img_width = $width; + $img_height = $height; + } + + $href = sprintf('view_jpeg_photo.php?dn=%s&index=%s&attr=%s',rawurlencode($dn),$index,$attr_name); + + printf('',number_format($outjpeg),_('bytes'),$width,$height,_('pixels')); + + printf('Photo', + htmlspecialchars($href), + is_null($server) ? 'location=session' : sprintf('server_id=%s',$server->getIndex()), + (! $img_width || $fixed['width'] ? '' : sprintf('width="%s"',$img_width)), + (! $img_height || $fixed['height'] ? '' : sprintf('height="%s"',$img_height)), + (isset($options['img_opts']) ? $options['img_opts'] : '')); + + echo ''; + + if ($draw_delete_buttons) + # + printf('
%s', + $attr_name,_('Delete photo')); +} + +/** + * Return the list of available password types + * + * @todo Dynamically work this list out so we only present hashes that we can encrypt + */ +function password_types() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + return array( + ''=>'clear', + 'blowfish'=>'blowfish', + 'crypt'=>'crypt', + 'ext_des'=>'ext_des', + 'md5'=>'md5', + 'k5key'=>'k5key', + 'md5crypt'=>'md5crypt', + 'sha'=>'sha', + 'smd5'=>'smd5', + 'ssha'=>'ssha', + 'sha512'=>'sha512', + ); +} + +/** + * Hashes a password and returns the hash based on the specified enc_type. + * + * @param string The password to hash in clear text. + * @param string Standard LDAP encryption type which must be one of + * crypt, ext_des, md5crypt, blowfish, md5, sha, smd5, ssha, sha512, or clear. + * @return string The hashed password. + */ +function hash_password($password_clear,$enc_type) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $enc_type = strtolower($enc_type); + + switch($enc_type) { + case 'blowfish': + if (! defined('CRYPT_BLOWFISH') || CRYPT_BLOWFISH == 0) + error(_('Your system crypt library does not support blowfish encryption.'),'error','index.php'); + + # Hardcoded to second blowfish version and set number of rounds + $new_value = sprintf('{CRYPT}%s',crypt($password_clear,'$2a$12$'.random_salt(13))); + + break; + + case 'crypt': + if ($_SESSION[APPCONFIG]->getValue('password', 'no_random_crypt_salt')) + $new_value = sprintf('{CRYPT}%s',crypt($password_clear,substr($password_clear,0,2))); + else + $new_value = sprintf('{CRYPT}%s',crypt($password_clear,random_salt(2))); + + break; + + case 'ext_des': + # Extended des crypt. see OpenBSD crypt man page. + if (! defined('CRYPT_EXT_DES') || CRYPT_EXT_DES == 0) + error(_('Your system crypt library does not support extended DES encryption.'),'error','index.php'); + + $new_value = sprintf('{CRYPT}%s',crypt($password_clear,'_'.random_salt(8))); + + break; + + case 'k5key': + $new_value = sprintf('{K5KEY}%s',$password_clear); + + system_message(array( + 'title'=>_('Unable to Encrypt Password'), + 'body'=>'phpLDAPadmin cannot encrypt K5KEY passwords', + 'type'=>'warn')); + + break; + + case 'md5': + $new_value = sprintf('{MD5}%s',base64_encode(pack('H*',md5($password_clear)))); + break; + + case 'md5crypt': + if (! defined('CRYPT_MD5') || CRYPT_MD5 == 0) + error(_('Your system crypt library does not support md5crypt encryption.'),'error','index.php'); + + $new_value = sprintf('{CRYPT}%s',crypt($password_clear,'$1$'.random_salt(9))); + + break; + + case 'sha': + # Use php 4.3.0+ sha1 function, if it is available. + if (function_exists('sha1')) + $new_value = sprintf('{SHA}%s',base64_encode(pack('H*',sha1($password_clear)))); + elseif (function_exists('mhash')) + $new_value = sprintf('{SHA}%s',base64_encode(mhash(MHASH_SHA1,$password_clear))); + else + error(_('Your PHP install does not have the mhash() function. Cannot do SHA hashes.'),'error','index.php'); + + break; + + case 'ssha': + if (function_exists('mhash') && function_exists('mhash_keygen_s2k')) { + mt_srand((double)microtime()*1000000); + $salt = mhash_keygen_s2k(MHASH_SHA1,$password_clear,substr(pack('h*',md5(mt_rand())),0,8),4); + $new_value = sprintf('{SSHA}%s',base64_encode(mhash(MHASH_SHA1,$password_clear.$salt).$salt)); + + } else { + error(_('Your PHP install does not have the mhash() or mhash_keygen_s2k() function. Cannot do S2K hashes.'),'error','index.php'); + } + + break; + + case 'smd5': + if (function_exists('mhash') && function_exists('mhash_keygen_s2k')) { + mt_srand((double)microtime()*1000000); + $salt = mhash_keygen_s2k(MHASH_MD5,$password_clear,substr(pack('h*',md5(mt_rand())),0,8),4); + $new_value = sprintf('{SMD5}%s',base64_encode(mhash(MHASH_MD5,$password_clear.$salt).$salt)); + + } else { + error(_('Your PHP install does not have the mhash() or mhash_keygen_s2k() function. Cannot do S2K hashes.'),'error','index.php'); + } + + break; + + case 'sha512': + if (function_exists('openssl_digest') && function_exists('base64_encode')) { + $new_value = sprintf('{SHA512}%s', base64_encode(openssl_digest($password_clear, 'sha512', true))); + + } else { + error(_('Your PHP install doest not have the openssl_digest() or base64_encode() function. Cannot do SHA512 hashes. '),'error','index.php'); + } + + break; + + case 'clear': + default: + $new_value = $password_clear; + } + + return $new_value; +} + +/** + * Given a clear-text password and a hash, this function determines if the clear-text password + * is the password that was used to generate the hash. This is handy to verify a user's password + * when all that is given is the hash and a "guess". + * @param String The hash. + * @param String The password in clear text to test. + * @return Boolean True if the clear password matches the hash, and false otherwise. + */ +function password_check($cryptedpassword,$plainpassword,$attribute='userpassword') { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (in_array($attribute,array('sambalmpassword','sambantpassword'))) { + $smb = new smbHash; + + switch($attribute) { + case 'sambalmpassword': + if (strcmp($smb->lmhash($plainpassword),strtoupper($cryptedpassword)) == 0) + return true; + else + return false; + + case 'sambantpassword': + if (strcmp($smb->nthash($plainpassword),strtoupper($cryptedpassword)) == 0) + return true; + else + return false; + } + + return false; + } + + if (preg_match('/{([^}]+)}(.*)/',$cryptedpassword,$matches)) { + $cryptedpassword = $matches[2]; + $cypher = strtolower($matches[1]); + + } else { + $cypher = null; + } + + switch($cypher) { + # SSHA crypted passwords + case 'ssha': + # Check php mhash support before using it + if (function_exists('mhash')) { + $hash = base64_decode($cryptedpassword); + + # OpenLDAP uses a 4 byte salt, SunDS uses an 8 byte salt - both from char 20. + $salt = substr($hash,20); + $new_hash = base64_encode(mhash(MHASH_SHA1,$plainpassword.$salt).$salt); + + if (strcmp($cryptedpassword,$new_hash) == 0) + return true; + else + return false; + + } else { + error(_('Your PHP install does not have the mhash() function. Cannot do SHA hashes.'),'error','index.php'); + } + + break; + + # Salted MD5 + case 'smd5': + # Check php mhash support before using it + if (function_exists('mhash')) { + $hash = base64_decode($cryptedpassword); + $salt = substr($hash,16); + $new_hash = base64_encode(mhash(MHASH_MD5,$plainpassword.$salt).$salt); + + if (strcmp($cryptedpassword,$new_hash) == 0) + return true; + else + return false; + + } else { + error(_('Your PHP install does not have the mhash() function. Cannot do SHA hashes.'),'error','index.php'); + } + + break; + + # SHA crypted passwords + case 'sha': + if (strcasecmp(password_hash($plainpassword,'sha'),'{SHA}'.$cryptedpassword) == 0) + return true; + else + return false; + + break; + + # MD5 crypted passwords + case 'md5': + if( strcasecmp(password_hash($plainpassword,'md5'),'{MD5}'.$cryptedpassword) == 0) + return true; + else + return false; + + break; + + # Crypt passwords + case 'crypt': + # Check if it's blowfish crypt + if (preg_match('/^\\$2+/',$cryptedpassword)) { + + # Make sure that web server supports blowfish crypt + if (! defined('CRYPT_BLOWFISH') || CRYPT_BLOWFISH == 0) + error(_('Your system crypt library does not support blowfish encryption.'),'error','index.php'); + + list($version,$rounds,$salt_hash) = explode('$',$cryptedpassword); + + if (crypt($plainpassword,'$'.$version.'$'.$rounds.'$'.$salt_hash) == $cryptedpassword) + return true; + else + return false; + } + + # Check if it's an crypted md5 + elseif (strstr($cryptedpassword,'$1$')) { + + # Make sure that web server supports md5 crypt + if (! defined('CRYPT_MD5') || CRYPT_MD5 == 0) + error(_('Your system crypt library does not support md5crypt encryption.'),'error','index.php'); + + list($dummy,$type,$salt,$hash) = explode('$',$cryptedpassword); + + if (crypt($plainpassword,'$1$'.$salt) == $cryptedpassword) + return true; + else + return false; + } + + # Check if it's extended des crypt + elseif (strstr($cryptedpassword,'_')) { + + # Make sure that web server supports ext_des + if (! defined('CRYPT_EXT_DES') || CRYPT_EXT_DES == 0) + error(_('Your system crypt library does not support extended DES encryption.'),'error','index.php'); + + if (crypt($plainpassword,$cryptedpassword) == $cryptedpassword) + return true; + else + return false; + } + + # Password is plain crypt + else { + + if (crypt($plainpassword,$cryptedpassword) == $cryptedpassword) + return true; + else + return false; + } + + break; + + # SHA512 crypted passwords + case 'sha512': + if (strcasecmp(password_hash($plainpassword,'sha512'),'{SHA512}'.$cryptedpassword) == 0) + return true; + else + return false; + + break; + + # No crypt is given assume plaintext passwords are used + default: + if ($plainpassword == $cryptedpassword) + return true; + else + return false; + } +} + +/** + * Detects password encryption type + * + * Returns crypto string listed in braces. If it is 'crypt' password, + * returns crypto detected in password hash. Function should detect + * md5crypt, blowfish and extended DES crypt. If function fails to detect + * encryption type, it returns NULL. + * @param string Hashed password + * @return string + */ +function get_enc_type($user_password) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # Capture the stuff in the { } to determine if this is crypt, md5, etc. + $enc_type = null; + + if (preg_match('/{([^}]+)}/',$user_password,$enc_type)) + $enc_type = strtolower($enc_type[1]); + else + return null; + + # Handle crypt types + if (strcasecmp($enc_type,'crypt') == 0) { + + # No need to check for standard crypt, because enc_type is already equal to 'crypt'. + if (preg_match('/{[^}]+}\\$1\\$+/',$user_password)) + $enc_type = 'md5crypt'; + + elseif (preg_match('/{[^}]+}\\$2+/',$user_password)) + $enc_type = 'blowfish'; + + elseif (preg_match('/{[^}]+}_+/',$user_password)) + $enc_type = 'ext_des'; + } + + return $enc_type; +} + +/** + * Draws an HTML browse button which, when clicked, pops up a DN chooser dialog. + * @param string The name of the form element to which this chooser + * dialog will publish the user's choice. The form element must be a member + * of a form with the "name" or "id" attribute set in the form tag, and the element + * must also define "name" or "id" for JavaScript to uniquely identify it. + * Example $form_element values may include "creation_form.container" or + * "edit_form.member_uid". See /templates/modification/default.php for example usage. + * @param boolean (optional) If true, the function draws the localized text "choose" to the right of the button. + */ +function draw_chooser_link($form,$element,$include_choose_text=true,$rdn='none') { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $href = sprintf("javascript:dnChooserPopup('%s','%s','%s');",$form,$element,$rdn == 'none' ? '' : rawurlencode($rdn)); + $title = _('Click to popup a dialog to select an entry (DN) graphically'); + + printf('Find',$href,$title,IMGDIR); + + if ($include_choose_text) + printf('%s',$href,$title,_('browse')); +} + +/** + * Explode a DN into an array of its RDN parts. + * + * NOTE: When a multivalue RDN is passed to ldap_explode_dn, the results returns with 'value + value'; + * + * + * Array ( + * [0] => uid=ppratt + * [1] => ou=People + * [2] => dc=example + * [3] => dc=com + * ) + * + * + * @param string The DN to explode. + * @param int (optional) Whether to include attribute names (see http://php.net/ldap_explode_dn for details) + * @return array An array of RDN parts of this format: + */ +function pla_explode_dn($dn,$with_attributes=0) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + global $CACHE; + + if (isset($CACHE['explode'][$dn][$with_attributes])) { + if (DEBUG_ENABLED) + debug_log('Return CACHED result (%s) for (%s)',1,0,__FILE__,__LINE__,__METHOD__, + $CACHE['explode'][$dn][$with_attributes],$dn); + + return $CACHE['explode'][$dn][$with_attributes]; + } + + $dn = addcslashes($dn,'<>+";'); + + # split the dn + $result[0] = ldap_explode_dn(dn_escape($dn),0); + $result[1] = ldap_explode_dn(dn_escape($dn),1); + if (! $result[$with_attributes]) { + if (DEBUG_ENABLED) + debug_log('Returning NULL - NO result.',1,0,__FILE__,__LINE__,__METHOD__); + + return array(); + } + + # Remove our count value that ldap_explode_dn returns us. + unset($result[0]['count']); + unset($result[1]['count']); + + # Record the forward and reverse entries in the cache. + foreach ($result as $key => $value) { + # translate hex code into ascii for display + $result[$key] = dn_unescape($value); + + $CACHE['explode'][implode(',',$result[0])][$key] = $result[$key]; + $CACHE['explode'][implode(',',array_reverse($result[0]))][$key] = array_reverse($result[$key]); + } + + if (DEBUG_ENABLED) + debug_log('Returning (%s)',1,0,__FILE__,__LINE__,__METHOD__,$result[$with_attributes]); + + return $result[$with_attributes]; +} + +/** + * Parse a DN and escape any special characters + */ +function dn_escape($dn) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $olddn = $dn; + + # Check if the RDN has a comma and escape it. + while (preg_match('/([^\\\\]),(\s*[^=]*\s*),/',$dn)) + $dn = preg_replace('/([^\\\\]),(\s*[^=]*\s*),/','$1\\\\2C$2,',$dn); + + $dn = preg_replace('/([^\\\\]),(\s*[^=]*\s*)([^,])$/','$1\\\\2C$2$3',$dn); + + if (DEBUG_ENABLED) + debug_log('Returning (%s)',1,0,__FILE__,__LINE__,__METHOD__,$dn); + + return $dn; +} + +/** + * Parse a DN and unescape any special characters + */ +function dn_unescape($dn) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $unescape = function ($input) { + return preg_replace_callback('/\\\([0-9A-Fa-f]{2})/', function ($match) { + return "'" . chr(hexdec($match[1])) . "'"; + }, $input); + }; + + if (is_array($dn)) { + $a = array(); + + foreach ($dn as $key => $rdn) + $a[$key] = $unescape($rdn); + // $a[$key] = preg_replace('/\\\([0-9A-Fa-f]{2})/e',"''.chr(hexdec('\\1')).''",$rdn); + + return $a; + + } else { + return $unescape($dn); + // return preg_replace('/\\\([0-9A-Fa-f]{2})/e',"''.chr(hexdec('\\1')).''",$dn); + } +} + +/** + * Fetches the URL for the specified item. This is a convenience function for + * fetching project HREFs (like bugs) + * + * @param string One of "open_bugs", "add_bug", "donate", or "add_rfe" + * (rfe = request for enhancement) + * @return string The URL to the requested item. + */ +function get_href($type,$extra_info='') { + $sf = 'https://sourceforge.net'; + $pla = 'http://phpldapadmin.sourceforge.net'; + $group_id = '61828'; + $bug_atid = '498546'; + $rfe_atid = '498549'; + $forum_id = 'phpldapadmin-users'; + + switch($type) { + case 'add_bug': + return sprintf('%s/tracker/?func=add&group_id=%s&atid=%s',$sf,$group_id,$bug_atid); + case 'add_rfe': + return sprintf('%s/tracker/?func=add&group_id=%s&atid=%s',$sf,$group_id,$rfe_atid); + case 'credits': + return sprintf('%s/Credits',$pla); + case 'documentation': + return sprintf('%s/Documentation',$pla); + case 'donate': + return sprintf('%s/donate/index.php?group_id=%s',$sf,$group_id); + case 'forum': + return sprintf('%s/mailarchive/forum.php?forum_name=%s',$sf,$forum_id); + case 'logo': + if (! isset($_SERVER['HTTPS']) || strtolower($_SERVER['HTTPS']) != 'on') + $proto = 'http'; + else + $proto = 'https'; + + return isset($_SESSION) && ! $_SESSION[APPCONFIG]->getValue('appearance','remoteurls') ? '' : sprintf('%s://sflogo.sourceforge.net/sflogo.php?group_id=%s&type=10',$proto,$group_id); + case 'sf': + return sprintf('%s/projects/phpldapadmin',$sf); + case 'web': + return sprintf('%s',$pla); + default: + return null; + } +} + +/** + * Returns the current time as a double (including micro-seconds). + * + * @return double The current time in seconds since the beginning of the UNIX epoch (Midnight Jan. 1, 1970) + */ +function utime() { + $time = explode(' ',microtime()); + $usec = (double)$time[0]; + $sec = (double)$time[1]; + return $sec + $usec; +} + +/** + * Converts an array to a query-string with the option to exclude certain variables + * from the returned query string. This is convenient if callers want to convert the + * current GET query string or POST array into a string and replace certain + * variables with their own. + * + * @param array The associate array to convert whose form is such that the keys are the + * names of the variables and the values are said variables' values like this: + * + * Array ( + * [server_id] = 0, + * [dn] = "dc=example,dc=com", + * [attr] = "sn" + * ) + * + * This will produce a string like this: "server_id=0&dn=dc=example,dc=com&attr=sn" + * @param array (optional) An array of variables to exclude in the resulting string + * @return string The string created from the array. + */ +function array_to_query_string($array,$exclude_vars=array()) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (! is_array($array) || ! count($array)) + return ''; + + $str = ''; + $i = 0; + foreach ($array as $name => $val) + if (! in_array($name,$exclude_vars)) + if (is_array($val)) + foreach ($val as $v) { + if ($i++ > 0) + $str .= '&'; + + $str .= sprintf('%s[]=%s',rawurlencode($name),rawurlencode($v)); + } + + else { + if ($i++ > 0) + $str .= '&'; + + $str .= sprintf('%s=%s',rawurlencode($name),rawurlencode($val)); + } + + return $str; +} + +/** + * Reverses a DN such that the top-level RDN is first and the bottom-level RDN is last + * For example: + * + * cn=Brigham,ou=People,dc=example,dc=com + * + * Becomes: + * + * dc=com,dc=example,ou=People,cn=Brigham + * + * This makes it possible to sort lists of DNs such that they are grouped by container. + * + * @param string The DN to reverse + * @return string The reversed DN + * + * @see pla_compare_dns + * @see pla_explode_dns + */ +function pla_reverse_dn($dn) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + return (implode(',',array_reverse(pla_explode_dn($dn)))); +} + +/** + * Attribute sorting + */ +function sortAttrs($a,$b) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if ($a == $b) + return 0; + + $server = $_SESSION[APPCONFIG]->getServer(get_request('server_id','REQUEST')); + $attrs_display_order = arrayLower($_SESSION[APPCONFIG]->getValue('appearance','attr_display_order')); + + # Check if $a is in $attrs_display_order, get its key + $a_key = array_search($a->getName(),$attrs_display_order); + $b_key = array_search($b->getName(),$attrs_display_order); + + if ((! $a_key) && ($a_key !== 0)) + if ((! $a_key = array_search(strtolower($a->getFriendlyName()),$attrs_display_order)) && ($a_key !== 0)) + $a_key = count($attrs_display_order)+1; + + if ((! $b_key) && ($b_key !== 0)) + if ((! $b_key = array_search(strtolower($b->getFriendlyName()),$attrs_display_order)) && ($b_key !== 0)) + $b_key = count($attrs_display_order)+1; + + # Case where neither $a, nor $b are in $attrs_display_order, $a_key = $b_key = one greater than num elements. + # So we sort them alphabetically + if ($a_key === $b_key) + return strcasecmp($a->getFriendlyName(),$b->getFriendlyName()); + + # Case where at least one attribute or its friendly name is in $attrs_display_order + # return -1 if $a before $b in $attrs_display_order + return ($a_key < $b_key) ? -1 : 1; +} + +/** + * Reads an array and returns the array values back in lower case + * + * @param array $array The array to convert the values to lowercase. + * @returns array Array with values converted to lowercase. + */ +function arrayLower($array) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (! is_array($array)) + return $array; + + $newarray = array(); + foreach ($array as $key => $value) + $newarray[$key] = strtolower($value); + + return $newarray; +} + +/** + * Checks if a string exists in an array, ignoring case. + * + * @param string What you are looking for + * @param array The array that you think it is in. + * @return boolean True if its there, false if its not. + */ +function in_array_ignore_case($needle,$haystack) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (! is_array($haystack)) + return false; + + if (! is_string($needle)) + return false; + + $return = false; + + foreach ($haystack as $element) { + if (is_string($element) && (strcasecmp($needle,$element) == 0)) { + $return = true; + break; + } + } + + if (DEBUG_ENABLED) + debug_log('Returning (%s)',1,0,__FILE__,__LINE__,__METHOD__,$return); + + return $return; +} + +/** + * Gets a DN string using the user-configured tree_display_format string to format it. + */ +function draw_formatted_dn($server,$entry) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $dn = $entry->getDn(); + + $formats = $_SESSION[APPCONFIG]->getValue('appearance','tree_display_format'); + + foreach ($formats as $format) { + $has_none = false; + preg_match_all('/%[a-zA-Z_0-9]+/',$format,$tokens); + $tokens = $tokens[0]; + + if (DEBUG_ENABLED) + debug_log('The tokens are (%s)',1,0,__FILE__,__LINE__,__METHOD__,$tokens); + + foreach ($tokens as $token) { + if (strcasecmp($token,'%dn') == 0) + $format = str_replace($token,pretty_print_dn($dn),$format); + + elseif (strcasecmp($token,'%rdn') == 0) + $format = str_replace($token,pretty_print_dn($entry->getRDN()),$format); + + elseif (strcasecmp($token,'%rdnvalue') == 0) { + $rdn = get_rdn($dn,0,true); + $rdn_value = explode('=',$rdn,2); + $rdn_value = $rdn_value[1]; + $format = str_replace($token,$rdn_value,$format); + + } else { + $attr_name = str_replace('%','',$token); + $attr_values = $server->getDNAttrValue($dn,$attr_name); + + if (is_null($attr_values) || (count($attr_values) <= 0)) { + $display = '<'._('none').'>'; + $has_none = true; + + } elseif (is_array($attr_values)) + $display = implode(', ',$attr_values); + + else + $display = $attr_values; + + $format = str_replace($token,$display,$format); + } + } + + # If this format has all values available, use it. Otherwise, try the next one + if (!$has_none) + return $format; + } + + return $format; +} + +/** + * Server html select list + */ +function server_select_list($selected=null,$logged_on=false,$name='index',$isVisible=true,$js=null) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $count = 0; + $server_menu_html = sprintf(''; + + if ($count > 1) + return $server_menu_html; + + elseif ($count) + return sprintf('%s ', + $selected_server->getName(),$name,$selected_server->getIndex()); + + else + return ''; +} + +/** + * Converts a little-endian hex-number to one, that 'hexdec' can convert + */ +function littleEndian($hex) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $result = ''; + + for ($x=strlen($hex)-2;$x>= 0;$x=$x-2) + $result .= substr($hex,$x,2); + + return $result; +} + +function binSIDtoText($binsid) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $hex_sid = bin2hex($binsid); + $rev = hexdec(substr($hex_sid,0,2)); // Get revision-part of SID + $subcount = hexdec(substr($hex_sid,2,2)); // Get count of sub-auth entries + $auth = hexdec(substr($hex_sid,4,12)); // SECURITY_NT_AUTHORITY + + $result = "$rev-$auth"; + + for ($x=0;$x<$subcount;$x++) { + $subauth[$x] = hexdec(littleEndian(substr($hex_sid,16+($x*8),8))); // get all SECURITY_NT_AUTHORITY + $result .= sprintf('-%s',$subauth[$x]); + } + + return $result; +} + +/** + * Query LDAP and return a hash. + * + * @param string The base DN to use. + * @param string LDAP Query filter. + * @param string LDAP attribute to use as key. + * @param array Attributes to use as values. + * @param boolean Specify false to not sort results by DN + * or true to have the returned array sorted by DN (uses ksort) + * or an array of attribute names to sort by attribute values + * @return array Array of values keyed by $key. + */ +function return_ldap_hash($base,$filter,$key,$attrs,$sort=true) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $server = $_SESSION[APPCONFIG]->getServer(get_request('server_id','REQUEST')); + $key = strtolower($key); + + $query = array(); + $query['base'] = $base; + $query['filter'] = $filter; + $query['attrs'] = $attrs; + $search = $server->query($query,null); + + $results = array(); + + foreach ($search as $dn => $values) + if (isset($values[$key])) + if (is_array($values[$key])) + foreach ($values[$key] as $i => $k) + foreach ($attrs as $attr) { + $lattr = strtolower($attr); + if (isset($values[$lattr])) { + $v = ''; + + if (is_array($values[$lattr]) && isset($values[$lattr][$i])) + $v = $values[$lattr][$i]; + + if (is_string($v) && (strlen($v) > 0)) + $results[$k][$attr] = $v; + } + } + + else + foreach ($attrs as $attr) { + $lattr = strtolower($attr); + if (isset($values[$lattr])) + $results[$values[$key]][$attr] = $values[$lattr]; + } + + if ($sort) + masort($results,is_array($sort) ? implode(',',$sort) : 'dn'); + + return $results; +} + +/** + * This function returns a string automatically generated + * based on the criteria defined in the array $criteria in config.php + */ +function password_generate() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $no_use_similiar = ! $_SESSION[APPCONFIG]->getValue('password','use_similar'); + $lowercase = $_SESSION[APPCONFIG]->getValue('password','lowercase'); + $uppercase = $_SESSION[APPCONFIG]->getValue('password','uppercase'); + $digits = $_SESSION[APPCONFIG]->getValue('password','numbers'); + $punctuation = $_SESSION[APPCONFIG]->getValue('password','punctuation'); + $length = $_SESSION[APPCONFIG]->getValue('password','length'); + + $outarray = array(); + + if ($no_use_similiar) { + $raw_lower = 'a b c d e f g h k m n p q r s t u v w x y z'; + $raw_numbers = '2 3 4 5 6 7 8 9'; + $raw_punc = '# $ % ^ & * ( ) _ - + = . , [ ] { } :'; + + } else { + $raw_lower = 'a b c d e f g h i j k l m n o p q r s t u v w x y z'; + $raw_numbers = '1 2 3 4 5 6 7 8 9 0'; + $raw_punc = '# $ % ^ & * ( ) _ - + = . , [ ] { } : |'; + } + + $llower = explode(' ',$raw_lower); + shuffle($llower); + $lupper = explode(' ',strtoupper($raw_lower)); + shuffle($lupper); + $numbers = explode(' ',$raw_numbers); + shuffle($numbers); + $punc = explode(' ',$raw_punc); + shuffle($punc); + + if ($lowercase > 0) + $outarray = array_merge($outarray,a_array_rand($llower,$lowercase)); + + if ($uppercase > 0) + $outarray = array_merge($outarray,a_array_rand($lupper,$uppercase)); + + if ($digits > 0) + $outarray = array_merge($outarray,a_array_rand($numbers,$digits)); + + if ($punctuation > 0) + $outarray = array_merge($outarray,a_array_rand($punc,$punctuation)); + + $num_spec = $lowercase + $uppercase + $digits + $punctuation; + + if ($num_spec < $length) { + $leftover = array(); + if ($lowercase > 0) + $leftover = array_merge($leftover,$llower); + if ($uppercase > 0) + $leftover = array_merge($leftover,$lupper); + if ($digits > 0) + $leftover = array_merge($leftover,$numbers); + if ($punctuation > 0) + $leftover = array_merge($leftover,$punc); + + if (count($leftover) == 0) + $leftover = array_merge($leftover,$llower,$lupper,$numbers,$punc); + + shuffle($leftover); + $outarray = array_merge($outarray,a_array_rand($leftover,$length-$num_spec)); + } + + shuffle($outarray); + $return = implode('',$outarray); + + if (DEBUG_ENABLED) + debug_log('Returning (%s)',1,0,__FILE__,__LINE__,__METHOD__,$return); + + return $return; +} + +/** + * This function returns an array of $num_req values + * randomly picked from the $input array + * + * @param array Array of values + * @param integer Number of values in returned array + * @return string The padded string + */ +function a_array_rand($input,$num_req) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (count($input) == 0) + return array(); + + if ($num_req < 1) + return array(); + + $return = array(); + if ($num_req > count($input)) { + for($i = 0; $i < $num_req; $i++) { + $idx = array_rand($input,1); + $return[] = $input[$idx]; + } + + } else { + $idxlist = array_rand($input,$num_req); + if ($num_req == 1) + $idxlist = array($idxlist); + + for($i = 0; $i < count($idxlist); $i++) + $return[] = $input[$idxlist[$i]]; + } + + if (DEBUG_ENABLED) + debug_log('Returning (%s)',1,0,__FILE__,__LINE__,__METHOD__,$return); + + return $return; +} + +/** + * This is for Opera. By putting "random junk" in the query string, it thinks + * that it does not have a cached version of the page, and will thus + * fetch the page rather than display the cached version + */ +function random_junk() { + $time = gettimeofday(); + return md5(strtotime('now').$time['usec']); +} + +/** + * Returns a HTML id that can be used in the URL after the #. + * + * @param string The DN to pretty-print. + * @return string + */ +function htmlid($sid,$dn) { + return sprintf('SID%s:%s',$sid,preg_replace('/[\ =,]/','_',$dn)); +} + +/** + * Is PLA configured for AJAX display + */ +function isAjaxEnabled() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (isset($_SESSION[APPCONFIG])) + return ($_SESSION[APPCONFIG]->getValue('appearance','tree') == 'AJAXTree'); + else + return false; +} +?> diff --git a/lib/hooks.php b/lib/hooks.php new file mode 100644 index 0000000..57066ed --- /dev/null +++ b/lib/hooks.php @@ -0,0 +1,201 @@ + and AlcÃ?ve + * @package phpLDAPadmin + */ + +/** + * Compares two arrays by numerically comparing their 'prority' + * value. Standard `cmp-like' function. + * + * @param a First element to compare. + * @param b Second element to compare. + * + * @return -1 if priority of first element is smaller than second + * element priority. 1 otherwise. + */ +function sort_array_by_priority($a,$b) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',257,0,__FILE__,__LINE__,__METHOD__,$fargs); + + return (($a['priority'] < $b['priority']) ? -1 : 1 ); +} + +/** + * Runs procedures attached to a hook. + * + * @param hook_name Name of hook to run. + * @param args Array of optional arguments set by phpldapadmin. It is normally in a form known by call_user_func_array() : + * + *
[ 'server_id' => 0,
+ * 'dn' => 'uid=epoussa,ou=tech,o=corp,o=fr' ]
+ * + * @return true if all procedures returned true, false otherwise. + */ +function run_hook($hook_name,$args) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',257,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $hooks = isset($_SESSION[APPCONFIG]) ? $_SESSION[APPCONFIG]->hooks : array(); + + if (! count($hooks) || ! array_key_exists($hook_name,$hooks)) { + if (DEBUG_ENABLED) + debug_log('Returning, HOOK not defined (%s)',257,0,__FILE__,__LINE__,__METHOD__,$hook_name); + + return true; + } + + $rollbacks = array(); + reset($hooks[$hook_name]); + + /* Execution of procedures attached is done using a numeric order + * since all procedures have been attached to the hook with a + * numerical weight. */ + while (list($key,$hook) = each($hooks[$hook_name])) { + if (DEBUG_ENABLED) + debug_log('Calling HOOK Function (%s)(%s)',257,0,__FILE__,__LINE__,__METHOD__, + $hook['hook_function'],$args); + + array_push($rollbacks,$hook['rollback_function']); + + $result = call_user_func_array($hook['hook_function'],$args); + if (DEBUG_ENABLED) + debug_log('Called HOOK Function (%s)',257,0,__FILE__,__LINE__,__METHOD__, + $hook['hook_function']); + + /* If a procedure fails (identified by a false return), its optional rollback is executed with + * the same arguments. After that, all rollbacks from + * previously executed procedures are executed in the reverse + * order. */ + if (! is_null($result) && $result == false) { + if (DEBUG_ENABLED) + debug_log('HOOK Function [%s] return (%s)',257,0,__FILE__,__LINE__,__METHOD__, + $hook['hook_function'],$result); + + while ($rollbacks) { + $rollback = array_pop($rollbacks); + + if ($rollback != false) { + if (DEBUG_ENABLED) + debug_log('HOOK Function Rollback (%s)',257,0,__FILE__,__LINE__,__METHOD__, + $rollback); + + call_user_func_array($rollback,$args); + } + } + + return false; + } + } + + return true; +} + +/** + * Adds a procedure to a hook for later execution. + * + * @param hook_name Name of the hook. + * @param hook_function Name of the php function called upon hook trigger. + * @param priority Numeric priority. Lowest means procedure will be executed before. + * @param rollback_function Name of the php rollback function called upon failure. + */ +function add_hook($hook_name,$hook_function,$priority=0,$rollback_function=null) { + if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',257,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # First, see if the hook function exists. + if (! function_exists($hook_function)) { + system_message(array( + 'title'=>_('Hook function does not exist'), + 'body'=>sprintf('Hook name: %s
Hook function: %s',$hook_name,$hook_function), + 'type'=>'warn')); + + return; + } + + if (! array_key_exists($hook_name,$_SESSION[APPCONFIG]->hooks)) + $_SESSION[APPCONFIG]->hooks[$hook_name] = array(); + + remove_hook($hook_name,$hook_function,-1,null); + + array_push($_SESSION[APPCONFIG]->hooks[$hook_name],array( + 'priority' => $priority, + 'hook_function' => $hook_function, + 'rollback_function' => $rollback_function)); + + uasort($_SESSION[APPCONFIG]->hooks[$hook_name],'sort_array_by_priority'); +} + +/** + * Removes a procedure from a hook, based on a filter. + * + * @param hook_name Name of the hook. + * @param priority Numeric priority. If set, all procedures of that priority will be removed. + * @param hook_function Name of the procedure function. If set, all procedures that call this function will be removed. + * @param rollback_function Name of the php rollback function called upon failure. If set, all + * procedures that call this function as a rollback will be removed. + */ +function remove_hook($hook_name,$hook_function,$priority,$rollback_function) { + if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',257,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (array_key_exists($hook_name,$_SESSION[APPCONFIG]->hooks)) { + reset($_SESSION[APPCONFIG]->hooks[$hook_name]); + + while (list($key,$hook) = each($_SESSION[APPCONFIG]->hooks[$hook_name])) { + if (($priority >= 0 && $priority == $hook['priority']) || + ($hook_function && $hook_function == $hook['hook_function']) || + ($rollback_function && $rollback_function == $hook['rollback_function'])) { + + unset($_SESSION[APPCONFIG]->hooks[$hook_name][$key]); + } + } + } +} + +/** + * Removes all procedures from a hook. + * + * @param hook_name Name of hook to clear. + */ +function clear_hooks($hook_name) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',257,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (array_key_exists($hook_name,$_SESSION[APPCONFIG]->hooks)) + unset($_SESSION[APPCONFIG]->hooks[$hook_name]); +} + +$hooks = array(); + +# Evaluating user-made hooks +if (is_dir(HOOKSDIR.'functions')) { + $hooks['dir'] = dir(HOOKSDIR.'functions'); + + while ($hooks['file'] = $hooks['dir']->read()) { + $script = sprintf('%s/%s/%s',HOOKSDIR,'functions',$hooks['file']); + + if (is_file($script) && preg_match('/php[0-9]?$/',$hooks['file'])) + require_once $script; + } + + $hooks['dir']->close(); +} +?> diff --git a/lib/import_functions.php b/lib/import_functions.php new file mode 100644 index 0000000..23a52f4 --- /dev/null +++ b/lib/import_functions.php @@ -0,0 +1,609 @@ +server_id = $server_id; + $this->template_id = $template_id; + + $this->accept(); + } + + static function types() { + $type = array(); + + $details = ImportLDIF::getType(); + $type[$details['type']] = $details; + + return $type; + } + + private function accept() { + switch($this->template_id) { + case 'LDIF': + $this->template = new ImportLDIF($this->server_id); + break; + + default: + system_message(array( + 'title'=>sprintf('%s %s',_('Unknown Import Type'),$this->template_id), + 'body'=>_('phpLDAPadmin has not been configured for that import type'), + 'type'=>'warn'),'index.php'); + + die(); + } + + $this->template->accept(); + } + + public function getTemplate() { + return $this->template; + } +} + +/** + * Import Class + * + * This abstract classes provides all the common methods and variables for the + * custom import classes. + * + * @package phpLDAPadmin + * @subpackage Import + */ +abstract class Import { + protected $server_id = null; + protected $input = null; + protected $source = array(); + + public function __construct($server_id) { + $this->server_id = $server_id; + } + + public function accept() { + if (get_request('ldif','REQUEST')) { + $this->input = explode("\n",get_request('ldif','REQUEST')); + $this->source['name'] = 'STDIN'; + $this->source['size'] = strlen(get_request('ldif','REQUEST')); + + } elseif (isset($_FILES['ldif_file']) && is_array($_FILES['ldif_file']) && ! $_FILES['ldif_file']['error']) { + $input = file_get_contents($_FILES['ldif_file']['tmp_name']); + $this->input = preg_split("/\n|\r\n|\r/",$input); + $this->source['name'] = $_FILES['ldif_file']['name']; + $this->source['size'] = $_FILES['ldif_file']['size']; + + } else { + system_message(array( + 'title'=>_('No import input'), + 'body'=>_('You must either upload a file or provide an import in the text box.'), + 'type'=>'error'),sprintf('cmd.php?cmd=import_form&server_id=%s',get_request('server_id','REQUEST'))); + + die(); + } + } + + public function getSource($attr) { + if (isset($this->source[$attr])) + return $this->source[$attr]; + else + return null; + } + + # @todo integrate hooks + public function LDAPimport() { + $template = $this->getTemplate(); + $server = $this->getServer(); + + switch ($template->getType()) { + case 'add': + return $server->add($template->getDN(),$template->getLDAPadd()); + + case 'modify': + return $server->modify($template->getDN(),$template->getLDAPmodify()); + + case 'moddn': + case 'modrdn': + return $server->rename($template->getDN(),$template->modrdn['newrdn'],$template->modrdn['newsuperior'],$template->modrdn['deleteoldrdn']); + + default: + debug_dump_backtrace(sprintf('Unknown template type %s',$template->getType()),1); + } + + return true; + } +} + +/** + * Import entries from LDIF + * + * The LDIF spec is described by RFC2849 + * http://www.ietf.org/rfc/rfc2849.txt + * + * @package phpLDAPadmin + * @subpackage Import + */ +class ImportLDIF extends Import { + private $_currentLineNumber = 0; + private $_currentLine = ''; + private $template; + public $error = array(); + + static public function getType() { + return array('type'=>'LDIF','description' => _('LDIF Import'),'extension'=>'ldif'); + } + + protected function getTemplate() { + return $this->template; + } + + protected function getServer() { + return $_SESSION[APPCONFIG]->getServer($this->server_id); + } + + public function readEntry() { + static $haveVersion = false; + + if ($lines = $this->nextLines()) { + + # If we have a version line. + if (! $haveVersion && preg_match('/^version:/',$lines[0])) { + list($text,$version) = $this->getAttrValue(array_shift($lines)); + + if ($version != 1) + return $this->error(sprintf('%s %s',_('LDIF import only suppports version 1'),$version),$lines); + + $haveVersion = true; + $lines = $this->nextLines(); + } + + $server = $this->getServer(); + + # The first line should be the DN + if (preg_match('/^dn:/',$lines[0])) { + list($text,$dn) = $this->getAttrValue(array_shift($lines)); + + # The second line should be our changetype + if (preg_match('/^changetype:[ ]*(delete|add|modrdn|moddn|modify)/i',$lines[0])) { + $attrvalue = $this->getAttrValue($lines[0]); + $changetype = $attrvalue[1]; + array_shift($lines); + + } else + $changetype = 'add'; + + $this->template = new Template($this->server_id,null,null,$changetype); + + switch ($changetype) { + case 'add': + $rdn = get_rdn($dn); + $container = $server->getContainer($dn); + + $this->template->setContainer($container); + $this->template->accept(); + + $this->getAddDetails($lines); + $this->template->setRDNAttributes($rdn); + + return $this->template; + + break; + + case 'modify': + if (! $server->dnExists($dn)) + return $this->error(sprintf('%s %s',_('DN does not exist'),$dn),$lines); + + $this->template->setDN($dn); + $this->template->accept(false,true); + + return $this->getModifyDetails($lines); + + break; + + case 'moddn': + case 'modrdn': + if (! $server->dnExists($dn)) + return $this->error(sprintf('%s %s',_('DN does not exist'),$dn),$lines); + + $this->template->setDN($dn); + $this->template->accept(); + + return $this->getModRDNAttributes($lines); + + break; + + default: + if (! $server->dnExists($dn)) + return $this->error(_('Unkown change type'),$lines); + } + + } else + return $this->error(_('A valid dn line is required'),$lines); + + } else + return false; + } + + /** + * Get the Attribute and Decoded Value + */ + private function getAttrValue($line) { + list($attr,$value) = explode(':',$line,2); + + # Get the DN + if (substr($value,0,1) == ':') + $value = base64_decode(trim(substr($value,1))); + else + $value = trim($value); + + return array($attr,$value); + } + + /** + * Get the lines of the next entry + * + * @return The lines (unfolded) of the next entry + */ + private function nextLines() { + $current = array(); + $endEntryFound = false; + + if ($this->hasMoreEntries() && ! $this->eof()) { + # The first line is the DN one + $current[0]= trim($this->_currentLine); + + # While we end on a blank line, fetch the attribute lines + $count = 0; + while (! $this->eof() && ! $endEntryFound) { + # Fetch the next line + $this->nextLine(); + + /* If the next line begin with a space, we append it to the current row + * else we push it into the array (unwrap)*/ + if ($this->isWrappedLine()) + $current[$count] .= trim($this->_currentLine); + elseif ($this->isCommentLine()) {} + # Do nothing + elseif (! $this->isBlankLine()) + $current[++$count] = trim($this->_currentLine); + else + $endEntryFound = true; + } + + # Return the LDIF entry array + return $current; + + } else + return array(); + } + + /** + * Private method to check if there is more entries in the input. + * + * @return boolean true if an entry was found, false otherwise. + */ + private function hasMoreEntries() { + $entry_found = false; + + while (! $this->eof() && ! $entry_found) { + # If it's a comment or blank line, switch to the next line + if ($this->isCommentLine() || $this->isBlankLine()) { + # Do nothing + $this->nextLine(); + + } else { + $this->_currentDnLine = $this->_currentLine; + $this->dnLineNumber = $this->_currentLineNumber; + $entry_found = true; + } + } + + return $entry_found; + } + + /** + * Helper method to switch to the next line + */ + private function nextLine() { + $this->_currentLineNumber++; + $this->_currentLine = array_shift($this->input); + } + + /** + * Check if it's a comment line. + * + * @return boolean true if it's a comment line,false otherwise + */ + private function isCommentLine() { + return substr(trim($this->_currentLine),0,1) == '#' ? true : false; + } + + /** + * Check if it's a wrapped line. + * + * @return boolean true if it's a wrapped line,false otherwise + */ + private function isWrappedLine() { + return substr($this->_currentLine,0,1) == ' ' ? true : false; + } + + /** + * Check if is the current line is a blank line. + * + * @return boolean if it is a blank line,false otherwise. + */ + private function isBlankLine() { + return(trim($this->_currentLine) == '') ? true : false; + } + + /** + * Returns true if we reached the end of the input. + * + * @return boolean true if it's the end of file, false otherwise. + */ + public function eof() { + return count($this->input) > 0 ? false : true; + } + + private function error($msg,$data) { + $this->error['message'] = sprintf('%s [%s]',$msg,$this->template ? $this->template->getDN() : ''); + $this->error['line'] = $this->_currentLineNumber; + $this->error['data'] = $data; + $this->error['changetype'] = $this->template ? $this->template->getType() : 'Not set'; + + return false; + } + + /** + * Method to retrieve the attribute value of a ldif line, + * and get the base 64 decoded value if it is encoded + */ + private function getAttributeValue($value) { + $return = ''; + + if (substr($value,0,1) == '<') { + $url = trim(substr($value,1)); + + if (preg_match('^file://',$url)) { + $filename = substr(trim($url),7); + + if ($fh = @fopen($filename,'rb')) { + if (! $return = @fread($fh,filesize($filename))) + return $this->error(_('Unable to read file for'),$value); + + @fclose($fh); + + } else + return $this->error(_('Unable to open file for'),$value); + + } else + return $this->error(_('The url attribute value should begin with file:// for'),$value); + + # It's a string + } else + $return = $value; + + return trim($return); + } + + /** + * Build the attributes array when the change type is add. + */ + private function getAddDetails($lines) { + foreach ($lines as $line) { + list($attr,$value) = $this->getAttrValue($line); + + if (is_null($attribute = $this->template->getAttribute($attr))) { + $attribute = $this->template->addAttribute($attr,array('values'=>array($value))); + $attribute->justModified(); + + } else + if ($attribute->hasBeenModified()) + $attribute->addValue($value); + else + $attribute->setValue(array($value)); + } + } + + /** + * Build the attributes array for the entry when the change type is modify + */ + private function getModifyDetails($lines) { + if (! count($lines)) + return $this->error(_('Missing attributes for'),$lines); + + # While the array is not empty + while (count($lines)) { + $processline = false; + $deleteattr = false; + + # Get the current line with the action + $currentLine = array_shift($lines); + $attrvalue = $this->getAttrValue($currentLine); + $action_attribute = $attrvalue[0]; + $action_attribute_value = $attrvalue[1]; + + if (! in_array($action_attribute,array('add','delete','replace'))) + return $this->error(_('Missing modify command add, delete or replace'),array_merge(array($currentLine),$lines)); + + $processline = true; + switch ($action_attribute) { + case 'add': + + break; + + case 'delete': + $attribute = $this->template->getAttribute($action_attribute_value); + + if (is_null($attribute)) + return $this->error(sprintf('%s %s',_('Attempting to delete a non existant attribute'),$action_attribute_value), + array_merge(array($currentLine),$lines)); + + $deleteattr = true; + + break; + + case 'replace': + $attribute = $this->template->getAttribute($action_attribute_value); + + if (is_null($attribute)) + return $this->error(sprintf('%s %s',_('Attempting to replace a non existant attribute'),$action_attribute_value), + array_merge(array($currentLine),$lines)); + + break; + + default: + debug_dump_backtrace(sprintf('Unknown action %s',$action_attribute),1); + } + + # Fetch the attribute for the following line + $currentLine = array_shift($lines); + + while ($processline && trim($currentLine) && (trim($currentLine) != '-')) { + $processline = false; + + # If there is a valid line + if (preg_match('/:/',$currentLine)) { + $attrvalue = $this->getAttrValue($currentLine); + $attr = $attrvalue[0]; + $attribute_value_part = $attrvalue[1]; + + # Check that it correspond to the one specified before + if ($attr == $action_attribute_value) { + # Get the value part of the attribute + $attribute_value = $this->getAttributeValue($attribute_value_part); + + $attribute = $this->template->getAttribute($attr); + + # This should be a add/replace operation + switch ($action_attribute) { + case 'add': + if (is_null($attribute)) + $attribute = $this->template->addAttribute($attr,array('values'=>array($attribute_value_part))); + else + $attribute->addValue($attribute_value_part,-1); + + $attribute->justModified(); + + break; + + case 'delete': + $deleteattr = false; + + if (($key = array_search($attribute_value_part,$attribute->getValues())) !== false) + $attribute->delValue($key); + else + return $this->error(sprintf('%s %s',_('Delete value doesnt exist in DN'),$attribute_value_part), + array_merge(array($currentLine),$lines)); + + + break; + + case 'replace': + if ($attribute->hasBeenModified()) + $attribute->addValue($attribute_value_part,-1); + else + $attribute->setValue(array($attribute_value_part)); + + break; + + default: + debug_dump_backtrace(sprintf('Unexpected operation %s',$action_attribute)); + } + + } else + return $this->error(sprintf('%s %s',_('The attribute to modify doesnt match the one specified by'),$action_attribute), + array_merge(array($currentLine),$lines)); + + } else + return $this->error(sprintf('%s %s',_('Attribute not valid'),$currentLine), + array_merge(array($currentLine),$lines)); + + $currentLine = array_shift($lines); + if (trim($currentLine)) + $processline = true; + } + + if ($action_attribute == 'delete' && $deleteattr) + $attribute->setValue(array()); + + } + + return $this->template; + } + + /** + * Build the attributes for the entry when the change type is modrdn + */ + function getModRDNAttributes($lines) { + $server = $this->getServer(); + $attrs = array(); + + # MODRDN MODDN should only be 2 or 3 lines. + if (count($lines) != 2 && count($lines) !=3) + return $this->error(_('Invalid entry'),$lines); + + else { + $currentLine = array_shift($lines); + + # First we need to check if there is an new rdn specified + if (preg_match('/^newrdn:(:?)/',$currentLine)) { + + $attrvalue = $this->getAttrValue($currentLine); + $attrs['newrdn'] = $attrvalue[1]; + + $currentLine = array_shift($lines); + + if (preg_match('/^deleteoldrdn:[ ]*(0|1)/',$currentLine)) { + $attrvalue = $this->getAttrValue($currentLine); + $attrs['deleteoldrdn'] = $attrvalue[1]; + + # Switch to the possible new superior attribute + if (count($lines)) { + $currentLine = array_shift($lines); + + # then the possible new superior attribute + if (preg_match('/^newsuperior:/',$currentLine)) { + $attrvalue = $this->getAttrValue($currentLine); + $attrs['newsuperior'] = $attrvalue[1]; + + } else + return $this->error(_('A valid newsuperior attribute should be specified'),$lines); + + } else + $attrs['newsuperior'] = $server->getContainer($this->template->getDN()); + + } else + return $this->error(_('A valid deleteoldrdn attribute should be specified'),$lines); + + } else + return $this->error(_('A valid newrdn attribute should be specified'),$lines); + } + + # Well do something out of the ordinary here, since our template doesnt handle mod[r]dn yet. + $this->template->modrdn = $attrs; + return $this->template; + } +} +?> diff --git a/lib/ldap_error_codes.txt b/lib/ldap_error_codes.txt new file mode 100644 index 0000000..8d4a2cc --- /dev/null +++ b/lib/ldap_error_codes.txt @@ -0,0 +1,94 @@ +0x00 LDAP_SUCCESS "The operation completed successfully." +0x01 LDAP_OPERATIONS_ERROR "An operations error occurred. This is + typically the result of an internal error on your LDAP server." +0x02 LDAP_PROTOCOL_ERROR "A protocol violation was detected." +0x03 LDAP_TIMELIMIT_EXCEEDED "The operation timed out waiting to complete." +0x04 LDAP_SIZELIMIT_EXCEEDED "The LDAP server refused to serve such a large result set." +0x05 LDAP_COMPARE_FALSE "A compare operation returned false." +0x06 LDAP_COMPARE_TRUE "A compare operation returned true." +0x07 LDAP_AUTH_METHOD_NOT_SUPPORTED "The authentication method you specified is not supported by + the LDAP server." +0x08 LDAP_STRONG_AUTH_REQUIRED "This LDAP server requires strong (encrypted) authentication, + not clear text." +0x09 LDAP_PARTIAL_RESULTS "The result set received is a partial result set." +0x0a LDAP_REFERRAL "" +0x0b LDAP_ADMINLIMIT_EXCEEDED "" +0x0c LDAP_UNAVAILABLE_CRITICAL_EXTENSION "" +0x0d LDAP_CONFIDENTIALITY_REQUIRED "" +0x0e LDAP_SASL_BIND_INPROGRESS "" +0x10 LDAP_NO_SUCH_ATTRIBUTE "That entry does not contain the attribute specified." +0x11 LDAP_UNDEFINED_TYPE "The attribute type specified is invalid." +0x12 LDAP_INAPPROPRIATE_MATCHING "This usually means that your LDAP server has not defined an equality rule + for the attribute you are trying to alter. This is not phpLDAPadmin's fault as the + LDAP server has refused to perform the operation (as well it should if there is + no equality rule for it to use for the operation). This generally applies when + adding a new value to a binary attribute, or removing a single value from a + multi-valued binary attribute." +0x13 LDAP_CONSTRAINT_VIOLATION "Some constraint would be violated by performing the action. This can happen when + you try to add a second value to a single-valued attribute, for example." +0x14 LDAP_TYPE_OR_VALUE_EXISTS "An attribute type or attribute value + specified already exists in the entry" +0x15 LDAP_INVALID_SYNTAX "An invalid attribute value was specified." +0x20 LDAP_NO_SUCH_OBJECT "That object does not exist." +0x21 LDAP_ALIAS_PROBLEM "An alias in the directory points to a + non-existent entry." +0x22 LDAP_INVALID_DN_SYNTAX "You used an invalid syntax in the specified DN." +0x23 LDAP_IS_LEAF "The object specified is a leaf" +0x24 LDAP_ALIAS_DEREF_PROBLEM "A problem was encountereed when + dereferencing an alias" +0x30 LDAP_INAPPROPRIATE_AUTH "Inappropriate authentication was + specified (e.g. LDAP_AUTH_SIMPLE was + specified and the entry does not have + a userPassword attribute)." +0x31 LDAP_INVALID_CREDENTIALS "Incorrect login DN and/or password." +0x32 LDAP_INSUFFICIENT_ACCESS "You do not have sufficient permissions + to perform that operation." +0x33 LDAP_BUSY "The LDAP server is busy." +0x34 LDAP_UNAVAILABLE "The LDAP server is unavailable." +0x35 LDAP_UNWILLING_TO_PERFORM "The LDAP server refused to perform the operation." +0x36 LDAP_LOOP_DETECT "A loop was detected." +0x3C LDAP_SORT_CONTROL_MISSING "" +0x3D LDAP_INDEX_RANGE_ERROR "" +0x40 LDAP_NAMING_VIOLATION "A naming violation occurred. This usually + means that you tried to change the value of an attribute that is used in the + DN. For example, if you change the 'cn' value of an entry whose DN is 'cn=Bob + Jones,dc=example,dc=com', you must also rename the entry to reflect the + change." +0x41 LDAP_OBJECT_CLASS_VIOLATION "You tried to perform an operation that would cause an undefined attribute + to exist or that would remove a required attribute, given the current list + of ObjectClasses. This can also occur if you do not + specify a structural objectClass when creating an entry, or if you specify + more than one structural objectClass." +0x42 LDAP_NOT_ALLOWED_ON_NONLEAF "The entry you tried to operate on has children. Usually this means you + tried to delete or rename the entry, which you cannot do to an entry + with children." +0x43 LDAP_NOT_ALLOWED_ON_RDN "You cannot preform that operation on a the relative distinguished name + (RDN) of an object." +0x44 LDAP_ALREADY_EXISTS "The object already exists. Usually you are trying to create a new object + on top of an existing one." +0x45 LDAP_NO_OBJECT_CLASS_MODS "ObjectClass modifications are not allowed." +0x46 LDAP_RESULTS_TOO_LARGE "" +0x47 LDAP_AFFECTS_MULTIPLE_DSAS "" +0x50 LDAP_OTHER "" +0x51 LDAP_SERVER_DOWN "The LDAP server is down." +0x52 LDAP_LOCAL_ERROR "" +0x53 LDAP_ENCODING_ERROR "" +0x54 LDAP_DECODING_ERROR "" +0x55 LDAP_TIMEOUT "" +0x56 LDAP_AUTH_UNKNOWN "" +0x57 LDAP_FILTER_ERROR "The LDAP search filter specified is inavlid." +0x58 LDAP_USER_CANCELLED "The user cancelled the LDAP operation." +0x59 LDAP_PARAM_ERROR "An ldap routine was called with a bad + parameter." +0x5a LDAP_NO_MEMORY "A memory allocation (e.g., malloc(3) + or other dynamic memory allocator) + call failed in an ldap library rou- + tine." +0x5b LDAP_CONNECT_ERROR "" +0x5c LDAP_NOT_SUPPORTED "The requested operation is not supported by the LDAP server." +0x5d LDAP_CONTROL_NOT_FOUND "" +0x5e LDAP_NO_RESULTS_RETURNED "The search came back empty." +0x5f LDAP_MORE_RESULTS_TO_RETURN "The LDAP server has more results that it would like to return." +0x60 LDAP_CLIENT_LOOP "" +0x61 LDAP_REFERRAL_LIMIT_EXCEEDED "This means that a search was performed that required the LDAP + server to follow a chain of referrals that was too lengthy." diff --git a/lib/ldap_supported_oids.txt b/lib/ldap_supported_oids.txt new file mode 100644 index 0000000..9fc5a66 --- /dev/null +++ b/lib/ldap_supported_oids.txt @@ -0,0 +1,187 @@ +# If you find some reliable and more meaningful descriptions to this OIDS, +# then please let the phpldapadmin development know so that this file can be +# more descriptive. + +1.2.826.0.1.334810.2.3 "LDAP_CONTROL_VALUESRETURNFILTER" +1.2.826.0.1.3344810.2.3 "Matched Values Control" "RFC 3876" "Describes a control for the LDAP v3 that is used to return a subset of attribute values from an entry. Specifically, only those values that match a 'values return' filter. Without support for this control, a client must retrieve all of an attribute's values and search for specific values locally." +1.2.826.0.1050.11.1.1 "Read-Only LDAP Server" +1.2.826.0.1050.11.2.1 "Read-Write LDAP Server" +1.2.826.0.1050.11.3.1 "White Pages Application LDAP Server" +1.2.826.0.1050.11.4.1 "Certificate Application LDAP Server" +1.2.826.0.1050.11.5.1 "Single Sign On Application LDAP Server" +1.2.840.113549.6.0.0 "Signed Operation" +1.2.840.113549.6.0.1 "Demand Signed Result" +1.2.840.113549.6.0.2 "Signed Result RFC 2649" +1.2.840.113556.1.4.319 "Simple Paged Results Manipulation Control Extension" "RFC 2696" "This control extension allows a client to control the rate at which an LDAP server returns the results of an LDAP search operation. This control may be useful when the LDAP client has limited resources and may not be able to process the entire result set from a given LDAP query, or when the LDAP client is connected over a low-bandwidth connection." +1.2.840.113556.1.4.417 "Show deleted control" "" "The LDAP_SERVER_SHOW_DELETED_OID control is used with an extended LDAP search function to specify that the search results include any deleted objects that match the search filter." +1.2.840.113556.1.4.473 "LDAP Server Sort Result extension" "draft-ietf-ldapext-sorting-01" "This control is included in the searchRequest message as part of the controls field of the LDAPMessage." +1.2.840.113556.1.4.474 "LDAP Server Sort Result extension response control" "" "This control is included in the searchResultDone message as part of the controls field of the LDAPMessage" +1.2.840.113556.1.4.521 "Cross-domain move control" "" "The LDAP_SERVER_CROSSDOM_MOVE_TARGET_OID control is used with an extended LDAP rename function to move an LDAP object from one domain to another. The control specifies the DNS hostname of the domain controller in the destination domain." +1.2.840.113556.1.4.528 "Server search notification control" "" "The LDAP_SERVER_NOTIFICATION_OID control is used with an extended LDAP asynchronous search function to register the client to be notified when changes are made to an object in Active Directory." +1.2.840.113556.1.4.529 "Extended DN control" "" "The LDAP_SERVER_EXTENDED_DN_OID control is used with an extended LDAP search function to request an extended form of an Active Directory object distinguished name. The extended form includes a string representation of the object objectGUID property. For security principal objects such as users, groups, and computers, the extended form also includes a string representation of the object objectSID property." +1.2.840.113556.1.4.616 "LDAP_CONTROL_REFERRALS" +1.2.840.113556.1.4.619 "Lazy commit control" "" "The LDAP_SERVER_LAZY_COMMIT_OID control is used to instruct the server to return the results of a DS modification command, such as add, delete, or replace, after it has been completed in memory, but before it has been committed to disk. The server can then return results quickly, and save the data to disk without holding the client." +1.2.840.113556.1.4.800 "LDAP_CAP_ACTIVE_DIRECTORY_OID" "" "This is an Actrive Directory Server (Win2k and later)." +1.2.840.113556.1.4.801 "Security descriptor flags control" "" "The LDAP_SERVER_SD_FLAGS_OID control is used to pass flags to the server to control various security descriptor results." +1.2.840.113556.1.4.802 "Attribute Range Option" "" "Server supports the Range property enabling clients to incremental retrieve values from multivalue attributes." +1.2.840.113556.1.4.803 "LDAP_MATCHING_RULE_BIT_AND" +1.2.840.113556.1.4.804 "LDAP_MATCHING_RULE_BIT_OR" +1.2.840.113556.1.4.805 "Tree Delete" "" "The LDAP_SERVER_TREE_DELETE_OID control is used with an extended LDAP delete function to delete an entire subtree in the directory." +1.2.840.113556.1.4.841 "Directory synchronization control" "" "The LDAP_SERVER_DIRSYNC_OID control enables an application to search the directory for objects changed from a previous state. It is also used with the extended LDAP search functions such as ldap_search_ext." +1.2.840.113556.1.4.906 "Microsoft Large Integer" +1.2.840.113556.1.4.970 "Get stats control (Stateless)" +1.2.840.113556.1.4.1302 "Microsoft OID used with DEN Attributes" +1.2.840.113556.1.4.1338 "Verify name control" "" "The LDAP_SERVER_VERIFY_NAME_OID control is used with extended LDAP add and modify requests to instruct the DC accepting the update which DC it should verify with, the existence of any DN attribute values." +1.2.840.113556.1.4.1339 "LDAP_SERVER_DOMAIN_SCOPE_OID" "" "The LDAP_SERVER_DOMAIN_SCOPE_OID control is used to instruct the LDAP server not to generate any referrals when completing a request. This control also limits any search using it to a single naming context." +1.2.840.113556.1.4.1340 "Search options control" "" " The LDAP_SERVER_SEARCH_OPTIONS_OID control is used to pass flags to the server to control various search behaviors." +1.2.840.113556.1.4.1413 "LDAP ease modify restrictions" "" "Allows an LDAP modify to work under less restrictive conditions. Without it, a delete will fail if an attribute does not exist, and an add will fail if an attribute already exists." +1.2.840.113556.1.4.1504 "Attribute scoped query control" "" "The LDAP_SERVER_ASQ_OID control is used with an extended LDAP search function to force the query to be based on a specific DN-valued attribute. Only one source attribute can be specified with this control and the search request is limited to base object scoped queries." +1.2.840.113556.1.4.1670 "LDAP_CAP_ACTIVE_DIRECTORY_V51_OID" "" "This server is a Whistler Active Directory server (Win2k3 and later)." +1.2.840.113556.1.4.1781 "Fast concurrent bind extended operation" "" "The Microsoft LDAP API will send an extended request with this name to Active Directory to request that all binds on this connection be processed as 'fast' binds." +1.2.840.113556.1.4.1791 "LDAP_CAP_ACTIVE_DIRECTORY_LDAP_INTEG_OID" "" "LDAP server is capable of doing signing and sealing on an NTLM authenticated connection, and that the server is capable of performing subsequent binds on a signed or sealed connection." +1.2.840.113556.1.4.1852 "LDAP_SERVER_QUOTA_CONTROL_OID" "" "The LDAP_SERVER_QUOTA_CONTROL_OID control is used to pass the SID of a security principal, whose quota is being queried, to the server in a LDAP search operation." +1.3.6.1.1.7.1 "LCUP Sync Request Control. RFC 3928 control" +1.3.6.1.1.7.2 "LCUP Sync Update Control. RFC 3928 control" +1.3.6.1.1.7.3 "LCUP Sync Done Control. RFC 3928 control" +1.3.6.1.1.8 "Cancel Operation. RFC 3909 extension" +1.3.6.1.1.12 "Assertion Control" "RFC 4511" "The assertion control allows the client to specify a condition that must be true for the operation to be processed normally." +1.3.6.1.1.13.1 "Pre-Read Controls" "" "The Pre-Read request control, indicates that a copy of the entry before application of update is to be returned." +1.3.6.1.1.13.2 "Post-Read Controls" "" "The Pre-Read request control, indicates that a copy of the entry before application of update is to be returned." +1.3.6.1.1.14 "Modify-Increment Extension" "RFC 4525" "An extension to the Lightweight Directory Access Protocol (LDAP) Modify operation to support an increment capability." +1.3.6.1.4.1.42.2.27.8.5.1 "passwordPolicyRequest" +1.3.6.1.4.1.42.2.27.9.5.2 "GetEffectiveRights control" "" "May be used to determine what operations a given user may perform on a specified entry." +1.3.6.1.4.1.1466.101.119.1 "Dynamic Directory Services Refresh Request" "RFC 2589" +1.3.6.1.4.1.1466.20036 "LDAP_NOTICE_OF_DISCONNECTION" +1.3.6.1.4.1.1466.20037 "Transport Layer Security Extension" "RFC 2830" "This operation provides for TLS establishment in an LDAP association and is defined in terms of an LDAP extended request." +1.3.6.1.4.1.1466.29539.1 "LDAP_CONTROL_ATTR_SIZELIMIT" +1.3.6.1.4.1.1466.29539.2 "LDAP_CONTROL_NO_COPY" +1.3.6.1.4.1.1466.29539.3 "LDAP_CONTROL_PARTIAL_COPY" +1.3.6.1.4.1.1466.29539.5 "LDAP_CONTROL_NO_CHAINING" +1.3.6.1.4.1.1466.29539.7 "LDAP_CONTROL_ALIAS_ON_UPDATE" +1.3.6.1.4.1.1466.29539.10 "LDAP_CONTROL_TRIGGER" +1.3.6.1.4.1.1466.29539.12 "nsTransmittedControl" +1.3.6.1.4.1.4203.1.5.1 "All Operational Attribute" "RFC 3673" "An LDAP extension which clients may use to request the return of all operational attributes." +1.3.6.1.4.1.4203.1.5.2 "Requesting Attributes by Object Class" "draft-zeilenga-ldap-adlist-10.txt" "Extends LDAP to support a mechanism that LDAP clients may use to request the return of all attributes of an object class." +1.3.6.1.4.1.4203.1.5.3 "LDAP Absolute True and False Filters" "draft-zeilenga-ldap-t-f-10.txt" "Implementations of this extension SHALL allow 'and' and 'or' choices with zero filter elements." +1.3.6.1.4.1.4203.1.5.4 "Language Tags" "RFC 3866" "Supports storing attributes with language tag options in the DIT" +1.3.6.1.4.1.4203.1.5.5 "Language Ranges" "RFC 3866" "Supports language range matching of attributes with language tag options stored in the DIT" +1.3.6.1.4.1.4203.1.9.1.1 "LDAP Content Synchronization Control" "draft=zeilenga-ldup-sync-06.txt" "The operation allows a client to maintain a copy of a fragment of directory information tree. It supports both polling for changes and listening for changes. The operation is defined as an extension of the LDAP Search Operation." +1.3.6.1.4.1.4203.1.10.1 "Subentries in LDAP" "RFC 3672" "The subentries control MAY be sent with a searchRequest to control the visibility of entries and subentries which are within scope. Non-visible entries or subentries are not returned in response to the request." +1.3.6.1.4.1.4203.1.10.2 "LDAP No-Op Control" "draft-zeilenga-ldap-noop-02.txt" "The No-Op control can be used to disable the normal effect of an operation. The control can be used to discover how a server might react to a particular update request without updating the directory." +1.3.6.1.4.1.4203.1.11.1 "LDAP Password Modify Extended Operation" "RFC 3062" "An LDAP extended operation to allow modification of user passwords which is not dependent upon the form of the authentication identity nor the password storage mechanism used." +1.3.6.1.4.1.4203.1.11.2 "LDAP Cancel Extended Operation" +1.3.6.1.4.1.4203.1.11.3 "Who Am I? Extended Operation" "draft-zeilenga-ldap-authzid-10.txt" "This specification provides a mechanism for Lightweight Directory Access Protocol (LDAP) clients to obtain the authorization identity which the server has associated with the user or application entity." +1.3.6.1.4.1.4203.666.5.1 "Subentries Control" +1.3.6.1.4.1.4203.666.5.2 "NO OP Control" +1.3.18.0.2.12.1 "The ACL credential controls provide a method to flow a subject's credentials associated with a bind." +1.3.18.0.2.12.5 "tranExtOpInit" +1.3.18.0.2.12.6 "tranExtOpInit" +2.16.840.1.113531.18.2.1 "LDAP_C_SETOPTIONS_OID" +2.16.840.1.113531.18.2.2 "LDAP_C_SETDONTUSECOPY_OID" +2.16.840.1.113531.18.2.3 "LDAP_C_SETLOCALSCOPE_OID" +2.16.840.1.113531.18.2.4 "Return operational attributes as well as user attributes" +2.16.840.1.113531.18.2.5 "Return only subentries" +2.16.840.1.113531.18.2.6 "LDAP_C_SETUSEALIAS_OID" +2.16.840.1.113531.18.2.7 "LDAP_C_SETPREFERCHAIN_OID" +2.16.840.1.113531.18.2.8 "LDAP_C_SETX500DN_OID" +2.16.840.1.113531.18.2.9 "LDAP_C_SETCOPYSHALLDO_OID" +2.16.840.1.113531.18.2.10 "LDAP_C_SETDONTMAPATTRS_OID" +2.16.840.1.113531.18.2.11 "Return normal entries as well as sub-entries" +2.16.840.1.113719.1.27.99.1 "Superior References" +2.16.840.1.113719.1.27.100.1 "ndsToLdapResponse" +2.16.840.1.113719.1.27.100.2 "ndsToLdapRequest" +2.16.840.1.113719.1.27.100.3 "createNamingContextRequest" +2.16.840.1.113719.1.27.100.4 "createNamingContextResponse" +2.16.840.1.113719.1.27.100.5 "mergeNamingContextRequest" +2.16.840.1.113719.1.27.100.6 "mergeNamingContextResponse" +2.16.840.1.113719.1.27.100.7 "addReplicaRequest" +2.16.840.1.113719.1.27.100.8 "addReplicaResponse" +2.16.840.1.113719.1.27.100.9 "refreshLDAPServerRequest" +2.16.840.1.113719.1.27.100.10 "refreshLDAPServerResponse" +2.16.840.1.113719.1.27.100.11 "removeReplicaRequest" +2.16.840.1.113719.1.27.100.12 "removeReplicaResponse" +2.16.840.1.113719.1.27.100.13 "namingContextEntryCountRequest" +2.16.840.1.113719.1.27.100.14 "namingContextEntryCountResponse" +2.16.840.1.113719.1.27.100.15 "changeReplicaTypeRequest" +2.16.840.1.113719.1.27.100.16 "changeReplicaTypeResponse" +2.16.840.1.113719.1.27.100.17 "getReplicaInfoRequest" +2.16.840.1.113719.1.27.100.18 "getReplicaInfoResponse" +2.16.840.1.113719.1.27.100.19 "listReplicaRequest" +2.16.840.1.113719.1.27.100.20 "listReplicaResponse" +2.16.840.1.113719.1.27.100.21 "receiveAllUpdatesRequest" +2.16.840.1.113719.1.27.100.22 "receiveAllUpdatesResponse" +2.16.840.1.113719.1.27.100.23 "sendAllUpdatesRequest" +2.16.840.1.113719.1.27.100.24 "sendAllUpdatesResponse" +2.16.840.1.113719.1.27.100.25 "requestNamingContextSyncRequest" +2.16.840.1.113719.1.27.100.26 "requestNamingContextSyncResponse" +2.16.840.1.113719.1.27.100.27 "requestSchemaSyncRequest" +2.16.840.1.113719.1.27.100.28 "requestSchemaSyncResponse" +2.16.840.1.113719.1.27.100.29 "abortNamingContextOperationRequest" +2.16.840.1.113719.1.27.100.30 "abortNamingContextOperationResponse" +2.16.840.1.113719.1.27.100.31 "Get Bind DN Request" +2.16.840.1.113719.1.27.100.32 "Get Bind DN Response" +2.16.840.1.113719.1.27.100.33 "Get Effective Privileges Request" +2.16.840.1.113719.1.27.100.34 "Get Effective Privileges Response" +2.16.840.1.113719.1.27.100.35 "Set Replication Filter Request" +2.16.840.1.113719.1.27.100.36 "Set Replication Filter Response" +2.16.840.1.113719.1.27.100.37 "Get Replication Filter Request" +2.16.840.1.113719.1.27.100.38 "Get Replication Filter Response" +2.16.840.1.113719.1.27.100.39 "Create Orphan Partition Request" +2.16.840.1.113719.1.27.100.40 "Create Orphan Partition Response" +2.16.840.1.113719.1.27.100.41 "Remove Orphan Partition Request" +2.16.840.1.113719.1.27.100.42 "Remove Orphan Partition Response" +2.16.840.1.113719.1.27.100.43 "Trigger Backlinker Request" +2.16.840.1.113719.1.27.100.44 "Trigger Backlinker Response" +2.16.840.1.113719.1.27.100.47 "Trigger Janitor Request" +2.16.840.1.113719.1.27.100.48 "Trigger Janitor Response" +2.16.840.1.113719.1.27.100.49 "Trigger Limber Request" +2.16.840.1.113719.1.27.100.50 "Trigger Limber Response" +2.16.840.1.113719.1.27.100.51 "Trigger Skulker Request" +2.16.840.1.113719.1.27.100.52 "Trigger Skulker Response" +2.16.840.1.113719.1.27.100.53 "Trigger Schema Synch Request" +2.16.840.1.113719.1.27.100.54 "Trigger Schema Synch Response" +2.16.840.1.113719.1.27.100.55 "Trigger Partition Purge Request" +2.16.840.1.113719.1.27.100.56 "Trigger Partition Purge Response" +2.16.840.1.113719.1.27.100.79 "Monitor Events Request" +2.16.840.1.113719.1.27.100.80 "Monitor Events Response" +2.16.840.1.113719.1.27.100.81 "Event Notification" +2.16.840.1.113719.1.27.101.1 "Duplicate Entry Request" +2.16.840.1.113719.1.27.101.2 "DuplicateSearchResult" +2.16.840.1.113719.1.27.101.3 "DuplicateEntryResponseDone" +2.16.840.1.113719.1.27.101.5 "Simple Password" +2.16.840.1.113719.1.27.101.6 "Forward Reference" +2.16.840.1.113719.1.142.100.1 "startFramedProtocolRequest" +2.16.840.1.113719.1.142.100.2 "startFramedProtocolResponse" +2.16.840.1.113719.1.142.100.3 "ReplicationUpdate" +2.16.840.1.113719.1.142.100.4 "endFramedProtocolRequest" +2.16.840.1.113719.1.142.100.5 "endFramedProtocolResponse" +2.16.840.1.113719.1.142.100.6 "lburpOperationRequest" +2.16.840.1.113719.1.142.100.7 "lburpOperationResponse" +2.16.840.1.113730.3.4 "Netscape LDAPv3 controls" +2.16.840.1.113730.3.4.2 "ManageDsaIT Control" "RFC 3296" "The client may provide the ManageDsaIT control with an operation to indicate that the operation is intended to manage objects within the DSA (server) Information Tree. The control causes Directory-specific entries (DSEs), regardless of type, to be treated as normal entries allowing clients to interrogate and update these entries using LDAP operations." +2.16.840.1.113730.3.4.3 "Persistent Search LDAPv3 control" +2.16.840.1.113730.3.4.4 "Netscape Password Expired LDAPv3 control" +2.16.840.1.113730.3.4.5 "Netscape Password Expiring LDAPv3 control" +2.16.840.1.113730.3.4.6 "Netscape NT Synchronization Client LDAPv3 control" +2.16.840.1.113730.3.4.7 "Entry Change Notification LDAPv3 control" +2.16.840.1.113730.3.4.8 "Transaction ID Request Control" +2.16.840.1.113730.3.4.9 "VLV Request LDAPv3 control" "" "As defined in the 'LDAPv3 Extensions for Virtual List View' IETF document." +2.16.840.1.113730.3.4.10 "VLV Response LDAPv3 control" "" "As defined in the 'LDAPv3 Extensions for Virtual List View' IETF document." +2.16.840.1.113730.3.4.11 "Transaction ID Response Control" +2.16.840.1.113730.3.4.12 "Proxied Authorization (version 1) control" "draft-weltman-ldapv3-proxy-05" "For assuming the identity of another entry for the duration of a request. This has been replaced by a new 'version 2' Proxied Authorization control." +2.16.840.1.113730.3.4.13 "iPlanet Directory Server Replication Update Information Control" +2.16.840.1.113730.3.4.14 "iPlanet Directory Server 'search on specific backend' control" +2.16.840.1.113730.3.4.15 "Authentication Response Control" +2.16.840.1.113730.3.4.16 "Authentication Request Control" +2.16.840.1.113730.3.4.17 "Real Attributes Only Request Control" +2.16.840.1.113730.3.4.18 "LDAP Proxied Authorization Control" "draft-weltman-ldapv3-proxy-06.txt" "The Proxied Authorization Control allows a client to request that an operation be processed under a provided authorization identity [AUTH] instead of as the current authorization identity associated with the connection." +2.16.840.1.113730.3.4.19 "Virtual Attributes Only Request Control" +2.16.840.1.113730.3.4.20 "Use One Backend" +2.16.840.1.113730.3.4.999 "iPlanet Replication Modrdn Extra Mods Control" +2.16.840.1.113730.3.5.3 "iPlanet Start Replication Request Extended Operation" +2.16.840.1.113730.3.5.4 "iPlanet Replication Response Extended Operation" +2.16.840.1.113730.3.5.5 "iPlanet End Replication Request Extended Operation" +2.16.840.1.113730.3.5.6 "iPlanet Replication Entry Request Extended Operation" +2.16.840.1.113730.3.5.7 "iPlanet Bulk Import Start Extended Operation" +2.16.840.1.113730.3.5.8 "iPlanet Bulk Import Finished Extended Operation" +2.16.840.1.113730.3.5.9 "iPlanet Digest authentication calculation" diff --git a/lib/page.php b/lib/page.php new file mode 100644 index 0000000..59927ce --- /dev/null +++ b/lib/page.php @@ -0,0 +1,519 @@ + + protected $_head; + + # Settings for this application + protected $_app; + + # Default values array. + protected $_default; + + public function __construct($index=null) { + if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # If we done have a configuration, then our IMGDIR and CSS are not defined + if (! defined('IMGDIR')) + define('IMGDIR','images/default'); + if (! defined('CSSDIR')) + define('CSSDIR','css/default'); + + $this->index = $index; + + # To be defined in a configuration file. + $this->_app['title'] = app_name(); + $this->_app['logo'] = IMGDIR.'/logo-small.png'; + + if (! is_null($index)) + $this->_app['urlcss'] = sprintf('%s/%s',CSSDIR,$_SESSION[APPCONFIG]->getValue('appearance','stylesheet')); + else + $this->_app['urlcss'] = sprintf('%s/%s',CSSDIR,'style.css'); + + # Default Values for configurable items. + $this->_default['sysmsg']['error'] = IMGDIR.'/error-big.png'; + $this->_default['sysmsg']['warn'] = IMGDIR.'/warn-big.png'; + $this->_default['sysmsg']['info'] = IMGDIR.'/info-big.png'; + + # Capture any output so far (in case we send some headers below) - there shouldnt be any output anyway. + $preOutput = ''; + + # Try and work around if php compression is on, or the user has set compression in the config. + # type = 1 for user gzip, 0 for php.ini gzip. + $obStatus = ob_get_status(); + if (isset($obStatus['type']) && $obStatus['type'] && $obStatus['status']) { + $preOutput = ob_get_contents(); + ob_end_clean(); + } + + header('Content-type: text/html; charset="UTF-8"'); + if (isCompress()) { + header('Content-Encoding: gzip'); + + if (defined('DEBUG_ENABLED') && DEBUG_ENABLED) + debug_log('Sent COMPRESSED header to browser and discarded (%s)',129,0,__FILE__,__LINE__,__METHOD__,$preOutput); + } + + if (isset($_SESSION[APPCONFIG]) + && $_SESSION[APPCONFIG]->getValue('appearance','compress') + && ini_get('zlib.output_compression')) + $this->setsysmsg(array('title'=>_('Warning'),'body'=>_('WARNING: You cannot have PHP compression and application compression enabled at the same time. Please unset zlib.output_compression or set $config->custom->appearance[\'compress\']=false'),'type'=>'warn')); + + # Turn back on output buffering. + ob_start(); + + # Initial Values + $this->_pageheader[] = ''; + $this->_pageheader[] .= ''."\n"; + } + + /* Add to the HTML Header */ + public function head_add($html) { + if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->_head[] .= $html; + } + + /* Print out the HTML header */ + private function pageheader_print() { + if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # HTML prepage requirements. + foreach ($this->_pageheader as $line) + echo $line."\n"; + + # Page Title + echo ''; + printf(''); + + $DNs = get_request('dn','REQUEST'); + if (is_array($DNs)) + $DNs = ''; + + if (isset($_SESSION[APPCONFIG])) + printf('%s (%s) - %s%s', + $this->_app['title'], + app_version(), + $DNs ? htmlspecialchars($DNs).' ' : '', + $_SESSION[APPCONFIG]->getValue('appearance','page_title')); + else + printf('%s - %s',$this->_app['title'],app_version()); + + echo ''; + # Style sheet. + printf('',$this->_app['urlcss']); + + if (defined('JSDIR')) { + printf('',JSDIR); + echo "\n"; + printf('',JSDIR); + printf('',JSDIR); + echo "\n"; + } + + # HTML head requirements. + if (is_array($this->_head) && count($this->_head)) + foreach ($this->_head as $line) + echo $line."\n"; + + echo ''; + echo "\n"; + } + + private function head_print() { + if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (isset($_SESSION[APPCONFIG])) + $pagetitle = $_SESSION[APPCONFIG]->getValue('appearance','page_title') ? ' - '.$_SESSION[APPCONFIG]->getValue('appearance','page_title') : ''; + else + $pagetitle = ''; + + echo ''; + + echo '
'; + printf('',get_href('sf'),$this->_app['logo']); + + echo ''; + echo '
'; + $empty = true; + if (function_exists('cmd_control_pane')) + foreach (cmd_control_pane('top') as $cmddetails) + if ((isset($cmddetails['enable']) && $cmddetails['enable']) || ! isset($cmddetails['enable'])) { + if (! $empty) + echo ' '; + + printf('%s',$cmddetails['link'],$cmddetails['image']); + + $empty = false; + } + + if ($empty) + echo ' '; + + echo '
'; + echo ''; + echo "\n"; + } + + private function control_print() { + if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + echo ''; + echo ''; + if ($empty) + echo ''; + + echo ''; + echo '
'; + + $empty = true; + if (function_exists('cmd_control_pane')) + foreach (cmd_control_pane('main') as $cmddetails) + if ((isset($cmddetails['enable']) && trim($cmddetails['enable'])) || ! isset($cmddetails['enable'])) { + if (! $empty) + echo ' | '; + + printf('%s',$cmddetails['link'], + (isset($_SESSION[APPCONFIG]) && $_SESSION[APPCONFIG]->getValue('appearance','control_icons')) ? $cmddetails['image'] : $cmddetails['title']); + + $empty = false; + } + + echo ' 
'; + } + + protected function tree() { + if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (! isset($_SESSION[APPCONFIG])) + return; + + if (is_null($this->index)) + $this->index = min(array_keys($_SESSION[APPCONFIG]->getServerList())); + + if (count($_SESSION[APPCONFIG]->getServerList()) > 1) { + echo '
'; + echo '
'; + printf('%s:
%s',_('Server Select'), + server_select_list($this->index,false,'index',true,sprintf("onchange=\"tree_unhide('index',%s)\"",$this->index))); + echo '
'; + echo '
'; + echo "\n\n"; + } + + foreach ($_SESSION[APPCONFIG]->getServerList() as $index => $server) { + printf('
',$server->getIndex(),($server->getIndex() == $this->index) ? 'block' : 'none'); + $tree = Tree::getInstance($server->getIndex()); + $tree->draw(); + echo '
'; + echo "\n\n"; + } + } + + public function block_add($side,$object) { + if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (! is_object($object)) + error(sprintf('block_add called with [%s], but it is not an object',serialize($object))); + + $this->_block[$side][] = $object; + } + + private function block_print($side) { + if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (! isset($this->_block[$side])) + return; + + printf('',$side); + foreach ($this->_block[$side] as $object) + echo $object->draw($side); + echo ''; + } + + private function sysmsg() { + if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (isset($this->sysmsg)) { + foreach ($this->sysmsg as $index => $details) { + switch ($details['type']) { + case 'error': + $icon = $this->_default['sysmsg']['error']; + break; + + case 'warn': + $icon = $this->_default['sysmsg']['warn']; + break; + + case 'info': + default: + $icon = $this->_default['sysmsg']['info']; + break; + } + + if (isset($details['title'])) + printf('%s%s', + $icon,$details['type'],$details['title']); + + if (isset($details['body'])) + if (is_array($details['body'])) { + echo ''; + foreach ($details['body'] as $line) + printf('%s
',$line); + echo ''; + + } else + printf('%s',$details['body']); + } + } + } + + private function body($raw=false) { + if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # Add the Session System Messages + if (isset($_SESSION['sysmsg']) && is_array($_SESSION['sysmsg'])) { + foreach ($_SESSION['sysmsg'] as $msg) + $this->setsysmsg($msg); + + unset($_SESSION['sysmsg']); + } + + if (isset($this->sysmsg)) { + echo ''; + $this->sysmsg(); + echo '
'; + echo "\n"; + } + + if (isset($this->_block['body'])) + foreach ($this->_block['body'] as $object) + echo $object->draw('body',$raw); + } + + private function footer_print() { + if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + printf('%s
%s
%s', + isCompress() ? '[C]' : ' ', + app_version(), + get_href('logo') ? sprintf('SourceForge.net Logo',get_href('sf'),get_href('logo')) : ' '); + } + + /** + * Only show a particular page frame - used by an AJAX call + */ + public function show($frame,$compress=false,$raw=false) { + if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # If the body is called via AJAX, and compression is enable, we need to compress the output + if ($compress && ob_get_level() && isCompress()) { + ob_end_clean(); + ob_start(); + } + + switch ($frame) { + case 'BODY': + $this->body($raw); + break; + + case 'TREE': + $this->tree(); + break; + + default: + error(sprintf('show called with unknown frame [%s]',$frame),'error','index.php'); + } + + if ($compress && ob_get_level() && isCompress()) { + $output = ob_get_contents(); + ob_end_clean(); + + if (defined('DEBUG_ENABLED') && DEBUG_ENABLED) + debug_log('Sending COMPRESSED output to browser[(%s),%s]',129,0,__FILE__,__LINE__,__METHOD__, + strlen($output),$output); + + print gzencode($output); + } + } + + public function display($filter=array()) { + if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # Control what is displayed. + $display = array( + 'HEAD'=>true, + 'CONTROL'=>true, + 'TREE'=>true, + 'FOOT'=>true + ); + + if ($_SESSION[APPCONFIG]->getValue('appearance','minimalMode')) { + $display = array( + 'HEAD'=>false, + 'CONTROL'=>false, + 'TREE'=>true, + 'FOOT'=>false + ); + } + + $display = array_merge($display,$filter); + + # HTML Header + $this->pageheader_print(); + + # Start of body + # Page Header + echo ''; + echo "\n"; + echo ''; + + if ($display['HEAD']) + $this->head_print(); + + # Control Line + if ($display['CONTROL']) { + echo ''; + echo "\n"; + } + + # Left Block + echo ''; + + if ($display['TREE']) { + echo ''; + } + + echo ''; + echo ''; + echo "\n"; + + # Page Footer + if ($display['FOOT']) + $this->footer_print(); + + # Finish HTML + echo '
'; + echo '
'; + $this->control_print(); + echo '
'; + printf('',_('Hide/Unhide the tree'),IMGDIR); + echo '
'; + $this->tree(); + echo '
'; + echo '
'; + echo '
'; + echo "\n"; + $this->body(); + echo '
'; + echo '
'; + echo ''; + echo ''; + + # compress output + if (ob_get_level() && isCompress()) { + $output = ob_get_contents(); + ob_end_clean(); + + if (defined('DEBUG_ENABLED') && DEBUG_ENABLED) + debug_log('Sending COMPRESSED output to browser[(%s),%s]',129,0,__FILE__,__LINE__,__METHOD__, + strlen($output),$output); + + print gzencode($output); + } + } + + public function setsysmsg($data) { + if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (! is_array($data)) + return; + + if (isset($this->sysmsg)) + $msgnum = count($this->sysmsg) + 1; + else + $msgnum = 1; + + foreach (array('title','body','type') as $index) + if (isset($data[$index])) + $this->sysmsg[$msgnum][$index] = $data[$index]; + } +} + +/** + * This class draws a block. + * + * @package phpLDAPadmin + * @subpackage Page + */ +class block { + private $title; + private $body; + private $foot; + + public function setTitle($html) { + $this->title = $html; + } + + public function setBody($html) { + $this->body = $html; + } + + public function setFooter($html) { + $this->foot = $html; + } + + public function draw($side,$raw=false) { + $output = ''; + + if ($raw) + $output .= $this->body; + + else { + $output .= sprintf('',$side); + + if (isset($this->title)) + $output .= sprintf('',$this->title); + + if (isset($this->body)) + $output .= sprintf('',$this->body); + + if (isset($this->footer)) + $output .= sprintf('',$this->foot); + + $output .= '
%s
%s
%s
'; + } + + return $output; + } +} +?> diff --git a/lib/query_functions.php b/lib/query_functions.php new file mode 100644 index 0000000..de47630 --- /dev/null +++ b/lib/query_functions.php @@ -0,0 +1,22 @@ + diff --git a/lib/schema_functions.php b/lib/schema_functions.php new file mode 100644 index 0000000..efa0cbc --- /dev/null +++ b/lib/schema_functions.php @@ -0,0 +1,1539 @@ +oid = $oid; + } + + public function setDescription($desc) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->description = $desc; + } + + public function getOID() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->oid); + + return $this->oid; + } + + public function getDescription() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->description); + + return $this->description; + } + + /** + * Gets whether this objectClass is flagged as obsolete by the LDAP server. + */ + public function getIsObsolete() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->is_obsolete); + + return $this->is_obsolete; + } + + /** + * Return the objects name. + * + * param boolean $lower Return the name in lower case (default) + * @return string The name + */ + public function getName($lower=true) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->name); + + return $lower ? strtolower($this->name) : $this->name; + } +} + +/** + * Represents an LDAP objectClass + * + * @package phpLDAPadmin + * @subpackage Schema + */ +class ObjectClass extends SchemaItem { + # The server ID that this objectclass belongs to. + private $server_id = null; + # Array of objectClass names from which this objectClass inherits + private $sup_classes = array(); + # One of STRUCTURAL, ABSTRACT, or AUXILIARY + private $type; + # Arrays of attribute names that this objectClass requires + private $must_attrs = array(); + # Arrays of attribute names that this objectClass allows, but does not require + private $may_attrs = array(); + # Arrays of attribute names that this objectClass has been forced to MAY attrs, due to configuration + private $force_may = array(); + # Array of objectClasses which inherit from this one (must be set at runtime explicitly by the caller) + private $children_objectclasses = array(); + # The objectclass hierarchy + private $hierarchy = array(); + + /** + * Creates a new ObjectClass object given a raw LDAP objectClass string. + */ + public function __construct($class,$server) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->server_id = $server->getIndex(); + $this->type = $server->getValue('server','schema_oclass_default'); + + $strings = preg_split('/[\s,]+/',$class,-1,PREG_SPLIT_DELIM_CAPTURE); + $str_count = count($strings); + + for ($i=0; $i < $str_count; $i++) { + + switch ($strings[$i]) { + case '(': + break; + + case 'NAME': + if ($strings[$i+1]!='(') { + do { + $i++; + if (strlen($this->name) == 0) + $this->name = $strings[$i]; + else + $this->name .= ' '.$strings[$i]; + + } while (! preg_match('/\'$/s',$strings[$i])); + + } else { + $i++; + do { + $i++; + if (strlen($this->name) == 0) + $this->name = $strings[$i]; + else + $this->name .= ' '.$strings[$i]; + + } while (! preg_match('/\'$/s',$strings[$i])); + + do { + $i++; + } while (! preg_match('/\)+\)?/',$strings[$i])); + } + + $this->name = preg_replace('/^\'/','',$this->name); + $this->name = preg_replace('/\'$/','',$this->name); + + if (DEBUG_ENABLED) + debug_log('Case NAME returned (%s)',8,0,__FILE__,__LINE__,__METHOD__,$this->name); + break; + + case 'DESC': + do { + $i++; + if (strlen($this->description) == 0) + $this->description=$this->description.$strings[$i]; + else + $this->description=$this->description.' '.$strings[$i]; + + } while (! preg_match('/\'$/s',$strings[$i])); + + if (DEBUG_ENABLED) + debug_log('Case DESC returned (%s)',8,0,__FILE__,__LINE__,__METHOD__,$this->description); + break; + + case 'OBSOLETE': + $this->is_obsolete = TRUE; + + if (DEBUG_ENABLED) + debug_log('Case OBSOLETE returned (%s)',8,0,__FILE__,__LINE__,__METHOD__,$this->is_obsolete); + break; + + case 'SUP': + if ($strings[$i+1] != '(') { + $i++; + array_push($this->sup_classes,preg_replace("/'/",'',$strings[$i])); + + } else { + $i++; + do { + $i++; + if ($strings[$i] != '$') + array_push($this->sup_classes,preg_replace("/'/",'',$strings[$i])); + + } while (! preg_match('/\)+\)?/',$strings[$i+1])); + } + + if (DEBUG_ENABLED) + debug_log('Case SUP returned (%s)',8,0,__FILE__,__LINE__,__METHOD__,$this->sup_classes); + break; + + case 'ABSTRACT': + $this->type = 'abstract'; + + if (DEBUG_ENABLED) + debug_log('Case ABSTRACT returned (%s)',8,0,__FILE__,__LINE__,__METHOD__,$this->type); + break; + + case 'STRUCTURAL': + $this->type = 'structural'; + + if (DEBUG_ENABLED) + debug_log('Case STRUCTURAL returned (%s)',8,0,__FILE__,__LINE__,__METHOD__,$this->type); + break; + + case 'AUXILIARY': + $this->type = 'auxiliary'; + + if (DEBUG_ENABLED) + debug_log('Case AUXILIARY returned (%s)',8,0,__FILE__,__LINE__,__METHOD__,$this->type); + break; + + case 'MUST': + $attrs = array(); + + $i = $this->parseList(++$i,$strings,$attrs); + + if (DEBUG_ENABLED) + debug_log('parseList returned %d (%s)',8,0,__FILE__,__LINE__,__METHOD__,$i,$attrs); + + foreach ($attrs as $string) { + $attr = new ObjectClass_ObjectClassAttribute($string,$this->name); + + if ($server->isForceMay($attr->getName())) { + array_push($this->force_may,$attr); + array_push($this->may_attrs,$attr); + + } else + array_push($this->must_attrs,$attr); + } + + if (DEBUG_ENABLED) + debug_log('Case MUST returned (%s) (%s)',8,0,__FILE__,__LINE__,__METHOD__,$this->must_attrs,$this->force_may); + break; + + case 'MAY': + $attrs = array(); + + $i = $this->parseList(++$i,$strings,$attrs); + + if (DEBUG_ENABLED) + debug_log('parseList returned %d (%s)',8,0,__FILE__,__LINE__,__METHOD__,$i,$attrs); + + foreach ($attrs as $string) { + $attr = new ObjectClass_ObjectClassAttribute($string,$this->name); + array_push($this->may_attrs,$attr); + } + + if (DEBUG_ENABLED) + debug_log('Case MAY returned (%s)',8,0,__FILE__,__LINE__,__METHOD__,$this->may_attrs); + break; + + default: + if (preg_match('/[\d\.]+/i',$strings[$i]) && $i == 1) { + $this->setOID($strings[$i]); + + if (DEBUG_ENABLED) + debug_log('Case default returned (%s)',8,0,__FILE__,__LINE__,__METHOD__,$this->getOID()); + } + break; + } + } + + $this->description = preg_replace("/^\'/",'',$this->description); + $this->description = preg_replace("/\'$/",'',$this->description); + + if (DEBUG_ENABLED) + debug_log('Returning () - NAME (%s), DESCRIPTION (%s), MUST (%s), MAY (%s), FORCE MAY (%s)',9,0,__FILE__,__LINE__,__METHOD__, + $this->name,$this->description,$this->must_attrs,$this->may_attrs,$this->force_may); + } + + /** + * Parse an LDAP schema list + */ + private function parseList($i,$strings,&$attrs) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,0,__FILE__,__LINE__,__METHOD__,$fargs); + + /* + * A list starts with a ( followed by a list of attributes separated by $ terminated by ) + * The first token can therefore be a ( or a (NAME or a (NAME) + * The last token can therefore be a ) or NAME) + * The last token may be terminate by more than one bracket + */ + + $string = $strings[$i]; + if (! preg_match('/^\(/',$string)) { + # A bareword only - can be terminated by a ) if the last item + if (preg_match('/\)+$/',$string)) + $string = preg_replace('/\)+$/','',$string); + + array_push($attrs,$string); + + } elseif (preg_match('/^\(.*\)$/',$string)) { + $string = preg_replace('/^\(/','',$string); + $string = preg_replace('/\)+$/','',$string); + array_push($attrs,$string); + + } else { + # Handle the opening cases first + if ($string == '(') { + $i++; + + } elseif (preg_match('/^\(./',$string)) { + $string = preg_replace('/^\(/','',$string); + array_push($attrs,$string); + $i++; + } + + # Token is either a name, a $ or a ')' + # NAME can be terminated by one or more ')' + while (! preg_match('/\)+$/',$strings[$i])) { + $string = $strings[$i]; + if ($string == '$') { + $i++; + continue; + } + + if (preg_match('/\)$/',$string)) + $string = preg_replace('/\)+$/','',$string); + else + $i++; + + array_push($attrs,$string); + } + } + + sort($attrs); + + if (DEBUG_ENABLED) + debug_log('Returning (%d,[%s],[%s])',9,0,__FILE__,__LINE__,__METHOD__,$i,$strings,$attrs); + + return $i; + } + + /** + * This will return all our parent ObjectClass Objects + */ + public function getParents() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if ((count($this->sup_classes) == 1) && ($this->sup_classes[0] == 'top')) + return array(); + + $server = $_SESSION[APPCONFIG]->getServer($this->server_id); + $return = array(); + + foreach ($this->sup_classes as $object_class) { + array_push($return,$object_class); + + $oc = $server->getSchemaObjectClass($object_class); + + if ($oc) + $return = array_merge($return,$oc->getParents()); + } + + return $return; + } + + /** + * Gets an array of AttributeType objects that entries of this ObjectClass must define. + * This differs from getMustAttrNames in that it returns an array of AttributeType objects + * + * @param array $parents An array of ObjectClass objects to use when traversing + * the inheritance tree. This presents some what of a bootstrapping problem + * as we must fetch all objectClasses to determine through inheritance which + * attributes this objectClass requires. + * @return array The array of required AttributeType objects. + * + * @see getMustAttrNames + * @see getMayAttrs + * @see getMayAttrNames + */ + public function getMustAttrs($parents=false) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (! $parents) + return $this->must_attrs; + + $server = $_SESSION[APPCONFIG]->getServer($this->server_id); + $attrs = $this->must_attrs; + + foreach ($this->getParents() as $sup_class) { + $sc = $server->getSchemaObjectClass($sup_class); + $attrs = array_merge($attrs,$sc->getMustAttrs()); + } + + masort($attrs,'name,source'); + + # Remove any duplicates + foreach ($attrs as $index => $attr) + if (isset($allattr[$attr->getName()])) + unset($attrs[$index]); + else + $allattr[$attr->getName()] = 1; + + return $attrs; + } + + /** + * Gets an array of AttributeType objects that entries of this ObjectClass may define. + * This differs from getMayAttrNames in that it returns an array of AttributeType objects + * + * @param array $parents An array of ObjectClass objects to use when traversing + * the inheritance tree. This presents some what of a bootstrapping problem + * as we must fetch all objectClasses to determine through inheritance which + * attributes this objectClass provides. + * @return array The array of allowed AttributeType objects. + * + * @see getMustAttrNames + * @see getMustAttrs + * @see getMayAttrNames + * @see AttributeType + */ + public function getMayAttrs($parents=false) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (! $parents) + return $this->may_attrs; + + $server = $_SESSION[APPCONFIG]->getServer($this->server_id); + $attrs = $this->may_attrs; + + foreach ($this->getParents() as $sup_class) { + $sc = $server->getSchemaObjectClass($sup_class); + $attrs = array_merge($attrs,$sc->getMayAttrs()); + } + + masort($attrs,'name,source'); + + # Remove any duplicates + foreach ($attrs as $index => $attr) + if (isset($allattr[$attr->name])) + unset($attrs[$index]); + else + $allattr[$attr->name] = 1; + + return $attrs; + } + + public function getForceMayAttrs() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,0,__FILE__,__LINE__,__METHOD__,$fargs); + + return $this->force_may; + } + + /** + * Gets an array of attribute names (strings) that entries of this ObjectClass must define. + * This differs from getMustAttrs in that it returns an array of strings rather than + * array of AttributeType objects + * + * @param array $parents An array of ObjectClass objects to use when traversing + * the inheritance tree. This presents some what of a bootstrapping problem + * as we must fetch all objectClasses to determine through inheritance which + * attributes this objectClass provides. + * @return array The array of allowed attribute names (strings). + * + * @see getMustAttrs + * @see getMayAttrs + * @see getMayAttrNames + */ + public function getMustAttrNames($parents=false) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $attr_names = array(); + + foreach ($this->getMustAttrs($parents) as $attr) + array_push($attr_names,$attr->getName()); + + return $attr_names; + } + + /** + * Gets an array of attribute names (strings) that entries of this ObjectClass must define. + * This differs from getMayAttrs in that it returns an array of strings rather than + * array of AttributeType objects + * + * @param array $parents An array of ObjectClass objects to use when traversing + * the inheritance tree. This presents some what of a bootstrapping problem + * as we must fetch all objectClasses to determine through inheritance which + * attributes this objectClass provides. + * @return array The array of allowed attribute names (strings). + * + * @see getMustAttrs + * @see getMayAttrs + * @see getMustAttrNames + */ + public function getMayAttrNames($parents=false) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $attr_names = array(); + + foreach ($this->getMayAttrs($parents) as $attr) + array_push($attr_names,$attr->getName()); + + return $attr_names; + } + + /** + * Adds an objectClass to the list of objectClasses that inherit + * from this objectClass. + * + * @param String $name The name of the objectClass to add + * @return boolean Returns true on success or false on failure (objectclass already existed for example) + */ + public function addChildObjectClass($name) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $name = trim($name); + + foreach ($this->children_objectclasses as $existing_objectclass) + if (strcasecmp($name,$existing_objectclass) == 0) + return false; + + array_push($this->children_objectclasses,$name); + } + + /** + * Returns the array of objectClass names which inherit from this objectClass. + * + * @return Array Names of objectClasses which inherit from this objectClass. + */ + public function getChildObjectClasses() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,0,__FILE__,__LINE__,__METHOD__,$fargs); + + return $this->children_objectclasses; + } + + /** + * Gets the objectClass names from which this objectClass inherits. + * + * @return array An array of objectClass names (strings) + */ + public function getSupClasses() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,0,__FILE__,__LINE__,__METHOD__,$fargs); + + return $this->sup_classes; + } + + /** + * Return if this objectClass is related to $oclass + * + * @param array ObjectClasses that this attribute may be related to + */ + public function isRelated($oclass) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,0,__FILE__,__LINE__,__METHOD__,$fargs); + + # If I am in the array, we'll just return false + if (in_array_ignore_case($this->name,$oclass)) + return false; + + $server = $_SESSION[APPCONFIG]->getServer($this->server_id); + + foreach ($oclass as $object_class) { + $oc = $server->getSchemaObjectClass($object_class); + + if ($oc->isStructural() && in_array_ignore_case($this->getName(),$oc->getParents())) + return true; + } + + return false; + } + + /** + * Gets the type of this objectClass: STRUCTURAL, ABSTRACT, or AUXILIARY. + */ + public function getType() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->type); + + return $this->type; + } + + /** + * Adds the specified array of attributes to this objectClass' list of + * MUST attributes. The resulting array of must attributes will contain + * unique members. + * + * @param array $attr An array of attribute names (strings) to add. + */ + private function addMustAttrs($attr) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (! is_array($attr) || ! count($attr)) + return; + + $this->must_attrs = array_values(array_unique(array_merge($this->must_attrs,$attr))); + } + + /** + * Behaves identically to addMustAttrs, but it operates on the MAY + * attributes of this objectClass. + * + * @param array $attr An array of attribute names (strings) to add. + */ + private function addMayAttrs($attr) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (! is_array($attr) || ! count($attr)) + return; + + $this->may_attrs = array_values(array_unique(array_merge($this->may_attrs,$attr))); + } + + /** + * Determine if an array is listed in the force_may attrs + */ + public function isForceMay($attr) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,0,__FILE__,__LINE__,__METHOD__,$fargs); + + foreach ($this->force_may as $forcemay) + if ($forcemay->getName() == $attr) + return true; + + return false; + } + + public function isStructural() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if ($this->type == 'structural') + return true; + else + return false; + } +} + +/** + * A simple class for representing AttributeTypes used only by the ObjectClass class. + * Users should never instantiate this class. It represents an attribute internal to + * an ObjectClass. If PHP supported inner-classes and variable permissions, this would + * be interior to class ObjectClass and flagged private. The reason this class is used + * and not the "real" class AttributeType is because this class supports the notion of + * a "source" objectClass, meaning that it keeps track of which objectClass originally + * specified it. This class is therefore used by the class ObjectClass to determine + * inheritance. + * + * @package phpLDAPadmin + * @subpackage Schema + */ +class ObjectClass_ObjectClassAttribute { + # This Attribute's name (needs to be public, as we sort on it with masort). + public $name; + # This Attribute's root (needs to be public, as we sort on it with masort). + public $source; + + /** + * Creates a new ObjectClass_ObjectClassAttribute with specified name and source objectClass. + * + * @param string $name the name of the new attribute. + * @param string $source the name of the ObjectClass which specifies this attribute. + */ + public function __construct($name,$source) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->name = $name; + $this->source = $source; + } + + # Gets this attribute's name + public function getName($lower=true) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->name); + + return $lower ? strtolower($this->name) : $this->name; + } + + # Gets the name of the ObjectClass which originally specified this attribute. + public function getSource() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->source); + + return $this->source; + } +} + +/** + * Represents an LDAP AttributeType + * + * @package phpLDAPadmin + * @subpackage Schema + */ +class AttributeType extends SchemaItem { + # The attribute from which this attribute inherits (if any) + private $sup_attribute = null; + # The equality rule used + private $equality = null; + # The ordering of the attributeType + private $ordering = null; + # Boolean: supports substring matching? + private $sub_str = null; + # The full syntax string, ie 1.2.3.4{16} + private $syntax = null; + private $syntax_oid = null; + # boolean: is single valued only? + private $is_single_value = false; + # boolean: is collective? + private $is_collective = false; + # boolean: can use modify? + private $is_no_user_modification = false; + # The usage string set by the LDAP schema + private $usage = null; + # An array of alias attribute names, strings + private $aliases = array(); + # The max number of characters this attribute can be + private $max_length = null; + # A string description of the syntax type (taken from the LDAPSyntaxes) + private $type = null; + # An array of objectClasses which use this attributeType (must be set by caller) + private $used_in_object_classes = array(); + # A list of object class names that require this attribute type. + private $required_by_object_classes = array(); + # This attribute has been forced a MAY attribute by the configuration. + private $forced_as_may = false; + + /** + * Creates a new AttributeType object from a raw LDAP AttributeType string. + */ + public function __construct($attr) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $strings = preg_split('/[\s,]+/',$attr,-1,PREG_SPLIT_DELIM_CAPTURE); + + for($i=0; $iname)==0) + $this->name = $strings[$i]; + else + $this->name .= ' '.$strings[$i]; + + } while (! preg_match("/\'$/s",$strings[$i])); + + # This attribute has no aliases + $this->aliases = array(); + + } else { + $i++; + do { + # In case we came here becaues of a (' + if (preg_match('/^\(/',$strings[$i])) + $strings[$i] = preg_replace('/^\(/','',$strings[$i]); + else + $i++; + + if (strlen($this->name) == 0) + $this->name = $strings[$i]; + else + $this->name .= ' '.$strings[$i]; + + } while (! preg_match("/\'$/s",$strings[$i])); + + # Add alias names for this attribute + while ($strings[++$i] != ')') { + $alias = $strings[$i]; + $alias = preg_replace("/^\'/",'',$alias); + $alias = preg_replace("/\'$/",'',$alias); + $this->addAlias($alias); + } + } + + if (DEBUG_ENABLED) + debug_log('Case NAME returned (%s) (%s)',8,0,__FILE__,__LINE__,__METHOD__,$this->name,$this->aliases); + break; + + case 'DESC': + do { + $i++; + if (strlen($this->description)==0) + $this->description=$this->description.$strings[$i]; + else + $this->description=$this->description.' '.$strings[$i]; + } while (! preg_match("/\'$/s",$strings[$i])); + + if (DEBUG_ENABLED) + debug_log('Case DESC returned (%s)',8,0,__FILE__,__LINE__,__METHOD__,$this->description); + break; + + case 'OBSOLETE': + $this->is_obsolete = TRUE; + + if (DEBUG_ENABLED) + debug_log('Case OBSOLETE returned (%s)',8,0,__FILE__,__LINE__,__METHOD__,$this->is_obsolete); + break; + + case 'SUP': + $i++; + $this->sup_attribute = $strings[$i]; + + if (DEBUG_ENABLED) + debug_log('Case SUP returned (%s)',8,0,__FILE__,__LINE__,__METHOD__,$this->sup_attribute); + break; + + case 'EQUALITY': + $i++; + $this->equality = $strings[$i]; + + if (DEBUG_ENABLED) + debug_log('Case EQUALITY returned (%s)',8,0,__FILE__,__LINE__,__METHOD__,$this->equality); + break; + + case 'ORDERING': + $i++; + $this->ordering = $strings[$i]; + + if (DEBUG_ENABLED) + debug_log('Case ORDERING returned (%s)',8,0,__FILE__,__LINE__,__METHOD__,$this->ordering); + break; + + case 'SUBSTR': + $i++; + $this->sub_str = $strings[$i]; + + if (DEBUG_ENABLED) + debug_log('Case SUBSTR returned (%s)',8,0,__FILE__,__LINE__,__METHOD__,$this->sub_str); + break; + + case 'SYNTAX': + $i++; + $this->syntax = $strings[$i]; + $this->syntax_oid = preg_replace('/{\d+}$/','',$this->syntax); + + # Does this SYNTAX string specify a max length (ie, 1.2.3.4{16}) + if (preg_match('/{(\d+)}$/',$this->syntax,$this->max_length)) + $this->max_length = $this->max_length[1]; + else + $this->max_length = null; + + if ($i < count($strings) - 1 && $strings[$i+1] == '{') { + do { + $i++; + $this->name .= ' '.$strings[$i]; + } while ($strings[$i] != '}'); + } + + if (DEBUG_ENABLED) + debug_log('Case SYNTAX returned (%s) (%s) (%s)',8,0,__FILE__,__LINE__,__METHOD__, + $this->syntax,$this->syntax_oid,$this->max_length); + break; + + case 'SINGLE-VALUE': + $this->is_single_value = TRUE; + if (DEBUG_ENABLED) + debug_log('Case SINGLE-VALUE returned (%s)',8,0,__FILE__,__LINE__,__METHOD__,$this->is_single_value); + break; + + case 'COLLECTIVE': + $this->is_collective = TRUE; + + if (DEBUG_ENABLED) + debug_log('Case COLLECTIVE returned (%s)',8,0,__FILE__,__LINE__,__METHOD__,$this->is_collective); + break; + + case 'NO-USER-MODIFICATION': + $this->is_no_user_modification = TRUE; + + if (DEBUG_ENABLED) + debug_log('Case NO-USER-MODIFICATION returned (%s)',8,0,__FILE__,__LINE__,__METHOD__,$this->is_no_user_modification); + break; + + case 'USAGE': + $i++; + $this->usage = $strings[$i]; + + if (DEBUG_ENABLED) + debug_log('Case USAGE returned (%s)',8,0,__FILE__,__LINE__,__METHOD__,$this->usage); + break; + + default: + if (preg_match('/[\d\.]+/i',$strings[$i]) && $i == 1) { + $this->setOID($strings[$i]); + + if (DEBUG_ENABLED) + debug_log('Case default returned (%s)',8,0,__FILE__,__LINE__,__METHOD__,$this->getOID()); + } + } + } + + $this->name = preg_replace("/^\'/",'',$this->name); + $this->name = preg_replace("/\'$/",'',$this->name); + $this->description = preg_replace("/^\'/",'',$this->description); + $this->description = preg_replace("/\'$/",'',$this->description); + $this->syntax = preg_replace("/^\'/",'',$this->syntax); + $this->syntax = preg_replace("/\'$/",'',$this->syntax); + $this->syntax_oid = preg_replace("/^\'/",'',$this->syntax_oid); + $this->syntax_oid = preg_replace("/\'$/",'',$this->syntax_oid); + $this->sup_attribute = preg_replace("/^\'/",'',$this->sup_attribute); + $this->sup_attribute = preg_replace("/\'$/",'',$this->sup_attribute); + + if (DEBUG_ENABLED) + debug_log('Returning ()',9,0,__FILE__,__LINE__,__METHOD__); + } + + /** + * Gets this attribute's usage string as defined by the LDAP server + * + * @return string + */ + public function getUsage() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->usage); + + return $this->usage; + } + + /** + * Gets this attribute's parent attribute (if any). If this attribute does not + * inherit from another attribute, null is returned. + * + * @return string + */ + public function getSupAttribute() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->sup_attribute); + + return $this->sup_attribute; + } + + /** + * Gets this attribute's equality string + * + * @return string + */ + public function getEquality() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->equality); + + return $this->equality; + } + + /** + * Gets this attribute's ordering specification. + * + * @return string + */ + public function getOrdering() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->ordering); + + return $this->ordering; + } + + /** + * Gets this attribute's substring matching specification + * + * @return string + */ + public function getSubstr() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->sub_str); + + return $this->sub_str; + } + + /** + * Gets the names of attributes that are an alias for this attribute (if any). + * + * @return array An array of names of attributes which alias this attribute or + * an empty array if no attribute aliases this object. + */ + public function getAliases() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->aliases); + + return $this->aliases; + } + + /** + * Returns whether the specified attribute is an alias for this one (based on this attribute's alias list). + * + * @param string $attr_name The name of the attribute to check. + * @return boolean True if the specified attribute is an alias for this one, or false otherwise. + */ + public function isAliasFor($attr_name) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,0,__FILE__,__LINE__,__METHOD__,$fargs); + + foreach ($this->aliases as $alias_attr_name) + if (strcasecmp($alias_attr_name,$attr_name) == 0) + return true; + + return false; + } + + /** + * Gets this attribute's raw syntax string (ie: "1.2.3.4{16}"). + * + * @return string The raw syntax string + */ + public function getSyntaxString() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->syntax); + + return $this->syntax; + } + + /** + * Gets this attribute's syntax OID. Differs from getSyntaxString() in that this + * function only returns the actual OID with any length specification removed. + * Ie, if the syntax string is "1.2.3.4{16}", this function only retruns + * "1.2.3.4". + * + * @return string The syntax OID string. + */ + public function getSyntaxOID() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->syntax_oid); + + return $this->syntax_oid; + } + + /** + * Gets this attribute's the maximum length. If no maximum is defined by the LDAP server, null is returned. + * + * @return int The maximum length (in characters) of this attribute or null if no maximum is specified. + */ + public function getMaxLength() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->max_length); + + return $this->max_length; + } + + /** + * Gets whether this attribute is single-valued. If this attribute only supports single values, true + * is returned. If this attribute supports multiple values, false is returned. + * + * @return boolean Returns true if this attribute is single-valued or false otherwise. + */ + public function getIsSingleValue() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->is_single_value); + + return $this->is_single_value; + } + + /** + * Sets whether this attribute is single-valued. + * + * @param boolean $is + */ + public function setIsSingleValue($is) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->is_single_value = $is; + } + + /** + * Gets whether this attribute is collective. + * + * @return boolean Returns true if this attribute is collective and false otherwise. + */ + public function getIsCollective() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->is_collective); + + return $this->is_collective; + } + + /** + * Gets whether this attribute is not modifiable by users. + * + * @return boolean Returns true if this attribute is not modifiable by users. + */ + public function getIsNoUserModification() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->is_no_user_modification); + + return $this->is_no_user_modification; + } + + /** + * Gets this attribute's type + * + * @return string The attribute's type. + */ + public function getType() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->type); + + return $this->type; + } + + /** + * Removes an attribute name from this attribute's alias array. + * + * @param string $remove_alias_name The name of the attribute to remove. + * @return boolean true on success or false on failure (ie, if the specified + * attribute name is not found in this attribute's list of aliases) + */ + public function removeAlias($remove_alias_name) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,0,__FILE__,__LINE__,__METHOD__,$fargs); + + foreach ($this->aliases as $i => $alias_name) { + + if (strcasecmp($alias_name,$remove_alias_name) == 0) { + unset($this->aliases[$i]); + + $this->aliases = array_values($this->aliases); + return true; + } + } + return false; + } + + /** + * Adds an attribute name to the alias array. + * + * @param string $alias The name of a new attribute to add to this attribute's list of aliases. + */ + public function addAlias($alias) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,0,__FILE__,__LINE__,__METHOD__,$fargs); + + array_push($this->aliases,$alias); + } + + /** + * Sets this attriute's name. + * + * @param string $name The new name to give this attribute. + */ + public function setName($name) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->name = $name; + } + + /** + * Sets this attriute's SUP attribute (ie, the attribute from which this attribute inherits). + * + * @param string $attr The name of the new parent (SUP) attribute + */ + public function setSupAttribute($attr) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->sup_attribute = $attr; + } + + /** + * Sets this attribute's list of aliases. + * + * @param array $aliases The array of alias names (strings) + */ + public function setAliases($aliases) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->aliases = $aliases; + } + + /** + * Sets this attribute's type. + * + * @param string $type The new type. + */ + public function setType($type) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->type = $type; + } + + /** + * Adds an objectClass name to this attribute's list of "used in" objectClasses, + * that is the list of objectClasses which provide this attribute. + * + * @param string $name The name of the objectClass to add. + */ + public function addUsedInObjectClass($name) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,0,__FILE__,__LINE__,__METHOD__,$fargs); + + foreach ($this->used_in_object_classes as $used_in_object_class) { + if (DEBUG_ENABLED) + debug_log('Checking (%s) with (%s)',8,0,__FILE__,__LINE__,__METHOD__,$used_in_object_class,$name); + + if (strcasecmp($used_in_object_class,$name) == 0) + return false; + } + + array_push($this->used_in_object_classes,$name); + } + + /** + * Gets the list of "used in" objectClasses, that is the list of objectClasses + * which provide this attribute. + * + * @return array An array of names of objectclasses (strings) which provide this attribute + */ + public function getUsedInObjectClasses() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->used_in_object_classes); + + return $this->used_in_object_classes; + } + + /** + * Adds an objectClass name to this attribute's list of "required by" objectClasses, + * that is the list of objectClasses which must have this attribute. + * + * @param string $name The name of the objectClass to add. + */ + public function addRequiredByObjectClass($name) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,0,__FILE__,__LINE__,__METHOD__,$fargs); + + foreach ($this->required_by_object_classes as $required_by_object_class) + if (strcasecmp($required_by_object_class,$name) == 0) + return false; + + array_push($this->required_by_object_classes,$name); + } + + /** + * Gets the list of "required by" objectClasses, that is the list of objectClasses + * which provide must have attribute. + * + * @return array An array of names of objectclasses (strings) which provide this attribute + */ + public function getRequiredByObjectClasses() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->required_by_object_classes); + + return $this->required_by_object_classes; + } + + /** + * This function will mark this attribute as a forced MAY attribute + */ + public function setForceMay() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->forced_as_may = true; + } + + public function isForceMay() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->forced_as_may); + + return $this->forced_as_may; + } +} + +/** + * Represents an LDAP Syntax + * + * @package phpLDAPadmin + * @subpackage Schema + */ +class Syntax extends SchemaItem { + /** + * Creates a new Syntax object from a raw LDAP syntax string. + */ + public function __construct($class) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $strings = preg_split('/[\s,]+/',$class,-1,PREG_SPLIT_DELIM_CAPTURE); + + for($i=0; $idescription) == 0) + $this->description=$this->description.$strings[$i]; + else + $this->description=$this->description.' '.$strings[$i]; + } while (! preg_match("/\'$/s",$strings[$i])); + break; + + default: + if (preg_match('/[\d\.]+/i',$strings[$i]) && $i == 1) + $this->setOID($strings[$i]); + } + } + + $this->description = preg_replace("/^\'/",'',$this->description); + $this->description = preg_replace("/\'$/",'',$this->description); + } +} + +/** + * Represents an LDAP MatchingRule + * + * @package phpLDAPadmin + * @subpackage Schema + */ +class MatchingRule extends SchemaItem { + # This rule's syntax OID + private $syntax = null; + # An array of attribute names who use this MatchingRule + private $used_by_attrs = array(); + + /** + * Creates a new MatchingRule object from a raw LDAP MatchingRule string. + */ + function __construct($strings) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $strings = preg_split('/[\s,]+/',$strings,-1,PREG_SPLIT_DELIM_CAPTURE); + + for ($i=0; $iname) == 0) + $this->name = $strings[$i]; + else + $this->name .= ' '.$strings[$i]; + } while (! preg_match("/\'$/s",$strings[$i])); + + } else { + $i++; + do { + $i++; + if (strlen($this->name) == 0) + $this->name = $strings[$i]; + else + $this->name .= ' '.$strings[$i]; + } while (! preg_match("/\'$/s",$strings[$i])); + + do { + $i++; + } while (! preg_match('/\)+\)?/',$strings[$i])); + } + + $this->name = preg_replace("/^\'/",'',$this->name); + $this->name = preg_replace("/\'$/",'',$this->name); + break; + + case 'DESC': + do { + $i++; + if (strlen($this->description)==0) + $this->description=$this->description.$strings[$i]; + else + $this->description=$this->description.' '.$strings[$i]; + } while (! preg_match("/\'$/s",$strings[$i])); + break; + + case 'OBSOLETE': + $this->is_obsolete = TRUE; + break; + + case 'SYNTAX': + $this->syntax = $strings[++$i]; + break; + + default: + if (preg_match('/[\d\.]+/i',$strings[$i]) && $i == 1) + $this->setOID($strings[$i]); + } + } + $this->description = preg_replace("/^\'/",'',$this->description); + $this->description = preg_replace("/\'$/",'',$this->description); + } + + /** + * Sets the list of used_by_attrs to the array specified by $attrs; + * + * @param array $attrs The array of attribute names (strings) which use this MatchingRule + */ + public function setUsedByAttrs($attrs) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->used_by_attrs = $attrs; + } + + /** + * Adds an attribute name to the list of attributes who use this MatchingRule + * + * @return true if the attribute was added and false otherwise (already in the list) + */ + public function addUsedByAttr($attr) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,0,__FILE__,__LINE__,__METHOD__,$fargs); + + foreach ($this->used_by_attrs as $attr_name) + if (strcasecmp($attr_name,$attr) == 0) + return false; + + array_push($this->used_by_attrs,$attr); + + return true; + } + + /** + * Gets an array of attribute names (strings) which use this MatchingRule + * + * @return array The array of attribute names (strings). + */ + public function getUsedByAttrs() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->used_by_attrs); + + return $this->used_by_attrs; + } +} + +/** + * Represents an LDAP schema matchingRuleUse entry + * + * @package phpLDAPadmin + * @subpackage Schema + */ +class MatchingRuleUse extends SchemaItem { + # An array of attribute names who use this MatchingRule + private $used_by_attrs = array(); + + function __construct($strings) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $strings = preg_split('/[\s,]+/',$strings,-1,PREG_SPLIT_DELIM_CAPTURE); + + for($i=0; $iname) || strlen($this->name) == 0) + $this->name = $strings[$i]; + else + $this->name .= ' '.$strings[$i]; + + } while (! preg_match("/\'$/s",$strings[$i])); + + } else { + $i++; + do { + $i++; + if (strlen($this->name) == 0) + $this->name = $strings[$i]; + else + $this->name .= ' '.$strings[$i]; + } while (! preg_match("/\'$/s",$strings[$i])); + + do { + $i++; + } while (! preg_match('/\)+\)?/',$strings[$i])); + } + + $this->name = preg_replace("/^\'/",'',$this->name); + $this->name = preg_replace("/\'$/",'',$this->name); + break; + + case 'APPLIES': + if ($strings[$i+1] != '(') { + # Has a single attribute name + $i++; + $this->used_by_attrs = array($strings[$i]); + + } else { + # Has multiple attribute names + $i++; + while ($strings[$i] != ')') { + $i++; + $new_attr = $strings[$i]; + $new_attr = preg_replace("/^\'/",'',$new_attr); + $new_attr = preg_replace("/\'$/",'',$new_attr); + array_push($this->used_by_attrs,$new_attr); + $i++; + } + } + break; + + default: + if (preg_match('/[\d\.]+/i',$strings[$i]) && $i == 1) + $this->setOID($strings[$i]); + } + } + + sort($this->used_by_attrs); + } + + /** + * Gets an array of attribute names (strings) which use this MatchingRuleUse object. + * + * @return array The array of attribute names (strings). + */ + public function getUsedByAttrs() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->used_by_attrs); + + return $this->used_by_attrs; + } +} +?> diff --git a/lib/session_functions.php b/lib/session_functions.php new file mode 100644 index 0000000..30ae3c9 --- /dev/null +++ b/lib/session_functions.php @@ -0,0 +1,176 @@ +_('Configuration cache stale.'), + 'body'=>_('Your configuration has been automatically refreshed.'), + 'type'=>'info','special'=>true)); + + $config_file = CONFDIR.'config.php'; + $config = check_config($config_file); + if (! $config) + debug_dump_backtrace('config is empty?',1); + + } else { + # Sanity check, specially when upgrading from a previous release. + if (isset($_SESSION['cache'])) + foreach (array_keys($_SESSION['cache']) as $id) + if (isset($_SESSION['cache'][$id]['tree']['null']) && ! is_object($_SESSION['cache'][$id]['tree']['null'])) + unset($_SESSION['cache'][$id]); + } + } + + # If we came via index.php, then set our $config. + if (! isset($_SESSION[APPCONFIG]) && isset($config)) + $_SESSION[APPCONFIG] = $config; + + # Restore our sysmsg's if there were any. + if ($sysmsg) { + if (! isset($_SESSION['sysmsg']) || ! is_array($_SESSION['sysmsg'])) + $_SESSION['sysmsg'] = array(); + + $_SESSION['sysmsg'] = array_merge($_SESSION['sysmsg'],$sysmsg); + } +} + +/** + * Stops the current session. + */ +function app_session_close() { + @session_write_close(); +} +?> diff --git a/lib/syslog.php b/lib/syslog.php new file mode 100644 index 0000000..25ca16c --- /dev/null +++ b/lib/syslog.php @@ -0,0 +1,88 @@ + and Alcôve + * @package phpLDAPadmin + */ + +# If config_default.php hasnt been called yet, then return. +if (! defined('APPCONFIG') || ! isset($_SESSION[APPCONFIG])) + return; + +# Initialize syslog +if ($_SESSION[APPCONFIG]->getValue('debug','syslog') && function_exists('syslog')) { + openlog('phpldapadmin',LOG_ODELAY,LOG_DAEMON); +} + +/** + * Verify that syslog logging is activated in the config via the + * debug->syslog variable and does a call to the syslog() function is it + * is true. + * + * @param emergency Syslog emergency. + * @param log_string String to log. + */ +function syslog_msg($emergency,$log_string) { + if (! function_exists('syslog') || ! isset($_SESSION[APPCONFIG]) || ! $_SESSION[APPCONFIG]->getValue('debug','syslog')) + return; + + return syslog($emergency,$log_string); +} + +/** + * Issue an error message via syslog. + * + * @param log_string Log message to send to syslog. + * @return true on success. + */ +function syslog_err($log_string) { + return syslog_msg(LOG_ERR,$log_string); +} + +/** + * Issue a warning message via syslog. + * + * @param log_string Log message to send to syslog. + * @return true on success. + */ +function syslog_warning($log_string) { + return syslog_msg(LOG_WARNING,$log_string); +} + +/** + * Issue a notice message via syslog. + * + * @param log_string Log message to send to syslog. + * @return true on success. + */ +function syslog_notice($log_string) { + return syslog_msg(LOG_NOTICE,$log_string); +} + +/** + * Issue a debug message via syslog, only if $log_level is set to + * 'debug' from the config file. + * + * @param log_string Log message to send to syslog. + * @return true on success or if debug log is not activated. + */ +function syslog_debug($log_string) { + return syslog_msg(LOG_DEBUG,$log_string); +} +?> diff --git a/lib/template_functions.php b/lib/template_functions.php new file mode 100644 index 0000000..bb3b606 --- /dev/null +++ b/lib/template_functions.php @@ -0,0 +1,23 @@ + diff --git a/lib/xml2array.php b/lib/xml2array.php new file mode 100644 index 0000000..d260c9e --- /dev/null +++ b/lib/xml2array.php @@ -0,0 +1,144 @@ +stack[count($this->stack)] = &$pos; + $this->stack_ref = &$pos; + } + + private function pop_pos() { + unset($this->stack[count($this->stack) - 1]); + $this->stack_ref = &$this->stack[count($this->stack) - 1]; + } + + public function parseXML($strInputXML,$filename) { + $this->resParser = xml_parser_create(); + xml_set_object($this->resParser,$this); + xml_set_element_handler($this->resParser,'tagOpen','tagClosed'); + + xml_set_character_data_handler($this->resParser,'tagData'); + + $this->push_pos($this->arrOutput); + + $this->strXmlData = xml_parse($this->resParser,$strInputXML); + + if (! $this->strXmlData) + die(sprintf('XML error: %s at line %d in file %s', + xml_error_string(xml_get_error_code($this->resParser)), + xml_get_current_line_number($this->resParser), + $filename)); + + xml_parser_free($this->resParser); + + $output = array(); + foreach ($this->arrOutput as $key => $values) + $output[$key] = $this->cleanXML($values); + + #return $this->arrOutput; + return $output; + } + + private function tagOpen($parser,$name,$attrs) { + $name = strtolower($name); + + if (isset($this->stack_ref[$name])) { + if (! isset($this->stack_ref[$name][0])) { + $tmp = $this->stack_ref[$name]; + unset($this->stack_ref[$name]); + $this->stack_ref[$name][0] = $tmp; + } + + $cnt = count($this->stack_ref[$name]); + $this->stack_ref[$name][$cnt] = array(); + if (isset($attrs)) + $this->stack_ref[$name][$cnt] = $attrs; + + $this->push_pos($this->stack_ref[$name][$cnt]); + + } else { + $this->stack_ref[$name]=array(); + + if (isset($attrs)) + $this->stack_ref[$name]=$attrs; + + $this->push_pos($this->stack_ref[$name]); + } + } + + private function tagData($parser,$tagData) { + if (trim($tagData) != '') { + + if (isset($this->stack_ref['#text'])) + $this->stack_ref['#text'] .= $tagData; + else + $this->stack_ref['#text'] = $tagData; + } + } + + private function tagClosed($parser,$name) { + $this->pop_pos(); + } + + /** + * This function will parse an XML array and make a normal array. + * + * @return array - Clean XML data + */ + private function cleanXML($details) { + # Quick processing for the final branch of the XML array. + if (is_array($details) && isset($details['#text'])) + return $details['#text']; + + elseif (is_array($details) && isset($details['ID']) && count($details) == 1) + return $details['ID']; + + $cleanXML = array(); + + # Quick processing for the final branch, when it holds the ID and values. + if (is_array($details) && isset($details['ID']) && count($details) > 1) { + $key = $details['ID']; + unset($details['ID']); + $cleanXML[$key] = $this->cleanXML($details); + $details = array(); + } + + # More detailed processing... + if (is_array($details)) + foreach ($details as $key => $values) + if (is_numeric($key) && isset($values['ID']) && count($values) > 1) { + $key = $values['ID']; + unset($values['ID']); + $cleanXML[$key] = $this->cleanXML($values); + + } elseif (isset($values['#text'])) + $cleanXML[$key] = $this->cleanXML($values); + + elseif (is_array($values)) + $cleanXML[$key] = $this->cleanXML($values); + + if (! $cleanXML) + return $details; + else + return $cleanXML; + } +} diff --git a/lib/xmlTemplates.php b/lib/xmlTemplates.php new file mode 100644 index 0000000..1749bac --- /dev/null +++ b/lib/xmlTemplates.php @@ -0,0 +1,496 @@ +server_id = $server_id; + $server = $_SESSION[APPCONFIG]->getServer($this->server_id); + $custom_prefix = $server->getValue('custom','pages_prefix'); + $class = $this->getClassVars(); + $changed = false; + + # Try to get the templates from our CACHE. + if ($this->templates = get_cached_item($server_id,$class['item'])) { + if (DEBUG_ENABLED) + debug_log('Using CACHED templates',4,0,__FILE__,__LINE__,__METHOD__); + + # See if the template_time has expired to see if we should reload the templates. + foreach ($this->templates as $index => $template) { + # If the file no longer exists, we'll delete the template. + if (! file_exists($template->getFileName())) { + unset($this->templates[$index]); + $changed = true; + + system_message(array( + 'title'=>_('Template XML file removed.'), + 'body'=>sprintf('%s %s (%s)',_('Template XML file has removed'),$template->getName(false),$template->getType()), + 'type'=>'info','special'=>true)); + + continue; + } + + if (($template->getReadTime() < (time()-$class['cachetime'])) + && (filectime($template->getFileName()) > $template->getReadTime())) { + + system_message(array( + 'title'=>_('Template XML file changed.'), + 'body'=>sprintf('%s %s (%s)',_('Template XML file has changed and been reread'),$template->getName(false),$template->getType()), + 'type'=>'info','special'=>true)); + + $changed = true; + $this->templates[$index] = new $class['name']($this->server_id,$template->getName(false),$template->getFileName(),$template->getType(),$index); + } + } + + if (DEBUG_ENABLED) + debug_log('Templates refreshed',4,0,__FILE__,__LINE__,__METHOD__); + + # See if there are any new template files + $index = max(array_keys($this->templates))+1; + foreach ($class['types'] as $type) { + $dir = $class['dir'].$type; + $dh = opendir($dir); + if (! $type) + $type = 'template'; + + while ($file = readdir($dh)) { + # Ignore any files that are not XML files. + if (! preg_match('/.xml$/',$file)) + continue; + + # Ignore any files that are not the predefined custom files. + if ($_SESSION[APPCONFIG]->getValue('appearance','custom_templates_only') + && ! preg_match("/^${custom_prefix}/",$file)) + continue; + + $filename = sprintf('%s/%s',$dir,$file); + + if (! in_array($filename,$this->getTemplateFiles())) { + $templatename = preg_replace('/.xml$/','',$file); + + $this->templates[$index] = new $class['name']($this->server_id,$templatename,$filename,$type,$index); + $index++; + + $changed = true; + + system_message(array( + 'title'=>_('New Template XML found.'), + 'body'=>sprintf('%s %s (%s)',_('A new template XML file has been loaded'),$file,$type), + 'type'=>'info','special'=>true)); + } + } + } + + } else { + if (DEBUG_ENABLED) + debug_log('Parsing templates',4,0,__FILE__,__LINE__,__METHOD__); + + # Need to reset this, as get_cached_item() returns null if nothing cached. + $this->templates = array(); + $changed = true; + + $counter = 0; + foreach ($class['types'] as $type) { + $dir = $class['dir'].$type; + $dh = opendir($class['dir'].$type); + if (! $type) + $type = 'template'; + + while ($file = readdir($dh)) { + # Ignore any files that are not XML files. + if (! preg_match('/.xml$/',$file)) + continue; + + # Ignore any files that are not the predefined custom files. + if ($_SESSION[APPCONFIG]->getValue('appearance','custom_templates_only') + && ! preg_match("/^${custom_prefix}/",$file)) + continue; + + $filename = sprintf('%s/%s',$dir,$file); + + # Store the template + $templatename = preg_replace('/.xml$/','',$file); + $this->templates[$counter] = new $class['name']($this->server_id,$templatename,$filename,$type,$counter); + $counter++; + } + } + } + + if (DEBUG_ENABLED) + debug_log('Templates loaded',4,0,__FILE__,__LINE__,__METHOD__); + + if ($changed) { + masort($this->templates,'title'); + set_cached_item($server_id,$class['item'],'null',$this->templates); + } + } + + /** + * This will return our custom class variables, used by the parent to create objects. + */ + private function getClassVars() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $class = array(); + + switch (get_class($this)) { + case 'Queries': + $class['item'] = 'query'; + $class['name'] = 'Query'; + $class['cachetime'] = $_SESSION[APPCONFIG]->getValue('cache','query_time'); + $class['types'] = array(''); + $class['dir'] = QUERYDIR; + + break; + + case 'Templates': + $class['item'] = 'template'; + $class['name'] = 'Template'; + $class['cachetime'] = $_SESSION[APPCONFIG]->getValue('cache','template_time'); + $class['types'] = array('creation','modification'); + $class['dir'] = TMPLDIR; + + break; + + default: + debug_dump_backtrace(sprintf('Unknown class %s',get_class($this)),1); + } + + return $class; + } + + /** + * Return a list of templates by their type + * This function should return a sorted list, as the array is built sorted. + * + * @param string Type of template, eg: creation, modification + * @param boolean Exclude templates purposely disabled. + * @return array List of templates of the type + */ + public function getTemplates($type=null,$container=null,$disabled=false) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $result = array(); + + if (is_array($this->templates)) + foreach ($this->templates as $details) { + + # Clone this, as we'll disable some templates, as a result of the container being requested. + $template = clone $details; + if (! is_null($container) && ($regexp = $template->getRegExp()) && (! @preg_match('/'.$regexp.'/i',$container))) { + $template->setInvalid(_('This template is not valid in this container'),true); + + if ($_SESSION[APPCONFIG]->getValue('appearance','hide_template_regexp')) + $template->setInvisible(); + } + + if ($template->isVisible() && (! $disabled || ! $template->isAdminDisabled())) + if (is_null($type) || (! is_null($type) && $template->isType($type))) + array_push($result,$template); + } + + return $result; + } + + /** + * Return a template by its ID + * + * @param string The template ID as it was when it was generated (normally used in $_REQUEST vars). + * @return object Template (or default template if the ID doesnt exist) + */ + function getTemplate($templateid) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $class = $this->getClassVars(); + + foreach ($this->templates as $template) + if ($template->getID() === $templateid) + return clone $template; + + # If we get here, the template ID didnt exist, so return a blank template, which be interpreted as the default template + $object = new $class['name']($this->server_id,null,null,'default'); + return $object; + } + + /** + * Get a list of template filenames. + */ + private function getTemplateFiles() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $result = array(); + + foreach ($this->templates as $template) + array_push($result,$template->getFileName()); + + return $result; + } +} + +/** + * XML Template Class + * + * @package phpLDAPadmin + * @subpackage Templates + */ +abstract class xmlTemplate { + # Server ID that the template is linked to + protected $server_id; + # Template unique ID + protected $id; + # Template name - as extracted from the filename + protected $name; + # Template type - creation/modification + protected $type; + # Time this object was created + protected $readtime; + # Template file name + protected $filename; + # The TEMPLATE attributes as per the template definition, or the DN entry + protected $attributes = array(); + + public function __construct($server_id,$name=null,$filename=null,$type=null,$id=null) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $this->server_id = $server_id; + $this->name = $name; + $this->type = $type; + $this->filename = $filename; + $this->readtime = time(); + $this->id = $id; + + # If there is no filename, then this template is a default template. + if (is_null($filename)) + return; + + # If we have a filename, parse the template file and build the object. + $objXML = new xml2array(); + $xmldata = $objXML->parseXML(file_get_contents($filename),$filename); + $this->storeTemplate($xmldata); + } + + /** + * Get an attribute ID + * + * @param string The Attribute being searched. + * @return int Attribute ID in the array + */ + protected function getAttrID($attr) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + foreach ($this->attributes as $index => $attribute) + if (strtolower($attr) == $attribute->getName() || in_array(strtolower($attr),$attribute->getAliases())) + return $index; + + return null; + } + + /** + * Get the Template filename. + */ + public function getFileName() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->filename); + + return $this->filename; + } + + /** + * Return the template by ID + */ + public function getID() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs,$this->id); + + if ($this->name) + return sprintf('%s:%s',$this->getName(false),$this->id); + else + return 'none'; + } + + /** + * Return the template name + * + * @param boolean Force the name to be lowercase (default) + */ + public function getName($lower=true) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->name); + + if ($lower) + return strtolower($this->name); + else + return $this->name; + } + + /** + * Get the Template read time. + */ + public function getReadTime() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->readtime); + + return $this->readtime; + } + + /** + * Return this LDAP Server object + * + * @return object DataStore Server + */ + protected function getServer() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs); + + return $_SESSION[APPCONFIG]->getServer($this->getServerID()); + } + + /** + * Return the LDAP server ID + * + * @return int Server ID + */ + protected function getServerID() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->server_id); + + return $this->server_id; + } + + /** + * Test if a template is of a type + * + * @return boolean + */ + public function isType($type) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs,$this->type); + + if ($this->type == $type) + return true; + else + return false; + } + + /** + * Return the template type + */ + public function getType() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->type); + + return $this->type; + } + + /** + * Get template title + */ + public function getTitle() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (! isset($this->title) && ! isset($this->description)) + return ''; + + return isset($this->title) ? $this->title : $this->description; + } + + /** + * Add another attribute to this template + * + * @return int Attribute ID + */ + public function addAttribute($name,$value,$source=null) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + if (! is_array($value)) + debug_dump_backtrace('Value should be an array()',1); + + $server = $this->getServer(); + + # Initialise the Attribute Factory. + $attribute_factory = new AttributeFactory(); + + if (preg_match('/;/',$name)) + system_message(array( + 'title'=>'phpLDAPadmin doesnt support RFC3866.', + 'body'=>sprintf('%s {%s} (%s)','PLA might not do what you expect...',$name,(is_array($value) ? serialize($value) : $value)), + 'type'=>'warn')); + + # If there isnt a schema item for this attribute + $attribute = $attribute_factory->newAttribute($name,$value,$server->getIndex(),$source); + + $attrid = $this->getAttrID($attribute->getName()); + + if (is_null($attrid)) + array_push($this->attributes,$attribute); + + return $attribute; + } + + /** + * Get the attribute names + * + * @return array Array of attributes Names + */ + public function getAttributeNames() { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + $result = array(); + + foreach ($this->attributes as $attribute) + array_push($result,$attribute->getName()); + + return $result; + } + + /** + * Get a specific Attribute + * + * @param string Name of attribute to retrieve + * @return object Attribute + */ + public function getAttribute($name) { + if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) + debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); + + foreach ($this->attributes as $attribute) + if (($attribute->getName() == strtolower($name)) || in_array(strtolower($name),$attribute->getAliases())) + return $attribute; + + return null; + } + + /** + * May be overloaded in other classes + */ + public function isAdminDisabled() {} +} +?> diff --git a/locale/ca_ES/LC_MESSAGES/messages.mo b/locale/ca_ES/LC_MESSAGES/messages.mo new file mode 100644 index 0000000000000000000000000000000000000000..b3dabc83d2e835b637aa0f0091faa0e7e749229d GIT binary patch literal 9706 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 UKbnkF3!U>aTNyIswz^CCKY3G^6951J literal 0 HcmV?d00001 diff --git a/locale/cs_CZ/LC_MESSAGES/messages.mo b/locale/cs_CZ/LC_MESSAGES/messages.mo new file mode 100644 index 0000000000000000000000000000000000000000..fb39b76dcaca3dcec53c95aebb620c8f54842cbe GIT binary patch literal 21326 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 literal 0 HcmV?d00001 diff --git a/locale/da_DK/LC_MESSAGES/messages.mo b/locale/da_DK/LC_MESSAGES/messages.mo new file mode 100644 index 0000000000000000000000000000000000000000..350f4ee5d53dbc3a563726fdb40ced2cc1f6cba9 GIT binary patch literal 26102 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 literal 0 HcmV?d00001 diff --git a/locale/es_ES/LC_MESSAGES/messages.mo b/locale/es_ES/LC_MESSAGES/messages.mo new file mode 100644 index 0000000000000000000000000000000000000000..a03a9a426d72a2a184d9abb959729201a02c7da4 GIT binary patch literal 64477 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 literal 0 HcmV?d00001 diff --git a/locale/fi_FI/LC_MESSAGES/messages.mo b/locale/fi_FI/LC_MESSAGES/messages.mo new file mode 100644 index 0000000000000000000000000000000000000000..0318b4d14f7156f5ac6f851bfe21afd6b2a64887 GIT binary patch literal 62050 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 literal 0 HcmV?d00001 diff --git a/locale/gn_PY/LC_MESSAGES/messages.mo b/locale/gn_PY/LC_MESSAGES/messages.mo new file mode 100644 index 0000000000000000000000000000000000000000..c7a17b7310f2cfd8b4e3100585147a40b5cb0e84 GIT binary patch literal 472 zcmaKoK~KUk6vr`o+R?Lz9z1C9VLL>&iUfo~NH!%f4A;Wys2T0jbp}6(S3jDc#ZD5q z`I29Hc>mY``@f&_v#*-16U&9=(sF9Ku~g+*zHQUDZ>2fZRI7KsHZV!xmFq$%Nm0JZ zvxMa=*$U~*c&@a8s7OTuPi0y_tSA~S!Vo?8qX2b+s6PpN{o!yH%;#Na`VzxHb7t&U zFl2^Pz}fU$-*sgsd|TlgeHu8cL^KCz?dTF)3+aXP~6v(pr4xc2~o9<~GlmkPm3R zVY=YvaS@NeJL;-c-nfQ9u2mvrN|Cn`##uthO1a+HyFsw~JK7<>3)lyIkFZNI*~ePK Ym`kqrkq(pSYE_CXL8Rql|Jtej0$a3#SpWb4 literal 0 HcmV?d00001 diff --git a/locale/hu_HU/LC_MESSAGES/messages.mo b/locale/hu_HU/LC_MESSAGES/messages.mo new file mode 100644 index 0000000000000000000000000000000000000000..029ceec36227792be9817d77732939680fbaf93e GIT binary patch literal 22125 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 HR`&i6o?n`D zO$B#R5W!tk6cJGncdv@OUibaFd#~bx-uL@^o~m0ba#Ut;8(!o!ClVa0;hs|gVO`f1CJ)W6g(Il1or^1 z0+sK1A^cYG0K)G9CxV{Icq|C1CF{Ubz*|7I=To5Q z>&u|Z+lk4b_e}uRj}t-F`zTQTG#NY+JOexiyckrywt}MTmxC(j-68&i;L`|y1=RRF z0jhnwFZOyL4~kxV4gy+BE>umB~g><$nNVY9}8BRsXMo>c3rhUlr`rmb_)4?I2 z=%*7@{TG3|gBOAt-}RvApbBcfUInVW7lX?8h7f)~sDAiti2quM{}s3g@jEZ`@+W}m zm!rX_fSmzP4S06IWuV@_8r%h35AF>1fvV2{xF5I~RCzA|cLiSw?gqXN)O+s))tF*;z5IOwrl9C$HmLfp2GxI;fXZJ3MQ_)GqT82+=XZc7 z5WWu--FzR^^Zy3*o_)^q_#;4-Hy0EgEC(lnHBkM1GpKgH9#p@-3sid^1=Y^af=>k> z16A&KK+WS{fYZRkmU}r}pyv7cpz>V?o(PVF=dTI)7Etf`0I2qU4pjQDf_s7g4ju>o z98~@GUg7mQ0#tYssCLc_@n?Z4;U%Ev+aRd%ycV1QJ`dEm-3+Q-w}NW#Ys2$*1iT*< z-})G+bl(D1uOEP_=g&Zmj{`ueA4 zeaZJh)&KZa@DQ*9s+fsK^T0XaHQ?#s zdqL6L??BP<0js@!9iZN~1l0S^1J$mJL5=?qsQw-WMb}q>8kg6A6T$a{_(#DL2>%dN z{(X8}FE|o}G?PW3`1ws>ANUDSeCP9^N5Ky8 z>!9Y-?icv@9}9}U&II-T3&2CbesF*A3h)5%MsQ#74p8-Z52$)R1Ztc<2C80bQ9c^jzm-VLffp8}Qtm!QV+Z{W`09v8Vj zI{}9{e%I^ZzFPDIm!78Znyal8ylh=W> z!NTz)t@_+y#EdYRsM0H=F5rT5V#OjId28k-UmU^!M}lrgI@yGU%v)b{;|D|ouKl~ z2UWinpvGwpsCM>(N`E=1a;^gBg0BR{|Gor@fBhX)Jtx8JRL&`&$~gm6`R9S^pG!md zrQjKa-vp|jKLpj@pMk3XpFr`OJ^TIr2ZEXx$AagB^FWpVVsKaRRiMgyJt%tkHYk4f zS5W2cRCf8XKd5|DK-KePQ0+WDJU=glp9!j;>!9Ad2~5G8z)9e{LG{a*L6!4;Q1$&8 zsB!#HkblV&A>2FQ@81BbAFlyBz*mE+@25iiPeIL(od=!1_5xQBJ|0xRH$c7rZQzmM z=fQ>GFTrEL84yD!xDwR(Tm>Et-UF%~p9H6a-v>1w`&7I?7X`c(Jf8TUflI-?FZ1v^ zQ15#dcoO&u@I>%)py=w);GW?04W9lKQ1O?5bHE$GCE&xL-oIzn?aEU?^~WGM1-uqi zJKh2+{ii{_cjBr72N8oPY@4;QcKY_b|e*;r+r@G6pNucVn92A{B2UI`598AG?fRn+` zgPI?I0L3r%9P#%Y7jPE1FY#xAdhbe5p9tTBl2e$lu=Yo(-@(i#8{1m8skAo+Hb4Sr7!5Vlj z_(@RoaKJ`my~)MkD#8zdDu1s{?iZQ{GUbzD@LAwvAVZdPZ}xH@1kWP;d$0?fy~V>D z!MTL*14YNb1=YWQ0VjgVR_C|-gS!))2I~3D5IzM|zB9lH;5nfBc{Ql{c<}f`hOpIB=|6>{`@ZZ{hjD{ zuuAw7&vyUfN!PkPb1Qf<@!tZ~-ig;aeXRj6Bm4>w)|c$^9G@q3aDec~K+)%k&xJ<7 zSApk(e*kBIXFt#Nj}cJw9OF+@}1EA9X0Xz|$ ze!Zu^5EOqYfug$>n1U|^j{)BbYJ5KfP6xjk!h5{H=l{Xr5yZ~|JHZv;ao`o8^4|^~ z41NSu|9=hK6Z|Qt_x%pk^F3bZ{eLv5{+;C?Um_jQ3!CA=cwMFGp8@?Q?B-q(Su_bb7} zz;}V7yH5xFAt-u!0#x}EU*hF23fK+m`Gw$K;4r9u+zP56Zv|DqM?tmskD%JM=MBz3 zCxQx32KNCwK+(bJ;8bukcsBS3Q0aaE?gRb@sCN7rR6jrUMxQ?uLA~ctQ0+Pq6yI0~ zc7r`&5BNr~3;ZKE0i1V}^VP-RQwVPbRql15=GhBCjpGfV`so#53f>D&0>1>R-G2lR z0r$Vz%Q*o|3C{sLz%`)8-+y|;19|e`}%b?2t4R|j2)LXnh z>%f%oGr^hQv%wkQy&?Vwpy+p(m-_rW4m^eMx!@9|2UGBq;5_i>U?+I|%RIg(U<*8+ z_?Lrf-v>d_?PK6X@Q9atdY(VO72=-_?nC(H;DO+spvLQdaDVU% zpvK{cpx*aOQ047Ecn7q~O{_VD~&px*mY za9{Atpz8f2P~-D+P~-L+P;~fLP~)`AZC>wvK=t!vQ2cf=sP^`P>bE+m`o0X*_}m?y ze;qu8@Q*>|`x~hD9R3Qg&(pwz3C{&j1y_NS!RtZM#XCUN`%|Fa|L-CE1b8UneP8Kx zHx*QWuLG6742o_ygKFoiLACRCQ03kQsy-hD=Yrn>RqsPzV0cLcYue19|Ly* zzXR?K{s2^cehcb7e*pEKCqn#Qukq&-!70Qa4C;Mnf@=Q~P;|E(6uqnk7lW698t-?3 zD(?X>1wR8G4*n8U`aNFj<9#HkaasVX9fP38<0??&a2u$4-xb1d0rmd-LDl;qP;~uq zP~-LW@cb8`>i0YFXz(xKk>FvkbAE6NcnRUN!4=?Zz;)n%g!l!o_wrv0iXQI-RsRow zs{fb3qrjhms`u`;CI1`z{BtGa$4Y_ zgl`7bzPEs?=R=_Q#ZN)e>7PLH_g(Mwe%~ix3eF&YHmG^p3o89qQ1yOZz#Bk~>#d;1 z@lBxG`Bv}<@IFxQe+;zug7#ie{j=+vJpV*c?M^}EKLr$BF93G~SAq+{wV=|y0@OTs z2Pk^^B&hd&6I8qZ7@qHYm-GK=;56b_fg0bfpybBQpvL`S@Hp^$py+PbH+z2{0v&o@?(zOS4&0gWOz?DY4k-E<0hR8p;B@dKpxX5- zQ049Y7H`*7Q2n|RoC{V!(d8YW`t>6LzX7VfzX$uk$H9leOWx}3Ir?or&u4?`pHsk- zz=hybz)hg~=^9Y&x)D@AyaPNNd^p7K@^+_(NubK<0F`epsPSGJupc~!@HL>?`AJak z`F6mcfO^kw!0F&V@9=ib2i2|%!A|gUP<-xo@N)27;3?pwcRGDs1S)(bSO(t&27UERA2GyT8fhU9S2;m=rD+%v>pQm39D*Z*^ zf#7AJ>UnjDzY$b>ZwJo>9|ZRSpYndM_aWe7!bgEh*9U5RuK_i0ZU8l(?go|b5pWmq zF>p`ttDwg7d*A`!pF#EW-XCx}IvAWpcs6(fxE9;h|`#`E5QUj~Re-9MBq#yNmo(vvCxEt&MYoOZs8gLHy3GhVlui#GLl!u+}rh)38 zd7$Rm3Q+C22;3DcfuffIP~&tNsB&%w)xHNoy?2*K9FGIlKV1Pwz#|C17EHnWLDBm+ zLDBgyz@x#xf}*FxKj!0i9C#4n6`U?_;JcMuq6rH^gycm1~sBwM*+y&h8hkB9hWpLBZL3@#x4wV>MhU2qHdcTn}({3##rw}5jA{{|cdr+pe;1il`ufPV+C z1&2Q4{+?fe>esVB>+4rf2djkN2fiAd^f~GTei+m|S@dr{kDdiCCj3wc@Ai4uW0rxU zgBOFlfv*SE?{5OtPag#L0KW+C3Vs9J6Z}rVp9TCq_!Q!w0QUuV`+}Ey5U6pQ3aXsb zLDhc|sP{b+)c6g6`+--7@J--egzo{B?>H2e?dt}22QLJb ze?6#rmBGWnVNmn<`CtmZ6jb}(3##8f3C;vR2kL!)2Q|KXeAU}=G^qL92`YUzxDyzE zTXy!lXMz77A}iouNOTVP0`S>9TNIuh7}Eca@cBI3m+-HO1ron2;SYju083nta(}JT zb4}%XDVKh4=Gh@!`aPRV^K=E*L0s|oQ=VTO0t>i*9`_H0@Kqu2U0{iNoD;&2gI5sl z2j3dvUPK#rr&uiOF5tTfzn<&V@Xo(;uirbsA>zIa&IC7ru!DptolFR6-@*NT zdJbN~C7Ou8PlTIikoLFS-%7euxStjBZX*0J@t1*LJnI3U#dQIfc;NBGeF*$I z*OlDA68uln*TDw(U!Z=Ea=$m%WDh1!A?@+p|B$#<+z)f<_bkF!`E9aB@r3u_(r+SH zAJ<0};P+0hZ*V=0bT@OI#kC)4Pbco1ArH6NZy|AiBJ^)yAJ^HWKM<^e&nJF_`?*~D z{n;T|O8Bo_=MjEgc&0~}=@0pK<vu8F^_##ogSdWh4sp-p+QNO6 z>o%?lgdYL*dp7rP0WSz;tmgiiTuTZ6H_w)XcY@z1?y2B3u46*lLGJZCkMPq$$=0J4 z!S4#LSM&Tdu3vDSNmxAWY%cx&(;@piDU@|A_$989@Z`NA{_Wr!iGwxS8pkWLoX8vQ zpTTuAX|(tIzq$V@*LB?g5qxDR<6-a$uJ4#Ggi* z6Sz9LzQ?l_VEkRk{cR!dkBMAI_(fcQBJNtQ#oX@$UKi3xo;<<*+d~1b0)HExg(!pL zh+9V97lY3P)8fN$e>%^e&!yiXq|xuMTp#1Qitw*__BQUX2Y2VXo$Iw+KP2u8;9Amr zfcqoCuYpsD`xe(&=A@E0@AIkk7LinSE_1ldyj^MhK`(IcL{xoouxCJ5n z8`6F!q+cK68Uart-HF_Pp68OG&jh=`H*oFD{d2iK$8{rDH)(%K{8BFc-bLK|!1bVh z_j9e`{`e672Dm42cXIWUw?+6h+`pFVbzHCK8syS%fakMAz8k<}xN0HnDg5u#iTeQ8 zX0GMo!I_10P44d^{w*Qy)gjFbz#-yVyyri_-w-QPLZ{vC@;WGFm;%?x626&4S@Y^e-eP77?hk$zaG45Xu{w>7q6w)ps?k9zG zHxj;xtB2<=1pkX?U*~!O;a?Hf?<0iI4S5DbIf`FQ+-tbj6ZZo}gx^;16CwRgF%sMy z@*WVLEeGEkp5Mr`wS=z)cLSdj;^%QcDdf9^`!^TLdpY4>a;+imO0F+(9l|x6>oD?s zg=g1szd!d&xIc+Yze@-|0PY{c`+@_6@8i0fYhsA+=3c*#a1HB*->11c?GCvR>UDWY z|NDT~6TgD{UT`$TUB-QPxc_dzeJH1k_p6k~M&g1z) z4ZlTFD8BwsNZ44@6LV8gUP+%QH1Ak9mI7o z;g^9g3(u!=uip&v9mRDr;bq{V;5p%$;No!qH11dO{AjLkbN@o(=YjfNNZgTJr*gfN z_#23OBlkbxI-6@QaZdsDdyj+Jp}TVbDXx!m{U|*DHnmft!dNd z_toZ4?yF5sr%oQN^k30&(&TAbHJ^MTWF0?OvCrCGJfAGveetSF--aDj{+vdAbcCws zW26?$=hs)us84UM9WM2k(^fqlEVmYw2TBa~f>x_h=^bsAr%p>Z zRa!%7sg{n`HqN*W4SRst+digGwrW5OTE={ ze>zZaq^%)hn&k%1|Jl-7L*=x$)U;YR%cVx&P}*NFH`7|Zm6kU{sAFHy`M>Z6YFi#2 zX>CziRlTD=kd|UcHPwMMZ=_nhDjpnPZ`DMtNPSI$E~S%ADm>l|ou-L{>{EGHNe_S!$1&f~EfcN~=<@m8u%=Q6vAX zDwc>rh?o{$m&I+9x-e9{*`}m(*(^(Mr3M4Z(`63|+?ZNhbQAjPgTfVnKM9xw);wW4 z75ZqZ{!9UXL{y_bz%y%B9=)($-;ge@wHjNJ1=UK4BJ?+1!+Y!o2I6;RJz}J5rB-EQ zIbDnprN4~&HCx*loN>HTIxt%6Q#aDwQp*?zBw}nMWOUvq#tr)ugRJ-4q_I(Bq6}3A zhpJq(lu1>sZ-OP%(z0qB=h{$-%G8-xO@weC)W?_=I!qbrwJpQ-QL5i4r%d9sIT~&@ zm8cJ+L1#gP6kFXAX13T0T+a(?p7l>=rRJWKjLl}fuOeoYy55mMbk<+Ix8B=A6A2_X zxtR_$;6Rh9s3&1yRXgW3X$huF+r@NM?E-CiiaFYr+7`D%{U5+|Mc8 zuh}vp63FsM4&=j`MN2X;eMFk=aT}o*$)qvy-ny}=BO#1QY@DkQ=aX}jF!P#LO55D@(^oSQnfJ!q7N>l+!@ zQhb$ZvrWEP>f4a=fx|*c;Hf5u5jXW(b;~r5ThyH_bgp4M zEm=5Psfr(@&01*$VPvAS)hHVS>#L7!Aw_jVIy%xXX(-V-P_HtrltuiyixwMKHn|85 z^+|2^>Dwo&qk{*~K>JBq>nm52uAx$G(AgvXKZG2}n%^~4ruLb9=^CPHjdCsNsF+^5;DvOQQS~bYSv(*G&1Ca_hd3f zelm4Y_q6fzZmdX$ptG9PW0<#;2P!p_52hF7Bn-vB@-h= zJtc$RnFLsw%kin@<}{u{!TOW>-^C`jETVhm8u)r&9|CS*6uML*RA0?d?-gsf$B#`{ z5XPdW*tyj@9D|XWE?x=+Eb5-FBID!0IrJtqilU|Z1@;&C|CmV8kk5a;N1^457OV<9 zNZk-ih%7(jEXL@@N#Uh!n^R?5i`(-APUb2-%%k|m_)J+Fb!Qz&%ZArcOr%)WK)Ho2 zaM?(CP?HW(FVR(K&6t^S$>ipx#q7r486g|sLN$U!R2_!v%rW|#St2{g3M^VOdEF7; zXeq;KwZAm7K9)?Rjb8DsupegAwr>sb<8~UVDw;M_6ehnKTBtCD-e{$3miH9jlSihj zU}7+D7zfNN?@lM4b`D@Am}*nd-e_frYSZ3`HvNAELUmpm+ybgrG1k<%F6J6?&mky! zAz;H5=8&ZdnruuA`xn!Wyug$ATrk=~C(n`wh7@L*C#|&3iqAEFJP$G=)JBS7J{6Bu zQnYUP-)MsYX{GRjniy%lmd6EikTgwXbUG{E%#Js6;>}6%=KRqzx^35JD}mtQjqUcU zVrVmTXQhibkJKCFg1nPO<=)Xj{+iJa%K8hCs#uF~`d2e6Xi6cjG{D4S zpy5YT#f_%T%brxLD0_h#v-BfK?Rrd-cTbG58Q{GfUf?=VQ5%z494iHD@~q-f&QGVp zNf*gPZVjuO$Jhmn%FVt;WyC}h_b_amMqXeZ>~VKOF-4$hBv7A^Aj;F~#S0d7tn6NX zQD?F!x+D;Svcs9z1?k6Av*?#FkxO)X2%7YZ0nJYlQlF7mq)VPks*F~eL#QsEp>BG9 zRPQ}~K@6OgENV|NT-spjkj+$SG^qTG>V2c?AeYXryhD@2BN!VsYFMvLX(8w8BPe8P zxzVVjuo0=r=C+ajMcB!x@_TnJCW~u*n$=7Ml*f=a-NaNY%MuYQ(_py;+(~K?klJn| z&FFdKOjuMasyH&Mzki-mit>Vn7DGHm6WpYt(Z&X;ofwM$75zy;X^!@Gn3~vcgsg}t zN~^eGEJxZkRIf9}AruB7gvLy&#g~uLZuGpx>KFf;y0a<-HZ@S7XeG5XA<`NiK}~8f z-|MQ}<`N#8Ai@aQM0AiG5QT&gHCM%xB``uXbO)7M)cO^6>MSH!ULUNFnu44?+RWq4 zsXLI9B^0PX^nQRiI(ko~fnUmq&2J@G5{OrpS2JC);Gz^VcM?~$Y7C4HCrg4&oZYnB z#qlxzKP}Wi@JMKr;#kmB!&3{k}PgzW3W_XPK#4ubFZ$`UE6!O7Ezu*TqRd_YM#3W$3xqX>d~zmdhSJhCFchC-p|h8kt0T$MN`Kk@z!4cn zRWno8oAzMF+S(9_YNp-vgn6NBa(lkuIGpYdPp^h4JC!nmS5vdk%$_D*j?PdoiWqB= z447V;H*R{!Ca#gSI2Db?LN3A&GK>&K#A{aLS19$#{jq&dN;*|+q$c6gi{mpb^-7v0 zOY0E6{-let>1)ANLn6? zO*}d0YwCp!W%%L_@*o9CU1~H+Tg)eK@4|X6$xj92Q)YU+vQdWbrV6TnY*~4y>I3q2 z%MG-w)>j>cIGbCVSk?JJ+LJm;5;iYBeR=fcB44$16 zwb)-0IT;;`7_1FS3{HC>K6}krBKG!DXQVE!rfR*FWkWbP;qR zs%oI(!yeE-&G@0Rl@|4 z^5%5X1teb5q$w&!yA zm%5!?D{xLx1J?ys$S1x+%4GC0H{$xpROgpI*WG=OZdeT_7IPUM*6buR{x;X_xeuee zn$b;HE?Y#*=F0FWhIY9&*c!@$wxrdpY%M1%@JZquUtYn31V_PNzM_K5pQ=tqMzyoJ z{Fx?jE+%%A@)A~qTbDxO?#ZFV$S|`PWd%tQZDi5GF7FF2F%;J6VN}E0N7v zxGgt&D=egrqiQNio4%)rb+&xhT~E4E-V2M2ZU?P5?{|T3OXVp}$sOdfH4~%8u{qiZ zUoUQpuqCN%rH!Xyh0YvarOaW#1M^Ue)r^cb2GOw;6}%WOvrIvYW2VO@*qBFQ883^` zDp-tFfzG&;!{tufYsb@SNePJ#MFkW!V0fO%4a&eY)t`B(X@5vCIAb=`co~&KjjAyi zg-L8{cjN0+A#W(uMgt)=!Yf#AvBeYA6a2igsF{Fnxk$(956T#N4#7q$jjB;;ZjiX6 zgnD$|(Xq84Wg#f^NfL;=(r|hh#}K-^yZPMCE;pysAhdK=0lAg_99AVHC4*3w=83id?nhl zQ};>)#Z;-qRn(0t-Cx5wH)QVEX`E;kOsT@;UfD=lfk81hjWzgU-Ta7lBaPVTCJa3% z4klw$szX9%mS0#Au|76QY~Ht(rY-kwApzY-$8eL|a%}-kcG+&l1jMn(MjQhNooF%B z#4OJIet%U@*V4r+7O=?z9y;KLIm#(aX`r0K#>>entR(skYc48&*$r+6T&0lV8a5YX zu|Y44R&fdMguS(B7iWptz2HinsYk~a;$y_N>%EyMree@ivwl_*T(=jLXlv%iwdF4B z&#>=7TTO-;WwzeHkqUlZ)V_Mypfi0u9_D_ftYGlXgblL~fQ@uylKlo{dXTZ~=A} z6gFLW3NyUJdgu0%KqK3IO)NgNIa!TufpP83JgoQIib=+2NrJ>^YG;Lf#bbivRD-tI zmM05^ZTo~5nY+1-r0E&s&#wN)V+$BB|-#4#7hd0=ZIj zY)IB#5E;d0RvQUJU~;BQm%+cB4!{E0kYQnMiYn?ht9|iB`YU?5Tuf;fILZ{IOEQvj zbF^nc&+>e_P+8jm2OZjUbz+^)tAorDM`9+hP+2urYUZ4*6J}YevO4XrE9^2Mg8#ZR zDQa7;_j`oi3u=t~l2)|Lb6nL) zk1tD0$8gb*^w?It0BLYydStrVH_OF`Ja5rpta@VgXzU3jkKW@1X1u&})YK0BoI#S9D_1Itu1ouxnN z*?@`EBM)E3t=M2@TejrzG{cUKj!w8ljI(L0C&-0D0b;SH8`EOeSRg_DE$#`45p4^f zJ+1PH_&u{@vU1}4XIKoPrIGZE_NG&%f>N2VJ}^y@?s-dPO%t>Qj)?3T$oMlmwYt;x z2XvZy3m9adVsuhriA24s1Z@inBwo<4gdM_ME{4Ww5R4pd9l`P4}j=rFH5G_Hv{j=mE1+weY~=cO^S!9@|4 zQcYL1LZq-~`+3n8#^iJhZ;TULg-2fpZcdsJ?3l)A&GI9U!cG^>+`M?3SnY*%ra@UN zsCg>iGyri?CPTrkXIo|bdA?qozizx2SdID%tG&i?eUe9A#;s`Yw!-5vRkf1*ar=|) zJ}|yv9&n^bWw6G=7DPnzOvpG}(+Y*ifF1HMcB2Mq+wE`gs%5z{D_SPC(S(+~-7Jkl zYdTx9H&n}LW?_#n#;>hAxUd^jV$7wgXyY=jT8#ZTIIjBZqZBrWO%HN${cvgXdU@tx z8|E_emYIzviJ>JGqcKxqqCoLPuq1IJ(;R%^+xwMl^i*5~-^AWV)AuBd>7KNSL5)1H zv{uk?@K8#7i@Rp==s5Q;rN>*Mrqlo_?W{w?vW(AZyT3nlftq!7{1)BFtO$ zzB*c^hA-4Z?4d|mw5SAMwwh8QPiyO!=p5N})VC6i4H7E0j?$*hTNa9-7`=!)#zXp` z8S`pGrf>MRqb!k8!7MWRO6qhPOXpD)35sm%J_HcTjZ}%e@hy|GEMW$=Q_j@sVYzGl z8F^HX=;X;6I!aGpXo)Qh=SjkLKvzxUKEUl2lXnQ#1nLNDkLroGcM=eriKbRyg6@?t zC2^b#(E+rBN15KnID~haJ8ryr9-ceT8`5%2&9XQ3c?zxrSTq~can6VWhVdrbz?roP zr91U8vh%z;{sxJgHtHxoq|GWSZdqf2EpBEAJWmsY5mZqu2!#5n+vq2}F!d4J22)r_ zD+&#Nlcn}`GuvQZa10sy%H34CG}Fi^pZ09qZicKVRhKD|ZL_gKEHH3os|V*%sICS{ z#*#b}P`IrNHr1+V9*k+8D=9{U5JYrsx&9l9%q9tM6VV{XSO7GVAtsX-Uh7TeUPXod zSgPPCyI^dsPTZOa6F=mLlM5+c$F^$Q#pN-JeISxGjS`!!&0Jc$dU>+e3^s9|@FLw7 z9BPFG!Sprau+`O!Gx^5_c~N|6Wz><+IhWQlL{ZB6#VU=5+c7AJGvgq<^MecQGZ9|zyt zZs&D!n>RfqN{>&QtWqX8*?pdsYoqE;QC_t?AkQ1S0X9|!ODNtXG9So-$hs&kL=}iq z?|`c0zvB}PUxu-mX0lHEqYJd?5wn~&JrFlfvLIxsRgsKzO~M(?>r2f%LAKpGn<{}3 zWogYdYZ=sZXBJR!t_GsgA!05lHEJYCE`W+xY4vu@o;Ss7YgEztxIm(zupO&JsYMSB z?mq4QFi%Ts$hJ^8T?ZaEti?MzoVuctXcN%|_($uTn(i^Ui2l3?#ZR(Ovv1TE>81>| zS|iOVovCWn+aNVPZc?bl_i0UE)RX;Iv{?!EX{$V9Z*!~DN)7xdR6i45zQ-)^1}e5q zR~0kkbCALy{w4b*G|M%A-^w3(4#w7?^Yf4=_uumpwGMlj?-Q|)Y6NQ?)OH|do@Vdl z>oH5{MupKSvc?|S_XaR)WgK8HX0=_Z$CY%fr894Ho12+em=6ep$i(Ex2(AhDJ7^6+ z`%A>eHe;OPS7k8ikIYBy9qE$=VjassdbReP>3-Ys#cF`F62>S&UVzm+OA;;cbi9Yo zxa^5dgDAHPRg-G(^|mif5t-3Nq?**^UUl|r8!yYu+0Jxvbh4P@Y?~8Eg99D+X1X8~ zUSi7Ra;2P6h2d${!2|}GI)jX3cY?*xfNc^E^V6<{d^s1tGc9aq)XSVS!IhL z=zICcIa)QQG6bn{DA;PQz+oZ*w8Jd!-sT3x$)?i)1GKpBcSwZ(Qc^UnD z-c;B5>8D_VwQ2e2;Rq62N0RRv7Gupvw2bFlGy)al8)gy>v6K-vKy{{kO`~Z-ulFp~ zx(Ry^P*k!?ZsVqWQbqj_ia{z`<<_&kX|P;d-<-W+d-a@s-Zu5@T-LqJdf%q9um0ey zTp#){JtJM&opq$o&9+X~{G;bW!=v}DW!^V=R%|P^_ezl(qwQ?ER@|Sp?Fupr{+bQ! zX9_RyGPHalG8+#2BzoM|VXJre#wQn=oF;jJ&Kk6WU%9>C3W+g^nR} zt-?U6T`RknEIVi1nNaw`TO>3J6R-4VU+;!hHkDzTOR!2ixBawacD{8H?=M zXvdOq|9G!cE6pvWbuffs_?j+!W2divjJ(6%Hq#_A#(Nw31U6IW;@s^;d-u5{$fn=Q%hG15?k;}^ob&>1%%yTH(~LvnHWtrhK0U;(Ui$%613;+g$Y_o zO-}q!pRfS#khvu6JdH%7+P!j(k8E&3bXu&9^|mpgF{HtDorLXO(q0ngoOVd6@sekW zK8{bEdil$IPr_%AVhg^1hef1LTNlZ;PIjhH0gQ-+mT`!Ua)MX3GYQT;D=6;$NpO4X z%0*~1L1-3jv-V)_)K@y`Mf%c%+x9~8WVym>N>ofb_ET@VB5o(yHV56J>870x_Bop= z0z}ycMQJqps8+$q2>X+w1)O$Z)Hd<&Bj3rcBwL$^A7dcnl=Q4^>o`vJtWfJYGqdyB7FWjp zpH@_pTOWRC7qAZ95X<#%;nX9!nd8eUu4;F-w^egU!{sw3d<6qhj#*<7wR6In-Qym03qJO`&m`}fFly=fiaD;r%(S}U&wBh#&~e_&zHc+G(BmZp8A16Al zCqaa!X9u;l6IZ=Pa=0`is@B3$_*TcYZZ@jejd7}+TO_s*KTLz9K=oGLjKS)ID{~oY zPlHU{j%EEF>wM$(JXtgPaM89@Oz;)*julM~$>~@)I@s)3Q*TewVNR>FH5Z$m?qh{; z@I&Ldp0H}=nvO2USF^B#57*f0HGAf)SsgP^>X`ops8*Ide|rdm{V>#mr&dzsOe!f*m*BE45)U??5xO_M?120!yqf{HM zZ$v-A2-gcTk3a6_m|nwdhg|vaXCA1&lHRXxoKdaW2V+ZQex_9{+{~L6FN%WB2!NLl zp%e#ll2T9O?2MaAKi^T;H#W+>EMJaaWLAUARdCX zR#Ky!+sr7{o~B}hUho*Som=&f>2Vn@$+nZQ+V-#OHAC_qvl!nR$(MlgO$YAmzrczk9qJJ?3XH?jl#CZD< zu;#9B^Vns}v@YD`s}4-#?0Gu1TH09G=Jt*CX-Vj3Y$~|d>d{_JaX*&J|B8ag-X)7W z^gR+COpn{CU8N+jPHfl6_KiG%jI){R-kSpZd6 zhU;v?tE9~eYcW{r6-vPYA{&?Eh}e)}44gxEG}X1PYyK8yUg~3AIcwbP^j=$@a+MFL zIE^jj=A<=O=sB(>ckS3f!b1b|CSXzpWy9tls9dtXZ8U zRy0m?&PAy7YHw=$li1d6vY120$Ye|o_=0#oyfJVHQGL!LjJaiG6XXaVB=qHVf<YExYbbPIxGK&+8S;qIM>P8bft24n~or2%Dul;>}RaVor zrmN*l7EVVWxi`vq1lLA1O6G5kElnkk4jb;R@a-x~vn&fH7{a!oob5m5aD~BYMMs3S z9=Sb08;|rS?Tfgu&efHXQFKPQ1?+%|*x_G&Yz%@wltvmpd0=N^V=SkN_WcMk*D+zN zk#*Y{Vp`-@8ug~W`1)Tg&N!dW8!MK{QF3A&40l}jrhc{x;RCB?z|C8g5#xKMIR6qm zaE#4m8|&P{#_+J&8dg-Gp-|d}nr^Fpr9dWpeiYPcGKttL$exXr5}!iZfnznkPe3S8 zWVn-XM3g{1P$8uio&<5~@madD2~cXq@ySY(DJrU1dNJA(7P7ZdBJmtN27iW-L~aZb zd5dk^SniVy>*UY?eXeRPHdZ$#-C*UB+d~((kS|^4SJ0VLI%o~iVIPH}sjp zv1}(DFIiRfX)RA;I09`#O z!^uUYi=EhNvGIw?nB}lp7zeQ}qqHO=7@1A3`j|e>kcngGEwT5+0{x|ds-{-Z z>ngT4U2m;#qt`65t)gCl^SQ8<$fJ6~=4@#Tw%^~Qmu1X~`B8i#iwssijF=A^U(d?r z3p$oBUbANH>IGDVljC=&I>>vp#CEXT+{-;x{^E6+=Srdgrh>YfM=_it_%NuxUaWVH zJ;H6>Xq_(Agb6m7cR%KvOg=_dJsgc#CzDKD4QzL)TsXwd>n7DfD;1c9tnbK>L*3DC zIxGNfRgwb6u;Ki&rrCly6pJw*&U9N~%hmL#OLU!<1|P%tkZa2=!*L%{Yq}j1*Y{4E z(QT#E9kOni@0mhP7M^lfRqG>}$mw}z|12U5XO^zFNNvellwO)jJNBJ zUWg56DOo;+Bu-rg{;*c7L3CejE1jurtsF+cfo8Hsrg&FqY`51-{iyXCHo8W;LCq;( zT_+tK(WGPJ%nrk4BA25!+a`;f7-ksjR5I3xIDOz*$|;z>w-~38@YuV;dxAsZs@N5n zm(i%Sqy>G5RUJ92<6$u}30?nUUyf(xT)C{Z6=FGQPNp({7^(nKZxl^3X?*6mk4)#u zvC3!6d^~kNwkAJg&RfH2a$eV>>!wFj2Z_PRh8+Xi6q$}x9=RVzQAua(0}0~}PG$Po z9+s%CkL69B7F)wnb73^oaQGW1wE3BHEL_H3m&Qf*=(rj`0o<~ukk_Z0iQzo`>QULl zej0&f8%9q$b!F%3&S{05Ift{dwD8^#LCXKZK=*_=v!YuVx^EdoTZxDSnIqD z?SaL#9h83n!@H8Kk-5y=>#y*2vPGpOPNh?6NwnutFb6$mo1^KVBU>!#E@|lmVI6Nw zUPZHx=`N;J%O1m;W~_))7`4+>R}>!3zz{dg@8;!#QC4ms#O&}osLzRlN9s$Ac1=>4 z26A2}%W+_xXvPetuq26^!X- zsk#x4Hm0;(eu#}zAvha{Z0kksrH4|2P%)Cqy+RyPIR$>8kBM3TP$^})Mf|+X5rsjZ ztH7d*rYSwayo)-URqPS*+pLe!ZAbym5og@ti1NzH-a={M00t2<_GhgRnavaqJdAku zg3^HqPq#Q(JINSRA$^=e=_DP3H>sdOG2R@cS2+7F^97?y2XBsss;FVfA`mxQMQ=qn zGi`Q-Wk%a6c+u_cf>ehuZ7eVVabt+qmWuQ>g0>PDj=!rgrA_mdVU6_8SN#~!?PY|Q zYXtoaylp*p5QH6tM+wWP$o*!g;W2SxMzoR1!IlQ*05Nb;i73WFU%t3zm(LU;Z0&9s zf#$m^0!>RJ7Uv=X8}rBw4;^;uhH2^Zat%1kQX!z*WmL*sTk?l!25M46z1le1elU^7 z0^Lu(%7qJh7TZXA*oYT0VHh~QZk_XReZyABVvNO^40e0A?v|y%y&;2;r2}dxS}t(q zERlPz#(c8c_d zoM2&Yc$&`&BLA(9EN*EHIBmSV>XghmX`jTPN;PeJe{>k4Cb8H%FLREHno*rkS zxpn5}?AeKWSu0DODQbzS9nvu-*+F`6bCH%7=U7BFI)UoU@fG;`c>cC5SAmsCFys@g z=(dCQis=~C%ziW37SwmUxBgXsMJ>gJw~jk7Ynqu}h+)$B?9b!kW_S8tyqzY|mogU1 z*nojocxq?OR&petbomNsjt_9n|L4g5AO80eIEpxX9ZM743U!6@Y-N`SnVz(9qts5c z%%C;u13tJVdU0lDV4pS%I+W25Z_1P^9FVeZrbyku(at#tuv!)EdqNjW1?C0D+Sn)W z{w=IysmZWwm(;`LW~V6(5k`v38B3XkB6bA@g;@*^rh~~SE@@qMZu0v(C4^HXxn0_|0+fjCC z&4Ja@e|*zpTC|ron$m?CFZ|-5A@4yV>oU+1t5k zk)PrhHQ`brDyUOgF??AnX^b(qmCY)dy0r#LB~=EoZ5}l_nPiG{upf=$V80%-+?*;4 zRk75Wm2+%cvS?;90kXN$y~efl?%e4k^;JQngjtC;r9GlyYHLv;&D2&eKnH4VPi6HY zy!}C4Ra7O716N6z2G-wbi&lYXi`uy~u~Pnj2l9mz+lb~^qz(}E`BIFH_3sJC{*5iO zJvxZ6jeay>nThFV3i5fUmVMY7Z8eHZWI8l0yc?Ebl;7~>Y(CP;4h;;iq;hsbY}CcA zBp0XjK6*#9iGoqw_~82?+7Amd}6T?G-alR)23)KRvv=I zC1YeOdbO86Cb5@*Z#f()Xhte_Xjnq^mLV>Eg#&hOnsoy~8XAqFq0JMS(@(W5IHN-{ z>3UUqIj@h_cWRP=swm|K{-=AZsB4E&fr*;F$&9SbOnetL(NM3voo>It$6cS7BzCt1 zcA>;C6@f$R51TmUP~i}l!p-?v`JOhoKF0*%p z;iu_#Kq1=^s^S9r2)*hQf~U1w$Ma)m2Qi!@^i)QsSOs}=nc`CD_Dt%5? znQ>GU3av%+zsF@`uyRCQLGzN8)17Qs!6?_T2FK`)st5WvdNc&-qh@?LXylOg$`Ovw zlvj&!;7#OL_uFAlILkSMkj=Yh7=~M8;^AmQ1g#V4j*R~uJzGXc$sWOI^}R4=02{@s zPF|OAu%Vh_)-nQ8t`i+-rq-bsCHevgAw`FXq4${jf!N@`zCxGD2{F;$wnUFr0xBJCq<{U(lzI!eNN==|N~3J=3=!2KKILY?%^t zsYaK7(zWgXzw*fxvuF>-I0q-1J>+>&M`MpMdBVi*E%ntSV}oAhu+g6NVnuNh7Cbl1 zbA6hxMebr_v`th?|Do7mGstzBmiUjkpkMP7G??Sf#=}*aO z&I6ZF%msOcIBYl>LGebD4KKY?`xCEdagovE#}pkRvu3ixM&2fQbu`;3PEwjW=gXhb zxoGUKASOI1%RHD)wzjTqB%I_ZGnFG9@zk?r!pfojV@TQ#cFc6Ee02)GrIxXIeGDs^ zj$Rv|gm0&V;VkZK+}qE2EENxWgdpT=LaE7KA>DyF+^$ZuagP7O*}ccEVE4$e$(fA& zr3txvW1G=@GHGB-k@YsU2xj~@WHgQS%Lk4pe#GlN@p?>rr2YyL#E zmcA0@n@TfA&7-nG?b0L;J7+~;EaI8s5n97L%`KoAqGcu*_S?-tZj-3YbJ}Jzr7f-1 z%e)^w?nsDFWx#};Gr6-6yD;{rge6wwvMh|d2A3$VEqrd-3S>B*LzSdQIPaRjkKD~B zP5=y(CqDoGHf$ z3A9X&i;>i)%Q(JgmhKxyI7FBj%#^>lMzKhSjFg5Uv}PwsH4s;Z{x9v|Yi88UkP{&w zN|0h|zI6Irf9Z_gQXN4FZxEf!k0T4MC|K+eJ5#}A$KZs>PNlJBOqADr(=mN7YK6X{ zAk902)W-V7mSD5B@{At2HrqpOn-AO4wQtgv_EwjOWVk2mSRA~`*>-O`l+yYuDAT@z z!?wlD_m~|~8PArK=yn&jON_WAYx|vY&zW=ce9^M8Va$IJNUM-#wxeXHwMiE7~6wbI0 zm+5IUJVuxyl+`#R7HDF7DKjGWE$pH)S%O;cx2?%LC_Zfb-EPsbELNQ4>GMXh+7MUG zq%=`i^SGYH(nwUN`07&sbqtTnoTe}&Yk)c-oG}T+eu``2jBT50jeT7>xmyb^d8x4H z*dwq@NymbnU{r!gHXCq+?WlcBUtX(~l3Z=#aiKsJ;k(kUQNfR>*rH|^sMLCs>Y|9- z*2}`0G#02%nazvqM0z0zHX=yWgfJbP{F!q_Kf8L9LQ9xr`oHP1NAkTf+Y~D!Nit&m zgx(a>UwLatIkslmgS@umM2X$FmSG27;wZ?dq#1=Dof}6VPitOWPOD>*Iz73BC9@fb z7-E@&1G5}If^?docfz6ZFQ~ChpJ3k*V6BX9jT0g(kIG=OX{nqAQ7pjDv@0{>Dn*me zk9o;Yyv*Fzke<%Ow4%elAuN1!O;&dxJxM7DZ(FfvnxJwqA<%qAAaOG+p>`iF^oqDc z$XwO(@|((@rGO|J743spF{rZ)u`#L4@2Rh;;TyL9pGrV8>XhTz%|pCtM0i@r8=NK@ zj&LXmLJOx%Sg2A*gwrokXyy5(Cspt8dIr9Y0!?&Dmf|yq&q~kKJVtJ5G~))IqQuMR zyc(%Z37HgzVX#giF~?$M*AxbfCTPsrg`@A@bH->^7HO5n=!AsPkARUb3C_|^T&l&4 zr*c|D$KRl(RmNYEHGVo|=Af1bWS*D`YW)`snBoI{Sx+i9b-Deo%tuC%eosjK7RnbX=zu%N*`UB-ND7oVWRtE2rwxgwTJZ$_gGhyRSoZ?Oe z^So{04Qdu@d+c+lt@wT#Oy|a((Z&11nM*dB0Fp{!@G`|CkQ7P^`vfGcFZT)Hz3Lwu zgvt z@tqoGYodcTwGPZ=)VEriufE9w)|o4bM(SzWplR{}Ur!a+0P-o0n z1YX*cPIZ8@5KE%&=4RyD>8ASW8Y$ zc?q+FK((V!yL<57G>phv5dw5idttd_Y~Da(YL~4%iY{uhqT?ZrlQ;{TX;zZo zH?MIhORHj3Be0!#Vrf}DCLc%U%yKe7jZ=p~p`4@`NjEIo5nph@xODa9u`tOLWqHtR zwCygM81ePytbvZ@{OC3VX4}S!XlZECeXU+|JI+N54O3@Xw^D!=n0IY3(~ytazvP_| z){SIsw>#2#9DV8Tb7TmtVqpOwJLR-94HGnH5*h2^JhLI4cxq;~`gFVR$VN~yLW1u} zyk=0_&^3ZO^$9+#xBb&^f>eFGG+MU`(EmU;&KarWv~s-Hr#-XJv)N=cO9$GKsbWYd zl!_a3Rx0H0+{Z?#Z7A8OZ-qe6Do0cqPE0M^JT@mYy~USOVhIDR#iB=yH&L>W0Aw}} z=X+flV&;TxuWQ>IQ&4RvSc|+)jCPVL0|ouC2a4Q1{$e{j~A3W#87pJNh zHST$;;bqopa(YTO_xb#z17V-h!R&DrUzGJ}xx>R%QE=?|Aa$fPGBlmO%4&?9D*PAR8o;ot+Bs8PF=O&+LfPl>@m$t_r3^cgRc?@fsV4DsR;x+T zAdOrK`f$F(2ud51Q1-51KQcYS*5E-WrOreukWT|PUa7F9lcnlTQ5(8a`~(0A1%Gq> z2UCmP|ASKM#t?C568+Y&Ek8#iFV(gkCS!JtC1IvWH_Chkg?pp)d<~6{uzY4o>x_Z0 zp)pr=3h7NV2@1oGvV?;>Xmz&dZ#!A*p$d5C=yO}@hv@{O6t$s?qKe9xPZZ3UIfGO5 zzqsq2fyBiZ#}fu7L)G>+_*96iiB`V3_atqD9pegjXSz;&TVF4WL)b|NW_jsEN>dwD z2zGbD`UyP}ICXeEQ-JM$oDa)<(SJiLyPW?ghv+e9!`h-jq0VlOn2Kq2uSXS4J&rOQ z8)2*G7_U}u(|M3M=vKCLEfrE0%0FN0M{c*Wpc++M%#b;2yKBbO+lE8Wan_ns#I=z& z16dM864dp;&h{Zw0r|X)+AZ@SR=)VcGV{i)V>Xk#-`_ds-nzHC8%^eY|9k7x zr+@eC=RD^*&-0w;+^V0Pe%zxTpL37#ypMrLPW8Nh?{roDIGOjsPcIX6r2nZz29Rcmp_Wu;*P2e$L@j;85b<1kVHi z3=RQ5%D)eR6Tl0>8KCOT0~wOH1!M@`x4?_QKZ3`CK8<}CyvX5D@B-pDfMvI1tF>TBk)AUXecb_yfBpc9KTkl&Dg7+) z5^w-`J~$0j{{5iZZ*=J^K$UL=wXTOi?en)l$*W^;u;V@r)O^kX)!zl6+PMVO{`(ZD zeUk)LZzXsR_ynkWFN2qYuYt<%1hr1@fSS)qEUwC(398+Xg4+KVgQD9lpz2KpHII8; zdIt1~&jCLQt^>7BFMwKymqFEk71TPt?&9AA)!&<-`hN=){kuT%$zMSA*JqSn?{h${ z<9VR!eZt{DP~|QI)!%gvM}eCEjV^vKIGuPBdooj=yDcR47&9p>U=K;=(y=?U;S;i3HdpLFSa9R58h zdGmcx{PRoj1n}e=t^7R$)H)6ZHQw={=x`gT^|=?+zR!Ug#{y7vTmp)|TU`D=7ylY4 zy1fOeonL~-fPZx9e+IQqeQ&b;mVw%z<3Q2#PEhlj2Ywt}>hhlj)$c)2^!#T~^ZqHQ z_5CF%{yS;B=Y1Kx7d#fc@Mc^7lc41G72t=!Dp2FA1wRJP1vTF_py<34)cgvd%KypX z2{4!F)E89wkAWJ`U{LK{51s_x1ghS2Q0sU%sP?j;=(7y$4{iic0$&F&2EPqz-tV~d zvnSZ{7lM6AzZ_Kg>%o)3n?cS0cJPzn{osY*W1#5sDyV+H0h)aUUP=62@PpvciI)Du zK&|schj)YGlUnd(Fb8U#nn1138c_4w?(%nms{a}&y1W5?7<>y9-@FZq|9%Y)1y7k| z+a2j}5~z0X0!_c5>gT{yz-Cb6cmz~Co4{+p{op0wuR-;D!DL&1D5(0^fNJ+fQ1iYM z)Oc2ceZe)L)?*te`o09JpD%&h7vBPJ1=~Tjcl8uoe;kNv^lkyg&r3k<;~k*NJr8Og zuY%G8uY;$6KLADdcF+gk2DM&&=|uew1yyeZsPT*gMdw=`ei~GJm7w@-9;o$g1}B1# zgKDo66kne-)ym@mp!jMwSPm`&MYjW>_FVzge2<%E?V$5Pn(%IRxDix)Z-ZBWC$ZTs z1#bWcfi5=!0uP?Xy=v>6d>4&j9}dYW`>3Zp&Q{YJc40 z;`3enaZvrf=cgN(K;`B>oI2 zI{z1_bvflOyDu&UMVAD4AJ_nvfp38{<(={wcmbRR!m{38Q1y?y+wwy{a0Kz&KvcH3 z*2UihuOa@?&su(+4vHS11;yu8E}$$>?n==F$8Uk^%dY;o~t9PS2H?iEnuIt*%DKLj<;Jos_23l!Z?tgz!d7gT!} zfST{cp!oM%P<${RRQ+o3J0D>Gfi=XhtFr!xXTd9ppPaPw7zK(?9s=(JzYfj@uc)?s zz6G31{8ym(@4lJ#eDxLZCgR7=vh7R&#}Z!&imu-W$ADhS&TlNJb^0u*{Kvr&;8(#> z;PG_+N$@7{1TX_?-g7|l%|cN7V55tF!{xsPUO@UUT)Z!XSGkXaqU%KPaKJ;LqP4HtHJSLJqW41*T8Y$g|*0FFa@gqv*3l`--D7P z?V!f-k+kjS7EtRy)#0ZdR)CuKeW2#`0C+LD-r<)Wb~!vPWBa=XRJp03=J5b1x;24) z!F6Cia0e)Qe;vFLJh{%6n+}Q|_krTO2f>rUCqUJI7Q7Zb0IHqeIz0D&yY9n5m2U!- z|1c;z>;|;X0YUxHVGzXR3oWe8K@wV>8(Jg9Qh zK=t!!Q1r@z>VGw;`M(INzi)sl-wvwXpMjTy7v=2y?f}b(&jM9$EvWT*!sS2h@Fh^? zzUtz?1~rdk8|?nQ3sn2np!nnoa4^{6($AS=`F}E~au0ylfqOtix%YE$7&w7VHyvCA zs@#vko4_;X+5P(&Q2S>!sCoPocm;UEe9H&J!5PFWLCt4BsCE1jcsBSQP;}`4&jOEq z!1C+4pyJnpXMj^d(X$#<`Ng2*%r;Q%ei>A|Ujt7Ce+Zrqc7a;2cR{V!iJ!CWoB?Vd zUJ0tbPlL*z1FC$Zi?0CH{yI?YZ2~p!J)qY4Yv4ez162Q~ecq0@AE@zP32Hyw0;>Hi zsCo~AYIh^3a!-NhfcwE~!GCh;eIK;r=?|*@P*CH(7W^=n0JXm}p!UmZP~&_7RQq2A zHLf>6wf|#K{r@+p^*ZzKto?TrsBz2%)y@h~^`8f?244i#@6SNZ=kzbw{9&NRH4;=m zw}4~7yFiU&3#fkgf|r1Axb)wG;@>`vb{toO+MhL`=wAn_y$3<{y8_gBUI3N8-^ITU zUO@aiU?1@3pz{9!9s~Aivh_af@Jvwcp9gAO13)u=mwyW=I!txxv%nPbdJqxe{TTcV zIH?(18*Bwt|DqPlN9CZ#b2F%Mq`+Ij`7ZyPpyts5s@~fUf9KMVSzz-|1WzOXRB!}% zA*g;UK(&7u)cAh_YP`P%#RngL$esrWgQ|ZmcnUZP{0MkA_zAE9)Hv3I$AVj2d>dF! zycJaYZ-QE!8DLfg1O} zf&IaE9bUN7p5tx;HJ?UMba)aR3jP>W`+Zm0_C5xx{Xw9{d6mNnpy*TqUI(rR2ZKKV z`+^^O#Fjq?)I7_pP(8wS(fPUxT7o-!EEvo(+y7J`z;<1r8qvRem?9@^85G?}2Ks3p^cs2h_TpxCR>^ zyaH7G8PEs+8C3cI2G#yCk6OF?98mq1fy%FQ_@Kk3p!V@P7vBwPJO{zgfj@HTGuB$V zRe-mXUIU&5eg)LH-vl+z{{Yp`Z$Q!g1M6(LfuPEb0IveaIeZWlJzsSB-vj#)e-l(Y z1yJq&3KYK_|Co(m3~HRiz&pU(K;`cOwVvMv?*iX(@u}-=zjGb7ftQkB05#6j9=CjW z4OmS)3!;L&H$nCP=?w(17F4~jfn&knfExd>jrLq{Cn!E_1U1h+;2mHmcqKUU32TSX z1;tl~K(%uORQXFb+4V?(;?oB}^}oQy*MXwrR#0@>2}(Zi1#bsm0WSypZnk=MG^qJ4 z2G0a{gBssg9lisKZWnK{a(z4~JuweF2iyQ^9bN=Ao-c!H|C^x3^%w9w@bs;AKa_(? zzaBguycPTycsraL0!OCrxt_#6ih`#}<{d1nS>vc1D9q|;XdF}vT1iu8102{X3eqRC?5Wivv zYYOfMRd3i%TW%hhAifW*06+SSjXwyEA^z{6=yuVwc0T0}uLPBTt&5LyIMLyBP;|V@ z#nYhX-vDagHM{i3K$Y7JY923u$AjMlF9N^o(%*5|x7GGL0F?Y13Z4Lt0>ww;U3?;_ z{-%Q}mjJbX_k;I>E5Lr>+o0;7`kXEQ5m4i}$l-OM%H0Ou1kMAegI@+!@9gJo{`n3^ zfa)g!9`gb0J8%y1#x|?>e+!;W{G?rW-sga#8Ls!wgmFA2!4(h}H1?Q^HoBPX>QW2tEb((BI*SwDr&Af0+1b;3QY}7Vvw7`w9P> z@B_jY!bOD7QT7YqLa+f0J}1yt^z$&054rrU;M;_er2ReNUtPKk^&^o=!y?ZoxiX&s zn@K;NvZxC0GsGo#4!ZmYcwWQvL*PGwKLP)da0_7)VKiX_L7%$`t*+kj;15kIGK}Y6 z@H`FN4=#7TJd5dLVMtnc4FdX1FXL*ygi7YX|O zFTy1}=fKwqs0r^s2%jZfNC-ZYdH5P(0im7pL%|<`i@-GmeU2sG4nApOcE5a&=Q9aU z5k5|S6L=>jv#z;pDokodPrNP{0GjBxp= z10zR1<>Jvg@^|X(Uhc z4bQ&>UnN|s1U|31{8M{ditNIL!0E69yBW zBK~8-TEgSRKSKTg4bCNANzmt4gg?0F&w*zVK0vuV>2Iol`~2LMQS{3^zYESKe3-Hs z@H>Q6uFPVdujcs~!hg9mlDxLa^C>((LHGvYb;4K4-v^#Wdv}AsCO(RAEa6V#e*&ee zp5*xzfzTfk8nHT zM)Dp7SAhCtz>~mQ@LS+glkFrBw;^6pU1&Fz)ln6tV`T?c`nIoA%3n)y8`?@VMUM$zUuOp zgF6ZTK=?M{LBiYQ9|wMna2a79L7yLjCxag+v=P2f_&VVXm(Qbj4`C(YBZR&X;Xgrr zrVv(A?nhvY68M}>c#O245l*A*o8TsbKF5fFd~PHByGwh*q`>3g@q|kVIhW_MyytlM zJYfjwzbMH&jr2aWI|Cd~xS0Gc;8cP>A0+-zNu8%j&ysc%I28O}gn#2XMR@Zf=W-|f9eXSw=@|50B-4-*?|a;XWaY>ugv481OsP0brwS(#}_ z=LQZO-jJ#a#}%s;oo=j-stoU6neOio=+EQl%dY4@Fl=H(ri~vnynpbdAw|k)HTn-!>m`Zrw<|N;iHW+pRC;Ew9WntomMQhA z+C=?)Q%mCtr!~^AOw`o)a}!y=Hc^%Ia~XeTGB+k!onW0t=5qC^iiTWrz(9X)DmTkd zr2U5U?9AM>Uzthg;7YIO`uC*CyC-c~cHkg?R%UK;PO^TGpPQBRD-v1LPd1sTubkyq zWs+Gxoyqyhd2oeaovEi(D(h#H^;9YUzt97XC2Q+)^VL?3`p8uKiC}73O}Q$St*c4Q z_fu&z!un*E*=PL$m6_VwL|Hajm#9zVl2rp~Af24+=V-2m1pkhS6a4B_P12tQ{VI~l zv|p2fidB@WPo&vqejR&qZl=DOw+Ckou$%ApV`$X?{7%eNAehCwxKRrpGwxhS8L-Z`jglh z-pCo#C*Lz^#>7!$r$PqXMNMXADt%cng?N#yh?c0RNmi9ES*%=LCQ~C4$yw@*6g9Q zqR3<@k+O`4s-~bgBi;sE#bmP&5>-{HTq=`J)MyDC3`d7UF@;!!0R2dJVOqD+k)@(% zvk9!I3#(M5((K}5xiBLl5*f8g&cafaFs&j82?2ad~ak;DnW++ zCqcu3+A%S)VB|!?uWm?JYTk@5ku#f@H8oq;RkRXA;tru9v687WjBCgYv(8G*oK-_$ zXfSq7W-i+@?I$&mfZt~&<|O?Lyq!hsRKhM0IWj{k)F*wmkDqOD4|5ZY0;0k5@CuF9 z%y)ZA8yb0It7k|2l~oz9tx3gfHdC3B81Sun_23OdCHl=&U#Eme`slo zK!1(S?s7kYxMRi=cN%tt4`QY3lL(p0!ojOM3HKbGbYqtiSGvo#q zGo4FSO7=oet0I(~L9A56*0W5cHlZ>#h6fNlwTMZEMX6#&eX=$)howvet=lCFBzrHV zBTQIYJ|K!;o0OrJ^+qKsXZthiK-h19QF_SsOuA8#&XO;dWWPLJuAt~Lai`*7Q?PjroGXr z+SwfDPWQ?gGpT?0gE-@$+&$PnPSzxA-Fh81T zg{aFiBBwhaFeak~Mn|V%7Yk{ds7aPnKQcr1ST3iw5;gV7M3tl}bWB#6Vv>2udR4Gb zM#N7pYSsbC>_BqiT>bOy|FK5pn1o4_rz65ED^W+)4e*=_Vg6}nTB?|d+w{_M5%nl; z3W!^iK{&87gCsWLfH9K>smUPQNeuO*Nzt_ID<|oks4qzr57~XMeiWN9X5^I6JT0~m zNcT{p7?~zQ1%0>@wzcl*YTL{>UdKr=Yd0e_qU{BFs#>41A_K)(Z^tO%5pAnFnZw|A zMg-dqZ7w|(nNP{yxT}Bm?(PlTSC^crT}yS5HkfZ@V78-3xxcO(qcdOy!%2~5otD*P zYcp(SdS^T89AZWiIW|NpVG=ORTEC_$QFl+!GKq#wqLV|0v2DBe>e72$9jsK0Y}nOF z8PPM+H#@36=TDz7E!s~p(Vv2}L^~j%kdno9vs@Y%HMGD6%ppz;ILpmN%nG`VWwY%r z3<@LfC8YxaVT;%eVi*q7IV|d=l-qi?Xeu`%$k(Q_bx;a!G}=l=&51izL-t{D!}e1m zS_>)JP!Bb8J`y7>ahpjO)7;67GFcS0e``Y$%XD-@&ZAMJWBiz?6timswd;+U##!vP z@*)1%d3Bk3YQdl0m}Eu6O#YkGET}`417FRW1k3-LQwp=lr6sC$VyTow8X$Qza9EgA zQ-fva*d#1phrZ4PMT%1oQVeTalDZD8!4oyTbovYi1x0ODk=Cx|0A%TyWVW(CRcBNW z&j@BqYg4Tlon};(N{1yJOQC5h?HXVlO&vROOxff~6Yebc#sp_Ml${Q>Y^#WtBi9^{ z$FYwRkk&t26#-=OfS%PaZ`!FEt>yaOG z*%wJ28zdt{YrBdCj&Y=g1)H!xG|uCbbp{qI}9i;K*y z$LL{RjK|31Tx}huO+C9W!~Sxc#e#&W*4M=tod)NPgR0oi7Sv8JW_Yo{gv`uLgE3#7 zz8#mC=Z&Kk{e!Fy0y2|q%y`9}my$te>hDzi=YO>O(pOI$=&KgR{uUI<-8^pI$r(Mw~r^tdq*HoKxxv2{3)L9UuuI85}V;(|u*E9KYvWfS>tPA`VtvEzSfB5@oD-=&4Fz(gpsB? z5a=|Ysg_?($L8_r%9;kek=glKjvd9}E2lccKggWYN!;jL7qzEuGOgFZ5PZB_UQ*e{ zINGM7ILw9)Q)aM|R`J*SQ=GT1+#Aoyq^^#$j5{QWicvc$bod35lEJVwq?78g2Vf}l zoiWMEy_*}@b7Us)V_|@4H`X_>8N&3)s`=(P63MYfkn!z@6(Y8;$%q_oJTu6sel-cx ztVXaiNTjMLHhx^7D$TQDxs+X?2?>}&H1Q^2;G2Kw{HiQZ)_ckZFd~mhad33fYnV3y z=O?oZFl^r@`)>JNDc>w*5J6-hqJ!8pb7m_>ji;FC%$blG=0mgx6{zN;{!CPRo(Cs; zqUPX4X@-eXB!SDQKJZEouuN=O(K^l09yQKlLQvwp&6ZP{^Rm_5JiBF_$};+s$B&7p zWQop8)iz*RC(|=?v%;ux6=zcqB)y5aAMkfgNY!$fH$Je5sccr9fofnzVzt`m?7!{IxY=#+F>z>l5=#Iy?f?4sY&UNjN42}_5Q%<|mcXvT1 z;Wp#Cos{t=Wy~fHMOwE6<8=(ZpA?TCcoLz(NQUuIXlK?n)XzjLD#=->Mn;sJZ^#zo z9ok6M^v|BjKo#ia_Sj>#eWV%BJlCO4{e_{XZg>;Zh z4)cv5=lX)Z7_tb1V6YG|4V6P;6{Q*SJ|bFlQV;67M$PuYUaX@Fd~U{_#)S+X0C|RB z8EeBxa925RHNu-{y)P9}pUTcI_ovIZkqJ&)5IijjX`Fjis2K`qPeKqV&tU+yY|mxZ zeoJNt$*+f{#!V+DdQ_qFMM;RdxzsZ8%0vV6sjJW6m8@m6YD-$H*~rIaHXhRs)9zvj z!L<`95%Eq771@kAElftuS>BtBLwbO8V+{hnhDoG3>2RFp1UJx|Y>aX^J;KM6>wUaz zXw*TLERhZZi-sZ3Vbbh(=#)aY$pB-^FaVj2XuqH;;@TXzCf7qFzhXWGc+hr@Znan> z*mqNIn&MAOR409;MADmrb;7g}l{`T;YdZy+k3@H2HCl&Kx|+@nPMFHAk5zI;ll6&9TiAf(6HzfhUaZQiWa4n!0lKB8;oLoL13l z-*WEBJtPbMD^fJa`b=dKRq@H0x#0?7!u8jCQ?%FZ){j1CZKO&9xMF@T3ENiNQsthE zhHwk9&v8rRBxNp~b&4)AZz^iv_?*Q!?k>PMSi-s#LBM2jGcr!xV)3XLc&72r71OOC z=^=-X%;_{nU50Ep$?j~_q(3)VQ^N$DbKIe$vN@2rB&nY1vi7GM$9O2rh#Nz|f;tf+s{5jRGY{J)BT=Je{sb9_B;qu1Bb#)otH&d-sMMFZfPs8jr|Kuu` zB^96KQL>D{5Phg2Ys~mSU_w^~dr_)W?FR=-&l(;^?pp)jn`Uhf3%)zQxY$&CPwdM0 z(^wGNGZm0qy5?kJY28hj`((0MeVM(6!8r(^<&8~HkT1mGF=nEX<+Tay{uF|? zoSM#A9(du+5Vbwb@eqk27Lg-0EGmJ9(6Do~=AX3!ecKoXb-`|=j#?Y$2Pt+dO1ws| z5hBt_c0cDkXqv34_NH+pF#n=!sKhYNZn6bNn@a(c7t&4zd(w#0QrcruFZR@5WhG&q zlTSvb+T%-_7HVWa`iYqd{u`gTQAE;xK?R5ik+Ii|G_Ufe%}&*M({yMFwP^jPXvu4!LBVWC}dkUuo>IoHwnZ!XF^5O1tiu zJy409T*L@6D~TFkK!7;N+44-&n!pH0%b-jv;xq^f#E#z-fg~6gcK1%3kKbgTXTeyn z_K`)J?p|yNA1tw)jtFuo2WLnq@6D zN&JQ6mRd|m$UAB7?pDf6TC)~eiT^_bF)wN8lpOlmWd}8+O??!EyPFUvg>O;Vg^o8? z9=Ky=;u%h|Logy(JB%ePF_}ykRS`E^u{*;_B^`7t4hztiDHJ+)-B z<2jLf@eISq=C}=YQZv&Ty)U9pi~uskaaOIdpUoO^edP?lKr{{Fos-!$NsK`E#slVM zPTmhI((JIq7K2)10=>pjlaQGmklA{@^@&P&&@h7Ub3Z!>jrulgtm9W%xH(Vc30GNmK0 zXhbY-L)fCV?{3>&FOf|o&d4}Z+vQrZX5OgctYEw)thd!kuE^YEg=B@hLQoqGyz^06 zKfg}zyI`=|7lz2oXoH2ERHzTb#9mH|Y z5;No-B=a+5IQ#ZXv827=f#2rIMhk`+X-Ym>(`FAI*%|5C=rep8_R=EMp^|f)=Xm8V zD4`Qfut|cnkQss;>((f4`SP%OXi40~JCwP*!xwwH7YJVY>7FwSXDTK{q=5V-Gt=x} zZUBrG@0`&y?3)ReMLZWXnmFst$jU#?iQlj+eAf`z{x!*J^IA_jF()-s+LS`PH8j6S z71g#$5w1d$ky`JMA7e4<9Wg0c@3zq+r;hQ57VnF0)B6H!h|owh2}5k$Gm+qq4@bL+ zYl8*FwL@T5akJjVEf#Q<5Hi8djoa{HS?k+Vi`tWhza;94suEKK=fv%a`ZNW++j#{h z@SLkcf|Aig1^3-@Nt?q#ZkF-uS}u3OvsTV4J5~g>yz#e7esh6^tM5)ocPENcLQp65 z2IG^ucvdb~m%X^$znzU&QJ9&<2A>u^^$0m+&6jZ;^r=!c*a&5pAH zFQ(#DNE1z$G1}@tAPzKr^2VYmXf05~o=9nvWo~;QzA9F8*H{x1kUH!1GvzD`!zsnB zX)T$GnnZebs0?S?iwh$+Bld^ZB5a{VQP~FKodm|N-&1C!U&Diea*7O1rifiD^ENQ* z#a+3XZqhnaBMOm3=5{d2hAH>QhA$*>oU%rr#3cr5rrg)7ee)8$E^Fi$wXD6t0w5pd z`Y`@nd|BnL*oC(Hz*3KZg!x_l-@=+!U4kR(mm0^Yi}@D*WfhHd(zIiRIRv}Bbm9j z)>@f2BZ^nJ#TS$lC9lDmx90RdkE!G?T#PEk)T^l1>!zWi3v8+iwoNrxx@;Cxk}>>M z^^N;lOFw4pw7<2D+NvwFM#rDWbVl(CVF*9@5CW-9nJ#qeJbDlXS>p#rm zxi=NXQ}zmgGg!G48Lt(%3%YV&63DQ-={3$h?lekU<(@e&ySs$&vX%3<7xzDVh?Iyf zEQv<^3?AfA<>D1|go5tJ%DHX2c{(<^~WCjCs{n z(eU)>MQvd@wTmhk?s6+{q?Fa>I%PS2=Ga8&65_QU%gSMMuO3s-2L&IOog2)K@Yj%I%w4>ZoYlSVxQ1 z$K~-R#5rDFYF@G?>&ZYdwgyl3-CL_?iMp>N*e1QKb)jW34RwiV?@7$$V&8V~ibn}A zXNX>$bHuoV)~0!+D&w~=F*&14-%;|cmczYm9`ss9^c}T1GV=n)ijdF@C)})h*T#5} z^6HA8YV@rm&uIJqL1}%mQBp^#i6oM4KuT4(=+iRW#&M2gBCVhZqJ>J ziGwgl=RQ*=PcIt{CAFkwytBk@&d|X_hLjDyqHO3j{*X@%yYf@!8(I`Bo0^;% z(6Yh$^9K(dHsp#+`6AcgKDxUt<2;kj^3s94dfc!iW~J&g{w;hnEa_kCjtbXPk{5HZ zyvwF16Wk}oc>3Dt9FI1E>-$U`KXGi4Hbcq>_Zh8&N}5q{o*HJ%zsq=iD3u;AV}dJ( z+;uaik1M;nSWctmmZxkiZ|F$%4)d?BNagz6Q8ppLt01$WbeVl8B{uVG$_8JhnGYUf zXMRVSc^$;gI;_d7*LttoA9Ce2gRdFb=e@q>_W!?Am%Z-)f2Zz$_MN&T`&P6+_He%G z*?jZfd<%aI^UcraoA>8i7U!FG^!W9on_AnqZR~jQNzx0O540axtA{Nw zwl8T^YtKJc*tpa5NWUBM&0qZ6`aMb)9nUbe9r>p9YPsX3RqdNLGN#V0J3F?Ku|D6t zY(PM;O@-wL3X2!zo0l@ifrUMr+8e3ZmT!TiBBR&7cDEVp0ufgvUYBoq&P){&x8WJd zw?M?L`Q~l;mezdp>dt4M&o>?JJOmXE$0(a`YSuzQW;OqeX{#~cvPFq4kC@(enRb`Z zO2?Yb?Tc3hL<$zCedChC(*0Dh%GiF1&yBfxb^G!~g|^2{9lD`KR+h0d5#|;lb=XQL zE3x?L!m1UFsB@ob6jDjxy9>T z^lV|-qaBYvTUhzZFkig<{8NS+u<&j}(7k5hP>fnJ62 zmh36BUWX08wsjs}V+gl7LK6rA9T)uV^$XirjrIAahfA6$a;{^y<-te~A1o~0;)N9M zwDFJy3ys^vVKz124BxEHH}A_g?=WOtZ2mtZPHNg&+J=iawZ_}f@F>1LXj1}V345jI z;=w>xmJDp=(Z&)EIILYdwqWtP%?CN+cHhdV3@ULkZ<18Fnmv2UNhs59RMKqFDE99c$K;LJDj)QIarWNfg zH{_exj3u3zz3%q*5Qjq@ULNlG!-kpH1@Ye0WjIF5p#d?CHkI@aG)Ct$FBs}e=ear( zmd&L)A#ATW=TK!t+bfofv1Ye^Lt!3t8fcUt-X=NJw7hH4iq36|%y{G6Ys<0UVrE6> zvnx7xzUIVfVc`nP{DF8C54X1OIS^>Uh*{%QjVaNSA~&32r7_zs#-Jf7t+qO96Y&ky zb336<6_3iGkjdm3FzQhfrUf&Dr1erx&HMcU#Yeu_sh!qzcwi(SM{!IHHg5BvYUfi2 zt+A7D!FXY7Vv?{&v1*W&>LK6!O1@=>d4^qAA33-Yo5Kh@Ct}))+K}vhjqS^x>v&~n z*M@~&AcT4-fy6>Mdqq2_8M`OkZJQ%XYI)~&=^} zX3&Ej)@mgsRESv#lr*eueHEHIuwMn7J+Ss)da;1 z7*9px*)iQ#Qo?eHC2O%>4-6Z&S=hLvV_%yWObZ&tc>^K55-vq^q8>Een4S%*b?$uL zNS@{G>p1zK?+j_(5i4FNIDK%UU@x-!!{eKYGwhypDMqlYJGZwT_@0|8YiRa-xb@i- zd)gmGjyT&mVh%{GxZrE zvg;gWpx7wcZa%Z`q47Ymp*T371jm=CY|z_0(T1V<-`G-2DHY{^?_KxUPay7luNJP< zdlwDQ%|&7&qV^ofH#f=H(%G(8nn*?#C4T#s{p|;^k>79an8q#YMSVe6@*`qy=UWyT z1%=JBx?lvg@hM>a^fa`P$a)pwudCX9rMr#muWz*HHFRc8?`s(Brl?)gR`MNTOAlF^ z;@4i-x2E_l;r1`CK>4ax+h%hR@4Z$JqehCaT2WZCLiOKs_<>yfYwEN=x3yGryw`#c z^Y|(<1L|74tgr*U)BA*Mxy~Kdc8`~9Z0^4Df%d^iVpMxzJ0hL8$e+a#2&a#=Ws0KF z#Z7a;nT_GOu|S z*0RzdDhg~b_GBuvO|=)VDlFx^2G`NF%+`Kh=iW`7dpCF;D-Ri;TU-0XPj|fhcrh-$ zynV+oL@=^*f4&)a$QJ9Kz}k{m%uT3a%6c{rmj)%c6_(M+@mZB_4#5yd>uVG&CTqJXIvn7Z(B;WG5 z(YO2P(9+KyI9$F1IXVJ))wB~=(UF5_pomEjFmIG=HOQDzZ7jt20%-8v3ialo=y-m~ zkwaT;anYstWc|I~%~QtS=sOYo^z&jfc6~D^GF)pIx{HGoYb%TeIjuvzgxIFhQsL1} zo;c1l+hA?cGSV@tRPnu7U8Y^FdxyxCnuyARNPI{nV1nqPiDKHqM-D%M zTqiMp%(rV}J+j?;)KJm7!FgQv(hKNg%Z6?MjZN>>fQAR9NC9gW=Gu33`&RZk*1TG1LB=ib(IS9>aN)CP zfeFC-D?6>n}G(+GH3%( z1}<+6$_Fg2O}ywu!>xvAbwJ){++L76^f4n{M19(8b$dJF#$*|SRBPA7SSj#v1Vzkj zoQ>ISX2v+9JzchSJimr0UmEK!gI#)b-)Wn~`J;2$y2A78WX&kFZ)}Bw;{J`MHf!5L z#_mQMDmJ{PZAN0S``Jp}C>NJ1y;8G^Cag4tC#BvbZLrMQ*cfu`aCp1T z*lXAWa4Y;Pfg1=eE1>BW4Sw{4pz&He+q$dCoJJ(QwI9qk(n|J-*S@i_ux&@zqp#Qj zI%UjYY(}ANf7haw-2s_=XN9A zSzsA|=3X_vnOz|+V3FJ%FD>ZUzs4oGUwMd*+U4*nL)VtYR?-KZL}Ybd>IBw9dc$3j z*F20+mo(sSvH3o>(-vaQnD~xo2Ao-H8e?NIB22s@Lp~UAt3A=_w9$R=-Q?x+qs<@?p>{BFNo#f`(~OAGfQw_3 zYhD%_0VSi4TZQjutfdWfpG`>#d%)Qr+FI_A*{v`4YZvW%cMfBJO02~cp4onOXNnYo z!zOZP><)E?P^ym|#xA#2(9~v2%Y<@!-3xnC;;#0C8*$W_+xXV5CpH!K>8w{+v8QW2 zhNiI#8)<>MEOe7DHDB4&`NDHYUVYW%+N=20!FHF?8Hi>C6^BRj;*z`d+biZPUav*G zw$#$e2!_SHW}9F&y~>NXymg+aF%#n5g*NNhFFd-kYb)3Pt2-N83cKVOF>ejnOA_pz zEk&1H$uDK_zK>i_&M1f(K&|E{GoV|EpTzw-8+Q0pnILHi2RmDHxtI#q+*ItnYXW8b>vWZh-bS-WVl-> z*|F5&uhn-p&+5(>*#1j(p{RE&5Uu;rcl+BnAQ7LN?Bsa@`?^#MRiBiFP zMeV!y9oaAaSE}Yqtu%C~c`bzc!2zIYY2gr6@kJLIiVn#uqp{6o2@`#rfTj zlKVp|$a_hZ8Q`>o7QUparsLFrCA!F|!RssWPRwgN!%Tam$lTEg;vp+~y@3oB1oCJ} z@%@~hUw_a-AfHzh_OTAAN*$|9<4j$axGjb7a@vA5EjlP5rrjO*09Gw;-vQ^t1a|S* zhVi>a2vK4N(pG#7Q6ZM+Me{791Ott0M5G(y zlqCue6cX~XV>)*14qiZr8!oZDz|3w7{FXg>>;sy_bu1#G^o}R!Jbv>Np8&7nbhRAh zM&E9P!2ct;&QTf}k7&n18a0(*EX{D`x+90#X(i1W7e`3ro|dhp(HKtKgTBz}ZG)uKVRQR5|)^LZS_~FB4+E;~L#8kE? zk9DzpBw?v>q3srIP2-}l9%u-J_Xs=OiC|0$y%o|Tt;6X`k{j2CwHP-?&j_*vnxAc7 zfW%@appLEOz;h2Kgyezs)E3=ca&s_tx-lxBjS!rjg5!0Bs6kdh@Q5--YQ+w9c1Ofg ztt#X zp-EX;*(zO6VLaf-T+dcP?6Bb5)FYWj9NS;)fE|LfmthtLwr^SIPDCh2cFs;%YR{Pe zs1VCd5t=$R!7IT!2eeuJ<`p*XE^L-N9|-`jh$T6aUe-Tb`kEBWzZN^nnY970iYwNJ zGISs}a=Y5sF2W^KSPaj(^EDo0-AI-&1{Q7T8(`pj(F5I2hvMltKZSKLNViL}_g<}= z=rlK(*0|y*xTt;aqYjJ*z@|8J)KDX~bG+_JmXhJN?xBRcc{XlBR|9} zz@xXrt+{@0&!<+=u~WQ?3*CQqC5l>A6tnfs=%TiB)FhP(FTU6n=x4+iu1ilFGfHGAy=d{URRjdP9eKWk zb6nt6*7?p0Yz`w5rKLjEw~L~>J6XKYzO9|_L6;Qu(0lxPPEVDC%^mA?Io>eC9Wk#K zEUe$sflJ%E{hW?t=cD`Of?HHsF&(=W6gIqo0JPR%RN?H>8U^k^PET@{JLPGaqZQF@ z1ckdfh?^{-AHp$I3&+=xx$t8${^eMs`6eSu9Xps|1X8odO}Nwc671WawxXR(*orl= zwA?**;^ahY>GyB)Eu2&_Q88mmgj#R=yLcQbZUIDz8%XSU4g)%l4M|_p$u8riEa{p} zYi>;p)r&g7NOddtk>SvRUf`|fz)lgLI{RPec}%jnQV*DS zd%l^8thIL_%)9;Zb$q+2u$)&|OW4GC1`Dq}s&9tCg~4})%%ZIKI$l{BysPsH8a}o# z(1&j;9qwq`<8|z8>)N`>{FIP8mg=X3O3Fj8fLJ{^X;B>A%J;@ycI)AcY}TPOn55Ry zyyewH>wnulzgeA#Mhd^@*uHZ;UndN>IZ#a+kU7bO<%|c(?oWIx?n{!kT2VZiuZNjq zC>#R=1$+}$=&t$2dX3BN?-=D9SGa5Sqf~hB5(u=%jLGzfNNVrt^=<)o$zo=xV3dVe zKyDnn%-p$jdui6ac<;J4-dvSHK%)B9^!>=u21)6&gQG|dT z9Mr8#plJt%B)B;3mgw)Gw#kd$h3XfPqH$}#cKb;rabEnk&BG&7XfzfuZ|iV0iQI^L zLwe6LLbCKC-M7NNcth30k=0x>6`cXG{(6)kv16ru3o9IFBo;;Kchd$&a~-fO(cy3LbmdzY>w)*jbmo^L<+-~=pmhYT|d!g zbp2xpsP=*%p0eAgr<()I>ec{VysdpLdM&)&wiXDs)k0L(k;9m>hFF*-*5+wmq%0WQ zTnvP>CNnl5q*r$rl=}j*X-Q+?9bqGK)TjK5m_m(Bq0L_$Q%}5M91+G9-Llw-KNip} ztNHOPmNWb@E2d`%cr@c(KW-&22R;f}9r~)4T}LAVp)c!b^<=PdEDg*LU|FHn?T4?- z%G$kDYRNh3#fa9OVz8n6Ebqsl$ZDcfmIPasscT^%@51&M^&K^{<6vGSALd8kt?gky zF-1u;yKy8X;=P%6Sjpn_BArKiW+2XdwJ)o%l6q&wu9JHY--w}@Ea^R?n|Tq{MD~S| zo{#aZ_I--N%3Zw7i&YjKha_F^$I=persswNj>XXz{FFj3jY9l&ScaH={K*{Ep`(;J z5$4khh_$(JBb6jiM!4>L%TV%;OT$z8g`rfJ;p^6oOt)D7{_6PbFiZIL46u zjp}#wh7GwFL(5p1y*%J{qkG|{z!TMN1%sCjp;zdfr>~XGNDjkbrM7l>?HWD=ec3Ii zYu6FR_?Ci)Dr&gIajc|>d0yhfu*Tf}@B&P8U%A$NDNWO9U%Q`UA&DKEQK?H~A}!vJ zHqDFd)HQ}UsI}JEDaU?EByt7Y%T1-ZWMqREM-*Jip%a~T>g#9PSUq>mWZge>jrSRe zfY#zYPnOsChI%}kb@QOvEz< KF}$6=_kRHEXd$rx literal 0 HcmV?d00001 diff --git a/locale/nb_NO/LC_MESSAGES/messages.mo b/locale/nb_NO/LC_MESSAGES/messages.mo new file mode 100644 index 0000000000000000000000000000000000000000..d2ebacd44ebc0b5f0b6e0656074ee00bd85bc369 GIT binary patch literal 44164 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 B#2o+t literal 0 HcmV?d00001 diff --git a/locale/oc_FR/LC_MESSAGES/messages.mo b/locale/oc_FR/LC_MESSAGES/messages.mo new file mode 100644 index 0000000000000000000000000000000000000000..7823c66483db16004429234f4f4df24b0ccd8c46 GIT binary patch literal 3562 zcmY+EU2Gjk6~`wfKx&ew(rmGH)c1em`3ETT{_OcTC~^H0O1}OLC9b#q`+Wo< z@BaXb-=BE? z%=5Ppm+B2D@%mpp!ofde}50o<(&6J@q5to5h&}2q4=vq z@qfayA9?0e;vv`H=wM)1qn^P>c{&~^70GM z-$U{L7sz$0%8chHp!|blzCYo45?v&O}10Kab zhSe}Rj}*!4GuScgK}^aM15`DkRz=P?i-|5wVdI#Tk7I|cmQwG7@|_>WPWUl_+$AZ~ z*i%(YsWWgAd)oIu3_pTNJ|DpXOmcY|+bIniXEBW}V5cxCawk5Bos$klzD*r#WAdFJ z!j5B4Vn;A3^8=_4LHVYm(r-nPn9kyBLKo+`YNd(sbqq6`ZFg-+t0-KuQ5NxTOV{_b z8++PgyKNShMJLXRBs8o&Yw}pnEURggg>kB;J4wp6nVL?DZ8dGXU1sK0BPlA_OfQ>m zEbX3g16FZP+a4=iEM7sB$htBwY?rWnqp{N%+i8r`C=>zAn8K);c%$5+-ZW*(Xq?74 ztB_}D|Ac1@CLiP>h1su`O}oNb2F zL9I=d=XO@OZPj+pI@P}3v#wCH%!wm#T}&^R-Hq6(Sq7ylsjnk}=i3S}<28v7K^Sv6;MLG5hWQ}c03l|(TWA{uLrg9pfREACz{7k9IMxAH6{iZ;;V^lxjU~B)EYr!T-T2`$H$K`tu`b9 z2W!q`d1^RqQ&0DAMlK2UdTVj1b>UNbc+D1?boOtDBYHBtYSON8+h?{-$J)_NH-!hT zh1rUOwb*o<`q?l{3X|#Ko+T;u*Nzb?P*ae;hT7St;mWQjsS#mdu5n4O*7>I*UN55op>^m=r6K4BgYq+qaLC_`b|f-{dN?ku z4*R!LqwU~p8QHFICMxM8Khe>P8)a6Mda|q-r1e@B*f8NU=0!d_7#$65cj`&GfHmF9 zb6%Tj_3n+)!`H4|8!aqHv!Q(d5w*g9fHI`XbB612ceinOckJ#iI%YXnrDS-BkZj}% zH8aH)zgp}#1gci3)w1W3ZsMwjKfV_>iLc6)A<-SAL-H0?+Qv^^B3fS4s)={R49}^K zBVGbRZg8t`Zt_LMZ?0`ED8N}AcJObKlZ#cd_+ky+#`ORXx5p~u6`DIruc$yC&^%JorX N0mc`wsvB literal 0 HcmV?d00001 diff --git a/locale/pl_PL/LC_MESSAGES/messages.mo b/locale/pl_PL/LC_MESSAGES/messages.mo new file mode 100644 index 0000000000000000000000000000000000000000..ed781a03e311b522beb3ddb0ebfaa26cb0c3d1d1 GIT binary patch literal 64280 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 literal 0 HcmV?d00001 diff --git a/locale/pt_BR/LC_MESSAGES/messages.mo b/locale/pt_BR/LC_MESSAGES/messages.mo new file mode 100644 index 0000000000000000000000000000000000000000..ab7cad57d102d53da9ad319c80d55a1d6a24d192 GIT binary patch literal 62930 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 literal 0 HcmV?d00001 diff --git a/locale/ru_RU/LC_MESSAGES/messages.mo b/locale/ru_RU/LC_MESSAGES/messages.mo new file mode 100644 index 0000000000000000000000000000000000000000..feeb91e6b0b7cd589c63e313a49134df4a751e84 GIT binary patch literal 56058 zcmeI5cYs_~+5ay^gn%F&rQHMq31l~go)AJvfk2wsget=9?j#wqyR*#9rYLIYBE3mb zItmsvkc1RMP%Ma|?%J@tul2RO))!Q)=6qnc2RWVVako7Hy;&6UEuCu0elZQ75ou+3^@GgD4GJE z2VMl;2QC4J@bF}CDR?-zF5nNrairgPY!vMXjtBL83P`un67Wr6IpDj&gGgTs?gM@d zd?WZ7@KEsikp3OGC+Szf-N7NpMNteM0PY7)1or{Y1a|?u!5zSNf@<$la1ZbrP~|=p z(yPHYkp2QFdS3u{0>1^S-VZ_b_Y3fN@UH>Kkr+dI38?ZP0>^_N0r@}rF@IF=ttUiL z3pfgF17eZfACyT?JN!X?*+yGyTJp&he6T%EGRj64ip_< z0Y&$BK=tz*P~+MDq$rvU?ggsdGr_&U3qa9b1BZeSfU5UdP;`7h;GaS9d(TO(KU2WN zNnZi-DEb7bdcOuofZLty=~1BCnF<~RUI?n+_kyD5Hc;~YZBX<5-=O3~4>gW`K=JVi zQ1dtz)O?==N+0KfYVRGO>QzJf8c_VWH{^d5d^721!t;Jm^YJrK{rnabpSC&0``I0o z-X8>R3l0O-?{HA<90!X3r-9=CEKu#Wfui?3Q1jIes{JnTE#OK}blweWJgY#p`*gss zftsHmgW}7tK-GH{lpO7gQIk9#0_yoV@Ca}kcp%stp5Fkf{d+?G$3T_;A~+QMJ~#|~ z6%-%ism{k%Q1nj$HLlY^^*a|-dv6D&eeFK?Nvb0u`;Bu1~u;6L;k~HO#0)X^yUR{JMb5v=Ka^;_TVd^ z+W9-EdE0inKi@OpL7?PrB)9{3GWZ7YR8Vxz0ySS}f@-%56n)D;$@P_>`1$~-d0qo* zoL>Z0?>|A+`vbTw_)k!BvdyX9&rSh%1J&-{py)m%;0RE5uLV@Q(?kAw;C#{-f`~@6 z7KG)|U%=Vm#M8W;>p=1CW>9i=e@H(8s=d#EqWjz64&bjqSQWhl9t9pZ16v9%0VOw& zf|AECfuifbK+*dusD8FR-N&&zsChjY+z}iFN zKZ5FS7cy1vFi>(b5mfyGsClh|JA+q%JApTa^xXkJ0v<~K6QIh!2&&vK1HKIIO!^<7 z#P_D-wulYQpjHx@G5W@@^1$vR}X^X$D;us2PG#P z!69HjxC{7wP;~qfRKLFkH4lFRMd!F#KK_$H(K9#T1tGsD;7U+(dJ8B$`6Q@$ejb$n z=?68BzXf*zcbM(+yeBCB90p20#(=VqQ$h7V9~6BTf|{2isCF(1>D$3Kk^Tg@E4UF< z{pUf=>vuuT!%Lv_XWKcBdj}i=NVIy)PEhi&98~>VK+*XSD84=hO3$7I)$RsR z^Y;QMdHFSXF!(Acx(}S|?HvtjJhMURRU7yj@KMm@^lffmE&(;JmEdUb22lNO21Unn zp!hlfitgWmnzwD|`M4*6Dt}hM3qkR{1giYffbR!2Z})=gZzCxA`68%(z6z?H?|_n@ zAA_U7KZD}$p>58e6T#u6XMw6;1vP&wz;WP}p!9M*csTfN5K)N!35riMVaBdt7pQvg z0^bZ?4N6|`4EYa%8po$V&Ce!K^}Y>?o}Y#MSHWXQ@4LX|dKS0`=>_0!;Np;84r-j& zhWy(>$?bHQdJYsHe*%iGz0YzS2CCiBpy-|qs-4q7wR%k+y=Rn!HmqF3L&)GiDM}TVgWKiRq7t-yZ=&uF565NmU2f%&7Pl2N2IZ$+b z6;wO_0UiVXE~F1V$H#XpsP-p-YWECK^Zj;EbT0z;18d;h!0SP^`$JIt`7JmRd>NE{ zjXBr-(`-<3cq^!O?*jJ%KL)D)Goa}F3Mf8(Gd%xkNdEi;qDt>Cj@3;3U)=-&D5o<9_kl-)w}3~2&w--v58!n0RZ!!ZdZFv}1>nJ?uLkw}5m4>?4x9k)T)@|Zr-BE9 z?*%okdjftMRQ;cVn!oMZoo_pV+mb#Als*mxC09p-n$PK=%FhQS7w3YShYLW(YZrkr z*aN-=yb)CSkAfQar$Dv)O>l4U7og_5qXsk^eZT`FaX`BlrbS z{QN4YdOrZg@1KFv*H^&p!8b4%Js$!pe|J#*$DsN@3{<(}L6w^r(o;dTKO>~i0afoE zpvrZE>Td}sxxECG{;mf#FJA%G-$1}0fzr3%gG0a_m$*Le363Rw5-2))LCIMksQT{% zCBJuokAfctPXT9lIsG?-JCS|}6ki?#Mc-O*M{rX}e?H&~pvrv%6g}SuMb95W>D9kL zjr-tkr)M;%c8&%$zKP&2;5<6O=st3w$$p0>Uo3PX|YV7lGpE9iZ&l z^Pu$UU*H^Y-?d zLwp2k9Nz}d01sQ?a#8_R@6v#`1bhhGpZqnT=<5d$1^)_)j)UIm_UIH)cA*0lAFl$Z zgR4Qc`!{eOaOZcq-5LgJ{@cK#z+P}B_%JvNdCxE_a*&jw9U#P6O`) znbPQIpycC%D_ovF1*+VES9&{h!4pZ}0Zs(J32GdBT;=1Q45BJg4|oXp6L5cUhpSya zhJlBXo(5`uy1;|McY!hZK~Uv4fd_)$0X5E7K*>Xll8fInLCxd&p!l{7)c8LHil3hV z)&Db~+WRTk0{#nB{g!Lo-=72?KzcGLd3Xo73%C>%eV2#)TSEF{pyqu87=vF1PX~Vk zjs%Z;zqeBWMgIzL7^R@0j4**qf4A=(F2FHRAf*Q{^LGkM^ zpyqSG>s+p9fD=eB0pAWj0`3QHf4#>;2ZBm30EdD-p!&H96n{PmP6WRMz75>*27i7o zxC`m!;56_`P<;9_XnX}VpZ@~I_rq@V@+W{QHywNj_zqCxeHz>qd=XUtKL-y7x4+59 zKMK@1PX;x=t{-$cISf?(c<>BxW=P)&iq9VlxB=8WeGwENeh#XgKY-%@&L8seoCHcQ=78$| zVo>9_8PxdJf%}6$1J&L(_qaS93=ScE5-2&H0gA49p!nDcieEQ?dxH0YD!&@k_%?%` z;CDdvKk;6-a~FV`k8456-)e9S_#!BM+wne^-_hVy(r1H`pL@U~!ByZ1;D3OkW1std zyeESyR|UoYtH2|`C&AsoAA{1Pm%yXIzkrgXQ4e_k=YZnF`$5^YkAMe)&x5VtFT(SE z9`tz~2OdOz8z{Of;4tv6kiRM5_rWRT{|(f5PkPAvX$M8mdjehwYW}VRHNJ~x$A9!I(iivN#*OkK1dT)GXi|6%9L3m@@#`xQ`f^EdDUaHmIHzDuCS_a5+g z@I#>F;alJeaJxrckKPT6FW&&A7rzJh0k{9CucP)4cr2*-cpE7GzYA2q9|twAjiBW8 z>!AAmAt?EN72FS;@iCX9c5oKyrJ(xz9C$eRU2qw=&BuNJZv}WE>92xUf}=m-{9Ox* z-tU6y=TD&IbI-?oy>K`vdX5P=3mi$h2)2MXf+vGdgX6(}f*s%qpLBlT10G8Hli*PB z8v*|WY8?B1%IO#bzLoTRQ1q9yr+X}T2XU%w2v?c?6=0pQ-`p9)G(&j&T`GAO;c96Sd60C*1g0;qlud&2F(3@|2L28Vz* zf$HajpvJit6klHi#iu`j*MdV=yPiG<&LsUZ*al8oQhG3#y#~@IBzKzzJY!6Fv_7FerJ8pLRPn6`Vx+eW3dJA}Bup3DmqE zu$es~uot`&{4#hM*!c{x7x)YC6!6SXyFb1Q+@JI>!SliGKjZzkgW}u0pz3`Tl%DMO ztn1y$;1tsD0!8ODpyqG;Ogoqu?>%FG2C`pwBxUM}pgu zJ{4>QPX`YMSAcH;?*exPSA#o%&w_`5&x6~6zXhj)FM+Cm>=#_mi=gsXf|}pY2YdreVKFHFEdxh@w}Kk~CQ$SG6>vB3dm;TRa97fQ2KNDX_@?vWKv4M;Li%)2^ST&R zd)I~M_kglfp8$6Rp9kLrejVHc{1K>r{{ZdV2;&jrQTO27|*D!&nw{=5Q0p3w+IttjK)$=DX$i|cf*$H^D3K0?0Q+6BCi>v}GI z-WTw#;15WjMV)@`ui^Ty@T`secJ3vM-63x=_s4SofspP2zskUJJ)4gZ{TA3Egr%AMZY5bD5%d*xJE(G&%x2;SGoSm{b#wZ;=aO_e752K=}fx9 zgX5|Du8=1^IgI-YxjxOcJ=edu#&eC}x`^vqHAbDYfCEVD^KtNh{5HCi`@eF%k?Y4? zXOsU=u1C553Rjs+pO1p?13v+N(sEc6fTxE0?Qx*q5MknKEw4j(vrLFc|Jcp`yTiq@;bSa&l`Du9QkkJI*I!wJUA^p zd^>5`Abob^`ZZ;Sfp6rxfJ>iukf)Di^aET!B|Vnw%UmVW(uu!wttPGg+MjT>lim*0 zM>?#JV(dkJ8~u{|4z4>%OEd53d zK7Zuq8m_mHcNlnG@&KG1?mr67RhlyW;P*rRO|*yUiyi`}gtqnQLdv~BdL)E!V@`9|GP8CZFNl+z`qqc{_#lgn(b;!4U2zBn80r zr2iX~A2>GTzYD~5M|(ie)KK?t;n^!8t>oXh|B&i)$?yINBy_OP?fOevpA!P^9`J7R zJ`?T_pbvfi#dUAUdx`rqmC0urd6)ZbG@P>Agz_87+lOcG=em-sg-bEbpSa{BKf(16 zu6w!k*^B3&<$8(hey-&69d0fl{Uq1fTswsa8@NB2zHSBoOx}AyeddP#U*Y~sT&u{x z8Jt4?H^9lHf50_2lqbvf5QV?fA3h5mq9dqtG3ADVGeWyZhi3^a2p*_ z>wY@-cjzYb`EV$wEX7R|L-{{&e|mWKt$+uq5TDO;jUw+tCHTC7YYNvm@=oSDB(!lp z_pK_x=M)Evsps>2|BxQd{aeF*0*`U?cIw^*&IVr%55CI%Uy?%LBV2DGZ-Uw zbqVQnL49uE+Ltm*JDy{HU6-wn^c#r?tI{xW-lpCJ7`?yu)+;ab5po@+Ii zKAk-OWT^9vfXd&EPF^KFTM0fVbIss-hdSr;L5FA^W%|PX2Q&2#2zd$Y#2ar+WZ~qw{rg?cr(}j+#l~nqEC@t$#oU!OS!(p{h{I6AGn{zrO(x1duUJT zp`_ohoABuh_)qeG#QmP3-q*Q5hkD-ycOdUXu3vNigvyZrHeKAmhwBWk+qmxMdYp2L zxK?q$H#m)Q=YYv)4)bLgy zAEbYuN#90#IhQ_d;8|QRaQ{QD-9sCC_BpN#GHK;i^@q=qT&MEvRO+6~^&sgDT(@u? z!}TQBaPn*5_)HtWAa4>^NyxK4F!}t9`#ZP}7tT2Fz~z?rmj9k>ta6Ekhz zLf&u4yN~NXxz}eR*Hp?BxCY3(maB)nnCn(9edaktyM{W4hqPcKc|$@UZzBDlTx-bt zB6vF2JGq|^?wq0Hm!#iD{zpK4w&yyKYdgve1xIo{&Gkph=<_mHjr(a_H*x=EW%4O- z?L(cH$v*)+Bh$yxuu4-|@h{Hyd+b=41)TVS5s?~|rLU(&%YPq{m>KQpAlbBuTE>7%T zVL6@tc;tj5#*I31?3giQMxKBEYjswu^!*?8mGm&Hud7y?S*q3;N(1S=8cwwol7%whV*(NsMu4qhT?_gO1z@nN4ceiu2N^*S?ns-isi1(N@q`~R5_J3C9YQn{zlr4jWN zRXF9b6@qaI#+mNYyg{Yw_0^b-$dx~>(q8Ien(O7#2N@$lUCXY*;ST0d38YBCG~4im z@rd4Hr7HTFWPe0frM!@5HmrK~DdqB#cv?@5qcM}aN(GwG-*`U#*bQ^*cSSv_6)Qc3 zT4`x9o`#)*UpBu8P|ZZ58*$O_I^bnoh!^(tbcl@%w@`~a%f)I>EiNucXhTI8TB+Aa zuV3yov9MWV&KH*!E$-rCq=-#dd0DF}7Da6$O^XW{guyY-?z6x`eVVEkEdscLp z`yjtkl$gfVzHqaw06mZkv$_jCG~2Zz$gUKpO1maV)k*(mRVeqGRIFCZ9VMw-?4~_J z=)^B(OV9)`+Hz^yErcifC#_ajV6hr|KqfcWmZDcoy_(;&PJXV^ z?4B~Tb(%@Y=PgATq_3GKRMtm_l;%ozhgojOHrtWObIn_3HbaeJH~M-?7fZ*J<{-I` znd+&PI$&`wA?79~qmTPaaUq(qSY_~`s?cS#jYM~sdZbCY2bE%Xc`1`tNV$TH85x)9=MZ|JsriaXv*RuT_iS}WC@F0?1`q7YAftd)=Vg~(MC+^ zDi$gd)Q&>O;$k$V3qx)CQts{Rg@Dddp{s0S?Dj}mawLl?h2F)^;n!0s(dZFVXOC=N zcWFs}3SU-*j&6D>E-dw!g*N|CpQIXc98D?1C=3s$dZ);2(!RpmF=rBYlzSGI z7GX1FrK~WrRJEH@%>b>Gzt=r(Gerzk8G0)5)Y75zZIdvB~qF5ct z(_UnPKe7LvW*)&ZX3v?A$?WLBcP#8fs#FMvFa7Z0+K4>Av0TQ_NpKRbb(PUqSUyUY zjH#VEdz6|?9tXWuPZ}#tD{ctJCz#fTObLf;pZZa1=G4h^g9Q*9k`@w!o9eZhnIScb*0DGa(E$2{AC>9J zjHf~9&l_GnKTC`^a8Yk@k<^juVr??s3}J)H{d?V*8AlXMk}}QWP3f^a?&>V`UXTQmqX zmp2F2f<+pcV2W7{S-D_}Y^bWlvv7msC9S&@#*O3C`uXk|u>Q z__E-MVem?>KPHdF`)Sc&oh(1eEY&6@x6(PUgAEJRNYl(0NqE(`0=K$84^<{nF=nT) z!VJ}73`&p8Y`LeN7ZxOxsp4kixAhf?E2s3;A{xaiDy%R)_8^cPQ|iPwMpF^jXlk*& zZxMeN7Ff1`T1y1LP$YMz4jMy=z{Ly2g@tGuvxtEjA@ekHeENiVba)b#rR94Umx-rC z<@!*Q95Y_dLMsD@{E=AYb29?dIaLd)TDMrz5Mxg*Ry!&sVm+J-_r!e8RU1V;+2$*o zY>6O{_>vCiHnGaQX_Ke6%$Ys&oYrV+vO2<@Y1P(|bpU#5>%Zw}VF3N%P_~#k36;Hk#_mswrshj@7naB`D17c%Tj!B5n2MEP&ZzNS`-z; z%j{@ws)Q{ai(4rzdC*YJ$TL|!7IOw&CDDmb>g*h^k`g3LrQ#>0R`_2@jRJ^jUwexT zbrRBMG^1;U^~927%HndFnF}=oYeT9*^rv0i$MA^5rfK;8H}0{WqL5ftA;4iUkZ7j7 z*4;}OQ$gd(B5rwsReSJ6qI;hob=&ZEMT&BRx@}hE| zIji*1avm>_eHSa5PJ{XblLI7^pnggf_9je({8qL;LL{|(sm8M=pA#dzF1X4T#Xw(o zG(D^u)0_Ot@zfbp69P`v4n(OVb{>Wl_BX6}GfUg_+0@x>u}^QBWtPMiyHT1qR~uTf zZMoDl7r=(pxSvXR8Dhgz%h9Q296!4lAQmOm)2>t+?w?ld>Wxk-br$Upwi>Q!e<5|u zReLacLC<0enb6v_okmHX^wh>c6cZRj{LNo!p^OSlPs1E-jVW>oJ?{jn1#HK{Iht}g;UfRba*ic&5qiwEs_L|~C zyG(v`S{XUhpLlAjEtZ_SSZxK_wVb*-omQ^aM$d+?@NRUFpJ+yRVUc*pnm6@OGrCRF zX0TGLbjrAx0SWfbLm}JERZy*mbssXyY>y4mx4%|Iv?7M2`)=9?85Jv>lVT`tm+@iM zyQD`0T~fr-Y^4s~LOicj3M)p%rJA#oMPWgEBbX9ZhN-2cTIww;;S#la(~d}aq4p55 zb(HAn>O=mjE2^w@>vLsK$~gXxTFf?_c99gt&OL1|RTh@{gRqsf&0!H)NMcYGpUvp; z%^4HB8A0;N#VWH~nBDp7F3M+=s;c8pPnp~{%_3M9{@A@Fdmgca8TB+r+9`q3LSk;% zr__kO8MH*TnabW?yhB(vi~HHQI^Fn894g~s5+wo^f=<+x0LVi4*68#;46>#_#&i*x zVX7;A7{oL`BmS|iOEXV0l9E=)td&fJGOOI^479d=d~6oT&6klqB@=>KMw^EcKBhvc zGnzSd#`HM22fGgfZ1*J-X15yEzTRGmb~T;ev0mBK-%Ca_3yDp)J2UAsi`s!ZrK`}h zB$~-e)BX@$c2>Fb?P)Pz-W6^kj-3|K;dE!RjRD&dOv&`@IH5F2O3Xr)7}rF!o21%o zSD>CW_fK-sBIXbCKopTwpju4$Wl8AKP4IEXemA7#mX~Nk>0=gKAB@U9nc{nLN?q;c zvX@xV&bgwE5pITDzmjbcRLx^|^as09ZKX0>Hy(L%ALM5q@)OUQF*To4CAqxR z-NzEJ*t3Yeh9qfw_0`fli_t80tB5~lmby`U+a{e=VyBl85WXa%Qz&e!O1e*Hf*|F9l4hX*Uz!NKo&sTGO)lLm(@&G;%qCoI;@Xv+U1_Brdhi2_CzV}~0+cdsnVde%`hGp0m#}GavWBi2 zEp2*V7l&P46|{__a{Y&_AVgjb)#yfq;(Cv5N!FAuJRs4OwU%UNdr0!;6?wrE$Vl?e zELCa*m1ZQYg~h91P>YWYK}P64UL+n<1BmWf~{lQ2*#(e_pjv&((56=9Ajtj;5bK;l~``L zQmQU#jpu8lubgaaz{MVU3Fu@2L7YJWnFj_AJ6RzU)Ai}ZTt?<#@kS_I>cZ`HF{~ao1lW{f^JHW+$5ymRT1Fw}RAP3c3D_*m z2|HVEO_T7QK`iyq7S5Hh=8E|-IuKCNE;Sp+#$$6$wl6WqLag=`6o7p)9CIp*6dw3G zGMkXxvm=}#glwPNq1A#CE zs9K&B5zUG~-_JU$z%X-rTefCpxoXP*_|29|{k1Nyk?`~^(n6I*zIrh+)T_0^qC$yj z2~WLrh-9@|m2O)g-^pqlnGEHs#hR^DN3l{RvR0`=tW~UD4Aqye5DHG4(OOYE8|cs%CM3DqTg;f*KOTFDNZzDl{Hh(9}QQEh^*Xl}?j>7;0`teYFV z>^<|M2c2@1?JM*Gov7AKVrw+7h#{=%Wv8~38j{k;Y~ zr*}C@*G=H$9hW{c?Jg|bW9+~lG~EFtz~S>F)ic9wk&U1(eh3& zS>KMeisKW99a4#BZX<}L0&~sVB}Ml6+1bh?(;7`IHMBZN^fXjq38aY1nhyJ6k;kj% zSVO?s<{_&?9QIT~YM!6ph(fXrNuoWgfDeK9yuH*4A7Ruv4;~@5TH@Kx+ITz_FOHxA zE3S#?>y>~|MeYTE)m>mgU&86NQd2G+4kWKRjYKJ{?PY1rht%suP?MtaNbC=rZd-(q zmXW(*72_&CXNyC`3seKD7DY}%1v{|uohb}giqoxOtv-0#g*E`E4o=D%dQrYAf;f*Ov7zZ=LQ|d&8PIvk$?pg0=uqBD47RCesTm zv`Q)<7sw6rW1&H3)V8G58?|YJB@=x45f1G)*&82@_PAb<(c}i9R}KIT9Sx;e+T#%l7a395Ql*o=cHdfwwR9tCZ%Gs6Z7GI7 zEO#-0NKX11l?QO%*QaQXn*li8q(E*DmLj|*h9A?+A%w*IaD*#rTfw%`@&LA!^c>_U zEtA~%e1^@_G&9|d3c}NxR;=$+X`3XGEzO&q6{|4$h0ZOM4#z2)JPl9k-9RY{H4k?A zo+DP?_97=)ekw7xRFDf;*i|q-LX!w+u|3e>7n;Nv;blMl(M!EGU+Oe$(yIuOhrd8K zjYXnE=Nd41$THscVYPj+DbtaYkKYCBSV3uw-yWd`!Z)48VeJWcW28ufn@QW+$$rG zt1J~U!B*B9>JFPoa&5`MHC&z>+(LY)6|xA(j=`~*~k-4-6-Kf;L@AgO=eMJ98s2NyXdac}1Ci0ZX1lpz6S-FG@1uUP9 zjzL&i(&SMKKG!uV-9yD$cE}Cz&|de{i-bcs9@HnNZyK7R&1A*j*hA(~8lYe=L=%tf z07f&(4$pak$TD}a_JMms2*%={B?Rijkx5qL8e}(th=QGVTfD%2XE5U(@7;J08Z4n# zIy4zCXz+*JsHx<{2ix$;OT?h%k{8^LO0zv0=%bcx*e8b>Gi!TO!TL@^-E`VsMEyjM z1iu^>^`X@u3r=q>*+TFTCKOp#Y?rkQ@ATD1A7>(MWow$w#zwKyUaE99eZw}tRKo+> z-^Mle{Bp!{nLx9LrDeJvo?q6wZA#i9th1bH&W&h(rND7L3;7q+U->PVH#1t$W0Qig z2XZC%nH>!ZXrFaa5BkjJrY%{+tJMWnR`?Ooo=>*QX6Mv%6qVRrH9Awr*qHEiiC`IHJ?&4EV=Zi#+C!0+ z6n8shbE|I+)C+`4=xcJ^Am~L}*0zSMf@Cg;CtF#m!z5}$sn04@dSv|0LKL(Y(m0dK z@AdrjeDPVbewml=1zOFnn>pE~x01I0t(k`i@*Y>f5&(0kq;1wEKA$FX7_c+d9kP zv_?-cItPxQgR_w}(vDl7ZF3*KxK`_}9^M*@!uCpendZWrRgI(TRo@m@pqmZPNp|Rj zBg>uTwN`62C|4K`&Vd6|MHc3E!XW4ngi($C91fPgEd|G zEf?1CL#>=kK5~{?v2f_UUGH>Kzqy4?BF#nGLW9Tf2J)RGtBSbULyyAjiAiwc0Wzd1 zEb_VPW);ie!q8nRdbIuHhQSVY7Ew3W49U9Gf)4F5s|?$4)pBb*nRyC_DKID0vW2S5 zALd^hmi7vXO0A*TFz-GIg($_V@=UiJeKTq9W!P?|PO^pt3nSD4WxU25#?O41yG6ZiiJCn&-{MLAiZ&fq=w$mny z3eM`(n`)ggdqzVuqV0k}TRbtIGdm>^N!Q+9mU!s~V+{=^i{6?odbN_VGg=Y}9n{L4 zzOC<078(v>+iqB~Gqf09Oq*LGDr~RlI}>SunFKfOsLeu7F`+D0(zcnc)7Mwu-iT@H zr%r48-)*D2^BAXc5Dobk=ymFOH;C=jsfWY>X$CDWY>f(h>BaOTV#9_vnssdrE6i+8 z_Nx|d4kO#$jCAZB6N|a1a1Z%xZ@-{?!Nr5cw{zT!W zgaby>x1{X*Zjnr&EfquH+!_&w)S~ciS(Z6M>vV)c1C#-Xy7WTXwkY%$`H8~ud5M|7 zXk=%yRi2TVD7Yb>K=8erY!1u87NX{$A|y^8S0GI>=QvG<{?KG14}mB~2QhGgb+ z2<3uvQ<;1t^GIUdPOPn|lcR+gBo&<$$sqfz{J|}!gBk;Wpz{!mweyKU36={2}w>Q ze{GQncfP;wK9{7w1&_R~sOnp>RU$~8VesXtjVkwTw#bjPV9dLs`Yc%5b&-qgKvg138Lk;2sp{+aseNfcZ#oncw#?{kIn$5ljF-FD z8EkvQGQ{`pTV_@Hl4Q#%eT%9s^UL`nEuDJTce0M~R$F};hzhcDX01JB?wt88Q{bUy zv4vy0yqg_2X6)FOF-NzIJ0Tu>-1uXTv+tu)uw`CxsX4w}x#L^Lj8nO>#~#VoR>us{ z0g@JC{GKZ3(X_2PxeNcQB}Uv6|#6=Pe+44HyigQG24QjE8lZ#2hbOFa`5K~z}xPh2p6 zdduGOEH-7qbn0xFoCyY5^-hhFVfeMaFx>w@|1vh{f`e^K5!XXPmGHDH}-GV{lLnBYx~#6o}j?W{#E@?T7~Q4 z{wHG6Yx~y?T;BiGz;zU-A+9Uq5ms(p{~De?#r1Um)85QFsy{PuBmG_5zo~!y$f*Aw z^+#%hHkDfjuAsn%{-@%B_i^($l{Zs)RZP#5vS@n&S~M zK>d5o8pC?n$QPJ%-(5DIZKUHH=on&S8_B@+#^Oz)Nn}1@f7faxn;GybGS;idK^YAs zGr5!4eLrMv9Jnm*U*FL9z_m@9Z)g({X{>d5lUh$`oK5oA zK*2LyPeCaIh7u-%`)1@f^wYnpNqaVU&Ft2m<%YfWg1PzrH;Rfa$s7+{p6hU+8Gll` zk#VL<)3(yI1rdEM8a9USp7@?lqXeN9@S{NmvmjJP%&wTmByHNPGMtT?YBY3x)PJ9(f<`3;%G?z7KLEKm zrursI9^ir4V+CT$qUuemCc@f8noQG+EjnZu_1{eDDcKT@YAwwP=|SemvgzuXfon;i z_|Cj_WHIu1;0nya)9A`oR9K(2j?59}=V^2ft8w|jHR2&HJmHoEUZKmWY4z7Li7nei z<7<%pE4XNvVu`szA8BJPti(cyl^WU_SSDkU+LHCMfvr*hL*lHgvY5HLe{)XeG!o@M zuw65U1pw+vh>V;St2s>B0V zL;mJ?;7St=({2@61C>un*%^|l2xcc^hNwu37(kPa)ha%zS@WZswogmAEV{?Y8}ouW zY1%RJn(LZ=Qt^X^Fl_N{6Vrg3xsThrY@}n6XImcxpmF{&`$&UNNKTPuzVhvvTeF^= z2a=(jEN!)|oQO3_+}Os9ag7;A;r*C>M%Q3)81fU1g&FVblXNR+lIK3nY)!M)R7NTT zPZ4+VIyau6TZ!;&sQ?35=X15iHt1+={|0r1tOk$ch3|majI(TH0~(}JTXaAhhz_*M zCQ0i|$}lV#upHeoN;e_O7D5?yt4zr;U^g+h((b4EYuc}d{GllTmPC4=XjIw`^YJ+S z%1Goaw{^nc5i;7tJWzk5T)IToEnPMW!$AhZn$$@p+qG0}(nN?1i4*$QHAH5wr!frd z4YZ@Es!0ojd{`OE`G(FOyq1?tve+}nlRiNaF;o0*7Ej%yTv_nda`G};8^nHzhQvZ~YHCMP z^BMKuOCeKq8n+@n)r3wbQMB{ZYeJ|r8 z_J)1LzT)oEWSrmZG|Ug??UEZ37*>uZ)H#!m$jn4`R| z(}B0;zCdd!DWBpcx>!TIE+~o`OnUBxvvM-b7BQ5h{sFa4G5IAc(vZOz&BMc2dgoof z1zPz^A%4Zs+4Fi8kJFkImJX!zBJX}_y%PNlBCD}LuJ*tUx$+EVmF9;!X7|>>LAh4V zopkj9WY$DV%tMm5#BJ%O&6=2sL3Ccr2s01x3k__N1!L75T#LYIjwFGuxoO{n zGUGu-H7%N~lvkSDhUSto_w?WHl5h4;1ac8?Jz&z*(7#Pt!z^sEW%X`?gxbGmqY`JS zPG+_EM0Ro+O`;B)35CFEwc z%M$uuV^e5e)IGTt0LfO6Z`Y(EfR#)-vJIUEc8<62!oJ>~^)2}p8RN7!63v=z&htSd z8Qk9gP3r5RYcg+jW%CJ3g)fM;!aBkev_onvM~;R`fy7P^C2z?7=*pJ)rV49m$zu|U zikY*)s%2A|(?;*DY30=LBg};0+!b)6;)TgXrgsg9-lwI954XlxK^)QHsBFj zrh2Avf5tRIpGT%4E~+<8|FGLkdA0-W%Aj`EDt?i;tzqQ(D59~fEz&as&Ul(k(PZpt zoKM>_V={gZVGt#@?-PMTGnFJ0@>5z0YfDs%Z*h?Fg#XZ{jVQTFTUlhwSOn+cC>szS zsA;W{Tdc4*Zc8$3u=7LmsKDzMOtut|S+HmgBIPsbi>{3dSMOvyDLjOrhBfnTbzA3) z3<4HPAyP(?9HSiRQy6Cn?s~;o4^bf9kZDLdyRrouv{$)hiRCIOn7- zW}=AZKn1SGQGT4Ku_@aF(hFyZP9qQQ5ukjhsIUoQJ>Mdl80KZ>y8hIShjyO^Nn6se zQKdcWhKxKdt44?%qQQF+9@}Icyv|~{ddFfMSA&Z5m|G^ncbFuTjd_$$ouVW(O<25w zq+oWm5(_M)>zpWP<1n+@4GS9Cl2F45&b*dTWYyFfQo~-#MEwub$4cf5A%zLnL-Hml z*Q(}9mXUy*$`Uw4AuLR=dJ@M()Lpd_YlZ5|_U4R{_^RDP3nyqU?B`{gM0*n{Kwq1)wK_ny`v?1$k{sZloK+%JO zXSsz<=~J!NnU%0aCwi25QZXZ2HPxoZCu(fxJVTa(L?q`43Tg4|otn5a%dIe&=Vm!2 zdYamd-1e^>F>vEZ6FUhL3sPD5^# zVMc`T$QH@sOX9VBJxHD44=@=tE`z8^yH-PhEZgA7NT$qQwsp8$ce)tc>@$YE1v}n< zKOKobOeqAxNvUNzOyAH)@AxaM2?>!A@jj45Z*g! zcPE$JN}Q0DANKEPxG9~~hU&51DUc>)PZiVszylf1`UyXAWP ztVaIfU^ArUUcSt&38l#G+&OJC&dxu^R+$rM2(5zDLY_7Zqz97ltmE-TjtPhCl9F;b zY>&y}$_QpkFg$iw>y*g&CKelJ&aglH*K5GVdKq;Y6QB=eZ@W zCMQ#6wC(t1{iO__ra_|=$=VN8P$`dUy${M_DivHbgkj>03_Pz3iGYm!bx3luN@w>M znYFH@s2ZJT*=<&R)KYYdeyM|mh_fSM<%c-p;+m2F zh?F0RwHJ(;U=^8^iqepsSczL?C8cJz6s8hpMF9`$Z7rB!nBS9iCnPa13k#CH?qQ5% zb81U1MjZB9B!!_}N+UQG8yXXzj!NNWj!J|YI`M*;ewBoezRRsgTG4yBxE=@8j3*&* zK^15RKjoIs;w}lEv=dvWInkO0V=hAie~_Qo^@`V{7sYNHl3VQs=`FeWczIcqHw8Hg z3ALEgj2g#bFNT#!W9xMvVxUBHqx%)#LiK1C!07>mJ9$`-B+apD(hw*MPc)}y&`|TJ zAA?-?O1EJjIJqOCVab;mTN5CLPn)nN9IsJRVzdHr+Rg3oBHDCjH1G!77zaNRhbYd= z*P52!k~_6TOPL>TlT1-rO2i2YDT7*7JSEMNWcn&VowK8TwIYtKG>7nr-ModT4V}G_68)#LLbT;5O>+_68B!c7_T|Z%{k%f9ZLD&>YM=e_7g}ao?lt%#j zb^MCAk>Z~DY3 zJ)>VUD)!_d#+1Bhvu19gZCQ00Nf}wZnUm&*EHGOu&ns=}H4~e%zd4sH?E~;#1mm>r zA6iUA4=_rB!##8oT8D1rs3FYNmzSHA(qK)QnmIHcggx`j2{mRh+m|udXwkfwp-}X! zSxF8@h>N@ou}xKol@uDKvhI!1O1h}v42T%#rqbBU1gjypY}{JxNPXwB?e8_ZPdECe zX-EwILtSpBiod?ni(uW^oDHhWBYXEIo0T`8w)h`Zo`%!?fq~1#3HOp73d#`T0gYH& zqnl{3`w?Dox#7(;!K8*C*fZnXWG5%;Cmx`g+@6rJSx@S0_V7k!)qL3NfVG~Vi;&5i zF+FF>vNl_+8(5;mcq*xF1gL#uzPevjgY%D=b=}5Qmyuk+bL+hYco-l>NNyr$|Bb38p zEp?Hy#?m|s?~v^oQ-&$R7@$I~OB%O%&0Ej|EvB)tHj`3zTW_mrMW-m3bRhgLq0GlE zffC=k(iWH&ra{0lVp&-hd+FV6QZhA0x5YvxWHLSOxCscdn*fw2;>hg>;Ptf=N=W<= z=007|Gv4bG_Znl+(^V5&d@RHm;aZmW>(JmUC7>oXiJ($IL|$nOFsaq)2DBR+_aVy4 z!N~{6o;FHI#7~?xm>12>mW&IWNX^hz%F(L{m1ZJ2d0-Zn-7|)Us2XLBWi$y%04=Yw zQk)3uZa3GsXOkKjAimNPJ{PMl^RG!}#OCqq6=iy*@cgv{U{-}M95%M+XUixp;}T9y zGClP@G7X)+**f4Z#84Uq<$bm^^$PLslozxTX{6Qs&GXPfWfg1XwpkP6+<@k#ZhP^ex1-JsT)L+) zP8IYfU<>7uVAmx{bXqh$Hy+QPA2dqyV}Xm5OSQsQ6izG&Y*k&BFIhcfbgYhv5ydhu zfFvZQhlKax2Q71jpOFSZn8H6XCA+8BPyyC8P-IKBv8qiA1 zB+SmvBiI&B=RCJeOj4Zji)a%#zTLymX6BydxnR$a3I%*1sojE-++*kB;IXuY-;>I9 zlSKR2bF{W;kqnhhTCfpoqi{p>+KO&)*_f|jPXc)iy-7&XybTl4!Ecfhb~Fn&^~{Vl zv7&bA{5%X)C@wUUf*N56DdC9Q+PS$BNy)PonNUFlOjxMEEv z@0ckR-a+J?y@b*_9aPy!r%`#(AX>I#B8QO^D|o5biSBsiXVsoLgETl&Sadylu6Gf# zMC`$zChZYnlY8BYEIjmTg!tN@*X}HoY_2W8~U1`pN{QO^EYv7zB!JY&uYuI4@>S?nXmqLqJej z3p1PH8#_2+w5UpsKdQY|G?DB$W9%iP$ezu;j9M}klH3M+Cq_cprLgcR7|NjdKRMWD z%UjI`k;@={+jQy>9xRsZ*@lY~=Z;t3IZ~9T7XXq)u~F}j8v@UC$)vgpOMI^~e4|Dt z?{4wei4=>{RSNg)BjO_MSF~V*RFlkxpguh^J7@(**-a3~%WSdVOwki^^!*#84xZKA zI^0Vq+62<8%dj1!(})t~AS*^l{*de@J7VeEAq|m+NiZZxh7)VT$nRw2;ylA-LzHQ> z<8{6cOumM-R?n&0Y=s(lVk1jKC`uD$nxx8NDRj+mB-{W`tY=BE!UUP1l^8!o%J4Y5 z-{VUuSTD}QM}JrB{A20SF7-{b`htDEHMjp+~A@-^A;E4UWTDui}@9<)%U52Qe55{@xf zshu|E(@d%}h0M%^RDxKI=@^vvASE`soAZ6I*Zdv`+TVN`GD%BeGtpX!(ksgwXM_BJ zOsqu8bT3g{JqVnWtqz7LwW=W;wmMin`M%7{mv|CZ(CnwrMzDkkCd21HH*x4oSeV&a zYPVG~a%i5JAT8Yn)8{2%zh;%jm{lmS2z3og=CyD+8pQ2H{s z7fOV|D!{FeP5uwYgso_e-xzA%k0)luBt^8iwdOs5(3{QV2Zd?WR#r^KGZ+F1I$8A{ zI+|m}E?Zrg#x+m zPNaKUh2bG?N<_gq##bCuVOLznQZLbPH4J+ge%Ro8DDWXna6TTEXs@kTmJzjyR<(8oqEubpNQ3tyf^|@+d4fZu5HTTT;F2#`Z&2gt`@kF3xt5f@75g?`_YazmF z0al{WvH}z`i+l9|`)m&yi?_bCyaSHP9O_M!AEmh=oODi)P{?R0*iTQKnFg6HOW);S z3av9O{E|C`$l`afFg9$bG%WjNb;4>EFBaCb4?@N>xh;zD#Gc3cy=rYK)}t4NC(VDb zy5U@?HNeW`wxrW2$zco2hL3SK2bq7D*(A&3AvQ|4tS|q2werdtUTrb~W|6{9U(=T5 z2l(oAFwjkl$dS4Rq*f!d{tN3&dG(bji2lM1%(i(0wlFgXI^6NuI!1+Ldvd>Gp!ceh znzV#0hsX0~fO5~$F2c&k44YemT%)wdiuGQbC_CDvKsy(*NeN)odgfT$@%kYI89?#Q z){D3~Ous8&Vnv9GsaC!jHD4&Fg30 z;ttZP^u>z$$?f_`UDJ)7JGCJjn@whp>kpC=Ovin6pWAYaG7pobo?@((*#{X#4V}@H zgiUs3eYWH+;)|>+6JWczNl+8a%WIVli^xH{OXBGR#x&E2gu#fD7@E_RI|nVPG}rlJ z?2F{u)6>+#OIp3Wgi4Pz%075%#D@n~{ zB#;*g_n-`dP4W?C#8X>GtVA2Cyq*#v!fLE(B<8faY5Rk=trRK@BJ07{{*CN?m@3z8 znkzDc*9IJ-t!124g*j!hY=x!B^>ZI8CWUep^0-Fd!IIH>#w*IINwm{Ot(41Fru|k0 zIh??!Qt}4dECn1i62iMbS~kYBFOoA$gU6WtrGvyeX@#VEyZ0 z(>+vGNZ@vL!Bw`2bQ0qsrd^yfbDQ4Y z!n|_i#Fw&xZ^1;$R&8eIM)Q}v10!q?tTjE6HensuM>5vimm(UHG4?18(}}83{!DQf zqwu2C7M2pU)TT5od#%6Bq+qVBEjE)#5`EWs7zS*qS}H%ZTP`m_VCu zz*=JpRKBiuvXi&fescx0Tu5vjcHDl4A2r~GA5y)UT@vm75}GvFH~%&MP)sT(UvFV_ zJWLhLyAgk+;YH@V3B!EPkV1pLnuS(pe+&>aa0hLt--H-sX0@rLtyQSa{gMVeL^1ES zE@X7VH-E93P2w#05*&`yFW9s#wThv*k7i{k6dGRi>y;`L^K47;uut5d zex=07v)RtXYm)4g-q)g~eken4od>-Gw0}_m67^oF8HbF$$xEEq9C+r9kIeU$81y=e znY@dCiuI5#XQ+NR2w9R9HU|5q1?JEKM&oX}PSZ2?oYJ*Ktl2}cW&d0-neH@e%jAX- zyt!x9)wSjVtM93~K;Ib@uTV0CKaR}dlxAr&>>D-n~P`9FwY(kyR%L*u`V zfM4MuYiDx-{;f1MVsT4qubnN)L_$Qmj__G!SR%;w=|P{;H1hMKm$Dxl($#kQ`d1M_ z8VreT>QuU_eP7=Nz;__pH@aUsG`G(n-rA8!8fW^MChDvUY*&V_9@V#PBPBZ_nr8Y~ zC$qS<1z}crRo&eA$xV|g2|+59TeDEKVN>U;X??-N zmNWG)wVOOKUq%YEYg1xp?u;0jD*M8kaeWi&E$*A?p)LCcl1o<5cNl>EWmBzx^LXzX zuQiBL8c@t*#xTbac)@;xC~l|*qw%@?rH<~-hWx79cWm^{%ajm` z>KJh%)r>lLtawmI^hV$;zX>M4AV!ynXxIu84Yo@46}LM>i{`RjXqJ;-CrsqbXqEyP zA*>hq`a(v*v@z)_5PHflMblNPf=U{Z_-kiG8e&nMxx!qFlz?=#sbf@E(0^j2HuH~r zWd0G1`iTcgSNdLns%8)~Cw}fot=w8!q{QSA#M65Am-HSGg*l_W$(l2J)cCf{WD%P?7s2+vcssU@uQ)wcM zPi%(PSBio0`F{L5)wM{)NDV5~N!cl$< zG;ijUsWZEr*+m)PJ z^ai_5TDk?VMw(2RoC7j#vYGydpMn!2S!*{r6ulC*Ym5Z6IfrENL=ycN_o@7EOYN3P z4t(->LmGtLqZ`OhV*%TXR5aoIvz28gKFKOG)e-y4TG_N?Jd!(2LwZOonU!2`rY{W2 zrdk1hvf-dob(8I{0nCh}B=s4nZ=CqThq%xkl+GdHhq%)9aNVJ-%55$12Gkm~2px&B zb4Lnb8pB%SjYP<{n?+q97QxxX$_f>yR~Z209fJTHrN}lYDf5>12`5%LI@RBYCEoZ0tBh2Bv^o|5-$kczSJlW&TMZje|(1KGV!S z$NfEH(2w{@PW0{;(<*1|=gcjV@%$|j!=UvK3AtukRle6v1N0-IN!||P9O?r@Bg2@b z+DNA#eoa>VqA*xWH*-ve%@_~pL2gHqXvbtMhE6CMK*ie1_U&o7L$qnZ4ROWBFhmrk^^zTP~C-X5*uAI)6RTMMRsiybf_5UXya(jM0_ zjm`SyA85*S`Tuy3$v^3o=`pBOUerxe_ff{^^WlxsOHhX_3~ z62e)s$TmFfw-?NKI|ZAd5Sx%oXm`x!6PYwYhZY-!N;PO--3hOcQldlQWDJ1=xe-P= z_1glEU`Mi~3Qgv|JQ!{DNH?>>$vR#+8PVZ~ikKN6nY2uAqWK$X0+g*6i%K*eOuo^% zlTMc6JsqqS?=|7xh;5!qi=EN-V%K{cv|2O4!tGe)Rg zA(JdI4~nJt^^IV7k$mMh+1_AK2#tKY!eblX%3%NGeC-Ib4Nj*6vt35Uv1AFJNLl8! zsFWdDHM${_#@mD?GcG?aiRDy`78ZlQr?DYQ2$sdtV6>3lNUl#i<6RR4QAy50=XD_F zA3ake*esQkBtU|_ZipJDE!h@Mzr(TxqA*!-2E!5bPG(Kyhn-(3f&8St=m^mbE-*2p v4f!)f_;`v)LYwf%#rRh3pGEmF4yC6;Qa6d;ws7U+2^RS=L0B7XoaLa1t0Bv+Io zAu5&MnftNtZR~tVTxxj(DD(LSd<*<0ly?6NWxRif zcftQIx$o^tP4V4=QvVq^3%?Ad-nXE%d-u;3dYFKF`Thu$`X7g=R(-nU7fL=4X{!DN zikz3A%=@3&P2a^;G5z5 zq0IAE$e+5Ce^T!l6#19oB(zZ4eFjRupNFEiFF}#>kD%z~&!E`<-@+T=_o0mc)^`?i z-U6kc!%*^%!CT-e6nUP4Vh5jrG*!O`MZT{!!BX}Af zVlibsJ_|nxUxatSe}Upx@7z<^>3(>C?*QUL>RG7a^Kcw~15UyJgwp;4C`s&N8H%1i z2{AqOX^3cQ3rhblLWWZR2t{9)q4f6?DC3M{By_3nfMSOy;jM5D$~t`tiv9dC#8lKv zQ1tY#Q1tjcDC7PBGG%oQ%946}py+E7O8prqeswpLc1NJ-`8b?`2F}8#;a%|Wpwz#f z!DZezK=FflDC?iX+u$dl*x?J%%LQfqzgP0VO8x}O{Krs=w0|!YdH0rl0E(U-E5A2N zehSLEJqJaem!RnTWhni88;ah32xUHFC{5zXjc^(+L8~hy&p(GE*Iz^a)W7jh#=n+9 z#BSaWWj^_yf}1%kvSE=yaKsljLcVPLS@F4<6K|K1vc>I7oVgB3-4%sZIJ2N!D4Ohe&JwjrdwpY+CH)G$||dVu(8ZBetB79w(jgIYk`6EWQ3e z48{KLC5e9Jd9Z;0FSc>2{1!iu=hsN{{!OVz;Stj9<+rTeW2C!CVkdWyt|i?=s-Bhd zMb`T`N$jk8#HW6p^aLp=Geh_r<-0)a^APDe`QX`465EpJR}1+6DgS?^{Jsy0J?$&M zCreJ1JPO7CPLkHkJc0P$ounC3k7P+=&x<7g%;~0yBE4Z!-7$gHnbT`FTd=DpkFvQe zOTv{rv*QzbBg|Ub#5#}LZX?!B7iad#OkKJC<1uBA$9ZSPCgT&6y5%-(&nA;P%ygLQ zAWY3lWCOkG5}mckNo_*;8|^J?S-oOXFLi27(roF#*;L0a)Aq?Q&2|s4_y1u8q_v%H z)|b8_8N;n=Qz*yqW$aKAN312H z4An&z#Y^uSM~dScHmtXt+A>6}5+!ijlobIxlA3 zWF?GE(%-397Zml1>157lr`TT;3zv^DUK8L1etJSZj(wyeKQ2%dk(Ibr%KWr;vJX4g z)<@zj>8rUYG;|^V^(n^jF9eX{%}Nm~9h)rdS$(8qLiFXWU%YiB!1;)0^lBbAMU70? zWIk|UB0g-C4U5>P$3K`7{v<%Uz&nj!H5{cCuC*c(GsUSQw?RmVwH0YAUuzkJarjl5 zC3zF;W6g#XCJkKN@3`D#Mi8ogR9h z8G7G8^nR+}mG!OLNRZ!It2$f4KE5G#H=5VO7-YlQm0yI(-Lc^p0=K3)xu$T=$&XJHc+k9>%7t35C0J+Z5JMoa3j4$>g2+PPgQjpk= z>#=C28cMGwY!B5=a+TUchPS(Zr6Jw1vS+92uxYmS=`O_3#{DMCUgF}YKT+f@EUCjq zNbmtm9nQl@oL#4}>9W)KeKAX{k4{b3?NcLaYfI?zyW*;g@EBj ziH+5KnDza?;pilpyF=4_#7RTsZklGxs(I!?up{X3%KlD3ua7q?eLtCEq2NVwSuITsfp!mnaoZ9JWzkkha_nK;?X8%Kl28Jq?|W_7pKjRMm( z0e(C7uT~VbD07uceJsZnR1x;9wlxF9*qVZ|d@-Y1z}(?B3XBV<%6XYWUgG zbAu__Sv@l~J>8hPy)ko8Pv1Fv;Lh8or>3T;*m&6XLXlvn-c)01e`ET9o;oml;P%_7 zHZ^wKq*>z>hsl%!r%Pt_f<<``S{YH_b2@IvobB(UTD+EFEOprw&exsVm=mRyag%nx2bHJh-5_TiDHbu+`~zbi23$xsJ3Pz47Rg zR+Ad<(6K2aeyG>2?)AHIo((R%zP2latxcoxKS`}i7fmqO>X|t7y#|DbPThBG{XU(q z+c(lR!tL%EA-f6V2C-4gZWAA3yJ6EFoX=cuQn#_6!C9RePRQ$n^Lo>5t|VqN-2Ow| zb4+hX%E383?%0+i8`I#@Q=v)PrV~!6CD$8l`CHHS7TfdS1*AZ6oHk60g&%DB8fP_c zEf+{*jy;i+Ix<4mbGY{4tXkwyMW{uT?XBWs({??BAabpeRV%!>z7G|XP-ptvC=x|U z%erc;lh6dN{o1|O*P^n&*A!#)YE-tG;}(SKHwPDbZ8LHuiRCzj{AbyeW4F)GeWb#U z8KEP?k)l(dD#DS9Y#uulxOqS#ER zllap1#Wq@%3W!15p^Fy2UtF|gT>mB)vErUJIM+jF+wfPd!-UCRpOEOoWY@Lxv<#ap zLmiU_=bO3QyV}i=Un|OJQe3bkVirelab8&d(p5%1`Aim&?xJY}{9m5ZR2D;3b3j_+5o-RAXDNHi5jZ z>w_Val3;(;%9Sp6lq&bCBE)F9R+X>&6h(~-=I&dTVk9`b&_6WB+3xbUk7rMjW}qY}H}E!H-ja-(5HB%@qToNcu z86OSTCfUE({Nus74!@Kjx$ERU-n0iVbaAqW$dLA1m2(ZYxbU-Gq}-@nkHz3eQ@Y-% zXWChAqLA=-#fr=ISx5q>1fY-~1$G4h}knItm*Znr7~!E%yU{oQ^np9joqgvRle$cW{mwN{2)5dgns~@h7v` z4$kuf^Y#|gze4dV3cUp*rJU!yYOA+HWu}jPzU!g3XZjd>*us>MXz*-cIPiKK5D76& rIWu`_yNT%qMpcId;z#j16lK(=tIn?F0`wKzfNToo_c%X$q+0zSkymiM literal 0 HcmV?d00001 diff --git a/locale/sv_FI/LC_MESSAGES/messages.mo b/locale/sv_FI/LC_MESSAGES/messages.mo new file mode 100644 index 0000000000000000000000000000000000000000..83f78db7390244b9f23dd51ed124f3138735a07c GIT binary patch literal 9337 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 M2=E`0ZD7UYH#xR`2mk;8 literal 0 HcmV?d00001 diff --git a/locale/uk_UA/LC_MESSAGES/messages.mo b/locale/uk_UA/LC_MESSAGES/messages.mo new file mode 100644 index 0000000000000000000000000000000000000000..c461e1598a92fa842de005f4e6b9b974fd75e221 GIT binary patch literal 12624 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 literal 0 HcmV?d00001 diff --git a/locale/zh_TW/LC_MESSAGES/messages.mo b/locale/zh_TW/LC_MESSAGES/messages.mo new file mode 100644 index 0000000000000000000000000000000000000000..7a208753bd7fb9a72dced51bc386325af3c3184c GIT binary patch literal 14356 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 literal 0 HcmV?d00001 diff --git a/queries/SambaUsers.xml b/queries/SambaUsers.xml new file mode 100644 index 0000000..70220f6 --- /dev/null +++ b/queries/SambaUsers.xml @@ -0,0 +1,32 @@ + + + + +Samba User List + + + + +Samba Users +ldap-user.png +sub +1 + + + + Common Name + 1 + 2 + + + User ID + 2 + 1 + + + Samba Home Directory + 3 + 3 + + + diff --git a/queries/UserList.xml b/queries/UserList.xml new file mode 100644 index 0000000..b670fc1 --- /dev/null +++ b/queries/UserList.xml @@ -0,0 +1,42 @@ + + + + +User List + + + + +User List +ldap-user.png +sub +1 + + + + Common Name + 1 + 2 + + + User ID + 2 + 1 + + + Home Directory + 3 + 3 + + + Telephone Number + 4 + 4 + + + Photo + 5 + 5 + + + diff --git a/queries/query.dtd b/queries/query.dtd new file mode 100644 index 0000000..99a8213 --- /dev/null +++ b/queries/query.dtd @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/templates/creation/alias.xml b/templates/creation/alias.xml new file mode 100644 index 0000000..3c803d1 --- /dev/null +++ b/templates/creation/alias.xml @@ -0,0 +1,32 @@ + + + + diff --git a/templates/creation/courierMailAccount.xml b/templates/creation/courierMailAccount.xml new file mode 100644 index 0000000..b7602ab --- /dev/null +++ b/templates/creation/courierMailAccount.xml @@ -0,0 +1,91 @@ + + + + diff --git a/templates/creation/courierMailAlias.xml b/templates/creation/courierMailAlias.xml new file mode 100644 index 0000000..9a53196 --- /dev/null +++ b/templates/creation/courierMailAlias.xml @@ -0,0 +1,42 @@ + + + + diff --git a/templates/creation/dNSDomain.xml b/templates/creation/dNSDomain.xml new file mode 100644 index 0000000..4a98054 --- /dev/null +++ b/templates/creation/dNSDomain.xml @@ -0,0 +1,32 @@ + + + + diff --git a/templates/creation/example.xml b/templates/creation/example.xml new file mode 100644 index 0000000..812b707 --- /dev/null +++ b/templates/creation/example.xml @@ -0,0 +1,38 @@ + + + + diff --git a/templates/creation/inetOrgPerson.xml b/templates/creation/inetOrgPerson.xml new file mode 100644 index 0000000..6469221 --- /dev/null +++ b/templates/creation/inetOrgPerson.xml @@ -0,0 +1,96 @@ + + + + diff --git a/templates/creation/kolabPerson.xml b/templates/creation/kolabPerson.xml new file mode 100644 index 0000000..8be2e6b --- /dev/null +++ b/templates/creation/kolabPerson.xml @@ -0,0 +1,109 @@ + + + + diff --git a/templates/creation/mozillaOrgPerson.xml b/templates/creation/mozillaOrgPerson.xml new file mode 100644 index 0000000..dc39a73 --- /dev/null +++ b/templates/creation/mozillaOrgPerson.xml @@ -0,0 +1,161 @@ + + + + diff --git a/templates/creation/organizationalRole.xml b/templates/creation/organizationalRole.xml new file mode 100644 index 0000000..85e595a --- /dev/null +++ b/templates/creation/organizationalRole.xml @@ -0,0 +1,77 @@ + + + + diff --git a/templates/creation/ou.xml b/templates/creation/ou.xml new file mode 100644 index 0000000..6e0f45a --- /dev/null +++ b/templates/creation/ou.xml @@ -0,0 +1,27 @@ + + + + diff --git a/templates/creation/posixAccount.xml b/templates/creation/posixAccount.xml new file mode 100644 index 0000000..ce4a474 --- /dev/null +++ b/templates/creation/posixAccount.xml @@ -0,0 +1,95 @@ + + + + diff --git a/templates/creation/posixGroup.xml b/templates/creation/posixGroup.xml new file mode 100644 index 0000000..6f8d26b --- /dev/null +++ b/templates/creation/posixGroup.xml @@ -0,0 +1,42 @@ + + + + diff --git a/templates/creation/sambaDomain.xml b/templates/creation/sambaDomain.xml new file mode 100644 index 0000000..563828e --- /dev/null +++ b/templates/creation/sambaDomain.xml @@ -0,0 +1,33 @@ + + + + diff --git a/templates/creation/sambaGroupMapping.xml b/templates/creation/sambaGroupMapping.xml new file mode 100644 index 0000000..c93745c --- /dev/null +++ b/templates/creation/sambaGroupMapping.xml @@ -0,0 +1,70 @@ + + + + diff --git a/templates/creation/sambaMachine.xml b/templates/creation/sambaMachine.xml new file mode 100644 index 0000000..fe5e5d3 --- /dev/null +++ b/templates/creation/sambaMachine.xml @@ -0,0 +1,67 @@ + + + + diff --git a/templates/creation/sambaSamAccount.xml b/templates/creation/sambaSamAccount.xml new file mode 100644 index 0000000..d44fad8 --- /dev/null +++ b/templates/creation/sambaSamAccount.xml @@ -0,0 +1,133 @@ + + + + diff --git a/templates/creation/sendmailMTAAliasObject.xml b/templates/creation/sendmailMTAAliasObject.xml new file mode 100644 index 0000000..86688b6 --- /dev/null +++ b/templates/creation/sendmailMTAAliasObject.xml @@ -0,0 +1,48 @@ + + + + diff --git a/templates/creation/sendmailMTAClass.xml b/templates/creation/sendmailMTAClass.xml new file mode 100644 index 0000000..9bbde8e --- /dev/null +++ b/templates/creation/sendmailMTAClass.xml @@ -0,0 +1,42 @@ + + + + diff --git a/templates/creation/sendmailMTACluster.xml b/templates/creation/sendmailMTACluster.xml new file mode 100644 index 0000000..08bba5c --- /dev/null +++ b/templates/creation/sendmailMTACluster.xml @@ -0,0 +1,26 @@ + + + + diff --git a/templates/creation/sendmailMTAMapObject.xml b/templates/creation/sendmailMTAMapObject.xml new file mode 100644 index 0000000..5f4afd5 --- /dev/null +++ b/templates/creation/sendmailMTAMapObject.xml @@ -0,0 +1,53 @@ + + + + + + diff --git a/templates/creation/sendmailVirtualDomain.xml b/templates/creation/sendmailVirtualDomain.xml new file mode 100644 index 0000000..b2c1047 --- /dev/null +++ b/templates/creation/sendmailVirtualDomain.xml @@ -0,0 +1,42 @@ + + + + diff --git a/templates/creation/sendmailVirtualUser.xml b/templates/creation/sendmailVirtualUser.xml new file mode 100644 index 0000000..c046991 --- /dev/null +++ b/templates/creation/sendmailVirtualUser.xml @@ -0,0 +1,54 @@ + + + + + + diff --git a/templates/creation/simpleSecurityObject.xml b/templates/creation/simpleSecurityObject.xml new file mode 100644 index 0000000..2cb2000 --- /dev/null +++ b/templates/creation/simpleSecurityObject.xml @@ -0,0 +1,37 @@ + + + + diff --git a/templates/modification/inetOrgPerson.xml b/templates/modification/inetOrgPerson.xml new file mode 100644 index 0000000..b7f17e9 --- /dev/null +++ b/templates/modification/inetOrgPerson.xml @@ -0,0 +1,85 @@ + + + + diff --git a/templates/modification/posixGroup.xml b/templates/modification/posixGroup.xml new file mode 100644 index 0000000..f761c3a --- /dev/null +++ b/templates/modification/posixGroup.xml @@ -0,0 +1,43 @@ + + + + diff --git a/templates/template.dtd b/templates/template.dtd new file mode 100644 index 0000000..64ed786 --- /dev/null +++ b/templates/template.dtd @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tools/po/Makefile b/tools/po/Makefile new file mode 100644 index 0000000..0f596d1 --- /dev/null +++ b/tools/po/Makefile @@ -0,0 +1,65 @@ +#!/bin/bash +# +# Makefile Utility to manipulate PO and POT files +# Copyright (c) 2009 Alessandro De Zorzi - +# +# This code is part of phpLDAPadmin +# http://phpldapadmin.wiki.sourceforge.net +# Released under the same licence of phpldapadmin +# +# Current target list: +# +# all display target +# all-mo compile .mo files from .po translation available +# pot create a update main POT file +# all-merge merge last POT with each current translations (re-create POT) +# all-merge-pot merge last POT with each current translations + +LOCALEDIR = ../../locale +TEMPLATEFILES=`find ../../templates -iname *xml -exec echo -m {} \;|grep -v /test_|grep -v /custom_` +EXPORTFILE = $(shell echo $${EXPORTFILE:-/tmp/launchpad-export.tar.gz}) + +all: + @echo Please, specify a target [pot, xml-pot, all-mo, all-merge, all-merge-pot, launchpad-export] + +all-mo: + @for i in `ls -1 $(LOCALEDIR)` ; \ + do \ + if [ -f $(LOCALEDIR)/$$i/LC_MESSAGES/messages.po ]; then \ + echo Processing: $$i ; \ + msgfmt -v -c --statistics $(LOCALEDIR)/$$i/LC_MESSAGES/messages.po -o $(LOCALEDIR)/$$i/LC_MESSAGES/messages.mo; \ + fi \ + done + + +pot: + @po4a-gettextize -o tags=" <description> <display> <hint>" -o tagsonly=1 -f xml $(TEMPLATEFILES) -p messages.pot + @find ../../ -name *.php -exec xgettext --keyword=_ -L PHP -j --omit-header -o messages.pot -s {} \; + @find ../../ -name *.inc -exec xgettext --keyword=_ -L PHP -j --omit-header -o messages.pot -s {} \; + @echo messages.pot created, you might like to change the header with contents of messages.header + +all-merge: pot +all-merge-pot: + @for i in `ls -1 $(LOCALEDIR)` ; \ + do \ + if [ -f $(LOCALEDIR)/$$i/LC_MESSAGES/messages.po ]; then \ + echo Processing: $$i ; \ + msgmerge -v $(LOCALEDIR)/$$i/LC_MESSAGES/messages.po messages.pot -o $$i.po; \ + mv $$i.po $(LOCALEDIR)/$$i/LC_MESSAGES/messages.po; \ + fi \ + done + +launchpad-extract: + @[ ! -r $(EXPORTFILE) ] && echo "No export file [$(EXPORTFILE)] found?" && exit 1 || true + @cd $(LOCALEDIR); tar xzf $(EXPORTFILE) + @rm -f $(LOCALEDIR)/phpldapadmin/phpldapadmin-uk.po + @rm -f $(LOCALEDIR)/phpldapadmin/phpldapadmin.pot + @find $(LOCALEDIR) -name phpldapadmin-\*.po | while read i; do newi=$$(echo $$i| sed -r 's/phpldapadmin-(.*).po/..\/\1\*\/LC_MESSAGES\/messages.po/'); mv $$i $$newi; done + rmdir $(LOCALEDIR)/phpldapadmin + +launchpad-export: launchpad-extract all-mo + +launchpad-import: + @[ -d /tmp/pla ] && rmdir /tmp/pla + @mkdir /tmp/pla + @for i in $(LOCALEDIR)/*/LC_MESSAGES/messages.po; do echo $$i; x=$${i##$(LOCALEDIR)/}; x=$${x/_??\/LC_MESSAGES\/messages/}; [ ! -e /tmp/pla/$$x ] && cp $$i /tmp/pla/$$x || echo "$$x Already exists!"; done diff --git a/tools/po/messages.header b/tools/po/messages.header new file mode 100644 index 0000000..9cfb2fe --- /dev/null +++ b/tools/po/messages.header @@ -0,0 +1,15 @@ +# phpLDAPadmin +# + +msgid "" +msgstr "" +"Project-Id-Version: phpldapadmin\n" +"Report-Msgid-Bugs-To: phpldapadmin-devel@lists.sourceforge.net\n" +"POT-Creation-Date: 2004-01-14 17:45+0200\n" +"PO-Revision-Date: 2004-01-14 17:45+0200\n" +"Last-Translator: Unknown <Unknown>\n" +"Language-Team: phpLDAPadmin <phpldapadmin-devel@lists.sourceforge.net>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + diff --git a/tools/unserialize.php b/tools/unserialize.php new file mode 100644 index 0000000..2a35e60 --- /dev/null +++ b/tools/unserialize.php @@ -0,0 +1,26 @@ +<?php + +require '../lib/common.php'; + +echo '<head><link type="text/css" rel="stylesheet" href="../htdocs/css/style.css" /></head>'; +echo '<body>'."\n"; +$index = get_request('index','REQUEST'); +if (! isset($_SESSION['backtrace'][$index])) + die('No backtrace available...?'); + +$line = $_SESSION['backtrace'][$index]; +echo '<table class="result_table">'; +printf('<tr class="hightlight"><td colspan="2"><b><small>%s</small></b></td><td>%s (%s)</td></tr>', + _('File'),isset($line['file']) ? $line['file'] : $last['file'],isset($line['line']) ? $line['line'] : ''); + +printf('<tr><td> </td><td><b><small>%s</small></b></td>', + _('Function'),$line['function']); + +echo '<td><small><pre>'; +print_r($line['args']); +echo '</pre></small></td>'; + +echo '</tr>'; +echo '</table>'; +echo '</body>'; +?>