Class: Metalink4File

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

Overview

Describes the files listed in the Metalink 4 file

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(opts = {}) ⇒ Metalink4File

Options: local_path, copyright, description, identity, language, logo, os, urls, publisher_name, publisher_url, signature, version, piece_size, piece_count



150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
# File 'lib/metalink4.rb', line 150

def initialize(opts = {})
  opts = opts.inject({}){ |r, (k,v)| r[k.to_sym] = v; r }
  
  self.language = []
  self.os = []
  

  self.local_path = opts.fetch(:local_path, nil)
  self.copyright = opts.fetch(:copyright, nil)
  self.description = opts.fetch(:description, nil)
  self.identity = opts.fetch(:identity, nil)
  case opts.fetch(:language, nil)
  when Array
      self.language = opts.fetch(:language, nil)
  when String
      self.language = [opts.fetch(:language, nil)]
  end
  
  self. = opts.fetch(:logo, nil)
  case opts.fetch(:os, nil)
  when Array
      self.os = opts.fetch(:os, nil)
  when String
      self.os = [opts.fetch(:os, nil)]
  end

  self.urls = []
  opts.fetch(:urls, []).each do |url|
    self.urls << Metalink4FileUrl.new(url)
  end
    
  self.publisher_name = opts.fetch(:publisher_name, nil)
  self.publisher_url = opts.fetch(:publisher_url, nil)
  self.signature = opts.fetch(:signature, nil)
  self.version = opts.fetch(:version, nil)
  
  self.piece_size = opts.fetch(:piece_size, nil) 
  self.piece_count = opts.fetch(:piece_count, nil) 
  
  self.hashes = []
end

Instance Attribute Details

Returns the value of attribute copyright.



131
132
133
# File 'lib/metalink4.rb', line 131

def copyright
  @copyright
end

#descriptionObject

Returns the value of attribute description.



131
132
133
# File 'lib/metalink4.rb', line 131

def description
  @description
end

#hashesObject

Returns the value of attribute hashes.



131
132
133
# File 'lib/metalink4.rb', line 131

def hashes
  @hashes
end

#identityObject

Returns the value of attribute identity.



131
132
133
# File 'lib/metalink4.rb', line 131

def identity
  @identity
end

#languageObject

Returns the value of attribute language.



131
132
133
# File 'lib/metalink4.rb', line 131

def language
  @language
end

#local_pathObject

Returns the value of attribute local_path.



131
132
133
# File 'lib/metalink4.rb', line 131

def local_path
  @local_path
end

#logoObject

Returns the value of attribute logo.



131
132
133
# File 'lib/metalink4.rb', line 131

def 
  @logo
end

#osObject

Returns the value of attribute os.



131
132
133
# File 'lib/metalink4.rb', line 131

def os
  @os
end

#piece_countObject

Returns the value of attribute piece_count.



131
132
133
# File 'lib/metalink4.rb', line 131

def piece_count
  @piece_count
end

#piece_sizeObject

Returns the value of attribute piece_size.



131
132
133
# File 'lib/metalink4.rb', line 131

def piece_size
  @piece_size
end

#publisher_nameObject

Returns the value of attribute publisher_name.



131
132
133
# File 'lib/metalink4.rb', line 131

def publisher_name
  @publisher_name
end

#publisher_urlObject

Returns the value of attribute publisher_url.



131
132
133
# File 'lib/metalink4.rb', line 131

def publisher_url
  @publisher_url
end

#signatureObject

Returns the value of attribute signature.



131
132
133
# File 'lib/metalink4.rb', line 131

def signature
  @signature
end

#sizeObject

Returns the value of attribute size.



131
132
133
# File 'lib/metalink4.rb', line 131

def size
  @size
end

#urlsObject

Returns the value of attribute urls.



131
132
133
# File 'lib/metalink4.rb', line 131

def urls
  @urls
end

#versionObject

Returns the value of attribute version.



131
132
133
# File 'lib/metalink4.rb', line 131

def version
  @version
end

Instance Method Details

#checksum!(path = nil, opts = {}) ⇒ Object

Overwrite any present hashes. If no path is provided, checksum will be attempted of local_file. This might require a Dir.chdir.

There is no protection of what this path can call - please sanitize any input to make sure files outside your project can’t be checksummed.

options: debug - show full path on error dump, piece_size - bytes, integer, OR piece_count - integer

These hashes will be SHA256



298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
# File 'lib/metalink4.rb', line 298

def checksum!(path = nil, opts = {})
  opts = opts.inject({}){ |r, (k,v)| r[k.to_sym] = v; r }

  raise "Path uses differnt extension" if path && File.extname(path) != File.extname(self.local_path)


  if opts[:debug]
   raise ("File '%s' does not exist" % File.expand_path( path ) ) if path && !File.exist?( File.expand_path( path ) )
  else
    raise ("File '%s' does not exist" % path ) if path && !File.exist?( File.expand_path( path ) )
  end
  
  raise "Can not specify both piece_size and piece_count" if opts[:piece_size] && opts[:piece_count]
  raise "piece_size must be an Integer" if opts[:piece_size] && !opts[:piece_size].is_a?(Integer)
  raise "piece_count must be an Integer" if opts[:piece_count] && !opts[:piece_count].is_a?(Integer)

  path ||= self.local_path

  #get filesize
  self.size = File.size( File.expand_path( path ) )

  # Overrides piece_count if set
  # minimum size of 1KB for a piece
  if opts[:piece_size]
    @piece_count = nil
    @piece_size = [opts[:piece_size], 1024].max
  end


  # Overrides piece_size if set
  # This will be a multiple of 1024, and the last file will be slightly smaller
  # this means 1KB is the minimum size for a piece
  if opts[:piece_count]
    @piece_count = opts[:piece_count]
    @piece_size = ((@size / @piece_count) / 1024.0).ceil * 1024 
  end

  self.hashes = []
  self.hashes << Metalink4FileHash.new( hash_value: Digest::SHA256.file( File.expand_path( path ) ).hexdigest, hash_type: "sha-256" )
  if self.piece_size
    i = 0
    (0...@size).step(self.piece_size).each do |offset|
      self.hashes << Metalink4FileHash.new( hash_value: Digest::SHA256.hexdigest(File.read(File.expand_path( path ), self.piece_size, offset)), hash_type: "sha-256", piece: i )
      i += 1
    end
  end
end

#render(builder_metalink, metalink4) ⇒ Object

Fragement call for builder. For internal use.



350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
# File 'lib/metalink4.rb', line 350

def render(builder_metalink, metalink4)

  raise "Local path required" if !@local_path
  #raise ("Local path '%s' does not match any files" % @local_path) if File.exist?(@local_path) || !self.hashes.empty?

  #build up hashes if none were imported
  if self.hashes.empty? && File.exist?(@local_path)
    self.checksum!
  end

  metalink4.file( name: self.local_path ) do |metalink_file|
    metalink_file.copyright( ("\n%s\n" % self.copyright) ) if self.copyright
    metalink_file.description( self.description ) if self.description
    metalink_file.identity( self.identity ) if self.identity 

    self.hashes.select{ |x| x.piece.nil? }.each do |hash|
      metalink_file.hash(hash.hash_value, type: hash.hash_type)
    end
    
    #multiple languages possible
    self.language.each do |language|
      metalink_file.language( language )
    end if self.language

    metalink_file.( self. ) if self.
    
    #multiple operating systems possible
    self.os.each do |os|
      metalink_file.os( os )
    end if self.os
    
    self.urls.each do |file_url|
      file_url.render(
        metalink_file,
        self.local_path
        )
    end if self.urls
    
    metalink_file.pieces(length: self.piece_size, type: self.hashes.select{ |x| x.piece }.first.hash_type) do |pieces|
      self.hashes.select{ |x| x.piece }.sort_by(&:piece).each do |hash|
        metalink_file.hash(hash.hash_value)
      end
    end if self.hashes.any?{ |x| x.piece }
        
    metalink_file.publisher( name: self.publisher_name, url: self.publisher_url.to_s) if self.publisher_name || self.publisher_url

    #what other type is it going to be
    metalink_file.signature( ("\n%s\n" % self.signature), mediatype: "application/pgp-signature" ) if self.signature

    metalink_file.size( self.size ) #SHOULD, file bytesize
    metalink_file.version( self.version ) if self.version
  end
end