diff --git a/backup.rails2.3/Gemfile.rails2.3 b/backup.rails2.3/Gemfile.rails2.3 new file mode 100644 index 00000000..dc3af876 --- /dev/null +++ b/backup.rails2.3/Gemfile.rails2.3 @@ -0,0 +1,65 @@ +source :gemcutter +source "http://gems.github.com/" + +gem "rake", "~>0.8.7" +gem "rails", "~>2.3.12" +gem "highline", "~>1.5.0" +gem "RedCloth", "4.2.8" +gem "sanitize", "~>1.2.1" +gem "rack", "1.1.0" +gem "will_paginate", "~> 2.3.15" +gem "has_many_polymorphs", "~> 2.13" +gem "acts_as_list", "~>0.1.4" +gem "aasm", "~>2.2.0" +gem "rubyjedi-actionwebservice", :require => "actionwebservice" +gem "rubycas-client", "~>2.2.1" +gem "ruby-openid", :require => "openid" + +# you may comment out the database driver you will not be using. +# This will prevent a native build of the driver. Building native drivers is not always possible on all hosters +gem "sqlite3" +gem "mysql" + +gem 'bcrypt-ruby', '~> 2.1.4' +gem 'htmlentities', '~> 4.3.0' +gem "mail" + +if RUBY_VERSION.to_f >= 1.9 + gem "soap4r-ruby1.9" +else + gem "soap4r", "~>1.5.8" +end + +group :development do + if RUBY_VERSION.to_f >= 1.9 + gem "ruby-debug19" + gem "mongrel", "1.2.0.pre2" + else + gem "ruby-debug" + gem "mongrel" + end + gem "yard" +end + +group :test do + gem "test-unit", "1.2.3" + gem "flexmock" + gem "ZenTest", ">=4.0.0" + gem "hpricot" + gem "hoe" + gem "rspec-rails", "~>1.3.3" + gem "thoughtbot-factory_girl" + gem 'memory_test_fix', '~>0.1.3' + gem "capybara", ">=0.3.5" + gem "selenium-webdriver" # Note that > 2.14 has problems: https://code.google.com/p/selenium/issues/detail?id=3075 + gem "database_cleaner", ">=0.5.0" + gem "cucumber-rails", "~>0.3.2" + gem "aruba", "0.2.2", :path => "vendor/gems/aruba-0.2.2" + + # uncomment to use the webkit option. This depends on Qt to be installed + #gem "capybara-webkit" + + # uncomment to be able to make screenshots from scenarios + #gem "capybara-screenshot" + #gem "launchy" +end diff --git a/backup.rails2.3/Gemfile.rails3 b/backup.rails2.3/Gemfile.rails3 new file mode 100644 index 00000000..c07b2b6a --- /dev/null +++ b/backup.rails2.3/Gemfile.rails3 @@ -0,0 +1,39 @@ +source 'https://rubygems.org' + +gem 'rails', '3.2.3' + +# Bundle edge Rails instead: +# gem 'rails', :git => 'git://github.com/rails/rails.git' + +gem 'sqlite3' +gem 'mysql' + + +# Gems used only for assets and not required +# in production environments by default. +group :assets do + gem 'sass-rails', '~> 3.2.3' + gem 'coffee-rails', '~> 3.2.1' + + # See https://github.com/sstephenson/execjs#readme for more supported runtimes + # gem 'therubyracer', :platform => :ruby + + gem 'uglifier', '>= 1.0.3' +end + +gem 'jquery-rails' + +# To use ActiveModel has_secure_password +# gem 'bcrypt-ruby', '~> 3.0.0' + +# To use Jbuilder templates for JSON +# gem 'jbuilder' + +# Use unicorn as the app server +# gem 'unicorn' + +# Deploy with Capistrano +# gem 'capistrano' + +# To use debugger +# gem 'ruby-debug19', :require => 'ruby-debug' diff --git a/backup.rails2.3/app/apis/todo_api.rb b/backup.rails2.3/app/apis/todo_api.rb new file mode 100644 index 00000000..5f980a64 --- /dev/null +++ b/backup.rails2.3/app/apis/todo_api.rb @@ -0,0 +1,22 @@ +class TodoApi < ActionWebService::API::Base + api_method :new_todo, + :expects => [{:username => :string}, {:token => :string}, {:context_id => :int}, {:description => :string}, {:notes => :string}], + :returns => [:int] + + api_method :new_todo_for_project, + :expects => [{:username => :string}, {:token => :string}, {:context_id => :int}, {:project_id => :int}, {:description => :string}, {:notes => :string}], + :returns => [:int] + + api_method :new_rich_todo, + :expects => [{:username => :string}, {:token => :string}, {:default_context_id => :int}, {:description => :string}, {:notes => :string}], + :returns => [:int] + + api_method :list_contexts, + :expects => [{:username => :string}, {:token => :string}], + :returns => [[Context]] + + api_method :list_projects, + :expects => [{:username => :string}, {:token => :string}], + :returns => [[Project]] + +end diff --git a/backup.rails2.3/application_helper.rb.rails2 b/backup.rails2.3/application_helper.rb.rails2 new file mode 100644 index 00000000..39c591e4 --- /dev/null +++ b/backup.rails2.3/application_helper.rb.rails2 @@ -0,0 +1,301 @@ +# The methods added to this helper will be available to all templates in the +# application. +module ApplicationHelper + + # Replicates the link_to method but also checks request.request_uri to find + # current page. If that matches the url, the link is marked id = "current" + # + def navigation_link(name, options = {}, html_options = nil, *parameters_for_method_reference) + if html_options + html_options = html_options.stringify_keys + convert_options_to_javascript!(html_options) + tag_options = tag_options(html_options) + else + tag_options = nil + end + url = options.is_a?(String) ? options : self.url_for(options, *parameters_for_method_reference) + id_tag = (request.request_uri == url) ? " id=\"current\"" : "" + + "#{name || url}" + end + + def days_from_today(date) + date.in_time_zone.to_date - current_user.time.to_date + end + + # Check due date in comparison to today's date Flag up date appropriately with + # a 'traffic light' colour code + # + def due_date(due) + return "" if due.nil? + + days = days_from_today(due) + + colors = ['amber','amber','orange','orange','orange','orange','orange','orange'] + color = :red if days < 0 + color = :green if days > 7 + color = colors[days] if color.nil? + + return content_tag(:a, {:title => format_date(due)}) { + content_tag(:span, {:class => color}) { + case days + when 0 + t('todos.next_actions_due_date.due_today') + when 1 + t('todos.next_actions_due_date.due_tomorrow') + when 2..7 + if prefs.due_style == Preference.due_styles[:due_on] + # TODO: internationalize strftime here + t('models.preference.due_on', :date => due.strftime("%A")) + else + t('models.preference.due_in', :days => days) + end + else + # overdue or due very soon! sound the alarm! + if days == -1 + t('todos.next_actions_due_date.overdue_by', :days => days * -1) + elsif days < -1 + t('todos.next_actions_due_date.overdue_by_plural', :days => days * -1) + else + # more than a week away - relax + t('models.preference.due_in', :days => days) + end + end + } + } + end + + # Check due date in comparison to today's date Flag up date appropriately with + # a 'traffic light' colour code Modified method for mobile screen + # + def due_date_mobile(due) + if due == nil + return "" + end + + days = days_from_today(due) + + case days + when 0 + ""+ format_date(due) + "" + when 1 + "" + format_date(due) + "" + # due 2-7 days away + when 2..7 + "" + format_date(due) + "" + else + # overdue or due very soon! sound the alarm! + if days < 0 + "" + format_date(due) +"" + else + # more than a week away - relax + "" + format_date(due) + "" + end + end + end + + # Returns a count of next actions in the given context or project. The result + # is count and a string descriptor, correctly pluralised if there are no + # actions or multiple actions + # + def count_undone_todos_phrase(todos_parent, string="actions") + @controller.count_undone_todos_phrase(todos_parent, string) + end + + def count_undone_todos_phrase_text(todos_parent, string="actions") + count_undone_todos_phrase(todos_parent, string).gsub(" "," ") + end + + def count_undone_todos_and_notes_phrase(project, string="actions") + s = count_undone_todos_phrase(project, string) + s += ", #{pluralize(project.note_count, 'note')}" unless project.note_count == 0 + s + end + + def link_to_context(context, descriptor = sanitize(context.name)) + link_to( descriptor, context, :title => "View context: #{context.name}" ) + end + + def link_to_project(project, descriptor = sanitize(project.name)) + link_to( descriptor, project, :title => "View project: #{project.name}" ) + end + + def link_to_edit_note (note, descriptor = sanitize(note.id.to_s)) + link_to(descriptor, + url_for({:controller => 'notes', :action => 'edit', :id => note.id}), + {:id => "link_edit_#{dom_id(note)}", :class => "note_edit_settings"}) + end + + def link_to_project_mobile(project, accesskey, descriptor = sanitize(project.name)) + link_to( descriptor, project_path(project, :format => 'm'), {:title => "View project: #{project.name}", :accesskey => accesskey} ) + end + + def item_link_to_context(item) + descriptor = "[C]" + descriptor = "[#{item.context.name}]" if prefs.verbose_action_descriptors + link_to_context( item.context, descriptor ) + end + + def item_link_to_project(item) + descriptor = "[P]" + descriptor = "[#{item.project.name}]" if prefs.verbose_action_descriptors + link_to_project( item.project, descriptor ) + end + + def render_flash + render :partial => 'shared/flash', :object => flash + end + + def recurrence_time_span(rt) + case rt.ends_on + when "no_end_date" + return rt.start_from.nil? ? "" : I18n.t("todos.recurrence.pattern.from") + " " + format_date(rt.start_from) + when "ends_on_number_of_times" + return I18n.t("todos.recurrence.pattern.times", :number => rt.number_of_occurences) + when "ends_on_end_date" + starts = rt.start_from.nil? ? "" : I18n.t("todos.recurrence.pattern.from") + " " + format_date(rt.start_from) + ends = rt.end_date.nil? ? "" : " " + I18n.t("todos.recurrence.pattern.until") + " " + format_date(rt.end_date) + return starts+ends + else + raise Exception.new, "unknown recurrence time span selection (#{rt.ends_on})" + end + end + + def recurrence_pattern_as_text(recurring_todo) + rt = recurring_todo.recurring_target_as_text + rp = recurring_todo.recurrence_pattern + # only add space if recurrence_pattern has content + rp = " " + rp if !rp.nil? + rts = recurrence_time_span(recurring_todo) + # only add space if recurrence_time_span has content + rts = " " + rts if !(rts == "") + return rt+rp+rts + end + + def date_format_for_date_picker() + standard_format = current_user.prefs.date_format + translations = [ + ['%m', 'mm'], + ['%b', 'M'], + ['%B', 'MM'], + ['%d', 'dd'], + ['%a', 'D'], + ['%A', 'DD'], + ['%y', 'y'], + ['%Y', 'yy'] + ] + translations.inject(standard_format) do |str, translation| + str.gsub(*translation) + end + end + + AUTO_LINK_MESSAGE_RE = %r{message://<[^>]+>} unless const_defined?(:AUTO_LINK_MESSAGE_RE) + + # Converts message:// links to href. This URL scheme is used on Mac OS X + # to link to a mail message in Mail.app. + def auto_link_message(text) + text.gsub(AUTO_LINK_MESSAGE_RE) do + href = $& + left, right = $`, $' + # detect already linked URLs and URLs in the middle of a tag + if left =~ /<[^>]+$/ && right =~ /^[^>]*>/ + # do not change string; URL is alreay linked + href + else + content = content_tag(:a, h(href), :href => h(href)) + end + end + end + + def format_note(note) + note = auto_link_message(note) + note = markdown(note) + note = auto_link(note, :link => :urls) + + # add onenote and message protocols + Sanitize::Config::RELAXED[:protocols]['a']['href'] << 'onenote' + Sanitize::Config::RELAXED[:protocols]['a']['href'] << 'message' + + note = Sanitize.clean(note, Sanitize::Config::RELAXED) + return note + end + + def sidebar_html_for_titled_list (list, title) + return content_tag(:h3, title+" (#{list.length})") + + content_tag(:ul, sidebar_html_for_list(list)) + end + + def sidebar_html_for_list(list) + if list.empty? + return content_tag(:li, t('sidebar.list_empty')) + else + return list.inject("") do |html, item| + link = (item.class == "Project") ? link_to_project( item ) : link_to_context(item) + html << content_tag(:li, link + " (" + count_undone_todos_phrase(item,"actions")+")") + end + end + end + + def generate_i18n_strings + js = "i18n_locale='#{I18n.locale}';\n" + js << "i18n = new Array();\n" + %w{ + shared.toggle_multi shared.toggle_multi_title + shared.hide_form shared.hide_action_form_title + shared.toggle_single shared.toggle_single_title + projects.hide_form projects.hide_form_title + projects.show_form projects.show_form_title + contexts.hide_form contexts.hide_form_title + contexts.show_form contexts.show_form_title + contexts.new_context_pre contexts.new_context_post + common.cancel common.ok + common.ajaxError todos.unresolved_dependency + }.each do |s| + js << "i18n['#{s}'] = '#{ t(s).gsub(/'/, "\\\\'") }';\n" + end + return js + end + + def javascript_tag_for_i18n_datepicker + locale = I18n.locale + # do not include en as locale since this the available by default + if locale and locale != :en + javascript_include_tag("i18n/jquery.ui.datepicker-#{locale}.js") + end + end + + def determine_done_path + case @controller.controller_name + when "contexts" + done_todos_context_path(@context) + when "projects" + done_todos_project_path(@project) + when "todos" + if source_view_is(:tag) + done_tag_path(@tag_name) + else + done_todos_path + end + else + done_todos_path + end + end + + def determine_all_done_path + case @controller.controller_name + when "contexts" + all_done_todos_context_path(@context) + when "projects" + all_done_todos_project_path(@project) + when "todos" + if source_view_is(:tag) + all_done_tag_path(@tag_name) + else + all_done_todos_path + end + else + all_done_todos_path + end + end + +end diff --git a/backup.rails2.3/database.yml.rails2 b/backup.rails2.3/database.yml.rails2 new file mode 100644 index 00000000..da7aebc8 --- /dev/null +++ b/backup.rails2.3/database.yml.rails2 @@ -0,0 +1,37 @@ +# MySQL. Versions 4.1 and 5.0 are recommended. +# +# +# Be sure to use new-style password hashing: +# http://dev.mysql.com/doc/refman/5.0/en/old-client.html +development: + adapter: mysql + database: tracks_trunk + encoding: utf8 + host: localhost + username: tracks + password: 32tracks55 + +mdevelopment: + adapter: sqlite3 + database: db/tracks-21-test.sqlite3.db + +test: &TEST +# adapter: sqlite3 +# database: ":memory:" +# verbosity: quiet + adapter: mysql + database: tracks_test + host: localhost + username: tracks + password: 32tracks55 + +production: + adapter: mysql + database: tracks_trunk + encoding: utf8 + host: localhost + username: tracks + password: 32tracks55 + +cucumber: + <<: *TEST diff --git a/backup.rails2.3/development.rb.rails2 b/backup.rails2.3/development.rb.rails2 new file mode 100644 index 00000000..05c880d7 --- /dev/null +++ b/backup.rails2.3/development.rb.rails2 @@ -0,0 +1,19 @@ +# In the development environment your application's code is reloaded on +# every request. This slows down response time but is perfect for development +# since you don't have to restart the webserver when you make code changes. +config.cache_classes = false + +# Log error messages when you accidentally call methods on nil. +config.whiny_nils = true + +# Show full error reports and disable caching +config.action_controller.consider_all_requests_local = true +config.action_controller.perform_caching = false + +# Don't care if the mailer can't send +config.action_mailer.raise_delivery_errors = false + +# Unique cookies +config.action_controller.session = { :key => 'TracksDev' } + +NOTIFY_BAR="
+ + <%= text_field_tag "name" %> +
+ ++ + <%= password_field_tag %> +
+ ++ ...or use: +
+ ++ + <%= text_field_tag "openid_identifier" %> +
+ ++ <%= submit_tag 'Sign in', :disable_with => "Signing in…" %> +
+ <% end %> + +app/controllers/sessions_controller.rb + class SessionsController < ApplicationController + def create + if using_open_id? + open_id_authentication + else + password_authentication(params[:name], params[:password]) + end + end + + + protected + def password_authentication(name, password) + if @current_user = @account.users.authenticate(params[:name], params[:password]) + successful_login + else + failed_login "Sorry, that username/password doesn't work" + end + end + + def open_id_authentication + authenticate_with_open_id do |result, identity_url| + if result.successful? + if @current_user = @account.users.find_by_identity_url(identity_url) + successful_login + else + failed_login "Sorry, no user by that identity URL exists (#{identity_url})" + end + else + failed_login result.message + end + end + end + + + private + def successful_login + session[:user_id] = @current_user.id + redirect_to(root_url) + end + + def failed_login(message) + flash[:error] = message + redirect_to(new_session_url) + end + end + + + +If you're fine with the result messages above and don't need individual logic on a per-failure basis, +you can collapse the case into a mere boolean: + + def open_id_authentication + authenticate_with_open_id do |result, identity_url| + if result.successful? && @current_user = @account.users.find_by_identity_url(identity_url) + successful_login + else + failed_login(result.message || "Sorry, no user by that identity URL exists (#{identity_url})") + end + end + end + + +Simple Registration OpenID Extension +==================================== + +Some OpenID Providers support this lightweight profile exchange protocol. See more: http://www.openidenabled.com/openid/simple-registration-extension + +You can support it in your app by changing #open_id_authentication + + def open_id_authentication(identity_url) + # Pass optional :required and :optional keys to specify what sreg fields you want. + # Be sure to yield registration, a third argument in the #authenticate_with_open_id block. + authenticate_with_open_id(identity_url, + :required => [ :nickname, :email ], + :optional => :fullname) do |result, identity_url, registration| + case result.status + when :missing + failed_login "Sorry, the OpenID server couldn't be found" + when :invalid + failed_login "Sorry, but this does not appear to be a valid OpenID" + when :canceled + failed_login "OpenID verification was canceled" + when :failed + failed_login "Sorry, the OpenID verification failed" + when :successful + if @current_user = @account.users.find_by_identity_url(identity_url) + assign_registration_attributes!(registration) + + if current_user.save + successful_login + else + failed_login "Your OpenID profile registration failed: " + + @current_user.errors.full_messages.to_sentence + end + else + failed_login "Sorry, no user by that identity URL exists" + end + end + end + end + + # registration is a hash containing the valid sreg keys given above + # use this to map them to fields of your user model + def assign_registration_attributes!(registration) + model_to_registration_mapping.each do |model_attribute, registration_attribute| + unless registration[registration_attribute].blank? + @current_user.send("#{model_attribute}=", registration[registration_attribute]) + end + end + end + + def model_to_registration_mapping + { :login => 'nickname', :email => 'email', :display_name => 'fullname' } + end + +Attribute Exchange OpenID Extension +=================================== + +Some OpenID providers also support the OpenID AX (attribute exchange) protocol for exchanging identity information between endpoints. See more: http://openid.net/specs/openid-attribute-exchange-1_0.html + +Accessing AX data is very similar to the Simple Registration process, described above -- just add the URI identifier for the AX field to your :optional or :required parameters. For example: + + authenticate_with_open_id(identity_url, + :required => [ :email, 'http://schema.openid.net/birthDate' ]) do |result, identity_url, registration| + +This would provide the sreg data for :email, and the AX data for 'http://schema.openid.net/birthDate' + + + +Copyright (c) 2007 David Heinemeier Hansson, released under the MIT license \ No newline at end of file diff --git a/backup.rails2.3/plugins/open_id_authentication/Rakefile b/backup.rails2.3/plugins/open_id_authentication/Rakefile new file mode 100644 index 00000000..31074b85 --- /dev/null +++ b/backup.rails2.3/plugins/open_id_authentication/Rakefile @@ -0,0 +1,22 @@ +require 'rake' +require 'rake/testtask' +require 'rake/rdoctask' + +desc 'Default: run unit tests.' +task :default => :test + +desc 'Test the open_id_authentication plugin.' +Rake::TestTask.new(:test) do |t| + t.libs << 'lib' + t.pattern = 'test/**/*_test.rb' + t.verbose = true +end + +desc 'Generate documentation for the open_id_authentication plugin.' +Rake::RDocTask.new(:rdoc) do |rdoc| + rdoc.rdoc_dir = 'rdoc' + rdoc.title = 'OpenIdAuthentication' + rdoc.options << '--line-numbers' << '--inline-source' + rdoc.rdoc_files.include('README') + rdoc.rdoc_files.include('lib/**/*.rb') +end diff --git a/backup.rails2.3/plugins/open_id_authentication/generators/open_id_authentication_tables/open_id_authentication_tables_generator.rb b/backup.rails2.3/plugins/open_id_authentication/generators/open_id_authentication_tables/open_id_authentication_tables_generator.rb new file mode 100644 index 00000000..6f78afc7 --- /dev/null +++ b/backup.rails2.3/plugins/open_id_authentication/generators/open_id_authentication_tables/open_id_authentication_tables_generator.rb @@ -0,0 +1,11 @@ +class OpenIdAuthenticationTablesGenerator < Rails::Generator::NamedBase + def initialize(runtime_args, runtime_options = {}) + super + end + + def manifest + record do |m| + m.migration_template 'migration.rb', 'db/migrate' + end + end +end diff --git a/backup.rails2.3/plugins/open_id_authentication/generators/open_id_authentication_tables/templates/migration.rb b/backup.rails2.3/plugins/open_id_authentication/generators/open_id_authentication_tables/templates/migration.rb new file mode 100644 index 00000000..ef2a0cfb --- /dev/null +++ b/backup.rails2.3/plugins/open_id_authentication/generators/open_id_authentication_tables/templates/migration.rb @@ -0,0 +1,20 @@ +class <%= class_name %> < ActiveRecord::Migration + def self.up + create_table :open_id_authentication_associations, :force => true do |t| + t.integer :issued, :lifetime + t.string :handle, :assoc_type + t.binary :server_url, :secret + end + + create_table :open_id_authentication_nonces, :force => true do |t| + t.integer :timestamp, :null => false + t.string :server_url, :null => true + t.string :salt, :null => false + end + end + + def self.down + drop_table :open_id_authentication_associations + drop_table :open_id_authentication_nonces + end +end diff --git a/backup.rails2.3/plugins/open_id_authentication/generators/upgrade_open_id_authentication_tables/templates/migration.rb b/backup.rails2.3/plugins/open_id_authentication/generators/upgrade_open_id_authentication_tables/templates/migration.rb new file mode 100644 index 00000000..d13bbab2 --- /dev/null +++ b/backup.rails2.3/plugins/open_id_authentication/generators/upgrade_open_id_authentication_tables/templates/migration.rb @@ -0,0 +1,26 @@ +class <%= class_name %> < ActiveRecord::Migration + def self.up + drop_table :open_id_authentication_settings + drop_table :open_id_authentication_nonces + + create_table :open_id_authentication_nonces, :force => true do |t| + t.integer :timestamp, :null => false + t.string :server_url, :null => true + t.string :salt, :null => false + end + end + + def self.down + drop_table :open_id_authentication_nonces + + create_table :open_id_authentication_nonces, :force => true do |t| + t.integer :created + t.string :nonce + end + + create_table :open_id_authentication_settings, :force => true do |t| + t.string :setting + t.binary :value + end + end +end diff --git a/backup.rails2.3/plugins/open_id_authentication/generators/upgrade_open_id_authentication_tables/upgrade_open_id_authentication_tables_generator.rb b/backup.rails2.3/plugins/open_id_authentication/generators/upgrade_open_id_authentication_tables/upgrade_open_id_authentication_tables_generator.rb new file mode 100644 index 00000000..02fddd7f --- /dev/null +++ b/backup.rails2.3/plugins/open_id_authentication/generators/upgrade_open_id_authentication_tables/upgrade_open_id_authentication_tables_generator.rb @@ -0,0 +1,11 @@ +class UpgradeOpenIdAuthenticationTablesGenerator < Rails::Generator::NamedBase + def initialize(runtime_args, runtime_options = {}) + super + end + + def manifest + record do |m| + m.migration_template 'migration.rb', 'db/migrate' + end + end +end diff --git a/backup.rails2.3/plugins/open_id_authentication/init.rb b/backup.rails2.3/plugins/open_id_authentication/init.rb new file mode 100644 index 00000000..808c7bdb --- /dev/null +++ b/backup.rails2.3/plugins/open_id_authentication/init.rb @@ -0,0 +1,18 @@ +if config.respond_to?(:gems) + config.gem 'ruby-openid', :lib => 'openid', :version => '>=2.0.4' +else + begin + require 'openid' + rescue LoadError + begin + gem 'ruby-openid', '>=2.0.4' + rescue Gem::LoadError + puts "Install the ruby-openid gem to enable OpenID support" + end + end +end + +config.to_prepare do + OpenID::Util.logger = Rails.logger + ActionController::Base.send :include, OpenIdAuthentication +end diff --git a/backup.rails2.3/plugins/open_id_authentication/lib/open_id_authentication.rb b/backup.rails2.3/plugins/open_id_authentication/lib/open_id_authentication.rb new file mode 100644 index 00000000..b485c5fe --- /dev/null +++ b/backup.rails2.3/plugins/open_id_authentication/lib/open_id_authentication.rb @@ -0,0 +1,240 @@ +require 'uri' +require 'openid/extensions/sreg' +require 'openid/extensions/ax' +require 'openid/store/filesystem' + +require File.dirname(__FILE__) + '/open_id_authentication/association' +require File.dirname(__FILE__) + '/open_id_authentication/nonce' +require File.dirname(__FILE__) + '/open_id_authentication/db_store' +require File.dirname(__FILE__) + '/open_id_authentication/request' +require File.dirname(__FILE__) + '/open_id_authentication/timeout_fixes' if OpenID::VERSION == "2.0.4" + +module OpenIdAuthentication + OPEN_ID_AUTHENTICATION_DIR = RAILS_ROOT + "/tmp/openids" + + def self.store + @@store + end + + def self.store=(*store_option) + store, *parameters = *([ store_option ].flatten) + + @@store = case store + when :db + OpenIdAuthentication::DbStore.new + when :file + OpenID::Store::Filesystem.new(OPEN_ID_AUTHENTICATION_DIR) + else + store + end + end + + self.store = :db + + class InvalidOpenId < StandardError + end + + class Result + ERROR_MESSAGES = { + :missing => "Sorry, the OpenID server couldn't be found", + :invalid => "Sorry, but this does not appear to be a valid OpenID", + :canceled => "OpenID verification was canceled", + :failed => "OpenID verification failed", + :setup_needed => "OpenID verification needs setup" + } + + def self.[](code) + new(code) + end + + def initialize(code) + @code = code + end + + def status + @code + end + + ERROR_MESSAGES.keys.each { |state| define_method("#{state}?") { @code == state } } + + def successful? + @code == :successful + end + + def unsuccessful? + ERROR_MESSAGES.keys.include?(@code) + end + + def message + ERROR_MESSAGES[@code] + end + end + + # normalizes an OpenID according to http://openid.net/specs/openid-authentication-2_0.html#normalization + def self.normalize_identifier(identifier) + # clean up whitespace + identifier = identifier.to_s.strip + + # if an XRI has a prefix, strip it. + identifier.gsub!(/xri:\/\//i, '') + + # dodge XRIs -- TODO: validate, don't just skip. + unless ['=', '@', '+', '$', '!', '('].include?(identifier.at(0)) + # does it begin with http? if not, add it. + identifier = "http://#{identifier}" unless identifier =~ /^http/i + + # strip any fragments + identifier.gsub!(/\#(.*)$/, '') + + begin + uri = URI.parse(identifier) + uri.scheme = uri.scheme.downcase # URI should do this + identifier = uri.normalize.to_s + rescue URI::InvalidURIError + raise InvalidOpenId.new("#{identifier} is not an OpenID identifier") + end + end + + return identifier + end + + # deprecated for OpenID 2.0, where not all OpenIDs are URLs + def self.normalize_url(url) + ActiveSupport::Deprecation.warn "normalize_url has been deprecated, use normalize_identifier instead" + self.normalize_identifier(url) + end + + protected + def normalize_url(url) + OpenIdAuthentication.normalize_url(url) + end + + def normalize_identifier(url) + OpenIdAuthentication.normalize_identifier(url) + end + + # The parameter name of "openid_identifier" is used rather than the Rails convention "open_id_identifier" + # because that's what the specification dictates in order to get browser auto-complete working across sites + def using_open_id?(identity_url = nil) #:doc: + identity_url ||= params[:openid_identifier] || params[:openid_url] + !identity_url.blank? || params[:open_id_complete] + end + + def authenticate_with_open_id(identity_url = nil, options = {}, &block) #:doc: + identity_url ||= params[:openid_identifier] || params[:openid_url] + + if params[:open_id_complete].nil? + begin_open_id_authentication(identity_url, options, &block) + else + complete_open_id_authentication(&block) + end + end + + private + def begin_open_id_authentication(identity_url, options = {}) + identity_url = normalize_identifier(identity_url) + return_to = options.delete(:return_to) + method = options.delete(:method) + + options[:required] ||= [] # reduces validation later + options[:optional] ||= [] + + open_id_request = open_id_consumer.begin(identity_url) + add_simple_registration_fields(open_id_request, options) + add_ax_fields(open_id_request, options) + redirect_to(open_id_redirect_url(open_id_request, return_to, method)) + rescue OpenIdAuthentication::InvalidOpenId => e + yield Result[:invalid], identity_url, nil + rescue OpenID::OpenIDError, Timeout::Error => e + logger.error("[OPENID] #{e}") + yield Result[:missing], identity_url, nil + end + + def complete_open_id_authentication + params_with_path = params.reject { |key, value| request.path_parameters[key] } + params_with_path.delete(:format) + open_id_response = timeout_protection_from_identity_server { open_id_consumer.complete(params_with_path, requested_url) } + identity_url = normalize_identifier(open_id_response.display_identifier) if open_id_response.display_identifier + + case open_id_response.status + when OpenID::Consumer::SUCCESS + profile_data = {} + + # merge the SReg data and the AX data into a single hash of profile data + [ OpenID::SReg::Response, OpenID::AX::FetchResponse ].each do |data_response| + if data_response.from_success_response( open_id_response ) + profile_data.merge! data_response.from_success_response( open_id_response ).data + end + end + + yield Result[:successful], identity_url, profile_data + when OpenID::Consumer::CANCEL + yield Result[:canceled], identity_url, nil + when OpenID::Consumer::FAILURE + yield Result[:failed], identity_url, nil + when OpenID::Consumer::SETUP_NEEDED + yield Result[:setup_needed], open_id_response.setup_url, nil + end + end + + def open_id_consumer + OpenID::Consumer.new(session, OpenIdAuthentication.store) + end + + def add_simple_registration_fields(open_id_request, fields) + sreg_request = OpenID::SReg::Request.new + + # filter out AX identifiers (URIs) + required_fields = fields[:required].collect { |f| f.to_s unless f =~ /^https?:\/\// }.compact + optional_fields = fields[:optional].collect { |f| f.to_s unless f =~ /^https?:\/\// }.compact + + sreg_request.request_fields(required_fields, true) unless required_fields.blank? + sreg_request.request_fields(optional_fields, false) unless optional_fields.blank? + sreg_request.policy_url = fields[:policy_url] if fields[:policy_url] + open_id_request.add_extension(sreg_request) + end + + def add_ax_fields( open_id_request, fields ) + ax_request = OpenID::AX::FetchRequest.new + + # look through the :required and :optional fields for URIs (AX identifiers) + fields[:required].each do |f| + next unless f =~ /^https?:\/\// + ax_request.add( OpenID::AX::AttrInfo.new( f, nil, true ) ) + end + + fields[:optional].each do |f| + next unless f =~ /^https?:\/\// + ax_request.add( OpenID::AX::AttrInfo.new( f, nil, false ) ) + end + + open_id_request.add_extension( ax_request ) + end + + def open_id_redirect_url(open_id_request, return_to = nil, method = nil) + open_id_request.return_to_args['_method'] = (method || request.method).to_s + open_id_request.return_to_args['open_id_complete'] = '1' + open_id_request.redirect_url(root_url, return_to || requested_url) + end + + def requested_url + relative_url_root = self.class.respond_to?(:relative_url_root) ? + self.class.relative_url_root.to_s : + request.relative_url_root + "#{request.protocol}#{request.host_with_port}#{ActionController::Base.relative_url_root}#{request.path}" + end + + def timeout_protection_from_identity_server + yield + rescue Timeout::Error + Class.new do + def status + OpenID::FAILURE + end + + def msg + "Identity server timed out" + end + end.new + end +end diff --git a/backup.rails2.3/plugins/open_id_authentication/lib/open_id_authentication/association.rb b/backup.rails2.3/plugins/open_id_authentication/lib/open_id_authentication/association.rb new file mode 100644 index 00000000..9654eaeb --- /dev/null +++ b/backup.rails2.3/plugins/open_id_authentication/lib/open_id_authentication/association.rb @@ -0,0 +1,9 @@ +module OpenIdAuthentication + class Association < ActiveRecord::Base + set_table_name :open_id_authentication_associations + + def from_record + OpenID::Association.new(handle, secret, issued, lifetime, assoc_type) + end + end +end diff --git a/backup.rails2.3/plugins/open_id_authentication/lib/open_id_authentication/db_store.rb b/backup.rails2.3/plugins/open_id_authentication/lib/open_id_authentication/db_store.rb new file mode 100644 index 00000000..780fb6ad --- /dev/null +++ b/backup.rails2.3/plugins/open_id_authentication/lib/open_id_authentication/db_store.rb @@ -0,0 +1,55 @@ +require 'openid/store/interface' + +module OpenIdAuthentication + class DbStore < OpenID::Store::Interface + def self.cleanup_nonces + now = Time.now.to_i + Nonce.delete_all(["timestamp > ? OR timestamp < ?", now + OpenID::Nonce.skew, now - OpenID::Nonce.skew]) + end + + def self.cleanup_associations + now = Time.now.to_i + Association.delete_all(['issued + lifetime > ?',now]) + end + + def store_association(server_url, assoc) + remove_association(server_url, assoc.handle) + Association.create(:server_url => server_url, + :handle => assoc.handle, + :secret => assoc.secret, + :issued => assoc.issued, + :lifetime => assoc.lifetime, + :assoc_type => assoc.assoc_type) + end + + def get_association(server_url, handle = nil) + assocs = if handle.blank? + Association.find_all_by_server_url(server_url) + else + Association.find_all_by_server_url_and_handle(server_url, handle) + end + + assocs.reverse.each do |assoc| + a = assoc.from_record + if a.expires_in == 0 + assoc.destroy + else + return a + end + end if assocs.any? + + return nil + end + + def remove_association(server_url, handle) + Association.delete_all(['server_url = ? AND handle = ?', server_url, handle]) > 0 + end + + def use_nonce(server_url, timestamp, salt) + return false if Nonce.find_by_server_url_and_timestamp_and_salt(server_url, timestamp, salt) + return false if (timestamp - Time.now.to_i).abs > OpenID::Nonce.skew + Nonce.create(:server_url => server_url, :timestamp => timestamp, :salt => salt) + return true + end + end +end diff --git a/backup.rails2.3/plugins/open_id_authentication/lib/open_id_authentication/nonce.rb b/backup.rails2.3/plugins/open_id_authentication/lib/open_id_authentication/nonce.rb new file mode 100644 index 00000000..c52f6c50 --- /dev/null +++ b/backup.rails2.3/plugins/open_id_authentication/lib/open_id_authentication/nonce.rb @@ -0,0 +1,5 @@ +module OpenIdAuthentication + class Nonce < ActiveRecord::Base + set_table_name :open_id_authentication_nonces + end +end diff --git a/backup.rails2.3/plugins/open_id_authentication/lib/open_id_authentication/request.rb b/backup.rails2.3/plugins/open_id_authentication/lib/open_id_authentication/request.rb new file mode 100644 index 00000000..e0cc8e3f --- /dev/null +++ b/backup.rails2.3/plugins/open_id_authentication/lib/open_id_authentication/request.rb @@ -0,0 +1,23 @@ +module OpenIdAuthentication + module Request + def self.included(base) + base.alias_method_chain :request_method, :openid + end + + def request_method_with_openid + if !parameters[:_method].blank? && parameters[:open_id_complete] == '1' + parameters[:_method].to_sym + else + request_method_without_openid + end + end + end +end + +# In Rails 2.3, the request object has been renamed +# from AbstractRequest to Request +if defined? ActionController::Request + ActionController::Request.send :include, OpenIdAuthentication::Request +else + ActionController::AbstractRequest.send :include, OpenIdAuthentication::Request +end diff --git a/backup.rails2.3/plugins/open_id_authentication/lib/open_id_authentication/timeout_fixes.rb b/backup.rails2.3/plugins/open_id_authentication/lib/open_id_authentication/timeout_fixes.rb new file mode 100644 index 00000000..cc711c9a --- /dev/null +++ b/backup.rails2.3/plugins/open_id_authentication/lib/open_id_authentication/timeout_fixes.rb @@ -0,0 +1,20 @@ +# http://trac.openidenabled.com/trac/ticket/156 +module OpenID + @@timeout_threshold = 20 + + def self.timeout_threshold + @@timeout_threshold + end + + def self.timeout_threshold=(value) + @@timeout_threshold = value + end + + class StandardFetcher + def make_http(uri) + http = @proxy.new(uri.host, uri.port) + http.read_timeout = http.open_timeout = OpenID.timeout_threshold + http + end + end +end \ No newline at end of file diff --git a/backup.rails2.3/plugins/open_id_authentication/tasks/open_id_authentication_tasks.rake b/backup.rails2.3/plugins/open_id_authentication/tasks/open_id_authentication_tasks.rake new file mode 100644 index 00000000..c71434a5 --- /dev/null +++ b/backup.rails2.3/plugins/open_id_authentication/tasks/open_id_authentication_tasks.rake @@ -0,0 +1,30 @@ +namespace :open_id_authentication do + namespace :db do + desc "Creates authentication tables for use with OpenIdAuthentication" + task :create => :environment do + generate_migration(["open_id_authentication_tables", "add_open_id_authentication_tables"]) + end + + desc "Upgrade authentication tables from ruby-openid 1.x.x to 2.x.x" + task :upgrade => :environment do + generate_migration(["upgrade_open_id_authentication_tables", "upgrade_open_id_authentication_tables"]) + end + + def generate_migration(args) + require 'rails_generator' + require 'rails_generator/scripts/generate' + + if ActiveRecord::Base.connection.supports_migrations? + Rails::Generator::Scripts::Generate.new.run(args) + else + raise "Task unavailable to this database (no migration support)" + end + end + + desc "Clear the authentication tables" + task :clear => :environment do + OpenIdAuthentication::DbStore.cleanup_nonces + OpenIdAuthentication::DbStore.cleanup_associations + end + end +end diff --git a/backup.rails2.3/plugins/open_id_authentication/test/normalize_test.rb b/backup.rails2.3/plugins/open_id_authentication/test/normalize_test.rb new file mode 100644 index 00000000..635d3abc --- /dev/null +++ b/backup.rails2.3/plugins/open_id_authentication/test/normalize_test.rb @@ -0,0 +1,32 @@ +require File.dirname(__FILE__) + '/test_helper' + +class NormalizeTest < Test::Unit::TestCase + include OpenIdAuthentication + + NORMALIZATIONS = { + "openid.aol.com/nextangler" => "http://openid.aol.com/nextangler", + "http://openid.aol.com/nextangler" => "http://openid.aol.com/nextangler", + "https://openid.aol.com/nextangler" => "https://openid.aol.com/nextangler", + "HTTP://OPENID.AOL.COM/NEXTANGLER" => "http://openid.aol.com/NEXTANGLER", + "HTTPS://OPENID.AOL.COM/NEXTANGLER" => "https://openid.aol.com/NEXTANGLER", + "loudthinking.com" => "http://loudthinking.com/", + "http://loudthinking.com" => "http://loudthinking.com/", + "http://loudthinking.com:80" => "http://loudthinking.com/", + "https://loudthinking.com:443" => "https://loudthinking.com/", + "http://loudthinking.com:8080" => "http://loudthinking.com:8080/", + "techno-weenie.net" => "http://techno-weenie.net/", + "http://techno-weenie.net" => "http://techno-weenie.net/", + "http://techno-weenie.net " => "http://techno-weenie.net/", + "=name" => "=name" + } + + def test_normalizations + NORMALIZATIONS.each do |from, to| + assert_equal to, normalize_identifier(from) + end + end + + def test_broken_open_id + assert_raises(InvalidOpenId) { normalize_identifier(nil) } + end +end diff --git a/backup.rails2.3/plugins/open_id_authentication/test/open_id_authentication_test.rb b/backup.rails2.3/plugins/open_id_authentication/test/open_id_authentication_test.rb new file mode 100644 index 00000000..ddcc17b9 --- /dev/null +++ b/backup.rails2.3/plugins/open_id_authentication/test/open_id_authentication_test.rb @@ -0,0 +1,46 @@ +require File.dirname(__FILE__) + '/test_helper' + +class OpenIdAuthenticationTest < Test::Unit::TestCase + def setup + @controller = Class.new do + include OpenIdAuthentication + def params() {} end + end.new + end + + def test_authentication_should_fail_when_the_identity_server_is_missing + open_id_consumer = mock() + open_id_consumer.expects(:begin).raises(OpenID::OpenIDError) + @controller.expects(:open_id_consumer).returns(open_id_consumer) + @controller.expects(:logger).returns(mock(:error => true)) + + @controller.send(:authenticate_with_open_id, "http://someone.example.com") do |result, identity_url| + assert result.missing? + assert_equal "Sorry, the OpenID server couldn't be found", result.message + end + end + + def test_authentication_should_be_invalid_when_the_identity_url_is_invalid + @controller.send(:authenticate_with_open_id, "!") do |result, identity_url| + assert result.invalid?, "Result expected to be invalid but was not" + assert_equal "Sorry, but this does not appear to be a valid OpenID", result.message + end + end + + def test_authentication_should_fail_when_the_identity_server_times_out + open_id_consumer = mock() + open_id_consumer.expects(:begin).raises(Timeout::Error, "Identity Server took too long.") + @controller.expects(:open_id_consumer).returns(open_id_consumer) + @controller.expects(:logger).returns(mock(:error => true)) + + @controller.send(:authenticate_with_open_id, "http://someone.example.com") do |result, identity_url| + assert result.missing? + assert_equal "Sorry, the OpenID server couldn't be found", result.message + end + end + + def test_authentication_should_begin_when_the_identity_server_is_present + @controller.expects(:begin_open_id_authentication) + @controller.send(:authenticate_with_open_id, "http://someone.example.com") + end +end diff --git a/backup.rails2.3/plugins/open_id_authentication/test/status_test.rb b/backup.rails2.3/plugins/open_id_authentication/test/status_test.rb new file mode 100644 index 00000000..b1d5e093 --- /dev/null +++ b/backup.rails2.3/plugins/open_id_authentication/test/status_test.rb @@ -0,0 +1,14 @@ +require File.dirname(__FILE__) + '/test_helper' + +class StatusTest < Test::Unit::TestCase + include OpenIdAuthentication + + def test_state_conditional + assert Result[:missing].missing? + assert Result[:missing].unsuccessful? + assert !Result[:missing].successful? + + assert Result[:successful].successful? + assert !Result[:successful].unsuccessful? + end +end \ No newline at end of file diff --git a/backup.rails2.3/plugins/open_id_authentication/test/test_helper.rb b/backup.rails2.3/plugins/open_id_authentication/test/test_helper.rb new file mode 100644 index 00000000..43216e1e --- /dev/null +++ b/backup.rails2.3/plugins/open_id_authentication/test/test_helper.rb @@ -0,0 +1,17 @@ +require 'test/unit' +require 'rubygems' + +gem 'activesupport' +require 'active_support' + +gem 'actionpack' +require 'action_controller' + +gem 'mocha' +require 'mocha' + +gem 'ruby-openid' +require 'openid' + +RAILS_ROOT = File.dirname(__FILE__) unless defined? RAILS_ROOT +require File.dirname(__FILE__) + "/../lib/open_id_authentication" diff --git a/backup.rails2.3/plugins/resource_feeder/README b/backup.rails2.3/plugins/resource_feeder/README new file mode 100644 index 00000000..5502be25 --- /dev/null +++ b/backup.rails2.3/plugins/resource_feeder/README @@ -0,0 +1,7 @@ +ResourceFeeder +============== + +Simple feeds for resources + +NOTE: This plugin depends on the latest version of simply_helpful, available here: +http://dev.rubyonrails.org/svn/rails/plugins/simply_helpful/ diff --git a/backup.rails2.3/plugins/resource_feeder/Rakefile b/backup.rails2.3/plugins/resource_feeder/Rakefile new file mode 100644 index 00000000..51fce7b3 --- /dev/null +++ b/backup.rails2.3/plugins/resource_feeder/Rakefile @@ -0,0 +1,22 @@ +require 'rake' +require 'rake/testtask' +require 'rake/rdoctask' + +desc 'Default: run unit tests.' +task :default => :test + +desc 'Test the resource_feed plugin.' +Rake::TestTask.new(:test) do |t| + t.libs << 'lib' + t.pattern = 'test/**/*_test.rb' + t.verbose = true +end + +desc 'Generate documentation for the resource_feed plugin.' +Rake::RDocTask.new(:rdoc) do |rdoc| + rdoc.rdoc_dir = 'rdoc' + rdoc.title = 'ResourceFeed' + rdoc.options << '--line-numbers' << '--inline-source' + rdoc.rdoc_files.include('README') + rdoc.rdoc_files.include('lib/**/*.rb') +end diff --git a/backup.rails2.3/plugins/resource_feeder/init.rb b/backup.rails2.3/plugins/resource_feeder/init.rb new file mode 100644 index 00000000..7b55d76f --- /dev/null +++ b/backup.rails2.3/plugins/resource_feeder/init.rb @@ -0,0 +1,2 @@ +require 'resource_feeder' +ActionController::Base.send(:include, ResourceFeeder::Rss, ResourceFeeder::Atom) \ No newline at end of file diff --git a/backup.rails2.3/plugins/resource_feeder/lib/resource_feeder.rb b/backup.rails2.3/plugins/resource_feeder/lib/resource_feeder.rb new file mode 100644 index 00000000..b5003419 --- /dev/null +++ b/backup.rails2.3/plugins/resource_feeder/lib/resource_feeder.rb @@ -0,0 +1,2 @@ +require 'resource_feeder/rss' +require 'resource_feeder/atom' diff --git a/backup.rails2.3/plugins/resource_feeder/lib/resource_feeder/atom.rb b/backup.rails2.3/plugins/resource_feeder/lib/resource_feeder/atom.rb new file mode 100644 index 00000000..40af87df --- /dev/null +++ b/backup.rails2.3/plugins/resource_feeder/lib/resource_feeder/atom.rb @@ -0,0 +1,67 @@ +require 'resource_feeder/common' + +module ResourceFeeder + module Atom + include ResourceFeeder::Common + include ActionController::Routing + extend self + + def render_atom_feed_for(resources, options = {}) + render :text => atom_feed_for(resources, options), :content_type => Mime::ATOM + end + + def atom_feed_for(resources, options = {}) + xml = Builder::XmlMarkup.new(:indent => 2) + + options[:feed] ||= {} + options[:item] ||= {} + options[:url_writer] ||= self + + if options[:class] || resources.first + klass = options[:class] || resources.first.class + new_record = klass.new + else + options[:feed] = { :title => "Empty", :link => "http://example.com" } + end + + options[:feed][:title] ||= klass.name.pluralize + options[:feed][:id] ||= "tag:#{request.host_with_port}:#{klass.name.pluralize}" + options[:feed][:link] ||= polymorphic_url(new_record, :controller => options[:url_writer].controller_name) + + options[:item][:title] ||= [ :title, :subject, :headline, :name ] + options[:item][:description] ||= [ :description, :body, :content ] + options[:item][:pub_date] ||= [ :updated_at, :updated_on, :created_at, :created_on ] + options[:item][:author] ||= [ :author, :creator ] + + resource_link = lambda { |r| polymorphic_url(r, :controller => options[:url_writer].controller_name) } + + xml.instruct! + xml.feed "xml:lang" => "en-US", "xmlns" => 'http://www.w3.org/2005/Atom' do + xml.title(options[:feed][:title]) + xml.id(options[:feed][:id]) + xml.link(:rel => 'alternate', :type => 'text/html', :href => options[:feed][:link]) + xml.link(:rel => 'self', :type => 'application/atom+xml', :href => options[:feed][:self]) if options[:feed][:self] + xml.subtitle(options[:feed][:description]) if options[:feed][:description] + + for resource in resources + published_at = call_or_read(options[:item][:pub_date], resource) + + xml.entry do + xml.title(call_or_read(options[:item][:title], resource)) + xml.content(call_or_read(options[:item][:description], resource), :type => 'html') + xml.id("tag:#{request.host_with_port},#{published_at.xmlschema}:#{call_or_read(options[:item][:guid] || options[:item][:link] || resource_link, resource)}") + xml.published(published_at.xmlschema) + xml.updated((resource.respond_to?(:updated_at) ? call_or_read(options[:item][:pub_date] || :updated_at, resource) : published_at).xmlschema) + xml.link(:rel => 'alternate', :type => 'text/html', :href => call_or_read(options[:item][:link] || options[:item][:guid] || resource_link, resource)) + + if author = call_or_read(options[:item][:author], resource) + xml.author do + xml.name() + end + end + end + end + end + end + end +end diff --git a/backup.rails2.3/plugins/resource_feeder/lib/resource_feeder/common.rb b/backup.rails2.3/plugins/resource_feeder/lib/resource_feeder/common.rb new file mode 100644 index 00000000..383b965e --- /dev/null +++ b/backup.rails2.3/plugins/resource_feeder/lib/resource_feeder/common.rb @@ -0,0 +1,24 @@ +module ResourceFeeder + module Common + private + def call_or_read(procedure_or_attributes, resource) + case procedure_or_attributes + when nil + raise ArgumentError, "WTF is nil here? #{resource.inspect}" + when Array + attributes = procedure_or_attributes + if attr = attributes.select { |a| resource.respond_to?(a) }.first + resource.send attr + end + when Symbol + attribute = procedure_or_attributes + resource.send(attribute) + when Proc + procedure = procedure_or_attributes + procedure.call(resource) + else + raise ArgumentError, "WTF is #{procedure_or_attributes.inspect} here? #{resource.inspect}" + end + end + end +end diff --git a/backup.rails2.3/plugins/resource_feeder/lib/resource_feeder/rss.rb b/backup.rails2.3/plugins/resource_feeder/lib/resource_feeder/rss.rb new file mode 100644 index 00000000..d3fa56d7 --- /dev/null +++ b/backup.rails2.3/plugins/resource_feeder/lib/resource_feeder/rss.rb @@ -0,0 +1,68 @@ +require 'resource_feeder/common' + +module ResourceFeeder + module Rss + include ResourceFeeder::Common + include ActionController::Routing + extend self + + def render_rss_feed_for(resources, options = {}) + render :text => rss_feed_for(resources, options), :content_type => Mime::RSS + end + + def rss_feed_for(resources, options = {}) + xml = Builder::XmlMarkup.new(:indent => 2) + + options[:feed] ||= {} + options[:item] ||= {} + options[:url_writer] ||= self + + if options[:class] || resources.first + klass = options[:class] || resources.first.class + new_record = klass.new + else + options[:feed] = { :title => "Empty", :link => "http://example.com" } + end + use_content_encoded = options[:item].has_key?(:content_encoded) + + options[:feed][:title] ||= klass.name.pluralize + options[:feed][:link] ||= polymorphic_url(new_record, :controller => options[:url_writer].controller_name) + options[:feed][:language] ||= "en-us" + options[:feed][:ttl] ||= "40" + + options[:item][:title] ||= [ :title, :subject, :headline, :name ] + options[:item][:description] ||= [ :description, :body, :content ] + options[:item][:pub_date] ||= [ :updated_at, :updated_on, :created_at, :created_on ] + + resource_link = lambda { |r| polymorphic_url(r, :controller => options[:url_writer].controller_name) } + + rss_root_attributes = { :version => 2.0 } + rss_root_attributes.merge!("xmlns:content" => "http://purl.org/rss/1.0/modules/content/") if use_content_encoded + + xml.instruct! + + xml.rss(rss_root_attributes) do + xml.channel do + xml.title(options[:feed][:title]) + xml.link(options[:feed][:link]) + xml.description(options[:feed][:description]) if options[:feed][:description] + xml.language(options[:feed][:language]) + xml.ttl(options[:feed][:ttl]) + + for resource in resources + xml.item do + xml.title(call_or_read(options[:item][:title], resource)) + xml.description(call_or_read(options[:item][:description], resource)) + if use_content_encoded then + xml.content(:encoded) { xml.cdata!(call_or_read(options[:item][:content_encoded], resource)) } + end + xml.pubDate(call_or_read(options[:item][:pub_date], resource).to_s(:rfc822)) + xml.guid(call_or_read(options[:item][:guid] || options[:item][:link] || resource_link, resource)) + xml.link(call_or_read(options[:item][:link] || options[:item][:guid] || resource_link, resource)) + end + end + end + end + end + end +end diff --git a/backup.rails2.3/plugins/resource_feeder/test/atom_feed_test.rb b/backup.rails2.3/plugins/resource_feeder/test/atom_feed_test.rb new file mode 100644 index 00000000..3112da47 --- /dev/null +++ b/backup.rails2.3/plugins/resource_feeder/test/atom_feed_test.rb @@ -0,0 +1,85 @@ +require File.dirname(__FILE__) + '/test_helper' +class AtomFeedTest < Test::Unit::TestCase + attr_reader :request + + def setup + @request = OpenStruct.new + @request.host_with_port = 'example.com' + @records = Array.new(5).fill(Post.new) + @records.each &:save + end + + def test_default_atom_feed + atom_feed_for @records + + assert_select 'feed' do + assert_select '>title', 'Posts' + assert_select '>id', "tag:#{request.host_with_port}:Posts" + assert_select '>link' do + assert_select "[rel='alternate']" + assert_select "[type='text/html']" + assert_select "[href='http://example.com/posts']" + end + assert_select 'entry', 5 do + assert_select 'title', :text => 'feed title (title)' + assert_select "content[type='html']", '<p>feed description (description)</p>' + assert_select 'id', "tag:#{request.host_with_port},#{@records.first.created_at.xmlschema}:#{'http://example.com/posts/1'}" + assert_select 'published', @records.first.created_at.xmlschema + assert_select 'updated', @records.first.created_at.xmlschema + assert_select 'link' do + assert_select "[rel='alternate']" + assert_select "[type='text/html']" + assert_select "[href='http://example.com/posts/1']" + end + end + end + end + + def test_should_allow_custom_feed_options + atom_feed_for @records, :feed => { :title => 'Custom Posts', :link => '/posts', :description => 'stuff', :self => '/posts.atom' } + + assert_select 'feed>title', 'Custom Posts' + assert_select "feed>link[href='/posts']" + assert_select 'feed>subtitle', 'stuff' + assert_select 'feed>link' do + assert_select "[rel='self']" + assert_select "[type='application/atom+xml']" + assert_select "[href='/posts.atom']" + end + end + + def test_should_allow_custom_item_attributes + atom_feed_for @records, :item => { :title => :name, :description => :body, :pub_date => :create_date, :link => :id } + + assert_select 'entry', 5 do + assert_select 'title', :text => 'feed title (name)' + assert_select "content[type='html']", '<p>feed description (body)</p>' + assert_select 'published', (@records.first.created_at - 5.minutes).xmlschema + assert_select 'updated', (@records.first.created_at - 5.minutes).xmlschema + assert_select 'id', "tag:#{request.host_with_port},#{(@records.first.created_at - 5.minutes).xmlschema}:1" + assert_select 'link' do + assert_select "[rel='alternate']" + assert_select "[type='text/html']" + assert_select "[href='1']" + end + end + end + + def test_should_allow_custom_item_attribute_blocks + atom_feed_for @records, :item => { :title => lambda { |r| r.name }, :description => lambda { |r| r.body }, :pub_date => lambda { |r| r.create_date }, + :link => lambda { |r| "/#{r.created_at.to_i}" }, :guid => lambda { |r| r.created_at.to_i } } + + assert_select 'entry', 5 do + assert_select 'title', :text => 'feed title (name)' + assert_select "content[type='html']", '<p>feed description (body)</p>' + assert_select 'published', (@records.first.created_at - 5.minutes).xmlschema + assert_select 'updated', (@records.first.created_at - 5.minutes).xmlschema + assert_select 'id', /:\d+$/ + assert_select 'link' do + assert_select "[rel='alternate']" + assert_select "[type='text/html']" + assert_select "[href=?]", /^\/\d+$/ + end + end + end +end diff --git a/backup.rails2.3/plugins/resource_feeder/test/rss_feed_test.rb b/backup.rails2.3/plugins/resource_feeder/test/rss_feed_test.rb new file mode 100644 index 00000000..90525baf --- /dev/null +++ b/backup.rails2.3/plugins/resource_feeder/test/rss_feed_test.rb @@ -0,0 +1,86 @@ +require File.dirname(__FILE__) + '/test_helper' +class RssFeedTest < Test::Unit::TestCase + def setup + @records = Array.new(5).fill(Post.new) + @records.each &:save + end + + def test_default_rss_feed + rss_feed_for @records + + assert_select 'rss[version="2.0"]' do + assert_select 'channel' do + assert_select '>title', 'Posts' + assert_select '>link', 'http://example.com/posts' + assert_select 'language', 'en-us' + assert_select 'ttl', '40' + end + assert_select 'item', 5 do + assert_select 'title', :text => 'feed title (title)' + assert_select 'description', '<p>feed description (description)</p>' + %w(guid link).each do |node| + assert_select node, 'http://example.com/posts/1' + end + assert_select 'pubDate', @records.first.created_at.to_s(:rfc822) + end + end + end + + def test_should_allow_custom_feed_options + rss_feed_for @records, :feed => { :title => 'Custom Posts', :link => '/posts', :description => 'stuff', :language => 'en-gb', :ttl => '80' } + + assert_select 'channel>title', 'Custom Posts' + assert_select 'channel>link', '/posts' + assert_select 'channel>description', 'stuff' + assert_select 'channel>language', 'en-gb' + assert_select 'channel>ttl', '80' + end + + def test_should_allow_custom_item_attributes + rss_feed_for @records, :item => { :title => :name, :description => :body, :pub_date => :create_date, :link => :id } + + assert_select 'item', 5 do + assert_select 'title', :text => 'feed title (name)' + assert_select 'description', '<p>feed description (body)</p>' + assert_select 'pubDate', (@records.first.created_at - 5.minutes).to_s(:rfc822) + assert_select 'link', '1' + assert_select 'guid', '1' + end + end + + def test_should_allow_custom_item_attribute_blocks + rss_feed_for @records, :item => { :title => lambda { |r| r.name }, :description => lambda { |r| r.body }, :pub_date => lambda { |r| r.create_date }, + :link => lambda { |r| "/#{r.created_at.to_i}" }, :guid => lambda { |r| r.created_at.to_i } } + + assert_select 'item', 5 do + assert_select 'title', :text => 'feed title (name)' + assert_select 'description', '<p>feed description (body)</p>' + assert_select 'pubDate', (@records.first.created_at - 5.minutes).to_s(:rfc822) + end + end + + # note that assert_select isnt easily able to get elements that have xml namespaces (as it thinks they are + # invalid html psuedo children), so we do some manual testing with the response body + def test_should_allow_content_encoded_for_items + rss_feed_for @records, :item => { :content_encoded => :full_html_body } + + html_content = "Here is some full content, with out any excerpts" + assert_equal 5, @response.body.scan("").size + assert_select 'item', 5 do + assert_select 'description + *', " { :content_encoded => :full_html_body } + assert_equal %[Add your form elements here, please!
+ <%- else -%> + <%- attributes.each do |attribute| -%> +
+ <%%= f.label :<%= attribute.name %> %>
+ <%%= f.<%= attribute.field_type %> :<%= attribute.name %> %>
+
| There are no <%= plural_name.humanize.downcase %> | +||||
| + <%- else -%> + <%- attributes.each do |attribute| -%> + | <%= attribute.name.titleize %> | + <%- end -%> + <%- end -%> ++ | + | + |
|---|
Add your customized markup here, please!
+<% else -%> + <%- attributes.each do |attribute| -%> ++ + <%%=h @<%= singular_name %>.<%= attribute.name %> %> +
+ <%- end -%> +<% end -%> +
+
+ EOS
+ }.freeze
+
+ class Generator # :nodoc:
+ VALID_MODES = [:static, :dynamic]
+ def initialize(source, options, view)
+ @view = view
+ @source = view.swf_path(source)
+ options = ActionView::Base.swf_default_options.merge(options)
+ options.each do |key, value|
+ options[key] = value.call(source) if value.respond_to?(:call)
+ end
+ [:html_options, :parameters, :flashvars].each do |k|
+ options[k] = convert_to_hash(options[k]).reverse_merge convert_to_hash(ActionView::Base.swf_default_options[k])
+ end
+ options.reverse_merge!(DEFAULTS)
+ options[:id] ||= source.gsub(/^.*\//, '').gsub(/\.swf$/,'')
+ options[:id] = force_to_valid_id(options[:id])
+ options[:div_id] ||= options[:id]+"_div"
+ options[:div_id] = force_to_valid_id(options[:div_id])
+ options[:width], options[:height] = options[:size].scan(/^(\d*%?)x(\d*%?)$/).first if options[:size]
+ options[:auto_install] &&= @view.swf_path(options[:auto_install])
+ options[:flashvars][:id] ||= options[:id]
+ @mode = options.delete(:mode)
+ @options = options
+ unless VALID_MODES.include? @mode
+ raise ArgumentError, "options[:mode] should be either #{VALID_MODES.join(' or ')}"
+ end
+ end
+
+ def force_to_valid_id(id)
+ id = id.gsub /[^A-Za-z0-9\-_]/, "_" # HTML id can only contain these characters
+ id = "swf_" + id unless id =~ /^[A-Z]/i # HTML id must start with alpha
+ id
+ end
+
+ def generate(&block)
+ if block_given?
+ @options[:alt] = @view.capture(&block)
+ if Rails::VERSION::STRING >= "3.0"
+ send(@mode)
+ elsif Rails::VERSION::STRING < "2.2"
+ @view.concat(send(@mode), block.binding)
+ else
+ @view.concat(send(@mode))
+ end
+ else
+ send(@mode)
+ end
+ end
+
+ private
+ CONCAT = ActiveSupport.const_defined?(:SafeBuffer) ? :safe_concat : :concat
+ def convert_to_hash(s)
+ case s
+ when Hash
+ s
+ when nil
+ {}
+ when String
+ s.split("&").inject({}) do |h, kvp|
+ key, value = kvp.split("=")
+ h[key.to_sym] = CGI::unescape(value)
+ h
+ end
+ else
+ raise ArgumentError, "#{s} should be a Hash, a String or nil"
+ end
+ end
+
+ def convert_to_string(h)
+ h.map do |key_value|
+ key_value.map{|val| CGI::escape(val.to_s)}.join("=")
+ end.join("&")
+ end
+
+ def static
+ param_list = @options[:parameters].map{|k,v| %() }.join("\n")
+ param_list += %(\n) unless @options[:flashvars].empty?
+ html_options = @options[:html_options].map{|k,v| %(#{k}="#{v}")}.join(" ")
+ r = @view.javascript_tag(
+ %(swfobject.registerObject("#{@options[:id]}_container", "#{@options[:flash_version]}", #{@options[:auto_install].to_json});)
+ )
+ r.send CONCAT, <<-"EOS".strip
+
+ EOS
+ r << @view.javascript_tag(extend_js) if @options[:javascript_class]
+ r.send CONCAT, library_check
+ r
+ end
+
+ def dynamic
+ @options[:html_options] = @options[:html_options].merge(:id => @options[:id])
+ @options[:parameters] = @options[:parameters].dup # don't modify the original parameters
+ args = (([@source] + @options.values_at(:div_id,:width,:height,:flash_version)).map(&:to_s) +
+ @options.values_at(:auto_install,:flashvars,:parameters,:html_options)
+ ).map(&:to_json).join(",")
+ preambule = @options[:switch_off_auto_hide_show] ? "swfobject.switchOffAutoHideShow();" : ""
+ r = @view.javascript_tag(preambule + "swfobject.embedSWF(#{args})")
+ r.send CONCAT, <<-"EOS".strip
+
+
+
+
+
++ <%= submit_tag "Save Translations" %> +
+ <% @paginated_keys.each do |key| + from_text = lookup(@from_locale, key) + to_text = lookup(@to_locale, key) + line_size = 100 + n_lines = n_lines(from_text, line_size) + field_name = "key[#{key}]" + %> ++ <%= simple_format(h(from_text)) %> +
+ <% end %> ++ <% if n_lines > 1 %> + <%= text_area_tag(field_name, to_text, :size => "#{line_size}x#{n_lines}", :id => key) %> + <% else %> + <%= text_field_tag(field_name, to_text, :size => line_size, :id => key) %> + <% end %> +
+
+
+ <%= link_to_function 'Auto Translate', "getGoogleTranslation('#{key}', \"#{escape_javascript(from_text)}\", '#{@from_locale}', '#{@to_locale}')", :style => 'padding: 0; margin: 0;' %>
+
+ Key:<%=h key %>
+ <% if @files[key] %>
+ File:<%= @files[key].join("
") %>
+ <% end %>
+
+
+ <%= submit_tag "Save Translations" %> +
+