Class: RubyTorrent::MetaInfoInfo

Inherits:
Object
  • Object
show all
Defined in:
lib/rubytorrent/metainfo.rb

Instance Method Summary collapse

Constructor Details

#initialize(dict = nil) ⇒ MetaInfoInfo

Returns a new instance of MetaInfoInfo.



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/rubytorrent/metainfo.rb', line 57

def initialize(dict=nil)
  @s = TypedStruct.new do |s|
    s.field :length => Integer, :md5sum => String, :name => String,
            :piece_length => Integer, :pieces => String,
            :files => MetaInfoInfoFile, :sha1 => String
    s.label :piece_length => "piece length"
    s.required :name, :piece_length, :pieces
    s.array :files
    s.coerce :files => lambda { |x| x.map { |y| MetaInfoInfoFile.new(y) } }
  end

  @dict = dict
  unless dict.nil?
    @s.parse dict
    check
    if dict["sha1"]
      ## this seems to always be off. don't know how it's supposed
      ## to be calculated, so fuck it.
#        puts "we have #{sha1.inspect}, they have #{dict['sha1'].inspect}"
#        rt_warning "info hash SHA1 mismatch" unless dict["sha1"] == sha1
#        raise MetaInfoFormatError, "info hash SHA1 mismatch" unless dict["sha1"] == sha1
    end
  end
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(meth, *args) ⇒ Object



127
128
129
# File 'lib/rubytorrent/metainfo.rb', line 127

def method_missing(meth, *args)
  @s.send(meth, *args)
end

Instance Method Details

#checkObject



82
83
84
85
86
87
88
89
90
91
92
# File 'lib/rubytorrent/metainfo.rb', line 82

def check
  raise MetaInfoFormatError, "invalid file length" unless @s.length.nil? || @s.length >= 0
  raise MetaInfoFormatError, "one (and only one) of 'length' (single-file torrent) or 'files' (multi-file torrent) must be specified" if (@s.length.nil? && @s.files.nil?) || (!@s.length.nil? && !@s.files.nil?)
  if single?
    length = @s.length
  else
    length = @s.files.inject(0) { |s, x| s + x.length }
  end
  raise MetaInfoFormatError, "invalid metainfo file: length #{length} > (#{@s.pieces.length / 20} pieces * #{@s.piece_length})" unless length <= (@s.pieces.length / 20) * @s.piece_length
  raise MetaInfoFormatError, "invalid metainfo file: pieces length = #{@s.pieces.length} not a multiple of 20" unless (@s.pieces.length % 20) == 0
end

#multiple?Boolean

Returns:

  • (Boolean)


111
112
113
# File 'lib/rubytorrent/metainfo.rb', line 111

def multiple?
  length.nil?
end

#num_piecesObject



123
124
125
# File 'lib/rubytorrent/metainfo.rb', line 123

def num_pieces
  pieces.length / 20
end

#sha1Object



99
100
101
102
103
104
105
# File 'lib/rubytorrent/metainfo.rb', line 99

def sha1
  if @s.dirty
    @sha1 = Digest::SHA1.digest(self.to_bencoding)
    @s.dirty = false
  end
  @sha1
end

#single?Boolean

Returns:

  • (Boolean)


107
108
109
# File 'lib/rubytorrent/metainfo.rb', line 107

def single?
  !length.nil?
end

#to_bencodingObject



94
95
96
97
# File 'lib/rubytorrent/metainfo.rb', line 94

def to_bencoding
  check
  (@dict || @s).to_bencoding
end

#total_lengthObject



115
116
117
118
119
120
121
# File 'lib/rubytorrent/metainfo.rb', line 115

def total_length
  if single?
    length
  else
    files.inject(0) { |a, f| a + f.length }
  end
end