class RMail::Header

Overview

The RMail::Header class supports the creation and manipulation of RFC2822 mail headers.

A mail header is a little bit like a Hash. The fields are keyed by a string field name. It is also a little bit like an Array, since the fields are in a specific order. This class provides many of the methods of both the Hash and Array class. It also includes the Enumerable module.

Terminology

header

The entire header. Each RMail::Header object is one mail header.

field

An element of the header. Fields have a name and a value. For example, the field “Subject: Hi Mom!” has a name of “Subject” and a value of “Hi Mom!”

name

A name of a field. For example: “Subject” or “From”.

value

The value of a field.

Conventions

The header’s fields are stored in a particular order. Methods such as each process the headers in this order.

When field names or values are added to the object they are frozen. This helps prevent accidental modification to what is stored in the object.

Constants

BASE36
MESSAGE_ID_MAXRAND
NAME_VALUE_SCAN_RE
PARAM_SCAN_RE

Attributes

fields[RW]

Public Class Methods

new() click to toggle source

Creates a new empty header object.

# File lib/rmail/header.rb, line 134
def initialize()
  clear()
end

Public Instance Methods

==(other) click to toggle source

Returns true if the two objects have the same number of fields, in the same order, with the same values.

# File lib/rmail/header.rb, line 411
def ==(other)
  return other.kind_of?(self.class) &&
    @fields == other.fields &&
    @mbox_from == other.mbox_from
end
[](name_or_index) click to toggle source

Return the value of the first matching field of a field name, or nil if none found. If passed an Integer, returns the header indexed by the number.

# File lib/rmail/header.rb, line 141
def [](name_or_index)
  if name_or_index.kind_of? Integer
    temp = @fields[name_or_index]
    temp = temp.value unless temp.nil?
  else
    name = Field.name_canonicalize(name_or_index)
    result = detect { |n, v|
      if n.downcase == name then true else false end
    }
    if result.nil? then nil else result[1] end
  end
end
[]=(name, value) click to toggle source

Append a new field with name and value. If you want control of where the field is inserted, see add.

Returns value.

# File lib/rmail/header.rb, line 404
def []=(name, value)
  add(name, value)
  value
end
add(name, value, index = nil, params = nil) click to toggle source

Add a new field with name and value. When index is nil (the default if not specified) the line is appended to the header, otherwise it is inserted at the specified index. E.g. an index of 0 will prepend the header line.

You can pass additional parameters for the header as a hash table params. Every key of the hash will be the name of the parameter, and every key’s value the parameter value.

E.g.

header.add('Content-Type', 'multipart/mixed', nil,
           'boundary' => 'the boundary')

will add this header

Content-Type: multipart/mixed; boundary="the boundary"

Always returns self.

# File lib/rmail/header.rb, line 360
def add(name, value, index = nil, params = nil)
  value = value.to_str
  if params
    value = value.dup
    sep = "; "
    params.each do |n, v|
      value << sep
      value << n.to_s
      value << '='
      v = v.to_s
      if v =~ /^\w+$/
        value << v
      else
        value << '"'
        value << v
        value << '"'
      end
    end
  end
  field = Field.new(name, value)
  index ||= @fields.length
  @fields[index, 0] = field
  self
end
add_message_id(fqdn = nil) click to toggle source

Sets the value of this object’s Message-Id: field to a new random value.

If you don’t supply a fqdn (fully qualified domain name) then one will be randomly generated for you. If a valid address exists in the From: field, its domain will be used as a basis.

Part of the randomness in the header is taken from the header itself, so it is best to call this method after adding other fields to the header – especially those that make it unique (Subject:, To:, Cc:, etc).

# File lib/rmail/header.rb, line 775
def add_message_id(fqdn = nil)

  # If they don't supply a fqdn, we supply one for them.
  #
  # First grab the From: field and see if we can use a domain from
  # there.  If so, use that domain name plus the hash of the From:
  # field's value (this guarantees that bob@example.com and
  # sally@example.com will never have clashes).
  #
  # If there is no From: field, grab the current host name and use
  # some randomness from Ruby's random number generator.  Since
  # Ruby's random number generator is fairly good this will
  # suffice so long as it is seeded corretly.
  #
  # P.S. There is no portable way to get the fully qualified
  # domain name of the current host.  Those truly interested in
  # generating "correct" message-ids should pass it in.  We
  # generate a hopefully random and unique domain name.
  unless fqdn
    unless fqdn = from.domains.first
      require 'socket'
      fqdn = sprintf("%s.invalid", Socket.gethostname)
    end
  else
    raise ArgumentError, "fqdn must have at least one dot" unless
      fqdn.index('.')
  end

  # Hash the header we have so far.
  md5 = Digest::MD5.new
  starting_digest = md5.digest
  @fields.each { |f|
    if f.raw
      md5.update(f.raw)
    else
      md5.update(f.name) if f.name
      md5.update(f.value) if f.value
    end
  }
  if (digest = md5.digest) == starting_digest
    digest = 0
  end

  set('Message-Id', sprintf("<%s.%s.%s.rubymail@%s>",
                            base36(Time.now.to_i),
                            base36(rand(MESSAGE_ID_MAXRAND)),
                            base36(digest),
                            fqdn))
end
add_raw(raw) click to toggle source

Add a new field as a raw string together with a parsed name/value. This method is used mainly by the parser and regular programs should stick to add.

# File lib/rmail/header.rb, line 388
def add_raw(raw)
  @fields << Field.new(raw)
  self
end
address_list_assign(field_name, addresses) click to toggle source

Set a given field to a list of supplied addresses.

The addresses may be a String, RMail::Address, or Array. If a String, it is parsed for valid email addresses and those found are used. If an RMail::Address, the result of RMail::Address#format is used. If an Array, each element of the array must be either a String or RMail::Address and is treated as above.

This method is used to implement many of the convenience methods such as from=, to=, etc.

# File lib/rmail/header.rb, line 874
def address_list_assign(field_name, addresses)
  if addresses.kind_of?(Array)
    value = addresses.collect { |e|
      if e.kind_of?(RMail::Address)
        e.format
      else
        RMail::Address.parse(e.to_str).collect { |a|
          a.format
        }
      end
    }.flatten.join(", ")
    set(field_name, value)
  elsif addresses.kind_of?(RMail::Address)
    set(field_name, addresses.format)
  else
    address_list_assign(field_name,
                        RMail::Address.parse(addresses.to_str))
  end
end
address_list_fetch(field_name) click to toggle source

Retrieve a given field’s value as an RMail::Address::List of RMail::Address objects.

This method is used to implement many of the convenience methods such as from, to, etc.

# File lib/rmail/header.rb, line 847
def address_list_fetch(field_name)
  if values = fetch_all(field_name, nil)
    list = nil
    values.each { |value|
      if list
        list.concat(Address.parse(value))
      else
        list = Address.parse(value)
      end
    }
    if list and !list.empty?
      list
    end
  end or RMail::Address::List.new
end
bcc() click to toggle source

Returns the value of the Bcc: field as an Array of RMail::Address objects.

See address_list_fetch for details on what is returned.

# File lib/rmail/header.rb, line 733
def bcc
  address_list_fetch('bcc')
end
bcc=(addresses) click to toggle source

Sets the Bcc: field to the supplied address or addresses.

See address_list_assign for information on valid values for addresses.

# File lib/rmail/header.rb, line 741
def bcc=(addresses)
  address_list_assign('Bcc', addresses)
end
cc() click to toggle source

Returns the value of the Cc: field as an Array of RMail::Address objects.

See address_list_fetch for details on what is returned.

# File lib/rmail/header.rb, line 717
def cc
  address_list_fetch('cc')
end
cc=(addresses) click to toggle source

Sets the Cc: field to the supplied address or addresses.

See address_list_assign for information on valid values for addresses.

# File lib/rmail/header.rb, line 725
def cc=(addresses)
  address_list_assign('Cc', addresses)
end
clear() click to toggle source

Delete all fields in this object. Returns self.

# File lib/rmail/header.rb, line 177
def clear()
  @fields = []
  @mbox_from = nil
  self
end
clone() click to toggle source

Creates a complete copy of this header object, including any singleton methods and strings. The returned object will be a complete and unrelated duplicate of the original.

Calls superclass method
# File lib/rmail/header.rb, line 169
def clone
  h = super
  h.fields = Marshal::load(Marshal::dump(@fields))
  h.mbox_from = Marshal::load(Marshal::dump(@mbox_from))
  h
end
content_type(default = nil) { || ... } click to toggle source

This returns the full content type of this message converted to lower case.

If there is no content type header, returns the passed block is executed and its return value is returned. If no block is passed, the value of the default argument is returned.

# File lib/rmail/header.rb, line 538
def content_type(default = nil)
  content_type = self['content-type']
  if content_type && content_type.length > 0
    content_type.strip.split(/\s*;\s*/)[0].downcase
  else
    if block_given?
      yield
    else
      default
    end
  end
end
date() click to toggle source

Return the value of the Date: field, parsed into a Time object. Returns nil if there is no Date: field or the field value could not be parsed.

# File lib/rmail/header.rb, line 649
def date
  if value = self['date']
    begin
      # Rely on Ruby's standard time.rb to parse the time.
      (Time.rfc2822(value) rescue Time.parse(value)).localtime
    rescue
      # Exceptions during time parsing just cause nil to be
      # returned.
    end
  end
end
date=(time) click to toggle source

Deletes any existing Date: fields and appends a new one corresponding to the given Time object.

# File lib/rmail/header.rb, line 663
def date=(time)
  delete('Date')
  add('Date', time.rfc2822)
end
delete(name) click to toggle source

Deletes all fields with name. Returns self.

# File lib/rmail/header.rb, line 259
def delete(name)
  name = Field.name_canonicalize(name.to_str)
  delete_if { |n, v|
    n.downcase == name
  }
  self
end
delete_at(index) click to toggle source

Deletes the field at the specified index and returns its value.

# File lib/rmail/header.rb, line 268
def delete_at(index)
  @fields.delete_at(index)
  self
end
delete_if() { |name, value| ... } click to toggle source

Deletes the field if the passed block returns true. Returns self.

# File lib/rmail/header.rb, line 275
def delete_if # yields: name, value
  @fields.delete_if { |i|
    yield i.name, i.value
  }
  self
end
dup() click to toggle source

Creates a copy of this header object. A new RMail::Header is created and the instance data is copied over. However, the new object will still reference the same strings held in the original object. Since these strings are frozen, this usually won’t matter.

Calls superclass method
# File lib/rmail/header.rb, line 159
def dup
  h = super
  h.fields = @fields.dup
  h.mbox_from = @mbox_from
  h
end
each() { |name, value| ... } click to toggle source

Executes block once for each field in the header, passing the key and value as parameters.

Returns self.

# File lib/rmail/header.rb, line 286
def each                    # yields: name, value
  @fields.each { |i|
    yield [i.name, i.value]
  }
end
Also aliased as: each_pair
each_key()
Alias for: each_name
each_name() { |name| ... } click to toggle source

Executes block once for each field in the header, passing the field’s name as a parameter.

Returns self

# File lib/rmail/header.rb, line 297
def each_name
  @fields.each { |i|
    yield(i.name)
  }
end
Also aliased as: each_key
each_pair()
Alias for: each
each_value() { |value| ... } click to toggle source

Executes block once for each field in the header, passing the field’s value as a parameter.

Returns self

# File lib/rmail/header.rb, line 308
def each_value
  @fields.each { |i|
    yield(i.value)
  }
end
empty?() click to toggle source

Returns true if the header contains no fields

# File lib/rmail/header.rb, line 315
def empty?
  @fields.empty?
end
fetch(name, *rest) { |name| ... } click to toggle source

Return the value of the first matching field of a given name. If there is no such field, the value returned by the supplied block is returned. If no block is passed, the value of default_value is returned. If no default_value is specified, an IndexError exception is raised.

# File lib/rmail/header.rb, line 206
def fetch(name, *rest)
  if rest.length > 1
    raise ArgumentError, "wrong # of arguments(#{rest.length + 1} for 2)"
  end
  result = self[name]
  if result.nil?
    if block_given?
      yield name
    elsif rest.length == 1
      rest[0]
    else
      raise IndexError, 'name not found'
    end
  else
    result
  end
end
fetch_all(name, *rest) { |name| ... } click to toggle source

Returns the values of every field named name. If there are no such fields, the value returned by the block is returned. If no block is passed, the value of default_value is returned. If no default_value is specified, an IndexError exception is raised.

# File lib/rmail/header.rb, line 229
def fetch_all name, *rest
  if rest.length > 1
    raise ArgumentError, "wrong # of arguments(#{rest.length + 1} for 2)"
  end
  result = select(name)
  if result.nil?
    if block_given?
      yield name
    elsif rest.length == 1
      rest[0]
    else
      raise IndexError, 'name not found'
    end
  else
    result.collect { |n, v|
      v
    }
  end
end
field?(name) click to toggle source

Returns true if the message has a field named ‘name’.

# File lib/rmail/header.rb, line 250
def field?(name)
  ! self[name].nil?
end
Also aliased as: member?, include?, has_key?, key?
from() click to toggle source

Returns the value of the From: header as an Array of RMail::Address objects.

See address_list_fetch for details on what is returned.

This method does not return a single RMail::Address value because it is legal to have multiple addresses in a From: header.

This method always returns at least the empty list. So if you are always only interested in the first from address (most likely the case), you can safely say:

header.from.first
# File lib/rmail/header.rb, line 682
def from
  address_list_fetch('from')
end
from=(addresses) click to toggle source

Sets the From: field to the supplied address or addresses.

See address_list_assign for information on valid values for addresses.

Note that the From: header usually contains only one address, but it is legal to have more than one.

# File lib/rmail/header.rb, line 693
def from=(addresses)
  address_list_assign('From', addresses)
end
has_key?(name)
Alias for: field?
include?(name)
Alias for: field?
key?(name)
Alias for: field?
keys()
Alias for: names
length() click to toggle source

Return the number of fields in this object.

# File lib/rmail/header.rb, line 196
def length
  @fields.length
end
Also aliased as: size
match(name, value) click to toggle source

Find all fields that match the given +name and value.

If name is a String, all fields of that name are tested. If name is a Regexp, the field names are matched against the regexp (the field names are converted to lower case first). Use the regexp // if you want to test all field names.

If value is a String, it is converted to a case insensitive Regexp that matches the string. Otherwise, it must be a Regexp. Note that the field value may be folded across many lines, so you may need to use a multi-line Regexp. Also consider using a case insensitive Regexp. Use the regexp // if you want to match all possible field values.

Returns a new RMail::Header holding all matching headers.

Examples:

received = header.match('Received', //)
destinations = header.match(/^(to|cc|bcc)$/, //)
bigfoot_received = header.match('received',
                                /from.*by.*bigfoot\.com.*LiteMail/im)

See also: match?

# File lib/rmail/header.rb, line 509
def match(name, value)
  massage_match_args(name, value) { |mname, mvalue|
    header = RMail::Header.new
    each { |n, v|
      if n.downcase =~ mname  &&  mvalue =~ v
        header[n] = v
      end
    }
    header
  }
end
match?(name, value) click to toggle source

Determine if there is any fields that match the given name and value.

If name is a String, all fields of that name are tested. If name is a Regexp the field names are matched against the regexp (the field names are converted to lower case first). Use the regexp // if you want to test all field names.

If value is a String, it is converted to a case insensitive Regexp that matches the string. Otherwise, it must be a Regexp. Note that the field value may be folded across many lines, so you should use a multi-line Regexp. Also consider using a case insensitive Regexp. Use the regexp // if you want to match all possible field values.

Returns true if there is a match, false otherwise.

Example:

if h.match?('x-ml-name', /ruby-dev/im)
  # do something
end

See also: match

# File lib/rmail/header.rb, line 476
def match?(name, value)
  massage_match_args(name, value) { |mname, mvalue|
    match = detect {|n, v|
      n =~ mname && v =~ mvalue
    }
    ! match.nil?
  }
end
mbox_from() click to toggle source

Gets the “From ” line previously set with mbox_from=, or nil.

# File lib/rmail/header.rb, line 528
def mbox_from
  @mbox_from
end
mbox_from=(value) click to toggle source

Sets the “From ” line commonly used in the Unix mbox mailbox format. The value supplied should be the entire “From ” line.

# File lib/rmail/header.rb, line 523
def mbox_from=(value)
  @mbox_from = value
end
media_type(default = nil) { || ... } click to toggle source

This returns the main media type for this message converted to lower case. This is the first portion of the content type. E.g. a content type of text/plain has a media type of text.

If there is no content type field, returns the passed block is executed and its return value is returned. If no block is passed, the value of the default argument is returned.

# File lib/rmail/header.rb, line 559
def media_type(default = nil)
  if value = content_type
    value.split('/')[0]
  else
    if block_given?
      yield
    else
      default
    end
  end
end
member?(name)
Alias for: field?
message_id() click to toggle source

Returns the value of this object’s Message-Id: field.

# File lib/rmail/header.rb, line 760
def message_id
  self['message-id']
end
names() click to toggle source

Returns an array consisting of the names of every field in this header.

# File lib/rmail/header.rb, line 334
def names
  collect { |n, v|
    n
  }
end
Also aliased as: keys
param(field_name, param_name, default = nil) { |field_name, param_name| ... } click to toggle source

This returns the parameter value for the given parameter in the given field. The value returned is unquoted.

If the field or parameter does not exist or it is malformed in a way that makes it impossible to parse, then the passed block is executed and its return value is returned. If no block is passed, the value of the default argument is returned.

# File lib/rmail/header.rb, line 621
def param(field_name, param_name, default = nil)
  if field?(field_name)
    params = params_quoted(field_name)
    value = params[param_name]
    return Utils.unquote(value) if value
  end
  if block_given?
    yield field_name, param_name
  else
    default
  end
end
params(field_name, default = nil) { |field_name| ... } click to toggle source

This returns a hash of parameters. Each key in the hash is the name of the parameter in lower case and each value in the hash is the unquoted parameter value. If a parameter has no value, its value in the hash will be true.

If the field or parameter does not exist or it is malformed in a way that makes it impossible to parse, then the passed block is executed and its return value is returned. If no block is passed, the value of the default argument is returned.

# File lib/rmail/header.rb, line 600
def params(field_name, default = nil)
  if params = params_quoted(field_name)
    params.each { |name, value|
      params[name] = value ? Utils.unquote(value) : nil
    }
  else
    if block_given?
      yield field_name
    else
      default
    end
  end
end
recipients() click to toggle source

Returns an RMail::Address::List array holding all the recipients of this message. This uses the contents of the To, Cc, and Bcc fields. Duplicate addresses are eliminated.

# File lib/rmail/header.rb, line 838
def recipients
  RMail::Address::List.new([ to, cc, bcc ].flatten.uniq)
end
replace(other) click to toggle source

Replaces the contents of this header with that of another header object. Returns self.

# File lib/rmail/header.rb, line 185
def replace(other)
  unless other.kind_of?(RMail::Header)
    raise TypeError, "#{other.class.to_s} is not of type RMail::Header"
  end
  temp = other.dup
  @fields = temp.fields
  @mbox_from = temp.mbox_from
  self
end
reply_to() click to toggle source

Returns the value of the Reply-To: header as an Array of RMail::Address objects.

# File lib/rmail/header.rb, line 747
def reply_to
  address_list_fetch('reply-to')
end
reply_to=(addresses) click to toggle source

Sets the Reply-To: field to the supplied address or addresses.

See address_list_assign for information on valid values for addresses.

# File lib/rmail/header.rb, line 755
def reply_to=(addresses)
  address_list_assign('Reply-To', addresses)
end
select(*names) click to toggle source

Returns an array of pairs [ name, value ] for all fields with one of the names passed.

# File lib/rmail/header.rb, line 321
def select(*names)
  result = []
  names.each { |name|
    name = Field.name_canonicalize(name)
    result.concat(find_all { |n, v|
                    n.downcase == name
                  })
  }
  result
end
set(name, value, params = nil) click to toggle source

First delete any fields with name, then append a new field with name, value, and params as in add.

# File lib/rmail/header.rb, line 395
def set(name, value, params = nil)
  delete(name)
  add(name, value, nil, params)
end
set_boundary(boundary) click to toggle source

Set the boundary parameter of this message’s Content-Type: field.

# File lib/rmail/header.rb, line 636
def set_boundary(boundary)
  params = params('content-type')
  params ||= {}
  params['boundary'] = boundary
  content_type = content_type()
  content_type ||= "multipart/mixed"
  delete('Content-Type')
  add('Content-Type', content_type, nil, params)
end
size()
Alias for: length
subject() click to toggle source

Return the subject of this message.

# File lib/rmail/header.rb, line 826
def subject
  self['subject']
end
subject=(string) click to toggle source

Set the subject of this message

# File lib/rmail/header.rb, line 831
def subject=(string)
  set('Subject', string)
end
subtype(default = nil) { || ... } click to toggle source

This returns the media subtype for this message, converted to lower case. This is the second portion of the content type. E.g. a content type of text/plain has a media subtype of plain.

If there is no content type field, returns the passed block is executed and its return value is returned. If no block is passed, the value of the default argument is returned.

# File lib/rmail/header.rb, line 579
def subtype(default = nil)
  if value = content_type
    value.split('/')[1]
  else
    if block_given? then
      yield
    else
      default
    end
  end
end
to() click to toggle source

Returns the value of the To: field as an Array of RMail::Address objects.

See address_list_fetch for details on what is returned.

# File lib/rmail/header.rb, line 701
def to
  address_list_fetch('to')
end
to=(addresses) click to toggle source

Sets the To: field to the supplied address or addresses.

See address_list_assign for information on valid values for addresses.

# File lib/rmail/header.rb, line 709
def to=(addresses)
  address_list_assign('To', addresses)
end
to_a() click to toggle source

Returns a new array holding one [ name, value ] array per field in the header.

# File lib/rmail/header.rb, line 419
def to_a
  @fields.collect { |field|
    [ field.name, field.value ]
  }
end
to_s() click to toggle source

Converts the header to a string, including any mbox from line. Equivalent to header.to_string(true).

# File lib/rmail/header.rb, line 427
def to_s
  to_string(true)
end
to_string(mbox_from = false) click to toggle source

Converts the header to a string. If mbox_from is true, then the mbox from line is also included.

# File lib/rmail/header.rb, line 433
def to_string(mbox_from = false)
  s = ""
  if mbox_from && ! @mbox_from.nil?
    s << @mbox_from
    s << "\n" unless @mbox_from[-1] == ?\n
  end
  @fields.each { |field|
    if field.raw
      s << field.raw
    else
      s << field.name
      s << ': '
      s << field.value
    end
    s << "\n" unless s[-1] == ?\n
  }
  s
end

Private Instance Methods

base36(number) click to toggle source
# File lib/rmail/header.rb, line 912
def base36(number)
  if number.kind_of?(String)
    number = string2num(number)
  end
  raise ArgumentError, "need non-negative number" if number < 0
  return "0" if number == 0
  result = ""
  while number > 0
    number, remainder = number.divmod(36)
    result << BASE36[remainder]
  end
  return result.reverse!
end
massage_match_args(name, value) { |name, value| ... } click to toggle source
# File lib/rmail/header.rb, line 966
def massage_match_args(name, value)
  case name
  when String
    name = /^#{Regexp.escape(Field.name_strip(name))}$/i
  when Regexp
  else
    raise ArgumentError,
      "name not a Regexp or String: #{name.class}:#{name.inspect}"
  end
  case value
  when String
    value = Regexp.new(Regexp.escape(value), Regexp::IGNORECASE)
  when Regexp
  else
    raise ArgumentError, "value not a Regexp or String"
  end
  yield(name, value)
end
params_quoted(field_name, default = nil) { |field_name else default end| ... } click to toggle source
# File lib/rmail/header.rb, line 942
  def params_quoted(field_name, default = nil)
    if value = self[field_name]
      params = {}
      first = true
      value.scan(PARAM_SCAN_RE) do |param|
        if param != ';'
          unless first
            name, value = param.scan(NAME_VALUE_SCAN_RE).collect do |p|
              if p == '=' then nil else p end
            end.compact
            if name && (name = name.strip.downcase) && name.length > 0
              params[name] = (value || '').strip
            end
          else
            first = false
          end
        end
      end
      params
    else
      if block_given? then yield field_name else default end
    end
  end

  def massage_match_args(name, value)
    case name
    when String
      name = /^#{Regexp.escape(Field.name_strip(name))}$/i
    when Regexp
    else
      raise ArgumentError,
        "name not a Regexp or String: #{name.class}:#{name.inspect}"
    end
    case value
    when String
      value = Regexp.new(Regexp.escape(value), Regexp::IGNORECASE)
    when Regexp
    else
      raise ArgumentError, "value not a Regexp or String"
    end
    yield(name, value)
  end
end
string2num(string) click to toggle source
# File lib/rmail/header.rb, line 902
def string2num(string)
  temp = 0
  string.reverse.each_byte { |b|
    temp <<= 8
    temp |= b
  }
  return temp
end