instiki 0.9.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. data/README +172 -0
  2. data/app/controllers/wiki.rb +389 -0
  3. data/app/models/author.rb +4 -0
  4. data/app/models/chunks/category.rb +31 -0
  5. data/app/models/chunks/chunk.rb +20 -0
  6. data/app/models/chunks/engines.rb +38 -0
  7. data/app/models/chunks/include.rb +29 -0
  8. data/app/models/chunks/literal.rb +19 -0
  9. data/app/models/chunks/match.rb +19 -0
  10. data/app/models/chunks/nowiki.rb +31 -0
  11. data/app/models/chunks/test.rb +18 -0
  12. data/app/models/chunks/uri.rb +97 -0
  13. data/app/models/chunks/wiki.rb +82 -0
  14. data/app/models/page.rb +86 -0
  15. data/app/models/page_lock.rb +24 -0
  16. data/app/models/page_set.rb +64 -0
  17. data/app/models/revision.rb +90 -0
  18. data/app/models/web.rb +89 -0
  19. data/app/models/wiki_content.rb +105 -0
  20. data/app/models/wiki_service.rb +83 -0
  21. data/app/models/wiki_words.rb +25 -0
  22. data/app/views/bottom.rhtml +4 -0
  23. data/app/views/markdown_help.rhtml +16 -0
  24. data/app/views/navigation.rhtml +19 -0
  25. data/app/views/rdoc_help.rhtml +16 -0
  26. data/app/views/static_style_sheet.rhtml +199 -0
  27. data/app/views/textile_help.rhtml +28 -0
  28. data/app/views/top.rhtml +49 -0
  29. data/app/views/wiki/authors.rhtml +13 -0
  30. data/app/views/wiki/edit.rhtml +31 -0
  31. data/app/views/wiki/edit_web.rhtml +138 -0
  32. data/app/views/wiki/export.rhtml +14 -0
  33. data/app/views/wiki/feeds.rhtml +10 -0
  34. data/app/views/wiki/list.rhtml +57 -0
  35. data/app/views/wiki/locked.rhtml +14 -0
  36. data/app/views/wiki/login.rhtml +11 -0
  37. data/app/views/wiki/new.rhtml +27 -0
  38. data/app/views/wiki/new_system.rhtml +78 -0
  39. data/app/views/wiki/new_web.rhtml +64 -0
  40. data/app/views/wiki/page.rhtml +81 -0
  41. data/app/views/wiki/print.rhtml +16 -0
  42. data/app/views/wiki/published.rhtml +10 -0
  43. data/app/views/wiki/recently_revised.rhtml +30 -0
  44. data/app/views/wiki/revision.rhtml +81 -0
  45. data/app/views/wiki/rollback.rhtml +31 -0
  46. data/app/views/wiki/rss_feed.rhtml +22 -0
  47. data/app/views/wiki/search.rhtml +15 -0
  48. data/app/views/wiki/tex.rhtml +23 -0
  49. data/app/views/wiki/tex_web.rhtml +35 -0
  50. data/app/views/wiki/web_list.rhtml +13 -0
  51. data/app/views/wiki_words_help.rhtml +8 -0
  52. data/instiki +67 -0
  53. data/libraries/action_controller_servlet.rb +177 -0
  54. data/libraries/diff/diff.rb +475 -0
  55. data/libraries/erb.rb +490 -0
  56. data/libraries/madeleine_service.rb +68 -0
  57. data/libraries/rdocsupport.rb +156 -0
  58. data/libraries/redcloth_for_tex.rb +869 -0
  59. data/libraries/view_helper.rb +33 -0
  60. data/libraries/web_controller_server.rb +81 -0
  61. metadata +142 -0
data/README ADDED
@@ -0,0 +1,172 @@
1
+ ===What is Instiki?
2
+
3
+ Admitted, it's YetAnotherWikiClone[http://c2.com/cgi/wiki?WikiWikiClones], but with a strong focus
4
+ on simplicity of installation and running:
5
+
6
+ Step 1. Download
7
+
8
+ Step 2. Run "instiki"
9
+
10
+ Step 3. Chuckle... "There's no step three!" (TM)
11
+
12
+ You're now running a perfectly suitable wiki on port 2500
13
+ that'll present you with one-step setup, followed by a textarea for the home page
14
+ on http://localhost:2500.
15
+
16
+ Instiki lowers the barriers of interest for when you might consider
17
+ using a wiki. It's so simple to get running that you'll find yourself
18
+ using it for anything -- taking notes, brainstorming, organizing a
19
+ gathering.
20
+
21
+ ===Features:
22
+ * Regular expression search: Find deep stuff really fast
23
+ * Revisions: Follow the changes on every page from birth. Rollback to an earlier rev
24
+ * Export to HTML or markup in a zip: Take the entire wiki with you home or for reference
25
+ * RSS feeds to track recently revised pages
26
+ * Multiple webs: Create separate wikis with their own namespace
27
+ * Password-protected webs: Keep it private
28
+ * Authors: Each revision is associated with an author, so you can see who changed what
29
+ * Reference tracker: Which other pages are pointing to the current?
30
+ * Speed: Using Madelein[http://madeleine.sourceforge.net] for persistence (all pages are in memory)
31
+ * Three markup choices: Textile[http://www.textism.com/tools/textile]
32
+ (default / RedCloth[http://www.whytheluckystiff.net/ruby/redcloth]),
33
+ Markdown (BlueCloth[http://bluecloth.rubyforge.org]), and RDoc[http://rdoc.sourceforge.net/doc]
34
+ * Embedded webserver: Through WEBrick[http://www.webrick.org]
35
+ * Internationalization: Wiki words in any latin, greek, cyrillian, or armenian characters
36
+ * Color diffs: Track changes through revisions
37
+
38
+ ===Missing:
39
+ * File attachments
40
+
41
+ ===Install from gem:
42
+ * Install rubygems
43
+ * Run "gem install instiki"
44
+ * Change to a directory where you want Instiki to keep its data files (for example, ~/instiki/)
45
+ * Run "instiki" - this will create a "storage" directory (for example, ~/instiki/storage), and start a new Wiki service
46
+
47
+ Make sure that you always launch Instiki from the same working directory, or specify the storage directory in runtime parameters, such as:
48
+ instiki --storage ~/instiki/storage
49
+
50
+ ===Command-line options:
51
+ * Run "instiki --help"
52
+
53
+ ===History:
54
+ * 0.9.2: Rollback takes the user to an edit form. The form has to be submitted for the change to take place.
55
+ Changed to use inline style on published pages
56
+ Fixed "forward in time" on the last revision before current page
57
+ Instiki won't log bogus error messages when creating a new Wiki.
58
+ Fixed deprecation warning for Object.id (introduced in Ruby 1.8.2)
59
+ Madeleine upgraded to 0.7.1
60
+ Madeleine snapshots are compressed
61
+ Packaged as a gem
62
+ * 0.9.1: Added performance improvements for updating existing pages
63
+ Fixed IP logging and RSS feeds behind proxies [With help from Guan Yang]
64
+ Fixed default storage directory (borked running on Windows) [Spotted by Curt Hibbs]
65
+ * 0.9.0: Added aliased links such as [[HomePage|that nice home page]] [Mark Reid]
66
+ Added include other page content with [[!include TableOfContents]] [Mark Reid]
67
+ Added delete orphan pages from the Edit Web screen [by inspiration from Simon Arnaud]
68
+ Added logging of IP address for authors (who's behind the rollback wars)
69
+ Added Categories pages through backlinks (use "categories: news, instiki" on start of line) [Mark Reid]
70
+ Added option to use bracket-style wiki links only (and hence ban WikiWords)
71
+ Added command-line option to specify different storage path
72
+ Added print view without navigation
73
+ Added character and page (2275 characters including spaces) counter (important for student papers)
74
+ Off by default, activate it on the Edit Web screen
75
+ Added LaTeX/PDF integration on Textile installations with pdflatex installed on system (EXPERIMENTAL)
76
+ Use the home page as a table of contents with a unordered list to control sections
77
+ Added limit of 15 to the number of pages included in RSS feed
78
+ Moved static parts of stylesheet to separate file [Lau T�rnskov]
79
+ Fixed better semantics for revision movement [Ryan Singer]
80
+ Fixed color diffs to work much better [Xen/Mertz/Atkins]
81
+ Fixed performance problems for All Pages list [Dennis Mertz]
82
+ Fixed lots of rendering bugs [Mark Reid]
83
+ Upgraded to RedCloth 2.0.11 [integrating the fine work of Dennis Mertz]
84
+ * 0.8.9: Added color diffs to see changes between revisions [Bill Atkins]
85
+ They're aren't quite perfect yet as new paragraphs split the <ins> tags (hence 0.8.9, not 0.9.0)
86
+ Added redirect to edit if content of page generates an error
87
+ (so the page doesn't become unusable on bugs in the markup engines)
88
+ Fixed update Web with different address bug [Denis Metz]
89
+ Fixed a bunch of wiki word rendering issues by doing wiki word detection and replacment at once
90
+ Upgraded to BlueCloth 0.0.3b (should fix loads of problems on Markdown wikis)
91
+ * 0.8.5: Instiki can now serve as a CMS by running a password-protected web with a published front
92
+ Added version check at startup (Instiki needs Ruby 1.8.1)
93
+ * 0.8.1: Actually included RedCloth 2.0.7 in the release
94
+ * 0.8.0: NOTE: Single-web wikis created in versions prior to 0.8.0 have "instiki" as their system password
95
+ Accepts wiki words in bracket style. Ex: [[wiki word]], [[c]], [[We could'nt have done it!]]
96
+ Accepts camel-case wiki words in all latin, greek, cyrillian, and armenian unicode characters
97
+ Many thanks to Guan Yang for building the higher- and lower-case lookup tables
98
+ And thanks to Simon Arnaud for the initial patch that got the work started
99
+ Changed charset to UTF-8
100
+ Cut down on command-line options and replaced them with an per-web config screen
101
+ Added option to extend the stylesheet on a per-web basis to tweak the look in details
102
+ Added simple color options for variety
103
+ Added option to add/remove password protection on each web
104
+ Added the wiki name of the author locking a given page (instead of just "someone")
105
+ Removed single/multi-web distinction -- all Instikis are now multi-web
106
+ Load libraries from an unshifted load path, so that old installed libraries doesn't clash [Emiel van de Laar]
107
+ Keeps the author cookie forever, so you don't have to enter your name again and again
108
+ Fixed XHTML so it validates [Bruce D'Arcus]
109
+ Authors are no longer listed under orphan pages
110
+ Added export to markup (great for backups, potentially for switching wiki engine)
111
+ Don't link wiki words that proceeds from either /, = or ?
112
+ (http://c2.com/cgi/wiki?WikiWikiClones, /show/HomePage, cgi.pl?show=WikiWord without escaping)
113
+ Accessing an unexisting page redirects to a different url (/new/PageName)
114
+ Increased snapshot time to just once a day (cuts down on disk storage requirements)
115
+ Made RDoc support work better with 1.8.1 [Mauricio Fern�ndez]
116
+ Added convinient redirect from /wiki/ to /wiki/show/HomePage
117
+ Fixed BlueCloth bug with backticks at start of line
118
+ Updated to RedCloth 2.0.7 (and linked to the new Textile reference)
119
+ * 0.7.0: Added Markdown (BlueCloth) and RDoc [Mauricio Fern�ndez] as command-line markup choices
120
+ Added wanted and orphan page lists to All pages (only show up if there's actually orphan or wanted pages)
121
+ Added ISO-8859-1 as XML encoding in RSS feeds (makes FeedReader among others happy for special entities)
122
+ Added proper links in the RSS feed (but the body links are still relative, which NNW and others doesn't grok)
123
+ Added access keys: E => Edit, H => HomePage, A => All Pages, U => Recently Revised, X => Export
124
+ Added password-login through URL (so you can subscribe to feed on a protected web)
125
+ Added web passwords to the feed links for protected webs, so they work without manual login
126
+ Added the web name in small letters above all pages within a web
127
+ Polished authors and recently revised
128
+ Updated to RedCloth 2.0.6
129
+ Changed content type for RSS feeds to text/xml (makes Mozilla Aggreg8 happy)
130
+ Changed searching to be case insensitive
131
+ Changed HomePage to display the name of the web instead
132
+ Changed exported HTML pages to be valid XHTML (which can be preprocessed by XSLT)
133
+ Fixed broken recently revised
134
+ * 0.6.0: Fixed Windows compatibility [Florian]
135
+ Fixed bug that would prevent Madeleine from taking snapshots in Daemon mode
136
+ Added export entire web as HTML in a zip file
137
+ Added RSS feeds
138
+ Added proper getops support for the growing number of options [Florian]
139
+ Added safe mode that forbids style options in RedCloth [Florian]
140
+ Updated RedCloth to 2.0.5
141
+ * 0.5.0: NOTE: 0.5.0 is NOT compatible with databases from earlier versions
142
+ Added revisions
143
+ Added multiple webs
144
+ Added password protection for webs on multi-web setups
145
+ Added the notion of authors (that are saved in a cookie)
146
+ Added command-line option for not running as a Daemon on Unix
147
+ * 0.3.1: Added option to escape wiki words with \
148
+ * 0.3.0: Brought all files into common style (including Textile help on the edit page)
149
+ Added page locking (if someone already is editing a page there's a warning)
150
+ Added daemon abilities on Unix (keep Instiki running after you close the terminal)
151
+ Made port 2500 the default port, so Instiki can be launched by dobbelt-click
152
+ Added Textile cache to speed-up rendering of large pages
153
+ Made WikiWords look like "Wiki Words"
154
+ Updated RedCloth to 2.0.4
155
+ * 0.2.5: Upgraded to RedCloth 2.0.2 and Madeleine 0.6.1, which means the
156
+ Windows problems are gone. Also fixed a problem with wikiwords
157
+ that used part of other wikiwords.
158
+ * 0.2.0: First public release
159
+
160
+ ===Download latest from:
161
+ * http://rubyforge.org/project/showfiles.php?group_id=186
162
+
163
+ ===Visit the official Instiki wiki:
164
+ * http://www.instiki.org
165
+
166
+ ===License:
167
+ * same as Ruby's
168
+
169
+ ---
170
+ Author:: David Heinemeier Hansson
171
+ Email:: david@loudthinking.com
172
+ Weblog:: http://www.loudthinking.com
@@ -0,0 +1,389 @@
1
+ require "cgi"
2
+ require "redcloth_for_tex"
3
+
4
+ class WikiController < ActionControllerServlet
5
+ EXPORT_DIRECTORY = File.dirname(__FILE__) + "/../../storage/" unless const_defined?("EXPORT_DIRECTORY")
6
+
7
+ def index
8
+ if web_address
9
+ redirect_show "HomePage"
10
+ elsif !wiki.setup?
11
+ redirect_path "/new_system/"
12
+ elsif wiki.webs.length == 1
13
+ redirect_show "HomePage", wiki.webs.values.first.address
14
+ else
15
+ redirect_path "/web_list/"
16
+ end
17
+ end
18
+
19
+ # Administrating the Instiki setup --------------------------------------------
20
+
21
+ def new_system
22
+ wiki.setup? ? redirect_path("/") : render
23
+ end
24
+
25
+ def new_web
26
+ redirect_path("/") if wiki.system["password"].nil?
27
+ end
28
+
29
+ def create_system
30
+ wiki.setup(@params["password"], @params["web_name"], @params["web_address"]) unless wiki.setup?
31
+ redirect_path "/"
32
+ end
33
+
34
+ def create_web
35
+ redirect_path("/") unless wiki.authenticate(@params["system_password"])
36
+ wiki.create_web(@params["name"], @params["address"])
37
+ redirect_show("HomePage", @params["address"])
38
+ end
39
+
40
+
41
+ # Outside a single web --------------------------------------------------------
42
+
43
+ def web_list
44
+ @system, @webs = wiki.system, wiki.webs.values
45
+ render "wiki/web_list"
46
+ end
47
+
48
+ def login
49
+ render "wiki/login"
50
+ end
51
+
52
+ def authenticate
53
+ password_check(@params["password"]) ? redirect_show("HomePage") : redirect_action("login")
54
+ end
55
+
56
+ def static_style_sheet() render "static_style_sheet" end
57
+
58
+
59
+ # Within a single web ---------------------------------------------------------
60
+
61
+ def parse_category
62
+ @categories = web.categories
63
+ @category = @params["category"]
64
+ @pages_in_category = web.select { |page| page.in_category?(@category) }
65
+ @set_name = ( @categories.include?(@category) ? "category '#{@category}'" : "the web" )
66
+ @category_links = @categories.map do |c|
67
+ (@category == c ? "<span class=\"selected\">#{c}</span>" : "<a href=\"?category=#{c}\">#{c}</a>")
68
+ end
69
+ end
70
+
71
+ def search
72
+ @query = @params["query"]
73
+ @results = web.select { |page| page.content =~ /#{@query}/i }
74
+ @results.length == 1 ? redirect_show(@results.first.name) : render
75
+ end
76
+
77
+ def authors
78
+ @authors = web.select.authors
79
+ end
80
+
81
+ def recently_revised
82
+ parse_category
83
+ @pages_by_revision = @pages_in_category.by_revision
84
+ end
85
+
86
+ def rss_with_content
87
+ @pages_by_revision = web.select.by_revision.first(15)
88
+ @uri = @req.request_uri
89
+ host = @req.meta_vars["HTTP_X_FORWARDED_HOST"] || "#{@uri.host}:#{@uri.port.to_s}"
90
+ @web_url = "#{@uri.scheme}://#{host}/#{@web.address}"
91
+ @res["Content-Type"] = "text/xml"
92
+ render "wiki/rss_feed"
93
+ end
94
+
95
+ def rss_with_headlines
96
+ @hide_description = true
97
+ rss_with_content
98
+ end
99
+
100
+ def list
101
+ parse_category
102
+ @pages_by_name = @pages_in_category.by_name
103
+ @page_names_that_are_wanted = @pages_in_category.wanted_pages
104
+ @pages_that_are_orphaned = @pages_in_category.orphaned_pages
105
+ end
106
+
107
+ def export_html
108
+ file_name = "#{web.address}-html-#{web.revised_on.strftime("%Y-%m-%d-%H-%M")}.zip"
109
+ file_path = EXPORT_DIRECTORY + file_name
110
+
111
+ export_pages_to_zip_file(file_path) unless FileTest.exists?(file_path)
112
+ send_export(file_name, file_path)
113
+ end
114
+
115
+ def export_markup
116
+ file_name = "#{web.address}-markup-#{web.revised_on.strftime("%Y-%m-%d-%H-%M")}.zip"
117
+ file_path = EXPORT_DIRECTORY + file_name
118
+
119
+ export_markup_to_zip_file(file_path) unless FileTest.exists?(file_path)
120
+ send_export(file_name, file_path)
121
+ end
122
+
123
+ def export_pdf
124
+ file_name = "#{web.address}-tex-#{web.revised_on.strftime("%Y-%m-%d-%H-%M")}"
125
+ file_path = EXPORT_DIRECTORY + file_name
126
+
127
+ export_web_to_tex(file_path + ".tex") unless FileTest.exists?(file_path + ".tex")
128
+ convert_tex_to_pdf(file_path + ".tex")
129
+ send_export(file_name + ".pdf", file_path + ".pdf")
130
+ end
131
+
132
+ def export_tex
133
+ file_name = "#{web.address}-tex-#{web.revised_on.strftime("%Y-%m-%d-%H-%M")}.tex"
134
+ file_path = EXPORT_DIRECTORY + file_name
135
+
136
+ export_web_to_tex(file_path) unless FileTest.exists?(file_path)
137
+ send_export(file_name, file_path)
138
+ end
139
+
140
+ def update_web
141
+ redirect_show("HomePage") unless wiki.authenticate(@params["system_password"])
142
+
143
+ wiki.update_web(
144
+ web.address, @params["address"], @params["name"],
145
+ @params["markup"].intern,
146
+ @params["color"], @params["additional_style"],
147
+ @params["safe_mode"] ? true : false,
148
+ @params["password"].empty? ? nil : @params["password"],
149
+ @params["published"] ? true : false,
150
+ @params["brackets_only"] ? true : false,
151
+ @params["count_pages"] ? true : false
152
+ )
153
+
154
+ redirect_show("HomePage", @params["address"])
155
+ end
156
+
157
+ def remove_orphaned_pages
158
+ if wiki.authenticate(@params["system_password"])
159
+ wiki.remove_orphaned_pages(web_address)
160
+ redirect_action "list/"
161
+ else
162
+ redirect_show "HomePage"
163
+ end
164
+ end
165
+
166
+ # Within a single page --------------------------------------------------------
167
+
168
+ def show
169
+ if @page = wiki.read_page(web_address, page_name)
170
+ begin
171
+ render_action "page"
172
+ rescue => e
173
+ $stderr << e.backtrace.join("\n")
174
+ redirect_action "edit/#{CGI.escape(page_name)}?msg=#{CGI.escape(e.message)}"
175
+ end
176
+ else
177
+ redirect_action "new/#{CGI.escape(page_name)}"
178
+ end
179
+ end
180
+
181
+ def published
182
+ if web.published then @page = wiki.read_page(web_address, page_name || "HomePage") else redirect_show("HomePage") end
183
+ end
184
+
185
+ def print
186
+ @page = wiki.read_page(web_address, page_name)
187
+ end
188
+
189
+ def tex
190
+ @page = wiki.read_page(web_address, page_name)
191
+ @tex_content = RedClothForTex.new(@page.content).to_tex
192
+ end
193
+
194
+ def pdf
195
+ page = wiki.read_page(web_address, page_name)
196
+ safe_page_name = page.name.gsub(/\W/, "")
197
+ file_name = "#{safe_page_name}-#{web.address}-#{page.created_at.strftime("%Y-%m-%d-%H-%M")}"
198
+ file_path = EXPORT_DIRECTORY + file_name
199
+
200
+ export_page_to_tex(file_path + ".tex") unless FileTest.exists?(file_path + ".tex")
201
+ convert_tex_to_pdf(file_path + ".tex")
202
+ send_export(file_name + ".pdf", file_path + ".pdf")
203
+ end
204
+
205
+ def new
206
+ @page_name, @author = page_name, default_author
207
+ end
208
+
209
+ def edit
210
+ @page = wiki.read_page(web_address, page_name)
211
+
212
+ if !@page.locked?(Time.now) || @params["break_lock"]
213
+ @page.lock(Time.now, default_author)
214
+ @author = default_author
215
+ render
216
+ else
217
+ render "wiki/locked"
218
+ end
219
+ end
220
+
221
+ def cancel_edit
222
+ @page = wiki.read_page(web_address, page_name)
223
+ @page.unlock
224
+ redirect_show
225
+ end
226
+
227
+ def save
228
+ if web.pages[page_name]
229
+ page = wiki.revise_page(
230
+ web_address, page_name, @params["content"], Time.now,
231
+ Author.new(@params["author"], remote_ip)
232
+ )
233
+
234
+ page.unlock
235
+ else
236
+ page = wiki.write_page(
237
+ web_address, page_name, @params["content"], Time.now,
238
+ Author.new(@params["author"], remote_ip)
239
+ )
240
+ end
241
+
242
+ write_cookie("author", @params["author"], true)
243
+ redirect_show(page_name)
244
+ end
245
+
246
+ def revision
247
+ @page = wiki.read_page(web_address, page_name)
248
+ @revision = @page.revisions[@params["rev"].to_i]
249
+ end
250
+
251
+ def rollback
252
+ @page = wiki.read_page(web_address, page_name)
253
+ @revision = @page.revisions[@params["rev"].to_i]
254
+ end
255
+
256
+
257
+ protected
258
+ def before_action
259
+ if in_a_web? && !authorized?(web_address) && !%w( login authenticate published ).include?(action_name)
260
+ redirect_action("login")
261
+ return false
262
+ elsif in_a_web?
263
+ @web, @page_name, @action_name = web, page_name, action_name
264
+ end
265
+ end
266
+
267
+ def action_name
268
+ if in_a_web?
269
+ request_path[1]
270
+ elsif action_methods.include?(request_path[0])
271
+ request_path[0]
272
+ else
273
+ "index"
274
+ end
275
+ end
276
+
277
+ def redirect_show(page = @page.name, web = web_address)
278
+ redirect_path "/#{web}/show/#{CGI.escape(page)}"
279
+ end
280
+
281
+ def redirect_action(action, web = web_address)
282
+ redirect_path "/#{web}/#{action}"
283
+ end
284
+
285
+
286
+
287
+ private
288
+ def wiki
289
+ WikiService.instance
290
+ end
291
+
292
+ def web
293
+ wiki.webs[web_address]
294
+ end
295
+
296
+ def in_a_web?
297
+ request_path.length > 1
298
+ end
299
+
300
+ def web_address
301
+ request_path[0]
302
+ end
303
+
304
+ def page_name
305
+ CGI.unescape(request_path[2]) if request_path[2]
306
+ end
307
+
308
+ def authorized?(web_address)
309
+ web.nil? ||
310
+ web.password.nil? ||
311
+ (read_cookie(web_address) && read_cookie(web_address) == web.password) ||
312
+ password_check(@params["password"])
313
+ end
314
+
315
+ def default_author
316
+ read_cookie("author") || "AnonymousCoward"
317
+ end
318
+
319
+ def password_check(password)
320
+ @params["password"] == web.password && write_cookie(web_address, @params["password"])
321
+ end
322
+
323
+ def export_pages_to_zip_file(zip_file_path)
324
+ Zip::ZipOutputStream.open(zip_file_path) do |zos|
325
+ web.select.by_name.each do |@page|
326
+ zos.put_next_entry(@page.name + ".html")
327
+ zos.puts(template_engine("print").result(binding))
328
+ end
329
+
330
+ zos.put_next_entry("index.html")
331
+ zos.puts('<html><head><META HTTP-EQUIV="Refresh" CONTENT="0;URL=HomePage.html"></head></html>')
332
+ end
333
+ end
334
+
335
+ def export_markup_to_zip_file(zip_file_path)
336
+ Zip::ZipOutputStream.open(zip_file_path) do |zos|
337
+ web.select.by_name.each do |page|
338
+ zos.put_next_entry(page.name + ".#{web.markup}")
339
+ zos.puts(page.content)
340
+ end
341
+ end
342
+ end
343
+
344
+ def export_web_to_tex(file_path)
345
+ @web_name = web.name
346
+ @tex_content = table_of_contents(web.pages["HomePage"].content.dup, render_tex_web)
347
+ File.open(file_path, "w") { |f| f.write(template_engine("tex_web").result(binding)) }
348
+ end
349
+
350
+ def render_tex_web
351
+ web.select.by_name.inject({}) do |tex_web, page|
352
+ tex_web[page.name] = RedClothForTex.new(page.content).to_tex
353
+ tex_web
354
+ end
355
+ end
356
+
357
+ def export_page_to_tex(file_path)
358
+ tex
359
+ File.open(file_path, "w") { |f| f.write(template_engine("tex").result(binding)) }
360
+ end
361
+
362
+ def convert_tex_to_pdf(tex_path)
363
+ `cd #{File.dirname(tex_path)}; pdflatex --interaction=scrollmode '#{File.basename(tex_path)}'`
364
+ end
365
+
366
+ def truncate(text, length = 30, truncate_string = "...")
367
+ if text.length > length then text[0..(length - 3)] + truncate_string else text end
368
+ end
369
+
370
+ def render_markup_help
371
+ web ? sub_template("#{web.markup}_help") : ''
372
+ end
373
+
374
+ def send_export(file_name, file_path, content_type = "application/zip")
375
+ @res["Content-Type"] = content_type
376
+ @res["Content-Disposition"] = "attachment; filename=#{file_name}"
377
+ @res["Content-Length"] = File.size(file_path)
378
+ File.open(file_path, "rb") { |f| @res.body = f.read }
379
+ end
380
+
381
+ def template_engine(template_name)
382
+ ERB.new(IO.readlines(action_template_path(template_name)).join)
383
+ end
384
+
385
+ def remote_ip
386
+ $stderr << "#{@req.meta_vars['HTTP_X_FORWARDED_FOR']} || #{@req.meta_vars['REMOTE_ADDR']}"
387
+ @req.meta_vars["HTTP_X_FORWARDED_FOR"] || @req.meta_vars["REMOTE_ADDR"]
388
+ end
389
+ end