3 # The Potlatch module provides helper functions for potlatch and its communication with the server
6 # The AMF class is a set of helper functions for encoding and decoding AMF.
9 # Return two-byte integer
11 s.getbyte*256+s.getbyte
14 # Return four-byte long
16 ((s.getbyte*256+s.getbyte)*256+s.getbyte)*256+s.getbyte
19 # Return string with two-byte length
21 len=s.getbyte*256+s.getbyte
23 str.force_encoding("UTF-8") if str.respond_to?("force_encoding")
27 # Return eight-byte double-precision float
29 a=s.read(8).unpack('G') # G big-endian, E little-endian
33 # Return numeric array
46 while (key=getstring(s))
47 if (key=='') then break end
50 s.getbyte # skip the 9 'end of object' value
57 when 0; return getdouble(s) # number
58 when 1; return s.getbyte # boolean
59 when 2; return getstring(s) # string
60 when 3; return getobject(s) # object/hash
61 when 5; return nil # null
62 when 6; return nil # undefined
63 when 8; s.read(4) # mixedArray
64 return getobject(s) # |
65 when 10; return getarray(s) # array
66 else; return nil # error
70 # Envelope data into AMF writeable form
71 def self.putdata(index,n)
72 d =encodestring(index+"/onResult")
73 d+=encodestring("null")
78 # Pack variables as AMF
79 def self.encodevalue(n)
82 a=10.chr+encodelong(n.length)
90 a+=encodestring(k.to_s)+encodevalue(v)
95 when 'Bignum','Fixnum','Float'
100 0.chr+encodedouble(1)
102 0.chr+encodedouble(0)
104 Rails.logger.error("Unexpected Ruby type for AMF conversion: "+n.class.to_s)
108 # Encode string with two-byte length
109 def self.encodestring(n)
110 n=n.dup.force_encoding("ASCII-8BIT")
111 a,b=n.size.divmod(256)
115 # Encode number as eight-byte double precision float
116 def self.encodedouble(n)
120 # Encode number as four-byte long
121 def self.encodelong(n)
127 # The Dispatcher class handles decoding a series of RPC calls
128 # from the request, dispatching them, and encoding the response
130 def initialize(request, &block)
131 # Get stream for request data
132 @request = StringIO.new(request + 0.chr)
134 # Skip version indicator and client ID
138 AMF.getint(@request).times do # Read number of headers and loop
139 AMF.getstring(@request) # | skip name
140 req.getbyte # | skip boolean
141 AMF.getvalue(@request) # | skip value
144 # Capture the dispatch routine
149 # Read number of message bodies
150 bodies = AMF.getint(@request)
152 # Output response header
153 a,b = bodies.divmod(256)
154 yield 0.chr + 0.chr + 0.chr + 0.chr + a.chr + b.chr
157 bodies.times do # Read each body
158 name = AMF.getstring(@request) # | get message name
159 index = AMF.getstring(@request) # | get index in response sequence
160 bytes = AMF.getlong(@request) # | get total size in bytes
161 args = AMF.getvalue(@request) # | get response (probably an array)
163 result = @dispatch.call(name, *args)
165 yield AMF.putdata(index, result)
170 # The Potlatch class is a helper for Potlatch
175 # does: reads tag preset menus, colours, and autocomplete config files
176 # out: [0] presets, [1] presetmenus, [2] presetnames,
177 # [3] colours, [4] casing, [5] areas, [6] autotags
180 Rails.logger.info(" Message: getpresets")
184 presetmenus={}; presetmenus['point']=[]; presetmenus['way']=[]; presetmenus['POI']=[]
185 presetnames={}; presetnames['point']={}; presetnames['way']={}; presetnames['POI']={}
188 # StringIO.open(txt) do |file|
189 File.open("#{Rails.root}/config/potlatch/presets.txt") do |file|
190 file.each_line {|line|
192 if (t=~/(\w+)\/(\w+)/) then
195 presetmenus[presettype].push(presetcategory)
196 presetnames[presettype][presetcategory]=["(no preset)"]
197 elsif (t=~/^([\w\s]+):\s?(.+)$/) then
199 presetnames[presettype][presetcategory].push(pre)
201 kv.split(',').each {|a|
202 if (a=~/^(.+)=(.*)$/) then presets[pre][$1]=$2 end
208 # Read colours/styling
209 colours={}; casing={}; areas={}
210 File.open("#{Rails.root}/config/potlatch/colours.txt") do |file|
211 file.each_line {|line|
213 if (t=~/(\w+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)/) then
215 if ($2!='-') then colours[tag]=$2.hex end
216 if ($3!='-') then casing[tag]=$3.hex end
217 if ($4!='-') then areas[tag]=$4.hex end
222 # Read relations colours/styling
223 relcolours={}; relalphas={}; relwidths={}
224 File.open("#{Rails.root}/config/potlatch/relation_colours.txt") do |file|
225 file.each_line {|line|
227 if (t=~/(\w+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)/) then
229 if ($2!='-') then relcolours[tag]=$2.hex end
230 if ($3!='-') then relalphas[tag]=$3.to_i end
231 if ($4!='-') then relwidths[tag]=$4.to_i end
237 icon_list=[]; icon_tags={};
238 File.open("#{Rails.root}/config/potlatch/icon_presets.txt") do |file|
239 file.each_line {|line|
240 (icon,tags)=line.chomp.split("\t")
242 icon_tags[icon]=Hash[*tags.scan(/([^;=]+)=([^;=]+)/).flatten]
248 autotags={}; autotags['point']={}; autotags['way']={}; autotags['POI']={};
249 File.open("#{Rails.root}/config/potlatch/autocomplete.txt") do |file|
250 file.each_line {|line|
252 if (t=~/^([\w:]+)\/(\w+)\s+(.+)$/) then
253 tag=$1; type=$2; values=$3
254 if values=='-' then autotags[type][tag]=[]
255 else autotags[type][tag]=values.split(',').sort.reverse end
260 [presets,presetmenus,presetnames,colours,casing,areas,autotags,relcolours,relalphas,relwidths,icon_list,{},icon_tags]