rets-hack 0.11
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +142 -0
- data/Manifest.txt +58 -0
- data/README.md +129 -0
- data/Rakefile +28 -0
- data/bin/rets +202 -0
- data/example/connect.rb +19 -0
- data/example/get-photos.rb +20 -0
- data/example/get-property.rb +16 -0
- data/lib/rets/client.rb +373 -0
- data/lib/rets/client_progress_reporter.rb +48 -0
- data/lib/rets/http_client.rb +133 -0
- data/lib/rets/locking_http_client.rb +34 -0
- data/lib/rets/measuring_http_client.rb +27 -0
- data/lib/rets/metadata/caching.rb +59 -0
- data/lib/rets/metadata/containers.rb +89 -0
- data/lib/rets/metadata/file_cache.rb +29 -0
- data/lib/rets/metadata/json_serializer.rb +27 -0
- data/lib/rets/metadata/lookup_table.rb +65 -0
- data/lib/rets/metadata/lookup_type.rb +19 -0
- data/lib/rets/metadata/marshal_serializer.rb +27 -0
- data/lib/rets/metadata/multi_lookup_table.rb +70 -0
- data/lib/rets/metadata/null_cache.rb +24 -0
- data/lib/rets/metadata/resource.rb +103 -0
- data/lib/rets/metadata/rets_class.rb +57 -0
- data/lib/rets/metadata/rets_object.rb +41 -0
- data/lib/rets/metadata/root.rb +155 -0
- data/lib/rets/metadata/table.rb +33 -0
- data/lib/rets/metadata/table_factory.rb +19 -0
- data/lib/rets/metadata/yaml_serializer.rb +27 -0
- data/lib/rets/metadata.rb +18 -0
- data/lib/rets/parser/compact.rb +117 -0
- data/lib/rets/parser/error_checker.rb +56 -0
- data/lib/rets/parser/multipart.rb +39 -0
- data/lib/rets.rb +269 -0
- data/test/fixtures.rb +324 -0
- data/test/helper.rb +14 -0
- data/test/test_caching.rb +89 -0
- data/test/test_client.rb +307 -0
- data/test/test_error_checker.rb +87 -0
- data/test/test_file_cache.rb +42 -0
- data/test/test_http_client.rb +132 -0
- data/test/test_json_serializer.rb +26 -0
- data/test/test_locking_http_client.rb +29 -0
- data/test/test_marshal_serializer.rb +26 -0
- data/test/test_metadata.rb +71 -0
- data/test/test_metadata_class.rb +50 -0
- data/test/test_metadata_lookup_table.rb +21 -0
- data/test/test_metadata_lookup_type.rb +21 -0
- data/test/test_metadata_multi_lookup_table.rb +60 -0
- data/test/test_metadata_object.rb +33 -0
- data/test/test_metadata_resource.rb +148 -0
- data/test/test_metadata_root.rb +151 -0
- data/test/test_metadata_table.rb +21 -0
- data/test/test_metadata_table_factory.rb +24 -0
- data/test/test_parser_compact.rb +115 -0
- data/test/test_parser_multipart.rb +39 -0
- data/test/test_yaml_serializer.rb +26 -0
- data/test/vcr_cassettes/unauthorized_response.yml +262 -0
- metadata +227 -0
@@ -0,0 +1,115 @@
|
|
1
|
+
require_relative "helper"
|
2
|
+
|
3
|
+
class TestParserCompact < MiniTest::Test
|
4
|
+
def test_parse_document_raises_on_invalid_delimiter
|
5
|
+
assert_raises Rets::Parser::Compact::InvalidDelimiter do
|
6
|
+
Rets::Parser::Compact.parse_document(INVALID_DELIMETER)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_parse_document_delegates_to_parse
|
11
|
+
result = Rets::Parser::Compact.parse_document(COMPACT)
|
12
|
+
|
13
|
+
assert_equal([{"A" => "1", "B" => "2"}, {"A" => "4", "B" => "5"}], result)
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_parser_rejects_empty_key_value_pairs
|
17
|
+
result = Rets::Parser::Compact.parse_document(METADATA_OBJECT)
|
18
|
+
|
19
|
+
result.each do |row|
|
20
|
+
assert !row.any? { |k,v| k.to_s.size == 0 }, "Should not contain empty keys"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# RMLS does this. :|
|
25
|
+
def test_remaining_columns_produce_empty_string_values
|
26
|
+
column_names = "A B C D"
|
27
|
+
data = "1 2"
|
28
|
+
|
29
|
+
assert_equal({"A" => "1", "B" => "2", "C" => "", "D" => ""}, Rets::Parser::Compact.parse(column_names, data, ' '))
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_leading_empty_columns_are_preserved_with_delimiter
|
33
|
+
column_names = "A\tB\tC\tD"
|
34
|
+
data = "\t\t3\t4" # first two columns are empty data.
|
35
|
+
|
36
|
+
assert_equal({"A" => "", "B" => "", "C" => "3", "D" => "4"}, Rets::Parser::Compact.parse(column_names, data, "\t"))
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_parse_empty_document
|
40
|
+
rows = Rets::Parser::Compact.parse_document(EMPTY_COMPACT)
|
41
|
+
assert_equal [], rows
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_get_count
|
45
|
+
count = Rets::Parser::Compact.get_count(COUNT_ONLY)
|
46
|
+
assert_equal 1234, count
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_get_count_with_no_matching_records
|
50
|
+
count = Rets::Parser::Compact.get_count(RETS_STATUS_NO_MATCHING_RECORDS)
|
51
|
+
assert_equal 0, count
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_get_count_with_unrecognized_document
|
55
|
+
count = Rets::Parser::Compact.get_count("")
|
56
|
+
assert_equal 0, count
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_parse_example
|
60
|
+
rows = Rets::Parser::Compact.parse_document(SAMPLE_COMPACT)
|
61
|
+
|
62
|
+
assert_equal "7", rows.first["MetadataEntryID"]
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_parse_example_2
|
66
|
+
rows = Rets::Parser::Compact.parse_document(SAMPLE_COMPACT_2)
|
67
|
+
|
68
|
+
assert_equal "", rows.first["ModTimeStamp"]
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_parse_with_changed_delimiter
|
72
|
+
rows = Rets::Parser::Compact.parse_document(CHANGED_DELIMITER)
|
73
|
+
|
74
|
+
assert_equal [{"A" => "1", "B" => "2"}, {"A" => "4", "B" => "5"}], rows
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_parse_html_encoded_chars
|
78
|
+
rows = Rets::Parser::Compact.parse_document(SAMPLE_COMPACT_WITH_SPECIAL_CHARS)
|
79
|
+
|
80
|
+
assert_equal "porte-coch\u{E8}re welcomes ", rows.last["PublicRemarksNew"]
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_parse_html_encoded_chars_2
|
84
|
+
rows = Rets::Parser::Compact.parse_document(SAMPLE_COMPACT_WITH_SPECIAL_CHARS_2)
|
85
|
+
|
86
|
+
assert_equal "text with <tag>", rows.last["PublicRemarksNew"]
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_parse_doubly_encoded_bad_character_references
|
90
|
+
rows = Rets::Parser::Compact.parse_document(SAMPLE_COMPACT_WITH_DOUBLY_ENCODED_BAD_CHARACTER_REFERENCES)
|
91
|
+
assert_equal "foo bar", rows.last["PublicRemarksNew"]
|
92
|
+
end
|
93
|
+
|
94
|
+
def test_parse_property_with_lots_of_columns
|
95
|
+
row = Rets::Parser::Compact.parse_document(SAMPLE_PROPERTY_WITH_LOTS_OF_COLUMNS).first
|
96
|
+
assert_equal 800, row.keys.size
|
97
|
+
assert_equal 800.times.map { |x| "K%03d" % x }, row.keys
|
98
|
+
end
|
99
|
+
|
100
|
+
def test_safely_decode_character_references!
|
101
|
+
assert_decoded "a", "a"
|
102
|
+
assert_decoded "a", "a"
|
103
|
+
assert_decoded "a", "a"
|
104
|
+
assert_decoded "a", "a"
|
105
|
+
assert_decoded "", "�"
|
106
|
+
assert_decoded "", "�"
|
107
|
+
assert_decoded "", "�"
|
108
|
+
end
|
109
|
+
|
110
|
+
|
111
|
+
def assert_decoded(a, b)
|
112
|
+
recoded = Rets::Parser::Compact.safely_decode_character_references!(b)
|
113
|
+
assert_equal a, recoded
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require_relative "helper"
|
2
|
+
|
3
|
+
class TestParserMultipart < MiniTest::Test
|
4
|
+
def test_parse_returns_multiple_parts
|
5
|
+
headers = {"content-type"=>"image/jpeg", "content-id"=>"90020062739", "content-length"=>"10"}
|
6
|
+
|
7
|
+
parts = Rets::Parser::Multipart.parse(MULITPART_RESPONSE, "simple boundary")
|
8
|
+
|
9
|
+
assert_equal 2, parts.size
|
10
|
+
|
11
|
+
part = parts[0]
|
12
|
+
|
13
|
+
assert_equal headers.merge("object-id" => "1"), part.headers
|
14
|
+
assert_equal "xxxxxxxx", part.body.strip
|
15
|
+
|
16
|
+
part = parts[1]
|
17
|
+
|
18
|
+
assert_equal headers.merge("object-id" => "2"), part.headers
|
19
|
+
assert_equal "yyyyyyyy", part.body.strip
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_parse_real_mls_data
|
23
|
+
parts = Rets::Parser::Multipart.parse(MULTIPART_RESPONSE_URLS, "rets.object.content.boundary.1330546052739")
|
24
|
+
assert_equal 5, parts.size
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_parse_values_with_colon_data
|
28
|
+
parts = Rets::Parser::Multipart.parse(MULTIPART_RESPONSE_URLS, "rets.object.content.boundary.1330546052739")
|
29
|
+
assert_equal 'http://foobarmls.com/RETS//MediaDisplay/98/hr2890998-1.jpg', parts[0].headers['location']
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_parse_with_error
|
33
|
+
raw = "\r\n--89467f8e0c6b48158c8f1883910212ec\r\nContent-Type: text/xml\r\nContent-ID: foo\r\nObject-ID: *\r\n\r\n<RETS ReplyCode=\"999\" ReplyText=\"An Unexplaned Error\" />\r\n\r\n--89467f8e0c6b48158c8f1883910212ec--\r\n"
|
34
|
+
boundary = "89467f8e0c6b48158c8f1883910212ec"
|
35
|
+
assert_raises Rets::InvalidRequest do
|
36
|
+
Rets::Parser::Multipart.parse(raw, boundary)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require_relative "helper"
|
2
|
+
|
3
|
+
require "stringio"
|
4
|
+
|
5
|
+
class TestYamlSerializer < MiniTest::Test
|
6
|
+
|
7
|
+
def setup
|
8
|
+
@serializer = Rets::Metadata::YamlSerializer.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_round_trip
|
12
|
+
metadata = {"foo" => "bar"}
|
13
|
+
file = StringIO.new
|
14
|
+
@serializer.save(file, metadata)
|
15
|
+
file.rewind
|
16
|
+
loaded = @serializer.load(file)
|
17
|
+
assert_equal metadata, loaded
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_bad_data
|
21
|
+
file = StringIO.new("\x01")
|
22
|
+
loaded = @serializer.load(file)
|
23
|
+
assert_nil loaded
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,262 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: post
|
5
|
+
uri: http://rets.example.com/GetObject.asmx/GetObject
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: Resource=Property&Type=Photo&ID=2661580%3A1&Location=0
|
9
|
+
headers:
|
10
|
+
User-Agent:
|
11
|
+
- Estately/1.0
|
12
|
+
Host:
|
13
|
+
- rets.example.com:80
|
14
|
+
Rets-Version:
|
15
|
+
- RETS/1.7.2
|
16
|
+
Authorization:
|
17
|
+
- Digest username="login", realm="fake_realm", qop="auth",
|
18
|
+
uri="/Login.asmx/Login", nonce="a8f4bc805062602c8ba7a87b2109f808", nc=00000001,
|
19
|
+
cnonce="6e2dd038eea6cbacf0b956fd11f914b6", response="fake_digest",
|
20
|
+
opaque="96eda461-41d0-4624-b7fe-b59e966035f3"
|
21
|
+
Cookie:
|
22
|
+
- ASP.NET_SessionId=mapij045k3bphj3gqqgpmmrx
|
23
|
+
Accept:
|
24
|
+
- image/jpeg, image/png;q=0.5, image/gif;q=0.1
|
25
|
+
Content-Type:
|
26
|
+
- application/x-www-form-urlencoded
|
27
|
+
Content-Length:
|
28
|
+
- '54'
|
29
|
+
response:
|
30
|
+
status:
|
31
|
+
code: 401
|
32
|
+
message: Unauthorized
|
33
|
+
headers:
|
34
|
+
Connection:
|
35
|
+
- close
|
36
|
+
Date:
|
37
|
+
- Thu, 26 Jul 2012 00:11:02 GMT
|
38
|
+
Server:
|
39
|
+
- Microsoft-IIS/6.0
|
40
|
+
Cache-Control:
|
41
|
+
- private
|
42
|
+
- private
|
43
|
+
X-Aspnet-Version:
|
44
|
+
- 2.0.50727
|
45
|
+
Www-Authenticate:
|
46
|
+
- Digest realm="fake_realm",nonce="dfd74deac03147e1a4fff598679f1a80",opaque="8e5029c6-bb9c-4562-b440-e7c2b8960743",qop="auth"
|
47
|
+
Content-Type:
|
48
|
+
- text/plain
|
49
|
+
body:
|
50
|
+
encoding: US-ASCII
|
51
|
+
string: ! "Unauthorized Request. Digest Session Invalid Reauthenticate\r\nReference:
|
52
|
+
e0ff89c0-2d64-4287-a6b7-6be27c7d3ade"
|
53
|
+
http_version:
|
54
|
+
recorded_at: Thu, 26 Jul 2012 00:11:13 GMT
|
55
|
+
- request:
|
56
|
+
method: post
|
57
|
+
uri: http://rets.example.com/Login.asmx/Login
|
58
|
+
body:
|
59
|
+
encoding: US-ASCII
|
60
|
+
string: ''
|
61
|
+
headers:
|
62
|
+
User-Agent:
|
63
|
+
- Estately/1.0
|
64
|
+
Host:
|
65
|
+
- rets.example.com:80
|
66
|
+
Rets-Version:
|
67
|
+
- RETS/1.7.2
|
68
|
+
Accept:
|
69
|
+
- ! '*/*'
|
70
|
+
response:
|
71
|
+
status:
|
72
|
+
code: 401
|
73
|
+
message: Unauthorized
|
74
|
+
headers:
|
75
|
+
Connection:
|
76
|
+
- close
|
77
|
+
Date:
|
78
|
+
- Thu, 26 Jul 2012 00:11:03 GMT
|
79
|
+
Server:
|
80
|
+
- Microsoft-IIS/6.0
|
81
|
+
Cache-Control:
|
82
|
+
- private
|
83
|
+
- private
|
84
|
+
X-Aspnet-Version:
|
85
|
+
- 2.0.50727
|
86
|
+
Www-Authenticate:
|
87
|
+
- Digest realm="fake_realm",nonce="17fdfe2c6125296bd93bb81bd88dc4be",opaque="aee1e7da-60eb-41b3-b704-8eb3969645fd",qop="auth"
|
88
|
+
Content-Type:
|
89
|
+
- text/plain
|
90
|
+
body:
|
91
|
+
encoding: US-ASCII
|
92
|
+
string: ! "Unauthorized Request. Authentication needed\r\nReference: c2c5ab9f-8c12-42bb-94ce-5b6ebf156da4"
|
93
|
+
http_version:
|
94
|
+
recorded_at: Thu, 26 Jul 2012 00:11:13 GMT
|
95
|
+
- request:
|
96
|
+
method: post
|
97
|
+
uri: http://rets.example.com/Login.asmx/Login
|
98
|
+
body:
|
99
|
+
encoding: US-ASCII
|
100
|
+
string: ''
|
101
|
+
headers:
|
102
|
+
User-Agent:
|
103
|
+
- Estately/1.0
|
104
|
+
Host:
|
105
|
+
- rets.example.com:80
|
106
|
+
Rets-Version:
|
107
|
+
- RETS/1.7.2
|
108
|
+
Authorization:
|
109
|
+
- Digest username="login", realm="fake_realm", qop="auth",
|
110
|
+
uri="/Login.asmx/Login", nonce="17fdfe2c6125296bd93bb81bd88dc4be", nc=00000001,
|
111
|
+
cnonce="ad805b9e2d6f08ad82175085e5febd8d", response="7402076f53663602f052e1aa343d3dab",
|
112
|
+
opaque="aee1e7da-60eb-41b3-b704-8eb3969645fd"
|
113
|
+
Accept:
|
114
|
+
- ! '*/*'
|
115
|
+
response:
|
116
|
+
status:
|
117
|
+
code: 200
|
118
|
+
message: OK
|
119
|
+
headers:
|
120
|
+
Date:
|
121
|
+
- Thu, 26 Jul 2012 00:11:03 GMT
|
122
|
+
Server:
|
123
|
+
- Microsoft-IIS/6.0
|
124
|
+
Cache-Control:
|
125
|
+
- private
|
126
|
+
- private, max-age=0
|
127
|
+
X-Aspnet-Version:
|
128
|
+
- 2.0.50727
|
129
|
+
Rets-Version:
|
130
|
+
- RETS/1.7.2
|
131
|
+
Rets-Server:
|
132
|
+
- Interealty-RETS/1.5.247.0
|
133
|
+
Transfer-Encoding:
|
134
|
+
- chunked
|
135
|
+
Set-Cookie:
|
136
|
+
- ASP.NET_SessionId=vuesmq55l0cpjy45zyn0e555; path=/; HttpOnly
|
137
|
+
- RETS-Session-ID=vuesmq55l0cpjy45zyn0e555; path=/
|
138
|
+
Content-Type:
|
139
|
+
- text/xml
|
140
|
+
body:
|
141
|
+
encoding: US-ASCII
|
142
|
+
string: ! "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<RETS ReplyCode=\"0\"
|
143
|
+
ReplyText=\"Success. Reference ID: a3073726-a011-4391-b22e-900adae5184b\">\r\n
|
144
|
+
\ <RETS-RESPONSE>\r\nMemberName=John Wolff\r\nUser=23756,60,RH,login\r\nBroker=BRDA,BRDA01\r\nMetadataVersion=31.76.69587\r\nMetadataTimeStamp=2012-07-24T17:33:07Z\r\nMinMetadataTimeStamp=2012-07-24T17:33:07Z\r\nTimeoutSeconds=7200\r\nChangePassword=/ChangePassword.asmx/ChangePassword\r\nGetObject=/GetObject.asmx/GetObject\r\nLogin=/Login.asmx/Login\r\nLogout=/Logout.asmx/Logout\r\nSearch=/Search.asmx/Search\r\nGetMetadata=/GetMetadata.asmx/GetMetadata\r\n</RETS-RESPONSE>\r\n</RETS>"
|
145
|
+
http_version:
|
146
|
+
recorded_at: Thu, 26 Jul 2012 00:11:14 GMT
|
147
|
+
- request:
|
148
|
+
method: post
|
149
|
+
uri: http://rets.example.com/Login.asmx/Login
|
150
|
+
body:
|
151
|
+
encoding: US-ASCII
|
152
|
+
string: ''
|
153
|
+
headers:
|
154
|
+
User-Agent:
|
155
|
+
- Estately/1.0
|
156
|
+
Host:
|
157
|
+
- rets.example.com:80
|
158
|
+
Rets-Version:
|
159
|
+
- RETS/1.7.2
|
160
|
+
Authorization:
|
161
|
+
- Digest username="login", realm="fake_realm", qop="auth",
|
162
|
+
uri="/Login.asmx/Login", nonce="17fdfe2c6125296bd93bb81bd88dc4be", nc=00000001,
|
163
|
+
cnonce="ad805b9e2d6f08ad82175085e5febd8d", response="7402076f53663602f052e1aa343d3dab",
|
164
|
+
opaque="aee1e7da-60eb-41b3-b704-8eb3969645fd"
|
165
|
+
Cookie:
|
166
|
+
- ASP.NET_SessionId=vuesmq55l0cpjy45zyn0e555; RETS-Session-ID=vuesmq55l0cpjy45zyn0e555
|
167
|
+
Accept:
|
168
|
+
- ! '*/*'
|
169
|
+
response:
|
170
|
+
status:
|
171
|
+
code: 200
|
172
|
+
message: OK
|
173
|
+
headers:
|
174
|
+
Date:
|
175
|
+
- Thu, 26 Jul 2012 00:11:03 GMT
|
176
|
+
Server:
|
177
|
+
- Microsoft-IIS/6.0
|
178
|
+
Cache-Control:
|
179
|
+
- private
|
180
|
+
- private, max-age=0
|
181
|
+
X-Aspnet-Version:
|
182
|
+
- 2.0.50727
|
183
|
+
Rets-Version:
|
184
|
+
- RETS/1.7.2
|
185
|
+
Rets-Server:
|
186
|
+
- Interealty-RETS/1.5.247.0
|
187
|
+
Transfer-Encoding:
|
188
|
+
- chunked
|
189
|
+
Set-Cookie:
|
190
|
+
- RETS-Session-ID=vuesmq55l0cpjy45zyn0e555; path=/
|
191
|
+
Content-Type:
|
192
|
+
- text/xml
|
193
|
+
body:
|
194
|
+
encoding: US-ASCII
|
195
|
+
string: ! "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<RETS ReplyCode=\"0\"
|
196
|
+
ReplyText=\"Success. Reference ID: a48b4f59-cb22-41be-8e7b-1cee28fb8644\">\r\n
|
197
|
+
\ <RETS-RESPONSE>\r\nMemberName=John Wolff\r\nUser=23756,60,RH,login\r\nBroker=BRDA,BRDA01\r\nMetadataVersion=31.76.69587\r\nMetadataTimeStamp=2012-07-24T17:33:07Z\r\nMinMetadataTimeStamp=2012-07-24T17:33:07Z\r\nTimeoutSeconds=7200\r\nChangePassword=/ChangePassword.asmx/ChangePassword\r\nGetObject=/GetObject.asmx/GetObject\r\nLogin=/Login.asmx/Login\r\nLogout=/Logout.asmx/Logout\r\nSearch=/Search.asmx/Search\r\nGetMetadata=/GetMetadata.asmx/GetMetadata\r\n</RETS-RESPONSE>\r\n</RETS>"
|
198
|
+
http_version:
|
199
|
+
recorded_at: Thu, 26 Jul 2012 00:11:14 GMT
|
200
|
+
- request:
|
201
|
+
method: post
|
202
|
+
uri: http://rets.example.com/GetObject.asmx/GetObject
|
203
|
+
body:
|
204
|
+
encoding: US-ASCII
|
205
|
+
string: Resource=Property&Type=Photo&ID=2661580%3A1&Location=0
|
206
|
+
headers:
|
207
|
+
User-Agent:
|
208
|
+
- Estately/1.0
|
209
|
+
Host:
|
210
|
+
- rets.example.com:80
|
211
|
+
Rets-Version:
|
212
|
+
- RETS/1.7.2
|
213
|
+
Authorization:
|
214
|
+
- Digest username="login", realm="fake_realm", qop="auth",
|
215
|
+
uri="/Login.asmx/Login", nonce="17fdfe2c6125296bd93bb81bd88dc4be", nc=00000001,
|
216
|
+
cnonce="ad805b9e2d6f08ad82175085e5febd8d", response="7402076f53663602f052e1aa343d3dab",
|
217
|
+
opaque="aee1e7da-60eb-41b3-b704-8eb3969645fd"
|
218
|
+
Cookie:
|
219
|
+
- ASP.NET_SessionId=vuesmq55l0cpjy45zyn0e555; RETS-Session-ID=vuesmq55l0cpjy45zyn0e555
|
220
|
+
Accept:
|
221
|
+
- image/jpeg, image/png;q=0.5, image/gif;q=0.1
|
222
|
+
Content-Type:
|
223
|
+
- application/x-www-form-urlencoded
|
224
|
+
Content-Length:
|
225
|
+
- '54'
|
226
|
+
response:
|
227
|
+
status:
|
228
|
+
code: 200
|
229
|
+
message: OK
|
230
|
+
headers:
|
231
|
+
Date:
|
232
|
+
- Thu, 26 Jul 2012 00:11:04 GMT
|
233
|
+
Server:
|
234
|
+
- Microsoft-IIS/6.0
|
235
|
+
Cache-Control:
|
236
|
+
- private
|
237
|
+
- private, max-age=0
|
238
|
+
X-Aspnet-Version:
|
239
|
+
- 2.0.50727
|
240
|
+
Mime-Version:
|
241
|
+
- '1.0'
|
242
|
+
Rets-Version:
|
243
|
+
- RETS/1.7.2
|
244
|
+
Rets-Server:
|
245
|
+
- Interealty-RETS/1.5.247.0
|
246
|
+
Content-Id:
|
247
|
+
- '2661580'
|
248
|
+
Object-Id:
|
249
|
+
- '1'
|
250
|
+
Transfer-Encoding:
|
251
|
+
- chunked
|
252
|
+
Set-Cookie:
|
253
|
+
- RETS-Session-ID=vuesmq55l0cpjy45zyn0e555; path=/
|
254
|
+
Content-Type:
|
255
|
+
- image/jpeg
|
256
|
+
body:
|
257
|
+
encoding: ASCII-8BIT
|
258
|
+
string: !binary |-
|
259
|
+
/9j/4AAQSkZJRgABAQEAYABgAAD///2Q==
|
260
|
+
http_version:
|
261
|
+
recorded_at: Thu, 26 Jul 2012 00:11:14 GMT
|
262
|
+
recorded_with: VCR 2.2.2
|
metadata
ADDED
@@ -0,0 +1,227 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rets-hack
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0.11'
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Estately, Inc. Open Source
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-01-30 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: httpclient
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 2.7.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 2.7.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: http-cookie
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.0.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 1.0.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: nokogiri
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.5'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.5'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rdoc
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '4.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '4.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: mocha
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 1.1.0
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 1.1.0
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: vcr
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '2.2'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '2.2'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: webmock
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '1.8'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '1.8'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: hoe
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '3.15'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '3.15'
|
125
|
+
description: |-
|
126
|
+
[![Build Status](https://secure.travis-ci.org/estately/rets.png?branch=master)](http://travis-ci.org/estately/rets)
|
127
|
+
A pure-ruby library for fetching data from [RETS] servers.
|
128
|
+
|
129
|
+
If you're looking for a slick CLI interface check out [retscli](https://github.com/summera/retscli), which is an awesome tool for exploring metadata or learning about RETS.
|
130
|
+
|
131
|
+
[RETS]: http://www.rets.org
|
132
|
+
email:
|
133
|
+
- opensource@estately.com
|
134
|
+
executables:
|
135
|
+
- rets
|
136
|
+
extensions: []
|
137
|
+
extra_rdoc_files:
|
138
|
+
- CHANGELOG.md
|
139
|
+
- Manifest.txt
|
140
|
+
- README.md
|
141
|
+
files:
|
142
|
+
- CHANGELOG.md
|
143
|
+
- Manifest.txt
|
144
|
+
- README.md
|
145
|
+
- Rakefile
|
146
|
+
- bin/rets
|
147
|
+
- example/connect.rb
|
148
|
+
- example/get-photos.rb
|
149
|
+
- example/get-property.rb
|
150
|
+
- lib/rets.rb
|
151
|
+
- lib/rets/client.rb
|
152
|
+
- lib/rets/client_progress_reporter.rb
|
153
|
+
- lib/rets/http_client.rb
|
154
|
+
- lib/rets/locking_http_client.rb
|
155
|
+
- lib/rets/measuring_http_client.rb
|
156
|
+
- lib/rets/metadata.rb
|
157
|
+
- lib/rets/metadata/caching.rb
|
158
|
+
- lib/rets/metadata/containers.rb
|
159
|
+
- lib/rets/metadata/file_cache.rb
|
160
|
+
- lib/rets/metadata/json_serializer.rb
|
161
|
+
- lib/rets/metadata/lookup_table.rb
|
162
|
+
- lib/rets/metadata/lookup_type.rb
|
163
|
+
- lib/rets/metadata/marshal_serializer.rb
|
164
|
+
- lib/rets/metadata/multi_lookup_table.rb
|
165
|
+
- lib/rets/metadata/null_cache.rb
|
166
|
+
- lib/rets/metadata/resource.rb
|
167
|
+
- lib/rets/metadata/rets_class.rb
|
168
|
+
- lib/rets/metadata/rets_object.rb
|
169
|
+
- lib/rets/metadata/root.rb
|
170
|
+
- lib/rets/metadata/table.rb
|
171
|
+
- lib/rets/metadata/table_factory.rb
|
172
|
+
- lib/rets/metadata/yaml_serializer.rb
|
173
|
+
- lib/rets/parser/compact.rb
|
174
|
+
- lib/rets/parser/error_checker.rb
|
175
|
+
- lib/rets/parser/multipart.rb
|
176
|
+
- test/fixtures.rb
|
177
|
+
- test/helper.rb
|
178
|
+
- test/test_caching.rb
|
179
|
+
- test/test_client.rb
|
180
|
+
- test/test_error_checker.rb
|
181
|
+
- test/test_file_cache.rb
|
182
|
+
- test/test_http_client.rb
|
183
|
+
- test/test_json_serializer.rb
|
184
|
+
- test/test_locking_http_client.rb
|
185
|
+
- test/test_marshal_serializer.rb
|
186
|
+
- test/test_metadata.rb
|
187
|
+
- test/test_metadata_class.rb
|
188
|
+
- test/test_metadata_lookup_table.rb
|
189
|
+
- test/test_metadata_lookup_type.rb
|
190
|
+
- test/test_metadata_multi_lookup_table.rb
|
191
|
+
- test/test_metadata_object.rb
|
192
|
+
- test/test_metadata_resource.rb
|
193
|
+
- test/test_metadata_root.rb
|
194
|
+
- test/test_metadata_table.rb
|
195
|
+
- test/test_metadata_table_factory.rb
|
196
|
+
- test/test_parser_compact.rb
|
197
|
+
- test/test_parser_multipart.rb
|
198
|
+
- test/test_yaml_serializer.rb
|
199
|
+
- test/vcr_cassettes/unauthorized_response.yml
|
200
|
+
homepage: http://github.com/mlessard/rets
|
201
|
+
licenses:
|
202
|
+
- MIT
|
203
|
+
metadata: {}
|
204
|
+
post_install_message:
|
205
|
+
rdoc_options:
|
206
|
+
- "--main"
|
207
|
+
- README.md
|
208
|
+
require_paths:
|
209
|
+
- lib
|
210
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
211
|
+
requirements:
|
212
|
+
- - ">="
|
213
|
+
- !ruby/object:Gem::Version
|
214
|
+
version: '0'
|
215
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
216
|
+
requirements:
|
217
|
+
- - ">="
|
218
|
+
- !ruby/object:Gem::Version
|
219
|
+
version: '0'
|
220
|
+
requirements: []
|
221
|
+
rubyforge_project:
|
222
|
+
rubygems_version: 2.4.5
|
223
|
+
signing_key:
|
224
|
+
specification_version: 4
|
225
|
+
summary: "[![Build Status](https://secure.travis-ci.org/estately/rets.png?branch=master)](http://travis-ci.org/estately/rets)
|
226
|
+
A pure-ruby library for fetching data from [RETS] servers"
|
227
|
+
test_files: []
|