net-sftp 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. data/doc/LICENSE-BSD +27 -0
  2. data/doc/LICENSE-GPL +280 -0
  3. data/doc/LICENSE-RUBY +56 -0
  4. data/examples/asynchronous.rb +57 -0
  5. data/examples/ssh-service.rb +31 -0
  6. data/examples/synchronous.rb +120 -0
  7. data/lib/net/sftp.rb +39 -0
  8. data/lib/net/sftp/errors.rb +25 -0
  9. data/lib/net/sftp/operations/abstract.rb +103 -0
  10. data/lib/net/sftp/operations/close.rb +31 -0
  11. data/lib/net/sftp/operations/errors.rb +76 -0
  12. data/lib/net/sftp/operations/fsetstat.rb +36 -0
  13. data/lib/net/sftp/operations/fstat.rb +32 -0
  14. data/lib/net/sftp/operations/lstat.rb +31 -0
  15. data/lib/net/sftp/operations/mkdir.rb +33 -0
  16. data/lib/net/sftp/operations/open.rb +32 -0
  17. data/lib/net/sftp/operations/opendir.rb +32 -0
  18. data/lib/net/sftp/operations/read.rb +84 -0
  19. data/lib/net/sftp/operations/readdir.rb +55 -0
  20. data/lib/net/sftp/operations/realpath.rb +37 -0
  21. data/lib/net/sftp/operations/remove.rb +31 -0
  22. data/lib/net/sftp/operations/rename.rb +32 -0
  23. data/lib/net/sftp/operations/rmdir.rb +31 -0
  24. data/lib/net/sftp/operations/services.rb +42 -0
  25. data/lib/net/sftp/operations/setstat.rb +33 -0
  26. data/lib/net/sftp/operations/stat.rb +31 -0
  27. data/lib/net/sftp/operations/write.rb +63 -0
  28. data/lib/net/sftp/protocol/01/attributes.rb +146 -0
  29. data/lib/net/sftp/protocol/01/impl.rb +251 -0
  30. data/lib/net/sftp/protocol/01/packet-assistant.rb +82 -0
  31. data/lib/net/sftp/protocol/01/services.rb +47 -0
  32. data/lib/net/sftp/protocol/02/impl.rb +39 -0
  33. data/lib/net/sftp/protocol/02/packet-assistant.rb +32 -0
  34. data/lib/net/sftp/protocol/02/services.rb +44 -0
  35. data/lib/net/sftp/protocol/03/impl.rb +42 -0
  36. data/lib/net/sftp/protocol/03/packet-assistant.rb +35 -0
  37. data/lib/net/sftp/protocol/03/services.rb +44 -0
  38. data/lib/net/sftp/protocol/04/attributes.rb +227 -0
  39. data/lib/net/sftp/protocol/04/impl.rb +134 -0
  40. data/lib/net/sftp/protocol/04/packet-assistant.rb +51 -0
  41. data/lib/net/sftp/protocol/04/services.rb +44 -0
  42. data/lib/net/sftp/protocol/05/services.rb +44 -0
  43. data/lib/net/sftp/protocol/constants.rb +60 -0
  44. data/lib/net/sftp/protocol/driver.rb +232 -0
  45. data/lib/net/sftp/protocol/packet-assistant.rb +84 -0
  46. data/lib/net/sftp/protocol/services.rb +55 -0
  47. data/lib/net/sftp/session.rb +215 -0
  48. data/lib/net/sftp/version.rb +25 -0
  49. data/test/ALL-TESTS.rb +21 -0
  50. data/test/operations/tc_abstract.rb +124 -0
  51. data/test/operations/tc_close.rb +40 -0
  52. data/test/operations/tc_fsetstat.rb +48 -0
  53. data/test/operations/tc_fstat.rb +40 -0
  54. data/test/operations/tc_lstat.rb +40 -0
  55. data/test/operations/tc_mkdir.rb +48 -0
  56. data/test/operations/tc_open.rb +42 -0
  57. data/test/operations/tc_opendir.rb +40 -0
  58. data/test/operations/tc_read.rb +103 -0
  59. data/test/operations/tc_readdir.rb +88 -0
  60. data/test/operations/tc_realpath.rb +54 -0
  61. data/test/operations/tc_remove.rb +40 -0
  62. data/test/operations/tc_rmdir.rb +40 -0
  63. data/test/operations/tc_setstat.rb +48 -0
  64. data/test/operations/tc_stat.rb +40 -0
  65. data/test/operations/tc_write.rb +91 -0
  66. data/test/protocol/01/tc_attributes.rb +138 -0
  67. data/test/protocol/01/tc_impl.rb +294 -0
  68. data/test/protocol/01/tc_packet_assistant.rb +81 -0
  69. data/test/protocol/02/tc_impl.rb +41 -0
  70. data/test/protocol/02/tc_packet_assistant.rb +31 -0
  71. data/test/protocol/03/tc_impl.rb +48 -0
  72. data/test/protocol/03/tc_packet_assistant.rb +34 -0
  73. data/test/protocol/04/tc_attributes.rb +174 -0
  74. data/test/protocol/04/tc_impl.rb +102 -0
  75. data/test/protocol/04/tc_packet_assistant.rb +41 -0
  76. data/test/protocol/tc_driver.rb +219 -0
  77. metadata +137 -0
@@ -0,0 +1,33 @@
1
+ #--
2
+ # =============================================================================
3
+ # Copyright (c) 2004, Jamis Buck (jgb3@email.byu.edu)
4
+ # All rights reserved.
5
+ #
6
+ # This source file is distributed as part of the Net::SFTP Secure FTP Client
7
+ # library for Ruby. This file (and the library as a whole) may be used only as
8
+ # allowed by either the BSD license, or the Ruby license (or, by association
9
+ # with the Ruby license, the GPL). See the "doc" subdirectory of the Net::SFTP
10
+ # distribution for the texts of these licenses.
11
+ # -----------------------------------------------------------------------------
12
+ # net-sftp website: http://net-ssh.rubyforge.org/sftp
13
+ # project website : http://rubyforge.org/projects/net-ssh
14
+ # =============================================================================
15
+ #++
16
+
17
+ require 'net/sftp/operations/abstract'
18
+
19
+ module Net ; module SFTP ; module Operations
20
+
21
+ # Implements the +setstat+ operation.
22
+ class Setstat < Abstract
23
+
24
+ # Perform the operation. The +hash+ parameter is a hash of attributes that
25
+ # should be set on the file or directory indicated by the +path+.
26
+ def perform( path, hash )
27
+ attrs = @driver.attr_factory.from_hash( hash )
28
+ @driver.setstat( nil, path, attrs )
29
+ end
30
+
31
+ end
32
+
33
+ end ; end ; end
@@ -0,0 +1,31 @@
1
+ #--
2
+ # =============================================================================
3
+ # Copyright (c) 2004, Jamis Buck (jgb3@email.byu.edu)
4
+ # All rights reserved.
5
+ #
6
+ # This source file is distributed as part of the Net::SFTP Secure FTP Client
7
+ # library for Ruby. This file (and the library as a whole) may be used only as
8
+ # allowed by either the BSD license, or the Ruby license (or, by association
9
+ # with the Ruby license, the GPL). See the "doc" subdirectory of the Net::SFTP
10
+ # distribution for the texts of these licenses.
11
+ # -----------------------------------------------------------------------------
12
+ # net-sftp website: http://net-ssh.rubyforge.org/sftp
13
+ # project website : http://rubyforge.org/projects/net-ssh
14
+ # =============================================================================
15
+ #++
16
+
17
+ require 'net/sftp/operations/abstract'
18
+
19
+ module Net ; module SFTP ; module Operations
20
+
21
+ # Implements the +stat+ operation.
22
+ class Stat < Abstract
23
+
24
+ # Perform the operation.
25
+ def perform( path )
26
+ @driver.stat( nil, path )
27
+ end
28
+
29
+ end
30
+
31
+ end ; end ; end
@@ -0,0 +1,63 @@
1
+ #--
2
+ # =============================================================================
3
+ # Copyright (c) 2004, Jamis Buck (jgb3@email.byu.edu)
4
+ # All rights reserved.
5
+ #
6
+ # This source file is distributed as part of the Net::SFTP Secure FTP Client
7
+ # library for Ruby. This file (and the library as a whole) may be used only as
8
+ # allowed by either the BSD license, or the Ruby license (or, by association
9
+ # with the Ruby license, the GPL). See the "doc" subdirectory of the Net::SFTP
10
+ # distribution for the texts of these licenses.
11
+ # -----------------------------------------------------------------------------
12
+ # net-sftp website: http://net-ssh.rubyforge.org/sftp
13
+ # project website : http://rubyforge.org/projects/net-ssh
14
+ # =============================================================================
15
+ #++
16
+
17
+ require 'net/sftp/operations/abstract'
18
+
19
+ module Net ; module SFTP ; module Operations
20
+
21
+ # Implements the +write+ operation. Handles, automatically, the looping
22
+ # necessary to write a large data set.
23
+ class Write < Abstract
24
+
25
+ # The maximum size of data that will be written at one time.
26
+ CHUNK_SIZE = 64 * 1024
27
+
28
+ # Perform the operation. Only CHUNK_SIZE portions of the +data+ parameter
29
+ # will be written at a time, with subsequent chunks being writteni
30
+ # automatically when prior chunks complete.
31
+ def perform( handle, data, offset=0 )
32
+ @handle = handle
33
+ @offset = offset
34
+ @data = data
35
+ @pos = 0
36
+
37
+ @driver.write( nil, handle, offset, data[0,CHUNK_SIZE] )
38
+ end
39
+
40
+ # Invoked when the server sends a status packet. If the status is FX_OK,
41
+ # then the callback is invoked (if all data has been written), or the
42
+ # next chunk is written to the server (if more data remains). Other
43
+ # status codes are handled by the superclass.
44
+ def do_status( code, message, language )
45
+ if code == FX_OK
46
+ @log.debug "[#{@id}] chunk written" if @log.debug?
47
+ @pos += CHUNK_SIZE
48
+
49
+ if @pos > @data.length
50
+ @callback[ OK ]
51
+ return
52
+ end
53
+
54
+ @driver.write @id, @handle, @offset + @pos, @data[@pos,CHUNK_SIZE]
55
+ @session.register @id, self
56
+ else
57
+ super
58
+ end
59
+ end
60
+
61
+ end
62
+
63
+ end ; end ; end
@@ -0,0 +1,146 @@
1
+ #--
2
+ # =============================================================================
3
+ # Copyright (c) 2004, Jamis Buck (jgb3@email.byu.edu)
4
+ # All rights reserved.
5
+ #
6
+ # This source file is distributed as part of the Net::SFTP Secure FTP Client
7
+ # library for Ruby. This file (and the library as a whole) may be used only as
8
+ # allowed by either the BSD license, or the Ruby license (or, by association
9
+ # with the Ruby license, the GPL). See the "doc" subdirectory of the Net::SFTP
10
+ # distribution for the texts of these licenses.
11
+ # -----------------------------------------------------------------------------
12
+ # net-sftp website: http://net-ssh.rubyforge.org/sftp
13
+ # project website : http://rubyforge.org/projects/net-ssh
14
+ # =============================================================================
15
+ #++
16
+
17
+ module Net ; module SFTP ; module Protocol ; module V_01
18
+
19
+ # A class representing the attributes of a file or directory on the server.
20
+ # It may be used to specify new attributes, or to query existing attributes.
21
+ class Attributes
22
+
23
+ F_SIZE = 0x00000001
24
+ F_UIDGID = 0x00000002
25
+ F_PERMISSIONS = 0x00000004
26
+ F_ACMODTIME = 0x00000008
27
+ F_EXTENDED = 0x80000000
28
+
29
+ attr_accessor :size
30
+ attr_accessor :uid
31
+ attr_accessor :gid
32
+ attr_accessor :permissions
33
+ attr_accessor :atime
34
+ attr_accessor :mtime
35
+ attr_accessor :extended
36
+
37
+ # An initialization routine, to grant the class (factory) access to a
38
+ # buffer factory. The buffer factory is used by the class' #to_s
39
+ # method to encode the object's attributes.
40
+ #
41
+ # This returns +self+, making it suitable for chaining.
42
+ def self.init( buffers )
43
+ @buffers = buffers
44
+ self
45
+ end
46
+
47
+ # Returns the buffer factory for this class.
48
+ def self.buffers
49
+ @buffers
50
+ end
51
+
52
+ # Returns the buffer factory for the object's class.
53
+ def buffers
54
+ self.class.buffers
55
+ end
56
+
57
+ # Create a new, empty Attributes object.
58
+ def self.empty
59
+ new
60
+ end
61
+
62
+ # Create a new Attributes object, initialized from the given buffer.
63
+ def self.from_buffer( buffer )
64
+ flags = buffer.read_long
65
+
66
+ size = buffer.read_int64 if ( flags & F_SIZE ) != 0
67
+ uid = buffer.read_long if ( flags & F_UIDGID ) != 0
68
+ gid = buffer.read_long if ( flags & F_UIDGID ) != 0
69
+ permissions = buffer.read_long if ( flags & F_PERMISSIONS ) != 0
70
+ atime = buffer.read_long if ( flags & F_ACMODTIME ) != 0
71
+ mtime = buffer.read_long if ( flags & F_ACMODTIME ) != 0
72
+
73
+ if ( flags & F_EXTENDED ) != 0
74
+ extended = Hash.new
75
+ buffer.read_long.times do
76
+ extended[ buffer.read_string ] = buffer.read_string
77
+ end
78
+ end
79
+
80
+ new( size, uid, gid, permissions, atime, mtime, extended )
81
+ end
82
+
83
+ # Create a new attributes object, initialized from the given hash. The
84
+ # :owner and :group attributes are treated specially; they are not actually
85
+ # supported by this version of the protocol, but are instead converted
86
+ # by this method to their corresponding id numbers, and assigned
87
+ # (respectively) to :uid and :gid.
88
+ def self.from_hash( hash )
89
+ if hash[:owner]
90
+ require 'etc'
91
+ hash[:uid] = Etc.getpwnam( hash[:owner] ).uid
92
+ end
93
+
94
+ if hash[:group]
95
+ require 'etc'
96
+ hash[:gid] = Etc.getgrnam( hash[:group] ).gid
97
+ end
98
+
99
+ new hash[:size], hash[:uid], hash[:gid], hash[:permissions],
100
+ hash[:atime], hash[:mtime], hash[:extended]
101
+ end
102
+
103
+ private_class_method :new
104
+
105
+ # Create a new Attributes with the given attributes.
106
+ def initialize( size=nil, uid=nil, gid=nil, permissions=nil,
107
+ atime=nil, mtime=nil, extended=nil )
108
+ # begin
109
+ @size = size
110
+ @uid = uid
111
+ @gid = gid
112
+ @permissions = permissions
113
+ @atime = atime
114
+ @mtime = mtime
115
+ @extended = extended
116
+ end
117
+
118
+ # Convert the object to a string suitable for passing in an SFTP
119
+ # packet.
120
+ def to_s
121
+ flags = 0
122
+
123
+ flags |= F_SIZE if @size
124
+ flags |= F_UIDGID if @uid && @gid
125
+ flags |= F_PERMISSIONS if @permissions
126
+ flags |= F_ACMODTIME if @atime && @mtime
127
+ flags |= F_EXTENDED if @extended
128
+
129
+ buffer = buffers.writer
130
+ buffer.write_long flags
131
+ buffer.write_int64 @size if @size
132
+ buffer.write_long @uid, @gid if @uid && @gid
133
+ buffer.write_long @permissions if @permissions
134
+ buffer.write_long @atime, @mtime if @atime && @mtime
135
+
136
+ if @extended
137
+ buffer.write_long @extended.size
138
+ @extended.each { |k,v| buffer.write_string k, v }
139
+ end
140
+
141
+ buffer.to_s
142
+ end
143
+
144
+ end
145
+
146
+ end ; end ; end ; end
@@ -0,0 +1,251 @@
1
+ #--
2
+ # =============================================================================
3
+ # Copyright (c) 2004, Jamis Buck (jgb3@email.byu.edu)
4
+ # All rights reserved.
5
+ #
6
+ # This source file is distributed as part of the Net::SFTP Secure FTP Client
7
+ # library for Ruby. This file (and the library as a whole) may be used only as
8
+ # allowed by either the BSD license, or the Ruby license (or, by association
9
+ # with the Ruby license, the GPL). See the "doc" subdirectory of the Net::SFTP
10
+ # distribution for the texts of these licenses.
11
+ # -----------------------------------------------------------------------------
12
+ # net-sftp website: http://net-ssh.rubyforge.org/sftp
13
+ # project website : http://rubyforge.org/projects/net-ssh
14
+ # =============================================================================
15
+ #++
16
+
17
+ require 'net/sftp/errors'
18
+ require 'net/sftp/protocol/constants'
19
+
20
+ module Net ; module SFTP ; module Protocol ; module V_01
21
+
22
+ # The implementing class for version 1 of the SFTP protocol. It
23
+ # implements the various operations and callbacks available to this
24
+ # level of the protocol. Other protocol versions will typically
25
+ # extend this class, adding (or modifying) methods as needed to bring
26
+ # the implementation into sync with the needed version.
27
+ class Impl
28
+ include Constants
29
+
30
+ Name = Struct.new( :filename, :longname, :attributes )
31
+
32
+ # The protocol driver that drives this dispatcher.
33
+ attr_reader :driver
34
+
35
+ # The attribute-factory used by this dispatcher.
36
+ attr_reader :attr_factory
37
+
38
+ # The protocol extensions specified when the protocol version was
39
+ # negotiated.
40
+ attr_accessor :extensions
41
+
42
+ # Create a new instance using the given protocol driver, packet
43
+ # assistant, and attributes factory.
44
+ def initialize( buffers, driver, assistant, attr_factory )
45
+ @buffers = buffers
46
+ @driver = driver
47
+ @assistant = assistant
48
+ @attr_factory = attr_factory
49
+ @on_status = nil
50
+ @on_handle = nil
51
+ @on_data = nil
52
+ @on_name = nil
53
+ @on_attrs = nil
54
+ end
55
+
56
+ # A helper method for defining new operations supported by this
57
+ # implementation. This will create one method for each named operation.
58
+ # By default, the method simply formats the packet (using the packet
59
+ # assistant), and then sends the data via the driver. It will then
60
+ # return the request id used for this operation.
61
+ def self.operation( *names )
62
+ names.each do |name|
63
+ const = "FXP_#{name.to_s.upcase}"
64
+ class_eval <<-EOF, __FILE__, __LINE__+1
65
+ def #{name}( id, *args )
66
+ id, packet = @assistant.#{name}( id, *args )
67
+ @driver.send_data #{const}, packet
68
+ id
69
+ end
70
+ EOF
71
+ end
72
+ end
73
+
74
+ # A helper method for registering new callbacks. Each callback will
75
+ # cause three new methods to be created, <tt>on_<em>name</em></tt>,
76
+ # <tt>has_on_<em>name</em>?</tt>, and <tt>call_on_<em>name</em></tt>.
77
+ # The <tt>on_<em>name</em></tt> method may be used to register a block
78
+ # for the corresponding callback.
79
+ def self.callback( *names )
80
+ names.each do |name|
81
+ class_eval <<-EOF, __FILE__, __LINE__+1
82
+ def on_#{name}( &block )
83
+ @on_#{name} = block
84
+ end
85
+
86
+ def has_on_#{name}?
87
+ not @on_#{name}.nil?
88
+ end
89
+
90
+ def call_on_#{name}( *args )
91
+ return unless @on_#{name}
92
+ @on_#{name}.call( *args )
93
+ end
94
+
95
+ public :on_#{name}
96
+ protected :has_on_#{name}?, :call_on_#{name}
97
+ EOF
98
+ end
99
+ end
100
+
101
+ operation :open,
102
+ :close,
103
+ :read,
104
+ :write,
105
+ :opendir,
106
+ :readdir,
107
+ :remove,
108
+ :stat,
109
+ :lstat,
110
+ :fstat,
111
+ :setstat,
112
+ :fsetstat,
113
+ :mkdir,
114
+ :rmdir,
115
+ :realpath
116
+
117
+ callback :status,
118
+ :handle,
119
+ :data,
120
+ :name,
121
+ :attrs
122
+
123
+ alias :open_raw :open
124
+ alias :stat_raw :stat
125
+ alias :lstat_raw :lstat
126
+ alias :fstat_raw :fstat
127
+
128
+ alias :close_handle :close
129
+
130
+ F_READ = 0x00000001
131
+ F_WRITE = 0x00000002
132
+ F_APPEND = 0x00000004
133
+ F_CREAT = 0x00000008
134
+ F_TRUNC = 0x00000010
135
+ F_EXCL = 0x00000020
136
+
137
+ # The open operation is special, since it protects the caller from the
138
+ # specific flags and options required by SFTP. Instead, the caller simply
139
+ # specifies a combination of IO flags, and an appropriate posix mode, and
140
+ # they are translated into the correct SFTP flags.
141
+ def open( id, path, flags, mode=0660 )
142
+ sftp_flags = case
143
+ when ( flags & IO::WRONLY ) != 0 then F_WRITE
144
+ when ( flags & IO::RDWR ) != 0 then F_READ | F_WRITE
145
+ when ( flags & IO::APPEND ) != 0 then F_APPEND
146
+ else F_READ
147
+ end
148
+
149
+ sftp_flags |= F_CREAT if ( flags & IO::CREAT ) != 0
150
+ sftp_flags |= F_TRUNC if ( flags & IO::TRUNC ) != 0
151
+ sftp_flags |= F_EXCL if ( flags & IO::EXCL ) != 0
152
+
153
+ attributes = @attr_factory.empty
154
+ attributes.permissions = mode
155
+
156
+ open_raw id, path, sftp_flags, attributes
157
+ end
158
+
159
+ # The stat operation is special, since later versions of the protocol add
160
+ # support for 'flags'. These flags are ignored in this version, but the
161
+ # parameter exists to allow a program written for one version of the
162
+ # protocol to work with later versions.
163
+ def stat( id, filename, flags=nil )
164
+ stat_raw id, filename
165
+ end
166
+
167
+ # The lstat operation is special, since later versions of the protocol add
168
+ # support for 'flags'. These flags are ignored in this version, but the
169
+ # parameter exists to allow a program written for one version of the
170
+ # protocol to work with later versions.
171
+ def lstat( id, filename, flags=nil )
172
+ lstat_raw id, filename
173
+ end
174
+
175
+ # The fstat operation is special, since later versions of the protocol add
176
+ # support for 'flags'. These flags are ignored in this version, but the
177
+ # parameter exists to allow a program written for one version of the
178
+ # protocol to work with later versions.
179
+ def fstat( id, handle, flags=nil )
180
+ fstat_raw id, handle
181
+ end
182
+
183
+ # Dispatches the given packet type to the appropriate handler method.
184
+ # If a new protocol version adds a new packet type, it should override
185
+ # this method, performing its own checking first, followed by calling
186
+ # +super+.
187
+ def dispatch( channel, type, content )
188
+ case type
189
+ when FXP_STATUS then do_status( channel, content )
190
+ when FXP_HANDLE then do_handle( channel, content )
191
+ when FXP_DATA then do_data( channel, content )
192
+ when FXP_NAME then do_name( channel, content )
193
+ when FXP_ATTRS then do_attrs( channel, content )
194
+ else
195
+ raise Net::SFTP::Exception,
196
+ "unsupported SFTP packet type #{type} (#{content.to_s.inspect})"
197
+ end
198
+ end
199
+
200
+ # Used internally to handle +status+ packets. The +on_status+ callback is
201
+ # invoked, if registered, with the driver, id, and code.
202
+ def do_status( channel, content )
203
+ return unless has_on_status?
204
+ id = content.read_long
205
+ code = content.read_long
206
+ call_on_status( driver, id, code, nil, nil )
207
+ end
208
+
209
+ # Used internally to handle +handle+ packets. The +on_handle+ callback is
210
+ # invoked, if registered, with the driver, id, and handle.
211
+ def do_handle( channel, content )
212
+ return unless has_on_handle?
213
+ id = content.read_long
214
+ handle = content.read_string
215
+ call_on_handle( driver, id, handle )
216
+ end
217
+
218
+ # Used internally to handle +data+ packets. The +on_data+ callback is
219
+ # invoked, if registered, with the driver, id, and data (as a buffer).
220
+ def do_data( channel, content )
221
+ return unless has_on_data?
222
+ id = content.read_long
223
+ data = content.read_string
224
+ call_on_data( driver, id, data )
225
+ end
226
+
227
+ # Used internally to handle +name+ packets. The +on_name+ callback is
228
+ # invoked, if registered, with the driver, id, and array of items.
229
+ def do_name( channel, content )
230
+ return unless has_on_name?
231
+ id = content.read_long
232
+ items = []
233
+ content.read_long.times do
234
+ items.push( Name.new( content.read_string, content.read_string,
235
+ @attr_factory.from_buffer( content ) ) )
236
+ end
237
+ call_on_name( driver, id, items )
238
+ end
239
+
240
+ # Used internally to handle +attrs+ packets. The +on_attrs+ callback is
241
+ # invoked, if registered, with the driver, id, and attribute object.
242
+ def do_attrs( channel, content )
243
+ return unless has_on_attrs?
244
+ id = content.read_long
245
+ attrs = @attr_factory.from_buffer( content )
246
+ call_on_attrs( driver, id, attrs )
247
+ end
248
+
249
+ end
250
+
251
+ end ; end ; end ; end