clwiki 2.4.0 → 3.0.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 (239) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +19 -9
  3. data/app/controllers/cl_wiki/application_controller.rb +29 -1
  4. data/app/controllers/cl_wiki/page_controller.rb +52 -38
  5. data/app/controllers/cl_wiki/sessions_controller.rb +30 -0
  6. data/app/helpers/cl_wiki/application_helper.rb +3 -1
  7. data/app/models/cl_wiki/user.rb +89 -0
  8. data/app/views/cl_wiki/page/edit.html.erb +5 -1
  9. data/app/views/cl_wiki/page/recent.html.erb +1 -1
  10. data/app/views/cl_wiki/page/recent.rss.builder +10 -8
  11. data/app/views/cl_wiki/sessions/new.html.erb +10 -0
  12. data/config/clwiki.yml +16 -30
  13. data/config/initializers/clwiki.rb +4 -3
  14. data/config/routes.rb +9 -0
  15. data/lib/cl_wiki.rb +5 -1
  16. data/lib/cl_wiki/configuration.rb +28 -137
  17. data/lib/cl_wiki/engine.rb +3 -1
  18. data/lib/cl_wiki/file.rb +140 -117
  19. data/lib/cl_wiki/format/format.blockquote.rb +8 -6
  20. data/lib/cl_wiki/format/format.graphviz.digraph.rb +8 -7
  21. data/lib/cl_wiki/format/format.opml.rb +11 -9
  22. data/lib/cl_wiki/format/format.pre.blockquote.rb +8 -6
  23. data/lib/cl_wiki/format/format.simpletable.rb +10 -8
  24. data/lib/cl_wiki/memory_index.rb +102 -0
  25. data/lib/cl_wiki/page.rb +129 -257
  26. data/lib/cl_wiki/public_user.rb +9 -0
  27. data/lib/cl_wiki/user_base.rb +25 -0
  28. data/lib/cl_wiki/version.rb +3 -1
  29. data/lib/cl_wiki_lib.rb +9 -0
  30. data/lib/tasks/index.rake +4 -4
  31. data/test/dummy/app/assets/config/manifest.js +3 -0
  32. data/test/dummy/config/application.rb +1 -0
  33. data/test/dummy/config/environments/development.rb +2 -0
  34. data/test/dummy/config/initializers/clwiki.rb +3 -0
  35. data/test/dummy/config/routes.rb +3 -0
  36. data/test/dummy/log/development.log +5909 -0
  37. data/test/dummy/log/test.log +33349 -0
  38. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/-8/-8X-3n5w3EAS5uiBS2GQxjMlqD43Qout1GsSJUU6e4k.cache +1 -0
  39. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/-P/-Pa1BPD1Ps1OvnKPyrGE4MiUEnlzMEccXN8CzzxSRjM.cache +1 -0
  40. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/0k/0ktSefuSiZXp-1v5uXwST57lRoAF2HvHzclO4Gtftgo.cache +0 -0
  41. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/1V/1VmPI9-8O9Y8OP-JxSXl7-yNRMZHqapeh2drmkXiRGE.cache +1 -0
  42. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/2W/2WKPDryRtGzZO6Uedw4RNjnI5M9YVH-IbFg5GvLvTTQ.cache +0 -0
  43. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/3G/3GuA3P7RM10Vv7NgdH65pwfAH7gMHlJ_xBUO74i-ZjM.cache +0 -0
  44. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/3S/3SzCkB81tc9XbtFdEYxCeR3If141gvhEnHchU_C6hHs.cache +1 -0
  45. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/41/41dY2GtQJAt3CmkQn8IDa9B3clQaUT6XymanCfFZR2o.cache +0 -0
  46. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/46/46WEPovJzlkEgsdG0aV08HiNsRkf0L8Txt1SWLi4atg.cache +1 -0
  47. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/4I/4Ir0PJhTRUd9iGlSu6n2AREP-_amedFe4-1fKwB2wvg.cache +1 -0
  48. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/5L/5LXSsjTcB5Un8FHlrhi6AOjxwgzWoXeWBhU_hi1gdcg.cache +1 -0
  49. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/67/67V_0cxwrU68Onen7N2Lb9bTd1jLulH06F9zh1VgZ0U.cache +1 -0
  50. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/6A/6AXD3XLczHK8MPb5e10-7sLcS45ZrP7Iwgyo9xle0nU.cache +0 -0
  51. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/6D/6D8TdXG6KyMkGDvPbv87qUCDz9_6gRZbNAohojB484w.cache +1 -0
  52. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/7L/7LVfTxjfHpOSp2FeG-uhloqIUqIZ7uE3nT40dqhoqY8.cache +2 -0
  53. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/7b/7bceaEE3qsyoVjeou6RR-V9w2Wgzraq0OI2erU4s9ew.cache +1 -0
  54. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/7h/7hRfgp9EsoD33qh0aNXeyg9qdGapPlUT6FmcL8xztY4.cache +0 -0
  55. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/8c/8cq-JtJ9Zwg4F0bFdkqaGHjdB7a9JBmfDO_sczTWycI.cache +1 -0
  56. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/8h/8hO7EIQ5iOa2rL6ZlP318Lrk0unB2CfhHCI0TrUr-Oo.cache +0 -0
  57. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/8x/8x0PXM3vatUzVGk-vKi80S7LXrGb6bE-3EzEj54VNak.cache +1 -0
  58. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/9v/9vfh8eoLcnq3s_rolIXPs15SPTQWGxJrrjpJ3PoABek.cache +1 -0
  59. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/9w/9w-0hdVYmxONDHQlpGn7DFzlRA3oXqpW4x3t9LBUU6M.cache +1 -0
  60. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/B3/B385Es3x0hpGSQNWzSjiDcExPuEV9m1dUZWlEp5zGbw.cache +0 -0
  61. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/BR/BRBOvy22uVEx9Z5Aal_0BfPilVYEQl6AYXG2u8yBqBg.cache +0 -0
  62. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/BX/BXdNycvZI2UN7cgqvk6P4MQCc1PH2bTwa9i9vP-s-jk.cache +0 -0
  63. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/CO/CO-z80mMyQGRy-BwknxOV5bI2IFbcMMNc05j7v8Nqso.cache +0 -0
  64. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Cg/CgPqTXtSkCxEox0z95JfY89MndA2GhTTQK39fjKk6QU.cache +1 -0
  65. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Ct/CtQeoxqXfctXd_NvChnCVaJ_cCjNuXJMv3LBXhswU6A.cache +0 -0
  66. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Dc/DcZ_YfpX7rLYFw-u7jSJCRp_z0iIyB7XKOcwm1cQexk.cache +0 -0
  67. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Ex/Exqg59Ton1SZt_QH4hMa7wUFOAuIQnCan8B9578NzIg.cache +0 -0
  68. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/F5/F5c-QANC5X3kApAecuyiMZEme0NT_UUB6SjxKvb0ALg.cache +1 -0
  69. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Fd/FdwPBPhLtL4s8RSPhJ53YoYoFdRkNxANV_zQYw-KsVc.cache +1 -0
  70. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/GK/GKrbCoxDofzkQCmA17lE84OT6RW_6NKm7jwyZ4n2T6s.cache +0 -0
  71. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Gh/GhVuWwPtbWpQY_Ny4MyilnH9iUqCPxTDzOonAXM4od8.cache +1 -0
  72. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Gv/GvQrSgGYXiR-rgsPHFZq1oJ5zCkDK54muqIw6KW2GyA.cache +0 -0
  73. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Gw/Gwhhfk9vS7QWmHsW90WtAt0_Rp_7AIM-ZcHmEqLf_Rg.cache +1 -0
  74. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/H5/H5Yxi2VJxpyMb-cbgwBNua8O2zZ03Jk4ByV6yhIzAsQ.cache +0 -0
  75. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/I0/I0OpFIfCc595P02GZa3LUD1uD-Payl41dWaW3oZSK7g.cache +1 -0
  76. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/IQ/IQoDS19BmJjvixXd16O_7P6DB-GRUEZgdNJexJ88fIc.cache +1 -0
  77. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/I_/I_zDBUxxL4b2Wk9_qqVs56Abw1jGccc4FgvKwuscswQ.cache +1 -0
  78. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Ig/IgcuJMmmdeYrq2F3D721tC7ficyRm92HIrLkim5DCxQ.cache +1 -0
  79. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/JI/JITjXC3hXUPgOQhDYsVjhPNjtTISt0j5uz2bjfoiSHI.cache +1 -0
  80. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/KL/KL75rsyvMJSIkYkXRijxh8cs7V1wtfLPjuodISQK5vc.cache +0 -0
  81. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Kw/KwqVMeMNxvnaSP-a-H5nkYyxloW_xoqR5JhEnqJ9puQ.cache +1 -0
  82. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/L1/L1KghIbeezpqVDyhAbCDc4pG11ElC5JpUl319-ZlZn8.cache +0 -0
  83. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Lh/LhI7QMLwiVavmyvwYzdc_t_V9OATXaBO8aCB2swJFCk.cache +1 -0
  84. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Lh/LhqYyoCtzXpfZq6UOhmZuZLSaAwZRX44sHfwPvPqezc.cache +2 -0
  85. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Lo/Lovn2yBpV04WnAQwZeM3hLL015H5syYBH2ufgIc6qCM.cache +1 -0
  86. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Lz/LznMZWa43whMHpqnPRsbUfREY3y_fiXQKaiKVEYW4fw.cache +0 -0
  87. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/MC/MC7GYdrSShtV64GB3hoINaYL3vCRZKq9KvwcwrJAdQo.cache +1 -0
  88. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/MU/MU6iF1YPAQqpVK_kVAtiJPtbHaYpYdOcO0g5bJ9exj8.cache +0 -0
  89. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Md/MdIg3XLcnbFsMXC-6xslVtmBvWH7Q21BSt9l5pm305o.cache +0 -0
  90. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Mw/Mwfi5Xeky61jhIuc6ooo4439CHOyz1hS48_taMRSlKM.cache +1 -0
  91. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Ni/Ni5yuK9FFnhLe5HciROve12UIYstBdESWm0LfdcuVVs.cache +1 -0
  92. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Nz/Nz3hkLq4WlqgoHg_ChdHSXbP7fVmCWCTw0lH0jkMmDg.cache +0 -0
  93. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/O3/O38OvSNrhXKbxauuC8GOBBnKrt2-rPaDmfyrXScgHcA.cache +1 -0
  94. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/OS/OSm-zAlxXS63lBjvzJeSWfqq5d3D9fu-_nBVFWyQ4j0.cache +0 -0
  95. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Oa/Oazc9AJ4e_67dU0aArJeCNEeWJKMIFPtAJtxTJoUKcs.cache +1 -0
  96. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/PV/PVDpEMY_ha4kHETTb3QvjOBoBUP4PMjNDNcIAgmDy2I.cache +1 -0
  97. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Pl/PldDxSvU1o_UFPYTE0GJmUS9mHQXH88zEw5HN6GtlRE.cache +1 -0
  98. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Pu/PuU5S_LPnhAX43U1VVN3qP_sv0ph4stXSGo7I0e_jOw.cache +1 -0
  99. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/QJ/QJ6RPZNUkui_k3wTkb62zo8wczYY7q0B174GfSJjjWE.cache +2 -0
  100. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/QX/QXCyCL-Eeb3uHm9iOvs4anspZqeFbQnNyzDfIsXgzC8.cache +0 -0
  101. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/R1/R1F4Qf-kXTMH0fTLahalFTHtNBvgDfkOkrPyW8zeN_E.cache +0 -0
  102. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/R1/R1__Y-gz4zkDYrXWyCf6YTkvXO0RZlrpK6ynGGVuvnM.cache +0 -0
  103. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/R2/R2Xqb6eAeUW2xTaTaTjlkyUCirkb1qfYgW2CyY80VjM.cache +1 -0
  104. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/RM/RMXouh7GkRuhy8S6jnpxFD27HRVT0LEHj9iR53ps4o4.cache +1 -0
  105. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/RV/RVmt1mCn0tykR8xyBylvh-Hvi-Am87neA2IEkYHjg-g.cache +1 -0
  106. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Tg/TgTXCuKAEg1DI5zjHO8tGMGuQGC9BRt9vgDZj2FdSa8.cache +1 -0
  107. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/UI/UIyRfqj_T27DnyWJiZK9BdUGTIDTQ9M953ArtrYz5fM.cache +1 -0
  108. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/U_/U_F-o3fo7oUYyn0O5KBlt3jOF53X_-4UuZb-_alPZPk.cache +1 -0
  109. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/U_/U_KCsVrX_QoGJ_FpUpCNU3XMT36CThwu8_0HYj_2k4w.cache +1 -0
  110. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/U_/U_ie5WwVJPItNZrqfbIrnZpaRokYT5klrYU92QSugd8.cache +0 -0
  111. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Ub/Ub-oUCoAiliSW8ohVsmtsflc4nPeiBvcjzgNbPLYQRc.cache +0 -0
  112. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Ud/UdvIJcVNQ_08Vaoyx4KuRGNjazpB9-qjOtDMTud8R0Y.cache +1 -0
  113. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Uz/UzEG5I_EszWbaSVnk497D0KfuIzsgHoPLVQd7e3mlQg.cache +1 -0
  114. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/V-/V-F9X0mrPgfTELxk9xdYnb27trOmB6nBDL973YWeOfU.cache +0 -0
  115. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/VA/VAOOXmbiiPy1jqpQQCDVrhkByG3pdeJoZCOvVkp-XVY.cache +1 -0
  116. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/VV/VVIuIm_HUOaEdZfXt-CmFQZb3ycoiXeeI-FV7nwkr0Y.cache +1 -0
  117. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/VX/VXHQHhwOUBuWlKPY6smpXG1xjASw927lyjUKBXBh3e0.cache +0 -0
  118. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Vn/VnMqvZo9nqGF_5tt3gNbMyoG8jJVm0K0r1fANEBjfkw.cache +0 -0
  119. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/W1/W1YuEAoPMZTXfbxg_xWV9o2RP60SAKs5bhk7teKdL2g.cache +1 -0
  120. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/W2/W2ZyYMlYmyA7_1WcpiWhYUJa6wfPCZ5kZj_-Nuw31yM.cache +0 -0
  121. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Wg/WgwI9C5-mh_smtsTGVmH4y76T5ifM4M_hKL1fn-K8iw.cache +2 -0
  122. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/X5/X5GHIj6tnz-w7d-60OaYcbzJczzkTBtm24BOxzoSDdo.cache +1 -0
  123. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/X6/X6jU4SPOD_b1ks9tCApsvWRa7q8cBYCjw3gI6Dwvr34.cache +2 -0
  124. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/X8/X88lT-cwuuj8gqiNY83uVqXFgeLcaHMc9Xh2X4Iux6k.cache +0 -0
  125. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/XQ/XQ0aFc1cceisG4P8qUPhW8z1H3I71pMguVRRMgJ66cs.cache +5 -0
  126. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Xh/XhXLVYOEEwpzOBAWDdiCEpTMz7vC8wnlBHYHJkySh-0.cache +1 -0
  127. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/YB/YBJNyX7HNPq78obeHYRGnJKSVl9EtRPbcGD253-ia34.cache +0 -0
  128. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Yu/YupDX89OAJ6u3BHBW-UJgO3nDfi7hwlpf_JHlnM8b6k.cache +1 -0
  129. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/ZH/ZHN5sHdNMxUCl3Ese5T5_AzQbD9WHqpgBL4PBOrgXJY.cache +1 -0
  130. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/ZP/ZPRvYWthjzuQ0tqk5AdgQbeTUqhDboF8bvTtdrmg4Jo.cache +1 -0
  131. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/ZV/ZVu2Ed9wpdsPLKStP971oLEJBwgJQHLInXIiQkIWC04.cache +0 -0
  132. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Zb/ZbnyIl6znMAVquD2ZD5OYA9SPXmQJYWU7V8F2Hgp3Uc.cache +0 -0
  133. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Zj/ZjALwFkjfG3uebsyy_CeJp5VQMJLE03zxPxkNp-sZDA.cache +0 -0
  134. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/_F/_Fu404i1O4mKpjPluBsq-3FZQnyQvla_6jDnH03Lpw8.cache +2 -0
  135. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/a-/a-t90hz_PZnc6ImKhk-cIh_WBB9vi_rChKzLv4hMBqw.cache +1 -0
  136. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/a5/a5cnzGcRAu4dPakq4_DHH9GanK42Ov5O1F62oeJR4Zo.cache +1 -0
  137. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/aJ/aJK2kxoM9CsnZpxiFvP6RoP0sxHBiix9X1P6Mhy9Dcg.cache +2 -0
  138. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/aO/aOU10S2QEOBHcdKwGRfXqqHdYshmYD20LYiJIGMzIa0.cache +1 -0
  139. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/aZ/aZEdK7dgijyjIs26V_QbKsDgO5JxeYXiT0Sl28M0e-U.cache +0 -0
  140. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/aq/aqBnFJWuQ-xmdUL8_asWtElNRrMr0W60LVdDqpt43L8.cache +1 -0
  141. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/b5/b5KTv2Hrf5faN7X4XahT1s8L5t-EANtcFKrMEsGm3lw.cache +1 -0
  142. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/bF/bFemYCjG73k2_Ys77S7qNyW7CYcyw4bngyc0OGneI-s.cache +1 -0
  143. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/bG/bGdy8gJL8acOmxK8AbkYbxNuakf4LlMZ-zPBkyL0E-0.cache +1 -0
  144. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/bK/bKm8sxC3i0ycUMXr6pnD61MdwytUWfpNOJlBY6qJaWg.cache +1 -0
  145. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/dA/dA1M22RMQvVwb74tbFg-_237SferZuCI10s4R0zx8NI.cache +0 -0
  146. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/dF/dFOzXjFeRtB5bukRI9wGrh2O_GkOeBPnrJRMiv8_ZbM.cache +0 -0
  147. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/dw/dwbXKkD4yllXOeD4T7BKoGvLS26j9lxMkjMiIxfyt6E.cache +0 -0
  148. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/eT/eTgN8O1TgsFV61pclFzCmmJ9qT7MgyGvtQrmRtJoNeg.cache +0 -0
  149. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/eu/eu6Xg0psMCuHIWG0WjCo9wwNOlWs-Z5OH4SyGEmdTNQ.cache +1 -0
  150. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/fC/fC-TBNdh4rVupPn2ObyZeIx6OSlpBSBQZfIzywI6xx0.cache +0 -0
  151. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/fR/fRIbNtGTaNqdwIDyusrUmllglSGMNnqnw7VOLvf5D_k.cache +1 -0
  152. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/fq/fq7SFxQSEFZCuS7jQj0n-BQfbJ5mpLpmJQsd9mJVq68.cache +1 -0
  153. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/gG/gGBN3yxvq8azMjDv3hsSw_zLUj9KLuqHPDXZK8x8pFc.cache +0 -0
  154. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/gd/gd3J0EmNeiTh2GzxcAKItmtUnUay9NG4Sm2vkiLKvmA.cache +1 -0
  155. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/gj/gjXteWe57D8FaBOQUw29N_mwHCeTQW8oLjyv8fu3wNw.cache +3 -0
  156. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/gt/gtFeEhjHn0G9WhgiMKaNtXVgNYW9s_wBLE0VGegeAN8.cache +1 -0
  157. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/hA/hA4-M5cp310ZkSe59_BWszdgXy7mmYagSRCfelGBA9o.cache +1 -0
  158. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/iC/iC3FCadetljjEIeMWfeqqDoMxhJi6rI20BpiVxtvgS4.cache +1 -0
  159. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/iV/iV16_jyEayI_vLgHw3HFhtJAiVOCIlzFho0Yt7a4v_Y.cache +0 -0
  160. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/j6/j62KRIr4T81zq1Ujpg7AJRQdI0ry9HGKPt4nK6fRt1g.cache +1 -0
  161. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/jR/jRg0Zbr59-UMtrWO5t2VWNI3GqU7XWOUsE44dX5cPyk.cache +0 -0
  162. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/jj/jj9HUpCSrLEyONEZNLLkgJ8hJmxOCLpcVJeiBa0KDsE.cache +1 -0
  163. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/jq/jqnMk9arxuef2cdSQuxj3WOQuAfGKup3H2pjO7x1DOg.cache +0 -0
  164. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/k1/k14rvggyKI9dk-yVjn-Lk0p8qU360H_JuVG9aZ4q0OM.cache +1 -0
  165. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/kb/Kb8Z49kajAX1vyy5d4-gA8StHhQp5yOUs0wtdZ7m8Hc.cache +1 -0
  166. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/kb/kbEMkrgp2k0pezn_gFfMqA142QwoJYBKMj7cEkE-Hag.cache +1 -0
  167. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/lD/lDpZHp5gBhRdNHdj1TwWq1_LZ_a56lxeksxqaEs2efA.cache +1 -0
  168. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/mE/mEfGHxLvdPQrcbpjLw4q_wOPirMzrR4z58KgozQ1zNY.cache +1 -0
  169. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/mM/mMZ3DR5b7kx70JtEg-ImWOa_V1jnHcWgHqNqapxIMXk.cache +0 -0
  170. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/mX/mXCT6vriuTtwLaKGnTa5hwXSrwGtAmP6pV5lmjbHaYM.cache +0 -0
  171. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/mZ/mZjIy4zRS4hbS4vWHpdKd7jeZgLatEx_nlFqv_KSCrs.cache +0 -0
  172. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/mg/mge36-9r2gGuKcPoghbLDM72AV4gIVTl6gQDbk7hrkg.cache +1 -0
  173. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/nK/nKZaLuUqTl9pf5Nb1oVuabxd74q4oN8YTBeo6bNd-Vk.cache +0 -0
  174. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/nP/nPbHGaYfJSLZ2K3YTROe7T1RPqKoBQJwawQtZ_FN1-I.cache +0 -0
  175. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/o9/o9KyTznHG0ZIHDI7kTg1Jp78qaga7gJqouXSKdocEjA.cache +1 -0
  176. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/oB/oBupyQ9cW436mBji6Rp7TtHE6CX_r8iq2sCBo0LNbc8.cache +1 -0
  177. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/oN/oN3TypgxDDLqcxy0Funa4RVCYXS-7qn6D56wgBiUT2Q.cache +1 -0
  178. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/om/omGcA_eTFAFIH3RJaPOpEW3yz0074cob3hozQFLOAxk.cache +1 -0
  179. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/p0/p0WHrZZBaXbPaNj5XmQGTli4mi08Rv8DidQfwj28a6w.cache +0 -0
  180. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/pA/pAvUFBt71eJx7E7oQbIxrEZ8YcMo9kboyGxjk73ZWrI.cache +1 -0
  181. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/pB/pBwzUQUu-GcmLiQwn6KnbbDP0ipnVHzVaeArqdpqi98.cache +0 -0
  182. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/pC/pCePfKbmTQ6s2Tl7ki3oBput2ruhpCzpa6Vvejbb5xg.cache +1 -0
  183. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/q6/q6BYa32YJF11eGVapO4ouNl6gayPIsARgMavlzZmoi0.cache +0 -0
  184. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/qY/qY78GTTnufmP1eP2CE16x833zGfQ0F5EVCFtUTMQ7Mw.cache +1 -0
  185. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/qm/qmZZzCnL9PLIyZ0iBu6Alr69AUfHHI1fKdNRRgG04yg.cache +1 -0
  186. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/s5/s5yv3jYvjyKZJ8SMzpj94eMKEuX46lAWV1ApHF-6bsM.cache +1 -0
  187. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/sO/sOBPF_p4Te56V9vdLV0Ywn6djNbmdPSIzvgYNPnAXYc.cache +0 -0
  188. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/sv/sv0a_JAC4GSc_cK-2OUAzhFwm_K3qzSfDefwpcqOCk4.cache +1 -0
  189. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/sw/sw2EAksRkslJNoJJCTS2FPOfHWCYvsS86AxmRMPjens.cache +1 -0
  190. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/t1/t1cv6bP9cTAIs82lyIsnXGeAwB1KNVY5_5rgUvelr04.cache +0 -0
  191. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/tO/To1SPyNegqysLIqhSzrNQPh1VKKj19MespjJediCde4.cache +1 -0
  192. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/tO/tOPkZNrO9FRDhSlCf7VWOexxRq2CE2X4_6KjyxJkq2A.cache +0 -0
  193. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/tR/tRoxwnX8bACHK5pW9tIi4ILY4XuYTIpueH0fGr2t0rc.cache +1 -0
  194. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/t_/t_bP70PmOB70862dwKmCTkmZuzTqCreOzNYW4Yn2n6A.cache +1 -0
  195. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/uj/ujdE_ewC5UIxr6uw5F7YRfKKWiu8-15wzBlOjYHsnkQ.cache +1 -0
  196. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/ut/ut8uBMdgxX8_wfU0l6kGew6H8TLXAj74kFnaI252F3k.cache +1 -0
  197. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/ut/utQEOZtBKQK_bUUDeZX4Mgk00L4AOMVyq6zrKAoo1Xw.cache +0 -0
  198. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/vm/vmjBl9ZCF5hj4sG4e2nid94GcRQYmsOsu-_Q3Zlud5c.cache +0 -0
  199. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/vz/vzBoVc4GQWi4UFp-4dBJnzrhyUuokPV8SCOxsdpOht8.cache +0 -0
  200. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/wM/wMWxmf8BN_NAJRCyardukpfDMwts44Bz2a8doi-49Rg.cache +1 -0
  201. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/x7/x7KkTV3ibfIEysLB_ug5bfmnn2VLV_BldukPR3EoPBk.cache +0 -0
  202. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/x7/x7iSOdqAIVmVpn9ujTwJ_C7EqUgmMSri5vjjHdRIX10.cache +1 -0
  203. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/xY/xYdD9O1JRIfpVj9Kw_b3JTUBQZLI_dcy-bf9uXEp-jg.cache +0 -0
  204. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/xx/xxkulLgT-tkVeDC50gUXRGGMou47BUdlYOwgs0j5muY.cache +1 -0
  205. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/yn/yn_3aZZwyjcI0O6fwisZ7zvcu4Gq5bV31g3tHFxfQNg.cache +1 -0
  206. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/yq/yqwjyepbYY4ctoMOySWiOIWUYwzl_BczAmXqJ5DPvb0.cache +0 -0
  207. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/z9/z9HQmzff5j_6CFyk6eQ52nYt9cPLXsxDQY0Yep1Hz-0.cache +1 -0
  208. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/zM/zMvcc87IG1SRbqwUNtWQfHgeWr5XN36OU8vg-v3rUus.cache +0 -0
  209. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/zn/znjQpjNzh1iUAe9DljeFghnStRvqNIr1GuOTibVcEJQ.cache +0 -0
  210. data/test/dummy/tmp/testrep/BazQuux.txt +5 -0
  211. data/test/dummy/tmp/testrep/FooBar.txt +5 -0
  212. data/test/dummy/tmp/testrep/NewPage.txt +5 -0
  213. data/test/dummy/tmp/testrep/users/testy.json +1 -0
  214. data/test/dummy/tmp/wikirep/FrontPage.txt +5 -0
  215. data/test/dummy/tmp/wikirep/users/chrismo.json +1 -0
  216. data/test/dummy/wikirep/EncryptedPage.txt +0 -0
  217. data/test/dummy/wikirep/FrontPage.txt +11 -4
  218. data/test/dummy/wikirep/users/chrismo.json +1 -0
  219. data/test/helpers/wiki_helper_test.rb +2 -0
  220. data/test/lib/clwiki/clwiki_test_helper.rb +19 -2
  221. data/test/lib/clwiki/file_owner_test.rb +58 -0
  222. data/test/lib/clwiki/file_test.rb +85 -56
  223. data/test/lib/clwiki/memory_index_test.rb +61 -0
  224. data/test/lib/clwiki/page_test.rb +71 -148
  225. data/test/lib/clwiki/test_base.rb +19 -19
  226. data/test/test_helper.rb +7 -5
  227. metadata +398 -23
  228. data/lib/cl_wiki/find_in_file.rb +0 -33
  229. data/lib/cl_wiki/index.rb +0 -458
  230. data/lib/cl_wiki/tools/cron.reminders.rb +0 -241
  231. data/lib/cl_wiki/tools/movepages.rb +0 -27
  232. data/lib/cl_wiki/tools/pagestomove.txt +0 -56
  233. data/lib/cl_wiki/tools/rublog/clWiki.rb +0 -62
  234. data/lib/cl_wiki/tools/rublog/readme.txt +0 -2
  235. data/lib/cl_wiki/tools/singlepage.rb +0 -58
  236. data/lib/cl_wiki/tools/test/singlepagetest.rb +0 -9
  237. data/lib/cl_wiki/tools/thunderbird.rb +0 -23
  238. data/test/lib/clwiki/find_in_file_test.rb +0 -111
  239. data/test/lib/clwiki/index_test.rb +0 -32
@@ -1,8 +1,9 @@
1
- require 'cl_wiki/configuration'
1
+ # frozen_string_literal: true
2
+
3
+ require_dependency 'cl_wiki/configuration'
2
4
 
3
5
  filename = File.join(File.dirname(__FILE__), '..', '..', 'config', 'clwiki.yml')
4
6
 
5
- conf_hash = YAML::load(::File.open(filename))[Rails.env]
7
+ conf_hash = YAML.safe_load(::File.open(filename))[Rails.env]
6
8
  conf_hash['wiki_path'] = ::File.expand_path(conf_hash['wiki_path'], Rails.root)
7
9
  $wiki_conf = ClWiki::Configuration.new(conf_hash)
8
- $wiki_path = $wiki_conf.wiki_path
@@ -1,14 +1,23 @@
1
+ # frozen_string_literal: true
2
+
1
3
  ClWiki::Engine.routes.draw do
2
4
  root to: 'page#show'
3
5
 
4
6
  # legacy CGI
5
7
  match '/clwikicgi.rb', to: 'page#show', via: [:get], as: 'legacy'
6
8
 
9
+ # Ordering of routes matters! Anything specific, like `find` needs to be
10
+ # _before_ the `/:page_name` route, otherwise it matches on `/:page_name`
11
+ # before matching on the specific route.
12
+
7
13
  get '/find' => 'page#find', as: 'page_find'
8
14
  post '/find' => 'page#find'
9
15
 
10
16
  get '/recent' => 'page#recent', as: 'recent'
11
17
 
18
+ get '/login', to: 'sessions#new'
19
+ post '/login', to: 'sessions#create'
20
+
12
21
  get '/:page_name' => 'page#show', as: 'page_show'
13
22
  get '/:page_name/edit' => 'page#edit', as: 'page_edit'
14
23
  post '/:page_name' => 'page#update'
@@ -1,5 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'cl_wiki/engine'
2
4
 
5
+ require_relative 'cl_wiki_lib'
6
+
3
7
  module ClWiki
4
8
  =begin
5
9
  http://edgeguides.rubyonrails.org/engines.html#inside-an-engine
@@ -9,4 +13,4 @@ module ClWiki
9
13
  options, the file where your engine's module is defined is perfect for that. Place
10
14
  the methods inside the module and you'll be good to go.
11
15
  =end
12
- end
16
+ end
@@ -1,83 +1,43 @@
1
- require File.dirname(__FILE__) + '/index'
1
+ # frozen_string_literal: true
2
+
2
3
  require 'yaml'
3
4
 
4
5
  $defaultConfFile = 'clwiki.yml'
5
6
 
6
7
  module ClWiki
8
+ # noinspection RubyTooManyInstanceVariablesInspection
7
9
  class Configuration
10
+ attr_accessor :wiki_path, :cssHref, :template, :publishTag, :url_prefix,
11
+ :global_edits, :page_update_format, :use_authentication,
12
+ :owner, :encryption_default
13
+ attr_reader :custom_formatter_load_path, :edit_rows, :edit_cols, :editable
8
14
 
9
- USE_INDEX_NO = 0
10
- USE_INDEX_DRB = 1
11
- USE_INDEX_LOCAL = 2
12
-
13
- attr_accessor :wiki_path, :cgifn, :indexPort, :cssHref, :template, :useGmt,
14
- :publishTag, :url_prefix, :global_edits, :cgifn_from_rss, :stats_name,
15
- :index_log_fn, :page_update_format
16
- attr_reader :custom_formatter_load_path
17
-
18
- def wait_on_threads
19
- # Ruby kills any threads as soon as the main process is done. Any
20
- # threads created should be registered here. The last
21
- # line of the CGI script should call out to wait_on_threads to make
22
- # sure nothing running async in the background is terminated too early
23
- @threads.each do |thread|
24
- thread.join
25
- end if !@threads.nil?
26
- end
27
-
28
- def wait_on_thread(thread)
29
- @threads = [] if !@threads
30
- @threads << thread
31
- end
32
-
33
- def useIndex
34
- @useIndex
35
- end
36
-
37
- def useIndex=(value)
38
- @useIndex = value.to_i
15
+ def initialize(hash = {})
16
+ default_hash.merge(hash).each do |k, v|
17
+ instance_variable_set(:"@#{k}", v)
18
+ end
39
19
  end
40
20
 
41
- def edit_rows
42
- @edit_rows
21
+ def default_hash
22
+ {
23
+ url_prefix: '/',
24
+ publishTag: nil,
25
+ useIndexForPageExists: false,
26
+ edit_rows: 25,
27
+ edit_cols: 80,
28
+ custom_formatter_load_path: [],
29
+ use_authentication: false
30
+ }
43
31
  end
44
32
 
45
33
  def edit_rows=(value)
46
34
  @edit_rows = value.to_i
47
35
  end
48
36
 
49
- def edit_cols
50
- @edit_cols
51
- end
52
-
53
37
  def edit_cols=(value)
54
38
  @edit_cols = value.to_i
55
39
  end
56
40
 
57
- def useIndexForPageExists
58
- @useIndexForPageExists
59
- end
60
-
61
- def useIndexForPageExists=(value)
62
- if value.class == String
63
- @useIndexForPageExists = (value =~ /true/i)
64
- else
65
- @useIndexForPageExists = value
66
- end
67
- end
68
-
69
- def access_log_index
70
- @access_log_index
71
- end
72
-
73
- def access_log_index=(value)
74
- if value.class == String
75
- @access_log_index = (value =~ /true/i)
76
- else
77
- @access_log_index = value
78
- end
79
- end
80
-
81
41
  def override_access_log_index
82
42
  @orig_access_log_index_value = @access_log_index
83
43
  @access_log_index = false
@@ -87,85 +47,16 @@ module ClWiki
87
47
  @access_log_index = @orig_access_log_index_value if @orig_access_log_index_value
88
48
  end
89
49
 
90
- def editable
91
- @editable
92
- end
93
-
94
50
  def editable=(value)
95
- if value.class == String
96
- @editable = (value =~ /true/i)
97
- else
98
- @editable = value
99
- end
100
- end
101
-
102
- def showSourceLink
103
- @showSourceLink
104
- end
105
-
106
- def showSourceLink=(value)
107
- if value.class == String
108
- @showSourceLink = (value =~ /true/i)
109
- else
110
- @showSourceLink = value
111
- end
51
+ @editable = if value.class == String
52
+ (value =~ /true/i)
53
+ else
54
+ value
55
+ end
112
56
  end
113
57
 
114
- def self.load(filename=$defaultConfFile)
115
- $wiki_conf = self.new(YAML::load(::File.open(filename)))
116
- $wiki_path = $wiki_conf.wiki_path
117
- $wiki_conf
58
+ def self.load(filename = $defaultConfFile)
59
+ $wiki_conf = self.new(YAML.safe_load(::File.open(filename)))
118
60
  end
119
-
120
- def initialize(hash={})
121
- default_hash.merge(hash).each do |k, v|
122
- instance_variable_set(:"@#{k.to_s}", v)
123
- end
124
- end
125
-
126
- def default_hash
127
- {
128
- :url_prefix => '/',
129
- :indexPort => ClWiki::Indexer.defaultPort,
130
- :cgifn => 'clwikicgi.rb',
131
- :default_recent_changes_name => "Recent Changes",
132
- :recent_changes_name => "Recent Changes",
133
- :stats_name => "Hit Counts",
134
- :useGmt => false,
135
- :publishTag => nil,
136
- :useIndexForPageExists => false,
137
- :showSourceLink => false,
138
- :cgifn_from_rss => 'blogki.rb',
139
- :edit_rows => 25,
140
- :edit_cols => 80,
141
- :access_log_index => false,
142
- :index_log_fn => nil,
143
- :custom_formatter_load_path => []
144
- }
145
- end
146
-
147
- def default_recent_changes_name=(value)
148
- if @recent_changes_name == @default_recent_changes_name
149
- @recent_changes_name = value
150
- end
151
- @default_recent_changes_name = default_recent_changes_name
152
- end
153
-
154
- def default_recent_changes_name
155
- @default_recent_changes_name
156
- end
157
-
158
- def recentChangesName=(value)
159
- @recent_changes_name = value
160
- @recent_changes_name = @default_recent_changes_name if @recent_changes_name.empty?
161
- end
162
-
163
- alias recent_changes_name= recentChangesName=
164
-
165
- def recentChangesName
166
- @recent_changes_name
167
- end
168
-
169
- alias recent_changes_name recentChangesName
170
61
  end
171
62
  end
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ClWiki
2
4
  class Engine < ::Rails::Engine
3
5
  isolate_namespace ClWiki
4
6
 
5
7
  initializer 'cl_wiki.assets.precompile' do |app|
6
- app.config.assets.precompile += %w(application.css application.js)
8
+ app.config.assets.precompile += %w[application.css application.js]
7
9
  end
8
10
  end
9
11
  end
@@ -1,168 +1,196 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'fileutils'
2
4
  require 'time'
3
5
 
4
- require_relative 'page'
5
-
6
- $wikiPageExt = '.txt'
7
-
8
6
  module ClWiki
7
+ FILE_EXT = '.txt'
8
+
9
9
  class File
10
- attr_reader :name, :fileExt, :wikiRootPath, :pagePath, :modTimeAtLastRead, :metadata
11
- attr_accessor :clientLastReadModTime
12
-
13
- def initialize(fullPageName, wikiRootPath, fileExt=$wikiPageExt, autocreate=true)
14
- # fullPageName must start with / ?
15
- @wikiRootPath = wikiRootPath
16
- fullPageName = ClWiki::Util.convertToNativePath(fullPageName)
17
- fullPageName.ensure_slash_prefix
18
- @pagePath, @name = ::File.split(fullPageName)
19
- @pagePath = '/' if @pagePath == '.'
20
- @fileExt = fileExt
21
- @metadata = {}
22
- @metadata_keys = ['mtime']
23
- if autocreate
24
- if file_exists?
25
- readFile
26
- else
27
- writeToFile(default_content, false)
28
- end
10
+ attr_reader :name, :mod_time_at_last_read, :metadata, :owner
11
+ attr_accessor :client_last_read_mod_time
12
+
13
+ def initialize(page_name, wiki_root_path, auto_create: true, owner: PublicUser.new)
14
+ @wiki_root_path = wiki_root_path
15
+ @owner = owner
16
+ @name = ::File.basename(ClWiki::Util.convert_to_native_path(page_name))
17
+ @metadata = Metadata.new
18
+ if auto_create
19
+ file_exists? ? read_file : write_to_file(default_content, false)
29
20
  end
30
21
  end
31
22
 
32
- def content_is_default?
23
+ def has_default_content?
33
24
  @contents.to_s == default_content
34
25
  end
35
26
 
36
- def delete
37
- File.delete(fullPathAndName) if File.exists?(fullPathAndName)
27
+ def default_content
28
+ "Describe #{@name} here."
38
29
  end
39
30
 
40
- def default_content
41
- "Describe " + @name + " here."
31
+ def delete
32
+ ::File.delete(full_path_and_name) if file_exists?
42
33
  end
43
34
 
44
35
  def file_exists?
45
- FileTest.exist?(fullPathAndName)
36
+ FileTest.exist?(full_path_and_name)
46
37
  end
47
38
 
48
- def fullPath
49
- res = ::File.expand_path(::File.join(@wikiRootPath, @pagePath))
50
- raise 'no dirs in fullPath' if res.split('/').empty?
51
- res
39
+ def full_path_and_name
40
+ ::File.expand_path(@name + FILE_EXT, @wiki_root_path)
52
41
  end
53
42
 
54
- def fullPathAndName
55
- ::File.expand_path(@name + @fileExt, fullPath)
43
+ def content
44
+ @contents
56
45
  end
57
46
 
58
- def fileName
59
- raise Exception, 'ClWikiFile.fileName is deprecated, use fullPathAndName'
60
- # fullPathAndName
47
+ def content=(new_content)
48
+ write_to_file(new_content)
61
49
  end
62
50
 
63
- def content
64
- @contents
51
+ def write_to_file(content, check_mod_time = true)
52
+ do_mod_time_check if check_mod_time
53
+
54
+ update_metadata
55
+ file_contents = String.new.tap do |s|
56
+ s << @metadata.to_s
57
+ s << (content_encrypted? ? @owner.lockbox.encrypt(content) : content)
58
+ end
59
+ ::File.binwrite(full_path_and_name, file_contents)
60
+ ::File.utime(@metadata['mtime'], @metadata['mtime'], full_path_and_name)
61
+ read_file
65
62
  end
66
63
 
67
- def content=(newContent)
68
- writeToFile(newContent)
64
+ def read_file
65
+ @mod_time_at_last_read = ::File.mtime(full_path_and_name)
66
+
67
+ # positive lookbehind regex is used here to retain the end of line
68
+ # newline, because this used to just be `File.readlines` which also keeps
69
+ # the newline characters.
70
+ raw_lines = ::File.binread(full_path_and_name).split(/(?<=\n)/)
71
+ @metadata, raw_content = Metadata.split_file_contents(raw_lines)
72
+ raw_content = raw_content.join
73
+
74
+ apply_metadata
75
+
76
+ @contents = content_encrypted? ? @owner.lockbox.decrypt_str(raw_content) : raw_content
69
77
  end
70
78
 
71
- def writeToFile(content, checkModTime=true)
72
- if checkModTime
73
- # refactor, bring raiseIfMTimeNotEqual back into this class
74
- ClWiki::Util.raiseIfMTimeNotEqual(@modTimeAtLastRead, fullPathAndName)
75
- unless @clientLastReadModTime.nil?
76
- ClWiki::Util.raiseIfMTimeNotEqual(@clientLastReadModTime, fullPathAndName)
77
- end
78
- end
79
+ def read_metadata(lines)
80
+ @metadata = Metadata.new(lines)
81
+ end
79
82
 
80
- make_dirs(fullPath)
81
- ding_mtime
82
- ::File.open(fullPathAndName, 'w+') do |f|
83
- f.print(metadata_to_write)
84
- f.print(content)
85
- end
86
- ::File.utime(@metadata['mtime'], @metadata['mtime'], fullPathAndName)
87
- readFile
83
+ def apply_metadata
84
+ @mod_time_at_last_read = Time.parse(@metadata['mtime']) if @metadata.has? 'mtime'
85
+ ensure_same_owner!
88
86
  end
89
87
 
90
- def ding_mtime
91
- @metadata['mtime'] = Time.now
88
+ def content_encrypted?
89
+ @metadata['encrypted'] == 'true'
92
90
  end
93
91
 
94
- def metadata_to_write
95
- @metadata.collect { |k, v| "#{k}: #{v}" }.join("\n") + "\n\n\n"
92
+ def encrypt_content!
93
+ raise "Owner <#{@owner.name}> cannot encrypt" unless @owner.can_encrypt?
94
+
95
+ @metadata['encrypted'] = 'true'
96
96
  end
97
97
 
98
- def make_dirs(dir)
99
- # need to commit each dir as we make it, which is why we just don't
100
- # call File::makedirs. Core code copied from ftools.rb
101
- parent = ::File.dirname(dir)
102
- return if parent == dir or FileTest.directory? dir
103
- make_dirs parent unless FileTest.directory? parent
104
- if ::File.basename(dir) != ""
105
- Dir.mkdir dir, 0755
98
+ def do_not_encrypt_content!
99
+ @metadata['encrypted'] = 'false'
100
+ end
101
+
102
+ private
103
+
104
+ def do_mod_time_check
105
+ ClWiki::Util.raise_if_mtime_not_equal(@mod_time_at_last_read, full_path_and_name)
106
+ unless @client_last_read_mod_time.nil?
107
+ ClWiki::Util.raise_if_mtime_not_equal(@client_last_read_mod_time, full_path_and_name)
106
108
  end
107
109
  end
108
110
 
109
- def readFile
110
- ::File.open(fullPathAndName, 'r') do |f|
111
- @modTimeAtLastRead = f.mtime
112
- raw_lines = f.readlines
113
- metadata_lines, content = split_metadata(raw_lines)
114
- read_metadata(metadata_lines)
115
- apply_metadata
116
- @contents = content
111
+ def update_metadata
112
+ @metadata['mtime'] = Time.now
113
+ @metadata['owner'] = @owner.name
114
+ end
115
+
116
+ def ensure_same_owner!
117
+ meta_owner = @metadata['owner']
118
+ is_legacy_file = meta_owner.to_s.empty?
119
+ unless is_legacy_file || meta_owner == @owner.name
120
+ raise "Owner must match: <#{meta_owner}> - <#{@owner.name}>"
117
121
  end
118
122
  end
123
+ end
119
124
 
120
- def split_metadata(raw_lines)
121
- start_index = 0
122
- raw_lines.each_with_index do |ln, index|
123
- if ln.chomp.empty?
124
- next_line = raw_lines[index+1]
125
- if next_line.nil? || next_line.chomp.empty?
126
- if all_lines_are_metadata_lines(raw_lines[0..index-1])
127
- start_index = index + 2
128
- end
129
- break
130
- end
125
+ class Metadata
126
+ def self.split_file_contents(lines)
127
+ st_idx = 0
128
+ lines.each_with_index do |ln, index|
129
+ next unless ln.chomp.empty?
130
+
131
+ next_line = lines[index + 1]
132
+ if next_line.nil? || next_line.chomp.empty?
133
+ st_idx = index + 2 if all_lines_are_metadata_lines(lines[0..index - 1])
134
+ break
131
135
  end
132
136
  end
133
137
 
134
- if start_index > 0
135
- [raw_lines[0..start_index-3], raw_lines[start_index..-1]]
136
- else
137
- [[], raw_lines]
138
- end
138
+ m, c = st_idx > 0 ? [lines[0..st_idx - 3], lines[st_idx..-1]] : [[], lines]
139
+ [self.new(m), c]
139
140
  end
140
141
 
141
- def all_lines_are_metadata_lines(lines)
142
+ def self.all_lines_are_metadata_lines(lines)
142
143
  lines.map { |ln| ln.scan(/\A(\w+):?/) }.flatten.
143
- map { |k| @metadata_keys.include?(k) }.uniq == [true]
144
+ map { |k| supported_keys.include?(k) }.uniq == [true]
144
145
  end
145
146
 
146
- def read_metadata(lines)
147
- @metadata = {}
147
+ def self.supported_keys
148
+ %w[mtime encrypted owner]
149
+ end
150
+
151
+ def initialize(lines = [])
152
+ @hash = {}
153
+ @keys = Metadata.supported_keys
154
+ parse_lines(lines)
155
+ end
156
+
157
+ def [](key)
158
+ @hash[key]
159
+ end
160
+
161
+ def []=(key, value)
162
+ raise "Unexpected key: #{key}" unless @keys.include?(key)
163
+
164
+ @hash[key] = value
165
+ end
166
+
167
+ def has?(key)
168
+ @hash.key?(key)
169
+ end
170
+
171
+ def to_s
172
+ @hash.collect { |k, v| "#{k}: #{v}" }.join("\n") + "\n\n\n"
173
+ end
174
+
175
+ def to_h
176
+ @hash
177
+ end
178
+
179
+ private
180
+
181
+ def parse_lines(lines)
148
182
  lines.each do |ln|
149
183
  key, value = ln.split(': ')
150
- @metadata[key] = value if @metadata_keys.include?(key)
184
+ @hash[key] = value.chomp if @keys.include?(key)
151
185
  end
152
186
  end
153
-
154
- def apply_metadata
155
- @modTimeAtLastRead = Time.parse(@metadata['mtime']) if @metadata.keys.include? 'mtime'
156
- end
157
187
  end
158
188
 
159
189
  class Util
160
- def self.raiseIfMTimeNotEqual(mtime_to_compare, file_name)
190
+ def self.raise_if_mtime_not_equal(mtime_to_compare, file_name)
161
191
  # reading the instance .mtime appears to take Windows DST into account,
162
192
  # whereas the static File.mtime(filename) method does not
163
- current_mtime = ::File.open(file_name) do |f|
164
- f.mtime
165
- end
193
+ current_mtime = ::File.open(file_name, &:mtime)
166
194
  compare_read_times!(mtime_to_compare, current_mtime)
167
195
  end
168
196
 
@@ -176,25 +204,20 @@ module ClWiki
176
204
  end
177
205
 
178
206
  def self.dump_time(time)
179
- ''.tap do |s|
180
- s << "#{time}"
207
+ String.new.tap do |s|
208
+ s << time.to_s
181
209
  s << ".#{time.usec}" if time.respond_to?(:usec)
182
210
  end
183
211
  end
184
212
 
185
- def self.convertToNativePath(path)
186
- newpath = path.gsub(/\//, ::File::SEPARATOR)
187
- newpath = newpath.gsub(/\\/, ::File::SEPARATOR)
188
- return newpath
213
+ def self.convert_to_native_path(path)
214
+ path.gsub(%r{/}, ::File::SEPARATOR).gsub(/\\/, ::File::SEPARATOR)
189
215
  end
190
216
  end
191
217
 
192
- class FileError < Exception
218
+ class FileError < RuntimeError
193
219
  end
194
220
 
195
221
  class FileModifiedSinceRead < FileError
196
222
  end
197
-
198
- class FileMustUseWriteNewContent < FileError
199
- end
200
223
  end