parlement 0.1
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.
- data/CHANGES +709 -0
- data/COPYING +223 -0
- data/README +20 -0
- data/Rakefile +136 -0
- data/app/controllers/account_controller.rb +181 -0
- data/app/controllers/application.rb +30 -0
- data/app/controllers/elt_controller.rb +83 -0
- data/app/helpers/account_helper.rb +2 -0
- data/app/helpers/application_helper.rb +4 -0
- data/app/helpers/elt_helper.rb +37 -0
- data/app/helpers/live_tree.rb +238 -0
- data/app/helpers/mailman.rb +96 -0
- data/app/models/attachment.rb +4 -0
- data/app/models/elt.rb +17 -0
- data/app/models/mail.rb +4 -0
- data/app/models/notifier.rb +13 -0
- data/app/models/person.rb +9 -0
- data/app/models/user.rb +7 -0
- data/app/models/user_notify.rb +75 -0
- data/app/views/account/_help.rhtml +23 -0
- data/app/views/account/_login.rhtml +57 -0
- data/app/views/account/_show.rhtml +31 -0
- data/app/views/account/logout.rhtml +10 -0
- data/app/views/account/signup.rhtml +17 -0
- data/app/views/account/welcome.rhtml +13 -0
- data/app/views/elt/_elt.rhtml +105 -0
- data/app/views/elt/_form.rhtml +31 -0
- data/app/views/elt/_list.rhtml +28 -0
- data/app/views/elt/new.rhtml +102 -0
- data/app/views/elt/rss.rxml +31 -0
- data/app/views/elt/show.rhtml +46 -0
- data/app/views/elt/show_tree.rhtml +8 -0
- data/app/views/layouts/scaffold.rhtml +13 -0
- data/app/views/layouts/top.rhtml +45 -0
- data/app/views/notifier/changeEmail.rhtml +10 -0
- data/config/boot.rb +17 -0
- data/config/database.yml +82 -0
- data/config/environment.rb +92 -0
- data/config/environments/development.rb +17 -0
- data/config/environments/production.rb +17 -0
- data/config/environments/test.rb +17 -0
- data/config/environments/user_environment.rb +1 -0
- data/config/routes.rb +28 -0
- data/db/ROOT/CV.txt +166 -0
- data/db/ROOT/IP.txt +3 -0
- data/db/ROOT/parleR.txt +3 -0
- data/db/ROOT/parlement/security.txt +34 -0
- data/db/ROOT/parlement/test.txt +4 -0
- data/db/ROOT/parlement.txt +51 -0
- data/db/ROOT/perso.txt +215 -0
- data/db/schema.sql +127 -0
- data/lib/data_import.rb +54 -0
- data/lib/file_column.rb +263 -0
- data/lib/file_column_helper.rb +45 -0
- data/lib/localization.rb +88 -0
- data/lib/localizer.rb +88 -0
- data/lib/login_system.rb +87 -0
- data/lib/rails_file_column.rb +19 -0
- data/lib/user_system.rb +101 -0
- data/public/404.html +8 -0
- data/public/500.html +8 -0
- data/public/dispatch.cgi +10 -0
- data/public/dispatch.fcgi +24 -0
- data/public/dispatch.rb +10 -0
- data/public/engine_files/README +5 -0
- data/public/engine_files/login_engine/stylesheets/login_engine.css +81 -0
- data/public/favicon.ico +0 -0
- data/public/favicon.png +0 -0
- data/public/images/live_tree_branch_collapsed_icon.gif +0 -0
- data/public/images/live_tree_branch_expanded_icon.gif +0 -0
- data/public/images/live_tree_leaf_icon.gif +0 -0
- data/public/images/live_tree_loading_spinner.gif +0 -0
- data/public/images/webfeed.gif +0 -0
- data/public/javascripts/controls.js +721 -0
- data/public/javascripts/dragdrop.js +519 -0
- data/public/javascripts/effects.js +992 -0
- data/public/javascripts/live_tree.js +749 -0
- data/public/javascripts/prototype.js +1726 -0
- data/public/javascripts/scriptaculous.js +47 -0
- data/public/javascripts/slider.js +258 -0
- data/public/oldREADME +190 -0
- data/public/oldindex.html +78 -0
- data/public/robots.txt +1 -0
- data/public/stylesheets/default.css +238 -0
- data/public/stylesheets/live_tree.css +62 -0
- data/public/stylesheets/scaffold.css +74 -0
- data/script/about +3 -0
- data/script/benchmarker +19 -0
- data/script/breakpointer +3 -0
- data/script/console +3 -0
- data/script/create_db +7 -0
- data/script/destroy +3 -0
- data/script/generate +3 -0
- data/script/performance/benchmarker +3 -0
- data/script/performance/profiler +3 -0
- data/script/plugin +3 -0
- data/script/process/reaper +3 -0
- data/script/process/spawner +3 -0
- data/script/process/spinner +3 -0
- data/script/profiler +34 -0
- data/script/runner +3 -0
- data/script/server +3 -0
- data/test/fixtures/attachments.yml +10 -0
- data/test/fixtures/elts.yml +15 -0
- data/test/fixtures/mails.yml +7 -0
- data/test/fixtures/people.yml +49 -0
- data/test/fixtures/users.yml +41 -0
- data/test/functional/account_controller_test.rb +239 -0
- data/test/functional/elt_controller_test.rb +18 -0
- data/test/mocks/test/time.rb +17 -0
- data/test/mocks/test/user_notify.rb +16 -0
- data/test/test_helper.rb +28 -0
- data/test/unit/attachment_test.rb +14 -0
- data/test/unit/elt_test.rb +14 -0
- data/test/unit/mail_test.rb +14 -0
- data/test/unit/notifier_test.rb +31 -0
- data/test/unit/person_test.rb +24 -0
- data/test/unit/user_test.rb +94 -0
- data/vendor/plugins/engines/CHANGELOG +7 -0
- data/vendor/plugins/engines/README +128 -0
- data/vendor/plugins/engines/init.rb +33 -0
- data/vendor/plugins/engines/lib/action_mailer_extensions.rb +160 -0
- data/vendor/plugins/engines/lib/action_view_extensions.rb +130 -0
- data/vendor/plugins/engines/lib/dependencies_extensions.rb +56 -0
- data/vendor/plugins/engines/lib/engines.rb +292 -0
- data/vendor/plugins/engines/lib/ruby_extensions.rb +127 -0
- data/vendor/plugins/engines/lib/testing_extensions.rb +33 -0
- data/vendor/plugins/engines/test/ruby_extensions_test.rb +94 -0
- data/vendor/plugins/login_engine/README +258 -0
- data/vendor/plugins/login_engine/app/controllers/user_controller.rb +248 -0
- data/vendor/plugins/login_engine/app/helpers/user_helper.rb +88 -0
- data/vendor/plugins/login_engine/app/models/user.rb +7 -0
- data/vendor/plugins/login_engine/app/models/user_notify.rb +75 -0
- data/vendor/plugins/login_engine/app/views/user/_edit.rhtml +11 -0
- data/vendor/plugins/login_engine/app/views/user/_password.rhtml +9 -0
- data/vendor/plugins/login_engine/app/views/user/change_password.rhtml +17 -0
- data/vendor/plugins/login_engine/app/views/user/edit.rhtml +23 -0
- data/vendor/plugins/login_engine/app/views/user/forgot_password.rhtml +18 -0
- data/vendor/plugins/login_engine/app/views/user/home.rhtml +7 -0
- data/vendor/plugins/login_engine/app/views/user/login.rhtml +17 -0
- data/vendor/plugins/login_engine/app/views/user/logout.rhtml +8 -0
- data/vendor/plugins/login_engine/app/views/user/signup.rhtml +17 -0
- data/vendor/plugins/login_engine/app/views/user_notify/change_password.rhtml +10 -0
- data/vendor/plugins/login_engine/app/views/user_notify/delete.rhtml +5 -0
- data/vendor/plugins/login_engine/app/views/user_notify/forgot_password.rhtml +11 -0
- data/vendor/plugins/login_engine/app/views/user_notify/pending_delete.rhtml +9 -0
- data/vendor/plugins/login_engine/app/views/user_notify/signup.rhtml +12 -0
- data/vendor/plugins/login_engine/db/schema.rb +25 -0
- data/vendor/plugins/login_engine/init_engine.rb +10 -0
- data/vendor/plugins/login_engine/lib/login_engine/authenticated_system.rb +107 -0
- data/vendor/plugins/login_engine/lib/login_engine/authenticated_user.rb +149 -0
- data/vendor/plugins/login_engine/lib/login_engine.rb +58 -0
- data/vendor/plugins/login_engine/public/stylesheets/login_engine.css +81 -0
- data/vendor/plugins/login_engine/tasks/tasks.rake +4 -0
- data/vendor/plugins/login_engine/test/fixtures/templates/users.yml +41 -0
- data/vendor/plugins/login_engine/test/fixtures/users.yml +41 -0
- data/vendor/plugins/login_engine/test/functional/user_controller_test.rb +533 -0
- data/vendor/plugins/login_engine/test/mocks/mail.rb +14 -0
- data/vendor/plugins/login_engine/test/mocks/time.rb +19 -0
- data/vendor/plugins/login_engine/test/test_helper.rb +15 -0
- data/vendor/plugins/login_engine/test/unit/user_test.rb +94 -0
- metadata +276 -0
data/lib/data_import.rb
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# This is to load initial data
|
|
2
|
+
|
|
3
|
+
require 'iconv'
|
|
4
|
+
require 'config/environment'
|
|
5
|
+
|
|
6
|
+
dir = 'db/ROOT'
|
|
7
|
+
|
|
8
|
+
ICONV = Iconv.new('UTF-8', 'ISO-8859-15')
|
|
9
|
+
|
|
10
|
+
def inputDir(directory)
|
|
11
|
+
Dir.glob(directory+'/*.txt') do |file|
|
|
12
|
+
dir = directory+'/'+file
|
|
13
|
+
inputFile File.basename(directory), file
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
Dir.foreach(directory) do |d|
|
|
17
|
+
if (d != '.' and d != '..')
|
|
18
|
+
dir = directory+'/'+d
|
|
19
|
+
if (File.directory?(dir) or File.symlink?(dir))
|
|
20
|
+
#puts 'dir: '+dir
|
|
21
|
+
inputDir dir
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def inputFile(d, fileName)
|
|
28
|
+
puts 'Loading: '+fileName
|
|
29
|
+
|
|
30
|
+
elt = Elt.find_by_id(File.basename(fileName).gsub(/.txt/, ''))
|
|
31
|
+
|
|
32
|
+
file = File.new(fileName)
|
|
33
|
+
|
|
34
|
+
if elt == nil
|
|
35
|
+
elt = Elt.new
|
|
36
|
+
elt.id = File.basename(fileName).gsub(/.txt/, '')
|
|
37
|
+
elt.created_on = nil
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
if elt.created_on == nil or elt.created_on < file.mtime
|
|
41
|
+
elt.parent_id = d
|
|
42
|
+
elt.created_on = file.mtime
|
|
43
|
+
puts elt.created_on.class
|
|
44
|
+
elt.subject = ICONV.iconv(file.gets.strip)
|
|
45
|
+
elt.body = format(ICONV.iconv(file.gets('\n')))
|
|
46
|
+
print "subject: "+elt.subject
|
|
47
|
+
#puts "body: "+elt.body
|
|
48
|
+
puts " (created_on: "+elt.created_on.to_s+")"
|
|
49
|
+
elt.save
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
inputDir dir
|
|
54
|
+
|
data/lib/file_column.rb
ADDED
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
require 'fileutils'
|
|
2
|
+
require 'tempfile'
|
|
3
|
+
|
|
4
|
+
module FileColumn # :nodoc:
|
|
5
|
+
def self.append_features(base)
|
|
6
|
+
super
|
|
7
|
+
base.extend(ClassMethods)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# The FileColumn module allows you to easily handle file uploads. You can designate
|
|
11
|
+
# one or more columns of your model's table as "file columns" like this:
|
|
12
|
+
#
|
|
13
|
+
# class Entry < ActiveRecord::Base
|
|
14
|
+
#
|
|
15
|
+
# file_column :image
|
|
16
|
+
# end
|
|
17
|
+
#
|
|
18
|
+
# Now, by default, an uploaded file "test.png" for an entry object with primary key 42 will
|
|
19
|
+
# be stored in in "public/entry/image/42/test.png". The filename "test.png" will be stored
|
|
20
|
+
# in the record's +image+ column.
|
|
21
|
+
#
|
|
22
|
+
# The methods of this module are automatically included into ActiveRecord::Base as class
|
|
23
|
+
# methods, so that you can use them in your models.
|
|
24
|
+
#
|
|
25
|
+
# == Generated Methods
|
|
26
|
+
#
|
|
27
|
+
# After calling "<tt>file_column :image</tt>" as in the example above, a number of instance methods
|
|
28
|
+
# will automatically be generated, all prefixed by "image":
|
|
29
|
+
#
|
|
30
|
+
# * <tt>Entry#image=(uploaded_file)</tt>: this will handle a newly uploaded file (see below). Note that
|
|
31
|
+
# you can simply call your upload field "entry[image]" in your view (or use the helper).
|
|
32
|
+
# * <tt>Entry#image</tt>: This will return an absolute path (as a string) to the currently uploaded file
|
|
33
|
+
# or nil if no file has been uploaded
|
|
34
|
+
# * <tt>Entry#image_relative_path</tt>: This will return a path relative to this file column's base
|
|
35
|
+
# directory
|
|
36
|
+
# as a string or nil if no file has been uploaded. This would be "42/test.png" in the example.
|
|
37
|
+
# * <tt>Entry#image_just_uploaded?</tt>: Returns true if a new file has been uploaded to this instance.
|
|
38
|
+
# You can use this in <tt>before_validation</tt> to resize images on newly uploaded files, for example.
|
|
39
|
+
#
|
|
40
|
+
# You can access the raw value of the "image" column (which will contain the filename) via the
|
|
41
|
+
# <tt>ActiveRecord::Base#attributes</tt> or <tt>ActiveRecord::Base#[]</tt> methods like this:
|
|
42
|
+
#
|
|
43
|
+
# entry['image'] # e.g."test.png"
|
|
44
|
+
#
|
|
45
|
+
# == Storage of uploaded file
|
|
46
|
+
#
|
|
47
|
+
# For a model class +Entry+ and a column +image+, all files will be stored under
|
|
48
|
+
# "public/entry/image". A sub-directory named after the primary key of the object will
|
|
49
|
+
# be created, so that files can be stored using their real filename. For example, a file
|
|
50
|
+
# "test.png" stored in an Entry object with id 42 will be stored in
|
|
51
|
+
#
|
|
52
|
+
# public/entry/image/42/test.png
|
|
53
|
+
#
|
|
54
|
+
# Files will be moved to this location in an +after_save+ callback. They will be stored in
|
|
55
|
+
# a temporary location previously as explained in the next section.
|
|
56
|
+
#
|
|
57
|
+
# == Handling of form redisplay
|
|
58
|
+
#
|
|
59
|
+
# Suppose you have a form for creating a new object where the user can upload an image. The form may
|
|
60
|
+
# have to be re-displayed because of validation errors. The uploaded file has to be stored somewhere so
|
|
61
|
+
# that the user does not have to upload it again. FileColumn will store these in a temporary directory
|
|
62
|
+
# (called "tmp" and located under the column's base directory by default) so that it can be moved to
|
|
63
|
+
# the final location if the object is successfully created. If the form is never completed, though, you
|
|
64
|
+
# can easily remove all the images in this "tmp" directory once per day or so.
|
|
65
|
+
#
|
|
66
|
+
# So in the example above, the image "test.png" would first be stored in
|
|
67
|
+
# "public/entry/image/tmp/<some_random_key>/test.png" and be moved to
|
|
68
|
+
# "public/entry/image/<primary_key>/test.png".
|
|
69
|
+
#
|
|
70
|
+
# This temporary location of newly uploaded files has another advantage when updating objects. If the
|
|
71
|
+
# update fails for some reasons (e.g. due to validations), the existing image will not be overwritten, so
|
|
72
|
+
# it has a kind of "transactional behaviour".
|
|
73
|
+
module ClassMethods
|
|
74
|
+
|
|
75
|
+
DEFAULT_OPTIONS = {
|
|
76
|
+
"root_path" => File.join(RAILS_ROOT, "public"),
|
|
77
|
+
"web_root" => ""
|
|
78
|
+
}.freeze
|
|
79
|
+
|
|
80
|
+
# handle one or more attributes as "file-upload" columns, generating additional methods as explained
|
|
81
|
+
# above. You should pass the names of the attributes as symbols, like this:
|
|
82
|
+
#
|
|
83
|
+
# file_column :image, :another_image
|
|
84
|
+
def file_column(*args)
|
|
85
|
+
options = DEFAULT_OPTIONS.dup
|
|
86
|
+
options.update(args.pop) if args.last.is_a?(Hash)
|
|
87
|
+
|
|
88
|
+
options["base_path"] ||= File.join(options["root_path"], Inflector.underscore(self.name).to_s)
|
|
89
|
+
options["base_url"] ||= options["web_root"]+"/"+Inflector.underscore(self.name).to_s+"/"
|
|
90
|
+
args.each do |attr|
|
|
91
|
+
store_dir = File.join(options["base_path"], attr.to_s)
|
|
92
|
+
tmp_base_dir = File.join(store_dir, "tmp")
|
|
93
|
+
FileUtils.mkpath([store_dir,tmp_base_dir])
|
|
94
|
+
|
|
95
|
+
column_attr = attr.to_s
|
|
96
|
+
column_read_method = attr.to_sym
|
|
97
|
+
column_write_method = (attr.to_s+"=").to_sym
|
|
98
|
+
read_temp_method = "#{attr}_temp".to_sym
|
|
99
|
+
write_temp_method = "#{attr}_temp=".to_sym
|
|
100
|
+
column_relative_path_method = (attr.to_s+"_relative_path").to_sym
|
|
101
|
+
column_options_method = "#{attr}_options".to_sym
|
|
102
|
+
just_uploaded_method = "#{attr}_just_uploaded?".to_sym
|
|
103
|
+
|
|
104
|
+
# symbols for callback methods
|
|
105
|
+
column_after_save_method = (attr.to_s+"_after_save").to_sym
|
|
106
|
+
column_after_destroy_method = (attr.to_s+"_after_destroy").to_sym
|
|
107
|
+
|
|
108
|
+
tmp_dir_attribute = "@#{attr}_temp".to_sym
|
|
109
|
+
just_uploaded_attribute = "@#{attr}_just_uploaded".to_sym
|
|
110
|
+
|
|
111
|
+
define_method column_read_method do
|
|
112
|
+
relative_path = self.send column_relative_path_method
|
|
113
|
+
return nil unless relative_path
|
|
114
|
+
File.join(store_dir, relative_path)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
define_method column_relative_path_method do
|
|
118
|
+
filename = read_attribute column_attr
|
|
119
|
+
return nil unless filename and !filename.empty?
|
|
120
|
+
tmp_dir = instance_variable_get tmp_dir_attribute
|
|
121
|
+
if tmp_dir
|
|
122
|
+
File.join("tmp",tmp_dir,filename)
|
|
123
|
+
else
|
|
124
|
+
File.join(self.id.to_s,filename)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
define_method column_write_method do |file|
|
|
130
|
+
if file.nil? and read_attribute(column_attr)
|
|
131
|
+
if (tmp_dir = instance_variable_get tmp_dir_attribute)
|
|
132
|
+
# delete temporary image immediately
|
|
133
|
+
FileColumn.remove_file_with_dir(File.join(tmp_base_dir,tmp_dir,
|
|
134
|
+
read_attribute(column_attr)))
|
|
135
|
+
remove_instance_variable tmp_dir_attribute
|
|
136
|
+
end
|
|
137
|
+
write_attribute column_attr, nil
|
|
138
|
+
end
|
|
139
|
+
return nil unless file and file.size > 0
|
|
140
|
+
|
|
141
|
+
tmp_dir = FileColumn.generate_temp_name
|
|
142
|
+
FileUtils.mkdir(File.join(tmp_base_dir, tmp_dir))
|
|
143
|
+
|
|
144
|
+
filename = FileColumn::sanitize_filename(file.original_filename)
|
|
145
|
+
local_file_path = File.join(tmp_base_dir,tmp_dir,filename)
|
|
146
|
+
|
|
147
|
+
# stored uploaded file into local_file_path
|
|
148
|
+
# If it was a Tempfile object, the temporary file will be
|
|
149
|
+
# cleaned up automatically, so we do not have to care for this
|
|
150
|
+
if file.respond_to?(:local_path) and file.local_path and File.exists?(file.local_path)
|
|
151
|
+
FileUtils.copy_file(file.local_path, local_file_path)
|
|
152
|
+
elsif file.respond_to?(:read)
|
|
153
|
+
File.open(local_file_path, "wb") { |f| f.write(file.read) }
|
|
154
|
+
else
|
|
155
|
+
raise ArgumentError.new("Do not know how to handle #{file.inspect}")
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
# if there already was an old temporary file, remove it
|
|
159
|
+
if (old_tmp_dir = instance_variable_get tmp_dir_attribute)
|
|
160
|
+
FileColumn.remove_file_with_dir(File.join(tmp_base_dir,old_tmp_dir,
|
|
161
|
+
read_attribute(column_attr)))
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
instance_variable_set tmp_dir_attribute, tmp_dir
|
|
165
|
+
write_attribute column_attr, filename
|
|
166
|
+
instance_variable_set just_uploaded_attribute, true
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
define_method read_temp_method do
|
|
170
|
+
tmp_dir = instance_variable_get tmp_dir_attribute
|
|
171
|
+
return nil unless tmp_dir
|
|
172
|
+
File.join(tmp_dir, read_attribute(column_attr))
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
define_method write_temp_method do |temp_path|
|
|
176
|
+
return nil if temp_path == ""
|
|
177
|
+
raise ArgumentError.new("invalid format of '#{temp_path}'") unless temp_path =~ %r{^((\d+\.)+\d+)/([^/].+)$}
|
|
178
|
+
tmp_dir, filename = $1, FileColumn.sanitize_filename($3)
|
|
179
|
+
|
|
180
|
+
if instance_variable_get(tmp_dir_attribute).nil?
|
|
181
|
+
instance_variable_set tmp_dir_attribute, tmp_dir
|
|
182
|
+
write_attribute column_attr, filename
|
|
183
|
+
else
|
|
184
|
+
# if tmp_dir_attribute is already set we have already uploaded
|
|
185
|
+
# a new file via column=, which takes precedence over the old
|
|
186
|
+
# temporary image. However, we can clean up the old image right now
|
|
187
|
+
FileColumn.remove_file_with_dir(File.join(tmp_base_dir,tmp_dir,filename))
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
define_method column_after_save_method do
|
|
192
|
+
if instance_variable_get tmp_dir_attribute
|
|
193
|
+
# we have a newly uploaded image, move it to the correct location
|
|
194
|
+
|
|
195
|
+
# create a directory named after the primary key, first
|
|
196
|
+
dir = File.join(store_dir,self.id.to_s)
|
|
197
|
+
FileUtils.mkdir(dir) unless File.exists?(dir)
|
|
198
|
+
|
|
199
|
+
# move the temporary file over
|
|
200
|
+
local_path = self.send(column_read_method)
|
|
201
|
+
FileUtils.mv local_path, dir
|
|
202
|
+
|
|
203
|
+
# remove all old files in the directory
|
|
204
|
+
# we do this _after_ moving the file to avoid a short period of
|
|
205
|
+
# time where none of the two files is available
|
|
206
|
+
filename = File.basename(local_path)
|
|
207
|
+
FileUtils.rm(
|
|
208
|
+
Dir.entries(dir).reject!{ |e| [".",".."].include?(e) or e == filename }.
|
|
209
|
+
collect{ |e| File.join(dir,e) }
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
# cleanup temporary file
|
|
213
|
+
Dir.rmdir(File.dirname(local_path))
|
|
214
|
+
remove_instance_variable tmp_dir_attribute
|
|
215
|
+
elsif read_attribute(column_attr).nil?
|
|
216
|
+
# we do not have a file stored anymore, make sure
|
|
217
|
+
# to remove it from disk if needed
|
|
218
|
+
FileUtils.rm_rf File.join(store_dir, self.id.to_s)
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
after_save column_after_save_method
|
|
222
|
+
|
|
223
|
+
define_method column_after_destroy_method do
|
|
224
|
+
local_path = self.send(column_read_method)
|
|
225
|
+
FileColumn.remove_file_with_dir(local_path) if local_path
|
|
226
|
+
end
|
|
227
|
+
after_destroy column_after_destroy_method
|
|
228
|
+
|
|
229
|
+
define_method just_uploaded_method do
|
|
230
|
+
instance_variable_get just_uploaded_attribute
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
define_method column_options_method do
|
|
234
|
+
options
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
private column_after_save_method, column_after_destroy_method
|
|
238
|
+
end
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
private
|
|
244
|
+
|
|
245
|
+
def self.generate_temp_name
|
|
246
|
+
now = Time.now
|
|
247
|
+
"#{now.to_i}.#{now.usec}.#{Process.pid}"
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
def self.sanitize_filename(filename)
|
|
251
|
+
filename = File.basename(filename.gsub("\\", "/")) # work-around for IE
|
|
252
|
+
filename.gsub(/[^a-zA-Z0-9\.\-\+_]/,"_")
|
|
253
|
+
filename = "_#{filename}" if filename =~ /^\.+$/
|
|
254
|
+
filename
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
def self.remove_file_with_dir(path)
|
|
258
|
+
return unless File.file?(path)
|
|
259
|
+
FileUtils.rm_f path
|
|
260
|
+
dir = File.dirname(path)
|
|
261
|
+
Dir.rmdir(dir) if File.exists?(dir)
|
|
262
|
+
end
|
|
263
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# This module contains helper methods for displaying and uploading files
|
|
2
|
+
# for attributes created by +FileColumn+'s +file_column+ method. It will be
|
|
3
|
+
# automatically included into ActionView::Base, thereby making this module's
|
|
4
|
+
# methods available in all your views.
|
|
5
|
+
module FileColumnHelper
|
|
6
|
+
|
|
7
|
+
# Use this helper to create an upload field for a file_column attribute. This will generate
|
|
8
|
+
# an additional hidden field to keep uploaded files during form-redisplays. For example,
|
|
9
|
+
# when called with
|
|
10
|
+
#
|
|
11
|
+
# <%= file_column_field("entry", "image") %>
|
|
12
|
+
#
|
|
13
|
+
# the following HTML will be generated (assuming the form is redisplayed and something has
|
|
14
|
+
# already been uploaded):
|
|
15
|
+
#
|
|
16
|
+
# <input type="hidden" name="entry[image_temp]" value="..." />
|
|
17
|
+
# <input type="file" name="entry[image]" />
|
|
18
|
+
#
|
|
19
|
+
# You can use the +option+ argument to pass additional options to the file-field tag.
|
|
20
|
+
def file_column_field(object, method, options={})
|
|
21
|
+
result = ActionView::Helpers::InstanceTag.new(object, method.to_s+"_temp", self).to_input_field_tag("hidden", {})
|
|
22
|
+
result << ActionView::Helpers::InstanceTag.new(object, method, self).to_input_field_tag("file", options)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Creates an URL where an uploaded file can be accessed. When called for an Entry object with
|
|
26
|
+
# id 42 like this
|
|
27
|
+
#
|
|
28
|
+
# <%= url_for_file_column("entry", "image")
|
|
29
|
+
#
|
|
30
|
+
# the follwoing URL will be produced, assuming the file "test.png" has been stored in
|
|
31
|
+
# the "image"-column:
|
|
32
|
+
#
|
|
33
|
+
# /entry/image/42/test.png
|
|
34
|
+
#
|
|
35
|
+
# This will produce a valid URL even for temporary uploaded files, e.g. files where the object
|
|
36
|
+
# they are belonging to has not been saved in the database yet.
|
|
37
|
+
def url_for_file_column(object_name, method)
|
|
38
|
+
object = instance_variable_get("@#{object_name.to_s}")
|
|
39
|
+
url = ""
|
|
40
|
+
url << @request.relative_url_root.to_s
|
|
41
|
+
url << object.send("#{method}_options")["base_url"]
|
|
42
|
+
url << "#{method}/"
|
|
43
|
+
url << object.send("#{method}_relative_path")
|
|
44
|
+
end
|
|
45
|
+
end
|
data/lib/localization.rb
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
require 'iconv'
|
|
2
|
+
|
|
3
|
+
module Localization
|
|
4
|
+
|
|
5
|
+
LOCALIZED_STRINGS = {}
|
|
6
|
+
|
|
7
|
+
def l(symbol, *arguments)
|
|
8
|
+
language = CONFIG[:default_language]
|
|
9
|
+
|
|
10
|
+
symbol = symbol.to_sym if symbol.is_a? String
|
|
11
|
+
|
|
12
|
+
# translation of an LString is simply a call to to_s
|
|
13
|
+
return symbol.to_s if symbol.is_a? LString
|
|
14
|
+
|
|
15
|
+
# translation of an array
|
|
16
|
+
if symbol.is_a? Array
|
|
17
|
+
raise ArgumentError.new("Cannot translate an empty array") if symbol.empty?
|
|
18
|
+
raise ArgumentError.new("Symbol is an array, arguments must be empty") unless arguments.empty?
|
|
19
|
+
arguments = symbol
|
|
20
|
+
symbol = arguments.shift
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
begin
|
|
24
|
+
translation = (LOCALIZED_STRINGS[language][symbol] or
|
|
25
|
+
LOCALIZED_STRINGS['en'][symbol] or
|
|
26
|
+
symbol.to_s)
|
|
27
|
+
rescue
|
|
28
|
+
translation = symbol.to_s
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
begin
|
|
32
|
+
return translation % arguments
|
|
33
|
+
rescue => e
|
|
34
|
+
raise ArgumentError.new("Translation value #{translation.inspect} " +
|
|
35
|
+
"with arguments #{arguments.inspect} caused error '#{e.message}'")
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def valid_language?(language)
|
|
40
|
+
LOCALIZED_STRINGS.has_key? language
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def self.load_localized_strings
|
|
44
|
+
# Load language files
|
|
45
|
+
Dir[RAILS_ROOT + '/lang/*.yaml'].each do |filename|
|
|
46
|
+
filename =~ /(([a-z]+_?)+)\.yaml$/
|
|
47
|
+
hash = YAML::load(File.read(filename))
|
|
48
|
+
file_charset = hash['file_charset'] || 'ascii'
|
|
49
|
+
lang = $1
|
|
50
|
+
|
|
51
|
+
# convert string keys to symbols
|
|
52
|
+
symbol_hash = Hash.new
|
|
53
|
+
Iconv.open(CONFIG[:web_charset], file_charset) do |i|
|
|
54
|
+
hash.each do |key, value|
|
|
55
|
+
symbol_hash[key.to_sym] = i.iconv(value)
|
|
56
|
+
if key =~ /^active_record_errors_(.*)/
|
|
57
|
+
ActiveRecord::Errors.default_error_messages[$1.to_sym] =
|
|
58
|
+
symbol_hash[key.to_sym]
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
LOCALIZED_STRINGS[lang] = symbol_hash
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
class LString
|
|
68
|
+
|
|
69
|
+
include Localization
|
|
70
|
+
|
|
71
|
+
def initialize(symbol, arguments)
|
|
72
|
+
@symbol, @arguments = symbol, arguments
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def to_s
|
|
76
|
+
l(@symbol, @arguments)
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# redefinition of ActionMail::Base#render_message, that adds locale suffix to
|
|
81
|
+
# the template name
|
|
82
|
+
ActionMailer::Base.module_eval <<-EOL
|
|
83
|
+
private
|
|
84
|
+
def render_message(method_name, body)
|
|
85
|
+
initialize_template_class(body).render_file(method_name + "_#{CONFIG[:default_language]}")
|
|
86
|
+
end
|
|
87
|
+
EOL
|
|
88
|
+
end
|
data/lib/localizer.rb
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
require 'iconv'
|
|
2
|
+
|
|
3
|
+
module Localizer
|
|
4
|
+
|
|
5
|
+
LOCALIZED_STRINGS = {}
|
|
6
|
+
|
|
7
|
+
def l(symbol, *arguments)
|
|
8
|
+
language = CONFIG[:default_language]
|
|
9
|
+
|
|
10
|
+
symbol = symbol.to_sym if symbol.is_a? String
|
|
11
|
+
|
|
12
|
+
# translation of an LString is simply a call to to_s
|
|
13
|
+
return symbol.to_s if symbol.is_a? LString
|
|
14
|
+
|
|
15
|
+
# translation of an array
|
|
16
|
+
if symbol.is_a? Array
|
|
17
|
+
raise ArgumentError.new("Cannot translate an empty array") if symbol.empty?
|
|
18
|
+
raise ArgumentError.new("Symbol is an array, arguments must be empty") unless arguments.empty?
|
|
19
|
+
arguments = symbol
|
|
20
|
+
symbol = arguments.shift
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
begin
|
|
24
|
+
translation = (LOCALIZED_STRINGS[language][symbol] or
|
|
25
|
+
LOCALIZED_STRINGS['en'][symbol] or
|
|
26
|
+
symbol.to_s)
|
|
27
|
+
rescue
|
|
28
|
+
translation = symbol.to_s
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
begin
|
|
32
|
+
return translation % arguments
|
|
33
|
+
rescue => e
|
|
34
|
+
raise ArgumentError.new("Translation value #{translation.inspect} " +
|
|
35
|
+
"with arguments #{arguments.inspect} caused error '#{e.message}'")
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def valid_language?(language)
|
|
40
|
+
LOCALIZED_STRINGS.has_key? language
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def self.load_localized_strings
|
|
44
|
+
# Load language files
|
|
45
|
+
Dir[RAILS_ROOT + '/lang/*.yaml'].each do |filename|
|
|
46
|
+
filename =~ /(([a-z]+_?)+)\.yaml$/
|
|
47
|
+
hash = YAML::load(File.read(filename))
|
|
48
|
+
file_charset = hash['file_charset'] || 'ascii'
|
|
49
|
+
lang = $1
|
|
50
|
+
|
|
51
|
+
# convert string keys to symbols
|
|
52
|
+
symbol_hash = Hash.new
|
|
53
|
+
Iconv.open(CONFIG[:web_charset], file_charset) do |i|
|
|
54
|
+
hash.each do |key, value|
|
|
55
|
+
symbol_hash[key.to_sym] = i.iconv(value)
|
|
56
|
+
if key =~ /^active_record_errors_(.*)/
|
|
57
|
+
ActiveRecord::Errors.default_error_messages[$1.to_sym] =
|
|
58
|
+
symbol_hash[key.to_sym]
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
LOCALIZED_STRINGS[lang] = symbol_hash
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
class LString
|
|
68
|
+
|
|
69
|
+
include Localizer
|
|
70
|
+
|
|
71
|
+
def initialize(symbol, arguments)
|
|
72
|
+
@symbol, @arguments = symbol, arguments
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def to_s
|
|
76
|
+
l(@symbol, @arguments)
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# redefinition of ActionMail::Base#render_message, that adds locale suffix to
|
|
81
|
+
# the template name
|
|
82
|
+
ActionMailer::Base.module_eval <<-EOL
|
|
83
|
+
private
|
|
84
|
+
def render_message(method_name, body)
|
|
85
|
+
initialize_template_class(body).render_file(method_name + "_#{CONFIG[:default_language]}")
|
|
86
|
+
end
|
|
87
|
+
EOL
|
|
88
|
+
end
|
data/lib/login_system.rb
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
require_dependency "user"
|
|
2
|
+
|
|
3
|
+
module LoginSystem
|
|
4
|
+
|
|
5
|
+
protected
|
|
6
|
+
|
|
7
|
+
# overwrite this if you want to restrict access to only a few actions
|
|
8
|
+
# or if you want to check if the user has the correct rights
|
|
9
|
+
# example:
|
|
10
|
+
#
|
|
11
|
+
# # only allow nonbobs
|
|
12
|
+
# def authorize?(user)
|
|
13
|
+
# user.login != "bob"
|
|
14
|
+
# end
|
|
15
|
+
def authorize?(user)
|
|
16
|
+
true
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# overwrite this method if you only want to protect certain actions of the controller
|
|
20
|
+
# example:
|
|
21
|
+
#
|
|
22
|
+
# # don't protect the login and the about method
|
|
23
|
+
# def protect?(action)
|
|
24
|
+
# if ['action', 'about'].include?(action)
|
|
25
|
+
# return false
|
|
26
|
+
# else
|
|
27
|
+
# return true
|
|
28
|
+
# end
|
|
29
|
+
# end
|
|
30
|
+
def protect?(action)
|
|
31
|
+
true
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# login_required filter. add
|
|
35
|
+
#
|
|
36
|
+
# before_filter :login_required
|
|
37
|
+
#
|
|
38
|
+
# if the controller should be under any rights management.
|
|
39
|
+
# for finer access control you can overwrite
|
|
40
|
+
#
|
|
41
|
+
# def authorize?(user)
|
|
42
|
+
#
|
|
43
|
+
def login_required
|
|
44
|
+
|
|
45
|
+
if not protect?(action_name)
|
|
46
|
+
return true
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
if @session[:user] and authorize?(@session[:user])
|
|
50
|
+
return true
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# store current location so that we can
|
|
54
|
+
# come back after the user logged in
|
|
55
|
+
store_location
|
|
56
|
+
|
|
57
|
+
# call overwriteable reaction to unauthorized access
|
|
58
|
+
access_denied
|
|
59
|
+
return false
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# overwrite if you want to have special behavior in case the user is not authorized
|
|
63
|
+
# to access the current operation.
|
|
64
|
+
# the default action is to redirect to the login screen
|
|
65
|
+
# example use :
|
|
66
|
+
# a popup window might just close itself for instance
|
|
67
|
+
def access_denied
|
|
68
|
+
redirect_to :controller=>"/account", :action =>"login"
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# store current uri in the session.
|
|
72
|
+
# we can return to this location by calling return_location
|
|
73
|
+
def store_location
|
|
74
|
+
@session[:return_to] = @request.request_uri
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# move to the last store_location call or to the passed default one
|
|
78
|
+
def redirect_back_or_default(default)
|
|
79
|
+
if @session[:return_to].nil?
|
|
80
|
+
redirect_to default
|
|
81
|
+
else
|
|
82
|
+
redirect_to_url @session[:return_to]
|
|
83
|
+
@session[:return_to] = nil
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# require this file from your "config/environment.rb" (after rails has been loaded)
|
|
2
|
+
# to integrate the file_column extension into rails.
|
|
3
|
+
|
|
4
|
+
require 'file_column'
|
|
5
|
+
require 'file_column_helper'
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
module ActiveRecord # :nodoc:
|
|
9
|
+
class Base # :nodoc:
|
|
10
|
+
# make file_column method available in all active record decendants
|
|
11
|
+
include FileColumn
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
module ActionView # :nodoc:
|
|
16
|
+
class Base # :nodoc:
|
|
17
|
+
include FileColumnHelper
|
|
18
|
+
end
|
|
19
|
+
end
|