vistarpc4r 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +12 -2
- data/VERSION +1 -1
- data/examples/test.rb +23 -37
- data/lib/vistarpc4r/rpc_broker_connection.rb +418 -369
- data/lib/vistarpc4r/rpc_response.rb +48 -39
- data/lib/vistarpc4r/vista_rpc.rb +58 -52
- data/vistarpc4r.gemspec +2 -2
- metadata +5 -5
data/README.rdoc
CHANGED
@@ -1,6 +1,16 @@
|
|
1
|
-
=
|
1
|
+
= VistaRPC4r
|
2
|
+
VistaRPC4r provides a Ruby interface to the Veterans Administration's almost opensource electronic health record called VistA.
|
3
|
+
The VistA architecture is old school client/server. The typical client is a Windows based GUI. The typical server is an Linux or Windows based server. The server is primarily written in MUMPS or M.
|
4
|
+
VistA provides an RPC-style interface to its core functions using TCP sockets and a custom message format
|
5
|
+
VistaRPC4r implements the socket layer and message format and provides methods which can initiate RPC requests and returns the RPC output.
|
6
|
+
The VistA server requires each connection to have a username/password authentication.
|
2
7
|
|
3
|
-
|
8
|
+
This gem has been tested with Medsphere's OpenVista server distribution.
|
9
|
+
|
10
|
+
Future topics for this document
|
11
|
+
* More detail on how to use
|
12
|
+
* Detailed examples
|
13
|
+
* links to more information
|
4
14
|
|
5
15
|
== Contributing to vistarpc4r
|
6
16
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
data/examples/test.rb
CHANGED
@@ -1,20 +1,20 @@
|
|
1
|
-
require '
|
1
|
+
require './../lib/vistarpc4r/rpc_response'
|
2
|
+
require './../lib/vistarpc4r/vista_rpc'
|
3
|
+
require './../lib/vistarpc4r/rpc_broker_connection'
|
2
4
|
|
3
5
|
#broker = RPCBrokerConnection.new('192.168.1.20', 9270, 'sys.admin', 'vista!123')
|
4
|
-
broker = RPCBrokerConnection.new('openvista.medsphere.org', 9201, 'PU1234', 'PU1234!!')
|
6
|
+
broker = VistaRPC4r::RPCBrokerConnection.new('openvista.medsphere.org', 9201, 'PU1234', 'PU1234!!')
|
5
7
|
|
6
8
|
broker.connect
|
7
9
|
broker.setContext('OR CPRS GUI CHART')
|
8
10
|
|
9
|
-
|
10
|
-
|
11
|
-
|
11
|
+
patient_ien = "4"
|
12
|
+
wardsarray = broker.call_a("ORQPT WARDS")
|
13
|
+
wardsarray.each do |ward|
|
12
14
|
a = ward.split("^")
|
13
15
|
puts "Ward:" + a[1]
|
14
|
-
|
15
|
-
|
16
|
-
wardresponse = broker.execute(wardrpc)
|
17
|
-
wardresponse.value.each do |patient|
|
16
|
+
wardarray = broker.call_a("ORQPT WARD PATIENTS", [a[0]]) # ward ien
|
17
|
+
wardarray.each do |patient|
|
18
18
|
b = patient.split("^")
|
19
19
|
puts b[0] + ":" + b[1]
|
20
20
|
end
|
@@ -22,63 +22,49 @@ end
|
|
22
22
|
|
23
23
|
# Problem list
|
24
24
|
puts "Problem list-------------------------------------"
|
25
|
-
|
26
|
-
|
27
|
-
patientrpc.params[1]="A" #patient ien
|
28
|
-
patientresponse = broker.execute(patientrpc)
|
29
|
-
patientresponse.value.each do |d|
|
25
|
+
patientarray = broker.call_a("ORQQPL LIST", [patient_ien, "A"])
|
26
|
+
patientarray.each do |d|
|
30
27
|
puts d
|
31
28
|
end
|
32
29
|
|
33
30
|
# Medications
|
34
31
|
puts "Medications-------------------------------------"
|
35
|
-
|
36
|
-
|
37
|
-
patientresponse = broker.execute(patientrpc)
|
38
|
-
patientresponse.value.each do |d|
|
32
|
+
patientarray = broker.call_a("ORWPS COVER", [patient_ien])
|
33
|
+
patientarray.each do |d|
|
39
34
|
puts d
|
40
35
|
end
|
41
36
|
|
42
37
|
#Labs
|
43
38
|
puts "Labs-------------------------------------"
|
44
|
-
|
45
|
-
|
46
|
-
patientresponse = broker.execute(patientrpc)
|
47
|
-
patientresponse.value.each do |d|
|
39
|
+
patientarray = broker.call_a("ORWCV LAB", [patient_ien])
|
40
|
+
patientarray.each do |d|
|
48
41
|
puts d
|
49
42
|
end
|
50
43
|
|
51
44
|
# Vitals
|
52
45
|
puts "Vitals-------------------------------------"
|
53
|
-
|
54
|
-
|
55
|
-
patientresponse = broker.execute(patientrpc)
|
56
|
-
patientresponse.value.each do |d|
|
46
|
+
patientarray = broker.call_a("ORQQVI VITALS", [patient_ien])
|
47
|
+
patientarray.each do |d|
|
57
48
|
puts d
|
58
49
|
end
|
59
50
|
|
60
51
|
# Demo
|
61
52
|
puts "Demographics-------------------------------------"
|
62
|
-
|
63
|
-
|
64
|
-
patientresponse = broker.execute(patientrpc)
|
65
|
-
patientresponse.value.each do |d|
|
53
|
+
patientarray = broker.call_a("ORWPT PTINQ", [patient_ien])
|
54
|
+
patientarray.each do |d|
|
66
55
|
puts d
|
67
56
|
end
|
68
57
|
|
69
58
|
#visits
|
70
59
|
puts "Visits-------------------------------------"
|
71
|
-
|
72
|
-
|
73
|
-
patientresponse = broker.execute(patientrpc)
|
74
|
-
patientresponse.value.each do |d|
|
60
|
+
patientarray = broker.call_a("ORWCV VST", [patient_ien])
|
61
|
+
patientarray.each do |d|
|
75
62
|
puts d
|
76
63
|
end
|
77
64
|
|
78
65
|
#providers
|
79
66
|
puts "Providers---------------------------------"
|
80
|
-
|
81
|
-
|
82
|
-
patientresponse.value.each do |d|
|
67
|
+
patientarray = broker.call_a("ORQPT PROVIDERS")
|
68
|
+
patientarray.each do |d|
|
83
69
|
puts d
|
84
70
|
end
|
@@ -3,427 +3,476 @@ require 'socket'
|
|
3
3
|
#require 'vista_rpc'
|
4
4
|
|
5
5
|
module VistaRPC4r
|
6
|
-
class RPCBrokerConnection
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
def connect
|
47
|
-
retVal = true
|
48
|
-
if isConnected()
|
49
|
-
puts " already connected, closing first"
|
50
|
-
close
|
6
|
+
class RPCBrokerConnection
|
7
|
+
# Header chunk types
|
8
|
+
CHUNK_TYPE_HEADER = "1"
|
9
|
+
CHUNK_TYPE_RPC = "2"
|
10
|
+
CHUNK_TYPE_SECURITY = "3"
|
11
|
+
CHUNK_TYPE_COMMAND = "4"
|
12
|
+
CHUNK_TYPE_DATA = "5"
|
13
|
+
XWB_HEADER = "[XWB]"
|
14
|
+
# Header and protocol info
|
15
|
+
VISTA_RPC_VERSION = "1"
|
16
|
+
VISTA_RPC_TYPE_CMD = "0"
|
17
|
+
VISTA_RPC_TYPE_RPC = "1"
|
18
|
+
VISTA_RPC_LENV = 3
|
19
|
+
VISTA_RPC_LENV_STR = "3"
|
20
|
+
VISTA_RPC_RETURN_DATA = "0"
|
21
|
+
VISTA_RPC_NO_RETURN_DATA = "1"
|
22
|
+
END_MARKER = 4
|
23
|
+
# Parameter types
|
24
|
+
PARAM_LITERAL_MARKER = "0"
|
25
|
+
PARAM_REFERENCE_MARKER = "1"
|
26
|
+
PARAM_LIST_MARKER = "2"
|
27
|
+
PARAM_GLOBAL_MARKER = "3"
|
28
|
+
PARAM_EMPTY_MARKER = "4"
|
29
|
+
|
30
|
+
public
|
31
|
+
|
32
|
+
def initialize(host, port, access, verify, debug=FALSE)
|
33
|
+
@sentConnect = false
|
34
|
+
@signedOn = false
|
35
|
+
@host=host
|
36
|
+
@port=port
|
37
|
+
@access=access
|
38
|
+
@verify=verify
|
39
|
+
@debug=debug
|
40
|
+
@token=nil
|
41
|
+
@socket = nil
|
42
|
+
@encryptedAV = nil
|
43
|
+
@writeBuffer = String.new
|
44
|
+
@duz = "0"
|
45
|
+
@currentContext = nil
|
51
46
|
end
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
47
|
+
|
48
|
+
def connect
|
49
|
+
retVal = true
|
50
|
+
if isConnected()
|
51
|
+
puts " already connected, closing first"
|
52
|
+
close
|
53
|
+
end
|
54
|
+
@socket = TCPSocket.open(@host, @port) # Connect
|
55
|
+
# socket.setTcpNoDelay(true)
|
56
|
+
tcpConnect = VistaRPC.new("TCPConnect", RPCResponse::SINGLE_VALUE, true)
|
57
|
+
tcpConnect.params[0]= @socket.addr[4] # local IP address
|
58
|
+
tcpConnect.params[1]= "0" # callback port ?
|
59
|
+
tcpConnect.params[2]= "OVID"
|
60
|
+
connectResponse = execute(tcpConnect)
|
61
|
+
if (connectResponse == nil || connectResponse.value == nil || connectResponse.value == "reject")
|
62
|
+
puts "Handshake error"
|
63
|
+
end
|
64
|
+
if (connectResponse.error_message != nil)
|
65
|
+
puts "RPC Error: " + connectResponse.error_message
|
66
|
+
end
|
67
|
+
@sentConnect = true
|
68
|
+
|
69
|
+
signOn()
|
70
|
+
retVal = logIn()
|
71
|
+
return retVal
|
61
72
|
end
|
62
|
-
|
63
|
-
|
73
|
+
|
74
|
+
def close()
|
75
|
+
if isConnected()
|
76
|
+
if @sentConnect
|
77
|
+
@sentConnect = false
|
78
|
+
bye = VistaRPC.new("#BYE#", RPCResponse::SINGLE_VALUE, true)
|
79
|
+
execute(bye)
|
80
|
+
@socket.close()
|
81
|
+
@socket = nil
|
82
|
+
end
|
83
|
+
end
|
64
84
|
end
|
65
|
-
@sentConnect = true
|
66
85
|
|
67
|
-
|
68
|
-
|
69
|
-
return retVal
|
70
|
-
end
|
71
|
-
|
72
|
-
def signOn()
|
73
|
-
signonResponse = execute(VistaRPC.new("XUS SIGNON SETUP", RPCResponse::ARRAY))
|
74
|
-
if (signonResponse == nil || signonResponse.error_message != nil)
|
75
|
-
puts "XUS SIGNON SETUP failed"
|
86
|
+
def isConnected()
|
87
|
+
return @socket != nil
|
76
88
|
end
|
77
|
-
@signedOn = true
|
78
|
-
end
|
79
|
-
|
80
|
-
def logIn()
|
81
|
-
xusAvCode = VistaRPC.new("XUS AV CODE", RPCResponse::ARRAY)
|
82
|
-
@duz = "0"
|
83
89
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
90
|
+
def execute(rpc)
|
91
|
+
retVal = executeOnce(rpc)
|
92
|
+
if (retVal == nil && @signedOn)
|
93
|
+
#reconnect
|
94
|
+
if (rpc.name == "#BYE#")
|
95
|
+
# We're disconnecting anyway
|
96
|
+
return nil
|
97
|
+
end
|
98
|
+
# attempt to log back on
|
99
|
+
if (connect())
|
100
|
+
if (@currentContext != nil)
|
101
|
+
context = !currentContext
|
102
|
+
@currentContext = nil
|
103
|
+
setContext(context)
|
104
|
+
end
|
105
|
+
retVal = executeOnce(rpc)
|
106
|
+
end
|
89
107
|
end
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
if (response == nil)
|
95
|
-
return false
|
108
|
+
if (retVal == nil)
|
109
|
+
puts "Lost connection to server"
|
110
|
+
end
|
111
|
+
return retVal
|
96
112
|
end
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
113
|
+
|
114
|
+
# Call the RPC function
|
115
|
+
# rpcname = String containing name of RPC
|
116
|
+
# args = Array of arguments 0-based
|
117
|
+
# response type = one of the types in RPCResponse
|
118
|
+
# returns RPCResponse
|
119
|
+
def call(rpcname, responsetype, args=nil)
|
120
|
+
rpc = VistaRPC.new(rpcname, responsetype)
|
121
|
+
if !args.nil?
|
122
|
+
rpc.params = args
|
104
123
|
end
|
124
|
+
rpcresponse = execute(rpc)
|
125
|
+
return rpcresponse
|
105
126
|
end
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
127
|
+
|
128
|
+
# Call the RPC function expecting to receive a string or SINGLE_VALUE
|
129
|
+
# rpcname = String containing name of RPC
|
130
|
+
# args = Array of arguments 0-based
|
131
|
+
# returns String
|
132
|
+
def call_s(rpcname, args=nil)
|
133
|
+
rpc = VistaRPC.new(rpcname, RPCResponse::SINGLE_VALUE)
|
134
|
+
if !args.nil?
|
135
|
+
rpc.params = args
|
136
|
+
end
|
137
|
+
rpcresponse = execute(rpc)
|
138
|
+
return rpcresponse.value
|
111
139
|
end
|
112
|
-
return true
|
113
|
-
end
|
114
140
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
#
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
# sb.append(answer)
|
124
|
-
# end
|
125
|
-
# end
|
126
|
-
# end
|
127
|
-
# end
|
128
|
-
return sb
|
129
|
-
end
|
130
|
-
|
131
|
-
def close()
|
132
|
-
if isConnected()
|
133
|
-
if @sentConnect
|
134
|
-
@sentConnect = false
|
135
|
-
bye = VistaRPC.new("#BYE#", RPCResponse::SINGLE_VALUE, true)
|
136
|
-
execute(bye)
|
137
|
-
@socket.close()
|
138
|
-
@socket = nil
|
141
|
+
# Call the RPC function expecting to receive a array of string ARRAY
|
142
|
+
# rpcname = String containing name of RPC
|
143
|
+
# args = Array of arguments 0-based
|
144
|
+
# returns Array
|
145
|
+
def call_a(rpcname, args=nil)
|
146
|
+
rpc = VistaRPC.new(rpcname, RPCResponse::ARRAY)
|
147
|
+
if !args.nil?
|
148
|
+
rpc.params = args
|
139
149
|
end
|
150
|
+
rpcresponse = execute(rpc)
|
151
|
+
return rpcresponse.value
|
140
152
|
end
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
# public String buildSubscript(String string) {
|
148
|
-
# return /* "\r" + */ string
|
149
|
-
# }
|
150
|
-
|
151
|
-
def executeOnce(rpc)
|
152
|
-
retVal = nil
|
153
|
-
writeProtocol()
|
154
|
-
writeCommand(rpc)
|
155
|
-
writeParams(rpc)
|
156
|
-
write(END_MARKER)
|
157
|
-
if (flush())
|
158
|
-
retVal = getResponse(rpc.type)
|
159
|
-
if @debug
|
160
|
-
puts "<Response> " + retVal.to_s + "</Response>"
|
153
|
+
|
154
|
+
|
155
|
+
def setContext(context)
|
156
|
+
if (context == @currentContext)
|
157
|
+
puts "context is already set to " + context + "..."
|
158
|
+
return
|
161
159
|
end
|
160
|
+
if (@currentContext != nil)
|
161
|
+
puts "changing context from " + currentContext + " to " + context
|
162
|
+
end
|
163
|
+
|
164
|
+
puts "Setting context to: " + context
|
165
|
+
xwbCreateContext = VistaRPC.new("XWB CREATE CONTEXT", RPCResponse::SINGLE_VALUE)
|
166
|
+
encryptedContext = xwbCreateContext.encrypt(context)
|
167
|
+
xwbCreateContext.params[0] = encryptedContext
|
168
|
+
response = execute(xwbCreateContext)
|
169
|
+
if (response == nil || response.error_message != nil)
|
170
|
+
puts "XWB CREATE CONTEXT failed: " + response.error_message
|
171
|
+
end
|
172
|
+
@currentContext = context
|
162
173
|
end
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
@writeBuffer << data
|
168
|
-
end
|
169
|
-
|
170
|
-
def writeProtocol
|
171
|
-
write(XWB_HEADER + VISTA_RPC_VERSION + VISTA_RPC_TYPE_RPC + VISTA_RPC_LENV_STR + VISTA_RPC_RETURN_DATA)
|
172
|
-
end
|
173
|
-
|
174
|
-
def writeCommand(rpc)
|
175
|
-
if (rpc.isCommand)
|
176
|
-
write(CHUNK_TYPE_COMMAND)
|
177
|
-
else
|
178
|
-
write(CHUNK_TYPE_RPC)
|
179
|
-
writeSPack(VISTA_RPC_VERSION)
|
174
|
+
|
175
|
+
|
176
|
+
def getDUZ
|
177
|
+
return @duz
|
180
178
|
end
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
len = sprintf("%03i", string.length) # 0-padded 3 place string of integer
|
191
|
-
#Integer.toString(string.length())
|
192
|
-
# while (len.length() < VISTA_RPC_LENV) {
|
193
|
-
# len = "0" + len
|
194
|
-
# }
|
195
|
-
write(len) # "003"
|
196
|
-
write(string)
|
197
|
-
end
|
198
|
-
|
199
|
-
def writeParams(rpc)
|
200
|
-
write(CHUNK_TYPE_DATA)
|
201
|
-
|
202
|
-
params = rpc.params # Hash integer => object
|
203
|
-
if (!params.empty?)
|
204
|
-
params.each do |param|
|
205
|
-
if param.nil?
|
206
|
-
writeEmptyParam()
|
207
|
-
elsif param.class == String
|
208
|
-
writeStringParam(param)
|
209
|
-
elsif param.class == Array
|
210
|
-
writeArrayParam(param)
|
211
|
-
else
|
212
|
-
writeEmptyParam()
|
213
|
-
end
|
179
|
+
|
180
|
+
|
181
|
+
|
182
|
+
private
|
183
|
+
|
184
|
+
def signOn()
|
185
|
+
signonResponse = execute(VistaRPC.new("XUS SIGNON SETUP", RPCResponse::ARRAY))
|
186
|
+
if (signonResponse == nil || signonResponse.error_message != nil)
|
187
|
+
puts "XUS SIGNON SETUP failed"
|
214
188
|
end
|
215
|
-
|
216
|
-
writeEmptyParam()
|
189
|
+
@signedOn = true
|
217
190
|
end
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
191
|
+
|
192
|
+
def logIn()
|
193
|
+
xusAvCode = VistaRPC.new("XUS AV CODE", RPCResponse::ARRAY)
|
194
|
+
@duz = "0"
|
195
|
+
|
196
|
+
if (@encryptedAV == nil)
|
197
|
+
if (@token != nil)
|
198
|
+
@encryptedAV = @token
|
199
|
+
else
|
200
|
+
@encryptedAV = xusAvCode.encrypt(@access + ";" + @verify)
|
201
|
+
end
|
202
|
+
|
203
|
+
end
|
204
|
+
xusAvCode.params[0]= @encryptedAV
|
205
|
+
response = execute(xusAvCode)
|
206
|
+
if (response == nil)
|
207
|
+
return false
|
231
208
|
end
|
209
|
+
hasErrors = (response.error_message != nil)
|
210
|
+
answer = response.value
|
211
|
+
if (!hasErrors)
|
212
|
+
if (answer.length == 0)
|
213
|
+
hasErrors = true
|
214
|
+
else
|
215
|
+
hasErrors = answer[0]== "0"
|
216
|
+
end
|
217
|
+
end
|
218
|
+
if (hasErrors)
|
219
|
+
brokerInfo = extractBrokerErrorInfo(response)
|
220
|
+
puts("Access denied: " + brokerInfo)
|
221
|
+
else
|
222
|
+
@duz = answer[0]
|
223
|
+
end
|
224
|
+
return true
|
232
225
|
end
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
retVal = false
|
249
|
-
if (isConnected() || connect())
|
250
|
-
if @debug
|
251
|
-
puts "<Request>" + @writeBuffer + "</Request>"
|
252
|
-
end
|
253
|
-
@socket.write(@writeBuffer)
|
254
|
-
@socket.flush
|
255
|
-
@writeBuffer = String.new
|
256
|
-
retVal = true
|
226
|
+
|
227
|
+
|
228
|
+
def extractBrokerErrorInfo(response)
|
229
|
+
sb = String.new
|
230
|
+
# if (response != nil && response.getArray() != nil)
|
231
|
+
# response.getArray.each do |answer|
|
232
|
+
# if (answer != nil && answer.length > 0 && !answer.matches("^(\\d+)$"))
|
233
|
+
# if (sb.length() != 0) # sb is Stringbuilder
|
234
|
+
# sb.append(" : ")
|
235
|
+
# sb.append(answer)
|
236
|
+
# end
|
237
|
+
# end
|
238
|
+
# end
|
239
|
+
# end
|
240
|
+
return sb
|
257
241
|
end
|
258
|
-
|
259
|
-
end
|
242
|
+
|
260
243
|
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
244
|
+
# public String buildSubscript(String string) {
|
245
|
+
# return /* "\r" + */ string
|
246
|
+
# }
|
247
|
+
|
248
|
+
def executeOnce(rpc)
|
249
|
+
retVal = nil
|
250
|
+
writeProtocol()
|
251
|
+
writeCommand(rpc)
|
252
|
+
writeParams(rpc)
|
253
|
+
write(END_MARKER)
|
254
|
+
if (flush())
|
255
|
+
retVal = getResponse(rpc.type)
|
256
|
+
if @debug
|
257
|
+
puts "<Response> " + retVal.to_s + "</Response>"
|
258
|
+
end
|
259
|
+
end
|
260
|
+
return retVal
|
271
261
|
end
|
272
262
|
|
273
|
-
|
274
|
-
|
275
|
-
return nil
|
263
|
+
def write(data)
|
264
|
+
@writeBuffer << data
|
276
265
|
end
|
277
|
-
|
278
|
-
|
266
|
+
|
267
|
+
def writeProtocol
|
268
|
+
write(XWB_HEADER + VISTA_RPC_VERSION + VISTA_RPC_TYPE_RPC + VISTA_RPC_LENV_STR + VISTA_RPC_RETURN_DATA)
|
279
269
|
end
|
280
270
|
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
elsif (rpcType == RPCResponse::GLOBAL_ARRAY or rpcType == RPCResponse::WORD_PROCESSING or rpcType == RPCResponse::ARRAY)
|
288
|
-
retVal = RPCResponse.new(readArray(hadError))
|
289
|
-
if (hadError[0])
|
290
|
-
return nil
|
271
|
+
def writeCommand(rpc)
|
272
|
+
if (rpc.isCommand)
|
273
|
+
write(CHUNK_TYPE_COMMAND)
|
274
|
+
else
|
275
|
+
write(CHUNK_TYPE_RPC)
|
276
|
+
writeSPack(VISTA_RPC_VERSION)
|
291
277
|
end
|
278
|
+
writeSPack(rpc.name)
|
292
279
|
end
|
293
280
|
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
elsif (otherError != nil)
|
298
|
-
retVal.error_message = otherError
|
299
|
-
else
|
300
|
-
retVal.error_message = securityError
|
301
|
-
end
|
281
|
+
def writeSPack(value)
|
282
|
+
write(value.length) # integer
|
283
|
+
write(value)
|
302
284
|
end
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
285
|
+
|
286
|
+
def writeLPack(string)
|
287
|
+
len = sprintf("%03i", string.length) # 0-padded 3 place string of integer
|
288
|
+
#Integer.toString(string.length())
|
289
|
+
# while (len.length() < VISTA_RPC_LENV) {
|
290
|
+
# len = "0" + len
|
291
|
+
# }
|
292
|
+
write(len) # "003"
|
293
|
+
write(string)
|
310
294
|
end
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
if (
|
317
|
-
|
318
|
-
|
295
|
+
|
296
|
+
def writeParams(rpc)
|
297
|
+
write(CHUNK_TYPE_DATA)
|
298
|
+
|
299
|
+
params = rpc.params # Hash integer => object
|
300
|
+
if (!params.empty?)
|
301
|
+
params.each do |param|
|
302
|
+
if param.nil?
|
303
|
+
writeEmptyParam()
|
304
|
+
elsif param.class == String
|
305
|
+
writeStringParam(param)
|
306
|
+
elsif param.class == Array
|
307
|
+
writeArrayParam(param)
|
308
|
+
else
|
309
|
+
writeEmptyParam()
|
310
|
+
end
|
319
311
|
end
|
320
|
-
|
312
|
+
else
|
313
|
+
writeEmptyParam()
|
321
314
|
end
|
322
|
-
|
323
|
-
break
|
324
|
-
end
|
325
|
-
arrayList << newString
|
315
|
+
#No end marker. Chunk 5 is assumed to be the last.
|
326
316
|
end
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
317
|
+
|
318
|
+
def writeArrayParam(paramarray)
|
319
|
+
write(PARAM_LIST_MARKER)
|
320
|
+
size = paramarray.size
|
321
|
+
index = 0
|
322
|
+
paramarray.each do |v|
|
323
|
+
writeLPack(v[0])
|
324
|
+
writeLPack(v[1])
|
325
|
+
index += 1
|
326
|
+
if index !=size # looks like don't write a 't' after the last entry
|
327
|
+
write("t")
|
328
|
+
end
|
329
|
+
end
|
330
|
+
write("f")
|
335
331
|
end
|
336
|
-
|
337
|
-
|
332
|
+
|
333
|
+
def writeStringParam(string)
|
334
|
+
write(PARAM_LITERAL_MARKER)
|
335
|
+
writeLPack(string)
|
336
|
+
write("f")
|
338
337
|
end
|
339
|
-
|
340
|
-
|
338
|
+
|
339
|
+
def writeEmptyParam()
|
340
|
+
write(PARAM_EMPTY_MARKER)
|
341
|
+
write("f")
|
341
342
|
end
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
endMarker[0] = true
|
343
|
+
|
344
|
+
def flush()
|
345
|
+
retVal = false
|
346
|
+
if (isConnected() || connect())
|
347
|
+
if @debug
|
348
|
+
puts "<Request>" + @writeBuffer + "</Request>"
|
349
349
|
end
|
350
|
-
|
350
|
+
@socket.write(@writeBuffer)
|
351
|
+
@socket.flush
|
352
|
+
@writeBuffer = String.new
|
353
|
+
retVal = true
|
351
354
|
end
|
352
|
-
|
353
|
-
|
355
|
+
return retVal
|
356
|
+
end
|
357
|
+
|
358
|
+
def getResponse(rpcType)
|
359
|
+
hadError = Array.new # for passing around boolean by reference
|
360
|
+
hadError[0]=false
|
361
|
+
securityError = readSPack(hadError)
|
362
|
+
#puts "<SecurityError>" + securityError + "</SecurityError>"
|
363
|
+
if (hadError[0])
|
364
|
+
return nil
|
354
365
|
end
|
355
|
-
if (
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
366
|
+
if (securityError.empty?)
|
367
|
+
securityError = nil
|
368
|
+
end
|
369
|
+
|
370
|
+
otherError = readSPack(hadError)
|
371
|
+
if (hadError[0])
|
372
|
+
return nil
|
373
|
+
end
|
374
|
+
if (otherError.empty?)
|
375
|
+
otherError = nil
|
376
|
+
end
|
377
|
+
|
378
|
+
retVal = nil
|
379
|
+
if (rpcType == RPCResponse::SINGLE_VALUE or rpcType == RPCResponse::GLOBAL_INSTANCE)
|
380
|
+
retVal = RPCResponse.new(readString(nil, hadError))
|
381
|
+
if (hadError[0])
|
382
|
+
return nil
|
383
|
+
end
|
384
|
+
elsif (rpcType == RPCResponse::GLOBAL_ARRAY or rpcType == RPCResponse::WORD_PROCESSING or rpcType == RPCResponse::ARRAY)
|
385
|
+
retVal = RPCResponse.new(readArray(hadError))
|
386
|
+
if (hadError[0])
|
387
|
+
return nil
|
361
388
|
end
|
362
|
-
buffer << byte
|
363
389
|
end
|
390
|
+
|
391
|
+
if (retVal != nil && (otherError != nil || securityError != nil))
|
392
|
+
if (otherError != nil && securityError != nil)
|
393
|
+
retVal.error_message = otherError + "^" + securityError
|
394
|
+
elsif (otherError != nil)
|
395
|
+
retVal.error_message = otherError
|
396
|
+
else
|
397
|
+
retVal.error_message = securityError
|
398
|
+
end
|
399
|
+
end
|
400
|
+
return retVal
|
364
401
|
end
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
402
|
+
|
403
|
+
# returns array of string
|
404
|
+
def readArray(hadError)
|
405
|
+
if (hadError != nil)
|
406
|
+
hadError[0] = false
|
407
|
+
end
|
408
|
+
arrayList = Array.new
|
409
|
+
endMarker = Array.new
|
410
|
+
endMarker[0] = false
|
411
|
+
while true
|
412
|
+
newString = readString(endMarker, hadError)
|
413
|
+
if (newString == nil)
|
414
|
+
if (hadError != nil)
|
415
|
+
hadError[0] = true
|
416
|
+
end
|
417
|
+
break
|
418
|
+
end
|
419
|
+
if (endMarker[0])
|
420
|
+
break
|
421
|
+
end
|
422
|
+
arrayList << newString
|
423
|
+
end
|
424
|
+
return arrayList
|
373
425
|
end
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
if (
|
385
|
-
# We're disconnecting anyway
|
426
|
+
|
427
|
+
|
428
|
+
# readString uses array argument so can pass values back
|
429
|
+
def readString(endMarker, hadError) # returns...string!
|
430
|
+
if (endMarker != nil)
|
431
|
+
endMarker[0] = !isConnected()
|
432
|
+
end
|
433
|
+
if (hadError != nil)
|
434
|
+
hadError[0] = !isConnected()
|
435
|
+
end
|
436
|
+
if (!isConnected())
|
386
437
|
return nil
|
387
438
|
end
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
439
|
+
buffer = String.new
|
440
|
+
gotCR = false
|
441
|
+
while true
|
442
|
+
byte = @socket.readbyte # read one byte
|
443
|
+
if (byte == END_MARKER)
|
444
|
+
if (endMarker != nil)
|
445
|
+
endMarker[0] = true
|
446
|
+
end
|
447
|
+
break
|
448
|
+
end
|
449
|
+
if (gotCR && byte == 10) # CR-LF
|
450
|
+
break
|
451
|
+
end
|
452
|
+
if (byte == 13)
|
453
|
+
gotCR = true
|
454
|
+
else
|
455
|
+
if (gotCR)
|
456
|
+
buffer << 13 # we got a CR without a LF, so keep it in.
|
457
|
+
gotCR = false
|
458
|
+
end
|
459
|
+
buffer << byte
|
394
460
|
end
|
395
|
-
retVal = executeOnce(rpc)
|
396
461
|
end
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
end
|
401
|
-
return retVal
|
402
|
-
end
|
403
|
-
|
404
|
-
def setContext(context)
|
405
|
-
if (context == @currentContext)
|
406
|
-
puts "context is already set to " + context + "..."
|
407
|
-
return
|
408
|
-
end
|
409
|
-
if (@currentContext != nil)
|
410
|
-
puts "changing context from " + currentContext + " to " + context
|
462
|
+
|
463
|
+
retVal = buffer
|
464
|
+
return retVal
|
411
465
|
end
|
412
466
|
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
467
|
+
def readSPack(hadError)
|
468
|
+
if (hadError != nil)
|
469
|
+
hadError[0] = false
|
470
|
+
end
|
471
|
+
len = @socket.readbyte # read one byte into a fixnum
|
472
|
+
data = String.new
|
473
|
+
data = @socket.read(len)
|
474
|
+
return data
|
420
475
|
end
|
421
|
-
|
422
|
-
end
|
423
|
-
|
424
|
-
def getDUZ
|
425
|
-
return duz
|
476
|
+
|
426
477
|
end
|
427
|
-
|
428
|
-
end
|
429
478
|
end
|
@@ -1,46 +1,55 @@
|
|
1
1
|
module VistaRPC4r
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
2
|
+
|
3
|
+
# Response object from RPC call
|
4
|
+
# type = one of the constant types
|
5
|
+
# value = String or Array of Strings representing the actual response
|
6
|
+
class RPCResponse
|
7
|
+
attr_accessor :type, :value, :error_message
|
8
|
+
|
9
|
+
# Single string response
|
10
|
+
SINGLE_VALUE = 1
|
11
|
+
# Not sure, but is usually a string response
|
12
|
+
GLOBAL_INSTANCE = 2
|
13
|
+
# Array of string response
|
14
|
+
ARRAY = 3
|
15
|
+
# Array of string response
|
16
|
+
GLOBAL_ARRAY=4
|
17
|
+
# Array of string response
|
18
|
+
WORD_PROCESSING=5
|
19
|
+
|
20
|
+
def initialize(value=nil, type=nil)
|
21
|
+
if value.nil?
|
22
|
+
@type = SINGLE_VALUE
|
23
|
+
@value = nil
|
24
|
+
elsif value.class == String
|
25
|
+
@value = value
|
26
|
+
@type = SINGLE_VALUE
|
27
|
+
elsif value.class == Array
|
22
28
|
@value = value
|
23
|
-
|
29
|
+
@type = ARRAY
|
30
|
+
elsif !type.nil?
|
31
|
+
@value = value
|
32
|
+
@type = type
|
33
|
+
end
|
34
|
+
@error_message = nil
|
24
35
|
end
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
sb
|
36
|
+
|
37
|
+
def to_s
|
38
|
+
sb = String.new
|
39
|
+
if !@error_message.nil?
|
40
|
+
sb << "ERROR: "
|
41
|
+
sb << @error_message
|
42
|
+
elsif @value.nil?
|
43
|
+
sb << "No value or error"
|
44
|
+
elsif @value.class == Array
|
45
|
+
sb = "ARRAY:" + value.join("|")
|
46
|
+
elsif @value.class == String
|
47
|
+
sb = "STRING:" + value.to_s
|
48
|
+
else
|
49
|
+
sb << "Unknown value type"
|
50
|
+
end
|
51
|
+
return sb
|
41
52
|
end
|
42
|
-
return sb
|
43
53
|
end
|
44
|
-
end
|
45
54
|
|
46
55
|
end
|
data/lib/vistarpc4r/vista_rpc.rb
CHANGED
@@ -1,36 +1,42 @@
|
|
1
1
|
# the 'Request' of the RPC request/response. Stores the command or api call, and arguments
|
2
2
|
module VistaRPC4r
|
3
|
-
class VistaRPC
|
4
|
-
attr_accessor :name, :type, :isCommand, :params
|
5
3
|
|
4
|
+
# Request object for the RPC call. It contains:
|
5
|
+
# name = string containing name of the RPC
|
6
|
+
# type = The response type from RPCResponse
|
7
|
+
# param = Array of parameters - This is 0-based. Delphi and Ovid code refer to 1-based
|
8
|
+
# isCommand = Is this a command, usually false
|
9
|
+
class VistaRPC
|
10
|
+
attr_accessor :name, :type, :isCommand, :params
|
11
|
+
|
6
12
|
def initialize(name, type=RPCResponse::SINGLE_VALUE, isCommand=false)
|
7
13
|
@name=name # string
|
8
14
|
@type=type # response type
|
9
15
|
@params=Array.new # params = new TreeMap<Integer, Object>();
|
10
16
|
@isCommand=isCommand # boolean
|
11
17
|
@cipher = [
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
18
|
+
"wkEo-ZJt!dG)49K{nX1BS$vH<&:Myf*>Ae0jQW=;|#PsO`'%+rmb[gpqN,l6/hFC@DcUa ]z~R}\"V\\iIxu?872.(TYL5_3",
|
19
|
+
"rKv`R;M/9BqAF%&tSs#Vh)dO1DZP> *fX'u[.4lY=-mg_ci802N7LTG<]!CWo:3?{+,5Q}(@jaExn$~p\\IyHwzU\"|k6Jeb",
|
20
|
+
"\\pV(ZJk\"WQmCn!Y,y@1d+~8s?[lNMxgHEt=uw|X:qSLjAI*}6zoF{T3#;ca)/h5%`P4$r]G'9e2if_>UDKb7<v0&- RBO.",
|
21
|
+
"depjt3g4W)qD0V~NJar\\B \"?OYhcu[<Ms%Z`RIL_6:]AX-zG.#}$@vk7/5x&*m;(yb2Fn+l'PwUof1K{9,|EQi>H=CT8S!",
|
22
|
+
"NZW:1}K$byP;jk)7'`x90B|cq@iSsEnu,(l-hf.&Y_?J#R]+voQXU8mrV[!p4tg~OMez CAaGFD6H53%L/dT2<*>\"{\\wI=",
|
23
|
+
"vCiJ<oZ9|phXVNn)m K`t/SI%]A5qOWe\\&?;jT~M!fz1l>[D_0xR32c*4.P\"G{r7}E8wUgyudF+6-:B=$(sY,LkbHa#'@Q",
|
24
|
+
"hvMX,'4Ty;[a8/{6l~F_V\"}qLI\\!@x(D7bRmUH]W15J%N0BYPkrs&9:$)Zj>u|zwQ=ieC-oGA.#?tfdcO3gp`S+En K2*<",
|
25
|
+
"jd!W5[];4'<C$/&x|rZ(k{>?ghBzIFN}fAK\"#`p_TqtD*1E37XGVs@0nmSe+Y6Qyo-aUu%i8c=H2vJ\\) R:MLb.9,wlO~P",
|
26
|
+
"2ThtjEM+!=xXb)7,ZV{*ci3\"8@_l-HS69L>]\\AUF/Q%:qD?1~m(yvO0e'<#o$p4dnIzKP|`NrkaGg.ufCRB[; sJYwW}5&",
|
27
|
+
"vB\\5/zl-9y:Pj|=(R'7QJI *&CTX\"p0]_3.idcuOefVU#omwNZ`$Fs?L+1Sk<,b)hM4A6[Y%aDrg@~KqEW8t>H};n!2xG{",
|
28
|
+
"sFz0Bo@_HfnK>LR}qWXV+D6`Y28=4Cm~G/7-5A\\b9!a#rP.l&M$hc3ijQk;),TvUd<[:I\"u1'NZSOw]*gxtE{eJp|y (?%",
|
29
|
+
"M@,D}|LJyGO8`$*ZqH .j>c~h<d=fimszv[#-53F!+a;NC'6T91IV?(0x&/{B)w\"]Q\\YUWprk4:ol%g2nE7teRKbAPuS_X",
|
30
|
+
".mjY#_0*H<B=Q+FML6]s;r2:e8R}[ic&KA 1w{)vV5d,$u\"~xD/Pg?IyfthO@CzWp%!`N4Z'3-(o|J9XUE7k\\TlqSb>anG",
|
31
|
+
"xVa1']_GU<X`|\\NgM?LS9{\"jT%s$}y[nvtlefB2RKJW~(/cIDCPow4,>#zm+:5b@06O3Ap8=*7ZFY!H-uEQk; .q)i&rhd",
|
32
|
+
"I]Jz7AG@QX.\"%3Lq>METUo{Pp_ |a6<0dYVSv8:b)~W9NK`(r'4fs&wim\\kReC2hg=HOj$1B*/nxt,;c#y+![?lFuZ-5D}",
|
33
|
+
"Rr(Ge6F Hx>q$m&C%M~Tn,:\"o'tX/*yP.{lZ!YkiVhuw_<KE5a[;}W0gjsz3]@7cI2\\QN?f#4p|vb1OUBD9)=-LJA+d`S8",
|
34
|
+
"I~k>y|m};d)-7DZ\"Fe/Y<B:xwojR,Vh]O0Sc[`$sg8GXE!1&Qrzp._W%TNK(=J 3i*2abuHA4C'?Mv\\Pq{n#56LftUl@9+",
|
35
|
+
"~A*>9 WidFN,1KsmwQ)GJM{I4:C%}#Ep(?HB/r;t.&U8o|l['Lg\"2hRDyZ5`nbf]qjc0!zS-TkYO<_=76a\\X@$Pe3+xVvu",
|
36
|
+
"yYgjf\"5VdHc#uA,W1i+v'6|@pr{n;DJ!8(btPGaQM.LT3oe?NB/&9>Z`-}02*%x<7lsqz4OS ~E$\\R]KI[:UwC_=h)kXmF",
|
37
|
+
"5:iar.{YU7mBZR@-K|2 \"+~`M%8sq4JhPo<_X\\Sg3WC;Tuxz,fvEQ1p9=w}FAI&j/keD0c?)LN6OHV]lGy'$*>nd[(tb!#" ]
|
32
38
|
end
|
33
|
-
|
39
|
+
|
34
40
|
def encrypt(orig_string)
|
35
41
|
ra = rand(19)
|
36
42
|
rb = rand(19)
|
@@ -41,7 +47,7 @@ class VistaRPC
|
|
41
47
|
cb = @cipher[rb]
|
42
48
|
len = orig_string.length
|
43
49
|
pos = 0;
|
44
|
-
|
50
|
+
|
45
51
|
buffer = String.new
|
46
52
|
buffer << ra+32
|
47
53
|
for i in 0..(len-1)
|
@@ -56,44 +62,44 @@ class VistaRPC
|
|
56
62
|
buffer << rb + 32
|
57
63
|
return buffer
|
58
64
|
end
|
59
|
-
|
65
|
+
|
60
66
|
def to_s
|
61
67
|
sb = String.new
|
62
68
|
sb << @name + ":"
|
63
69
|
sb << @params.to_s
|
64
70
|
return sb
|
65
71
|
end
|
66
|
-
|
67
|
-
# @Override
|
72
|
+
|
73
|
+
# @Override
|
68
74
|
# public boolean equals(Object obj) {
|
69
|
-
# if (obj == null) {
|
70
|
-
# return false;
|
71
|
-
# }
|
72
|
-
# if (getClass() != obj.getClass()) {
|
73
|
-
# return false;
|
74
|
-
# }
|
75
|
+
# if (obj == null) {
|
76
|
+
# return false;
|
77
|
+
# }
|
78
|
+
# if (getClass() != obj.getClass()) {
|
79
|
+
# return false;
|
80
|
+
# }
|
75
81
|
# final VistaRPC other = (VistaRPC) obj;
|
76
|
-
# if ((this.name == null) ? (other.name != null) : !this.name.equals(other.name)) {
|
77
|
-
# return false;
|
78
|
-
# }
|
79
|
-
# if (this.type != other.type) {
|
80
|
-
# return false;
|
81
|
-
# }
|
82
|
-
# if (this.params != other.params && (this.params == null || !this.params.equals(other.params))) {
|
82
|
+
# if ((this.name == null) ? (other.name != null) : !this.name.equals(other.name)) {
|
83
|
+
# return false;
|
84
|
+
# }
|
85
|
+
# if (this.type != other.type) {
|
83
86
|
# return false;
|
87
|
+
# }
|
88
|
+
# if (this.params != other.params && (this.params == null || !this.params.equals(other.params))) {
|
89
|
+
# return false;
|
84
90
|
# }
|
85
|
-
# return true;
|
86
|
-
# }
|
87
|
-
|
88
|
-
# @Override
|
89
|
-
# public int hashCode() {
|
91
|
+
# return true;
|
92
|
+
# }
|
93
|
+
|
94
|
+
# @Override
|
95
|
+
# public int hashCode() {
|
90
96
|
# int hash = 3;
|
91
|
-
# hash = 29 * hash + (this.name != null ? this.name.hashCode() : 0);
|
92
|
-
# hash = 29 * hash + (this.type != null ? this.type.hashCode() : 0);
|
93
|
-
# hash = 29 * hash + (this.params != null ? this.params.hashCode() : 0);
|
94
|
-
# return hash;
|
95
|
-
# }
|
97
|
+
# hash = 29 * hash + (this.name != null ? this.name.hashCode() : 0);
|
98
|
+
# hash = 29 * hash + (this.type != null ? this.type.hashCode() : 0);
|
99
|
+
# hash = 29 * hash + (this.params != null ? this.params.hashCode() : 0);
|
100
|
+
# return hash;
|
101
|
+
# }
|
96
102
|
|
97
|
-
|
98
|
-
end
|
103
|
+
|
104
|
+
end
|
99
105
|
end
|
data/vistarpc4r.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{vistarpc4r}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.2.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Mike Cham"]
|
12
|
-
s.date = %q{2011-05-
|
12
|
+
s.date = %q{2011-05-27}
|
13
13
|
s.description = %q{more}
|
14
14
|
s.email = %q{mike@blenderhouse.com}
|
15
15
|
s.extra_rdoc_files = [
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vistarpc4r
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 23
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 2
|
9
|
+
- 0
|
10
|
+
version: 0.2.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Mike Cham
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-05-
|
18
|
+
date: 2011-05-27 00:00:00 -04:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|