Sanitise parameters used in URL generation
authorTom Hughes <tom@compton.nu>
Fri, 2 Jun 2017 19:26:33 +0000 (20:26 +0100)
committerTom Hughes <tom@compton.nu>
Fri, 2 Jun 2017 19:27:07 +0000 (20:27 +0100)
app/controllers/changeset_controller.rb
app/controllers/geocoder_controller.rb
app/controllers/user_controller.rb
app/views/changeset/list.atom.builder
app/views/geocoder/search.html.erb
app/views/user/list.html.erb

index 185a3bd19fbeee8117bb85d48985fe3382183408..71fc2a59a58659e5cc37efc3169f77891a57f04d 100644 (file)
@@ -250,46 +250,48 @@ class ChangesetController < ApplicationController
   ##
   # list non-empty changesets in reverse chronological order
   def list
-    if request.format == :atom && params[:max_id]
-      redirect_to url_for(params.merge(:max_id => nil)), :status => :moved_permanently
+    @params = params.permit(:display_name, :bbox, :friends, :nearby, :max_id, :list)
+
+    if request.format == :atom && @params[:max_id]
+      redirect_to url_for(@params.merge(:max_id => nil)), :status => :moved_permanently
       return
     end
 
-    if params[:display_name]
-      user = User.find_by(:display_name => params[:display_name])
+    if @params[:display_name]
+      user = User.find_by(:display_name => @params[:display_name])
       if !user || !user.active?
-        render_unknown_user params[:display_name]
+        render_unknown_user @params[:display_name]
         return
       end
     end
 
-    if (params[:friends] || params[:nearby]) && !@user
+    if (@params[:friends] || @params[:nearby]) && !@user
       require_user
       return
     end
 
-    if request.format == :html && !params[:list]
+    if request.format == :html && !@params[:list]
       require_oauth
       render :action => :history, :layout => map_layout
     else
       changesets = conditions_nonempty(Changeset.all)
 
-      if params[:display_name]
+      if @params[:display_name]
         changesets = if user.data_public? || user == @user
                        changesets.where(:user_id => user.id)
                      else
                        changesets.where("false")
                      end
-      elsif params[:bbox]
+      elsif @params[:bbox]
         changesets = conditions_bbox(changesets, BoundingBox.from_bbox_params(params))
-      elsif params[:friends] && @user
+      elsif @params[:friends] && @user
         changesets = changesets.where(:user_id => @user.friend_users.identifiable)
-      elsif params[:nearby] && @user
+      elsif @params[:nearby] && @user
         changesets = changesets.where(:user_id => @user.nearby)
       end
 
-      if params[:max_id]
-        changesets = changesets.where("changesets.id <= ?", params[:max_id])
+      if @params[:max_id]
+        changesets = changesets.where("changesets.id <= ?", @params[:max_id])
       end
 
       @edits = changesets.order("changesets.id DESC").limit(20).preload(:user, :changeset_tags, :comments)
index a5f1810b7b05755d2262aa646a24df71239dfe69..2348425886342ec9d979a2800842da049ffef6a2 100644 (file)
@@ -10,22 +10,21 @@ class GeocoderController < ApplicationController
   before_action :require_oauth, :only => [:search]
 
   def search
-    normalize_params
-
+    @params = normalize_params
     @sources = []
 
-    if params[:lat] && params[:lon]
+    if @params[:lat] && @params[:lon]
       @sources.push "latlon"
       @sources.push "osm_nominatim_reverse"
       @sources.push "geonames_reverse" if defined?(GEONAMES_USERNAME)
-    elsif params[:query]
-      if params[:query] =~ /^\d{5}(-\d{4})?$/
+    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
+      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"
         @sources.push "osm_nominatim"
-      elsif params[:query] =~ /^[A-Z]\d[A-Z]\s*\d[A-Z]\d$/i
+      elsif @params[:query] =~ /^[A-Z]\d[A-Z]\s*\d[A-Z]\d$/i
         @sources.push "ca_postcode"
         @sources.push "osm_nominatim"
       else
@@ -316,29 +315,30 @@ class GeocoderController < ApplicationController
   end
 
   def normalize_params
-    query = params[:query]
-    return unless query
-
-    query.strip!
-
-    if latlon = query.match(/^([NS])\s*(\d{1,3}(\.\d*)?)\W*([EW])\s*(\d{1,3}(\.\d*)?)$/).try(:captures) # [NSEW] decimal degrees
-      params.merge!(nsew_to_decdeg(latlon)).delete(:query)
-    elsif latlon = query.match(/^(\d{1,3}(\.\d*)?)\s*([NS])\W*(\d{1,3}(\.\d*)?)\s*([EW])$/).try(:captures) # decimal degrees [NSEW]
-      params.merge!(nsew_to_decdeg(latlon)).delete(:query)
-
-    elsif latlon = query.match(/^([NS])\s*(\d{1,3})°?\s*(\d{1,3}(\.\d*)?)?['′]?\W*([EW])\s*(\d{1,3})°?\s*(\d{1,3}(\.\d*)?)?['′]?$/).try(:captures) # [NSEW] degrees, decimal minutes
-      params.merge!(ddm_to_decdeg(latlon)).delete(:query)
-    elsif latlon = query.match(/^(\d{1,3})°?\s*(\d{1,3}(\.\d*)?)?['′]?\s*([NS])\W*(\d{1,3})°?\s*(\d{1,3}(\.\d*)?)?['′]?\s*([EW])$/).try(:captures) # degrees, decimal minutes [NSEW]
-      params.merge!(ddm_to_decdeg(latlon)).delete(:query)
-
-    elsif latlon = query.match(/^([NS])\s*(\d{1,3})°?\s*(\d{1,2})['′]?\s*(\d{1,3}(\.\d*)?)?["″]?\W*([EW])\s*(\d{1,3})°?\s*(\d{1,2})['′]?\s*(\d{1,3}(\.\d*)?)?["″]?$/).try(:captures) # [NSEW] degrees, minutes, decimal seconds
-      params.merge!(dms_to_decdeg(latlon)).delete(:query)
-    elsif latlon = query.match(/^(\d{1,3})°?\s*(\d{1,2})['′]?\s*(\d{1,3}(\.\d*)?)?["″]\s*([NS])\W*(\d{1,3})°?\s*(\d{1,2})['′]?\s*(\d{1,3}(\.\d*)?)?["″]?\s*([EW])$/).try(:captures) # degrees, minutes, decimal seconds [NSEW]
-      params.merge!(dms_to_decdeg(latlon)).delete(:query)
-
-    elsif latlon = query.match(/^\s*([+-]?\d+(\.\d*)?)\s*[\s,]\s*([+-]?\d+(\.\d*)?)\s*$/)
-      params.merge!(:lat => latlon[1].to_f, :lon => latlon[3].to_f).delete(:query)
+    if query = params[:query]
+      query.strip!
+
+      if latlon = query.match(/^([NS])\s*(\d{1,3}(\.\d*)?)\W*([EW])\s*(\d{1,3}(\.\d*)?)$/).try(:captures) # [NSEW] decimal degrees
+        params.merge!(nsew_to_decdeg(latlon)).delete(:query)
+      elsif latlon = query.match(/^(\d{1,3}(\.\d*)?)\s*([NS])\W*(\d{1,3}(\.\d*)?)\s*([EW])$/).try(:captures) # decimal degrees [NSEW]
+        params.merge!(nsew_to_decdeg(latlon)).delete(:query)
+
+      elsif latlon = query.match(/^([NS])\s*(\d{1,3})°?\s*(\d{1,3}(\.\d*)?)?['′]?\W*([EW])\s*(\d{1,3})°?\s*(\d{1,3}(\.\d*)?)?['′]?$/).try(:captures) # [NSEW] degrees, decimal minutes
+        params.merge!(ddm_to_decdeg(latlon)).delete(:query)
+      elsif latlon = query.match(/^(\d{1,3})°?\s*(\d{1,3}(\.\d*)?)?['′]?\s*([NS])\W*(\d{1,3})°?\s*(\d{1,3}(\.\d*)?)?['′]?\s*([EW])$/).try(:captures) # degrees, decimal minutes [NSEW]
+        params.merge!(ddm_to_decdeg(latlon)).delete(:query)
+
+      elsif latlon = query.match(/^([NS])\s*(\d{1,3})°?\s*(\d{1,2})['′]?\s*(\d{1,3}(\.\d*)?)?["″]?\W*([EW])\s*(\d{1,3})°?\s*(\d{1,2})['′]?\s*(\d{1,3}(\.\d*)?)?["″]?$/).try(:captures) # [NSEW] degrees, minutes, decimal seconds
+        params.merge!(dms_to_decdeg(latlon)).delete(:query)
+      elsif latlon = query.match(/^(\d{1,3})°?\s*(\d{1,2})['′]?\s*(\d{1,3}(\.\d*)?)?["″]\s*([NS])\W*(\d{1,3})°?\s*(\d{1,2})['′]?\s*(\d{1,3}(\.\d*)?)?["″]?\s*([EW])$/).try(:captures) # degrees, minutes, decimal seconds [NSEW]
+        params.merge!(dms_to_decdeg(latlon)).delete(:query)
+
+      elsif latlon = query.match(/^\s*([+-]?\d+(\.\d*)?)\s*[\s,]\s*([+-]?\d+(\.\d*)?)\s*$/)
+        params.merge!(:lat => latlon[1].to_f, :lon => latlon[3].to_f).delete(:query)
+      end
     end
+
+    params.permit(:query, :lat, :lon, :zoom, :minlat, :minlon, :maxlat, :maxlon)
   end
 
   def nsew_to_decdeg(captures)
index 2ff9646e649a2c8784df78ec58891558cadc9446..430051c1755771f14db594433d1dc3e7b5bd6faa 100644 (file)
@@ -480,9 +480,11 @@ class UserController < ApplicationController
 
       redirect_to url_for(:status => params[:status], :ip => params[:ip], :page => params[:page])
     else
+      @params = params.permit(:status, :ip)
+
       conditions = {}
-      conditions[:status] = params[:status] if params[:status]
-      conditions[:creation_ip] = params[:ip] if params[:ip]
+      conditions[:status] = @params[:status] if @params[:status]
+      conditions[:creation_ip] = @params[:ip] if @params[:ip]
 
       @user_pages, @users = paginate(:users,
                                      :conditions => conditions,
index 68b4a198505b6204af025356f8a964a538097308..0235d182afbea03b092169b1b7be61db27fce942 100644 (file)
@@ -1,6 +1,6 @@
 atom_feed(:language => I18n.locale, :schema_date => 2009,
-          :id => url_for(params.merge(:only_path => false)),
-          :root_url => url_for(params.merge(:action => :list, :format => nil, :only_path => false)),
+          :id => url_for(@params.merge(:only_path => false)),
+          :root_url => url_for(@params.merge(:action => :list, :format => nil, :only_path => false)),
           "xmlns:georss" => "http://www.georss.org/georss") do |feed|
   feed.title changeset_list_title(params, @user)
 
index ac655147a9a4f367df4f18fc1d0f3ed59fc0f395..21484d4c072a76dd48dbff8340cd93e29658647b 100644 (file)
@@ -4,7 +4,7 @@
 </h2>
 <% @sources.each do |source| %>
   <h4 class="inner12"><%= raw(t "geocoder.search.title.#{source}") %></h4>
-  <div class="search_results_entry" data-href="<%= url_for params.merge(:action => "search_#{source}") %>">
+  <div class="search_results_entry" data-href="<%= url_for @params.merge(:action => "search_#{source}") %>">
     <%= image_tag "searching.gif", :class => "loader" %>
   </div>
 <% end %>
index fcd0c41fcfd7f49a349ecd2f1035f0f24ad804e2..903a51c5bb6bbbb7d308db77247d9ac57f58a981 100644 (file)
@@ -24,7 +24,7 @@
               :count => @user_pages.current_page.last_item - @user_pages.current_page.first_item + 1
           %>
           <% if @user_pages.page_count > 1 %>
-          | <%= raw pagination_links_each(@user_pages, {}) { |n| link_to n, params.merge(:page => n) } %>
+          | <%= raw pagination_links_each(@user_pages, {}) { |n| link_to n, @params.merge(:page => n) } %>
           <% end %>
         </td>
         <td>