activeldap3 1.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +6 -0
- data/CHANGES +691 -0
- data/COPYING +340 -0
- data/LICENSE +58 -0
- data/README +154 -0
- data/Rakefile +121 -0
- data/TODO +32 -0
- data/activeldap3.gemspec +18 -0
- data/benchmark/bench-al.rb +263 -0
- data/benchmark/config.yaml.sample +5 -0
- data/examples/al-admin/README +182 -0
- data/examples/al-admin/Rakefile +16 -0
- data/examples/al-admin/app/controllers/account_controller.rb +60 -0
- data/examples/al-admin/app/controllers/application_controller.rb +46 -0
- data/examples/al-admin/app/controllers/attributes_controller.rb +17 -0
- data/examples/al-admin/app/controllers/directory_controller.rb +49 -0
- data/examples/al-admin/app/controllers/object_classes_controller.rb +17 -0
- data/examples/al-admin/app/controllers/syntaxes_controller.rb +17 -0
- data/examples/al-admin/app/controllers/users_controller.rb +66 -0
- data/examples/al-admin/app/controllers/welcome_controller.rb +12 -0
- data/examples/al-admin/app/helpers/account_helper.rb +2 -0
- data/examples/al-admin/app/helpers/application_helper.rb +46 -0
- data/examples/al-admin/app/helpers/attributes_helper.rb +15 -0
- data/examples/al-admin/app/helpers/directory_helper.rb +7 -0
- data/examples/al-admin/app/helpers/object_classes_helper.rb +10 -0
- data/examples/al-admin/app/helpers/syntaxes_helper.rb +10 -0
- data/examples/al-admin/app/helpers/url_helper.rb +17 -0
- data/examples/al-admin/app/helpers/users_helper.rb +17 -0
- data/examples/al-admin/app/helpers/welcome_helper.rb +2 -0
- data/examples/al-admin/app/models/entry.rb +23 -0
- data/examples/al-admin/app/models/ldap_user.rb +58 -0
- data/examples/al-admin/app/models/user.rb +91 -0
- data/examples/al-admin/app/views/_entry/_attributes_information.html.erb +29 -0
- data/examples/al-admin/app/views/_entry/_entry.html.erb +15 -0
- data/examples/al-admin/app/views/_schema/_aliases.html.erb +7 -0
- data/examples/al-admin/app/views/_switcher/_after.html.erb +2 -0
- data/examples/al-admin/app/views/_switcher/_before.html.erb +5 -0
- data/examples/al-admin/app/views/account/login.html.erb +26 -0
- data/examples/al-admin/app/views/account/sign_up.html.erb +29 -0
- data/examples/al-admin/app/views/attributes/_attributes.html.erb +19 -0
- data/examples/al-admin/app/views/attributes/_detail.html.erb +29 -0
- data/examples/al-admin/app/views/attributes/index.html.erb +3 -0
- data/examples/al-admin/app/views/attributes/show.html.erb +31 -0
- data/examples/al-admin/app/views/directory/_tree.html.erb +10 -0
- data/examples/al-admin/app/views/directory/_tree_view_js.html.erb +25 -0
- data/examples/al-admin/app/views/directory/index.html.erb +13 -0
- data/examples/al-admin/app/views/directory/populate.html.erb +2 -0
- data/examples/al-admin/app/views/layouts/_footer.html.erb +11 -0
- data/examples/al-admin/app/views/layouts/_header_menu.html.erb +10 -0
- data/examples/al-admin/app/views/layouts/_main_menu.html.erb +18 -0
- data/examples/al-admin/app/views/layouts/application.html.erb +57 -0
- data/examples/al-admin/app/views/object_classes/_attributes.html.erb +28 -0
- data/examples/al-admin/app/views/object_classes/_object_classes.html.erb +19 -0
- data/examples/al-admin/app/views/object_classes/index.html.erb +3 -0
- data/examples/al-admin/app/views/object_classes/show.html.erb +39 -0
- data/examples/al-admin/app/views/syntaxes/_detail.html.erb +14 -0
- data/examples/al-admin/app/views/syntaxes/_syntaxes.html.erb +19 -0
- data/examples/al-admin/app/views/syntaxes/index.html.erb +3 -0
- data/examples/al-admin/app/views/syntaxes/show.html.erb +22 -0
- data/examples/al-admin/app/views/users/_attributes_update_form.html.erb +42 -0
- data/examples/al-admin/app/views/users/_form.html.erb +13 -0
- data/examples/al-admin/app/views/users/_object_classes_update_form.html.erb +46 -0
- data/examples/al-admin/app/views/users/_password_change_form.html.erb +20 -0
- data/examples/al-admin/app/views/users/edit.html.erb +15 -0
- data/examples/al-admin/app/views/users/index.html.erb +10 -0
- data/examples/al-admin/app/views/users/show.html.erb +11 -0
- data/examples/al-admin/app/views/welcome/index.html.erb +13 -0
- data/examples/al-admin/config.ru +7 -0
- data/examples/al-admin/config/boot.rb +110 -0
- data/examples/al-admin/config/database.yml.example +19 -0
- data/examples/al-admin/config/environment.rb +73 -0
- data/examples/al-admin/config/environments/development.rb +17 -0
- data/examples/al-admin/config/environments/production.rb +24 -0
- data/examples/al-admin/config/environments/test.rb +22 -0
- data/examples/al-admin/config/initializers/exception_notifier.rb +2 -0
- data/examples/al-admin/config/initializers/fast_gettext.rb +3 -0
- data/examples/al-admin/config/initializers/inflections.rb +10 -0
- data/examples/al-admin/config/initializers/mime_types.rb +5 -0
- data/examples/al-admin/config/initializers/session_store.rb +23 -0
- data/examples/al-admin/config/ldap.yml.example +21 -0
- data/examples/al-admin/config/routes.rb +58 -0
- data/examples/al-admin/db/migrate/001_create_users.rb +16 -0
- data/examples/al-admin/doc/README_FOR_APP +2 -0
- data/examples/al-admin/lib/authenticated_system.rb +124 -0
- data/examples/al-admin/lib/authenticated_test_helper.rb +113 -0
- data/examples/al-admin/lib/ldap_test_helper.rb +38 -0
- data/examples/al-admin/lib/tasks/testing.rake +10 -0
- data/examples/al-admin/po/en/al-admin.po +343 -0
- data/examples/al-admin/po/ja/al-admin.po +343 -0
- data/examples/al-admin/po/nl/al-admin.po +380 -0
- data/examples/al-admin/public/.htaccess +40 -0
- data/examples/al-admin/public/404.html +30 -0
- data/examples/al-admin/public/500.html +30 -0
- data/examples/al-admin/public/dispatch.cgi +10 -0
- data/examples/al-admin/public/dispatch.fcgi +24 -0
- data/examples/al-admin/public/dispatch.rb +10 -0
- data/examples/al-admin/public/favicon.ico +0 -0
- data/examples/al-admin/public/images/active-ldap.svg +6351 -0
- data/examples/al-admin/public/images/al-admin.png +0 -0
- data/examples/al-admin/public/images/al-admin.svg +6371 -0
- data/examples/al-admin/public/images/header-background.png +0 -0
- data/examples/al-admin/public/images/header-background.svg +99 -0
- data/examples/al-admin/public/images/rails.png +0 -0
- data/examples/al-admin/public/images/spinelz/accordion_tab_left_active.gif +0 -0
- data/examples/al-admin/public/images/spinelz/accordion_tab_left_inactive.gif +0 -0
- data/examples/al-admin/public/images/spinelz/accordion_tab_middle_active.gif +0 -0
- data/examples/al-admin/public/images/spinelz/accordion_tab_middle_inactive.gif +0 -0
- data/examples/al-admin/public/images/spinelz/accordion_tab_right_active.gif +0 -0
- data/examples/al-admin/public/images/spinelz/accordion_tab_right_inactive.gif +0 -0
- data/examples/al-admin/public/images/spinelz/balloon_back.gif +0 -0
- data/examples/al-admin/public/images/spinelz/balloon_bottom_left.gif +0 -0
- data/examples/al-admin/public/images/spinelz/balloon_bottom_middle.gif +0 -0
- data/examples/al-admin/public/images/spinelz/balloon_bottom_right.gif +0 -0
- data/examples/al-admin/public/images/spinelz/balloon_left_down_arrow.gif +0 -0
- data/examples/al-admin/public/images/spinelz/balloon_left_up_arrow.gif +0 -0
- data/examples/al-admin/public/images/spinelz/balloon_middle_left.gif +0 -0
- data/examples/al-admin/public/images/spinelz/balloon_middle_right.gif +0 -0
- data/examples/al-admin/public/images/spinelz/balloon_right_down_arrow.gif +0 -0
- data/examples/al-admin/public/images/spinelz/balloon_right_up_arrow.gif +0 -0
- data/examples/al-admin/public/images/spinelz/balloon_top_left.gif +0 -0
- data/examples/al-admin/public/images/spinelz/balloon_top_middle.gif +0 -0
- data/examples/al-admin/public/images/spinelz/balloon_top_right.gif +0 -0
- data/examples/al-admin/public/images/spinelz/barchart_h.gif +0 -0
- data/examples/al-admin/public/images/spinelz/barchart_v.gif +0 -0
- data/examples/al-admin/public/images/spinelz/button.gif +0 -0
- data/examples/al-admin/public/images/spinelz/calendar_default_handler.gif +0 -0
- data/examples/al-admin/public/images/spinelz/calendar_delete.gif +0 -0
- data/examples/al-admin/public/images/spinelz/calendar_next.gif +0 -0
- data/examples/al-admin/public/images/spinelz/calendar_next_second.gif +0 -0
- data/examples/al-admin/public/images/spinelz/calendar_pre.gif +0 -0
- data/examples/al-admin/public/images/spinelz/calendar_pre_second.gif +0 -0
- data/examples/al-admin/public/images/spinelz/calendar_private_icon.gif +0 -0
- data/examples/al-admin/public/images/spinelz/calendar_schedule.gif +0 -0
- data/examples/al-admin/public/images/spinelz/calender_back.gif +0 -0
- data/examples/al-admin/public/images/spinelz/calender_back_second.gif +0 -0
- data/examples/al-admin/public/images/spinelz/datepicker2_back.gif +0 -0
- data/examples/al-admin/public/images/spinelz/datepicker2_back_second.gif +0 -0
- data/examples/al-admin/public/images/spinelz/datepicker2_next.gif +0 -0
- data/examples/al-admin/public/images/spinelz/datepicker2_next_second.gif +0 -0
- data/examples/al-admin/public/images/spinelz/datepicker2_pre.gif +0 -0
- data/examples/al-admin/public/images/spinelz/datepicker2_pre_second.gif +0 -0
- data/examples/al-admin/public/images/spinelz/datepicker_back.gif +0 -0
- data/examples/al-admin/public/images/spinelz/datepicker_back_second.gif +0 -0
- data/examples/al-admin/public/images/spinelz/datepicker_next.gif +0 -0
- data/examples/al-admin/public/images/spinelz/datepicker_next_second.gif +0 -0
- data/examples/al-admin/public/images/spinelz/datepicker_pre.gif +0 -0
- data/examples/al-admin/public/images/spinelz/datepicker_pre_second.gif +0 -0
- data/examples/al-admin/public/images/spinelz/grid_down.gif +0 -0
- data/examples/al-admin/public/images/spinelz/grid_state.gif +0 -0
- data/examples/al-admin/public/images/spinelz/grid_up.gif +0 -0
- data/examples/al-admin/public/images/spinelz/icon_day.gif +0 -0
- data/examples/al-admin/public/images/spinelz/icon_month.gif +0 -0
- data/examples/al-admin/public/images/spinelz/icon_week.gif +0 -0
- data/examples/al-admin/public/images/spinelz/menubar_back.gif +0 -0
- data/examples/al-admin/public/images/spinelz/menubar_subcontents_back.gif +0 -0
- data/examples/al-admin/public/images/spinelz/navPanel_tab_left_active.gif +0 -0
- data/examples/al-admin/public/images/spinelz/navPanel_tab_left_inactive.gif +0 -0
- data/examples/al-admin/public/images/spinelz/navPanel_tab_middle_active.gif +0 -0
- data/examples/al-admin/public/images/spinelz/navPanel_tab_middle_inactive.gif +0 -0
- data/examples/al-admin/public/images/spinelz/navPanel_tab_right_active.gif +0 -0
- data/examples/al-admin/public/images/spinelz/navPanel_tab_right_inactive.gif +0 -0
- data/examples/al-admin/public/images/spinelz/select_date.gif +0 -0
- data/examples/al-admin/public/images/spinelz/selectabletable_selected.gif +0 -0
- data/examples/al-admin/public/images/spinelz/sideBarBox_about.gif +0 -0
- data/examples/al-admin/public/images/spinelz/sideBarBox_menu.gif +0 -0
- data/examples/al-admin/public/images/spinelz/sideBarBox_sample.gif +0 -0
- data/examples/al-admin/public/images/spinelz/sideBarBox_tabBottomActive.gif +0 -0
- data/examples/al-admin/public/images/spinelz/sideBarBox_tabBottomInactive.gif +0 -0
- data/examples/al-admin/public/images/spinelz/sideBarBox_tabMiddleActive.gif +0 -0
- data/examples/al-admin/public/images/spinelz/sideBarBox_tabMiddleActive2.gif +0 -0
- data/examples/al-admin/public/images/spinelz/sideBarBox_tabMiddleInactive.gif +0 -0
- data/examples/al-admin/public/images/spinelz/sideBarBox_tabMiddleInactive2.gif +0 -0
- data/examples/al-admin/public/images/spinelz/sideBarBox_tabTopActive.gif +0 -0
- data/examples/al-admin/public/images/spinelz/sideBarBox_tabTopInactive.gif +0 -0
- data/examples/al-admin/public/images/spinelz/sideBarBox_tabbar.gif +0 -0
- data/examples/al-admin/public/images/spinelz/sortableTable_down.gif +0 -0
- data/examples/al-admin/public/images/spinelz/sortableTable_normal.gif +0 -0
- data/examples/al-admin/public/images/spinelz/sortableTable_up.gif +0 -0
- data/examples/al-admin/public/images/spinelz/switcher_close.gif +0 -0
- data/examples/al-admin/public/images/spinelz/switcher_open.gif +0 -0
- data/examples/al-admin/public/images/spinelz/tabBox_close.gif +0 -0
- data/examples/al-admin/public/images/spinelz/tabBox_tabLeftActive.gif +0 -0
- data/examples/al-admin/public/images/spinelz/tabBox_tabLeftInactive.gif +0 -0
- data/examples/al-admin/public/images/spinelz/tabBox_tabMiddleActive.gif +0 -0
- data/examples/al-admin/public/images/spinelz/tabBox_tabMiddleInactive.gif +0 -0
- data/examples/al-admin/public/images/spinelz/tabBox_tabRightActive.gif +0 -0
- data/examples/al-admin/public/images/spinelz/tabBox_tabRightInactive.gif +0 -0
- data/examples/al-admin/public/images/spinelz/tab_bar.gif +0 -0
- data/examples/al-admin/public/images/spinelz/table_back.gif +0 -0
- data/examples/al-admin/public/images/spinelz/timepicker_clock.gif +0 -0
- data/examples/al-admin/public/images/spinelz/toolbar_close.gif +0 -0
- data/examples/al-admin/public/images/spinelz/toolbar_left.gif +0 -0
- data/examples/al-admin/public/images/spinelz/toolbar_max.gif +0 -0
- data/examples/al-admin/public/images/spinelz/toolbar_middle.gif +0 -0
- data/examples/al-admin/public/images/spinelz/toolbar_min.gif +0 -0
- data/examples/al-admin/public/images/spinelz/toolbar_next.gif +0 -0
- data/examples/al-admin/public/images/spinelz/toolbar_right.gif +0 -0
- data/examples/al-admin/public/images/spinelz/treeview_dir.gif +0 -0
- data/examples/al-admin/public/images/spinelz/treeview_file.gif +0 -0
- data/examples/al-admin/public/images/spinelz/treeview_group.gif +0 -0
- data/examples/al-admin/public/images/spinelz/treeview_group_special.gif +0 -0
- data/examples/al-admin/public/images/spinelz/treeview_state.gif +0 -0
- data/examples/al-admin/public/images/spinelz/treeview_user.gif +0 -0
- data/examples/al-admin/public/images/spinelz/window_bottom_left.gif +0 -0
- data/examples/al-admin/public/images/spinelz/window_bottom_middle.gif +0 -0
- data/examples/al-admin/public/images/spinelz/window_bottom_right.gif +0 -0
- data/examples/al-admin/public/images/spinelz/window_close.gif +0 -0
- data/examples/al-admin/public/images/spinelz/window_max.gif +0 -0
- data/examples/al-admin/public/images/spinelz/window_middle_left.gif +0 -0
- data/examples/al-admin/public/images/spinelz/window_middle_right.gif +0 -0
- data/examples/al-admin/public/images/spinelz/window_min.gif +0 -0
- data/examples/al-admin/public/images/spinelz/window_top_left.gif +0 -0
- data/examples/al-admin/public/images/spinelz/window_top_middle.gif +0 -0
- data/examples/al-admin/public/images/spinelz/window_top_right.gif +0 -0
- data/examples/al-admin/public/javascripts/application.js +2 -0
- data/examples/al-admin/public/javascripts/controls.js +963 -0
- data/examples/al-admin/public/javascripts/dragdrop.js +973 -0
- data/examples/al-admin/public/javascripts/effects.js +1128 -0
- data/examples/al-admin/public/javascripts/prototype.js +4320 -0
- data/examples/al-admin/public/javascripts/spinelz/accordion.js +185 -0
- data/examples/al-admin/public/javascripts/spinelz/ajaxHistory.js +157 -0
- data/examples/al-admin/public/javascripts/spinelz/balloon.js +287 -0
- data/examples/al-admin/public/javascripts/spinelz/barchart.js +524 -0
- data/examples/al-admin/public/javascripts/spinelz/calendar.js +3012 -0
- data/examples/al-admin/public/javascripts/spinelz/colorpicker.js +128 -0
- data/examples/al-admin/public/javascripts/spinelz/datepicker.js +438 -0
- data/examples/al-admin/public/javascripts/spinelz/grid.js +1391 -0
- data/examples/al-admin/public/javascripts/spinelz/grid_resizeEx.js +100 -0
- data/examples/al-admin/public/javascripts/spinelz/grid_sortabletableEx.js +129 -0
- data/examples/al-admin/public/javascripts/spinelz/inplaceEditorEx.js +148 -0
- data/examples/al-admin/public/javascripts/spinelz/menubar.js +232 -0
- data/examples/al-admin/public/javascripts/spinelz/navPanel.js +170 -0
- data/examples/al-admin/public/javascripts/spinelz/selectableTable.js +433 -0
- data/examples/al-admin/public/javascripts/spinelz/sideBarBox.js +282 -0
- data/examples/al-admin/public/javascripts/spinelz/sideBarBox_effects.js +83 -0
- data/examples/al-admin/public/javascripts/spinelz/sortableTable.js +270 -0
- data/examples/al-admin/public/javascripts/spinelz/switcher.js +78 -0
- data/examples/al-admin/public/javascripts/spinelz/tabBox.js +469 -0
- data/examples/al-admin/public/javascripts/spinelz/timepicker.js +384 -0
- data/examples/al-admin/public/javascripts/spinelz/toolbar.js +152 -0
- data/examples/al-admin/public/javascripts/spinelz/treeview.js +703 -0
- data/examples/al-admin/public/javascripts/spinelz/window.js +641 -0
- data/examples/al-admin/public/javascripts/spinelz/window_resizeEx.js +130 -0
- data/examples/al-admin/public/javascripts/spinelz_lib/builder.js +131 -0
- data/examples/al-admin/public/javascripts/spinelz_lib/controls.js +835 -0
- data/examples/al-admin/public/javascripts/spinelz_lib/dragdrop.js +944 -0
- data/examples/al-admin/public/javascripts/spinelz_lib/effects.js +1090 -0
- data/examples/al-admin/public/javascripts/spinelz_lib/json.js +139 -0
- data/examples/al-admin/public/javascripts/spinelz_lib/prototype.js +2515 -0
- data/examples/al-admin/public/javascripts/spinelz_lib/resize.js +215 -0
- data/examples/al-admin/public/javascripts/spinelz_lib/scriptaculous.js +51 -0
- data/examples/al-admin/public/javascripts/spinelz_lib/slider.js +278 -0
- data/examples/al-admin/public/javascripts/spinelz_lib/spinelz_util.js +1266 -0
- data/examples/al-admin/public/javascripts/spinelz_lib/unittest.js +564 -0
- data/examples/al-admin/public/robots.txt +1 -0
- data/examples/al-admin/public/stylesheets/account.css +41 -0
- data/examples/al-admin/public/stylesheets/attributes.css +1 -0
- data/examples/al-admin/public/stylesheets/base.css +104 -0
- data/examples/al-admin/public/stylesheets/detail.css +36 -0
- data/examples/al-admin/public/stylesheets/directory.css +22 -0
- data/examples/al-admin/public/stylesheets/object-classes.css +6 -0
- data/examples/al-admin/public/stylesheets/rails.css +35 -0
- data/examples/al-admin/public/stylesheets/spinelz/accordion.css +59 -0
- data/examples/al-admin/public/stylesheets/spinelz/balloon.css +151 -0
- data/examples/al-admin/public/stylesheets/spinelz/calendar.css +564 -0
- data/examples/al-admin/public/stylesheets/spinelz/datepicker.css +175 -0
- data/examples/al-admin/public/stylesheets/spinelz/grid.css +137 -0
- data/examples/al-admin/public/stylesheets/spinelz/menubar.css +78 -0
- data/examples/al-admin/public/stylesheets/spinelz/modal.css +22 -0
- data/examples/al-admin/public/stylesheets/spinelz/navPanel.css +58 -0
- data/examples/al-admin/public/stylesheets/spinelz/selectableTable.css +28 -0
- data/examples/al-admin/public/stylesheets/spinelz/sideBarBox.css +82 -0
- data/examples/al-admin/public/stylesheets/spinelz/sortableTable.css +51 -0
- data/examples/al-admin/public/stylesheets/spinelz/switcher.css +23 -0
- data/examples/al-admin/public/stylesheets/spinelz/tabBox.css +94 -0
- data/examples/al-admin/public/stylesheets/spinelz/timepicker.css +508 -0
- data/examples/al-admin/public/stylesheets/spinelz/toolbar.css +82 -0
- data/examples/al-admin/public/stylesheets/spinelz/treeview.css +121 -0
- data/examples/al-admin/public/stylesheets/spinelz/window.css +140 -0
- data/examples/al-admin/public/stylesheets/structure.css +81 -0
- data/examples/al-admin/public/stylesheets/syntaxes.css +1 -0
- data/examples/al-admin/public/stylesheets/users.css +13 -0
- data/examples/al-admin/public/stylesheets/welcome.css +0 -0
- data/examples/al-admin/script/about +3 -0
- data/examples/al-admin/script/console +3 -0
- data/examples/al-admin/script/dbconsole +3 -0
- data/examples/al-admin/script/destroy +3 -0
- data/examples/al-admin/script/generate +3 -0
- data/examples/al-admin/script/performance/benchmarker +3 -0
- data/examples/al-admin/script/performance/profiler +3 -0
- data/examples/al-admin/script/performance/request +3 -0
- data/examples/al-admin/script/plugin +3 -0
- data/examples/al-admin/script/process/inspector +3 -0
- data/examples/al-admin/script/process/reaper +3 -0
- data/examples/al-admin/script/process/spawner +3 -0
- data/examples/al-admin/script/runner +3 -0
- data/examples/al-admin/script/server +3 -0
- data/examples/al-admin/test/fixtures/users.yml +9 -0
- data/examples/al-admin/test/functional/account_controller_test.rb +12 -0
- data/examples/al-admin/test/functional/attributes_controller_test.rb +8 -0
- data/examples/al-admin/test/functional/directory_controller_test.rb +8 -0
- data/examples/al-admin/test/functional/object_classes_controller_test.rb +8 -0
- data/examples/al-admin/test/functional/syntaxes_controller_test.rb +8 -0
- data/examples/al-admin/test/functional/users_controller_test.rb +8 -0
- data/examples/al-admin/test/functional/welcome_controller_test.rb +8 -0
- data/examples/al-admin/test/integration/sign_up_test.rb +44 -0
- data/examples/al-admin/test/run-test.sh +3 -0
- data/examples/al-admin/test/test_helper.rb +52 -0
- data/examples/al-admin/test/unit/user_test.rb +12 -0
- data/examples/al-admin/vendor/plugins/exception_notification/README +111 -0
- data/examples/al-admin/vendor/plugins/exception_notification/init.rb +1 -0
- data/examples/al-admin/vendor/plugins/exception_notification/lib/exception_notifiable.rb +99 -0
- data/examples/al-admin/vendor/plugins/exception_notification/lib/exception_notifier.rb +66 -0
- data/examples/al-admin/vendor/plugins/exception_notification/lib/exception_notifier_helper.rb +78 -0
- data/examples/al-admin/vendor/plugins/exception_notification/test/exception_notifier_helper_test.rb +61 -0
- data/examples/al-admin/vendor/plugins/exception_notification/test/test_helper.rb +7 -0
- data/examples/al-admin/vendor/plugins/exception_notification/views/exception_notifier/_backtrace.rhtml +1 -0
- data/examples/al-admin/vendor/plugins/exception_notification/views/exception_notifier/_environment.rhtml +7 -0
- data/examples/al-admin/vendor/plugins/exception_notification/views/exception_notifier/_inspect_model.rhtml +16 -0
- data/examples/al-admin/vendor/plugins/exception_notification/views/exception_notifier/_request.rhtml +4 -0
- data/examples/al-admin/vendor/plugins/exception_notification/views/exception_notifier/_session.rhtml +2 -0
- data/examples/al-admin/vendor/plugins/exception_notification/views/exception_notifier/_title.rhtml +3 -0
- data/examples/al-admin/vendor/plugins/exception_notification/views/exception_notifier/exception_notification.rhtml +6 -0
- data/examples/config.yaml.example +5 -0
- data/examples/example.der +0 -0
- data/examples/example.jpg +0 -0
- data/examples/groupadd +41 -0
- data/examples/groupdel +35 -0
- data/examples/groupls +49 -0
- data/examples/groupmod +42 -0
- data/examples/lpasswd +55 -0
- data/examples/objects/group.rb +13 -0
- data/examples/objects/ou.rb +4 -0
- data/examples/objects/user.rb +20 -0
- data/examples/ouadd +38 -0
- data/examples/useradd +45 -0
- data/examples/useradd-binary +53 -0
- data/examples/userdel +34 -0
- data/examples/userls +50 -0
- data/examples/usermod +42 -0
- data/examples/usermod-binary-add +50 -0
- data/examples/usermod-binary-add-time +54 -0
- data/examples/usermod-binary-del +48 -0
- data/examples/usermod-lang-add +43 -0
- data/lib/active_ldap.rb +105 -0
- data/lib/active_ldap/action_controller/ldap_benchmarking.rb +55 -0
- data/lib/active_ldap/acts/tree.rb +75 -0
- data/lib/active_ldap/adapter/base.rb +705 -0
- data/lib/active_ldap/adapter/jndi.rb +184 -0
- data/lib/active_ldap/adapter/jndi_connection.rb +185 -0
- data/lib/active_ldap/adapter/ldap.rb +290 -0
- data/lib/active_ldap/adapter/ldap_ext.rb +105 -0
- data/lib/active_ldap/adapter/net_ldap.rb +309 -0
- data/lib/active_ldap/adapter/net_ldap_ext.rb +23 -0
- data/lib/active_ldap/association/belongs_to.rb +47 -0
- data/lib/active_ldap/association/belongs_to_many.rb +58 -0
- data/lib/active_ldap/association/children.rb +21 -0
- data/lib/active_ldap/association/collection.rb +105 -0
- data/lib/active_ldap/association/has_many.rb +31 -0
- data/lib/active_ldap/association/has_many_utils.rb +44 -0
- data/lib/active_ldap/association/has_many_wrap.rb +62 -0
- data/lib/active_ldap/association/proxy.rb +107 -0
- data/lib/active_ldap/associations.rb +202 -0
- data/lib/active_ldap/attributes.rb +184 -0
- data/lib/active_ldap/base.rb +1594 -0
- data/lib/active_ldap/callbacks.rb +52 -0
- data/lib/active_ldap/command.rb +49 -0
- data/lib/active_ldap/compatible.rb +44 -0
- data/lib/active_ldap/configuration.rb +147 -0
- data/lib/active_ldap/connection.rb +294 -0
- data/lib/active_ldap/distinguished_name.rb +291 -0
- data/lib/active_ldap/entry_attribute.rb +78 -0
- data/lib/active_ldap/escape.rb +12 -0
- data/lib/active_ldap/get_text.rb +9 -0
- data/lib/active_ldap/get_text/parser.rb +161 -0
- data/lib/active_ldap/get_text_fallback.rb +60 -0
- data/lib/active_ldap/get_text_support.rb +20 -0
- data/lib/active_ldap/helper.rb +92 -0
- data/lib/active_ldap/human_readable.rb +132 -0
- data/lib/active_ldap/ldap_error.rb +74 -0
- data/lib/active_ldap/ldif.rb +930 -0
- data/lib/active_ldap/object_class.rb +95 -0
- data/lib/active_ldap/operations.rb +610 -0
- data/lib/active_ldap/populate.rb +53 -0
- data/lib/active_ldap/railtie.rb +31 -0
- data/lib/active_ldap/schema.rb +699 -0
- data/lib/active_ldap/schema/syntaxes.rb +417 -0
- data/lib/active_ldap/timeout.rb +75 -0
- data/lib/active_ldap/timeout_stub.rb +17 -0
- data/lib/active_ldap/user_password.rb +92 -0
- data/lib/active_ldap/validations.rb +229 -0
- data/lib/active_ldap/xml.rb +122 -0
- data/po/en/active-ldap.po +4029 -0
- data/po/ja/active-ldap.po +4060 -0
- data/rails_generators/model_active_ldap/USAGE +17 -0
- data/rails_generators/model_active_ldap/model_active_ldap_generator.rb +69 -0
- data/rails_generators/model_active_ldap/templates/model_active_ldap.rb +3 -0
- data/rails_generators/model_active_ldap/templates/unit_test.rb +8 -0
- data/rails_generators/scaffold_active_ldap/scaffold_active_ldap_generator.rb +7 -0
- data/rails_generators/scaffold_active_ldap/templates/ldap.yml +18 -0
- data/test/al-test-utils.rb +439 -0
- data/test/command.rb +112 -0
- data/test/config.yaml.sample +6 -0
- data/test/fixtures/lower_case_object_class_schema.rb +802 -0
- data/test/run-test.rb +44 -0
- data/test/test_acts_as_tree.rb +60 -0
- data/test/test_adapter.rb +121 -0
- data/test/test_associations.rb +664 -0
- data/test/test_attributes.rb +117 -0
- data/test/test_base.rb +1177 -0
- data/test/test_base_per_instance.rb +61 -0
- data/test/test_bind.rb +62 -0
- data/test/test_callback.rb +37 -0
- data/test/test_configuration.rb +40 -0
- data/test/test_connection.rb +82 -0
- data/test/test_connection_per_class.rb +112 -0
- data/test/test_connection_per_dn.rb +112 -0
- data/test/test_dn.rb +172 -0
- data/test/test_find.rb +176 -0
- data/test/test_groupadd.rb +50 -0
- data/test/test_groupdel.rb +46 -0
- data/test/test_groupls.rb +107 -0
- data/test/test_groupmod.rb +51 -0
- data/test/test_ldif.rb +1891 -0
- data/test/test_load.rb +133 -0
- data/test/test_lpasswd.rb +75 -0
- data/test/test_object_class.rb +74 -0
- data/test/test_reflection.rb +182 -0
- data/test/test_schema.rb +559 -0
- data/test/test_syntax.rb +383 -0
- data/test/test_user.rb +217 -0
- data/test/test_user_password.rb +101 -0
- data/test/test_useradd-binary.rb +62 -0
- data/test/test_useradd.rb +57 -0
- data/test/test_userdel.rb +48 -0
- data/test/test_userls.rb +91 -0
- data/test/test_usermod-binary-add-time.rb +65 -0
- data/test/test_usermod-binary-add.rb +64 -0
- data/test/test_usermod-binary-del.rb +66 -0
- data/test/test_usermod-lang-add.rb +60 -0
- data/test/test_usermod.rb +58 -0
- data/test/test_validation.rb +274 -0
- metadata +502 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
module ActiveLdap
|
|
2
|
+
module GetTextFallback
|
|
3
|
+
module_function
|
|
4
|
+
def add_text_domain(name, options)
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
module_function
|
|
8
|
+
def default_available_locales=(name)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
module_function
|
|
12
|
+
def default_text_domain=(name)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
module Translation
|
|
16
|
+
class << self
|
|
17
|
+
def included(base)
|
|
18
|
+
base.extend(self)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def _(msg_id)
|
|
23
|
+
msg_id
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def n_(arg1, arg2, arg3=nil)
|
|
27
|
+
if arg1.kind_of?(Array)
|
|
28
|
+
msg_id = arg1[0]
|
|
29
|
+
msg_id_plural = arg1[1]
|
|
30
|
+
n = arg2
|
|
31
|
+
else
|
|
32
|
+
msg_id = arg1
|
|
33
|
+
msg_id_plural = arg2
|
|
34
|
+
n = arg3
|
|
35
|
+
end
|
|
36
|
+
n == 1 ? msg_id : msg_id_plural
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def N_(msg_id)
|
|
40
|
+
msg_id
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def Nn_(msg_id, msg_id_plural)
|
|
44
|
+
[msg_id, msg_id_plural]
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def s_(msg_id, div='|')
|
|
48
|
+
index = msg_id.rindex(div)
|
|
49
|
+
if index
|
|
50
|
+
msg_id[(index + 1)..-1]
|
|
51
|
+
else
|
|
52
|
+
msg_id
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
GetText = GetTextFallback
|
|
60
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module ActiveLdap
|
|
2
|
+
class << self
|
|
3
|
+
def get_text_supported?
|
|
4
|
+
not const_defined?(:GetTextFallback)
|
|
5
|
+
end
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
module GetTextSupport
|
|
9
|
+
class << self
|
|
10
|
+
def included(base)
|
|
11
|
+
base.class_eval do
|
|
12
|
+
include(GetText::Translation)
|
|
13
|
+
GetText.add_text_domain('active-ldap',:path=>'po', :type=>:po)
|
|
14
|
+
GetText.default_available_locales = ['en', 'jp']
|
|
15
|
+
GetText.default_text_domain = "active-ldap"
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
module ActiveLdap
|
|
2
|
+
module Helper
|
|
3
|
+
def ldap_attribute_name_gettext(attribute)
|
|
4
|
+
Base.human_attribute_name(attribute)
|
|
5
|
+
end
|
|
6
|
+
alias_method(:la_, :ldap_attribute_name_gettext)
|
|
7
|
+
|
|
8
|
+
def ldap_attribute_description_gettext(attribute)
|
|
9
|
+
Base.human_attribute_description(attribute)
|
|
10
|
+
end
|
|
11
|
+
alias_method(:lad_, :ldap_attribute_description_gettext)
|
|
12
|
+
|
|
13
|
+
def ldap_object_class_name_gettext(object_class)
|
|
14
|
+
Base.human_object_class_name(object_class)
|
|
15
|
+
end
|
|
16
|
+
alias_method(:loc_, :ldap_object_class_name_gettext)
|
|
17
|
+
|
|
18
|
+
def ldap_object_class_description_gettext(object_class)
|
|
19
|
+
Base.human_object_class_description(object_class)
|
|
20
|
+
end
|
|
21
|
+
alias_method(:locd_, :ldap_object_class_description_gettext)
|
|
22
|
+
|
|
23
|
+
def ldap_syntax_name_gettext(syntax)
|
|
24
|
+
Base.human_syntax_name(syntax)
|
|
25
|
+
end
|
|
26
|
+
alias_method(:ls_, :ldap_syntax_name_gettext)
|
|
27
|
+
|
|
28
|
+
def ldap_syntax_description_gettext(syntax)
|
|
29
|
+
Base.human_syntax_description(syntax)
|
|
30
|
+
end
|
|
31
|
+
alias_method(:lsd_, :ldap_syntax_description_gettext)
|
|
32
|
+
|
|
33
|
+
def ldap_field(type, object_name, method, options={})
|
|
34
|
+
case type
|
|
35
|
+
when "radio_button", "check_box", "text_area"
|
|
36
|
+
form_method = type
|
|
37
|
+
else
|
|
38
|
+
form_method = "#{type}_field"
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
object = options[:object]
|
|
42
|
+
if object.nil?
|
|
43
|
+
normalized_object_name = object_name.to_s.sub(/\[\](\])?$/, "\\1")
|
|
44
|
+
object = instance_variable_get("@#{normalized_object_name}")
|
|
45
|
+
end
|
|
46
|
+
values = object.nil? ? nil : object[method, true]
|
|
47
|
+
values = [nil] if values.blank?
|
|
48
|
+
required_ldap_options = options.delete(:ldap_options) || []
|
|
49
|
+
required_ldap_options.each do |required_ldap_option|
|
|
50
|
+
found = false
|
|
51
|
+
values.each do |value|
|
|
52
|
+
next unless value.is_a?(Hash)
|
|
53
|
+
if Hash.to_a[0].to_s == required_ldap_option.to_s
|
|
54
|
+
found = true
|
|
55
|
+
break
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
values << {required_ldap_option => ""} unless found
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
fields = []
|
|
62
|
+
collect_values = Proc.new do |value, ldap_options|
|
|
63
|
+
case value
|
|
64
|
+
when Hash
|
|
65
|
+
value.each do |k, v|
|
|
66
|
+
collect_values.call(v, ldap_options + [k])
|
|
67
|
+
end
|
|
68
|
+
when Array
|
|
69
|
+
value.each do |v|
|
|
70
|
+
collect_values.call(v, ldap_options)
|
|
71
|
+
end
|
|
72
|
+
else
|
|
73
|
+
id = "#{object_name}_#{method}"
|
|
74
|
+
name = "#{object_name}[#{method}][]"
|
|
75
|
+
ldap_options.collect.each do |ldap_option|
|
|
76
|
+
id << "_#{ldap_option}"
|
|
77
|
+
name << "[#{ldap_option}][]"
|
|
78
|
+
end
|
|
79
|
+
ldap_value_options = {:id => id, :name => name, :value => value}
|
|
80
|
+
field = send(form_method, object_name, method,
|
|
81
|
+
ldap_value_options.merge(options))
|
|
82
|
+
if block_given?
|
|
83
|
+
field = yield(field, {:options => ldap_options, :value => value})
|
|
84
|
+
end
|
|
85
|
+
fields << field unless field.blank?
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
collect_values.call(values, [])
|
|
89
|
+
fields.join("\n")
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
module ActiveLdap
|
|
2
|
+
module HumanReadable
|
|
3
|
+
def self.included(base)
|
|
4
|
+
super
|
|
5
|
+
base.extend(ClassMethods)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
module ClassMethods
|
|
9
|
+
def human_attribute_name(attribute_or_name)
|
|
10
|
+
msgid = human_attribute_name_msgid(attribute_or_name)
|
|
11
|
+
msgid ||= human_attribute_name_with_gettext(attribute_or_name)
|
|
12
|
+
s_(msgid)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def human_attribute_name_msgid(attribute_or_name)
|
|
16
|
+
if attribute_or_name.is_a?(Schema::Attribute)
|
|
17
|
+
name = attribute_or_name.name
|
|
18
|
+
else
|
|
19
|
+
attribute = schema.attribute(attribute_or_name)
|
|
20
|
+
return nil if attribute.id.nil?
|
|
21
|
+
if attribute.name == attribute_or_name or
|
|
22
|
+
attribute.aliases.include?(attribute_or_name)
|
|
23
|
+
name = attribute_or_name
|
|
24
|
+
else
|
|
25
|
+
return nil
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
"LDAP|Attribute|#{name}"
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def human_attribute_description(attribute_or_name)
|
|
32
|
+
msgid = human_attribute_description_msgid(attribute_or_name)
|
|
33
|
+
return nil if msgid.nil?
|
|
34
|
+
s_(msgid)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def human_attribute_description_msgid(attribute_or_name)
|
|
38
|
+
if attribute_or_name.is_a?(Schema::Attribute)
|
|
39
|
+
attribute = attribute_or_name
|
|
40
|
+
else
|
|
41
|
+
attribute = schema.attribute(attribute_or_name)
|
|
42
|
+
return nil if attribute.nil?
|
|
43
|
+
end
|
|
44
|
+
description = attribute.description
|
|
45
|
+
return nil if description.nil?
|
|
46
|
+
"LDAP|Description|Attribute|#{attribute.name}|#{description}"
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def human_object_class_name(object_class_or_name)
|
|
50
|
+
s_(human_object_class_name_msgid(object_class_or_name))
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def human_object_class_name_msgid(object_class_or_name)
|
|
54
|
+
if object_class_or_name.is_a?(Schema::ObjectClass)
|
|
55
|
+
name = object_class_or_name.name
|
|
56
|
+
else
|
|
57
|
+
name = object_class_or_name
|
|
58
|
+
end
|
|
59
|
+
"LDAP|ObjectClass|#{name}"
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def human_object_class_description(object_class_or_name)
|
|
63
|
+
msgid = human_object_class_description_msgid(object_class_or_name)
|
|
64
|
+
return nil if msgid.nil?
|
|
65
|
+
s_(msgid)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def human_object_class_description_msgid(object_class_or_name)
|
|
69
|
+
if object_class_or_name.is_a?(Schema::ObjectClass)
|
|
70
|
+
object_class = object_class_or_name
|
|
71
|
+
else
|
|
72
|
+
object_class = schema.object_class(object_class_or_name)
|
|
73
|
+
return nil if object_class.nil?
|
|
74
|
+
end
|
|
75
|
+
description = object_class.description
|
|
76
|
+
return nil if description.nil?
|
|
77
|
+
"LDAP|Description|ObjectClass|#{object_class.name}|#{description}"
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def human_syntax_name(syntax_or_id)
|
|
81
|
+
s_(human_syntax_name_msgid(syntax_or_id))
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def human_syntax_name_msgid(syntax_or_id)
|
|
85
|
+
if syntax_or_id.is_a?(Schema::Syntax)
|
|
86
|
+
id = syntax_or_id.id
|
|
87
|
+
else
|
|
88
|
+
id = syntax_or_id
|
|
89
|
+
end
|
|
90
|
+
"LDAP|Syntax|#{id}"
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def human_syntax_description(syntax_or_id)
|
|
94
|
+
msgid = human_syntax_description_msgid(syntax_or_id)
|
|
95
|
+
return nil if msgid.nil?
|
|
96
|
+
s_(msgid)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def human_syntax_description_msgid(syntax_or_id)
|
|
100
|
+
if syntax_or_id.is_a?(Schema::Syntax)
|
|
101
|
+
syntax = syntax_or_id
|
|
102
|
+
else
|
|
103
|
+
syntax = schema.ldap_syntax(syntax_or_id)
|
|
104
|
+
return nil if syntax.nil?
|
|
105
|
+
end
|
|
106
|
+
description = syntax.description
|
|
107
|
+
return nil if description.nil?
|
|
108
|
+
"LDAP|Description|Syntax|#{syntax.id}|#{description}"
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def human_readable_format(object)
|
|
112
|
+
case object
|
|
113
|
+
when Array
|
|
114
|
+
"[#{object.collect {|value| human_readable_format(value)}.join(', ')}]"
|
|
115
|
+
when Hash
|
|
116
|
+
formatted_values = []
|
|
117
|
+
object.each do |key, value|
|
|
118
|
+
formatted_values << [human_readable_format(key),
|
|
119
|
+
human_readable_format(value)].join("=>")
|
|
120
|
+
end
|
|
121
|
+
"{#{formatted_values.join(', ')}}"
|
|
122
|
+
else
|
|
123
|
+
if object.respond_to?(:to_human_readable_format)
|
|
124
|
+
object.to_human_readable_format
|
|
125
|
+
else
|
|
126
|
+
object.inspect
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
module ActiveLdap
|
|
2
|
+
class LdapError < Error
|
|
3
|
+
class << self
|
|
4
|
+
def define(code, name, target)
|
|
5
|
+
klass_name = name.downcase.camelize
|
|
6
|
+
target.module_eval(<<-EOC, __FILE__, __LINE__ + 1)
|
|
7
|
+
class #{klass_name} < #{self}
|
|
8
|
+
CODE = #{code}
|
|
9
|
+
def code
|
|
10
|
+
CODE
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
EOC
|
|
14
|
+
target.const_get(klass_name)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
ERRORS = {}
|
|
19
|
+
{
|
|
20
|
+
0x00 => "SUCCESS",
|
|
21
|
+
0x01 => "OPERATIONS_ERROR",
|
|
22
|
+
0x02 => "PROTOCOL_ERROR",
|
|
23
|
+
0x03 => "TIME_LIMIT_EXCEEDED",
|
|
24
|
+
0x04 => "SIZE_LIMIT_EXCEEDED",
|
|
25
|
+
0x05 => "COMPARE_FALSE",
|
|
26
|
+
0x06 => "COMPARE_TRUE",
|
|
27
|
+
0x07 => "AUTH_METHOD_NOT_SUPPORTED",
|
|
28
|
+
0x08 => "STRONG_AUTH_REQUIRED",
|
|
29
|
+
0x09 => "PARTIAL_RESULTS", # LDAPv2+ (not LDAPv3)
|
|
30
|
+
|
|
31
|
+
0x0a => "REFERRAL",
|
|
32
|
+
0x0b => "ADMIN_LIMIT_EXCEEDED",
|
|
33
|
+
0x0c => "UNAVAILABLE_CRITICAL_EXTENSION",
|
|
34
|
+
0x0d => "CONFIDENTIALITY_REQUIRED",
|
|
35
|
+
0x0e => "LDAP_SASL_BIND_IN_PROGRESS",
|
|
36
|
+
|
|
37
|
+
0x10 => "NO_SUCH_ATTRIBUTE",
|
|
38
|
+
0x11 => "UNDEFINED_TYPE",
|
|
39
|
+
0x12 => "INAPPROPRIATE_MATCHING",
|
|
40
|
+
0x13 => "CONSTRAINT_VIOLATION",
|
|
41
|
+
0x14 => "TYPE_OR_VALUE_EXISTS",
|
|
42
|
+
0x15 => "INVALID_SYNTAX",
|
|
43
|
+
|
|
44
|
+
0x20 => "NO_SUCH_OBJECT",
|
|
45
|
+
0x21 => "ALIAS_PROBLEM",
|
|
46
|
+
0x22 => "INVALID_DN_SYNTAX",
|
|
47
|
+
0x23 => "IS_LEAF",
|
|
48
|
+
0x24 => "ALIAS_DEREF_PROBLEM",
|
|
49
|
+
|
|
50
|
+
0x2F => "PROXY_AUTHZ_FAILURE",
|
|
51
|
+
0x30 => "INAPPROPRIATE_AUTH",
|
|
52
|
+
0x31 => "INVALID_CREDENTIALS",
|
|
53
|
+
0x32 => "INSUFFICIENT_ACCESS",
|
|
54
|
+
|
|
55
|
+
0x33 => "BUSY",
|
|
56
|
+
0x34 => "UNAVAILABLE",
|
|
57
|
+
0x35 => "UNWILLING_TO_PERFORM",
|
|
58
|
+
0x36 => "LOOP_DETECT",
|
|
59
|
+
|
|
60
|
+
0x40 => "NAMING_VIOLATION",
|
|
61
|
+
0x41 => "OBJECT_CLASS_VIOLATION",
|
|
62
|
+
0x42 => "NOT_ALLOWED_ON_NONLEAF",
|
|
63
|
+
0x43 => "NOT_ALLOWED_ON_RDN",
|
|
64
|
+
0x44 => "ALREADY_EXISTS",
|
|
65
|
+
0x45 => "NO_OBJECT_CLASS_MODS",
|
|
66
|
+
0x46 => "RESULTS_TOO_LARGE",
|
|
67
|
+
0x47 => "AFFECTS_MULTIPLE_DSAS",
|
|
68
|
+
|
|
69
|
+
0x50 => "OTHER",
|
|
70
|
+
}.each do |code, name|
|
|
71
|
+
ERRORS[code] = LdapError.define(code, name, self)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
@@ -0,0 +1,930 @@
|
|
|
1
|
+
require "strscan"
|
|
2
|
+
require "uri"
|
|
3
|
+
require "open-uri"
|
|
4
|
+
|
|
5
|
+
module ActiveLdap
|
|
6
|
+
class Ldif
|
|
7
|
+
module Attributes
|
|
8
|
+
module_function
|
|
9
|
+
def encode(attributes)
|
|
10
|
+
return "" if attributes.empty?
|
|
11
|
+
|
|
12
|
+
result = ""
|
|
13
|
+
normalize(attributes).sort_by {|name,| name}.each do |name, values|
|
|
14
|
+
values.each do |options, value|
|
|
15
|
+
result << Attribute.encode([name, *options].join(";"), value)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
result
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def normalize(attributes)
|
|
22
|
+
result = {}
|
|
23
|
+
attributes.each do |name, values|
|
|
24
|
+
result[name] = Attribute.normalize_value(values).sort
|
|
25
|
+
end
|
|
26
|
+
result
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
module Attribute
|
|
31
|
+
SIZE = 75
|
|
32
|
+
|
|
33
|
+
module_function
|
|
34
|
+
def binary_value?(value)
|
|
35
|
+
if value.respond_to?(:encoding)
|
|
36
|
+
return true if value.encoding == Encoding.find("ascii-8bit")
|
|
37
|
+
end
|
|
38
|
+
if /\A#{Parser::SAFE_STRING}\z/ =~ value
|
|
39
|
+
false
|
|
40
|
+
else
|
|
41
|
+
true
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def encode(name, value)
|
|
46
|
+
return "#{name}:\n" if value.blank?
|
|
47
|
+
result = "#{name}:"
|
|
48
|
+
|
|
49
|
+
value = value.to_s unless value.is_a?(String)
|
|
50
|
+
if value[-1, 1] == ' ' or binary_value?(value)
|
|
51
|
+
result << ":"
|
|
52
|
+
value = [value].pack("m").gsub(/\n/, '')
|
|
53
|
+
end
|
|
54
|
+
result << " "
|
|
55
|
+
|
|
56
|
+
first_line_value_size = SIZE - result.size
|
|
57
|
+
if value.size > first_line_value_size
|
|
58
|
+
first_line_value = value[0, first_line_value_size]
|
|
59
|
+
rest_value = value[first_line_value_size..-1]
|
|
60
|
+
else
|
|
61
|
+
first_line_value = value
|
|
62
|
+
rest_value = nil
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
result << "#{first_line_value}\n"
|
|
66
|
+
return result if rest_value.nil?
|
|
67
|
+
|
|
68
|
+
rest_value.scan(/.{1,#{SIZE - 1}}/).each do |line| # FIXME
|
|
69
|
+
result << " #{line}\n"
|
|
70
|
+
end
|
|
71
|
+
result
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def normalize_value(value, result=[])
|
|
75
|
+
case value
|
|
76
|
+
when Array
|
|
77
|
+
value.each {|val| normalize_value(val, result)}
|
|
78
|
+
when Hash
|
|
79
|
+
value.each do |option, val|
|
|
80
|
+
normalize_value(val).each do |options, v|
|
|
81
|
+
result << [[option] + options, v]
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
result
|
|
85
|
+
else
|
|
86
|
+
result << [[], value]
|
|
87
|
+
end
|
|
88
|
+
result
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
class Parser
|
|
93
|
+
include GetTextSupport
|
|
94
|
+
|
|
95
|
+
attr_reader :ldif
|
|
96
|
+
def initialize(source)
|
|
97
|
+
@ldif = nil
|
|
98
|
+
source = source.to_s if source.is_a?(LDIF)
|
|
99
|
+
@source = source
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
ATTRIBUTE_TYPE_CHARS = /[a-zA-Z][a-zA-Z0-9\-]*/
|
|
103
|
+
SAFE_CHAR = /[\x01-\x09\x0B-\x0C\x0E-\x7F]/
|
|
104
|
+
SAFE_INIT_CHAR = /[\x01-\x09\x0B-\x0C\x0E-\x1F\x21-\x39\x3B\x3D-\x7F]/
|
|
105
|
+
SAFE_STRING = /#{SAFE_INIT_CHAR}#{SAFE_CHAR}*/
|
|
106
|
+
FILL = / */
|
|
107
|
+
def parse
|
|
108
|
+
return @ldif if @ldif
|
|
109
|
+
|
|
110
|
+
@scanner = Scanner.new(@source)
|
|
111
|
+
raise version_spec_is_missing unless @scanner.scan(/version:/)
|
|
112
|
+
@scanner.scan(FILL)
|
|
113
|
+
|
|
114
|
+
version = @scanner.scan(/\d+/)
|
|
115
|
+
raise version_number_is_missing if version.nil?
|
|
116
|
+
|
|
117
|
+
version = Integer(version)
|
|
118
|
+
raise unsupported_version(version) if version != 1
|
|
119
|
+
|
|
120
|
+
raise separator_is_missing unless @scanner.scan_separators
|
|
121
|
+
|
|
122
|
+
records = parse_records
|
|
123
|
+
|
|
124
|
+
@ldif = LDIF.new(records)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
private
|
|
128
|
+
def read_base64_value
|
|
129
|
+
value = @scanner.scan(/[a-zA-Z0-9\+\/=]+/)
|
|
130
|
+
return nil if value.nil?
|
|
131
|
+
encoding = value.encoding if value.respond_to?(:encoding)
|
|
132
|
+
value = value.unpack("m")[0].chomp
|
|
133
|
+
if value.respond_to?(:force_encoding)
|
|
134
|
+
value.force_encoding(encoding)
|
|
135
|
+
value.force_encoding("ascii-8bit") unless value.valid_encoding?
|
|
136
|
+
end
|
|
137
|
+
value
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def read_external_file
|
|
141
|
+
uri_string = @scanner.scan(URI::ABS_URI)
|
|
142
|
+
raise uri_is_missing if uri_string.nil?
|
|
143
|
+
uri = nil
|
|
144
|
+
begin
|
|
145
|
+
uri = URI.parse(uri_string)
|
|
146
|
+
rescue URI::Error
|
|
147
|
+
raise invalid_uri(uri_string, $!.message)
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
if uri.scheme == "file"
|
|
151
|
+
File.open(uri.path, "rb") {|file| file.read}
|
|
152
|
+
else
|
|
153
|
+
uri.read
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def parse_dn(dn_string)
|
|
158
|
+
DN.parse(dn_string).to_s
|
|
159
|
+
rescue DistinguishedNameInvalid
|
|
160
|
+
raise invalid_dn(dn_string, $!.reason)
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def parse_attributes(least=0, &block)
|
|
164
|
+
i = 0
|
|
165
|
+
attributes = {}
|
|
166
|
+
block ||= Proc.new {@scanner.check_separator}
|
|
167
|
+
loop do
|
|
168
|
+
i += 1
|
|
169
|
+
if i >= least
|
|
170
|
+
break if block.call or @scanner.eos?
|
|
171
|
+
end
|
|
172
|
+
type, options, value = parse_attribute
|
|
173
|
+
if @scanner.scan_separator.nil? and !@scanner.eos?
|
|
174
|
+
raise separator_is_missing
|
|
175
|
+
end
|
|
176
|
+
attributes[type] ||= []
|
|
177
|
+
container = attributes[type]
|
|
178
|
+
options.each do |option|
|
|
179
|
+
parent = container.find do |val|
|
|
180
|
+
val.is_a?(Hash) and val.has_key?(option)
|
|
181
|
+
end
|
|
182
|
+
if parent.nil?
|
|
183
|
+
parent = {option => []}
|
|
184
|
+
container << parent
|
|
185
|
+
end
|
|
186
|
+
container = parent[option]
|
|
187
|
+
end
|
|
188
|
+
container << value
|
|
189
|
+
end
|
|
190
|
+
raise attribute_spec_is_missing if attributes.size < least
|
|
191
|
+
attributes
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
def parse_attribute_description
|
|
195
|
+
type = @scanner.scan(ATTRIBUTE_TYPE_CHARS)
|
|
196
|
+
raise attribute_type_is_missing if type.nil?
|
|
197
|
+
options = parse_options
|
|
198
|
+
[type, options]
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
def parse_attribute
|
|
202
|
+
type, options = parse_attribute_description
|
|
203
|
+
value = parse_attribute_value
|
|
204
|
+
[type, options, value]
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
def parse_options
|
|
208
|
+
options = []
|
|
209
|
+
while @scanner.scan(/;/)
|
|
210
|
+
option = @scanner.scan(ATTRIBUTE_TYPE_CHARS)
|
|
211
|
+
raise option_is_missing if option.nil?
|
|
212
|
+
options << option
|
|
213
|
+
end
|
|
214
|
+
options
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
def parse_attribute_value(accept_external_file=true)
|
|
218
|
+
raise attribute_value_separator_is_missing if @scanner.scan(/:/).nil?
|
|
219
|
+
if @scanner.scan(/:/)
|
|
220
|
+
@scanner.scan(FILL)
|
|
221
|
+
read_base64_value
|
|
222
|
+
elsif accept_external_file and @scanner.scan(/</)
|
|
223
|
+
@scanner.scan(FILL)
|
|
224
|
+
read_external_file
|
|
225
|
+
else
|
|
226
|
+
@scanner.scan(FILL)
|
|
227
|
+
@scanner.scan(SAFE_STRING)
|
|
228
|
+
end
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
def parse_control
|
|
232
|
+
return nil if @scanner.scan(/control:/).nil?
|
|
233
|
+
@scanner.scan(FILL)
|
|
234
|
+
type = @scanner.scan(/\d+(?:\.\d+)*/)
|
|
235
|
+
raise control_type_is_missing if type.nil?
|
|
236
|
+
criticality = nil
|
|
237
|
+
if @scanner.scan(/ +/)
|
|
238
|
+
criticality = @scanner.scan(/true|false/)
|
|
239
|
+
raise criticality_is_missing if criticality.nil?
|
|
240
|
+
end
|
|
241
|
+
value = parse_attribute_value if @scanner.check(/:/)
|
|
242
|
+
raise separator_is_missing unless @scanner.scan_separator
|
|
243
|
+
ChangeRecord::Control.new(type, criticality, value)
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
def parse_controls
|
|
247
|
+
controls = []
|
|
248
|
+
loop do
|
|
249
|
+
control = parse_control
|
|
250
|
+
break if control.nil?
|
|
251
|
+
controls << control
|
|
252
|
+
end
|
|
253
|
+
controls
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
def parse_change_type
|
|
257
|
+
return nil unless @scanner.scan(/changetype:/)
|
|
258
|
+
@scanner.scan(FILL)
|
|
259
|
+
type = @scanner.check(ATTRIBUTE_TYPE_CHARS)
|
|
260
|
+
raise change_type_value_is_missing if type.nil?
|
|
261
|
+
unless @scanner.scan(/add|delete|modrdn|moddn|modify/)
|
|
262
|
+
raise unknown_change_type(type)
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
raise separator_is_missing unless @scanner.scan_separator
|
|
266
|
+
type
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
def parse_modify_name_record(klass, dn, controls)
|
|
270
|
+
raise new_rdn_mark_is_missing unless @scanner.scan(/newrdn\b/)
|
|
271
|
+
new_rdn = parse_attribute_value(false)
|
|
272
|
+
raise new_rdn_value_is_missing if new_rdn.nil?
|
|
273
|
+
raise separator_is_missing unless @scanner.scan_separator
|
|
274
|
+
|
|
275
|
+
unless @scanner.scan(/deleteoldrdn:/)
|
|
276
|
+
raise delete_old_rdn_mark_is_missing
|
|
277
|
+
end
|
|
278
|
+
@scanner.scan(FILL)
|
|
279
|
+
delete_old_rdn = @scanner.scan(/[01]/)
|
|
280
|
+
raise delete_old_rdn_value_is_missing if delete_old_rdn.nil?
|
|
281
|
+
raise separator_is_missing unless @scanner.scan_separator
|
|
282
|
+
|
|
283
|
+
if @scanner.scan(/newsuperior\b/)
|
|
284
|
+
@scanner.scan(FILL)
|
|
285
|
+
new_superior = parse_attribute_value(false)
|
|
286
|
+
raise new_superior_value_is_missing if new_superior.nil?
|
|
287
|
+
new_superior = parse_dn(new_superior)
|
|
288
|
+
raise separator_is_missing unless @scanner.scan_separator
|
|
289
|
+
end
|
|
290
|
+
klass.new(dn, controls, new_rdn, delete_old_rdn, new_superior)
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
def parse_modify_spec
|
|
294
|
+
return nil unless @scanner.check(/(#{ATTRIBUTE_TYPE_CHARS}):/)
|
|
295
|
+
type = @scanner[1]
|
|
296
|
+
unless @scanner.scan(/(?:add|delete|replace):/)
|
|
297
|
+
raise unknown_modify_type(type)
|
|
298
|
+
end
|
|
299
|
+
@scanner.scan(FILL)
|
|
300
|
+
attribute, options = parse_attribute_description
|
|
301
|
+
raise separator_is_missing unless @scanner.scan_separator
|
|
302
|
+
attributes = parse_attributes {@scanner.check(/-/)}
|
|
303
|
+
raise modify_spec_separator_is_missing unless @scanner.scan(/-/)
|
|
304
|
+
raise separator_is_missing unless @scanner.scan_separator
|
|
305
|
+
[type, attribute, options, attributes]
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
def parse_modify_record(dn, controls)
|
|
309
|
+
operations = []
|
|
310
|
+
loop do
|
|
311
|
+
spec = parse_modify_spec
|
|
312
|
+
break if spec.nil?
|
|
313
|
+
type, attribute, options, attributes = spec
|
|
314
|
+
case type
|
|
315
|
+
when "add"
|
|
316
|
+
klass = ModifyRecord::AddOperation
|
|
317
|
+
when "delete"
|
|
318
|
+
klass = ModifyRecord::DeleteOperation
|
|
319
|
+
when "replace"
|
|
320
|
+
klass = ModifyRecord::ReplaceOperation
|
|
321
|
+
else
|
|
322
|
+
unknown_modify_type(type)
|
|
323
|
+
end
|
|
324
|
+
operations << klass.new(attribute, options, attributes)
|
|
325
|
+
end
|
|
326
|
+
ModifyRecord.new(dn, controls, operations)
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
def parse_change_type_record(dn, controls, change_type)
|
|
330
|
+
case change_type
|
|
331
|
+
when "add"
|
|
332
|
+
attributes = parse_attributes(1)
|
|
333
|
+
AddRecord.new(dn, controls, attributes)
|
|
334
|
+
when "delete"
|
|
335
|
+
DeleteRecord.new(dn, controls)
|
|
336
|
+
when "moddn"
|
|
337
|
+
parse_modify_name_record(ModifyDNRecord, dn, controls)
|
|
338
|
+
when "modrdn"
|
|
339
|
+
parse_modify_name_record(ModifyRDNRecord, dn, controls)
|
|
340
|
+
when "modify"
|
|
341
|
+
parse_modify_record(dn, controls)
|
|
342
|
+
else
|
|
343
|
+
raise unknown_change_type(change_type)
|
|
344
|
+
end
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
def parse_record
|
|
348
|
+
raise dn_mark_is_missing unless @scanner.scan(/dn:/)
|
|
349
|
+
if @scanner.scan(/:/)
|
|
350
|
+
@scanner.scan(FILL)
|
|
351
|
+
dn = read_base64_value
|
|
352
|
+
raise dn_is_missing if dn.nil?
|
|
353
|
+
dn = parse_dn(dn)
|
|
354
|
+
else
|
|
355
|
+
@scanner.scan(FILL)
|
|
356
|
+
dn = @scanner.scan(/#{SAFE_STRING}$/)
|
|
357
|
+
if dn.nil?
|
|
358
|
+
partial_dn = @scanner.scan(SAFE_STRING)
|
|
359
|
+
raise dn_has_invalid_character(@scanner.check(/./)) if partial_dn
|
|
360
|
+
raise dn_is_missing
|
|
361
|
+
end
|
|
362
|
+
dn = parse_dn(dn)
|
|
363
|
+
end
|
|
364
|
+
|
|
365
|
+
raise separator_is_missing unless @scanner.scan_separator
|
|
366
|
+
|
|
367
|
+
controls = parse_controls
|
|
368
|
+
change_type = parse_change_type
|
|
369
|
+
raise change_type_is_missing if change_type.nil? and !controls.empty?
|
|
370
|
+
|
|
371
|
+
if change_type
|
|
372
|
+
parse_change_type_record(dn, controls, change_type)
|
|
373
|
+
else
|
|
374
|
+
attributes = parse_attributes(1)
|
|
375
|
+
ContentRecord.new(dn, attributes)
|
|
376
|
+
end
|
|
377
|
+
end
|
|
378
|
+
|
|
379
|
+
def parse_records
|
|
380
|
+
records = []
|
|
381
|
+
loop do
|
|
382
|
+
records << parse_record
|
|
383
|
+
break if @scanner.eos?
|
|
384
|
+
raise separator_is_missing if @scanner.scan_separator.nil?
|
|
385
|
+
|
|
386
|
+
break if @scanner.eos?
|
|
387
|
+
break if @scanner.scan_separators and @scanner.eos?
|
|
388
|
+
end
|
|
389
|
+
records
|
|
390
|
+
end
|
|
391
|
+
|
|
392
|
+
def invalid_ldif(reason)
|
|
393
|
+
LdifInvalid.new(@source, reason, @scanner.line, @scanner.column)
|
|
394
|
+
end
|
|
395
|
+
|
|
396
|
+
def version_spec_is_missing
|
|
397
|
+
invalid_ldif(_("version spec is missing"))
|
|
398
|
+
end
|
|
399
|
+
|
|
400
|
+
def version_number_is_missing
|
|
401
|
+
invalid_ldif(_("version number is missing"))
|
|
402
|
+
end
|
|
403
|
+
|
|
404
|
+
def unsupported_version(version)
|
|
405
|
+
invalid_ldif(_("unsupported version: %d") % version)
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
def separator_is_missing
|
|
409
|
+
invalid_ldif(_("separator is missing"))
|
|
410
|
+
end
|
|
411
|
+
|
|
412
|
+
def dn_mark_is_missing
|
|
413
|
+
invalid_ldif(_("'dn:' is missing"))
|
|
414
|
+
end
|
|
415
|
+
|
|
416
|
+
def dn_is_missing
|
|
417
|
+
invalid_ldif(_("DN is missing"))
|
|
418
|
+
end
|
|
419
|
+
|
|
420
|
+
def invalid_dn(dn_string, reason)
|
|
421
|
+
invalid_ldif(_("DN is invalid: %s: %s") % [dn_string, reason])
|
|
422
|
+
end
|
|
423
|
+
|
|
424
|
+
def dn_has_invalid_character(character)
|
|
425
|
+
invalid_ldif(_("DN has an invalid character: %s") % character)
|
|
426
|
+
end
|
|
427
|
+
|
|
428
|
+
def attribute_type_is_missing
|
|
429
|
+
invalid_ldif(_("attribute type is missing"))
|
|
430
|
+
end
|
|
431
|
+
|
|
432
|
+
def option_is_missing
|
|
433
|
+
invalid_ldif(_("option is missing"))
|
|
434
|
+
end
|
|
435
|
+
|
|
436
|
+
def attribute_value_separator_is_missing
|
|
437
|
+
invalid_ldif(_("':' is missing"))
|
|
438
|
+
end
|
|
439
|
+
|
|
440
|
+
def invalid_uri(uri_string, message)
|
|
441
|
+
invalid_ldif(_("URI is invalid: %s: %s") % [uri_string, message])
|
|
442
|
+
end
|
|
443
|
+
|
|
444
|
+
def modify_spec_separator_is_missing
|
|
445
|
+
invalid_ldif(_("'-' is missing"))
|
|
446
|
+
end
|
|
447
|
+
|
|
448
|
+
def unknown_change_type(change_type)
|
|
449
|
+
invalid_ldif(_("unknown change type: %s") % change_type)
|
|
450
|
+
end
|
|
451
|
+
|
|
452
|
+
def change_type_is_missing
|
|
453
|
+
invalid_ldif(_("change type is missing"))
|
|
454
|
+
end
|
|
455
|
+
|
|
456
|
+
def control_type_is_missing
|
|
457
|
+
invalid_ldif(_("control type is missing"))
|
|
458
|
+
end
|
|
459
|
+
|
|
460
|
+
def criticality_is_missing
|
|
461
|
+
invalid_ldif(_("criticality is missing"))
|
|
462
|
+
end
|
|
463
|
+
|
|
464
|
+
def change_type_value_is_missing
|
|
465
|
+
invalid_ldif(_("change type value is missing"))
|
|
466
|
+
end
|
|
467
|
+
|
|
468
|
+
def attribute_spec_is_missing
|
|
469
|
+
invalid_ldif(_("attribute spec is missing"))
|
|
470
|
+
end
|
|
471
|
+
|
|
472
|
+
def new_rdn_mark_is_missing
|
|
473
|
+
invalid_ldif(_("'newrdn:' is missing"))
|
|
474
|
+
end
|
|
475
|
+
|
|
476
|
+
def new_rdn_value_is_missing
|
|
477
|
+
invalid_ldif(_("new RDN value is missing"))
|
|
478
|
+
end
|
|
479
|
+
|
|
480
|
+
def delete_old_rdn_mark_is_missing
|
|
481
|
+
invalid_ldif(_("'deleteoldrdn:' is missing"))
|
|
482
|
+
end
|
|
483
|
+
|
|
484
|
+
def delete_old_rdn_value_is_missing
|
|
485
|
+
invalid_ldif(_("delete old RDN value is missing"))
|
|
486
|
+
end
|
|
487
|
+
|
|
488
|
+
def new_superior_value_is_missing
|
|
489
|
+
invalid_ldif(_("new superior value is missing"))
|
|
490
|
+
end
|
|
491
|
+
|
|
492
|
+
def unknown_modify_type(type)
|
|
493
|
+
invalid_ldif(_("unknown modify type: %s") % type)
|
|
494
|
+
end
|
|
495
|
+
end
|
|
496
|
+
|
|
497
|
+
class Scanner
|
|
498
|
+
SEPARATOR = /(?:\r\n|\n)/
|
|
499
|
+
SEPARATORS = /(?:(?:^#.*)?#{SEPARATOR})+/
|
|
500
|
+
|
|
501
|
+
def initialize(source)
|
|
502
|
+
@source = source
|
|
503
|
+
@scanner = StringScanner.new(@source)
|
|
504
|
+
@sub_scanner = nil
|
|
505
|
+
@sub_scanner = next_segment || StringScanner.new("")
|
|
506
|
+
end
|
|
507
|
+
|
|
508
|
+
def scan(regexp)
|
|
509
|
+
@sub_scanner = next_segment if @sub_scanner.eos?
|
|
510
|
+
@sub_scanner.scan(regexp)
|
|
511
|
+
end
|
|
512
|
+
|
|
513
|
+
def check(regexp)
|
|
514
|
+
@sub_scanner = next_segment if @sub_scanner.eos?
|
|
515
|
+
@sub_scanner.check(regexp)
|
|
516
|
+
end
|
|
517
|
+
|
|
518
|
+
def scan_separator
|
|
519
|
+
return @scanner.scan(SEPARATOR) if @sub_scanner.eos?
|
|
520
|
+
|
|
521
|
+
scan(SEPARATOR)
|
|
522
|
+
end
|
|
523
|
+
|
|
524
|
+
def check_separator
|
|
525
|
+
return @scanner.check(SEPARATOR) if @sub_scanner.eos?
|
|
526
|
+
|
|
527
|
+
check(SEPARATOR)
|
|
528
|
+
end
|
|
529
|
+
|
|
530
|
+
def scan_separators
|
|
531
|
+
return @scanner.scan(SEPARATORS) if @sub_scanner.eos?
|
|
532
|
+
|
|
533
|
+
sub_result = scan(SEPARATORS)
|
|
534
|
+
return nil if sub_result.nil?
|
|
535
|
+
return sub_result unless @sub_scanner.eos?
|
|
536
|
+
|
|
537
|
+
result = @scanner.scan(SEPARATORS)
|
|
538
|
+
return sub_result if result.nil?
|
|
539
|
+
|
|
540
|
+
sub_result + result
|
|
541
|
+
end
|
|
542
|
+
|
|
543
|
+
def [](*args)
|
|
544
|
+
@sub_scanner[*args]
|
|
545
|
+
end
|
|
546
|
+
|
|
547
|
+
def eos?
|
|
548
|
+
@sub_scanner = next_segment if @sub_scanner.eos?
|
|
549
|
+
@sub_scanner.eos? and @scanner.eos?
|
|
550
|
+
end
|
|
551
|
+
|
|
552
|
+
def line
|
|
553
|
+
_consumed_source = consumed_source
|
|
554
|
+
return 1 if _consumed_source.empty?
|
|
555
|
+
|
|
556
|
+
n = Compatible.string_to_lines(_consumed_source).size
|
|
557
|
+
n += 1 if _consumed_source[-1, 1] == "\n"
|
|
558
|
+
n
|
|
559
|
+
end
|
|
560
|
+
|
|
561
|
+
def column
|
|
562
|
+
_consumed_source = consumed_source
|
|
563
|
+
return 1 if _consumed_source.empty?
|
|
564
|
+
|
|
565
|
+
position - (_consumed_source.rindex("\n") || -1)
|
|
566
|
+
end
|
|
567
|
+
|
|
568
|
+
def position
|
|
569
|
+
sub_scanner_string = @sub_scanner.string
|
|
570
|
+
if sub_scanner_string.respond_to?(:bytesize)
|
|
571
|
+
sub_scanner_string_size = sub_scanner_string.bytesize
|
|
572
|
+
else
|
|
573
|
+
sub_scanner_string_size = sub_scanner_string.size
|
|
574
|
+
end
|
|
575
|
+
@scanner.pos - (sub_scanner_string_size - @sub_scanner.pos)
|
|
576
|
+
end
|
|
577
|
+
|
|
578
|
+
private
|
|
579
|
+
def next_segment
|
|
580
|
+
loop do
|
|
581
|
+
segment = @scanner.scan(/.+(?:#{SEPARATOR} .*)*#{SEPARATOR}?/)
|
|
582
|
+
return @sub_scanner if segment.nil?
|
|
583
|
+
next if segment[0, 1] == "#"
|
|
584
|
+
return StringScanner.new(segment.gsub(/\r?\n /, ''))
|
|
585
|
+
end
|
|
586
|
+
end
|
|
587
|
+
|
|
588
|
+
def consumed_source
|
|
589
|
+
@source[0, position]
|
|
590
|
+
end
|
|
591
|
+
end
|
|
592
|
+
|
|
593
|
+
class << self
|
|
594
|
+
def parse(ldif)
|
|
595
|
+
Parser.new(ldif).parse
|
|
596
|
+
end
|
|
597
|
+
end
|
|
598
|
+
|
|
599
|
+
include Enumerable
|
|
600
|
+
|
|
601
|
+
attr_reader :version, :records
|
|
602
|
+
def initialize(records=[])
|
|
603
|
+
@version = 1
|
|
604
|
+
@records = records
|
|
605
|
+
end
|
|
606
|
+
|
|
607
|
+
def <<(record)
|
|
608
|
+
@records << record
|
|
609
|
+
end
|
|
610
|
+
|
|
611
|
+
def each(&block)
|
|
612
|
+
@records.each(&block)
|
|
613
|
+
end
|
|
614
|
+
|
|
615
|
+
def to_s
|
|
616
|
+
result = "version: #{@version}\n"
|
|
617
|
+
result << @records.collect do |record|
|
|
618
|
+
record.to_s
|
|
619
|
+
end.join("\n")
|
|
620
|
+
result
|
|
621
|
+
end
|
|
622
|
+
|
|
623
|
+
def ==(other)
|
|
624
|
+
other.is_a?(self.class) and
|
|
625
|
+
@version == other.version and @records == other.records
|
|
626
|
+
end
|
|
627
|
+
|
|
628
|
+
class Record
|
|
629
|
+
include GetTextSupport
|
|
630
|
+
|
|
631
|
+
attr_reader :dn, :attributes
|
|
632
|
+
def initialize(dn, attributes)
|
|
633
|
+
@dn = dn
|
|
634
|
+
@attributes = attributes
|
|
635
|
+
end
|
|
636
|
+
|
|
637
|
+
def to_hash
|
|
638
|
+
attributes.merge({"dn" => dn})
|
|
639
|
+
end
|
|
640
|
+
|
|
641
|
+
def to_s
|
|
642
|
+
result = to_s_prelude
|
|
643
|
+
result << to_s_content
|
|
644
|
+
result
|
|
645
|
+
end
|
|
646
|
+
|
|
647
|
+
def ==(other)
|
|
648
|
+
other.is_a?(self.class) and
|
|
649
|
+
@dn == other.dn and
|
|
650
|
+
Attributes.normalize(@attributes) ==
|
|
651
|
+
Attributes.normalize(other.attributes)
|
|
652
|
+
end
|
|
653
|
+
|
|
654
|
+
private
|
|
655
|
+
def to_s_prelude
|
|
656
|
+
Attribute.encode("dn", dn)
|
|
657
|
+
end
|
|
658
|
+
|
|
659
|
+
def to_s_content
|
|
660
|
+
Attributes.encode(@attributes)
|
|
661
|
+
end
|
|
662
|
+
end
|
|
663
|
+
|
|
664
|
+
class ContentRecord < Record
|
|
665
|
+
end
|
|
666
|
+
|
|
667
|
+
class ChangeRecord < Record
|
|
668
|
+
attr_reader :controls, :change_type
|
|
669
|
+
def initialize(dn, attributes, controls, change_type)
|
|
670
|
+
super(dn, attributes)
|
|
671
|
+
@controls = controls
|
|
672
|
+
@change_type = change_type
|
|
673
|
+
end
|
|
674
|
+
|
|
675
|
+
def add?
|
|
676
|
+
@change_type == "add"
|
|
677
|
+
end
|
|
678
|
+
|
|
679
|
+
def delete?
|
|
680
|
+
@change_type == "delete"
|
|
681
|
+
end
|
|
682
|
+
|
|
683
|
+
def modify?
|
|
684
|
+
@change_type == "modify"
|
|
685
|
+
end
|
|
686
|
+
|
|
687
|
+
def modify_dn?
|
|
688
|
+
@change_type == "moddn"
|
|
689
|
+
end
|
|
690
|
+
|
|
691
|
+
def modify_rdn?
|
|
692
|
+
@change_type == "modrdn"
|
|
693
|
+
end
|
|
694
|
+
|
|
695
|
+
def ==(other)
|
|
696
|
+
super(other) and
|
|
697
|
+
@controls = other.controls and
|
|
698
|
+
@change_type == other.change_type
|
|
699
|
+
end
|
|
700
|
+
|
|
701
|
+
private
|
|
702
|
+
def to_s_prelude
|
|
703
|
+
result = super
|
|
704
|
+
@controls.each do |control|
|
|
705
|
+
result << control.to_s
|
|
706
|
+
end
|
|
707
|
+
result
|
|
708
|
+
end
|
|
709
|
+
|
|
710
|
+
def to_s_content
|
|
711
|
+
result = "changetype: #{@change_type}\n"
|
|
712
|
+
result << super
|
|
713
|
+
result
|
|
714
|
+
end
|
|
715
|
+
|
|
716
|
+
class Control
|
|
717
|
+
attr_reader :type, :value
|
|
718
|
+
def initialize(type, criticality, value)
|
|
719
|
+
@type = type
|
|
720
|
+
@criticality = normalize_criticality(criticality)
|
|
721
|
+
@value = value
|
|
722
|
+
end
|
|
723
|
+
|
|
724
|
+
def criticality?
|
|
725
|
+
@criticality
|
|
726
|
+
end
|
|
727
|
+
|
|
728
|
+
def to_a
|
|
729
|
+
[@type, @criticality, @value]
|
|
730
|
+
end
|
|
731
|
+
|
|
732
|
+
def to_hash
|
|
733
|
+
{
|
|
734
|
+
:type => @type,
|
|
735
|
+
:criticality => @criticality,
|
|
736
|
+
:value => @value,
|
|
737
|
+
}
|
|
738
|
+
end
|
|
739
|
+
|
|
740
|
+
def to_s
|
|
741
|
+
result = "control: #{@type}"
|
|
742
|
+
result << " #{@criticality}" unless @criticality.nil?
|
|
743
|
+
result << @value if @value
|
|
744
|
+
result << "\n"
|
|
745
|
+
result
|
|
746
|
+
end
|
|
747
|
+
|
|
748
|
+
def ==(other)
|
|
749
|
+
other.is_a?(self.class) and
|
|
750
|
+
@type == other.type and
|
|
751
|
+
@criticality = other.criticality and
|
|
752
|
+
@value == other.value
|
|
753
|
+
end
|
|
754
|
+
|
|
755
|
+
private
|
|
756
|
+
def normalize_criticality(criticality)
|
|
757
|
+
case criticality
|
|
758
|
+
when "true", true
|
|
759
|
+
true
|
|
760
|
+
when "false", false
|
|
761
|
+
false
|
|
762
|
+
when nil
|
|
763
|
+
nil
|
|
764
|
+
else
|
|
765
|
+
raise ArgumentError,
|
|
766
|
+
_("invalid criticality value: %s") % criticality.inspect
|
|
767
|
+
end
|
|
768
|
+
end
|
|
769
|
+
end
|
|
770
|
+
end
|
|
771
|
+
|
|
772
|
+
class AddRecord < ChangeRecord
|
|
773
|
+
def initialize(dn, controls=[], attributes={})
|
|
774
|
+
super(dn, attributes, controls, "add")
|
|
775
|
+
end
|
|
776
|
+
end
|
|
777
|
+
|
|
778
|
+
class DeleteRecord < ChangeRecord
|
|
779
|
+
def initialize(dn, controls=[])
|
|
780
|
+
super(dn, {}, controls, "delete")
|
|
781
|
+
end
|
|
782
|
+
end
|
|
783
|
+
|
|
784
|
+
class ModifyNameRecord < ChangeRecord
|
|
785
|
+
attr_reader :new_rdn, :new_superior
|
|
786
|
+
def initialize(dn, controls, change_type,
|
|
787
|
+
new_rdn, delete_old_rdn, new_superior)
|
|
788
|
+
super(dn, {}, controls, change_type)
|
|
789
|
+
@new_rdn = new_rdn
|
|
790
|
+
@delete_old_rdn = normalize_delete_old_rdn(delete_old_rdn)
|
|
791
|
+
@new_superior = new_superior
|
|
792
|
+
end
|
|
793
|
+
|
|
794
|
+
def delete_old_rdn?
|
|
795
|
+
@delete_old_rdn
|
|
796
|
+
end
|
|
797
|
+
|
|
798
|
+
private
|
|
799
|
+
def normalize_delete_old_rdn(delete_old_rdn)
|
|
800
|
+
case delete_old_rdn
|
|
801
|
+
when "1", true
|
|
802
|
+
true
|
|
803
|
+
when "0", false
|
|
804
|
+
false
|
|
805
|
+
when nil
|
|
806
|
+
nil
|
|
807
|
+
else
|
|
808
|
+
raise ArgumentError,
|
|
809
|
+
_("invalid deleteoldrdn value: %s") % delete_old_rdn.inspect
|
|
810
|
+
end
|
|
811
|
+
end
|
|
812
|
+
|
|
813
|
+
def to_s_content
|
|
814
|
+
result = super
|
|
815
|
+
result << "newrdn: #{@new_rdn}\n"
|
|
816
|
+
result << "deleteoldrdn: #{@delete_old_rdn ? 1 : 0}\n"
|
|
817
|
+
result << Attribute.encode("newsuperior", @new_superior) if @new_superior
|
|
818
|
+
result
|
|
819
|
+
end
|
|
820
|
+
end
|
|
821
|
+
|
|
822
|
+
class ModifyDNRecord < ModifyNameRecord
|
|
823
|
+
def initialize(dn, controls, new_rdn, delete_old_rdn, new_superior=nil)
|
|
824
|
+
super(dn, controls, "moddn", new_rdn, delete_old_rdn, new_superior)
|
|
825
|
+
end
|
|
826
|
+
end
|
|
827
|
+
|
|
828
|
+
class ModifyRDNRecord < ModifyNameRecord
|
|
829
|
+
def initialize(dn, controls, new_rdn, delete_old_rdn, new_superior=nil)
|
|
830
|
+
super(dn, controls, "modrdn", new_rdn, delete_old_rdn, new_superior)
|
|
831
|
+
end
|
|
832
|
+
end
|
|
833
|
+
|
|
834
|
+
class ModifyRecord < ChangeRecord
|
|
835
|
+
include Enumerable
|
|
836
|
+
|
|
837
|
+
attr_reader :operations
|
|
838
|
+
def initialize(dn, controls=[], operations=[])
|
|
839
|
+
super(dn, {}, controls, "modify")
|
|
840
|
+
@operations = operations
|
|
841
|
+
end
|
|
842
|
+
|
|
843
|
+
def each(&block)
|
|
844
|
+
@operations.each(&block)
|
|
845
|
+
end
|
|
846
|
+
|
|
847
|
+
def <<(operation)
|
|
848
|
+
@operations << operation
|
|
849
|
+
end
|
|
850
|
+
|
|
851
|
+
def add_operation(type, attribute, options, attributes)
|
|
852
|
+
klass = self.class.const_get("#{type.to_s.capitalize}Operation")
|
|
853
|
+
self << klass.new(attribute, options, attributes)
|
|
854
|
+
end
|
|
855
|
+
|
|
856
|
+
def ==(other)
|
|
857
|
+
super(other) and @operations == other.operations
|
|
858
|
+
end
|
|
859
|
+
|
|
860
|
+
private
|
|
861
|
+
def to_s_content
|
|
862
|
+
result = super
|
|
863
|
+
return result if @operations.empty?
|
|
864
|
+
@operations.collect do |operation|
|
|
865
|
+
result << "#{operation}-\n"
|
|
866
|
+
end
|
|
867
|
+
result
|
|
868
|
+
end
|
|
869
|
+
|
|
870
|
+
class Operation
|
|
871
|
+
attr_reader :type, :attribute, :options, :attributes
|
|
872
|
+
def initialize(type, attribute, options, attributes)
|
|
873
|
+
@type = type
|
|
874
|
+
@attribute = attribute
|
|
875
|
+
@options = options
|
|
876
|
+
@attributes = attributes
|
|
877
|
+
end
|
|
878
|
+
|
|
879
|
+
def full_attribute_name
|
|
880
|
+
[@attribute, *@options].join(";")
|
|
881
|
+
end
|
|
882
|
+
|
|
883
|
+
def add?
|
|
884
|
+
@type == "add"
|
|
885
|
+
end
|
|
886
|
+
|
|
887
|
+
def delete?
|
|
888
|
+
@type == "delete"
|
|
889
|
+
end
|
|
890
|
+
|
|
891
|
+
def replace?
|
|
892
|
+
@type == "replace"
|
|
893
|
+
end
|
|
894
|
+
|
|
895
|
+
def to_s
|
|
896
|
+
Attribute.encode(@type, full_attribute_name) +
|
|
897
|
+
Attributes.encode(@attributes)
|
|
898
|
+
end
|
|
899
|
+
|
|
900
|
+
def ==(other)
|
|
901
|
+
other.is_a?(self.class) and
|
|
902
|
+
@type == other.type and
|
|
903
|
+
full_attribute_name == other.full_attribute_name and
|
|
904
|
+
Attributes.normalize(@attributes) ==
|
|
905
|
+
Attributes.normalize(other.attributes)
|
|
906
|
+
end
|
|
907
|
+
end
|
|
908
|
+
|
|
909
|
+
class AddOperation < Operation
|
|
910
|
+
def initialize(attribute, options, attributes)
|
|
911
|
+
super("add", attribute, options, attributes)
|
|
912
|
+
end
|
|
913
|
+
end
|
|
914
|
+
|
|
915
|
+
class DeleteOperation < Operation
|
|
916
|
+
def initialize(attribute, options, attributes)
|
|
917
|
+
super("delete", attribute, options, attributes)
|
|
918
|
+
end
|
|
919
|
+
end
|
|
920
|
+
|
|
921
|
+
class ReplaceOperation < Operation
|
|
922
|
+
def initialize(attribute, options, attributes)
|
|
923
|
+
super("replace", attribute, options, attributes)
|
|
924
|
+
end
|
|
925
|
+
end
|
|
926
|
+
end
|
|
927
|
+
end
|
|
928
|
+
|
|
929
|
+
LDIF = Ldif
|
|
930
|
+
end
|