rgadu 0.1.0 → 0.1.1
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/lib/gg/dccclient.rb +4 -0
- data/lib/gg/dccserver.rb +27 -10
- data/lib/gg.rb +43 -27
- metadata +3 -3
data/lib/gg/dccclient.rb
CHANGED
@@ -32,6 +32,8 @@ class DCCClient < DCCServer
|
|
32
32
|
@callback[@code] = callback if callback
|
33
33
|
begin
|
34
34
|
send7(@code, @socket, filename, filesize, offset)
|
35
|
+
rescue SystemCallError
|
36
|
+
callback.call(:aborted)
|
35
37
|
ensure
|
36
38
|
@progress.delete(@server_uin)
|
37
39
|
end
|
@@ -41,6 +43,8 @@ class DCCClient < DCCServer
|
|
41
43
|
@callback[@code] = callback if callback
|
42
44
|
begin
|
43
45
|
recv7(@code, @socket, filename, filesize, offset)
|
46
|
+
rescue SystemCallError, RuntimeError
|
47
|
+
callback.call(:aborted) if callback
|
44
48
|
ensure
|
45
49
|
@progress.delete(@server_uin)
|
46
50
|
end
|
data/lib/gg/dccserver.rb
CHANGED
@@ -40,6 +40,8 @@ class DCCServer
|
|
40
40
|
session.write(code)
|
41
41
|
begin
|
42
42
|
send7(code, session, filename, filesize, offset)
|
43
|
+
rescue SystemCallError
|
44
|
+
@callback[code].call(:aborted) if @callback[code]
|
43
45
|
ensure
|
44
46
|
@progress[code]=@callback[code]=nil
|
45
47
|
end
|
@@ -47,6 +49,8 @@ class DCCServer
|
|
47
49
|
session.write(packet_raw)
|
48
50
|
begin
|
49
51
|
recv7(code, session, filename, filesize, offset)
|
52
|
+
rescue SystemCallError, RuntimeError
|
53
|
+
@callback[code].call(:aborted) if @callback[code]
|
50
54
|
ensure
|
51
55
|
@progress[code]=@callback[code]=nil
|
52
56
|
end
|
@@ -62,11 +66,18 @@ class DCCServer
|
|
62
66
|
base=File.basename(filename)
|
63
67
|
alternate=base[0..12].upcase
|
64
68
|
session.write([0x01, 0x03, 0, 0, fileattr, creationlow, creationhigh, accesslow, accesshigh, writelow, writehigh, sizehigh, filesize, 0, 0, base, alternate].pack('LLLLLLLLLLLLLLLa262a14'))
|
65
|
-
|
69
|
+
begin
|
70
|
+
packet_raw = session.read(12) or raise
|
71
|
+
rescue SystemCallError, RuntimeError
|
72
|
+
@callback[client_uin].call(:rejected) if @callback[client_uin]
|
73
|
+
return
|
74
|
+
end
|
66
75
|
type, offset = packet_raw.unpack('LLL')
|
67
76
|
if type==0x06 and offset<filesize
|
68
77
|
begin
|
69
78
|
send(client_uin, session, filename, filesize, offset)
|
79
|
+
rescue SystemCallError
|
80
|
+
@callback[client_uin].call(:aborted) if @callback[client_uin]
|
70
81
|
ensure
|
71
82
|
@progress[client_uin]=@callback[client_uin]=nil
|
72
83
|
end
|
@@ -75,7 +86,7 @@ class DCCServer
|
|
75
86
|
|
76
87
|
def send(client_uin, session, filename, filesize, offset)
|
77
88
|
@progress[client_uin] = bytes = offset
|
78
|
-
file=File.open(filename, '
|
89
|
+
file=File.open(filename, 'rb')
|
79
90
|
file.seek(offset) if offset>0
|
80
91
|
while bytes<filesize and data=file.read(4096)
|
81
92
|
length = data.length
|
@@ -90,6 +101,7 @@ class DCCServer
|
|
90
101
|
@progress[client_uin] = bytes
|
91
102
|
@callback[client_uin].call(bytes) if @callback[client_uin]
|
92
103
|
end
|
104
|
+
file.close
|
93
105
|
end
|
94
106
|
|
95
107
|
def init_recv(session, client_uin)
|
@@ -116,6 +128,8 @@ class DCCServer
|
|
116
128
|
session.write([0x06, offset, 0].pack('LLL')) or return
|
117
129
|
begin
|
118
130
|
recv(client_uin, session, local_filename, filesize, offset)
|
131
|
+
rescue SystemCallError, RuntimeError
|
132
|
+
@callback[client_uin].call(:aborted) if @callback[client_uin]
|
119
133
|
ensure
|
120
134
|
@progress[client_uin]=@callback[client_uin]=nil
|
121
135
|
end
|
@@ -126,19 +140,20 @@ class DCCServer
|
|
126
140
|
|
127
141
|
def recv(client_uin, session, filename, filesize, offset)
|
128
142
|
if offset>0
|
129
|
-
mode='
|
143
|
+
mode='ab'
|
130
144
|
else
|
131
|
-
mode='
|
145
|
+
mode='wb'
|
132
146
|
end
|
133
147
|
file=File.open(filename, mode)
|
134
148
|
@progress[client_uin] = bytes = offset
|
135
|
-
while
|
149
|
+
while bytes < filesize
|
150
|
+
packet_raw=session.read(12) or raise
|
136
151
|
type, length = packet_raw.unpack('LLL')
|
137
152
|
if bytes+length > filesize
|
138
153
|
break
|
139
154
|
end
|
140
155
|
if type==0x03 or type==0x02
|
141
|
-
packet=session.read(length) or
|
156
|
+
packet=session.read(length) or raise
|
142
157
|
file.write(packet)
|
143
158
|
bytes+=length
|
144
159
|
@progress[client_uin] = bytes
|
@@ -152,7 +167,7 @@ class DCCServer
|
|
152
167
|
def send7(code, session, filename, filesize, offset)
|
153
168
|
return unless File.exist?(filename)
|
154
169
|
@progress[code]=bytes=offset
|
155
|
-
file=File.open(filename, '
|
170
|
+
file=File.open(filename, 'rb')
|
156
171
|
file.seek(offset) if offset>0
|
157
172
|
while bytes<filesize and data=file.read(4096)
|
158
173
|
session.write(data) or return
|
@@ -160,17 +175,19 @@ class DCCServer
|
|
160
175
|
@progress[code] = bytes
|
161
176
|
@callback[code].call(bytes) if @callback[code]
|
162
177
|
end
|
178
|
+
file.close
|
163
179
|
end
|
164
180
|
|
165
181
|
def recv7(code, session, filename, filesize, offset)
|
166
182
|
if offset>0
|
167
|
-
mode='
|
183
|
+
mode='ab'
|
168
184
|
else
|
169
|
-
mode='
|
185
|
+
mode='wb'
|
170
186
|
end
|
171
187
|
file=File.open(filename, mode)
|
172
188
|
@progress[code]=bytes=offset
|
173
|
-
while bytes<filesize
|
189
|
+
while bytes<filesize
|
190
|
+
data=session.read(4096) or raise
|
174
191
|
file.write(data)
|
175
192
|
bytes += data.length
|
176
193
|
@progress[code] = bytes
|
data/lib/gg.rb
CHANGED
@@ -36,9 +36,9 @@ class GG
|
|
36
36
|
0x1f => 'LLa8a21a43'}
|
37
37
|
|
38
38
|
=begin rdoc
|
39
|
-
Tworzy nowy obiekt GG i loguje sie na serwerze. Opcjonalnie uruchamia serwer DCC na porcie *dccport
|
39
|
+
Tworzy nowy obiekt GG i loguje sie na serwerze. Opcjonalnie uruchamia serwer DCC na porcie *dccport* i przesy�a serwerowi tablic� z list� kontakt�w.
|
40
40
|
=end
|
41
|
-
def initialize(uin, password, dccport=0, server='217.17.45.146', port=8074)
|
41
|
+
def initialize(uin, password, dccport=0, contacts=nil, server='217.17.45.146', port=8074)
|
42
42
|
@uin=uin
|
43
43
|
@dccport=dccport
|
44
44
|
@socket=TCPSocket.new(server, port)
|
@@ -60,7 +60,11 @@ Tworzy nowy obiekt GG i loguje sie na serwerze. Opcjonalnie uruchamia serwer DCC
|
|
60
60
|
unless type==0x03 or type==0x14
|
61
61
|
raise "Authorization failed"
|
62
62
|
end
|
63
|
-
|
63
|
+
if contacts and contacts.length > 0
|
64
|
+
write(0x10, 'LC'*contacts.length, *(contacts.map {|contact| [contact, 0x03] }.flatten))
|
65
|
+
else
|
66
|
+
write(0x12, '')
|
67
|
+
end
|
64
68
|
@action, @status, @search_reply, @dcc_code, @dcc_action, @dcc_client_action = {}, {}, {}, [], {}, {}
|
65
69
|
@action_thread, @dcc_client, @dcc_client_thread = [], [], []
|
66
70
|
@action[0x0a] = lambda {|sender, seq, time, cl, message| msg_received(sender, seq, time, cl, message) }
|
@@ -71,6 +75,7 @@ Tworzy nowy obiekt GG i loguje sie na serwerze. Opcjonalnie uruchamia serwer DCC
|
|
71
75
|
@action[0x0e] = lambda {|type, seq, response| @search_reply[seq] = response }
|
72
76
|
@action[0x23] = lambda {|type, code| @dcc_code << code }
|
73
77
|
@action[0x21] = lambda {|uin, code, offset, x| @dcc_action[code].call(offset) if @dcc_action[code] }
|
78
|
+
@action[0x22] = lambda {|uin, code, reason| @dcc_action[code].call(-1) if @dcc_action[code] }
|
74
79
|
@action[0x1f] = lambda do |uin, x, code, ip_port, y|
|
75
80
|
if action = @dcc_client_action[code]
|
76
81
|
@dcc_client_action.delete(code)
|
@@ -95,7 +100,7 @@ Tworzy nowy obiekt GG i loguje sie na serwerze. Opcjonalnie uruchamia serwer DCC
|
|
95
100
|
Wysyla wiadomosc *message* do *uin*.
|
96
101
|
=end
|
97
102
|
def msg(uin, message)
|
98
|
-
write(0x0b, 'LLLa*C', uin, rand(2**32),
|
103
|
+
write(0x0b, 'LLLa*C', uin, rand(2**32), 0x08, message, 0)
|
99
104
|
end
|
100
105
|
|
101
106
|
=begin rdoc
|
@@ -177,42 +182,53 @@ Wyszukiwanie w katalogu publicznym. *params* moze byc numerem GG lub tablica aso
|
|
177
182
|
end
|
178
183
|
|
179
184
|
=begin rdoc
|
180
|
-
Wysyla plik *filename* do *uin*. Jesli dolaczono blok kodu, blok ten bedzie wywolywany podczas wysylania pliku. Blok przyjmuje jeden parametr -
|
185
|
+
Wysyla plik *filename* do *uin*. Mo�na poda� hash SHA1 pliku w postaci ci�gu bajt�w, w przeciwnym razie hash jest obliczany w razie potrzeby. Jesli dolaczono blok kodu, blok ten bedzie wywolywany podczas wysylania pliku. Blok przyjmuje jeden parametr - aktualn� pozycj� pliku w bajtach, symbol :rejected je�li po��czenie zosta�o odrzucone lub :aborted w przypadku przerwania transferu. Funkcja w zaleznosci od wersji protokolu DCC zwraca kod transferu lub numer GG odbiorcy.
|
181
186
|
=end
|
182
|
-
def dcc_request(uin, filename, &callback)
|
187
|
+
def dcc_request(uin, filename, hash=nil, &callback)
|
183
188
|
raise "No DCC server" unless @dcc
|
184
189
|
if File.exist?(filename)
|
185
|
-
if @status[uin] and version=@status[uin][:version] and version.to_f >= 7.
|
190
|
+
if @status[uin] and version=@status[uin][:version] and version.to_f >= 7.6
|
186
191
|
write(0x23, 'L', 0x04)
|
187
192
|
sleep 0.1 until code = @dcc_code.shift
|
188
193
|
filesize=File.size(filename)
|
189
|
-
hash
|
194
|
+
unless hash
|
195
|
+
checksum = Digest::SHA1.new
|
196
|
+
file = File.open(filename, 'rb')
|
197
|
+
while chunk = file.read(1048576)
|
198
|
+
checksum << chunk
|
199
|
+
end
|
200
|
+
file.close
|
201
|
+
hash = checksum.digest
|
202
|
+
end
|
190
203
|
write(0x20, 'a8LLLa226a29LLa20', code, @uin, uin, 0x04, File.basename(filename), '', filesize, 0, hash)
|
191
204
|
@dcc_action[code] = lambda do |offset|
|
192
|
-
if
|
193
|
-
|
205
|
+
if offset == -1
|
206
|
+
callback.call(:rejected)
|
194
207
|
else
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
client.
|
206
|
-
|
207
|
-
|
208
|
+
if callback
|
209
|
+
@dcc.add_send_code(code, filename, filesize, offset) {|pos| callback.call(pos) }
|
210
|
+
else
|
211
|
+
@dcc.add_send_code(code, filename, filesize, offset)
|
212
|
+
end
|
213
|
+
write(0x1f, 'LLa8a21a43', uin, 0x01, code, @socket.addr[3]+' '+@dccport.to_s, '')
|
214
|
+
if @socket.addr[3] =~ /^(10\.|172\.16\.|192\.168\.)/
|
215
|
+
@dcc_client_action[code] = lambda do |ip, port|
|
216
|
+
@dcc_client_thread << Thread.new(ip, port, @uin, uin, code, filename, filesize, offset, callback) do |ip, port, client_uin, server_uin, code, filename, filesize, offset, callback|
|
217
|
+
begin
|
218
|
+
client = DCCClient.new(ip, port, client_uin, server_uin, code)
|
219
|
+
@dcc_client << client
|
220
|
+
if callback
|
221
|
+
client.client_send7(filename, filesize, offset) {|pos| callback.call(pos) }
|
222
|
+
else
|
223
|
+
client.client_send7(filename, filesize, offset)
|
224
|
+
end
|
225
|
+
rescue
|
226
|
+
warn "Error: #{$!}"
|
208
227
|
end
|
209
|
-
rescue
|
210
|
-
warn "Error: #{$!}"
|
211
228
|
end
|
212
229
|
end
|
213
230
|
end
|
214
231
|
end
|
215
|
-
|
216
232
|
end
|
217
233
|
code
|
218
234
|
else
|
@@ -362,7 +378,7 @@ Rozlacza sie z serwerem GG, wylacza serwer DCC i zamyka wszystkie polaczenia DCC
|
|
362
378
|
@ping_loop.exit
|
363
379
|
@read_loop.exit
|
364
380
|
@socket.close
|
365
|
-
@dcc.close
|
381
|
+
@dcc.close if @dcc
|
366
382
|
@dcc_client_thread.each {|t| t.exit }
|
367
383
|
end
|
368
384
|
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.11
|
|
3
3
|
specification_version: 1
|
4
4
|
name: rgadu
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.1.
|
7
|
-
date: 2007-08-
|
6
|
+
version: 0.1.1
|
7
|
+
date: 2007-08-22 00:00:00 +02:00
|
8
8
|
summary: A simple pure-Ruby implementation of the Gadu-Gadu protocol.
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -12,7 +12,7 @@ email: bl4@playker.info
|
|
12
12
|
homepage:
|
13
13
|
rubyforge_project:
|
14
14
|
description:
|
15
|
-
autorequire:
|
15
|
+
autorequire:
|
16
16
|
default_executable:
|
17
17
|
bindir: bin
|
18
18
|
has_rdoc: true
|