]> source.dussan.org Git - redmine.git/commitdiff
Merged rails-3.2 branch.
authorJean-Philippe Lang <jp_lang@yahoo.fr>
Wed, 25 Apr 2012 17:17:49 +0000 (17:17 +0000)
committerJean-Philippe Lang <jp_lang@yahoo.fr>
Wed, 25 Apr 2012 17:17:49 +0000 (17:17 +0000)
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@9528 e93f8b46-1217-0410-a6f0-8f06a7374b81

457 files changed:
.gitignore
.hgignore
Gemfile
Rakefile
app/controllers/application_controller.rb
app/controllers/messages_controller.rb
app/controllers/repositories_controller.rb
app/controllers/watchers_controller.rb
app/controllers/wiki_controller.rb
app/helpers/application_helper.rb
app/helpers/wiki_helper.rb
app/models/custom_field.rb
app/models/issue.rb
app/models/mail_handler.rb
app/models/mailer.rb
app/models/project.rb
app/models/repository.rb
app/models/role.rb
app/models/tracker.rb
app/views/account/login.html.erb
app/views/account/lost_password.html.erb
app/views/account/password_recovery.html.erb
app/views/account/register.html.erb
app/views/activities/index.html.erb
app/views/admin/_no_data.html.erb
app/views/admin/projects.html.erb
app/views/attachments/diff.html.erb
app/views/auth_sources/edit.html.erb
app/views/auth_sources/new.html.erb
app/views/boards/edit.html.erb
app/views/boards/new.html.erb
app/views/boards/show.html.erb
app/views/calendars/show.html.erb
app/views/common/feed.atom.builder
app/views/custom_fields/edit.html.erb
app/views/custom_fields/new.html.erb
app/views/documents/edit.html.erb
app/views/documents/index.html.erb
app/views/documents/new.html.erb
app/views/documents/show.html.erb
app/views/enumerations/destroy.html.erb
app/views/enumerations/edit.html.erb
app/views/enumerations/new.html.erb
app/views/files/new.html.erb
app/views/gantts/show.html.erb
app/views/groups/_general.html.erb
app/views/groups/_memberships.html.erb
app/views/groups/_users.html.erb
app/views/groups/new.html.erb
app/views/issue_categories/destroy.html.erb
app/views/issue_statuses/edit.html.erb
app/views/issue_statuses/new.html.erb
app/views/issues/_action_menu.html.erb
app/views/issues/_attributes.html.erb
app/views/issues/_edit.html.erb
app/views/issues/_form.html.erb
app/views/issues/_list.html.erb
app/views/issues/_list_simple.html.erb
app/views/issues/bulk_edit.html.erb
app/views/issues/destroy.html.erb
app/views/issues/index.html.erb
app/views/issues/new.html.erb
app/views/journals/_notes_form.html.erb
app/views/layouts/base.html.erb
app/views/messages/edit.html.erb
app/views/messages/new.html.erb
app/views/messages/show.html.erb
app/views/my/account.html.erb
app/views/my/destroy.html.erb
app/views/my/page_layout.html.erb
app/views/my/password.html.erb
app/views/news/edit.html.erb
app/views/news/index.html.erb
app/views/news/new.html.erb
app/views/news/show.html.erb
app/views/projects/_edit.html.erb
app/views/projects/copy.html.erb
app/views/projects/destroy.html.erb
app/views/projects/index.html.erb
app/views/projects/new.html.erb
app/views/projects/settings/_activities.html.erb
app/views/projects/settings/_modules.html.erb
app/views/projects/show.html.erb
app/views/queries/_filters.html.erb
app/views/queries/edit.html.erb
app/views/queries/new.html.erb
app/views/repositories/_navigation.html.erb
app/views/repositories/_revisions.html.erb
app/views/repositories/committers.html.erb
app/views/repositories/diff.html.erb
app/views/repositories/edit.html.erb
app/views/repositories/new.html.erb
app/views/repositories/revision.html.erb
app/views/repositories/revisions.html.erb
app/views/roles/edit.html.erb
app/views/roles/new.html.erb
app/views/roles/permissions.html.erb
app/views/search/index.html.erb
app/views/settings/_authentication.html.erb
app/views/settings/_display.html.erb
app/views/settings/_general.html.erb
app/views/settings/_issues.html.erb
app/views/settings/_mail_handler.html.erb
app/views/settings/_notifications.html.erb
app/views/settings/_projects.html.erb
app/views/settings/_repositories.html.erb
app/views/settings/plugin.html.erb
app/views/timelog/_date_range.html.erb
app/views/timelog/_list.html.erb
app/views/timelog/bulk_edit.html.erb
app/views/timelog/edit.html.erb
app/views/timelog/index.html.erb
app/views/timelog/new.html.erb
app/views/timelog/report.html.erb
app/views/trackers/edit.html.erb
app/views/trackers/new.html.erb
app/views/users/_general.html.erb
app/views/users/_groups.html.erb
app/views/users/_memberships.html.erb
app/views/users/_preferences.html.erb
app/views/users/index.html.erb
app/views/users/new.html.erb
app/views/versions/_issue_counts.html.erb
app/views/versions/_new_modal.html.erb
app/views/versions/edit.html.erb
app/views/versions/index.html.erb
app/views/versions/new.html.erb
app/views/versions/show.html.erb
app/views/watchers/_new.html.erb
app/views/wiki/_sidebar.html.erb
app/views/wiki/destroy.html.erb
app/views/wiki/edit.html.erb
app/views/wiki/history.html.erb
app/views/wiki/rename.html.erb
app/views/wiki/show.html.erb
app/views/wikis/destroy.html.erb
app/views/workflows/copy.html.erb
app/views/workflows/edit.html.erb
config.ru [new file with mode: 0644]
config/application.rb [new file with mode: 0644]
config/boot.rb
config/environment.rb
config/environments/development.rb
config/environments/production.rb
config/environments/test.rb
config/initializers/10-patches.rb
config/initializers/20-mime_types.rb
config/initializers/30-redmine.rb
config/routes.rb
db/migrate/20120422150750_change_repositories_to_full_sti.rb [new file with mode: 0644]
extra/sample_plugin/README
extra/sample_plugin/app/views/example/say_goodbye.html.erb
extra/sample_plugin/app/views/example/say_hello.html.erb
extra/sample_plugin/config/routes.rb [new file with mode: 0644]
extra/sample_plugin/init.rb
lib/generators/redmine_plugin/USAGE
lib/generators/redmine_plugin/redmine_plugin_generator.rb
lib/generators/redmine_plugin/templates/init.rb.erb
lib/generators/redmine_plugin/templates/routes.rb [new file with mode: 0644]
lib/generators/redmine_plugin_controller/USAGE
lib/generators/redmine_plugin_controller/redmine_plugin_controller_generator.rb
lib/generators/redmine_plugin_controller/templates/controller.rb.erb
lib/generators/redmine_plugin_controller/templates/functional_test.rb.erb
lib/generators/redmine_plugin_controller/templates/helper.rb.erb
lib/generators/redmine_plugin_controller/templates/view.html.erb
lib/generators/redmine_plugin_model/USAGE
lib/generators/redmine_plugin_model/redmine_plugin_model_generator.rb
lib/generators/redmine_plugin_model/templates/fixtures.yml [deleted file]
lib/generators/redmine_plugin_model/templates/migration.rb.erb [deleted file]
lib/generators/redmine_plugin_model/templates/model.rb.erb
lib/generators/redmine_plugin_model/templates/unit_test.rb.erb
lib/redmine.rb
lib/redmine/ciphering.rb
lib/redmine/core_ext/active_record.rb
lib/redmine/core_ext/string.rb
lib/redmine/hook.rb
lib/redmine/plugin.rb
lib/redmine/scm/adapters/cvs_adapter.rb
lib/redmine/themes.rb
lib/redmine/utils.rb
lib/redmine/version.rb
lib/redmine/views/api_template_handler.rb
lib/redmine/views/builders/xml.rb
lib/redmine/views/labelled_form_builder.rb
lib/redmine/views/my_page/block.rb
lib/redmine/wiki_formatting.rb
lib/tasks/deprecated.rake
lib/tasks/initializers.rake
lib/tasks/migrate_plugins.rake [deleted file]
lib/tasks/plugins.rake [deleted file]
lib/tasks/redmine.rake
lib/vendor/tmail-1.2.7/tmail.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/Makefile [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/address.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/attachments.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/base64.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/compat.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/config.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/core_extensions.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/encode.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/header.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/index.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/interface.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/loader.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/mail.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/mailbox.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/main.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/mbox.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/net.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/obsolete.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/parser.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/parser.y [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/port.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/quoting.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/require_arch.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/scanner.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/scanner_r.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/stringio.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/utils.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/COPYING [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/README [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/big5freq.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/big5prober.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/chardistribution.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/charsetgroupprober.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/charsetprober.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/codingstatemachine.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/constants.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/escprober.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/escsm.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/eucjpprober.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/euckrfreq.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/euckrprober.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/euctwfreq.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/euctwprober.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/gb2312freq.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/gb2312prober.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/hebrewprober.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/jisfreq.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/jpcntx.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/langbulgarianmodel.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/langcyrillicmodel.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/langgreekmodel.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/langhebrewmodel.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/langhungarianmodel.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/langthaimodel.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/latin1prober.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/mbcharsetprober.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/mbcsgroupprober.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/mbcssm.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/sbcharsetprober.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/sbcsgroupprober.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/sjisprober.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/universaldetector.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/utf8prober.rb [new file with mode: 0644]
lib/vendor/tmail-1.2.7/tmail/version.rb [new file with mode: 0644]
lib/vendor/tmail.rb [new file with mode: 0644]
plugins/README [new file with mode: 0644]
public/javascripts/rails.js [new file with mode: 0644]
script/about [deleted file]
script/breakpointer [deleted file]
script/console [deleted file]
script/dbconsole [deleted file]
script/destroy [deleted file]
script/generate [deleted file]
script/performance/benchmarker [deleted file]
script/performance/profiler [deleted file]
script/performance/request [deleted file]
script/plugin [deleted file]
script/process/inspector [deleted file]
script/process/reaper [deleted file]
script/process/spawner [deleted file]
script/process/spinner [deleted file]
script/rails [new file with mode: 0644]
script/runner [deleted file]
script/server [deleted file]
test/fixtures/custom_fields.yml
test/fixtures/repositories.yml
test/functional/issues_controller_test.rb
test/functional/queries_controller_test.rb
test/functional/repositories_subversion_controller_test.rb
test/functional/time_entry_reports_controller_test.rb
test/functional/timelog_controller_test.rb
test/functional/watchers_controller_test.rb
test/functional/wiki_controller_test.rb
test/integration/api_test/issue_relations_test.rb
test/integration/api_test/memberships_test.rb
test/integration/issues_test.rb
test/integration/projects_test.rb
test/integration/routing/activities_test.rb
test/integration/routing/repositories_test.rb
test/integration/routing/wiki_test.rb
test/test_helper.rb
test/unit/custom_field_test.rb
test/unit/helpers/application_helper_test.rb
test/unit/issue_test.rb
test/unit/lib/redmine/hook_test.rb
test/unit/lib/redmine/wiki_formatting/macros_test.rb
test/unit/mailer_test.rb
test/unit/user_test.rb
test/unit/watcher_test.rb
vendor/plugins/acts_as_versioned/lib/acts_as_versioned.rb
vendor/plugins/awesome_nested_set/.autotest [new file with mode: 0644]
vendor/plugins/awesome_nested_set/.travis.yml [new file with mode: 0644]
vendor/plugins/awesome_nested_set/CHANGELOG [new file with mode: 0644]
vendor/plugins/awesome_nested_set/MIT-LICENSE
vendor/plugins/awesome_nested_set/README.rdoc
vendor/plugins/awesome_nested_set/Rakefile
vendor/plugins/awesome_nested_set/awesome_nested_set.gemspec
vendor/plugins/awesome_nested_set/init.rb
vendor/plugins/awesome_nested_set/lib/awesome_nested_set.rb
vendor/plugins/awesome_nested_set/lib/awesome_nested_set/awesome_nested_set.rb [new file with mode: 0644]
vendor/plugins/awesome_nested_set/lib/awesome_nested_set/compatability.rb [deleted file]
vendor/plugins/awesome_nested_set/lib/awesome_nested_set/helper.rb
vendor/plugins/awesome_nested_set/lib/awesome_nested_set/named_scope.rb [deleted file]
vendor/plugins/awesome_nested_set/lib/awesome_nested_set/version.rb [new file with mode: 0644]
vendor/plugins/awesome_nested_set/spec/awesome_nested_set/helper_spec.rb [new file with mode: 0644]
vendor/plugins/awesome_nested_set/spec/awesome_nested_set_spec.rb [new file with mode: 0644]
vendor/plugins/awesome_nested_set/spec/db/database.yml [new file with mode: 0644]
vendor/plugins/awesome_nested_set/spec/db/schema.rb [new file with mode: 0644]
vendor/plugins/awesome_nested_set/spec/fixtures/brokens.yml [new file with mode: 0644]
vendor/plugins/awesome_nested_set/spec/fixtures/categories.yml [new file with mode: 0644]
vendor/plugins/awesome_nested_set/spec/fixtures/departments.yml [new file with mode: 0644]
vendor/plugins/awesome_nested_set/spec/fixtures/notes.yml [new file with mode: 0644]
vendor/plugins/awesome_nested_set/spec/fixtures/things.yml [new file with mode: 0644]
vendor/plugins/awesome_nested_set/spec/spec_helper.rb [new file with mode: 0644]
vendor/plugins/awesome_nested_set/spec/support/models.rb [new file with mode: 0644]
vendor/plugins/engines/.gitignore [deleted file]
vendor/plugins/engines/CHANGELOG [deleted file]
vendor/plugins/engines/MIT-LICENSE [deleted file]
vendor/plugins/engines/README [deleted file]
vendor/plugins/engines/Rakefile [deleted file]
vendor/plugins/engines/about.yml [deleted file]
vendor/plugins/engines/boot.rb [deleted file]
vendor/plugins/engines/generators/plugin_migration/USAGE [deleted file]
vendor/plugins/engines/generators/plugin_migration/plugin_migration_generator.rb [deleted file]
vendor/plugins/engines/generators/plugin_migration/templates/plugin_migration.erb [deleted file]
vendor/plugins/engines/init.rb [deleted file]
vendor/plugins/engines/lib/engines.rb [deleted file]
vendor/plugins/engines/lib/engines/assets.rb [deleted file]
vendor/plugins/engines/lib/engines/plugin.rb [deleted file]
vendor/plugins/engines/lib/engines/plugin/list.rb [deleted file]
vendor/plugins/engines/lib/engines/plugin/loader.rb [deleted file]
vendor/plugins/engines/lib/engines/plugin/locator.rb [deleted file]
vendor/plugins/engines/lib/engines/plugin/migrator.rb [deleted file]
vendor/plugins/engines/lib/engines/rails_extensions/asset_helpers.rb [deleted file]
vendor/plugins/engines/lib/engines/rails_extensions/dependencies.rb [deleted file]
vendor/plugins/engines/lib/engines/rails_extensions/form_tag_helpers.rb [deleted file]
vendor/plugins/engines/lib/engines/rails_extensions/migrations.rb [deleted file]
vendor/plugins/engines/lib/engines/rails_extensions/rails.rb [deleted file]
vendor/plugins/engines/lib/engines/testing.rb [deleted file]
vendor/plugins/engines/lib/tasks/engines.rake [deleted file]
vendor/plugins/engines/test/app/controllers/app_and_plugin_controller.rb [deleted file]
vendor/plugins/engines/test/app/controllers/namespace/app_and_plugin_controller.rb [deleted file]
vendor/plugins/engines/test/app/helpers/mail_helper.rb [deleted file]
vendor/plugins/engines/test/app/models/app_and_plugin_model.rb [deleted file]
vendor/plugins/engines/test/app/models/notify_mail.rb [deleted file]
vendor/plugins/engines/test/app/things/thing.rb [deleted file]
vendor/plugins/engines/test/app/views/app_and_plugin/a_view.html.erb [deleted file]
vendor/plugins/engines/test/app/views/namespace/app_and_plugin/a_view.html.erb [deleted file]
vendor/plugins/engines/test/app/views/notify_mail/implicit_multipart.text.html.erb [deleted file]
vendor/plugins/engines/test/app/views/notify_mail/implicit_multipart.text.plain.erb [deleted file]
vendor/plugins/engines/test/app/views/notify_mail/multipart_html.html.erb [deleted file]
vendor/plugins/engines/test/app/views/notify_mail/multipart_plain.html.erb [deleted file]
vendor/plugins/engines/test/app/views/notify_mail/signup.text.plain.erb [deleted file]
vendor/plugins/engines/test/app/views/plugin_mail/mail_from_plugin_with_application_template.text.plain.erb [deleted file]
vendor/plugins/engines/test/app/views/plugin_mail/multipart_from_plugin_with_application_template_plain.html.erb [deleted file]
vendor/plugins/engines/test/functional/controller_loading_test.rb [deleted file]
vendor/plugins/engines/test/functional/exception_notification_compatibility_test.rb [deleted file]
vendor/plugins/engines/test/functional/locale_loading_test.rb [deleted file]
vendor/plugins/engines/test/functional/routes_test.rb [deleted file]
vendor/plugins/engines/test/functional/view_helpers_test.rb [deleted file]
vendor/plugins/engines/test/functional/view_loading_test.rb [deleted file]
vendor/plugins/engines/test/lib/app_and_plugin_lib_model.rb [deleted file]
vendor/plugins/engines/test/lib/engines_test_helper.rb [deleted file]
vendor/plugins/engines/test/lib/render_information.rb [deleted file]
vendor/plugins/engines/test/plugins/alpha_plugin/app/controllers/alpha_plugin_controller.rb [deleted file]
vendor/plugins/engines/test/plugins/alpha_plugin/app/controllers/app_and_plugin_controller.rb [deleted file]
vendor/plugins/engines/test/plugins/alpha_plugin/app/controllers/namespace/alpha_plugin_controller.rb [deleted file]
vendor/plugins/engines/test/plugins/alpha_plugin/app/controllers/namespace/app_and_plugin_controller.rb [deleted file]
vendor/plugins/engines/test/plugins/alpha_plugin/app/controllers/namespace/shared_plugin_controller.rb [deleted file]
vendor/plugins/engines/test/plugins/alpha_plugin/app/controllers/shared_plugin_controller.rb [deleted file]
vendor/plugins/engines/test/plugins/alpha_plugin/app/models/alpha_plugin_model.rb [deleted file]
vendor/plugins/engines/test/plugins/alpha_plugin/app/models/app_and_plugin_model.rb [deleted file]
vendor/plugins/engines/test/plugins/alpha_plugin/app/models/shared_plugin_model.rb [deleted file]
vendor/plugins/engines/test/plugins/alpha_plugin/app/views/alpha_plugin/a_view.html.erb [deleted file]
vendor/plugins/engines/test/plugins/alpha_plugin/app/views/app_and_plugin/a_view.html.erb [deleted file]
vendor/plugins/engines/test/plugins/alpha_plugin/app/views/layouts/plugin_layout.erb [deleted file]
vendor/plugins/engines/test/plugins/alpha_plugin/app/views/namespace/alpha_plugin/a_view.html.erb [deleted file]
vendor/plugins/engines/test/plugins/alpha_plugin/app/views/namespace/app_and_plugin/a_view.html.erb [deleted file]
vendor/plugins/engines/test/plugins/alpha_plugin/app/views/namespace/shared_plugin/a_view.html.erb [deleted file]
vendor/plugins/engines/test/plugins/alpha_plugin/app/views/shared_plugin/a_view.html.erb [deleted file]
vendor/plugins/engines/test/plugins/alpha_plugin/lib/alpha_plugin_lib_model.rb [deleted file]
vendor/plugins/engines/test/plugins/alpha_plugin/lib/app_and_plugin_lib_model.rb [deleted file]
vendor/plugins/engines/test/plugins/alpha_plugin/locales/en.yml [deleted file]
vendor/plugins/engines/test/plugins/beta_plugin/app/controllers/app_and_plugin_controller.rb [deleted file]
vendor/plugins/engines/test/plugins/beta_plugin/app/controllers/namespace/shared_plugin_controller.rb [deleted file]
vendor/plugins/engines/test/plugins/beta_plugin/app/controllers/shared_plugin_controller.rb [deleted file]
vendor/plugins/engines/test/plugins/beta_plugin/app/models/shared_plugin_model.rb [deleted file]
vendor/plugins/engines/test/plugins/beta_plugin/app/views/namespace/shared_plugin/a_view.html.erb [deleted file]
vendor/plugins/engines/test/plugins/beta_plugin/app/views/shared_plugin/a_view.html.erb [deleted file]
vendor/plugins/engines/test/plugins/beta_plugin/init.rb [deleted file]
vendor/plugins/engines/test/plugins/beta_plugin/locales/en.yml [deleted file]
vendor/plugins/engines/test/plugins/not_a_plugin/public/should_not_be_copied.txt [deleted file]
vendor/plugins/engines/test/plugins/test_assets/app/controllers/assets_controller.rb [deleted file]
vendor/plugins/engines/test/plugins/test_assets/app/views/assets/index.html.erb [deleted file]
vendor/plugins/engines/test/plugins/test_assets/app/views/layouts/assets.html.erb [deleted file]
vendor/plugins/engines/test/plugins/test_assets/init.rb [deleted file]
vendor/plugins/engines/test/plugins/test_assets/public/file.txt [deleted file]
vendor/plugins/engines/test/plugins/test_assets/public/subfolder/file_in_subfolder.txt [deleted file]
vendor/plugins/engines/test/plugins/test_assets_with_assets_directory/assets/file.txt [deleted file]
vendor/plugins/engines/test/plugins/test_assets_with_assets_directory/assets/subfolder/file_in_subfolder.txt [deleted file]
vendor/plugins/engines/test/plugins/test_assets_with_assets_directory/init.rb [deleted file]
vendor/plugins/engines/test/plugins/test_assets_with_no_subdirectory/assets/file.txt [deleted file]
vendor/plugins/engines/test/plugins/test_assets_with_no_subdirectory/init.rb [deleted file]
vendor/plugins/engines/test/plugins/test_code_mixing/app/things/thing.rb [deleted file]
vendor/plugins/engines/test/plugins/test_code_mixing/init.rb [deleted file]
vendor/plugins/engines/test/plugins/test_load_path/init.rb [deleted file]
vendor/plugins/engines/test/plugins/test_migration/db/migrate/001_create_tests.rb [deleted file]
vendor/plugins/engines/test/plugins/test_migration/db/migrate/002_create_others.rb [deleted file]
vendor/plugins/engines/test/plugins/test_migration/db/migrate/003_create_extras.rb [deleted file]
vendor/plugins/engines/test/plugins/test_migration/init.rb [deleted file]
vendor/plugins/engines/test/plugins/test_plugin_mailing/app/models/plugin_mail.rb [deleted file]
vendor/plugins/engines/test/plugins/test_plugin_mailing/app/views/plugin_mail/mail_from_plugin.erb [deleted file]
vendor/plugins/engines/test/plugins/test_plugin_mailing/app/views/plugin_mail/multipart_from_plugin_html.html.erb [deleted file]
vendor/plugins/engines/test/plugins/test_plugin_mailing/app/views/plugin_mail/multipart_from_plugin_plain.html.erb [deleted file]
vendor/plugins/engines/test/plugins/test_plugin_mailing/app/views/plugin_mail/multipart_from_plugin_with_application_template_html.html.erb [deleted file]
vendor/plugins/engines/test/plugins/test_plugin_mailing/app/views/plugin_mail/multipart_from_plugin_with_application_template_plain.html.erb [deleted file]
vendor/plugins/engines/test/plugins/test_plugin_mailing/init.rb [deleted file]
vendor/plugins/engines/test/plugins/test_routing/app/controllers/namespace/test_routing_controller.rb [deleted file]
vendor/plugins/engines/test/plugins/test_routing/app/controllers/test_routing_controller.rb [deleted file]
vendor/plugins/engines/test/plugins/test_routing/config/routes.rb [deleted file]
vendor/plugins/engines/test/plugins/test_routing/init.rb [deleted file]
vendor/plugins/engines/test/plugins/test_testing/app/README.txt [deleted file]
vendor/plugins/engines/test/plugins/test_testing/init.rb [deleted file]
vendor/plugins/engines/test/plugins/test_testing/test/fixtures/testing_fixtures.yml [deleted file]
vendor/plugins/engines/test/plugins/test_testing/test/unit/override_test.rb [deleted file]
vendor/plugins/engines/test/unit/action_mailer_test.rb [deleted file]
vendor/plugins/engines/test/unit/arbitrary_code_mixing_test.rb [deleted file]
vendor/plugins/engines/test/unit/assets_test.rb [deleted file]
vendor/plugins/engines/test/unit/backwards_compat_test.rb [deleted file]
vendor/plugins/engines/test/unit/load_path_test.rb [deleted file]
vendor/plugins/engines/test/unit/migration_test.rb [deleted file]
vendor/plugins/engines/test/unit/model_and_lib_test.rb [deleted file]
vendor/plugins/engines/test/unit/plugins_test.rb [deleted file]
vendor/plugins/engines/test/unit/test_testing/override_test.rb [deleted file]
vendor/plugins/engines/test/unit/testing_test.rb [deleted file]
vendor/plugins/open_id_authentication/CHANGELOG
vendor/plugins/open_id_authentication/README
vendor/plugins/open_id_authentication/init.rb
vendor/plugins/open_id_authentication/lib/open_id_authentication.rb
vendor/plugins/prepend_engine_views/init.rb [deleted file]
vendor/plugins/prototype_legacy_helper/README.markdown [new file with mode: 0644]
vendor/plugins/prototype_legacy_helper/init.rb [new file with mode: 0644]
vendor/plugins/prototype_legacy_helper/lib/prototype_legacy_helper.rb [new file with mode: 0644]
vendor/plugins/prototype_legacy_helper/test/test_prototype_helper.rb [new file with mode: 0644]

index c90eace33cca3bcdb6bafe300639b1fe7b571af0..683c0f0548d096c1c3efe79c7467596ceb4e8d0e 100644 (file)
@@ -5,6 +5,7 @@
 /config/database.yml
 /config/email.yml
 /config/initializers/session_store.rb
+/config/initializers/secret_token.rb
 /coverage
 /db/*.db
 /db/*.sqlite3
index 3f7c70297886da4cef4f38a5061ffc694f7c3686..a84c9a82485e3f9e5f04f3c4cbe98b97563bd19d 100644 (file)
--- a/.hgignore
+++ b/.hgignore
@@ -7,6 +7,7 @@ config/configuration.yml
 config/database.yml
 config/email.yml
 config/initializers/session_store.rb
+config/initializers/secret_token.rb
 coverage
 db/*.db
 db/*.sqlite3
diff --git a/Gemfile b/Gemfile
index 5650a2cb0bd9cc23529412f9c96b18746324070f..d40f6c3228ac4c07ae83df4a5046dd7b0dd5ed19 100644 (file)
--- a/Gemfile
+++ b/Gemfile
@@ -1,10 +1,12 @@
-source :rubygems
+source 'http://rubygems.org'
 
-gem "rails", "2.3.14"
-gem "i18n", "~> 0.4.2"
+gem 'rails', '3.2.3'
+gem 'prototype-rails', '3.2.1'
+gem "i18n", "~> 0.6.0"
 gem "coderay", "~> 1.0.6"
 gem "fastercsv", "~> 1.5.0", :platforms => [:mri_18, :mingw_18, :jruby]
 gem "tzinfo", "~> 0.3.31"
+gem "builder"
 
 # Optional gem for LDAP authentication
 group :ldap do
@@ -14,6 +16,7 @@ end
 # Optional gem for OpenID authentication
 group :openid do
   gem "ruby-openid", "~> 2.1.4", :require => "openid"
+  gem "rack-openid"
 end
 
 # Optional gem for exporting the gantt to a PNG file, not supported with jruby
@@ -45,7 +48,7 @@ end
 
 platforms :mri_19, :mingw_19 do
   group :mysql do
-    gem "mysql2", "~> 0.2.7"
+    gem "mysql2", "~> 0.3.11"
   end
 end
 
@@ -69,8 +72,9 @@ group :development do
   gem "rdoc", ">= 2.4.2"
 end
 
+
 group :test do
-  gem "shoulda", "~> 2.10.3"
+  gem "shoulda"
   gem "mocha"
 end
 
index 13c7e79c7688eb705dbc3ef23579eb2ae68a8fec..5fbdf84ca155f8f2512d242635be261f3892ecab 100644 (file)
--- a/Rakefile
+++ b/Rakefile
@@ -1,15 +1,7 @@
+#!/usr/bin/env rake
 # Add your own tasks in files placed in lib/tasks ending in .rake,
-# for example lib/tasks/switchtower.rake, and they will automatically be available to Rake.
+# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
 
-require(File.join(File.dirname(__FILE__), 'config', 'boot'))
+require File.expand_path('../config/application', __FILE__)
 
-require 'rake'
-require 'rake/testtask'
-
-begin
-  require 'rdoc/task'
-rescue LoadError
-  # RDoc is not available
-end
-
-require 'tasks/rails'
+RedmineApp::Application.load_tasks
index 0ecc04fcb979d657bb41a9ea1b131d85036df4e1..17a0b9e1c5966ec129d6d369c24ac939b3529789 100644 (file)
@@ -22,9 +22,12 @@ class Unauthorized < Exception; end
 
 class ApplicationController < ActionController::Base
   include Redmine::I18n
+  
+  class_attribute :accept_api_auth_actions
+  class_attribute :accept_rss_auth_actions
+  class_attribute :model_object
 
   layout 'base'
-  exempt_from_layout 'builder', 'rsb'
 
   protect_from_forgery
   def handle_unverified_request
@@ -68,7 +71,6 @@ class ApplicationController < ActionController::Base
   end
 
   before_filter :user_setup, :check_if_login_required, :set_localization
-  filter_parameter_logging :password
 
   rescue_from ActionController::InvalidAuthenticityToken, :with => :invalid_authenticity_token
   rescue_from ::Unauthorized, :with => :deny_access
@@ -77,10 +79,6 @@ class ApplicationController < ActionController::Base
   include Redmine::MenuManager::MenuController
   helper Redmine::MenuManager::MenuHelper
 
-  Redmine::Scm::Base.all.each do |scm|
-    require_dependency "repository/#{scm.underscore}"
-  end
-
   def user_setup
     # Check the settings cache for each request
     Setting.check_cache
@@ -242,7 +240,7 @@ class ApplicationController < ActionController::Base
   end
 
   def find_model_object
-    model = self.class.read_inheritable_attribute('model_object')
+    model = self.class.model_object
     if model
       @object = model.find(params[:id])
       self.instance_variable_set('@' + controller_name.singularize, @object) if @object
@@ -252,7 +250,7 @@ class ApplicationController < ActionController::Base
   end
 
   def self.model_object(model)
-    write_inheritable_attribute('model_object', model)
+    self.model_object = model
   end
 
   # Filter for bulk issue operations
@@ -388,9 +386,9 @@ class ApplicationController < ActionController::Base
 
   def self.accept_rss_auth(*actions)
     if actions.any?
-      write_inheritable_attribute('accept_rss_auth_actions', actions)
+      self.accept_rss_auth_actions = actions
     else
-      read_inheritable_attribute('accept_rss_auth_actions') || []
+      self.accept_rss_auth_actions || []
     end
   end
 
@@ -400,9 +398,9 @@ class ApplicationController < ActionController::Base
 
   def self.accept_api_auth(*actions)
     if actions.any?
-      write_inheritable_attribute('accept_api_auth_actions', actions)
+      self.accept_api_auth_actions = actions
     else
-      read_inheritable_attribute('accept_api_auth_actions') || []
+      self.accept_api_auth_actions || []
     end
   end
 
@@ -523,26 +521,12 @@ class ApplicationController < ActionController::Base
     else
       @error_messages = objects.errors.full_messages
     end
-    render :template => 'common/error_messages.api', :status => :unprocessable_entity, :layout => false
-  end
-
-  # Overrides #default_template so that the api template
-  # is used automatically if it exists
-  def default_template(action_name = self.action_name)
-    if api_request?
-      begin
-        return self.view_paths.find_template(default_template_name(action_name), 'api')
-      rescue ::ActionView::MissingTemplate
-        # the api template was not found
-        # fallback to the default behaviour
-      end
-    end
-    super
+    render :template => 'common/error_messages.api', :status => :unprocessable_entity, :layout => nil
   end
 
-  # Overrides #pick_layout so that #render with no arguments
+  # Overrides #_include_layout? so that #render with no arguments
   # doesn't use the layout for api requests
-  def pick_layout(*args)
-    api_request? ? nil : super
+  def _include_layout?(*args)
+    api_request? ? false : super
   end
 end
index a8ef03f34cf9966791ee92c601bd9884c5d8def8..2a04641ad5dca81cc4d1a90e1bf5e559966b2f2f 100644 (file)
@@ -95,10 +95,11 @@ class MessagesController < ApplicationController
   # Delete a messages
   def destroy
     (render_403; return false) unless @message.destroyable_by?(User.current)
+    r = @message.to_param
     @message.destroy
     redirect_to @message.parent.nil? ?
       { :controller => 'boards', :action => 'show', :project_id => @project, :id => @board } :
-      { :action => 'show', :id => @message.parent, :r => @message }
+      { :action => 'show', :id => @message.parent, :r => r }
   end
 
   def quote
index 73892b1d8cacbc1862a6c5a7c52196013f1d4cf6..fb12ce373c99cd00bb3df594f144e779fa94d1be 100644 (file)
@@ -18,6 +18,7 @@
 require 'SVG/Graph/Bar'
 require 'SVG/Graph/BarHorizontal'
 require 'digest/sha1'
+require 'redmine/scm/adapters/abstract_adapter'
 
 class ChangesetNotFound < Exception; end
 class InvalidRevisionParam < Exception; end
@@ -307,8 +308,7 @@ class RepositoriesController < ApplicationController
       @repository = @project.repository
     end
     (render_404; return false) unless @repository
-    @path = params[:path].join('/') unless params[:path].nil?
-    @path ||= ''
+    @path = params[:path].is_a?(Array) ? params[:path].join('/') : params[:path].to_s
     @rev = params[:rev].blank? ? @repository.default_branch : params[:rev].to_s.strip
     @rev_to = params[:rev_to]
 
@@ -343,15 +343,15 @@ class RepositoriesController < ApplicationController
     @date_to = Date.today
     @date_from = @date_to << 11
     @date_from = Date.civil(@date_from.year, @date_from.month, 1)
-    commits_by_day = repository.changesets.count(
+    commits_by_day = Changeset.count(
                           :all, :group => :commit_date,
-                          :conditions => ["commit_date BETWEEN ? AND ?", @date_from, @date_to])
+                          :conditions => ["repository_id = ? AND commit_date BETWEEN ? AND ?", repository.id, @date_from, @date_to])
     commits_by_month = [0] * 12
     commits_by_day.each {|c| commits_by_month[c.first.to_date.months_ago] += c.last }
 
-    changes_by_day = repository.changes.count(
-                          :all, :group => :commit_date,
-                          :conditions => ["commit_date BETWEEN ? AND ?", @date_from, @date_to])
+    changes_by_day = Change.count(
+                          :all, :group => :commit_date, :include => :changeset,
+                          :conditions => ["#{Changeset.table_name}.repository_id = ? AND #{Changeset.table_name}.commit_date BETWEEN ? AND ?", repository.id, @date_from, @date_to])
     changes_by_month = [0] * 12
     changes_by_day.each {|c| changes_by_month[c.first.to_date.months_ago] += c.last }
 
@@ -384,10 +384,10 @@ class RepositoriesController < ApplicationController
   end
 
   def graph_commits_per_author(repository)
-    commits_by_author = repository.changesets.count(:all, :group => :committer)
+    commits_by_author = Changeset.count(:all, :group => :committer, :conditions => ["repository_id = ?", repository.id])
     commits_by_author.to_a.sort! {|x, y| x.last <=> y.last}
 
-    changes_by_author = repository.changes.count(:all, :group => :committer)
+    changes_by_author = Change.count(:all, :group => :committer, :include => :changeset, :conditions => ["#{Changeset.table_name}.repository_id = ?", repository.id])
     h = changes_by_author.inject({}) {|o, i| o[i.first] = i.last; o}
 
     fields = commits_by_author.collect {|r| r.first}
index 00f64702371d3075ec8046cb201cca9247e2d9f7..c4f857f985655596707d0e7d776ddbd269aea3d9 100644 (file)
@@ -109,7 +109,7 @@ private
       @watched = klass.find(params[:object_id])
       @project = @watched.project
     elsif params[:project_id]
-      @project = Project.visible.find(params[:project_id])
+      @project = Project.visible.find_by_param(params[:project_id])
     end
   rescue
     render_404
index 2f851aec9e31ca2fc1fe1334696b167004b5438d..671ab157b83cce3136e1733bd3968b3df052d2f3 100644 (file)
@@ -163,6 +163,8 @@ class WikiController < ApplicationController
     # Optimistic locking exception
     flash.now[:error] = l(:notice_locking_conflict)
     render :action => 'edit'
+  rescue ActiveRecord::RecordNotSaved
+    render :action => 'edit'
   end
 
   # rename a page
index 34f9d12859b007f47c3a68dccdb7b83c591a55b3..8310a49726499ef709cd81849d9b4f8bfe5186ed 100644 (file)
@@ -930,6 +930,9 @@ module ApplicationHelper
   def labelled_form_for(*args, &proc)
     args << {} unless args.last.is_a?(Hash)
     options = args.last
+    if args.first.is_a?(Symbol)
+      options.merge!(:as => args.shift)
+    end
     options.merge!({:builder => Redmine::Views::LabelledFormBuilder})
     form_for(*args, &proc)
   end
@@ -1060,7 +1063,7 @@ module ApplicationHelper
   # +user+ can be a User or a string that will be scanned for an email address (eg. 'joe <joe@foo.bar>')
   def avatar(user, options = { })
     if Setting.gravatar_enabled?
-      options.merge!({:ssl => (defined?(request) && request.ssl?), :default => Setting.gravatar_default})
+      options.merge!({:ssl => (request && request.ssl?), :default => Setting.gravatar_default})
       email = nil
       if user.respond_to?(:mail)
         email = user.mail
@@ -1079,7 +1082,7 @@ module ApplicationHelper
 
   # Returns the javascript tags that are included in the html layout head
   def javascript_heads
-    tags = javascript_include_tag(:defaults)
+    tags = javascript_include_tag('prototype', 'effects', 'dragdrop', 'controls', 'rails', 'application')
     unless User.current.pref.warn_on_leaving_unsaved == '0'
       tags << "\n".html_safe + javascript_tag("Event.observe(window, 'load', function(){ new WarnLeavingUnsaved('#{escape_javascript( l(:text_warn_on_leaving_unsaved) )}'); });")
     end
index 74bec74225b218e20a6a48341aeb718df022db0b..a6e38a12a00adc309a4a1ed2fbcdb7fda0950a5d 100644 (file)
@@ -21,14 +21,14 @@ module WikiHelper
 
   def wiki_page_options_for_select(pages, selected = nil, parent = nil, level = 0)
     pages = pages.group_by(&:parent) unless pages.is_a?(Hash)
-    s = ''
+    s = ''.html_safe
     if pages.has_key?(parent)
       pages[parent].each do |page|
         attrs = "value='#{page.id}'"
         attrs << " selected='selected'" if selected == page
-        indent = (level > 0) ? ('&nbsp;' * level * 2 + '&#187; ') : nil
+        indent = (level > 0) ? ('&nbsp;' * level * 2 + '&#187; ') : ''
 
-        s << "<option #{attrs}>#{indent}#{h page.pretty_title}</option>\n" +
+        s << content_tag('option', (indent + h(page.pretty_title)).html_safe, :value => page.id.to_s, :selected => selected == page) +
                wiki_page_options_for_select(pages, selected, page, level + 1)
       end
     end
index 75fac24642009b69f32c39403cdbb8a635517d77..c5c8a937341c530505e64e55fb38657da5d9daee 100644 (file)
@@ -80,7 +80,7 @@ class CustomField < ActiveRecord::Base
     when 'bool'
       [[l(:general_text_Yes), '1'], [l(:general_text_No), '0']]
     else
-      read_possible_values_utf8_encoded || []
+      possible_values || []
     end
   end
 
@@ -91,14 +91,20 @@ class CustomField < ActiveRecord::Base
     when 'bool'
       ['1', '0']
     else
-      read_possible_values_utf8_encoded
+      values = super()
+      if values.is_a?(Array)
+        values.each do |value|
+          value.force_encoding('UTF-8') if value.respond_to?(:force_encoding)
+        end
+      end
+      values
     end
   end
 
   # Makes possible_values accept a multiline string
   def possible_values=(arg)
     if arg.is_a?(Array)
-      write_attribute(:possible_values, arg.compact.collect(&:strip).select {|v| !v.blank?})
+      super(arg.compact.collect(&:strip).select {|v| !v.blank?})
     else
       self.possible_values = arg.to_s.split(/[\n\r]+/)
     end
@@ -218,14 +224,4 @@ class CustomField < ActiveRecord::Base
     end
     errs
   end
-
-  def read_possible_values_utf8_encoded
-    values = read_attribute(:possible_values)
-    if values.is_a?(Array)
-      values.each do |value|
-        value.force_encoding('UTF-8') if value.respond_to?(:force_encoding)
-      end
-    end
-    values
-  end
 end
index d72ff4dcff42ad6a9bd72f4be70eba0f0e11f0d4..a81dda16fbb83d76d50dedf416109d88c10b5980 100644 (file)
@@ -246,8 +246,8 @@ class Issue < ActiveRecord::Base
     write_attribute(:description, arg)
   end
 
-  # Overrides attributes= so that project and tracker get assigned first
-  def attributes_with_project_and_tracker_first=(new_attributes, *args)
+  # Overrides assign_attributes so that project and tracker get assigned first
+  def assign_attributes_with_project_and_tracker_first(new_attributes, *args)
     return if new_attributes.nil?
     attrs = new_attributes.dup
     attrs.stringify_keys!
@@ -257,10 +257,10 @@ class Issue < ActiveRecord::Base
         send "#{attr}=", attrs.delete(attr)
       end
     end
-    send :attributes_without_project_and_tracker_first=, attrs, *args
+    send :assign_attributes_without_project_and_tracker_first, attrs, *args
   end
   # Do not redefine alias chain on reload (see #4838)
-  alias_method_chain(:attributes=, :project_and_tracker_first) unless method_defined?(:attributes_without_project_and_tracker_first=)
+  alias_method_chain(:assign_attributes, :project_and_tracker_first) unless method_defined?(:assign_attributes_without_project_and_tracker_first)
 
   def estimated_hours=(h)
     write_attribute :estimated_hours, (h.is_a?(String) ? h.to_hours : h)
@@ -350,7 +350,7 @@ class Issue < ActiveRecord::Base
     end
 
     # mass-assignment security bypass
-    self.send :attributes=, attrs, false
+    assign_attributes attrs, :without_protection => true
   end
 
   def done_ratio
@@ -921,7 +921,7 @@ class Issue < ActiveRecord::Base
       p.estimated_hours = nil if p.estimated_hours == 0.0
 
       # ancestors will be recursively updated
-      p.save(false)
+      p.save(:validate => false)
     end
   end
 
index e920dbd5f11dd6d85f2681e0f7bdb22909766322..07083f0abea14b536588b23a014be5d6ce760054 100644 (file)
@@ -15,7 +15,9 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
-class MailHandler < ActionMailer::Base
+require 'vendor/tmail'
+
+class MailHandler
   include ActionView::Helpers::SanitizeHelper
   include Redmine::I18n
 
@@ -39,7 +41,14 @@ class MailHandler < ActionMailer::Base
     @@handler_options[:allow_override] << 'status' unless @@handler_options[:issue].has_key?(:status)
 
     @@handler_options[:no_permission_check] = (@@handler_options[:no_permission_check].to_s == '1' ? true : false)
-    super email
+
+    mail = TMail::Mail.parse(email)
+    mail.base64_decode
+    new.receive(mail)
+  end
+
+  def logger
+    Rails.logger
   end
 
   cattr_accessor :ignored_emails_headers
index 113a773378ecb30d9ef9ef709cc231830fab1444..1cfa7d6cd18e483aafdde73d6ef85180ce744b1f 100644 (file)
@@ -21,13 +21,10 @@ class Mailer < ActionMailer::Base
   helper :issues
   helper :custom_fields
 
-  include ActionController::UrlWriter
   include Redmine::I18n
 
   def self.default_url_options
-    h = Setting.host_name
-    h = h.to_s.gsub(%r{\/.*$}, '') unless Redmine::Utils.relative_url_root.blank?
-    { :host => h, :protocol => Setting.protocol }
+    { :host => Setting.host_name, :protocol => Setting.protocol }
   end
 
   # Builds a tmail object used to email recipients of the added issue.
@@ -42,12 +39,13 @@ class Mailer < ActionMailer::Base
     redmine_headers 'Issue-Assignee' => issue.assigned_to.login if issue.assigned_to
     message_id issue
     @author = issue.author
-    recipients issue.recipients
-    cc(issue.watcher_recipients - @recipients)
-    subject "[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}] (#{issue.status.name}) #{issue.subject}"
-    body :issue => issue,
-         :issue_url => url_for(:controller => 'issues', :action => 'show', :id => issue)
-    render_multipart('issue_add', body)
+    @issue = issue
+    @issue_url = url_for(:controller => 'issues', :action => 'show', :id => issue)
+    recipients = issue.recipients
+    cc = issue.watcher_recipients - recipients
+    mail :to => recipients,
+      :cc => cc,
+      :subject => "[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}] (#{issue.status.name}) #{issue.subject}"
   end
 
   # Builds a tmail object used to email recipients of the edited issue.
@@ -64,30 +62,29 @@ class Mailer < ActionMailer::Base
     message_id journal
     references issue
     @author = journal.user
-    recipients issue.recipients
+    recipients issue.recipients
     # Watchers in cc
-    cc(issue.watcher_recipients - @recipients)
+    cc = issue.watcher_recipients - recipients
     s = "[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}] "
     s << "(#{issue.status.name}) " if journal.new_value_for('status_id')
     s << issue.subject
-    subject s
-    body :issue => issue,
-         :journal => journal,
-         :issue_url => url_for(:controller => 'issues', :action => 'show', :id => issue, :anchor => "change-#{journal.id}")
-
-    render_multipart('issue_edit', body)
+    @issue = issue
+    @journal = journal
+    @issue_url = url_for(:controller => 'issues', :action => 'show', :id => issue, :anchor => "change-#{journal.id}")
+    mail :to => recipients,
+      :cc => cc,
+      :subject => s
   end
 
   def reminder(user, issues, days)
     set_language_if_valid user.language
-    recipients user.mail
-    subject l(:mail_subject_reminder, :count => issues.size, :days => days)
-    body :issues => issues,
-         :days => days,
-         :issues_url => url_for(:controller => 'issues', :action => 'index',
+    @issues = issues
+    @days = days
+    @issues_url = url_for(:controller => 'issues', :action => 'index',
                                 :set_filter => 1, :assigned_to_id => user.id,
                                 :sort => 'due_date:asc')
-    render_multipart('reminder', body)
+    mail :to => user.mail,
+      :subject => l(:mail_subject_reminder, :count => issues.size, :days => days)
   end
 
   # Builds a tmail object used to email users belonging to the added document's project.
@@ -97,12 +94,11 @@ class Mailer < ActionMailer::Base
   #   Mailer.deliver_document_added(document) => sends an email to the document's project recipients
   def document_added(document)
     redmine_headers 'Project' => document.project.identifier
-    recipients document.recipients
     @author = User.current
-    subject "[#{document.project.name}] #{l(:label_document_new)}: #{document.title}"
-    body :document => document,
-         :document_url => url_for(:controller => 'documents', :action => 'show', :id => document)
-    render_multipart('document_added', body)
+    @document = document
+    @document_url = url_for(:controller => 'documents', :action => 'show', :id => document)
+    mail :to => document.recipients,
+      :subject => "[#{document.project.name}] #{l(:label_document_new)}: #{document.title}"
   end
 
   # Builds a tmail object used to email recipients of a project when an attachements are added.
@@ -119,22 +115,22 @@ class Mailer < ActionMailer::Base
     when 'Project'
       added_to_url = url_for(:controller => 'files', :action => 'index', :project_id => container)
       added_to = "#{l(:label_project)}: #{container}"
-      recipients container.project.notified_users.select {|user| user.allowed_to?(:view_files, container.project)}.collect  {|u| u.mail}
+      recipients container.project.notified_users.select {|user| user.allowed_to?(:view_files, container.project)}.collect  {|u| u.mail}
     when 'Version'
       added_to_url = url_for(:controller => 'files', :action => 'index', :project_id => container.project)
       added_to = "#{l(:label_version)}: #{container.name}"
-      recipients container.project.notified_users.select {|user| user.allowed_to?(:view_files, container.project)}.collect  {|u| u.mail}
+      recipients container.project.notified_users.select {|user| user.allowed_to?(:view_files, container.project)}.collect  {|u| u.mail}
     when 'Document'
       added_to_url = url_for(:controller => 'documents', :action => 'show', :id => container.id)
       added_to = "#{l(:label_document)}: #{container.title}"
-      recipients container.recipients
+      recipients container.recipients
     end
     redmine_headers 'Project' => container.project.identifier
-    subject "[#{container.project.name}] #{l(:label_attachment_new)}"
-    body :attachments => attachments,
-         :added_to => added_to,
-         :added_to_url => added_to_url
-    render_multipart('attachments_added', body)
+    @attachments = attachments
+    @added_to = added_to
+    @added_to_url = added_to_url
+    mail :to => recipients,
+      :subject => "[#{container.project.name}] #{l(:label_attachment_new)}"
   end
 
   # Builds a tmail object used to email recipients of a news' project when a news item is added.
@@ -146,11 +142,10 @@ class Mailer < ActionMailer::Base
     redmine_headers 'Project' => news.project.identifier
     @author = news.author
     message_id news
-    recipients news.recipients
-    subject "[#{news.project.name}] #{l(:label_news)}: #{news.title}"
-    body :news => news,
-         :news_url => url_for(:controller => 'news', :action => 'show', :id => news)
-    render_multipart('news_added', body)
+    @news = news
+    @news_url = url_for(:controller => 'news', :action => 'show', :id => news)
+    mail :to => news.recipients,
+      :subject => "[#{news.project.name}] #{l(:label_news)}: #{news.title}"
   end
 
   # Builds a tmail object used to email recipients of a news' project when a news comment is added.
@@ -163,13 +158,12 @@ class Mailer < ActionMailer::Base
     redmine_headers 'Project' => news.project.identifier
     @author = comment.author
     message_id comment
-    recipients news.recipients
-    cc news.watcher_recipients
-    subject "Re: [#{news.project.name}] #{l(:label_news)}: #{news.title}"
-    body :news => news,
-         :comment => comment,
-         :news_url => url_for(:controller => 'news', :action => 'show', :id => news)
-    render_multipart('news_comment_added', body)
+    @news = news
+    @comment = comment
+    @news_url = url_for(:controller => 'news', :action => 'show', :id => news)
+    mail :to => news.recipients,
+     :cc => news.watcher_recipients,
+     :subject => "Re: [#{news.project.name}] #{l(:label_news)}: #{news.title}"
   end
 
   # Builds a tmail object used to email the recipients of the specified message that was posted.
@@ -183,12 +177,13 @@ class Mailer < ActionMailer::Base
     @author = message.author
     message_id message
     references message.parent unless message.parent.nil?
-    recipients(message.recipients)
-    cc((message.root.watcher_recipients + message.board.watcher_recipients).uniq - @recipients)
-    subject "[#{message.board.project.name} - #{message.board.name} - msg#{message.root.id}] #{message.subject}"
-    body :message => message,
-         :message_url => url_for(message.event_url)
-    render_multipart('message_posted', body)
+    recipients = message.recipients
+    cc = ((message.root.watcher_recipients + message.board.watcher_recipients).uniq - recipients)
+    @message = message
+    @message_url = url_for(message.event_url)
+    mail :to => recipients,
+      :cc => cc,
+      :subject => "[#{message.board.project.name} - #{message.board.name} - msg#{message.root.id}] #{message.subject}"
   end
 
   # Builds a tmail object used to email the recipients of a project of the specified wiki content was added.
@@ -201,14 +196,15 @@ class Mailer < ActionMailer::Base
                     'Wiki-Page-Id' => wiki_content.page.id
     @author = wiki_content.author
     message_id wiki_content
-    recipients wiki_content.recipients
-    cc(wiki_content.page.wiki.watcher_recipients - recipients)
-    subject "[#{wiki_content.project.name}] #{l(:mail_subject_wiki_content_added, :id => wiki_content.page.pretty_title)}"
-    body :wiki_content => wiki_content,
-         :wiki_content_url => url_for(:controller => 'wiki', :action => 'show',
+    recipients = wiki_content.recipients
+    cc = wiki_content.page.wiki.watcher_recipients - recipients
+    @wiki_content = wiki_content
+    @wiki_content_url = url_for(:controller => 'wiki', :action => 'show',
                                       :project_id => wiki_content.project,
                                       :id => wiki_content.page.title)
-    render_multipart('wiki_content_added', body)
+    mail :to => recipients,
+      :cc => cc,
+      :subject => "[#{wiki_content.project.name}] #{l(:mail_subject_wiki_content_added, :id => wiki_content.page.pretty_title)}"
   end
 
   # Builds a tmail object used to email the recipients of a project of the specified wiki content was updated.
@@ -221,17 +217,18 @@ class Mailer < ActionMailer::Base
                     'Wiki-Page-Id' => wiki_content.page.id
     @author = wiki_content.author
     message_id wiki_content
-    recipients wiki_content.recipients
-    cc(wiki_content.page.wiki.watcher_recipients + wiki_content.page.watcher_recipients - recipients)
-    subject "[#{wiki_content.project.name}] #{l(:mail_subject_wiki_content_updated, :id => wiki_content.page.pretty_title)}"
-    body :wiki_content => wiki_content,
-         :wiki_content_url => url_for(:controller => 'wiki', :action => 'show',
+    recipients = wiki_content.recipients
+    cc = wiki_content.page.wiki.watcher_recipients + wiki_content.page.watcher_recipients - recipients
+    @wiki_content = wiki_content
+    @wiki_content_url = url_for(:controller => 'wiki', :action => 'show',
                                       :project_id => wiki_content.project,
-                                      :id => wiki_content.page.title),
-         :wiki_diff_url => url_for(:controller => 'wiki', :action => 'diff',
+                                      :id => wiki_content.page.title)
+    @wiki_diff_url = url_for(:controller => 'wiki', :action => 'diff',
                                    :project_id => wiki_content.project, :id => wiki_content.page.title,
                                    :version => wiki_content.version)
-    render_multipart('wiki_content_updated', body)
+    mail :to => recipients,
+      :cc => cc,
+      :subject => "[#{wiki_content.project.name}] #{l(:mail_subject_wiki_content_updated, :id => wiki_content.page.pretty_title)}"
   end
 
   # Builds a tmail object used to email the specified user their account information.
@@ -241,12 +238,11 @@ class Mailer < ActionMailer::Base
   #   Mailer.deliver_account_information(user, password) => sends account information to the user
   def account_information(user, password)
     set_language_if_valid user.language
-    recipients user.mail
-    subject l(:mail_subject_register, Setting.app_title)
-    body :user => user,
-         :password => password,
-         :login_url => url_for(:controller => 'account', :action => 'login')
-    render_multipart('account_information', body)
+    @user = user
+    @password = password
+    @login_url = url_for(:controller => 'account', :action => 'login')
+    mail :to => user.mail,
+      :subject => l(:mail_subject_register, Setting.app_title)
   end
 
   # Builds a tmail object used to email all active administrators of an account activation request.
@@ -256,13 +252,13 @@ class Mailer < ActionMailer::Base
   #   Mailer.deliver_account_activation_request(user)=> sends an email to all active administrators
   def account_activation_request(user)
     # Send the email to all active administrators
-    recipients User.active.find(:all, :conditions => {:admin => true}).collect { |u| u.mail }.compact
-    subject l(:mail_subject_account_activation_request, Setting.app_title)
-    body :user => user,
-         :url => url_for(:controller => 'users', :action => 'index',
+    recipients = User.active.find(:all, :conditions => {:admin => true}).collect { |u| u.mail }.compact
+    @user = user
+    @url = url_for(:controller => 'users', :action => 'index',
                          :status => User::STATUS_REGISTERED,
                          :sort_key => 'created_on', :sort_order => 'desc')
-    render_multipart('account_activation_request', body)
+    mail :to => recipients,
+      :subject => l(:mail_subject_account_activation_request, Setting.app_title)
   end
 
   # Builds a tmail object used to email the specified user that their account was activated by an administrator.
@@ -272,37 +268,33 @@ class Mailer < ActionMailer::Base
   #   Mailer.deliver_account_activated(user) => sends an email to the registered user
   def account_activated(user)
     set_language_if_valid user.language
-    recipients user.mail
-    subject l(:mail_subject_register, Setting.app_title)
-    body :user => user,
-         :login_url => url_for(:controller => 'account', :action => 'login')
-    render_multipart('account_activated', body)
+    @user = user
+    @login_url = url_for(:controller => 'account', :action => 'login')
+    mail :to => user.mail,
+      :subject => l(:mail_subject_register, Setting.app_title)
   end
 
   def lost_password(token)
     set_language_if_valid(token.user.language)
-    recipients token.user.mail
-    subject l(:mail_subject_lost_password, Setting.app_title)
-    body :token => token,
-         :url => url_for(:controller => 'account', :action => 'lost_password', :token => token.value)
-    render_multipart('lost_password', body)
+    @token = token
+    @url = url_for(:controller => 'account', :action => 'lost_password', :token => token.value)
+    mail :to => token.user.mail,
+      :subject => l(:mail_subject_lost_password, Setting.app_title)
   end
 
   def register(token)
     set_language_if_valid(token.user.language)
-    recipients token.user.mail
-    subject l(:mail_subject_register, Setting.app_title)
-    body :token => token,
-         :url => url_for(:controller => 'account', :action => 'activate', :token => token.value)
-    render_multipart('register', body)
+    @token = token
+    @url = url_for(:controller => 'account', :action => 'activate', :token => token.value)
+    mail :to => token.user.mail,
+      :subject => l(:mail_subject_register, Setting.app_title)
   end
 
   def test_email(user)
     set_language_if_valid(user.language)
-    recipients user.mail
-    subject 'Redmine test'
-    body :url => url_for(:controller => 'welcome')
-    render_multipart('test_email', body)
+    @url = url_for(:controller => 'welcome')
+    mail :to => user.mail,
+      :subject => 'Redmine test'
   end
 
   # Overrides default deliver! method to prevent from sending an email
@@ -313,13 +305,6 @@ class Mailer < ActionMailer::Base
                     (cc.nil? || cc.empty?) &&
                     (bcc.nil? || bcc.empty?)
 
-    # Set Message-Id and References
-    if @message_id_object
-      mail.message_id = self.class.message_id_for(@message_id_object)
-    end
-    if @references_objects
-      mail.references = @references_objects.collect {|o| self.class.message_id_for(o)}
-    end
 
     # Log errors when raise_delivery_errors is set to false, Rails does not
     raise_errors = self.class.raise_delivery_errors
@@ -383,83 +368,72 @@ class Mailer < ActionMailer::Base
     ActionMailer::Base.delivery_method = saved_method
   end
 
-  private
-  def initialize_defaults(method_name)
-    super
-    @initial_language = current_language
-    set_language_if_valid Setting.default_language
-    from Setting.mail_from
-
-    # Common headers
-    headers 'X-Mailer' => 'Redmine',
+  def mail(headers={})
+    headers.merge! 'X-Mailer' => 'Redmine',
             'X-Redmine-Host' => Setting.host_name,
             'X-Redmine-Site' => Setting.app_title,
             'X-Auto-Response-Suppress' => 'OOF',
-            'Auto-Submitted' => 'auto-generated'
-  end
+            'Auto-Submitted' => 'auto-generated',
+            'From' => Setting.mail_from
 
-  # Appends a Redmine header field (name is prepended with 'X-Redmine-')
-  def redmine_headers(h)
-    h.each { |k,v| headers["X-Redmine-#{k}"] = v.to_s }
-  end
-
-  # Overrides the create_mail method
-  def create_mail
     # Removes the author from the recipients and cc
     # if he doesn't want to receive notifications about what he does
     if @author && @author.logged? && @author.pref[:no_self_notified]
-      if recipients
-        recipients((recipients.is_a?(Array) ? recipients : [recipients]) - [@author.mail])
-      end
-      if cc
-        cc((cc.is_a?(Array) ? cc : [cc]) - [@author.mail])
-      end
+      headers[:to].delete(@author.mail) if headers[:to].is_a?(Array)
+      headers[:cc].delete(@author.mail) if headers[:cc].is_a?(Array)
     end
 
     if @author && @author.logged?
       redmine_headers 'Sender' => @author.login
     end
 
-    notified_users = [recipients, cc].flatten.compact.uniq
-    # Rails would log recipients only, not cc and bcc
-    mylogger.info "Sending email notification to: #{notified_users.join(', ')}" if mylogger
-
     # Blind carbon copy recipients
     if Setting.bcc_recipients?
-      bcc(notified_users)
-      recipients []
-      cc []
+      headers[:bcc] = [headers[:to], headers[:cc]].flatten.uniq.reject(&:blank?)
+      headers[:to] = nil
+      headers[:cc] = nil
+    end
+
+    if @message_id_object
+      headers[:message_id] = "<#{self.class.message_id_for(@message_id_object)}>"
+    end
+    if @references_objects
+      headers[:references] = @references_objects.collect {|o| "<#{self.class.message_id_for(o)}>"}.join(' ')
+    end
+
+    super headers do |format|
+      format.text
+      format.html unless Setting.plain_text_mail?
     end
+
+    set_language_if_valid @initial_language
+  end
+
+  def initialize(*args)
+    @initial_language = current_language
+    set_language_if_valid Setting.default_language
+    super
+  end
+  
+  def self.deliver_mail(mail)
+    return false if mail.to.blank? && mail.cc.blank? && mail.bcc.blank?
     super
   end
 
-  # Rails 2.3 has problems rendering implicit multipart messages with
-  # layouts so this method will wrap an multipart messages with
-  # explicit parts.
-  #
-  # https://rails.lighthouseapp.com/projects/8994/tickets/2338-actionmailer-mailer-views-and-content-type
-  # https://rails.lighthouseapp.com/projects/8994/tickets/1799-actionmailer-doesnt-set-template_format-when-rendering-layouts
-
-  def render_multipart(method_name, body)
-    if Setting.plain_text_mail?
-      content_type "text/plain"
-      body render(:file => "#{method_name}.text.erb",
-                  :body => body,
-                  :layout => 'mailer.text.erb')
+  def self.method_missing(method, *args, &block)
+    if m = method.to_s.match(%r{^deliver_(.+)$})
+      send(m[1], *args).deliver
     else
-      content_type "multipart/alternative"
-      part :content_type => "text/plain",
-           :body => render(:file => "#{method_name}.text.erb",
-                           :body => body, :layout => 'mailer.text.erb')
-      part :content_type => "text/html",
-           :body => render_message("#{method_name}.html.erb", body)
+      super
     end
   end
 
-  # Makes partial rendering work with Rails 1.2 (retro-compatibility)
-  def self.controller_path
-    ''
-  end unless respond_to?('controller_path')
+  private
+
+  # Appends a Redmine header field (name is prepended with 'X-Redmine-')
+  def redmine_headers(h)
+    h.each { |k,v| headers["X-Redmine-#{k}"] = v.to_s }
+  end
 
   # Returns a predictable Message-Id for the given object
   def self.message_id_for(object)
@@ -469,11 +443,9 @@ class Mailer < ActionMailer::Base
     hash = "redmine.#{object.class.name.demodulize.underscore}-#{object.id}.#{timestamp.strftime("%Y%m%d%H%M%S")}"
     host = Setting.mail_from.to_s.gsub(%r{^.*@}, '')
     host = "#{::Socket.gethostname}.redmine" if host.empty?
-    "<#{hash}@#{host}>"
+    "#{hash}@#{host}"
   end
 
-  private
-
   def message_id(object)
     @message_id_object = object
   end
@@ -487,12 +459,3 @@ class Mailer < ActionMailer::Base
     Rails.logger
   end
 end
-
-# Patch TMail so that message_id is not overwritten
-module TMail
-  class Mail
-    def add_message_id( fqdn = nil )
-      self.message_id ||= ::TMail::new_message_id(fqdn)
-    end
-  end
-end
index 2e76612f5d44576808137a42ec0b234c2af3da20..6dfe95cc4672736396b36f66199d1a8ccf3b7db4 100644 (file)
@@ -272,6 +272,10 @@ class Project < ActiveRecord::Base
     end
   end
 
+  def self.find_by_param(*args)
+    self.find(*args)
+  end
+
   def reload(*args)
     @shared_versions = nil
     @rolled_up_versions = nil
index 5b1d681115cfbf1a597919a790c9fa5be96f8067..7efbc0c26a2f7c41d41ca25b093ee1144ec96449 100644 (file)
@@ -57,7 +57,7 @@ class Repository < ActiveRecord::Base
   end
 
   alias :attributes_without_extra_info= :attributes=
-  def attributes=(new_attributes, guard_protected_attributes = true)
+  def attributes=(new_attributes)
     return if new_attributes.nil?
     attributes = new_attributes.dup
     attributes.stringify_keys!
@@ -72,7 +72,7 @@ class Repository < ActiveRecord::Base
       end
     end
 
-    send :attributes_without_extra_info=, p, guard_protected_attributes
+    send :attributes_without_extra_info=, p
     if p_extra.keys.any?
       merge_extra_info(p_extra)
     end
index 44bb340c38b7041c5e0f29cc3cdacb3d261a865c..06822fdbaf29a95f224e66014ffc3189f3244073 100644 (file)
@@ -36,7 +36,7 @@ class Role < ActiveRecord::Base
   before_destroy :check_deletable
   has_many :workflows, :dependent => :delete_all do
     def copy(source_role)
-      Workflow.copy(nil, source_role, nil, proxy_owner)
+      Workflow.copy(nil, source_role, nil, proxy_association.owner)
     end
   end
 
index 784e18f5e729d0b264115ce42bf588197ce6acbb..32eea23093e8ddf72d31a2c815f0755ba920301d 100644 (file)
@@ -20,7 +20,7 @@ class Tracker < ActiveRecord::Base
   has_many :issues
   has_many :workflows, :dependent => :delete_all do
     def copy(source_tracker)
-      Workflow.copy(source_tracker, nil, proxy_owner, nil)
+      Workflow.copy(source_tracker, nil, proxy_association.owner, nil)
     end
   end
 
index fad59e9a46166e523686d7d420de8e59dedb6886..99eda92425575ba44022ca2db72187579d2351ef 100644 (file)
@@ -1,6 +1,6 @@
 <%= call_hook :view_account_login_top %>
 <div id="login-form">
-<% form_tag({:action=> "login"}) do %>
+<%= form_tag({:action=> "login"}) do %>
 <%= back_url_hidden_field_tag %>
 <table>
 <tr>
index 420e8f9b142d4b126f9f55dd22099ed2b23841c1..44f8514751d75c111b23f4bacab5808592501efc 100644 (file)
@@ -1,7 +1,7 @@
 <h2><%=l(:label_password_lost)%></h2>
 
 <div class="box">
-<% form_tag({:action=> "lost_password"}, :class => "tabular") do %>
+<%= form_tag({:action=> "lost_password"}, :class => "tabular") do %>
 
 <p><label for="mail"><%=l(:field_mail)%> <span class="required">*</span></label>
 <%= text_field_tag 'mail', nil, :size => 40 %>
index 72310aefc2c001c4f079c63b9aff131b862679d6..53c6350505f4f3d8dc388068862ed93f8afb1e7b 100644 (file)
@@ -2,7 +2,7 @@
 
 <%= error_messages_for 'user' %>
 
-<% form_tag({:token => @token.value}) do %>
+<%= form_tag({:token => @token.value}) do %>
 <div class="box tabular">
 <p><label for="new_password"><%=l(:field_new_password)%> <span class="required">*</span></label>
 <%= password_field_tag 'new_password', nil, :size => 25 %>
index adb43632629f2ad4069a9357d8ebd573364d47d5..7e44e123b2bfb1ab8e525290bb12037119bc3763 100644 (file)
@@ -1,6 +1,6 @@
 <h2><%=l(:label_register)%> <%=link_to l(:label_login_with_open_id_option), signin_url if Setting.openid? %></h2>
 
-<% labelled_form_for @user, :url => {:action => 'register'} do |f| %>
+<%= labelled_form_for @user, :url => {:action => 'register'} do |f| %>
 <%= error_messages_for 'user' %>
 
 <div class="box tabular">
index 81916e5e136e767690ff0ee6ccd42c9f5cab2bca..e2f15d109f301c87428c096692aa795ae0de560d 100644 (file)
@@ -40,7 +40,7 @@
 <% end %>
 
 <% content_for :sidebar do %>
-<% form_tag({}, :method => :get) do %>
+<%= form_tag({}, :method => :get) do %>
 <h3><%= l(:label_activity) %></h3>
 <p><% @activity.event_types.each do |t| %>
 <%= check_box_tag "show_#{t}", 1, @activity.scope.include?(t) %>
index 5d52dc05931ea65b7d6e1a5e3168682e952340f9..8ad39b19799a3417ed377f5a95f1c8cdcd8b80a1 100644 (file)
@@ -1,5 +1,5 @@
 <div class="nodata">
-<% form_tag({:action => 'default_configuration'}) do %>
+<%= form_tag({:action => 'default_configuration'}) do %>
     <%= simple_format(l(:text_no_configuration_data)) %>
     <p><%= l(:field_language) %>:
     <%= select_tag 'lang', options_for_select(lang_options_for_select(false), current_language.to_s) %>
index 33d1d881871f648247ea2037c300172d17177e5d..6525f8ea5baf55b243a30d8766fa30de5dafe97f 100644 (file)
@@ -4,7 +4,7 @@
 
 <h2><%=l(:label_project_plural)%></h2>
 
-<% form_tag({}, :method => :get) do %>
+<%= form_tag({}, :method => :get) do %>
 <fieldset><legend><%= l(:label_filter_plural) %></legend>
 <label for='status'><%= l(:field_status) %> :</label>
 <%= select_tag 'status', project_status_options_for_select(@status), :class => "small", :onchange => "this.form.submit(); return false;"  %>
index fa4e182fc5a2f6c8533ee34b817dd83be34aff89..5359d4eea121118be6adc9aa7f76c14a125a0073 100644 (file)
@@ -7,7 +7,7 @@
    <span class="size">(<%= number_to_human_size @attachment.filesize %>)</span></p>
 </div>
 <p>
-<% form_tag({}, :method => 'get') do %>
+<%= form_tag({}, :method => 'get') do %>
     <label><%= l(:label_view_diff) %></label>
     <%= select_tag 'type',
                     options_for_select(
index f2d76002c33449284472dcbdf226cc9d900d6b26..1673d83367fc102e5248d981a79c493a8fed92e8 100644 (file)
@@ -1,6 +1,6 @@
 <h2><%=l(:label_auth_source)%> (<%= h(@auth_source.auth_method_name) %>)</h2>
 
-<% form_tag({:action => 'update', :id => @auth_source}, :method => :put, :class => "tabular") do %>
+<%= form_tag({:action => 'update', :id => @auth_source}, :method => :put, :class => "tabular") do %>
   <%= render :partial => auth_source_partial_name(@auth_source) %>
   <%= submit_tag l(:button_save) %>
 <% end %>
index e5b9106bd07ed6168683f161c190c53e338f589c..b585c0aa0115710b462faa0de1691bd7789704c6 100644 (file)
@@ -1,6 +1,6 @@
 <h2><%=l(:label_auth_source_new)%> (<%= h(@auth_source.auth_method_name) %>)</h2>
 
-<% form_tag({:action => 'create'}, :class => "tabular") do %>
+<%= form_tag({:action => 'create'}, :class => "tabular") do %>
   <%= hidden_field_tag 'type', @auth_source.type %>
   <%= render :partial => auth_source_partial_name(@auth_source) %>
   <%= submit_tag l(:button_create) %>
index 9e94c25cd6dc21b7c989a35b30821b5a3e403993..e57509eab3ba042ae07fb8a7d399e03a354ba76b 100644 (file)
@@ -1,6 +1,6 @@
 <h2><%= l(:label_board) %></h2>
 
-<% labelled_form_for @board, :url => project_board_path(@project, @board) do |f| %>
+<%= labelled_form_for @board, :url => project_board_path(@project, @board) do |f| %>
   <%= render :partial => 'form', :locals => {:f => f} %>
   <%= submit_tag l(:button_save) %>
 <% end %>
index 68eb1a33c31cb707957aceeb71e2994b09f82b2d..acdf43fcfaeeeb30e4cca7a4fd69fd61e7f5c115 100644 (file)
@@ -1,6 +1,6 @@
 <h2><%= l(:label_board_new) %></h2>
 
-<% labelled_form_for @board, :url => project_boards_path(@project) do |f| %>
+<%= labelled_form_for @board, :url => project_boards_path(@project) do |f| %>
   <%= render :partial => 'form', :locals => {:f => f} %>
   <%= submit_tag l(:button_create) %>
 <% end %>
index 6441c5ce31906bdc7707be365ef9a566f5512df0..523dfea45525b7aa6fb261f5eb0ee54fc70bf711 100644 (file)
@@ -11,7 +11,7 @@
 <div id="add-message" style="display:none;">
 <% if authorize_for('messages', 'new') %>
 <h2><%= link_to h(@board.name), :controller => 'boards', :action => 'show', :project_id => @project, :id => @board %> &#187; <%= l(:label_message_new) %></h2>
-<% form_for :message, @message, :url => {:controller => 'messages', :action => 'new', :board_id => @board}, :html => {:multipart => true, :id => 'message-form'} do |f| %>
+<%= form_for @message, :url => {:controller => 'messages', :action => 'new', :board_id => @board}, :html => {:multipart => true, :id => 'message-form'} do |f| %>
   <%= render :partial => 'messages/form', :locals => {:f => f} %>
   <p><%= submit_tag l(:button_create) %>
   <%= link_to_remote l(:label_preview),
index 803a17357f9831ee610dff40a794ec61b0a9ff90..ab559012936d43511bc0a12275bbba429355c3d7 100644 (file)
@@ -1,6 +1,7 @@
 <h2><%= @query.new_record? ? l(:label_calendar) : h(@query.name) %></h2>
 
-<% form_tag({:controller => 'calendars', :action => 'show', :project_id => @project}, :method => :get, :id => 'query_form') do %>
+<%= form_tag({:controller => 'calendars', :action => 'show', :project_id => @project},
+             :method => :get, :id => 'query_form') do %>
 <%= hidden_field_tag 'set_filter', '1' %>
 <fieldset id="filters" class="collapsible <%= @query.new_record? ? "" : "collapsed" %>">
   <legend onclick="toggleFieldset(this);"><%= l(:label_filter_plural) %></legend>
index d76f0acd1bfaee6b3a42628e3a96d4402adcb447..70dacc75a15d68e1a636f94b93f3ca529c2bca64 100644 (file)
@@ -1,8 +1,8 @@
 xml.instruct!
 xml.feed "xmlns" => "http://www.w3.org/2005/Atom" do
   xml.title   truncate_single_line(@title, :length => 100)
-  xml.link    "rel" => "self", "href" => url_for(params.merge(:only_path => false, :escape => false))
-  xml.link    "rel" => "alternate", "href" => url_for(params.merge(:only_path => false, :format => nil, :key => nil, :escape => false))
+  xml.link    "rel" => "self", "href" => url_for(params.merge(:only_path => false))
+  xml.link    "rel" => "alternate", "href" => url_for(params.merge(:only_path => false, :format => nil, :key => nil))
   xml.id      url_for(:controller => 'welcome', :only_path => false)
   xml.updated((@items.first ? @items.first.event_datetime : Time.now).xmlschema)
   xml.author  { xml.name "#{Setting.app_title}" }
index 62672ab207b6aefd3c16a41dc171a08ac6dd364e..dce34736f19c99db6825a60b8c90380b39844937 100644 (file)
@@ -2,7 +2,7 @@
   &#187; <%= link_to l(@custom_field.type_name), :controller => 'custom_fields', :action => 'index', :tab => @custom_field.class.name %>
   &#187; <%=h @custom_field.name %></h2>
 
-<% labelled_form_for :custom_field, @custom_field, :url => custom_field_path(@custom_field), :html => {:method => :put} do |f| %>
+<%= labelled_form_for :custom_field, @custom_field, :url => custom_field_path(@custom_field), :html => {:method => :put} do |f| %>
 <%= render :partial => 'form', :locals => { :f => f } %>
 <%= submit_tag l(:button_save) %>
 <% end %>
index 4fcd160e489a3168653b726277de3e85cde3c60a..cde4fab580025f12cacf2b943d1d49008f7fdf98 100644 (file)
@@ -2,7 +2,7 @@
   &#187; <%= link_to l(@custom_field.type_name), :controller => 'custom_fields', :action => 'index', :tab => @custom_field.class.name %>
   &#187; <%= l(:label_custom_field_new) %></h2>
 
-<% labelled_form_for :custom_field, @custom_field, :url => custom_fields_path do |f| %>
+<%= labelled_form_for :custom_field, @custom_field, :url => custom_fields_path do |f| %>
 <%= render :partial => 'form', :locals => { :f => f } %>
 <%= hidden_field_tag 'type', @custom_field.type %>
 <%= submit_tag l(:button_save) %>
index 04e9b72e11e400be21bca9cc0790c7625ca36047..15491168df997582ad661867bfa69aaf5663fd3e 100644 (file)
@@ -1,6 +1,6 @@
 <h2><%=l(:label_document)%></h2>
 
-<% labelled_form_for @document do |f| %>
+<%= labelled_form_for @document do |f| %>
   <%= render :partial => 'form', :locals => {:f => f} %>
   <p><%= submit_tag l(:button_save) %></p>
 <% end %>
index d3658dac6fbd1fdee3892dc4dcc680e1d2e82e05..fd47c384207d262072cbd89a02797c868ea978e6 100644 (file)
@@ -5,7 +5,7 @@
 
 <div id="add-document" style="display:none;">
 <h2><%=l(:label_document_new)%></h2>
-<% labelled_form_for @document, :url => project_documents_path(@project), :html => {:multipart => true} do |f| %>
+<%= labelled_form_for @document, :url => project_documents_path(@project), :html => {:multipart => true} do |f| %>
 <%= render :partial => 'form', :locals => {:f => f} %>
 <p>
        <%= submit_tag l(:button_create) %>
index 772093e31d17f27d637116a386905f03d7d8f01f..a34391e3148b576659952f7194b0ad1aae003227 100644 (file)
@@ -1,6 +1,6 @@
 <h2><%=l(:label_document_new)%></h2>
 
-<% labelled_form_for @document, :url => project_documents_path(@project), :html => {:multipart => true} do |f| %>
+<%= labelled_form_for @document, :url => project_documents_path(@project), :html => {:multipart => true} do |f| %>
   <%= render :partial => 'form', :locals => {:f => f} %>
   <p><%= submit_tag l(:button_create) %></p>
 <% end %>
index fded300524ec1e7490f3e5a042a2b861620eec8c..f65d5ae88064d5547bf59bd635f3457e2bfd047f 100644 (file)
@@ -19,7 +19,7 @@
 <% if authorize_for('documents', 'add_attachment') %>
 <p><%= link_to l(:label_attachment_new), {}, :onclick => "Element.show('add_attachment_form'); Element.hide(this); Element.scrollTo('add_attachment_form'); return false;",
                                              :id => 'attach_files_link' %></p>
-  <% form_tag({ :controller => 'documents', :action => 'add_attachment', :id => @document }, :multipart => true, :id => "add_attachment_form", :style => "display:none;") do %>
+  <%= form_tag({ :controller => 'documents', :action => 'add_attachment', :id => @document }, :multipart => true, :id => "add_attachment_form", :style => "display:none;") do %>
   <div class="box">
   <p><%= render :partial => 'attachments/form' %></p>
   </div>
index 4fca33d4a3c5718c9dd240687478e7a99905255d..02e66bd9f0fe4a82a30fcaefbab72c41bb4c224a 100644 (file)
@@ -1,6 +1,6 @@
 <h2><%= l(@enumeration.option_name) %>: <%=h @enumeration %></h2>
 
-<% form_tag({}, :method => :delete) do %>
+<%= form_tag({}, :method => :delete) do %>
 <div class="box">
 <p><strong><%= l(:text_enumeration_destroy_question, @enumeration.objects_count) %></strong></p>
 <p><label for='reassign_to_id'><%= l(:text_enumeration_category_reassign_to) %></label>
index c46a7606f3437b7ee2cc4dc611ff974b778825c7..e5c523390ecd2c02048b879b7f62898527d7050c 100644 (file)
@@ -1,6 +1,6 @@
 <h2><%= link_to l(@enumeration.option_name), enumerations_path %> &#187; <%=h @enumeration %></h2>
 
-<% labelled_form_for :enumeration, @enumeration, :url => enumeration_path(@enumeration), :html => {:method => :put} do |f| %>
+<%= labelled_form_for :enumeration, @enumeration, :url => enumeration_path(@enumeration), :html => {:method => :put} do |f| %>
   <%= render :partial => 'form', :locals => {:f => f} %>
   <%= submit_tag l(:button_save) %>
 <% end %>
index f0e6bd3434a55fe6165d8e8b9a1c04162397559b..dfbd99f529d9e018f27e8f98aafe2af6bf2965d8 100644 (file)
@@ -1,6 +1,6 @@
 <h2><%= link_to l(@enumeration.option_name), enumerations_path %> &#187; <%=l(:label_enumeration_new)%></h2>
 
-<% labelled_form_for :enumeration, @enumeration, :url => enumerations_path do |f| %>
+<%= labelled_form_for :enumeration, @enumeration, :url => enumerations_path do |f| %>
   <%= f.hidden_field :type  %>
   <%= render :partial => 'form', :locals => {:f => f} %>
   <%= submit_tag l(:button_create) %>
index 544bd333beae359650f6fa1f82e4f967011ccba6..ab38b4472fee5982ab14637c921d5ba764691489 100644 (file)
@@ -1,7 +1,7 @@
 <h2><%=l(:label_attachment_new)%></h2>
 
 <%= error_messages_for 'attachment' %>
-<% form_tag(project_files_path(@project), :multipart => true, :class => "tabular") do %>
+<%= form_tag(project_files_path(@project), :multipart => true, :class => "tabular") do %>
 <div class="box">
 
 <% if @versions.any? %>
index 0b4af3523be75c8a2257a638891aabfec5028bd7..aeeb127e413c3ba1bff7e3d0e0f6158ba4fffeba 100644 (file)
@@ -1,7 +1,10 @@
 <% @gantt.view = self %>
 <h2><%= @query.new_record? ? l(:label_gantt) : h(@query.name) %></h2>
 
-<% form_tag({:controller => 'gantts', :action => 'show', :project_id => @project, :month => params[:month], :year => params[:year], :months => params[:months]}, :method => :get, :id => 'query_form') do %>
+<%= form_tag({:controller => 'gantts', :action => 'show',
+             :project_id => @project, :month => params[:month],
+             :year => params[:year], :months => params[:months]},
+             :method => :get, :id => 'query_form') do %>
 <%= hidden_field_tag 'set_filter', '1' %>
 <fieldset id="filters" class="collapsible <%= @query.new_record? ? "" : "collapsed" %>">
   <legend onclick="toggleFieldset(this);"><%= l(:label_filter_plural) %></legend>
index a9d05b7ca5899275c4aaefbd782bacc6df5614fe..8c720c3eef0dcb593758b61b0c5b41d98987d29c 100644 (file)
@@ -1,4 +1,4 @@
-<% labelled_form_for @group do |f| %>
+<%= labelled_form_for @group do |f| %>
 <%= render :partial => 'form', :locals => { :f => f } %>
 <%= submit_tag l(:button_save) %>
 <% end %>
index 9346e1021e9f704028a4cb5ef742f2c1c93652c8..79b990c84d0142a1b79fd2cdd47ed4bdb4144daf 100644 (file)
@@ -16,8 +16,9 @@
   <td class="project"><%=h membership.project %></td>
   <td class="roles">
     <span id="member-<%= membership.id %>-roles"><%=h membership.roles.sort.collect(&:to_s).join(', ') %></span>
-    <% remote_form_for(:membership, :url => { :action => 'edit_membership', :id => @group, :membership_id => membership },
-                                    :html => { :id => "member-#{membership.id}-roles-form", :style => 'display:none;'}) do %>
+    <%= form_for(:membership, :remote => true,
+                 :url => { :action => 'edit_membership', :id => @group, :membership_id => membership },
+                 :html => { :id => "member-#{membership.id}-roles-form", :style => 'display:none;'}) do %>
         <p><% roles.each do |role| %>
         <label><%= check_box_tag 'membership[role_ids][]', role.id, membership.roles.include?(role) %> <%=h role %></label><br />
         <% end %></p>
@@ -55,7 +56,7 @@
 <div class="splitcontentright">
 <% if projects.any? %>
 <fieldset><legend><%=l(:label_project_new)%></legend>
-<% remote_form_for(:membership, :url => { :action => 'edit_membership', :id => @group }) do %>
+<%= form_for(:membership, :remote => true, :url => { :action => 'edit_membership', :id => @group }) do %>
 <%= label_tag "membership_project_id", l(:description_choose_project), :class => "hidden-for-sighted" %>
 <%= select_tag 'membership[project_id]', options_for_membership_project_select(@group, projects) %>
 <p><%= l(:label_role_plural) %>:
index d265c751f892b6c929a72e9bfe5eb448e457408c..5d10fe694713e2356447bcf81b7daf77ac9acb1d 100644 (file)
@@ -29,7 +29,8 @@
 <div class="splitcontentright">
 <% users = User.active.not_in_group(@group).all(:limit => 100) %>
 <% if users.any? %>
-  <% remote_form_for(@group, :url => group_users_path(@group), :html => {:method => :post}) do |f| %>
+  <%= form_for(@group, :remote => true, :url => group_users_path(@group),
+               :html => {:method => :post}) do |f| %>
     <fieldset><legend><%=l(:label_user_new)%></legend>
 
     <p><%= label_tag "user_search", l(:label_user_search) %><%= text_field_tag 'user_search', nil %></p>
index a4426f2d14200c5eacf530bd51579765f9b8db3f..f47034588dfac8cdcd2d73093cf4ca2d8bb09d22 100644 (file)
@@ -1,6 +1,6 @@
 <h2><%= link_to l(:label_group_plural), groups_path %> &#187; <%= l(:label_group_new) %></h2>
 
-<% labelled_form_for @group do |f| %>
+<%= labelled_form_for @group do |f| %>
 <%= render :partial => 'form', :locals => { :f => f } %>
 <p>
   <%= f.submit l(:button_create) %>
index 882a75e4af3f392d30f948e0f4beff52b0cc8ef5..5f13eedcfe2f77efccd7cbc262e45c554e60346c 100644 (file)
@@ -1,6 +1,6 @@
 <h2><%=l(:label_issue_category)%>: <%=h @category.name %></h2>
 
-<% form_tag(issue_category_path(@category), :method => :delete) do %>
+<%= form_tag(issue_category_path(@category), :method => :delete) do %>
 <div class="box">
 <p><strong><%= l(:text_issue_category_destroy_question, @issue_count) %></strong></p>
 <p><label><%= radio_button_tag 'todo', 'nullify', true %> <%= l(:text_issue_category_destroy_assignments) %></label><br />
index 584fe06a90e1a2e94bd89474b62490c66db7a55e..d52d61bd2a0ff8c940a074c4b5348a30b2f0654d 100644 (file)
@@ -1,6 +1,6 @@
 <h2><%= link_to l(:label_issue_status_plural), issue_statuses_path %> &#187; <%=h @issue_status %></h2>
 
-<% labelled_form_for @issue_status do |f| %>
+<%= labelled_form_for @issue_status do |f| %>
   <%= render :partial => 'form', :locals => {:f => f} %>
   <%= submit_tag l(:button_save) %>
 <% end %>
index 6ab77b2146959fb1c5aee3285b64ccbce83a7485..c9e60abcd906957eb6d14f07444c81b952d427a3 100644 (file)
@@ -1,6 +1,6 @@
 <h2><%= link_to l(:label_issue_status_plural), issue_statuses_path %> &#187; <%=l(:label_issue_status_new)%></h2>
 
-<% labelled_form_for @issue_status do |f| %>
+<%= labelled_form_for @issue_status do |f| %>
   <%= render :partial => 'form', :locals => {:f => f} %>
   <%= submit_tag l(:button_create) %>
 <% end %>
index c643934d1675ec6764010194b4e7efbc256548fc..4d0503117920265b18a98593bc4147229c580691 100644 (file)
@@ -1,6 +1,6 @@
 <div class="contextual">
 <%= link_to_if_authorized(l(:button_update), {:controller => 'issues', :action => 'edit', :id => @issue }, :onclick => 'showAndScrollTo("update", "notes"); return false;', :class => 'icon icon-edit', :accesskey => accesskey(:edit)) %>
-<%= link_to_if_authorized l(:button_log_time), {:controller => 'timelog', :action => 'new', :issue_id => @issue}, :class => 'icon icon-time-add' %>
+<%= link_to l(:button_log_time), new_issue_time_entry_path(@issue), :class => 'icon icon-time-add' if User.current.allowed_to?(:log_time, @project) %>
 <%= watcher_tag(@issue, User.current) %>
 <%= link_to_if_authorized l(:button_copy), {:controller => 'issues', :action => 'new', :project_id => @project, :copy_from => @issue}, :class => 'icon icon-copy' %>
 <%= link_to l(:button_delete), issue_path(@issue), :confirm => issues_destroy_confirmation_message(@issue), :method => :delete, :class => 'icon icon-del' if User.current.allowed_to?(:delete_issues, @project) %>
index 7ac662e133d8c4378694ea405c9c326cf160ff0a..c65735ae4b27fb24df3d4f7e4422506d9be29fe4 100644 (file)
@@ -1,4 +1,4 @@
-<% labelled_fields_for :issue, @issue do |f| %>
+<%= labelled_fields_for :issue, @issue do |f| %>
 
 <div class="splitcontent">
 <div class="splitcontentleft">
index 690fa9386895fcdbde81c48cbc0fecf1c16a82d9..b5ddfac382399ebeb46a2858b3978cbe22766ecd 100644 (file)
@@ -1,4 +1,4 @@
-<% labelled_form_for @issue, :html => {:id => 'issue-form', :multipart => true} do |f| %>
+<%= labelled_form_for @issue, :html => {:id => 'issue-form', :multipart => true} do |f| %>
     <%= error_messages_for 'issue', 'time_entry' %>
     <%= render :partial => 'conflict' if @conflict %>
     <div class="box">
@@ -11,7 +11,7 @@
     <% end %>
     <% if User.current.allowed_to?(:log_time, @project) %>
         <fieldset class="tabular"><legend><%= l(:button_log_time) %></legend>
-        <% labelled_fields_for :time_entry, @time_entry do |time_entry| %>
+        <%= labelled_fields_for :time_entry, @time_entry do |time_entry| %>
         <div class="splitcontentleft">
         <p><%= time_entry.text_field :hours, :size => 6, :label => :label_spent_time %> <%= l(:field_hours) %></p>
         </div>
index 6634723f7730af49a01ace1a8f29f01fefffe62b..9bc362377e251ad8d2e3c4f3829f7b86e839f286 100644 (file)
@@ -1,4 +1,4 @@
-<% labelled_fields_for :issue, @issue do |f| %>
+<%= labelled_fields_for :issue, @issue do |f| %>
 <%= call_hook(:view_issues_form_details_top, { :issue => @issue, :form => f }) %>
 
 <% if @issue.safe_attribute? 'is_private' %>
@@ -28,7 +28,7 @@
   <label><%= l(:field_description) %></label>
   <%= link_to_function image_tag('edit.png'), 
     'Element.hide(this); Effect.toggle("issue_description_and_toolbar", "appear", {duration:0.3})' unless @issue.new_record? %>
-  <% content_tag 'span', :id => "issue_description_and_toolbar", :style => (@issue.new_record? ? nil : 'display:none') do %>
+  <%= content_tag 'span', :id => "issue_description_and_toolbar", :style => (@issue.new_record? ? nil : 'display:none') do %>
     <%= f.text_area :description,
                    :cols => 60,
                    :rows => (@issue.description.blank? ? 10 : [[10, @issue.description.length / 50].max, 100].min),
index f5b5bc1bbc8103509fb85348e2d4f18d6d5fc024..62cf4e44342d7a7d21e78fa668816d982c188d53 100644 (file)
@@ -1,4 +1,4 @@
-<% form_tag({}) do -%>
+<%= form_tag({}) do -%>
 <%= hidden_field_tag 'back_url', url_for(params), :id => nil %>
 <div class="autoscroll">
 <table class="list issues">
@@ -27,8 +27,8 @@
   <% end %>
   <tr id="issue-<%= issue.id %>" class="hascontextmenu <%= cycle('odd', 'even') %> <%= issue.css_classes %> <%= level > 0 ? "idnt idnt-#{level}" : nil %>">
     <td class="checkbox hide-when-print"><%= check_box_tag("ids[]", issue.id, false, :id => nil) %></td>
-    <td class="id"><%= link_to issue.id, :controller => 'issues', :action => 'show', :id => issue %></td>
-        <% query.columns.each do |column| %><%= content_tag 'td', column_content(column, issue), :class => column.css_classes %><% end %>
+    <td class="id"><%= link_to issue.id, issue_path(issue) %></td>
+        <%= raw query.columns.map {|column| "<td class=\"#{column.css_classes}\">#{column_content(column, issue)}</td>"}.join %>
   </tr>
   <% end -%>
   </tbody>
index fcbd9d3fe8d4141e799d6276a70dafeee01782a8..ae34000f1cd9b8926d3f12a4346460683893c42e 100644 (file)
@@ -1,5 +1,5 @@
 <% if issues && issues.any? %>
-<% form_tag({}) do %>
+<%= form_tag({}) do %>
   <table class="list issues">
     <thead><tr>
     <th>#</th>
index e81676adadf9f589c48da3c83c493feeb58f0ad3..946b5255bfde498798ee3cf4002f45face00a7be 100644 (file)
@@ -7,7 +7,7 @@
                             ) + h(": #{i.subject}"))
          }.join("\n").html_safe %></ul>
 
-<% form_tag({:action => 'bulk_update'}, :id => 'bulk_edit_form') do %>
+<%= form_tag({:action => 'bulk_update'}, :id => 'bulk_edit_form') do %>
 <%= @issues.collect {|i| hidden_field_tag('ids[]', i.id)}.join("\n").html_safe %>
 <div class="box tabular">
 <fieldset class="attributes">
index 3491c78eb0862d5d70ec9c61d567faf49bc3588e..a8ca7882674aa86973f4c37c02cfe7164797f99c 100644 (file)
@@ -1,6 +1,6 @@
 <h2><%= l(:label_confirmation) %></h2>
 
-<% form_tag({}, :method => :delete)  do %>
+<%= form_tag({}, :method => :delete)  do %>
 <%= @issues.collect {|i| hidden_field_tag('ids[]', i.id)}.join("\n").html_safe %>
 <div class="box">
 <p><strong><%= l(:text_destroy_time_entries_question, :hours => number_with_precision(@hours, :precision => 2)) %></strong></p>
index e3e256deeebdc52991160db4b734f182597bf376..ac9da57dc2c562dbe8ea1f7f93657ad617813e76 100644 (file)
@@ -9,7 +9,7 @@
 <h2><%= @query.new_record? ? l(:label_issue_plural) : h(@query.name) %></h2>
 <% html_title(@query.new_record? ? l(:label_issue_plural) : @query.name) %>
 
-<% form_tag({ :controller => 'issues', :action => 'index', :project_id => @project },
+<%= form_tag({ :controller => 'issues', :action => 'index', :project_id => @project },
             :method => :get, :id => 'query_form') do %>
     <%= hidden_field_tag 'set_filter', '1' %>
     <div id="query_form_content" class="hide-when-print">
@@ -68,7 +68,7 @@
 
 <div id="csv-export-options" style="display:none;">
   <h3 class="title"><%= l(:label_export_options, :export_format => 'CSV') %></h3>
-  <% form_tag(params.merge({:format => 'csv',:page=>nil}), :method => :get, :id => 'csv-export-form') do %>
+  <%= form_tag(params.merge({:format => 'csv',:page=>nil}), :method => :get, :id => 'csv-export-form') do %>
   <p>
     <label><%= radio_button_tag 'columns', '', true %> <%= l(:description_selected_columns) %></label><br />
     <label><%= radio_button_tag 'columns', 'all' %> <%= l(:description_all_columns) %></label>
index 40042331774cf088c48517f47d447c3dc1634af9..4e8449570faaec3f165ec194d93071ad488de88b 100644 (file)
@@ -2,7 +2,7 @@
 
 <%= call_hook(:view_issues_new_top, {:issue => @issue}) %>
 
-<% labelled_form_for @issue, :url => project_issues_path(@project),
+<%= labelled_form_for @issue, :url => project_issues_path(@project),
                              :html => {:id => 'issue-form', :multipart => true} do |f| %>
   <%= error_messages_for 'issue' %>
   <%= hidden_field_tag 'copy_from', params[:copy_from] if params[:copy_from] %>
index f1311ac3bd8f298d6826ae1bc66153188ac2390d..f451dbbeb6fc9fc8f37fa3652ca639a433a144a5 100644 (file)
@@ -1,4 +1,4 @@
-<% form_remote_tag(:url => {}, :html => { :id => "journal-#{@journal.id}-form" }) do %>
+<%= form_remote_tag(:url => {}, :html => { :id => "journal-#{@journal.id}-form" }) do %>
     <%= label_tag "notes", l(:description_notes), :class => "hidden-for-sighted" %>
     <%= text_area_tag :notes, @journal.notes,
           :id => "journal_#{@journal.id}_notes",
index 1a7c3c816247c5659b1180e8efea405028390dec..68b175848bf8e6dd1c2ac8cff3555d6b19fe07e7 100644 (file)
     <div id="account">
         <%= render_menu :account_menu -%>
     </div>
-    <%= content_tag(
-           'div',
-           "#{l(:label_logged_as)} #{link_to_user(User.current, :format => :username)}".html_safe,
-           :id => 'loggedas') if User.current.logged? %>
+    <%= content_tag('div', "#{l(:label_logged_as)} #{link_to_user(User.current, :format => :username)}".html_safe, :id => 'loggedas') if User.current.logged? %>
     <%= render_menu :top_menu if User.current.logged? || !Setting.login_required? -%>
 </div>
 
 <div id="header">
     <% if User.current.logged? || !Setting.login_required? %>
     <div id="quick-search">
-        <% form_tag({:controller => 'search', :action => 'index', :id => @project}, :method => :get ) do %>
+        <%= form_tag({:controller => 'search', :action => 'index', :id => @project}, :method => :get ) do %>
         <%= hidden_field_tag(controller.default_search_scope, 1, :id => nil) if controller.default_search_scope %>
         <label for='q'>
           <%= link_to l(:label_search), {:controller => 'search', :action => 'index', :id => @project}, :accesskey => accesskey(:search) %>:
     <% end %>
 </div>
 
+<% content_for :sidebar do %>
+  <%= call_hook :view_layouts_base_sidebar %>
+<% end %>
+
 <%= tag('div', {:id => 'main', :class => (has_content?(:sidebar) ? '' : 'nosidebar')}, true) %>
     <div id="sidebar">
         <%= yield :sidebar %>
-        <%= call_hook :view_layouts_base_sidebar %>
     </div>
 
     <div id="content">
index 054297ceeee808fee9994a78fb80ca50ebe433ca..362f1b6b902c2cf9928e379d8cd4dfb286bf4995 100644 (file)
@@ -2,11 +2,13 @@
                :action => 'show', :project_id => @project,
                :id => @board %> &#187; <%= h @message.subject %></h2>
 
-<% form_for :message, @message,
-            :url => {:action => 'edit'},
-            :html => {:multipart => true,
-                      :id => 'message-form',
-                      :method => :post} do |f| %>
+<%= form_for @message, {
+               :as => :message,
+               :url => {:action => 'edit'},
+               :html => {:multipart => true,
+                         :id => 'message-form',
+                         :method => :post}
+          } do |f| %>
   <%= render :partial => 'form',
              :locals => {:f => f, :replying => !@message.parent.nil?} %>
   <%= submit_tag l(:button_save) %>
index f41e270790f3e5e57ca6dab031ba941a5a3bb15b..f1dddb6f5d635bbc272c3469dfeca28ad5cde4b1 100644 (file)
@@ -1,6 +1,6 @@
 <h2><%= link_to h(@board.name), :controller => 'boards', :action => 'show', :project_id => @project, :id => @board %> &#187; <%= l(:label_message_new) %></h2>
 
-<% form_for :message, @message, :url => {:action => 'new'}, :html => {:multipart => true, :id => 'message-form'} do |f| %>
+<%= form_for @message, :url => {:action => 'new'}, :html => {:multipart => true, :id => 'message-form'} do |f| %>
   <%= render :partial => 'form', :locals => {:f => f} %>
   <%= submit_tag l(:button_create) %>
   <%= link_to_remote l(:label_preview),
index 9edc8451fdc6ff24cc5e7ce815576156591e78d6..d0857cf46058ac136b5e1f5874b59ee6ab745078 100644 (file)
@@ -72,7 +72,7 @@
 <% if !@topic.locked? && authorize_for('messages', 'reply') %>
 <p><%= toggle_link l(:button_reply), "reply", :focus => 'message_content' %></p>
 <div id="reply" style="display:none;">
-<% form_for :reply, @reply, :url => {:action => 'reply', :id => @topic}, :html => {:multipart => true, :id => 'message-form'} do |f| %>
+<%= form_for @reply, :as => :reply, :url => {:action => 'reply', :id => @topic}, :html => {:multipart => true, :id => 'message-form'} do |f| %>
   <%= render :partial => 'form', :locals => {:f => f, :replying => true} %>
   <%= submit_tag l(:button_submit) %>
   <%= link_to_remote l(:label_preview),
index 9d6910bce62de5571b181e94ca1d83268629ebe0..47e94594910dfca25ef1d53ace8e8ed5d5d15c95 100644 (file)
@@ -6,7 +6,7 @@
 <h2><%=l(:label_my_account)%></h2>
 <%= error_messages_for 'user' %>
 
-<% labelled_form_for :user, @user,
+<%= labelled_form_for :user, @user,
                      :url => { :action => "account" },
                      :html => { :id => 'my_account_form',
                                 :method => :post } do |f| %>
index 5d6eaa00468e543ffdfe9668217ea1310aa62ea8..68691412b3955a9325230583d98b5f71100f0761 100644 (file)
@@ -2,7 +2,7 @@
 <div class="warning">
 <p><%= simple_format l(:text_account_destroy_confirmation)%></p>
 <p>
-    <% form_tag({}) do %>
+    <%= form_tag({}) do %>
     <label><%= check_box_tag 'confirm', 1 %> <%= l(:general_text_Yes) %></label>
     <%= submit_tag l(:button_delete_my_account) %> |
                <%= link_to l(:button_cancel), :action => 'account' %>
index 67edb9f28ff93ee2c5b3bc0c5ad2e8b6c286accd..0025186d96ebbc97978daf4df66367555e56c3d6 100644 (file)
@@ -35,7 +35,7 @@ function removeBlock(block) {
 </script>
 
 <div class="contextual">
-<% form_tag({:action => "add_block"}, :id => "block-form") do %>
+<%= form_tag({:action => "add_block"}, :id => "block-form") do %>
 <%= label_tag('block-select', l(:label_my_page_block)) %>:
 <%= select_tag 'block',
                "<option></option>".html_safe + options_for_select(@block_options),
index 61d5c56caaa88346741c0a499eb65c09120a066d..de9a459e406c1bf1f37c1af3f5fc8a1a06ca8f1d 100644 (file)
@@ -2,7 +2,7 @@
 
 <%= error_messages_for 'user' %>
 
-<% form_tag({}, :class => "tabular") do %>
+<%= form_tag({}, :class => "tabular") do %>
 <div class="box">
 <p><label for="password"><%=l(:field_password)%> <span class="required">*</span></label>
 <%= password_field_tag 'password', nil, :size => 25 %></p>
index f00a024c1ad0759e05d73c11bf6cbc4ebe3bf1d0..5dd43c3cefb7774f772d8f13d51f30719b6e952a 100644 (file)
@@ -1,6 +1,6 @@
 <h2><%=l(:label_news)%></h2>
 
-<% labelled_form_for @news, :html => { :id => 'news-form', :multipart => true, :method => :put } do |f| %>
+<%= labelled_form_for @news, :html => { :id => 'news-form', :multipart => true, :method => :put } do |f| %>
 <%= render :partial => 'form', :locals => { :f => f } %>
 <%= submit_tag l(:button_save) %>
 <%= link_to_remote l(:label_preview),
index b839b5f4450e901c4acdb89d1fc6c454c71e1c34..b354adcb86a0682b06fc0ce7ecfc2d55aca69710 100644 (file)
@@ -7,7 +7,7 @@
 
 <div id="add-news" style="display:none;">
 <h2><%=l(:label_news_new)%></h2>
-<% labelled_form_for @news, :url => project_news_index_path(@project),
+<%= labelled_form_for @news, :url => project_news_index_path(@project),
                                            :html => { :id => 'news-form', :multipart => true } do |f| %>
 <%= render :partial => 'news/form', :locals => { :f => f } %>
 <%= submit_tag l(:button_create) %>
index 1c55215b7543c97d63444c881e3845bf37aee704..95a902432f55c6553909029df977fb8d75429541 100644 (file)
@@ -1,6 +1,6 @@
 <h2><%=l(:label_news_new)%></h2>
 
-<% labelled_form_for @news, :url => project_news_index_path(@project),
+<%= labelled_form_for @news, :url => project_news_index_path(@project),
                                            :html => { :id => 'news-form', :multipart => true } do |f| %>
   <%= render :partial => 'news/form', :locals => { :f => f } %>
   <%= submit_tag l(:button_create) %>
index b0b5f023e04e425fd1c8d0638c16b19e72f758ac..cb332f88c75519abef1aa7d1634d355c40c4bc2e 100644 (file)
@@ -16,7 +16,7 @@
 
 <% if authorize_for('news', 'edit') %>
 <div id="edit-news" style="display:none;">
-<% labelled_form_for :news, @news, :url => news_path(@news),
+<%= labelled_form_for :news, @news, :url => news_path(@news),
                                            :html => { :id => 'news-form', :multipart => true, :method => :put } do |f| %>
 <%= render :partial => 'form', :locals => { :f => f } %>
 <%= submit_tag l(:button_save) %>
@@ -55,7 +55,7 @@
 
 <% if @news.commentable? %>
 <p><%= toggle_link l(:label_comment_add), "add_comment_form", :focus => "comment_comments" %></p>
-<% form_tag({:controller => 'comments', :action => 'create', :id => @news}, :id => "add_comment_form", :style => "display:none;") do %>
+<%= form_tag({:controller => 'comments', :action => 'create', :id => @news}, :id => "add_comment_form", :style => "display:none;") do %>
 <div class="box">
     <%= text_area 'comment', 'comments', :cols => 80, :rows => 15, :class => 'wiki-edit' %>
     <%= wikitoolbar_for 'comment_comments' %>
index e52baa1167a9d8e9e27049a8044bdb1e8b25b71d..211762903c588f9d2f045a578a070c9b5b9984a8 100644 (file)
@@ -1,4 +1,4 @@
-<% labelled_form_for @project do |f| %>
+<%= labelled_form_for @project do |f| %>
 <%= render :partial => 'form', :locals => { :f => f } %>
 <%= submit_tag l(:button_save) %>
 <% end %>
index 66f6d335349a663716384254867fc3d6c1255ba7..26ec2e5a64755a3aabc4e5d3c6d0d3a9c76c6030 100644 (file)
@@ -1,6 +1,6 @@
 <h2><%=l(:label_project_new)%></h2>
 
-<% labelled_form_for @project, :url => { :action => "copy" } do |f| %>
+<%= labelled_form_for @project, :url => { :action => "copy" } do |f| %>
 <%= render :partial => 'form', :locals => { :f => f } %>
 
 <fieldset class="box tabular"><legend><%= l(:button_copy) %></legend>
index 23844ec67e49e1caadb9cf9f60a55064965d80fb..d4348b040d3e15d75e95c97a17f53cfdee29d2de 100644 (file)
@@ -8,7 +8,7 @@
 <% end %>
 </p>
 <p>
-    <% form_tag(project_path(@project_to_destroy), :method => :delete) do %>
+    <%= form_tag(project_path(@project_to_destroy), :method => :delete) do %>
     <label><%= check_box_tag 'confirm', 1 %> <%= l(:general_text_Yes) %></label>
     <%= submit_tag l(:button_delete) %>
     <% end %>
index b7cd8e6e8e2e9ab4054d1816c67067375069576d..42b400ff7b12f5feb281c8ab03d6fb8a57929582 100644 (file)
@@ -4,7 +4,7 @@
 
 <div class="contextual">
     <%= link_to(l(:label_project_new), {:controller => 'projects', :action => 'new'}, :class => 'icon icon-add') + ' |' if User.current.allowed_to?(:add_project, nil, :global => true) %>
-    <%= link_to(l(:label_issue_view_all), { :controller => 'issues' }) + ' |' if User.current.allowed_to?(:view_issues, nil, :global => true) %>
+    <%= link_to(l(:label_issue_view_all), issues_path) + ' |' if User.current.allowed_to?(:view_issues, nil, :global => true) %>
     <%= link_to(l(:label_overall_spent_time), time_entries_path) + ' |' if User.current.allowed_to?(:view_time_entries, nil, :global => true) %>
     <%= link_to l(:label_overall_activity),
                 { :controller => 'activities', :action => 'index',
index deca4e344d5424f9f135b0c09b0304efc1ecc44f..062073c5d44b37cfdd1bc2cd7d655415dbf29fc5 100644 (file)
@@ -1,6 +1,6 @@
 <h2><%=l(:label_project_new)%></h2>
 
-<% labelled_form_for @project do |f| %>
+<%= labelled_form_for @project do |f| %>
 <%= render :partial => 'form', :locals => { :f => f } %>
 <%= submit_tag l(:button_create) %>
 <%= submit_tag l(:button_create_and_continue), :name => 'continue' %>
index 296737dd52f42bb0d7f86a8efb8638b6a2a20009..0331cc8ac8855ba31821516eeaaaada0ebad1d91 100644 (file)
@@ -1,4 +1,4 @@
-<% form_tag(project_enumerations_path(@project), :method => :put, :class => "tabular") do %>
+<%= form_tag(project_enumerations_path(@project), :method => :put, :class => "tabular") do %>
 
 <table class="list">
   <thead><tr>
@@ -11,7 +11,7 @@
   </tr></thead>
 
   <% @project.activities(true).each do |enumeration| %>
-  <% fields_for "enumerations[#{enumeration.id}]", enumeration do |ff| %>
+  <%= fields_for "enumerations[#{enumeration.id}]", enumeration do |ff| %>
   <tr class="<%= cycle('odd', 'even') %>">
     <td>
       <%= ff.hidden_field :parent_id, :value => enumeration.id unless enumeration.project %>
index 437ea5e2ec0a8032be6d9bfbea9c2d18ece6b50b..e955d63f09cdf695a70affdde0ec7dadda0c4eda 100644 (file)
@@ -1,4 +1,4 @@
-<% form_for :project, @project,
+<%= form_for @project,
             :url => { :action => 'modules', :id => @project },
             :html => {:id => 'modules-form',
                       :method => :post} do |f| %>
index 5371bc4c884467bd601040a2b8de6ecbb1f0a6fc..4963ebbe47705047c7ecf4def472919494623fbf 100644 (file)
@@ -12,7 +12,7 @@
   </div>
   <ul>
   <% unless @project.homepage.blank? %>
-    <li><%=l(:field_homepage)%>: <%= auto_link(h(@project.homepage)).html_safe %></li>
+    <li><%=l(:field_homepage)%>: <%= link_to h(@project.homepage), @project.homepage %></li>
   <% end %>
   <% if @subprojects.any? %>
     <li><%=l(:label_subproject_plural)%>:
@@ -69,8 +69,8 @@
     <% if @total_hours.present? %>
     <h3><%= l(:label_spent_time) %></h3>
     <p><span class="icon icon-time"><%= l_hours(@total_hours) %></span></p>
-    <p><%= link_to(l(:label_details), {:controller => 'timelog', :action => 'index', :project_id => @project}) %> |
-    <%= link_to(l(:label_report), {:controller => 'timelog', :action => 'report', :project_id => @project}) %></p>
+    <p><%= link_to(l(:label_details), project_time_entries_path(@project)) %> |
+    <%= link_to(l(:label_report), report_project_time_entries_path(@project)) %></p>
     <% end %>
     <%= call_hook(:view_projects_show_sidebar_bottom, :project => @project) %>
 <% end %>
index ff84d854437e3c4117de758f9ae8f11c64d5d607..5bc6af2f369c2cf5466321d585c7fd8b2b166cb2 100644 (file)
@@ -5,7 +5,7 @@
 <% query.available_filters.sort{|a,b| a[1][:order]<=>b[1][:order]}.each do |filter| %>
     <% field = filter[0]
        options = filter[1] %>
-    <tr <%= 'style="display:none;"' unless query.has_filter?(field) %> id="tr_<%= field %>" class="filter">
+    <tr <%= 'style="display:none;"'.html_safe unless query.has_filter?(field) %> id="tr_<%= field %>" class="filter">
     <td class="field">
         <%= check_box_tag 'f[]', field, query.has_filter?(field), :onclick => "toggle_filter('#{field}');", :id => "cb_#{field}" %>
         <label for="cb_<%= field %>"><%= filter[1][:name] || l(("field_"+field.to_s.gsub(/\_id$/, "")).to_sym) %></label>
index 610ae01c3e7c12d647483474a23b7ff7ec4e08bd..a1534f82dad986dd390d9410e11a730d7097ff9e 100644 (file)
@@ -1,6 +1,6 @@
 <h2><%= l(:label_query) %></h2>
 
-<% form_tag(query_path(@query), :onsubmit => 'selectAllOptions("selected_columns");', :method => :put) do %>
+<%= form_tag(query_path(@query), :onsubmit => 'selectAllOptions("selected_columns");', :method => :put) do %>
   <%= render :partial => 'form', :locals => {:query => @query} %>
   <%= submit_tag l(:button_save) %>
 <% end %>
index 2ec7f66009394929f2e470b6512e584f0f256477..7081eee246ed983fc3ceacc654d9f132478e4fb7 100644 (file)
@@ -1,6 +1,6 @@
 <h2><%= l(:label_query_new) %></h2>
 
-<% form_tag(@project ? project_queries_path : queries_path, :onsubmit => 'selectAllOptions("selected_columns");') do %>
+<%= form_tag(@project ? project_queries_path(@project) : queries_path, :onsubmit => 'selectAllOptions("selected_columns");') do %>
   <%= render :partial => 'form', :locals => {:query => @query} %>
   <%= submit_tag l(:button_save) %>
 <% end %>
index ba38fed1a1762bdf9d33e9f7159944e46b85de80..a42daa8f51e5dddc6c5b02f2fcd51f6da834ab05 100644 (file)
@@ -6,7 +6,7 @@
             {:action => 'stats', :id => @project, :repository_id => @repository.identifier_param},
             :class => 'icon icon-stats' if @repository.supports_all_revisions? %>
 
-<% form_tag({:action => controller.action_name,
+<%= form_tag({:action => controller.action_name,
              :id => @project,
              :repository_id => @repository.identifier_param,
              :path => to_path_param(@path),
index e4a77388e36e685276ceb3e2e16c400a8a124748..d3059520b22103f9dcde962ffa0c0f5378523799 100644 (file)
@@ -14,7 +14,7 @@
             :space => graph_space
         }
 end %>
-<% form_tag(
+<%= form_tag(
       {:controller => 'repositories', :action => 'diff', :id => project,
        :repository_id => @repository.identifier_param, :path => to_path_param(path)},
       :method => :get
index f408d5382fc8c0b54ad0ebbe7b6b1b61fa5aea6e..a5426dfeee91ac5d925d3e4cd226c0ff6f6890d2 100644 (file)
@@ -6,7 +6,7 @@
 <p class="nodata"><%= l(:label_no_data) %></p>
 <% else %>
 
-<% form_tag({}) do %>
+<%= form_tag({}) do %>
 <table class="list">
 <thead>
   <tr>
index 738b4810acccea479587af2a5d79911f60501ea7..ecd19ccf8335243ff6ac71aa945cfcf185cf7265 100644 (file)
@@ -1,7 +1,7 @@
 <h2><%= l(:label_revision) %> <%= @diff_format_revisions %> <%=h @path %></h2>
 
 <!-- Choose view type -->
-<% form_tag({:path => to_path_param(@path)}, :method => 'get') do %>
+<%= form_tag({:path => to_path_param(@path)}, :method => 'get') do %>
   <%= hidden_field_tag('rev', params[:rev]) if params[:rev] %>
   <%= hidden_field_tag('rev_to', params[:rev_to]) if params[:rev_to] %>
   <p>
index 7a8d7d190b2a331c10234eca892ec5730315a131..78105acaaa0320e6089e5ed2dd34c8cfe7ebb769 100644 (file)
@@ -1,5 +1,5 @@
 <h2><%= l(:label_repository) %></h2>
 
-<% labelled_form_for :repository, @repository, :url => repository_path(@path), :html => {:method => :put} do |f| %>
+<%= labelled_form_for :repository, @repository, :url => repository_path(@path), :html => {:method => :put} do |f| %>
   <%= render :partial => 'form', :locals => {:f => f} %>
 <% end %>
index 9964042294cbe1e2346c2c079e191e5472bcb2a0..9f40c542f6042be4c3b3abb0c8f5c26dbdaf353b 100644 (file)
@@ -1,5 +1,5 @@
 <h2><%= l(:label_repository_new) %></h2>
 
-<% labelled_form_for :repository, @repository, :url => project_repositories_path(@project) do |f| %>
+<%= labelled_form_for :repository, @repository, :url => project_repositories_path(@project) do |f| %>
   <%= render :partial => 'form', :locals => {:f => f} %>
 <% end %>
index 4e7ad4c2a6b54f8fb19a23eabd7a82b3f5b86a52..c1e2413e1f66c00a735eae98ecfa8e9c4615e71c 100644 (file)
@@ -13,7 +13,7 @@
   <% end -%>
   &#187;&nbsp;
 
-  <% form_tag({:controller => 'repositories',
+  <%= form_tag({:controller => 'repositories',
                :action     => 'revision',
                :id         => @project,
                :repository_id => @repository.identifier_param,
index e2878fb7bf58fae4a77a73850619d9c836aa9b08..0395e4b965b92f69c5e170e700211df257aea31a 100644 (file)
@@ -1,6 +1,6 @@
 <div class="contextual">
-<% form_tag(
-       {:action => 'revision', :id => @project,
+<%= form_tag(
+       {:controller => 'repositories', :action => 'revision', :id => @project,
         :repository_id => @repository.identifier_param}
      ) do %>
   <%= l(:label_revision) %>: <%= text_field_tag 'rev', @rev, :size => 8 %>
index 3bb07c08ffae836b9320389bb6b93a69449e996c..7caca3002f6dde68def82e3757afbaf375ac5b2d 100644 (file)
@@ -1,6 +1,6 @@
 <h2><%= link_to l(:label_role_plural), roles_path %> &#187; <%=h @role.name %></h2>
 
-<% labelled_form_for @role do |f| %>
+<%= labelled_form_for @role do |f| %>
 <%= render :partial => 'form', :locals => { :f => f } %>
 <%= submit_tag l(:button_save) %>
 <% end %>
index 77f31a7c08e3809ed1f99b141000d021be8f37e1..0e5dfeb9c89e4e735970a35b4daa4dce154b6d98 100644 (file)
@@ -1,6 +1,6 @@
 <h2><%= link_to l(:label_role_plural), roles_path %> &#187; <%=l(:label_role_new)%></h2>
 
-<% labelled_form_for @role do |f| %>
+<%= labelled_form_for @role do |f| %>
 <%= render :partial => 'form', :locals => { :f => f } %>
 <%= submit_tag l(:button_create) %>
 <% end %>
index da8e1ad8b5042b40c2b646f7d8e3673bec05eb52..af78715e02931e8f710b307ffb706a407f17967e 100644 (file)
@@ -1,6 +1,6 @@
 <h2><%= link_to l(:label_role_plural), roles_path %> &#187; <%=l(:label_permissions_report)%></h2>
 
-<% form_tag(permissions_roles_path, :id => 'permissions_form') do %>
+<%= form_tag(permissions_roles_path, :id => 'permissions_form') do %>
 <%= hidden_field_tag 'permissions[0]', '', :id => nil %>
 <div class="autoscroll">
 <table class="list permissions">
index 7d24710bd97d34ac978c92855c32c07f17adcc91..6c9c56f4c2cce1027833e43507d4466234af5fdc 100644 (file)
@@ -1,7 +1,7 @@
 <h2><%= l(:label_search) %></h2>
 
 <div class="box">
-<% form_tag({}, :method => :get) do %>
+<%= form_tag({}, :method => :get) do %>
 <%= label_tag "search-input", l(:description_search), :class => "hidden-for-sighted" %>
 <p><%= text_field_tag 'q', @question, :size => 60, :id => 'search-input' %>
 <%= javascript_tag "Field.focus('search-input')" %>
index 14396e274cb151eb314d0cda7effb8367f093193..fe27e3d8812679fb354b774455b9311ac63e1ec9 100644 (file)
@@ -1,4 +1,4 @@
-<% form_tag({:action => 'edit', :tab => 'authentication'}) do %>
+<%= form_tag({:action => 'edit', :tab => 'authentication'}) do %>
 
 <div class="box tabular settings">
 <p><%= setting_check_box :login_required %></p>
index 25f65fc564b5fb4794563e554cdd99e2827a778e..3299ff10bc7c0a5f3fd2f87611ae7246d6c28bf2 100644 (file)
@@ -1,4 +1,4 @@
-<% form_tag({:action => 'edit', :tab => 'display'}) do %>
+<%= form_tag({:action => 'edit', :tab => 'display'}) do %>
 
 <div class="box tabular settings">
 <p><%= setting_select :ui_theme, Redmine::Themes.themes.collect {|t| [t.name, t.id]}, :blank => :label_default, :label => :label_theme %></p>
index befec041c6258b767ee9ed04f58d29b05b2880dc..4ec01995ae3f5b8ab4ac108ad0aaed2d04452e2c 100644 (file)
@@ -1,4 +1,4 @@
-<% form_tag({:action => 'edit'}) do %>
+<%= form_tag({:action => 'edit'}) do %>
 
 <div class="box tabular settings">
 <p><%= setting_text_field :app_title, :size => 30 %></p>
index 2ffa2111355a608ed43b17fe5f66ce3094cbab26..429685638695aad0f035f59738628e853bc12743 100644 (file)
@@ -1,4 +1,4 @@
-<% form_tag({:action => 'edit', :tab => 'issues'}) do %>
+<%= form_tag({:action => 'edit', :tab => 'issues'}) do %>
 
 <div class="box tabular settings">
 <p><%= setting_check_box :cross_project_issue_relations %></p>
index 3da97735387d7ff63312774f70c18fee6097c8ee..e4ddf5e994611730db0e59c1942757666c2969b1 100644 (file)
@@ -1,4 +1,4 @@
-<% form_tag({:action => 'edit', :tab => 'mail_handler'}) do %>
+<%= form_tag({:action => 'edit', :tab => 'mail_handler'}) do %>
 
 <div class="box tabular settings">
   <p>
index 26c11ad9a7e33982a52e0288b4fcd9f8d8f42a0e..f746f7cedbcfaf9e32ff9f5b12e5bd0df4d59640 100644 (file)
@@ -1,5 +1,5 @@
 <% if @deliveries %>
-<% form_tag({:action => 'edit', :tab => 'notifications'}) do %>
+<%= form_tag({:action => 'edit', :tab => 'notifications'}) do %>
 
 <div class="box tabular settings">
 <p><%= setting_text_field :mail_from, :size => 60 %></p>
index f61a0055de45e6c9dae83ddc22629391aed7ac93..90db6b1ceaf4375e6c84c63765cfd225dfd6cb7b 100644 (file)
@@ -1,4 +1,4 @@
-<% form_tag({:action => 'edit', :tab => 'projects'}) do %>
+<%= form_tag({:action => 'edit', :tab => 'projects'}) do %>
 
 <div class="box tabular settings">
 <p><%= setting_check_box :default_projects_public %></p>
index 9593a14c4a43eae87fec24186c9c6aef0eb2360c..d63c1db45c5683c8eba8a9e8f7088dab3d329f7f 100644 (file)
@@ -1,4 +1,4 @@
-<% form_tag({:action => 'edit', :tab => 'repositories'}) do %>
+<%= form_tag({:action => 'edit', :tab => 'repositories'}) do %>
 
 <fieldset class="box settings enabled_scm">
 <%= hidden_field_tag 'settings[enabled_scm][]', '' %>
index 61913484dab9571bf1f176e80b9743766eccb853..155f80c2258cd834b2549c1c23c82ad1edc0e53f 100644 (file)
@@ -1,7 +1,7 @@
 <h2><%= l(:label_settings) %>: <%=h @plugin.name %></h2>
 
 <div id="settings">
-<% form_tag({:action => 'plugin'}) do %>
+<%= form_tag({:action => 'plugin'}) do %>
 <div class="box tabular">
 <%= render :partial => @partial, :locals => {:settings => @settings}%>
 </div>
index 95e604dcf7fd14c4a1e8cfc7e2463f92577b8e1f..086f78bc2854983c015e2e3beab2b55ec8c170b5 100644 (file)
@@ -31,8 +31,8 @@
 <% url_params = @free_period ? { :from => @from, :to => @to } : { :period => params[:period] } %>
 <ul>
     <li><%= link_to(l(:label_details), url_params.merge({:controller => 'timelog', :action => 'index', :project_id => @project, :issue_id => @issue }),
-                                       :class => (@controller.action_name == 'index' ? 'selected' : nil)) %></li>
+                                       :class => (action_name == 'index' ? 'selected' : nil)) %></li>
     <li><%= link_to(l(:label_report), url_params.merge({:controller => 'timelog', :action => 'report', :project_id => @project, :issue_id => @issue}),
-                                       :class => (@controller.action_name == 'report' ? 'selected' : nil)) %></li>
+                                       :class => (action_name == 'report' ? 'selected' : nil)) %></li>
 </ul>
 </div>
index 4e86d78335c3d1438e7b6d83d0c67acdd16bf621..e916756c9c4b91b4f943ad5edc472b99e236e404 100644 (file)
@@ -1,4 +1,4 @@
-<% form_tag({}) do -%>
+<%= form_tag({}) do -%>
 <%= hidden_field_tag 'back_url', url_for(params) %>
 <div class="autoscroll">
 <table class="list time-entries">
index de1f9a365537a2c2f213a826f105b55f6c514252..dc0bd92f35685f6e1a19032d7680784742469ece 100644 (file)
@@ -7,7 +7,7 @@
      )}.join("\n").html_safe %>
 </ul>
 
-<% form_tag(:action => 'bulk_update') do %>
+<%= form_tag(:action => 'bulk_update') do %>
 <%= @time_entries.collect {|i| hidden_field_tag('ids[]', i.id)}.join.html_safe %>
 <div class="box tabular">
   <div>
index e5586e19af6cf83b551cb143c68319f2a8dc7365..db2e73cd58d58874d96feb5eebd94ba8a24e700b 100644 (file)
@@ -1,6 +1,6 @@
 <h2><%= l(:label_spent_time) %></h2>
 
-<% labelled_form_for @time_entry, :url => project_time_entry_path(@time_entry.project, @time_entry) do |f| %>
+<%= labelled_form_for @time_entry, :url => project_time_entry_path(@time_entry.project, @time_entry) do |f| %>
   <%= render :partial => 'form', :locals => {:f => f} %>
   <%= submit_tag l(:button_save) %>
 <% end %>
index c3a63436ef4d28df264ac9fc6a4b08109f222bc7..52c9118e7e2838afd5053c282b70b2467deb56cd 100644 (file)
@@ -8,7 +8,7 @@
 
 <h2><%= l(:label_spent_time) %></h2>
 
-<% form_tag({:controller => 'timelog', :action => 'index', :project_id => @project, :issue_id => @issue}, :method => :get, :id => 'query_form') do %>
+<%= form_tag({:controller => 'timelog', :action => 'index', :project_id => @project, :issue_id => @issue}, :method => :get, :id => 'query_form') do %>
 <%= render :partial => 'date_range' %>
 <% end %>
 
index f375743977220108535e1e09af20a279af8b5bcb..84bf7dae18151cbcfd6935cd5af14007eca22099 100644 (file)
@@ -1,6 +1,6 @@
 <h2><%= l(:label_spent_time) %></h2>
 
-<% labelled_form_for @time_entry, :url => time_entries_path do |f| %>
+<%= labelled_form_for @time_entry, :url => time_entries_path do |f| %>
   <%= render :partial => 'form', :locals => {:f => f} %>
   <%= submit_tag l(:button_create) %>
   <%= submit_tag l(:button_create_and_continue), :name => 'continue' %>
index 960d41b72e0736b958dccfc3db7c30cdca5489ef..4b9f0befe95f39e31eba91bb61fef25ffd33f4c8 100644 (file)
@@ -6,7 +6,9 @@
 
 <h2><%= l(:label_spent_time) %></h2>
 
-<% form_tag({:controller => 'timelog', :action => 'report', :project_id => @project, :issue_id => @issue}, :method => :get, :id => 'query_form') do %>
+<%= form_tag({:controller => 'timelog', :action => 'report',
+              :project_id => @project, :issue_id => @issue},
+            :method => :get, :id => 'query_form') do %>
   <% @report.criteria.each do |criterion| %>
     <%= hidden_field_tag 'criteria[]', criterion, :id => nil %>
   <% end %>
index b553704a02e6459f99c26b006d6b6a8860817530..76744c403d6b0d2344a0a927a5e77674366eca8f 100644 (file)
@@ -1,5 +1,5 @@
 <h2><%= link_to l(:label_tracker_plural), trackers_path %> &#187; <%=h @tracker %></h2>
 
-<% labelled_form_for @tracker do |f| %>
+<%= labelled_form_for @tracker do |f| %>
 <%= render :partial => 'form', :locals => { :f => f } %>
 <% end %>
index e4852579320af98abd9d4319521eb7eb7ff852ac..7bd8c6a00d88c21cc506ea659d92ddc7239122da 100644 (file)
@@ -1,5 +1,5 @@
 <h2><%= link_to l(:label_tracker_plural), trackers_path %> &#187; <%=l(:label_tracker_new)%></h2>
 
-<% labelled_form_for @tracker do |f| %>
+<%= labelled_form_for @tracker do |f| %>
 <%= render :partial => 'form', :locals => { :f => f } %>
 <% end %>
index b332e856e09116c83786fbf2533806e2b19cfba6..0daa421c76563974462af1c0c14613622a610e39 100644 (file)
@@ -1,4 +1,4 @@
-<% labelled_form_for @user do |f| %>
+<%= labelled_form_for @user do |f| %>
   <%= render :partial => 'form', :locals => { :f => f } %>
   <% if @user.active? && email_delivery_enabled? -%>
     <p><label><%= check_box_tag 'send_information', 1, true %> <%= l(:label_send_information) %></label></p>
index 0ab2f11eb768f4f53e9b88115e6a32971f076cdb..e24296ef0d73bfde76c25f2a3e22c720204edd61 100644 (file)
@@ -1,4 +1,4 @@
-<% form_for(:user, :url => { :action => 'update' }, :html => {:method => :put}) do %>
+<%= form_for(:user, :url => { :action => 'update' }, :html => {:method => :put}) do %>
 <div class="box">
 <% Group.all.sort.each do |group| %>
 <label><%= check_box_tag 'user[group_ids][]', group.id, @user.groups.include?(group) %> <%=h group %></label><br />
index 51fb111060f4281cc9825f608a0af0e66247524b..a480d2ac76a9007fadb8b86767d85c9ce1208b1a 100644 (file)
   </td>
   <td class="roles">
     <span id="member-<%= membership.id %>-roles"><%=h membership.roles.sort.collect(&:to_s).join(', ') %></span>
-    <% remote_form_for(:membership, :url => user_membership_path(@user, membership), :method => :put,
-                                    :html => { :id => "member-#{membership.id}-roles-form", :style => 'display:none;'}) do %>
+    <%= form_for(:membership, :remote => true,
+                 :url => user_membership_path(@user, membership), :method => :put,
+                 :html => {:id => "member-#{membership.id}-roles-form",
+                           :style => 'display:none;'}) do %>
         <p><% roles.each do |role| %>
         <label><%= check_box_tag 'membership[role_ids][]', role.id, membership.roles.include?(role),
                                                            :disabled => membership.member_roles.detect {|mr| mr.role_id == role.id && !mr.inherited_from.nil?} %> <%=h role %></label><br />
@@ -57,7 +59,7 @@
 <div class="splitcontentright">
 <% if projects.any? %>
 <fieldset><legend><%=l(:label_project_new)%></legend>
-<% remote_form_for(:membership, :url => user_memberships_path(@user)) do %>
+<%= form_for(:membership, :remote => true, :url => user_memberships_path(@user)) do %>
 <%= select_tag 'membership[project_id]', options_for_membership_project_select(@user, projects) %>
 <p><%= l(:label_role_plural) %>:
 <% roles.each do |role| %>
index a5a0e5cb133abe3d05beefcb09c6bd6badb5b211..26e83b1232941e7b3603070b5ba2e1e0fa71dd64 100644 (file)
@@ -1,4 +1,4 @@
-<% labelled_fields_for :pref, @user.pref do |pref_fields| %>
+<%= labelled_fields_for :pref, @user.pref do |pref_fields| %>
 <p><%= pref_fields.check_box :hide_mail %></p>
 <p><%= pref_fields.select :time_zone, ActiveSupport::TimeZone.all.collect {|z| [ z.to_s, z.name ]}, :include_blank => true %></p>
 <p><%= pref_fields.select :comments_sorting, [[l(:label_chronological_order), 'asc'], [l(:label_reverse_chronological_order), 'desc']] %></p>
index 3decdc971f880da15305e7cbebd18c79988e7ef9..d23be4ad2096a6c74753463856ceee4c79f67c87 100644 (file)
@@ -4,7 +4,7 @@
 
 <h2><%=l(:label_user_plural)%></h2>
 
-<% form_tag({}, :method => :get) do %>
+<%= form_tag({}, :method => :get) do %>
 <fieldset><legend><%= l(:label_filter_plural) %></legend>
 <label for='status'><%= l(:field_status) %>:</label>
 <%= select_tag 'status', users_status_options_for_select(@status), :class => "small", :onchange => "this.form.submit(); return false;"  %>
index eb8a9f93d43086a6bbbefe8dae9fdd9bfc33e448..3eecf4a20d71716a1b5b158c50b5fc3c389346aa 100644 (file)
@@ -1,6 +1,6 @@
 <h2><%= link_to l(:label_user_plural), users_path %> &#187; <%=l(:label_user_new)%></h2>
 
-<% labelled_form_for @user do |f| %>
+<%= labelled_form_for @user do |f| %>
   <%= render :partial => 'form', :locals => { :f => f } %>
   <% if email_delivery_enabled? %>
   <p><label><%= check_box_tag 'send_information', 1, true %> <%= l(:label_send_information) %></label></p>
index 78b77e4089fa33abdd90f56615f3c332b4f54207..e4bb6e666ea92234161ac69053b2d268805e7404 100644 (file)
@@ -1,4 +1,4 @@
-<% form_tag({}, :id => "status_by_form") do -%>
+<%= form_tag({}, :id => "status_by_form") do -%>
 <fieldset>
 <legend>
 <%= l(:label_issues_by,
index 8b58883c81cf24f2cde4a8dd7340b0c76eb023ba..cd51fdc932227df429efebae3d55e6f5a0e86b45 100644 (file)
@@ -1,6 +1,6 @@
 <h3 class="title"><%=l(:label_version_new)%></h3>
 
-<% labelled_remote_form_for @version, :url => project_versions_path(@project) do |f| %>
+<%= labelled_remote_form_for :version, @version, :url => project_versions_path(@project) do |f| %>
 <%= render :partial => 'versions/form', :locals => { :f => f } %>
   <p class="buttons">
     <%= submit_tag l(:button_create), :name => nil %>
index 6c8f5a5799b505199cb348e9e23bee2eed9363da..3c67f09c055fbf5f1ba7d55f9582193064b5545f 100644 (file)
@@ -1,6 +1,6 @@
 <h2><%=l(:label_version)%></h2>
 
-<% labelled_form_for @version do |f| %>
+<%= labelled_form_for @version do |f| %>
 <%= render :partial => 'form', :locals => { :f => f } %>
 <%= submit_tag l(:button_save) %>
 <% end %>
index 71a756ea707da465dd751d39e6ffef1dc8acd3a7..d8ac53401e8f9356f5e7f6e530af986cce1ecc08 100644 (file)
@@ -14,7 +14,7 @@
     <%= render(:partial => "wiki/content", :locals => {:content => version.wiki_page.content}) if version.wiki_page %>
 
     <% if (issues = @issues_by_version[version]) && issues.size > 0 %>
-    <% form_tag({}) do -%>
+    <%= form_tag({}) do -%>
     <table class="list related-issues">
     <caption><%= l(:label_related_issues) %></caption>
     <% issues.each do |issue| -%>
@@ -32,7 +32,7 @@
 <% end %>
 
 <% content_for :sidebar do %>
-<% form_tag({}, :method => :get) do %>
+<%= form_tag({}, :method => :get) do %>
 <h3><%= l(:label_roadmap) %></h3>
 <% @trackers.each do |tracker| %>
   <label><%= check_box_tag "tracker_ids[]", tracker.id, (@selected_tracker_ids.include? tracker.id.to_s), :id => nil %>
index 2a51957a1af9953f9ced3ec7d9ef998aac075e32..c63edade7eeef4f0ed10aee53b23796f8f6ae945 100644 (file)
@@ -1,6 +1,6 @@
 <h2><%=l(:label_version_new)%></h2>
 
-<% labelled_form_for @version, :url => project_versions_path(@project) do |f| %>
+<%= labelled_form_for @version, :url => project_versions_path(@project) do |f| %>
 <%= render :partial => 'versions/form', :locals => { :f => f } %>
 <%= submit_tag l(:button_create) %>
 <% end %>
index 07ae0b1cc6af29f4e4d818b57c3b219a48a18592..f44e3f272af23d6bd14aa876a767627cec1cb90b 100644 (file)
@@ -36,7 +36,7 @@
 </div>
 
 <% if @issues.present? %>
-<% form_tag({}) do -%>
+<%= form_tag({}) do -%>
   <table class="list related-issues">
   <caption><%= l(:label_related_issues) %></caption>
   <%- @issues.each do |issue| -%>
index c2c133ee7a55bc6652c6287153c48b6e4c05a2a6..4220776f3da0af0a9fb4f318d336c96f82ad063a 100644 (file)
@@ -1,6 +1,6 @@
 <h3 class="title"><%= l(:permission_add_issue_watchers) %></h3>
 
-<% form_remote_tag :url => {:controller => 'watchers',
+<%= form_remote_tag :url => {:controller => 'watchers',
                             :action => (watched ? 'create' : 'append'),
                             :object_type => watched.class.name.underscore,
                             :object_id => watched},
index 9a24963f28ca67215438504cb35d1e1d379f130a..b4034d88bcc883eb63ac81a62970dd0bf762f1ca 100644 (file)
@@ -6,4 +6,4 @@
 
 <%= link_to l(:field_start_page), {:action => 'show', :id => nil} %><br />
 <%= link_to l(:label_index_by_title), {:action => 'index'} %><br />
-<%= link_to l(:label_index_by_date), {:action => 'date_index'} %><br />
+<%= link_to l(:label_index_by_date), {:controller => 'wiki', :project_id => @project, :action => 'date_index'} %><br />
index a3cc476bf73aea08908f55608e8a7437d273fea6..05c0fd56d3313d6c19ccd5ad8507eb4590d57018 100644 (file)
@@ -2,7 +2,7 @@
 
 <h2><%=h @page.pretty_title %></h2>
 
-<% form_tag({}, :method => :delete) do %>
+<%= form_tag({}, :method => :delete) do %>
 <div class="box">
 <p><strong><%= l(:text_wiki_page_destroy_question, :descendants => @descendants_count) %></strong></p>
 <p><label><%= radio_button_tag 'todo', 'nullify', true %> <%= l(:text_wiki_page_nullify_children) %></label><br />
index 2816579907e7e400aca5a7ccc882517986fc37e6..51d8ab94e2211eb125bed32133a1aa1ef550891c 100644 (file)
@@ -2,7 +2,7 @@
 
 <h2><%= h @page.pretty_title %></h2>
 
-<% form_for :content, @content,
+<%= form_for @content, :as => :content,
             :url => {:action => 'update', :id => @page.title},
             :html => {:method => :put, :multipart => true, :id => 'wiki_form'} do |f| %>
 <%= f.hidden_field :version %>
 <%= text_area_tag 'content[text]', @text, :cols => 100, :rows => 25, :class => 'wiki-edit', :accesskey => accesskey(:edit) %>
 
 <% if @page.safe_attribute_names.include?('parent_id') && @wiki.pages.any? %>
-  <% fields_for @page do |fp| %>
+  <%= fields_for @page do |fp| %>
     <p>
       <label><%= l(:field_parent_title) %></label>
-      <%= fp.select :parent_id, "<option value=''></option>" + wiki_page_options_for_select(@wiki.pages.all(:include => :parent) - @page.self_and_descendants, @page.parent) %>
+      <%= fp.select :parent_id, content_tag('option', '', :value => '') + wiki_page_options_for_select(@wiki.pages.all(:include => :parent) - @page.self_and_descendants, @page.parent) %>
     </p>
   <% end %>
 <% end %>
index cfbf641542d23c3a54fc3e89d3b99fed9f56046b..fa9effd1ae042fed2f1919d1768e7a80f054211d 100644 (file)
@@ -4,7 +4,9 @@
 
 <h3><%= l(:label_history) %></h3>
 
-<% form_tag({:controller => 'wiki', :action => 'diff', :project_id => @page.project, :id => @page.title}, :method => :get) do %>
+<%= form_tag({:controller => 'wiki', :action => 'diff',
+              :project_id => @page.project, :id => @page.title},
+              :method => :get) do %>
 <table class="list wiki-page-versions">
 <thead><tr>
     <th>#</th>
index fea76383a55e69591be52e483d0467d661566266..86385a94b038149cff096f481fe60f372db48690 100644 (file)
@@ -4,14 +4,14 @@
 
 <%= error_messages_for 'page' %>
 
-<% labelled_form_for :wiki_page, @page,
+<%= labelled_form_for :wiki_page, @page,
                      :url => { :action => 'rename' },
                      :html => { :method => :post } do |f| %>
 <div class="box tabular">
 <p><%= f.text_field :title, :required => true, :size => 100  %></p>
 <p><%= f.check_box :redirect_existing_links %></p>
 <p><%= f.select :parent_id,
-                "<option value=''></option>" + 
+                content_tag('option', '', :value => '') + 
                   wiki_page_options_for_select(
                     @wiki.pages.all(:include => :parent) - @page.self_and_descendants,
                     @page.parent),
index 19215bb98be6c01cca9eee3aa96a9e26214123da..0ef8fc869d4ce0359b92b1fcff2154dc6e3e44a0 100644 (file)
 <div id="wiki_add_attachment">
 <p><%= link_to l(:label_attachment_new), {}, :onclick => "Element.show('add_attachment_form'); Element.hide(this); Element.scrollTo('add_attachment_form'); return false;",
                                              :id => 'attach_files_link' %></p>
-<% form_tag({ :controller => 'wiki', :action => 'add_attachment', :project_id => @project, :id => @page.title }, :multipart => true, :id => "add_attachment_form", :style => "display:none;") do %>
+<%= form_tag({:controller => 'wiki', :action => 'add_attachment',
+              :project_id => @project, :id => @page.title},
+             :multipart => true, :id => "add_attachment_form",
+             :style => "display:none;") do %>
   <div class="box">
   <p><%= render :partial => 'attachments/form' %></p>
   </div>
index 75c0eac24d6c5e38fd97e11866ef06bf97b9e989..bc33600141e25e2f95604d84002b25f2ec8ffd27 100644 (file)
@@ -3,7 +3,7 @@
 <div class="box"><center>
 <p><strong><%= h(@project.name) %></strong><br /><%=l(:text_wiki_destroy_confirmation)%></p>
 
-<% form_tag({:controller => 'wikis', :action => 'destroy', :id => @project}) do %>
+<%= form_tag({:controller => 'wikis', :action => 'destroy', :id => @project}) do %>
 <%= hidden_field_tag "confirm", 1 %>
 <%= submit_tag l(:button_delete) %>
 <% end %>
index cbe13b42bb3ac894f04f5a6a1bdc5a36cf3a89e5..057e40367051306295cb34e84dcd6d05d8095f9b 100644 (file)
@@ -2,7 +2,7 @@
 
 <h2><%=l(:label_workflow)%></h2>
 
-<% form_tag({}, :id => 'workflow_copy_form') do %>
+<%= form_tag({}, :id => 'workflow_copy_form') do %>
 <fieldset class="tabular box">
 <legend><%= l(:label_copy_source) %></legend>
 <p>
index 8dc509904a1b474e2e96ada52aa0ec7fd64ca6f7..20eaff992d9006a36b22e9f14d1299f3e104c727 100644 (file)
@@ -4,7 +4,7 @@
 
 <p><%=l(:text_workflow_edit)%>:</p>
 
-<% form_tag({}, :method => 'get') do %>
+<%= form_tag({}, :method => 'get') do %>
 <p>
   <label><%=l(:label_role)%>:
   <%= select_tag 'role_id', options_from_collection_for_select(@roles, "id", "name", @role && @role.id) %></label>
@@ -21,7 +21,7 @@
 <% end %>
 
 <% if @tracker && @role && @statuses.any? %>
-  <% form_tag({}, :id => 'workflow_form' ) do %>
+  <%= form_tag({}, :id => 'workflow_form' ) do %>
     <%= hidden_field_tag 'tracker_id', @tracker.id %>
     <%= hidden_field_tag 'role_id', @role.id %>
     <div class="autoscroll">
diff --git a/config.ru b/config.ru
new file mode 100644 (file)
index 0000000..2a89752
--- /dev/null
+++ b/config.ru
@@ -0,0 +1,4 @@
+# This file is used by Rack-based servers to start the application.
+
+require ::File.expand_path('../config/environment',  __FILE__)
+run RedmineApp::Application
diff --git a/config/application.rb b/config/application.rb
new file mode 100644 (file)
index 0000000..4cd7041
--- /dev/null
@@ -0,0 +1,56 @@
+require File.expand_path('../boot', __FILE__)
+
+require 'rails/all'
+
+if defined?(Bundler)
+  # If you precompile assets before deploying to production, use this line
+  Bundler.require(*Rails.groups(:assets => %w(development test)))
+  # If you want your assets lazily compiled in production, use this line
+  # Bundler.require(:default, :assets, Rails.env)
+end
+
+module RedmineApp
+  class Application < Rails::Application
+    # Settings in config/environments/* take precedence over those specified here.
+    # Application configuration should go into files in config/initializers
+    # -- all .rb files in that directory are automatically loaded.
+
+    # Custom directories with classes and modules you want to be autoloadable.
+    config.autoload_paths += %W(#{config.root}/lib)
+
+    # Only load the plugins named here, in the order given (default is alphabetical).
+    # :all can be used as a placeholder for all plugins not explicitly named.
+    # config.plugins = [ :exception_notification, :ssl_requirement, :all ]
+
+    # Activate observers that should always be running.
+    config.active_record.observers = :message_observer, :issue_observer, :journal_observer, :news_observer, :document_observer, :wiki_content_observer, :comment_observer
+
+    config.active_record.store_full_sti_class = true
+
+    # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
+    # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
+    # config.time_zone = 'Central Time (US & Canada)'
+
+    # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
+    # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
+    # config.i18n.default_locale = :de
+
+    # Configure the default encoding used in templates for Ruby 1.9.
+    config.encoding = "utf-8"
+
+    # Configure sensitive parameters which will be filtered from the log file.
+    config.filter_parameters += [:password]
+
+    # Enable the asset pipeline
+    config.assets.enabled = false
+
+    # Version of your assets, change this if you want to expire all your assets
+    config.assets.version = '1.0'
+
+    config.action_mailer.perform_deliveries = false
+
+    if File.exists?(File.join(File.dirname(__FILE__), 'additional_environment.rb'))
+      instance_eval File.read(File.join(File.dirname(__FILE__), 'additional_environment.rb'))
+    end
+  end
+end
index cfc60f758ba9f60395d1dc633e3ec3c1d1da3f2d..4489e58688ca642d8e0e9489f6896f49f9b89da6 100644 (file)
@@ -1,124 +1,6 @@
-# Don't change this file!
-# Configure your app in config/environment.rb and config/environments/*.rb
+require 'rubygems'
 
-if RUBY_VERSION >= '1.9'
-  require 'yaml'
-  YAML::ENGINE.yamler = 'syck'
-end
+# Set up gems listed in the Gemfile.
+ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
 
-RAILS_ROOT = "#{File.dirname(__FILE__)}/.." unless defined?(RAILS_ROOT)
-
-module Rails
-  class << self
-    def boot!
-      unless booted?
-        preinitialize
-        pick_boot.run
-      end
-    end
-
-    def booted?
-      defined? Rails::Initializer
-    end
-
-    def pick_boot
-      (vendor_rails? ? VendorBoot : GemBoot).new
-    end
-
-    def vendor_rails?
-      File.exist?("#{RAILS_ROOT}/vendor/rails")
-    end
-
-    def preinitialize
-      load(preinitializer_path) if File.exist?(preinitializer_path)
-    end
-
-    def preinitializer_path
-      "#{RAILS_ROOT}/config/preinitializer.rb"
-    end
-  end
-
-  class Boot
-    def run
-      load_initializer
-      Rails::Initializer.class_eval do
-        def load_gems
-          @bundler_loaded ||= Bundler.require :default, Rails.env
-        end
-      end
-      Rails::Initializer.run(:set_load_path)
-    end
-  end
-
-  class VendorBoot < Boot
-    def load_initializer
-      require "#{RAILS_ROOT}/vendor/rails/railties/lib/initializer"
-      Rails::Initializer.run(:install_gem_spec_stubs)
-      Rails::GemDependency.add_frozen_gem_path
-    end
-  end
-
-  class GemBoot < Boot
-    def load_initializer
-      self.class.load_rubygems
-      load_rails_gem
-      require 'initializer'
-    end
-
-    def load_rails_gem
-      if version = self.class.gem_version
-        gem 'rails', version
-      else
-        gem 'rails'
-      end
-    rescue Gem::LoadError => load_error
-      if load_error.message =~ /Could not find RubyGem rails/
-        STDERR.puts %(Missing the Rails #{version} gem. Please `gem install -v=#{version} rails`, update your RAILS_GEM_VERSION setting in config/environment.rb for the Rails version you do have installed, or comment out RAILS_GEM_VERSION to use the latest version installed.)
-        exit 1
-      else
-        raise
-      end
-    end
-
-    class << self
-      def rubygems_version
-        Gem::RubyGemsVersion rescue nil
-      end
-
-      def gem_version
-        if defined? RAILS_GEM_VERSION
-          RAILS_GEM_VERSION
-        elsif ENV.include?('RAILS_GEM_VERSION')
-          ENV['RAILS_GEM_VERSION']
-        else
-          parse_gem_version(read_environment_rb)
-        end
-      end
-
-      def load_rubygems
-        min_version = '1.3.2'
-        require 'rubygems'
-        unless rubygems_version >= min_version
-          $stderr.puts %Q(Rails requires RubyGems >= #{min_version} (you have #{rubygems_version}). Please `gem update --system` and try again.)
-          exit 1
-        end
-
-      rescue LoadError
-        $stderr.puts %Q(Rails requires RubyGems >= #{min_version}. Please install RubyGems and try again: http://rubygems.rubyforge.org)
-        exit 1
-      end
-
-      def parse_gem_version(text)
-        $1 if text =~ /^[^#]*RAILS_GEM_VERSION\s*=\s*["']([!~<>=]*\s*[\d.]+)["']/
-      end
-
-      private
-        def read_environment_rb
-          File.read("#{RAILS_ROOT}/config/environment.rb")
-        end
-    end
-  end
-end
-
-# All that for this:
-Rails.boot!
+require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
index 3da0fe490efddb11e8937c77ce4d710f17fdfaa4..39857ea77d7f8d434ad8cb80c825049861a51c5f 100644 (file)
@@ -1,59 +1,5 @@
-# Be sure to restart your web server when you modify this file.
+# Load the rails application
+require File.expand_path('../application', __FILE__)
 
-# Uncomment below to force Rails into production mode when
-# you don't control web/app server and can't set it the proper way
-# ENV['RAILS_ENV'] ||= 'production'
-
-# Bootstrap the Rails environment, frameworks, and default configuration
-require File.join(File.dirname(__FILE__), 'boot')
-
-if RUBY_VERSION >= '1.9' && defined?(Rails) && Rails::VERSION::MAJOR < 3
-  Encoding.default_external = 'UTF-8'
-end
-
-# Load Engine plugin if available
-begin
-  require File.join(File.dirname(__FILE__), '../vendor/plugins/engines/boot')
-rescue LoadError
-  # Not available
-end
-
-Rails::Initializer.run do |config|
-  # Settings in config/environments/* take precedence those specified here
-
-  # Skip frameworks you're not going to use
-  # config.frameworks -= [ :action_web_service, :action_mailer ]
-
-  # Add additional load paths for sweepers
-  config.autoload_paths += %W( #{RAILS_ROOT}/app/sweepers )
-
-  # Force all environments to use the same logger level
-  # (by default production uses :info, the others :debug)
-  # config.log_level = :debug
-
-  # Enable page/fragment caching by setting a file-based store
-  # (remember to create the caching directory and make it readable to the application)
-  # config.action_controller.cache_store = :file_store, "#{RAILS_ROOT}/tmp/cache"
-
-  # Activate observers that should always be running
-  # config.active_record.observers = :cacher, :garbage_collector
-  config.active_record.observers = :message_observer, :issue_observer, :journal_observer, :news_observer, :document_observer, :wiki_content_observer, :comment_observer
-
-  # Make Active Record use UTC-base instead of local time
-  # config.active_record.default_timezone = :utc
-
-  # Use Active Record's schema dumper instead of SQL when creating the test database
-  # (enables use of different database adapters for development and test environments)
-  # config.active_record.schema_format = :ruby
-
-  # Deliveries are disabled by default. Do NOT modify this section.
-  # Define your email configuration in configuration.yml instead.
-  # It will automatically turn deliveries on
-  config.action_mailer.perform_deliveries = false
-
-  # Load any local configuration that is kept out of source control
-  # (e.g. gems, patches).
-  if File.exists?(File.join(File.dirname(__FILE__), 'additional_environment.rb'))
-    instance_eval File.read(File.join(File.dirname(__FILE__), 'additional_environment.rb'))
-  end
-end
+# Initialize the rails application
+RedmineApp::Application.initialize!
index c816f03e3b8c265d39d63e8f4730c20d1967e96f..9657d8f11c69c1a3519aea943ee0ae9a259c97a9 100644 (file)
@@ -1,16 +1,19 @@
 # Settings specified here will take precedence over those in config/environment.rb
+RedmineApp::Application.configure do
+  # 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
 
-# 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
 
-# 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
 
-# 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
 
-# Don't care if the mailer can't send
-config.action_mailer.raise_delivery_errors = false
+  config.active_support.deprecation = :log
+end
index 91af89ce24f42af3d22e8aeac13ff7d8ac92fd30..9ff88560d5c3501e9adca57050265e91839673fe 100644 (file)
@@ -1,30 +1,32 @@
 # Settings specified here will take precedence over those in config/environment.rb
+RedmineApp::Application.configure do
+  # The production environment is meant for finished, "live" apps.
+  # Code is not reloaded between requests
+  config.cache_classes = true
 
-# The production environment is meant for finished, "live" apps.
-# Code is not reloaded between requests
-config.cache_classes = true
+  #####
+  # Customize the default logger (http://ruby-doc.org/core/classes/Logger.html)
+  #
+  # Use a different logger for distributed setups
+  # config.logger        = SyslogLogger.new
+  #
+  # Rotate logs bigger than 1MB, keeps no more than 7 rotated logs around.
+  # When setting a new Logger, make sure to set it's log level too.
+  #
+  # config.logger = Logger.new(config.log_path, 7, 1048576)
+  # config.logger.level = Logger::INFO
 
-#####
-# Customize the default logger (http://ruby-doc.org/core/classes/Logger.html)
-#
-# Use a different logger for distributed setups
-# config.logger        = SyslogLogger.new
-#
-# Rotate logs bigger than 1MB, keeps no more than 7 rotated logs around.
-# When setting a new Logger, make sure to set it's log level too.
-#
-# config.logger = Logger.new(config.log_path, 7, 1048576)
-# config.logger.level = Logger::INFO
+  # Full error reports are disabled and caching is turned on
+  config.action_controller.perform_caching = true
 
-# Full error reports are disabled and caching is turned on
-config.action_controller.consider_all_requests_local = false
-config.action_controller.perform_caching             = true
+  # Enable serving of images, stylesheets, and javascripts from an asset server
+  # config.action_controller.asset_host                  = "http://assets.example.com"
 
-# Enable serving of images, stylesheets, and javascripts from an asset server
-# config.action_controller.asset_host                  = "http://assets.example.com"
+  # Disable delivery errors if you bad email addresses should just be ignored
+  config.action_mailer.raise_delivery_errors = false
 
-# Disable delivery errors if you bad email addresses should just be ignored
-config.action_mailer.raise_delivery_errors = false
+  # No email in production log
+  config.action_mailer.logger = nil
 
-# No email in production log
-config.action_mailer.logger = nil
+  config.active_support.deprecation = :log
+end
index 4ce45527adae573dbbf7eeb3bd47fd929b7ddaa0..39b4738b706223dbf88d01c0cc514dccb2750edb 100644 (file)
@@ -1,25 +1,25 @@
 # Settings specified here will take precedence over those in config/environment.rb
+RedmineApp::Application.configure do
+  # The test environment is used exclusively to run your application's
+  # test suite.  You never need to work with it otherwise.  Remember that
+  # your test database is "scratch space" for the test suite and is wiped
+  # and recreated between test runs.  Don't rely on the data there!
+  config.cache_classes = true
 
-# The test environment is used exclusively to run your application's
-# test suite.  You never need to work with it otherwise.  Remember that
-# your test database is "scratch space" for the test suite and is wiped
-# and recreated between test runs.  Don't rely on the data there!
-config.cache_classes = true
+  # Log error messages when you accidentally call methods on nil.
+  config.whiny_nils = true
 
-# 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
 
-# Show full error reports and disable caching
-config.action_controller.consider_all_requests_local = true
-config.action_controller.perform_caching             = false
+  config.action_mailer.perform_deliveries = true
+  config.action_mailer.delivery_method = :test
 
-config.action_mailer.perform_deliveries = true
-config.action_mailer.delivery_method = :test
+  # Skip protect_from_forgery in requests http://m.onkey.org/2007/9/28/csrf-protection-for-your-existing-rails-application
+  config.action_controller.allow_forgery_protection = false
 
-config.action_controller.session = { 
-  :key => "_test_session",
-  :secret => "some secret phrase for the tests."
-}
+  config.active_support.deprecation = :log
 
-# Skip protect_from_forgery in requests http://m.onkey.org/2007/9/28/csrf-protection-for-your-existing-rails-application
-config.action_controller.allow_forgery_protection  = false
+  config.secret_token = 'a secret token for running the tests'
+end
index 9591070485b971dd6b320a5a4ea8f078a1c1aa6f..484ea1fb7adac0568251fcbeb87cc901eb7d0226 100644 (file)
@@ -8,6 +8,9 @@ require 'active_record'
 module ActiveRecord
   class Base
     include Redmine::I18n
+    def self.named_scope(*args)
+      scope(*args)
+    end
 
     # Translate attribute names for validation errors display
     def self.human_attribute_name(attr, *args)
@@ -35,6 +38,18 @@ module ActionView
       end
     end
   end
+
+  class Resolver
+    def find_all(name, prefix=nil, partial=false, details={}, key=nil, locals=[])
+      cached(key, [name, prefix, partial], details, locals) do
+        if details[:formats] & [:xml, :json]
+          details = details.dup
+          details[:formats] = details[:formats].dup + [:api]
+        end
+        find_templates(name, prefix, partial, details)
+      end
+    end
+  end
 end
 
 ActionView::Base.field_error_proc = Proc.new{ |html_tag, instance| "#{html_tag}" }
@@ -60,26 +75,9 @@ end
 
 ActionMailer::Base.send :include, AsynchronousMailer
 
-module TMail
-  # TMail::Unquoter.convert_to_with_fallback_on_iso_8859_1 introduced in TMail 1.2.7
-  # triggers a test failure in test_add_issue_with_japanese_keywords(MailHandlerTest)
-  class Unquoter
-    class << self
-      alias_method :convert_to, :convert_to_without_fallback_on_iso_8859_1
-    end
-  end
-
-  # Patch for TMail 1.2.7. See http://www.redmine.org/issues/8751
-  class Encoder
-    def puts_meta(str)
-      add_text str
-    end
-  end
-end
-
 module ActionController
   module MimeResponds
-    class Responder
+    class Collector
       def api(&block)
         any(:xml, :json, &block)
       end
index dabac346303a70e52b0fbe95f848f2d67d5183fc..cfd35a3e9d7ceb922a8e7192212b93aeaa8fbf40 100644 (file)
@@ -1,5 +1,4 @@
 # Add new mime types for use in respond_to blocks:
 
 Mime::SET << Mime::CSV unless Mime::SET.include?(Mime::CSV)
-Mime::Type.register 'application/pdf', :pdf
-Mime::Type.register 'image/png', :png
+
index 708dcd65517375b9622582f06ea48f3f295d4829..4286081db8803b0e2de0555aacdd7182f2a76e43 100644 (file)
@@ -3,3 +3,5 @@ I18n.default_locale = 'en'
 I18n::Backend::Simple.send(:include, I18n::Backend::Fallbacks)
 
 require 'redmine'
+
+Redmine::Plugin.load
index de2a7c8ee4389eda5c8745c29824a3cd4bddac12..d2f1cc22ce3336ca7ad51219dbde92f22360a315 100644 (file)
-ActionController::Routing::Routes.draw do |map|
-  # Add your own custom routes here.
-  # The priority is based upon order of creation: first created -> highest priority.
-
-  # Here's a sample route:
-  # map.connect 'products/:id', :controller => 'catalog', :action => 'view'
-  # Keep in mind you can assign values other than :controller and :action
-
-  map.home '', :controller => 'welcome', :conditions => {:method => :get}
-
-  map.signin 'login', :controller => 'account', :action => 'login',
-             :conditions => {:method => [:get, :post]}
-  map.signout 'logout', :controller => 'account', :action => 'logout',
-              :conditions => {:method => :get}
-  map.connect 'account/register', :controller => 'account', :action => 'register',
-              :conditions => {:method => [:get, :post]}
-  map.connect 'account/lost_password', :controller => 'account', :action => 'lost_password',
-              :conditions => {:method => [:get, :post]}
-  map.connect 'account/activate', :controller => 'account', :action => 'activate',
-              :conditions => {:method => :get}
-
-  map.connect 'projects/:id/wiki', :controller => 'wikis',
-              :action => 'edit', :conditions => {:method => :post}
-  map.connect 'projects/:id/wiki/destroy', :controller => 'wikis',
-              :action => 'destroy', :conditions => {:method => [:get, :post]}
-
-  map.with_options :controller => 'messages' do |messages_routes|
-    messages_routes.with_options :conditions => {:method => :get} do |messages_views|
-      messages_views.connect 'boards/:board_id/topics/new', :action => 'new'
-      messages_views.connect 'boards/:board_id/topics/:id', :action => 'show'
-      messages_views.connect 'boards/:board_id/topics/:id/edit', :action => 'edit'
+# Redmine - project management software
+# Copyright (C) 2006-2012  Jean-Philippe Lang
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+RedmineApp::Application.routes.draw do
+  root :to => 'welcome#index', :as => 'home'
+
+  match 'login', :to => 'account#login', :as => 'signin'
+  match 'logout', :to => 'account#logout', :as => 'signout'
+  match 'account/register', :to => 'account#register', :via => [:get, :post]
+  match 'account/lost_password', :to => 'account#lost_password', :via => [:get, :post]
+  match 'account/activate', :to => 'account#activate', :via => :get
+  
+  match '/news/preview', :controller => 'previews', :action => 'news', :as => 'preview_news'
+  match '/issues/preview/new/:project_id', :to => 'previews#issue', :as => 'preview_new_issue'
+  match '/issues/preview/edit/:id', :to => 'previews#issue', :as => 'preview_edit_issue'
+  match '/issues/preview', :to => 'previews#issue', :as => 'preview_issue'
+  
+  match 'projects/:id/wiki', :to => 'wikis#edit', :via => :post
+  match 'projects/:id/wiki/destroy', :to => 'wikis#destroy', :via => [:get, :post]
+
+  match 'boards/:board_id/topics/new', :to => 'messages#new', :via => [:get, :post]
+  get 'boards/:board_id/topics/:id', :to => 'messages#show'
+  match 'boards/:board_id/topics/quote/:id', :to => 'messages#quote', :via => [:get, :post]
+  get 'boards/:board_id/topics/:id/edit', :to => 'messages#edit'
+  
+  post 'boards/:board_id/topics/preview', :to => 'messages#preview'
+  post 'boards/:board_id/topics/:id/replies', :to => 'messages#reply'
+  post 'boards/:board_id/topics/:id/edit', :to => 'messages#edit'
+  post 'boards/:board_id/topics/:id/destroy', :to => 'messages#destroy'
+
+  # Misc issue routes. TODO: move into resources
+  match '/issues/auto_complete', :to => 'auto_completes#issues', :via => :get, :as => 'auto_complete_issues'
+  match '/issues/context_menu', :to => 'context_menus#issues', :as => 'issues_context_menu'
+  match '/issues/changes', :to => 'journals#index', :as => 'issue_changes'
+  match '/issues/:id/quoted', :to => 'journals#new', :id => /\d+/, :via => :post, :as => 'quoted_issue'
+
+  match '/journals/diff/:id', :to => 'journals#diff', :id => /\d+/, :via => :get
+  match '/journals/edit/:id', :to => 'journals#edit', :id => /\d+/, :via => [:get, :post]
+
+  match '/projects/:project_id/issues/gantt', :to => 'gantts#show'
+  match '/issues/gantt', :to => 'gantts#show'
+
+  match '/projects/:project_id/issues/calendar', :to => 'calendars#show'
+  match '/issues/calendar', :to => 'calendars#show'
+
+  match 'projects/:id/issues/report', :to => 'reports#issue_report', :via => :get
+  match 'projects/:id/issues/report/:detail', :to => 'reports#issue_report_details', :via => :get
+
+  match 'my/account', :controller => 'my', :action => 'account', :via => [:get, :post]
+  match 'my/account/destroy', :controller => 'my', :action => 'destroy', :via => [:get, :post]
+  match 'my/page', :controller => 'my', :action => 'page', :via => :get
+  match 'my', :controller => 'my', :action => 'index', :via => :get # Redirects to my/page
+  match 'my/reset_rss_key', :controller => 'my', :action => 'reset_rss_key', :via => :post
+  match 'my/reset_api_key', :controller => 'my', :action => 'reset_api_key', :via => :post
+  match 'my/password', :controller => 'my', :action => 'password', :via => [:get, :post]
+  match 'my/page_layout', :controller => 'my', :action => 'page_layout', :via => :get
+  match 'my/add_block', :controller => 'my', :action => 'add_block', :via => :post
+  match 'my/remove_block', :controller => 'my', :action => 'remove_block', :via => :post
+  match 'my/order_blocks', :controller => 'my', :action => 'order_blocks', :via => :post
+
+  resources :users
+  match 'users/:id/memberships/:membership_id', :to => 'users#edit_membership', :via => :put, :as => 'user_membership'
+  match 'users/:id/memberships/:membership_id', :to => 'users#destroy_membership', :via => :delete
+  match 'users/:id/memberships', :to => 'users#edit_membership', :via => :post, :as => 'user_memberships'
+
+  match 'watchers/new', :controller=> 'watchers', :action => 'new', :via => :get
+  match 'watchers', :controller=> 'watchers', :action => 'create', :via => :post
+  match 'watchers/append', :controller=> 'watchers', :action => 'append', :via => :post
+  match 'watchers/destroy', :controller=> 'watchers', :action => 'destroy', :via => :post
+  match 'watchers/watch', :controller=> 'watchers', :action => 'watch', :via => :post
+  match 'watchers/unwatch', :controller=> 'watchers', :action => 'unwatch', :via => :post
+  match 'watchers/autocomplete_for_user', :controller=> 'watchers', :action => 'autocomplete_for_user', :via => :get
+
+  match 'projects/:id/settings/:tab', :to => "projects#settings"
+
+  resources :projects do
+    member do
+      get 'settings'
+      post 'modules'
+      post 'archive'
+      post 'unarchive'
+      match 'copy', :via => [:get, :post]
     end
-    messages_routes.with_options :conditions => {:method => :post} do |messages_actions|
-      messages_actions.connect 'boards/:board_id/topics/new', :action => 'new'
-      messages_actions.connect 'boards/:board_id/topics/preview', :action => 'preview'
-      messages_actions.connect 'boards/:board_id/topics/quote/:id', :action => 'quote'
-      messages_actions.connect 'boards/:board_id/topics/:id/replies', :action => 'reply'
-      messages_actions.connect 'boards/:board_id/topics/:id/edit', :action => 'edit'
-      messages_actions.connect 'boards/:board_id/topics/:id/destroy', :action => 'destroy'
+
+    resources :memberships, :shallow => true, :controller => 'members', :only => [:index, :show, :create, :update, :destroy] do
+      collection do
+        get 'autocomplete'
+      end
     end
-  end
 
-  # Misc issue routes. TODO: move into resources
-  map.auto_complete_issues '/issues/auto_complete', :controller => 'auto_completes',
-                           :action => 'issues', :conditions => { :method => :get }
-  # TODO: would look nicer as /issues/:id/preview
-  map.preview_new_issue '/issues/preview/new/:project_id', :controller => 'previews',
-                        :action => 'issue'
-  map.preview_edit_issue '/issues/preview/edit/:id', :controller => 'previews',
-                         :action => 'issue'
-  map.issues_context_menu '/issues/context_menu',
-                          :controller => 'context_menus', :action => 'issues'
-
-  map.issue_changes '/issues/changes', :controller => 'journals', :action => 'index'
-  map.quoted_issue '/issues/:id/quoted', :controller => 'journals', :action => 'new',
-                   :id => /\d+/, :conditions => { :method => :post }
-
-  map.connect '/journals/diff/:id', :controller => 'journals', :action => 'diff',
-              :id => /\d+/, :conditions => { :method => :get }
-  map.connect '/journals/edit/:id', :controller => 'journals', :action => 'edit',
-              :id => /\d+/, :conditions => { :method => [:get, :post] }
-
-  map.with_options :controller => 'gantts', :action => 'show' do |gantts_routes|
-    gantts_routes.connect '/projects/:project_id/issues/gantt'
-    gantts_routes.connect '/projects/:project_id/issues/gantt.:format'
-    gantts_routes.connect '/issues/gantt.:format'
-  end
+    resource :enumerations, :controller => 'project_enumerations', :only => [:update, :destroy]
 
-  map.with_options :controller => 'calendars', :action => 'show' do |calendars_routes|
-    calendars_routes.connect '/projects/:project_id/issues/calendar'
-    calendars_routes.connect '/issues/calendar'
-  end
+    match 'issues/:copy_from/copy', :to => 'issues#new'
+    resources :issues, :only => [:index, :new, :create] do
+      resources :time_entries, :controller => 'timelog' do
+        collection do
+          get 'report'
+        end
+      end
+    end
+    # issue form update
+    match 'issues/new', :controller => 'issues', :action => 'new', :via => [:put, :post], :as => 'issue_form'
 
-  map.with_options :controller => 'reports', :conditions => {:method => :get} do |reports|
-    reports.connect 'projects/:id/issues/report', :action => 'issue_report'
-    reports.connect 'projects/:id/issues/report/:detail', :action => 'issue_report_details'
-  end
+    resources :files, :only => [:index, :new, :create]
 
-  map.connect 'my/account', :controller => 'my', :action => 'account',
-              :conditions => {:method => [:get, :post]}
-  map.connect 'my/account/destroy', :controller => 'my', :action => 'destroy',
-              :conditions => {:method => [:get, :post]}
-  map.connect 'my/page', :controller => 'my', :action => 'page',
-              :conditions => {:method => :get}
-  # Redirects to my/page
-  map.connect 'my', :controller => 'my', :action => 'index',
-              :conditions => {:method => :get}
-  map.connect 'my/reset_rss_key', :controller => 'my', :action => 'reset_rss_key',
-              :conditions => {:method => :post}
-  map.connect 'my/reset_api_key', :controller => 'my', :action => 'reset_api_key',
-              :conditions => {:method => :post}
-  map.connect 'my/password', :controller => 'my', :action => 'password',
-              :conditions => {:method => [:get, :post]}
-  map.connect 'my/page_layout', :controller => 'my', :action => 'page_layout',
-              :conditions => {:method => :get}
-  map.connect 'my/add_block', :controller => 'my', :action => 'add_block',
-              :conditions => {:method => :post}
-  map.connect 'my/remove_block', :controller => 'my', :action => 'remove_block',
-              :conditions => {:method => :post}
-  map.connect 'my/order_blocks', :controller => 'my', :action => 'order_blocks',
-              :conditions => {:method => :post}
-
-  map.with_options :controller => 'users' do |users|
-    users.user_membership 'users/:id/memberships/:membership_id',
-                          :action => 'edit_membership',
-                          :conditions => {:method => :put}
-    users.connect 'users/:id/memberships/:membership_id',
-                  :action => 'destroy_membership',
-                  :conditions => {:method => :delete}
-    users.user_memberships 'users/:id/memberships',
-                           :action => 'edit_membership',
-                           :conditions => {:method => :post}
-  end
-  map.resources :users
-
-  # For nice "roadmap" in the url for the index action
-  map.connect 'projects/:project_id/roadmap', :controller => 'versions', :action => 'index'
-
-  map.preview_news '/news/preview', :controller => 'previews', :action => 'news'
-  map.connect 'news/:id/comments', :controller => 'comments',
-              :action => 'create', :conditions => {:method => :post}
-  map.connect 'news/:id/comments/:comment_id', :controller => 'comments',
-              :action => 'destroy', :conditions => {:method => :delete}
-
-  map.connect 'watchers/new', :controller=> 'watchers', :action => 'new',
-              :conditions => {:method => :get}
-  map.connect 'watchers', :controller=> 'watchers', :action => 'create',
-              :conditions => {:method => :post}
-  map.connect 'watchers/append', :controller=> 'watchers', :action => 'append',
-              :conditions => {:method => :post}
-  map.connect 'watchers/destroy', :controller=> 'watchers', :action => 'destroy',
-              :conditions => {:method => :post}
-  map.connect 'watchers/watch', :controller=> 'watchers', :action => 'watch',
-              :conditions => {:method => :post}
-  map.connect 'watchers/unwatch', :controller=> 'watchers', :action => 'unwatch',
-              :conditions => {:method => :post}
-  map.connect 'watchers/autocomplete_for_user', :controller=> 'watchers', :action => 'autocomplete_for_user',
-              :conditions => {:method => :get}
+    resources :versions, :except => [:index, :show, :edit, :update, :destroy] do
+      collection do
+        put 'close_completed'
+      end
+    end
+    match 'versions.:format', :to => 'versions#index'
+    match 'roadmap', :to => 'versions#index', :format => false
+    match 'versions', :to => 'versions#index'
 
-  # TODO: port to be part of the resources route(s)
-  map.with_options :conditions => {:method => :get} do |project_views|
-    project_views.connect 'projects/:id/settings/:tab',
-                          :controller => 'projects', :action => 'settings'
-    project_views.connect 'projects/:project_id/issues/:copy_from/copy',
-                          :controller => 'issues', :action => 'new'
-  end
+    resources :news, :except => [:show, :edit, :update, :destroy]
+    resources :time_entries, :controller => 'timelog' do
+      get 'report', :on => :collection
+    end
+    resources :queries, :only => [:new, :create]
+    resources :issue_categories, :shallow => true
+    resources :documents, :except => [:show, :edit, :update, :destroy]
+    resources :boards
+    resources :repositories, :shallow => true, :except => [:index, :show] do
+      member do
+        match 'committers', :via => [:get, :post]
+      end
+    end
 
-  map.resources :projects, :member => {
-    :copy => [:get, :post],
-    :settings => :get,
-    :modules => :post,
-    :archive => :post,
-    :unarchive => :post
-  } do |project|
-    project.resource :enumerations, :controller => 'project_enumerations',
-                     :only => [:update, :destroy]
-    # issue form update
-    project.issue_form 'issues/new', :controller => 'issues',
-                       :action => 'new', :conditions => {:method => [:post, :put]}
-    project.resources :issues, :only => [:index, :new, :create] do |issues|
-      issues.resources :time_entries, :controller => 'timelog',
-                       :collection => {:report => :get}
+    match 'wiki/index', :controller => 'wiki', :action => 'index', :via => :get
+    match 'wiki/:id/diff/:version/vs/:version_from', :controller => 'wiki', :action => 'diff'
+    match 'wiki/:id/diff/:version', :controller => 'wiki', :action => 'diff'
+    resources :wiki, :except => [:index, :new, :create] do
+      member do
+        get 'rename'
+        post 'rename'
+        get 'history'
+        get 'diff'
+        match 'preview', :via => [:post, :put]
+        post 'protect'
+        post 'add_attachment'
+      end
+      collection do
+        get 'export'
+        get 'date_index'
+      end
     end
+    match 'wiki', :controller => 'wiki', :action => 'show', :via => :get
+    match 'wiki/:id/annotate/:version', :controller => 'wiki', :action => 'annotate'
+  end
 
-    project.resources :files, :only => [:index, :new, :create]
-    project.resources :versions, :shallow => true,
-                      :collection => {:close_completed => :put},
-                      :member => {:status_by => :post}
-    project.resources :news, :shallow => true
-    project.resources :time_entries, :controller => 'timelog',
-                      :collection => {:report => :get}
-    project.resources :queries, :only => [:new, :create]
-    project.resources :issue_categories, :shallow => true
-    project.resources :documents, :shallow => true, :member => {:add_attachment => :post}
-    project.resources :boards
-    project.resources :repositories, :shallow => true, :except => [:index, :show],
-                      :member => {:committers => [:get, :post]}
-    project.resources :memberships, :shallow => true, :controller => 'members',
-                      :only => [:index, :show, :create, :update, :destroy],
-                      :collection => {:autocomplete => :get}
-
-    project.wiki_start_page 'wiki', :controller => 'wiki', :action => 'show', :conditions => {:method => :get}
-    project.wiki_index 'wiki/index', :controller => 'wiki', :action => 'index', :conditions => {:method => :get}
-    project.wiki_diff 'wiki/:id/diff/:version', :controller => 'wiki', :action => 'diff', :version => nil
-    project.wiki_diff 'wiki/:id/diff/:version/vs/:version_from', :controller => 'wiki', :action => 'diff'
-    project.wiki_annotate 'wiki/:id/annotate/:version', :controller => 'wiki', :action => 'annotate'
-    project.resources :wiki, :except => [:new, :create], :member => {
-      :rename => [:get, :post],
-      :history => :get,
-      :preview => :any,
-      :protect => :post,
-      :add_attachment => :post
-    }, :collection => {
-      :export => :get,
-      :date_index => :get
-    }
+  resources :issues do
+    collection do
+      match 'bulk_edit', :via => [:get, :post]
+      post 'bulk_update'
+    end
+    resources :time_entries, :controller => 'timelog' do
+      collection do
+        get 'report'
+      end
+    end
+    resources :relations, :shallow => true, :controller => 'issue_relations', :only => [:index, :show, :create, :destroy]
   end
+  match '/issues', :controller => 'issues', :action => 'destroy', :via => :delete
+
+  resources :queries, :except => [:show]
 
-  map.connect 'news', :controller => 'news', :action => 'index'
-  map.connect 'news.:format', :controller => 'news', :action => 'index'
-
-  map.resources :queries, :except => [:show]
-  map.resources :issues,
-                :collection => {:bulk_edit => [:get, :post], :bulk_update => :post} do |issues|
-    issues.resources :time_entries, :controller => 'timelog',
-                     :collection => {:report => :get}
-    issues.resources :relations, :shallow => true,
-                     :controller => 'issue_relations',
-                     :only => [:index, :show, :create, :destroy]
+  resources :news, :only => [:index, :show, :edit, :update, :destroy]
+  match '/news/:id/comments', :to => 'comments#create', :via => :post
+  match '/news/:id/comments/:comment_id', :to => 'comments#destroy', :via => :delete
+  
+  resources :versions, :only => [:show, :edit, :update, :destroy] do
+    post 'status_by', :on => :member
   end
-  # Bulk deletion
-  map.connect '/issues', :controller => 'issues', :action => 'destroy',
-              :conditions => {:method => :delete}
-
-  map.connect '/time_entries/destroy',
-              :controller => 'timelog', :action => 'destroy',
-              :conditions => { :method => :delete }
-  map.time_entries_context_menu '/time_entries/context_menu',
-                   :controller => 'context_menus', :action => 'time_entries'
-
-  map.resources :time_entries, :controller => 'timelog',
-                :collection => {:report => :get, :bulk_edit => :get, :bulk_update => :post}
-
-  map.with_options :controller => 'activities', :action => 'index',
-                   :conditions => {:method => :get} do |activity|
-    activity.connect 'projects/:id/activity'
-    activity.connect 'projects/:id/activity.:format'
-    activity.connect 'activity', :id => nil
-    activity.connect 'activity.:format', :id => nil
+
+  resources :documents, :only => [:show, :edit, :update, :destroy] do
+    post 'add_attachment', :on => :member
   end
 
-  map.with_options :controller => 'repositories' do |repositories|
-    repositories.with_options :conditions => {:method => :get} do |repository_views|
-      repository_views.connect 'projects/:id/repository',
-                               :action => 'show'
-
-      repository_views.connect 'projects/:id/repository/:repository_id/statistics',
-                               :action => 'stats'
-      repository_views.connect 'projects/:id/repository/:repository_id/graph',
-                               :action => 'graph'
-
-      repository_views.connect 'projects/:id/repository/statistics',
-                               :action => 'stats'
-      repository_views.connect 'projects/:id/repository/graph',
-                               :action => 'graph'
-
-      repository_views.connect 'projects/:id/repository/:repository_id/revisions',
-                               :action => 'revisions'
-      repository_views.connect 'projects/:id/repository/:repository_id/revisions.:format',
-                               :action => 'revisions'
-      repository_views.connect 'projects/:id/repository/:repository_id/revisions/:rev',
-                               :action => 'revision'
-      repository_views.connect 'projects/:id/repository/:repository_id/revisions/:rev/issues',
-                                :action => 'add_related_issue', :conditions => {:method => :post}
-      repository_views.connect 'projects/:id/repository/:repository_id/revisions/:rev/issues/:issue_id',
-                                :action => 'remove_related_issue', :conditions => {:method => :delete}
-      repository_views.connect 'projects/:id/repository/:repository_id/revisions/:rev/diff',
-                               :action => 'diff'
-      repository_views.connect 'projects/:id/repository/:repository_id/revisions/:rev/diff.:format',
-                               :action => 'diff'
-      repository_views.connect 'projects/:id/repository/:repository_id/revisions/:rev/raw/*path',
-                               :action => 'entry', :format => 'raw'
-      repository_views.connect 'projects/:id/repository/:repository_id/revisions/:rev/:action/*path',
-                               :requirements => { 
-                                   :action => /(browse|show|entry|changes|annotate|diff)/,
-                                   :rev    => /[a-z0-9\.\-_]+/
-                                 }
-      repository_views.connect 'projects/:id/repository/:repository_id/raw/*path',
-                               :action => 'entry', :format => 'raw'
-      repository_views.connect 'projects/:id/repository/:repository_id/:action/*path',
-                               :requirements => { :action => /(browse|entry|changes|annotate|diff)/ }
-      repository_views.connect 'projects/:id/repository/:repository_id/show/*path',
-                               :requirements => { :path => /.+/ }
-
-      repository_views.connect 'projects/:id/repository/:repository_id/revision',
-                               :action => 'revision'
-
-      repository_views.connect 'projects/:id/repository/revisions',
-                               :action => 'revisions'
-      repository_views.connect 'projects/:id/repository/revisions.:format',
-                               :action => 'revisions'
-      repository_views.connect 'projects/:id/repository/revisions/:rev',
-                               :action => 'revision'
-      repository_views.connect 'projects/:id/repository/revisions/:rev/issues',
-                                :action => 'add_related_issue', :conditions => {:method => :post}
-      repository_views.connect 'projects/:id/repository/revisions/:rev/issues/:issue_id',
-                                :action => 'remove_related_issue', :conditions => {:method => :delete}
-      repository_views.connect 'projects/:id/repository/revisions/:rev/diff',
-                               :action => 'diff'
-      repository_views.connect 'projects/:id/repository/revisions/:rev/diff.:format',
-                               :action => 'diff'
-      repository_views.connect 'projects/:id/repository/revisions/:rev/raw/*path',
-                               :action => 'entry', :format => 'raw'
-      repository_views.connect 'projects/:id/repository/revisions/:rev/:action/*path',
-                               :requirements => { 
-                                   :action => /(browse|show|entry|changes|annotate|diff)/,
-                                   :rev    => /[a-z0-9\.\-_]+/
-                                 }
-      repository_views.connect 'projects/:id/repository/raw/*path',
-                               :action => 'entry', :format => 'raw'
-      repository_views.connect 'projects/:id/repository/:action/*path',
-                               :requirements => { :action => /(browse|show|entry|changes|annotate|diff)/ }
-
-      repository_views.connect 'projects/:id/repository/revision',
-                               :action => 'revision'
-
-      repository_views.connect 'projects/:id/repository/:repository_id',
-                               :action => 'show'
+  match '/time_entries/context_menu', :to => 'context_menus#time_entries', :as => :time_entries_context_menu
+
+  resources :time_entries, :controller => 'timelog', :except => :destroy do
+    collection do
+      get 'report'
+      get 'bulk_edit'
+      post 'bulk_update'
     end
   end
+  match '/time_entries/:id', :to => 'timelog#destroy', :via => :delete, :id => /\d+/
+  # TODO: delete /time_entries for bulk deletion
+  match '/time_entries/destroy', :to => 'timelog#destroy', :via => :delete
+  
+  # TODO: port to be part of the resources route(s)
+  match 'projects/:id/settings/:tab', :to => 'projects#settings', :via => :get
+
+  get 'projects/:id/activity', :to => 'activities#index'
+  get 'projects/:id/activity.:format', :to => 'activities#index'
+  get 'activity', :to => 'activities#index'
+
+  # repositories routes
+  get 'projects/:id/repository/:repository_id/statistics', :to => 'repositories#stats'
+  get 'projects/:id/repository/:repository_id/graph', :to => 'repositories#graph'
+  match 'projects/:id/repository/:repository_id/committers', :to => 'repositories#committers', :via => [:get, :post]
+
+  get 'projects/:id/repository/:repository_id/revisions/:rev', :to => 'repositories#revision'
+  get 'projects/:id/repository/:repository_id/revision', :to => 'repositories#revision'
+  post   'projects/:id/repository/:repository_id/revisions/:rev/issues', :to => 'repositories#add_related_issue'
+  delete 'projects/:id/repository/:repository_id/revisions/:rev/issues/:issue_id', :to => 'repositories#remove_related_issue'
+  get 'projects/:id/repository/:repository_id/revisions', :to => 'repositories#revisions'
+  get 'projects/:id/repository/:repository_id/revisions/:rev/:format(/*path(.:ext))', :to => 'repositories#entry', :format => /raw/
+  get 'projects/:id/repository/:repository_id/revisions/:rev/:action(/*path(.:ext))', :controller => 'repositories', :action => /(browse|show|entry|changes|annotate|diff)/
+
+  get 'projects/:id/repository/statistics', :to => 'repositories#stats'
+  get 'projects/:id/repository/graph', :to => 'repositories#graph'
+  match 'projects/:id/repository/committers', :to => 'repositories#committers', :via => [:get, :post]
+
+  get 'projects/:id/repository/revisions', :to => 'repositories#revisions'
+  get 'projects/:id/repository/revisions/:rev', :to => 'repositories#revision'
+  get 'projects/:id/repository/revision', :to => 'repositories#revision'
+  post   'projects/:id/repository/revisions/:rev/issues', :to => 'repositories#add_related_issue'
+  delete 'projects/:id/repository/revisions/:rev/issues/:issue_id', :to => 'repositories#remove_related_issue'
+  get 'projects/:id/repository/revisions/:rev/:format(/*path(.:ext))', :to => 'repositories#entry', :format => /raw/
+  get 'projects/:id/repository/revisions/:rev/:action(/*path(.:ext))', :controller => 'repositories', :action => /(browse|show|entry|changes|annotate|diff)/
+  get 'projects/:id/repository/:repository_id/:format(/*path(.:ext))', :to => 'repositories#entry', :format => /raw/
+  get 'projects/:id/repository/:repository_id/:action(/*path(.:ext))', :controller => 'repositories', :action => /(browse|show|entry|changes|annotate|diff)/
+  get 'projects/:id/repository/:repository_id', :to => 'repositories#show', :path => nil
+
+  get 'projects/:id/repository/:format(/*path(.:ext))', :to => 'repositories#entry', :format => /raw/
+  get 'projects/:id/repository/:action(/*path(.:ext))', :controller => 'repositories', :action => /(browse|show|entry|changes|annotate|diff)/
+  get 'projects/:id/repository', :to => 'repositories#show', :path => nil
 
   # additional routes for having the file name at the end of url
-  map.connect 'attachments/:id/:filename', :controller => 'attachments',
-              :action => 'show', :id => /\d+/, :filename => /.*/,
-              :conditions => {:method => :get}
-  map.connect 'attachments/download/:id/:filename', :controller => 'attachments',
-              :action => 'download', :id => /\d+/, :filename => /.*/,
-              :conditions => {:method => :get}
-  map.connect 'attachments/download/:id', :controller => 'attachments',
-              :action => 'download', :id => /\d+/,
-              :conditions => {:method => :get}
-  map.resources :attachments, :only => [:show, :destroy]
-
-  map.resources :groups, :member => {:autocomplete_for_user => :get}
-  map.group_users 'groups/:id/users', :controller => 'groups',
-                  :action => 'add_users', :id => /\d+/,
-                  :conditions => {:method => :post}
-  map.group_user  'groups/:id/users/:user_id', :controller => 'groups',
-                  :action => 'remove_user', :id => /\d+/,
-                  :conditions => {:method => :delete}
-  map.connect 'groups/destroy_membership/:id', :controller => 'groups',
-              :action => 'destroy_membership', :id => /\d+/,
-              :conditions => {:method => :post}
-  map.connect 'groups/edit_membership/:id', :controller => 'groups',
-              :action => 'edit_membership', :id => /\d+/,
-              :conditions => {:method => :post}
-
-  map.resources :trackers, :except => :show
-  map.resources :issue_statuses, :except => :show, :collection => {:update_issue_done_ratio => :post}
-  map.resources :custom_fields, :except => :show
-  map.resources :roles, :except => :show, :collection => {:permissions => [:get, :post]}
-  map.resources :enumerations, :except => :show
-
-  map.connect 'projects/:id/search', :controller => 'search', :action => 'index', :conditions => {:method => :get}
-  map.connect 'search', :controller => 'search', :action => 'index', :conditions => {:method => :get}
-
-  map.connect 'mail_handler', :controller => 'mail_handler',
-              :action => 'index', :conditions => {:method => :post}
-
-  map.connect 'admin', :controller => 'admin', :action => 'index',
-              :conditions => {:method => :get}
-  map.connect 'admin/projects', :controller => 'admin', :action => 'projects',
-              :conditions => {:method => :get}
-  map.connect 'admin/plugins', :controller => 'admin', :action => 'plugins',
-              :conditions => {:method => :get}
-  map.connect 'admin/info', :controller => 'admin', :action => 'info',
-              :conditions => {:method => :get}
-  map.connect 'admin/test_email', :controller => 'admin', :action => 'test_email',
-              :conditions => {:method => :get}
-  map.connect 'admin/default_configuration', :controller => 'admin',
-              :action => 'default_configuration', :conditions => {:method => :post}
-
-  map.resources :auth_sources, :member => {:test_connection => :get}
-
-  map.connect 'workflows', :controller => 'workflows',
-              :action => 'index', :conditions => {:method => :get}
-  map.connect 'workflows/edit', :controller => 'workflows',
-              :action => 'edit', :conditions => {:method => [:get, :post]}
-  map.connect 'workflows/copy', :controller => 'workflows',
-              :action => 'copy', :conditions => {:method => [:get, :post]}
-
-  map.connect 'settings', :controller => 'settings',
-              :action => 'index', :conditions => {:method => :get}
-  map.connect 'settings/edit', :controller => 'settings',
-              :action => 'edit', :conditions => {:method => [:get, :post]}
-  map.connect 'settings/plugin/:id', :controller => 'settings',
-              :action => 'plugin', :conditions => {:method => [:get, :post]}
-
-  map.with_options :controller => 'sys' do |sys|
-    sys.connect 'sys/projects.:format',
-                :action => 'projects',
-                :conditions => {:method => :get}
-    sys.connect 'sys/projects/:id/repository.:format',
-                :action => 'create_project_repository',
-                :conditions => {:method => :post}
-    sys.connect 'sys/fetch_changesets',
-                :action => 'fetch_changesets',
-                :conditions => {:method => :get}
+  match 'attachments/:id/:filename', :controller => 'attachments', :action => 'show', :id => /\d+/, :filename => /.*/, :via => :get
+  match 'attachments/download/:id/:filename', :controller => 'attachments', :action => 'download', :id => /\d+/, :filename => /.*/, :via => :get
+  match 'attachments/download/:id', :controller => 'attachments', :action => 'download', :id => /\d+/, :via => :get
+  resources :attachments, :only => [:show, :destroy]
+
+  resources :groups do
+    member do
+      get 'autocomplete_for_user'
+    end
+  end
+
+  match 'groups/:id/users', :controller => 'groups', :action => 'add_users', :id => /\d+/, :via => :post, :as => 'group_users'
+  match 'groups/:id/users/:user_id', :controller => 'groups', :action => 'remove_user', :id => /\d+/, :via => :delete, :as => 'group_user'
+  match 'groups/destroy_membership/:id', :controller => 'groups', :action => 'destroy_membership', :id => /\d+/, :via => :post
+  match 'groups/edit_membership/:id', :controller => 'groups', :action => 'edit_membership', :id => /\d+/, :via => :post
+
+  resources :trackers, :except => :show
+  resources :issue_statuses, :except => :show do
+    collection do
+      post 'update_issue_done_ratio'
+    end
+  end
+  resources :custom_fields, :except => :show
+  resources :roles, :except => :show do
+    collection do
+      match 'permissions', :via => [:get, :post]
+    end
   end
+  resources :enumerations, :except => :show
 
-  map.connect 'uploads.:format', :controller => 'attachments', :action => 'upload', :conditions => {:method => :post}
+  get 'projects/:id/search', :controller => 'search', :action => 'index'
+  get 'search', :controller => 'search', :action => 'index'
 
-  map.connect 'robots.txt', :controller => 'welcome',
-              :action => 'robots', :conditions => {:method => :get}
+  match 'mail_handler', :controller => 'mail_handler', :action => 'index', :via => :post
 
-  # Used for OpenID
-  map.root :controller => 'account', :action => 'login'
+  match 'admin', :controller => 'admin', :action => 'index', :via => :get
+  match 'admin/projects', :controller => 'admin', :action => 'projects', :via => :get
+  match 'admin/plugins', :controller => 'admin', :action => 'plugins', :via => :get
+  match 'admin/info', :controller => 'admin', :action => 'info', :via => :get
+  match 'admin/test_email', :controller => 'admin', :action => 'test_email', :via => :get
+  match 'admin/default_configuration', :controller => 'admin', :action => 'default_configuration', :via => :post
+
+  resources :auth_sources do
+    member do
+      get 'test_connection'
+    end
+  end
+
+  match 'workflows', :controller => 'workflows', :action => 'index', :via => :get
+  match 'workflows/edit', :controller => 'workflows', :action => 'edit', :via => [:get, :post]
+  match 'workflows/copy', :controller => 'workflows', :action => 'copy', :via => [:get, :post]
+  match 'settings', :controller => 'settings', :action => 'index', :via => :get
+  match 'settings/edit', :controller => 'settings', :action => 'edit', :via => [:get, :post]
+  match 'settings/plugin/:id', :controller => 'settings', :action => 'plugin', :via => [:get, :post]
+
+  match 'sys/projects', :to => 'sys#projects', :via => :get
+  match 'sys/projects/:id/repository', :to => 'sys#create_project_repository', :via => :post
+  match 'sys/fetch_changesets', :to => 'sys#fetch_changesets', :via => :get
+
+  match 'uploads', :to => 'attachments#upload', :via => :post
+
+  get 'robots.txt', :to => 'welcome#robots'
+
+  Dir.glob File.expand_path("plugins/*", Rails.root) do |plugin_dir|
+    file = File.join(plugin_dir, "config/routes.rb")
+    if File.exists?(file)
+      begin
+        instance_eval File.read(file)
+      rescue Exception => e
+        puts "An error occurred while loading the routes definition of #{File.basename(plugin_dir)} plugin (#{file}): #{e.message}."
+        exit 1
+      end
+    end
+  end
 end
diff --git a/db/migrate/20120422150750_change_repositories_to_full_sti.rb b/db/migrate/20120422150750_change_repositories_to_full_sti.rb
new file mode 100644 (file)
index 0000000..067d602
--- /dev/null
@@ -0,0 +1,17 @@
+class ChangeRepositoriesToFullSti < ActiveRecord::Migration
+  def up
+    Repository.connection.select_rows("SELECT id, type FROM #{Repository.table_name}").each do |repository_id, repository_type|
+      unless repository_type =~ /^Repository::/
+        Repository.update_all ["type = ?", "Repository::#{repository_type}"], ["id = ?", repository_id]
+      end
+    end
+  end
+
+  def down
+    Repository.connection.select_rows("SELECT id, type FROM #{Repository.table_name}").each do |repository_id, repository_type|
+      if repository_type =~ /^Repository::(.+)$/
+        Repository.update_all ["type = ?", $1], ["id = ?", repository_id]
+      end
+    end
+  end
+end
index d576ecfbfcab7578fe247d3283615aa84cfbbae9..5fe8a2a315c7c8499448f5fceadc520c1096b75d 100644 (file)
@@ -4,10 +4,11 @@ This is a sample plugin for Redmine
 
 == Installation
 
-1. Copy the plugin directory into the vendor/plugins directory
+1. Copy the plugin directory into the "plugins" directory at the root
+   of your Redmine directory
 
-2. Migrate plugin:
-   rake db:migrate_plugins
+2. Migrate and copy plugin assets:
+   rake redmine:plugins
 
 3. Start Redmine
 
index 3f4d63dae021aa390756b8155a9e78d04949f383..978fbd9b29f860278a11b04391d44a1abc757662 100644 (file)
@@ -1,5 +1,7 @@
+<h2>Good Bye</h2>
+
 <p class="icon icon-example-works"><%= l(:text_say_goodbye) %></p>
 
 <% content_for :header_tags do %>
-  <%= stylesheet_link_tag "example.css", :plugin => "sample_plugin", :media => "screen" %>
+  <%= stylesheet_link_tag "/plugin_assets/sample_plugin/stylesheets/example.css", :media => "screen" %>
 <% end %>
index 17aca7bc4b5146b811f71248bf7b7944c0fb9fa3..9bfa8cc4fa8e757fc6bfb28c21fcf10b78df83a8 100644 (file)
@@ -1,9 +1,15 @@
+<h2>Hello</h2>
+
 <p class="icon icon-example-works"><%= l(:text_say_hello) %></p>
 
 <p><label>Example setting</label>: <%= @value %></p>
 
-<%= link_to_if_authorized 'Good bye', :action => 'say_goodbye', :id => @project %>
+<%= link_to('Good bye', :action => 'say_goodbye', :id => @project) if User.current.allowed_to?(:example_say_goodbye, @project) %>
+
+<% content_for :sidebar do %>
+  <p>Adding content to the sidebar...</p>
+<% end %>
 
 <% content_for :header_tags do %>
-  <%= stylesheet_link_tag "example.css", :plugin => "sample_plugin", :media => "screen" %>
+  <%= stylesheet_link_tag "/plugin_assets/sample_plugin/stylesheets/example.css", :media => "screen" %>
 <% end %>
diff --git a/extra/sample_plugin/config/routes.rb b/extra/sample_plugin/config/routes.rb
new file mode 100644 (file)
index 0000000..53428a7
--- /dev/null
@@ -0,0 +1,7 @@
+# Plugin's routes
+# See: http://guides.rubyonrails.org/routing.html
+
+match 'projects/:id/hello', :to => 'example#say_hello', :via => 'get'
+match 'projects/:id/bye', :to => 'example#say_goodbye', :via => 'get'
+
+resources 'meetings'
index 5a5e266943f82794485f06267c9ab3b2e4ff4b4d..be7eeceb6619f58e8db36f6583a11064234e473f 100644 (file)
@@ -1,7 +1,4 @@
-# Redmine sample plugin
-require 'redmine'
-
-RAILS_DEFAULT_LOGGER.info 'Starting Example plugin for RedMine'
+Rails.logger.info 'Starting Example plugin for RedMine'
 
 Redmine::Plugin.register :sample_plugin do
   name 'Example plugin'
index 1ed0dd59181d126f183111aaee6622cff3e4181f..01486f0d8415a39e9f53c4d434dc87467c55e561 100644 (file)
@@ -3,19 +3,8 @@ Description:
        
 Example:
     ./script/generate redmine_plugin meetings
-      create  vendor/plugins/redmine_meetings/app/controllers
-      create  vendor/plugins/redmine_meetings/app/helpers
-      create  vendor/plugins/redmine_meetings/app/models
-      create  vendor/plugins/redmine_meetings/app/views
-      create  vendor/plugins/redmine_meetings/db/migrate
-      create  vendor/plugins/redmine_meetings/lib/tasks
-      create  vendor/plugins/redmine_meetings/assets/images
-      create  vendor/plugins/redmine_meetings/assets/javascripts
-      create  vendor/plugins/redmine_meetings/assets/stylesheets
-      create  vendor/plugins/redmine_meetings/lang
-      create  vendor/plugins/redmine_meetings/config/locales
-      create  vendor/plugins/redmine_meetings/test
-      create  vendor/plugins/redmine_meetings/README.rdoc
-      create  vendor/plugins/redmine_meetings/init.rb
-      create  vendor/plugins/redmine_meetings/config/locales/en.yml
-      create  vendor/plugins/redmine_meetings/test/test_helper.rb
+      create  plugins/meetings/README.rdoc
+      create  plugins/meetings/init.rb
+      create  plugins/meetings/config/routes.rb
+      create  plugins/meetings/config/locales/en.yml
+      create  plugins/meetings/test/test_helper.rb
index 0946d3ba0f17488fde952a8815120f762d5569c9..8e1e4f8220ff4044ea430125f2971e406ef4f99b 100644 (file)
@@ -1,32 +1,33 @@
-class RedminePluginGenerator < Rails::Generator::NamedBase
+class RedminePluginGenerator < Rails::Generators::NamedBase
+  source_root File.expand_path("../templates", __FILE__)
+
   attr_reader :plugin_path, :plugin_name, :plugin_pretty_name
 
-  def initialize(runtime_args, runtime_options = {})
+  def initialize(*args)
     super
-    @plugin_name = "redmine_#{file_name.underscore}"
+    @plugin_name = file_name.underscore
     @plugin_pretty_name = plugin_name.titleize
-    @plugin_path = "vendor/plugins/#{plugin_name}"
+    @plugin_path = "plugins/#{plugin_name}"
   end
 
-  def manifest
-    record do |m|
-      m.directory "#{plugin_path}/app/controllers"
-      m.directory "#{plugin_path}/app/helpers"
-      m.directory "#{plugin_path}/app/models"
-      m.directory "#{plugin_path}/app/views"
-      m.directory "#{plugin_path}/db/migrate"
-      m.directory "#{plugin_path}/lib/tasks"
-      m.directory "#{plugin_path}/assets/images"
-      m.directory "#{plugin_path}/assets/javascripts"
-      m.directory "#{plugin_path}/assets/stylesheets"
-      m.directory "#{plugin_path}/lang"
-      m.directory "#{plugin_path}/config/locales"
-      m.directory "#{plugin_path}/test"
+  def copy_templates
+    empty_directory "#{plugin_path}/app"
+    empty_directory "#{plugin_path}/app/controllers"
+    empty_directory "#{plugin_path}/app/helpers"
+    empty_directory "#{plugin_path}/app/models"
+    empty_directory "#{plugin_path}/app/views"
+    empty_directory "#{plugin_path}/db/migrate"
+    empty_directory "#{plugin_path}/lib/tasks"
+    empty_directory "#{plugin_path}/assets/images"
+    empty_directory "#{plugin_path}/assets/javascripts"
+    empty_directory "#{plugin_path}/assets/stylesheets"
+    empty_directory "#{plugin_path}/config/locales"
+    empty_directory "#{plugin_path}/test"
 
-      m.template 'README.rdoc',    "#{plugin_path}/README.rdoc"
-      m.template 'init.rb.erb',   "#{plugin_path}/init.rb"
-      m.template 'en_rails_i18n.yml',    "#{plugin_path}/config/locales/en.yml"
-      m.template 'test_helper.rb.erb',    "#{plugin_path}/test/test_helper.rb"
-    end
+    template 'README.rdoc',    "#{plugin_path}/README.rdoc"
+    template 'init.rb.erb',   "#{plugin_path}/init.rb"
+    template 'routes.rb',    "#{plugin_path}/config/routes.rb"
+    template 'en_rails_i18n.yml',    "#{plugin_path}/config/locales/en.yml"
+    template 'test_helper.rb.erb',    "#{plugin_path}/test/test_helper.rb"
   end
 end
index e6feded223f7b1b1c2942a6b97f1950faf718567..763ba7d2262fbd420c28136a0c6d9d690be3bbf6 100644 (file)
@@ -1,5 +1,3 @@
-require 'redmine'
-
 Redmine::Plugin.register :<%= plugin_name %> do
   name '<%= plugin_pretty_name %> plugin'
   author 'Author name'
diff --git a/lib/generators/redmine_plugin/templates/routes.rb b/lib/generators/redmine_plugin/templates/routes.rb
new file mode 100644 (file)
index 0000000..1803173
--- /dev/null
@@ -0,0 +1,2 @@
+# Plugin's routes
+# See: http://guides.rubyonrails.org/routing.html
index 8336e711753af40e5d3a1c2f54bbbf17b242f5e2..dc2a4b26bcce913767969772696266d0eab8971a 100644 (file)
@@ -2,4 +2,4 @@ Description:
     Generates a plugin controller.
 
 Example:
-    ./script/generate redmine_plugin_controller MyPlugin Pools index show vote
+    ./script/generate redmine_plugin_controller meetings pools index show vote
index 71d7d106c9259a5fb7bd31ff035d5a1ae08793f4..8351ce681e12210f60eb6defa14251a5838bb690 100644 (file)
@@ -1,55 +1,27 @@
-require 'rails_generator/base'
-require 'rails_generator/generators/components/controller/controller_generator'
+class RedminePluginControllerGenerator < Rails::Generators::NamedBase
+  source_root File.expand_path("../templates", __FILE__)
+  argument :controller, :type => :string
+  argument :actions, :type => :array, :default => [], :banner => "ACTION ACTION ..."
 
-class RedminePluginControllerGenerator < ControllerGenerator
   attr_reader :plugin_path, :plugin_name, :plugin_pretty_name
 
-  def initialize(runtime_args, runtime_options = {})
-    runtime_args = runtime_args.dup
-    usage if runtime_args.empty?
-    @plugin_name = "redmine_" + runtime_args.shift.underscore
+  def initialize(*args)
+    super
+    @plugin_name = file_name.underscore
     @plugin_pretty_name = plugin_name.titleize
-    @plugin_path = "vendor/plugins/#{plugin_name}"
-    super(runtime_args, runtime_options)
+    @plugin_path = "plugins/#{plugin_name}"
+    @controller_class = controller.camelize
   end
 
-  def destination_root
-    File.join(Rails.root, plugin_path)
-  end
-
-  def manifest
-    record do |m|
-      # Check for class naming collisions.
-      m.class_collisions class_path, "#{class_name}Controller", "#{class_name}ControllerTest", "#{class_name}Helper"
-
-      # Controller, helper, views, and test directories.
-      m.directory File.join('app/controllers', class_path)
-      m.directory File.join('app/helpers', class_path)
-      m.directory File.join('app/views', class_path, file_name)
-      m.directory File.join('test/functional', class_path)
-
-      # Controller class, functional test, and helper class.
-      m.template 'controller.rb.erb',
-                  File.join('app/controllers',
-                            class_path,
-                            "#{file_name}_controller.rb")
-
-      m.template 'functional_test.rb.erb',
-                  File.join('test/functional',
-                            class_path,
-                            "#{file_name}_controller_test.rb")
-
-      m.template 'helper.rb.erb',
-                  File.join('app/helpers',
-                            class_path,
-                            "#{file_name}_helper.rb")
-
-      # View template for each action.
-      actions.each do |action|
-        path = File.join('app/views', class_path, file_name, "#{action}.html.erb")
-        m.template 'view.html.erb', path,
-          :assigns => { :action => action, :path => path }
-      end
+  def copy_templates
+    template 'controller.rb.erb', "#{plugin_path}/app/controllers/#{controller}_controller.rb"
+    template 'helper.rb.erb', "#{plugin_path}/app/helpers/#{controller}_helper.rb"
+    template 'functional_test.rb.erb', "#{plugin_path}/test/functional/#{controller}_controller_test.rb"
+    # View template for each action.
+    actions.each do |action|
+      path = "#{plugin_path}/app/views/#{controller}/#{action}.html.erb"
+      @action_name = action
+      template 'view.html.erb', path
     end
   end
 end
index 2f4c70bd97ed6a34d6fcac6ee5b98274b0920528..dddbf7017d2ffaa60d24cd709b2490e01709aef5 100644 (file)
@@ -1,4 +1,4 @@
-class <%= class_name %>Controller < ApplicationController
+class <%= @controller_class %>Controller < ApplicationController
   unloadable
 
 <% actions.each do |action| -%>
index 876bd79e2386d9f71043669f73d49881bb9def70..df332fd21310b21f2b920281ee95505d1b603227 100644 (file)
@@ -1,6 +1,6 @@
 require File.dirname(__FILE__) + '/../test_helper'
 
-class <%= class_name %>ControllerTest < ActionController::TestCase
+class <%= @controller_class %>ControllerTest < ActionController::TestCase
   # Replace this with your real tests.
   def test_truth
     assert true
index 3fe2ecdc74c647aa21c3f3301740e253b5e379fc..059e12f3b7a1ff71aa291c321ede3a2af078da96 100644 (file)
@@ -1,2 +1,2 @@
-module <%= class_name %>Helper
+module <%= @controller_class %>Helper
 end
index c24afaa6eaa70639db40e82ea2bc15e5682c4318..1fdb03dc756a3804246ddd208c00958c33cf1a9d 100644 (file)
@@ -1 +1 @@
-<h2><%= class_name %>#<%= action %></h2>
+<h2><%= @controller_class %>Controller#<%= @action_name %></h2>
index 0cb55a186ed6f49278a16f227314e4a6436ad7b4..f070d54939e34ba99a0123e758cd882bb93cd59a 100644 (file)
@@ -2,4 +2,4 @@ Description:
     Generates a plugin model.
 
 Examples:
-    ./script/generate redmine_plugin_model MyPlugin pool title:string question:text
+    ./script/generate redmine_plugin_model meetings pool
index 07aff1fb79635788fe2f10713af7cdf15dc79db4..01ce31b1d1da1f07d8c74cc5c9b934f40cc2d935 100644 (file)
@@ -1,45 +1,19 @@
-require 'rails_generator/base'
-require 'rails_generator/generators/components/model/model_generator'
+class RedminePluginModelGenerator < Rails::Generators::NamedBase
+  source_root File.expand_path("../templates", __FILE__)
+  argument :model, :type => :string
 
-class RedminePluginModelGenerator < ModelGenerator
-  attr_accessor :plugin_path, :plugin_name, :plugin_pretty_name
+  attr_reader :plugin_path, :plugin_name, :plugin_pretty_name
 
-  def initialize(runtime_args, runtime_options = {})
-    runtime_args = runtime_args.dup
-    usage if runtime_args.empty?
-    @plugin_name = "redmine_" + runtime_args.shift.underscore
+  def initialize(*args)
+    super
+    @plugin_name = file_name.underscore
     @plugin_pretty_name = plugin_name.titleize
-    @plugin_path = "vendor/plugins/#{plugin_name}"
-    super(runtime_args, runtime_options)
+    @plugin_path = "plugins/#{plugin_name}"
+    @model_class = model.camelize
   end
 
-  def destination_root
-    File.join(Rails.root, plugin_path)
-  end
-
-  def manifest
-    record do |m|
-      # Check for class naming collisions.
-      m.class_collisions class_path, class_name, "#{class_name}Test"
-
-      # Model, test, and fixture directories.
-      m.directory File.join('app/models', class_path)
-      m.directory File.join('test/unit', class_path)
-      m.directory File.join('test/fixtures', class_path)
-
-      # Model class, unit test, and fixtures.
-      m.template 'model.rb.erb',      File.join('app/models', class_path, "#{file_name}.rb")
-      m.template 'unit_test.rb.erb',  File.join('test/unit', class_path, "#{file_name}_test.rb")
-
-      unless options[:skip_fixture]
-               m.template 'fixtures.yml',  File.join('test/fixtures', "#{table_name}.yml")
-      end
-
-      unless options[:skip_migration]
-        m.migration_template 'migration.rb.erb', 'db/migrate', :assigns => {
-          :migration_name => "Create#{class_name.pluralize.gsub(/::/, '')}"
-        }, :migration_file_name => "create_#{file_path.gsub(/\//, '_').pluralize}"
-      end
-    end
+  def copy_templates
+    template 'model.rb.erb', "#{plugin_path}/app/models/#{model}.rb"
+    template 'unit_test.rb.erb', "#{plugin_path}/test/unit/#{model}_test.rb"
   end
 end
diff --git a/lib/generators/redmine_plugin_model/templates/fixtures.yml b/lib/generators/redmine_plugin_model/templates/fixtures.yml
deleted file mode 100644 (file)
index 6be3c81..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
-one:
-  id: 1
-<% for attribute in attributes -%>
-  <%= attribute.name %>: <%= attribute.default %>
-<% end -%>
-two:
-  id: 2
-<% for attribute in attributes -%>
-  <%= attribute.name %>: <%= attribute.default %>
-<% end -%>
diff --git a/lib/generators/redmine_plugin_model/templates/migration.rb.erb b/lib/generators/redmine_plugin_model/templates/migration.rb.erb
deleted file mode 100644 (file)
index 2a305a6..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-class <%= migration_name %> < ActiveRecord::Migration
-  def self.up
-    create_table :<%= table_name %> do |t|
-<% for attribute in attributes -%>
-      t.column :<%= attribute.name %>, :<%= attribute.type %>
-<% end -%>
-    end
-  end
-
-  def self.down
-    drop_table :<%= table_name %>
-  end
-end
index e730492b010a3783462f826a85679e0ecab9a56b..71284e96d0699c3021ebeafd4a5e0ba00dbced60 100644 (file)
@@ -1,3 +1,3 @@
-class <%= class_name %> < ActiveRecord::Base
+class <%= @model_class %> < ActiveRecord::Base
   unloadable
 end
index bc6ae913b219c117534b75750862c257a0a86f53..531510470f974a89a7d1ead4971f370b564cf01c 100644 (file)
@@ -1,7 +1,6 @@
 require File.dirname(__FILE__) + '/../test_helper'
 
-class <%= class_name %>Test < ActiveSupport::TestCase
-  fixtures :<%= table_name %>
+class <%= @model_class %>Test < ActiveSupport::TestCase
 
   # Replace this with your real tests.
   def test_truth
index 156bc76c2c9e357f22f0183c1786280445926937..550cd70280aebf7c2191c2dc8f562e4c424a5ff1 100644 (file)
@@ -205,7 +205,7 @@ Redmine::MenuManager.map :project_menu do |menu|
   menu.push :boards, { :controller => 'boards', :action => 'index', :id => nil }, :param => :project_id,
               :if => Proc.new { |p| p.boards.any? }, :caption => :label_board_plural
   menu.push :files, { :controller => 'files', :action => 'index' }, :caption => :label_file_plural, :param => :project_id
-  menu.push :repository, { :controller => 'repositories', :action => 'show' },
+  menu.push :repository, { :controller => 'repositories', :action => 'show', :repository_id => nil, :path => nil, :rev => nil },
               :if => Proc.new { |p| p.repository && !p.repository.new_record? }
   menu.push :settings, { :controller => 'projects', :action => 'settings' }, :last => true
 end
index 3dd5df826564cf0f09446518e3703e1bfaee3647..186709016a32380e89055bab77cdaeaa269c0a75 100644 (file)
@@ -72,7 +72,7 @@ module Redmine
           all.each do |object|
             clear = object.send(attribute)
             object.send "#{attribute}=", clear
-            raise(ActiveRecord::Rollback) unless object.save(false)
+            raise(ActiveRecord::Rollback) unless object.save(:validation => false)
           end
         end ? true : false
       end
@@ -81,8 +81,8 @@ module Redmine
         transaction do
           all.each do |object|
             clear = object.send(attribute)
-            object.write_attribute attribute, clear
-            raise(ActiveRecord::Rollback) unless object.save(false)
+            object.send :write_attribute, attribute, clear
+            raise(ActiveRecord::Rollback) unless object.save(:validation => false)
           end
         end
       end ? true : false
index f881f90a5b8a48772ef87adf4673f2ef1f56a82e..5f84e144f20a06f72eaec7b53db56854543e8d57 100644 (file)
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 module ActiveRecord
-  class Base
-    def self.find_ids(options={})
-      find_ids_with_associations(options)
+  module FinderMethods
+    def find_ids(*args)
+      find_ids_with_associations
     end
-  end
 
-  module Associations
-    module ClassMethods
-      def find_ids_with_associations(options = {})
-        catch :invalid_query do
-          join_dependency = ActiveRecord::Associations::ClassMethods::JoinDependency.new(self, merge_includes(scope(:find, :include), options[:include]), options[:joins])
-          return connection.select_values(construct_ids_finder_sql_with_included_associations(options, join_dependency)).map(&:to_i)
-        end
+    private
+  
+    def find_ids_with_associations
+        join_dependency = construct_join_dependency_for_association_find
+        relation = construct_relation_for_association_find_ids(join_dependency)
+        rows = connection.select_all(relation, 'SQL', relation.bind_values)
+        rows.map {|row| row["id"].to_i}
+      rescue ThrowResult
         []
-      end
-
-      def construct_ids_finder_sql_with_included_associations(options, join_dependency)
-        scope = scope(:find)
-        sql = "SELECT #{table_name}.id FROM #{(scope && scope[:from]) || options[:from] || quoted_table_name} "
-        sql << join_dependency.join_associations.collect{|join| join.association_join }.join
-
-        add_joins!(sql, options[:joins], scope)
-        add_conditions!(sql, options[:conditions], scope)
-        add_limited_ids_condition!(sql, options, join_dependency) if !using_limitable_reflections?(join_dependency.reflections) && ((scope && scope[:limit]) || options[:limit])
-
-        add_group!(sql, options[:group], options[:having], scope)
-        add_order!(sql, options[:order], scope)
-        add_limit!(sql, options, scope) if using_limitable_reflections?(join_dependency.reflections)
-        add_lock!(sql, options, scope)
+    end
 
-        return sanitize_sql(sql)
-      end
+    def construct_relation_for_association_find_ids(join_dependency)
+      relation = except(:includes, :eager_load, :preload, :select).select("#{table_name}.id")
+      apply_join_dependency(relation, join_dependency)
     end
   end
 end
index 2da5ffef99a08f2d8a46c6acb5d81a6b9af5f442..c865284ac60466232cf0564dd6b5361f8ded4466 100644 (file)
@@ -4,4 +4,8 @@ require File.dirname(__FILE__) + '/string/inflections'
 class String #:nodoc:
   include Redmine::CoreExtensions::String::Conversions
   include Redmine::CoreExtensions::String::Inflections
+
+  def is_binary_data?
+    ( self.count( "^ -~", "^\r\n" ).fdiv(self.size) > 0.3 || self.index( "\x00" ) ) unless empty?
+  end
 end
index dba36a91a3c2a56290f83bf889b29fac45f63235..f0a95f020cb58441474f88082ac8039c555ebba0 100644 (file)
@@ -17,7 +17,7 @@
 
 module Redmine
   module Hook
-    include ActionController::UrlWriter
+    #include ActionController::UrlWriter
 
     @@listener_classes = []
     @@listeners = nil
@@ -88,12 +88,12 @@ module Redmine
       include ActionView::Helpers::FormTagHelper
       include ActionView::Helpers::FormOptionsHelper
       include ActionView::Helpers::JavaScriptHelper
-      include ActionView::Helpers::PrototypeHelper
+      #include ActionView::Helpers::PrototypeHelper
       include ActionView::Helpers::NumberHelper
       include ActionView::Helpers::UrlHelper
       include ActionView::Helpers::AssetTagHelper
       include ActionView::Helpers::TextHelper
-      include ActionController::UrlWriter
+      include Rails.application.routes.url_helpers
       include ApplicationHelper
 
       # Default to creating links using only the path.  Subclasses can
@@ -113,6 +113,14 @@ module Redmine
           context[:controller].send(:render_to_string, {:locals => context}.merge(options))
         end
       end
+      
+      def controller
+        nil
+      end
+      
+      def config
+        ActionController::Base.config
+      end
     end
 
     # Helper module included in ApplicationHelper and ActionController so that
@@ -143,7 +151,7 @@ module Redmine
           default_context = { :project => @project }
           default_context[:controller] = controller if respond_to?(:controller)
           default_context[:request] = request if respond_to?(:request)
-          Redmine::Hook.call_hook(hook, default_context.merge(context)).join(' ')
+          Redmine::Hook.call_hook(hook, default_context.merge(context)).join(' ').html_safe
         end
       end
     end
index 5c13e3d1fdf36d6729649c70abcdb83276526752..1f57c4d0c6d40b1cbe53446c0c280991b113a96f 100644 (file)
@@ -43,6 +43,9 @@ module Redmine #:nodoc:
   #
   # When rendered, the plugin settings value is available as the local variable +settings+
   class Plugin
+    cattr_accessor :directory
+    self.directory = File.join(Rails.root, 'plugins')
+
     cattr_accessor :public_directory
     self.public_directory = File.join(Rails.root, 'public', 'plugin_assets')
 
@@ -70,9 +73,22 @@ module Redmine #:nodoc:
       p.instance_eval(&block)
       # Set a default name if it was not provided during registration
       p.name(id.to_s.humanize) if p.name.nil?
+
       # Adds plugin locales if any
       # YAML translation files should be found under <plugin>/config/locales/
-      ::I18n.load_path += Dir.glob(File.join(Rails.root, 'vendor', 'plugins', id.to_s, 'config', 'locales', '*.yml'))
+      ::I18n.load_path += Dir.glob(File.join(p.directory, 'config', 'locales', '*.yml'))
+
+      # Prepends the app/views directory of the plugin to the view path
+      view_path = File.join(p.directory, 'app', 'views')
+      if File.directory?(view_path)
+        ActionController::Base.prepend_view_path(view_path)
+      end
+
+      # Adds the app/{controllers,helpers,models} directories of the plugin to the autoload path
+      Dir.glob File.expand_path(File.join(p.directory, 'app', '{controllers,helpers,models}')) do |dir|
+        ActiveSupport::Dependencies.autoload_paths += [dir]
+      end
+
       registered_plugins[id] = p
     end
 
@@ -100,10 +116,38 @@ module Redmine #:nodoc:
       registered_plugins[id.to_sym].present?
     end
 
+    def self.load
+      Dir.glob(File.join(self.directory, '*')).sort.each do |directory|
+        if File.directory?(directory)
+          lib = File.join(directory, "lib")
+          if File.directory?(lib)
+            $:.unshift lib
+            ActiveSupport::Dependencies.autoload_paths += [lib]
+          end
+          initializer = File.join(directory, "init.rb")
+          if File.file?(initializer)
+            require initializer
+          end
+        end
+      end
+    end
+
     def initialize(id)
       @id = id.to_sym
     end
 
+    def directory
+      File.join(self.class.directory, id.to_s)
+    end
+
+    def public_directory
+      File.join(self.class.public_directory, id.to_s)
+    end
+
+    def assets_directory
+      File.join(directory, 'assets')
+    end
+
     def <=>(plugin)
       self.id.to_s <=> plugin.id.to_s
     end
@@ -277,5 +321,96 @@ module Redmine #:nodoc:
     def configurable?
       settings && settings.is_a?(Hash) && !settings[:partial].blank?
     end
+
+    def mirror_assets
+      source = assets_directory
+      destination = public_directory
+      return unless File.directory?(source)
+
+      source_files = Dir[source + "/**/*"]
+      source_dirs = source_files.select { |d| File.directory?(d) }
+      source_files -= source_dirs
+
+      unless source_files.empty?
+        base_target_dir = File.join(destination, File.dirname(source_files.first).gsub(source, ''))
+        FileUtils.mkdir_p(base_target_dir)
+      end
+
+      source_dirs.each do |dir|
+        # strip down these paths so we have simple, relative paths we can
+        # add to the destination
+        target_dir = File.join(destination, dir.gsub(source, ''))
+        begin
+          FileUtils.mkdir_p(target_dir)
+        rescue Exception => e
+          raise "Could not create directory #{target_dir}: \n" + e
+        end
+      end
+
+      source_files.each do |file|
+        begin
+          target = File.join(destination, file.gsub(source, ''))
+          unless File.exist?(target) && FileUtils.identical?(file, target)
+            FileUtils.cp(file, target)
+          end
+        rescue Exception => e
+          raise "Could not copy #{file} to #{target}: \n" + e
+        end
+      end
+    end
+
+    # The directory containing this plugin's migrations (<tt>plugin/db/migrate</tt>)
+    def migration_directory
+      File.join(Rails.root, 'plugins', id.to_s, 'db', 'migrate')
+    end
+  
+    # Returns the version number of the latest migration for this plugin. Returns
+    # nil if this plugin has no migrations.
+    def latest_migration
+      migrations.last
+    end
+    
+    # Returns the version numbers of all migrations for this plugin.
+    def migrations
+      migrations = Dir[migration_directory+"/*.rb"]
+      migrations.map { |p| File.basename(p).match(/0*(\d+)\_/)[1].to_i }.sort
+    end
+    
+    # Migrate this plugin to the given version
+    def migrate(version = nil)
+      Redmine::Plugin::Migrator.migrate_plugin(self, version)
+    end
+
+    class Migrator < ActiveRecord::Migrator
+      # We need to be able to set the 'current' plugin being migrated.
+      cattr_accessor :current_plugin
+    
+      class << self
+        # Runs the migrations from a plugin, up (or down) to the version given
+        def migrate_plugin(plugin, version)
+          self.current_plugin = plugin
+          return if current_version(plugin) == version
+          migrate(plugin.migration_directory, version)
+        end
+        
+        def current_version(plugin=current_plugin)
+          # Delete migrations that don't match .. to_i will work because the number comes first
+          ::ActiveRecord::Base.connection.select_values(
+            "SELECT version FROM #{schema_migrations_table_name}"
+          ).delete_if{ |v| v.match(/-#{plugin.id}/) == nil }.map(&:to_i).max || 0
+        end
+      end
+           
+      def migrated
+        sm_table = self.class.schema_migrations_table_name
+        ::ActiveRecord::Base.connection.select_values(
+          "SELECT version FROM #{sm_table}"
+        ).delete_if{ |v| v.match(/-#{current_plugin.id}/) == nil }.map(&:to_i).sort
+      end
+      
+      def record_version_state_after_migrating(version)
+        super(version.to_s + "-" + current_plugin.id.to_s)
+      end
+    end
   end
 end
index 9bcee71a676440a0b6d340991e69b43846247892..3a0d27c34e8b2bfb5cfefbd4a83abcf05945a666 100644 (file)
@@ -222,8 +222,8 @@ module Redmine
                       :author  => author,
                       :message => commit_log.chomp,
                       :paths => [{
-                        :revision => revision,
-                        :branch   => revBranch,
+                        :revision => revision.dup,
+                        :branch   => revBranch.dup,
                         :path     => scm_iconv('UTF-8', @path_encoding, entry_path),
                         :name     => scm_iconv('UTF-8', @path_encoding, entry_name),
                         :kind     => 'file',
index 71d237e673f64dc06a113ded8d7b3ec61b9201f4..51b974fd7c685c64e955576c73d82f8d72272ec8 100644 (file)
@@ -118,6 +118,14 @@ module ApplicationHelper
     stylesheet_path source
   end
 
+  def stylesheet_link_tag(source, *args)
+    if current_theme && current_theme.stylesheets.include?(source)
+      super current_theme.stylesheet_path(source), *args
+    else
+      super
+    end
+  end
+
   # Returns the header tags for the current theme
   def heads_for_theme
     if current_theme && current_theme.javascripts.include?('theme')
index 96580168fcd13fdbf6284c6ebf6995ece4cab512..b04bbaa47c53ea08415e27ef781443fcada66a8c 100644 (file)
@@ -22,7 +22,7 @@ module Redmine
       def relative_url_root
         ActionController::Base.respond_to?('relative_url_root') ?
           ActionController::Base.relative_url_root.to_s :
-          ActionController::AbstractRequest.relative_url_root.to_s
+          ActionController::Base.config.relative_url_root.to_s
       end
 
       # Sets the relative root url of the application
@@ -30,7 +30,7 @@ module Redmine
         if ActionController::Base.respond_to?('relative_url_root=')
           ActionController::Base.relative_url_root=arg
         else
-          ActionController::AbstractRequest.relative_url_root=arg
+          ActionController::Base.config.relative_url_root = arg
         end
       end
 
@@ -38,7 +38,7 @@ module Redmine
       # Example:
       #   random_hex(4) # => "89b8c729"
       def random_hex(n)
-        ActiveSupport::SecureRandom.hex(n)
+        SecureRandom.hex(n)
       end
     end
   end
index 45c4059887bd3a4254ebb9cfd160eb407c2ff6ae..c473160db730b4c7896b646109ccb5907e561e2d 100644 (file)
@@ -2,9 +2,9 @@ require 'rexml/document'
 
 module Redmine
   module VERSION #:nodoc:
-    MAJOR = 1
-    MINOR = 4
-    TINY  = 1
+    MAJOR = 2
+    MINOR = 0
+    TINY  = 0
 
     # Branch values:
     # * official release: nil
index f603c433c7374fccfb0055fd14b19ae26c568200..298a20d0be8f38c6644000b7501ee2c4121fb230 100644 (file)
 
 module Redmine
   module Views
-    class ApiTemplateHandler < ActionView::TemplateHandler
-      include ActionView::TemplateHandlers::Compilable
-
-      def compile(template)
+    class ApiTemplateHandler
+      def self.call(template)
         "Redmine::Views::Builders.for(params[:format]) do |api|; #{template.source}; self.output_buffer = api.output; end"
       end
     end
index 5814d00cb0caa2ecf952572594e6ea6aecd84dba..dc2707d6620c74fb2be4beff64145b01079afd9b 100644 (file)
@@ -15,6 +15,8 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
+require 'builder'
+
 module Redmine
   module Views
     module Builders
@@ -29,7 +31,7 @@ module Redmine
         end
 
         def method_missing(sym, *args, &block)
-          if args.size == 1 && args.first.is_a?(Time)
+          if args.size == 1 && args.first.is_a?(::Time)
             __send__ sym, args.first.xmlschema, &block
           else
             super
index 857ac066acaa0cc76a239e1679d0fda478c8de1c..bdf5ffb1183c1e9b629c9faa6334feb5a8a21970 100644 (file)
@@ -24,14 +24,14 @@ class Redmine::Views::LabelledFormBuilder < ActionView::Helpers::FormBuilder
         %w(date_select)).each do |selector|
     src = <<-END_SRC
     def #{selector}(field, options = {})
-      label_for_field(field, options) + super(field, options.except(:label))
+      label_for_field(field, options) + super(field, options.except(:label)).html_safe
     end
     END_SRC
     class_eval src, __FILE__, __LINE__
   end
 
   def select(field, choices, options = {}, html_options = {})
-    label_for_field(field, options) + super(field, choices, options, html_options.except(:label))
+    label_for_field(field, options) + super(field, choices, options, html_options.except(:label)).html_safe
   end
 
   # Returns a label tag for the given field
index 06f532ddeb61fdf2661b7e0ea672049674506b18..79368675568d2b5d62b062d35523f60138d34d96 100644 (file)
@@ -20,7 +20,7 @@ module Redmine
     module MyPage
       module Block
         def self.additional_blocks
-          @@additional_blocks ||= Dir.glob("#{Rails.root}/vendor/plugins/*/app/views/my/blocks/_*.{rhtml,erb}").inject({}) do |h,file|
+          @@additional_blocks ||= Dir.glob("#{Redmine::Plugin.directory}/*/app/views/my/blocks/_*.{rhtml,erb}").inject({}) do |h,file|
             name = File.basename(file).split('.').first.gsub(/^_/, '')
             h[name] = name.to_sym
             h
index 63914e8ce9b2469d66521f8ac896b6c1b4cbbdfa..f1d8378f55b3235d564cc58dfef16a34551c2f58 100644 (file)
@@ -115,8 +115,9 @@ module Redmine
               url=url[0..-2] # discard closing parenth from url
               post = ")"+post # add closing parenth to post
             end
-            tag = content_tag('a', proto + url, :href => "#{proto=="www."?"http://www.":proto}#{url}", :class => 'external')
-            %(#{leading}#{tag}#{post})
+            content = proto + url
+            href = "#{proto=="www."?"http://www.":proto}#{url}"
+            %(#{leading}<a class="external" href="#{ERB::Util.html_escape href}">#{ERB::Util.html_escape content}</a>#{post}).html_safe
           end
         end
       end
@@ -128,7 +129,7 @@ module Redmine
           if text.match(/<a\b[^>]*>(.*)(#{Regexp.escape(mail)})(.*)<\/a>/)
             mail
           else
-            content_tag('a', mail, :href => "mailto:#{mail}", :class => "email")
+            %(<a class="email" href="mailto:#{ERB::Util.html_escape mail}">#{ERB::Util.html_escape mail}</a>).html_safe
           end
         end
       end      
index dca43ddc7d5e323cc635e46fc3da9d2991aa6752..2588ae8b2ec9bf271fdd89e5ed58aa29356ec4d3 100644 (file)
@@ -7,3 +7,4 @@ end
 deprecated_task :load_default_data, "redmine:load_default_data"
 deprecated_task :migrate_from_mantis, "redmine:migrate_from_mantis"
 deprecated_task :migrate_from_trac, "redmine:migrate_from_trac"
+deprecated_task "db:migrate_plugins", "redmine:plugins:migrate"
index a80bd1d1bd1b1772a98ebf2f3df593563b6cc6ad..c1fdc7bf55fa3a87d29ca93c44f779791f894aeb 100644 (file)
@@ -1,34 +1,24 @@
-desc 'Generates a configuration file for cookie store sessions.'
+desc 'Generates a secret token for the application.'
 
-file 'config/initializers/session_store.rb' do
-  path = File.join(Rails.root, 'config', 'initializers', 'session_store.rb')
-  secret = ActiveSupport::SecureRandom.hex(40)
+file 'config/initializers/secret_token.rb' do
+  path = File.join(Rails.root, 'config', 'initializers', 'secret_token.rb')
+  secret = SecureRandom.hex(40)
   File.open(path, 'w') do |f|
     f.write <<"EOF"
-# This file was generated by 'rake config/initializers/session_store.rb',
-# and should not be made visible to public.
+# This file was generated by 'rake generate_secret_token', and should
+# not be made visible to public.
 # If you have a load-balancing Redmine cluster, you will need to use the
 # same version of this file on each machine. And be sure to restart your
 # server when you modify this file.
-
+#
 # Your secret key for verifying cookie session data integrity. If you
 # change this key, all old sessions will become invalid! Make sure the
 # secret is at least 30 characters and all random, no regular words or
 # you'll be exposed to dictionary attacks.
-ActionController::Base.session = {
-  :key => '_redmine_session',
-  #
-  # Uncomment and edit the :session_path below if are hosting your Redmine
-  # at a suburi and don't want the top level path to access the cookies
-  #
-  # See: http://www.redmine.org/issues/3968
-  #
-  # :session_path => '/url_path_to/your/redmine/',
-  :secret => '#{secret}'
-}
+RedmineApp::Application.config.secret_token = '#{secret}'
 EOF
   end
 end
 
-desc 'Generates a configuration file for cookie store sessions.'
-task :generate_session_store => ['config/initializers/session_store.rb']
+desc 'Generates a secret token for the application.'
+task :generate_secret_token => ['config/initializers/secret_token.rb']
diff --git a/lib/tasks/migrate_plugins.rake b/lib/tasks/migrate_plugins.rake
deleted file mode 100644 (file)
index 0516d83..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-namespace :db do
-  desc 'Migrates installed plugins.'
-  task :migrate_plugins => :environment do
-    if Rails.respond_to?('plugins')
-      Rails.plugins.each do |plugin|
-        next unless plugin.respond_to?('migrate')
-        puts "Migrating #{plugin.name}..."
-        plugin.migrate
-      end
-    else
-      puts "Undefined method plugins for Rails!"
-      puts "Make sure engines plugin is installed."
-    end
-  end
-end
diff --git a/lib/tasks/plugins.rake b/lib/tasks/plugins.rake
deleted file mode 100644 (file)
index 1368771..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-require 'source_annotation_extractor'
-
-# Modified version of the SourceAnnotationExtractor in railties
-# Will search for runable code that uses <tt>call_hook</tt>
-class PluginSourceAnnotationExtractor < SourceAnnotationExtractor
-  # Returns a hash that maps filenames under +dir+ (recursively) to arrays
-  # with their annotations. Only files with annotations are included, and only
-  # those with extension +.builder+, +.rb+, +.rxml+, +.rjs+, +.rhtml+, and +.erb+
-  # are taken into account.
-  def find_in(dir)
-    results = {}
-
-    Dir.glob("#{dir}/*") do |item|
-      next if File.basename(item)[0] == ?.
-
-      if File.directory?(item)
-        results.update(find_in(item))
-      elsif item =~ /(hook|test)\.rb/
-        # skip
-      elsif item =~ /\.(builder|(r(?:b|xml|js)))$/
-        results.update(extract_annotations_from(item, /\s*(#{tag})\(?\s*(.*)$/))
-      elsif item =~ /\.(rhtml|erb)$/
-        results.update(extract_annotations_from(item, /<%=\s*\s*(#{tag})\(?\s*(.*?)\s*%>/))
-      end
-    end
-
-    results
-  end
-end
-
-namespace :redmine do
-  namespace :plugins do
-    desc "Enumerate all Redmine plugin hooks and their context parameters"
-    task :hook_list do
-      PluginSourceAnnotationExtractor.enumerate 'call_hook'
-    end
-  end
-end
index 3e9faea703c749974891312957299755d503f920..8a6b98b44a22f9ddf8762d142cb46fce6157b5fc 100644 (file)
@@ -41,4 +41,28 @@ namespace :redmine do
   task :fetch_changesets => :environment do
     Repository.fetch_changesets
   end
+
+  desc 'Migrates and copies plugins assets.'
+  task :plugins do
+    Rake::Task["redmine:plugins:migrate"].invoke
+    Rake::Task["redmine:plugins:assets"].invoke
+  end
+
+  namespace :plugins do
+    desc 'Migrates installed plugins.'
+    task :migrate => :environment do
+      Redmine::Plugin.all.each do |plugin|
+        puts "Migrating #{plugin.name}..."
+        plugin.migrate
+      end
+    end
+
+    desc 'Copies plugins assets into the public directory.'
+    task :assets => :environment do
+      Redmine::Plugin.all.each do |plugin|
+        puts "Copying #{plugin.name} assets..."
+        plugin.mirror_assets
+      end
+    end
+  end
 end
diff --git a/lib/vendor/tmail-1.2.7/tmail.rb b/lib/vendor/tmail-1.2.7/tmail.rb
new file mode 100644 (file)
index 0000000..79d9fa8
--- /dev/null
@@ -0,0 +1,6 @@
+require 'tmail/version'
+require 'tmail/mail'
+require 'tmail/mailbox'
+require 'tmail/core_extensions'
+require 'tmail/net'
+require 'tmail/vendor/rchardet-1.3/lib/rchardet'
\ No newline at end of file
diff --git a/lib/vendor/tmail-1.2.7/tmail/Makefile b/lib/vendor/tmail-1.2.7/tmail/Makefile
new file mode 100644 (file)
index 0000000..8688b7f
--- /dev/null
@@ -0,0 +1,18 @@
+# lib/tmail/Makefile
+#
+
+debug:
+       rm -f parser.rb
+       make parser.rb DEBUG=true
+
+parser.rb: parser.y
+       if [ "$(DEBUG)" = true ]; then \
+           racc -v -g -o$@ parser.y ;\
+       else \
+           racc -E -o$@ parser.y ;\
+       fi
+
+clean:
+       rm -f parser.rb parser.output
+
+distclean: clean
diff --git a/lib/vendor/tmail-1.2.7/tmail/address.rb b/lib/vendor/tmail-1.2.7/tmail/address.rb
new file mode 100644 (file)
index 0000000..d506eaf
--- /dev/null
@@ -0,0 +1,392 @@
+=begin rdoc
+
+= Address handling class
+
+=end
+#--
+# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Note: Originally licensed under LGPL v2+. Using MIT license for Rails
+# with permission of Minero Aoki.
+#++
+
+require 'tmail/encode'
+require 'tmail/parser'
+
+
+module TMail
+
+  # = Class Address
+  # 
+  # Provides a complete handling library for email addresses. Can parse a string of an
+  # address directly or take in preformatted addresses themselves.  Allows you to add
+  # and remove phrases from the front of the address and provides a compare function for
+  # email addresses.
+  # 
+  # == Parsing and Handling a Valid Address:
+  # 
+  # Just pass the email address in as a string to Address.parse:
+  # 
+  #  email = TMail::Address.parse('Mikel Lindsaar <mikel@lindsaar.net>')
+  #  #=> #<TMail::Address mikel@lindsaar.net>
+  #  email.address
+  #  #=> "mikel@lindsaar.net"
+  #  email.local
+  #  #=> "mikel"
+  #  email.domain
+  #  #=> "lindsaar.net"
+  #  email.name             # Aliased as phrase as well
+  #  #=> "Mikel Lindsaar"
+  # 
+  # == Detecting an Invalid Address
+  # 
+  # If you want to check the syntactical validity of an email address, just pass it to
+  # Address.parse and catch any SyntaxError:
+  # 
+  #  begin
+  #    TMail::Address.parse("mikel   2@@@@@ me .com")
+  #  rescue TMail::SyntaxError
+  #    puts("Invalid Email Address Detected")
+  #  else
+  #    puts("Address is valid")
+  #  end
+  #  #=> "Invalid Email Address Detected"
+  class Address
+
+    include TextUtils #:nodoc:
+    
+    # Sometimes you need to parse an address, TMail can do it for you and provide you with
+    # a fairly robust method of detecting a valid address.
+    # 
+    # Takes in a string, returns a TMail::Address object.
+    # 
+    # Raises a TMail::SyntaxError on invalid email format
+    def Address.parse( str )
+      Parser.parse :ADDRESS, str
+    end
+
+    def address_group? #:nodoc:
+      false
+    end
+
+    # Address.new(local, domain)
+    # 
+    # Accepts:
+    # 
+    # * local - Left of the at symbol
+    # 
+    # * domain - Array of the domain split at the periods.
+    # 
+    # For example:
+    # 
+    #  Address.new("mikel", ["lindsaar", "net"])
+    #  #=> "#<TMail::Address mikel@lindsaar.net>"
+    def initialize( local, domain )
+      if domain
+        domain.each do |s|
+          raise SyntaxError, 'empty word in domain' if s.empty?
+        end
+      end
+      
+      # This is to catch an unquoted "@" symbol in the local part of the
+      # address.  Handles addresses like <"@"@me.com> and makes sure they
+      # stay like <"@"@me.com> (previously were becoming <@@me.com>)
+      if local && (local.join == '@' || local.join =~ /\A[^"].*?@.*?[^"]\Z/)
+        @local = "\"#{local.join}\""
+      else
+        @local = local
+      end
+
+      @domain = domain
+      @name   = nil
+      @routes = []
+    end
+
+    # Provides the name or 'phrase' of the email address.
+    # 
+    # For Example:
+    # 
+    #  email = TMail::Address.parse("Mikel Lindsaar <mikel@lindsaar.net>")
+    #  email.name
+    #  #=> "Mikel Lindsaar"
+    def name
+      @name
+    end
+
+    # Setter method for the name or phrase of the email
+    # 
+    # For Example:
+    # 
+    #  email = TMail::Address.parse("mikel@lindsaar.net")
+    #  email.name
+    #  #=> nil
+    #  email.name = "Mikel Lindsaar"
+    #  email.to_s
+    #  #=> "Mikel Lindsaar <mikel@me.com>"
+    def name=( str )
+      @name = str
+      @name = nil if str and str.empty?
+    end
+
+    #:stopdoc:
+    alias phrase  name
+    alias phrase= name=
+    #:startdoc:
+    
+    # This is still here from RFC 822, and is now obsolete per RFC2822 Section 4.
+    # 
+    # "When interpreting addresses, the route portion SHOULD be ignored."
+    # 
+    # It is still here, so you can access it.
+    # 
+    # Routes return the route portion at the front of the email address, if any.
+    # 
+    # For Example:
+    #  email = TMail::Address.parse( "<@sa,@another:Mikel@me.com>")
+    #  => #<TMail::Address Mikel@me.com>
+    #  email.to_s
+    #  => "<@sa,@another:Mikel@me.com>"
+    #  email.routes
+    #  => ["sa", "another"]
+    def routes
+      @routes
+    end
+    
+    def inspect #:nodoc:
+      "#<#{self.class} #{address()}>"
+    end
+
+    # Returns the local part of the email address
+    # 
+    # For Example:
+    # 
+    #  email = TMail::Address.parse("mikel@lindsaar.net")
+    #  email.local
+    #  #=> "mikel"
+    def local
+      return nil unless @local
+      return '""' if @local.size == 1 and @local[0].empty?
+      # Check to see if it is an array before trying to map it
+      if @local.respond_to?(:map)
+        @local.map {|i| quote_atom(i) }.join('.')
+      else
+        quote_atom(@local)
+      end
+    end
+
+    # Returns the domain part of the email address
+    # 
+    # For Example:
+    # 
+    #  email = TMail::Address.parse("mikel@lindsaar.net")
+    #  email.local
+    #  #=> "lindsaar.net"
+    def domain
+      return nil unless @domain
+      join_domain(@domain)
+    end
+
+    # Returns the full specific address itself
+    # 
+    # For Example:
+    # 
+    #  email = TMail::Address.parse("mikel@lindsaar.net")
+    #  email.address
+    #  #=> "mikel@lindsaar.net"
+    def spec
+      s = self.local
+      d = self.domain
+      if s and d
+        s + '@' + d
+      else
+        s
+      end
+    end
+
+    alias address spec
+
+    # Provides == function to the email.  Only checks the actual address
+    # and ignores the name/phrase component
+    # 
+    # For Example
+    # 
+    #  addr1 = TMail::Address.parse("My Address <mikel@lindsaar.net>")
+    #  #=> "#<TMail::Address mikel@lindsaar.net>"
+    #  addr2 = TMail::Address.parse("Another <mikel@lindsaar.net>")
+    #  #=> "#<TMail::Address mikel@lindsaar.net>"
+    #  addr1 == addr2
+    #  #=> true
+    def ==( other )
+      other.respond_to? :spec and self.spec == other.spec
+    end
+
+    alias eql? ==
+
+    # Provides a unique hash value for this record against the local and domain
+    # parts, ignores the name/phrase value
+    # 
+    #  email = TMail::Address.parse("mikel@lindsaar.net")
+    #  email.hash
+    #  #=> 18767598
+    def hash
+      @local.hash ^ @domain.hash
+    end
+
+    # Duplicates a TMail::Address object returning the duplicate
+    # 
+    #  addr1 = TMail::Address.parse("mikel@lindsaar.net")
+    #  addr2 = addr1.dup
+    #  addr1.id == addr2.id
+    #  #=> false
+    def dup
+      obj = self.class.new(@local.dup, @domain.dup)
+      obj.name = @name.dup if @name
+      obj.routes.replace @routes
+      obj
+    end
+
+    include StrategyInterface #:nodoc:
+
+    def accept( strategy, dummy1 = nil, dummy2 = nil ) #:nodoc:
+      unless @local
+        strategy.meta '<>'   # empty return-path
+        return
+      end
+
+      spec_p = (not @name and @routes.empty?)
+      if @name
+        strategy.phrase @name
+        strategy.space
+      end
+      tmp = spec_p ? '' : '<'
+      unless @routes.empty?
+        tmp << @routes.map {|i| '@' + i }.join(',') << ':'
+      end
+      tmp << self.spec
+      tmp << '>' unless spec_p
+      strategy.meta tmp
+      strategy.lwsp ''
+    end
+
+  end
+
+
+  class AddressGroup
+
+    include Enumerable
+
+    def address_group?
+      true
+    end
+
+    def initialize( name, addrs )
+      @name = name
+      @addresses = addrs
+    end
+
+    attr_reader :name
+    
+    def ==( other )
+      other.respond_to? :to_a and @addresses == other.to_a
+    end
+
+    alias eql? ==
+
+    def hash
+      map {|i| i.hash }.hash
+    end
+
+    def []( idx )
+      @addresses[idx]
+    end
+
+    def size
+      @addresses.size
+    end
+
+    def empty?
+      @addresses.empty?
+    end
+
+    def each( &block )
+      @addresses.each(&block)
+    end
+
+    def to_a
+      @addresses.dup
+    end
+
+    alias to_ary to_a
+
+    def include?( a )
+      @addresses.include? a
+    end
+
+    def flatten
+      set = []
+      @addresses.each do |a|
+        if a.respond_to? :flatten
+          set.concat a.flatten
+        else
+          set.push a
+        end
+      end
+      set
+    end
+
+    def each_address( &block )
+      flatten.each(&block)
+    end
+
+    def add( a )
+      @addresses.push a
+    end
+
+    alias push add
+    
+    def delete( a )
+      @addresses.delete a
+    end
+
+    include StrategyInterface
+
+    def accept( strategy, dummy1 = nil, dummy2 = nil )
+      strategy.phrase @name
+      strategy.meta ':'
+      strategy.space
+      first = true
+      each do |mbox|
+        if first
+          first = false
+        else
+          strategy.puts_meta ','
+        end
+        strategy.space
+        mbox.accept strategy
+      end
+      strategy.meta ';'
+      strategy.lwsp ''
+    end
+
+  end
+
+end   # module TMail
diff --git a/lib/vendor/tmail-1.2.7/tmail/attachments.rb b/lib/vendor/tmail-1.2.7/tmail/attachments.rb
new file mode 100644 (file)
index 0000000..19ce1aa
--- /dev/null
@@ -0,0 +1,65 @@
+=begin rdoc
+
+= Attachment handling file
+
+=end
+
+require 'kconv'
+require 'stringio'
+
+module TMail
+  class Attachment < StringIO
+    attr_accessor :original_filename, :content_type
+    alias quoted_filename original_filename
+  end
+
+  class Mail
+    def has_attachments?
+      attachment?(self) || multipart? && parts.any? { |part| attachment?(part) }
+    end
+
+    # Returns true if this part's content main type is text, else returns false.
+    # By main type is meant "text/plain" is text.  "text/html" is text
+    def text_content_type?
+      self.header['content-type'] && (self.header['content-type'].main_type == 'text')
+    end
+  
+    def inline_attachment?(part)
+      part['content-id'] || (part['content-disposition'] && part['content-disposition'].disposition == 'inline' && !part.text_content_type?)
+    end
+  
+    def attachment?(part)
+      part.disposition_is_attachment? || (!part.content_type.nil? && !part.text_content_type?) unless part.multipart?
+    end
+  
+    def attachments
+      if multipart?
+        parts.collect { |part| attachment(part) }.flatten.compact
+      elsif attachment?(self)
+        [attachment(self)]
+      end
+    end
+  
+    private
+  
+    def attachment(part)
+      if part.multipart?
+        part.attachments
+      elsif attachment?(part)
+        content   = part.body # unquoted automatically by TMail#body
+        file_name = (part['content-location'] && part['content-location'].body) ||
+                    part.sub_header('content-type', 'name') ||
+                    part.sub_header('content-disposition', 'filename') ||
+                    'noname'
+
+        return if content.blank?
+
+        attachment = TMail::Attachment.new(content)
+        attachment.original_filename = file_name.strip unless file_name.blank?
+        attachment.content_type = part.content_type
+        attachment
+      end
+    end
+
+  end
+end
diff --git a/lib/vendor/tmail-1.2.7/tmail/base64.rb b/lib/vendor/tmail-1.2.7/tmail/base64.rb
new file mode 100644 (file)
index 0000000..e294c62
--- /dev/null
@@ -0,0 +1,46 @@
+#--
+#   Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
+#
+#   Permission is hereby granted, free of charge, to any person obtaining
+#   a copy of this software and associated documentation files (the
+#   "Software"), to deal in the Software without restriction, including
+#   without limitation the rights to use, copy, modify, merge, publish,
+#   distribute, sublicense, and/or sell copies of the Software, and to
+#   permit persons to whom the Software is furnished to do so, subject to
+#   the following conditions:
+#
+#   The above copyright notice and this permission notice shall be
+#   included in all copies or substantial portions of the Software.
+#
+#   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+#   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+#   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+#   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+#   LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+#   OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+#   WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+#   Note: Originally licensed under LGPL v2+. Using MIT license for Rails
+#   with permission of Minero Aoki.
+#++
+#:stopdoc:
+module TMail
+  module Base64
+
+    module_function
+
+    def folding_encode( str, eol = "\n", limit = 60 )
+      [str].pack('m')
+    end
+
+    def encode( str )
+      [str].pack('m').tr( "\r\n", '' )
+    end
+
+    def decode( str, strict = false )
+      str.unpack('m').first
+    end
+
+  end
+end
+#:startdoc:
diff --git a/lib/vendor/tmail-1.2.7/tmail/compat.rb b/lib/vendor/tmail-1.2.7/tmail/compat.rb
new file mode 100644 (file)
index 0000000..1275df7
--- /dev/null
@@ -0,0 +1,41 @@
+#:stopdoc:
+unless Enumerable.method_defined?(:map) 
+  module Enumerable #:nodoc:
+    alias map collect
+  end
+end
+
+unless Enumerable.method_defined?(:select)
+  module Enumerable #:nodoc:
+    alias select find_all
+  end
+end
+
+unless Enumerable.method_defined?(:reject)
+  module Enumerable #:nodoc:
+    def reject
+      result = []
+      each do |i|
+        result.push i unless yield(i)
+      end
+      result
+    end
+  end
+end
+
+unless Enumerable.method_defined?(:sort_by)
+  module Enumerable #:nodoc:
+    def sort_by
+      map {|i| [yield(i), i] }.sort.map {|val, i| i }
+    end
+  end
+end
+
+unless File.respond_to?(:read)
+  def File.read(fname) #:nodoc:
+    File.open(fname) {|f|
+      return f.read
+    }
+  end
+end
+#:startdoc:
\ No newline at end of file
diff --git a/lib/vendor/tmail-1.2.7/tmail/config.rb b/lib/vendor/tmail-1.2.7/tmail/config.rb
new file mode 100644 (file)
index 0000000..3a876dc
--- /dev/null
@@ -0,0 +1,67 @@
+#--
+# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Note: Originally licensed under LGPL v2+. Using MIT license for Rails
+# with permission of Minero Aoki.
+#++
+#:stopdoc:
+module TMail
+
+  class Config
+
+    def initialize( strict )
+      @strict_parse = strict
+      @strict_base64decode = strict
+    end
+
+    def strict_parse?
+      @strict_parse
+    end
+
+    attr_writer :strict_parse
+
+    def strict_base64decode?
+      @strict_base64decode
+    end
+
+    attr_writer :strict_base64decode
+
+    def new_body_port( mail )
+      StringPort.new
+    end
+
+    alias new_preamble_port  new_body_port
+    alias new_part_port      new_body_port
+  
+  end
+
+  DEFAULT_CONFIG        = Config.new(false)
+  DEFAULT_STRICT_CONFIG = Config.new(true)
+
+  def Config.to_config( arg )
+    return DEFAULT_STRICT_CONFIG if arg == true
+    return DEFAULT_CONFIG        if arg == false
+    arg or DEFAULT_CONFIG
+  end
+
+end
+#:startdoc:
\ No newline at end of file
diff --git a/lib/vendor/tmail-1.2.7/tmail/core_extensions.rb b/lib/vendor/tmail-1.2.7/tmail/core_extensions.rb
new file mode 100644 (file)
index 0000000..da62c33
--- /dev/null
@@ -0,0 +1,63 @@
+#:stopdoc:
+unless Object.respond_to?(:blank?)
+  class Object
+    # Check first to see if we are in a Rails environment, no need to 
+    # define these methods if we are
+
+    # An object is blank if it's nil, empty, or a whitespace string.
+    # For example, "", "   ", nil, [], and {} are blank.
+    #
+    # This simplifies
+    #   if !address.nil? && !address.empty?
+    # to
+    #   if !address.blank?
+    def blank?
+      if respond_to?(:empty?) && respond_to?(:strip)
+        empty? or strip.empty?
+      elsif respond_to?(:empty?)
+        empty?
+      else
+        !self
+      end
+    end
+  end
+
+  class NilClass
+    def blank?
+      true
+    end
+  end
+
+  class FalseClass
+    def blank?
+      true
+    end
+  end
+
+  class TrueClass
+    def blank?
+      false
+    end
+  end
+
+  class Array
+    alias_method :blank?, :empty?
+  end
+
+  class Hash
+    alias_method :blank?, :empty?
+  end
+
+  class String
+    def blank?
+      empty? || strip.empty?
+    end
+  end
+
+  class Numeric
+    def blank?
+      false
+    end
+  end
+end
+#:startdoc:
\ No newline at end of file
diff --git a/lib/vendor/tmail-1.2.7/tmail/encode.rb b/lib/vendor/tmail-1.2.7/tmail/encode.rb
new file mode 100644 (file)
index 0000000..af66dfa
--- /dev/null
@@ -0,0 +1,590 @@
+#--
+# = COPYRIGHT:
+#
+#   Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
+#
+#   Permission is hereby granted, free of charge, to any person obtaining
+#   a copy of this software and associated documentation files (the
+#   "Software"), to deal in the Software without restriction, including
+#   without limitation the rights to use, copy, modify, merge, publish,
+#   distribute, sublicense, and/or sell copies of the Software, and to
+#   permit persons to whom the Software is furnished to do so, subject to
+#   the following conditions:
+#
+#   The above copyright notice and this permission notice shall be
+#   included in all copies or substantial portions of the Software.
+#
+#   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+#   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+#   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+#   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+#   LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+#   OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+#   WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+#   Note: Originally licensed under LGPL v2+. Using MIT license for Rails
+#   with permission of Minero Aoki.
+#++
+#:stopdoc:
+require 'nkf'
+require 'tmail/base64'
+require 'tmail/stringio'
+require 'tmail/utils'
+#:startdoc:
+
+
+module TMail
+  
+  #:stopdoc:
+  class << self
+    attr_accessor :KCODE
+  end
+  self.KCODE = 'NONE'
+
+  module StrategyInterface
+
+    def create_dest( obj )
+      case obj
+      when nil
+        StringOutput.new
+      when String
+        StringOutput.new(obj)
+      when IO, StringOutput
+        obj
+      else
+        raise TypeError, 'cannot handle this type of object for dest'
+      end
+    end
+    module_function :create_dest
+
+    #:startdoc:
+    # Returns the TMail object encoded and ready to be sent via SMTP etc.
+    # You should call this before you are packaging up your  email to
+    # correctly escape all the values that need escaping in the email, line
+    # wrap the email etc.
+    # 
+    # It is also a good idea to call this before you marshal or serialize
+    # a TMail object.
+    # 
+    # For Example:
+    # 
+    #  email = TMail::Load(my_email_file)
+    #  email_to_send = email.encoded
+    def encoded( eol = "\r\n", charset = 'j', dest = nil )
+      accept_strategy Encoder, eol, charset, dest
+    end
+
+    # Returns the TMail object decoded and ready to be used by you, your
+    # program etc.
+    # 
+    # You should call this before you are packaging up your  email to
+    # correctly escape all the values that need escaping in the email, line
+    # wrap the email etc.
+    # 
+    # For Example:
+    # 
+    #  email = TMail::Load(my_email_file)
+    #  email_to_send = email.encoded
+    def decoded( eol = "\n", charset = 'e', dest = nil )
+      # Turn the E-Mail into a string and return it with all
+      # encoded characters decoded.  alias for to_s
+      accept_strategy Decoder, eol, charset, dest
+    end
+
+    alias to_s decoded
+
+    def accept_strategy( klass, eol, charset, dest = nil ) #:nodoc:
+      dest ||= ''
+      accept klass.new( create_dest(dest), charset, eol )
+      dest
+    end
+
+  end
+
+  #:stopdoc:
+
+  ###
+  ### MIME B encoding decoder
+  ###
+
+  class Decoder
+
+    include TextUtils
+
+    encoded = '=\?(?:iso-2022-jp|euc-jp|shift_jis)\?[QB]\?[a-z0-9+/=]+\?='
+    ENCODED_WORDS = /#{encoded}(?:\s+#{encoded})*/i
+    SPACER       = "\t"
+
+    OUTPUT_ENCODING = {
+      'EUC'  => 'e',
+      'SJIS' => 's',
+    }
+
+    def self.decode( str, encoding = nil )
+      encoding ||= (OUTPUT_ENCODING[TMail.KCODE] || 'j')
+      opt = '-mS' + encoding
+      str.gsub(ENCODED_WORDS) {|s| NKF.nkf(opt, s) }
+    end
+
+    def initialize( dest, encoding = nil, eol = "\n" )
+      @f = StrategyInterface.create_dest(dest)
+      @encoding = (/\A[ejs]/ === encoding) ? encoding[0,1] : nil
+      @eol = eol
+    end
+
+    def decode( str )
+      self.class.decode(str, @encoding)
+    end
+    private :decode
+
+    def terminate
+    end
+
+    def header_line( str )
+      @f << decode(str)
+    end
+
+    def header_name( nm )
+      @f << nm << ': '
+    end
+
+    def header_body( str )
+      @f << decode(str)
+    end
+
+    def space
+      @f << ' '
+    end
+
+    alias spc space
+
+    def lwsp( str )
+      @f << str
+    end
+
+    def meta( str )
+      @f << str
+    end
+
+    def puts_meta( str )
+      @f << str
+    end
+
+    def text( str )
+      @f << decode(str)
+    end
+
+    def phrase( str )
+      @f << quote_phrase(decode(str))
+    end
+
+    def kv_pair( k, v )
+      v = dquote(v) unless token_safe?(v)
+      @f << k << '=' << v
+    end
+
+    def puts( str = nil )
+      @f << str if str
+      @f << @eol
+    end
+
+    def write( str )
+      @f << str
+    end
+
+  end
+
+
+  ###
+  ### MIME B-encoding encoder
+  ###
+
+  #
+  # FIXME: This class can handle only (euc-jp/shift_jis -> iso-2022-jp).
+  #
+  class Encoder
+
+    include TextUtils
+
+    BENCODE_DEBUG = false unless defined?(BENCODE_DEBUG)
+
+    def Encoder.encode( str )
+      e = new()
+      e.header_body str
+      e.terminate
+      e.dest.string
+    end
+
+    SPACER       = "\t"
+    MAX_LINE_LEN = 78
+    RFC_2822_MAX_LENGTH = 998
+
+    OPTIONS = {
+      'EUC'  => '-Ej -m0',
+      'SJIS' => '-Sj -m0',
+      'UTF8' => nil,      # FIXME
+      'NONE' => nil
+    }
+
+    def initialize( dest = nil, encoding = nil, eol = "\r\n", limit = nil )
+      @f = StrategyInterface.create_dest(dest)
+      @opt = OPTIONS[TMail.KCODE]
+      @eol = eol
+      @folded = false
+      @preserve_quotes = true
+      reset
+    end
+
+    def preserve_quotes=( bool )
+      @preserve_quotes
+    end
+
+    def preserve_quotes
+      @preserve_quotes
+    end
+
+    def normalize_encoding( str )
+      if @opt
+      then NKF.nkf(@opt, str)
+      else str
+      end
+    end
+
+    def reset
+      @text = ''
+      @lwsp = ''
+      @curlen = 0
+    end
+
+    def terminate
+      add_lwsp ''
+      reset
+    end
+
+    def dest
+      @f
+    end
+
+    def puts( str = nil )
+      @f << str if str
+      @f << @eol
+    end
+
+    def write( str )
+      @f << str
+    end
+
+    #
+    # add
+    #
+
+    def header_line( line )
+      scanadd line
+    end
+
+    def header_name( name )
+      add_text name.split(/-/).map {|i| i.capitalize }.join('-')
+      add_text ':'
+      add_lwsp ' '
+    end
+
+    def header_body( str )
+      scanadd normalize_encoding(str)
+    end
+
+    def space
+      add_lwsp ' '
+    end
+
+    alias spc space
+
+    def lwsp( str )
+      add_lwsp str.sub(/[\r\n]+[^\r\n]*\z/, '')
+    end
+
+    def meta( str )
+      add_text str
+    end
+
+    def puts_meta( str )
+      add_text str + @eol + SPACER
+    end
+
+    def text( str )
+      scanadd normalize_encoding(str)
+    end
+
+    def phrase( str )
+      str = normalize_encoding(str)
+      if CONTROL_CHAR === str
+        scanadd str
+      else
+        add_text quote_phrase(str)
+      end
+    end
+
+    # FIXME: implement line folding
+    #
+    def kv_pair( k, v )
+      return if v.nil?
+      v = normalize_encoding(v)
+      if token_safe?(v)
+        add_text k + '=' + v
+      elsif not CONTROL_CHAR === v
+        add_text k + '=' + quote_token(v)
+      else
+        # apply RFC2231 encoding
+        kv = k + '*=' + "iso-2022-jp'ja'" + encode_value(v)
+        add_text kv
+      end
+    end
+
+    def encode_value( str )
+      str.gsub(TOKEN_UNSAFE) {|s| '%%%02x' % s[0] }
+    end
+
+    private
+
+    def scanadd( str, force = false )
+      types = ''
+      strs = []
+      if str.respond_to?(:encoding)
+        enc = str.encoding 
+        str.force_encoding(Encoding::ASCII_8BIT)
+      end
+      until str.empty?
+        if m = /\A[^\e\t\r\n ]+/.match(str)
+          types << (force ? 'j' : 'a')
+          if str.respond_to?(:encoding)
+            strs.push m[0].force_encoding(enc)
+          else
+            strs.push m[0]
+          end
+        elsif m = /\A[\t\r\n ]+/.match(str)
+          types << 's'
+          if str.respond_to?(:encoding)
+            strs.push m[0].force_encoding(enc)
+          else
+            strs.push m[0]
+          end
+
+        elsif m = /\A\e../.match(str)
+          esc = m[0]
+          str = m.post_match
+          if esc != "\e(B" and m = /\A[^\e]+/.match(str)
+            types << 'j'
+            if str.respond_to?(:encoding)
+              strs.push m[0].force_encoding(enc)
+            else
+              strs.push m[0]
+            end
+          end
+
+        else
+          raise 'TMail FATAL: encoder scan fail'
+        end
+        (str = m.post_match) unless m.nil?
+      end
+
+      do_encode types, strs
+    end
+
+    def do_encode( types, strs )
+      #
+      # result  : (A|E)(S(A|E))*
+      # E       : W(SW)*
+      # W       : (J|A)+ but must contain J  # (J|A)*J(J|A)*
+      # A       : <<A character string not to be encoded>>
+      # J       : <<A character string to be encoded>>
+      # S       : <<LWSP>>
+      #
+      # An encoding unit is `E'.
+      # Input (parameter `types') is  (J|A)(J|A|S)*(J|A)
+      #
+      if BENCODE_DEBUG
+        puts
+        puts '-- do_encode ------------'
+        puts types.split(//).join(' ')
+        p strs
+      end
+
+      e = /[ja]*j[ja]*(?:s[ja]*j[ja]*)*/
+
+      while m = e.match(types)
+        pre = m.pre_match
+        concat_A_S pre, strs[0, pre.size] unless pre.empty?
+        concat_E m[0], strs[m.begin(0) ... m.end(0)]
+        types = m.post_match
+        strs.slice! 0, m.end(0)
+      end
+      concat_A_S types, strs
+    end
+
+    def concat_A_S( types, strs )
+      if RUBY_VERSION < '1.9'
+        a = ?a; s = ?s
+      else
+        a = 'a'.ord; s = 's'.ord
+      end
+      i = 0
+      types.each_byte do |t|
+        case t
+        when a then add_text strs[i]
+        when s then add_lwsp strs[i]
+        else
+          raise "TMail FATAL: unknown flag: #{t.chr}"
+        end
+        i += 1
+      end
+    end
+
+    METHOD_ID = {
+      ?j => :extract_J,
+      ?e => :extract_E,
+      ?a => :extract_A,
+      ?s => :extract_S
+    }
+
+    def concat_E( types, strs )
+      if BENCODE_DEBUG
+        puts '---- concat_E'
+        puts "types=#{types.split(//).join(' ')}"
+        puts "strs =#{strs.inspect}"
+      end
+
+      flush() unless @text.empty?
+
+      chunk = ''
+      strs.each_with_index do |s,i|
+        mid = METHOD_ID[types[i]]
+        until s.empty?
+          unless c = __send__(mid, chunk.size, s)
+            add_with_encode chunk unless chunk.empty?
+            flush
+            chunk = ''
+            fold
+            c = __send__(mid, 0, s)
+            raise 'TMail FATAL: extract fail' unless c
+          end
+          chunk << c
+        end
+      end
+      add_with_encode chunk unless chunk.empty?
+    end
+
+    def extract_J( chunksize, str )
+      size = max_bytes(chunksize, str.size) - 6
+      size = (size % 2 == 0) ? (size) : (size - 1)
+      return nil if size <= 0
+      if str.respond_to?(:encoding)
+        enc = str.encoding
+        str.force_encoding(Encoding::ASCII_8BIT)
+        "\e$B#{str.slice!(0, size)}\e(B".force_encoding(enc)
+      else
+        "\e$B#{str.slice!(0, size)}\e(B"
+      end
+    end
+
+    def extract_A( chunksize, str )
+      size = max_bytes(chunksize, str.size)
+      return nil if size <= 0
+      str.slice!(0, size)
+    end
+
+    alias extract_S extract_A
+
+    def max_bytes( chunksize, ssize )
+      (restsize() - '=?iso-2022-jp?B??='.size) / 4 * 3 - chunksize
+    end
+
+    #
+    # free length buffer
+    #
+
+    def add_text( str )
+      @text << str
+      # puts '---- text -------------------------------------'
+      # puts "+ #{str.inspect}"
+      # puts "txt >>>#{@text.inspect}<<<"
+    end
+
+    def add_with_encode( str )
+      @text << "=?iso-2022-jp?B?#{Base64.encode(str)}?="
+    end
+
+    def add_lwsp( lwsp )
+      # puts '---- lwsp -------------------------------------'
+      # puts "+ #{lwsp.inspect}"
+      fold if restsize() <= 0
+      flush(@folded)
+      @lwsp = lwsp
+    end
+
+    def flush(folded = false)
+      # puts '---- flush ----'
+      # puts "spc >>>#{@lwsp.inspect}<<<"
+      # puts "txt >>>#{@text.inspect}<<<"
+      @f << @lwsp << @text
+      if folded
+        @curlen = 0
+      else
+        @curlen += (@lwsp.size + @text.size)
+      end
+      @text = ''
+      @lwsp = ''
+    end
+
+    def fold
+      # puts '---- fold ----'
+      unless @f.string =~ /^.*?:$/
+        @f << @eol
+        @lwsp = SPACER
+      else
+        fold_header
+        @folded = true
+      end
+      @curlen = 0
+    end
+
+    def fold_header
+      # Called because line is too long - so we need to wrap.
+      # First look for whitespace in the text
+      # if it has text, fold there
+      # check the remaining text, if too long, fold again
+      # if it doesn't, then don't fold unless the line goes beyond 998 chars
+
+      # Check the text to see if there is whitespace, or if not
+      @wrapped_text = []
+      until @text.blank?
+        fold_the_string
+      end
+      @text = @wrapped_text.join("#{@eol}#{SPACER}")
+    end
+
+    def fold_the_string
+      whitespace_location = @text =~ /\s/ || @text.length
+      # Is the location of the whitespace shorter than the RCF_2822_MAX_LENGTH?
+      # if there is no whitespace in the string, then this
+      unless mazsize(whitespace_location) <= 0
+        @text.strip!
+        @wrapped_text << @text.slice!(0...whitespace_location)
+      # If it is not less, we have to wrap it destructively
+      else
+        slice_point = RFC_2822_MAX_LENGTH - @curlen - @lwsp.length
+        @text.strip!
+        @wrapped_text << @text.slice!(0...slice_point)
+      end
+    end
+
+    def restsize
+      MAX_LINE_LEN - (@curlen + @lwsp.size + @text.size)
+    end
+
+    def mazsize(whitespace_location)
+      # Per RFC2822, the maximum length of a line is 998 chars
+      RFC_2822_MAX_LENGTH - (@curlen + @lwsp.size + whitespace_location)
+    end
+
+  end
+  #:startdoc:
+end    # module TMail
diff --git a/lib/vendor/tmail-1.2.7/tmail/header.rb b/lib/vendor/tmail-1.2.7/tmail/header.rb
new file mode 100644 (file)
index 0000000..c111ea5
--- /dev/null
@@ -0,0 +1,962 @@
+#--
+# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Note: Originally licensed under LGPL v2+. Using MIT license for Rails
+# with permission of Minero Aoki.
+#++
+
+require 'tmail/encode'
+require 'tmail/address'
+require 'tmail/parser'
+require 'tmail/config'
+require 'tmail/utils'
+
+#:startdoc:
+module TMail
+
+  # Provides methods to handle and manipulate headers in the email
+  class HeaderField
+
+    include TextUtils
+
+    class << self
+
+      alias newobj new
+
+      def new( name, body, conf = DEFAULT_CONFIG )
+        klass = FNAME_TO_CLASS[name.downcase] || UnstructuredHeader
+        klass.newobj body, conf
+      end
+
+      # Returns a HeaderField object matching the header you specify in the "name" param.
+      # Requires an initialized TMail::Port to be passed in.
+      #
+      # The method searches the header of the Port you pass into it to find a match on
+      # the header line you pass.  Once a match is found, it will unwrap the matching line
+      # as needed to return an initialized HeaderField object.
+      #
+      # If you want to get the Envelope sender of the email object, pass in "EnvelopeSender",
+      # if you want the From address of the email itself, pass in 'From'.
+      #
+      # This is because a mailbox doesn't have the : after the From that designates the
+      # beginning of the envelope sender (which can be different to the from address of 
+      # the email)
+      #
+      # Other fields can be passed as normal, "Reply-To", "Received" etc.
+      #
+      # Note: Change of behaviour in 1.2.1 => returns nil if it does not find the specified
+      # header field, otherwise returns an instantiated object of the correct header class
+      # 
+      # For example:
+      #   port = TMail::FilePort.new("/test/fixtures/raw_email_simple")
+      #   h = TMail::HeaderField.new_from_port(port, "From")
+      #   h.addrs.to_s #=> "Mikel Lindsaar <mikel@nowhere.com>"
+      #   h = TMail::HeaderField.new_from_port(port, "EvelopeSender")
+      #   h.addrs.to_s #=> "mike@anotherplace.com.au"
+      #   h = TMail::HeaderField.new_from_port(port, "SomeWeirdHeaderField")
+      #   h #=> nil
+      def new_from_port( port, name, conf = DEFAULT_CONFIG )
+        if name == "EnvelopeSender"
+          name = "From"
+          re = Regexp.new('\A(From) ', 'i')
+        else
+          re = Regexp.new('\A(' + Regexp.quote(name) + '):', 'i')
+        end
+        str = nil
+        port.ropen {|f|
+            f.each do |line|
+              if m = re.match(line)            then str = m.post_match.strip
+              elsif str and /\A[\t ]/ === line then str << ' ' << line.strip
+              elsif /\A-*\s*\z/ === line       then break
+              elsif str                        then break
+              end
+            end
+        }
+        new(name, str, Config.to_config(conf)) if str
+      end
+
+      def internal_new( name, conf )
+        FNAME_TO_CLASS[name].newobj('', conf, true)
+      end
+
+    end   # class << self
+
+    def initialize( body, conf, intern = false )
+      @body = body
+      @config = conf
+
+      @illegal = false
+      @parsed = false
+      
+      if intern
+        @parsed = true
+        parse_init
+      end
+    end
+
+    def inspect
+      "#<#{self.class} #{@body.inspect}>"
+    end
+
+    def illegal?
+      @illegal
+    end
+
+    def empty?
+      ensure_parsed
+      return true if @illegal
+      isempty?
+    end
+
+    private
+
+    def ensure_parsed
+      return if @parsed
+      @parsed = true
+      parse
+    end
+
+    # defabstract parse
+    # end
+
+    def clear_parse_status
+      @parsed = false
+      @illegal = false
+    end
+
+    public
+
+    def body
+      ensure_parsed
+      v = Decoder.new(s = '')
+      do_accept v
+      v.terminate
+      s
+    end
+
+    def body=( str )
+      @body = str
+      clear_parse_status
+    end
+
+    include StrategyInterface
+
+    def accept( strategy )
+      ensure_parsed
+      do_accept strategy
+      strategy.terminate
+    end
+
+    # abstract do_accept
+
+  end
+
+
+  class UnstructuredHeader < HeaderField
+
+    def body
+      ensure_parsed
+      @body
+    end
+
+    def body=( arg )
+      ensure_parsed
+      @body = arg
+    end
+
+    private
+
+    def parse_init
+    end
+
+    def parse
+      @body = Decoder.decode(@body.gsub(/\n|\r\n|\r/, ''))
+    end
+
+    def isempty?
+      not @body
+    end
+
+    def do_accept( strategy )
+      strategy.text @body
+    end
+
+  end
+
+
+  class StructuredHeader < HeaderField
+
+    def comments
+      ensure_parsed
+      if @comments[0]
+        [Decoder.decode(@comments[0])]
+      else
+        @comments
+      end
+    end
+
+    private
+
+    def parse
+      save = nil
+
+      begin
+        parse_init
+        do_parse
+      rescue SyntaxError
+        if not save and mime_encoded? @body
+          save = @body
+          @body = Decoder.decode(save)
+          retry
+        elsif save
+          @body = save
+        end
+
+        @illegal = true
+        raise if @config.strict_parse?
+      end
+    end
+
+    def parse_init
+      @comments = []
+      init
+    end
+
+    def do_parse
+      quote_boundary
+      quote_unquoted_name
+      quote_unquoted_bencode
+      obj = Parser.parse(self.class::PARSE_TYPE, @body, @comments)
+      set obj if obj
+    end
+
+  end
+
+
+  class DateTimeHeader < StructuredHeader
+
+    PARSE_TYPE = :DATETIME
+
+    def date
+      ensure_parsed
+      @date
+    end
+
+    def date=( arg )
+      ensure_parsed
+      @date = arg
+    end
+
+    private
+
+    def init
+      @date = nil
+    end
+
+    def set( t )
+      @date = t
+    end
+
+    def isempty?
+      not @date
+    end
+
+    def do_accept( strategy )
+      strategy.meta time2str(@date)
+    end
+
+  end
+
+
+  class AddressHeader < StructuredHeader
+
+    PARSE_TYPE = :MADDRESS
+
+    def addrs
+      ensure_parsed
+      @addrs
+    end
+
+    private
+
+    def init
+      @addrs = []
+    end
+
+    def set( a )
+      @addrs = a
+    end
+
+    def isempty?
+      @addrs.empty?
+    end
+
+    def do_accept( strategy )
+      first = true
+      @addrs.each do |a|
+        if first
+          first = false
+        else
+          strategy.puts_meta ','
+          strategy.space
+        end
+        a.accept strategy
+      end
+
+      @comments.each do |c|
+        strategy.space
+        strategy.meta '('
+        strategy.text c
+        strategy.meta ')'
+      end
+    end
+
+  end
+
+
+  class ReturnPathHeader < AddressHeader
+
+    PARSE_TYPE = :RETPATH
+
+    def addr
+      addrs()[0]
+    end
+
+    def spec
+      a = addr() or return nil
+      a.spec
+    end
+
+    def routes
+      a = addr() or return nil
+      a.routes
+    end
+
+    private
+
+    def do_accept( strategy )
+      a = addr()
+
+      strategy.meta '<'
+      unless a.routes.empty?
+        strategy.meta a.routes.map {|i| '@' + i }.join(',')
+        strategy.meta ':'
+      end
+      spec = a.spec
+      strategy.meta spec if spec
+      strategy.meta '>'
+    end
+
+  end
+
+
+  class SingleAddressHeader < AddressHeader
+
+    def addr
+      addrs()[0]
+    end
+
+    private
+
+    def do_accept( strategy )
+      a = addr()
+      a.accept strategy
+      @comments.each do |c|
+        strategy.space
+        strategy.meta '('
+        strategy.text c
+        strategy.meta ')'
+      end
+    end
+
+  end
+
+
+  class MessageIdHeader < StructuredHeader
+
+    def id
+      ensure_parsed
+      @id
+    end
+
+    def id=( arg )
+      ensure_parsed
+      @id = arg
+    end
+
+    private
+
+    def init
+      @id = nil
+    end
+
+    def isempty?
+      not @id
+    end
+
+    def do_parse
+      @id = @body.slice(MESSAGE_ID) or
+              raise SyntaxError, "wrong Message-ID format: #{@body}"
+    end
+
+    def do_accept( strategy )
+      strategy.meta @id
+    end
+
+  end
+
+
+  class ReferencesHeader < StructuredHeader
+
+    def refs
+      ensure_parsed
+      @refs
+    end
+
+    def each_id
+      self.refs.each do |i|
+        yield i if MESSAGE_ID === i
+      end
+    end
+
+    def ids
+      ensure_parsed
+      @ids
+    end
+
+    def each_phrase
+      self.refs.each do |i|
+        yield i unless MESSAGE_ID === i
+      end
+    end
+
+    def phrases
+      ret = []
+      each_phrase {|i| ret.push i }
+      ret
+    end
+
+    private
+
+    def init
+      @refs = []
+      @ids = []
+    end
+
+    def isempty?
+      @ids.empty?
+    end
+
+    def do_parse
+      str = @body
+      while m = MESSAGE_ID.match(str)
+        pre = m.pre_match.strip
+        @refs.push pre unless pre.empty?
+        @refs.push s = m[0]
+        @ids.push s
+        str = m.post_match
+      end
+      str = str.strip
+      @refs.push str unless str.empty?
+    end
+
+    def do_accept( strategy )
+      first = true
+      @ids.each do |i|
+        if first
+          first = false
+        else
+          strategy.space
+        end
+        strategy.meta i
+      end
+    end
+
+  end
+
+
+  class ReceivedHeader < StructuredHeader
+
+    PARSE_TYPE = :RECEIVED
+
+    def from
+      ensure_parsed
+      @from
+    end
+
+    def from=( arg )
+      ensure_parsed
+      @from = arg
+    end
+
+    def by
+      ensure_parsed
+      @by
+    end
+
+    def by=( arg )
+      ensure_parsed
+      @by = arg
+    end
+
+    def via
+      ensure_parsed
+      @via
+    end
+
+    def via=( arg )
+      ensure_parsed
+      @via = arg
+    end
+
+    def with
+      ensure_parsed
+      @with
+    end
+
+    def id
+      ensure_parsed
+      @id
+    end
+
+    def id=( arg )
+      ensure_parsed
+      @id = arg
+    end
+
+    def _for
+      ensure_parsed
+      @_for
+    end
+
+    def _for=( arg )
+      ensure_parsed
+      @_for = arg
+    end
+
+    def date
+      ensure_parsed
+      @date
+    end
+
+    def date=( arg )
+      ensure_parsed
+      @date = arg
+    end
+
+    private
+
+    def init
+      @from = @by = @via = @with = @id = @_for = nil
+      @with = []
+      @date = nil
+    end
+
+    def set( args )
+      @from, @by, @via, @with, @id, @_for, @date = *args
+    end
+
+    def isempty?
+      @with.empty? and not (@from or @by or @via or @id or @_for or @date)
+    end
+
+    def do_accept( strategy )
+      list = []
+      list.push 'from '  + @from       if @from
+      list.push 'by '    + @by         if @by
+      list.push 'via '   + @via        if @via
+      @with.each do |i|
+        list.push 'with ' + i
+      end
+      list.push 'id '    + @id         if @id
+      list.push 'for <'  + @_for + '>' if @_for
+
+      first = true
+      list.each do |i|
+        strategy.space unless first
+        strategy.meta i
+        first = false
+      end
+      if @date
+        strategy.meta ';'
+        strategy.space
+        strategy.meta time2str(@date)
+      end
+    end
+
+  end
+
+
+  class KeywordsHeader < StructuredHeader
+
+    PARSE_TYPE = :KEYWORDS
+
+    def keys
+      ensure_parsed
+      @keys
+    end
+
+    private
+
+    def init
+      @keys = []
+    end
+
+    def set( a )
+      @keys = a
+    end
+
+    def isempty?
+      @keys.empty?
+    end
+
+    def do_accept( strategy )
+      first = true
+      @keys.each do |i|
+        if first
+          first = false
+        else
+          strategy.meta ','
+        end
+        strategy.meta i
+      end
+    end
+
+  end
+
+
+  class EncryptedHeader < StructuredHeader
+
+    PARSE_TYPE = :ENCRYPTED
+
+    def encrypter
+      ensure_parsed
+      @encrypter
+    end
+
+    def encrypter=( arg )
+      ensure_parsed
+      @encrypter = arg
+    end
+
+    def keyword
+      ensure_parsed
+      @keyword
+    end
+
+    def keyword=( arg )
+      ensure_parsed
+      @keyword = arg
+    end
+
+    private
+
+    def init
+      @encrypter = nil
+      @keyword = nil
+    end
+
+    def set( args )
+      @encrypter, @keyword = args
+    end
+
+    def isempty?
+      not (@encrypter or @keyword)
+    end
+
+    def do_accept( strategy )
+      if @key
+        strategy.meta @encrypter + ','
+        strategy.space
+        strategy.meta @keyword
+      else
+        strategy.meta @encrypter
+      end
+    end
+
+  end
+
+
+  class MimeVersionHeader < StructuredHeader
+
+    PARSE_TYPE = :MIMEVERSION
+
+    def major
+      ensure_parsed
+      @major
+    end
+
+    def major=( arg )
+      ensure_parsed
+      @major = arg
+    end
+
+    def minor
+      ensure_parsed
+      @minor
+    end
+
+    def minor=( arg )
+      ensure_parsed
+      @minor = arg
+    end
+
+    def version
+      sprintf('%d.%d', major, minor)
+    end
+
+    private
+
+    def init
+      @major = nil
+      @minor = nil
+    end
+
+    def set( args )
+      @major, @minor = *args
+    end
+
+    def isempty?
+      not (@major or @minor)
+    end
+
+    def do_accept( strategy )
+      strategy.meta sprintf('%d.%d', @major, @minor)
+    end
+
+  end
+
+
+  class ContentTypeHeader < StructuredHeader
+
+    PARSE_TYPE = :CTYPE
+
+    def main_type
+      ensure_parsed
+      @main
+    end
+
+    def main_type=( arg )
+      ensure_parsed
+      @main = arg.downcase
+    end
+
+    def sub_type
+      ensure_parsed
+      @sub
+    end
+
+    def sub_type=( arg )
+      ensure_parsed
+      @sub = arg.downcase
+    end
+
+    def content_type
+      ensure_parsed
+      @sub ? sprintf('%s/%s', @main, @sub) : @main
+    end
+
+    def params
+      ensure_parsed
+      unless @params.blank?
+        @params.each do |k, v|
+          @params[k] = unquote(v)
+        end
+      end
+      @params
+    end
+
+    def []( key )
+      ensure_parsed
+      @params and unquote(@params[key])
+    end
+
+    def []=( key, val )
+      ensure_parsed
+      (@params ||= {})[key] = val
+    end
+
+    private
+
+    def init
+      @main = @sub = @params = nil
+    end
+
+    def set( args )
+      @main, @sub, @params = *args
+    end
+
+    def isempty?
+      not (@main or @sub)
+    end
+
+    def do_accept( strategy )
+      if @sub
+        strategy.meta sprintf('%s/%s', @main, @sub)
+      else
+        strategy.meta @main
+      end
+      @params.each do |k,v|
+        if v
+          strategy.meta ';'
+          strategy.space
+          strategy.kv_pair k, unquote(v)
+        end
+      end
+    end
+
+  end
+
+
+  class ContentTransferEncodingHeader < StructuredHeader
+
+    PARSE_TYPE = :CENCODING
+
+    def encoding
+      ensure_parsed
+      @encoding
+    end
+
+    def encoding=( arg )
+      ensure_parsed
+      @encoding = arg
+    end
+
+    private
+
+    def init
+      @encoding = nil
+    end
+
+    def set( s )
+      @encoding = s
+    end
+
+    def isempty?
+      not @encoding
+    end
+
+    def do_accept( strategy )
+      strategy.meta @encoding.capitalize
+    end
+
+  end
+
+
+  class ContentDispositionHeader < StructuredHeader
+
+    PARSE_TYPE = :CDISPOSITION
+
+    def disposition
+      ensure_parsed
+      @disposition
+    end
+
+    def disposition=( str )
+      ensure_parsed
+      @disposition = str.downcase
+    end
+
+    def params
+      ensure_parsed
+      unless @params.blank?
+        @params.each do |k, v|
+          @params[k] = unquote(v)
+        end
+      end
+      @params
+    end
+
+    def []( key )
+      ensure_parsed
+      @params and unquote(@params[key])
+    end
+
+    def []=( key, val )
+      ensure_parsed
+      (@params ||= {})[key] = val
+    end
+
+    private
+
+    def init
+      @disposition = @params = nil
+    end
+
+    def set( args )
+      @disposition, @params = *args
+    end
+
+    def isempty?
+      not @disposition and (not @params or @params.empty?)
+    end
+
+    def do_accept( strategy )
+      strategy.meta @disposition
+      @params.each do |k,v|
+        strategy.meta ';'
+        strategy.space
+        strategy.kv_pair k, unquote(v)
+      end
+    end
+      
+  end
+
+
+  class HeaderField   # redefine
+
+    FNAME_TO_CLASS = {
+      'date'                      => DateTimeHeader,
+      'resent-date'               => DateTimeHeader,
+      'to'                        => AddressHeader,
+      'cc'                        => AddressHeader,
+      'bcc'                       => AddressHeader,
+      'from'                      => AddressHeader,
+      'reply-to'                  => AddressHeader,
+      'resent-to'                 => AddressHeader,
+      'resent-cc'                 => AddressHeader,
+      'resent-bcc'                => AddressHeader,
+      'resent-from'               => AddressHeader,
+      'resent-reply-to'           => AddressHeader,
+      'sender'                    => SingleAddressHeader,
+      'resent-sender'             => SingleAddressHeader,
+      'return-path'               => ReturnPathHeader,
+      'message-id'                => MessageIdHeader,
+      'resent-message-id'         => MessageIdHeader,
+      'in-reply-to'               => ReferencesHeader,
+      'received'                  => ReceivedHeader,
+      'references'                => ReferencesHeader,
+      'keywords'                  => KeywordsHeader,
+      'encrypted'                 => EncryptedHeader,
+      'mime-version'              => MimeVersionHeader,
+      'content-type'              => ContentTypeHeader,
+      'content-transfer-encoding' => ContentTransferEncodingHeader,
+      'content-disposition'       => ContentDispositionHeader,
+      'content-id'                => MessageIdHeader,
+      'subject'                   => UnstructuredHeader,
+      'comments'                  => UnstructuredHeader,
+      'content-description'       => UnstructuredHeader
+    }
+
+  end
+
+end   # module TMail
diff --git a/lib/vendor/tmail-1.2.7/tmail/index.rb b/lib/vendor/tmail-1.2.7/tmail/index.rb
new file mode 100644 (file)
index 0000000..554e2fd
--- /dev/null
@@ -0,0 +1,9 @@
+#:stopdoc:
+# This is here for Rolls. 
+# Rolls uses this instead of lib/tmail.rb.
+
+require 'tmail/version'
+require 'tmail/mail'
+require 'tmail/mailbox'
+require 'tmail/core_extensions'
+#:startdoc:
\ No newline at end of file
diff --git a/lib/vendor/tmail-1.2.7/tmail/interface.rb b/lib/vendor/tmail-1.2.7/tmail/interface.rb
new file mode 100644 (file)
index 0000000..27680c1
--- /dev/null
@@ -0,0 +1,1162 @@
+=begin rdoc
+
+= interface.rb Provides an interface to the TMail object
+
+=end
+#--
+# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Note: Originally licensed under LGPL v2+. Using MIT license for Rails
+# with permission of Minero Aoki.
+#++
+
+# TMail::Mail objects get accessed primarily through the methods in this file.
+# 
+# 
+
+require 'tmail/utils'
+
+module TMail
+
+  class Mail
+
+    # Allows you to query the mail object with a string to get the contents
+    # of the field you want.
+    # 
+    # Returns a string of the exact contents of the field
+    # 
+    #  mail.from = "mikel <mikel@lindsaar.net>"
+    #  mail.header_string("From") #=> "mikel <mikel@lindsaar.net>"
+    def header_string( name, default = nil )
+      h = @header[name.downcase] or return default
+      h.to_s
+    end
+
+    #:stopdoc:
+    #--
+    #== Attributes
+
+    include TextUtils
+
+    def set_string_array_attr( key, strs )
+      strs.flatten!
+      if strs.empty?
+        @header.delete key.downcase
+      else
+        store key, strs.join(', ')
+      end
+      strs
+    end
+    private :set_string_array_attr
+
+    def set_string_attr( key, str )
+      if str
+        store key, str
+      else
+        @header.delete key.downcase
+      end
+      str
+    end
+    private :set_string_attr
+
+    def set_addrfield( name, arg )
+      if arg
+        h = HeaderField.internal_new(name, @config)
+        h.addrs.replace [arg].flatten
+        @header[name] = h
+      else
+        @header.delete name
+      end
+      arg
+    end
+    private :set_addrfield
+
+    def addrs2specs( addrs )
+      return nil unless addrs
+      list = addrs.map {|addr|
+          if addr.address_group?
+          then addr.map {|a| a.spec }
+          else addr.spec
+          end
+      }.flatten
+      return nil if list.empty?
+      list
+    end
+    private :addrs2specs
+
+    #:startdoc:
+
+    #== Date and Time methods
+
+    # Returns the date of the email message as per the "date" header value or returns
+    # nil by default (if no date field exists).  
+    # 
+    # You can also pass whatever default you want into this method and it will return 
+    # that instead of nil if there is no date already set. 
+    def date( default = nil )
+      if h = @header['date']
+        h.date
+      else
+        default
+      end
+    end
+
+    # Destructively sets the date of the mail object with the passed Time instance,
+    # returns a Time instance set to the date/time of the mail
+    # 
+    # Example:
+    # 
+    #  now = Time.now
+    #  mail.date = now
+    #  mail.date #=> Sat Nov 03 18:47:50 +1100 2007
+    #  mail.date.class #=> Time
+    def date=( time )
+      if time
+        store 'Date', time2str(time)
+      else
+        @header.delete 'date'
+      end
+      time
+    end
+
+    # Returns the time of the mail message formatted to your taste using a 
+    # strftime format string.  If no date set returns nil by default or whatever value
+    # you pass as the second optional parameter.
+    # 
+    #  time = Time.now # (on Nov 16 2007)
+    #  mail.date = time
+    #  mail.strftime("%D") #=> "11/16/07"
+    def strftime( fmt, default = nil )
+      if t = date
+        t.strftime(fmt)
+      else
+        default
+      end
+    end
+
+    #== Destination methods
+
+    # Return a TMail::Addresses instance for each entry in the "To:" field of the mail object header.
+    # 
+    # If the "To:" field does not exist, will return nil by default or the value you
+    # pass as the optional parameter.
+    # 
+    # Example:
+    # 
+    #  mail = TMail::Mail.new
+    #  mail.to_addrs #=> nil
+    #  mail.to_addrs([]) #=> []
+    #  mail.to = "Mikel <mikel@me.org>, another Mikel <mikel@you.org>"
+    #  mail.to_addrs #=>  [#<TMail::Address mikel@me.org>, #<TMail::Address mikel@you.org>]
+    def to_addrs( default = nil )
+      if h = @header['to']
+        h.addrs
+      else
+        default
+      end
+    end
+
+    # Return a TMail::Addresses instance for each entry in the "Cc:" field of the mail object header.
+    # 
+    # If the "Cc:" field does not exist, will return nil by default or the value you
+    # pass as the optional parameter.
+    # 
+    # Example:
+    # 
+    #  mail = TMail::Mail.new
+    #  mail.cc_addrs #=> nil
+    #  mail.cc_addrs([]) #=> []
+    #  mail.cc = "Mikel <mikel@me.org>, another Mikel <mikel@you.org>"
+    #  mail.cc_addrs #=>  [#<TMail::Address mikel@me.org>, #<TMail::Address mikel@you.org>]
+     def cc_addrs( default = nil )
+      if h = @header['cc']
+        h.addrs
+      else
+        default
+      end
+    end
+
+    # Return a TMail::Addresses instance for each entry in the "Bcc:" field of the mail object header.
+    # 
+    # If the "Bcc:" field does not exist, will return nil by default or the value you
+    # pass as the optional parameter.
+    # 
+    # Example:
+    # 
+    #  mail = TMail::Mail.new
+    #  mail.bcc_addrs #=> nil
+    #  mail.bcc_addrs([]) #=> []
+    #  mail.bcc = "Mikel <mikel@me.org>, another Mikel <mikel@you.org>"
+    #  mail.bcc_addrs #=>  [#<TMail::Address mikel@me.org>, #<TMail::Address mikel@you.org>]
+    def bcc_addrs( default = nil )
+      if h = @header['bcc']
+        h.addrs
+      else
+        default
+      end
+    end
+
+    # Destructively set the to field of the "To:" header to equal the passed in string.
+    # 
+    # TMail will parse your contents and turn each valid email address into a TMail::Address 
+    # object before assigning it to the mail message.
+    #
+    # Example:
+    # 
+    #  mail = TMail::Mail.new
+    #  mail.to = "Mikel <mikel@me.org>, another Mikel <mikel@you.org>"
+    #  mail.to_addrs #=>  [#<TMail::Address mikel@me.org>, #<TMail::Address mikel@you.org>]
+    def to_addrs=( arg )
+      set_addrfield 'to', arg
+    end
+
+    # Destructively set the to field of the "Cc:" header to equal the passed in string.
+    # 
+    # TMail will parse your contents and turn each valid email address into a TMail::Address 
+    # object before assigning it to the mail message.
+    #
+    # Example:
+    # 
+    #  mail = TMail::Mail.new
+    #  mail.cc = "Mikel <mikel@me.org>, another Mikel <mikel@you.org>"
+    #  mail.cc_addrs #=>  [#<TMail::Address mikel@me.org>, #<TMail::Address mikel@you.org>]
+    def cc_addrs=( arg )
+      set_addrfield 'cc', arg
+    end
+
+    # Destructively set the to field of the "Bcc:" header to equal the passed in string.
+    # 
+    # TMail will parse your contents and turn each valid email address into a TMail::Address 
+    # object before assigning it to the mail message.
+    #
+    # Example:
+    # 
+    #  mail = TMail::Mail.new
+    #  mail.bcc = "Mikel <mikel@me.org>, another Mikel <mikel@you.org>"
+    #  mail.bcc_addrs #=>  [#<TMail::Address mikel@me.org>, #<TMail::Address mikel@you.org>]
+    def bcc_addrs=( arg )
+      set_addrfield 'bcc', arg
+    end
+
+    # Returns who the email is to as an Array of email addresses as opposed to an Array of 
+    # TMail::Address objects which is what Mail#to_addrs returns
+    # 
+    # Example:
+    # 
+    #  mail = TMail::Mail.new
+    #  mail.to = "Mikel <mikel@me.org>, another Mikel <mikel@you.org>"
+    #  mail.to #=>  ["mikel@me.org", "mikel@you.org"]
+    def to( default = nil )
+      addrs2specs(to_addrs(nil)) || default
+    end
+
+    # Returns who the email cc'd as an Array of email addresses as opposed to an Array of 
+    # TMail::Address objects which is what Mail#to_addrs returns
+    # 
+    # Example:
+    # 
+    #  mail = TMail::Mail.new
+    #  mail.cc = "Mikel <mikel@me.org>, another Mikel <mikel@you.org>"
+    #  mail.cc #=>  ["mikel@me.org", "mikel@you.org"]
+    def cc( default = nil )
+      addrs2specs(cc_addrs(nil)) || default
+    end
+
+    # Returns who the email bcc'd as an Array of email addresses as opposed to an Array of 
+    # TMail::Address objects which is what Mail#to_addrs returns
+    # 
+    # Example:
+    # 
+    #  mail = TMail::Mail.new
+    #  mail.bcc = "Mikel <mikel@me.org>, another Mikel <mikel@you.org>"
+    #  mail.bcc #=>  ["mikel@me.org", "mikel@you.org"]
+    def bcc( default = nil )
+      addrs2specs(bcc_addrs(nil)) || default
+    end
+
+    # Destructively sets the "To:" field to the passed array of strings (which should be valid 
+    # email addresses)
+    # 
+    # Example:
+    # 
+    #  mail = TMail::Mail.new
+    #  mail.to = ["mikel@abc.com", "Mikel <mikel@xyz.com>"]
+    #  mail.to #=>  ["mikel@abc.org", "mikel@xyz.org"]
+    #  mail['to'].to_s #=> "mikel@abc.com, Mikel <mikel@xyz.com>"
+    def to=( *strs )
+      set_string_array_attr 'To', strs
+    end
+
+    # Destructively sets the "Cc:" field to the passed array of strings (which should be valid 
+    # email addresses)
+    # 
+    # Example:
+    # 
+    #  mail = TMail::Mail.new
+    #  mail.cc = ["mikel@abc.com", "Mikel <mikel@xyz.com>"]
+    #  mail.cc #=>  ["mikel@abc.org", "mikel@xyz.org"]
+    #  mail['cc'].to_s #=> "mikel@abc.com, Mikel <mikel@xyz.com>"
+    def cc=( *strs )
+      set_string_array_attr 'Cc', strs
+    end
+
+    # Destructively sets the "Bcc:" field to the passed array of strings (which should be valid 
+    # email addresses)
+    # 
+    # Example:
+    # 
+    #  mail = TMail::Mail.new
+    #  mail.bcc = ["mikel@abc.com", "Mikel <mikel@xyz.com>"]
+    #  mail.bcc #=>  ["mikel@abc.org", "mikel@xyz.org"]
+    #  mail['bcc'].to_s #=> "mikel@abc.com, Mikel <mikel@xyz.com>"
+    def bcc=( *strs )
+      set_string_array_attr 'Bcc', strs
+    end
+
+    #== Originator methods
+
+    # Return a TMail::Addresses instance for each entry in the "From:" field of the mail object header.
+    # 
+    # If the "From:" field does not exist, will return nil by default or the value you
+    # pass as the optional parameter.
+    # 
+    # Example:
+    # 
+    #  mail = TMail::Mail.new
+    #  mail.from_addrs #=> nil
+    #  mail.from_addrs([]) #=> []
+    #  mail.from = "Mikel <mikel@me.org>, another Mikel <mikel@you.org>"
+    #  mail.from_addrs #=>  [#<TMail::Address mikel@me.org>, #<TMail::Address mikel@you.org>]
+    def from_addrs( default = nil )
+      if h = @header['from']
+        h.addrs
+      else
+        default
+      end
+    end
+
+    # Destructively set the to value of the "From:" header to equal the passed in string.
+    # 
+    # TMail will parse your contents and turn each valid email address into a TMail::Address 
+    # object before assigning it to the mail message.
+    #
+    # Example:
+    # 
+    #  mail = TMail::Mail.new
+    #  mail.from_addrs = "Mikel <mikel@me.org>, another Mikel <mikel@you.org>"
+    #  mail.from_addrs #=>  [#<TMail::Address mikel@me.org>, #<TMail::Address mikel@you.org>]
+    def from_addrs=( arg )
+      set_addrfield 'from', arg
+    end
+
+    # Returns who the email is from as an Array of email address strings instead to an Array of 
+    # TMail::Address objects which is what Mail#from_addrs returns
+    # 
+    # Example:
+    # 
+    #  mail = TMail::Mail.new
+    #  mail.from = "Mikel <mikel@me.org>, another Mikel <mikel@you.org>"
+    #  mail.from #=>  ["mikel@me.org", "mikel@you.org"]
+    def from( default = nil )
+      addrs2specs(from_addrs(nil)) || default
+    end
+
+    # Destructively sets the "From:" field to the passed array of strings (which should be valid 
+    # email addresses)
+    # 
+    # Example:
+    # 
+    #  mail = TMail::Mail.new
+    #  mail.from = ["mikel@abc.com", "Mikel <mikel@xyz.com>"]
+    #  mail.from #=>  ["mikel@abc.org", "mikel@xyz.org"]
+    #  mail['from'].to_s #=> "mikel@abc.com, Mikel <mikel@xyz.com>"
+    def from=( *strs )
+      set_string_array_attr 'From', strs
+    end
+
+    # Returns the "friendly" human readable part of the address
+    # 
+    # Example:
+    # 
+    #  mail = TMail::Mail.new
+    #  mail.from = "Mikel Lindsaar <mikel@abc.com>"
+    #  mail.friendly_from #=> "Mikel Lindsaar"
+    def friendly_from( default = nil )
+      h = @header['from']
+      a, = h.addrs
+      return default unless a
+      return a.phrase if a.phrase
+      return h.comments.join(' ') unless h.comments.empty?
+      a.spec
+    end
+
+    # Return a TMail::Addresses instance for each entry in the "Reply-To:" field of the mail object header.
+    # 
+    # If the "Reply-To:" field does not exist, will return nil by default or the value you
+    # pass as the optional parameter.
+    # 
+    # Example:
+    # 
+    #  mail = TMail::Mail.new
+    #  mail.reply_to_addrs #=> nil
+    #  mail.reply_to_addrs([]) #=> []
+    #  mail.reply_to = "Mikel <mikel@me.org>, another Mikel <mikel@you.org>"
+    #  mail.reply_to_addrs #=>  [#<TMail::Address mikel@me.org>, #<TMail::Address mikel@you.org>]
+    def reply_to_addrs( default = nil )
+      if h = @header['reply-to']
+        h.addrs.blank? ? default : h.addrs
+      else
+        default
+      end
+    end
+
+    # Destructively set the to value of the "Reply-To:" header to equal the passed in argument.
+    # 
+    # TMail will parse your contents and turn each valid email address into a TMail::Address 
+    # object before assigning it to the mail message.
+    #
+    # Example:
+    # 
+    #  mail = TMail::Mail.new
+    #  mail.reply_to_addrs = "Mikel <mikel@me.org>, another Mikel <mikel@you.org>"
+    #  mail.reply_to_addrs #=>  [#<TMail::Address mikel@me.org>, #<TMail::Address mikel@you.org>]
+    def reply_to_addrs=( arg )
+      set_addrfield 'reply-to', arg
+    end
+
+    # Returns who the email is from as an Array of email address strings instead to an Array of 
+    # TMail::Address objects which is what Mail#reply_to_addrs returns
+    # 
+    # Example:
+    # 
+    #  mail = TMail::Mail.new
+    #  mail.reply_to = "Mikel <mikel@me.org>, another Mikel <mikel@you.org>"
+    #  mail.reply_to #=>  ["mikel@me.org", "mikel@you.org"]
+    def reply_to( default = nil )
+      addrs2specs(reply_to_addrs(nil)) || default
+    end
+
+    # Destructively sets the "Reply-To:" field to the passed array of strings (which should be valid 
+    # email addresses)
+    # 
+    # Example:
+    # 
+    #  mail = TMail::Mail.new
+    #  mail.reply_to = ["mikel@abc.com", "Mikel <mikel@xyz.com>"]
+    #  mail.reply_to #=>  ["mikel@abc.org", "mikel@xyz.org"]
+    #  mail['reply_to'].to_s #=> "mikel@abc.com, Mikel <mikel@xyz.com>"
+    def reply_to=( *strs )
+      set_string_array_attr 'Reply-To', strs
+    end
+
+    # Return a TMail::Addresses instance of the "Sender:" field of the mail object header.
+    # 
+    # If the "Sender:" field does not exist, will return nil by default or the value you
+    # pass as the optional parameter.
+    # 
+    # Example:
+    # 
+    #  mail = TMail::Mail.new
+    #  mail.sender #=> nil
+    #  mail.sender([]) #=> []
+    #  mail.sender = "Mikel <mikel@me.org>"
+    #  mail.reply_to_addrs #=>  [#<TMail::Address mikel@me.org>]
+    def sender_addr( default = nil )
+      f = @header['sender'] or return default
+      f.addr                or return default
+    end
+
+    # Destructively set the to value of the "Sender:" header to equal the passed in argument.
+    # 
+    # TMail will parse your contents and turn each valid email address into a TMail::Address 
+    # object before assigning it to the mail message.
+    #
+    # Example:
+    # 
+    #  mail = TMail::Mail.new
+    #  mail.sender_addrs = "Mikel <mikel@me.org>, another Mikel <mikel@you.org>"
+    #  mail.sender_addrs #=>  [#<TMail::Address mikel@me.org>, #<TMail::Address mikel@you.org>]
+    def sender_addr=( addr )
+      if addr
+        h = HeaderField.internal_new('sender', @config)
+        h.addr = addr
+        @header['sender'] = h
+      else
+        @header.delete 'sender'
+      end
+      addr
+    end
+
+    # Returns who the sender of this mail is as string instead to an Array of 
+    # TMail::Address objects which is what Mail#sender_addr returns
+    # 
+    # Example:
+    # 
+    #  mail = TMail::Mail.new
+    #  mail.sender = "Mikel <mikel@me.org>"
+    #  mail.sender #=>  "mikel@me.org"
+    def sender( default = nil )
+      f = @header['sender'] or return default
+      a = f.addr            or return default
+      a.spec
+    end
+
+    # Destructively sets the "Sender:" field to the passed string (which should be a valid 
+    # email address)
+    # 
+    # Example:
+    # 
+    #  mail = TMail::Mail.new
+    #  mail.sender = "mikel@abc.com"
+    #  mail.sender #=>  "mikel@abc.org"
+    #  mail['sender'].to_s #=> "mikel@abc.com"
+    def sender=( str )
+      set_string_attr 'Sender', str
+    end
+
+    #== Subject methods
+
+    # Returns the subject of the mail instance.
+    # 
+    # If the subject field does not exist, returns nil by default or you can pass in as
+    # the parameter for what you want the default value to be.
+    # 
+    # Example:
+    # 
+    #  mail = TMail::Mail.new
+    #  mail.subject #=> nil
+    #  mail.subject("") #=> ""
+    #  mail.subject = "Hello"
+    #  mail.subject #=> "Hello"
+    def subject( default = nil )
+      if h = @header['subject']
+        h.body
+      else
+        default
+      end
+    end
+    alias quoted_subject subject
+
+    # Destructively sets the passed string as the subject of the mail message.
+    # 
+    # Example
+    # 
+    #  mail = TMail::Mail.new
+    #  mail.subject #=> "This subject"
+    #  mail.subject = "Another subject"
+    #  mail.subject #=> "Another subject"
+    def subject=( str )
+      set_string_attr 'Subject', str
+    end
+
+    #== Message Identity & Threading Methods
+    
+    # Returns the message ID for this mail object instance.
+    # 
+    # If the message_id field does not exist, returns nil by default or you can pass in as
+    # the parameter for what you want the default value to be.
+    # 
+    # Example:
+    # 
+    #  mail = TMail::Mail.new
+    #  mail.message_id #=> nil
+    #  mail.message_id(TMail.new_message_id) #=> "<47404c5326d9c_2ad4fbb80161@baci.local.tmail>"
+    #  mail.message_id = TMail.new_message_id
+    #  mail.message_id #=> "<47404c5326d9c_2ad4fbb80161@baci.local.tmail>"
+    def message_id( default = nil )
+      if h = @header['message-id']
+        h.id || default
+      else
+        default
+      end
+    end
+
+    # Destructively sets the message ID of the mail object instance to the passed in string
+    # 
+    # Invalid message IDs are ignored (silently, unless configured otherwise) and result in 
+    # a nil message ID.  Left and right angle brackets are required.
+    #
+    # Be warned however, that calling mail.ready_to_send will overwrite whatever value you
+    # have in this field with an automatically generated unique value.
+    # 
+    # If you really want to set your own message ID and know what you are doing per the
+    # various RFCs, you can do so with the enforced_message_id= command
+    # 
+    # Example:
+    # 
+    #  mail = TMail::Mail.new
+    #  mail.message_id = "<348F04F142D69C21-291E56D292BC@xxxx.net>"
+    #  mail.message_id #=> "<348F04F142D69C21-291E56D292BC@xxxx.net>"
+    #  mail.message_id = "this_is_my_badly_formatted_message_id"
+    #  mail.message_id #=> nil
+    def message_id=( str )
+      set_string_attr 'Message-Id', str
+    end
+
+    # Destructively sets the message ID of the mail object instance to the passed in string
+    # and also guarantees that calling #ready_to_send will not destroy what you set as the
+    # message_id
+    # 
+    # Example:
+    # 
+    #  mail = TMail::Mail.new
+    #  mail.message_id = "<348F04F142D69C21-291E56D292BC@xxxx.net>"
+    #  mail.message_id #=> "<348F04F142D69C21-291E56D292BC@xxxx.net>"
+    #  mail.ready_to_send
+    #  mail.message_id #=> "<348F04F142D69C21-291E56D292BC@xxxx.net>"
+    def enforced_message_id=( str )
+      @message_id_enforced = true
+      self.message_id = ( str )
+    end
+
+    # Returns the "In-Reply-To:" field contents as an array of this mail instance if it exists\10
+    # 
+    # If the in_reply_to field does not exist, returns nil by default or you can pass in as
+    # the parameter for what you want the default value to be.
+    # 
+    # Example:
+    # 
+    #  mail = TMail::Mail.new
+    #  mail.in_reply_to #=> nil
+    #  mail.in_reply_to([]) #=> []
+    #  TMail::Mail.load("../test/fixtures/raw_email_reply")
+    #  mail.in_reply_to #=> ["<348F04F142D69C21-291E56D292BC@xxxx.net>"]
+    def in_reply_to( default = nil )
+      if h = @header['in-reply-to']
+        h.ids
+      else
+        default
+      end
+    end
+
+    # Destructively sets the value of the "In-Reply-To:" field of an email.
+    # 
+    # Accepts an array of a single string of a message id
+    #
+    # Example: 
+    # 
+    #  mail = TMail::Mail.new
+    #  mail.in_reply_to = ["<348F04F142D69C21-291E56D292BC@xxxx.net>"]
+    #  mail.in_reply_to #=> ["<348F04F142D69C21-291E56D292BC@xxxx.net>"]
+    def in_reply_to=( *idstrs )
+      set_string_array_attr 'In-Reply-To', idstrs
+    end
+
+    # Returns the references of this email (prior messages relating to this message)
+    # as an array of message ID strings.  Useful when you are trying to thread an
+    # email.
+    # 
+    # If the references field does not exist, returns nil by default or you can pass in as
+    # the parameter for what you want the default value to be.
+    # 
+    # Example:
+    #
+    #  mail = TMail::Mail.new
+    #  mail.references #=> nil
+    #  mail.references([]) #=> []
+    #  mail = TMail::Mail.load("../test/fixtures/raw_email_reply")
+    #  mail.references #=> ["<473FF3B8.9020707@xxx.org>", "<348F04F142D69C21-291E56D292BC@xxxx.net>"]
+    def references( default = nil )
+      if h = @header['references']
+        h.refs
+      else
+        default
+      end
+    end
+
+    # Destructively sets the value of the "References:" field of an email.
+    # 
+    # Accepts an array of strings of message IDs
+    #
+    # Example: 
+    # 
+    #  mail = TMail::Mail.new
+    #  mail.references = ["<348F04F142D69C21-291E56D292BC@xxxx.net>"]
+    #  mail.references #=> ["<348F04F142D69C21-291E56D292BC@xxxx.net>"]
+    def references=( *strs )
+      set_string_array_attr 'References', strs
+    end
+
+    #== MIME header methods
+
+    # Returns the listed MIME version of this email from the "Mime-Version:" header field
+    # 
+    # If the mime_version field does not exist, returns nil by default or you can pass in as
+    # the parameter for what you want the default value to be.
+    # 
+    # Example:
+    #
+    #  mail = TMail::Mail.new
+    #  mail.mime_version #=> nil
+    #  mail.mime_version([]) #=> []
+    #  mail = TMail::Mail.load("../test/fixtures/raw_email")
+    #  mail.mime_version #=> "1.0"
+    def mime_version( default = nil )
+      if h = @header['mime-version']
+        h.version || default
+      else
+        default
+      end
+    end
+
+    def mime_version=( m, opt = nil )
+      if opt
+        if h = @header['mime-version']
+          h.major = m
+          h.minor = opt
+        else
+          store 'Mime-Version', "#{m}.#{opt}"
+        end
+      else
+        store 'Mime-Version', m
+      end
+      m
+    end
+
+    # Returns the current "Content-Type" of the mail instance.
+    #
+    # If the content_type field does not exist, returns nil by default or you can pass in as
+    # the parameter for what you want the default value to be.
+    # 
+    # Example:
+    #
+    #  mail = TMail::Mail.new
+    #  mail.content_type #=> nil
+    #  mail.content_type([]) #=> []
+    #  mail = TMail::Mail.load("../test/fixtures/raw_email")
+    #  mail.content_type #=> "text/plain"
+    def content_type( default = nil )
+      if h = @header['content-type']
+        h.content_type || default
+      else
+        default
+      end
+    end
+
+    # Returns the current main type of the "Content-Type" of the mail instance.
+    #
+    # If the content_type field does not exist, returns nil by default or you can pass in as
+    # the parameter for what you want the default value to be.
+    # 
+    # Example:
+    #
+    #  mail = TMail::Mail.new
+    #  mail.main_type #=> nil
+    #  mail.main_type([]) #=> []
+    #  mail = TMail::Mail.load("../test/fixtures/raw_email")
+    #  mail.main_type #=> "text"
+    def main_type( default = nil )
+      if h = @header['content-type']
+        h.main_type || default
+      else
+        default
+      end
+    end
+
+    # Returns the current sub type of the "Content-Type" of the mail instance.
+    #
+    # If the content_type field does not exist, returns nil by default or you can pass in as
+    # the parameter for what you want the default value to be.
+    # 
+    # Example:
+    #
+    #  mail = TMail::Mail.new
+    #  mail.sub_type #=> nil
+    #  mail.sub_type([]) #=> []
+    #  mail = TMail::Mail.load("../test/fixtures/raw_email")
+    #  mail.sub_type #=> "plain"
+    def sub_type( default = nil )
+      if h = @header['content-type']
+        h.sub_type || default
+      else
+        default
+      end
+    end
+
+    # Destructively sets the "Content-Type:" header field of this mail object
+    # 
+    # Allows you to set the main type, sub type as well as parameters to the field.
+    # The main type and sub type need to be a string.
+    # 
+    # The optional params hash can be passed with keys as symbols and values as a string,
+    # or strings as keys and values.
+    # 
+    # Example:
+    # 
+    #  mail = TMail::Mail.new
+    #  mail.set_content_type("text", "plain")
+    #  mail.to_s #=> "Content-Type: text/plain\n\n"
+    # 
+    #  mail.set_content_type("text", "plain", {:charset => "EUC-KR", :format => "flowed"})
+    #  mail.to_s #=> "Content-Type: text/plain; charset=EUC-KR; format=flowed\n\n"
+    #
+    #  mail.set_content_type("text", "plain", {"charset" => "EUC-KR", "format" => "flowed"})
+    #  mail.to_s #=> "Content-Type: text/plain; charset=EUC-KR; format=flowed\n\n"
+    def set_content_type( str, sub = nil, param = nil )
+      if sub
+        main, sub = str, sub
+      else
+        main, sub = str.split(%r</>, 2)
+        raise ArgumentError, "sub type missing: #{str.inspect}" unless sub
+      end
+      if h = @header['content-type']
+        h.main_type = main
+        h.sub_type  = sub
+        h.params.clear
+      else
+        store 'Content-Type', "#{main}/#{sub}"
+      end
+      @header['content-type'].params.replace param if param
+      str
+    end
+
+    alias content_type= set_content_type
+    
+    # Returns the named type parameter as a string, from the "Content-Type:" header.
+    # 
+    # Example:
+    # 
+    #  mail = TMail::Mail.new
+    #  mail.type_param("charset") #=> nil
+    #  mail.type_param("charset", []) #=> []
+    #  mail.set_content_type("text", "plain", {:charset => "EUC-KR", :format => "flowed"})
+    #  mail.type_param("charset") #=> "EUC-KR"
+    #  mail.type_param("format") #=> "flowed"
+    def type_param( name, default = nil )
+      if h = @header['content-type']
+        h[name] || default
+      else
+        default
+      end
+    end
+
+    # Returns the character set of the email.  Returns nil if no encoding set or returns
+    # whatever default you pass as a parameter - note passing the parameter does NOT change
+    # the mail object in any way.
+    # 
+    # Example:
+    # 
+    #  mail = TMail::Mail.load("path_to/utf8_email")
+    #  mail.charset #=> "UTF-8"
+    # 
+    #  mail = TMail::Mail.new
+    #  mail.charset #=> nil
+    #  mail.charset("US-ASCII") #=> "US-ASCII"
+    def charset( default = nil )
+      if h = @header['content-type']
+        h['charset'] or default
+      else
+        mime_version_charset || default
+      end
+    end
+
+    # some weird emails come with the charset specified in the mime-version header:
+    #
+    #  #<TMail::MimeVersionHeader "1.0\n charset=\"gb2312\"">
+    #
+    def mime_version_charset
+      if header['mime-version'].inspect =~ /charset=('|\\")?([^\\"']+)/
+        $2
+      end
+    end
+
+    # Destructively sets the character set used by this mail object to the passed string, you
+    # should note though that this does nothing to the mail body, just changes the header
+    # value, you will need to transliterate the body as well to match whatever you put 
+    # in this header value if you are changing character sets.
+    # 
+    # Example:
+    # 
+    #  mail = TMail::Mail.new
+    #  mail.charset #=> nil
+    #  mail.charset = "UTF-8"
+    #  mail.charset #=> "UTF-8"
+    def charset=( str )
+      if str
+        if h = @header[ 'content-type' ]
+          h['charset'] = str
+        else
+          store 'Content-Type', "text/plain; charset=#{str}"
+        end
+      end
+      str
+    end
+
+    # Returns the transfer encoding of the email.  Returns nil if no encoding set or returns
+    # whatever default you pass as a parameter - note passing the parameter does NOT change
+    # the mail object in any way.
+    # 
+    # Example:
+    # 
+    #  mail = TMail::Mail.load("path_to/base64_encoded_email")
+    #  mail.transfer_encoding #=> "base64"
+    # 
+    #  mail = TMail::Mail.new
+    #  mail.transfer_encoding #=> nil
+    #  mail.transfer_encoding("base64") #=> "base64"
+    def transfer_encoding( default = nil )
+      if h = @header['content-transfer-encoding']
+        h.encoding || default
+      else
+        default
+      end
+    end
+
+    # Destructively sets the transfer encoding of the mail object to the passed string, you
+    # should note though that this does nothing to the mail body, just changes the header
+    # value, you will need to encode or decode the body as well to match whatever you put 
+    # in this header value.
+    # 
+    # Example:
+    # 
+    #  mail = TMail::Mail.new
+    #  mail.transfer_encoding #=> nil
+    #  mail.transfer_encoding = "base64"
+    #  mail.transfer_encoding #=> "base64"
+    def transfer_encoding=( str )
+      set_string_attr 'Content-Transfer-Encoding', str
+    end
+
+    alias encoding                   transfer_encoding
+    alias encoding=                  transfer_encoding=
+    alias content_transfer_encoding  transfer_encoding
+    alias content_transfer_encoding= transfer_encoding=
+
+    # Returns the content-disposition of the mail object, returns nil or the passed 
+    # default value if given
+    # 
+    # Example:
+    # 
+    #  mail = TMail::Mail.load("path_to/raw_mail_with_attachment") 
+    #  mail.disposition #=> "attachment"
+    #
+    #  mail = TMail::Mail.load("path_to/plain_simple_email")
+    #  mail.disposition #=> nil
+    #  mail.disposition(false) #=> false
+    def disposition( default = nil )
+      if h = @header['content-disposition']
+        h.disposition || default
+      else
+        default
+      end
+    end
+
+    alias content_disposition     disposition
+
+    # Allows you to set the content-disposition of the mail object.  Accepts a type
+    # and a hash of parameters.
+    # 
+    # Example:
+    # 
+    #  mail.set_disposition("attachment", {:filename => "test.rb"})
+    #  mail.disposition #=> "attachment"
+    #  mail['content-disposition'].to_s #=> "attachment; filename=test.rb"
+    def set_disposition( str, params = nil )
+      if h = @header['content-disposition']
+        h.disposition = str
+        h.params.clear
+      else
+        store('Content-Disposition', str)
+        h = @header['content-disposition']
+      end
+      h.params.replace params if params
+    end
+
+    alias disposition=            set_disposition
+    alias set_content_disposition set_disposition
+    alias content_disposition=    set_disposition
+
+    # Returns the value of a parameter in an existing content-disposition header
+    # 
+    # Example:
+    # 
+    #  mail.set_disposition("attachment", {:filename => "test.rb"})
+    #  mail['content-disposition'].to_s #=> "attachment; filename=test.rb"
+    #  mail.disposition_param("filename") #=> "test.rb"
+    #  mail.disposition_param("missing_param_key") #=> nil
+    #  mail.disposition_param("missing_param_key", false) #=> false
+    #  mail.disposition_param("missing_param_key", "Nothing to see here") #=> "Nothing to see here"
+    def disposition_param( name, default = nil )
+      if h = @header['content-disposition']
+        h[name] || default
+      else
+        default
+      end
+    end
+
+    # Convert the Mail object's body into a Base64 encoded email
+    # returning the modified Mail object
+    def base64_encode!
+      store 'Content-Transfer-Encoding', 'Base64'
+      self.body = base64_encode
+    end
+
+    # Return the result of encoding the TMail::Mail object body
+    # without altering the current body
+    def base64_encode
+      Base64.folding_encode(self.body)
+    end
+
+    # Convert the Mail object's body into a Base64 decoded email
+    # returning the modified Mail object
+    def base64_decode!
+      if /base64/i === self.transfer_encoding('')
+        store 'Content-Transfer-Encoding', '8bit'
+        self.body = base64_decode
+      end
+    end
+
+    # Returns the result of decoding the TMail::Mail object body
+    # without altering the current body
+    def base64_decode
+      Base64.decode(self.body, @config.strict_base64decode?)
+    end
+
+    # Returns an array of each destination in the email message including to: cc: or bcc:
+    # 
+    # Example:
+    # 
+    #  mail.to = "Mikel <mikel@lindsaar.net>"
+    #  mail.cc = "Trans <t@t.com>"
+    #  mail.bcc = "bob <bob@me.com>"
+    #  mail.destinations #=> ["mikel@lindsaar.net", "t@t.com", "bob@me.com"]
+    def destinations( default = nil )
+      ret = []
+      %w( to cc bcc ).each do |nm|
+        if h = @header[nm]
+          h.addrs.each {|i| ret.push i.address }
+        end
+      end
+      ret.empty? ? default : ret
+    end
+
+    # Yields a block of destination, yielding each as a string.
+    #  (from the destinations example)
+    #  mail.each_destination { |d| puts "#{d.class}: #{d}" }
+    #  String: mikel@lindsaar.net
+    #  String: t@t.com
+    #  String: bob@me.com
+    def each_destination( &block )
+      destinations([]).each do |i|
+        if Address === i
+          yield i
+        else
+          i.each(&block)
+        end
+      end
+    end
+
+    alias each_dest each_destination
+
+    # Returns an array of reply to addresses that the Mail object has, 
+    # or if the Mail message has no reply-to, returns an array of the
+    # Mail objects from addresses.  Else returns the default which can
+    # either be passed as a parameter or defaults to nil
+    # 
+    # Example:
+    #  mail.from = "Mikel <mikel@lindsaar.net>"
+    #  mail.reply_to = nil
+    #  mail.reply_addresses #=> [""]  
+    # 
+    def reply_addresses( default = nil )
+      reply_to_addrs(nil) or from_addrs(nil) or default
+    end
+
+    # Returns the "sender" field as an array -> useful to find out who to 
+    # send an error email to.
+    def error_reply_addresses( default = nil )
+      if s = sender(nil)
+        [s]
+      else
+        from_addrs(default)
+      end
+    end
+
+    # Returns true if the Mail object is a multipart message
+    def multipart?
+      main_type('').downcase == 'multipart'
+    end
+
+    # Creates a new email in reply to self.  Sets the In-Reply-To and
+    # References headers for you automagically.
+    #
+    # Example:
+    #  mail = TMail::Mail.load("my_email")
+    #  reply_email = mail.create_reply
+    #  reply_email.class         #=> TMail::Mail
+    #  reply_email.references  #=> ["<d3b8cf8e49f04480850c28713a1f473e@lindsaar.net>"]
+    #  reply_email.in_reply_to #=> ["<d3b8cf8e49f04480850c28713a1f473e@lindsaar.net>"]
+    def create_reply
+      setup_reply create_empty_mail()
+    end
+
+    # Creates a new email in reply to self.  Sets the In-Reply-To and
+    # References headers for you automagically.
+    #
+    # Example:
+    #  mail = TMail::Mail.load("my_email")
+    #  forward_email = mail.create_forward
+    #  forward_email.class         #=> TMail::Mail
+    #  forward_email.content_type  #=> "multipart/mixed"
+    #  forward_email.body          #=> "Attachment: (unnamed)"
+    #  forward_email.encoded       #=> Returns the original email as a MIME attachment
+    def create_forward
+      setup_forward create_empty_mail()
+    end
+
+    #:stopdoc:
+    private
+
+    def create_empty_mail
+      self.class.new(StringPort.new(''), @config)
+    end
+
+    def setup_reply( mail )
+      if tmp = reply_addresses(nil)
+        mail.to_addrs = tmp
+      end
+
+      mid = message_id(nil)
+      tmp = references(nil) || []
+      tmp.push mid if mid
+      mail.in_reply_to = [mid] if mid
+      mail.references = tmp unless tmp.empty?
+      mail.subject = 'Re: ' + subject('').sub(/\A(?:\[[^\]]+\])?(?:\s*Re:)*\s*/i, '')
+      mail.mime_version = '1.0'
+      mail
+    end
+
+    def setup_forward( mail )
+      m = Mail.new(StringPort.new(''))
+      m.body = decoded
+      m.set_content_type 'message', 'rfc822'
+      m.encoding = encoding('7bit')
+      mail.parts.push m
+      # call encoded to reparse the message
+      mail.encoded
+      mail
+    end
+
+  #:startdoc:
+  end   # class Mail
+
+end   # module TMail
diff --git a/lib/vendor/tmail-1.2.7/tmail/loader.rb b/lib/vendor/tmail-1.2.7/tmail/loader.rb
new file mode 100644 (file)
index 0000000..6c0e251
--- /dev/null
@@ -0,0 +1,3 @@
+#:stopdoc:
+require 'tmail/mailbox'
+#:startdoc:
\ No newline at end of file
diff --git a/lib/vendor/tmail-1.2.7/tmail/mail.rb b/lib/vendor/tmail-1.2.7/tmail/mail.rb
new file mode 100644 (file)
index 0000000..7074ed9
--- /dev/null
@@ -0,0 +1,578 @@
+=begin rdoc
+
+= Mail class
+
+=end
+#--
+# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Note: Originally licensed under LGPL v2+. Using MIT license for Rails
+# with permission of Minero Aoki.
+#++
+
+
+require 'tmail/interface'
+require 'tmail/encode'
+require 'tmail/header'
+require 'tmail/port'
+require 'tmail/config'
+require 'tmail/utils'
+require 'tmail/attachments'
+require 'tmail/quoting'
+require 'socket'
+
+module TMail
+
+  # == Mail Class
+  # 
+  # Accessing a TMail object done via the TMail::Mail class.  As email can be fairly complex
+  # creatures, you will find a large amount of accessor and setter methods in this class!
+  # 
+  # Most of the below methods handle the header, in fact, what TMail does best is handle the
+  # header of the email object.  There are only a few methods that deal directly with the body
+  # of the email, such as base64_encode and base64_decode.
+  # 
+  # === Using TMail inside your code
+  # 
+  # The usual way is to install the gem (see the {README}[link:/README] on how to do this) and
+  # then put at the top of your class:
+  # 
+  #  require 'tmail'
+  # 
+  # You can then create a new TMail object in your code with:
+  # 
+  #  @email = TMail::Mail.new
+  # 
+  # Or if you have an email as a string, you can initialize a new TMail::Mail object and get it
+  # to parse that string for you like so:
+  # 
+  #  @email = TMail::Mail.parse(email_text)
+  # 
+  # You can also read a single email off the disk, for example:
+  # 
+  #  @email = TMail::Mail.load('filename.txt')
+  # 
+  # Also, you can read a mailbox (usual unix mbox format) and end up with an array of TMail
+  # objects by doing something like this:
+  # 
+  #  # Note, we pass true as the last variable to open the mailbox read only
+  #  mailbox = TMail::UNIXMbox.new("mailbox", nil, true)
+  #  @emails = []
+  #  mailbox.each_port { |m| @emails << TMail::Mail.new(m) }
+  #
+  class Mail
+
+    class << self
+      
+      # Opens an email that has been saved out as a file by itself.
+      # 
+      # This function will read a file non-destructively and then parse
+      # the contents and return a TMail::Mail object.
+      # 
+      # Does not handle multiple email mailboxes (like a unix mbox) for that
+      # use the TMail::UNIXMbox class.
+      # 
+      # Example:
+      #  mail = TMail::Mail.load('filename')
+      # 
+      def load( fname )
+        new(FilePort.new(fname))
+      end
+
+      alias load_from load
+      alias loadfrom load
+      
+      # Parses an email from the supplied string and returns a TMail::Mail
+      # object.
+      # 
+      # Example:
+      #  require 'rubygems'; require 'tmail'
+      #  email_string =<<HEREDOC
+      #  To: mikel@lindsaar.net
+      #  From: mikel@me.com
+      #  Subject: This is a short Email
+      #  
+      #  Hello there Mikel!
+      #  
+      #  HEREDOC
+      #  mail = TMail::Mail.parse(email_string)
+      #  #=> #<TMail::Mail port=#<TMail::StringPort:id=0xa30ac0> bodyport=nil>
+      #  mail.body
+      #  #=> "Hello there Mikel!\n\n"
+      def parse( str )
+        new(StringPort.new(str))
+      end
+
+    end
+
+    def initialize( port = nil, conf = DEFAULT_CONFIG ) #:nodoc:
+      @port = port || StringPort.new
+      @config = Config.to_config(conf)
+
+      @header      = {}
+      @body_port   = nil
+      @body_parsed = false
+      @epilogue    = ''
+      @parts       = []
+
+      @port.ropen {|f|
+          parse_header f
+          parse_body f unless @port.reproducible?
+      }
+    end
+
+    # Provides access to the port this email is using to hold it's data
+    # 
+    # Example:
+    #  mail = TMail::Mail.parse(email_string)
+    #  mail.port
+    #  #=> #<TMail::StringPort:id=0xa2c952>
+    attr_reader :port
+
+    def inspect
+      "\#<#{self.class} port=#{@port.inspect} bodyport=#{@body_port.inspect}>"
+    end
+
+    #
+    # to_s interfaces
+    #
+
+    public
+
+    include StrategyInterface
+
+    def write_back( eol = "\n", charset = 'e' )
+      parse_body
+      @port.wopen {|stream| encoded eol, charset, stream }
+    end
+
+    def accept( strategy )
+      with_multipart_encoding(strategy) {
+          ordered_each do |name, field|
+            next if field.empty?
+            strategy.header_name canonical(name)
+            field.accept strategy
+            strategy.puts
+          end
+          strategy.puts
+          body_port().ropen {|r|
+              strategy.write r.read
+          }
+      }
+    end
+
+    private
+
+    def canonical( name )
+      name.split(/-/).map {|s| s.capitalize }.join('-')
+    end
+
+    def with_multipart_encoding( strategy )
+      if parts().empty?    # DO NOT USE @parts
+        yield
+
+      else
+        bound = ::TMail.new_boundary
+        if @header.key? 'content-type'
+          @header['content-type'].params['boundary'] = bound
+        else
+          store 'Content-Type', %<multipart/mixed; boundary="#{bound}">
+        end
+
+        yield
+
+        parts().each do |tm|
+          strategy.puts
+          strategy.puts '--' + bound
+          tm.accept strategy
+        end
+        strategy.puts
+        strategy.puts '--' + bound + '--'
+        strategy.write epilogue()
+      end
+    end
+
+    ###
+    ### header
+    ###
+
+    public
+
+    ALLOW_MULTIPLE = {
+      'received'          => true,
+      'resent-date'       => true,
+      'resent-from'       => true,
+      'resent-sender'     => true,
+      'resent-to'         => true,
+      'resent-cc'         => true,
+      'resent-bcc'        => true,
+      'resent-message-id' => true,
+      'comments'          => true,
+      'keywords'          => true
+    }
+    USE_ARRAY = ALLOW_MULTIPLE
+
+    def header
+      @header.dup
+    end
+
+    # Returns a TMail::AddressHeader object of the field you are querying.
+    # Examples:
+    #  @mail['from']  #=> #<TMail::AddressHeader "mikel@test.com.au">
+    #  @mail['to']    #=> #<TMail::AddressHeader "mikel@test.com.au">
+    #
+    # You can get the string value of this by passing "to_s" to the query:
+    # Example:
+    #  @mail['to'].to_s #=> "mikel@test.com.au"
+    def []( key )
+      @header[key.downcase]
+    end
+
+    def sub_header(key, param)
+      (hdr = self[key]) ? hdr[param] : nil
+    end
+
+    alias fetch []
+
+    # Allows you to set or delete TMail header objects at will.
+    # Examples:
+    #  @mail = TMail::Mail.new
+    #  @mail['to'].to_s       # => 'mikel@test.com.au'
+    #  @mail['to'] = 'mikel@elsewhere.org'
+    #  @mail['to'].to_s       # => 'mikel@elsewhere.org'
+    #  @mail.encoded          # => "To: mikel@elsewhere.org\r\n\r\n"
+    #  @mail['to'] = nil
+    #  @mail['to'].to_s       # => nil
+    #  @mail.encoded          # => "\r\n"
+    # 
+    # Note: setting mail[] = nil actually deletes the header field in question from the object,
+    # it does not just set the value of the hash to nil
+    def []=( key, val )
+      dkey = key.downcase
+
+      if val.nil?
+        @header.delete dkey
+        return nil
+      end
+
+      case val
+      when String
+        header = new_hf(key, val)
+      when HeaderField
+        ;
+      when Array
+        ALLOW_MULTIPLE.include? dkey or
+                raise ArgumentError, "#{key}: Header must not be multiple"
+        @header[dkey] = val
+        return val
+      else
+        header = new_hf(key, val.to_s)
+      end
+      if ALLOW_MULTIPLE.include? dkey
+        (@header[dkey] ||= []).push header
+      else
+        @header[dkey] = header
+      end
+
+      val
+    end
+
+    alias store []=
+    
+    # Allows you to loop through each header in the TMail::Mail object in a block
+    # Example:
+    #   @mail['to'] = 'mikel@elsewhere.org'
+    #   @mail['from'] = 'me@me.com'
+    #   @mail.each_header { |k,v| puts "#{k} = #{v}" }
+    #   # => from = me@me.com
+    #   # => to = mikel@elsewhere.org
+    def each_header
+      @header.each do |key, val|
+        [val].flatten.each {|v| yield key, v }
+      end
+    end
+
+    alias each_pair each_header
+
+    def each_header_name( &block )
+      @header.each_key(&block)
+    end
+
+    alias each_key each_header_name
+
+    def each_field( &block )
+      @header.values.flatten.each(&block)
+    end
+
+    alias each_value each_field
+
+    FIELD_ORDER = %w(
+      return-path received
+      resent-date resent-from resent-sender resent-to
+      resent-cc resent-bcc resent-message-id
+      date from sender reply-to to cc bcc
+      message-id in-reply-to references
+      subject comments keywords
+      mime-version content-type content-transfer-encoding
+      content-disposition content-description
+    )
+
+    def ordered_each
+      list = @header.keys
+      FIELD_ORDER.each do |name|
+        if list.delete(name)
+          [@header[name]].flatten.each {|v| yield name, v }
+        end
+      end
+      list.each do |name|
+        [@header[name]].flatten.each {|v| yield name, v }
+      end
+    end
+
+    def clear
+      @header.clear
+    end
+
+    def delete( key )
+      @header.delete key.downcase
+    end
+
+    def delete_if
+      @header.delete_if do |key,val|
+        if Array === val
+          val.delete_if {|v| yield key, v }
+          val.empty?
+        else
+          yield key, val
+        end
+      end
+    end
+
+    def keys
+      @header.keys
+    end
+
+    def key?( key )
+      @header.key? key.downcase
+    end
+
+    def values_at( *args )
+      args.map {|k| @header[k.downcase] }.flatten
+    end
+
+    alias indexes values_at
+    alias indices values_at
+
+    private
+
+    def parse_header( f )
+      name = field = nil
+      unixfrom = nil
+
+      while line = f.gets
+        case line
+        when /\A[ \t]/             # continue from prev line
+          raise SyntaxError, 'mail is began by space' unless field
+          field << ' ' << line.strip
+
+        when /\A([^\: \t]+):\s*/   # new header line
+          add_hf name, field if field
+          name = $1
+          field = $' #.strip
+
+        when /\A\-*\s*\z/          # end of header
+          add_hf name, field if field
+          name = field = nil
+          break
+
+        when /\AFrom (\S+)/
+          unixfrom = $1
+
+        when /^charset=.*/
+
+        else
+          raise SyntaxError, "wrong mail header: '#{line.inspect}'"
+        end
+      end
+      add_hf name, field if name
+
+      if unixfrom
+        add_hf 'Return-Path', "<#{unixfrom}>" unless @header['return-path']
+      end
+    end
+
+    def add_hf( name, field )
+      key = name.downcase
+      field = new_hf(name, field)
+
+      if ALLOW_MULTIPLE.include? key
+        (@header[key] ||= []).push field
+      else
+        @header[key] = field
+      end
+    end
+
+    def new_hf( name, field )
+      HeaderField.new(name, field, @config)
+    end
+
+    ###
+    ### body
+    ###
+
+    public
+
+    def body_port
+      parse_body
+      @body_port
+    end
+
+    def each( &block )
+      body_port().ropen {|f| f.each(&block) }
+    end
+
+    def quoted_body
+      body_port.ropen {|f| return f.read }
+    end
+
+    def quoted_body= str
+      body_port.wopen { |f| f.write str }
+      str
+    end
+
+    def body=( str )
+      # Sets the body of the email to a new (encoded) string.
+      # 
+      # We also reparses the email if the body is ever reassigned, this is a performance hit, however when
+      # you assign the body, you usually want to be able to make sure that you can access the attachments etc.
+      # 
+      # Usage:
+      # 
+      #  mail.body = "Hello, this is\nthe body text"
+      #  # => "Hello, this is\nthe body"
+      #  mail.body
+      #  # => "Hello, this is\nthe body"
+      @body_parsed = false
+      parse_body(StringInput.new(str))
+      parse_body
+      @body_port.wopen {|f| f.write str }
+      str
+    end
+
+    alias preamble  quoted_body
+    alias preamble= quoted_body=
+
+    def epilogue
+      parse_body
+      @epilogue.dup
+    end
+
+    def epilogue=( str )
+      parse_body
+      @epilogue = str
+      str
+    end
+
+    def parts
+      parse_body
+      @parts
+    end
+    
+    def each_part( &block )
+      parts().each(&block)
+    end
+    
+    # Returns true if the content type of this part of the email is
+    # a disposition attachment
+    def disposition_is_attachment?
+      (self['content-disposition'] && self['content-disposition'].disposition == "attachment")
+    end
+
+    # Returns true if this part's content main type is text, else returns false.
+    # By main type is meant "text/plain" is text.  "text/html" is text
+    def content_type_is_text?
+      self.header['content-type'] && (self.header['content-type'].main_type != "text")
+    end
+
+    private
+
+    def parse_body( f = nil )
+      return if @body_parsed
+      if f
+        parse_body_0 f
+      else
+        @port.ropen {|f|
+            skip_header f
+            parse_body_0 f
+        }
+      end
+      @body_parsed = true
+    end
+
+    def skip_header( f )
+      while line = f.gets
+        return if /\A[\r\n]*\z/ === line
+      end
+    end
+
+    def parse_body_0( f )
+      if multipart?
+        read_multipart f
+      else
+        @body_port = @config.new_body_port(self)
+        @body_port.wopen {|w|
+            w.write f.read
+        }
+      end
+    end
+    
+    def read_multipart( src )
+      bound = @header['content-type'].params['boundary'] || ::TMail.new_boundary
+      is_sep = /\A--#{Regexp.quote bound}(?:--)?[ \t]*(?:\n|\r\n|\r)/
+      lastbound = "--#{bound}--"
+
+      ports = [ @config.new_preamble_port(self) ]
+      begin
+        f = ports.last.wopen
+        while line = src.gets
+          if is_sep === line
+            f.close
+            break if line.strip == lastbound
+            ports.push @config.new_part_port(self)
+            f = ports.last.wopen
+          else
+            f << line
+          end
+        end
+        @epilogue = (src.read || '')
+      ensure
+        f.close if f and not f.closed?
+      end
+
+      @body_port = ports.shift
+      @parts = ports.map {|p| self.class.new(p, @config) }
+    end
+
+  end   # class Mail
+
+end   # module TMail
diff --git a/lib/vendor/tmail-1.2.7/tmail/mailbox.rb b/lib/vendor/tmail-1.2.7/tmail/mailbox.rb
new file mode 100644 (file)
index 0000000..fe3e2c3
--- /dev/null
@@ -0,0 +1,496 @@
+=begin rdoc
+
+= Mailbox and Mbox interaction class
+
+=end
+#--
+# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Note: Originally licensed under LGPL v2+. Using MIT license for Rails
+# with permission of Minero Aoki.
+#++
+
+require 'tmail/port'
+require 'socket'
+require 'mutex_m'
+
+
+unless [].respond_to?(:sort_by)
+module Enumerable#:nodoc:
+  def sort_by
+    map {|i| [yield(i), i] }.sort {|a,b| a.first <=> b.first }.map {|i| i[1] }
+  end
+end
+end
+
+
+module TMail
+
+  class MhMailbox
+
+    PORT_CLASS = MhPort
+
+    def initialize( dir )
+      edir = File.expand_path(dir)
+      raise ArgumentError, "not directory: #{dir}"\
+                              unless FileTest.directory? edir
+      @dirname = edir
+      @last_file = nil
+      @last_atime = nil
+    end
+
+    def directory
+      @dirname
+    end
+
+    alias dirname directory
+
+    attr_accessor :last_atime
+
+    def inspect
+      "#<#{self.class} #{@dirname}>"
+    end
+
+    def close
+    end
+
+    def new_port
+      PORT_CLASS.new(next_file_name())
+    end
+
+    def each_port
+      mail_files().each do |path|
+        yield PORT_CLASS.new(path)
+      end
+      @last_atime = Time.now
+    end
+
+    alias each each_port
+
+    def reverse_each_port
+      mail_files().reverse_each do |path|
+        yield PORT_CLASS.new(path)
+      end
+      @last_atime = Time.now
+    end
+
+    alias reverse_each reverse_each_port
+
+    # old #each_mail returns Port
+    #def each_mail
+    #  each_port do |port|
+    #    yield Mail.new(port)
+    #  end
+    #end
+
+    def each_new_port( mtime = nil, &block )
+      mtime ||= @last_atime
+      return each_port(&block) unless mtime
+      return unless File.mtime(@dirname) >= mtime
+
+      mail_files().each do |path|
+        yield PORT_CLASS.new(path) if File.mtime(path) > mtime
+      end
+      @last_atime = Time.now
+    end
+
+    private
+
+    def mail_files
+      Dir.entries(@dirname)\
+              .select {|s| /\A\d+\z/ === s }\
+              .map {|s| s.to_i }\
+              .sort\
+              .map {|i| "#{@dirname}/#{i}" }\
+              .select {|path| FileTest.file? path }
+    end
+
+    def next_file_name
+      unless n = @last_file
+        n = 0
+        Dir.entries(@dirname)\
+                .select {|s| /\A\d+\z/ === s }\
+                .map {|s| s.to_i }.sort\
+        .each do |i|
+          next unless FileTest.file? "#{@dirname}/#{i}"
+          n = i
+        end
+      end
+      begin
+        n += 1
+      end while FileTest.exist? "#{@dirname}/#{n}"
+      @last_file = n
+
+      "#{@dirname}/#{n}"
+    end
+
+  end   # MhMailbox
+
+  MhLoader = MhMailbox
+
+
+  class UNIXMbox
+  
+    class << self
+      alias newobj new
+    end
+
+    # Creates a new mailbox object that you can iterate through to collect the
+    # emails from with "each_port".  
+    # 
+    # You need to pass it a filename of a unix mailbox format file, the format of this
+    # file can be researched at this page at {wikipedia}[link:http://en.wikipedia.org/wiki/Mbox]
+    # 
+    # ==== Parameters
+    # 
+    # +filename+: The filename of the mailbox you want to open
+    # 
+    # +tmpdir+: Can be set to override TMail using the system environment's temp dir. TMail will first
+    # use the temp dir specified by you (if any) or then the temp dir specified in the Environment's TEMP
+    # value then the value in the Environment's TMP value or failing all of the above, '/tmp'
+    # 
+    # +readonly+: If set to false, each email you take from the mail box will be removed from the mailbox.
+    # default is *false* - ie, it *WILL* truncate your mailbox file to ZERO once it has read the emails out.
+    # 
+    # ==== Options:
+    # 
+    # None
+    # 
+    # ==== Examples:
+    # 
+    #  # First show using readonly true:
+    # 
+    #  require 'ftools'
+    #  File.size("../test/fixtures/mailbox")
+    #  #=> 20426
+    #
+    #  mailbox = TMail::UNIXMbox.new("../test/fixtures/mailbox", nil, true) 
+    #  #=> #<TMail::UNIXMbox:0x14a2aa8 @readonly=true.....>
+    #
+    #  mailbox.each_port do |port| 
+    #    mail = TMail::Mail.new(port)
+    #    puts mail.subject
+    #  end
+    #  #Testing mailbox 1
+    #  #Testing mailbox 2
+    #  #Testing mailbox 3
+    #  #Testing mailbox 4
+    #  require 'ftools'
+    #  File.size?("../test/fixtures/mailbox")
+    #  #=> 20426
+    # 
+    #  # Now show with readonly set to the default false
+    # 
+    #  mailbox = TMail::UNIXMbox.new("../test/fixtures/mailbox") 
+    #  #=> #<TMail::UNIXMbox:0x14a2aa8 @readonly=false.....>
+    #
+    #  mailbox.each_port do |port| 
+    #    mail = TMail::Mail.new(port)
+    #    puts mail.subject
+    #  end
+    #  #Testing mailbox 1
+    #  #Testing mailbox 2
+    #  #Testing mailbox 3
+    #  #Testing mailbox 4
+    # 
+    #  File.size?("../test/fixtures/mailbox")
+    #  #=> nil
+    def UNIXMbox.new( filename, tmpdir = nil, readonly = false )
+      tmpdir = ENV['TEMP'] || ENV['TMP'] || '/tmp'
+      newobj(filename, "#{tmpdir}/ruby_tmail_#{$$}_#{rand()}", readonly, false)
+    end
+
+    def UNIXMbox.lock( fname )
+      begin
+        f = File.open(fname, 'r+')
+        f.flock File::LOCK_EX
+        yield f
+      ensure
+        f.flock File::LOCK_UN
+        f.close if f and not f.closed?
+      end
+    end
+
+    def UNIXMbox.static_new( fname, dir, readonly = false )
+      newobj(fname, dir, readonly, true)
+    end
+
+    def initialize( fname, mhdir, readonly, static )
+      @filename = fname
+      @readonly = readonly
+      @closed = false
+
+      Dir.mkdir mhdir
+      @real = MhMailbox.new(mhdir)
+      @finalizer = UNIXMbox.mkfinal(@real, @filename, !@readonly, !static)
+      ObjectSpace.define_finalizer self, @finalizer
+    end
+
+    def UNIXMbox.mkfinal( mh, mboxfile, writeback_p, cleanup_p )
+      lambda {
+          if writeback_p
+            lock(mboxfile) {|f|
+                mh.each_port do |port|
+                  f.puts create_from_line(port)
+                  port.ropen {|r|
+                      f.puts r.read
+                  }
+                end
+            }
+          end
+          if cleanup_p
+            Dir.foreach(mh.dirname) do |fname|
+              next if /\A\.\.?\z/ === fname
+              File.unlink "#{mh.dirname}/#{fname}"
+            end
+            Dir.rmdir mh.dirname
+          end
+      }
+    end
+
+    # make _From line
+    def UNIXMbox.create_from_line( port )
+      sprintf 'From %s %s',
+              fromaddr(), TextUtils.time2str(File.mtime(port.filename))
+    end
+
+    def UNIXMbox.fromaddr(port)
+      h = HeaderField.new_from_port(port, 'Return-Path') ||
+      HeaderField.new_from_port(port, 'From') ||
+      HeaderField.new_from_port(port, 'EnvelopeSender') or return 'nobody'
+      a = h.addrs[0] or return 'nobody'
+      a.spec
+    end
+
+    def close
+      return if @closed
+
+      ObjectSpace.undefine_finalizer self
+      @finalizer.call
+      @finalizer = nil
+      @real = nil
+      @closed = true
+      @updated = nil
+    end
+
+    def each_port( &block )
+      close_check
+      update
+      @real.each_port(&block)
+    end
+
+    alias each each_port
+
+    def reverse_each_port( &block )
+      close_check
+      update
+      @real.reverse_each_port(&block)
+    end
+
+    alias reverse_each reverse_each_port
+
+    # old #each_mail returns Port
+    #def each_mail( &block )
+    #  each_port do |port|
+    #    yield Mail.new(port)
+    #  end
+    #end
+
+    def each_new_port( mtime = nil )
+      close_check
+      update
+      @real.each_new_port(mtime) {|p| yield p }
+    end
+
+    def new_port
+      close_check
+      @real.new_port
+    end
+
+    private
+
+    def close_check
+      @closed and raise ArgumentError, 'accessing already closed mbox'
+    end
+
+    def update
+      return if FileTest.zero?(@filename)
+      return if @updated and File.mtime(@filename) < @updated
+      w = nil
+      port = nil
+      time = nil
+      UNIXMbox.lock(@filename) {|f|
+          begin
+            f.each do |line|
+              if /\AFrom / === line
+                w.close if w
+                File.utime time, time, port.filename if time
+
+                port = @real.new_port
+                w = port.wopen
+                time = fromline2time(line)
+              else
+                w.print line if w
+              end
+            end
+          ensure
+            if w and not w.closed?
+              w.close
+              File.utime time, time, port.filename if time
+            end
+          end
+          f.truncate(0) unless @readonly
+          @updated = Time.now
+      }
+    end
+
+    def fromline2time( line )
+      m = /\AFrom \S+ \w+ (\w+) (\d+) (\d+):(\d+):(\d+) (\d+)/.match(line) or return nil
+      Time.local(m[6].to_i, m[1], m[2].to_i, m[3].to_i, m[4].to_i, m[5].to_i)
+    rescue
+      nil
+    end
+
+  end   # UNIXMbox
+
+  MboxLoader = UNIXMbox
+
+
+  class Maildir
+
+    extend Mutex_m
+
+    PORT_CLASS = MaildirPort
+
+    @seq = 0
+    def Maildir.unique_number
+      synchronize {
+          @seq += 1
+          return @seq
+      }
+    end
+
+    def initialize( dir = nil )
+      @dirname = dir || ENV['MAILDIR']
+      raise ArgumentError, "not directory: #{@dirname}"\
+                              unless FileTest.directory? @dirname
+      @new = "#{@dirname}/new"
+      @tmp = "#{@dirname}/tmp"
+      @cur = "#{@dirname}/cur"
+    end
+
+    def directory
+      @dirname
+    end
+
+    def inspect
+      "#<#{self.class} #{@dirname}>"
+    end
+
+    def close
+    end
+
+    def each_port
+      mail_files(@cur).each do |path|
+        yield PORT_CLASS.new(path)
+      end
+    end
+
+    alias each each_port
+
+    def reverse_each_port
+      mail_files(@cur).reverse_each do |path|
+        yield PORT_CLASS.new(path)
+      end
+    end
+
+    alias reverse_each reverse_each_port
+
+    def new_port
+      fname = nil
+      tmpfname = nil
+      newfname = nil
+
+      begin
+        fname = "#{Time.now.to_i}.#{$$}_#{Maildir.unique_number}.#{Socket.gethostname}"
+        
+        tmpfname = "#{@tmp}/#{fname}"
+        newfname = "#{@new}/#{fname}"
+      end while FileTest.exist? tmpfname
+
+      if block_given?
+        File.open(tmpfname, 'w') {|f| yield f }
+        File.rename tmpfname, newfname
+        PORT_CLASS.new(newfname)
+      else
+        File.open(tmpfname, 'w') {|f| f.write "\n\n" }
+        PORT_CLASS.new(tmpfname)
+      end
+    end
+
+    def each_new_port
+      mail_files(@new).each do |path|
+        dest = @cur + '/' + File.basename(path)
+        File.rename path, dest
+        yield PORT_CLASS.new(dest)
+      end
+
+      check_tmp
+    end
+
+    TOO_OLD = 60 * 60 * 36   # 36 hour
+
+    def check_tmp
+      old = Time.now.to_i - TOO_OLD
+      
+      each_filename(@tmp) do |full, fname|
+        if FileTest.file? full and
+           File.stat(full).mtime.to_i < old
+          File.unlink full
+        end
+      end
+    end
+
+    private
+
+    def mail_files( dir )
+      Dir.entries(dir)\
+              .select {|s| s[0] != ?. }\
+              .sort_by {|s| s.slice(/\A\d+/).to_i }\
+              .map {|s| "#{dir}/#{s}" }\
+              .select {|path| FileTest.file? path }
+    end
+
+    def each_filename( dir )
+      Dir.foreach(dir) do |fname|
+        path = "#{dir}/#{fname}"
+        if fname[0] != ?. and FileTest.file? path
+          yield path, fname
+        end
+      end
+    end
+    
+  end   # Maildir
+
+  MaildirLoader = Maildir
+
+end   # module TMail
diff --git a/lib/vendor/tmail-1.2.7/tmail/main.rb b/lib/vendor/tmail-1.2.7/tmail/main.rb
new file mode 100644 (file)
index 0000000..e527727
--- /dev/null
@@ -0,0 +1,6 @@
+#:stopdoc:
+require 'tmail/version'
+require 'tmail/mail'
+require 'tmail/mailbox'
+require 'tmail/core_extensions'
+#:startdoc:
\ No newline at end of file
diff --git a/lib/vendor/tmail-1.2.7/tmail/mbox.rb b/lib/vendor/tmail-1.2.7/tmail/mbox.rb
new file mode 100644 (file)
index 0000000..6c0e251
--- /dev/null
@@ -0,0 +1,3 @@
+#:stopdoc:
+require 'tmail/mailbox'
+#:startdoc:
\ No newline at end of file
diff --git a/lib/vendor/tmail-1.2.7/tmail/net.rb b/lib/vendor/tmail-1.2.7/tmail/net.rb
new file mode 100644 (file)
index 0000000..1d87c30
--- /dev/null
@@ -0,0 +1,250 @@
+#--
+# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Note: Originally licensed under LGPL v2+. Using MIT license for Rails
+# with permission of Minero Aoki.
+#++
+
+#:stopdoc:
+require 'nkf'
+#:startdoc:
+
+module TMail
+
+  class Mail
+    
+    def send_to( smtp )
+      do_send_to(smtp) do
+        ready_to_send
+      end
+    end
+
+    def send_text_to( smtp )
+      do_send_to(smtp) do
+        ready_to_send
+        mime_encode
+      end
+    end
+
+    def do_send_to( smtp )
+      from = from_address or raise ArgumentError, 'no from address'
+      (dests = destinations).empty? and raise ArgumentError, 'no receipient'
+      yield
+      send_to_0 smtp, from, dests
+    end
+    private :do_send_to
+
+    def send_to_0( smtp, from, to )
+      smtp.ready(from, to) do |f|
+        encoded "\r\n", 'j', f, ''
+      end
+    end
+
+    def ready_to_send
+      delete_no_send_fields
+      add_message_id
+      add_date
+    end
+
+    NOSEND_FIELDS = %w(
+      received
+      bcc
+    )
+
+    def delete_no_send_fields
+      NOSEND_FIELDS.each do |nm|
+        delete nm
+      end
+      delete_if {|n,v| v.empty? }
+    end
+
+    def add_message_id( fqdn = nil )
+      unless @message_id_enforced
+        self.message_id = ::TMail::new_message_id(fqdn)
+      end
+    end
+
+    def add_date
+      self.date = Time.now
+    end
+
+    def mime_encode
+      if parts.empty?
+        mime_encode_singlepart
+      else
+        mime_encode_multipart true
+      end
+    end
+
+    def mime_encode_singlepart
+      self.mime_version = '1.0'
+      b = body
+      if NKF.guess(b) != NKF::BINARY
+        mime_encode_text b
+      else
+        mime_encode_binary b
+      end
+    end
+
+    def mime_encode_text( body )
+      self.body = NKF.nkf('-j -m0', body)
+      self.set_content_type 'text', 'plain', {'charset' => 'iso-2022-jp'}
+      self.encoding = '7bit'
+    end
+
+    def mime_encode_binary( body )
+      self.body = [body].pack('m')
+      self.set_content_type 'application', 'octet-stream'
+      self.encoding = 'Base64'
+    end
+
+    def mime_encode_multipart( top = true )
+      self.mime_version = '1.0' if top
+      self.set_content_type 'multipart', 'mixed'
+      e = encoding(nil)
+      if e and not /\A(?:7bit|8bit|binary)\z/i === e
+        raise ArgumentError,
+              'using C.T.Encoding with multipart mail is not permitted'
+      end
+    end
+  
+  end
+
+  #:stopdoc:
+  class DeleteFields
+
+    NOSEND_FIELDS = %w(
+      received
+      bcc
+    )
+
+    def initialize( nosend = nil, delempty = true )
+      @no_send_fields = nosend || NOSEND_FIELDS.dup
+      @delete_empty_fields = delempty
+    end
+
+    attr :no_send_fields
+    attr :delete_empty_fields, true
+
+    def exec( mail )
+      @no_send_fields.each do |nm|
+        delete nm
+      end
+      delete_if {|n,v| v.empty? } if @delete_empty_fields
+    end
+  
+  end
+  #:startdoc:
+
+  #:stopdoc:
+  class AddMessageId
+
+    def initialize( fqdn = nil )
+      @fqdn = fqdn
+    end
+
+    attr :fqdn, true
+
+    def exec( mail )
+      mail.message_id = ::TMail::new_msgid(@fqdn)
+    end
+  
+  end
+  #:startdoc:
+
+  #:stopdoc:
+  class AddDate
+
+    def exec( mail )
+      mail.date = Time.now
+    end
+  
+  end
+  #:startdoc:
+
+  #:stopdoc:
+  class MimeEncodeAuto
+
+    def initialize( s = nil, m = nil )
+      @singlepart_composer = s || MimeEncodeSingle.new
+      @multipart_composer  = m || MimeEncodeMulti.new
+    end
+
+    attr :singlepart_composer
+    attr :multipart_composer
+
+    def exec( mail )
+      if mail._builtin_multipart?
+      then @multipart_composer
+      else @singlepart_composer end.exec mail
+    end
+  
+  end
+  #:startdoc:
+  
+  #:stopdoc:
+  class MimeEncodeSingle
+
+    def exec( mail )
+      mail.mime_version = '1.0'
+      b = mail.body
+      if NKF.guess(b) != NKF::BINARY
+        on_text b
+      else
+        on_binary b
+      end
+    end
+
+    def on_text( body )
+      mail.body = NKF.nkf('-j -m0', body)
+      mail.set_content_type 'text', 'plain', {'charset' => 'iso-2022-jp'}
+      mail.encoding = '7bit'
+    end
+
+    def on_binary( body )
+      mail.body = [body].pack('m')
+      mail.set_content_type 'application', 'octet-stream'
+      mail.encoding = 'Base64'
+    end
+  
+  end
+  #:startdoc:
+  
+  #:stopdoc:
+  class MimeEncodeMulti
+
+    def exec( mail, top = true )
+      mail.mime_version = '1.0' if top
+      mail.set_content_type 'multipart', 'mixed'
+      e = encoding(nil)
+      if e and not /\A(?:7bit|8bit|binary)\z/i === e
+        raise ArgumentError,
+              'using C.T.Encoding with multipart mail is not permitted'
+      end
+      mail.parts.each do |m|
+        exec m, false if m._builtin_multipart?
+      end
+    end
+
+  end
+  #:startdoc:
+end   # module TMail
diff --git a/lib/vendor/tmail-1.2.7/tmail/obsolete.rb b/lib/vendor/tmail-1.2.7/tmail/obsolete.rb
new file mode 100644 (file)
index 0000000..22b0a12
--- /dev/null
@@ -0,0 +1,132 @@
+=begin rdoc
+
+= Obsolete methods that are depriciated
+
+If you really want to see them, go to lib/tmail/obsolete.rb and view to your
+heart's content.
+
+=end
+#--
+# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Note: Originally licensed under LGPL v2+. Using MIT license for Rails
+# with permission of Minero Aoki.
+#++
+#:stopdoc:
+module TMail #:nodoc:
+
+  class Mail
+    alias include? key?
+    alias has_key? key?
+
+    def values
+      ret = []
+      each_field {|v| ret.push v }
+      ret
+    end
+
+    def value?( val )
+      HeaderField === val or return false
+
+      [ @header[val.name.downcase] ].flatten.include? val
+    end
+
+    alias has_value? value?
+  end
+
+  class Mail
+    def from_addr( default = nil )
+      addr, = from_addrs(nil)
+      addr || default
+    end
+
+    def from_address( default = nil )
+      if a = from_addr(nil)
+        a.spec
+      else
+        default
+      end
+    end
+
+    alias from_address= from_addrs=
+
+    def from_phrase( default = nil )
+      if a = from_addr(nil)
+        a.phrase
+      else
+        default
+      end
+    end
+
+    alias msgid  message_id
+    alias msgid= message_id=
+
+    alias each_dest each_destination
+  end
+
+  class Address
+    alias route routes
+    alias addr spec
+
+    def spec=( str ) 
+      @local, @domain = str.split(/@/,2).map {|s| s.split(/\./) }
+    end
+
+    alias addr= spec=
+    alias address= spec=
+  end
+
+  class MhMailbox
+    alias new_mail new_port
+    alias each_mail each_port
+    alias each_newmail each_new_port
+  end
+  class UNIXMbox
+    alias new_mail new_port
+    alias each_mail each_port
+    alias each_newmail each_new_port
+  end
+  class Maildir
+    alias new_mail new_port
+    alias each_mail each_port
+    alias each_newmail each_new_port
+  end
+
+  extend TextUtils
+
+  class << self
+    alias msgid?    message_id?
+    alias boundary  new_boundary
+    alias msgid     new_message_id
+    alias new_msgid new_message_id
+  end
+
+  def Mail.boundary
+    ::TMail.new_boundary
+  end
+
+  def Mail.msgid
+    ::TMail.new_message_id
+  end
+
+end   # module TMail
+#:startdoc:
\ No newline at end of file
diff --git a/lib/vendor/tmail-1.2.7/tmail/parser.rb b/lib/vendor/tmail-1.2.7/tmail/parser.rb
new file mode 100644 (file)
index 0000000..1d4dcc2
--- /dev/null
@@ -0,0 +1,1060 @@
+#
+# DO NOT MODIFY!!!!
+# This file is automatically generated by racc 1.4.5
+# from racc grammer file "lib/tmail/parser.y".
+#
+
+require 'racc/parser'
+
+
+#
+# parser.rb
+#
+# Copyright (c) 1998-2007 Minero Aoki
+#
+# This program is free software.
+# You can distribute/modify this program under the terms of
+# the GNU Lesser General Public License version 2.1.
+#
+
+require 'tmail/scanner'
+require 'tmail/utils'
+
+
+module TMail
+
+  class Parser < Racc::Parser
+
+module_eval <<'..end lib/tmail/parser.y modeval..id2dd1c7d21d', 'lib/tmail/parser.y', 340
+
+  include TextUtils
+
+  def self.parse( ident, str, cmt = nil )
+    str = special_quote_address(str) if ident.to_s =~ /M?ADDRESS/
+    new.parse(ident, str, cmt)
+  end
+
+  def self.special_quote_address(str) #:nodoc:
+    # Takes a string which is an address and adds quotation marks to special
+    # edge case methods that the RACC parser can not handle.
+    #
+    # Right now just handles two edge cases:
+    #
+    # Full stop as the last character of the display name:
+    #   Mikel L. <mikel@me.com>
+    # Returns:
+    #   "Mikel L." <mikel@me.com>
+    #
+    # Unquoted @ symbol in the display name:
+    #   mikel@me.com <mikel@me.com>
+    # Returns:
+    #   "mikel@me.com" <mikel@me.com>
+    #
+    # Any other address not matching these patterns just gets returned as is.
+    case
+    # This handles the missing "" in an older version of Apple Mail.app
+    # around the display name when the display name contains a '@'
+    # like 'mikel@me.com <mikel@me.com>'
+    # Just quotes it to: '"mikel@me.com" <mikel@me.com>'
+    when str =~ /\A([^"].+@.+[^"])\s(<.*?>)\Z/
+      return "\"#{$1}\" #{$2}"
+    # This handles cases where 'Mikel A. <mikel@me.com>' which is a trailing
+    # full stop before the address section.  Just quotes it to
+    # '"Mikel A." <mikel@me.com>'
+    when str =~ /\A(.*?\.)\s(<.*?>)\s*\Z/
+      return "\"#{$1}\" #{$2}"
+    else
+      str
+    end
+  end
+
+  MAILP_DEBUG = false
+
+  def initialize
+    self.debug = MAILP_DEBUG
+  end
+
+  def debug=( flag )
+    @yydebug = flag && Racc_debug_parser
+    @scanner_debug = flag
+  end
+
+  def debug
+    @yydebug
+  end
+
+  def parse( ident, str, comments = nil )
+    @scanner = Scanner.new(str, ident, comments)
+    @scanner.debug = @scanner_debug
+    @first = [ident, ident]
+    result = yyparse(self, :parse_in)
+    comments.map! {|c| to_kcode(c) } if comments
+    result
+  end
+
+  private
+
+  def parse_in( &block )
+    yield @first
+    @scanner.scan(&block)
+  end
+  
+  def on_error( t, val, vstack )
+    raise TMail::SyntaxError, "parse error on token #{racc_token2str t}"
+  end
+
+..end lib/tmail/parser.y modeval..id2dd1c7d21d
+
+##### racc 1.4.5 generates ###
+
+racc_reduce_table = [
+ 0, 0, :racc_error,
+ 2, 35, :_reduce_1,
+ 2, 35, :_reduce_2,
+ 2, 35, :_reduce_3,
+ 2, 35, :_reduce_4,
+ 2, 35, :_reduce_5,
+ 2, 35, :_reduce_6,
+ 2, 35, :_reduce_7,
+ 2, 35, :_reduce_8,
+ 2, 35, :_reduce_9,
+ 2, 35, :_reduce_10,
+ 2, 35, :_reduce_11,
+ 2, 35, :_reduce_12,
+ 6, 36, :_reduce_13,
+ 0, 48, :_reduce_none,
+ 2, 48, :_reduce_none,
+ 3, 49, :_reduce_16,
+ 5, 49, :_reduce_17,
+ 1, 50, :_reduce_18,
+ 7, 37, :_reduce_19,
+ 0, 51, :_reduce_none,
+ 2, 51, :_reduce_21,
+ 0, 52, :_reduce_none,
+ 2, 52, :_reduce_23,
+ 1, 58, :_reduce_24,
+ 3, 58, :_reduce_25,
+ 2, 58, :_reduce_26,
+ 0, 53, :_reduce_none,
+ 2, 53, :_reduce_28,
+ 0, 54, :_reduce_29,
+ 3, 54, :_reduce_30,
+ 0, 55, :_reduce_none,
+ 2, 55, :_reduce_32,
+ 2, 55, :_reduce_33,
+ 0, 56, :_reduce_none,
+ 2, 56, :_reduce_35,
+ 1, 61, :_reduce_36,
+ 1, 61, :_reduce_37,
+ 0, 57, :_reduce_none,
+ 2, 57, :_reduce_39,
+ 1, 38, :_reduce_none,
+ 1, 38, :_reduce_none,
+ 3, 38, :_reduce_none,
+ 1, 46, :_reduce_none,
+ 1, 46, :_reduce_none,
+ 1, 46, :_reduce_none,
+ 1, 39, :_reduce_none,
+ 2, 39, :_reduce_47,
+ 1, 64, :_reduce_48,
+ 3, 64, :_reduce_49,
+ 1, 68, :_reduce_none,
+ 1, 68, :_reduce_none,
+ 1, 69, :_reduce_52,
+ 3, 69, :_reduce_53,
+ 1, 47, :_reduce_none,
+ 1, 47, :_reduce_none,
+ 2, 47, :_reduce_56,
+ 2, 67, :_reduce_none,
+ 3, 65, :_reduce_58,
+ 2, 65, :_reduce_59,
+ 1, 70, :_reduce_60,
+ 2, 70, :_reduce_61,
+ 4, 62, :_reduce_62,
+ 3, 62, :_reduce_63,
+ 2, 72, :_reduce_none,
+ 2, 73, :_reduce_65,
+ 4, 73, :_reduce_66,
+ 3, 63, :_reduce_67,
+ 1, 63, :_reduce_68,
+ 1, 74, :_reduce_none,
+ 2, 74, :_reduce_70,
+ 1, 71, :_reduce_71,
+ 3, 71, :_reduce_72,
+ 1, 59, :_reduce_73,
+ 3, 59, :_reduce_74,
+ 1, 76, :_reduce_75,
+ 2, 76, :_reduce_76,
+ 1, 75, :_reduce_none,
+ 1, 75, :_reduce_none,
+ 1, 75, :_reduce_none,
+ 1, 77, :_reduce_none,
+ 1, 77, :_reduce_none,
+ 1, 77, :_reduce_none,
+ 1, 66, :_reduce_none,
+ 2, 66, :_reduce_none,
+ 3, 60, :_reduce_85,
+ 1, 40, :_reduce_86,
+ 3, 40, :_reduce_87,
+ 1, 79, :_reduce_none,
+ 2, 79, :_reduce_89,
+ 1, 41, :_reduce_90,
+ 2, 41, :_reduce_91,
+ 3, 42, :_reduce_92,
+ 5, 43, :_reduce_93,
+ 3, 43, :_reduce_94,
+ 0, 80, :_reduce_95,
+ 5, 80, :_reduce_96,
+ 5, 80, :_reduce_97,
+ 1, 44, :_reduce_98,
+ 3, 45, :_reduce_99,
+ 0, 81, :_reduce_none,
+ 1, 81, :_reduce_none,
+ 1, 78, :_reduce_none,
+ 1, 78, :_reduce_none,
+ 1, 78, :_reduce_none,
+ 1, 78, :_reduce_none,
+ 1, 78, :_reduce_none,
+ 1, 78, :_reduce_none,
+ 1, 78, :_reduce_none ]
+
+racc_reduce_n = 109
+
+racc_shift_n = 167
+
+racc_action_table = [
+   -69,   130,   -70,    23,    25,   153,    94,    29,    31,   142,
+   143,    16,    17,    20,    22,    98,   -69,   154,   -70,    32,
+   -69,   107,   -70,   145,   146,    78,   -69,    91,   -70,    75,
+   -70,    23,    25,   120,    88,    29,    31,   105,   106,    16,
+    17,    20,    22,    81,    27,    23,    25,    32,   112,    29,
+    31,    96,    80,    16,    17,    20,    22,   117,    27,    23,
+    25,    32,    79,    29,    31,    78,   123,    16,    17,    20,
+    22,   100,    27,    23,    25,    32,   125,    29,    31,   113,
+   115,    16,    17,    20,    22,   126,    23,    25,   101,    32,
+    29,    31,    91,   128,    16,    17,    20,    22,   129,    27,
+    23,    25,    32,   101,    29,    31,   101,    75,    16,    17,
+    20,    22,    77,    52,    23,    25,    32,    65,    29,    31,
+   133,    78,    16,    17,    20,    22,    62,    23,    25,   136,
+    32,    29,    31,    60,    44,    16,    17,    20,    22,   139,
+    23,    25,   101,    32,    29,    31,   101,   100,    16,    17,
+    20,    22,   100,    27,    23,    25,    32,   101,    29,    31,
+   147,   148,    16,    17,    20,    22,   151,    23,    25,   152,
+    32,    29,    31,    74,    42,    16,    17,    20,    22,   156,
+   158,    92,    40,    32,    23,    25,    15,    68,    29,    31,
+   163,    40,    16,    17,    20,    22,   165,    27,    23,    25,
+    32,   166,    29,    31,   nil,   nil,    16,    17,    20,    22,
+   nil,    27,    23,    25,    32,   nil,    29,    31,   nil,   nil,
+    16,    17,    20,    22,   nil,    23,    25,   nil,    32,    29,
+    31,   nil,   nil,    16,    17,    20,    22,   nil,    23,    25,
+   nil,    32,    29,    31,   nil,   nil,    16,    17,    20,    22,
+   nil,    23,    25,   nil,    32,    29,    31,   nil,   nil,    16,
+    17,    20,    22,   nil,    27,   nil,   nil,    32,    23,    25,
+   120,   nil,    29,    31,   nil,   nil,    16,    17,    20,    22,
+   nil,    27,    23,    25,    32,   nil,    29,    31,   nil,   nil,
+    16,    17,    20,    22,   nil,    23,    25,   109,    32,    29,
+    31,    74,   nil,    16,    17,    20,    22,   nil,    84,    25,
+   nil,    32,    29,    31,   nil,    87,    16,    17,    20,    22,
+    84,    25,   nil,   109,    29,    31,   nil,    87,    16,    17,
+    20,    22,    84,    25,   nil,   nil,    29,    31,   nil,    87,
+    16,    17,    20,    22,    84,    25,   nil,   nil,    29,    31,
+   nil,    87,    16,    17,    20,    22,    84,    25,   nil,   nil,
+    29,    31,   nil,    87,    16,    17,    20,    22,    84,    25,
+   nil,   nil,    29,    31,   nil,    87,    16,    17,    20,    22,
+     4,     6,     7,     8,     9,    10,    11,    12,    13,     1,
+     2,     3,    84,    25,   nil,   nil,    29,    31,   nil,    87,
+    16,    17,    20,    22 ]
+
+racc_action_check = [
+    28,   112,    75,    71,    71,   143,    56,    71,    71,   134,
+   134,    71,    71,    71,    71,    62,    28,   143,    75,    71,
+    28,    73,    75,   136,   136,    51,    28,    50,    75,    28,
+    75,   127,   127,   127,    45,   127,   127,    72,    72,   127,
+   127,   127,   127,    42,   127,     3,     3,   127,    80,     3,
+     3,    60,    41,     3,     3,     3,     3,    89,     3,   151,
+   151,     3,    40,   151,   151,    36,    96,   151,   151,   151,
+   151,    97,   151,    55,    55,   151,    98,    55,    55,    86,
+    86,    55,    55,    55,    55,   100,     7,     7,    86,    55,
+     7,     7,   102,   104,     7,     7,     7,     7,   105,     7,
+     8,     8,     7,   108,     8,     8,   111,    70,     8,     8,
+     8,     8,    33,     8,     9,     9,     8,    13,     9,     9,
+   117,   121,     9,     9,     9,     9,    12,    10,    10,   126,
+     9,    10,    10,    11,     6,    10,    10,    10,    10,   130,
+     2,     2,   131,    10,     2,     2,    67,   135,     2,     2,
+     2,     2,    66,     2,   122,   122,     2,   138,   122,   122,
+   139,   140,   122,   122,   122,   122,   141,    52,    52,   142,
+   122,    52,    52,    52,     5,    52,    52,    52,    52,   147,
+   150,    52,     4,    52,    26,    26,     1,    26,    26,    26,
+   156,   158,    26,    26,    26,    26,   162,    26,    68,    68,
+    26,   163,    68,    68,   nil,   nil,    68,    68,    68,    68,
+   nil,    68,    59,    59,    68,   nil,    59,    59,   nil,   nil,
+    59,    59,    59,    59,   nil,   154,   154,   nil,    59,   154,
+   154,   nil,   nil,   154,   154,   154,   154,   nil,    94,    94,
+   nil,   154,    94,    94,   nil,   nil,    94,    94,    94,    94,
+   nil,    38,    38,   nil,    94,    38,    38,   nil,   nil,    38,
+    38,    38,    38,   nil,    38,   nil,   nil,    38,    90,    90,
+    90,   nil,    90,    90,   nil,   nil,    90,    90,    90,    90,
+   nil,    90,    76,    76,    90,   nil,    76,    76,   nil,   nil,
+    76,    76,    76,    76,   nil,    27,    27,    76,    76,    27,
+    27,    27,   nil,    27,    27,    27,    27,   nil,   114,   114,
+   nil,    27,   114,   114,   nil,   114,   114,   114,   114,   114,
+    44,    44,   nil,   114,    44,    44,   nil,    44,    44,    44,
+    44,    44,    74,    74,   nil,   nil,    74,    74,   nil,    74,
+    74,    74,    74,    74,   113,   113,   nil,   nil,   113,   113,
+   nil,   113,   113,   113,   113,   113,   129,   129,   nil,   nil,
+   129,   129,   nil,   129,   129,   129,   129,   129,    88,    88,
+   nil,   nil,    88,    88,   nil,    88,    88,    88,    88,    88,
+     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+     0,     0,    77,    77,   nil,   nil,    77,    77,   nil,    77,
+    77,    77,    77,    77 ]
+
+racc_action_pointer = [
+   378,   155,   126,    31,   167,   174,   116,    72,    86,   100,
+   113,   119,    95,    86,   nil,   nil,   nil,   nil,   nil,   nil,
+   nil,   nil,   nil,   nil,   nil,   nil,   170,   281,     0,   nil,
+   nil,   nil,   nil,    92,   nil,   nil,    39,   nil,   237,   nil,
+    46,    38,    43,   nil,   306,    15,   nil,   nil,   nil,   nil,
+    11,    -1,   153,   nil,   nil,    59,   -10,   nil,   nil,   198,
+    22,   nil,   -17,   nil,   nil,   nil,   126,   117,   184,   nil,
+    78,   -11,    21,    -7,   318,     2,   268,   378,   nil,   nil,
+    33,   nil,   nil,   nil,   nil,   nil,    59,   nil,   354,    35,
+   254,   nil,   nil,   nil,   224,   nil,    52,    45,    45,   nil,
+    54,   nil,    76,   nil,    65,    78,   nil,   nil,    74,   nil,
+   nil,    77,   -13,   330,   294,   nil,   nil,   105,   nil,   nil,
+   nil,    95,   140,   nil,   nil,   nil,    96,    17,   nil,   342,
+   125,   113,   nil,   nil,   -14,   121,    -7,   nil,   128,   143,
+   146,   141,   154,   -10,   nil,   nil,   nil,   165,   nil,   nil,
+   154,    45,   nil,   nil,   211,   nil,   173,   nil,   176,   nil,
+   nil,   nil,   168,   187,   nil,   nil,   nil ]
+
+racc_action_default = [
+  -109,  -109,  -109,  -109,   -14,  -109,   -20,  -109,  -109,  -109,
+  -109,  -109,  -109,  -109,   -10,   -95,  -105,  -106,   -77,   -44,
+  -107,   -11,  -108,   -79,   -43,  -102,  -109,  -109,   -60,  -103,
+   -55,  -104,   -78,   -68,   -54,   -71,   -45,   -12,  -109,    -1,
+  -109,  -109,  -109,    -2,  -109,   -22,   -51,   -48,   -50,    -3,
+   -40,   -41,  -109,   -46,    -4,   -86,    -5,   -88,    -6,   -90,
+  -109,    -7,   -95,    -8,    -9,   -98,  -100,   -61,   -59,   -56,
+   -69,  -109,  -109,  -109,  -109,   -75,  -109,  -109,   -57,   -15,
+  -109,   167,   -73,   -80,   -82,   -21,   -24,   -81,  -109,   -27,
+  -109,   -83,   -47,   -89,  -109,   -91,  -109,  -100,  -109,   -99,
+  -101,   -75,   -58,   -52,  -109,  -109,   -64,   -63,   -65,   -76,
+   -72,   -67,  -109,  -109,  -109,   -26,   -23,  -109,   -29,   -49,
+   -84,   -42,   -87,   -92,   -94,   -95,  -109,  -109,   -62,  -109,
+  -109,   -25,   -74,   -28,   -31,  -100,  -109,   -53,   -66,  -109,
+  -109,   -34,  -109,  -109,   -93,   -96,   -97,  -109,   -18,   -13,
+   -38,  -109,   -30,   -33,  -109,   -32,   -16,   -19,   -14,   -35,
+   -36,   -37,  -109,  -109,   -39,   -85,   -17 ]
+
+racc_goto_table = [
+    39,    67,    70,    73,    38,    66,    69,    24,    37,    57,
+    59,    36,    55,    67,    99,    90,    85,   157,    69,   108,
+    83,   134,   111,    76,    49,    53,   141,    70,    73,   150,
+   118,    89,    45,   155,   159,   149,   140,    21,    14,    19,
+   119,   102,    64,    63,    61,   124,    70,   104,    58,   132,
+    83,    56,    97,    83,    54,    93,    43,     5,   131,    95,
+   116,   nil,    76,   nil,    83,    76,   nil,   127,   nil,    38,
+   nil,   nil,   nil,   103,   138,   nil,   110,   nil,   nil,   nil,
+   nil,   nil,   nil,   144,   nil,   nil,   nil,   nil,   nil,    83,
+    83,   nil,   nil,   nil,    57,   nil,   nil,   122,   nil,   121,
+   nil,   nil,   nil,   nil,   nil,    83,   nil,   nil,   nil,   nil,
+   nil,   nil,   nil,   nil,   nil,   135,   nil,   nil,   nil,   nil,
+   nil,   nil,    93,   nil,   nil,   nil,    70,   161,    38,    70,
+   162,   160,   137,   nil,   nil,   nil,   nil,   nil,   nil,   nil,
+   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,
+   nil,   nil,   nil,   nil,   164 ]
+
+racc_goto_check = [
+     2,    37,    37,    29,    36,    46,    28,    13,    13,    41,
+    41,    31,    45,    37,    47,    32,    24,    23,    28,    25,
+    44,    20,    25,    42,     4,     4,    21,    37,    29,    22,
+    19,    18,    17,    26,    27,    16,    15,    12,    11,    33,
+    34,    35,    10,     9,     8,    47,    37,    29,     7,    43,
+    44,     6,    46,    44,     5,    41,     3,     1,    25,    41,
+    24,   nil,    42,   nil,    44,    42,   nil,    32,   nil,    36,
+   nil,   nil,   nil,    13,    25,   nil,    41,   nil,   nil,   nil,
+   nil,   nil,   nil,    47,   nil,   nil,   nil,   nil,   nil,    44,
+    44,   nil,   nil,   nil,    41,   nil,   nil,    45,   nil,    31,
+   nil,   nil,   nil,   nil,   nil,    44,   nil,   nil,   nil,   nil,
+   nil,   nil,   nil,   nil,   nil,    46,   nil,   nil,   nil,   nil,
+   nil,   nil,    41,   nil,   nil,   nil,    37,    29,    36,    37,
+    29,    28,    13,   nil,   nil,   nil,   nil,   nil,   nil,   nil,
+   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,
+   nil,   nil,   nil,   nil,     2 ]
+
+racc_goto_pointer = [
+   nil,    57,    -4,    50,    17,    46,    42,    38,    33,    31,
+    29,    37,    35,     5,   nil,   -94,  -105,    26,   -14,   -59,
+   -97,  -108,  -112,  -133,   -28,   -55,  -110,  -117,   -20,   -24,
+   nil,     9,   -35,    37,   -50,   -27,     1,   -25,   nil,   nil,
+   nil,     0,    -5,   -65,   -24,     3,   -10,   -52 ]
+
+racc_goto_default = [
+   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,
+   nil,   nil,   nil,    48,    41,   nil,   nil,   nil,   nil,   nil,
+   nil,   nil,   nil,   nil,   nil,    86,   nil,   nil,    30,    34,
+    50,    51,   nil,    46,    47,   nil,    26,    28,    71,    72,
+    33,    35,   114,    82,    18,   nil,   nil,   nil ]
+
+racc_token_table = {
+ false => 0,
+ Object.new => 1,
+ :DATETIME => 2,
+ :RECEIVED => 3,
+ :MADDRESS => 4,
+ :RETPATH => 5,
+ :KEYWORDS => 6,
+ :ENCRYPTED => 7,
+ :MIMEVERSION => 8,
+ :CTYPE => 9,
+ :CENCODING => 10,
+ :CDISPOSITION => 11,
+ :ADDRESS => 12,
+ :MAILBOX => 13,
+ :DIGIT => 14,
+ :ATOM => 15,
+ "," => 16,
+ ":" => 17,
+ :FROM => 18,
+ :BY => 19,
+ "@" => 20,
+ :DOMLIT => 21,
+ :VIA => 22,
+ :WITH => 23,
+ :ID => 24,
+ :FOR => 25,
+ ";" => 26,
+ "<" => 27,
+ ">" => 28,
+ "." => 29,
+ :QUOTED => 30,
+ :TOKEN => 31,
+ "/" => 32,
+ "=" => 33 }
+
+racc_use_result_var = false
+
+racc_nt_base = 34
+
+Racc_arg = [
+ racc_action_table,
+ racc_action_check,
+ racc_action_default,
+ racc_action_pointer,
+ racc_goto_table,
+ racc_goto_check,
+ racc_goto_default,
+ racc_goto_pointer,
+ racc_nt_base,
+ racc_reduce_table,
+ racc_token_table,
+ racc_shift_n,
+ racc_reduce_n,
+ racc_use_result_var ]
+
+Racc_token_to_s_table = [
+'$end',
+'error',
+'DATETIME',
+'RECEIVED',
+'MADDRESS',
+'RETPATH',
+'KEYWORDS',
+'ENCRYPTED',
+'MIMEVERSION',
+'CTYPE',
+'CENCODING',
+'CDISPOSITION',
+'ADDRESS',
+'MAILBOX',
+'DIGIT',
+'ATOM',
+'","',
+'":"',
+'FROM',
+'BY',
+'"@"',
+'DOMLIT',
+'VIA',
+'WITH',
+'ID',
+'FOR',
+'";"',
+'"<"',
+'">"',
+'"."',
+'QUOTED',
+'TOKEN',
+'"/"',
+'"="',
+'$start',
+'content',
+'datetime',
+'received',
+'addrs_TOP',
+'retpath',
+'keys',
+'enc',
+'version',
+'ctype',
+'cencode',
+'cdisp',
+'addr_TOP',
+'mbox',
+'day',
+'hour',
+'zone',
+'from',
+'by',
+'via',
+'with',
+'id',
+'for',
+'received_datetime',
+'received_domain',
+'domain',
+'msgid',
+'received_addrspec',
+'routeaddr',
+'spec',
+'addrs',
+'group_bare',
+'commas',
+'group',
+'addr',
+'mboxes',
+'addr_phrase',
+'local_head',
+'routes',
+'at_domains',
+'local',
+'word',
+'dots',
+'domword',
+'atom',
+'phrase',
+'params',
+'opt_semicolon']
+
+Racc_debug_parser = false
+
+##### racc system variables end #####
+
+ # reduce 0 omitted
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 16
+  def _reduce_1( val, _values)
+ val[1]
+  end
+.,.,
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 17
+  def _reduce_2( val, _values)
+ val[1]
+  end
+.,.,
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 18
+  def _reduce_3( val, _values)
+ val[1]
+  end
+.,.,
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 19
+  def _reduce_4( val, _values)
+ val[1]
+  end
+.,.,
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 20
+  def _reduce_5( val, _values)
+ val[1]
+  end
+.,.,
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 21
+  def _reduce_6( val, _values)
+ val[1]
+  end
+.,.,
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 22
+  def _reduce_7( val, _values)
+ val[1]
+  end
+.,.,
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 23
+  def _reduce_8( val, _values)
+ val[1]
+  end
+.,.,
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 24
+  def _reduce_9( val, _values)
+ val[1]
+  end
+.,.,
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 25
+  def _reduce_10( val, _values)
+ val[1]
+  end
+.,.,
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 26
+  def _reduce_11( val, _values)
+ val[1]
+  end
+.,.,
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 27
+  def _reduce_12( val, _values)
+ val[1]
+  end
+.,.,
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 36
+  def _reduce_13( val, _values)
+                  t = Time.gm(val[3].to_i, val[2], val[1].to_i, 0, 0, 0)
+                  (t + val[4] - val[5]).localtime
+  end
+.,.,
+
+ # reduce 14 omitted
+
+ # reduce 15 omitted
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 45
+  def _reduce_16( val, _values)
+                  (val[0].to_i * 60 * 60) +
+                  (val[2].to_i * 60)
+  end
+.,.,
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 51
+  def _reduce_17( val, _values)
+                  (val[0].to_i * 60 * 60) +
+                  (val[2].to_i * 60) +
+                  (val[4].to_i)
+  end
+.,.,
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 56
+  def _reduce_18( val, _values)
+                  timezone_string_to_unixtime(val[0])
+  end
+.,.,
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 61
+  def _reduce_19( val, _values)
+                  val
+  end
+.,.,
+
+ # reduce 20 omitted
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 67
+  def _reduce_21( val, _values)
+                  val[1]
+  end
+.,.,
+
+ # reduce 22 omitted
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 73
+  def _reduce_23( val, _values)
+                  val[1]
+  end
+.,.,
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 79
+  def _reduce_24( val, _values)
+                  join_domain(val[0])
+  end
+.,.,
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 83
+  def _reduce_25( val, _values)
+                  join_domain(val[2])
+  end
+.,.,
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 87
+  def _reduce_26( val, _values)
+                  join_domain(val[0])
+  end
+.,.,
+
+ # reduce 27 omitted
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 93
+  def _reduce_28( val, _values)
+                  val[1]
+  end
+.,.,
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 98
+  def _reduce_29( val, _values)
+                  []
+  end
+.,.,
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 103
+  def _reduce_30( val, _values)
+                  val[0].push val[2]
+                  val[0]
+  end
+.,.,
+
+ # reduce 31 omitted
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 109
+  def _reduce_32( val, _values)
+                  val[1]
+  end
+.,.,
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 113
+  def _reduce_33( val, _values)
+                  val[1]
+  end
+.,.,
+
+ # reduce 34 omitted
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 119
+  def _reduce_35( val, _values)
+                  val[1]
+  end
+.,.,
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 125
+  def _reduce_36( val, _values)
+                  val[0].spec
+  end
+.,.,
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 129
+  def _reduce_37( val, _values)
+                  val[0].spec
+  end
+.,.,
+
+ # reduce 38 omitted
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 136
+  def _reduce_39( val, _values)
+                  val[1]
+  end
+.,.,
+
+ # reduce 40 omitted
+
+ # reduce 41 omitted
+
+ # reduce 42 omitted
+
+ # reduce 43 omitted
+
+ # reduce 44 omitted
+
+ # reduce 45 omitted
+
+ # reduce 46 omitted
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 146
+  def _reduce_47( val, _values)
+ [ Address.new(nil, nil) ]
+  end
+.,.,
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 152
+  def _reduce_48( val, _values)
+                  val
+  end
+.,.,
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 157
+  def _reduce_49( val, _values)
+                  val[0].push val[2]
+                  val[0]
+  end
+.,.,
+
+ # reduce 50 omitted
+
+ # reduce 51 omitted
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 165
+  def _reduce_52( val, _values)
+                  val
+  end
+.,.,
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 170
+  def _reduce_53( val, _values)
+                  val[0].push val[2]
+                  val[0]
+  end
+.,.,
+
+ # reduce 54 omitted
+
+ # reduce 55 omitted
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 178
+  def _reduce_56( val, _values)
+                  val[1].phrase = Decoder.decode(val[0])
+                  val[1]
+  end
+.,.,
+
+ # reduce 57 omitted
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 185
+  def _reduce_58( val, _values)
+                  AddressGroup.new(val[0], val[2])
+  end
+.,.,
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 185
+  def _reduce_59( val, _values)
+ AddressGroup.new(val[0], [])
+  end
+.,.,
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 188
+  def _reduce_60( val, _values)
+ val[0].join('.')
+  end
+.,.,
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 189
+  def _reduce_61( val, _values)
+ val[0] << ' ' << val[1].join('.')
+  end
+.,.,
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 196
+  def _reduce_62( val, _values)
+                  val[2].routes.replace val[1]
+                  val[2]
+  end
+.,.,
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 200
+  def _reduce_63( val, _values)
+                  val[1]
+  end
+.,.,
+
+ # reduce 64 omitted
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 203
+  def _reduce_65( val, _values)
+ [ val[1].join('.') ]
+  end
+.,.,
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 204
+  def _reduce_66( val, _values)
+ val[0].push val[3].join('.'); val[0]
+  end
+.,.,
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 206
+  def _reduce_67( val, _values)
+ Address.new( val[0], val[2] )
+  end
+.,.,
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 207
+  def _reduce_68( val, _values)
+ Address.new( val[0], nil )
+  end
+.,.,
+
+ # reduce 69 omitted
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 210
+  def _reduce_70( val, _values)
+ val[0].push ''; val[0]
+  end
+.,.,
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 213
+  def _reduce_71( val, _values)
+ val
+  end
+.,.,
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 222
+  def _reduce_72( val, _values)
+                  val[1].times do
+                    val[0].push ''
+                  end
+                  val[0].push val[2]
+                  val[0]
+  end
+.,.,
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 224
+  def _reduce_73( val, _values)
+ val
+  end
+.,.,
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 233
+  def _reduce_74( val, _values)
+                  val[1].times do
+                    val[0].push ''
+                  end
+                  val[0].push val[2]
+                  val[0]
+  end
+.,.,
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 234
+  def _reduce_75( val, _values)
+ 0
+  end
+.,.,
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 235
+  def _reduce_76( val, _values)
+ val[0] + 1
+  end
+.,.,
+
+ # reduce 77 omitted
+
+ # reduce 78 omitted
+
+ # reduce 79 omitted
+
+ # reduce 80 omitted
+
+ # reduce 81 omitted
+
+ # reduce 82 omitted
+
+ # reduce 83 omitted
+
+ # reduce 84 omitted
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 253
+  def _reduce_85( val, _values)
+                  val[1] = val[1].spec
+                  val.join('')
+  end
+.,.,
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 254
+  def _reduce_86( val, _values)
+ val
+  end
+.,.,
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 255
+  def _reduce_87( val, _values)
+ val[0].push val[2]; val[0]
+  end
+.,.,
+
+ # reduce 88 omitted
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 258
+  def _reduce_89( val, _values)
+ val[0] << ' ' << val[1]
+  end
+.,.,
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 265
+  def _reduce_90( val, _values)
+                  val.push nil
+                  val
+  end
+.,.,
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 269
+  def _reduce_91( val, _values)
+                  val
+  end
+.,.,
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 274
+  def _reduce_92( val, _values)
+                  [ val[0].to_i, val[2].to_i ]
+  end
+.,.,
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 279
+  def _reduce_93( val, _values)
+                  [ val[0].downcase, val[2].downcase, decode_params(val[3]) ]
+  end
+.,.,
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 283
+  def _reduce_94( val, _values)
+                  [ val[0].downcase, nil, decode_params(val[1]) ]
+  end
+.,.,
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 288
+  def _reduce_95( val, _values)
+                  {}
+  end
+.,.,
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 293
+  def _reduce_96( val, _values)
+                  val[0][ val[2].downcase ] = ('"' + val[4].to_s + '"')
+                  val[0]
+  end
+.,.,
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 298
+  def _reduce_97( val, _values)
+                  val[0][ val[2].downcase ] = val[4]
+                  val[0]
+  end
+.,.,
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 303
+  def _reduce_98( val, _values)
+                  val[0].downcase
+  end
+.,.,
+
+module_eval <<'.,.,', 'lib/tmail/parser.y', 308
+  def _reduce_99( val, _values)
+                  [ val[0].downcase, decode_params(val[1]) ]
+  end
+.,.,
+
+ # reduce 100 omitted
+
+ # reduce 101 omitted
+
+ # reduce 102 omitted
+
+ # reduce 103 omitted
+
+ # reduce 104 omitted
+
+ # reduce 105 omitted
+
+ # reduce 106 omitted
+
+ # reduce 107 omitted
+
+ # reduce 108 omitted
+
+ def _reduce_none( val, _values)
+  val[0]
+ end
+
+  end   # class Parser
+
+end   # module TMail
diff --git a/lib/vendor/tmail-1.2.7/tmail/parser.y b/lib/vendor/tmail-1.2.7/tmail/parser.y
new file mode 100644 (file)
index 0000000..7c1873c
--- /dev/null
@@ -0,0 +1,416 @@
+#
+# parser.y
+#
+# Copyright (c) 1998-2007 Minero Aoki
+#
+# This program is free software.
+# You can distribute/modify this program under the terms of
+# the GNU Lesser General Public License version 2.1.
+#
+
+class TMail::Parser
+
+  options no_result_var
+
+rule
+
+  content   : DATETIME      datetime   { val[1] }
+            | RECEIVED      received   { val[1] }
+            | MADDRESS      addrs_TOP  { val[1] }
+            | RETPATH       retpath    { val[1] }
+            | KEYWORDS      keys       { val[1] }
+            | ENCRYPTED     enc        { val[1] }
+            | MIMEVERSION   version    { val[1] }
+            | CTYPE         ctype      { val[1] }
+            | CENCODING     cencode    { val[1] }
+            | CDISPOSITION  cdisp      { val[1] }
+            | ADDRESS       addr_TOP   { val[1] }
+            | MAILBOX       mbox       { val[1] }
+  
+  datetime  : day DIGIT ATOM DIGIT hour zone
+            # 0   1     2    3     4    5
+            #     date month year
+                {
+                  t = Time.gm(val[3].to_i, val[2], val[1].to_i, 0, 0, 0)
+                  (t + val[4] - val[5]).localtime
+                }
+  
+  day       :  /* none */
+            | ATOM ','
+  
+  hour      : DIGIT ':' DIGIT
+                {
+                  (val[0].to_i * 60 * 60) +
+                  (val[2].to_i * 60)
+                }
+            | DIGIT ':' DIGIT ':' DIGIT
+                {
+                  (val[0].to_i * 60 * 60) +
+                  (val[2].to_i * 60) +
+                  (val[4].to_i)
+                }
+  
+  zone      : ATOM
+                {
+                  timezone_string_to_unixtime(val[0])
+                }
+  
+  received  : from by via with id for received_datetime
+                {
+                  val
+                }
+  
+  from      : /* none */
+            | FROM received_domain
+                {
+                  val[1]
+                }
+  
+  by        :  /* none */
+            | BY received_domain
+                {
+                  val[1]
+                }
+  
+  received_domain
+            : domain
+                {
+                  join_domain(val[0])
+                }
+            | domain '@' domain
+                {
+                  join_domain(val[2])
+                }
+            | domain DOMLIT
+                {
+                  join_domain(val[0])
+                }
+  
+  via       :  /* none */
+            | VIA ATOM
+                {
+                  val[1]
+                }
+  
+  with      : /* none */
+                {
+                  []
+                }
+            | with WITH ATOM
+                {
+                  val[0].push val[2]
+                  val[0]
+                }
+  
+  id        :  /* none */
+            | ID msgid
+                {
+                  val[1]
+                }
+            | ID ATOM
+                {
+                  val[1]
+                }
+  
+  for       :  /* none */
+            | FOR received_addrspec
+                {
+                  val[1]
+                }
+
+  received_addrspec
+            : routeaddr
+                {
+                  val[0].spec
+                }
+            | spec
+                {
+                  val[0].spec
+                }
+  
+  received_datetime
+            :  /* none */
+            | ';' datetime
+                {
+                  val[1]
+                }
+  
+  addrs_TOP : addrs
+            | group_bare
+            | addrs commas group_bare
+
+  addr_TOP  : mbox
+            | group
+            | group_bare
+
+  retpath   : addrs_TOP
+            | '<' '>' { [ Address.new(nil, nil) ] }
+
+  addrs     : addr
+                {
+                  val
+                }
+            | addrs commas addr
+                {
+                  val[0].push val[2]
+                  val[0]
+                }
+
+  addr      : mbox
+            | group
+
+  mboxes    : mbox
+                {
+                  val
+                }
+            | mboxes commas mbox
+                {
+                  val[0].push val[2]
+                  val[0]
+                }
+
+  mbox      : spec
+            | routeaddr
+            | addr_phrase routeaddr
+                {
+                  val[1].phrase = Decoder.decode(val[0])
+                  val[1]
+                }
+
+  group     : group_bare ';'
+
+  group_bare: addr_phrase ':' mboxes
+                {
+                  AddressGroup.new(val[0], val[2])
+                }
+            | addr_phrase ':' { AddressGroup.new(val[0], []) }
+  
+  addr_phrase
+            : local_head             { val[0].join('.') }
+            | addr_phrase local_head { val[0] << ' ' << val[1].join('.') }
+
+  routeaddr : '<' routes spec '>'
+                {
+                  val[2].routes.replace val[1]
+                  val[2]
+                }
+            | '<' spec '>'
+                {
+                  val[1]
+                }
+  
+  routes    : at_domains ':'
+  
+  at_domains: '@' domain                { [ val[1].join('.') ] }
+            | at_domains ',' '@' domain { val[0].push val[3].join('.'); val[0] }
+  
+  spec      : local '@' domain { Address.new( val[0], val[2] ) }
+            | local            { Address.new( val[0], nil ) }
+  
+  local: local_head
+       | local_head '.' { val[0].push ''; val[0] }
+
+  local_head: word
+                { val }
+            | local_head dots word
+                {
+                  val[1].times do
+                    val[0].push ''
+                  end
+                  val[0].push val[2]
+                  val[0]
+                }
+  
+  domain    : domword
+                { val }
+            | domain dots domword
+                {
+                  val[1].times do
+                    val[0].push ''
+                  end
+                  val[0].push val[2]
+                  val[0]
+                }
+
+  dots      : '.'      { 0 }
+            | dots '.' { val[0] + 1 }
+
+  word      : atom
+            | QUOTED
+            | DIGIT
+
+  domword   : atom
+            | DOMLIT
+            | DIGIT
+
+  commas    : ','
+            | commas ','
+
+  msgid     : '<' spec '>'
+                {
+                  val[1] = val[1].spec
+                  val.join('')
+                }
+
+  keys      : phrase          { val }
+            | keys ',' phrase { val[0].push val[2]; val[0] }
+  
+  phrase    : word
+            | phrase word { val[0] << ' ' << val[1] }
+  
+  enc       : word
+                {
+                  val.push nil
+                  val
+                }
+            | word word
+                {
+                  val
+                }
+
+  version   : DIGIT '.' DIGIT
+                {
+                  [ val[0].to_i, val[2].to_i ]
+                }
+
+  ctype     : TOKEN '/' TOKEN params opt_semicolon
+                {
+                  [ val[0].downcase, val[2].downcase, decode_params(val[3]) ]
+                }
+            | TOKEN params opt_semicolon
+                {
+                  [ val[0].downcase, nil, decode_params(val[1]) ]
+                }
+  
+  params    : /* none */
+                {
+                  {}
+                }
+            | params ';' TOKEN '=' QUOTED
+                {
+                  val[0][ val[2].downcase ] = ('"' + val[4].to_s + '"')
+                  val[0]
+                }
+            | params ';' TOKEN '=' TOKEN
+                {
+                  val[0][ val[2].downcase ] = val[4]
+                  val[0]
+                }
+
+  cencode   : TOKEN
+                {
+                  val[0].downcase
+                }
+
+  cdisp     : TOKEN params opt_semicolon
+                {
+                  [ val[0].downcase, decode_params(val[1]) ]
+                }
+  
+  opt_semicolon
+            :
+            | ';'
+              
+  atom      : ATOM
+            | FROM
+            | BY
+            | VIA
+            | WITH
+            | ID
+            | FOR
+  
+end
+
+
+---- header
+#
+# parser.rb
+#
+# Copyright (c) 1998-2007 Minero Aoki
+#
+# This program is free software.
+# You can distribute/modify this program under the terms of
+# the GNU Lesser General Public License version 2.1.
+#
+
+require 'tmail/scanner'
+require 'tmail/utils'
+
+---- inner
+
+  include TextUtils
+
+  def self.parse( ident, str, cmt = nil )
+    str = special_quote_address(str) if ident.to_s =~ /M?ADDRESS/
+    new.parse(ident, str, cmt)
+  end
+
+  def self.special_quote_address(str) #:nodoc:
+    # Takes a string which is an address and adds quotation marks to special
+    # edge case methods that the RACC parser can not handle.
+    #
+    # Right now just handles two edge cases:
+    #
+    # Full stop as the last character of the display name:
+    #   Mikel L. <mikel@me.com>
+    # Returns:
+    #   "Mikel L." <mikel@me.com>
+    #
+    # Unquoted @ symbol in the display name:
+    #   mikel@me.com <mikel@me.com>
+    # Returns:
+    #   "mikel@me.com" <mikel@me.com>
+    #
+    # Any other address not matching these patterns just gets returned as is.
+    case
+    # This handles the missing "" in an older version of Apple Mail.app
+    # around the display name when the display name contains a '@'
+    # like 'mikel@me.com <mikel@me.com>'
+    # Just quotes it to: '"mikel@me.com" <mikel@me.com>'
+    when str =~ /\A([^"].+@.+[^"])\s(<.*?>)\Z/
+      return "\"#{$1}\" #{$2}"
+    # This handles cases where 'Mikel A. <mikel@me.com>' which is a trailing
+    # full stop before the address section.  Just quotes it to
+    # '"Mikel A." <mikel@me.com>'
+    when str =~ /\A(.*?\.)\s(<.*?>)\s*\Z/
+      return "\"#{$1}\" #{$2}"
+    else
+      str
+    end
+  end
+
+  MAILP_DEBUG = false
+
+  def initialize
+    self.debug = MAILP_DEBUG
+  end
+
+  def debug=( flag )
+    @yydebug = flag && Racc_debug_parser
+    @scanner_debug = flag
+  end
+
+  def debug
+    @yydebug
+  end
+
+  def parse( ident, str, comments = nil )
+    @scanner = Scanner.new(str, ident, comments)
+    @scanner.debug = @scanner_debug
+    @first = [ident, ident]
+    result = yyparse(self, :parse_in)
+    comments.map! {|c| to_kcode(c) } if comments
+    result
+  end
+
+  private
+
+  def parse_in( &block )
+    yield @first
+    @scanner.scan(&block)
+  end
+  
+  def on_error( t, val, vstack )
+    raise TMail::SyntaxError, "parse error on token #{racc_token2str t}"
+  end
+
diff --git a/lib/vendor/tmail-1.2.7/tmail/port.rb b/lib/vendor/tmail-1.2.7/tmail/port.rb
new file mode 100644 (file)
index 0000000..445f0e6
--- /dev/null
@@ -0,0 +1,379 @@
+=begin rdoc
+
+= Port class
+
+=end
+#--
+# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Note: Originally licensed under LGPL v2+. Using MIT license for Rails
+# with permission of Minero Aoki.
+#++
+
+require 'tmail/stringio'
+
+
+module TMail
+
+  class Port
+    def reproducible?
+      false
+    end
+  end
+
+
+  ###
+  ### FilePort
+  ###
+
+  class FilePort < Port
+
+    def initialize( fname )
+      @filename = File.expand_path(fname)
+      super()
+    end
+
+    attr_reader :filename
+
+    alias ident filename
+
+    def ==( other )
+      other.respond_to?(:filename) and @filename == other.filename
+    end
+
+    alias eql? ==
+
+    def hash
+      @filename.hash
+    end
+
+    def inspect
+      "#<#{self.class}:#{@filename}>"
+    end
+
+    def reproducible?
+      true
+    end
+
+    def size
+      File.size @filename
+    end
+
+
+    def ropen( &block )
+      File.open(@filename, &block)
+    end
+
+    def wopen( &block )
+      File.open(@filename, 'w', &block)
+    end
+
+    def aopen( &block )
+      File.open(@filename, 'a', &block)
+    end
+
+
+    def read_all
+      ropen {|f|
+          return f.read
+      }
+    end
+
+
+    def remove
+      File.unlink @filename
+    end
+
+    def move_to( port )
+      begin
+        File.link @filename, port.filename
+      rescue Errno::EXDEV
+        copy_to port
+      end
+      File.unlink @filename
+    end
+
+    alias mv move_to
+
+    def copy_to( port )
+      if FilePort === port
+        copy_file @filename, port.filename
+      else
+        File.open(@filename) {|r|
+        port.wopen {|w|
+            while s = r.sysread(4096)
+              w.write << s
+            end
+        } }
+      end
+    end
+
+    alias cp copy_to
+
+    private
+
+    # from fileutils.rb
+    def copy_file( src, dest )
+      st = r = w = nil
+
+      File.open(src,  'rb') {|r|
+      File.open(dest, 'wb') {|w|
+          st = r.stat
+          begin
+            while true
+              w.write r.sysread(st.blksize)
+            end
+          rescue EOFError
+          end
+      } }
+    end
+
+  end
+
+
+  module MailFlags
+
+    def seen=( b )
+      set_status 'S', b
+    end
+
+    def seen?
+      get_status 'S'
+    end
+
+    def replied=( b )
+      set_status 'R', b
+    end
+
+    def replied?
+      get_status 'R'
+    end
+
+    def flagged=( b )
+      set_status 'F', b
+    end
+
+    def flagged?
+      get_status 'F'
+    end
+
+    private
+
+    def procinfostr( str, tag, true_p )
+      a = str.upcase.split(//)
+      a.push true_p ? tag : nil
+      a.delete tag unless true_p
+      a.compact.sort.join('').squeeze
+    end
+  
+  end
+
+
+  class MhPort < FilePort
+
+    include MailFlags
+
+    private
+    
+    def set_status( tag, flag )
+      begin
+        tmpfile = @filename + '.tmailtmp.' + $$.to_s
+        File.open(tmpfile, 'w') {|f|
+          write_status f, tag, flag
+        }
+        File.unlink @filename
+        File.link tmpfile, @filename
+      ensure
+        File.unlink tmpfile
+      end
+    end
+
+    def write_status( f, tag, flag )
+      stat = ''
+      File.open(@filename) {|r|
+        while line = r.gets
+          if line.strip.empty?
+            break
+          elsif m = /\AX-TMail-Status:/i.match(line)
+            stat = m.post_match.strip
+          else
+            f.print line
+          end
+        end
+
+        s = procinfostr(stat, tag, flag)
+        f.puts 'X-TMail-Status: ' + s unless s.empty?
+        f.puts
+
+        while s = r.read(2048)
+          f.write s
+        end
+      }
+    end
+
+    def get_status( tag )
+      File.foreach(@filename) {|line|
+        return false if line.strip.empty?
+        if m = /\AX-TMail-Status:/i.match(line)
+          return m.post_match.strip.include?(tag[0])
+        end
+      }
+      false
+    end
+  
+  end
+
+
+  class MaildirPort < FilePort
+
+    def move_to_new
+      new = replace_dir(@filename, 'new')
+      File.rename @filename, new
+      @filename = new
+    end
+
+    def move_to_cur
+      new = replace_dir(@filename, 'cur')
+      File.rename @filename, new
+      @filename = new
+    end
+
+    def replace_dir( path, dir )
+      "#{File.dirname File.dirname(path)}/#{dir}/#{File.basename path}"
+    end
+    private :replace_dir
+
+
+    include MailFlags
+
+    private
+
+    MAIL_FILE = /\A(\d+\.[\d_]+\.[^:]+)(?:\:(\d),(\w+)?)?\z/
+
+    def set_status( tag, flag )
+      if m = MAIL_FILE.match(File.basename(@filename))
+        s, uniq, type, info, = m.to_a
+        return if type and type != '2'  # do not change anything
+        newname = File.dirname(@filename) + '/' +
+                  uniq + ':2,' + procinfostr(info.to_s, tag, flag)
+      else
+        newname = @filename + ':2,' + tag
+      end
+
+      File.link @filename, newname
+      File.unlink @filename
+      @filename = newname
+    end
+
+    def get_status( tag )
+      m = MAIL_FILE.match(File.basename(@filename)) or return false
+      m[2] == '2' and m[3].to_s.include?(tag[0])
+    end
+  
+  end
+
+
+  ###
+  ###  StringPort
+  ###
+
+  class StringPort < Port
+
+    def initialize( str = '' )
+      @buffer = str
+      super()
+    end
+
+    def string
+      @buffer
+    end
+
+    def to_s
+      @buffer.dup
+    end
+
+    alias read_all to_s
+
+    def size
+      @buffer.size
+    end
+
+    def ==( other )
+      StringPort === other and @buffer.equal? other.string
+    end
+
+    alias eql? ==
+
+    def hash
+      @buffer.object_id.hash
+    end
+
+    def inspect
+      "#<#{self.class}:id=#{sprintf '0x%x', @buffer.object_id}>"
+    end
+
+    def reproducible?
+      true
+    end
+
+    def ropen( &block )
+      @buffer or raise Errno::ENOENT, "#{inspect} is already removed"
+      StringInput.open(@buffer, &block)
+    end
+
+    def wopen( &block )
+      @buffer = ''
+      StringOutput.new(@buffer, &block)
+    end
+
+    def aopen( &block )
+      @buffer ||= ''
+      StringOutput.new(@buffer, &block)
+    end
+
+    def remove
+      @buffer = nil
+    end
+
+    alias rm remove
+
+    def copy_to( port )
+      port.wopen {|f|
+          f.write @buffer
+      }
+    end
+
+    alias cp copy_to
+
+    def move_to( port )
+      if StringPort === port
+        str = @buffer
+        port.instance_eval { @buffer = str }
+      else
+        copy_to port
+      end
+      remove
+    end
+
+  end
+
+end   # module TMail
diff --git a/lib/vendor/tmail-1.2.7/tmail/quoting.rb b/lib/vendor/tmail-1.2.7/tmail/quoting.rb
new file mode 100644 (file)
index 0000000..cd2ed54
--- /dev/null
@@ -0,0 +1,164 @@
+=begin rdoc
+
+= Quoting methods
+
+=end
+module TMail
+  class Mail
+    def subject(to_charset = 'utf-8')
+      Unquoter.unquote_and_convert_to(quoted_subject, to_charset)
+    end
+
+    def unquoted_body(to_charset = 'utf-8')
+      from_charset = charset
+      case (content_transfer_encoding || "7bit").downcase
+        when "quoted-printable"
+          # the default charset is set to iso-8859-1 instead of 'us-ascii'.
+          # This is needed as many mailer do not set the charset but send in ISO. This is only used if no charset is set.
+          if !from_charset.blank? && from_charset.downcase == 'us-ascii'
+            from_charset = 'iso-8859-1'
+          end
+
+          Unquoter.unquote_quoted_printable_and_convert_to(quoted_body,
+            to_charset, from_charset, true)
+        when "base64"
+          Unquoter.unquote_base64_and_convert_to(quoted_body, to_charset,
+            from_charset)
+        when "7bit", "8bit"
+          Unquoter.convert_to(quoted_body, to_charset, from_charset)
+        when "binary"
+          quoted_body
+        else
+          quoted_body
+      end
+    end
+
+    def body(to_charset = 'utf-8', &block)
+      attachment_presenter = block || Proc.new { |file_name| "Attachment: #{file_name}\n" }
+
+      if multipart?
+        parts.collect { |part|
+          header = part["content-type"]
+
+          if part.multipart?
+            part.body(to_charset, &attachment_presenter)
+          elsif header.nil?
+            ""
+          elsif !attachment?(part)
+            part.unquoted_body(to_charset)
+          else
+            attachment_presenter.call(header["name"] || "(unnamed)")
+          end
+        }.join
+      else
+        unquoted_body(to_charset)
+      end
+    end
+  end
+
+  class Attachment
+    
+    include TextUtils
+    
+    def quoted?(string)
+      !!((string =~ /.+'\w\w'.+/) || (string =~ /=\?.+\?.\?.+\?=/))
+    end
+    
+    # Only unquote if quoted
+    def original_filename(to_charset = 'utf-8')
+      if quoted?(quoted_filename)
+        Unquoter.unquote_and_convert_to(quoted_filename, to_charset).chomp
+      else
+        quoted_filename
+      end
+    end
+  end
+
+  class Unquoter
+    class << self
+      def unquote_and_convert_to(text, to_charset, from_charset = "iso-8859-1", preserve_underscores=false)
+        return "" if text.nil?
+        text.gsub!(/\?=(\s*)=\?/, '?==?') # Remove whitespaces between 'encoded-word's
+        text.gsub(/(.*?)(?:(?:=\?(.*?)\?(.)\?(.*?)\?=)|$)/) do
+          before = $1
+          from_charset = $2
+          quoting_method = $3
+          text = $4
+
+          before = convert_to(before, to_charset, from_charset) if before.length > 0
+          before + case quoting_method
+              when "q", "Q" then
+                unquote_quoted_printable_and_convert_to(text, to_charset, from_charset, preserve_underscores)
+              when "b", "B" then
+                unquote_base64_and_convert_to(text, to_charset, from_charset)
+              when nil then
+                # will be nil at the end of the string, due to the nature of
+                # the regex used.
+                ""
+              else
+                raise "unknown quoting method #{quoting_method.inspect}"
+            end
+        end
+      end
+
+      def convert_to_with_fallback_on_iso_8859_1(text, to, from)
+        return text if to == 'utf-8' and text.isutf8
+
+        if from.blank? and !text.is_binary_data?
+          from = CharDet.detect(text)['encoding']
+
+          # Chardet ususally detects iso-8859-2 (aka windows-1250), but the text is
+          # iso-8859-1 (aka windows-1252 and Latin1). http://en.wikipedia.org/wiki/ISO/IEC_8859-2
+          # This can cause unwanted characters, like Å• instead of Ã .
+          # (I know, could be a very bad decision...)
+          from = 'iso-8859-1' if from =~ /iso-8859-2/i
+        end
+
+        begin
+          convert_to_without_fallback_on_iso_8859_1(text, to, from)
+        rescue Iconv::InvalidCharacter
+          unless from == 'iso-8859-1'
+            from = 'iso-8859-1'
+            retry
+          end
+        end
+      end
+
+      def unquote_quoted_printable_and_convert_to(text, to, from, preserve_underscores=false)
+        text = text.gsub(/_/, " ") unless preserve_underscores
+        text = text.gsub(/\r\n|\r/, "\n") # normalize newlines
+        convert_to(text.unpack("M*").first, to, from)
+      end
+
+      def unquote_base64_and_convert_to(text, to, from)
+        convert_to(Base64.decode(text), to, from)
+      end
+
+      begin
+        require 'iconv'
+        def convert_to(text, to, from)
+          return text unless to && from
+          text ? Iconv.iconv(to, from, text).first : ""
+        rescue Iconv::IllegalSequence, Iconv::InvalidEncoding, Errno::EINVAL
+          # the 'from' parameter specifies a charset other than what the text
+          # actually is...not much we can do in this case but just return the
+          # unconverted text.
+          #
+          # Ditto if either parameter represents an unknown charset, like
+          # X-UNKNOWN.
+          text
+        end
+      rescue LoadError
+        # Not providing quoting support
+        def convert_to(text, to, from)
+          warn "Action Mailer: iconv not loaded; ignoring conversion from #{from} to #{to} (#{__FILE__}:#{__LINE__})"
+          text
+        end
+      end
+      
+      alias_method :convert_to_without_fallback_on_iso_8859_1, :convert_to
+      alias_method :convert_to, :convert_to_with_fallback_on_iso_8859_1
+      
+    end
+  end
+end
diff --git a/lib/vendor/tmail-1.2.7/tmail/require_arch.rb b/lib/vendor/tmail-1.2.7/tmail/require_arch.rb
new file mode 100644 (file)
index 0000000..b4fffb8
--- /dev/null
@@ -0,0 +1,58 @@
+#:stopdoc:
+require 'rbconfig'
+
+# Attempts to require anative extension.
+# Falls back to pure-ruby version, if it fails.
+#
+# This uses Config::CONFIG['arch'] from rbconfig.
+
+def require_arch(fname)
+  arch = Config::CONFIG['arch']
+  begin
+    path = File.join("tmail", arch, fname)
+    require path
+  rescue LoadError => e
+    # try pre-built Windows binaries
+    if arch =~ /mswin/
+      require File.join("tmail", 'mswin32', fname)
+    else
+      raise e
+    end
+  end
+end
+
+
+# def require_arch(fname)
+#   dext = Config::CONFIG['DLEXT']
+#   begin
+#     if File.extname(fname) == dext
+#       path = fname
+#     else
+#       path = File.join("tmail","#{fname}.#{dext}")
+#     end
+#     require path
+#   rescue LoadError => e
+#     begin
+#       arch = Config::CONFIG['arch']
+#       path = File.join("tmail", arch, "#{fname}.#{dext}")
+#       require path
+#     rescue LoadError
+#       case path
+#       when /i686/
+#         path.sub!('i686', 'i586')
+#       when /i586/
+#         path.sub!('i586', 'i486')
+#       when /i486/
+#         path.sub!('i486', 'i386')
+#       else
+#         begin
+#           require fname + '.rb'
+#         rescue LoadError
+#           raise e
+#         end
+#       end
+#       retry
+#     end
+#   end
+# end
+#:startdoc:
\ No newline at end of file
diff --git a/lib/vendor/tmail-1.2.7/tmail/scanner.rb b/lib/vendor/tmail-1.2.7/tmail/scanner.rb
new file mode 100644 (file)
index 0000000..a5d0139
--- /dev/null
@@ -0,0 +1,49 @@
+=begin rdoc
+
+= Scanner for TMail
+
+=end
+#--
+# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Note: Originally licensed under LGPL v2+. Using MIT license for Rails
+# with permission of Minero Aoki.
+#++
+#:stopdoc:
+#require 'tmail/require_arch'
+require 'tmail/utils'
+require 'tmail/config'
+
+module TMail
+  # NOTE: It woiuld be nice if these two libs could boith be called "tmailscanner", and
+  # the native extension would have precedence. However RubyGems boffs that up b/c
+  # it does not gaurantee load_path order.
+  begin
+    raise LoadError, 'Turned off native extentions by user choice' if ENV['NORUBYEXT']
+    require('tmail/tmailscanner') # c extension
+    Scanner = TMailScanner
+  rescue LoadError
+    require 'tmail/scanner_r'
+    Scanner = TMailScanner
+  end
+end
+#:stopdoc:
\ No newline at end of file
diff --git a/lib/vendor/tmail-1.2.7/tmail/scanner_r.rb b/lib/vendor/tmail-1.2.7/tmail/scanner_r.rb
new file mode 100644 (file)
index 0000000..5ed8256
--- /dev/null
@@ -0,0 +1,262 @@
+# encoding: us-ascii
+# scanner_r.rb
+#
+#--
+# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Note: Originally licensed under LGPL v2+. Using MIT license for Rails
+# with permission of Minero Aoki.
+#++
+#:stopdoc:
+require 'tmail/config'
+
+module TMail
+
+  class TMailScanner
+
+    Version = '1.2.3'
+    Version.freeze
+
+    MIME_HEADERS = {
+      :CTYPE        => true,
+      :CENCODING    => true,
+      :CDISPOSITION => true
+    }
+
+    alnum      = 'a-zA-Z0-9'
+    atomsyms   = %q[  _#!$%&`'*+-{|}~^/=?  ].strip
+    tokensyms  = %q[  _#!$%&`'*+-{|}~^@.    ].strip
+    atomchars  = alnum + Regexp.quote(atomsyms)
+    tokenchars = alnum + Regexp.quote(tokensyms)
+    iso2022str = '\e(?!\(B)..(?:[^\e]+|\e(?!\(B)..)*\e\(B'
+
+    eucstr  = "(?:[\xa1-\xfe][\xa1-\xfe])+"
+    sjisstr = "(?:[\x81-\x9f\xe0-\xef][\x40-\x7e\x80-\xfc])+"
+    utf8str = "(?:[\xc0-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf][\x80-\xbf])+"
+
+    quoted_with_iso2022  = /\A(?:[^\\\e"]+|#{iso2022str})+/n
+    domlit_with_iso2022  = /\A(?:[^\\\e\]]+|#{iso2022str})+/n
+    comment_with_iso2022 = /\A(?:[^\\\e()]+|#{iso2022str})+/n
+
+    quoted_without_iso2022  = /\A[^\\"]+/n
+    domlit_without_iso2022  = /\A[^\\\]]+/n
+    comment_without_iso2022 = /\A[^\\()]+/n
+
+    PATTERN_TABLE = {}
+    PATTERN_TABLE['EUC'] =
+      [
+        /\A(?:[#{atomchars}]+|#{iso2022str}|#{eucstr})+/n,
+        /\A(?:[#{tokenchars}]+|#{iso2022str}|#{eucstr})+/n,
+        quoted_with_iso2022,
+        domlit_with_iso2022,
+        comment_with_iso2022
+      ]
+    PATTERN_TABLE['SJIS'] =
+      [
+        /\A(?:[#{atomchars}]+|#{iso2022str}|#{sjisstr})+/n,
+        /\A(?:[#{tokenchars}]+|#{iso2022str}|#{sjisstr})+/n,
+        quoted_with_iso2022,
+        domlit_with_iso2022,
+        comment_with_iso2022
+      ]
+    PATTERN_TABLE['UTF8'] =
+      [
+        /\A(?:[#{atomchars}]+|#{utf8str})+/n,
+        /\A(?:[#{tokenchars}]+|#{utf8str})+/n,
+        quoted_without_iso2022,
+        domlit_without_iso2022,
+        comment_without_iso2022
+      ]
+    PATTERN_TABLE['NONE'] =
+      [
+        /\A[#{atomchars}]+/n,
+        /\A[#{tokenchars}]+/n,
+        quoted_without_iso2022,
+        domlit_without_iso2022,
+        comment_without_iso2022
+      ]
+
+
+    def initialize( str, scantype, comments )
+      init_scanner str
+      @comments = comments || []
+      @debug    = false
+
+      # fix scanner mode
+      @received  = (scantype == :RECEIVED)
+      @is_mime_header = MIME_HEADERS[scantype]
+
+      atom, token, @quoted_re, @domlit_re, @comment_re = PATTERN_TABLE[TMail.KCODE]
+      @word_re = (MIME_HEADERS[scantype] ? token : atom)
+    end
+
+    attr_accessor :debug
+
+    def scan( &block )
+      if @debug
+        scan_main do |arr|
+          s, v = arr
+          printf "%7d %-10s %s\n",
+                 rest_size(),
+                 s.respond_to?(:id2name) ? s.id2name : s.inspect,
+                 v.inspect
+          yield arr
+        end
+      else
+        scan_main(&block)
+      end
+    end
+
+    private
+
+    RECV_TOKEN = {
+      'from' => :FROM,
+      'by'   => :BY,
+      'via'  => :VIA,
+      'with' => :WITH,
+      'id'   => :ID,
+      'for'  => :FOR
+    }
+
+    def scan_main
+      until eof?
+        if skip(/\A[\n\r\t ]+/n)   # LWSP
+          break if eof?
+        end
+
+        if s = readstr(@word_re)
+          if @is_mime_header
+            yield [:TOKEN, s]
+          else
+            # atom
+            if /\A\d+\z/ === s
+              yield [:DIGIT, s]
+            elsif @received
+              yield [RECV_TOKEN[s.downcase] || :ATOM, s]
+            else
+              yield [:ATOM, s]
+            end
+          end
+
+        elsif skip(/\A"/)
+          yield [:QUOTED, scan_quoted_word()]
+
+        elsif skip(/\A\[/)
+          yield [:DOMLIT, scan_domain_literal()]
+
+        elsif skip(/\A\(/)
+          @comments.push scan_comment()
+
+        else
+          c = readchar()
+          yield [c, c]
+        end
+      end
+
+      yield [false, '$']
+    end
+
+    def scan_quoted_word
+      scan_qstr(@quoted_re, /\A"/, 'quoted-word')
+    end
+
+    def scan_domain_literal
+      '[' + scan_qstr(@domlit_re, /\A\]/, 'domain-literal') + ']'
+    end
+
+    def scan_qstr( pattern, terminal, type )
+      result = ''
+      until eof?
+        if    s = readstr(pattern) then result << s
+        elsif skip(terminal)       then return result
+        elsif skip(/\A\\/)         then result << readchar()
+        else
+          raise "TMail FATAL: not match in #{type}"
+        end
+      end
+      scan_error! "found unterminated #{type}"
+    end
+
+    def scan_comment
+      result = ''
+      nest = 1
+      content = @comment_re
+
+      until eof?
+        if s = readstr(content) then result << s
+        elsif skip(/\A\)/)      then nest -= 1
+                                     return result if nest == 0
+                                     result << ')'
+        elsif skip(/\A\(/)      then nest += 1
+                                     result << '('
+        elsif skip(/\A\\/)      then result << readchar()
+        else
+          raise 'TMail FATAL: not match in comment'
+        end
+      end
+      scan_error! 'found unterminated comment'
+    end
+
+    # string scanner
+
+    def init_scanner( str )
+      @src = str
+    end
+
+    def eof?
+      @src.empty?
+    end
+
+    def rest_size
+      @src.size
+    end
+
+    def readstr( re )
+      if m = re.match(@src)
+        @src = m.post_match
+        m[0]
+      else
+        nil
+      end
+    end
+
+    def readchar
+      readstr(/\A./)
+    end
+
+    def skip( re )
+      if m = re.match(@src)
+        @src = m.post_match
+        true
+      else
+        false
+      end
+    end
+
+    def scan_error!( msg )
+      raise SyntaxError, msg
+    end
+
+  end
+
+end   # module TMail
+#:startdoc:
diff --git a/lib/vendor/tmail-1.2.7/tmail/stringio.rb b/lib/vendor/tmail-1.2.7/tmail/stringio.rb
new file mode 100644 (file)
index 0000000..8357398
--- /dev/null
@@ -0,0 +1,280 @@
+# encoding: utf-8
+=begin rdoc
+
+= String handling class
+
+=end
+#--
+# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Note: Originally licensed under LGPL v2+. Using MIT license for Rails
+# with permission of Minero Aoki.
+#++
+
+class StringInput#:nodoc:
+
+  include Enumerable
+
+  class << self
+
+    def new( str )
+      if block_given?
+        begin
+          f = super
+          yield f
+        ensure
+          f.close if f
+        end
+      else
+        super
+      end
+    end
+
+    alias open new
+  
+  end
+
+  def initialize( str )
+    @src = str
+    @pos = 0
+    @closed = false
+    @lineno = 0
+  end
+
+  attr_reader :lineno
+
+  def string
+    @src
+  end
+
+  def inspect
+    "#<#{self.class}:#{@closed ? 'closed' : 'open'},src=#{@src[0,30].inspect}>"
+  end
+
+  def close
+    stream_check!
+    @pos = nil
+    @closed = true
+  end
+
+  def closed?
+    @closed
+  end
+
+  def pos
+    stream_check!
+    [@pos, @src.size].min
+  end
+
+  alias tell pos
+
+  def seek( offset, whence = IO::SEEK_SET )
+    stream_check!
+    case whence
+    when IO::SEEK_SET
+      @pos = offset
+    when IO::SEEK_CUR
+      @pos += offset
+    when IO::SEEK_END
+      @pos = @src.size - offset
+    else
+      raise ArgumentError, "unknown seek flag: #{whence}"
+    end
+    @pos = 0 if @pos < 0
+    @pos = [@pos, @src.size + 1].min
+    offset
+  end
+
+  def rewind
+    stream_check!
+    @pos = 0
+  end
+
+  def eof?
+    stream_check!
+    @pos > @src.size
+  end
+
+  def each( &block )
+    stream_check!
+    begin
+      @src.each(&block)
+    ensure
+      @pos = 0
+    end
+  end
+
+  def gets
+    stream_check!
+    if idx = @src.index(?\n, @pos)
+      idx += 1  # "\n".size
+      line = @src[ @pos ... idx ]
+      @pos = idx
+      @pos += 1 if @pos == @src.size
+    else
+      line = @src[ @pos .. -1 ]
+      @pos = @src.size + 1
+    end
+    @lineno += 1
+
+    line
+  end
+
+  def getc
+    stream_check!
+    ch = @src[@pos]
+    @pos += 1
+    @pos += 1 if @pos == @src.size
+    ch
+  end
+
+  def read( len = nil )
+    stream_check!
+    return read_all unless len
+    str = @src[@pos, len]
+    @pos += len
+    @pos += 1 if @pos == @src.size
+    str
+  end
+
+  alias sysread read
+
+  def read_all
+    stream_check!
+    return nil if eof?
+    rest = @src[@pos ... @src.size]
+    @pos = @src.size + 1
+    rest
+  end
+
+  def stream_check!
+    @closed and raise IOError, 'closed stream'
+  end
+
+end
+
+
+class StringOutput#:nodoc:
+
+  class << self
+
+    def new( str = '' )
+      if block_given?
+        begin
+          f = super
+          yield f
+        ensure
+          f.close if f
+        end
+      else
+        super
+      end
+    end
+
+    alias open new
+  
+  end
+
+  def initialize( str = '' )
+    @dest = str
+    @closed = false
+  end
+
+  def close
+    @closed = true
+  end
+
+  def closed?
+    @closed
+  end
+
+  def string
+    @dest
+  end
+
+  alias value string
+  alias to_str string
+
+  def size
+    @dest.size
+  end
+
+  alias pos size
+
+  def inspect
+    "#<#{self.class}:#{@dest ? 'open' : 'closed'},#{object_id}>"
+  end
+
+  def print( *args )
+    stream_check!
+    raise ArgumentError, 'wrong # of argument (0 for >1)' if args.empty?
+    args.each do |s|
+      raise ArgumentError, 'nil not allowed' if s.nil?
+      @dest << s.to_s
+    end
+    nil
+  end
+
+  def puts( *args )
+    stream_check!
+    args.each do |str|
+      @dest << (s = str.to_s)
+      @dest << "\n" unless s[-1] == ?\n
+    end
+    @dest << "\n" if args.empty?
+    nil
+  end
+
+  def putc( ch )
+    stream_check!
+    @dest << ch.chr
+    nil
+  end
+
+  def printf( *args )
+    stream_check!
+    @dest << sprintf(*args)
+    nil
+  end
+
+  def write( str )
+    stream_check!
+    s = str.to_s
+    @dest << s
+    s.size
+  end
+
+  alias syswrite write
+
+  def <<( str )
+    stream_check!
+    @dest << str.to_s
+    self
+  end
+
+  private
+
+  def stream_check!
+    @closed and raise IOError, 'closed stream'
+  end
+
+end
diff --git a/lib/vendor/tmail-1.2.7/tmail/utils.rb b/lib/vendor/tmail-1.2.7/tmail/utils.rb
new file mode 100644 (file)
index 0000000..3590ca2
--- /dev/null
@@ -0,0 +1,362 @@
+# encoding: us-ascii
+#--
+# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Note: Originally licensed under LGPL v2+. Using MIT license for Rails
+# with permission of Minero Aoki.
+#++
+
+# = TMail - The EMail Swiss Army Knife for Ruby
+#
+# The TMail library provides you with a very complete way to handle and manipulate EMails
+# from within your Ruby programs.
+#
+# Used as the backbone for email handling by the Ruby on Rails and Nitro web frameworks as
+# well as a bunch of other Ruby apps including the Ruby-Talk mailing list to newsgroup email
+# gateway, it is a proven and reliable email handler that won't let you down.
+#
+# Originally created by Minero Aoki, TMail has been recently picked up by Mikel Lindsaar and
+# is being actively maintained.  Numerous backlogged bug fixes have been applied as well as
+# Ruby 1.9 compatibility and a swath of documentation to boot.
+#
+# TMail allows you to treat an email totally as an object and allow you to get on with your
+# own programming without having to worry about crafting the perfect email address validation
+# parser, or assembling an email from all it's component parts.
+#
+# TMail handles the most complex part of the email - the header.  It generates and parses
+# headers and provides you with instant access to their innards through simple and logically
+# named accessor and setter methods.
+#
+# TMail also provides a wrapper to Net/SMTP as well as Unix Mailbox handling methods to
+# directly read emails from your unix mailbox, parse them and use them.
+#
+# Following is the comprehensive list of methods to access TMail::Mail objects.  You can also
+# check out TMail::Mail, TMail::Address and TMail::Headers for other lists.
+module TMail
+
+  # Provides an exception to throw on errors in Syntax within TMail's parsers
+  class SyntaxError < StandardError; end
+
+  # Provides a new email boundary to separate parts of the email.  This is a random
+  # string based off the current time, so should be fairly unique.
+  #
+  # For Example:
+  #
+  #  TMail.new_boundary
+  #  #=> "mimepart_47bf656968207_25a8fbb80114"
+  #  TMail.new_boundary
+  #  #=> "mimepart_47bf66051de4_25a8fbb80240"
+  def TMail.new_boundary
+    'mimepart_' + random_tag
+  end
+
+  # Provides a new email message ID.  You can use this to generate unique email message
+  # id's for your email so you can track them.
+  #
+  # Optionally takes a fully qualified domain name (default to the current hostname
+  # returned by Socket.gethostname) that will be appended to the message ID.
+  #
+  # For Example:
+  #
+  #  email.message_id = TMail.new_message_id
+  #  #=> "<47bf66845380e_25a8fbb80332@baci.local.tmail>"
+  #  email.to_s
+  #  #=> "Message-Id: <47bf668b633f1_25a8fbb80475@baci.local.tmail>\n\n"
+  #  email.message_id = TMail.new_message_id("lindsaar.net")
+  #  #=> "<47bf668b633f1_25a8fbb80475@lindsaar.net.tmail>"
+  #  email.to_s
+  #  #=> "Message-Id: <47bf668b633f1_25a8fbb80475@lindsaar.net.tmail>\n\n"
+  def TMail.new_message_id( fqdn = nil )
+    fqdn ||= ::Socket.gethostname
+    "<#{random_tag()}@#{fqdn}.tmail>"
+  end
+
+  #:stopdoc:
+  def TMail.random_tag #:nodoc:
+    @uniq += 1
+    t = Time.now
+    sprintf('%x%x_%x%x%d%x',
+            t.to_i, t.tv_usec,
+            $$, Thread.current.object_id, @uniq, rand(255))
+  end
+  private_class_method :random_tag
+
+  @uniq = 0
+
+  #:startdoc:
+
+  # Text Utils provides a namespace to define TOKENs, ATOMs, PHRASEs and CONTROL characters that
+  # are OK per RFC 2822.
+  #
+  # It also provides methods you can call to determine if a string is safe
+  module TextUtils
+
+    aspecial     = %Q|()<>[]:;.\\,"|
+    tspecial     = %Q|()<>[];:\\,"/?=|
+    lwsp         = %Q| \t\r\n|
+    control      = %Q|\x00-\x1f\x7f-\xff|
+
+    CONTROL_CHAR  = /[#{control}]/n
+    ATOM_UNSAFE   = /[#{Regexp.quote aspecial}#{control}#{lwsp}]/n
+    PHRASE_UNSAFE = /[#{Regexp.quote aspecial}#{control}]/n
+    TOKEN_UNSAFE  = /[#{Regexp.quote tspecial}#{control}#{lwsp}]/n
+
+    # Returns true if the string supplied is free from characters not allowed as an ATOM
+    def atom_safe?( str )
+      not ATOM_UNSAFE === str
+    end
+
+    # If the string supplied has ATOM unsafe characters in it, will return the string quoted
+    # in double quotes, otherwise returns the string unmodified
+    def quote_atom( str )
+      (ATOM_UNSAFE === str) ? dquote(str) : str
+    end
+
+    # If the string supplied has PHRASE unsafe characters in it, will return the string quoted
+    # in double quotes, otherwise returns the string unmodified
+    def quote_phrase( str )
+      (PHRASE_UNSAFE === str) ? dquote(str) : str
+    end
+
+    # Returns true if the string supplied is free from characters not allowed as a TOKEN
+    def token_safe?( str )
+      not TOKEN_UNSAFE === str
+    end
+
+    # If the string supplied has TOKEN unsafe characters in it, will return the string quoted
+    # in double quotes, otherwise returns the string unmodified
+    def quote_token( str )
+      (TOKEN_UNSAFE === str) ? dquote(str) : str
+    end
+
+    # Wraps supplied string in double quotes unless it is already wrapped
+    # Returns double quoted string
+    def dquote( str ) #:nodoc:
+      unless str =~ /^".*?"$/
+        '"' + str.gsub(/["\\]/n) {|s| '\\' + s } + '"'
+      else
+        str
+      end
+    end
+    private :dquote
+
+    # Unwraps supplied string from inside double quotes
+    # Returns unquoted string
+    def unquote( str )
+      str =~ /^"(.*?)"$/m ? $1 : str
+    end
+
+    # Provides a method to join a domain name by it's parts and also makes it
+    # ATOM safe by quoting it as needed
+    def join_domain( arr )
+      arr.map {|i|
+          if /\A\[.*\]\z/ === i
+            i
+          else
+            quote_atom(i)
+          end
+      }.join('.')
+    end
+
+    #:stopdoc:
+    ZONESTR_TABLE = {
+      'jst' =>   9 * 60,
+      'eet' =>   2 * 60,
+      'bst' =>   1 * 60,
+      'met' =>   1 * 60,
+      'gmt' =>   0,
+      'utc' =>   0,
+      'ut'  =>   0,
+      'nst' => -(3 * 60 + 30),
+      'ast' =>  -4 * 60,
+      'edt' =>  -4 * 60,
+      'est' =>  -5 * 60,
+      'cdt' =>  -5 * 60,
+      'cst' =>  -6 * 60,
+      'mdt' =>  -6 * 60,
+      'mst' =>  -7 * 60,
+      'pdt' =>  -7 * 60,
+      'pst' =>  -8 * 60,
+      'a'   =>  -1 * 60,
+      'b'   =>  -2 * 60,
+      'c'   =>  -3 * 60,
+      'd'   =>  -4 * 60,
+      'e'   =>  -5 * 60,
+      'f'   =>  -6 * 60,
+      'g'   =>  -7 * 60,
+      'h'   =>  -8 * 60,
+      'i'   =>  -9 * 60,
+      # j not use
+      'k'   => -10 * 60,
+      'l'   => -11 * 60,
+      'm'   => -12 * 60,
+      'n'   =>   1 * 60,
+      'o'   =>   2 * 60,
+      'p'   =>   3 * 60,
+      'q'   =>   4 * 60,
+      'r'   =>   5 * 60,
+      's'   =>   6 * 60,
+      't'   =>   7 * 60,
+      'u'   =>   8 * 60,
+      'v'   =>   9 * 60,
+      'w'   =>  10 * 60,
+      'x'   =>  11 * 60,
+      'y'   =>  12 * 60,
+      'z'   =>   0 * 60
+    }
+    #:startdoc:
+
+    # Takes a time zone string from an EMail and converts it to Unix Time (seconds)
+    def timezone_string_to_unixtime( str )
+      if m = /([\+\-])(\d\d?)(\d\d)/.match(str)
+        sec = (m[2].to_i * 60 + m[3].to_i) * 60
+        m[1] == '-' ? -sec : sec
+      else
+        min = ZONESTR_TABLE[str.downcase] or
+                raise SyntaxError, "wrong timezone format '#{str}'"
+        min * 60
+      end
+    end
+
+    #:stopdoc:
+    WDAY = %w( Sun Mon Tue Wed Thu Fri Sat TMailBUG )
+    MONTH = %w( TMailBUG Jan Feb Mar Apr May Jun
+                         Jul Aug Sep Oct Nov Dec TMailBUG )
+
+    def time2str( tm )
+      # [ruby-list:7928]
+      gmt = Time.at(tm.to_i)
+      gmt.gmtime
+      offset = tm.to_i - Time.local(*gmt.to_a[0,6].reverse).to_i
+
+      # DO NOT USE strftime: setlocale() breaks it
+      sprintf '%s, %s %s %d %02d:%02d:%02d %+.2d%.2d',
+              WDAY[tm.wday], tm.mday, MONTH[tm.month],
+              tm.year, tm.hour, tm.min, tm.sec,
+              *(offset / 60).divmod(60)
+    end
+
+
+    MESSAGE_ID = /<[^\@>]+\@[^>]+>/
+
+    def message_id?( str )
+      MESSAGE_ID === str
+    end
+
+
+    MIME_ENCODED = /=\?[^\s?=]+\?[QB]\?[^\s?=]+\?=/i
+
+    def mime_encoded?( str )
+      MIME_ENCODED === str
+    end
+
+
+    def decode_params( hash )
+      new = Hash.new
+      encoded = nil
+      hash.each do |key, value|
+        if m = /\*(?:(\d+)\*)?\z/.match(key)
+          ((encoded ||= {})[m.pre_match] ||= [])[(m[1] || 0).to_i] = value
+        else
+          new[key] = to_kcode(value)
+        end
+      end
+      if encoded
+        encoded.each do |key, strings|
+          new[key] = decode_RFC2231(strings.join(''))
+        end
+      end
+
+      new
+    end
+
+    NKF_FLAGS = {
+      'EUC'  => '-e -m',
+      'SJIS' => '-s -m'
+    }
+
+    def to_kcode( str )
+      flag = NKF_FLAGS[TMail.KCODE] or return str
+      NKF.nkf(flag, str)
+    end
+
+    RFC2231_ENCODED = /\A(?:iso-2022-jp|euc-jp|shift_jis|us-ascii)?'[a-z]*'/in
+
+    def decode_RFC2231( str )
+      m = RFC2231_ENCODED.match(str) or return str
+      begin
+        to_kcode(m.post_match.gsub(/%[\da-f]{2}/in) {|s| s[1,2].hex.chr })
+      rescue
+        m.post_match.gsub(/%[\da-f]{2}/in, "")
+      end
+    end
+
+    def quote_boundary
+      # Make sure the Content-Type boundary= parameter is quoted if it contains illegal characters
+      # (to ensure any special characters in the boundary text are escaped from the parser
+      # (such as = in MS Outlook's boundary text))
+      if @body =~ /^(.*)boundary=(.*)$/m
+        preamble = $1
+        remainder = $2
+        if remainder =~ /;/
+          remainder =~ /^(.*?)(;.*)$/m
+          boundary_text = $1
+          post = $2.chomp
+        else
+          boundary_text = remainder.chomp
+        end
+        if boundary_text =~ /[\/\?\=]/
+          boundary_text = "\"#{boundary_text}\"" unless boundary_text =~ /^".*?"$/
+          @body = "#{preamble}boundary=#{boundary_text}#{post}"
+        end
+      end
+    end
+
+    # AppleMail generates illegal character contained Content-Type parameter like:
+    #   name==?ISO-2022-JP?B?...=?=
+    # so quote. (This case is only value fits in one line.)
+    def quote_unquoted_bencode
+      @body = @body.gsub(%r"(;\s+[-a-z]+=)(=\?.+?)([;\r\n ]|\z)"m) {
+        head, should_quoted, tail = $~.captures
+        # head: "; name="
+        # should_quoted: "=?ISO-2022-JP?B?...=?="
+
+        head << quote_token(should_quoted) << tail
+      }
+    end
+
+    # AppleMail generates name=filename attributes in the content type that
+    # contain spaces.  Need to handle this so the TMail Parser can.
+    def quote_unquoted_name
+      @body = @body.gsub(%r|(name=)([\w\s.]+)(.*)|m) {
+        head, should_quoted, tail = $~.captures
+        # head: "; name="
+        # should_quoted: "=?ISO-2022-JP?B?...=?="
+        head  << quote_token(should_quoted) << tail
+      }
+    end
+
+    #:startdoc:
+
+  end
+
+end
diff --git a/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/COPYING b/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/COPYING
new file mode 100644 (file)
index 0000000..8add30a
--- /dev/null
@@ -0,0 +1,504 @@
+                 GNU LESSER GENERAL PUBLIC LICENSE
+                      Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+     51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+\f
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+\f
+                 GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+\f
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+\f
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+\f
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+\f
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+\f
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+\f
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+                           NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+\f
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
+
+
diff --git a/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/README b/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/README
new file mode 100644 (file)
index 0000000..f89c61a
--- /dev/null
@@ -0,0 +1,12 @@
+Usage:
+    require 'rubygems'
+    require 'rchardet'
+
+    cd = CharDet.detect(some_data)
+    encoding = cd['encoding']
+    confidence = cd['confidence'] # 0.0 <= confidence <= 1.0
+
+Project page: 
+    http://rubyforge.org/projects/rchardet
+
+    Made for rFeedParser <http://rfeedparser.rubyforge.org>.
diff --git a/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet.rb b/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet.rb
new file mode 100644 (file)
index 0000000..b64338b
--- /dev/null
@@ -0,0 +1,67 @@
+######################## BEGIN LICENSE BLOCK ########################
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+# 
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301  USA
+######################### END LICENSE BLOCK #########################
+
+$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__))
+
+require 'rchardet/charsetprober'
+require 'rchardet/mbcharsetprober'
+
+require 'rchardet/big5freq'
+require 'rchardet/big5prober'
+require 'rchardet/chardistribution'
+require 'rchardet/charsetgroupprober'
+
+require 'rchardet/codingstatemachine'
+require 'rchardet/constants'
+require 'rchardet/escprober'
+require 'rchardet/escsm'
+require 'rchardet/eucjpprober'
+require 'rchardet/euckrfreq'
+require 'rchardet/euckrprober'
+require 'rchardet/euctwfreq'
+require 'rchardet/euctwprober'
+require 'rchardet/gb2312freq'
+require 'rchardet/gb2312prober'
+require 'rchardet/hebrewprober'
+require 'rchardet/jisfreq'
+require 'rchardet/jpcntx'
+require 'rchardet/langbulgarianmodel'
+require 'rchardet/langcyrillicmodel'
+require 'rchardet/langgreekmodel'
+require 'rchardet/langhebrewmodel'
+require 'rchardet/langhungarianmodel'
+require 'rchardet/langthaimodel'
+require 'rchardet/latin1prober'
+
+require 'rchardet/mbcsgroupprober'
+require 'rchardet/mbcssm'
+require 'rchardet/sbcharsetprober'
+require 'rchardet/sbcsgroupprober'
+require 'rchardet/sjisprober'
+require 'rchardet/universaldetector'
+require 'rchardet/utf8prober'
+
+module CharDet
+  VERSION = "1.3"
+  def CharDet.detect(aBuf)
+    u = UniversalDetector.new
+    u.reset
+    u.feed(aBuf)
+    u.close
+    u.result
+  end
+end
diff --git a/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/big5freq.rb b/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/big5freq.rb
new file mode 100644 (file)
index 0000000..3606f39
--- /dev/null
@@ -0,0 +1,927 @@
+######################## BEGIN LICENSE BLOCK ########################
+# The Original Code is Mozilla Communicator client code.
+# 
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+# 
+# Contributor(s):
+#   Jeff Hodges - port to Ruby
+#   Mark Pilgrim - port to Python
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+# 
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301  USA
+######################### END LICENSE BLOCK #########################
+
+# Big5 frequency table
+# by Taiwan's Mandarin Promotion Council 
+# <http://www.edu.tw:81/mandr/>
+# 
+# 128  --> 0.42261
+# 256  --> 0.57851
+# 512  --> 0.74851
+# 1024 --> 0.89384
+# 2048 --> 0.97583
+# 
+# Ideal Distribution Ratio = 0.74851/(1-0.74851) =2.98
+# Random Distribution Ration = 512/(5401-512)=0.105
+# 
+# Typical Distribution Ratio about 25% of Ideal one, still much higher than RDR
+
+module CharDet
+BIG5_TYPICAL_DISTRIBUTION_RATIO = 0.75
+
+#Char to FreqOrder table
+BIG5_TABLE_SIZE = 5376
+
+Big5CharToFreqOrder = [ 
+   1,1801,1506, 255,1431, 198,   9,  82,   6,5008, 177, 202,3681,1256,2821, 110, #   16
+3814,  33,3274, 261,  76,  44,2114,  16,2946,2187,1176, 659,3971,  26,3451,2653, #   32
+1198,3972,3350,4202, 410,2215, 302, 590, 361,1964,   8, 204,  58,4510,5009,1932, #   48
+  63,5010,5011, 317,1614,  75, 222, 159,4203,2417,1480,5012,3555,3091, 224,2822, #   64
+3682,   3,  10,3973,1471,  29,2787,1135,2866,1940, 873, 130,3275,1123, 312,5013, #   80
+4511,2052, 507, 252, 682,5014, 142,1915, 124, 206,2947,  34,3556,3204,  64, 604, #   96
+5015,2501,1977,1978, 155,1991, 645, 641,1606,5016,3452, 337,  72, 406,5017,  80, #  112
+ 630, 238,3205,1509, 263, 939,1092,2654, 756,1440,1094,3453, 449,  69,2987, 591, #  128
+ 179,2096, 471, 115,2035,1844,  60,  50,2988, 134, 806,1869, 734,2036,3454, 180, #  144
+ 995,1607, 156, 537,2907, 688,5018, 319,1305, 779,2145, 514,2379, 298,4512, 359, #  160
+2502,  90,2716,1338, 663,  11, 906,1099,2553,  20,2441, 182, 532,1716,5019, 732, #  176
+1376,4204,1311,1420,3206,  25,2317,1056, 113, 399, 382,1950, 242,3455,2474, 529, #  192
+3276, 475,1447,3683,5020, 117,  21, 656, 810,1297,2300,2334,3557,5021, 126,4205, #  208
+ 706, 456, 150, 613,4513,  71,1118,2037,4206, 145,3092,  85, 835, 486,2115,1246, #  224
+1426, 428, 727,1285,1015, 800, 106, 623, 303,1281,5022,2128,2359, 347,3815, 221, #  240
+3558,3135,5023,1956,1153,4207,  83, 296,1199,3093, 192, 624,  93,5024, 822,1898, #  256
+2823,3136, 795,2065, 991,1554,1542,1592,  27,  43,2867, 859, 139,1456, 860,4514, #  272
+ 437, 712,3974, 164,2397,3137, 695, 211,3037,2097, 195,3975,1608,3559,3560,3684, #  288
+3976, 234, 811,2989,2098,3977,2233,1441,3561,1615,2380, 668,2077,1638, 305, 228, #  304
+1664,4515, 467, 415,5025, 262,2099,1593, 239, 108, 300, 200,1033, 512,1247,2078, #  320
+5026,5027,2176,3207,3685,2682, 593, 845,1062,3277,  88,1723,2038,3978,1951, 212, #  336
+ 266, 152, 149, 468,1899,4208,4516,  77, 187,5028,3038,  37,   5,2990,5029,3979, #  352
+5030,5031,  39,2524,4517,2908,3208,2079,  55, 148,  74,4518, 545, 483,1474,1029, #  368
+1665, 217,1870,1531,3138,1104,2655,4209,  24, 172,3562, 900,3980,3563,3564,4519, #  384
+  32,1408,2824,1312, 329, 487,2360,2251,2717, 784,2683,   4,3039,3351,1427,1789, #  400
+ 188, 109, 499,5032,3686,1717,1790, 888,1217,3040,4520,5033,3565,5034,3352,1520, #  416
+3687,3981, 196,1034, 775,5035,5036, 929,1816, 249, 439,  38,5037,1063,5038, 794, #  432
+3982,1435,2301,  46, 178,3278,2066,5039,2381,5040, 214,1709,4521, 804,  35, 707, #  448
+ 324,3688,1601,2554, 140, 459,4210,5041,5042,1365, 839, 272, 978,2262,2580,3456, #  464
+2129,1363,3689,1423, 697, 100,3094,  48,  70,1231, 495,3139,2196,5043,1294,5044, #  480
+2080, 462, 586,1042,3279, 853, 256, 988, 185,2382,3457,1698, 434,1084,5045,3458, #  496
+ 314,2625,2788,4522,2335,2336, 569,2285, 637,1817,2525, 757,1162,1879,1616,3459, #  512
+ 287,1577,2116, 768,4523,1671,2868,3566,2526,1321,3816, 909,2418,5046,4211, 933, #  528
+3817,4212,2053,2361,1222,4524, 765,2419,1322, 786,4525,5047,1920,1462,1677,2909, #  544
+1699,5048,4526,1424,2442,3140,3690,2600,3353,1775,1941,3460,3983,4213, 309,1369, #  560
+1130,2825, 364,2234,1653,1299,3984,3567,3985,3986,2656, 525,1085,3041, 902,2001, #  576
+1475, 964,4527, 421,1845,1415,1057,2286, 940,1364,3141, 376,4528,4529,1381,   7, #  592
+2527, 983,2383, 336,1710,2684,1846, 321,3461, 559,1131,3042,2752,1809,1132,1313, #  608
+ 265,1481,1858,5049, 352,1203,2826,3280, 167,1089, 420,2827, 776, 792,1724,3568, #  624
+4214,2443,3281,5050,4215,5051, 446, 229, 333,2753, 901,3818,1200,1557,4530,2657, #  640
+1921, 395,2754,2685,3819,4216,1836, 125, 916,3209,2626,4531,5052,5053,3820,5054, #  656
+5055,5056,4532,3142,3691,1133,2555,1757,3462,1510,2318,1409,3569,5057,2146, 438, #  672
+2601,2910,2384,3354,1068, 958,3043, 461, 311,2869,2686,4217,1916,3210,4218,1979, #  688
+ 383, 750,2755,2627,4219, 274, 539, 385,1278,1442,5058,1154,1965, 384, 561, 210, #  704
+  98,1295,2556,3570,5059,1711,2420,1482,3463,3987,2911,1257, 129,5060,3821, 642, #  720
+ 523,2789,2790,2658,5061, 141,2235,1333,  68, 176, 441, 876, 907,4220, 603,2602, #  736
+ 710, 171,3464, 404, 549,  18,3143,2398,1410,3692,1666,5062,3571,4533,2912,4534, #  752
+5063,2991, 368,5064, 146, 366,  99, 871,3693,1543, 748, 807,1586,1185,  22,2263, #  768
+ 379,3822,3211,5065,3212, 505,1942,2628,1992,1382,2319,5066, 380,2362, 218, 702, #  784
+1818,1248,3465,3044,3572,3355,3282,5067,2992,3694, 930,3283,3823,5068,  59,5069, #  800
+ 585, 601,4221, 497,3466,1112,1314,4535,1802,5070,1223,1472,2177,5071, 749,1837, #  816
+ 690,1900,3824,1773,3988,1476, 429,1043,1791,2236,2117, 917,4222, 447,1086,1629, #  832
+5072, 556,5073,5074,2021,1654, 844,1090, 105, 550, 966,1758,2828,1008,1783, 686, #  848
+1095,5075,2287, 793,1602,5076,3573,2603,4536,4223,2948,2302,4537,3825, 980,2503, #  864
+ 544, 353, 527,4538, 908,2687,2913,5077, 381,2629,1943,1348,5078,1341,1252, 560, #  880
+3095,5079,3467,2870,5080,2054, 973, 886,2081, 143,4539,5081,5082, 157,3989, 496, #  896
+4224,  57, 840, 540,2039,4540,4541,3468,2118,1445, 970,2264,1748,1966,2082,4225, #  912
+3144,1234,1776,3284,2829,3695, 773,1206,2130,1066,2040,1326,3990,1738,1725,4226, #  928
+ 279,3145,  51,1544,2604, 423,1578,2131,2067, 173,4542,1880,5083,5084,1583, 264, #  944
+ 610,3696,4543,2444, 280, 154,5085,5086,5087,1739, 338,1282,3096, 693,2871,1411, #  960
+1074,3826,2445,5088,4544,5089,5090,1240, 952,2399,5091,2914,1538,2688, 685,1483, #  976
+4227,2475,1436, 953,4228,2055,4545, 671,2400,  79,4229,2446,3285, 608, 567,2689, #  992
+3469,4230,4231,1691, 393,1261,1792,2401,5092,4546,5093,5094,5095,5096,1383,1672, # 1008
+3827,3213,1464, 522,1119, 661,1150, 216, 675,4547,3991,1432,3574, 609,4548,2690, # 1024
+2402,5097,5098,5099,4232,3045,   0,5100,2476, 315, 231,2447, 301,3356,4549,2385, # 1040
+5101, 233,4233,3697,1819,4550,4551,5102,  96,1777,1315,2083,5103, 257,5104,1810, # 1056
+3698,2718,1139,1820,4234,2022,1124,2164,2791,1778,2659,5105,3097, 363,1655,3214, # 1072
+5106,2993,5107,5108,5109,3992,1567,3993, 718, 103,3215, 849,1443, 341,3357,2949, # 1088
+1484,5110,1712, 127,  67, 339,4235,2403, 679,1412, 821,5111,5112, 834, 738, 351, # 1104
+2994,2147, 846, 235,1497,1881, 418,1993,3828,2719, 186,1100,2148,2756,3575,1545, # 1120
+1355,2950,2872,1377, 583,3994,4236,2581,2995,5113,1298,3699,1078,2557,3700,2363, # 1136
+  78,3829,3830, 267,1289,2100,2002,1594,4237, 348, 369,1274,2197,2178,1838,4552, # 1152
+1821,2830,3701,2757,2288,2003,4553,2951,2758, 144,3358, 882,4554,3995,2759,3470, # 1168
+4555,2915,5114,4238,1726, 320,5115,3996,3046, 788,2996,5116,2831,1774,1327,2873, # 1184
+3997,2832,5117,1306,4556,2004,1700,3831,3576,2364,2660, 787,2023, 506, 824,3702, # 1200
+ 534, 323,4557,1044,3359,2024,1901, 946,3471,5118,1779,1500,1678,5119,1882,4558, # 1216
+ 165, 243,4559,3703,2528, 123, 683,4239, 764,4560,  36,3998,1793, 589,2916, 816, # 1232
+ 626,1667,3047,2237,1639,1555,1622,3832,3999,5120,4000,2874,1370,1228,1933, 891, # 1248
+2084,2917, 304,4240,5121, 292,2997,2720,3577, 691,2101,4241,1115,4561, 118, 662, # 1264
+5122, 611,1156, 854,2386,1316,2875,   2, 386, 515,2918,5123,5124,3286, 868,2238, # 1280
+1486, 855,2661, 785,2216,3048,5125,1040,3216,3578,5126,3146, 448,5127,1525,5128, # 1296
+2165,4562,5129,3833,5130,4242,2833,3579,3147, 503, 818,4001,3148,1568, 814, 676, # 1312
+1444, 306,1749,5131,3834,1416,1030, 197,1428, 805,2834,1501,4563,5132,5133,5134, # 1328
+1994,5135,4564,5136,5137,2198,  13,2792,3704,2998,3149,1229,1917,5138,3835,2132, # 1344
+5139,4243,4565,2404,3580,5140,2217,1511,1727,1120,5141,5142, 646,3836,2448, 307, # 1360
+5143,5144,1595,3217,5145,5146,5147,3705,1113,1356,4002,1465,2529,2530,5148, 519, # 1376
+5149, 128,2133,  92,2289,1980,5150,4003,1512, 342,3150,2199,5151,2793,2218,1981, # 1392
+3360,4244, 290,1656,1317, 789, 827,2365,5152,3837,4566, 562, 581,4004,5153, 401, # 1408
+4567,2252,  94,4568,5154,1399,2794,5155,1463,2025,4569,3218,1944,5156, 828,1105, # 1424
+4245,1262,1394,5157,4246, 605,4570,5158,1784,2876,5159,2835, 819,2102, 578,2200, # 1440
+2952,5160,1502, 436,3287,4247,3288,2836,4005,2919,3472,3473,5161,2721,2320,5162, # 1456
+5163,2337,2068,  23,4571, 193, 826,3838,2103, 699,1630,4248,3098, 390,1794,1064, # 1472
+3581,5164,1579,3099,3100,1400,5165,4249,1839,1640,2877,5166,4572,4573, 137,4250, # 1488
+ 598,3101,1967, 780, 104, 974,2953,5167, 278, 899, 253, 402, 572, 504, 493,1339, # 1504
+5168,4006,1275,4574,2582,2558,5169,3706,3049,3102,2253, 565,1334,2722, 863,  41, # 1520
+5170,5171,4575,5172,1657,2338,  19, 463,2760,4251, 606,5173,2999,3289,1087,2085, # 1536
+1323,2662,3000,5174,1631,1623,1750,4252,2691,5175,2878, 791,2723,2663,2339, 232, # 1552
+2421,5176,3001,1498,5177,2664,2630, 755,1366,3707,3290,3151,2026,1609, 119,1918, # 1568
+3474, 862,1026,4253,5178,4007,3839,4576,4008,4577,2265,1952,2477,5179,1125, 817, # 1584
+4254,4255,4009,1513,1766,2041,1487,4256,3050,3291,2837,3840,3152,5180,5181,1507, # 1600
+5182,2692, 733,  40,1632,1106,2879, 345,4257, 841,2531, 230,4578,3002,1847,3292, # 1616
+3475,5183,1263, 986,3476,5184, 735, 879, 254,1137, 857, 622,1300,1180,1388,1562, # 1632
+4010,4011,2954, 967,2761,2665,1349, 592,2134,1692,3361,3003,1995,4258,1679,4012, # 1648
+1902,2188,5185, 739,3708,2724,1296,1290,5186,4259,2201,2202,1922,1563,2605,2559, # 1664
+1871,2762,3004,5187, 435,5188, 343,1108, 596,  17,1751,4579,2239,3477,3709,5189, # 1680
+4580, 294,3582,2955,1693, 477, 979, 281,2042,3583, 643,2043,3710,2631,2795,2266, # 1696
+1031,2340,2135,2303,3584,4581, 367,1249,2560,5190,3585,5191,4582,1283,3362,2005, # 1712
+ 240,1762,3363,4583,4584, 836,1069,3153, 474,5192,2149,2532, 268,3586,5193,3219, # 1728
+1521,1284,5194,1658,1546,4260,5195,3587,3588,5196,4261,3364,2693,1685,4262, 961, # 1744
+1673,2632, 190,2006,2203,3841,4585,4586,5197, 570,2504,3711,1490,5198,4587,2633, # 1760
+3293,1957,4588, 584,1514, 396,1045,1945,5199,4589,1968,2449,5200,5201,4590,4013, # 1776
+ 619,5202,3154,3294, 215,2007,2796,2561,3220,4591,3221,4592, 763,4263,3842,4593, # 1792
+5203,5204,1958,1767,2956,3365,3712,1174, 452,1477,4594,3366,3155,5205,2838,1253, # 1808
+2387,2189,1091,2290,4264, 492,5206, 638,1169,1825,2136,1752,4014, 648, 926,1021, # 1824
+1324,4595, 520,4596, 997, 847,1007, 892,4597,3843,2267,1872,3713,2405,1785,4598, # 1840
+1953,2957,3103,3222,1728,4265,2044,3714,4599,2008,1701,3156,1551,  30,2268,4266, # 1856
+5207,2027,4600,3589,5208, 501,5209,4267, 594,3478,2166,1822,3590,3479,3591,3223, # 1872
+ 829,2839,4268,5210,1680,3157,1225,4269,5211,3295,4601,4270,3158,2341,5212,4602, # 1888
+4271,5213,4015,4016,5214,1848,2388,2606,3367,5215,4603, 374,4017, 652,4272,4273, # 1904
+ 375,1140, 798,5216,5217,5218,2366,4604,2269, 546,1659, 138,3051,2450,4605,5219, # 1920
+2254, 612,1849, 910, 796,3844,1740,1371, 825,3845,3846,5220,2920,2562,5221, 692, # 1936
+ 444,3052,2634, 801,4606,4274,5222,1491, 244,1053,3053,4275,4276, 340,5223,4018, # 1952
+1041,3005, 293,1168,  87,1357,5224,1539, 959,5225,2240, 721, 694,4277,3847, 219, # 1968
+1478, 644,1417,3368,2666,1413,1401,1335,1389,4019,5226,5227,3006,2367,3159,1826, # 1984
+ 730,1515, 184,2840,  66,4607,5228,1660,2958, 246,3369, 378,1457, 226,3480, 975, # 2000
+4020,2959,1264,3592, 674, 696,5229, 163,5230,1141,2422,2167, 713,3593,3370,4608, # 2016
+4021,5231,5232,1186,  15,5233,1079,1070,5234,1522,3224,3594, 276,1050,2725, 758, # 2032
+1126, 653,2960,3296,5235,2342, 889,3595,4022,3104,3007, 903,1250,4609,4023,3481, # 2048
+3596,1342,1681,1718, 766,3297, 286,  89,2961,3715,5236,1713,5237,2607,3371,3008, # 2064
+5238,2962,2219,3225,2880,5239,4610,2505,2533, 181, 387,1075,4024, 731,2190,3372, # 2080
+5240,3298, 310, 313,3482,2304, 770,4278,  54,3054, 189,4611,3105,3848,4025,5241, # 2096
+1230,1617,1850, 355,3597,4279,4612,3373, 111,4280,3716,1350,3160,3483,3055,4281, # 2112
+2150,3299,3598,5242,2797,4026,4027,3009, 722,2009,5243,1071, 247,1207,2343,2478, # 2128
+1378,4613,2010, 864,1437,1214,4614, 373,3849,1142,2220, 667,4615, 442,2763,2563, # 2144
+3850,4028,1969,4282,3300,1840, 837, 170,1107, 934,1336,1883,5244,5245,2119,4283, # 2160
+2841, 743,1569,5246,4616,4284, 582,2389,1418,3484,5247,1803,5248, 357,1395,1729, # 2176
+3717,3301,2423,1564,2241,5249,3106,3851,1633,4617,1114,2086,4285,1532,5250, 482, # 2192
+2451,4618,5251,5252,1492, 833,1466,5253,2726,3599,1641,2842,5254,1526,1272,3718, # 2208
+4286,1686,1795, 416,2564,1903,1954,1804,5255,3852,2798,3853,1159,2321,5256,2881, # 2224
+4619,1610,1584,3056,2424,2764, 443,3302,1163,3161,5257,5258,4029,5259,4287,2506, # 2240
+3057,4620,4030,3162,2104,1647,3600,2011,1873,4288,5260,4289, 431,3485,5261, 250, # 2256
+  97,  81,4290,5262,1648,1851,1558, 160, 848,5263, 866, 740,1694,5264,2204,2843, # 2272
+3226,4291,4621,3719,1687, 950,2479, 426, 469,3227,3720,3721,4031,5265,5266,1188, # 2288
+ 424,1996, 861,3601,4292,3854,2205,2694, 168,1235,3602,4293,5267,2087,1674,4622, # 2304
+3374,3303, 220,2565,1009,5268,3855, 670,3010, 332,1208, 717,5269,5270,3603,2452, # 2320
+4032,3375,5271, 513,5272,1209,2882,3376,3163,4623,1080,5273,5274,5275,5276,2534, # 2336
+3722,3604, 815,1587,4033,4034,5277,3605,3486,3856,1254,4624,1328,3058,1390,4035, # 2352
+1741,4036,3857,4037,5278, 236,3858,2453,3304,5279,5280,3723,3859,1273,3860,4625, # 2368
+5281, 308,5282,4626, 245,4627,1852,2480,1307,2583, 430, 715,2137,2454,5283, 270, # 2384
+ 199,2883,4038,5284,3606,2727,1753, 761,1754, 725,1661,1841,4628,3487,3724,5285, # 2400
+5286, 587,  14,3305, 227,2608, 326, 480,2270, 943,2765,3607, 291, 650,1884,5287, # 2416
+1702,1226, 102,1547,  62,3488, 904,4629,3489,1164,4294,5288,5289,1224,1548,2766, # 2432
+ 391, 498,1493,5290,1386,1419,5291,2056,1177,4630, 813, 880,1081,2368, 566,1145, # 2448
+4631,2291,1001,1035,2566,2609,2242, 394,1286,5292,5293,2069,5294,  86,1494,1730, # 2464
+4039, 491,1588, 745, 897,2963, 843,3377,4040,2767,2884,3306,1768, 998,2221,2070, # 2480
+ 397,1827,1195,1970,3725,3011,3378, 284,5295,3861,2507,2138,2120,1904,5296,4041, # 2496
+2151,4042,4295,1036,3490,1905, 114,2567,4296, 209,1527,5297,5298,2964,2844,2635, # 2512
+2390,2728,3164, 812,2568,5299,3307,5300,1559, 737,1885,3726,1210, 885,  28,2695, # 2528
+3608,3862,5301,4297,1004,1780,4632,5302, 346,1982,2222,2696,4633,3863,1742, 797, # 2544
+1642,4043,1934,1072,1384,2152, 896,4044,3308,3727,3228,2885,3609,5303,2569,1959, # 2560
+4634,2455,1786,5304,5305,5306,4045,4298,1005,1308,3728,4299,2729,4635,4636,1528, # 2576
+2610, 161,1178,4300,1983, 987,4637,1101,4301, 631,4046,1157,3229,2425,1343,1241, # 2592
+1016,2243,2570, 372, 877,2344,2508,1160, 555,1935, 911,4047,5307, 466,1170, 169, # 2608
+1051,2921,2697,3729,2481,3012,1182,2012,2571,1251,2636,5308, 992,2345,3491,1540, # 2624
+2730,1201,2071,2406,1997,2482,5309,4638, 528,1923,2191,1503,1874,1570,2369,3379, # 2640
+3309,5310, 557,1073,5311,1828,3492,2088,2271,3165,3059,3107, 767,3108,2799,4639, # 2656
+1006,4302,4640,2346,1267,2179,3730,3230, 778,4048,3231,2731,1597,2667,5312,4641, # 2672
+5313,3493,5314,5315,5316,3310,2698,1433,3311, 131,  95,1504,4049, 723,4303,3166, # 2688
+1842,3610,2768,2192,4050,2028,2105,3731,5317,3013,4051,1218,5318,3380,3232,4052, # 2704
+4304,2584, 248,1634,3864, 912,5319,2845,3732,3060,3865, 654,  53,5320,3014,5321, # 2720
+1688,4642, 777,3494,1032,4053,1425,5322, 191, 820,2121,2846, 971,4643, 931,3233, # 2736
+ 135, 664, 783,3866,1998, 772,2922,1936,4054,3867,4644,2923,3234, 282,2732, 640, # 2752
+1372,3495,1127, 922, 325,3381,5323,5324, 711,2045,5325,5326,4055,2223,2800,1937, # 2768
+4056,3382,2224,2255,3868,2305,5327,4645,3869,1258,3312,4057,3235,2139,2965,4058, # 2784
+4059,5328,2225, 258,3236,4646, 101,1227,5329,3313,1755,5330,1391,3314,5331,2924, # 2800
+2057, 893,5332,5333,5334,1402,4305,2347,5335,5336,3237,3611,5337,5338, 878,1325, # 2816
+1781,2801,4647, 259,1385,2585, 744,1183,2272,4648,5339,4060,2509,5340, 684,1024, # 2832
+4306,5341, 472,3612,3496,1165,3315,4061,4062, 322,2153, 881, 455,1695,1152,1340, # 2848
+ 660, 554,2154,4649,1058,4650,4307, 830,1065,3383,4063,4651,1924,5342,1703,1919, # 2864
+5343, 932,2273, 122,5344,4652, 947, 677,5345,3870,2637, 297,1906,1925,2274,4653, # 2880
+2322,3316,5346,5347,4308,5348,4309,  84,4310, 112, 989,5349, 547,1059,4064, 701, # 2896
+3613,1019,5350,4311,5351,3497, 942, 639, 457,2306,2456, 993,2966, 407, 851, 494, # 2912
+4654,3384, 927,5352,1237,5353,2426,3385, 573,4312, 680, 921,2925,1279,1875, 285, # 2928
+ 790,1448,1984, 719,2168,5354,5355,4655,4065,4066,1649,5356,1541, 563,5357,1077, # 2944
+5358,3386,3061,3498, 511,3015,4067,4068,3733,4069,1268,2572,3387,3238,4656,4657, # 2960
+5359, 535,1048,1276,1189,2926,2029,3167,1438,1373,2847,2967,1134,2013,5360,4313, # 2976
+1238,2586,3109,1259,5361, 700,5362,2968,3168,3734,4314,5363,4315,1146,1876,1907, # 2992
+4658,2611,4070, 781,2427, 132,1589, 203, 147, 273,2802,2407, 898,1787,2155,4071, # 3008
+4072,5364,3871,2803,5365,5366,4659,4660,5367,3239,5368,1635,3872, 965,5369,1805, # 3024
+2699,1516,3614,1121,1082,1329,3317,4073,1449,3873,  65,1128,2848,2927,2769,1590, # 3040
+3874,5370,5371,  12,2668,  45, 976,2587,3169,4661, 517,2535,1013,1037,3240,5372, # 3056
+3875,2849,5373,3876,5374,3499,5375,2612, 614,1999,2323,3877,3110,2733,2638,5376, # 3072
+2588,4316, 599,1269,5377,1811,3735,5378,2700,3111, 759,1060, 489,1806,3388,3318, # 3088
+1358,5379,5380,2391,1387,1215,2639,2256, 490,5381,5382,4317,1759,2392,2348,5383, # 3104
+4662,3878,1908,4074,2640,1807,3241,4663,3500,3319,2770,2349, 874,5384,5385,3501, # 3120
+3736,1859,  91,2928,3737,3062,3879,4664,5386,3170,4075,2669,5387,3502,1202,1403, # 3136
+3880,2969,2536,1517,2510,4665,3503,2511,5388,4666,5389,2701,1886,1495,1731,4076, # 3152
+2370,4667,5390,2030,5391,5392,4077,2702,1216, 237,2589,4318,2324,4078,3881,4668, # 3168
+4669,2703,3615,3504, 445,4670,5393,5394,5395,5396,2771,  61,4079,3738,1823,4080, # 3184
+5397, 687,2046, 935, 925, 405,2670, 703,1096,1860,2734,4671,4081,1877,1367,2704, # 3200
+3389, 918,2106,1782,2483, 334,3320,1611,1093,4672, 564,3171,3505,3739,3390, 945, # 3216
+2641,2058,4673,5398,1926, 872,4319,5399,3506,2705,3112, 349,4320,3740,4082,4674, # 3232
+3882,4321,3741,2156,4083,4675,4676,4322,4677,2408,2047, 782,4084, 400, 251,4323, # 3248
+1624,5400,5401, 277,3742, 299,1265, 476,1191,3883,2122,4324,4325,1109, 205,5402, # 3264
+2590,1000,2157,3616,1861,5403,5404,5405,4678,5406,4679,2573, 107,2484,2158,4085, # 3280
+3507,3172,5407,1533, 541,1301, 158, 753,4326,2886,3617,5408,1696, 370,1088,4327, # 3296
+4680,3618, 579, 327, 440, 162,2244, 269,1938,1374,3508, 968,3063,  56,1396,3113, # 3312
+2107,3321,3391,5409,1927,2159,4681,3016,5410,3619,5411,5412,3743,4682,2485,5413, # 3328
+2804,5414,1650,4683,5415,2613,5416,5417,4086,2671,3392,1149,3393,4087,3884,4088, # 3344
+5418,1076,  49,5419, 951,3242,3322,3323, 450,2850, 920,5420,1812,2805,2371,4328, # 3360
+1909,1138,2372,3885,3509,5421,3243,4684,1910,1147,1518,2428,4685,3886,5422,4686, # 3376
+2393,2614, 260,1796,3244,5423,5424,3887,3324, 708,5425,3620,1704,5426,3621,1351, # 3392
+1618,3394,3017,1887, 944,4329,3395,4330,3064,3396,4331,5427,3744, 422, 413,1714, # 3408
+3325, 500,2059,2350,4332,2486,5428,1344,1911, 954,5429,1668,5430,5431,4089,2409, # 3424
+4333,3622,3888,4334,5432,2307,1318,2512,3114, 133,3115,2887,4687, 629,  31,2851, # 3440
+2706,3889,4688, 850, 949,4689,4090,2970,1732,2089,4335,1496,1853,5433,4091, 620, # 3456
+3245, 981,1242,3745,3397,1619,3746,1643,3326,2140,2457,1971,1719,3510,2169,5434, # 3472
+3246,5435,5436,3398,1829,5437,1277,4690,1565,2048,5438,1636,3623,3116,5439, 869, # 3488
+2852, 655,3890,3891,3117,4092,3018,3892,1310,3624,4691,5440,5441,5442,1733, 558, # 3504
+4692,3747, 335,1549,3065,1756,4336,3748,1946,3511,1830,1291,1192, 470,2735,2108, # 3520
+2806, 913,1054,4093,5443,1027,5444,3066,4094,4693, 982,2672,3399,3173,3512,3247, # 3536
+3248,1947,2807,5445, 571,4694,5446,1831,5447,3625,2591,1523,2429,5448,2090, 984, # 3552
+4695,3749,1960,5449,3750, 852, 923,2808,3513,3751, 969,1519, 999,2049,2325,1705, # 3568
+5450,3118, 615,1662, 151, 597,4095,2410,2326,1049, 275,4696,3752,4337, 568,3753, # 3584
+3626,2487,4338,3754,5451,2430,2275, 409,3249,5452,1566,2888,3514,1002, 769,2853, # 3600
+ 194,2091,3174,3755,2226,3327,4339, 628,1505,5453,5454,1763,2180,3019,4096, 521, # 3616
+1161,2592,1788,2206,2411,4697,4097,1625,4340,4341, 412,  42,3119, 464,5455,2642, # 3632
+4698,3400,1760,1571,2889,3515,2537,1219,2207,3893,2643,2141,2373,4699,4700,3328, # 3648
+1651,3401,3627,5456,5457,3628,2488,3516,5458,3756,5459,5460,2276,2092, 460,5461, # 3664
+4701,5462,3020, 962, 588,3629, 289,3250,2644,1116,  52,5463,3067,1797,5464,5465, # 3680
+5466,1467,5467,1598,1143,3757,4342,1985,1734,1067,4702,1280,3402, 465,4703,1572, # 3696
+ 510,5468,1928,2245,1813,1644,3630,5469,4704,3758,5470,5471,2673,1573,1534,5472, # 3712
+5473, 536,1808,1761,3517,3894,3175,2645,5474,5475,5476,4705,3518,2929,1912,2809, # 3728
+5477,3329,1122, 377,3251,5478, 360,5479,5480,4343,1529, 551,5481,2060,3759,1769, # 3744
+2431,5482,2930,4344,3330,3120,2327,2109,2031,4706,1404, 136,1468,1479, 672,1171, # 3760
+3252,2308, 271,3176,5483,2772,5484,2050, 678,2736, 865,1948,4707,5485,2014,4098, # 3776
+2971,5486,2737,2227,1397,3068,3760,4708,4709,1735,2931,3403,3631,5487,3895, 509, # 3792
+2854,2458,2890,3896,5488,5489,3177,3178,4710,4345,2538,4711,2309,1166,1010, 552, # 3808
+ 681,1888,5490,5491,2972,2973,4099,1287,1596,1862,3179, 358, 453, 736, 175, 478, # 3824
+1117, 905,1167,1097,5492,1854,1530,5493,1706,5494,2181,3519,2292,3761,3520,3632, # 3840
+4346,2093,4347,5495,3404,1193,2489,4348,1458,2193,2208,1863,1889,1421,3331,2932, # 3856
+3069,2182,3521, 595,2123,5496,4100,5497,5498,4349,1707,2646, 223,3762,1359, 751, # 3872
+3121, 183,3522,5499,2810,3021, 419,2374, 633, 704,3897,2394, 241,5500,5501,5502, # 3888
+ 838,3022,3763,2277,2773,2459,3898,1939,2051,4101,1309,3122,2246,1181,5503,1136, # 3904
+2209,3899,2375,1446,4350,2310,4712,5504,5505,4351,1055,2615, 484,3764,5506,4102, # 3920
+ 625,4352,2278,3405,1499,4353,4103,5507,4104,4354,3253,2279,2280,3523,5508,5509, # 3936
+2774, 808,2616,3765,3406,4105,4355,3123,2539, 526,3407,3900,4356, 955,5510,1620, # 3952
+4357,2647,2432,5511,1429,3766,1669,1832, 994, 928,5512,3633,1260,5513,5514,5515, # 3968
+1949,2293, 741,2933,1626,4358,2738,2460, 867,1184, 362,3408,1392,5516,5517,4106, # 3984
+4359,1770,1736,3254,2934,4713,4714,1929,2707,1459,1158,5518,3070,3409,2891,1292, # 4000
+1930,2513,2855,3767,1986,1187,2072,2015,2617,4360,5519,2574,2514,2170,3768,2490, # 4016
+3332,5520,3769,4715,5521,5522, 666,1003,3023,1022,3634,4361,5523,4716,1814,2257, # 4032
+ 574,3901,1603, 295,1535, 705,3902,4362, 283, 858, 417,5524,5525,3255,4717,4718, # 4048
+3071,1220,1890,1046,2281,2461,4107,1393,1599, 689,2575, 388,4363,5526,2491, 802, # 4064
+5527,2811,3903,2061,1405,2258,5528,4719,3904,2110,1052,1345,3256,1585,5529, 809, # 4080
+5530,5531,5532, 575,2739,3524, 956,1552,1469,1144,2328,5533,2329,1560,2462,3635, # 4096
+3257,4108, 616,2210,4364,3180,2183,2294,5534,1833,5535,3525,4720,5536,1319,3770, # 4112
+3771,1211,3636,1023,3258,1293,2812,5537,5538,5539,3905, 607,2311,3906, 762,2892, # 4128
+1439,4365,1360,4721,1485,3072,5540,4722,1038,4366,1450,2062,2648,4367,1379,4723, # 4144
+2593,5541,5542,4368,1352,1414,2330,2935,1172,5543,5544,3907,3908,4724,1798,1451, # 4160
+5545,5546,5547,5548,2936,4109,4110,2492,2351, 411,4111,4112,3637,3333,3124,4725, # 4176
+1561,2674,1452,4113,1375,5549,5550,  47,2974, 316,5551,1406,1591,2937,3181,5552, # 4192
+1025,2142,3125,3182, 354,2740, 884,2228,4369,2412, 508,3772, 726,3638, 996,2433, # 4208
+3639, 729,5553, 392,2194,1453,4114,4726,3773,5554,5555,2463,3640,2618,1675,2813, # 4224
+ 919,2352,2975,2353,1270,4727,4115,  73,5556,5557, 647,5558,3259,2856,2259,1550, # 4240
+1346,3024,5559,1332, 883,3526,5560,5561,5562,5563,3334,2775,5564,1212, 831,1347, # 4256
+4370,4728,2331,3909,1864,3073, 720,3910,4729,4730,3911,5565,4371,5566,5567,4731, # 4272
+5568,5569,1799,4732,3774,2619,4733,3641,1645,2376,4734,5570,2938, 669,2211,2675, # 4288
+2434,5571,2893,5572,5573,1028,3260,5574,4372,2413,5575,2260,1353,5576,5577,4735, # 4304
+3183, 518,5578,4116,5579,4373,1961,5580,2143,4374,5581,5582,3025,2354,2355,3912, # 4320
+ 516,1834,1454,4117,2708,4375,4736,2229,2620,1972,1129,3642,5583,2776,5584,2976, # 4336
+1422, 577,1470,3026,1524,3410,5585,5586, 432,4376,3074,3527,5587,2594,1455,2515, # 4352
+2230,1973,1175,5588,1020,2741,4118,3528,4737,5589,2742,5590,1743,1361,3075,3529, # 4368
+2649,4119,4377,4738,2295, 895, 924,4378,2171, 331,2247,3076, 166,1627,3077,1098, # 4384
+5591,1232,2894,2231,3411,4739, 657, 403,1196,2377, 542,3775,3412,1600,4379,3530, # 4400
+5592,4740,2777,3261, 576, 530,1362,4741,4742,2540,2676,3776,4120,5593, 842,3913, # 4416
+5594,2814,2032,1014,4121, 213,2709,3413, 665, 621,4380,5595,3777,2939,2435,5596, # 4432
+2436,3335,3643,3414,4743,4381,2541,4382,4744,3644,1682,4383,3531,1380,5597, 724, # 4448
+2282, 600,1670,5598,1337,1233,4745,3126,2248,5599,1621,4746,5600, 651,4384,5601, # 4464
+1612,4385,2621,5602,2857,5603,2743,2312,3078,5604, 716,2464,3079, 174,1255,2710, # 4480
+4122,3645, 548,1320,1398, 728,4123,1574,5605,1891,1197,3080,4124,5606,3081,3082, # 4496
+3778,3646,3779, 747,5607, 635,4386,4747,5608,5609,5610,4387,5611,5612,4748,5613, # 4512
+3415,4749,2437, 451,5614,3780,2542,2073,4388,2744,4389,4125,5615,1764,4750,5616, # 4528
+4390, 350,4751,2283,2395,2493,5617,4391,4126,2249,1434,4127, 488,4752, 458,4392, # 4544
+4128,3781, 771,1330,2396,3914,2576,3184,2160,2414,1553,2677,3185,4393,5618,2494, # 4560
+2895,2622,1720,2711,4394,3416,4753,5619,2543,4395,5620,3262,4396,2778,5621,2016, # 4576
+2745,5622,1155,1017,3782,3915,5623,3336,2313, 201,1865,4397,1430,5624,4129,5625, # 4592
+5626,5627,5628,5629,4398,1604,5630, 414,1866, 371,2595,4754,4755,3532,2017,3127, # 4608
+4756,1708, 960,4399, 887, 389,2172,1536,1663,1721,5631,2232,4130,2356,2940,1580, # 4624
+5632,5633,1744,4757,2544,4758,4759,5634,4760,5635,2074,5636,4761,3647,3417,2896, # 4640
+4400,5637,4401,2650,3418,2815, 673,2712,2465, 709,3533,4131,3648,4402,5638,1148, # 4656
+ 502, 634,5639,5640,1204,4762,3649,1575,4763,2623,3783,5641,3784,3128, 948,3263, # 4672
+ 121,1745,3916,1110,5642,4403,3083,2516,3027,4132,3785,1151,1771,3917,1488,4133, # 4688
+1987,5643,2438,3534,5644,5645,2094,5646,4404,3918,1213,1407,2816, 531,2746,2545, # 4704
+3264,1011,1537,4764,2779,4405,3129,1061,5647,3786,3787,1867,2897,5648,2018, 120, # 4720
+4406,4407,2063,3650,3265,2314,3919,2678,3419,1955,4765,4134,5649,3535,1047,2713, # 4736
+1266,5650,1368,4766,2858, 649,3420,3920,2546,2747,1102,2859,2679,5651,5652,2000, # 4752
+5653,1111,3651,2977,5654,2495,3921,3652,2817,1855,3421,3788,5655,5656,3422,2415, # 4768
+2898,3337,3266,3653,5657,2577,5658,3654,2818,4135,1460, 856,5659,3655,5660,2899, # 4784
+2978,5661,2900,3922,5662,4408, 632,2517, 875,3923,1697,3924,2296,5663,5664,4767, # 4800
+3028,1239, 580,4768,4409,5665, 914, 936,2075,1190,4136,1039,2124,5666,5667,5668, # 4816
+5669,3423,1473,5670,1354,4410,3925,4769,2173,3084,4137, 915,3338,4411,4412,3339, # 4832
+1605,1835,5671,2748, 398,3656,4413,3926,4138, 328,1913,2860,4139,3927,1331,4414, # 4848
+3029, 937,4415,5672,3657,4140,4141,3424,2161,4770,3425, 524, 742, 538,3085,1012, # 4864
+5673,5674,3928,2466,5675, 658,1103, 225,3929,5676,5677,4771,5678,4772,5679,3267, # 4880
+1243,5680,4142, 963,2250,4773,5681,2714,3658,3186,5682,5683,2596,2332,5684,4774, # 4896
+5685,5686,5687,3536, 957,3426,2547,2033,1931,2941,2467, 870,2019,3659,1746,2780, # 4912
+2781,2439,2468,5688,3930,5689,3789,3130,3790,3537,3427,3791,5690,1179,3086,5691, # 4928
+3187,2378,4416,3792,2548,3188,3131,2749,4143,5692,3428,1556,2549,2297, 977,2901, # 4944
+2034,4144,1205,3429,5693,1765,3430,3189,2125,1271, 714,1689,4775,3538,5694,2333, # 4960
+3931, 533,4417,3660,2184, 617,5695,2469,3340,3539,2315,5696,5697,3190,5698,5699, # 4976
+3932,1988, 618, 427,2651,3540,3431,5700,5701,1244,1690,5702,2819,4418,4776,5703, # 4992
+3541,4777,5704,2284,1576, 473,3661,4419,3432, 972,5705,3662,5706,3087,5707,5708, # 5008
+4778,4779,5709,3793,4145,4146,5710, 153,4780, 356,5711,1892,2902,4420,2144, 408, # 5024
+ 803,2357,5712,3933,5713,4421,1646,2578,2518,4781,4782,3934,5714,3935,4422,5715, # 5040
+2416,3433, 752,5716,5717,1962,3341,2979,5718, 746,3030,2470,4783,4423,3794, 698, # 5056
+4784,1893,4424,3663,2550,4785,3664,3936,5719,3191,3434,5720,1824,1302,4147,2715, # 5072
+3937,1974,4425,5721,4426,3192, 823,1303,1288,1236,2861,3542,4148,3435, 774,3938, # 5088
+5722,1581,4786,1304,2862,3939,4787,5723,2440,2162,1083,3268,4427,4149,4428, 344, # 5104
+1173, 288,2316, 454,1683,5724,5725,1461,4788,4150,2597,5726,5727,4789, 985, 894, # 5120
+5728,3436,3193,5729,1914,2942,3795,1989,5730,2111,1975,5731,4151,5732,2579,1194, # 5136
+ 425,5733,4790,3194,1245,3796,4429,5734,5735,2863,5736, 636,4791,1856,3940, 760, # 5152
+1800,5737,4430,2212,1508,4792,4152,1894,1684,2298,5738,5739,4793,4431,4432,2213, # 5168
+ 479,5740,5741, 832,5742,4153,2496,5743,2980,2497,3797, 990,3132, 627,1815,2652, # 5184
+4433,1582,4434,2126,2112,3543,4794,5744, 799,4435,3195,5745,4795,2113,1737,3031, # 5200
+1018, 543, 754,4436,3342,1676,4796,4797,4154,4798,1489,5746,3544,5747,2624,2903, # 5216
+4155,5748,5749,2981,5750,5751,5752,5753,3196,4799,4800,2185,1722,5754,3269,3270, # 5232
+1843,3665,1715, 481, 365,1976,1857,5755,5756,1963,2498,4801,5757,2127,3666,3271, # 5248
+ 433,1895,2064,2076,5758, 602,2750,5759,5760,5761,5762,5763,3032,1628,3437,5764, # 5264
+3197,4802,4156,2904,4803,2519,5765,2551,2782,5766,5767,5768,3343,4804,2905,5769, # 5280
+4805,5770,2864,4806,4807,1221,2982,4157,2520,5771,5772,5773,1868,1990,5774,5775, # 5296
+5776,1896,5777,5778,4808,1897,4158, 318,5779,2095,4159,4437,5780,5781, 485,5782, # 5312
+ 938,3941, 553,2680, 116,5783,3942,3667,5784,3545,2681,2783,3438,3344,2820,5785, # 5328
+3668,2943,4160,1747,2944,2983,5786,5787, 207,5788,4809,5789,4810,2521,5790,3033, # 5344
+ 890,3669,3943,5791,1878,3798,3439,5792,2186,2358,3440,1652,5793,5794,5795, 941, # 5360
+2299, 208,3546,4161,2020, 330,4438,3944,2906,2499,3799,4439,4811,5796,5797,5798, # 5376  #last 512
+#Everything below is of no interest for detection purpose
+2522,1613,4812,5799,3345,3945,2523,5800,4162,5801,1637,4163,2471,4813,3946,5802, # 5392
+2500,3034,3800,5803,5804,2195,4814,5805,2163,5806,5807,5808,5809,5810,5811,5812, # 5408
+5813,5814,5815,5816,5817,5818,5819,5820,5821,5822,5823,5824,5825,5826,5827,5828, # 5424
+5829,5830,5831,5832,5833,5834,5835,5836,5837,5838,5839,5840,5841,5842,5843,5844, # 5440
+5845,5846,5847,5848,5849,5850,5851,5852,5853,5854,5855,5856,5857,5858,5859,5860, # 5456
+5861,5862,5863,5864,5865,5866,5867,5868,5869,5870,5871,5872,5873,5874,5875,5876, # 5472
+5877,5878,5879,5880,5881,5882,5883,5884,5885,5886,5887,5888,5889,5890,5891,5892, # 5488
+5893,5894,5895,5896,5897,5898,5899,5900,5901,5902,5903,5904,5905,5906,5907,5908, # 5504
+5909,5910,5911,5912,5913,5914,5915,5916,5917,5918,5919,5920,5921,5922,5923,5924, # 5520
+5925,5926,5927,5928,5929,5930,5931,5932,5933,5934,5935,5936,5937,5938,5939,5940, # 5536
+5941,5942,5943,5944,5945,5946,5947,5948,5949,5950,5951,5952,5953,5954,5955,5956, # 5552
+5957,5958,5959,5960,5961,5962,5963,5964,5965,5966,5967,5968,5969,5970,5971,5972, # 5568
+5973,5974,5975,5976,5977,5978,5979,5980,5981,5982,5983,5984,5985,5986,5987,5988, # 5584
+5989,5990,5991,5992,5993,5994,5995,5996,5997,5998,5999,6000,6001,6002,6003,6004, # 5600
+6005,6006,6007,6008,6009,6010,6011,6012,6013,6014,6015,6016,6017,6018,6019,6020, # 5616
+6021,6022,6023,6024,6025,6026,6027,6028,6029,6030,6031,6032,6033,6034,6035,6036, # 5632
+6037,6038,6039,6040,6041,6042,6043,6044,6045,6046,6047,6048,6049,6050,6051,6052, # 5648
+6053,6054,6055,6056,6057,6058,6059,6060,6061,6062,6063,6064,6065,6066,6067,6068, # 5664
+6069,6070,6071,6072,6073,6074,6075,6076,6077,6078,6079,6080,6081,6082,6083,6084, # 5680
+6085,6086,6087,6088,6089,6090,6091,6092,6093,6094,6095,6096,6097,6098,6099,6100, # 5696
+6101,6102,6103,6104,6105,6106,6107,6108,6109,6110,6111,6112,6113,6114,6115,6116, # 5712
+6117,6118,6119,6120,6121,6122,6123,6124,6125,6126,6127,6128,6129,6130,6131,6132, # 5728
+6133,6134,6135,6136,6137,6138,6139,6140,6141,6142,6143,6144,6145,6146,6147,6148, # 5744
+6149,6150,6151,6152,6153,6154,6155,6156,6157,6158,6159,6160,6161,6162,6163,6164, # 5760
+6165,6166,6167,6168,6169,6170,6171,6172,6173,6174,6175,6176,6177,6178,6179,6180, # 5776
+6181,6182,6183,6184,6185,6186,6187,6188,6189,6190,6191,6192,6193,6194,6195,6196, # 5792
+6197,6198,6199,6200,6201,6202,6203,6204,6205,6206,6207,6208,6209,6210,6211,6212, # 5808
+6213,6214,6215,6216,6217,6218,6219,6220,6221,6222,6223,3670,6224,6225,6226,6227, # 5824
+6228,6229,6230,6231,6232,6233,6234,6235,6236,6237,6238,6239,6240,6241,6242,6243, # 5840
+6244,6245,6246,6247,6248,6249,6250,6251,6252,6253,6254,6255,6256,6257,6258,6259, # 5856
+6260,6261,6262,6263,6264,6265,6266,6267,6268,6269,6270,6271,6272,6273,6274,6275, # 5872
+6276,6277,6278,6279,6280,6281,6282,6283,6284,6285,4815,6286,6287,6288,6289,6290, # 5888
+6291,6292,4816,6293,6294,6295,6296,6297,6298,6299,6300,6301,6302,6303,6304,6305, # 5904
+6306,6307,6308,6309,6310,6311,4817,4818,6312,6313,6314,6315,6316,6317,6318,4819, # 5920
+6319,6320,6321,6322,6323,6324,6325,6326,6327,6328,6329,6330,6331,6332,6333,6334, # 5936
+6335,6336,6337,4820,6338,6339,6340,6341,6342,6343,6344,6345,6346,6347,6348,6349, # 5952
+6350,6351,6352,6353,6354,6355,6356,6357,6358,6359,6360,6361,6362,6363,6364,6365, # 5968
+6366,6367,6368,6369,6370,6371,6372,6373,6374,6375,6376,6377,6378,6379,6380,6381, # 5984
+6382,6383,6384,6385,6386,6387,6388,6389,6390,6391,6392,6393,6394,6395,6396,6397, # 6000
+6398,6399,6400,6401,6402,6403,6404,6405,6406,6407,6408,6409,6410,3441,6411,6412, # 6016
+6413,6414,6415,6416,6417,6418,6419,6420,6421,6422,6423,6424,6425,4440,6426,6427, # 6032
+6428,6429,6430,6431,6432,6433,6434,6435,6436,6437,6438,6439,6440,6441,6442,6443, # 6048
+6444,6445,6446,6447,6448,6449,6450,6451,6452,6453,6454,4821,6455,6456,6457,6458, # 6064
+6459,6460,6461,6462,6463,6464,6465,6466,6467,6468,6469,6470,6471,6472,6473,6474, # 6080
+6475,6476,6477,3947,3948,6478,6479,6480,6481,3272,4441,6482,6483,6484,6485,4442, # 6096
+6486,6487,6488,6489,6490,6491,6492,6493,6494,6495,6496,4822,6497,6498,6499,6500, # 6112
+6501,6502,6503,6504,6505,6506,6507,6508,6509,6510,6511,6512,6513,6514,6515,6516, # 6128
+6517,6518,6519,6520,6521,6522,6523,6524,6525,6526,6527,6528,6529,6530,6531,6532, # 6144
+6533,6534,6535,6536,6537,6538,6539,6540,6541,6542,6543,6544,6545,6546,6547,6548, # 6160
+6549,6550,6551,6552,6553,6554,6555,6556,2784,6557,4823,6558,6559,6560,6561,6562, # 6176
+6563,6564,6565,6566,6567,6568,6569,3949,6570,6571,6572,4824,6573,6574,6575,6576, # 6192
+6577,6578,6579,6580,6581,6582,6583,4825,6584,6585,6586,3950,2785,6587,6588,6589, # 6208
+6590,6591,6592,6593,6594,6595,6596,6597,6598,6599,6600,6601,6602,6603,6604,6605, # 6224
+6606,6607,6608,6609,6610,6611,6612,4826,6613,6614,6615,4827,6616,6617,6618,6619, # 6240
+6620,6621,6622,6623,6624,6625,4164,6626,6627,6628,6629,6630,6631,6632,6633,6634, # 6256
+3547,6635,4828,6636,6637,6638,6639,6640,6641,6642,3951,2984,6643,6644,6645,6646, # 6272
+6647,6648,6649,4165,6650,4829,6651,6652,4830,6653,6654,6655,6656,6657,6658,6659, # 6288
+6660,6661,6662,4831,6663,6664,6665,6666,6667,6668,6669,6670,6671,4166,6672,4832, # 6304
+3952,6673,6674,6675,6676,4833,6677,6678,6679,4167,6680,6681,6682,3198,6683,6684, # 6320
+6685,6686,6687,6688,6689,6690,6691,6692,6693,6694,6695,6696,6697,4834,6698,6699, # 6336
+6700,6701,6702,6703,6704,6705,6706,6707,6708,6709,6710,6711,6712,6713,6714,6715, # 6352
+6716,6717,6718,6719,6720,6721,6722,6723,6724,6725,6726,6727,6728,6729,6730,6731, # 6368
+6732,6733,6734,4443,6735,6736,6737,6738,6739,6740,6741,6742,6743,6744,6745,4444, # 6384
+6746,6747,6748,6749,6750,6751,6752,6753,6754,6755,6756,6757,6758,6759,6760,6761, # 6400
+6762,6763,6764,6765,6766,6767,6768,6769,6770,6771,6772,6773,6774,6775,6776,6777, # 6416
+6778,6779,6780,6781,4168,6782,6783,3442,6784,6785,6786,6787,6788,6789,6790,6791, # 6432
+4169,6792,6793,6794,6795,6796,6797,6798,6799,6800,6801,6802,6803,6804,6805,6806, # 6448
+6807,6808,6809,6810,6811,4835,6812,6813,6814,4445,6815,6816,4446,6817,6818,6819, # 6464
+6820,6821,6822,6823,6824,6825,6826,6827,6828,6829,6830,6831,6832,6833,6834,6835, # 6480
+3548,6836,6837,6838,6839,6840,6841,6842,6843,6844,6845,6846,4836,6847,6848,6849, # 6496
+6850,6851,6852,6853,6854,3953,6855,6856,6857,6858,6859,6860,6861,6862,6863,6864, # 6512
+6865,6866,6867,6868,6869,6870,6871,6872,6873,6874,6875,6876,6877,3199,6878,6879, # 6528
+6880,6881,6882,4447,6883,6884,6885,6886,6887,6888,6889,6890,6891,6892,6893,6894, # 6544
+6895,6896,6897,6898,6899,6900,6901,6902,6903,6904,4170,6905,6906,6907,6908,6909, # 6560
+6910,6911,6912,6913,6914,6915,6916,6917,6918,6919,6920,6921,6922,6923,6924,6925, # 6576
+6926,6927,4837,6928,6929,6930,6931,6932,6933,6934,6935,6936,3346,6937,6938,4838, # 6592
+6939,6940,6941,4448,6942,6943,6944,6945,6946,4449,6947,6948,6949,6950,6951,6952, # 6608
+6953,6954,6955,6956,6957,6958,6959,6960,6961,6962,6963,6964,6965,6966,6967,6968, # 6624
+6969,6970,6971,6972,6973,6974,6975,6976,6977,6978,6979,6980,6981,6982,6983,6984, # 6640
+6985,6986,6987,6988,6989,6990,6991,6992,6993,6994,3671,6995,6996,6997,6998,4839, # 6656
+6999,7000,7001,7002,3549,7003,7004,7005,7006,7007,7008,7009,7010,7011,7012,7013, # 6672
+7014,7015,7016,7017,7018,7019,7020,7021,7022,7023,7024,7025,7026,7027,7028,7029, # 6688
+7030,4840,7031,7032,7033,7034,7035,7036,7037,7038,4841,7039,7040,7041,7042,7043, # 6704
+7044,7045,7046,7047,7048,7049,7050,7051,7052,7053,7054,7055,7056,7057,7058,7059, # 6720
+7060,7061,7062,7063,7064,7065,7066,7067,7068,7069,7070,2985,7071,7072,7073,7074, # 6736
+7075,7076,7077,7078,7079,7080,4842,7081,7082,7083,7084,7085,7086,7087,7088,7089, # 6752
+7090,7091,7092,7093,7094,7095,7096,7097,7098,7099,7100,7101,7102,7103,7104,7105, # 6768
+7106,7107,7108,7109,7110,7111,7112,7113,7114,7115,7116,7117,7118,4450,7119,7120, # 6784
+7121,7122,7123,7124,7125,7126,7127,7128,7129,7130,7131,7132,7133,7134,7135,7136, # 6800
+7137,7138,7139,7140,7141,7142,7143,4843,7144,7145,7146,7147,7148,7149,7150,7151, # 6816
+7152,7153,7154,7155,7156,7157,7158,7159,7160,7161,7162,7163,7164,7165,7166,7167, # 6832
+7168,7169,7170,7171,7172,7173,7174,7175,7176,7177,7178,7179,7180,7181,7182,7183, # 6848
+7184,7185,7186,7187,7188,4171,4172,7189,7190,7191,7192,7193,7194,7195,7196,7197, # 6864
+7198,7199,7200,7201,7202,7203,7204,7205,7206,7207,7208,7209,7210,7211,7212,7213, # 6880
+7214,7215,7216,7217,7218,7219,7220,7221,7222,7223,7224,7225,7226,7227,7228,7229, # 6896
+7230,7231,7232,7233,7234,7235,7236,7237,7238,7239,7240,7241,7242,7243,7244,7245, # 6912
+7246,7247,7248,7249,7250,7251,7252,7253,7254,7255,7256,7257,7258,7259,7260,7261, # 6928
+7262,7263,7264,7265,7266,7267,7268,7269,7270,7271,7272,7273,7274,7275,7276,7277, # 6944
+7278,7279,7280,7281,7282,7283,7284,7285,7286,7287,7288,7289,7290,7291,7292,7293, # 6960
+7294,7295,7296,4844,7297,7298,7299,7300,7301,7302,7303,7304,7305,7306,7307,7308, # 6976
+7309,7310,7311,7312,7313,7314,7315,7316,4451,7317,7318,7319,7320,7321,7322,7323, # 6992
+7324,7325,7326,7327,7328,7329,7330,7331,7332,7333,7334,7335,7336,7337,7338,7339, # 7008
+7340,7341,7342,7343,7344,7345,7346,7347,7348,7349,7350,7351,7352,7353,4173,7354, # 7024
+7355,4845,7356,7357,7358,7359,7360,7361,7362,7363,7364,7365,7366,7367,7368,7369, # 7040
+7370,7371,7372,7373,7374,7375,7376,7377,7378,7379,7380,7381,7382,7383,7384,7385, # 7056
+7386,7387,7388,4846,7389,7390,7391,7392,7393,7394,7395,7396,7397,7398,7399,7400, # 7072
+7401,7402,7403,7404,7405,3672,7406,7407,7408,7409,7410,7411,7412,7413,7414,7415, # 7088
+7416,7417,7418,7419,7420,7421,7422,7423,7424,7425,7426,7427,7428,7429,7430,7431, # 7104
+7432,7433,7434,7435,7436,7437,7438,7439,7440,7441,7442,7443,7444,7445,7446,7447, # 7120
+7448,7449,7450,7451,7452,7453,4452,7454,3200,7455,7456,7457,7458,7459,7460,7461, # 7136
+7462,7463,7464,7465,7466,7467,7468,7469,7470,7471,7472,7473,7474,4847,7475,7476, # 7152
+7477,3133,7478,7479,7480,7481,7482,7483,7484,7485,7486,7487,7488,7489,7490,7491, # 7168
+7492,7493,7494,7495,7496,7497,7498,7499,7500,7501,7502,3347,7503,7504,7505,7506, # 7184
+7507,7508,7509,7510,7511,7512,7513,7514,7515,7516,7517,7518,7519,7520,7521,4848, # 7200
+7522,7523,7524,7525,7526,7527,7528,7529,7530,7531,7532,7533,7534,7535,7536,7537, # 7216
+7538,7539,7540,7541,7542,7543,7544,7545,7546,7547,7548,7549,3801,4849,7550,7551, # 7232
+7552,7553,7554,7555,7556,7557,7558,7559,7560,7561,7562,7563,7564,7565,7566,7567, # 7248
+7568,7569,3035,7570,7571,7572,7573,7574,7575,7576,7577,7578,7579,7580,7581,7582, # 7264
+7583,7584,7585,7586,7587,7588,7589,7590,7591,7592,7593,7594,7595,7596,7597,7598, # 7280
+7599,7600,7601,7602,7603,7604,7605,7606,7607,7608,7609,7610,7611,7612,7613,7614, # 7296
+7615,7616,4850,7617,7618,3802,7619,7620,7621,7622,7623,7624,7625,7626,7627,7628, # 7312
+7629,7630,7631,7632,4851,7633,7634,7635,7636,7637,7638,7639,7640,7641,7642,7643, # 7328
+7644,7645,7646,7647,7648,7649,7650,7651,7652,7653,7654,7655,7656,7657,7658,7659, # 7344
+7660,7661,7662,7663,7664,7665,7666,7667,7668,7669,7670,4453,7671,7672,7673,7674, # 7360
+7675,7676,7677,7678,7679,7680,7681,7682,7683,7684,7685,7686,7687,7688,7689,7690, # 7376
+7691,7692,7693,7694,7695,7696,7697,3443,7698,7699,7700,7701,7702,4454,7703,7704, # 7392
+7705,7706,7707,7708,7709,7710,7711,7712,7713,2472,7714,7715,7716,7717,7718,7719, # 7408
+7720,7721,7722,7723,7724,7725,7726,7727,7728,7729,7730,7731,3954,7732,7733,7734, # 7424
+7735,7736,7737,7738,7739,7740,7741,7742,7743,7744,7745,7746,7747,7748,7749,7750, # 7440
+3134,7751,7752,4852,7753,7754,7755,4853,7756,7757,7758,7759,7760,4174,7761,7762, # 7456
+7763,7764,7765,7766,7767,7768,7769,7770,7771,7772,7773,7774,7775,7776,7777,7778, # 7472
+7779,7780,7781,7782,7783,7784,7785,7786,7787,7788,7789,7790,7791,7792,7793,7794, # 7488
+7795,7796,7797,7798,7799,7800,7801,7802,7803,7804,7805,4854,7806,7807,7808,7809, # 7504
+7810,7811,7812,7813,7814,7815,7816,7817,7818,7819,7820,7821,7822,7823,7824,7825, # 7520
+4855,7826,7827,7828,7829,7830,7831,7832,7833,7834,7835,7836,7837,7838,7839,7840, # 7536
+7841,7842,7843,7844,7845,7846,7847,3955,7848,7849,7850,7851,7852,7853,7854,7855, # 7552
+7856,7857,7858,7859,7860,3444,7861,7862,7863,7864,7865,7866,7867,7868,7869,7870, # 7568
+7871,7872,7873,7874,7875,7876,7877,7878,7879,7880,7881,7882,7883,7884,7885,7886, # 7584
+7887,7888,7889,7890,7891,4175,7892,7893,7894,7895,7896,4856,4857,7897,7898,7899, # 7600
+7900,2598,7901,7902,7903,7904,7905,7906,7907,7908,4455,7909,7910,7911,7912,7913, # 7616
+7914,3201,7915,7916,7917,7918,7919,7920,7921,4858,7922,7923,7924,7925,7926,7927, # 7632
+7928,7929,7930,7931,7932,7933,7934,7935,7936,7937,7938,7939,7940,7941,7942,7943, # 7648
+7944,7945,7946,7947,7948,7949,7950,7951,7952,7953,7954,7955,7956,7957,7958,7959, # 7664
+7960,7961,7962,7963,7964,7965,7966,7967,7968,7969,7970,7971,7972,7973,7974,7975, # 7680
+7976,7977,7978,7979,7980,7981,4859,7982,7983,7984,7985,7986,7987,7988,7989,7990, # 7696
+7991,7992,7993,7994,7995,7996,4860,7997,7998,7999,8000,8001,8002,8003,8004,8005, # 7712
+8006,8007,8008,8009,8010,8011,8012,8013,8014,8015,8016,4176,8017,8018,8019,8020, # 7728
+8021,8022,8023,4861,8024,8025,8026,8027,8028,8029,8030,8031,8032,8033,8034,8035, # 7744
+8036,4862,4456,8037,8038,8039,8040,4863,8041,8042,8043,8044,8045,8046,8047,8048, # 7760
+8049,8050,8051,8052,8053,8054,8055,8056,8057,8058,8059,8060,8061,8062,8063,8064, # 7776
+8065,8066,8067,8068,8069,8070,8071,8072,8073,8074,8075,8076,8077,8078,8079,8080, # 7792
+8081,8082,8083,8084,8085,8086,8087,8088,8089,8090,8091,8092,8093,8094,8095,8096, # 7808
+8097,8098,8099,4864,4177,8100,8101,8102,8103,8104,8105,8106,8107,8108,8109,8110, # 7824
+8111,8112,8113,8114,8115,8116,8117,8118,8119,8120,4178,8121,8122,8123,8124,8125, # 7840
+8126,8127,8128,8129,8130,8131,8132,8133,8134,8135,8136,8137,8138,8139,8140,8141, # 7856
+8142,8143,8144,8145,4865,4866,8146,8147,8148,8149,8150,8151,8152,8153,8154,8155, # 7872
+8156,8157,8158,8159,8160,8161,8162,8163,8164,8165,4179,8166,8167,8168,8169,8170, # 7888
+8171,8172,8173,8174,8175,8176,8177,8178,8179,8180,8181,4457,8182,8183,8184,8185, # 7904
+8186,8187,8188,8189,8190,8191,8192,8193,8194,8195,8196,8197,8198,8199,8200,8201, # 7920
+8202,8203,8204,8205,8206,8207,8208,8209,8210,8211,8212,8213,8214,8215,8216,8217, # 7936
+8218,8219,8220,8221,8222,8223,8224,8225,8226,8227,8228,8229,8230,8231,8232,8233, # 7952
+8234,8235,8236,8237,8238,8239,8240,8241,8242,8243,8244,8245,8246,8247,8248,8249, # 7968
+8250,8251,8252,8253,8254,8255,8256,3445,8257,8258,8259,8260,8261,8262,4458,8263, # 7984
+8264,8265,8266,8267,8268,8269,8270,8271,8272,4459,8273,8274,8275,8276,3550,8277, # 8000
+8278,8279,8280,8281,8282,8283,8284,8285,8286,8287,8288,8289,4460,8290,8291,8292, # 8016
+8293,8294,8295,8296,8297,8298,8299,8300,8301,8302,8303,8304,8305,8306,8307,4867, # 8032
+8308,8309,8310,8311,8312,3551,8313,8314,8315,8316,8317,8318,8319,8320,8321,8322, # 8048
+8323,8324,8325,8326,4868,8327,8328,8329,8330,8331,8332,8333,8334,8335,8336,8337, # 8064
+8338,8339,8340,8341,8342,8343,8344,8345,8346,8347,8348,8349,8350,8351,8352,8353, # 8080
+8354,8355,8356,8357,8358,8359,8360,8361,8362,8363,4869,4461,8364,8365,8366,8367, # 8096
+8368,8369,8370,4870,8371,8372,8373,8374,8375,8376,8377,8378,8379,8380,8381,8382, # 8112
+8383,8384,8385,8386,8387,8388,8389,8390,8391,8392,8393,8394,8395,8396,8397,8398, # 8128
+8399,8400,8401,8402,8403,8404,8405,8406,8407,8408,8409,8410,4871,8411,8412,8413, # 8144
+8414,8415,8416,8417,8418,8419,8420,8421,8422,4462,8423,8424,8425,8426,8427,8428, # 8160
+8429,8430,8431,8432,8433,2986,8434,8435,8436,8437,8438,8439,8440,8441,8442,8443, # 8176
+8444,8445,8446,8447,8448,8449,8450,8451,8452,8453,8454,8455,8456,8457,8458,8459, # 8192
+8460,8461,8462,8463,8464,8465,8466,8467,8468,8469,8470,8471,8472,8473,8474,8475, # 8208
+8476,8477,8478,4180,8479,8480,8481,8482,8483,8484,8485,8486,8487,8488,8489,8490, # 8224
+8491,8492,8493,8494,8495,8496,8497,8498,8499,8500,8501,8502,8503,8504,8505,8506, # 8240
+8507,8508,8509,8510,8511,8512,8513,8514,8515,8516,8517,8518,8519,8520,8521,8522, # 8256
+8523,8524,8525,8526,8527,8528,8529,8530,8531,8532,8533,8534,8535,8536,8537,8538, # 8272
+8539,8540,8541,8542,8543,8544,8545,8546,8547,8548,8549,8550,8551,8552,8553,8554, # 8288
+8555,8556,8557,8558,8559,8560,8561,8562,8563,8564,4872,8565,8566,8567,8568,8569, # 8304
+8570,8571,8572,8573,4873,8574,8575,8576,8577,8578,8579,8580,8581,8582,8583,8584, # 8320
+8585,8586,8587,8588,8589,8590,8591,8592,8593,8594,8595,8596,8597,8598,8599,8600, # 8336
+8601,8602,8603,8604,8605,3803,8606,8607,8608,8609,8610,8611,8612,8613,4874,3804, # 8352
+8614,8615,8616,8617,8618,8619,8620,8621,3956,8622,8623,8624,8625,8626,8627,8628, # 8368
+8629,8630,8631,8632,8633,8634,8635,8636,8637,8638,2865,8639,8640,8641,8642,8643, # 8384
+8644,8645,8646,8647,8648,8649,8650,8651,8652,8653,8654,8655,8656,4463,8657,8658, # 8400
+8659,4875,4876,8660,8661,8662,8663,8664,8665,8666,8667,8668,8669,8670,8671,8672, # 8416
+8673,8674,8675,8676,8677,8678,8679,8680,8681,4464,8682,8683,8684,8685,8686,8687, # 8432
+8688,8689,8690,8691,8692,8693,8694,8695,8696,8697,8698,8699,8700,8701,8702,8703, # 8448
+8704,8705,8706,8707,8708,8709,2261,8710,8711,8712,8713,8714,8715,8716,8717,8718, # 8464
+8719,8720,8721,8722,8723,8724,8725,8726,8727,8728,8729,8730,8731,8732,8733,4181, # 8480
+8734,8735,8736,8737,8738,8739,8740,8741,8742,8743,8744,8745,8746,8747,8748,8749, # 8496
+8750,8751,8752,8753,8754,8755,8756,8757,8758,8759,8760,8761,8762,8763,4877,8764, # 8512
+8765,8766,8767,8768,8769,8770,8771,8772,8773,8774,8775,8776,8777,8778,8779,8780, # 8528
+8781,8782,8783,8784,8785,8786,8787,8788,4878,8789,4879,8790,8791,8792,4880,8793, # 8544
+8794,8795,8796,8797,8798,8799,8800,8801,4881,8802,8803,8804,8805,8806,8807,8808, # 8560
+8809,8810,8811,8812,8813,8814,8815,3957,8816,8817,8818,8819,8820,8821,8822,8823, # 8576
+8824,8825,8826,8827,8828,8829,8830,8831,8832,8833,8834,8835,8836,8837,8838,8839, # 8592
+8840,8841,8842,8843,8844,8845,8846,8847,4882,8848,8849,8850,8851,8852,8853,8854, # 8608
+8855,8856,8857,8858,8859,8860,8861,8862,8863,8864,8865,8866,8867,8868,8869,8870, # 8624
+8871,8872,8873,8874,8875,8876,8877,8878,8879,8880,8881,8882,8883,8884,3202,8885, # 8640
+8886,8887,8888,8889,8890,8891,8892,8893,8894,8895,8896,8897,8898,8899,8900,8901, # 8656
+8902,8903,8904,8905,8906,8907,8908,8909,8910,8911,8912,8913,8914,8915,8916,8917, # 8672
+8918,8919,8920,8921,8922,8923,8924,4465,8925,8926,8927,8928,8929,8930,8931,8932, # 8688
+4883,8933,8934,8935,8936,8937,8938,8939,8940,8941,8942,8943,2214,8944,8945,8946, # 8704
+8947,8948,8949,8950,8951,8952,8953,8954,8955,8956,8957,8958,8959,8960,8961,8962, # 8720
+8963,8964,8965,4884,8966,8967,8968,8969,8970,8971,8972,8973,8974,8975,8976,8977, # 8736
+8978,8979,8980,8981,8982,8983,8984,8985,8986,8987,8988,8989,8990,8991,8992,4885, # 8752
+8993,8994,8995,8996,8997,8998,8999,9000,9001,9002,9003,9004,9005,9006,9007,9008, # 8768
+9009,9010,9011,9012,9013,9014,9015,9016,9017,9018,9019,9020,9021,4182,9022,9023, # 8784
+9024,9025,9026,9027,9028,9029,9030,9031,9032,9033,9034,9035,9036,9037,9038,9039, # 8800
+9040,9041,9042,9043,9044,9045,9046,9047,9048,9049,9050,9051,9052,9053,9054,9055, # 8816
+9056,9057,9058,9059,9060,9061,9062,9063,4886,9064,9065,9066,9067,9068,9069,4887, # 8832
+9070,9071,9072,9073,9074,9075,9076,9077,9078,9079,9080,9081,9082,9083,9084,9085, # 8848
+9086,9087,9088,9089,9090,9091,9092,9093,9094,9095,9096,9097,9098,9099,9100,9101, # 8864
+9102,9103,9104,9105,9106,9107,9108,9109,9110,9111,9112,9113,9114,9115,9116,9117, # 8880
+9118,9119,9120,9121,9122,9123,9124,9125,9126,9127,9128,9129,9130,9131,9132,9133, # 8896
+9134,9135,9136,9137,9138,9139,9140,9141,3958,9142,9143,9144,9145,9146,9147,9148, # 8912
+9149,9150,9151,4888,9152,9153,9154,9155,9156,9157,9158,9159,9160,9161,9162,9163, # 8928
+9164,9165,9166,9167,9168,9169,9170,9171,9172,9173,9174,9175,4889,9176,9177,9178, # 8944
+9179,9180,9181,9182,9183,9184,9185,9186,9187,9188,9189,9190,9191,9192,9193,9194, # 8960
+9195,9196,9197,9198,9199,9200,9201,9202,9203,4890,9204,9205,9206,9207,9208,9209, # 8976
+9210,9211,9212,9213,9214,9215,9216,9217,9218,9219,9220,9221,9222,4466,9223,9224, # 8992
+9225,9226,9227,9228,9229,9230,9231,9232,9233,9234,9235,9236,9237,9238,9239,9240, # 9008
+9241,9242,9243,9244,9245,4891,9246,9247,9248,9249,9250,9251,9252,9253,9254,9255, # 9024
+9256,9257,4892,9258,9259,9260,9261,4893,4894,9262,9263,9264,9265,9266,9267,9268, # 9040
+9269,9270,9271,9272,9273,4467,9274,9275,9276,9277,9278,9279,9280,9281,9282,9283, # 9056
+9284,9285,3673,9286,9287,9288,9289,9290,9291,9292,9293,9294,9295,9296,9297,9298, # 9072
+9299,9300,9301,9302,9303,9304,9305,9306,9307,9308,9309,9310,9311,9312,9313,9314, # 9088
+9315,9316,9317,9318,9319,9320,9321,9322,4895,9323,9324,9325,9326,9327,9328,9329, # 9104
+9330,9331,9332,9333,9334,9335,9336,9337,9338,9339,9340,9341,9342,9343,9344,9345, # 9120
+9346,9347,4468,9348,9349,9350,9351,9352,9353,9354,9355,9356,9357,9358,9359,9360, # 9136
+9361,9362,9363,9364,9365,9366,9367,9368,9369,9370,9371,9372,9373,4896,9374,4469, # 9152
+9375,9376,9377,9378,9379,4897,9380,9381,9382,9383,9384,9385,9386,9387,9388,9389, # 9168
+9390,9391,9392,9393,9394,9395,9396,9397,9398,9399,9400,9401,9402,9403,9404,9405, # 9184
+9406,4470,9407,2751,9408,9409,3674,3552,9410,9411,9412,9413,9414,9415,9416,9417, # 9200
+9418,9419,9420,9421,4898,9422,9423,9424,9425,9426,9427,9428,9429,3959,9430,9431, # 9216
+9432,9433,9434,9435,9436,4471,9437,9438,9439,9440,9441,9442,9443,9444,9445,9446, # 9232
+9447,9448,9449,9450,3348,9451,9452,9453,9454,9455,9456,9457,9458,9459,9460,9461, # 9248
+9462,9463,9464,9465,9466,9467,9468,9469,9470,9471,9472,4899,9473,9474,9475,9476, # 9264
+9477,4900,9478,9479,9480,9481,9482,9483,9484,9485,9486,9487,9488,3349,9489,9490, # 9280
+9491,9492,9493,9494,9495,9496,9497,9498,9499,9500,9501,9502,9503,9504,9505,9506, # 9296
+9507,9508,9509,9510,9511,9512,9513,9514,9515,9516,9517,9518,9519,9520,4901,9521, # 9312
+9522,9523,9524,9525,9526,4902,9527,9528,9529,9530,9531,9532,9533,9534,9535,9536, # 9328
+9537,9538,9539,9540,9541,9542,9543,9544,9545,9546,9547,9548,9549,9550,9551,9552, # 9344
+9553,9554,9555,9556,9557,9558,9559,9560,9561,9562,9563,9564,9565,9566,9567,9568, # 9360
+9569,9570,9571,9572,9573,9574,9575,9576,9577,9578,9579,9580,9581,9582,9583,9584, # 9376
+3805,9585,9586,9587,9588,9589,9590,9591,9592,9593,9594,9595,9596,9597,9598,9599, # 9392
+9600,9601,9602,4903,9603,9604,9605,9606,9607,4904,9608,9609,9610,9611,9612,9613, # 9408
+9614,4905,9615,9616,9617,9618,9619,9620,9621,9622,9623,9624,9625,9626,9627,9628, # 9424
+9629,9630,9631,9632,4906,9633,9634,9635,9636,9637,9638,9639,9640,9641,9642,9643, # 9440
+4907,9644,9645,9646,9647,9648,9649,9650,9651,9652,9653,9654,9655,9656,9657,9658, # 9456
+9659,9660,9661,9662,9663,9664,9665,9666,9667,9668,9669,9670,9671,9672,4183,9673, # 9472
+9674,9675,9676,9677,4908,9678,9679,9680,9681,4909,9682,9683,9684,9685,9686,9687, # 9488
+9688,9689,9690,4910,9691,9692,9693,3675,9694,9695,9696,2945,9697,9698,9699,9700, # 9504
+9701,9702,9703,9704,9705,4911,9706,9707,9708,9709,9710,9711,9712,9713,9714,9715, # 9520
+9716,9717,9718,9719,9720,9721,9722,9723,9724,9725,9726,9727,9728,9729,9730,9731, # 9536
+9732,9733,9734,9735,4912,9736,9737,9738,9739,9740,4913,9741,9742,9743,9744,9745, # 9552
+9746,9747,9748,9749,9750,9751,9752,9753,9754,9755,9756,9757,9758,4914,9759,9760, # 9568
+9761,9762,9763,9764,9765,9766,9767,9768,9769,9770,9771,9772,9773,9774,9775,9776, # 9584
+9777,9778,9779,9780,9781,9782,4915,9783,9784,9785,9786,9787,9788,9789,9790,9791, # 9600
+9792,9793,4916,9794,9795,9796,9797,9798,9799,9800,9801,9802,9803,9804,9805,9806, # 9616
+9807,9808,9809,9810,9811,9812,9813,9814,9815,9816,9817,9818,9819,9820,9821,9822, # 9632
+9823,9824,9825,9826,9827,9828,9829,9830,9831,9832,9833,9834,9835,9836,9837,9838, # 9648
+9839,9840,9841,9842,9843,9844,9845,9846,9847,9848,9849,9850,9851,9852,9853,9854, # 9664
+9855,9856,9857,9858,9859,9860,9861,9862,9863,9864,9865,9866,9867,9868,4917,9869, # 9680
+9870,9871,9872,9873,9874,9875,9876,9877,9878,9879,9880,9881,9882,9883,9884,9885, # 9696
+9886,9887,9888,9889,9890,9891,9892,4472,9893,9894,9895,9896,9897,3806,9898,9899, # 9712
+9900,9901,9902,9903,9904,9905,9906,9907,9908,9909,9910,9911,9912,9913,9914,4918, # 9728
+9915,9916,9917,4919,9918,9919,9920,9921,4184,9922,9923,9924,9925,9926,9927,9928, # 9744
+9929,9930,9931,9932,9933,9934,9935,9936,9937,9938,9939,9940,9941,9942,9943,9944, # 9760
+9945,9946,4920,9947,9948,9949,9950,9951,9952,9953,9954,9955,4185,9956,9957,9958, # 9776
+9959,9960,9961,9962,9963,9964,9965,4921,9966,9967,9968,4473,9969,9970,9971,9972, # 9792
+9973,9974,9975,9976,9977,4474,9978,9979,9980,9981,9982,9983,9984,9985,9986,9987, # 9808
+9988,9989,9990,9991,9992,9993,9994,9995,9996,9997,9998,9999,10000,10001,10002,10003, # 9824
+10004,10005,10006,10007,10008,10009,10010,10011,10012,10013,10014,10015,10016,10017,10018,10019, # 9840
+10020,10021,4922,10022,4923,10023,10024,10025,10026,10027,10028,10029,10030,10031,10032,10033, # 9856
+10034,10035,10036,10037,10038,10039,10040,10041,10042,10043,10044,10045,10046,10047,10048,4924, # 9872
+10049,10050,10051,10052,10053,10054,10055,10056,10057,10058,10059,10060,10061,10062,10063,10064, # 9888
+10065,10066,10067,10068,10069,10070,10071,10072,10073,10074,10075,10076,10077,10078,10079,10080, # 9904
+10081,10082,10083,10084,10085,10086,10087,4475,10088,10089,10090,10091,10092,10093,10094,10095, # 9920
+10096,10097,4476,10098,10099,10100,10101,10102,10103,10104,10105,10106,10107,10108,10109,10110, # 9936
+10111,2174,10112,10113,10114,10115,10116,10117,10118,10119,10120,10121,10122,10123,10124,10125, # 9952
+10126,10127,10128,10129,10130,10131,10132,10133,10134,10135,10136,10137,10138,10139,10140,3807, # 9968
+4186,4925,10141,10142,10143,10144,10145,10146,10147,4477,4187,10148,10149,10150,10151,10152, # 9984
+10153,4188,10154,10155,10156,10157,10158,10159,10160,10161,4926,10162,10163,10164,10165,10166, #10000
+10167,10168,10169,10170,10171,10172,10173,10174,10175,10176,10177,10178,10179,10180,10181,10182, #10016
+10183,10184,10185,10186,10187,10188,10189,10190,10191,10192,3203,10193,10194,10195,10196,10197, #10032
+10198,10199,10200,4478,10201,10202,10203,10204,4479,10205,10206,10207,10208,10209,10210,10211, #10048
+10212,10213,10214,10215,10216,10217,10218,10219,10220,10221,10222,10223,10224,10225,10226,10227, #10064
+10228,10229,10230,10231,10232,10233,10234,4927,10235,10236,10237,10238,10239,10240,10241,10242, #10080
+10243,10244,10245,10246,10247,10248,10249,10250,10251,10252,10253,10254,10255,10256,10257,10258, #10096
+10259,10260,10261,10262,10263,10264,10265,10266,10267,10268,10269,10270,10271,10272,10273,4480, #10112
+4928,4929,10274,10275,10276,10277,10278,10279,10280,10281,10282,10283,10284,10285,10286,10287, #10128
+10288,10289,10290,10291,10292,10293,10294,10295,10296,10297,10298,10299,10300,10301,10302,10303, #10144
+10304,10305,10306,10307,10308,10309,10310,10311,10312,10313,10314,10315,10316,10317,10318,10319, #10160
+10320,10321,10322,10323,10324,10325,10326,10327,10328,10329,10330,10331,10332,10333,10334,4930, #10176
+10335,10336,10337,10338,10339,10340,10341,10342,4931,10343,10344,10345,10346,10347,10348,10349, #10192
+10350,10351,10352,10353,10354,10355,3088,10356,2786,10357,10358,10359,10360,4189,10361,10362, #10208
+10363,10364,10365,10366,10367,10368,10369,10370,10371,10372,10373,10374,10375,4932,10376,10377, #10224
+10378,10379,10380,10381,10382,10383,10384,10385,10386,10387,10388,10389,10390,10391,10392,4933, #10240
+10393,10394,10395,4934,10396,10397,10398,10399,10400,10401,10402,10403,10404,10405,10406,10407, #10256
+10408,10409,10410,10411,10412,3446,10413,10414,10415,10416,10417,10418,10419,10420,10421,10422, #10272
+10423,4935,10424,10425,10426,10427,10428,10429,10430,4936,10431,10432,10433,10434,10435,10436, #10288
+10437,10438,10439,10440,10441,10442,10443,4937,10444,10445,10446,10447,4481,10448,10449,10450, #10304
+10451,10452,10453,10454,10455,10456,10457,10458,10459,10460,10461,10462,10463,10464,10465,10466, #10320
+10467,10468,10469,10470,10471,10472,10473,10474,10475,10476,10477,10478,10479,10480,10481,10482, #10336
+10483,10484,10485,10486,10487,10488,10489,10490,10491,10492,10493,10494,10495,10496,10497,10498, #10352
+10499,10500,10501,10502,10503,10504,10505,4938,10506,10507,10508,10509,10510,2552,10511,10512, #10368
+10513,10514,10515,10516,3447,10517,10518,10519,10520,10521,10522,10523,10524,10525,10526,10527, #10384
+10528,10529,10530,10531,10532,10533,10534,10535,10536,10537,10538,10539,10540,10541,10542,10543, #10400
+4482,10544,4939,10545,10546,10547,10548,10549,10550,10551,10552,10553,10554,10555,10556,10557, #10416
+10558,10559,10560,10561,10562,10563,10564,10565,10566,10567,3676,4483,10568,10569,10570,10571, #10432
+10572,3448,10573,10574,10575,10576,10577,10578,10579,10580,10581,10582,10583,10584,10585,10586, #10448
+10587,10588,10589,10590,10591,10592,10593,10594,10595,10596,10597,10598,10599,10600,10601,10602, #10464
+10603,10604,10605,10606,10607,10608,10609,10610,10611,10612,10613,10614,10615,10616,10617,10618, #10480
+10619,10620,10621,10622,10623,10624,10625,10626,10627,4484,10628,10629,10630,10631,10632,4940, #10496
+10633,10634,10635,10636,10637,10638,10639,10640,10641,10642,10643,10644,10645,10646,10647,10648, #10512
+10649,10650,10651,10652,10653,10654,10655,10656,4941,10657,10658,10659,2599,10660,10661,10662, #10528
+10663,10664,10665,10666,3089,10667,10668,10669,10670,10671,10672,10673,10674,10675,10676,10677, #10544
+10678,10679,10680,4942,10681,10682,10683,10684,10685,10686,10687,10688,10689,10690,10691,10692, #10560
+10693,10694,10695,10696,10697,4485,10698,10699,10700,10701,10702,10703,10704,4943,10705,3677, #10576
+10706,10707,10708,10709,10710,10711,10712,4944,10713,10714,10715,10716,10717,10718,10719,10720, #10592
+10721,10722,10723,10724,10725,10726,10727,10728,4945,10729,10730,10731,10732,10733,10734,10735, #10608
+10736,10737,10738,10739,10740,10741,10742,10743,10744,10745,10746,10747,10748,10749,10750,10751, #10624
+10752,10753,10754,10755,10756,10757,10758,10759,10760,10761,4946,10762,10763,10764,10765,10766, #10640
+10767,4947,4948,10768,10769,10770,10771,10772,10773,10774,10775,10776,10777,10778,10779,10780, #10656
+10781,10782,10783,10784,10785,10786,10787,10788,10789,10790,10791,10792,10793,10794,10795,10796, #10672
+10797,10798,10799,10800,10801,10802,10803,10804,10805,10806,10807,10808,10809,10810,10811,10812, #10688
+10813,10814,10815,10816,10817,10818,10819,10820,10821,10822,10823,10824,10825,10826,10827,10828, #10704
+10829,10830,10831,10832,10833,10834,10835,10836,10837,10838,10839,10840,10841,10842,10843,10844, #10720
+10845,10846,10847,10848,10849,10850,10851,10852,10853,10854,10855,10856,10857,10858,10859,10860, #10736
+10861,10862,10863,10864,10865,10866,10867,10868,10869,10870,10871,10872,10873,10874,10875,10876, #10752
+10877,10878,4486,10879,10880,10881,10882,10883,10884,10885,4949,10886,10887,10888,10889,10890, #10768
+10891,10892,10893,10894,10895,10896,10897,10898,10899,10900,10901,10902,10903,10904,10905,10906, #10784
+10907,10908,10909,10910,10911,10912,10913,10914,10915,10916,10917,10918,10919,4487,10920,10921, #10800
+10922,10923,10924,10925,10926,10927,10928,10929,10930,10931,10932,4950,10933,10934,10935,10936, #10816
+10937,10938,10939,10940,10941,10942,10943,10944,10945,10946,10947,10948,10949,4488,10950,10951, #10832
+10952,10953,10954,10955,10956,10957,10958,10959,4190,10960,10961,10962,10963,10964,10965,10966, #10848
+10967,10968,10969,10970,10971,10972,10973,10974,10975,10976,10977,10978,10979,10980,10981,10982, #10864
+10983,10984,10985,10986,10987,10988,10989,10990,10991,10992,10993,10994,10995,10996,10997,10998, #10880
+10999,11000,11001,11002,11003,11004,11005,11006,3960,11007,11008,11009,11010,11011,11012,11013, #10896
+11014,11015,11016,11017,11018,11019,11020,11021,11022,11023,11024,11025,11026,11027,11028,11029, #10912
+11030,11031,11032,4951,11033,11034,11035,11036,11037,11038,11039,11040,11041,11042,11043,11044, #10928
+11045,11046,11047,4489,11048,11049,11050,11051,4952,11052,11053,11054,11055,11056,11057,11058, #10944
+4953,11059,11060,11061,11062,11063,11064,11065,11066,11067,11068,11069,11070,11071,4954,11072, #10960
+11073,11074,11075,11076,11077,11078,11079,11080,11081,11082,11083,11084,11085,11086,11087,11088, #10976
+11089,11090,11091,11092,11093,11094,11095,11096,11097,11098,11099,11100,11101,11102,11103,11104, #10992
+11105,11106,11107,11108,11109,11110,11111,11112,11113,11114,11115,3808,11116,11117,11118,11119, #11008
+11120,11121,11122,11123,11124,11125,11126,11127,11128,11129,11130,11131,11132,11133,11134,4955, #11024
+11135,11136,11137,11138,11139,11140,11141,11142,11143,11144,11145,11146,11147,11148,11149,11150, #11040
+11151,11152,11153,11154,11155,11156,11157,11158,11159,11160,11161,4956,11162,11163,11164,11165, #11056
+11166,11167,11168,11169,11170,11171,11172,11173,11174,11175,11176,11177,11178,11179,11180,4957, #11072
+11181,11182,11183,11184,11185,11186,4958,11187,11188,11189,11190,11191,11192,11193,11194,11195, #11088
+11196,11197,11198,11199,11200,3678,11201,11202,11203,11204,11205,11206,4191,11207,11208,11209, #11104
+11210,11211,11212,11213,11214,11215,11216,11217,11218,11219,11220,11221,11222,11223,11224,11225, #11120
+11226,11227,11228,11229,11230,11231,11232,11233,11234,11235,11236,11237,11238,11239,11240,11241, #11136
+11242,11243,11244,11245,11246,11247,11248,11249,11250,11251,4959,11252,11253,11254,11255,11256, #11152
+11257,11258,11259,11260,11261,11262,11263,11264,11265,11266,11267,11268,11269,11270,11271,11272, #11168
+11273,11274,11275,11276,11277,11278,11279,11280,11281,11282,11283,11284,11285,11286,11287,11288, #11184
+11289,11290,11291,11292,11293,11294,11295,11296,11297,11298,11299,11300,11301,11302,11303,11304, #11200
+11305,11306,11307,11308,11309,11310,11311,11312,11313,11314,3679,11315,11316,11317,11318,4490, #11216
+11319,11320,11321,11322,11323,11324,11325,11326,11327,11328,11329,11330,11331,11332,11333,11334, #11232
+11335,11336,11337,11338,11339,11340,11341,11342,11343,11344,11345,11346,11347,4960,11348,11349, #11248
+11350,11351,11352,11353,11354,11355,11356,11357,11358,11359,11360,11361,11362,11363,11364,11365, #11264
+11366,11367,11368,11369,11370,11371,11372,11373,11374,11375,11376,11377,3961,4961,11378,11379, #11280
+11380,11381,11382,11383,11384,11385,11386,11387,11388,11389,11390,11391,11392,11393,11394,11395, #11296
+11396,11397,4192,11398,11399,11400,11401,11402,11403,11404,11405,11406,11407,11408,11409,11410, #11312
+11411,4962,11412,11413,11414,11415,11416,11417,11418,11419,11420,11421,11422,11423,11424,11425, #11328
+11426,11427,11428,11429,11430,11431,11432,11433,11434,11435,11436,11437,11438,11439,11440,11441, #11344
+11442,11443,11444,11445,11446,11447,11448,11449,11450,11451,11452,11453,11454,11455,11456,11457, #11360
+11458,11459,11460,11461,11462,11463,11464,11465,11466,11467,11468,11469,4963,11470,11471,4491, #11376
+11472,11473,11474,11475,4964,11476,11477,11478,11479,11480,11481,11482,11483,11484,11485,11486, #11392
+11487,11488,11489,11490,11491,11492,4965,11493,11494,11495,11496,11497,11498,11499,11500,11501, #11408
+11502,11503,11504,11505,11506,11507,11508,11509,11510,11511,11512,11513,11514,11515,11516,11517, #11424
+11518,11519,11520,11521,11522,11523,11524,11525,11526,11527,11528,11529,3962,11530,11531,11532, #11440
+11533,11534,11535,11536,11537,11538,11539,11540,11541,11542,11543,11544,11545,11546,11547,11548, #11456
+11549,11550,11551,11552,11553,11554,11555,11556,11557,11558,11559,11560,11561,11562,11563,11564, #11472
+4193,4194,11565,11566,11567,11568,11569,11570,11571,11572,11573,11574,11575,11576,11577,11578, #11488
+11579,11580,11581,11582,11583,11584,11585,11586,11587,11588,11589,11590,11591,4966,4195,11592, #11504
+11593,11594,11595,11596,11597,11598,11599,11600,11601,11602,11603,11604,3090,11605,11606,11607, #11520
+11608,11609,11610,4967,11611,11612,11613,11614,11615,11616,11617,11618,11619,11620,11621,11622, #11536
+11623,11624,11625,11626,11627,11628,11629,11630,11631,11632,11633,11634,11635,11636,11637,11638, #11552
+11639,11640,11641,11642,11643,11644,11645,11646,11647,11648,11649,11650,11651,11652,11653,11654, #11568
+11655,11656,11657,11658,11659,11660,11661,11662,11663,11664,11665,11666,11667,11668,11669,11670, #11584
+11671,11672,11673,11674,4968,11675,11676,11677,11678,11679,11680,11681,11682,11683,11684,11685, #11600
+11686,11687,11688,11689,11690,11691,11692,11693,3809,11694,11695,11696,11697,11698,11699,11700, #11616
+11701,11702,11703,11704,11705,11706,11707,11708,11709,11710,11711,11712,11713,11714,11715,11716, #11632
+11717,11718,3553,11719,11720,11721,11722,11723,11724,11725,11726,11727,11728,11729,11730,4969, #11648
+11731,11732,11733,11734,11735,11736,11737,11738,11739,11740,4492,11741,11742,11743,11744,11745, #11664
+11746,11747,11748,11749,11750,11751,11752,4970,11753,11754,11755,11756,11757,11758,11759,11760, #11680
+11761,11762,11763,11764,11765,11766,11767,11768,11769,11770,11771,11772,11773,11774,11775,11776, #11696
+11777,11778,11779,11780,11781,11782,11783,11784,11785,11786,11787,11788,11789,11790,4971,11791, #11712
+11792,11793,11794,11795,11796,11797,4972,11798,11799,11800,11801,11802,11803,11804,11805,11806, #11728
+11807,11808,11809,11810,4973,11811,11812,11813,11814,11815,11816,11817,11818,11819,11820,11821, #11744
+11822,11823,11824,11825,11826,11827,11828,11829,11830,11831,11832,11833,11834,3680,3810,11835, #11760
+11836,4974,11837,11838,11839,11840,11841,11842,11843,11844,11845,11846,11847,11848,11849,11850, #11776
+11851,11852,11853,11854,11855,11856,11857,11858,11859,11860,11861,11862,11863,11864,11865,11866, #11792
+11867,11868,11869,11870,11871,11872,11873,11874,11875,11876,11877,11878,11879,11880,11881,11882, #11808
+11883,11884,4493,11885,11886,11887,11888,11889,11890,11891,11892,11893,11894,11895,11896,11897, #11824
+11898,11899,11900,11901,11902,11903,11904,11905,11906,11907,11908,11909,11910,11911,11912,11913, #11840
+11914,11915,4975,11916,11917,11918,11919,11920,11921,11922,11923,11924,11925,11926,11927,11928, #11856
+11929,11930,11931,11932,11933,11934,11935,11936,11937,11938,11939,11940,11941,11942,11943,11944, #11872
+11945,11946,11947,11948,11949,4976,11950,11951,11952,11953,11954,11955,11956,11957,11958,11959, #11888
+11960,11961,11962,11963,11964,11965,11966,11967,11968,11969,11970,11971,11972,11973,11974,11975, #11904
+11976,11977,11978,11979,11980,11981,11982,11983,11984,11985,11986,11987,4196,11988,11989,11990, #11920
+11991,11992,4977,11993,11994,11995,11996,11997,11998,11999,12000,12001,12002,12003,12004,12005, #11936
+12006,12007,12008,12009,12010,12011,12012,12013,12014,12015,12016,12017,12018,12019,12020,12021, #11952
+12022,12023,12024,12025,12026,12027,12028,12029,12030,12031,12032,12033,12034,12035,12036,12037, #11968
+12038,12039,12040,12041,12042,12043,12044,12045,12046,12047,12048,12049,12050,12051,12052,12053, #11984
+12054,12055,12056,12057,12058,12059,12060,12061,4978,12062,12063,12064,12065,12066,12067,12068, #12000
+12069,12070,12071,12072,12073,12074,12075,12076,12077,12078,12079,12080,12081,12082,12083,12084, #12016
+12085,12086,12087,12088,12089,12090,12091,12092,12093,12094,12095,12096,12097,12098,12099,12100, #12032
+12101,12102,12103,12104,12105,12106,12107,12108,12109,12110,12111,12112,12113,12114,12115,12116, #12048
+12117,12118,12119,12120,12121,12122,12123,4979,12124,12125,12126,12127,12128,4197,12129,12130, #12064
+12131,12132,12133,12134,12135,12136,12137,12138,12139,12140,12141,12142,12143,12144,12145,12146, #12080
+12147,12148,12149,12150,12151,12152,12153,12154,4980,12155,12156,12157,12158,12159,12160,4494, #12096
+12161,12162,12163,12164,3811,12165,12166,12167,12168,12169,4495,12170,12171,4496,12172,12173, #12112
+12174,12175,12176,3812,12177,12178,12179,12180,12181,12182,12183,12184,12185,12186,12187,12188, #12128
+12189,12190,12191,12192,12193,12194,12195,12196,12197,12198,12199,12200,12201,12202,12203,12204, #12144
+12205,12206,12207,12208,12209,12210,12211,12212,12213,12214,12215,12216,12217,12218,12219,12220, #12160
+12221,4981,12222,12223,12224,12225,12226,12227,12228,12229,12230,12231,12232,12233,12234,12235, #12176
+4982,12236,12237,12238,12239,12240,12241,12242,12243,12244,12245,4983,12246,12247,12248,12249, #12192
+4984,12250,12251,12252,12253,12254,12255,12256,12257,12258,12259,12260,12261,12262,12263,12264, #12208
+4985,12265,4497,12266,12267,12268,12269,12270,12271,12272,12273,12274,12275,12276,12277,12278, #12224
+12279,12280,12281,12282,12283,12284,12285,12286,12287,4986,12288,12289,12290,12291,12292,12293, #12240
+12294,12295,12296,2473,12297,12298,12299,12300,12301,12302,12303,12304,12305,12306,12307,12308, #12256
+12309,12310,12311,12312,12313,12314,12315,12316,12317,12318,12319,3963,12320,12321,12322,12323, #12272
+12324,12325,12326,12327,12328,12329,12330,12331,12332,4987,12333,12334,12335,12336,12337,12338, #12288
+12339,12340,12341,12342,12343,12344,12345,12346,12347,12348,12349,12350,12351,12352,12353,12354, #12304
+12355,12356,12357,12358,12359,3964,12360,12361,12362,12363,12364,12365,12366,12367,12368,12369, #12320
+12370,3965,12371,12372,12373,12374,12375,12376,12377,12378,12379,12380,12381,12382,12383,12384, #12336
+12385,12386,12387,12388,12389,12390,12391,12392,12393,12394,12395,12396,12397,12398,12399,12400, #12352
+12401,12402,12403,12404,12405,12406,12407,12408,4988,12409,12410,12411,12412,12413,12414,12415, #12368
+12416,12417,12418,12419,12420,12421,12422,12423,12424,12425,12426,12427,12428,12429,12430,12431, #12384
+12432,12433,12434,12435,12436,12437,12438,3554,12439,12440,12441,12442,12443,12444,12445,12446, #12400
+12447,12448,12449,12450,12451,12452,12453,12454,12455,12456,12457,12458,12459,12460,12461,12462, #12416
+12463,12464,4989,12465,12466,12467,12468,12469,12470,12471,12472,12473,12474,12475,12476,12477, #12432
+12478,12479,12480,4990,12481,12482,12483,12484,12485,12486,12487,12488,12489,4498,12490,12491, #12448
+12492,12493,12494,12495,12496,12497,12498,12499,12500,12501,12502,12503,12504,12505,12506,12507, #12464
+12508,12509,12510,12511,12512,12513,12514,12515,12516,12517,12518,12519,12520,12521,12522,12523, #12480
+12524,12525,12526,12527,12528,12529,12530,12531,12532,12533,12534,12535,12536,12537,12538,12539, #12496
+12540,12541,12542,12543,12544,12545,12546,12547,12548,12549,12550,12551,4991,12552,12553,12554, #12512
+12555,12556,12557,12558,12559,12560,12561,12562,12563,12564,12565,12566,12567,12568,12569,12570, #12528
+12571,12572,12573,12574,12575,12576,12577,12578,3036,12579,12580,12581,12582,12583,3966,12584, #12544
+12585,12586,12587,12588,12589,12590,12591,12592,12593,12594,12595,12596,12597,12598,12599,12600, #12560
+12601,12602,12603,12604,12605,12606,12607,12608,12609,12610,12611,12612,12613,12614,12615,12616, #12576
+12617,12618,12619,12620,12621,12622,12623,12624,12625,12626,12627,12628,12629,12630,12631,12632, #12592
+12633,12634,12635,12636,12637,12638,12639,12640,12641,12642,12643,12644,12645,12646,4499,12647, #12608
+12648,12649,12650,12651,12652,12653,12654,12655,12656,12657,12658,12659,12660,12661,12662,12663, #12624
+12664,12665,12666,12667,12668,12669,12670,12671,12672,12673,12674,12675,12676,12677,12678,12679, #12640
+12680,12681,12682,12683,12684,12685,12686,12687,12688,12689,12690,12691,12692,12693,12694,12695, #12656
+12696,12697,12698,4992,12699,12700,12701,12702,12703,12704,12705,12706,12707,12708,12709,12710, #12672
+12711,12712,12713,12714,12715,12716,12717,12718,12719,12720,12721,12722,12723,12724,12725,12726, #12688
+12727,12728,12729,12730,12731,12732,12733,12734,12735,12736,12737,12738,12739,12740,12741,12742, #12704
+12743,12744,12745,12746,12747,12748,12749,12750,12751,12752,12753,12754,12755,12756,12757,12758, #12720
+12759,12760,12761,12762,12763,12764,12765,12766,12767,12768,12769,12770,12771,12772,12773,12774, #12736
+12775,12776,12777,12778,4993,2175,12779,12780,12781,12782,12783,12784,12785,12786,4500,12787, #12752
+12788,12789,12790,12791,12792,12793,12794,12795,12796,12797,12798,12799,12800,12801,12802,12803, #12768
+12804,12805,12806,12807,12808,12809,12810,12811,12812,12813,12814,12815,12816,12817,12818,12819, #12784
+12820,12821,12822,12823,12824,12825,12826,4198,3967,12827,12828,12829,12830,12831,12832,12833, #12800
+12834,12835,12836,12837,12838,12839,12840,12841,12842,12843,12844,12845,12846,12847,12848,12849, #12816
+12850,12851,12852,12853,12854,12855,12856,12857,12858,12859,12860,12861,4199,12862,12863,12864, #12832
+12865,12866,12867,12868,12869,12870,12871,12872,12873,12874,12875,12876,12877,12878,12879,12880, #12848
+12881,12882,12883,12884,12885,12886,12887,4501,12888,12889,12890,12891,12892,12893,12894,12895, #12864
+12896,12897,12898,12899,12900,12901,12902,12903,12904,12905,12906,12907,12908,12909,12910,12911, #12880
+12912,4994,12913,12914,12915,12916,12917,12918,12919,12920,12921,12922,12923,12924,12925,12926, #12896
+12927,12928,12929,12930,12931,12932,12933,12934,12935,12936,12937,12938,12939,12940,12941,12942, #12912
+12943,12944,12945,12946,12947,12948,12949,12950,12951,12952,12953,12954,12955,12956,1772,12957, #12928
+12958,12959,12960,12961,12962,12963,12964,12965,12966,12967,12968,12969,12970,12971,12972,12973, #12944
+12974,12975,12976,12977,12978,12979,12980,12981,12982,12983,12984,12985,12986,12987,12988,12989, #12960
+12990,12991,12992,12993,12994,12995,12996,12997,4502,12998,4503,12999,13000,13001,13002,13003, #12976
+4504,13004,13005,13006,13007,13008,13009,13010,13011,13012,13013,13014,13015,13016,13017,13018, #12992
+13019,13020,13021,13022,13023,13024,13025,13026,13027,13028,13029,3449,13030,13031,13032,13033, #13008
+13034,13035,13036,13037,13038,13039,13040,13041,13042,13043,13044,13045,13046,13047,13048,13049, #13024
+13050,13051,13052,13053,13054,13055,13056,13057,13058,13059,13060,13061,13062,13063,13064,13065, #13040
+13066,13067,13068,13069,13070,13071,13072,13073,13074,13075,13076,13077,13078,13079,13080,13081, #13056
+13082,13083,13084,13085,13086,13087,13088,13089,13090,13091,13092,13093,13094,13095,13096,13097, #13072
+13098,13099,13100,13101,13102,13103,13104,13105,13106,13107,13108,13109,13110,13111,13112,13113, #13088
+13114,13115,13116,13117,13118,3968,13119,4995,13120,13121,13122,13123,13124,13125,13126,13127, #13104
+4505,13128,13129,13130,13131,13132,13133,13134,4996,4506,13135,13136,13137,13138,13139,4997, #13120
+13140,13141,13142,13143,13144,13145,13146,13147,13148,13149,13150,13151,13152,13153,13154,13155, #13136
+13156,13157,13158,13159,4998,13160,13161,13162,13163,13164,13165,13166,13167,13168,13169,13170, #13152
+13171,13172,13173,13174,13175,13176,4999,13177,13178,13179,13180,13181,13182,13183,13184,13185, #13168
+13186,13187,13188,13189,13190,13191,13192,13193,13194,13195,13196,13197,13198,13199,13200,13201, #13184
+13202,13203,13204,13205,13206,5000,13207,13208,13209,13210,13211,13212,13213,13214,13215,13216, #13200
+13217,13218,13219,13220,13221,13222,13223,13224,13225,13226,13227,4200,5001,13228,13229,13230, #13216
+13231,13232,13233,13234,13235,13236,13237,13238,13239,13240,3969,13241,13242,13243,13244,3970, #13232
+13245,13246,13247,13248,13249,13250,13251,13252,13253,13254,13255,13256,13257,13258,13259,13260, #13248
+13261,13262,13263,13264,13265,13266,13267,13268,3450,13269,13270,13271,13272,13273,13274,13275, #13264
+13276,5002,13277,13278,13279,13280,13281,13282,13283,13284,13285,13286,13287,13288,13289,13290, #13280
+13291,13292,13293,13294,13295,13296,13297,13298,13299,13300,13301,13302,3813,13303,13304,13305, #13296
+13306,13307,13308,13309,13310,13311,13312,13313,13314,13315,13316,13317,13318,13319,13320,13321, #13312
+13322,13323,13324,13325,13326,13327,13328,4507,13329,13330,13331,13332,13333,13334,13335,13336, #13328
+13337,13338,13339,13340,13341,5003,13342,13343,13344,13345,13346,13347,13348,13349,13350,13351, #13344
+13352,13353,13354,13355,13356,13357,13358,13359,13360,13361,13362,13363,13364,13365,13366,13367, #13360
+5004,13368,13369,13370,13371,13372,13373,13374,13375,13376,13377,13378,13379,13380,13381,13382, #13376
+13383,13384,13385,13386,13387,13388,13389,13390,13391,13392,13393,13394,13395,13396,13397,13398, #13392
+13399,13400,13401,13402,13403,13404,13405,13406,13407,13408,13409,13410,13411,13412,13413,13414, #13408
+13415,13416,13417,13418,13419,13420,13421,13422,13423,13424,13425,13426,13427,13428,13429,13430, #13424
+13431,13432,4508,13433,13434,13435,4201,13436,13437,13438,13439,13440,13441,13442,13443,13444, #13440
+13445,13446,13447,13448,13449,13450,13451,13452,13453,13454,13455,13456,13457,5005,13458,13459, #13456
+13460,13461,13462,13463,13464,13465,13466,13467,13468,13469,13470,4509,13471,13472,13473,13474, #13472
+13475,13476,13477,13478,13479,13480,13481,13482,13483,13484,13485,13486,13487,13488,13489,13490, #13488
+13491,13492,13493,13494,13495,13496,13497,13498,13499,13500,13501,13502,13503,13504,13505,13506, #13504
+13507,13508,13509,13510,13511,13512,13513,13514,13515,13516,13517,13518,13519,13520,13521,13522, #13520
+13523,13524,13525,13526,13527,13528,13529,13530,13531,13532,13533,13534,13535,13536,13537,13538, #13536
+13539,13540,13541,13542,13543,13544,13545,13546,13547,13548,13549,13550,13551,13552,13553,13554, #13552
+13555,13556,13557,13558,13559,13560,13561,13562,13563,13564,13565,13566,13567,13568,13569,13570, #13568
+13571,13572,13573,13574,13575,13576,13577,13578,13579,13580,13581,13582,13583,13584,13585,13586, #13584
+13587,13588,13589,13590,13591,13592,13593,13594,13595,13596,13597,13598,13599,13600,13601,13602, #13600
+13603,13604,13605,13606,13607,13608,13609,13610,13611,13612,13613,13614,13615,13616,13617,13618, #13616
+13619,13620,13621,13622,13623,13624,13625,13626,13627,13628,13629,13630,13631,13632,13633,13634, #13632
+13635,13636,13637,13638,13639,13640,13641,13642,5006,13643,13644,13645,13646,13647,13648,13649, #13648
+13650,13651,5007,13652,13653,13654,13655,13656,13657,13658,13659,13660,13661,13662,13663,13664, #13664
+13665,13666,13667,13668,13669,13670,13671,13672,13673,13674,13675,13676,13677,13678,13679,13680, #13680
+13681,13682,13683,13684,13685,13686,13687,13688,13689,13690,13691,13692,13693,13694,13695,13696, #13696
+13697,13698,13699,13700,13701,13702,13703,13704,13705,13706,13707,13708,13709,13710,13711,13712, #13712
+13713,13714,13715,13716,13717,13718,13719,13720,13721,13722,13723,13724,13725,13726,13727,13728, #13728
+13729,13730,13731,13732,13733,13734,13735,13736,13737,13738,13739,13740,13741,13742,13743,13744, #13744
+13745,13746,13747,13748,13749,13750,13751,13752,13753,13754,13755,13756,13757,13758,13759,13760, #13760
+13761,13762,13763,13764,13765,13766,13767,13768,13769,13770,13771,13772,13773,13774,3273,13775, #13776
+13776,13777,13778,13779,13780,13781,13782,13783,13784,13785,13786,13787,13788,13789,13790,13791, #13792
+13792,13793,13794,13795,13796,13797,13798,13799,13800,13801,13802,13803,13804,13805,13806,13807, #13808
+13808,13809,13810,13811,13812,13813,13814,13815,13816,13817,13818,13819,13820,13821,13822,13823, #13824
+13824,13825,13826,13827,13828,13829,13830,13831,13832,13833,13834,13835,13836,13837,13838,13839, #13840
+13840,13841,13842,13843,13844,13845,13846,13847,13848,13849,13850,13851,13852,13853,13854,13855, #13856
+13856,13857,13858,13859,13860,13861,13862,13863,13864,13865,13866,13867,13868,13869,13870,13871, #13872
+13872,13873,13874,13875,13876,13877,13878,13879,13880,13881,13882,13883,13884,13885,13886,13887, #13888
+13888,13889,13890,13891,13892,13893,13894,13895,13896,13897,13898,13899,13900,13901,13902,13903, #13904
+13904,13905,13906,13907,13908,13909,13910,13911,13912,13913,13914,13915,13916,13917,13918,13919, #13920
+13920,13921,13922,13923,13924,13925,13926,13927,13928,13929,13930,13931,13932,13933,13934,13935, #13936
+13936,13937,13938,13939,13940,13941,13942,13943,13944,13945,13946,13947,13948,13949,13950,13951, #13952
+13952,13953,13954,13955,13956,13957,13958,13959,13960,13961,13962,13963,13964,13965,13966,13967, #13968
+13968,13969,13970,13971,13972] #13973
+end
+
diff --git a/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/big5prober.rb b/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/big5prober.rb
new file mode 100644 (file)
index 0000000..6b6ebcc
--- /dev/null
@@ -0,0 +1,42 @@
+######################## BEGIN LICENSE BLOCK ########################
+# The Original Code is Mozilla Communicator client code.
+# 
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+# 
+# Contributor(s):
+#   Jeff Hodges - port to Ruby
+#   Mark Pilgrim - port to Python
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+# 
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301  USA
+######################### END LICENSE BLOCK #########################
+
+module CharDet
+  class Big5Prober < MultiByteCharSetProber 
+    def initialize
+      super
+      @_mCodingSM = CodingStateMachine.new(Big5SMModel)
+      @_mDistributionAnalyzer = Big5DistributionAnalysis.new()
+      reset()
+    end
+
+    def get_charset_name
+      return "Big5"
+    end
+  end
+end
diff --git a/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/chardistribution.rb b/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/chardistribution.rb
new file mode 100644 (file)
index 0000000..de873a3
--- /dev/null
@@ -0,0 +1,238 @@
+######################## BEGIN LICENSE BLOCK ########################
+# The Original Code is Mozilla Communicator client code.
+# 
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+# 
+# Contributor(s)
+
+#   Jeff Hodges
+#   Mark Pilgrim - port to Python
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+# 
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301  USA
+######################### END LICENSE BLOCK #########################
+
+module CharDet
+  ENOUGH_DATA_THRESHOLD = 1024
+  SURE_YES = 0.99
+  SURE_NO = 0.01
+
+  class CharDistributionAnalysis
+    def initialize
+      @_mCharToFreqOrder = nil # Mapping table to get frequency order from char order (get from GetOrder())
+      @_mTableSize = nil # Size of above table
+      @_mTypicalDistributionRatio = nil # This is a constant value which varies from language to language, used in calculating confidence.  See http://www.mozilla.org/projects/intl/UniversalCharsetDetection.html for further detail.
+      reset()
+    end
+
+    def reset
+      # # """reset analyser, clear any state"""
+      @_mDone = false # If this flag is set to constants.True, detection is done and conclusion has been made
+      @_mTotalChars = 0 # Total characters encountered
+      @_mFreqChars = 0 # The number of characters whose frequency order is less than 512
+    end
+
+    def feed(aStr, aCharLen)
+      # # """feed a character with known length"""
+      if aCharLen == 2
+        # we only care about 2-bytes character in our distribution analysis
+        order = get_order(aStr)
+      else
+        order = -1
+      end
+      if order >= 0
+        @_mTotalChars += 1
+        # order is valid
+        if order < @_mTableSize
+          if 512 > @_mCharToFreqOrder[order]
+            @_mFreqChars += 1
+          end
+        end
+      end
+    end
+
+    def get_confidence
+      # """return confidence based on existing data"""
+      # if we didn't receive any character in our consideration range, return negative answer
+      if @_mTotalChars <= 0
+        return SURE_NO
+      end
+
+      if @_mTotalChars != @_mFreqChars
+        r = @_mFreqChars / ((@_mTotalChars - @_mFreqChars) * @_mTypicalDistributionRatio)
+        if r < SURE_YES
+          return r
+        end
+      end
+
+      # normalize confidence (we don't want to be 100% sure)
+      return SURE_YES
+    end
+
+    def got_enough_data
+      # It is not necessary to receive all data to draw conclusion. For charset detection,
+      # certain amount of data is enough
+      return @_mTotalChars > ENOUGH_DATA_THRESHOLD
+    end
+
+    def get_order(aStr)
+      # We do not handle characters based on the original encoding string, but 
+      # convert this encoding string to a number, here called order.
+      # This allows multiple encodings of a language to share one frequency table.
+      return -1
+    end
+  end
+
+  class EUCTWDistributionAnalysis < CharDistributionAnalysis
+    def initialize
+      super()
+      @_mCharToFreqOrder = EUCTWCharToFreqOrder
+      @_mTableSize = EUCTW_TABLE_SIZE
+      @_mTypicalDistributionRatio = EUCTW_TYPICAL_DISTRIBUTION_RATIO
+    end
+
+    def get_order(aStr)
+      # for euc-TW encoding, we are interested 
+      #   first  byte range: 0xc4 -- 0xfe
+      #   second byte range: 0xa1 -- 0xfe
+      # no validation needed here. State machine has done that
+      if aStr[0..0] >= "\xC4"
+        return 94 * (aStr[0] - 0xC4) + aStr[1] - 0xA1
+      else
+        return -1
+      end
+    end
+  end
+
+  class EUCKRDistributionAnalysis < CharDistributionAnalysis
+    def initialize
+      super()
+      @_mCharToFreqOrder = EUCKRCharToFreqOrder
+      @_mTableSize = EUCKR_TABLE_SIZE
+      @_mTypicalDistributionRatio = EUCKR_TYPICAL_DISTRIBUTION_RATIO
+    end
+
+    def get_order(aStr)
+      # for euc-KR encoding, we are interested 
+      #   first  byte range: 0xb0 -- 0xfe
+      #   second byte range: 0xa1 -- 0xfe
+      # no validation needed here. State machine has done that
+      if aStr[0..0] >= "\xB0"
+        return 94 * (aStr[0] - 0xB0) + aStr[1] - 0xA1
+      else
+        return -1
+      end
+    end
+  end
+
+  class GB2312DistributionAnalysis < CharDistributionAnalysis
+    def initialize
+      super()
+      @_mCharToFreqOrder = GB2312CharToFreqOrder
+      @_mTableSize = GB2312_TABLE_SIZE
+      @_mTypicalDistributionRatio = GB2312_TYPICAL_DISTRIBUTION_RATIO
+    end
+
+    def get_order(aStr)
+      # for GB2312 encoding, we are interested 
+      #  first  byte range: 0xb0 -- 0xfe
+      #  second byte range: 0xa1 -- 0xfe
+      # no validation needed here. State machine has done that
+      if (aStr[0..0] >= "\xB0") and (aStr[1..1] >= "\xA1")
+        return 94 * (aStr[0] - 0xB0) + aStr[1] - 0xA1
+      else
+        return -1
+      end
+    end
+  end
+
+  class Big5DistributionAnalysis < CharDistributionAnalysis
+    def initialize
+      super
+      @_mCharToFreqOrder = Big5CharToFreqOrder
+      @_mTableSize = BIG5_TABLE_SIZE
+      @_mTypicalDistributionRatio = BIG5_TYPICAL_DISTRIBUTION_RATIO
+    end
+
+    def get_order(aStr)
+      # for big5 encoding, we are interested 
+      #   first  byte range: 0xa4 -- 0xfe
+      #   second byte range: 0x40 -- 0x7e , 0xa1 -- 0xfe
+      # no validation needed here. State machine has done that
+      if aStr[0..0] >= "\xA4"
+        if aStr[1..1] >= "\xA1"
+          return 157 * (aStr[0] - 0xA4) + aStr[1] - 0xA1 + 63
+        else
+          return 157 * (aStr[0] - 0xA4) + aStr[1] - 0x40
+        end
+      else
+        return -1
+      end
+    end
+  end
+
+  class SJISDistributionAnalysis < CharDistributionAnalysis
+    def initialize
+      super()
+      @_mCharToFreqOrder = JISCharToFreqOrder
+      @_mTableSize = JIS_TABLE_SIZE
+      @_mTypicalDistributionRatio = JIS_TYPICAL_DISTRIBUTION_RATIO
+    end
+
+    def get_order(aStr)
+      # for sjis encoding, we are interested 
+      #   first  byte range: 0x81 -- 0x9f , 0xe0 -- 0xfe
+      #   second byte range: 0x40 -- 0x7e,  0x81 -- oxfe
+      # no validation needed here. State machine has done that
+      aStr = aStr[0..1].join if aStr.class == Array
+      if (aStr[0..0] >= "\x81") and (aStr[0..0] <= "\x9F")
+        order = 188 * (aStr[0] - 0x81)
+      elsif (aStr[0..0] >= "\xE0") and (aStr[0..0] <= "\xEF")
+        order = 188 * (aStr[0] - 0xE0 + 31)
+      else
+        return -1
+      end
+      order = order + aStr[1] - 0x40
+      if aStr[1..1] > "\x7F"
+        order =- 1
+      end
+      return order
+    end
+  end
+
+  class EUCJPDistributionAnalysis < CharDistributionAnalysis
+    def initialize
+      super()
+      @_mCharToFreqOrder = JISCharToFreqOrder
+      @_mTableSize = JIS_TABLE_SIZE
+      @_mTypicalDistributionRatio = JIS_TYPICAL_DISTRIBUTION_RATIO
+    end
+
+    def get_order(aStr)
+      # for euc-JP encoding, we are interested 
+      #   first  byte range: 0xa0 -- 0xfe
+      #   second byte range: 0xa1 -- 0xfe
+      # no validation needed here. State machine has done that
+      if aStr[0..0] >= "\xA0"
+        return 94 * (aStr[0] - 0xA1) + aStr[1] - 0xa1
+      else
+        return -1
+      end
+    end
+  end
+end
diff --git a/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/charsetgroupprober.rb b/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/charsetgroupprober.rb
new file mode 100644 (file)
index 0000000..0feebca
--- /dev/null
@@ -0,0 +1,112 @@
+######################## BEGIN LICENSE BLOCK ########################
+# The Original Code is Mozilla Communicator client code.
+# 
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+# 
+# Contributor(s)
+#   Jeff Hodges - port to Ruby
+#   Mark Pilgrim - port to Python
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+# 
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301  USA
+######################### END LICENSE BLOCK #########################
+
+module CharDet
+  class CharSetGroupProber < CharSetProber
+    attr_accessor :_mProbers
+    def initialize
+      super
+      @_mActiveNum = 0
+      @_mProbers = []
+      @_mBestGuessProber = nil
+    end
+
+    def reset
+      super
+      @_mActiveNum = 0
+
+      for prober in @_mProbers
+        if prober
+          prober.reset()
+          prober.active = true
+          @_mActiveNum += 1
+        end
+      end
+      @_mBestGuessProber = nil
+    end
+
+    def get_charset_name
+      if not @_mBestGuessProber
+        get_confidence()
+        return nil unless @_mBestGuessProber
+        #                self._mBestGuessProber = self._mProbers[0]
+      end
+      return @_mBestGuessProber.get_charset_name()
+    end
+
+    def feed(aBuf)
+      for prober in @_mProbers
+        next unless prober
+        next unless prober.active
+        st = prober.feed(aBuf)
+        next unless st
+        if st == EFoundIt
+          @_mBestGuessProber = prober
+          return get_state()
+        elsif st == ENotMe
+          prober.active = false
+          @_mActiveNum -= 1
+          if @_mActiveNum <= 0
+            @_mState = ENotMe
+            return get_state()
+          end
+        end
+      end
+      return get_state()
+    end
+
+    def get_confidence()
+      st = get_state()
+      if st == EFoundIt
+        return 0.99
+      elsif st == ENotMe
+        return 0.01
+      end
+      bestConf = 0.0
+      @_mBestGuessProber = nil
+      for prober in @_mProbers
+        next unless prober
+        unless prober.active
+          $stderr << "#{prober.get_charset_name()} not active\n" if $debug
+          next
+        end
+        cf = prober.get_confidence()
+        $stderr << "#{prober.get_charset_name} confidence = #{cf}\n" if $debug
+        if bestConf < cf
+          bestConf = cf
+          @_mBestGuessProber = prober
+        end
+      end
+      return 0.0 unless @_mBestGuessProber
+      return bestConf
+      #        else
+      #            self._mBestGuessProber = self._mProbers[0]
+      #            return self._mBestGuessProber.get_confidence()
+    end
+  end
+end
diff --git a/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/charsetprober.rb b/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/charsetprober.rb
new file mode 100644 (file)
index 0000000..ce58cac
--- /dev/null
@@ -0,0 +1,75 @@
+######################## BEGIN LICENSE BLOCK ########################
+# The Original Code is Mozilla Universal charset detector code.
+# 
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 2001
+# the Initial Developer. All Rights Reserved.
+# 
+# Contributor(s):
+#   Jeff Hodges - port to Ruby
+#   Mark Pilgrim - port to Python
+#   Shy Shalom - original C code
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+# 
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301  USA
+######################### END LICENSE BLOCK #########################
+
+module CharDet
+  class CharSetProber
+    attr_accessor :active
+    def initialize
+    end
+
+    def reset
+      @_mState = EDetecting
+    end
+
+    def get_charset_name
+      return nil
+    end
+
+    def feed(aBuf)
+    end
+
+    def get_state
+      return @_mState
+    end
+
+    def get_confidence
+      return 0.0
+    end
+
+    def filter_high_bit_only(aBuf)
+      # DO NOT USE `gsub!`
+      # It will remove all characters from the buffer that is later used by
+      # other probers.  This is because gsub! removes data from the instance variable
+      # that will be passed to later probers, while gsub makes a new instance variable
+      # that will not. 
+      newBuf = aBuf.gsub(/([\x00-\x7F])+/, ' ')
+      return newBuf
+    end
+
+    def filter_without_english_letters(aBuf)
+      newBuf = aBuf.gsub(/([A-Za-z])+/,' ')
+      return newBuf
+    end
+
+    def filter_with_english_letters(aBuf)
+      # TODO
+      return aBuf
+    end
+  end
+end
diff --git a/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/codingstatemachine.rb b/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/codingstatemachine.rb
new file mode 100644 (file)
index 0000000..24fda79
--- /dev/null
@@ -0,0 +1,64 @@
+######################## BEGIN LICENSE BLOCK ########################
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Jeff Hodges - port to Ruby
+#   Mark Pilgrim - port to Python
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+# 
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301  USA
+######################### END LICENSE BLOCK #########################
+
+module CharDet
+  class CodingStateMachine
+    def initialize(sm)
+      @_mModel = sm
+      @_mCurrentBytePos = 0
+      @_mCurrentCharLen = 0
+      reset()
+    end
+
+    def reset
+      @_mCurrentState = EStart
+    end
+
+    def next_state(c)
+      # for each byte we get its class
+      # if it is first byte, we also get byte length
+      byteCls = @_mModel['classTable'][c[0]]
+      if @_mCurrentState == EStart
+        @_mCurrentBytePos = 0
+        @_mCurrentCharLen = @_mModel['charLenTable'][byteCls]
+      end
+      # from byte's class and stateTable, we get its next state
+      @_mCurrentState = @_mModel['stateTable'][@_mCurrentState * @_mModel['classFactor'] + byteCls]
+      @_mCurrentBytePos += 1
+      return @_mCurrentState
+    end
+
+    def get_current_charlen
+      return @_mCurrentCharLen
+    end
+
+    def get_coding_state_machine
+      return @_mModel['name']
+    end
+  end
+end
diff --git a/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/constants.rb b/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/constants.rb
new file mode 100644 (file)
index 0000000..156b4af
--- /dev/null
@@ -0,0 +1,42 @@
+######################## BEGIN LICENSE BLOCK ########################
+# The Original Code is Mozilla Universal charset detector code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 2001
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Jeff Hodges - port to Ruby
+#   Mark Pilgrim - port to Python
+#   Shy Shalom - original C code
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+# 
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301  USA
+######################### END LICENSE BLOCK #########################
+
+module CharDet
+  $debug = false
+
+  EDetecting = 0
+  EFoundIt = 1
+  ENotMe = 2
+
+  EStart = 0
+  EError = 1
+  EItsMe = 2
+
+  SHORTCUT_THRESHOLD = 0.95
+end
diff --git a/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/escprober.rb b/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/escprober.rb
new file mode 100644 (file)
index 0000000..288e3eb
--- /dev/null
@@ -0,0 +1,89 @@
+######################## BEGIN LICENSE BLOCK ########################
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Jeff Hodges - port to Ruby
+#   Mark Pilgrim - port to Python
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+# 
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301  USA
+######################### END LICENSE BLOCK #########################
+
+module CharDet
+  class EscCharSetProber < CharSetProber
+    def initialize
+      super()
+      @_mCodingSM = [ CodingStateMachine.new(HZSMModel),
+                      CodingStateMachine.new(ISO2022CNSMModel),
+                      CodingStateMachine.new(ISO2022JPSMModel),
+                      CodingStateMachine.new(ISO2022KRSMModel)  ]
+      reset()
+    end
+
+    def reset
+      super()
+      for codingSM in @_mCodingSM
+        next if not codingSM
+        codingSM.active = true
+        codingSM.reset()
+      end
+      @_mActiveSM = @_mCodingSM.length
+      @_mDetectedCharset = nil
+    end
+
+    def get_charset_name
+      return @_mDetectedCharset
+    end
+
+    def get_confidence
+      if @_mDetectedCharset
+        return 0.99
+      else
+        return 0.00
+      end
+    end
+
+    def feed(aBuf)
+      aBuf.each_byte do |b|
+        c = b.chr
+        for codingSM in @_mCodingSM
+          next unless codingSM
+          next unless codingSM.active
+          codingState = codingSM.next_state(c)
+          if codingState == EError
+            codingSM.active = false
+            @_mActiveSM -= 1
+            if @_mActiveSM <= 0
+              @_mState = ENotMe
+              return get_state()
+            end
+          elsif codingState == EItsMe
+            @_mState = EFoundIt
+            @_mDetectedCharset = codingSM.get_coding_state_machine()
+            return get_state()
+          end
+        end
+      end
+      return get_state()
+
+    end
+
+  end
+end
diff --git a/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/escsm.rb b/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/escsm.rb
new file mode 100644 (file)
index 0000000..c1969c6
--- /dev/null
@@ -0,0 +1,244 @@
+######################## BEGIN LICENSE BLOCK ########################
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Mark Pilgrim - port to Python
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+# 
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301  USA
+######################### END LICENSE BLOCK #########################
+
+module CharDet
+  HZ_cls = [
+    1,0,0,0,0,0,0,0,  # 00 - 07 
+    0,0,0,0,0,0,0,0,  # 08 - 0f 
+    0,0,0,0,0,0,0,0,  # 10 - 17 
+    0,0,0,1,0,0,0,0,  # 18 - 1f 
+    0,0,0,0,0,0,0,0,  # 20 - 27 
+    0,0,0,0,0,0,0,0,  # 28 - 2f 
+    0,0,0,0,0,0,0,0,  # 30 - 37 
+    0,0,0,0,0,0,0,0,  # 38 - 3f 
+    0,0,0,0,0,0,0,0,  # 40 - 47 
+    0,0,0,0,0,0,0,0,  # 48 - 4f 
+    0,0,0,0,0,0,0,0,  # 50 - 57 
+    0,0,0,0,0,0,0,0,  # 58 - 5f 
+    0,0,0,0,0,0,0,0,  # 60 - 67 
+    0,0,0,0,0,0,0,0,  # 68 - 6f 
+    0,0,0,0,0,0,0,0,  # 70 - 77 
+    0,0,0,4,0,5,2,0,  # 78 - 7f 
+    1,1,1,1,1,1,1,1,  # 80 - 87 
+    1,1,1,1,1,1,1,1,  # 88 - 8f 
+    1,1,1,1,1,1,1,1,  # 90 - 97 
+    1,1,1,1,1,1,1,1,  # 98 - 9f 
+    1,1,1,1,1,1,1,1,  # a0 - a7 
+    1,1,1,1,1,1,1,1,  # a8 - af 
+    1,1,1,1,1,1,1,1,  # b0 - b7 
+    1,1,1,1,1,1,1,1,  # b8 - bf 
+    1,1,1,1,1,1,1,1,  # c0 - c7 
+    1,1,1,1,1,1,1,1,  # c8 - cf 
+    1,1,1,1,1,1,1,1,  # d0 - d7 
+    1,1,1,1,1,1,1,1,  # d8 - df 
+    1,1,1,1,1,1,1,1,  # e0 - e7 
+    1,1,1,1,1,1,1,1,  # e8 - ef 
+    1,1,1,1,1,1,1,1,  # f0 - f7 
+    1,1,1,1,1,1,1,1,  # f8 - ff 
+  ]
+
+  HZ_st = [
+    EStart,EError,     3,EStart,EStart,EStart,EError,EError,# 00-07 
+    EError,EError,EError,EError,EItsMe,EItsMe,EItsMe,EItsMe,# 08-0f 
+    EItsMe,EItsMe,EError,EError,EStart,EStart,     4,EError,# 10-17 
+    5,EError,     6,EError,     5,     5,     4,EError,# 18-1f 
+    4,EError,     4,     4,     4,EError,     4,EError,# 20-27 
+    4,EItsMe,EStart,EStart,EStart,EStart,EStart,EStart,# 28-2f 
+  ]
+
+  HZCharLenTable = [0, 0, 0, 0, 0, 0]
+
+  HZSMModel = {'classTable' => HZ_cls,
+            'classFactor' => 6,
+            'stateTable' => HZ_st,
+            'charLenTable' => HZCharLenTable,
+            'name' => "HZ-GB-2312"
+}
+
+ISO2022CN_cls = [
+2,0,0,0,0,0,0,0,  # 00 - 07 
+0,0,0,0,0,0,0,0,  # 08 - 0f 
+0,0,0,0,0,0,0,0,  # 10 - 17 
+0,0,0,1,0,0,0,0,  # 18 - 1f 
+0,0,0,0,0,0,0,0,  # 20 - 27 
+0,3,0,0,0,0,0,0,  # 28 - 2f 
+0,0,0,0,0,0,0,0,  # 30 - 37 
+0,0,0,0,0,0,0,0,  # 38 - 3f 
+0,0,0,4,0,0,0,0,  # 40 - 47 
+0,0,0,0,0,0,0,0,  # 48 - 4f 
+0,0,0,0,0,0,0,0,  # 50 - 57 
+0,0,0,0,0,0,0,0,  # 58 - 5f 
+0,0,0,0,0,0,0,0,  # 60 - 67 
+0,0,0,0,0,0,0,0,  # 68 - 6f 
+0,0,0,0,0,0,0,0,  # 70 - 77 
+0,0,0,0,0,0,0,0,  # 78 - 7f 
+2,2,2,2,2,2,2,2,  # 80 - 87 
+2,2,2,2,2,2,2,2,  # 88 - 8f 
+2,2,2,2,2,2,2,2,  # 90 - 97 
+2,2,2,2,2,2,2,2,  # 98 - 9f 
+2,2,2,2,2,2,2,2,  # a0 - a7 
+2,2,2,2,2,2,2,2,  # a8 - af 
+2,2,2,2,2,2,2,2,  # b0 - b7 
+2,2,2,2,2,2,2,2,  # b8 - bf 
+2,2,2,2,2,2,2,2,  # c0 - c7 
+2,2,2,2,2,2,2,2,  # c8 - cf 
+2,2,2,2,2,2,2,2,  # d0 - d7 
+2,2,2,2,2,2,2,2,  # d8 - df 
+2,2,2,2,2,2,2,2,  # e0 - e7 
+2,2,2,2,2,2,2,2,  # e8 - ef 
+2,2,2,2,2,2,2,2,  # f0 - f7 
+2,2,2,2,2,2,2,2,  # f8 - ff 
+]
+
+ISO2022CN_st = [
+EStart,     3,EError,EStart,EStart,EStart,EStart,EStart,# 00-07 
+EStart,EError,EError,EError,EError,EError,EError,EError,# 08-0f 
+EError,EError,EItsMe,EItsMe,EItsMe,EItsMe,EItsMe,EItsMe,# 10-17 
+EItsMe,EItsMe,EItsMe,EError,EError,EError,     4,EError,# 18-1f 
+EError,EError,EError,EItsMe,EError,EError,EError,EError,# 20-27 
+     5,     6,EError,EError,EError,EError,EError,EError,# 28-2f 
+EError,EError,EError,EItsMe,EError,EError,EError,EError,# 30-37 
+EError,EError,EError,EError,EError,EItsMe,EError,EStart,# 38-3f 
+]
+
+ISO2022CNCharLenTable = [0, 0, 0, 0, 0, 0, 0, 0, 0]
+
+ISO2022CNSMModel = {'classTable' => ISO2022CN_cls,
+                   'classFactor' => 9,
+                   'stateTable' => ISO2022CN_st,
+                   'charLenTable' => ISO2022CNCharLenTable,
+                   'name' => "ISO-2022-CN"
+}
+
+ISO2022JP_cls = [
+2,0,0,0,0,0,0,0,  # 00 - 07 
+0,0,0,0,0,0,2,2,  # 08 - 0f 
+0,0,0,0,0,0,0,0,  # 10 - 17 
+0,0,0,1,0,0,0,0,  # 18 - 1f 
+0,0,0,0,7,0,0,0,  # 20 - 27 
+3,0,0,0,0,0,0,0,  # 28 - 2f 
+0,0,0,0,0,0,0,0,  # 30 - 37 
+0,0,0,0,0,0,0,0,  # 38 - 3f 
+6,0,4,0,8,0,0,0,  # 40 - 47 
+0,9,5,0,0,0,0,0,  # 48 - 4f 
+0,0,0,0,0,0,0,0,  # 50 - 57 
+0,0,0,0,0,0,0,0,  # 58 - 5f 
+0,0,0,0,0,0,0,0,  # 60 - 67 
+0,0,0,0,0,0,0,0,  # 68 - 6f 
+0,0,0,0,0,0,0,0,  # 70 - 77 
+0,0,0,0,0,0,0,0,  # 78 - 7f 
+2,2,2,2,2,2,2,2,  # 80 - 87 
+2,2,2,2,2,2,2,2,  # 88 - 8f 
+2,2,2,2,2,2,2,2,  # 90 - 97 
+2,2,2,2,2,2,2,2,  # 98 - 9f 
+2,2,2,2,2,2,2,2,  # a0 - a7 
+2,2,2,2,2,2,2,2,  # a8 - af 
+2,2,2,2,2,2,2,2,  # b0 - b7 
+2,2,2,2,2,2,2,2,  # b8 - bf 
+2,2,2,2,2,2,2,2,  # c0 - c7 
+2,2,2,2,2,2,2,2,  # c8 - cf 
+2,2,2,2,2,2,2,2,  # d0 - d7 
+2,2,2,2,2,2,2,2,  # d8 - df 
+2,2,2,2,2,2,2,2,  # e0 - e7 
+2,2,2,2,2,2,2,2,  # e8 - ef 
+2,2,2,2,2,2,2,2,  # f0 - f7 
+2,2,2,2,2,2,2,2,  # f8 - ff 
+]
+
+ISO2022JP_st = [ 
+EStart,     3,EError,EStart,EStart,EStart,EStart,EStart,# 00-07 
+EStart,EStart,EError,EError,EError,EError,EError,EError,# 08-0f 
+EError,EError,EError,EError,EItsMe,EItsMe,EItsMe,EItsMe,# 10-17 
+EItsMe,EItsMe,EItsMe,EItsMe,EItsMe,EItsMe,EError,EError,# 18-1f 
+EError,     5,EError,EError,EError,     4,EError,EError,# 20-27 
+EError,EError,EError,     6,EItsMe,EError,EItsMe,EError,# 28-2f 
+EError,EError,EError,EError,EError,EError,EItsMe,EItsMe,# 30-37 
+EError,EError,EError,EItsMe,EError,EError,EError,EError,# 38-3f 
+EError,EError,EError,EError,EItsMe,EError,EStart,EStart,# 40-47 
+]
+
+ISO2022JPCharLenTable = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+
+ISO2022JPSMModel = {'classTable' => ISO2022JP_cls,
+                   'classFactor' => 10,
+                   'stateTable' => ISO2022JP_st,
+                   'charLenTable' => ISO2022JPCharLenTable,
+                   'name' => "ISO-2022-JP"
+}
+
+ISO2022KR_cls = [
+2,0,0,0,0,0,0,0,  # 00 - 07 
+0,0,0,0,0,0,0,0,  # 08 - 0f 
+0,0,0,0,0,0,0,0,  # 10 - 17 
+0,0,0,1,0,0,0,0,  # 18 - 1f 
+0,0,0,0,3,0,0,0,  # 20 - 27 
+0,4,0,0,0,0,0,0,  # 28 - 2f 
+0,0,0,0,0,0,0,0,  # 30 - 37 
+0,0,0,0,0,0,0,0,  # 38 - 3f 
+0,0,0,5,0,0,0,0,  # 40 - 47 
+0,0,0,0,0,0,0,0,  # 48 - 4f 
+0,0,0,0,0,0,0,0,  # 50 - 57 
+0,0,0,0,0,0,0,0,  # 58 - 5f 
+0,0,0,0,0,0,0,0,  # 60 - 67 
+0,0,0,0,0,0,0,0,  # 68 - 6f 
+0,0,0,0,0,0,0,0,  # 70 - 77 
+0,0,0,0,0,0,0,0,  # 78 - 7f 
+2,2,2,2,2,2,2,2,  # 80 - 87 
+2,2,2,2,2,2,2,2,  # 88 - 8f 
+2,2,2,2,2,2,2,2,  # 90 - 97 
+2,2,2,2,2,2,2,2,  # 98 - 9f 
+2,2,2,2,2,2,2,2,  # a0 - a7 
+2,2,2,2,2,2,2,2,  # a8 - af 
+2,2,2,2,2,2,2,2,  # b0 - b7 
+2,2,2,2,2,2,2,2,  # b8 - bf 
+2,2,2,2,2,2,2,2,  # c0 - c7 
+2,2,2,2,2,2,2,2,  # c8 - cf 
+2,2,2,2,2,2,2,2,  # d0 - d7 
+2,2,2,2,2,2,2,2,  # d8 - df 
+2,2,2,2,2,2,2,2,  # e0 - e7 
+2,2,2,2,2,2,2,2,  # e8 - ef 
+2,2,2,2,2,2,2,2,  # f0 - f7 
+2,2,2,2,2,2,2,2,  # f8 - ff 
+]
+
+ISO2022KR_st = [ 
+EStart,     3,EError,EStart,EStart,EStart,EError,EError,# 00-07 
+EError,EError,EError,EError,EItsMe,EItsMe,EItsMe,EItsMe,# 08-0f 
+EItsMe,EItsMe,EError,EError,EError,     4,EError,EError,# 10-17 
+EError,EError,EError,EError,     5,EError,EError,EError,# 18-1f 
+EError,EError,EError,EItsMe,EStart,EStart,EStart,EStart,# 20-27 
+]
+
+ISO2022KRCharLenTable = [0, 0, 0, 0, 0, 0]
+
+ISO2022KRSMModel = {'classTable' => ISO2022KR_cls,
+                   'classFactor' => 6,
+                   'stateTable' => ISO2022KR_st,
+                   'charLenTable' => ISO2022KRCharLenTable,
+                   'name' => "ISO-2022-KR"
+}
+end
diff --git a/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/eucjpprober.rb b/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/eucjpprober.rb
new file mode 100644 (file)
index 0000000..1fb0eeb
--- /dev/null
@@ -0,0 +1,88 @@
+######################## BEGIN LICENSE BLOCK ########################
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Jeff Hodges - port to Ruby
+#   Mark Pilgrim - port to Python
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+# 
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301  USA
+######################### END LICENSE BLOCK #########################
+
+module CharDet
+  class EUCJPProber < MultiByteCharSetProber
+    def initialize
+      super()
+      @_mCodingSM = CodingStateMachine.new(EUCJPSMModel)
+      @_mDistributionAnalyzer = EUCJPDistributionAnalysis.new()
+      @_mContextAnalyzer = EUCJPContextAnalysis.new()
+      reset
+    end
+
+    def reset
+      super()
+      @_mContextAnalyzer.reset()
+    end
+
+    def get_charset_name
+      return "EUC-JP"
+    end
+
+    def feed(aBuf)
+      aLen = aBuf.length
+      for i in (0...aLen)
+        codingState = @_mCodingSM.next_state(aBuf[i..i])
+        if codingState == EError
+          $stderr << "#{get_charset_name} prober hit error at byte #{i}\n" if $debug
+          @_mState = ENotMe
+          break
+        elsif codingState == EItsMe
+          @_mState = EFoundIt
+          break
+        elsif codingState == EStart
+          charLen = @_mCodingSM.get_current_charlen()
+          if i == 0
+            @_mLastChar[1] = aBuf[0..0]
+            @_mContextAnalyzer.feed(@_mLastChar, charLen)
+            @_mDistributionAnalyzer.feed(@_mLastChar, charLen)
+          else
+            @_mContextAnalyzer.feed(aBuf[i-1...i+1], charLen)
+            @_mDistributionAnalyzer.feed(aBuf[i-1...i+1], charLen)
+          end
+        end
+      end
+
+      @_mLastChar[0] = aBuf[aLen-1..aLen-1]
+
+      if get_state() == EDetecting
+        if @_mContextAnalyzer.got_enough_data() and (get_confidence() > SHORTCUT_THRESHOLD)
+          @_mState = EFoundIt
+        end
+      end
+
+      return get_state()
+    end
+
+    def get_confidence
+      l = [@_mContextAnalyzer.get_confidence,@_mDistributionAnalyzer.get_confidence]
+      return l.max
+    end
+  end
+end
diff --git a/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/euckrfreq.rb b/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/euckrfreq.rb
new file mode 100644 (file)
index 0000000..764a34f
--- /dev/null
@@ -0,0 +1,596 @@
+######################## BEGIN LICENSE BLOCK ########################
+# The Original Code is Mozilla Communicator client code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Mark Pilgrim - port to Python
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+# 
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301  USA
+######################### END LICENSE BLOCK #########################
+
+# Sampling from about 20M text materials include literature and computer technology
+
+# 128  --> 0.79
+# 256  --> 0.92
+# 512  --> 0.986
+# 1024 --> 0.99944
+# 2048 --> 0.99999
+#
+# Idea Distribution Ratio = 0.98653 / (1-0.98653) = 73.24
+# Random Distribution Ration = 512 / (2350-512) = 0.279.
+# 
+# Typical Distribution Ratio  
+module CharDet
+EUCKR_TYPICAL_DISTRIBUTION_RATIO = 6.0
+
+EUCKR_TABLE_SIZE = 2352
+
+# Char to FreqOrder table , 
+EUCKRCharToFreqOrder = [
+  13, 130, 120,1396, 481,1719,1720, 328, 609, 212,1721, 707, 400, 299,1722,  87,
+1397,1723, 104, 536,1117,1203,1724,1267, 685,1268, 508,1725,1726,1727,1728,1398,
+1399,1729,1730,1731, 141, 621, 326,1057, 368,1732, 267, 488,  20,1733,1269,1734,
+ 945,1400,1735,  47, 904,1270,1736,1737, 773, 248,1738, 409, 313, 786, 429,1739,
+ 116, 987, 813,1401, 683,  75,1204, 145,1740,1741,1742,1743,  16, 847, 667, 622,
+ 708,1744,1745,1746, 966, 787, 304, 129,1747,  60, 820, 123, 676,1748,1749,1750,
+1751, 617,1752, 626,1753,1754,1755,1756, 653,1757,1758,1759,1760,1761,1762, 856,
+ 344,1763,1764,1765,1766,  89, 401, 418, 806, 905, 848,1767,1768,1769, 946,1205,
+ 709,1770,1118,1771, 241,1772,1773,1774,1271,1775, 569,1776, 999,1777,1778,1779,
+1780, 337, 751,1058,  28, 628, 254,1781, 177, 906, 270, 349, 891,1079,1782,  19,
+1783, 379,1784, 315,1785, 629, 754,1402, 559,1786, 636, 203,1206,1787, 710, 567,
+1788, 935, 814,1789,1790,1207, 766, 528,1791,1792,1208,1793,1794,1795,1796,1797,
+1403,1798,1799, 533,1059,1404,1405,1156,1406, 936, 884,1080,1800, 351,1801,1802,
+1803,1804,1805, 801,1806,1807,1808,1119,1809,1157, 714, 474,1407,1810, 298, 899,
+ 885,1811,1120, 802,1158,1812, 892,1813,1814,1408, 659,1815,1816,1121,1817,1818,
+1819,1820,1821,1822, 319,1823, 594, 545,1824, 815, 937,1209,1825,1826, 573,1409,
+1022,1827,1210,1828,1829,1830,1831,1832,1833, 556, 722, 807,1122,1060,1834, 697,
+1835, 900, 557, 715,1836,1410, 540,1411, 752,1159, 294, 597,1211, 976, 803, 770,
+1412,1837,1838,  39, 794,1413, 358,1839, 371, 925,1840, 453, 661, 788, 531, 723,
+ 544,1023,1081, 869,  91,1841, 392, 430, 790, 602,1414, 677,1082, 457,1415,1416,
+1842,1843, 475, 327,1024,1417, 795, 121,1844, 733, 403,1418,1845,1846,1847, 300,
+ 119, 711,1212, 627,1848,1272, 207,1849,1850, 796,1213, 382,1851, 519,1852,1083,
+ 893,1853,1854,1855, 367, 809, 487, 671,1856, 663,1857,1858, 956, 471, 306, 857,
+1859,1860,1160,1084,1861,1862,1863,1864,1865,1061,1866,1867,1868,1869,1870,1871,
+ 282,  96, 574,1872, 502,1085,1873,1214,1874, 907,1875,1876, 827, 977,1419,1420,
+1421, 268,1877,1422,1878,1879,1880, 308,1881,   2, 537,1882,1883,1215,1884,1885,
+ 127, 791,1886,1273,1423,1887,  34, 336, 404, 643,1888, 571, 654, 894, 840,1889,
+   0, 886,1274, 122, 575, 260, 908, 938,1890,1275, 410, 316,1891,1892, 100,1893,
+1894,1123,  48,1161,1124,1025,1895, 633, 901,1276,1896,1897, 115, 816,1898, 317,
+1899, 694,1900, 909, 734,1424, 572, 866,1425, 691,  85, 524,1010, 543, 394, 841,
+1901,1902,1903,1026,1904,1905,1906,1907,1908,1909,  30, 451, 651, 988, 310,1910,
+1911,1426, 810,1216,  93,1912,1913,1277,1217,1914, 858, 759,  45,  58, 181, 610,
+ 269,1915,1916, 131,1062, 551, 443,1000, 821,1427, 957, 895,1086,1917,1918, 375,
+1919, 359,1920, 687,1921, 822,1922, 293,1923,1924,  40, 662, 118, 692,  29, 939,
+ 887, 640, 482, 174,1925,  69,1162, 728,1428, 910,1926,1278,1218,1279, 386, 870,
+ 217, 854,1163, 823,1927,1928,1929,1930, 834,1931,  78,1932, 859,1933,1063,1934,
+1935,1936,1937, 438,1164, 208, 595,1938,1939,1940,1941,1219,1125,1942, 280, 888,
+1429,1430,1220,1431,1943,1944,1945,1946,1947,1280, 150, 510,1432,1948,1949,1950,
+1951,1952,1953,1954,1011,1087,1955,1433,1043,1956, 881,1957, 614, 958,1064,1065,
+1221,1958, 638,1001, 860, 967, 896,1434, 989, 492, 553,1281,1165,1959,1282,1002,
+1283,1222,1960,1961,1962,1963,  36, 383, 228, 753, 247, 454,1964, 876, 678,1965,
+1966,1284, 126, 464, 490, 835, 136, 672, 529, 940,1088,1435, 473,1967,1968, 467,
+  50, 390, 227, 587, 279, 378, 598, 792, 968, 240, 151, 160, 849, 882,1126,1285,
+ 639,1044, 133, 140, 288, 360, 811, 563,1027, 561, 142, 523,1969,1970,1971,   7,
+ 103, 296, 439, 407, 506, 634, 990,1972,1973,1974,1975, 645,1976,1977,1978,1979,
+1980,1981, 236,1982,1436,1983,1984,1089, 192, 828, 618, 518,1166, 333,1127,1985,
+ 818,1223,1986,1987,1988,1989,1990,1991,1992,1993, 342,1128,1286, 746, 842,1994,
+1995, 560, 223,1287,  98,   8, 189, 650, 978,1288,1996,1437,1997,  17, 345, 250,
+ 423, 277, 234, 512, 226,  97, 289,  42, 167,1998, 201,1999,2000, 843, 836, 824,
+ 532, 338, 783,1090, 182, 576, 436,1438,1439, 527, 500,2001, 947, 889,2002,2003,
+2004,2005, 262, 600, 314, 447,2006, 547,2007, 693, 738,1129,2008,  71,1440, 745,
+ 619, 688,2009, 829,2010,2011, 147,2012,  33, 948,2013,2014,  74, 224,2015,  61,
+ 191, 918, 399, 637,2016,1028,1130, 257, 902,2017,2018,2019,2020,2021,2022,2023,
+2024,2025,2026, 837,2027,2028,2029,2030, 179, 874, 591,  52, 724, 246,2031,2032,
+2033,2034,1167, 969,2035,1289, 630, 605, 911,1091,1168,2036,2037,2038,1441, 912,
+2039, 623,2040,2041, 253,1169,1290,2042,1442, 146, 620, 611, 577, 433,2043,1224,
+ 719,1170, 959, 440, 437, 534,  84, 388, 480,1131, 159, 220, 198, 679,2044,1012,
+ 819,1066,1443, 113,1225, 194, 318,1003,1029,2045,2046,2047,2048,1067,2049,2050,
+2051,2052,2053,  59, 913, 112,2054, 632,2055, 455, 144, 739,1291,2056, 273, 681,
+ 499,2057, 448,2058,2059, 760,2060,2061, 970, 384, 169, 245,1132,2062,2063, 414,
+1444,2064,2065,  41, 235,2066, 157, 252, 877, 568, 919, 789, 580,2067, 725,2068,
+2069,1292,2070,2071,1445,2072,1446,2073,2074,  55, 588,  66,1447, 271,1092,2075,
+1226,2076, 960,1013, 372,2077,2078,2079,2080,2081,1293,2082,2083,2084,2085, 850,
+2086,2087,2088,2089,2090, 186,2091,1068, 180,2092,2093,2094, 109,1227, 522, 606,
+2095, 867,1448,1093, 991,1171, 926, 353,1133,2096, 581,2097,2098,2099,1294,1449,
+1450,2100, 596,1172,1014,1228,2101,1451,1295,1173,1229,2102,2103,1296,1134,1452,
+ 949,1135,2104,2105,1094,1453,1454,1455,2106,1095,2107,2108,2109,2110,2111,2112,
+2113,2114,2115,2116,2117, 804,2118,2119,1230,1231, 805,1456, 405,1136,2120,2121,
+2122,2123,2124, 720, 701,1297, 992,1457, 927,1004,2125,2126,2127,2128,2129,2130,
+  22, 417,2131, 303,2132, 385,2133, 971, 520, 513,2134,1174,  73,1096, 231, 274,
+ 962,1458, 673,2135,1459,2136, 152,1137,2137,2138,2139,2140,1005,1138,1460,1139,
+2141,2142,2143,2144,  11, 374, 844,2145, 154,1232,  46,1461,2146, 838, 830, 721,
+1233, 106,2147,  90, 428, 462, 578, 566,1175, 352,2148,2149, 538,1234, 124,1298,
+2150,1462, 761, 565,2151, 686,2152, 649,2153,  72, 173,2154, 460, 415,2155,1463,
+2156,1235, 305,2157,2158,2159,2160,2161,2162, 579,2163,2164,2165,2166,2167, 747,
+2168,2169,2170,2171,1464, 669,2172,2173,2174,2175,2176,1465,2177,  23, 530, 285,
+2178, 335, 729,2179, 397,2180,2181,2182,1030,2183,2184, 698,2185,2186, 325,2187,
+2188, 369,2189, 799,1097,1015, 348,2190,1069, 680,2191, 851,1466,2192,2193,  10,
+2194, 613, 424,2195, 979, 108, 449, 589,  27, 172,  81,1031,  80, 774, 281, 350,
+1032, 525, 301, 582,1176,2196, 674,1045,2197,2198,1467, 730, 762,2199,2200,2201,
+2202,1468,2203, 993,2204,2205, 266,1070, 963,1140,2206,2207,2208, 664,1098, 972,
+2209,2210,2211,1177,1469,1470, 871,2212,2213,2214,2215,2216,1471,2217,2218,2219,
+2220,2221,2222,2223,2224,2225,2226,2227,1472,1236,2228,2229,2230,2231,2232,2233,
+2234,2235,1299,2236,2237, 200,2238, 477, 373,2239,2240, 731, 825, 777,2241,2242,
+2243, 521, 486, 548,2244,2245,2246,1473,1300,  53, 549, 137, 875,  76, 158,2247,
+1301,1474, 469, 396,1016, 278, 712,2248, 321, 442, 503, 767, 744, 941,1237,1178,
+1475,2249,  82, 178,1141,1179, 973,2250,1302,2251, 297,2252,2253, 570,2254,2255,
+2256,  18, 450, 206,2257, 290, 292,1142,2258, 511, 162,  99, 346, 164, 735,2259,
+1476,1477,   4, 554, 343, 798,1099,2260,1100,2261,  43, 171,1303, 139, 215,2262,
+2263, 717, 775,2264,1033, 322, 216,2265, 831,2266, 149,2267,1304,2268,2269, 702,
+1238, 135, 845, 347, 309,2270, 484,2271, 878, 655, 238,1006,1478,2272,  67,2273,
+ 295,2274,2275, 461,2276, 478, 942, 412,2277,1034,2278,2279,2280, 265,2281, 541,
+2282,2283,2284,2285,2286,  70, 852,1071,2287,2288,2289,2290,  21,  56, 509, 117,
+ 432,2291,2292, 331, 980, 552,1101, 148, 284, 105, 393,1180,1239, 755,2293, 187,
+2294,1046,1479,2295, 340,2296,  63,1047, 230,2297,2298,1305, 763,1306, 101, 800,
+ 808, 494,2299,2300,2301, 903,2302,  37,1072,  14,   5,2303,  79, 675,2304, 312,
+2305,2306,2307,2308,2309,1480,   6,1307,2310,2311,2312,   1, 470,  35,  24, 229,
+2313, 695, 210,  86, 778,  15, 784, 592, 779,  32,  77, 855, 964,2314, 259,2315,
+ 501, 380,2316,2317,  83, 981, 153, 689,1308,1481,1482,1483,2318,2319, 716,1484,
+2320,2321,2322,2323,2324,2325,1485,2326,2327, 128,  57,  68, 261,1048, 211, 170,
+1240,  31,2328,  51, 435, 742,2329,2330,2331, 635,2332, 264, 456,2333,2334,2335,
+ 425,2336,1486, 143, 507, 263, 943,2337, 363, 920,1487, 256,1488,1102, 243, 601,
+1489,2338,2339,2340,2341,2342,2343,2344, 861,2345,2346,2347,2348,2349,2350, 395,
+2351,1490,1491,  62, 535, 166, 225,2352,2353, 668, 419,1241, 138, 604, 928,2354,
+1181,2355,1492,1493,2356,2357,2358,1143,2359, 696,2360, 387, 307,1309, 682, 476,
+2361,2362, 332,  12, 222, 156,2363, 232,2364, 641, 276, 656, 517,1494,1495,1035,
+ 416, 736,1496,2365,1017, 586,2366,2367,2368,1497,2369, 242,2370,2371,2372,1498,
+2373, 965, 713,2374,2375,2376,2377, 740, 982,1499, 944,1500,1007,2378,2379,1310,
+1501,2380,2381,2382, 785, 329,2383,2384,1502,2385,2386,2387, 932,2388,1503,2389,
+2390,2391,2392,1242,2393,2394,2395,2396,2397, 994, 950,2398,2399,2400,2401,1504,
+1311,2402,2403,2404,2405,1049, 749,2406,2407, 853, 718,1144,1312,2408,1182,1505,
+2409,2410, 255, 516, 479, 564, 550, 214,1506,1507,1313, 413, 239, 444, 339,1145,
+1036,1508,1509,1314,1037,1510,1315,2411,1511,2412,2413,2414, 176, 703, 497, 624,
+ 593, 921, 302,2415, 341, 165,1103,1512,2416,1513,2417,2418,2419, 376,2420, 700,
+2421,2422,2423, 258, 768,1316,2424,1183,2425, 995, 608,2426,2427,2428,2429, 221,
+2430,2431,2432,2433,2434,2435,2436,2437, 195, 323, 726, 188, 897, 983,1317, 377,
+ 644,1050, 879,2438, 452,2439,2440,2441,2442,2443,2444, 914,2445,2446,2447,2448,
+ 915, 489,2449,1514,1184,2450,2451, 515,  64, 427, 495,2452, 583,2453, 483, 485,
+1038, 562, 213,1515, 748, 666,2454,2455,2456,2457, 334,2458, 780, 996,1008, 705,
+1243,2459,2460,2461,2462,2463, 114,2464, 493,1146, 366, 163,1516, 961,1104,2465,
+ 291,2466,1318,1105,2467,1517, 365,2468, 355, 951,1244,2469,1319,2470, 631,2471,
+2472, 218,1320, 364, 320, 756,1518,1519,1321,1520,1322,2473,2474,2475,2476, 997,
+2477,2478,2479,2480, 665,1185,2481, 916,1521,2482,2483,2484, 584, 684,2485,2486,
+ 797,2487,1051,1186,2488,2489,2490,1522,2491,2492, 370,2493,1039,1187,  65,2494,
+ 434, 205, 463,1188,2495, 125, 812, 391, 402, 826, 699, 286, 398, 155, 781, 771,
+ 585,2496, 590, 505,1073,2497, 599, 244, 219, 917,1018, 952, 646,1523,2498,1323,
+2499,2500,  49, 984, 354, 741,2501, 625,2502,1324,2503,1019, 190, 357, 757, 491,
+  95, 782, 868,2504,2505,2506,2507,2508,2509, 134,1524,1074, 422,1525, 898,2510,
+ 161,2511,2512,2513,2514, 769,2515,1526,2516,2517, 411,1325,2518, 472,1527,2519,
+2520,2521,2522,2523,2524, 985,2525,2526,2527,2528,2529,2530, 764,2531,1245,2532,
+2533,  25, 204, 311,2534, 496,2535,1052,2536,2537,2538,2539,2540,2541,2542, 199,
+ 704, 504, 468, 758, 657,1528, 196,  44, 839,1246, 272, 750,2543, 765, 862,2544,
+2545,1326,2546, 132, 615, 933,2547, 732,2548,2549,2550,1189,1529,2551, 283,1247,
+1053, 607, 929,2552,2553,2554, 930, 183, 872, 616,1040,1147,2555,1148,1020, 441,
+ 249,1075,2556,2557,2558, 466, 743,2559,2560,2561,  92, 514, 426, 420, 526,2562,
+2563,2564,2565,2566,2567,2568, 185,2569,2570,2571,2572, 776,1530, 658,2573, 362,
+2574, 361, 922,1076, 793,2575,2576,2577,2578,2579,2580,1531, 251,2581,2582,2583,
+2584,1532,  54, 612, 237,1327,2585,2586, 275, 408, 647, 111,2587,1533,1106, 465,
+   3, 458,   9,  38,2588, 107, 110, 890, 209,  26, 737, 498,2589,1534,2590, 431,
+ 202,  88,1535, 356, 287,1107, 660,1149,2591, 381,1536, 986,1150, 445,1248,1151,
+ 974,2592,2593, 846,2594, 446, 953, 184,1249,1250, 727,2595, 923, 193, 883,2596,
+2597,2598, 102, 324, 539, 817,2599, 421,1041,2600, 832,2601,  94, 175, 197, 406,
+2602, 459,2603,2604,2605,2606,2607, 330, 555,2608,2609,2610, 706,1108, 389,2611,
+2612,2613,2614, 233,2615, 833, 558, 931, 954,1251,2616,2617,1537, 546,2618,2619,
+1009,2620,2621,2622,1538, 690,1328,2623, 955,2624,1539,2625,2626, 772,2627,2628,
+2629,2630,2631, 924, 648, 863, 603,2632,2633, 934,1540, 864, 865,2634, 642,1042,
+ 670,1190,2635,2636,2637,2638, 168,2639, 652, 873, 542,1054,1541,2640,2641,2642,  # 512, 256
+#Everything below is of no interest for detection purpose
+2643,2644,2645,2646,2647,2648,2649,2650,2651,2652,2653,2654,2655,2656,2657,2658,
+2659,2660,2661,2662,2663,2664,2665,2666,2667,2668,2669,2670,2671,2672,2673,2674,
+2675,2676,2677,2678,2679,2680,2681,2682,2683,2684,2685,2686,2687,2688,2689,2690,
+2691,2692,2693,2694,2695,2696,2697,2698,2699,1542, 880,2700,2701,2702,2703,2704,
+2705,2706,2707,2708,2709,2710,2711,2712,2713,2714,2715,2716,2717,2718,2719,2720,
+2721,2722,2723,2724,2725,1543,2726,2727,2728,2729,2730,2731,2732,1544,2733,2734,
+2735,2736,2737,2738,2739,2740,2741,2742,2743,2744,2745,2746,2747,2748,2749,2750,
+2751,2752,2753,2754,1545,2755,2756,2757,2758,2759,2760,2761,2762,2763,2764,2765,
+2766,1546,2767,1547,2768,2769,2770,2771,2772,2773,2774,2775,2776,2777,2778,2779,
+2780,2781,2782,2783,2784,2785,2786,1548,2787,2788,2789,1109,2790,2791,2792,2793,
+2794,2795,2796,2797,2798,2799,2800,2801,2802,2803,2804,2805,2806,2807,2808,2809,
+2810,2811,2812,1329,2813,2814,2815,2816,2817,2818,2819,2820,2821,2822,2823,2824,
+2825,2826,2827,2828,2829,2830,2831,2832,2833,2834,2835,2836,2837,2838,2839,2840,
+2841,2842,2843,2844,2845,2846,2847,2848,2849,2850,2851,2852,2853,2854,2855,2856,
+1549,2857,2858,2859,2860,1550,2861,2862,1551,2863,2864,2865,2866,2867,2868,2869,
+2870,2871,2872,2873,2874,1110,1330,2875,2876,2877,2878,2879,2880,2881,2882,2883,
+2884,2885,2886,2887,2888,2889,2890,2891,2892,2893,2894,2895,2896,2897,2898,2899,
+2900,2901,2902,2903,2904,2905,2906,2907,2908,2909,2910,2911,2912,2913,2914,2915,
+2916,2917,2918,2919,2920,2921,2922,2923,2924,2925,2926,2927,2928,2929,2930,1331,
+2931,2932,2933,2934,2935,2936,2937,2938,2939,2940,2941,2942,2943,1552,2944,2945,
+2946,2947,2948,2949,2950,2951,2952,2953,2954,2955,2956,2957,2958,2959,2960,2961,
+2962,2963,2964,1252,2965,2966,2967,2968,2969,2970,2971,2972,2973,2974,2975,2976,
+2977,2978,2979,2980,2981,2982,2983,2984,2985,2986,2987,2988,2989,2990,2991,2992,
+2993,2994,2995,2996,2997,2998,2999,3000,3001,3002,3003,3004,3005,3006,3007,3008,
+3009,3010,3011,3012,1553,3013,3014,3015,3016,3017,1554,3018,1332,3019,3020,3021,
+3022,3023,3024,3025,3026,3027,3028,3029,3030,3031,3032,3033,3034,3035,3036,3037,
+3038,3039,3040,3041,3042,3043,3044,3045,3046,3047,3048,3049,3050,1555,3051,3052,
+3053,1556,1557,3054,3055,3056,3057,3058,3059,3060,3061,3062,3063,3064,3065,3066,
+3067,1558,3068,3069,3070,3071,3072,3073,3074,3075,3076,1559,3077,3078,3079,3080,
+3081,3082,3083,1253,3084,3085,3086,3087,3088,3089,3090,3091,3092,3093,3094,3095,
+3096,3097,3098,3099,3100,3101,3102,3103,3104,3105,3106,3107,3108,1152,3109,3110,
+3111,3112,3113,1560,3114,3115,3116,3117,1111,3118,3119,3120,3121,3122,3123,3124,
+3125,3126,3127,3128,3129,3130,3131,3132,3133,3134,3135,3136,3137,3138,3139,3140,
+3141,3142,3143,3144,3145,3146,3147,3148,3149,3150,3151,3152,3153,3154,3155,3156,
+3157,3158,3159,3160,3161,3162,3163,3164,3165,3166,3167,3168,3169,3170,3171,3172,
+3173,3174,3175,3176,1333,3177,3178,3179,3180,3181,3182,3183,3184,3185,3186,3187,
+3188,3189,1561,3190,3191,1334,3192,3193,3194,3195,3196,3197,3198,3199,3200,3201,
+3202,3203,3204,3205,3206,3207,3208,3209,3210,3211,3212,3213,3214,3215,3216,3217,
+3218,3219,3220,3221,3222,3223,3224,3225,3226,3227,3228,3229,3230,3231,3232,3233,
+3234,1562,3235,3236,3237,3238,3239,3240,3241,3242,3243,3244,3245,3246,3247,3248,
+3249,3250,3251,3252,3253,3254,3255,3256,3257,3258,3259,3260,3261,3262,3263,3264,
+3265,3266,3267,3268,3269,3270,3271,3272,3273,3274,3275,3276,3277,1563,3278,3279,
+3280,3281,3282,3283,3284,3285,3286,3287,3288,3289,3290,3291,3292,3293,3294,3295,
+3296,3297,3298,3299,3300,3301,3302,3303,3304,3305,3306,3307,3308,3309,3310,3311,
+3312,3313,3314,3315,3316,3317,3318,3319,3320,3321,3322,3323,3324,3325,3326,3327,
+3328,3329,3330,3331,3332,3333,3334,3335,3336,3337,3338,3339,3340,3341,3342,3343,
+3344,3345,3346,3347,3348,3349,3350,3351,3352,3353,3354,3355,3356,3357,3358,3359,
+3360,3361,3362,3363,3364,1335,3365,3366,3367,3368,3369,3370,3371,3372,3373,3374,
+3375,3376,3377,3378,3379,3380,3381,3382,3383,3384,3385,3386,3387,1336,3388,3389,
+3390,3391,3392,3393,3394,3395,3396,3397,3398,3399,3400,3401,3402,3403,3404,3405,
+3406,3407,3408,3409,3410,3411,3412,3413,3414,1337,3415,3416,3417,3418,3419,1338,
+3420,3421,3422,1564,1565,3423,3424,3425,3426,3427,3428,3429,3430,3431,1254,3432,
+3433,3434,1339,3435,3436,3437,3438,3439,1566,3440,3441,3442,3443,3444,3445,3446,
+3447,3448,3449,3450,3451,3452,3453,3454,1255,3455,3456,3457,3458,3459,1567,1191,
+3460,1568,1569,3461,3462,3463,1570,3464,3465,3466,3467,3468,1571,3469,3470,3471,
+3472,3473,1572,3474,3475,3476,3477,3478,3479,3480,3481,3482,3483,3484,3485,3486,
+1340,3487,3488,3489,3490,3491,3492,1021,3493,3494,3495,3496,3497,3498,1573,3499,
+1341,3500,3501,3502,3503,3504,3505,3506,3507,3508,3509,3510,3511,1342,3512,3513,
+3514,3515,3516,1574,1343,3517,3518,3519,1575,3520,1576,3521,3522,3523,3524,3525,
+3526,3527,3528,3529,3530,3531,3532,3533,3534,3535,3536,3537,3538,3539,3540,3541,
+3542,3543,3544,3545,3546,3547,3548,3549,3550,3551,3552,3553,3554,3555,3556,3557,
+3558,3559,3560,3561,3562,3563,3564,3565,3566,3567,3568,3569,3570,3571,3572,3573,
+3574,3575,3576,3577,3578,3579,3580,1577,3581,3582,1578,3583,3584,3585,3586,3587,
+3588,3589,3590,3591,3592,3593,3594,3595,3596,3597,3598,3599,3600,3601,3602,3603,
+3604,1579,3605,3606,3607,3608,3609,3610,3611,3612,3613,3614,3615,3616,3617,3618,
+3619,3620,3621,3622,3623,3624,3625,3626,3627,3628,3629,1580,3630,3631,1581,3632,
+3633,3634,3635,3636,3637,3638,3639,3640,3641,3642,3643,3644,3645,3646,3647,3648,
+3649,3650,3651,3652,3653,3654,3655,3656,1582,3657,3658,3659,3660,3661,3662,3663,
+3664,3665,3666,3667,3668,3669,3670,3671,3672,3673,3674,3675,3676,3677,3678,3679,
+3680,3681,3682,3683,3684,3685,3686,3687,3688,3689,3690,3691,3692,3693,3694,3695,
+3696,3697,3698,3699,3700,1192,3701,3702,3703,3704,1256,3705,3706,3707,3708,1583,
+1257,3709,3710,3711,3712,3713,3714,3715,3716,1584,3717,3718,3719,3720,3721,3722,
+3723,3724,3725,3726,3727,3728,3729,3730,3731,3732,3733,3734,3735,3736,3737,3738,
+3739,3740,3741,3742,3743,3744,3745,1344,3746,3747,3748,3749,3750,3751,3752,3753,
+3754,3755,3756,1585,3757,3758,3759,3760,3761,3762,3763,3764,3765,3766,1586,3767,
+3768,3769,3770,3771,3772,3773,3774,3775,3776,3777,3778,1345,3779,3780,3781,3782,
+3783,3784,3785,3786,3787,3788,3789,3790,3791,3792,3793,3794,3795,1346,1587,3796,
+3797,1588,3798,3799,3800,3801,3802,3803,3804,3805,3806,1347,3807,3808,3809,3810,
+3811,1589,3812,3813,3814,3815,3816,3817,3818,3819,3820,3821,1590,3822,3823,1591,
+1348,3824,3825,3826,3827,3828,3829,3830,1592,3831,3832,1593,3833,3834,3835,3836,
+3837,3838,3839,3840,3841,3842,3843,3844,1349,3845,3846,3847,3848,3849,3850,3851,
+3852,3853,3854,3855,3856,3857,3858,1594,3859,3860,3861,3862,3863,3864,3865,3866,
+3867,3868,3869,1595,3870,3871,3872,3873,1596,3874,3875,3876,3877,3878,3879,3880,
+3881,3882,3883,3884,3885,3886,1597,3887,3888,3889,3890,3891,3892,3893,3894,3895,
+1598,3896,3897,3898,1599,1600,3899,1350,3900,1351,3901,3902,1352,3903,3904,3905,
+3906,3907,3908,3909,3910,3911,3912,3913,3914,3915,3916,3917,3918,3919,3920,3921,
+3922,3923,3924,1258,3925,3926,3927,3928,3929,3930,3931,1193,3932,1601,3933,3934,
+3935,3936,3937,3938,3939,3940,3941,3942,3943,1602,3944,3945,3946,3947,3948,1603,
+3949,3950,3951,3952,3953,3954,3955,3956,3957,3958,3959,3960,3961,3962,3963,3964,
+3965,1604,3966,3967,3968,3969,3970,3971,3972,3973,3974,3975,3976,3977,1353,3978,
+3979,3980,3981,3982,3983,3984,3985,3986,3987,3988,3989,3990,3991,1354,3992,3993,
+3994,3995,3996,3997,3998,3999,4000,4001,4002,4003,4004,4005,4006,4007,4008,4009,
+4010,4011,4012,4013,4014,4015,4016,4017,4018,4019,4020,4021,4022,4023,1355,4024,
+4025,4026,4027,4028,4029,4030,4031,4032,4033,4034,4035,4036,4037,4038,4039,4040,
+1605,4041,4042,4043,4044,4045,4046,4047,4048,4049,4050,4051,4052,4053,4054,4055,
+4056,4057,4058,4059,4060,1606,4061,4062,4063,4064,1607,4065,4066,4067,4068,4069,
+4070,4071,4072,4073,4074,4075,4076,1194,4077,4078,1608,4079,4080,4081,4082,4083,
+4084,4085,4086,4087,1609,4088,4089,4090,4091,4092,4093,4094,4095,4096,4097,4098,
+4099,4100,4101,4102,4103,4104,4105,4106,4107,4108,1259,4109,4110,4111,4112,4113,
+4114,4115,4116,4117,4118,4119,4120,4121,4122,4123,4124,1195,4125,4126,4127,1610,
+4128,4129,4130,4131,4132,4133,4134,4135,4136,4137,1356,4138,4139,4140,4141,4142,
+4143,4144,1611,4145,4146,4147,4148,4149,4150,4151,4152,4153,4154,4155,4156,4157,
+4158,4159,4160,4161,4162,4163,4164,4165,4166,4167,4168,4169,4170,4171,4172,4173,
+4174,4175,4176,4177,4178,4179,4180,4181,4182,4183,4184,4185,4186,4187,4188,4189,
+4190,4191,4192,4193,4194,4195,4196,4197,4198,4199,4200,4201,4202,4203,4204,4205,
+4206,4207,4208,4209,4210,4211,4212,4213,4214,4215,4216,4217,4218,4219,1612,4220,
+4221,4222,4223,4224,4225,4226,4227,1357,4228,1613,4229,4230,4231,4232,4233,4234,
+4235,4236,4237,4238,4239,4240,4241,4242,4243,1614,4244,4245,4246,4247,4248,4249,
+4250,4251,4252,4253,4254,4255,4256,4257,4258,4259,4260,4261,4262,4263,4264,4265,
+4266,4267,4268,4269,4270,1196,1358,4271,4272,4273,4274,4275,4276,4277,4278,4279,
+4280,4281,4282,4283,4284,4285,4286,4287,1615,4288,4289,4290,4291,4292,4293,4294,
+4295,4296,4297,4298,4299,4300,4301,4302,4303,4304,4305,4306,4307,4308,4309,4310,
+4311,4312,4313,4314,4315,4316,4317,4318,4319,4320,4321,4322,4323,4324,4325,4326,
+4327,4328,4329,4330,4331,4332,4333,4334,1616,4335,4336,4337,4338,4339,4340,4341,
+4342,4343,4344,4345,4346,4347,4348,4349,4350,4351,4352,4353,4354,4355,4356,4357,
+4358,4359,4360,1617,4361,4362,4363,4364,4365,1618,4366,4367,4368,4369,4370,4371,
+4372,4373,4374,4375,4376,4377,4378,4379,4380,4381,4382,4383,4384,4385,4386,4387,
+4388,4389,4390,4391,4392,4393,4394,4395,4396,4397,4398,4399,4400,4401,4402,4403,
+4404,4405,4406,4407,4408,4409,4410,4411,4412,4413,4414,4415,4416,1619,4417,4418,
+4419,4420,4421,4422,4423,4424,4425,1112,4426,4427,4428,4429,4430,1620,4431,4432,
+4433,4434,4435,4436,4437,4438,4439,4440,4441,4442,1260,1261,4443,4444,4445,4446,
+4447,4448,4449,4450,4451,4452,4453,4454,4455,1359,4456,4457,4458,4459,4460,4461,
+4462,4463,4464,4465,1621,4466,4467,4468,4469,4470,4471,4472,4473,4474,4475,4476,
+4477,4478,4479,4480,4481,4482,4483,4484,4485,4486,4487,4488,4489,1055,4490,4491,
+4492,4493,4494,4495,4496,4497,4498,4499,4500,4501,4502,4503,4504,4505,4506,4507,
+4508,4509,4510,4511,4512,4513,4514,4515,4516,4517,4518,1622,4519,4520,4521,1623,
+4522,4523,4524,4525,4526,4527,4528,4529,4530,4531,4532,4533,4534,4535,1360,4536,
+4537,4538,4539,4540,4541,4542,4543, 975,4544,4545,4546,4547,4548,4549,4550,4551,
+4552,4553,4554,4555,4556,4557,4558,4559,4560,4561,4562,4563,4564,4565,4566,4567,
+4568,4569,4570,4571,1624,4572,4573,4574,4575,4576,1625,4577,4578,4579,4580,4581,
+4582,4583,4584,1626,4585,4586,4587,4588,4589,4590,4591,4592,4593,4594,4595,1627,
+4596,4597,4598,4599,4600,4601,4602,4603,4604,4605,4606,4607,4608,4609,4610,4611,
+4612,4613,4614,4615,1628,4616,4617,4618,4619,4620,4621,4622,4623,4624,4625,4626,
+4627,4628,4629,4630,4631,4632,4633,4634,4635,4636,4637,4638,4639,4640,4641,4642,
+4643,4644,4645,4646,4647,4648,4649,1361,4650,4651,4652,4653,4654,4655,4656,4657,
+4658,4659,4660,4661,1362,4662,4663,4664,4665,4666,4667,4668,4669,4670,4671,4672,
+4673,4674,4675,4676,4677,4678,4679,4680,4681,4682,1629,4683,4684,4685,4686,4687,
+1630,4688,4689,4690,4691,1153,4692,4693,4694,1113,4695,4696,4697,4698,4699,4700,
+4701,4702,4703,4704,4705,4706,4707,4708,4709,4710,4711,1197,4712,4713,4714,4715,
+4716,4717,4718,4719,4720,4721,4722,4723,4724,4725,4726,4727,4728,4729,4730,4731,
+4732,4733,4734,4735,1631,4736,1632,4737,4738,4739,4740,4741,4742,4743,4744,1633,
+4745,4746,4747,4748,4749,1262,4750,4751,4752,4753,4754,1363,4755,4756,4757,4758,
+4759,4760,4761,4762,4763,4764,4765,4766,4767,4768,1634,4769,4770,4771,4772,4773,
+4774,4775,4776,4777,4778,1635,4779,4780,4781,4782,4783,4784,4785,4786,4787,4788,
+4789,1636,4790,4791,4792,4793,4794,4795,4796,4797,4798,4799,4800,4801,4802,4803,
+4804,4805,4806,1637,4807,4808,4809,1638,4810,4811,4812,4813,4814,4815,4816,4817,
+4818,1639,4819,4820,4821,4822,4823,4824,4825,4826,4827,4828,4829,4830,4831,4832,
+4833,1077,4834,4835,4836,4837,4838,4839,4840,4841,4842,4843,4844,4845,4846,4847,
+4848,4849,4850,4851,4852,4853,4854,4855,4856,4857,4858,4859,4860,4861,4862,4863,
+4864,4865,4866,4867,4868,4869,4870,4871,4872,4873,4874,4875,4876,4877,4878,4879,
+4880,4881,4882,4883,1640,4884,4885,1641,4886,4887,4888,4889,4890,4891,4892,4893,
+4894,4895,4896,4897,4898,4899,4900,4901,4902,4903,4904,4905,4906,4907,4908,4909,
+4910,4911,1642,4912,4913,4914,1364,4915,4916,4917,4918,4919,4920,4921,4922,4923,
+4924,4925,4926,4927,4928,4929,4930,4931,1643,4932,4933,4934,4935,4936,4937,4938,
+4939,4940,4941,4942,4943,4944,4945,4946,4947,4948,4949,4950,4951,4952,4953,4954,
+4955,4956,4957,4958,4959,4960,4961,4962,4963,4964,4965,4966,4967,4968,4969,4970,
+4971,4972,4973,4974,4975,4976,4977,4978,4979,4980,1644,4981,4982,4983,4984,1645,
+4985,4986,1646,4987,4988,4989,4990,4991,4992,4993,4994,4995,4996,4997,4998,4999,
+5000,5001,5002,5003,5004,5005,1647,5006,1648,5007,5008,5009,5010,5011,5012,1078,
+5013,5014,5015,5016,5017,5018,5019,5020,5021,5022,5023,5024,5025,5026,5027,5028,
+1365,5029,5030,5031,5032,5033,5034,5035,5036,5037,5038,5039,1649,5040,5041,5042,
+5043,5044,5045,1366,5046,5047,5048,5049,5050,5051,5052,5053,5054,5055,1650,5056,
+5057,5058,5059,5060,5061,5062,5063,5064,5065,5066,5067,5068,5069,5070,5071,5072,
+5073,5074,5075,5076,5077,1651,5078,5079,5080,5081,5082,5083,5084,5085,5086,5087,
+5088,5089,5090,5091,5092,5093,5094,5095,5096,5097,5098,5099,5100,5101,5102,5103,
+5104,5105,5106,5107,5108,5109,5110,1652,5111,5112,5113,5114,5115,5116,5117,5118,
+1367,5119,5120,5121,5122,5123,5124,5125,5126,5127,5128,5129,1653,5130,5131,5132,
+5133,5134,5135,5136,5137,5138,5139,5140,5141,5142,5143,5144,5145,5146,5147,5148,
+5149,1368,5150,1654,5151,1369,5152,5153,5154,5155,5156,5157,5158,5159,5160,5161,
+5162,5163,5164,5165,5166,5167,5168,5169,5170,5171,5172,5173,5174,5175,5176,5177,
+5178,1370,5179,5180,5181,5182,5183,5184,5185,5186,5187,5188,5189,5190,5191,5192,
+5193,5194,5195,5196,5197,5198,1655,5199,5200,5201,5202,1656,5203,5204,5205,5206,
+1371,5207,1372,5208,5209,5210,5211,1373,5212,5213,1374,5214,5215,5216,5217,5218,
+5219,5220,5221,5222,5223,5224,5225,5226,5227,5228,5229,5230,5231,5232,5233,5234,
+5235,5236,5237,5238,5239,5240,5241,5242,5243,5244,5245,5246,5247,1657,5248,5249,
+5250,5251,1658,1263,5252,5253,5254,5255,5256,1375,5257,5258,5259,5260,5261,5262,
+5263,5264,5265,5266,5267,5268,5269,5270,5271,5272,5273,5274,5275,5276,5277,5278,
+5279,5280,5281,5282,5283,1659,5284,5285,5286,5287,5288,5289,5290,5291,5292,5293,
+5294,5295,5296,5297,5298,5299,5300,1660,5301,5302,5303,5304,5305,5306,5307,5308,
+5309,5310,5311,5312,5313,5314,5315,5316,5317,5318,5319,5320,5321,1376,5322,5323,
+5324,5325,5326,5327,5328,5329,5330,5331,5332,5333,1198,5334,5335,5336,5337,5338,
+5339,5340,5341,5342,5343,1661,5344,5345,5346,5347,5348,5349,5350,5351,5352,5353,
+5354,5355,5356,5357,5358,5359,5360,5361,5362,5363,5364,5365,5366,5367,5368,5369,
+5370,5371,5372,5373,5374,5375,5376,5377,5378,5379,5380,5381,5382,5383,5384,5385,
+5386,5387,5388,5389,5390,5391,5392,5393,5394,5395,5396,5397,5398,1264,5399,5400,
+5401,5402,5403,5404,5405,5406,5407,5408,5409,5410,5411,5412,1662,5413,5414,5415,
+5416,1663,5417,5418,5419,5420,5421,5422,5423,5424,5425,5426,5427,5428,5429,5430,
+5431,5432,5433,5434,5435,5436,5437,5438,1664,5439,5440,5441,5442,5443,5444,5445,
+5446,5447,5448,5449,5450,5451,5452,5453,5454,5455,5456,5457,5458,5459,5460,5461,
+5462,5463,5464,5465,5466,5467,5468,5469,5470,5471,5472,5473,5474,5475,5476,5477,
+5478,1154,5479,5480,5481,5482,5483,5484,5485,1665,5486,5487,5488,5489,5490,5491,
+5492,5493,5494,5495,5496,5497,5498,5499,5500,5501,5502,5503,5504,5505,5506,5507,
+5508,5509,5510,5511,5512,5513,5514,5515,5516,5517,5518,5519,5520,5521,5522,5523,
+5524,5525,5526,5527,5528,5529,5530,5531,5532,5533,5534,5535,5536,5537,5538,5539,
+5540,5541,5542,5543,5544,5545,5546,5547,5548,1377,5549,5550,5551,5552,5553,5554,
+5555,5556,5557,5558,5559,5560,5561,5562,5563,5564,5565,5566,5567,5568,5569,5570,
+1114,5571,5572,5573,5574,5575,5576,5577,5578,5579,5580,5581,5582,5583,5584,5585,
+5586,5587,5588,5589,5590,5591,5592,1378,5593,5594,5595,5596,5597,5598,5599,5600,
+5601,5602,5603,5604,5605,5606,5607,5608,5609,5610,5611,5612,5613,5614,1379,5615,
+5616,5617,5618,5619,5620,5621,5622,5623,5624,5625,5626,5627,5628,5629,5630,5631,
+5632,5633,5634,1380,5635,5636,5637,5638,5639,5640,5641,5642,5643,5644,5645,5646,
+5647,5648,5649,1381,1056,5650,5651,5652,5653,5654,5655,5656,5657,5658,5659,5660,
+1666,5661,5662,5663,5664,5665,5666,5667,5668,1667,5669,1668,5670,5671,5672,5673,
+5674,5675,5676,5677,5678,1155,5679,5680,5681,5682,5683,5684,5685,5686,5687,5688,
+5689,5690,5691,5692,5693,5694,5695,5696,5697,5698,1669,5699,5700,5701,5702,5703,
+5704,5705,1670,5706,5707,5708,5709,5710,1671,5711,5712,5713,5714,1382,5715,5716,
+5717,5718,5719,5720,5721,5722,5723,5724,5725,1672,5726,5727,1673,1674,5728,5729,
+5730,5731,5732,5733,5734,5735,5736,1675,5737,5738,5739,5740,5741,5742,5743,5744,
+1676,5745,5746,5747,5748,5749,5750,5751,1383,5752,5753,5754,5755,5756,5757,5758,
+5759,5760,5761,5762,5763,5764,5765,5766,5767,5768,1677,5769,5770,5771,5772,5773,
+1678,5774,5775,5776, 998,5777,5778,5779,5780,5781,5782,5783,5784,5785,1384,5786,
+5787,5788,5789,5790,5791,5792,5793,5794,5795,5796,5797,5798,5799,5800,1679,5801,
+5802,5803,1115,1116,5804,5805,5806,5807,5808,5809,5810,5811,5812,5813,5814,5815,
+5816,5817,5818,5819,5820,5821,5822,5823,5824,5825,5826,5827,5828,5829,5830,5831,
+5832,5833,5834,5835,5836,5837,5838,5839,5840,5841,5842,5843,5844,5845,5846,5847,
+5848,5849,5850,5851,5852,5853,5854,5855,1680,5856,5857,5858,5859,5860,5861,5862,
+5863,5864,1681,5865,5866,5867,1682,5868,5869,5870,5871,5872,5873,5874,5875,5876,
+5877,5878,5879,1683,5880,1684,5881,5882,5883,5884,1685,5885,5886,5887,5888,5889,
+5890,5891,5892,5893,5894,5895,5896,5897,5898,5899,5900,5901,5902,5903,5904,5905,
+5906,5907,1686,5908,5909,5910,5911,5912,5913,5914,5915,5916,5917,5918,5919,5920,
+5921,5922,5923,5924,5925,5926,5927,5928,5929,5930,5931,5932,5933,5934,5935,1687,
+5936,5937,5938,5939,5940,5941,5942,5943,5944,5945,5946,5947,5948,5949,5950,5951,
+5952,1688,1689,5953,1199,5954,5955,5956,5957,5958,5959,5960,5961,1690,5962,5963,
+5964,5965,5966,5967,5968,5969,5970,5971,5972,5973,5974,5975,5976,5977,5978,5979,
+5980,5981,1385,5982,1386,5983,5984,5985,5986,5987,5988,5989,5990,5991,5992,5993,
+5994,5995,5996,5997,5998,5999,6000,6001,6002,6003,6004,6005,6006,6007,6008,6009,
+6010,6011,6012,6013,6014,6015,6016,6017,6018,6019,6020,6021,6022,6023,6024,6025,
+6026,6027,1265,6028,6029,1691,6030,6031,6032,6033,6034,6035,6036,6037,6038,6039,
+6040,6041,6042,6043,6044,6045,6046,6047,6048,6049,6050,6051,6052,6053,6054,6055,
+6056,6057,6058,6059,6060,6061,6062,6063,6064,6065,6066,6067,6068,6069,6070,6071,
+6072,6073,6074,6075,6076,6077,6078,6079,6080,6081,6082,6083,6084,1692,6085,6086,
+6087,6088,6089,6090,6091,6092,6093,6094,6095,6096,6097,6098,6099,6100,6101,6102,
+6103,6104,6105,6106,6107,6108,6109,6110,6111,6112,6113,6114,6115,6116,6117,6118,
+6119,6120,6121,6122,6123,6124,6125,6126,6127,6128,6129,6130,6131,1693,6132,6133,
+6134,6135,6136,1694,6137,6138,6139,6140,6141,1695,6142,6143,6144,6145,6146,6147,
+6148,6149,6150,6151,6152,6153,6154,6155,6156,6157,6158,6159,6160,6161,6162,6163,
+6164,6165,6166,6167,6168,6169,6170,6171,6172,6173,6174,6175,6176,6177,6178,6179,
+6180,6181,6182,6183,6184,6185,1696,6186,6187,6188,6189,6190,6191,6192,6193,6194,
+6195,6196,6197,6198,6199,6200,6201,6202,6203,6204,6205,6206,6207,6208,6209,6210,
+6211,6212,6213,6214,6215,6216,6217,6218,6219,1697,6220,6221,6222,6223,6224,6225,
+6226,6227,6228,6229,6230,6231,6232,6233,6234,6235,6236,6237,6238,6239,6240,6241,
+6242,6243,6244,6245,6246,6247,6248,6249,6250,6251,6252,6253,1698,6254,6255,6256,
+6257,6258,6259,6260,6261,6262,6263,1200,6264,6265,6266,6267,6268,6269,6270,6271,  #1024
+6272,6273,6274,6275,6276,6277,6278,6279,6280,6281,6282,6283,6284,6285,6286,6287,
+6288,6289,6290,6291,6292,6293,6294,6295,6296,6297,6298,6299,6300,6301,6302,1699,
+6303,6304,1700,6305,6306,6307,6308,6309,6310,6311,6312,6313,6314,6315,6316,6317,
+6318,6319,6320,6321,6322,6323,6324,6325,6326,6327,6328,6329,6330,6331,6332,6333,
+6334,6335,6336,6337,6338,6339,1701,6340,6341,6342,6343,6344,1387,6345,6346,6347,
+6348,6349,6350,6351,6352,6353,6354,6355,6356,6357,6358,6359,6360,6361,6362,6363,
+6364,6365,6366,6367,6368,6369,6370,6371,6372,6373,6374,6375,6376,6377,6378,6379,
+6380,6381,6382,6383,6384,6385,6386,6387,6388,6389,6390,6391,6392,6393,6394,6395,
+6396,6397,6398,6399,6400,6401,6402,6403,6404,6405,6406,6407,6408,6409,6410,6411,
+6412,6413,1702,6414,6415,6416,6417,6418,6419,6420,6421,6422,1703,6423,6424,6425,
+6426,6427,6428,6429,6430,6431,6432,6433,6434,6435,6436,6437,6438,1704,6439,6440,
+6441,6442,6443,6444,6445,6446,6447,6448,6449,6450,6451,6452,6453,6454,6455,6456,
+6457,6458,6459,6460,6461,6462,6463,6464,6465,6466,6467,6468,6469,6470,6471,6472,
+6473,6474,6475,6476,6477,6478,6479,6480,6481,6482,6483,6484,6485,6486,6487,6488,
+6489,6490,6491,6492,6493,6494,6495,6496,6497,6498,6499,6500,6501,6502,6503,1266,
+6504,6505,6506,6507,6508,6509,6510,6511,6512,6513,6514,6515,6516,6517,6518,6519,
+6520,6521,6522,6523,6524,6525,6526,6527,6528,6529,6530,6531,6532,6533,6534,6535,
+6536,6537,6538,6539,6540,6541,6542,6543,6544,6545,6546,6547,6548,6549,6550,6551,
+1705,1706,6552,6553,6554,6555,6556,6557,6558,6559,6560,6561,6562,6563,6564,6565,
+6566,6567,6568,6569,6570,6571,6572,6573,6574,6575,6576,6577,6578,6579,6580,6581,
+6582,6583,6584,6585,6586,6587,6588,6589,6590,6591,6592,6593,6594,6595,6596,6597,
+6598,6599,6600,6601,6602,6603,6604,6605,6606,6607,6608,6609,6610,6611,6612,6613,
+6614,6615,6616,6617,6618,6619,6620,6621,6622,6623,6624,6625,6626,6627,6628,6629,
+6630,6631,6632,6633,6634,6635,6636,6637,1388,6638,6639,6640,6641,6642,6643,6644,
+1707,6645,6646,6647,6648,6649,6650,6651,6652,6653,6654,6655,6656,6657,6658,6659,
+6660,6661,6662,6663,1708,6664,6665,6666,6667,6668,6669,6670,6671,6672,6673,6674,
+1201,6675,6676,6677,6678,6679,6680,6681,6682,6683,6684,6685,6686,6687,6688,6689,
+6690,6691,6692,6693,6694,6695,6696,6697,6698,6699,6700,6701,6702,6703,6704,6705,
+6706,6707,6708,6709,6710,6711,6712,6713,6714,6715,6716,6717,6718,6719,6720,6721,
+6722,6723,6724,6725,1389,6726,6727,6728,6729,6730,6731,6732,6733,6734,6735,6736,
+1390,1709,6737,6738,6739,6740,6741,6742,1710,6743,6744,6745,6746,1391,6747,6748,
+6749,6750,6751,6752,6753,6754,6755,6756,6757,1392,6758,6759,6760,6761,6762,6763,
+6764,6765,6766,6767,6768,6769,6770,6771,6772,6773,6774,6775,6776,6777,6778,6779,
+6780,1202,6781,6782,6783,6784,6785,6786,6787,6788,6789,6790,6791,6792,6793,6794,
+6795,6796,6797,6798,6799,6800,6801,6802,6803,6804,6805,6806,6807,6808,6809,1711,
+6810,6811,6812,6813,6814,6815,6816,6817,6818,6819,6820,6821,6822,6823,6824,6825,
+6826,6827,6828,6829,6830,6831,6832,6833,6834,6835,6836,1393,6837,6838,6839,6840,
+6841,6842,6843,6844,6845,6846,6847,6848,6849,6850,6851,6852,6853,6854,6855,6856,
+6857,6858,6859,6860,6861,6862,6863,6864,6865,6866,6867,6868,6869,6870,6871,6872,
+6873,6874,6875,6876,6877,6878,6879,6880,6881,6882,6883,6884,6885,6886,6887,6888,
+6889,6890,6891,6892,6893,6894,6895,6896,6897,6898,6899,6900,6901,6902,1712,6903,
+6904,6905,6906,6907,6908,6909,6910,1713,6911,6912,6913,6914,6915,6916,6917,6918,
+6919,6920,6921,6922,6923,6924,6925,6926,6927,6928,6929,6930,6931,6932,6933,6934,
+6935,6936,6937,6938,6939,6940,6941,6942,6943,6944,6945,6946,6947,6948,6949,6950,
+6951,6952,6953,6954,6955,6956,6957,6958,6959,6960,6961,6962,6963,6964,6965,6966,
+6967,6968,6969,6970,6971,6972,6973,6974,1714,6975,6976,6977,6978,6979,6980,6981,
+6982,6983,6984,6985,6986,6987,6988,1394,6989,6990,6991,6992,6993,6994,6995,6996,
+6997,6998,6999,7000,1715,7001,7002,7003,7004,7005,7006,7007,7008,7009,7010,7011,
+7012,7013,7014,7015,7016,7017,7018,7019,7020,7021,7022,7023,7024,7025,7026,7027,
+7028,1716,7029,7030,7031,7032,7033,7034,7035,7036,7037,7038,7039,7040,7041,7042,
+7043,7044,7045,7046,7047,7048,7049,7050,7051,7052,7053,7054,7055,7056,7057,7058,
+7059,7060,7061,7062,7063,7064,7065,7066,7067,7068,7069,7070,7071,7072,7073,7074,
+7075,7076,7077,7078,7079,7080,7081,7082,7083,7084,7085,7086,7087,7088,7089,7090,
+7091,7092,7093,7094,7095,7096,7097,7098,7099,7100,7101,7102,7103,7104,7105,7106,
+7107,7108,7109,7110,7111,7112,7113,7114,7115,7116,7117,7118,7119,7120,7121,7122,
+7123,7124,7125,7126,7127,7128,7129,7130,7131,7132,7133,7134,7135,7136,7137,7138,
+7139,7140,7141,7142,7143,7144,7145,7146,7147,7148,7149,7150,7151,7152,7153,7154,
+7155,7156,7157,7158,7159,7160,7161,7162,7163,7164,7165,7166,7167,7168,7169,7170,
+7171,7172,7173,7174,7175,7176,7177,7178,7179,7180,7181,7182,7183,7184,7185,7186,
+7187,7188,7189,7190,7191,7192,7193,7194,7195,7196,7197,7198,7199,7200,7201,7202,
+7203,7204,7205,7206,7207,1395,7208,7209,7210,7211,7212,7213,1717,7214,7215,7216,
+7217,7218,7219,7220,7221,7222,7223,7224,7225,7226,7227,7228,7229,7230,7231,7232,
+7233,7234,7235,7236,7237,7238,7239,7240,7241,7242,7243,7244,7245,7246,7247,7248,
+7249,7250,7251,7252,7253,7254,7255,7256,7257,7258,7259,7260,7261,7262,7263,7264,
+7265,7266,7267,7268,7269,7270,7271,7272,7273,7274,7275,7276,7277,7278,7279,7280,
+7281,7282,7283,7284,7285,7286,7287,7288,7289,7290,7291,7292,7293,7294,7295,7296,
+7297,7298,7299,7300,7301,7302,7303,7304,7305,7306,7307,7308,7309,7310,7311,7312,
+7313,1718,7314,7315,7316,7317,7318,7319,7320,7321,7322,7323,7324,7325,7326,7327,
+7328,7329,7330,7331,7332,7333,7334,7335,7336,7337,7338,7339,7340,7341,7342,7343,
+7344,7345,7346,7347,7348,7349,7350,7351,7352,7353,7354,7355,7356,7357,7358,7359,
+7360,7361,7362,7363,7364,7365,7366,7367,7368,7369,7370,7371,7372,7373,7374,7375,
+7376,7377,7378,7379,7380,7381,7382,7383,7384,7385,7386,7387,7388,7389,7390,7391,
+7392,7393,7394,7395,7396,7397,7398,7399,7400,7401,7402,7403,7404,7405,7406,7407,
+7408,7409,7410,7411,7412,7413,7414,7415,7416,7417,7418,7419,7420,7421,7422,7423,
+7424,7425,7426,7427,7428,7429,7430,7431,7432,7433,7434,7435,7436,7437,7438,7439,
+7440,7441,7442,7443,7444,7445,7446,7447,7448,7449,7450,7451,7452,7453,7454,7455,
+7456,7457,7458,7459,7460,7461,7462,7463,7464,7465,7466,7467,7468,7469,7470,7471,
+7472,7473,7474,7475,7476,7477,7478,7479,7480,7481,7482,7483,7484,7485,7486,7487,
+7488,7489,7490,7491,7492,7493,7494,7495,7496,7497,7498,7499,7500,7501,7502,7503,
+7504,7505,7506,7507,7508,7509,7510,7511,7512,7513,7514,7515,7516,7517,7518,7519,
+7520,7521,7522,7523,7524,7525,7526,7527,7528,7529,7530,7531,7532,7533,7534,7535,
+7536,7537,7538,7539,7540,7541,7542,7543,7544,7545,7546,7547,7548,7549,7550,7551,
+7552,7553,7554,7555,7556,7557,7558,7559,7560,7561,7562,7563,7564,7565,7566,7567,
+7568,7569,7570,7571,7572,7573,7574,7575,7576,7577,7578,7579,7580,7581,7582,7583,
+7584,7585,7586,7587,7588,7589,7590,7591,7592,7593,7594,7595,7596,7597,7598,7599,
+7600,7601,7602,7603,7604,7605,7606,7607,7608,7609,7610,7611,7612,7613,7614,7615,
+7616,7617,7618,7619,7620,7621,7622,7623,7624,7625,7626,7627,7628,7629,7630,7631,
+7632,7633,7634,7635,7636,7637,7638,7639,7640,7641,7642,7643,7644,7645,7646,7647,
+7648,7649,7650,7651,7652,7653,7654,7655,7656,7657,7658,7659,7660,7661,7662,7663,
+7664,7665,7666,7667,7668,7669,7670,7671,7672,7673,7674,7675,7676,7677,7678,7679,
+7680,7681,7682,7683,7684,7685,7686,7687,7688,7689,7690,7691,7692,7693,7694,7695,
+7696,7697,7698,7699,7700,7701,7702,7703,7704,7705,7706,7707,7708,7709,7710,7711,
+7712,7713,7714,7715,7716,7717,7718,7719,7720,7721,7722,7723,7724,7725,7726,7727,
+7728,7729,7730,7731,7732,7733,7734,7735,7736,7737,7738,7739,7740,7741,7742,7743,
+7744,7745,7746,7747,7748,7749,7750,7751,7752,7753,7754,7755,7756,7757,7758,7759,
+7760,7761,7762,7763,7764,7765,7766,7767,7768,7769,7770,7771,7772,7773,7774,7775,
+7776,7777,7778,7779,7780,7781,7782,7783,7784,7785,7786,7787,7788,7789,7790,7791,
+7792,7793,7794,7795,7796,7797,7798,7799,7800,7801,7802,7803,7804,7805,7806,7807,
+7808,7809,7810,7811,7812,7813,7814,7815,7816,7817,7818,7819,7820,7821,7822,7823,
+7824,7825,7826,7827,7828,7829,7830,7831,7832,7833,7834,7835,7836,7837,7838,7839,
+7840,7841,7842,7843,7844,7845,7846,7847,7848,7849,7850,7851,7852,7853,7854,7855,
+7856,7857,7858,7859,7860,7861,7862,7863,7864,7865,7866,7867,7868,7869,7870,7871,
+7872,7873,7874,7875,7876,7877,7878,7879,7880,7881,7882,7883,7884,7885,7886,7887,
+7888,7889,7890,7891,7892,7893,7894,7895,7896,7897,7898,7899,7900,7901,7902,7903,
+7904,7905,7906,7907,7908,7909,7910,7911,7912,7913,7914,7915,7916,7917,7918,7919,
+7920,7921,7922,7923,7924,7925,7926,7927,7928,7929,7930,7931,7932,7933,7934,7935,
+7936,7937,7938,7939,7940,7941,7942,7943,7944,7945,7946,7947,7948,7949,7950,7951,
+7952,7953,7954,7955,7956,7957,7958,7959,7960,7961,7962,7963,7964,7965,7966,7967,
+7968,7969,7970,7971,7972,7973,7974,7975,7976,7977,7978,7979,7980,7981,7982,7983,
+7984,7985,7986,7987,7988,7989,7990,7991,7992,7993,7994,7995,7996,7997,7998,7999,
+8000,8001,8002,8003,8004,8005,8006,8007,8008,8009,8010,8011,8012,8013,8014,8015,
+8016,8017,8018,8019,8020,8021,8022,8023,8024,8025,8026,8027,8028,8029,8030,8031,
+8032,8033,8034,8035,8036,8037,8038,8039,8040,8041,8042,8043,8044,8045,8046,8047,
+8048,8049,8050,8051,8052,8053,8054,8055,8056,8057,8058,8059,8060,8061,8062,8063,
+8064,8065,8066,8067,8068,8069,8070,8071,8072,8073,8074,8075,8076,8077,8078,8079,
+8080,8081,8082,8083,8084,8085,8086,8087,8088,8089,8090,8091,8092,8093,8094,8095,
+8096,8097,8098,8099,8100,8101,8102,8103,8104,8105,8106,8107,8108,8109,8110,8111,
+8112,8113,8114,8115,8116,8117,8118,8119,8120,8121,8122,8123,8124,8125,8126,8127,
+8128,8129,8130,8131,8132,8133,8134,8135,8136,8137,8138,8139,8140,8141,8142,8143,
+8144,8145,8146,8147,8148,8149,8150,8151,8152,8153,8154,8155,8156,8157,8158,8159,
+8160,8161,8162,8163,8164,8165,8166,8167,8168,8169,8170,8171,8172,8173,8174,8175,
+8176,8177,8178,8179,8180,8181,8182,8183,8184,8185,8186,8187,8188,8189,8190,8191,
+8192,8193,8194,8195,8196,8197,8198,8199,8200,8201,8202,8203,8204,8205,8206,8207,
+8208,8209,8210,8211,8212,8213,8214,8215,8216,8217,8218,8219,8220,8221,8222,8223,
+8224,8225,8226,8227,8228,8229,8230,8231,8232,8233,8234,8235,8236,8237,8238,8239,
+8240,8241,8242,8243,8244,8245,8246,8247,8248,8249,8250,8251,8252,8253,8254,8255,
+8256,8257,8258,8259,8260,8261,8262,8263,8264,8265,8266,8267,8268,8269,8270,8271,
+8272,8273,8274,8275,8276,8277,8278,8279,8280,8281,8282,8283,8284,8285,8286,8287,
+8288,8289,8290,8291,8292,8293,8294,8295,8296,8297,8298,8299,8300,8301,8302,8303,
+8304,8305,8306,8307,8308,8309,8310,8311,8312,8313,8314,8315,8316,8317,8318,8319,
+8320,8321,8322,8323,8324,8325,8326,8327,8328,8329,8330,8331,8332,8333,8334,8335,
+8336,8337,8338,8339,8340,8341,8342,8343,8344,8345,8346,8347,8348,8349,8350,8351,
+8352,8353,8354,8355,8356,8357,8358,8359,8360,8361,8362,8363,8364,8365,8366,8367,
+8368,8369,8370,8371,8372,8373,8374,8375,8376,8377,8378,8379,8380,8381,8382,8383,
+8384,8385,8386,8387,8388,8389,8390,8391,8392,8393,8394,8395,8396,8397,8398,8399,
+8400,8401,8402,8403,8404,8405,8406,8407,8408,8409,8410,8411,8412,8413,8414,8415,
+8416,8417,8418,8419,8420,8421,8422,8423,8424,8425,8426,8427,8428,8429,8430,8431,
+8432,8433,8434,8435,8436,8437,8438,8439,8440,8441,8442,8443,8444,8445,8446,8447,
+8448,8449,8450,8451,8452,8453,8454,8455,8456,8457,8458,8459,8460,8461,8462,8463,
+8464,8465,8466,8467,8468,8469,8470,8471,8472,8473,8474,8475,8476,8477,8478,8479,
+8480,8481,8482,8483,8484,8485,8486,8487,8488,8489,8490,8491,8492,8493,8494,8495,
+8496,8497,8498,8499,8500,8501,8502,8503,8504,8505,8506,8507,8508,8509,8510,8511,
+8512,8513,8514,8515,8516,8517,8518,8519,8520,8521,8522,8523,8524,8525,8526,8527,
+8528,8529,8530,8531,8532,8533,8534,8535,8536,8537,8538,8539,8540,8541,8542,8543,
+8544,8545,8546,8547,8548,8549,8550,8551,8552,8553,8554,8555,8556,8557,8558,8559,
+8560,8561,8562,8563,8564,8565,8566,8567,8568,8569,8570,8571,8572,8573,8574,8575,
+8576,8577,8578,8579,8580,8581,8582,8583,8584,8585,8586,8587,8588,8589,8590,8591,
+8592,8593,8594,8595,8596,8597,8598,8599,8600,8601,8602,8603,8604,8605,8606,8607,
+8608,8609,8610,8611,8612,8613,8614,8615,8616,8617,8618,8619,8620,8621,8622,8623,
+8624,8625,8626,8627,8628,8629,8630,8631,8632,8633,8634,8635,8636,8637,8638,8639,
+8640,8641,8642,8643,8644,8645,8646,8647,8648,8649,8650,8651,8652,8653,8654,8655,
+8656,8657,8658,8659,8660,8661,8662,8663,8664,8665,8666,8667,8668,8669,8670,8671,
+8672,8673,8674,8675,8676,8677,8678,8679,8680,8681,8682,8683,8684,8685,8686,8687,
+8688,8689,8690,8691,8692,8693,8694,8695,8696,8697,8698,8699,8700,8701,8702,8703,
+8704,8705,8706,8707,8708,8709,8710,8711,8712,8713,8714,8715,8716,8717,8718,8719,
+8720,8721,8722,8723,8724,8725,8726,8727,8728,8729,8730,8731,8732,8733,8734,8735,
+8736,8737,8738,8739,8740,8741
+]
+end
diff --git a/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/euckrprober.rb b/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/euckrprober.rb
new file mode 100644 (file)
index 0000000..7b45e0f
--- /dev/null
@@ -0,0 +1,42 @@
+######################## BEGIN LICENSE BLOCK ########################
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Jeff Hodges - port to Ruby
+#   Mark Pilgrim - port to Python
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+# 
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301  USA
+######################### END LICENSE BLOCK #########################
+
+module CharDet
+  class EUCKRProber < MultiByteCharSetProber
+    def initialize
+      super()
+      @_mCodingSM = CodingStateMachine.new(EUCKRSMModel)
+      @_mDistributionAnalyzer = EUCKRDistributionAnalysis.new()
+      reset()
+    end
+
+    def get_charset_name
+      return "EUC-KR"
+    end
+  end
+end
diff --git a/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/euctwfreq.rb b/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/euctwfreq.rb
new file mode 100644 (file)
index 0000000..207597a
--- /dev/null
@@ -0,0 +1,430 @@
+######################## BEGIN LICENSE BLOCK ########################
+# The Original Code is Mozilla Communicator client code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Jeff Hodges - port to Ruby
+#   Mark Pilgrim - port to Python
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+# 
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301  USA
+######################### END LICENSE BLOCK #########################
+
+# EUCTW frequency table
+# Converted from big5 work 
+# by Taiwan's Mandarin Promotion Council 
+# <http:#www.edu.tw:81/mandr/>
+
+# 128  --> 0.42261
+# 256  --> 0.57851
+# 512  --> 0.74851
+# 1024 --> 0.89384
+# 2048 --> 0.97583
+#
+# Idea Distribution Ratio = 0.74851/(1-0.74851) =2.98
+# Random Distribution Ration = 512/(5401-512)=0.105
+# 
+# Typical Distribution Ratio about 25% of Ideal one, still much higher than RDR
+
+module CharDet
+
+EUCTW_TYPICAL_DISTRIBUTION_RATIO = 0.75
+
+# Char to FreqOrder table , 
+EUCTW_TABLE_SIZE = 8102
+
+EUCTWCharToFreqOrder = [
+   1,1800,1506, 255,1431, 198,   9,  82,   6,7310, 177, 202,3615,1256,2808, 110, # 2742
+3735,  33,3241, 261,  76,  44,2113,  16,2931,2184,1176, 659,3868,  26,3404,2643, # 2758
+1198,3869,3313,4060, 410,2211, 302, 590, 361,1963,   8, 204,  58,4296,7311,1931, # 2774
+  63,7312,7313, 317,1614,  75, 222, 159,4061,2412,1480,7314,3500,3068, 224,2809, # 2790
+3616,   3,  10,3870,1471,  29,2774,1135,2852,1939, 873, 130,3242,1123, 312,7315, # 2806
+4297,2051, 507, 252, 682,7316, 142,1914, 124, 206,2932,  34,3501,3173,  64, 604, # 2822
+7317,2494,1976,1977, 155,1990, 645, 641,1606,7318,3405, 337,  72, 406,7319,  80, # 2838
+ 630, 238,3174,1509, 263, 939,1092,2644, 756,1440,1094,3406, 449,  69,2969, 591, # 2854
+ 179,2095, 471, 115,2034,1843,  60,  50,2970, 134, 806,1868, 734,2035,3407, 180, # 2870
+ 995,1607, 156, 537,2893, 688,7320, 319,1305, 779,2144, 514,2374, 298,4298, 359, # 2886
+2495,  90,2707,1338, 663,  11, 906,1099,2545,  20,2436, 182, 532,1716,7321, 732, # 2902
+1376,4062,1311,1420,3175,  25,2312,1056, 113, 399, 382,1949, 242,3408,2467, 529, # 2918
+3243, 475,1447,3617,7322, 117,  21, 656, 810,1297,2295,2329,3502,7323, 126,4063, # 2934
+ 706, 456, 150, 613,4299,  71,1118,2036,4064, 145,3069,  85, 835, 486,2114,1246, # 2950
+1426, 428, 727,1285,1015, 800, 106, 623, 303,1281,7324,2127,2354, 347,3736, 221, # 2966
+3503,3110,7325,1955,1153,4065,  83, 296,1199,3070, 192, 624,  93,7326, 822,1897, # 2982
+2810,3111, 795,2064, 991,1554,1542,1592,  27,  43,2853, 859, 139,1456, 860,4300, # 2998
+ 437, 712,3871, 164,2392,3112, 695, 211,3017,2096, 195,3872,1608,3504,3505,3618, # 3014
+3873, 234, 811,2971,2097,3874,2229,1441,3506,1615,2375, 668,2076,1638, 305, 228, # 3030
+1664,4301, 467, 415,7327, 262,2098,1593, 239, 108, 300, 200,1033, 512,1247,2077, # 3046
+7328,7329,2173,3176,3619,2673, 593, 845,1062,3244,  88,1723,2037,3875,1950, 212, # 3062
+ 266, 152, 149, 468,1898,4066,4302,  77, 187,7330,3018,  37,   5,2972,7331,3876, # 3078
+7332,7333,  39,2517,4303,2894,3177,2078,  55, 148,  74,4304, 545, 483,1474,1029, # 3094
+1665, 217,1869,1531,3113,1104,2645,4067,  24, 172,3507, 900,3877,3508,3509,4305, # 3110
+  32,1408,2811,1312, 329, 487,2355,2247,2708, 784,2674,   4,3019,3314,1427,1788, # 3126
+ 188, 109, 499,7334,3620,1717,1789, 888,1217,3020,4306,7335,3510,7336,3315,1520, # 3142
+3621,3878, 196,1034, 775,7337,7338, 929,1815, 249, 439,  38,7339,1063,7340, 794, # 3158
+3879,1435,2296,  46, 178,3245,2065,7341,2376,7342, 214,1709,4307, 804,  35, 707, # 3174
+ 324,3622,1601,2546, 140, 459,4068,7343,7344,1365, 839, 272, 978,2257,2572,3409, # 3190
+2128,1363,3623,1423, 697, 100,3071,  48,  70,1231, 495,3114,2193,7345,1294,7346, # 3206
+2079, 462, 586,1042,3246, 853, 256, 988, 185,2377,3410,1698, 434,1084,7347,3411, # 3222
+ 314,2615,2775,4308,2330,2331, 569,2280, 637,1816,2518, 757,1162,1878,1616,3412, # 3238
+ 287,1577,2115, 768,4309,1671,2854,3511,2519,1321,3737, 909,2413,7348,4069, 933, # 3254
+3738,7349,2052,2356,1222,4310, 765,2414,1322, 786,4311,7350,1919,1462,1677,2895, # 3270
+1699,7351,4312,1424,2437,3115,3624,2590,3316,1774,1940,3413,3880,4070, 309,1369, # 3286
+1130,2812, 364,2230,1653,1299,3881,3512,3882,3883,2646, 525,1085,3021, 902,2000, # 3302
+1475, 964,4313, 421,1844,1415,1057,2281, 940,1364,3116, 376,4314,4315,1381,   7, # 3318
+2520, 983,2378, 336,1710,2675,1845, 321,3414, 559,1131,3022,2742,1808,1132,1313, # 3334
+ 265,1481,1857,7352, 352,1203,2813,3247, 167,1089, 420,2814, 776, 792,1724,3513, # 3350
+4071,2438,3248,7353,4072,7354, 446, 229, 333,2743, 901,3739,1200,1557,4316,2647, # 3366
+1920, 395,2744,2676,3740,4073,1835, 125, 916,3178,2616,4317,7355,7356,3741,7357, # 3382
+7358,7359,4318,3117,3625,1133,2547,1757,3415,1510,2313,1409,3514,7360,2145, 438, # 3398
+2591,2896,2379,3317,1068, 958,3023, 461, 311,2855,2677,4074,1915,3179,4075,1978, # 3414
+ 383, 750,2745,2617,4076, 274, 539, 385,1278,1442,7361,1154,1964, 384, 561, 210, # 3430
+  98,1295,2548,3515,7362,1711,2415,1482,3416,3884,2897,1257, 129,7363,3742, 642, # 3446
+ 523,2776,2777,2648,7364, 141,2231,1333,  68, 176, 441, 876, 907,4077, 603,2592, # 3462
+ 710, 171,3417, 404, 549,  18,3118,2393,1410,3626,1666,7365,3516,4319,2898,4320, # 3478
+7366,2973, 368,7367, 146, 366,  99, 871,3627,1543, 748, 807,1586,1185,  22,2258, # 3494
+ 379,3743,3180,7368,3181, 505,1941,2618,1991,1382,2314,7369, 380,2357, 218, 702, # 3510
+1817,1248,3418,3024,3517,3318,3249,7370,2974,3628, 930,3250,3744,7371,  59,7372, # 3526
+ 585, 601,4078, 497,3419,1112,1314,4321,1801,7373,1223,1472,2174,7374, 749,1836, # 3542
+ 690,1899,3745,1772,3885,1476, 429,1043,1790,2232,2116, 917,4079, 447,1086,1629, # 3558
+7375, 556,7376,7377,2020,1654, 844,1090, 105, 550, 966,1758,2815,1008,1782, 686, # 3574
+1095,7378,2282, 793,1602,7379,3518,2593,4322,4080,2933,2297,4323,3746, 980,2496, # 3590
+ 544, 353, 527,4324, 908,2678,2899,7380, 381,2619,1942,1348,7381,1341,1252, 560, # 3606
+3072,7382,3420,2856,7383,2053, 973, 886,2080, 143,4325,7384,7385, 157,3886, 496, # 3622
+4081,  57, 840, 540,2038,4326,4327,3421,2117,1445, 970,2259,1748,1965,2081,4082, # 3638
+3119,1234,1775,3251,2816,3629, 773,1206,2129,1066,2039,1326,3887,1738,1725,4083, # 3654
+ 279,3120,  51,1544,2594, 423,1578,2130,2066, 173,4328,1879,7386,7387,1583, 264, # 3670
+ 610,3630,4329,2439, 280, 154,7388,7389,7390,1739, 338,1282,3073, 693,2857,1411, # 3686
+1074,3747,2440,7391,4330,7392,7393,1240, 952,2394,7394,2900,1538,2679, 685,1483, # 3702
+4084,2468,1436, 953,4085,2054,4331, 671,2395,  79,4086,2441,3252, 608, 567,2680, # 3718
+3422,4087,4088,1691, 393,1261,1791,2396,7395,4332,7396,7397,7398,7399,1383,1672, # 3734
+3748,3182,1464, 522,1119, 661,1150, 216, 675,4333,3888,1432,3519, 609,4334,2681, # 3750
+2397,7400,7401,7402,4089,3025,   0,7403,2469, 315, 231,2442, 301,3319,4335,2380, # 3766
+7404, 233,4090,3631,1818,4336,4337,7405,  96,1776,1315,2082,7406, 257,7407,1809, # 3782
+3632,2709,1139,1819,4091,2021,1124,2163,2778,1777,2649,7408,3074, 363,1655,3183, # 3798
+7409,2975,7410,7411,7412,3889,1567,3890, 718, 103,3184, 849,1443, 341,3320,2934, # 3814
+1484,7413,1712, 127,  67, 339,4092,2398, 679,1412, 821,7414,7415, 834, 738, 351, # 3830
+2976,2146, 846, 235,1497,1880, 418,1992,3749,2710, 186,1100,2147,2746,3520,1545, # 3846
+1355,2935,2858,1377, 583,3891,4093,2573,2977,7416,1298,3633,1078,2549,3634,2358, # 3862
+  78,3750,3751, 267,1289,2099,2001,1594,4094, 348, 369,1274,2194,2175,1837,4338, # 3878
+1820,2817,3635,2747,2283,2002,4339,2936,2748, 144,3321, 882,4340,3892,2749,3423, # 3894
+4341,2901,7417,4095,1726, 320,7418,3893,3026, 788,2978,7419,2818,1773,1327,2859, # 3910
+3894,2819,7420,1306,4342,2003,1700,3752,3521,2359,2650, 787,2022, 506, 824,3636, # 3926
+ 534, 323,4343,1044,3322,2023,1900, 946,3424,7421,1778,1500,1678,7422,1881,4344, # 3942
+ 165, 243,4345,3637,2521, 123, 683,4096, 764,4346,  36,3895,1792, 589,2902, 816, # 3958
+ 626,1667,3027,2233,1639,1555,1622,3753,3896,7423,3897,2860,1370,1228,1932, 891, # 3974
+2083,2903, 304,4097,7424, 292,2979,2711,3522, 691,2100,4098,1115,4347, 118, 662, # 3990
+7425, 611,1156, 854,2381,1316,2861,   2, 386, 515,2904,7426,7427,3253, 868,2234, # 4006
+1486, 855,2651, 785,2212,3028,7428,1040,3185,3523,7429,3121, 448,7430,1525,7431, # 4022
+2164,4348,7432,3754,7433,4099,2820,3524,3122, 503, 818,3898,3123,1568, 814, 676, # 4038
+1444, 306,1749,7434,3755,1416,1030, 197,1428, 805,2821,1501,4349,7435,7436,7437, # 4054
+1993,7438,4350,7439,7440,2195,  13,2779,3638,2980,3124,1229,1916,7441,3756,2131, # 4070
+7442,4100,4351,2399,3525,7443,2213,1511,1727,1120,7444,7445, 646,3757,2443, 307, # 4086
+7446,7447,1595,3186,7448,7449,7450,3639,1113,1356,3899,1465,2522,2523,7451, 519, # 4102
+7452, 128,2132,  92,2284,1979,7453,3900,1512, 342,3125,2196,7454,2780,2214,1980, # 4118
+3323,7455, 290,1656,1317, 789, 827,2360,7456,3758,4352, 562, 581,3901,7457, 401, # 4134
+4353,2248,  94,4354,1399,2781,7458,1463,2024,4355,3187,1943,7459, 828,1105,4101, # 4150
+1262,1394,7460,4102, 605,4356,7461,1783,2862,7462,2822, 819,2101, 578,2197,2937, # 4166
+7463,1502, 436,3254,4103,3255,2823,3902,2905,3425,3426,7464,2712,2315,7465,7466, # 4182
+2332,2067,  23,4357, 193, 826,3759,2102, 699,1630,4104,3075, 390,1793,1064,3526, # 4198
+7467,1579,3076,3077,1400,7468,4105,1838,1640,2863,7469,4358,4359, 137,4106, 598, # 4214
+3078,1966, 780, 104, 974,2938,7470, 278, 899, 253, 402, 572, 504, 493,1339,7471, # 4230
+3903,1275,4360,2574,2550,7472,3640,3029,3079,2249, 565,1334,2713, 863,  41,7473, # 4246
+7474,4361,7475,1657,2333,  19, 463,2750,4107, 606,7476,2981,3256,1087,2084,1323, # 4262
+2652,2982,7477,1631,1623,1750,4108,2682,7478,2864, 791,2714,2653,2334, 232,2416, # 4278
+7479,2983,1498,7480,2654,2620, 755,1366,3641,3257,3126,2025,1609, 119,1917,3427, # 4294
+ 862,1026,4109,7481,3904,3760,4362,3905,4363,2260,1951,2470,7482,1125, 817,4110, # 4310
+4111,3906,1513,1766,2040,1487,4112,3030,3258,2824,3761,3127,7483,7484,1507,7485, # 4326
+2683, 733,  40,1632,1106,2865, 345,4113, 841,2524, 230,4364,2984,1846,3259,3428, # 4342
+7486,1263, 986,3429,7487, 735, 879, 254,1137, 857, 622,1300,1180,1388,1562,3907, # 4358
+3908,2939, 967,2751,2655,1349, 592,2133,1692,3324,2985,1994,4114,1679,3909,1901, # 4374
+2185,7488, 739,3642,2715,1296,1290,7489,4115,2198,2199,1921,1563,2595,2551,1870, # 4390
+2752,2986,7490, 435,7491, 343,1108, 596,  17,1751,4365,2235,3430,3643,7492,4366, # 4406
+ 294,3527,2940,1693, 477, 979, 281,2041,3528, 643,2042,3644,2621,2782,2261,1031, # 4422
+2335,2134,2298,3529,4367, 367,1249,2552,7493,3530,7494,4368,1283,3325,2004, 240, # 4438
+1762,3326,4369,4370, 836,1069,3128, 474,7495,2148,2525, 268,3531,7496,3188,1521, # 4454
+1284,7497,1658,1546,4116,7498,3532,3533,7499,4117,3327,2684,1685,4118, 961,1673, # 4470
+2622, 190,2005,2200,3762,4371,4372,7500, 570,2497,3645,1490,7501,4373,2623,3260, # 4486
+1956,4374, 584,1514, 396,1045,1944,7502,4375,1967,2444,7503,7504,4376,3910, 619, # 4502
+7505,3129,3261, 215,2006,2783,2553,3189,4377,3190,4378, 763,4119,3763,4379,7506, # 4518
+7507,1957,1767,2941,3328,3646,1174, 452,1477,4380,3329,3130,7508,2825,1253,2382, # 4534
+2186,1091,2285,4120, 492,7509, 638,1169,1824,2135,1752,3911, 648, 926,1021,1324, # 4550
+4381, 520,4382, 997, 847,1007, 892,4383,3764,2262,1871,3647,7510,2400,1784,4384, # 4566
+1952,2942,3080,3191,1728,4121,2043,3648,4385,2007,1701,3131,1551,  30,2263,4122, # 4582
+7511,2026,4386,3534,7512, 501,7513,4123, 594,3431,2165,1821,3535,3432,3536,3192, # 4598
+ 829,2826,4124,7514,1680,3132,1225,4125,7515,3262,4387,4126,3133,2336,7516,4388, # 4614
+4127,7517,3912,3913,7518,1847,2383,2596,3330,7519,4389, 374,3914, 652,4128,4129, # 4630
+ 375,1140, 798,7520,7521,7522,2361,4390,2264, 546,1659, 138,3031,2445,4391,7523, # 4646
+2250, 612,1848, 910, 796,3765,1740,1371, 825,3766,3767,7524,2906,2554,7525, 692, # 4662
+ 444,3032,2624, 801,4392,4130,7526,1491, 244,1053,3033,4131,4132, 340,7527,3915, # 4678
+1041,2987, 293,1168,  87,1357,7528,1539, 959,7529,2236, 721, 694,4133,3768, 219, # 4694
+1478, 644,1417,3331,2656,1413,1401,1335,1389,3916,7530,7531,2988,2362,3134,1825, # 4710
+ 730,1515, 184,2827,  66,4393,7532,1660,2943, 246,3332, 378,1457, 226,3433, 975, # 4726
+3917,2944,1264,3537, 674, 696,7533, 163,7534,1141,2417,2166, 713,3538,3333,4394, # 4742
+3918,7535,7536,1186,  15,7537,1079,1070,7538,1522,3193,3539, 276,1050,2716, 758, # 4758
+1126, 653,2945,3263,7539,2337, 889,3540,3919,3081,2989, 903,1250,4395,3920,3434, # 4774
+3541,1342,1681,1718, 766,3264, 286,  89,2946,3649,7540,1713,7541,2597,3334,2990, # 4790
+7542,2947,2215,3194,2866,7543,4396,2498,2526, 181, 387,1075,3921, 731,2187,3335, # 4806
+7544,3265, 310, 313,3435,2299, 770,4134,  54,3034, 189,4397,3082,3769,3922,7545, # 4822
+1230,1617,1849, 355,3542,4135,4398,3336, 111,4136,3650,1350,3135,3436,3035,4137, # 4838
+2149,3266,3543,7546,2784,3923,3924,2991, 722,2008,7547,1071, 247,1207,2338,2471, # 4854
+1378,4399,2009, 864,1437,1214,4400, 373,3770,1142,2216, 667,4401, 442,2753,2555, # 4870
+3771,3925,1968,4138,3267,1839, 837, 170,1107, 934,1336,1882,7548,7549,2118,4139, # 4886
+2828, 743,1569,7550,4402,4140, 582,2384,1418,3437,7551,1802,7552, 357,1395,1729, # 4902
+3651,3268,2418,1564,2237,7553,3083,3772,1633,4403,1114,2085,4141,1532,7554, 482, # 4918
+2446,4404,7555,7556,1492, 833,1466,7557,2717,3544,1641,2829,7558,1526,1272,3652, # 4934
+4142,1686,1794, 416,2556,1902,1953,1803,7559,3773,2785,3774,1159,2316,7560,2867, # 4950
+4405,1610,1584,3036,2419,2754, 443,3269,1163,3136,7561,7562,3926,7563,4143,2499, # 4966
+3037,4406,3927,3137,2103,1647,3545,2010,1872,4144,7564,4145, 431,3438,7565, 250, # 4982
+  97,  81,4146,7566,1648,1850,1558, 160, 848,7567, 866, 740,1694,7568,2201,2830, # 4998
+3195,4147,4407,3653,1687, 950,2472, 426, 469,3196,3654,3655,3928,7569,7570,1188, # 5014
+ 424,1995, 861,3546,4148,3775,2202,2685, 168,1235,3547,4149,7571,2086,1674,4408, # 5030
+3337,3270, 220,2557,1009,7572,3776, 670,2992, 332,1208, 717,7573,7574,3548,2447, # 5046
+3929,3338,7575, 513,7576,1209,2868,3339,3138,4409,1080,7577,7578,7579,7580,2527, # 5062
+3656,3549, 815,1587,3930,3931,7581,3550,3439,3777,1254,4410,1328,3038,1390,3932, # 5078
+1741,3933,3778,3934,7582, 236,3779,2448,3271,7583,7584,3657,3780,1273,3781,4411, # 5094
+7585, 308,7586,4412, 245,4413,1851,2473,1307,2575, 430, 715,2136,2449,7587, 270, # 5110
+ 199,2869,3935,7588,3551,2718,1753, 761,1754, 725,1661,1840,4414,3440,3658,7589, # 5126
+7590, 587,  14,3272, 227,2598, 326, 480,2265, 943,2755,3552, 291, 650,1883,7591, # 5142
+1702,1226, 102,1547,  62,3441, 904,4415,3442,1164,4150,7592,7593,1224,1548,2756, # 5158
+ 391, 498,1493,7594,1386,1419,7595,2055,1177,4416, 813, 880,1081,2363, 566,1145, # 5174
+4417,2286,1001,1035,2558,2599,2238, 394,1286,7596,7597,2068,7598,  86,1494,1730, # 5190
+3936, 491,1588, 745, 897,2948, 843,3340,3937,2757,2870,3273,1768, 998,2217,2069, # 5206
+ 397,1826,1195,1969,3659,2993,3341, 284,7599,3782,2500,2137,2119,1903,7600,3938, # 5222
+2150,3939,4151,1036,3443,1904, 114,2559,4152, 209,1527,7601,7602,2949,2831,2625, # 5238
+2385,2719,3139, 812,2560,7603,3274,7604,1559, 737,1884,3660,1210, 885,  28,2686, # 5254
+3553,3783,7605,4153,1004,1779,4418,7606, 346,1981,2218,2687,4419,3784,1742, 797, # 5270
+1642,3940,1933,1072,1384,2151, 896,3941,3275,3661,3197,2871,3554,7607,2561,1958, # 5286
+4420,2450,1785,7608,7609,7610,3942,4154,1005,1308,3662,4155,2720,4421,4422,1528, # 5302
+2600, 161,1178,4156,1982, 987,4423,1101,4157, 631,3943,1157,3198,2420,1343,1241, # 5318
+1016,2239,2562, 372, 877,2339,2501,1160, 555,1934, 911,3944,7611, 466,1170, 169, # 5334
+1051,2907,2688,3663,2474,2994,1182,2011,2563,1251,2626,7612, 992,2340,3444,1540, # 5350
+2721,1201,2070,2401,1996,2475,7613,4424, 528,1922,2188,1503,1873,1570,2364,3342, # 5366
+3276,7614, 557,1073,7615,1827,3445,2087,2266,3140,3039,3084, 767,3085,2786,4425, # 5382
+1006,4158,4426,2341,1267,2176,3664,3199, 778,3945,3200,2722,1597,2657,7616,4427, # 5398
+7617,3446,7618,7619,7620,3277,2689,1433,3278, 131,  95,1504,3946, 723,4159,3141, # 5414
+1841,3555,2758,2189,3947,2027,2104,3665,7621,2995,3948,1218,7622,3343,3201,3949, # 5430
+4160,2576, 248,1634,3785, 912,7623,2832,3666,3040,3786, 654,  53,7624,2996,7625, # 5446
+1688,4428, 777,3447,1032,3950,1425,7626, 191, 820,2120,2833, 971,4429, 931,3202, # 5462
+ 135, 664, 783,3787,1997, 772,2908,1935,3951,3788,4430,2909,3203, 282,2723, 640, # 5478
+1372,3448,1127, 922, 325,3344,7627,7628, 711,2044,7629,7630,3952,2219,2787,1936, # 5494
+3953,3345,2220,2251,3789,2300,7631,4431,3790,1258,3279,3954,3204,2138,2950,3955, # 5510
+3956,7632,2221, 258,3205,4432, 101,1227,7633,3280,1755,7634,1391,3281,7635,2910, # 5526
+2056, 893,7636,7637,7638,1402,4161,2342,7639,7640,3206,3556,7641,7642, 878,1325, # 5542
+1780,2788,4433, 259,1385,2577, 744,1183,2267,4434,7643,3957,2502,7644, 684,1024, # 5558
+4162,7645, 472,3557,3449,1165,3282,3958,3959, 322,2152, 881, 455,1695,1152,1340, # 5574
+ 660, 554,2153,4435,1058,4436,4163, 830,1065,3346,3960,4437,1923,7646,1703,1918, # 5590
+7647, 932,2268, 122,7648,4438, 947, 677,7649,3791,2627, 297,1905,1924,2269,4439, # 5606
+2317,3283,7650,7651,4164,7652,4165,  84,4166, 112, 989,7653, 547,1059,3961, 701, # 5622
+3558,1019,7654,4167,7655,3450, 942, 639, 457,2301,2451, 993,2951, 407, 851, 494, # 5638
+4440,3347, 927,7656,1237,7657,2421,3348, 573,4168, 680, 921,2911,1279,1874, 285, # 5654
+ 790,1448,1983, 719,2167,7658,7659,4441,3962,3963,1649,7660,1541, 563,7661,1077, # 5670
+7662,3349,3041,3451, 511,2997,3964,3965,3667,3966,1268,2564,3350,3207,4442,4443, # 5686
+7663, 535,1048,1276,1189,2912,2028,3142,1438,1373,2834,2952,1134,2012,7664,4169, # 5702
+1238,2578,3086,1259,7665, 700,7666,2953,3143,3668,4170,7667,4171,1146,1875,1906, # 5718
+4444,2601,3967, 781,2422, 132,1589, 203, 147, 273,2789,2402, 898,1786,2154,3968, # 5734
+3969,7668,3792,2790,7669,7670,4445,4446,7671,3208,7672,1635,3793, 965,7673,1804, # 5750
+2690,1516,3559,1121,1082,1329,3284,3970,1449,3794,  65,1128,2835,2913,2759,1590, # 5766
+3795,7674,7675,  12,2658,  45, 976,2579,3144,4447, 517,2528,1013,1037,3209,7676, # 5782
+3796,2836,7677,3797,7678,3452,7679,2602, 614,1998,2318,3798,3087,2724,2628,7680, # 5798
+2580,4172, 599,1269,7681,1810,3669,7682,2691,3088, 759,1060, 489,1805,3351,3285, # 5814
+1358,7683,7684,2386,1387,1215,2629,2252, 490,7685,7686,4173,1759,2387,2343,7687, # 5830
+4448,3799,1907,3971,2630,1806,3210,4449,3453,3286,2760,2344, 874,7688,7689,3454, # 5846
+3670,1858,  91,2914,3671,3042,3800,4450,7690,3145,3972,2659,7691,3455,1202,1403, # 5862
+3801,2954,2529,1517,2503,4451,3456,2504,7692,4452,7693,2692,1885,1495,1731,3973, # 5878
+2365,4453,7694,2029,7695,7696,3974,2693,1216, 237,2581,4174,2319,3975,3802,4454, # 5894
+4455,2694,3560,3457, 445,4456,7697,7698,7699,7700,2761,  61,3976,3672,1822,3977, # 5910
+7701, 687,2045, 935, 925, 405,2660, 703,1096,1859,2725,4457,3978,1876,1367,2695, # 5926
+3352, 918,2105,1781,2476, 334,3287,1611,1093,4458, 564,3146,3458,3673,3353, 945, # 5942
+2631,2057,4459,7702,1925, 872,4175,7703,3459,2696,3089, 349,4176,3674,3979,4460, # 5958
+3803,4177,3675,2155,3980,4461,4462,4178,4463,2403,2046, 782,3981, 400, 251,4179, # 5974
+1624,7704,7705, 277,3676, 299,1265, 476,1191,3804,2121,4180,4181,1109, 205,7706, # 5990
+2582,1000,2156,3561,1860,7707,7708,7709,4464,7710,4465,2565, 107,2477,2157,3982, # 6006
+3460,3147,7711,1533, 541,1301, 158, 753,4182,2872,3562,7712,1696, 370,1088,4183, # 6022
+4466,3563, 579, 327, 440, 162,2240, 269,1937,1374,3461, 968,3043,  56,1396,3090, # 6038
+2106,3288,3354,7713,1926,2158,4467,2998,7714,3564,7715,7716,3677,4468,2478,7717, # 6054
+2791,7718,1650,4469,7719,2603,7720,7721,3983,2661,3355,1149,3356,3984,3805,3985, # 6070
+7722,1076,  49,7723, 951,3211,3289,3290, 450,2837, 920,7724,1811,2792,2366,4184, # 6086
+1908,1138,2367,3806,3462,7725,3212,4470,1909,1147,1518,2423,4471,3807,7726,4472, # 6102
+2388,2604, 260,1795,3213,7727,7728,3808,3291, 708,7729,3565,1704,7730,3566,1351, # 6118
+1618,3357,2999,1886, 944,4185,3358,4186,3044,3359,4187,7731,3678, 422, 413,1714, # 6134
+3292, 500,2058,2345,4188,2479,7732,1344,1910, 954,7733,1668,7734,7735,3986,2404, # 6150
+4189,3567,3809,4190,7736,2302,1318,2505,3091, 133,3092,2873,4473, 629,  31,2838, # 6166
+2697,3810,4474, 850, 949,4475,3987,2955,1732,2088,4191,1496,1852,7737,3988, 620, # 6182
+3214, 981,1242,3679,3360,1619,3680,1643,3293,2139,2452,1970,1719,3463,2168,7738, # 6198
+3215,7739,7740,3361,1828,7741,1277,4476,1565,2047,7742,1636,3568,3093,7743, 869, # 6214
+2839, 655,3811,3812,3094,3989,3000,3813,1310,3569,4477,7744,7745,7746,1733, 558, # 6230
+4478,3681, 335,1549,3045,1756,4192,3682,1945,3464,1829,1291,1192, 470,2726,2107, # 6246
+2793, 913,1054,3990,7747,1027,7748,3046,3991,4479, 982,2662,3362,3148,3465,3216, # 6262
+3217,1946,2794,7749, 571,4480,7750,1830,7751,3570,2583,1523,2424,7752,2089, 984, # 6278
+4481,3683,1959,7753,3684, 852, 923,2795,3466,3685, 969,1519, 999,2048,2320,1705, # 6294
+7754,3095, 615,1662, 151, 597,3992,2405,2321,1049, 275,4482,3686,4193, 568,3687, # 6310
+3571,2480,4194,3688,7755,2425,2270, 409,3218,7756,1566,2874,3467,1002, 769,2840, # 6326
+ 194,2090,3149,3689,2222,3294,4195, 628,1505,7757,7758,1763,2177,3001,3993, 521, # 6342
+1161,2584,1787,2203,2406,4483,3994,1625,4196,4197, 412,  42,3096, 464,7759,2632, # 6358
+4484,3363,1760,1571,2875,3468,2530,1219,2204,3814,2633,2140,2368,4485,4486,3295, # 6374
+1651,3364,3572,7760,7761,3573,2481,3469,7762,3690,7763,7764,2271,2091, 460,7765, # 6390
+4487,7766,3002, 962, 588,3574, 289,3219,2634,1116,  52,7767,3047,1796,7768,7769, # 6406
+7770,1467,7771,1598,1143,3691,4198,1984,1734,1067,4488,1280,3365, 465,4489,1572, # 6422
+ 510,7772,1927,2241,1812,1644,3575,7773,4490,3692,7774,7775,2663,1573,1534,7776, # 6438
+7777,4199, 536,1807,1761,3470,3815,3150,2635,7778,7779,7780,4491,3471,2915,1911, # 6454
+2796,7781,3296,1122, 377,3220,7782, 360,7783,7784,4200,1529, 551,7785,2059,3693, # 6470
+1769,2426,7786,2916,4201,3297,3097,2322,2108,2030,4492,1404, 136,1468,1479, 672, # 6486
+1171,3221,2303, 271,3151,7787,2762,7788,2049, 678,2727, 865,1947,4493,7789,2013, # 6502
+3995,2956,7790,2728,2223,1397,3048,3694,4494,4495,1735,2917,3366,3576,7791,3816, # 6518
+ 509,2841,2453,2876,3817,7792,7793,3152,3153,4496,4202,2531,4497,2304,1166,1010, # 6534
+ 552, 681,1887,7794,7795,2957,2958,3996,1287,1596,1861,3154, 358, 453, 736, 175, # 6550
+ 478,1117, 905,1167,1097,7796,1853,1530,7797,1706,7798,2178,3472,2287,3695,3473, # 6566
+3577,4203,2092,4204,7799,3367,1193,2482,4205,1458,2190,2205,1862,1888,1421,3298, # 6582
+2918,3049,2179,3474, 595,2122,7800,3997,7801,7802,4206,1707,2636, 223,3696,1359, # 6598
+ 751,3098, 183,3475,7803,2797,3003, 419,2369, 633, 704,3818,2389, 241,7804,7805, # 6614
+7806, 838,3004,3697,2272,2763,2454,3819,1938,2050,3998,1309,3099,2242,1181,7807, # 6630
+1136,2206,3820,2370,1446,4207,2305,4498,7808,7809,4208,1055,2605, 484,3698,7810, # 6646
+3999, 625,4209,2273,3368,1499,4210,4000,7811,4001,4211,3222,2274,2275,3476,7812, # 6662
+7813,2764, 808,2606,3699,3369,4002,4212,3100,2532, 526,3370,3821,4213, 955,7814, # 6678
+1620,4214,2637,2427,7815,1429,3700,1669,1831, 994, 928,7816,3578,1260,7817,7818, # 6694
+7819,1948,2288, 741,2919,1626,4215,2729,2455, 867,1184, 362,3371,1392,7820,7821, # 6710
+4003,4216,1770,1736,3223,2920,4499,4500,1928,2698,1459,1158,7822,3050,3372,2877, # 6726
+1292,1929,2506,2842,3701,1985,1187,2071,2014,2607,4217,7823,2566,2507,2169,3702, # 6742
+2483,3299,7824,3703,4501,7825,7826, 666,1003,3005,1022,3579,4218,7827,4502,1813, # 6758
+2253, 574,3822,1603, 295,1535, 705,3823,4219, 283, 858, 417,7828,7829,3224,4503, # 6774
+4504,3051,1220,1889,1046,2276,2456,4004,1393,1599, 689,2567, 388,4220,7830,2484, # 6790
+ 802,7831,2798,3824,2060,1405,2254,7832,4505,3825,2109,1052,1345,3225,1585,7833, # 6806
+ 809,7834,7835,7836, 575,2730,3477, 956,1552,1469,1144,2323,7837,2324,1560,2457, # 6822
+3580,3226,4005, 616,2207,3155,2180,2289,7838,1832,7839,3478,4506,7840,1319,3704, # 6838
+3705,1211,3581,1023,3227,1293,2799,7841,7842,7843,3826, 607,2306,3827, 762,2878, # 6854
+1439,4221,1360,7844,1485,3052,7845,4507,1038,4222,1450,2061,2638,4223,1379,4508, # 6870
+2585,7846,7847,4224,1352,1414,2325,2921,1172,7848,7849,3828,3829,7850,1797,1451, # 6886
+7851,7852,7853,7854,2922,4006,4007,2485,2346, 411,4008,4009,3582,3300,3101,4509, # 6902
+1561,2664,1452,4010,1375,7855,7856,  47,2959, 316,7857,1406,1591,2923,3156,7858, # 6918
+1025,2141,3102,3157, 354,2731, 884,2224,4225,2407, 508,3706, 726,3583, 996,2428, # 6934
+3584, 729,7859, 392,2191,1453,4011,4510,3707,7860,7861,2458,3585,2608,1675,2800, # 6950
+ 919,2347,2960,2348,1270,4511,4012,  73,7862,7863, 647,7864,3228,2843,2255,1550, # 6966
+1346,3006,7865,1332, 883,3479,7866,7867,7868,7869,3301,2765,7870,1212, 831,1347, # 6982
+4226,4512,2326,3830,1863,3053, 720,3831,4513,4514,3832,7871,4227,7872,7873,4515, # 6998
+7874,7875,1798,4516,3708,2609,4517,3586,1645,2371,7876,7877,2924, 669,2208,2665, # 7014
+2429,7878,2879,7879,7880,1028,3229,7881,4228,2408,7882,2256,1353,7883,7884,4518, # 7030
+3158, 518,7885,4013,7886,4229,1960,7887,2142,4230,7888,7889,3007,2349,2350,3833, # 7046
+ 516,1833,1454,4014,2699,4231,4519,2225,2610,1971,1129,3587,7890,2766,7891,2961, # 7062
+1422, 577,1470,3008,1524,3373,7892,7893, 432,4232,3054,3480,7894,2586,1455,2508, # 7078
+2226,1972,1175,7895,1020,2732,4015,3481,4520,7896,2733,7897,1743,1361,3055,3482, # 7094
+2639,4016,4233,4521,2290, 895, 924,4234,2170, 331,2243,3056, 166,1627,3057,1098, # 7110
+7898,1232,2880,2227,3374,4522, 657, 403,1196,2372, 542,3709,3375,1600,4235,3483, # 7126
+7899,4523,2767,3230, 576, 530,1362,7900,4524,2533,2666,3710,4017,7901, 842,3834, # 7142
+7902,2801,2031,1014,4018, 213,2700,3376, 665, 621,4236,7903,3711,2925,2430,7904, # 7158
+2431,3302,3588,3377,7905,4237,2534,4238,4525,3589,1682,4239,3484,1380,7906, 724, # 7174
+2277, 600,1670,7907,1337,1233,4526,3103,2244,7908,1621,4527,7909, 651,4240,7910, # 7190
+1612,4241,2611,7911,2844,7912,2734,2307,3058,7913, 716,2459,3059, 174,1255,2701, # 7206
+4019,3590, 548,1320,1398, 728,4020,1574,7914,1890,1197,3060,4021,7915,3061,3062, # 7222
+3712,3591,3713, 747,7916, 635,4242,4528,7917,7918,7919,4243,7920,7921,4529,7922, # 7238
+3378,4530,2432, 451,7923,3714,2535,2072,4244,2735,4245,4022,7924,1764,4531,7925, # 7254
+4246, 350,7926,2278,2390,2486,7927,4247,4023,2245,1434,4024, 488,4532, 458,4248, # 7270
+4025,3715, 771,1330,2391,3835,2568,3159,2159,2409,1553,2667,3160,4249,7928,2487, # 7286
+2881,2612,1720,2702,4250,3379,4533,7929,2536,4251,7930,3231,4252,2768,7931,2015, # 7302
+2736,7932,1155,1017,3716,3836,7933,3303,2308, 201,1864,4253,1430,7934,4026,7935, # 7318
+7936,7937,7938,7939,4254,1604,7940, 414,1865, 371,2587,4534,4535,3485,2016,3104, # 7334
+4536,1708, 960,4255, 887, 389,2171,1536,1663,1721,7941,2228,4027,2351,2926,1580, # 7350
+7942,7943,7944,1744,7945,2537,4537,4538,7946,4539,7947,2073,7948,7949,3592,3380, # 7366
+2882,4256,7950,4257,2640,3381,2802, 673,2703,2460, 709,3486,4028,3593,4258,7951, # 7382
+1148, 502, 634,7952,7953,1204,4540,3594,1575,4541,2613,3717,7954,3718,3105, 948, # 7398
+3232, 121,1745,3837,1110,7955,4259,3063,2509,3009,4029,3719,1151,1771,3838,1488, # 7414
+4030,1986,7956,2433,3487,7957,7958,2093,7959,4260,3839,1213,1407,2803, 531,2737, # 7430
+2538,3233,1011,1537,7960,2769,4261,3106,1061,7961,3720,3721,1866,2883,7962,2017, # 7446
+ 120,4262,4263,2062,3595,3234,2309,3840,2668,3382,1954,4542,7963,7964,3488,1047, # 7462
+2704,1266,7965,1368,4543,2845, 649,3383,3841,2539,2738,1102,2846,2669,7966,7967, # 7478
+1999,7968,1111,3596,2962,7969,2488,3842,3597,2804,1854,3384,3722,7970,7971,3385, # 7494
+2410,2884,3304,3235,3598,7972,2569,7973,3599,2805,4031,1460, 856,7974,3600,7975, # 7510
+2885,2963,7976,2886,3843,7977,4264, 632,2510, 875,3844,1697,3845,2291,7978,7979, # 7526
+4544,3010,1239, 580,4545,4265,7980, 914, 936,2074,1190,4032,1039,2123,7981,7982, # 7542
+7983,3386,1473,7984,1354,4266,3846,7985,2172,3064,4033, 915,3305,4267,4268,3306, # 7558
+1605,1834,7986,2739, 398,3601,4269,3847,4034, 328,1912,2847,4035,3848,1331,4270, # 7574
+3011, 937,4271,7987,3602,4036,4037,3387,2160,4546,3388, 524, 742, 538,3065,1012, # 7590
+7988,7989,3849,2461,7990, 658,1103, 225,3850,7991,7992,4547,7993,4548,7994,3236, # 7606
+1243,7995,4038, 963,2246,4549,7996,2705,3603,3161,7997,7998,2588,2327,7999,4550, # 7622
+8000,8001,8002,3489,3307, 957,3389,2540,2032,1930,2927,2462, 870,2018,3604,1746, # 7638
+2770,2771,2434,2463,8003,3851,8004,3723,3107,3724,3490,3390,3725,8005,1179,3066, # 7654
+8006,3162,2373,4272,3726,2541,3163,3108,2740,4039,8007,3391,1556,2542,2292, 977, # 7670
+2887,2033,4040,1205,3392,8008,1765,3393,3164,2124,1271,1689, 714,4551,3491,8009, # 7686
+2328,3852, 533,4273,3605,2181, 617,8010,2464,3308,3492,2310,8011,8012,3165,8013, # 7702
+8014,3853,1987, 618, 427,2641,3493,3394,8015,8016,1244,1690,8017,2806,4274,4552, # 7718
+8018,3494,8019,8020,2279,1576, 473,3606,4275,3395, 972,8021,3607,8022,3067,8023, # 7734
+8024,4553,4554,8025,3727,4041,4042,8026, 153,4555, 356,8027,1891,2888,4276,2143, # 7750
+ 408, 803,2352,8028,3854,8029,4277,1646,2570,2511,4556,4557,3855,8030,3856,4278, # 7766
+8031,2411,3396, 752,8032,8033,1961,2964,8034, 746,3012,2465,8035,4279,3728, 698, # 7782
+4558,1892,4280,3608,2543,4559,3609,3857,8036,3166,3397,8037,1823,1302,4043,2706, # 7798
+3858,1973,4281,8038,4282,3167, 823,1303,1288,1236,2848,3495,4044,3398, 774,3859, # 7814
+8039,1581,4560,1304,2849,3860,4561,8040,2435,2161,1083,3237,4283,4045,4284, 344, # 7830
+1173, 288,2311, 454,1683,8041,8042,1461,4562,4046,2589,8043,8044,4563, 985, 894, # 7846
+8045,3399,3168,8046,1913,2928,3729,1988,8047,2110,1974,8048,4047,8049,2571,1194, # 7862
+ 425,8050,4564,3169,1245,3730,4285,8051,8052,2850,8053, 636,4565,1855,3861, 760, # 7878
+1799,8054,4286,2209,1508,4566,4048,1893,1684,2293,8055,8056,8057,4287,4288,2210, # 7894
+ 479,8058,8059, 832,8060,4049,2489,8061,2965,2490,3731, 990,3109, 627,1814,2642, # 7910
+4289,1582,4290,2125,2111,3496,4567,8062, 799,4291,3170,8063,4568,2112,1737,3013, # 7926
+1018, 543, 754,4292,3309,1676,4569,4570,4050,8064,1489,8065,3497,8066,2614,2889, # 7942
+4051,8067,8068,2966,8069,8070,8071,8072,3171,4571,4572,2182,1722,8073,3238,3239, # 7958
+1842,3610,1715, 481, 365,1975,1856,8074,8075,1962,2491,4573,8076,2126,3611,3240, # 7974
+ 433,1894,2063,2075,8077, 602,2741,8078,8079,8080,8081,8082,3014,1628,3400,8083, # 7990
+3172,4574,4052,2890,4575,2512,8084,2544,2772,8085,8086,8087,3310,4576,2891,8088, # 8006
+4577,8089,2851,4578,4579,1221,2967,4053,2513,8090,8091,8092,1867,1989,8093,8094, # 8022
+8095,1895,8096,8097,4580,1896,4054, 318,8098,2094,4055,4293,8099,8100, 485,8101, # 8038
+ 938,3862, 553,2670, 116,8102,3863,3612,8103,3498,2671,2773,3401,3311,2807,8104, # 8054
+3613,2929,4056,1747,2930,2968,8105,8106, 207,8107,8108,2672,4581,2514,8109,3015, # 8070
+ 890,3614,3864,8110,1877,3732,3402,8111,2183,2353,3403,1652,8112,8113,8114, 941, # 8086
+2294, 208,3499,4057,2019, 330,4294,3865,2892,2492,3733,4295,8115,8116,8117,8118, # 8102
+#Everything below is of no interest for detection purpose
+2515,1613,4582,8119,3312,3866,2516,8120,4058,8121,1637,4059,2466,4583,3867,8122, # 8118
+2493,3016,3734,8123,8124,2192,8125,8126,2162,8127,8128,8129,8130,8131,8132,8133, # 8134
+8134,8135,8136,8137,8138,8139,8140,8141,8142,8143,8144,8145,8146,8147,8148,8149, # 8150
+8150,8151,8152,8153,8154,8155,8156,8157,8158,8159,8160,8161,8162,8163,8164,8165, # 8166
+8166,8167,8168,8169,8170,8171,8172,8173,8174,8175,8176,8177,8178,8179,8180,8181, # 8182
+8182,8183,8184,8185,8186,8187,8188,8189,8190,8191,8192,8193,8194,8195,8196,8197, # 8198
+8198,8199,8200,8201,8202,8203,8204,8205,8206,8207,8208,8209,8210,8211,8212,8213, # 8214
+8214,8215,8216,8217,8218,8219,8220,8221,8222,8223,8224,8225,8226,8227,8228,8229, # 8230
+8230,8231,8232,8233,8234,8235,8236,8237,8238,8239,8240,8241,8242,8243,8244,8245, # 8246
+8246,8247,8248,8249,8250,8251,8252,8253,8254,8255,8256,8257,8258,8259,8260,8261, # 8262
+8262,8263,8264,8265,8266,8267,8268,8269,8270,8271,8272,8273,8274,8275,8276,8277, # 8278
+8278,8279,8280,8281,8282,8283,8284,8285,8286,8287,8288,8289,8290,8291,8292,8293, # 8294
+8294,8295,8296,8297,8298,8299,8300,8301,8302,8303,8304,8305,8306,8307,8308,8309, # 8310
+8310,8311,8312,8313,8314,8315,8316,8317,8318,8319,8320,8321,8322,8323,8324,8325, # 8326
+8326,8327,8328,8329,8330,8331,8332,8333,8334,8335,8336,8337,8338,8339,8340,8341, # 8342
+8342,8343,8344,8345,8346,8347,8348,8349,8350,8351,8352,8353,8354,8355,8356,8357, # 8358
+8358,8359,8360,8361,8362,8363,8364,8365,8366,8367,8368,8369,8370,8371,8372,8373, # 8374
+8374,8375,8376,8377,8378,8379,8380,8381,8382,8383,8384,8385,8386,8387,8388,8389, # 8390
+8390,8391,8392,8393,8394,8395,8396,8397,8398,8399,8400,8401,8402,8403,8404,8405, # 8406
+8406,8407,8408,8409,8410,8411,8412,8413,8414,8415,8416,8417,8418,8419,8420,8421, # 8422
+8422,8423,8424,8425,8426,8427,8428,8429,8430,8431,8432,8433,8434,8435,8436,8437, # 8438
+8438,8439,8440,8441,8442,8443,8444,8445,8446,8447,8448,8449,8450,8451,8452,8453, # 8454
+8454,8455,8456,8457,8458,8459,8460,8461,8462,8463,8464,8465,8466,8467,8468,8469, # 8470
+8470,8471,8472,8473,8474,8475,8476,8477,8478,8479,8480,8481,8482,8483,8484,8485, # 8486
+8486,8487,8488,8489,8490,8491,8492,8493,8494,8495,8496,8497,8498,8499,8500,8501, # 8502
+8502,8503,8504,8505,8506,8507,8508,8509,8510,8511,8512,8513,8514,8515,8516,8517, # 8518
+8518,8519,8520,8521,8522,8523,8524,8525,8526,8527,8528,8529,8530,8531,8532,8533, # 8534
+8534,8535,8536,8537,8538,8539,8540,8541,8542,8543,8544,8545,8546,8547,8548,8549, # 8550
+8550,8551,8552,8553,8554,8555,8556,8557,8558,8559,8560,8561,8562,8563,8564,8565, # 8566
+8566,8567,8568,8569,8570,8571,8572,8573,8574,8575,8576,8577,8578,8579,8580,8581, # 8582
+8582,8583,8584,8585,8586,8587,8588,8589,8590,8591,8592,8593,8594,8595,8596,8597, # 8598
+8598,8599,8600,8601,8602,8603,8604,8605,8606,8607,8608,8609,8610,8611,8612,8613, # 8614
+8614,8615,8616,8617,8618,8619,8620,8621,8622,8623,8624,8625,8626,8627,8628,8629, # 8630
+8630,8631,8632,8633,8634,8635,8636,8637,8638,8639,8640,8641,8642,8643,8644,8645, # 8646
+8646,8647,8648,8649,8650,8651,8652,8653,8654,8655,8656,8657,8658,8659,8660,8661, # 8662
+8662,8663,8664,8665,8666,8667,8668,8669,8670,8671,8672,8673,8674,8675,8676,8677, # 8678
+8678,8679,8680,8681,8682,8683,8684,8685,8686,8687,8688,8689,8690,8691,8692,8693, # 8694
+8694,8695,8696,8697,8698,8699,8700,8701,8702,8703,8704,8705,8706,8707,8708,8709, # 8710
+8710,8711,8712,8713,8714,8715,8716,8717,8718,8719,8720,8721,8722,8723,8724,8725, # 8726
+8726,8727,8728,8729,8730,8731,8732,8733,8734,8735,8736,8737,8738,8739,8740,8741] # 8742
+end
diff --git a/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/euctwprober.rb b/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/euctwprober.rb
new file mode 100644 (file)
index 0000000..a65a3f4
--- /dev/null
@@ -0,0 +1,42 @@
+######################## BEGIN LICENSE BLOCK ########################
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Jeff Hodges - port to Ruby
+#   Mark Pilgrim - port to Python
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+# 
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301  USA
+######################### END LICENSE BLOCK #########################
+
+module CharDet
+  class EUCTWProber < MultiByteCharSetProber
+    def initialize
+      super()
+      @_mCodingSM = CodingStateMachine.new(EUCTWSMModel)
+      @_mDistributionAnalyzer = EUCTWDistributionAnalysis.new()
+      reset()
+    end
+
+    def get_charset_name
+      return "EUC-TW"
+    end
+  end
+end
diff --git a/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/gb2312freq.rb b/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/gb2312freq.rb
new file mode 100644 (file)
index 0000000..1b43eab
--- /dev/null
@@ -0,0 +1,474 @@
+######################## BEGIN LICENSE BLOCK ########################
+# The Original Code is Mozilla Communicator client code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Jeff Hodges - port to Ruby
+#   Mark Pilgrim - port to Python
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+# 
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301  USA
+######################### END LICENSE BLOCK #########################
+
+# GB2312 most frequently used character table
+#
+# Char to FreqOrder table , from hz6763
+
+# 512  --> 0.79  -- 0.79
+# 1024 --> 0.92  -- 0.13
+# 2048 --> 0.98  -- 0.06
+# 6768 --> 1.00  -- 0.02
+#
+# Ideal Distribution Ratio = 0.79135/(1-0.79135) = 3.79
+# Random Distribution Ration = 512 / (3755 - 512) = 0.157
+# 
+# Typical Distribution Ratio about 25% of Ideal one, still much higher that RDR
+
+module CharDet
+GB2312_TYPICAL_DISTRIBUTION_RATIO = 0.9
+
+GB2312_TABLE_SIZE = 3760
+
+GB2312CharToFreqOrder = [
+1671, 749,1443,2364,3924,3807,2330,3921,1704,3463,2691,1511,1515, 572,3191,2205,
+2361, 224,2558, 479,1711, 963,3162, 440,4060,1905,2966,2947,3580,2647,3961,3842,
+2204, 869,4207, 970,2678,5626,2944,2956,1479,4048, 514,3595, 588,1346,2820,3409,
+ 249,4088,1746,1873,2047,1774, 581,1813, 358,1174,3590,1014,1561,4844,2245, 670,
+1636,3112, 889,1286, 953, 556,2327,3060,1290,3141, 613, 185,3477,1367, 850,3820,
+1715,2428,2642,2303,2732,3041,2562,2648,3566,3946,1349, 388,3098,2091,1360,3585,
+ 152,1687,1539, 738,1559,  59,1232,2925,2267,1388,1249,1741,1679,2960, 151,1566,
+1125,1352,4271, 924,4296, 385,3166,4459, 310,1245,2850,  70,3285,2729,3534,3575,
+2398,3298,3466,1960,2265, 217,3647, 864,1909,2084,4401,2773,1010,3269,5152, 853,
+3051,3121,1244,4251,1895, 364,1499,1540,2313,1180,3655,2268, 562, 715,2417,3061,
+ 544, 336,3768,2380,1752,4075, 950, 280,2425,4382, 183,2759,3272, 333,4297,2155,
+1688,2356,1444,1039,4540, 736,1177,3349,2443,2368,2144,2225, 565, 196,1482,3406,
+ 927,1335,4147, 692, 878,1311,1653,3911,3622,1378,4200,1840,2969,3149,2126,1816,
+2534,1546,2393,2760, 737,2494,  13, 447, 245,2747,  38,2765,2129,2589,1079, 606,
+ 360, 471,3755,2890, 404, 848, 699,1785,1236, 370,2221,1023,3746,2074,2026,2023,
+2388,1581,2119, 812,1141,3091,2536,1519, 804,2053, 406,1596,1090, 784, 548,4414,
+1806,2264,2936,1100, 343,4114,5096, 622,3358, 743,3668,1510,1626,5020,3567,2513,
+3195,4115,5627,2489,2991,  24,2065,2697,1087,2719,  48,1634, 315,  68, 985,2052,
+ 198,2239,1347,1107,1439, 597,2366,2172, 871,3307, 919,2487,2790,1867, 236,2570,
+1413,3794, 906,3365,3381,1701,1982,1818,1524,2924,1205, 616,2586,2072,2004, 575,
+ 253,3099,  32,1365,1182, 197,1714,2454,1201, 554,3388,3224,2748, 756,2587, 250,
+2567,1507,1517,3529,1922,2761,2337,3416,1961,1677,2452,2238,3153, 615, 911,1506,
+1474,2495,1265,1906,2749,3756,3280,2161, 898,2714,1759,3450,2243,2444, 563,  26,
+3286,2266,3769,3344,2707,3677, 611,1402, 531,1028,2871,4548,1375, 261,2948, 835,
+1190,4134, 353, 840,2684,1900,3082,1435,2109,1207,1674, 329,1872,2781,4055,2686,
+2104, 608,3318,2423,2957,2768,1108,3739,3512,3271,3985,2203,1771,3520,1418,2054,
+1681,1153, 225,1627,2929, 162,2050,2511,3687,1954, 124,1859,2431,1684,3032,2894,
+ 585,4805,3969,2869,2704,2088,2032,2095,3656,2635,4362,2209, 256, 518,2042,2105,
+3777,3657, 643,2298,1148,1779, 190, 989,3544, 414,  11,2135,2063,2979,1471, 403,
+3678, 126, 770,1563, 671,2499,3216,2877, 600,1179, 307,2805,4937,1268,1297,2694,
+ 252,4032,1448,1494,1331,1394, 127,2256, 222,1647,1035,1481,3056,1915,1048, 873,
+3651, 210,  33,1608,2516, 200,1520, 415, 102,   0,3389,1287, 817,  91,3299,2940,
+ 836,1814, 549,2197,1396,1669,2987,3582,2297,2848,4528,1070, 687,  20,1819, 121,
+1552,1364,1461,1968,2617,3540,2824,2083, 177, 948,4938,2291, 110,4549,2066, 648,
+3359,1755,2110,2114,4642,4845,1693,3937,3308,1257,1869,2123, 208,1804,3159,2992,
+2531,2549,3361,2418,1350,2347,2800,2568,1291,2036,2680,  72, 842,1990, 212,1233,
+1154,1586,  75,2027,3410,4900,1823,1337,2710,2676, 728,2810,1522,3026,4995, 157,
+ 755,1050,4022, 710, 785,1936,2194,2085,1406,2777,2400, 150,1250,4049,1206, 807,
+1910, 534, 529,3309,1721,1660, 274,  39,2827, 661,2670,1578, 925,3248,3815,1094,
+4278,4901,4252,  41,1150,3747,2572,2227,4501,3658,4902,3813,3357,3617,2884,2258,
+ 887, 538,4187,3199,1294,2439,3042,2329,2343,2497,1255, 107, 543,1527, 521,3478,
+3568, 194,5062,  15, 961,3870,1241,1192,2664,  66,5215,3260,2111,1295,1127,2152,
+3805,4135, 901,1164,1976, 398,1278, 530,1460, 748, 904,1054,1966,1426,  53,2909,
+ 509, 523,2279,1534, 536,1019, 239,1685, 460,2353, 673,1065,2401,3600,4298,2272,
+1272,2363, 284,1753,3679,4064,1695,  81, 815,2677,2757,2731,1386, 859, 500,4221,
+2190,2566, 757,1006,2519,2068,1166,1455, 337,2654,3203,1863,1682,1914,3025,1252,
+1409,1366, 847, 714,2834,2038,3209, 964,2970,1901, 885,2553,1078,1756,3049, 301,
+1572,3326, 688,2130,1996,2429,1805,1648,2930,3421,2750,3652,3088, 262,1158,1254,
+ 389,1641,1812, 526,1719, 923,2073,1073,1902, 468, 489,4625,1140, 857,2375,3070,
+3319,2863, 380, 116,1328,2693,1161,2244, 273,1212,1884,2769,3011,1775,1142, 461,
+3066,1200,2147,2212, 790, 702,2695,4222,1601,1058, 434,2338,5153,3640,  67,2360,
+4099,2502, 618,3472,1329, 416,1132, 830,2782,1807,2653,3211,3510,1662, 192,2124,
+ 296,3979,1739,1611,3684,  23, 118, 324, 446,1239,1225, 293,2520,3814,3795,2535,
+3116,  17,1074, 467,2692,2201, 387,2922,  45,1326,3055,1645,3659,2817, 958, 243,
+1903,2320,1339,2825,1784,3289, 356, 576, 865,2315,2381,3377,3916,1088,3122,1713,
+1655, 935, 628,4689,1034,1327, 441, 800, 720, 894,1979,2183,1528,5289,2702,1071,
+4046,3572,2399,1571,3281,  79, 761,1103, 327, 134, 758,1899,1371,1615, 879, 442,
+ 215,2605,2579, 173,2048,2485,1057,2975,3317,1097,2253,3801,4263,1403,1650,2946,
+ 814,4968,3487,1548,2644,1567,1285,   2, 295,2636,  97, 946,3576, 832, 141,4257,
+3273, 760,3821,3521,3156,2607, 949,1024,1733,1516,1803,1920,2125,2283,2665,3180,
+1501,2064,3560,2171,1592, 803,3518,1416, 732,3897,4258,1363,1362,2458, 119,1427,
+ 602,1525,2608,1605,1639,3175, 694,3064,  10, 465,  76,2000,4846,4208, 444,3781,
+1619,3353,2206,1273,3796, 740,2483, 320,1723,2377,3660,2619,1359,1137,1762,1724,
+2345,2842,1850,1862, 912, 821,1866, 612,2625,1735,2573,3369,1093, 844,  89, 937,
+ 930,1424,3564,2413,2972,1004,3046,3019,2011, 711,3171,1452,4178, 428, 801,1943,
+ 432, 445,2811, 206,4136,1472, 730, 349,  73, 397,2802,2547, 998,1637,1167, 789,
+ 396,3217, 154,1218, 716,1120,1780,2819,4826,1931,3334,3762,2139,1215,2627, 552,
+3664,3628,3232,1405,2383,3111,1356,2652,3577,3320,3101,1703, 640,1045,1370,1246,
+4996, 371,1575,2436,1621,2210, 984,4033,1734,2638,  16,4529, 663,2755,3255,1451,
+3917,2257,1253,1955,2234,1263,2951, 214,1229, 617, 485, 359,1831,1969, 473,2310,
+ 750,2058, 165,  80,2864,2419, 361,4344,2416,2479,1134, 796,3726,1266,2943, 860,
+2715, 938, 390,2734,1313,1384, 248, 202, 877,1064,2854, 522,3907, 279,1602, 297,
+2357, 395,3740, 137,2075, 944,4089,2584,1267,3802,  62,1533,2285, 178, 176, 780,
+2440, 201,3707, 590, 478,1560,4354,2117,1075,  30,  74,4643,4004,1635,1441,2745,
+ 776,2596, 238,1077,1692,1912,2844, 605, 499,1742,3947, 241,3053, 980,1749, 936,
+2640,4511,2582, 515,1543,2162,5322,2892,2993, 890,2148,1924, 665,1827,3581,1032,
+ 968,3163, 339,1044,1896, 270, 583,1791,1720,4367,1194,3488,3669,  43,2523,1657,
+ 163,2167, 290,1209,1622,3378, 550, 634,2508,2510, 695,2634,2384,2512,1476,1414,
+ 220,1469,2341,2138,2852,3183,2900,4939,2865,3502,1211,3680, 854,3227,1299,2976,
+3172, 186,2998,1459, 443,1067,3251,1495, 321,1932,3054, 909, 753,1410,1828, 436,
+2441,1119,1587,3164,2186,1258, 227, 231,1425,1890,3200,3942, 247, 959, 725,5254,
+2741, 577,2158,2079, 929, 120, 174, 838,2813, 591,1115, 417,2024,  40,3240,1536,
+1037, 291,4151,2354, 632,1298,2406,2500,3535,1825,1846,3451, 205,1171, 345,4238,
+  18,1163, 811, 685,2208,1217, 425,1312,1508,1175,4308,2552,1033, 587,1381,3059,
+2984,3482, 340,1316,4023,3972, 792,3176, 519, 777,4690, 918, 933,4130,2981,3741,
+  90,3360,2911,2200,5184,4550, 609,3079,2030, 272,3379,2736, 363,3881,1130,1447,
+ 286, 779, 357,1169,3350,3137,1630,1220,2687,2391, 747,1277,3688,2618,2682,2601,
+1156,3196,5290,4034,3102,1689,3596,3128, 874, 219,2783, 798, 508,1843,2461, 269,
+1658,1776,1392,1913,2983,3287,2866,2159,2372, 829,4076,  46,4253,2873,1889,1894,
+ 915,1834,1631,2181,2318, 298, 664,2818,3555,2735, 954,3228,3117, 527,3511,2173,
+ 681,2712,3033,2247,2346,3467,1652, 155,2164,3382, 113,1994, 450, 899, 494, 994,
+1237,2958,1875,2336,1926,3727, 545,1577,1550, 633,3473, 204,1305,3072,2410,1956,
+2471, 707,2134, 841,2195,2196,2663,3843,1026,4940, 990,3252,4997, 368,1092, 437,
+3212,3258,1933,1829, 675,2977,2893, 412, 943,3723,4644,3294,3283,2230,2373,5154,
+2389,2241,2661,2323,1404,2524, 593, 787, 677,3008,1275,2059, 438,2709,2609,2240,
+2269,2246,1446,  36,1568,1373,3892,1574,2301,1456,3962, 693,2276,5216,2035,1143,
+2720,1919,1797,1811,2763,4137,2597,1830,1699,1488,1198,2090, 424,1694, 312,3634,
+3390,4179,3335,2252,1214, 561,1059,3243,2295,2561, 975,5155,2321,2751,3772, 472,
+1537,3282,3398,1047,2077,2348,2878,1323,3340,3076, 690,2906,  51, 369, 170,3541,
+1060,2187,2688,3670,2541,1083,1683, 928,3918, 459, 109,4427, 599,3744,4286, 143,
+2101,2730,2490,  82,1588,3036,2121, 281,1860, 477,4035,1238,2812,3020,2716,3312,
+1530,2188,2055,1317, 843, 636,1808,1173,3495, 649, 181,1002, 147,3641,1159,2414,
+3750,2289,2795, 813,3123,2610,1136,4368,   5,3391,4541,2174, 420, 429,1728, 754,
+1228,2115,2219, 347,2223,2733, 735,1518,3003,2355,3134,1764,3948,3329,1888,2424,
+1001,1234,1972,3321,3363,1672,1021,1450,1584, 226, 765, 655,2526,3404,3244,2302,
+3665, 731, 594,2184, 319,1576, 621, 658,2656,4299,2099,3864,1279,2071,2598,2739,
+ 795,3086,3699,3908,1707,2352,2402,1382,3136,2475,1465,4847,3496,3865,1085,3004,
+2591,1084, 213,2287,1963,3565,2250, 822, 793,4574,3187,1772,1789,3050, 595,1484,
+1959,2770,1080,2650, 456, 422,2996, 940,3322,4328,4345,3092,2742, 965,2784, 739,
+4124, 952,1358,2498,2949,2565, 332,2698,2378, 660,2260,2473,4194,3856,2919, 535,
+1260,2651,1208,1428,1300,1949,1303,2942, 433,2455,2450,1251,1946, 614,1269, 641,
+1306,1810,2737,3078,2912, 564,2365,1419,1415,1497,4460,2367,2185,1379,3005,1307,
+3218,2175,1897,3063, 682,1157,4040,4005,1712,1160,1941,1399, 394, 402,2952,1573,
+1151,2986,2404, 862, 299,2033,1489,3006, 346, 171,2886,3401,1726,2932, 168,2533,
+  47,2507,1030,3735,1145,3370,1395,1318,1579,3609,4560,2857,4116,1457,2529,1965,
+ 504,1036,2690,2988,2405, 745,5871, 849,2397,2056,3081, 863,2359,3857,2096,  99,
+1397,1769,2300,4428,1643,3455,1978,1757,3718,1440,  35,4879,3742,1296,4228,2280,
+ 160,5063,1599,2013, 166, 520,3479,1646,3345,3012, 490,1937,1545,1264,2182,2505,
+1096,1188,1369,1436,2421,1667,2792,2460,1270,2122, 727,3167,2143, 806,1706,1012,
+1800,3037, 960,2218,1882, 805, 139,2456,1139,1521, 851,1052,3093,3089, 342,2039,
+ 744,5097,1468,1502,1585,2087, 223, 939, 326,2140,2577, 892,2481,1623,4077, 982,
+3708, 135,2131,  87,2503,3114,2326,1106, 876,1616, 547,2997,2831,2093,3441,4530,
+4314,   9,3256,4229,4148, 659,1462,1986,1710,2046,2913,2231,4090,4880,5255,3392,
+3274,1368,3689,4645,1477, 705,3384,3635,1068,1529,2941,1458,3782,1509, 100,1656,
+2548, 718,2339, 408,1590,2780,3548,1838,4117,3719,1345,3530, 717,3442,2778,3220,
+2898,1892,4590,3614,3371,2043,1998,1224,3483, 891, 635, 584,2559,3355, 733,1766,
+1729,1172,3789,1891,2307, 781,2982,2271,1957,1580,5773,2633,2005,4195,3097,1535,
+3213,1189,1934,5693,3262, 586,3118,1324,1598, 517,1564,2217,1868,1893,4445,3728,
+2703,3139,1526,1787,1992,3882,2875,1549,1199,1056,2224,1904,2711,5098,4287, 338,
+1993,3129,3489,2689,1809,2815,1997, 957,1855,3898,2550,3275,3057,1105,1319, 627,
+1505,1911,1883,3526, 698,3629,3456,1833,1431, 746,  77,1261,2017,2296,1977,1885,
+ 125,1334,1600, 525,1798,1109,2222,1470,1945, 559,2236,1186,3443,2476,1929,1411,
+2411,3135,1777,3372,2621,1841,1613,3229, 668,1430,1839,2643,2916, 195,1989,2671,
+2358,1387, 629,3205,2293,5256,4439, 123,1310, 888,1879,4300,3021,3605,1003,1162,
+3192,2910,2010, 140,2395,2859,  55,1082,2012,2901, 662, 419,2081,1438, 680,2774,
+4654,3912,1620,1731,1625,5035,4065,2328, 512,1344, 802,5443,2163,2311,2537, 524,
+3399,  98,1155,2103,1918,2606,3925,2816,1393,2465,1504,3773,2177,3963,1478,4346,
+ 180,1113,4655,3461,2028,1698, 833,2696,1235,1322,1594,4408,3623,3013,3225,2040,
+3022, 541,2881, 607,3632,2029,1665,1219, 639,1385,1686,1099,2803,3231,1938,3188,
+2858, 427, 676,2772,1168,2025, 454,3253,2486,3556, 230,1950, 580, 791,1991,1280,
+1086,1974,2034, 630, 257,3338,2788,4903,1017,  86,4790, 966,2789,1995,1696,1131,
+ 259,3095,4188,1308, 179,1463,5257, 289,4107,1248,  42,3413,1725,2288, 896,1947,
+ 774,4474,4254, 604,3430,4264, 392,2514,2588, 452, 237,1408,3018, 988,4531,1970,
+3034,3310, 540,2370,1562,1288,2990, 502,4765,1147,   4,1853,2708, 207, 294,2814,
+4078,2902,2509, 684,  34,3105,3532,2551, 644, 709,2801,2344, 573,1727,3573,3557,
+2021,1081,3100,4315,2100,3681, 199,2263,1837,2385, 146,3484,1195,2776,3949, 997,
+1939,3973,1008,1091,1202,1962,1847,1149,4209,5444,1076, 493, 117,5400,2521, 972,
+1490,2934,1796,4542,2374,1512,2933,2657, 413,2888,1135,2762,2314,2156,1355,2369,
+ 766,2007,2527,2170,3124,2491,2593,2632,4757,2437, 234,3125,3591,1898,1750,1376,
+1942,3468,3138, 570,2127,2145,3276,4131, 962, 132,1445,4196,  19, 941,3624,3480,
+3366,1973,1374,4461,3431,2629, 283,2415,2275, 808,2887,3620,2112,2563,1353,3610,
+ 955,1089,3103,1053,  96,  88,4097, 823,3808,1583, 399, 292,4091,3313, 421,1128,
+ 642,4006, 903,2539,1877,2082, 596,  29,4066,1790, 722,2157, 130, 995,1569, 769,
+1485, 464, 513,2213, 288,1923,1101,2453,4316, 133, 486,2445,  50, 625, 487,2207,
+  57, 423, 481,2962, 159,3729,1558, 491, 303, 482, 501, 240,2837, 112,3648,2392,
+1783, 362,   8,3433,3422, 610,2793,3277,1390,1284,1654,  21,3823, 734, 367, 623,
+ 193, 287, 374,1009,1483, 816, 476, 313,2255,2340,1262,2150,2899,1146,2581, 782,
+2116,1659,2018,1880, 255,3586,3314,1110,2867,2137,2564, 986,2767,5185,2006, 650,
+ 158, 926, 762, 881,3157,2717,2362,3587, 306,3690,3245,1542,3077,2427,1691,2478,
+2118,2985,3490,2438, 539,2305, 983, 129,1754, 355,4201,2386, 827,2923, 104,1773,
+2838,2771, 411,2905,3919, 376, 767, 122,1114, 828,2422,1817,3506, 266,3460,1007,
+1609,4998, 945,2612,4429,2274, 726,1247,1964,2914,2199,2070,4002,4108, 657,3323,
+1422, 579, 455,2764,4737,1222,2895,1670, 824,1223,1487,2525, 558, 861,3080, 598,
+2659,2515,1967, 752,2583,2376,2214,4180, 977, 704,2464,4999,2622,4109,1210,2961,
+ 819,1541, 142,2284,  44, 418, 457,1126,3730,4347,4626,1644,1876,3671,1864, 302,
+1063,5694, 624, 723,1984,3745,1314,1676,2488,1610,1449,3558,3569,2166,2098, 409,
+1011,2325,3704,2306, 818,1732,1383,1824,1844,3757, 999,2705,3497,1216,1423,2683,
+2426,2954,2501,2726,2229,1475,2554,5064,1971,1794,1666,2014,1343, 783, 724, 191,
+2434,1354,2220,5065,1763,2752,2472,4152, 131, 175,2885,3434,  92,1466,4920,2616,
+3871,3872,3866, 128,1551,1632, 669,1854,3682,4691,4125,1230, 188,2973,3290,1302,
+1213, 560,3266, 917, 763,3909,3249,1760, 868,1958, 764,1782,2097, 145,2277,3774,
+4462,  64,1491,3062, 971,2132,3606,2442, 221,1226,1617, 218, 323,1185,3207,3147,
+ 571, 619,1473,1005,1744,2281, 449,1887,2396,3685, 275, 375,3816,1743,3844,3731,
+ 845,1983,2350,4210,1377, 773, 967,3499,3052,3743,2725,4007,1697,1022,3943,1464,
+3264,2855,2722,1952,1029,2839,2467,  84,4383,2215, 820,1391,2015,2448,3672, 377,
+1948,2168, 797,2545,3536,2578,2645,  94,2874,1678, 405,1259,3071, 771, 546,1315,
+ 470,1243,3083, 895,2468, 981, 969,2037, 846,4181, 653,1276,2928,  14,2594, 557,
+3007,2474, 156, 902,1338,1740,2574, 537,2518, 973,2282,2216,2433,1928, 138,2903,
+1293,2631,1612, 646,3457, 839,2935, 111, 496,2191,2847, 589,3186, 149,3994,2060,
+4031,2641,4067,3145,1870,  37,3597,2136,1025,2051,3009,3383,3549,1121,1016,3261,
+1301, 251,2446,2599,2153, 872,3246, 637, 334,3705, 831, 884, 921,3065,3140,4092,
+2198,1944, 246,2964, 108,2045,1152,1921,2308,1031, 203,3173,4170,1907,3890, 810,
+1401,2003,1690, 506, 647,1242,2828,1761,1649,3208,2249,1589,3709,2931,5156,1708,
+ 498, 666,2613, 834,3817,1231, 184,2851,1124, 883,3197,2261,3710,1765,1553,2658,
+1178,2639,2351,  93,1193, 942,2538,2141,4402, 235,1821, 870,1591,2192,1709,1871,
+3341,1618,4126,2595,2334, 603, 651,  69, 701, 268,2662,3411,2555,1380,1606, 503,
+ 448, 254,2371,2646, 574,1187,2309,1770, 322,2235,1292,1801, 305, 566,1133, 229,
+2067,2057, 706, 167, 483,2002,2672,3295,1820,3561,3067, 316, 378,2746,3452,1112,
+ 136,1981, 507,1651,2917,1117, 285,4591, 182,2580,3522,1304, 335,3303,1835,2504,
+1795,1792,2248, 674,1018,2106,2449,1857,2292,2845, 976,3047,1781,2600,2727,1389,
+1281,  52,3152, 153, 265,3950, 672,3485,3951,4463, 430,1183, 365, 278,2169,  27,
+1407,1336,2304, 209,1340,1730,2202,1852,2403,2883, 979,1737,1062, 631,2829,2542,
+3876,2592, 825,2086,2226,3048,3625, 352,1417,3724, 542, 991, 431,1351,3938,1861,
+2294, 826,1361,2927,3142,3503,1738, 463,2462,2723, 582,1916,1595,2808, 400,3845,
+3891,2868,3621,2254,  58,2492,1123, 910,2160,2614,1372,1603,1196,1072,3385,1700,
+3267,1980, 696, 480,2430, 920, 799,1570,2920,1951,2041,4047,2540,1321,4223,2469,
+3562,2228,1271,2602, 401,2833,3351,2575,5157, 907,2312,1256, 410, 263,3507,1582,
+ 996, 678,1849,2316,1480, 908,3545,2237, 703,2322, 667,1826,2849,1531,2604,2999,
+2407,3146,2151,2630,1786,3711, 469,3542, 497,3899,2409, 858, 837,4446,3393,1274,
+ 786, 620,1845,2001,3311, 484, 308,3367,1204,1815,3691,2332,1532,2557,1842,2020,
+2724,1927,2333,4440, 567,  22,1673,2728,4475,1987,1858,1144,1597, 101,1832,3601,
+  12, 974,3783,4391, 951,1412,   1,3720, 453,4608,4041, 528,1041,1027,3230,2628,
+1129, 875,1051,3291,1203,2262,1069,2860,2799,2149,2615,3278, 144,1758,3040,  31,
+ 475,1680, 366,2685,3184, 311,1642,4008,2466,5036,1593,1493,2809, 216,1420,1668,
+ 233, 304,2128,3284, 232,1429,1768,1040,2008,3407,2740,2967,2543, 242,2133, 778,
+1565,2022,2620, 505,2189,2756,1098,2273, 372,1614, 708, 553,2846,2094,2278, 169,
+3626,2835,4161, 228,2674,3165, 809,1454,1309, 466,1705,1095, 900,3423, 880,2667,
+3751,5258,2317,3109,2571,4317,2766,1503,1342, 866,4447,1118,  63,2076, 314,1881,
+1348,1061, 172, 978,3515,1747, 532, 511,3970,   6, 601, 905,2699,3300,1751, 276,
+1467,3725,2668,  65,4239,2544,2779,2556,1604, 578,2451,1802, 992,2331,2624,1320,
+3446, 713,1513,1013, 103,2786,2447,1661, 886,1702, 916, 654,3574,2031,1556, 751,
+2178,2821,2179,1498,1538,2176, 271, 914,2251,2080,1325, 638,1953,2937,3877,2432,
+2754,  95,3265,1716, 260,1227,4083, 775, 106,1357,3254, 426,1607, 555,2480, 772,
+1985, 244,2546, 474, 495,1046,2611,1851,2061,  71,2089,1675,2590, 742,3758,2843,
+3222,1433, 267,2180,2576,2826,2233,2092,3913,2435, 956,1745,3075, 856,2113,1116,
+ 451,   3,1988,2896,1398, 993,2463,1878,2049,1341,2718,2721,2870,2108, 712,2904,
+4363,2753,2324, 277,2872,2349,2649, 384, 987, 435, 691,3000, 922, 164,3939, 652,
+1500,1184,4153,2482,3373,2165,4848,2335,3775,3508,3154,2806,2830,1554,2102,1664,
+2530,1434,2408, 893,1547,2623,3447,2832,2242,2532,3169,2856,3223,2078,  49,3770,
+3469, 462, 318, 656,2259,3250,3069, 679,1629,2758, 344,1138,1104,3120,1836,1283,
+3115,2154,1437,4448, 934, 759,1999, 794,2862,1038, 533,2560,1722,2342, 855,2626,
+1197,1663,4476,3127,  85,4240,2528,  25,1111,1181,3673, 407,3470,4561,2679,2713,
+ 768,1925,2841,3986,1544,1165, 932, 373,1240,2146,1930,2673, 721,4766, 354,4333,
+ 391,2963, 187,  61,3364,1442,1102, 330,1940,1767, 341,3809,4118, 393,2496,2062,
+2211, 105, 331, 300, 439, 913,1332, 626, 379,3304,1557, 328, 689,3952, 309,1555,
+ 931, 317,2517,3027, 325, 569, 686,2107,3084,  60,1042,1333,2794, 264,3177,4014,
+1628, 258,3712,   7,4464,1176,1043,1778, 683, 114,1975,  78,1492, 383,1886, 510,
+ 386, 645,5291,2891,2069,3305,4138,3867,2939,2603,2493,1935,1066,1848,3588,1015,
+1282,1289,4609, 697,1453,3044,2666,3611,1856,2412,  54, 719,1330, 568,3778,2459,
+1748, 788, 492, 551,1191,1000, 488,3394,3763, 282,1799, 348,2016,1523,3155,2390,
+1049, 382,2019,1788,1170, 729,2968,3523, 897,3926,2785,2938,3292, 350,2319,3238,
+1718,1717,2655,3453,3143,4465, 161,2889,2980,2009,1421,  56,1908,1640,2387,2232,
+1917,1874,2477,4921, 148,  83,3438, 592,4245,2882,1822,1055, 741, 115,1496,1624,
+ 381,1638,4592,1020, 516,3214, 458, 947,4575,1432, 211,1514,2926,1865,2142, 189,
+ 852,1221,1400,1486, 882,2299,4036, 351,  28,1122, 700,6479,6480,6481,6482,6483,  # last 512
+#Everything below is of no interest for detection purpose
+5508,6484,3900,3414,3974,4441,4024,3537,4037,5628,5099,3633,6485,3148,6486,3636,
+5509,3257,5510,5973,5445,5872,4941,4403,3174,4627,5873,6276,2286,4230,5446,5874,
+5122,6102,6103,4162,5447,5123,5323,4849,6277,3980,3851,5066,4246,5774,5067,6278,
+3001,2807,5695,3346,5775,5974,5158,5448,6487,5975,5976,5776,3598,6279,5696,4806,
+4211,4154,6280,6488,6489,6490,6281,4212,5037,3374,4171,6491,4562,4807,4722,4827,
+5977,6104,4532,4079,5159,5324,5160,4404,3858,5359,5875,3975,4288,4610,3486,4512,
+5325,3893,5360,6282,6283,5560,2522,4231,5978,5186,5449,2569,3878,6284,5401,3578,
+4415,6285,4656,5124,5979,2506,4247,4449,3219,3417,4334,4969,4329,6492,4576,4828,
+4172,4416,4829,5402,6286,3927,3852,5361,4369,4830,4477,4867,5876,4173,6493,6105,
+4657,6287,6106,5877,5450,6494,4155,4868,5451,3700,5629,4384,6288,6289,5878,3189,
+4881,6107,6290,6495,4513,6496,4692,4515,4723,5100,3356,6497,6291,3810,4080,5561,
+3570,4430,5980,6498,4355,5697,6499,4724,6108,6109,3764,4050,5038,5879,4093,3226,
+6292,5068,5217,4693,3342,5630,3504,4831,4377,4466,4309,5698,4431,5777,6293,5778,
+4272,3706,6110,5326,3752,4676,5327,4273,5403,4767,5631,6500,5699,5880,3475,5039,
+6294,5562,5125,4348,4301,4482,4068,5126,4593,5700,3380,3462,5981,5563,3824,5404,
+4970,5511,3825,4738,6295,6501,5452,4516,6111,5881,5564,6502,6296,5982,6503,4213,
+4163,3454,6504,6112,4009,4450,6113,4658,6297,6114,3035,6505,6115,3995,4904,4739,
+4563,4942,4110,5040,3661,3928,5362,3674,6506,5292,3612,4791,5565,4149,5983,5328,
+5259,5021,4725,4577,4564,4517,4364,6298,5405,4578,5260,4594,4156,4157,5453,3592,
+3491,6507,5127,5512,4709,4922,5984,5701,4726,4289,6508,4015,6116,5128,4628,3424,
+4241,5779,6299,4905,6509,6510,5454,5702,5780,6300,4365,4923,3971,6511,5161,3270,
+3158,5985,4100, 867,5129,5703,6117,5363,3695,3301,5513,4467,6118,6512,5455,4232,
+4242,4629,6513,3959,4478,6514,5514,5329,5986,4850,5162,5566,3846,4694,6119,5456,
+4869,5781,3779,6301,5704,5987,5515,4710,6302,5882,6120,4392,5364,5705,6515,6121,
+6516,6517,3736,5988,5457,5989,4695,2457,5883,4551,5782,6303,6304,6305,5130,4971,
+6122,5163,6123,4870,3263,5365,3150,4871,6518,6306,5783,5069,5706,3513,3498,4409,
+5330,5632,5366,5458,5459,3991,5990,4502,3324,5991,5784,3696,4518,5633,4119,6519,
+4630,5634,4417,5707,4832,5992,3418,6124,5993,5567,4768,5218,6520,4595,3458,5367,
+6125,5635,6126,4202,6521,4740,4924,6307,3981,4069,4385,6308,3883,2675,4051,3834,
+4302,4483,5568,5994,4972,4101,5368,6309,5164,5884,3922,6127,6522,6523,5261,5460,
+5187,4164,5219,3538,5516,4111,3524,5995,6310,6311,5369,3181,3386,2484,5188,3464,
+5569,3627,5708,6524,5406,5165,4677,4492,6312,4872,4851,5885,4468,5996,6313,5709,
+5710,6128,2470,5886,6314,5293,4882,5785,3325,5461,5101,6129,5711,5786,6525,4906,
+6526,6527,4418,5887,5712,4808,2907,3701,5713,5888,6528,3765,5636,5331,6529,6530,
+3593,5889,3637,4943,3692,5714,5787,4925,6315,6130,5462,4405,6131,6132,6316,5262,
+6531,6532,5715,3859,5716,5070,4696,5102,3929,5788,3987,4792,5997,6533,6534,3920,
+4809,5000,5998,6535,2974,5370,6317,5189,5263,5717,3826,6536,3953,5001,4883,3190,
+5463,5890,4973,5999,4741,6133,6134,3607,5570,6000,4711,3362,3630,4552,5041,6318,
+6001,2950,2953,5637,4646,5371,4944,6002,2044,4120,3429,6319,6537,5103,4833,6538,
+6539,4884,4647,3884,6003,6004,4758,3835,5220,5789,4565,5407,6540,6135,5294,4697,
+4852,6320,6321,3206,4907,6541,6322,4945,6542,6136,6543,6323,6005,4631,3519,6544,
+5891,6545,5464,3784,5221,6546,5571,4659,6547,6324,6137,5190,6548,3853,6549,4016,
+4834,3954,6138,5332,3827,4017,3210,3546,4469,5408,5718,3505,4648,5790,5131,5638,
+5791,5465,4727,4318,6325,6326,5792,4553,4010,4698,3439,4974,3638,4335,3085,6006,
+5104,5042,5166,5892,5572,6327,4356,4519,5222,5573,5333,5793,5043,6550,5639,5071,
+4503,6328,6139,6551,6140,3914,3901,5372,6007,5640,4728,4793,3976,3836,4885,6552,
+4127,6553,4451,4102,5002,6554,3686,5105,6555,5191,5072,5295,4611,5794,5296,6556,
+5893,5264,5894,4975,5466,5265,4699,4976,4370,4056,3492,5044,4886,6557,5795,4432,
+4769,4357,5467,3940,4660,4290,6141,4484,4770,4661,3992,6329,4025,4662,5022,4632,
+4835,4070,5297,4663,4596,5574,5132,5409,5895,6142,4504,5192,4664,5796,5896,3885,
+5575,5797,5023,4810,5798,3732,5223,4712,5298,4084,5334,5468,6143,4052,4053,4336,
+4977,4794,6558,5335,4908,5576,5224,4233,5024,4128,5469,5225,4873,6008,5045,4729,
+4742,4633,3675,4597,6559,5897,5133,5577,5003,5641,5719,6330,6560,3017,2382,3854,
+4406,4811,6331,4393,3964,4946,6561,2420,3722,6562,4926,4378,3247,1736,4442,6332,
+5134,6333,5226,3996,2918,5470,4319,4003,4598,4743,4744,4485,3785,3902,5167,5004,
+5373,4394,5898,6144,4874,1793,3997,6334,4085,4214,5106,5642,4909,5799,6009,4419,
+4189,3330,5899,4165,4420,5299,5720,5227,3347,6145,4081,6335,2876,3930,6146,3293,
+3786,3910,3998,5900,5300,5578,2840,6563,5901,5579,6147,3531,5374,6564,6565,5580,
+4759,5375,6566,6148,3559,5643,6336,6010,5517,6337,6338,5721,5902,3873,6011,6339,
+6567,5518,3868,3649,5722,6568,4771,4947,6569,6149,4812,6570,2853,5471,6340,6341,
+5644,4795,6342,6012,5723,6343,5724,6013,4349,6344,3160,6150,5193,4599,4514,4493,
+5168,4320,6345,4927,3666,4745,5169,5903,5005,4928,6346,5725,6014,4730,4203,5046,
+4948,3395,5170,6015,4150,6016,5726,5519,6347,5047,3550,6151,6348,4197,4310,5904,
+6571,5581,2965,6152,4978,3960,4291,5135,6572,5301,5727,4129,4026,5905,4853,5728,
+5472,6153,6349,4533,2700,4505,5336,4678,3583,5073,2994,4486,3043,4554,5520,6350,
+6017,5800,4487,6351,3931,4103,5376,6352,4011,4321,4311,4190,5136,6018,3988,3233,
+4350,5906,5645,4198,6573,5107,3432,4191,3435,5582,6574,4139,5410,6353,5411,3944,
+5583,5074,3198,6575,6354,4358,6576,5302,4600,5584,5194,5412,6577,6578,5585,5413,
+5303,4248,5414,3879,4433,6579,4479,5025,4854,5415,6355,4760,4772,3683,2978,4700,
+3797,4452,3965,3932,3721,4910,5801,6580,5195,3551,5907,3221,3471,3029,6019,3999,
+5908,5909,5266,5267,3444,3023,3828,3170,4796,5646,4979,4259,6356,5647,5337,3694,
+6357,5648,5338,4520,4322,5802,3031,3759,4071,6020,5586,4836,4386,5048,6581,3571,
+4679,4174,4949,6154,4813,3787,3402,3822,3958,3215,3552,5268,4387,3933,4950,4359,
+6021,5910,5075,3579,6358,4234,4566,5521,6359,3613,5049,6022,5911,3375,3702,3178,
+4911,5339,4521,6582,6583,4395,3087,3811,5377,6023,6360,6155,4027,5171,5649,4421,
+4249,2804,6584,2270,6585,4000,4235,3045,6156,5137,5729,4140,4312,3886,6361,4330,
+6157,4215,6158,3500,3676,4929,4331,3713,4930,5912,4265,3776,3368,5587,4470,4855,
+3038,4980,3631,6159,6160,4132,4680,6161,6362,3923,4379,5588,4255,6586,4121,6587,
+6363,4649,6364,3288,4773,4774,6162,6024,6365,3543,6588,4274,3107,3737,5050,5803,
+4797,4522,5589,5051,5730,3714,4887,5378,4001,4523,6163,5026,5522,4701,4175,2791,
+3760,6589,5473,4224,4133,3847,4814,4815,4775,3259,5416,6590,2738,6164,6025,5304,
+3733,5076,5650,4816,5590,6591,6165,6592,3934,5269,6593,3396,5340,6594,5804,3445,
+3602,4042,4488,5731,5732,3525,5591,4601,5196,6166,6026,5172,3642,4612,3202,4506,
+4798,6366,3818,5108,4303,5138,5139,4776,3332,4304,2915,3415,4434,5077,5109,4856,
+2879,5305,4817,6595,5913,3104,3144,3903,4634,5341,3133,5110,5651,5805,6167,4057,
+5592,2945,4371,5593,6596,3474,4182,6367,6597,6168,4507,4279,6598,2822,6599,4777,
+4713,5594,3829,6169,3887,5417,6170,3653,5474,6368,4216,2971,5228,3790,4579,6369,
+5733,6600,6601,4951,4746,4555,6602,5418,5475,6027,3400,4665,5806,6171,4799,6028,
+5052,6172,3343,4800,4747,5006,6370,4556,4217,5476,4396,5229,5379,5477,3839,5914,
+5652,5807,4714,3068,4635,5808,6173,5342,4192,5078,5419,5523,5734,6174,4557,6175,
+4602,6371,6176,6603,5809,6372,5735,4260,3869,5111,5230,6029,5112,6177,3126,4681,
+5524,5915,2706,3563,4748,3130,6178,4018,5525,6604,6605,5478,4012,4837,6606,4534,
+4193,5810,4857,3615,5479,6030,4082,3697,3539,4086,5270,3662,4508,4931,5916,4912,
+5811,5027,3888,6607,4397,3527,3302,3798,2775,2921,2637,3966,4122,4388,4028,4054,
+1633,4858,5079,3024,5007,3982,3412,5736,6608,3426,3236,5595,3030,6179,3427,3336,
+3279,3110,6373,3874,3039,5080,5917,5140,4489,3119,6374,5812,3405,4494,6031,4666,
+4141,6180,4166,6032,5813,4981,6609,5081,4422,4982,4112,3915,5653,3296,3983,6375,
+4266,4410,5654,6610,6181,3436,5082,6611,5380,6033,3819,5596,4535,5231,5306,5113,
+6612,4952,5918,4275,3113,6613,6376,6182,6183,5814,3073,4731,4838,5008,3831,6614,
+4888,3090,3848,4280,5526,5232,3014,5655,5009,5737,5420,5527,6615,5815,5343,5173,
+5381,4818,6616,3151,4953,6617,5738,2796,3204,4360,2989,4281,5739,5174,5421,5197,
+3132,5141,3849,5142,5528,5083,3799,3904,4839,5480,2880,4495,3448,6377,6184,5271,
+5919,3771,3193,6034,6035,5920,5010,6036,5597,6037,6378,6038,3106,5422,6618,5423,
+5424,4142,6619,4889,5084,4890,4313,5740,6620,3437,5175,5307,5816,4199,5198,5529,
+5817,5199,5656,4913,5028,5344,3850,6185,2955,5272,5011,5818,4567,4580,5029,5921,
+3616,5233,6621,6622,6186,4176,6039,6379,6380,3352,5200,5273,2908,5598,5234,3837,
+5308,6623,6624,5819,4496,4323,5309,5201,6625,6626,4983,3194,3838,4167,5530,5922,
+5274,6381,6382,3860,3861,5599,3333,4292,4509,6383,3553,5481,5820,5531,4778,6187,
+3955,3956,4324,4389,4218,3945,4325,3397,2681,5923,4779,5085,4019,5482,4891,5382,
+5383,6040,4682,3425,5275,4094,6627,5310,3015,5483,5657,4398,5924,3168,4819,6628,
+5925,6629,5532,4932,4613,6041,6630,4636,6384,4780,4204,5658,4423,5821,3989,4683,
+5822,6385,4954,6631,5345,6188,5425,5012,5384,3894,6386,4490,4104,6632,5741,5053,
+6633,5823,5926,5659,5660,5927,6634,5235,5742,5824,4840,4933,4820,6387,4859,5928,
+4955,6388,4143,3584,5825,5346,5013,6635,5661,6389,5014,5484,5743,4337,5176,5662,
+6390,2836,6391,3268,6392,6636,6042,5236,6637,4158,6638,5744,5663,4471,5347,3663,
+4123,5143,4293,3895,6639,6640,5311,5929,5826,3800,6189,6393,6190,5664,5348,3554,
+3594,4749,4603,6641,5385,4801,6043,5827,4183,6642,5312,5426,4761,6394,5665,6191,
+4715,2669,6643,6644,5533,3185,5427,5086,5930,5931,5386,6192,6044,6645,4781,4013,
+5745,4282,4435,5534,4390,4267,6045,5746,4984,6046,2743,6193,3501,4087,5485,5932,
+5428,4184,4095,5747,4061,5054,3058,3862,5933,5600,6646,5144,3618,6395,3131,5055,
+5313,6396,4650,4956,3855,6194,3896,5202,4985,4029,4225,6195,6647,5828,5486,5829,
+3589,3002,6648,6397,4782,5276,6649,6196,6650,4105,3803,4043,5237,5830,6398,4096,
+3643,6399,3528,6651,4453,3315,4637,6652,3984,6197,5535,3182,3339,6653,3096,2660,
+6400,6654,3449,5934,4250,4236,6047,6401,5831,6655,5487,3753,4062,5832,6198,6199,
+6656,3766,6657,3403,4667,6048,6658,4338,2897,5833,3880,2797,3780,4326,6659,5748,
+5015,6660,5387,4351,5601,4411,6661,3654,4424,5935,4339,4072,5277,4568,5536,6402,
+6662,5238,6663,5349,5203,6200,5204,6201,5145,4536,5016,5056,4762,5834,4399,4957,
+6202,6403,5666,5749,6664,4340,6665,5936,5177,5667,6666,6667,3459,4668,6404,6668,
+6669,4543,6203,6670,4276,6405,4480,5537,6671,4614,5205,5668,6672,3348,2193,4763,
+6406,6204,5937,5602,4177,5669,3419,6673,4020,6205,4443,4569,5388,3715,3639,6407,
+6049,4058,6206,6674,5938,4544,6050,4185,4294,4841,4651,4615,5488,6207,6408,6051,
+5178,3241,3509,5835,6208,4958,5836,4341,5489,5278,6209,2823,5538,5350,5206,5429,
+6675,4638,4875,4073,3516,4684,4914,4860,5939,5603,5389,6052,5057,3237,5490,3791,
+6676,6409,6677,4821,4915,4106,5351,5058,4243,5539,4244,5604,4842,4916,5239,3028,
+3716,5837,5114,5605,5390,5940,5430,6210,4332,6678,5540,4732,3667,3840,6053,4305,
+3408,5670,5541,6410,2744,5240,5750,6679,3234,5606,6680,5607,5671,3608,4283,4159,
+4400,5352,4783,6681,6411,6682,4491,4802,6211,6412,5941,6413,6414,5542,5751,6683,
+4669,3734,5942,6684,6415,5943,5059,3328,4670,4144,4268,6685,6686,6687,6688,4372,
+3603,6689,5944,5491,4373,3440,6416,5543,4784,4822,5608,3792,4616,5838,5672,3514,
+5391,6417,4892,6690,4639,6691,6054,5673,5839,6055,6692,6056,5392,6212,4038,5544,
+5674,4497,6057,6693,5840,4284,5675,4021,4545,5609,6418,4454,6419,6213,4113,4472,
+5314,3738,5087,5279,4074,5610,4959,4063,3179,4750,6058,6420,6214,3476,4498,4716,
+5431,4960,4685,6215,5241,6694,6421,6216,6695,5841,5945,6422,3748,5946,5179,3905,
+5752,5545,5947,4374,6217,4455,6423,4412,6218,4803,5353,6696,3832,5280,6219,4327,
+4702,6220,6221,6059,4652,5432,6424,3749,4751,6425,5753,4986,5393,4917,5948,5030,
+5754,4861,4733,6426,4703,6697,6222,4671,5949,4546,4961,5180,6223,5031,3316,5281,
+6698,4862,4295,4934,5207,3644,6427,5842,5950,6428,6429,4570,5843,5282,6430,6224,
+5088,3239,6060,6699,5844,5755,6061,6431,2701,5546,6432,5115,5676,4039,3993,3327,
+4752,4425,5315,6433,3941,6434,5677,4617,4604,3074,4581,6225,5433,6435,6226,6062,
+4823,5756,5116,6227,3717,5678,4717,5845,6436,5679,5846,6063,5847,6064,3977,3354,
+6437,3863,5117,6228,5547,5394,4499,4524,6229,4605,6230,4306,4500,6700,5951,6065,
+3693,5952,5089,4366,4918,6701,6231,5548,6232,6702,6438,4704,5434,6703,6704,5953,
+4168,6705,5680,3420,6706,5242,4407,6066,3812,5757,5090,5954,4672,4525,3481,5681,
+4618,5395,5354,5316,5955,6439,4962,6707,4526,6440,3465,4673,6067,6441,5682,6708,
+5435,5492,5758,5683,4619,4571,4674,4804,4893,4686,5493,4753,6233,6068,4269,6442,
+6234,5032,4705,5146,5243,5208,5848,6235,6443,4963,5033,4640,4226,6236,5849,3387,
+6444,6445,4436,4437,5850,4843,5494,4785,4894,6709,4361,6710,5091,5956,3331,6237,
+4987,5549,6069,6711,4342,3517,4473,5317,6070,6712,6071,4706,6446,5017,5355,6713,
+6714,4988,5436,6447,4734,5759,6715,4735,4547,4456,4754,6448,5851,6449,6450,3547,
+5852,5318,6451,6452,5092,4205,6716,6238,4620,4219,5611,6239,6072,4481,5760,5957,
+5958,4059,6240,6453,4227,4537,6241,5761,4030,4186,5244,5209,3761,4457,4876,3337,
+5495,5181,6242,5959,5319,5612,5684,5853,3493,5854,6073,4169,5613,5147,4895,6074,
+5210,6717,5182,6718,3830,6243,2798,3841,6075,6244,5855,5614,3604,4606,5496,5685,
+5118,5356,6719,6454,5960,5357,5961,6720,4145,3935,4621,5119,5962,4261,6721,6455,
+4786,5963,4375,4582,6245,6246,6247,6076,5437,4877,5856,3376,4380,6248,4160,6722,
+5148,6456,5211,6457,6723,4718,6458,6724,6249,5358,4044,3297,6459,6250,5857,5615,
+5497,5245,6460,5498,6725,6251,6252,5550,3793,5499,2959,5396,6461,6462,4572,5093,
+5500,5964,3806,4146,6463,4426,5762,5858,6077,6253,4755,3967,4220,5965,6254,4989,
+5501,6464,4352,6726,6078,4764,2290,5246,3906,5438,5283,3767,4964,2861,5763,5094,
+6255,6256,4622,5616,5859,5860,4707,6727,4285,4708,4824,5617,6257,5551,4787,5212,
+4965,4935,4687,6465,6728,6466,5686,6079,3494,4413,2995,5247,5966,5618,6729,5967,
+5764,5765,5687,5502,6730,6731,6080,5397,6467,4990,6258,6732,4538,5060,5619,6733,
+4719,5688,5439,5018,5149,5284,5503,6734,6081,4607,6259,5120,3645,5861,4583,6260,
+4584,4675,5620,4098,5440,6261,4863,2379,3306,4585,5552,5689,4586,5285,6735,4864,
+6736,5286,6082,6737,4623,3010,4788,4381,4558,5621,4587,4896,3698,3161,5248,4353,
+4045,6262,3754,5183,4588,6738,6263,6739,6740,5622,3936,6741,6468,6742,6264,5095,
+6469,4991,5968,6743,4992,6744,6083,4897,6745,4256,5766,4307,3108,3968,4444,5287,
+3889,4343,6084,4510,6085,4559,6086,4898,5969,6746,5623,5061,4919,5249,5250,5504,
+5441,6265,5320,4878,3242,5862,5251,3428,6087,6747,4237,5624,5442,6266,5553,4539,
+6748,2585,3533,5398,4262,6088,5150,4736,4438,6089,6267,5505,4966,6749,6268,6750,
+6269,5288,5554,3650,6090,6091,4624,6092,5690,6751,5863,4270,5691,4277,5555,5864,
+6752,5692,4720,4865,6470,5151,4688,4825,6753,3094,6754,6471,3235,4653,6755,5213,
+5399,6756,3201,4589,5865,4967,6472,5866,6473,5019,3016,6757,5321,4756,3957,4573,
+6093,4993,5767,4721,6474,6758,5625,6759,4458,6475,6270,6760,5556,4994,5214,5252,
+6271,3875,5768,6094,5034,5506,4376,5769,6761,2120,6476,5253,5770,6762,5771,5970,
+3990,5971,5557,5558,5772,6477,6095,2787,4641,5972,5121,6096,6097,6272,6763,3703,
+5867,5507,6273,4206,6274,4789,6098,6764,3619,3646,3833,3804,2394,3788,4936,3978,
+4866,4899,6099,6100,5559,6478,6765,3599,5868,6101,5869,5870,6275,6766,4527,6767]
+
+end
diff --git a/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/gb2312prober.rb b/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/gb2312prober.rb
new file mode 100644 (file)
index 0000000..edc9a0b
--- /dev/null
@@ -0,0 +1,42 @@
+######################## BEGIN LICENSE BLOCK ########################
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Jeff Hodges - port to Ruby
+#   Mark Pilgrim - port to Python
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+# 
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301  USA
+######################### END LICENSE BLOCK #########################
+
+module CharDet
+  class GB2312Prober < MultiByteCharSetProber
+    def initialize
+      super
+      @_mCodingSM = CodingStateMachine.new(GB2312SMModel)
+      @_mDistributionAnalyzer = GB2312DistributionAnalysis.new()
+      reset()
+    end
+
+    def get_charset_name
+      return "GB2312"
+    end
+  end
+end
diff --git a/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/hebrewprober.rb b/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/hebrewprober.rb
new file mode 100644 (file)
index 0000000..798f6ce
--- /dev/null
@@ -0,0 +1,289 @@
+######################## BEGIN LICENSE BLOCK ########################
+# The Original Code is Mozilla Universal charset detector code.
+#
+# The Initial Developer of the Original Code is
+#          Shy Shalom
+# Portions created by the Initial Developer are Copyright (C) 2005
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Jeff Hodges - port to Ruby
+#   Mark Pilgrim - port to Python
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+# 
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301  USA
+######################### END LICENSE BLOCK #########################
+
+# This prober doesn't actually recognize a language or a charset.
+# It is a helper prober for the use of the Hebrew model probers
+
+### General ideas of the Hebrew charset recognition ###
+#
+# Four main charsets exist in Hebrew:
+# "ISO-8859-8" - Visual Hebrew
+# "windows-1255" - Logical Hebrew 
+# "ISO-8859-8-I" - Logical Hebrew
+# "x-mac-hebrew" - ?? Logical Hebrew ??
+#
+# Both "ISO" charsets use a completely identical set of code points, whereas
+# "windows-1255" and "x-mac-hebrew" are two different proper supersets of 
+# these code points. windows-1255 defines additional characters in the range
+# 0x80-0x9F as some misc punctuation marks as well as some Hebrew-specific 
+# diacritics and additional 'Yiddish' ligature letters in the range 0xc0-0xd6.
+# x-mac-hebrew defines similar additional code points but with a different 
+# mapping.
+#
+# As far as an average Hebrew text with no diacritics is concerned, all four 
+# charsets are identical with respect to code points. Meaning that for the 
+# main Hebrew alphabet, all four map the same values to all 27 Hebrew letters 
+# (including final letters).
+#
+# The dominant difference between these charsets is their directionality.
+# "Visual" directionality means that the text is ordered as if the renderer is
+# not aware of a BIDI rendering algorithm. The renderer sees the text and 
+# draws it from left to right. The text itself when ordered naturally is read 
+# backwards. A buffer of Visual Hebrew generally looks like so:
+# "[last word of first line spelled backwards] [whole line ordered backwards
+# and spelled backwards] [first word of first line spelled backwards] 
+# [end of line] [last word of second line] ... etc' "
+# adding punctuation marks, numbers and English text to visual text is
+# naturally also "visual" and from left to right.
+# 
+# "Logical" directionality means the text is ordered "naturally" according to
+# the order it is read. It is the responsibility of the renderer to display 
+# the text from right to left. A BIDI algorithm is used to place general 
+# punctuation marks, numbers and English text in the text.
+#
+# Texts in x-mac-hebrew are almost impossible to find on the Internet. From 
+# what little evidence I could find, it seems that its general directionality
+# is Logical.
+#
+# To sum up all of the above, the Hebrew probing mechanism knows about two
+# charsets:
+# Visual Hebrew - "ISO-8859-8" - backwards text - Words and sentences are
+#    backwards while line order is natural. For charset recognition purposes
+#    the line order is unimportant (In fact, for this implementation, even 
+#    word order is unimportant).
+# Logical Hebrew - "windows-1255" - normal, naturally ordered text.
+#
+# "ISO-8859-8-I" is a subset of windows-1255 and doesn't need to be 
+#    specifically identified.
+# "x-mac-hebrew" is also identified as windows-1255. A text in x-mac-hebrew
+#    that contain special punctuation marks or diacritics is displayed with
+#    some unconverted characters showing as question marks. This problem might
+#    be corrected using another model prober for x-mac-hebrew. Due to the fact
+#    that x-mac-hebrew texts are so rare, writing another model prober isn't 
+#    worth the effort and performance hit.
+#
+#### The Prober ####
+#
+# The prober is divided between two SBCharSetProbers and a HebrewProber,
+# all of which are managed, created, fed data, inquired and deleted by the
+# SBCSGroupProber. The two SBCharSetProbers identify that the text is in
+# fact some kind of Hebrew, Logical or Visual. The final decision about which
+# one is it is made by the HebrewProber by combining final-letter scores
+# with the scores of the two SBCharSetProbers to produce a final answer.
+#
+# The SBCSGroupProber is responsible for stripping the original text of HTML
+# tags, English characters, numbers, low-ASCII punctuation characters, spaces
+# and new lines. It reduces any sequence of such characters to a single space.
+# The buffer fed to each prober in the SBCS group prober is pure text in
+# high-ASCII.
+# The two SBCharSetProbers (model probers) share the same language model:
+# Win1255Model.
+# The first SBCharSetProber uses the model normally as any other
+# SBCharSetProber does, to recognize windows-1255, upon which this model was
+# built. The second SBCharSetProber is told to make the pair-of-letter
+# lookup in the language model backwards. This in practice exactly simulates
+# a visual Hebrew model using the windows-1255 logical Hebrew model.
+#
+# The HebrewProber is not using any language model. All it does is look for
+# final-letter evidence suggesting the text is either logical Hebrew or visual
+# Hebrew. Disjointed from the model probers, the results of the HebrewProber
+# alone are meaningless. HebrewProber always returns 0.00 as confidence
+# since it never identifies a charset by itself. Instead, the pointer to the
+# HebrewProber is passed to the model probers as a helper "Name Prober".
+# When the Group prober receives a positive identification from any prober,
+# it asks for the name of the charset identified. If the prober queried is a
+# Hebrew model prober, the model prober forwards the call to the
+# HebrewProber to make the final decision. In the HebrewProber, the
+# decision is made according to the final-letters scores maintained and Both
+# model probers scores. The answer is returned in the form of the name of the
+# charset identified, either "windows-1255" or "ISO-8859-8".
+
+# windows-1255 / ISO-8859-8 code points of interest
+module CharDet
+  FINAL_KAF = "\xea"
+  NORMAL_KAF = "\xeb"
+  FINAL_MEM = "\xed"
+  NORMAL_MEM = "\xee"
+  FINAL_NUN = "\xef"
+  NORMAL_NUN = "\xf0"
+  FINAL_PE = "\xf3"
+  NORMAL_PE = "\xf4"
+  FINAL_TSADI = "\xf5"
+  NORMAL_TSADI = "\xf6"
+
+  # Minimum Visual vs Logical final letter score difference.
+  # If the difference is below this, don't rely solely on the final letter score distance.
+  MIN_FINAL_CHAR_DISTANCE = 5
+
+  # Minimum Visual vs Logical model score difference.
+  # If the difference is below this, don't rely at all on the model score distance.
+  MIN_MODEL_DISTANCE = 0.01
+
+  VISUAL_HEBREW_NAME = "ISO-8859-8"
+  LOGICAL_HEBREW_NAME = "windows-1255"
+
+  class HebrewProber < CharSetProber
+    def initialize
+      super()
+      @_mLogicalProber = nil
+      @_mVisualProber = nil
+      reset()
+    end
+
+    def reset
+      @_mFinalCharLogicalScore = 0
+      @_mFinalCharVisualScore = 0
+      # The two last characters seen in the previous buffer,
+      # mPrev and mBeforePrev are initialized to space in order to simulate a word 
+      # delimiter at the beginning of the data
+      @_mPrev = ' '
+      @_mBeforePrev = ' '
+      # These probers are owned by the group prober.
+    end
+
+    def set_model_probers(logicalProber, visualProber)
+      @_mLogicalProber = logicalProber
+      @_mVisualProber = visualProber
+    end
+
+    def is_final(c)
+      return [FINAL_KAF, FINAL_MEM, FINAL_NUN, FINAL_PE, FINAL_TSADI].include?(c)
+    end
+
+    def is_non_final(c)
+      # The normal Tsadi is not a good Non-Final letter due to words like 
+      # 'lechotet' (to chat) containing an apostrophe after the tsadi. This 
+      # apostrophe is converted to a space in FilterWithoutEnglishLetters causing 
+      # the Non-Final tsadi to appear at an end of a word even though this is not 
+      # the case in the original text.
+      # The letters Pe and Kaf rarely display a related behavior of not being a 
+      # good Non-Final letter. Words like 'Pop', 'Winamp' and 'Mubarak' for 
+      # example legally end with a Non-Final Pe or Kaf. However, the benefit of 
+      # these letters as Non-Final letters outweighs the damage since these words 
+      # are quite rare.
+      return [NORMAL_KAF, NORMAL_MEM, NORMAL_NUN, NORMAL_PE].include?(c)
+    end
+
+    def feed(aBuf)
+      # Final letter analysis for logical-visual decision.
+      # Look for evidence that the received buffer is either logical Hebrew or 
+      # visual Hebrew.
+      # The following cases are checked:
+      # 1) A word longer than 1 letter, ending with a final letter. This is an 
+      #    indication that the text is laid out "naturally" since the final letter 
+      #    really appears at the end. +1 for logical score.
+      # 2) A word longer than 1 letter, ending with a Non-Final letter. In normal
+      #    Hebrew, words ending with Kaf, Mem, Nun, Pe or Tsadi, should not end with
+      #    the Non-Final form of that letter. Exceptions to this rule are mentioned
+      #    above in isNonFinal(). This is an indication that the text is laid out
+      #    backwards. +1 for visual score
+      # 3) A word longer than 1 letter, starting with a final letter. Final letters 
+      #    should not appear at the beginning of a word. This is an indication that 
+      #    the text is laid out backwards. +1 for visual score.
+      # 
+      # The visual score and logical score are accumulated throughout the text and 
+      # are finally checked against each other in GetCharSetName().
+      # No checking for final letters in the middle of words is done since that case
+      # is not an indication for either Logical or Visual text.
+      # 
+      # We automatically filter out all 7-bit characters (replace them with spaces)
+      # so the word boundary detection works properly. [MAP]
+
+      if get_state() == ENotMe
+        # Both model probers say it's not them. No reason to continue.
+        return ENotMe
+      end
+
+      aBuf = filter_high_bit_only(aBuf)
+
+      for cur in aBuf.split(' ')
+        if cur == ' '
+          # We stand on a space - a word just ended
+          if @_mBeforePrev != ' '
+            # next-to-last char was not a space so self._mPrev is not a 1 letter word
+            if is_final(@_mPrev)
+              # case (1) [-2:not space][-1:final letter][cur:space]
+              @_mFinalCharLogicalScore += 1
+            elsif is_non_final(@_mPrev)
+              # case (2) [-2:not space][-1:Non-Final letter][cur:space]
+              @_mFinalCharVisualScore += 1
+            end
+          end
+        else
+          # Not standing on a space
+          if (@_mBeforePrev == ' ') and (is_final(@_mPrev)) and (cur != ' ')
+            # case (3) [-2:space][-1:final letter][cur:not space]
+            @_mFinalCharVisualScore += 1
+          end
+        end
+        @_mBeforePrev = @_mPrev
+        @_mPrev = cur
+      end
+
+      # Forever detecting, till the end or until both model probers return eNotMe (handled above)
+      return EDetecting
+    end
+
+    def get_charset_name
+      # Make the decision: is it Logical or Visual?
+      # If the final letter score distance is dominant enough, rely on it.
+      finalsub = @_mFinalCharLogicalScore - @_mFinalCharVisualScore
+      if finalsub >= MIN_FINAL_CHAR_DISTANCE
+        return LOGICAL_HEBREW_NAME
+      end
+      if finalsub <= -MIN_FINAL_CHAR_DISTANCE
+        return VISUAL_HEBREW_NAME
+      end
+
+      # It's not dominant enough, try to rely on the model scores instead.
+      modelsub = @_mLogicalProber.get_confidence() - @_mVisualProber.get_confidence()
+      if modelsub > MIN_MODEL_DISTANCE
+        return LOGICAL_HEBREW_NAME
+      end
+      if modelsub < -MIN_MODEL_DISTANCE
+        return VISUAL_HEBREW_NAME
+      end
+
+      # Still no good, back to final letter distance, maybe it'll save the day.
+      if finalsub < 0.0
+        return VISUAL_HEBREW_NAME
+      end
+
+      # (finalsub > 0 - Logical) or (don't know what to do) default to Logical.
+      return LOGICAL_HEBREW_NAME
+    end
+
+    def get_state
+      # Remain active as long as any of the model probers are active.
+      if (@_mLogicalProber.get_state() == ENotMe) and (@_mVisualProber.get_state() == ENotMe)
+        return ENotMe
+      end
+      return EDetecting
+    end
+  end
+end
diff --git a/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/jisfreq.rb b/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/jisfreq.rb
new file mode 100644 (file)
index 0000000..2245eeb
--- /dev/null
@@ -0,0 +1,570 @@
+######################## BEGIN LICENSE BLOCK ########################
+# The Original Code is Mozilla Communicator client code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Jeff Hodges - port to Ruby
+#   Mark Pilgrim - port to Python
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+# 
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301  USA
+######################### END LICENSE BLOCK #########################
+
+# Sampling from about 20M text materials include literature and computer technology
+#
+# Japanese frequency table, applied to both S-JIS and EUC-JP
+# They are sorted in order. 
+
+# 128  --> 0.77094
+# 256  --> 0.85710
+# 512  --> 0.92635
+# 1024 --> 0.97130
+# 2048 --> 0.99431
+#
+# Ideal Distribution Ratio = 0.92635 / (1-0.92635) = 12.58
+# Random Distribution Ration = 512 / (2965+62+83+86-512) = 0.191
+# 
+# Typical Distribution Ratio, 25% of IDR 
+
+module CharDet
+JIS_TYPICAL_DISTRIBUTION_RATIO = 3.0
+
+# Char to FreqOrder table , 
+JIS_TABLE_SIZE = 4368
+
+JISCharToFreqOrder = [
+  40,   1,   6, 182, 152, 180, 295,2127, 285, 381,3295,4304,3068,4606,3165,3510, #   16
+3511,1822,2785,4607,1193,2226,5070,4608, 171,2996,1247,  18, 179,5071, 856,1661, #   32
+1262,5072, 619, 127,3431,3512,3230,1899,1700, 232, 228,1294,1298, 284, 283,2041, #   48
+2042,1061,1062,  48,  49,  44,  45, 433, 434,1040,1041, 996, 787,2997,1255,4305, #   64
+2108,4609,1684,1648,5073,5074,5075,5076,5077,5078,3687,5079,4610,5080,3927,3928, #   80
+5081,3296,3432, 290,2285,1471,2187,5082,2580,2825,1303,2140,1739,1445,2691,3375, #   96
+1691,3297,4306,4307,4611, 452,3376,1182,2713,3688,3069,4308,5083,5084,5085,5086, #  112
+5087,5088,5089,5090,5091,5092,5093,5094,5095,5096,5097,5098,5099,5100,5101,5102, #  128
+5103,5104,5105,5106,5107,5108,5109,5110,5111,5112,4097,5113,5114,5115,5116,5117, #  144
+5118,5119,5120,5121,5122,5123,5124,5125,5126,5127,5128,5129,5130,5131,5132,5133, #  160
+5134,5135,5136,5137,5138,5139,5140,5141,5142,5143,5144,5145,5146,5147,5148,5149, #  176
+5150,5151,5152,4612,5153,5154,5155,5156,5157,5158,5159,5160,5161,5162,5163,5164, #  192
+5165,5166,5167,5168,5169,5170,5171,5172,5173,5174,5175,1472, 598, 618, 820,1205, #  208
+1309,1412,1858,1307,1692,5176,5177,5178,5179,5180,5181,5182,1142,1452,1234,1172, #  224
+1875,2043,2149,1793,1382,2973, 925,2404,1067,1241, 960,1377,2935,1491, 919,1217, #  240
+1865,2030,1406,1499,2749,4098,5183,5184,5185,5186,5187,5188,2561,4099,3117,1804, #  256
+2049,3689,4309,3513,1663,5189,3166,3118,3298,1587,1561,3433,5190,3119,1625,2998, #  272
+3299,4613,1766,3690,2786,4614,5191,5192,5193,5194,2161,  26,3377,   2,3929,  20, #  288
+3691,  47,4100,  50,  17,  16,  35, 268,  27, 243,  42, 155,  24, 154,  29, 184, #  304
+   4,  91,  14,  92,  53, 396,  33, 289,   9,  37,  64, 620,  21,  39, 321,   5, #  320
+  12,  11,  52,  13,   3, 208, 138,   0,   7,  60, 526, 141, 151,1069, 181, 275, #  336
+1591,  83, 132,1475, 126, 331, 829,  15,  69, 160,  59,  22, 157,  55,1079, 312, #  352
+ 109,  38,  23,  25,  10,  19,  79,5195,  61, 382,1124,   8,  30,5196,5197,5198, #  368
+5199,5200,5201,5202,5203,5204,5205,5206,  89,  62,  74,  34,2416, 112, 139, 196, #  384
+ 271, 149,  84, 607, 131, 765,  46,  88, 153, 683,  76, 874, 101, 258,  57,  80, #  400
+  32, 364, 121,1508, 169,1547,  68, 235, 145,2999,  41, 360,3027,  70,  63,  31, #  416
+  43, 259, 262,1383,  99, 533, 194,  66,  93, 846, 217, 192,  56, 106,  58, 565, #  432
+ 280, 272, 311, 256, 146,  82, 308,  71, 100, 128, 214, 655, 110, 261, 104,1140, #  448
+  54,  51,  36,  87,  67,3070, 185,2618,2936,2020,  28,1066,2390,2059,5207,5208, #  464
+5209,5210,5211,5212,5213,5214,5215,5216,4615,5217,5218,5219,5220,5221,5222,5223, #  480
+5224,5225,5226,5227,5228,5229,5230,5231,5232,5233,5234,5235,5236,3514,5237,5238, #  496
+5239,5240,5241,5242,5243,5244,2297,2031,4616,4310,3692,5245,3071,5246,3598,5247, #  512
+4617,3231,3515,5248,4101,4311,4618,3808,4312,4102,5249,4103,4104,3599,5250,5251, #  528
+5252,5253,5254,5255,5256,5257,5258,5259,5260,5261,5262,5263,5264,5265,5266,5267, #  544
+5268,5269,5270,5271,5272,5273,5274,5275,5276,5277,5278,5279,5280,5281,5282,5283, #  560
+5284,5285,5286,5287,5288,5289,5290,5291,5292,5293,5294,5295,5296,5297,5298,5299, #  576
+5300,5301,5302,5303,5304,5305,5306,5307,5308,5309,5310,5311,5312,5313,5314,5315, #  592
+5316,5317,5318,5319,5320,5321,5322,5323,5324,5325,5326,5327,5328,5329,5330,5331, #  608
+5332,5333,5334,5335,5336,5337,5338,5339,5340,5341,5342,5343,5344,5345,5346,5347, #  624
+5348,5349,5350,5351,5352,5353,5354,5355,5356,5357,5358,5359,5360,5361,5362,5363, #  640
+5364,5365,5366,5367,5368,5369,5370,5371,5372,5373,5374,5375,5376,5377,5378,5379, #  656
+5380,5381, 363, 642,2787,2878,2788,2789,2316,3232,2317,3434,2011, 165,1942,3930, #  672
+3931,3932,3933,5382,4619,5383,4620,5384,5385,5386,5387,5388,5389,5390,5391,5392, #  688
+5393,5394,5395,5396,5397,5398,5399,5400,5401,5402,5403,5404,5405,5406,5407,5408, #  704
+5409,5410,5411,5412,5413,5414,5415,5416,5417,5418,5419,5420,5421,5422,5423,5424, #  720
+5425,5426,5427,5428,5429,5430,5431,5432,5433,5434,5435,5436,5437,5438,5439,5440, #  736
+5441,5442,5443,5444,5445,5446,5447,5448,5449,5450,5451,5452,5453,5454,5455,5456, #  752
+5457,5458,5459,5460,5461,5462,5463,5464,5465,5466,5467,5468,5469,5470,5471,5472, #  768
+5473,5474,5475,5476,5477,5478,5479,5480,5481,5482,5483,5484,5485,5486,5487,5488, #  784
+5489,5490,5491,5492,5493,5494,5495,5496,5497,5498,5499,5500,5501,5502,5503,5504, #  800
+5505,5506,5507,5508,5509,5510,5511,5512,5513,5514,5515,5516,5517,5518,5519,5520, #  816
+5521,5522,5523,5524,5525,5526,5527,5528,5529,5530,5531,5532,5533,5534,5535,5536, #  832
+5537,5538,5539,5540,5541,5542,5543,5544,5545,5546,5547,5548,5549,5550,5551,5552, #  848
+5553,5554,5555,5556,5557,5558,5559,5560,5561,5562,5563,5564,5565,5566,5567,5568, #  864
+5569,5570,5571,5572,5573,5574,5575,5576,5577,5578,5579,5580,5581,5582,5583,5584, #  880
+5585,5586,5587,5588,5589,5590,5591,5592,5593,5594,5595,5596,5597,5598,5599,5600, #  896
+5601,5602,5603,5604,5605,5606,5607,5608,5609,5610,5611,5612,5613,5614,5615,5616, #  912
+5617,5618,5619,5620,5621,5622,5623,5624,5625,5626,5627,5628,5629,5630,5631,5632, #  928
+5633,5634,5635,5636,5637,5638,5639,5640,5641,5642,5643,5644,5645,5646,5647,5648, #  944
+5649,5650,5651,5652,5653,5654,5655,5656,5657,5658,5659,5660,5661,5662,5663,5664, #  960
+5665,5666,5667,5668,5669,5670,5671,5672,5673,5674,5675,5676,5677,5678,5679,5680, #  976
+5681,5682,5683,5684,5685,5686,5687,5688,5689,5690,5691,5692,5693,5694,5695,5696, #  992
+5697,5698,5699,5700,5701,5702,5703,5704,5705,5706,5707,5708,5709,5710,5711,5712, # 1008
+5713,5714,5715,5716,5717,5718,5719,5720,5721,5722,5723,5724,5725,5726,5727,5728, # 1024
+5729,5730,5731,5732,5733,5734,5735,5736,5737,5738,5739,5740,5741,5742,5743,5744, # 1040
+5745,5746,5747,5748,5749,5750,5751,5752,5753,5754,5755,5756,5757,5758,5759,5760, # 1056
+5761,5762,5763,5764,5765,5766,5767,5768,5769,5770,5771,5772,5773,5774,5775,5776, # 1072
+5777,5778,5779,5780,5781,5782,5783,5784,5785,5786,5787,5788,5789,5790,5791,5792, # 1088
+5793,5794,5795,5796,5797,5798,5799,5800,5801,5802,5803,5804,5805,5806,5807,5808, # 1104
+5809,5810,5811,5812,5813,5814,5815,5816,5817,5818,5819,5820,5821,5822,5823,5824, # 1120
+5825,5826,5827,5828,5829,5830,5831,5832,5833,5834,5835,5836,5837,5838,5839,5840, # 1136
+5841,5842,5843,5844,5845,5846,5847,5848,5849,5850,5851,5852,5853,5854,5855,5856, # 1152
+5857,5858,5859,5860,5861,5862,5863,5864,5865,5866,5867,5868,5869,5870,5871,5872, # 1168
+5873,5874,5875,5876,5877,5878,5879,5880,5881,5882,5883,5884,5885,5886,5887,5888, # 1184
+5889,5890,5891,5892,5893,5894,5895,5896,5897,5898,5899,5900,5901,5902,5903,5904, # 1200
+5905,5906,5907,5908,5909,5910,5911,5912,5913,5914,5915,5916,5917,5918,5919,5920, # 1216
+5921,5922,5923,5924,5925,5926,5927,5928,5929,5930,5931,5932,5933,5934,5935,5936, # 1232
+5937,5938,5939,5940,5941,5942,5943,5944,5945,5946,5947,5948,5949,5950,5951,5952, # 1248
+5953,5954,5955,5956,5957,5958,5959,5960,5961,5962,5963,5964,5965,5966,5967,5968, # 1264
+5969,5970,5971,5972,5973,5974,5975,5976,5977,5978,5979,5980,5981,5982,5983,5984, # 1280
+5985,5986,5987,5988,5989,5990,5991,5992,5993,5994,5995,5996,5997,5998,5999,6000, # 1296
+6001,6002,6003,6004,6005,6006,6007,6008,6009,6010,6011,6012,6013,6014,6015,6016, # 1312
+6017,6018,6019,6020,6021,6022,6023,6024,6025,6026,6027,6028,6029,6030,6031,6032, # 1328
+6033,6034,6035,6036,6037,6038,6039,6040,6041,6042,6043,6044,6045,6046,6047,6048, # 1344
+6049,6050,6051,6052,6053,6054,6055,6056,6057,6058,6059,6060,6061,6062,6063,6064, # 1360
+6065,6066,6067,6068,6069,6070,6071,6072,6073,6074,6075,6076,6077,6078,6079,6080, # 1376
+6081,6082,6083,6084,6085,6086,6087,6088,6089,6090,6091,6092,6093,6094,6095,6096, # 1392
+6097,6098,6099,6100,6101,6102,6103,6104,6105,6106,6107,6108,6109,6110,6111,6112, # 1408
+6113,6114,2044,2060,4621, 997,1235, 473,1186,4622, 920,3378,6115,6116, 379,1108, # 1424
+4313,2657,2735,3934,6117,3809, 636,3233, 573,1026,3693,3435,2974,3300,2298,4105, # 1440
+ 854,2937,2463, 393,2581,2417, 539, 752,1280,2750,2480, 140,1161, 440, 708,1569, # 1456
+ 665,2497,1746,1291,1523,3000, 164,1603, 847,1331, 537,1997, 486, 508,1693,2418, # 1472
+1970,2227, 878,1220, 299,1030, 969, 652,2751, 624,1137,3301,2619,  65,3302,2045, # 1488
+1761,1859,3120,1930,3694,3516, 663,1767, 852, 835,3695, 269, 767,2826,2339,1305, # 1504
+ 896,1150, 770,1616,6118, 506,1502,2075,1012,2519, 775,2520,2975,2340,2938,4314, # 1520
+3028,2086,1224,1943,2286,6119,3072,4315,2240,1273,1987,3935,1557, 175, 597, 985, # 1536
+3517,2419,2521,1416,3029, 585, 938,1931,1007,1052,1932,1685,6120,3379,4316,4623, # 1552
+ 804, 599,3121,1333,2128,2539,1159,1554,2032,3810, 687,2033,2904, 952, 675,1467, # 1568
+3436,6121,2241,1096,1786,2440,1543,1924, 980,1813,2228, 781,2692,1879, 728,1918, # 1584
+3696,4624, 548,1950,4625,1809,1088,1356,3303,2522,1944, 502, 972, 373, 513,2827, # 1600
+ 586,2377,2391,1003,1976,1631,6122,2464,1084, 648,1776,4626,2141, 324, 962,2012, # 1616
+2177,2076,1384, 742,2178,1448,1173,1810, 222, 102, 301, 445, 125,2420, 662,2498, # 1632
+ 277, 200,1476,1165,1068, 224,2562,1378,1446, 450,1880, 659, 791, 582,4627,2939, # 1648
+3936,1516,1274, 555,2099,3697,1020,1389,1526,3380,1762,1723,1787,2229, 412,2114, # 1664
+1900,2392,3518, 512,2597, 427,1925,2341,3122,1653,1686,2465,2499, 697, 330, 273, # 1680
+ 380,2162, 951, 832, 780, 991,1301,3073, 965,2270,3519, 668,2523,2636,1286, 535, # 1696
+1407, 518, 671, 957,2658,2378, 267, 611,2197,3030,6123, 248,2299, 967,1799,2356, # 1712
+ 850,1418,3437,1876,1256,1480,2828,1718,6124,6125,1755,1664,2405,6126,4628,2879, # 1728
+2829, 499,2179, 676,4629, 557,2329,2214,2090, 325,3234, 464, 811,3001, 992,2342, # 1744
+2481,1232,1469, 303,2242, 466,1070,2163, 603,1777,2091,4630,2752,4631,2714, 322, # 1760
+2659,1964,1768, 481,2188,1463,2330,2857,3600,2092,3031,2421,4632,2318,2070,1849, # 1776
+2598,4633,1302,2254,1668,1701,2422,3811,2905,3032,3123,2046,4106,1763,1694,4634, # 1792
+1604, 943,1724,1454, 917, 868,2215,1169,2940, 552,1145,1800,1228,1823,1955, 316, # 1808
+1080,2510, 361,1807,2830,4107,2660,3381,1346,1423,1134,4108,6127, 541,1263,1229, # 1824
+1148,2540, 545, 465,1833,2880,3438,1901,3074,2482, 816,3937, 713,1788,2500, 122, # 1840
+1575, 195,1451,2501,1111,6128, 859, 374,1225,2243,2483,4317, 390,1033,3439,3075, # 1856
+2524,1687, 266, 793,1440,2599, 946, 779, 802, 507, 897,1081, 528,2189,1292, 711, # 1872
+1866,1725,1167,1640, 753, 398,2661,1053, 246, 348,4318, 137,1024,3440,1600,2077, # 1888
+2129, 825,4319, 698, 238, 521, 187,2300,1157,2423,1641,1605,1464,1610,1097,2541, # 1904
+1260,1436, 759,2255,1814,2150, 705,3235, 409,2563,3304, 561,3033,2005,2564, 726, # 1920
+1956,2343,3698,4109, 949,3812,3813,3520,1669, 653,1379,2525, 881,2198, 632,2256, # 1936
+1027, 778,1074, 733,1957, 514,1481,2466, 554,2180, 702,3938,1606,1017,1398,6129, # 1952
+1380,3521, 921, 993,1313, 594, 449,1489,1617,1166, 768,1426,1360, 495,1794,3601, # 1968
+1177,3602,1170,4320,2344, 476, 425,3167,4635,3168,1424, 401,2662,1171,3382,1998, # 1984
+1089,4110, 477,3169, 474,6130,1909, 596,2831,1842, 494, 693,1051,1028,1207,3076, # 2000
+ 606,2115, 727,2790,1473,1115, 743,3522, 630, 805,1532,4321,2021, 366,1057, 838, # 2016
+ 684,1114,2142,4322,2050,1492,1892,1808,2271,3814,2424,1971,1447,1373,3305,1090, # 2032
+1536,3939,3523,3306,1455,2199, 336, 369,2331,1035, 584,2393, 902, 718,2600,6131, # 2048
+2753, 463,2151,1149,1611,2467, 715,1308,3124,1268, 343,1413,3236,1517,1347,2663, # 2064
+2093,3940,2022,1131,1553,2100,2941,1427,3441,2942,1323,2484,6132,1980, 872,2368, # 2080
+2441,2943, 320,2369,2116,1082, 679,1933,3941,2791,3815, 625,1143,2023, 422,2200, # 2096
+3816,6133, 730,1695, 356,2257,1626,2301,2858,2637,1627,1778, 937, 883,2906,2693, # 2112
+3002,1769,1086, 400,1063,1325,3307,2792,4111,3077, 456,2345,1046, 747,6134,1524, # 2128
+ 884,1094,3383,1474,2164,1059, 974,1688,2181,2258,1047, 345,1665,1187, 358, 875, # 2144
+3170, 305, 660,3524,2190,1334,1135,3171,1540,1649,2542,1527, 927, 968,2793, 885, # 2160
+1972,1850, 482, 500,2638,1218,1109,1085,2543,1654,2034, 876,  78,2287,1482,1277, # 2176
+ 861,1675,1083,1779, 724,2754, 454, 397,1132,1612,2332, 893, 672,1237, 257,2259, # 2192
+2370, 135,3384, 337,2244, 547, 352, 340, 709,2485,1400, 788,1138,2511, 540, 772, # 2208
+1682,2260,2272,2544,2013,1843,1902,4636,1999,1562,2288,4637,2201,1403,1533, 407, # 2224
+ 576,3308,1254,2071, 978,3385, 170, 136,1201,3125,2664,3172,2394, 213, 912, 873, # 2240
+3603,1713,2202, 699,3604,3699, 813,3442, 493, 531,1054, 468,2907,1483, 304, 281, # 2256
+4112,1726,1252,2094, 339,2319,2130,2639, 756,1563,2944, 748, 571,2976,1588,2425, # 2272
+2715,1851,1460,2426,1528,1392,1973,3237, 288,3309, 685,3386, 296, 892,2716,2216, # 2288
+1570,2245, 722,1747,2217, 905,3238,1103,6135,1893,1441,1965, 251,1805,2371,3700, # 2304
+2601,1919,1078,  75,2182,1509,1592,1270,2640,4638,2152,6136,3310,3817, 524, 706, # 2320
+1075, 292,3818,1756,2602, 317,  98,3173,3605,3525,1844,2218,3819,2502, 814, 567, # 2336
+ 385,2908,1534,6137, 534,1642,3239, 797,6138,1670,1529, 953,4323, 188,1071, 538, # 2352
+ 178, 729,3240,2109,1226,1374,2000,2357,2977, 731,2468,1116,2014,2051,6139,1261, # 2368
+1593, 803,2859,2736,3443, 556, 682, 823,1541,6140,1369,2289,1706,2794, 845, 462, # 2384
+2603,2665,1361, 387, 162,2358,1740, 739,1770,1720,1304,1401,3241,1049, 627,1571, # 2400
+2427,3526,1877,3942,1852,1500, 431,1910,1503, 677, 297,2795, 286,1433,1038,1198, # 2416
+2290,1133,1596,4113,4639,2469,1510,1484,3943,6141,2442, 108, 712,4640,2372, 866, # 2432
+3701,2755,3242,1348, 834,1945,1408,3527,2395,3243,1811, 824, 994,1179,2110,1548, # 2448
+1453, 790,3003, 690,4324,4325,2832,2909,3820,1860,3821, 225,1748, 310, 346,1780, # 2464
+2470, 821,1993,2717,2796, 828, 877,3528,2860,2471,1702,2165,2910,2486,1789, 453, # 2480
+ 359,2291,1676,  73,1164,1461,1127,3311, 421, 604, 314,1037, 589, 116,2487, 737, # 2496
+ 837,1180, 111, 244, 735,6142,2261,1861,1362, 986, 523, 418, 581,2666,3822, 103, # 2512
+ 855, 503,1414,1867,2488,1091, 657,1597, 979, 605,1316,4641,1021,2443,2078,2001, # 2528
+1209,  96, 587,2166,1032, 260,1072,2153, 173,  94, 226,3244, 819,2006,4642,4114, # 2544
+2203, 231,1744, 782,  97,2667, 786,3387, 887, 391, 442,2219,4326,1425,6143,2694, # 2560
+ 633,1544,1202, 483,2015, 592,2052,1958,2472,1655, 419, 129,4327,3444,3312,1714, # 2576
+1257,3078,4328,1518,1098, 865,1310,1019,1885,1512,1734, 469,2444, 148, 773, 436, # 2592
+1815,1868,1128,1055,4329,1245,2756,3445,2154,1934,1039,4643, 579,1238, 932,2320, # 2608
+ 353, 205, 801, 115,2428, 944,2321,1881, 399,2565,1211, 678, 766,3944, 335,2101, # 2624
+1459,1781,1402,3945,2737,2131,1010, 844, 981,1326,1013, 550,1816,1545,2620,1335, # 2640
+1008, 371,2881, 936,1419,1613,3529,1456,1395,2273,1834,2604,1317,2738,2503, 416, # 2656
+1643,4330, 806,1126, 229, 591,3946,1314,1981,1576,1837,1666, 347,1790, 977,3313, # 2672
+ 764,2861,1853, 688,2429,1920,1462,  77, 595, 415,2002,3034, 798,1192,4115,6144, # 2688
+2978,4331,3035,2695,2582,2072,2566, 430,2430,1727, 842,1396,3947,3702, 613, 377, # 2704
+ 278, 236,1417,3388,3314,3174, 757,1869, 107,3530,6145,1194, 623,2262, 207,1253, # 2720
+2167,3446,3948, 492,1117,1935, 536,1838,2757,1246,4332, 696,2095,2406,1393,1572, # 2736
+3175,1782, 583, 190, 253,1390,2230, 830,3126,3389, 934,3245,1703,1749,2979,1870, # 2752
+2545,1656,2204, 869,2346,4116,3176,1817, 496,1764,4644, 942,1504, 404,1903,1122, # 2768
+1580,3606,2945,1022, 515, 372,1735, 955,2431,3036,6146,2797,1110,2302,2798, 617, # 2784
+6147, 441, 762,1771,3447,3607,3608,1904, 840,3037,  86, 939,1385, 572,1370,2445, # 2800
+1336, 114,3703, 898, 294, 203,3315, 703,1583,2274, 429, 961,4333,1854,1951,3390, # 2816
+2373,3704,4334,1318,1381, 966,1911,2322,1006,1155, 309, 989, 458,2718,1795,1372, # 2832
+1203, 252,1689,1363,3177, 517,1936, 168,1490, 562, 193,3823,1042,4117,1835, 551, # 2848
+ 470,4645, 395, 489,3448,1871,1465,2583,2641, 417,1493, 279,1295, 511,1236,1119, # 2864
+  72,1231,1982,1812,3004, 871,1564, 984,3449,1667,2696,2096,4646,2347,2833,1673, # 2880
+3609, 695,3246,2668, 807,1183,4647, 890, 388,2333,1801,1457,2911,1765,1477,1031, # 2896
+3316,3317,1278,3391,2799,2292,2526, 163,3450,4335,2669,1404,1802,6148,2323,2407, # 2912
+1584,1728,1494,1824,1269, 298, 909,3318,1034,1632, 375, 776,1683,2061, 291, 210, # 2928
+1123, 809,1249,1002,2642,3038, 206,1011,2132, 144, 975, 882,1565, 342, 667, 754, # 2944
+1442,2143,1299,2303,2062, 447, 626,2205,1221,2739,2912,1144,1214,2206,2584, 760, # 2960
+1715, 614, 950,1281,2670,2621, 810, 577,1287,2546,4648, 242,2168, 250,2643, 691, # 2976
+ 123,2644, 647, 313,1029, 689,1357,2946,1650, 216, 771,1339,1306, 808,2063, 549, # 2992
+ 913,1371,2913,2914,6149,1466,1092,1174,1196,1311,2605,2396,1783,1796,3079, 406, # 3008
+2671,2117,3949,4649, 487,1825,2220,6150,2915, 448,2348,1073,6151,2397,1707, 130, # 3024
+ 900,1598, 329, 176,1959,2527,1620,6152,2275,4336,3319,1983,2191,3705,3610,2155, # 3040
+3706,1912,1513,1614,6153,1988, 646, 392,2304,1589,3320,3039,1826,1239,1352,1340, # 3056
+2916, 505,2567,1709,1437,2408,2547, 906,6154,2672, 384,1458,1594,1100,1329, 710, # 3072
+ 423,3531,2064,2231,2622,1989,2673,1087,1882, 333, 841,3005,1296,2882,2379, 580, # 3088
+1937,1827,1293,2585, 601, 574, 249,1772,4118,2079,1120, 645, 901,1176,1690, 795, # 3104
+2207, 478,1434, 516,1190,1530, 761,2080, 930,1264, 355, 435,1552, 644,1791, 987, # 3120
+ 220,1364,1163,1121,1538, 306,2169,1327,1222, 546,2645, 218, 241, 610,1704,3321, # 3136
+1984,1839,1966,2528, 451,6155,2586,3707,2568, 907,3178, 254,2947, 186,1845,4650, # 3152
+ 745, 432,1757, 428,1633, 888,2246,2221,2489,3611,2118,1258,1265, 956,3127,1784, # 3168
+4337,2490, 319, 510, 119, 457,3612, 274,2035,2007,4651,1409,3128, 970,2758, 590, # 3184
+2800, 661,2247,4652,2008,3950,1420,1549,3080,3322,3951,1651,1375,2111, 485,2491, # 3200
+1429,1156,6156,2548,2183,1495, 831,1840,2529,2446, 501,1657, 307,1894,3247,1341, # 3216
+ 666, 899,2156,1539,2549,1559, 886, 349,2208,3081,2305,1736,3824,2170,2759,1014, # 3232
+1913,1386, 542,1397,2948, 490, 368, 716, 362, 159, 282,2569,1129,1658,1288,1750, # 3248
+2674, 276, 649,2016, 751,1496, 658,1818,1284,1862,2209,2087,2512,3451, 622,2834, # 3264
+ 376, 117,1060,2053,1208,1721,1101,1443, 247,1250,3179,1792,3952,2760,2398,3953, # 3280
+6157,2144,3708, 446,2432,1151,2570,3452,2447,2761,2835,1210,2448,3082, 424,2222, # 3296
+1251,2449,2119,2836, 504,1581,4338, 602, 817, 857,3825,2349,2306, 357,3826,1470, # 3312
+1883,2883, 255, 958, 929,2917,3248, 302,4653,1050,1271,1751,2307,1952,1430,2697, # 3328
+2719,2359, 354,3180, 777, 158,2036,4339,1659,4340,4654,2308,2949,2248,1146,2232, # 3344
+3532,2720,1696,2623,3827,6158,3129,1550,2698,1485,1297,1428, 637, 931,2721,2145, # 3360
+ 914,2550,2587,  81,2450, 612, 827,2646,1242,4655,1118,2884, 472,1855,3181,3533, # 3376
+3534, 569,1353,2699,1244,1758,2588,4119,2009,2762,2171,3709,1312,1531,6159,1152, # 3392
+1938, 134,1830, 471,3710,2276,1112,1535,3323,3453,3535, 982,1337,2950, 488, 826, # 3408
+ 674,1058,1628,4120,2017, 522,2399, 211, 568,1367,3454, 350, 293,1872,1139,3249, # 3424
+1399,1946,3006,1300,2360,3324, 588, 736,6160,2606, 744, 669,3536,3828,6161,1358, # 3440
+ 199, 723, 848, 933, 851,1939,1505,1514,1338,1618,1831,4656,1634,3613, 443,2740, # 3456
+3829, 717,1947, 491,1914,6162,2551,1542,4121,1025,6163,1099,1223, 198,3040,2722, # 3472
+ 370, 410,1905,2589, 998,1248,3182,2380, 519,1449,4122,1710, 947, 928,1153,4341, # 3488
+2277, 344,2624,1511, 615, 105, 161,1212,1076,1960,3130,2054,1926,1175,1906,2473, # 3504
+ 414,1873,2801,6164,2309, 315,1319,3325, 318,2018,2146,2157, 963, 631, 223,4342, # 3520
+4343,2675, 479,3711,1197,2625,3712,2676,2361,6165,4344,4123,6166,2451,3183,1886, # 3536
+2184,1674,1330,1711,1635,1506, 799, 219,3250,3083,3954,1677,3713,3326,2081,3614, # 3552
+1652,2073,4657,1147,3041,1752, 643,1961, 147,1974,3955,6167,1716,2037, 918,3007, # 3568
+1994, 120,1537, 118, 609,3184,4345, 740,3455,1219, 332,1615,3830,6168,1621,2980, # 3584
+1582, 783, 212, 553,2350,3714,1349,2433,2082,4124, 889,6169,2310,1275,1410, 973, # 3600
+ 166,1320,3456,1797,1215,3185,2885,1846,2590,2763,4658, 629, 822,3008, 763, 940, # 3616
+1990,2862, 439,2409,1566,1240,1622, 926,1282,1907,2764, 654,2210,1607, 327,1130, # 3632
+3956,1678,1623,6170,2434,2192, 686, 608,3831,3715, 903,3957,3042,6171,2741,1522, # 3648
+1915,1105,1555,2552,1359, 323,3251,4346,3457, 738,1354,2553,2311,2334,1828,2003, # 3664
+3832,1753,2351,1227,6172,1887,4125,1478,6173,2410,1874,1712,1847, 520,1204,2607, # 3680
+ 264,4659, 836,2677,2102, 600,4660,3833,2278,3084,6174,4347,3615,1342, 640, 532, # 3696
+ 543,2608,1888,2400,2591,1009,4348,1497, 341,1737,3616,2723,1394, 529,3252,1321, # 3712
+ 983,4661,1515,2120, 971,2592, 924, 287,1662,3186,4349,2700,4350,1519, 908,1948, # 3728
+2452, 156, 796,1629,1486,2223,2055, 694,4126,1259,1036,3392,1213,2249,2742,1889, # 3744
+1230,3958,1015, 910, 408, 559,3617,4662, 746, 725, 935,4663,3959,3009,1289, 563, # 3760
+ 867,4664,3960,1567,2981,2038,2626, 988,2263,2381,4351, 143,2374, 704,1895,6175, # 3776
+1188,3716,2088, 673,3085,2362,4352, 484,1608,1921,2765,2918, 215, 904,3618,3537, # 3792
+ 894, 509, 976,3043,2701,3961,4353,2837,2982, 498,6176,6177,1102,3538,1332,3393, # 3808
+1487,1636,1637, 233, 245,3962, 383, 650, 995,3044, 460,1520,1206,2352, 749,3327, # 3824
+ 530, 700, 389,1438,1560,1773,3963,2264, 719,2951,2724,3834, 870,1832,1644,1000, # 3840
+ 839,2474,3717, 197,1630,3394, 365,2886,3964,1285,2133, 734, 922, 818,1106, 732, # 3856
+ 480,2083,1774,3458, 923,2279,1350, 221,3086,  85,2233,2234,3835,1585,3010,2147, # 3872
+1387,1705,2382,1619,2475, 133, 239,2802,1991,1016,2084,2383, 411,2838,1113, 651, # 3888
+1985,1160,3328, 990,1863,3087,1048,1276,2647, 265,2627,1599,3253,2056, 150, 638, # 3904
+2019, 656, 853, 326,1479, 680,1439,4354,1001,1759, 413,3459,3395,2492,1431, 459, # 3920
+4355,1125,3329,2265,1953,1450,2065,2863, 849, 351,2678,3131,3254,3255,1104,1577, # 3936
+ 227,1351,1645,2453,2193,1421,2887, 812,2121, 634,  95,2435, 201,2312,4665,1646, # 3952
+1671,2743,1601,2554,2702,2648,2280,1315,1366,2089,3132,1573,3718,3965,1729,1189, # 3968
+ 328,2679,1077,1940,1136, 558,1283, 964,1195, 621,2074,1199,1743,3460,3619,1896, # 3984
+1916,1890,3836,2952,1154,2112,1064, 862, 378,3011,2066,2113,2803,1568,2839,6178, # 4000
+3088,2919,1941,1660,2004,1992,2194, 142, 707,1590,1708,1624,1922,1023,1836,1233, # 4016
+1004,2313, 789, 741,3620,6179,1609,2411,1200,4127,3719,3720,4666,2057,3721, 593, # 4032
+2840, 367,2920,1878,6180,3461,1521, 628,1168, 692,2211,2649, 300, 720,2067,2571, # 4048
+2953,3396, 959,2504,3966,3539,3462,1977, 701,6181, 954,1043, 800, 681, 183,3722, # 4064
+1803,1730,3540,4128,2103, 815,2314, 174, 467, 230,2454,1093,2134, 755,3541,3397, # 4080
+1141,1162,6182,1738,2039, 270,3256,2513,1005,1647,2185,3837, 858,1679,1897,1719, # 4096
+2954,2324,1806, 402, 670, 167,4129,1498,2158,2104, 750,6183, 915, 189,1680,1551, # 4112
+ 455,4356,1501,2455, 405,1095,2955, 338,1586,1266,1819, 570, 641,1324, 237,1556, # 4128
+2650,1388,3723,6184,1368,2384,1343,1978,3089,2436, 879,3724, 792,1191, 758,3012, # 4144
+1411,2135,1322,4357, 240,4667,1848,3725,1574,6185, 420,3045,1546,1391, 714,4358, # 4160
+1967, 941,1864, 863, 664, 426, 560,1731,2680,1785,2864,1949,2363, 403,3330,1415, # 4176
+1279,2136,1697,2335, 204, 721,2097,3838,  90,6186,2085,2505, 191,3967, 124,2148, # 4192
+1376,1798,1178,1107,1898,1405, 860,4359,1243,1272,2375,2983,1558,2456,1638, 113, # 4208
+3621, 578,1923,2609, 880, 386,4130, 784,2186,2266,1422,2956,2172,1722, 497, 263, # 4224
+2514,1267,2412,2610, 177,2703,3542, 774,1927,1344, 616,1432,1595,1018, 172,4360, # 4240
+2325, 911,4361, 438,1468,3622, 794,3968,2024,2173,1681,1829,2957, 945, 895,3090, # 4256
+ 575,2212,2476, 475,2401,2681, 785,2744,1745,2293,2555,1975,3133,2865, 394,4668, # 4272
+3839, 635,4131, 639, 202,1507,2195,2766,1345,1435,2572,3726,1908,1184,1181,2457, # 4288
+3727,3134,4362, 843,2611, 437, 916,4669, 234, 769,1884,3046,3047,3623, 833,6187, # 4304
+1639,2250,2402,1355,1185,2010,2047, 999, 525,1732,1290,1488,2612, 948,1578,3728, # 4320
+2413,2477,1216,2725,2159, 334,3840,1328,3624,2921,1525,4132, 564,1056, 891,4363, # 4336
+1444,1698,2385,2251,3729,1365,2281,2235,1717,6188, 864,3841,2515, 444, 527,2767, # 4352
+2922,3625, 544, 461,6189, 566, 209,2437,3398,2098,1065,2068,3331,3626,3257,2137, # 4368  #last 512
+#Everything below is of no interest for detection purpose
+2138,2122,3730,2888,1995,1820,1044,6190,6191,6192,6193,6194,6195,6196,6197,6198, # 4384
+6199,6200,6201,6202,6203,6204,6205,4670,6206,6207,6208,6209,6210,6211,6212,6213, # 4400
+6214,6215,6216,6217,6218,6219,6220,6221,6222,6223,6224,6225,6226,6227,6228,6229, # 4416
+6230,6231,6232,6233,6234,6235,6236,6237,3187,6238,6239,3969,6240,6241,6242,6243, # 4432
+6244,4671,6245,6246,4672,6247,6248,4133,6249,6250,4364,6251,2923,2556,2613,4673, # 4448
+4365,3970,6252,6253,6254,6255,4674,6256,6257,6258,2768,2353,4366,4675,4676,3188, # 4464
+4367,3463,6259,4134,4677,4678,6260,2267,6261,3842,3332,4368,3543,6262,6263,6264, # 4480
+3013,1954,1928,4135,4679,6265,6266,2478,3091,6267,4680,4369,6268,6269,1699,6270, # 4496
+3544,4136,4681,6271,4137,6272,4370,2804,6273,6274,2593,3971,3972,4682,6275,2236, # 4512
+4683,6276,6277,4684,6278,6279,4138,3973,4685,6280,6281,3258,6282,6283,6284,6285, # 4528
+3974,4686,2841,3975,6286,6287,3545,6288,6289,4139,4687,4140,6290,4141,6291,4142, # 4544
+6292,6293,3333,6294,6295,6296,4371,6297,3399,6298,6299,4372,3976,6300,6301,6302, # 4560
+4373,6303,6304,3843,3731,6305,4688,4374,6306,6307,3259,2294,6308,3732,2530,4143, # 4576
+6309,4689,6310,6311,6312,3048,6313,6314,4690,3733,2237,6315,6316,2282,3334,6317, # 4592
+6318,3844,6319,6320,4691,6321,3400,4692,6322,4693,6323,3049,6324,4375,6325,3977, # 4608
+6326,6327,6328,3546,6329,4694,3335,6330,4695,4696,6331,6332,6333,6334,4376,3978, # 4624
+6335,4697,3979,4144,6336,3980,4698,6337,6338,6339,6340,6341,4699,4700,4701,6342, # 4640
+6343,4702,6344,6345,4703,6346,6347,4704,6348,4705,4706,3135,6349,4707,6350,4708, # 4656
+6351,4377,6352,4709,3734,4145,6353,2506,4710,3189,6354,3050,4711,3981,6355,3547, # 4672
+3014,4146,4378,3735,2651,3845,3260,3136,2224,1986,6356,3401,6357,4712,2594,3627, # 4688
+3137,2573,3736,3982,4713,3628,4714,4715,2682,3629,4716,6358,3630,4379,3631,6359, # 4704
+6360,6361,3983,6362,6363,6364,6365,4147,3846,4717,6366,6367,3737,2842,6368,4718, # 4720
+2628,6369,3261,6370,2386,6371,6372,3738,3984,4719,3464,4720,3402,6373,2924,3336, # 4736
+4148,2866,6374,2805,3262,4380,2704,2069,2531,3138,2806,2984,6375,2769,6376,4721, # 4752
+4722,3403,6377,6378,3548,6379,6380,2705,3092,1979,4149,2629,3337,2889,6381,3338, # 4768
+4150,2557,3339,4381,6382,3190,3263,3739,6383,4151,4723,4152,2558,2574,3404,3191, # 4784
+6384,6385,4153,6386,4724,4382,6387,6388,4383,6389,6390,4154,6391,4725,3985,6392, # 4800
+3847,4155,6393,6394,6395,6396,6397,3465,6398,4384,6399,6400,6401,6402,6403,6404, # 4816
+4156,6405,6406,6407,6408,2123,6409,6410,2326,3192,4726,6411,6412,6413,6414,4385, # 4832
+4157,6415,6416,4158,6417,3093,3848,6418,3986,6419,6420,3849,6421,6422,6423,4159, # 4848
+6424,6425,4160,6426,3740,6427,6428,6429,6430,3987,6431,4727,6432,2238,6433,6434, # 4864
+4386,3988,6435,6436,3632,6437,6438,2843,6439,6440,6441,6442,3633,6443,2958,6444, # 4880
+6445,3466,6446,2364,4387,3850,6447,4388,2959,3340,6448,3851,6449,4728,6450,6451, # 4896
+3264,4729,6452,3193,6453,4389,4390,2706,3341,4730,6454,3139,6455,3194,6456,3051, # 4912
+2124,3852,1602,4391,4161,3853,1158,3854,4162,3989,4392,3990,4731,4732,4393,2040, # 4928
+4163,4394,3265,6457,2807,3467,3855,6458,6459,6460,3991,3468,4733,4734,6461,3140, # 4944
+2960,6462,4735,6463,6464,6465,6466,4736,4737,4738,4739,6467,6468,4164,2403,3856, # 4960
+6469,6470,2770,2844,6471,4740,6472,6473,6474,6475,6476,6477,6478,3195,6479,4741, # 4976
+4395,6480,2867,6481,4742,2808,6482,2493,4165,6483,6484,6485,6486,2295,4743,6487, # 4992
+6488,6489,3634,6490,6491,6492,6493,6494,6495,6496,2985,4744,6497,6498,4745,6499, # 5008
+6500,2925,3141,4166,6501,6502,4746,6503,6504,4747,6505,6506,6507,2890,6508,6509, # 5024
+6510,6511,6512,6513,6514,6515,6516,6517,6518,6519,3469,4167,6520,6521,6522,4748, # 5040
+4396,3741,4397,4749,4398,3342,2125,4750,6523,4751,4752,4753,3052,6524,2961,4168, # 5056
+6525,4754,6526,4755,4399,2926,4169,6527,3857,6528,4400,4170,6529,4171,6530,6531, # 5072
+2595,6532,6533,6534,6535,3635,6536,6537,6538,6539,6540,6541,6542,4756,6543,6544, # 5088
+6545,6546,6547,6548,4401,6549,6550,6551,6552,4402,3405,4757,4403,6553,6554,6555, # 5104
+4172,3742,6556,6557,6558,3992,3636,6559,6560,3053,2726,6561,3549,4173,3054,4404, # 5120
+6562,6563,3993,4405,3266,3550,2809,4406,6564,6565,6566,4758,4759,6567,3743,6568, # 5136
+4760,3744,4761,3470,6569,6570,6571,4407,6572,3745,4174,6573,4175,2810,4176,3196, # 5152
+4762,6574,4177,6575,6576,2494,2891,3551,6577,6578,3471,6579,4408,6580,3015,3197, # 5168
+6581,3343,2532,3994,3858,6582,3094,3406,4409,6583,2892,4178,4763,4410,3016,4411, # 5184
+6584,3995,3142,3017,2683,6585,4179,6586,6587,4764,4412,6588,6589,4413,6590,2986, # 5200
+6591,2962,3552,6592,2963,3472,6593,6594,4180,4765,6595,6596,2225,3267,4414,6597, # 5216
+3407,3637,4766,6598,6599,3198,6600,4415,6601,3859,3199,6602,3473,4767,2811,4416, # 5232
+1856,3268,3200,2575,3996,3997,3201,4417,6603,3095,2927,6604,3143,6605,2268,6606, # 5248
+3998,3860,3096,2771,6607,6608,3638,2495,4768,6609,3861,6610,3269,2745,4769,4181, # 5264
+3553,6611,2845,3270,6612,6613,6614,3862,6615,6616,4770,4771,6617,3474,3999,4418, # 5280
+4419,6618,3639,3344,6619,4772,4182,6620,2126,6621,6622,6623,4420,4773,6624,3018, # 5296
+6625,4774,3554,6626,4183,2025,3746,6627,4184,2707,6628,4421,4422,3097,1775,4185, # 5312
+3555,6629,6630,2868,6631,6632,4423,6633,6634,4424,2414,2533,2928,6635,4186,2387, # 5328
+6636,4775,6637,4187,6638,1891,4425,3202,3203,6639,6640,4776,6641,3345,6642,6643, # 5344
+3640,6644,3475,3346,3641,4000,6645,3144,6646,3098,2812,4188,3642,3204,6647,3863, # 5360
+3476,6648,3864,6649,4426,4001,6650,6651,6652,2576,6653,4189,4777,6654,6655,6656, # 5376
+2846,6657,3477,3205,4002,6658,4003,6659,3347,2252,6660,6661,6662,4778,6663,6664, # 5392
+6665,6666,6667,6668,6669,4779,4780,2048,6670,3478,3099,6671,3556,3747,4004,6672, # 5408
+6673,6674,3145,4005,3748,6675,6676,6677,6678,6679,3408,6680,6681,6682,6683,3206, # 5424
+3207,6684,6685,4781,4427,6686,4782,4783,4784,6687,6688,6689,4190,6690,6691,3479, # 5440
+6692,2746,6693,4428,6694,6695,6696,6697,6698,6699,4785,6700,6701,3208,2727,6702, # 5456
+3146,6703,6704,3409,2196,6705,4429,6706,6707,6708,2534,1996,6709,6710,6711,2747, # 5472
+6712,6713,6714,4786,3643,6715,4430,4431,6716,3557,6717,4432,4433,6718,6719,6720, # 5488
+6721,3749,6722,4006,4787,6723,6724,3644,4788,4434,6725,6726,4789,2772,6727,6728, # 5504
+6729,6730,6731,2708,3865,2813,4435,6732,6733,4790,4791,3480,6734,6735,6736,6737, # 5520
+4436,3348,6738,3410,4007,6739,6740,4008,6741,6742,4792,3411,4191,6743,6744,6745, # 5536
+6746,6747,3866,6748,3750,6749,6750,6751,6752,6753,6754,6755,3867,6756,4009,6757, # 5552
+4793,4794,6758,2814,2987,6759,6760,6761,4437,6762,6763,6764,6765,3645,6766,6767, # 5568
+3481,4192,6768,3751,6769,6770,2174,6771,3868,3752,6772,6773,6774,4193,4795,4438, # 5584
+3558,4796,4439,6775,4797,6776,6777,4798,6778,4799,3559,4800,6779,6780,6781,3482, # 5600
+6782,2893,6783,6784,4194,4801,4010,6785,6786,4440,6787,4011,6788,6789,6790,6791, # 5616
+6792,6793,4802,6794,6795,6796,4012,6797,6798,6799,6800,3349,4803,3483,6801,4804, # 5632
+4195,6802,4013,6803,6804,4196,6805,4014,4015,6806,2847,3271,2848,6807,3484,6808, # 5648
+6809,6810,4441,6811,4442,4197,4443,3272,4805,6812,3412,4016,1579,6813,6814,4017, # 5664
+6815,3869,6816,2964,6817,4806,6818,6819,4018,3646,6820,6821,4807,4019,4020,6822, # 5680
+6823,3560,6824,6825,4021,4444,6826,4198,6827,6828,4445,6829,6830,4199,4808,6831, # 5696
+6832,6833,3870,3019,2458,6834,3753,3413,3350,6835,4809,3871,4810,3561,4446,6836, # 5712
+6837,4447,4811,4812,6838,2459,4448,6839,4449,6840,6841,4022,3872,6842,4813,4814, # 5728
+6843,6844,4815,4200,4201,4202,6845,4023,6846,6847,4450,3562,3873,6848,6849,4816, # 5744
+4817,6850,4451,4818,2139,6851,3563,6852,6853,3351,6854,6855,3352,4024,2709,3414, # 5760
+4203,4452,6856,4204,6857,6858,3874,3875,6859,6860,4819,6861,6862,6863,6864,4453, # 5776
+3647,6865,6866,4820,6867,6868,6869,6870,4454,6871,2869,6872,6873,4821,6874,3754, # 5792
+6875,4822,4205,6876,6877,6878,3648,4206,4455,6879,4823,6880,4824,3876,6881,3055, # 5808
+4207,6882,3415,6883,6884,6885,4208,4209,6886,4210,3353,6887,3354,3564,3209,3485, # 5824
+2652,6888,2728,6889,3210,3755,6890,4025,4456,6891,4825,6892,6893,6894,6895,4211, # 5840
+6896,6897,6898,4826,6899,6900,4212,6901,4827,6902,2773,3565,6903,4828,6904,6905, # 5856
+6906,6907,3649,3650,6908,2849,3566,6909,3567,3100,6910,6911,6912,6913,6914,6915, # 5872
+4026,6916,3355,4829,3056,4457,3756,6917,3651,6918,4213,3652,2870,6919,4458,6920, # 5888
+2438,6921,6922,3757,2774,4830,6923,3356,4831,4832,6924,4833,4459,3653,2507,6925, # 5904
+4834,2535,6926,6927,3273,4027,3147,6928,3568,6929,6930,6931,4460,6932,3877,4461, # 5920
+2729,3654,6933,6934,6935,6936,2175,4835,2630,4214,4028,4462,4836,4215,6937,3148, # 5936
+4216,4463,4837,4838,4217,6938,6939,2850,4839,6940,4464,6941,6942,6943,4840,6944, # 5952
+4218,3274,4465,6945,6946,2710,6947,4841,4466,6948,6949,2894,6950,6951,4842,6952, # 5968
+4219,3057,2871,6953,6954,6955,6956,4467,6957,2711,6958,6959,6960,3275,3101,4843, # 5984
+6961,3357,3569,6962,4844,6963,6964,4468,4845,3570,6965,3102,4846,3758,6966,4847, # 6000
+3878,4848,4849,4029,6967,2929,3879,4850,4851,6968,6969,1733,6970,4220,6971,6972, # 6016
+6973,6974,6975,6976,4852,6977,6978,6979,6980,6981,6982,3759,6983,6984,6985,3486, # 6032
+3487,6986,3488,3416,6987,6988,6989,6990,6991,6992,6993,6994,6995,6996,6997,4853, # 6048
+6998,6999,4030,7000,7001,3211,7002,7003,4221,7004,7005,3571,4031,7006,3572,7007, # 6064
+2614,4854,2577,7008,7009,2965,3655,3656,4855,2775,3489,3880,4222,4856,3881,4032, # 6080
+3882,3657,2730,3490,4857,7010,3149,7011,4469,4858,2496,3491,4859,2283,7012,7013, # 6096
+7014,2365,4860,4470,7015,7016,3760,7017,7018,4223,1917,7019,7020,7021,4471,7022, # 6112
+2776,4472,7023,7024,7025,7026,4033,7027,3573,4224,4861,4034,4862,7028,7029,1929, # 6128
+3883,4035,7030,4473,3058,7031,2536,3761,3884,7032,4036,7033,2966,2895,1968,4474, # 6144
+3276,4225,3417,3492,4226,2105,7034,7035,1754,2596,3762,4227,4863,4475,3763,4864, # 6160
+3764,2615,2777,3103,3765,3658,3418,4865,2296,3766,2815,7036,7037,7038,3574,2872, # 6176
+3277,4476,7039,4037,4477,7040,7041,4038,7042,7043,7044,7045,7046,7047,2537,7048, # 6192
+7049,7050,7051,7052,7053,7054,4478,7055,7056,3767,3659,4228,3575,7057,7058,4229, # 6208
+7059,7060,7061,3660,7062,3212,7063,3885,4039,2460,7064,7065,7066,7067,7068,7069, # 6224
+7070,7071,7072,7073,7074,4866,3768,4867,7075,7076,7077,7078,4868,3358,3278,2653, # 6240
+7079,7080,4479,3886,7081,7082,4869,7083,7084,7085,7086,7087,7088,2538,7089,7090, # 6256
+7091,4040,3150,3769,4870,4041,2896,3359,4230,2930,7092,3279,7093,2967,4480,3213, # 6272
+4481,3661,7094,7095,7096,7097,7098,7099,7100,7101,7102,2461,3770,7103,7104,4231, # 6288
+3151,7105,7106,7107,4042,3662,7108,7109,4871,3663,4872,4043,3059,7110,7111,7112, # 6304
+3493,2988,7113,4873,7114,7115,7116,3771,4874,7117,7118,4232,4875,7119,3576,2336, # 6320
+4876,7120,4233,3419,4044,4877,4878,4482,4483,4879,4484,4234,7121,3772,4880,1045, # 6336
+3280,3664,4881,4882,7122,7123,7124,7125,4883,7126,2778,7127,4485,4486,7128,4884, # 6352
+3214,3887,7129,7130,3215,7131,4885,4045,7132,7133,4046,7134,7135,7136,7137,7138, # 6368
+7139,7140,7141,7142,7143,4235,7144,4886,7145,7146,7147,4887,7148,7149,7150,4487, # 6384
+4047,4488,7151,7152,4888,4048,2989,3888,7153,3665,7154,4049,7155,7156,7157,7158, # 6400
+7159,7160,2931,4889,4890,4489,7161,2631,3889,4236,2779,7162,7163,4891,7164,3060, # 6416
+7165,1672,4892,7166,4893,4237,3281,4894,7167,7168,3666,7169,3494,7170,7171,4050, # 6432
+7172,7173,3104,3360,3420,4490,4051,2684,4052,7174,4053,7175,7176,7177,2253,4054, # 6448
+7178,7179,4895,7180,3152,3890,3153,4491,3216,7181,7182,7183,2968,4238,4492,4055, # 6464
+7184,2990,7185,2479,7186,7187,4493,7188,7189,7190,7191,7192,4896,7193,4897,2969, # 6480
+4494,4898,7194,3495,7195,7196,4899,4495,7197,3105,2731,7198,4900,7199,7200,7201, # 6496
+4056,7202,3361,7203,7204,4496,4901,4902,7205,4497,7206,7207,2315,4903,7208,4904, # 6512
+7209,4905,2851,7210,7211,3577,7212,3578,4906,7213,4057,3667,4907,7214,4058,2354, # 6528
+3891,2376,3217,3773,7215,7216,7217,7218,7219,4498,7220,4908,3282,2685,7221,3496, # 6544
+4909,2632,3154,4910,7222,2337,7223,4911,7224,7225,7226,4912,4913,3283,4239,4499, # 6560
+7227,2816,7228,7229,7230,7231,7232,7233,7234,4914,4500,4501,7235,7236,7237,2686, # 6576
+7238,4915,7239,2897,4502,7240,4503,7241,2516,7242,4504,3362,3218,7243,7244,7245, # 6592
+4916,7246,7247,4505,3363,7248,7249,7250,7251,3774,4506,7252,7253,4917,7254,7255, # 6608
+3284,2991,4918,4919,3219,3892,4920,3106,3497,4921,7256,7257,7258,4922,7259,4923, # 6624
+3364,4507,4508,4059,7260,4240,3498,7261,7262,4924,7263,2992,3893,4060,3220,7264, # 6640
+7265,7266,7267,7268,7269,4509,3775,7270,2817,7271,4061,4925,4510,3776,7272,4241, # 6656
+4511,3285,7273,7274,3499,7275,7276,7277,4062,4512,4926,7278,3107,3894,7279,7280, # 6672
+4927,7281,4513,7282,7283,3668,7284,7285,4242,4514,4243,7286,2058,4515,4928,4929, # 6688
+4516,7287,3286,4244,7288,4517,7289,7290,7291,3669,7292,7293,4930,4931,4932,2355, # 6704
+4933,7294,2633,4518,7295,4245,7296,7297,4519,7298,7299,4520,4521,4934,7300,4246, # 6720
+4522,7301,7302,7303,3579,7304,4247,4935,7305,4936,7306,7307,7308,7309,3777,7310, # 6736
+4523,7311,7312,7313,4248,3580,7314,4524,3778,4249,7315,3581,7316,3287,7317,3221, # 6752
+7318,4937,7319,7320,7321,7322,7323,7324,4938,4939,7325,4525,7326,7327,7328,4063, # 6768
+7329,7330,4940,7331,7332,4941,7333,4526,7334,3500,2780,1741,4942,2026,1742,7335, # 6784
+7336,3582,4527,2388,7337,7338,7339,4528,7340,4250,4943,7341,7342,7343,4944,7344, # 6800
+7345,7346,3020,7347,4945,7348,7349,7350,7351,3895,7352,3896,4064,3897,7353,7354, # 6816
+7355,4251,7356,7357,3898,7358,3779,7359,3780,3288,7360,7361,4529,7362,4946,4530, # 6832
+2027,7363,3899,4531,4947,3222,3583,7364,4948,7365,7366,7367,7368,4949,3501,4950, # 6848
+3781,4951,4532,7369,2517,4952,4252,4953,3155,7370,4954,4955,4253,2518,4533,7371, # 6864
+7372,2712,4254,7373,7374,7375,3670,4956,3671,7376,2389,3502,4065,7377,2338,7378, # 6880
+7379,7380,7381,3061,7382,4957,7383,7384,7385,7386,4958,4534,7387,7388,2993,7389, # 6896
+3062,7390,4959,7391,7392,7393,4960,3108,4961,7394,4535,7395,4962,3421,4536,7396, # 6912
+4963,7397,4964,1857,7398,4965,7399,7400,2176,3584,4966,7401,7402,3422,4537,3900, # 6928
+3585,7403,3782,7404,2852,7405,7406,7407,4538,3783,2654,3423,4967,4539,7408,3784, # 6944
+3586,2853,4540,4541,7409,3901,7410,3902,7411,7412,3785,3109,2327,3903,7413,7414, # 6960
+2970,4066,2932,7415,7416,7417,3904,3672,3424,7418,4542,4543,4544,7419,4968,7420, # 6976
+7421,4255,7422,7423,7424,7425,7426,4067,7427,3673,3365,4545,7428,3110,2559,3674, # 6992
+7429,7430,3156,7431,7432,3503,7433,3425,4546,7434,3063,2873,7435,3223,4969,4547, # 7008
+4548,2898,4256,4068,7436,4069,3587,3786,2933,3787,4257,4970,4971,3788,7437,4972, # 7024
+3064,7438,4549,7439,7440,7441,7442,7443,4973,3905,7444,2874,7445,7446,7447,7448, # 7040
+3021,7449,4550,3906,3588,4974,7450,7451,3789,3675,7452,2578,7453,4070,7454,7455, # 7056
+7456,4258,3676,7457,4975,7458,4976,4259,3790,3504,2634,4977,3677,4551,4260,7459, # 7072
+7460,7461,7462,3907,4261,4978,7463,7464,7465,7466,4979,4980,7467,7468,2213,4262, # 7088
+7469,7470,7471,3678,4981,7472,2439,7473,4263,3224,3289,7474,3908,2415,4982,7475, # 7104
+4264,7476,4983,2655,7477,7478,2732,4552,2854,2875,7479,7480,4265,7481,4553,4984, # 7120
+7482,7483,4266,7484,3679,3366,3680,2818,2781,2782,3367,3589,4554,3065,7485,4071, # 7136
+2899,7486,7487,3157,2462,4072,4555,4073,4985,4986,3111,4267,2687,3368,4556,4074, # 7152
+3791,4268,7488,3909,2783,7489,2656,1962,3158,4557,4987,1963,3159,3160,7490,3112, # 7168
+4988,4989,3022,4990,4991,3792,2855,7491,7492,2971,4558,7493,7494,4992,7495,7496, # 7184
+7497,7498,4993,7499,3426,4559,4994,7500,3681,4560,4269,4270,3910,7501,4075,4995, # 7200
+4271,7502,7503,4076,7504,4996,7505,3225,4997,4272,4077,2819,3023,7506,7507,2733, # 7216
+4561,7508,4562,7509,3369,3793,7510,3590,2508,7511,7512,4273,3113,2994,2616,7513, # 7232
+7514,7515,7516,7517,7518,2820,3911,4078,2748,7519,7520,4563,4998,7521,7522,7523, # 7248
+7524,4999,4274,7525,4564,3682,2239,4079,4565,7526,7527,7528,7529,5000,7530,7531, # 7264
+5001,4275,3794,7532,7533,7534,3066,5002,4566,3161,7535,7536,4080,7537,3162,7538, # 7280
+7539,4567,7540,7541,7542,7543,7544,7545,5003,7546,4568,7547,7548,7549,7550,7551, # 7296
+7552,7553,7554,7555,7556,5004,7557,7558,7559,5005,7560,3795,7561,4569,7562,7563, # 7312
+7564,2821,3796,4276,4277,4081,7565,2876,7566,5006,7567,7568,2900,7569,3797,3912, # 7328
+7570,7571,7572,4278,7573,7574,7575,5007,7576,7577,5008,7578,7579,4279,2934,7580, # 7344
+7581,5009,7582,4570,7583,4280,7584,7585,7586,4571,4572,3913,7587,4573,3505,7588, # 7360
+5010,7589,7590,7591,7592,3798,4574,7593,7594,5011,7595,4281,7596,7597,7598,4282, # 7376
+5012,7599,7600,5013,3163,7601,5014,7602,3914,7603,7604,2734,4575,4576,4577,7605, # 7392
+7606,7607,7608,7609,3506,5015,4578,7610,4082,7611,2822,2901,2579,3683,3024,4579, # 7408
+3507,7612,4580,7613,3226,3799,5016,7614,7615,7616,7617,7618,7619,7620,2995,3290, # 7424
+7621,4083,7622,5017,7623,7624,7625,7626,7627,4581,3915,7628,3291,7629,5018,7630, # 7440
+7631,7632,7633,4084,7634,7635,3427,3800,7636,7637,4582,7638,5019,4583,5020,7639, # 7456
+3916,7640,3801,5021,4584,4283,7641,7642,3428,3591,2269,7643,2617,7644,4585,3592, # 7472
+7645,4586,2902,7646,7647,3227,5022,7648,4587,7649,4284,7650,7651,7652,4588,2284, # 7488
+7653,5023,7654,7655,7656,4589,5024,3802,7657,7658,5025,3508,4590,7659,7660,7661, # 7504
+1969,5026,7662,7663,3684,1821,2688,7664,2028,2509,4285,7665,2823,1841,7666,2689, # 7520
+3114,7667,3917,4085,2160,5027,5028,2972,7668,5029,7669,7670,7671,3593,4086,7672, # 7536
+4591,4087,5030,3803,7673,7674,7675,7676,7677,7678,7679,4286,2366,4592,4593,3067, # 7552
+2328,7680,7681,4594,3594,3918,2029,4287,7682,5031,3919,3370,4288,4595,2856,7683, # 7568
+3509,7684,7685,5032,5033,7686,7687,3804,2784,7688,7689,7690,7691,3371,7692,7693, # 7584
+2877,5034,7694,7695,3920,4289,4088,7696,7697,7698,5035,7699,5036,4290,5037,5038, # 7600
+5039,7700,7701,7702,5040,5041,3228,7703,1760,7704,5042,3229,4596,2106,4089,7705, # 7616
+4597,2824,5043,2107,3372,7706,4291,4090,5044,7707,4091,7708,5045,3025,3805,4598, # 7632
+4292,4293,4294,3373,7709,4599,7710,5046,7711,7712,5047,5048,3806,7713,7714,7715, # 7648
+5049,7716,7717,7718,7719,4600,5050,7720,7721,7722,5051,7723,4295,3429,7724,7725, # 7664
+7726,7727,3921,7728,3292,5052,4092,7729,7730,7731,7732,7733,7734,7735,5053,5054, # 7680
+7736,7737,7738,7739,3922,3685,7740,7741,7742,7743,2635,5055,7744,5056,4601,7745, # 7696
+7746,2560,7747,7748,7749,7750,3923,7751,7752,7753,7754,7755,4296,2903,7756,7757, # 7712
+7758,7759,7760,3924,7761,5057,4297,7762,7763,5058,4298,7764,4093,7765,7766,5059, # 7728
+3925,7767,7768,7769,7770,7771,7772,7773,7774,7775,7776,3595,7777,4299,5060,4094, # 7744
+7778,3293,5061,7779,7780,4300,7781,7782,4602,7783,3596,7784,7785,3430,2367,7786, # 7760
+3164,5062,5063,4301,7787,7788,4095,5064,5065,7789,3374,3115,7790,7791,7792,7793, # 7776
+7794,7795,7796,3597,4603,7797,7798,3686,3116,3807,5066,7799,7800,5067,7801,7802, # 7792
+4604,4302,5068,4303,4096,7803,7804,3294,7805,7806,5069,4605,2690,7807,3026,7808, # 7808
+7809,7810,7811,7812,7813,7814,7815,7816,7817,7818,7819,7820,7821,7822,7823,7824, # 7824
+7825,7826,7827,7828,7829,7830,7831,7832,7833,7834,7835,7836,7837,7838,7839,7840, # 7840
+7841,7842,7843,7844,7845,7846,7847,7848,7849,7850,7851,7852,7853,7854,7855,7856, # 7856
+7857,7858,7859,7860,7861,7862,7863,7864,7865,7866,7867,7868,7869,7870,7871,7872, # 7872
+7873,7874,7875,7876,7877,7878,7879,7880,7881,7882,7883,7884,7885,7886,7887,7888, # 7888
+7889,7890,7891,7892,7893,7894,7895,7896,7897,7898,7899,7900,7901,7902,7903,7904, # 7904
+7905,7906,7907,7908,7909,7910,7911,7912,7913,7914,7915,7916,7917,7918,7919,7920, # 7920
+7921,7922,7923,7924,3926,7925,7926,7927,7928,7929,7930,7931,7932,7933,7934,7935, # 7936
+7936,7937,7938,7939,7940,7941,7942,7943,7944,7945,7946,7947,7948,7949,7950,7951, # 7952
+7952,7953,7954,7955,7956,7957,7958,7959,7960,7961,7962,7963,7964,7965,7966,7967, # 7968
+7968,7969,7970,7971,7972,7973,7974,7975,7976,7977,7978,7979,7980,7981,7982,7983, # 7984
+7984,7985,7986,7987,7988,7989,7990,7991,7992,7993,7994,7995,7996,7997,7998,7999, # 8000
+8000,8001,8002,8003,8004,8005,8006,8007,8008,8009,8010,8011,8012,8013,8014,8015, # 8016
+8016,8017,8018,8019,8020,8021,8022,8023,8024,8025,8026,8027,8028,8029,8030,8031, # 8032
+8032,8033,8034,8035,8036,8037,8038,8039,8040,8041,8042,8043,8044,8045,8046,8047, # 8048
+8048,8049,8050,8051,8052,8053,8054,8055,8056,8057,8058,8059,8060,8061,8062,8063, # 8064
+8064,8065,8066,8067,8068,8069,8070,8071,8072,8073,8074,8075,8076,8077,8078,8079, # 8080
+8080,8081,8082,8083,8084,8085,8086,8087,8088,8089,8090,8091,8092,8093,8094,8095, # 8096
+8096,8097,8098,8099,8100,8101,8102,8103,8104,8105,8106,8107,8108,8109,8110,8111, # 8112
+8112,8113,8114,8115,8116,8117,8118,8119,8120,8121,8122,8123,8124,8125,8126,8127, # 8128
+8128,8129,8130,8131,8132,8133,8134,8135,8136,8137,8138,8139,8140,8141,8142,8143, # 8144
+8144,8145,8146,8147,8148,8149,8150,8151,8152,8153,8154,8155,8156,8157,8158,8159, # 8160
+8160,8161,8162,8163,8164,8165,8166,8167,8168,8169,8170,8171,8172,8173,8174,8175, # 8176
+8176,8177,8178,8179,8180,8181,8182,8183,8184,8185,8186,8187,8188,8189,8190,8191, # 8192
+8192,8193,8194,8195,8196,8197,8198,8199,8200,8201,8202,8203,8204,8205,8206,8207, # 8208
+8208,8209,8210,8211,8212,8213,8214,8215,8216,8217,8218,8219,8220,8221,8222,8223, # 8224
+8224,8225,8226,8227,8228,8229,8230,8231,8232,8233,8234,8235,8236,8237,8238,8239, # 8240
+8240,8241,8242,8243,8244,8245,8246,8247,8248,8249,8250,8251,8252,8253,8254,8255, # 8256
+8256,8257,8258,8259,8260,8261,8262,8263,8264,8265,8266,8267,8268,8269,8270,8271] # 8272
+end
diff --git a/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/jpcntx.rb b/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/jpcntx.rb
new file mode 100644 (file)
index 0000000..6f8e97c
--- /dev/null
@@ -0,0 +1,229 @@
+######################## BEGIN LICENSE BLOCK ########################
+# The Original Code is Mozilla Communicator client code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Jeff Hodges - port to Ruby
+#   Mark Pilgrim - port to Python
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+# 
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301  USA
+######################### END LICENSE BLOCK #########################
+
+module CharDet
+  NUM_OF_CATEGORY = 6
+  DONT_KNOW = -1
+  ENOUGH_REL_THRESHOLD = 100
+  MAX_REL_THRESHOLD = 1000
+  MINIMUM_DATA_THRESHOLD = 4
+
+  # This is hiragana 2-char sequence table, the number in each cell represents its frequency category
+  jp2CharContext = [
+    [0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1],
+    [2,4,0,4,0,3,0,4,0,3,4,4,4,2,4,3,3,4,3,2,3,3,4,2,3,3,3,2,4,1,4,3,3,1,5,4,3,4,3,4,3,5,3,0,3,5,4,2,0,3,1,0,3,3,0,3,3,0,1,1,0,4,3,0,3,3,0,4,0,2,0,3,5,5,5,5,4,0,4,1,0,3,4],
+    [0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2],
+    [0,4,0,5,0,5,0,4,0,4,5,4,4,3,5,3,5,1,5,3,4,3,4,4,3,4,3,3,4,3,5,4,4,3,5,5,3,5,5,5,3,5,5,3,4,5,5,3,1,3,2,0,3,4,0,4,2,0,4,2,1,5,3,2,3,5,0,4,0,2,0,5,4,4,5,4,5,0,4,0,0,4,4],
+    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
+    [0,3,0,4,0,3,0,3,0,4,5,4,3,3,3,3,4,3,5,4,4,3,5,4,4,3,4,3,4,4,4,4,5,3,4,4,3,4,5,5,4,5,5,1,4,5,4,3,0,3,3,1,3,3,0,4,4,0,3,3,1,5,3,3,3,5,0,4,0,3,0,4,4,3,4,3,3,0,4,1,1,3,4],
+    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
+    [0,4,0,3,0,3,0,4,0,3,4,4,3,2,2,1,2,1,3,1,3,3,3,3,3,4,3,1,3,3,5,3,3,0,4,3,0,5,4,3,3,5,4,4,3,4,4,5,0,1,2,0,1,2,0,2,2,0,1,0,0,5,2,2,1,4,0,3,0,1,0,4,4,3,5,4,3,0,2,1,0,4,3],
+    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
+    [0,3,0,5,0,4,0,2,1,4,4,2,4,1,4,2,4,2,4,3,3,3,4,3,3,3,3,1,4,2,3,3,3,1,4,4,1,1,1,4,3,3,2,0,2,4,3,2,0,3,3,0,3,1,1,0,0,0,3,3,0,4,2,2,3,4,0,4,0,3,0,4,4,5,3,4,4,0,3,0,0,1,4],
+    [1,4,0,4,0,4,0,4,0,3,5,4,4,3,4,3,5,4,3,3,4,3,5,4,4,4,4,3,4,2,4,3,3,1,5,4,3,2,4,5,4,5,5,4,4,5,4,4,0,3,2,2,3,3,0,4,3,1,3,2,1,4,3,3,4,5,0,3,0,2,0,4,5,5,4,5,4,0,4,0,0,5,4],
+    [0,5,0,5,0,4,0,3,0,4,4,3,4,3,3,3,4,0,4,4,4,3,4,3,4,3,3,1,4,2,4,3,4,0,5,4,1,4,5,4,4,5,3,2,4,3,4,3,2,4,1,3,3,3,2,3,2,0,4,3,3,4,3,3,3,4,0,4,0,3,0,4,5,4,4,4,3,0,4,1,0,1,3],
+    [0,3,1,4,0,3,0,2,0,3,4,4,3,1,4,2,3,3,4,3,4,3,4,3,4,4,3,2,3,1,5,4,4,1,4,4,3,5,4,4,3,5,5,4,3,4,4,3,1,2,3,1,2,2,0,3,2,0,3,1,0,5,3,3,3,4,3,3,3,3,4,4,4,4,5,4,2,0,3,3,2,4,3],
+    [0,2,0,3,0,1,0,1,0,0,3,2,0,0,2,0,1,0,2,1,3,3,3,1,2,3,1,0,1,0,4,2,1,1,3,3,0,4,3,3,1,4,3,3,0,3,3,2,0,0,0,0,1,0,0,2,0,0,0,0,0,4,1,0,2,3,2,2,2,1,3,3,3,4,4,3,2,0,3,1,0,3,3],
+    [0,4,0,4,0,3,0,3,0,4,4,4,3,3,3,3,3,3,4,3,4,2,4,3,4,3,3,2,4,3,4,5,4,1,4,5,3,5,4,5,3,5,4,0,3,5,5,3,1,3,3,2,2,3,0,3,4,1,3,3,2,4,3,3,3,4,0,4,0,3,0,4,5,4,4,5,3,0,4,1,0,3,4],
+    [0,2,0,3,0,3,0,0,0,2,2,2,1,0,1,0,0,0,3,0,3,0,3,0,1,3,1,0,3,1,3,3,3,1,3,3,3,0,1,3,1,3,4,0,0,3,1,1,0,3,2,0,0,0,0,1,3,0,1,0,0,3,3,2,0,3,0,0,0,0,0,3,4,3,4,3,3,0,3,0,0,2,3],
+    [2,3,0,3,0,2,0,1,0,3,3,4,3,1,3,1,1,1,3,1,4,3,4,3,3,3,0,0,3,1,5,4,3,1,4,3,2,5,5,4,4,4,4,3,3,4,4,4,0,2,1,1,3,2,0,1,2,0,0,1,0,4,1,3,3,3,0,3,0,1,0,4,4,4,5,5,3,0,2,0,0,4,4],
+    [0,2,0,1,0,3,1,3,0,2,3,3,3,0,3,1,0,0,3,0,3,2,3,1,3,2,1,1,0,0,4,2,1,0,2,3,1,4,3,2,0,4,4,3,1,3,1,3,0,1,0,0,1,0,0,0,1,0,0,0,0,4,1,1,1,2,0,3,0,0,0,3,4,2,4,3,2,0,1,0,0,3,3],
+    [0,1,0,4,0,5,0,4,0,2,4,4,2,3,3,2,3,3,5,3,3,3,4,3,4,2,3,0,4,3,3,3,4,1,4,3,2,1,5,5,3,4,5,1,3,5,4,2,0,3,3,0,1,3,0,4,2,0,1,3,1,4,3,3,3,3,0,3,0,1,0,3,4,4,4,5,5,0,3,0,1,4,5],
+    [0,2,0,3,0,3,0,0,0,2,3,1,3,0,4,0,1,1,3,0,3,4,3,2,3,1,0,3,3,2,3,1,3,0,2,3,0,2,1,4,1,2,2,0,0,3,3,0,0,2,0,0,0,1,0,0,0,0,2,2,0,3,2,1,3,3,0,2,0,2,0,0,3,3,1,2,4,0,3,0,2,2,3],
+    [2,4,0,5,0,4,0,4,0,2,4,4,4,3,4,3,3,3,1,2,4,3,4,3,4,4,5,0,3,3,3,3,2,0,4,3,1,4,3,4,1,4,4,3,3,4,4,3,1,2,3,0,4,2,0,4,1,0,3,3,0,4,3,3,3,4,0,4,0,2,0,3,5,3,4,5,2,0,3,0,0,4,5],
+    [0,3,0,4,0,1,0,1,0,1,3,2,2,1,3,0,3,0,2,0,2,0,3,0,2,0,0,0,1,0,1,1,0,0,3,1,0,0,0,4,0,3,1,0,2,1,3,0,0,0,0,0,0,3,0,0,0,0,0,0,0,4,2,2,3,1,0,3,0,0,0,1,4,4,4,3,0,0,4,0,0,1,4],
+    [1,4,1,5,0,3,0,3,0,4,5,4,4,3,5,3,3,4,4,3,4,1,3,3,3,3,2,1,4,1,5,4,3,1,4,4,3,5,4,4,3,5,4,3,3,4,4,4,0,3,3,1,2,3,0,3,1,0,3,3,0,5,4,4,4,4,4,4,3,3,5,4,4,3,3,5,4,0,3,2,0,4,4],
+    [0,2,0,3,0,1,0,0,0,1,3,3,3,2,4,1,3,0,3,1,3,0,2,2,1,1,0,0,2,0,4,3,1,0,4,3,0,4,4,4,1,4,3,1,1,3,3,1,0,2,0,0,1,3,0,0,0,0,2,0,0,4,3,2,4,3,5,4,3,3,3,4,3,3,4,3,3,0,2,1,0,3,3],
+    [0,2,0,4,0,3,0,2,0,2,5,5,3,4,4,4,4,1,4,3,3,0,4,3,4,3,1,3,3,2,4,3,0,3,4,3,0,3,4,4,2,4,4,0,4,5,3,3,2,2,1,1,1,2,0,1,5,0,3,3,2,4,3,3,3,4,0,3,0,2,0,4,4,3,5,5,0,0,3,0,2,3,3],
+    [0,3,0,4,0,3,0,1,0,3,4,3,3,1,3,3,3,0,3,1,3,0,4,3,3,1,1,0,3,0,3,3,0,0,4,4,0,1,5,4,3,3,5,0,3,3,4,3,0,2,0,1,1,1,0,1,3,0,1,2,1,3,3,2,3,3,0,3,0,1,0,1,3,3,4,4,1,0,1,2,2,1,3],
+    [0,1,0,4,0,4,0,3,0,1,3,3,3,2,3,1,1,0,3,0,3,3,4,3,2,4,2,0,1,0,4,3,2,0,4,3,0,5,3,3,2,4,4,4,3,3,3,4,0,1,3,0,0,1,0,0,1,0,0,0,0,4,2,3,3,3,0,3,0,0,0,4,4,4,5,3,2,0,3,3,0,3,5],
+    [0,2,0,3,0,0,0,3,0,1,3,0,2,0,0,0,1,0,3,1,1,3,3,0,0,3,0,0,3,0,2,3,1,0,3,1,0,3,3,2,0,4,2,2,0,2,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,2,1,2,0,1,0,1,0,0,0,1,3,1,2,0,0,0,1,0,0,1,4],
+    [0,3,0,3,0,5,0,1,0,2,4,3,1,3,3,2,1,1,5,2,1,0,5,1,2,0,0,0,3,3,2,2,3,2,4,3,0,0,3,3,1,3,3,0,2,5,3,4,0,3,3,0,1,2,0,2,2,0,3,2,0,2,2,3,3,3,0,2,0,1,0,3,4,4,2,5,4,0,3,0,0,3,5],
+    [0,3,0,3,0,3,0,1,0,3,3,3,3,0,3,0,2,0,2,1,1,0,2,0,1,0,0,0,2,1,0,0,1,0,3,2,0,0,3,3,1,2,3,1,0,3,3,0,0,1,0,0,0,0,0,2,0,0,0,0,0,2,3,1,2,3,0,3,0,1,0,3,2,1,0,4,3,0,1,1,0,3,3],
+    [0,4,0,5,0,3,0,3,0,4,5,5,4,3,5,3,4,3,5,3,3,2,5,3,4,4,4,3,4,3,4,5,5,3,4,4,3,4,4,5,4,4,4,3,4,5,5,4,2,3,4,2,3,4,0,3,3,1,4,3,2,4,3,3,5,5,0,3,0,3,0,5,5,5,5,4,4,0,4,0,1,4,4],
+    [0,4,0,4,0,3,0,3,0,3,5,4,4,2,3,2,5,1,3,2,5,1,4,2,3,2,3,3,4,3,3,3,3,2,5,4,1,3,3,5,3,4,4,0,4,4,3,1,1,3,1,0,2,3,0,2,3,0,3,0,0,4,3,1,3,4,0,3,0,2,0,4,4,4,3,4,5,0,4,0,0,3,4],
+    [0,3,0,3,0,3,1,2,0,3,4,4,3,3,3,0,2,2,4,3,3,1,3,3,3,1,1,0,3,1,4,3,2,3,4,4,2,4,4,4,3,4,4,3,2,4,4,3,1,3,3,1,3,3,0,4,1,0,2,2,1,4,3,2,3,3,5,4,3,3,5,4,4,3,3,0,4,0,3,2,2,4,4],
+    [0,2,0,1,0,0,0,0,0,1,2,1,3,0,0,0,0,0,2,0,1,2,1,0,0,1,0,0,0,0,3,0,0,1,0,1,1,3,1,0,0,0,1,1,0,1,1,0,0,0,0,0,2,0,0,0,0,0,0,0,0,1,1,2,2,0,3,4,0,0,0,1,1,0,0,1,0,0,0,0,0,1,1],
+    [0,1,0,0,0,1,0,0,0,0,4,0,4,1,4,0,3,0,4,0,3,0,4,0,3,0,3,0,4,1,5,1,4,0,0,3,0,5,0,5,2,0,1,0,0,0,2,1,4,0,1,3,0,0,3,0,0,3,1,1,4,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0],
+    [1,4,0,5,0,3,0,2,0,3,5,4,4,3,4,3,5,3,4,3,3,0,4,3,3,3,3,3,3,2,4,4,3,1,3,4,4,5,4,4,3,4,4,1,3,5,4,3,3,3,1,2,2,3,3,1,3,1,3,3,3,5,3,3,4,5,0,3,0,3,0,3,4,3,4,4,3,0,3,0,2,4,3],
+    [0,1,0,4,0,0,0,0,0,1,4,0,4,1,4,2,4,0,3,0,1,0,1,0,0,0,0,0,2,0,3,1,1,1,0,3,0,0,0,1,2,1,0,0,1,1,1,1,0,1,0,0,0,1,0,0,3,0,0,0,0,3,2,0,2,2,0,1,0,0,0,2,3,2,3,3,0,0,0,0,2,1,0],
+    [0,5,1,5,0,3,0,3,0,5,4,4,5,1,5,3,3,0,4,3,4,3,5,3,4,3,3,2,4,3,4,3,3,0,3,3,1,4,4,3,4,4,4,3,4,5,5,3,2,3,1,1,3,3,1,3,1,1,3,3,2,4,5,3,3,5,0,4,0,3,0,4,4,3,5,3,3,0,3,4,0,4,3],
+    [0,5,0,5,0,3,0,2,0,4,4,3,5,2,4,3,3,3,4,4,4,3,5,3,5,3,3,1,4,0,4,3,3,0,3,3,0,4,4,4,4,5,4,3,3,5,5,3,2,3,1,2,3,2,0,1,0,0,3,2,2,4,4,3,1,5,0,4,0,3,0,4,3,1,3,2,1,0,3,3,0,3,3],
+    [0,4,0,5,0,5,0,4,0,4,5,5,5,3,4,3,3,2,5,4,4,3,5,3,5,3,4,0,4,3,4,4,3,2,4,4,3,4,5,4,4,5,5,0,3,5,5,4,1,3,3,2,3,3,1,3,1,0,4,3,1,4,4,3,4,5,0,4,0,2,0,4,3,4,4,3,3,0,4,0,0,5,5],
+    [0,4,0,4,0,5,0,1,1,3,3,4,4,3,4,1,3,0,5,1,3,0,3,1,3,1,1,0,3,0,3,3,4,0,4,3,0,4,4,4,3,4,4,0,3,5,4,1,0,3,0,0,2,3,0,3,1,0,3,1,0,3,2,1,3,5,0,3,0,1,0,3,2,3,3,4,4,0,2,2,0,4,4],
+    [2,4,0,5,0,4,0,3,0,4,5,5,4,3,5,3,5,3,5,3,5,2,5,3,4,3,3,4,3,4,5,3,2,1,5,4,3,2,3,4,5,3,4,1,2,5,4,3,0,3,3,0,3,2,0,2,3,0,4,1,0,3,4,3,3,5,0,3,0,1,0,4,5,5,5,4,3,0,4,2,0,3,5],
+    [0,5,0,4,0,4,0,2,0,5,4,3,4,3,4,3,3,3,4,3,4,2,5,3,5,3,4,1,4,3,4,4,4,0,3,5,0,4,4,4,4,5,3,1,3,4,5,3,3,3,3,3,3,3,0,2,2,0,3,3,2,4,3,3,3,5,3,4,1,3,3,5,3,2,0,0,0,0,4,3,1,3,3],
+    [0,1,0,3,0,3,0,1,0,1,3,3,3,2,3,3,3,0,3,0,0,0,3,1,3,0,0,0,2,2,2,3,0,0,3,2,0,1,2,4,1,3,3,0,0,3,3,3,0,1,0,0,2,1,0,0,3,0,3,1,0,3,0,0,1,3,0,2,0,1,0,3,3,1,3,3,0,0,1,1,0,3,3],
+    [0,2,0,3,0,2,1,4,0,2,2,3,1,1,3,1,1,0,2,0,3,1,2,3,1,3,0,0,1,0,4,3,2,3,3,3,1,4,2,3,3,3,3,1,0,3,1,4,0,1,1,0,1,2,0,1,1,0,1,1,0,3,1,3,2,2,0,1,0,0,0,2,3,3,3,1,0,0,0,0,0,2,3],
+    [0,5,0,4,0,5,0,2,0,4,5,5,3,3,4,3,3,1,5,4,4,2,4,4,4,3,4,2,4,3,5,5,4,3,3,4,3,3,5,5,4,5,5,1,3,4,5,3,1,4,3,1,3,3,0,3,3,1,4,3,1,4,5,3,3,5,0,4,0,3,0,5,3,3,1,4,3,0,4,0,1,5,3],
+    [0,5,0,5,0,4,0,2,0,4,4,3,4,3,3,3,3,3,5,4,4,4,4,4,4,5,3,3,5,2,4,4,4,3,4,4,3,3,4,4,5,5,3,3,4,3,4,3,3,4,3,3,3,3,1,2,2,1,4,3,3,5,4,4,3,4,0,4,0,3,0,4,4,4,4,4,1,0,4,2,0,2,4],
+    [0,4,0,4,0,3,0,1,0,3,5,2,3,0,3,0,2,1,4,2,3,3,4,1,4,3,3,2,4,1,3,3,3,0,3,3,0,0,3,3,3,5,3,3,3,3,3,2,0,2,0,0,2,0,0,2,0,0,1,0,0,3,1,2,2,3,0,3,0,2,0,4,4,3,3,4,1,0,3,0,0,2,4],
+    [0,0,0,4,0,0,0,0,0,0,1,0,1,0,2,0,0,0,0,0,1,0,2,0,1,0,0,0,0,0,3,1,3,0,3,2,0,0,0,1,0,3,2,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,4,0,2,0,0,0,0,0,0,2],
+    [0,2,1,3,0,2,0,2,0,3,3,3,3,1,3,1,3,3,3,3,3,3,4,2,2,1,2,1,4,0,4,3,1,3,3,3,2,4,3,5,4,3,3,3,3,3,3,3,0,1,3,0,2,0,0,1,0,0,1,0,0,4,2,0,2,3,0,3,3,0,3,3,4,2,3,1,4,0,1,2,0,2,3],
+    [0,3,0,3,0,1,0,3,0,2,3,3,3,0,3,1,2,0,3,3,2,3,3,2,3,2,3,1,3,0,4,3,2,0,3,3,1,4,3,3,2,3,4,3,1,3,3,1,1,0,1,1,0,1,0,1,0,1,0,0,0,4,1,1,0,3,0,3,1,0,2,3,3,3,3,3,1,0,0,2,0,3,3],
+    [0,0,0,0,0,0,0,0,0,0,3,0,2,0,3,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,3,0,3,0,3,1,0,1,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,2,0,2,3,0,0,0,0,0,0,0,0,3],
+    [0,2,0,3,1,3,0,3,0,2,3,3,3,1,3,1,3,1,3,1,3,3,3,1,3,0,2,3,1,1,4,3,3,2,3,3,1,2,2,4,1,3,3,0,1,4,2,3,0,1,3,0,3,0,0,1,3,0,2,0,0,3,3,2,1,3,0,3,0,2,0,3,4,4,4,3,1,0,3,0,0,3,3],
+    [0,2,0,1,0,2,0,0,0,1,3,2,2,1,3,0,1,1,3,0,3,2,3,1,2,0,2,0,1,1,3,3,3,0,3,3,1,1,2,3,2,3,3,1,2,3,2,0,0,1,0,0,0,0,0,0,3,0,1,0,0,2,1,2,1,3,0,3,0,0,0,3,4,4,4,3,2,0,2,0,0,2,4],
+    [0,0,0,1,0,1,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,2,2,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,3,1,0,0,0,0,0,0,0,3],
+    [0,3,0,3,0,2,0,3,0,3,3,3,2,3,2,2,2,0,3,1,3,3,3,2,3,3,0,0,3,0,3,2,2,0,2,3,1,4,3,4,3,3,2,3,1,5,4,4,0,3,1,2,1,3,0,3,1,1,2,0,2,3,1,3,1,3,0,3,0,1,0,3,3,4,4,2,1,0,2,1,0,2,4],
+    [0,1,0,3,0,1,0,2,0,1,4,2,5,1,4,0,2,0,2,1,3,1,4,0,2,1,0,0,2,1,4,1,1,0,3,3,0,5,1,3,2,3,3,1,0,3,2,3,0,1,0,0,0,0,0,0,1,0,0,0,0,4,0,1,0,3,0,2,0,1,0,3,3,3,4,3,3,0,0,0,0,2,3],
+    [0,0,0,1,0,0,0,0,0,0,2,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,0,0,1,0,0,0,0,0,3],
+    [0,1,0,3,0,4,0,3,0,2,4,3,1,0,3,2,2,1,3,1,2,2,3,1,1,1,2,1,3,0,1,2,0,1,3,2,1,3,0,5,5,1,0,0,1,3,2,1,0,3,0,0,1,0,0,0,0,0,3,4,0,1,1,1,3,2,0,2,0,1,0,2,3,3,1,2,3,0,1,0,1,0,4],
+    [0,0,0,1,0,3,0,3,0,2,2,1,0,0,4,0,3,0,3,1,3,0,3,0,3,0,1,0,3,0,3,1,3,0,3,3,0,0,1,2,1,1,1,0,1,2,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,2,2,1,2,0,0,2,0,0,0,0,2,3,3,3,3,0,0,0,0,1,4],
+    [0,0,0,3,0,3,0,0,0,0,3,1,1,0,3,0,1,0,2,0,1,0,0,0,0,0,0,0,1,0,3,0,2,0,2,3,0,0,2,2,3,1,2,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,2,0,0,0,0,2,3],
+    [2,4,0,5,0,5,0,4,0,3,4,3,3,3,4,3,3,3,4,3,4,4,5,4,5,5,5,2,3,0,5,5,4,1,5,4,3,1,5,4,3,4,4,3,3,4,3,3,0,3,2,0,2,3,0,3,0,0,3,3,0,5,3,2,3,3,0,3,0,3,0,3,4,5,4,5,3,0,4,3,0,3,4],
+    [0,3,0,3,0,3,0,3,0,3,3,4,3,2,3,2,3,0,4,3,3,3,3,3,3,3,3,0,3,2,4,3,3,1,3,4,3,4,4,4,3,4,4,3,2,4,4,1,0,2,0,0,1,1,0,2,0,0,3,1,0,5,3,2,1,3,0,3,0,1,2,4,3,2,4,3,3,0,3,2,0,4,4],
+    [0,3,0,3,0,1,0,0,0,1,4,3,3,2,3,1,3,1,4,2,3,2,4,2,3,4,3,0,2,2,3,3,3,0,3,3,3,0,3,4,1,3,3,0,3,4,3,3,0,1,1,0,1,0,0,0,4,0,3,0,0,3,1,2,1,3,0,4,0,1,0,4,3,3,4,3,3,0,2,0,0,3,3],
+    [0,3,0,4,0,1,0,3,0,3,4,3,3,0,3,3,3,1,3,1,3,3,4,3,3,3,0,0,3,1,5,3,3,1,3,3,2,5,4,3,3,4,5,3,2,5,3,4,0,1,0,0,0,0,0,2,0,0,1,1,0,4,2,2,1,3,0,3,0,2,0,4,4,3,5,3,2,0,1,1,0,3,4],
+    [0,5,0,4,0,5,0,2,0,4,4,3,3,2,3,3,3,1,4,3,4,1,5,3,4,3,4,0,4,2,4,3,4,1,5,4,0,4,4,4,4,5,4,1,3,5,4,2,1,4,1,1,3,2,0,3,1,0,3,2,1,4,3,3,3,4,0,4,0,3,0,4,4,4,3,3,3,0,4,2,0,3,4],
+    [1,4,0,4,0,3,0,1,0,3,3,3,1,1,3,3,2,2,3,3,1,0,3,2,2,1,2,0,3,1,2,1,2,0,3,2,0,2,2,3,3,4,3,0,3,3,1,2,0,1,1,3,1,2,0,0,3,0,1,1,0,3,2,2,3,3,0,3,0,0,0,2,3,3,4,3,3,0,1,0,0,1,4],
+    [0,4,0,4,0,4,0,0,0,3,4,4,3,1,4,2,3,2,3,3,3,1,4,3,4,0,3,0,4,2,3,3,2,2,5,4,2,1,3,4,3,4,3,1,3,3,4,2,0,2,1,0,3,3,0,0,2,0,3,1,0,4,4,3,4,3,0,4,0,1,0,2,4,4,4,4,4,0,3,2,0,3,3],
+    [0,0,0,1,0,4,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,3,2,0,0,1,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,2],
+    [0,2,0,3,0,4,0,4,0,1,3,3,3,0,4,0,2,1,2,1,1,1,2,0,3,1,1,0,1,0,3,1,0,0,3,3,2,0,1,1,0,0,0,0,0,1,0,2,0,2,2,0,3,1,0,0,1,0,1,1,0,1,2,0,3,0,0,0,0,1,0,0,3,3,4,3,1,0,1,0,3,0,2],
+    [0,0,0,3,0,5,0,0,0,0,1,0,2,0,3,1,0,1,3,0,0,0,2,0,0,0,1,0,0,0,1,1,0,0,4,0,0,0,2,3,0,1,4,1,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,1,0,0,0,0,0,0,0,2,0,0,3,0,0,0,0,0,3],
+    [0,2,0,5,0,5,0,1,0,2,4,3,3,2,5,1,3,2,3,3,3,0,4,1,2,0,3,0,4,0,2,2,1,1,5,3,0,0,1,4,2,3,2,0,3,3,3,2,0,2,4,1,1,2,0,1,1,0,3,1,0,1,3,1,2,3,0,2,0,0,0,1,3,5,4,4,4,0,3,0,0,1,3],
+    [0,4,0,5,0,4,0,4,0,4,5,4,3,3,4,3,3,3,4,3,4,4,5,3,4,5,4,2,4,2,3,4,3,1,4,4,1,3,5,4,4,5,5,4,4,5,5,5,2,3,3,1,4,3,1,3,3,0,3,3,1,4,3,4,4,4,0,3,0,4,0,3,3,4,4,5,0,0,4,3,0,4,5],
+    [0,4,0,4,0,3,0,3,0,3,4,4,4,3,3,2,4,3,4,3,4,3,5,3,4,3,2,1,4,2,4,4,3,1,3,4,2,4,5,5,3,4,5,4,1,5,4,3,0,3,2,2,3,2,1,3,1,0,3,3,3,5,3,3,3,5,4,4,2,3,3,4,3,3,3,2,1,0,3,2,1,4,3],
+    [0,4,0,5,0,4,0,3,0,3,5,5,3,2,4,3,4,0,5,4,4,1,4,4,4,3,3,3,4,3,5,5,2,3,3,4,1,2,5,5,3,5,5,2,3,5,5,4,0,3,2,0,3,3,1,1,5,1,4,1,0,4,3,2,3,5,0,4,0,3,0,5,4,3,4,3,0,0,4,1,0,4,4],
+    [1,3,0,4,0,2,0,2,0,2,5,5,3,3,3,3,3,0,4,2,3,4,4,4,3,4,0,0,3,4,5,4,3,3,3,3,2,5,5,4,5,5,5,4,3,5,5,5,1,3,1,0,1,0,0,3,2,0,4,2,0,5,2,3,2,4,1,3,0,3,0,4,5,4,5,4,3,0,4,2,0,5,4],
+    [0,3,0,4,0,5,0,3,0,3,4,4,3,2,3,2,3,3,3,3,3,2,4,3,3,2,2,0,3,3,3,3,3,1,3,3,3,0,4,4,3,4,4,1,1,4,4,2,0,3,1,0,1,1,0,4,1,0,2,3,1,3,3,1,3,4,0,3,0,1,0,3,1,3,0,0,1,0,2,0,0,4,4],
+    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
+    [0,3,0,3,0,2,0,3,0,1,5,4,3,3,3,1,4,2,1,2,3,4,4,2,4,4,5,0,3,1,4,3,4,0,4,3,3,3,2,3,2,5,3,4,3,2,2,3,0,0,3,0,2,1,0,1,2,0,0,0,0,2,1,1,3,1,0,2,0,4,0,3,4,4,4,5,2,0,2,0,0,1,3],
+    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,1,1,0,0,1,1,0,0,0,4,2,1,1,0,1,0,3,2,0,0,3,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,1,0,0,0,2,0,0,0,1,4,0,4,2,1,0,0,0,0,0,1],
+    [0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,1,0,0,0,0,0,0,1,0,1,0,0,0,0,3,1,0,0,0,2,0,2,1,0,0,1,2,1,0,1,1,0,0,3,0,0,0,0,0,0,0,0,0,0,0,1,3,1,0,0,0,0,0,1,0,0,2,1,0,0,0,0,0,0,0,0,2],
+    [0,4,0,4,0,4,0,3,0,4,4,3,4,2,4,3,2,0,4,4,4,3,5,3,5,3,3,2,4,2,4,3,4,3,1,4,0,2,3,4,4,4,3,3,3,4,4,4,3,4,1,3,4,3,2,1,2,1,3,3,3,4,4,3,3,5,0,4,0,3,0,4,3,3,3,2,1,0,3,0,0,3,3],
+    [0,4,0,3,0,3,0,3,0,3,5,5,3,3,3,3,4,3,4,3,3,3,4,4,4,3,3,3,3,4,3,5,3,3,1,3,2,4,5,5,5,5,4,3,4,5,5,3,2,2,3,3,3,3,2,3,3,1,2,3,2,4,3,3,3,4,0,4,0,2,0,4,3,2,2,1,2,0,3,0,0,4,1],
+  ]
+
+  class JapaneseContextAnalysis
+    def initialize
+      reset()
+    end
+
+    def reset
+      @_mTotalRel = 0 # total sequence received
+      @_mRelSample = [0] * NUM_OF_CATEGORY # category counters, each interger counts sequence in its category
+      @_mNeedToSkipCharNum = 0 # if last byte in current buffer is not the last byte of a character, we need to know how many bytes to skip in next buffer
+      @_mLastCharOrder = -1 # The order of previous char
+      @_mDone = false # If this flag is set to constants.True, detection is done and conclusion has been made
+    end
+
+    def feed(aBuf, aLen)
+      return if @_mDone
+
+      # The buffer we got is byte oriented, and a character may span in more than one
+      # buffers. In case the last one or two byte in last buffer is not complete, we 
+      # record how many byte needed to complete that character and skip these bytes here.
+      # We can choose to record those bytes as well and analyse the character once it 
+      # is complete, but since a character will not make much difference, by simply skipping
+      # this character will simply our logic and improve performance.
+      i = @_mNeedToSkipCharNum
+      while i < aLen
+        order, charLen = get_order(aBuf[i...i+2])
+        i += charLen
+        if i > aLen
+          @_mNeedToSkipCharNum = i - aLen
+          @_mLastCharOrder = -1
+        else
+          if (order != -1) and (@_mLastCharOrder != -1)
+            @_mTotalRel += 1
+            if @_mTotalRel > MAX_REL_THRESHOLD
+              @_mDone = true
+              break
+            end
+            @_mRelSample[jp2CharContext[@_mLastCharOrder][order]] += 1
+          end
+          @_mLastCharOrder = order
+        end
+      end
+    end
+
+    def got_enough_data
+      return @_mTotalRel > ENOUGH_REL_THRESHOLD
+    end
+
+    def get_confidence
+      # This is just one way to calculate confidence. It works well for me.
+      if @_mTotalRel > MINIMUM_DATA_THRESHOLD
+        return (@_mTotalRel - @_mRelSample[0]) / @_mTotalRel
+      else
+        return DONT_KNOW
+      end
+    end
+
+    def get_order(aStr)
+      return -1, 1
+    end
+  end
+
+
+  class SJISContextAnalysis < JapaneseContextAnalysis
+    def get_order(aStr)
+      return -1, 1 if not aStr
+      # find out current char's byte length
+      aStr = aStr[0..1].join if aStr.class == Array
+      if ((aStr[0..0] >= "\x81") and (aStr[0..0] <= "\x9F")) or ((aStr[0..0] >= "\xE0") and (aStr[0..0] <= "\xFC"))
+        charLen = 2
+      else
+        charLen = 1
+      end
+      # return its order if it is hiragana
+      if aStr.length > 1
+        if (aStr[0..0] == "\202") and (aStr[1..1] >= "\x9F") and (aStr[1..1] <= "\xF1")
+          return aStr[1] - 0x9F, charLen
+        end
+      end
+    
+      return -1, charLen
+    end
+  end
+
+  class EUCJPContextAnalysis < JapaneseContextAnalysis
+    def get_order(aStr)
+      return -1, 1 unless aStr
+      # find out current char's byte length
+      aStr = aStr[0..1].join if aStr.class == Array
+      if (aStr[0..0] == "\x8E") or ((aStr[0..0] >= "\xA1") and (aStr[0..0] <= "\xFE"))
+        charLen = 2
+      elsif aStr[0..0] == "\x8F"
+        charLen = 3
+      else
+        charLen = 1
+      end
+
+      # return its order if it is hiragana
+      if aStr.length > 1
+        if (aStr[0..0] == "\xA4") and (aStr[1..1] >= "\xA1") and (aStr[1..1] <= "\xF3")
+          return aStr[1] - 0xA1, charLen
+        end
+      end
+
+      return -1, charLen
+    end
+  end
+end
diff --git a/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/langbulgarianmodel.rb b/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/langbulgarianmodel.rb
new file mode 100644 (file)
index 0000000..eb98038
--- /dev/null
@@ -0,0 +1,229 @@
+######################## BEGIN LICENSE BLOCK ########################
+# The Original Code is Mozilla Communicator client code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Jeff Hodges - port to Ruby
+#   Mark Pilgrim - port to Python
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+# 
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301  USA
+######################### END LICENSE BLOCK #########################
+
+# 255: Control characters that usually does not exist in any text
+# 254: Carriage/Return
+# 253: symbol (punctuation) that does not belong to word
+# 252: 0 - 9
+
+# Character Mapping Table:
+# this table is modified base on win1251BulgarianCharToOrderMap, so 
+# only number <64 is sure valid
+
+module CharDet
+Latin5_BulgarianCharToOrderMap = [
+255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255,  # 00
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  # 10
+253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,  # 20
+252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253,  # 30
+253, 77, 90, 99,100, 72,109,107,101, 79,185, 81,102, 76, 94, 82,  # 40
+110,186,108, 91, 74,119, 84, 96,111,187,115,253,253,253,253,253,  # 50
+253, 65, 69, 70, 66, 63, 68,112,103, 92,194,104, 95, 86, 87, 71,  # 60
+116,195, 85, 93, 97,113,196,197,198,199,200,253,253,253,253,253,  # 70
+194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,  # 80
+210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,  # 90
+ 81,226,227,228,229,230,105,231,232,233,234,235,236, 45,237,238,  # a0
+ 31, 32, 35, 43, 37, 44, 55, 47, 40, 59, 33, 46, 38, 36, 41, 30,  # b0
+ 39, 28, 34, 51, 48, 49, 53, 50, 54, 57, 61,239, 67,240, 60, 56,  # c0
+  1, 18,  9, 20, 11,  3, 23, 15,  2, 26, 12, 10, 14,  6,  4, 13,  # d0
+  7,  8,  5, 19, 29, 25, 22, 21, 27, 24, 17, 75, 52,241, 42, 16,  # e0
+ 62,242,243,244, 58,245, 98,246,247,248,249,250,251, 91,252,253,  # f0
+]
+
+win1251BulgarianCharToOrderMap = [
+255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255,  # 00
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  # 10
+253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,  # 20
+252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253,  # 30
+253, 77, 90, 99,100, 72,109,107,101, 79,185, 81,102, 76, 94, 82,  # 40
+110,186,108, 91, 74,119, 84, 96,111,187,115,253,253,253,253,253,  # 50
+253, 65, 69, 70, 66, 63, 68,112,103, 92,194,104, 95, 86, 87, 71,  # 60
+116,195, 85, 93, 97,113,196,197,198,199,200,253,253,253,253,253,  # 70
+206,207,208,209,210,211,212,213,120,214,215,216,217,218,219,220,  # 80
+221, 78, 64, 83,121, 98,117,105,222,223,224,225,226,227,228,229,  # 90
+ 88,230,231,232,233,122, 89,106,234,235,236,237,238, 45,239,240,  # a0
+ 73, 80,118,114,241,242,243,244,245, 62, 58,246,247,248,249,250,  # b0
+ 31, 32, 35, 43, 37, 44, 55, 47, 40, 59, 33, 46, 38, 36, 41, 30,  # c0
+ 39, 28, 34, 51, 48, 49, 53, 50, 54, 57, 61,251, 67,252, 60, 56,  # d0
+  1, 18,  9, 20, 11,  3, 23, 15,  2, 26, 12, 10, 14,  6,  4, 13,  # e0
+  7,  8,  5, 19, 29, 25, 22, 21, 27, 24, 17, 75, 52,253, 42, 16,  # f0
+]
+
+# Model Table: 
+# total sequences: 100%
+# first 512 sequences: 96.9392%
+# first 1024 sequences:3.0618%
+# rest  sequences:     0.2992%
+# negative sequences:  0.0020% 
+BulgarianLangModel = [
+0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,3,3,3,3,3,3,3,2,3,3,3,3,3,
+3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,3,3,3,2,2,3,2,2,1,2,2,
+3,1,3,3,2,3,3,3,3,3,3,3,3,3,3,3,3,0,3,3,3,3,3,3,3,3,3,3,0,3,0,1,
+0,0,0,0,0,0,0,0,0,0,1,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
+3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,2,3,3,3,3,3,3,3,3,0,3,1,0,
+0,1,0,0,0,0,0,0,0,0,1,1,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
+3,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,1,3,2,3,3,3,3,3,3,3,3,0,3,0,0,
+0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+3,2,3,3,2,3,3,3,3,3,3,3,3,3,3,3,3,1,3,2,3,3,3,3,3,3,3,3,0,3,0,0,
+0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+3,3,3,3,3,3,3,3,3,3,3,2,3,2,2,1,3,3,3,3,2,2,2,1,1,2,0,1,0,1,0,0,
+0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,1,
+3,3,3,3,3,3,3,2,3,2,2,3,3,1,1,2,3,3,2,3,3,3,3,2,1,2,0,2,0,3,0,0,
+0,0,0,0,0,0,0,1,0,0,2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,1,
+3,3,3,3,3,3,3,1,3,3,3,3,3,2,3,2,3,3,3,3,3,2,3,3,1,3,0,3,0,2,0,0,
+0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,
+3,3,3,3,3,3,3,3,1,3,3,2,3,3,3,1,3,3,2,3,2,2,2,0,0,2,0,2,0,2,0,0,
+0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,1,
+3,3,3,3,3,3,3,3,3,0,3,3,3,2,2,3,3,3,1,2,2,3,2,1,1,2,0,2,0,0,0,0,
+1,0,0,0,0,0,0,0,0,0,2,0,0,1,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,
+3,3,3,3,3,3,3,2,3,3,1,2,3,2,2,2,3,3,3,3,3,2,2,3,1,2,0,2,1,2,0,0,
+0,0,0,0,0,0,0,0,0,0,3,0,0,1,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,1,
+3,3,3,3,3,1,3,3,3,3,3,2,3,3,3,2,3,3,2,3,2,2,2,3,1,2,0,1,0,1,0,0,
+0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,
+3,3,3,3,3,3,3,3,3,3,3,1,1,1,2,2,1,3,1,3,2,2,3,0,0,1,0,1,0,1,0,0,
+0,0,0,1,0,0,0,0,1,0,2,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,
+3,3,3,3,3,2,2,3,2,2,3,1,2,1,1,1,2,3,1,3,1,2,2,0,1,1,1,1,0,1,0,0,
+0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,
+3,3,3,3,3,1,3,2,2,3,3,1,2,3,1,1,3,3,3,3,1,2,2,1,1,1,0,2,0,2,0,1,
+0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,
+3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,2,2,3,3,3,2,2,1,1,2,0,2,0,1,0,0,
+0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,
+3,0,1,2,1,3,3,2,3,3,3,3,3,2,3,2,1,0,3,1,2,1,2,1,2,3,2,1,0,1,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+1,1,1,2,3,3,3,3,3,3,3,3,3,3,3,3,0,0,3,1,3,3,2,3,3,2,2,2,0,1,0,0,
+0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+2,3,3,3,3,0,3,3,3,3,3,2,1,1,2,1,3,3,0,3,1,1,1,1,3,2,0,1,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,
+3,3,2,2,2,3,3,3,3,3,3,3,3,3,3,3,1,1,3,1,3,3,2,3,2,2,2,3,0,2,0,0,
+0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+3,3,3,3,3,2,3,3,2,2,3,2,1,1,1,1,1,3,1,3,1,1,0,0,0,1,0,0,0,1,0,0,
+0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,
+3,3,3,3,3,2,3,2,0,3,2,0,3,0,2,0,0,2,1,3,1,0,0,1,0,0,0,1,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
+3,3,3,3,2,1,1,1,1,2,1,1,2,1,1,1,2,2,1,2,1,1,1,0,1,1,0,1,0,1,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,
+3,3,3,3,2,1,3,1,1,2,1,3,2,1,1,0,1,2,3,2,1,1,1,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+2,3,3,3,3,2,2,1,0,1,0,0,1,0,0,0,2,1,0,3,0,0,1,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
+3,3,3,2,3,2,3,3,1,3,2,1,1,1,2,1,1,2,1,3,0,1,0,0,0,1,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+3,1,1,2,2,3,3,2,3,2,2,2,3,1,2,2,1,1,2,1,1,2,2,0,1,1,0,1,0,2,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+3,3,3,3,2,1,3,1,0,2,2,1,3,2,1,0,0,2,0,2,0,1,0,0,0,0,0,0,0,1,0,0,
+0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,
+3,3,3,3,3,3,1,2,0,2,3,1,2,3,2,0,1,3,1,2,1,1,1,0,0,1,0,0,2,2,2,3,
+2,2,2,2,1,2,1,1,2,2,1,1,2,0,1,1,1,0,0,1,1,0,0,1,1,0,0,0,1,1,0,1,
+3,3,3,3,3,2,1,2,2,1,2,0,2,0,1,0,1,2,1,2,1,1,0,0,0,1,0,1,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,1,
+3,3,2,3,3,1,1,3,1,0,3,2,1,0,0,0,1,2,0,2,0,1,0,0,0,1,0,1,2,1,2,2,
+1,1,1,1,1,1,1,2,2,2,1,1,1,1,1,1,1,0,1,2,1,1,1,0,0,0,0,0,1,1,0,0,
+3,1,0,1,0,2,3,2,2,2,3,2,2,2,2,2,1,0,2,1,2,1,1,1,0,1,2,1,2,2,2,1,
+1,1,2,2,2,2,1,2,1,1,0,1,2,1,2,2,2,1,1,1,0,1,1,1,1,2,0,1,0,0,0,0,
+2,3,2,3,3,0,0,2,1,0,2,1,0,0,0,0,2,3,0,2,0,0,0,0,0,1,0,0,2,0,1,2,
+2,1,2,1,2,2,1,1,1,2,1,1,1,0,1,2,2,1,1,1,1,1,0,1,1,1,0,0,1,2,0,0,
+3,3,2,2,3,0,2,3,1,1,2,0,0,0,1,0,0,2,0,2,0,0,0,1,0,1,0,1,2,0,2,2,
+1,1,1,1,2,1,0,1,2,2,2,1,1,1,1,1,1,1,0,1,1,1,0,0,0,0,0,0,1,1,0,0,
+2,3,2,3,3,0,0,3,0,1,1,0,1,0,0,0,2,2,1,2,0,0,0,0,0,0,0,0,2,0,1,2,
+2,2,1,1,1,1,1,2,2,2,1,0,2,0,1,0,1,0,0,1,0,1,0,0,1,0,0,0,0,1,0,0,
+3,3,3,3,2,2,2,2,2,0,2,1,1,1,1,2,1,2,1,1,0,2,0,1,0,1,0,0,2,0,1,2,
+1,1,1,1,1,1,1,2,2,1,1,0,2,0,1,0,2,0,0,1,1,1,0,0,2,0,0,0,1,1,0,0,
+2,3,3,3,3,1,0,0,0,0,0,0,0,0,0,0,2,0,0,1,1,0,0,0,0,0,0,1,2,0,1,2,
+2,2,2,1,1,2,1,1,2,2,2,1,2,0,1,1,1,1,1,1,0,1,1,1,1,0,0,1,1,1,0,0,
+2,3,3,3,3,0,2,2,0,2,1,0,0,0,1,1,1,2,0,2,0,0,0,3,0,0,0,0,2,0,2,2,
+1,1,1,2,1,2,1,1,2,2,2,1,2,0,1,1,1,0,1,1,1,1,0,2,1,0,0,0,1,1,0,0,
+2,3,3,3,3,0,2,1,0,0,2,0,0,0,0,0,1,2,0,2,0,0,0,0,0,0,0,0,2,0,1,2,
+1,1,1,2,1,1,1,1,2,2,2,0,1,0,1,1,1,0,0,1,1,1,0,0,1,0,0,0,0,1,0,0,
+3,3,2,2,3,0,1,0,1,0,0,0,0,0,0,0,1,1,0,3,0,0,0,0,0,0,0,0,1,0,2,2,
+1,1,1,1,1,2,1,1,2,2,1,2,2,1,0,1,1,1,1,1,0,1,0,0,1,0,0,0,1,1,0,0,
+3,1,0,1,0,2,2,2,2,3,2,1,1,1,2,3,0,0,1,0,2,1,1,0,1,1,1,1,2,1,1,1,
+1,2,2,1,2,1,2,2,1,1,0,1,2,1,2,2,1,1,1,0,0,1,1,1,2,1,0,1,0,0,0,0,
+2,1,0,1,0,3,1,2,2,2,2,1,2,2,1,1,1,0,2,1,2,2,1,1,2,1,1,0,2,1,1,1,
+1,2,2,2,2,2,2,2,1,2,0,1,1,0,2,1,1,1,1,1,0,0,1,1,1,1,0,1,0,0,0,0,
+2,1,1,1,1,2,2,2,2,1,2,2,2,1,2,2,1,1,2,1,2,3,2,2,1,1,1,1,0,1,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+2,2,2,3,2,0,1,2,0,1,2,1,1,0,1,0,1,2,1,2,0,0,0,1,1,0,0,0,1,0,0,2,
+1,1,0,0,1,1,0,1,1,1,1,0,2,0,1,1,1,0,0,1,1,0,0,0,0,1,0,0,0,1,0,0,
+2,0,0,0,0,1,2,2,2,2,2,2,2,1,2,1,1,1,1,1,1,1,0,1,1,1,1,1,2,1,1,1,
+1,2,2,2,2,1,1,2,1,2,1,1,1,0,2,1,2,1,1,1,0,2,1,1,1,1,0,1,0,0,0,0,
+3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,
+1,1,0,1,0,1,1,1,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+2,2,2,3,2,0,0,0,0,1,0,0,0,0,0,0,1,1,0,2,0,0,0,0,0,0,0,0,1,0,1,2,
+1,1,1,1,1,1,0,0,2,2,2,2,2,0,1,1,0,1,1,1,1,1,0,0,1,0,0,0,1,1,0,1,
+2,3,1,2,1,0,1,1,0,2,2,2,0,0,1,0,0,1,1,1,1,0,0,0,0,0,0,0,1,0,1,2,
+1,1,1,1,2,1,1,1,1,1,1,1,1,0,1,1,0,1,0,1,0,1,0,0,1,0,0,0,0,1,0,0,
+2,2,2,2,2,0,0,2,0,0,2,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,2,0,2,2,
+1,1,1,1,1,0,0,1,2,1,1,0,1,0,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,
+1,2,2,2,2,0,0,2,0,1,1,0,0,0,1,0,0,2,0,2,0,0,0,0,0,0,0,0,0,0,1,1,
+0,0,0,1,1,1,1,1,1,1,1,1,1,0,1,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,
+1,2,2,3,2,0,0,1,0,0,1,0,0,0,0,0,0,1,0,2,0,0,0,1,0,0,0,0,0,0,0,2,
+1,1,0,0,1,0,0,0,1,1,0,0,1,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,
+2,1,2,2,2,1,2,1,2,2,1,1,2,1,1,1,0,1,1,1,1,2,0,1,0,1,1,1,1,0,1,1,
+1,1,2,1,1,1,1,1,1,0,0,1,2,1,1,1,1,1,1,0,0,1,1,1,0,0,0,0,0,0,0,0,
+1,0,0,1,3,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+2,2,2,2,1,0,0,1,0,2,0,0,0,0,0,1,1,1,0,1,0,0,0,0,0,0,0,0,2,0,0,1,
+0,2,0,1,0,0,1,1,2,0,1,0,1,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,
+1,2,2,2,2,0,1,1,0,2,1,0,1,1,1,0,0,1,0,2,0,1,0,0,0,0,0,0,0,0,0,1,
+0,1,0,0,1,0,0,0,1,1,0,0,1,0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,
+2,2,2,2,2,0,0,1,0,0,0,1,0,1,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,1,
+0,1,0,1,1,1,0,0,1,1,1,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,
+2,0,1,0,0,1,2,1,1,1,1,1,1,2,2,1,0,0,1,0,1,0,0,0,0,1,1,1,1,0,0,0,
+1,1,2,1,1,1,1,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+2,2,1,2,1,0,0,1,0,0,0,0,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,1,
+0,0,0,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+1,0,0,1,2,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,
+0,1,1,0,1,1,1,0,0,1,0,0,1,0,1,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,
+1,0,1,0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,1,0,2,0,0,2,0,1,0,0,1,0,0,1,
+1,1,0,0,1,1,0,1,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,
+1,1,1,1,1,1,1,2,0,0,0,0,0,0,2,1,0,1,1,0,0,1,1,1,0,1,0,0,0,0,0,0,
+2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,1,1,0,1,1,1,1,1,0,1,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
+]
+
+Latin5BulgarianModel = { 
+  'charToOrderMap' =>  Latin5_BulgarianCharToOrderMap,
+  'precedenceMatrix' =>  BulgarianLangModel,
+  'mTypicalPositiveRatio' =>  0.969392,
+  'keepEnglishLetter' =>  false,
+  'charsetName' =>  "ISO-8859-5"
+}
+
+Win1251BulgarianModel = { 
+  'charToOrderMap' =>  win1251BulgarianCharToOrderMap,
+  'precedenceMatrix' =>  BulgarianLangModel,
+  'mTypicalPositiveRatio' =>  0.969392,
+  'keepEnglishLetter' =>  false,
+  'charsetName' =>  "windows-1251"
+}
+end
diff --git a/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/langcyrillicmodel.rb b/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/langcyrillicmodel.rb
new file mode 100644 (file)
index 0000000..d6e4fb9
--- /dev/null
@@ -0,0 +1,330 @@
+######################## BEGIN LICENSE BLOCK ########################
+# The Original Code is Mozilla Communicator client code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Jeff Hodges - port to Ruby
+#   Mark Pilgrim - port to Python
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+# 
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301  USA
+######################### END LICENSE BLOCK #########################
+
+module CharDet
+# KOI8-R language model
+# Character Mapping Table:
+KOI8R_CharToOrderMap = [
+255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255,  # 00
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  # 10
+253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,  # 20
+252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253,  # 30
+253,142,143,144,145,146,147,148,149,150,151,152, 74,153, 75,154,  # 40
+155,156,157,158,159,160,161,162,163,164,165,253,253,253,253,253,  # 50
+253, 71,172, 66,173, 65,174, 76,175, 64,176,177, 77, 72,178, 69,  # 60
+ 67,179, 78, 73,180,181, 79,182,183,184,185,253,253,253,253,253,  # 70
+191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,  # 80
+207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,  # 90
+223,224,225, 68,226,227,228,229,230,231,232,233,234,235,236,237,  # a0
+238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,  # b0
+ 27,  3, 21, 28, 13,  2, 39, 19, 26,  4, 23, 11,  8, 12,  5,  1,  # c0
+ 15, 16,  9,  7,  6, 14, 24, 10, 17, 18, 20, 25, 30, 29, 22, 54,  # d0
+ 59, 37, 44, 58, 41, 48, 53, 46, 55, 42, 60, 36, 49, 38, 31, 34,  # e0
+ 35, 43, 45, 32, 40, 52, 56, 33, 61, 62, 51, 57, 47, 63, 50, 70,  # f0
+]
+
+win1251_CharToOrderMap = [ 
+255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255,  # 00
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  # 10
+253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,  # 20
+252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253,  # 30
+253,142,143,144,145,146,147,148,149,150,151,152, 74,153, 75,154,  # 40
+155,156,157,158,159,160,161,162,163,164,165,253,253,253,253,253,  # 50
+253, 71,172, 66,173, 65,174, 76,175, 64,176,177, 77, 72,178, 69,  # 60
+ 67,179, 78, 73,180,181, 79,182,183,184,185,253,253,253,253,253,  # 70
+191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,
+207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,
+223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,
+239,240,241,242,243,244,245,246, 68,247,248,249,250,251,252,253,
+ 37, 44, 33, 46, 41, 48, 56, 51, 42, 60, 36, 49, 38, 31, 34, 35,
+ 45, 32, 40, 52, 53, 55, 58, 50, 57, 63, 70, 62, 61, 47, 59, 43,
+  3, 21, 10, 19, 13,  2, 24, 20,  4, 23, 11,  8, 12,  5,  1, 15,
+  9,  7,  6, 14, 39, 26, 28, 22, 25, 29, 54, 18, 17, 30, 27, 16,
+]
+
+latin5_CharToOrderMap = [
+255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255,  # 00
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  # 10
+253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,  # 20
+252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253,  # 30
+253,142,143,144,145,146,147,148,149,150,151,152, 74,153, 75,154,  # 40
+155,156,157,158,159,160,161,162,163,164,165,253,253,253,253,253,  # 50
+253, 71,172, 66,173, 65,174, 76,175, 64,176,177, 77, 72,178, 69,  # 60
+ 67,179, 78, 73,180,181, 79,182,183,184,185,253,253,253,253,253,  # 70
+191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,
+207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,
+223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,
+ 37, 44, 33, 46, 41, 48, 56, 51, 42, 60, 36, 49, 38, 31, 34, 35,
+ 45, 32, 40, 52, 53, 55, 58, 50, 57, 63, 70, 62, 61, 47, 59, 43,
+  3, 21, 10, 19, 13,  2, 24, 20,  4, 23, 11,  8, 12,  5,  1, 15,
+  9,  7,  6, 14, 39, 26, 28, 22, 25, 29, 54, 18, 17, 30, 27, 16,
+239, 68,240,241,242,243,244,245,246,247,248,249,250,251,252,255,
+]
+
+macCyrillic_CharToOrderMap = [
+255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255,  # 00
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  # 10
+253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,  # 20
+252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253,  # 30
+253,142,143,144,145,146,147,148,149,150,151,152, 74,153, 75,154,  # 40
+155,156,157,158,159,160,161,162,163,164,165,253,253,253,253,253,  # 50
+253, 71,172, 66,173, 65,174, 76,175, 64,176,177, 77, 72,178, 69,  # 60
+ 67,179, 78, 73,180,181, 79,182,183,184,185,253,253,253,253,253,  # 70
+ 37, 44, 33, 46, 41, 48, 56, 51, 42, 60, 36, 49, 38, 31, 34, 35,
+ 45, 32, 40, 52, 53, 55, 58, 50, 57, 63, 70, 62, 61, 47, 59, 43,
+191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,
+207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,
+223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,
+239,240,241,242,243,244,245,246,247,248,249,250,251,252, 68, 16,
+  3, 21, 10, 19, 13,  2, 24, 20,  4, 23, 11,  8, 12,  5,  1, 15,
+  9,  7,  6, 14, 39, 26, 28, 22, 25, 29, 54, 18, 17, 30, 27,255,
+]
+
+IBM855_CharToOrderMap = [
+255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255,  # 00
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  # 10
+253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,  # 20
+252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253,  # 30
+253,142,143,144,145,146,147,148,149,150,151,152, 74,153, 75,154,  # 40
+155,156,157,158,159,160,161,162,163,164,165,253,253,253,253,253,  # 50
+253, 71,172, 66,173, 65,174, 76,175, 64,176,177, 77, 72,178, 69,  # 60
+ 67,179, 78, 73,180,181, 79,182,183,184,185,253,253,253,253,253,  # 70
+191,192,193,194, 68,195,196,197,198,199,200,201,202,203,204,205,
+206,207,208,209,210,211,212,213,214,215,216,217, 27, 59, 54, 70,
+  3, 37, 21, 44, 28, 58, 13, 41,  2, 48, 39, 53, 19, 46,218,219,
+220,221,222,223,224, 26, 55,  4, 42,225,226,227,228, 23, 60,229,
+230,231,232,233,234,235, 11, 36,236,237,238,239,240,241,242,243,
+  8, 49, 12, 38,  5, 31,  1, 34, 15,244,245,246,247, 35, 16,248,
+ 43,  9, 45,  7, 32,  6, 40, 14, 52, 24, 56, 10, 33, 17, 61,249,
+250, 18, 62, 20, 51, 25, 57, 30, 47, 29, 63, 22, 50,251,252,255,
+]
+
+IBM866_CharToOrderMap = [
+255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255,  # 00
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  # 10
+253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,  # 20
+252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253,  # 30
+253,142,143,144,145,146,147,148,149,150,151,152, 74,153, 75,154,  # 40
+155,156,157,158,159,160,161,162,163,164,165,253,253,253,253,253,  # 50
+253, 71,172, 66,173, 65,174, 76,175, 64,176,177, 77, 72,178, 69,  # 60
+ 67,179, 78, 73,180,181, 79,182,183,184,185,253,253,253,253,253,  # 70
+ 37, 44, 33, 46, 41, 48, 56, 51, 42, 60, 36, 49, 38, 31, 34, 35,
+ 45, 32, 40, 52, 53, 55, 58, 50, 57, 63, 70, 62, 61, 47, 59, 43,
+  3, 21, 10, 19, 13,  2, 24, 20,  4, 23, 11,  8, 12,  5,  1, 15,
+191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,
+207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,
+223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,
+  9,  7,  6, 14, 39, 26, 28, 22, 25, 29, 54, 18, 17, 30, 27, 16,
+239, 68,240,241,242,243,244,245,246,247,248,249,250,251,252,255,
+]
+
+# Model Table: 
+# total sequences: 100%
+# first 512 sequences: 97.6601%
+# first 1024 sequences: 2.3389%
+# rest  sequences:      0.1237%
+# negative sequences:   0.0009% 
+RussianLangModel = [
+0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,1,3,3,3,3,1,3,3,3,2,3,2,3,3,
+3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,3,2,2,2,2,2,0,0,2,
+3,3,3,2,3,3,3,3,3,3,3,3,3,3,2,3,3,0,0,3,3,3,3,3,3,3,3,3,2,3,2,0,
+0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+3,3,3,2,2,3,3,3,3,3,3,3,3,3,2,3,3,0,0,3,3,3,3,3,3,3,3,2,3,3,1,0,
+0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+3,2,3,2,3,3,3,3,3,3,3,3,3,3,3,3,3,0,0,3,3,3,3,3,3,3,3,3,3,3,2,1,
+0,0,0,0,0,0,0,2,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,3,0,0,3,3,3,3,3,3,3,3,3,3,3,2,1,
+0,0,0,0,0,1,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+3,3,3,3,3,3,3,3,2,2,2,3,1,3,3,1,3,3,3,3,2,2,3,0,2,2,2,3,3,2,1,0,
+0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,
+3,3,3,3,3,3,2,3,3,3,3,3,2,2,3,2,3,3,3,2,1,2,2,0,1,2,2,2,2,2,2,0,
+0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,
+3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,2,3,0,2,2,3,3,2,1,2,0,
+0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,1,0,0,2,0,0,0,0,0,0,0,0,0,
+3,3,3,3,3,3,2,3,3,1,2,3,2,2,3,2,3,3,3,3,2,2,3,0,3,2,2,3,1,1,1,0,
+0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+3,3,3,3,3,3,3,3,2,2,3,3,3,3,3,2,3,3,3,3,2,2,2,0,3,3,3,2,2,2,2,0,
+0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+3,3,3,3,3,3,3,3,3,3,2,3,2,3,3,3,3,3,3,2,3,2,2,0,1,3,2,1,2,2,1,0,
+0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,
+3,3,3,3,3,3,3,3,3,3,3,2,1,1,3,0,1,1,1,1,2,1,1,0,2,2,2,1,2,0,1,0,
+0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+3,3,3,3,3,3,2,3,3,2,2,2,2,1,3,2,3,2,3,2,1,2,2,0,1,1,2,1,2,1,2,0,
+0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+3,3,3,3,3,3,3,3,3,3,3,3,2,2,3,2,3,3,3,2,2,2,2,0,2,2,2,2,3,1,1,0,
+0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,
+3,2,3,2,2,3,3,3,3,3,3,3,3,3,1,3,2,0,0,3,3,3,3,2,3,3,3,3,2,3,2,0,
+0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+2,3,3,3,3,3,2,2,3,3,0,2,1,0,3,2,3,2,3,0,0,1,2,0,0,1,0,1,2,1,1,0,
+0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+3,0,3,0,2,3,3,3,3,2,3,3,3,3,1,2,2,0,0,2,3,2,2,2,3,2,3,2,2,3,0,0,
+0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+3,2,3,0,2,3,2,3,0,1,2,3,3,2,0,2,3,0,0,2,3,2,2,0,1,3,1,3,2,2,1,0,
+0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+3,1,3,0,2,3,3,3,3,3,3,3,3,2,1,3,2,0,0,2,2,3,3,3,2,3,3,0,2,2,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+3,3,3,3,3,3,2,2,3,3,2,2,2,3,3,0,0,1,1,1,1,1,2,0,0,1,1,1,1,0,1,0,
+0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+3,3,3,3,3,3,2,2,3,3,3,3,3,3,3,0,3,2,3,3,2,3,2,0,2,1,0,1,1,0,1,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,
+3,3,3,3,3,3,2,3,3,3,2,2,2,2,3,1,3,2,3,1,1,2,1,0,2,2,2,2,1,3,1,0,
+0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,
+2,2,3,3,3,3,3,1,2,2,1,3,1,0,3,0,0,3,0,0,0,1,1,0,1,2,1,0,0,0,0,0,
+0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+3,2,2,1,1,3,3,3,2,2,1,2,2,3,1,1,2,0,0,2,2,1,3,0,0,2,1,1,2,1,1,0,
+0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+3,2,3,3,3,3,1,2,2,2,1,2,1,3,3,1,1,2,1,2,1,2,2,0,2,0,0,1,1,0,1,0,
+0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+2,3,3,3,3,3,2,1,3,2,2,3,2,0,3,2,0,3,0,1,0,1,1,0,0,1,1,1,1,0,1,0,
+0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+3,3,2,3,3,3,2,2,2,3,3,1,2,1,2,1,0,1,0,1,1,0,1,0,0,2,1,1,1,0,1,0,
+0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,
+3,1,1,2,1,2,3,3,2,2,1,2,2,3,0,2,1,0,0,2,2,3,2,1,2,2,2,2,2,3,1,0,
+0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+3,3,3,3,3,1,1,0,1,1,2,2,1,1,3,0,0,1,3,1,1,1,0,0,0,1,0,1,1,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+2,1,3,3,3,2,0,0,0,2,1,0,1,0,2,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+2,0,1,0,0,2,3,2,2,2,1,2,2,2,1,2,1,0,0,1,1,1,0,2,0,1,1,1,0,0,1,1,
+1,0,0,0,0,0,1,2,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,
+2,3,3,3,3,0,0,0,0,1,0,0,0,0,3,0,1,2,1,0,0,0,0,0,0,0,1,1,0,0,1,1,
+1,0,1,0,1,2,0,0,1,1,2,1,0,1,1,1,1,0,1,1,1,1,0,1,0,0,1,0,0,1,1,0,
+2,2,3,2,2,2,3,1,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,0,1,0,1,1,1,0,2,1,
+1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,0,1,0,1,1,0,1,1,1,0,1,1,0,
+3,3,3,2,2,2,2,3,2,2,1,1,2,2,2,2,1,1,3,1,2,1,2,0,0,1,1,0,1,0,2,1,
+1,1,1,1,1,2,1,0,1,1,1,1,0,1,0,0,1,1,0,0,1,0,1,0,0,1,0,0,0,1,1,0,
+2,0,0,1,0,3,2,2,2,2,1,2,1,2,1,2,0,0,0,2,1,2,2,1,1,2,2,0,1,1,0,2,
+1,1,1,1,1,0,1,1,1,2,1,1,1,2,1,0,1,2,1,1,1,1,0,1,1,1,0,0,1,0,0,1,
+1,3,2,2,2,1,1,1,2,3,0,0,0,0,2,0,2,2,1,0,0,0,0,0,0,1,0,0,0,0,1,1,
+1,0,1,1,0,1,0,1,1,0,1,1,0,2,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,1,1,0,
+2,3,2,3,2,1,2,2,2,2,1,0,0,0,2,0,0,1,1,0,0,0,0,0,0,0,1,1,0,0,2,1,
+1,1,2,1,0,2,0,0,1,0,1,0,0,1,0,0,1,1,0,1,1,0,0,0,0,0,1,0,0,0,0,0,
+3,0,0,1,0,2,2,2,3,2,2,2,2,2,2,2,0,0,0,2,1,2,1,1,1,2,2,0,0,0,1,2,
+1,1,1,1,1,0,1,2,1,1,1,1,1,1,1,0,1,1,1,1,1,1,0,1,1,1,1,1,1,0,0,1,
+2,3,2,3,3,2,0,1,1,1,0,0,1,0,2,0,1,1,3,1,0,0,0,0,0,0,0,1,0,0,2,1,
+1,1,1,1,1,1,1,0,1,0,1,1,1,1,0,1,1,1,0,0,1,1,0,1,0,0,0,0,0,0,1,0,
+2,3,3,3,3,1,2,2,2,2,0,1,1,0,2,1,1,1,2,1,0,1,1,0,0,1,0,1,0,0,2,0,
+0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+2,3,3,3,2,0,0,1,1,2,2,1,0,0,2,0,1,1,3,0,0,1,0,0,0,0,0,1,0,1,2,1,
+1,1,2,0,1,1,1,0,1,0,1,1,0,1,0,1,1,1,1,0,1,0,0,0,0,0,0,1,0,1,1,0,
+1,3,2,3,2,1,0,0,2,2,2,0,1,0,2,0,1,1,1,0,1,0,0,0,3,0,1,1,0,0,2,1,
+1,1,1,0,1,1,0,0,0,0,1,1,0,1,0,0,2,1,1,0,1,0,0,0,1,0,1,0,0,1,1,0,
+3,1,2,1,1,2,2,2,2,2,2,1,2,2,1,1,0,0,0,2,2,2,0,0,0,1,2,1,0,1,0,1,
+2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,2,1,1,1,0,1,0,1,1,0,1,1,1,0,0,1,
+3,0,0,0,0,2,0,1,1,1,1,1,1,1,0,1,0,0,0,1,1,1,0,1,0,1,1,0,0,1,0,1,
+1,1,0,0,1,0,0,0,1,0,1,1,0,0,1,0,1,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,
+1,3,3,2,2,0,0,0,2,2,0,0,0,1,2,0,1,1,2,0,0,0,0,0,0,0,0,1,0,0,2,1,
+0,1,1,0,0,1,1,0,0,0,1,1,0,1,1,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,1,0,
+2,3,2,3,2,0,0,0,0,1,1,0,0,0,2,0,2,0,2,0,0,0,0,0,1,0,0,1,0,0,1,1,
+1,1,2,0,1,2,1,0,1,1,2,1,1,1,1,1,2,1,1,0,1,0,0,1,1,1,1,1,0,1,1,0,
+1,3,2,2,2,1,0,0,2,2,1,0,1,2,2,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,1,1,
+0,0,1,1,0,1,1,0,0,1,1,0,1,1,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,
+1,0,0,1,0,2,3,1,2,2,2,2,2,2,1,1,0,0,0,1,0,1,0,2,1,1,1,0,0,0,0,1,
+1,1,0,1,1,0,1,1,1,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,
+2,0,2,0,0,1,0,3,2,1,2,1,2,2,0,1,0,0,0,2,1,0,0,2,1,1,1,1,0,2,0,2,
+2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,0,1,1,1,1,0,0,0,1,1,1,1,0,1,0,0,1,
+1,2,2,2,2,1,0,0,1,0,0,0,0,0,2,0,1,1,1,1,0,0,0,0,1,0,1,2,0,0,2,0,
+1,0,1,1,1,2,1,0,1,0,1,1,0,0,1,0,1,1,1,0,1,0,0,0,1,0,0,1,0,1,1,0,
+2,1,2,2,2,0,3,0,1,1,0,0,0,0,2,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
+0,0,0,1,1,1,0,0,1,0,1,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,
+1,2,2,3,2,2,0,0,1,1,2,0,1,2,1,0,1,0,1,0,0,1,0,0,0,0,0,0,0,0,0,1,
+0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,1,1,0,0,1,0,0,0,0,0,0,0,0,1,1,0,
+2,2,1,1,2,1,2,2,2,2,2,1,2,2,0,1,0,0,0,1,2,2,2,1,2,1,1,1,1,1,2,1,
+1,1,1,1,1,1,1,1,1,1,0,0,1,1,1,0,1,1,1,0,0,0,0,1,1,1,0,1,1,0,0,1,
+1,2,2,2,2,0,1,0,2,2,0,0,0,0,2,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,2,0,
+0,0,1,0,0,1,0,0,0,0,1,0,1,1,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,
+0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+1,2,2,2,2,0,0,0,2,2,2,0,1,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,
+0,1,1,0,0,1,1,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+1,2,2,2,2,0,0,0,0,1,0,0,1,1,2,0,0,0,0,1,0,1,0,0,1,0,0,2,0,0,0,1,
+0,0,1,0,0,1,0,0,0,1,1,0,0,0,0,0,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,
+1,2,2,2,1,1,2,0,2,1,1,1,1,0,2,2,0,0,0,0,0,0,0,0,0,1,1,0,0,0,1,1,
+0,0,1,0,1,1,0,0,0,0,1,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,
+1,0,2,1,2,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,
+0,0,1,0,1,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,
+1,0,0,0,0,2,0,1,2,1,0,1,1,1,0,1,0,0,0,1,0,1,0,0,1,0,1,0,0,0,0,1,
+0,0,0,0,0,1,0,0,1,1,0,0,1,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,
+2,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
+1,0,0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,1,0,0,0,0,0,
+2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
+1,1,1,0,1,0,1,0,0,1,1,1,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,1,0,0,0,0,
+1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
+1,1,0,1,1,0,1,0,1,0,0,0,0,1,1,0,1,1,0,0,0,0,0,1,0,1,1,0,1,0,0,0,
+0,1,1,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,
+]
+
+Koi8rModel = { 
+  'charToOrderMap' =>  KOI8R_CharToOrderMap,
+  'precedenceMatrix' =>  RussianLangModel,
+  'mTypicalPositiveRatio' =>  0.976601,
+  'keepEnglishLetter' =>  false,
+  'charsetName' =>  "KOI8-R"
+}
+
+Win1251CyrillicModel = { 
+  'charToOrderMap' =>  win1251_CharToOrderMap,
+  'precedenceMatrix' =>  RussianLangModel,
+  'mTypicalPositiveRatio' =>  0.976601,
+  'keepEnglishLetter' =>  false,
+  'charsetName' =>  "windows-1251"
+}
+
+Latin5CyrillicModel = { 
+  'charToOrderMap' =>  latin5_CharToOrderMap,
+  'precedenceMatrix' =>  RussianLangModel,
+  'mTypicalPositiveRatio' =>  0.976601,
+  'keepEnglishLetter' =>  false,
+  'charsetName' =>  "ISO-8859-5"
+}
+
+MacCyrillicModel = { 
+  'charToOrderMap' =>  macCyrillic_CharToOrderMap,
+  'precedenceMatrix' =>  RussianLangModel,
+  'mTypicalPositiveRatio' =>  0.976601,
+  'keepEnglishLetter' =>  false,
+  'charsetName' =>  "MacCyrillic"
+}
+
+Ibm866Model = { 
+  'charToOrderMap' =>  IBM866_CharToOrderMap,
+  'precedenceMatrix' =>  RussianLangModel,
+  'mTypicalPositiveRatio' =>  0.976601,
+  'keepEnglishLetter' =>  false,
+  'charsetName' =>  "IBM866"
+}
+
+Ibm855Model = { 
+  'charToOrderMap' =>  IBM855_CharToOrderMap,
+  'precedenceMatrix' =>  RussianLangModel,
+  'mTypicalPositiveRatio' =>  0.976601,
+  'keepEnglishLetter' =>  false,
+  'charsetName' =>  "IBM855"
+}
+end
diff --git a/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/langgreekmodel.rb b/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/langgreekmodel.rb
new file mode 100644 (file)
index 0000000..934a233
--- /dev/null
@@ -0,0 +1,227 @@
+######################## BEGIN LICENSE BLOCK ########################
+# The Original Code is Mozilla Communicator client code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Jeff Hodges - port to Ruby
+#   Mark Pilgrim - port to Python
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+# 
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301  USA
+######################### END LICENSE BLOCK #########################
+
+
+module CharDet
+  # 255: Control characters that usually does not exist in any text
+  # 254: Carriage/Return
+  # 253: symbol (punctuation) that does not belong to word
+  # 252: 0 - 9
+
+  # Character Mapping Table:
+  Latin7_CharToOrderMap = [
+    255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255,  # 00
+    255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  # 10
+    253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,  # 20
+    252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253,  # 30
+    253, 82,100,104, 94, 98,101,116,102,111,187,117, 92, 88,113, 85,  # 40
+    79,118,105, 83, 67,114,119, 95, 99,109,188,253,253,253,253,253,  # 50
+    253, 72, 70, 80, 81, 60, 96, 93, 89, 68,120, 97, 77, 86, 69, 55,  # 60
+    78,115, 65, 66, 58, 76,106,103, 87,107,112,253,253,253,253,253,  # 70
+    255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  # 80
+    255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  # 90
+    253,233, 90,253,253,253,253,253,253,253,253,253,253, 74,253,253,  # a0
+    253,253,253,253,247,248, 61, 36, 46, 71, 73,253, 54,253,108,123,  # b0
+    110, 31, 51, 43, 41, 34, 91, 40, 52, 47, 44, 53, 38, 49, 59, 39,  # c0
+    35, 48,250, 37, 33, 45, 56, 50, 84, 57,120,121, 17, 18, 22, 15,  # d0
+    124,  1, 29, 20, 21,  3, 32, 13, 25,  5, 11, 16, 10,  6, 30,  4,  # e0
+    9,  8, 14,  7,  2, 12, 28, 23, 42, 24, 64, 75, 19, 26, 27,253,  # f0
+  ]
+
+  Win1253_CharToOrderMap = [
+    255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255,  # 00
+    255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  # 10
+    253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,  # 20
+    252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253,  # 30
+    253, 82,100,104, 94, 98,101,116,102,111,187,117, 92, 88,113, 85,  # 40
+    79,118,105, 83, 67,114,119, 95, 99,109,188,253,253,253,253,253,  # 50
+    253, 72, 70, 80, 81, 60, 96, 93, 89, 68,120, 97, 77, 86, 69, 55,  # 60
+    78,115, 65, 66, 58, 76,106,103, 87,107,112,253,253,253,253,253,  # 70
+    255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  # 80
+    255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  # 90
+    253,233, 61,253,253,253,253,253,253,253,253,253,253, 74,253,253,  # a0
+    253,253,253,253,247,253,253, 36, 46, 71, 73,253, 54,253,108,123,  # b0
+    110, 31, 51, 43, 41, 34, 91, 40, 52, 47, 44, 53, 38, 49, 59, 39,  # c0
+    35, 48,250, 37, 33, 45, 56, 50, 84, 57,120,121, 17, 18, 22, 15,  # d0
+    124,  1, 29, 20, 21,  3, 32, 13, 25,  5, 11, 16, 10,  6, 30,  4,  # e0
+    9,  8, 14,  7,  2, 12, 28, 23, 42, 24, 64, 75, 19, 26, 27,253,  # f0
+  ]
+
+  # Model Table: 
+  # total sequences: 100%
+  # first 512 sequences: 98.2851%
+  # first 1024 sequences:1.7001%
+  # rest  sequences:     0.0359%
+  # negative sequences:  0.0148% 
+  GreekLangModel = [
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,3,2,2,3,3,3,3,3,3,3,3,1,3,3,3,0,2,2,3,3,0,3,0,3,2,0,3,3,3,0,
+    3,0,0,0,2,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,3,3,3,3,3,0,3,3,0,3,2,3,3,0,3,2,3,3,3,0,0,3,0,3,0,3,3,2,0,0,0,
+    2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,
+    0,2,3,2,2,3,3,3,3,3,3,3,3,0,3,3,3,3,0,2,3,3,0,3,3,3,3,2,3,3,3,0,
+    2,0,0,0,2,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,2,3,3,2,3,3,3,3,3,3,3,3,3,3,3,3,0,2,1,3,3,3,3,2,3,3,2,3,3,2,0,
+    0,0,0,0,2,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,3,3,3,3,0,3,3,3,3,3,3,0,3,3,0,3,3,3,3,3,3,3,3,3,3,0,3,2,3,3,0,
+    2,0,1,0,2,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,
+    0,3,3,3,3,3,2,3,0,0,0,0,3,3,0,3,1,3,3,3,0,3,3,0,3,3,3,3,0,0,0,0,
+    2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,3,3,3,3,3,0,3,0,3,3,3,3,3,0,3,2,2,2,3,0,2,3,3,3,3,3,2,3,3,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,3,3,3,3,3,3,2,2,2,3,3,3,3,0,3,1,3,3,3,3,2,3,3,3,3,3,3,3,2,2,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,3,3,3,3,3,2,0,3,0,0,0,3,3,2,3,3,3,3,3,0,0,3,2,3,0,2,3,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,3,0,3,3,3,3,0,0,3,3,0,2,3,0,3,0,3,3,3,0,0,3,0,3,0,2,2,3,3,0,0,
+    0,0,1,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,3,3,3,3,3,2,0,3,2,3,3,3,3,0,3,3,3,3,3,0,3,3,2,3,2,3,3,2,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,3,3,2,3,2,3,3,3,3,3,3,0,2,3,2,3,2,2,2,3,2,3,3,2,3,0,2,2,2,3,0,
+    2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,3,0,0,0,3,3,3,2,3,3,0,0,3,0,3,0,0,0,3,2,0,3,0,3,0,0,2,0,2,0,
+    0,0,0,0,2,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,3,3,3,3,0,3,3,3,3,3,3,0,3,3,0,3,0,0,0,3,3,0,3,3,3,0,0,1,2,3,0,
+    3,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,3,3,3,3,3,2,0,0,3,2,2,3,3,0,3,3,3,3,3,2,1,3,0,3,2,3,3,2,1,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,3,3,0,2,3,3,3,3,3,3,0,0,3,0,3,0,0,0,3,3,0,3,2,3,0,0,3,3,3,0,
+    3,0,0,0,2,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,3,3,3,3,0,3,3,3,3,3,3,0,0,3,0,3,0,0,0,3,2,0,3,2,3,0,0,3,2,3,0,
+    2,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,3,1,2,2,3,3,3,3,3,3,0,2,3,0,3,0,0,0,3,3,0,3,0,2,0,0,2,3,1,0,
+    2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,3,0,3,3,3,3,0,3,0,3,3,2,3,0,3,3,3,3,3,3,0,3,3,3,0,2,3,0,0,3,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,3,0,3,3,3,0,0,3,0,0,0,3,3,0,3,0,2,3,3,0,0,3,0,3,0,3,3,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,3,0,0,0,3,3,3,3,3,3,0,0,3,0,2,0,0,0,3,3,0,3,0,3,0,0,2,0,2,0,
+    0,0,0,0,1,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,3,3,3,3,3,3,0,3,0,2,0,3,2,0,3,2,3,2,3,0,0,3,2,3,2,3,3,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,3,0,0,2,3,3,3,3,3,0,0,0,3,0,2,1,0,0,3,2,2,2,0,3,0,0,2,2,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,3,0,3,3,3,2,0,3,0,3,0,3,3,0,2,1,2,3,3,0,0,3,0,3,0,3,3,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,2,3,3,3,0,3,3,3,3,3,3,0,2,3,0,3,0,0,0,2,1,0,2,2,3,0,0,2,2,2,0,
+    0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,3,0,0,2,3,3,3,2,3,0,0,1,3,0,2,0,0,0,0,3,0,1,0,2,0,0,1,1,1,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,3,3,3,3,3,1,0,3,0,0,0,3,2,0,3,2,3,3,3,0,0,3,0,3,2,2,2,1,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,3,0,3,3,3,0,0,3,0,0,0,0,2,0,2,3,3,2,2,2,2,3,0,2,0,2,2,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,3,3,3,3,2,0,0,0,0,0,0,2,3,0,2,0,2,3,2,0,0,3,0,3,0,3,1,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,3,2,3,3,2,2,3,0,2,0,3,0,0,0,2,0,0,0,0,1,2,0,2,0,2,0,
+    0,2,0,2,0,2,2,0,0,1,0,2,2,2,0,2,2,2,0,2,2,2,0,0,2,0,0,1,0,0,0,0,
+    0,2,0,3,3,2,0,0,0,0,0,0,1,3,0,2,0,2,2,2,0,0,2,0,3,0,0,2,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,3,0,2,3,2,0,2,2,0,2,0,2,2,0,2,0,2,2,2,0,0,0,0,0,0,2,3,0,0,0,2,
+    0,1,2,0,0,0,0,2,2,0,0,0,2,1,0,2,2,0,0,0,0,0,0,1,0,2,0,0,0,0,0,0,
+    0,0,2,1,0,2,3,2,2,3,2,3,2,0,0,3,3,3,0,0,3,2,0,0,0,1,1,0,2,0,2,2,
+    0,2,0,2,0,2,2,0,0,2,0,2,2,2,0,2,2,2,2,0,0,2,0,0,0,2,0,1,0,0,0,0,
+    0,3,0,3,3,2,2,0,3,0,0,0,2,2,0,2,2,2,1,2,0,0,1,2,2,0,0,3,0,0,0,2,
+    0,1,2,0,0,0,1,2,0,0,0,0,0,0,0,2,2,0,1,0,0,2,0,0,0,2,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,2,3,3,2,2,0,0,0,2,0,2,3,3,0,2,0,0,0,0,0,0,2,2,2,0,2,2,0,2,0,2,
+    0,2,2,0,0,2,2,2,2,1,0,0,2,2,0,2,0,0,2,0,0,0,0,0,0,2,0,0,0,0,0,0,
+    0,2,0,3,2,3,0,0,0,3,0,0,2,2,0,2,0,2,2,2,0,0,2,0,0,0,0,0,0,0,0,2,
+    0,0,2,2,0,0,2,2,2,0,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,2,0,0,3,2,0,2,2,2,2,2,0,0,0,2,0,0,0,0,2,0,1,0,0,2,0,1,0,0,0,
+    0,2,2,2,0,2,2,0,1,2,0,2,2,2,0,2,2,2,2,1,2,2,0,0,2,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,
+    0,2,0,2,0,2,2,0,0,0,0,1,2,1,0,0,2,2,0,0,2,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,3,2,3,0,0,2,0,0,0,2,2,0,2,0,0,0,1,0,0,2,0,2,0,2,2,0,0,0,0,
+    0,0,2,0,0,0,0,2,2,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,
+    0,2,2,3,2,2,0,0,0,0,0,0,1,3,0,2,0,2,2,0,0,0,1,0,2,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,2,0,2,0,3,2,0,2,0,0,0,0,0,0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
+    0,0,2,0,0,0,0,1,1,0,0,2,1,2,0,2,2,0,1,0,0,1,0,0,0,2,0,0,0,0,0,0,
+    0,3,0,2,2,2,0,0,2,0,0,0,2,0,0,0,2,3,0,2,0,0,0,0,0,0,2,2,0,0,0,2,
+    0,1,2,0,0,0,1,2,2,1,0,0,0,2,0,0,2,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,2,1,2,0,2,2,0,2,0,0,2,0,0,0,0,1,2,1,0,2,1,0,0,0,0,0,0,0,0,0,0,
+    0,0,2,0,0,0,3,1,2,2,0,2,0,0,0,0,2,0,0,0,2,0,0,3,0,0,0,0,2,2,2,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,2,1,0,2,0,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,1,0,0,0,0,0,0,2,
+    0,2,2,0,0,2,2,2,2,2,0,1,2,0,0,0,2,2,0,1,0,2,0,0,2,2,0,0,0,0,0,0,
+    0,0,0,0,1,0,0,0,0,0,0,0,3,0,0,2,0,0,0,0,0,0,0,0,2,0,2,0,0,0,0,2,
+    0,1,2,0,0,0,0,2,2,1,0,1,0,1,0,2,2,2,1,0,0,0,0,0,0,1,0,0,0,0,0,0,
+    0,2,0,1,2,0,0,0,0,0,0,0,0,0,0,2,0,0,2,2,0,0,0,0,1,0,0,0,0,0,0,2,
+    0,2,2,0,0,0,0,2,2,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,2,0,0,2,0,0,0,
+    0,2,2,2,2,0,0,0,3,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,2,0,0,0,0,0,0,1,
+    0,0,2,0,0,0,0,1,2,0,0,0,0,0,0,2,2,1,1,0,0,0,0,0,0,1,0,0,0,0,0,0,
+    0,2,0,2,2,2,0,0,2,0,0,0,0,0,0,0,2,2,2,0,0,0,2,0,0,0,0,0,0,0,0,2,
+    0,0,1,0,0,0,0,2,1,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,
+    0,3,0,2,0,0,0,0,0,0,0,0,2,0,0,0,0,0,2,0,0,0,0,0,0,0,2,0,0,0,0,2,
+    0,0,2,0,0,0,0,2,2,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,2,0,2,2,1,0,0,0,0,0,0,2,0,0,2,0,2,2,2,0,0,0,0,0,0,2,0,0,0,0,2,
+    0,0,2,0,0,2,0,2,2,0,0,0,0,2,0,2,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0,
+    0,0,3,0,0,0,2,2,0,2,2,0,0,0,0,0,2,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,2,0,0,0,0,0,
+    0,2,2,2,2,2,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,1,
+    0,0,0,0,0,0,0,2,1,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,2,2,0,0,0,0,0,2,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,
+    0,2,0,0,0,2,0,0,0,0,0,1,0,0,0,0,2,2,0,0,0,1,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,2,0,0,0,
+    0,2,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,2,0,2,0,0,0,
+    0,0,0,0,0,0,0,0,2,1,0,0,0,0,0,0,2,0,0,0,1,2,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  ]
+
+  Latin7GreekModel = { 
+  'charToOrderMap' =>  Latin7_CharToOrderMap,
+  'precedenceMatrix' =>  GreekLangModel,
+  'mTypicalPositiveRatio' =>  0.982851,
+  'keepEnglishLetter' =>  false,
+  'charsetName' =>  "ISO-8859-7"
+  }
+
+  Win1253GreekModel = { 
+  'charToOrderMap' => Win1253_CharToOrderMap,
+  'precedenceMatrix' => GreekLangModel,
+  'mTypicalPositiveRatio' => 0.982851,
+  'keepEnglishLetter' => false,
+  'charsetName' => "windows-1253"
+  }
+end
diff --git a/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/langhebrewmodel.rb b/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/langhebrewmodel.rb
new file mode 100644 (file)
index 0000000..37b3b2d
--- /dev/null
@@ -0,0 +1,202 @@
+######################## BEGIN LICENSE BLOCK ########################
+# The Original Code is Mozilla Universal charset detector code.
+#
+# The Initial Developer of the Original Code is
+#          Simon Montagu
+# Portions created by the Initial Developer are Copyright (C) 2005
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Jeff Hodges - port to Ruby
+#   Mark Pilgrim - port to Python
+#   Shy Shalom - original C code
+#   Shoshannah Forbes - original C code (?)
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+# 
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301  USA
+######################### END LICENSE BLOCK #########################
+
+module CharDet
+# 255: Control characters that usually does not exist in any text
+# 254: Carriage/Return
+# 253: symbol (punctuation) that does not belong to word
+# 252: 0 - 9
+
+# Windows-1255 language model
+# Character Mapping Table:
+Win1255_CharToOrderMap = [
+255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255,  # 00
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  # 10
+253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,  # 20
+252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253,  # 30
+253, 69, 91, 79, 80, 92, 89, 97, 90, 68,111,112, 82, 73, 95, 85,  # 40
+ 78,121, 86, 71, 67,102,107, 84,114,103,115,253,253,253,253,253,  # 50
+253, 50, 74, 60, 61, 42, 76, 70, 64, 53,105, 93, 56, 65, 54, 49,  # 60
+ 66,110, 51, 43, 44, 63, 81, 77, 98, 75,108,253,253,253,253,253,  # 70
+124,202,203,204,205, 40, 58,206,207,208,209,210,211,212,213,214,
+215, 83, 52, 47, 46, 72, 32, 94,216,113,217,109,218,219,220,221,
+ 34,116,222,118,100,223,224,117,119,104,125,225,226, 87, 99,227,
+106,122,123,228, 55,229,230,101,231,232,120,233, 48, 39, 57,234,
+ 30, 59, 41, 88, 33, 37, 36, 31, 29, 35,235, 62, 28,236,126,237,
+238, 38, 45,239,240,241,242,243,127,244,245,246,247,248,249,250,
+  9,  8, 20, 16,  3,  2, 24, 14, 22,  1, 25, 15,  4, 11,  6, 23,
+ 12, 19, 13, 26, 18, 27, 21, 17,  7, 10,  5,251,252,128, 96,253,
+]
+
+# Model Table: 
+# total sequences: 100%
+# first 512 sequences: 98.4004%
+# first 1024 sequences: 1.5981%
+# rest  sequences:      0.087%
+# negative sequences:   0.0015% 
+HebrewLangModel = [
+0,3,3,3,3,3,3,3,3,3,3,2,3,3,3,3,3,3,3,3,3,3,3,2,3,2,1,2,0,1,0,0,
+3,0,3,1,0,0,1,3,2,0,1,1,2,0,2,2,2,1,1,1,1,2,1,1,1,2,0,0,2,2,0,1,
+3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,2,2,
+1,2,1,2,1,2,0,0,2,0,0,0,0,0,1,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,
+3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,2,
+1,2,1,3,1,1,0,0,2,0,0,0,1,0,1,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,
+3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,0,1,2,2,1,3,
+1,2,1,1,2,2,0,0,2,2,0,0,0,0,1,0,1,0,0,0,1,0,0,0,0,0,0,1,0,1,1,0,
+3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,3,2,2,2,2,3,2,
+1,2,1,2,2,2,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,
+3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,3,2,3,2,2,3,2,2,2,1,2,2,2,2,
+1,2,1,1,2,2,0,1,2,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,
+3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,0,2,2,2,2,2,
+0,2,0,2,2,2,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,
+3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,0,2,2,2,
+0,2,1,2,2,2,0,0,2,1,0,0,0,0,1,0,1,0,0,0,0,0,0,2,0,0,0,0,0,0,1,0,
+3,3,3,3,3,3,3,3,3,3,3,2,3,3,3,3,3,3,3,3,3,3,3,3,3,2,1,2,3,2,2,2,
+1,2,1,2,2,2,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,1,0,
+3,3,3,3,3,3,3,3,3,2,3,3,3,2,3,3,3,3,3,3,3,3,3,3,3,3,3,1,0,2,0,2,
+0,2,1,2,2,2,0,0,1,2,0,0,0,0,1,0,1,0,0,0,0,0,0,1,0,0,0,2,0,0,1,0,
+3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,2,3,2,2,3,2,1,2,1,1,1,
+0,1,1,1,1,1,3,0,1,0,0,0,0,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,
+3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,0,1,1,0,0,1,0,0,1,0,0,0,0,
+0,0,1,0,0,0,0,0,2,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,2,2,2,2,2,
+0,2,0,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,
+3,3,3,3,3,3,3,3,3,2,3,3,3,2,1,2,3,3,2,3,3,3,3,2,3,2,1,2,0,2,1,2,
+0,2,0,2,2,2,0,0,1,2,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,
+3,3,3,3,3,3,3,3,3,2,3,3,3,1,2,2,3,3,2,3,2,3,2,2,3,1,2,2,0,2,2,2,
+0,2,1,2,2,2,0,0,1,2,0,0,0,0,1,0,0,0,0,0,1,0,0,1,0,0,0,1,0,0,1,0,
+3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,3,3,2,3,3,2,2,2,3,3,3,3,1,3,2,2,2,
+0,2,0,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,
+3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,3,3,3,2,3,2,2,2,1,2,2,0,2,2,2,2,
+0,2,0,2,2,2,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,
+3,3,3,3,3,3,3,3,3,3,3,2,3,3,3,1,3,2,3,3,2,3,3,2,2,1,2,2,2,2,2,2,
+0,2,1,2,1,2,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,1,0,
+3,3,3,3,3,3,2,3,2,3,3,2,3,3,3,3,2,3,2,3,3,3,3,3,2,2,2,2,2,2,2,1,
+0,2,0,1,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,
+3,3,3,3,3,3,3,3,3,2,1,2,3,3,3,3,3,3,3,2,3,2,3,2,1,2,3,0,2,1,2,2,
+0,2,1,1,2,1,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,2,0,
+3,3,3,3,3,3,3,3,3,2,3,3,3,3,2,1,3,1,2,2,2,1,2,3,3,1,2,1,2,2,2,2,
+0,1,1,1,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,2,0,0,0,0,0,0,0,0,
+3,3,3,3,3,3,3,3,3,3,0,2,3,3,3,1,3,3,3,1,2,2,2,2,1,1,2,2,2,2,2,2,
+0,2,0,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,
+3,3,3,3,3,3,2,3,3,3,2,2,3,3,3,2,1,2,3,2,3,2,2,2,2,1,2,1,1,1,2,2,
+0,2,1,1,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,
+3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,0,0,1,0,0,0,0,0,
+1,0,1,0,0,0,0,0,2,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+3,3,3,3,3,2,3,3,2,3,1,2,2,2,2,3,2,3,1,1,2,2,1,2,2,1,1,0,2,2,2,2,
+0,1,0,1,2,2,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,
+3,0,0,1,1,0,1,0,0,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,2,0,
+0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+3,0,1,0,1,0,1,1,0,1,1,0,0,0,1,1,0,1,1,1,0,0,0,0,0,0,1,0,0,0,0,0,
+0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+3,0,0,0,1,1,0,1,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,
+3,2,2,1,2,2,2,2,2,2,2,1,2,2,1,2,2,1,1,1,1,1,1,1,1,2,1,1,0,3,3,3,
+0,3,0,2,2,2,2,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,
+2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,1,2,2,2,1,1,1,2,0,1,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,0,2,2,0,0,0,0,0,0,
+0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+2,3,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,1,0,2,1,0,
+0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+3,1,1,1,1,1,1,1,1,1,1,0,0,1,1,1,1,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,
+0,3,1,1,2,2,2,2,2,1,2,2,2,1,1,2,2,2,2,2,2,2,1,2,2,1,0,1,1,1,1,0,
+0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+3,2,1,1,1,1,2,1,1,2,1,0,1,1,1,1,1,1,1,1,1,1,1,0,1,0,0,0,0,0,0,0,
+0,0,2,0,0,0,0,0,0,0,0,1,1,0,0,0,0,1,1,0,0,1,1,0,0,0,0,0,0,1,0,0,
+2,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,2,1,2,1,1,1,1,0,0,0,0,
+0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+1,2,1,2,2,2,2,2,2,2,2,2,2,1,2,1,2,1,1,2,1,1,1,2,1,2,1,2,0,1,0,1,
+0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,3,1,2,2,2,1,2,2,2,2,2,2,2,2,1,2,1,1,1,1,1,1,2,1,2,1,1,0,1,0,1,
+0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+2,1,2,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,
+0,2,0,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,
+3,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+2,1,1,1,1,1,1,1,0,1,1,0,1,0,0,1,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,2,0,1,1,1,0,1,0,0,0,1,1,0,1,1,0,0,0,0,0,1,1,0,0,
+0,1,1,1,2,1,2,2,2,0,2,0,2,0,1,1,2,1,1,1,1,2,1,0,1,1,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,
+1,0,1,0,0,0,0,0,1,0,1,2,2,0,1,0,0,1,1,2,2,1,2,0,2,0,0,0,1,2,0,1,
+2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,2,0,2,1,2,0,2,0,0,1,1,1,1,1,1,0,1,0,0,0,1,0,0,1,
+2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,1,0,0,0,0,0,1,0,2,1,1,0,1,0,0,1,1,1,2,2,0,0,1,0,0,0,1,0,0,1,
+1,1,2,1,0,1,1,1,0,1,0,1,1,1,1,0,0,0,1,0,1,0,0,0,0,0,0,0,0,2,2,1,
+0,2,0,1,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+2,1,0,0,1,0,1,1,1,1,0,0,0,0,0,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+1,1,1,1,1,1,1,1,1,2,1,0,1,1,1,1,1,1,1,1,1,1,1,0,1,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,1,1,1,0,1,1,0,1,0,0,0,1,1,0,1,
+2,0,1,0,1,0,1,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,1,0,1,1,1,0,1,0,0,1,1,2,1,1,2,0,1,0,0,0,1,1,0,1,
+1,0,0,1,0,0,1,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,1,0,1,1,2,0,1,0,0,0,0,2,1,1,2,0,2,0,0,0,1,1,0,1,
+1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,1,0,2,1,1,0,1,0,0,2,2,1,2,1,1,0,1,0,0,0,1,1,0,1,
+2,0,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,1,2,2,0,0,0,0,0,1,1,0,1,0,0,1,0,0,0,0,1,0,1,
+1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,1,2,2,0,0,0,0,2,1,1,1,0,2,1,1,0,0,0,2,1,0,1,
+1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,1,0,1,1,2,0,1,0,0,1,1,0,2,1,1,0,1,0,0,0,1,1,0,1,
+2,2,1,1,1,0,1,1,0,1,1,0,1,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,1,0,2,1,1,0,1,0,0,1,1,0,1,2,1,0,2,0,0,0,1,1,0,1,
+2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,
+0,1,0,0,2,0,2,1,1,0,1,0,1,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,0,0,1,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,1,0,1,1,2,0,1,0,0,1,1,1,0,1,0,0,1,0,0,0,1,0,0,1,
+1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+1,0,0,0,0,0,0,0,1,0,1,1,0,0,1,0,0,2,1,1,1,1,1,0,1,0,0,0,0,1,0,1,
+0,1,1,1,2,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,1,2,1,0,0,0,0,0,1,1,1,1,1,0,1,0,0,0,1,1,0,0,
+]
+
+Win1255HebrewModel = { 
+  'charToOrderMap' =>  Win1255_CharToOrderMap,
+  'precedenceMatrix' =>  HebrewLangModel,
+  'mTypicalPositiveRatio' =>  0.984004,
+  'keepEnglishLetter' =>  false,
+  'charsetName' =>  "windows-1255"
+}
+end
diff --git a/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/langhungarianmodel.rb b/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/langhungarianmodel.rb
new file mode 100644 (file)
index 0000000..1150595
--- /dev/null
@@ -0,0 +1,226 @@
+######################## BEGIN LICENSE BLOCK ########################
+# The Original Code is Mozilla Communicator client code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Jeff Hodges - port to Ruby
+#   Mark Pilgrim - port to Python
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+# 
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301  USA
+######################### END LICENSE BLOCK #########################
+
+module CharDet
+# 255: Control characters that usually does not exist in any text
+# 254: Carriage/Return
+# 253: symbol (punctuation) that does not belong to word
+# 252: 0 - 9
+
+# Character Mapping Table:
+Latin2_HungarianCharToOrderMap = [
+255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255,  # 00
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  # 10
+253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,  # 20
+252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253,  # 30
+253, 28, 40, 54, 45, 32, 50, 49, 38, 39, 53, 36, 41, 34, 35, 47,
+ 46, 71, 43, 33, 37, 57, 48, 64, 68, 55, 52,253,253,253,253,253,
+253,  2, 18, 26, 17,  1, 27, 12, 20,  9, 22,  7,  6, 13,  4,  8,
+ 23, 67, 10,  5,  3, 21, 19, 65, 62, 16, 11,253,253,253,253,253,
+159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,
+175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,
+191,192,193,194,195,196,197, 75,198,199,200,201,202,203,204,205,
+ 79,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,
+221, 51, 81,222, 78,223,224,225,226, 44,227,228,229, 61,230,231,
+232,233,234, 58,235, 66, 59,236,237,238, 60, 69, 63,239,240,241,
+ 82, 14, 74,242, 70, 80,243, 72,244, 15, 83, 77, 84, 30, 76, 85,
+245,246,247, 25, 73, 42, 24,248,249,250, 31, 56, 29,251,252,253,
+]
+
+Win1250HungarianCharToOrderMap = [
+255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255,  # 00
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  # 10
+253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,  # 20
+252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253,  # 30
+253, 28, 40, 54, 45, 32, 50, 49, 38, 39, 53, 36, 41, 34, 35, 47,
+ 46, 72, 43, 33, 37, 57, 48, 64, 68, 55, 52,253,253,253,253,253,
+253,  2, 18, 26, 17,  1, 27, 12, 20,  9, 22,  7,  6, 13,  4,  8,
+ 23, 67, 10,  5,  3, 21, 19, 65, 62, 16, 11,253,253,253,253,253,
+161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,
+177,178,179,180, 78,181, 69,182,183,184,185,186,187,188,189,190,
+191,192,193,194,195,196,197, 76,198,199,200,201,202,203,204,205,
+ 81,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,
+221, 51, 83,222, 80,223,224,225,226, 44,227,228,229, 61,230,231,
+232,233,234, 58,235, 66, 59,236,237,238, 60, 70, 63,239,240,241,
+ 84, 14, 75,242, 71, 82,243, 73,244, 15, 85, 79, 86, 30, 77, 87,
+245,246,247, 25, 74, 42, 24,248,249,250, 31, 56, 29,251,252,253,
+]
+
+# Model Table: 
+# total sequences: 100%
+# first 512 sequences: 94.7368%
+# first 1024 sequences:5.2623%
+# rest  sequences:     0.8894%
+# negative sequences:  0.0009% 
+HungarianLangModel = [
+0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
+3,3,3,3,3,3,3,3,3,3,2,3,3,3,3,3,3,3,3,2,2,3,3,1,1,2,2,2,2,2,1,2,
+3,2,2,3,3,3,3,3,2,3,3,3,3,3,3,1,2,3,3,3,3,2,3,3,1,1,3,3,0,1,1,1,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,
+3,2,1,3,3,3,3,3,2,3,3,3,3,3,1,1,2,3,3,3,3,3,3,3,1,1,3,2,0,1,1,1,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,
+3,3,3,3,3,3,3,3,3,3,3,1,1,2,3,3,3,1,3,3,3,3,3,1,3,3,2,2,0,3,2,3,
+0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,
+3,3,3,3,3,3,2,3,3,3,2,3,3,2,3,3,3,3,3,2,3,3,2,2,3,2,3,2,0,3,2,2,
+0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,
+3,3,3,3,3,3,2,3,3,3,3,3,2,3,3,3,1,2,3,2,2,3,1,2,3,3,2,2,0,3,3,3,
+0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,
+3,3,3,3,3,3,3,3,3,3,2,2,3,3,3,3,3,3,2,3,3,3,3,2,3,3,3,3,0,2,3,2,
+0,0,0,1,1,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,
+3,3,3,3,3,3,3,3,3,3,3,1,1,1,3,3,2,1,3,2,2,3,2,1,3,2,2,1,0,3,3,1,
+0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,
+3,2,2,3,3,3,3,3,1,2,3,3,3,3,1,2,1,3,3,3,3,2,2,3,1,1,3,2,0,1,1,1,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,
+3,3,3,3,3,3,3,3,2,2,3,3,3,3,3,2,1,3,3,3,3,3,2,2,1,3,3,3,0,1,1,2,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,
+3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,3,3,2,3,3,2,3,3,3,2,0,3,2,3,
+0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,1,0,
+3,3,3,3,3,3,2,3,3,3,2,3,2,3,3,3,1,3,2,2,2,3,1,1,3,3,1,1,0,3,3,2,
+0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,
+3,3,3,3,3,3,3,2,3,3,3,2,3,2,3,3,3,2,3,3,3,3,3,1,2,3,2,2,0,2,2,2,
+0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,
+3,3,3,2,2,2,3,1,3,3,2,2,1,3,3,3,1,1,3,1,2,3,2,3,2,2,2,1,0,2,2,2,
+0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,
+3,1,1,3,3,3,3,3,1,2,3,3,3,3,1,2,1,3,3,3,2,2,3,2,1,0,3,2,0,1,1,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+3,1,1,3,3,3,3,3,1,2,3,3,3,3,1,1,0,3,3,3,3,0,2,3,0,0,2,1,0,1,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+3,3,3,3,3,3,2,2,3,3,2,2,2,2,3,3,0,1,2,3,2,3,2,2,3,2,1,2,0,2,2,2,
+0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,
+3,3,3,3,3,3,1,2,3,3,3,2,1,2,3,3,2,2,2,3,2,3,3,1,3,3,1,1,0,2,3,2,
+0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,
+3,3,3,1,2,2,2,2,3,3,3,1,1,1,3,3,1,1,3,1,1,3,2,1,2,3,1,1,0,2,2,2,
+0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,
+3,3,3,2,1,2,1,1,3,3,1,1,1,1,3,3,1,1,2,2,1,2,1,1,2,2,1,1,0,2,2,1,
+0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,
+3,3,3,1,1,2,1,1,3,3,1,0,1,1,3,3,2,0,1,1,2,3,1,0,2,2,1,0,0,1,3,2,
+0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,
+3,2,1,3,3,3,3,3,1,2,3,2,3,3,2,1,1,3,2,3,2,1,2,2,0,1,2,1,0,0,1,1,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,
+3,3,3,3,2,2,2,2,3,1,2,2,1,1,3,3,0,3,2,1,2,3,2,1,3,3,1,1,0,2,1,3,
+0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,
+3,3,3,2,2,2,3,2,3,3,3,2,1,1,3,3,1,1,1,2,2,3,2,3,2,2,2,1,0,2,2,1,
+0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,
+1,0,0,3,3,3,3,3,0,0,3,3,2,3,0,0,0,2,3,3,1,0,1,2,0,0,1,1,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+3,1,2,3,3,3,3,3,1,2,3,3,2,2,1,1,0,3,3,2,2,1,2,2,1,0,2,2,0,1,1,1,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+3,3,2,2,1,3,1,2,3,3,2,2,1,1,2,2,1,1,1,1,3,2,1,1,1,1,2,1,0,1,2,1,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,
+2,3,3,1,1,1,1,1,3,3,3,0,1,1,3,3,1,1,1,1,1,2,2,0,3,1,1,2,0,2,1,1,
+0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,
+3,1,0,1,2,1,2,2,0,1,2,3,1,2,0,0,0,2,1,1,1,1,1,2,0,0,1,1,0,0,0,0,
+1,2,1,2,2,2,1,2,1,2,0,2,0,2,2,1,1,2,1,1,2,1,1,1,0,1,0,0,0,1,1,0,
+1,1,1,2,3,2,3,3,0,1,2,2,3,1,0,1,0,2,1,2,2,0,1,1,0,0,1,1,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+1,0,0,3,3,2,2,1,0,0,3,2,3,2,0,0,0,1,1,3,0,0,1,1,0,0,2,1,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+3,1,1,2,2,3,3,1,0,1,3,2,3,1,1,1,0,1,1,1,1,1,3,1,0,0,2,2,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+3,1,1,1,2,2,2,1,0,1,2,3,3,2,0,0,0,2,1,1,1,2,1,1,1,0,1,1,1,0,0,0,
+1,2,2,2,2,2,1,1,1,2,0,2,1,1,1,1,1,2,1,1,1,1,1,1,0,1,1,1,0,0,1,1,
+3,2,2,1,0,0,1,1,2,2,0,3,0,1,2,1,1,0,0,1,1,1,0,1,1,1,1,0,2,1,1,1,
+2,2,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,2,3,1,1,1,1,1,1,1,1,1,0,1,
+2,3,3,0,1,0,0,0,3,3,1,0,0,1,2,2,1,0,0,0,0,2,0,0,1,1,1,0,2,1,1,1,
+2,1,1,1,1,1,1,2,1,1,0,1,1,0,1,1,1,0,1,2,1,1,0,1,1,1,1,1,1,1,0,1,
+2,3,3,0,1,0,0,0,2,2,0,0,0,0,1,2,2,0,0,0,0,1,0,0,1,1,0,0,2,0,1,0,
+2,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,2,0,1,1,1,1,1,0,1,
+3,2,2,0,1,0,1,0,2,3,2,0,0,1,2,2,1,0,0,1,1,1,0,0,2,1,0,1,2,2,1,1,
+2,1,1,1,1,1,1,2,1,1,1,1,1,1,0,2,1,0,1,1,0,1,1,1,0,1,1,2,1,1,0,1,
+2,2,2,0,0,1,0,0,2,2,1,1,0,0,2,1,1,0,0,0,1,2,0,0,2,1,0,0,2,1,1,1,
+2,1,1,1,1,2,1,2,1,1,1,2,2,1,1,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,0,1,
+1,2,3,0,0,0,1,0,3,2,1,0,0,1,2,1,1,0,0,0,0,2,1,0,1,1,0,0,2,1,2,1,
+1,1,0,0,0,1,0,1,1,1,1,1,2,0,0,1,0,0,0,2,0,0,1,1,1,1,1,1,1,1,0,1,
+3,0,0,2,1,2,2,1,0,0,2,1,2,2,0,0,0,2,1,1,1,0,1,1,0,0,1,1,2,0,0,0,
+1,2,1,2,2,1,1,2,1,2,0,1,1,1,1,1,1,1,1,1,2,1,1,0,0,1,1,1,1,0,0,1,
+1,3,2,0,0,0,1,0,2,2,2,0,0,0,2,2,1,0,0,0,0,3,1,1,1,1,0,0,2,1,1,1,
+2,1,0,1,1,1,0,1,1,1,1,1,1,1,0,2,1,0,0,1,0,1,1,0,1,1,1,1,1,1,0,1,
+2,3,2,0,0,0,1,0,2,2,0,0,0,0,2,1,1,0,0,0,0,2,1,0,1,1,0,0,2,1,1,0,
+2,1,1,1,1,2,1,2,1,2,0,1,1,1,0,2,1,1,1,2,1,1,1,1,0,1,1,1,1,1,0,1,
+3,1,1,2,2,2,3,2,1,1,2,2,1,1,0,1,0,2,2,1,1,1,1,1,0,0,1,1,0,1,1,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+2,2,2,0,0,0,0,0,2,2,0,0,0,0,2,2,1,0,0,0,1,1,0,0,1,2,0,0,2,1,1,1,
+2,2,1,1,1,2,1,2,1,1,0,1,1,1,1,2,1,1,1,2,1,1,1,1,0,1,2,1,1,1,0,1,
+1,0,0,1,2,3,2,1,0,0,2,0,1,1,0,0,0,1,1,1,1,0,1,1,0,0,1,0,0,0,0,0,
+1,2,1,2,1,2,1,1,1,2,0,2,1,1,1,0,1,2,0,0,1,1,1,0,0,0,0,0,0,0,0,0,
+2,3,2,0,0,0,0,0,1,1,2,1,0,0,1,1,1,0,0,0,0,2,0,0,1,1,0,0,2,1,1,1,
+2,1,1,1,1,1,1,2,1,0,1,1,1,1,0,2,1,1,1,1,1,1,0,1,0,1,1,1,1,1,0,1,
+1,2,2,0,1,1,1,0,2,2,2,0,0,0,3,2,1,0,0,0,1,1,0,0,1,1,0,1,1,1,0,0,
+1,1,0,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,0,0,1,1,1,0,1,0,1,
+2,1,0,2,1,1,2,2,1,1,2,1,1,1,0,0,0,1,1,0,1,1,1,1,0,0,1,1,1,0,0,0,
+1,2,2,2,2,2,1,1,1,2,0,2,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,0,0,0,1,0,
+1,2,3,0,0,0,1,0,2,2,0,0,0,0,2,2,0,0,0,0,0,1,0,0,1,0,0,0,2,0,1,0,
+2,1,1,1,1,1,0,2,0,0,0,1,2,1,1,1,1,0,1,2,0,1,0,1,0,1,1,1,0,1,0,1,
+2,2,2,0,0,0,1,0,2,1,2,0,0,0,1,1,2,0,0,0,0,1,0,0,1,1,0,0,2,1,0,1,
+2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,0,1,1,1,1,1,0,1,
+1,2,2,0,0,0,1,0,2,2,2,0,0,0,1,1,0,0,0,0,0,1,1,0,2,0,0,1,1,1,0,1,
+1,0,1,1,1,1,1,1,0,1,1,1,1,0,0,1,0,0,1,1,0,1,0,1,1,1,1,1,0,0,0,1,
+1,0,0,1,0,1,2,1,0,0,1,1,1,2,0,0,0,1,1,0,1,0,1,1,0,0,1,0,0,0,0,0,
+0,2,1,2,1,1,1,1,1,2,0,2,0,1,1,0,1,2,1,0,1,1,1,0,0,0,0,0,0,1,0,0,
+2,1,1,0,1,2,0,0,1,1,1,0,0,0,1,1,0,0,0,0,0,1,0,0,1,0,0,0,2,1,0,1,
+2,2,1,1,1,1,1,2,1,1,0,1,1,1,1,2,1,1,1,2,1,1,0,1,0,1,1,1,1,1,0,1,
+1,2,2,0,0,0,0,0,1,1,0,0,0,0,2,1,0,0,0,0,0,2,0,0,2,2,0,0,2,0,0,1,
+2,1,1,1,1,1,1,1,0,1,1,0,1,1,0,1,0,0,0,1,1,1,1,0,0,1,1,1,1,0,0,1,
+1,1,2,0,0,3,1,0,2,1,1,1,0,0,1,1,1,0,0,0,1,1,0,0,0,1,0,0,1,0,1,0,
+1,2,1,0,1,1,1,2,1,1,0,1,1,1,1,1,0,0,0,1,1,1,1,1,0,1,0,0,0,1,0,0,
+2,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,1,0,0,0,1,0,0,0,0,2,0,0,0,
+2,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,2,1,1,0,0,1,1,1,1,1,0,1,
+2,1,1,1,2,1,1,1,0,1,1,2,1,0,0,0,0,1,1,1,1,0,1,0,0,0,0,1,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+1,1,0,1,1,1,1,1,0,0,1,1,2,1,0,0,0,1,1,0,0,0,1,1,0,0,1,0,1,0,0,0,
+1,2,1,1,1,1,1,1,1,1,0,1,0,1,1,1,1,1,1,0,1,1,1,0,0,0,0,0,0,1,0,0,
+2,0,0,0,1,1,1,1,0,0,1,1,0,0,0,0,0,1,1,1,2,0,0,1,0,0,1,0,1,0,0,0,
+0,1,1,1,1,1,1,1,1,2,0,1,1,1,1,0,1,1,1,0,1,1,1,0,0,0,0,0,0,0,0,0,
+1,0,0,1,1,1,1,1,0,0,2,1,0,1,0,0,0,1,0,1,0,0,0,0,0,0,1,0,0,0,0,0,
+0,1,1,1,1,1,1,0,1,1,0,1,0,1,1,0,1,1,0,0,1,1,1,0,0,0,0,0,0,0,0,0,
+1,0,0,1,1,1,0,0,0,0,1,0,2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,
+0,1,1,1,1,1,0,0,1,1,0,1,0,1,0,0,1,1,1,0,1,1,1,0,0,0,0,0,0,0,0,0,
+0,0,0,1,0,0,0,0,0,0,1,1,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,1,1,1,0,1,0,0,1,1,0,1,0,1,1,0,1,1,1,0,1,1,1,0,0,0,0,0,0,0,0,0,
+2,1,1,1,1,1,1,1,1,1,1,0,0,1,1,1,0,0,1,0,0,1,0,1,0,1,1,1,0,0,1,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+1,0,0,1,1,1,1,0,0,0,1,1,1,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,
+0,1,1,1,1,1,1,0,1,1,0,1,0,1,0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,
+]
+
+Latin2HungarianModel = { 
+  'charToOrderMap' =>  Latin2_HungarianCharToOrderMap,
+  'precedenceMatrix' =>  HungarianLangModel,
+  'mTypicalPositiveRatio' =>  0.947368,
+  'keepEnglishLetter' =>  true,
+  'charsetName' =>  "ISO-8859-2"
+}
+
+Win1250HungarianModel = { 
+  'charToOrderMap' =>  Win1250HungarianCharToOrderMap,
+  'precedenceMatrix' =>  HungarianLangModel,
+  'mTypicalPositiveRatio' =>  0.947368,
+  'keepEnglishLetter' =>  true,
+  'charsetName' =>  "windows-1250"
+}
+end
diff --git a/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/langthaimodel.rb b/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/langthaimodel.rb
new file mode 100644 (file)
index 0000000..d430df3
--- /dev/null
@@ -0,0 +1,201 @@
+######################## BEGIN LICENSE BLOCK ########################
+# The Original Code is Mozilla Communicator client code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Jeff Hodges - port to Ruby
+#   Mark Pilgrim - port to Python
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+# 
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301  USA
+######################### END LICENSE BLOCK #########################
+
+module CharDet
+# 255: Control characters that usually does not exist in any text
+# 254: Carriage/Return
+# 253: symbol (punctuation) that does not belong to word
+# 252: 0 - 9
+
+# The following result for thai was collected from a limited sample (1M). 
+
+# Character Mapping Table:
+TIS620CharToOrderMap = [
+255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255,  # 00
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  # 10
+253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,  # 20
+252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253,  # 30
+253,182,106,107,100,183,184,185,101, 94,186,187,108,109,110,111,  # 40
+188,189,190, 89, 95,112,113,191,192,193,194,253,253,253,253,253,  # 50
+253, 64, 72, 73,114, 74,115,116,102, 81,201,117, 90,103, 78, 82,  # 60
+ 96,202, 91, 79, 84,104,105, 97, 98, 92,203,253,253,253,253,253,  # 70
+209,210,211,212,213, 88,214,215,216,217,218,219,220,118,221,222,
+223,224, 99, 85, 83,225,226,227,228,229,230,231,232,233,234,235,
+236,  5, 30,237, 24,238, 75,  8, 26, 52, 34, 51,119, 47, 58, 57,
+ 49, 53, 55, 43, 20, 19, 44, 14, 48,  3, 17, 25, 39, 62, 31, 54,
+ 45,  9, 16,  2, 61, 15,239, 12, 42, 46, 18, 21, 76,  4, 66, 63,
+ 22, 10,  1, 36, 23, 13, 40, 27, 32, 35, 86,240,241,242,243,244,
+ 11, 28, 41, 29, 33,245, 50, 37,  6,  7, 67, 77, 38, 93,246,247,
+ 68, 56, 59, 65, 69, 60, 70, 80, 71, 87,248,249,250,251,252,253,
+]
+
+# Model Table: 
+# total sequences: 100%
+# first 512 sequences: 92.6386%
+# first 1024 sequences:7.3177%
+# rest  sequences:     1.0230%
+# negative sequences:  0.0436% 
+ThaiLangModel = [
+0,1,3,3,3,3,0,0,3,3,0,3,3,0,3,3,3,3,3,3,3,3,0,0,3,3,3,0,3,3,3,3,
+0,3,3,0,0,0,1,3,0,3,3,2,3,3,0,1,2,3,3,3,3,0,2,0,2,0,0,3,2,1,2,2,
+3,0,3,3,2,3,0,0,3,3,0,3,3,0,3,3,3,3,3,3,3,3,3,0,3,2,3,0,2,2,2,3,
+0,2,3,0,0,0,0,1,0,1,2,3,1,1,3,2,2,0,1,1,0,0,1,0,0,0,0,0,0,0,1,1,
+3,3,3,2,3,3,3,3,3,3,3,3,3,3,3,2,2,2,2,2,2,2,3,3,2,3,2,3,3,2,2,2,
+3,1,2,3,0,3,3,2,2,1,2,3,3,1,2,0,1,3,0,1,0,0,1,0,0,0,0,0,0,0,1,1,
+3,3,2,2,3,3,3,3,1,2,3,3,3,3,3,2,2,2,2,3,3,2,2,3,3,2,2,3,2,3,2,2,
+3,3,1,2,3,1,2,2,3,3,1,0,2,1,0,0,3,1,2,1,0,0,1,0,0,0,0,0,0,1,0,1,
+3,3,3,3,3,3,2,2,3,3,3,3,2,3,2,2,3,3,2,2,3,2,2,2,2,1,1,3,1,2,1,1,
+3,2,1,0,2,1,0,1,0,1,1,0,1,1,0,0,1,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,
+3,3,3,2,3,2,3,3,2,2,3,2,3,3,2,3,1,1,2,3,2,2,2,3,2,2,2,2,2,1,2,1,
+2,2,1,1,3,3,2,1,0,1,2,2,0,1,3,0,0,0,1,1,0,0,0,0,0,2,3,0,0,2,1,1,
+3,3,2,3,3,2,0,0,3,3,0,3,3,0,2,2,3,1,2,2,1,1,1,0,2,2,2,0,2,2,1,1,
+0,2,1,0,2,0,0,2,0,1,0,0,1,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1,0,
+3,3,2,3,3,2,0,0,3,3,0,2,3,0,2,1,2,2,2,2,1,2,0,0,2,2,2,0,2,2,1,1,
+0,2,1,0,2,0,0,2,0,1,1,0,1,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,
+3,3,2,3,2,3,2,0,2,2,1,3,2,1,3,2,1,2,3,2,2,3,0,2,3,2,2,1,2,2,2,2,
+1,2,2,0,0,0,0,2,0,1,2,0,1,1,1,0,1,0,3,1,1,0,0,0,0,0,0,0,0,0,1,0,
+3,3,2,3,3,2,3,2,2,2,3,2,2,3,2,2,1,2,3,2,2,3,1,3,2,2,2,3,2,2,2,3,
+3,2,1,3,0,1,1,1,0,2,1,1,1,1,1,0,1,0,1,1,0,0,0,0,0,0,0,0,0,2,0,0,
+1,0,0,3,0,3,3,3,3,3,0,0,3,0,2,2,3,3,3,3,3,0,0,0,1,1,3,0,0,0,0,2,
+0,0,1,0,0,0,0,0,0,0,2,3,0,0,0,3,0,2,0,0,0,0,0,3,0,0,0,0,0,0,0,0,
+2,0,3,3,3,3,0,0,2,3,0,0,3,0,3,3,2,3,3,3,3,3,0,0,3,3,3,0,0,0,3,3,
+0,0,3,0,0,0,0,2,0,0,2,1,1,3,0,0,1,0,0,2,3,0,1,0,0,0,0,0,0,0,1,0,
+3,3,3,3,2,3,3,3,3,3,3,3,1,2,1,3,3,2,2,1,2,2,2,3,1,1,2,0,2,1,2,1,
+2,2,1,0,0,0,1,1,0,1,0,1,1,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,
+3,0,2,1,2,3,3,3,0,2,0,2,2,0,2,1,3,2,2,1,2,1,0,0,2,2,1,0,2,1,2,2,
+0,1,1,0,0,0,0,1,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,
+3,3,3,3,2,1,3,3,1,1,3,0,2,3,1,1,3,2,1,1,2,0,2,2,3,2,1,1,1,1,1,2,
+3,0,0,1,3,1,2,1,2,0,3,0,0,0,1,0,3,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,
+3,3,1,1,3,2,3,3,3,1,3,2,1,3,2,1,3,2,2,2,2,1,3,3,1,2,1,3,1,2,3,0,
+2,1,1,3,2,2,2,1,2,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,
+3,3,2,3,2,3,3,2,3,2,3,2,3,3,2,1,0,3,2,2,2,1,2,2,2,1,2,2,1,2,1,1,
+2,2,2,3,0,1,3,1,1,1,1,0,1,1,0,2,1,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,
+3,3,3,3,2,3,2,2,1,1,3,2,3,2,3,2,0,3,2,2,1,2,0,2,2,2,1,2,2,2,2,1,
+3,2,1,2,2,1,0,2,0,1,0,0,1,1,0,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,1,
+3,3,3,3,3,2,3,1,2,3,3,2,2,3,0,1,1,2,0,3,3,2,2,3,0,1,1,3,0,0,0,0,
+3,1,0,3,3,0,2,0,2,1,0,0,3,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+3,3,3,2,3,2,3,3,0,1,3,1,1,2,1,2,1,1,3,1,1,0,2,3,1,1,1,1,1,1,1,1,
+3,1,1,2,2,2,2,1,1,1,0,0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
+3,2,2,1,1,2,1,3,3,2,3,2,2,3,2,2,3,1,2,2,1,2,0,3,2,1,2,2,2,2,2,1,
+3,2,1,2,2,2,1,1,1,1,0,0,1,1,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,
+3,3,3,3,3,3,3,3,1,3,3,0,2,1,0,3,2,0,0,3,1,0,1,1,0,1,0,0,0,0,0,1,
+1,0,0,1,0,3,2,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+3,0,2,2,2,3,0,0,1,3,0,3,2,0,3,2,2,3,3,3,3,3,1,0,2,2,2,0,2,2,1,2,
+0,2,3,0,0,0,0,1,0,1,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
+3,0,2,3,1,3,3,2,3,3,0,3,3,0,3,2,2,3,2,3,3,3,0,0,2,2,3,0,1,1,1,3,
+0,0,3,0,0,0,2,2,0,1,3,0,1,2,2,2,3,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,
+3,2,3,3,2,0,3,3,2,2,3,1,3,2,1,3,2,0,1,2,2,0,2,3,2,1,0,3,0,0,0,0,
+3,0,0,2,3,1,3,0,0,3,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+3,1,3,2,2,2,1,2,0,1,3,1,1,3,1,3,0,0,2,1,1,1,1,2,1,1,1,0,2,1,0,1,
+1,2,0,0,0,3,1,1,0,0,0,0,1,0,1,0,0,1,0,1,0,0,0,0,0,3,1,0,0,0,1,0,
+3,3,3,3,2,2,2,2,2,1,3,1,1,1,2,0,1,1,2,1,2,1,3,2,0,0,3,1,1,1,1,1,
+3,1,0,2,3,0,0,0,3,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,2,3,0,3,3,0,2,0,0,0,0,0,0,0,3,0,0,1,0,0,0,0,0,0,0,0,0,0,0,
+0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,2,3,1,3,0,0,1,2,0,0,2,0,3,3,2,3,3,3,2,3,0,0,2,2,2,0,0,0,2,2,
+0,0,1,0,0,0,0,3,0,0,0,0,2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,
+0,0,0,3,0,2,0,0,0,0,0,0,0,0,0,0,1,2,3,1,3,3,0,0,1,0,3,0,0,0,0,0,
+0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+3,3,1,2,3,1,2,3,1,0,3,0,2,2,1,0,2,1,1,2,0,1,0,0,1,1,1,1,0,1,0,0,
+1,0,0,0,0,1,1,0,3,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+3,3,3,3,2,1,0,1,1,1,3,1,2,2,2,2,2,2,1,1,1,1,0,3,1,0,1,3,1,1,1,1,
+1,1,0,2,0,1,3,1,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,2,0,1,
+3,0,2,2,1,3,3,2,3,3,0,1,1,0,2,2,1,2,1,3,3,1,0,0,3,2,0,0,0,0,2,1,
+0,1,0,0,0,0,1,2,0,1,1,3,1,1,2,2,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,
+0,0,3,0,0,1,0,0,0,3,0,0,3,0,3,1,0,1,1,1,3,2,0,0,0,3,0,0,0,0,2,0,
+0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,2,0,0,0,0,0,0,0,0,0,
+3,3,1,3,2,1,3,3,1,2,2,0,1,2,1,0,1,2,0,0,0,0,0,3,0,0,0,3,0,0,0,0,
+3,0,0,1,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+3,0,1,2,0,3,3,3,2,2,0,1,1,0,1,3,0,0,0,2,2,0,0,0,0,3,1,0,1,0,0,0,
+0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+3,0,2,3,1,2,0,0,2,1,0,3,1,0,1,2,0,1,1,1,1,3,0,0,3,1,1,0,2,2,1,1,
+0,2,0,0,0,0,0,1,0,1,0,0,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+3,0,0,3,1,2,0,0,2,2,0,1,2,0,1,0,1,3,1,2,1,0,0,0,2,0,3,0,0,0,1,0,
+0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+3,0,1,1,2,2,0,0,0,2,0,2,1,0,1,1,0,1,1,1,2,1,0,0,1,1,1,0,2,1,1,1,
+0,1,1,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,1,
+0,0,0,2,0,1,3,1,1,1,1,0,0,0,0,3,2,0,1,0,0,0,1,2,0,0,0,1,0,0,0,0,
+0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,3,3,3,3,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+1,0,2,3,2,2,0,0,0,1,0,0,0,0,2,3,2,1,2,2,3,0,0,0,2,3,1,0,0,0,1,1,
+0,0,1,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,0,
+3,3,2,2,0,1,0,0,0,0,2,0,2,0,1,0,0,0,1,1,0,0,0,2,1,0,1,0,1,1,0,0,
+0,1,0,2,0,0,1,0,3,0,1,0,0,0,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+3,3,1,0,0,1,0,0,0,0,0,1,1,2,0,0,0,0,1,0,0,1,3,1,0,0,0,0,1,1,0,0,
+0,1,0,0,0,0,3,0,0,0,0,0,0,3,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,
+3,3,1,1,1,1,2,3,0,0,2,1,1,1,1,1,0,2,1,1,0,0,0,2,1,0,1,2,1,1,0,1,
+2,1,0,3,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+1,3,1,0,0,0,0,0,0,0,3,0,0,0,3,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,
+0,0,0,2,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+3,3,2,0,0,0,0,0,0,1,2,1,0,1,1,0,2,0,0,1,0,0,2,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,2,0,0,0,1,3,0,1,0,0,0,2,0,0,0,0,0,0,0,1,2,0,0,0,0,0,
+3,3,0,0,1,1,2,0,0,1,2,1,0,1,1,1,0,1,1,0,0,2,1,1,0,1,0,0,1,1,1,0,
+0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,
+2,2,2,1,0,0,0,0,1,0,0,0,0,3,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,
+2,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+2,3,0,0,1,1,0,0,0,2,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+1,1,0,1,2,0,1,2,0,0,1,1,0,2,0,1,0,0,1,0,0,0,0,1,0,0,0,2,0,0,0,0,
+1,0,0,1,0,1,1,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,1,0,0,0,0,0,0,0,1,1,0,1,1,0,2,1,3,0,0,0,0,1,1,0,0,0,0,0,0,0,3,
+1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+2,0,1,0,1,0,0,2,0,0,2,0,0,1,1,2,0,0,1,1,0,0,0,1,0,0,0,1,1,0,0,0,
+1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,
+1,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,1,1,0,0,0,
+2,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+2,0,0,0,0,2,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,3,0,0,0,
+2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,1,0,0,0,0,
+1,0,0,0,0,0,0,0,0,1,0,0,0,0,2,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,1,1,0,0,2,1,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+]
+
+TIS620ThaiModel = { 
+  'charToOrderMap' =>  TIS620CharToOrderMap,
+  'precedenceMatrix' =>  ThaiLangModel,
+  'mTypicalPositiveRatio' =>  0.926386,
+  'keepEnglishLetter' =>  false,
+  'charsetName' =>  "TIS-620"
+}
+end
diff --git a/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/latin1prober.rb b/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/latin1prober.rb
new file mode 100644 (file)
index 0000000..3f40ff1
--- /dev/null
@@ -0,0 +1,147 @@
+######################## BEGIN LICENSE BLOCK ########################
+# The Original Code is Mozilla Universal charset detector code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 2001
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Jeff Hodges - port to Ruby
+#   Mark Pilgrim - port to Python
+#   Shy Shalom - original C code
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+# 
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301  USA
+######################### END LICENSE BLOCK #########################
+
+module CharDet
+  FREQ_CAT_NUM = 4
+
+  UDF = 0 # undefined
+  OTH = 1 # other
+  ASC = 2 # ascii capital letter
+  ASS = 3 # ascii small letter
+  ACV = 4 # accent capital vowel
+  ACO = 5 # accent capital other
+  ASV = 6 # accent small vowel
+  ASO = 7 # accent small other
+  CLASS_NUM = 8 # total classes
+
+  Latin1_CharToClass = [
+    OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH,   # 00 - 07
+    OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH,   # 08 - 0F
+    OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH,   # 10 - 17
+    OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH,   # 18 - 1F
+    OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH,   # 20 - 27
+    OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH,   # 28 - 2F
+    OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH,   # 30 - 37
+    OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH,   # 38 - 3F
+    OTH, ASC, ASC, ASC, ASC, ASC, ASC, ASC,   # 40 - 47
+    ASC, ASC, ASC, ASC, ASC, ASC, ASC, ASC,   # 48 - 4F
+    ASC, ASC, ASC, ASC, ASC, ASC, ASC, ASC,   # 50 - 57
+    ASC, ASC, ASC, OTH, OTH, OTH, OTH, OTH,   # 58 - 5F
+    OTH, ASS, ASS, ASS, ASS, ASS, ASS, ASS,   # 60 - 67
+    ASS, ASS, ASS, ASS, ASS, ASS, ASS, ASS,   # 68 - 6F
+    ASS, ASS, ASS, ASS, ASS, ASS, ASS, ASS,   # 70 - 77
+    ASS, ASS, ASS, OTH, OTH, OTH, OTH, OTH,   # 78 - 7F
+    OTH, UDF, OTH, ASO, OTH, OTH, OTH, OTH,   # 80 - 87
+    OTH, OTH, ACO, OTH, ACO, UDF, ACO, UDF,   # 88 - 8F
+    UDF, OTH, OTH, OTH, OTH, OTH, OTH, OTH,   # 90 - 97
+    OTH, OTH, ASO, OTH, ASO, UDF, ASO, ACO,   # 98 - 9F
+    OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH,   # A0 - A7
+    OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH,   # A8 - AF
+    OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH,   # B0 - B7
+    OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH,   # B8 - BF
+    ACV, ACV, ACV, ACV, ACV, ACV, ACO, ACO,   # C0 - C7
+    ACV, ACV, ACV, ACV, ACV, ACV, ACV, ACV,   # C8 - CF
+    ACO, ACO, ACV, ACV, ACV, ACV, ACV, OTH,   # D0 - D7
+    ACV, ACV, ACV, ACV, ACV, ACO, ACO, ACO,   # D8 - DF
+    ASV, ASV, ASV, ASV, ASV, ASV, ASO, ASO,   # E0 - E7
+    ASV, ASV, ASV, ASV, ASV, ASV, ASV, ASV,   # E8 - EF
+    ASO, ASO, ASV, ASV, ASV, ASV, ASV, OTH,   # F0 - F7
+    ASV, ASV, ASV, ASV, ASV, ASO, ASO, ASO,   # F8 - FF
+  ]
+
+  # 0 : illegal 
+  # 1 : very unlikely 
+  # 2 : normal 
+  # 3 : very likely
+  Latin1ClassModel = [
+    # UDF OTH ASC ASS ACV ACO ASV ASO
+    0,  0,  0,  0,  0,  0,  0,  0,  # UDF
+    0,  3,  3,  3,  3,  3,  3,  3,  # OTH
+    0,  3,  3,  3,  3,  3,  3,  3,  # ASC
+    0,  3,  3,  3,  1,  1,  3,  3,  # ASS
+    0,  3,  3,  3,  1,  2,  1,  2,  # ACV
+    0,  3,  3,  3,  3,  3,  3,  3,  # ACO
+    0,  3,  1,  3,  1,  1,  1,  3,  # ASV
+    0,  3,  1,  3,  1,  1,  3,  3,  # ASO
+  ]
+
+  class Latin1Prober < CharSetProber
+    def initialize
+      super
+      reset()
+    end
+
+    def reset
+      @_mLastCharClass = OTH
+      @_mFreqCounter = [0] * FREQ_CAT_NUM
+      super
+    end
+
+    def get_charset_name
+      return "windows-1252"
+    end
+
+    def feed(aBuf)
+      aBuf = filter_with_english_letters(aBuf)
+      aBuf.each_byte do |b|
+        c = b.chr
+        charClass = Latin1_CharToClass[c[0]]
+        freq = Latin1ClassModel[(@_mLastCharClass * CLASS_NUM) + charClass]
+        if freq == 0
+          @_mState = ENotMe
+          break
+        end
+        @_mFreqCounter[freq] += 1
+        @_mLastCharClass = charClass
+      end
+
+      return get_state()
+    end
+
+    def get_confidence
+      if get_state() == ENotMe
+        return 0.01
+      end
+
+      total = @_mFreqCounter.inject{|a,b| a+b} 
+      if total < 0.01
+        confidence = 0.0
+      else
+        confidence = (@_mFreqCounter[3] / total) - (@_mFreqCounter[1] * 20.0 / total)
+      end
+      if confidence < 0.0
+        confidence = 0.0
+      end
+      # lower the confidence of latin1 so that other more accurate detector 
+      # can take priority.
+      confidence = confidence * 0.5
+      return confidence
+    end
+  end
+end
diff --git a/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/mbcharsetprober.rb b/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/mbcharsetprober.rb
new file mode 100644 (file)
index 0000000..ede33dd
--- /dev/null
@@ -0,0 +1,89 @@
+######################## BEGIN LICENSE BLOCK ########################
+# The Original Code is Mozilla Universal charset detector code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 2001
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Jeff Hodges - port to Ruby
+#   Mark Pilgrim - port to Python
+#   Shy Shalom - original C code
+#   Proofpoint, Inc.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+# 
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301  USA
+######################### END LICENSE BLOCK #########################
+
+module CharDet
+  class MultiByteCharSetProber < CharSetProber
+    def initialize
+      super
+      @_mDistributionAnalyzer = nil
+      @_mCodingSM = nil
+      @_mLastChar = "\x00\x00"
+    end
+
+    def reset
+      super
+      if @_mCodingSM
+        @_mCodingSM.reset()
+      end
+      if @_mDistributionAnalyzer
+        @_mDistributionAnalyzer.reset()
+      end
+      @_mLastChar = "\x00\x00"
+    end
+
+    def get_charset_name
+    end
+
+    def feed(aBuf)
+      aLen = aBuf.length
+      for i in (0...aLen)
+        codingState = @_mCodingSM.next_state(aBuf[i..i])
+        if codingState == EError
+          $stderr << "#{get_charset_name} prober hit error at byte #{i}\n" if $debug
+          @_mState = ENotMe
+          break
+        elsif codingState == EItsMe
+          @_mState = EFoundIt
+          break
+        elsif codingState == EStart
+          charLen = @_mCodingSM.get_current_charlen()
+          if i == 0
+            @_mLastChar[1] = aBuf[0..0]
+            @_mDistributionAnalyzer.feed(@_mLastChar, charLen)
+          else
+            @_mDistributionAnalyzer.feed(aBuf[i-1...i+1], charLen)
+          end
+        end
+      end
+      @_mLastChar[0] = aBuf[aLen-1..aLen-1]
+
+      if get_state() == EDetecting
+        if @_mDistributionAnalyzer.got_enough_data() and (get_confidence() > SHORTCUT_THRESHOLD)
+          @_mState = EFoundIt
+        end
+      end
+      return get_state()
+    end
+
+    def get_confidence
+      return @_mDistributionAnalyzer.get_confidence()
+    end
+  end
+end
diff --git a/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/mbcsgroupprober.rb b/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/mbcsgroupprober.rb
new file mode 100644 (file)
index 0000000..4f4113c
--- /dev/null
@@ -0,0 +1,45 @@
+######################## BEGIN LICENSE BLOCK ########################
+# The Original Code is Mozilla Universal charset detector code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 2001
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Jeff Hodges - port to Ruby
+#   Mark Pilgrim - port to Python
+#   Shy Shalom - original C code
+#   Proofpoint, Inc.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+# 
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301  USA
+######################### END LICENSE BLOCK #########################
+
+module CharDet
+  class MBCSGroupProber < CharSetGroupProber
+    def initialize
+      super
+      @_mProbers = [ UTF8Prober.new,
+                     SJISProber.new,
+                     EUCJPProber.new,
+                     GB2312Prober.new,
+                     EUCKRProber.new,
+                     Big5Prober.new,
+                     EUCTWProber.new ]
+      reset()
+    end
+  end
+end
diff --git a/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/mbcssm.rb b/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/mbcssm.rb
new file mode 100644 (file)
index 0000000..3c6abaf
--- /dev/null
@@ -0,0 +1,542 @@
+######################## BEGIN LICENSE BLOCK ########################
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Jeff Hodges - port to Ruby
+#   Mark Pilgrim - port to Python
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+# 
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301  USA
+######################### END LICENSE BLOCK #########################
+
+module CharDet
+  # BIG5 
+
+  BIG5_cls = [
+    1,1,1,1,1,1,1,1,  # 00 - 07    #allow 0x00 as legal value
+    1,1,1,1,1,1,0,0,  # 08 - 0f 
+    1,1,1,1,1,1,1,1,  # 10 - 17 
+    1,1,1,0,1,1,1,1,  # 18 - 1f 
+    1,1,1,1,1,1,1,1,  # 20 - 27 
+    1,1,1,1,1,1,1,1,  # 28 - 2f 
+    1,1,1,1,1,1,1,1,  # 30 - 37 
+    1,1,1,1,1,1,1,1,  # 38 - 3f 
+    2,2,2,2,2,2,2,2,  # 40 - 47 
+    2,2,2,2,2,2,2,2,  # 48 - 4f 
+    2,2,2,2,2,2,2,2,  # 50 - 57 
+    2,2,2,2,2,2,2,2,  # 58 - 5f 
+    2,2,2,2,2,2,2,2,  # 60 - 67 
+    2,2,2,2,2,2,2,2,  # 68 - 6f 
+    2,2,2,2,2,2,2,2,  # 70 - 77 
+    2,2,2,2,2,2,2,1,  # 78 - 7f 
+    4,4,4,4,4,4,4,4,  # 80 - 87 
+    4,4,4,4,4,4,4,4,  # 88 - 8f 
+    4,4,4,4,4,4,4,4,  # 90 - 97 
+    4,4,4,4,4,4,4,4,  # 98 - 9f 
+    4,3,3,3,3,3,3,3,  # a0 - a7 
+    3,3,3,3,3,3,3,3,  # a8 - af 
+    3,3,3,3,3,3,3,3,  # b0 - b7 
+    3,3,3,3,3,3,3,3,  # b8 - bf 
+    3,3,3,3,3,3,3,3,  # c0 - c7 
+    3,3,3,3,3,3,3,3,  # c8 - cf 
+    3,3,3,3,3,3,3,3,  # d0 - d7 
+    3,3,3,3,3,3,3,3,  # d8 - df 
+    3,3,3,3,3,3,3,3,  # e0 - e7 
+    3,3,3,3,3,3,3,3,  # e8 - ef 
+    3,3,3,3,3,3,3,3,  # f0 - f7 
+    3,3,3,3,3,3,3,0  # f8 - ff 
+  ]
+
+  BIG5_st = [
+    EError,EStart,EStart,     3,EError,EError,EError,EError,#00-07 
+    EError,EError,EItsMe,EItsMe,EItsMe,EItsMe,EItsMe,EError,#08-0f 
+    EError,EStart,EStart,EStart,EStart,EStart,EStart,EStart #10-17 
+  ]
+
+  Big5CharLenTable = [0, 1, 1, 2, 0]
+
+  Big5SMModel = {'classTable' =>  BIG5_cls,
+                 'classFactor' =>  5,
+                 'stateTable' =>  BIG5_st,
+                 'charLenTable' =>  Big5CharLenTable,
+                 'name' =>  'Big5'
+  }
+
+  # EUC-JP
+
+  EUCJP_cls = [
+    4,4,4,4,4,4,4,4,  # 00 - 07 
+    4,4,4,4,4,4,5,5,  # 08 - 0f 
+    4,4,4,4,4,4,4,4,  # 10 - 17 
+    4,4,4,5,4,4,4,4,  # 18 - 1f 
+    4,4,4,4,4,4,4,4,  # 20 - 27 
+    4,4,4,4,4,4,4,4,  # 28 - 2f 
+    4,4,4,4,4,4,4,4,  # 30 - 37 
+    4,4,4,4,4,4,4,4,  # 38 - 3f 
+    4,4,4,4,4,4,4,4,  # 40 - 47 
+    4,4,4,4,4,4,4,4,  # 48 - 4f 
+    4,4,4,4,4,4,4,4,  # 50 - 57 
+    4,4,4,4,4,4,4,4,  # 58 - 5f 
+    4,4,4,4,4,4,4,4,  # 60 - 67 
+    4,4,4,4,4,4,4,4,  # 68 - 6f 
+    4,4,4,4,4,4,4,4,  # 70 - 77 
+    4,4,4,4,4,4,4,4,  # 78 - 7f 
+    5,5,5,5,5,5,5,5,  # 80 - 87 
+    5,5,5,5,5,5,1,3,  # 88 - 8f 
+    5,5,5,5,5,5,5,5,  # 90 - 97 
+    5,5,5,5,5,5,5,5,  # 98 - 9f 
+    5,2,2,2,2,2,2,2,  # a0 - a7 
+    2,2,2,2,2,2,2,2,  # a8 - af 
+    2,2,2,2,2,2,2,2,  # b0 - b7 
+    2,2,2,2,2,2,2,2,  # b8 - bf 
+    2,2,2,2,2,2,2,2,  # c0 - c7 
+    2,2,2,2,2,2,2,2,  # c8 - cf 
+    2,2,2,2,2,2,2,2,  # d0 - d7 
+    2,2,2,2,2,2,2,2,  # d8 - df 
+    0,0,0,0,0,0,0,0,  # e0 - e7 
+    0,0,0,0,0,0,0,0,  # e8 - ef 
+    0,0,0,0,0,0,0,0,  # f0 - f7 
+    0,0,0,0,0,0,0,5  # f8 - ff 
+  ]
+
+  EUCJP_st = [
+    3,     4,     3,     5,EStart,EError,EError,EError,#00-07 
+    EError,EError,EError,EError,EItsMe,EItsMe,EItsMe,EItsMe,#08-0f 
+    EItsMe,EItsMe,EStart,EError,EStart,EError,EError,EError,#10-17 
+    EError,EError,EStart,EError,EError,EError,     3,EError,#18-1f 
+    3,EError,EError,EError,EStart,EStart,EStart,EStart #20-27 
+  ]
+
+  EUCJPCharLenTable = [2, 2, 2, 3, 1, 0]
+
+  EUCJPSMModel = {'classTable' =>  EUCJP_cls,
+                  'classFactor' =>  6,
+                  'stateTable' =>  EUCJP_st,
+                  'charLenTable' =>  EUCJPCharLenTable,
+                  'name' =>  'EUC-JP'
+  }
+
+  # EUC-KR
+
+  EUCKR_cls  = [
+    1,1,1,1,1,1,1,1,  # 00 - 07 
+    1,1,1,1,1,1,0,0,  # 08 - 0f 
+    1,1,1,1,1,1,1,1,  # 10 - 17 
+    1,1,1,0,1,1,1,1,  # 18 - 1f 
+    1,1,1,1,1,1,1,1,  # 20 - 27 
+    1,1,1,1,1,1,1,1,  # 28 - 2f 
+    1,1,1,1,1,1,1,1,  # 30 - 37 
+    1,1,1,1,1,1,1,1,  # 38 - 3f 
+    1,1,1,1,1,1,1,1,  # 40 - 47 
+    1,1,1,1,1,1,1,1,  # 48 - 4f 
+    1,1,1,1,1,1,1,1,  # 50 - 57 
+    1,1,1,1,1,1,1,1,  # 58 - 5f 
+    1,1,1,1,1,1,1,1,  # 60 - 67 
+    1,1,1,1,1,1,1,1,  # 68 - 6f 
+    1,1,1,1,1,1,1,1,  # 70 - 77 
+    1,1,1,1,1,1,1,1,  # 78 - 7f 
+    0,0,0,0,0,0,0,0,  # 80 - 87 
+    0,0,0,0,0,0,0,0,  # 88 - 8f 
+    0,0,0,0,0,0,0,0,  # 90 - 97 
+    0,0,0,0,0,0,0,0,  # 98 - 9f 
+    0,2,2,2,2,2,2,2,  # a0 - a7 
+    2,2,2,2,2,3,3,3,  # a8 - af 
+    2,2,2,2,2,2,2,2,  # b0 - b7 
+    2,2,2,2,2,2,2,2,  # b8 - bf 
+    2,2,2,2,2,2,2,2,  # c0 - c7 
+    2,3,2,2,2,2,2,2,  # c8 - cf 
+    2,2,2,2,2,2,2,2,  # d0 - d7 
+    2,2,2,2,2,2,2,2,  # d8 - df 
+    2,2,2,2,2,2,2,2,  # e0 - e7 
+    2,2,2,2,2,2,2,2,  # e8 - ef 
+    2,2,2,2,2,2,2,2,  # f0 - f7 
+    2,2,2,2,2,2,2,0  # f8 - ff 
+  ]
+
+  EUCKR_st = [
+    EError,EStart,     3,EError,EError,EError,EError,EError,#00-07 
+    EItsMe,EItsMe,EItsMe,EItsMe,EError,EError,EStart,EStart#08-0f 
+  ]
+
+  EUCKRCharLenTable = [0, 1, 2, 0]
+
+  EUCKRSMModel = {'classTable' =>  EUCKR_cls,
+                  'classFactor' =>  4,
+                  'stateTable' =>  EUCKR_st,
+                  'charLenTable' =>  EUCKRCharLenTable,
+                  'name' =>  'EUC-KR'
+  }
+
+  # EUC-TW
+
+  EUCTW_cls = [
+    2,2,2,2,2,2,2,2,  # 00 - 07 
+    2,2,2,2,2,2,0,0,  # 08 - 0f 
+    2,2,2,2,2,2,2,2,  # 10 - 17 
+    2,2,2,0,2,2,2,2,  # 18 - 1f 
+    2,2,2,2,2,2,2,2,  # 20 - 27 
+    2,2,2,2,2,2,2,2,  # 28 - 2f 
+    2,2,2,2,2,2,2,2,  # 30 - 37 
+    2,2,2,2,2,2,2,2,  # 38 - 3f 
+    2,2,2,2,2,2,2,2,  # 40 - 47 
+    2,2,2,2,2,2,2,2,  # 48 - 4f 
+    2,2,2,2,2,2,2,2,  # 50 - 57 
+    2,2,2,2,2,2,2,2,  # 58 - 5f 
+    2,2,2,2,2,2,2,2,  # 60 - 67 
+    2,2,2,2,2,2,2,2,  # 68 - 6f 
+    2,2,2,2,2,2,2,2,  # 70 - 77 
+    2,2,2,2,2,2,2,2,  # 78 - 7f 
+    0,0,0,0,0,0,0,0,  # 80 - 87 
+    0,0,0,0,0,0,6,0,  # 88 - 8f 
+    0,0,0,0,0,0,0,0,  # 90 - 97 
+    0,0,0,0,0,0,0,0,  # 98 - 9f 
+    0,3,4,4,4,4,4,4,  # a0 - a7 
+    5,5,1,1,1,1,1,1,  # a8 - af 
+    1,1,1,1,1,1,1,1,  # b0 - b7 
+    1,1,1,1,1,1,1,1,  # b8 - bf 
+    1,1,3,1,3,3,3,3,  # c0 - c7 
+    3,3,3,3,3,3,3,3,  # c8 - cf 
+    3,3,3,3,3,3,3,3,  # d0 - d7 
+    3,3,3,3,3,3,3,3,  # d8 - df 
+    3,3,3,3,3,3,3,3,  # e0 - e7 
+    3,3,3,3,3,3,3,3,  # e8 - ef 
+    3,3,3,3,3,3,3,3,  # f0 - f7 
+    3,3,3,3,3,3,3,0  # f8 - ff 
+  ]
+
+  EUCTW_st = [
+    EError,EError,EStart,     3,     3,     3,     4,EError,#00-07 
+    EError,EError,EError,EError,EError,EError,EItsMe,EItsMe,#08-0f 
+    EItsMe,EItsMe,EItsMe,EItsMe,EItsMe,EError,EStart,EError,#10-17 
+    EStart,EStart,EStart,EError,EError,EError,EError,EError,#18-1f 
+    5,EError,EError,EError,EStart,EError,EStart,EStart,#20-27 
+    EStart,EError,EStart,EStart,EStart,EStart,EStart,EStart #28-2f 
+  ]
+
+  EUCTWCharLenTable = [0, 0, 1, 2, 2, 2, 3]
+
+  EUCTWSMModel = {'classTable' =>  EUCTW_cls,
+                  'classFactor' =>  7,
+                  'stateTable' =>  EUCTW_st,
+                  'charLenTable' =>  EUCTWCharLenTable,
+                  'name' =>  'x-euc-tw'
+  }
+
+  # GB2312
+
+  GB2312_cls = [
+    1,1,1,1,1,1,1,1,  # 00 - 07 
+    1,1,1,1,1,1,0,0,  # 08 - 0f 
+    1,1,1,1,1,1,1,1,  # 10 - 17 
+    1,1,1,0,1,1,1,1,  # 18 - 1f 
+    1,1,1,1,1,1,1,1,  # 20 - 27 
+    1,1,1,1,1,1,1,1,  # 28 - 2f 
+    3,3,3,3,3,3,3,3,  # 30 - 37 
+    3,3,1,1,1,1,1,1,  # 38 - 3f 
+    2,2,2,2,2,2,2,2,  # 40 - 47 
+    2,2,2,2,2,2,2,2,  # 48 - 4f 
+    2,2,2,2,2,2,2,2,  # 50 - 57 
+    2,2,2,2,2,2,2,2,  # 58 - 5f 
+    2,2,2,2,2,2,2,2,  # 60 - 67 
+    2,2,2,2,2,2,2,2,  # 68 - 6f 
+    2,2,2,2,2,2,2,2,  # 70 - 77 
+    2,2,2,2,2,2,2,4,  # 78 - 7f 
+    5,6,6,6,6,6,6,6,  # 80 - 87 
+    6,6,6,6,6,6,6,6,  # 88 - 8f 
+    6,6,6,6,6,6,6,6,  # 90 - 97 
+    6,6,6,6,6,6,6,6,  # 98 - 9f 
+    6,6,6,6,6,6,6,6,  # a0 - a7 
+    6,6,6,6,6,6,6,6,  # a8 - af 
+    6,6,6,6,6,6,6,6,  # b0 - b7 
+    6,6,6,6,6,6,6,6,  # b8 - bf 
+    6,6,6,6,6,6,6,6,  # c0 - c7 
+    6,6,6,6,6,6,6,6,  # c8 - cf 
+    6,6,6,6,6,6,6,6,  # d0 - d7 
+    6,6,6,6,6,6,6,6,  # d8 - df 
+    6,6,6,6,6,6,6,6,  # e0 - e7 
+    6,6,6,6,6,6,6,6,  # e8 - ef 
+    6,6,6,6,6,6,6,6,  # f0 - f7 
+    6,6,6,6,6,6,6,0  # f8 - ff 
+  ]
+
+  GB2312_st = [
+    EError,EStart,EStart,EStart,EStart,EStart,     3,EError,#00-07 
+    EError,EError,EError,EError,EError,EError,EItsMe,EItsMe,#08-0f 
+    EItsMe,EItsMe,EItsMe,EItsMe,EItsMe,EError,EError,EStart,#10-17 
+    4,EError,EStart,EStart,EError,EError,EError,EError,#18-1f 
+    EError,EError,     5,EError,EError,EError,EItsMe,EError,#20-27 
+    EError,EError,EStart,EStart,EStart,EStart,EStart,EStart#28-2f 
+  ]
+
+  # To be accurate, the length of class 6 can be either 2 or 4. 
+  # But it is not necessary to discriminate between the two since 
+  # it is used for frequency analysis only, and we are validing 
+  # each code range there as well. So it is safe to set it to be 
+  # 2 here. 
+  GB2312CharLenTable = [0, 1, 1, 1, 1, 1, 2]
+
+  GB2312SMModel = {'classTable' =>  GB2312_cls,
+                   'classFactor' =>  7,
+                   'stateTable' =>  GB2312_st,
+                   'charLenTable' =>  GB2312CharLenTable,
+                   'name' =>  'GB2312'
+  }
+
+  # Shift_JIS
+
+  SJIS_cls = [
+    1,1,1,1,1,1,1,1,  # 00 - 07 
+    1,1,1,1,1,1,0,0,  # 08 - 0f 
+    1,1,1,1,1,1,1,1,  # 10 - 17 
+    1,1,1,0,1,1,1,1,  # 18 - 1f 
+    1,1,1,1,1,1,1,1,  # 20 - 27 
+    1,1,1,1,1,1,1,1,  # 28 - 2f 
+    1,1,1,1,1,1,1,1,  # 30 - 37 
+    1,1,1,1,1,1,1,1,  # 38 - 3f 
+    2,2,2,2,2,2,2,2,  # 40 - 47 
+    2,2,2,2,2,2,2,2,  # 48 - 4f 
+    2,2,2,2,2,2,2,2,  # 50 - 57 
+    2,2,2,2,2,2,2,2,  # 58 - 5f 
+    2,2,2,2,2,2,2,2,  # 60 - 67 
+    2,2,2,2,2,2,2,2,  # 68 - 6f 
+    2,2,2,2,2,2,2,2,  # 70 - 77 
+    2,2,2,2,2,2,2,1,  # 78 - 7f 
+    3,3,3,3,3,3,3,3,  # 80 - 87 
+    3,3,3,3,3,3,3,3,  # 88 - 8f 
+    3,3,3,3,3,3,3,3,  # 90 - 97 
+    3,3,3,3,3,3,3,3,  # 98 - 9f 
+    #0xa0 is illegal in sjis encoding, but some pages does 
+    #contain such byte. We need to be more error forgiven.
+    2,2,2,2,2,2,2,2,  # a0 - a7     
+    2,2,2,2,2,2,2,2,  # a8 - af 
+    2,2,2,2,2,2,2,2,  # b0 - b7 
+    2,2,2,2,2,2,2,2,  # b8 - bf 
+    2,2,2,2,2,2,2,2,  # c0 - c7 
+    2,2,2,2,2,2,2,2,  # c8 - cf 
+    2,2,2,2,2,2,2,2,  # d0 - d7 
+    2,2,2,2,2,2,2,2,  # d8 - df 
+    3,3,3,3,3,3,3,3,  # e0 - e7 
+    3,3,3,3,3,4,4,4,  # e8 - ef 
+    4,4,4,4,4,4,4,4,  # f0 - f7 
+    4,4,4,4,4,0,0,0  # f8 - ff 
+  ]
+
+  SJIS_st = [
+    EError,EStart,EStart,     3,EError,EError,EError,EError,#00-07 
+    EError,EError,EError,EError,EItsMe,EItsMe,EItsMe,EItsMe,#08-0f 
+    EItsMe,EItsMe,EError,EError,EStart,EStart,EStart,EStart#10-17 
+  ]
+
+  SJISCharLenTable = [0, 1, 1, 2, 0, 0]
+
+  SJISSMModel = {'classTable' =>  SJIS_cls,
+                 'classFactor' =>  6,
+                 'stateTable' =>  SJIS_st,
+                 'charLenTable' =>  SJISCharLenTable,
+                 'name' =>  'Shift_JIS'
+  }
+
+  # UCS2-BE
+
+  UCS2BE_cls = [
+    0,0,0,0,0,0,0,0,  # 00 - 07 
+    0,0,1,0,0,2,0,0,  # 08 - 0f 
+    0,0,0,0,0,0,0,0,  # 10 - 17 
+    0,0,0,3,0,0,0,0,  # 18 - 1f 
+    0,0,0,0,0,0,0,0,  # 20 - 27 
+    0,3,3,3,3,3,0,0,  # 28 - 2f 
+    0,0,0,0,0,0,0,0,  # 30 - 37 
+    0,0,0,0,0,0,0,0,  # 38 - 3f 
+    0,0,0,0,0,0,0,0,  # 40 - 47 
+    0,0,0,0,0,0,0,0,  # 48 - 4f 
+    0,0,0,0,0,0,0,0,  # 50 - 57 
+    0,0,0,0,0,0,0,0,  # 58 - 5f 
+    0,0,0,0,0,0,0,0,  # 60 - 67 
+    0,0,0,0,0,0,0,0,  # 68 - 6f 
+    0,0,0,0,0,0,0,0,  # 70 - 77 
+    0,0,0,0,0,0,0,0,  # 78 - 7f 
+    0,0,0,0,0,0,0,0,  # 80 - 87 
+    0,0,0,0,0,0,0,0,  # 88 - 8f 
+    0,0,0,0,0,0,0,0,  # 90 - 97 
+    0,0,0,0,0,0,0,0,  # 98 - 9f 
+    0,0,0,0,0,0,0,0,  # a0 - a7 
+    0,0,0,0,0,0,0,0,  # a8 - af 
+    0,0,0,0,0,0,0,0,  # b0 - b7 
+    0,0,0,0,0,0,0,0,  # b8 - bf 
+    0,0,0,0,0,0,0,0,  # c0 - c7 
+    0,0,0,0,0,0,0,0,  # c8 - cf 
+    0,0,0,0,0,0,0,0,  # d0 - d7 
+    0,0,0,0,0,0,0,0,  # d8 - df 
+    0,0,0,0,0,0,0,0,  # e0 - e7 
+    0,0,0,0,0,0,0,0,  # e8 - ef 
+    0,0,0,0,0,0,0,0,  # f0 - f7 
+    0,0,0,0,0,0,4,5  # f8 - ff 
+  ]
+
+  UCS2BE_st  = [
+    5,     7,     7,EError,     4,     3,EError,EError,#00-07 
+    EError,EError,EError,EError,EItsMe,EItsMe,EItsMe,EItsMe,#08-0f 
+    EItsMe,EItsMe,     6,     6,     6,     6,EError,EError,#10-17 
+    6,     6,     6,     6,     6,EItsMe,     6,     6,#18-1f 
+    6,     6,     6,     6,     5,     7,     7,EError,#20-27 
+    5,     8,     6,     6,EError,     6,     6,     6,#28-2f 
+    6,     6,     6,     6,EError,EError,EStart,EStart#30-37 
+  ]
+
+  UCS2BECharLenTable = [2, 2, 2, 0, 2, 2]
+
+  UCS2BESMModel = {'classTable' =>  UCS2BE_cls,
+                   'classFactor' =>  6,
+                   'stateTable' =>  UCS2BE_st,
+                   'charLenTable' =>  UCS2BECharLenTable,
+                   'name' =>  'UTF-16BE'
+  }
+
+  # UCS2-LE
+
+  UCS2LE_cls = [
+    0,0,0,0,0,0,0,0,  # 00 - 07 
+    0,0,1,0,0,2,0,0,  # 08 - 0f 
+    0,0,0,0,0,0,0,0,  # 10 - 17 
+    0,0,0,3,0,0,0,0,  # 18 - 1f 
+    0,0,0,0,0,0,0,0,  # 20 - 27 
+    0,3,3,3,3,3,0,0,  # 28 - 2f 
+    0,0,0,0,0,0,0,0,  # 30 - 37 
+    0,0,0,0,0,0,0,0,  # 38 - 3f 
+    0,0,0,0,0,0,0,0,  # 40 - 47 
+    0,0,0,0,0,0,0,0,  # 48 - 4f 
+    0,0,0,0,0,0,0,0,  # 50 - 57 
+    0,0,0,0,0,0,0,0,  # 58 - 5f 
+    0,0,0,0,0,0,0,0,  # 60 - 67 
+    0,0,0,0,0,0,0,0,  # 68 - 6f 
+    0,0,0,0,0,0,0,0,  # 70 - 77 
+    0,0,0,0,0,0,0,0,  # 78 - 7f 
+    0,0,0,0,0,0,0,0,  # 80 - 87 
+    0,0,0,0,0,0,0,0,  # 88 - 8f 
+    0,0,0,0,0,0,0,0,  # 90 - 97 
+    0,0,0,0,0,0,0,0,  # 98 - 9f 
+    0,0,0,0,0,0,0,0,  # a0 - a7 
+    0,0,0,0,0,0,0,0,  # a8 - af 
+    0,0,0,0,0,0,0,0,  # b0 - b7 
+    0,0,0,0,0,0,0,0,  # b8 - bf 
+    0,0,0,0,0,0,0,0,  # c0 - c7 
+    0,0,0,0,0,0,0,0,  # c8 - cf 
+    0,0,0,0,0,0,0,0,  # d0 - d7 
+    0,0,0,0,0,0,0,0,  # d8 - df 
+    0,0,0,0,0,0,0,0,  # e0 - e7 
+    0,0,0,0,0,0,0,0,  # e8 - ef 
+    0,0,0,0,0,0,0,0,  # f0 - f7 
+    0,0,0,0,0,0,4,5  # f8 - ff 
+  ]
+
+  UCS2LE_st = [
+    6,     6,     7,     6,     4,     3,EError,EError,#00-07 
+    EError,EError,EError,EError,EItsMe,EItsMe,EItsMe,EItsMe,#08-0f 
+    EItsMe,EItsMe,     5,     5,     5,EError,EItsMe,EError,#10-17 
+    5,     5,     5,EError,     5,EError,     6,     6,#18-1f 
+    7,     6,     8,     8,     5,     5,     5,EError,#20-27 
+    5,     5,     5,EError,EError,EError,     5,     5,#28-2f 
+    5,     5,     5,EError,     5,EError,EStart,EStart#30-37 
+  ]
+
+  UCS2LECharLenTable = [2, 2, 2, 2, 2, 2]
+
+  UCS2LESMModel = {'classTable' =>  UCS2LE_cls,
+                   'classFactor' =>  6,
+                   'stateTable' =>  UCS2LE_st,
+                   'charLenTable' =>  UCS2LECharLenTable,
+                   'name' =>  'UTF-16LE'
+  }
+
+  # UTF-8
+
+  UTF8_cls = [
+    1,1,1,1,1,1,1,1,  # 00 - 07  #allow 0x00 as a legal value
+    1,1,1,1,1,1,0,0,  # 08 - 0f 
+    1,1,1,1,1,1,1,1,  # 10 - 17 
+    1,1,1,0,1,1,1,1,  # 18 - 1f 
+    1,1,1,1,1,1,1,1,  # 20 - 27 
+    1,1,1,1,1,1,1,1,  # 28 - 2f 
+    1,1,1,1,1,1,1,1,  # 30 - 37 
+    1,1,1,1,1,1,1,1,  # 38 - 3f 
+    1,1,1,1,1,1,1,1,  # 40 - 47 
+    1,1,1,1,1,1,1,1,  # 48 - 4f 
+    1,1,1,1,1,1,1,1,  # 50 - 57 
+    1,1,1,1,1,1,1,1,  # 58 - 5f 
+    1,1,1,1,1,1,1,1,  # 60 - 67 
+    1,1,1,1,1,1,1,1,  # 68 - 6f 
+    1,1,1,1,1,1,1,1,  # 70 - 77 
+    1,1,1,1,1,1,1,1,  # 78 - 7f 
+    2,2,2,2,3,3,3,3,  # 80 - 87 
+    4,4,4,4,4,4,4,4,  # 88 - 8f 
+    4,4,4,4,4,4,4,4,  # 90 - 97 
+    4,4,4,4,4,4,4,4,  # 98 - 9f 
+    5,5,5,5,5,5,5,5,  # a0 - a7 
+    5,5,5,5,5,5,5,5,  # a8 - af 
+    5,5,5,5,5,5,5,5,  # b0 - b7 
+    5,5,5,5,5,5,5,5,  # b8 - bf 
+    0,0,6,6,6,6,6,6,  # c0 - c7 
+    6,6,6,6,6,6,6,6,  # c8 - cf 
+    6,6,6,6,6,6,6,6,  # d0 - d7 
+    6,6,6,6,6,6,6,6,  # d8 - df 
+    7,8,8,8,8,8,8,8,  # e0 - e7 
+    8,8,8,8,8,9,8,8,  # e8 - ef 
+    10,11,11,11,11,11,11,11,  # f0 - f7 
+    12,13,13,13,14,15,0,0   # f8 - ff 
+  ]
+
+  UTF8_st = [ 
+    EError,EStart,EError,EError,EError,EError,     12,   10,#00-07 
+    9,     11,     8,     7,     6,     5,     4,    3,#08-0f 
+    EError,EError,EError,EError,EError,EError,EError,EError,#10-17 
+    EError,EError,EError,EError,EError,EError,EError,EError,#18-1f 
+    EItsMe,EItsMe,EItsMe,EItsMe,EItsMe,EItsMe,EItsMe,EItsMe,#20-27 
+    EItsMe,EItsMe,EItsMe,EItsMe,EItsMe,EItsMe,EItsMe,EItsMe,#28-2f 
+    EError,EError,     5,     5,     5,     5,EError,EError,#30-37 
+    EError,EError,EError,EError,EError,EError,EError,EError,#38-3f 
+    EError,EError,EError,     5,     5,     5,EError,EError,#40-47 
+    EError,EError,EError,EError,EError,EError,EError,EError,#48-4f 
+    EError,EError,     7,     7,     7,     7,EError,EError,#50-57 
+    EError,EError,EError,EError,EError,EError,EError,EError,#58-5f 
+    EError,EError,EError,EError,     7,     7,EError,EError,#60-67 
+    EError,EError,EError,EError,EError,EError,EError,EError,#68-6f 
+    EError,EError,     9,     9,     9,     9,EError,EError,#70-77 
+    EError,EError,EError,EError,EError,EError,EError,EError,#78-7f 
+    EError,EError,EError,EError,EError,     9,EError,EError,#80-87 
+    EError,EError,EError,EError,EError,EError,EError,EError,#88-8f 
+    EError,EError,    12,    12,    12,    12,EError,EError,#90-97 
+    EError,EError,EError,EError,EError,EError,EError,EError,#98-9f 
+    EError,EError,EError,EError,EError,    12,EError,EError,#a0-a7 
+    EError,EError,EError,EError,EError,EError,EError,EError,#a8-af 
+    EError,EError,    12,    12,    12,EError,EError,EError,#b0-b7 
+    EError,EError,EError,EError,EError,EError,EError,EError,#b8-bf 
+    EError,EError,EStart,EStart,EStart,EStart,EError,EError,#c0-c7 
+    EError,EError,EError,EError,EError,EError,EError,EError#c8-cf 
+  ]
+
+  UTF8CharLenTable = [0, 1, 0, 0, 0, 0, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6]
+
+  UTF8SMModel = {'classTable' =>  UTF8_cls,
+                 'classFactor' =>  16,
+                 'stateTable' =>  UTF8_st,
+                 'charLenTable' =>  UTF8CharLenTable,
+                 'name' =>  'UTF-8'
+  }
+end
diff --git a/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/sbcharsetprober.rb b/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/sbcharsetprober.rb
new file mode 100644 (file)
index 0000000..dc16774
--- /dev/null
@@ -0,0 +1,124 @@
+######################## BEGIN LICENSE BLOCK ########################
+# The Original Code is Mozilla Universal charset detector code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 2001
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Jeff Hodges - port to Ruby
+#   Mark Pilgrim - port to Python
+#   Shy Shalom - original C code
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+# 
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301  USA
+######################### END LICENSE BLOCK #########################
+
+module CharDet
+  SAMPLE_SIZE = 64
+  SB_ENOUGH_REL_THRESHOLD = 1024
+  POSITIVE_SHORTCUT_THRESHOLD = 0.95
+  NEGATIVE_SHORTCUT_THRESHOLD = 0.05
+  SYMBOL_CAT_ORDER = 250
+  NUMBER_OF_SEQ_CAT = 4
+  POSITIVE_CAT = NUMBER_OF_SEQ_CAT - 1
+  #NEGATIVE_CAT = 0
+
+  class SingleByteCharSetProber < CharSetProber
+    def initialize(model, reversed=false, nameProber=nil)
+      super()
+      @_mModel = model
+      @_mReversed = reversed # TRUE if we need to reverse every pair in the model lookup
+      @_mNameProber = nameProber # Optional auxiliary prober for name decision
+      reset()
+    end
+
+    def reset
+      super()
+      @_mLastOrder = 255 # char order of last character
+      @_mSeqCounters = [0] * NUMBER_OF_SEQ_CAT
+      @_mTotalSeqs = 0
+      @_mTotalChar = 0
+      @_mFreqChar = 0 # characters that fall in our sampling range
+    end
+
+    def get_charset_name
+      if @_mNameProber
+        return @_mNameProber.get_charset_name()
+      else
+        return @_mModel['charsetName']
+      end
+    end
+
+    def feed(aBuf)
+      if not @_mModel['keepEnglishLetter']
+        aBuf = filter_without_english_letters(aBuf)
+      end
+      aLen = aBuf.length
+      if not aLen
+        return get_state()
+      end
+      aBuf.each_byte do |b|
+        c = b.chr
+        order = @_mModel['charToOrderMap'][c[0]]
+        if order < SYMBOL_CAT_ORDER
+          @_mTotalChar += 1
+        end
+        if order < SAMPLE_SIZE
+          @_mFreqChar += 1
+          if @_mLastOrder < SAMPLE_SIZE
+            @_mTotalSeqs += 1
+            if not @_mReversed
+              @_mSeqCounters[@_mModel['precedenceMatrix'][(@_mLastOrder * SAMPLE_SIZE) + order]] += 1
+            else # reverse the order of the letters in the lookup
+              @_mSeqCounters[@_mModel['precedenceMatrix'][(order * SAMPLE_SIZE) + @_mLastOrder]] += 1
+            end
+          end
+        end
+        @_mLastOrder = order
+      end
+
+      if get_state() == EDetecting
+        if @_mTotalSeqs > SB_ENOUGH_REL_THRESHOLD
+          cf = get_confidence()
+          if cf > POSITIVE_SHORTCUT_THRESHOLD
+            $stderr << "#{@_mModel['charsetName']} confidence = #{cf}, we have a winner\n" if $debug
+            @_mState = EFoundIt
+          elsif cf < NEGATIVE_SHORTCUT_THRESHOLD
+            $stderr << "#{@_mModel['charsetName']} confidence = #{cf}, below negative shortcut threshold #{NEGATIVE_SHORTCUT_THRESHOLD}\n" if $debug
+            @_mState = ENotMe
+          end
+        end
+      end
+
+      return get_state()
+    end
+
+    def get_confidence
+      r = 0.01
+      if @_mTotalSeqs > 0
+        #            print self._mSeqCounters[POSITIVE_CAT], self._mTotalSeqs, self._mModel['mTypicalPositiveRatio']
+        r = (1.0 * @_mSeqCounters[POSITIVE_CAT]) / @_mTotalSeqs / @_mModel['mTypicalPositiveRatio']
+        #            print r, self._mFreqChar, self._mTotalChar
+        r = r * @_mFreqChar / @_mTotalChar
+        if r >= 1.0
+          r = 0.99
+        end
+      end
+      return r
+    end
+  end
+end
diff --git a/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/sbcsgroupprober.rb b/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/sbcsgroupprober.rb
new file mode 100644 (file)
index 0000000..2251ed3
--- /dev/null
@@ -0,0 +1,56 @@
+######################## BEGIN LICENSE BLOCK ########################
+# The Original Code is Mozilla Universal charset detector code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 2001
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Jeff Hodges - port to Ruby
+#   Mark Pilgrim - port to Python
+#   Shy Shalom - original C code
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+# 
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301  USA
+######################### END LICENSE BLOCK #########################
+
+module CharDet
+  class SBCSGroupProber < CharSetGroupProber
+    def initialize
+      super
+      @_mProbers = [ SingleByteCharSetProber.new(Win1251CyrillicModel),
+                     SingleByteCharSetProber.new(Koi8rModel),
+                     SingleByteCharSetProber.new(Latin5CyrillicModel),
+                     SingleByteCharSetProber.new(MacCyrillicModel),
+                     SingleByteCharSetProber.new(Ibm866Model),
+                     SingleByteCharSetProber.new(Ibm855Model),
+                     SingleByteCharSetProber.new(Latin7GreekModel),
+                     SingleByteCharSetProber.new(Win1253GreekModel),
+                     SingleByteCharSetProber.new(Latin5BulgarianModel),
+                     SingleByteCharSetProber.new(Win1251BulgarianModel),
+                     SingleByteCharSetProber.new(Latin2HungarianModel),
+                     SingleByteCharSetProber.new(Win1250HungarianModel),
+                     SingleByteCharSetProber.new(TIS620ThaiModel) ]
+      hebrewProber = HebrewProber.new()
+      logicalHebrewProber = SingleByteCharSetProber.new(Win1255HebrewModel, false, hebrewProber)
+      visualHebrewProber = SingleByteCharSetProber.new(Win1255HebrewModel, true, hebrewProber)
+      hebrewProber.set_model_probers(logicalHebrewProber, visualHebrewProber)
+      @_mProbers += [hebrewProber, logicalHebrewProber, visualHebrewProber]
+
+      reset()
+    end
+  end
+end
diff --git a/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/sjisprober.rb b/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/sjisprober.rb
new file mode 100644 (file)
index 0000000..2205d3e
--- /dev/null
@@ -0,0 +1,88 @@
+######################## BEGIN LICENSE BLOCK ########################
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Jeff Hodges - port to Ruby
+#   Mark Pilgrim - port to Python
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+# 
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301  USA
+######################### END LICENSE BLOCK #########################
+
+module CharDet
+  class SJISProber < MultiByteCharSetProber
+    def initialize
+      super()
+      @_mCodingSM = CodingStateMachine.new(SJISSMModel)
+      @_mDistributionAnalyzer = SJISDistributionAnalysis.new()
+      @_mContextAnalyzer = SJISContextAnalysis.new()
+      reset()
+    end
+
+    def reset
+      super()
+      @_mContextAnalyzer.reset()
+    end
+
+    def get_charset_name
+      return "SHIFT_JIS"
+    end
+
+    def feed(aBuf)
+      aLen = aBuf.length
+      for i in (0...aLen)
+        codingState = @_mCodingSM.next_state(aBuf[i..i])
+        if codingState == EError
+          $stderr << "#{get_charset_name} prober hit error at byte #{i}\n" if $debug
+          @_mState = ENotMe
+          break
+        elsif codingState == EItsMe
+          @_mState = EFoundIt
+          break
+        elsif codingState == EStart
+          charLen = @_mCodingSM.get_current_charlen()
+          if i == 0
+            @_mLastChar[1] = aBuf[0..0]
+            @_mContextAnalyzer.feed(@_mLastChar[2 - charLen..-1], charLen)
+            @_mDistributionAnalyzer.feed(@_mLastChar, charLen)
+          else
+            @_mContextAnalyzer.feed(aBuf[i + 1 - charLen ... i + 3 - charLen], charLen)
+            @_mDistributionAnalyzer.feed(aBuf[i - 1 ... i + 1], charLen)
+          end
+        end
+      end
+
+      @_mLastChar[0] = aBuf[aLen - 1.. aLen-1]
+
+      if get_state() == EDetecting
+        if @_mContextAnalyzer.got_enough_data() and (get_confidence() > SHORTCUT_THRESHOLD)
+          @_mState = EFoundIt
+        end
+      end
+
+      return get_state()
+    end
+
+    def get_confidence
+      l = [@_mContextAnalyzer.get_confidence(), @_mDistributionAnalyzer.get_confidence()]
+      return l.max
+    end
+  end
+end
diff --git a/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/universaldetector.rb b/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/universaldetector.rb
new file mode 100644 (file)
index 0000000..c8990c6
--- /dev/null
@@ -0,0 +1,168 @@
+# encoding: us-ascii
+######################## BEGIN LICENSE BLOCK ########################
+# The Original Code is Mozilla Universal charset detector code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 2001
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Jeff Hodges - port to Ruby
+#   Mark Pilgrim - port to Python
+#   Shy Shalom - original C code
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301  USA
+######################### END LICENSE BLOCK #########################
+
+module CharDet
+  MINIMUM_THRESHOLD = 0.20
+  EPureAscii = 0
+  EEscAscii = 1
+  EHighbyte = 2
+
+  class UniversalDetector
+    attr_accessor :result
+    def initialize
+      @_highBitDetector = /[\x80-\xFF]/
+      @_escDetector = /(\033|\~\{)/
+      @_mEscCharSetProber = nil
+      @_mCharSetProbers = []
+      reset()
+    end
+
+    def reset
+      @result = {'encoding' => nil, 'confidence' => 0.0}
+      @done = false
+      @_mStart = true
+      @_mGotData = false
+      @_mInputState = EPureAscii
+      @_mLastChar = ''
+      if @_mEscCharSetProber
+        @_mEscCharSetProber.reset()
+      end
+      for prober in @_mCharSetProbers
+        prober.reset()
+      end
+    end
+
+    def feed(aBuf)
+      return if @done
+
+      aLen = aBuf.length
+      return if not aLen
+
+      if not @_mGotData
+        # If the data starts with BOM, we know it is UTF
+        if aBuf[0...3] == "\xEF\xBB\xBF"
+          # EF BB BF  UTF-8 with BOM
+          @result = {'encoding' => "UTF-8", 'confidence' => 1.0}
+        elsif aBuf[0...4] == "\xFF\xFE\x00\x00"
+          # FF FE 00 00  UTF-32, little-endian BOM
+          @result = {'encoding' => "UTF-32LE", 'confidence' => 1.0}
+        elsif aBuf[0...4] == "\x00\x00\xFE\xFF"
+          # 00 00 FE FF  UTF-32, big-endian BOM
+          @result = {'encoding' => "UTF-32BE", 'confidence' => 1.0}
+        elsif aBuf[0...4] == "\xFE\xFF\x00\x00"
+          # FE FF 00 00  UCS-4, unusual octet order BOM (3412)
+          @result = {'encoding' => "X-ISO-10646-UCS-4-3412", 'confidence' => 1.0}
+        elsif aBuf[0...4] == "\x00\x00\xFF\xFE"
+          # 00 00 FF FE  UCS-4, unusual octet order BOM (2143)
+          @result = {'encoding' =>  "X-ISO-10646-UCS-4-2143", 'confidence' =>  1.0}
+        elsif aBuf[0...2] == "\xFF\xFE"
+          # FF FE  UTF-16, little endian BOM
+          @result = {'encoding' =>  "UTF-16LE", 'confidence' =>  1.0}
+        elsif aBuf[0...2] == "\xFE\xFF"
+          # FE FF  UTF-16, big endian BOM
+          @result = {'encoding' =>  "UTF-16BE", 'confidence' =>  1.0}
+        end
+      end
+
+      @_mGotData = true
+      if @result['encoding'] and (@result['confidence'] > 0.0)
+        @done = true
+        return
+      end
+
+      if @_mInputState == EPureAscii
+        if @_highBitDetector =~ (aBuf)
+          @_mInputState = EHighbyte
+        elsif (@_mInputState == EPureAscii) and @_escDetector =~ (@_mLastChar + aBuf)
+          @_mInputState = EEscAscii
+        end
+      end
+
+      @_mLastChar = aBuf[-1..-1]
+      if @_mInputState == EEscAscii
+        if not @_mEscCharSetProber
+          @_mEscCharSetProber = EscCharSetProber.new()
+        end
+        if @_mEscCharSetProber.feed(aBuf) == EFoundIt
+          @result = {'encoding' =>  self._mEscCharSetProber.get_charset_name(),
+                     'confidence' =>  @_mEscCharSetProber.get_confidence()
+          }
+          @done = true
+        end
+      elsif @_mInputState == EHighbyte
+        if not @_mCharSetProbers or @_mCharSetProbers.empty?
+          @_mCharSetProbers = [MBCSGroupProber.new(), SBCSGroupProber.new(), Latin1Prober.new()]
+        end
+        for prober in @_mCharSetProbers
+          if prober.feed(aBuf) == EFoundIt
+            @result = {'encoding' =>  prober.get_charset_name(),
+                       'confidence' =>  prober.get_confidence()}
+            @done = true
+            break
+          end
+        end
+      end
+
+    end
+
+    def close
+      return if @done
+      if not @_mGotData
+        $stderr << "no data received!\n" if $debug
+        return
+      end
+      @done = true
+
+      if @_mInputState == EPureAscii
+        @result = {'encoding' => 'ascii', 'confidence' => 1.0}
+        return @result
+      end
+
+      if @_mInputState == EHighbyte
+        confidences = {}
+        @_mCharSetProbers.each{ |prober| confidences[prober] = prober.get_confidence }
+        maxProber = @_mCharSetProbers.max{ |a,b| confidences[a] <=> confidences[b] }
+        if maxProber and maxProber.get_confidence > MINIMUM_THRESHOLD
+          @result = {'encoding' =>  maxProber.get_charset_name(),
+                     'confidence' =>  maxProber.get_confidence()}
+          return @result
+        end
+      end
+
+      if $debug
+        $stderr << "no probers hit minimum threshhold\n" if $debug
+        for prober in @_mCharSetProbers[0]._mProbers
+          next if not prober
+          $stderr << "#{prober.get_charset_name} confidence = #{prober.get_confidence}\n" if $debug
+        end
+      end
+    end
+  end
+end
diff --git a/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/utf8prober.rb b/lib/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/utf8prober.rb
new file mode 100644 (file)
index 0000000..269d8c5
--- /dev/null
@@ -0,0 +1,87 @@
+######################## BEGIN LICENSE BLOCK ########################
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Jeff Hodges - port to Ruby
+#   Mark Pilgrim - port to Python
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+# 
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301  USA
+######################### END LICENSE BLOCK #########################
+
+module CharDet
+  ONE_CHAR_PROB = 0.5
+
+  class UTF8Prober < CharSetProber
+    def initialize
+      super()
+      @_mCodingSM = CodingStateMachine.new(UTF8SMModel)
+      reset()
+    end
+
+    def reset
+      super()
+      @_mCodingSM.reset()
+      @_mNumOfMBChar = 0
+    end
+
+    def get_charset_name
+      return "utf-8"
+    end
+
+    def feed(aBuf)
+      aBuf.each_byte do |b|
+        c = b.chr
+        codingState = @_mCodingSM.next_state(c)
+        if codingState == EError
+          @_mState = ENotMe
+          break
+        elsif codingState == EItsMe
+          @_mState = EFoundIt
+          break
+        elsif codingState == EStart
+          if @_mCodingSM.get_current_charlen() >= 2
+            @_mNumOfMBChar += 1
+          end
+        end
+      end
+
+      if get_state() == EDetecting
+        if get_confidence() > SHORTCUT_THRESHOLD
+          @_mState = EFoundIt
+        end
+      end
+
+      return get_state()
+    end
+
+    def get_confidence
+      unlike = 0.99
+      if @_mNumOfMBChar < 6
+        for i in (0...@_mNumOfMBChar)
+          unlike = unlike * ONE_CHAR_PROB
+        end
+        return 1.0 - unlike
+      else
+        return unlike
+      end
+    end
+  end
+end
diff --git a/lib/vendor/tmail-1.2.7/tmail/version.rb b/lib/vendor/tmail-1.2.7/tmail/version.rb
new file mode 100644 (file)
index 0000000..2cafcd7
--- /dev/null
@@ -0,0 +1,39 @@
+#
+# version.rb
+#
+#--
+# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Note: Originally licensed under LGPL v2+. Using MIT license for Rails
+# with permission of Minero Aoki.
+#++
+
+#:stopdoc:
+module TMail
+  module VERSION
+    MAJOR = 1
+    MINOR = 2
+    TINY  = 6
+
+    STRING = [MAJOR, MINOR, TINY].join('.')
+  end
+end
diff --git a/lib/vendor/tmail.rb b/lib/vendor/tmail.rb
new file mode 100644 (file)
index 0000000..eb077f2
--- /dev/null
@@ -0,0 +1,20 @@
+$:.unshift "#{File.dirname(__FILE__)}/tmail-1.2.7"
+
+require 'tmail'
+
+module TMail
+  # TMail::Unquoter.convert_to_with_fallback_on_iso_8859_1 introduced in TMail 1.2.7
+  # triggers a test failure in test_add_issue_with_japanese_keywords(MailHandlerTest)
+  class Unquoter
+    class << self
+      alias_method :convert_to, :convert_to_without_fallback_on_iso_8859_1
+    end
+  end
+
+  # Patch for TMail 1.2.7. See http://www.redmine.org/issues/8751
+  class Encoder
+    def puts_meta(str)
+      add_text str
+    end
+  end
+end
diff --git a/plugins/README b/plugins/README
new file mode 100644 (file)
index 0000000..edef256
--- /dev/null
@@ -0,0 +1 @@
+Put your Redmine plugins here.
diff --git a/public/javascripts/rails.js b/public/javascripts/rails.js
new file mode 100644 (file)
index 0000000..88eac6e
--- /dev/null
@@ -0,0 +1,202 @@
+(function() {
+  Ajax.Responders.register({
+    onCreate: function(request) {
+      var token = $$('meta[name=csrf-token]')[0];
+      if (token) {
+        if (!request.options.requestHeaders) request.options.requestHeaders = {};
+        request.options.requestHeaders['X-CSRF-Token'] = token.readAttribute('content');
+      }
+    }
+  });
+
+  // Technique from Juriy Zaytsev
+  // http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/
+  function isEventSupported(eventName) {
+    var el = document.createElement('div');
+    eventName = 'on' + eventName;
+    var isSupported = (eventName in el);
+    if (!isSupported) {
+      el.setAttribute(eventName, 'return;');
+      isSupported = typeof el[eventName] == 'function';
+    }
+    el = null;
+    return isSupported;
+  }
+
+  function isForm(element) {
+    return Object.isElement(element) && element.nodeName.toUpperCase() == 'FORM';
+  }
+
+  function isInput(element) {
+    if (Object.isElement(element)) {
+      var name = element.nodeName.toUpperCase();
+      return name == 'INPUT' || name == 'SELECT' || name == 'TEXTAREA';
+    }
+    else return false;
+  }
+
+  var submitBubbles = isEventSupported('submit'),
+      changeBubbles = isEventSupported('change');
+
+  if (!submitBubbles || !changeBubbles) {
+    // augment the Event.Handler class to observe custom events when needed
+    Event.Handler.prototype.initialize = Event.Handler.prototype.initialize.wrap(
+      function(init, element, eventName, selector, callback) {
+        init(element, eventName, selector, callback);
+        // is the handler being attached to an element that doesn't support this event?
+        if ( (!submitBubbles && this.eventName == 'submit' && !isForm(this.element)) ||
+             (!changeBubbles && this.eventName == 'change' && !isInput(this.element)) ) {
+          // "submit" => "emulated:submit"
+          this.eventName = 'emulated:' + this.eventName;
+        }
+      }
+    );
+  }
+
+  if (!submitBubbles) {
+    // discover forms on the page by observing focus events which always bubble
+    document.on('focusin', 'form', function(focusEvent, form) {
+      // special handler for the real "submit" event (one-time operation)
+      if (!form.retrieve('emulated:submit')) {
+        form.on('submit', function(submitEvent) {
+          var emulated = form.fire('emulated:submit', submitEvent, true);
+          // if custom event received preventDefault, cancel the real one too
+          if (emulated.returnValue === false) submitEvent.preventDefault();
+        });
+        form.store('emulated:submit', true);
+      }
+    });
+  }
+
+  if (!changeBubbles) {
+    // discover form inputs on the page
+    document.on('focusin', 'input, select, textarea', function(focusEvent, input) {
+      // special handler for real "change" events
+      if (!input.retrieve('emulated:change')) {
+        input.on('change', function(changeEvent) {
+          input.fire('emulated:change', changeEvent, true);
+        });
+        input.store('emulated:change', true);
+      }
+    });
+  }
+
+  function handleRemote(element) {
+    var method, url, params;
+
+    var event = element.fire("ajax:before");
+    if (event.stopped) return false;
+
+    if (element.tagName.toLowerCase() === 'form') {
+      method = element.readAttribute('method') || 'post';
+      url    = element.readAttribute('action');
+      // serialize the form with respect to the submit button that was pressed
+      params = element.serialize({ submit: element.retrieve('rails:submit-button') });
+      // clear the pressed submit button information
+      element.store('rails:submit-button', null);
+    } else {
+      method = element.readAttribute('data-method') || 'get';
+      url    = element.readAttribute('href');
+      params = {};
+    }
+
+    new Ajax.Request(url, {
+      method: method,
+      parameters: params,
+      evalScripts: true,
+
+      onCreate:   function(response) { element.fire("ajax:create",   response); },
+      onComplete: function(response) { element.fire("ajax:complete", response); },
+      onSuccess:  function(response) { element.fire("ajax:success",  response); },
+      onFailure:  function(response) { element.fire("ajax:failure",  response); }
+    });
+
+    element.fire("ajax:after");
+  }
+
+  function insertHiddenField(form, name, value) {
+    form.insert(new Element('input', { type: 'hidden', name: name, value: value }));
+  }
+
+  function handleMethod(element) {
+    var method = element.readAttribute('data-method'),
+        url = element.readAttribute('href'),
+        csrf_param = $$('meta[name=csrf-param]')[0],
+        csrf_token = $$('meta[name=csrf-token]')[0];
+
+    var form = new Element('form', { method: "POST", action: url, style: "display: none;" });
+    $(element.parentNode).insert(form);
+
+    if (method !== 'post') {
+      insertHiddenField(form, '_method', method);
+    }
+
+    if (csrf_param) {
+      insertHiddenField(form, csrf_param.readAttribute('content'), csrf_token.readAttribute('content'));
+    }
+
+    form.submit();
+  }
+
+  function disableFormElements(form) {
+    form.select('input[type=submit][data-disable-with]').each(function(input) {
+      input.store('rails:original-value', input.getValue());
+      input.setValue(input.readAttribute('data-disable-with')).disable();
+    });
+  }
+  
+  function enableFormElements(form) {
+    form.select('input[type=submit][data-disable-with]').each(function(input) {
+      input.setValue(input.retrieve('rails:original-value')).enable();
+    });
+  }
+
+  function allowAction(element) {
+    var message = element.readAttribute('data-confirm');
+    return !message || confirm(message);
+  }
+
+  document.on('click', 'a[data-confirm], a[data-remote], a[data-method]', function(event, link) {
+    if (!allowAction(link)) {
+      event.stop();
+      return false;
+    }
+
+    if (link.readAttribute('data-remote')) {
+      handleRemote(link);
+      event.stop();
+    } else if (link.readAttribute('data-method')) {
+      handleMethod(link);
+      event.stop();
+    }
+  });
+
+  document.on("click", "form input[type=submit], form button[type=submit], form button:not([type])", function(event, button) {
+    // register the pressed submit button
+    event.findElement('form').store('rails:submit-button', button.name || false);
+  });
+
+  document.on("submit", function(event) {
+    var form = event.findElement();
+
+    if (!allowAction(form)) {
+      event.stop();
+      return false;
+    }
+
+    if (form.readAttribute('data-remote')) {
+      handleRemote(form);
+      event.stop();
+    } else {
+      disableFormElements(form);
+    }
+  });
+
+  document.on('ajax:create', 'form', function(event, form) {
+    if (form == event.findElement()) disableFormElements(form);
+  });
+  
+  document.on('ajax:complete', 'form', function(event, form) {
+    if (form == event.findElement()) enableFormElements(form);
+  });
+})();
diff --git a/script/about b/script/about
deleted file mode 100755 (executable)
index 61112a0..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/usr/bin/env ruby
-require File.expand_path('../../config/boot',  __FILE__)
-$LOAD_PATH.unshift "#{RAILTIES_PATH}/builtin/rails_info"
-require 'commands/about'
-
-Redmine::About.print_plugin_info
diff --git a/script/breakpointer b/script/breakpointer
deleted file mode 100755 (executable)
index d7db15a..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/usr/bin/env ruby
-require File.expand_path('../../config/boot',  __FILE__)
-require 'commands/breakpointer'
diff --git a/script/console b/script/console
deleted file mode 100755 (executable)
index 235a1f2..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/usr/bin/env ruby
-require File.expand_path('../../config/boot',  __FILE__)
-require 'commands/console'
diff --git a/script/dbconsole b/script/dbconsole
deleted file mode 100755 (executable)
index 83c8436..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/usr/bin/env ruby
-require File.expand_path('../../config/boot',  __FILE__)
-require 'commands/dbconsole'
diff --git a/script/destroy b/script/destroy
deleted file mode 100755 (executable)
index 88d295f..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/usr/bin/env ruby
-require File.expand_path('../../config/boot',  __FILE__)
-require 'commands/destroy'
diff --git a/script/generate b/script/generate
deleted file mode 100755 (executable)
index 62a8a4c..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/usr/bin/env ruby
-require File.expand_path('../../config/boot',  __FILE__)
-require 'commands/generate'
diff --git a/script/performance/benchmarker b/script/performance/benchmarker
deleted file mode 100755 (executable)
index 3bff809..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/usr/bin/env ruby
-require File.expand_path('../../../config/boot',  __FILE__)
-require 'commands/performance/benchmarker'
diff --git a/script/performance/profiler b/script/performance/profiler
deleted file mode 100755 (executable)
index 0764057..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/usr/bin/env ruby
-require File.expand_path('../../../config/boot',  __FILE__)
-require 'commands/performance/profiler'
diff --git a/script/performance/request b/script/performance/request
deleted file mode 100755 (executable)
index 489e568..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/usr/bin/env ruby
-require File.expand_path('../../config/boot',  __FILE__)
-require 'commands/performance/request'
diff --git a/script/plugin b/script/plugin
deleted file mode 100755 (executable)
index b82201f..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/usr/bin/env ruby
-require File.expand_path('../../config/boot',  __FILE__)
-require 'commands/plugin'
diff --git a/script/process/inspector b/script/process/inspector
deleted file mode 100755 (executable)
index 8bcabb0..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/usr/bin/env ruby
-require File.expand_path('../../config/boot',  __FILE__)
-require 'commands/process/inspector'
diff --git a/script/process/reaper b/script/process/reaper
deleted file mode 100755 (executable)
index aa7c1a0..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/usr/bin/env ruby
-require File.expand_path('../../config/boot',  __FILE__)
-require 'commands/process/reaper'
diff --git a/script/process/spawner b/script/process/spawner
deleted file mode 100755 (executable)
index 69b3359..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/usr/bin/env ruby
-require File.expand_path('../../config/boot',  __FILE__)
-require 'commands/process/spawner'
diff --git a/script/process/spinner b/script/process/spinner
deleted file mode 100755 (executable)
index 190c2be..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/usr/bin/env ruby
-require File.expand_path('../../config/boot',  __FILE__)
-require 'commands/process/spinner'
diff --git a/script/rails b/script/rails
new file mode 100644 (file)
index 0000000..81eab02
--- /dev/null
@@ -0,0 +1,6 @@
+#!/usr/bin/env ruby.exe
+# This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
+
+APP_PATH = File.expand_path('../../config/application',  __FILE__)
+require File.expand_path('../../config/boot',  __FILE__)
+require 'rails/commands'
diff --git a/script/runner b/script/runner
deleted file mode 100755 (executable)
index be4c5d4..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/usr/bin/env ruby
-require File.expand_path('../../config/boot',  __FILE__)
-require 'commands/runner'
diff --git a/script/server b/script/server
deleted file mode 100755 (executable)
index b9fcb71..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/usr/bin/env ruby
-require File.expand_path('../../config/boot',  __FILE__)
-require 'commands/server'
index b99de35a3e6496906fa95625cf804c0d76ae5a62..e114ffa00fdcdfa841902d4be4bb048eba7b7377 100644 (file)
@@ -143,3 +143,12 @@ custom_fields_010:
   field_format: bool
   default_value: 0
   editable: true
+custom_fields_011:
+  id: 11
+  name: Binary
+  type: CustomField
+  possible_values: 
+  - !binary |
+    SGXDqWzDp2prc2Tigqw2NTTDuQ==
+  - Other value
+  field_format: list
index ef7285f61e81a6e11405ff261a1841a3a6db859c..5be709a1d0780ec6c8fb2df81fe551ea53169bab 100644 (file)
@@ -6,7 +6,7 @@ repositories_001:
   root_url: file:///<%= Rails.root %>/tmp/test/subversion_repository
   password: ""
   login: ""
-  type: Subversion
+  type: Repository::Subversion
   is_default: true
 repositories_002: 
   project_id: 2
@@ -15,5 +15,5 @@ repositories_002:
   root_url: svn://localhost
   password: ""
   login: ""
-  type: Subversion
+  type: Repository::Subversion
   is_default: true
index adb7ebf2f82b16f0825f98ff1536499c0950b643..bf24ff368e88853b8d1ec379f70b335e392a1650 100644 (file)
@@ -318,7 +318,7 @@ class IssuesControllerTest < ActionController::TestCase
     get :index, :format => 'csv'
     assert_response :success
     assert_not_nil assigns(:issues)
-    assert_equal 'text/csv', @response.content_type
+    assert_equal 'text/csv; header=present', @response.content_type
     assert @response.body.starts_with?("#,")
     lines = @response.body.chomp.split("\n")
     assert_equal assigns(:query).columns.size + 1, lines[0].split(',').size
@@ -328,14 +328,14 @@ class IssuesControllerTest < ActionController::TestCase
     get :index, :project_id => 1, :format => 'csv'
     assert_response :success
     assert_not_nil assigns(:issues)
-    assert_equal 'text/csv', @response.content_type
+    assert_equal 'text/csv; header=present', @response.content_type
   end
 
   def test_index_csv_with_description
     get :index, :format => 'csv', :description => '1'
     assert_response :success
     assert_not_nil assigns(:issues)
-    assert_equal 'text/csv', @response.content_type
+    assert_equal 'text/csv; header=present', @response.content_type
     assert @response.body.starts_with?("#,")
     lines = @response.body.chomp.split("\n")
     assert_equal assigns(:query).columns.size + 2, lines[0].split(',').size
@@ -347,7 +347,7 @@ class IssuesControllerTest < ActionController::TestCase
 
     get :index, :format => 'csv', :set_filter => '1', :c => %w(subject spent_hours)
     assert_response :success
-    assert_equal 'text/csv', @response.content_type
+    assert_equal 'text/csv; header=present', @response.content_type
     lines = @response.body.chomp.split("\n")
     assert_include "#{issue.id},#{issue.subject},7.33", lines
   end
@@ -356,7 +356,7 @@ class IssuesControllerTest < ActionController::TestCase
     get :index, :format => 'csv', :columns => 'all'
     assert_response :success
     assert_not_nil assigns(:issues)
-    assert_equal 'text/csv', @response.content_type
+    assert_equal 'text/csv; header=present', @response.content_type
     assert @response.body.starts_with?("#,")
     lines = @response.body.chomp.split("\n")
     assert_equal assigns(:query).available_columns.size + 1, lines[0].split(',').size
@@ -391,7 +391,7 @@ class IssuesControllerTest < ActionController::TestCase
                   :f => ['subject'], 
                   :op => '=', :values => [str_utf8],
                   :format => 'csv'
-      assert_equal 'text/csv', @response.content_type
+      assert_equal 'text/csv; header=present', @response.content_type
       lines = @response.body.chomp.split("\n")
       s1 = "\xaa\xac\xbaA"
       if str_utf8.respond_to?(:force_encoding)
@@ -419,7 +419,7 @@ class IssuesControllerTest < ActionController::TestCase
                   :c => ['status', 'subject'],
                   :format => 'csv',
                   :set_filter => 1
-      assert_equal 'text/csv', @response.content_type
+      assert_equal 'text/csv; header=present', @response.content_type
       lines = @response.body.chomp.split("\n")
       s1 = "\xaa\xac\xbaA" # status
       if str_utf8.respond_to?(:force_encoding)
@@ -454,7 +454,7 @@ class IssuesControllerTest < ActionController::TestCase
                   :c => ['estimated_hours', 'subject'],
                   :format => 'csv',
                   :set_filter => 1
-      assert_equal 'text/csv', @response.content_type
+      assert_equal 'text/csv; header=present', @response.content_type
       lines = @response.body.chomp.split("\n")
       assert_equal "#{issue.id},1234.50,#{str1}", lines[1]
 
@@ -483,7 +483,7 @@ class IssuesControllerTest < ActionController::TestCase
                   :c => ['estimated_hours', 'subject'],
                   :format => 'csv',
                   :set_filter => 1
-      assert_equal 'text/csv', @response.content_type
+      assert_equal 'text/csv; header=present', @response.content_type
       lines = @response.body.chomp.split("\n")
       assert_equal "#{issue.id};1234,50;#{str1}", lines[1]
 
@@ -1357,7 +1357,7 @@ class IssuesControllerTest < ActionController::TestCase
       :attributes => {:name => 'issue[tracker_id]'},
       :child => {:tag => 'option', :attributes => {:value => '3', :selected => 'selected'}}
     assert_tag 'textarea',
-      :attributes => {:name => 'issue[description]'}, :content => 'Prefilled'
+      :attributes => {:name => 'issue[description]'}, :content => "\nPrefilled"
     assert_tag 'input',
       :attributes => {:name => 'issue[custom_field_values][2]', :value => 'Custom field value'}
   end
@@ -1727,7 +1727,7 @@ class IssuesControllerTest < ActionController::TestCase
     assert_template 'new'
 
     assert_tag :textarea, :attributes => { :name => 'issue[description]' },
-                          :content => 'This is a description'
+                          :content => "\nThis is a description"
     assert_tag :select, :attributes => { :name => 'issue[priority_id]' },
                         :child => { :tag => 'option', :attributes => { :selected => 'selected',
                                                                        :value => '6' },
@@ -2621,7 +2621,7 @@ class IssuesControllerTest < ActionController::TestCase
     assert_template 'edit'
 
     assert_error_tag :descendant => {:content => /Activity can't be blank/}
-    assert_tag :textarea, :attributes => { :name => 'notes' }, :content => notes
+    assert_tag :textarea, :attributes => { :name => 'notes' }, :content => "\n"+notes
     assert_tag :input, :attributes => { :name => 'time_entry[hours]', :value => "2z" }
   end
 
@@ -2640,7 +2640,7 @@ class IssuesControllerTest < ActionController::TestCase
 
     assert_error_tag :descendant => {:content => /Activity can't be blank/}
     assert_error_tag :descendant => {:content => /Hours can't be blank/}
-    assert_tag :textarea, :attributes => { :name => 'notes' }, :content => notes
+    assert_tag :textarea, :attributes => { :name => 'notes' }, :content => "\n"+notes
     assert_tag :input, :attributes => { :name => 'time_entry[comments]', :value => "this is my comment" }
   end
 
index 5fc454388ec03ddc05439dd5bd1f8303c7c40662..fc509a24113ec2e6d93b630e2028137ddca5d4fe 100644 (file)
@@ -140,7 +140,7 @@ class QueriesControllerTest < ActionController::TestCase
 
   def test_create_with_failure
     @request.session[:user_id] = 2
-    assert_no_difference 'Query.count' do
+    assert_no_difference '::Query.count' do
       post :create, :project_id => 'ecookbook', :query => {:name => ''}
     end
     assert_response :success
index 419d6dc398c9b837ae705952206bf0441f202177..4e9bde9d28df2da0afb344ee78ef0bb6e3b5213f 100644 (file)
@@ -62,12 +62,26 @@ class RepositoriesSubversionControllerTest < ActionController::TestCase
       entry = assigns(:entries).detect {|e| e.name == 'subversion_test'}
       assert_not_nil entry
       assert_equal 'dir', entry.kind
+      assert_select 'tr.dir a[href=/projects/subproject1/repository/show/subversion_test]'
 
       assert_tag 'input', :attributes => {:name => 'rev'}
       assert_tag 'a', :content => 'Statistics'
       assert_tag 'a', :content => 'Atom'
     end
 
+    def test_show_non_default
+      Repository::Subversion.create(:project => @project,
+        :url => self.class.subversion_repository_url,
+        :is_default => false, :identifier => 'svn')
+
+      get :show, :id => PRJ_ID, :repository_id => 'svn'
+      assert_response :success
+      assert_template 'show'
+      assert_select 'tr.dir a[href=/projects/subproject1/repository/svn/show/subversion_test]'
+      # Repository menu should link to the main repo
+      assert_select '#main-menu a[href=/projects/subproject1/repository]'
+    end
+
     def test_browse_directory
       assert_equal 0, @repository.changesets.count
       @repository.fetch_changesets
index e4ea8b8eca3265fffb9ad7262584609dda12ed29..44a5037d8d1a344db587df04cb3f22c40a456eb1 100644 (file)
@@ -136,7 +136,7 @@ class TimeEntryReportsControllerTest < ActionController::TestCase
     get :report, :columns => 'month', :from => "2007-01-01", :to => "2007-06-30",
         :criteria => ["project", "member", "activity"], :format => "csv"
     assert_response :success
-    assert_equal 'text/csv', @response.content_type
+    assert_equal 'text/csv; header=present', @response.content_type
     lines = @response.body.chomp.split("\n")
     # Headers
     assert_equal 'Project,Member,Activity,2007-1,2007-2,2007-3,2007-4,2007-5,2007-6,Total',
@@ -150,7 +150,7 @@ class TimeEntryReportsControllerTest < ActionController::TestCase
         :from => "2007-01-01", :to => "2007-06-30",
         :criteria => ["project", "member", "activity"], :format => "csv"
     assert_response :success
-    assert_equal 'text/csv', @response.content_type
+    assert_equal 'text/csv; header=present', @response.content_type
     lines = @response.body.chomp.split("\n")
     # Headers
     assert_equal 'Project,Member,Activity,2007-1,2007-2,2007-3,2007-4,2007-5,2007-6,Total',
@@ -188,7 +188,7 @@ class TimeEntryReportsControllerTest < ActionController::TestCase
         :from => "2011-11-11", :to => "2011-11-11",
         :criteria => ["member"], :format => "csv"
     assert_response :success
-    assert_equal 'text/csv', @response.content_type
+    assert_equal 'text/csv; header=present', @response.content_type
     lines = @response.body.chomp.split("\n")    
     # Headers
     s1 = "\xa6\xa8\xad\xfb,2011-11-11,\xc1`\xadp"
@@ -239,7 +239,7 @@ class TimeEntryReportsControllerTest < ActionController::TestCase
         :from => "2011-11-11", :to => "2011-11-11",
         :criteria => ["member"], :format => "csv"
     assert_response :success
-    assert_equal 'text/csv', @response.content_type
+    assert_equal 'text/csv; header=present', @response.content_type
     lines = @response.body.chomp.split("\n")    
     # Headers
     s1 = "\xa6\xa8\xad\xfb,2011-11-11,\xc1`\xadp"
@@ -280,7 +280,7 @@ class TimeEntryReportsControllerTest < ActionController::TestCase
           :from => "2011-11-11", :to => "2011-11-11",
           :criteria => ["member"], :format => "csv"
       assert_response :success
-      assert_equal 'text/csv', @response.content_type
+      assert_equal 'text/csv; header=present', @response.content_type
       lines = @response.body.chomp.split("\n")    
       # Headers
       s1 = "Membre;2011-11-11;Total"
index 9fa9ae637f9c01fea553d0da18362a383866f7c1..a314bd80bf90681a1cef5c9b61aaf612fbf4fccf 100644 (file)
@@ -561,7 +561,7 @@ class TimelogControllerTest < ActionController::TestCase
     Setting.date_format = '%m/%d/%Y'
     get :index, :format => 'csv'
     assert_response :success
-    assert_equal 'text/csv', @response.content_type
+    assert_equal 'text/csv; header=present', @response.content_type
     assert @response.body.include?("Date,User,Activity,Project,Issue,Tracker,Subject,Hours,Comment,Overtime\n")
     assert @response.body.include?("\n04/21/2007,redMine Admin,Design,eCookbook,3,Bug,Error 281 when updating a recipe,1.0,\"\",\"\"\n")
   end
@@ -570,7 +570,7 @@ class TimelogControllerTest < ActionController::TestCase
     Setting.date_format = '%m/%d/%Y'
     get :index, :project_id => 1, :format => 'csv'
     assert_response :success
-    assert_equal 'text/csv', @response.content_type
+    assert_equal 'text/csv; header=present', @response.content_type
     assert @response.body.include?("Date,User,Activity,Project,Issue,Tracker,Subject,Hours,Comment,Overtime\n")
     assert @response.body.include?("\n04/21/2007,redMine Admin,Design,eCookbook,3,Bug,Error 281 when updating a recipe,1.0,\"\",\"\"\n")
   end
@@ -616,7 +616,7 @@ class TimelogControllerTest < ActionController::TestCase
     get :index, :project_id => 1, :format => 'csv',
         :from => '2011-11-10', :to => '2011-11-10'
     assert_response :success
-    assert_equal 'text/csv', @response.content_type
+    assert_equal 'text/csv; header=present', @response.content_type
     ar = @response.body.chomp.split("\n")
     s1 = "\xa4\xe9\xb4\xc1"
     if str_utf8.respond_to?(:force_encoding)
@@ -653,7 +653,7 @@ class TimelogControllerTest < ActionController::TestCase
     get :index, :project_id => 1, :format => 'csv',
         :from => '2011-11-10', :to => '2011-11-10'
     assert_response :success
-    assert_equal 'text/csv', @response.content_type
+    assert_equal 'text/csv; header=present', @response.content_type
     ar = @response.body.chomp.split("\n")
     s1 = "\xa4\xe9\xb4\xc1"
     if str_utf8.respond_to?(:force_encoding)
@@ -690,7 +690,7 @@ class TimelogControllerTest < ActionController::TestCase
       get :index, :project_id => 1, :format => 'csv',
           :from => '2011-11-10', :to => '2011-11-10'
       assert_response :success
-      assert_equal 'text/csv', @response.content_type
+      assert_equal 'text/csv; header=present', @response.content_type
 
       ar = @response.body.chomp.split("\n")
       s2 = ar[1].split(",")[7]
@@ -724,7 +724,7 @@ class TimelogControllerTest < ActionController::TestCase
       get :index, :project_id => 1, :format => 'csv',
           :from => '2011-11-10', :to => '2011-11-10'
       assert_response :success
-      assert_equal 'text/csv', @response.content_type
+      assert_equal 'text/csv; header=present', @response.content_type
 
       ar = @response.body.chomp.split("\n")
       s2 = ar[1].split(";")[7]
index 9247b6631c763ec28503483674d59629f90ca93f..e477af5e831b4abc117b712a0dc3cdd622d889f4 100644 (file)
@@ -84,10 +84,19 @@ class WatchersControllerTest < ActionController::TestCase
     assert_select_rjs :replace_html, 'ajax-modal'
   end
 
-  def test_new_for_new_record
+  def test_new_for_new_record_with_id
     @request.session[:user_id] = 2
     xhr :get, :new, :project_id => 1
     assert_response :success
+    assert_equal Project.find(1), assigns(:project)
+    assert_select_rjs :replace_html, 'ajax-modal'
+  end
+
+  def test_new_for_new_record_with_identifier
+    @request.session[:user_id] = 2
+    xhr :get, :new, :project_id => 'ecookbook'
+    assert_response :success
+    assert_equal Project.find(1), assigns(:project)
     assert_select_rjs :replace_html, 'ajax-modal'
   end
 
index 54a3f650d4603e68152ac7284e05595dfab110e0..ce0c8480f8242e949fff164acf70d3bcd2b2b01f 100644 (file)
@@ -198,7 +198,7 @@ class WikiControllerTest < ActionController::TestCase
 
     assert_tag 'textarea',
       :attributes => { :name => 'content[text]' },
-      :content => WikiPage.find_by_title('Another_page').content.text
+      :content => "\n"+WikiPage.find_by_title('Another_page').content.text
   end
 
   def test_edit_section
@@ -213,7 +213,7 @@ class WikiControllerTest < ActionController::TestCase
 
     assert_tag 'textarea',
       :attributes => { :name => 'content[text]' },
-      :content => section
+      :content => "\n"+section
     assert_tag 'input',
       :attributes => { :name => 'section', :type => 'hidden', :value => '2' }
     assert_tag 'input',
@@ -294,7 +294,7 @@ class WikiControllerTest < ActionController::TestCase
     assert_template 'edit'
 
     assert_error_tag :descendant => {:content => /Comment is too long/}
-    assert_tag :tag => 'textarea', :attributes => {:id => 'content_text'}, :content => 'edited'
+    assert_tag :tag => 'textarea', :attributes => {:id => 'content_text'}, :content => "\nedited"
     assert_tag :tag => 'input', :attributes => {:id => 'content_version', :value => '1'}
   end
 
index 55fd761a9bfada0695d1b23c63138cf9c2cfcd25..46a14462e0df36642ee631eb001ba264d41ee5f4 100644 (file)
@@ -75,7 +75,7 @@ class ApiTest::IssueRelationsTest < ActionController::IntegrationTest
           end
 
           assert_response :unprocessable_entity
-          assert_tag :errors, :child => {:tag => 'error', :content => 'relation_type is not included in the list'}
+          assert_tag :errors, :child => {:tag => 'error', :content => /relation_type is not included in the list/}
         end
       end
     end
index dcda2c4dd7af6ec6f12901ac757051c5f982a490..0243b3f040e01779a792f36483dfebf8383c6bfd 100644 (file)
@@ -167,7 +167,7 @@ class ApiTest::MembershipsTest < ActionController::IntegrationTest
 
           assert_response :unprocessable_entity
           assert_equal 'application/xml', @response.content_type
-          assert_tag 'errors', :child => {:tag => 'error', :content => "member_roles is invalid"}
+          assert_tag 'errors', :child => {:tag => 'error', :content => /member_roles is invalid/}
         end
       end
     end
index 4f5503026ba75bec1add142e862a6443b707c773..ee03abd870b4b28825b4f9b81ba664be092f48f0 100644 (file)
@@ -215,14 +215,14 @@ class IssuesTest < ActionController::IntegrationTest
     assert_not_equal subject, Issue.find(1).subject
 
     post '/issues/1', {:issue => {:subject => subject}}, credentials('jsmith')
-    assert_response 405
+    assert_response 404
     assert_not_equal subject, Issue.find(1).subject
   end
 
   def test_get_watch_should_be_invalid
     assert_no_difference 'Watcher.count' do
       get '/watchers/watch?object_type=issue&object_id=1', {}, credentials('jsmith')
-      assert_response 405
+      assert_response 404
     end
   end
 end
index 1abe6ad962d6092c5fa83ad3d9758325671d5b34..51a97aafbf59ad64b95a8514a5f224266b90eea0 100644 (file)
@@ -45,7 +45,7 @@ class ProjectsTest < ActionController::IntegrationTest
   def test_modules_should_not_allow_get
     assert_no_difference 'EnabledModule.count' do
       get '/projects/1/modules', {:enabled_module_names => ['']}, credentials('jsmith')
-      assert_response :method_not_allowed
+      assert_response 404
     end
   end
 end
index 6fb63e3515fc3862c82989d0628c17b9a5eaf659..8475ff5553eefb21b90e0d04e50d2783d52cd241 100644 (file)
@@ -21,11 +21,11 @@ class RoutingActivitiesTest < ActionController::IntegrationTest
   def test_activities
     assert_routing(
            { :method => 'get', :path => "/activity" },
-           { :controller => 'activities', :action => 'index', :id => nil }
+           { :controller => 'activities', :action => 'index' }
         )
     assert_routing(
            { :method => 'get', :path => "/activity.atom" },
-           { :controller => 'activities', :action => 'index', :id => nil, :format => 'atom' }
+           { :controller => 'activities', :action => 'index', :format => 'atom' }
         )
     assert_routing(
         { :method => 'get', :path => "/projects/33/activity" },
index 60a1d408b0f86d2414384747fc71ace421340de4..ce8a2db89665eaebfd7e1e19c88d2f1ebf0ebb2d 100644 (file)
@@ -21,7 +21,7 @@ class RoutingRepositoriesTest < ActionController::IntegrationTest
   def setup
     @path_hash  = repository_path_hash(%w[path to file.c])
     assert_equal "path/to/file.c", @path_hash[:path]
-    assert_equal %w[path to file.c], @path_hash[:param]
+    assert_equal "path/to/file.c", @path_hash[:param]
   end
 
   def test_repositories_resources
@@ -124,7 +124,7 @@ class RoutingRepositoriesTest < ActionController::IntegrationTest
         { :method => 'get',
           :path => "/projects/redmine/repository/revisions/2457/show" },
         { :controller => 'repositories', :action => 'show', :id => 'redmine',
-          :path => empty_path_param, :rev => '2457' }
+          :rev => '2457' }
       )
     assert_routing(
         { :method => 'get',
@@ -136,7 +136,7 @@ class RoutingRepositoriesTest < ActionController::IntegrationTest
         { :method => 'get',
           :path => "/projects/redmine/repository/revisions/2457/changes" },
         { :controller => 'repositories', :action => 'changes', :id => 'redmine',
-          :path => empty_path_param, :rev => '2457' }
+          :rev => '2457' }
       )
     assert_routing(
         { :method => 'get',
@@ -205,7 +205,7 @@ class RoutingRepositoriesTest < ActionController::IntegrationTest
         { :method => 'get',
           :path => "/projects/redmine/repository/foo/revisions/2457/show" },
         { :controller => 'repositories', :action => 'show', :id => 'redmine', :repository_id => 'foo',
-          :path => empty_path_param, :rev => '2457' }
+          :rev => '2457' }
       )
     assert_routing(
         { :method => 'get',
@@ -217,7 +217,7 @@ class RoutingRepositoriesTest < ActionController::IntegrationTest
         { :method => 'get',
           :path => "/projects/redmine/repository/foo/revisions/2457/changes" },
         { :controller => 'repositories', :action => 'changes', :id => 'redmine', :repository_id => 'foo',
-          :path => empty_path_param, :rev => '2457' }
+          :rev => '2457' }
       )
     assert_routing(
         { :method => 'get',
index 35ee4310ca9fa75812a9d2c5c2a66e479fcb0c89..ef652e26083669dd0d30a4a1ae8aa493ed55f5b9 100644 (file)
@@ -90,11 +90,13 @@ class RoutingWikiTest < ActionController::IntegrationTest
         { :controller => 'wiki', :action => 'rename', :project_id => '22',
           :id => 'ladida' }
       )
-    assert_routing(
-        { :method => 'post', :path => "/projects/567/wiki/CookBook_documentation/preview" },
-        { :controller => 'wiki', :action => 'preview', :project_id => '567',
-          :id => 'CookBook_documentation' }
-      )
+    ["post", "put"].each do |method|
+      assert_routing(
+          { :method => method, :path => "/projects/567/wiki/CookBook_documentation/preview" },
+          { :controller => 'wiki', :action => 'preview', :project_id => '567',
+            :id => 'CookBook_documentation' }
+        )
+    end
     assert_routing(
         { :method => 'post', :path => "/projects/22/wiki/ladida/rename" },
         { :controller => 'wiki', :action => 'rename', :project_id => '22',
index 759aaf43886c9f4e21ba1830cf425e6f5daa52ab..a8a7ef79a5b283cecc623e002e8fccc87497ef5b 100644 (file)
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
+#require 'shoulda'
 ENV["RAILS_ENV"] = "test"
 require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
-require 'test_help'
+require 'rails/test_help'
 require Rails.root.join('test', 'mocks', 'open_id_authentication_mock.rb').to_s
 
 require File.expand_path(File.dirname(__FILE__) + '/object_helpers')
 include ObjectHelpers
 
 class ActiveSupport::TestCase
+  include ActionDispatch::TestProcess
+  
   # Transactional fixtures accelerate your tests by wrapping each test method
   # in a transaction that's rolled back on completion.  This ensures that the
   # test database remains unchanged so your fixtures don't have to be reloaded
@@ -58,12 +61,11 @@ class ActiveSupport::TestCase
   end
 
   def uploaded_test_file(name, mime)
-    ActionController::TestUploadedFile.new(
-      ActiveSupport::TestCase.fixture_path + "/files/#{name}", mime, true)
+    fixture_file_upload("files/#{name}", mime, true)
   end
 
   def credentials(user, password=nil)
-    {:authorization => ActionController::HttpAuthentication::Basic.encode_credentials(user, password || user)}
+    {'HTTP_AUTHORIZATION' => ActionController::HttpAuthentication::Basic.encode_credentials(user, password || user)}
   end
 
   # Mock out a file
@@ -146,7 +148,7 @@ class ActiveSupport::TestCase
   def repository_path_hash(arr)
     hs = {}
     hs[:path]  = arr.join("/")
-    hs[:param] = arr
+    hs[:param] = arr.join("/")
     hs
   end
 
@@ -179,7 +181,7 @@ class ActiveSupport::TestCase
   end
 
   def mail_body(mail)
-    mail.body
+    mail.parts.first.body.encoded
   end
 
   # Shoulda macros
@@ -417,9 +419,13 @@ class ActiveSupport::TestCase
   def self.should_respond_with_content_type_based_on_url(url)
     case
     when url.match(/xml/i)
-      should_respond_with_content_type :xml
+      should "respond with XML" do
+        assert_equal 'application/xml', @response.content_type
+      end
     when url.match(/json/i)
-      should_respond_with_content_type :json
+      should "respond with JSON" do
+        assert_equal 'application/json', @response.content_type
+      end
     else
       raise "Unknown content type for should_respond_with_content_type_based_on_url: #{url}"
     end
@@ -458,6 +464,11 @@ class ActiveSupport::TestCase
     end
   end
 
+  def self.should_respond_with(status)
+    should "respond with #{status}" do
+      assert_response status
+    end
+  end
 end
 
 # Simple module to "namespace" all of the API tests
index 529aa699d779d25b8d72c1fe62dbce40a8b6689e..4509dc8ed02b63fe9e3981c444b62fd26b6ad596 100644 (file)
@@ -75,6 +75,17 @@ class CustomFieldTest < ActiveSupport::TestCase
     assert_equal ["One value", "And another one"], field.possible_values
   end
 
+  if "string".respond_to?(:encoding)
+    def test_possible_values_stored_as_binary_should_be_utf8_encoded
+      field = CustomField.find(11)
+      assert_kind_of Array, field.possible_values
+      assert field.possible_values.size > 0
+      field.possible_values.each do |value|
+        assert_equal "UTF-8", value.encoding.name
+      end
+    end
+  end
+
   def test_destroy
     field = CustomField.find(1)
     assert field.destroy
index 7e6c15585f3730764cab05affa8401d7071c3739..a7a05f3e052173c033e1d5cb2bfffdf3fc7485cc 100644 (file)
@@ -79,7 +79,7 @@ class ApplicationHelperTest < ActionView::TestCase
       # two exclamation marks
       'http://example.net/path!602815048C7B5C20!302.html' => '<a class="external" href="http://example.net/path!602815048C7B5C20!302.html">http://example.net/path!602815048C7B5C20!302.html</a>',
       # escaping
-      'http://foo"bar' => '<a class="external" href="http://foo&quot;bar">http://foo"bar</a>',
+      'http://foo"bar' => '<a class="external" href="http://foo&quot;bar">http://foo&quot;bar</a>',
       # wrap in angle brackets
       '<http://foo.bar>' => '&lt;<a class="external" href="http://foo.bar">http://foo.bar</a>&gt;'
     }
index 64844edbb036630d5ed10347465b46a218d168cd..729e7cc54839573883c8235de0e13f9db9f52198 100644 (file)
@@ -1033,11 +1033,12 @@ class IssueTest < ActiveSupport::TestCase
     assert IssueRelation.create!(:issue_from => Issue.find(2),
                                  :issue_to   => Issue.find(3),
                                  :relation_type => IssueRelation::TYPE_PRECEDES)
-    # Validation skipping
-    assert IssueRelation.new(:issue_from => Issue.find(3),
-                             :issue_to   => Issue.find(1),
-                             :relation_type => IssueRelation::TYPE_PRECEDES).save(false)
 
+    r = IssueRelation.create!(:issue_from => Issue.find(3),
+                             :issue_to   => Issue.find(7),
+                             :relation_type => IssueRelation::TYPE_PRECEDES)
+    IssueRelation.update_all("issue_to_id = 1", ["id = ?", r.id])
+    
     assert_equal [2, 3], Issue.find(1).all_dependent_issues.collect(&:id).sort
   end
 
@@ -1052,13 +1053,16 @@ class IssueTest < ActiveSupport::TestCase
     assert IssueRelation.create!(:issue_from => Issue.find(3),
                                  :issue_to   => Issue.find(8),
                                  :relation_type => IssueRelation::TYPE_RELATES)
-    # Validation skipping
-    assert IssueRelation.new(:issue_from => Issue.find(8),
-                             :issue_to   => Issue.find(2),
-                             :relation_type => IssueRelation::TYPE_RELATES).save(false)
-    assert IssueRelation.new(:issue_from => Issue.find(3),
-                             :issue_to   => Issue.find(1),
-                             :relation_type => IssueRelation::TYPE_RELATES).save(false)
+
+    r = IssueRelation.create!(:issue_from => Issue.find(8),
+                             :issue_to   => Issue.find(7),
+                             :relation_type => IssueRelation::TYPE_RELATES)
+    IssueRelation.update_all("issue_to_id = 2", ["id = ?", r.id])
+    
+    r = IssueRelation.create!(:issue_from => Issue.find(3),
+                             :issue_to   => Issue.find(7),
+                             :relation_type => IssueRelation::TYPE_RELATES)
+    IssueRelation.update_all("issue_to_id = 1", ["id = ?", r.id])
 
     assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
   end
index 1b0034c95739d07e465e0ac8084c31c6f450892c..07aeb1aff914c5f6f1891d6a7e53a3acd6b6dbb6 100644 (file)
@@ -17,7 +17,7 @@
 
 require File.expand_path('../../../../test_helper', __FILE__)
 
-class Redmine::Hook::ManagerTest < ActiveSupport::TestCase
+class Redmine::Hook::ManagerTest < ActionView::TestCase
 
   fixtures :issues
 
index 3f4966bbf75a7561c520cf2423000c78b3e68611..7a8eb11709d0d777fcdcdda28ff0497ae2880045 100644 (file)
@@ -21,6 +21,7 @@ class Redmine::WikiFormatting::MacrosTest < ActionView::TestCase
   include ApplicationHelper
   include ActionView::Helpers::TextHelper
   include ActionView::Helpers::SanitizeHelper
+  include ERB::Util
   extend ActionView::Helpers::SanitizeHelper::ClassMethods
 
   fixtures :projects, :roles, :enabled_modules, :users,
index 5607d1636ef7455ef1b08270a4d0ce5b2e872272..97516c139b47c844b77c7100c3a3ff4b5603c188 100644 (file)
@@ -19,7 +19,7 @@ require File.expand_path('../../test_helper', __FILE__)
 
 class MailerTest < ActiveSupport::TestCase
   include Redmine::I18n
-  include ActionController::Assertions::SelectorAssertions
+  include ActionDispatch::Assertions::SelectorAssertions 
   fixtures :projects, :enabled_modules, :issues, :users, :members,
            :member_roles, :roles, :documents, :attachments, :news,
            :tokens, :journals, :journal_details, :changesets, :trackers,
@@ -78,7 +78,6 @@ class MailerTest < ActiveSupport::TestCase
     relative_url_root = Redmine::Utils.relative_url_root
     Setting.host_name = 'mydomain.foo/rdm'
     Setting.protocol = 'http'
-    Redmine::Utils.relative_url_root = '/rdm'
 
     journal = Journal.find(3)
     assert Mailer.deliver_issue_edit(journal)
@@ -111,9 +110,6 @@ class MailerTest < ActiveSupport::TestCase
                     'http://mydomain.foo/rdm/attachments/download/4/source.rb',
                     :text => 'source.rb'
     end
-  ensure
-    # restore it
-    Redmine::Utils.relative_url_root = relative_url_root
   end
 
   def test_generated_links_with_prefix_and_no_relative_url_root
@@ -164,15 +160,15 @@ class MailerTest < ActiveSupport::TestCase
     Mailer.deliver_issue_add(issue)
     mail = last_email
     assert_not_nil mail
-    assert_equal 'OOF', mail.header_string('X-Auto-Response-Suppress')
-    assert_equal 'auto-generated', mail.header_string('Auto-Submitted')
+    assert_equal 'OOF', mail.header['X-Auto-Response-Suppress'].to_s
+    assert_equal 'auto-generated', mail.header['Auto-Submitted'].to_s
   end
 
   def test_email_headers_should_include_sender
     issue = Issue.find(1)
     Mailer.deliver_issue_add(issue)
     mail = last_email
-    assert_equal issue.author.login, mail.header_string('X-Redmine-Sender')
+    assert_equal issue.author.login, mail.header['X-Redmine-Sender'].to_s
   end
 
   def test_plain_text_mail
@@ -180,7 +176,7 @@ class MailerTest < ActiveSupport::TestCase
     journal = Journal.find(2)
     Mailer.deliver_issue_edit(journal)
     mail = last_email
-    assert_equal "text/plain", mail.content_type
+    assert_equal "text/plain; charset=UTF-8", mail.content_type
     assert_equal 0, mail.parts.size
     assert !mail.encoded.include?('href')
   end
@@ -199,7 +195,7 @@ class MailerTest < ActiveSupport::TestCase
       Mailer.deliver_test_email(User.find(1))
     end
     mail = last_email
-    assert_equal 'redmine@example.net', mail.from_addrs.first.address
+    assert_equal 'redmine@example.net', mail.from_addrs.first
   end
 
   def test_from_header_with_phrase
@@ -207,8 +203,8 @@ class MailerTest < ActiveSupport::TestCase
       Mailer.deliver_test_email(User.find(1))
     end
     mail = last_email
-    assert_equal 'redmine@example.net', mail.from_addrs.first.address
-    assert_equal 'Redmine app', mail.from_addrs.first.name
+    assert_equal 'redmine@example.net', mail.from_addrs.first
+    assert_equal 'Redmine app <redmine@example.net>', mail.header['From'].to_s
   end
 
   def test_should_not_send_email_without_recipient
@@ -245,7 +241,7 @@ class MailerTest < ActiveSupport::TestCase
     Mailer.deliver_issue_edit(journal)
     mail = last_email
     assert_equal Mailer.message_id_for(journal), mail.message_id
-    assert_equal Mailer.message_id_for(journal.issue), mail.references.first.to_s
+    assert_include Mailer.message_id_for(journal.issue), mail.references
     assert_select_email do
       # link to the update
       assert_select "a[href=?]",
@@ -272,7 +268,7 @@ class MailerTest < ActiveSupport::TestCase
     Mailer.deliver_message_posted(message)
     mail = last_email
     assert_equal Mailer.message_id_for(message), mail.message_id
-    assert_equal Mailer.message_id_for(message.parent), mail.references.first.to_s
+    assert_include Mailer.message_id_for(message.parent), mail.references
     assert_select_email do
       # link to the reply
       assert_select "a[href=?]",
@@ -528,14 +524,6 @@ class MailerTest < ActiveSupport::TestCase
     # should restore perform_deliveries
     assert ActionMailer::Base.perform_deliveries
   end
-  
-  def test_tmail_to_header_field_should_not_include_blank_lines
-    mail = TMail::Mail.new
-    mail.to = ["a.user@example.com", "v.user2@example.com", "e.smith@example.com", "info@example.com", "v.pupkin@example.com",
-      "b.user@example.com", "w.user2@example.com", "f.smith@example.com", "info2@example.com", "w.pupkin@example.com"]
-    
-    assert !mail.encoded.strip.split("\r\n").detect(&:blank?), "#{mail.encoded} malformed"
-  end
 
   def test_layout_should_include_the_emails_header
     with_settings :emails_header => "*Header content*" do
index 6488bb07e3a52cdfab62443db25d96f270fe727b..545edc42bfa2ca9e020b5b3ccb152f5c9cd6f2d1 100644 (file)
@@ -141,7 +141,7 @@ class UserTest < ActiveSupport::TestCase
 
     u2 = User.new(:firstname => "new", :lastname => "user", :mail => "newuser2@somenet.foo")
     u2.login = 'newuser1'
-    assert u2.save(false)
+    assert u2.save(:validate => false)
 
     user = User.find(u2.id)
     user.firstname = "firstname"
index ed0400a7e104ac0432c362731bde3cc72ba7bb6b..32c93d5fe9a9151bd984e4f539d71305d3233184 100644 (file)
@@ -157,7 +157,7 @@ class WatcherTest < ActiveSupport::TestCase
 
   def test_prune_all
     user = User.find(9)
-    Watcher.new(:watchable => Issue.find(4), :user => User.find(9)).save(false)
+    Watcher.new(:watchable => Issue.find(4), :user => User.find(9)).save(:validate => false)
 
     assert Watcher.prune > 0
     assert !Issue.find(4).watched_by?(user)
index bba10c437380774f5b92a6ed0750d2d4bda995bb..36442b2ad15ffbd514cb6bf6d44f19aa46eb674d 100644 (file)
@@ -377,10 +377,12 @@ module ActiveRecord #:nodoc:
             new_model.send("#{key}=", orig_model.send(key)) if orig_model.has_attribute?(key)
           end
 
-          if orig_model.is_a?(self.class.versioned_class)
-            new_model[new_model.class.inheritance_column] = orig_model[self.class.versioned_inheritance_column]
-          elsif new_model.is_a?(self.class.versioned_class)
-            new_model[self.class.versioned_inheritance_column] = orig_model[orig_model.class.inheritance_column]
+                                       if self.class.columns_hash.include?(self.class.inheritance_column)
+            if orig_model.is_a?(self.class.versioned_class)
+              new_model[new_model.class.inheritance_column] = orig_model[self.class.versioned_inheritance_column]
+            elsif new_model.is_a?(self.class.versioned_class)
+              new_model[self.class.versioned_inheritance_column] = orig_model[orig_model.class.inheritance_column]
+            end
           end
         end
 
diff --git a/vendor/plugins/awesome_nested_set/.autotest b/vendor/plugins/awesome_nested_set/.autotest
new file mode 100644 (file)
index 0000000..8614a66
--- /dev/null
@@ -0,0 +1,13 @@
+Autotest.add_hook :initialize do |at|\r
+  at.clear_mappings\r
+\r
+  at.add_mapping %r%^lib/(.*)\.rb$% do |_, m|\r
+    at.files_matching %r%^test/#{m[1]}_test.rb$%\r
+  end\r
+\r
+  at.add_mapping(%r%^test/.*\.rb$%) {|filename, _| filename }\r
+\r
+  at.add_mapping %r%^test/fixtures/(.*)s.yml% do |_, _|\r
+    at.files_matching %r%^test/.*\.rb$%\r
+  end\r
+end
\ No newline at end of file
diff --git a/vendor/plugins/awesome_nested_set/.travis.yml b/vendor/plugins/awesome_nested_set/.travis.yml
new file mode 100644 (file)
index 0000000..8b9a876
--- /dev/null
@@ -0,0 +1,14 @@
+notifications:\r
+  email:\r
+    - parndt@gmail.com\r
+env:\r
+  - DB=sqlite3\r
+  - DB=sqlite3mem\r
+  - DB=postgresql\r
+  - DB=mysql\r
+rvm:\r
+  - 1.8.7\r
+  - 1.9.2\r
+  - 1.9.3\r
+  - rbx-2.0\r
+  - jruby
\ No newline at end of file
diff --git a/vendor/plugins/awesome_nested_set/CHANGELOG b/vendor/plugins/awesome_nested_set/CHANGELOG
new file mode 100644 (file)
index 0000000..140164f
--- /dev/null
@@ -0,0 +1,14 @@
+2.0.2
+* Fixed deprecation warning under Rails 3.1 [Philip Arndt]
+* Converted Test::Unit matchers to RSpec. [UÄ£is Ozols]
+* Added inverse_of to associations to improve performance rendering trees. [Sergio Cambra]
+* Added row locking and fixed some race conditions. [Markus J. Q. Roberts]
+
+2.0.1
+* Fixed a bug with move_to not using nested_set_scope [Andreas Sekine]
+
+2.0.0.pre
+* Expect Rails 3
+* Changed how callbacks work. Returning false in a before_move action does not block save operations. Use a validation or exception in the callback if you need that.
+* Switched to RSpec
+* Remove use of Comparable
index 570ecf870677bf8d573ff4f0a8fa6bd8be42792e..7cdb82927dce0d33f47a2712bfe3eaa5ac66010d 100644 (file)
@@ -1,4 +1,4 @@
-Copyright (c) 2007 [name of plugin creator]
+Copyright (c) 2007-2011 Collective Idea
 
 Permission is hereby granted, free of charge, to any person obtaining
 a copy of this software and associated documentation files (the
index c093f751d95a9bae9a13c852c434e30372313e00..6a7380b600150b8f5d52517030ef8957869c3c5a 100644 (file)
@@ -1,6 +1,8 @@
 = AwesomeNestedSet
 
-Awesome Nested Set is an implementation of the nested set pattern for ActiveRecord models. It is replacement for acts_as_nested_set and BetterNestedSet, but awesomer.
+Awesome Nested Set is an implementation of the nested set pattern for ActiveRecord models. It is replacement for acts_as_nested_set and BetterNestedSet, but more awesome.
+
+Version 2 supports Rails 3. Gem versions prior to 2.0 support Rails 2.
 
 == What makes this so awesome?
 
@@ -8,10 +10,10 @@ This is a new implementation of nested set based off of BetterNestedSet that fix
 
 == Installation
 
-If you are on Rails 2.1 or later:
+  Add to your Gemfile:
+
+  gem 'awesome_nested_set'
 
-  script/plugin install git://github.com/collectiveidea/awesome_nested_set.git
-  
 == Usage
 
 To make use of awesome_nested_set, your model needs to have 3 fields: lft, rgt, and parent_id:
@@ -36,12 +38,36 @@ Enable the nested set functionality by declaring acts_as_nested_set on your mode
   class Category < ActiveRecord::Base
     acts_as_nested_set
   end
-  
-Run `rake rdoc` to generate the API docs and see CollectiveIdea::Acts::NestedSet::SingletonMethods for more info.
+
+Run `rake rdoc` to generate the API docs and see CollectiveIdea::Acts::NestedSet for more info.
+
+== Protecting attributes from mass assignment
+
+It's generally best to "white list" the attributes that can be used in mass assignment:
+
+  class Category < ActiveRecord::Base
+    acts_as_nested_set
+    attr_accessible :name, :parent_id
+  end
+
+If for some reason that is not possible, you will probably want to protect the lft and rgt attributes:
+
+  class Category < ActiveRecord::Base
+    acts_as_nested_set
+    attr_protected :lft, :rgt
+  end
+
+== Conversion from other trees
+
+Coming from acts_as_tree or another system where you only have a parent_id? No problem. Simply add the lft & rgt fields as above, and then run
+
+  Category.rebuild!
+
+Your tree will be converted to a valid nested set. Awesome!
 
 == View Helper
 
-The view helper is called #nested_set_options. 
+The view helper is called #nested_set_options.
 
 Example usage:
 
@@ -53,12 +79,22 @@ See CollectiveIdea::Acts::NestedSet::Helper for more information about the helpe
 
 == References
 
-You can learn more about nested sets at:
+You can learn more about nested sets at: http://threebit.net/tutorials/nestedset/tutorial1.html
+
+== How to contribute
+
+If you find what you might think is a bug:
+
+1. Check the GitHub issue tracker to see if anyone else has had the same issue.
+   http://github.com/collectiveidea/awesome_nested_set/issues/
+2. If you don't see anything, create an issue with information on how to reproduce it.
 
-  http://www.dbmsmag.com/9603d06.html
-  http://threebit.net/tutorials/nestedset/tutorial1.html
-  http://api.rubyonrails.com/classes/ActiveRecord/Acts/NestedSet/ClassMethods.html
-  http://opensource.symetrie.com/trac/better_nested_set/
+If you want to contribute an enhancement or a fix:
 
+1. Fork the project on github.
+   http://github.com/collectiveidea/awesome_nested_set/
+2. Make your changes with tests.
+3. Commit the changes without making changes to the Rakefile, VERSION, or any other files that aren't related to your enhancement or fix
+4. Send a pull request.
 
-Copyright (c) 2008 Collective Idea, released under the MIT license
\ No newline at end of file
+Copyright Â©2008 Collective Idea, released under the MIT license
index 53906f68b314eb69bc38aa47c9b15e4f05b0d40c..b913bc5e2d5e6fc6fc689579a6fe9bfce91b0c56 100644 (file)
@@ -1,30 +1,23 @@
-require 'rake'
-require 'rake/testtask'
-require 'rake/rdoctask'
-require 'rake/gempackagetask'
-require 'rcov/rcovtask'
-require "load_multi_rails_rake_tasks" 
+# -*- encoding: utf-8 -*-
+$LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
+require 'rubygems'
+require 'bundler/setup'
+require 'awesome_nested_set/version'
 
-spec = eval(File.read("#{File.dirname(__FILE__)}/awesome_nested_set.gemspec"))
-PKG_NAME = spec.name
-PKG_VERSION = spec.version
-Rake::GemPackageTask.new(spec) do |pkg|
-  pkg.need_zip = true
-  pkg.need_tar = true
-end
+require "rspec/core/rake_task"
+RSpec::Core::RakeTask.new(:spec)
 
+task :default => :spec
 
-desc 'Default: run unit tests.'
-task :default => :test
+task :build do
+  system "gem build awesome_nested_set.gemspec"
+end
 
-desc 'Test the awesome_nested_set plugin.'
-Rake::TestTask.new(:test) do |t|
-  t.libs << 'lib'
-  t.pattern = 'test/**/*_test.rb'
-  t.verbose = true
+task :release => :build do
+  system "gem push awesome_nested_set-#{ActsAsGeocodable::VERSION}.gem"
 end
 
+require 'rdoc/task'
 desc 'Generate documentation for the awesome_nested_set plugin.'
 Rake::RDocTask.new(:rdoc) do |rdoc|
   rdoc.rdoc_dir = 'rdoc'
@@ -33,14 +26,3 @@ Rake::RDocTask.new(:rdoc) do |rdoc|
   rdoc.rdoc_files.include('README.rdoc')
   rdoc.rdoc_files.include('lib/**/*.rb')
 end
-
-namespace :test do
-  desc "just rcov minus html output"
-  Rcov::RcovTask.new(:coverage) do |t|
-    # t.libs << 'test'
-    t.test_files = FileList['test/**/*_test.rb']
-    t.output_dir = 'coverage'
-    t.verbose = true
-    t.rcov_opts = %w(--exclude test,/usr/lib/ruby,/Library/Ruby,lib/awesome_nested_set/named_scope.rb --sort coverage)
-  end
-end
\ No newline at end of file
index c5a1d49e5bc9f638fb1cd4b90a5b1fae76aa2704..8e85d6733114a3983e2802eb3230b4f2314cb308 100644 (file)
@@ -1,20 +1,22 @@
+# -*- encoding: utf-8 -*-
+lib = File.expand_path('../lib/', __FILE__)
+$:.unshift lib unless $:.include?(lib)
+require 'awesome_nested_set/version'
+
 Gem::Specification.new do |s|
-  s.name = "awesome_nested_set"
-  s.version = "1.1.1"
-  s.summary = "An awesome replacement for acts_as_nested_set and better_nested_set."
-  s.description = s.summary
-  s.files = %w(init.rb MIT-LICENSE Rakefile README.rdoc lib/awesome_nested_set.rb lib/awesome_nested_set/compatability.rb lib/awesome_nested_set/helper.rb lib/awesome_nested_set/named_scope.rb rails/init.rb test/awesome_nested_set_test.rb test/test_helper.rb test/awesome_nested_set/helper_test.rb test/db/database.yml test/db/schema.rb test/fixtures/categories.yml test/fixtures/category.rb test/fixtures/departments.yml test/fixtures/notes.yml)
-  s.add_dependency "activerecord", ['>= 1.1']
-  s.has_rdoc = true
-  s.extra_rdoc_files = [ "README.rdoc"]
+  s.name = %q{awesome_nested_set}
+  s.version = ::AwesomeNestedSet::VERSION
+  s.authors = ["Brandon Keepers", "Daniel Morrison", "Philip Arndt"]
+  s.description = %q{An awesome nested set implementation for Active Record}
+  s.email = %q{info@collectiveidea.com}
+  s.extra_rdoc_files = [
+    "README.rdoc"
+  ]
+  s.files = Dir.glob("lib/**/*") + %w(MIT-LICENSE README.rdoc CHANGELOG)
+  s.homepage = %q{http://github.com/collectiveidea/awesome_nested_set}
   s.rdoc_options = ["--main", "README.rdoc", "--inline-source", "--line-numbers"]
-  s.test_files = %w(test/awesome_nested_set_test.rb test/test_helper.rb test/awesome_nested_set/helper_test.rb test/db/database.yml test/db/schema.rb test/fixtures/categories.yml test/fixtures/category.rb test/fixtures/departments.yml test/fixtures/notes.yml)
-  s.require_path = 'lib'
-  s.author = "Collective Idea"
-  s.email = "info@collectiveidea.com"
-  s.homepage = "http://collectiveidea.com"
+  s.require_paths = ["lib"]
+  s.rubygems_version = %q{1.3.6}
+  s.summary = %q{An awesome nested set implementation for Active Record}
+  s.add_runtime_dependency 'activerecord', '>= 3.0.0'
 end
index 43dc7c274ef242403e560e493f0d6dd132d65877..a505b6acf25146f05fca3bf6fe5d9472fedf8440 100644 (file)
@@ -1 +1 @@
-require File.dirname(__FILE__) + "/rails/init"  
+require File.dirname(__FILE__) + '/lib/awesome_nested_set'
\ No newline at end of file
index e14b9d75f0bf2ec80d5925deb32817a2e2fcba3a..022044275ba3099c815cc0fa24ce3d35c3c5f4b5 100644 (file)
@@ -1,554 +1,7 @@
-module CollectiveIdea #:nodoc:
-  module Acts #:nodoc:
-    module NestedSet #:nodoc:
-      def self.included(base)
-        base.extend(SingletonMethods)
-      end
+require 'awesome_nested_set/awesome_nested_set'
+ActiveRecord::Base.send :extend, CollectiveIdea::Acts::NestedSet
 
-      # This acts provides Nested Set functionality. Nested Set is a smart way to implement
-      # an _ordered_ tree, with the added feature that you can select the children and all of their
-      # descendants with a single query. The drawback is that insertion or move need some complex
-      # sql queries. But everything is done here by this module!
-      #
-      # Nested sets are appropriate each time you want either an orderd tree (menus,
-      # commercial categories) or an efficient way of querying big trees (threaded posts).
-      #
-      # == API
-      #
-      # Methods names are aligned with acts_as_tree as much as possible, to make replacment from one
-      # by another easier, except for the creation:
-      #
-      # in acts_as_tree:
-      #   item.children.create(:name => "child1")
-      #
-      # in acts_as_nested_set:
-      #   # adds a new item at the "end" of the tree, i.e. with child.left = max(tree.right)+1
-      #   child = MyClass.new(:name => "child1")
-      #   child.save
-      #   # now move the item to its right place
-      #   child.move_to_child_of my_item
-      #
-      # You can pass an id or an object to:
-      # * <tt>#move_to_child_of</tt>
-      # * <tt>#move_to_right_of</tt>
-      # * <tt>#move_to_left_of</tt>
-      #
-      module SingletonMethods
-        # Configuration options are:
-        #
-        # * +:parent_column+ - specifies the column name to use for keeping the position integer (default: parent_id)
-        # * +:left_column+ - column name for left boundry data, default "lft"
-        # * +:right_column+ - column name for right boundry data, default "rgt"
-        # * +:scope+ - restricts what is to be considered a list. Given a symbol, it'll attach "_id"
-        #   (if it hasn't been already) and use that as the foreign key restriction. You
-        #   can also pass an array to scope by multiple attributes.
-        #   Example: <tt>acts_as_nested_set :scope => [:notable_id, :notable_type]</tt>
-        # * +:dependent+ - behavior for cascading destroy. If set to :destroy, all the
-        #   child objects are destroyed alongside this object by calling their destroy
-        #   method. If set to :delete_all (default), all the child objects are deleted
-        #   without calling their destroy method.
-        #
-        # See CollectiveIdea::Acts::NestedSet::ClassMethods for a list of class methods and
-        # CollectiveIdea::Acts::NestedSet::InstanceMethods for a list of instance methods added 
-        # to acts_as_nested_set models
-        def acts_as_nested_set(options = {})
-          options = {
-            :parent_column => 'parent_id',
-            :left_column => 'lft',
-            :right_column => 'rgt',
-            :order => 'id',
-            :dependent => :delete_all, # or :destroy
-          }.merge(options)
-          
-          if options[:scope].is_a?(Symbol) && options[:scope].to_s !~ /_id$/
-            options[:scope] = "#{options[:scope]}_id".intern
-          end
-
-          write_inheritable_attribute :acts_as_nested_set_options, options
-          class_inheritable_reader :acts_as_nested_set_options
-          
-          include Comparable
-          include Columns
-          include InstanceMethods
-          extend Columns
-          extend ClassMethods
-
-          # no bulk assignment
-          attr_protected  left_column_name.intern,
-                          right_column_name.intern, 
-                          parent_column_name.intern
-                          
-          before_create :set_default_left_and_right
-          before_destroy :prune_from_tree
-                          
-          # no assignment to structure fields
-          [left_column_name, right_column_name, parent_column_name].each do |column|
-            module_eval <<-"end_eval", __FILE__, __LINE__
-              def #{column}=(x)
-                raise ActiveRecord::ActiveRecordError, "Unauthorized assignment to #{column}: it's an internal field handled by acts_as_nested_set code, use move_to_* methods instead."
-              end
-            end_eval
-          end
-          
-          named_scope :roots, :conditions => {parent_column_name => nil}, :order => quoted_left_column_name
-          named_scope :leaves, :conditions => "#{quoted_right_column_name} - #{quoted_left_column_name} = 1", :order => quoted_left_column_name
-          if self.respond_to?(:define_callbacks)
-            define_callbacks("before_move", "after_move")              
-          end
-
-          
-        end
-        
-      end
-      
-      module ClassMethods
-        
-        # Returns the first root
-        def root
-          roots.find(:first)
-        end
-        
-        def valid?
-          left_and_rights_valid? && no_duplicates_for_columns? && all_roots_valid?
-        end
-        
-        def left_and_rights_valid?
-          count(
-            :joins => "LEFT OUTER JOIN #{quoted_table_name} AS parent ON " +
-              "#{quoted_table_name}.#{quoted_parent_column_name} = parent.#{primary_key}",
-            :conditions =>
-              "#{quoted_table_name}.#{quoted_left_column_name} IS NULL OR " +
-              "#{quoted_table_name}.#{quoted_right_column_name} IS NULL OR " +
-              "#{quoted_table_name}.#{quoted_left_column_name} >= " +
-                "#{quoted_table_name}.#{quoted_right_column_name} OR " +
-              "(#{quoted_table_name}.#{quoted_parent_column_name} IS NOT NULL AND " +
-                "(#{quoted_table_name}.#{quoted_left_column_name} <= parent.#{quoted_left_column_name} OR " +
-                "#{quoted_table_name}.#{quoted_right_column_name} >= parent.#{quoted_right_column_name}))"
-          ) == 0
-        end
-        
-        def no_duplicates_for_columns?
-          scope_string = Array(acts_as_nested_set_options[:scope]).map do |c|
-            connection.quote_column_name(c)
-          end.push(nil).join(", ")
-          [quoted_left_column_name, quoted_right_column_name].all? do |column|
-            # No duplicates
-            find(:first, 
-              :select => "#{scope_string}#{column}, COUNT(#{column})", 
-              :group => "#{scope_string}#{column} 
-                HAVING COUNT(#{column}) > 1").nil?
-          end
-        end
-        
-        # Wrapper for each_root_valid? that can deal with scope.
-        def all_roots_valid?
-          if acts_as_nested_set_options[:scope]
-            roots(:group => scope_column_names).group_by{|record| scope_column_names.collect{|col| record.send(col.to_sym)}}.all? do |scope, grouped_roots|
-              each_root_valid?(grouped_roots)
-            end
-          else
-            each_root_valid?(roots)
-          end
-        end
-        
-        def each_root_valid?(roots_to_validate)
-          left = right = 0
-          roots_to_validate.all? do |root|
-            (root.left > left && root.right > right).tap do
-              left = root.left
-              right = root.right
-            end
-          end
-        end
-                
-        # Rebuilds the left & rights if unset or invalid.  Also very useful for converting from acts_as_tree.
-        def rebuild!(force=false)
-          # Don't rebuild a valid tree.
-          # valid? doesn't strictly validate the tree
-          return true if !force && valid?
-          
-          scope = lambda{|node|}
-          if acts_as_nested_set_options[:scope]
-            scope = lambda{|node| 
-              scope_column_names.inject(""){|str, column_name|
-                str << "AND #{connection.quote_column_name(column_name)} = #{connection.quote(node.send(column_name.to_sym))} "
-              }
-            }
-          end
-          indices = {}
-          
-          set_left_and_rights = lambda do |node|
-            # set left
-            node[left_column_name] = indices[scope.call(node)] += 1
-            # find
-            find(:all, :conditions => ["#{quoted_parent_column_name} = ? #{scope.call(node)}", node], :order => "#{quoted_left_column_name}, #{quoted_right_column_name}, #{acts_as_nested_set_options[:order]}").each{|n| set_left_and_rights.call(n) }
-            # set right
-            node[right_column_name] = indices[scope.call(node)] += 1    
-            node.save!    
-          end
-                              
-          # Find root node(s)
-          root_nodes = find(:all, :conditions => "#{quoted_parent_column_name} IS NULL", :order => "#{quoted_left_column_name}, #{quoted_right_column_name}, #{acts_as_nested_set_options[:order]}").each do |root_node|
-            # setup index for this scope
-            indices[scope.call(root_node)] ||= 0
-            set_left_and_rights.call(root_node)
-          end
-        end
-      end
-      
-      # Mixed into both classes and instances to provide easy access to the column names
-      module Columns
-        def left_column_name
-          acts_as_nested_set_options[:left_column]
-        end
-        
-        def right_column_name
-          acts_as_nested_set_options[:right_column]
-        end
-        
-        def parent_column_name
-          acts_as_nested_set_options[:parent_column]
-        end
-        
-        def scope_column_names
-          Array(acts_as_nested_set_options[:scope])
-        end
-        
-        def quoted_left_column_name
-          connection.quote_column_name(left_column_name)
-        end
-        
-        def quoted_right_column_name
-          connection.quote_column_name(right_column_name)
-        end
-        
-        def quoted_parent_column_name
-          connection.quote_column_name(parent_column_name)
-        end
-        
-        def quoted_scope_column_names
-          scope_column_names.collect {|column_name| connection.quote_column_name(column_name) }
-        end
-      end
-
-      # Any instance method that returns a collection makes use of Rails 2.1's named_scope (which is bundled for Rails 2.0), so it can be treated as a finder.
-      #
-      #   category.self_and_descendants.count
-      #   category.ancestors.find(:all, :conditions => "name like '%foo%'")
-      module InstanceMethods
-        # Value of the parent column
-        def parent_id
-          self[parent_column_name]
-        end
-        
-        # Value of the left column
-        def left
-          self[left_column_name]
-        end
-        
-        # Value of the right column
-        def right
-          self[right_column_name]
-        end
-
-        # Returns true if this is a root node.
-        def root?
-          parent_id.nil?
-        end
-        
-        def leaf?
-          new_record? || (right - left == 1)
-        end
-
-        # Returns true is this is a child node
-        def child?
-          !parent_id.nil?
-        end
-
-        # order by left column
-        def <=>(x)
-          left <=> x.left
-        end
-        
-        # Redefine to act like active record
-        def ==(comparison_object)
-          comparison_object.equal?(self) ||
-            (comparison_object.instance_of?(self.class) &&
-              comparison_object.id == id &&
-              !comparison_object.new_record?)
-        end
-
-        # Returns root
-        def root
-          self_and_ancestors.find(:first)
-        end
-
-        # Returns the immediate parent
-        def parent
-          nested_set_scope.find_by_id(parent_id) if parent_id
-        end
-
-        # Returns the array of all parents and self
-        def self_and_ancestors
-          nested_set_scope.scoped :conditions => [
-            "#{self.class.table_name}.#{quoted_left_column_name} <= ? AND #{self.class.table_name}.#{quoted_right_column_name} >= ?", left, right
-          ]
-        end
-
-        # Returns an array of all parents
-        def ancestors
-          without_self self_and_ancestors
-        end
-
-        # Returns the array of all children of the parent, including self
-        def self_and_siblings
-          nested_set_scope.scoped :conditions => {parent_column_name => parent_id}
-        end
-
-        # Returns the array of all children of the parent, except self
-        def siblings
-          without_self self_and_siblings
-        end
-
-        # Returns a set of all of its nested children which do not have children  
-        def leaves
-          descendants.scoped :conditions => "#{self.class.table_name}.#{quoted_right_column_name} - #{self.class.table_name}.#{quoted_left_column_name} = 1"
-        end    
-
-        # Returns the level of this object in the tree
-        # root level is 0
-        def level
-          parent_id.nil? ? 0 : ancestors.count
-        end
-
-        # Returns a set of itself and all of its nested children
-        def self_and_descendants
-          nested_set_scope.scoped :conditions => [
-            "#{self.class.table_name}.#{quoted_left_column_name} >= ? AND #{self.class.table_name}.#{quoted_right_column_name} <= ?", left, right
-          ]
-        end
-
-        # Returns a set of all of its children and nested children
-        def descendants
-          without_self self_and_descendants
-        end
-
-        # Returns a set of only this entry's immediate children
-        def children
-          nested_set_scope.scoped :conditions => {parent_column_name => self}
-        end
-
-        def is_descendant_of?(other)
-          other.left < self.left && self.left < other.right && same_scope?(other)
-        end
-        
-        def is_or_is_descendant_of?(other)
-          other.left <= self.left && self.left < other.right && same_scope?(other)
-        end
-
-        def is_ancestor_of?(other)
-          self.left < other.left && other.left < self.right && same_scope?(other)
-        end
-        
-        def is_or_is_ancestor_of?(other)
-          self.left <= other.left && other.left < self.right && same_scope?(other)
-        end
-        
-        # Check if other model is in the same scope
-        def same_scope?(other)
-          Array(acts_as_nested_set_options[:scope]).all? do |attr|
-            self.send(attr) == other.send(attr)
-          end
-        end
-
-        # Find the first sibling to the left
-        def left_sibling
-          siblings.find(:first, :conditions => ["#{self.class.table_name}.#{quoted_left_column_name} < ?", left],
-            :order => "#{self.class.table_name}.#{quoted_left_column_name} DESC")
-        end
-
-        # Find the first sibling to the right
-        def right_sibling
-          siblings.find(:first, :conditions => ["#{self.class.table_name}.#{quoted_left_column_name} > ?", left])
-        end
-
-        # Shorthand method for finding the left sibling and moving to the left of it.
-        def move_left
-          move_to_left_of left_sibling
-        end
-
-        # Shorthand method for finding the right sibling and moving to the right of it.
-        def move_right
-          move_to_right_of right_sibling
-        end
-
-        # Move the node to the left of another node (you can pass id only)
-        def move_to_left_of(node)
-          move_to node, :left
-        end
-
-        # Move the node to the left of another node (you can pass id only)
-        def move_to_right_of(node)
-          move_to node, :right
-        end
-
-        # Move the node to the child of another node (you can pass id only)
-        def move_to_child_of(node)
-          move_to node, :child
-        end
-        
-        # Move the node to root nodes
-        def move_to_root
-          move_to nil, :root
-        end
-        
-        def move_possible?(target)
-          self != target && # Can't target self
-          same_scope?(target) && # can't be in different scopes
-          # !(left..right).include?(target.left..target.right) # this needs tested more
-          # detect impossible move
-          !((left <= target.left && right >= target.left) or (left <= target.right && right >= target.right))
-        end
-        
-        def to_text
-          self_and_descendants.map do |node|
-            "#{'*'*(node.level+1)} #{node.id} #{node.to_s} (#{node.parent_id}, #{node.left}, #{node.right})"
-          end.join("\n")
-        end
-        
-      protected
-      
-        def without_self(scope)
-          scope.scoped :conditions => ["#{self.class.table_name}.#{self.class.primary_key} != ?", self]
-        end
-        
-        # All nested set queries should use this nested_set_scope, which performs finds on
-        # the base ActiveRecord class, using the :scope declared in the acts_as_nested_set
-        # declaration.
-        def nested_set_scope
-          options = {:order => "#{self.class.table_name}.#{quoted_left_column_name}"}
-          scopes = Array(acts_as_nested_set_options[:scope])
-          options[:conditions] = scopes.inject({}) do |conditions,attr|
-            conditions.merge attr => self[attr]
-          end unless scopes.empty?
-          self.class.base_class.scoped options
-        end
-        
-        # on creation, set automatically lft and rgt to the end of the tree
-        def set_default_left_and_right
-          maxright = nested_set_scope.maximum(right_column_name) || 0
-          # adds the new node to the right of all existing nodes
-          self[left_column_name] = maxright + 1
-          self[right_column_name] = maxright + 2
-        end
-      
-        # Prunes a branch off of the tree, shifting all of the elements on the right
-        # back to the left so the counts still work.
-        def prune_from_tree
-          return if right.nil? || left.nil? || !self.class.exists?(id)
-
-          self.class.base_class.transaction do
-            reload_nested_set
-            if acts_as_nested_set_options[:dependent] == :destroy
-              children.each(&:destroy)
-            else
-              nested_set_scope.send(:delete_all,
-                ["#{quoted_left_column_name} > ? AND #{quoted_right_column_name} < ?",
-                  left, right]
-              )
-            end
-            reload_nested_set
-            diff = right - left + 1
-            nested_set_scope.update_all(
-              ["#{quoted_left_column_name} = (#{quoted_left_column_name} - ?)", diff],
-              ["#{quoted_left_column_name} >= ?", right]
-            )
-            nested_set_scope.update_all(
-              ["#{quoted_right_column_name} = (#{quoted_right_column_name} - ?)", diff],
-              ["#{quoted_right_column_name} >= ?", right]
-            )
-          end
-          
-          # Reload is needed because children may have updated their parent (self) during deletion.
-          reload
-        end
-
-        # reload left, right, and parent
-        def reload_nested_set
-          reload(:select => "#{quoted_left_column_name}, " +
-            "#{quoted_right_column_name}, #{quoted_parent_column_name}")
-        end
-        
-        def move_to(target, position)
-          raise ActiveRecord::ActiveRecordError, "You cannot move a new node" if self.new_record?
-          return if callback(:before_move) == false
-          transaction do
-            if target.is_a? self.class.base_class
-              target.reload_nested_set
-            elsif position != :root
-              # load object if node is not an object
-              target = nested_set_scope.find(target)
-            end
-            self.reload_nested_set
-          
-            unless position == :root || move_possible?(target)
-              raise ActiveRecord::ActiveRecordError, "Impossible move, target node cannot be inside moved tree."
-            end
-            
-            bound = case position
-              when :child;  target[right_column_name]
-              when :left;   target[left_column_name]
-              when :right;  target[right_column_name] + 1
-              when :root;   1
-              else raise ActiveRecord::ActiveRecordError, "Position should be :child, :left, :right or :root ('#{position}' received)."
-            end
-          
-            if bound > self[right_column_name]
-              bound = bound - 1
-              other_bound = self[right_column_name] + 1
-            else
-              other_bound = self[left_column_name] - 1
-            end
-
-            # there would be no change
-            return if bound == self[right_column_name] || bound == self[left_column_name]
-          
-            # we have defined the boundaries of two non-overlapping intervals, 
-            # so sorting puts both the intervals and their boundaries in order
-            a, b, c, d = [self[left_column_name], self[right_column_name], bound, other_bound].sort
-
-            new_parent = case position
-              when :child;  target.id
-              when :root;   nil
-              else          target[parent_column_name]
-            end
-
-            self.class.base_class.update_all([
-              "#{quoted_left_column_name} = CASE " +
-                "WHEN #{quoted_left_column_name} BETWEEN :a AND :b " +
-                  "THEN #{quoted_left_column_name} + :d - :b " +
-                "WHEN #{quoted_left_column_name} BETWEEN :c AND :d " +
-                  "THEN #{quoted_left_column_name} + :a - :c " +
-                "ELSE #{quoted_left_column_name} END, " +
-              "#{quoted_right_column_name} = CASE " +
-                "WHEN #{quoted_right_column_name} BETWEEN :a AND :b " +
-                  "THEN #{quoted_right_column_name} + :d - :b " +
-                "WHEN #{quoted_right_column_name} BETWEEN :c AND :d " +
-                  "THEN #{quoted_right_column_name} + :a - :c " +
-                "ELSE #{quoted_right_column_name} END, " +
-              "#{quoted_parent_column_name} = CASE " +
-                "WHEN #{self.class.base_class.primary_key} = :id THEN :new_parent " +
-                "ELSE #{quoted_parent_column_name} END",
-              {:a => a, :b => b, :c => c, :d => d, :id => self.id, :new_parent => new_parent}
-            ], nested_set_scope.proxy_options[:conditions])
-          end
-          target.reload_nested_set if target
-          self.reload_nested_set
-          callback(:after_move)
-        end
-
-      end
-      
-    end
-  end
-end
+if defined?(ActionView)
+  require 'awesome_nested_set/helper'
+  ActionView::Base.send :include, CollectiveIdea::Acts::NestedSet::Helper
+end
\ No newline at end of file
diff --git a/vendor/plugins/awesome_nested_set/lib/awesome_nested_set/awesome_nested_set.rb b/vendor/plugins/awesome_nested_set/lib/awesome_nested_set/awesome_nested_set.rb
new file mode 100644 (file)
index 0000000..9608806
--- /dev/null
@@ -0,0 +1,603 @@
+module CollectiveIdea #:nodoc:
+  module Acts #:nodoc:
+    module NestedSet #:nodoc:
+
+      # This acts provides Nested Set functionality. Nested Set is a smart way to implement
+      # an _ordered_ tree, with the added feature that you can select the children and all of their
+      # descendants with a single query. The drawback is that insertion or move need some complex
+      # sql queries. But everything is done here by this module!
+      #
+      # Nested sets are appropriate each time you want either an orderd tree (menus,
+      # commercial categories) or an efficient way of querying big trees (threaded posts).
+      #
+      # == API
+      #
+      # Methods names are aligned with acts_as_tree as much as possible to make replacment from one
+      # by another easier.
+      #
+      #   item.children.create(:name => "child1")
+      #
+
+      # Configuration options are:
+      #
+      # * +:parent_column+ - specifies the column name to use for keeping the position integer (default: parent_id)
+      # * +:left_column+ - column name for left boundry data, default "lft"
+      # * +:right_column+ - column name for right boundry data, default "rgt"
+      # * +:scope+ - restricts what is to be considered a list. Given a symbol, it'll attach "_id"
+      #   (if it hasn't been already) and use that as the foreign key restriction. You
+      #   can also pass an array to scope by multiple attributes.
+      #   Example: <tt>acts_as_nested_set :scope => [:notable_id, :notable_type]</tt>
+      # * +:dependent+ - behavior for cascading destroy. If set to :destroy, all the
+      #   child objects are destroyed alongside this object by calling their destroy
+      #   method. If set to :delete_all (default), all the child objects are deleted
+      #   without calling their destroy method.
+      # * +:counter_cache+ adds a counter cache for the number of children.
+      #   defaults to false.
+      #   Example: <tt>acts_as_nested_set :counter_cache => :children_count</tt>
+      #
+      # See CollectiveIdea::Acts::NestedSet::Model::ClassMethods for a list of class methods and
+      # CollectiveIdea::Acts::NestedSet::Model::InstanceMethods for a list of instance methods added
+      # to acts_as_nested_set models
+      def acts_as_nested_set(options = {})
+        options = {
+          :parent_column => 'parent_id',
+          :left_column => 'lft',
+          :right_column => 'rgt',
+          :dependent => :delete_all, # or :destroy
+          :counter_cache => false,
+          :order => 'id'
+        }.merge(options)
+
+        if options[:scope].is_a?(Symbol) && options[:scope].to_s !~ /_id$/
+          options[:scope] = "#{options[:scope]}_id".intern
+        end
+
+        class_attribute :acts_as_nested_set_options
+        self.acts_as_nested_set_options = options
+
+        include CollectiveIdea::Acts::NestedSet::Model
+        include Columns
+        extend Columns
+
+        belongs_to :parent, :class_name => self.base_class.to_s,
+          :foreign_key => parent_column_name,
+          :counter_cache => options[:counter_cache],
+          :inverse_of => :children
+        has_many :children, :class_name => self.base_class.to_s,
+          :foreign_key => parent_column_name, :order => left_column_name,
+          :inverse_of => :parent,
+          :before_add    => options[:before_add],
+          :after_add     => options[:after_add],
+          :before_remove => options[:before_remove],
+          :after_remove  => options[:after_remove]
+
+        attr_accessor :skip_before_destroy
+
+        before_create  :set_default_left_and_right
+        before_save    :store_new_parent
+        after_save     :move_to_new_parent
+        before_destroy :destroy_descendants
+
+        # no assignment to structure fields
+        [left_column_name, right_column_name].each do |column|
+          module_eval <<-"end_eval", __FILE__, __LINE__
+            def #{column}=(x)
+              raise ActiveRecord::ActiveRecordError, "Unauthorized assignment to #{column}: it's an internal field handled by acts_as_nested_set code, use move_to_* methods instead."
+            end
+          end_eval
+        end
+
+        define_model_callbacks :move
+      end
+
+      module Model
+        extend ActiveSupport::Concern
+
+        module ClassMethods
+          # Returns the first root
+          def root
+            roots.first
+          end
+
+          def roots
+            where(parent_column_name => nil).order(quoted_left_column_name)
+          end
+
+          def leaves
+            where("#{quoted_right_column_name} - #{quoted_left_column_name} = 1").order(quoted_left_column_name)
+          end
+
+          def valid?
+            left_and_rights_valid? && no_duplicates_for_columns? && all_roots_valid?
+          end
+
+          def left_and_rights_valid?
+            joins("LEFT OUTER JOIN #{quoted_table_name} AS parent ON " +
+                "#{quoted_table_name}.#{quoted_parent_column_name} = parent.#{primary_key}").
+            where(
+                "#{quoted_table_name}.#{quoted_left_column_name} IS NULL OR " +
+                "#{quoted_table_name}.#{quoted_right_column_name} IS NULL OR " +
+                "#{quoted_table_name}.#{quoted_left_column_name} >= " +
+                  "#{quoted_table_name}.#{quoted_right_column_name} OR " +
+                "(#{quoted_table_name}.#{quoted_parent_column_name} IS NOT NULL AND " +
+                  "(#{quoted_table_name}.#{quoted_left_column_name} <= parent.#{quoted_left_column_name} OR " +
+                  "#{quoted_table_name}.#{quoted_right_column_name} >= parent.#{quoted_right_column_name}))"
+            ).count == 0
+          end
+
+          def no_duplicates_for_columns?
+            scope_string = Array(acts_as_nested_set_options[:scope]).map do |c|
+              connection.quote_column_name(c)
+            end.push(nil).join(", ")
+            [quoted_left_column_name, quoted_right_column_name].all? do |column|
+              # No duplicates
+              select("#{scope_string}#{column}, COUNT(#{column})").
+                  group("#{scope_string}#{column}").
+                  having("COUNT(#{column}) > 1").
+                  first.nil?
+            end
+          end
+
+          # Wrapper for each_root_valid? that can deal with scope.
+          def all_roots_valid?
+            if acts_as_nested_set_options[:scope]
+              roots.group(scope_column_names).group_by{|record| scope_column_names.collect{|col| record.send(col.to_sym)}}.all? do |scope, grouped_roots|
+                each_root_valid?(grouped_roots)
+              end
+            else
+              each_root_valid?(roots)
+            end
+          end
+
+          def each_root_valid?(roots_to_validate)
+            left = right = 0
+            roots_to_validate.all? do |root|
+              (root.left > left && root.right > right).tap do
+                left = root.left
+                right = root.right
+              end
+            end
+          end
+
+          # Rebuilds the left & rights if unset or invalid.
+          # Also very useful for converting from acts_as_tree.
+          def rebuild!(validate_nodes = true)
+            # Don't rebuild a valid tree.
+            return true if valid?
+
+            scope = lambda{|node|}
+            if acts_as_nested_set_options[:scope]
+              scope = lambda{|node|
+                scope_column_names.inject(""){|str, column_name|
+                  str << "AND #{connection.quote_column_name(column_name)} = #{connection.quote(node.send(column_name.to_sym))} "
+                }
+              }
+            end
+            indices = {}
+
+            set_left_and_rights = lambda do |node|
+              # set left
+              node[left_column_name] = indices[scope.call(node)] += 1
+              # find
+              where(["#{quoted_parent_column_name} = ? #{scope.call(node)}", node]).order(acts_as_nested_set_options[:order]).each{|n| set_left_and_rights.call(n) }
+              # set right
+              node[right_column_name] = indices[scope.call(node)] += 1
+              node.save!(:validate => validate_nodes)
+            end
+
+            # Find root node(s)
+            root_nodes = where("#{quoted_parent_column_name} IS NULL").order("#{quoted_left_column_name}, #{quoted_right_column_name}, id").each do |root_node|
+              # setup index for this scope
+              indices[scope.call(root_node)] ||= 0
+              set_left_and_rights.call(root_node)
+            end
+          end
+
+          # Iterates over tree elements and determines the current level in the tree.
+          # Only accepts default ordering, odering by an other column than lft
+          # does not work. This method is much more efficent than calling level
+          # because it doesn't require any additional database queries.
+          #
+          # Example:
+          #    Category.each_with_level(Category.root.self_and_descendants) do |o, level|
+          #
+          def each_with_level(objects)
+            path = [nil]
+            objects.each do |o|
+              if o.parent_id != path.last
+                # we are on a new level, did we decent or ascent?
+                if path.include?(o.parent_id)
+                  # remove wrong wrong tailing paths elements
+                  path.pop while path.last != o.parent_id
+                else
+                  path << o.parent_id
+                end
+              end
+              yield(o, path.length - 1)
+            end
+          end
+        end
+
+        # Any instance method that returns a collection makes use of Rails 2.1's named_scope (which is bundled for Rails 2.0), so it can be treated as a finder.
+        #
+        #   category.self_and_descendants.count
+        #   category.ancestors.find(:all, :conditions => "name like '%foo%'")
+        module InstanceMethods
+          # Value of the parent column
+          def parent_id
+            self[parent_column_name]
+          end
+
+          # Value of the left column
+          def left
+            self[left_column_name]
+          end
+
+          # Value of the right column
+          def right
+            self[right_column_name]
+          end
+
+          # Returns true if this is a root node.
+          def root?
+            parent_id.nil?
+          end
+
+          def leaf?
+            new_record? || (right - left == 1)
+          end
+
+          # Returns true is this is a child node
+          def child?
+            !parent_id.nil?
+          end
+
+          # Returns root
+          def root
+            self_and_ancestors.where(parent_column_name => nil).first
+          end
+
+          # Returns the array of all parents and self
+          def self_and_ancestors
+            nested_set_scope.where([
+              "#{self.class.quoted_table_name}.#{quoted_left_column_name} <= ? AND #{self.class.quoted_table_name}.#{quoted_right_column_name} >= ?", left, right
+            ])
+          end
+
+          # Returns an array of all parents
+          def ancestors
+            without_self self_and_ancestors
+          end
+
+          # Returns the array of all children of the parent, including self
+          def self_and_siblings
+            nested_set_scope.where(parent_column_name => parent_id)
+          end
+
+          # Returns the array of all children of the parent, except self
+          def siblings
+            without_self self_and_siblings
+          end
+
+          # Returns a set of all of its nested children which do not have children
+          def leaves
+            descendants.where("#{self.class.quoted_table_name}.#{quoted_right_column_name} - #{self.class.quoted_table_name}.#{quoted_left_column_name} = 1")
+          end
+
+          # Returns the level of this object in the tree
+          # root level is 0
+          def level
+            parent_id.nil? ? 0 : ancestors.count
+          end
+
+          # Returns a set of itself and all of its nested children
+          def self_and_descendants
+            nested_set_scope.where([
+              "#{self.class.quoted_table_name}.#{quoted_left_column_name} >= ? AND #{self.class.quoted_table_name}.#{quoted_right_column_name} <= ?", left, right
+            ])
+          end
+
+          # Returns a set of all of its children and nested children
+          def descendants
+            without_self self_and_descendants
+          end
+
+          def is_descendant_of?(other)
+            other.left < self.left && self.left < other.right && same_scope?(other)
+          end
+
+          def is_or_is_descendant_of?(other)
+            other.left <= self.left && self.left < other.right && same_scope?(other)
+          end
+
+          def is_ancestor_of?(other)
+            self.left < other.left && other.left < self.right && same_scope?(other)
+          end
+
+          def is_or_is_ancestor_of?(other)
+            self.left <= other.left && other.left < self.right && same_scope?(other)
+          end
+
+          # Check if other model is in the same scope
+          def same_scope?(other)
+            Array(acts_as_nested_set_options[:scope]).all? do |attr|
+              self.send(attr) == other.send(attr)
+            end
+          end
+
+          # Find the first sibling to the left
+          def left_sibling
+            siblings.where(["#{self.class.quoted_table_name}.#{quoted_left_column_name} < ?", left]).
+                    order("#{self.class.quoted_table_name}.#{quoted_left_column_name} DESC").last
+          end
+
+          # Find the first sibling to the right
+          def right_sibling
+            siblings.where(["#{self.class.quoted_table_name}.#{quoted_left_column_name} > ?", left]).first
+          end
+
+          # Shorthand method for finding the left sibling and moving to the left of it.
+          def move_left
+            move_to_left_of left_sibling
+          end
+
+          # Shorthand method for finding the right sibling and moving to the right of it.
+          def move_right
+            move_to_right_of right_sibling
+          end
+
+          # Move the node to the left of another node (you can pass id only)
+          def move_to_left_of(node)
+            move_to node, :left
+          end
+
+          # Move the node to the left of another node (you can pass id only)
+          def move_to_right_of(node)
+            move_to node, :right
+          end
+
+          # Move the node to the child of another node (you can pass id only)
+          def move_to_child_of(node)
+            move_to node, :child
+          end
+
+          # Move the node to root nodes
+          def move_to_root
+            move_to nil, :root
+          end
+
+          def move_possible?(target)
+            self != target && # Can't target self
+            same_scope?(target) && # can't be in different scopes
+            # !(left..right).include?(target.left..target.right) # this needs tested more
+            # detect impossible move
+            !((left <= target.left && right >= target.left) or (left <= target.right && right >= target.right))
+          end
+
+          def to_text
+            self_and_descendants.map do |node|
+              "#{'*'*(node.level+1)} #{node.id} #{node.to_s} (#{node.parent_id}, #{node.left}, #{node.right})"
+            end.join("\n")
+          end
+
+        protected
+
+          def without_self(scope)
+            scope.where(["#{self.class.quoted_table_name}.#{self.class.primary_key} != ?", self])
+          end
+
+          # All nested set queries should use this nested_set_scope, which performs finds on
+          # the base ActiveRecord class, using the :scope declared in the acts_as_nested_set
+          # declaration.
+          def nested_set_scope(options = {})
+            options = {:order => "#{self.class.quoted_table_name}.#{quoted_left_column_name}"}.merge(options)
+            scopes = Array(acts_as_nested_set_options[:scope])
+            options[:conditions] = scopes.inject({}) do |conditions,attr|
+              conditions.merge attr => self[attr]
+            end unless scopes.empty?
+            self.class.base_class.scoped options
+          end
+
+          def store_new_parent
+            @move_to_new_parent_id = send("#{parent_column_name}_changed?") ? parent_id : false
+            true # force callback to return true
+          end
+
+          def move_to_new_parent
+            if @move_to_new_parent_id.nil?
+              move_to_root
+            elsif @move_to_new_parent_id
+              move_to_child_of(@move_to_new_parent_id)
+            end
+          end
+
+          # on creation, set automatically lft and rgt to the end of the tree
+          def set_default_left_and_right
+            highest_right_row = nested_set_scope(:order => "#{quoted_right_column_name} desc").find(:first, :limit => 1,:lock => true )
+            maxright = highest_right_row ? (highest_right_row[right_column_name] || 0) : 0
+            # adds the new node to the right of all existing nodes
+            self[left_column_name] = maxright + 1
+            self[right_column_name] = maxright + 2
+          end
+
+          def in_tenacious_transaction(&block)
+            retry_count = 0
+            begin
+              transaction(&block)
+            rescue ActiveRecord::StatementInvalid => error
+              raise unless connection.open_transactions.zero?
+              raise unless error.message =~ /Deadlock found when trying to get lock|Lock wait timeout exceeded/
+              raise unless retry_count < 10
+              retry_count += 1
+              logger.info "Deadlock detected on retry #{retry_count}, restarting transaction"
+              sleep(rand(retry_count)*0.1) # Aloha protocol
+              retry
+            end
+          end
+
+          # Prunes a branch off of the tree, shifting all of the elements on the right
+          # back to the left so the counts still work.
+          def destroy_descendants
+            return if right.nil? || left.nil? || skip_before_destroy
+
+            in_tenacious_transaction do
+              reload_nested_set
+              # select the rows in the model that extend past the deletion point and apply a lock
+              self.class.base_class.find(:all,
+                :select => "id",
+                :conditions => ["#{quoted_left_column_name} >= ?", left],
+                :lock => true
+              )
+
+              if acts_as_nested_set_options[:dependent] == :destroy
+                descendants.each do |model|
+                  model.skip_before_destroy = true
+                  model.destroy
+                end
+              else
+                nested_set_scope.delete_all(
+                  ["#{quoted_left_column_name} > ? AND #{quoted_right_column_name} < ?",
+                    left, right]
+                )
+              end
+
+              # update lefts and rights for remaining nodes
+              diff = right - left + 1
+              nested_set_scope.update_all(
+                ["#{quoted_left_column_name} = (#{quoted_left_column_name} - ?)", diff],
+                ["#{quoted_left_column_name} > ?", right]
+              )
+              nested_set_scope.update_all(
+                ["#{quoted_right_column_name} = (#{quoted_right_column_name} - ?)", diff],
+                ["#{quoted_right_column_name} > ?", right]
+              )
+              
+reload
+              # Don't allow multiple calls to destroy to corrupt the set
+              self.skip_before_destroy = true
+            end
+          end
+
+          # reload left, right, and parent
+          def reload_nested_set
+            reload(
+              :select => "#{quoted_left_column_name}, #{quoted_right_column_name}, #{quoted_parent_column_name}",
+              :lock => true
+            )
+          end
+
+          def move_to(target, position)
+            raise ActiveRecord::ActiveRecordError, "You cannot move a new node" if self.new_record?
+            run_callbacks :move do
+              in_tenacious_transaction do
+                if target.is_a? self.class.base_class
+                  target.reload_nested_set
+                elsif position != :root
+                  # load object if node is not an object
+                  target = nested_set_scope.find(target)
+                end
+                self.reload_nested_set
+
+                unless position == :root || move_possible?(target)
+                  raise ActiveRecord::ActiveRecordError, "Impossible move, target node cannot be inside moved tree."
+                end
+
+                bound = case position
+                  when :child;  target[right_column_name]
+                  when :left;   target[left_column_name]
+                  when :right;  target[right_column_name] + 1
+                  when :root;   1
+                  else raise ActiveRecord::ActiveRecordError, "Position should be :child, :left, :right or :root ('#{position}' received)."
+                end
+
+                if bound > self[right_column_name]
+                  bound = bound - 1
+                  other_bound = self[right_column_name] + 1
+                else
+                  other_bound = self[left_column_name] - 1
+                end
+
+                # there would be no change
+                return if bound == self[right_column_name] || bound == self[left_column_name]
+
+                # we have defined the boundaries of two non-overlapping intervals,
+                # so sorting puts both the intervals and their boundaries in order
+                a, b, c, d = [self[left_column_name], self[right_column_name], bound, other_bound].sort
+
+                # select the rows in the model between a and d, and apply a lock
+                self.class.base_class.select('id').lock(true).where(
+                  ["#{quoted_left_column_name} >= :a and #{quoted_right_column_name} <= :d", {:a => a, :d => d}]
+                )
+
+                new_parent = case position
+                  when :child;  target.id
+                  when :root;   nil
+                  else          target[parent_column_name]
+                end
+
+                self.nested_set_scope.update_all([
+                  "#{quoted_left_column_name} = CASE " +
+                    "WHEN #{quoted_left_column_name} BETWEEN :a AND :b " +
+                      "THEN #{quoted_left_column_name} + :d - :b " +
+                    "WHEN #{quoted_left_column_name} BETWEEN :c AND :d " +
+                      "THEN #{quoted_left_column_name} + :a - :c " +
+                    "ELSE #{quoted_left_column_name} END, " +
+                  "#{quoted_right_column_name} = CASE " +
+                    "WHEN #{quoted_right_column_name} BETWEEN :a AND :b " +
+                      "THEN #{quoted_right_column_name} + :d - :b " +
+                    "WHEN #{quoted_right_column_name} BETWEEN :c AND :d " +
+                      "THEN #{quoted_right_column_name} + :a - :c " +
+                    "ELSE #{quoted_right_column_name} END, " +
+                  "#{quoted_parent_column_name} = CASE " +
+                    "WHEN #{self.class.base_class.primary_key} = :id THEN :new_parent " +
+                    "ELSE #{quoted_parent_column_name} END",
+                  {:a => a, :b => b, :c => c, :d => d, :id => self.id, :new_parent => new_parent}
+                ])
+              end
+              target.reload_nested_set if target
+              self.reload_nested_set
+            end
+          end
+
+        end
+
+      end
+
+      # Mixed into both classes and instances to provide easy access to the column names
+      module Columns
+        def left_column_name
+          acts_as_nested_set_options[:left_column]
+        end
+
+        def right_column_name
+          acts_as_nested_set_options[:right_column]
+        end
+
+        def parent_column_name
+          acts_as_nested_set_options[:parent_column]
+        end
+
+        def scope_column_names
+          Array(acts_as_nested_set_options[:scope])
+        end
+
+        def quoted_left_column_name
+          connection.quote_column_name(left_column_name)
+        end
+
+        def quoted_right_column_name
+          connection.quote_column_name(right_column_name)
+        end
+
+        def quoted_parent_column_name
+          connection.quote_column_name(parent_column_name)
+        end
+
+        def quoted_scope_column_names
+          scope_column_names.collect {|column_name| connection.quote_column_name(column_name) }
+        end
+      end
+
+    end
+  end
+end
diff --git a/vendor/plugins/awesome_nested_set/lib/awesome_nested_set/compatability.rb b/vendor/plugins/awesome_nested_set/lib/awesome_nested_set/compatability.rb
deleted file mode 100644 (file)
index 2d11da3..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-# Rails <2.x doesn't define #except
-class Hash #:nodoc:
-  # Returns a new hash without the given keys.
-  def except(*keys)
-    clone.except!(*keys)
-  end unless method_defined?(:except)
-
-  # Replaces the hash without the given keys.
-  def except!(*keys)
-    keys.map! { |key| convert_key(key) } if respond_to?(:convert_key)
-    keys.each { |key| delete(key) }
-    self
-  end unless method_defined?(:except!)
-end
-
-# NamedScope is new to Rails 2.1
-unless defined? ActiveRecord::NamedScope
-  require 'awesome_nested_set/named_scope'
-  ActiveRecord::Base.class_eval do
-    include CollectiveIdea::NamedScope
-  end
-end
-
-# Rails 1.2.x doesn't define #quoted_table_name
-class ActiveRecord::Base  #:nodoc:
-  def self.quoted_table_name
-    self.connection.quote_column_name(self.table_name)
-  end unless methods.include?('quoted_table_name')
-end
\ No newline at end of file
index 09c803fd0abd64231f858b328e2ea1ce4676a790..bfeb18ce4431f26e5f556dfa869ea7616fe23ac4 100644 (file)
@@ -21,8 +21,12 @@ module CollectiveIdea #:nodoc:
         #     }) %>
         #
         def nested_set_options(class_or_item, mover = nil)
-          class_or_item = class_or_item.roots if class_or_item.is_a?(Class)
-          items = Array(class_or_item)
+          if class_or_item.is_a? Array
+            items = class_or_item.reject { |e| !e.root? }
+          else
+            class_or_item = class_or_item.roots if class_or_item.is_a?(Class)
+            items = Array(class_or_item)
+          end
           result = []
           items.each do |root|
             result += root.self_and_descendants.map do |i|
@@ -32,9 +36,9 @@ module CollectiveIdea #:nodoc:
             end.compact
           end
           result
-        end  
-        
+        end
+
       end
-    end  
+    end
   end
-end
\ No newline at end of file
+end
diff --git a/vendor/plugins/awesome_nested_set/lib/awesome_nested_set/named_scope.rb b/vendor/plugins/awesome_nested_set/lib/awesome_nested_set/named_scope.rb
deleted file mode 100644 (file)
index 1836498..0000000
+++ /dev/null
@@ -1,140 +0,0 @@
-# Taken from Rails 2.1
-module CollectiveIdea #:nodoc:
-  module NamedScope #:nodoc:
-    # All subclasses of ActiveRecord::Base have two named_scopes:
-    # * <tt>all</tt>, which is similar to a <tt>find(:all)</tt> query, and
-    # * <tt>scoped</tt>, which allows for the creation of anonymous scopes, on the fly:
-    #
-    #   Shirt.scoped(:conditions => {:color => 'red'}).scoped(:include => :washing_instructions)
-    #
-    # These anonymous scopes tend to be useful when procedurally generating complex queries, where passing
-    # intermediate values (scopes) around as first-class objects is convenient.
-    def self.included(base)
-      base.class_eval do
-        extend ClassMethods
-        named_scope :scoped, lambda { |scope| scope }
-      end
-    end
-
-    module ClassMethods #:nodoc:
-      def scopes
-        read_inheritable_attribute(:scopes) || write_inheritable_attribute(:scopes, {})
-      end
-
-      # Adds a class method for retrieving and querying objects. A scope represents a narrowing of a database query,
-      # such as <tt>:conditions => {:color => :red}, :select => 'shirts.*', :include => :washing_instructions</tt>.
-      #
-      #   class Shirt < ActiveRecord::Base
-      #     named_scope :red, :conditions => {:color => 'red'}
-      #     named_scope :dry_clean_only, :joins => :washing_instructions, :conditions => ['washing_instructions.dry_clean_only = ?', true]
-      #   end
-      # 
-      # The above calls to <tt>named_scope</tt> define class methods <tt>Shirt.red</tt> and <tt>Shirt.dry_clean_only</tt>. <tt>Shirt.red</tt>, 
-      # in effect, represents the query <tt>Shirt.find(:all, :conditions => {:color => 'red'})</tt>.
-      #
-      # Unlike Shirt.find(...), however, the object returned by <tt>Shirt.red</tt> is not an Array; it resembles the association object
-      # constructed by a <tt>has_many</tt> declaration. For instance, you can invoke <tt>Shirt.red.find(:first)</tt>, <tt>Shirt.red.count</tt>,
-      # <tt>Shirt.red.find(:all, :conditions => {:size => 'small'})</tt>. Also, just
-      # as with the association objects, name scopes acts like an Array, implementing Enumerable; <tt>Shirt.red.each(&block)</tt>,
-      # <tt>Shirt.red.first</tt>, and <tt>Shirt.red.inject(memo, &block)</tt> all behave as if Shirt.red really were an Array.
-      #
-      # These named scopes are composable. For instance, <tt>Shirt.red.dry_clean_only</tt> will produce all shirts that are both red and dry clean only.
-      # Nested finds and calculations also work with these compositions: <tt>Shirt.red.dry_clean_only.count</tt> returns the number of garments
-      # for which these criteria obtain. Similarly with <tt>Shirt.red.dry_clean_only.average(:thread_count)</tt>.
-      #
-      # All scopes are available as class methods on the ActiveRecord descendent upon which the scopes were defined. But they are also available to
-      # <tt>has_many</tt> associations. If,
-      #
-      #   class Person < ActiveRecord::Base
-      #     has_many :shirts
-      #   end
-      #
-      # then <tt>elton.shirts.red.dry_clean_only</tt> will return all of Elton's red, dry clean
-      # only shirts.
-      #
-      # Named scopes can also be procedural.
-      #
-      #   class Shirt < ActiveRecord::Base
-      #     named_scope :colored, lambda { |color|
-      #       { :conditions => { :color => color } }
-      #     }
-      #   end
-      #
-      # In this example, <tt>Shirt.colored('puce')</tt> finds all puce shirts.
-      #
-      # Named scopes can also have extensions, just as with <tt>has_many</tt> declarations:
-      #
-      #   class Shirt < ActiveRecord::Base
-      #     named_scope :red, :conditions => {:color => 'red'} do
-      #       def dom_id
-      #         'red_shirts'
-      #       end
-      #     end
-      #   end
-      #
-      #
-      # For testing complex named scopes, you can examine the scoping options using the
-      # <tt>proxy_options</tt> method on the proxy itself.
-      #
-      #   class Shirt < ActiveRecord::Base
-      #     named_scope :colored, lambda { |color|
-      #       { :conditions => { :color => color } }
-      #     }
-      #   end
-      #
-      #   expected_options = { :conditions => { :colored => 'red' } }
-      #   assert_equal expected_options, Shirt.colored('red').proxy_options
-      def named_scope(name, options = {}, &block)
-        scopes[name] = lambda do |parent_scope, *args|
-          Scope.new(parent_scope, case options
-            when Hash
-              options
-            when Proc
-              options.call(*args)
-          end, &block)
-        end
-        (class << self; self end).instance_eval do
-          define_method name do |*args|
-            scopes[name].call(self, *args)
-          end
-        end
-      end
-    end
-
-    class Scope #:nodoc:
-      attr_reader :proxy_scope, :proxy_options
-      [].methods.each { |m| delegate m, :to => :proxy_found unless m =~ /(^__|^nil\?|^send|class|extend|find|count|sum|average|maximum|minimum|paginate)/ }
-      delegate :scopes, :with_scope, :to => :proxy_scope
-
-      def initialize(proxy_scope, options, &block)
-        [options[:extend]].flatten.each { |extension| extend extension } if options[:extend]
-        extend Module.new(&block) if block_given?
-        @proxy_scope, @proxy_options = proxy_scope, options.except(:extend)
-      end
-
-      def reload
-        load_found; self
-      end
-
-      protected
-      def proxy_found
-        @found || load_found
-      end
-
-      private
-      def method_missing(method, *args, &block)
-        if scopes.include?(method)
-          scopes[method].call(self, *args)
-        else
-          with_scope :find => proxy_options do
-            proxy_scope.send(method, *args, &block)
-          end
-        end
-      end
-
-      def load_found
-        @found = find(:all)
-      end
-    end
-  end
-end
\ No newline at end of file
diff --git a/vendor/plugins/awesome_nested_set/lib/awesome_nested_set/version.rb b/vendor/plugins/awesome_nested_set/lib/awesome_nested_set/version.rb
new file mode 100644 (file)
index 0000000..755256a
--- /dev/null
@@ -0,0 +1,3 @@
+module AwesomeNestedSet
+  VERSION = '2.1.0' unless defined?(::AwesomeNestedSet::VERSION)
+end
diff --git a/vendor/plugins/awesome_nested_set/spec/awesome_nested_set/helper_spec.rb b/vendor/plugins/awesome_nested_set/spec/awesome_nested_set/helper_spec.rb
new file mode 100644 (file)
index 0000000..cc32a0d
--- /dev/null
@@ -0,0 +1,67 @@
+require 'spec_helper'\r
+\r
+describe "Helper" do\r
+  include CollectiveIdea::Acts::NestedSet::Helper\r
+\r
+  before(:all) do\r
+    self.class.fixtures :categories\r
+  end\r
+\r
+  describe "nested_set_options" do\r
+    it "test_nested_set_options" do\r
+      expected = [\r
+        [" Top Level", 1],\r
+        ["- Child 1", 2],\r
+        ['- Child 2', 3],\r
+        ['-- Child 2.1', 4],\r
+        ['- Child 3', 5],\r
+        [" Top Level 2", 6]\r
+      ]\r
+      actual = nested_set_options(Category) do |c|\r
+        "#{'-' * c.level} #{c.name}"\r
+      end\r
+      actual.should == expected\r
+    end\r
+\r
+    it "test_nested_set_options_with_mover" do\r
+      expected = [\r
+        [" Top Level", 1],\r
+        ["- Child 1", 2],\r
+        ['- Child 3', 5],\r
+        [" Top Level 2", 6]\r
+      ]\r
+      actual = nested_set_options(Category, categories(:child_2)) do |c|\r
+        "#{'-' * c.level} #{c.name}"\r
+      end\r
+      actual.should == expected\r
+    end\r
+\r
+    it "test_nested_set_options_with_array_as_argument_without_mover" do\r
+      expected = [\r
+        [" Top Level", 1],\r
+        ["- Child 1", 2],\r
+        ['- Child 2', 3],\r
+        ['-- Child 2.1', 4],\r
+        ['- Child 3', 5],\r
+        [" Top Level 2", 6]\r
+      ]\r
+      actual = nested_set_options(Category.all) do |c|\r
+        "#{'-' * c.level} #{c.name}"\r
+      end\r
+      actual.should == expected\r
+    end\r
+\r
+    it "test_nested_set_options_with_array_as_argument_with_mover" do\r
+      expected = [\r
+        [" Top Level", 1],\r
+        ["- Child 1", 2],\r
+        ['- Child 3', 5],\r
+        [" Top Level 2", 6]\r
+      ]\r
+      actual = nested_set_options(Category.all, categories(:child_2)) do |c|\r
+        "#{'-' * c.level} #{c.name}"\r
+      end\r
+      actual.should == expected\r
+    end\r
+  end\r
+end\r
diff --git a/vendor/plugins/awesome_nested_set/spec/awesome_nested_set_spec.rb b/vendor/plugins/awesome_nested_set/spec/awesome_nested_set_spec.rb
new file mode 100644 (file)
index 0000000..1060bba
--- /dev/null
@@ -0,0 +1,841 @@
+require 'spec_helper'\r
+\r
+describe "AwesomeNestedSet" do\r
+  before(:all) do\r
+    self.class.fixtures :categories, :departments, :notes, :things, :brokens\r
+  end\r
+\r
+  describe "defaults" do\r
+    it "should have left_column_default" do\r
+      Default.acts_as_nested_set_options[:left_column].should == 'lft'\r
+    end\r
+\r
+    it "should have right_column_default" do\r
+      Default.acts_as_nested_set_options[:right_column].should == 'rgt'\r
+    end\r
+\r
+    it "should have parent_column_default" do\r
+      Default.acts_as_nested_set_options[:parent_column].should == 'parent_id'\r
+    end\r
+\r
+    it "should have scope_default" do\r
+      Default.acts_as_nested_set_options[:scope].should be_nil\r
+    end\r
+\r
+    it "should have left_column_name" do\r
+      Default.left_column_name.should == 'lft'\r
+      Default.new.left_column_name.should == 'lft'\r
+      RenamedColumns.left_column_name.should == 'red'\r
+      RenamedColumns.new.left_column_name.should == 'red'\r
+    end\r
+\r
+    it "should have right_column_name" do\r
+      Default.right_column_name.should == 'rgt'\r
+      Default.new.right_column_name.should == 'rgt'\r
+      RenamedColumns.right_column_name.should == 'black'\r
+      RenamedColumns.new.right_column_name.should == 'black'\r
+    end\r
+\r
+    it "should have parent_column_name" do\r
+      Default.parent_column_name.should == 'parent_id'\r
+      Default.new.parent_column_name.should == 'parent_id'\r
+      RenamedColumns.parent_column_name.should == 'mother_id'\r
+      RenamedColumns.new.parent_column_name.should == 'mother_id'\r
+    end\r
+  end\r
+\r
+  it "creation_with_altered_column_names" do\r
+    lambda {\r
+      RenamedColumns.create!()\r
+    }.should_not raise_exception\r
+  end\r
+\r
+  it "creation when existing record has nil left column" do\r
+    assert_nothing_raised do\r
+      Broken.create!\r
+    end\r
+  end\r
+  \r
+  it "quoted_left_column_name" do\r
+    quoted = Default.connection.quote_column_name('lft')\r
+    Default.quoted_left_column_name.should == quoted\r
+    Default.new.quoted_left_column_name.should == quoted\r
+  end\r
+\r
+  it "quoted_right_column_name" do\r
+    quoted = Default.connection.quote_column_name('rgt')\r
+    Default.quoted_right_column_name.should == quoted\r
+    Default.new.quoted_right_column_name.should == quoted\r
+  end\r
+\r
+  it "left_column_protected_from_assignment" do\r
+    lambda {\r
+      Category.new.lft = 1\r
+    }.should raise_exception(ActiveRecord::ActiveRecordError)\r
+  end\r
+\r
+  it "right_column_protected_from_assignment" do\r
+    lambda {\r
+      Category.new.rgt = 1\r
+    }.should raise_exception(ActiveRecord::ActiveRecordError)\r
+  end\r
+\r
+  it "scoped_appends_id" do\r
+    ScopedCategory.acts_as_nested_set_options[:scope].should == :organization_id\r
+  end\r
+\r
+  it "roots_class_method" do\r
+    Category.roots.should == Category.find_all_by_parent_id(nil)\r
+  end\r
+\r
+  it "root_class_method" do\r
+    Category.root.should == categories(:top_level)\r
+  end\r
+\r
+  it "root" do\r
+    categories(:child_3).root.should == categories(:top_level)\r
+  end\r
+\r
+  it "root?" do\r
+    categories(:top_level).root?.should be_true\r
+    categories(:top_level_2).root?.should be_true\r
+  end\r
+\r
+  it "leaves_class_method" do\r
+    Category.find(:all, :conditions => "#{Category.right_column_name} - #{Category.left_column_name} = 1").should == Category.leaves\r
+    Category.leaves.count.should == 4\r
+    Category.leaves.should include(categories(:child_1))\r
+    Category.leaves.should include(categories(:child_2_1))\r
+    Category.leaves.should include(categories(:child_3))\r
+    Category.leaves.should include(categories(:top_level_2))\r
+  end\r
+\r
+  it "leaf" do\r
+    categories(:child_1).leaf?.should be_true\r
+    categories(:child_2_1).leaf?.should be_true\r
+    categories(:child_3).leaf?.should be_true\r
+    categories(:top_level_2).leaf?.should be_true\r
+\r
+    categories(:top_level).leaf?.should be_false\r
+    categories(:child_2).leaf?.should be_false\r
+    Category.new.leaf?.should be_false\r
+  end\r
+\r
+\r
+  it "parent" do\r
+    categories(:child_2_1).parent.should == categories(:child_2)\r
+  end\r
+\r
+  it "self_and_ancestors" do\r
+    child = categories(:child_2_1)\r
+    self_and_ancestors = [categories(:top_level), categories(:child_2), child]\r
+    self_and_ancestors.should == child.self_and_ancestors\r
+  end\r
+\r
+  it "ancestors" do\r
+    child = categories(:child_2_1)\r
+    ancestors = [categories(:top_level), categories(:child_2)]\r
+    ancestors.should == child.ancestors\r
+  end\r
+\r
+  it "self_and_siblings" do\r
+    child = categories(:child_2)\r
+    self_and_siblings = [categories(:child_1), child, categories(:child_3)]\r
+    self_and_siblings.should == child.self_and_siblings\r
+    lambda do\r
+      tops = [categories(:top_level), categories(:top_level_2)]\r
+      assert_equal tops, categories(:top_level).self_and_siblings\r
+    end.should_not raise_exception\r
+  end\r
+\r
+  it "siblings" do\r
+    child = categories(:child_2)\r
+    siblings = [categories(:child_1), categories(:child_3)]\r
+    siblings.should == child.siblings\r
+  end\r
+\r
+  it "leaves" do\r
+    leaves = [categories(:child_1), categories(:child_2_1), categories(:child_3)]\r
+    categories(:top_level).leaves.should == leaves\r
+  end\r
+\r
+  it "level" do\r
+    categories(:top_level).level.should == 0\r
+    categories(:child_1).level.should == 1\r
+    categories(:child_2_1).level.should == 2\r
+  end\r
+\r
+  it "has_children?" do\r
+    categories(:child_2_1).children.empty?.should be_true\r
+    categories(:child_2).children.empty?.should be_false\r
+    categories(:top_level).children.empty?.should be_false\r
+  end\r
+\r
+  it "self_and_descendents" do\r
+    parent = categories(:top_level)\r
+    self_and_descendants = [parent, categories(:child_1), categories(:child_2),\r
+      categories(:child_2_1), categories(:child_3)]\r
+    self_and_descendants.should == parent.self_and_descendants\r
+    self_and_descendants.count.should == parent.self_and_descendants.count\r
+  end\r
+\r
+  it "descendents" do\r
+    lawyers = Category.create!(:name => "lawyers")\r
+    us = Category.create!(:name => "United States")\r
+    us.move_to_child_of(lawyers)\r
+    patent = Category.create!(:name => "Patent Law")\r
+    patent.move_to_child_of(us)\r
+    lawyers.reload\r
+\r
+    lawyers.children.size.should == 1\r
+    us.children.size.should == 1\r
+    lawyers.descendants.size.should == 2\r
+  end\r
+\r
+  it "self_and_descendents" do\r
+    parent = categories(:top_level)\r
+    descendants = [categories(:child_1), categories(:child_2),\r
+      categories(:child_2_1), categories(:child_3)]\r
+    descendants.should == parent.descendants\r
+  end\r
+\r
+  it "children" do\r
+    category = categories(:top_level)\r
+    category.children.each {|c| category.id.should == c.parent_id }\r
+  end\r
+\r
+  it "order_of_children" do\r
+    categories(:child_2).move_left\r
+    categories(:child_2).should == categories(:top_level).children[0]\r
+    categories(:child_1).should == categories(:top_level).children[1]\r
+    categories(:child_3).should == categories(:top_level).children[2]\r
+  end\r
+\r
+  it "is_or_is_ancestor_of?" do\r
+    categories(:top_level).is_or_is_ancestor_of?(categories(:child_1)).should be_true\r
+    categories(:top_level).is_or_is_ancestor_of?(categories(:child_2_1)).should be_true\r
+    categories(:child_2).is_or_is_ancestor_of?(categories(:child_2_1)).should be_true\r
+    categories(:child_2_1).is_or_is_ancestor_of?(categories(:child_2)).should be_false\r
+    categories(:child_1).is_or_is_ancestor_of?(categories(:child_2)).should be_false\r
+    categories(:child_1).is_or_is_ancestor_of?(categories(:child_1)).should be_true\r
+  end\r
+\r
+  it "is_ancestor_of?" do\r
+    categories(:top_level).is_ancestor_of?(categories(:child_1)).should be_true\r
+    categories(:top_level).is_ancestor_of?(categories(:child_2_1)).should be_true\r
+    categories(:child_2).is_ancestor_of?(categories(:child_2_1)).should be_true\r
+    categories(:child_2_1).is_ancestor_of?(categories(:child_2)).should be_false\r
+    categories(:child_1).is_ancestor_of?(categories(:child_2)).should be_false\r
+    categories(:child_1).is_ancestor_of?(categories(:child_1)).should be_false\r
+  end\r
+\r
+  it "is_or_is_ancestor_of_with_scope" do\r
+    root = ScopedCategory.root\r
+    child = root.children.first\r
+    root.is_or_is_ancestor_of?(child).should be_true\r
+    child.update_attribute :organization_id, 'different'\r
+    root.is_or_is_ancestor_of?(child).should be_false\r
+  end\r
+\r
+  it "is_or_is_descendant_of?" do\r
+    categories(:child_1).is_or_is_descendant_of?(categories(:top_level)).should be_true\r
+    categories(:child_2_1).is_or_is_descendant_of?(categories(:top_level)).should be_true\r
+    categories(:child_2_1).is_or_is_descendant_of?(categories(:child_2)).should be_true\r
+    categories(:child_2).is_or_is_descendant_of?(categories(:child_2_1)).should be_false\r
+    categories(:child_2).is_or_is_descendant_of?(categories(:child_1)).should be_false\r
+    categories(:child_1).is_or_is_descendant_of?(categories(:child_1)).should be_true\r
+  end\r
+\r
+  it "is_descendant_of?" do\r
+    categories(:child_1).is_descendant_of?(categories(:top_level)).should be_true\r
+    categories(:child_2_1).is_descendant_of?(categories(:top_level)).should be_true\r
+    categories(:child_2_1).is_descendant_of?(categories(:child_2)).should be_true\r
+    categories(:child_2).is_descendant_of?(categories(:child_2_1)).should be_false\r
+    categories(:child_2).is_descendant_of?(categories(:child_1)).should be_false\r
+    categories(:child_1).is_descendant_of?(categories(:child_1)).should be_false\r
+  end\r
+\r
+  it "is_or_is_descendant_of_with_scope" do\r
+    root = ScopedCategory.root\r
+    child = root.children.first\r
+    child.is_or_is_descendant_of?(root).should be_true\r
+    child.update_attribute :organization_id, 'different'\r
+    child.is_or_is_descendant_of?(root).should be_false\r
+  end\r
+\r
+  it "same_scope?" do\r
+    root = ScopedCategory.root\r
+    child = root.children.first\r
+    child.same_scope?(root).should be_true\r
+    child.update_attribute :organization_id, 'different'\r
+    child.same_scope?(root).should be_false\r
+  end\r
+\r
+  it "left_sibling" do\r
+    categories(:child_1).should == categories(:child_2).left_sibling\r
+    categories(:child_2).should == categories(:child_3).left_sibling\r
+  end\r
+\r
+  it "left_sibling_of_root" do\r
+    categories(:top_level).left_sibling.should be_nil\r
+  end\r
+\r
+  it "left_sibling_without_siblings" do\r
+    categories(:child_2_1).left_sibling.should be_nil\r
+  end\r
+\r
+  it "left_sibling_of_leftmost_node" do\r
+    categories(:child_1).left_sibling.should be_nil\r
+  end\r
+\r
+  it "right_sibling" do\r
+    categories(:child_3).should == categories(:child_2).right_sibling\r
+    categories(:child_2).should == categories(:child_1).right_sibling\r
+  end\r
+\r
+  it "right_sibling_of_root" do\r
+    categories(:top_level_2).should == categories(:top_level).right_sibling\r
+    categories(:top_level_2).right_sibling.should be_nil\r
+  end\r
+\r
+  it "right_sibling_without_siblings" do\r
+    categories(:child_2_1).right_sibling.should be_nil\r
+  end\r
+\r
+  it "right_sibling_of_rightmost_node" do\r
+    categories(:child_3).right_sibling.should be_nil\r
+  end\r
+\r
+  it "move_left" do\r
+    categories(:child_2).move_left\r
+    categories(:child_2).left_sibling.should be_nil\r
+    categories(:child_1).should == categories(:child_2).right_sibling\r
+    Category.valid?.should be_true\r
+  end\r
+\r
+  it "move_right" do\r
+    categories(:child_2).move_right\r
+    categories(:child_2).right_sibling.should be_nil\r
+    categories(:child_3).should == categories(:child_2).left_sibling\r
+    Category.valid?.should be_true\r
+  end\r
+\r
+  it "move_to_left_of" do\r
+    categories(:child_3).move_to_left_of(categories(:child_1))\r
+    categories(:child_3).left_sibling.should be_nil\r
+    categories(:child_1).should == categories(:child_3).right_sibling\r
+    Category.valid?.should be_true\r
+  end\r
+\r
+  it "move_to_right_of" do\r
+    categories(:child_1).move_to_right_of(categories(:child_3))\r
+    categories(:child_1).right_sibling.should be_nil\r
+    categories(:child_3).should == categories(:child_1).left_sibling\r
+    Category.valid?.should be_true\r
+  end\r
+\r
+  it "move_to_root" do\r
+    categories(:child_2).move_to_root\r
+    categories(:child_2).parent.should be_nil\r
+    categories(:child_2).level.should == 0\r
+    categories(:child_2_1).level.should == 1\r
+    categories(:child_2).left.should == 1\r
+    categories(:child_2).right.should == 4\r
+    Category.valid?.should be_true\r
+  end\r
+\r
+  it "move_to_child_of" do\r
+    categories(:child_1).move_to_child_of(categories(:child_3))\r
+    categories(:child_3).id.should == categories(:child_1).parent_id\r
+    Category.valid?.should be_true\r
+  end\r
+\r
+  it "move_to_child_of_appends_to_end" do\r
+    child = Category.create! :name => 'New Child'\r
+    child.move_to_child_of categories(:top_level)\r
+    child.should == categories(:top_level).children.last\r
+  end\r
+\r
+  it "subtree_move_to_child_of" do\r
+    categories(:child_2).left.should == 4\r
+    categories(:child_2).right.should == 7\r
+\r
+    categories(:child_1).left.should == 2\r
+    categories(:child_1).right.should == 3\r
+\r
+    categories(:child_2).move_to_child_of(categories(:child_1))\r
+    Category.valid?.should be_true\r
+    categories(:child_1).id.should == categories(:child_2).parent_id\r
+\r
+    categories(:child_2).left.should == 3\r
+    categories(:child_2).right.should == 6\r
+    categories(:child_1).left.should == 2\r
+    categories(:child_1).right.should == 7\r
+  end\r
+\r
+  it "slightly_difficult_move_to_child_of" do\r
+    categories(:top_level_2).left.should == 11\r
+    categories(:top_level_2).right.should == 12\r
+\r
+    # create a new top-level node and move single-node top-level tree inside it.\r
+    new_top = Category.create(:name => 'New Top')\r
+    new_top.left.should == 13\r
+    new_top.right.should == 14\r
+\r
+    categories(:top_level_2).move_to_child_of(new_top)\r
+\r
+    Category.valid?.should be_true\r
+    new_top.id.should == categories(:top_level_2).parent_id\r
+\r
+    categories(:top_level_2).left.should == 12\r
+    categories(:top_level_2).right.should == 13\r
+    new_top.left.should == 11\r
+    new_top.right.should == 14\r
+  end\r
+\r
+  it "difficult_move_to_child_of" do\r
+    categories(:top_level).left.should == 1\r
+    categories(:top_level).right.should == 10\r
+    categories(:child_2_1).left.should == 5\r
+    categories(:child_2_1).right.should == 6\r
+\r
+    # create a new top-level node and move an entire top-level tree inside it.\r
+    new_top = Category.create(:name => 'New Top')\r
+    categories(:top_level).move_to_child_of(new_top)\r
+    categories(:child_2_1).reload\r
+    Category.valid?.should be_true\r
+    new_top.id.should == categories(:top_level).parent_id\r
+\r
+    categories(:top_level).left.should == 4\r
+    categories(:top_level).right.should == 13\r
+    categories(:child_2_1).left.should == 8\r
+    categories(:child_2_1).right.should == 9\r
+  end\r
+\r
+  #rebuild swaps the position of the 2 children when added using move_to_child twice onto same parent\r
+  it "move_to_child_more_than_once_per_parent_rebuild" do\r
+    root1 = Category.create(:name => 'Root1')\r
+    root2 = Category.create(:name => 'Root2')\r
+    root3 = Category.create(:name => 'Root3')\r
+\r
+    root2.move_to_child_of root1\r
+    root3.move_to_child_of root1\r
+\r
+    output = Category.roots.last.to_text\r
+    Category.update_all('lft = null, rgt = null')\r
+    Category.rebuild!\r
+\r
+    Category.roots.last.to_text.should == output\r
+  end\r
+\r
+  # doing move_to_child twice onto same parent from the furthest right first\r
+  it "move_to_child_more_than_once_per_parent_outside_in" do\r
+    node1 = Category.create(:name => 'Node-1')\r
+    node2 = Category.create(:name => 'Node-2')\r
+    node3 = Category.create(:name => 'Node-3')\r
+\r
+    node2.move_to_child_of node1\r
+    node3.move_to_child_of node1\r
+\r
+    output = Category.roots.last.to_text\r
+    Category.update_all('lft = null, rgt = null')\r
+    Category.rebuild!\r
+\r
+    Category.roots.last.to_text.should == output\r
+  end\r
+\r
+  it "should be able to rebuild without validating each record" do\r
+    root1 = Category.create(:name => 'Root1')\r
+    root2 = Category.create(:name => 'Root2')\r
+    root3 = Category.create(:name => 'Root3')\r
+\r
+    root2.move_to_child_of root1\r
+    root3.move_to_child_of root1\r
+\r
+    root2.name = nil\r
+    root2.save!(:validate => false)\r
+\r
+    output = Category.roots.last.to_text\r
+    Category.update_all('lft = null, rgt = null')\r
+    Category.rebuild!(false)\r
+\r
+    Category.roots.last.to_text.should == output\r
+  end\r
+\r
+  it "valid_with_null_lefts" do\r
+    Category.valid?.should be_true\r
+    Category.update_all('lft = null')\r
+    Category.valid?.should be_false\r
+  end\r
+\r
+  it "valid_with_null_rights" do\r
+    Category.valid?.should be_true\r
+    Category.update_all('rgt = null')\r
+    Category.valid?.should be_false\r
+  end\r
+\r
+  it "valid_with_missing_intermediate_node" do\r
+    # Even though child_2_1 will still exist, it is a sign of a sloppy delete, not an invalid tree.\r
+    Category.valid?.should be_true\r
+    Category.delete(categories(:child_2).id)\r
+    Category.valid?.should be_true\r
+  end\r
+\r
+  it "valid_with_overlapping_and_rights" do\r
+    Category.valid?.should be_true\r
+    categories(:top_level_2)['lft'] = 0\r
+    categories(:top_level_2).save\r
+    Category.valid?.should be_false\r
+  end\r
+\r
+  it "rebuild" do\r
+    Category.valid?.should be_true\r
+    before_text = Category.root.to_text\r
+    Category.update_all('lft = null, rgt = null')\r
+    Category.rebuild!\r
+    Category.valid?.should be_true\r
+    before_text.should == Category.root.to_text\r
+  end\r
+\r
+  it "move_possible_for_sibling" do\r
+    categories(:child_2).move_possible?(categories(:child_1)).should be_true\r
+  end\r
+\r
+  it "move_not_possible_to_self" do\r
+    categories(:top_level).move_possible?(categories(:top_level)).should be_false\r
+  end\r
+\r
+  it "move_not_possible_to_parent" do\r
+    categories(:top_level).descendants.each do |descendant|\r
+      categories(:top_level).move_possible?(descendant).should be_false\r
+      descendant.move_possible?(categories(:top_level)).should be_true\r
+    end\r
+  end\r
+\r
+  it "is_or_is_ancestor_of?" do\r
+    [:child_1, :child_2, :child_2_1, :child_3].each do |c|\r
+      categories(:top_level).is_or_is_ancestor_of?(categories(c)).should be_true\r
+    end\r
+    categories(:top_level).is_or_is_ancestor_of?(categories(:top_level_2)).should be_false\r
+  end\r
+\r
+  it "left_and_rights_valid_with_blank_left" do\r
+    Category.left_and_rights_valid?.should be_true\r
+    categories(:child_2)[:lft] = nil\r
+    categories(:child_2).save(:validate => false)\r
+    Category.left_and_rights_valid?.should be_false\r
+  end\r
+\r
+  it "left_and_rights_valid_with_blank_right" do\r
+    Category.left_and_rights_valid?.should be_true\r
+    categories(:child_2)[:rgt] = nil\r
+    categories(:child_2).save(:validate => false)\r
+    Category.left_and_rights_valid?.should be_false\r
+  end\r
+\r
+  it "left_and_rights_valid_with_equal" do\r
+    Category.left_and_rights_valid?.should be_true\r
+    categories(:top_level_2)[:lft] = categories(:top_level_2)[:rgt]\r
+    categories(:top_level_2).save(:validate => false)\r
+    Category.left_and_rights_valid?.should be_false\r
+  end\r
+\r
+  it "left_and_rights_valid_with_left_equal_to_parent" do\r
+    Category.left_and_rights_valid?.should be_true\r
+    categories(:child_2)[:lft] = categories(:top_level)[:lft]\r
+    categories(:child_2).save(:validate => false)\r
+    Category.left_and_rights_valid?.should be_false\r
+  end\r
+\r
+  it "left_and_rights_valid_with_right_equal_to_parent" do\r
+    Category.left_and_rights_valid?.should be_true\r
+    categories(:child_2)[:rgt] = categories(:top_level)[:rgt]\r
+    categories(:child_2).save(:validate => false)\r
+    Category.left_and_rights_valid?.should be_false\r
+  end\r
+\r
+  it "moving_dirty_objects_doesnt_invalidate_tree" do\r
+    r1 = Category.create :name => "Test 1"\r
+    r2 = Category.create :name => "Test 2"\r
+    r3 = Category.create :name => "Test 3"\r
+    r4 = Category.create :name => "Test 4"\r
+    nodes = [r1, r2, r3, r4]\r
+\r
+    r2.move_to_child_of(r1)\r
+    Category.valid?.should be_true\r
+\r
+    r3.move_to_child_of(r1)\r
+    Category.valid?.should be_true\r
+\r
+    r4.move_to_child_of(r2)\r
+    Category.valid?.should be_true\r
+  end\r
+\r
+  it "multi_scoped_no_duplicates_for_columns?" do\r
+    lambda {\r
+      Note.no_duplicates_for_columns?\r
+    }.should_not raise_exception\r
+  end\r
+\r
+  it "multi_scoped_all_roots_valid?" do\r
+    lambda {\r
+      Note.all_roots_valid?\r
+    }.should_not raise_exception\r
+  end\r
+\r
+  it "multi_scoped" do\r
+    note1 = Note.create!(:body => "A", :notable_id => 2, :notable_type => 'Category')\r
+    note2 = Note.create!(:body => "B", :notable_id => 2, :notable_type => 'Category')\r
+    note3 = Note.create!(:body => "C", :notable_id => 2, :notable_type => 'Default')\r
+\r
+    [note1, note2].should == note1.self_and_siblings\r
+    [note3].should == note3.self_and_siblings\r
+  end\r
+\r
+  it "multi_scoped_rebuild" do\r
+    root = Note.create!(:body => "A", :notable_id => 3, :notable_type => 'Category')\r
+    child1 = Note.create!(:body => "B", :notable_id => 3, :notable_type => 'Category')\r
+    child2 = Note.create!(:body => "C", :notable_id => 3, :notable_type => 'Category')\r
+\r
+    child1.move_to_child_of root\r
+    child2.move_to_child_of root\r
+\r
+    Note.update_all('lft = null, rgt = null')\r
+    Note.rebuild!\r
+\r
+    Note.roots.find_by_body('A').should == root\r
+    [child1, child2].should == Note.roots.find_by_body('A').children\r
+  end\r
+\r
+  it "same_scope_with_multi_scopes" do\r
+    lambda {\r
+      notes(:scope1).same_scope?(notes(:child_1))\r
+    }.should_not raise_exception\r
+    notes(:scope1).same_scope?(notes(:child_1)).should be_true\r
+    notes(:child_1).same_scope?(notes(:scope1)).should be_true\r
+    notes(:scope1).same_scope?(notes(:scope2)).should be_false\r
+  end\r
+\r
+  it "quoting_of_multi_scope_column_names" do\r
+    ["\"notable_id\"", "\"notable_type\""].should == Note.quoted_scope_column_names\r
+  end\r
+\r
+  it "equal_in_same_scope" do\r
+    notes(:scope1).should == notes(:scope1)\r
+    notes(:scope1).should_not == notes(:child_1)\r
+  end\r
+\r
+  it "equal_in_different_scopes" do\r
+    notes(:scope1).should_not == notes(:scope2)\r
+  end\r
+\r
+  it "delete_does_not_invalidate" do\r
+    Category.acts_as_nested_set_options[:dependent] = :delete\r
+    categories(:child_2).destroy\r
+    Category.valid?.should be_true\r
+  end\r
+\r
+  it "destroy_does_not_invalidate" do\r
+    Category.acts_as_nested_set_options[:dependent] = :destroy\r
+    categories(:child_2).destroy\r
+    Category.valid?.should be_true\r
+  end\r
+\r
+  it "destroy_multiple_times_does_not_invalidate" do\r
+    Category.acts_as_nested_set_options[:dependent] = :destroy\r
+    categories(:child_2).destroy\r
+    categories(:child_2).destroy\r
+    Category.valid?.should be_true\r
+  end\r
+\r
+  it "assigning_parent_id_on_create" do\r
+    category = Category.create!(:name => "Child", :parent_id => categories(:child_2).id)\r
+    categories(:child_2).should == category.parent\r
+    categories(:child_2).id.should == category.parent_id\r
+    category.left.should_not be_nil\r
+    category.right.should_not be_nil\r
+    Category.valid?.should be_true\r
+  end\r
+\r
+  it "assigning_parent_on_create" do\r
+    category = Category.create!(:name => "Child", :parent => categories(:child_2))\r
+    categories(:child_2).should == category.parent\r
+    categories(:child_2).id.should == category.parent_id\r
+    category.left.should_not be_nil\r
+    category.right.should_not be_nil\r
+    Category.valid?.should be_true\r
+  end\r
+\r
+  it "assigning_parent_id_to_nil_on_create" do\r
+    category = Category.create!(:name => "New Root", :parent_id => nil)\r
+    category.parent.should be_nil\r
+    category.parent_id.should be_nil\r
+    category.left.should_not be_nil\r
+    category.right.should_not be_nil\r
+    Category.valid?.should be_true\r
+  end\r
+\r
+  it "assigning_parent_id_on_update" do\r
+    category = categories(:child_2_1)\r
+    category.parent_id = categories(:child_3).id\r
+    category.save\r
+    category.reload\r
+    categories(:child_3).reload\r
+    categories(:child_3).should == category.parent\r
+    categories(:child_3).id.should == category.parent_id\r
+    Category.valid?.should be_true\r
+  end\r
+\r
+  it "assigning_parent_on_update" do\r
+    category = categories(:child_2_1)\r
+    category.parent = categories(:child_3)\r
+    category.save\r
+    category.reload\r
+    categories(:child_3).reload\r
+    categories(:child_3).should == category.parent\r
+    categories(:child_3).id.should ==  category.parent_id\r
+    Category.valid?.should be_true\r
+  end\r
+\r
+  it "assigning_parent_id_to_nil_on_update" do\r
+    category = categories(:child_2_1)\r
+    category.parent_id = nil\r
+    category.save\r
+    category.parent.should be_nil\r
+    category.parent_id.should be_nil\r
+    Category.valid?.should be_true\r
+  end\r
+\r
+  it "creating_child_from_parent" do\r
+    category = categories(:child_2).children.create!(:name => "Child")\r
+    categories(:child_2).should == category.parent\r
+    categories(:child_2).id.should == category.parent_id\r
+    category.left.should_not be_nil\r
+    category.right.should_not be_nil\r
+    Category.valid?.should be_true\r
+  end\r
+\r
+  def check_structure(entries, structure)\r
+    structure = structure.dup\r
+    Category.each_with_level(entries) do |category, level|\r
+      expected_level, expected_name = structure.shift\r
+      expected_name.should == category.name\r
+      expected_level.should == level\r
+    end\r
+  end\r
+\r
+  it "each_with_level" do\r
+    levels = [\r
+      [0, "Top Level"],\r
+      [1, "Child 1"],\r
+      [1, "Child 2"],\r
+      [2, "Child 2.1"],\r
+      [1, "Child 3" ]]\r
+\r
+    check_structure(Category.root.self_and_descendants, levels)\r
+\r
+    # test some deeper structures\r
+    category = Category.find_by_name("Child 1")\r
+    c1 = Category.new(:name => "Child 1.1")\r
+    c2 = Category.new(:name => "Child 1.1.1")\r
+    c3 = Category.new(:name => "Child 1.1.1.1")\r
+    c4 = Category.new(:name => "Child 1.2")\r
+    [c1, c2, c3, c4].each(&:save!)\r
+\r
+    c1.move_to_child_of(category)\r
+    c2.move_to_child_of(c1)\r
+    c3.move_to_child_of(c2)\r
+    c4.move_to_child_of(category)\r
+\r
+    levels = [\r
+      [0, "Top Level"],\r
+      [1, "Child 1"],\r
+      [2, "Child 1.1"],\r
+      [3, "Child 1.1.1"],\r
+      [4, "Child 1.1.1.1"],\r
+      [2, "Child 1.2"],\r
+      [1, "Child 2"],\r
+      [2, "Child 2.1"],\r
+      [1, "Child 3" ]]\r
+\r
+      check_structure(Category.root.self_and_descendants, levels)\r
+  end\r
+\r
+  it "should not error on a model with attr_accessible" do\r
+    model = Class.new(ActiveRecord::Base)\r
+    model.set_table_name 'categories'\r
+    model.attr_accessible :name\r
+    lambda {\r
+      model.acts_as_nested_set\r
+      model.new(:name => 'foo')\r
+    }.should_not raise_exception\r
+  end\r
+\r
+  describe "before_move_callback" do\r
+    it "should fire the callback" do\r
+      categories(:child_2).should_receive(:custom_before_move)\r
+      categories(:child_2).move_to_root\r
+    end\r
+\r
+    it "should stop move when callback returns false" do\r
+      Category.test_allows_move = false\r
+      categories(:child_3).move_to_root.should be_false\r
+      categories(:child_3).root?.should be_false\r
+    end\r
+\r
+    it "should not halt save actions" do\r
+      Category.test_allows_move = false\r
+      categories(:child_3).parent_id = nil\r
+      categories(:child_3).save.should be_true\r
+    end\r
+  end\r
+\r
+  describe "counter_cache" do\r
+\r
+    it "should allow use of a counter cache for children" do\r
+      note1 = things(:parent1)\r
+      note1.children.count.should == 2\r
+    end\r
+\r
+    it "should increment the counter cache on create" do\r
+      note1 = things(:parent1)\r
+      note1.children.count.should == 2\r
+      note1[:children_count].should == 2\r
+      note1.children.create :body => 'Child 3'\r
+      note1.children.count.should == 3\r
+      note1.reload\r
+      note1[:children_count].should == 3\r
+    end\r
+\r
+    it "should decrement the counter cache on destroy" do\r
+      note1 = things(:parent1)\r
+      note1.children.count.should == 2\r
+      note1[:children_count].should == 2\r
+      note1.children.last.destroy\r
+      note1.children.count.should == 1\r
+      note1.reload\r
+      note1[:children_count].should == 1\r
+    end\r
+  end\r
+\r
+  describe "association callbacks on children" do\r
+    it "should call the appropriate callbacks on the children :has_many association " do\r
+      root = DefaultWithCallbacks.create\r
+      root.should_not be_new_record\r
+\r
+      child = root.children.build\r
+\r
+      root.before_add.should == child\r
+      root.after_add.should  == child\r
+\r
+      root.before_remove.should_not == child\r
+      root.after_remove.should_not  == child\r
+\r
+      child.save.should be_true\r
+      root.children.delete(child).should be_true\r
+\r
+      root.before_remove.should == child\r
+      root.after_remove.should  == child\r
+    end\r
+  end\r
+end\r
diff --git a/vendor/plugins/awesome_nested_set/spec/db/database.yml b/vendor/plugins/awesome_nested_set/spec/db/database.yml
new file mode 100644 (file)
index 0000000..c8c0aee
--- /dev/null
@@ -0,0 +1,18 @@
+sqlite3:\r
+  adapter: <%= "jdbc" if defined? JRUBY_VERSION %>sqlite3\r
+  database: awesome_nested_set.sqlite3.db\r
+sqlite3mem:\r
+  adapter: <%= "jdbc" if defined? JRUBY_VERSION %>sqlite3\r
+  database: ":memory:"\r
+postgresql:\r
+  adapter: postgresql\r
+  username: postgres\r
+  password: postgres\r
+  database: awesome_nested_set_plugin_test\r
+  min_messages: ERROR\r
+mysql:\r
+  adapter: mysql2\r
+  host: localhost\r
+  username: root\r
+  password:\r
+  database: awesome_nested_set_plugin_test
\ No newline at end of file
diff --git a/vendor/plugins/awesome_nested_set/spec/db/schema.rb b/vendor/plugins/awesome_nested_set/spec/db/schema.rb
new file mode 100644 (file)
index 0000000..d3625fa
--- /dev/null
@@ -0,0 +1,45 @@
+ActiveRecord::Schema.define(:version => 0) do\r
+\r
+  create_table :categories, :force => true do |t|\r
+    t.column :name, :string\r
+    t.column :parent_id, :integer\r
+    t.column :lft, :integer\r
+    t.column :rgt, :integer\r
+    t.column :organization_id, :integer\r
+  end\r
+\r
+  create_table :departments, :force => true do |t|\r
+    t.column :name, :string\r
+  end\r
+\r
+  create_table :notes, :force => true do |t|\r
+    t.column :body, :text\r
+    t.column :parent_id, :integer\r
+    t.column :lft, :integer\r
+    t.column :rgt, :integer\r
+    t.column :notable_id, :integer\r
+    t.column :notable_type, :string\r
+  end\r
+\r
+  create_table :renamed_columns, :force => true do |t|\r
+    t.column :name, :string\r
+    t.column :mother_id, :integer\r
+    t.column :red, :integer\r
+    t.column :black, :integer\r
+  end\r
+\r
+  create_table :things, :force => true do |t|\r
+    t.column :body, :text\r
+    t.column :parent_id, :integer\r
+    t.column :lft, :integer\r
+    t.column :rgt, :integer\r
+    t.column :children_count, :integer\r
+  end\r
+  \r
+  create_table :brokens, :force => true do |t|\r
+    t.column :name, :string\r
+    t.column :parent_id, :integer\r
+    t.column :lft, :integer\r
+    t.column :rgt, :integer\r
+  end\r
+end\r
diff --git a/vendor/plugins/awesome_nested_set/spec/fixtures/brokens.yml b/vendor/plugins/awesome_nested_set/spec/fixtures/brokens.yml
new file mode 100644 (file)
index 0000000..45a8c09
--- /dev/null
@@ -0,0 +1,3 @@
+one:\r
+  id: 1\r
+  name: One
\ No newline at end of file
diff --git a/vendor/plugins/awesome_nested_set/spec/fixtures/categories.yml b/vendor/plugins/awesome_nested_set/spec/fixtures/categories.yml
new file mode 100644 (file)
index 0000000..6cf7f3f
--- /dev/null
@@ -0,0 +1,34 @@
+top_level:\r
+  id: 1\r
+  name: Top Level\r
+  lft: 1\r
+  rgt: 10\r
+child_1:\r
+  id: 2\r
+  name: Child 1\r
+  parent_id: 1\r
+  lft: 2\r
+  rgt: 3\r
+child_2:\r
+  id: 3\r
+  name: Child 2\r
+  parent_id: 1\r
+  lft: 4\r
+  rgt: 7\r
+child_2_1:\r
+  id: 4\r
+  name: Child 2.1\r
+  parent_id: 3\r
+  lft: 5\r
+  rgt: 6\r
+child_3:\r
+  id: 5\r
+  name: Child 3\r
+  parent_id: 1\r
+  lft: 8\r
+  rgt: 9\r
+top_level_2:\r
+  id: 6\r
+  name: Top Level 2\r
+  lft: 11\r
+  rgt: 12\r
diff --git a/vendor/plugins/awesome_nested_set/spec/fixtures/departments.yml b/vendor/plugins/awesome_nested_set/spec/fixtures/departments.yml
new file mode 100644 (file)
index 0000000..31d6562
--- /dev/null
@@ -0,0 +1,3 @@
+top:\r
+  id: 1\r
+  name: Top
\ No newline at end of file
diff --git a/vendor/plugins/awesome_nested_set/spec/fixtures/notes.yml b/vendor/plugins/awesome_nested_set/spec/fixtures/notes.yml
new file mode 100644 (file)
index 0000000..cb7a48f
--- /dev/null
@@ -0,0 +1,38 @@
+scope1:\r
+  id: 1\r
+  body: Top Level\r
+  lft: 1\r
+  rgt: 10\r
+  notable_id: 1\r
+  notable_type: Category\r
+child_1:\r
+  id: 2\r
+  body: Child 1\r
+  parent_id: 1\r
+  lft: 2\r
+  rgt: 3\r
+  notable_id: 1\r
+  notable_type: Category\r
+child_2:\r
+  id: 3\r
+  body: Child 2\r
+  parent_id: 1\r
+  lft: 4\r
+  rgt: 7\r
+  notable_id: 1\r
+  notable_type: Category\r
+child_3:\r
+  id: 4\r
+  body: Child 3\r
+  parent_id: 1\r
+  lft: 8\r
+  rgt: 9\r
+  notable_id: 1\r
+  notable_type: Category\r
+scope2:\r
+  id: 5\r
+  body: Top Level 2\r
+  lft: 1\r
+  rgt: 2\r
+  notable_id: 1\r
+  notable_type: Departments\r
diff --git a/vendor/plugins/awesome_nested_set/spec/fixtures/things.yml b/vendor/plugins/awesome_nested_set/spec/fixtures/things.yml
new file mode 100644 (file)
index 0000000..b9c8688
--- /dev/null
@@ -0,0 +1,27 @@
+parent1:\r
+  id: 1\r
+  body: Top Level\r
+  lft: 1\r
+  rgt: 10\r
+  children_count: 2\r
+child_1:\r
+  id: 2\r
+  body: Child 1\r
+  parent_id: 1\r
+  lft: 2\r
+  rgt: 3\r
+  children_count: 0\r
+child_2:\r
+  id: 3\r
+  body: Child 2\r
+  parent_id: 1\r
+  lft: 4\r
+  rgt: 7\r
+  children_count: 0\r
+child_2_1:\r
+  id: 4\r
+  body: Child 2.1\r
+  parent_id: 3\r
+  lft: 8\r
+  rgt: 9\r
+  children_count: 0\r
diff --git a/vendor/plugins/awesome_nested_set/spec/spec_helper.rb b/vendor/plugins/awesome_nested_set/spec/spec_helper.rb
new file mode 100644 (file)
index 0000000..3fa1ba3
--- /dev/null
@@ -0,0 +1,32 @@
+$:.unshift(File.dirname(__FILE__) + '/../lib')\r
+plugin_test_dir = File.dirname(__FILE__)\r
+\r
+require 'rubygems'\r
+require 'bundler/setup'\r
+\r
+require 'rspec'\r
+require 'logger'\r
+\r
+require 'active_support'\r
+require 'active_model'\r
+require 'active_record'\r
+require 'action_controller'\r
+\r
+require 'awesome_nested_set'\r
+\r
+ActiveRecord::Base.logger = Logger.new(plugin_test_dir + "/debug.log")\r
+\r
+require 'yaml'\r
+require 'erb'\r
+ActiveRecord::Base.configurations = YAML::load(ERB.new(IO.read(plugin_test_dir + "/db/database.yml")).result)\r
+ActiveRecord::Base.establish_connection(ENV["DB"] || "sqlite3mem")\r
+ActiveRecord::Migration.verbose = false\r
+load(File.join(plugin_test_dir, "db", "schema.rb"))\r
+\r
+require 'support/models'\r
+\r
+require 'rspec/rails'\r
+RSpec.configure do |config|\r
+  config.fixture_path = "#{plugin_test_dir}/fixtures"\r
+  config.use_transactional_fixtures = true\r
+end\r
diff --git a/vendor/plugins/awesome_nested_set/spec/support/models.rb b/vendor/plugins/awesome_nested_set/spec/support/models.rb
new file mode 100644 (file)
index 0000000..816b682
--- /dev/null
@@ -0,0 +1,72 @@
+class Note < ActiveRecord::Base\r
+  acts_as_nested_set :scope => [:notable_id, :notable_type]\r
+end\r
+\r
+class Default < ActiveRecord::Base\r
+  set_table_name 'categories'\r
+  acts_as_nested_set\r
+end\r
+\r
+class ScopedCategory < ActiveRecord::Base\r
+  set_table_name 'categories'\r
+  acts_as_nested_set :scope => :organization\r
+end\r
+\r
+class RenamedColumns < ActiveRecord::Base\r
+  acts_as_nested_set :parent_column => 'mother_id', :left_column => 'red', :right_column => 'black'\r
+end\r
+\r
+class Category < ActiveRecord::Base\r
+  acts_as_nested_set\r
+\r
+  validates_presence_of :name\r
+\r
+  # Setup a callback that we can switch to true or false per-test\r
+  set_callback :move, :before, :custom_before_move\r
+  cattr_accessor :test_allows_move\r
+  @@test_allows_move = true\r
+  def custom_before_move\r
+    @@test_allows_move\r
+  end\r
+\r
+  def to_s\r
+    name\r
+  end\r
+\r
+  def recurse &block\r
+    block.call self, lambda{\r
+      self.children.each do |child|\r
+        child.recurse &block\r
+      end\r
+    }\r
+  end\r
+end\r
+\r
+class Thing < ActiveRecord::Base\r
+  acts_as_nested_set :counter_cache => 'children_count'\r
+end\r
+\r
+class DefaultWithCallbacks < ActiveRecord::Base\r
+\r
+  set_table_name 'categories'\r
+\r
+  attr_accessor :before_add, :after_add, :before_remove, :after_remove\r
+\r
+  acts_as_nested_set :before_add => :do_before_add_stuff,\r
+    :after_add     => :do_after_add_stuff,\r
+    :before_remove => :do_before_remove_stuff,\r
+    :after_remove  => :do_after_remove_stuff\r
+\r
+  private\r
+\r
+    [ :before_add, :after_add, :before_remove, :after_remove ].each do |hook_name|\r
+      define_method "do_#{hook_name}_stuff" do |child_node|\r
+        self.send("#{hook_name}=", child_node)\r
+      end\r
+    end\r
+\r
+end\r
+\r
+class Broken < ActiveRecord::Base\r
+  acts_as_nested_set\r
+end
\ No newline at end of file
diff --git a/vendor/plugins/engines/.gitignore b/vendor/plugins/engines/.gitignore
deleted file mode 100644 (file)
index 721bd7d..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-.DS_Store
-test_app
-doc
\ No newline at end of file
diff --git a/vendor/plugins/engines/CHANGELOG b/vendor/plugins/engines/CHANGELOG
deleted file mode 100644 (file)
index 20e9b34..0000000
+++ /dev/null
@@ -1,274 +0,0 @@
-= EDGE
-
-* Samuel Williams (http://www.oriontransfer.co.nz/):
-       Thanks to Tekin for his patches.
-       Updated migrations system to tie in more closely with the current rails mechanism.
-       Rake task for updating database schema info
-               rake db:migrate:upgrade_plugin_migrations
-       Please see http://engines.lighthouseapp.com/projects/10178-engines-plugin/tickets/17 for more information.
-
-* Refactored the view loading to work with changes in Edge Rails
-
-* Fixed integration of plugin migrations with the new, default timestamped migrations in Edge Rails
-
-* Refactored tests into the plugin itself - the plugin can now generate its own test_app harness and run tests within it.
-
-
-= 2.0.0 - (ANOTHER) MASSIVE INTERNAL REFACTORING
-
-* Engines now conforms to the new plugin loading mechanism, delegating plugin load order and lots of other things to Rails itself.
-
-
-
-= 1.2.2
-
-* Added the ability to code mix different types of files, cleaning up the existing code-mixing implementation slightly (Ticket #271)
-
-
-= 1.2.1
-
-* Added documentation to clarify some of the issues with Rails unloading classes that aren't required using "require_dependency" (Ticket #266)
-
-* Fixed a bug where test_help was being loaded when it wasn't needed, and was actually causing problems (Ticket #265)
-
-
-= 1.2.0 - MASSIVE INTERNAL REFACTORING
-
-* !!!Support for Rails < 1.2 has been dropped!!!; if you are using Rails =< 1.1.6, please use Engines 1.1.6, available from http://svn.rails-engines.org/engines/tags/rel_1.1.6
-
-* Engines are dead! Long live plugins! There is now no meaningful notion of an engine - all plugins can take advantage of the more powerful features that the engines plugin provides by including app directories, etc.
-
-* Init_engine.rb is no longer used; please use the plugin-standard init.rb instead.
-
-* Engines.start is no longer required; please use the config.plugins array provided by Rails instead
-
-* To get the most benefit from Engines, set config.plugins to ["engines", "*"] to load the engines plugin first, and then all other plugins in their normal order after.
-
-* Access all loaded plugins via the new Rails.plugins array, and by name using Rails.plugins[:plugin_name].
-
-* Access plugin metadata loaded automatically from about.yml: Rails.plugins[:name].about. Plugin#version is provided directly, for easy access.
-
-* Module.config is has been removed - use mattr_accessor instead, and initialize your default values via the init.rb mechanism.
-
-* Public asset helpers have been rewritten; instead of engine_stylesheet, now use stylesheet_link_tag :name, :plugin => "plugin_name"
-
-* Plugin migrations have been reworked to integrate into the main migration stream. Please run script/generate plugin_migration to create plugin migrations in your main application.
-
-* The fixture method for loading fixtures against any class has been removed; instead, engines will now provide a mechanism for loading fixtures from all plugins, by mirroring fixtures into a common location.
-
-* All references to engines have been removed; For example, any rake tasks which applied to engines now apply to all plugins. The default Rails rake tasks for plugins are overridden where necessary.
-
-* Layouts can now be shared via plugins - inspiration gratefully taken from PluginAWeek's plugin_routing :)
-
-* Actual routing from plugins is now possible, by including routes.rb in your plugin directory and using the from_plugin method in config/routes.rb (Ticket #182)
-
-* Controllers are no longer loaded twice if they're not present in the normal app/ directory (Ticket #177)
-
-* The preferred location for javascripts/stylesheets/etc is now 'assets' rather than 'public'
-
-* Ensure that plugins started before routing have their controllers appropriately added to config.controller_paths (Ticket #258)
-
-* Removed Engines.version - it's not longer relevant, now we're loading version information from about.yml files.
-
-* Added a huge amount of documentation to all new modules.
-
-* Added new warning message if installation of engines 1.2.x is attempted in a Rails 1.1.x application
-
-* Added details of the removal of the config method to UPGRADING
-
-* Removed the plugins:info rake task in favour of adding information to script/about via the Rails::Info module (Ticket #261)
-
-* Improved handling of testing and documentation tasks for plugins
-
-
-
-= 1.1.4
-
-* Fixed creation of multipart emails (Ticket #190)
-
-* Added a temporary fix to the code-mixing issue. In your engine's test/test_helper.rb, please add the following lines:
-
-   # Ensure that the code mixing and view loading from the application is disabled
-   Engines.disable_app_views_loading = true
-   Engines.disable_app_code_mixing = true
-
-  which will prevent code mixing for controllers and helpers, and loading views from the application. One thing to remember is to load any controllers/helpers using 'require_or_load' in your tests, to ensure that the engine behaviour is respected (Ticket #135)
-
-* Added tasks to easily test engines individually (Ticket #120)
-
-* Fixture extensions will now fail with an exception if the corresponding class cannot be loaded (Ticket #138)
-
-* Patch for new routing/controller loading in Rails 1.1.6. The routing code is now replaced with the contents of config.controller_paths, along with controller paths from any started engines (Ticket #196)
-
-* Rails' Configuration instance is now stored, and available from all engines and plugins.
-
-
-
-= 1.1.3
-
-* Fixed README to show 'models' rather than 'model' class (Ticket #167)
-* Fixed dependency loading to work with Rails 1.1.4 (Ticket #180)
-
-
-
-= 1.1.2
-
-* Added better fix to version checking (Ticket #130, jdell@gbdev.com).
-
-* Fixed generated init_engine.rb so that VERSION module doesn't cause probems (Ticket #131, japgolly@gmail.com)
-
-* Fixed error with Rails 1.0 when trying to ignore the engine_schema_info table (Ticket #132, snowblink@gmail.com)
-
-* Re-added old style rake tasks (Ticket #133)
-
-* No longer adding all subdirectories of <engine>/app or <engine>/lib, as this can cause issues when files are grouped in modules (Ticket #149, kasatani@gmail.com)
-
-* Fixed engine precidence ordering for Rails 1.1 (Ticket #146)
-
-* Added new Engines.each method to assist in processing the engines in the desired order (Ticket #146)
-
-* Fixed annoying error message at appears when starting the console in development mode (Ticket #134)
-
-* Engines is now super-careful about loading the correct version of Rails from vendor (Ticket #154)
-
-
-
-= 1.1.1
-
-* Fixed migration rake task failing when given a specific version (Ticket #115)
-
-* Added new rake task "test:engines" which will test engines (and other plugins) but ensure that the test database is cloned from development beforehand (Ticket #125)
-
-* Fixed issue where 'engine_schema_info' table was included in schema dumps (Ticket #87)
-
-* Fixed multi-part emails (Ticket #121)
-
-* Added an 'install.rb' file to new engines created by the bundled generator, which installs the engines plugin automatically if it doesn't already exist (Ticket #122)
-
-* Added a default VERSION module to generated engines (Ticket #123)
-
-* Refactored copying of engine's public files to a method of an Engine instance. You can now call Engines.get(:engine_name).copy_public_files (Ticket #108)
-
-* Changed engine generator templates from .rb files to .erb files (Ticket #106)
-
-* Fixed the test_helper.erb file to use the correct testing extensions and not load any schema - the schema will be cloned automatically via rake test:engines
-
-* Fixed problem when running with Rails 1.1.1 where version wasn't determined correctly (Ticket #129)
-
-* Fixed bug preventing engines from loading when both Rails 1.1.0 and 1.1.1 gems are installed and in use.
-
-* Updated version (d'oh!)
-
-
-
-= 1.1.0
-
-* Improved regexp matching for Rails 1.0 engines with peculiar paths
-
-* Engine instance objects can be accessed via Engines[:name], an alias for Engines.get(:name) (Ticket #99)
-
-* init_engine.rb is now processed as the final step in the Engine.start process, so it can access files within the lib directory, which is now in the $LOAD_PATH at that point. (Ticket #99)
-
-* Clarified MIT license (Ticket #98)
-
-* Updated Rake tasks to integrate smoothly with Rails 1.1 namespaces
-
-* Changed the version to "1.1.0 (svn)"
-
-* Added more information about using the plugin with Edge Rails to the README
-
-* moved extensions into lib/engines/ directory to enable use of Engines module in extension code.
-
-* Added conditional require_or_load method which attempts to detect the current Rails version. To use the Edge Rails version of the loading mechanism, add the line:
-
-*   Engines.config :edge, true
-
-* to your environment.rb file.
-
-* Merged changes from /branches/edge and /branches/rb_1.0 into /trunk
-
-* engine_schema_info now respects the prefix/suffixes set for ActiveRecord::Base (Ticket #67)
-
-* added ActiveRecord::Base.wrapped_table_name(name) method to assist in determining the correct table name
-
-
-
-= 1.0.6
-
-* Added ability to determine version information for engines: rake engine_info
-
-* Added a custom logger for the Engines module, to stop pollution of the Rails logs.
-
-* Added some more tests (in particular, see rails_engines/applications/engines_test).
-
-* Another attempt at solving Ticket #53 - controllers and helpers should now be loadable from modules, and if a full path (including RAILS_ROOT/ENGINES_ROOT) is given, it should be safely stripped from the require filename such that corresponding files can be located in any active engines. In other words, controller/helper overloading should now completely work, even if the controllers/helpers are in modules.
-
-* Added (finally) patch from Ticket #22 - ActionMailer helpers should now load
-
-* Removed support for Engines.start :engine, :engine_name => 'whatever'. It was pointless.
-
-* Fixed engine name referencing; engine_stylesheet/engine_javascript can now happily use shorthand engine names (i.e. :test == :test_engine) (Ticket #45)
-
-* Fixed minor documentation error ('Engine.start' ==> 'Engines.start') (Ticket #57)
-
-* Fixed double inclusion of RAILS_ROOT in engine_migrate rake task (Ticket #61)
-
-* Added ability to force config values even if given as a hash (Ticket #62)
-
-
-
-= 1.0.5
-
-* Fixed bug stopping fixtures from loading with PostgreSQL
-
-
-
-= 1.0.4
-
-* Another attempt at loading controllers within modules (Ticket #56)
-
-
-
-= 1.0.3
-
-* Fixed serious dependency bug stopping controllers being loaded (Ticket #56)
-
-
-
-= 1.0.2
-
-* Fixed bug with overloading controllers in modules from /app directory
-
-* Fixed exception thrown when public files couldn't be created; exception is now logged (Ticket #52)
-
-* Fixed problem with generated test_helper.rb file via File.expand_path (Ticket #50)
-
-
-
-= 1.0.1
-
-* Added engine generator for creation of new engines
-
-* Fixed 'Engine' typo in README
-
-* Fixed bug in fixtures extensions
-
-* Fixed /lib path management bug
-
-* Added method to determine public directory location from Engine object
-
-* Fixed bug in the error message in get_engine_dir()
-
-* Added proper component loading
-
-* Added preliminary tests for the config() methods module
-
-
-
-= pre-v170
-
-* Fixed copyright notices to point to DHH, rather than me.
-
-* Moved extension require statements into lib/engines.rb, so the will be loaded if another module/file calls require 'engines
-
-* Added a CHANGELOG file (this file)
diff --git a/vendor/plugins/engines/MIT-LICENSE b/vendor/plugins/engines/MIT-LICENSE
deleted file mode 100644 (file)
index 2718d6d..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-Copyright (c) 2008 James Adam
-
-The MIT License
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
\ No newline at end of file
diff --git a/vendor/plugins/engines/README b/vendor/plugins/engines/README
deleted file mode 100644 (file)
index e261013..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-The engines plugin enhances Rails' own plugin framework, making it simple to share controllers, helpers, models, public assets, routes and migrations in plugins.
-
-For more information, see http://rails-engines.org
-
-= Using the plugin
-
-Once you've installed the engines plugin, you'll need to add a single line to the top of config/environment.rb:
-
-  require File.join(File.dirname(__FILE__), '../vendor/plugins/engines/boot')
-  
-You should add this line just below the require for Rails' own boot.rb file. This will enabled the enhanced plugin loading mechanism automatically for you (i.e. you don't need to set config.plugin_loader manually).
-
-With that aside, you're now ready to start using more powerful plugins in your application. Read on to find out more about what the engines plugin enables.
-
-
-== Better plugins
-
-In addition to the regular set of plugin-supported files (lib, init.rb, tasks, generators, tests), plugins can carry the following when the engines plugin is also installed.
-
-
-=== Controllers, Helpers, and Views
-
-Include these files in an <tt>app</tt> directory just like you would in a normal Rails application. If you need to override a method, view or partial, create the corresponding file in your main <tt>app</tt> directory and it will be used instead.
-
-* Controllers & Helpers: See Engines::RailsExtensions::Dependencies for more information.
-* Views: now handled almost entirely by ActionView itself (see Engines::Plugin#add_plugin_view_paths for more information)
-
-=== Models
-
-Model code can similarly be placed in an <tt>app/models/</tt> directory. Unfortunately, it's not possible to automatically override methods within a model; if your application needs to change the way a model behaves, consider creating a subclass, or replacing the model entirely within your application's <tt>app/models/</tt> directory. See Engines::RailsExtensions::Dependencies for more information.
-
-IMPORTANT NOTE: when you load code from within plugins, it is typically not handled well by Rails in terms of unloading and reloading changes. Look here for more information - http://rails-engines.org/development/common-issues-when-overloading-code-from-plugins/
-
-=== Routes
-
-Include your route declarations in a <tt>routes.rb</tt> file at the root of your plugins, e.g.:
-
-  connect "/my/url", :controller => "some_controller"
-  my_named_route "do_stuff", :controller => "blah", :action => "stuff"
-  # etc.
-  
-You can then load these files into your application by declaring their inclusion in the application's <tt>config/routes.rb</tt>:
-
-  map.from_plugin :plugin_name
-
-See Engines::RailsExtensions::Routing for more information.
-  
-=== Migrations
-
-Migrations record the changes in your database as your application evolves. With engines 1.2, migrations from plugins can also join in this evolution as first-class entities. To add migrations to a plugin, include a <tt>db/migrate/</tt> folder and add migrations there as normal. These migrations can then be integrated into the main flow of database evolution by running the plugin_migration generator:
-
-  script/generate plugin_migration
-  
-This will produce a migration in your application. Running this migration (via <tt>rake db:migrate</tt>, as normal) will migrate the database according to the latest migrations in each plugin. See Engines::RailsExtensions::Migrations for more information.
-
-
-=== More powerful Rake tasks
-
-The engines plugin enhances and adds to the suite of default rake tasks for working with plugins. The <tt>doc:plugins</tt> task now includes controllers, helpers and models under <tt>app</tt>, and anything other code found under the plugin's <tt>code_paths</tt> attribute. New testing tasks have been added to run unit, functional and integration tests from plugins, whilst making it easier to load fixtures from plugins. See Engines::Testing for more details about testing, and run
-
-  rake -T
-  
-to see the set of rake tasks available.
-
-= Testing the engines plugin itself
-
-Because of the way the engines plugin modifies Rails, the simplest way to consistently test it against multiple versions is by generating a test harness application - a full Rails application that includes tests to verify the engines plugin behaviour in a real, running environment.
-
-Run the tests like this:
-
-  $ cd engines
-  $ rake test
-  
-This will generate a test_app directory within the engines plugin (using the default 'rails' command), import tests and code into that application and then run the test suite.
-
-If you wish to test against a specific version of Rails, run the tests with the RAILS environment variable set to the local directory containing your Rails checkout
-
-  $ rake test RAILS=/Users/james/Code/rails_edge_checkout
-  
-Alternatively, you can clone the latest version of Rails ('edge rails') from github like so:
-
-  $ rake test RAILS=edge
-  
diff --git a/vendor/plugins/engines/Rakefile b/vendor/plugins/engines/Rakefile
deleted file mode 100644 (file)
index 6c621de..0000000
+++ /dev/null
@@ -1,226 +0,0 @@
-require 'rake'
-require 'rake/rdoctask'
-require 'tmpdir'
-
-task :default => :doc
-
-desc 'Generate documentation for the engines plugin.'
-Rake::RDocTask.new(:doc) do |doc|
-  doc.rdoc_dir = 'doc'
-  doc.title    = 'Engines'
-  doc.main     = "README"
-  doc.rdoc_files.include("README", "CHANGELOG", "MIT-LICENSE")
-  doc.rdoc_files.include('lib/**/*.rb')
-  doc.options << '--line-numbers' << '--inline-source'
-end
-
-desc 'Run the engine plugin tests within their test harness'
-task :cruise do
-  # checkout the project into a temporary directory
-  version = "rails_2.0"
-  test_dir = "#{Dir.tmpdir}/engines_plugin_#{version}_test"
-  puts "Checking out test harness for #{version} into #{test_dir}"
-  `svn co http://svn.rails-engines.org/test/engines/#{version} #{test_dir}`
-
-  # run all the tests in this project
-  Dir.chdir(test_dir)
-  load 'Rakefile'
-  puts "Running all tests in test harness"
-  ['db:migrate', 'test', 'test:plugins'].each do |t|
-    Rake::Task[t].invoke
-  end  
-end
-
-task :clean => [:clobber_doc, "test:clean"]
-
-namespace :test do
-  
-  # Yields a block with STDOUT and STDERR silenced. If you *really* want
-  # to output something, the block is yielded with the original output
-  # streams, i.e.
-  #
-  #   silence do |o, e|
-  #     puts 'hello!' # no output produced
-  #     o.puts 'hello!' # output on STDOUT
-  #   end
-  #
-  # (based on silence_stream in ActiveSupport.)
-  def silence
-    yield(STDOUT, STDERR) if ENV['VERBOSE']
-    streams = [STDOUT, STDERR]
-    actual_stdout = STDOUT.dup
-    actual_stderr = STDERR.dup
-    streams.each do |s| 
-      s.reopen(RUBY_PLATFORM =~ /mswin/ ? 'NUL:' : '/dev/null') 
-      s.sync = true
-    end
-    yield actual_stdout, actual_stderr
-  ensure
-    STDOUT.reopen(actual_stdout)
-    STDERR.reopen(actual_stderr)
-  end
-  
-  def test_app_dir
-    File.join(File.dirname(__FILE__), 'test_app')
-  end
-  
-  def run(cmd)
-    cmd = cmd.join(" && ") if cmd.is_a?(Array)
-    system(cmd) || raise("failed running '#{cmd}'")
-  end
-  
-  desc 'Remove the test application'
-  task :clean do
-    FileUtils.rm_r(test_app_dir) if File.exist?(test_app_dir)
-  end
-  
-  desc 'Build the test rails application (use RAILS=[edge,<directory>] to test against specific version)'
-  task :generate_app do
-    silence do |out, err|
-      out.puts "> Creating test application at #{test_app_dir}"
-        
-      if ENV['RAILS']
-        vendor_dir = File.join(test_app_dir, 'vendor')
-        FileUtils.mkdir_p vendor_dir
-        
-        if ENV['RAILS'] == 'edge'
-          out.puts "    Cloning Edge Rails from GitHub"
-          run "cd #{vendor_dir} && git clone --depth 1 git://github.com/rails/rails.git"
-        elsif ENV['RAILS'] =~ /\d\.\d\.\d/
-          if ENV['CURL']
-            out.puts "    Cloning Rails Tag #{ENV['RAILS']} from GitHub using curl and tar"
-            run ["cd #{vendor_dir}",
-                 "mkdir rails",
-                 "cd rails",
-                 "curl -s -L http://github.com/rails/rails/tarball/#{ENV['RAILS']} | tar xzv --strip-components 1"]
-          else
-            out.puts "    Cloning Rails Tag #{ENV['RAILS']} from GitHub (can be slow - set CURL=true to use curl)"
-            run ["cd #{vendor_dir}",
-                 "git clone git://github.com/rails/rails.git",
-                 "cd rails",
-                 "git pull",
-                 "git checkout v#{ENV['RAILS']}"]
-          end
-        elsif File.exist?(ENV['RAILS'])
-          out.puts "    Linking rails from #{ENV['RAILS']}"
-          run "cd #{vendor_dir} && ln -s #{ENV['RAILS']} rails"
-        else
-          raise "Couldn't build test application from '#{ENV['RAILS']}'"
-        end
-      
-        out.puts "    generating rails default directory structure"
-        run "ruby #{File.join(vendor_dir, 'rails', 'railties', 'bin', 'rails')} #{test_app_dir}"
-      else
-        version = `rails --version`.chomp.split.last
-        out.puts "    building rails using the 'rails' command (rails version: #{version})"
-        run "rails #{test_app_dir}"
-      end
-    
-      # get the database config and schema in place
-      out.puts "    writing database.yml"
-      require 'yaml'
-      File.open(File.join(test_app_dir, 'config', 'database.yml'), 'w') do |f|
-        f.write(%w(development test).inject({}) do |h, env| 
-          h[env] = {"adapter" => "sqlite3", "database" => "engines_#{env}.sqlite3"} ; h
-        end.to_yaml)
-      end
-      out.puts "    installing exception_notification plugin"
-      run "cd #{test_app_dir} && ./script/plugin install git://github.com/rails/exception_notification.git"
-    end
-  end
-  
-  # We can't link the plugin, as it needs to be present for script/generate to find
-  # the plugin generator.
-  # TODO: find and +1/create issue for loading generators from symlinked plugins
-  desc 'Mirror the engines plugin into the test application'
-  task :copy_engines_plugin do
-    puts "> Copying engines plugin into test application"
-    engines_plugin = File.join(test_app_dir, "vendor", "plugins", "engines")
-    FileUtils.rm_r(engines_plugin) if File.exist?(engines_plugin)
-    FileUtils.mkdir_p(engines_plugin)
-    FileList["*"].exclude("test_app").each do |file|
-      FileUtils.cp_r(file, engines_plugin)
-    end
-  end
-  
-  def insert_line(line, options)
-    line = line + "\n"
-    target_file = File.join(test_app_dir, options[:into])
-    lines = File.readlines(target_file)
-    return if lines.include?(line)
-    
-    if options[:after]
-      if options[:after].is_a?(String)
-        after_line = options[:after] + "\n"
-      else
-        after_line = lines.find { |l| l =~ options[:after] }
-        raise "couldn't find a line matching #{options[:after].inspect} in #{target_file}" unless after_line
-      end
-      index = lines.index(after_line)
-      raise "couldn't find line '#{after_line}' in #{target_file}" unless index
-      lines.insert(index + 1, line)
-    else
-      lines << line
-    end
-    File.open(target_file, 'w') { |f| f.write lines.join }
-  end
-  
-  def mirror_test_files(src, dest=nil)
-    destination_dir = File.join(*([test_app_dir, dest].compact))
-    FileUtils.cp_r(File.join(File.dirname(__FILE__), 'test', src), destination_dir)
-  end
-  
-  desc 'Update the plugin and tests files in the test application from the plugin'
-  task :mirror_engine_files => [:test_app, :copy_engines_plugin] do
-    puts "> Tweaking generated application to be suitable for testing"
-    
-    # Replace the Rails plugin loader with the engines one.
-    insert_line("require File.join(File.dirname(__FILE__), '../vendor/plugins/engines/boot')",
-                :into => 'config/environment.rb',
-                :after => "require File.join(File.dirname(__FILE__), 'boot')")
-    
-    # Add the engines test helper to handle fixtures & stuff.
-    insert_line("require 'engines_test_helper'", :into => 'test/test_helper.rb')
-    
-    # Run engine plugin tests when running the application 
-    insert_line("task :test => ['test:engines:all']", :into => 'Rakefile')
-    
-    # We want exceptions to be raised
-    insert_line("def rescue_action(e) raise e end;", 
-                :into => "app/controllers/application_controller.rb",
-                :after => "class ApplicationController < ActionController::Base")
-    
-    # We need this method to test where actions are being rendered from.
-    insert_line("include RenderInformation", 
-                :into => "app/controllers/application_controller.rb",
-                :after => "class ApplicationController < ActionController::Base")
-    
-    puts "> Mirroring test application files into #{test_app_dir}"
-    mirror_test_files('app')
-    mirror_test_files('lib')
-    mirror_test_files('plugins', 'vendor')
-    mirror_test_files('unit', 'test')
-    mirror_test_files('functional', 'test')
-  end
-  
-  desc 'Prepare the engines test environment'
-  task :test_app do
-    version_tag = File.join(test_app_dir, 'RAILS_VERSION')
-    existing_version = File.read(version_tag).chomp rescue 'unknown'
-    if existing_version == ENV['RAILS']
-      puts "> Reusing existing test application (#{ENV['RAILS']})"
-    else
-      puts "> Recreating test application"
-      Rake::Task["test:clean"].invoke
-      Rake::Task["test:generate_app"].invoke
-      
-      File.open(version_tag, "w") { |f| f.write ENV['RAILS'] }
-    end
-  end
-end
-
-task :test => "test:mirror_engine_files" do
-  puts "> Loading the test application environment and running tests"
-  # We use exec here to replace the current running rake process
-  exec("cd #{test_app_dir} && rake db:migrate && rake")
-end
diff --git a/vendor/plugins/engines/about.yml b/vendor/plugins/engines/about.yml
deleted file mode 100644 (file)
index 13f55ec..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-author: James Adam
-email: james.adam@gmail.com
-homepage: http://www.rails-engines.org
-summary: Enhances the plugin mechanism to perform more flexible sharing
-description: The Rails Engines plugin allows the sharing of almost any type of code or asset that you could use in a Rails application, including controllers, models, stylesheets, and views.
-license: MIT
-version: 2.3.2
\ No newline at end of file
diff --git a/vendor/plugins/engines/boot.rb b/vendor/plugins/engines/boot.rb
deleted file mode 100644 (file)
index 7dd90d1..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-begin
-  require 'rails/version'
-  unless Rails::VERSION::MAJOR >= 2 && Rails::VERSION::MINOR >= 3 && Rails::VERSION::TINY >= 2
-    raise "This version of the engines plugin requires Rails 2.3.2 or later!"
-  end
-end
-
-require File.join(File.dirname(__FILE__), 'lib/engines')
-
-# initialize Rails::Configuration with our own default values to spare users 
-# some hassle with the installation and keep the environment cleaner
-
-{ :default_plugin_locators => (defined?(Gem) ? [Rails::Plugin::GemLocator] : []).push(Engines::Plugin::FileSystemLocator),
-  :default_plugin_loader => Engines::Plugin::Loader,
-  :default_plugins => [:engines, :all] }.each do |name, default|    
-  Rails::Configuration.send(:define_method, name) { default }
-end
\ No newline at end of file
diff --git a/vendor/plugins/engines/generators/plugin_migration/USAGE b/vendor/plugins/engines/generators/plugin_migration/USAGE
deleted file mode 100644 (file)
index ae05db7..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-Description:
-  The plugin migration generator assists in working with schema additions 
-  required by plugins. Instead of running migrations from plugins directly,
-  the generator creates a regular Rails migration which will be responsible
-  for migrating the plugins from their current version to the latest version
-  installed.
-  
-  This is important because the set of application migrations remains an
-  accurate record of the state of the database, even as plugins are installed
-  and removed during the development process.
-
-Example:
-  ./script/generate plugin_migration [<plugin_name> <another_plugin_name> ...]
-
-  This will generate:
-
-    RAILS_ROOT
-      |- db
-          |-migrate
-              |- xxx_plugin_migrations.rb
-
-  which contains the migrations for the given plugin(s).
-  
-  
-Advanced Usage:
-
-There may be situations where you need *complete* control over the migrations
-of plugins in your application, migrating a certainly plugin down to X, and
-another plugin up to Y, where neither X or Y are the latest migrations for those
-plugins.
-
-For those unfortunate few, I have two pieces of advice:
-
- 1. Why? This is a code smell [http://c2.com/xp/CodeSmell.html].
- 2. Well, OK. Don't panic. You can completely control plugin migrations by
-    creating your own migrations. To manually migrate a plugin to a specific
-    version, simply use
-    
-      Engines.plugins[:your_plugin_name].migrate(version)
-      
-    where version is the integer of the migration this plugin should end
-    up at.
-    
-With great power comes great responsibility. Use this wisely.
\ No newline at end of file
diff --git a/vendor/plugins/engines/generators/plugin_migration/plugin_migration_generator.rb b/vendor/plugins/engines/generators/plugin_migration/plugin_migration_generator.rb
deleted file mode 100644 (file)
index 900dc05..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-# Generates a migration which migrates all plugins to their latest versions
-# within the database.
-class PluginMigrationGenerator < Rails::Generator::Base
-  
-  # 255 characters max for Windows NTFS (http://en.wikipedia.org/wiki/Filename)
-  # minus 14 for timestamp, minus some extra chars for dot, underscore, file 
-  # extension. So let's have 230.
-  MAX_FILENAME_LENGTH = 230
-    
-  def initialize(runtime_args, runtime_options={})
-    super
-    @options = {:assigns => {}}
-    ensure_schema_table_exists    
-    get_plugins_to_migrate(runtime_args)
-    
-    if @plugins_to_migrate.empty?
-      puts "All plugins are migrated to their latest versions"
-      exit(0)
-    end
-
-    @options[:migration_file_name] = build_migration_name
-    @options[:assigns][:class_name] = build_migration_name.classify
-  end
-  
-  def manifest
-    record do |m|
-      m.migration_template 'plugin_migration.erb', 'db/migrate', @options
-    end
-  end
-  
-  protected
-
-    # Create the schema table if it doesn't already exist.
-    def ensure_schema_table_exists
-      ActiveRecord::Base.connection.initialize_schema_migrations_table
-    end
-
-    # Determine all the plugins which have migrations that aren't present
-    # according to the plugin schema information from the database.
-    def get_plugins_to_migrate(plugin_names)
-
-      # First, grab all the plugins which exist and have migrations
-      @plugins_to_migrate = if plugin_names.empty?
-        Engines.plugins
-      else
-        plugin_names.map do |name| 
-          Engines.plugins[name] ? Engines.plugins[name] : raise("Cannot find the plugin '#{name}'")
-        end
-      end
-      
-      @plugins_to_migrate.reject! { |p| !p.respond_to?(:latest_migration) || p.latest_migration.nil? }
-      
-      # Then find the current versions from the database    
-      @current_versions = {}
-      @plugins_to_migrate.each do |plugin|
-        @current_versions[plugin.name] = Engines::Plugin::Migrator.current_version(plugin)
-      end
-
-      # Then find the latest versions from their migration directories
-      @new_versions = {}      
-      @plugins_to_migrate.each do |plugin|
-        @new_versions[plugin.name] = plugin.latest_migration
-      end
-      
-      # Remove any plugins that don't need migration
-      @plugins_to_migrate.map { |p| p.name }.each do |name|
-        @plugins_to_migrate.delete(Engines.plugins[name]) if @current_versions[name] == @new_versions[name]
-      end
-      
-      @options[:assigns][:plugins] = @plugins_to_migrate
-      @options[:assigns][:new_versions] = @new_versions
-      @options[:assigns][:current_versions] = @current_versions
-    end
-
-    # Returns a migration name. If the descriptive migration name based on the 
-    # plugin names involved is shorter than 230 characters that one will be
-    # used. Otherwise a shorter name will be returned.
-    def build_migration_name
-      descriptive_migration_name.tap do |name|        
-        name.replace short_migration_name if name.length > MAX_FILENAME_LENGTH
-      end
-    end
-
-    # Construct a unique migration name based on the plugins involved and the
-    # versions they should reach after this migration is run. The name constructed
-    # needs to be lowercase
-    def descriptive_migration_name
-      @plugins_to_migrate.map do |plugin| 
-        "#{plugin.name}_to_version_#{@new_versions[plugin.name]}" 
-      end.join("_and_").downcase
-    end
-
-    # Short migration name that will be used if the descriptive_migration_name
-    # exceeds 230 characters
-    def short_migration_name
-      'plugin_migrations'
-    end
-end
\ No newline at end of file
diff --git a/vendor/plugins/engines/generators/plugin_migration/templates/plugin_migration.erb b/vendor/plugins/engines/generators/plugin_migration/templates/plugin_migration.erb
deleted file mode 100644 (file)
index 044f623..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-class <%= class_name %> < ActiveRecord::Migration
-  def self.up
-  <%- plugins.each do |plugin| -%>
-    Engines.plugins["<%= plugin.name %>"].migrate(<%= new_versions[plugin.name] %>)
-  <%- end -%>
-  end
-
-  def self.down
-  <%- plugins.each do |plugin| -%>
-    Engines.plugins["<%= plugin.name %>"].migrate(<%= current_versions[plugin.name] %>)
-  <%- end -%>
-  end
-end
diff --git a/vendor/plugins/engines/init.rb b/vendor/plugins/engines/init.rb
deleted file mode 100644 (file)
index 2841816..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-# Only call Engines.init once, in the after_initialize block so that Rails
-# plugin reloading works when turned on
-config.after_initialize do
-  Engines.init(initializer) if defined? :Engines
-end
\ No newline at end of file
diff --git a/vendor/plugins/engines/lib/engines.rb b/vendor/plugins/engines/lib/engines.rb
deleted file mode 100644 (file)
index d601710..0000000
+++ /dev/null
@@ -1,174 +0,0 @@
-require 'active_support'
-require File.join(File.dirname(__FILE__), 'engines/plugin')
-require File.join(File.dirname(__FILE__), 'engines/plugin/list')
-require File.join(File.dirname(__FILE__), 'engines/plugin/loader')
-require File.join(File.dirname(__FILE__), 'engines/plugin/locator')
-require File.join(File.dirname(__FILE__), 'engines/assets')
-require File.join(File.dirname(__FILE__), 'engines/rails_extensions/rails')
-
-# == Parameters
-#
-# The Engines module has a number of public configuration parameters:
-#
-# [+public_directory+]  The directory into which plugin assets should be
-#                       mirrored. Defaults to <tt>RAILS_ROOT/public/plugin_assets</tt>.
-# [+schema_info_table+] The table to use when storing plugin migration 
-#                       version information. Defaults to +plugin_schema_info+.
-#
-# Additionally, there are a few flags which control the behaviour of
-# some of the features the engines plugin adds to Rails:
-#
-# [+disable_application_view_loading+] A boolean flag determining whether
-#                                      or not views should be loaded from 
-#                                      the main <tt>app/views</tt> directory.
-#                                      Defaults to false; probably only 
-#                                      useful when testing your plugin.
-# [+disable_application_code_loading+] A boolean flag determining whether
-#                                      or not to load controllers/helpers 
-#                                      from the main +app+ directory,
-#                                      if corresponding code exists within 
-#                                      a plugin. Defaults to false; again, 
-#                                      probably only useful when testing 
-#                                      your plugin.
-# [+disable_code_mixing+] A boolean flag indicating whether all plugin
-#                         copies of a particular controller/helper should 
-#                         be loaded and allowed to override each other, 
-#                         or if the first matching file should be loaded 
-#                         instead. Defaults to false.
-#
-module Engines
-  # The set of all loaded plugins
-  mattr_accessor :plugins
-  self.plugins = Engines::Plugin::List.new  
-  
-  # List of extensions to load, can be changed in init.rb before calling Engines.init
-  mattr_accessor :rails_extensions
-  self.rails_extensions = %w(asset_helpers form_tag_helpers migrations dependencies)
-  
-  # The name of the public directory to mirror public engine assets into.
-  # Defaults to <tt>RAILS_ROOT/public/plugin_assets</tt>.
-  mattr_accessor :public_directory
-  self.public_directory = File.join(RAILS_ROOT, 'public', 'plugin_assets')
-
-  # The table in which to store plugin schema information. Defaults to
-  # "plugin_schema_info".
-  mattr_accessor :schema_info_table
-  self.schema_info_table = "plugin_schema_info"
-
-  #--
-  # These attributes control the behaviour of the engines extensions
-  #++
-  
-  # Set this to true if views should *only* be loaded from plugins
-  mattr_accessor :disable_application_view_loading
-  self.disable_application_view_loading = false
-  
-  # Set this to true if controller/helper code shouldn't be loaded 
-  # from the application
-  mattr_accessor :disable_application_code_loading
-  self.disable_application_code_loading = false
-  
-  # Set this to true if code should not be mixed (i.e. it will be loaded
-  # from the first valid path on $LOAD_PATH)
-  mattr_accessor :disable_code_mixing
-  self.disable_code_mixing = false
-  
-  # This is used to determine which files are candidates for the "code
-  # mixing" feature that the engines plugin provides, where classes from
-  # plugins can be loaded, and then code from the application loaded
-  # on top of that code to override certain methods.
-  mattr_accessor :code_mixing_file_types
-  self.code_mixing_file_types = %w(controller helper)
-  
-  class << self
-    def init(initializer)
-      load_extensions
-      Engines::Assets.initialize_base_public_directory
-    end
-    
-    def logger
-      RAILS_DEFAULT_LOGGER
-    end
-    
-    def load_extensions
-      rails_extensions.each { |name| require "engines/rails_extensions/#{name}" }
-      # load the testing extensions, if we are in the test environment.
-      require "engines/testing" if RAILS_ENV == "test"
-    end
-    
-    def select_existing_paths(paths)
-      paths.select { |path| File.directory?(path) }
-    end  
-  
-    # The engines plugin will, by default, mix code from controllers and helpers,
-    # allowing application code to override specific methods in the corresponding
-    # controller or helper classes and modules. However, if other file types should
-    # also be mixed like this, they can be added by calling this method. For example,
-    # if you want to include "things" within your plugin and override them from
-    # your applications, you should use the following layout:
-    #
-    #   app/
-    #    +-- things/
-    #    |       +-- one_thing.rb
-    #    |       +-- another_thing.rb
-    #   ...
-    #   vendor/
-    #       +-- plugins/
-    #                +-- my_plugin/
-    #                           +-- app/
-    #                                +-- things/
-    #                                        +-- one_thing.rb
-    #                                        +-- another_thing.rb
-    #
-    # The important point here is that your "things" are named <whatever>_thing.rb,
-    # and that they are placed within plugin/app/things (the pluralized form of 'thing').
-    # 
-    # It's important to note that you'll also want to ensure that the "things" are
-    # on your load path by including them in Rails load path mechanism, e.g. in init.rb:
-    #
-    #  ActiveSupport::Dependencies.load_paths << File.join(File.dirname(__FILE__), 'app', 'things'))
-    #
-    def mix_code_from(*types)
-      self.code_mixing_file_types += types.map { |x| x.to_s.singularize }
-    end
-    
-    # A general purpose method to mirror a directory (+source+) into a destination
-    # directory, including all files and subdirectories. Files will not be mirrored
-    # if they are identical already (checked via FileUtils#identical?).
-    def mirror_files_from(source, destination)
-      return unless File.directory?(source)
-      
-      # TODO: use Rake::FileList#pathmap?    
-      source_files = Dir[source + "/**/*"]
-      source_dirs = source_files.select { |d| File.directory?(d) }
-      source_files -= source_dirs
-      
-      unless source_files.empty?
-        base_target_dir = File.join(destination, File.dirname(source_files.first).gsub(source, ''))
-        FileUtils.mkdir_p(base_target_dir)
-      end
-      
-      source_dirs.each do |dir|
-        # strip down these paths so we have simple, relative paths we can
-        # add to the destination
-        target_dir = File.join(destination, dir.gsub(source, ''))
-        begin        
-          FileUtils.mkdir_p(target_dir)
-        rescue Exception => e
-          raise "Could not create directory #{target_dir}: \n" + e
-        end
-      end
-      
-      source_files.each do |file|
-        begin
-          target = File.join(destination, file.gsub(source, ''))
-          unless File.exist?(target) && FileUtils.identical?(file, target)
-            FileUtils.cp(file, target)
-          end 
-        rescue Exception => e
-          raise "Could not copy #{file} to #{target}: \n" + e 
-        end
-      end  
-    end   
-  end  
-end
diff --git a/vendor/plugins/engines/lib/engines/assets.rb b/vendor/plugins/engines/lib/engines/assets.rb
deleted file mode 100644 (file)
index e6435bb..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-module Engines
-  module Assets    
-    class << self      
-      @@readme = %{Files in this directory are automatically generated from your plugins.
-They are copied from the 'assets' directories of each plugin into this directory
-each time Rails starts (script/server, script/console... and so on).
-Any edits you make will NOT persist across the next server restart; instead you
-should edit the files within the <plugin_name>/assets/ directory itself.}     
-       
-      # Ensure that the plugin asset subdirectory of RAILS_ROOT/public exists, and
-      # that we've added a little warning message to instruct developers not to mess with
-      # the files inside, since they're automatically generated.
-      def initialize_base_public_directory
-        dir = Engines.public_directory
-        unless File.exist?(dir)
-          FileUtils.mkdir_p(dir)
-        end
-        readme = File.join(dir, "README")        
-        File.open(readme, 'w') { |f| f.puts @@readme } unless File.exist?(readme)
-      end
-    
-      # Replicates the subdirectories under the plugins's +assets+ (or +public+) 
-      # directory into the corresponding public directory. See also 
-      # Plugin#public_directory for more.
-      def mirror_files_for(plugin)
-        return if plugin.public_directory.nil?
-        begin 
-          Engines.mirror_files_from(plugin.public_directory, File.join(Engines.public_directory, plugin.name))      
-        rescue Exception => e
-          Engines.logger.warn "WARNING: Couldn't create the public file structure for plugin '#{plugin.name}'; Error follows:"
-          Engines.logger.warn e
-        end
-      end
-    end 
-  end
-end
\ No newline at end of file
diff --git a/vendor/plugins/engines/lib/engines/plugin.rb b/vendor/plugins/engines/lib/engines/plugin.rb
deleted file mode 100644 (file)
index c52bbb0..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-# An instance of Plugin is created for each plugin loaded by Rails, and
-# stored in the <tt>Engines.plugins</tt> PluginList 
-# (see Engines::RailsExtensions::RailsInitializer for more details).
-#
-#   Engines.plugins[:plugin_name]
-#
-# Other properties of the Plugin instance can also be set.
-module Engines
-  class Plugin < Rails::Plugin    
-    # Plugins can add paths to this attribute in init.rb if they need
-    # controllers loaded from additional locations. 
-    attr_accessor :controller_paths
-  
-    # The directory in this plugin to mirror into the shared directory
-    # under +public+.
-    #
-    # Defaults to "assets" (see default_public_directory).
-    attr_accessor :public_directory   
-    
-    protected
-      # The default set of code paths which will be added to the routing system
-      def default_controller_paths
-        %w(app/controllers components)
-      end
-
-      # Attempts to detect the directory to use for public files.
-      # If +assets+ exists in the plugin, this will be used. If +assets+ is missing
-      # but +public+ is found, +public+ will be used.
-      def default_public_directory
-        Engines.select_existing_paths(%w(assets public).map { |p| File.join(directory, p) }).first
-      end
-    
-    public
-  
-    def initialize(directory)
-      super directory
-      @controller_paths = default_controller_paths
-      @public_directory = default_public_directory
-    end
-  
-    # Extends the superclass' load method to additionally mirror public assets
-    def load(initializer)
-      return if loaded?
-      super initializer
-      add_plugin_locale_paths
-      Assets.mirror_files_for(self)
-    end    
-  
-    # select those paths that actually exist in the plugin's directory
-    def select_existing_paths(name)
-      Engines.select_existing_paths(self.send(name).map { |p| File.join(directory, p) })
-    end    
-
-    def add_plugin_locale_paths
-      locale_path = File.join(directory, 'locales')
-      return unless File.exists?(locale_path)
-
-      locale_files = Dir[File.join(locale_path, '*.{rb,yml}')]
-      return if locale_files.blank?
-
-      first_app_element = 
-        I18n.load_path.select{ |e| e =~ /^#{ RAILS_ROOT }/ }.reject{ |e| e =~ /^#{ RAILS_ROOT }\/vendor\/plugins/ }.first
-      app_index = I18n.load_path.index(first_app_element) || - 1
-
-      I18n.load_path.insert(app_index, *locale_files)
-    end
-
-    # The path to this plugin's public files
-    def public_asset_directory
-      "#{File.basename(Engines.public_directory)}/#{name}"
-    end
-    
-    # The directory containing this plugin's migrations (<tt>plugin/db/migrate</tt>)
-    def migration_directory
-      File.join(self.directory, 'db', 'migrate')
-    end
-  
-    # Returns the version number of the latest migration for this plugin. Returns
-    # nil if this plugin has no migrations.
-    def latest_migration
-      migrations.last
-    end
-    
-    # Returns the version numbers of all migrations for this plugin.
-    def migrations
-      migrations = Dir[migration_directory+"/*.rb"]
-      migrations.map { |p| File.basename(p).match(/0*(\d+)\_/)[1].to_i }.sort
-    end
-    
-    # Migrate this plugin to the given version. See Engines::Plugin::Migrator for more
-    # information.   
-    def migrate(version = nil)
-      Engines::Plugin::Migrator.migrate_plugin(self, version)
-    end
-  end
-end
-
diff --git a/vendor/plugins/engines/lib/engines/plugin/list.rb b/vendor/plugins/engines/lib/engines/plugin/list.rb
deleted file mode 100644 (file)
index 316fa57..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-# The PluginList class is an array, enhanced to allow access to loaded plugins
-# by name, and iteration over loaded plugins in order of priority. This array is used
-# by Engines::RailsExtensions::RailsInitializer to create the Engines.plugins array.
-#
-# Each loaded plugin has a corresponding Plugin instance within this array, and 
-# the order the plugins were loaded is reflected in the entries in this array.
-#
-# For more information, see the Rails module.
-module Engines
-  class Plugin
-    class List < Array
-      # Finds plugins with the set with the given name (accepts Strings or Symbols), or
-      # index. So, Engines.plugins[0] returns the first-loaded Plugin, and Engines.plugins[:engines]
-      # returns the Plugin instance for the engines plugin itself.
-      def [](name_or_index)
-        if name_or_index.is_a?(Fixnum)
-          super
-        else
-          self.find { |plugin| plugin.name.to_s == name_or_index.to_s }
-        end
-      end
-  
-      # Go through each plugin, highest priority first (last loaded first). Effectively,
-      # this is like <tt>Engines.plugins.reverse</tt>
-      def by_precedence
-        reverse
-      end
-    end
-  end
-end
\ No newline at end of file
diff --git a/vendor/plugins/engines/lib/engines/plugin/loader.rb b/vendor/plugins/engines/lib/engines/plugin/loader.rb
deleted file mode 100644 (file)
index e316e47..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-module Engines
-  class Plugin
-    class Loader < Rails::Plugin::Loader    
-      protected    
-        def register_plugin_as_loaded(plugin)
-          super plugin
-          Engines.plugins << plugin
-        end    
-    end
-  end
-end
\ No newline at end of file
diff --git a/vendor/plugins/engines/lib/engines/plugin/locator.rb b/vendor/plugins/engines/lib/engines/plugin/locator.rb
deleted file mode 100644 (file)
index 1ff5c76..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-module Engines
-  class Plugin
-    class FileSystemLocator < Rails::Plugin::FileSystemLocator
-      def create_plugin(path)
-        plugin = Engines::Plugin.new(path)
-        plugin.valid? ? plugin : nil
-      end        
-    end
-  end
-end
-
diff --git a/vendor/plugins/engines/lib/engines/plugin/migrator.rb b/vendor/plugins/engines/lib/engines/plugin/migrator.rb
deleted file mode 100644 (file)
index 05379d9..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-# The Plugin::Migrator class contains the logic to run migrations from
-# within plugin directories. The directory in which a plugin's migrations
-# should be is determined by the Plugin#migration_directory method.
-#
-# To migrate a plugin, you can simple call the migrate method (Plugin#migrate)
-# with the version number that plugin should be at. The plugin's migrations
-# will then be used to migrate up (or down) to the given version.
-#
-# For more information, see Engines::RailsExtensions::Migrations
-class Engines::Plugin::Migrator < ActiveRecord::Migrator
-
-  # We need to be able to set the 'current' engine being migrated.
-  cattr_accessor :current_plugin
-
-  class << self
-    # Runs the migrations from a plugin, up (or down) to the version given
-    def migrate_plugin(plugin, version)
-      self.current_plugin = plugin
-      return if current_version(plugin) == version
-      migrate(plugin.migration_directory, version)
-    end
-    
-    def current_version(plugin=current_plugin)
-      # Delete migrations that don't match .. to_i will work because the number comes first
-      ::ActiveRecord::Base.connection.select_values(
-        "SELECT version FROM #{schema_migrations_table_name}"
-      ).delete_if{ |v| v.match(/-#{plugin.name}/) == nil }.map(&:to_i).max || 0
-    end
-  end
-       
-  def migrated
-    sm_table = self.class.schema_migrations_table_name
-    ::ActiveRecord::Base.connection.select_values(
-      "SELECT version FROM #{sm_table}"
-    ).delete_if{ |v| v.match(/-#{current_plugin.name}/) == nil }.map(&:to_i).sort
-  end
-  
-  def record_version_state_after_migrating(version)
-    super(version.to_s + "-" + current_plugin.name)
-  end
-end
diff --git a/vendor/plugins/engines/lib/engines/rails_extensions/asset_helpers.rb b/vendor/plugins/engines/lib/engines/rails_extensions/asset_helpers.rb
deleted file mode 100644 (file)
index a4a9266..0000000
+++ /dev/null
@@ -1,119 +0,0 @@
-# The engines plugin makes it trivial to share public assets using plugins. 
-# To do this, include an <tt>assets</tt> directory within your plugin, and put
-# your javascripts, stylesheets and images in subdirectories of that folder:
-#
-#   my_plugin
-#     |- init.rb
-#     |- lib/
-#     |- assets/
-#          |- javascripts/
-#          |    |- my_functions.js
-#          |
-#          |- stylesheets/
-#          |    |- my_styles.css
-#          |
-#          |- images/
-#               |- my_face.jpg
-#
-# Files within the <tt>asset</tt> structure are automatically mirrored into
-# a publicly-accessible folder each time your application starts (see
-# Engines::Assets#mirror_assets).
-#
-#
-# == Using plugin assets in views
-#
-# It's also simple to use Rails' helpers in your views to use plugin assets.
-# The default helper methods have been enhanced by the engines plugin to accept
-# a <tt>:plugin</tt> option, indicating the plugin containing the desired asset.
-#
-# For example, it's easy to use plugin assets in your layouts:
-#
-#   <%= stylesheet_link_tag "my_styles", :plugin => "my_plugin", :media => "screen" %>
-#   <%= javascript_include_tag "my_functions", :plugin => "my_plugin" %>
-# 
-# ... and similarly in views and partials, it's easy to use plugin images:
-#
-#   <%= image_tag "my_face", :plugin => "my_plugin" %>
-#   <!-- or -->
-#   <%= image_path "my_face", :plugin => "my_plugin" %>
-#
-# Where the default helpers allow the specification of more than one file (i.e. the
-# javascript and stylesheet helpers), you can do similarly for multiple assets from 
-# within a single plugin.
-#
-# ---
-#
-# This module enhances four of the methods from ActionView::Helpers::AssetTagHelper:
-#
-#  * stylesheet_link_tag
-#  * javascript_include_tag
-#  * image_path
-#  * image_tag
-#
-# Each one of these methods now accepts the key/value pair <tt>:plugin => "plugin_name"</tt>,
-# which can be used to specify the originating plugin for any assets.
-#
-module Engines::RailsExtensions::AssetHelpers
-  def self.included(base) #:nodoc:
-    base.class_eval do
-      [:stylesheet_link_tag, :javascript_include_tag, :image_path, :image_tag].each do |m|
-        alias_method_chain m, :engine_additions
-      end
-    end
-  end
-
-  # Adds plugin functionality to Rails' default stylesheet_link_tag method.
-  def stylesheet_link_tag_with_engine_additions(*sources)
-    stylesheet_link_tag_without_engine_additions(*Engines::RailsExtensions::AssetHelpers.pluginify_sources("stylesheets", *sources))
-  end
-
-  # Adds plugin functionality to Rails' default javascript_include_tag method.  
-  def javascript_include_tag_with_engine_additions(*sources)
-    javascript_include_tag_without_engine_additions(*Engines::RailsExtensions::AssetHelpers.pluginify_sources("javascripts", *sources))
-  end
-
-  #--
-  # Our modified image_path now takes a 'plugin' option, though it doesn't require it
-  #++
-
-  # Adds plugin functionality to Rails' default image_path method.
-  def image_path_with_engine_additions(source, options={})
-    options.stringify_keys!
-    source = Engines::RailsExtensions::AssetHelpers.plugin_asset_path(options["plugin"], "images", source) if options["plugin"]
-    image_path_without_engine_additions(source)
-  end
-
-  # Adds plugin functionality to Rails' default image_tag method.
-  def image_tag_with_engine_additions(source, options={})
-    options.stringify_keys!
-    if options["plugin"]
-      source = Engines::RailsExtensions::AssetHelpers.plugin_asset_path(options["plugin"], "images", source)
-      options.delete("plugin")
-    end
-    image_tag_without_engine_additions(source, options)
-  end
-
-  #--
-  # The following are methods on this module directly because of the weird-freaky way
-  # Rails creates the helper instance that views actually get
-  #++
-
-  # Convert sources to the paths for the given plugin, if any plugin option is given
-  def self.pluginify_sources(type, *sources)
-    options = sources.last.is_a?(Hash) ? sources.pop.stringify_keys : { }
-    sources.map! { |s| plugin_asset_path(options["plugin"], type, s) } if options["plugin"]
-    options.delete("plugin") # we don't want it appearing in the HTML
-    sources << options # re-add options      
-  end  
-
-  # Returns the publicly-addressable relative URI for the given asset, type and plugin
-  def self.plugin_asset_path(plugin_name, type, asset)
-    raise "No plugin called '#{plugin_name}' - please use the full name of a loaded plugin." if Engines.plugins[plugin_name].nil?
-    "#{ActionController::Base.relative_url_root}/#{Engines.plugins[plugin_name].public_asset_directory}/#{type}/#{asset}"
-  end
-  
-end
-
-module ::ActionView::Helpers::AssetTagHelper #:nodoc:
-  include Engines::RailsExtensions::AssetHelpers
-end
diff --git a/vendor/plugins/engines/lib/engines/rails_extensions/dependencies.rb b/vendor/plugins/engines/lib/engines/rails_extensions/dependencies.rb
deleted file mode 100644 (file)
index f18b19a..0000000
+++ /dev/null
@@ -1,138 +0,0 @@
-# One of the magic features that that engines plugin provides is the ability to
-# override selected methods in controllers and helpers from your application.
-# This is achieved by trapping requests to load those files, and then mixing in
-# code from plugins (in the order the plugins were loaded) before finally loading
-# any versions from the main +app+ directory.
-#
-# The behaviour of this extension is output to the log file for help when
-# debugging.
-#
-# == Example
-#
-# A plugin contains the following controller in <tt>plugin/app/controllers/my_controller.rb</tt>:
-#
-#   class MyController < ApplicationController
-#     def index
-#       @name = "HAL 9000"
-#     end
-#     def list
-#       @robots = Robot.find(:all)
-#     end
-#   end
-#
-# In one application that uses this plugin, we decide that the name used in the
-# index action should be "Robbie", not "HAL 9000". To override this single method,
-# we create the corresponding controller in our application 
-# (<tt>RAILS_ROOT/app/controllers/my_controller.rb</tt>), and redefine the method:
-#
-#   class MyController < ApplicationController
-#     def index
-#       @name = "Robbie"
-#     end
-#   end
-#
-# The list method remains as it was defined in the plugin controller.
-#
-# The same basic principle applies to helpers, and also views and partials (although
-# view overriding is performed in Engines::RailsExtensions::Templates; see that
-# module for more information).
-#
-# === What about models?
-#
-# Unfortunately, it's not possible to provide this kind of magic for models.
-# The only reason why it's possible for controllers and helpers is because
-# they can be recognised by their filenames ("whatever_controller", "jazz_helper"),
-# whereas models appear the same as any other typical Ruby library ("node",
-# "user", "image", etc.). 
-#
-# If mixing were allowed in models, it would mean code mixing for *every* 
-# file that was loaded via +require_or_load+, and this could result in
-# problems where, for example, a Node model might start to include 
-# functionality from another file called "node" somewhere else in the
-# <tt>$LOAD_PATH</tt>.
-#
-# One way to overcome this is to provide model functionality as a module in
-# a plugin, which developers can then include into their own model
-# implementations.
-#
-# Another option is to provide an abstract model (see the ActiveRecord::Base
-# documentation) and have developers subclass this model in their own
-# application if they must.
-#
-# ---
-#
-# The Engines::RailsExtensions::Dependencies module includes a method to
-# override Dependencies.require_or_load, which is called to load code needed
-# by Rails as it encounters constants that aren't defined.
-#
-# This method is enhanced with the code-mixing features described above.
-#
-module Engines::RailsExtensions::Dependencies
-  def self.included(base) #:nodoc:
-    base.class_eval { alias_method_chain :require_or_load, :engine_additions }
-  end
-
-  # Attempt to load the given file from any plugins, as well as the application.
-  # This performs the 'code mixing' magic, allowing application controllers and
-  # helpers to override single methods from those in plugins.
-  # If the file can be found in any plugins, it will be loaded first from those
-  # locations. Finally, the application version is loaded, using Ruby's behaviour
-  # to replace existing methods with their new definitions.
-  #
-  # If <tt>Engines.disable_code_mixing == true</tt>, the first controller/helper on the
-  # <tt>$LOAD_PATH</tt> will be used (plugins' +app+ directories are always lower on the
-  # <tt>$LOAD_PATH</tt> than the main +app+ directory).
-  #
-  # If <tt>Engines.disable_application_code_loading == true</tt>, controllers will
-  # not be loaded from the main +app+ directory *if* they are present in any
-  # plugins.
-  #
-  # Returns true if the file could be loaded (from anywhere); false otherwise -
-  # mirroring the behaviour of +require_or_load+ from Rails (which mirrors
-  # that of Ruby's own +require+, I believe).
-  def require_or_load_with_engine_additions(file_name, const_path=nil)
-    return require_or_load_without_engine_additions(file_name, const_path) if Engines.disable_code_mixing
-
-    file_loaded = false
-
-    # try and load the plugin code first
-    # can't use model, as there's nothing in the name to indicate that the file is a 'model' file
-    # rather than a library or anything else.
-    Engines.code_mixing_file_types.each do |file_type| 
-      # if we recognise this type
-      # (this regexp splits out the module/filename from any instances of app/#{type}, so that
-      #  modules are still respected.)
-      if file_name =~ /^(.*app\/#{file_type}s\/)+(.*_#{file_type})(\.rb)?$/
-        base_name = $2
-        # ... go through the plugins from first started to last, so that
-        # code with a high precedence (started later) will override lower precedence
-        # implementations
-        Engines.plugins.each do |plugin|
-          plugin_file_name = File.expand_path(File.join(plugin.directory, 'app', "#{file_type}s", base_name))
-          if File.file?("#{plugin_file_name}.rb")
-            file_loaded = true if require_or_load_without_engine_additions(plugin_file_name, const_path)
-          end
-        end
-    
-        # finally, load any application-specific controller classes using the 'proper'
-        # rails load mechanism, EXCEPT when we're testing engines and could load this file
-        # from an engine
-        unless Engines.disable_application_code_loading
-          # Ensure we are only loading from the /app directory at this point
-          app_file_name = File.join(RAILS_ROOT, 'app', "#{file_type}s", "#{base_name}")
-          if File.file?("#{app_file_name}.rb")
-            file_loaded = true if require_or_load_without_engine_additions(app_file_name, const_path)
-          end
-        end        
-      end 
-    end
-
-    # if we managed to load a file, return true. If not, default to the original method.
-    # Note that this relies on the RHS of a boolean || not to be evaluated if the LHS is true.
-    file_loaded || require_or_load_without_engine_additions(file_name, const_path)
-  end  
-end
-
-module ActiveSupport::Dependencies #:nodoc:
-  include Engines::RailsExtensions::Dependencies
-end
diff --git a/vendor/plugins/engines/lib/engines/rails_extensions/form_tag_helpers.rb b/vendor/plugins/engines/lib/engines/rails_extensions/form_tag_helpers.rb
deleted file mode 100644 (file)
index c4dab3c..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-# == Using plugin assets for form tag helpers
-#
-# It's as easy to use plugin images for image_submit_tag using Engines as it is for image_tag:
-#
-#   <%= image_submit_tag "my_face", :plugin => "my_plugin" %>
-#
-# ---
-#
-# This module enhances one of the methods from ActionView::Helpers::FormTagHelper:
-#
-#  * image_submit_tag
-#
-# This method now accepts the key/value pair <tt>:plugin => "plugin_name"</tt>,
-# which can be used to specify the originating plugin for any assets.
-#
-module Engines::RailsExtensions::FormTagHelpers
-       def self.included(base)
-               base.class_eval do
-                       alias_method_chain :image_submit_tag, :engine_additions
-               end
-       end
-       
-       # Adds plugin functionality to Rails' default image_submit_tag method.
-       def image_submit_tag_with_engine_additions(source, options={})
-               options.stringify_keys!
-               if options["plugin"]
-                       source = Engines::RailsExtensions::AssetHelpers.plugin_asset_path(options["plugin"], "images", source)
-                       options.delete("plugin")
-               end
-               image_submit_tag_without_engine_additions(source, options)
-       end
-end
-
-module ::ActionView::Helpers::FormTagHelper #:nodoc:
-  include Engines::RailsExtensions::FormTagHelpers
-end
-
diff --git a/vendor/plugins/engines/lib/engines/rails_extensions/migrations.rb b/vendor/plugins/engines/lib/engines/rails_extensions/migrations.rb
deleted file mode 100644 (file)
index 7f51cb8..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-# Contains the enhancements to Rails' migrations system to support the 
-# Engines::Plugin::Migrator. See Engines::RailsExtensions::Migrations for more
-# information.
-
-require "engines/plugin/migrator"
-
-# = Plugins and Migrations: Background
-#
-# Rails uses migrations to describe changes to the databases as your application
-# evolves. Each change to your application - adding and removing models, most
-# commonly - might require tweaks to your schema in the form of new tables, or new
-# columns on existing tables, or possibly the removal of tables or columns. Migrations
-# can even include arbitrary code to *transform* data as the underlying schema
-# changes.
-# 
-# The point is that at any particular stage in your application's development, 
-# migrations serve to transform the database into a state where it is compatible
-# and appropriate at that time.
-# 
-# == What about plugins?
-# 
-# If you want to share models using plugins, chances are that you might also
-# want to include the corresponding migrations to create tables for those models.
-# With the engines plugin installed, plugins can carry migration data easily:
-# 
-#   vendor/
-#     |
-#     plugins/
-#       |
-#       my_plugin/
-#         |- init.rb
-#         |- lib/
-#         |- db/
-#             |-migrate/
-#                 |- 20081105123419_add_some_new_feature.rb
-#                 |- 20081107144959_and_something_else.rb
-#                 |- ...
-# 
-# When you install a plugin which contains migrations, you are undertaking a
-# further step in the development of your application, the same as the addition
-# of any other code. With this in mind, you may want to 'roll back' the
-# installation of this plugin at some point, and the database should be able
-# to migrate back to the point without this plugin in it too.
-#
-# == An example
-#
-# For example, our current application is at version 20081106164503 (according to the
-# +schema_migrations+ table), when we decide that we want to add a tagging plugin. The
-# tagging plugin chosen includes migrations to create the tables it requires
-# (say, _tags_ and _taggings_, for instance), along with the models and helpers
-# one might expect.
-#
-# After installing this plugin, these tables should be created in our database.
-# Rather than running the migrations directly from the plugin, they should be
-# integrated into our main migration stream in order to accurately reflect the
-# state of our application's database *at this moment in time*.
-#
-#   $ script/generate plugin_migration
-#         exists  db/migrate
-#         create  db/migrate/20081108120415_my_plugin_to_version_20081107144959.rb
-#
-# This migration will take our application to version 20081108120415, and contains the 
-# following, typical migration code:
-# 
-#   class TaggingToVersion20081107144959 < ActiveRecord::Migration
-#     def self.up
-#       Engines.plugins[:tagging].migrate(20081107144959)
-#     end
-#     def self.down
-#       Engines.plugins[:tagging].migrate(0)
-#     end
-#   end
-#
-# When we migrate our application up, using <tt>rake db:migrate</tt> as normal,
-# the plugin will be migrated up to its latest version (20081108120415 in this example). If we
-# ever decide to migrate the application back to the state it was in at version 20081106164503,
-# the plugin migrations will be taken back down to version 0 (which, typically,
-# would remove all tables the plugin migrations define).
-#
-# == Upgrading plugins
-#
-# It might happen that later in an application's life, we update to a new version of
-# the tagging plugin which requires some changes to our database. The tagging plugin
-# provides these changes in the form of its own migrations. 
-#
-# In this case, we just need to re-run the plugin_migration generator to create a 
-# new migration from the current revision to the newest one:
-#
-#   $ script/generate plugin_migration
-#        exists db/migrate
-#        create db/migrate/20081210131437_tagging_to_version_20081201172034.rb
-#
-# The contents of this migration are:
-#
-#   class TaggingToVersion20081108120415 < ActiveRecord::Migration
-#     def self.up
-#       Engines.plugins[:tagging].migrate(20081201172034)
-#     end
-#     def self.down
-#       Engines.plugins[:tagging].migrate(20081107144959)
-#     end
-#   end
-#
-# Notice that if we were to migrate down to revision 20081108120415 or lower, the tagging plugin
-# will be migrated back down to version 20081107144959 - the version we were previously at.
-#
-#
-# = Creating migrations in plugins
-#
-# In order to use the plugin migration functionality that engines provides, a plugin 
-# only needs to provide regular migrations in a <tt>db/migrate</tt> folder within it.
-#
-# = Explicitly migrating plugins
-#
-# It's possible to migrate plugins within your own migrations, or any other code.
-# Simply get the Plugin instance, and its Plugin#migrate method with the version
-# you wish to end up at:
-#
-#   Engines.plugins[:whatever].migrate(version)
-#
-#
-# = Upgrading from previous versions of the engines plugin
-#
-# Thanks to the tireless work of the plugin developer community, we can now relying on the migration 
-# mechanism in Rails 2.1+ to do much of the plugin migration work for us. This also means that we
-# don't need a seperate schema_info table for plugins.
-#
-# To update your application, run
-#
-#   rake db:migrate:upgrade_plugin_migrations
-#
-# This will ensure that migration information is carried over into the main schema_migrations table.
-# 
\ No newline at end of file
diff --git a/vendor/plugins/engines/lib/engines/rails_extensions/rails.rb b/vendor/plugins/engines/lib/engines/rails_extensions/rails.rb
deleted file mode 100644 (file)
index 3692d0d..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-# This is only here to allow for backwards compability with Engines that
-# have been implemented based on Engines for Rails 1.2. It is preferred that
-# the plugin list be accessed via Engines.plugins.
-
-module Rails
-  # Returns the Engines::Plugin::List from Engines.plugins. It is preferable to
-  # access Engines.plugins directly.
-  def self.plugins
-    Engines.plugins
-  end
-end
diff --git a/vendor/plugins/engines/lib/engines/testing.rb b/vendor/plugins/engines/lib/engines/testing.rb
deleted file mode 100644 (file)
index c411f83..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-# Contains the enhancements to assist in testing plugins. See Engines::Testing
-# for more details.
-
-require 'test/unit'
-
-require 'tmpdir'
-require 'fileutils'
-
-# In most cases, Rails' own plugin testing mechanisms are sufficient. However, there
-# are cases where plugins can be given a helping hand in the testing arena. This module 
-# contains some methods to assist when testing plugins that contain fixtures.
-# 
-# == Fixtures and plugins
-#
-# Since Rails' own fixtures method is fairly strict about where files can be loaded from,
-# the simplest approach when running plugin tests with fixtures is to simply copy all
-# fixtures into a single temporary location and inform the standard Rails mechanism to
-# use this directory, rather than RAILS_ROOT/test/fixtures.
-#
-# The Engines::Testing#setup_plugin_fixtures method does this, copying all plugin fixtures
-# into the temporary location before and tests are performed. This behaviour is invoked
-# the the rake tasks provided by the Engines plugin, in the "test:plugins" namespace. If
-# necessary, you can invoke the task manually.
-#
-# If you wish to take advantage of this, add a call to the Engines::Testing.set_fixture_path
-# method somewhere before your tests (in a test_helper file, or above the TestCase itself).
-#
-# = Testing plugins
-#
-# Normally testing a plugin will require that Rails is loaded, unless you are including
-# a skeleton Rails environment or set of mocks within your plugin tests. If you require
-# the Rails environment to be started, you must ensure that this actually happens; while
-# it's not obvious, your tests do not automatically run with Rails loaded.
-#
-# The simplest way to setup plugin tests is to include a test helper with the following
-# contents:
-#
-#   # Load the normal Rails helper. This ensures the environment is loaded
-#   require File.expand_path(File.dirname(__FILE__) + '/../../../../test/test_helper')
-#   # Ensure that we are using the temporary fixture path
-#   Engines::Testing.set_fixture_path
-#
-# Then run tests using the provided tasks (<tt>test:plugins</tt>, or the tasks that the engines
-# plugin provides - <tt>test:plugins:units</tt>, etc.).
-#
-# Alternatively, you can explicitly load the environment by adpating the contents of the
-# default <tt>test_helper</tt>:
-#
-#   ENV["RAILS_ENV"] = "test"
-#   # Note that we are requiring config/environment from the root of the enclosing application.
-#   require File.expand_path(File.dirname(__FILE__) + "/../../../../config/environment")
-#   require 'test_help'
-#
-module Engines::Testing
-  mattr_accessor :temporary_fixtures_directory
-  self.temporary_fixtures_directory = FileUtils.mkdir_p(File.join(Dir.tmpdir, "rails_fixtures"))
-  
-  # Copies fixtures from plugins and the application into a temporary directory 
-  # (Engines::Testing.temporary_fixtures_directory). 
-  # 
-  # If a set of plugins is not given, fixtures are copied from all plugins in order 
-  # of precedence, meaning that plugins can 'overwrite' the fixtures of others if they are 
-  # loaded later; the application's fixtures are copied last, allowing any custom fixtures
-  # to override those in the plugins. If no argument is given, plugins are loaded via
-  # PluginList#by_precedence.
-  #
-  # This method is called by the engines-supplied plugin testing rake tasks
-  def self.setup_plugin_fixtures(plugins = Engines.plugins.by_precedence)
-    
-    # First, clear the directory
-    Dir.glob("#{self.temporary_fixtures_directory}/*.yml").each{|fixture| File.delete(fixture)}
-    
-    # Copy all plugin fixtures, and then the application fixtures, into this directory
-    plugins.each do |plugin| 
-      plugin_fixtures_directory =  File.join(plugin.directory, "test", "fixtures")
-      plugin_app_directory =  File.join(plugin.directory, "app")
-      if File.directory?(plugin_app_directory) && File.directory?(plugin_fixtures_directory)
-        Engines.mirror_files_from(plugin_fixtures_directory, self.temporary_fixtures_directory)
-      end
-    end
-    Engines.mirror_files_from(File.join(RAILS_ROOT, "test", "fixtures"),
-                              self.temporary_fixtures_directory)
-  end
-  
-  # Sets the fixture path used by Test::Unit::TestCase to the temporary
-  # directory which contains all plugin fixtures.
-  def self.set_fixture_path
-    ActiveSupport::TestCase.fixture_path = self.temporary_fixtures_directory
-    $LOAD_PATH.unshift self.temporary_fixtures_directory
-  end
-  
-  # overridden test should be in test/{unit,functional,integration}/{plugin_name}/{test_name}
-  def self.override_tests_from_app
-    filename = caller.first.split(":").first
-    plugin_name = filename.split("/")[-4]
-    test_kind = filename.split("/")[-2]
-    override_file = File.expand_path(File.join(File.dirname(filename), "..", "..", "..", "..", "..", "test", 
-                                               test_kind, plugin_name, File.basename(filename)))
-    load(override_file) if File.exist?(override_file)
-  end
-end
\ No newline at end of file
diff --git a/vendor/plugins/engines/lib/tasks/engines.rake b/vendor/plugins/engines/lib/tasks/engines.rake
deleted file mode 100644 (file)
index 231cd02..0000000
+++ /dev/null
@@ -1,281 +0,0 @@
-# This code lets us redefine existing Rake tasks, which is extremely
-# handy for modifying existing Rails rake tasks.
-# Credit for the original snippet of code goes to Jeremy Kemper
-# http://pastie.caboo.se/9620
-unless Rake::TaskManager.methods.include?('redefine_task')
-  module Rake
-    module TaskManager
-      def redefine_task(task_class, args, &block)
-        task_name, arg_names, deps = resolve_args([args])
-        task_name = task_class.scope_name(@scope, task_name)
-        deps = [deps] unless deps.respond_to?(:to_ary)
-        deps = deps.collect {|d| d.to_s }
-        task = @tasks[task_name.to_s] = task_class.new(task_name, self)
-        task.application = self
-        task.add_description(@last_description)
-        @last_description = nil
-        task.enhance(deps, &block)
-        task
-      end
-      
-    end
-    class Task
-      class << self
-        def redefine_task(args, &block)
-          Rake.application.redefine_task(self, [args], &block)
-        end
-      end
-    end
-  end
-end
-
-namespace :db do
-  namespace :migrate do
-    desc 'Migrate database and plugins to current status.'
-    task :all => [ 'db:migrate', 'db:migrate:plugins' ]
-    
-    desc 'Migrate plugins to current status.'
-    task :plugins => :environment do
-      Engines.plugins.each do |plugin|
-        next unless plugin.respond_to?(:migration_directory)
-        next unless File.exists? plugin.migration_directory
-        puts "Migrating plugin #{plugin.name} ..."
-        plugin.migrate
-      end
-    end
-
-    desc 'For engines coming from Rails version < 2.0 or for those previously updated to work with Sven Fuch\'s fork of engines, you need to upgrade the schema info table'
-    task :upgrade_plugin_migrations => :environment do
-      svens_fork_table_name = 'plugin_schema_migrations'
-      
-      # Check if app was previously using Sven's fork
-      if ActiveRecord::Base.connection.table_exists?(svens_fork_table_name)
-        old_sm_table = svens_fork_table_name
-      else
-        old_sm_table = ActiveRecord::Migrator.proper_table_name(Engines.schema_info_table)
-      end
-      
-      unless ActiveRecord::Base.connection.table_exists?(old_sm_table)
-        abort "Cannot find old migration table - assuming nothing needs to be done"
-      end
-      
-      # There are two forms of the engines schema info - pre-fix_plugin_migrations and post
-      # We need to figure this out before we continue.
-      
-      results = ActiveRecord::Base.connection.select_rows(
-        "SELECT version, plugin_name FROM #{old_sm_table}"
-      ).uniq
-      
-      def insert_new_version(plugin_name, version)
-        version_string = "#{version}-#{plugin_name}"
-        new_sm_table = ActiveRecord::Migrator.schema_migrations_table_name
-        
-        # Check if the row already exists for some reason - maybe run this task more than once.
-        return if ActiveRecord::Base.connection.select_rows("SELECT * FROM #{new_sm_table} WHERE version = #{version_string.dump.gsub("\"", "'")}").size > 0
-        
-        puts "Inserting new version #{version} for plugin #{plugin_name}.."
-        ActiveRecord::Base.connection.insert("INSERT INTO #{new_sm_table} (version) VALUES (#{version_string.dump.gsub("\"", "'")})")
-      end
-      
-      # We need to figure out if they already used "fix_plugin_migrations"
-      versions = {}
-      results.each do |r|
-        versions[r[1]] ||= []
-        versions[r[1]] << r[0].to_i
-      end
-      
-      if versions.values.find{ |v| v.size > 1 } == nil
-        puts "Fixing migration info"
-        # We only have one listed migration per plugin - this is pre-fix_plugin_migrations,
-        # so we build all versions required. In this case, all migrations should 
-        versions.each do |plugin_name, version|
-          version = version[0] # There is only one version
-          
-          # We have to make an assumption that numeric migrations won't get this long..
-          # I'm not sure if there is a better assumption, it should work in all
-          # current cases.. (touch wood..)
-          if version.to_s.size < "YYYYMMDDHHMMSS".size
-            # Insert version records for each migration
-            (1..version).each do |v|
-             insert_new_version(plugin_name, v)
-            end
-          else
-            # If the plugin is new-format "YYYYMMDDHHMMSS", we just copy it across... 
-            # The case in which this occurs is very rare..
-            insert_new_version(plugin_name, version)
-          end
-        end
-      else
-        puts "Moving migration info"
-        # We have multiple migrations listed per plugin - thus we can assume they have
-        # already applied fix_plugin_migrations - we just copy it across verbatim
-        versions.each do |plugin_name, version|
-          version.each { |v| insert_new_version(plugin_name, v) }
-        end
-      end
-      
-      puts "Migration info successfully migrated - removing old schema info table"
-      ActiveRecord::Base.connection.drop_table(old_sm_table)
-    end
-    
-    desc 'Migrate a specified plugin.'
-    task(:plugin => :environment) do
-      name = ENV['NAME']
-      if plugin = Engines.plugins[name]
-        version = ENV['VERSION']
-        puts "Migrating #{plugin.name} to " + (version ? "version #{version}" : 'latest version') + " ..."
-        plugin.migrate(version ? version.to_i : nil)
-      else
-        puts "Plugin #{name} does not exist."
-      end
-    end
-  end
-end
-
-
-namespace :db do  
-  namespace :fixtures do
-    namespace :plugins do
-      
-      desc "Load plugin fixtures into the current environment's database."
-      task :load => :environment do
-        require 'active_record/fixtures'
-        ActiveRecord::Base.establish_connection(RAILS_ENV.to_sym)
-        Dir.glob(File.join(RAILS_ROOT, 'vendor', 'plugins', ENV['PLUGIN'] || '**', 
-                 'test', 'fixtures', '*.yml')).each do |fixture_file|
-          Fixtures.create_fixtures(File.dirname(fixture_file), File.basename(fixture_file, '.*'))
-        end
-      end
-      
-    end
-  end
-end
-
-# this is just a modification of the original task in railties/lib/tasks/documentation.rake, 
-# because the default task doesn't support subdirectories like <plugin>/app or
-# <plugin>/component. These tasks now include every file under a plugin's load paths (see
-# Plugin#load_paths).
-namespace :doc do
-
-  plugins = FileList['vendor/plugins/**'].collect { |plugin| File.basename(plugin) }
-
-  namespace :plugins do
-
-    # Define doc tasks for each plugin
-    plugins.each do |plugin|
-      desc "Create plugin documentation for '#{plugin}'"
-      Rake::Task.redefine_task(plugin => :environment) do
-        plugin_base   = RAILS_ROOT + "/vendor/plugins/#{plugin}"
-        options       = []
-        files         = Rake::FileList.new
-        options << "-o doc/plugins/#{plugin}"
-        options << "--title '#{plugin.titlecase} Plugin Documentation'"
-        options << '--line-numbers' << '--inline-source'
-        options << '-T html'
-
-        # Include every file in the plugin's load_paths (see Plugin#load_paths)
-        if Engines.plugins[plugin]
-          files.include("#{plugin_base}/{#{Engines.plugins[plugin].load_paths.join(",")}}/**/*.rb")
-        end
-        if File.exists?("#{plugin_base}/README")
-          files.include("#{plugin_base}/README")    
-          options << "--main '#{plugin_base}/README'"
-        end
-        files.include("#{plugin_base}/CHANGELOG") if File.exists?("#{plugin_base}/CHANGELOG")
-
-        if files.empty?
-          puts "No source files found in #{plugin_base}. No documentation will be generated."
-        else
-          options << files.to_s
-          sh %(rdoc #{options * ' '})
-        end
-      end
-    end
-  end
-end
-
-
-
-namespace :test do
-  task :warn_about_multiple_plugin_testing_with_engines do
-    puts %{-~============== A Moste Polite Warninge ===========================~-
-
-You may experience issues testing multiple plugins at once when using
-the code-mixing features that the engines plugin provides. If you do
-experience any problems, please test plugins individually, i.e.
-
-  $ rake test:plugins PLUGIN=my_plugin
-
-or use the per-type plugin test tasks:
-
-  $ rake test:plugins:units
-  $ rake test:plugins:functionals
-  $ rake test:plugins:integration
-  $ rake test:plugins:all
-
-Report any issues on http://dev.rails-engines.org. Thanks!
-
--~===============( ... as you were ... )============================~-}
-  end
-  
-  namespace :engines do
-    
-    def engine_plugins
-      Dir["vendor/plugins/*"].select { |f| File.directory?(File.join(f, "app")) }.map { |f| File.basename(f) }.join(",")
-    end
-    
-    desc "Run tests from within engines plugins (plugins with an 'app' directory)"
-    task :all => [:units, :functionals, :integration]
-    
-    desc "Run unit tests from within engines plugins (plugins with an 'app' directory)"
-    Rake::TestTask.new(:units => "test:plugins:setup_plugin_fixtures") do |t|
-      t.pattern = "vendor/plugins/{#{ENV['PLUGIN'] || engine_plugins}}/test/unit/**/*_test.rb"
-      t.verbose = true
-    end
-
-    desc "Run functional tests from within engines plugins (plugins with an 'app' directory)"
-    Rake::TestTask.new(:functionals => "test:plugins:setup_plugin_fixtures") do |t|
-      t.pattern = "vendor/plugins/{#{ENV['PLUGIN'] || engine_plugins}}/test/functional/**/*_test.rb"
-      t.verbose = true
-    end
-
-    desc "Run integration tests from within engines plugins (plugins with an 'app' directory)"
-    Rake::TestTask.new(:integration => "test:plugins:setup_plugin_fixtures") do |t|
-      t.pattern = "vendor/plugins/{#{ENV['PLUGIN'] || engine_plugins}}/test/integration/**/*_test.rb"
-      t.verbose = true
-    end
-  end
-  
-  namespace :plugins do
-
-    desc "Run the plugin tests in vendor/plugins/**/test (or specify with PLUGIN=name)"
-    task :all => [:warn_about_multiple_plugin_testing_with_engines, 
-                  :units, :functionals, :integration]
-    
-    desc "Run all plugin unit tests"
-    Rake::TestTask.new(:units => :setup_plugin_fixtures) do |t|
-      t.pattern = "vendor/plugins/#{ENV['PLUGIN'] || "**"}/test/unit/**/*_test.rb"
-      t.verbose = true
-    end
-    
-    desc "Run all plugin functional tests"
-    Rake::TestTask.new(:functionals => :setup_plugin_fixtures) do |t|
-      t.pattern = "vendor/plugins/#{ENV['PLUGIN'] || "**"}/test/functional/**/*_test.rb"
-      t.verbose = true
-    end
-    
-    desc "Integration test engines"
-    Rake::TestTask.new(:integration => :setup_plugin_fixtures) do |t|
-      t.pattern = "vendor/plugins/#{ENV['PLUGIN'] || "**"}/test/integration/**/*_test.rb"
-      t.verbose = true
-    end
-
-    desc "Mirrors plugin fixtures into a single location to help plugin tests"
-    task :setup_plugin_fixtures => :environment do
-      Engines::Testing.setup_plugin_fixtures
-    end
-    
-    # Patch the default plugin testing task to have setup_plugin_fixtures as a prerequisite
-    Rake::Task["test:plugins"].prerequisites << "test:plugins:setup_plugin_fixtures"
-  end
-end
diff --git a/vendor/plugins/engines/test/app/controllers/app_and_plugin_controller.rb b/vendor/plugins/engines/test/app/controllers/app_and_plugin_controller.rb
deleted file mode 100644 (file)
index 90b13ff..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-class AppAndPluginController < ApplicationController
-  def an_action
-    render_class_and_action 'from app'
-  end
-end
diff --git a/vendor/plugins/engines/test/app/controllers/namespace/app_and_plugin_controller.rb b/vendor/plugins/engines/test/app/controllers/namespace/app_and_plugin_controller.rb
deleted file mode 100644 (file)
index 05f9049..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-class Namespace::AppAndPluginController < ApplicationController
-  def an_action
-    render_class_and_action 'from app'
-  end
-end
diff --git a/vendor/plugins/engines/test/app/helpers/mail_helper.rb b/vendor/plugins/engines/test/app/helpers/mail_helper.rb
deleted file mode 100644 (file)
index 9e081e7..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-module MailHelper
-  def do_something_helpful(var)
-    var.to_s.reverse
-  end
-end
\ No newline at end of file
diff --git a/vendor/plugins/engines/test/app/models/app_and_plugin_model.rb b/vendor/plugins/engines/test/app/models/app_and_plugin_model.rb
deleted file mode 100644 (file)
index f0fe903..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-class AppAndPluginModel < ActiveRecord::Base
-  def self.report_location; TestHelper::report_location(__FILE__); end
-end
\ No newline at end of file
diff --git a/vendor/plugins/engines/test/app/models/notify_mail.rb b/vendor/plugins/engines/test/app/models/notify_mail.rb
deleted file mode 100644 (file)
index 899fc1a..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-class NotifyMail < ActionMailer::Base
-
-  helper :mail
-  
-  def signup(txt)
-    body(:name => txt)
-  end
-  
-  def multipart
-    recipients 'some_address@email.com'
-    subject    'multi part email'
-    from       "another_user@email.com"
-    content_type 'multipart/alternative'
-    
-    part :content_type => "text/html", :body => render_message("multipart_html", {})
-    part "text/plain" do |p|
-      p.body = render_message("multipart_plain", {})
-    end
-  end
-  
-  def implicit_multipart
-    recipients 'some_address@email.com'
-    subject    'multi part email'
-    from       "another_user@email.com"
-  end
-end
\ No newline at end of file
diff --git a/vendor/plugins/engines/test/app/things/thing.rb b/vendor/plugins/engines/test/app/things/thing.rb
deleted file mode 100644 (file)
index ae6fbbf..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-class Thing
-  def self.from_app; TestHelper::report_location(__FILE__); end
-end
\ No newline at end of file
diff --git a/vendor/plugins/engines/test/app/views/app_and_plugin/a_view.html.erb b/vendor/plugins/engines/test/app/views/app_and_plugin/a_view.html.erb
deleted file mode 100644 (file)
index 03e2bf8..0000000
+++ /dev/null
@@ -1 +0,0 @@
-<%= TestHelper.view_path_for __FILE__ %> (from app)
\ No newline at end of file
diff --git a/vendor/plugins/engines/test/app/views/namespace/app_and_plugin/a_view.html.erb b/vendor/plugins/engines/test/app/views/namespace/app_and_plugin/a_view.html.erb
deleted file mode 100644 (file)
index 03e2bf8..0000000
+++ /dev/null
@@ -1 +0,0 @@
-<%= TestHelper.view_path_for __FILE__ %> (from app)
\ No newline at end of file
diff --git a/vendor/plugins/engines/test/app/views/notify_mail/implicit_multipart.text.html.erb b/vendor/plugins/engines/test/app/views/notify_mail/implicit_multipart.text.html.erb
deleted file mode 100644 (file)
index 042b5c4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-the implicit html part of the email <%= do_something_helpful("semaj") %>
\ No newline at end of file
diff --git a/vendor/plugins/engines/test/app/views/notify_mail/implicit_multipart.text.plain.erb b/vendor/plugins/engines/test/app/views/notify_mail/implicit_multipart.text.plain.erb
deleted file mode 100644 (file)
index 552acc1..0000000
+++ /dev/null
@@ -1 +0,0 @@
-the implicit plaintext part of the email
\ No newline at end of file
diff --git a/vendor/plugins/engines/test/app/views/notify_mail/multipart_html.html.erb b/vendor/plugins/engines/test/app/views/notify_mail/multipart_html.html.erb
deleted file mode 100644 (file)
index 135488b..0000000
+++ /dev/null
@@ -1 +0,0 @@
-the html part of the email <%= do_something_helpful("semaj") %>
\ No newline at end of file
diff --git a/vendor/plugins/engines/test/app/views/notify_mail/multipart_plain.html.erb b/vendor/plugins/engines/test/app/views/notify_mail/multipart_plain.html.erb
deleted file mode 100644 (file)
index e005046..0000000
+++ /dev/null
@@ -1 +0,0 @@
-the plaintext part of the email
\ No newline at end of file
diff --git a/vendor/plugins/engines/test/app/views/notify_mail/signup.text.plain.erb b/vendor/plugins/engines/test/app/views/notify_mail/signup.text.plain.erb
deleted file mode 100644 (file)
index 5aaf46e..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-Signup template from application
-
-Here's a local variable set in the Mail object: <%= @name %>.
-
-And here's a method called in a mail helper: <%= do_something_helpful(@name) %>
diff --git a/vendor/plugins/engines/test/app/views/plugin_mail/mail_from_plugin_with_application_template.text.plain.erb b/vendor/plugins/engines/test/app/views/plugin_mail/mail_from_plugin_with_application_template.text.plain.erb
deleted file mode 100644 (file)
index 67a6b8f..0000000
+++ /dev/null
@@ -1 +0,0 @@
-<%= @note %> (from application)
\ No newline at end of file
diff --git a/vendor/plugins/engines/test/app/views/plugin_mail/multipart_from_plugin_with_application_template_plain.html.erb b/vendor/plugins/engines/test/app/views/plugin_mail/multipart_from_plugin_with_application_template_plain.html.erb
deleted file mode 100644 (file)
index 284e450..0000000
+++ /dev/null
@@ -1 +0,0 @@
-plugin mail template loaded from application
\ No newline at end of file
diff --git a/vendor/plugins/engines/test/functional/controller_loading_test.rb b/vendor/plugins/engines/test/functional/controller_loading_test.rb
deleted file mode 100644 (file)
index d51bc00..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-# Tests in this file ensure that:
-#
-# * plugin controller actions are found
-# * actions defined in application controllers take precedence over those in plugins
-# * actions in controllers in subsequently loaded plugins take precendence over those in previously loaded plugins
-# * this works for actions in namespaced controllers accordingly
-
-require File.dirname(__FILE__) + '/../test_helper'
-
-class ControllerLoadingTest < ActionController::TestCase
-  def setup
-    @request    = ActionController::TestRequest.new
-    @response   = ActionController::TestResponse.new
-  end
-
-  # plugin controller actions should be found
-
-       def test_WITH_an_action_defined_only_in_a_plugin_IT_should_use_this_action
-         get_action_on_controller :an_action, :alpha_plugin
-    assert_response_body 'rendered in AlphaPluginController#an_action'
-  end
-  
-       def test_WITH_an_action_defined_only_in_a_namespaced_plugin_controller_IT_should_use_this_action
-         get_action_on_controller :an_action, :alpha_plugin, :namespace
-    assert_response_body 'rendered in Namespace::AlphaPluginController#an_action'
-  end
-
-  # app takes precedence over plugins
-
-  def test_WITH_an_action_defined_in_both_app_and_plugin_IT_should_use_the_one_in_app
-         get_action_on_controller :an_action, :app_and_plugin
-    assert_response_body 'rendered in AppAndPluginController#an_action (from app)'
-  end
-  
-  def test_WITH_an_action_defined_in_namespaced_controllers_in_both_app_and_plugin_IT_should_use_the_one_in_app
-         get_action_on_controller :an_action, :app_and_plugin, :namespace
-    assert_response_body 'rendered in Namespace::AppAndPluginController#an_action (from app)'
-  end
-
-  # subsequently loaded plugins take precendence over previously loaded plugins
-
-  def test_WITH_an_action_defined_in_two_plugin_controllers_IT_should_use_the_latter_of_both
-         get_action_on_controller :an_action, :shared_plugin
-    assert_response_body 'rendered in SharedPluginController#an_action (from beta_plugin)'
-  end
-  
-  def test_WITH_an_action_defined_in_two_namespaced_plugin_controllers_IT_should_use_the_latter_of_both
-         get_action_on_controller :an_action, :shared_plugin, :namespace
-    assert_response_body 'rendered in Namespace::SharedPluginController#an_action (from beta_plugin)'
-  end
-end
diff --git a/vendor/plugins/engines/test/functional/exception_notification_compatibility_test.rb b/vendor/plugins/engines/test/functional/exception_notification_compatibility_test.rb
deleted file mode 100644 (file)
index 3093306..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-require File.dirname(__FILE__) + '/../test_helper'
-
-class ExceptionNotificationCompatibilityTest < ActionController::TestCase
-  ExceptionNotifier.exception_recipients = %w(joe@schmoe.com bill@schmoe.com)
-  class SimpleController < ApplicationController
-    include ExceptionNotifiable
-    local_addresses.clear
-    consider_all_requests_local = false
-    def index
-      begin
-        raise "Fail!"
-      rescue Exception => e
-        rescue_action_in_public(e)
-      end
-    end
-  end
-  
-  def setup
-    @controller = SimpleController.new
-    @request    = ActionController::TestRequest.new
-    @response   = ActionController::TestResponse.new
-  end
-  
-  def test_should_work
-    assert_nothing_raised do
-      get :index
-    end
-  end
-end
\ No newline at end of file
diff --git a/vendor/plugins/engines/test/functional/locale_loading_test.rb b/vendor/plugins/engines/test/functional/locale_loading_test.rb
deleted file mode 100644 (file)
index 21c8c7f..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-# Tests in this file ensure that:
-#
-# * translations in the application take precedence over those in plugins
-# * translations in subsequently loaded plugins take precendence over those in previously loaded plugins
-
-require File.dirname(__FILE__) + '/../test_helper'
-
-class LocaleLoadingTest < ActionController::TestCase
-  def setup
-    @request    = ActionController::TestRequest.new
-    @response   = ActionController::TestResponse.new
-  end
-
-  # app takes precedence over plugins
-       
-  def test_WITH_a_translation_defined_in_both_app_and_plugin_IT_should_find_the_one_in_app
-    assert_equal I18n.t('hello'), 'Hello world'
-  end
-       
-  # subsequently loaded plugins take precendence over previously loaded plugins
-       
-  def test_WITH_a_translation_defined_in_two_plugins_IT_should_find_the_latter_of_both
-    assert_equal I18n.t('plugin'), 'beta'
-  end
-end
-       
diff --git a/vendor/plugins/engines/test/functional/routes_test.rb b/vendor/plugins/engines/test/functional/routes_test.rb
deleted file mode 100644 (file)
index 733dd39..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-# Tests in this file ensure that:
-#
-# * Routes from plugins can be routed to
-# * Named routes can be defined within a plugin
-
-require File.dirname(__FILE__) + '/../test_helper'
-
-class RoutesTest < ActionController::TestCase
-  tests TestRoutingController
-  
-       def test_WITH_a_route_defined_in_a_plugin_IT_should_route_it
-         path = '/routes/an_action'
-    opts = {:controller => 'test_routing', :action => 'an_action'}
-    assert_routing path, opts
-    assert_recognizes opts, path # not sure what exactly the difference is, but it won't hurt either
-  end
-
-       def test_WITH_a_route_for_a_namespaced_controller_defined_in_a_plugin_IT_should_route_it
-         path = 'somespace/routes/an_action'
-    opts = {:controller => 'namespace/test_routing', :action => 'an_action'}
-    assert_routing path, opts
-    assert_recognizes opts, path
-  end
-  
-  def test_should_properly_generate_named_routes
-    get :test_named_routes_from_plugin
-    assert_response_body '/somespace/routes'
-  end
-end
\ No newline at end of file
diff --git a/vendor/plugins/engines/test/functional/view_helpers_test.rb b/vendor/plugins/engines/test/functional/view_helpers_test.rb
deleted file mode 100644 (file)
index 5448ffe..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-require File.dirname(__FILE__) + '/../test_helper'
-
-class ViewHelpersTest < ActionController::TestCase
-  tests AssetsController
-  
-  def setup
-    get :index
-  end
-  
-  def test_plugin_javascript_helpers
-    base_selector = "script[type='text/javascript']"
-    js_dir = "/plugin_assets/test_assets/javascripts"
-    assert_select "#{base_selector}[src='#{js_dir}/file.1.js']"
-    assert_select "#{base_selector}[src='#{js_dir}/file2.js']"
-  end
-
-  def test_plugin_stylesheet_helpers
-    base_selector = "link[media='screen'][rel='stylesheet'][type='text/css']"
-    css_dir = "/plugin_assets/test_assets/stylesheets"
-    assert_select "#{base_selector}[href='#{css_dir}/file.1.css']"
-    assert_select "#{base_selector}[href='#{css_dir}/file2.css']"
-  end
-
-  def test_plugin_image_helpers
-    assert_select "img[src='/plugin_assets/test_assets/images/image.png'][alt='Image']"
-  end
-
-  def test_plugin_layouts
-    get :index
-    assert_select "div[id='assets_layout']"
-  end  
-
-  def test_plugin_image_submit_helpers
-    assert_select "input[src='/plugin_assets/test_assets/images/image.png'][type='image']"
-  end
-
-end
diff --git a/vendor/plugins/engines/test/functional/view_loading_test.rb b/vendor/plugins/engines/test/functional/view_loading_test.rb
deleted file mode 100644 (file)
index 28d4754..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-# Tests in this file ensure that:
-#
-# * plugin views are found
-# * views in the application take precedence over those in plugins
-# * views in subsequently loaded plugins take precendence over those in previously loaded plugins
-# * this works for namespaced views accordingly
-
-require File.dirname(__FILE__) + '/../test_helper'
-
-class ViewLoadingTest < ActionController::TestCase
-  def setup
-    @request    = ActionController::TestRequest.new
-    @response   = ActionController::TestResponse.new
-  end
-
-  # plugin views should be found
-
-       def test_WITH_a_view_defined_only_in_a_plugin_IT_should_find_the_view
-         get_action_on_controller :a_view, :alpha_plugin
-    assert_response_body 'alpha_plugin/a_view'
-  end
-       
-       def test_WITH_a_namespaced_view_defined_only_in_a_plugin_IT_should_find_the_view
-         get_action_on_controller :a_view, :alpha_plugin, :namespace
-    assert_response_body 'namespace/alpha_plugin/a_view'
-  end
-
-  # app takes precedence over plugins
-       
-       def test_WITH_a_view_defined_in_both_app_and_plugin_IT_should_find_the_one_in_app
-         get_action_on_controller :a_view, :app_and_plugin
-    assert_response_body 'app_and_plugin/a_view (from app)'
-  end
-       
-       def test_WITH_a_namespaced_view_defined_in_both_app_and_plugin_IT_should_find_the_one_in_app
-         get_action_on_controller :a_view, :app_and_plugin, :namespace
-    assert_response_body 'namespace/app_and_plugin/a_view (from app)'
-  end
-
-  # subsequently loaded plugins take precendence over previously loaded plugins
-       
-       def test_WITH_a_view_defined_in_two_plugins_IT_should_find_the_latter_of_both
-         get_action_on_controller :a_view, :shared_plugin
-    assert_response_body 'shared_plugin/a_view (from beta_plugin)'
-  end
-       
-       def test_WITH_a_namespaced_view_defined_in_two_plugins_IT_should_find_the_latter_of_both
-         get_action_on_controller :a_view, :shared_plugin, :namespace
-    assert_response_body 'namespace/shared_plugin/a_view (from beta_plugin)'
-  end
-  
-  # layouts loaded from plugins
-
-  def test_should_be_able_to_load_a_layout_from_a_plugin
-    get_action_on_controller :action_with_layout, :alpha_plugin
-    assert_response_body 'rendered in AlphaPluginController#action_with_layout (with plugin layout)'
-  end
-       
-end
-       
\ No newline at end of file
diff --git a/vendor/plugins/engines/test/lib/app_and_plugin_lib_model.rb b/vendor/plugins/engines/test/lib/app_and_plugin_lib_model.rb
deleted file mode 100644 (file)
index 6ffe178..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-class AppAndPluginLibModel < ActiveRecord::Base
-  def self.report_location; TestHelper::report_location(__FILE__); end
-end
\ No newline at end of file
diff --git a/vendor/plugins/engines/test/lib/engines_test_helper.rb b/vendor/plugins/engines/test/lib/engines_test_helper.rb
deleted file mode 100644 (file)
index 47bd2bb..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-module TestHelper
-  def self.report_location(path)
-    [RAILS_ROOT + '/', 'vendor/plugins/'].each { |part| path.sub! part, ''}
-    path = path.split('/')
-    location, subject = path.first, path.last
-    if subject.sub! '.rb', ''
-      subject = subject.classify
-    else 
-      subject.sub! '.html.erb', ''
-    end
-    "#{subject} (from #{location})"
-  end
-  
-  def self.view_path_for path
-    [RAILS_ROOT + '/', 'vendor/plugins/', '.html.erb'].each { |part| path.sub! part, ''}
-    parts = path.split('/')
-    parts[(parts.index('views')+1)..-1].join('/')
-  end
-end
-
-class Test::Unit::TestCase
-  # Add more helper methods to be used by all tests here...  
-  def get_action_on_controller(*args)
-    action = args.shift
-    with_controller *args
-    get action
-  end
-  
-  def with_controller(controller, namespace = nil)
-    classname = controller.to_s.classify + 'Controller'
-    classname = namespace.to_s.classify + '::' + classname unless namespace.nil?
-    @controller = classname.constantize.new
-  end
-  
-  def assert_response_body(expected)
-    assert_equal expected, @response.body
-  end
-end
-
-# Because we're testing this behaviour, we actually want these features on!
-Engines.disable_application_view_loading = false
-Engines.disable_application_code_loading = false
diff --git a/vendor/plugins/engines/test/lib/render_information.rb b/vendor/plugins/engines/test/lib/render_information.rb
deleted file mode 100644 (file)
index 0deb5d9..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-module RenderInformation
-  def render_class_and_action(note = nil, options={})
-    text = "rendered in #{self.class.name}##{params[:action]}"
-    text += " (#{note})" unless note.nil?
-    render options.update(:text => text)
-  end
-end
\ No newline at end of file
diff --git a/vendor/plugins/engines/test/plugins/alpha_plugin/app/controllers/alpha_plugin_controller.rb b/vendor/plugins/engines/test/plugins/alpha_plugin/app/controllers/alpha_plugin_controller.rb
deleted file mode 100644 (file)
index 736d59b..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-class AlphaPluginController < ApplicationController
-  def an_action
-    render_class_and_action
-  end
-  def action_with_layout
-    render_class_and_action(nil, :layout => "plugin_layout")
-  end
-end
diff --git a/vendor/plugins/engines/test/plugins/alpha_plugin/app/controllers/app_and_plugin_controller.rb b/vendor/plugins/engines/test/plugins/alpha_plugin/app/controllers/app_and_plugin_controller.rb
deleted file mode 100644 (file)
index c41d6ed..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-class AppAndPluginController < ApplicationController
-  def an_action
-    render_class_and_action 'from alpha_plugin'
-  end
-end
diff --git a/vendor/plugins/engines/test/plugins/alpha_plugin/app/controllers/namespace/alpha_plugin_controller.rb b/vendor/plugins/engines/test/plugins/alpha_plugin/app/controllers/namespace/alpha_plugin_controller.rb
deleted file mode 100644 (file)
index 5edf81b..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-class Namespace::AlphaPluginController < ApplicationController
-  def an_action
-    render_class_and_action
-  end  
-end
\ No newline at end of file
diff --git a/vendor/plugins/engines/test/plugins/alpha_plugin/app/controllers/namespace/app_and_plugin_controller.rb b/vendor/plugins/engines/test/plugins/alpha_plugin/app/controllers/namespace/app_and_plugin_controller.rb
deleted file mode 100644 (file)
index 7431a36..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-class Namespace::AppAndPluginController < ApplicationController
-  def an_action
-    render_class_and_action 'from alpha_plugin'
-  end
-end
diff --git a/vendor/plugins/engines/test/plugins/alpha_plugin/app/controllers/namespace/shared_plugin_controller.rb b/vendor/plugins/engines/test/plugins/alpha_plugin/app/controllers/namespace/shared_plugin_controller.rb
deleted file mode 100644 (file)
index fb162bc..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-class Namespace::SharedPluginController < ApplicationController
-  def an_action
-    render_class_and_action 'from alpha_plugin'
-  end
-end
diff --git a/vendor/plugins/engines/test/plugins/alpha_plugin/app/controllers/shared_plugin_controller.rb b/vendor/plugins/engines/test/plugins/alpha_plugin/app/controllers/shared_plugin_controller.rb
deleted file mode 100644 (file)
index 00539bb..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-class SharedEngineController < ApplicationController
-  def an_action
-    render_class_and_action 'from alpha_engine'
-  end
-end
diff --git a/vendor/plugins/engines/test/plugins/alpha_plugin/app/models/alpha_plugin_model.rb b/vendor/plugins/engines/test/plugins/alpha_plugin/app/models/alpha_plugin_model.rb
deleted file mode 100644 (file)
index cde71b8..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-class AlphaPluginModel < ActiveRecord::Base
-  def self.report_location; TestHelper::report_location(__FILE__); end
-end
\ No newline at end of file
diff --git a/vendor/plugins/engines/test/plugins/alpha_plugin/app/models/app_and_plugin_model.rb b/vendor/plugins/engines/test/plugins/alpha_plugin/app/models/app_and_plugin_model.rb
deleted file mode 100644 (file)
index 92e6e62..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-class AppAndPluginModel < ActiveRecord::Base
-  def self.report_location; TestHelper::report_location(__FILE__); end
-
-  def defined_only_in_alpha_plugin_version
-    # should not be defined as the model in app/models takes precedence
-  end
-end
\ No newline at end of file
diff --git a/vendor/plugins/engines/test/plugins/alpha_plugin/app/models/shared_plugin_model.rb b/vendor/plugins/engines/test/plugins/alpha_plugin/app/models/shared_plugin_model.rb
deleted file mode 100644 (file)
index e2ef43d..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-class SharedPluginModel < ActiveRecord::Base  
-  def self.report_location; TestHelper::report_location(__FILE__); end
-end
\ No newline at end of file
diff --git a/vendor/plugins/engines/test/plugins/alpha_plugin/app/views/alpha_plugin/a_view.html.erb b/vendor/plugins/engines/test/plugins/alpha_plugin/app/views/alpha_plugin/a_view.html.erb
deleted file mode 100644 (file)
index 1ad6945..0000000
+++ /dev/null
@@ -1 +0,0 @@
-<%= TestHelper.view_path_for __FILE__ %>
\ No newline at end of file
diff --git a/vendor/plugins/engines/test/plugins/alpha_plugin/app/views/app_and_plugin/a_view.html.erb b/vendor/plugins/engines/test/plugins/alpha_plugin/app/views/app_and_plugin/a_view.html.erb
deleted file mode 100644 (file)
index 791a6fa..0000000
+++ /dev/null
@@ -1 +0,0 @@
-<%= TestHelper.view_path_for __FILE__ %> (from a_view)
\ No newline at end of file
diff --git a/vendor/plugins/engines/test/plugins/alpha_plugin/app/views/layouts/plugin_layout.erb b/vendor/plugins/engines/test/plugins/alpha_plugin/app/views/layouts/plugin_layout.erb
deleted file mode 100644 (file)
index 878e07c..0000000
+++ /dev/null
@@ -1 +0,0 @@
-<%= yield %> (with plugin layout)
\ No newline at end of file
diff --git a/vendor/plugins/engines/test/plugins/alpha_plugin/app/views/namespace/alpha_plugin/a_view.html.erb b/vendor/plugins/engines/test/plugins/alpha_plugin/app/views/namespace/alpha_plugin/a_view.html.erb
deleted file mode 100644 (file)
index 1ad6945..0000000
+++ /dev/null
@@ -1 +0,0 @@
-<%= TestHelper.view_path_for __FILE__ %>
\ No newline at end of file
diff --git a/vendor/plugins/engines/test/plugins/alpha_plugin/app/views/namespace/app_and_plugin/a_view.html.erb b/vendor/plugins/engines/test/plugins/alpha_plugin/app/views/namespace/app_and_plugin/a_view.html.erb
deleted file mode 100644 (file)
index 1ad6945..0000000
+++ /dev/null
@@ -1 +0,0 @@
-<%= TestHelper.view_path_for __FILE__ %>
\ No newline at end of file
diff --git a/vendor/plugins/engines/test/plugins/alpha_plugin/app/views/namespace/shared_plugin/a_view.html.erb b/vendor/plugins/engines/test/plugins/alpha_plugin/app/views/namespace/shared_plugin/a_view.html.erb
deleted file mode 100644 (file)
index f144ab3..0000000
+++ /dev/null
@@ -1 +0,0 @@
-<%= TestHelper.view_path_for __FILE__ %> (from alpha_plugin)
\ No newline at end of file
diff --git a/vendor/plugins/engines/test/plugins/alpha_plugin/app/views/shared_plugin/a_view.html.erb b/vendor/plugins/engines/test/plugins/alpha_plugin/app/views/shared_plugin/a_view.html.erb
deleted file mode 100644 (file)
index f144ab3..0000000
+++ /dev/null
@@ -1 +0,0 @@
-<%= TestHelper.view_path_for __FILE__ %> (from alpha_plugin)
\ No newline at end of file
diff --git a/vendor/plugins/engines/test/plugins/alpha_plugin/lib/alpha_plugin_lib_model.rb b/vendor/plugins/engines/test/plugins/alpha_plugin/lib/alpha_plugin_lib_model.rb
deleted file mode 100644 (file)
index 0ce4f91..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-class AlphaPluginLibModel < ActiveRecord::Base
-  def self.report_location; TestHelper::report_location(__FILE__); end
-end
\ No newline at end of file
diff --git a/vendor/plugins/engines/test/plugins/alpha_plugin/lib/app_and_plugin_lib_model.rb b/vendor/plugins/engines/test/plugins/alpha_plugin/lib/app_and_plugin_lib_model.rb
deleted file mode 100644 (file)
index 645a70c..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-class AppAndPluginLibModel < ActiveRecord::Base
-  def self.report_location; TestHelper::report_location(__FILE__); end
-
-  def defined_only_in_alpha_plugin_version
-    # should not be defined
-  end
-end
\ No newline at end of file
diff --git a/vendor/plugins/engines/test/plugins/alpha_plugin/locales/en.yml b/vendor/plugins/engines/test/plugins/alpha_plugin/locales/en.yml
deleted file mode 100644 (file)
index 76d39d3..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-en:
-  hello: "Hello from alfa"
-  plugin: "alfa"
diff --git a/vendor/plugins/engines/test/plugins/beta_plugin/app/controllers/app_and_plugin_controller.rb b/vendor/plugins/engines/test/plugins/beta_plugin/app/controllers/app_and_plugin_controller.rb
deleted file mode 100644 (file)
index 2e77989..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-class AppAndPluginController < ApplicationController
-  def an_action
-    render_class_and_action 'from beta_plugin'
-  end
-end
diff --git a/vendor/plugins/engines/test/plugins/beta_plugin/app/controllers/namespace/shared_plugin_controller.rb b/vendor/plugins/engines/test/plugins/beta_plugin/app/controllers/namespace/shared_plugin_controller.rb
deleted file mode 100644 (file)
index 971c7d5..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-class Namespace::SharedPluginController < ApplicationController
-  def an_action
-    render_class_and_action 'from beta_plugin'
-  end
-end
diff --git a/vendor/plugins/engines/test/plugins/beta_plugin/app/controllers/shared_plugin_controller.rb b/vendor/plugins/engines/test/plugins/beta_plugin/app/controllers/shared_plugin_controller.rb
deleted file mode 100644 (file)
index ddd9dbe..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-class SharedPluginController < ApplicationController
-  def an_action
-    render_class_and_action 'from beta_plugin'
-  end
-end
diff --git a/vendor/plugins/engines/test/plugins/beta_plugin/app/models/shared_plugin_model.rb b/vendor/plugins/engines/test/plugins/beta_plugin/app/models/shared_plugin_model.rb
deleted file mode 100644 (file)
index bfde227..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-class SharedPluginModel < ActiveRecord::Base
-  def self.report_location; TestHelper::report_location(__FILE__); end
-end
\ No newline at end of file
diff --git a/vendor/plugins/engines/test/plugins/beta_plugin/app/views/namespace/shared_plugin/a_view.html.erb b/vendor/plugins/engines/test/plugins/beta_plugin/app/views/namespace/shared_plugin/a_view.html.erb
deleted file mode 100644 (file)
index 77b5a15..0000000
+++ /dev/null
@@ -1 +0,0 @@
-<%= TestHelper.view_path_for __FILE__ %> (from beta_plugin)
\ No newline at end of file
diff --git a/vendor/plugins/engines/test/plugins/beta_plugin/app/views/shared_plugin/a_view.html.erb b/vendor/plugins/engines/test/plugins/beta_plugin/app/views/shared_plugin/a_view.html.erb
deleted file mode 100644 (file)
index 77b5a15..0000000
+++ /dev/null
@@ -1 +0,0 @@
-<%= TestHelper.view_path_for __FILE__ %> (from beta_plugin)
\ No newline at end of file
diff --git a/vendor/plugins/engines/test/plugins/beta_plugin/init.rb b/vendor/plugins/engines/test/plugins/beta_plugin/init.rb
deleted file mode 100644 (file)
index b4c4b0e..0000000
+++ /dev/null
@@ -1 +0,0 @@
-# just here so that Rails recognizes this as a plugin
\ No newline at end of file
diff --git a/vendor/plugins/engines/test/plugins/beta_plugin/locales/en.yml b/vendor/plugins/engines/test/plugins/beta_plugin/locales/en.yml
deleted file mode 100644 (file)
index f49279c..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-en:
-  hello: "Hello from beta"
-  plugin: "beta"
diff --git a/vendor/plugins/engines/test/plugins/not_a_plugin/public/should_not_be_copied.txt b/vendor/plugins/engines/test/plugins/not_a_plugin/public/should_not_be_copied.txt
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/vendor/plugins/engines/test/plugins/test_assets/app/controllers/assets_controller.rb b/vendor/plugins/engines/test/plugins/test_assets/app/controllers/assets_controller.rb
deleted file mode 100644 (file)
index db5de2e..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-class AssetsController < ApplicationController
-end
\ No newline at end of file
diff --git a/vendor/plugins/engines/test/plugins/test_assets/app/views/assets/index.html.erb b/vendor/plugins/engines/test/plugins/test_assets/app/views/assets/index.html.erb
deleted file mode 100644 (file)
index 8340f76..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-<%= image_tag 'image.png', :plugin => 'test_assets' %>
-<%= javascript_include_tag 'file.1.js', 'file2', :plugin => "test_assets" %>
-<%= stylesheet_link_tag 'file.1.css', 'file2', :plugin => "test_assets" %>
-<%= image_submit_tag 'image.png', :plugin => "test_assets" %>
diff --git a/vendor/plugins/engines/test/plugins/test_assets/app/views/layouts/assets.html.erb b/vendor/plugins/engines/test/plugins/test_assets/app/views/layouts/assets.html.erb
deleted file mode 100644 (file)
index b7da375..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-<div id="assets_layout">
-       <%= yield %>
-</div>
\ No newline at end of file
diff --git a/vendor/plugins/engines/test/plugins/test_assets/init.rb b/vendor/plugins/engines/test/plugins/test_assets/init.rb
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/vendor/plugins/engines/test/plugins/test_assets/public/file.txt b/vendor/plugins/engines/test/plugins/test_assets/public/file.txt
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/vendor/plugins/engines/test/plugins/test_assets/public/subfolder/file_in_subfolder.txt b/vendor/plugins/engines/test/plugins/test_assets/public/subfolder/file_in_subfolder.txt
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/vendor/plugins/engines/test/plugins/test_assets_with_assets_directory/assets/file.txt b/vendor/plugins/engines/test/plugins/test_assets_with_assets_directory/assets/file.txt
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/vendor/plugins/engines/test/plugins/test_assets_with_assets_directory/assets/subfolder/file_in_subfolder.txt b/vendor/plugins/engines/test/plugins/test_assets_with_assets_directory/assets/subfolder/file_in_subfolder.txt
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/vendor/plugins/engines/test/plugins/test_assets_with_assets_directory/init.rb b/vendor/plugins/engines/test/plugins/test_assets_with_assets_directory/init.rb
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/vendor/plugins/engines/test/plugins/test_assets_with_no_subdirectory/assets/file.txt b/vendor/plugins/engines/test/plugins/test_assets_with_no_subdirectory/assets/file.txt
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/vendor/plugins/engines/test/plugins/test_assets_with_no_subdirectory/init.rb b/vendor/plugins/engines/test/plugins/test_assets_with_no_subdirectory/init.rb
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/vendor/plugins/engines/test/plugins/test_code_mixing/app/things/thing.rb b/vendor/plugins/engines/test/plugins/test_code_mixing/app/things/thing.rb
deleted file mode 100644 (file)
index 535d988..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-class Thing
-  def self.from_plugin; TestHelper::report_location(__FILE__); end
-end
\ No newline at end of file
diff --git a/vendor/plugins/engines/test/plugins/test_code_mixing/init.rb b/vendor/plugins/engines/test/plugins/test_code_mixing/init.rb
deleted file mode 100644 (file)
index b4c4b0e..0000000
+++ /dev/null
@@ -1 +0,0 @@
-# just here so that Rails recognizes this as a plugin
\ No newline at end of file
diff --git a/vendor/plugins/engines/test/plugins/test_load_path/init.rb b/vendor/plugins/engines/test/plugins/test_load_path/init.rb
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/vendor/plugins/engines/test/plugins/test_migration/db/migrate/001_create_tests.rb b/vendor/plugins/engines/test/plugins/test_migration/db/migrate/001_create_tests.rb
deleted file mode 100644 (file)
index 804a0cd..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-class CreateTests < ActiveRecord::Migration
-  def self.up
-    create_table 'tests' do |t|
-      t.column 'name', :string
-    end
-  end
-
-  def self.down
-    drop_table 'tests'
-  end
-end
diff --git a/vendor/plugins/engines/test/plugins/test_migration/db/migrate/002_create_others.rb b/vendor/plugins/engines/test/plugins/test_migration/db/migrate/002_create_others.rb
deleted file mode 100644 (file)
index 756aca6..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-class CreateOthers < ActiveRecord::Migration
-  def self.up
-    create_table 'others' do |t|
-      t.column 'name', :string
-    end
-  end
-
-  def self.down
-    drop_table 'others'
-  end
-end
diff --git a/vendor/plugins/engines/test/plugins/test_migration/db/migrate/003_create_extras.rb b/vendor/plugins/engines/test/plugins/test_migration/db/migrate/003_create_extras.rb
deleted file mode 100644 (file)
index fb5b6c2..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-class CreateExtras < ActiveRecord::Migration
-  def self.up
-    create_table 'extras' do |t|
-      t.column 'name', :string
-    end
-  end
-
-  def self.down
-    drop_table 'extras'
-  end
-end
diff --git a/vendor/plugins/engines/test/plugins/test_migration/init.rb b/vendor/plugins/engines/test/plugins/test_migration/init.rb
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/vendor/plugins/engines/test/plugins/test_plugin_mailing/app/models/plugin_mail.rb b/vendor/plugins/engines/test/plugins/test_plugin_mailing/app/models/plugin_mail.rb
deleted file mode 100644 (file)
index 4f36616..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-class PluginMail < ActionMailer::Base
-  def mail_from_plugin(note=nil)
-    body(:note => note)
-  end
-  
-  def mail_from_plugin_with_application_template(note=nil)
-    body(:note => note)
-  end
-  
-  def multipart_from_plugin
-    content_type 'multipart/alternative'
-    part :content_type => "text/html", :body => render_message("multipart_from_plugin_html", {})
-    part "text/plain" do |p|
-      p.body = render_message("multipart_from_plugin_plain", {})
-    end
-  end
-  
-  def multipart_from_plugin_with_application_template
-    content_type 'multipart/alternative'
-    part :content_type => "text/html", :body => render_message("multipart_from_plugin_with_application_template_html", {})
-    part "text/plain" do |p|
-      p.body = render_message("multipart_from_plugin_with_application_template_plain", {})
-    end
-  end  
-  
-end
\ No newline at end of file
diff --git a/vendor/plugins/engines/test/plugins/test_plugin_mailing/app/views/plugin_mail/mail_from_plugin.erb b/vendor/plugins/engines/test/plugins/test_plugin_mailing/app/views/plugin_mail/mail_from_plugin.erb
deleted file mode 100644 (file)
index 2b49606..0000000
+++ /dev/null
@@ -1 +0,0 @@
-<%= @note %>
\ No newline at end of file
diff --git a/vendor/plugins/engines/test/plugins/test_plugin_mailing/app/views/plugin_mail/multipart_from_plugin_html.html.erb b/vendor/plugins/engines/test/plugins/test_plugin_mailing/app/views/plugin_mail/multipart_from_plugin_html.html.erb
deleted file mode 100644 (file)
index 46291d8..0000000
+++ /dev/null
@@ -1 +0,0 @@
-html template
\ No newline at end of file
diff --git a/vendor/plugins/engines/test/plugins/test_plugin_mailing/app/views/plugin_mail/multipart_from_plugin_plain.html.erb b/vendor/plugins/engines/test/plugins/test_plugin_mailing/app/views/plugin_mail/multipart_from_plugin_plain.html.erb
deleted file mode 100644 (file)
index f690dba..0000000
+++ /dev/null
@@ -1 +0,0 @@
-plain template
\ No newline at end of file
diff --git a/vendor/plugins/engines/test/plugins/test_plugin_mailing/app/views/plugin_mail/multipart_from_plugin_with_application_template_html.html.erb b/vendor/plugins/engines/test/plugins/test_plugin_mailing/app/views/plugin_mail/multipart_from_plugin_with_application_template_html.html.erb
deleted file mode 100644 (file)
index 795f0d5..0000000
+++ /dev/null
@@ -1 +0,0 @@
-template from plugin
\ No newline at end of file
diff --git a/vendor/plugins/engines/test/plugins/test_plugin_mailing/app/views/plugin_mail/multipart_from_plugin_with_application_template_plain.html.erb b/vendor/plugins/engines/test/plugins/test_plugin_mailing/app/views/plugin_mail/multipart_from_plugin_with_application_template_plain.html.erb
deleted file mode 100644 (file)
index 795f0d5..0000000
+++ /dev/null
@@ -1 +0,0 @@
-template from plugin
\ No newline at end of file
diff --git a/vendor/plugins/engines/test/plugins/test_plugin_mailing/init.rb b/vendor/plugins/engines/test/plugins/test_plugin_mailing/init.rb
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/vendor/plugins/engines/test/plugins/test_routing/app/controllers/namespace/test_routing_controller.rb b/vendor/plugins/engines/test/plugins/test_routing/app/controllers/namespace/test_routing_controller.rb
deleted file mode 100644 (file)
index 29d7bdb..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-class Namespace::TestRoutingController < ApplicationController
-  def routed_action
-    render_class_and_action
-  end
-end
\ No newline at end of file
diff --git a/vendor/plugins/engines/test/plugins/test_routing/app/controllers/test_routing_controller.rb b/vendor/plugins/engines/test/plugins/test_routing/app/controllers/test_routing_controller.rb
deleted file mode 100644 (file)
index ac3164a..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-class TestRoutingController < ApplicationController
-  def routed_action
-    render_class_and_action
-  end
-  
-  def test_named_routes_from_plugin
-    render :text => plugin_route_path(:action => "index")
-  end
-end
\ No newline at end of file
diff --git a/vendor/plugins/engines/test/plugins/test_routing/config/routes.rb b/vendor/plugins/engines/test/plugins/test_routing/config/routes.rb
deleted file mode 100644 (file)
index dbc49f9..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-ActionController::Routing::Routes.draw do |map|
-  map.connect 'routes/:action', :controller => "test_routing"
-  map.plugin_route 'somespace/routes/:action', :controller => "namespace/test_routing"
-end
\ No newline at end of file
diff --git a/vendor/plugins/engines/test/plugins/test_routing/init.rb b/vendor/plugins/engines/test/plugins/test_routing/init.rb
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/vendor/plugins/engines/test/plugins/test_testing/app/README.txt b/vendor/plugins/engines/test/plugins/test_testing/app/README.txt
deleted file mode 100644 (file)
index 784e4fe..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Fixtures are only copied from plugins with an +app+ directory, but git needs this directory to be non-empty
\ No newline at end of file
diff --git a/vendor/plugins/engines/test/plugins/test_testing/init.rb b/vendor/plugins/engines/test/plugins/test_testing/init.rb
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/vendor/plugins/engines/test/plugins/test_testing/test/fixtures/testing_fixtures.yml b/vendor/plugins/engines/test/plugins/test_testing/test/fixtures/testing_fixtures.yml
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/vendor/plugins/engines/test/plugins/test_testing/test/unit/override_test.rb b/vendor/plugins/engines/test/plugins/test_testing/test/unit/override_test.rb
deleted file mode 100644 (file)
index 4c4c42a..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-require File.expand_path(File.join(File.dirname(__FILE__), *%w[.. .. .. .. .. test test_helper]))
-
-class OverrideTest < ActiveSupport::TestCase
-  def test_overrides_from_the_application_should_work
-    flunk "this test should be overridden by the app"
-  end
-  
-  def test_tests_within_the_plugin_should_still_run
-    assert true, "non-overridden plugin tests should still run"
-  end
-end
-
-Engines::Testing.override_tests_from_app
\ No newline at end of file
diff --git a/vendor/plugins/engines/test/unit/action_mailer_test.rb b/vendor/plugins/engines/test/unit/action_mailer_test.rb
deleted file mode 100644 (file)
index fc3e756..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-require File.dirname(__FILE__) + '/../test_helper'
-
-class ActionMailerWithinApplicationTest < Test::Unit::TestCase
-  
-  def test_normal_implicit_template
-    m = NotifyMail.create_signup("hello")
-    assert m.body =~ /^Signup template from application/
-  end
-  
-  def test_action_mailer_can_get_helper
-    m = NotifyMail.create_signup('James')
-    assert m.body =~ /James/
-    assert m.body =~ /semaJ/ # from the helper
-  end
-  
-  def test_multipart_mails_with_explicit_templates
-    m = NotifyMail.create_multipart
-    assert_equal 2, m.parts.length
-    assert_equal 'the html part of the email james', m.parts[0].body
-    assert_equal 'the plaintext part of the email', m.parts[1].body
-  end
-  
-  def test_multipart_mails_with_implicit_templates
-    m = NotifyMail.create_implicit_multipart
-    assert_equal 2, m.parts.length
-    assert_equal 'the implicit plaintext part of the email', m.parts[0].body    
-    assert_equal 'the implicit html part of the email james', m.parts[1].body
-  end
-end
-
-
-class ActionMailerWithinPluginsTest < Test::Unit::TestCase  
-  def test_should_be_able_to_create_mails_from_plugin
-    m = PluginMail.create_mail_from_plugin("from_plugin")
-    assert_equal "from_plugin", m.body
-  end
-  
-  def test_should_be_able_to_overload_views_within_the_application
-    m = PluginMail.create_mail_from_plugin_with_application_template("from_plugin")
-    assert_equal "from_plugin (from application)", m.body    
-  end
-  
-  def test_should_be_able_to_create_a_multipart_mail_from_within_plugin
-    m = PluginMail.create_multipart_from_plugin
-    assert_equal 2, m.parts.length
-    assert_equal 'html template', m.parts[0].body
-    assert_equal 'plain template', m.parts[1].body
-  end
-  
-  def test_plugin_mailer_template_overriding
-    m = PluginMail.create_multipart_from_plugin_with_application_template
-    assert_equal 'plugin mail template loaded from application', m.parts[1].body
-  end
-end
\ No newline at end of file
diff --git a/vendor/plugins/engines/test/unit/arbitrary_code_mixing_test.rb b/vendor/plugins/engines/test/unit/arbitrary_code_mixing_test.rb
deleted file mode 100644 (file)
index 4b862f3..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-require File.dirname(__FILE__) + '/../test_helper'
-
-class ArbitraryCodeMixingTest < Test::Unit::TestCase  
-  def setup
-    Engines.code_mixing_file_types = %w(controller helper)
-  end
-  
-  def test_should_allow_setting_of_different_code_mixing_file_types
-    assert_nothing_raised {
-      Engines.mix_code_from :things
-    }
-  end
-
-  def test_should_add_new_types_to_existing_code_mixing_file_types
-    Engines.mix_code_from :things
-    assert_equal ["controller", "helper", "thing"], Engines.code_mixing_file_types
-    Engines.mix_code_from :other
-    assert_equal ["controller", "helper", "thing", "other"], Engines.code_mixing_file_types
-  end
-  
-  def test_should_allow_setting_of_multiple_types_at_once
-    Engines.mix_code_from :things, :other
-    assert_equal ["controller", "helper", "thing", "other"], Engines.code_mixing_file_types
-  end
-   
-  def test_should_singularize_elements_to_be_mixed
-    # this is the only test using mocha, so let's try to work around it
-    # also, this seems to be already tested with the :things in the tests above
-    # arg = stub(:to_s => stub(:singularize => "element")) 
-    Engines.mix_code_from :elements
-    assert Engines.code_mixing_file_types.include?("element")
-  end
-  
-  # TODO doesn't seem to work as expected?
-  
-  # def test_should_successfully_mix_custom_types
-  #   Engines.mix_code_from :things    
-  #   assert_equal 'Thing (from app)', Thing.from_app
-  #   assert_equal 'Thing (from test_code_mixing)', Thing.from_plugin
-  # end
-end
\ No newline at end of file
diff --git a/vendor/plugins/engines/test/unit/assets_test.rb b/vendor/plugins/engines/test/unit/assets_test.rb
deleted file mode 100644 (file)
index 3332c53..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-require File.dirname(__FILE__) + '/../test_helper'
-
-class AssetsTest < Test::Unit::TestCase  
-  def setup
-    Engines::Assets.mirror_files_for Engines.plugins[:test_assets]
-  end
-  
-  def teardown
-    FileUtils.rm_r(Engines.public_directory) if File.exist?(Engines.public_directory)
-  end
-  
-  def test_engines_has_created_base_public_file
-    assert File.exist?(Engines.public_directory)
-  end
-  
-  def test_engines_has_created_README_in_public_directory
-    assert File.exist?(File.join(Engines.public_directory, 'README'))
-  end
-  
-  def test_public_files_have_been_copied_from_test_assets_plugin
-    assert File.exist?(File.join(Engines.public_directory, 'test_assets'))
-    assert File.exist?(File.join(Engines.public_directory, 'test_assets', 'file.txt'))
-    assert File.exist?(File.join(Engines.public_directory, 'test_assets', 'subfolder'))
-    assert File.exist?(File.join(Engines.public_directory, 'test_assets', 'subfolder', 'file_in_subfolder.txt'))
-  end
-  
-  def test_engines_has_not_created_duplicated_file_structure
-    assert !File.exists?(File.join(Engines.public_directory, "test_assets", RAILS_ROOT))
-  end
-  
-  def test_public_files_have_been_copied_from_test_assets_with_assets_dir_plugin
-    Engines::Assets.mirror_files_for Engines.plugins[:test_assets_with_assets_directory]
-
-    assert File.exist?(File.join(Engines.public_directory, 'test_assets_with_assets_directory'))
-    assert File.exist?(File.join(Engines.public_directory, 'test_assets_with_assets_directory', 'file.txt'))
-    assert File.exist?(File.join(Engines.public_directory, 'test_assets_with_assets_directory', 'subfolder'))
-    assert File.exist?(File.join(Engines.public_directory, 'test_assets_with_assets_directory', 'subfolder', 'file_in_subfolder.txt'))
-  end
-  
-  def test_public_files_have_been_copied_from_test_assets_with_no_subdirectory_plugin
-    Engines::Assets.mirror_files_for Engines.plugins[:test_assets_with_no_subdirectory]
-
-    assert File.exist?(File.join(Engines.public_directory, 'test_assets_with_no_subdirectory'))
-    assert File.exist?(File.join(Engines.public_directory, 'test_assets_with_no_subdirectory', 'file.txt'))    
-  end
-  
-  def test_public_files_have_NOT_been_copied_from_plugins_without_public_or_asset_directories
-    Engines::Assets.mirror_files_for Engines.plugins[:alpha_plugin]
-    
-    assert !File.exist?(File.join(Engines.public_directory, 'alpha_plugin'))
-  end
-end
\ No newline at end of file
diff --git a/vendor/plugins/engines/test/unit/backwards_compat_test.rb b/vendor/plugins/engines/test/unit/backwards_compat_test.rb
deleted file mode 100644 (file)
index 4fa3698..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-require File.dirname(__FILE__) + '/../test_helper'
-
-class BackwardsCompatibilityTest < Test::Unit::TestCase
-  def test_rails_module_plugin_method_should_delegate_to_engines_plugins
-    assert_nothing_raised { Rails.plugins }
-    assert_equal Engines.plugins, Rails.plugins 
-  end
-end
\ No newline at end of file
diff --git a/vendor/plugins/engines/test/unit/load_path_test.rb b/vendor/plugins/engines/test/unit/load_path_test.rb
deleted file mode 100644 (file)
index c26d331..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-# Tests in this file ensure that:
-#
-# * the application /app/[controllers|helpers|models] and /lib 
-#   paths preceed the corresponding plugin paths
-# * the plugin paths are added to $LOAD_PATH in the order in which plugins are 
-#   loaded
-
-require File.dirname(__FILE__) + '/../test_helper'
-
-class LoadPathTest < Test::Unit::TestCase
-  def setup
-    @load_path = expand_paths($LOAD_PATH)
-  end
-  
-  # Not sure if these test actually make sense as this now essentially tests
-  # Rails core functionality. On the other hand Engines relies on this to some
-  # extend so this will choke if something important changes in Rails.
-  
-  # the application app/... and lib/ directories should appear
-  # before any plugin directories
-  
-  def test_application_app_libs_should_precede_all_plugin_app_libs
-    types = %w(app/controllers app/helpers app/models lib)
-    types.each do |t|
-      app_index = load_path_index(File.join(RAILS_ROOT, t))
-      assert_not_nil app_index, "#{t} is missing in $LOAD_PATH"
-      Engines.plugins.each do |plugin|
-        first_plugin_index = load_path_index(File.join(plugin.directory, t))
-        assert(app_index < first_plugin_index) unless first_plugin_index.nil?
-      end
-    end
-  end
-  
-  # the engine directories should appear in the proper order based on
-  # the order they were started  
-  
-  def test_plugin_dirs_should_appear_in_reverse_plugin_loading_order
-    app_paths = %w(app/controllers/ app app/models app/helpers lib)
-    app_paths.map { |p| File.join(RAILS_ROOT, p)}
-    plugin_paths = Engines.plugins.reverse.collect { |plugin| plugin.load_paths.reverse }.flatten    
-    
-    expected_paths = expand_paths(app_paths + plugin_paths)    
-    # only look at those paths that are also present in expected_paths so
-    # the only difference would be in the order of the paths
-    actual_paths = @load_path & expected_paths 
-    
-    assert_equal expected_paths, actual_paths
-  end
-  
-  protected    
-    def expand_paths(paths)
-      paths.collect { |p| File.expand_path(p) }
-    end
-    
-    def load_path_index(dir)
-      @load_path.index(File.expand_path(dir))
-    end  
-end
\ No newline at end of file
diff --git a/vendor/plugins/engines/test/unit/migration_test.rb b/vendor/plugins/engines/test/unit/migration_test.rb
deleted file mode 100644 (file)
index eae7fe7..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-require File.dirname(__FILE__) + '/../test_helper'
-require 'rails_generator'
-require 'rails_generator/scripts/generate'
-
-class MigrationsTest < Test::Unit::TestCase
-  
-  @@migration_dir = "#{RAILS_ROOT}/db/migrate"
-
-  def setup
-    ActiveRecord::Migration.verbose = false
-    Engines.plugins[:test_migration].migrate(0)
-  end
-  
-  def teardown
-    FileUtils.rm_r(@@migration_dir) if File.exist?(@@migration_dir)
-  end
-  
-  def test_engine_migrations_can_run_down
-    assert !table_exists?('tests'), ActiveRecord::Base.connection.tables.inspect
-    assert !table_exists?('others'), ActiveRecord::Base.connection.tables.inspect
-    assert !table_exists?('extras'), ActiveRecord::Base.connection.tables.inspect
-  end
-    
-  def test_engine_migrations_can_run_up
-    Engines.plugins[:test_migration].migrate(3)
-    assert table_exists?('tests')
-    assert table_exists?('others')
-    assert table_exists?('extras')
-  end
-  
-  def test_engine_migrations_can_upgrade_incrementally
-    Engines.plugins[:test_migration].migrate(1)
-    assert table_exists?('tests')
-    assert !table_exists?('others')
-    assert !table_exists?('extras')
-    assert_equal 1, Engines::Plugin::Migrator.current_version(Engines.plugins[:test_migration])
-    
-    
-    Engines.plugins[:test_migration].migrate(2)
-    assert table_exists?('others')
-    assert_equal 2, Engines::Plugin::Migrator.current_version(Engines.plugins[:test_migration])
-    
-    
-    Engines.plugins[:test_migration].migrate(3)
-    assert table_exists?('extras')
-    assert_equal 3, Engines::Plugin::Migrator.current_version(Engines.plugins[:test_migration])
-  end
-    
-  def test_generator_creates_plugin_migration_file
-    Rails::Generator::Scripts::Generate.new.run(['plugin_migration', 'test_migration'], :quiet => true)
-    assert migration_file, "migration file is missing"
-  end
-  
-  private
-  
-  def table_exists?(table)
-    ActiveRecord::Base.connection.tables.include?(table)
-  end
-  
-  def migration_file
-    Dir["#{@@migration_dir}/*test_migration_to_version_3.rb"][0]
-  end
-end
\ No newline at end of file
diff --git a/vendor/plugins/engines/test/unit/model_and_lib_test.rb b/vendor/plugins/engines/test/unit/model_and_lib_test.rb
deleted file mode 100644 (file)
index e5aa773..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-require File.dirname(__FILE__) + '/../test_helper'
-
-class ModelAndLibTest < Test::Unit::TestCase
-
-       def test_WITH_a_model_defined_only_in_a_plugin_IT_should_load_the_model
-         assert_equal 'AlphaPluginModel (from alpha_plugin)', AlphaPluginModel.report_location
-  end
-  
-  def test_WITH_a_model_defined_only_in_a_plugin_lib_dir_IT_should_load_the_model
-         assert_equal 'AlphaPluginLibModel (from alpha_plugin)', AlphaPluginLibModel.report_location
-  end
-
-  # app takes precedence over plugins
-       
-       def test_WITH_a_model_defined_in_both_app_and_plugin_IT_should_load_the_one_in_app
-         assert_equal 'AppAndPluginModel (from app)',  AppAndPluginModel.report_location  
-         assert_raises(NoMethodError) { AppAndPluginLibModel.defined_only_in_alpha_engine_version }
-  end
-       
-       def test_WITH_a_model_defined_in_both_app_and_plugin_lib_dirs_IT_should_load_the_one_in_app
-         assert_equal 'AppAndPluginLibModel (from lib)', AppAndPluginLibModel.report_location
-         assert_raises(NoMethodError) { AppAndPluginLibModel.defined_only_in_alpha_engine_version }
-  end
-
-  # subsequently loaded plugins take precendence over previously loaded plugins
-       
-  # TODO
-  #
-  # this does work when we rely on $LOAD_PATH while it won't work when we use
-  # Dependency constant autoloading. This somewhat confusing difference has
-  # been there since at least Rails 1.2.x. See http://www.ruby-forum.com/topic/134529
-  
-  def test_WITH_a_model_defined_in_two_plugins_IT_should_load_the_latter_of_both
-    require 'shared_plugin_model'
-    assert_equal SharedPluginModel.report_location, 'SharedPluginModel (from beta_plugin)'
-  end
-end
\ No newline at end of file
diff --git a/vendor/plugins/engines/test/unit/plugins_test.rb b/vendor/plugins/engines/test/unit/plugins_test.rb
deleted file mode 100644 (file)
index f8627bc..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-require File.dirname(__FILE__) + '/../test_helper'
-
-class PluginsTest < Test::Unit::TestCase
-  
-  def test_should_allow_access_to_plugins_by_strings_or_symbols
-    p = Engines.plugins["alpha_plugin"]
-    q = Engines.plugins[:alpha_plugin]
-    assert_kind_of Engines::Plugin, p
-    assert_equal p, q
-  end
-end
\ No newline at end of file
diff --git a/vendor/plugins/engines/test/unit/test_testing/override_test.rb b/vendor/plugins/engines/test/unit/test_testing/override_test.rb
deleted file mode 100644 (file)
index ea58a51..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-require File.join(File.dirname(__FILE__), *%w[.. .. test_helper])
-
-class OverrideTest < ActiveSupport::TestCase
-  def test_overrides_from_the_application_should_work
-    assert true, "overriding plugin tests from the application should work"
-  end
-end
\ No newline at end of file
diff --git a/vendor/plugins/engines/test/unit/testing_test.rb b/vendor/plugins/engines/test/unit/testing_test.rb
deleted file mode 100644 (file)
index c0c37ed..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-require File.dirname(__FILE__) + '/../test_helper'
-
-class TestingTest < Test::Unit::TestCase
-  def setup
-    Engines::Testing.set_fixture_path
-    @filename = File.join(Engines::Testing.temporary_fixtures_directory, 'testing_fixtures.yml')
-    File.delete(@filename) if File.exists?(@filename)
-  end
-  
-  def teardown
-    File.delete(@filename) if File.exists?(@filename)
-  end
-
-  def test_should_copy_fixtures_files_to_tmp_directory
-    assert !File.exists?(@filename)
-    Engines::Testing.setup_plugin_fixtures
-    assert File.exists?(@filename)
-  end
-end
\ No newline at end of file
index 7349bd3c0c149349446aeaed76f026994ad0da1f..0c8971efdf4a0e48511bc40bfa42840c5dd5d8c2 100644 (file)
@@ -1,3 +1,5 @@
+* Dump heavy lifting off to rack-openid gem. OpenIdAuthentication is just a simple controller concern.
+
 * Fake HTTP method from OpenID server since they only support a GET. Eliminates the need to set an extra route to match the server's reply. [Josh Peek]
 
 * OpenID 2.0 recommends that forms should use the field name "openid_identifier" rather than "openid_url" [Josh Peek]
index 807cdc7562eac0e5e6a0ee339db0e259482b689b..fe2b37e297444eacf00703b7da9e522e753a61ca 100644 (file)
@@ -14,22 +14,14 @@ The specification used is http://openid.net/specs/openid-authentication-2_0.html
 Prerequisites
 =============
 
-OpenID authentication uses the session, so be sure that you haven't turned that off. It also relies on a number of
-database tables to store the authentication keys. So you'll have to run the migration to create these before you get started:
-
-  rake open_id_authentication:db:create
-
-Or, use the included generators to install or upgrade:
-
-  ./script/generate open_id_authentication_tables MigrationName
-  ./script/generate upgrade_open_id_authentication_tables MigrationName
+OpenID authentication uses the session, so be sure that you haven't turned that off.
 
 Alternatively, you can use the file-based store, which just relies on on tmp/openids being present in RAILS_ROOT. But be aware that this store only works if you have a single application server. And it's not safe to use across NFS. It's recommended that you use the database store if at all possible. To use the file-based store, you'll also have to add this line to your config/environment.rb:
 
   OpenIdAuthentication.store = :file
 
 This particular plugin also relies on the fact that the authentication action allows for both POST and GET operations.
-If you're using RESTful authentication, you'll need to explicitly allow for this in your routes.rb. 
+If you're using RESTful authentication, you'll need to explicitly allow for this in your routes.rb.
 
 The plugin also expects to find a root_url method that points to the home page of your site. You can accomplish this by using a root route in config/routes.rb:
 
@@ -53,7 +45,7 @@ Also of note is the following code block used in the example below:
   authenticate_with_open_id do |result, identity_url|
     ...
   end
-  
+
 In the above code block, 'identity_url' will need to match user.identity_url exactly. 'identity_url' will be a string in the form of 'http://example.com' -
 If you are storing just 'example.com' with your user, the lookup will fail.
 
@@ -131,8 +123,8 @@ app/controllers/sessions_controller.rb
           end
         end
       end
-    
-    
+
+
     private
       def successful_login
         session[:user_id] = @current_user.id
@@ -171,7 +163,7 @@ 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, 
+        authenticate_with_open_id(identity_url,
             :required => [ :nickname, :email ],
             :optional => :fullname) do |result, identity_url, registration|
           case result.status
@@ -199,7 +191,7 @@ You can support it in your app by changing #open_id_authentication
           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)
@@ -221,9 +213,9 @@ Some OpenID providers also support the OpenID AX (attribute exchange) protocol f
 
 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, 
+        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'
 
 
index 2055ef700363c78d902d8676c841ef8a10f9cc9b..84ec11fc4919a4ca9412e25e26e67f157022aa97 100644 (file)
@@ -1,16 +1,12 @@
-begin\r
-  require 'openid'\r
-rescue LoadError\r
-  begin\r
-    gem 'ruby-openid', '>=2.1.4'\r
-  rescue Gem::LoadError\r
-    # no openid support\r
-  end\r
-end\r
-\r
-if Object.const_defined?(:OpenID)\r
-  config.to_prepare do\r
-    OpenID::Util.logger = Rails.logger\r
-    ActionController::Base.send :include, OpenIdAuthentication\r
-  end\r
-end\r
+if Rails.version < '3'
+  config.gem 'rack-openid', :lib => 'rack/openid', :version => '>=0.2.1'
+end
+
+require 'open_id_authentication'
+
+config.middleware.use OpenIdAuthentication
+
+config.after_initialize do
+  OpenID::Util.logger = Rails.logger
+  ActionController::Base.send :include, OpenIdAuthentication
+end
index 70418fde7ea7ff008b15f94ce52ab54a567fe2a9..48be8ddba01c93d142bcd776a529f801eb0625b1 100644 (file)
@@ -1,15 +1,16 @@
 require 'uri'
-require 'openid/extensions/sreg'
-require 'openid/extensions/ax'
-require 'openid/store/filesystem'
-
-require File.dirname(__FILE__) + '/open_id_authentication/db_store'
-require File.dirname(__FILE__) + '/open_id_authentication/mem_cache_store'
-require File.dirname(__FILE__) + '/open_id_authentication/request'
-require File.dirname(__FILE__) + '/open_id_authentication/timeout_fixes' if OpenID::VERSION == "2.0.4"
+require 'openid'
+require 'rack/openid'
 
 module OpenIdAuthentication
-  OPEN_ID_AUTHENTICATION_DIR = RAILS_ROOT + "/tmp/openids"
+  def self.new(app)
+    store = OpenIdAuthentication.store
+    if store.nil?
+      Rails.logger.warn "OpenIdAuthentication.store is nil. Using in-memory store."
+    end
+
+    ::Rack::OpenID.new(app, OpenIdAuthentication.store)
+  end
 
   def self.store
     @@store
@@ -19,18 +20,22 @@ module OpenIdAuthentication
     store, *parameters = *([ store_option ].flatten)
 
     @@store = case store
-    when :db
-      OpenIdAuthentication::DbStore.new
-    when :mem_cache
-      OpenIdAuthentication::MemCacheStore.new(*parameters)
+    when :memory
+      require 'openid/store/memory'
+      OpenID::Store::Memory.new
     when :file
-      OpenID::Store::Filesystem.new(OPEN_ID_AUTHENTICATION_DIR)
+      require 'openid/store/filesystem'
+      OpenID::Store::Filesystem.new(Rails.root.join('tmp/openids'))
+    when :memcache
+      require 'memcache'
+      require 'openid/store/memcache'
+      OpenID::Store::Memcache.new(MemCache.new(parameters))
     else
-      raise "Unknown store: #{store}"
+      store
     end
   end
 
-  self.store = :db
+  self.store = nil
 
   class InvalidOpenId < StandardError
   end
@@ -99,143 +104,56 @@ module OpenIdAuthentication
     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]
+    # 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?(identifier = nil) #:doc:
+      identifier ||= open_id_identifier
+      !identifier.blank? || request.env[Rack::OpenID::RESPONSE]
     end
 
-    def authenticate_with_open_id(identity_url = nil, options = {}, &block) #:doc:
-      identity_url ||= params[:openid_identifier] || params[:openid_url]
+    def authenticate_with_open_id(identifier = nil, options = {}, &block) #:doc:
+      identifier ||= open_id_identifier
 
-      if params[:open_id_complete].nil?
-        begin_open_id_authentication(identity_url, options, &block)
-      else
+      if request.env[Rack::OpenID::RESPONSE]
         complete_open_id_authentication(&block)
+      else
+        begin_open_id_authentication(identifier, options, &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
+    def open_id_identifier
+      params[:openid_identifier] || params[:openid_url]
+    end
+
+    def begin_open_id_authentication(identifier, options = {})
+      options[:identifier] = identifier
+      value = Rack::OpenID.build_header(options)
+      response.headers[Rack::OpenID::AUTHENTICATE_HEADER] = value
+      head :unauthorized
     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
+      response   = request.env[Rack::OpenID::RESPONSE]
+      identifier = response.display_identifier
 
-      case open_id_response.status
+      case 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
+        yield Result[:successful], identifier,
+          OpenID::SReg::Response.from_success_response(response)
+      when :missing
+        yield Result[:missing], identifier, nil
+      when :invalid
+        yield Result[:invalid], identifier, nil
       when OpenID::Consumer::CANCEL
-        yield Result[:canceled], identity_url, nil
+        yield Result[:canceled], identifier, nil
       when OpenID::Consumer::FAILURE
-        yield Result[:failed], identity_url, nil
+        yield Result[:failed], identifier, nil
       when OpenID::Consumer::SETUP_NEEDED
-        yield Result[:setup_needed], open_id_response.setup_url, nil
+        yield Result[:setup_needed], 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}#{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/vendor/plugins/prepend_engine_views/init.rb b/vendor/plugins/prepend_engine_views/init.rb
deleted file mode 100644 (file)
index cbf0e89..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-module PrependEngineViews
-  def self.included(base)
-    base.send(:include, InstanceMethods)
-    base.class_eval do
-      alias_method_chain :add_engine_view_paths, :prepend
-    end
-  end
-
-  module InstanceMethods
-    # Patch Rails so engine's views are prepended to the view_path,
-    # thereby letting plugins override application views
-    def add_engine_view_paths_with_prepend
-      paths = ActionView::PathSet.new(engines.collect(&:view_path))
-      ActionController::Base.view_paths.unshift(*paths)
-      ActionMailer::Base.view_paths.unshift(*paths) if configuration.frameworks.include?(:action_mailer)
-    end
-  end
-end
-
-Rails::Plugin::Loader.send :include, PrependEngineViews
-
diff --git a/vendor/plugins/prototype_legacy_helper/README.markdown b/vendor/plugins/prototype_legacy_helper/README.markdown
new file mode 100644 (file)
index 0000000..8f87439
--- /dev/null
@@ -0,0 +1,13 @@
+# Prototype Legacy Helper
+
+This plugin adds support for `form_remote_tag`, etc from Rails 2 to Rails 3.
+
+## Installation
+
+Either add the following to your `Gemfile` and run `bundle`:
+
+    gem 'prototype_legacy_helper', '0.0.0', :git => 'git://github.com/rails/prototype_legacy_helper.git'
+
+or run the following command to vendor the plugin within your app:
+
+    rails plugin install git://github.com/rails/prototype_legacy_helper.git
diff --git a/vendor/plugins/prototype_legacy_helper/init.rb b/vendor/plugins/prototype_legacy_helper/init.rb
new file mode 100644 (file)
index 0000000..8590056
--- /dev/null
@@ -0,0 +1 @@
+require 'prototype_legacy_helper'
diff --git a/vendor/plugins/prototype_legacy_helper/lib/prototype_legacy_helper.rb b/vendor/plugins/prototype_legacy_helper/lib/prototype_legacy_helper.rb
new file mode 100644 (file)
index 0000000..8161eed
--- /dev/null
@@ -0,0 +1,432 @@
+module PrototypeHelper
+  # Creates a button with an onclick event which calls a remote action
+  # via XMLHttpRequest
+  # The options for specifying the target with :url
+  # and defining callbacks is the same as link_to_remote.
+  def button_to_remote(name, options = {}, html_options = {})
+    button_to_function(name, remote_function(options), html_options)
+  end
+
+  # Returns a button input tag with the element name of +name+ and a value (i.e., display text) of +value+
+  # that will submit form using XMLHttpRequest in the background instead of a regular POST request that
+  # reloads the page.
+  #
+  #  # Create a button that submits to the create action
+  #  #
+  #  # Generates: <input name="create_btn" onclick="new Ajax.Request('/testing/create',
+  #  #     {asynchronous:true, evalScripts:true, parameters:Form.serialize(this.form)});
+  #  #     return false;" type="button" value="Create" />
+  #  <%= submit_to_remote 'create_btn', 'Create', :url => { :action => 'create' } %>
+  #
+  #  # Submit to the remote action update and update the DIV succeed or fail based
+  #  # on the success or failure of the request
+  #  #
+  #  # Generates: <input name="update_btn" onclick="new Ajax.Updater({success:'succeed',failure:'fail'},
+  #  #      '/testing/update', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this.form)});
+  #  #      return false;" type="button" value="Update" />
+  #  <%= submit_to_remote 'update_btn', 'Update', :url => { :action => 'update' },
+  #     :update => { :success => "succeed", :failure => "fail" }
+  #
+  # <tt>options</tt> argument is the same as in form_remote_tag.
+  def submit_to_remote(name, value, options = {})
+    options[:with] ||= 'Form.serialize(this.form)'
+
+    html_options = options.delete(:html) || {}
+    html_options[:name] = name
+
+    button_to_remote(value, options, html_options)
+  end
+
+  # Returns a link to a remote action defined by <tt>options[:url]</tt>
+  # (using the url_for format) that's called in the background using
+  # XMLHttpRequest. The result of that request can then be inserted into a
+  # DOM object whose id can be specified with <tt>options[:update]</tt>.
+  # Usually, the result would be a partial prepared by the controller with
+  # render :partial.
+  #
+  # Examples:
+  #   # Generates: <a href="#" onclick="new Ajax.Updater('posts', '/blog/destroy/3', {asynchronous:true, evalScripts:true});
+  #   #            return false;">Delete this post</a>
+  #   link_to_remote "Delete this post", :update => "posts",
+  #     :url => { :action => "destroy", :id => post.id }
+  #
+  #   # Generates: <a href="#" onclick="new Ajax.Updater('emails', '/mail/list_emails', {asynchronous:true, evalScripts:true});
+  #   #            return false;"><img alt="Refresh" src="/images/refresh.png?" /></a>
+  #   link_to_remote(image_tag("refresh"), :update => "emails",
+  #     :url => { :action => "list_emails" })
+  #
+  # You can override the generated HTML options by specifying a hash in
+  # <tt>options[:html]</tt>.
+  #
+  #   link_to_remote "Delete this post", :update => "posts",
+  #     :url  => post_url(@post), :method => :delete,
+  #     :html => { :class  => "destructive" }
+  #
+  # You can also specify a hash for <tt>options[:update]</tt> to allow for
+  # easy redirection of output to an other DOM element if a server-side
+  # error occurs:
+  #
+  # Example:
+  #   # Generates: <a href="#" onclick="new Ajax.Updater({success:'posts',failure:'error'}, '/blog/destroy/5',
+  #   #            {asynchronous:true, evalScripts:true}); return false;">Delete this post</a>
+  #   link_to_remote "Delete this post",
+  #     :url => { :action => "destroy", :id => post.id },
+  #     :update => { :success => "posts", :failure => "error" }
+  #
+  # Optionally, you can use the <tt>options[:position]</tt> parameter to
+  # influence how the target DOM element is updated. It must be one of
+  # <tt>:before</tt>, <tt>:top</tt>, <tt>:bottom</tt>, or <tt>:after</tt>.
+  #
+  # The method used is by default POST. You can also specify GET or you
+  # can simulate PUT or DELETE over POST. All specified with <tt>options[:method]</tt>
+  #
+  # Example:
+  #   # Generates: <a href="#" onclick="new Ajax.Request('/person/4', {asynchronous:true, evalScripts:true, method:'delete'});
+  #   #            return false;">Destroy</a>
+  #   link_to_remote "Destroy", :url => person_url(:id => person), :method => :delete
+  #
+  # By default, these remote requests are processed asynchronous during
+  # which various JavaScript callbacks can be triggered (for progress
+  # indicators and the likes). All callbacks get access to the
+  # <tt>request</tt> object, which holds the underlying XMLHttpRequest.
+  #
+  # To access the server response, use <tt>request.responseText</tt>, to
+  # find out the HTTP status, use <tt>request.status</tt>.
+  #
+  # Example:
+  #   # Generates: <a href="#" onclick="new Ajax.Request('/words/undo?n=33', {asynchronous:true, evalScripts:true,
+  #   #            onComplete:function(request){undoRequestCompleted(request)}}); return false;">hello</a>
+  #   word = 'hello'
+  #   link_to_remote word,
+  #     :url => { :action => "undo", :n => word_counter },
+  #     :complete => "undoRequestCompleted(request)"
+  #
+  # The callbacks that may be specified are (in order):
+  #
+  # <tt>:loading</tt>::       Called when the remote document is being
+  #                           loaded with data by the browser.
+  # <tt>:loaded</tt>::        Called when the browser has finished loading
+  #                           the remote document.
+  # <tt>:interactive</tt>::   Called when the user can interact with the
+  #                           remote document, even though it has not
+  #                           finished loading.
+  # <tt>:success</tt>::       Called when the XMLHttpRequest is completed,
+  #                           and the HTTP status code is in the 2XX range.
+  # <tt>:failure</tt>::       Called when the XMLHttpRequest is completed,
+  #                           and the HTTP status code is not in the 2XX
+  #                           range.
+  # <tt>:complete</tt>::      Called when the XMLHttpRequest is complete
+  #                           (fires after success/failure if they are
+  #                           present).
+  #
+  # You can further refine <tt>:success</tt> and <tt>:failure</tt> by
+  # adding additional callbacks for specific status codes.
+  #
+  # Example:
+  #   # Generates: <a href="#" onclick="new Ajax.Request('/testing/action', {asynchronous:true, evalScripts:true,
+  #   #            on404:function(request){alert('Not found...? Wrong URL...?')},
+  #   #            onFailure:function(request){alert('HTTP Error ' + request.status + '!')}}); return false;">hello</a>
+  #   link_to_remote word,
+  #     :url => { :action => "action" },
+  #     404 => "alert('Not found...? Wrong URL...?')",
+  #     :failure => "alert('HTTP Error ' + request.status + '!')"
+  #
+  # A status code callback overrides the success/failure handlers if
+  # present.
+  #
+  # If you for some reason or another need synchronous processing (that'll
+  # block the browser while the request is happening), you can specify
+  # <tt>options[:type] = :synchronous</tt>.
+  #
+  # You can customize further browser side call logic by passing in
+  # JavaScript code snippets via some optional parameters. In their order
+  # of use these are:
+  #
+  # <tt>:confirm</tt>::      Adds confirmation dialog.
+  # <tt>:condition</tt>::    Perform remote request conditionally
+  #                          by this expression. Use this to
+  #                          describe browser-side conditions when
+  #                          request should not be initiated.
+  # <tt>:before</tt>::       Called before request is initiated.
+  # <tt>:after</tt>::        Called immediately after request was
+  #                          initiated and before <tt>:loading</tt>.
+  # <tt>:submit</tt>::       Specifies the DOM element ID that's used
+  #                          as the parent of the form elements. By
+  #                          default this is the current form, but
+  #                          it could just as well be the ID of a
+  #                          table row or any other DOM element.
+  # <tt>:with</tt>::         A JavaScript expression specifying
+  #                          the parameters for the XMLHttpRequest.
+  #                          Any expressions should return a valid
+  #                          URL query string.
+  #
+  #                          Example:
+  #
+  #                            :with => "'name=' + $('name').value"
+  #
+  # You can generate a link that uses AJAX in the general case, while
+  # degrading gracefully to plain link behavior in the absence of
+  # JavaScript by setting <tt>html_options[:href]</tt> to an alternate URL.
+  # Note the extra curly braces around the <tt>options</tt> hash separate
+  # it as the second parameter from <tt>html_options</tt>, the third.
+  #
+  # Example:
+  #   link_to_remote "Delete this post",
+  #     { :update => "posts", :url => { :action => "destroy", :id => post.id } },
+  #     :href => url_for(:action => "destroy", :id => post.id)
+  def link_to_remote(name, options = {}, html_options = nil)
+    link_to_function(name, remote_function(options), html_options || options.delete(:html))
+  end
+
+  # Returns a form tag that will submit using XMLHttpRequest in the
+  # background instead of the regular reloading POST arrangement. Even
+  # though it's using JavaScript to serialize the form elements, the form
+  # submission will work just like a regular submission as viewed by the
+  # receiving side (all elements available in <tt>params</tt>). The options for
+  # specifying the target with <tt>:url</tt> and defining callbacks is the same as
+  # +link_to_remote+.
+  #
+  # A "fall-through" target for browsers that doesn't do JavaScript can be
+  # specified with the <tt>:action</tt>/<tt>:method</tt> options on <tt>:html</tt>.
+  #
+  # Example:
+  #   # Generates:
+  #   #      <form action="/some/place" method="post" onsubmit="new Ajax.Request('',
+  #   #      {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;">
+  #   form_remote_tag :html => { :action =>
+  #     url_for(:controller => "some", :action => "place") }
+  #
+  # The Hash passed to the <tt>:html</tt> key is equivalent to the options (2nd)
+  # argument in the FormTagHelper.form_tag method.
+  #
+  # By default the fall-through action is the same as the one specified in
+  # the <tt>:url</tt> (and the default method is <tt>:post</tt>).
+  #
+  # form_remote_tag also takes a block, like form_tag:
+  #   # Generates:
+  #   #     <form action="/" method="post" onsubmit="new Ajax.Request('/',
+  #   #     {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)});
+  #   #     return false;"> <div><input name="commit" type="submit" value="Save" /></div>
+  #   #     </form>
+  #   <% form_remote_tag :url => '/posts' do -%>
+  #     <div><%= submit_tag 'Save' %></div>
+  #   <% end -%>
+  def form_remote_tag(options = {}, &block)
+    options[:form] = true
+
+    options[:html] ||= {}
+    options[:html][:onsubmit] =
+      (options[:html][:onsubmit] ? options[:html][:onsubmit] + "; " : "") +
+      "#{remote_function(options)}; return false;"
+
+    form_tag(options[:html].delete(:action) || url_for(options[:url]), options[:html], &block)
+  end
+
+  # Creates a form that will submit using XMLHttpRequest in the background
+  # instead of the regular reloading POST arrangement and a scope around a
+  # specific resource that is used as a base for questioning about
+  # values for the fields.
+  #
+  # === Resource
+  #
+  # Example:
+  #   <% remote_form_for(@post) do |f| %>
+  #     ...
+  #   <% end %>
+  #
+  # This will expand to be the same as:
+  #
+  #   <% remote_form_for :post, @post, :url => post_path(@post), :html => { :method => :put, :class => "edit_post", :id => "edit_post_45" } do |f| %>
+  #     ...
+  #   <% end %>
+  #
+  # === Nested Resource
+  #
+  # Example:
+  #   <% remote_form_for([@post, @comment]) do |f| %>
+  #     ...
+  #   <% end %>
+  #
+  # This will expand to be the same as:
+  #
+  #   <% remote_form_for :comment, @comment, :url => post_comment_path(@post, @comment), :html => { :method => :put, :class => "edit_comment", :id => "edit_comment_45" } do |f| %>
+  #     ...
+  #   <% end %>
+  #
+  # If you don't need to attach a form to a resource, then check out form_remote_tag.
+  #
+  # See FormHelper#form_for for additional semantics.
+  def remote_form_for(record_or_name_or_array, *args, &proc)
+    options = args.extract_options!
+
+    case record_or_name_or_array
+    when String, Symbol
+      object_name = record_or_name_or_array
+    when Array
+      object = record_or_name_or_array.last
+      object_name = ActiveModel::Naming.singular(object)
+      apply_form_for_options!(record_or_name_or_array, options)
+      args.unshift object
+    else
+      object      = record_or_name_or_array
+      object_name = ActiveModel::Naming.singular(record_or_name_or_array)
+      apply_form_for_options!(object, options)
+      args.unshift object
+    end
+
+    form_remote_tag options do
+      fields_for object_name, *(args << options), &proc
+    end
+  end
+  alias_method :form_remote_for, :remote_form_for
+
+  # Returns '<tt>eval(request.responseText)</tt>' which is the JavaScript function
+  # that +form_remote_tag+ can call in <tt>:complete</tt> to evaluate a multiple
+  # update return document using +update_element_function+ calls.
+  def evaluate_remote_response
+    "eval(request.responseText)"
+  end
+
+  # Observes the field with the DOM ID specified by +field_id+ and calls a
+  # callback when its contents have changed. The default callback is an
+  # Ajax call. By default the value of the observed field is sent as a
+  # parameter with the Ajax call.
+  #
+  # Example:
+  #  # Generates: new Form.Element.Observer('suggest', 0.25, function(element, value) {new Ajax.Updater('suggest',
+  #  #         '/testing/find_suggestion', {asynchronous:true, evalScripts:true, parameters:'q=' + value})})
+  #  <%= observe_field :suggest, :url => { :action => :find_suggestion },
+  #       :frequency => 0.25,
+  #       :update => :suggest,
+  #       :with => 'q'
+  #       %>
+  #
+  # Required +options+ are either of:
+  # <tt>:url</tt>::       +url_for+-style options for the action to call
+  #                       when the field has changed.
+  # <tt>:function</tt>::  Instead of making a remote call to a URL, you
+  #                       can specify javascript code to be called instead.
+  #                       Note that the value of this option is used as the
+  #                       *body* of the javascript function, a function definition
+  #                       with parameters named element and value will be generated for you
+  #                       for example:
+  #                         observe_field("glass", :frequency => 1, :function => "alert('Element changed')")
+  #                       will generate:
+  #                         new Form.Element.Observer('glass', 1, function(element, value) {alert('Element changed')})
+  #                       The element parameter is the DOM element being observed, and the value is its value at the
+  #                       time the observer is triggered.
+  #
+  # Additional options are:
+  # <tt>:frequency</tt>:: The frequency (in seconds) at which changes to
+  #                       this field will be detected. Not setting this
+  #                       option at all or to a value equal to or less than
+  #                       zero will use event based observation instead of
+  #                       time based observation.
+  # <tt>:update</tt>::    Specifies the DOM ID of the element whose
+  #                       innerHTML should be updated with the
+  #                       XMLHttpRequest response text.
+  # <tt>:with</tt>::      A JavaScript expression specifying the parameters
+  #                       for the XMLHttpRequest. The default is to send the
+  #                       key and value of the observed field. Any custom
+  #                       expressions should return a valid URL query string.
+  #                       The value of the field is stored in the JavaScript
+  #                       variable +value+.
+  #
+  #                       Examples
+  #
+  #                         :with => "'my_custom_key=' + value"
+  #                         :with => "'person[name]=' + prompt('New name')"
+  #                         :with => "Form.Element.serialize('other-field')"
+  #
+  #                       Finally
+  #                         :with => 'name'
+  #                       is shorthand for
+  #                         :with => "'name=' + value"
+  #                       This essentially just changes the key of the parameter.
+  #
+  # Additionally, you may specify any of the options documented in the
+  # <em>Common options</em> section at the top of this document.
+  #
+  # Example:
+  #
+  #   # Sends params: {:title => 'Title of the book'} when the book_title input
+  #   # field is changed.
+  #   observe_field 'book_title',
+  #     :url => 'http://example.com/books/edit/1',
+  #     :with => 'title'
+  #
+  #
+  def observe_field(field_id, options = {})
+    if options[:frequency] && options[:frequency] > 0
+      build_observer('Form.Element.Observer', field_id, options)
+    else
+      build_observer('Form.Element.EventObserver', field_id, options)
+    end
+  end
+
+  # Observes the form with the DOM ID specified by +form_id+ and calls a
+  # callback when its contents have changed. The default callback is an
+  # Ajax call. By default all fields of the observed field are sent as
+  # parameters with the Ajax call.
+  #
+  # The +options+ for +observe_form+ are the same as the options for
+  # +observe_field+. The JavaScript variable +value+ available to the
+  # <tt>:with</tt> option is set to the serialized form by default.
+  def observe_form(form_id, options = {})
+    if options[:frequency]
+      build_observer('Form.Observer', form_id, options)
+    else
+      build_observer('Form.EventObserver', form_id, options)
+    end
+  end
+
+  # Periodically calls the specified url (<tt>options[:url]</tt>) every
+  # <tt>options[:frequency]</tt> seconds (default is 10). Usually used to
+  # update a specified div (<tt>options[:update]</tt>) with the results
+  # of the remote call. The options for specifying the target with <tt>:url</tt>
+  # and defining callbacks is the same as link_to_remote.
+  # Examples:
+  #  # Call get_averages and put its results in 'avg' every 10 seconds
+  #  # Generates:
+  #  #      new PeriodicalExecuter(function() {new Ajax.Updater('avg', '/grades/get_averages',
+  #  #      {asynchronous:true, evalScripts:true})}, 10)
+  #  periodically_call_remote(:url => { :action => 'get_averages' }, :update => 'avg')
+  #
+  #  # Call invoice every 10 seconds with the id of the customer
+  #  # If it succeeds, update the invoice DIV; if it fails, update the error DIV
+  #  # Generates:
+  #  #      new PeriodicalExecuter(function() {new Ajax.Updater({success:'invoice',failure:'error'},
+  #  #      '/testing/invoice/16', {asynchronous:true, evalScripts:true})}, 10)
+  #  periodically_call_remote(:url => { :action => 'invoice', :id => customer.id },
+  #     :update => { :success => "invoice", :failure => "error" }
+  #
+  #  # Call update every 20 seconds and update the new_block DIV
+  #  # Generates:
+  #  # new PeriodicalExecuter(function() {new Ajax.Updater('news_block', 'update', {asynchronous:true, evalScripts:true})}, 20)
+  #  periodically_call_remote(:url => 'update', :frequency => '20', :update => 'news_block')
+  #
+  def periodically_call_remote(options = {})
+     frequency = options[:frequency] || 10 # every ten seconds by default
+     code = "new PeriodicalExecuter(function() {#{remote_function(options)}}, #{frequency})"
+     javascript_tag(code)
+  end
+
+  protected
+    def build_observer(klass, name, options = {})
+      if options[:with] && (options[:with] !~ /[\{=(.]/)
+        options[:with] = "'#{options[:with]}=' + encodeURIComponent(value)"
+      else
+        options[:with] ||= 'value' unless options[:function]
+      end
+
+      callback = options[:function] || remote_function(options)
+      javascript  = "new #{klass}('#{name}', "
+      javascript << "#{options[:frequency]}, " if options[:frequency]
+      javascript << "function(element, value) {"
+      javascript << "#{callback}}"
+      javascript << ")"
+      javascript_tag(javascript)
+    end
+end
+
+ActionController::Base.helper PrototypeHelper
diff --git a/vendor/plugins/prototype_legacy_helper/test/test_prototype_helper.rb b/vendor/plugins/prototype_legacy_helper/test/test_prototype_helper.rb
new file mode 100644 (file)
index 0000000..f21666f
--- /dev/null
@@ -0,0 +1,297 @@
+if ENV['RAILS_ROOT']
+  environment = File.expand_path('vendor/gems/environment', ENV['RAILS_ROOT'])
+  require environment if File.exist?("#{environment}.rb")
+end
+
+$:.unshift File.expand_path('../../lib', __FILE__)
+
+require 'test/unit'
+require 'action_view'
+require 'action_controller'
+require 'active_model'
+require 'prototype_helper'
+
+class Bunny < Struct.new(:Bunny, :id)
+end
+
+class Author
+  extend ActiveModel::Naming
+
+  attr_reader :id
+  def save; @id = 1 end
+  def new_record?; @id.nil? end
+  def name
+    @id.nil? ? 'new author' : "author ##{@id}"
+  end
+end
+
+class Article
+  extend ActiveModel::Naming
+
+  attr_reader :id
+  attr_reader :author_id
+  def save; @id = 1; @author_id = 1 end
+  def new_record?; @id.nil? end
+  def name
+    @id.nil? ? 'new article' : "article ##{@id}"
+  end
+end
+
+class Author::Nested < Author; end
+
+class PrototypeHelperTest < ActionView::TestCase
+  attr_accessor :formats, :output_buffer, :template_format
+
+  def _evaluate_assigns_and_ivars() end
+
+  def reset_formats(format)
+    @format = format
+  end
+
+  def setup
+    @record = @author = Author.new
+    @article = Article.new
+    super
+    @template = self
+    @controller = Class.new do
+      def url_for(options)
+        if options.is_a?(String)
+          options
+        else
+          url =  "http://www.example.com/"
+          url << options[:action].to_s if options and options[:action]
+          url << "?a=#{options[:a]}" if options && options[:a]
+          url << "&b=#{options[:b]}" if options && options[:a] && options[:b]
+          url
+        end
+      end
+    end.new
+  end
+
+
+  def test_observe_form
+    assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nnew Form.Observer('cart', 2, function(element, value) {new Ajax.Request('http://www.example.com/cart_changed', {asynchronous:true, evalScripts:true, parameters:value})})\n//]]>\n</script>),
+      observe_form("cart", :frequency => 2, :url => { :action => "cart_changed" })
+  end
+
+  def test_observe_form_using_function_for_callback
+    assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nnew Form.Observer('cart', 2, function(element, value) {alert('Form changed')})\n//]]>\n</script>),
+      observe_form("cart", :frequency => 2, :function => "alert('Form changed')")
+  end
+
+  def test_observe_field
+    assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nnew Form.Element.Observer('glass', 300, function(element, value) {new Ajax.Request('http://www.example.com/reorder_if_empty', {asynchronous:true, evalScripts:true, parameters:value})})\n//]]>\n</script>),
+      observe_field("glass", :frequency => 5.minutes, :url => { :action => "reorder_if_empty" })
+  end
+
+  def test_observe_field_using_with_option
+    expected = %(<script type=\"text/javascript\">\n//<![CDATA[\nnew Form.Element.Observer('glass', 300, function(element, value) {new Ajax.Request('http://www.example.com/check_value', {asynchronous:true, evalScripts:true, parameters:'id=' + encodeURIComponent(value)})})\n//]]>\n</script>)
+    assert_dom_equal expected, observe_field("glass", :frequency => 5.minutes, :url => { :action => "check_value" }, :with => 'id')
+    assert_dom_equal expected, observe_field("glass", :frequency => 5.minutes, :url => { :action => "check_value" }, :with => "'id=' + encodeURIComponent(value)")
+  end
+
+  def test_observe_field_using_json_in_with_option
+    expected = %(<script type=\"text/javascript\">\n//<![CDATA[\nnew Form.Element.Observer('glass', 300, function(element, value) {new Ajax.Request('http://www.example.com/check_value', {asynchronous:true, evalScripts:true, parameters:{'id':value}})})\n//]]>\n</script>)
+    assert_dom_equal expected, observe_field("glass", :frequency => 5.minutes, :url => { :action => "check_value" }, :with => "{'id':value}")
+  end
+
+  def test_observe_field_using_function_for_callback
+    assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nnew Form.Element.Observer('glass', 300, function(element, value) {alert('Element changed')})\n//]]>\n</script>),
+      observe_field("glass", :frequency => 5.minutes, :function => "alert('Element changed')")
+  end
+
+  def test_observe_field_without_frequency
+    assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nnew Form.Element.EventObserver('glass', function(element, value) {new Ajax.Request('http://www.example.com/', {asynchronous:true, evalScripts:true, parameters:value})})\n//]]>\n</script>),
+      observe_field("glass")
+  end
+
+
+  def test_periodically_call_remote
+    assert_dom_equal %(<script type="text/javascript">\n//<![CDATA[\nnew PeriodicalExecuter(function() {new Ajax.Updater('schremser_bier', 'http://www.example.com/mehr_bier', {asynchronous:true, evalScripts:true})}, 10)\n//]]>\n</script>),
+      periodically_call_remote(:update => "schremser_bier", :url => { :action => "mehr_bier" })
+  end
+
+  def test_periodically_call_remote_with_frequency
+    assert_dom_equal(
+      "<script type=\"text/javascript\">\n//<![CDATA[\nnew PeriodicalExecuter(function() {new Ajax.Request('http://www.example.com/', {asynchronous:true, evalScripts:true})}, 2)\n//]]>\n</script>",
+      periodically_call_remote(:frequency => 2)
+    )
+  end
+
+
+  def test_form_remote_tag
+    assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater('glass_of_beer', 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;\">),
+      form_remote_tag(:update => "glass_of_beer", :url => { :action => :fast  })
+    assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater({success:'glass_of_beer'}, 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;\">),
+      form_remote_tag(:update => { :success => "glass_of_beer" }, :url => { :action => :fast  })
+    assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater({failure:'glass_of_water'}, 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;\">),
+      form_remote_tag(:update => { :failure => "glass_of_water" }, :url => { :action => :fast  })
+    assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater({success:'glass_of_beer',failure:'glass_of_water'}, 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;\">),
+      form_remote_tag(:update => { :success => 'glass_of_beer', :failure => "glass_of_water" }, :url => { :action => :fast  })
+  end
+
+  def test_form_remote_tag_with_method
+    assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater('glass_of_beer', 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;\"><div style='margin:0;padding:0;display:inline'><input name='_method' type='hidden' value='put' /></div>),
+      form_remote_tag(:update => "glass_of_beer", :url => { :action => :fast  }, :html => { :method => :put })
+  end
+
+  def test_form_remote_tag_with_block_in_erb
+    __in_erb_template = ''
+    form_remote_tag(:update => "glass_of_beer", :url => { :action => :fast  }) { concat "Hello world!" }
+    assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater('glass_of_beer', 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;\">Hello world!</form>), output_buffer
+  end
+
+  def test_on_callbacks
+    callbacks = [:uninitialized, :loading, :loaded, :interactive, :complete, :success, :failure]
+    callbacks.each do |callback|
+      assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater('glass_of_beer', 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, on#{callback.to_s.capitalize}:function(request){monkeys();}, parameters:Form.serialize(this)}); return false;">),
+        form_remote_tag(:update => "glass_of_beer", :url => { :action => :fast  }, callback=>"monkeys();")
+      assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater({success:'glass_of_beer'}, 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, on#{callback.to_s.capitalize}:function(request){monkeys();}, parameters:Form.serialize(this)}); return false;">),
+        form_remote_tag(:update => { :success => "glass_of_beer" }, :url => { :action => :fast  }, callback=>"monkeys();")
+      assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater({failure:'glass_of_beer'}, 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, on#{callback.to_s.capitalize}:function(request){monkeys();}, parameters:Form.serialize(this)}); return false;">),
+        form_remote_tag(:update => { :failure => "glass_of_beer" }, :url => { :action => :fast  }, callback=>"monkeys();")
+      assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater({success:'glass_of_beer',failure:'glass_of_water'}, 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, on#{callback.to_s.capitalize}:function(request){monkeys();}, parameters:Form.serialize(this)}); return false;">),
+        form_remote_tag(:update => { :success => "glass_of_beer", :failure => "glass_of_water" }, :url => { :action => :fast  }, callback=>"monkeys();")
+    end
+
+    #HTTP status codes 200 up to 599 have callbacks
+    #these should work
+    100.upto(599) do |callback|
+      assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater('glass_of_beer', 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, on#{callback.to_s.capitalize}:function(request){monkeys();}, parameters:Form.serialize(this)}); return false;">),
+        form_remote_tag(:update => "glass_of_beer", :url => { :action => :fast  }, callback=>"monkeys();")
+    end
+
+    #test 200 and 404
+    assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater('glass_of_beer', 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, on200:function(request){monkeys();}, on404:function(request){bananas();}, parameters:Form.serialize(this)}); return false;">),
+      form_remote_tag(:update => "glass_of_beer", :url => { :action => :fast  }, 200=>"monkeys();", 404=>"bananas();")
+
+    #these shouldn't
+    1.upto(99) do |callback|
+      assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater('glass_of_beer', 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;">),
+        form_remote_tag(:update => "glass_of_beer", :url => { :action => :fast  }, callback=>"monkeys();")
+    end
+    600.upto(999) do |callback|
+      assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater('glass_of_beer', 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;">),
+        form_remote_tag(:update => "glass_of_beer", :url => { :action => :fast  }, callback=>"monkeys();")
+    end
+
+    #test ultimate combo
+    assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater('glass_of_beer', 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, on200:function(request){monkeys();}, on404:function(request){bananas();}, onComplete:function(request){c();}, onFailure:function(request){f();}, onLoading:function(request){c1()}, onSuccess:function(request){s()}, parameters:Form.serialize(this)}); return false;\">),
+      form_remote_tag(:update => "glass_of_beer", :url => { :action => :fast  }, :loading => "c1()", :success => "s()", :failure => "f();", :complete => "c();", 200=>"monkeys();", 404=>"bananas();")
+  end
+
+  def test_remote_form_for_with_record_identification_with_new_record
+    remote_form_for(@record, {:html => { :id => 'create-author' }}) {}
+
+    expected = %(<form action='#{authors_path}' onsubmit="new Ajax.Request('#{authors_path}', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;" class='new_author' id='create-author' method='post'></form>)
+    assert_dom_equal expected, output_buffer
+  end
+
+  def test_remote_form_for_with_record_identification_without_html_options
+    remote_form_for(@record) {}
+
+    expected = %(<form action='#{authors_path}' onsubmit="new Ajax.Request('#{authors_path}', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;" class='new_author' method='post' id='new_author'></form>)
+    assert_dom_equal expected, output_buffer
+  end
+
+  def test_remote_form_for_with_record_identification_with_existing_record
+    @record.save
+    remote_form_for(@record) {}
+
+    expected = %(<form action='#{author_path(@record)}' id='edit_author_1' method='post' onsubmit="new Ajax.Request('#{author_path(@record)}', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;" class='edit_author'><div style='margin:0;padding:0;display:inline'><input name='_method' type='hidden' value='put' /></div></form>)
+    assert_dom_equal expected, output_buffer
+  end
+
+  def test_remote_form_for_with_new_object_in_list
+    remote_form_for([@author, @article]) {}
+
+    expected = %(<form action='#{author_articles_path(@author)}' onsubmit="new Ajax.Request('#{author_articles_path(@author)}', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;" class='new_article' method='post' id='new_article'></form>)
+    assert_dom_equal expected, output_buffer
+  end
+
+  def test_remote_form_for_with_existing_object_in_list
+    @author.save
+    @article.save
+    remote_form_for([@author, @article]) {}
+
+    expected = %(<form action='#{author_article_path(@author, @article)}' id='edit_article_1' method='post' onsubmit="new Ajax.Request('#{author_article_path(@author, @article)}', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;" class='edit_article'><div style='margin:0;padding:0;display:inline'><input name='_method' type='hidden' value='put' /></div></form>)
+    assert_dom_equal expected, output_buffer
+  end
+
+
+  def test_button_to_remote
+    assert_dom_equal %(<input class=\"fine\" type=\"button\" value=\"Remote outpost\" onclick=\"new Ajax.Request('http://www.example.com/whatnot', {asynchronous:true, evalScripts:true});\" />),
+      button_to_remote("Remote outpost", { :url => { :action => "whatnot"  }}, { :class => "fine"  })
+    assert_dom_equal %(<input type=\"button\" value=\"Remote outpost\" onclick=\"new Ajax.Request('http://www.example.com/whatnot', {asynchronous:true, evalScripts:true, onComplete:function(request){alert(request.reponseText)}});\" />),
+      button_to_remote("Remote outpost", :complete => "alert(request.reponseText)", :url => { :action => "whatnot"  })
+    assert_dom_equal %(<input type=\"button\" value=\"Remote outpost\" onclick=\"new Ajax.Request('http://www.example.com/whatnot', {asynchronous:true, evalScripts:true, onSuccess:function(request){alert(request.reponseText)}});\" />),
+      button_to_remote("Remote outpost", :success => "alert(request.reponseText)", :url => { :action => "whatnot"  })
+    assert_dom_equal %(<input type=\"button\" value=\"Remote outpost\" onclick=\"new Ajax.Request('http://www.example.com/whatnot', {asynchronous:true, evalScripts:true, onFailure:function(request){alert(request.reponseText)}});\" />),
+      button_to_remote("Remote outpost", :failure => "alert(request.reponseText)", :url => { :action => "whatnot"  })
+    assert_dom_equal %(<input type=\"button\" value=\"Remote outpost\" onclick=\"new Ajax.Request('http://www.example.com/whatnot?a=10&amp;b=20', {asynchronous:true, evalScripts:true, onFailure:function(request){alert(request.reponseText)}});\" />),
+      button_to_remote("Remote outpost", :failure => "alert(request.reponseText)", :url => { :action => "whatnot", :a => '10', :b => '20' })
+  end
+
+  def test_submit_to_remote
+    assert_dom_equal %(<input name=\"More beer!\" onclick=\"new Ajax.Updater('empty_bottle', 'http://www.example.com/', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this.form)});\" type=\"button\" value=\"1000000\" />),
+      submit_to_remote("More beer!", 1_000_000, :update => "empty_bottle")
+  end
+
+
+  def test_link_to_remote
+    assert_dom_equal %(<a class=\"fine\" href=\"#\" onclick=\"new Ajax.Request('http://www.example.com/whatnot', {asynchronous:true, evalScripts:true}); return false;\">Remote outauthor</a>),
+      link_to_remote("Remote outauthor", { :url => { :action => "whatnot"  }}, { :class => "fine"  })
+    assert_dom_equal %(<a href=\"#\" onclick=\"new Ajax.Request('http://www.example.com/whatnot', {asynchronous:true, evalScripts:true, onComplete:function(request){alert(request.responseText)}}); return false;\">Remote outauthor</a>),
+      link_to_remote("Remote outauthor", :complete => "alert(request.responseText)", :url => { :action => "whatnot"  })
+    assert_dom_equal %(<a href=\"#\" onclick=\"new Ajax.Request('http://www.example.com/whatnot', {asynchronous:true, evalScripts:true, onSuccess:function(request){alert(request.responseText)}}); return false;\">Remote outauthor</a>),
+      link_to_remote("Remote outauthor", :success => "alert(request.responseText)", :url => { :action => "whatnot"  })
+    assert_dom_equal %(<a href=\"#\" onclick=\"new Ajax.Request('http://www.example.com/whatnot', {asynchronous:true, evalScripts:true, onFailure:function(request){alert(request.responseText)}}); return false;\">Remote outauthor</a>),
+      link_to_remote("Remote outauthor", :failure => "alert(request.responseText)", :url => { :action => "whatnot"  })
+    assert_dom_equal %(<a href=\"#\" onclick=\"new Ajax.Request('http://www.example.com/whatnot?a=10&amp;b=20', {asynchronous:true, evalScripts:true, onFailure:function(request){alert(request.responseText)}}); return false;\">Remote outauthor</a>),
+      link_to_remote("Remote outauthor", :failure => "alert(request.responseText)", :url => { :action => "whatnot", :a => '10', :b => '20' })
+    assert_dom_equal %(<a href=\"#\" onclick=\"new Ajax.Request('http://www.example.com/whatnot', {asynchronous:false, evalScripts:true}); return false;\">Remote outauthor</a>),
+      link_to_remote("Remote outauthor", :url => { :action => "whatnot" }, :type => :synchronous)
+    assert_dom_equal %(<a href=\"#\" onclick=\"new Ajax.Request('http://www.example.com/whatnot', {asynchronous:true, evalScripts:true, insertion:'bottom'}); return false;\">Remote outauthor</a>),
+      link_to_remote("Remote outauthor", :url => { :action => "whatnot" }, :position => :bottom)
+  end
+
+  def test_link_to_remote_html_options
+    assert_dom_equal %(<a class=\"fine\" href=\"#\" onclick=\"new Ajax.Request('http://www.example.com/whatnot', {asynchronous:true, evalScripts:true}); return false;\">Remote outauthor</a>),
+      link_to_remote("Remote outauthor", { :url => { :action => "whatnot"  }, :html => { :class => "fine" } })
+  end
+
+  def test_link_to_remote_url_quote_escaping
+    assert_dom_equal %(<a href="#" onclick="new Ajax.Request('http://www.example.com/whatnot\\\'s', {asynchronous:true, evalScripts:true}); return false;">Remote</a>),
+      link_to_remote("Remote", { :url => { :action => "whatnot's" } })
+  end
+
+  protected
+    def request_forgery_protection_token
+      nil
+    end
+
+    def protect_against_forgery?
+      false
+    end
+
+    def create_generator
+      block = Proc.new { |*args| yield *args if block_given? }
+      JavaScriptGenerator.new self, &block
+    end
+
+    def author_path(record)
+      "/authors/#{record.id}"
+    end
+
+    def authors_path
+      "/authors"
+    end
+
+    def author_articles_path(author)
+      "/authors/#{author.id}/articles"
+    end
+
+    def author_article_path(author, article)
+      "/authors/#{author.id}/articles/#{article.id}"
+    end
+end