Changesets can be listed by changeset number.
The Git repository is here.
Changeset 12
Configured for temporary /rails/rforum location on Alpha. Updated
several layouts to suit RISC OS Open Limited site style in addition
to producing a theme stylesheet. View changes included a few fixes
to invalid HTML 'class' attribute values (they contained spaces).
Some examples may remain. Note temporary hacks to force in
"/rails/rforum" prefix to some URLs where they are either hard coded
or the user helpers but for currently unknown reasons the helpers are
giving an incorrect result.
Extended menu item renderer to allow a separator string to be
supplied; needed to allow horizontal navigation regions as well as
sidebar-based vertical navigation regions ("|" vs "</li><li>").
Fix in models.rb to allow attempts to unsubscribe from a topic from
which the user has already subscribed - e.g. clicking on the relevant
link in a notification e-mail message twice. Previously, an application
error would be raised.
Extended permissions system to include whether or not a user can post
(can_post?()) or reply (can_reply?()) to a message. Normal and admin
users always can. Guests follow new options token "guests_cannot_post"
(note that this is not the same as "anon_posting_allowed" which asks
that guests supply at least their name rather than be anonymous - of
course that's pretty useless as a guest can put in any name they want,
real or otherwise). The navbar and post_menu controllers know about
the new options and won't generate links for prohibited actions. Topic
controller enforces permissions in case someone builds links by hand.
Changed user_controller.rb to add flash[:attention] tokens when a user
logs in or out. Fixed broken hard-coded URL generation to use url_for
helper method instead. Used the flash[:attention] mechanism to produce
the notification about an e-mail message sent for a forgotten password
rather than writing just that text into a blank page - redirects back
to the forum controller, list action.
This revision is believed to be the functional equivalent of revision
906 of RForum merged with changes made to an unknown prior revision of
RForum along with acts_as_authenticated modification plus the above
set of fixes and documentation. At the time of writing this specific
combination has not been tested live on the RISC OS Open Limited
prototype site.
- Comitted by: adh
- Date: Saturday July 22 21:15:03 2006 (over 18 years ago)
Affected files:
- rool/rails/rforum/trunk/app/views/shared/
- rool/rails/rforum/trunk/public/skins/risc_os_open/
- rool/rails/rforum/trunk/app/views/shared/_powered.rhtml
- rool/rails/rforum/trunk/app/views/shared/_theme.rhtml
- rool/rails/rforum/trunk/config/site.rb
- rool/rails/rforum/trunk/public/skins/risc_os_open/style.css
- rool/rails/rforum/trunk/app/controllers/navbar.rb (diff)
- rool/rails/rforum/trunk/app/controllers/post_menu.rb (diff)
- rool/rails/rforum/trunk/app/controllers/topic_controller.rb (diff)
- rool/rails/rforum/trunk/app/controllers/user_controller.rb (diff)
- rool/rails/rforum/trunk/app/helpers/application_helper.rb (diff)
- rool/rails/rforum/trunk/app/models/admin_permissions.rb (diff)
- rool/rails/rforum/trunk/app/models/guest_permissions.rb (diff)
- rool/rails/rforum/trunk/app/models/user.rb (diff)
- rool/rails/rforum/trunk/app/models/user_permissions.rb (diff)
- rool/rails/rforum/trunk/app/views/layouts/default.rhtml (diff)
- rool/rails/rforum/trunk/app/views/nav.rhtml (diff)
- rool/rails/rforum/trunk/app/views/sidebar.rhtml (diff)
- rool/rails/rforum/trunk/app/views/topic/_post.rhtml (diff)
- rool/rails/rforum/trunk/app/views/topic/_postform.rhtml (diff)
- rool/rails/rforum/trunk/app/views/user/login.rhtml (diff)
- rool/rails/rforum/trunk/config/database.yml (diff)
- rool/rails/rforum/trunk/config/environment.rb (diff)
- rool/rails/rforum/trunk/config/routes.rb (diff)
- rool/rails/rforum/trunk/public/dispatch.cgi (diff)
- rool/rails/rforum/trunk/public/dispatch.fcgi (diff)
- rool/rails/rforum/trunk/public/dispatch.rb (diff)
- rool/rails/rforum/trunk/public/stylesheets/main.css (diff)
- rool/rails/rforum/trunk/public/stylesheets/print.css (diff)
rool/rails/rforum/trunk/app/controllers/navbar.rb:
prev. | current | |
end | ||
def new_topic | ||
17 | | |
18 | | |
17 | if @forum and @user.can_post? | |
18 | Item.new(l(:nav_create_topic), | |
{:controller => 'topic', :action => 'new', :params => {'forum_id' => @forum.id}}) | ||
else | ||
nil |
rool/rails/rforum/trunk/app/controllers/post_menu.rb:
prev. | current | |
# Menu of actions that can be done with a post (represented as hyperlinks in post view) | ||
class PostMenu | ||
include RForum::Localization | ||
6 | | |
6 | ||
Item = Struct.new(:prompt, :target, :confirmation_message) | ||
8 | | |
8 | ||
def initialize(post, user) | ||
@post = post | ||
@user = user | ||
... | ... | |
def move | ||
if @user.can_move?(@post.topic) && @post.root? | ||
16 | | |
16 | Item.new(l(:postmenu_move_topic), {:controller => 'topic', :action => 'move', | |
:id => @post.topic_id}) | ||
end | ||
end | ||
... | ... | |
if !@post.hidden? and @user.can_delete?(@post) | ||
# display 'delete topic' for root posts, and 'delete post' for all others | ||
if @post.root? | ||
25 | | |
25 | Item.new(l(:postmenu_delete_topic), {:controller => 'topic', :action => 'delete_post', | |
:id => @post.id}, l(:delete_topic_confirmation_prompt)) | ||
else | ||
Item.new(l(:postmenu_delete_post), | ||
... | ... | |
def edit | ||
if @user.can_edit?(@post) | ||
57 | | |
57 | Item.new(l(:postmenu_edit_post), {:controller => 'topic', :action => 'show', | |
:id => @post.topic_id, :anchor => 'postform', :params => {'edit' => @post.id}}) | ||
else | ||
nil | ||
end | ||
end | ||
63 | | |
63 | ||
def reply_to | ||
65 | | |
66 | | |
67 | | |
65 | if @user.can_reply? | |
66 | Item.new(l(:postmenu_reply_to), | |
67 | {:controller => 'topic', :action => 'show', :id => @post.topic_id, :anchor => 'postform', | |
68 | :params => {'reply_to' => @post.id}}) | |
69 | else | |
70 | nil | |
71 | end | |
end | ||
end |
rool/rails/rforum/trunk/app/controllers/topic_controller.rb:
prev. | current | |
class TopicController < ApplicationController | ||
helper :forum | ||
3 | | |
3 | ||
# Display a topic. If reply_to parameter is included, handle the post editing form, too | ||
def show | ||
begin | ||
... | ... | |
@forum = @topic.forum | ||
return if redirect_if_site_doesnt_match | ||
17 | | |
17 | ||
raise RForum::SecurityError if @topic.hidden? && !@user.can_view_deleted_posts?(@topic) | ||
19 | | |
19 | ||
# Get the time of the last visit | ||
@last_read_at = @user.last_read_time(@topic) || Time.at(0) unless @user.guest? | ||
@user.update_read_time(@topic).updated_at unless @user.guest? | ||
... | ... | |
if not @params['post']['id'].to_s.empty? | ||
# Edit post; check permission and update text and subject | ||
raise RForum::SecurityError unless @user.can_edit?(Post.find(@params['post']['id'])) | ||
31 | | |
31 | post = Post.update(@params['post']['id'], | |
{'subject' => @params['post']['subject'], 'text' => @params['post']['text']}) | ||
else | ||
# Create reply | ||
35 | raise RForum::SecurityError unless @user.can_reply? | |
post = prepare_post_from_params(@params['post']) | ||
post.parent_id = @params['post']['parent_id'] | ||
parent = Post.find(@params['post']['parent_id']) | ||
39 | | |
40 | ||
if parent.topic.forum.readonly == 1 | ||
render_text 'This forum does not allow posts.' | ||
end | ||
43 | | |
44 | ||
parent.add_reply(post) | ||
end | ||
46 | | |
47 | ||
display_post(post) | ||
# on error, re-render the same topic with the form again | ||
rescue RForum::ValidationError => e | ||
... | ... | |
end | ||
# if reply_to parameter specified, prepare template inputs for a post editing form | ||
elsif @params['reply_to'] | ||
54 | ||
if @forum.readonly == 1 | ||
render_text 'This forum does not allow posts.' | ||
end | ||
58 | | |
58 | ||
59 | raise RForum::SecurityError unless @user.can_post? | |
60 | ||
@no_robots = true | ||
@post = prepare_reply_for_form(@params['reply_to']) | ||
elsif @params['edit'] | ||
@no_robots = true | ||
@post = Post.find(@params['edit']) | ||
66 | ||
raise RForum::SecurityError unless @user.can_edit?(@post) | ||
end | ||
end | ||
... | ... | |
# If this action is called via a hyperlink, it displays a form | ||
# Submit button on the same form reinvokes the same action, but also puts the form data | ||
# into @params['post'], and in that case the action creates the form. | ||
71 | | |
74 | # If form creation fails due to validation errors, the form is re-displayed; otherwise | |
# user is redirected to the post in the topic | ||
def new | ||
77 | raise RForum::SecurityError unless @user.can_post? | |
78 | ||
@no_robots = true | ||
@forum = Forum.find(@params['forum_id']) rescue Forum.find_first | ||
@title = "New post in forum '#{@forum.name}'" | ||
... | ... | |
if @params['post'] | ||
# Form submitted | ||
new_post = prepare_post_from_params(@params['post']) | ||
86 | | |
91 | ||
begin | ||
saved_post = @forum.add_post(new_post) | ||
display_post(saved_post) | ||
... | ... | |
@post.author = @user | ||
end | ||
end | ||
100 | | |
105 | ||
def move | ||
topic = Topic.find(@params['id']) | ||
raise RForum::SecurityError unless @user.can_move?(topic) | ||
104 | | |
109 | ||
@title = l(:move_topic_title) | ||
106 | | |
111 | ||
if @params['to'] | ||
new_forum = Forum.find(@params['to']) | ||
topic.forum = new_forum | ||
... | ... | |
@topic = topic | ||
end | ||
end | ||
116 | | |
121 | ||
# Delete a topic or a single post | ||
def delete_post | ||
post = Post.find(@params['id']) | ||
raise RForum::SecurityError unless @user.can_delete?(post) | ||
recursive = @user.can_delete_recursive?(post) && (@params['recursive'].to_i == 1) | ||
123 | | |
128 | ||
if post.root? | ||
Post.transaction do | ||
post.topic.hide | ||
... | ... | |
raise RForum::SecurityError unless @user.can_undelete?(post) | ||
recursive = @user.can_undelete_recursive?(post) && (@params['recursive'].to_i == 1) | ||
143 | | |
148 | ||
if post.root? | ||
Post.transaction do | ||
post.topic.unhide(recursive) | ||
... | ... | |
def unsubscribe | ||
@topic = Topic.find(@params['id']) | ||
unless @user.guest? | ||
175 | # Ignore errors; if the user wasn't subscribed anyway, there's no need | |
176 | # to moan about it. | |
@user.unsubscribe_topic(@topic) | ||
end | ||
redirect_to :controller => 'topic', :action => 'show', :id => @topic.id | ||
end | ||
175 | | |
182 | ||
private | ||
def display_post(post) | ||
... | ... | |
reply_to = Post.find_with_user_data(reply_to_id) | ||
post = Post.new( | ||
'topic_id' => reply_to.topic_id, | ||
186 | | |
193 | 'parent_id' => reply_to.id, | |
'subject' => reply_to.reply_subject, | ||
'text' => "#{reply_to.get_display_name} wrote:\n#{reply_to.quoted_text}\n\n") | ||
post.author = @user | ||
191 | | |
198 | ||
return post | ||
end | ||
# prepare a Post object from a form, update @user with guest_name and guest_email | ||
def prepare_post_from_params(form_attributes) | ||
new_post = Post.new | ||
198 | | |
205 | ||
if form_attributes['new_attachment'] && form_attributes['new_attachment'].size > 0 | ||
new_post.new_attachment = form_attributes['new_attachment'] | ||
end | ||
202 | | |
209 | ||
new_post.subject = form_attributes['subject'] | ||
new_post.text = form_attributes['text'] | ||
205 | | |
212 | ||
if @user.guest? | ||
@user.guest_name = form_attributes['guest_name'] | ||
@user.guest_email = form_attributes['guest_email'] | ||
end | ||
210 | | |
217 | ||
new_post.author = @user | ||
new_post.author_host = @request.remote_ip | ||
213 | | |
220 | ||
return new_post | ||
end | ||
rool/rails/rforum/trunk/app/controllers/user_controller.rb:
prev. | current | |
class UserController < ApplicationController | ||
2 | | |
2 | ||
def login | ||
@title = l(:login_title) | ||
5 | | |
5 | ||
if @params['submit'] | ||
user = User.find_by_login(@params['name'], @params['password']) | ||
if user | ||
# login successful | ||
@user = user | ||
11 | | |
12 | | |
11 | flash[:attention] = "You are now logged in to the forum." | |
return_to_last_remembered | ||
else | ||
# login failed | ||
... | ... | |
user = User.find_by_name(@params['name']) | ||
if user | ||
key = user.generate_security_token | ||
24 | | |
23 | reset_url = url_for({:controller=>'user', :action=>'edit'}) + "?user_id=#{user.id}&key=#{key}" | |
Mailer.deliver_reset_password(user, reset_url) | ||
26 | | |
25 | ||
26 | flash[:attention] = "An e-mail message explaining how to change your password has been sent." | |
27 | redirect_to :controller => 'forum', :action => 'list' | |
else | ||
@error = l(:no_user_with_this_name) | ||
end | ||
... | ... | |
def logout | ||
@user = Guest.new | ||
36 | flash[:attention] = "You are now logged out of the forum." | |
redirect_to :controller => 'forum', :action => 'list' | ||
end | ||
def edit | ||
@title = l(:user_settings_title) | ||
40 | | |
42 | ||
if @params['form'] | ||
# some form was submitted (there are several in the user/edit view) | ||
# need to update user details | ||
... | ... | |
def register | ||
@title = l(:register_title) | ||
70 | | |
72 | ||
if @params['new_user'].nil? | ||
# Show form with a new user object | ||
@new_user = User.new | ||
... | ... | |
@new_user = User.create(@params['new_user']) | ||
password = @new_user.tell_and_forget_unencrypted_password | ||
79 | | |
80 | | |
81 | | |
82 | | |
81 | Mailer.deliver_registration_mail(@new_user, password, | |
82 | url_for({ :controller => 'user', :action => 'login' })) | |
83 | ||
84 | @title = l(:registration_complete_title) | |
render_action 'registration_complete' | ||
rescue RForum::ValidationError => e | ||
@new_user = e.entity | ||
... | ... | |
end | ||
end | ||
end | ||
90 | | |
92 | ||
def show | ||
@title = 'User information' | ||
@selected_user = User.find(@params['id']) | ||
... | ... | |
def list | ||
@title = l(:user_list_title) | ||
109 | | |
111 | ||
@users = User.find_all | ||
end | ||
112 | | |
114 | ||
protected | ||
def render_edit_form(user) | ||
raise RForum::SecurityError.new if user.guest? | ||
@new_user = user | ||
118 | | |
119 | | |
120 | # actual password values should always be hidden, even on re-render with errors, | |
121 | # because we don't want to pass password values in plain HTML. | |
# If user makes a mistake the first time, s/he will have to retype all passwords again. | ||
@new_user.reset_password_fields | ||
render_action 'register' |
rool/rails/rforum/trunk/app/helpers/application_helper.rb:
prev. | current | |
# The methods added to this helper will be available to all templates in the application. | ||
module ApplicationHelper | ||
include RForum::Localization | ||
5 | | |
6 | | |
6 | protected | |
7 | ||
def format_datetime(datetime) | ||
datetime.strftime "%d.%m.%Y %H:%M" | ||
end | ||
11 | | |
11 | ||
# Useful abstraction for form input fields - combines an input field with error message (if any) | ||
# and writes an appropriate style (for errors) | ||
# Usage: | ||
... | ... | |
end | ||
end | ||
59 | | |
59 | # Helper method that has the same signature as real input field helpers, but simply displays | |
# the value of a given field enclosed within <p> </p> tags. | ||
# Usage: | ||
# <%= form_input :read_only_field, 'new_user', 'name', l(:user_name)) %> | ||
... | ... | |
end | ||
def render_navbar_items(*items) | ||
79 | | |
79 | render_menu_items(RForum::NavigationBar.new(@forum, @user), '</li><li>', *items) | |
end | ||
82 | | |
83 | | |
82 | def render_menu_items(menu, joinstr, *items) | |
83 | ((items.map { |item| menu.send(item) }).compact.map { |item| render_menu_item(item) }).join(joinstr) | |
end | ||
def render_menu_item(item) | ||
... | ... | |
if header_text == site_name | ||
site_name | ||
else | ||
98 | | |
98 | link_to("#{site_name}:", { :controller => 'forum', :action => 'list'} ) + " #{header_text}" | |
end | ||
end | ||
end | ||
103 |
rool/rails/rforum/trunk/app/models/admin_permissions.rb:
prev. | current | |
module AdminPermissions | ||
include UserPermissions | ||
5 | | |
5 | ||
6 | def can_post?() true end | |
7 | def can_reply?() true end | |
def can_move?(topic) true end | ||
7 | | |
def can_delete?(post) true end | ||
def can_delete_recursive?(post) true end | ||
def can_undelete?(post) true end | ||
def can_undelete_recursive?(post) true end | ||
12 | ||
def can_edit?(post) true end | ||
14 | ||
def can_view_deleted_posts?(topic=nil) true end | ||
16 | ||
def can_change_user_settings?(user_id) true end | ||
18 | ||
def can_see_user_email?() true end | ||
end |
rool/rails/rforum/trunk/app/models/guest_permissions.rb:
prev. | current | |
module GuestPermissions | ||
def can_move?(topic) false end | ||
3 | ||
def can_delete?(post) false end | ||
def can_delete_recursive?(post) false end | ||
def can_undelete?(post) false end | ||
def can_undelete_recursive?(post) false end | ||
8 | ||
def can_edit?(post) false end | ||
10 | ||
def can_view_deleted_posts?(topic=nil) false end | ||
12 | ||
def can_change_user_settings?(topic) false end | ||
def can_see_user_email? | ||
RForum::CONFIG[:show_user_email_to] == :everyone | ||
end | ||
14 | ||
15 | def can_post? | |
16 | RForum::CONFIG[:guests_cannot_post] == false | |
17 | end | |
18 | ||
19 | def can_reply? | |
20 | RForum::CONFIG[:guests_cannot_post] == false | |
21 | end | |
end |
rool/rails/rforum/trunk/app/models/user.rb:
prev. | current | |
has_many :posts | ||
has_many :topic_reads, :dependent => true | ||
serialize :additional_information, Hash | ||
10 | | |
10 | ||
def self.inheritance_column() 'role' end | ||
include ErrorRaising, RForum::Localization | ||
... | ... | |
return user | ||
end | ||
end | ||
40 | | |
40 | ||
# Encrypts some data with the salt. | ||
def self.encrypt(password, salt) | ||
Digest::SHA1.hexdigest("--#{salt}--#{password}--") | ||
... | ... | |
def before_validation_on_create | ||
%w(name email name firstname surname).each do |attr| | ||
54 | | |
54 | self[attr] = self[attr].to_s.strip.squeeze(' ').chomp | |
end | ||
self.name.downcase! | ||
... | ... | |
errors.add 'firstname', :user_firstname_invalid unless self.firstname =~ /^.{2,20}$/i | ||
errors.add 'surname', :user_surname_invalid unless self.surname =~ /^.{2,20}$/i | ||
errors.add_on_duplicate 'email', :user_email_duplicate | ||
78 | | |
78 | ||
if (@new_password or self.password.nil?) and password.size < 3 | ||
errors.add 'new_password', :user_password_invalid | ||
end | ||
82 | | |
82 | ||
# nick cannot be changed | ||
unless self.new_record? | ||
old_record = User.find(self.id) | ||
errors.add 'name', l(:user_cannot_change_nick) unless old_record.name == self.name | ||
end | ||
end | ||
89 | | |
89 | ||
# NORMAL METHODS | ||
def guest? | ||
... | ... | |
# use the first token. I don't want to create a new table for | ||
# temporary security tokens. | ||
def generate_security_token | ||
108 | | |
108 | if self.security_token.nil? or self.token_expiry.nil? or | |
(Time.now.to_i + token_lifetime / 2) >= self.token_expiry.to_i | ||
return new_security_token | ||
else | ||
... | ... | |
def guest_email | ||
nil | ||
end | ||
132 | | |
132 | ||
def guest_name | ||
nil | ||
end | ||
... | ... | |
# Update the last time a topic was read. | ||
def update_read_time(topic) | ||
topic_read = self.topic_reads.find_all("topic_id = #{topic.id}") | ||
181 | | |
181 | ||
if topic_read.empty? | ||
# first time this topic is read by this user | ||
topic_read = TopicRead.new('topic_id' => topic.id, 'user_id' => self.id) | ||
... | ... | |
end | ||
end | ||
211 | # Returns true if successful, else false. The latter indicates that the | |
212 | # subscription information wasn't found - the user wasn't subscribed. | |
213 | # This can happen if someone follows a notification e-mail link more | |
214 | # than once, or tries to unsubscribe from a topic they were subscribed | |
215 | # to under a different user name, but not under the current user name. | |
216 | ||
def unsubscribe_topic(topic) | ||
212 | | |
218 | found = TopicSubscription.find_first("topic_id = #{topic.id} AND user_id = #{self.id}") | |
219 | ||
220 | if found | |
221 | found.destroy | |
222 | return true | |
223 | else | |
224 | return false | |
225 | end | |
end | ||
# Unencrypted password field is needed in the controller to send an email notification. | ||
216 | | |
229 | # It is populated on creation, and not written to the database, so only a freshly created | |
# user instance has it set. | ||
def tell_and_forget_unencrypted_password | ||
raise "Unencrypted password not available" if @unencrypted_password.nil? | ||
... | ... | |
@unencrypted_password = nil | ||
return p | ||
end | ||
224 | | |
237 | ||
def admin? | ||
false | ||
end | ||
228 | | |
241 | ||
def token_expired? | ||
self.security_token and self.token_expiry and (Time.now > self.token_expiry) | ||
end | ||
... | ... | |
"#{self.firstname} #{self.surname}" | ||
end | ||
237 | ||
250 | private | |
def new_security_token | ||
239 | | |
252 | self['security_token'] = | |
Digest::SHA1.hexdigest(self['password'] + (Time.now.to_i.to_s) + rand.to_s) | ||
self.token_expiry = Time.at(Time.now.to_i + token_lifetime) | ||
self.save | ||
return self['security_token'] | ||
end | ||
245 | | |
258 | ||
def token_lifetime | ||
RForum::CONFIG[:security_token_life_hours] * 60 * 60 | ||
end |
rool/rails/rforum/trunk/app/models/user_permissions.rb:
prev. | current | |
def can_move?(topic) false end | ||
8 | # Normal users can post new topics | |
9 | def can_post?() true end | |
10 | ||
11 | # Normal users can post replies | |
12 | def can_reply?() true end | |
13 | ||
def can_delete?(post) | ||
9 | | |
15 | # Normal users can delete a post that they wrote, if the post has no children | |
# (hidden children don't count) | ||
(self.id == post.user_id) and not post.has_undeleted_children? | ||
end | ||
... | ... | |
def can_see_user_email? | ||
[:everyone, :users].include?(RForum::CONFIG[:show_user_email_to]) | ||
end | ||
27 | | |
33 | ||
end |
rool/rails/rforum/trunk/app/views/layouts/default.rhtml:
prev. | current | |
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> | ||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="de" lang="de" dir="ltr"> | ||
3 | ||
4 | ||
5 | | |
6 | | |
3 | <head> | |
4 | <title><%= h RForum::CONFIG[:site_name] %> - <%= h @title %></title> | |
5 | <meta http-equiv="Content-type" content="text/html; charset=<%= RForum::CONFIG[:web_charset] %>" /> | |
6 | <% if @no_robots %><meta name="robots" content="noindex,follow" /><% end %> | |
8 | | |
9 | | |
10 | | |
11 | | |
12 | | |
13 | | |
14 | | |
15 | | |
16 | | |
17 | | |
18 | | |
19 | | |
20 | | |
21 | | |
8 | <%= stylesheet_link_tag "main.css" %> | |
9 | <%= stylesheet_link_tag "syntax.css" %> | |
10 | <% if @skin %><link type="text/css" rel="stylesheet" href="/rails/rforum/skins/<%= h @skin %>/style.css" /><% end %> | |
23 | | |
24 | | |
25 | | |
12 | <% if @forum %><link rel="alternate" type="application/atom+xml" title="<%= l(:feed_description_forum) %> "<%=h @forum.name %>"" href="/rails/rforum/feed/forum/<%= @forum.id %>" /><% end %> | |
13 | <% if @topic %><link rel="alternate" type="application/atom+xml" title="<%= l(:feed_description_topic) %> "<%=h @topic.subject %>"" href="/rails/rforum/feed/topic/<%= @topic.id %>" /><% end %> | |
14 | <link rel="alternate" type="application/atom+xml" title="<%= l(:feed_description_global) %>" href="/rails/rforum/feed/global" /> | |
15 | </head> | |
16 | <body> | |
17 | <%= render 'shared/fixed_header' %> | |
27 | | |
28 | | |
29 | | |
19 | <!-- Forum contents table --> | |
31 | ||
32 | ||
21 | <p /> | |
22 | <table width="85%" cellspacing="0" cellpadding="0" align="center"> | |
23 | <tr valign="top" align="left"> | |
24 | <td width="75%"> | |
25 | <%= '<h2 align="left" class="notice">' + flash[:notice] + '</h2><p>' if (flash[:notice]) %><%= '<h2 align="left" class="attention">' + flash[:attention] + '</h2><p>' if (flash[:attention]) %><%= '<h2 align="left" class="alert">' + flash[:alert] + '</h2><p>' if (flash[:alert]) %> | |
26 | <h2 id="pageName"><%= header %></h2> | |
34 | ||
35 | | |
36 | | |
37 | | |
38 | | |
39 | | |
40 | | |
41 | | |
42 | | |
43 | | |
44 | | |
45 | ||
28 | <p /> | |
29 | <div id="content"> | |
30 | <%= @content_for_layout %> | |
31 | </div> | |
32 | </td> | |
47 | ||
34 | <td> </td> | |
35 | <td bgcolor="#bbbbbb" class="column_divider"><img src="/images/utilities/blank.gif" width="1" height="1" alt="." border="0" /></td> | |
36 | <td> </td> | |
49 | ||
38 | <td width="25%"> | |
39 | <div id="sidebar"> | |
40 | <%= render 'sidebar' %> | |
41 | </div> | |
42 | <div id="nav-top"> | |
43 | <%= render 'nav' %> | |
44 | </div> | |
45 | </td> | |
46 | </tr> | |
47 | </table> | |
48 | ||
49 | <%= render 'shared/fixed_footer' %> | |
50 | </body> | |
</html> |
rool/rails/rforum/trunk/app/views/nav.rhtml:
prev. | current | |
1 | ||
2 | | |
3 | | |
4 | | |
5 | | |
6 | | |
7 | | |
8 | | |
9 | | |
10 | | |
11 | | |
12 | | |
13 | | |
14 | | |
15 | | |
16 | | |
17 | | |
18 | | |
19 | | |
20 | | |
21 | | |
22 | | |
23 | | |
24 | | |
1 | <div class="navbar"> | |
2 | <h3>Options</h3> | |
26 | | |
27 | ||
4 | <ul> | |
5 | <li><%= render_navbar_items(:forums_list, :new_topic, :search, :user_settings, :user_list, :login_info) %></li> | |
6 | </ul> | |
7 | ||
8 | <% if @page %> | |
9 | <% | |
10 | # Additional parameters for the page URLs. | |
11 | # This should probably be moved somewhere else. | |
12 | @page_params ||= {} | |
13 | %> | |
14 | ||
15 | <% if @page > 1 %> | |
16 | <%= link_to(h('<<'), :params => ({'page' => (@page - 1)}.merge(@page_params))) %> | |
17 | <% end %> | |
18 | ||
19 | Page <%= @page %> | |
20 | ||
21 | <% unless @last_page %> | |
22 | <%= link_to(h('>>'), :params => ({'page' => (@page + 1)}.merge(@page_params))) %> | |
23 | <% end %> | |
24 | <% end %> | |
25 | </div> |
rool/rails/rforum/trunk/app/views/sidebar.rhtml:
prev. | current | |
1 | ||
2 | ||
3 | ||
4 | | |
5 | | |
6 | | |
7 | | |
8 | | |
9 | | |
10 | ||
11 | ||
1 | <div class="sidebar-node"> | |
2 | <h3>Search forums</h3> | |
13 | ||
14 | ||
15 | ||
16 | ||
17 | ||
18 | ||
19 | ||
4 | <p /> | |
5 | <form method="post" action="/rails/rforum/forum/search"> | |
6 | <input type="text" name="query" size="15" value="<%=h @query.to_s %>" /> | |
7 | <input type="submit" name="submit" value="Go" /> | |
8 | </form> | |
9 | </div> | |
11 | <%= render 'shared/fixed_sidebar' %> | |
12 | ||
13 | <p /> | |
14 | <div class="sidebar-node"> | |
15 | <h3>Forums</h3> | |
16 | ||
17 | <ul><% @forums.each do |forum| %> | |
18 | <li> | |
19 | <%= link_to(forum.name, | |
20 | { :controller => 'forum', :action => 'forum', :id => forum.id }, | |
21 | :title => forum.description) | |
22 | %> | |
23 | </li><% end %> | |
24 | </ul> | |
25 | </div> |
rool/rails/rforum/trunk/app/views/topic/_post.rhtml:
prev. | current | |
<a name="new"></a> | ||
<% @have_newpost_anchor = true %> | ||
<% end %> | ||
5 | ||
6 | ||
7 | ||
8 | ||
5 | <div class="post<%= "_new" if @last_read_at and post.created_at > @last_read_at %><%= "_deleted" if post.hidden? %>"> | |
<div class="subject"> | ||
10 | | |
7 | <strong><a name="<%=h post.id %>" href="/rails/rforum/#<%=h post.id %>"><%=h post.subject %><%= ' (' + l(:deleted_post) + ')' if post.hidden? %></a></strong> | |
</div> | ||
<div class="info"> | ||
... | ... | |
<% for attachment in post.attachments %> | ||
<div class="attachment"> | ||
<%=l :attachment %>: | ||
44 | | |
41 | <a href="/rails/rforum<%=h attachment.url %>"><%=h attachment.filename %></a> | |
</div> | ||
<% end %> | ||
47 | | |
44 | ||
<% if post.post_method == 'mail' %> | ||
49 | | |
46 | <%= image_tag("email.png", options = { :alt => l(:received_by_mail), :title => l(:received_by_mail) } ) %> | |
<% end %> | ||
</div> | ||
... | ... | |
<div class="foot"> | ||
<% menu = RForum::PostMenu.new(post, @user) %> | ||
63 | | |
60 | <%= render_menu_items(menu, ' | ', :edit, :move, :undelete, :delete, :reply_to) %> | |
</div> | ||
</div> |
rool/rails/rforum/trunk/app/views/topic/_postform.rhtml:
prev. | current | |
<%= form_input(:text_field, 'post', 'subject', 'Subject', 'size' => '60', 'maxlength' => '60') %> | ||
<%= form_input(:file_field, 'post', 'new_attachment', 'Attachment') %> | ||
27 | | |
27 | <%= form_input(:text_area, 'post', 'text', 'Text', 'cols' => 80, 'rows' => 16, 'wrap' => 'virtual') %> | |
<%= form_input(:submit_button, 'post', 'submit', 'Submit') %> | ||
</table> |
rool/rails/rforum/trunk/app/views/user/login.rhtml:
prev. | current | |
<div class="login"> | ||
3 | <% if @error %> | |
4 | <div class="formError"><h2 class="alert"><%= @error %></h2></div> | |
5 | <p> | |
6 | <% end %> | |
7 | ||
<div class="box"> | ||
4 | | |
9 | <strong><%=l :login_no_account %></strong> <a href="/rails/rforum<%=h url_for(:action => 'register') %>"><%=l :login_register_here %></a> | |
</div> | ||
<div class="box"> | ||
<strong><%=l :login_existing_account %></strong><br /> | ||
10 | | |
11 | | |
12 | | |
13 | | |
<form action="<%=h url_for() %>" method="post"> | ||
15 | | |
16 | ||
<table> | ||
<tr> | ||
<td> | ||
... | ... | |
</td> | ||
</tr> | ||
</table> | ||
34 | | |
35 | ||
<input type="submit" value="<%=l :login_submit %>" name="submit" /> | ||
<input type="submit" value="<%=l :i_forgot_my_password %>" name="i_forgot_my_password" /> | ||
37 | | |
38 | ||
<% if @params['from'] %> | ||
<input type="hidden" name="from" value="<%=h @params['from'] %>" /> | ||
<% end %> |
rool/rails/rforum/trunk/config/database.yml:
prev. | current | |
1 | ||
2 | ||
3 | | |
4 | | |
1 | # RForum PostgreSQL database configuration. Syntax taken from | |
2 | # "http://blog.bleything.net/" (Ben Bleything, June 2006). | |
6 | ||
7 | ||
8 | ||
9 | ||
10 | ||
11 | ||
12 | ||
4 | dbinfo: &dbinfo | |
5 | adapter: postgresql | |
6 | host: /home/adh/postgres/ | |
7 | username: adh | |
8 | password: oiarfewa | |
9 | ||
10 | # Warning: The database defined as 'test' will be erased and | |
11 | # re-generated from your development database when you run 'rake'. | |
12 | # Do not set this db to the same as development or production. | |
14 | ||
15 | ||
16 | ||
17 | ||
18 | ||
19 | ||
20 | ||
21 | ||
22 | ||
development: | ||
24 | | |
25 | | |
15 | <<: *dbinfo | |
16 | database: rforum | |
test: | ||
28 | | |
29 | | |
19 | <<: *dbinfo | |
20 | database: rforum-test | |
21 | ||
22 | production: | |
23 | <<: *dbinfo | |
24 | database: rforum |
rool/rails/rforum/trunk/config/environment.rb:
prev. | current | |
require File.join(File.dirname(__FILE__), 'boot') | ||
Rails::Initializer.run do |config| | ||
11 | # We don't run in the document root, so images etc. must come from | |
12 | # a non-root location too. Hijack the 'asset host' facility to get | |
13 | # helper-based links pointing in the right place. | |
14 | config.action_controller.asset_host = "/rails/rforum" | |
15 | ||
# Skip frameworks you're not going to use | ||
config.frameworks -= [ :action_web_service ] | ||
# Add additional load paths for your own custom dirs | ||
# config.load_paths += %W( #{RAILS_ROOT}/app/services ) | ||
17 | | |
22 | # Force all environments to use the same logger level | |
# (by default production uses :info, the others :debug) | ||
config.log_level = :warn | ||
... | ... | |
# Make Active Record use UTC-base instead of local time | ||
# config.active_record.default_timezone = :utc | ||
34 | | |
39 | ||
# Use Active Record's schema dumper instead of SQL when creating the test database | ||
# (enables use of different database adapters for development and test environments) | ||
config.active_record.schema_format = :ruby | ||
... | ... | |
# See Rails::Configuration for more options | ||
end | ||
42 | ||
47 | # Add new inflection rules using the following format | |
# (all these examples are active by default): | ||
# Inflector.inflections do |inflect| | ||
# inflect.plural /^(ox)$/i, '\1en' | ||
... | ... | |
# end | ||
# Include your application configuration below | ||
57 | ||
58 | # Allow multiple Rails applications by giving the session cookie a | |
59 | # unique prefix. | |
60 | ||
61 | ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS[:session_key] = 'rforumapp_session_id' | |
62 | ||
require RAILS_ROOT + '/config/app.rb' |
rool/rails/rforum/trunk/config/routes.rb:
prev. | current | |
ActionController::Routing::Routes.draw do |map| | ||
2 | | |
3 | | |
2 | map.connect '/rails/rforum/', :controller => 'forum', :action => 'list' | |
3 | map.connect '/rails/rforum/topic/:id', :controller => 'topic', :action => 'show', | |
:requirements => {:id => /^[0-9]+$/} | ||
5 | | |
5 | map.connect '/rails/rforum/forum/:id', :controller => 'forum', :action => 'forum', | |
:requirements => {:id => /^[0-9]+$/} | ||
7 | | |
8 | | |
7 | map.connect '/rails/rforum/search', :controller => 'forum', :action => 'search' | |
8 | map.connect '/rails/rforum/attachment/:id/:filename', :controller => 'attachment', | |
:action => 'fetch', :requirements => {:id => /^[0-9]+$/} | ||
10 | | |
11 | | |
10 | map.connect '/rails/rforum/:controller/:action/:id' | |
11 | map.connect '/rails/rforum/:controller/:action' | |
end |
rool/rails/rforum/trunk/public/dispatch.cgi:
prev. | current | |
1 | ||
1 | #!/bin/ruby | |
require File.dirname(__FILE__) + "/../config/environment" unless defined?(RAILS_ROOT) | ||
... | ... | |
require "dispatcher" | ||
ADDITIONAL_LOAD_PATHS.reverse.each { |dir| $:.unshift(dir) if File.directory?(dir) } if defined?(Apache::RubyRun) | ||
10 | ||
11 | Dispatcher.dispatch |
rool/rails/rforum/trunk/public/dispatch.fcgi:
prev. | current | |
1 | ||
1 | #!/bin/env ruby | |
# | ||
# You may specify the path to the FastCGI crash log (a log of unhandled | ||
# exceptions which forced the FastCGI instance to exit, great for debugging) |
rool/rails/rforum/trunk/public/dispatch.rb:
prev. | current | |
1 | ||
1 | #!/bin/ruby | |
require File.dirname(__FILE__) + "/../config/environment" unless defined?(RAILS_ROOT) | ||
... | ... | |
require "dispatcher" | ||
ADDITIONAL_LOAD_PATHS.reverse.each { |dir| $:.unshift(dir) if File.directory?(dir) } if defined?(Apache::RubyRun) | ||
10 | ||
11 | Dispatcher.dispatch |
rool/rails/rforum/trunk/public/stylesheets/main.css:
prev. | current | |
.clear { clear: both; } | ||
2 | .currentlink { text-decoration: underline ! important; } | |
4 | /* | |
5 | ||
body | ||
{ | ||
font-family: "Lucida Grande", verdana, arial, helvetica, sans-serif; | ||
... | ... | |
a, a:link, a:visited { color: #a00000; text-decoration: none; } | ||
a:hover { text-decoration: underline; } | ||
15 | ||
16 | ||
a img { border-width: 0; } | ||
h1#pageName { | ||
... | ... | |
h2 { font-size: 18px } | ||
h3 { font-size: 16px } | ||
39 | */ | |
40 | ||
/* <Sidebar> */ | ||
43 | /* | |
44 | ||
#sidebar { | ||
text-align: left; | ||
width: 15ex; | ||
... | ... | |
margin-left: 0; | ||
} | ||
61 | */ | |
62 | ||
/* </Sidebar> */ | ||
65 | /* | |
66 | ||
#container { | ||
width: 80%; | ||
float: right; | ||
... | ... | |
height: 15em; | ||
} | ||
123 | /* | |
124 | ||
/* Forum list view */ | ||
126 | ||
127 | /* | |
128 | ||
.forum div.list .name { | ||
font-weight: bold; | ||
} | ||
... | ... | |
font-weight: normal; | ||
} | ||
142 | */ | |
143 | ||
/* Forum view */ | ||
145 | ||
146 | /* | |
147 | ||
.forum div.forum td.subject { | ||
width: 50%; | ||
} | ||
... | ... | |
margin: 0; | ||
} | ||
157 | */ | |
158 | ||
/* <borders> */ | ||
160 | ||
161 | /* | |
162 | ||
table.list { | ||
border: 1px solid #EEE; | ||
} | ||
... | ... | |
.forum .forum table.topics td.last-post { | ||
border-right: 1px solid #EEE; | ||
} | ||
182 | ||
183 | */ | |
184 | ||
/* </borders> */ | ||
187 | /* | |
.forum .forum table.topics .last-post { | ||
padding-left: 15px; | ||
... | ... | |
color: #D0D0D0 ! important; | ||
} | ||
205 | */ | |
206 | ||
/* Topic view */ | ||
208 | ||
209 | /* | |
210 | ||
.forum .post { | ||
margin-bottom: 1.5ex; | ||
padding-bottom: 0.4ex; | ||
... | ... | |
} | ||
.forum .post .subject { | ||
192 | ||
color: #101010; | ||
margin-bottom: 5px; | ||
font-size: 1.1em; | ||
... | ... | |
} | ||
.forum .topic .foot a { | ||
226 | ||
padding-left: 3px; | ||
padding-right: 3px; | ||
padding-bottom: 1px; | ||
... | ... | |
text-decoration: none; | ||
} | ||
265 | */ | |
235 | ||
236 | ||
237 | ||
/* Styles for simple quote coloring */ | ||
.forum .post span.quoting-level-1 { color: #007000; } | ||
.forum .post span.quoting-level-2 { color: #000070; } | ||
... | ... | |
.forum .post div.level-5 { border-left: 2px solid #800080; } | ||
.forum .post div.level-6 { border-left: 2px solid #606000; } | ||
267 | ||
268 | ||
269 | ||
270 | ||
271 | ||
.forum .searchresults td.subject { | ||
width: 50%; | ||
} |
rool/rails/rforum/trunk/public/stylesheets/print.css:
prev. | current | |
1 | /* | |
2 | ||
body { | ||
font-family: serif; | ||
} | ||
... | ... | |
.foot { | ||
display: none; | ||
} | ||
31 | ||
32 | */ | |
33 |