- AntiSPAM: included form-spam-protection rails plugin (Hivelogic Enkoder)

- update: updated scripts and javascripts to rails 1.2.1
This commit is contained in:
Matthias Tarasiewicz 2007-02-13 13:24:03 +00:00
parent ad22579668
commit 113223f364
15 changed files with 2722 additions and 1339 deletions

View file

@ -4,6 +4,8 @@
- updated and included spam_patterns.txt - updated and included spam_patterns.txt
- included dnsbl_check - DNS Blackhole Lists check - included dnsbl_check - DNS Blackhole Lists check
[thanks to joost from http://www.spacebabies.nl ] [thanks to joost from http://www.spacebabies.nl ]
- included the form-spam-protection rails plugin
http://form-spam-protection.googlecode.com/svn/form_spam_protection/
- BUGFIXES: - BUGFIXES:
- fix PDF output not to contain garbage chars [Jesse Newland] - fix PDF output not to contain garbage chars [Jesse Newland]
@ -16,7 +18,7 @@
- lots of small bugfixes and changes - lots of small bugfixes and changes
- UPDATES: - UPDATES:
- Rails 1.2 tested and packaged with instiki - Rails 1.2.1 tested and packaged with instiki
- updated RubyZip to 0.9.1 - updated RubyZip to 0.9.1
- updated RedCloth to 3.0.4 - updated RedCloth to 3.0.4
- updated packaged sqlite3-ruby to 1.2.0 - updated packaged sqlite3-ruby to 1.2.0

View file

@ -2,6 +2,7 @@
# Likewise will all the methods added be available for all controllers. # Likewise will all the methods added be available for all controllers.
class ApplicationController < ActionController::Base class ApplicationController < ActionController::Base
# require 'dnsbl_check' # require 'dnsbl_check'
protect_forms_from_spam
before_filter :dnsbl_check, :connect_to_model, :check_authorization, :setup_url_generator, :set_content_type_header, :set_robots_metatag before_filter :dnsbl_check, :connect_to_model, :check_authorization, :setup_url_generator, :set_content_type_header, :set_robots_metatag
after_filter :remember_location, :teardown_url_generator after_filter :remember_location, :teardown_url_generator

View file

@ -1,17 +1,45 @@
# Don't change this file. Configuration is done in config/environment.rb and config/environments/*.rb
unless defined?(RAILS_ROOT) unless defined?(RAILS_ROOT)
root_path = File.join(File.dirname(__FILE__), '..') root_path = File.join(File.dirname(__FILE__), '..')
unless RUBY_PLATFORM =~ /mswin32/ unless RUBY_PLATFORM =~ /mswin32/
require 'pathname' require 'pathname'
root_path = Pathname.new(root_path).cleanpath.to_s root_path = Pathname.new(root_path).cleanpath(true).to_s
end end
RAILS_ROOT = root_path RAILS_ROOT = root_path
end end
if File.directory?("#{RAILS_ROOT}/vendor/rails") unless defined?(Rails::Initializer)
if File.directory?("#{RAILS_ROOT}/vendor/rails")
require "#{RAILS_ROOT}/vendor/rails/railties/lib/initializer" require "#{RAILS_ROOT}/vendor/rails/railties/lib/initializer"
else else
require 'rubygems' require 'rubygems'
require 'initializer'
end
Rails::Initializer.run(:set_load_path) environment_without_comments = IO.readlines(File.dirname(__FILE__) + '/environment.rb').reject { |l| l =~ /^#/ }.join
environment_without_comments =~ /[^#]RAILS_GEM_VERSION = '([\d.]+)'/
rails_gem_version = $1
if version = defined?(RAILS_GEM_VERSION) ? RAILS_GEM_VERSION : rails_gem_version
# Asking for 1.1.6 will give you 1.1.6.5206, if available -- makes it easier to use beta gems
rails_gem = Gem.cache.search('rails', "~>#{version}.0").sort_by { |g| g.version.version }.last
if rails_gem
gem "rails", "=#{rails_gem.version.version}"
require rails_gem.full_gem_path + '/lib/initializer'
else
STDERR.puts %(Cannot find gem for Rails ~>#{version}.0:
Install the missing gem with 'gem install -v=#{version} rails', or
change environment.rb to define RAILS_GEM_VERSION with your desired version.
)
exit 1
end
else
gem "rails"
require 'initializer'
end
end
Rails::Initializer.run(:set_load_path)
end

View file

@ -0,0 +1,2 @@
// Place your application-specific JavaScript functions and classes here
// This file is automatically included by javascript_include_tag :defaults

View file

@ -1,12 +1,13 @@
// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) // Copyright (c) 2005, 2006 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
// (c) 2005 Ivan Krstic (http://blogs.law.harvard.edu/ivan) // (c) 2005, 2006 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
// (c) 2005 Jon Tirsen (http://www.tirsen.com) // (c) 2005, 2006 Jon Tirsen (http://www.tirsen.com)
// Contributors: // Contributors:
// Richard Livsey // Richard Livsey
// Rahul Bhargava // Rahul Bhargava
// Rob Wills // Rob Wills
// //
// See scriptaculous.js for full license. // script.aculo.us is freely distributable under the terms of an MIT-style license.
// For details, see the script.aculo.us web site: http://script.aculo.us/
// Autocompleter.Base handles all the autocompletion functionality // Autocompleter.Base handles all the autocompletion functionality
// that's independent of the data source for autocompletion. This // that's independent of the data source for autocompletion. This
@ -33,6 +34,9 @@
// useful when one of the tokens is \n (a newline), as it // useful when one of the tokens is \n (a newline), as it
// allows smart autocompletion after linebreaks. // allows smart autocompletion after linebreaks.
if(typeof Effect == 'undefined')
throw("controls.js requires including script.aculo.us' effects.js library");
var Autocompleter = {} var Autocompleter = {}
Autocompleter.Base = function() {}; Autocompleter.Base = function() {};
Autocompleter.Base.prototype = { Autocompleter.Base.prototype = {
@ -45,7 +49,7 @@ Autocompleter.Base.prototype = {
this.index = 0; this.index = 0;
this.entryCount = 0; this.entryCount = 0;
if (this.setOptions) if(this.setOptions)
this.setOptions(options); this.setOptions(options);
else else
this.options = options || {}; this.options = options || {};
@ -58,14 +62,17 @@ Autocompleter.Base.prototype = {
function(element, update){ function(element, update){
if(!update.style.position || update.style.position=='absolute') { if(!update.style.position || update.style.position=='absolute') {
update.style.position = 'absolute'; update.style.position = 'absolute';
Position.clone(element, update, {setHeight: false, offsetTop: element.offsetHeight}); Position.clone(element, update, {
setHeight: false,
offsetTop: element.offsetHeight
});
} }
Effect.Appear(update,{duration:0.15}); Effect.Appear(update,{duration:0.15});
}; };
this.options.onHide = this.options.onHide || this.options.onHide = this.options.onHide ||
function(element, update){ new Effect.Fade(update,{duration:0.15}) }; function(element, update){ new Effect.Fade(update,{duration:0.15}) };
if (typeof(this.options.tokens) == 'string') if(typeof(this.options.tokens) == 'string')
this.options.tokens = new Array(this.options.tokens); this.options.tokens = new Array(this.options.tokens);
this.observer = null; this.observer = null;
@ -80,7 +87,10 @@ Autocompleter.Base.prototype = {
show: function() { show: function() {
if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update); if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update);
if(!this.iefix && (navigator.appVersion.indexOf('MSIE')>0) && (Element.getStyle(this.update, 'position')=='absolute')) { if(!this.iefix &&
(navigator.appVersion.indexOf('MSIE')>0) &&
(navigator.userAgent.indexOf('Opera')<0) &&
(Element.getStyle(this.update, 'position')=='absolute')) {
new Insertion.After(this.update, new Insertion.After(this.update,
'<iframe id="' + this.update.id + '_iefix" '+ '<iframe id="' + this.update.id + '_iefix" '+
'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' + 'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' +
@ -91,7 +101,7 @@ Autocompleter.Base.prototype = {
}, },
fixIEOverlapping: function() { fixIEOverlapping: function() {
Position.clone(this.update, this.iefix); Position.clone(this.update, this.iefix, {setTop:(!this.update.style.height)});
this.iefix.style.zIndex = 1; this.iefix.style.zIndex = 1;
this.update.style.zIndex = 2; this.update.style.zIndex = 2;
Element.show(this.iefix); Element.show(this.iefix);
@ -138,8 +148,8 @@ Autocompleter.Base.prototype = {
return; return;
} }
else else
if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN) if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN ||
return; (navigator.appVersion.indexOf('AppleWebKit') > 0 && event.keyCode == 0)) return;
this.changed = true; this.changed = true;
this.hasFocus = true; this.hasFocus = true;
@ -149,6 +159,12 @@ Autocompleter.Base.prototype = {
setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000); setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000);
}, },
activate: function() {
this.changed = false;
this.hasFocus = true;
this.getUpdatedChoices();
},
onHover: function(event) { onHover: function(event) {
var element = Event.findElement(event, 'LI'); var element = Event.findElement(event, 'LI');
if(this.index != element.autocompleteIndex) if(this.index != element.autocompleteIndex)
@ -184,17 +200,22 @@ Autocompleter.Base.prototype = {
this.show(); this.show();
this.active = true; this.active = true;
} }
} else this.hide(); } else {
this.active = false;
this.hide();
}
}, },
markPrevious: function() { markPrevious: function() {
if(this.index > 0) this.index-- if(this.index > 0) this.index--
else this.index = this.entryCount-1; else this.index = this.entryCount-1;
this.getEntry(this.index).scrollIntoView(true);
}, },
markNext: function() { markNext: function() {
if(this.index < this.entryCount-1) this.index++ if(this.index < this.entryCount-1) this.index++
else this.index = 0; else this.index = 0;
this.getEntry(this.index).scrollIntoView(false);
}, },
getEntry: function(index) { getEntry: function(index) {
@ -215,8 +236,13 @@ Autocompleter.Base.prototype = {
this.options.updateElement(selectedElement); this.options.updateElement(selectedElement);
return; return;
} }
var value = '';
if (this.options.select) {
var nodes = document.getElementsByClassName(this.options.select, selectedElement) || [];
if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select);
} else
value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal');
var value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal');
var lastTokenPos = this.findLastToken(); var lastTokenPos = this.findLastToken();
if (lastTokenPos != -1) { if (lastTokenPos != -1) {
var newValue = this.element.value.substr(0, lastTokenPos + 1); var newValue = this.element.value.substr(0, lastTokenPos + 1);
@ -237,11 +263,11 @@ Autocompleter.Base.prototype = {
if(!this.changed && this.hasFocus) { if(!this.changed && this.hasFocus) {
this.update.innerHTML = choices; this.update.innerHTML = choices;
Element.cleanWhitespace(this.update); Element.cleanWhitespace(this.update);
Element.cleanWhitespace(this.update.firstChild); Element.cleanWhitespace(this.update.down());
if(this.update.firstChild && this.update.firstChild.childNodes) { if(this.update.firstChild && this.update.down().childNodes) {
this.entryCount = this.entryCount =
this.update.firstChild.childNodes.length; this.update.down().childNodes.length;
for (var i = 0; i < this.entryCount; i++) { for (var i = 0; i < this.entryCount; i++) {
var entry = this.getEntry(i); var entry = this.getEntry(i);
entry.autocompleteIndex = i; entry.autocompleteIndex = i;
@ -252,10 +278,15 @@ Autocompleter.Base.prototype = {
} }
this.stopIndicator(); this.stopIndicator();
this.index = 0; this.index = 0;
if(this.entryCount==1 && this.options.autoSelect) {
this.selectEntry();
this.hide();
} else {
this.render(); this.render();
} }
}
}, },
addObservers: function(element) { addObservers: function(element) {
@ -425,6 +456,15 @@ Autocompleter.Local.prototype = Object.extend(new Autocompleter.Base(), {
// //
// see documentation on http://wiki.script.aculo.us/scriptaculous/show/Ajax.InPlaceEditor // see documentation on http://wiki.script.aculo.us/scriptaculous/show/Ajax.InPlaceEditor
// Use this if you notice weird scrolling problems on some browsers,
// the DOM might be a bit confused when this gets called so do this
// waits 1 ms (with setTimeout) until it does the activation
Field.scrollFreeActivate = function(field) {
setTimeout(function() {
Field.activate(field);
}, 1);
}
Ajax.InPlaceEditor = Class.create(); Ajax.InPlaceEditor = Class.create();
Ajax.InPlaceEditor.defaultHighlightColor = "#FFFF99"; Ajax.InPlaceEditor.defaultHighlightColor = "#FFFF99";
Ajax.InPlaceEditor.prototype = { Ajax.InPlaceEditor.prototype = {
@ -433,7 +473,10 @@ Ajax.InPlaceEditor.prototype = {
this.element = $(element); this.element = $(element);
this.options = Object.extend({ this.options = Object.extend({
paramName: "value",
okButton: true,
okText: "ok", okText: "ok",
cancelLink: true,
cancelText: "cancel", cancelText: "cancel",
savingText: "Saving...", savingText: "Saving...",
clickToEditText: "Click to edit", clickToEditText: "Click to edit",
@ -456,7 +499,9 @@ Ajax.InPlaceEditor.prototype = {
highlightcolor: Ajax.InPlaceEditor.defaultHighlightColor, highlightcolor: Ajax.InPlaceEditor.defaultHighlightColor,
highlightendcolor: "#FFFFFF", highlightendcolor: "#FFFFFF",
externalControl: null, externalControl: null,
ajaxOptions: {} submitOnBlur: false,
ajaxOptions: {},
evalScripts: false
}, options || {}); }, options || {});
if(!this.options.formId && this.element.id) { if(!this.options.formId && this.element.id) {
@ -490,7 +535,7 @@ Ajax.InPlaceEditor.prototype = {
Event.observe(this.options.externalControl, 'mouseout', this.mouseoutListener); Event.observe(this.options.externalControl, 'mouseout', this.mouseoutListener);
} }
}, },
enterEditMode: function() { enterEditMode: function(evt) {
if (this.saving) return; if (this.saving) return;
if (this.editing) return; if (this.editing) return;
this.editing = true; this.editing = true;
@ -501,11 +546,12 @@ Ajax.InPlaceEditor.prototype = {
Element.hide(this.element); Element.hide(this.element);
this.createForm(); this.createForm();
this.element.parentNode.insertBefore(this.form, this.element); this.element.parentNode.insertBefore(this.form, this.element);
Field.focus(this.editField); if (!this.options.loadTextURL) Field.scrollFreeActivate(this.editField);
// stop the event to avoid a page refresh in Safari // stop the event to avoid a page refresh in Safari
if (arguments.length > 1) { if (evt) {
Event.stop(arguments[0]); Event.stop(evt);
} }
return false;
}, },
createForm: function() { createForm: function() {
this.form = document.createElement("form"); this.form = document.createElement("form");
@ -520,16 +566,22 @@ Ajax.InPlaceEditor.prototype = {
this.form.appendChild(br); this.form.appendChild(br);
} }
if (this.options.okButton) {
okButton = document.createElement("input"); okButton = document.createElement("input");
okButton.type = "submit"; okButton.type = "submit";
okButton.value = this.options.okText; okButton.value = this.options.okText;
okButton.className = 'editor_ok_button';
this.form.appendChild(okButton); this.form.appendChild(okButton);
}
if (this.options.cancelLink) {
cancelLink = document.createElement("a"); cancelLink = document.createElement("a");
cancelLink.href = "#"; cancelLink.href = "#";
cancelLink.appendChild(document.createTextNode(this.options.cancelText)); cancelLink.appendChild(document.createTextNode(this.options.cancelText));
cancelLink.onclick = this.onclickCancel.bind(this); cancelLink.onclick = this.onclickCancel.bind(this);
cancelLink.className = 'editor_cancel';
this.form.appendChild(cancelLink); this.form.appendChild(cancelLink);
}
}, },
hasHTMLLineBreaks: function(string) { hasHTMLLineBreaks: function(string) {
if (!this.options.handleLineBreaks) return false; if (!this.options.handleLineBreaks) return false;
@ -546,23 +598,33 @@ Ajax.InPlaceEditor.prototype = {
text = this.getText(); text = this.getText();
} }
var obj = this;
if (this.options.rows == 1 && !this.hasHTMLLineBreaks(text)) { if (this.options.rows == 1 && !this.hasHTMLLineBreaks(text)) {
this.options.textarea = false; this.options.textarea = false;
var textField = document.createElement("input"); var textField = document.createElement("input");
textField.obj = this;
textField.type = "text"; textField.type = "text";
textField.name = "value"; textField.name = this.options.paramName;
textField.value = text; textField.value = text;
textField.style.backgroundColor = this.options.highlightcolor; textField.style.backgroundColor = this.options.highlightcolor;
textField.className = 'editor_field';
var size = this.options.size || this.options.cols || 0; var size = this.options.size || this.options.cols || 0;
if (size != 0) textField.size = size; if (size != 0) textField.size = size;
if (this.options.submitOnBlur)
textField.onblur = this.onSubmit.bind(this);
this.editField = textField; this.editField = textField;
} else { } else {
this.options.textarea = true; this.options.textarea = true;
var textArea = document.createElement("textarea"); var textArea = document.createElement("textarea");
textArea.name = "value"; textArea.obj = this;
textArea.name = this.options.paramName;
textArea.value = this.convertHTMLLineBreaks(text); textArea.value = this.convertHTMLLineBreaks(text);
textArea.rows = this.options.rows; textArea.rows = this.options.rows;
textArea.cols = this.options.cols || 40; textArea.cols = this.options.cols || 40;
textArea.className = 'editor_field';
if (this.options.submitOnBlur)
textArea.onblur = this.onSubmit.bind(this);
this.editField = textArea; this.editField = textArea;
} }
@ -589,6 +651,7 @@ Ajax.InPlaceEditor.prototype = {
Element.removeClassName(this.form, this.options.loadingClassName); Element.removeClassName(this.form, this.options.loadingClassName);
this.editField.disabled = false; this.editField.disabled = false;
this.editField.value = transport.responseText.stripTags(); this.editField.value = transport.responseText.stripTags();
Field.scrollFreeActivate(this.editField);
}, },
onclickCancel: function() { onclickCancel: function() {
this.onComplete(); this.onComplete();
@ -613,19 +676,26 @@ Ajax.InPlaceEditor.prototype = {
// to be displayed indefinitely // to be displayed indefinitely
this.onLoading(); this.onLoading();
if (this.options.evalScripts) {
new Ajax.Request(
this.url, Object.extend({
parameters: this.options.callback(form, value),
onComplete: this.onComplete.bind(this),
onFailure: this.onFailure.bind(this),
asynchronous:true,
evalScripts:true
}, this.options.ajaxOptions));
} else {
new Ajax.Updater( new Ajax.Updater(
{ { success: this.element,
success: this.element,
// don't update on failure (this could be an option) // don't update on failure (this could be an option)
failure: null failure: null },
}, this.url, Object.extend({
this.url,
Object.extend({
parameters: this.options.callback(form, value), parameters: this.options.callback(form, value),
onComplete: this.onComplete.bind(this), onComplete: this.onComplete.bind(this),
onFailure: this.onFailure.bind(this) onFailure: this.onFailure.bind(this)
}, this.options.ajaxOptions) }, this.options.ajaxOptions));
); }
// stop the event to avoid a page refresh in Safari // stop the event to avoid a page refresh in Safari
if (arguments.length > 1) { if (arguments.length > 1) {
Event.stop(arguments[0]); Event.stop(arguments[0]);
@ -706,3 +776,58 @@ Ajax.InPlaceEditor.prototype = {
} }
} }
}; };
Ajax.InPlaceCollectionEditor = Class.create();
Object.extend(Ajax.InPlaceCollectionEditor.prototype, Ajax.InPlaceEditor.prototype);
Object.extend(Ajax.InPlaceCollectionEditor.prototype, {
createEditField: function() {
if (!this.cached_selectTag) {
var selectTag = document.createElement("select");
var collection = this.options.collection || [];
var optionTag;
collection.each(function(e,i) {
optionTag = document.createElement("option");
optionTag.value = (e instanceof Array) ? e[0] : e;
if((typeof this.options.value == 'undefined') &&
((e instanceof Array) ? this.element.innerHTML == e[1] : e == optionTag.value)) optionTag.selected = true;
if(this.options.value==optionTag.value) optionTag.selected = true;
optionTag.appendChild(document.createTextNode((e instanceof Array) ? e[1] : e));
selectTag.appendChild(optionTag);
}.bind(this));
this.cached_selectTag = selectTag;
}
this.editField = this.cached_selectTag;
if(this.options.loadTextURL) this.loadExternalText();
this.form.appendChild(this.editField);
this.options.callback = function(form, value) {
return "value=" + encodeURIComponent(value);
}
}
});
// Delayed observer, like Form.Element.Observer,
// but waits for delay after last key input
// Ideal for live-search fields
Form.Element.DelayedObserver = Class.create();
Form.Element.DelayedObserver.prototype = {
initialize: function(element, delay, callback) {
this.delay = delay || 0.5;
this.element = $(element);
this.callback = callback;
this.timer = null;
this.lastValue = $F(this.element);
Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this));
},
delayedListener: function(event) {
if(this.lastValue == $F(this.element)) return;
if(this.timer) clearTimeout(this.timer);
this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000);
this.lastValue = $F(this.element);
},
onTimerEvent: function() {
this.timer = null;
this.callback(this.element, $F(this.element));
}
};

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

3
script/about Executable file
View file

@ -0,0 +1,3 @@
#!/usr/bin/env ruby
require File.dirname(__FILE__) + '/../config/boot'
require 'commands/about'

3
script/performance/benchmarker Executable file
View file

@ -0,0 +1,3 @@
#!/usr/bin/env ruby
require File.dirname(__FILE__) + '/../../config/boot'
require 'commands/performance/benchmarker'

3
script/performance/profiler Executable file
View file

@ -0,0 +1,3 @@
#!/usr/bin/env ruby
require File.dirname(__FILE__) + '/../../config/boot'
require 'commands/performance/profiler'

3
script/plugin Executable file
View file

@ -0,0 +1,3 @@
#!/usr/bin/env ruby
require File.dirname(__FILE__) + '/../config/boot'
require 'commands/plugin'

3
script/process/inspector Executable file
View file

@ -0,0 +1,3 @@
#!/usr/bin/env ruby
require File.dirname(__FILE__) + '/../../config/boot'
require 'commands/process/inspector'

3
script/process/reaper Executable file
View file

@ -0,0 +1,3 @@
#!/usr/bin/env ruby
require File.dirname(__FILE__) + '/../../config/boot'
require 'commands/process/reaper'

3
script/process/spawner Executable file
View file

@ -0,0 +1,3 @@
#!/usr/bin/env ruby
require File.dirname(__FILE__) + '/../../config/boot'
require 'commands/process/spawner'