आईओएस 4.0 आईट्यून्स बैकअप में मैनिफेस्ट.एमबीडी फाइल को पार्स कैसे करें


82

IOS 4.0 में Apple ने बैकअप प्रक्रिया को फिर से डिजाइन किया है।

आइट्यून्स मैनिफेस्ट.प्लेस्ट फाइल में बैकअप फाइल्स से जुड़े फाइलनाम की एक सूची को स्टोर करते थे, लेकिन iOS 4.0 में यह जानकारी को मेनिफेस्ट.बैंडब में स्थानांतरित कर दिया है।

आप अपने iOS 4.0 उपकरणों के साथ बैकअप बनाकर और अपने ~ / लाइब्रेरी / एप्लिकेशन सपोर्ट / MobileSync / बैकअप फ़ोल्डर में देख कर इस फ़ाइल का एक उदाहरण देख सकते हैं (सबसे हाल की तारीख के साथ सबफ़ोल्डर्स के अंदर देखें)

यहां एक टेक्स्ट एडिटर में फ़ाइल कैसी दिखती है, इसका स्क्रीनशॉट है:

वैकल्पिक शब्द
(स्रोत: supercrazyawesome.com )

मैं इसे कोको एप्लिकेशन में पार्स कैसे करूं ताकि मैं iOS 4.0 के लिए अपने (फ्री) iPhone बैकअप एक्सट्रैक्टर ऐप ( http://supercrazyawesome.com ) को अपडेट कर सकूं ?


मेरे पास भी वही प्रश्न है। मैंने SQLite, बर्कले डीबी की कोशिश की, एनएसडॉर और कुछ अन्य चीजों को क्रमबद्ध किया। यदि आप इसका पता लगाते हैं तो कृपया इसे अपडेट करें। एक dbx फ़ाइल भी है जो एक एन्क्रिप्टेड स्वरूप प्रतीत होती है।
जॉन राइट

सिर्फ एक नोट; एक बार जब आप यह निर्धारित कर लेते हैं कि कौन सी फ़ाइल समेकित है। डीबी फ़ाइल, अगर आपके पास एक वेरिज़ोन फोन है, तो आपका डेटा CdmaCellLocation तालिका में रहेगा, न कि सेललोकेशन टेबल (जो खाली है)। बस के मामले में किसी को यह पता नहीं चला =)

जवाबों:


83

धन्यवाद, user374559 और reneD - कि कोड और विवरण बहुत उपयोगी है।

कुछ पाइथन में मेरा छुरा पार्स करने के लिए और यूनिक्स एलएस-एल में प्रारूप की तरह जानकारी प्रिंट करने के लिए:

#!/usr/bin/env python
import sys

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

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

def process_mbdb_file(filename):
    mbdb = {} # Map offset of info in this file => file info
    data = open(filename).read()
    if data[0:4] != "mbdb": raise Exception("This does not look like an MBDB file")
    offset = 4
    offset = offset + 2 # value x05 x00, not sure what this is
    while offset < len(data):
        fileinfo = {}
        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)
        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'] = {}
        for ii in range(fileinfo['numprops']):
            propname, offset = getstring(data, offset)
            propval, offset = getstring(data, offset)
            fileinfo['properties'][propname] = propval
        mbdb[fileinfo['start_offset']] = fileinfo
    return mbdb

def process_mbdx_file(filename):
    mbdx = {} # Map offset of info in the MBDB file => fileID string
    data = open(filename).read()
    if data[0:4] != "mbdx": raise Exception("This does not look like an MBDX file")
    offset = 4
    offset = offset + 2 # value 0x02 0x00, not sure what this is
    filecount, offset = getint(data, offset, 4) # 4-byte count of records 
    while offset < len(data):
        # 26 byte record, made up of ...
        fileID = data[offset:offset+20] # 20 bytes of fileID
        fileID_string = ''.join(['%02x' % ord(b) for b in fileID])
        offset = offset + 20
        mbdb_offset, offset = getint(data, offset, 4) # 4-byte offset field
        mbdb_offset = mbdb_offset + 6 # Add 6 to get past prolog
        mode, offset = getint(data, offset, 2) # 2-byte mode field
        mbdx[mbdb_offset] = fileID_string
    return mbdx

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

def fileinfo_str(f, verbose=False):
    if not verbose: return "(%s)%s::%s" % (f['fileID'], f['domain'], f['filename'])
    if (f['mode'] & 0xE000) == 0xA000: type = 'l' # symlink
    elif (f['mode'] & 0xE000) == 0x8000: type = '-' # file
    elif (f['mode'] & 0xE000) == 0x4000: type = 'd' # dir
    else: 
        print >> sys.stderr, "Unknown file type %04x for %s" % (f['mode'], fileinfo_str(f, False))
        type = '?' # unknown
    info = ("%s%s %08x %08x %7d %10d %10d %10d (%s)%s::%s" % 
            (type, modestr(f['mode']&0x0FFF) , f['userid'], f['groupid'], f['filelen'], 
             f['mtime'], f['atime'], f['ctime'], f['fileID'], f['domain'], f['filename']))
    if type == 'l': info = info + ' -> ' + f['linktarget'] # symlink destination
    for name, value in f['properties'].items(): # extra properties
        info = info + ' ' + name + '=' + repr(value)
    return info

verbose = True
if __name__ == '__main__':
    mbdb = process_mbdb_file("Manifest.mbdb")
    mbdx = process_mbdx_file("Manifest.mbdx")
    for offset, fileinfo in mbdb.items():
        if offset in mbdx:
            fileinfo['fileID'] = mbdx[offset]
        else:
            fileinfo['fileID'] = "<nofileID>"
            print >> sys.stderr, "No fileID found for %s" % fileinfo_str(fileinfo)
        print fileinfo_str(fileinfo, verbose)

14
यह पोस्ट इतिहास में नीचे जाने वाली है।
पर्कनी

प्रतिभाशाली! मुझे user374559 से कोड के साथ लापता मॉड्यूल के साथ कुछ परेशानी थी - लेकिन, फिर, मैं अजगर के साथ नौसिखिया हूं।
19-30 को वेस्टसाइडर्स

3
उपरोक्त पाठ पेटी वार्डन में "iphonels.py" के रूप में संदर्भित स्क्रिप्ट है। github.com/iPhoneTracker , जो Apple लोकेशन ट्रैकिंग डेटाबेस खोजने के लिए उपयोगी है।
फ्लैश शेरिडन

4
ध्यान दें कि यह विंडोज पर ठीक काम करता है, भी (जब तक आपके पास इसे चलाने के लिए पायथन है, निश्चित रूप से), अगर आप खुले में एक "आरबी" पैरामीटर जोड़ते हैं () कॉल।
tml

1
कोई चिंता नहीं। इस सप्ताह से पहले मैंने पायथन की एक पंक्ति कभी नहीं देखी थी, यह आश्चर्यजनक रूप से सीधा बंदरगाह था। अब अजगर सीख सकते हैं :-)
tomfanning

29

IOS 5 में, Manifest.mbdx फ़ाइल को समाप्त कर दिया गया था। इस लेख के उद्देश्य के लिए, यह वैसे भी बेमानी था, क्योंकि डोमेन और पथ मेनिफेस्ट.बैंब में हैं और SHA1 के साथ आईडी हैश उत्पन्न किया जा सकता है।

यहाँ गैलाग्लास के कोड का मेरा अपडेट है इसलिए यह iOS 5 उपकरणों के बैकअप के साथ काम करता है। केवल परिवर्तन process_mbdx_file () और process_mbdb_file () में कुछ पंक्तियों के जोड़ के उन्मूलन हैं।

एक iPhone 4S और एक iPad 1 के बैकअप के साथ परीक्षण किया गया, दोनों में बहुत सारे ऐप और फाइलें।

#!/usr/bin/env python
import sys
import hashlib

mbdx = {}

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

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

def process_mbdb_file(filename):
    mbdb = {} # Map offset of info in this file => file info
    data = open(filename).read()
    if data[0:4] != "mbdb": raise Exception("This does not look like an MBDB file")
    offset = 4
    offset = offset + 2 # value x05 x00, not sure what this is
    while offset < len(data):
        fileinfo = {}
        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)
        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'] = {}
        for ii in range(fileinfo['numprops']):
            propname, offset = getstring(data, offset)
            propval, offset = getstring(data, offset)
            fileinfo['properties'][propname] = propval
        mbdb[fileinfo['start_offset']] = fileinfo
        fullpath = fileinfo['domain'] + '-' + fileinfo['filename']
        id = hashlib.sha1(fullpath)
        mbdx[fileinfo['start_offset']] = id.hexdigest()
    return mbdb

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

def fileinfo_str(f, verbose=False):
    if not verbose: return "(%s)%s::%s" % (f['fileID'], f['domain'], f['filename'])
    if (f['mode'] & 0xE000) == 0xA000: type = 'l' # symlink
    elif (f['mode'] & 0xE000) == 0x8000: type = '-' # file
    elif (f['mode'] & 0xE000) == 0x4000: type = 'd' # dir
    else: 
        print >> sys.stderr, "Unknown file type %04x for %s" % (f['mode'], fileinfo_str(f, False))
        type = '?' # unknown
    info = ("%s%s %08x %08x %7d %10d %10d %10d (%s)%s::%s" % 
            (type, modestr(f['mode']&0x0FFF) , f['userid'], f['groupid'], f['filelen'], 
             f['mtime'], f['atime'], f['ctime'], f['fileID'], f['domain'], f['filename']))
    if type == 'l': info = info + ' -> ' + f['linktarget'] # symlink destination
    for name, value in f['properties'].items(): # extra properties
        info = info + ' ' + name + '=' + repr(value)
    return info

verbose = True
if __name__ == '__main__':
    mbdb = process_mbdb_file("Manifest.mbdb")
    for offset, fileinfo in mbdb.items():
        if offset in mbdx:
            fileinfo['fileID'] = mbdx[offset]
        else:
            fileinfo['fileID'] = "<nofileID>"
            print >> sys.stderr, "No fileID found for %s" % fileinfo_str(fileinfo)
        print fileinfo_str(fileinfo, verbose)

1
जनवरी 2016, अभी भी iTunes 12.3.2.35 और iOS 9.2 के साथ काम करता है।
सिगुज़ा

18

मैंने इस सामान पर अपना काम पूरा कर लिया है - अर्थात, iOS 4 + iTunes 9.2 पायथन के लिए मेरे बैकअप डिकोडर लाइब्रेरी का अद्यतन - http://www.iki.fi/fingon/iphonebackupdb.py

यह वही करता है जो मुझे चाहिए, थोड़ा दस्तावेज़ीकरण, लेकिन वहाँ से विचारों को कॉपी करने के लिए स्वतंत्र महसूस करें ;-)

(कम से कम मेरे बैकअप के साथ काम करने लगता है।)


3
अजगर मॉड्यूल "एमएस" मेरी मशीन इसे खोजने के लिए प्रतीत नहीं कर सकते हैं
JiminyCricket

1
वे मार्कस स्टैनबर्ग के अजगर पुस्तकालयों का हिस्सा हैं: <कर्मचारी.org/~stenber/>; आपको उनमें से एक आंशिक सेट तक ले जाएगा। दुर्भाग्य से, उन लोगों के साथ भी, आप अन्य लापता फ़ाइलों (?) का सामना करेंगे। कॉपी और चिपके हुए गैलग्लास 'अधिक आसानी से काम करता है - लेकिन व्युत्पन्न है। सभी को धन्यवाद!
वेस्टस्पेडर

10

आप जानकारी और MBDB / MBDX प्रारूप का थोड़ा विवरण यहाँ पा सकते हैं:

http://code.google.com/p/iphonebackupbrowser/

यह बैकअप फ़ाइलों को ब्राउज़ करने के लिए मेरा आवेदन है। मैंने आईट्यून्स 9.2 के साथ आने वाली नई फाइलों के प्रारूप का दस्तावेजीकरण करने की कोशिश की है।


7

यह पाइथन स्क्रिप्ट कमाल की है।

यहां मेरा रूबी संस्करण है (मामूली सुधार के साथ) और खोज क्षमताएं। (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

4

मुझे गैलग्लॉस का कोड पसंद आया, और मैंने मुख्य फ़ंक्शन को बदल दिया ताकि यह एप्लिकेशन द्वारा कुल आकार की एक सॉर्ट की गई सूची दिखाता है:

verbose = True
if __name__ == '__main__':
    mbdb = process_mbdb_file("Manifest.mbdb")
    mbdx = process_mbdx_file("Manifest.mbdx")
    sizes = {}
    for offset, fileinfo in mbdb.items():
        if offset in mbdx:
            fileinfo['fileID'] = mbdx[offset]
        else:
            fileinfo['fileID'] = "<nofileID>"
            print >> sys.stderr, "No fileID found for %s" % fileinfo_str(fileinfo)
        print fileinfo_str(fileinfo, verbose)
        if (fileinfo['mode'] & 0xE000) == 0x8000:
        sizes[fileinfo['domain']]= sizes.get(fileinfo['domain'],0) + fileinfo['filelen']
    for domain in sorted(sizes, key=sizes.get):
        print "%-60s %11d (%dMB)" % (domain, sizes[domain], int(sizes[domain]/1024/1024))

इस तरह से आप यह पता लगा सकते हैं कि कौन सी एप्लीकेशन सभी जगह खा रही है।


महान। आश्चर्य की बात नहीं, कम से कम मेरे लिए यह पत्रिका एप्लिकेशन है जो सबसे अधिक बैकअप स्थान खाते हैं। (मैंने अपने आईपैड पर न्यू यॉर्कर और वैनिटी फेयर के मुद्दों का एक गुच्छा खरीदा है।) लेकिन जो इनफ्लुएंस है वह यह है कि ये मैगज़ीन ऐप अलग-अलग फाइलों को डिवाइस पर अलग-अलग फाइलों के रूप में रखते हैं। बैकअप को बहुत धीमा कर देता है।
tml

हा हा, कुछ मामलों में न्यू यॉर्कर ऐप में लेखों के लिए SVN डेटा भी है ... मुझे AppDomain-com.condenet.newyorker :: दस्तावेज़ / मुद्दे / New Yorker / 396efb8c-fcdd-4997-8122-2e2bdc3940e5 जैसी फाइलें दिखाई देती हैं। /1700_talk_surowiecki_110328/images/.svn/prop-base/101011_r20103_p280.jpg.svn-base
tml

2

MBDB फ़ाइल रीडर के जावा कार्यान्वयन की तलाश करने वालों के लिए, वहाँ कई हैं:


0

गैलॉग्लास के जवाब के लिए धन्यवाद। कोड पायथन 2.7 के साथ बहुत अच्छा काम करता है। केवल एक चीज है जो मैं चाहता हूं कि मैं पैमाइश करूं। मैनिफ़ेस्ट .mbdb फ़ाइल पढ़ते समय, आपको बाइनरी मोड का उपयोग करना चाहिए। अन्यथा, सभी सामग्री पढ़ी नहीं जाती हैं।

मैंने पायथन 3.4 के साथ कोड काम करने के लिए कुछ छोटे बदलाव भी किए। यहाँ कोड है।

#!/usr/bin/env python
import sys
import hashlib

mbdx = {}

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

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

def process_mbdb_file(filename):
    mbdb = {}  # Map offset of info in this file => file info
    data = open(filename, 'rb').read()  # 'b' is needed to read all content at once
    if data[0:4].decode() != "mbdb": raise Exception("This does not look like an MBDB file")
    offset = 4
    offset = offset + 2  # value x05 x00, not sure what this is
    while offset < len(data):
        fileinfo = {}
        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)
        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'] = {}
        for ii in range(fileinfo['numprops']):
            propname, offset = getstring(data, offset)
            propval, offset = getstring(data, offset)
            fileinfo['properties'][propname] = propval
        mbdb[fileinfo['start_offset']] = fileinfo
        fullpath = fileinfo['domain'] + '-' + fileinfo['filename']
        id = hashlib.sha1(fullpath.encode())
        mbdx[fileinfo['start_offset']] = id.hexdigest()
    return mbdb

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

def fileinfo_str(f, verbose=False):
    if not verbose: return "(%s)%s::%s" % (f['fileID'], f['domain'], f['filename'])
    if (f['mode'] & 0xE000) == 0xA000:
        type = 'l'  # symlink
    elif (f['mode'] & 0xE000) == 0x8000:
        type = '-'  # file
    elif (f['mode'] & 0xE000) == 0x4000:
        type = 'd'  # dir
    else:
        print >> sys.stderr, "Unknown file type %04x for %s" % (f['mode'], fileinfo_str(f, False))
        type = '?'  # unknown
    info = ("%s%s %08x %08x %7d %10d %10d %10d (%s)%s::%s" %
            (type, modestr(f['mode'] & 0x0FFF), f['userid'], f['groupid'], f['filelen'],
             f['mtime'], f['atime'], f['ctime'], f['fileID'], f['domain'], f['filename']))
    if type == 'l': info = info + ' -> ' + f['linktarget']  # symlink destination
    for name, value in f['properties'].items():  # extra properties
        info = info + ' ' + name + '=' + repr(value)
    return info

verbose = True
if __name__ == '__main__':
    mbdb = process_mbdb_file(
        r"Manifest.mbdb")
    for offset, fileinfo in mbdb.items():
        if offset in mbdx:
            fileinfo['fileID'] = mbdx[offset]
        else:
            fileinfo['fileID'] = "<nofileID>"
            print >> sys.stderr, "No fileID found for %s" % fileinfo_str(fileinfo)
        print(fileinfo_str(fileinfo, verbose))

मैंने आपका कोड आज़मा लिया है, मुझे IndexError मिलता है; सीमा से बाहर स्ट्रिंग के कारणvalue = (value<<8) + ord(data[offset])
जोस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.