typo 3.99.3 → 3.99.4
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/README +1 -39
- data/app/controllers/admin/feedback_controller.rb +71 -0
- data/app/controllers/articles_controller.rb +11 -0
- data/app/helpers/admin/feedback_helper.rb +9 -0
- data/app/helpers/application_helper.rb +5 -1
- data/app/models/article.rb +21 -1
- data/app/models/blog.rb +25 -1
- data/app/models/comment.rb +12 -2
- data/app/models/content.rb +63 -4
- data/app/models/ping.rb +3 -3
- data/app/models/text_filter.rb +1 -1
- data/app/models/trackback.rb +12 -1
- data/app/views/admin/content/_form.rhtml +2 -2
- data/app/views/admin/feedback/_item.rhtml +15 -0
- data/app/views/admin/feedback/list.rhtml +46 -0
- data/app/views/admin/general/index.rhtml +26 -0
- data/app/views/articles/_comment.rhtml +3 -0
- data/app/views/articles/read.rhtml +2 -2
- data/app/views/layouts/administration.rhtml +1 -0
- data/bin/typo +3 -23
- data/components/plugins/sidebars/archives_controller.rb +1 -1
- data/components/plugins/sidebars/xml_controller.rb +1 -1
- data/components/plugins/textfilters/flickr_controller.rb +1 -1
- data/components/plugins/textfilters/sparkline_controller.rb +3 -2
- data/components/plugins/textfilters/textile_controller.rb +6 -0
- data/config/mongrel.conf +2 -0
- data/db/converters/wordpress2.rb +291 -0
- data/db/migrate/022_superclass_trackbacks.rb +1 -0
- data/db/migrate/023_superclass_pages.rb +4 -3
- data/db/schema.rb +4 -4
- data/doc/Installer.txt +81 -6
- data/doc/typo-4.0-release-notes.txt +135 -0
- data/installer/rails-installer.rb +22 -3
- data/installer/rails-installer/commands.rb +27 -26
- data/installer/rails-installer/web-servers.rb +2 -0
- data/lib/sidebars/plugin.rb +10 -8
- data/lib/tasks/release.rake +1 -1
- data/lib/typo_version.rb +1 -1
- data/public/javascripts/dragdrop.js +252 -63
- data/public/javascripts/effects.js +15 -10
- data/public/javascripts/prototype.js +59 -38
- data/public/javascripts/typo.js +10 -0
- data/public/stylesheets/administration.css +111 -66
- data/test/functional/admin/feedback_controller_test.rb +24 -0
- data/test/mocks/test/http_mock.rb +2 -1
- data/test/unit/article_test.rb +6 -0
- data/test/unit/comment_test.rb +12 -9
- data/test/unit/ping_test.rb +1 -1
- data/test/unit/trackback_test.rb +3 -5
- data/themes/azure/stylesheets/azure.css +7 -0
- data/themes/scribbish/views/articles/_article.rhtml +1 -1
- data/themes/scribbish/views/articles/_comment_form.rhtml +1 -1
- data/vendor/akismet/Akismet.rb +36 -17
- data/vendor/plugins/expiring_action_cache/lib/actionparamcache.rb +3 -1
- metadata +11 -42
- data/installer/rails-installer/web-server.rb +0 -108
- data/tmp/cache/META/DATA/ACTION_PARAM/10.1.0.181/articles/index/.cache +0 -537
- data/tmp/cache/META/DATA/ACTION_PARAM/localhost/articles/index/.cache +0 -537
- data/tmp/cache/META/DATA/ACTION_PARAM/localhost/xml/feed/format=atom&type=feed.cache +0 -671
- data/tmp/cache/META/DATA/ACTION_PARAM/localhost/xml/feed/format=rss20&type=feed.cache +0 -401
- data/tmp/cache/META/META/ACTION_PARAM/10.1.0.181/articles/index/.cache +0 -2
- data/tmp/cache/META/META/ACTION_PARAM/localhost/articles/index/.cache +0 -2
- data/tmp/cache/META/META/ACTION_PARAM/localhost/xml/feed/format=atom&type=feed.cache +0 -2
- data/tmp/cache/META/META/ACTION_PARAM/localhost/xml/feed/format=rss20&type=feed.cache +0 -2
data/README
CHANGED
|
@@ -24,45 +24,7 @@ Currently you need all of those things to get typo to run:
|
|
|
24
24
|
Installation
|
|
25
25
|
============
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
Decide which database to use. We support Sqlite, MySQL, and Postgres,
|
|
30
|
-
but Sqlite doesn't have full support for database migrations in Rails
|
|
31
|
-
0.13.1.
|
|
32
|
-
|
|
33
|
-
* Create a database for typo. You can find schemas in the db/ folder.
|
|
34
|
-
* Create config/database.yml using database.yml.example to reflect your
|
|
35
|
-
newly created database configuration
|
|
36
|
-
* Run script/server -e production and see if it works
|
|
37
|
-
* Point your browser to http://your.domain.com:3000/ and follow the
|
|
38
|
-
install process
|
|
39
|
-
|
|
40
|
-
Typo, like all Rails apps, doesn't work well as a CGI. Seriously consider
|
|
41
|
-
using FastCGI instead. To deploy on FastCGI you will need to follow the setup
|
|
42
|
-
instructions on the typo page at http://www.typosphere.org/trac/wiki/FastCgi
|
|
43
|
-
|
|
44
|
-
By default, Typo runs in *development* mode. This is very useful for
|
|
45
|
-
developers, but it can cause horrible performance for users who aren't
|
|
46
|
-
changing Typo's code. Production mode can easily be 20x as fast as development
|
|
47
|
-
mode. To change the default, edit the second line of config/environment.rb and
|
|
48
|
-
change 'development' to 'production', or follow the directions on the FastCGI
|
|
49
|
-
configuration page on the Typo wiki.
|
|
50
|
-
|
|
51
|
-
Permissions
|
|
52
|
-
===========
|
|
53
|
-
|
|
54
|
-
Typo needs write access to several directories in order to function
|
|
55
|
-
correctly. These need to be writable by the user that runs the Typo
|
|
56
|
-
process--in a hosted environment this may be your user; on dedicated
|
|
57
|
-
systems it may be something like 'httpd' or 'www-data'.
|
|
58
|
-
|
|
59
|
-
The specific directories in question are 'log/' (and everything underneath
|
|
60
|
-
it), 'cache/', and 'public/'. Strictly speaking, Rails will continue to work
|
|
61
|
-
if public isn't writable, but Typo's page caching code will work properly and
|
|
62
|
-
this will cause Typo to be slower and use much more CPU time. For the security
|
|
63
|
-
conscious, Rails really only needs the ability to change a half-dozen files
|
|
64
|
-
and subdirectories under public/, ask on the Typo mailing list for more
|
|
65
|
-
details.
|
|
27
|
+
See doc/Installer.text and doc/typo-4.0-release-notes.txt.
|
|
66
28
|
|
|
67
29
|
Usage
|
|
68
30
|
======
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
class Admin::FeedbackController < Admin::BaseController
|
|
2
|
+
def index
|
|
3
|
+
conditions = ["(contents.type = 'Comment' or contents.type = 'Trackback')"]
|
|
4
|
+
|
|
5
|
+
if params[:search]
|
|
6
|
+
search_sql = "%#{params[:search]}%"
|
|
7
|
+
conditions.first << ' and (url like ? or author like ? or title like ? or ip like ? or email like ?)'
|
|
8
|
+
5.times { conditions.push search_sql }
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
if params[:published] == 'f'
|
|
12
|
+
conditions.first << ' and (published = ?)'
|
|
13
|
+
conditions.push false
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
@pages, @feedback = paginate(:contents,
|
|
17
|
+
:order => 'contents.created_at desc',
|
|
18
|
+
:conditions => conditions,
|
|
19
|
+
:per_page => 40)
|
|
20
|
+
|
|
21
|
+
render_action 'list'
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def delete
|
|
25
|
+
if request.post?
|
|
26
|
+
feedback = Content.find(params[:id])
|
|
27
|
+
if feedback.kind_of? Comment or feedback.kind_of? Trackback
|
|
28
|
+
feedback.destroy
|
|
29
|
+
flash[:notice] = "Deleted"
|
|
30
|
+
else
|
|
31
|
+
flash[:notice] = "Not found"
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
redirect_to :action => 'index', :page => params[:page], :search => params[:search]
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def bulkops
|
|
38
|
+
STDERR.puts "Bulkops: #{params.inspect}"
|
|
39
|
+
|
|
40
|
+
ids = (params[:feedback_check]||{}).keys.map(&:to_i)
|
|
41
|
+
|
|
42
|
+
case params[:commit]
|
|
43
|
+
when 'Delete Checked Items'
|
|
44
|
+
count = 0
|
|
45
|
+
ids.each do |id|
|
|
46
|
+
count += Content.delete(id)
|
|
47
|
+
end
|
|
48
|
+
flash[:notice] = "Deleted #{count} item(s)"
|
|
49
|
+
when 'Publish Checked Items'
|
|
50
|
+
ids.each do |id|
|
|
51
|
+
feedback = Content.find(id)
|
|
52
|
+
feedback.attributes[:published] = true
|
|
53
|
+
feedback.set_spam(false)
|
|
54
|
+
feedback.save
|
|
55
|
+
end
|
|
56
|
+
flash[:notice]= "Published #{ids.size} item(s)"
|
|
57
|
+
when 'Unpublish Checked Items'
|
|
58
|
+
ids.each do |id|
|
|
59
|
+
feedback = Content.find(id)
|
|
60
|
+
feedback.withdraw!
|
|
61
|
+
feedback.set_spam(true)
|
|
62
|
+
feedback.save
|
|
63
|
+
end
|
|
64
|
+
flash[:notice]= "Unpublished #{ids.size} item(s)"
|
|
65
|
+
else
|
|
66
|
+
flash[:notice] = "Not implemented"
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
redirect_to :action => 'index', :page => params[:page], :search => params[:search]
|
|
70
|
+
end
|
|
71
|
+
end
|
|
@@ -99,6 +99,17 @@ class ArticlesController < ContentController
|
|
|
99
99
|
@article = this_blog.published_articles.find(params[:id])
|
|
100
100
|
@comment = @article.comments.build(params[:comment])
|
|
101
101
|
@comment.user = session[:user]
|
|
102
|
+
|
|
103
|
+
spam_options = {
|
|
104
|
+
:user_agent => request.env['HTTP_USER_AGENT'],
|
|
105
|
+
:referrer => request.env['HTTP_REFERER'],
|
|
106
|
+
:permalink => this_blog.article_url(@article, false)}
|
|
107
|
+
|
|
108
|
+
if @comment.is_spam? spam_options
|
|
109
|
+
STDERR.puts "Moderating comment as spam!"
|
|
110
|
+
@comment.withdraw
|
|
111
|
+
end
|
|
112
|
+
|
|
102
113
|
@comment.save!
|
|
103
114
|
add_to_cookies(:author, @comment.author)
|
|
104
115
|
add_to_cookies(:url, @comment.url)
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
module Admin::FeedbackHelper
|
|
2
|
+
def link_to_article_edit(article)
|
|
3
|
+
link_to truncate(article.title, 60), :controller => 'content', :action => 'edit', :id => article.id
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
def task_showmod(title)
|
|
7
|
+
content_tag :li, link_to(title, :published => 'f', :search => params[:search])
|
|
8
|
+
end
|
|
9
|
+
end
|
|
@@ -93,6 +93,10 @@ module ApplicationHelper
|
|
|
93
93
|
end
|
|
94
94
|
|
|
95
95
|
def markup_help_popup(markup, text)
|
|
96
|
-
|
|
96
|
+
if markup and markup.commenthelp.size > 1
|
|
97
|
+
"<a href=\"#{url_for :controller => '/articles', :action => 'markup_help', :id => markup.id}\" onClick=\"return popup(this, 'Typo Markup Help')\">#{text}</a>"
|
|
98
|
+
else
|
|
99
|
+
''
|
|
100
|
+
end
|
|
97
101
|
end
|
|
98
102
|
end
|
data/app/models/article.rb
CHANGED
|
@@ -120,7 +120,7 @@ class Article < Content
|
|
|
120
120
|
def keywords_to_tags
|
|
121
121
|
Article.transaction do
|
|
122
122
|
tags.clear
|
|
123
|
-
keywords.to_s.scan(/((['"]).*?\2
|
|
123
|
+
keywords.to_s.scan(/((['"]).*?\2|[\.\w]+)/).collect do |x|
|
|
124
124
|
x.first.tr("\"'", '')
|
|
125
125
|
end.uniq.each do |tagword|
|
|
126
126
|
tags << Tag.get(tagword)
|
|
@@ -146,15 +146,34 @@ class Article < Content
|
|
|
146
146
|
end
|
|
147
147
|
end
|
|
148
148
|
|
|
149
|
+
def comments_closed?
|
|
150
|
+
if self.allow_comments?
|
|
151
|
+
if !self.blog.sp_article_auto_close.zero? and self.created_at.to_i < self.blog.sp_article_auto_close.days.ago.to_i
|
|
152
|
+
return true
|
|
153
|
+
else
|
|
154
|
+
return false
|
|
155
|
+
end
|
|
156
|
+
else
|
|
157
|
+
return true
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
|
|
149
161
|
protected
|
|
150
162
|
|
|
151
163
|
before_create :set_defaults, :create_guid, :add_notifications
|
|
164
|
+
before_save :set_published_at
|
|
152
165
|
after_save :keywords_to_tags
|
|
153
166
|
|
|
154
167
|
def correct_counts
|
|
155
168
|
self.comments_count = self.comments_count
|
|
156
169
|
self.trackbacks_count = self.trackbacks_count
|
|
157
170
|
end
|
|
171
|
+
|
|
172
|
+
def set_published_at
|
|
173
|
+
if self.published and self[:published_at].nil?
|
|
174
|
+
self[:published_at] = self.created_at || Time.now
|
|
175
|
+
end
|
|
176
|
+
end
|
|
158
177
|
|
|
159
178
|
def set_defaults
|
|
160
179
|
if self.attributes.include?("permalink") and self.permalink.blank?
|
|
@@ -168,6 +187,7 @@ class Article < Content
|
|
|
168
187
|
if blog && self.allow_pings.nil?
|
|
169
188
|
self.allow_pings = blog.default_allow_pings
|
|
170
189
|
end
|
|
190
|
+
|
|
171
191
|
true
|
|
172
192
|
end
|
|
173
193
|
|
data/app/models/blog.rb
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
# BlogRequest is a fake Request object, created so blog.url_for will work.
|
|
2
|
+
# This isn't enabled yet, but it will be soon...
|
|
3
|
+
class BlogRequest
|
|
4
|
+
include Reloadable
|
|
5
|
+
|
|
6
|
+
attr_accessor :protocol, :host_with_port, :path, :symbolized_path_parameters, :relative_url_root
|
|
7
|
+
|
|
8
|
+
def initialize(root)
|
|
9
|
+
@protocol = @host_with_port = @path = ''
|
|
10
|
+
@symbolized_path_parameters = {}
|
|
11
|
+
@relative_url_root = root.gsub(%r{/^},'')
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
1
15
|
class Blog < ActiveRecord::Base
|
|
2
16
|
include ConfigManager
|
|
3
17
|
|
|
@@ -31,6 +45,7 @@ class Blog < ActiveRecord::Base
|
|
|
31
45
|
setting :sp_article_auto_close, :integer, 0
|
|
32
46
|
setting :sp_allow_non_ajax_comments, :boolean, true
|
|
33
47
|
setting :sp_url_limit, :integer, 0
|
|
48
|
+
setting :sp_akismet_key, :string, ''
|
|
34
49
|
|
|
35
50
|
# Podcasting
|
|
36
51
|
setting :itunes_explicit, :boolean, false
|
|
@@ -53,6 +68,7 @@ class Blog < ActiveRecord::Base
|
|
|
53
68
|
setting :show_extended_on_rss, :boolean, true
|
|
54
69
|
setting :theme, :string, 'azure'
|
|
55
70
|
setting :use_gravatar, :boolean, false
|
|
71
|
+
setting :global_pings_disable, :boolean, false
|
|
56
72
|
setting :ping_urls, :string, "http://rpc.technorati.com/rpc/ping\nhttp://ping.blo.gs/\nhttp://rpc.weblogs.com/RPC2"
|
|
57
73
|
setting :send_outbound_pings, :boolean, true
|
|
58
74
|
setting :email_from, :string, 'typo@example.com'
|
|
@@ -69,7 +85,14 @@ class Blog < ActiveRecord::Base
|
|
|
69
85
|
settings[:blog_id] = self.id
|
|
70
86
|
article_id = settings[:id]
|
|
71
87
|
settings.delete(:id)
|
|
72
|
-
published_articles.find(article_id).trackbacks.create!(settings)
|
|
88
|
+
trackback = published_articles.find(article_id).trackbacks.create!(settings)
|
|
89
|
+
|
|
90
|
+
if trackback.is_spam?
|
|
91
|
+
STDERR.puts "Moderating trackback as spam!"
|
|
92
|
+
trackback.withdraw!
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
trackback
|
|
73
96
|
end
|
|
74
97
|
|
|
75
98
|
|
|
@@ -156,6 +179,7 @@ class Blog < ActiveRecord::Base
|
|
|
156
179
|
private
|
|
157
180
|
|
|
158
181
|
def request
|
|
182
|
+
#BlogRequest.new(self.canonical_server_url)
|
|
159
183
|
controller.request rescue ActionController::TestRequest.new
|
|
160
184
|
end
|
|
161
185
|
end
|
data/app/models/comment.rb
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
require_dependency 'spam_protection'
|
|
2
2
|
require 'sanitize'
|
|
3
|
+
require 'timeout'
|
|
3
4
|
|
|
4
5
|
class Comment < Content
|
|
5
6
|
include TypoGuid
|
|
@@ -10,10 +11,10 @@ class Comment < Content
|
|
|
10
11
|
belongs_to :user
|
|
11
12
|
|
|
12
13
|
validates_presence_of :author, :body
|
|
13
|
-
validates_against_spamdb :body, :url, :ip
|
|
14
14
|
validates_age_of :article_id
|
|
15
15
|
validate_on_create :check_article_is_open_to_comments
|
|
16
16
|
|
|
17
|
+
|
|
17
18
|
def self.default_order
|
|
18
19
|
'created_at ASC'
|
|
19
20
|
end
|
|
@@ -50,7 +51,7 @@ class Comment < Content
|
|
|
50
51
|
end
|
|
51
52
|
|
|
52
53
|
def body_html_postprocess(value, controller)
|
|
53
|
-
sanitize(controller.send(:auto_link, value),'a href, b, br, i, p, em, strong, pre, code')
|
|
54
|
+
sanitize(controller.send(:auto_link, value),'a href, b, br, i, p, em, strong, pre, code, ol, ul, li')
|
|
54
55
|
end
|
|
55
56
|
|
|
56
57
|
def default_text_filter_config_key
|
|
@@ -72,4 +73,13 @@ class Comment < Content
|
|
|
72
73
|
self.author = author.nofollowify
|
|
73
74
|
self.body_html = body_html.to_s.nofollowify
|
|
74
75
|
end
|
|
76
|
+
|
|
77
|
+
def akismet_options
|
|
78
|
+
{:user_ip => ip, :comment_type => 'comment', :comment_author => author, :comment_author_email => email,
|
|
79
|
+
:comment_author_url => url, :comment_content => body}
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def spam_fields
|
|
83
|
+
[:body, :url, :ip]
|
|
84
|
+
end
|
|
75
85
|
end
|
data/app/models/content.rb
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
require 'observer'
|
|
2
2
|
require 'set'
|
|
3
|
+
require 'Akismet'
|
|
4
|
+
|
|
3
5
|
class Content < ActiveRecord::Base
|
|
4
6
|
include Observable
|
|
5
7
|
|
|
@@ -20,11 +22,11 @@ class Content < ActiveRecord::Base
|
|
|
20
22
|
|
|
21
23
|
@@content_fields = Hash.new
|
|
22
24
|
@@html_map = Hash.new
|
|
23
|
-
|
|
25
|
+
|
|
24
26
|
def initialize(*args)
|
|
25
27
|
super(*args)
|
|
26
|
-
|
|
27
|
-
#
|
|
28
|
+
|
|
29
|
+
#
|
|
28
30
|
if self.blog_id == nil or self.blog_id == 0
|
|
29
31
|
self.blog_id = Blog.default
|
|
30
32
|
end
|
|
@@ -170,7 +172,7 @@ class Content < ActiveRecord::Base
|
|
|
170
172
|
end
|
|
171
173
|
|
|
172
174
|
def text_filter=(filter)
|
|
173
|
-
self[:
|
|
175
|
+
self[:text_filter_id] = filter.to_text_filter.id
|
|
174
176
|
end
|
|
175
177
|
|
|
176
178
|
def blog
|
|
@@ -182,6 +184,16 @@ class Content < ActiveRecord::Base
|
|
|
182
184
|
self.save!
|
|
183
185
|
end
|
|
184
186
|
|
|
187
|
+
def withdraw
|
|
188
|
+
self.published = false
|
|
189
|
+
self.published_at = nil
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
def withdraw!
|
|
193
|
+
self.withdraw
|
|
194
|
+
self.save!
|
|
195
|
+
end
|
|
196
|
+
|
|
185
197
|
def published=(a_boolean)
|
|
186
198
|
self[:published] = a_boolean
|
|
187
199
|
state.change_published_state(self, a_boolean)
|
|
@@ -219,6 +231,53 @@ class Content < ActiveRecord::Base
|
|
|
219
231
|
def send_notifications(controller = nil)
|
|
220
232
|
state.send_notifications(self, controller || blog.controller)
|
|
221
233
|
end
|
|
234
|
+
|
|
235
|
+
# is_spam? checks to see if this is spam. This really belongs in a 'feedback' class
|
|
236
|
+
# that is the parent of Comment and Trackback, but we aren't going to build one right
|
|
237
|
+
# now.
|
|
238
|
+
#
|
|
239
|
+
# options are passed on to Akismet. Recommended options (when available) are:
|
|
240
|
+
#
|
|
241
|
+
# :permalink => the article's URL
|
|
242
|
+
# :user_agent => the poster's UserAgent string
|
|
243
|
+
# :referer => the poster's Referer string
|
|
244
|
+
#
|
|
245
|
+
def is_spam?(options={})
|
|
246
|
+
return false unless blog.sp_global
|
|
247
|
+
|
|
248
|
+
sp = SpamProtection.new(blog)
|
|
249
|
+
spam = false
|
|
250
|
+
|
|
251
|
+
# Check fields against the blacklist.
|
|
252
|
+
spam_fields.each do |field|
|
|
253
|
+
spam ||= sp.is_spam? self[field]
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
# Attempt to use Akismet. Timeout after 5 seconds if we can't contact them.
|
|
257
|
+
unless blog.sp_akismet_key.blank?
|
|
258
|
+
Timeout.timeout(5) do
|
|
259
|
+
akismet = Akismet.new(blog.sp_akismet_key,blog.canonical_server_url)
|
|
260
|
+
spam ||= akismet.commentCheck(akismet_options.merge(options))
|
|
261
|
+
end
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
spam == true
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
def set_spam(is_spam, options ={})
|
|
268
|
+
unless blog.sp_akismet_key.blank?
|
|
269
|
+
Timeout.timeout(5) do
|
|
270
|
+
akismet = Akismet.new(blog.sp_akismet_key,blog.canonical_server_url)
|
|
271
|
+
if is_spam
|
|
272
|
+
STDERR.puts "** submitting spam for #{id}"
|
|
273
|
+
akismet.submitSpam(akismet_options.merge(options))
|
|
274
|
+
else
|
|
275
|
+
STDERR.puts "** submitting ham for #{id}"
|
|
276
|
+
akismet.submitHam(akismet_options.merge(options))
|
|
277
|
+
end
|
|
278
|
+
end
|
|
279
|
+
end
|
|
280
|
+
end
|
|
222
281
|
end
|
|
223
282
|
|
|
224
283
|
class Object; def to_text_filter; TextFilter.find_by_name(self.to_s); end; end
|
data/app/models/ping.rb
CHANGED
|
@@ -97,10 +97,10 @@ class Ping < ActiveRecord::Base
|
|
|
97
97
|
t = Thread.start do
|
|
98
98
|
trackback_uri = URI.parse(trackback_url)
|
|
99
99
|
|
|
100
|
-
post = "title=#{
|
|
101
|
-
post << "&excerpt=#{
|
|
100
|
+
post = "title=#{CGI.escape(article.title)}"
|
|
101
|
+
post << "&excerpt=#{CGI.escape(article.body_html.strip_html[0..254])}"
|
|
102
102
|
post << "&url=#{origin_url}"
|
|
103
|
-
post << "&blog_name=#{
|
|
103
|
+
post << "&blog_name=#{CGI.escape(article.blog.blog_name)}"
|
|
104
104
|
|
|
105
105
|
Net::HTTP.start(trackback_uri.host, trackback_uri.port) do |http|
|
|
106
106
|
path = trackback_uri.path
|
data/app/models/text_filter.rb
CHANGED
data/app/models/trackback.rb
CHANGED
|
@@ -7,7 +7,6 @@ class Trackback < Content
|
|
|
7
7
|
content_fields :excerpt
|
|
8
8
|
|
|
9
9
|
validates_age_of :article_id
|
|
10
|
-
validates_against_spamdb :title, :excerpt, :ip, :url
|
|
11
10
|
validates_presence_of :title, :excerpt, :url
|
|
12
11
|
validate_on_create :article_is_pingable
|
|
13
12
|
|
|
@@ -43,9 +42,21 @@ class Trackback < Content
|
|
|
43
42
|
|
|
44
43
|
def article_is_pingable
|
|
45
44
|
return if article.nil?
|
|
45
|
+
if blog.global_pings_disable
|
|
46
|
+
errors.add(:article, "Pings are disabled")
|
|
47
|
+
end
|
|
46
48
|
unless article.allow_pings?
|
|
47
49
|
errors.add(:article, "Article is not pingable")
|
|
48
50
|
end
|
|
49
51
|
end
|
|
52
|
+
|
|
53
|
+
def akismet_options
|
|
54
|
+
{:user_ip => ip, :comment_type => 'trackback', :comment_author => blog_name, :comment_author_email => nil,
|
|
55
|
+
:comment_author_url => url, :comment_content => excerpt}
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def spam_fields
|
|
59
|
+
[:title, :excerpt, :ip, :url]
|
|
60
|
+
end
|
|
50
61
|
end
|
|
51
62
|
|