publify_core 9.0.0.pre1

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 (372) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +21 -0
  3. data/README.rdoc +3 -0
  4. data/Rakefile +35 -0
  5. data/app/assets/fonts/open-sans-bold.woff +0 -0
  6. data/app/assets/fonts/open-sans.woff +0 -0
  7. data/app/assets/images/admin/loading.gif +0 -0
  8. data/app/assets/images/admin/typologo.gif +0 -0
  9. data/app/assets/images/calendar_date_select/calendar.gif +0 -0
  10. data/app/assets/images/close.gif +0 -0
  11. data/app/assets/images/closelabel.gif +0 -0
  12. data/app/assets/images/go.png +0 -0
  13. data/app/assets/images/loading.gif +0 -0
  14. data/app/assets/images/nextlabel.gif +0 -0
  15. data/app/assets/images/overlay.png +0 -0
  16. data/app/assets/images/powered.gif +0 -0
  17. data/app/assets/images/prevlabel.gif +0 -0
  18. data/app/assets/images/spinner-blue.gif +0 -0
  19. data/app/assets/images/spinner.gif +0 -0
  20. data/app/assets/images/thumb_blank.jpg +0 -0
  21. data/app/assets/javascripts/application.js +2 -0
  22. data/app/assets/javascripts/cookies.js +60 -0
  23. data/app/assets/javascripts/datetimepicker.js +1470 -0
  24. data/app/assets/javascripts/lang/da_DK.js +17 -0
  25. data/app/assets/javascripts/lang/default.js +21 -0
  26. data/app/assets/javascripts/lang/en_US.js +21 -0
  27. data/app/assets/javascripts/lang/fr_FR.js +21 -0
  28. data/app/assets/javascripts/lang/nl_NL.js +21 -0
  29. data/app/assets/javascripts/lang/zh_TW.js +17 -0
  30. data/app/assets/javascripts/lightbox.js +350 -0
  31. data/app/assets/javascripts/observe.js +28 -0
  32. data/app/assets/javascripts/publify.js +11 -0
  33. data/app/assets/javascripts/publify_admin.js +138 -0
  34. data/app/assets/javascripts/quicktags.js +440 -0
  35. data/app/assets/javascripts/set-timeago-lang.js +3 -0
  36. data/app/assets/javascripts/sidebar.js +28 -0
  37. data/app/assets/javascripts/spinnable.js +5 -0
  38. data/app/assets/javascripts/tagmanager.js +481 -0
  39. data/app/assets/javascripts/typeahead.js +1139 -0
  40. data/app/assets/javascripts/widearea.js +486 -0
  41. data/app/assets/stylesheets/accounts.css.scss +7 -0
  42. data/app/assets/stylesheets/administration_structure.css.scss +239 -0
  43. data/app/assets/stylesheets/coderay.css +135 -0
  44. data/app/assets/stylesheets/datetimepicker.css +306 -0
  45. data/app/assets/stylesheets/lightbox.css +63 -0
  46. data/app/assets/stylesheets/publify.css.scss +9 -0
  47. data/app/assets/stylesheets/publify_admin.css.scss +11 -0
  48. data/app/assets/stylesheets/rss.css +53 -0
  49. data/app/assets/stylesheets/sidebar_admin.css.scss +36 -0
  50. data/app/assets/stylesheets/tagmanager.css +102 -0
  51. data/app/assets/stylesheets/user-styles.css +29 -0
  52. data/app/assets/stylesheets/widearea.css +133 -0
  53. data/app/controllers/accounts_controller.rb +2 -0
  54. data/app/controllers/admin/base_controller.rb +41 -0
  55. data/app/controllers/admin/cache_controller.rb +33 -0
  56. data/app/controllers/admin/content_controller.rb +174 -0
  57. data/app/controllers/admin/dashboard_controller.rb +87 -0
  58. data/app/controllers/admin/feedback_controller.rb +159 -0
  59. data/app/controllers/admin/migrations_controller.rb +20 -0
  60. data/app/controllers/admin/notes_controller.rb +69 -0
  61. data/app/controllers/admin/pages_controller.rb +88 -0
  62. data/app/controllers/admin/post_types_controller.rb +56 -0
  63. data/app/controllers/admin/profiles_controller.rb +48 -0
  64. data/app/controllers/admin/redirects_controller.rb +47 -0
  65. data/app/controllers/admin/resources_controller.rb +30 -0
  66. data/app/controllers/admin/seo_controller.rb +45 -0
  67. data/app/controllers/admin/settings_controller.rb +53 -0
  68. data/app/controllers/admin/sidebar_controller.rb +66 -0
  69. data/app/controllers/admin/tags_controller.rb +53 -0
  70. data/app/controllers/admin/textfilters_controller.rb +6 -0
  71. data/app/controllers/admin/themes_controller.rb +37 -0
  72. data/app/controllers/admin/users_controller.rb +65 -0
  73. data/app/controllers/articles_controller.rb +205 -0
  74. data/app/controllers/authors_controller.rb +27 -0
  75. data/app/controllers/base_controller.rb +45 -0
  76. data/app/controllers/comments_controller.rb +69 -0
  77. data/app/controllers/content_controller.rb +31 -0
  78. data/app/controllers/feedback_controller.rb +47 -0
  79. data/app/controllers/notes_controller.rb +37 -0
  80. data/app/controllers/setup_controller.rb +62 -0
  81. data/app/controllers/tags_controller.rb +55 -0
  82. data/app/controllers/text_controller.rb +9 -0
  83. data/app/controllers/textfilter_controller.rb +3 -0
  84. data/app/controllers/theme_controller.rb +59 -0
  85. data/app/controllers/trackbacks_controller.rb +36 -0
  86. data/app/controllers/xml_controller.rb +70 -0
  87. data/app/helpers/admin/base_helper.rb +87 -0
  88. data/app/helpers/admin/feedback_helper.rb +42 -0
  89. data/app/helpers/articles_helper.rb +8 -0
  90. data/app/helpers/authors_helper.rb +39 -0
  91. data/app/helpers/base_helper.rb +246 -0
  92. data/app/helpers/blog_helper.rb +12 -0
  93. data/app/helpers/xml_helper.rb +16 -0
  94. data/app/mailers/notification_mailer.rb +38 -0
  95. data/app/models/ability.rb +52 -0
  96. data/app/models/archives_sidebar.rb +45 -0
  97. data/app/models/article/factory.rb +56 -0
  98. data/app/models/article/states.rb +178 -0
  99. data/app/models/article.rb +321 -0
  100. data/app/models/blog.rb +290 -0
  101. data/app/models/blog_sweeper.rb +86 -0
  102. data/app/models/comment.rb +53 -0
  103. data/app/models/config_manager.rb +81 -0
  104. data/app/models/content.rb +138 -0
  105. data/app/models/content_base.rb +95 -0
  106. data/app/models/feedback/states.rb +256 -0
  107. data/app/models/feedback.rb +225 -0
  108. data/app/models/meta_sidebar.rb +8 -0
  109. data/app/models/note.rb +144 -0
  110. data/app/models/page.rb +36 -0
  111. data/app/models/page_cache.rb +33 -0
  112. data/app/models/page_sidebar.rb +12 -0
  113. data/app/models/ping.rb +116 -0
  114. data/app/models/post_type.rb +15 -0
  115. data/app/models/redirect.rb +45 -0
  116. data/app/models/redirection.rb +4 -0
  117. data/app/models/resource.rb +28 -0
  118. data/app/models/search_sidebar.rb +7 -0
  119. data/app/models/sidebar.rb +138 -0
  120. data/app/models/static_sidebar.rb +20 -0
  121. data/app/models/tag.rb +63 -0
  122. data/app/models/tag_sidebar.rb +27 -0
  123. data/app/models/text_filter.rb +61 -0
  124. data/app/models/trackback.rb +58 -0
  125. data/app/models/trigger.rb +45 -0
  126. data/app/models/user.rb +148 -0
  127. data/app/services/migrator.rb +25 -0
  128. data/app/services/title_builder.rb +80 -0
  129. data/app/uploaders/resource_uploader.rb +30 -0
  130. data/app/views/accounts/confirm.html.erb +8 -0
  131. data/app/views/admin/cache/show.html.erb +18 -0
  132. data/app/views/admin/content/_article_list.html.erb +26 -0
  133. data/app/views/admin/content/_form.html.erb +165 -0
  134. data/app/views/admin/content/autosave.js.erb +5 -0
  135. data/app/views/admin/content/edit.html.erb +3 -0
  136. data/app/views/admin/content/index.html.erb +48 -0
  137. data/app/views/admin/content/index.js.erb +1 -0
  138. data/app/views/admin/content/new.html.erb +3 -0
  139. data/app/views/admin/dashboard/_comment.html.erb +18 -0
  140. data/app/views/admin/dashboard/_comments.html.erb +10 -0
  141. data/app/views/admin/dashboard/_drafts.html.erb +25 -0
  142. data/app/views/admin/dashboard/_inbound.html.erb +31 -0
  143. data/app/views/admin/dashboard/_overview.html.erb +23 -0
  144. data/app/views/admin/dashboard/_welcome.html.erb +28 -0
  145. data/app/views/admin/dashboard/index.html.erb +17 -0
  146. data/app/views/admin/feedback/_button.html.erb +19 -0
  147. data/app/views/admin/feedback/_feedback.html.erb +7 -0
  148. data/app/views/admin/feedback/_ham.html.erb +17 -0
  149. data/app/views/admin/feedback/_spam.html.erb +23 -0
  150. data/app/views/admin/feedback/article.html.erb +69 -0
  151. data/app/views/admin/feedback/edit.html.erb +48 -0
  152. data/app/views/admin/feedback/ham.js +1 -0
  153. data/app/views/admin/feedback/index.html.erb +53 -0
  154. data/app/views/admin/feedback/spam.js +1 -0
  155. data/app/views/admin/migrations/show.html.erb +39 -0
  156. data/app/views/admin/notes/_form.html.erb +37 -0
  157. data/app/views/admin/notes/_header.html.erb +6 -0
  158. data/app/views/admin/notes/_list.html.erb +13 -0
  159. data/app/views/admin/notes/_note.html.erb +14 -0
  160. data/app/views/admin/notes/edit.html.erb +11 -0
  161. data/app/views/admin/notes/index.html.erb +11 -0
  162. data/app/views/admin/notes/show.html.erb +14 -0
  163. data/app/views/admin/pages/_form.html.erb +101 -0
  164. data/app/views/admin/pages/_pages.html.erb +21 -0
  165. data/app/views/admin/pages/edit.html.erb +1 -0
  166. data/app/views/admin/pages/index.html.erb +17 -0
  167. data/app/views/admin/pages/new.html.erb +1 -0
  168. data/app/views/admin/post_types/_index_and_form.html.erb +65 -0
  169. data/app/views/admin/post_types/edit.html.erb +1 -0
  170. data/app/views/admin/post_types/index.html.erb +1 -0
  171. data/app/views/admin/profiles/index.html.erb +10 -0
  172. data/app/views/admin/redirects/_index_and_form.html.erb +68 -0
  173. data/app/views/admin/redirects/edit.html.erb +1 -0
  174. data/app/views/admin/redirects/index.html.erb +1 -0
  175. data/app/views/admin/resources/index.html.erb +68 -0
  176. data/app/views/admin/seo/_general.html.erb +123 -0
  177. data/app/views/admin/seo/_permalinks.html.erb +53 -0
  178. data/app/views/admin/seo/_titles.html.erb +210 -0
  179. data/app/views/admin/seo/show.html.erb +32 -0
  180. data/app/views/admin/settings/display.html.erb +110 -0
  181. data/app/views/admin/settings/feedback.html.erb +125 -0
  182. data/app/views/admin/settings/index.html.erb +73 -0
  183. data/app/views/admin/settings/write.html.erb +87 -0
  184. data/app/views/admin/shared/_edit.html.erb +4 -0
  185. data/app/views/admin/shared/_menu.html.erb +122 -0
  186. data/app/views/admin/shared/_twitter_alert.html.erb +3 -0
  187. data/app/views/admin/sidebar/_available.html.erb +6 -0
  188. data/app/views/admin/sidebar/_available.json.erb +6 -0
  189. data/app/views/admin/sidebar/_config.html.erb +27 -0
  190. data/app/views/admin/sidebar/_target.html.erb +9 -0
  191. data/app/views/admin/sidebar/_target_sidebar.html.erb +20 -0
  192. data/app/views/admin/sidebar/destroy.js.erb +1 -0
  193. data/app/views/admin/sidebar/index.html.erb +31 -0
  194. data/app/views/admin/sidebar/sortable.js.erb +3 -0
  195. data/app/views/admin/sidebar/update.js.erb +2 -0
  196. data/app/views/admin/tags/_index_and_form.html.erb +59 -0
  197. data/app/views/admin/tags/edit.html.erb +1 -0
  198. data/app/views/admin/tags/index.html.erb +1 -0
  199. data/app/views/admin/themes/index.html.erb +27 -0
  200. data/app/views/admin/users/_form.html.erb +215 -0
  201. data/app/views/admin/users/edit.html.erb +8 -0
  202. data/app/views/admin/users/index.html.erb +39 -0
  203. data/app/views/admin/users/new.html.erb +8 -0
  204. data/app/views/archives_sidebar/_content.html.erb +13 -0
  205. data/app/views/articles/_article.html.erb +9 -0
  206. data/app/views/articles/_article_collection.html.erb +8 -0
  207. data/app/views/articles/_article_content.html.erb +5 -0
  208. data/app/views/articles/_article_excerpt.html.erb +13 -0
  209. data/app/views/articles/_article_links.html.erb +10 -0
  210. data/app/views/articles/_comment.html.erb +1 -0
  211. data/app/views/articles/_comment_errors.html.erb +2 -0
  212. data/app/views/articles/_comment_form.html.erb +48 -0
  213. data/app/views/articles/_comment_list.html.erb +5 -0
  214. data/app/views/articles/_comment_preview.html.erb +4 -0
  215. data/app/views/articles/_full_article_content.html.erb +2 -0
  216. data/app/views/articles/_password_form.html.erb +10 -0
  217. data/app/views/articles/_protected_article_content.html.erb +6 -0
  218. data/app/views/articles/_trackback.html.erb +6 -0
  219. data/app/views/articles/archives.html.erb +25 -0
  220. data/app/views/articles/comment.js.erb +5 -0
  221. data/app/views/articles/comment_failed.js.erb +3 -0
  222. data/app/views/articles/error.html.erb +3 -0
  223. data/app/views/articles/feedback_atom_feed.atom.builder +8 -0
  224. data/app/views/articles/feedback_rss_feed.rss.builder +21 -0
  225. data/app/views/articles/index.html.erb +1 -0
  226. data/app/views/articles/index_atom_feed.atom.builder +8 -0
  227. data/app/views/articles/index_rss_feed.rss.builder +20 -0
  228. data/app/views/articles/live_search.html.erb +10 -0
  229. data/app/views/articles/read.html.erb +61 -0
  230. data/app/views/articles/search.html.erb +8 -0
  231. data/app/views/articles/trackback.xml.builder +5 -0
  232. data/app/views/articles/view_page.html.erb +3 -0
  233. data/app/views/authors/show.html.erb +40 -0
  234. data/app/views/authors/show_atom_feed.atom.builder +8 -0
  235. data/app/views/authors/show_rss_feed.rss.builder +20 -0
  236. data/app/views/comments/_comment.html.erb +16 -0
  237. data/app/views/comments/index.html.erb +1 -0
  238. data/app/views/comments/index_atom_feed.atom.builder +8 -0
  239. data/app/views/comments/index_rss_feed.rss.builder +20 -0
  240. data/app/views/comments/preview.html.erb +1 -0
  241. data/app/views/comments/preview.js.erb +3 -0
  242. data/app/views/devise/mailer/reset_password_instructions.html.erb +13 -0
  243. data/app/views/devise/passwords/edit.html.erb +28 -0
  244. data/app/views/devise/passwords/new.html.erb +20 -0
  245. data/app/views/devise/registrations/new.html.erb +36 -0
  246. data/app/views/devise/sessions/new.html.erb +32 -0
  247. data/app/views/devise/shared/_links.html.erb +15 -0
  248. data/app/views/errors/404.html.erb +2 -0
  249. data/app/views/layouts/accounts.html.erb +33 -0
  250. data/app/views/layouts/administration.html.erb +37 -0
  251. data/app/views/layouts/default.html.erb +32 -0
  252. data/app/views/layouts/editor.html.erb +31 -0
  253. data/app/views/meta_sidebar/_content.html.erb +8 -0
  254. data/app/views/notes/_note.html.erb +15 -0
  255. data/app/views/notes/error.html.erb +3 -0
  256. data/app/views/notes/index.html.erb +15 -0
  257. data/app/views/notes/show.html.erb +5 -0
  258. data/app/views/notes/show_in_reply.html.erb +16 -0
  259. data/app/views/notification_mailer/_mail_footer.html.erb +7 -0
  260. data/app/views/notification_mailer/_mail_header.html.erb +1 -0
  261. data/app/views/notification_mailer/article.html.erb +6 -0
  262. data/app/views/notification_mailer/comment.html.erb +11 -0
  263. data/app/views/notification_mailer/notif_user.html.erb +14 -0
  264. data/app/views/page_sidebar/_content.html.erb +12 -0
  265. data/app/views/search_sidebar/_content.html.erb +10 -0
  266. data/app/views/settings/done.html.erb +2 -0
  267. data/app/views/settings/install.html.erb +12 -0
  268. data/app/views/setup/index.html.erb +13 -0
  269. data/app/views/shared/_atom_header.atom.builder +6 -0
  270. data/app/views/shared/_atom_item_article.atom.builder +39 -0
  271. data/app/views/shared/_atom_item_comment.atom.builder +10 -0
  272. data/app/views/shared/_atom_item_trackback.atom.builder +9 -0
  273. data/app/views/shared/_flash.erb +10 -0
  274. data/app/views/shared/_page_header.html.erb +26 -0
  275. data/app/views/shared/_rss_item_article.rss.builder +35 -0
  276. data/app/views/shared/_rss_item_comment.rss.builder +8 -0
  277. data/app/views/shared/_rss_item_trackback.rss.builder +7 -0
  278. data/app/views/sidebar/_row.html.erb +1 -0
  279. data/app/views/sidebar/_sidebar.html.erb +5 -0
  280. data/app/views/sidebar/display_plugins.html.erb +5 -0
  281. data/app/views/sidebar/show.html.erb +1 -0
  282. data/app/views/static_sidebar/_content.html.erb +2 -0
  283. data/app/views/tag_sidebar/_content.html.erb +10 -0
  284. data/app/views/tags/index.html.erb +15 -0
  285. data/app/views/tags/show.html.erb +1 -0
  286. data/app/views/theme/static_view_test.html.erb +1 -0
  287. data/app/views/trackbacks/index_atom_feed.atom.builder +7 -0
  288. data/app/views/trackbacks/index_rss_feed.rss.builder +20 -0
  289. data/app/views/trackbacks/trackback.xml.builder +4 -0
  290. data/app/views/xml/_googlesitemap_item_article.googlesitemap.builder +5 -0
  291. data/app/views/xml/_googlesitemap_item_category.googlesitemap.builder +4 -0
  292. data/app/views/xml/_googlesitemap_item_page.googlesitemap.builder +4 -0
  293. data/app/views/xml/_googlesitemap_item_tag.googlesitemap.builder +4 -0
  294. data/app/views/xml/feed.googlesitemap.builder +7 -0
  295. data/app/views/xml/rsd.rsd.builder +8 -0
  296. data/config/i18n-tasks.yml +49 -0
  297. data/config/initializers/devise.rb +265 -0
  298. data/config/initializers/mime_types.rb +6 -0
  299. data/config/locales/da.yml +827 -0
  300. data/config/locales/de.yml +827 -0
  301. data/config/locales/en.yml +827 -0
  302. data/config/locales/es-MX.yml +827 -0
  303. data/config/locales/fr.yml +827 -0
  304. data/config/locales/he.yml +827 -0
  305. data/config/locales/it.yml +827 -0
  306. data/config/locales/ja.yml +827 -0
  307. data/config/locales/lt.yml +827 -0
  308. data/config/locales/nb-NO.yml +827 -0
  309. data/config/locales/nl.yml +827 -0
  310. data/config/locales/pl.yml +827 -0
  311. data/config/locales/pt-BR.yml +827 -0
  312. data/config/locales/ro.yml +827 -0
  313. data/config/locales/ru.yml +827 -0
  314. data/config/locales/sidebars.da.yml +20 -0
  315. data/config/locales/sidebars.de.yml +20 -0
  316. data/config/locales/sidebars.en.yml +20 -0
  317. data/config/locales/sidebars.es-MX.yml +20 -0
  318. data/config/locales/sidebars.fr.yml +20 -0
  319. data/config/locales/sidebars.he.yml +20 -0
  320. data/config/locales/sidebars.it.yml +20 -0
  321. data/config/locales/sidebars.ja.yml +20 -0
  322. data/config/locales/sidebars.lt.yml +20 -0
  323. data/config/locales/sidebars.nb-NO.yml +20 -0
  324. data/config/locales/sidebars.nl.yml +20 -0
  325. data/config/locales/sidebars.pl.yml +20 -0
  326. data/config/locales/sidebars.pt-BR.yml +20 -0
  327. data/config/locales/sidebars.ro.yml +20 -0
  328. data/config/locales/sidebars.ru.yml +20 -0
  329. data/config/locales/sidebars.zh-CN.yml +20 -0
  330. data/config/locales/sidebars.zh-TW.yml +20 -0
  331. data/config/locales/zh-CN.yml +827 -0
  332. data/config/locales/zh-TW.yml +827 -0
  333. data/config/routes.rb +177 -0
  334. data/db/migrate/113_initial_schema.rb +205 -0
  335. data/db/migrate/114_fixes_buggy_articles_and_notes.rb +52 -0
  336. data/db/migrate/115_drops_categories_for_tags.rb +34 -0
  337. data/db/migrate/20150207131657_add_missing_indexes.rb +19 -0
  338. data/db/migrate/20150807134129_simplify_redirect_relations.rb +38 -0
  339. data/db/migrate/20150808052637_add_blog_ids.rb +33 -0
  340. data/db/migrate/20150808191127_add_blog_id_to_redirects.rb +15 -0
  341. data/db/migrate/20150810094754_add_blog_id_to_tags.rb +15 -0
  342. data/db/migrate/20160108111120_add_devise_to_users.rb +53 -0
  343. data/db/migrate/20160108184201_move_last_connection_to_last_sign_in_at.rb +16 -0
  344. data/db/migrate/20160110094906_remove_profiles_rights.rb +14 -0
  345. data/db/migrate/20160605103918_replace_profile_id_with_string.rb +30 -0
  346. data/db/migrate/20160605154632_remove_profiles.rb +24 -0
  347. data/db/migrate/20160701061851_demand_blog_id_on_contents.rb +9 -0
  348. data/db/migrate/20160701062604_add_blog_id_to_resources.rb +28 -0
  349. data/db/seeds.rb +37 -0
  350. data/lib/email_notify.rb +26 -0
  351. data/lib/format.rb +17 -0
  352. data/lib/publify_core/engine.rb +23 -0
  353. data/lib/publify_core/lang.rb +5 -0
  354. data/lib/publify_core/version.rb +3 -0
  355. data/lib/publify_core.rb +56 -0
  356. data/lib/publify_guid.rb +9 -0
  357. data/lib/publify_plugins.rb +72 -0
  358. data/lib/publify_textfilter_markdown.rb +44 -0
  359. data/lib/publify_textfilter_none.rb +14 -0
  360. data/lib/publify_textfilter_smartypants.rb +14 -0
  361. data/lib/publify_textfilter_textile.rb +21 -0
  362. data/lib/publify_textfilter_twitterfilter.rb +33 -0
  363. data/lib/publify_time.rb +30 -0
  364. data/lib/sidebar_field.rb +115 -0
  365. data/lib/sidebar_registry.rb +33 -0
  366. data/lib/spam_protection.rb +101 -0
  367. data/lib/stateful.rb +106 -0
  368. data/lib/tasks/publify_core_tasks.rake +4 -0
  369. data/lib/text_filter_plugin.rb +182 -0
  370. data/lib/theme.rb +72 -0
  371. data/lib/transforms.rb +45 -0
  372. metadata +865 -0
@@ -0,0 +1,101 @@
1
+ require 'format'
2
+
3
+ class SpamProtection
4
+ IP_RBLS = ['opm.blitzed.us', 'bsb.empty.us'].freeze
5
+ HOST_RBLS = ['multi.surbl.org', 'bsb.empty.us'].freeze
6
+ SECOND_LEVEL = %w(co com net org gov).freeze
7
+
8
+ attr_accessor :this_blog
9
+
10
+ def initialize(a_blog)
11
+ self.this_blog = a_blog
12
+ end
13
+
14
+ def is_spam?(string)
15
+ return false unless this_blog.sp_global
16
+ return false if string.blank?
17
+
18
+ reason = catch(:hit) do
19
+ case string
20
+ when Format::IP_ADDRESS then scan_ip(string)
21
+ when Format::HTTP_URI then scan_uris([string])
22
+ else scan_text(string)
23
+ end
24
+ end
25
+
26
+ if reason
27
+ logger.info("[SP] Hit: #{reason}")
28
+ return true
29
+ end
30
+ end
31
+
32
+ protected
33
+
34
+ def scan_ip(ip_address)
35
+ logger.info("[SP] Scanning IP #{ip_address}")
36
+ query_rbls(IP_RBLS, ip_address.split('.').reverse.join('.'))
37
+ end
38
+
39
+ def scan_text(string)
40
+ uri_list = string.scan(/(http:\/\/[^\s"]+)/m).flatten
41
+
42
+ check_uri_count(uri_list)
43
+ scan_uris(uri_list)
44
+
45
+ false
46
+ end
47
+
48
+ def check_uri_count(uris)
49
+ limit = this_blog.sp_url_limit
50
+ return if limit.to_i.zero?
51
+ if uris.size > limit
52
+ throw :hit, "Hard URL Limit hit: #{uris.size} > #{limit}"
53
+ end
54
+ end
55
+
56
+ def scan_uris(uris = [])
57
+ uris.each do |uri|
58
+ host = begin
59
+ URI.parse(uri).host
60
+ rescue URI::InvalidURIError
61
+ next
62
+ end
63
+ return scan_ip(host) if host =~ Format::IP_ADDRESS
64
+
65
+ host_parts = host.split('.').reverse
66
+ domain = []
67
+
68
+ # Check for two level TLD
69
+ (SECOND_LEVEL.include?(host_parts[1]) ? 3 : 2).times do
70
+ domain.unshift(host_parts.shift)
71
+ end
72
+
73
+ logger.info("[SP] Scanning domain #{domain.join('.')}")
74
+ query_rbls(HOST_RBLS, host, domain.join('.'))
75
+ logger.info("[SP] Finished domain scan #{domain.join('.')}")
76
+ return false
77
+ end
78
+ end
79
+
80
+ def query_rbls(rbls, *subdomains)
81
+ rbls.each do |rbl|
82
+ subdomains.uniq.each do |d|
83
+ begin
84
+ response = IPSocket.getaddress([d, rbl].join('.'))
85
+ if response =~ /^127\.0\.0\./
86
+ throw :hit,
87
+ "#{rbl} positively resolved subdomain #{d} => #{response}"
88
+ end
89
+ rescue SocketError
90
+ # NXDOMAIN response => negative: d is not in RBL
91
+ next
92
+ end
93
+ end
94
+ end
95
+ false
96
+ end
97
+
98
+ def logger
99
+ @logger ||= ::Rails.logger || Logger.new(STDOUT)
100
+ end
101
+ end
data/lib/stateful.rb ADDED
@@ -0,0 +1,106 @@
1
+ module Stateful
2
+ class State
3
+ def initialize(model)
4
+ @model = model
5
+ end
6
+
7
+ def to_s
8
+ self.class.to_s.demodulize
9
+ end
10
+
11
+ def exit_hook(_target_state)
12
+ ::Rails.logger.debug("#{model} leaving state #{self}")
13
+ end
14
+
15
+ def enter_hook
16
+ ::Rails.logger.debug("#{model} entering state #{self}")
17
+ end
18
+
19
+ def method_missing(predicate, *args)
20
+ if predicate.to_s.last == '?'
21
+ self.class.to_s.demodulize.underscore == predicate.to_s.chop
22
+ else
23
+ super
24
+ end
25
+ end
26
+
27
+ def ==(other)
28
+ self.class == other.class
29
+ end
30
+
31
+ def hash
32
+ self.class.hash
33
+ end
34
+
35
+ private
36
+
37
+ attr_reader :model
38
+ end
39
+
40
+ def self.included(base)
41
+ base.extend ClassMethods
42
+ end
43
+
44
+ module ClassMethods
45
+ def has_state(field, options = {})
46
+ options.assert_valid_keys(:valid_states, :handles, :initial_state)
47
+
48
+ unless (states = options[:valid_states])
49
+ raise 'You must specify at least one state'
50
+ end
51
+
52
+ states = states.map(&:to_sym)
53
+ delegations = Set.new(options[:handles]) + states.map { |value| "#{value}?" }
54
+ initial_state = options[:initial_state] || states.first
55
+
56
+ state_writer_method(field, states, initial_state)
57
+ state_reader_method(field, states, initial_state)
58
+
59
+ delegations.each do |value|
60
+ delegate value, to: field
61
+ end
62
+ end
63
+
64
+ def state_reader_method(name, states, initial_state)
65
+ module_eval <<-end_meth
66
+ def #{name}(force_reload = false)
67
+ if @#{name}_obj.nil? || force_reload
68
+ memento = read_attribute(#{name.inspect}) || #{initial_state.inspect}
69
+ unless #{states.inspect}.include? memento.to_sym
70
+ raise \"Invalid state: \#{memento} in the database.\"
71
+ end
72
+ @#{name}_obj = self.class.class_eval(memento.to_s.classify).new(self)
73
+ end
74
+ @#{name}_obj
75
+ end
76
+ end_meth
77
+ end
78
+
79
+ def state_writer_method(name, states, _initial_state)
80
+ module_eval <<-end_meth
81
+ def #{name}=(state)
82
+ case state
83
+ when Symbol
84
+ set_#{name}_from_symbol state
85
+ when String
86
+ set_#{name}_from_symbol state.to_sym
87
+ else
88
+ raise "You must set the state with a symbol or a string"
89
+ end
90
+ end
91
+
92
+ def set_#{name}_from_symbol(memento)
93
+ unless #{states.inspect}.include?(memento)
94
+ raise "Invalid state: " + memento
95
+ end
96
+ self[:#{name}] = memento.to_s
97
+ new_state = self.class.class_eval(memento.to_s.classify).new(self)
98
+ @#{name}_obj.exit_hook(new_state) if @#{name}_obj
99
+ @#{name}_obj = new_state
100
+ @#{name}_obj.enter_hook
101
+ @#{name}_obj
102
+ end
103
+ end_meth
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :publify_core do
3
+ # # Task goes here
4
+ # end
@@ -0,0 +1,182 @@
1
+ require 'publify_plugins'
2
+
3
+ class TextFilterPlugin
4
+ class << self
5
+ include PublifyPlugins
6
+ include ActionView::Helpers::TextHelper
7
+ include ActionView::Helpers::TagHelper
8
+ end
9
+
10
+ @@filter_map = {}
11
+ def self.inherited(sub)
12
+ if sub.to_s =~ /^Plugin/ || sub.to_s =~ /^PublifyApp::Textfilter/
13
+ name = sub.short_name
14
+ @@filter_map[name] = sub
15
+ end
16
+ end
17
+
18
+ def self.filter_map
19
+ @@filter_map
20
+ end
21
+
22
+ def self.available_filters
23
+ filter_map.values
24
+ end
25
+
26
+ def self.available_filter_types
27
+ unless @cached_filter_types
28
+ types = { 'macropre' => [],
29
+ 'macropost' => [],
30
+ 'markup' => [],
31
+ 'postprocess' => [],
32
+ 'other' => [] }
33
+
34
+ available_filters.each { |filter| types[filter.filter_type].push(filter) }
35
+
36
+ @cached_filter_types = types
37
+ end
38
+ @cached_filter_types
39
+ end
40
+
41
+ def self.macro_filters
42
+ available_filters.select { |filter| TextFilterPlugin::Macro > filter }
43
+ end
44
+
45
+ plugin_display_name 'Unknown Text Filter'
46
+ plugin_description 'Unknown Text Filter Description'
47
+
48
+ def self.reloadable?
49
+ false
50
+ end
51
+
52
+ # The name that needs to be used when refering to the plugin's
53
+ # controller in render statements
54
+ def self.component_name
55
+ if to_s =~ /::([a-zA-Z]+)$/
56
+ "plugins/textfilters/#{Regexp.last_match[1]}".downcase
57
+ else
58
+ raise "I don't know who I am: #{self}"
59
+ end
60
+ end
61
+
62
+ # The name that's stored in the DB. This is the final chunk of the
63
+ # controller name, like 'markdown' or 'smartypants'.
64
+ def self.short_name
65
+ component_name.split(%r{/}).last
66
+ end
67
+
68
+ def self.filter_type
69
+ 'other'
70
+ end
71
+
72
+ def self.default_config
73
+ {}
74
+ end
75
+
76
+ def self.help_text
77
+ ''
78
+ end
79
+
80
+ def self.sanitize(*args)
81
+ (@sanitizer ||= HTML::WhiteListSanitizer.new).sanitize(*args)
82
+ end
83
+
84
+ def self.default_helper_module!
85
+ end
86
+
87
+ # Look up a config paramater, falling back to the default as needed.
88
+ def self.config_value(params, name)
89
+ params[:filterparams][name] || default_config[name][:default]
90
+ end
91
+
92
+ def self.logger
93
+ @logger ||= ::Rails.logger || Logger.new(STDOUT)
94
+ end
95
+ end
96
+
97
+ class TextFilterPlugin::PostProcess < TextFilterPlugin
98
+ def self.filter_type
99
+ 'postprocess'
100
+ end
101
+ end
102
+
103
+ class TextFilterPlugin::Macro < TextFilterPlugin
104
+ # Utility function -- hand it a XML string like <a href="foo" title="bar">
105
+ # and it'll give you back { "href" => "foo", "title" => "bar" }
106
+ def self.attributes_parse(string)
107
+ attributes = {}
108
+
109
+ string.gsub(/([^ =]+="[^"]*")/) do |match|
110
+ key, value = match.split(/=/, 2)
111
+ attributes[key] = value.delete('"')
112
+ end
113
+
114
+ string.gsub(/([^ =]+='[^']*')/) do |match|
115
+ key, value = match.split(/=/, 2)
116
+ attributes[key] = value.delete("'")
117
+ end
118
+
119
+ attributes
120
+ end
121
+
122
+ def self.filtertext(text)
123
+ regex1 = /<publify:#{short_name}(?:[ \t][^>]*)?\/>/
124
+ regex2 = /<publify:#{short_name}([ \t][^>]*)?>(.*?)<\/publify:#{short_name}>/m
125
+
126
+ new_text = text.gsub(regex1) do |match|
127
+ macrofilter(attributes_parse(match))
128
+ end
129
+
130
+ new_text = new_text.gsub(regex2) do |_match|
131
+ macrofilter(attributes_parse(Regexp.last_match[1].to_s), Regexp.last_match[2].to_s)
132
+ end
133
+
134
+ new_text
135
+ end
136
+ end
137
+
138
+ class TextFilterPlugin::MacroPre < TextFilterPlugin::Macro
139
+ def self.filter_type
140
+ 'macropre'
141
+ end
142
+ end
143
+
144
+ class TextFilterPlugin::MacroPost < TextFilterPlugin::Macro
145
+ def self.filter_type
146
+ 'macropost'
147
+ end
148
+ end
149
+
150
+ class TextFilterPlugin::Markup < TextFilterPlugin
151
+ def self.filter_type
152
+ 'markup'
153
+ end
154
+ end
155
+
156
+ class PublifyApp
157
+ class Textfilter
158
+ class MacroPost < TextFilterPlugin
159
+ plugin_display_name 'MacroPost'
160
+ plugin_description 'Macro expansion meta-filter (post-markup)'
161
+
162
+ def self.filtertext(text)
163
+ macros = TextFilterPlugin.available_filter_types['macropost']
164
+ macros.reduce(text) do |new_text, macro|
165
+ macro.filtertext(new_text)
166
+ end
167
+ end
168
+ end
169
+
170
+ class MacroPre < TextFilterPlugin
171
+ plugin_display_name 'MacroPre'
172
+ plugin_description 'Macro expansion meta-filter (pre-markup)'
173
+
174
+ def self.filtertext(text)
175
+ macros = TextFilterPlugin.available_filter_types['macropre']
176
+ macros.reduce(text) do |new_text, macro|
177
+ macro.filtertext(new_text)
178
+ end
179
+ end
180
+ end
181
+ end
182
+ end
data/lib/theme.rb ADDED
@@ -0,0 +1,72 @@
1
+ class Theme
2
+ attr_accessor :name, :path, :description_html
3
+
4
+ def initialize(name, path)
5
+ @name = name
6
+ @path = path
7
+ end
8
+
9
+ def layout(action = :default)
10
+ if action.to_s == 'view_page'
11
+ if File.exist? "#{view_path}/layouts/pages.html.erb"
12
+ return 'layouts/pages'
13
+ end
14
+ end
15
+ 'layouts/default'
16
+ end
17
+
18
+ def description
19
+ about_file = "#{path}/about.markdown"
20
+ if File.exist? about_file
21
+ File.read about_file
22
+ else
23
+ "### #{name}"
24
+ end
25
+ end
26
+
27
+ def view_path
28
+ "#{path}/views"
29
+ end
30
+
31
+ # Find a theme, given the theme name
32
+ def self.find(name)
33
+ registered_themes[name]
34
+ end
35
+
36
+ # List all themes
37
+ def self.find_all
38
+ registered_themes.values
39
+ end
40
+
41
+ def self.register_theme(path)
42
+ theme = theme_from_path(path)
43
+ registered_themes[theme.name] = theme
44
+ end
45
+
46
+ def self.register_themes(themes_root)
47
+ search_theme_directory(themes_root).each do |path|
48
+ register_theme path
49
+ end
50
+ end
51
+
52
+ # Private
53
+
54
+ def self.registered_themes
55
+ @registered_themes ||= {}
56
+ end
57
+
58
+ def self.theme_from_path(path)
59
+ name = path.scan(/[-\w]+$/i).flatten.first
60
+ new(name, path)
61
+ end
62
+
63
+ def self.search_theme_directory(themes_root)
64
+ glob = "#{themes_root}/[a-zA-Z0-9]*"
65
+ Dir.glob(glob).select do |file|
66
+ File.readable?("#{file}/about.markdown")
67
+ end.compact
68
+ end
69
+
70
+ private_class_method :search_theme_directory,
71
+ :theme_from_path, :registered_themes
72
+ end
data/lib/transforms.rb ADDED
@@ -0,0 +1,45 @@
1
+ # coding: utf-8
2
+ # FIXME: Replace with helpers and/or methods provided by Rails
3
+ class String
4
+ ACCENTS = { %w(á à â ä ã Ã Ä Â À) => 'a',
5
+ %w(é è ê ë Ë É È Ê) => 'e',
6
+ %w(í ì î ï I Î Ì) => 'i',
7
+ %w(ó ò ô ö õ Õ Ö Ô Ò) => 'o',
8
+ ['œ'] => 'oe',
9
+ ['ß'] => 'ss',
10
+ %w(ú ù û ü U Û Ù) => 'u',
11
+ %w(ç Ç) => 'c' }.freeze
12
+
13
+ def to_permalink
14
+ string = self
15
+ ACCENTS.each do |key, value|
16
+ string = string.tr(key.join, value)
17
+ end
18
+ string = string.tr("'", '-')
19
+ string.gsub(/<[^>]*>/, '').to_url
20
+ end
21
+
22
+ # Returns a-string-with-dashes when passed 'a string with dashes'.
23
+ # All special chars are stripped in the process
24
+ def to_url
25
+ return if nil?
26
+
27
+ s = downcase.tr("\"'", '')
28
+ s = s.gsub(/\P{Word}/, ' ')
29
+ s.strip.tr_s(' ', '-').tr(' ', '-').sub(/^$/, '-')
30
+ end
31
+
32
+ def to_title(item, settings, params)
33
+ TitleBuilder.new(self).build(item, settings, params)
34
+ end
35
+
36
+ # Strips any html markup from a string
37
+ TYPO_TAG_KEY = TYPO_ATTRIBUTE_KEY = /[\w:_-]+/
38
+ TYPO_ATTRIBUTE_VALUE = /(?:[A-Za-z0-9]+|(?:'[^']*?'|"[^"]*?"))/
39
+ TYPO_ATTRIBUTE = /(?:#{TYPO_ATTRIBUTE_KEY}(?:\s*=\s*#{TYPO_ATTRIBUTE_VALUE})?)/
40
+ TYPO_ATTRIBUTES = /(?:#{TYPO_ATTRIBUTE}(?:\s+#{TYPO_ATTRIBUTE})*)/
41
+ TAG = %r{<[!/?\[]?(?:#{TYPO_TAG_KEY}|--)(?:\s+#{TYPO_ATTRIBUTES})?\s*(?:[!/?\]]+|--)?>}
42
+ def strip_html
43
+ gsub(TAG, '').gsub(/\s+/, ' ').strip
44
+ end
45
+ end