Beispiel #1
0
    def get_formatted_content(self, pyobj):
        if isinstance(pyobj, _floattypes) or isinstance(pyobj, _inttypes):
            pyobj = _gmtime(pyobj)

        if self.fix_timezone:
            pyobj = _fix_timezone(pyobj, tz_from=None, tz_to="Z")

        d = {}
        pyobj = tuple(pyobj)
        if 1 in [x < 0 for x in pyobj[0:6]]:
            pyobj = [abs(y) for y in pyobj]
            d['neg'] = '-'
        else:
            d['neg'] = ''

        d = {}
        for k, i in [('Y', 0), ('M', 1), ('D', 2), ('h', 3), ('m', 4),
                     ('s', 5)]:
            d[k] = pyobj[i]

        ms = pyobj[6]
        if not ms or not hasattr(self, 'format_ms'):
            return self.format % d

        if ms > 999:
            raise ValueError(
                'milliseconds must be a integer between 0 and 999')

        d['ms'] = ms
        return self.format_ms % d
Beispiel #2
0
    def get_formatted_content(self, pyobj):
        if isinstance(pyobj, _floattypes) or isinstance(pyobj, _inttypes):
            pyobj = _gmtime(pyobj)

        if self.fix_timezone:
            pyobj = _fix_timezone(pyobj, tz_from = None, tz_to = "Z")

        d = {}
        pyobj = tuple(pyobj)
        if 1 in [x < 0 for x in pyobj[0:6]]:
            pyobj = [abs(y) for y in pyobj]
            d['neg'] = '-'
        else:
            d['neg'] = ''

        d = {}
        for k,i in [ ('Y', 0), ('M', 1), ('D', 2), ('h', 3), ('m', 4), ('s', 5) ]:
            d[k] = pyobj[i]

        ms = pyobj[6]
        if not ms or not hasattr(self, 'format_ms'):
            return self.format % d

        if  ms > 999:
            raise ValueError('milliseconds must be a integer between 0 and 999')

        d['ms'] = ms
        return self.format_ms % d
Beispiel #3
0
    def get_formatted_content(self, pyobj):
        if type(pyobj) in _floattypes or type(pyobj) in _inttypes:
            pyobj = _gmtime(pyobj)
        
        if self.fix_timezone:
            pyobj = _fix_timezone(pyobj, tz_from = None, tz_to = "Z")

        d = {}
        pyobj = tuple(pyobj)
        if 1 in map(lambda x: x < 0, pyobj[0:6]):
            pyobj = map(abs, pyobj)
            d['neg'] = '-'
        else:
            d['neg'] = ''

        d = {}
        for k,i in [ ('Y', 0), ('M', 1), ('D', 2), ('h', 3), ('m', 4), ('s', 5) ]:
            d[k] = pyobj[i]

        ms = pyobj[6]
        if not ms or not hasattr(self, 'format_ms'): 
            return self.format % d

        if  ms > 999:
            raise ValueError, 'milliseconds must be a integer between 0 and 999'

        d['ms'] = ms
        return self.format_ms % d
Beispiel #4
0
 def addLog(self):
     argvs = _sys.argv
     command = "%s " % _strftime("%B-%d-%Y %H:%M", _gmtime())
     for ii in range(len(argvs)):
         command = command + " " + argvs[ii]
     # end for
     self.comments.append("   ")
     self.comments.append(command)
Beispiel #5
0
    def get_formatted_content(self, pyobj):
        if type(pyobj) in _floattypes or type(pyobj) in _inttypes:
            pyobj = _gmtime(pyobj)

        #
        # handle null time strings
        #

        if pyobj == "":
            return ""

        #
        # handle perforce style time strings
        #
        elif type(pyobj) == type(""):
            if "/" in pyobj:
                tokens = pyobj.split("/")
                d = {"Y": int(tokens[0]), "M": int(tokens[1])}
                if not ":" in tokens[2]:
                    d["D"] = int(tokens[2])
                    return self.format % d
                else:
                    # this is actually a datetime format, not just a date format
                    timetokens = tokens[2].split(":")
                    d["D"] = int(timetokens[0])
                    d["h"] = int(timetokens[1])
                    d["m"] = int(timetokens[2])
                    d["s"] = int(timetokens[3])
                    return "%(Y)04d-%(M)02d-%(D)02dT%(h)02d:%(m)02d:%(s)02dZ" % d
        #
        #
        #

        d = {}
        pyobj = tuple(pyobj)
        if 1 in map(lambda x: x < 0, pyobj[0:6]):
            pyobj = map(abs, pyobj)
            d["neg"] = "-"
        else:
            d["neg"] = ""

        ms = pyobj[6]
        if not ms or not hasattr(self, "format_ms"):
            d = {"Y": pyobj[0], "M": pyobj[1], "D": pyobj[2], "h": pyobj[3], "m": pyobj[4], "s": pyobj[5]}
            return self.format % d

        if ms > 999:
            raise ValueError, "milliseconds must be a integer between 0 and 999"

        d = {"Y": pyobj[0], "M": pyobj[1], "D": pyobj[2], "h": pyobj[3], "m": pyobj[4], "s": pyobj[5], "ms": ms}
        return self.format_ms % d
Beispiel #6
0
    def get_formatted_content(self, pyobj):
        if type(pyobj) in _floattypes or type(pyobj) in _inttypes:
            pyobj = _gmtime(pyobj)

        d = {}
        pyobj = tuple(pyobj)
        if 1 in map(lambda x: x < 0, pyobj[0:6]):
            pyobj = map(abs, pyobj)
            neg = "-"
        else:
            neg = ""

        val = "%sP%dY%dM%dDT%dH%dM%dS" % (neg, pyobj[0], pyobj[1], pyobj[2], pyobj[3], pyobj[4], pyobj[5])

        return val
Beispiel #7
0
    def get_formatted_content(self, pyobj):
        if isinstance(pyobj, _floattypes) or isinstance(pyobj, _inttypes):
            pyobj = _gmtime(pyobj)

        pyobj = tuple(pyobj)
        if 1 in [x < 0 for x in pyobj[0:6]]:
            pyobj = [abs(y) for y in pyobj]
            neg = '-'
        else:
            neg = ''

        val = '%sP%dY%dM%dDT%dH%dM%dS' % \
            ( neg, pyobj[0], pyobj[1], pyobj[2], pyobj[3], pyobj[4], pyobj[5])

        return val
Beispiel #8
0
    def get_formatted_content(self, pyobj):
        if isinstance(pyobj, _floattypes) or isinstance(pyobj, _inttypes):
            pyobj = _gmtime(pyobj)

        pyobj = tuple(pyobj)
        if 1 in [x < 0 for x in pyobj[0:6]]:
            pyobj = [abs(y) for y in pyobj]
            neg = '-'
        else:
            neg = ''

        val = '%sP%dY%dM%dDT%dH%dM%dS' % \
            ( neg, pyobj[0], pyobj[1], pyobj[2], pyobj[3], pyobj[4], pyobj[5])

        return val
Beispiel #9
0
    def get_formatted_content(self, pyobj):
        if type(pyobj) in _floattypes or type(pyobj) in _inttypes:
            pyobj = _gmtime(pyobj)
        
        d = {}
        pyobj = tuple(pyobj)
        if 1 in [x < 0 for x in pyobj[0:6]]:
            pyobj = list(map(abs, pyobj))
            neg = '-'
        else:
            neg = ''
            
        val = '%sP%dY%dM%dDT%dH%dM%dS' % \
            ( neg, pyobj[0], pyobj[1], pyobj[2], pyobj[3], pyobj[4], pyobj[5])

        return val
Beispiel #10
0
    def get_formatted_content(self, pyobj):
        if type(pyobj) in _floattypes or type(pyobj) in _inttypes:
            pyobj = _gmtime(pyobj)
        
        d = {}
        pyobj = tuple(pyobj)
        if 1 in map(lambda x: x < 0, pyobj[0:6]):
            pyobj = map(abs, pyobj)
            neg = '-'
        else:
            neg = ''
            
        val = '%sP%dY%dM%dDT%dH%dM%dS' % \
            ( neg, pyobj[0], pyobj[1], pyobj[2], pyobj[3], pyobj[4], pyobj[5])

        return val
Beispiel #11
0
    def convert2to1(self, source, idx=1, idz=[1]):
        idy = 2
        if idx == 2:
            idy = 1
        # end if
        nx = source.DimSize[idx - 1]
        ny = source.DimSize[idy - 1]
        nz = len(idz)
        self.new(dimno=1, valno=ny * nz, dimsize=[nx])
        self.Name = source.Name
        self.ShotNo = source.ShotNo
        self.SubNo = source.SubNo
        self.Date = _strftime("%m/%d/%Y %H:%M", _gmtime())
        self.DimName = [source.DimName[idx - 1]]
        self.DimUnit = [source.DimUnit[idx - 1]]
        self.ValName = []
        self.ValUnit = []
        self.comments = source.comments
        if idx == 1:
            xx = source.getDimData(dimid=idx - 1)
            yy = source.getDimData(dimid=idy - 1)
            for ii in range(nz):
                self.data[:, ii + 1::nz] = source.getValData(valid=idz[ii] - 1)
            # end for
        else:
            xx = source.getDimData(dimid=idx).transpose()
            yy = source.getDimData(dimid=idy).transpose()
            for ii in range(nz):
                self.data[:, ii + 1::nz] = source.getValData(valid=idz[ii] -
                                                             1).transpose()
            # end for
        # end if

        self.data[:, 0] = xx[:, 0]
        for j in range(ny):
            for ii in range(nz):
                valname = source.ValName[idz[ii] - 1] + "@%.6E" % yy[
                    0, j] + "(%s)" % source.DimUnit[idy - 1]
                self.ValName.append(valname)
                self.ValUnit.append(source.ValUnit[idz[ii] - 1])
Beispiel #12
0
    def get_formatted_content(self, pyobj):
        if type(pyobj) in _floattypes or type(pyobj) in _inttypes:
            pyobj = _gmtime(pyobj)

        d = {}
        pyobj = tuple(pyobj)
        if 1 in [x < 0 for x in pyobj[0:6]]:
            pyobj = list(map(abs, pyobj))
            d['neg'] = '-'
        else:
            d['neg'] = ''

        ms = pyobj[6]
        if not ms or not hasattr(self, 'format_ms'):
            d = {
                'Y': pyobj[0],
                'M': pyobj[1],
                'D': pyobj[2],
                'h': pyobj[3],
                'm': pyobj[4],
                's': pyobj[5],
            }
            return self.format % d

        if ms > 999:
            raise ValueError(
                'milliseconds must be a integer between 0 and 999')

        d = {
            'Y': pyobj[0],
            'M': pyobj[1],
            'D': pyobj[2],
            'h': pyobj[3],
            'm': pyobj[4],
            's': pyobj[5],
            'ms': ms,
        }
        return self.format_ms % d
Beispiel #13
0
    def get_formatted_content(self, pyobj):
        if type(pyobj) in _floattypes or type(pyobj) in _inttypes:
            pyobj = _gmtime(pyobj)

        d = {}
        pyobj = tuple(pyobj)
        if 1 in map(lambda x: x < 0, pyobj[0:6]):
            pyobj = map(abs, pyobj)
            d['neg'] = '-'
        else:
            d['neg'] = ''

        ms = pyobj[6]
        if not ms or not hasattr(self, 'format_ms'):
            d = {
                'Y': pyobj[0],
                'M': pyobj[1],
                'D': pyobj[2],
                'h': pyobj[3],
                'm': pyobj[4],
                's': pyobj[5],
            }
            return self.format % d

        if ms > 999:
            raise ValueError, 'milliseconds must be a integer between 0 and 999'

        d = {
            'Y': pyobj[0],
            'M': pyobj[1],
            'D': pyobj[2],
            'h': pyobj[3],
            'm': pyobj[4],
            's': pyobj[5],
            'ms': ms,
        }
        return self.format_ms % d
Beispiel #14
0
    def get_formatted_content(self, pyobj):
        if type(pyobj) in _floattypes or type(pyobj) in _inttypes:
            pyobj = _gmtime(pyobj)

        d = {}
        pyobj = tuple(pyobj)
        if 1 in map(lambda x: x < 0, pyobj[0:6]):
            pyobj = map(abs, pyobj)
            d['neg'] = '-'
        else:
            d['neg'] = ''

        ms = pyobj[6]
        if not ms:
            d = {
                'Y': pyobj[0],
                'M': pyobj[1],
                'D': pyobj[2],
                'h': pyobj[3],
                'm': pyobj[4],
                's': pyobj[5],
            }
            return self.format % d

        if ms > 999:
            raise ValueError, 'milliseconds must be a integer between 0 and 999'

        d = {
            'Y': pyobj[0],
            'M': pyobj[1],
            'D': pyobj[2],
            'h': pyobj[3],
            'm': pyobj[4],
            's': pyobj[5],
            'ms': ms,
        }
        return self.format_ms % d
Beispiel #15
0
    def convert1to2(self,
                    source,
                    ydata,
                    yname="",
                    yunit="",
                    zname="",
                    zunit=""):
        self.new(dimno=2, valno=1, dimsize=[source.DimSize[0], source.ValNo])
        self.Name = source.Name
        self.ShotNo = source.ShotNo
        self.SubNo = source.SubNo
        self.Date = _strftime("%m/%d/%Y %H:%M", _gmtime())
        self.DimName.append(source.DimName)
        self.DimName.append(yname)
        self.DimUnit.append(source.DimUnit)
        self.DimUnit.append(yunit)
        self.ValName.append(zname)
        self.ValUnit.append(zunit)
        self.comments = source.comments

        xx, yy = _np.meshgrid(source.data[:, 0], ydata)
        self.data[:, 0] = xx.reshape(_np.prod(self.DimSize), order='F')
        self.data[:, 1] = yy.reshape(_np.prod(self.DimSize), order='F')
        self.data[:, 2] = source.data[:, 1:].reshape(_np.prod(self.DimSize))
Beispiel #16
0
    def get_formatted_content(self, pyobj):
        if type(pyobj) in _floattypes or type(pyobj) in _inttypes:
            pyobj = _gmtime(pyobj)
        
        d = {}
        pyobj = tuple(pyobj)
        if 1 in [x < 0 for x in pyobj[0:6]]:
            pyobj = list(map(abs, pyobj))
            d['neg'] = '-'
        else:
            d['neg'] = ''

        ms = pyobj[6]
        if not ms: 
            d = { 'Y': pyobj[0], 'M': pyobj[1], 'D': pyobj[2],
                'h': pyobj[3], 'm': pyobj[4], 's': pyobj[5], }
            return self.format % d

        if  ms > 999:
            raise ValueError('milliseconds must be a integer between 0 and 999')

        d = { 'Y': pyobj[0], 'M': pyobj[1], 'D': pyobj[2],
            'h': pyobj[3], 'm': pyobj[4], 's': pyobj[5], 'ms':ms, }
        return self.format_ms % d
Beispiel #17
0
    def writeHeader(self, filename=None):
        self.Date = _strftime("%m/%d/%Y %H:%M", _gmtime())
        for ii in range(self.DimNo):
            if ii == 0:
                dimname = "'%s'" % self.DimName[ii]
                dimsize = "%d" % self.DimSize[ii]
                dimunit = "'%s'" % self.DimUnit[ii]
            else:
                dimname = dimname + ", '%s'" % self.DimName[ii]
                dimsize = dimsize + ", %d" % self.DimSize[ii]
                dimunit = dimunit + ", '%s'" % self.DimUnit[ii]
            # end if
        # end for range dimensions

        for ii in range(self.ValNo):
            if ii == 0:
                valname = "'%s'" % self.ValName[ii]
                valunit = "'%s'" % self.ValUnit[ii]
            else:
                valname = valname + ", '%s'" % self.ValName[ii]
                valunit = valunit + ", '%s'" % self.ValUnit[ii]
            # end if
        # end for in range value number

        if filename is None:
            """printing to stdout"""
            print("# [Parameters]")
            print("# Name = '%s'" % self.Name)
            print("# ShotNo = %d" % self.ShotNo)
            print("# SubNo = %d" % self.SubNo)
            print("# Date = '%s'" % self.Date)
            print("#")
            print("# DimNo = %d" % self.DimNo)
            print("# DimName = %s" % dimname)
            print("# DimSize = %s" % dimsize)
            print("# DimUnit = %s" % dimunit)
            print("#")
            print("# ValNo = %d" % self.ValNo)
            print("# ValName = %s" % valname)
            print("# ValUnit = %s" % valunit)
            print("#")
            print("# [Comments]")
            for line in self.comments:
                print("# %s" % line)
            print("#")
            print("# [Data]")
        else:
            """ printting into a file """
            try:
                with open(filename, 'w') as fp:
                    print("# [Parameters]", file=fp)
                    print("# Name = '%s'" % self.Name, file=fp)
                    print("# ShotNo = %d" % self.ShotNo, file=fp)
                    print("# SubNo = %d" % self.SubNo, file=fp)
                    print("# Date = '%s'" % self.Date, file=fp)
                    print("#", file=fp)
                    print("# DimNo = %d" % self.DimNo, file=fp)
                    print("# DimName = %s" % dimname, file=fp)
                    print("# DimSize = %s" % dimsize, file=fp)
                    print("# DimUnit = %s" % dimunit, file=fp)
                    print("#", file=fp)
                    print("# ValNo = %d" % self.ValNo, file=fp)
                    print("# ValName = %s" % valname, file=fp)
                    print("# ValUnit = %s" % valunit, file=fp)
                    print("#", file=fp)
                    print("# [Comments]", file=fp)
                    for line in self.comments:
                        print("# %s" % line, file=fp)
                    print("# filename = %s (written by egDataFormatIO)" %
                          filename,
                          file=fp)
                    print("#", file=fp)
                    print("# [Data]", file=fp)
                # end with open filename
            except:
                """ python2: when the with_statement fails """
                fp = open(filename, 'w')
                print("# [Parameters]", file=fp)
                print("# Name = '%s'" % self.Name, file=fp)
                print("# ShotNo = %d" % self.ShotNo, file=fp)
                print("# SubNo = %d" % self.SubNo, file=fp)
                print("# Date = '%s'" % self.Date, file=fp)
                print("#", file=fp)
                print("# DimNo = %d" % self.DimNo, file=fp)
                print("# DimName = %s" % dimname, file=fp)
                print("# DimSize = %s" % dimsize, file=fp)
                print("# DimUnit = %s" % dimunit, file=fp)
                print("#", file=fp)
                print("# ValNo = %d" % self.ValNo, file=fp)
                print("# ValName = %s" % valname, file=fp)
                print("# ValUnit = %s" % valunit, file=fp)
                print("#", file=fp)
                print("# [Comments]", file=fp)
                for line in self.comments:
                    print("# %s" % line, file=fp)
                print("# filename = %s (written by egDataFormatIO)" % filename,
                      file=fp)
                print("#", file=fp)
                print("# [Data]", file=fp)
                fp.close()
            finally:
                try:
                    fp.close()
                except:
                    pass
Beispiel #18
0
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
#  For any information, bug report, idea, donation, hug, beer, please contact
#    [email protected]
#
###############################################################################

from time import gmtime as _gmtime

_disclaimer = """ASTROOBS  Copyright (C) 2015-%s  Guillaume Schworer
This program comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it
under certain conditions.""" % _gmtime()[0]

print(_disclaimer)
"""
Provides astronomy ephemeris to plan telescope observations

.. note::
  * All altitudes, azimuth, hour angle are in degrees
  * However, ``horizon`` attribute of :class:`Observatory` or :class:`Observation` is in radian
  * All times are in UT, except for ``Observatory.localnight`` - obviously

.. warning::
  * it can occur that the Sun, the Moon or a target does not rise or set for an observatory/date combination. In that case, the corresponding attributes will be set to ``None``

Real-life example use:
>>> import astroobs as obs
Beispiel #19
0
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#   See the GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License,
#   'LICENSE.txt', along with this program.  If not, see 
#   <http://www.gnu.org/licenses/>.

import tosdb

from random import choice as _choice, randint as _randint
from time import sleep as _sleep, gmtime as _gmtime
from argparse import ArgumentParser as _ArgumentParser
from platform import system as _system

NEXT_YEAR = _gmtime().tm_year + 1

#expires 01/19/2018
SPY_CALL = '.SPY180119C250'

T_ITEMS = ['SPY','GOOG','QQQ','XLU','XLI','XLE','XLF','XLB','XLP','XLK',
            'MSFT','IWM',SPY_CALL]

T_TOPICS = [t.val for t in tosdb.TOPICS]
T_TOPICS.remove('NULL_TOPIC')

BSIZE = 100
BTIMEOUT = 3000
MAX_ADD = 7

args=None
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#   See the GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License,
#   'LICENSE.txt', along with this program.  If not, see
#   <http://www.gnu.org/licenses/>.

import tosdb

from random import choice as _choice, randint as _randint
from time import sleep as _sleep, gmtime as _gmtime
from argparse import ArgumentParser as _ArgumentParser
from platform import system as _system

NEXT_YEAR = _gmtime().tm_year + 1

#expires 01/19/2018
SPY_CALL = '.SPY180119C250'

T_ITEMS = [
    'SPY', 'GOOG', 'QQQ', 'XLU', 'XLI', 'XLE', 'XLF', 'XLB', 'XLP', 'XLK',
    'MSFT', 'IWM', SPY_CALL
]

T_TOPICS = [t.val for t in tosdb.TOPICS]
T_TOPICS.remove('NULL_TOPIC')

BSIZE = 100
BTIMEOUT = 3000
MAX_ADD = 7
Beispiel #21
0
#  GNU General Public License for more details.
#  
#  You should have received a copy of the GNU General Public License
#  along with this program.  If not, see <http://www.gnu.org/licenses/>.
#  
#  For any information, bug report, idea, donation, hug, beer, please contact
#    [email protected]
#
###############################################################################

from time import gmtime as _gmtime

_disclaimer = """ASTROOBS  Copyright (C) 2015-%s  Guillaume Schworer
This program comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it
under certain conditions.""" % _gmtime()[0]

print(_disclaimer)


"""
Provides astronomy ephemeris to plan telescope observations

.. note::
  * All altitudes, azimuth, hour angle are in degrees
  * However, ``horizon`` attribute of :class:`Observatory` or :class:`Observation` is in radian
  * All times are in UT, except for ``Observatory.localnight`` - obviously

.. warning::
  * it can occur that the Sun, the Moon or a target does not rise or set for an observatory/date combination. In that case, the corresponding attributes will be set to ``None``
Beispiel #22
0
def _db_parse_file_column(bytes_):
    ''' parse the plist in the file column of the Files table of iOS10+ backups '''

    # NOTE: using the plistlib parser failed, not sure why
    p = _biplist.readPlistFromString(bytes_)

    # check if we have the same fields as in our reference sample
    if set(p.keys()) != _known_plist_keys:
        raise PlistParseError(
            'someting in file column of Files table in Manifest.db changed')

    # we have only seen backups where $version, $archiver and $top have fixed
    # values, so raise exception when we hit some other value
    version = p.get('$version')
    if version != 100000:
        raise PlistParseError('$version != 100000')
    archiver = p.get('$archiver')
    if archiver != 'NSKeyedArchiver':
        raise PlistParseError('$archiver != NSKeyedArchiver')
    root_uid = p.get('$top').get('root')
    if root_uid.integer != 1:
        raise PlistParseError("$top['root'] != Uid(1)")

    # the interesting data is in the $objects field
    objects = p.get('$objects')
    # first field is expected to be $null
    if objects[0] != '$null':
        raise PlistParseError("$objects[0] != $null")

    # check if we have any new types of of fields
    #if len(set(objects[1].keys()) - _known_object_keys) != 0:
    #    raise PlistParseError("$objects[1] fields do not match known fields: {:s}".format(str(objects[1].keys())))

    uid = objects[1].get('UserID')
    # contents modification time
    mtime = _datetime(*list(_gmtime(objects[1].get('LastModified'))[0:7]) +
                      [_UTC])
    inode = objects[1].get('InodeNumber')
    mode = objects[1].get('Mode')
    # determine filetype and permissions based on mode
    filetype = FileType(mode & 0xE000)
    permissions = oct(mode & 0x1FFF)
    # metadata-change time
    ctime = _datetime(*list(_gmtime(objects[1].get('LastStatusChange'))[0:7]) +
                      [_UTC])
    gid = objects[1].get('GroupID')
    # birth-time (aka creation time)
    btime = _datetime(*list(_gmtime(objects[1].get('Birth'))[0:7]) + [_UTC])
    size = objects[1].get('Size')
    # not sure what this is
    protection = objects[1].get('ProtectionClass')

    # apparently since iOS11 the plist includes a field 'Flags' in the plist
    # field as well, but I've only seen value 0 in my backups
    if objects[1].get('Flags', 0) != 0:
        raise PearBackError('assumption on plist flags field broken')

    # the Uid stored in 'RelativePath' seems to point to index in 'objects'
    # where the actual value is stored. The Uid.integer property gives the
    # integer value
    relpath = objects[objects[1].get('RelativePath').integer]

    # something similar for the '$class', which seems to be 'MBFile' always
    class_ = objects[objects[1].get('$class').integer].get('$classname')
    if class_ != 'MBFile':
        raise PlistParseError('assumption broken: $class is not always MBFile')

    # extended attributes are not always present, but if they are, they seem to
    # be pointed to by the UID value in the 'ExtendedAttributes' fields. The
    # target item then contains a bplist with key-value pairs under the key
    # 'NS.data'
    if 'ExtendedAttributes' in objects[1]:
        ea_idx = objects[1]['ExtendedAttributes'].integer
        extended_attributes = _biplist.readPlistFromString(
            objects[ea_idx].get('NS.data'))
    else:
        extended_attributes = None

    # target is only available when type is a symlink and its value indicates
    # the index of the property in the $objects field
    if filetype == FileType.Symlink:
        if 'Target' not in objects[1]:
            raise PlistParseError('Assumption broken on symlinks')
        tgt_idx = objects[1]['Target'].integer
        linktarget = objects[tgt_idx]
    else:
        linktarget = None

    # digest is also not always present, it works similar as above two fields,
    # let's store hex string instead of bytes
    if 'Digest' in objects[1]:
        d_idx = objects[1]['Digest'].integer
        digest = objects[d_idx]
        if type(digest) == dict:
            digest = digest['NS.data']
            digest = _hexlify(digest).decode()
        else:
            digest = _hexlify(digest).decode()
    else:
        digest = None

    # convert to our named tuple and return object
    return _plistvals(uid, gid, mtime, ctime, btime, inode, mode, filetype,
                      permissions, size, protection, relpath,
                      extended_attributes, linktarget, digest)
Beispiel #23
0
def _parse_mbdb_entry(mbdb, pos):
    ''' parse a single entry in the mbdb file '''

    offset = pos
    domain, pos = _mbdb_string(mbdb, pos)
    filename, pos = _mbdb_string(mbdb, pos)
    linktarget, pos = _mbdb_string(mbdb, pos)
    # a simple test (N=1, scientific is it not?) shows that what is commonly
    # called 'datahash' in the scripts I used as basis for this, is stored in a
    # value that is called 'digest' in the newer (iOS10+) backups. So, we call
    # this 'digest' here as well.
    digest, pos = _mbdb_string(mbdb, pos)
    # this is commonly called enckey in the scripts that I used as source, but
    # in my backups it is consistently an empty string. So assume that it is,
    # break if it isn't.
    unknown, pos = _mbdb_string(mbdb, pos)
    if unknown != '':
        raise MbdbParseError(
            'assumption broken on empty string in unknown field')

    mode = int.from_bytes(mbdb[pos:pos + 2], 'big')
    pos += 2
    inode = int.from_bytes(mbdb[pos:pos + 8], 'big')
    pos += 8
    uid = int.from_bytes(mbdb[pos:pos + 4], 'big')
    pos += 4
    gid = int.from_bytes(mbdb[pos:pos + 4], 'big')
    pos += 4
    # some sources that I based this function on had a different
    # order for these timestamps and in addition instead of a
    # btime assumed an atime, which I think is incorrect based on some simple
    # experiments (comparing timestamps on a rooted phone with backup
    # timestamps).
    mtime = _datetime(
        *list(_gmtime(int.from_bytes(mbdb[pos:pos + 4], 'big'))[0:7]) + [_UTC])
    pos += 4
    ctime = _datetime(
        *list(_gmtime(int.from_bytes(mbdb[pos:pos + 4], 'big'))[0:7]) + [_UTC])
    pos += 4
    btime = _datetime(
        *list(_gmtime(int.from_bytes(mbdb[pos:pos + 4], 'big'))[0:7]) + [_UTC])
    pos += 4
    size = int.from_bytes(mbdb[pos:pos + 8], 'big')
    pos += 8
    # Based on the different values I've encountered in the field that is
    # commonly called 'flags' in the scripts that I've used as source it would
    # seem that this is what is called 'protection' in the newer backups.
    # Perhaps these values represent some enum value of the protection level.
    # So, I've called this field 'protection' in contrast to the other scripts
    # out there.
    protection = int.from_bytes(mbdb[pos:pos + 1], 'big')
    pos += 1
    numprops = int.from_bytes(mbdb[pos:pos + 1], 'big')
    pos += 1

    # determine filetype and permissions based on mode
    filetype = FileType(mode & 0xE000)
    permissions = oct(mode & 0x1FFF)

    extended_attributes = _OD()
    for ii in range(numprops):
        pname, pos = _mbdb_string(mbdb, pos)
        pval, pos = _mbdb_string(mbdb, pos)
        extended_attributes[pname] = pval

    # the fileID was originally stored in a separate mbdx file, but we can also
    # determine this by combining the domain and filepath and calculating sha1
    # hash over it
    fileID = _sha1('{:s}-{:s}'.format(domain,
                                      filename).encode('utf8')).hexdigest()

    return _file_entry(fileID, domain, filename, uid, gid, mtime, ctime, btime,
                       inode, mode, filetype, permissions, size, protection,
                       extended_attributes, linktarget, digest), pos