Merge branch 'master' into moderation
authorAndy Allan <git@gravitystorm.co.uk>
Wed, 29 Nov 2017 12:18:39 +0000 (12:18 +0000)
committerAndy Allan <git@gravitystorm.co.uk>
Wed, 29 Nov 2017 12:18:39 +0000 (12:18 +0000)
438 files changed:
.rubocop.yml
.rubocop_todo.yml
.travis.yml
CONTRIBUTING.md
FAQ.md [new file with mode: 0644]
Gemfile
Gemfile.lock
README.md
Vendorfile
app/assets/images/banners/banner-sotm-2017.png [deleted file]
app/assets/images/banners/banner-sotmus2017.png [new file with mode: 0644]
app/assets/images/banners/osmf-membership-drive-2017.png [new file with mode: 0644]
app/assets/images/banners/sotmasia-2017-banner.png [new file with mode: 0644]
app/assets/javascripts/application.js
app/assets/javascripts/edit/id.js.erb
app/assets/javascripts/index.js
app/assets/javascripts/index/contextmenu.js
app/assets/javascripts/index/query.js
app/assets/javascripts/leaflet.layers.js
app/assets/javascripts/user.js
app/assets/stylesheets/common.scss
app/controllers/amf_controller.rb
app/controllers/api_controller.rb
app/controllers/application_controller.rb
app/controllers/changeset_controller.rb
app/controllers/diary_entry_controller.rb
app/controllers/geocoder_controller.rb
app/controllers/message_controller.rb
app/controllers/node_controller.rb
app/controllers/notes_controller.rb
app/controllers/oauth_controller.rb
app/controllers/old_controller.rb
app/controllers/relation_controller.rb
app/controllers/search_controller.rb
app/controllers/site_controller.rb
app/controllers/trace_controller.rb
app/controllers/user_blocks_controller.rb
app/controllers/user_controller.rb
app/controllers/user_preference_controller.rb
app/controllers/user_roles_controller.rb
app/controllers/way_controller.rb
app/helpers/application_helper.rb
app/helpers/banner_helper.rb
app/helpers/browse_helper.rb
app/helpers/changeset_helper.rb
app/helpers/open_graph_helper.rb
app/helpers/title_helper.rb
app/models/access_token.rb
app/models/acl.rb
app/models/changeset.rb
app/models/changeset_comment.rb
app/models/changeset_tag.rb
app/models/client_application.rb
app/models/diary_comment.rb
app/models/diary_entry.rb
app/models/diary_entry_subscription.rb
app/models/friend.rb
app/models/language.rb
app/models/message.rb
app/models/node.rb
app/models/node_tag.rb
app/models/note.rb
app/models/note_comment.rb
app/models/oauth2_token.rb
app/models/oauth2_verifier.rb
app/models/oauth_nonce.rb
app/models/oauth_token.rb
app/models/old_node.rb
app/models/old_node_tag.rb
app/models/old_relation.rb
app/models/old_relation_member.rb
app/models/old_relation_tag.rb
app/models/old_way.rb
app/models/old_way_node.rb
app/models/old_way_tag.rb
app/models/redaction.rb
app/models/relation.rb
app/models/relation_member.rb
app/models/relation_tag.rb
app/models/request_token.rb
app/models/trace.rb
app/models/tracepoint.rb
app/models/tracetag.rb
app/models/user.rb
app/models/user_block.rb
app/models/user_preference.rb
app/models/user_role.rb
app/models/user_token.rb
app/models/way.rb
app/models/way_node.rb
app/models/way_tag.rb
app/views/changeset/list.atom.builder
app/views/diary_entry/list.html.erb
app/views/layouts/_head.html.erb
app/views/user/account.html.erb
app/views/user/reset_password.html.erb
app/views/user/save.html.erb [deleted file]
config/banners.yml
config/environment.rb
config/environments/development.rb
config/environments/production.rb
config/initializers/banners.rb
config/initializers/secure_headers.rb
config/initializers/session_store.rb
config/initializers/streaming.rb [deleted file]
config/initializers/wrap_parameters.rb
config/locales/af.yml
config/locales/aln.yml
config/locales/ar.yml
config/locales/arz.yml
config/locales/ast.yml
config/locales/az.yml
config/locales/be-Tarask.yml
config/locales/be.yml
config/locales/bg.yml
config/locales/bn.yml
config/locales/br.yml
config/locales/bs.yml
config/locales/ca.yml
config/locales/cs.yml
config/locales/cy.yml
config/locales/da.yml
config/locales/de.yml
config/locales/diq.yml
config/locales/dsb.yml
config/locales/el.yml
config/locales/en-GB.yml
config/locales/en.yml
config/locales/eo.yml
config/locales/es.yml
config/locales/et.yml
config/locales/eu.yml
config/locales/fa.yml
config/locales/fi.yml
config/locales/fr.yml
config/locales/fur.yml
config/locales/ga.yml
config/locales/gd.yml
config/locales/gl.yml
config/locales/he.yml
config/locales/hr.yml
config/locales/hsb.yml
config/locales/hu.yml
config/locales/ia.yml
config/locales/id.yml
config/locales/is.yml
config/locales/it.yml
config/locales/ja.yml
config/locales/ka.yml
config/locales/kab.yml [new file with mode: 0644]
config/locales/ko.yml
config/locales/lb.yml
config/locales/lt.yml
config/locales/lv.yml
config/locales/mk.yml
config/locales/mr.yml
config/locales/ms.yml
config/locales/nb.yml
config/locales/ne.yml
config/locales/nl.yml
config/locales/nn.yml
config/locales/oc.yml
config/locales/pl.yml
config/locales/pt-BR.yml
config/locales/pt-PT.yml
config/locales/ro.yml
config/locales/ru.yml
config/locales/scn.yml
config/locales/sco.yml
config/locales/sk.yml
config/locales/sl.yml
config/locales/sq.yml
config/locales/sr-Latn.yml
config/locales/sr.yml
config/locales/sv.yml
config/locales/te.yml
config/locales/th.yml [new file with mode: 0644]
config/locales/tl.yml
config/locales/tr.yml
config/locales/uk.yml
config/locales/vi.yml
config/locales/zh-CN.yml
config/locales/zh-TW.yml
config/routes.rb
db/migrate/001_create_osm_db.rb
db/migrate/002_cleanup_osm_db.rb
db/migrate/003_sql_session_store_setup.rb
db/migrate/004_user_enhancements.rb
db/migrate/005_tile_tracepoints.rb
db/migrate/006_tile_nodes.rb
db/migrate/007_add_relations.rb
db/migrate/008_remove_segments.rb
db/migrate/009_way_nodes_node_idx.rb
db/migrate/010_diary_comments.rb
db/migrate/011_add_user_image.rb
db/migrate/012_add_admin_flag.rb
db/migrate/013_add_email_valid.rb
db/migrate/014_add_new_email.rb
db/migrate/015_add_user_visible.rb
db/migrate/016_add_creation_ip.rb
db/migrate/017_add_gpx_indexes.rb
db/migrate/018_create_acls.rb
db/migrate/019_add_timestamp_indexes.rb
db/migrate/020_populate_node_tags_and_remove.rb
db/migrate/021_move_to_innodb.rb
db/migrate/022_key_constraints.rb
db/migrate/023_add_changesets.rb
db/migrate/024_order_relation_members.rb
db/migrate/025_add_end_time_to_changesets.rb
db/migrate/026_add_changeset_user_index.rb
db/migrate/027_add_changeset_indexes.rb
db/migrate/028_add_more_changeset_indexes.rb
db/migrate/029_add_user_foreign_keys.rb
db/migrate/030_add_foreign_keys.rb
db/migrate/031_create_countries.rb
db/migrate/032_add_user_locale.rb
db/migrate/033_change_diary_entries_language.rb
db/migrate/034_create_languages.rb
db/migrate/035_change_user_locale.rb
db/migrate/036_add_visible_to_message.rb
db/migrate/037_add_sender_visible_to_message.rb
db/migrate/038_add_message_sender_index.rb
db/migrate/039_add_more_controls_to_gpx_files.rb
db/migrate/040_create_oauth_tables.rb
db/migrate/041_add_fine_o_auth_permissions.rb
db/migrate/042_add_foreign_keys_to_oauth_tables.rb
db/migrate/043_add_referer_to_user_token.rb
db/migrate/044_create_user_roles.rb
db/migrate/045_create_user_blocks.rb
db/migrate/046_alter_user_roles_and_blocks.rb
db/migrate/047_add_visible_to_diaries.rb
db/migrate/048_add_diary_creation_indexes.rb
db/migrate/049_improve_changeset_user_index.rb
db/migrate/050_add_user_index_to_diary_comments.rb
db/migrate/051_add_status_to_user.rb
db/migrate/052_add_contributor_terms_to_user.rb
db/migrate/053_add_map_bug_tables.rb
db/migrate/054_refactor_map_bug_tables.rb
db/migrate/055_change_map_bug_comment_type.rb
db/migrate/056_add_date_closed.rb
db/migrate/057_add_map_bug_comment_event.rb
db/migrate/20100513171259_add_user_date_index_to_changeset.rb
db/migrate/20100516124737_add_open_id.rb
db/migrate/20100910084426_add_callback_to_oauth_tokens.rb
db/migrate/20101114011429_add_editor_preference_to_user.rb
db/migrate/20110322001319_add_terms_seen_to_user.rb
db/migrate/20110508145337_cleanup_bug_tables.rb
db/migrate/20110521142405_rename_bugs_to_notes.rb
db/migrate/20110925112722_rename_ids.rb
db/migrate/20111116184519_update_oauth.rb
db/migrate/20111212183945_add_lowercase_user_indexes.rb
db/migrate/20120123184321_switch_to_paperclip.rb
db/migrate/20120208122334_merge_acl_address_and_mask.rb
db/migrate/20120208194454_add_domain_to_acl.rb
db/migrate/20120214210114_add_text_format.rb
db/migrate/20120219161649_add_user_image_fingerprint.rb
db/migrate/20120318201948_create_redactions.rb
db/migrate/20120328090602_drop_session_table.rb
db/migrate/20120404205604_add_user_and_description_to_redaction.rb
db/migrate/20120808231205_add_counter_caches.rb
db/migrate/20121005195010_add_diary_entry_counter_caches.rb
db/migrate/20121012044047_add_image_use_gravatar_to_users.rb
db/migrate/20121119165817_drop_nearby_place_from_notes.rb
db/migrate/20121202155309_remove_author_name_from_note_comment.rb
db/migrate/20121203124841_change_note_address_to_inet.rb
db/migrate/20130328184137_add_write_notes_permission.rb
db/migrate/20131212124700_add_created_at_index_to_note_comments.rb
db/migrate/20140115192822_add_text_index_to_note_comments.rb
db/migrate/20140117185510_drop_countries.rb
db/migrate/20140210003018_add_user_image_content_type.rb
db/migrate/20140507110937_create_changeset_comments.rb
db/migrate/20140519141742_add_join_table_between_users_and_changesets.rb
db/migrate/20150110152606_change_default_formats.rb
db/migrate/20150111192335_subscribe_old_changesets.rb
db/migrate/20150222101847_rename_openid_url.rb
db/migrate/20150818224516_set_default_gravatar_to_false_for_privacy.rb
db/migrate/20161002153425_add_join_table_between_users_and_diary_entries.rb
db/migrate/20161011010929_subscribe_authors_to_diary_entries.rb
db/migrate/20170222134109_add_user_indexes.rb
lib/bounding_box.rb
lib/classic_pagination/pagination_helper.rb
lib/consistency_validations.rb
lib/daemons/gpx_import_ctl
lib/diff_reader.rb
lib/gpx.rb
lib/not_redactable.rb
lib/osm.rb
lib/redactable.rb
lib/rich_text.rb
lib/session_persistence.rb
lib/tasks/auto_annotate_models.rake [new file with mode: 0644]
lib/tasks/testing.rake
test/application_system_test_case.rb [new file with mode: 0644]
test/controllers/changeset_controller_test.rb
test/controllers/diary_entry_controller_test.rb
test/controllers/geocoder_controller_test.rb
test/controllers/message_controller_test.rb
test/controllers/node_controller_test.rb
test/controllers/old_node_controller_test.rb
test/controllers/relation_controller_test.rb
test/controllers/trace_controller_test.rb
test/controllers/user_controller_test.rb
test/controllers/way_controller_test.rb
test/factories/acls.rb
test/factories/changeset_comments.rb
test/factories/changeset_tags.rb
test/factories/changesets.rb
test/factories/client_applications.rb
test/factories/diary_comments.rb
test/factories/diary_entries.rb
test/factories/friends.rb
test/factories/languages.rb
test/factories/messages.rb
test/factories/node.rb
test/factories/node_tags.rb
test/factories/note_comments.rb
test/factories/notes.rb
test/factories/old_node.rb
test/factories/old_node_tags.rb
test/factories/old_relation.rb
test/factories/old_relation_member.rb
test/factories/old_relation_tags.rb
test/factories/old_way.rb
test/factories/old_way_node.rb
test/factories/old_way_tags.rb
test/factories/redaction.rb
test/factories/relation.rb
test/factories/relation_member.rb
test/factories/relation_tags.rb
test/factories/tracepoints.rb
test/factories/traces.rb
test/factories/tracetags.rb
test/factories/user.rb
test/factories/user_blocks.rb
test/factories/user_preferences.rb
test/factories/user_role.rb
test/factories/way.rb
test/factories/way_node.rb
test/factories/way_tags.rb
test/helpers/browse_helper_test.rb
test/helpers/changeset_helper_test.rb
test/helpers/note_helper_test.rb
test/helpers/title_helper_test.rb
test/helpers/user_helper_test.rb
test/helpers/user_roles_helper_test.rb
test/http/geocoder_us.yml [deleted file]
test/integration/client_applications_test.rb
test/integration/user_roles_test.rb
test/lib/bounding_box_test.rb
test/lib/i18n_test.rb
test/lib/utf8_test.rb
test/models/changeset_comment_test.rb
test/models/language_test.rb
test/models/message_test.rb
test/models/note_comment_test.rb
test/models/note_test.rb
test/models/user_test.rb
test/system/site_test.rb [new file with mode: 0644]
test/test_helper.rb
vendor/assets/iD/iD.css.erb
vendor/assets/iD/iD.js
vendor/assets/iD/iD/img/cursor-pointer.png [deleted file]
vendor/assets/iD/iD/img/cursor-pointer2x.png [deleted file]
vendor/assets/iD/iD/img/iD-sprite.svg
vendor/assets/iD/iD/locales/af.json
vendor/assets/iD/iD/locales/ar-AA.json
vendor/assets/iD/iD/locales/ar.json
vendor/assets/iD/iD/locales/ast.json
vendor/assets/iD/iD/locales/bg-BG.json
vendor/assets/iD/iD/locales/bn.json
vendor/assets/iD/iD/locales/bs.json
vendor/assets/iD/iD/locales/ca.json
vendor/assets/iD/iD/locales/cs.json
vendor/assets/iD/iD/locales/da.json
vendor/assets/iD/iD/locales/de.json
vendor/assets/iD/iD/locales/dv.json
vendor/assets/iD/iD/locales/el.json
vendor/assets/iD/iD/locales/en-GB.json
vendor/assets/iD/iD/locales/en.json
vendor/assets/iD/iD/locales/eo.json
vendor/assets/iD/iD/locales/es.json
vendor/assets/iD/iD/locales/et.json
vendor/assets/iD/iD/locales/eu.json [new file with mode: 0644]
vendor/assets/iD/iD/locales/fa.json
vendor/assets/iD/iD/locales/fi.json
vendor/assets/iD/iD/locales/fr.json
vendor/assets/iD/iD/locales/gl.json
vendor/assets/iD/iD/locales/gu.json
vendor/assets/iD/iD/locales/he.json
vendor/assets/iD/iD/locales/hi.json
vendor/assets/iD/iD/locales/hr.json
vendor/assets/iD/iD/locales/hu.json
vendor/assets/iD/iD/locales/hy.json
vendor/assets/iD/iD/locales/id.json
vendor/assets/iD/iD/locales/is.json
vendor/assets/iD/iD/locales/it.json
vendor/assets/iD/iD/locales/ja.json
vendor/assets/iD/iD/locales/kn.json
vendor/assets/iD/iD/locales/ko.json
vendor/assets/iD/iD/locales/lt.json
vendor/assets/iD/iD/locales/lv.json
vendor/assets/iD/iD/locales/mk.json
vendor/assets/iD/iD/locales/ml.json
vendor/assets/iD/iD/locales/ms.json
vendor/assets/iD/iD/locales/ne.json
vendor/assets/iD/iD/locales/nl.json
vendor/assets/iD/iD/locales/no.json
vendor/assets/iD/iD/locales/pl.json
vendor/assets/iD/iD/locales/pt-BR.json
vendor/assets/iD/iD/locales/pt.json
vendor/assets/iD/iD/locales/ro.json
vendor/assets/iD/iD/locales/ru.json
vendor/assets/iD/iD/locales/si.json
vendor/assets/iD/iD/locales/sk.json
vendor/assets/iD/iD/locales/sl.json
vendor/assets/iD/iD/locales/sq.json
vendor/assets/iD/iD/locales/sr.json
vendor/assets/iD/iD/locales/sv.json
vendor/assets/iD/iD/locales/ta.json
vendor/assets/iD/iD/locales/te.json
vendor/assets/iD/iD/locales/th.json
vendor/assets/iD/iD/locales/tl.json
vendor/assets/iD/iD/locales/tr.json
vendor/assets/iD/iD/locales/uk.json
vendor/assets/iD/iD/locales/vi.json
vendor/assets/iD/iD/locales/yue.json
vendor/assets/iD/iD/locales/zh-CN.json
vendor/assets/iD/iD/locales/zh-HK.json
vendor/assets/iD/iD/locales/zh-TW.json
vendor/assets/iD/iD/locales/zh.json
vendor/assets/iD/iD/mapillary-js/arrow-up-white.svg [deleted file]
vendor/assets/iD/iD/mapillary-js/mapillary.js
vendor/assets/iD/iD/mapillary-js/mapillary.js.map
vendor/assets/iD/iD/mapillary-js/mapillary.min.css
vendor/assets/iD/iD/mapillary-js/mapillary.min.js
vendor/assets/leaflet/leaflet.css
vendor/assets/leaflet/leaflet.js
vendor/assets/leaflet/leaflet.osm.js

index e1f1724e0f995623182ed9025b71b5dbdfd65bf5..55be8141cf31c53115cecdcbe08ffd8d266b9089 100644 (file)
@@ -27,15 +27,34 @@ Rails:
 Layout/ExtraSpacing:
   AllowForAlignment: true
 
-Style/BracesAroundHashParameters:
-  EnforcedStyle: context_dependent
+Lint/PercentStringArray:
+  Exclude:
+    - 'config/initializers/secure_headers.rb'
+    - 'app/controllers/site_controller.rb'
 
-Style/FileName:
+Naming/FileName:
   Exclude:
     - 'script/deliver-message'
     - 'script/locale/reload-languages'
     - 'script/update-spam-blocks'
 
+Rails/ApplicationRecord:
+  Enabled: false
+
+Rails/HasManyOrHasOneDependent:
+  Enabled: false
+
+Rails/HttpPositionalArguments:
+  Enabled: false
+
+Rails/SkipsModelValidations:
+  Exclude:
+    - 'db/migrate/*.rb'
+    - 'app/controllers/user_controller.rb'
+
+Style/BracesAroundHashParameters:
+  EnforcedStyle: context_dependent
+
 Style/FormatStringToken:
   EnforcedStyle: template
 
@@ -60,19 +79,3 @@ Style/StringLiterals:
 
 Style/SymbolArray:
   EnforcedStyle: brackets
-
-Rails/ApplicationRecord:
-  Enabled: false
-
-Rails/HttpPositionalArguments:
-  Enabled: false
-
-Rails/SkipsModelValidations:
-  Exclude:
-    - 'db/migrate/*.rb'
-    - 'app/controllers/user_controller.rb'
-
-Lint/PercentStringArray:
-  Exclude:
-    - 'config/initializers/secure_headers.rb'
-    - 'app/controllers/site_controller.rb'
index e89927c9d83dc00c472d55aad17c8843e1ed8489..b4104079cb75734dd1f5802d9a4401482fe7e598 100644 (file)
@@ -1,11 +1,19 @@
 # This configuration was generated by
 # `rubocop --auto-gen-config`
-# on 2016-10-20 21:45:27 +0100 using RuboCop version 0.44.1.
+# on 2017-10-05 10:04:24 +0100 using RuboCop version 0.50.0.
 # The point is for the user to remove these configuration records
 # one by one as the offenses are removed from the code base.
 # Note that changes in the inspected code, or installation of new
 # versions of RuboCop, may require this file to be generated again.
 
+# Offense count: 1
+# Cop supports --auto-correct.
+# Configuration parameters: EnforcedStyle, SupportedStyles, IndentationWidth.
+# SupportedStyles: aligned, indented
+Layout/MultilineOperationIndentation:
+  Exclude:
+    - 'lib/bounding_box.rb'
+
 # Offense count: 34
 Lint/AmbiguousOperator:
   Exclude:
@@ -14,11 +22,11 @@ Lint/AmbiguousOperator:
     - 'test/lib/bounding_box_test.rb'
     - 'test/lib/country_test.rb'
 
-# Offense count: 117
+# Offense count: 124
 Lint/AmbiguousRegexpLiteral:
   Enabled: false
 
-# Offense count: 30
+# Offense count: 32
 # Configuration parameters: AllowSafeAssignment.
 Lint/AssignmentInCondition:
   Exclude:
@@ -36,52 +44,62 @@ Lint/AssignmentInCondition:
     - 'lib/osm.rb'
     - 'script/deliver-message'
 
-# Offense count: 5
+# Offense count: 4
 Lint/HandleExceptions:
   Exclude:
     - 'app/controllers/amf_controller.rb'
     - 'app/controllers/user_controller.rb'
-    - 'config/initializers/session.rb'
+
+# Offense count: 3
+Lint/InterpolationCheck:
+  Exclude:
+    - 'test/controllers/node_controller_test.rb'
+
+# Offense count: 2
+Lint/RescueWithoutErrorClass:
+  Exclude:
+    - 'app/helpers/browse_helper.rb'
 
 # Offense count: 2
 Lint/ShadowingOuterLocalVariable:
   Exclude:
     - 'app/views/changeset/list.atom.builder'
 
-# Offense count: 630
+# Offense count: 666
 Metrics/AbcSize:
   Max: 280
 
-# Offense count: 35
-# Configuration parameters: CountComments.
+# Offense count: 41
+# Configuration parameters: CountComments, ExcludedMethods.
 Metrics/BlockLength:
-  Max: 295
+  Max: 240
 
 # Offense count: 12
+# Configuration parameters: CountBlocks.
 Metrics/BlockNesting:
   Max: 5
 
-# Offense count: 62
+# Offense count: 63
 # Configuration parameters: CountComments.
 Metrics/ClassLength:
-  Max: 1790
+  Max: 1796
 
-# Offense count: 69
+# Offense count: 71
 Metrics/CyclomaticComplexity:
   Max: 20
 
-# Offense count: 2826
-# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives.
+# Offense count: 3004
+# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
 # URISchemes: http, https
 Metrics/LineLength:
-  Max: 1072
+  Max: 1073
 
-# Offense count: 612
+# Offense count: 675
 # Configuration parameters: CountComments.
 Metrics/MethodLength:
   Max: 179
 
-# Offense count: 1
+# Offense count: 2
 # Configuration parameters: CountComments.
 Metrics/ModuleLength:
   Max: 147
@@ -95,6 +113,30 @@ Metrics/ParameterLists:
 Metrics/PerceivedComplexity:
   Max: 23
 
+# Offense count: 5
+Naming/AccessorMethodName:
+  Exclude:
+    - 'app/controllers/application_controller.rb'
+    - 'app/helpers/title_helper.rb'
+    - 'app/models/old_way.rb'
+    - 'lib/osm.rb'
+    - 'lib/potlatch.rb'
+
+# Offense count: 8
+# Configuration parameters: NamePrefix, NamePrefixBlacklist, NameWhitelist.
+# NamePrefix: is_, has_, have_
+# NamePrefixBlacklist: is_, has_, have_
+# NameWhitelist: is_a?
+Naming/PredicateName:
+  Exclude:
+    - 'spec/**/*'
+    - 'app/models/changeset.rb'
+    - 'app/models/old_node.rb'
+    - 'app/models/old_relation.rb'
+    - 'app/models/old_way.rb'
+    - 'app/models/user.rb'
+    - 'lib/classic_pagination/pagination.rb'
+
 # Offense count: 2
 # Configuration parameters: Include.
 # Include: app/**/*.rb, config/**/*.rb, lib/**/*.rb
@@ -122,7 +164,7 @@ Rails/NotNullColumn:
     - 'db/migrate/025_add_end_time_to_changesets.rb'
     - 'db/migrate/20120404205604_add_user_and_description_to_redaction.rb'
 
-# Offense count: 17
+# Offense count: 20
 Rails/OutputSafety:
   Exclude:
     - 'app/controllers/user_controller.rb'
@@ -136,27 +178,18 @@ Rails/OutputSafety:
     - 'lib/rich_text.rb'
     - 'test/helpers/application_helper_test.rb'
 
-# Offense count: 74
+# Offense count: 86
 # Configuration parameters: EnforcedStyle, SupportedStyles.
 # SupportedStyles: strict, flexible
 Rails/TimeZone:
   Enabled: false
 
-# Offense count: 5
-Style/AccessorMethodName:
-  Exclude:
-    - 'app/controllers/application_controller.rb'
-    - 'app/helpers/title_helper.rb'
-    - 'app/models/old_way.rb'
-    - 'lib/osm.rb'
-    - 'lib/potlatch.rb'
-
 # Offense count: 1
 Style/AsciiComments:
   Exclude:
     - 'test/models/message_test.rb'
 
-# Offense count: 220
+# Offense count: 219
 Style/Documentation:
   Enabled: false
 
@@ -182,35 +215,15 @@ Style/LineEndConcatenation:
     - 'test/controllers/relation_controller_test.rb'
     - 'test/controllers/way_controller_test.rb'
 
-# Offense count: 71
+# Offense count: 75
 # Cop supports --auto-correct.
+# Configuration parameters: Strict.
 Style/NumericLiterals:
   MinDigits: 11
 
-# Offense count: 8
-# Configuration parameters: NamePrefix, NamePrefixBlacklist, NameWhitelist.
-# NamePrefix: is_, has_, have_
-# NamePrefixBlacklist: is_, has_, have_
-# NameWhitelist: is_a?
-Style/PredicateName:
-  Exclude:
-    - 'spec/**/*'
-    - 'app/models/changeset.rb'
-    - 'app/models/old_node.rb'
-    - 'app/models/old_relation.rb'
-    - 'app/models/old_way.rb'
-    - 'app/models/user.rb'
-    - 'lib/classic_pagination/pagination.rb'
-
-# Offense count: 97
+# Offense count: 95
 # Cop supports --auto-correct.
 # Configuration parameters: EnforcedStyle, SupportedStyles.
 # SupportedStyles: compact, exploded
 Style/RaiseArgs:
   Enabled: false
-
-# Offense count: 2
-# Cop supports --auto-correct.
-Style/RescueModifier:
-  Exclude:
-    - 'app/helpers/browse_helper.rb'
index ad8f7e599ea42dff4504becf9e0aaa15625a942d..48ddb4a1d09d4e3f1ca0b508c123ee39b0a96b31 100644 (file)
@@ -4,10 +4,10 @@ rvm:
   - 2.3.1
 cache: bundler
 addons:
-  postgresql: 9.1
+  postgresql: 9.5
   apt:
     packages:
-      - postgresql-server-dev-9.1
+      - postgresql-server-dev-9.5
 services:
   - memcached
 env:
@@ -18,9 +18,10 @@ before_script:
   - psql -U postgres -c "CREATE DATABASE openstreetmap"
   - psql -U postgres -c "CREATE EXTENSION btree_gist" openstreetmap
   - make -C db/functions libpgosm.so
-  - psql -U postgres -c "CREATE FUNCTION maptile_for_point(int8, int8, int4) RETURNS int4 AS '${PWD}/db/functions/libpgosm', 'maptile_for_point' LANGUAGE C STRICT" openstreetmap
-  - psql -U postgres -c "CREATE FUNCTION tile_for_point(int4, int4) RETURNS int8 AS '${PWD}/db/functions/libpgosm', 'tile_for_point' LANGUAGE C STRICT" openstreetmap
-  - psql -U postgres -c "CREATE FUNCTION xid_to_int4(xid) RETURNS int4 AS '${PWD}/db/functions/libpgosm', 'xid_to_int4' LANGUAGE C STRICT" openstreetmap
+  - ln db/functions/libpgosm.so /tmp
+  - psql -U postgres -c "CREATE FUNCTION maptile_for_point(int8, int8, int4) RETURNS int4 AS '/tmp/libpgosm', 'maptile_for_point' LANGUAGE C STRICT" openstreetmap
+  - psql -U postgres -c "CREATE FUNCTION tile_for_point(int4, int4) RETURNS int8 AS '/tmp/libpgosm', 'tile_for_point' LANGUAGE C STRICT" openstreetmap
+  - psql -U postgres -c "CREATE FUNCTION xid_to_int4(xid) RETURNS int4 AS '/tmp/libpgosm', 'xid_to_int4' LANGUAGE C STRICT" openstreetmap
   - cp config/travis.database.yml config/database.yml
   - bundle exec rake db:migrate
 script:
index 477e8c63f5f9272b2fb99e27bddeb6478b286168..961377ec83f389625f664b3bf9cc8a01f1dbd14b 100644 (file)
@@ -42,7 +42,8 @@ sudo gem install rcov
 rcov -x gems test/*/*.rb
 ```
 
-The tests are automatically run on commit with the results shown at [http://cruise.openstreetmap.org/](http://cruise.openstreetmap.org/)
+The tests are automatically run on Pull Requests and other commits with the
+results shown on [Travis CI](https://travis-ci.org/openstreetmap/openstreetmap-website).
 
 ## Comments
 
@@ -96,4 +97,3 @@ Otherwise you should either push your changes to a publicly visible git reposito
 and send the details to the [rails-dev](http://lists.openstreetmap.org/listinfo/rails-dev)
 list or generate patches with `git format-patch` and send them to the
 [rails-dev](http://lists.openstreetmap.org/listinfo/rails-dev) list.
-
diff --git a/FAQ.md b/FAQ.md
new file mode 100644 (file)
index 0000000..423ef70
--- /dev/null
+++ b/FAQ.md
@@ -0,0 +1,30 @@
+## How do I create a banner to promote my OpenStreetMap event?
+
+We occasionally display banner images on the main page of [openstreetmap.org](https://www.openstreetmap.org/) to
+promote a large OpenStreetMap focused conference or host a worldwide donation
+drive.  This is a great way to reach a lot of people!
+
+1. Please review [openstreetmap/operations#150](https://github.com/openstreetmap/operations/issues/150) to
+know whether your event qualifies for a front-page banner.
+
+2. Create the banner image.  Some guidelines:
+  * Image should be 350px wide (exactly) x 350px tall (or shorter).
+  * Use a standard web image format (.gif, .jpg, .png)
+  * Note that a close 'X' button will be drawn over the top right 60x60px
+  corner of the banner, so please do not put anything important in that space.
+
+3. Prepare a pull request which includes the following:
+  * The banner should be saved under the
+  [`app/assets/images/banners/`](https://github.com/openstreetmap/openstreetmap-website/tree/master/app/assets/images/banners) folder, and should have a name that makes it clear what it is for (e.g. `donate-2017.jpg`)
+  * Edit [`config/banners.yml`](https://github.com/openstreetmap/openstreetmap-website/blob/master/config/banners.yml)
+  to contain an entry for the event banner.  It should contain the following:
+    * `id` - a unique identifier (e.g. `donate2017`)
+    * `alt` - alt name for the image (e.g. `OpenStreetMap Funding Drive 2017`)
+    * `link` - URL for your event page (e.g. `https://donate.openstreetmap.org/`)
+    * `img` - the filename for the banner image (e.g. `banners/donate-2017.jpg`)
+    * `enddate` - the final date that the banner will be shown (e.g. `2017-oct-31`)
+  * (optional) Feel free to cleanup the old images from the `app/assets/images/banners/`
+  folder and old entries in the `config/banners.yml` file.
+
+See [PR #1296](https://github.com/openstreetmap/openstreetmap-website/pull/1296)
+as an example.
diff --git a/Gemfile b/Gemfile
index 92e0def8fbed9f3cac7c35cfe300e7c0385262d4..43f39340a812d78ad5ad660ffada06872d2a2fc0 100644 (file)
--- a/Gemfile
+++ b/Gemfile
@@ -1,7 +1,7 @@
 source "https://rubygems.org"
 
 # Require rails
-gem "rails", "5.0.5"
+gem "rails", "5.1.4"
 
 # Require things which have moved to gems in ruby 1.9
 gem "bigdecimal", "~> 1.1.0", :platforms => :ruby_19
@@ -32,7 +32,7 @@ gem "jquery-rails"
 gem "jsonify-rails"
 
 # Use R2 for RTL conversion
-gem "r2"
+gem "r2", "~> 0.2.7"
 
 # Use autoprefixer to generate CSS prefixes
 gem "autoprefixer-rails"
@@ -42,12 +42,12 @@ gem "image_optim_rails"
 
 # Load rails plugins
 gem "actionpack-page_caching"
-gem "composite_primary_keys", "~> 9.0.7"
-gem "deadlock_retry", ">= 1.2.0"
+gem "composite_primary_keys", "~> 10.0.0"
 gem "dynamic_form"
 gem "http_accept_language", "~> 2.0.0"
 gem "i18n-js", ">= 3.0.0"
 gem "oauth-plugin", ">= 0.5.1"
+gem "openstreetmap-deadlock_retry", ">= 1.3.0", :require => "deadlock_retry"
 gem "paperclip", "~> 4.0"
 gem "rack-cors"
 gem "rails-i18n", "~> 4.0.0"
@@ -107,6 +107,7 @@ gem "logstasher"
 
 # Gems useful for development
 group :development do
+  gem "annotate"
   gem "listen"
   gem "vendorer"
 end
@@ -122,9 +123,10 @@ end
 
 # Needed in development as well so rake can see konacha tasks
 group :development, :test do
+  gem "capybara", "~> 2.13"
   gem "coveralls", :require => false
-  gem "factory_girl_rails"
+  gem "factory_bot_rails"
   gem "jshint"
-  #  gem "konacha"
   gem "poltergeist"
+  gem "puma", "~> 3.7"
 end
index ce2b4f11483c631b4c7984fb2a5fdb9f09d18f61..d67d34d4723d4a670c57f156350b966e8e0998af 100644 (file)
@@ -3,58 +3,61 @@ GEM
   specs:
     SystemTimer (1.2.3)
     aasm (4.1.0)
-    actioncable (5.0.5)
-      actionpack (= 5.0.5)
-      nio4r (>= 1.2, < 3.0)
+    actioncable (5.1.4)
+      actionpack (= 5.1.4)
+      nio4r (~> 2.0)
       websocket-driver (~> 0.6.1)
-    actionmailer (5.0.5)
-      actionpack (= 5.0.5)
-      actionview (= 5.0.5)
-      activejob (= 5.0.5)
+    actionmailer (5.1.4)
+      actionpack (= 5.1.4)
+      actionview (= 5.1.4)
+      activejob (= 5.1.4)
       mail (~> 2.5, >= 2.5.4)
       rails-dom-testing (~> 2.0)
-    actionpack (5.0.5)
-      actionview (= 5.0.5)
-      activesupport (= 5.0.5)
+    actionpack (5.1.4)
+      actionview (= 5.1.4)
+      activesupport (= 5.1.4)
       rack (~> 2.0)
-      rack-test (~> 0.6.3)
+      rack-test (>= 0.6.3)
       rails-dom-testing (~> 2.0)
       rails-html-sanitizer (~> 1.0, >= 1.0.2)
     actionpack-page_caching (1.1.0)
       actionpack (>= 4.0.0, < 6)
-    actionview (5.0.5)
-      activesupport (= 5.0.5)
+    actionview (5.1.4)
+      activesupport (= 5.1.4)
       builder (~> 3.1)
-      erubis (~> 2.7.0)
+      erubi (~> 1.4)
       rails-dom-testing (~> 2.0)
       rails-html-sanitizer (~> 1.0, >= 1.0.3)
-    activejob (5.0.5)
-      activesupport (= 5.0.5)
+    activejob (5.1.4)
+      activesupport (= 5.1.4)
       globalid (>= 0.3.6)
-    activemodel (5.0.5)
-      activesupport (= 5.0.5)
-    activerecord (5.0.5)
-      activemodel (= 5.0.5)
-      activesupport (= 5.0.5)
-      arel (~> 7.0)
-    activesupport (5.0.5)
+    activemodel (5.1.4)
+      activesupport (= 5.1.4)
+    activerecord (5.1.4)
+      activemodel (= 5.1.4)
+      activesupport (= 5.1.4)
+      arel (~> 8.0)
+    activesupport (5.1.4)
       concurrent-ruby (~> 1.0, >= 1.0.2)
       i18n (~> 0.7)
       minitest (~> 5.1)
       tzinfo (~> 1.1)
-    addressable (2.5.1)
-      public_suffix (~> 2.0, >= 2.0.2)
-    arel (7.1.4)
+    addressable (2.5.2)
+      public_suffix (>= 2.0.2, < 4.0)
+    annotate (2.7.2)
+      activerecord (>= 3.2, < 6.0)
+      rake (>= 10.4, < 13.0)
+    arel (8.0.0)
     ast (2.3.0)
-    autoprefixer-rails (7.1.2.3)
+    autoprefixer-rails (7.1.6)
       execjs
     bigdecimal (1.1.0)
     builder (3.2.3)
     canonical-rails (0.2.1)
       rails (>= 4.1, < 5.2)
-    capybara (2.14.4)
+    capybara (2.15.4)
       addressable
-      mime-types (>= 1.16)
+      mini_mime (>= 0.1.3)
       nokogiri (>= 1.3.3)
       rack (>= 1.0.0)
       rack-test (>= 0.5.4)
@@ -70,8 +73,8 @@ GEM
       coffee-script-source
       execjs
     coffee-script-source (1.12.2)
-    composite_primary_keys (9.0.7)
-      activerecord (~> 5.0.0)
+    composite_primary_keys (10.0.1)
+      activerecord (~> 5.1.0)
     concurrent-ruby (1.0.5)
     coveralls (0.8.21)
       json (>= 1.8, < 3)
@@ -83,30 +86,30 @@ GEM
       safe_yaml (~> 1.0.0)
     crass (1.0.2)
     dalli (2.7.6)
-    deadlock_retry (1.2.0)
     docile (1.1.5)
     dynamic_form (1.1.4)
-    erubis (2.7.0)
+    erubi (1.7.0)
     execjs (2.7.0)
-    exifr (1.3.1)
-    factory_girl (4.8.0)
+    exifr (1.3.2)
+    factory_bot (4.8.2)
       activesupport (>= 3.0.0)
-    factory_girl_rails (4.8.0)
-      factory_girl (~> 4.8.0)
+    factory_bot_rails (4.8.2)
+      factory_bot (~> 4.8.2)
       railties (>= 3.0.0)
     faraday (0.12.2)
       multipart-post (>= 1.2, < 3)
     ffi (1.9.18)
     fspath (3.1.0)
     geoip (1.6.3)
-    globalid (0.4.0)
+    globalid (0.4.1)
       activesupport (>= 4.2.0)
-    hashdiff (0.3.4)
+    hashdiff (0.3.7)
     hashie (3.5.6)
     htmlentities (4.3.4)
     http_accept_language (2.0.5)
-    i18n (0.8.6)
-    i18n-js (3.0.0)
+    i18n (0.9.0)
+      concurrent-ruby (~> 1.0)
+    i18n-js (3.0.2)
       i18n (~> 0.6, >= 0.6.6)
     image_optim (0.25.0)
       exifr (~> 1.2, >= 1.2.2)
@@ -143,20 +146,22 @@ GEM
       rb-inotify (~> 0.9, >= 0.9.7)
       ruby_dep (~> 1.2)
     logstash-event (1.2.02)
-    logstasher (1.2.1)
+    logstasher (1.2.2)
       activesupport (>= 4.0)
       logstash-event (~> 1.2.0)
       request_store
-    loofah (2.0.3)
+    loofah (2.1.1)
+      crass (~> 1.0.2)
       nokogiri (>= 1.5.9)
     mail (2.6.6)
       mime-types (>= 1.16, < 4)
-    method_source (0.8.2)
+    method_source (0.9.0)
     mime-types (3.1)
       mime-types-data (~> 3.2015)
     mime-types-data (3.2016.0521)
     mimemagic (0.3.0)
-    mini_portile2 (2.2.0)
+    mini_mime (0.1.4)
+    mini_portile2 (2.3.0)
     minitest (5.10.3)
     minitest-capybara (0.8.2)
       capybara (~> 2.2)
@@ -172,12 +177,12 @@ GEM
       minitest-capybara (~> 0.8)
       minitest-metadata (~> 0.6)
       minitest-rails (~> 3.0)
-    multi_json (1.12.1)
+    multi_json (1.12.2)
     multi_xml (0.6.0)
     multipart-post (2.0.0)
     nio4r (2.1.0)
-    nokogiri (1.8.0)
-      mini_portile2 (~> 2.2.0)
+    nokogiri (1.8.1)
+      mini_portile2 (~> 2.3.0)
     nokogumbo (1.4.13)
       nokogiri
     oauth (0.4.7)
@@ -192,7 +197,7 @@ GEM
       multi_json (~> 1.3)
       multi_xml (~> 0.5)
       rack (>= 1.2, < 3)
-    omniauth (1.6.1)
+    omniauth (1.7.1)
       hashie (>= 3.4.6, < 3.6.0)
       rack (>= 1.6.2, < 3)
     omniauth-facebook (4.0.0)
@@ -220,6 +225,7 @@ GEM
     omniauth-windowslive (0.0.12)
       multi_json (~> 1.12)
       omniauth-oauth2 (~> 1.4)
+    openstreetmap-deadlock_retry (1.3.0)
     paperclip (4.3.7)
       activemodel (>= 3.2.0)
       activesupport (>= 3.2.0)
@@ -230,34 +236,35 @@ GEM
     parser (2.4.0.0)
       ast (~> 2.2)
     pg (0.21.0)
-    poltergeist (1.15.0)
+    poltergeist (1.16.0)
       capybara (~> 2.1)
       cliver (~> 0.3.1)
       websocket-driver (>= 0.2.0)
     powerpack (0.1.1)
-    progress (3.3.1)
+    progress (3.4.0)
     psych (2.2.4)
-    public_suffix (2.0.5)
+    public_suffix (3.0.0)
+    puma (3.10.0)
     r2 (0.2.7)
     rack (2.0.3)
-    rack-cors (1.0.1)
+    rack-cors (1.0.2)
     rack-openid (1.3.1)
       rack (>= 1.1.0)
       ruby-openid (>= 2.1.8)
-    rack-test (0.6.3)
-      rack (>= 1.0)
+    rack-test (0.7.0)
+      rack (>= 1.0, < 3)
     rack-uri_sanitizer (0.0.2)
-    rails (5.0.5)
-      actioncable (= 5.0.5)
-      actionmailer (= 5.0.5)
-      actionpack (= 5.0.5)
-      actionview (= 5.0.5)
-      activejob (= 5.0.5)
-      activemodel (= 5.0.5)
-      activerecord (= 5.0.5)
-      activesupport (= 5.0.5)
+    rails (5.1.4)
+      actioncable (= 5.1.4)
+      actionmailer (= 5.1.4)
+      actionpack (= 5.1.4)
+      actionview (= 5.1.4)
+      activejob (= 5.1.4)
+      activemodel (= 5.1.4)
+      activerecord (= 5.1.4)
+      activesupport (= 5.1.4)
       bundler (>= 1.3.0)
-      railties (= 5.0.5)
+      railties (= 5.1.4)
       sprockets-rails (>= 2.0.0)
     rails-controller-testing (1.0.2)
       actionpack (~> 5.x, >= 5.0.1)
@@ -271,15 +278,15 @@ GEM
     rails-i18n (4.0.2)
       i18n (~> 0.6)
       rails (>= 4.0)
-    railties (5.0.5)
-      actionpack (= 5.0.5)
-      activesupport (= 5.0.5)
+    railties (5.1.4)
+      actionpack (= 5.1.4)
+      activesupport (= 5.1.4)
       method_source
       rake (>= 0.8.7)
       thor (>= 0.18.1, < 2.0)
     rainbow (2.2.2)
       rake
-    rake (12.0.0)
+    rake (12.2.1)
     rb-fsevent (0.10.2)
     rb-inotify (0.9.10)
       ffi (>= 0.5.0, < 2)
@@ -288,24 +295,24 @@ GEM
     redcarpet (3.4.0)
     ref (2.0.0)
     request_store (1.3.2)
-    rinku (2.0.2)
+    rinku (2.0.3)
     rotp (3.3.0)
-    rubocop (0.49.1)
+    rubocop (0.51.0)
       parallel (~> 1.10)
       parser (>= 2.3.3.1, < 3.0)
       powerpack (~> 0.1)
-      rainbow (>= 1.99.1, < 3.0)
+      rainbow (>= 2.2.2, < 3.0)
       ruby-progressbar (~> 1.7)
       unicode-display_width (~> 1.0, >= 1.0.1)
     ruby-openid (2.7.0)
-    ruby-progressbar (1.8.1)
+    ruby-progressbar (1.9.0)
     ruby_dep (1.5.0)
     safe_yaml (1.0.4)
     sanitize (4.5.0)
       crass (~> 1.0.2)
       nokogiri (>= 1.4.4)
       nokogumbo (~> 1.4.1)
-    sass (3.5.1)
+    sass (3.5.3)
       sass-listen (~> 4.0.0)
     sass-listen (4.0.0)
       rb-fsevent (~> 0.9, >= 0.9.4)
@@ -316,17 +323,17 @@ GEM
       sprockets (>= 2.8, < 4.0)
       sprockets-rails (>= 2.0, < 4.0)
       tilt (>= 1.1, < 3)
-    secure_headers (3.6.7)
-      useragent
+    secure_headers (5.0.1)
+      useragent (>= 0.15.0)
     simplecov (0.14.1)
       docile (~> 1.1.0)
       json (>= 1.8, < 3)
       simplecov-html (~> 0.10.0)
-    simplecov-html (0.10.1)
+    simplecov-html (0.10.2)
     sprockets (3.7.1)
       concurrent-ruby (~> 1.0)
       rack (> 1, < 3)
-    sprockets-rails (3.2.0)
+    sprockets-rails (3.2.1)
       actionpack (>= 4.0)
       activesupport (>= 4.0)
       sprockets (>= 3.0.0)
@@ -339,7 +346,7 @@ GEM
     thread_safe (0.3.6)
     tilt (2.0.8)
     tins (1.15.0)
-    tzinfo (1.2.3)
+    tzinfo (1.2.4)
       thread_safe (~> 0.1)
     uglifier (3.2.0)
       execjs (>= 0.3.0, < 3)
@@ -348,7 +355,7 @@ GEM
     validates_email_format_of (1.6.3)
       i18n
     vendorer (0.1.16)
-    webmock (3.0.1)
+    webmock (3.1.0)
       addressable (>= 2.3.6)
       crack (>= 0.3.2)
       hashdiff
@@ -365,16 +372,17 @@ DEPENDENCIES
   SystemTimer (>= 1.1.3)
   aasm
   actionpack-page_caching
+  annotate
   autoprefixer-rails
   bigdecimal (~> 1.1.0)
   canonical-rails
+  capybara (~> 2.13)
   coffee-rails (~> 4.2)
-  composite_primary_keys (~> 9.0.7)
+  composite_primary_keys (~> 10.0.0)
   coveralls
   dalli
-  deadlock_retry (>= 1.2.0)
   dynamic_form
-  factory_girl_rails
+  factory_bot_rails
   faraday
   geoip
   htmlentities
@@ -399,14 +407,16 @@ DEPENDENCIES
   omniauth-mediawiki (>= 0.0.3)
   omniauth-openid
   omniauth-windowslive
+  openstreetmap-deadlock_retry (>= 1.3.0)
   paperclip (~> 4.0)
   pg
   poltergeist
   psych
-  r2
+  puma (~> 3.7)
+  r2 (~> 0.2.7)
   rack-cors
   rack-uri_sanitizer
-  rails (= 5.0.5)
+  rails (= 5.1.4)
   rails-controller-testing
   rails-i18n (~> 4.0.0)
   record_tag_helper
@@ -423,4 +433,4 @@ DEPENDENCIES
   webmock
 
 BUNDLED WITH
-   1.13.7
+   1.15.4
index 5b909454f0f4b538f118d0b0d335cbdc6ac12fa5..6b929fef9f48e7e9be810c2576d7eb6ef47eaa38 100644 (file)
--- a/README.md
+++ b/README.md
@@ -40,3 +40,8 @@ We're always keen to have more developers! Pull requests are very welcome.
 * IRC - there is the #osm-dev channel on irc.oftc.net.
 
 More details on contributing to the code are in the [CONTRIBUTING.md](CONTRIBUTING.md) file.
+
+# Maintainers
+
+* Tom Hughes [@tomhughes](https://github.com/tomhughes/)
+* Andy Allan [@gravitystorm](https://github.com/gravitystorm/)
index 8c9898dd92be803cf182edc8411e6708c93983ed..d66dd80d8077afcbaf3f04aa394a6f767cbdf6ac 100644 (file)
@@ -11,13 +11,13 @@ folder 'vendor/assets' do
   end
 
   folder 'leaflet' do
-    file 'leaflet.js', 'https://unpkg.com/leaflet@1.1.0/dist/leaflet-src.js'
-    file 'leaflet.css', 'https://unpkg.com/leaflet@1.1.0/dist/leaflet.css'
+    file 'leaflet.js', 'https://unpkg.com/leaflet@1.2.0/dist/leaflet-src.js'
+    file 'leaflet.css', 'https://unpkg.com/leaflet@1.2.0/dist/leaflet.css'
 
     [ 'layers.png', 'layers-2x.png',
       'marker-icon.png', 'marker-icon-2x.png',
       'marker-shadow.png' ].each do |image|
-      file "images/#{image}", "https://unpkg.com/leaflet@1.1.0/dist/images/#{image}"
+      file "images/#{image}", "https://unpkg.com/leaflet@1.2.0/dist/images/#{image}"
     end
 
     from 'git://github.com/aratcliffe/Leaflet.contextmenu.git', :tag => 'v1.2.1' do
diff --git a/app/assets/images/banners/banner-sotm-2017.png b/app/assets/images/banners/banner-sotm-2017.png
deleted file mode 100644 (file)
index a861d1f..0000000
Binary files a/app/assets/images/banners/banner-sotm-2017.png and /dev/null differ
diff --git a/app/assets/images/banners/banner-sotmus2017.png b/app/assets/images/banners/banner-sotmus2017.png
new file mode 100644 (file)
index 0000000..25382bf
Binary files /dev/null and b/app/assets/images/banners/banner-sotmus2017.png differ
diff --git a/app/assets/images/banners/osmf-membership-drive-2017.png b/app/assets/images/banners/osmf-membership-drive-2017.png
new file mode 100644 (file)
index 0000000..0b62b21
Binary files /dev/null and b/app/assets/images/banners/osmf-membership-drive-2017.png differ
diff --git a/app/assets/images/banners/sotmasia-2017-banner.png b/app/assets/images/banners/sotmasia-2017-banner.png
new file mode 100644 (file)
index 0000000..f18f5bf
Binary files /dev/null and b/app/assets/images/banners/sotmasia-2017-banner.png differ
index 7d5b99f601e54ef8eacd9882c766a4305be356eb..4461c5ab71cc950e43a0c5ae5ac82003e0874840 100644 (file)
@@ -1,4 +1,4 @@
-//= require jquery
+//= require jquery3
 //= require jquery_ujs
 //= require jquery.timers
 //= require jquery.cookie
@@ -79,18 +79,6 @@ $(document).ready(function () {
   var headerWidth = 0,
       compactWidth = 0;
 
-  $("header").children(":visible").each(function (i,e) {
-    headerWidth = headerWidth + $(e).outerWidth();
-  });
-
-  $("body").addClass("compact");
-
-  $("header").children(":visible").each(function (i,e) {
-    compactWidth = compactWidth + $(e).outerWidth();
-  });
-
-  $("body").removeClass("compact");
-
   function updateHeader() {
     var windowWidth = $(window).width();
 
@@ -103,9 +91,29 @@ $(document).ready(function () {
     }
   }
 
-  updateHeader();
+  /*
+   * Chrome 60 and later seem to fire the "ready" callback
+   * before the DOM is fully ready causing us to measure the
+   * wrong sizes for the header elements - use a 0ms timeout
+   * to defer the measurement slightly as a workaround.
+   */
+  setTimeout(function () {
+    $("header").children(":visible").each(function (i,e) {
+      headerWidth = headerWidth + $(e).outerWidth();
+    });
+
+    $("body").addClass("compact");
+
+    $("header").children(":visible").each(function (i,e) {
+      compactWidth = compactWidth + $(e).outerWidth();
+    });
+
+    $("body").removeClass("compact");
+
+    updateHeader();
 
-  $(window).resize(updateHeader);
+    $(window).resize(updateHeader);
+  }, 0);
 
   $("#menu-icon").on("click", function(e) {
     e.preventDefault();
index 6b902587ec58bfb619b59ec9eb4613b109955f2e..9831171831db58a071d6f55fcfffcf97cc025be9 100644 (file)
@@ -20,6 +20,8 @@ $(document).ready(function () {
 
     if (hashParams.background) params.background = hashParams.background;
     if (hashParams.comment) params.comment = hashParams.comment;
+    if (hashParams.disable_features) params.disable_features = hashParams.disable_features;
+    if (hashParams.hashtags) params.hashtags = hashParams.hashtags;
     if (hashParams.offset) params.offset = hashParams.offset;
     if (hashParams.walkthrough) params.walkthrough = hashParams.walkthrough;
 
index b30564a1ae64b12ee3c7a98aff01b1c131da8c26..00e6a9d32a0d815b05676e0428540fc6a82ac16a 100644 (file)
@@ -114,6 +114,7 @@ $(document).ready(function () {
     .removeClass('leaflet-control-locate leaflet-bar')
     .addClass('control-locate')
     .children("a")
+    .attr('href', '#')
     .removeClass('leaflet-bar-part leaflet-bar-part-single')
     .addClass('control-button');
 
index 148ccf908441b99cc23a62da95e81c21c55484df..1ee703e604579d01444a880ec12d7e5f26dcc9be 100644 (file)
@@ -8,7 +8,8 @@ OSM.initializeContextMenu = function (map) {
           lng = latlng.lng.toFixed(precision);
 
       OSM.router.route("/directions?" + querystring.stringify({
-        route: lat + "," + lng + ";" + $("#route_to").val()
+        from: lat + "," + lng,
+        to: $("#route_to").val()
       }));
     }
   });
@@ -22,7 +23,8 @@ OSM.initializeContextMenu = function (map) {
           lng = latlng.lng.toFixed(precision);
 
       OSM.router.route("/directions?" + querystring.stringify({
-        route: $("#route_from").val() + ";" + lat + "," + lng
+        from: $("#route_from").val(),
+        to: lat + "," + lng
       }));
     }
   });
index 018aedf98a01df4c5bc3a4996611b9596edbd386..7ac613d71ec1737e2d80088ad5f3c0e29d177868 100644 (file)
@@ -146,7 +146,7 @@ OSM.Query = function(map) {
 
     if (feature.type === "node" && feature.lat && feature.lon) {
       geometry = L.circleMarker([feature.lat, feature.lon], featureStyle);
-    } else if (feature.type === "way" && feature.geometry) {
+    } else if (feature.type === "way" && feature.geometry && feature.geometry.length > 0) {
       geometry = L.polyline(feature.geometry.filter(function (point) {
         return point !== null;
       }).map(function (point) {
index eedf718d3a262ceb332f99d9dd89a87f264f918e..a465e144993d8470a82c31f740fb09b273d8f5b2 100644 (file)
@@ -49,7 +49,7 @@ L.OSM.layers = function(options) {
         .appendTo(item);
 
       map.whenReady(function() {
-        var miniMap = L.map(div[0], {attributionControl: false, zoomControl: false})
+        var miniMap = L.map(div[0], {attributionControl: false, zoomControl: false, keyboard: false})
           .addLayer(new layer.constructor({ apikey: layer.options.apikey }));
 
         miniMap.dragging.disable();
index 44872a78c6f12c2432df5fa40f268406b0109c30..bdf0443056329df566e07fbc880dd8ea3153b79c 100644 (file)
@@ -28,6 +28,7 @@ $(document).ready(function () {
       .removeClass('leaflet-control-locate leaflet-bar')
       .addClass('control-locate')
       .children("a")
+      .attr('href', '#')
       .removeClass('leaflet-bar-part leaflet-bar-part-single')
       .addClass('control-button');
 
@@ -84,6 +85,10 @@ $(document).ready(function () {
 
   $("select#user_auth_provider").on("change", updateAuthUID);
 
+  $("input#user_image").on("change", function () {
+    $("#image_action_new").prop("checked", true);
+  });
+
   function enableAuth() {
     $("#auth_prompt").hide();
     $("#auth_field").show();
index 6755b7e560f5d4bc0ef0e94b414d630ee17d1822..4e89c04c9b6d1924b301338f1f253fd4cab0eb2d 100644 (file)
@@ -1664,6 +1664,10 @@ tr.turn:hover {
   display: inline;
 }
 
+.pagination {
+  padding-top: $lineheight;
+}
+
 /* Rules for the diary entry page */
 
 .diary_entry {
@@ -2776,12 +2780,30 @@ input.richtext_title[type="text"] {
     vertical-align: middle;
     background: 40px 40px image-url('about/sprite.png') no-repeat;
 
-    &.local        { background-position: 0px    0px; }
-    &.community    { background-position: 0px  -40px; }
-    &.open         { background-position: 0px  -80px; }
-    &.partners     { background-position: 0px -120px; }
-    &.infringement { background-position: 0px -160px; }
-    &.legal        { background-position: -45px -160px; }
+    &.local {
+      /* no-r2 */
+      background-position: 0px 0px;
+    }
+    &.community {
+      /* no-r2 */
+      background-position: 0px -40px;
+    }
+    &.open {
+      /* no-r2 */
+      background-position: 0px -80px;
+    }
+    &.partners {
+      /* no-r2 */
+      background-position: 0px -120px;
+    }
+    &.infringement {
+      /* no-r2 */
+      background-position: 0px -160px;
+    }
+    &.legal {
+      /* no-r2 */
+      background-position: -45px -160px;
+    }
   }
 }
 
index 51db8296df7312f6701236fcb81ce9b94f871380..5181280d9410eff5c9b2eb6fe06a7fefd5b2f98f 100644 (file)
@@ -151,7 +151,7 @@ class AmfController < ApplicationController
         cs = Changeset.find(closeid.to_i)
         cs.set_closed_time_now
         if cs.user_id != user.id
-          raise OSM::APIUserChangesetMismatchError.new
+          raise OSM::APIUserChangesetMismatchError
         elsif closecomment.empty?
           cs.save!
         else
@@ -186,7 +186,7 @@ class AmfController < ApplicationController
   # Return presets (default tags, localisation etc.):
   # uses POTLATCH_PRESETS global, set up in OSM::Potlatch.
 
-  def getpresets(usertoken, lang) #:doc:
+  def getpresets(usertoken, _lang)
     user = getuser(usertoken)
 
     langs = if user && !user.languages.empty?
@@ -229,7 +229,7 @@ class AmfController < ApplicationController
       begin
         other = YAML.safe_load(File.open(Rails.root.join("config", "potlatch", "locales", "#{lang}.yml")))[lang]
         loaded_lang = lang
-      rescue
+      rescue StandardError
         other = en
       end
 
@@ -253,7 +253,7 @@ class AmfController < ApplicationController
   # nodes in the bbox, nodes are any visible nodes in the bbox but not
   # used in any way, rel is any relation which refers to either a way
   # or node that we're returning.
-  def whichways(xmin, ymin, xmax, ymax) #:doc:
+  def whichways(xmin, ymin, xmax, ymax)
     amf_handle_error_with_timeout("'whichways'", nil, nil) do
       enlarge = [(xmax - xmin) / 8, 0.01].min
       xmin -= enlarge
@@ -297,7 +297,7 @@ class AmfController < ApplicationController
   # Find deleted ways in current bounding box (similar to whichways, but ways
   # with a deleted node only - not POIs or relations).
 
-  def whichways_deleted(xmin, ymin, xmax, ymax) #:doc:
+  def whichways_deleted(xmin, ymin, xmax, ymax)
     amf_handle_error_with_timeout("'whichways_deleted'", nil, nil) do
       enlarge = [(xmax - xmin) / 8, 0.01].min
       xmin -= enlarge
@@ -321,7 +321,7 @@ class AmfController < ApplicationController
   # Get a way including nodes and tags.
   # Returns the way id, a Potlatch-style array of points, a hash of tags, the version number, and the user ID.
 
-  def getway(wayid) #:doc:
+  def getway(wayid)
     amf_handle_error_with_timeout("'getway' #{wayid}", "way", wayid) do
       if POTLATCH_USE_SQL
         points = sql_get_nodes_in_way(wayid)
@@ -366,7 +366,7 @@ class AmfController < ApplicationController
   # 4. version,
   # 5. is this the current, visible version? (boolean)
 
-  def getway_old(id, timestamp) #:doc:
+  def getway_old(id, timestamp)
     amf_handle_error_with_timeout("'getway_old' #{id}, #{timestamp}", "way", id) do
       if timestamp == ""
         # undelete
@@ -375,7 +375,7 @@ class AmfController < ApplicationController
       else
         begin
           # revert
-          timestamp = DateTime.strptime(timestamp.to_s, "%d %b %Y, %H:%M:%S")
+          timestamp = Time.strptime(timestamp.to_s, "%d %b %Y, %H:%M:%S")
           old_way = OldWay.where("way_id = ? AND timestamp <= ?", id, timestamp).unredacted.order("timestamp DESC").first
           unless old_way.nil?
             if old_way.visible
@@ -411,7 +411,7 @@ class AmfController < ApplicationController
   # sort and collapse list (to within 2 seconds); trim all dates before the
   # start date of the way.
 
-  def getway_history(wayid) #:doc:
+  def getway_history(wayid)
     revdates = []
     revusers = {}
     Way.find(wayid).old_ways.unredacted.collect do |a|
@@ -444,7 +444,7 @@ class AmfController < ApplicationController
 
   # Find history of a node. Returns 'node', id, and an array of previous versions as above.
 
-  def getnode_history(nodeid) #:doc:
+  def getnode_history(nodeid)
     history = Node.find(nodeid).old_nodes.unredacted.reverse.collect do |old_node|
       [(old_node.timestamp + 1).strftime("%d %b %Y, %H:%M:%S")] + change_user(old_node)
     end
@@ -492,7 +492,7 @@ class AmfController < ApplicationController
   # 4. list of members,
   # 5. version.
 
-  def getrelation(relid) #:doc:
+  def getrelation(relid)
     amf_handle_error("'getrelation' #{relid}", "relation", relid) do
       rel = Relation.where(:id => relid).first
 
@@ -528,7 +528,7 @@ class AmfController < ApplicationController
   # 2. new relation id,
   # 3. version.
 
-  def putrelation(renumberednodes, renumberedways, usertoken, changeset_id, version, relid, tags, members, visible) #:doc:
+  def putrelation(renumberednodes, renumberedways, usertoken, changeset_id, version, relid, tags, members, visible)
     amf_handle_error("'putrelation' #{relid}", "relation", relid) do
       user = getuser(usertoken)
 
@@ -582,7 +582,7 @@ class AmfController < ApplicationController
           new_relation.id = relid
           relation.delete_with_history!(new_relation, user)
         end
-      end # transaction
+      end
 
       if relid <= 0
         return [0, "", relid, new_relation.id, new_relation.version]
@@ -616,7 +616,7 @@ class AmfController < ApplicationController
   # 6. hash of changed node versions (node=>version)
   # 7. hash of deleted node versions (node=>version)
 
-  def putway(renumberednodes, usertoken, changeset_id, wayversion, originalway, pointlist, attributes, nodes, deletednodes) #:doc:
+  def putway(renumberednodes, usertoken, changeset_id, wayversion, originalway, pointlist, attributes, nodes, deletednodes)
     amf_handle_error("'putway' #{originalway}", "way", originalway) do
       # -- Initialise
 
@@ -679,7 +679,7 @@ class AmfController < ApplicationController
 
         pointlist.collect! do |a|
           renumberednodes[a] ? renumberednodes[a] : a
-        end # renumber nodes
+        end
         new_way = Way.new
         new_way.tags = attributes
         new_way.nds = pointlist
@@ -711,7 +711,7 @@ class AmfController < ApplicationController
             # and we don't want to delete it
           end
         end
-      end # transaction
+      end
 
       [0, "", originalway, way.id, renumberednodes, way.version, nodeversions, deletednodes]
     end
@@ -726,7 +726,7 @@ class AmfController < ApplicationController
   # 3. new node id,
   # 4. version.
 
-  def putpoi(usertoken, changeset_id, version, id, lon, lat, tags, visible) #:doc:
+  def putpoi(usertoken, changeset_id, version, id, lon, lat, tags, visible)
     amf_handle_error("'putpoi' #{id}", "node", id) do
       user = getuser(usertoken)
       return -1, "You are not logged in, so the point could not be saved." unless user
@@ -772,7 +772,7 @@ class AmfController < ApplicationController
           new_node.id = id
           node.delete_with_history!(new_node, user)
         end
-      end # transaction
+      end
 
       if id <= 0
         return [0, "", id, new_node.id, new_node.version]
@@ -787,7 +787,7 @@ class AmfController < ApplicationController
   #
   # Returns array of id, long, lat, hash of tags, (current) version.
 
-  def getpoi(id, timestamp) #:doc:
+  def getpoi(id, timestamp)
     amf_handle_error("'getpoi' #{id}", "node", id) do
       id = id.to_i
       n = Node.where(:id => id).first
@@ -816,7 +816,7 @@ class AmfController < ApplicationController
   # of the nodes have been changed by someone else then, there is a problem!
   # Returns 0 (success), unchanged way id, new way version, new node versions.
 
-  def deleteway(usertoken, changeset_id, way_id, way_version, deletednodes) #:doc:
+  def deleteway(usertoken, changeset_id, way_id, way_version, deletednodes)
     amf_handle_error("'deleteway' #{way_id}", "way", way_id) do
       user = getuser(usertoken)
       return -1, "You are not logged in, so the way could not be deleted." unless user
@@ -853,7 +853,7 @@ class AmfController < ApplicationController
             # elsewhere and we don't want to delete it
           end
         end
-      end # transaction
+      end
       [0, "", way_id, old_way.version, nodeversions]
     end
   end
@@ -866,7 +866,7 @@ class AmfController < ApplicationController
   # When we are writing to the api, we need the actual user model,
   # not just the id, hence this abstraction
 
-  def getuser(token) #:doc:
+  def getuser(token)
     if token =~ /^(.+)\:(.+)$/
       User.authenticate(:username => Regexp.last_match(1), :password => Regexp.last_match(2))
     else
@@ -907,7 +907,7 @@ class AmfController < ApplicationController
   # Alternative SQL queries for getway/whichways
 
   def sql_find_ways_in_area(bbox)
-    sql = <<-EOF
+    sql = <<-SQL
     SELECT DISTINCT current_ways.id AS wayid,current_ways.version AS version
       FROM current_way_nodes
     INNER JOIN current_nodes ON current_nodes.id=current_way_nodes.node_id
@@ -915,20 +915,20 @@ class AmfController < ApplicationController
        WHERE current_nodes.visible=TRUE
        AND current_ways.visible=TRUE
        AND #{OSM.sql_for_area(bbox, 'current_nodes.')}
-    EOF
+    SQL
     ActiveRecord::Base.connection.select_all(sql).collect { |a| [a["wayid"].to_i, a["version"].to_i] }
   end
 
   def sql_find_pois_in_area(bbox)
     pois = []
-    sql = <<-EOF
+    sql = <<-SQL
       SELECT current_nodes.id,current_nodes.latitude*0.0000001 AS lat,current_nodes.longitude*0.0000001 AS lon,current_nodes.version
       FROM current_nodes
        LEFT OUTER JOIN current_way_nodes cwn ON cwn.node_id=current_nodes.id
        WHERE current_nodes.visible=TRUE
        AND cwn.id IS NULL
        AND #{OSM.sql_for_area(bbox, 'current_nodes.')}
-    EOF
+    SQL
     ActiveRecord::Base.connection.select_all(sql).each do |row|
       poitags = {}
       ActiveRecord::Base.connection.select_all("SELECT k,v FROM current_node_tags WHERE id=#{row['id']}").each do |n|
@@ -942,36 +942,36 @@ class AmfController < ApplicationController
   def sql_find_relations_in_area_and_ways(bbox, way_ids)
     # ** It would be more Potlatchy to get relations for nodes within ways
     #    during 'getway', not here
-    sql = <<-EOF
+    sql = <<-SQL
       SELECT DISTINCT cr.id AS relid,cr.version AS version
       FROM current_relations cr
       INNER JOIN current_relation_members crm ON crm.id=cr.id
       INNER JOIN current_nodes cn ON crm.member_id=cn.id AND crm.member_type='Node'
        WHERE #{OSM.sql_for_area(bbox, 'cn.')}
-      EOF
+      SQL
     unless way_ids.empty?
-      sql += <<-EOF
+      sql += <<-SQL
        UNION
         SELECT DISTINCT cr.id AS relid,cr.version AS version
         FROM current_relations cr
         INNER JOIN current_relation_members crm ON crm.id=cr.id
          WHERE crm.member_type='Way'
          AND crm.member_id IN (#{way_ids.join(',')})
-        EOF
+        SQL
     end
     ActiveRecord::Base.connection.select_all(sql).collect { |a| [a["relid"].to_i, a["version"].to_i] }
   end
 
   def sql_get_nodes_in_way(wayid)
     points = []
-    sql = <<-EOF
+    sql = <<-SQL
       SELECT latitude*0.0000001 AS lat,longitude*0.0000001 AS lon,current_nodes.id,current_nodes.version
       FROM current_way_nodes,current_nodes
        WHERE current_way_nodes.id=#{wayid.to_i}
        AND current_way_nodes.node_id=current_nodes.id
        AND current_nodes.visible=TRUE
       ORDER BY sequence_id
-    EOF
+    SQL
     ActiveRecord::Base.connection.select_all(sql).each do |row|
       nodetags = {}
       ActiveRecord::Base.connection.select_all("SELECT k,v FROM current_node_tags WHERE id=#{row['id']}").each do |n|
index 9324a8ed56a4c4eb2351123a0c7d677ce56fd894..c6cc3ba5f46cbaf71412b7e414e3f48a0363e2b8 100644 (file)
@@ -193,7 +193,7 @@ class ApiController < ApplicationController
     # this "uniq" may be slightly inefficient; it may be better to first collect and output
     # all node-related relations, then find the *not yet covered* way-related ones etc.
     relations.uniq.each do |relation|
-      doc.root << relation.to_xml_node(nil, changeset_cache, user_display_name_cache)
+      doc.root << relation.to_xml_node(changeset_cache, user_display_name_cache)
     end
 
     response.headers["Content-Disposition"] = "attachment; filename=\"map.osm\""
index 68fc4338ee7a90d66b28d280faeee3be9bd90208..db5d086ecbf088c06c7e4f850299329ee8be1068 100644 (file)
@@ -346,7 +346,7 @@ class ApplicationController < ActionController::Base
   # or raises a suitable error. +method+ should be a symbol, e.g: :put or :get.
   def assert_method(method)
     ok = request.send((method.to_s.downcase + "?").to_sym)
-    raise OSM::APIBadMethodError.new(method) unless ok
+    raise OSM::APIBadMethodError, method unless ok
   end
 
   ##
@@ -366,7 +366,7 @@ class ApplicationController < ActionController::Base
       yield
     end
   rescue ActionView::Template::Error => ex
-    ex = ex.original_exception
+    ex = ex.cause
 
     if ex.is_a?(Timeout::Error) ||
        (ex.is_a?(ActiveRecord::StatementInvalid) && ex.message =~ /execution expired/)
@@ -413,7 +413,9 @@ class ApplicationController < ActionController::Base
 
   def map_layout
     append_content_security_policy_directives(
+      :child_src => %w[127.0.0.1:8111 127.0.0.1:8112],
       :connect_src => %w[nominatim.openstreetmap.org overpass-api.de router.project-osrm.org valhalla.mapzen.com],
+      :form_action => %w[render.openstreetmap.org],
       :script_src => %w[graphhopper.com open.mapquestapi.com],
       :img_src => %w[developer.mapquest.com]
     )
@@ -427,6 +429,10 @@ class ApplicationController < ActionController::Base
     request.xhr? ? "xhr" : "map"
   end
 
+  def allow_thirdparty_images
+    append_content_security_policy_directives(:img_src => %w[*])
+  end
+
   def preferred_editor
     editor = if params[:editor]
                params[:editor]
index 1c658ccbd61290c35284e4cb152a73de3ff852db..898afae4a30de945a7d5e338c0b4c93b8c8643b1 100644 (file)
@@ -28,7 +28,7 @@ class ChangesetController < ApplicationController
     cs = Changeset.from_xml(request.raw_post, true)
 
     # Assume that Changeset.from_xml has thrown an exception if there is an error parsing the xml
-    cs.user_id = current_user.id
+    cs.user = current_user
     cs.save_with_tags!
 
     # Subscribe user to changeset comments
@@ -310,8 +310,8 @@ class ChangesetController < ApplicationController
   # Add a comment to a changeset
   def comment
     # Check the arguments are sane
-    raise OSM::APIBadUserInput.new("No id was given") unless params[:id]
-    raise OSM::APIBadUserInput.new("No text was given") if params[:text].blank?
+    raise OSM::APIBadUserInput, "No id was given" unless params[:id]
+    raise OSM::APIBadUserInput, "No text was given" if params[:text].blank?
 
     # Extract the arguments
     id = params[:id].to_i
@@ -319,7 +319,7 @@ class ChangesetController < ApplicationController
 
     # Find the changeset and check it is valid
     changeset = Changeset.find(id)
-    raise OSM::APIChangesetNotYetClosedError.new(changeset) if changeset.is_open?
+    raise OSM::APIChangesetNotYetClosedError, changeset if changeset.is_open?
 
     # Add a comment to the changeset
     comment = changeset.comments.create(:changeset => changeset,
@@ -344,15 +344,15 @@ class ChangesetController < ApplicationController
   # Adds a subscriber to the changeset
   def subscribe
     # Check the arguments are sane
-    raise OSM::APIBadUserInput.new("No id was given") unless params[:id]
+    raise OSM::APIBadUserInput, "No id was given" unless params[:id]
 
     # Extract the arguments
     id = params[:id].to_i
 
     # Find the changeset and check it is valid
     changeset = Changeset.find(id)
-    raise OSM::APIChangesetNotYetClosedError.new(changeset) if changeset.is_open?
-    raise OSM::APIChangesetAlreadySubscribedError.new(changeset) if changeset.subscribers.exists?(current_user.id)
+    raise OSM::APIChangesetNotYetClosedError, changeset if changeset.is_open?
+    raise OSM::APIChangesetAlreadySubscribedError, changeset if changeset.subscribers.exists?(current_user.id)
 
     # Add the subscriber
     changeset.subscribers << current_user
@@ -365,15 +365,15 @@ class ChangesetController < ApplicationController
   # Removes a subscriber from the changeset
   def unsubscribe
     # Check the arguments are sane
-    raise OSM::APIBadUserInput.new("No id was given") unless params[:id]
+    raise OSM::APIBadUserInput, "No id was given" unless params[:id]
 
     # Extract the arguments
     id = params[:id].to_i
 
     # Find the changeset and check it is valid
     changeset = Changeset.find(id)
-    raise OSM::APIChangesetNotYetClosedError.new(changeset) if changeset.is_open?
-    raise OSM::APIChangesetNotSubscribedError.new(changeset) unless changeset.subscribers.exists?(current_user.id)
+    raise OSM::APIChangesetNotYetClosedError, changeset if changeset.is_open?
+    raise OSM::APIChangesetNotSubscribedError, changeset unless changeset.subscribers.exists?(current_user.id)
 
     # Remove the subscriber
     changeset.subscribers.delete(current_user)
@@ -386,7 +386,7 @@ class ChangesetController < ApplicationController
   # Sets visible flag on comment to false
   def hide_comment
     # Check the arguments are sane
-    raise OSM::APIBadUserInput.new("No id was given") unless params[:id]
+    raise OSM::APIBadUserInput, "No id was given" unless params[:id]
 
     # Extract the arguments
     id = params[:id].to_i
@@ -405,7 +405,7 @@ class ChangesetController < ApplicationController
   # Sets visible flag on comment to true
   def unhide_comment
     # Check the arguments are sane
-    raise OSM::APIBadUserInput.new("No id was given") unless params[:id]
+    raise OSM::APIBadUserInput, "No id was given" unless params[:id]
 
     # Extract the arguments
     id = params[:id].to_i
@@ -434,7 +434,7 @@ class ChangesetController < ApplicationController
       @comments = changeset.comments.includes(:author, :changeset).limit(comments_limit)
     else
       # Return comments
-      @comments = ChangesetComment.includes(:author, :changeset).where(:visible => :true).order("created_at DESC").limit(comments_limit).preload(:changeset)
+      @comments = ChangesetComment.includes(:author, :changeset).where(:visible => true).order("created_at DESC").limit(comments_limit).preload(:changeset)
     end
 
     # Render the result
@@ -475,19 +475,19 @@ class ChangesetController < ApplicationController
       changesets
     else
       # shouldn't provide both name and UID
-      raise OSM::APIBadUserInput.new("provide either the user ID or display name, but not both") if user && name
+      raise OSM::APIBadUserInput, "provide either the user ID or display name, but not both" if user && name
 
       # use either the name or the UID to find the user which we're selecting on.
       u = if name.nil?
             # user input checking, we don't have any UIDs < 1
-            raise OSM::APIBadUserInput.new("invalid user ID") if user.to_i < 1
+            raise OSM::APIBadUserInput, "invalid user ID" if user.to_i < 1
             u = User.find(user.to_i)
           else
             u = User.find_by(:display_name => name)
           end
 
       # make sure we found a user
-      raise OSM::APINotFoundError.new if u.nil?
+      raise OSM::APINotFoundError if u.nil?
 
       # should be able to get changesets of public users only, or
       # our own changesets regardless of public-ness.
@@ -496,7 +496,7 @@ class ChangesetController < ApplicationController
         # changesets if they're non-public
         setup_user_auth
 
-        raise OSM::APINotFoundError if current_user.nil? || current_user.id != u.id
+        raise OSM::APINotFoundError if current_user.nil? || current_user != u
       end
 
       changesets.where(:user_id => u.id)
@@ -514,20 +514,20 @@ class ChangesetController < ApplicationController
 
       # check that we actually have 2 elements in the array
       times = time.split(/,/)
-      raise OSM::APIBadUserInput.new("bad time range") if times.size != 2
+      raise OSM::APIBadUserInput, "bad time range" if times.size != 2
 
-      from, to = times.collect { |t| DateTime.parse(t) }
+      from, to = times.collect { |t| Time.parse(t) }
       return changesets.where("closed_at >= ? and created_at <= ?", from, to)
     else
       # if there is no comma, assume its a lower limit on time
-      return changesets.where("closed_at >= ?", DateTime.parse(time))
+      return changesets.where("closed_at >= ?", Time.parse(time))
     end
-    # stupid DateTime seems to throw both of these for bad parsing, so
+    # stupid Time seems to throw both of these for bad parsing, so
     # we have to catch both and ensure the correct code path is taken.
   rescue ArgumentError => ex
-    raise OSM::APIBadUserInput.new(ex.message.to_s)
+    raise OSM::APIBadUserInput, ex.message.to_s
   rescue RuntimeError => ex
-    raise OSM::APIBadUserInput.new(ex.message.to_s)
+    raise OSM::APIBadUserInput, ex.message.to_s
   end
 
   ##
@@ -563,7 +563,7 @@ class ChangesetController < ApplicationController
     if ids.nil?
       changesets
     elsif ids.empty?
-      raise OSM::APIBadUserInput.new("No changesets were given to search for")
+      raise OSM::APIBadUserInput, "No changesets were given to search for"
     else
       ids = ids.split(",").collect(&:to_i)
       changesets.where(:id => ids)
@@ -584,7 +584,7 @@ class ChangesetController < ApplicationController
       if params[:limit].to_i > 0 && params[:limit].to_i <= 10000
         params[:limit].to_i
       else
-        raise OSM::APIBadUserInput.new("Comments limit must be between 1 and 10000")
+        raise OSM::APIBadUserInput, "Comments limit must be between 1 and 10000"
       end
     else
       100
index 1b57fa59b19f4b6948385ff4d06461fa702c94a5..88febbe2fe96c520a75dcf04696121be5a627fba 100644 (file)
@@ -8,6 +8,7 @@ class DiaryEntryController < ApplicationController
   before_action :check_database_readable
   before_action :check_database_writable, :only => [:new, :edit, :comment, :hide, :hidecomment, :subscribe, :unsubscribe]
   before_action :require_administrator, :only => [:hide, :hidecomment]
+  before_action :allow_thirdparty_images, :only => [:new, :edit, :list, :view, :comments]
 
   def new
     @title = t "diary_entry.new.title"
index 6ec2d46f8ac2db2e752909ff92fe8db49d710b42..6110baead8b0086042a5b3fbf926b80e0396ab90 100644 (file)
@@ -1,5 +1,3 @@
-# coding: utf-8
-
 class GeocoderController < ApplicationController
   require "cgi"
   require "uri"
@@ -19,7 +17,6 @@ class GeocoderController < ApplicationController
       @sources.push "geonames_reverse" if defined?(GEONAMES_USERNAME)
     elsif @params[:query]
       if @params[:query] =~ /^\d{5}(-\d{4})?$/
-        @sources.push "us_postcode"
         @sources.push "osm_nominatim"
       elsif @params[:query] =~ /^(GIR 0AA|[A-PR-UWYZ]([0-9]{1,2}|([A-HK-Y][0-9]|[A-HK-Y][0-9]([0-9]|[ABEHMNPRV-Y]))|[0-9][A-HJKS-UW])\s*[0-9][ABD-HJLNP-UW-Z]{2})$/i
         @sources.push "uk_postcode"
@@ -58,31 +55,6 @@ class GeocoderController < ApplicationController
     end
   end
 
-  def search_us_postcode
-    # get query parameters
-    query = params[:query]
-
-    # create result array
-    @results = []
-
-    # ask geocoder.us (they have a non-commercial use api)
-    response = fetch_text("http://rpc.geocoder.us/service/csv?zip=#{escape_query(query)}")
-
-    # parse the response
-    unless response =~ /couldn't find this zip/
-      data = response.split(/\s*,\s+/) # lat,long,town,state,zip
-      @results.push(:lat => data[0], :lon => data[1],
-                    :zoom => POSTCODE_ZOOM,
-                    :prefix => "#{data[2]}, #{data[3]},",
-                    :name => data[4])
-    end
-
-    render :action => "results"
-  rescue StandardError => ex
-    @error = "Error contacting rpc.geocoder.us: #{ex}"
-    render :action => "error"
-  end
-
   def search_uk_postcode
     # get query parameters
     query = params[:query]
@@ -313,7 +285,7 @@ class GeocoderController < ApplicationController
   end
 
   def escape_query(query)
-    URI.escape(query, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]", false, "N"))
+    CGI.escape(query)
   end
 
   def normalize_params
@@ -348,7 +320,7 @@ class GeocoderController < ApplicationController
       Float(captures[0])
       lat = !captures[2].casecmp("s").zero? ? captures[0].to_f : -captures[0].to_f
       lon = !captures[5].casecmp("w").zero? ? captures[3].to_f : -captures[3].to_f
-    rescue
+    rescue StandardError
       lat = !captures[0].casecmp("s").zero? ? captures[1].to_f : -captures[1].to_f
       lon = !captures[3].casecmp("w").zero? ? captures[4].to_f : -captures[4].to_f
     end
@@ -360,7 +332,7 @@ class GeocoderController < ApplicationController
       Float(captures[0])
       lat = !captures[3].casecmp("s").zero? ? captures[0].to_f + captures[1].to_f / 60 : -(captures[0].to_f + captures[1].to_f / 60)
       lon = !captures[7].casecmp("w").zero? ? captures[4].to_f + captures[5].to_f / 60 : -(captures[4].to_f + captures[5].to_f / 60)
-    rescue
+    rescue StandardError
       lat = !captures[0].casecmp("s").zero? ? captures[1].to_f + captures[2].to_f / 60 : -(captures[1].to_f + captures[2].to_f / 60)
       lon = !captures[4].casecmp("w").zero? ? captures[5].to_f + captures[6].to_f / 60 : -(captures[5].to_f + captures[6].to_f / 60)
     end
@@ -372,7 +344,7 @@ class GeocoderController < ApplicationController
       Float(captures[0])
       lat = !captures[4].casecmp("s").zero? ? captures[0].to_f + (captures[1].to_f + captures[2].to_f / 60) / 60 : -(captures[0].to_f + (captures[1].to_f + captures[2].to_f / 60) / 60)
       lon = !captures[9].casecmp("w").zero? ? captures[5].to_f + (captures[6].to_f + captures[7].to_f / 60) / 60 : -(captures[5].to_f + (captures[6].to_f + captures[7].to_f / 60) / 60)
-    rescue
+    rescue StandardError
       lat = !captures[0].casecmp("s").zero? ? captures[1].to_f + (captures[2].to_f + captures[3].to_f / 60) / 60 : -(captures[1].to_f + (captures[2].to_f + captures[3].to_f / 60) / 60)
       lon = !captures[5].casecmp("w").zero? ? captures[6].to_f + (captures[7].to_f + captures[8].to_f / 60) / 60 : -(captures[6].to_f + (captures[7].to_f + captures[8].to_f / 60) / 60)
     end
index 9b39f1c0588152d814d7104576697bd37f7f7da0..3952b67ca47e1ae40a0b15ff593054e8f146c73e 100644 (file)
@@ -7,6 +7,7 @@ class MessageController < ApplicationController
   before_action :lookup_this_user, :only => [:new]
   before_action :check_database_readable
   before_action :check_database_writable, :only => [:new, :reply, :mark]
+  before_action :allow_thirdparty_images, :only => [:new, :read]
 
   # Allow the user to write a new message to another user. This action also
   # deals with the sending of that message to the other user when the user
@@ -18,8 +19,8 @@ class MessageController < ApplicationController
         flash[:error] = t "message.new.limit_exceeded"
       else
         @message = Message.new(message_params)
-        @message.to_user_id = @this_user.id
-        @message.from_user_id = current_user.id
+        @message.recipient = @this_user
+        @message.sender = current_user
         @message.sent_on = Time.now.getutc
 
         if @message.save
@@ -38,7 +39,7 @@ class MessageController < ApplicationController
   def reply
     message = Message.find(params[:message_id])
 
-    if message.to_user_id == current_user.id
+    if message.recipient == current_user
       message.update(:message_read => true)
 
       @message = Message.new(
@@ -64,8 +65,8 @@ class MessageController < ApplicationController
     @title = t "message.read.title"
     @message = Message.find(params[:message_id])
 
-    if @message.to_user_id == current_user.id || @message.from_user_id == current_user.id
-      @message.message_read = true if @message.to_user_id == current_user.id
+    if @message.recipient == current_user || @message.sender == current_user
+      @message.message_read = true if @message.recipient == current_user
       @message.save
     else
       flash[:notice] = t "message.read.wrong_user", :user => current_user.display_name
index 3eb127cb149fda5095238c741c276d322fbf52fe..29651bceb5dc5d13e97260904ccdef3f9f8b31be 100644 (file)
@@ -41,7 +41,7 @@ class NodeController < ApplicationController
     new_node = Node.from_xml(request.raw_post)
 
     unless new_node && new_node.id == node.id
-      raise OSM::APIBadUserInput.new("The id in the url (#{node.id}) is not the same as provided in the xml (#{new_node.id})")
+      raise OSM::APIBadUserInput, "The id in the url (#{node.id}) is not the same as provided in the xml (#{new_node.id})"
     end
 
     node.update_from(new_node, current_user)
@@ -56,7 +56,7 @@ class NodeController < ApplicationController
     new_node = Node.from_xml(request.raw_post)
 
     unless new_node && new_node.id == node.id
-      raise OSM::APIBadUserInput.new("The id in the url (#{node.id}) is not the same as provided in the xml (#{new_node.id})")
+      raise OSM::APIBadUserInput, "The id in the url (#{node.id}) is not the same as provided in the xml (#{new_node.id})"
     end
     node.delete_with_history!(new_node, current_user)
     render :plain => node.version.to_s
@@ -65,13 +65,13 @@ class NodeController < ApplicationController
   # Dump the details on many nodes whose ids are given in the "nodes" parameter.
   def nodes
     unless params["nodes"]
-      raise OSM::APIBadUserInput.new("The parameter nodes is required, and must be of the form nodes=id[,id[,id...]]")
+      raise OSM::APIBadUserInput, "The parameter nodes is required, and must be of the form nodes=id[,id[,id...]]"
     end
 
     ids = params["nodes"].split(",").collect(&:to_i)
 
     if ids.empty?
-      raise OSM::APIBadUserInput.new("No nodes were given to search for")
+      raise OSM::APIBadUserInput, "No nodes were given to search for"
     end
     doc = OSM::API.new.get_xml_doc
 
index f577dc2f28198580c72944fcb231d12861f54772..92f63e304f76c539b009cdbbfff4d593e8236447 100644 (file)
@@ -20,10 +20,10 @@ class NotesController < ApplicationController
     if params[:bbox]
       bbox = BoundingBox.from_bbox_params(params)
     else
-      raise OSM::APIBadUserInput.new("No l was given") unless params[:l]
-      raise OSM::APIBadUserInput.new("No r was given") unless params[:r]
-      raise OSM::APIBadUserInput.new("No b was given") unless params[:b]
-      raise OSM::APIBadUserInput.new("No t was given") unless params[:t]
+      raise OSM::APIBadUserInput, "No l was given" unless params[:l]
+      raise OSM::APIBadUserInput, "No r was given" unless params[:r]
+      raise OSM::APIBadUserInput, "No b was given" unless params[:b]
+      raise OSM::APIBadUserInput, "No t was given" unless params[:t]
 
       bbox = BoundingBox.from_lrbt_params(params)
     end
@@ -56,9 +56,9 @@ class NotesController < ApplicationController
     raise OSM::APIAccessDenied if Acl.no_note_comment(request.remote_ip)
 
     # Check the arguments are sane
-    raise OSM::APIBadUserInput.new("No lat was given") unless params[:lat]
-    raise OSM::APIBadUserInput.new("No lon was given") unless params[:lon]
-    raise OSM::APIBadUserInput.new("No text was given") if params[:text].blank?
+    raise OSM::APIBadUserInput, "No lat was given" unless params[:lat]
+    raise OSM::APIBadUserInput, "No lon was given" unless params[:lon]
+    raise OSM::APIBadUserInput, "No text was given" if params[:text].blank?
 
     # Extract the arguments
     lon = OSM.parse_float(params[:lon], OSM::APIBadUserInput, "lon was not a number")
@@ -69,7 +69,7 @@ class NotesController < ApplicationController
     Note.transaction do
       # Create the note
       @note = Note.create(:lat => lat, :lon => lon)
-      raise OSM::APIBadUserInput.new("The note is outside this world") unless @note.in_world?
+      raise OSM::APIBadUserInput, "The note is outside this world" unless @note.in_world?
 
       # Save the note
       @note.save!
@@ -92,8 +92,8 @@ class NotesController < ApplicationController
     raise OSM::APIAccessDenied if Acl.no_note_comment(request.remote_ip)
 
     # Check the arguments are sane
-    raise OSM::APIBadUserInput.new("No id was given") unless params[:id]
-    raise OSM::APIBadUserInput.new("No text was given") if params[:text].blank?
+    raise OSM::APIBadUserInput, "No id was given" unless params[:id]
+    raise OSM::APIBadUserInput, "No text was given" if params[:text].blank?
 
     # Extract the arguments
     id = params[:id].to_i
@@ -103,7 +103,7 @@ class NotesController < ApplicationController
     @note = Note.find(id)
     raise OSM::APINotFoundError unless @note
     raise OSM::APIAlreadyDeletedError.new("note", @note.id) unless @note.visible?
-    raise OSM::APINoteAlreadyClosedError.new(@note) if @note.closed?
+    raise OSM::APINoteAlreadyClosedError, @note if @note.closed?
 
     # Add a comment to the note
     Note.transaction do
@@ -121,7 +121,7 @@ class NotesController < ApplicationController
   # Close a note
   def close
     # Check the arguments are sane
-    raise OSM::APIBadUserInput.new("No id was given") unless params[:id]
+    raise OSM::APIBadUserInput, "No id was given" unless params[:id]
 
     # Extract the arguments
     id = params[:id].to_i
@@ -131,7 +131,7 @@ class NotesController < ApplicationController
     @note = Note.find_by(:id => id)
     raise OSM::APINotFoundError unless @note
     raise OSM::APIAlreadyDeletedError.new("note", @note.id) unless @note.visible?
-    raise OSM::APINoteAlreadyClosedError.new(@note) if @note.closed?
+    raise OSM::APINoteAlreadyClosedError, @note if @note.closed?
 
     # Close the note and add a comment
     Note.transaction do
@@ -151,7 +151,7 @@ class NotesController < ApplicationController
   # Reopen a note
   def reopen
     # Check the arguments are sane
-    raise OSM::APIBadUserInput.new("No id was given") unless params[:id]
+    raise OSM::APIBadUserInput, "No id was given" unless params[:id]
 
     # Extract the arguments
     id = params[:id].to_i
@@ -161,7 +161,7 @@ class NotesController < ApplicationController
     @note = Note.find_by(:id => id)
     raise OSM::APINotFoundError unless @note
     raise OSM::APIAlreadyDeletedError.new("note", @note.id) unless @note.visible? || current_user.moderator?
-    raise OSM::APINoteAlreadyOpenError.new(@note) unless @note.closed? || !@note.visible?
+    raise OSM::APINoteAlreadyOpenError, @note unless @note.closed? || !@note.visible?
 
     # Reopen the note and add a comment
     Note.transaction do
@@ -206,7 +206,7 @@ class NotesController < ApplicationController
   # Read a note
   def show
     # Check the arguments are sane
-    raise OSM::APIBadUserInput.new("No id was given") unless params[:id]
+    raise OSM::APIBadUserInput, "No id was given" unless params[:id]
 
     # Find the note and check it is valid
     @note = Note.find(params[:id])
@@ -226,7 +226,7 @@ class NotesController < ApplicationController
   # Delete (hide) a note
   def destroy
     # Check the arguments are sane
-    raise OSM::APIBadUserInput.new("No id was given") unless params[:id]
+    raise OSM::APIBadUserInput, "No id was given" unless params[:id]
 
     # Extract the arguments
     id = params[:id].to_i
@@ -256,7 +256,7 @@ class NotesController < ApplicationController
   # Return a list of notes matching a given string
   def search
     # Check the arguments are sane
-    raise OSM::APIBadUserInput.new("No query string was given") unless params[:q]
+    raise OSM::APIBadUserInput, "No query string was given" unless params[:q]
 
     # Get any conditions that need to be applied
     @notes = closed_condition(Note.all)
@@ -310,7 +310,7 @@ class NotesController < ApplicationController
       if params[:limit].to_i > 0 && params[:limit].to_i <= 10000
         params[:limit].to_i
       else
-        raise OSM::APIBadUserInput.new("Note limit must be between 1 and 10000")
+        raise OSM::APIBadUserInput, "Note limit must be between 1 and 10000"
       end
     else
       100
index 4bb129ba442c16bf4df6cd1758a866f4f04dcdc6..734783a35eef61f4df429abfee6b1aa2fd9facf8 100644 (file)
@@ -38,6 +38,8 @@ class OauthController < ApplicationController
   protected
 
   def oauth1_authorize
+    append_content_security_policy_directives(:form_action => %w[*])
+
     if @token.invalidated?
       @message = t "oauth.oauthorize_failure.invalid"
       render :action => "authorize_failure"
index 3815f5ae05fe231f079384cf7b27dc7a0922b30f..9adf141d959f4a319ec39c64a97826a573faf49b 100644 (file)
@@ -19,7 +19,7 @@ class OldController < ApplicationController
     # the .where() method used in the lookup_old_element_versions
     # call won't throw an error if no records are found, so we have
     # to do that ourselves.
-    raise OSM::APINotFoundError.new if @elements.empty?
+    raise OSM::APINotFoundError if @elements.empty?
 
     doc = OSM::API.new.get_xml_doc
 
index 97e83204939c7061f68dd8d877d1cda294fa4283..25532a95c72c0dc965f0ddeb1757099a7755773f 100644 (file)
@@ -36,7 +36,7 @@ class RelationController < ApplicationController
     new_relation = Relation.from_xml(request.raw_post)
 
     unless new_relation && new_relation.id == relation.id
-      raise OSM::APIBadUserInput.new("The id in the url (#{relation.id}) is not the same as provided in the xml (#{new_relation.id})")
+      raise OSM::APIBadUserInput, "The id in the url (#{relation.id}) is not the same as provided in the xml (#{new_relation.id})"
     end
 
     relation.update_from new_relation, current_user
@@ -91,7 +91,6 @@ class RelationController < ApplicationController
       # create XML.
       doc = OSM::API.new.get_xml_doc
       visible_nodes = {}
-      visible_members = { "Node" => {}, "Way" => {}, "Relation" => {} }
       changeset_cache = {}
       user_display_name_cache = {}
 
@@ -100,25 +99,22 @@ class RelationController < ApplicationController
 
         doc.root << node.to_xml_node(changeset_cache, user_display_name_cache)
         visible_nodes[node.id] = node
-        visible_members["Node"][node.id] = true
       end
 
       ways.each do |way|
         next unless way.visible? # should be unnecessary if data is consistent.
 
         doc.root << way.to_xml_node(visible_nodes, changeset_cache, user_display_name_cache)
-        visible_members["Way"][way.id] = true
       end
 
       relations.each do |rel|
         next unless rel.visible? # should be unnecessary if data is consistent.
 
-        doc.root << rel.to_xml_node(nil, changeset_cache, user_display_name_cache)
-        visible_members["Relation"][rel.id] = true
+        doc.root << rel.to_xml_node(changeset_cache, user_display_name_cache)
       end
 
       # finally add self and output
-      doc.root << relation.to_xml_node(visible_members, changeset_cache, user_display_name_cache)
+      doc.root << relation.to_xml_node(changeset_cache, user_display_name_cache)
       render :xml => doc.to_s
 
     else
@@ -128,13 +124,13 @@ class RelationController < ApplicationController
 
   def relations
     unless params["relations"]
-      raise OSM::APIBadUserInput.new("The parameter relations is required, and must be of the form relations=id[,id[,id...]]")
+      raise OSM::APIBadUserInput, "The parameter relations is required, and must be of the form relations=id[,id[,id...]]"
     end
 
     ids = params["relations"].split(",").collect(&:to_i)
 
     if ids.empty?
-      raise OSM::APIBadUserInput.new("No relations were given to search for")
+      raise OSM::APIBadUserInput, "No relations were given to search for"
     end
 
     doc = OSM::API.new.get_xml_doc
index 4b8b2f402509655cb8efd5ed046fa54bc50ba324..0d40b6691ab4e69e6fac431004d61a9327522e64 100644 (file)
@@ -91,7 +91,7 @@ class SearchController < ApplicationController
     end
 
     relations.each do |rel|
-      doc.root << rel.to_xml_node(nil, changeset_cache, user_display_name_cache)
+      doc.root << rel.to_xml_node(changeset_cache, user_display_name_cache)
     end
 
     render :xml => doc.to_s
index c727f86d9a55ab5084da81ce8ad637040024e500..74dbc41f553c2a652661b762f68190dc1a92bc7c 100644 (file)
@@ -120,9 +120,9 @@ class SiteController < ApplicationController
 
   def id
     append_content_security_policy_directives(
-      :connect_src => %w[taginfo.openstreetmap.org *.mapillary.com],
-      :img_src => %w[*],
-      :script_src => %w[dev.virtualearth.net]
+      :connect_src => %w[*],
+      :img_src => %w[* blob:],
+      :script_src => %w[dev.virtualearth.net 'unsafe-eval']
     )
 
     render "id", :layout => false
index eaeb4f5d0686de96901a87023c3eb6a817a6a639..105405ccfdad7e0fd11b525443a4786ed496f307 100644 (file)
@@ -112,7 +112,7 @@ class TraceController < ApplicationController
         begin
           do_create(params[:trace][:gpx_file], params[:trace][:tagstring],
                     params[:trace][:description], params[:trace][:visibility])
-        rescue => ex
+        rescue StandardError => ex
           logger.debug ex
         end
 
@@ -149,9 +149,9 @@ class TraceController < ApplicationController
       if Acl.no_trace_download(request.remote_ip)
         head :forbidden
       elsif request.format == Mime[:xml]
-        send_file(trace.xml_file, :filename => "#{trace.id}.xml", :type => request.format.to_s, :disposition => "attachment")
+        send_data(trace.xml_file.read, :filename => "#{trace.id}.xml", :type => request.format.to_s, :disposition => "attachment")
       elsif request.format == Mime[:gpx]
-        send_file(trace.xml_file, :filename => "#{trace.id}.gpx", :type => request.format.to_s, :disposition => "attachment")
+        send_data(trace.xml_file.read, :filename => "#{trace.id}.gpx", :type => request.format.to_s, :disposition => "attachment")
       else
         send_file(trace.trace_name, :filename => "#{trace.id}#{trace.extension_name}", :type => trace.mime_type, :disposition => "attachment")
       end
@@ -263,15 +263,7 @@ class TraceController < ApplicationController
     trace = Trace.visible.find(params[:id])
 
     if trace.user == current_user
-      new_trace = Trace.from_xml(request.raw_post)
-
-      unless new_trace && new_trace.id == trace.id
-        raise OSM::APIBadUserInput.new("The id in the url (#{trace.id}) is not the same as provided in the xml (#{new_trace.id})")
-      end
-
-      trace.description = new_trace.description
-      trace.tags = new_trace.tags
-      trace.visibility = new_trace.visibility
+      trace.update_from_xml(request.raw_post)
       trace.save!
 
       head :ok
@@ -298,9 +290,9 @@ class TraceController < ApplicationController
 
     if trace.public? || trace.user == current_user
       if request.format == Mime[:xml]
-        send_file(trace.xml_file, :filename => "#{trace.id}.xml", :type => request.format.to_s, :disposition => "attachment")
+        send_data(trace.xml_file.read, :filename => "#{trace.id}.xml", :type => request.format.to_s, :disposition => "attachment")
       elsif request.format == Mime[:gpx]
-        send_file(trace.xml_file, :filename => "#{trace.id}.gpx", :type => request.format.to_s, :disposition => "attachment")
+        send_data(trace.xml_file.read, :filename => "#{trace.id}.gpx", :type => request.format.to_s, :disposition => "attachment")
       else
         send_file(trace.trace_name, :filename => "#{trace.id}#{trace.extension_name}", :type => trace.mime_type, :disposition => "attachment")
       end
index 45cd537288d424bfbc627a084c4526c09b18640b..d5820568e45c8b1094a0137729d78ecb19a825d5 100644 (file)
@@ -20,7 +20,7 @@ class UserBlocksController < ApplicationController
   end
 
   def show
-    if current_user && current_user.id == @user_block.user_id
+    if current_user && current_user == @user_block.user
       @user_block.needs_view = false
       @user_block.save!
     end
@@ -37,8 +37,8 @@ class UserBlocksController < ApplicationController
   def create
     if @valid_params
       @user_block = UserBlock.new(
-        :user_id => @this_user.id,
-        :creator_id => current_user.id,
+        :user => @this_user,
+        :creator => current_user,
         :reason => params[:user_block][:reason],
         :ends_at => Time.now.getutc + @block_period.hours,
         :needs_view => params[:user_block][:needs_view]
@@ -57,7 +57,7 @@ class UserBlocksController < ApplicationController
 
   def update
     if @valid_params
-      if @user_block.creator_id != current_user.id
+      if @user_block.creator != current_user
         flash[:error] = t("user_block.update.only_creator_can_edit")
         redirect_to :action => "edit"
       elsif @user_block.update_attributes(
index d3ed53c1bc040353d52d8b23884bf6decf13cd31..5c41a79dc84da7f336d7ed0152094571c0e0fe8a 100644 (file)
@@ -18,6 +18,7 @@ class UserController < ApplicationController
   around_action :api_call_handle_error, :only => [:api_read, :api_details, :api_gpx_files]
   before_action :lookup_user_by_id, :only => [:api_read]
   before_action :lookup_user_by_name, :only => [:set_status, :delete]
+  before_action :allow_thirdparty_images, :only => [:view, :account]
 
   def terms
     @legale = params[:legale] || OSM.ip_to_country(request.remote_ip) || DEFAULT_LEGALE
@@ -99,7 +100,7 @@ class UserController < ApplicationController
                                        "lat" => m[2],
                                        "lon" => m[3] }.merge(editor))
             end
-          rescue
+          rescue StandardError
             # Use default
           end
 
@@ -202,6 +203,10 @@ class UserController < ApplicationController
     @title = t "user.new.title"
     @referer = params[:referer] || session[:referer]
 
+    append_content_security_policy_directives(
+      :form_action => %w[accounts.google.com *.facebook.com login.live.com github.com meta.wikimedia.org]
+    )
+
     if current_user
       # The user is logged in already, so don't show them the signup
       # page, instead send them to the home page
@@ -411,8 +416,8 @@ class UserController < ApplicationController
     if @new_friend
       if request.post?
         friend = Friend.new
-        friend.user_id = current_user.id
-        friend.friend_user_id = @new_friend.id
+        friend.befriender = current_user
+        friend.befriendee = @new_friend
         if current_user.is_friends_with?(@new_friend)
           flash[:warning] = t "user.make_friend.already_a_friend", :name => @new_friend.display_name
         elsif friend.save
@@ -723,7 +728,7 @@ class UserController < ApplicationController
 
           begin
             Notifier.email_confirm(user, user.tokens.create).deliver_now
-          rescue
+          rescue StandardError
             # Ignore errors sending email
           end
         else
index 4b556aed011741dc0e4f952c7136ee29aaa973a1..16165513aefa217b11b1ac80520a89882de5d465 100644 (file)
@@ -45,7 +45,7 @@ class UserPreferenceController < ApplicationController
       if preference = old_preferences.delete(pt["k"])
         preference.v = pt["v"]
       elsif new_preferences.include?(pt["k"])
-        raise OSM::APIDuplicatePreferenceError.new(pt["k"])
+        raise OSM::APIDuplicatePreferenceError, pt["k"]
       else
         preference = current_user.preferences.build(:k => pt["k"], :v => pt["v"])
       end
index 2f5b5a84c6219cf537a63d880293128b765e6299..536790dc5b36f9e924b971d3cd9c66ed46248558 100644 (file)
@@ -10,7 +10,7 @@ class UserRolesController < ApplicationController
   before_action :in_role, :only => [:revoke]
 
   def grant
-    @this_user.roles.create(:role => @role, :granter_id => current_user.id)
+    @this_user.roles.create(:role => @role, :granter => current_user)
     redirect_to :controller => "user", :action => "view", :display_name => @this_user.display_name
   end
 
index 8e9e00b884bcfc04bf7b2f7937cbfd09367c9b76..e48073e10063073cfb72a28756d074efa0407403 100644 (file)
@@ -36,7 +36,7 @@ class WayController < ApplicationController
     new_way = Way.from_xml(request.raw_post)
 
     unless new_way && new_way.id == way.id
-      raise OSM::APIBadUserInput.new("The id in the url (#{way.id}) is not the same as provided in the xml (#{new_way.id})")
+      raise OSM::APIBadUserInput, "The id in the url (#{way.id}) is not the same as provided in the xml (#{new_way.id})"
     end
 
     way.update_from(new_way, current_user)
@@ -81,14 +81,12 @@ class WayController < ApplicationController
 
   def ways
     unless params["ways"]
-      raise OSM::APIBadUserInput.new("The parameter ways is required, and must be of the form ways=id[,id[,id...]]")
+      raise OSM::APIBadUserInput, "The parameter ways is required, and must be of the form ways=id[,id[,id...]]"
     end
 
     ids = params["ways"].split(",").collect(&:to_i)
 
-    if ids.empty?
-      raise OSM::APIBadUserInput.new("No ways were given to search for")
-    end
+    raise OSM::APIBadUserInput, "No ways were given to search for" if ids.empty?
 
     doc = OSM::API.new.get_xml_doc
 
index d27b47f275f815397cd7315d578bc9c960e51d9d..a330eb5f97d47a19d98d874d3681384219e82d54 100644 (file)
@@ -3,9 +3,9 @@ module ApplicationHelper
 
   def linkify(text)
     if text.html_safe?
-      Rinku.auto_link(text, :urls, tag_options(:rel => "nofollow")).html_safe
+      Rinku.auto_link(text, :urls, tag_builder.tag_options(:rel => "nofollow")).html_safe
     else
-      Rinku.auto_link(text, :urls, tag_options(:rel => "nofollow"))
+      Rinku.auto_link(text, :urls, tag_builder.tag_options(:rel => "nofollow"))
     end
   end
 
index 4e888173b34ca0e127ff4574239413d9a6b26792..661369454fb065b024985df35b347d0fb09c2f55 100644 (file)
@@ -4,7 +4,7 @@ module BannerHelper
       enddate = v[:enddate]
       begin
         parsed = enddate && Date.parse(enddate)
-      rescue
+      rescue StandardError
         parsed = nil
       end
       !parsed.is_a?(Date) || (parsed.is_a?(Date) && parsed.past?)
index 998ea405fca1f80018ec07a2c294dc2d37076346..c4ce41b064df9550fb0113ec9b628a4120f74189 100644 (file)
@@ -1,4 +1,4 @@
-require "uri"
+require "cgi"
 
 module BrowseHelper
   def printable_name(object, version = false)
@@ -114,9 +114,9 @@ module BrowseHelper
     # the correct page.
     lookup_us = lookup.tr(" ", "_")
 
-    if page = WIKI_PAGES[locale][type][lookup_us] rescue nil
+    if page = WIKI_PAGES.dig(locale, type, lookup_us)
       url = "http://wiki.openstreetmap.org/wiki/#{page}?uselang=#{locale}"
-    elsif page = WIKI_PAGES["en"][type][lookup_us] rescue nil
+    elsif page = WIKI_PAGES.dig("en", type, lookup_us)
       url = "http://wiki.openstreetmap.org/wiki/#{page}?uselang=#{locale}"
     end
 
@@ -151,7 +151,7 @@ module BrowseHelper
       # Must break it up to correctly build the url
       value = Regexp.last_match(1)
       section = "#" + Regexp.last_match(2)
-      encoded_section = "#" + URI.encode(Regexp.last_match(2).gsub(/ +/, "_"), /[^A-Za-z0-9:_]/).tr("%", ".")
+      encoded_section = "#" + CGI.escape(Regexp.last_match(2).gsub(/ +/, "_")).tr("%", ".")
     else
       section = ""
       encoded_section = ""
index cc008aab758ff568ba970a19e55b03e78cebdc3f..7eb389023ba54a9cfc373dda4ee6f7a39ea51215 100644 (file)
@@ -10,7 +10,7 @@ module ChangesetHelper
   end
 
   def changeset_details(changeset)
-    if changeset.closed_at > DateTime.now
+    if changeset.closed_at > Time.now
       action = :created
       time = distance_of_time_in_words_to_now(changeset.created_at)
       title = l(changeset.created_at)
index ab7e230cbec768a7745192934bc5d7ebb40965b1..11cfe50306ee4d1e4fe1b08ea647735e6b565379 100644 (file)
@@ -2,7 +2,7 @@ module OpenGraphHelper
   def opengraph_tags(title = nil)
     tags = {
       "og:site_name" => t("layouts.project_name.title"),
-      "og:title" => [t("layouts.project_name.title"), title].compact.join(" | "),
+      "og:title" => [title, t("layouts.project_name.title")].compact.join(" | "),
       "og:type" => "website",
       "og:image" => image_url("osm_logo_256.png", :protocol => "http"),
       "og:image:secure_url" => image_url("osm_logo_256.png", :protocol => "https"),
index 8b1eb53b6dfdcae08ea8291a4c2d393ed1b7bad0..88a5a2a74ae3a42a6970fdd94239d11d9efcf9c9 100644 (file)
@@ -8,10 +8,10 @@ module TitleHelper
   def set_title(title = nil)
     if title
       @title = TitleHelper.coder.decode(title.gsub("<bdi>", "\u202a").gsub("</bdi>", "\u202c"))
-      response.headers["X-Page-Title"] = URI.escape(t("layouts.project_name.title") + " | " + @title)
+      response.headers["X-Page-Title"] = ERB::Util.u(@title + " | " + t("layouts.project_name.title"))
     else
       @title = title
-      response.headers["X-Page-Title"] = URI.escape(t("layouts.project_name.title"))
+      response.headers["X-Page-Title"] = ERB::Util.u(t("layouts.project_name.title"))
     end
   end
 end
index f690c97542472dfa4fdbc54b5826e5dea4cf2d37..e5ba2e240916cce272059fa4abd316501ed785ac 100644 (file)
@@ -1,3 +1,40 @@
+# == Schema Information
+#
+# Table name: oauth_tokens
+#
+#  id                    :integer          not null, primary key
+#  user_id               :integer
+#  type                  :string(20)
+#  client_application_id :integer
+#  token                 :string(50)
+#  secret                :string(50)
+#  authorized_at         :datetime
+#  invalidated_at        :datetime
+#  created_at            :datetime
+#  updated_at            :datetime
+#  allow_read_prefs      :boolean          default(FALSE), not null
+#  allow_write_prefs     :boolean          default(FALSE), not null
+#  allow_write_diary     :boolean          default(FALSE), not null
+#  allow_write_api       :boolean          default(FALSE), not null
+#  allow_read_gpx        :boolean          default(FALSE), not null
+#  allow_write_gpx       :boolean          default(FALSE), not null
+#  callback_url          :string
+#  verifier              :string(20)
+#  scope                 :string
+#  valid_to              :datetime
+#  allow_write_notes     :boolean          default(FALSE), not null
+#
+# Indexes
+#
+#  index_oauth_tokens_on_token    (token) UNIQUE
+#  index_oauth_tokens_on_user_id  (user_id)
+#
+# Foreign Keys
+#
+#  oauth_tokens_client_application_id_fkey  (client_application_id => client_applications.id)
+#  oauth_tokens_user_id_fkey                (user_id => users.id)
+#
+
 class AccessToken < OauthToken
   belongs_to :user
   belongs_to :client_application
index 529ccbe3bc26640dfb057674aca5b433ec1582d3..095bad89b942d07e62ee74b18e999100905c456b 100644 (file)
@@ -1,3 +1,18 @@
+# == Schema Information
+#
+# Table name: acls
+#
+#  id      :integer          not null, primary key
+#  address :inet
+#  k       :string           not null
+#  v       :string
+#  domain  :string
+#
+# Indexes
+#
+#  acls_k_idx  (k)
+#
+
 class Acl < ActiveRecord::Base
   validates :k, :presence => true
 
index f41ad99551f96ed3c8b5bba53c285231ba30ddef..37d26e0a7bf82e1bb911382c82d9be174fa29e47 100644 (file)
@@ -1,3 +1,30 @@
+# == Schema Information
+#
+# Table name: changesets
+#
+#  id          :integer          not null, primary key
+#  user_id     :integer          not null
+#  created_at  :datetime         not null
+#  min_lat     :integer
+#  max_lat     :integer
+#  min_lon     :integer
+#  max_lon     :integer
+#  closed_at   :datetime         not null
+#  num_changes :integer          default(0), not null
+#
+# Indexes
+#
+#  changesets_bbox_idx                (min_lat,max_lat,min_lon,max_lon)
+#  changesets_closed_at_idx           (closed_at)
+#  changesets_created_at_idx          (created_at)
+#  changesets_user_id_created_at_idx  (user_id,created_at)
+#  changesets_user_id_id_idx          (user_id,id)
+#
+# Foreign Keys
+#
+#  changesets_user_id_fkey  (user_id => users.id)
+#
+
 class Changeset < ActiveRecord::Base
   require "xml/libxml"
 
@@ -133,7 +160,7 @@ class Changeset < ActiveRecord::Base
   attr_writer :tags
 
   def add_tag_keyval(k, v)
-    @tags = {} unless @tags
+    @tags ||= {}
 
     # duplicate tags are now forbidden, so we can't allow values
     # in the hash to be overwritten.
@@ -241,10 +268,10 @@ class Changeset < ActiveRecord::Base
   # bounding box, only the tags of the changeset.
   def update_from(other, user)
     # ensure that only the user who opened the changeset may modify it.
-    raise OSM::APIUserChangesetMismatchError.new unless user.id == user_id
+    raise OSM::APIUserChangesetMismatchError unless user.id == user_id
 
     # can't change a closed changeset
-    raise OSM::APIChangesetAlreadyClosedError.new(self) unless is_open?
+    raise OSM::APIChangesetAlreadyClosedError, self unless is_open?
 
     # copy the other's tags
     self.tags = other.tags
index 2fedadff04129e72e0d5eaee741309246c485d28..756fda14c6e7b85adb198d89ddf002316ce9d740 100644 (file)
@@ -1,3 +1,24 @@
+# == Schema Information
+#
+# Table name: changeset_comments
+#
+#  id           :integer          not null, primary key
+#  changeset_id :integer          not null
+#  author_id    :integer          not null
+#  body         :text             not null
+#  created_at   :datetime         not null
+#  visible      :boolean          not null
+#
+# Indexes
+#
+#  index_changeset_comments_on_created_at  (created_at)
+#
+# Foreign Keys
+#
+#  changeset_comments_author_id_fkey     (author_id => users.id)
+#  changeset_comments_changeset_id_fkey  (changeset_id => changesets.id)
+#
+
 class ChangesetComment < ActiveRecord::Base
   belongs_to :changeset
   belongs_to :author, :class_name => "User"
index 7ffba0dc3350c0348c094d4b7ddd0e8893fbeea4..8d6cd45ac3bb1056aa72f8643b4dfd7c8c37ffe1 100644 (file)
@@ -1,3 +1,20 @@
+# == Schema Information
+#
+# Table name: changeset_tags
+#
+#  changeset_id :integer          not null, primary key
+#  k            :string           default(""), not null, primary key
+#  v            :string           default(""), not null
+#
+# Indexes
+#
+#  changeset_tags_id_idx  (changeset_id)
+#
+# Foreign Keys
+#
+#  changeset_tags_id_fkey  (changeset_id => changesets.id)
+#
+
 class ChangesetTag < ActiveRecord::Base
   self.primary_keys = "changeset_id", "k"
 
index 85b6ba68a131664f4fcdb7899bc8c480da5e0bb3..67b86417a3a6a069a23d45e5e059c7b4aa415b87 100644 (file)
@@ -1,3 +1,35 @@
+# == Schema Information
+#
+# Table name: client_applications
+#
+#  id                :integer          not null, primary key
+#  name              :string
+#  url               :string
+#  support_url       :string
+#  callback_url      :string
+#  key               :string(50)
+#  secret            :string(50)
+#  user_id           :integer
+#  created_at        :datetime
+#  updated_at        :datetime
+#  allow_read_prefs  :boolean          default(FALSE), not null
+#  allow_write_prefs :boolean          default(FALSE), not null
+#  allow_write_diary :boolean          default(FALSE), not null
+#  allow_write_api   :boolean          default(FALSE), not null
+#  allow_read_gpx    :boolean          default(FALSE), not null
+#  allow_write_gpx   :boolean          default(FALSE), not null
+#  allow_write_notes :boolean          default(FALSE), not null
+#
+# Indexes
+#
+#  index_client_applications_on_key      (key) UNIQUE
+#  index_client_applications_on_user_id  (user_id)
+#
+# Foreign Keys
+#
+#  client_applications_user_id_fkey  (user_id => users.id)
+#
+
 require "oauth"
 
 class ClientApplication < ActiveRecord::Base
@@ -43,7 +75,7 @@ class ClientApplication < ActiveRecord::Base
     @oauth_client ||= OAuth::Consumer.new(key, secret)
   end
 
-  def create_request_token(params = {})
+  def create_request_token(_params = {})
     params = { :client_application => self, :callback_url => token_callback_url }
     permissions.each do |p|
       params[p] = true
index 2796eb612ac8eea869270fc7cee2f72bb73b6da8..8a99c7b2ce461fdc80ebed2987149f4c2e8e93b1 100644 (file)
@@ -1,3 +1,27 @@
+# == Schema Information
+#
+# Table name: diary_comments
+#
+#  id             :integer          not null, primary key
+#  diary_entry_id :integer          not null
+#  user_id        :integer          not null
+#  body           :text             not null
+#  created_at     :datetime         not null
+#  updated_at     :datetime         not null
+#  visible        :boolean          default(TRUE), not null
+#  body_format    :enum             default("markdown"), not null
+#
+# Indexes
+#
+#  diary_comment_user_id_created_at_index  (user_id,created_at)
+#  diary_comments_entry_id_idx             (diary_entry_id,id) UNIQUE
+#
+# Foreign Keys
+#
+#  diary_comments_diary_entry_id_fkey  (diary_entry_id => diary_entries.id)
+#  diary_comments_user_id_fkey         (user_id => users.id)
+#
+
 class DiaryComment < ActiveRecord::Base
   belongs_to :user
   belongs_to :diary_entry
index 143ddc1dc0949ad74b451501ae7a20ec8ec38273..2a24d800296b80902fffdd33656e67447505e9a5 100644 (file)
@@ -1,3 +1,31 @@
+# == Schema Information
+#
+# Table name: diary_entries
+#
+#  id            :integer          not null, primary key
+#  user_id       :integer          not null
+#  title         :string           not null
+#  body          :text             not null
+#  created_at    :datetime         not null
+#  updated_at    :datetime         not null
+#  latitude      :float
+#  longitude     :float
+#  language_code :string           default("en"), not null
+#  visible       :boolean          default(TRUE), not null
+#  body_format   :enum             default("markdown"), not null
+#
+# Indexes
+#
+#  diary_entry_created_at_index                (created_at)
+#  diary_entry_language_code_created_at_index  (language_code,created_at)
+#  diary_entry_user_id_created_at_index        (user_id,created_at)
+#
+# Foreign Keys
+#
+#  diary_entries_language_code_fkey  (language_code => languages.code)
+#  diary_entries_user_id_fkey        (user_id => users.id)
+#
+
 class DiaryEntry < ActiveRecord::Base
   belongs_to :user, :counter_cache => true
   belongs_to :language, :foreign_key => "language_code"
index 8b96f60743fbedd5ca1b4acda887d248c0dce86e..6d24c4598c42af2eb22c98732c05f605f1d6a166 100644 (file)
@@ -1,3 +1,20 @@
+# == Schema Information
+#
+# Table name: diary_entry_subscriptions
+#
+#  user_id        :integer          not null, primary key
+#  diary_entry_id :integer          not null, primary key
+#
+# Indexes
+#
+#  index_diary_entry_subscriptions_on_diary_entry_id  (diary_entry_id)
+#
+# Foreign Keys
+#
+#  diary_entry_subscriptions_diary_entry_id_fkey  (diary_entry_id => diary_entries.id)
+#  diary_entry_subscriptions_user_id_fkey         (user_id => users.id)
+#
+
 class DiaryEntrySubscription < ActiveRecord::Base
   self.primary_keys = "user_id", "diary_entry_id"
 
index d740a711cfaef4c97dcbcb7d17a2de812f0e2b16..86da87b932ac99b332e95c864f346c12cc8a7ba4 100644 (file)
@@ -1,3 +1,22 @@
+# == Schema Information
+#
+# Table name: friends
+#
+#  id             :integer          not null, primary key
+#  user_id        :integer          not null
+#  friend_user_id :integer          not null
+#
+# Indexes
+#
+#  friends_user_id_idx  (user_id)
+#  user_id_idx          (friend_user_id)
+#
+# Foreign Keys
+#
+#  friends_friend_user_id_fkey  (friend_user_id => users.id)
+#  friends_user_id_fkey         (user_id => users.id)
+#
+
 class Friend < ActiveRecord::Base
   belongs_to :befriender, :class_name => "User", :foreign_key => :user_id
   belongs_to :befriendee, :class_name => "User", :foreign_key => :friend_user_id
index 776182e6376c90e8be6224e3fcd9a580f0c26e9b..67e98569bbf14315099efb4b79d40dc7ef32e2ad 100644 (file)
@@ -1,3 +1,12 @@
+# == Schema Information
+#
+# Table name: languages
+#
+#  code         :string           not null, primary key
+#  english_name :string           not null
+#  native_name  :string
+#
+
 class Language < ActiveRecord::Base
   self.primary_key = "code"
 
index 2a0cea4a1faa7840c10d5b9f2c2f79169a989237..aff628e035901e685c18515902087db8e48a088d 100644 (file)
@@ -1,3 +1,29 @@
+# == Schema Information
+#
+# Table name: messages
+#
+#  id                :integer          not null, primary key
+#  from_user_id      :integer          not null
+#  title             :string           not null
+#  body              :text             not null
+#  sent_on           :datetime         not null
+#  message_read      :boolean          default(FALSE), not null
+#  to_user_id        :integer          not null
+#  to_user_visible   :boolean          default(TRUE), not null
+#  from_user_visible :boolean          default(TRUE), not null
+#  body_format       :enum             default("markdown"), not null
+#
+# Indexes
+#
+#  messages_from_user_id_idx  (from_user_id)
+#  messages_to_user_id_idx    (to_user_id)
+#
+# Foreign Keys
+#
+#  messages_from_user_id_fkey  (from_user_id => users.id)
+#  messages_to_user_id_fkey    (to_user_id => users.id)
+#
+
 require "validators"
 
 class Message < ActiveRecord::Base
index f4367e45954edf51964b903ce54b733c89f8de0b..c09fcbd6778cbce6083c14cdd15653b3da957237 100644 (file)
@@ -1,3 +1,26 @@
+# == Schema Information
+#
+# Table name: current_nodes
+#
+#  id           :integer          not null, primary key
+#  latitude     :integer          not null
+#  longitude    :integer          not null
+#  changeset_id :integer          not null
+#  visible      :boolean          not null
+#  timestamp    :datetime         not null
+#  tile         :integer          not null
+#  version      :integer          not null
+#
+# Indexes
+#
+#  current_nodes_tile_idx       (tile)
+#  current_nodes_timestamp_idx  (timestamp)
+#
+# Foreign Keys
+#
+#  current_nodes_changeset_id_fkey  (changeset_id => changesets.id)
+#
+
 class Node < ActiveRecord::Base
   require "xml/libxml"
 
@@ -70,7 +93,7 @@ class Node < ActiveRecord::Base
     raise OSM::APIBadXMLError.new("node", pt, "Changeset id is missing") if pt["changeset"].nil?
     node.changeset_id = pt["changeset"].to_i
 
-    raise OSM::APIBadUserInput.new("The node is outside this world") unless node.in_world?
+    raise OSM::APIBadUserInput, "The node is outside this world" unless node.in_world?
 
     # version must be present unless creating
     raise OSM::APIBadXMLError.new("node", pt, "Version is required when updating") unless create || !pt["version"].nil?
@@ -81,7 +104,7 @@ class Node < ActiveRecord::Base
       node.id = pt["id"].to_i
       # .to_i will return 0 if there is no number that can be parsed.
       # We want to make sure that there is no id with zero anyway
-      raise OSM::APIBadUserInput.new("ID of node cannot be zero when updating.") if node.id.zero?
+      raise OSM::APIBadUserInput, "ID of node cannot be zero when updating." if node.id.zero?
     end
 
     # We don't care about the time, as it is explicitly set on create/update/delete
@@ -120,10 +143,10 @@ class Node < ActiveRecord::Base
       lock!
       check_consistency(self, new_node, user)
       ways = Way.joins(:way_nodes).where(:visible => true, :current_way_nodes => { :node_id => id }).order(:id)
-      raise OSM::APIPreconditionFailedError.new("Node #{id} is still used by ways #{ways.collect(&:id).join(',')}.") unless ways.empty?
+      raise OSM::APIPreconditionFailedError, "Node #{id} is still used by ways #{ways.collect(&:id).join(',')}." unless ways.empty?
 
       rels = Relation.joins(:relation_members).where(:visible => true, :current_relation_members => { :member_type => "Node", :member_id => id }).order(:id)
-      raise OSM::APIPreconditionFailedError.new("Node #{id} is still used by relations #{rels.collect(&:id).join(',')}.") unless rels.empty?
+      raise OSM::APIPreconditionFailedError, "Node #{id} is still used by relations #{rels.collect(&:id).join(',')}." unless rels.empty?
 
       self.changeset_id = new_node.changeset_id
       self.tags = {}
@@ -205,7 +228,7 @@ class Node < ActiveRecord::Base
   attr_writer :tags
 
   def add_tag_key_val(k, v)
-    @tags = {} unless @tags
+    @tags ||= {}
 
     # duplicate tags are now forbidden, so we can't allow values
     # in the hash to be overwritten.
index 5f2f9efc9107036fef2bb97b244d63325c1efe15..20065b993137f8e1df485c24c81d716371c062ae 100644 (file)
@@ -1,3 +1,16 @@
+# == Schema Information
+#
+# Table name: current_node_tags
+#
+#  node_id :integer          not null, primary key
+#  k       :string           default(""), not null, primary key
+#  v       :string           default(""), not null
+#
+# Foreign Keys
+#
+#  current_node_tags_id_fkey  (node_id => current_nodes.id)
+#
+
 class NodeTag < ActiveRecord::Base
   self.table_name = "current_node_tags"
   self.primary_keys = "node_id", "k"
index d2c36071da0dfe5b3e8a545446ebe9c0396f6ad6..b7f6928b869a75c626422b46438b81a4f7d38262 100644 (file)
@@ -1,3 +1,23 @@
+# == Schema Information
+#
+# Table name: notes
+#
+#  id         :integer          not null, primary key
+#  latitude   :integer          not null
+#  longitude  :integer          not null
+#  tile       :integer          not null
+#  updated_at :datetime         not null
+#  created_at :datetime         not null
+#  status     :enum             not null
+#  closed_at  :datetime
+#
+# Indexes
+#
+#  notes_created_at_idx   (created_at)
+#  notes_tile_status_idx  (tile,status)
+#  notes_updated_at_idx   (updated_at)
+#
+
 class Note < ActiveRecord::Base
   include GeoRecord
 
index aa8635aadde724c6bbb233650460d27a2471b49b..f8450d0a369625be13158760ae3ae5eb70ec5635 100644 (file)
@@ -1,3 +1,28 @@
+# == Schema Information
+#
+# Table name: note_comments
+#
+#  id         :integer          not null, primary key
+#  note_id    :integer          not null
+#  visible    :boolean          not null
+#  created_at :datetime         not null
+#  author_ip  :inet
+#  author_id  :integer
+#  body       :text
+#  event      :enum
+#
+# Indexes
+#
+#  index_note_comments_on_body        (to_tsvector('english'::regconfig, body))
+#  index_note_comments_on_created_at  (created_at)
+#  note_comments_note_id_idx          (note_id)
+#
+# Foreign Keys
+#
+#  note_comments_author_id_fkey  (author_id => users.id)
+#  note_comments_note_id_fkey    (note_id => notes.id)
+#
+
 class NoteComment < ActiveRecord::Base
   belongs_to :note, :foreign_key => :note_id, :touch => true
   belongs_to :author, :class_name => "User", :foreign_key => :author_id
index 1e67194fef19dc5c3a88e794d1c83b528245e7b6..3435b25a31494dbf2b7a386211689b3048df8f1d 100644 (file)
@@ -1,3 +1,40 @@
+# == Schema Information
+#
+# Table name: oauth_tokens
+#
+#  id                    :integer          not null, primary key
+#  user_id               :integer
+#  type                  :string(20)
+#  client_application_id :integer
+#  token                 :string(50)
+#  secret                :string(50)
+#  authorized_at         :datetime
+#  invalidated_at        :datetime
+#  created_at            :datetime
+#  updated_at            :datetime
+#  allow_read_prefs      :boolean          default(FALSE), not null
+#  allow_write_prefs     :boolean          default(FALSE), not null
+#  allow_write_diary     :boolean          default(FALSE), not null
+#  allow_write_api       :boolean          default(FALSE), not null
+#  allow_read_gpx        :boolean          default(FALSE), not null
+#  allow_write_gpx       :boolean          default(FALSE), not null
+#  callback_url          :string
+#  verifier              :string(20)
+#  scope                 :string
+#  valid_to              :datetime
+#  allow_write_notes     :boolean          default(FALSE), not null
+#
+# Indexes
+#
+#  index_oauth_tokens_on_token    (token) UNIQUE
+#  index_oauth_tokens_on_user_id  (user_id)
+#
+# Foreign Keys
+#
+#  oauth_tokens_client_application_id_fkey  (client_application_id => client_applications.id)
+#  oauth_tokens_user_id_fkey                (user_id => users.id)
+#
+
 class Oauth2Token < AccessToken
   attr_accessor :state
 
@@ -9,9 +46,9 @@ class Oauth2Token < AccessToken
 
   def to_query
     q = "access_token=#{token}&token_type=bearer"
-    q << "&state=#{URI.escape(state)}" if @state
+    q << "&state=#{CGI.escape(state)}" if @state
     q << "&expires_in=#{expires_in}" if expires_at
-    q << "&scope=#{URI.escape(scope)}" if scope
+    q << "&scope=#{CGI.escape(scope)}" if scope
     q
   end
 
index a404d0c7a872c6d1cb8673cafdc3ea3feb792f4f..3eca1038c22333263f8d213974d90ba78066395f 100644 (file)
@@ -1,3 +1,40 @@
+# == Schema Information
+#
+# Table name: oauth_tokens
+#
+#  id                    :integer          not null, primary key
+#  user_id               :integer
+#  type                  :string(20)
+#  client_application_id :integer
+#  token                 :string(50)
+#  secret                :string(50)
+#  authorized_at         :datetime
+#  invalidated_at        :datetime
+#  created_at            :datetime
+#  updated_at            :datetime
+#  allow_read_prefs      :boolean          default(FALSE), not null
+#  allow_write_prefs     :boolean          default(FALSE), not null
+#  allow_write_diary     :boolean          default(FALSE), not null
+#  allow_write_api       :boolean          default(FALSE), not null
+#  allow_read_gpx        :boolean          default(FALSE), not null
+#  allow_write_gpx       :boolean          default(FALSE), not null
+#  callback_url          :string
+#  verifier              :string(20)
+#  scope                 :string
+#  valid_to              :datetime
+#  allow_write_notes     :boolean          default(FALSE), not null
+#
+# Indexes
+#
+#  index_oauth_tokens_on_token    (token) UNIQUE
+#  index_oauth_tokens_on_user_id  (user_id)
+#
+# Foreign Keys
+#
+#  oauth_tokens_client_application_id_fkey  (client_application_id => client_applications.id)
+#  oauth_tokens_user_id_fkey                (user_id => users.id)
+#
+
 class Oauth2Verifier < OauthToken
   validates :user, :presence => true, :associated => true
 
@@ -21,7 +58,7 @@ class Oauth2Verifier < OauthToken
 
   def to_query
     q = "code=#{token}"
-    q << "&state=#{URI.escape(state)}" if @state
+    q << "&state=#{CGI.escape(state)}" if @state
     q
   end
 
index e0510dcbf85bb59a237b33fca0c8aa6a9008ece2..0952f068edc6b9a9d2525206e1fd5069c8ff7516 100644 (file)
@@ -1,3 +1,18 @@
+# == Schema Information
+#
+# Table name: oauth_nonces
+#
+#  id         :integer          not null, primary key
+#  nonce      :string
+#  timestamp  :integer
+#  created_at :datetime
+#  updated_at :datetime
+#
+# Indexes
+#
+#  index_oauth_nonces_on_nonce_and_timestamp  (nonce,timestamp) UNIQUE
+#
+
 # Simple store of nonces. The OAuth Spec requires that any given pair of nonce and timestamps are unique.
 # Thus you can use the same nonce with a different timestamp and viceversa.
 class OauthNonce < ActiveRecord::Base
index 9a3e7de9eca142c21574f011ef33ee393f573539..fd332723f25c07333cf2ca5d2483ea671887f121 100644 (file)
@@ -1,3 +1,40 @@
+# == Schema Information
+#
+# Table name: oauth_tokens
+#
+#  id                    :integer          not null, primary key
+#  user_id               :integer
+#  type                  :string(20)
+#  client_application_id :integer
+#  token                 :string(50)
+#  secret                :string(50)
+#  authorized_at         :datetime
+#  invalidated_at        :datetime
+#  created_at            :datetime
+#  updated_at            :datetime
+#  allow_read_prefs      :boolean          default(FALSE), not null
+#  allow_write_prefs     :boolean          default(FALSE), not null
+#  allow_write_diary     :boolean          default(FALSE), not null
+#  allow_write_api       :boolean          default(FALSE), not null
+#  allow_read_gpx        :boolean          default(FALSE), not null
+#  allow_write_gpx       :boolean          default(FALSE), not null
+#  callback_url          :string
+#  verifier              :string(20)
+#  scope                 :string
+#  valid_to              :datetime
+#  allow_write_notes     :boolean          default(FALSE), not null
+#
+# Indexes
+#
+#  index_oauth_tokens_on_token    (token) UNIQUE
+#  index_oauth_tokens_on_user_id  (user_id)
+#
+# Foreign Keys
+#
+#  oauth_tokens_client_application_id_fkey  (client_application_id => client_applications.id)
+#  oauth_tokens_user_id_fkey                (user_id => users.id)
+#
+
 class OauthToken < ActiveRecord::Base
   belongs_to :client_application
   belongs_to :user
index b103e5c7310160033f1d733029b26f5a29da50d7..9690dc46ca807106f7080f41e88e9e94048d6e78 100644 (file)
@@ -1,3 +1,29 @@
+# == Schema Information
+#
+# Table name: nodes
+#
+#  node_id      :integer          not null, primary key
+#  latitude     :integer          not null
+#  longitude    :integer          not null
+#  changeset_id :integer          not null
+#  visible      :boolean          not null
+#  timestamp    :datetime         not null
+#  tile         :integer          not null
+#  version      :integer          not null, primary key
+#  redaction_id :integer
+#
+# Indexes
+#
+#  nodes_changeset_id_idx  (changeset_id)
+#  nodes_tile_idx          (tile)
+#  nodes_timestamp_idx     (timestamp)
+#
+# Foreign Keys
+#
+#  nodes_changeset_id_fkey  (changeset_id => changesets.id)
+#  nodes_redaction_id_fkey  (redaction_id => redactions.id)
+#
+
 class OldNode < ActiveRecord::Base
   include GeoRecord
   include ConsistencyValidations
index f1df02c84095c279e18f579591e35f09df57645d..9e03d34f983a86553d6ca2fb3b8c7ff5d8472056 100644 (file)
@@ -1,3 +1,17 @@
+# == Schema Information
+#
+# Table name: node_tags
+#
+#  node_id :integer          not null, primary key
+#  version :integer          not null, primary key
+#  k       :string           default(""), not null, primary key
+#  v       :string           default(""), not null
+#
+# Foreign Keys
+#
+#  node_tags_id_fkey  (node_id => nodes.node_id)
+#
+
 class OldNodeTag < ActiveRecord::Base
   self.table_name = "node_tags"
   self.primary_keys = "node_id", "version", "k"
index 0e85122a48b67bba0954e047a95065f7fdb7dceb..3470561cee4df036a318d2901a7c59752ae19bbd 100644 (file)
@@ -1,3 +1,25 @@
+# == Schema Information
+#
+# Table name: relations
+#
+#  relation_id  :integer          default(0), not null, primary key
+#  changeset_id :integer          not null
+#  timestamp    :datetime         not null
+#  version      :integer          not null, primary key
+#  visible      :boolean          default(TRUE), not null
+#  redaction_id :integer
+#
+# Indexes
+#
+#  relations_changeset_id_idx  (changeset_id)
+#  relations_timestamp_idx     (timestamp)
+#
+# Foreign Keys
+#
+#  relations_changeset_id_fkey  (changeset_id => changesets.id)
+#  relations_redaction_id_fkey  (redaction_id => redactions.id)
+#
+
 class OldRelation < ActiveRecord::Base
   include ConsistencyValidations
   include ObjectMetadata
index 77a5a3786eceebfb25c705762f36fe6508d03b94..a746374357d6b47a74b750e191a297646cce43ca 100644 (file)
@@ -1,3 +1,23 @@
+# == Schema Information
+#
+# Table name: relation_members
+#
+#  relation_id :integer          default(0), not null, primary key
+#  member_type :enum             not null
+#  member_id   :integer          not null
+#  member_role :string           not null
+#  version     :integer          default(0), not null, primary key
+#  sequence_id :integer          default(0), not null, primary key
+#
+# Indexes
+#
+#  relation_members_member_idx  (member_type,member_id)
+#
+# Foreign Keys
+#
+#  relation_members_id_fkey  (relation_id => relations.relation_id)
+#
+
 class OldRelationMember < ActiveRecord::Base
   self.table_name = "relation_members"
   self.primary_keys = "relation_id", "version", "sequence_id"
index ad3b72734aed707bfebc87c4c26562690fa5f9c6..052b60853e9ec0f630d9b8ccd5aef59b81c89575 100644 (file)
@@ -1,3 +1,17 @@
+# == Schema Information
+#
+# Table name: relation_tags
+#
+#  relation_id :integer          default(0), not null, primary key
+#  k           :string           default(""), not null, primary key
+#  v           :string           default(""), not null
+#  version     :integer          not null, primary key
+#
+# Foreign Keys
+#
+#  relation_tags_id_fkey  (relation_id => relations.relation_id)
+#
+
 class OldRelationTag < ActiveRecord::Base
   self.table_name = "relation_tags"
   self.primary_keys = "relation_id", "version", "k"
index 63c4d8b65d2d6c4acb24b3a3d111f0a105c9eb72..baca05d33549738c391d373602782515a7a94eff 100644 (file)
@@ -1,3 +1,25 @@
+# == Schema Information
+#
+# Table name: ways
+#
+#  way_id       :integer          default(0), not null, primary key
+#  changeset_id :integer          not null
+#  timestamp    :datetime         not null
+#  version      :integer          not null, primary key
+#  visible      :boolean          default(TRUE), not null
+#  redaction_id :integer
+#
+# Indexes
+#
+#  ways_changeset_id_idx  (changeset_id)
+#  ways_timestamp_idx     (timestamp)
+#
+# Foreign Keys
+#
+#  ways_changeset_id_fkey  (changeset_id => changesets.id)
+#  ways_redaction_id_fkey  (redaction_id => redactions.id)
+#
+
 class OldWay < ActiveRecord::Base
   include ConsistencyValidations
   include ObjectMetadata
index 23ff503edf665ff922e6fe4b874f5484734f488f..e1627d3faa3091c002bef4fbb2b0f07a56fd2492 100644 (file)
@@ -1,3 +1,21 @@
+# == Schema Information
+#
+# Table name: way_nodes
+#
+#  way_id      :integer          not null, primary key
+#  node_id     :integer          not null
+#  version     :integer          not null, primary key
+#  sequence_id :integer          not null, primary key
+#
+# Indexes
+#
+#  way_nodes_node_idx  (node_id)
+#
+# Foreign Keys
+#
+#  way_nodes_id_fkey  (way_id => ways.way_id)
+#
+
 class OldWayNode < ActiveRecord::Base
   self.table_name = "way_nodes"
   self.primary_keys = "way_id", "version", "sequence_id"
index 69bd2b1861d12d845d2c3716f8fd651311d781c1..8fffebc2553ab9e8c217195dd8da41c56374f787 100644 (file)
@@ -1,3 +1,17 @@
+# == Schema Information
+#
+# Table name: way_tags
+#
+#  way_id  :integer          default(0), not null, primary key
+#  k       :string           not null, primary key
+#  v       :string           not null
+#  version :integer          not null, primary key
+#
+# Foreign Keys
+#
+#  way_tags_id_fkey  (way_id => ways.way_id)
+#
+
 class OldWayTag < ActiveRecord::Base
   self.table_name = "way_tags"
   self.primary_keys = "way_id", "version", "k"
index 04f002e3637ccf62c1f808dea10f3b22677e0074..b835864db074b40e7c27cfd8521e0689b96aa979 100644 (file)
@@ -1,3 +1,20 @@
+# == Schema Information
+#
+# Table name: redactions
+#
+#  id                 :integer          not null, primary key
+#  title              :string
+#  description        :text
+#  created_at         :datetime
+#  updated_at         :datetime
+#  user_id            :integer          not null
+#  description_format :enum             default("markdown"), not null
+#
+# Foreign Keys
+#
+#  redactions_user_id_fkey  (user_id => users.id)
+#
+
 ##
 # Redaction represents a record associated with a particular
 # action on the database to hide revisions from the history
index d2490dbaec0e872080fabec0b2d82a64b1628a32..157794cd69cee7424771a248b0331b569f6d32d8 100644 (file)
@@ -1,3 +1,22 @@
+# == Schema Information
+#
+# Table name: current_relations
+#
+#  id           :integer          not null, primary key
+#  changeset_id :integer          not null
+#  timestamp    :datetime         not null
+#  visible      :boolean          not null
+#  version      :integer          not null
+#
+# Indexes
+#
+#  current_relations_timestamp_idx  (timestamp)
+#
+# Foreign Keys
+#
+#  current_relations_changeset_id_fkey  (changeset_id => changesets.id)
+#
+
 class Relation < ActiveRecord::Base
   require "xml/libxml"
 
@@ -60,7 +79,7 @@ class Relation < ActiveRecord::Base
       relation.id = pt["id"].to_i
       # .to_i will return 0 if there is no number that can be parsed.
       # We want to make sure that there is no id with zero anyway
-      raise OSM::APIBadUserInput.new("ID of relation cannot be zero when updating.") if relation.id.zero?
+      raise OSM::APIBadUserInput, "ID of relation cannot be zero when updating." if relation.id.zero?
     end
 
     # We don't care about the timestamp nor the visibility as these are either
@@ -92,7 +111,7 @@ class Relation < ActiveRecord::Base
       member["role"] ||= "" # Allow  the upload to not include this, in which case we default to an empty string.
       relation.add_member(member["type"].classify, member["ref"], member["role"])
     end
-    raise OSM::APIBadUserInput.new("Some bad xml in relation") if relation.nil?
+    raise OSM::APIBadUserInput, "Some bad xml in relation" if relation.nil?
 
     relation
   end
@@ -103,25 +122,13 @@ class Relation < ActiveRecord::Base
     doc
   end
 
-  def to_xml_node(visible_members = nil, changeset_cache = {}, user_display_name_cache = {})
+  def to_xml_node(changeset_cache = {}, user_display_name_cache = {})
     el = XML::Node.new "relation"
     el["id"] = id.to_s
 
     add_metadata_to_xml_node(el, self, changeset_cache, user_display_name_cache)
 
     relation_members.each do |member|
-      p = 0
-
-      if visible_members
-        # if there is a list of visible members then use that to weed out deleted segments
-        p = 1 if visible_members[member.member_type][member.member_id]
-      else
-        # otherwise, manually go to the db to check things
-        p = 1 if member.member.visible?
-      end
-
-      next unless p
-
       member_el = XML::Node.new "member"
       member_el["type"] = member.member_type.downcase
       member_el["ref"] = member.member_id.to_s
@@ -155,7 +162,7 @@ class Relation < ActiveRecord::Base
   end
 
   def add_tag_keyval(k, v)
-    @tags = {} unless @tags
+    @tags ||= {}
 
     # duplicate tags are now forbidden, so we can't allow values
     # in the hash to be overwritten.
@@ -187,7 +194,7 @@ class Relation < ActiveRecord::Base
       check_consistency(self, new_relation, user)
       # This will check to see if this relation is used by another relation
       rel = RelationMember.joins(:relation).find_by("visible = ? AND member_type = 'Relation' and member_id = ? ", true, id)
-      raise OSM::APIPreconditionFailedError.new("The relation #{new_relation.id} is used in relation #{rel.relation.id}.") unless rel.nil?
+      raise OSM::APIPreconditionFailedError, "The relation #{new_relation.id} is used in relation #{rel.relation.id}." unless rel.nil?
 
       self.changeset_id = new_relation.changeset_id
       self.tags = {}
@@ -202,7 +209,7 @@ class Relation < ActiveRecord::Base
       lock!
       check_consistency(self, new_relation, user)
       unless new_relation.preconditions_ok?(members)
-        raise OSM::APIPreconditionFailedError.new("Cannot update relation #{id}: data or member data is invalid.")
+        raise OSM::APIPreconditionFailedError, "Cannot update relation #{id}: data or member data is invalid."
       end
       self.changeset_id = new_relation.changeset_id
       self.changeset = new_relation.changeset
@@ -216,7 +223,7 @@ class Relation < ActiveRecord::Base
   def create_with_history(user)
     check_create_consistency(self, user)
     unless preconditions_ok?
-      raise OSM::APIPreconditionFailedError.new("Cannot create relation: data or member data is invalid.")
+      raise OSM::APIPreconditionFailedError, "Cannot create relation: data or member data is invalid."
     end
     self.version = 0
     self.visible = true
@@ -253,7 +260,7 @@ class Relation < ActiveRecord::Base
 
       # and check that it is OK to use.
       unless element && element.visible? && element.preconditions_ok?
-        raise OSM::APIPreconditionFailedError.new("Relation with id #{id} cannot be saved due to #{m[0]} with id #{m[1]}")
+        raise OSM::APIPreconditionFailedError, "Relation with id #{id} cannot be saved due to #{m[0]} with id #{m[1]}"
       end
       hash[m[1]] = true
     end
@@ -270,7 +277,7 @@ class Relation < ActiveRecord::Base
       old_id = id.to_i
       if old_id < 0
         new_id = id_map[type.downcase.to_sym][old_id]
-        raise OSM::APIBadUserInput.new("Placeholder #{type} not found for reference #{old_id} in relation #{self.id.nil? ? placeholder_id : self.id}.") if new_id.nil?
+        raise OSM::APIBadUserInput, "Placeholder #{type} not found for reference #{old_id} in relation #{self.id.nil? ? placeholder_id : self.id}." if new_id.nil?
         [type, new_id, role]
       else
         [type, id, role]
index e5c783f5c68b788e7d5f034970a3a4ebc28acd5e..3e5cdfca27e1513856f12c4adf04fc89e95c5bd6 100644 (file)
@@ -1,3 +1,22 @@
+# == Schema Information
+#
+# Table name: current_relation_members
+#
+#  relation_id :integer          not null, primary key
+#  member_type :enum             not null
+#  member_id   :integer          not null
+#  member_role :string           not null
+#  sequence_id :integer          default(0), not null, primary key
+#
+# Indexes
+#
+#  current_relation_members_member_idx  (member_type,member_id)
+#
+# Foreign Keys
+#
+#  current_relation_members_id_fkey  (relation_id => current_relations.id)
+#
+
 class RelationMember < ActiveRecord::Base
   self.table_name = "current_relation_members"
   self.primary_keys = "relation_id", "sequence_id"
index 382606795cab0416326971239a393173edb6c491..5dc609987370ffbc3731e9f6864fc5b155f65f6a 100644 (file)
@@ -1,3 +1,16 @@
+# == Schema Information
+#
+# Table name: current_relation_tags
+#
+#  relation_id :integer          not null, primary key
+#  k           :string           default(""), not null, primary key
+#  v           :string           default(""), not null
+#
+# Foreign Keys
+#
+#  current_relation_tags_id_fkey  (relation_id => current_relations.id)
+#
+
 class RelationTag < ActiveRecord::Base
   self.table_name = "current_relation_tags"
   self.primary_keys = "relation_id", "k"
index c0f0194860f0117fcf71181301bfb2c53385a849..335a735bc5a4dbcab80c07d92f2791df53447509 100644 (file)
@@ -1,3 +1,40 @@
+# == Schema Information
+#
+# Table name: oauth_tokens
+#
+#  id                    :integer          not null, primary key
+#  user_id               :integer
+#  type                  :string(20)
+#  client_application_id :integer
+#  token                 :string(50)
+#  secret                :string(50)
+#  authorized_at         :datetime
+#  invalidated_at        :datetime
+#  created_at            :datetime
+#  updated_at            :datetime
+#  allow_read_prefs      :boolean          default(FALSE), not null
+#  allow_write_prefs     :boolean          default(FALSE), not null
+#  allow_write_diary     :boolean          default(FALSE), not null
+#  allow_write_api       :boolean          default(FALSE), not null
+#  allow_read_gpx        :boolean          default(FALSE), not null
+#  allow_write_gpx       :boolean          default(FALSE), not null
+#  callback_url          :string
+#  verifier              :string(20)
+#  scope                 :string
+#  valid_to              :datetime
+#  allow_write_notes     :boolean          default(FALSE), not null
+#
+# Indexes
+#
+#  index_oauth_tokens_on_token    (token) UNIQUE
+#  index_oauth_tokens_on_user_id  (user_id)
+#
+# Foreign Keys
+#
+#  oauth_tokens_client_application_id_fkey  (client_application_id => client_applications.id)
+#  oauth_tokens_user_id_fkey                (user_id => users.id)
+#
+
 class RequestToken < OauthToken
   attr_accessor :provided_oauth_verifier
 
index eed09dbe536b3b268067837eb6000fc57711d104..214b0b6470aacc20fbe1262d2b553778b55bf729 100644 (file)
@@ -1,3 +1,30 @@
+# == Schema Information
+#
+# Table name: gpx_files
+#
+#  id          :integer          not null, primary key
+#  user_id     :integer          not null
+#  visible     :boolean          default(TRUE), not null
+#  name        :string           default(""), not null
+#  size        :integer
+#  latitude    :float
+#  longitude   :float
+#  timestamp   :datetime         not null
+#  description :string           default(""), not null
+#  inserted    :boolean          not null
+#  visibility  :enum             default("public"), not null
+#
+# Indexes
+#
+#  gpx_files_timestamp_idx           (timestamp)
+#  gpx_files_user_id_idx             (user_id)
+#  gpx_files_visible_visibility_idx  (visible,visibility)
+#
+# Foreign Keys
+#
+#  gpx_files_user_id_fkey  (user_id => users.id)
+#
+
 class Trace < ActiveRecord::Base
   self.table_name = "gpx_files"
 
@@ -172,13 +199,12 @@ class Trace < ActiveRecord::Base
     el1
   end
 
-  # Read in xml as text and return it's Node object representation
-  def self.from_xml(xml, create = false)
+  def update_from_xml(xml, create = false)
     p = XML::Parser.string(xml, :options => XML::Parser::Options::NOERROR)
     doc = p.parse
 
     doc.find("//osm/gpx_file").each do |pt|
-      return Trace.from_xml_node(pt, create)
+      return update_from_xml_node(pt, create)
     end
 
     raise OSM::APIBadXMLError.new("trace", xml, "XML doesn't contain an osm/gpx_file element.")
@@ -186,34 +212,31 @@ class Trace < ActiveRecord::Base
     raise OSM::APIBadXMLError.new("trace", xml, ex.message)
   end
 
-  def self.from_xml_node(pt, create = false)
-    trace = Trace.new
-
+  def update_from_xml_node(pt, create = false)
     raise OSM::APIBadXMLError.new("trace", pt, "visibility missing") if pt["visibility"].nil?
-    trace.visibility = pt["visibility"]
+    self.visibility = pt["visibility"]
 
     unless create
       raise OSM::APIBadXMLError.new("trace", pt, "ID is required when updating.") if pt["id"].nil?
-      trace.id = pt["id"].to_i
+      id = pt["id"].to_i
       # .to_i will return 0 if there is no number that can be parsed.
       # We want to make sure that there is no id with zero anyway
-      raise OSM::APIBadUserInput.new("ID of trace cannot be zero when updating.") if trace.id.zero?
+      raise OSM::APIBadUserInput, "ID of trace cannot be zero when updating." if id.zero?
+      raise OSM::APIBadUserInput, "The id in the url (#{self.id}) is not the same as provided in the xml (#{id})" unless self.id == id
     end
 
     # We don't care about the time, as it is explicitly set on create/update/delete
     # We don't care about the visibility as it is implicit based on the action
     # and set manually before the actual delete
-    trace.visible = true
+    self.visible = true
 
     description = pt.find("description").first
     raise OSM::APIBadXMLError.new("trace", pt, "description missing") if description.nil?
-    trace.description = description.content
+    self.description = description.content
 
-    pt.find("tag").each do |tag|
-      trace.tags.build(:tag => tag.content)
+    self.tags = pt.find("tag").collect do |tag|
+      Tracetag.new(:tag => tag.content)
     end
-
-    trace
   end
 
   def xml_file
index 9485b8a14086b7d291c42eb24ff85a2fa4ee689c..445688c5554389e66aa90b6e77fb8dca6b354c67 100644 (file)
@@ -1,3 +1,25 @@
+# == Schema Information
+#
+# Table name: gps_points
+#
+#  altitude  :float
+#  trackid   :integer          not null
+#  latitude  :integer          not null
+#  longitude :integer          not null
+#  gpx_id    :integer          not null
+#  timestamp :datetime
+#  tile      :integer
+#
+# Indexes
+#
+#  points_gpxid_idx  (gpx_id)
+#  points_tile_idx   (tile)
+#
+# Foreign Keys
+#
+#  gps_points_gpx_id_fkey  (gpx_id => gpx_files.id)
+#
+
 class Tracepoint < ActiveRecord::Base
   include GeoRecord
 
index 9d21959205cbcd12edb261fa7ea81fccd4c0fc01..1a4fbd39889195a4653fcc1ed9fec5be3d8e4126 100644 (file)
@@ -1,3 +1,21 @@
+# == Schema Information
+#
+# Table name: gpx_file_tags
+#
+#  gpx_id :integer          default(0), not null
+#  tag    :string           not null
+#  id     :integer          not null, primary key
+#
+# Indexes
+#
+#  gpx_file_tags_gpxid_idx  (gpx_id)
+#  gpx_file_tags_tag_idx    (tag)
+#
+# Foreign Keys
+#
+#  gpx_file_tags_gpx_id_fkey  (gpx_id => gpx_files.id)
+#
+
 class Tracetag < ActiveRecord::Base
   self.table_name = "gpx_file_tags"
 
index 63c9527c7870415bae932bb387bc8a158eb5ff20..678bbad9de34b0466ec916b34c69af5744af0a36 100644 (file)
@@ -1,3 +1,48 @@
+# == Schema Information
+#
+# Table name: users
+#
+#  email               :string           not null
+#  id                  :integer          not null, primary key
+#  pass_crypt          :string           not null
+#  creation_time       :datetime         not null
+#  display_name        :string           default(""), not null
+#  data_public         :boolean          default(FALSE), not null
+#  description         :text             default(""), not null
+#  home_lat            :float
+#  home_lon            :float
+#  home_zoom           :integer          default(3)
+#  nearby              :integer          default(50)
+#  pass_salt           :string
+#  image_file_name     :text
+#  email_valid         :boolean          default(FALSE), not null
+#  new_email           :string
+#  creation_ip         :string
+#  languages           :string
+#  status              :enum             default("pending"), not null
+#  terms_agreed        :datetime
+#  consider_pd         :boolean          default(FALSE), not null
+#  auth_uid            :string
+#  preferred_editor    :string
+#  terms_seen          :boolean          default(FALSE), not null
+#  description_format  :enum             default("markdown"), not null
+#  image_fingerprint   :string
+#  changesets_count    :integer          default(0), not null
+#  traces_count        :integer          default(0), not null
+#  diary_entries_count :integer          default(0), not null
+#  image_use_gravatar  :boolean          default(FALSE), not null
+#  image_content_type  :string
+#  auth_provider       :string
+#
+# Indexes
+#
+#  users_auth_idx                (auth_provider,auth_uid) UNIQUE
+#  users_display_name_idx        (display_name) UNIQUE
+#  users_display_name_lower_idx  (lower((display_name)::text))
+#  users_email_idx               (email) UNIQUE
+#  users_email_lower_idx         (lower((email)::text))
+#
+
 class User < ActiveRecord::Base
   require "xml/libxml"
 
index eb0daba6569731cad0fe0486b6ea814099e6d2d5..4f9cf11281896f6238e699160616510c91619b86 100644 (file)
@@ -1,3 +1,29 @@
+# == Schema Information
+#
+# Table name: user_blocks
+#
+#  id            :integer          not null, primary key
+#  user_id       :integer          not null
+#  creator_id    :integer          not null
+#  reason        :text             not null
+#  ends_at       :datetime         not null
+#  needs_view    :boolean          default(FALSE), not null
+#  revoker_id    :integer
+#  created_at    :datetime
+#  updated_at    :datetime
+#  reason_format :enum             default("markdown"), not null
+#
+# Indexes
+#
+#  index_user_blocks_on_user_id  (user_id)
+#
+# Foreign Keys
+#
+#  user_blocks_moderator_id_fkey  (creator_id => users.id)
+#  user_blocks_revoker_id_fkey    (revoker_id => users.id)
+#  user_blocks_user_id_fkey       (user_id => users.id)
+#
+
 class UserBlock < ActiveRecord::Base
   validate :moderator_permissions
 
index 7c65a589953a688e3d4aa87e533ac00e9c8839ce..69b0e9ddec9fc020787c76165f3323ec9cceccd7 100644 (file)
@@ -1,3 +1,16 @@
+# == Schema Information
+#
+# Table name: user_preferences
+#
+#  user_id :integer          not null, primary key
+#  k       :string           not null, primary key
+#  v       :string           not null
+#
+# Foreign Keys
+#
+#  user_preferences_user_id_fkey  (user_id => users.id)
+#
+
 class UserPreference < ActiveRecord::Base
   self.primary_keys = "user_id", "k"
 
index 967850145f838b4dcff1af82858235dbcecebec7..adf569a03fe79a5d5827a5e33ddf4cdddb12e94d 100644 (file)
@@ -1,3 +1,24 @@
+# == Schema Information
+#
+# Table name: user_roles
+#
+#  id         :integer          not null, primary key
+#  user_id    :integer          not null
+#  role       :enum             not null
+#  created_at :datetime
+#  updated_at :datetime
+#  granter_id :integer          not null
+#
+# Indexes
+#
+#  user_roles_id_role_unique  (user_id,role) UNIQUE
+#
+# Foreign Keys
+#
+#  user_roles_granter_id_fkey  (granter_id => users.id)
+#  user_roles_user_id_fkey     (user_id => users.id)
+#
+
 class UserRole < ActiveRecord::Base
   belongs_to :user
   belongs_to :granter, :class_name => "User"
index faa540e67c043dd07d0f8dd5e0c6a8e320d5ab29..0d1e16e8acead524674dbca9aafb58398fe6cb14 100644 (file)
@@ -1,3 +1,23 @@
+# == Schema Information
+#
+# Table name: user_tokens
+#
+#  id      :integer          not null, primary key
+#  user_id :integer          not null
+#  token   :string           not null
+#  expiry  :datetime         not null
+#  referer :text
+#
+# Indexes
+#
+#  user_tokens_token_idx    (token) UNIQUE
+#  user_tokens_user_id_idx  (user_id)
+#
+# Foreign Keys
+#
+#  user_tokens_user_id_fkey  (user_id => users.id)
+#
+
 class UserToken < ActiveRecord::Base
   belongs_to :user
 
index 9586094ff10951020aed5f27b2394bf201933303..1954f744ca9332d1c45c7bd133e27f9b7b24bed2 100644 (file)
@@ -1,3 +1,22 @@
+# == Schema Information
+#
+# Table name: current_ways
+#
+#  id           :integer          not null, primary key
+#  changeset_id :integer          not null
+#  timestamp    :datetime         not null
+#  visible      :boolean          not null
+#  version      :integer          not null
+#
+# Indexes
+#
+#  current_ways_timestamp_idx  (timestamp)
+#
+# Foreign Keys
+#
+#  current_ways_changeset_id_fkey  (changeset_id => changesets.id)
+#
+
 class Way < ActiveRecord::Base
   require "xml/libxml"
 
@@ -58,7 +77,7 @@ class Way < ActiveRecord::Base
       way.id = pt["id"].to_i
       # .to_i will return 0 if there is no number that can be parsed.
       # We want to make sure that there is no id with zero anyway
-      raise OSM::APIBadUserInput.new("ID of way cannot be zero when updating.") if way.id.zero?
+      raise OSM::APIBadUserInput, "ID of way cannot be zero when updating." if way.id.zero?
     end
 
     # We don't care about the timestamp nor the visibility as these are either
@@ -138,12 +157,12 @@ class Way < ActiveRecord::Base
   attr_writer :tags
 
   def add_nd_num(n)
-    @nds = [] unless @nds
+    @nds ||= []
     @nds << n.to_i
   end
 
   def add_tag_keyval(k, v)
-    @tags = {} unless @tags
+    @tags ||= {}
 
     # duplicate tags are now forbidden, so we can't allow values
     # in the hash to be overwritten.
@@ -166,7 +185,7 @@ class Way < ActiveRecord::Base
       lock!
       check_consistency(self, new_way, user)
       unless new_way.preconditions_ok?(nds)
-        raise OSM::APIPreconditionFailedError.new("Cannot update way #{id}: data is invalid.")
+        raise OSM::APIPreconditionFailedError, "Cannot update way #{id}: data is invalid."
       end
 
       self.changeset_id = new_way.changeset_id
@@ -181,7 +200,7 @@ class Way < ActiveRecord::Base
   def create_with_history(user)
     check_create_consistency(self, user)
     unless preconditions_ok?
-      raise OSM::APIPreconditionFailedError.new("Cannot create way: data is invalid.")
+      raise OSM::APIPreconditionFailedError, "Cannot create way: data is invalid."
     end
     self.version = 0
     self.visible = true
@@ -205,7 +224,7 @@ class Way < ActiveRecord::Base
 
       if db_nds.length < new_nds.length
         missing = new_nds - db_nds.collect(&:id)
-        raise OSM::APIPreconditionFailedError.new("Way #{id} requires the nodes with id in (#{missing.join(',')}), which either do not exist, or are not visible.")
+        raise OSM::APIPreconditionFailedError, "Way #{id} requires the nodes with id in (#{missing.join(',')}), which either do not exist, or are not visible."
       end
     end
 
@@ -222,7 +241,7 @@ class Way < ActiveRecord::Base
       lock!
       check_consistency(self, new_way, user)
       rels = Relation.joins(:relation_members).where(:visible => true, :current_relation_members => { :member_type => "Way", :member_id => id }).order(:id)
-      raise OSM::APIPreconditionFailedError.new("Way #{id} is still used by relations #{rels.collect(&:id).join(',')}.") unless rels.empty?
+      raise OSM::APIPreconditionFailedError, "Way #{id} is still used by relations #{rels.collect(&:id).join(',')}." unless rels.empty?
 
       self.changeset_id = new_way.changeset_id
       self.changeset = new_way.changeset
@@ -242,7 +261,7 @@ class Way < ActiveRecord::Base
     nds.map! do |node_id|
       if node_id < 0
         new_id = id_map[:node][node_id]
-        raise OSM::APIBadUserInput.new("Placeholder node not found for reference #{node_id} in way #{id.nil? ? placeholder_id : id}") if new_id.nil?
+        raise OSM::APIBadUserInput, "Placeholder node not found for reference #{node_id} in way #{id.nil? ? placeholder_id : id}" if new_id.nil?
         new_id
       else
         node_id
index 30d9013565eb9ebf3c78f795e9a51ae7c84304b4..5c09cd740cefc92b442ed4dcff59733e6c310aa6 100644 (file)
@@ -1,3 +1,21 @@
+# == Schema Information
+#
+# Table name: current_way_nodes
+#
+#  way_id      :integer          not null, primary key
+#  node_id     :integer          not null
+#  sequence_id :integer          not null, primary key
+#
+# Indexes
+#
+#  current_way_nodes_node_idx  (node_id)
+#
+# Foreign Keys
+#
+#  current_way_nodes_id_fkey       (way_id => current_ways.id)
+#  current_way_nodes_node_id_fkey  (node_id => current_nodes.id)
+#
+
 class WayNode < ActiveRecord::Base
   self.table_name = "current_way_nodes"
   self.primary_keys = "way_id", "sequence_id"
index 99d435d33a7d78dec9e00af3f38d263d57b2cfc5..8ef75f38e21698b99bb24b63e2cce6d6f0def5e1 100644 (file)
@@ -1,3 +1,16 @@
+# == Schema Information
+#
+# Table name: current_way_tags
+#
+#  way_id :integer          not null, primary key
+#  k      :string           default(""), not null, primary key
+#  v      :string           default(""), not null
+#
+# Foreign Keys
+#
+#  current_way_tags_id_fkey  (way_id => current_ways.id)
+#
+
 class WayTag < ActiveRecord::Base
   self.table_name = "current_way_tags"
   self.primary_keys = "way_id", "k"
index ace586ae54cd25d64e987b1164d03fa7a3defcb5..a3b7a224091f66ab9b18f971e6795be211e0a5c9 100644 (file)
@@ -62,7 +62,7 @@ atom_feed(:language => I18n.locale, :schema_date => 2009,
                 td.table :cellpadding => "0" do |table|
                   changeset.tags.sort.each do |tag|
                     table.tr do |tr|
-                      tr.td << "#{h(tag[0])} = #{auto_link(h(tag[1]))}"
+                      tr.td << "#{h(tag[0])} = #{linkify(h(tag[1]))}"
                     end
                   end
                 end
index 756464aa26ac79116c23219b090b5f2521069da5..d6af432fb01d485adfa7cdc7ec6585fbd8fdb9b0 100644 (file)
     <%= render :partial => 'diary_list_entry', :collection => @entries %>
   <% end %>
 
-  <% if @entries.size < @page_size -%>
-    <%= t('diary_entry.list.older_entries') %>
-  <% else -%>
-    <%= link_to t('diary_entry.list.older_entries'), @params.merge(:page => @page + 1 ) %>
-  <% end -%>
-
-  |
-
-  <% if @page > 1 -%>
-    <%= link_to t('diary_entry.list.newer_entries'), @params.merge(:page => @page - 1) %>
-  <% else -%>
-    <%= t('diary_entry.list.newer_entries') %>
-  <% end -%>
+  <div class="pagination">
+    <% if @entries.size < @page_size -%>
+      <%= t('diary_entry.list.older_entries') %>
+    <% else -%>
+      <%= link_to t('diary_entry.list.older_entries'), @params.merge(:page => @page + 1 ) %>
+    <% end -%>
+
+    |
+
+    <% if @page > 1 -%>
+      <%= link_to t('diary_entry.list.newer_entries'), @params.merge(:page => @page - 1) %>
+    <% else -%>
+      <%= t('diary_entry.list.newer_entries') %>
+    <% end -%>
+  </div>
 <% end %>
 
 <% unless params[:friends] or params[:nearby] -%>
index 377d55e9dedf821501c396855e70e0162d55261c..bf9f78b4376c3774129afd2d05e8f9c5a14bbe86 100644 (file)
@@ -7,7 +7,6 @@
   <%= stylesheet_link_tag "print-#{dir}", :media => "print" %>
   <%= stylesheet_link_tag "leaflet-all", :media => "screen, print" %>
   <!--[if IE]>
-    <%= stylesheet_link_tag "large-#{dir}", :media => "screen" %>
     <%= favicon_link_tag "favicon.ico" %>
   <![endif]-->
   <% [57, 60, 72, 76, 114, 120, 144, 152, 180].each do |size| -%>
@@ -18,7 +17,7 @@
   <%= favicon_link_tag "favicon-96x96.png", :rel => "icon", :sizes => "96x96", :type => "image/png" %>
   <%= favicon_link_tag "android-chrome-192x192.png", :rel => "icon", :sizes => "192x192", :type => "image/png" %>
   <%= favicon_link_tag "favicon-16x16.png", :rel => "icon", :sizes => "16x16", :type => "image/png" %>
-  <%= tag("link", { :rel => "mask-icon", :href => asset_path("tag-icon.svg"), :color => "#7ebc6f" }) %>
+  <%= tag("link", { :rel => "mask-icon", :href => asset_path("tab-icon.svg"), :color => "#7ebc6f" }) %>
   <%= tag("link", { :rel => "manifest", :href => asset_path("manifest.json") }) %>
   <%= tag("meta", { :name => "msapplication-config", :content => asset_path("browserconfig.xml") }) %>
   <%= tag("meta", { :name => "msapplication-TileColor", :content => "#00a300" }) %>
   <%= opengraph_tags(@title) %>
   <% if flash[:piwik_goal] -%>
   <%= tag("meta", :name => "piwik-goal", :content => flash[:piwik_goal]) %>
-  <% end -%>  
+  <% end -%>
   <%= style_rules %>
   <%= yield :head %>
   <%= yield :auto_discovery_link_tag %>
   <%= csrf_meta_tag %>
-  <title><%= t 'layouts.project_name.title' %><%= ' | ' + @title if @title %></title>
+  <title><%= @title + ' | ' if @title %><%= t 'layouts.project_name.title' %></title>
 <% end %>
index 752d1cd017740bc9f83bd9b9c01ce68fee263e62..169e5662aaedd4448b9c905072ea040fd14fca11 100644 (file)
@@ -11,7 +11,7 @@
 <% end %>
 
 <%= error_messages_for current_user %>
-<%= form_for current_user, :url => { :action => :account }, :html => { :multipart => true, :id => 'accountForm', :class => 'standard-form', :autocomplete => :off } do |f| %>
+<%= form_for current_user, :url => { :action => :account }, :method => :post, :html => { :multipart => true, :id => 'accountForm', :class => 'standard-form', :autocomplete => :off } do |f| %>
   <fieldset>
     <div class="form-row">
       <label class="standard-label"><%= t 'user.new.display name' %></label>
                 <%= t 'user.account.replace image' %>
                 <span class="form-help deemphasize"><%= t 'user.account.image size hint' %></span>
             </label>
-            <%= f.file_field :image, :onchange => "$('#image_action_new').prop('checked', true)" %>
+            <%= f.file_field :image %>
           </li>
         <% else %>
         <li>
             <%= t 'user.account.new image' %>
             <span class="form-help deemphasize"><%= t 'user.account.image size hint' %></span>
           </label>
-          <%= f.file_field :image, :onchange => "$('#image_action_new').prop('checked', true)" %>
+          <%= f.file_field :image %>
         </li>
         <% end %>
         <li>
index 4cb94374ade7f47069d80448106efad3320194c2..895bd98b6fef24b5fc4993578dbc92e903e7aa43 100644 (file)
@@ -2,7 +2,7 @@
   <h1><%= t 'user.reset_password.heading', :user => current_user.display_name %></h1>
 <% end %>
 
-<%= error_messages_for :user %>
+<%= error_messages_for current_user %>
 
 <%= form_tag do %>
 <%= hidden_field_tag(:token, params[:token]) %>
diff --git a/app/views/user/save.html.erb b/app/views/user/save.html.erb
deleted file mode 100644 (file)
index 7134a16..0000000
+++ /dev/null
@@ -1 +0,0 @@
-<%= current_user.email %>
index 7bdf169bf1bcf971b7e7ab64517f3c88bd17e3ed..ce53c3f02df3dc4cd17ae729b55e05fa64c67a8a 100644 (file)
@@ -1,6 +1,18 @@
-sotm2017:
-  id: sotm2017
-  alt: State of the Map 2017
-  link: http://2017.stateofthemap.org/
-  img: banners/banner-sotm-2017.png
-  enddate: 2017-aug-27
+sotmasia2017:
+  id: sotmasia2017
+  alt: State of the Map Asia 2017
+  link: http://stateofthemap.asia/
+  img: banners/sotmasia-2017-banner.png
+  enddate: 2017-sep-25
+sotmus2017:
+  id: sotmus2017
+  alt: State of the Map US 2017
+  link: https://2017.stateofthemap.us/
+  img: banners/banner-sotmus2017.png
+  enddate: 2017-oct-20
+osmfmembership2017:
+  id: osmfmembership2017
+  alt: Join the OpenStreetMap Foundation
+  link: https://blog.openstreetmap.org/2017/09/25/join-the-openstreetmap-foundation-now-and-help-shape-the-future-of-the-project/
+  img: banners/osmf-membership-drive-2017.png
+  enddate: 2017-nov-11
index 171198560fcd3affff765799a1cfb64c32089fee..cac5315775258a68f5e18885605d3fb1b758319e 100644 (file)
@@ -1,5 +1,5 @@
 # Load the Rails application.
-require File.expand_path("../application", __FILE__)
+require_relative "application"
 
 # Initialize the Rails application.
 Rails.application.initialize!
index 9101bb1ebc49485db70919089643860909c67e04..8e7213a9d35dd080ffe4d2798db9d0c7a879afce 100644 (file)
@@ -12,6 +12,20 @@ Rails.application.configure do
   # Show full error reports.
   config.consider_all_requests_local = true
 
+  # Enable/disable caching. By default caching is disabled.
+  if Rails.root.join("tmp", "caching-dev.txt").exist?
+    config.action_controller.perform_caching = true
+
+    config.cache_store = :memory_store
+    config.public_file_server.headers = {
+      "Cache-Control" => "public, max-age=#{2.days.seconds.to_i}"
+    }
+  else
+    config.action_controller.perform_caching = false
+
+    config.cache_store = :null_store
+  end
+
   # Don't care if the mailer can't send.
   config.action_mailer.raise_delivery_errors = false
 
index e421abc58a82be4b7d8a266929e8767eedafa9cb..c4c98ad48fc3de6a72bbbf830fac696e998cc5a8 100644 (file)
@@ -14,6 +14,11 @@ Rails.application.configure do
   config.consider_all_requests_local       = false
   config.action_controller.perform_caching = true
 
+  # Attempt to read encrypted secrets from `config/secrets.yml.enc`.
+  # Requires an encryption key in `ENV["RAILS_MASTER_KEY"]` or
+  # `config/secrets.yml.key`.
+  config.read_encrypted_secrets = true
+
   # Disable serving static files from the `/public` folder by default since
   # Apache or NGINX already handles this.
   config.public_file_server.enabled = ENV["RAILS_SERVE_STATIC_FILES"].present?
@@ -57,7 +62,7 @@ Rails.application.configure do
 
   # Use a real queuing backend for Active Job (and separate queues per environment)
   # config.active_job.queue_adapter     = :resque
-  # config.active_job.queue_name_prefix = "rails50_#{Rails.env}"
+  # config.active_job.queue_name_prefix = "openstreetmap_#{Rails.env}"
   config.action_mailer.perform_caching = false
 
   # Configure caching of static assets
index 5c83c045d777266178e66ce2f19d9e61fc470005..8eda290c57d2e1d7c5d6fe9cabc21df2155d9d21 100644 (file)
@@ -1,5 +1,5 @@
 begin
   BANNERS = YAML.load_file(Rails.root.join("config", "banners.yml")).deep_symbolize_keys
-rescue
+rescue StandardError
   BANNERS = {}.freeze
 end
index 59fe4225d810443cfe75949cc049a111d36a8736..f30a4b86c3a6631e8e667f0ad1074df981662faf 100644 (file)
@@ -1,5 +1,5 @@
 if defined?(CSP_REPORT_URL)
-  policy = {
+  csp_policy = {
     :default_src => %w['self'],
     :child_src => %w['self'],
     :connect_src => %w['self'],
@@ -9,19 +9,26 @@ if defined?(CSP_REPORT_URL)
     :img_src => %w['self' data: www.gravatar.com *.wp.com *.tile.openstreetmap.org *.tile.thunderforest.com *.openstreetmap.fr],
     :media_src => %w['none'],
     :object_src => %w['self'],
-    :plugin_types => %w['none'],
+    :plugin_types => %w[],
     :script_src => %w['self'],
     :style_src => %w['self' 'unsafe-inline'],
     :report_uri => [CSP_REPORT_URL]
   }
 
-  policy[:script_src] << PIWIK["location"] if defined?(PIWIK)
+  csp_policy[:img_src] << PIWIK["location"] if defined?(PIWIK)
+  csp_policy[:script_src] << PIWIK["location"] if defined?(PIWIK)
 else
-  policy = SecureHeaders::OPT_OUT
+  csp_policy = SecureHeaders::OPT_OUT
 end
 
+cookie_policy = {
+  :secure => SecureHeaders::OPT_OUT,
+  :httponly => SecureHeaders::OPT_OUT
+}
+
 SecureHeaders::Configuration.default do |config|
   config.hsts = "max-age=0"
   config.csp = SecureHeaders::OPT_OUT
-  config.csp_report_only = policy
+  config.csp_report_only = csp_policy
+  config.cookies = cookie_policy
 end
index 0f9e899704b0223960085e20457233394edd4849..8a0fd8f03a98eb67b8e91f91bb72a6a1898dc796 100644 (file)
@@ -2,6 +2,8 @@
 
 if defined?(MEMCACHE_SERVERS)
   Rails.application.config.session_store :mem_cache_store, :memcache_server => MEMCACHE_SERVERS, :namespace => "rails:session", :key => "_osm_session"
-else
+elsif Rails.application.config.cache_store != :null_store
   Rails.application.config.session_store :cache_store, :key => "_osm_session"
+else
+  Rails.application.config.session_store :cookie_store, :key => "_osm_session"
 end
diff --git a/config/initializers/streaming.rb b/config/initializers/streaming.rb
deleted file mode 100644 (file)
index 0c27ba2..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-# Hack ActionController::DataStreaming to allow streaming from a file handle
-module ActionController
-  module DataStreaming
-    alias old_send_file send_file
-
-    def send_file(file, options = {})
-      if file.is_a?(File) || file.is_a?(Tempfile)
-        headers["Content-Length"] ||= file.size.to_s
-
-        options[:filename] ||= File.basename(file.path) unless options[:url_based_filename]
-        send_file_headers! options
-
-        self.status = options[:status] || 200
-        self.content_type = options[:content_type] if options.key?(:content_type)
-        self.response_body = file
-      else
-        headers["Content-Length"] ||= File.size(file).to_s
-
-        old_send_file(file, options)
-      end
-    end
-  end
-end
index 33725e95fd22b9053f75ef6626aa1af781ebe947..cf733efd119893abd444b9d75c53b3f09e77d4a4 100644 (file)
@@ -5,7 +5,7 @@
 
 # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
 ActiveSupport.on_load(:action_controller) do
-  wrap_parameters format: [:json] if respond_to?(:wrap_parameters)
+  wrap_parameters format: [:json]
 end
 
 # To enable root element in JSON for ActiveRecord objects.
index e66a0cdf8b8c0d2c6c9a9841b1a2ff7f06cef042..c0989fcfcbae5115e624f4939deb5e98baaac61a 100644 (file)
@@ -2,6 +2,7 @@
 # Exported from translatewiki.net
 # Export driver: phpyaml
 # Author: Arnobarnard
+# Author: Biggs ZA
 # Author: Firefishy
 # Author: Fwolff
 # Author: Naudefj
@@ -15,20 +16,37 @@ af:
     models:
       acl: Toegangsbeheerlys
       changeset: Wysigingstel
+      changeset_tag: Wysigingstel-merker
       country: Land
       diary_comment: Dagboekopmerking
       diary_entry: Dagboekinskrywing
       friend: Vriend
       language: Taal
       message: Boodskap
-      node: Node
+      node: Knooppunt
+      node_tag: Knooppuntmerker
       notifier: Kennisgewer
-      old_node: Ou Node
+      old_node: Ou Knooppunt
+      old_node_tag: Ou knooppuntmerker
+      old_relation: Ou Verband
+      old_relation_member: Ou Verbandslid
+      old_relation_tag: Ou Verbandsmerker
+      old_way: Ou pad
+      old_way_node: Ou weg-knooppunt
+      old_way_tag: Ou weg-merker
+      relation: Verband
+      relation_member: Verbandslid
+      relation_tag: Verbandsmerker
       session: Sessie
       trace: Spoor
+      tracepoint: Natrekpunt
+      tracetag: Natrekmerker
       user: Gebruiker
       user_preference: Gebruikersvoorkeure
+      user_token: Gebruikerskoepon
       way: Weg
+      way_node: Weg-knooppunt
+      way_tag: Weg-merker
     attributes:
       diary_comment:
         body: Teks
@@ -48,57 +66,147 @@ af:
         size: Grootte
         latitude: Breedtegraad
         longitude: Lengtegraad
-        public: Openbaar
+        public: Publiek
         description: Beskrywing
       message:
-        sender: Afsender
+        sender: Sender
         title: Onderwerp
         body: Teks
         recipient: Ontvanger
       user:
         email: E-pos
-        active: Aktief
-        display_name: Vertoon Naam
+        active: Bedrywig
+        display_name: Skermnaam
         description: Beskrywing
         languages: Tale
         pass_crypt: Wagwoord
   editor:
+    default: Verstek (tans %{name})
+    potlatch:
+      name: Potknip 1
+      description: Potknip 1 (aanlynredigeerder)
     id:
       name: iD
+      description: iD (aanlynredigeerder)
+    potlatch2:
+      name: Potknip 2
+      description: Potknip 2 (aanlynredigeerder)
+    remote:
+      name: Afstandsbeheer
+      description: Afstandsbeheer (JOSM of Merkaartor)
   browse:
+    created: Geskep
+    closed: Gesluit
+    created_html: Geskep <abbr titel='%{title}'>%{time} gelede</abbr>
+    closed_html: Geslote <abbr titel='%{title}'>%{time} gelede</abbr>
+    created_by_html: Geskep <abbr titel='%{title}'>%{time} gelede</abbr> deur %{user}
+    deleted_by_html: Geskrap <abbr titel='%{title}'>%{time} gelede</abbr> deur %{user}
+    edited_by_html: Geredigeer <abbr titel='%{title}'>%{time} gelede</abbr> deur %{user}
+    closed_by_html: Gesluit <abbr titel='%{title}'>%{time} gelede</abbr> deur %{user}
     version: Weergawe
+    in_changeset: Wysigingsstel
+    anonymous: anoniem
+    no_comment: (geen kommentaar)
+    part_of: Deel van
     download_xml: Laai XML af
-    view_history: Sien geskiedenis
-    view_details: Sien detail
+    view_history: Beskou Geskiedenis
+    view_details: Bekyk Detail
     location: 'Ligging:'
     changeset:
+      title: 'Wysigingsstel: %{id}'
+      belongs_to: Skrywer
+      node: Knooppunte (%{count})
+      node_paginated: Knooppunte (%{x}-%{y} van %{count})
+      way: Weë (%{count})
+      way_paginated: Weë (%{x}-%{y} van %{count})
+      relation: Verwantskappe (%{count})
+      relation_paginated: Verwantskappe (%{x}-%{y} of %{count})
+      comment: Kommentaar (%{count})
+      hidden_commented_by: Verskuilde kommentaar deur %{user} <abbr title='%{exact_time}'>%{when}
+        ago</abbr>
+      commented_by: Kommentaar deur %{user} <abbr title='%{exact_time}'>%{when} ago</abbr>
+      changesetxml: Wysigingsstel XML
+      osmchangexml: osmWysiging XML
+      feed:
+        title: Wysigingsstel %{id}
+        title_comment: Wysigingstel %{id} - %{comment}
+      join_discussion: Meld aan en gesels saam
       discussion: Bespreking
+    node:
+      title: 'Knooppunt: %{name}'
+      history_title: 'Knooppuntgeskiedenis: %{name}'
+    way:
+      title: 'Weg: %{name}'
+      history_title: 'Weggeskiedenis: %{name}'
+      nodes: Knooppunte
+      also_part_of:
+        one: gedeelte van weg %{related_ways}
+        other: gedeelte van weë %{related_ways}
+    relation:
+      title: 'Verwantskap: %{name}'
+      history_title: 'Verwantskapgeskiedenis: %{name}'
+      members: Lede
     relation_member:
       entry_role: '%{type} %{name} as %{role}'
       type:
-        node: Node
+        node: Knooppunt
         way: Weg
         relation: Verwantskap
     containing_relation:
       entry: Verwantskap %{relation_name}
       entry_role: Verwantskap %{relation_name} (as %{relation_role})
     not_found:
-      sorry: 'Jammer, %{type} #%{id} kan nie gevind word nie.'
+      sorry: 'Jammer, %{type} #%{id} blyk onverkrygbaar.'
       type:
-        node: node
+        node: knooppunt
         way: weg
         relation: verwantskap
-        changeset: veranderingstel
+        changeset: wysigingstel
+        note: nota
     timeout:
-      sorry: Jammer, dit het te lank geneem om data vir die %{type} met die id %{id}
+      sorry: Jammer, die gegewens vir die %{type} met die id %{id} neem te lank om
         op te soek.
       type:
-        node: node
+        node: knooppunt
+        way: weg
+        relation: verband
+        changeset: wysigingstel
+        note: nota
+    redacted:
+      redaction: Redigering %{id}
+      message_html: Weergawe %{version} van hierdie %{type} kan nie vertoon word nie,
+        synde dit geredigeer is. Raadpleeg asseblief %{redaction_link} vir besonderhede.
+      type:
+        node: knooppunt
+        way: weg
+        relation: verband
     start_rjs:
+      feature_warning: Laai tans %{num_features} kenmerke wat u internetblaaier kan
+        vertraag of laat hang. Is u seker u wil hierdie data vertoon?
       load_data: Laai data
-      loading: Laai...
+      loading: Laai tans…
     tag_details:
-      tags: Oortjies
+      tags: Merkers
+      wiki_link:
+        key: Die wiki-beskrywingsblad vir %{key} tag
+        tag: Die wikibeskrywingsblad vir die %{key}=%{value} merker
+      wikidata_link: Die %{page} item op Wikidata
+      wikipedia_link: Die bladsy %{page} op Wikipedia
+      telephone_link: Skakel %{phone_number}
+    note:
+      title: 'Nota: %{id}'
+      new_note: Nuwe Nota
+      description: Beskrywing
+      open_by_anonymous: Anoniem het <abbr title='%{exact_time}'>%{when} ago</abbr>
+        geskep
+      commented_by: Kommentaar deur %{user} <abbr title='%{exact_time}'>%{when} ago</abbr>
+      commented_by_anonymous: Kommentaar deur anoniem <abbr title='%{exact_time}'>%{when}
+        ago</abbr>
+    query:
+      title: Bevraagteken Gidsbakens
+      introduction: Klik op die kaart om nabye bakens te ontdek.
+      nearby: Nabye kenmerke
+      enclosing: Omsluitende kenmerke
   changeset:
     changeset_paging_nav:
       showing_page: Bladsy %{page}
@@ -106,26 +214,47 @@ af:
       previous: « Vorige
     changeset:
       anonymous: Anoniem
-      no_edits: (geen wysigings)
+      no_edits: (geen redigerings)
+      view_changeset_details: Bekyk die wysigingsstel se besonderhede
     changesets:
       id: ID
-      saved_at: Gestoor op
+      saved_at: Gebêre op
       user: Gebruiker
       comment: Opmerking
       area: Gebied
+    list:
+      title: Wysigingsstel
+      empty: Geen wysigingstelle gevind nie.
+      empty_area: Geen wysigingstelle in hierdie gebied.
+      empty_user: Geen wysigingstelle deur hierdie gebruiker.
+      no_more: Geen meer wysigingstelle gevind nie.
+      no_more_area: Geen wysigingstelle in hierdie gebied nie.
+      no_more_user: Geen ander wysigingstelle deur hierdie gebruiker nie.
+      load_more: Laai nog
+    timeout:
+      sorry: Jammer, die lys wysigingstelle wat u versoek het, neem lank om uit te
+        haal.
+    rss:
+      title_all: OpenStreetMap bespreking oor wysigingstelle
+      commented_at_html: '%{when} gelede bygewerk'
+      commented_at_by_html: '%{when} gelede deur %{user} bygewerk'
+      full: Volledige bespreking
   diary_entry:
     new:
       title: Nuwe dagboekinskrywing
+      publish_button: Publiseer
     list:
       title: Gebruikersdagboeke
-      user_title: Dagboek van %{user}
+      title_friends: Dagboeke van vriende
+      title_nearby: Gebruikers in die omgewing se dagboeke
+      user_title: '%{user} se dagboek'
       in_language_title: Dagboekinkrywings in %{language}
       new: Nuwe dagboekinskrywing
-      new_title: Plaas nuwe artikel in u dagboek
+      new_title: Maak 'n nuwe inskrywing in jou dagboek
       no_entries: Geen dagboekinskrywings nie
       recent_entries: Onlangse dagboekinskrywings
-      older_entries: Ouer inskrywings
-      newer_entries: Nuwer inskrywings
+      older_entries: Vorige Inskrywings
+      newer_entries: Jonger inskrywings
     edit:
       title: Wysig dagboekinskrywing
       subject: 'Onderwerp:'
@@ -134,111 +263,139 @@ af:
       location: 'Ligging:'
       latitude: 'Breedtegraad:'
       longitude: 'Lengtegraad:'
-      use_map_link: gebruik kaart
+      use_map_link: benut kaart
       save_button: Stoor
       marker_text: Ligging van dagboekinskrywing
     view:
       title: '%{user} se dagboek | %{title}'
-      user_title: Dagboek van %{user}
-      leave_a_comment: Los 'n opmerking
-      login_to_leave_a_comment: U moet eers %{login_link} alvorens u kommentaar kan
-        lewer
+      user_title: '%{user} se dagboek'
+      leave_a_comment: Lewer kommentaar
+      login_to_leave_a_comment: '%{login_link} om kommentaar te lewer'
       login: Meld aan
       save_button: Stoor
     no_such_entry:
-      title: Die opgevraagde dagboekinskrywing bestaan nie
-      heading: Die inskrywing met id %{id} bestaan nie
-      body: Jammer, daar is geen dagboekinskrywing of kommentaar met die id %{id}
-        nie. Kontroleer u spelling, of miskien is die skakel waarop u gekliek het
-        verkeerd.
+      title: Geen só 'n dagboekinskrywing
+      heading: 'Geen inskrywing met die id: %{id}'
+      body: Jammer, geen dagboekinskrywing of kommentaar met die id %{id} bestaan
+        nie. Gaan u spelling na, of u het moontlik op 'n foutiewe skakel geklik.
     diary_entry:
-      posted_by: Gepos deur %{link_user} op %{created} in %{language_link}
-      comment_link: Lewer kommentaar op hierdie bydrae
-      reply_link: Antwoord op hierdie bydrae
+      posted_by: Plasing deur %{link_user} op %{created} in %{language_link}
+      comment_link: Lewer hierop kommentaar
+      reply_link: Antwoord hierop
       comment_count:
-        one: 1 reaksie
-        other: '%{count} reaksies'
-      edit_link: Wysig hierdie inskrywing
-      hide_link: Versteek die inskrywing
-      confirm: Bevestig
+        zero: Geen opmerkings
+        one: '%{count} opmerking'
+        other: '%{count} opmerkings'
+      edit_link: Redigeer hierdie inskrywing
+      hide_link: Steek dié inskrywing weg
+      confirm: Bekragtig
     diary_comment:
       comment_from: Kommentaar van %{link_user} op %{comment_created_at}
-      hide_link: Versteek die opmerking
-      confirm: Bevestig
+      hide_link: Steek die opmerking weg
+      confirm: Bekragtig
     location:
       location: 'Ligging:'
       view: Wys
-      edit: Wysig
+      edit: Redigeer
     feed:
       user:
-        title: OpenStreetMap dagboekinskrywings van %{user}
-        description: Onlangse OpenStreetMap dagboekinskrywings van %{user}
+        title: OpenStreetMap-dagboekinskrywings deur %{user}
+        description: Onlangse OpenStreetMap-dagboekinskrywings deur %{user}
       language:
         title: OpenStreetMap dagboekinskrywings in %{language_name}
-        description: Onlangse dagboekinskrywings van OpenStreetMap-gebruikers in %{language_name}
+        description: Onlangse dagboekinskrywings deur OpenStreetMap-gebruikers in
+          %{language_name}
       all:
-        title: OpenStreetMap dagboekinskrywings
-        description: Onlangse dagboekinskrywings van OpenStreetMap-gebruikers
+        title: OpenStreetMap-dagboekinskrywings
+        description: Onlangse dagboekinskrywings deur OpenStreetMap-gebruikers
     comments:
+      post: Plasing
       when: Wanneer
+      comment: Kommentaar
+      ago: '%{ago} gelede'
+      newer_comments: Jongste Kommentaar
+      older_comments: Ouer Kommentaar
   export:
+    title: Voer Uit
     start:
-      area_to_export: Area om te eksporteer
-      manually_select: Kies 'n ander gebied handmatig
-      format_to_export: Lêerformaat
+      area_to_export: Area om uit te voer
+      manually_select: Kies self 'n ander area
+      format_to_export: Formaat om uit te voer
       osm_xml_data: OpenStreetMap XML-data
-      embeddable_html: HTML-kode
+      map_image: Kaartbeeld (wys standaardlaag)
+      embeddable_html: Versteekbare HTML-kode
       licence: Lisensie
-      export_details: OpenStreetMap se data is gelisensieer onder die <a href="http://creativecommons.org/licenses/by-sa/2.0/deed.af">Creative
-        Commons Erkenning-Insgelyks Deel 2.0 lisensie</a>.
+      export_details: OpenStreetMap se data word ingevolge die <a href="http://opendatacommons.org/licenses/odbl/1.0/"></a>
+        (ODbL) gelisensieer.
+      too_large:
+        advice: 'Ingeval die uitvoering hierbo misluk, oorweeg asseblief een van die
+          volgende bronne:'
+        body: Hierdie gebied is te groot om as OpenStreenMap XML Data uitgevoer te
+          word. Verdiep asseblief die kamerablik of kies 'n kleiner gebied. Wend andersins
+          een van die bronne hieronder aan om massadata af te laai.
+        planet:
+          title: Planeet OSM
       options: Voorkeure
       format: Formaat
       scale: Skaal
       max: maksimum
-      image_size: 'Prentgrootte:'
-      zoom: Zoom
+      image_size: Beeldgrootte
+      zoom: Vergroot
       add_marker: Plaas 'n merker op die kaart
       latitude: 'Breedte:'
       longitude: 'Lengte:'
-      output: Afvoer
-      export_button: Eksporteer
+      output: Uitset
+      paste_html: Plak HTML om in die webblad te versteek
+      export_button: Uitvoer
   geocoder:
     search:
       title:
-        latlon: Resultate vanaf <a href="http://openstreetmap.org/">intern</a>
-        us_postcode: Resultate vanaf <a href="http://geocoder.us/">Geocoder.us</a>
-        uk_postcode: Resultate vanaf <a href="http://www.npemap.org.uk/">NPEMap /
-          FreeThe Postcode</a>
-        ca_postcode: Resultate vanaf <a href="http://geocoder.ca/">Geocoder.CA</a>
-        osm_nominatim: Resultate vanaf <a href="http://nominatim.openstreetmap.org/">OpenStreetMap
+        latlon: Uitslae vooruitspruitend <a href="http://openstreetmap.org/">intern</a>
+        uk_postcode: Uitslae vanaf <a href="http://www.npemap.org.uk/">NPEMap / FreeThe
+          Postcode</a>
+        ca_postcode: Uitslae vanaf <a href="http://geocoder.ca/">Geocoder.CA</a>
+        osm_nominatim: Uitslae vanaf <a href="http://nominatim.openstreetmap.org/">OpenStreetMap
           Nominatim</a>
-        geonames: Resultate vanaf <a href="http://www.geonames.org/">GeoNames</a>
-        geonames_reverse: Resultate vanaf <a href="http://www.geonames.org/">GeoNames</a>
+        geonames: Uitslae vanaf <a href="http://www.geonames.org/">GeoNames</a>
+        geonames_reverse: Uitslae vanaf <a href="http://www.geonames.org/">GeoNames</a>
     search_osm_nominatim:
       prefix:
         aerialway:
-          cable_car: Kabelkar
+          cable_car: Sweefspoor
         aeroway:
+          aerodrome: Vliegveld
           gate: Hek
+          helipad: Helikopterplatform
+          runway: Aanloopbaan
+          taxiway: Rybaan
+          terminal: Terminaal
         amenity:
+          animal_shelter: Dierebeskermingsvereniging
           arts_centre: Kunssentrum
           atm: OTM
           bank: Bank
           bar: Kroeg
-          bench: Bank
+          bbq: Braai
+          bench: Bankie
           bicycle_parking: Fietsparkering
-          bicycle_rental: Fietsverhuring
+          bicycle_rental: Fietshuur
+          biergarten: Biertuin
+          boat_rental: Boothuur
           brothel: Bordeel
           bureau_de_change: Wisselkantoor
           bus_station: Bushalte
           cafe: Kafee
-          car_rental: Motorverhuring
+          car_rental: Motorverhuurder
+          car_sharing: Saam-ry
           car_wash: Karwas
-          casino: Casino
-          cinema: Bioskoop
+          casino: Dobbelhuis
+          charging_station: Herlaaistasie
+          childcare: Kindersorg
+          cinema: Rolprentteater
           clinic: Kliniek
+          clock: Klok
           college: Kollege
-          community_centre: Gemeenskap-sentrum
+          community_centre: Gemeenskapsentrum
           courthouse: Hof
           crematorium: Krematorium
           dentist: Tandarts
@@ -249,12 +406,15 @@ af:
           embassy: Ambassade
           emergency_phone: Noodtelefoon
           fast_food: Wegneemetes
-          ferry_terminal: Veerterminaal
+          ferry_terminal: Pontterminaal
           fire_hydrant: Brandkraan
           fire_station: Brandweerstasie
+          food_court: Kosarea
           fountain: Fontein
           fuel: Brandstof
+          gambling: Dobbelary
           grave_yard: Begraafplaas
+          gym: Fiksheidsentrum / Gim
           health_centre: Gesondheidsentrum
           hospital: Hospitaal
           hunting_stand: Jagtoring
@@ -263,20 +423,23 @@ af:
           library: Biblioteek
           market: Mark
           marketplace: Markplein
+          monastery: Monnikeklooster
+          motorcycle_parking: Motorfietsparkering
           nightclub: Nagklub
           nursery: Kleuterskool
-          nursing_home: Verpleeghuis
+          nursing_home: Verpleging- en versorgingshuis
           office: Kantoor
-          parking: Parkade
+          parking: Parkering
+          parking_entrance: Parkeeringang
           pharmacy: Apteek
-          place_of_worship: Plek van aanbidding
+          place_of_worship: Plek van Aanbidding
           police: Polisie
           post_box: Posbus
           post_office: Poskantoor
           preschool: Kleuterskool
           prison: Tronk
           pub: Kroeg
-          public_building: Openbare gebou
+          public_building: Openbare Gebou
           reception_area: Ontvangsarea
           recycling: Herwinningspunt
           restaurant: Restaurant
@@ -285,22 +448,30 @@ af:
           school: Skool
           shelter: Skuiling
           shop: Winkel
+          shower: Stort
+          social_centre: Maatskaplike Sentrum
           social_club: Sosiale klub
-          studio: Studio
+          studio: Ateljee
           swimming_pool: Swembad
           taxi: Taxi
-          telephone: Openbare telefoon
+          telephone: Openbare Telefoon
           theatre: Teater
           toilets: Toilette
           townhall: Stadsaal
           university: Universiteit
           veterinary: Veearts
-          waste_basket: Asblik
+          village_hall: Dorpsaal
+          waste_basket: Snippermandjie
+          waste_disposal: Stortingsterrein
           youth_centre: Jeugsentrum
         boundary:
           administrative: Administratiewe grens
-          national_park: Nasionale park
+          national_park: Nasionale Park
+          protected_area: Beskermingsgebied
         bridge:
+          aqueduct: Waterbrug
+          suspension: Hangbrug
+          viaduct: Viaduk
           "yes": Brug
         building:
           "yes": Gebou
@@ -309,36 +480,52 @@ af:
           carpenter: Skrynwerker
           electrician: Elektrisiën
           gardener: Tuinier
+          painter: Verwer
           photographer: Fotograaf
           plumber: Loodgieter
           shoemaker: Skoenmaker
+          tailor: Snyer
+          "yes": Handwerkwinkel
+        emergency:
+          ambulance_station: Ambulansstasie
+          defibrillator: Defibrillator
+          landing_site: Noodlandingsarea
+          phone: Noodtelefoon
         highway:
+          abandoned: Verlate Snelweg
           bridleway: Ruiterpad
+          bus_guideway: Toegewyde busbaan
           bus_stop: Bushalte
           construction: Snelweg in aanbou
           cycleway: Fietspad
+          elevator: Hysbak
           emergency_access_point: Noodtoeganspunt
           footway: Voetpad
           ford: Drif
+          milestone: Mylpaal
           motorway: Snelweg
           motorway_junction: Snelwegknooppunt
           path: Pad
-          pedestrian: Voetpad
+          pedestrian: Voetgangerspad
           platform: Platform
-          primary: Primêre pad
-          primary_link: Primêre pad
+          primary: Primêre Pad
+          primary_link: Primêre Pad
+          proposed: Voorgestelde pad
           raceway: Renbaan
           residential: Residensiële straat
+          rest_area: Rusarea
           road: Pad
-          secondary: Sekondêre pad
-          secondary_link: Sekondêre pad
+          secondary: Sekondêre Pad
+          secondary_link: Sekondêre Pad
           service: Dienspad
-          services: Snelweg Dienste
-          speed_camera: Spoedkamera
+          services: Snelwegdienste
+          speed_camera: Snelheidskamera
           steps: Trappe
-          street_lamp: Straatlamp
-          tertiary: Tersiêre pad
+          street_lamp: Straatlig
+          tertiary: Tersiêre Pad
+          tertiary_link: Tersiêre pad
           track: Spoor
+          traffic_signals: Verkeerstekens
           trail: Wandelpad
           trunk: Hoofroete
           trunk_link: Hoofroete
@@ -348,102 +535,165 @@ af:
         historic:
           archaeological_site: Argeologiese werf
           battlefield: Slagveld
+          boundary_stone: Grenspaal
           building: Historiese gebou
+          bunker: Bomskuiling
           castle: Kasteel
           church: Kerk
+          city_gate: Stadspoort
+          citywalls: Stadsmure
+          fort: Fort
+          heritage: Erfenisterrein
           house: Huis
           icon: Ikoon
           manor: Landgoed
           memorial: Gedenkteken
           mine: Myn
           monument: Monument
+          roman_road: Romeinse pad
           ruins: Ruïnes
+          stone: Steen
+          tomb: Graf
           tower: Toring
-          wayside_cross: Kruis langs die pad
-          wayside_shrine: Altaar langs die pad
+          wayside_cross: Padkruis
+          wayside_shrine: Padaltaar
           wreck: Wrak
+        junction:
+          "yes": Verkeersaansluiting
         landuse:
           allotments: Volkstuine
+          basin: Kom
           cemetery: Begraafplaas
-          commercial: Kommersiële gebied
+          commercial: Handelsarea
+          conservation: Natuurbewaring
           construction: Konstruksie
           farm: Plaas
           farmland: Plaasgrond
           farmyard: Plaaswerf
           forest: Woud
+          garages: Vulstasies
           grass: Gras
-          industrial: Industriële gebied
+          industrial: Nywerheidsgebied
           landfill: Stortingsterrein
+          meadow: Vleiweiding
           military: Militêre gebied
           mine: Myn
-          quarry: Steengroewe
+          orchard: Vrugteboord
+          quarry: Steengroef
           railway: Spoorweg
+          recreation_ground: Ontspanningsterrein
           reservoir: Reservoir
           residential: Woongebied
           retail: Kleinhandel
           vineyard: Wingerd
+          "yes": Landgebruik
         leisure:
-          beach_resort: Strandoort
-          fishing: Visvangarea
+          beach_resort: Strandoord
+          bird_hide: Voëlkykhuisie
+          club: Klub
+          dog_park: Hondepark
+          fishing: Visvanggebied
+          fitness_centre: Fiksheidsentrum
           garden: Tuin
           golf_course: Gholfbaan
-          ice_rink: Ysbaan
+          horse_riding: Perdry
+          ice_rink: Ysskaatsbaan
           marina: Marina
-          miniature_golf: Minigolf
+          miniature_golf: Mini-gholf
           nature_reserve: Natuurreservaat
           park: Park
           pitch: Sportveld
           playground: Speelgrond
-          sports_centre: Sport-sentrum
+          recreation_ground: Ontspanningsterrein
+          resort: Oord
+          sauna: Sauna
+          slipway: Glybaan
+          sports_centre: Sportsentrum
           stadium: Stadion
           swimming_pool: Swembad
           track: Atletiekbaan
           water_park: Waterspeelpark
+          "yes": Vrye tyd
+        man_made:
+          lighthouse: Vuurtoring
+          pipeline: Pypleiding
+          tower: Toring
+          works: Fabriek
+          "yes": Mensgemaak
+        military:
+          airfield: Miliêre vliegveld
+          barracks: Barakke
+          bunker: Bomskuiling
+        mountain_pass:
+          "yes": Bergpas
         natural:
           bay: Baai
           beach: Strand
           cape: Kaap
           cave_entrance: Grotingang
-          cliff: Kloof
+          cliff: Krans
           crater: Krater
+          dune: Duin
+          fell: Heuwel
           fjord: Fjord
           forest: Woud
           geyser: Geiser
           glacier: Gletser
+          grassland: Grasveld
           heath: Heide
           hill: Heuwel
           island: Eiland
           land: Land
           marsh: Moeras
+          moor: Vleiland
           mud: Modder
           peak: Piek
           point: Punt
           reef: Rif
-          ridge: Bergkam
-          rock: Rotse
-          scree: Puin
+          ridge: Bergrif
+          rock: Rots
+          saddle: Saal
+          sand: Sand
+          scree: Berghellingspuin
           scrub: Struikgewas
           spring: Bron
+          stone: Steen
           strait: Seestraat
           tree: Boom
           valley: Vallei
-          volcano: Vulkaan
+          volcano: Vuurspuwende Berg
           water: Water
-          wetland: Moeras
+          wetland: Vleiland
           wood: Bos
+        office:
+          accountant: Boekhouer
+          administrative: Administrasie
+          architect: Argitek
+          company: Maatskappy
+          estate_agent: Eiendomsagent
+          insurance: Versekeringskantoor
+          lawyer: Prokureur
+          telecommunication: Telekommunikasiekantoor
+          travel_agent: Reisagent
+          "yes": Kantoor
         place:
+          allotments: Toekennings
+          block: Blokkeer
           airport: Lughawe
           city: Stad
           country: Land
           county: Distrik
           farm: Plaas
-          hamlet: Dorpie
+          hamlet: Gehuggie
           house: Huis
           houses: Huise
           island: Eiland
           islet: Eilandjie
+          isolated_dwelling: Geïsoleerde woning
           locality: Ligging
+          moor: Vleiland
           municipality: Munisipaliteit
+          neighbourhood: Woonbuurt
           postcode: Poskode
           region: Streek
           sea: See
@@ -451,33 +701,43 @@ af:
           subdivision: Onderverdeling
           suburb: Voorstad
           town: Dorp
-          unincorporated_area: Uitgesluite Ruimte
-          village: Dorp
+          unincorporated_area: Uitgeslote Ruimte
+          village: Gehug
+          "yes": Plek
         railway:
+          abandoned: Verlate Spoorweg
           construction: Spoor in aanbou
-          disused_station: Ongebruikte spoorwegstasie
+          disused: Spoorweg in onbruik
+          disused_station: Spoorwegstasie in onbruik
           funicular: Kabelspoorweg
           halt: Treinhalte
           historic_station: Historiese spoorwegstasie
           junction: Spoorwegkruising
           level_crossing: Spooroorgang
+          light_rail: Ligte spoor
+          miniature: Miniatuur spoorweg
           monorail: Monospoor
           narrow_gauge: Smalspoorweg
-          platform: Spoorweg-platform
+          platform: Spoorwegperron
           preserved: Historiese spoorweg
+          proposed: Voorgestelde spoorlyn
           station: Spoorwegstasie
-          subway: Metrostasie
+          subway: Duikwegspoor
           subway_entrance: Ondergrondse spoorwegingang
           switch: Spoogwegpunte
+          tram: Tremspoor
           tram_stop: Tremhalte
         shop:
+          antiques: Antiek / Oudhede
           art: Kunswinkel
           bakery: Bakkery
           beauty: Skoonheidssalon
+          beverages: Drankwinkel
           bicycle: Fietswinkel
           books: Boekwinkel
+          boutique: Boutique
           butcher: Slagter
-          car: Motorwinkel
+          car: Motorhandelaar
           car_parts: Motoronderdele
           car_repair: Motorherstel
           carpet: Mat-/tapytwinkel
@@ -485,13 +745,17 @@ af:
           chemist: Apteek
           clothes: Klerewinkel
           computer: Rekenaarwinkel
-          convenience: Gemakswinkel
-          copyshop: Fotokopie-winkel
-          cosmetics: Kosmetiesewinkel
+          confectionery: Banketbakkery
+          convenience: Geriefswinkel
+          copyshop: Fotostaatwinkel
+          cosmetics: Kosmetiekwinkel
+          deli: Deli
+          department_store: Afdelingswinkel
           discount: Afslagwinkel
-          doityourself: Doen-dit-self-winkel
+          doityourself: Doen-Dit-Self-winkel
           dry_cleaning: Droogskoonmaker
           electronics: Elektronikawinkel
+          estate_agent: Eiendomsagent
           farm: Plaaswinkel
           fashion: Modewinkel
           fish: Viswinkel
@@ -501,15 +765,16 @@ af:
           furniture: Meubels
           gallery: Galery
           garden_centre: Kwekery/Tuinsentrum
-          general: Algemene winkel
-          gift: Geskenkwinkel
-          grocery: Kruideniersware-winkel
+          general: Algemene Handelaar
+          gift: Geskenkewinkel
+          greengrocer: Groentehandelaar
+          grocery: Kruidenierswinkel
           hairdresser: Haarkapper
-          hardware: Hardwarewinkel
-          hifi: Hi-Fi
+          hardware: Hardewarewinkel
+          hifi: Hoëtrou
           insurance: Versekering
           jewelry: Juwelierswinkel
-          kiosk: Kioskwinkel
+          kiosk: Kiosk
           laundry: Wassery
           mall: Winkelsentrum
           market: Mark
@@ -519,27 +784,33 @@ af:
           newsagent: Nuusagent
           optician: Oogkundige
           organic: Organiese koswinkel
-          outdoor: Buitelug-winkel
+          outdoor: Buitelugwinkel
           pet: Troeteldierwinkel
+          pharmacy: Apteek
           photo: Fotowinkel
           salon: Skoonheidssalon
+          second_hand: Tweedehandswinkel
           shoes: Skoenwinkel
           shopping_centre: Winkelsentrum
           sports: Sportwinkel
-          stationery: Skryfbehoeftes-winkel
+          stationery: Skryfbehoeftewinkel
           supermarket: Supermark
+          tailor: Snyer
           toys: Speelgoedwinkel
-          travel_agency: Reisburo
-          video: Video-winkel
+          travel_agency: Reisagentskap
+          video: Videowinkel
+          "yes": Winkel
         tourism:
           alpine_hut: Berghut
+          apartment: Woonstel
           artwork: Kunswerk
-          attraction: Attraksie
+          attraction: Trekpleister
           bed_and_breakfast: Bed en Ontbyt
           cabin: Hut
           camp_site: Kampterrein
           caravan_site: Karavaanpark
           chalet: Chalet
+          gallery: Galery
           guest_house: Gastehuis
           hostel: Jeugherberg
           hotel: Hotel
@@ -551,20 +822,32 @@ af:
           viewpoint: Uitkykpunt
           zoo: Dieretuin
         tunnel:
+          culvert: Duiksloot
           "yes": Tonnel
         waterway:
+          artificial: Kunstmatige waterweg
           boatyard: Skeepswerf
           canal: Kanaal
           dam: Dam
+          derelict_canal: Verlate Kanaal
           ditch: Sloot
           dock: Dokke
           drain: Afvoerkanaal
           lock: Sluis
           lock_gate: Sluisdeur
+          mooring: Kaai
           rapids: Stroomversnelling
           river: Rivier
           stream: Stroom
+          wadi: Droë woestynrivierbedding
           waterfall: Waterval
+          weir: Stuwal
+          "yes": Waterweg
+      admin_levels:
+        level4: Staatsgrens
+        level5: Streekgrens
+        level8: Stadsgrens
+        level9: Dorpsgrens
     description:
       title:
         geonames: Ligging vanaf <a href="http://www.geonames.org/">GeoNames</a>
@@ -574,101 +857,167 @@ af:
         places: Plekke
     results:
       no_results: Geen resultate gevind nie
-      more_results: Meer resultate
+      more_results: Nog resultate
   layouts:
     logo:
       alt_text: OpenStreetMap-logo
-    home: tuis
+    home: Keer terug na tuisoord
     logout: Meld af
     log_in: Meld aan
-    log_in_tooltip: Teken aan met 'n bestaande rekening
+    log_in_tooltip: Teken met 'n bestaande rekening aan
     sign_up: Registreer
-    sign_up_tooltip: Skep 'n rekening vir wysigings
-    edit: Wysig
+    start_mapping: Begin Karteer
+    sign_up_tooltip: Skep 'n rekening vir redigeerregte
+    edit: Redigeer
     history: Geskiedenis
-    export: Eksporteer
+    export: Voer uit
     data: Data
+    export_data: Voer data uit
     gps_traces: GPS-spore
-    gps_traces_tooltip: Beheer GPS-spore
+    gps_traces_tooltip: Bestuur GPS-spore
     user_diaries: Gebruikersdagboeke
     user_diaries_tooltip: Wys gebruikersdagboeke
-    tag_line: Die vrye wiki-wêreldkaart
+    edit_with: Redigeer met %{editor}
+    tag_line: Die Vrye Wiki-Wêreldkaart
     intro_header: Welkom by OpenStreetMap!
-    intro_text: OpenStreetMap is 'n kaart van die wêreld, geskep deur gewone mense.
-      Dis gratis om te gebruik onder 'n oop lisensie.
-    intro_2_create_account: Skep gebruikerrekening
-    osm_read_only: Die OpenStreetMap-databasis kan op die oomblik slegs gelees word
-      aangesien noodsaaklik onderhoud tans uitgevoer word.
+    intro_text: OpenStreetMap is wêreldkaart deur gewone mense geskep. Die gebruik
+      daarvan is gratis en val onder 'n oop-lisensie.
+    intro_2_create_account: Skep 'n gebruikerrekening
+    partners_partners: vennote
+    osm_offline: Instandhouding word tans op die OpenStreetMap-databasis uitgevoer;
+      derhalwe is dit tans vanlyn tot en met die instandhouding afgehandel is.
+    osm_read_only: Aangesien noodsaaklik onderhoud tans op die OpenStreetMap-databasis
+      uitgevoer word, bied dit tans slegs leesregte.
     donate: Ondersteun OpenStreetMap deur aan die Hardeware Opgradeer-fonds te %{link}.
     help: Hulp
     about: Aangaande
     copyright: Kopiereg
     community: Gemeenskap
+    community_blogs: Gemeenskapblogs
+    foundation: Stigting
     foundation_title: Die OpenStreetMap-stigting
     make_a_donation:
-      title: Ondersteun OpenStreetMap met 'n geldelike donasie
-      text: Maak 'n donasie
-    learn_more: Meer inligting
+      title: Ondersteun OpenStreetMap met 'n geldelike skenking
+      text: Skenk aan die projek
+    learn_more: Kom meer te wete
     more: Meer
   license_page:
     foreign:
-      title: Oor hierdie vertaling
+      title: Aangaande dié vertaling
+    native:
+      title: Aangaande dié blad
+      mapping_link: begin karteer
+    legal_babble:
+      title_html: Kopiereg en Lisensie
+      intro_2_html: |-
+        Dit staan u vry om ons data te kopieer, versprei, versend of aan te maps, mits u erkenning aan OpenStreetMap en die bydraers gee. Indien u ons data wysig of daarop voortbou, mag u dit slegs in terme van dieselfde lisensie versprei. Die volledige <a href="http://opendatacommons.org/licenses/odbl/1.0/">legal
+        code</a> verduidelik u regte en verantwoordelikhede.
+      credit_title_html: Hoe om na OpenStreetMap te verwys
+      contributors_title_html: Ons bydraers
+      infringement_title_html: Kopieregoortreding
   welcome_page:
     title: Welkom!
+    basic_terms:
+      title: Grondliggende begrippe vir kartering
+      paragraph_1_html: OpenStreetMap bevat 'n gedeelte van ons eie vakbegrippe. Hier
+        is 'n paar wat handig te pas sal kom.
+    rules:
+      title: Reëls!
+    questions:
+      title: Enige vrae?
+    start_mapping: Begin Karteer
+    add_a_note:
+      title: Geen tyd om te redigeer? Voeg 'n opmerking by!
+  fixthemap:
+    how_to_help:
+      title: Hoe om te help
+      join_the_community:
+        title: Sluit by die gemeenskap aan
+    other_concerns:
+      title: Andere aangeleenthede
   help_page:
+    welcome:
+      url: /welkom
     mailing_lists:
       title: Poslyste
+    forums:
+      title: Forums
+    wiki:
+      url: http://wiki.openstreetmap.org/
+      title: wiki.openstreetmap.org
+  about_page:
+    next: Volgende
+    local_knowledge_title: Plaaslike Kennis
+    community_driven_title: Gemeenskapsgedrewe
+    legal_title: Wetlik
+    partners_title: Vennote
   notifier:
     diary_comment_notification:
-      subject: '[OpenStreetMap] %{user} het kommentaar op u dagboekinskrywing gelewer'
+      subject: '[OpenStreetMap] %{user} het ''n kommentaar oor ''n dagboekinskrywing
+        gemaak.'
       hi: Hallo %{to_user},
+      header: '%{from_user} het kommentaar oor die OpenStreetMap dagboekinskrywing
+        met die tema %{subject} gelewer:'
     message_notification:
       hi: Hallo %{to_user},
     friend_notification:
+      hi: Hallo %{to_user},
       subject: '[OpenStreetMap] %{user} het u as ''n vriend bygevoeg'
     gpx_notification:
       greeting: Hallo,
       your_gpx_file: Dit lyk soos jou GPX-lêer
       with_description: met die beskrywing
-      and_the_tags: 'en die volgende etikette:'
-      and_no_tags: en geen etikette.
+      and_the_tags: 'en die volgende merkers:'
+      and_no_tags: en geen merkers nie.
       failure:
-        more_info_2: 'hulle kan gevind word by:'
+        more_info_2: 'hulle kan gevind word te:'
     signup_confirm:
       subject: '[OpenStreetMap] Welkom by OpenStreetMap'
+      greeting: Hallo!
+      created: Iemand (hopelik u) het pas 'n rekening op %{site_url} geskep.
+      confirm: 'Voordat ons iets doen, verlang ons ''n bevestiging dat dié versoek
+        inderdaad van u afkomstig is. As dit so is, klik op die onderstaande skakel
+        om u rekening te bevestig:'
+      welcome: Nadat u u rekening bevestig het, bied ons u graag  addisionele inligting
+        sodat u kan wegtrek.
     email_confirm:
       subject: '[OpenStreetMap] Bevestig u e-posadres'
     email_confirm_plain:
       greeting: Hallo,
     email_confirm_html:
       greeting: Hallo,
-      hopefully_you: Iemand (hopelik u) wil graag sy e-posadres op %{server_url} verander
-        na %{new_address}.
-      click_the_link: As dit u is, kliek op die onderstaande skakel om die verandering
+      hopefully_you: Iemand (hopelik u) wil graag hul e-posadres op %{server_url}
+        verander na %{new_address}.
+      click_the_link: As dit u is, klik die onderstaande skakel om die verandering
         te bevestig.
     lost_password:
-      subject: '[OpenStreetMap] Versoek herstel van wagwoord'
+      subject: '[OpenStreetMap] Rig wagwoordherstel versoek'
     lost_password_plain:
       greeting: Hallo,
-      click_the_link: As dit u is, kliek op die onderstaande skakel om die wagwoord
-        te herstel.
+      click_the_link: As dit u is, klik die onderstaande skakel om u wagwoord te herstel.
     lost_password_html:
       greeting: Hallo,
+    note_comment_notification:
+      anonymous: '''n Anonieme gebruiker'
+      greeting: Hallo,
+    changeset_comment_notification:
+      hi: Hallo %{to_user},
+      greeting: Hallo,
   message:
     inbox:
-      title: Inboks
-      my_inbox: My inboks
-      outbox: uitboks
-      from: Vanaf
+      title: In-vakkie
+      my_inbox: My in-vakkie
+      outbox: uit-vakkie
+      from: Van
       subject: Onderwerp
       date: Datum
-      no_messages_yet: U het nog geen boodskappe nie. Hoekom kontak u nie sommige
-        van die %{people_mapping_nearby_link} nie?
+      no_messages_yet: U het nog geen boodskappe nie. Waarom tree u nie met sommige
+        van die %{people_mapping_nearby_link} in verbinding nie?
       people_mapping_nearby: nabygeleë karteerders
     message_summary:
       unread_button: Merk as ongelees
       read_button: Merk as gelees
-      reply_button: Antwoord
+      reply_button: Beantwoord
       delete_button: Verwyder
     new:
       title: Stuur boodskap
@@ -676,56 +1025,62 @@ af:
       subject: Onderwerp
       body: Teks
       send_button: Stuur
-      back_to_inbox: Terug na inboks
+      back_to_inbox: Terug na in-vakkie
       message_sent: Boodskap is gestuur
     no_such_message:
-      title: Die boodskap bestaan nie
-      heading: Die boodskap bestaan nie
+      title: Geen so 'n boodskap nie
+      heading: Geen so 'n boodskap nie
     outbox:
-      title: Uitboks
+      title: Uit-vakkie
       my_inbox: My %{inbox_link}
-      inbox: inboks
-      outbox: uitboks
+      inbox: in-vakkie
+      outbox: uit-vakkie
       to: Aan
       subject: Onderwerp
       date: Datum
-      no_sent_messages: U het nog geen boodskappe gestuur nie. Hoekom kontak u nie
-        sommige van die %{people_mapping_nearby_link} nie?
+      no_sent_messages: U het nog geen boodskappe gestuur nie. Waarom tree u nie met
+        sommige van die %{people_mapping_nearby_link} in verbinding nie?
       people_mapping_nearby: nabygeleë karteerders
     read:
       title: Lees boodskap
       from: Van
       subject: Onderwerp
       date: Datum
-      reply_button: Antwoord
+      reply_button: Beantwoord
       unread_button: Merk as ongelees
+      delete_button: Skrap
+      back: Terug
       to: Aan
     sent_message_summary:
       delete_button: Verwyder
     mark:
-      as_read: Boodskap gemerk as gelees
-      as_unread: Boodskap gemerk as ongelees
+      as_read: Boodskap as gelees gemerk
+      as_unread: Boodskap as ongelees gemerk
     delete:
       deleted: Boodskap is verwyder
   site:
     index:
-      permalink: Permanente skakel
-      shortlink: Kort skakel
+      permalink: Perma-skakel
+      shortlink: Kortskakel
     edit:
       user_page_link: gebruikersbladsy
       anon_edits_link_text: Lees waarom dit die geval is.
     sidebar:
-      search_results: Soekresultate
+      search_results: Soekuitslae
       close: Sluit
     search:
       search: Soek
-      get_directions_title: Kry aanwysings tussen twee punte
-      where_am_i: Waar is ek?
+      get_directions: Kry rigtingaanwysings
+      get_directions_title: Kry rigtingaanwysings tussen twee punte
+      from: Vanaf
+      to: Na
+      where_am_i: Waar bevind ek my?
       submit_text: Soek
     key:
       table:
         entry:
           motorway: Snelweg
+          main_road: Hoofweg
           trunk: Hoofroete
           primary: Primêre pad
           secondary: Sekondêre pad
@@ -733,6 +1088,7 @@ af:
           track: Spoor
           bridleway: Ruiterpad
           cycleway: Fietspad
+          cycleway_national: Nasionale fietsroete
           footway: Voetpad
           rail: Spoorweg
           subway: Ondergrondse spoorweg
@@ -740,11 +1096,11 @@ af:
           - Ligte spoor
           - trem
           cable:
-          - Kabelkar
+          - Sweefspoor
           - stoelhyser
           runway:
           - Lughawe aanloopbaan
-          - taxibaan
+          - vliegtuigrybaan
           apron:
           - Lughaweplatform
           - terminaal
@@ -757,98 +1113,117 @@ af:
           common:
           - Gemeen
           - weiland
-          retail: Winkelgebied
-          industrial: Industriële gebied
+          retail: Handelsgebied
+          industrial: Nywerheidsgebied
           commercial: Kommersiële gebied
           heathland: Heide
           lake:
           - Meer
           - reservoir
           farm: Plaas
-          brownfield: Braakveld terrein
+          brownfield: Braakveldterrein
           cemetery: Begraafplaas
           allotments: Volkstuine
           pitch: Sportveld
-          centre: Sport-sentrum
+          centre: Sportsentrum
           reserve: Natuurreservaat
           military: Militêre gebied
           school:
           - Skool
           - universiteit
-          building: Belangrike gebou
+          building: Betekenisvolle gebou
           station: Spoorwegstasie
           summit:
           - Piek
           - piek
           tunnel: Strepieomhulsel = tonnel
           bridge: Swartomhulsel = brug
-          private: Privaat toegang
+          private: Privaat-toegang
           destination: Bestemmingsverkeer
-          construction: Paaie onder konstruksie
+          construction: Paaie in aanbou
+          bicycle_shop: Fietswinkel
+          bicycle_parking: Fietsparkering
+          toilets: Toilette
+    richtext_area:
+      edit: Redigeer
+      preview: Voorskou
+    markdown_help:
+      headings: Opskrifte
+      heading: Opskrif
+      unordered: Ongeordende lys
+      ordered: Geordende lys
+      first: Eerste item
+      second: Tweede item
+      link: Skakel
+      text: Teks
+      image: Beeld
+      alt: Alternatiewe teks
+      url: URL
   trace:
     create:
       upload_trace: Laai GPS-spore op
     edit:
-      title: Wysig spoor %{name}
+      title: Redigeer tans spoor %{name}
       heading: Wysig spoor %{name}
       filename: 'Lêernaam:'
-      download: aflaai
+      download: laai af
       uploaded_at: 'Opgelaai op:'
       points: 'Punte:'
       start_coord: 'Beginkoördinaat:'
       map: kaart
-      edit: wysig
+      edit: redigeer
       owner: 'Eienaar:'
       description: 'Beskrywing:'
-      tags: 'Etikette:'
-      tags_help: met kommas geskei
-      save_button: Stoor wysigings
+      tags: 'Merkers:'
+      tags_help: komma afgebaken
+      save_button: Stoor Wysigings
       visibility: 'Sigbaarheid:'
       visibility_help: wat beteken dit?
     trace_form:
       upload_gpx: 'Laai GPX-lêer op:'
       description: 'Beskrywing:'
-      tags: 'Etikette:'
-      tags_help: met kommas geskei
+      tags: 'Merkers:'
+      tags_help: komma afgebaken
       visibility: 'Sigbaarheid:'
       visibility_help: wat beteken dit?
       upload_button: Laai op
       help: Hulp
     trace_header:
+      upload_trace: Laai 'n GPS-spoor op
       see_all_traces: Wys alle spore
       see_your_traces: Sien al u spore
     trace_optionals:
-      tags: Etikette
+      tags: Merkers
     view:
       title: Besigtig spoor %{name}
       heading: Besigtig spoor %{name}
-      pending: BESIG
+      pending: HANGEND
       filename: 'Lêernaam:'
       download: laai af
       uploaded: 'Opgelaai op:'
       points: 'Punte:'
       start_coordinates: 'Beginkoördinaat:'
       map: kaart
-      edit: wysig
+      edit: redigeer
       owner: 'Eienaar:'
       description: 'Beskrywing:'
-      tags: 'Etikette:'
+      tags: 'Merkers:'
       none: Geen
       edit_track: Wysig hierdie spoor
       delete_track: Verwyder hierdie spoor
-      trace_not_found: Spoor nie gevind nie!
+      trace_not_found: Spoor onverkrygbaar!
       visibility: 'Sigbaarheid:'
     trace_paging_nav:
       showing_page: Bladsy %{page}
     trace:
-      pending: BESIG
+      pending: HANGEND
       count_points: '%{count} punte'
       ago: '%{time_in_words_ago} gelede'
       more: meer
-      trace_details: Wys spoor besonderhede
+      trace_details: Wys Besonderhede van die Spoor
       view_map: Wys kaart
-      edit: wysig
-      edit_map: Wysig kaart
+      edit: redigeer
+      edit_map: Redigeer Kaart
       public: OPENBAAR
       identifiable: IDENTIFISEERBAAR
       private: PRIVAAT
@@ -859,48 +1234,68 @@ af:
       public_traces: Openbare GPS-spore
       your_traces: U GPS-spore
       public_traces_from: Openbare GPS-spore van %{user}
-      tagged_with: geëtiketteer met %{tags}
+      tagged_with: gemerk met %{tags}
     delete:
-      scheduled_for_deletion: Spoor is geskeduleer vir verwydering
+      scheduled_for_deletion: Spoor is vir verwydering geoormerk
     make_public:
       made_public: Spoor is openbaar gemaak
   oauth:
     oauthorize:
       allow_read_prefs: lees u gebruikersvoorkeure.
       allow_write_prefs: verander jou gebruikersvoorkeure.
-      allow_write_api: die kaart wysig.
+      allow_write_api: wysig die kaart.
       allow_write_gpx: laai GPS-spore op.
+      allow_write_notes: wysig opmerkings.
+      grant_access: Verleen toegang
+    oauthorize_success:
+      title: Magtigingsversoek toegestaan
+      allowed: U het die program %{app_name} toegang tot u rekening verleen.
+      verification: Die bevestigingskode is %{code}
+    oauthorize_failure:
+      title: Magtigingsversoek het misluk
+      denied: U het die program %{app_name} toegang tot u rekening geweier.
+      invalid: Die magtigingsteken is ongeldig.
+    revoke:
+      flash: U het die teken vir %{application} teruggetrek.
+    permissions:
+      missing: U het nie die program toegang tot hierdie fasilititeit verleen nie.
   oauth_clients:
     new:
       title: Registreer 'n nuwe toepassing
       submit: Registreer
     edit:
-      title: Wysig u toepassing
-      submit: Wysig
+      title: Redigeer u program
+      submit: Redigeer
     show:
+      title: OAuth-besonderhede vir %{app_name}
+      secret: 'Verbruikersgeheim:'
+      url: Versoek teken-URL
+      access_url: 'Toegangsteken URL:'
       authorize_url: 'Magtig URL:'
-      edit: Wysig details
-      allow_read_prefs: lees hulle gebruikersvoorkeure.
-      allow_write_diary: skep dagboekinskrywings, lewer kommentaar en maak vriende.
+      edit: Redigeer Besonderhede
+      confirm: Is u seker?
+      allow_read_prefs: lees hul gebruikersvoorkeure.
+      allow_write_diary: skep dagboekinskrywings, maak opmerkings en maak vriende.
       allow_write_api: wysig die kaart.
       allow_write_gpx: laai GPS-spore op.
     index:
-      title: My OAuth-details
-      application: Toepassingnaam
+      title: My OAuth-gegewens
+      application: Programnaam
       issued_at: Uitgereik op
       revoke: Herroep!
-      my_apps: My kliënt-toepassing
-      register_new: Registreer u toepassing
+      my_apps: My Kliënt-programme
+      register_new: Registreer u program
     form:
       name: Naam
       required: Verplig
       url: Toepassing-URL
       support_url: Ondersteunings-URL
-      allow_read_prefs: lees hulle gebruikersvoorkeure.
+      allow_read_prefs: lees hul gebruikersvoorkeure.
       allow_write_prefs: verander hulle gebruikersvoorkeure.
-      allow_write_diary: skep dagboekinskrywings, lewer kommentaar en maak vriende.
+      allow_write_diary: skep dagboekinskrywings, lewer kommentaar en ontmoet vriende.
+      allow_write_api: wysig die kaart.
     not_found:
-      sorry: Jammer, die %{type} kon nie gevind word nie.
+      sorry: Jammer, die %{type} blyk onverkrygbaar te wees.
   user:
     login:
       title: Meld aan
@@ -910,17 +1305,18 @@ af:
       remember: Onthou my
       lost password link: Wagwoord vergeet?
       login_button: Meld aan
+      register now: Skryf nou in
       auth failure: Jammer, kon nie met hierdie inligting aanmeld nie.
     logout:
       title: Teken af
-      heading: Teken van OpenStreetMap af
+      heading: Meld van OpenStreetMap af
       logout_button: Teken af
     lost_password:
-      title: Wagwoord vergeet
+      title: Wagwoord verloor
       heading: Wagwoord vergeet?
       email address: 'E-posadres:'
       new password button: Herstel wagwoord
-      notice email cannot find: Kon nie die e-posadres vind nie, jammer.
+      notice email cannot find: E-posadres is ongelukkig onverkrygbaar, jammer.
     reset_password:
       title: Herstel wagwoord
       heading: Herstel wagwoord vir %{user}
@@ -929,19 +1325,29 @@ af:
       reset: Herstel wagwoord
       flash changed: U wagwoord is verander.
     new:
-      title: Skep rekening
-      license_agreement: Deur 'n rekening hier te skep bevestig u dat u akkoord gaan
-        met voorwaarde dat al die werk wat u na OpenStreetMap oplaai onder die <a
-        href="http://creativecommons.org/licenses/by-sa/2.0/deed.af">Creative Commons-lisensie
-        (by-sa)</a> gelisensieer word (nie-eksklusief).
+      title: Teken aan
+      about:
+        header: Gratis en redigeerbaar
+        html: <p>Anders as ander kaarte, skep mense soos jy OpenStreetMap geheel en
+          al; daarbenewens is dit gratis vir enigeen om te herstel, by te werk, af
+          te laai en te benut.</p> <p>Registreer om 'n bydrae te lewer. Ons sal dan
+          u registrasie per e-pos bevestig.</p>
+      license_agreement: Wanneer u u rekening bevestig, sal u ooreenkomstig die <a
+        href="http://www.osmfoundation.org/wiki/License/Contributor_Terms">bepalings
+        vir bydraers</a> moet toestem.
       email address: 'E-posadres:'
-      confirm email address: 'Bevestig E-posadres:'
-      not displayed publicly: Word nie publiek vertoon nie (sien <a href="http://wiki.openstreetmap.org/wiki/Privacy_Policy"
-        title="wiki privacy policy including section on email addresses">geheimhoudingbeleid</a>)
-      display name: 'Vertoon naam:'
+      confirm email address: 'Bevestig e-posadres:'
+      not displayed publicly: U adres word nie openbaar gemaak nie; raadpleeg ons
+        <a href="http://wiki.osmfoundation.org/wiki/Privacy_Policy" title="OSMF privaatheidsbeleid
+        insluitende die klousule ten opsigte van e-posadresse">privaatheidsbeleid</a>
+        vir verdere inligting.
+      display name: 'Skermnaam:'
+      display name description: U gebruikernaam wat openbaar verskyn. U kan dit wel
+        later nog onder voorkeure wysig.
       password: 'Wagwoord:'
       confirm password: 'Bevestig wagwoord:'
-      continue: Gaan voort
+      use external auth: Gebruik andersins 'n derde party om mee aan te meld
+      continue: Teken aan
       terms accepted: Dankie dat u die nuwe bydraerooreenkoms aanvaar het!
     terms:
       title: Bydraerooreenkoms
@@ -951,24 +1357,24 @@ af:
       legale_names:
         france: Frankryk
         italy: Italië
-        rest_of_world: Res van die wêreld
+        rest_of_world: Die res van die wêreld
     no_such_user:
-      title: Gebruiker bestaan nie
+      title: Geen so 'n gebruiker nie
       heading: Die gebruiker %{user} bestaan nie
-      body: Daar is geen gebruiker met die naam %{user} nie. Kontroleer u spelling,
-        of die skakel waarop u gekliek het is verkeerd.
+      body: Daar is geen gebruiker met die naam %{user} nie. Gaan u spelling na, of
+        u het moontlik op 'n foutiewe skakel geklik.
     view:
-      my diary: My dagboek
+      my diary: My Dagboek
       new diary entry: nuwe dagboekinskrywing
-      my edits: My wysigings
-      my traces: My spore
-      my settings: My voorkeure
+      my edits: My Redigerings
+      my traces: My Spore
+      my settings: My Instellings
       oauth settings: Oauth-instellings
-      blocks on me: blokkades op my
-      blocks by me: blokkades deur my
-      send message: Stuur boodskap
+      blocks on me: Versperrings vir u
+      blocks by me: Versperrings deur u
+      send message: Stuur Boodskap
       diary: Dagboek
-      edits: Wysigings
+      edits: Redigerings
       traces: Spore
       remove as friend: Verwyder as vriend
       add as friend: Voeg by as vriend
@@ -980,16 +1386,16 @@ af:
       spam score: 'SPAM-telling:'
       description: Beskrywing
       user location: Ligging van gebruiker
-      if set location: As u u ligging stel, sal 'n pragtige kaart en ander inligting
-        hieronder verskyn. U kan u ligging stel in u %{settings_link}.
-      settings_link_text: voorkeure
+      if set location: Stel u tuisligging by %{settings_link} in om gebruikers naby
+        u te sien.
+      settings_link_text: instellings
       your friends: U vriende
       no friends: U het nog geen vriende bygevoeg nie.
       km away: '%{count}km vêr'
       m away: '%{count}m vêr'
       nearby users: Ander nabygeleë gebruikers
-      no nearby users: Daar is nog geen gebruikers wat erken dat hulle nabygeleë karterinswerk
-        doen nie.
+      no nearby users: Daar is nog geen ander gebruikers wat erken dat hulle kaarte
+        in die nabye gebied afrond nie.
       role:
         administrator: Hierdie gebruiker is 'n administrateur
         moderator: Hierdie gebruiker is 'n moderator
@@ -997,66 +1403,77 @@ af:
           administrator: Ken adminregte toe
           moderator: Ken moderatorregte toe
         revoke:
-          administrator: Trek adminregte terug
-          moderator: Trek moderatorregte terug
-      block_history: wys blokkades ontvang
-      moderator_history: wys blokkades uitgedeel
-      create_block: blokkeer die gebruiker
-      activate_user: aktiveer hierdie gebruiker
-      deactivate_user: deaktiveer hierdie gebruiker
-      confirm_user: bevestig hierdie gebruiker
-      hide_user: versteek hierdie gebruiker
-      unhide_user: maak die gebruiker weer sigbaar
-      delete_user: skrap die gebruiker
+          administrator: Herroep adminregte
+          moderator: Herroep moderatorregte
+      block_history: Aktiewe Versperrings
+      moderator_history: Uitgevoerde Versperrings
+      create_block: Versper hierdie gebruiker
+      activate_user: Aktiveer hierdie gebruiker
+      deactivate_user: Deaktiveer hierdie gebruiker
+      confirm_user: Bevestig dié Gebruiker
+      hide_user: Versteek hierdie gebruiker
+      unhide_user: Wys hierdie gebruiker
+      delete_user: Skrap dié Gebruiker
       confirm: Bevestig
     popup:
       your location: U ligging
       nearby mapper: Nabygeleë karteerder
       friend: Vriend
     account:
-      title: Wysig rekening
-      my settings: My voorkeure
+      title: Redigeer rekening
+      my settings: My instellings
       current email address: 'Huidige e-posadres:'
       new email address: 'Nuwe e-posadres:'
-      email never displayed publicly: (word nie openbaar gemaak nie)
+      email never displayed publicly: (word nooit openbaar vertoon nie)
       public editing:
-        heading: 'Openbaar wysigings:'
-        enabled: Geaktiveer. U is nie anoniem nie en kan inligting wysig.
-        enabled link text: wat is dit?
-        disabled link text: hoekom kan ek niks wysig nie?
+        heading: 'Openbare redigerings:'
+        enabled: Geaktiveer. Nie anoniem nie en kan tog data redigeer.
+        enabled link text: wat is dié?
+        disabled link text: hoekom kan ek nie redigeer nie?
       contributor terms:
-        link text: wat is dit?
+        link text: wat is dié?
       profile description: 'Profielbeskrywing:'
-      preferred languages: 'Voorkeur tale:'
+      preferred languages: 'Verkose Tale:'
       image: 'Beeld:'
-      new image: Voeg beeld by
+      new image: Voeg 'n beeld by
       replace image: Vervang die huidige beeld
       home location: 'Tuisligging:'
-      no home location: U het nog nie u huis se ligging ingevoer nie.
+      no home location: U het nog geen tuisligging ingelees nie.
       latitude: 'Breedtegraad:'
       longitude: 'Lengtegraad:'
-      update home location on click: Opdateer tuisligging wanneer ek op die kaart
-        kliek?
-      save changes button: Stoor wysigings
-      make edits public button: Maak al my wysigings openbaar
+      update home location on click: Werk tuisligging by wanneer ek op die kaart klik?
+      save changes button: Stoor Wysigings
+      make edits public button: Stel al my redigerings openbaar
       return to profile: Terug na profiel
-      flash update success: U gebruikersinligting is verander.
+      flash update success: Gebruikersbesonderhede suksesvol bygewerk.
     confirm:
-      heading: Kontroleer u e-pos!
-      press confirm button: Kliek op "Bevestig" hieronder om u rekening aktiveer.
+      heading: Gaan u e-pos na!
+      introduction_1: Ons het u 'n e-pos ter bevestiging getuur.
+      introduction_2: Klik op die skakel in die e-pos en bevestig u rekening, dan
+        sal u kan karteer.
+      press confirm button: Klik 'bevestig' hieronder om u rekening te aktiveer.
       button: Bevestig
+      success: U rekening is bevestig. Dankie dat u aangeteken het!
+      already active: Hierdie rekening is reeds bevestig.
+      unknown token: Die bevestigingskode het reeds verval of bestaan nie.
+      reconfirm_html: Sou u van ons verlang om weer die e-pos ter bevestiging te stuur,
+        <a href="%{reconfirm}">klik hier</a>.
+    confirm_resend:
+      failure: Die gebruiker %{name} is nie gevind nie.
     confirm_email:
-      heading: Bevestig verandering van e-posadres
+      heading: Bevestig 'n verandering van e-posadres
+      press confirm button: Klik op die volgende knoppie om u e-posadres te bevestig.
       button: Bevestig
-      success: U e-posadres verandering is bevestig!
+      success: Die verandering van u e-posadres is bevestig!
     set_home:
       flash success: U tuisligging is suksesvol gestoor
     make_friend:
+      button: As vriend byvoeg
       success: '%{name} is nou u vriend!'
       failed: Jammer, kon nie %{name} as 'n vriend byvoeg nie.
       already_a_friend: U is reeds met %{name} bevriend.
     remove_friend:
-      success: '%{name} is uit u lys van vriende verwyder.'
+      success: '%{name} is uit u vriendekring verwyder.'
       not_a_friend: '%{name} is nie een van u vriende nie.'
     list:
       title: Gebruikers
@@