activeldap 0.9.0

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.
Files changed (435) hide show
  1. data/CHANGES +454 -0
  2. data/COPYING +340 -0
  3. data/LICENSE +58 -0
  4. data/README +101 -0
  5. data/Rakefile +175 -0
  6. data/TODO +25 -0
  7. data/benchmark/bench-al.rb +202 -0
  8. data/benchmark/config.yaml.sample +5 -0
  9. data/data/locale/en/LC_MESSAGES/active-ldap.mo +0 -0
  10. data/data/locale/ja/LC_MESSAGES/active-ldap.mo +0 -0
  11. data/examples/al-admin/README +182 -0
  12. data/examples/al-admin/Rakefile +10 -0
  13. data/examples/al-admin/app/controllers/account_controller.rb +59 -0
  14. data/examples/al-admin/app/controllers/application.rb +34 -0
  15. data/examples/al-admin/app/controllers/attributes_controller.rb +17 -0
  16. data/examples/al-admin/app/controllers/directory_controller.rb +47 -0
  17. data/examples/al-admin/app/controllers/object_classes_controller.rb +17 -0
  18. data/examples/al-admin/app/controllers/syntaxes_controller.rb +17 -0
  19. data/examples/al-admin/app/controllers/users_controller.rb +51 -0
  20. data/examples/al-admin/app/controllers/welcome_controller.rb +10 -0
  21. data/examples/al-admin/app/helpers/account_helper.rb +2 -0
  22. data/examples/al-admin/app/helpers/application_helper.rb +42 -0
  23. data/examples/al-admin/app/helpers/attributes_helper.rb +15 -0
  24. data/examples/al-admin/app/helpers/directory_helper.rb +7 -0
  25. data/examples/al-admin/app/helpers/object_classes_helper.rb +10 -0
  26. data/examples/al-admin/app/helpers/syntaxes_helper.rb +10 -0
  27. data/examples/al-admin/app/helpers/url_helper.rb +13 -0
  28. data/examples/al-admin/app/helpers/users_helper.rb +17 -0
  29. data/examples/al-admin/app/helpers/welcome_helper.rb +2 -0
  30. data/examples/al-admin/app/models/entry.rb +23 -0
  31. data/examples/al-admin/app/models/ldap_user.rb +54 -0
  32. data/examples/al-admin/app/models/user.rb +91 -0
  33. data/examples/al-admin/app/views/_entry/_attributes_information.rhtml +23 -0
  34. data/examples/al-admin/app/views/_entry/_entry.rhtml +15 -0
  35. data/examples/al-admin/app/views/_schema/_aliases.rhtml +7 -0
  36. data/examples/al-admin/app/views/_switcher/_after.rhtml +2 -0
  37. data/examples/al-admin/app/views/_switcher/_before.rhtml +5 -0
  38. data/examples/al-admin/app/views/account/login.rhtml +26 -0
  39. data/examples/al-admin/app/views/account/sign_up.rhtml +28 -0
  40. data/examples/al-admin/app/views/attributes/_attributes.rhtml +19 -0
  41. data/examples/al-admin/app/views/attributes/_detail.rhtml +29 -0
  42. data/examples/al-admin/app/views/attributes/index.rhtml +3 -0
  43. data/examples/al-admin/app/views/attributes/show.rhtml +31 -0
  44. data/examples/al-admin/app/views/directory/_tree.rhtml +10 -0
  45. data/examples/al-admin/app/views/directory/_tree_view_js.rhtml +26 -0
  46. data/examples/al-admin/app/views/directory/index.rhtml +13 -0
  47. data/examples/al-admin/app/views/directory/populate.rhtml +2 -0
  48. data/examples/al-admin/app/views/layouts/_flash_box.rhtml +4 -0
  49. data/examples/al-admin/app/views/layouts/_footer.rhtml +9 -0
  50. data/examples/al-admin/app/views/layouts/_header_menu.rhtml +10 -0
  51. data/examples/al-admin/app/views/layouts/_main_menu.rhtml +18 -0
  52. data/examples/al-admin/app/views/layouts/application.rhtml +56 -0
  53. data/examples/al-admin/app/views/object_classes/_attributes.rhtml +28 -0
  54. data/examples/al-admin/app/views/object_classes/_object_classes.rhtml +19 -0
  55. data/examples/al-admin/app/views/object_classes/index.rhtml +3 -0
  56. data/examples/al-admin/app/views/object_classes/show.rhtml +39 -0
  57. data/examples/al-admin/app/views/syntaxes/_detail.rhtml +14 -0
  58. data/examples/al-admin/app/views/syntaxes/_syntaxes.rhtml +19 -0
  59. data/examples/al-admin/app/views/syntaxes/index.rhtml +3 -0
  60. data/examples/al-admin/app/views/syntaxes/show.rhtml +22 -0
  61. data/examples/al-admin/app/views/users/_attributes_update_form.rhtml +30 -0
  62. data/examples/al-admin/app/views/users/_form.rhtml +13 -0
  63. data/examples/al-admin/app/views/users/_object_classes_update_form.rhtml +40 -0
  64. data/examples/al-admin/app/views/users/_password_change_form.rhtml +20 -0
  65. data/examples/al-admin/app/views/users/edit.rhtml +15 -0
  66. data/examples/al-admin/app/views/users/index.rhtml +10 -0
  67. data/examples/al-admin/app/views/users/show.rhtml +11 -0
  68. data/examples/al-admin/app/views/welcome/index.rhtml +13 -0
  69. data/examples/al-admin/config/boot.rb +45 -0
  70. data/examples/al-admin/config/database.yml.example +19 -0
  71. data/examples/al-admin/config/environment.rb +70 -0
  72. data/examples/al-admin/config/environments/development.rb +21 -0
  73. data/examples/al-admin/config/environments/production.rb +18 -0
  74. data/examples/al-admin/config/environments/test.rb +19 -0
  75. data/examples/al-admin/config/ldap.yml.example +21 -0
  76. data/examples/al-admin/config/routes.rb +46 -0
  77. data/examples/al-admin/db/migrate/001_create_users.rb +16 -0
  78. data/examples/al-admin/lib/accept_http_rails_relative_url_root.rb +9 -0
  79. data/examples/al-admin/lib/authenticated_system.rb +124 -0
  80. data/examples/al-admin/lib/authenticated_test_helper.rb +113 -0
  81. data/examples/al-admin/lib/tasks/gettext.rake +35 -0
  82. data/examples/al-admin/po/en/al-admin.po +341 -0
  83. data/examples/al-admin/po/ja/al-admin.po +341 -0
  84. data/examples/al-admin/po/nl/al-admin.po +373 -0
  85. data/examples/al-admin/public/.htaccess +40 -0
  86. data/examples/al-admin/public/404.html +30 -0
  87. data/examples/al-admin/public/500.html +30 -0
  88. data/examples/al-admin/public/dispatch.cgi +10 -0
  89. data/examples/al-admin/public/dispatch.fcgi +24 -0
  90. data/examples/al-admin/public/dispatch.rb +10 -0
  91. data/examples/al-admin/public/favicon.ico +0 -0
  92. data/examples/al-admin/public/images/active-ldap.svg +6351 -0
  93. data/examples/al-admin/public/images/al-admin.png +0 -0
  94. data/examples/al-admin/public/images/al-admin.svg +6371 -0
  95. data/examples/al-admin/public/images/header-background.png +0 -0
  96. data/examples/al-admin/public/images/header-background.svg +99 -0
  97. data/examples/al-admin/public/images/rails.png +0 -0
  98. data/examples/al-admin/public/images/spinelz/accordion_tab_left_active.gif +0 -0
  99. data/examples/al-admin/public/images/spinelz/accordion_tab_left_inactive.gif +0 -0
  100. data/examples/al-admin/public/images/spinelz/accordion_tab_middle_active.gif +0 -0
  101. data/examples/al-admin/public/images/spinelz/accordion_tab_middle_inactive.gif +0 -0
  102. data/examples/al-admin/public/images/spinelz/accordion_tab_right_active.gif +0 -0
  103. data/examples/al-admin/public/images/spinelz/accordion_tab_right_inactive.gif +0 -0
  104. data/examples/al-admin/public/images/spinelz/balloon_back.gif +0 -0
  105. data/examples/al-admin/public/images/spinelz/balloon_bottom_left.gif +0 -0
  106. data/examples/al-admin/public/images/spinelz/balloon_bottom_middle.gif +0 -0
  107. data/examples/al-admin/public/images/spinelz/balloon_bottom_right.gif +0 -0
  108. data/examples/al-admin/public/images/spinelz/balloon_left_down_arrow.gif +0 -0
  109. data/examples/al-admin/public/images/spinelz/balloon_left_up_arrow.gif +0 -0
  110. data/examples/al-admin/public/images/spinelz/balloon_middle_left.gif +0 -0
  111. data/examples/al-admin/public/images/spinelz/balloon_middle_right.gif +0 -0
  112. data/examples/al-admin/public/images/spinelz/balloon_right_down_arrow.gif +0 -0
  113. data/examples/al-admin/public/images/spinelz/balloon_right_up_arrow.gif +0 -0
  114. data/examples/al-admin/public/images/spinelz/balloon_top_left.gif +0 -0
  115. data/examples/al-admin/public/images/spinelz/balloon_top_middle.gif +0 -0
  116. data/examples/al-admin/public/images/spinelz/balloon_top_right.gif +0 -0
  117. data/examples/al-admin/public/images/spinelz/barchart_h.gif +0 -0
  118. data/examples/al-admin/public/images/spinelz/barchart_v.gif +0 -0
  119. data/examples/al-admin/public/images/spinelz/button.gif +0 -0
  120. data/examples/al-admin/public/images/spinelz/calendar_default_handler.gif +0 -0
  121. data/examples/al-admin/public/images/spinelz/calendar_delete.gif +0 -0
  122. data/examples/al-admin/public/images/spinelz/calendar_next.gif +0 -0
  123. data/examples/al-admin/public/images/spinelz/calendar_next_second.gif +0 -0
  124. data/examples/al-admin/public/images/spinelz/calendar_pre.gif +0 -0
  125. data/examples/al-admin/public/images/spinelz/calendar_pre_second.gif +0 -0
  126. data/examples/al-admin/public/images/spinelz/calendar_private_icon.gif +0 -0
  127. data/examples/al-admin/public/images/spinelz/calendar_schedule.gif +0 -0
  128. data/examples/al-admin/public/images/spinelz/calender_back.gif +0 -0
  129. data/examples/al-admin/public/images/spinelz/calender_back_second.gif +0 -0
  130. data/examples/al-admin/public/images/spinelz/datepicker2_back.gif +0 -0
  131. data/examples/al-admin/public/images/spinelz/datepicker2_back_second.gif +0 -0
  132. data/examples/al-admin/public/images/spinelz/datepicker2_next.gif +0 -0
  133. data/examples/al-admin/public/images/spinelz/datepicker2_next_second.gif +0 -0
  134. data/examples/al-admin/public/images/spinelz/datepicker2_pre.gif +0 -0
  135. data/examples/al-admin/public/images/spinelz/datepicker2_pre_second.gif +0 -0
  136. data/examples/al-admin/public/images/spinelz/datepicker_back.gif +0 -0
  137. data/examples/al-admin/public/images/spinelz/datepicker_back_second.gif +0 -0
  138. data/examples/al-admin/public/images/spinelz/datepicker_next.gif +0 -0
  139. data/examples/al-admin/public/images/spinelz/datepicker_next_second.gif +0 -0
  140. data/examples/al-admin/public/images/spinelz/datepicker_pre.gif +0 -0
  141. data/examples/al-admin/public/images/spinelz/datepicker_pre_second.gif +0 -0
  142. data/examples/al-admin/public/images/spinelz/grid_down.gif +0 -0
  143. data/examples/al-admin/public/images/spinelz/grid_state.gif +0 -0
  144. data/examples/al-admin/public/images/spinelz/grid_up.gif +0 -0
  145. data/examples/al-admin/public/images/spinelz/icon_day.gif +0 -0
  146. data/examples/al-admin/public/images/spinelz/icon_month.gif +0 -0
  147. data/examples/al-admin/public/images/spinelz/icon_week.gif +0 -0
  148. data/examples/al-admin/public/images/spinelz/menubar_back.gif +0 -0
  149. data/examples/al-admin/public/images/spinelz/menubar_subcontents_back.gif +0 -0
  150. data/examples/al-admin/public/images/spinelz/navPanel_tab_left_active.gif +0 -0
  151. data/examples/al-admin/public/images/spinelz/navPanel_tab_left_inactive.gif +0 -0
  152. data/examples/al-admin/public/images/spinelz/navPanel_tab_middle_active.gif +0 -0
  153. data/examples/al-admin/public/images/spinelz/navPanel_tab_middle_inactive.gif +0 -0
  154. data/examples/al-admin/public/images/spinelz/navPanel_tab_right_active.gif +0 -0
  155. data/examples/al-admin/public/images/spinelz/navPanel_tab_right_inactive.gif +0 -0
  156. data/examples/al-admin/public/images/spinelz/select_date.gif +0 -0
  157. data/examples/al-admin/public/images/spinelz/selectabletable_selected.gif +0 -0
  158. data/examples/al-admin/public/images/spinelz/sideBarBox_about.gif +0 -0
  159. data/examples/al-admin/public/images/spinelz/sideBarBox_menu.gif +0 -0
  160. data/examples/al-admin/public/images/spinelz/sideBarBox_sample.gif +0 -0
  161. data/examples/al-admin/public/images/spinelz/sideBarBox_tabBottomActive.gif +0 -0
  162. data/examples/al-admin/public/images/spinelz/sideBarBox_tabBottomInactive.gif +0 -0
  163. data/examples/al-admin/public/images/spinelz/sideBarBox_tabMiddleActive.gif +0 -0
  164. data/examples/al-admin/public/images/spinelz/sideBarBox_tabMiddleActive2.gif +0 -0
  165. data/examples/al-admin/public/images/spinelz/sideBarBox_tabMiddleInactive.gif +0 -0
  166. data/examples/al-admin/public/images/spinelz/sideBarBox_tabMiddleInactive2.gif +0 -0
  167. data/examples/al-admin/public/images/spinelz/sideBarBox_tabTopActive.gif +0 -0
  168. data/examples/al-admin/public/images/spinelz/sideBarBox_tabTopInactive.gif +0 -0
  169. data/examples/al-admin/public/images/spinelz/sideBarBox_tabbar.gif +0 -0
  170. data/examples/al-admin/public/images/spinelz/sortableTable_down.gif +0 -0
  171. data/examples/al-admin/public/images/spinelz/sortableTable_normal.gif +0 -0
  172. data/examples/al-admin/public/images/spinelz/sortableTable_up.gif +0 -0
  173. data/examples/al-admin/public/images/spinelz/switcher_close.gif +0 -0
  174. data/examples/al-admin/public/images/spinelz/switcher_open.gif +0 -0
  175. data/examples/al-admin/public/images/spinelz/tabBox_close.gif +0 -0
  176. data/examples/al-admin/public/images/spinelz/tabBox_tabLeftActive.gif +0 -0
  177. data/examples/al-admin/public/images/spinelz/tabBox_tabLeftInactive.gif +0 -0
  178. data/examples/al-admin/public/images/spinelz/tabBox_tabMiddleActive.gif +0 -0
  179. data/examples/al-admin/public/images/spinelz/tabBox_tabMiddleInactive.gif +0 -0
  180. data/examples/al-admin/public/images/spinelz/tabBox_tabRightActive.gif +0 -0
  181. data/examples/al-admin/public/images/spinelz/tabBox_tabRightInactive.gif +0 -0
  182. data/examples/al-admin/public/images/spinelz/tab_bar.gif +0 -0
  183. data/examples/al-admin/public/images/spinelz/table_back.gif +0 -0
  184. data/examples/al-admin/public/images/spinelz/timepicker_clock.gif +0 -0
  185. data/examples/al-admin/public/images/spinelz/toolbar_close.gif +0 -0
  186. data/examples/al-admin/public/images/spinelz/toolbar_left.gif +0 -0
  187. data/examples/al-admin/public/images/spinelz/toolbar_max.gif +0 -0
  188. data/examples/al-admin/public/images/spinelz/toolbar_middle.gif +0 -0
  189. data/examples/al-admin/public/images/spinelz/toolbar_min.gif +0 -0
  190. data/examples/al-admin/public/images/spinelz/toolbar_next.gif +0 -0
  191. data/examples/al-admin/public/images/spinelz/toolbar_right.gif +0 -0
  192. data/examples/al-admin/public/images/spinelz/treeview_dir.gif +0 -0
  193. data/examples/al-admin/public/images/spinelz/treeview_file.gif +0 -0
  194. data/examples/al-admin/public/images/spinelz/treeview_group.gif +0 -0
  195. data/examples/al-admin/public/images/spinelz/treeview_group_special.gif +0 -0
  196. data/examples/al-admin/public/images/spinelz/treeview_state.gif +0 -0
  197. data/examples/al-admin/public/images/spinelz/treeview_user.gif +0 -0
  198. data/examples/al-admin/public/images/spinelz/window_bottom_left.gif +0 -0
  199. data/examples/al-admin/public/images/spinelz/window_bottom_middle.gif +0 -0
  200. data/examples/al-admin/public/images/spinelz/window_bottom_right.gif +0 -0
  201. data/examples/al-admin/public/images/spinelz/window_close.gif +0 -0
  202. data/examples/al-admin/public/images/spinelz/window_max.gif +0 -0
  203. data/examples/al-admin/public/images/spinelz/window_middle_left.gif +0 -0
  204. data/examples/al-admin/public/images/spinelz/window_middle_right.gif +0 -0
  205. data/examples/al-admin/public/images/spinelz/window_min.gif +0 -0
  206. data/examples/al-admin/public/images/spinelz/window_top_left.gif +0 -0
  207. data/examples/al-admin/public/images/spinelz/window_top_middle.gif +0 -0
  208. data/examples/al-admin/public/images/spinelz/window_top_right.gif +0 -0
  209. data/examples/al-admin/public/javascripts/application.js +2 -0
  210. data/examples/al-admin/public/javascripts/controls.js +833 -0
  211. data/examples/al-admin/public/javascripts/dragdrop.js +942 -0
  212. data/examples/al-admin/public/javascripts/effects.js +1088 -0
  213. data/examples/al-admin/public/javascripts/prototype.js +2515 -0
  214. data/examples/al-admin/public/javascripts/spinelz/accordion.js +185 -0
  215. data/examples/al-admin/public/javascripts/spinelz/ajaxHistory.js +157 -0
  216. data/examples/al-admin/public/javascripts/spinelz/balloon.js +287 -0
  217. data/examples/al-admin/public/javascripts/spinelz/barchart.js +524 -0
  218. data/examples/al-admin/public/javascripts/spinelz/calendar.js +3012 -0
  219. data/examples/al-admin/public/javascripts/spinelz/colorpicker.js +128 -0
  220. data/examples/al-admin/public/javascripts/spinelz/datepicker.js +438 -0
  221. data/examples/al-admin/public/javascripts/spinelz/grid.js +1391 -0
  222. data/examples/al-admin/public/javascripts/spinelz/grid_resizeEx.js +100 -0
  223. data/examples/al-admin/public/javascripts/spinelz/grid_sortabletableEx.js +129 -0
  224. data/examples/al-admin/public/javascripts/spinelz/inplaceEditorEx.js +148 -0
  225. data/examples/al-admin/public/javascripts/spinelz/menubar.js +232 -0
  226. data/examples/al-admin/public/javascripts/spinelz/navPanel.js +170 -0
  227. data/examples/al-admin/public/javascripts/spinelz/selectableTable.js +433 -0
  228. data/examples/al-admin/public/javascripts/spinelz/sideBarBox.js +282 -0
  229. data/examples/al-admin/public/javascripts/spinelz/sideBarBox_effects.js +83 -0
  230. data/examples/al-admin/public/javascripts/spinelz/sortableTable.js +270 -0
  231. data/examples/al-admin/public/javascripts/spinelz/switcher.js +78 -0
  232. data/examples/al-admin/public/javascripts/spinelz/tabBox.js +469 -0
  233. data/examples/al-admin/public/javascripts/spinelz/timepicker.js +384 -0
  234. data/examples/al-admin/public/javascripts/spinelz/toolbar.js +152 -0
  235. data/examples/al-admin/public/javascripts/spinelz/treeview.js +703 -0
  236. data/examples/al-admin/public/javascripts/spinelz/window.js +641 -0
  237. data/examples/al-admin/public/javascripts/spinelz/window_resizeEx.js +130 -0
  238. data/examples/al-admin/public/javascripts/spinelz_lib/builder.js +131 -0
  239. data/examples/al-admin/public/javascripts/spinelz_lib/controls.js +835 -0
  240. data/examples/al-admin/public/javascripts/spinelz_lib/dragdrop.js +944 -0
  241. data/examples/al-admin/public/javascripts/spinelz_lib/effects.js +1090 -0
  242. data/examples/al-admin/public/javascripts/spinelz_lib/json.js +139 -0
  243. data/examples/al-admin/public/javascripts/spinelz_lib/prototype.js +2515 -0
  244. data/examples/al-admin/public/javascripts/spinelz_lib/resize.js +215 -0
  245. data/examples/al-admin/public/javascripts/spinelz_lib/scriptaculous.js +51 -0
  246. data/examples/al-admin/public/javascripts/spinelz_lib/slider.js +278 -0
  247. data/examples/al-admin/public/javascripts/spinelz_lib/spinelz_util.js +1266 -0
  248. data/examples/al-admin/public/javascripts/spinelz_lib/unittest.js +564 -0
  249. data/examples/al-admin/public/robots.txt +1 -0
  250. data/examples/al-admin/public/stylesheets/account.css +41 -0
  251. data/examples/al-admin/public/stylesheets/attributes.css +1 -0
  252. data/examples/al-admin/public/stylesheets/base.css +99 -0
  253. data/examples/al-admin/public/stylesheets/common.css +2 -0
  254. data/examples/al-admin/public/stylesheets/detail.css +36 -0
  255. data/examples/al-admin/public/stylesheets/directory.css +22 -0
  256. data/examples/al-admin/public/stylesheets/object-classes.css +6 -0
  257. data/examples/al-admin/public/stylesheets/rails.css +35 -0
  258. data/examples/al-admin/public/stylesheets/spinelz/accordion.css +59 -0
  259. data/examples/al-admin/public/stylesheets/spinelz/balloon.css +151 -0
  260. data/examples/al-admin/public/stylesheets/spinelz/calendar.css +564 -0
  261. data/examples/al-admin/public/stylesheets/spinelz/datepicker.css +175 -0
  262. data/examples/al-admin/public/stylesheets/spinelz/grid.css +137 -0
  263. data/examples/al-admin/public/stylesheets/spinelz/menubar.css +78 -0
  264. data/examples/al-admin/public/stylesheets/spinelz/modal.css +22 -0
  265. data/examples/al-admin/public/stylesheets/spinelz/navPanel.css +58 -0
  266. data/examples/al-admin/public/stylesheets/spinelz/selectableTable.css +28 -0
  267. data/examples/al-admin/public/stylesheets/spinelz/sideBarBox.css +82 -0
  268. data/examples/al-admin/public/stylesheets/spinelz/sortableTable.css +51 -0
  269. data/examples/al-admin/public/stylesheets/spinelz/switcher.css +23 -0
  270. data/examples/al-admin/public/stylesheets/spinelz/tabBox.css +94 -0
  271. data/examples/al-admin/public/stylesheets/spinelz/timepicker.css +508 -0
  272. data/examples/al-admin/public/stylesheets/spinelz/toolbar.css +82 -0
  273. data/examples/al-admin/public/stylesheets/spinelz/treeview.css +121 -0
  274. data/examples/al-admin/public/stylesheets/spinelz/window.css +140 -0
  275. data/examples/al-admin/public/stylesheets/structure.css +81 -0
  276. data/examples/al-admin/public/stylesheets/syntaxes.css +1 -0
  277. data/examples/al-admin/public/stylesheets/users.css +13 -0
  278. data/examples/al-admin/public/stylesheets/welcome.css +0 -0
  279. data/examples/al-admin/script/about +3 -0
  280. data/examples/al-admin/script/breakpointer +3 -0
  281. data/examples/al-admin/script/console +3 -0
  282. data/examples/al-admin/script/destroy +3 -0
  283. data/examples/al-admin/script/generate +3 -0
  284. data/examples/al-admin/script/performance/benchmarker +3 -0
  285. data/examples/al-admin/script/performance/profiler +3 -0
  286. data/examples/al-admin/script/plugin +3 -0
  287. data/examples/al-admin/script/process/inspector +3 -0
  288. data/examples/al-admin/script/process/reaper +3 -0
  289. data/examples/al-admin/script/process/spawner +3 -0
  290. data/examples/al-admin/script/runner +3 -0
  291. data/examples/al-admin/script/server +3 -0
  292. data/examples/al-admin/test/fixtures/users.yml +9 -0
  293. data/examples/al-admin/test/functional/account_controller_test.rb +24 -0
  294. data/examples/al-admin/test/functional/attributes_controller_test.rb +18 -0
  295. data/examples/al-admin/test/functional/directory_controller_test.rb +18 -0
  296. data/examples/al-admin/test/functional/object_classes_controller_test.rb +18 -0
  297. data/examples/al-admin/test/functional/syntaxes_controller_test.rb +18 -0
  298. data/examples/al-admin/test/functional/users_controller_test.rb +18 -0
  299. data/examples/al-admin/test/functional/welcome_controller_test.rb +18 -0
  300. data/examples/al-admin/test/run-test.sh +3 -0
  301. data/examples/al-admin/test/test_helper.rb +28 -0
  302. data/examples/al-admin/test/unit/user_test.rb +13 -0
  303. data/examples/al-admin/vendor/plugins/exception_notification/README +111 -0
  304. data/examples/al-admin/vendor/plugins/exception_notification/init.rb +1 -0
  305. data/examples/al-admin/vendor/plugins/exception_notification/lib/exception_notifiable.rb +99 -0
  306. data/examples/al-admin/vendor/plugins/exception_notification/lib/exception_notifier.rb +67 -0
  307. data/examples/al-admin/vendor/plugins/exception_notification/lib/exception_notifier_helper.rb +77 -0
  308. data/examples/al-admin/vendor/plugins/exception_notification/test/exception_notifier_helper_test.rb +61 -0
  309. data/examples/al-admin/vendor/plugins/exception_notification/test/test_helper.rb +7 -0
  310. data/examples/al-admin/vendor/plugins/exception_notification/views/exception_notifier/_backtrace.rhtml +1 -0
  311. data/examples/al-admin/vendor/plugins/exception_notification/views/exception_notifier/_environment.rhtml +7 -0
  312. data/examples/al-admin/vendor/plugins/exception_notification/views/exception_notifier/_inspect_model.rhtml +16 -0
  313. data/examples/al-admin/vendor/plugins/exception_notification/views/exception_notifier/_request.rhtml +3 -0
  314. data/examples/al-admin/vendor/plugins/exception_notification/views/exception_notifier/_session.rhtml +2 -0
  315. data/examples/al-admin/vendor/plugins/exception_notification/views/exception_notifier/_title.rhtml +3 -0
  316. data/examples/al-admin/vendor/plugins/exception_notification/views/exception_notifier/exception_notification.rhtml +6 -0
  317. data/examples/config.yaml.example +5 -0
  318. data/examples/example.der +0 -0
  319. data/examples/example.jpg +0 -0
  320. data/examples/groupadd +41 -0
  321. data/examples/groupdel +35 -0
  322. data/examples/groupls +49 -0
  323. data/examples/groupmod +42 -0
  324. data/examples/lpasswd +55 -0
  325. data/examples/objects/group.rb +13 -0
  326. data/examples/objects/ou.rb +4 -0
  327. data/examples/objects/user.rb +20 -0
  328. data/examples/ouadd +38 -0
  329. data/examples/useradd +45 -0
  330. data/examples/useradd-binary +50 -0
  331. data/examples/userdel +34 -0
  332. data/examples/userls +50 -0
  333. data/examples/usermod +42 -0
  334. data/examples/usermod-binary-add +47 -0
  335. data/examples/usermod-binary-add-time +51 -0
  336. data/examples/usermod-binary-del +48 -0
  337. data/examples/usermod-lang-add +43 -0
  338. data/lib/active_ldap/acts/tree.rb +75 -0
  339. data/lib/active_ldap/adapter/base.rb +531 -0
  340. data/lib/active_ldap/adapter/ldap.rb +231 -0
  341. data/lib/active_ldap/adapter/ldap_ext.rb +69 -0
  342. data/lib/active_ldap/adapter/net_ldap.rb +292 -0
  343. data/lib/active_ldap/adapter/net_ldap_ext.rb +29 -0
  344. data/lib/active_ldap/association/belongs_to.rb +47 -0
  345. data/lib/active_ldap/association/belongs_to_many.rb +42 -0
  346. data/lib/active_ldap/association/children.rb +21 -0
  347. data/lib/active_ldap/association/collection.rb +83 -0
  348. data/lib/active_ldap/association/has_many.rb +31 -0
  349. data/lib/active_ldap/association/has_many_utils.rb +35 -0
  350. data/lib/active_ldap/association/has_many_wrap.rb +46 -0
  351. data/lib/active_ldap/association/proxy.rb +102 -0
  352. data/lib/active_ldap/associations.rb +172 -0
  353. data/lib/active_ldap/attributes.rb +211 -0
  354. data/lib/active_ldap/base.rb +1273 -0
  355. data/lib/active_ldap/callbacks.rb +19 -0
  356. data/lib/active_ldap/command.rb +49 -0
  357. data/lib/active_ldap/configuration.rb +147 -0
  358. data/lib/active_ldap/connection.rb +237 -0
  359. data/lib/active_ldap/distinguished_name.rb +251 -0
  360. data/lib/active_ldap/escape.rb +12 -0
  361. data/lib/active_ldap/get_text/parser.rb +159 -0
  362. data/lib/active_ldap/get_text.rb +8 -0
  363. data/lib/active_ldap/get_text_fallback.rb +53 -0
  364. data/lib/active_ldap/get_text_support.rb +26 -0
  365. data/lib/active_ldap/helper.rb +33 -0
  366. data/lib/active_ldap/human_readable.rb +112 -0
  367. data/lib/active_ldap/ldap_error.rb +74 -0
  368. data/lib/active_ldap/ldif.rb +52 -0
  369. data/lib/active_ldap/object_class.rb +93 -0
  370. data/lib/active_ldap/operations.rb +429 -0
  371. data/lib/active_ldap/populate.rb +44 -0
  372. data/lib/active_ldap/schema/syntaxes.rb +386 -0
  373. data/lib/active_ldap/schema.rb +530 -0
  374. data/lib/active_ldap/timeout.rb +75 -0
  375. data/lib/active_ldap/timeout_stub.rb +17 -0
  376. data/lib/active_ldap/user_password.rb +93 -0
  377. data/lib/active_ldap/validations.rb +171 -0
  378. data/lib/active_ldap.rb +982 -0
  379. data/po/en/active-ldap.po +3677 -0
  380. data/po/ja/active-ldap.po +3713 -0
  381. data/rails/plugin/active_ldap/README +54 -0
  382. data/rails/plugin/active_ldap/generators/model_active_ldap/USAGE +17 -0
  383. data/rails/plugin/active_ldap/generators/model_active_ldap/model_active_ldap_generator.rb +70 -0
  384. data/rails/plugin/active_ldap/generators/model_active_ldap/templates/fixtures.yml +11 -0
  385. data/rails/plugin/active_ldap/generators/model_active_ldap/templates/model_active_ldap.rb +3 -0
  386. data/rails/plugin/active_ldap/generators/model_active_ldap/templates/unit_test.rb +10 -0
  387. data/rails/plugin/active_ldap/generators/scaffold_active_ldap/scaffold_active_ldap_generator.rb +7 -0
  388. data/rails/plugin/active_ldap/generators/scaffold_al/scaffold_al_generator.rb +20 -0
  389. data/rails/plugin/active_ldap/init.rb +26 -0
  390. data/test/al-test-utils.rb +362 -0
  391. data/test/command.rb +62 -0
  392. data/test/config.yaml.sample +6 -0
  393. data/test/run-test.rb +31 -0
  394. data/test/test-unit-ext/always-show-result.rb +28 -0
  395. data/test/test-unit-ext/backtrace-filter.rb +17 -0
  396. data/test/test-unit-ext/long-display-for-emacs.rb +25 -0
  397. data/test/test-unit-ext/priority.rb +163 -0
  398. data/test/test-unit-ext.rb +4 -0
  399. data/test/test_acts_as_tree.rb +57 -0
  400. data/test/test_adapter.rb +98 -0
  401. data/test/test_associations.rb +353 -0
  402. data/test/test_attributes.rb +79 -0
  403. data/test/test_base.rb +547 -0
  404. data/test/test_base_per_instance.rb +55 -0
  405. data/test/test_bind.rb +62 -0
  406. data/test/test_callback.rb +35 -0
  407. data/test/test_configuration.rb +40 -0
  408. data/test/test_connection.rb +59 -0
  409. data/test/test_connection_per_class.rb +58 -0
  410. data/test/test_connection_per_dn.rb +78 -0
  411. data/test/test_dn.rb +160 -0
  412. data/test/test_find.rb +96 -0
  413. data/test/test_groupadd.rb +50 -0
  414. data/test/test_groupdel.rb +46 -0
  415. data/test/test_groupls.rb +107 -0
  416. data/test/test_groupmod.rb +51 -0
  417. data/test/test_ldif.rb +35 -0
  418. data/test/test_lpasswd.rb +75 -0
  419. data/test/test_object_class.rb +56 -0
  420. data/test/test_reflection.rb +179 -0
  421. data/test/test_schema.rb +433 -0
  422. data/test/test_syntax.rb +329 -0
  423. data/test/test_user.rb +227 -0
  424. data/test/test_user_password.rb +93 -0
  425. data/test/test_useradd-binary.rb +61 -0
  426. data/test/test_useradd.rb +57 -0
  427. data/test/test_userdel.rb +48 -0
  428. data/test/test_userls.rb +91 -0
  429. data/test/test_usermod-binary-add-time.rb +64 -0
  430. data/test/test_usermod-binary-add.rb +63 -0
  431. data/test/test_usermod-binary-del.rb +66 -0
  432. data/test/test_usermod-lang-add.rb +59 -0
  433. data/test/test_usermod.rb +58 -0
  434. data/test/test_validation.rb +110 -0
  435. metadata +536 -0
@@ -0,0 +1,19 @@
1
+ require 'active_record/callbacks'
2
+
3
+ module ActiveLdap
4
+ module Callbacks
5
+ def self.append_features(base)
6
+ super
7
+
8
+ base.class_eval do
9
+ include ActiveRecord::Callbacks
10
+
11
+ def callback(method)
12
+ super
13
+ rescue ActiveRecord::ActiveRecordError
14
+ raise Error, $!.message
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,49 @@
1
+ require 'optparse'
2
+ require 'ostruct'
3
+
4
+ module ActiveLdap
5
+ module Command
6
+ include GetTextSupport
7
+
8
+ module_function
9
+ def parse_options(argv=nil, version=nil)
10
+ argv ||= ARGV.dup
11
+ options = OpenStruct.new
12
+ opts = OptionParser.new do |opts|
13
+ yield(opts, options)
14
+
15
+ opts.separator ""
16
+ opts.separator _("Common options:")
17
+
18
+ opts.on_tail("--config=CONFIG",
19
+ _("Specify configuration file written as YAML")) do |file|
20
+ require 'yaml'
21
+ config = YAML.load(File.read(file)).symbolize_keys
22
+ config = Base.prepare_configuration(config)
23
+ Configuration::DEFAULT_CONFIG.update(config)
24
+ end
25
+
26
+ opts.on_tail("-h", "--help", _("Show this message")) do
27
+ puts opts
28
+ exit
29
+ end
30
+
31
+ opts.on_tail("--version", _("Show version")) do
32
+ puts(version || VERSION)
33
+ exit
34
+ end
35
+ end
36
+ opts.parse!(argv)
37
+ [argv, opts, options]
38
+ end
39
+
40
+ def read_password(prompt, input=$stdin, output=$stdout)
41
+ output.print prompt
42
+ system "/bin/stty -echo" if input.tty?
43
+ input.gets.chomp
44
+ ensure
45
+ system "/bin/stty echo" if input.tty?
46
+ output.puts
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,147 @@
1
+ require 'uri'
2
+ begin
3
+ require 'uri/ldaps'
4
+ rescue LoadError
5
+ module URI
6
+ class LDAPS < LDAP
7
+ DEFAULT_PORT = 636
8
+ end
9
+ @@schemes['LDAPS'] = LDAPS
10
+ end
11
+ end
12
+
13
+ module ActiveLdap
14
+ # Configuration
15
+ #
16
+ # Configuration provides the default settings required for
17
+ # ActiveLdap to work with your LDAP server. All of these
18
+ # settings can be passed in at initialization time.
19
+ module Configuration
20
+ def self.included(base)
21
+ base.extend(ClassMethods)
22
+ end
23
+
24
+ DEFAULT_CONFIG = {}
25
+ DEFAULT_CONFIG[:host] = '127.0.0.1'
26
+ DEFAULT_CONFIG[:port] = 389
27
+ DEFAULT_CONFIG[:method] = :plain # :ssl, :tls, :plain allowed
28
+
29
+ DEFAULT_CONFIG[:bind_dn] = nil
30
+ DEFAULT_CONFIG[:password_block] = nil
31
+ DEFAULT_CONFIG[:password] = nil
32
+ DEFAULT_CONFIG[:store_password] = true
33
+ DEFAULT_CONFIG[:allow_anonymous] = true
34
+ DEFAULT_CONFIG[:sasl_quiet] = false
35
+ DEFAULT_CONFIG[:try_sasl] = false
36
+ # See http://www.iana.org/assignments/sasl-mechanisms
37
+ DEFAULT_CONFIG[:sasl_mechanisms] = ["GSSAPI", "DIGEST-MD5",
38
+ "CRAM-MD5", "EXTERNAL"]
39
+
40
+ DEFAULT_CONFIG[:retry_limit] = 3
41
+ DEFAULT_CONFIG[:retry_wait] = 3
42
+ DEFAULT_CONFIG[:timeout] = 0 # in seconds; 0 <= Never timeout
43
+ # Whether or not to retry on timeouts
44
+ DEFAULT_CONFIG[:retry_on_timeout] = true
45
+
46
+ DEFAULT_CONFIG[:logger] = nil
47
+
48
+ module ClassMethods
49
+ @@defined_configurations = {}
50
+
51
+ def default_configuration
52
+ DEFAULT_CONFIG.dup
53
+ end
54
+
55
+ def ensure_configuration(config=nil)
56
+ if config.nil?
57
+ if defined?(LDAP_ENV)
58
+ config = LDAP_ENV
59
+ elsif defined?(RAILS_ENV)
60
+ config = RAILS_ENV
61
+ else
62
+ config = {}
63
+ end
64
+ end
65
+
66
+ if config.is_a?(Symbol) or config.is_a?(String)
67
+ _config = configurations[config.to_s]
68
+ unless _config
69
+ raise ConnectionError,
70
+ _("%s connection is not configured") % config
71
+ end
72
+ config = _config
73
+ end
74
+
75
+ config
76
+ end
77
+
78
+ def configuration(key=nil)
79
+ @@defined_configurations[key || active_connection_name]
80
+ end
81
+
82
+ def define_configuration(key, config)
83
+ @@defined_configurations[key] = config
84
+ end
85
+
86
+ def defined_configurations
87
+ @@defined_configurations
88
+ end
89
+
90
+ def remove_configuration_by_configuration(config)
91
+ @@defined_configurations.delete_if {|key, value| value == config}
92
+ end
93
+
94
+ CONNECTION_CONFIGURATION_KEYS = [:uri, :base, :adapter]
95
+ def remove_connection_related_configuration(config)
96
+ config.reject do |key, value|
97
+ CONNECTION_CONFIGURATION_KEYS.include?(key)
98
+ end
99
+ end
100
+
101
+ def merge_configuration(user_configuration, target=self)
102
+ configuration = default_configuration
103
+ prepare_configuration(user_configuration).each do |key, value|
104
+ case key
105
+ when :base
106
+ # Scrub before inserting
107
+ target.base = value.gsub(/['}{#]/, '')
108
+ when :scope, :ldap_scope
109
+ if key == :ldap_scope
110
+ logger.warning do
111
+ _(":ldap_scope configuration option is deprecated. " \
112
+ "Use :scope instead.")
113
+ end
114
+ end
115
+ target.scope = value
116
+ configuration[:scope] = value
117
+ else
118
+ configuration[key] = value
119
+ end
120
+ end
121
+ configuration
122
+ end
123
+
124
+ def prepare_configuration(configuration)
125
+ configuration = configuration.symbolize_keys
126
+ uri = configuration.delete(:uri)
127
+ return configuration unless uri
128
+
129
+ begin
130
+ uri = URI.parse(uri)
131
+ rescue URI::InvalidURIError
132
+ raise ConfigurationError.new(_("invalid URI: %s") % uri)
133
+ end
134
+ unless uri.is_a?(URI::LDAP)
135
+ raise ConfigurationError.new(_("not a LDAP URI: %s") % uri.to_s)
136
+ end
137
+
138
+ uri_configuration = {:port => uri.port}
139
+ uri_configuration[:host] = uri.host if uri.host
140
+ uri_configuration[:bind_dn] = uri.dn if uri.dn
141
+ uri_configuration[:scope] = uri.scope if uri.scope
142
+ uri_configuration[:method] = :ssl if uri.is_a?(URI::LDAPS)
143
+ uri_configuration.merge(configuration)
144
+ end
145
+ end
146
+ end
147
+ end
@@ -0,0 +1,237 @@
1
+ module ActiveLdap
2
+ module Connection
3
+ def self.included(base)
4
+ base.extend(ClassMethods)
5
+ end
6
+
7
+ module ClassMethods
8
+ @@active_connections = {}
9
+ @@allow_concurrency = false
10
+
11
+ def thread_safe_active_connections
12
+ @@active_connections[Thread.current.object_id] ||= {}
13
+ end
14
+
15
+ def single_threaded_active_connections
16
+ @@active_connections
17
+ end
18
+
19
+ if @@allow_concurrency
20
+ alias_method :active_connections, :thread_safe_active_connections
21
+ else
22
+ alias_method :active_connections, :single_threaded_active_connections
23
+ end
24
+
25
+ def allow_concurrency=(threaded) #:nodoc:
26
+ logger.debug {"allow_concurrency=#{threaded}"} if logger
27
+ return if @@allow_concurrency == threaded
28
+ clear_all_cached_connections!
29
+ @@allow_concurrency = threaded
30
+ method_prefix = threaded ? "thread_safe" : "single_threaded"
31
+ sing = (class << self; self; end)
32
+ [:active_connections].each do |method|
33
+ sing.send(:alias_method, method, "#{method_prefix}_#{method}")
34
+ end
35
+ end
36
+
37
+ def active_connection_name
38
+ @active_connection_name ||= determine_active_connection_name
39
+ end
40
+
41
+ def remove_active_connections!
42
+ active_connections.keys.each do |key|
43
+ remove_connection(key)
44
+ end
45
+ end
46
+
47
+ def clear_active_connections!
48
+ connections = active_connections
49
+ connections.each do |key, connection|
50
+ connection.disconnect!
51
+ end
52
+ connections.clear
53
+ end
54
+
55
+ def clear_active_connection_name
56
+ @active_connection_name = nil
57
+ ObjectSpace.each_object(Class) do |klass|
58
+ if klass < self and !klass.name.empty?
59
+ klass.instance_variable_set("@active_connection_name", nil)
60
+ end
61
+ end
62
+ end
63
+
64
+ def connection
65
+ conn = nil
66
+ @active_connection_name ||= nil
67
+ if @active_connection_name
68
+ conn = active_connections[@active_connection_name]
69
+ end
70
+ unless conn
71
+ conn = retrieve_connection
72
+ active_connections[@active_connection_name] = conn
73
+ end
74
+ conn
75
+ end
76
+
77
+ def connection=(adapter)
78
+ if adapter.is_a?(Adapter::Base)
79
+ active_connections[active_connection_name] = adapter
80
+ elsif adapter.is_a?(Hash)
81
+ config = adapter
82
+ self.connection = instantiate_adapter(config)
83
+ elsif adapter.nil?
84
+ raise ConnectionNotEstablished
85
+ else
86
+ establish_connection(adapter)
87
+ end
88
+ end
89
+
90
+ def instantiate_adapter(config)
91
+ adapter = (config[:adapter] || "ldap")
92
+ normalized_adapter = adapter.downcase.gsub(/-/, "_")
93
+ adapter_method = "#{normalized_adapter}_connection"
94
+ unless Adapter::Base.respond_to?(adapter_method)
95
+ raise AdapterNotFound.new(adapter)
96
+ end
97
+ if config.has_key?(:ldap_scope)
98
+ logger.warning do
99
+ _(":ldap_scope connection option is deprecated. Use :scope instead.")
100
+ end
101
+ config[:scope] ||= config.delete(:ldap_scope)
102
+ end
103
+ config = remove_connection_related_configuration(config)
104
+ Adapter::Base.send(adapter_method, config)
105
+ end
106
+
107
+ def connected?
108
+ active_connections[active_connection_name] ? true : false
109
+ end
110
+
111
+ def retrieve_connection
112
+ conn = nil
113
+ name = active_connection_name
114
+ raise ConnectionNotEstablished unless name
115
+ conn = active_connections[name]
116
+ if conn.nil?
117
+ config = configuration(name)
118
+ raise ConnectionNotEstablished unless config
119
+ self.connection = config
120
+ conn = active_connections[name]
121
+ end
122
+ raise ConnectionNotEstablished if conn.nil?
123
+ conn
124
+ end
125
+
126
+ def remove_connection(klass_or_key=self)
127
+ if klass_or_key.is_a?(Module)
128
+ key = active_connection_key(klass_or_key)
129
+ else
130
+ key = klass_or_key
131
+ end
132
+ config = configuration(key)
133
+ conn = active_connections[key]
134
+ remove_configuration_by_configuration(config)
135
+ active_connections.delete_if {|key, value| value == conn}
136
+ conn.disconnect! if conn
137
+ config
138
+ end
139
+
140
+ def establish_connection(config=nil)
141
+ config = ensure_configuration(config)
142
+ remove_connection
143
+
144
+ clear_active_connection_name
145
+ key = active_connection_key
146
+ @active_connection_name = key
147
+ define_configuration(key, merge_configuration(config))
148
+ end
149
+
150
+ # Return the schema object
151
+ def schema
152
+ connection.schema
153
+ end
154
+
155
+ private
156
+ def active_connection_key(k=self)
157
+ k.name.empty? ? k.object_id : k.name
158
+ end
159
+
160
+ def determine_active_connection_name
161
+ key = active_connection_key
162
+ if active_connections[key] or configuration(key)
163
+ key
164
+ elsif self == ActiveLdap::Base
165
+ nil
166
+ else
167
+ superclass.active_connection_name
168
+ end
169
+ end
170
+
171
+ def clear_all_cached_connections!
172
+ if @@allow_concurrency
173
+ @@active_connections.each_value do |connection_hash_for_thread|
174
+ connection_hash_for_thread.each_value {|conn| conn.disconnect!}
175
+ connection_hash_for_thread.clear
176
+ end
177
+ else
178
+ @@active_connections.each_value {|conn| conn.disconnect!}
179
+ end
180
+ @@active_connections.clear
181
+ end
182
+ end
183
+
184
+ def establish_connection(config=nil)
185
+ config = self.class.ensure_configuration(config)
186
+ config = self.class.configuration.merge(config)
187
+ config = self.class.merge_configuration(config, self)
188
+
189
+ remove_connection
190
+ self.class.define_configuration(dn, config)
191
+ end
192
+
193
+ def remove_connection
194
+ self.class.remove_connection(dn)
195
+ @connection = nil
196
+ end
197
+
198
+ def connection
199
+ conn = @connection
200
+ if get_attribute_before_type_cast(dn_attribute)[1]
201
+ conn ||= self.class.active_connections[dn] || retrieve_connection
202
+ end
203
+ conn || self.class.connection
204
+ end
205
+
206
+ def connected?
207
+ connection != self.class.connection
208
+ end
209
+
210
+ def connection=(adapter)
211
+ if adapter.nil? or adapter.is_a?(Adapter::Base)
212
+ @connection = adapter
213
+ elsif adapter.is_a?(Hash)
214
+ config = adapter
215
+ @connection = self.class.instantiate_adapter(config)
216
+ else
217
+ establish_connection(adapter)
218
+ end
219
+ end
220
+
221
+ def retrieve_connection
222
+ conn = self.class.active_connections[dn]
223
+ return conn if conn
224
+
225
+ config = self.class.configuration(dn)
226
+ return nil unless config
227
+
228
+ conn = self.class.instantiate_adapter(config)
229
+ @connection = self.class.active_connections[dn] = conn
230
+ conn
231
+ end
232
+
233
+ def schema
234
+ connection.schema
235
+ end
236
+ end
237
+ end
@@ -0,0 +1,251 @@
1
+ require 'strscan'
2
+
3
+ module ActiveLdap
4
+ class DistinguishedName
5
+ include GetTextSupport
6
+
7
+ class Parser
8
+ include GetTextSupport
9
+
10
+ attr_reader :dn
11
+ def initialize(source)
12
+ @dn = nil
13
+ source = source.to_s if source.is_a?(DN)
14
+ @source = source
15
+ end
16
+
17
+ def parse
18
+ return @dn if @dn
19
+
20
+ rdns = []
21
+ scanner = StringScanner.new(@source)
22
+
23
+ scanner.scan(/\s*/)
24
+ raise rdn_is_missing if scanner.scan(/\s*\+\s*/)
25
+ raise name_component_is_missing if scanner.scan(/\s*,\s*/)
26
+
27
+ rdn = {}
28
+ until scanner.eos?
29
+ type = scan_attribute_type(scanner)
30
+ skip_attribute_type_and_value_separator(scanner)
31
+ value = scan_attribute_value(scanner)
32
+ rdn[type] = value
33
+ if scanner.scan(/\s*\+\s*/)
34
+ raise rdn_is_missing if scanner.eos?
35
+ elsif scanner.scan(/\s*\,\s*/)
36
+ rdns << rdn
37
+ rdn = {}
38
+ raise name_component_is_missing if scanner.eos?
39
+ else
40
+ scanner.scan(/\s*/)
41
+ rdns << rdn if scanner.eos?
42
+ end
43
+ end
44
+
45
+ @dn = DN.new(*rdns)
46
+ @dn
47
+ end
48
+
49
+ private
50
+ ATTRIBUTE_TYPE_RE = /\s*([a-zA-Z][a-zA-Z\d\-]*|\d+(?:\.\d+)*)\s*/
51
+ def scan_attribute_type(scanner)
52
+ raise attribute_type_is_missing unless scanner.scan(ATTRIBUTE_TYPE_RE)
53
+ scanner[1]
54
+ end
55
+
56
+ def skip_attribute_type_and_value_separator(scanner)
57
+ raise attribute_value_is_missing unless scanner.scan(/\s*=\s*/)
58
+ end
59
+
60
+ HEX_PAIR = "(?:[\\da-fA-F]{2})"
61
+ STRING_CHARS_RE = /[^,=\+<>\#;\\\"]*/ #
62
+ PAIR_RE = /\\([,=\+<>\#;]|\\|\"|(#{HEX_PAIR}))/ #
63
+ HEX_STRING_RE = /\#(#{HEX_PAIR}+)/ #
64
+ def scan_attribute_value(scanner)
65
+ if scanner.scan(HEX_STRING_RE)
66
+ value = scanner[1].scan(/../).collect do |hex_pair|
67
+ hex_pair.hex
68
+ end.pack("C*")
69
+ elsif scanner.scan(/\"/)
70
+ value = scan_quoted_attribute_value(scanner)
71
+ else
72
+ value = scan_not_quoted_attribute_value(scanner)
73
+ end
74
+ raise attribute_value_is_missing if value.blank?
75
+
76
+ value
77
+ end
78
+
79
+ def scan_quoted_attribute_value(scanner)
80
+ result = ""
81
+ until scanner.scan(/\"/)
82
+ scanner.scan(/([^\\\"]*)/)
83
+ quoted_strings = scanner[1]
84
+ pairs = collect_pairs(scanner)
85
+
86
+ if scanner.eos? or (quoted_strings.empty? and pairs.empty?)
87
+ raise found_unmatched_quotation
88
+ end
89
+
90
+ result << quoted_strings
91
+ result << pairs
92
+ end
93
+ result
94
+ end
95
+
96
+ def scan_not_quoted_attribute_value(scanner)
97
+ result = ""
98
+ until scanner.eos?
99
+ prev_size = result.size
100
+ pairs = collect_pairs(scanner)
101
+ strings = scanner.scan(STRING_CHARS_RE)
102
+ result << pairs if !pairs.nil? and !pairs.empty?
103
+ unless strings.nil?
104
+ if scanner.peek(1) == ","
105
+ result << strings.rstrip
106
+ else
107
+ result << strings
108
+ end
109
+ end
110
+ break if prev_size == result.size
111
+ end
112
+ result
113
+ end
114
+
115
+ def collect_pairs(scanner)
116
+ result = ""
117
+ while scanner.scan(PAIR_RE)
118
+ if scanner[2]
119
+ result << [scanner[2].hex].pack("C*")
120
+ else
121
+ result << scanner[1]
122
+ end
123
+ end
124
+ result
125
+ end
126
+
127
+ def invalid_dn(reason)
128
+ DistinguishedNameInvalid.new(@source, reason)
129
+ end
130
+
131
+ def name_component_is_missing
132
+ invalid_dn(_("name component is missing"))
133
+ end
134
+
135
+ def rdn_is_missing
136
+ invalid_dn(_("relative distinguished name (RDN) is missing"))
137
+ end
138
+
139
+ def attribute_type_is_missing
140
+ invalid_dn(_("attribute type is missing"))
141
+ end
142
+
143
+ def attribute_value_is_missing
144
+ invalid_dn(_("attribute value is missing"))
145
+ end
146
+
147
+ def found_unmatched_quotation
148
+ invalid_dn(_("found unmatched quotation"))
149
+ end
150
+ end
151
+
152
+ class << self
153
+ def parse(source)
154
+ Parser.new(source).parse
155
+ end
156
+ end
157
+
158
+ attr_reader :rdns
159
+ def initialize(*rdns)
160
+ @rdns = rdns.collect do |rdn|
161
+ rdn = {rdn[0] => rdn[1]} if rdn.is_a?(Array) and rdn.size == 2
162
+ rdn
163
+ end
164
+ end
165
+
166
+ def -(other)
167
+ rdns = @rdns.dup
168
+ normalized_rdns = normalize(@rdns)
169
+ normalize(other.rdns).reverse_each do |rdn|
170
+ if rdn == normalized_rdns.pop
171
+ rdns.pop
172
+ else
173
+ raise ArgumentError, _("%s isn't sub DN of %s") % [other, self]
174
+ end
175
+ end
176
+ self.class.new(*rdns)
177
+ end
178
+
179
+ def <<(rdn)
180
+ @rdns << rdn
181
+ end
182
+
183
+ def unshift(rdn)
184
+ @rdns.unshift(rdn)
185
+ end
186
+
187
+ def <=>(other)
188
+ normalize_for_comparing(@rdns) <=>
189
+ normalize_for_comparing(other.rdns)
190
+ end
191
+
192
+ def ==(other)
193
+ other.is_a?(self.class) and
194
+ normalize(@rdns) == normalize(other.rdns)
195
+ end
196
+
197
+ def eql?(other)
198
+ other.is_a?(self.class) and
199
+ normalize(@rdns).to_s.eql?(normalize(other.rdns).to_s)
200
+ end
201
+
202
+ def hash
203
+ normalize(@rdns).to_s.hash
204
+ end
205
+
206
+ def inspect
207
+ super
208
+ end
209
+
210
+ def to_s
211
+ @rdns.collect do |rdn|
212
+ rdn.sort_by do |type, value|
213
+ type.upcase
214
+ end.collect do |type, value|
215
+ "#{type}=#{escape(value)}"
216
+ end.join("+")
217
+ end.join(",")
218
+ end
219
+
220
+ private
221
+ def normalize(rdns)
222
+ rdns.collect do |rdn|
223
+ normalized_rdn = {}
224
+ rdn.each do |key, value|
225
+ normalized_rdn[key.upcase] = value.upcase
226
+ end
227
+ normalized_rdn
228
+ end
229
+ end
230
+
231
+ def normalize_for_comparing(rdns)
232
+ normalize(rdns).collect do |rdn|
233
+ rdn.sort_by do |key, value|
234
+ key
235
+ end
236
+ end.collect do |key, value|
237
+ [key, value]
238
+ end
239
+ end
240
+
241
+ def escape(value)
242
+ if /(\A | \z)/.match(value)
243
+ '"' + value.gsub(/([\\\"])/, '\\\\\1') + '"'
244
+ else
245
+ value.gsub(/([,=\+<>#;\\\"])/, '\\\\\1')
246
+ end
247
+ end
248
+ end
249
+
250
+ DN = DistinguishedName
251
+ end
@@ -0,0 +1,12 @@
1
+ module ActiveLdap
2
+ module Escape
3
+ module_function
4
+ def ldap_filter_escape(str)
5
+ str.to_s.gsub(/\*/, "**")
6
+ end
7
+
8
+ def ldap_filter_unescape(str)
9
+ str.to_s.gsub(/\*\*/, "*")
10
+ end
11
+ end
12
+ end