]> git.openstreetmap.org Git - rails.git/blobdiff - lib/potlatch.rb
Cleanup trailing whitespace
[rails.git] / lib / potlatch.rb
index 7a7926f043864f74fe7128b47cd6b4d9bf987257..bd2c905fecf73d49a706520bb54f143dd2a637f5 100644 (file)
@@ -1,33 +1,37 @@
+require 'stringio'
+
 # The Potlatch module provides helper functions for potlatch and its communication with the server
 module Potlatch
 
   # The AMF class is a set of helper functions for encoding and decoding AMF.
   class AMF
-    
+
     # Return two-byte integer
-    def self.getint(s) 
-      s.getc*256+s.getc
+    def self.getint(s)
+      s.getbyte*256+s.getbyte
     end
 
     # Return four-byte long
-    def self.getlong(s) 
-      ((s.getc*256+s.getc)*256+s.getc)*256+s.getc
+    def self.getlong(s)
+      ((s.getbyte*256+s.getbyte)*256+s.getbyte)*256+s.getbyte
     end
 
-    # Return string with two-byte length 
-    def self.getstring(s) 
-      len=s.getc*256+s.getc
-      s.read(len)
+    # Return string with two-byte length
+    def self.getstring(s)
+      len=s.getbyte*256+s.getbyte
+      str=s.read(len)
+      str.force_encoding("UTF-8") if str.respond_to?("force_encoding")
+      str
     end
 
-    # Return eight-byte double-precision float 
-    def self.getdouble(s) 
+    # Return eight-byte double-precision float
+    def self.getdouble(s)
       a=s.read(8).unpack('G')                  # G big-endian, E little-endian
       a[0]
     end
 
     # Return numeric array
-    def self.getarray(s) 
+    def self.getarray(s)
       len=getlong(s)
       arr=[]
       for i in (0..len-1)
@@ -36,35 +40,35 @@ module Potlatch
       arr
     end
 
-    # Return object/hash 
-    def self.getobject(s) 
+    # Return object/hash
+    def self.getobject(s)
       arr={}
       while (key=getstring(s))
         if (key=='') then break end
         arr[key]=getvalue(s)
       end
-      s.getc           # skip the 9 'end of object' value
+      s.getbyte                # skip the 9 'end of object' value
       arr
     end
 
     # Parse and get value
-    def self.getvalue(s) 
-      case s.getc
+    def self.getvalue(s)
+      case s.getbyte
       when 0;  return getdouble(s)                     # number
-      when 1;  return s.getc                           # boolean
+      when 1;  return s.getbyte                        # boolean
       when 2;  return getstring(s)                     # string
       when 3;  return getobject(s)                     # object/hash
-      when 5;  return nil                                      # null
-      when 6;  return nil                                      # undefined
-      when 8;  s.read(4)                                       # mixedArray
-        return getobject(s)                    #  |
-      when 10;return getarray(s)                       # array
-      else;    return nil                                      # error
+      when 5;  return nil                              # null
+      when 6;  return nil                              # undefined
+      when 8;  s.read(4)                               # mixedArray
+                return getobject(s)                    #  |
+      when 10;  return getarray(s)                     # array
+      else;    return nil                              # error
       end
     end
 
     # Envelope data into AMF writeable form
-    def self.putdata(index,n) 
+    def self.putdata(index,n)
       d =encodestring(index+"/onResult")
       d+=encodestring("null")
       d+=[-1].pack("N")
@@ -72,7 +76,7 @@ module Potlatch
     end
 
     # Pack variables as AMF
-    def self.encodevalue(n) 
+    def self.encodevalue(n)
       case n.class.to_s
       when 'Array'
         a=10.chr+encodelong(n.length)
@@ -97,28 +101,71 @@ module Potlatch
          when 'FalseClass'
         0.chr+encodedouble(0)
       else
-        RAILS_DEFAULT_LOGGER.error("Unexpected Ruby type for AMF conversion: "+n.class.to_s)
+        Rails.logger.error("Unexpected Ruby type for AMF conversion: "+n.class.to_s)
       end
     end
 
     # Encode string with two-byte length
-    def self.encodestring(n) 
+    def self.encodestring(n)
+      n=n.dup.force_encoding("ASCII-8BIT") if n.respond_to?("force_encoding")
       a,b=n.size.divmod(256)
       a.chr+b.chr+n
     end
 
-    # Encode number as eight-byte double precision float 
-    def self.encodedouble(n) 
+    # Encode number as eight-byte double precision float
+    def self.encodedouble(n)
       [n].pack('G')
     end
 
     # Encode number as four-byte long
-    def self.encodelong(n) 
+    def self.encodelong(n)
       [n].pack('N')
     end
 
   end
 
+  # The Dispatcher class handles decoding a series of RPC calls
+  # from the request, dispatching them, and encoding the response
+  class Dispatcher
+    def initialize(request, &block)
+      # Get stream for request data
+      @request = StringIO.new(request + 0.chr)
+
+      # Skip version indicator and client ID
+      @request.read(2)
+
+      # Skip headers
+      AMF.getint(@request).times do     # Read number of headers and loop
+        AMF.getstring(@request)         #  | skip name
+        req.getbyte                     #  | skip boolean
+        AMF.getvalue(@request)          #  | skip value
+      end
+
+      # Capture the dispatch routine
+      @dispatch = Proc.new
+    end
+
+    def each(&block)
+      # Read number of message bodies
+      bodies = AMF.getint(@request)
+
+      # Output response header
+      a,b = bodies.divmod(256)
+      yield 0.chr + 0.chr + 0.chr + 0.chr + a.chr + b.chr
+
+      # Process the bodies
+      bodies.times do                     # Read each body
+        name = AMF.getstring(@request)    #  | get message name
+        index = AMF.getstring(@request)   #  | get index in response sequence
+        bytes = AMF.getlong(@request)     #  | get total size in bytes
+        args = AMF.getvalue(@request)     #  | get response (probably an array)
+
+        result = @dispatch.call(name, *args)
+
+        yield AMF.putdata(index, result)
+      end
+    end
+  end
 
   # The Potlatch class is a helper for Potlatch
   class Potlatch
@@ -130,7 +177,7 @@ module Potlatch
     #                          [3] colours, [4] casing, [5] areas, [6] autotags
     #                          (all hashes)
     def self.get_presets
-      RAILS_DEFAULT_LOGGER.info("  Message: getpresets")
+      Rails.logger.info("  Message: getpresets")
 
       # Read preset menus
       presets={}
@@ -139,7 +186,7 @@ module Potlatch
       presettype=''
       presetcategory=''
       #        StringIO.open(txt) do |file|
-      File.open("#{RAILS_ROOT}/config/potlatch/presets.txt") do |file|
+      File.open("#{Rails.root}/config/potlatch/presets.txt") do |file|
         file.each_line {|line|
           t=line.chomp
           if (t=~/(\w+)\/(\w+)/) then
@@ -160,7 +207,7 @@ module Potlatch
 
       # Read colours/styling
       colours={}; casing={}; areas={}
-      File.open("#{RAILS_ROOT}/config/potlatch/colours.txt") do |file|
+      File.open("#{Rails.root}/config/potlatch/colours.txt") do |file|
         file.each_line {|line|
           t=line.chomp
           if (t=~/(\w+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)/) then
@@ -174,7 +221,7 @@ module Potlatch
 
       # Read relations colours/styling
       relcolours={}; relalphas={}; relwidths={}
-      File.open("#{RAILS_ROOT}/config/potlatch/relation_colours.txt") do |file|
+      File.open("#{Rails.root}/config/potlatch/relation_colours.txt") do |file|
         file.each_line {|line|
           t=line.chomp
           if (t=~/(\w+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)/) then
@@ -187,20 +234,19 @@ module Potlatch
       end
 
       # Read POI presets
-      icon_list=[]; icon_names={}; icon_tags={};
-      File.open("#{RAILS_ROOT}/config/potlatch/icon_presets.txt") do |file|
+      icon_list=[]; icon_tags={};
+      File.open("#{Rails.root}/config/potlatch/icon_presets.txt") do |file|
         file.each_line {|line|
-          (icon,name,tags)=line.chomp.split("\t")
+          (icon,tags)=line.chomp.split("\t")
           icon_list.push(icon)
-          icon_names[icon]=name
           icon_tags[icon]=Hash[*tags.scan(/([^;=]+)=([^;=]+)/).flatten]
         }
       end
       icon_list.reverse!
-      
+
       # Read auto-complete
       autotags={}; autotags['point']={}; autotags['way']={}; autotags['POI']={};
-      File.open("#{RAILS_ROOT}/config/potlatch/autocomplete.txt") do |file|
+      File.open("#{Rails.root}/config/potlatch/autocomplete.txt") do |file|
         file.each_line {|line|
           t=line.chomp
           if (t=~/^([\w:]+)\/(\w+)\s+(.+)$/) then
@@ -211,9 +257,8 @@ module Potlatch
         }
       end
 
-      [presets,presetmenus,presetnames,colours,casing,areas,autotags,relcolours,relalphas,relwidths,icon_list,icon_names,icon_tags]
+      [presets,presetmenus,presetnames,colours,casing,areas,autotags,relcolours,relalphas,relwidths,icon_list,{},icon_tags]
     end
   end
 
 end
-