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.
Files changed (443) hide show
  1. data/.gitignore +6 -0
  2. data/CHANGES +691 -0
  3. data/COPYING +340 -0
  4. data/LICENSE +58 -0
  5. data/README +154 -0
  6. data/Rakefile +121 -0
  7. data/TODO +32 -0
  8. data/activeldap3.gemspec +18 -0
  9. data/benchmark/bench-al.rb +263 -0
  10. data/benchmark/config.yaml.sample +5 -0
  11. data/examples/al-admin/README +182 -0
  12. data/examples/al-admin/Rakefile +16 -0
  13. data/examples/al-admin/app/controllers/account_controller.rb +60 -0
  14. data/examples/al-admin/app/controllers/application_controller.rb +46 -0
  15. data/examples/al-admin/app/controllers/attributes_controller.rb +17 -0
  16. data/examples/al-admin/app/controllers/directory_controller.rb +49 -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 +66 -0
  20. data/examples/al-admin/app/controllers/welcome_controller.rb +12 -0
  21. data/examples/al-admin/app/helpers/account_helper.rb +2 -0
  22. data/examples/al-admin/app/helpers/application_helper.rb +46 -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 +17 -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 +58 -0
  32. data/examples/al-admin/app/models/user.rb +91 -0
  33. data/examples/al-admin/app/views/_entry/_attributes_information.html.erb +29 -0
  34. data/examples/al-admin/app/views/_entry/_entry.html.erb +15 -0
  35. data/examples/al-admin/app/views/_schema/_aliases.html.erb +7 -0
  36. data/examples/al-admin/app/views/_switcher/_after.html.erb +2 -0
  37. data/examples/al-admin/app/views/_switcher/_before.html.erb +5 -0
  38. data/examples/al-admin/app/views/account/login.html.erb +26 -0
  39. data/examples/al-admin/app/views/account/sign_up.html.erb +29 -0
  40. data/examples/al-admin/app/views/attributes/_attributes.html.erb +19 -0
  41. data/examples/al-admin/app/views/attributes/_detail.html.erb +29 -0
  42. data/examples/al-admin/app/views/attributes/index.html.erb +3 -0
  43. data/examples/al-admin/app/views/attributes/show.html.erb +31 -0
  44. data/examples/al-admin/app/views/directory/_tree.html.erb +10 -0
  45. data/examples/al-admin/app/views/directory/_tree_view_js.html.erb +25 -0
  46. data/examples/al-admin/app/views/directory/index.html.erb +13 -0
  47. data/examples/al-admin/app/views/directory/populate.html.erb +2 -0
  48. data/examples/al-admin/app/views/layouts/_footer.html.erb +11 -0
  49. data/examples/al-admin/app/views/layouts/_header_menu.html.erb +10 -0
  50. data/examples/al-admin/app/views/layouts/_main_menu.html.erb +18 -0
  51. data/examples/al-admin/app/views/layouts/application.html.erb +57 -0
  52. data/examples/al-admin/app/views/object_classes/_attributes.html.erb +28 -0
  53. data/examples/al-admin/app/views/object_classes/_object_classes.html.erb +19 -0
  54. data/examples/al-admin/app/views/object_classes/index.html.erb +3 -0
  55. data/examples/al-admin/app/views/object_classes/show.html.erb +39 -0
  56. data/examples/al-admin/app/views/syntaxes/_detail.html.erb +14 -0
  57. data/examples/al-admin/app/views/syntaxes/_syntaxes.html.erb +19 -0
  58. data/examples/al-admin/app/views/syntaxes/index.html.erb +3 -0
  59. data/examples/al-admin/app/views/syntaxes/show.html.erb +22 -0
  60. data/examples/al-admin/app/views/users/_attributes_update_form.html.erb +42 -0
  61. data/examples/al-admin/app/views/users/_form.html.erb +13 -0
  62. data/examples/al-admin/app/views/users/_object_classes_update_form.html.erb +46 -0
  63. data/examples/al-admin/app/views/users/_password_change_form.html.erb +20 -0
  64. data/examples/al-admin/app/views/users/edit.html.erb +15 -0
  65. data/examples/al-admin/app/views/users/index.html.erb +10 -0
  66. data/examples/al-admin/app/views/users/show.html.erb +11 -0
  67. data/examples/al-admin/app/views/welcome/index.html.erb +13 -0
  68. data/examples/al-admin/config.ru +7 -0
  69. data/examples/al-admin/config/boot.rb +110 -0
  70. data/examples/al-admin/config/database.yml.example +19 -0
  71. data/examples/al-admin/config/environment.rb +73 -0
  72. data/examples/al-admin/config/environments/development.rb +17 -0
  73. data/examples/al-admin/config/environments/production.rb +24 -0
  74. data/examples/al-admin/config/environments/test.rb +22 -0
  75. data/examples/al-admin/config/initializers/exception_notifier.rb +2 -0
  76. data/examples/al-admin/config/initializers/fast_gettext.rb +3 -0
  77. data/examples/al-admin/config/initializers/inflections.rb +10 -0
  78. data/examples/al-admin/config/initializers/mime_types.rb +5 -0
  79. data/examples/al-admin/config/initializers/session_store.rb +23 -0
  80. data/examples/al-admin/config/ldap.yml.example +21 -0
  81. data/examples/al-admin/config/routes.rb +58 -0
  82. data/examples/al-admin/db/migrate/001_create_users.rb +16 -0
  83. data/examples/al-admin/doc/README_FOR_APP +2 -0
  84. data/examples/al-admin/lib/authenticated_system.rb +124 -0
  85. data/examples/al-admin/lib/authenticated_test_helper.rb +113 -0
  86. data/examples/al-admin/lib/ldap_test_helper.rb +38 -0
  87. data/examples/al-admin/lib/tasks/testing.rake +10 -0
  88. data/examples/al-admin/po/en/al-admin.po +343 -0
  89. data/examples/al-admin/po/ja/al-admin.po +343 -0
  90. data/examples/al-admin/po/nl/al-admin.po +380 -0
  91. data/examples/al-admin/public/.htaccess +40 -0
  92. data/examples/al-admin/public/404.html +30 -0
  93. data/examples/al-admin/public/500.html +30 -0
  94. data/examples/al-admin/public/dispatch.cgi +10 -0
  95. data/examples/al-admin/public/dispatch.fcgi +24 -0
  96. data/examples/al-admin/public/dispatch.rb +10 -0
  97. data/examples/al-admin/public/favicon.ico +0 -0
  98. data/examples/al-admin/public/images/active-ldap.svg +6351 -0
  99. data/examples/al-admin/public/images/al-admin.png +0 -0
  100. data/examples/al-admin/public/images/al-admin.svg +6371 -0
  101. data/examples/al-admin/public/images/header-background.png +0 -0
  102. data/examples/al-admin/public/images/header-background.svg +99 -0
  103. data/examples/al-admin/public/images/rails.png +0 -0
  104. data/examples/al-admin/public/images/spinelz/accordion_tab_left_active.gif +0 -0
  105. data/examples/al-admin/public/images/spinelz/accordion_tab_left_inactive.gif +0 -0
  106. data/examples/al-admin/public/images/spinelz/accordion_tab_middle_active.gif +0 -0
  107. data/examples/al-admin/public/images/spinelz/accordion_tab_middle_inactive.gif +0 -0
  108. data/examples/al-admin/public/images/spinelz/accordion_tab_right_active.gif +0 -0
  109. data/examples/al-admin/public/images/spinelz/accordion_tab_right_inactive.gif +0 -0
  110. data/examples/al-admin/public/images/spinelz/balloon_back.gif +0 -0
  111. data/examples/al-admin/public/images/spinelz/balloon_bottom_left.gif +0 -0
  112. data/examples/al-admin/public/images/spinelz/balloon_bottom_middle.gif +0 -0
  113. data/examples/al-admin/public/images/spinelz/balloon_bottom_right.gif +0 -0
  114. data/examples/al-admin/public/images/spinelz/balloon_left_down_arrow.gif +0 -0
  115. data/examples/al-admin/public/images/spinelz/balloon_left_up_arrow.gif +0 -0
  116. data/examples/al-admin/public/images/spinelz/balloon_middle_left.gif +0 -0
  117. data/examples/al-admin/public/images/spinelz/balloon_middle_right.gif +0 -0
  118. data/examples/al-admin/public/images/spinelz/balloon_right_down_arrow.gif +0 -0
  119. data/examples/al-admin/public/images/spinelz/balloon_right_up_arrow.gif +0 -0
  120. data/examples/al-admin/public/images/spinelz/balloon_top_left.gif +0 -0
  121. data/examples/al-admin/public/images/spinelz/balloon_top_middle.gif +0 -0
  122. data/examples/al-admin/public/images/spinelz/balloon_top_right.gif +0 -0
  123. data/examples/al-admin/public/images/spinelz/barchart_h.gif +0 -0
  124. data/examples/al-admin/public/images/spinelz/barchart_v.gif +0 -0
  125. data/examples/al-admin/public/images/spinelz/button.gif +0 -0
  126. data/examples/al-admin/public/images/spinelz/calendar_default_handler.gif +0 -0
  127. data/examples/al-admin/public/images/spinelz/calendar_delete.gif +0 -0
  128. data/examples/al-admin/public/images/spinelz/calendar_next.gif +0 -0
  129. data/examples/al-admin/public/images/spinelz/calendar_next_second.gif +0 -0
  130. data/examples/al-admin/public/images/spinelz/calendar_pre.gif +0 -0
  131. data/examples/al-admin/public/images/spinelz/calendar_pre_second.gif +0 -0
  132. data/examples/al-admin/public/images/spinelz/calendar_private_icon.gif +0 -0
  133. data/examples/al-admin/public/images/spinelz/calendar_schedule.gif +0 -0
  134. data/examples/al-admin/public/images/spinelz/calender_back.gif +0 -0
  135. data/examples/al-admin/public/images/spinelz/calender_back_second.gif +0 -0
  136. data/examples/al-admin/public/images/spinelz/datepicker2_back.gif +0 -0
  137. data/examples/al-admin/public/images/spinelz/datepicker2_back_second.gif +0 -0
  138. data/examples/al-admin/public/images/spinelz/datepicker2_next.gif +0 -0
  139. data/examples/al-admin/public/images/spinelz/datepicker2_next_second.gif +0 -0
  140. data/examples/al-admin/public/images/spinelz/datepicker2_pre.gif +0 -0
  141. data/examples/al-admin/public/images/spinelz/datepicker2_pre_second.gif +0 -0
  142. data/examples/al-admin/public/images/spinelz/datepicker_back.gif +0 -0
  143. data/examples/al-admin/public/images/spinelz/datepicker_back_second.gif +0 -0
  144. data/examples/al-admin/public/images/spinelz/datepicker_next.gif +0 -0
  145. data/examples/al-admin/public/images/spinelz/datepicker_next_second.gif +0 -0
  146. data/examples/al-admin/public/images/spinelz/datepicker_pre.gif +0 -0
  147. data/examples/al-admin/public/images/spinelz/datepicker_pre_second.gif +0 -0
  148. data/examples/al-admin/public/images/spinelz/grid_down.gif +0 -0
  149. data/examples/al-admin/public/images/spinelz/grid_state.gif +0 -0
  150. data/examples/al-admin/public/images/spinelz/grid_up.gif +0 -0
  151. data/examples/al-admin/public/images/spinelz/icon_day.gif +0 -0
  152. data/examples/al-admin/public/images/spinelz/icon_month.gif +0 -0
  153. data/examples/al-admin/public/images/spinelz/icon_week.gif +0 -0
  154. data/examples/al-admin/public/images/spinelz/menubar_back.gif +0 -0
  155. data/examples/al-admin/public/images/spinelz/menubar_subcontents_back.gif +0 -0
  156. data/examples/al-admin/public/images/spinelz/navPanel_tab_left_active.gif +0 -0
  157. data/examples/al-admin/public/images/spinelz/navPanel_tab_left_inactive.gif +0 -0
  158. data/examples/al-admin/public/images/spinelz/navPanel_tab_middle_active.gif +0 -0
  159. data/examples/al-admin/public/images/spinelz/navPanel_tab_middle_inactive.gif +0 -0
  160. data/examples/al-admin/public/images/spinelz/navPanel_tab_right_active.gif +0 -0
  161. data/examples/al-admin/public/images/spinelz/navPanel_tab_right_inactive.gif +0 -0
  162. data/examples/al-admin/public/images/spinelz/select_date.gif +0 -0
  163. data/examples/al-admin/public/images/spinelz/selectabletable_selected.gif +0 -0
  164. data/examples/al-admin/public/images/spinelz/sideBarBox_about.gif +0 -0
  165. data/examples/al-admin/public/images/spinelz/sideBarBox_menu.gif +0 -0
  166. data/examples/al-admin/public/images/spinelz/sideBarBox_sample.gif +0 -0
  167. data/examples/al-admin/public/images/spinelz/sideBarBox_tabBottomActive.gif +0 -0
  168. data/examples/al-admin/public/images/spinelz/sideBarBox_tabBottomInactive.gif +0 -0
  169. data/examples/al-admin/public/images/spinelz/sideBarBox_tabMiddleActive.gif +0 -0
  170. data/examples/al-admin/public/images/spinelz/sideBarBox_tabMiddleActive2.gif +0 -0
  171. data/examples/al-admin/public/images/spinelz/sideBarBox_tabMiddleInactive.gif +0 -0
  172. data/examples/al-admin/public/images/spinelz/sideBarBox_tabMiddleInactive2.gif +0 -0
  173. data/examples/al-admin/public/images/spinelz/sideBarBox_tabTopActive.gif +0 -0
  174. data/examples/al-admin/public/images/spinelz/sideBarBox_tabTopInactive.gif +0 -0
  175. data/examples/al-admin/public/images/spinelz/sideBarBox_tabbar.gif +0 -0
  176. data/examples/al-admin/public/images/spinelz/sortableTable_down.gif +0 -0
  177. data/examples/al-admin/public/images/spinelz/sortableTable_normal.gif +0 -0
  178. data/examples/al-admin/public/images/spinelz/sortableTable_up.gif +0 -0
  179. data/examples/al-admin/public/images/spinelz/switcher_close.gif +0 -0
  180. data/examples/al-admin/public/images/spinelz/switcher_open.gif +0 -0
  181. data/examples/al-admin/public/images/spinelz/tabBox_close.gif +0 -0
  182. data/examples/al-admin/public/images/spinelz/tabBox_tabLeftActive.gif +0 -0
  183. data/examples/al-admin/public/images/spinelz/tabBox_tabLeftInactive.gif +0 -0
  184. data/examples/al-admin/public/images/spinelz/tabBox_tabMiddleActive.gif +0 -0
  185. data/examples/al-admin/public/images/spinelz/tabBox_tabMiddleInactive.gif +0 -0
  186. data/examples/al-admin/public/images/spinelz/tabBox_tabRightActive.gif +0 -0
  187. data/examples/al-admin/public/images/spinelz/tabBox_tabRightInactive.gif +0 -0
  188. data/examples/al-admin/public/images/spinelz/tab_bar.gif +0 -0
  189. data/examples/al-admin/public/images/spinelz/table_back.gif +0 -0
  190. data/examples/al-admin/public/images/spinelz/timepicker_clock.gif +0 -0
  191. data/examples/al-admin/public/images/spinelz/toolbar_close.gif +0 -0
  192. data/examples/al-admin/public/images/spinelz/toolbar_left.gif +0 -0
  193. data/examples/al-admin/public/images/spinelz/toolbar_max.gif +0 -0
  194. data/examples/al-admin/public/images/spinelz/toolbar_middle.gif +0 -0
  195. data/examples/al-admin/public/images/spinelz/toolbar_min.gif +0 -0
  196. data/examples/al-admin/public/images/spinelz/toolbar_next.gif +0 -0
  197. data/examples/al-admin/public/images/spinelz/toolbar_right.gif +0 -0
  198. data/examples/al-admin/public/images/spinelz/treeview_dir.gif +0 -0
  199. data/examples/al-admin/public/images/spinelz/treeview_file.gif +0 -0
  200. data/examples/al-admin/public/images/spinelz/treeview_group.gif +0 -0
  201. data/examples/al-admin/public/images/spinelz/treeview_group_special.gif +0 -0
  202. data/examples/al-admin/public/images/spinelz/treeview_state.gif +0 -0
  203. data/examples/al-admin/public/images/spinelz/treeview_user.gif +0 -0
  204. data/examples/al-admin/public/images/spinelz/window_bottom_left.gif +0 -0
  205. data/examples/al-admin/public/images/spinelz/window_bottom_middle.gif +0 -0
  206. data/examples/al-admin/public/images/spinelz/window_bottom_right.gif +0 -0
  207. data/examples/al-admin/public/images/spinelz/window_close.gif +0 -0
  208. data/examples/al-admin/public/images/spinelz/window_max.gif +0 -0
  209. data/examples/al-admin/public/images/spinelz/window_middle_left.gif +0 -0
  210. data/examples/al-admin/public/images/spinelz/window_middle_right.gif +0 -0
  211. data/examples/al-admin/public/images/spinelz/window_min.gif +0 -0
  212. data/examples/al-admin/public/images/spinelz/window_top_left.gif +0 -0
  213. data/examples/al-admin/public/images/spinelz/window_top_middle.gif +0 -0
  214. data/examples/al-admin/public/images/spinelz/window_top_right.gif +0 -0
  215. data/examples/al-admin/public/javascripts/application.js +2 -0
  216. data/examples/al-admin/public/javascripts/controls.js +963 -0
  217. data/examples/al-admin/public/javascripts/dragdrop.js +973 -0
  218. data/examples/al-admin/public/javascripts/effects.js +1128 -0
  219. data/examples/al-admin/public/javascripts/prototype.js +4320 -0
  220. data/examples/al-admin/public/javascripts/spinelz/accordion.js +185 -0
  221. data/examples/al-admin/public/javascripts/spinelz/ajaxHistory.js +157 -0
  222. data/examples/al-admin/public/javascripts/spinelz/balloon.js +287 -0
  223. data/examples/al-admin/public/javascripts/spinelz/barchart.js +524 -0
  224. data/examples/al-admin/public/javascripts/spinelz/calendar.js +3012 -0
  225. data/examples/al-admin/public/javascripts/spinelz/colorpicker.js +128 -0
  226. data/examples/al-admin/public/javascripts/spinelz/datepicker.js +438 -0
  227. data/examples/al-admin/public/javascripts/spinelz/grid.js +1391 -0
  228. data/examples/al-admin/public/javascripts/spinelz/grid_resizeEx.js +100 -0
  229. data/examples/al-admin/public/javascripts/spinelz/grid_sortabletableEx.js +129 -0
  230. data/examples/al-admin/public/javascripts/spinelz/inplaceEditorEx.js +148 -0
  231. data/examples/al-admin/public/javascripts/spinelz/menubar.js +232 -0
  232. data/examples/al-admin/public/javascripts/spinelz/navPanel.js +170 -0
  233. data/examples/al-admin/public/javascripts/spinelz/selectableTable.js +433 -0
  234. data/examples/al-admin/public/javascripts/spinelz/sideBarBox.js +282 -0
  235. data/examples/al-admin/public/javascripts/spinelz/sideBarBox_effects.js +83 -0
  236. data/examples/al-admin/public/javascripts/spinelz/sortableTable.js +270 -0
  237. data/examples/al-admin/public/javascripts/spinelz/switcher.js +78 -0
  238. data/examples/al-admin/public/javascripts/spinelz/tabBox.js +469 -0
  239. data/examples/al-admin/public/javascripts/spinelz/timepicker.js +384 -0
  240. data/examples/al-admin/public/javascripts/spinelz/toolbar.js +152 -0
  241. data/examples/al-admin/public/javascripts/spinelz/treeview.js +703 -0
  242. data/examples/al-admin/public/javascripts/spinelz/window.js +641 -0
  243. data/examples/al-admin/public/javascripts/spinelz/window_resizeEx.js +130 -0
  244. data/examples/al-admin/public/javascripts/spinelz_lib/builder.js +131 -0
  245. data/examples/al-admin/public/javascripts/spinelz_lib/controls.js +835 -0
  246. data/examples/al-admin/public/javascripts/spinelz_lib/dragdrop.js +944 -0
  247. data/examples/al-admin/public/javascripts/spinelz_lib/effects.js +1090 -0
  248. data/examples/al-admin/public/javascripts/spinelz_lib/json.js +139 -0
  249. data/examples/al-admin/public/javascripts/spinelz_lib/prototype.js +2515 -0
  250. data/examples/al-admin/public/javascripts/spinelz_lib/resize.js +215 -0
  251. data/examples/al-admin/public/javascripts/spinelz_lib/scriptaculous.js +51 -0
  252. data/examples/al-admin/public/javascripts/spinelz_lib/slider.js +278 -0
  253. data/examples/al-admin/public/javascripts/spinelz_lib/spinelz_util.js +1266 -0
  254. data/examples/al-admin/public/javascripts/spinelz_lib/unittest.js +564 -0
  255. data/examples/al-admin/public/robots.txt +1 -0
  256. data/examples/al-admin/public/stylesheets/account.css +41 -0
  257. data/examples/al-admin/public/stylesheets/attributes.css +1 -0
  258. data/examples/al-admin/public/stylesheets/base.css +104 -0
  259. data/examples/al-admin/public/stylesheets/detail.css +36 -0
  260. data/examples/al-admin/public/stylesheets/directory.css +22 -0
  261. data/examples/al-admin/public/stylesheets/object-classes.css +6 -0
  262. data/examples/al-admin/public/stylesheets/rails.css +35 -0
  263. data/examples/al-admin/public/stylesheets/spinelz/accordion.css +59 -0
  264. data/examples/al-admin/public/stylesheets/spinelz/balloon.css +151 -0
  265. data/examples/al-admin/public/stylesheets/spinelz/calendar.css +564 -0
  266. data/examples/al-admin/public/stylesheets/spinelz/datepicker.css +175 -0
  267. data/examples/al-admin/public/stylesheets/spinelz/grid.css +137 -0
  268. data/examples/al-admin/public/stylesheets/spinelz/menubar.css +78 -0
  269. data/examples/al-admin/public/stylesheets/spinelz/modal.css +22 -0
  270. data/examples/al-admin/public/stylesheets/spinelz/navPanel.css +58 -0
  271. data/examples/al-admin/public/stylesheets/spinelz/selectableTable.css +28 -0
  272. data/examples/al-admin/public/stylesheets/spinelz/sideBarBox.css +82 -0
  273. data/examples/al-admin/public/stylesheets/spinelz/sortableTable.css +51 -0
  274. data/examples/al-admin/public/stylesheets/spinelz/switcher.css +23 -0
  275. data/examples/al-admin/public/stylesheets/spinelz/tabBox.css +94 -0
  276. data/examples/al-admin/public/stylesheets/spinelz/timepicker.css +508 -0
  277. data/examples/al-admin/public/stylesheets/spinelz/toolbar.css +82 -0
  278. data/examples/al-admin/public/stylesheets/spinelz/treeview.css +121 -0
  279. data/examples/al-admin/public/stylesheets/spinelz/window.css +140 -0
  280. data/examples/al-admin/public/stylesheets/structure.css +81 -0
  281. data/examples/al-admin/public/stylesheets/syntaxes.css +1 -0
  282. data/examples/al-admin/public/stylesheets/users.css +13 -0
  283. data/examples/al-admin/public/stylesheets/welcome.css +0 -0
  284. data/examples/al-admin/script/about +3 -0
  285. data/examples/al-admin/script/console +3 -0
  286. data/examples/al-admin/script/dbconsole +3 -0
  287. data/examples/al-admin/script/destroy +3 -0
  288. data/examples/al-admin/script/generate +3 -0
  289. data/examples/al-admin/script/performance/benchmarker +3 -0
  290. data/examples/al-admin/script/performance/profiler +3 -0
  291. data/examples/al-admin/script/performance/request +3 -0
  292. data/examples/al-admin/script/plugin +3 -0
  293. data/examples/al-admin/script/process/inspector +3 -0
  294. data/examples/al-admin/script/process/reaper +3 -0
  295. data/examples/al-admin/script/process/spawner +3 -0
  296. data/examples/al-admin/script/runner +3 -0
  297. data/examples/al-admin/script/server +3 -0
  298. data/examples/al-admin/test/fixtures/users.yml +9 -0
  299. data/examples/al-admin/test/functional/account_controller_test.rb +12 -0
  300. data/examples/al-admin/test/functional/attributes_controller_test.rb +8 -0
  301. data/examples/al-admin/test/functional/directory_controller_test.rb +8 -0
  302. data/examples/al-admin/test/functional/object_classes_controller_test.rb +8 -0
  303. data/examples/al-admin/test/functional/syntaxes_controller_test.rb +8 -0
  304. data/examples/al-admin/test/functional/users_controller_test.rb +8 -0
  305. data/examples/al-admin/test/functional/welcome_controller_test.rb +8 -0
  306. data/examples/al-admin/test/integration/sign_up_test.rb +44 -0
  307. data/examples/al-admin/test/run-test.sh +3 -0
  308. data/examples/al-admin/test/test_helper.rb +52 -0
  309. data/examples/al-admin/test/unit/user_test.rb +12 -0
  310. data/examples/al-admin/vendor/plugins/exception_notification/README +111 -0
  311. data/examples/al-admin/vendor/plugins/exception_notification/init.rb +1 -0
  312. data/examples/al-admin/vendor/plugins/exception_notification/lib/exception_notifiable.rb +99 -0
  313. data/examples/al-admin/vendor/plugins/exception_notification/lib/exception_notifier.rb +66 -0
  314. data/examples/al-admin/vendor/plugins/exception_notification/lib/exception_notifier_helper.rb +78 -0
  315. data/examples/al-admin/vendor/plugins/exception_notification/test/exception_notifier_helper_test.rb +61 -0
  316. data/examples/al-admin/vendor/plugins/exception_notification/test/test_helper.rb +7 -0
  317. data/examples/al-admin/vendor/plugins/exception_notification/views/exception_notifier/_backtrace.rhtml +1 -0
  318. data/examples/al-admin/vendor/plugins/exception_notification/views/exception_notifier/_environment.rhtml +7 -0
  319. data/examples/al-admin/vendor/plugins/exception_notification/views/exception_notifier/_inspect_model.rhtml +16 -0
  320. data/examples/al-admin/vendor/plugins/exception_notification/views/exception_notifier/_request.rhtml +4 -0
  321. data/examples/al-admin/vendor/plugins/exception_notification/views/exception_notifier/_session.rhtml +2 -0
  322. data/examples/al-admin/vendor/plugins/exception_notification/views/exception_notifier/_title.rhtml +3 -0
  323. data/examples/al-admin/vendor/plugins/exception_notification/views/exception_notifier/exception_notification.rhtml +6 -0
  324. data/examples/config.yaml.example +5 -0
  325. data/examples/example.der +0 -0
  326. data/examples/example.jpg +0 -0
  327. data/examples/groupadd +41 -0
  328. data/examples/groupdel +35 -0
  329. data/examples/groupls +49 -0
  330. data/examples/groupmod +42 -0
  331. data/examples/lpasswd +55 -0
  332. data/examples/objects/group.rb +13 -0
  333. data/examples/objects/ou.rb +4 -0
  334. data/examples/objects/user.rb +20 -0
  335. data/examples/ouadd +38 -0
  336. data/examples/useradd +45 -0
  337. data/examples/useradd-binary +53 -0
  338. data/examples/userdel +34 -0
  339. data/examples/userls +50 -0
  340. data/examples/usermod +42 -0
  341. data/examples/usermod-binary-add +50 -0
  342. data/examples/usermod-binary-add-time +54 -0
  343. data/examples/usermod-binary-del +48 -0
  344. data/examples/usermod-lang-add +43 -0
  345. data/lib/active_ldap.rb +105 -0
  346. data/lib/active_ldap/action_controller/ldap_benchmarking.rb +55 -0
  347. data/lib/active_ldap/acts/tree.rb +75 -0
  348. data/lib/active_ldap/adapter/base.rb +705 -0
  349. data/lib/active_ldap/adapter/jndi.rb +184 -0
  350. data/lib/active_ldap/adapter/jndi_connection.rb +185 -0
  351. data/lib/active_ldap/adapter/ldap.rb +290 -0
  352. data/lib/active_ldap/adapter/ldap_ext.rb +105 -0
  353. data/lib/active_ldap/adapter/net_ldap.rb +309 -0
  354. data/lib/active_ldap/adapter/net_ldap_ext.rb +23 -0
  355. data/lib/active_ldap/association/belongs_to.rb +47 -0
  356. data/lib/active_ldap/association/belongs_to_many.rb +58 -0
  357. data/lib/active_ldap/association/children.rb +21 -0
  358. data/lib/active_ldap/association/collection.rb +105 -0
  359. data/lib/active_ldap/association/has_many.rb +31 -0
  360. data/lib/active_ldap/association/has_many_utils.rb +44 -0
  361. data/lib/active_ldap/association/has_many_wrap.rb +62 -0
  362. data/lib/active_ldap/association/proxy.rb +107 -0
  363. data/lib/active_ldap/associations.rb +202 -0
  364. data/lib/active_ldap/attributes.rb +184 -0
  365. data/lib/active_ldap/base.rb +1594 -0
  366. data/lib/active_ldap/callbacks.rb +52 -0
  367. data/lib/active_ldap/command.rb +49 -0
  368. data/lib/active_ldap/compatible.rb +44 -0
  369. data/lib/active_ldap/configuration.rb +147 -0
  370. data/lib/active_ldap/connection.rb +294 -0
  371. data/lib/active_ldap/distinguished_name.rb +291 -0
  372. data/lib/active_ldap/entry_attribute.rb +78 -0
  373. data/lib/active_ldap/escape.rb +12 -0
  374. data/lib/active_ldap/get_text.rb +9 -0
  375. data/lib/active_ldap/get_text/parser.rb +161 -0
  376. data/lib/active_ldap/get_text_fallback.rb +60 -0
  377. data/lib/active_ldap/get_text_support.rb +20 -0
  378. data/lib/active_ldap/helper.rb +92 -0
  379. data/lib/active_ldap/human_readable.rb +132 -0
  380. data/lib/active_ldap/ldap_error.rb +74 -0
  381. data/lib/active_ldap/ldif.rb +930 -0
  382. data/lib/active_ldap/object_class.rb +95 -0
  383. data/lib/active_ldap/operations.rb +610 -0
  384. data/lib/active_ldap/populate.rb +53 -0
  385. data/lib/active_ldap/railtie.rb +31 -0
  386. data/lib/active_ldap/schema.rb +699 -0
  387. data/lib/active_ldap/schema/syntaxes.rb +417 -0
  388. data/lib/active_ldap/timeout.rb +75 -0
  389. data/lib/active_ldap/timeout_stub.rb +17 -0
  390. data/lib/active_ldap/user_password.rb +92 -0
  391. data/lib/active_ldap/validations.rb +229 -0
  392. data/lib/active_ldap/xml.rb +122 -0
  393. data/po/en/active-ldap.po +4029 -0
  394. data/po/ja/active-ldap.po +4060 -0
  395. data/rails_generators/model_active_ldap/USAGE +17 -0
  396. data/rails_generators/model_active_ldap/model_active_ldap_generator.rb +69 -0
  397. data/rails_generators/model_active_ldap/templates/model_active_ldap.rb +3 -0
  398. data/rails_generators/model_active_ldap/templates/unit_test.rb +8 -0
  399. data/rails_generators/scaffold_active_ldap/scaffold_active_ldap_generator.rb +7 -0
  400. data/rails_generators/scaffold_active_ldap/templates/ldap.yml +18 -0
  401. data/test/al-test-utils.rb +439 -0
  402. data/test/command.rb +112 -0
  403. data/test/config.yaml.sample +6 -0
  404. data/test/fixtures/lower_case_object_class_schema.rb +802 -0
  405. data/test/run-test.rb +44 -0
  406. data/test/test_acts_as_tree.rb +60 -0
  407. data/test/test_adapter.rb +121 -0
  408. data/test/test_associations.rb +664 -0
  409. data/test/test_attributes.rb +117 -0
  410. data/test/test_base.rb +1177 -0
  411. data/test/test_base_per_instance.rb +61 -0
  412. data/test/test_bind.rb +62 -0
  413. data/test/test_callback.rb +37 -0
  414. data/test/test_configuration.rb +40 -0
  415. data/test/test_connection.rb +82 -0
  416. data/test/test_connection_per_class.rb +112 -0
  417. data/test/test_connection_per_dn.rb +112 -0
  418. data/test/test_dn.rb +172 -0
  419. data/test/test_find.rb +176 -0
  420. data/test/test_groupadd.rb +50 -0
  421. data/test/test_groupdel.rb +46 -0
  422. data/test/test_groupls.rb +107 -0
  423. data/test/test_groupmod.rb +51 -0
  424. data/test/test_ldif.rb +1891 -0
  425. data/test/test_load.rb +133 -0
  426. data/test/test_lpasswd.rb +75 -0
  427. data/test/test_object_class.rb +74 -0
  428. data/test/test_reflection.rb +182 -0
  429. data/test/test_schema.rb +559 -0
  430. data/test/test_syntax.rb +383 -0
  431. data/test/test_user.rb +217 -0
  432. data/test/test_user_password.rb +101 -0
  433. data/test/test_useradd-binary.rb +62 -0
  434. data/test/test_useradd.rb +57 -0
  435. data/test/test_userdel.rb +48 -0
  436. data/test/test_userls.rb +91 -0
  437. data/test/test_usermod-binary-add-time.rb +65 -0
  438. data/test/test_usermod-binary-add.rb +64 -0
  439. data/test/test_usermod-binary-del.rb +66 -0
  440. data/test/test_usermod-lang-add.rb +60 -0
  441. data/test/test_usermod.rb +58 -0
  442. data/test/test_validation.rb +274 -0
  443. metadata +502 -0
@@ -0,0 +1,51 @@
1
+ require 'al-test-utils'
2
+
3
+ class TestGroupmod < Test::Unit::TestCase
4
+ include AlTestUtils
5
+
6
+ def setup
7
+ super
8
+ @command = File.join(@examples_dir, "groupmod")
9
+ end
10
+
11
+ priority :must
12
+
13
+ priority :normal
14
+ def test_non_exist_group
15
+ ensure_delete_group("test-group") do |name|
16
+ assert(!@group_class.exists?(name))
17
+ assert_equal([false, "Group #{name} doesn't exist.\n"],
18
+ run_command(name, 111111))
19
+ assert(!@group_class.exists?(name))
20
+ end
21
+ end
22
+
23
+ def test_modify_group
24
+ make_temporary_group do |group|
25
+ assert_groupmod_successfully(group.cn, group.gid_number.succ)
26
+ end
27
+ end
28
+
29
+ private
30
+ def assert_groupmod_successfully(name, gid, *args, &block)
31
+ _wrap_assertion do
32
+ assert(@group_class.exists?(name))
33
+ args.concat([name, gid])
34
+ assert_equal([true, ""], run_command(*args, &block))
35
+ assert(@group_class.exists?(name))
36
+
37
+ group = @group_class.find(name)
38
+ assert_equal(name, group.cn)
39
+ assert_equal(gid, group.gid_number)
40
+ end
41
+ end
42
+
43
+ def assert_groupmod_failed(name, gid, message, *args, &block)
44
+ _wrap_assertion do
45
+ assert(@group_class.exists?(name))
46
+ args.concat([name, gid])
47
+ assert_equal([false, message], run_command(*args, &block))
48
+ assert(@group_class.exists?(name))
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,1891 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'al-test-utils'
4
+
5
+ class TestLDIF < Test::Unit::TestCase
6
+ include ActiveLdap::GetTextSupport
7
+ include AlTestUtils::Assertions
8
+ include AlTestUtils::Config
9
+ include AlTestUtils::ExampleFile
10
+
11
+ priority :must
12
+ def test_integer_attribute_value_to_s
13
+ dn = ActiveLdap::DN.parse("uid=user,ou=People,dc=example,dc=com")
14
+ record = ActiveLdap::Ldif::Record.new(dn, {"uidNumber" => [100]})
15
+ assert_equal(<<-EOL, record.to_s)
16
+ dn: uid=user,ou=People,dc=example,dc=com
17
+ uidNumber: 100
18
+ EOL
19
+ end
20
+
21
+ priority :normal
22
+ def test_accept_empty_lines_after_content
23
+ ldif_source = <<-EOL
24
+ version: 1
25
+ dn: dc=devel,dc=example,dc=com
26
+ dc: devel
27
+ objectClass: top
28
+ objectClass: dcObject
29
+ objectClass: organization
30
+ o: devel
31
+ EOL
32
+
33
+ expected_ldif_to_s = <<-EOL
34
+ version: 1
35
+ dn: dc=devel,dc=example,dc=com
36
+ dc: devel
37
+ o: devel
38
+ objectClass: dcObject
39
+ objectClass: organization
40
+ objectClass: top
41
+ EOL
42
+
43
+
44
+ assert_ldif_to_s(expected_ldif_to_s, ldif_source)
45
+ assert_ldif_to_s(expected_ldif_to_s, ldif_source + "\n")
46
+ assert_ldif_to_s(expected_ldif_to_s, ldif_source + "\n\n")
47
+ assert_ldif_to_s(expected_ldif_to_s, ldif_source + ("\n" * 10))
48
+ end
49
+
50
+ def test_accept_comments_after_content
51
+ ldif_source = <<-EOL
52
+ version: 1
53
+ dn: dc=devel,dc=example,dc=com
54
+ dc: devel
55
+ objectClass: top
56
+ objectClass: dcObject
57
+ objectClass: organization
58
+ o: devel
59
+
60
+ # search result
61
+
62
+ # numResponse: 1
63
+ # numEntries: 1
64
+
65
+ EOL
66
+
67
+ assert_ldif_to_s(<<-EOL, ldif_source)
68
+ version: 1
69
+ dn: dc=devel,dc=example,dc=com
70
+ dc: devel
71
+ o: devel
72
+ objectClass: dcObject
73
+ objectClass: organization
74
+ objectClass: top
75
+ EOL
76
+ end
77
+
78
+ def test_comments_and_empty_lines_before_content
79
+ ldif_source = <<-EOL
80
+ version: 1
81
+
82
+ #
83
+ # LDAPv3
84
+ # base <dc=devel,dc=clear-code,dc=com> with scope subtree
85
+ # filter: (objectclass=*)
86
+ # requesting: ALL
87
+ #
88
+
89
+ # devel.example.com
90
+ dn: dc=devel,dc=example,dc=com
91
+ dc: devel
92
+ objectClass: top
93
+ objectClass: dcObject
94
+ objectClass: organization
95
+ o: devel
96
+ EOL
97
+
98
+ assert_ldif_to_s(<<-EOL, ldif_source)
99
+ version: 1
100
+ dn: dc=devel,dc=example,dc=com
101
+ dc: devel
102
+ o: devel
103
+ objectClass: dcObject
104
+ objectClass: organization
105
+ objectClass: top
106
+ EOL
107
+ end
108
+
109
+ def test_unknown_change_type
110
+ ldif_source = <<-EOL
111
+ version: 1
112
+ dn: ou=Product Development, dc=airius, dc=com
113
+ changetype: XXX
114
+ EOL
115
+
116
+ ldif_source_with_error_mark = <<-EOL
117
+ changetype: |@|XXX
118
+ EOL
119
+
120
+ assert_invalid_ldif(["unknown change type: %s", "XXX"],
121
+ ldif_source, 3, 13, ldif_source_with_error_mark)
122
+ end
123
+
124
+ def test_unknown_modify_type
125
+ ldif_source = <<-EOL
126
+ version: 1
127
+ dn: ou=Product Development, dc=airius, dc=com
128
+ changetype: modify
129
+ XXX: postaladdress
130
+ -
131
+ EOL
132
+
133
+ ldif_source_with_error_mark = <<-EOL
134
+ |@|XXX: postaladdress
135
+ EOL
136
+
137
+ assert_invalid_ldif(["unknown modify type: %s", "XXX"],
138
+ ldif_source, 4, 1, ldif_source_with_error_mark)
139
+ end
140
+
141
+ def test_modify_spec_block_separator_is_missing
142
+ ldif_source = <<-EOL
143
+ version: 1
144
+ dn: ou=Product Development, dc=airius, dc=com
145
+ changetype: modify
146
+ add: postaladdress
147
+ EOL
148
+
149
+ ldif_source_with_error_mark = <<-EOL.chomp
150
+ add: postaladdress
151
+ |@|
152
+ EOL
153
+
154
+ assert_invalid_ldif("'-' is missing",
155
+ ldif_source, 5, 1, ldif_source_with_error_mark)
156
+ end
157
+
158
+ def test_modify_spec_first_line_separator_is_missing
159
+ ldif_source = <<-EOL.chomp
160
+ version: 1
161
+ dn: ou=Product Development, dc=airius, dc=com
162
+ changetype: modify
163
+ add: postaladdress
164
+ EOL
165
+
166
+ ldif_source_with_error_mark = <<-EOL.chomp
167
+ add: postaladdress|@|
168
+ EOL
169
+
170
+ assert_invalid_ldif("separator is missing",
171
+ ldif_source, 4, 19, ldif_source_with_error_mark)
172
+ end
173
+
174
+ def test_modify_target_attribute_name_is_missing
175
+ ldif_source = <<-EOL
176
+ version: 1
177
+ dn: ou=Product Development, dc=airius, dc=com
178
+ changetype: modify
179
+ add:
180
+ -
181
+ EOL
182
+
183
+ ldif_source_with_error_mark = <<-EOL
184
+ add:|@|
185
+ EOL
186
+
187
+ assert_invalid_ldif("attribute type is missing",
188
+ ldif_source, 4, 5, ldif_source_with_error_mark)
189
+ end
190
+
191
+ def test_newsuperior_separator_is_missing
192
+ ldif_source = <<-EOL.chomp
193
+ version: 1
194
+ dn: ou=Product Development, dc=airius, dc=com
195
+ changetype: moddn
196
+ newrdn: cn=Paula Jensen
197
+ deleteoldrdn: 1
198
+ newsuperior: ou=Accounting, dc=airius, dc=com
199
+ EOL
200
+
201
+ ldif_source_with_error_mark = <<-EOL.chomp
202
+ newsuperior: ou=Accounting, dc=airius, dc=com|@|
203
+ EOL
204
+
205
+ assert_invalid_ldif("separator is missing",
206
+ ldif_source, 6, 46, ldif_source_with_error_mark)
207
+ end
208
+
209
+ def test_newsuperior_value_is_missing
210
+ ldif_source = <<-EOL
211
+ version: 1
212
+ dn: ou=Product Development, dc=airius, dc=com
213
+ changetype: moddn
214
+ newrdn: cn=Paula Jensen
215
+ deleteoldrdn: 1
216
+ newsuperior:
217
+ EOL
218
+
219
+ ldif_source_with_error_mark = <<-EOL
220
+ newsuperior:|@|
221
+ EOL
222
+
223
+ assert_invalid_ldif("new superior value is missing",
224
+ ldif_source, 6, 13, ldif_source_with_error_mark)
225
+ end
226
+
227
+ def test_deleteoldrdn_separator_is_missing
228
+ ldif_source = <<-EOL.chomp
229
+ version: 1
230
+ dn: ou=Product Development, dc=airius, dc=com
231
+ changetype: moddn
232
+ newrdn: cn=Paula Jensen
233
+ deleteoldrdn: 1
234
+ EOL
235
+
236
+ ldif_source_with_error_mark = <<-EOL.chomp
237
+ deleteoldrdn: 1|@|
238
+ EOL
239
+
240
+ assert_invalid_ldif("separator is missing",
241
+ ldif_source, 5, 16, ldif_source_with_error_mark)
242
+ end
243
+
244
+ def test_invalid_deleteoldrdn_value
245
+ ldif_source = <<-EOL
246
+ version: 1
247
+ dn: ou=Product Development, dc=airius, dc=com
248
+ changetype: moddn
249
+ newrdn: cn=Paula Jensen
250
+ deleteoldrdn: x
251
+ EOL
252
+
253
+ ldif_source_with_error_mark = <<-EOL
254
+ deleteoldrdn: |@|x
255
+ EOL
256
+
257
+ assert_invalid_ldif("delete old RDN value is missing",
258
+ ldif_source, 5, 15, ldif_source_with_error_mark)
259
+ end
260
+
261
+ def test_deleteoldrdn_value_is_missing
262
+ ldif_source = <<-EOL
263
+ version: 1
264
+ dn: ou=Product Development, dc=airius, dc=com
265
+ changetype: moddn
266
+ newrdn: cn=Paula Jensen
267
+ deleteoldrdn:
268
+ EOL
269
+
270
+ ldif_source_with_error_mark = <<-EOL
271
+ deleteoldrdn:|@|
272
+ EOL
273
+
274
+ assert_invalid_ldif("delete old RDN value is missing",
275
+ ldif_source, 5, 14, ldif_source_with_error_mark)
276
+ end
277
+
278
+ def test_deleteoldrdn_mark_is_missing
279
+ ldif_source = <<-EOL
280
+ version: 1
281
+ dn: ou=Product Development, dc=airius, dc=com
282
+ changetype: moddn
283
+ newrdn: cn=Paula Jensen
284
+ EOL
285
+
286
+ ldif_source_with_error_mark = <<-EOL.chomp
287
+ newrdn: cn=Paula Jensen
288
+ |@|
289
+ EOL
290
+
291
+ assert_invalid_ldif("'deleteoldrdn:' is missing",
292
+ ldif_source, 5, 1, ldif_source_with_error_mark)
293
+ end
294
+
295
+ def test_newrdn_separator_is_missing
296
+ ldif_source = <<-EOL.chomp
297
+ version: 1
298
+ dn: ou=Product Development, dc=airius, dc=com
299
+ changetype: moddn
300
+ newrdn: cn=Paula Jensen
301
+ EOL
302
+
303
+ ldif_source_with_error_mark = <<-EOL.chomp
304
+ newrdn: cn=Paula Jensen|@|
305
+ EOL
306
+
307
+ assert_invalid_ldif("separator is missing",
308
+ ldif_source, 4, 24, ldif_source_with_error_mark)
309
+ end
310
+
311
+ def test_newrdn_value_is_missing
312
+ ldif_source = <<-EOL
313
+ version: 1
314
+ dn: ou=Product Development, dc=airius, dc=com
315
+ changetype: moddn
316
+ newrdn:
317
+ EOL
318
+
319
+ ldif_source_with_error_mark = <<-EOL
320
+ newrdn:|@|
321
+ EOL
322
+
323
+ assert_invalid_ldif("new RDN value is missing",
324
+ ldif_source, 4, 8, ldif_source_with_error_mark)
325
+ end
326
+
327
+ def test_newrdn_mark_is_missing
328
+ ldif_source = <<-EOL
329
+ version: 1
330
+ dn: ou=Product Development, dc=airius, dc=com
331
+ changetype: moddn
332
+ EOL
333
+
334
+ ldif_source_with_error_mark = <<-EOL.chomp
335
+ changetype: moddn
336
+ |@|
337
+ EOL
338
+
339
+ assert_invalid_ldif("'newrdn:' is missing",
340
+ ldif_source, 4, 1, ldif_source_with_error_mark)
341
+ end
342
+
343
+ def test_add_change_type_without_attribute
344
+ ldif_source = <<-EOL
345
+ version: 1
346
+ dn: ou=Product Development, dc=airius, dc=com
347
+ changetype: add
348
+ EOL
349
+
350
+ ldif_source_with_error_mark = <<-EOL.chomp
351
+ changetype: add
352
+ |@|
353
+ EOL
354
+
355
+ assert_invalid_ldif("attribute spec is missing",
356
+ ldif_source, 4, 1, ldif_source_with_error_mark)
357
+ end
358
+
359
+ def test_change_type_with_an_extra_space
360
+ ldif_source = <<-EOL
361
+ version: 1
362
+ dn: ou=Product Development, dc=airius, dc=com
363
+ changetype: delete
364
+ EOL
365
+
366
+ ldif_source_with_error_mark = <<-EOL
367
+ changetype: delete|@|
368
+ EOL
369
+
370
+ assert_invalid_ldif("separator is missing",
371
+ ldif_source, 3, 19, ldif_source_with_error_mark)
372
+ end
373
+
374
+ def test_change_type_separator_is_missing
375
+ ldif_source = <<-EOL.chomp
376
+ version: 1
377
+ dn: ou=Product Development, dc=airius, dc=com
378
+ changetype: delete
379
+ EOL
380
+
381
+ ldif_source_with_error_mark = <<-EOL.chomp
382
+ changetype: delete|@|
383
+ EOL
384
+
385
+ assert_invalid_ldif("separator is missing",
386
+ ldif_source, 3, 19, ldif_source_with_error_mark)
387
+ end
388
+
389
+ def test_change_type_value_is_missing
390
+ ldif_source = <<-EOL
391
+ version: 1
392
+ dn: ou=Product Development, dc=airius, dc=com
393
+ changetype:
394
+ EOL
395
+
396
+ ldif_source_with_error_mark = <<-EOL
397
+ changetype:|@|
398
+ EOL
399
+
400
+ assert_invalid_ldif("change type value is missing",
401
+ ldif_source, 3, 12, ldif_source_with_error_mark)
402
+ end
403
+
404
+ def test_control_separator_is_missing
405
+ ldif_source = <<-EOL.chomp
406
+ version: 1
407
+ dn: ou=Product Development, dc=airius, dc=com
408
+ control: 1.2.840.113556.1.4.805 true
409
+ EOL
410
+
411
+ ldif_source_with_error_mark = <<-EOL.chomp
412
+ control: 1.2.840.113556.1.4.805 true|@|
413
+ EOL
414
+
415
+ assert_invalid_ldif("separator is missing",
416
+ ldif_source, 3, 37, ldif_source_with_error_mark)
417
+ end
418
+
419
+ def test_criticality_is_missing
420
+ ldif_source = <<-EOL
421
+ version: 1
422
+ dn: ou=Product Development, dc=airius, dc=com
423
+ control: 1.2.840.113556.1.4.805
424
+ EOL
425
+
426
+ ldif_source_with_error_mark = <<-EOL
427
+ control: 1.2.840.113556.1.4.805 |@|
428
+ EOL
429
+
430
+ assert_invalid_ldif("criticality is missing",
431
+ ldif_source, 3, 33, ldif_source_with_error_mark)
432
+ end
433
+
434
+ def test_control_type_is_missing
435
+ ldif_source = <<-EOL
436
+ version: 1
437
+ dn: ou=Product Development, dc=airius, dc=com
438
+ control:
439
+ EOL
440
+
441
+ ldif_source_with_error_mark = <<-EOL
442
+ control:|@|
443
+ EOL
444
+
445
+ assert_invalid_ldif("control type is missing",
446
+ ldif_source, 3, 9, ldif_source_with_error_mark)
447
+ end
448
+
449
+ def test_change_type_is_missing
450
+ ldif_source = <<-EOL
451
+ version: 1
452
+ dn: ou=Product Development, dc=airius, dc=com
453
+ control: 1.2.840.113556.1.4.805 true
454
+ EOL
455
+
456
+ ldif_source_with_error_mark = <<-EOL.chomp
457
+ control: 1.2.840.113556.1.4.805 true
458
+ |@|
459
+ EOL
460
+
461
+ assert_invalid_ldif("change type is missing",
462
+ ldif_source, 4, 1, ldif_source_with_error_mark)
463
+ end
464
+
465
+ def test_invalid_dn
466
+ ldif_source = <<-EOL
467
+ version: 1
468
+ dn: ou=o=Airius
469
+ EOL
470
+
471
+ ldif_source_with_error_mark = <<-EOL
472
+ dn: ou=o=Airius|@|
473
+ EOL
474
+
475
+ assert_invalid_ldif(["DN is invalid: %s: %s",
476
+ "ou=o=Airius", "attribute type is missing"],
477
+ ldif_source, 2, 16, ldif_source_with_error_mark)
478
+ end
479
+
480
+ def test_invalid_dn_value
481
+ ldif_source = <<-EOL
482
+ version: 1
483
+ # dn:: ou=<JapaneseOU>,o=Airius
484
+ dn: ou=営業部,o=Airius
485
+ EOL
486
+
487
+ ldif_source_with_error_mark = <<-EOL
488
+ dn: ou=|@|営業部,o=Airius
489
+ EOL
490
+
491
+ assert_invalid_ldif(["DN has an invalid character: %s", "営"],
492
+ ldif_source, 3, 8, ldif_source_with_error_mark)
493
+ end
494
+
495
+ def test_multi_records_without_separator
496
+ ldif_source = <<-EOL
497
+ version: 1
498
+ dn: ou=Product Development, dc=airius, dc=com
499
+ changetype: delete
500
+ dn: cn=Fiona Jensen, ou=Marketing, dc=airius, dc=com
501
+ seealso:
502
+ description::
503
+ EOL
504
+
505
+ ldif_source_with_error_mark = <<-EOL
506
+ |@|dn: cn=Fiona Jensen, ou=Marketing, dc=airius, dc=com
507
+ EOL
508
+
509
+ assert_invalid_ldif("separator is missing", ldif_source,
510
+ 4, 1, ldif_source_with_error_mark)
511
+ end
512
+
513
+ def test_to_s_with_blank_value
514
+ ldif_source = <<-EOL
515
+ version: 1
516
+ dn: ou=Product Development,dc=airius,dc=com
517
+ seealso:
518
+ description::
519
+ EOL
520
+
521
+ assert_ldif_to_s(<<-EOL, ldif_source)
522
+ version: 1
523
+ dn: ou=Product Development,dc=airius,dc=com
524
+ description:
525
+ seealso:
526
+ EOL
527
+ end
528
+
529
+ def test_to_s_with_last_space
530
+ ldif_source = <<-EOL
531
+ version: 1
532
+ # 'ou=Product Development,dc=airius,dc=com '
533
+ dn:: b3U9UHJvZHVjdCBEZXZlbG9wbWVudCwgZGM9YWlyaXVzLCBkYz1jb20g
534
+ # 'ou=Product Development,dc=airius,dc=com '
535
+ description:: b3U9UHJvZHVjdCBEZXZlbG9wbWVudCwgZGM9YWlyaXVzLCBkYz1jb20g
536
+ EOL
537
+
538
+ assert_ldif_to_s(<<-EOL, ldif_source)
539
+ version: 1
540
+ dn: ou=Product Development,dc=airius,dc="com "
541
+ description:: b3U9UHJvZHVjdCBEZXZlbG9wbWVudCwgZGM9YWlyaXVzLCBkYz1jb20g
542
+ EOL
543
+ end
544
+
545
+ def test_change_record_with_control
546
+ ldif_source = <<-EOL
547
+ version: 1
548
+ # Delete an entry. The operation will attach the LDAPv3
549
+ # Tree Delete Control defined in [9]. The criticality
550
+ # field is "true" and the controlValue field is
551
+ # absent, as required by [9].
552
+ dn: ou=Product Development, dc=airius, dc=com
553
+ control: 1.2.840.113556.1.4.805 true
554
+ changetype: delete
555
+ EOL
556
+
557
+ change_attributes = {
558
+ "dn" => "ou=Product Development,dc=airius,dc=com",
559
+ }
560
+
561
+ ldif = assert_ldif(1, [change_attributes], ldif_source)
562
+ record = ldif.records[0]
563
+ assert_equal("delete", record.change_type)
564
+ assert_true(record.delete?)
565
+ assert_equal([{
566
+ :type => "1.2.840.113556.1.4.805",
567
+ :criticality => true,
568
+ :value => nil
569
+ }],
570
+ record.controls.collect {|control| control.to_hash})
571
+
572
+ control = record.controls[0]
573
+ assert_equal("1.2.840.113556.1.4.805", control.type)
574
+ assert_true(control.criticality?)
575
+ assert_nil(control.value)
576
+ end
577
+
578
+ def test_change_record_with_control_to_s
579
+ ldif_source = <<-EOL
580
+ version: 1
581
+ # Delete an entry. The operation will attach the LDAPv3
582
+ # Tree Delete Control defined in [9]. The criticality
583
+ # field is "true" and the controlValue field is
584
+ # absent, as required by [9].
585
+ dn: ou=Product Development, dc=airius, dc=com
586
+ control: 1.2.840.113556.1.4.805 true
587
+ changetype: delete
588
+ EOL
589
+
590
+ assert_ldif_to_s(<<-EOL, ldif_source)
591
+ version: 1
592
+ dn: ou=Product Development,dc=airius,dc=com
593
+ control: 1.2.840.113556.1.4.805 true
594
+ changetype: delete
595
+ EOL
596
+ end
597
+
598
+ def test_multi_change_type_records
599
+ ldif_source = <<-EOL
600
+ version: 1
601
+ # Add a new entry
602
+ dn: cn=Fiona Jensen, ou=Marketing, dc=airius, dc=com
603
+ changetype: add
604
+ objectclass: top
605
+ objectclass: person
606
+ objectclass: organizationalPerson
607
+ cn: Fiona Jensen
608
+ sn: Jensen
609
+ uid: fiona
610
+ telephonenumber: +1 408 555 1212
611
+
612
+ # Delete an existing entry
613
+ dn: cn=Robert Jensen, ou=Marketing, dc=airius, dc=com
614
+ changetype: delete
615
+
616
+ # Modify an entry's relative distinguished name
617
+ dn: cn=Paul Jensen, ou=Product Development, dc=airius, dc=com
618
+ changetype: modrdn
619
+ newrdn: cn=Paula Jensen
620
+ deleteoldrdn: 1
621
+
622
+ # Rename an entry and move all of its children to a new location in
623
+ # the directory tree (only implemented by LDAPv3 servers).
624
+ dn: ou=PD Accountants, ou=Product Development, dc=airius, dc=com
625
+ changetype: modrdn
626
+ newrdn: ou=Product Development Accountants
627
+ deleteoldrdn: 0
628
+ newsuperior: ou=Accounting, dc=airius, dc=com
629
+
630
+ # Modify an entry: add an additional value to the postaladdress
631
+ # attribute, completely delete the description attribute, replace
632
+ # the telephonenumber attribute with two values, and delete a specific
633
+ # value from the facsimiletelephonenumber attribute
634
+ dn: cn=Paula Jensen, ou=Product Development, dc=airius, dc=com
635
+ changetype: modify
636
+ add: postaladdress
637
+ postaladdress: 123 Anystreet $ Sunnyvale, CA $ 94086
638
+ -
639
+ delete: description
640
+ -
641
+ replace: telephonenumber
642
+ telephonenumber: +1 408 555 1234
643
+ telephonenumber: +1 408 555 5678
644
+ -
645
+ delete: facsimiletelephonenumber
646
+ facsimiletelephonenumber: +1 408 555 9876
647
+ -
648
+
649
+ # Modify an entry: replace the postaladdress attribute with an empty
650
+ # set of values (which will cause the attribute to be removed), and
651
+ # delete the entire description attribute. Note that the first will
652
+ # always succeed, while the second will only succeed if at least
653
+ # one value for the description attribute is present.
654
+ dn: cn=Ingrid Jensen, ou=Product Support, dc=airius, dc=com
655
+ changetype: modify
656
+ replace: postaladdress
657
+ -
658
+ delete: description
659
+ -
660
+ EOL
661
+
662
+ assert_ldif_to_s(<<-EOL, ldif_source)
663
+ version: 1
664
+ dn: cn=Fiona Jensen,ou=Marketing,dc=airius,dc=com
665
+ changetype: add
666
+ cn: Fiona Jensen
667
+ objectclass: organizationalPerson
668
+ objectclass: person
669
+ objectclass: top
670
+ sn: Jensen
671
+ telephonenumber: +1 408 555 1212
672
+ uid: fiona
673
+
674
+ dn: cn=Robert Jensen,ou=Marketing,dc=airius,dc=com
675
+ changetype: delete
676
+
677
+ dn: cn=Paul Jensen,ou=Product Development,dc=airius,dc=com
678
+ changetype: modrdn
679
+ newrdn: cn=Paula Jensen
680
+ deleteoldrdn: 1
681
+
682
+ dn: ou=PD Accountants,ou=Product Development,dc=airius,dc=com
683
+ changetype: modrdn
684
+ newrdn: ou=Product Development Accountants
685
+ deleteoldrdn: 0
686
+ newsuperior: ou=Accounting,dc=airius,dc=com
687
+
688
+ dn: cn=Paula Jensen,ou=Product Development,dc=airius,dc=com
689
+ changetype: modify
690
+ add: postaladdress
691
+ postaladdress: 123 Anystreet $ Sunnyvale, CA $ 94086
692
+ -
693
+ delete: description
694
+ -
695
+ replace: telephonenumber
696
+ telephonenumber: +1 408 555 1234
697
+ telephonenumber: +1 408 555 5678
698
+ -
699
+ delete: facsimiletelephonenumber
700
+ facsimiletelephonenumber: +1 408 555 9876
701
+ -
702
+
703
+ dn: cn=Ingrid Jensen,ou=Product Support,dc=airius,dc=com
704
+ changetype: modify
705
+ replace: postaladdress
706
+ -
707
+ delete: description
708
+ -
709
+ EOL
710
+
711
+ change_attributes_add = {
712
+ "dn" => "cn=Fiona Jensen,ou=Marketing,dc=airius,dc=com",
713
+ "objectclass" => ["top", "person", "organizationalPerson"],
714
+ "cn" => ["Fiona Jensen"],
715
+ "sn" => ["Jensen"],
716
+ "uid" => ["fiona"],
717
+ "telephonenumber" => ["+1 408 555 1212"],
718
+ }
719
+
720
+ change_attributes_delete = {
721
+ "dn" => "cn=Robert Jensen,ou=Marketing,dc=airius,dc=com",
722
+ }
723
+
724
+ change_attributes_modrdn = {
725
+ "dn" => "cn=Paul Jensen,ou=Product Development,dc=airius,dc=com",
726
+ }
727
+
728
+ change_attributes_modrdn_with_new_superior = {
729
+ "dn" => "ou=PD Accountants,ou=Product Development,dc=airius,dc=com",
730
+ }
731
+
732
+ change_attributes_modify = {
733
+ "dn" => "cn=Paula Jensen,ou=Product Development,dc=airius,dc=com",
734
+ }
735
+
736
+ change_attributes_modify_with_empty_replace = {
737
+ "dn" => "cn=Ingrid Jensen,ou=Product Support,dc=airius,dc=com",
738
+ }
739
+
740
+ ldif = assert_ldif(1,
741
+ [change_attributes_add,
742
+ change_attributes_delete,
743
+ change_attributes_modrdn,
744
+ change_attributes_modrdn_with_new_superior,
745
+ change_attributes_modify,
746
+ change_attributes_modify_with_empty_replace],
747
+ ldif_source)
748
+ record = ldif.records[0]
749
+ assert_equal("add", record.change_type)
750
+ assert_true(record.add?)
751
+
752
+ record = ldif.records[1]
753
+ assert_equal("delete", record.change_type)
754
+ assert_true(record.delete?)
755
+
756
+ record = ldif.records[2]
757
+ assert_equal("modrdn", record.change_type)
758
+ assert_true(record.modify_rdn?)
759
+ assert_equal("cn=Paula Jensen", record.new_rdn)
760
+ assert_true(record.delete_old_rdn?)
761
+ assert_nil(record.new_superior)
762
+
763
+ record = ldif.records[3]
764
+ assert_equal("modrdn", record.change_type)
765
+ assert_true(record.modify_rdn?)
766
+ assert_equal("ou=Product Development Accountants", record.new_rdn)
767
+ assert_false(record.delete_old_rdn?)
768
+ assert_equal("ou=Accounting,dc=airius,dc=com", record.new_superior)
769
+
770
+ record = ldif.records[4]
771
+ assert_equal("modify", record.change_type)
772
+ assert_true(record.modify?)
773
+ operations = [
774
+ ["add", "postaladdress",
775
+ {"postaladdress" =>
776
+ ["123 Anystreet $ Sunnyvale, CA $ 94086"]}],
777
+ ["delete", "description", {}],
778
+ ["replace", "telephonenumber",
779
+ {"telephonenumber" => [
780
+ "+1 408 555 1234",
781
+ "+1 408 555 5678",
782
+ ]}],
783
+ ["delete", "facsimiletelephonenumber",
784
+ {"facsimiletelephonenumber" => ["+1 408 555 9876"]}],
785
+ ]
786
+ i = -1
787
+ actual = record.operations.collect do |operation|
788
+ i += 1
789
+ type = operations[i][0]
790
+ [operation.send("#{type}?"),
791
+ [operation.type, operation.attribute, operation.attributes]]
792
+ end
793
+ assert_equal(operations.collect {|operation| [true, operation]},
794
+ actual)
795
+
796
+ record = ldif.records[5]
797
+ assert_equal("modify", record.change_type)
798
+ assert_true(record.modify?)
799
+ operations = [
800
+ ["replace", "postaladdress", {}],
801
+ ["delete", "description", {}],
802
+ ]
803
+ i = -1
804
+ actual = record.operations.collect do |operation|
805
+ i += 1
806
+ type = operations[i][0]
807
+ [operation.send("#{type}?"),
808
+ [operation.type, operation.attribute, operation.attributes]]
809
+ end
810
+ assert_equal(operations.collect {|operation| [true, operation]},
811
+ actual)
812
+ end
813
+
814
+ def test_modify_record
815
+ ldif_source = <<-EOL
816
+ version: 1
817
+ # Modify an entry: add an additional value to the postaladdress
818
+ # attribute, completely delete the description attribute, replace
819
+ # the telephonenumber attribute with two values, and delete a specific
820
+ # value from the facsimiletelephonenumber attribute
821
+ dn: cn=Paula Jensen, ou=Product Development, dc=airius, dc=com
822
+ changetype: modify
823
+ add: postaladdress
824
+ postaladdress: 123 Anystreet $ Sunnyvale, CA $ 94086
825
+ -
826
+ delete: description
827
+ -
828
+ replace: telephonenumber
829
+ telephonenumber: +1 408 555 1234
830
+ telephonenumber: +1 408 555 5678
831
+ -
832
+ delete: facsimiletelephonenumber
833
+ facsimiletelephonenumber: +1 408 555 9876
834
+ -
835
+ EOL
836
+
837
+ change_attributes = {
838
+ "dn" => "cn=Paula Jensen,ou=Product Development,dc=airius,dc=com",
839
+ }
840
+
841
+ ldif = assert_ldif(1, [change_attributes], ldif_source)
842
+ record = ldif.records[0]
843
+ assert_equal("modify", record.change_type)
844
+ assert_true(record.modify?)
845
+
846
+ operations = [
847
+ ["add", "postaladdress",
848
+ {"postaladdress" =>
849
+ ["123 Anystreet $ Sunnyvale, CA $ 94086"]}],
850
+ ["delete", "description", {}],
851
+ ["replace", "telephonenumber",
852
+ {"telephonenumber" => [
853
+ "+1 408 555 1234",
854
+ "+1 408 555 5678",
855
+ ]}],
856
+ ["delete", "facsimiletelephonenumber",
857
+ {"facsimiletelephonenumber" => ["+1 408 555 9876"]}],
858
+ ]
859
+ i = -1
860
+ actual = record.operations.collect do |operation|
861
+ i += 1
862
+ type = operations[i][0]
863
+ [operation.send("#{type}?"),
864
+ [operation.type, operation.attribute, operation.attributes]]
865
+ end
866
+ assert_equal(operations.collect {|operation| [true, operation]},
867
+ actual)
868
+ end
869
+
870
+ def test_modify_record_to_s
871
+ ldif_source = <<-EOL
872
+ version: 1
873
+ # Modify an entry: add an additional value to the postaladdress
874
+ # attribute, completely delete the description attribute, replace
875
+ # the telephonenumber attribute with two values, and delete a specific
876
+ # value from the facsimiletelephonenumber attribute
877
+ dn: cn=Paula Jensen, ou=Product Development, dc=airius, dc=com
878
+ changetype: modify
879
+ add: postaladdress
880
+ postaladdress: 123 Anystreet $ Sunnyvale, CA $ 94086
881
+ -
882
+ delete: description
883
+ -
884
+ replace: telephonenumber
885
+ telephonenumber: +1 408 555 1234
886
+ telephonenumber: +1 408 555 5678
887
+ -
888
+ delete: facsimiletelephonenumber
889
+ facsimiletelephonenumber: +1 408 555 9876
890
+ -
891
+ EOL
892
+
893
+ assert_ldif_to_s(<<-EOL, ldif_source)
894
+ version: 1
895
+ dn: cn=Paula Jensen,ou=Product Development,dc=airius,dc=com
896
+ changetype: modify
897
+ add: postaladdress
898
+ postaladdress: 123 Anystreet $ Sunnyvale, CA $ 94086
899
+ -
900
+ delete: description
901
+ -
902
+ replace: telephonenumber
903
+ telephonenumber: +1 408 555 1234
904
+ telephonenumber: +1 408 555 5678
905
+ -
906
+ delete: facsimiletelephonenumber
907
+ facsimiletelephonenumber: +1 408 555 9876
908
+ -
909
+ EOL
910
+ end
911
+
912
+ def test_modrdn_record_with_newsuperior
913
+ ldif_source = <<-EOL
914
+ version: 1
915
+ # Rename an entry and move all of its children to a new location in
916
+ # the directory tree (only implemented by LDAPv3 servers).
917
+ dn: ou=PD Accountants, ou=Product Development, dc=airius, dc=com
918
+ changetype: modrdn
919
+ newrdn: ou=Product Development Accountants
920
+ deleteoldrdn: 0
921
+ newsuperior: ou=Accounting, dc=airius, dc=com
922
+ EOL
923
+
924
+ change_attributes = {
925
+ "dn" => "ou=PD Accountants,ou=Product Development,dc=airius,dc=com",
926
+ }
927
+
928
+ ldif = assert_ldif(1, [change_attributes], ldif_source)
929
+ record = ldif.records[0]
930
+ assert_equal("modrdn", record.change_type)
931
+ assert_true(record.modify_rdn?)
932
+ assert_equal("ou=Product Development Accountants", record.new_rdn)
933
+ assert_false(record.delete_old_rdn?)
934
+ assert_equal("ou=Accounting,dc=airius,dc=com", record.new_superior)
935
+ end
936
+
937
+ def test_modrdn_record_with_newsuperior_to_s
938
+ ldif_source = <<-EOL
939
+ version: 1
940
+ # Rename an entry and move all of its children to a new location in
941
+ # the directory tree (only implemented by LDAPv3 servers).
942
+ dn: ou=PD Accountants, ou=Product Development, dc=airius, dc=com
943
+ changetype: modrdn
944
+ newrdn: ou=Product Development Accountants
945
+ deleteoldrdn: 0
946
+ newsuperior: ou=Accounting, dc=airius, dc=com
947
+ EOL
948
+
949
+ assert_ldif_to_s(<<-EOL, ldif_source)
950
+ version: 1
951
+ dn: ou=PD Accountants,ou=Product Development,dc=airius,dc=com
952
+ changetype: modrdn
953
+ newrdn: ou=Product Development Accountants
954
+ deleteoldrdn: 0
955
+ newsuperior: ou=Accounting,dc=airius,dc=com
956
+ EOL
957
+ end
958
+
959
+ def test_modrdn_record
960
+ ldif_source = <<-EOL
961
+ version: 1
962
+ # Modify an entry's relative distinguished name
963
+ dn: cn=Paul Jensen, ou=Product Development, dc=airius, dc=com
964
+ changetype: modrdn
965
+ newrdn: cn=Paula Jensen
966
+ deleteoldrdn: 1
967
+ EOL
968
+
969
+ change_attributes = {
970
+ "dn" => "cn=Paul Jensen,ou=Product Development,dc=airius,dc=com",
971
+ }
972
+
973
+ ldif = assert_ldif(1, [change_attributes], ldif_source)
974
+ record = ldif.records[0]
975
+ assert_equal("modrdn", record.change_type)
976
+ assert_true(record.modify_rdn?)
977
+ assert_equal("cn=Paula Jensen", record.new_rdn)
978
+ assert_true(record.delete_old_rdn?)
979
+ assert_nil(record.new_superior)
980
+ end
981
+
982
+ def test_modrdn_record_to_s
983
+ ldif_source = <<-EOL
984
+ version: 1
985
+ # Modify an entry's relative distinguished name
986
+ dn: cn=Paul Jensen, ou=Product Development, dc=airius, dc=com
987
+ changetype: modrdn
988
+ newrdn: cn=Paula Jensen
989
+ deleteoldrdn: 1
990
+ EOL
991
+
992
+ assert_ldif_to_s(<<-EOL, ldif_source)
993
+ version: 1
994
+ dn: cn=Paul Jensen,ou=Product Development,dc=airius,dc=com
995
+ changetype: modrdn
996
+ newrdn: cn=Paula Jensen
997
+ deleteoldrdn: 1
998
+ EOL
999
+ end
1000
+
1001
+ def test_moddn_record_with_newsuperior
1002
+ ldif_source = <<-EOL
1003
+ version: 1
1004
+ # Rename an entry and move all of its children to a new location in
1005
+ # the directory tree (only implemented by LDAPv3 servers).
1006
+ dn: ou=PD Accountants, ou=Product Development, dc=airius, dc=com
1007
+ changetype: moddn
1008
+ newrdn: ou=Product Development Accountants
1009
+ deleteoldrdn: 0
1010
+ newsuperior: ou=Accounting, dc=airius, dc=com
1011
+ EOL
1012
+
1013
+ change_attributes = {
1014
+ "dn" => "ou=PD Accountants,ou=Product Development,dc=airius,dc=com",
1015
+ }
1016
+
1017
+ ldif = assert_ldif(1, [change_attributes], ldif_source)
1018
+ record = ldif.records[0]
1019
+ assert_equal("moddn", record.change_type)
1020
+ assert_true(record.modify_dn?)
1021
+ assert_equal("ou=Product Development Accountants", record.new_rdn)
1022
+ assert_false(record.delete_old_rdn?)
1023
+ assert_equal("ou=Accounting,dc=airius,dc=com", record.new_superior)
1024
+ end
1025
+
1026
+ def test_moddn_record_with_newsuperior_to_s
1027
+ ldif_source = <<-EOL
1028
+ version: 1
1029
+ # Rename an entry and move all of its children to a new location in
1030
+ # the directory tree (only implemented by LDAPv3 servers).
1031
+ dn: ou=PD Accountants, ou=Product Development, dc=airius, dc=com
1032
+ changetype: moddn
1033
+ newrdn: ou=Product Development Accountants
1034
+ deleteoldrdn: 0
1035
+ newsuperior: ou=Accounting, dc=airius, dc=com
1036
+ EOL
1037
+
1038
+ assert_ldif_to_s(<<-EOL, ldif_source)
1039
+ version: 1
1040
+ dn: ou=PD Accountants,ou=Product Development,dc=airius,dc=com
1041
+ changetype: moddn
1042
+ newrdn: ou=Product Development Accountants
1043
+ deleteoldrdn: 0
1044
+ newsuperior: ou=Accounting,dc=airius,dc=com
1045
+ EOL
1046
+ end
1047
+
1048
+ def test_moddn_record
1049
+ ldif_source = <<-EOL
1050
+ version: 1
1051
+ # Modify an entry's relative distinguished name
1052
+ dn: cn=Paul Jensen, ou=Product Development, dc=airius, dc=com
1053
+ changetype: moddn
1054
+ newrdn: cn=Paula Jensen
1055
+ deleteoldrdn: 1
1056
+ EOL
1057
+
1058
+ change_attributes = {
1059
+ "dn" => "cn=Paul Jensen,ou=Product Development,dc=airius,dc=com",
1060
+ }
1061
+
1062
+ ldif = assert_ldif(1, [change_attributes], ldif_source)
1063
+ record = ldif.records[0]
1064
+ assert_equal("moddn", record.change_type)
1065
+ assert_true(record.modify_dn?)
1066
+ assert_equal("cn=Paula Jensen", record.new_rdn)
1067
+ assert_true(record.delete_old_rdn?)
1068
+ assert_nil(record.new_superior)
1069
+ end
1070
+
1071
+ def test_moddn_record_to_s
1072
+ ldif_source = <<-EOL
1073
+ version: 1
1074
+ # Modify an entry's relative distinguished name
1075
+ dn: cn=Paul Jensen, ou=Product Development, dc=airius, dc=com
1076
+ changetype: moddn
1077
+ newrdn: cn=Paula Jensen
1078
+ deleteoldrdn: 1
1079
+ EOL
1080
+
1081
+ assert_ldif_to_s(<<-EOL, ldif_source)
1082
+ version: 1
1083
+ dn: cn=Paul Jensen,ou=Product Development,dc=airius,dc=com
1084
+ changetype: moddn
1085
+ newrdn: cn=Paula Jensen
1086
+ deleteoldrdn: 1
1087
+ EOL
1088
+ end
1089
+
1090
+ def test_delete_record
1091
+ ldif_source = <<-EOL
1092
+ version: 1
1093
+ # Delete an existing entry
1094
+ dn: cn=Robert Jensen, ou=Marketing, dc=airius, dc=com
1095
+ changetype: delete
1096
+ EOL
1097
+
1098
+ change_attributes = {
1099
+ "dn" => "cn=Robert Jensen,ou=Marketing,dc=airius,dc=com",
1100
+ }
1101
+
1102
+ ldif = assert_ldif(1, [change_attributes], ldif_source)
1103
+ record = ldif.records[0]
1104
+ assert_equal("delete", record.change_type)
1105
+ assert_true(record.delete?)
1106
+ end
1107
+
1108
+ def test_delete_record_to_s
1109
+ ldif_source = <<-EOL
1110
+ version: 1
1111
+ # Delete an existing entry
1112
+ dn: cn=Robert Jensen, ou=Marketing, dc=airius, dc=com
1113
+ changetype: delete
1114
+ EOL
1115
+
1116
+ assert_ldif_to_s(<<-EOL, ldif_source)
1117
+ version: 1
1118
+ dn: cn=Robert Jensen,ou=Marketing,dc=airius,dc=com
1119
+ changetype: delete
1120
+ EOL
1121
+ end
1122
+
1123
+ def test_add_record
1124
+ ldif_source = <<-EOL
1125
+ version: 1
1126
+ # Add a new entry
1127
+ dn: cn=Fiona Jensen, ou=Marketing, dc=airius, dc=com
1128
+ changetype: add
1129
+ objectclass: top
1130
+ objectclass: person
1131
+ objectclass: organizationalPerson
1132
+ cn: Fiona Jensen
1133
+ sn: Jensen
1134
+ uid: fiona
1135
+ telephonenumber: +1 408 555 1212
1136
+ EOL
1137
+
1138
+ change_attributes = {
1139
+ "dn" => "cn=Fiona Jensen,ou=Marketing,dc=airius,dc=com",
1140
+ "objectclass" => ["top", "person", "organizationalPerson"],
1141
+ "cn" => ["Fiona Jensen"],
1142
+ "sn" => ["Jensen"],
1143
+ "uid" => ["fiona"],
1144
+ "telephonenumber" => ["+1 408 555 1212"],
1145
+ }
1146
+
1147
+ ldif = assert_ldif(1, [change_attributes], ldif_source)
1148
+ record = ldif.records[0]
1149
+ assert_equal("add", record.change_type)
1150
+ assert_true(record.add?)
1151
+ end
1152
+
1153
+ def test_add_record_to_s
1154
+ ldif_source = <<-EOL
1155
+ version: 1
1156
+ # Add a new entry
1157
+ dn: cn=Fiona Jensen, ou=Marketing, dc=airius, dc=com
1158
+ changetype: add
1159
+ objectclass: top
1160
+ objectclass: person
1161
+ objectclass: organizationalPerson
1162
+ cn: Fiona Jensen
1163
+ sn: Jensen
1164
+ uid: fiona
1165
+ telephonenumber: +1 408 555 1212
1166
+ EOL
1167
+
1168
+ assert_ldif_to_s(<<-EOL, ldif_source)
1169
+ version: 1
1170
+ dn: cn=Fiona Jensen,ou=Marketing,dc=airius,dc=com
1171
+ changetype: add
1172
+ cn: Fiona Jensen
1173
+ objectclass: organizationalPerson
1174
+ objectclass: person
1175
+ objectclass: top
1176
+ sn: Jensen
1177
+ telephonenumber: +1 408 555 1212
1178
+ uid: fiona
1179
+ EOL
1180
+ end
1181
+
1182
+ def test_records_with_external_file_reference
1183
+ ldif_source = <<-EOL
1184
+ version: 1
1185
+ dn: cn=Horatio Jensen, ou=Product Testing, dc=airius, dc=com
1186
+ objectclass: top
1187
+ objectclass: person
1188
+ objectclass: organizationalPerson
1189
+ cn: Horatio Jensen
1190
+ cn: Horatio N Jensen
1191
+ sn: Jensen
1192
+ uid: hjensen
1193
+ telephonenumber: +1 408 555 1212
1194
+ jpegphoto:< file://#{jpeg_photo_path}
1195
+ EOL
1196
+
1197
+ record = {
1198
+ "dn" => "cn=Horatio Jensen,ou=Product Testing,dc=airius,dc=com",
1199
+ "objectclass" => ["top", "person", "organizationalPerson"],
1200
+ "cn" => ["Horatio Jensen", "Horatio N Jensen"],
1201
+ "sn" => ["Jensen"],
1202
+ "uid" => ["hjensen"],
1203
+ "telephonenumber" => ["+1 408 555 1212"],
1204
+ "jpegphoto" => [jpeg_photo],
1205
+ }
1206
+
1207
+ assert_ldif(1, [record], ldif_source)
1208
+ end
1209
+
1210
+ def test_records_with_external_file_reference_to_s
1211
+ ldif_source = <<-EOL
1212
+ version: 1
1213
+ dn: cn=Horatio Jensen, ou=Product Testing, dc=airius, dc=com
1214
+ objectclass: top
1215
+ objectclass: person
1216
+ objectclass: organizationalPerson
1217
+ cn: Horatio Jensen
1218
+ cn: Horatio N Jensen
1219
+ sn: Jensen
1220
+ uid: hjensen
1221
+ telephonenumber: +1 408 555 1212
1222
+ jpegphoto:< file://#{jpeg_photo_path}
1223
+ EOL
1224
+ set_encoding(ldif_source, "utf-8")
1225
+
1226
+ jpeg_photo_attribute = "jpegphoto:: "
1227
+ value = [jpeg_photo].pack("m").gsub(/\n/, '')
1228
+ first_line_value_size = 75 - jpeg_photo_attribute.size
1229
+ jpeg_photo_attribute << value[0, first_line_value_size] + "\n"
1230
+ value = value[first_line_value_size..-1]
1231
+ value.scan(/.{1,74}/).each do |line|
1232
+ jpeg_photo_attribute << " #{line}\n"
1233
+ end
1234
+ jpeg_photo_attribute = jpeg_photo_attribute.chomp
1235
+
1236
+ assert_ldif_to_s(<<-EOL, ldif_source)
1237
+ version: 1
1238
+ dn: cn=Horatio Jensen,ou=Product Testing,dc=airius,dc=com
1239
+ cn: Horatio Jensen
1240
+ cn: Horatio N Jensen
1241
+ #{jpeg_photo_attribute}
1242
+ objectclass: organizationalPerson
1243
+ objectclass: person
1244
+ objectclass: top
1245
+ sn: Jensen
1246
+ telephonenumber: +1 408 555 1212
1247
+ uid: hjensen
1248
+ EOL
1249
+ end
1250
+
1251
+ def test_records_with_option_attributes
1252
+ ldif_source = <<-EOL
1253
+ version: 1
1254
+ dn:: b3U95Za25qWt6YOoLG89QWlyaXVz
1255
+ # dn:: ou=<JapaneseOU>,o=Airius
1256
+ objectclass: top
1257
+ objectclass: organizationalUnit
1258
+ ou:: 5Za25qWt6YOo
1259
+ # ou:: <JapaneseOU>
1260
+ ou;lang-ja:: 5Za25qWt6YOo
1261
+ # ou;lang-ja:: <JapaneseOU>
1262
+ ou;lang-ja;phonetic:: 44GI44GE44GO44KH44GG44G2
1263
+ # ou;lang-ja:: <JapaneseOU_in_phonetic_representation>
1264
+ ou;lang-en: Sales
1265
+ description: Japanese office
1266
+
1267
+ dn:: dWlkPXJvZ2FzYXdhcmEsb3U95Za25qWt6YOoLG89QWlyaXVz
1268
+ # dn:: uid=<uid>,ou=<JapaneseOU>,o=Airius
1269
+ userpassword: {SHA}O3HSv1MusyL4kTjP+HKI5uxuNoM=
1270
+ objectclass: top
1271
+ objectclass: person
1272
+ objectclass: organizationalPerson
1273
+ objectclass: inetOrgPerson
1274
+ uid: rogasawara
1275
+ mail: rogasawara@airius.co.jp
1276
+ givenname;lang-ja:: 44Ot44OJ44OL44O8
1277
+ # givenname;lang-ja:: <JapaneseGivenname>
1278
+ sn;lang-ja:: 5bCP56yg5Y6f
1279
+ # sn;lang-ja:: <JapaneseSn>
1280
+ cn;lang-ja:: 5bCP56yg5Y6fIOODreODieODi+ODvA==
1281
+ # cn;lang-ja:: <JapaneseCn>
1282
+ title;lang-ja:: 5Za25qWt6YOoIOmDqOmVtw==
1283
+ # title;lang-ja:: <JapaneseTitle>
1284
+ preferredlanguage: ja
1285
+ givenname:: 44Ot44OJ44OL44O8
1286
+ # givenname:: <JapaneseGivenname>
1287
+ sn:: 5bCP56yg5Y6f
1288
+ # sn:: <JapaneseSn>
1289
+ cn:: 5bCP56yg5Y6fIOODreODieODi+ODvA==
1290
+ # cn:: <JapaneseCn>
1291
+ title:: 5Za25qWt6YOoIOmDqOmVtw==
1292
+ # title:: <JapaneseTitle>
1293
+ givenname;lang-ja;phonetic:: 44KN44Gp44Gr44O8
1294
+ # givenname;lang-ja;phonetic::
1295
+ <JapaneseGivenname_in_phonetic_representation_kana>
1296
+ sn;lang-ja;phonetic:: 44GK44GM44GV44KP44KJ
1297
+ # sn;lang-ja;phonetic:: <JapaneseSn_in_phonetic_representation_kana>
1298
+ cn;lang-ja;phonetic:: 44GK44GM44GV44KP44KJIOOCjeOBqeOBq+ODvA==
1299
+ # cn;lang-ja;phonetic:: <JapaneseCn_in_phonetic_representation_kana>
1300
+ title;lang-ja;phonetic:: 44GI44GE44GO44KH44GG44G2IOOBtuOBoeOCh+OBhg==
1301
+ # title;lang-ja;phonetic::
1302
+ # <JapaneseTitle_in_phonetic_representation_kana>
1303
+ givenname;lang-en: Rodney
1304
+ sn;lang-en: Ogasawara
1305
+ cn;lang-en: Rodney Ogasawara
1306
+ title;lang-en: Sales, Director
1307
+ EOL
1308
+ set_encoding(ldif_source, "utf-8")
1309
+
1310
+ record1 = {
1311
+ "dn" => "ou=営業部,o=Airius",
1312
+ "objectclass" => ["top", "organizationalUnit"],
1313
+ "ou" => [
1314
+ "営業部",
1315
+ {"lang-ja" =>
1316
+ [
1317
+ "営業部",
1318
+ {"phonetic" => ["えいぎょうぶ"]},
1319
+ ],
1320
+ },
1321
+ {"lang-en" => ["Sales"]},
1322
+ ],
1323
+ "description" => ["Japanese office"],
1324
+ }
1325
+
1326
+ record2 = {
1327
+ "dn" => "uid=rogasawara,ou=営業部,o=Airius",
1328
+ "userpassword" => ["{SHA}O3HSv1MusyL4kTjP+HKI5uxuNoM="],
1329
+ "objectclass" => ["top", "person",
1330
+ "organizationalPerson", "inetOrgPerson"],
1331
+ "uid" => ["rogasawara"],
1332
+ "mail" => ["rogasawara@airius.co.jp"],
1333
+ "givenname" => [
1334
+ {"lang-ja" =>
1335
+ [
1336
+ "ロドニー",
1337
+ {"phonetic" => ["ろどにー"]},
1338
+ ]
1339
+ },
1340
+ "ロドニー",
1341
+ {"lang-en" => ["Rodney"]},
1342
+ ],
1343
+ "sn" => [
1344
+ {"lang-ja" =>
1345
+ [
1346
+ "小笠原",
1347
+ {"phonetic" => ["おがさわら"]},
1348
+ ]
1349
+ },
1350
+ "小笠原",
1351
+ {"lang-en" => ["Ogasawara"]},
1352
+ ],
1353
+ "cn" => [
1354
+ {"lang-ja" =>
1355
+ [
1356
+ "小笠原 ロドニー",
1357
+ {"phonetic" => ["おがさわら ろどにー"]},
1358
+ ],
1359
+ },
1360
+ "小笠原 ロドニー",
1361
+ {"lang-en" => ["Rodney Ogasawara"]},
1362
+ ],
1363
+ "title" => [
1364
+ {"lang-ja" =>
1365
+ [
1366
+ "営業部 部長",
1367
+ {"phonetic" => ["えいぎょうぶ ぶちょう"]}
1368
+ ]
1369
+ },
1370
+ "営業部 部長",
1371
+ {"lang-en" => ["Sales, Director"]},
1372
+ ],
1373
+ "preferredlanguage" => ["ja"],
1374
+ }
1375
+
1376
+ assert_ldif(1, [record1, record2], ldif_source)
1377
+ end
1378
+
1379
+ def test_records_with_option_attributes_to_s
1380
+ ldif_source = <<-EOL
1381
+ version: 1
1382
+ dn:: b3U95Za25qWt6YOoLG89QWlyaXVz
1383
+ # dn:: ou=<JapaneseOU>,o=Airius
1384
+ objectclass: top
1385
+ objectclass: organizationalUnit
1386
+ ou:: 5Za25qWt6YOo
1387
+ # ou:: <JapaneseOU>
1388
+ ou;lang-ja:: 5Za25qWt6YOo
1389
+ # ou;lang-ja:: <JapaneseOU>
1390
+ ou;lang-ja;phonetic:: 44GI44GE44GO44KH44GG44G2
1391
+ # ou;lang-ja:: <JapaneseOU_in_phonetic_representation>
1392
+ ou;lang-en: Sales
1393
+ description: Japanese office
1394
+
1395
+ dn:: dWlkPXJvZ2FzYXdhcmEsb3U95Za25qWt6YOoLG89QWlyaXVz
1396
+ # dn:: uid=<uid>,ou=<JapaneseOU>,o=Airius
1397
+ userpassword: {SHA}O3HSv1MusyL4kTjP+HKI5uxuNoM=
1398
+ objectclass: top
1399
+ objectclass: person
1400
+ objectclass: organizationalPerson
1401
+ objectclass: inetOrgPerson
1402
+ uid: rogasawara
1403
+ mail: rogasawara@airius.co.jp
1404
+ givenname;lang-ja:: 44Ot44OJ44OL44O8
1405
+ # givenname;lang-ja:: <JapaneseGivenname>
1406
+ sn;lang-ja:: 5bCP56yg5Y6f
1407
+ # sn;lang-ja:: <JapaneseSn>
1408
+ cn;lang-ja:: 5bCP56yg5Y6fIOODreODieODi+ODvA==
1409
+ # cn;lang-ja:: <JapaneseCn>
1410
+ title;lang-ja:: 5Za25qWt6YOoIOmDqOmVtw==
1411
+ # title;lang-ja:: <JapaneseTitle>
1412
+ preferredlanguage: ja
1413
+ givenname:: 44Ot44OJ44OL44O8
1414
+ # givenname:: <JapaneseGivenname>
1415
+ sn:: 5bCP56yg5Y6f
1416
+ # sn:: <JapaneseSn>
1417
+ cn:: 5bCP56yg5Y6fIOODreODieODi+ODvA==
1418
+ # cn:: <JapaneseCn>
1419
+ title:: 5Za25qWt6YOoIOmDqOmVtw==
1420
+ # title:: <JapaneseTitle>
1421
+ givenname;lang-ja;phonetic:: 44KN44Gp44Gr44O8
1422
+ # givenname;lang-ja;phonetic::
1423
+ <JapaneseGivenname_in_phonetic_representation_kana>
1424
+ sn;lang-ja;phonetic:: 44GK44GM44GV44KP44KJ
1425
+ # sn;lang-ja;phonetic:: <JapaneseSn_in_phonetic_representation_kana>
1426
+ cn;lang-ja;phonetic:: 44GK44GM44GV44KP44KJIOOCjeOBqeOBq+ODvA==
1427
+ # cn;lang-ja;phonetic:: <JapaneseCn_in_phonetic_representation_kana>
1428
+ title;lang-ja;phonetic:: 44GI44GE44GO44KH44GG44G2IOOBtuOBoeOCh+OBhg==
1429
+ # title;lang-ja;phonetic::
1430
+ # <JapaneseTitle_in_phonetic_representation_kana>
1431
+ givenname;lang-en: Rodney
1432
+ sn;lang-en: Ogasawara
1433
+ cn;lang-en: Rodney Ogasawara
1434
+ title;lang-en: Sales, Director
1435
+ EOL
1436
+ set_encoding(ldif_source, "utf-8")
1437
+
1438
+ assert_ldif_to_s(<<-EOL, ldif_source)
1439
+ version: 1
1440
+ dn:: b3U95Za25qWt6YOoLG89QWlyaXVz
1441
+ description: Japanese office
1442
+ objectclass: organizationalUnit
1443
+ objectclass: top
1444
+ ou:: 5Za25qWt6YOo
1445
+ ou;lang-en: Sales
1446
+ ou;lang-ja:: 5Za25qWt6YOo
1447
+ ou;lang-ja;phonetic:: 44GI44GE44GO44KH44GG44G2
1448
+
1449
+ dn:: dWlkPXJvZ2FzYXdhcmEsb3U95Za25qWt6YOoLG89QWlyaXVz
1450
+ cn:: 5bCP56yg5Y6fIOODreODieODi+ODvA==
1451
+ cn;lang-en: Rodney Ogasawara
1452
+ cn;lang-ja:: 5bCP56yg5Y6fIOODreODieODi+ODvA==
1453
+ cn;lang-ja;phonetic:: 44GK44GM44GV44KP44KJIOOCjeOBqeOBq+ODvA==
1454
+ givenname:: 44Ot44OJ44OL44O8
1455
+ givenname;lang-en: Rodney
1456
+ givenname;lang-ja:: 44Ot44OJ44OL44O8
1457
+ givenname;lang-ja;phonetic:: 44KN44Gp44Gr44O8
1458
+ mail: rogasawara@airius.co.jp
1459
+ objectclass: inetOrgPerson
1460
+ objectclass: organizationalPerson
1461
+ objectclass: person
1462
+ objectclass: top
1463
+ preferredlanguage: ja
1464
+ sn:: 5bCP56yg5Y6f
1465
+ sn;lang-en: Ogasawara
1466
+ sn;lang-ja:: 5bCP56yg5Y6f
1467
+ sn;lang-ja;phonetic:: 44GK44GM44GV44KP44KJ
1468
+ title:: 5Za25qWt6YOoIOmDqOmVtw==
1469
+ title;lang-en: Sales, Director
1470
+ title;lang-ja:: 5Za25qWt6YOoIOmDqOmVtw==
1471
+ title;lang-ja;phonetic:: 44GI44GE44GO44KH44GG44G2IOOBtuOBoeOCh+OBhg==
1472
+ uid: rogasawara
1473
+ userpassword: {SHA}O3HSv1MusyL4kTjP+HKI5uxuNoM=
1474
+ EOL
1475
+ end
1476
+
1477
+ def test_an_record_with_base64_encoded_value
1478
+ ldif_source = <<-EOL
1479
+ version: 1
1480
+ dn: cn=Gern Jensen, ou=Product Testing, dc=airius, dc=com
1481
+ objectclass: top
1482
+ objectclass: person
1483
+ objectclass: organizationalPerson
1484
+ cn: Gern Jensen
1485
+ cn: Gern O Jensen
1486
+ sn: Jensen
1487
+ uid: gernj
1488
+ telephonenumber: +1 408 555 1212
1489
+ description:: V2hhdCBhIGNhcmVmdWwgcmVhZGVyIHlvdSBhcmUhICBUaGlzIHZhbHVl
1490
+ IGlzIGJhc2UtNjQtZW5jb2RlZCBiZWNhdXNlIGl0IGhhcyBhIGNvbnRyb2wgY2hhcmFjdG
1491
+ VyIGluIGl0IChhIENSKS4NICBCeSB0aGUgd2F5LCB5b3Ugc2hvdWxkIHJlYWxseSBnZXQg
1492
+ b3V0IG1vcmUu
1493
+ EOL
1494
+
1495
+ record = {
1496
+ "dn" => "cn=Gern Jensen,ou=Product Testing,dc=airius,dc=com",
1497
+ "objectclass" => ["top", "person", "organizationalPerson"],
1498
+ "cn" => ["Gern Jensen", "Gern O Jensen"],
1499
+ "sn" => ["Jensen"],
1500
+ "uid" => ["gernj"],
1501
+ "telephonenumber" => ["+1 408 555 1212"],
1502
+ "description" => ["What a careful reader you are! " +
1503
+ "This value is base-64-encoded because it has a " +
1504
+ "control character in it (a CR).\r By the way, " +
1505
+ "you should really get out more."],
1506
+ }
1507
+ assert_ldif(1, [record], ldif_source)
1508
+ end
1509
+
1510
+ def test_an_record_with_base64_encoded_value_to_s
1511
+ ldif_source = <<-EOL
1512
+ version: 1
1513
+ dn: cn=Gern Jensen, ou=Product Testing, dc=airius, dc=com
1514
+ objectclass: top
1515
+ objectclass: person
1516
+ objectclass: organizationalPerson
1517
+ cn: Gern Jensen
1518
+ cn: Gern O Jensen
1519
+ sn: Jensen
1520
+ uid: gernj
1521
+ telephonenumber: +1 408 555 1212
1522
+ description:: V2hhdCBhIGNhcmVmdWwgcmVhZGVyIHlvdSBhcmUhICBUaGlzIHZhbHVl
1523
+ IGlzIGJhc2UtNjQtZW5jb2RlZCBiZWNhdXNlIGl0IGhhcyBhIGNvbnRyb2wgY2hhcmFjdG
1524
+ VyIGluIGl0IChhIENSKS4NICBCeSB0aGUgd2F5LCB5b3Ugc2hvdWxkIHJlYWxseSBnZXQg
1525
+ b3V0IG1vcmUu
1526
+ EOL
1527
+
1528
+ assert_ldif_to_s(<<-EOL, ldif_source)
1529
+ version: 1
1530
+ dn: cn=Gern Jensen,ou=Product Testing,dc=airius,dc=com
1531
+ cn: Gern Jensen
1532
+ cn: Gern O Jensen
1533
+ description:: V2hhdCBhIGNhcmVmdWwgcmVhZGVyIHlvdSBhcmUhICBUaGlzIHZhbHVlIGlzI
1534
+ GJhc2UtNjQtZW5jb2RlZCBiZWNhdXNlIGl0IGhhcyBhIGNvbnRyb2wgY2hhcmFjdGVyIGluIGl
1535
+ 0IChhIENSKS4NICBCeSB0aGUgd2F5LCB5b3Ugc2hvdWxkIHJlYWxseSBnZXQgb3V0IG1vcmUu
1536
+ objectclass: organizationalPerson
1537
+ objectclass: person
1538
+ objectclass: top
1539
+ sn: Jensen
1540
+ telephonenumber: +1 408 555 1212
1541
+ uid: gernj
1542
+ EOL
1543
+ end
1544
+
1545
+ def test_an_record_with_folded_attribute_value
1546
+ ldif_source = <<-EOL
1547
+ version: 1
1548
+ dn:cn=Barbara Jensen, ou=Product Development, dc=airius, dc=com
1549
+ objectclass:top
1550
+ objectclass:person
1551
+ objectclass:organizationalPerson
1552
+ cn:Barbara Jensen
1553
+ cn:Barbara J Jensen
1554
+ cn:Babs Jensen
1555
+ sn:Jensen
1556
+ uid:bjensen
1557
+ telephonenumber:+1 408 555 1212
1558
+ description:Babs is a big sailing fan, and travels extensively in sea
1559
+ rch of perfect sailing conditions.
1560
+ title:Product Manager, Rod and Reel Division
1561
+ EOL
1562
+
1563
+ record = {
1564
+ "dn" => "cn=Barbara Jensen,ou=Product Development,dc=airius,dc=com",
1565
+ "objectclass" => ["top", "person", "organizationalPerson"],
1566
+ "cn" => ["Barbara Jensen", "Barbara J Jensen", "Babs Jensen"],
1567
+ "sn" => ["Jensen"],
1568
+ "uid" => ["bjensen"],
1569
+ "telephonenumber" => ["+1 408 555 1212"],
1570
+ "description" => ["Babs is a big sailing fan, and travels extensively " +
1571
+ "in search of perfect sailing conditions."],
1572
+ "title" => ["Product Manager, Rod and Reel Division"],
1573
+ }
1574
+ assert_ldif(1, [record], ldif_source)
1575
+ end
1576
+
1577
+ def test_an_record_with_folded_attribute_value_to_s
1578
+ ldif_source = <<-EOL
1579
+ version: 1
1580
+ dn:cn=Barbara Jensen, ou=Product Development, dc=airius, dc=com
1581
+ objectclass:top
1582
+ objectclass:person
1583
+ objectclass:organizationalPerson
1584
+ cn:Barbara Jensen
1585
+ cn:Barbara J Jensen
1586
+ cn:Babs Jensen
1587
+ sn:Jensen
1588
+ uid:bjensen
1589
+ telephonenumber:+1 408 555 1212
1590
+ description:Babs is a big sailing fan, and travels extensively in sea
1591
+ rch of perfect sailing conditions.
1592
+ title:Product Manager, Rod and Reel Division
1593
+ EOL
1594
+
1595
+ assert_ldif_to_s(<<-EOL, ldif_source)
1596
+ version: 1
1597
+ dn: cn=Barbara Jensen,ou=Product Development,dc=airius,dc=com
1598
+ cn: Babs Jensen
1599
+ cn: Barbara J Jensen
1600
+ cn: Barbara Jensen
1601
+ description: Babs is a big sailing fan, and travels extensively in search o
1602
+ f perfect sailing conditions.
1603
+ objectclass: organizationalPerson
1604
+ objectclass: person
1605
+ objectclass: top
1606
+ sn: Jensen
1607
+ telephonenumber: +1 408 555 1212
1608
+ title: Product Manager, Rod and Reel Division
1609
+ uid: bjensen
1610
+ EOL
1611
+ end
1612
+
1613
+ def test_records
1614
+ ldif_source = <<-EOL
1615
+ version: 1
1616
+ dn: cn=Barbara Jensen, ou=Product Development, dc=airius, dc=com
1617
+ objectclass: top
1618
+ objectclass: person
1619
+ objectclass: organizationalPerson
1620
+ cn: Barbara Jensen
1621
+ cn: Barbara J Jensen
1622
+ cn: Babs Jensen
1623
+ sn: Jensen
1624
+ uid: bjensen
1625
+ telephonenumber: +1 408 555 1212
1626
+ description: A big sailing fan.
1627
+
1628
+ dn: cn=Bjorn Jensen, ou=Accounting, dc=airius, dc=com
1629
+ objectclass: top
1630
+ objectclass: person
1631
+ objectclass: organizationalPerson
1632
+ cn: Bjorn Jensen
1633
+ sn: Jensen
1634
+ telephonenumber: +1 408 555 1212
1635
+ EOL
1636
+
1637
+ record1 = {
1638
+ "dn" => "cn=Barbara Jensen,ou=Product Development,dc=airius,dc=com",
1639
+ "objectclass" => ["top", "person", "organizationalPerson"],
1640
+ "cn" => ["Barbara Jensen", "Barbara J Jensen", "Babs Jensen"],
1641
+ "sn" => ["Jensen"],
1642
+ "uid" => ["bjensen"],
1643
+ "telephonenumber" => ["+1 408 555 1212"],
1644
+ "description" => ["A big sailing fan."],
1645
+ }
1646
+ record2 = {
1647
+ "dn" => "cn=Bjorn Jensen,ou=Accounting,dc=airius,dc=com",
1648
+ "objectclass" => ["top", "person", "organizationalPerson"],
1649
+ "cn" => ["Bjorn Jensen"],
1650
+ "sn" => ["Jensen"],
1651
+ "telephonenumber" => ["+1 408 555 1212"],
1652
+ }
1653
+ assert_ldif(1, [record1, record2], ldif_source)
1654
+ end
1655
+
1656
+ def test_records_to_s
1657
+ ldif_source = <<-EOL
1658
+ version: 1
1659
+ dn: cn=Barbara Jensen, ou=Product Development, dc=airius, dc=com
1660
+ objectclass: top
1661
+ objectclass: person
1662
+ objectclass: organizationalPerson
1663
+ cn: Barbara Jensen
1664
+ cn: Barbara J Jensen
1665
+ cn: Babs Jensen
1666
+ sn: Jensen
1667
+ uid: bjensen
1668
+ telephonenumber: +1 408 555 1212
1669
+ description: A big sailing fan.
1670
+
1671
+ dn: cn=Bjorn Jensen, ou=Accounting, dc=airius, dc=com
1672
+ objectclass: top
1673
+ objectclass: person
1674
+ objectclass: organizationalPerson
1675
+ cn: Bjorn Jensen
1676
+ sn: Jensen
1677
+ telephonenumber: +1 408 555 1212
1678
+ EOL
1679
+
1680
+ assert_ldif_to_s(<<-EOL, ldif_source)
1681
+ version: 1
1682
+ dn: cn=Barbara Jensen,ou=Product Development,dc=airius,dc=com
1683
+ cn: Babs Jensen
1684
+ cn: Barbara J Jensen
1685
+ cn: Barbara Jensen
1686
+ description: A big sailing fan.
1687
+ objectclass: organizationalPerson
1688
+ objectclass: person
1689
+ objectclass: top
1690
+ sn: Jensen
1691
+ telephonenumber: +1 408 555 1212
1692
+ uid: bjensen
1693
+
1694
+ dn: cn=Bjorn Jensen,ou=Accounting,dc=airius,dc=com
1695
+ cn: Bjorn Jensen
1696
+ objectclass: organizationalPerson
1697
+ objectclass: person
1698
+ objectclass: top
1699
+ sn: Jensen
1700
+ telephonenumber: +1 408 555 1212
1701
+ EOL
1702
+ end
1703
+
1704
+ def test_an_record
1705
+ ldif_source = <<-EOL
1706
+ version: 1
1707
+ dn: cn=Barbara Jensen, ou=Product Development, dc=airius, dc=com
1708
+ objectclass: top
1709
+ objectclass: person
1710
+ objectclass: organizationalPerson
1711
+ cn: Barbara Jensen
1712
+ cn: Barbara J Jensen
1713
+ cn: Babs Jensen
1714
+ sn: Jensen
1715
+ uid: bjensen
1716
+ telephonenumber: +1 408 555 1212
1717
+ description: A big sailing fan.
1718
+ EOL
1719
+
1720
+ record = {
1721
+ "dn" => "cn=Barbara Jensen,ou=Product Development,dc=airius,dc=com",
1722
+ "objectclass" => ["top", "person", "organizationalPerson"],
1723
+ "cn" => ["Barbara Jensen", "Barbara J Jensen", "Babs Jensen"],
1724
+ "sn" => ["Jensen"],
1725
+ "uid" => ["bjensen"],
1726
+ "telephonenumber" => ["+1 408 555 1212"],
1727
+ "description" => ["A big sailing fan."],
1728
+ }
1729
+ assert_ldif(1, [record], ldif_source)
1730
+ end
1731
+
1732
+ def test_an_record_to_s
1733
+ ldif_source = <<-EOL
1734
+ version: 1
1735
+ dn: cn=Barbara Jensen, ou=Product Development, dc=airius, dc=com
1736
+ objectclass: top
1737
+ objectclass: person
1738
+ objectclass: organizationalPerson
1739
+ cn: Barbara Jensen
1740
+ cn: Barbara J Jensen
1741
+ cn: Babs Jensen
1742
+ sn: Jensen
1743
+ uid: bjensen
1744
+ telephonenumber: +1 408 555 1212
1745
+ description: A big sailing fan.
1746
+ EOL
1747
+
1748
+ assert_ldif_to_s(<<-EOL, ldif_source)
1749
+ version: 1
1750
+ dn: cn=Barbara Jensen,ou=Product Development,dc=airius,dc=com
1751
+ cn: Babs Jensen
1752
+ cn: Barbara J Jensen
1753
+ cn: Barbara Jensen
1754
+ description: A big sailing fan.
1755
+ objectclass: organizationalPerson
1756
+ objectclass: person
1757
+ objectclass: top
1758
+ sn: Jensen
1759
+ telephonenumber: +1 408 555 1212
1760
+ uid: bjensen
1761
+ EOL
1762
+ end
1763
+
1764
+ def test_comment
1765
+ ldif_source = <<-EOL
1766
+ version: 1
1767
+ dn: cn=Barbara Jensen, ou=Product Development, dc=airius, dc=com
1768
+ objectclass: top
1769
+ # objectclass: person
1770
+ #objectcl
1771
+ ass: organizationalPerson
1772
+ EOL
1773
+
1774
+ record = {
1775
+ "dn" => "cn=Barbara Jensen,ou=Product Development,dc=airius,dc=com",
1776
+ "objectclass" => ["top"],
1777
+ }
1778
+ assert_ldif(1, [record], ldif_source)
1779
+ end
1780
+
1781
+ def test_comment_to_s
1782
+ ldif_source = <<-EOL
1783
+ version: 1
1784
+ dn: cn=Barbara Jensen, ou=Product Development, dc=airius, dc=com
1785
+ objectclass: top
1786
+ # objectclass: person
1787
+ #objectcl
1788
+ ass: organizationalPerson
1789
+ EOL
1790
+
1791
+ assert_ldif_to_s(<<-EOL, ldif_source)
1792
+ version: 1
1793
+ dn: cn=Barbara Jensen,ou=Product Development,dc=airius,dc=com
1794
+ objectclass: top
1795
+ EOL
1796
+ end
1797
+
1798
+ def test_dn_spec
1799
+ assert_invalid_ldif("'dn:' is missing",
1800
+ "version: 1\n", 2, 1, "version: 1\n|@|")
1801
+ assert_invalid_ldif("DN is missing",
1802
+ "version: 1\ndn:", 2, 4, "dn:|@|")
1803
+ assert_invalid_ldif("DN is missing",
1804
+ "version: 1\ndn::", 2, 5, "dn::|@|")
1805
+ assert_invalid_ldif("DN is missing",
1806
+ "version: 1\ndn:\n", 2, 4, "dn:|@|\n")
1807
+ assert_invalid_ldif("DN is missing",
1808
+ "version: 1\ndn: \n", 2, 5, "dn: |@|\n")
1809
+
1810
+ dn = "cn=Barbara Jensen,ou=Product Development,dc=example,dc=com"
1811
+ cn = "Barbara Jensen"
1812
+ assert_valid_dn(dn, "version: 1\ndn: #{dn}\ncn:#{cn}\n")
1813
+
1814
+ encoded_dn = Base64.encode64(dn).gsub(/\n/, "\n ")
1815
+ encoded_cn = Base64.encode64(cn).gsub(/\n/, "\n ")
1816
+ assert_valid_dn(dn, "version: 1\ndn:: #{encoded_dn}\ncn::#{encoded_cn}\n")
1817
+ end
1818
+
1819
+ def test_version_number
1820
+ assert_valid_version(1, "version: 1\ndn: dc=com\ndc: com")
1821
+ assert_valid_version(1, "version: 1\r\ndn: dc=com\ndc: com\n")
1822
+ assert_valid_version(1, "version: 1\r\n\n\r\n\ndn: dc=com\ndc: com\n")
1823
+
1824
+ assert_invalid_ldif(["unsupported version: %d", 0],
1825
+ "version: 0", 1, 11, "version: 0|@|")
1826
+ assert_invalid_ldif(["unsupported version: %d", 2],
1827
+ "version: 2", 1, 11, "version: 2|@|")
1828
+
1829
+ assert_invalid_ldif("separator is missing",
1830
+ "version: 1", 1, 11, "version: 1|@|")
1831
+ end
1832
+
1833
+ def test_version_spec
1834
+ assert_invalid_ldif("version spec is missing",
1835
+ "", 1, 1, "|@|")
1836
+ assert_invalid_ldif("version spec is missing",
1837
+ "VERSION: 1", 1, 1, "|@|VERSION: 1")
1838
+ assert_invalid_ldif("version number is missing",
1839
+ "version:", 1, 9, "version:|@|")
1840
+ assert_invalid_ldif("version number is missing",
1841
+ "version: ", 1, 10, "version: |@|")
1842
+ assert_invalid_ldif("version number is missing",
1843
+ "version: XXX", 1, 10, "version: |@|XXX")
1844
+ end
1845
+
1846
+ private
1847
+ def assert_ldif(version, records, ldif_source)
1848
+ encoding = ldif_source.encoding if ldif_source.respond_to?(:encoding)
1849
+ ldif = ActiveLdap::Ldif.parse(ldif_source)
1850
+ assert_equal(version, ldif.version)
1851
+ assert_equal(records,
1852
+ ldif.records.collect {|record| record.to_hash})
1853
+
1854
+ regenerated_ldif = ldif.to_s
1855
+ set_encoding(regenerated_ldif, encoding)
1856
+ reparsed_ldif = ActiveLdap::Ldif.parse(regenerated_ldif)
1857
+ assert_equal(ldif, reparsed_ldif)
1858
+
1859
+ ldif
1860
+ end
1861
+
1862
+ def assert_valid_dn(dn, ldif_source)
1863
+ ldif = ActiveLdap::Ldif.parse(ldif_source)
1864
+ assert_equal([dn], ldif.records.collect {|record| record.dn})
1865
+ end
1866
+
1867
+ def assert_valid_version(version, ldif_source)
1868
+ ldif = ActiveLdap::Ldif.parse(ldif_source)
1869
+ assert_equal(version, ldif.version)
1870
+ end
1871
+
1872
+ def assert_invalid_ldif(reason, ldif, line, column, nearest)
1873
+ exception = assert_raise(ActiveLdap::LdifInvalid) do
1874
+ ActiveLdap::Ldif.parse(ldif)
1875
+ end
1876
+ reason, *params = reason
1877
+ params = params.collect {|param| param.is_a?(String) ? _(param) : param}
1878
+ assert_equal([_(reason) % params, line, column, nearest, ldif],
1879
+ [exception.reason, exception.line, exception.column,
1880
+ exception.nearest, exception.ldif])
1881
+ end
1882
+
1883
+ def assert_ldif_to_s(expected_ldif_source, original_ldif_source)
1884
+ ldif = ActiveLdap::Ldif.parse(original_ldif_source)
1885
+ assert_equal(expected_ldif_source, ldif.to_s)
1886
+ end
1887
+
1888
+ def set_encoding(string, encoding)
1889
+ string.force_encoding("utf-8") if string.respond_to?(:force_encoding)
1890
+ end
1891
+ end