rapi 0.0.0 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/VERSION +1 -1
- data/lib/rapi.rb +462 -0
- data/lib/rapi/ce_registry_key.rb +8 -0
- data/rapi.gemspec +3 -2
- metadata +14 -13
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.1.0
|
data/lib/rapi.rb
CHANGED
@@ -0,0 +1,462 @@
|
|
1
|
+
require 'ffi'
|
2
|
+
require 'iconv'
|
3
|
+
|
4
|
+
class RAPI
|
5
|
+
|
6
|
+
attr_accessor :copy_buffer_size
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@connected = false
|
10
|
+
@copy_buffer_size = 0x1000
|
11
|
+
end
|
12
|
+
|
13
|
+
def connected?
|
14
|
+
@connected
|
15
|
+
end
|
16
|
+
|
17
|
+
def connect(timeout_seconds = 1)
|
18
|
+
self.disconnect if connected?
|
19
|
+
|
20
|
+
init = Native::Rapi::RAPIINIT.new
|
21
|
+
init[:cbSize] = Native::Rapi::RAPIINIT.size
|
22
|
+
ret = Native::Rapi.CeRapiInitEx(init)
|
23
|
+
handle_hresult! ret
|
24
|
+
init_event = init[:heRapiInit]
|
25
|
+
|
26
|
+
timeout = timeout_seconds * 4
|
27
|
+
infinite_timeout = timeout < 0
|
28
|
+
|
29
|
+
begin
|
30
|
+
ret = Native::Kernel32.WaitForSingleObject(init_event, 250)
|
31
|
+
|
32
|
+
if ret == Native::WAIT_FAILED || ret == Native::WAIT_ABANDONED
|
33
|
+
Native::Kernel32.CloseHandle(init_event)
|
34
|
+
Native::Rapi.CeRapiUninit
|
35
|
+
raise RAPIException, "Failed to Initialize RAPI"
|
36
|
+
end
|
37
|
+
|
38
|
+
if !infinite_timeout
|
39
|
+
if (timeout -= 1) < 0
|
40
|
+
Native::Kernel32.CloseHandle(init_event)
|
41
|
+
Native::Rapi.CeRapiUninit
|
42
|
+
raise RAPIException, "Timeout waiting for device connection"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end while ret != Native::WAIT_OBJECT_0
|
46
|
+
|
47
|
+
@connected = true
|
48
|
+
Native::Kernel32.CloseHandle(init_event)
|
49
|
+
|
50
|
+
true
|
51
|
+
end
|
52
|
+
|
53
|
+
def disconnect
|
54
|
+
if connected?
|
55
|
+
Native::Rapi.CeRapiUninit
|
56
|
+
@connected = false
|
57
|
+
end
|
58
|
+
|
59
|
+
true
|
60
|
+
end
|
61
|
+
|
62
|
+
def exist?(remote_file_name)
|
63
|
+
check_connection()
|
64
|
+
|
65
|
+
Native::Rapi::CeGetFileAttributes(to_utf16(remote_file_name)) != 0xFFFFFFFF
|
66
|
+
end
|
67
|
+
|
68
|
+
alias exists? exist?
|
69
|
+
|
70
|
+
def download(remote_file_name, local_file_name, overwrite = false)
|
71
|
+
check_connection()
|
72
|
+
|
73
|
+
if !overwrite && File.exists?(local_file_name)
|
74
|
+
raise RAPIException, "A local file with the given name already exists"
|
75
|
+
end
|
76
|
+
|
77
|
+
remote_file = Native::Rapi.CeCreateFile(to_utf16(remote_file_name), Native::GENERIC_READ, 0, 0, Native::OPEN_EXISTING, Native::FILE_ATTRIBUTE_NORMAL, 0)
|
78
|
+
if remote_file == Native::INVALID_HANDLE
|
79
|
+
raise RAPIException, "Could not open remote file"
|
80
|
+
end
|
81
|
+
|
82
|
+
File.open(local_file_name, "wb") do |f|
|
83
|
+
buffer = FFI::MemoryPointer.new(1, @copy_buffer_size)
|
84
|
+
bytes_read_ptr = FFI::MemoryPointer.new(FFI::Type::INT.size)
|
85
|
+
|
86
|
+
while true
|
87
|
+
ret = Native::Rapi.CeReadFile(remote_file, buffer, buffer.size, bytes_read_ptr, 0)
|
88
|
+
|
89
|
+
bytes_read = bytes_read_ptr.get_int(0)
|
90
|
+
|
91
|
+
if bytes_read != 0 && ret == 0
|
92
|
+
buffer.free
|
93
|
+
bytes_read_ptr.free
|
94
|
+
Native::Rapi.CeCloseHandle(remote_file)
|
95
|
+
raise RAPIException, "Failed to read device data"
|
96
|
+
elsif bytes_read == 0
|
97
|
+
break
|
98
|
+
end
|
99
|
+
|
100
|
+
f << buffer.get_bytes(0, bytes_read)
|
101
|
+
end
|
102
|
+
|
103
|
+
buffer.free
|
104
|
+
bytes_read_ptr.free
|
105
|
+
Native::Rapi.CeCloseHandle(remote_file)
|
106
|
+
end
|
107
|
+
|
108
|
+
true
|
109
|
+
end
|
110
|
+
|
111
|
+
def upload(local_file_name, remote_file_name, overwrite = false)
|
112
|
+
check_connection()
|
113
|
+
|
114
|
+
create = overwrite ? Native::CREATE_ALWAYS : Native::CREATE_NEW
|
115
|
+
remote_file = Native::Rapi.CeCreateFile(to_utf16(remote_file_name), Native::GENERIC_WRITE, 0, 0, create, Native::FILE_ATTRIBUTE_NORMAL, 0)
|
116
|
+
|
117
|
+
if remote_file == Native::INVALID_HANDLE
|
118
|
+
raise RAPIException, "Could not create remote file"
|
119
|
+
end
|
120
|
+
|
121
|
+
if File.size(local_file_name) != 0
|
122
|
+
File.open(local_file_name, "rb") do |f|
|
123
|
+
while buffer = f.read(copy_buffer_size)
|
124
|
+
if Native::Rapi.CeWriteFile(remote_file, buffer, buffer.size, nil, 0) == 0
|
125
|
+
Native::Rapi.CeCloseHandle(remote_file)
|
126
|
+
raise RAPIException, "Could not write to remote file"
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
Native::Rapi.CeCloseHandle(remote_file)
|
133
|
+
|
134
|
+
true
|
135
|
+
end
|
136
|
+
|
137
|
+
def copy(existing_file_name, new_file_name, overwrite = false)
|
138
|
+
check_connection()
|
139
|
+
|
140
|
+
if Native::Rapi.CeCopyFile(to_utf16(existing_file_name), to_utf16(new_file_name), overwrite ? 0 : 1) == 0
|
141
|
+
raise RAPIException, "Cannot copy file"
|
142
|
+
end
|
143
|
+
|
144
|
+
true
|
145
|
+
end
|
146
|
+
|
147
|
+
def delete(file_name)
|
148
|
+
check_connection()
|
149
|
+
|
150
|
+
if Native::Rapi.CeDeleteFile(to_utf16(file_name)) == 0
|
151
|
+
raise RAPIException, "Could not delete file"
|
152
|
+
end
|
153
|
+
|
154
|
+
true
|
155
|
+
end
|
156
|
+
|
157
|
+
def move(existing_file_name, new_file_name)
|
158
|
+
check_connection()
|
159
|
+
|
160
|
+
if Native::Rapi.CeMoveFile(to_utf16(existing_file_name), to_utf16(new_file_name)) == 0
|
161
|
+
raise RAPIException, "Cannot move file"
|
162
|
+
end
|
163
|
+
|
164
|
+
true
|
165
|
+
end
|
166
|
+
|
167
|
+
def get_attributes(file_name)
|
168
|
+
check_connection()
|
169
|
+
|
170
|
+
ret = Native::Rapi.CeGetFileAttributes(to_utf16(file_name))
|
171
|
+
if ret == 0xFFFFFFFF
|
172
|
+
raise RAPIException, "Could not get file attributes"
|
173
|
+
end
|
174
|
+
|
175
|
+
FileAttributes.new(ret)
|
176
|
+
end
|
177
|
+
|
178
|
+
alias get_attrs get_attributes
|
179
|
+
|
180
|
+
def set_attributes(file_name, attributes)
|
181
|
+
check_connection()
|
182
|
+
|
183
|
+
if Native::Rapi.CeSetFileAttributes(to_utf16(file_name), attributes.to_i) == 0
|
184
|
+
raise RAPIExcpetion, "Cannot set device file attributes"
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
alias set_attrs set_attributes
|
189
|
+
|
190
|
+
def search(file_name)
|
191
|
+
check_connection()
|
192
|
+
|
193
|
+
find_data = Native::Rapi::CE_FIND_DATA.new
|
194
|
+
|
195
|
+
file_infos = []
|
196
|
+
handle = Native::Rapi.CeFindFirstFile(to_utf16(file_name), find_data)
|
197
|
+
|
198
|
+
if handle != Native::INVALID_HANDLE
|
199
|
+
file_infos << FileInformation.new(find_data)
|
200
|
+
find_data.pointer.clear
|
201
|
+
|
202
|
+
while Native::Rapi.CeFindNextFile(handle, find_data) != 0
|
203
|
+
file_infos << FileInformation.new(find_data)
|
204
|
+
find_data.pointer.clear
|
205
|
+
end
|
206
|
+
|
207
|
+
Native::Rapi.CeFindClose(handle)
|
208
|
+
end
|
209
|
+
|
210
|
+
file_infos
|
211
|
+
end
|
212
|
+
|
213
|
+
alias glob search
|
214
|
+
|
215
|
+
def exec(file_name, *args)
|
216
|
+
check_connection
|
217
|
+
|
218
|
+
args = if args.empty?
|
219
|
+
nil
|
220
|
+
else
|
221
|
+
args.join(' ')
|
222
|
+
end
|
223
|
+
|
224
|
+
pi = Native::Rapi::PROCESS_INFORMATION.new
|
225
|
+
|
226
|
+
if Native::Rapi.CeCreateProcess(to_utf16(file_name), to_utf16(args), nil, nil, 0, 0, nil, nil, nil, pi) == 0
|
227
|
+
errnum = Native::Rapi.CeGetLastError
|
228
|
+
handle_hresult! errnum
|
229
|
+
end
|
230
|
+
|
231
|
+
ProcessInformation.new(pi)
|
232
|
+
end
|
233
|
+
|
234
|
+
private
|
235
|
+
|
236
|
+
def check_connection
|
237
|
+
unless connected?
|
238
|
+
raise RAPIException, "Cannot perform operation while disconnected"
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
def handle_hresult!(hresult)
|
243
|
+
if hresult != 0
|
244
|
+
msg_ptr = FFI::MemoryPointer.new(FFI::Pointer)
|
245
|
+
format = Native::FORMAT_MESSAGE_ALLOCATE_BUFFER | Native::FORMAT_MESSAGE_FROM_SYSTEM | Native::FORMAT_MESSAGE_IGNORE_INSERTS
|
246
|
+
len = Native::Kernel32.FormatMessageA(format, nil, hresult, 0, msg_ptr, 0, nil)
|
247
|
+
if len == 0
|
248
|
+
msg = "Error {hresult} (0x#{hresult.to_s(16).upcase})"
|
249
|
+
else
|
250
|
+
msg = msg_ptr.get_pointer(0).get_string(0)
|
251
|
+
end
|
252
|
+
Native::Kernel32.LocalFree(msg_ptr.get_pointer(0))
|
253
|
+
msg_ptr.free
|
254
|
+
raise RAPIException, msg
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
if RUBY_VERSION =~ /^1\.9\.\d/
|
259
|
+
def to_utf16(str)
|
260
|
+
return nil if str.nil?
|
261
|
+
str.encode("UTF-16LE") + "\0\0".force_encoding("UTF-16LE")
|
262
|
+
end
|
263
|
+
else
|
264
|
+
def to_utf16(str)
|
265
|
+
return nil if str.nil?
|
266
|
+
Iconv.conv("UTF-16LE", "ASCII", str) + "\0\0"
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
public
|
271
|
+
|
272
|
+
class ProcessInformation
|
273
|
+
attr_reader :process_handle
|
274
|
+
attr_reader :thread_handle
|
275
|
+
attr_reader :process_id
|
276
|
+
attr_reader :thread_id
|
277
|
+
|
278
|
+
def initialize(process_information)
|
279
|
+
@process_handle = process_information[:hProcess]
|
280
|
+
@thread_handle = process_information[:hThread]
|
281
|
+
@process_id = process_information[:dwProcessId]
|
282
|
+
@thread_id = process_information[:dwThreadId]
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
class FileInformation
|
287
|
+
attr_reader :attributes
|
288
|
+
attr_reader :create_time
|
289
|
+
attr_reader :last_access_time
|
290
|
+
attr_reader :last_write_time
|
291
|
+
attr_reader :size
|
292
|
+
attr_reader :name
|
293
|
+
|
294
|
+
def initialize(ce_find_data)
|
295
|
+
@attributes = FileAttributes.new(ce_find_data[:dwFileAttributes])
|
296
|
+
@create_time = ce_find_data[:ftCreationTime]
|
297
|
+
@last_access_time = ce_find_data[:ftLastAccessTime]
|
298
|
+
@last_write_time = ce_find_data[:ftLastWriteTime]
|
299
|
+
@name = encode(ce_find_data[:cFileName].to_ptr.get_bytes(0, 260))
|
300
|
+
@size = ce_find_data[:nFileSizeHigh] << 32 &&
|
301
|
+
ce_find_data[:nFileSizeLow]
|
302
|
+
end
|
303
|
+
|
304
|
+
private
|
305
|
+
|
306
|
+
if RUBY_VERSION =~ /^1\.9\.\d/
|
307
|
+
def encode(path)
|
308
|
+
path.force_encoding("UTF-16LE").strip
|
309
|
+
end
|
310
|
+
else
|
311
|
+
def encode(path)
|
312
|
+
Iconv.conv("ASCII", "UTF-16LE", path).strip
|
313
|
+
end
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
class Enum
|
318
|
+
|
319
|
+
private
|
320
|
+
|
321
|
+
def self.enum_attr(name, num)
|
322
|
+
name = name.to_s
|
323
|
+
define_method(name + "?") do
|
324
|
+
@attrs & num != 0
|
325
|
+
end
|
326
|
+
|
327
|
+
define_method(name + "=") do |set|
|
328
|
+
if set
|
329
|
+
@attrs |= num
|
330
|
+
else
|
331
|
+
@attrs &= ~num
|
332
|
+
end
|
333
|
+
end
|
334
|
+
end
|
335
|
+
|
336
|
+
public
|
337
|
+
|
338
|
+
def initialize(attrs = 0)
|
339
|
+
@attrs = attrs.to_i
|
340
|
+
end
|
341
|
+
|
342
|
+
def to_i
|
343
|
+
@attrs
|
344
|
+
end
|
345
|
+
end
|
346
|
+
|
347
|
+
class FileAttributes < Enum
|
348
|
+
enum_attr :readonly, 0x0001
|
349
|
+
enum_attr :hidden, 0x0002
|
350
|
+
enum_attr :system, 0x0004
|
351
|
+
enum_attr :directory, 0x0010
|
352
|
+
enum_attr :archive, 0x0020
|
353
|
+
enum_attr :in_rom, 0x0040
|
354
|
+
enum_attr :normal, 0x0080
|
355
|
+
enum_attr :temporary, 0x0100
|
356
|
+
enum_attr :sparse, 0x0200
|
357
|
+
enum_attr :reparse_point, 0x0400
|
358
|
+
enum_attr :compressed, 0x0800
|
359
|
+
enum_attr :rom_module, 0x2000
|
360
|
+
end
|
361
|
+
|
362
|
+
class RAPIException < Exception
|
363
|
+
end
|
364
|
+
|
365
|
+
module Native
|
366
|
+
|
367
|
+
# Winbase.h
|
368
|
+
WAIT_ABANDONED = 0x00000080
|
369
|
+
WAIT_FAILED = 0xFFFFFFFF
|
370
|
+
WAIT_TIMEOUT = 0x00000102
|
371
|
+
WAIT_OBJECT_0 = 0x00000000
|
372
|
+
|
373
|
+
FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000
|
374
|
+
FORMAT_MESSAGE_FROM_HMODULE = 0x00000800
|
375
|
+
FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200
|
376
|
+
FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100
|
377
|
+
|
378
|
+
FILE_SHARE_READ = 0x00000001
|
379
|
+
CREATE_NEW = 0x00000001
|
380
|
+
CREATE_ALWAYS = 0x00000002
|
381
|
+
GENERIC_WRITE = 0x40000000
|
382
|
+
GENERIC_READ = 0x80000000
|
383
|
+
OPEN_EXISTING = 0x00000003
|
384
|
+
FILE_ATTRIBUTE_NORMAL = 0x80
|
385
|
+
INVALID_HANDLE = FFI::Pointer.new(-1)
|
386
|
+
|
387
|
+
class FILETIME
|
388
|
+
extend FFI::DataConverter
|
389
|
+
native_type :uint64
|
390
|
+
|
391
|
+
def self.from_native(val, ctx)
|
392
|
+
Time.at((val * 1.0e-07) + Time.new(1601).to_f)
|
393
|
+
end
|
394
|
+
|
395
|
+
def self.to_native(val, ctx)
|
396
|
+
((val.to_f - Time.new(1601).to_f) / 1.0e-07).to_i
|
397
|
+
end
|
398
|
+
end
|
399
|
+
|
400
|
+
module Rapi
|
401
|
+
extend FFI::Library
|
402
|
+
ffi_lib 'rapi.dll'
|
403
|
+
ffi_convention :stdcall
|
404
|
+
|
405
|
+
class RAPIINIT < FFI::Struct
|
406
|
+
layout :cbSize, :int,
|
407
|
+
:heRapiInit, :pointer,
|
408
|
+
:hrRapiInit, :int
|
409
|
+
end
|
410
|
+
|
411
|
+
class CE_FIND_DATA < FFI::Struct
|
412
|
+
layout :dwFileAttributes, :uint, 0,
|
413
|
+
:ftCreationTime, FILETIME, 4,
|
414
|
+
:ftLastAccessTime, FILETIME, 12,
|
415
|
+
:ftLastWriteTime, FILETIME, 20,
|
416
|
+
:nFileSizeHigh, :uint, 28,
|
417
|
+
:nFileSizeLow, :uint, 32,
|
418
|
+
:dwOID, :uint, 36,
|
419
|
+
:cFileName, [:uint8, 260], 40
|
420
|
+
end
|
421
|
+
|
422
|
+
class PROCESS_INFORMATION < FFI::Struct
|
423
|
+
layout :hProcess, :pointer,
|
424
|
+
:hThread, :pointer,
|
425
|
+
:dwProcessId, :uint,
|
426
|
+
:dwThreadId, :uint
|
427
|
+
end
|
428
|
+
|
429
|
+
attach_function :CeRapiInitEx, [RAPIINIT.by_ref], :int
|
430
|
+
attach_function :CeRapiUninit, [], :int
|
431
|
+
attach_function :CeRapiGetError, [], :int
|
432
|
+
attach_function :CeCloseHandle, [:pointer], :int
|
433
|
+
attach_function :CeWriteFile, [:pointer, :pointer, :int, :pointer, :int], :int
|
434
|
+
attach_function :CeReadFile, [:pointer, :pointer, :int, :pointer, :int], :int
|
435
|
+
attach_function :CeRapiFreeBuffer, [:pointer], :void
|
436
|
+
attach_function :CeGetFileAttributes, [:pointer], :uint
|
437
|
+
attach_function :CeCreateFile, [:pointer, :uint, :int, :int, :int, :int, :int], :pointer
|
438
|
+
attach_function :CeCopyFile, [:pointer, :pointer, :int], :int
|
439
|
+
attach_function :CeDeleteFile, [:pointer], :int
|
440
|
+
attach_function :CeGetFileAttributes, [:pointer], :uint
|
441
|
+
attach_function :CeSetFileAttributes, [:pointer, :uint], :int
|
442
|
+
attach_function :CeFindFirstFile, [:pointer, CE_FIND_DATA.by_ref], :pointer
|
443
|
+
attach_function :CeFindNextFile, [:pointer, CE_FIND_DATA.by_ref], :int
|
444
|
+
attach_function :CeFindClose, [:pointer], :int
|
445
|
+
attach_function :CeCreateProcess, [:pointer, :pointer, :pointer, :pointer, :int, :int, :pointer, :pointer, :pointer, PROCESS_INFORMATION.ptr], :int
|
446
|
+
attach_function :CeGetLastError, [], :int
|
447
|
+
end
|
448
|
+
|
449
|
+
module Kernel32
|
450
|
+
extend FFI::Library
|
451
|
+
ffi_lib 'kernel32'
|
452
|
+
ffi_convention :stdcall
|
453
|
+
|
454
|
+
@blocking = true
|
455
|
+
attach_function :WaitForSingleObject, [:pointer, :uint], :uint
|
456
|
+
attach_function :FormatMessageW, [:int, :pointer, :int, :int, :pointer, :int, :pointer], :int
|
457
|
+
attach_function :FormatMessageA, [:int, :pointer, :int, :int, :pointer, :int, :pointer], :int
|
458
|
+
attach_function :CloseHandle, [:pointer], :int
|
459
|
+
attach_function :LocalFree, [:pointer], :pointer
|
460
|
+
end
|
461
|
+
end
|
462
|
+
end
|
data/rapi.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{rapi}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.1.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Charles Strahan"]
|
12
|
-
s.date = %q{2011-05-
|
12
|
+
s.date = %q{2011-05-30}
|
13
13
|
s.description = %q{A Remote API (RAPI) interface.}
|
14
14
|
s.email = %q{charles.c.strahan@gmail.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -24,6 +24,7 @@ Gem::Specification.new do |s|
|
|
24
24
|
"Rakefile",
|
25
25
|
"VERSION",
|
26
26
|
"lib/rapi.rb",
|
27
|
+
"lib/rapi/ce_registry_key.rb",
|
27
28
|
"rapi.gemspec",
|
28
29
|
"test/helper.rb",
|
29
30
|
"test/test_rapi.rb"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rapi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,12 +9,12 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-05-
|
12
|
+
date: 2011-05-30 00:00:00.000000000 -05:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: ffi
|
17
|
-
requirement: &
|
17
|
+
requirement: &21938064 !ruby/object:Gem::Requirement
|
18
18
|
none: false
|
19
19
|
requirements:
|
20
20
|
- - ~>
|
@@ -22,10 +22,10 @@ dependencies:
|
|
22
22
|
version: 1.0.7
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
|
-
version_requirements: *
|
25
|
+
version_requirements: *21938064
|
26
26
|
- !ruby/object:Gem::Dependency
|
27
27
|
name: shoulda
|
28
|
-
requirement: &
|
28
|
+
requirement: &21937572 !ruby/object:Gem::Requirement
|
29
29
|
none: false
|
30
30
|
requirements:
|
31
31
|
- - ! '>='
|
@@ -33,10 +33,10 @@ dependencies:
|
|
33
33
|
version: '0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
|
-
version_requirements: *
|
36
|
+
version_requirements: *21937572
|
37
37
|
- !ruby/object:Gem::Dependency
|
38
38
|
name: bundler
|
39
|
-
requirement: &
|
39
|
+
requirement: &21936936 !ruby/object:Gem::Requirement
|
40
40
|
none: false
|
41
41
|
requirements:
|
42
42
|
- - ~>
|
@@ -44,10 +44,10 @@ dependencies:
|
|
44
44
|
version: 1.0.0
|
45
45
|
type: :development
|
46
46
|
prerelease: false
|
47
|
-
version_requirements: *
|
47
|
+
version_requirements: *21936936
|
48
48
|
- !ruby/object:Gem::Dependency
|
49
49
|
name: jeweler
|
50
|
-
requirement: &
|
50
|
+
requirement: &21936348 !ruby/object:Gem::Requirement
|
51
51
|
none: false
|
52
52
|
requirements:
|
53
53
|
- - ~>
|
@@ -55,10 +55,10 @@ dependencies:
|
|
55
55
|
version: 1.6.0
|
56
56
|
type: :development
|
57
57
|
prerelease: false
|
58
|
-
version_requirements: *
|
58
|
+
version_requirements: *21936348
|
59
59
|
- !ruby/object:Gem::Dependency
|
60
60
|
name: rcov
|
61
|
-
requirement: &
|
61
|
+
requirement: &21935700 !ruby/object:Gem::Requirement
|
62
62
|
none: false
|
63
63
|
requirements:
|
64
64
|
- - ! '>='
|
@@ -66,7 +66,7 @@ dependencies:
|
|
66
66
|
version: '0'
|
67
67
|
type: :development
|
68
68
|
prerelease: false
|
69
|
-
version_requirements: *
|
69
|
+
version_requirements: *21935700
|
70
70
|
description: A Remote API (RAPI) interface.
|
71
71
|
email: charles.c.strahan@gmail.com
|
72
72
|
executables: []
|
@@ -82,6 +82,7 @@ files:
|
|
82
82
|
- Rakefile
|
83
83
|
- VERSION
|
84
84
|
- lib/rapi.rb
|
85
|
+
- lib/rapi/ce_registry_key.rb
|
85
86
|
- rapi.gemspec
|
86
87
|
- test/helper.rb
|
87
88
|
- test/test_rapi.rb
|
@@ -101,7 +102,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
101
102
|
version: '0'
|
102
103
|
segments:
|
103
104
|
- 0
|
104
|
-
hash:
|
105
|
+
hash: 285988977
|
105
106
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
106
107
|
none: false
|
107
108
|
requirements:
|