ibid
[rails.git] / lib / potlatch.rb
1 # The Potlatch module provides helper functions for potlatch and its communication with the server
2 module Potlatch
3
4   # The AMF class is a set of helper functions for encoding and decoding AMF.
5   class AMF
6     
7     # Return two-byte integer
8     def self.getint(s) 
9       s.getc*256+s.getc
10     end
11
12     # Return four-byte long
13     def self.getlong(s) 
14       ((s.getc*256+s.getc)*256+s.getc)*256+s.getc
15     end
16
17     # Return string with two-byte length 
18     def self.getstring(s) 
19       len=s.getc*256+s.getc
20       s.read(len)
21     end
22
23     # Return eight-byte double-precision float 
24     def self.getdouble(s) 
25       a=s.read(8).unpack('G')                   # G big-endian, E little-endian
26       a[0]
27     end
28
29     # Return numeric array
30     def self.getarray(s) 
31       len=getlong(s)
32       arr=[]
33       for i in (0..len-1)
34         arr[i]=getvalue(s)
35       end
36       arr
37     end
38
39     # Return object/hash 
40     def self.getobject(s) 
41       arr={}
42       while (key=getstring(s))
43         if (key=='') then break end
44         arr[key]=getvalue(s)
45       end
46       s.getc            # skip the 9 'end of object' value
47       arr
48     end
49
50     # Parse and get value
51     def self.getvalue(s) 
52       case s.getc
53       when 0;   return getdouble(s)                     # number
54       when 1;   return s.getc                           # boolean
55       when 2;   return getstring(s)                     # string
56       when 3;   return getobject(s)                     # object/hash
57       when 5;   return nil                                      # null
58       when 6;   return nil                                      # undefined
59       when 8;   s.read(4)                                       # mixedArray
60         return getobject(s)                     #  |
61       when 10;return getarray(s)                        # array
62       else;     return nil                                      # error
63       end
64     end
65
66     # Envelope data into AMF writeable form
67     def self.putdata(index,n) 
68       d =encodestring(index+"/onResult")
69       d+=encodestring("null")
70       d+=[-1].pack("N")
71       d+=encodevalue(n)
72     end
73
74     # Pack variables as AMF
75     def self.encodevalue(n) 
76       case n.class.to_s
77       when 'Array'
78         a=10.chr+encodelong(n.length)
79         n.each do |b|
80           a+=encodevalue(b)
81         end
82         a
83       when 'Hash'
84         a=3.chr
85         n.each do |k,v|
86           a+=encodestring(k.to_s)+encodevalue(v)
87         end
88         a+0.chr+0.chr+9.chr
89       when 'String'
90         2.chr+encodestring(n)
91       when 'Bignum','Fixnum','Float'
92         0.chr+encodedouble(n)
93       when 'NilClass'
94         5.chr
95           when 'TrueClass'
96         0.chr+encodedouble(1)
97           when 'FalseClass'
98         0.chr+encodedouble(0)
99       else
100         RAILS_DEFAULT_LOGGER.error("Unexpected Ruby type for AMF conversion: "+n.class.to_s)
101       end
102     end
103
104     # Encode string with two-byte length
105     def self.encodestring(n) 
106       a,b=n.size.divmod(256)
107       a.chr+b.chr+n
108     end
109
110     # Encode number as eight-byte double precision float 
111     def self.encodedouble(n) 
112       [n].pack('G')
113     end
114
115     # Encode number as four-byte long
116     def self.encodelong(n) 
117       [n].pack('N')
118     end
119
120   end
121
122
123   # The Potlatch class is a helper for Potlatch
124   class Potlatch
125
126     # ----- getpresets
127     #             in:   none
128     #             does: reads tag preset menus, colours, and autocomplete config files
129     #         out:  [0] presets, [1] presetmenus, [2] presetnames,
130     #                           [3] colours, [4] casing, [5] areas, [6] autotags
131     #                           (all hashes)
132     def self.get_presets
133       RAILS_DEFAULT_LOGGER.info("  Message: getpresets")
134
135       # Read preset menus
136       presets={}
137       presetmenus={}; presetmenus['point']=[]; presetmenus['way']=[]; presetmenus['POI']=[]
138       presetnames={}; presetnames['point']={}; presetnames['way']={}; presetnames['POI']={}
139       presettype=''
140       presetcategory=''
141       # StringIO.open(txt) do |file|
142       File.open("#{RAILS_ROOT}/config/potlatch/presets.txt") do |file|
143         file.each_line {|line|
144           t=line.chomp
145           if (t=~/(\w+)\/(\w+)/) then
146             presettype=$1
147             presetcategory=$2
148             presetmenus[presettype].push(presetcategory)
149             presetnames[presettype][presetcategory]=["(no preset)"]
150           elsif (t=~/^([\w\s]+):\s?(.+)$/) then
151             pre=$1; kv=$2
152             presetnames[presettype][presetcategory].push(pre)
153             presets[pre]={}
154             kv.split(',').each {|a|
155               if (a=~/^(.+)=(.*)$/) then presets[pre][$1]=$2 end
156             }
157           end
158         }
159       end
160
161       # Read colours/styling
162       colours={}; casing={}; areas={}
163       File.open("#{RAILS_ROOT}/config/potlatch/colours.txt") do |file|
164         file.each_line {|line|
165           t=line.chomp
166           if (t=~/(\w+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)/) then
167             tag=$1
168             if ($2!='-') then colours[tag]=$2.hex end
169             if ($3!='-') then casing[tag]=$3.hex end
170             if ($4!='-') then areas[tag]=$4.hex end
171           end
172         }
173       end
174
175       # Read relations colours/styling
176       relcolours={}; relalphas={}; relwidths={}
177       File.open("#{RAILS_ROOT}/config/potlatch/relation_colours.txt") do |file|
178         file.each_line {|line|
179           t=line.chomp
180           if (t=~/(\w+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)/) then
181             tag=$1
182             if ($2!='-') then relcolours[tag]=$2.hex end
183             if ($3!='-') then relalphas[tag]=$3.to_i end
184             if ($4!='-') then relwidths[tag]=$4.to_i end
185           end
186         }
187       end
188
189       # Read auto-complete
190       autotags={}; autotags['point']={}; autotags['way']={}; autotags['POI']={};
191       File.open("#{RAILS_ROOT}/config/potlatch/autocomplete.txt") do |file|
192         file.each_line {|line|
193           t=line.chomp
194           if (t=~/^([\w:]+)\/(\w+)\s+(.+)$/) then
195             tag=$1; type=$2; values=$3
196             if values=='-' then autotags[type][tag]=[]
197             else autotags[type][tag]=values.split(',').sort.reverse end
198           end
199         }
200       end
201
202           # Read internationalisation
203           localised = YAML::load(File.open("#{RAILS_ROOT}/config/potlatch/localised.yaml"))
204
205       [presets,presetmenus,presetnames,colours,casing,areas,autotags,relcolours,relalphas,relwidths,localised]
206     end
207   end
208
209 end
210