X-Git-Url: https://git.openstreetmap.org./rails.git/blobdiff_plain/749a735472792d9e8a5e77674169872f6a9a50b0..9acc6d32883435ab9734cd4970b292583075a75d:/app/controllers/amf_controller.rb?ds=sidebyside diff --git a/app/controllers/amf_controller.rb b/app/controllers/amf_controller.rb index 0bc5148a1..900439721 100644 --- a/app/controllers/amf_controller.rb +++ b/app/controllers/amf_controller.rb @@ -48,87 +48,95 @@ class AmfController < ApplicationController # ** FIXME: refactor to reduce duplication of code across read/write def amf_read - req=StringIO.new(request.raw_post+0.chr)# Get POST data as request - # (cf http://www.ruby-forum.com/topic/122163) - req.read(2) # Skip version indicator and client ID - results={} # Results of each body + if request.post? + req=StringIO.new(request.raw_post+0.chr)# Get POST data as request + # (cf http://www.ruby-forum.com/topic/122163) + req.read(2) # Skip version indicator and client ID + results={} # Results of each body - # Parse request + # Parse request - headers=AMF.getint(req) # Read number of headers + headers=AMF.getint(req) # Read number of headers - headers.times do # Read each header - name=AMF.getstring(req) # | - req.getc # | skip boolean - value=AMF.getvalue(req) # | - header["name"]=value # | - end + headers.times do # Read each header + name=AMF.getstring(req) # | + req.getc # | skip boolean + value=AMF.getvalue(req) # | + header["name"]=value # | + end - bodies=AMF.getint(req) # Read number of bodies - bodies.times do # Read each body - message=AMF.getstring(req) # | get message name - index=AMF.getstring(req) # | get index in response sequence - bytes=AMF.getlong(req) # | get total size in bytes - args=AMF.getvalue(req) # | get response (probably an array) - logger.info("Executing AMF #{message}:#{index}") - - case message - when 'getpresets'; results[index]=AMF.putdata(index,getpresets()) - when 'whichways'; results[index]=AMF.putdata(index,whichways(*args)) - when 'whichways_deleted'; results[index]=AMF.putdata(index,whichways_deleted(*args)) - when 'getway'; r=AMF.putdata(index,getway(args[0].to_i)) - results[index]=r - when 'getrelation'; results[index]=AMF.putdata(index,getrelation(args[0].to_i)) - when 'getway_old'; results[index]=AMF.putdata(index,getway_old(args[0].to_i,args[1])) - when 'getway_history'; results[index]=AMF.putdata(index,getway_history(args[0].to_i)) - when 'getnode_history'; results[index]=AMF.putdata(index,getnode_history(args[0].to_i)) - when 'findgpx'; results[index]=AMF.putdata(index,findgpx(*args)) - when 'findrelations'; results[index]=AMF.putdata(index,findrelations(*args)) - when 'getpoi'; results[index]=AMF.putdata(index,getpoi(*args)) + bodies=AMF.getint(req) # Read number of bodies + bodies.times do # Read each body + message=AMF.getstring(req) # | get message name + index=AMF.getstring(req) # | get index in response sequence + bytes=AMF.getlong(req) # | get total size in bytes + args=AMF.getvalue(req) # | get response (probably an array) + logger.info("Executing AMF #{message}:#{index}") + + case message + when 'getpresets'; results[index]=AMF.putdata(index,getpresets()) + when 'whichways'; results[index]=AMF.putdata(index,whichways(*args)) + when 'whichways_deleted'; results[index]=AMF.putdata(index,whichways_deleted(*args)) + when 'getway'; r=AMF.putdata(index,getway(args[0].to_i)) + results[index]=r + when 'getrelation'; results[index]=AMF.putdata(index,getrelation(args[0].to_i)) + when 'getway_old'; results[index]=AMF.putdata(index,getway_old(args[0].to_i,args[1])) + when 'getway_history'; results[index]=AMF.putdata(index,getway_history(args[0].to_i)) + when 'getnode_history'; results[index]=AMF.putdata(index,getnode_history(args[0].to_i)) + when 'findgpx'; results[index]=AMF.putdata(index,findgpx(*args)) + when 'findrelations'; results[index]=AMF.putdata(index,findrelations(*args)) + when 'getpoi'; results[index]=AMF.putdata(index,getpoi(*args)) + end end + logger.info("encoding AMF results") + sendresponse(results) + else + render :nothing => true, :status => :method_not_allowed end - logger.info("encoding AMF results") - sendresponse(results) end def amf_write - req=StringIO.new(request.raw_post+0.chr) - req.read(2) - results={} - renumberednodes={} # Shared across repeated putways - renumberedways={} # Shared across repeated putways - - headers=AMF.getint(req) # Read number of headers - headers.times do # Read each header - name=AMF.getstring(req) # | - req.getc # | skip boolean - value=AMF.getvalue(req) # | - header["name"]=value # | - end + if request.post? + req=StringIO.new(request.raw_post+0.chr) + req.read(2) + results={} + renumberednodes={} # Shared across repeated putways + renumberedways={} # Shared across repeated putways + + headers=AMF.getint(req) # Read number of headers + headers.times do # Read each header + name=AMF.getstring(req) # | + req.getc # | skip boolean + value=AMF.getvalue(req) # | + header["name"]=value # | + end - bodies=AMF.getint(req) # Read number of bodies - bodies.times do # Read each body - message=AMF.getstring(req) # | get message name - index=AMF.getstring(req) # | get index in response sequence - bytes=AMF.getlong(req) # | get total size in bytes - args=AMF.getvalue(req) # | get response (probably an array) - - logger.info("Executing AMF #{message}:#{index}") - case message - when 'putway'; r=putway(renumberednodes,*args) - renumberednodes=r[3] - if r[1] != r[2] then renumberedways[r[1]] = r[2] end - results[index]=AMF.putdata(index,r) - when 'putrelation'; results[index]=AMF.putdata(index,putrelation(renumberednodes, renumberedways, *args)) - when 'deleteway'; results[index]=AMF.putdata(index,deleteway(*args)) - when 'putpoi'; r=putpoi(*args) - if r[1] != r[2] then renumberednodes[r[1]] = r[2] end - results[index]=AMF.putdata(index,r) - when 'startchangeset'; results[index]=AMF.putdata(index,startchangeset(*args)) + bodies=AMF.getint(req) # Read number of bodies + bodies.times do # Read each body + message=AMF.getstring(req) # | get message name + index=AMF.getstring(req) # | get index in response sequence + bytes=AMF.getlong(req) # | get total size in bytes + args=AMF.getvalue(req) # | get response (probably an array) + + logger.info("Executing AMF #{message}:#{index}") + case message + when 'putway'; r=putway(renumberednodes,*args) + renumberednodes=r[3] + if r[1] != r[2] then renumberedways[r[1]] = r[2] end + results[index]=AMF.putdata(index,r) + when 'putrelation'; results[index]=AMF.putdata(index,putrelation(renumberednodes, renumberedways, *args)) + when 'deleteway'; results[index]=AMF.putdata(index,deleteway(*args)) + when 'putpoi'; r=putpoi(*args) + if r[1] != r[2] then renumberednodes[r[1]] = r[2] end + results[index]=AMF.putdata(index,r) + when 'startchangeset'; results[index]=AMF.putdata(index,startchangeset(*args)) + end end + logger.info("encoding AMF results") + sendresponse(results) + else + render :nothing => true, :status => :method_not_allowed end - logger.info("encoding AMF results") - sendresponse(results) end private @@ -220,7 +228,7 @@ class AmfController < ApplicationController [0, ways, points, relations] rescue Exception => err - [-2,"Sorry - I can't get the map for that area."] + [-2,"Sorry - I can't get the map for that area. The server said: #{err}"] end # Find deleted ways in current bounding box (similar to whichways, but ways @@ -236,7 +244,7 @@ class AmfController < ApplicationController begin check_boundaries(xmin, ymin, xmax, ymax) rescue Exception => err - return [-2,"Sorry - I can't get the map for that area."] + return [-2,"Sorry - I can't get the map for that area. The server said: #{err}"] end nodes_in_area = Node.find_by_area(ymin, xmin, ymax, xmax, :conditions => ["current_ways.visible = ?", false], :include => :ways_via_history) @@ -258,7 +266,7 @@ class AmfController < ApplicationController # then rails only seems to return the first copy of a node when a # way includes a node more than once begin - way = Way.find(wayid) + way = Way.find(wayid, :include => { :nodes => :node_tags }) rescue ActiveRecord::RecordNotFound return [wayid,[],{}] end @@ -436,12 +444,12 @@ class AmfController < ApplicationController if searchterm.to_i>0 then rel = Relation.find(searchterm.to_i) if rel and rel.visible then - rels.push([rel.id, rel.tags, rel.members]) + rels.push([rel.id, rel.tags, rel.members, rel.version]) end else RelationTag.find(:all, :limit => 11, :conditions => ["match(v) against (?)", searchterm] ).each do |t| if t.relation.visible then - rels.push([t.relation.id, t.relation.tags, t.relation.members]) + rels.push([t.relation.id, t.relation.tags, t.relation.members, t.relation.version]) end end end @@ -477,8 +485,8 @@ class AmfController < ApplicationController members.each do |m| mid = m[1].to_i if mid < 0 - mid = renumberednodes[mid] if m[0] == 'node' - mid = renumberedways[mid] if m[0] == 'way' + mid = renumberednodes[mid] if m[0] == 'Node' + mid = renumberedways[mid] if m[0] == 'Way' end if mid typedmembers << [m[0], mid, m[2]] @@ -515,12 +523,12 @@ class AmfController < ApplicationController # Really need to check to see whether this is a server load issue, and the # last version was in the same changeset, or belongs to the same user, then # we can return something different - return [-3, "Sorry, someone else has changed this relation since you started editing. Please click the 'Edit' tab to reload the area."] + return [-3, "Sorry, someone else has changed this relation since you started editing. Please click the 'Edit' tab to reload the area. The server said: #{ex}"] rescue OSM::APIAlreadyDeletedError => ex return [-1, "The relation has already been deleted."] rescue OSM::APIError => ex # Some error that we don't specifically catch - return [-2, "An unusual error happened (in 'putrelation' #{relid})."] + return [-2, "An unusual error happened (in 'putrelation' #{relid}). The server said: #{ex}"] end # Save a way to the database, including all nodes. Any nodes in the previous @@ -621,7 +629,7 @@ class AmfController < ApplicationController uniques=uniques-pointlist uniques.each do |n| node = Node.find(n) - deleteitemrelations(user, changeset_id, id, 'node', node.version) + deleteitemrelations(user, changeset_id, id, 'Node', node.version) new_node = Node.new new_node.changeset_id = changeset_id new_node.version = node.version @@ -637,14 +645,14 @@ class AmfController < ApplicationController # Really need to check to see whether this is a server load issue, and the # last version was in the same changeset, or belongs to the same user, then # we can return something different - return [-3, "Sorry, someone else has changed this way since you started editing. Please click the 'Edit' tab to reload the area."] + return [-3, "Sorry, someone else has changed this way since you started editing. Click the 'Edit' tab to reload the area. The server said: #{ex}"] rescue OSM::APITooManyWayNodesError => ex return [-1, "You have tried to upload a really long way with #{ex.provided} points: only #{ex.max} are allowed."] rescue OSM::APIAlreadyDeletedError => ex return [-1, "The point has already been deleted."] rescue OSM::APIError => ex # Some error that we don't specifically catch - return [-2, "An unusual error happened (in 'putway' #{originalway})."] + return [-2, "An unusual error happened (in 'putway' #{originalway}). The server said: #{ex}"] end # Save POI to the database. @@ -702,28 +710,28 @@ class AmfController < ApplicationController # Really need to check to see whether this is a server load issue, and the # last version was in the same changeset, or belongs to the same user, then # we can return something different - return [-3, "Sorry, someone else has changed this point since you started editing. Please click the 'Edit' tab to reload the area."] + return [-3, "Sorry, someone else has changed this point since you started editing. Please click the 'Edit' tab to reload the area. The server said: #{ex}"] rescue OSM::APIAlreadyDeletedError => ex return [-1, "The point has already been deleted"] rescue OSM::APIError => ex # Some error that we don't specifically catch - return [-2, "An unusual error happened (in 'putpoi' #{id})."] + return [-2, "An unusual error happened (in 'putpoi' #{id}). The server said: #{ex}"] end # Read POI from database # (only called on revert: POIs are usually read by whichways). # - # Returns array of id, long, lat, hash of tags, version. + # Returns array of id, long, lat, hash of tags, (current) version. def getpoi(id,timestamp) #:doc: - if timestamp == '' then - n = Node.find(id) - else + n = Node.find(id) + v = n.version + unless timestamp == '' n = OldNode.find(id, :conditions=>['timestamp=?',DateTime.strptime(timestamp, "%d %b %Y, %H:%M:%S")]) end if n - return [n.id, n.lon, n.lat, n.tags, n.version] + return [n.id, n.lon, n.lat, n.tags, v] else return [nil, nil, nil, {}, nil] end @@ -765,7 +773,7 @@ class AmfController < ApplicationController else # in case the node wasn't passed (i.e. if it was previously removed # from the way in Potlatch) - deleteitemrelations(user, changeset_id, node_id, 'node', node.version) + deleteitemrelations(user, changeset_id, node_id, 'Node', node.version) delete_node.version = node.version end node.delete_with_history!(delete_node, user) @@ -783,7 +791,7 @@ class AmfController < ApplicationController return [-1, "The way has already been deleted."] rescue OSM::APIError => ex # Some error that we don't specifically catch - return [-2, "An unusual error happened (in 'deleteway' #{way_id})."] + return [-2, "An unusual error happened (in 'deleteway' #{way_id}). The server said: #{ex}"] end