[iphone] How to parse the Manifest.mbdb file in an iOS 4.0 iTunes Backup

This python script is awesome.

Here's my Ruby version of it (with minor improvement) and search capabilities. (for iOS 5)

# encoding: utf-8
require 'fileutils'
require 'digest/sha1'

class ManifestParser
  def initialize(mbdb_filename, verbose = false)
    @verbose = verbose
    process_mbdb_file(mbdb_filename)
  end

  # Returns the numbers of records in the Manifest files.
  def record_number
    @mbdb.size
  end

  # Returns a huge string containing the parsing of the Manifest files.
  def to_s
    s = ''
    @mbdb.each do |v|
      s += "#{fileinfo_str(v)}\n"
    end
    s
  end

  def to_file(filename)
    File.open(filename, 'w') do |f|
      @mbdb.each do |v|
        f.puts fileinfo_str(v)
      end
    end
  end

  # Copy the backup files to their real path/name.
  # * domain_match Can be a regexp to restrict the files to copy.
  # * filename_match Can be a regexp to restrict the files to copy.
  def rename_files(domain_match = nil, filename_match = nil)
    @mbdb.each do |v|
      if v[:type] == '-' # Only rename files.
        if (domain_match.nil? or v[:domain] =~ domain_match) and (filename_match.nil? or v[:filename] =~ filename_match)
          dst = "#{v[:domain]}/#{v[:filename]}"
          puts "Creating: #{dst}"
          FileUtils.mkdir_p(File.dirname(dst))
          FileUtils.cp(v[:fileID], dst)
        end
      end
    end
  end

  # Return the filename that math the given regexp.
  def search(regexp)
    result = Array.new
    @mbdb.each do |v|
      if "#{v[:domain]}::#{v[:filename]}" =~ regexp
        result << v
      end
    end
    result
  end

  private
  # Retrieve an integer (big-endian) and new offset from the current offset
  def getint(data, offset, intsize)
    value = 0
    while intsize > 0
      value = (value<<8) + data[offset].ord
      offset += 1
      intsize -= 1
    end
    return value, offset
  end

  # Retrieve a string and new offset from the current offset into the data
  def getstring(data, offset)
    return '', offset + 2 if data[offset] == 0xFF.chr and data[offset + 1] == 0xFF.chr # Blank string
    length, offset = getint(data, offset, 2) # 2-byte length
    value = data[offset...(offset + length)]
    return value, (offset + length)
  end

  def process_mbdb_file(filename)
    @mbdb = Array.new
    data = File.open(filename, 'rb') { |f| f.read }
    puts "MBDB file read. Size: #{data.size}"
    raise 'This does not look like an MBDB file' if data[0...4] != 'mbdb'
    offset = 4
    offset += 2 # value x05 x00, not sure what this is
    while offset < data.size
      fileinfo = Hash.new
      fileinfo[:start_offset] = offset
      fileinfo[:domain], offset = getstring(data, offset)
      fileinfo[:filename], offset = getstring(data, offset)
      fileinfo[:linktarget], offset = getstring(data, offset)
      fileinfo[:datahash], offset = getstring(data, offset)
      fileinfo[:unknown1], offset = getstring(data, offset)
      fileinfo[:mode], offset = getint(data, offset, 2)
      if (fileinfo[:mode] & 0xE000) == 0xA000 # Symlink
        fileinfo[:type] = 'l'
      elsif (fileinfo[:mode] & 0xE000) == 0x8000 # File
        fileinfo[:type] = '-'
      elsif (fileinfo[:mode] & 0xE000) == 0x4000 # Dir
        fileinfo[:type] = 'd'
      else
        # $stderr.puts "Unknown file type %04x for #{fileinfo_str(f, false)}" % f['mode']
        fileinfo[:type] = '?'
      end
      fileinfo[:unknown2], offset = getint(data, offset, 4)
      fileinfo[:unknown3], offset = getint(data, offset, 4)
      fileinfo[:userid], offset = getint(data, offset, 4)
      fileinfo[:groupid], offset = getint(data, offset, 4)
      fileinfo[:mtime], offset = getint(data, offset, 4)
      fileinfo[:atime], offset = getint(data, offset, 4)
      fileinfo[:ctime], offset = getint(data, offset, 4)
      fileinfo[:filelen], offset = getint(data, offset, 8)
      fileinfo[:flag], offset = getint(data, offset, 1)
      fileinfo[:numprops], offset = getint(data, offset, 1)
      fileinfo[:properties] = Hash.new
      (0...(fileinfo[:numprops])).each do |ii|
        propname, offset = getstring(data, offset)
        propval, offset = getstring(data, offset)
        fileinfo[:properties][propname] = propval
      end
      # Compute the ID of the file.
      fullpath = fileinfo[:domain] + '-' + fileinfo[:filename]
      fileinfo[:fileID] = Digest::SHA1.hexdigest(fullpath)
      # We add the file to the list of files.
      @mbdb << fileinfo
    end
    @mbdb
  end

  def modestr(val)
    def mode(val)
      r = (val & 0x4) ? 'r' : '-'
      w = (val & 0x2) ? 'w' : '-'
      x = (val & 0x1) ? 'x' : '-'
      r + w + x
    end
    mode(val >> 6) + mode(val >> 3) + mode(val)
  end

  def fileinfo_str(f)
    return "(#{f[:fileID]})#{f[:domain]}::#{f[:filename]}" unless @verbose
    data = [f[:type], modestr(f[:mode]), f[:userid], f[:groupid], f[:filelen], f[:mtime], f[:atime], f[:ctime], f[:fileID], f[:domain], f[:filename]]
    info = "%s%s %08x %08x %7d %10d %10d %10d (%s)%s::%s" % data
    info += ' -> ' + f[:linktarget] if f[:type] == 'l' # Symlink destination
    f[:properties].each do |k, v|
      info += " #{k}=#{v.inspect}"
    end
    info
  end
end

if __FILE__ == $0
  mp = ManifestParser.new 'Manifest.mbdb', true
  mp.to_file 'filenames.txt'
end

Examples related to iphone

Detect if the device is iPhone X Xcode 8 shows error that provisioning profile doesn't include signing certificate Access files in /var/mobile/Containers/Data/Application without jailbreaking iPhone Certificate has either expired or has been revoked Missing Compliance in Status when I add built for internal testing in Test Flight.How to solve? cordova run with ios error .. Error code 65 for command: xcodebuild with args: "Could not find Developer Disk Image" Reason: no suitable image found iPad Multitasking support requires these orientations How to insert new cell into UITableView in Swift

Examples related to ios4

Unbalanced calls to begin/end appearance transitions for <UITabBarController: 0x197870> How can we programmatically detect which iOS version is device running on? Convert a string into an int Xcode Objective-C | iOS: delay function / NSTimer help? How can I use NSError in my iPhone App? What programming languages can one use to develop iPhone, iPod Touch and iPad (iOS) applications? How to keep an iPhone app running on background fully operational How do you use NSAttributedString? How to parse the Manifest.mbdb file in an iOS 4.0 iTunes Backup

Examples related to backup

input file appears to be a text format dump. Please use psql How can I backup a Docker-container with its data-volumes? Backup/Restore a dockerized PostgreSQL database Export MySQL database using PHP only Tar a directory, but don't store full absolute paths in the archive How to extract or unpack an .ab file (Android Backup file) mysqldump with create database line Postgresql 9.2 pg_dump version mismatch How to backup Sql Database Programmatically in C# Opening a SQL Server .bak file (Not restoring!)

Examples related to extract

python pandas extract year from datetime: df['year'] = df['date'].year is not working Accessing last x characters of a string in Bash How to extract one column of a csv file How can I extract the folder path from file path in Python? Extract and delete all .gz in a directory- Linux Read Content from Files which are inside Zip file Get string after character how to extract only the year from the date in sql server 2008? In Excel, how do I extract last four letters of a ten letter string? How can I extract all values from a dictionary in Python?