rgadu 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. data/lib/gg/dccclient.rb +4 -0
  2. data/lib/gg/dccserver.rb +27 -10
  3. data/lib/gg.rb +43 -27
  4. 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
- packet_raw = session.read(12) or return
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, 'r')
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='a'
143
+ mode='ab'
130
144
  else
131
- mode='w'
145
+ mode='wb'
132
146
  end
133
147
  file=File.open(filename, mode)
134
148
  @progress[client_uin] = bytes = offset
135
- while packet_raw=session.read(12)
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 return
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, 'r')
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='a'
183
+ mode='ab'
168
184
  else
169
- mode='w'
185
+ mode='wb'
170
186
  end
171
187
  file=File.open(filename, mode)
172
188
  @progress[code]=bytes=offset
173
- while bytes<filesize and data=session.read(4096)
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
- write(0x12, '')
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), 0x04, message, 0)
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 - aktualna pozycje pliku w bajtach. Funkcja w zaleznosci od wersji protokolu DCC zwraca kod transferu lub numer GG odbiorcy.
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.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=Digest::SHA1.digest(File.read(filename))
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 callback
193
- @dcc.add_send_code(code, filename, filesize, offset) {|pos| callback.call(pos) }
205
+ if offset == -1
206
+ callback.call(:rejected)
194
207
  else
195
- @dcc.add_send_code(code, filename, filesize, offset)
196
- end
197
- write(0x1f, 'LLa8a21a43', uin, 0x01, code, @socket.addr[3]+' '+@dccport.to_s, '')
198
- if @socket.addr[3] =~ /^(10\.|172\.16\.|192\.168\.)/
199
- @dcc_client_action[code] = lambda do |ip, port|
200
- @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|
201
- begin
202
- client = DCCClient.new(ip, port, client_uin, server_uin, code)
203
- @dcc_client << client
204
- if callback
205
- client.client_send7(filename, filesize, offset) {|pos| callback.call(pos) }
206
- else
207
- client.client_send7(filename, filesize, offset)
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.0
7
- date: 2007-08-04 00:00:00 +02:00
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: gg
15
+ autorequire:
16
16
  default_executable:
17
17
  bindir: bin
18
18
  has_rdoc: true