rgadu 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|