buildframework/helium/tools/iad/iadinfo.py
changeset 307 22ecbfc20eb4
parent 215 b61c19d4168d
parent 217 0f5e3a7fb6af
child 308 7830b8253b5a
equal deleted inserted replaced
215:b61c19d4168d 307:22ecbfc20eb4
     1 #============================================================================ 
       
     2 #Name        : iadinfo.py 
       
     3 #Part of     : Helium 
       
     4 
       
     5 #Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     6 #All rights reserved.
       
     7 #This component and the accompanying materials are made available
       
     8 #under the terms of the License "Eclipse Public License v1.0"
       
     9 #which accompanies this distribution, and is available
       
    10 #at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
    11 #
       
    12 #Initial Contributors:
       
    13 #Nokia Corporation - initial contribution.
       
    14 #
       
    15 #Contributors:
       
    16 #
       
    17 #Description:
       
    18 #===============================================================================
       
    19 
       
    20 import optparse
       
    21 import sys, os
       
    22 import struct
       
    23 import zlib
       
    24 import pdb
       
    25     
       
    26 PyASN1Availabe = True
       
    27 
       
    28 try :
       
    29     from pyasn1.codec.der import decoder
       
    30     from pyasn1.type import univ, base
       
    31 except :
       
    32     PyASN1Availabe = False
       
    33 
       
    34 def _findItem(item, itemParent, index, objectIdentifier) :
       
    35     if isinstance(item, base.AbstractSimpleAsn1Item) :
       
    36         if item == objectIdentifier :
       
    37             return itemParent[index + 1]
       
    38     else:
       
    39         for i in range(len(item)) :
       
    40             found = _findItem(item[i], item, i, objectIdentifier)
       
    41             if found: 
       
    42                 return found
       
    43 
       
    44 def findItem(decodedCert, objectIdentifier) :
       
    45     return _findItem(decodedCert, None, 0, objectIdentifier)
       
    46 
       
    47 
       
    48 class CertificateOrganization :
       
    49     def __init__(self) :
       
    50         pass
       
    51     
       
    52     def parse(self, decodedCert) :
       
    53         self.commonName = findItem(decodedCert, (2, 5, 4, 3))
       
    54         self.countryCode = findItem(decodedCert, (2, 5, 4, 6))
       
    55         self.locality = findItem(decodedCert, (2, 5, 4, 7))
       
    56         self.state = findItem(decodedCert, (2, 5, 4, 8))
       
    57         self.street = findItem(decodedCert, (2, 5, 4, 9))
       
    58         self.organization = findItem(decodedCert, (2, 5, 4, 10))
       
    59 
       
    60     def readableStr(self) :
       
    61         buf = ""
       
    62         if self.commonName :
       
    63             buf += self.commonName.prettyPrint() + "\n"
       
    64         if self.countryCode :
       
    65             buf += self.countryCode.prettyPrint() + "\n"
       
    66         if self.locality :
       
    67             buf += self.locality.prettyPrint() + "\n"
       
    68         if self.state :
       
    69             buf += self.state.prettyPrint() + "\n"
       
    70         if self.street :
       
    71             buf += self.street.prettyPrint() + "\n"
       
    72         if self.organization :
       
    73             buf += self.organization.prettyPrint()
       
    74         return buf
       
    75 
       
    76 class CertificateInfo :
       
    77     def __init__(self) :
       
    78         pass
       
    79         
       
    80     def parse(self, decodedCert) :
       
    81         self.issuer = CertificateOrganization()
       
    82         self.issuer.parse(decodedCert[0][3])
       
    83         
       
    84         self.signer = CertificateOrganization()
       
    85         self.signer.parse(decodedCert[0][5])
       
    86         
       
    87     def readableStr(self) :
       
    88         buf = "Signer:\n      " + "\n      ".join(self.signer.readableStr().split('\n')) + "\n"
       
    89         buf += "Issuer:\n      " + "\n      ".join(self.issuer.readableStr().split('\n')) + "\n"
       
    90         return buf
       
    91             
       
    92 
       
    93 class SISFileHeader :
       
    94     def __init__(self) :
       
    95         self.uid1 = 0
       
    96         self.uid2 = 0
       
    97         self.uid3 = 0
       
    98         self.uidChecksum = 0
       
    99 
       
   100 class SISField :
       
   101     def __init__(self) :
       
   102         self.type = 0
       
   103         self.length = None
       
   104         self.subFields = []
       
   105         
       
   106     def readFieldLength(self, fileReader) :
       
   107         length = fileReader.readBytesAsUint(4)
       
   108         if length & 0x80000000 > 0 :
       
   109             length = length << 32
       
   110             length |= fileReader.readBytesAsUint(4)
       
   111         return length
       
   112         
       
   113     def findField(self, fieldType, startIndex=0) :
       
   114         result = None
       
   115         index = startIndex
       
   116         
       
   117         for field in self.subFields[startIndex:] :
       
   118             if field.type == fieldType :
       
   119                 result = field
       
   120                 break
       
   121             ++ index
       
   122         return (result, index)
       
   123         
       
   124     def readableStr(self) :
       
   125         return ""
       
   126     
       
   127     def traverse(self, handler, depth=0) :
       
   128         handler.handleField(self, depth)
       
   129         for field in self.subFields :
       
   130             field.traverse(handler, depth + 1)
       
   131         
       
   132 class SISUnsupportedField(SISField) :
       
   133     def __init__(self) :
       
   134         SISField.__init__(self)
       
   135         
       
   136     def initFromFile(self, fileReader) :
       
   137         self.length = self.readFieldLength(fileReader)
       
   138         fileReader.readPlainBytes(self.length)
       
   139 
       
   140 class SISStringField(SISField) :
       
   141     def __init__(self) :
       
   142         SISField.__init__(self)
       
   143         self.data = None
       
   144         
       
   145     def initFromFile(self, fileReader) :
       
   146         self.length = self.readFieldLength(fileReader)
       
   147         buf = fileReader.readPlainBytes(self.length)
       
   148         self.data = u""
       
   149         while len(buf) > 0 :
       
   150             temp = buf[:2]
       
   151             buf = buf[2:]
       
   152             self.data += unichr(ord(temp[0]) | ord(temp[1]) << 8)
       
   153         
       
   154     def readableStr(self) :
       
   155         return self.data
       
   156         
       
   157 class SISArrayField(SISField) :
       
   158     def __init__(self) :
       
   159         SISField.__init__(self)
       
   160         
       
   161     def initFromFile(self, fileReader) :
       
   162         self.length = self.readFieldLength(fileReader)
       
   163         type = fileReader.readBytesAsInt(4)
       
   164         l = self.length - 4
       
   165         while l > 0 :
       
   166             field = SISFieldTypes[type]()
       
   167             field.type = type
       
   168             field.initFromFile(fileReader)
       
   169             self.subFields.append(field)
       
   170             
       
   171             l -= field.length + 4 # field length + the length field
       
   172             padding = fileReader.skipPadding()
       
   173             l -= padding
       
   174 
       
   175 class SISCompressedField(SISField) :
       
   176     def __init__(self) :
       
   177         SISField.__init__(self)
       
   178         self.algorithm = None
       
   179         self.uncompressedDataSize = None
       
   180         self.data = None
       
   181         
       
   182     def initFromFile(self, fileReader) :
       
   183         self.length = self.readFieldLength(fileReader)
       
   184         self.algorithm = fileReader.readBytesAsUint(4)
       
   185         self.uncompressedDataSize = fileReader.readBytesAsUint(8)
       
   186         data = fileReader.readPlainBytes(self.length - 4 - 8)
       
   187         if self.algorithm == 0 :
       
   188             self.data = data
       
   189         elif self.algorithm == 1 :
       
   190             self.data = zlib.decompress(data)
       
   191             
       
   192 class SISVersionField(SISField) :
       
   193     def __init__(self) :
       
   194         SISField.__init__(self)
       
   195         self.version = (- 1, - 1, - 1)
       
   196         
       
   197     def initFromFile(self, fileReader) :
       
   198         self.length = self.readFieldLength(fileReader)
       
   199         major = fileReader.readBytesAsInt(4)
       
   200         minor = fileReader.readBytesAsInt(4)
       
   201         build = fileReader.readBytesAsInt(4)
       
   202         self.version = (major, minor, build)
       
   203         
       
   204     def readableStr(self) :
       
   205         return str(self.version)
       
   206     
       
   207 class SISVersionRangeField(SISField) :
       
   208     def __init__(self) :
       
   209         SISField.__init__(self)
       
   210         self.fromVersion = None
       
   211         self.toVersion = None
       
   212         
       
   213     def initFromFile(self, fileReader) :
       
   214         self.length = self.readFieldLength(fileReader)
       
   215         fieldParser = SISFieldParser()
       
   216         self.fromVersion = fieldParser.parseField(fileReader)
       
   217         if self.length - fieldParser.lastReadBytes > 0  :
       
   218             self.toVersion = fieldParser.parseField(fileReader)
       
   219     
       
   220 class SISDateField(SISField) :
       
   221     def __init__(self) :
       
   222         SISField.__init__(self)
       
   223         self.year = None
       
   224         self.month = None
       
   225         self.day = None
       
   226         
       
   227     def initFromFile(self, fileReader) :
       
   228         self.length = self.readFieldLength(fileReader)
       
   229         self.year = fileReader.readBytesAsUint(2)
       
   230         self.month = fileReader.readBytesAsUint(1)
       
   231         self.day = fileReader.readBytesAsUint(1)
       
   232     
       
   233     def readableStr(self) :
       
   234         return str(self.year) + "." + str(self.month) + "." + str(self.day)
       
   235     
       
   236 class SISTimeField(SISField) :
       
   237     def __init__(self) :
       
   238         SISField.__init__(self)
       
   239         self.hours = None
       
   240         self.minutes = None
       
   241         self.seconds = None
       
   242         
       
   243     def initFromFile(self, fileReader) :
       
   244         self.length = self.readFieldLength(fileReader)
       
   245         self.hours = fileReader.readBytesAsUint(1)
       
   246         self.minutes = fileReader.readBytesAsUint(1)
       
   247         self.seconds = fileReader.readBytesAsUint(1)
       
   248     
       
   249     def readableStr(self) :
       
   250         return str(self.hours) + ":" + str(self.minutes) + ":" + str(self.seconds)
       
   251     
       
   252 class SISDateTimeField(SISField) :
       
   253     def __init__(self) :
       
   254         SISField.__init__(self)
       
   255         self.date = None
       
   256         self.time = None
       
   257         
       
   258     def initFromFile(self, fileReader) :
       
   259         self.length = self.readFieldLength(fileReader)
       
   260         fieldParser = SISFieldParser()
       
   261         self.date = fieldParser.parseField(fileReader)
       
   262         self.time = fieldParser.parseField(fileReader)
       
   263     
       
   264 class SISUidField(SISField) :
       
   265     def __init__(self) :
       
   266         SISField.__init__(self)
       
   267         self.uid = None
       
   268         
       
   269     def initFromFile(self, fileReader) :
       
   270         self.length = self.readFieldLength(fileReader)
       
   271         self.uid = fileReader.readBytesAsUint(4)
       
   272         
       
   273     def readableStr(self) :
       
   274         return hex(self.uid)
       
   275     
       
   276 class SISLanguageField(SISField) :
       
   277     def __init__(self) :
       
   278         SISField.__init__(self)
       
   279         self.language = None
       
   280         
       
   281     def initFromFile(self, fileReader) :
       
   282         self.length = self.readFieldLength(fileReader)
       
   283         self.language = fileReader.readBytesAsUint(4)
       
   284         
       
   285     def readableStr(self) :
       
   286         return str(self.language)
       
   287     
       
   288 class SISContentsField(SISField) :
       
   289     def __init__(self) :
       
   290         SISField.__init__(self)
       
   291         
       
   292     def initFromFile(self, fileReader) :
       
   293         self.length = self.readFieldLength(fileReader)
       
   294         fieldParser = SISFieldParser()
       
   295         field = fieldParser.parseField(fileReader)
       
   296         while field :
       
   297             if field.type == 3 : # compressed<conroller>
       
   298                 bufferReader = SISBufferReader(field.data)
       
   299                 field = fieldParser.parseField(bufferReader)
       
   300             self.subFields.append(field)
       
   301             field = fieldParser.parseField(fileReader)
       
   302 
       
   303 class SISControllerField(SISField) :
       
   304     def __init__(self) :
       
   305         SISField.__init__(self)
       
   306         
       
   307     def initFromFile(self, fileReader) :
       
   308         self.length = self.readFieldLength(fileReader)
       
   309         fieldParser = SISFieldParser()
       
   310         bufferReader = SISBufferReader(fileReader.readPlainBytes(self.length))
       
   311         field = fieldParser.parseField(bufferReader)
       
   312         while field :
       
   313             self.subFields.append(field)
       
   314             field = fieldParser.parseField(bufferReader)
       
   315 
       
   316 class SISInfoField(SISField) :
       
   317     def __init__(self) :
       
   318         SISField.__init__(self)
       
   319         self.installType = None
       
   320         self.installFlags = None
       
   321         
       
   322     def initFromFile(self, fileReader) :
       
   323         self.length = self.readFieldLength(fileReader)
       
   324         fieldParser = SISFieldParser()
       
   325         self.subFields.append(fieldParser.parseField(fileReader)) # UID
       
   326         self.subFields.append(fieldParser.parseField(fileReader)) # Vendor name unique
       
   327         self.subFields.append(fieldParser.parseField(fileReader)) # names
       
   328         self.subFields.append(fieldParser.parseField(fileReader)) # vendor names
       
   329         self.subFields.append(fieldParser.parseField(fileReader)) # version
       
   330         self.subFields.append(fieldParser.parseField(fileReader)) # creation time
       
   331         self.installType = fileReader.readBytesAsUint(1)
       
   332         self.installFlags = fileReader.readBytesAsUint(1) 
       
   333             
       
   334 class SISSupportedLanguagesField(SISField) :
       
   335     def __init__(self) :
       
   336         SISField.__init__(self)
       
   337         
       
   338     def initFromFile(self, fileReader) :
       
   339         self.length = self.readFieldLength(fileReader)
       
   340         fieldParser = SISFieldParser()
       
   341         self.subFields.append(fieldParser.parseField(fileReader)) # languages
       
   342         
       
   343 class SISSupportedOptionsField(SISField) :
       
   344     def __init__(self) :
       
   345         SISField.__init__(self)
       
   346         
       
   347     def initFromFile(self, fileReader) :
       
   348         self.length = self.readFieldLength(fileReader)
       
   349         fieldParser = SISFieldParser()
       
   350         self.subFields.append(fieldParser.parseField(fileReader)) # options
       
   351             
       
   352 class SISPrerequisitiesField(SISField) :
       
   353     def __init__(self) :
       
   354         SISField.__init__(self)
       
   355         
       
   356     def initFromFile(self, fileReader) :
       
   357         self.length = self.readFieldLength(fileReader)
       
   358         fieldParser = SISFieldParser()
       
   359         self.subFields.append(fieldParser.parseField(fileReader)) # target devices
       
   360         self.subFields.append(fieldParser.parseField(fileReader)) # dependencies
       
   361         
       
   362         
       
   363 class SISDependencyField(SISField) :
       
   364     def __init__(self) :
       
   365         SISField.__init__(self)
       
   366         
       
   367     def initFromFile(self, fileReader) :
       
   368         self.length = self.readFieldLength(fileReader)
       
   369         fieldParser = SISFieldParser()
       
   370         self.subFields.append(fieldParser.parseField(fileReader)) # UID
       
   371         field = fieldParser.parseField(fileReader)
       
   372         # Version range field is optional
       
   373         if field.type == VersionRangeField :
       
   374             self.subFields.append(field) # version range
       
   375             self.subFields.append(fieldParser.parseField(fileReader)) # dependency names
       
   376         else :
       
   377             self.subFields.append(field) # dependency names
       
   378     
       
   379 class SISPropertiesField(SISField) :
       
   380     def __init__(self) :
       
   381         SISField.__init__(self)
       
   382         
       
   383     def initFromFile(self, fileReader) :
       
   384         self.length = self.readFieldLength(fileReader)
       
   385         fieldParser = SISFieldParser()
       
   386         self.subFields.append(fieldParser.parseField(fileReader)) # properties
       
   387     
       
   388 class SISPropertyField(SISField) :
       
   389     def __init__(self) :
       
   390         SISField.__init__(self)
       
   391         self.key = None
       
   392         self.value = None
       
   393         
       
   394     def initFromFile(self, fileReader) :
       
   395         self.length = self.readFieldLength(fileReader)
       
   396         self.key = fileReader.readBytesAsInt(4)
       
   397         self.value = fileReader.readBytesAsInt(4)
       
   398     
       
   399 # There is a type for this field, but there is no definition of the field contents
       
   400 class SISSignaturesField(SISUnsupportedField) :
       
   401     pass
       
   402     
       
   403 class SISCertificateChainField(SISField) :
       
   404     def __init__(self) :
       
   405         SISField.__init__(self)
       
   406         
       
   407     def initFromFile(self, fileReader) :
       
   408         self.length = self.readFieldLength(fileReader)
       
   409         fieldParser = SISFieldParser()
       
   410         self.subFields.append(fieldParser.parseField(fileReader)) # certificate data
       
   411     
       
   412 class SISLogoField(SISField) :
       
   413     def __init__(self) :
       
   414         SISField.__init__(self)
       
   415 
       
   416     def initFromFile(self, fileReader) :
       
   417         self.length = self.readFieldLength(fileReader)
       
   418         fieldParser = SISFieldParser()
       
   419         self.subFields.append(fieldParser.parseField(fileReader)) # logo file
       
   420     
       
   421 class SISFileDescriptionField(SISField) :
       
   422     def __init__(self) :
       
   423         SISField.__init__(self)
       
   424         self.operation = None
       
   425         self.operationOptions = None
       
   426         self.compressedLength = None
       
   427         self.uncompressedLength = None
       
   428         self.fileIndex = None
       
   429         
       
   430     def initFromFile(self, fileReader) :
       
   431         self.length = self.readFieldLength(fileReader)
       
   432         fieldParser = SISFieldParser()
       
   433         
       
   434         self.subFields.append(fieldParser.parseField(fileReader))
       
   435         self.subFields.append(fieldParser.parseField(fileReader))
       
   436         field = fieldParser.parseField(fileReader)
       
   437         self.subFields.append(field)
       
   438         if field.type == 41 : # read field was capabilities ==> there is one more field left
       
   439             self.subFields.append(fieldParser.parseField(fileReader))
       
   440         
       
   441         self.operation = fileReader.readBytesAsUint(4)
       
   442         self.operationOptions = fileReader.readBytesAsUint(4)
       
   443         self.compressedLength = fileReader.readBytesAsUint(8)
       
   444         self.uncompressedLength = fileReader.readBytesAsUint(8)
       
   445         self.fileIndex = fileReader.readBytesAsUint(4)
       
   446         
       
   447     def readableStr(self) :
       
   448         return "index: " + str(self.fileIndex)
       
   449     
       
   450 class SISHashField(SISField) :
       
   451     def __init__(self) :
       
   452         SISField.__init__(self)
       
   453         self.algorithm = None
       
   454 
       
   455     def initFromFile(self, fileReader) :
       
   456         self.length = self.readFieldLength(fileReader)
       
   457         fieldParser = SISFieldParser()
       
   458         self.algorithm = fileReader.readBytesAsUint(4)
       
   459         self.subFields.append(fieldParser.parseField(fileReader)) # logo file
       
   460     
       
   461 class SISIfField(SISField) :
       
   462     def __init__(self) :
       
   463         SISField.__init__(self)
       
   464 
       
   465     def initFromFile(self, fileReader) :
       
   466         self.length = self.readFieldLength(fileReader)
       
   467         fieldParser = SISFieldParser()
       
   468         self.subFields.append(fieldParser.parseField(fileReader)) # expression
       
   469         self.subFields.append(fieldParser.parseField(fileReader)) # install block
       
   470         self.subFields.append(fieldParser.parseField(fileReader)) # else ifs
       
   471 
       
   472 class SISElseIfField(SISField) :
       
   473     def __init__(self) :
       
   474         SISField.__init__(self)
       
   475 
       
   476     def initFromFile(self, fileReader) :
       
   477         self.length = self.readFieldLength(fileReader)
       
   478         fieldParser = SISFieldParser()
       
   479         self.subFields.append(fieldParser.parseField(fileReader)) # expression
       
   480         self.subFields.append(fieldParser.parseField(fileReader)) # install block
       
   481     
       
   482 class SISInstallBlockField(SISField) :
       
   483     def __init__(self) :
       
   484         SISField.__init__(self)
       
   485         self.files = None
       
   486         self.embeddedSISFiles = None
       
   487         self.ifBlocks = None
       
   488         
       
   489     def initFromFile(self, fileReader) :
       
   490         self.length = self.readFieldLength(fileReader)
       
   491         fieldParser = SISFieldParser()
       
   492         self.subFields.append(fieldParser.parseField(fileReader))
       
   493         self.subFields.append(fieldParser.parseField(fileReader))
       
   494         self.subFields.append(fieldParser.parseField(fileReader))
       
   495 
       
   496 class SISExpressionField(SISField) :
       
   497     def __init__(self) :
       
   498         SISField.__init__(self)
       
   499         self.operator = None
       
   500         self.integerValue = None
       
   501         
       
   502     def initFromFile(self, fileReader) :
       
   503         self.length = self.readFieldLength(fileReader)
       
   504         fieldParser = SISFieldParser()
       
   505         self.operator = fileReader.readBytesAsUint(4)
       
   506         self.integerValue = fileReader.readBytesAsInt(4)
       
   507         
       
   508         if self.operator == 10 or self.operator == 13 :
       
   509             self.subFields.append(fieldParser.parseField(fileReader))
       
   510         if self.operator == 1 or self.operator == 2 or self.operator == 3 or self.operator == 4 or self.operator == 5 or self.operator == 6 or self.operator == 7 or self.operator == 8 or self.operator == 11 or self.operator == 12 :
       
   511             self.subFields.append(fieldParser.parseField(fileReader))
       
   512         if not (self.operator == 13 or self.operator == 14 or self.operator == 15 or self.operator == 16 or self.operator == 10) :
       
   513             self.subFields.append(fieldParser.parseField(fileReader))
       
   514         
       
   515 class SISDataField(SISField) :
       
   516     def __init__(self) :
       
   517         SISField.__init__(self)
       
   518         
       
   519     def initFromFile(self, fileReader) :
       
   520         self.length = self.readFieldLength(fileReader)
       
   521         fieldParser = SISFieldParser()
       
   522         self.subFields.append(fieldParser.parseField(fileReader)) # data units
       
   523     
       
   524 class SISDataUnitField(SISField) :
       
   525     def __init__(self) :
       
   526         SISField.__init__(self)
       
   527         
       
   528     def initFromFile(self, fileReader) :
       
   529         self.length = self.readFieldLength(fileReader)
       
   530         fieldParser = SISFieldParser()
       
   531         self.subFields.append(fieldParser.parseField(fileReader)) # file data
       
   532     
       
   533 class SISFileDataField(SISField) :
       
   534     def __init__(self) :
       
   535         SISField.__init__(self)
       
   536         
       
   537     def initFromFile(self, fileReader) :
       
   538         self.length = self.readFieldLength(fileReader)
       
   539         fieldParser = SISFieldParser()
       
   540         self.subFields.append(fieldParser.parseField(fileReader)) # raw file data
       
   541     
       
   542 class SISSupportedOptionField(SISField) :
       
   543     def __init__(self) :
       
   544         SISField.__init__(self)
       
   545         
       
   546     def initFromFile(self, fileReader) :
       
   547         self.length = self.readFieldLength(fileReader)
       
   548         fieldParser = SISFieldParser()
       
   549         self.subFields.append(fieldParser.parseField(fileReader)) # names
       
   550     
       
   551 class SISControllerChecksumField(SISField) :
       
   552     def __init__(self) :
       
   553         SISField.__init__(self)
       
   554         self.checksum = None
       
   555         
       
   556     def initFromFile(self, fileReader) :
       
   557         self.length = self.readFieldLength(fileReader)
       
   558         self.checksum = fileReader.readBytesAsUint(2)
       
   559     
       
   560 class SISDataChecksumField(SISField) :
       
   561     def __init__(self) :
       
   562         SISField.__init__(self)
       
   563         self.checksum = None
       
   564         
       
   565     def initFromFile(self, fileReader) :
       
   566         self.length = self.readFieldLength(fileReader)
       
   567         self.checksum = fileReader.readBytesAsUint(2)
       
   568     
       
   569 class SISSignatureField(SISField) :
       
   570     def __init__(self) :
       
   571         SISField.__init__(self)
       
   572         
       
   573     def initFromFile(self, fileReader) :
       
   574         self.length = self.readFieldLength(fileReader)
       
   575         fieldParser = SISFieldParser()
       
   576         self.subFields.append(fieldParser.parseField(fileReader)) # signature algorithm
       
   577         self.subFields.append(fieldParser.parseField(fileReader)) # signature data
       
   578     
       
   579 class SISBlobField(SISField) :
       
   580     def __init__(self) :
       
   581         SISField.__init__(self)
       
   582         self.data = None
       
   583         
       
   584     def initFromFile(self, fileReader) :
       
   585         self.length = self.readFieldLength(fileReader)
       
   586         self.data = fileReader.readPlainBytes(self.length)
       
   587     
       
   588 class SISSignatureAlgorithmField(SISField) :
       
   589     def __init__(self) :
       
   590         SISField.__init__(self)
       
   591         
       
   592     def initFromFile(self, fileReader) :
       
   593         self.length = self.readFieldLength(fileReader)
       
   594         fieldParser = SISFieldParser()
       
   595         self.subFields.append(fieldParser.parseField(fileReader)) # algorithm identifier
       
   596     
       
   597 class SISSignatureCertificateChainField(SISField) :
       
   598     def __init__(self) :
       
   599         SISField.__init__(self)
       
   600         
       
   601     def initFromFile(self, fileReader) :
       
   602         self.length = self.readFieldLength(fileReader)
       
   603         fieldParser = SISFieldParser()
       
   604         self.subFields.append(fieldParser.parseField(fileReader)) # signatures
       
   605         self.subFields.append(fieldParser.parseField(fileReader)) # certificate chain
       
   606     
       
   607 class SISDataIndexField(SISField) :
       
   608     def __init__(self) :
       
   609         SISField.__init__(self)
       
   610         self.dataIndex = None
       
   611         
       
   612     def initFromFile(self, fileReader) :
       
   613         self.length = self.readFieldLength(fileReader)
       
   614         self.dataIndex = fileReader.readBytesAsUint(4)
       
   615 
       
   616 class SISCapabilitiesField(SISField) :
       
   617     def __init__(self) :
       
   618         SISField.__init__(self)
       
   619         self.capabilities = 0
       
   620         self.readableCaps = []
       
   621         
       
   622     def initFromFile(self, fileReader) :
       
   623         self.length = self.readFieldLength(fileReader)
       
   624         self.capabilities = fileReader.readBytesAsUint(self.length)
       
   625         
       
   626         for i in range(20) :
       
   627             if (self.capabilities >> i) & 0x01 :
       
   628                 self.readableCaps.append(CapabilityNames[i])
       
   629                 
       
   630     def readableStr(self) :
       
   631         return " ".join(self.readableCaps)
       
   632     
       
   633 SISFieldTypes = { 
       
   634     1 : SISStringField,
       
   635     2 : SISArrayField,
       
   636     3 : SISCompressedField,
       
   637     4 : SISVersionField,
       
   638     5 : SISVersionRangeField,
       
   639     6 : SISDateField,
       
   640     7 : SISTimeField,
       
   641     8 : SISDateTimeField,
       
   642     9 : SISUidField,
       
   643     10 : SISUnsupportedField,
       
   644     11 : SISLanguageField,
       
   645     12 : SISContentsField,
       
   646     13 : SISControllerField,
       
   647     14 : SISInfoField,
       
   648     15 : SISSupportedLanguagesField,
       
   649     16 : SISSupportedOptionsField,
       
   650     17 : SISPrerequisitiesField,
       
   651     18 : SISDependencyField,
       
   652     19 : SISPropertiesField,
       
   653     20 : SISPropertyField,
       
   654     21 : SISSignaturesField,
       
   655     22 : SISCertificateChainField,
       
   656     23 : SISLogoField,
       
   657     24 : SISFileDescriptionField,
       
   658     25 : SISHashField,
       
   659     26 : SISIfField,
       
   660     27 : SISElseIfField,
       
   661     28 : SISInstallBlockField,
       
   662     29 : SISExpressionField,
       
   663     30 : SISDataField,
       
   664     31 : SISDataUnitField,
       
   665     32 : SISFileDataField,
       
   666     33 : SISSupportedOptionField,
       
   667     34 : SISControllerChecksumField,
       
   668     35 : SISDataChecksumField,
       
   669     36 : SISSignatureField,
       
   670     37 : SISBlobField,
       
   671     38 : SISSignatureAlgorithmField,
       
   672     39 : SISSignatureCertificateChainField,
       
   673     40 : SISDataIndexField,
       
   674     41 : SISCapabilitiesField
       
   675     }
       
   676 
       
   677 [StringField,
       
   678  ArrayField,
       
   679  CompressedField,
       
   680  VersionField,
       
   681  VersionRangeField,
       
   682  DateField,
       
   683  TimeField,
       
   684  DateTimeField,
       
   685  UidField,
       
   686  UnusedField,
       
   687  LanguageField,
       
   688  ContentsField,
       
   689  ControllerField,
       
   690  InfoField,
       
   691  SupportedLanguagesField,
       
   692  SupportedOptionsField,
       
   693  PrerequisitiesField,
       
   694  DependencyField,
       
   695  PropertiesField,
       
   696  PropertyField,
       
   697  SignaturesField,
       
   698  CertificateChainField,
       
   699  LogoField,
       
   700  FileDescriptionField,
       
   701  HashField,
       
   702  IfField,
       
   703  ElseIfField,
       
   704  InstallBlockField,
       
   705  ExpressionField,
       
   706  DataField,
       
   707  DataUnitField,
       
   708  FileDataField,
       
   709  SupportedOptionField,
       
   710  ControllerChecksumField,
       
   711  DataChecksumField,
       
   712  SignatureField,
       
   713  BlobField,
       
   714  SignatureAlgorithmField,
       
   715  SignatureCertificateChainField,
       
   716  DataIndexField,
       
   717  CapabilitiesField] = range(1, 42)
       
   718      
       
   719 FieldNames = {
       
   720  0 : "ROOT",
       
   721  StringField : "StringField",
       
   722  ArrayField : "ArrayField",
       
   723  CompressedField : "CompressedField",
       
   724  VersionField : "VersionField",
       
   725  VersionRangeField : "VersionRangeField",
       
   726  DateField : "DateField",
       
   727  TimeField : "TimeField",
       
   728  DateTimeField : "DateTimeField",
       
   729  UidField : "UidField",
       
   730  UnusedField : "UnusedField",
       
   731  LanguageField : "LanguageField",
       
   732  ContentsField : "ContentsField",
       
   733  ControllerField : "ControllerField",
       
   734  InfoField : "InfoField",
       
   735  SupportedLanguagesField : "SupportedLanguagesField",
       
   736  SupportedOptionsField : "SupportedOptionsField",
       
   737  PrerequisitiesField : "PrerequisitiesField",
       
   738  DependencyField : "DependencyField",
       
   739  PropertiesField : "PropertiesField",
       
   740  PropertyField : "PropertyField",
       
   741  SignaturesField : "SignaturesField",
       
   742  CertificateChainField : "CertificateChainField",
       
   743  LogoField : "LogoField",
       
   744  FileDescriptionField : "FileDescriptionField",
       
   745  HashField : "HashField",
       
   746  IfField : "IfField",
       
   747  ElseIfField : "ElseIfField",
       
   748  InstallBlockField : "InstallBlockField",
       
   749  ExpressionField : "ExpressionField",
       
   750  DataField : "DataField",
       
   751  DataUnitField : "DataUnitField",
       
   752  FileDataField : "FileDataField",
       
   753  SupportedOptionField : "SupportedOptionField",
       
   754  ControllerChecksumField : "ControllerChecksumField",
       
   755  DataChecksumField : "DataChecksumField",
       
   756  SignatureField : "SignatureField",
       
   757  BlobField : "BlobField",
       
   758  SignatureAlgorithmField : "SignatureAlgorithmField",
       
   759  SignatureCertificateChainField : "SignatureCertificateChainField",
       
   760  DataIndexField : "DataIndexField",
       
   761  CapabilitiesField : "CapabilitiesField"
       
   762 }
       
   763      
       
   764 CapabilityNames = {
       
   765     0 : "TCB",
       
   766     1 : "CommDD",
       
   767     2 : "PowerMgmt",
       
   768     3 : "MultimediaDD",
       
   769     4 : "ReadDeviceData",
       
   770     5 : "WriteDeviceData",
       
   771     6 : "DRM",
       
   772     7 : "TrustedUI",
       
   773     8 : "ProtServ",
       
   774     9 : "DiskAdmin",
       
   775     10 : "NetworkControl",
       
   776     11 : "AllFiles",
       
   777     12 : "SwEvent",
       
   778     13 : "NetworkServices",
       
   779     14 : "LocalServices",
       
   780     15 : "ReadUserData",
       
   781     16 : "WriteUserData",
       
   782     17 : "Location",
       
   783     18 : "SurroundingsDD",
       
   784     19 : "UserEnvironment"
       
   785     }
       
   786 
       
   787 InstallTypes = {
       
   788     0: "SA",
       
   789     1: "SP",
       
   790     2: "PU",
       
   791     3: "PA",
       
   792     4: "PP"
       
   793     }
       
   794     
       
   795 class SISReader :
       
   796     def __init__(self) :
       
   797         self.bytesRead = 0
       
   798         
       
   799     def readUnsignedBytes(self, numBytes) :
       
   800         buf = self.readPlainBytes(numBytes)
       
   801         if len(buf) < numBytes :
       
   802             return []
       
   803             
       
   804         format = ""
       
   805         for i in range(numBytes) :
       
   806             format += "B"
       
   807         return struct.unpack(format, buf)
       
   808     
       
   809     def readSignedBytes(self, numBytes) :
       
   810         buf = self.readPlainBytes(numBytes)
       
   811         if len(buf) < numBytes :
       
   812             return []
       
   813             
       
   814         format = ""
       
   815         for i in range(numBytes) :
       
   816             format += "b"
       
   817         return struct.unpack(format, buf)
       
   818         
       
   819     def readBytesAsUint(self, numBytes) :
       
   820         result = 0
       
   821         bytes = self.readUnsignedBytes(numBytes)
       
   822         if len(bytes) == numBytes :
       
   823             for i in range(numBytes) :
       
   824                 result |= bytes[i] << (i * 8)
       
   825         
       
   826         return result
       
   827         
       
   828     def readBytesAsInt(self, numBytes) :
       
   829         result = 0
       
   830         bytes = self.readSignedBytes(numBytes)
       
   831         if len(bytes) == numBytes :
       
   832             for i in range(numBytes) :
       
   833                 result |= bytes[i] << (i * 8)
       
   834         
       
   835         return result
       
   836         
       
   837     def skipPadding(self) :
       
   838         result = 0
       
   839         if self.bytesRead % 4 != 0 :
       
   840             paddingLength = 4 - self.bytesRead % 4
       
   841             self.readPlainBytes(paddingLength)
       
   842             result = paddingLength
       
   843             
       
   844         return result
       
   845 
       
   846     def readPlainBytes(self, numBytes) :
       
   847         pass
       
   848 
       
   849 class SISFileReader(SISReader) : 
       
   850     def __init__(self, inStream) :
       
   851         SISReader.__init__(self)
       
   852         self.inStream = inStream
       
   853         self.eof = False
       
   854         self.bytesRead = 0
       
   855 
       
   856     def readPlainBytes(self, numBytes) :
       
   857         if self.eof :
       
   858             return ""
       
   859             
       
   860         if numBytes == 0 :
       
   861             return ""
       
   862             
       
   863         buf = ""
       
   864         buf = self.inStream.read(numBytes)
       
   865         if len(buf) < numBytes :
       
   866             self.eof = True
       
   867             return ""
       
   868             
       
   869         self.bytesRead += numBytes
       
   870         
       
   871         return buf
       
   872 
       
   873     def isEof(self) :
       
   874         return self.eof
       
   875         
       
   876 class SISBufferReader(SISReader) :
       
   877     def __init__(self, buffer) :
       
   878         self.buffer = buffer
       
   879         self.bytesRead = 0
       
   880         
       
   881     def readPlainBytes(self, numBytes) :
       
   882         if self.isEof() :
       
   883             return ""
       
   884             
       
   885         if numBytes == 0 :
       
   886             return ""
       
   887             
       
   888         result = self.buffer[self.bytesRead:self.bytesRead + numBytes]
       
   889             
       
   890         self.bytesRead += numBytes
       
   891         
       
   892         return result
       
   893             
       
   894     def isEof(self) :
       
   895         return self.bytesRead >= len(self.buffer)
       
   896         
       
   897 class SISFieldParser :
       
   898     def __init__(self) :
       
   899         self.lastReadBytes = 0
       
   900         
       
   901     def parseField(self, fileReader) :
       
   902         """Reads the next field from the fileReader stream and returns it"""
       
   903         field = None
       
   904         self.lastReadBytes = 0
       
   905         type = fileReader.readBytesAsUint(4)
       
   906         self.lastReadBytes += 4
       
   907         if type != 0 :
       
   908             field = SISFieldTypes[type]()
       
   909             field.type = type
       
   910             field.initFromFile(fileReader)
       
   911             self.lastReadBytes += field.length + 4 # Field length + length field
       
   912             self.lastReadBytes += fileReader.skipPadding()
       
   913         return field
       
   914 
       
   915 class SISInfo(SISField) :
       
   916     def __init__(self) :
       
   917         SISField.__init__(self)
       
   918         self.fin = None
       
   919         self.fileHeader = SISFileHeader()
       
   920         
       
   921     def parse(self, filename) :
       
   922         fin = open(filename, 'rb')
       
   923         fileReader = SISFileReader(fin)
       
   924         self.parseHeader(fileReader)
       
   925         self.parseSISFields(fileReader)
       
   926         
       
   927     def parseHeader(self, fileReader) :
       
   928         self.fileHeader.uid1 = fileReader.readBytesAsUint(4)
       
   929         self.fileHeader.uid2 = fileReader.readBytesAsUint(4)
       
   930         self.fileHeader.uid3 = fileReader.readBytesAsUint(4)
       
   931         self.fileHeader.uidChecksum = fileReader.readBytesAsUint(4)
       
   932         
       
   933     def parseSISFields(self, fileReader) :
       
   934         parser = SISFieldParser()
       
   935         while not fileReader.isEof() :
       
   936             self.subFields.append(parser.parseField(fileReader))
       
   937 
       
   938 class Handler :
       
   939     def __init__(self) :
       
   940         self.files = []
       
   941         self.fileDatas = []
       
   942         self.signatureCertificateChains = []
       
   943         
       
   944     def handleField(self, field, depth) :
       
   945         if field.type == FileDescriptionField :
       
   946             self.files.append(field)
       
   947         elif field.type == FileDataField :
       
   948             self.fileDatas.append(field)
       
   949         elif field.type == SignatureCertificateChainField  :
       
   950             self.signatureCertificateChains.append(field)
       
   951 
       
   952     def execute(self, options) :
       
   953         for f in self.files :
       
   954             if options.info :
       
   955                 buf = "   " + f.findField(StringField)[0].readableStr()
       
   956                 caps = f.findField(CapabilitiesField)[0]
       
   957                 if caps :
       
   958                     buf += " [" + " ".join(f.findField(CapabilitiesField)[0].readableCaps) + "]"
       
   959                 print buf
       
   960             if options.extract :
       
   961                 parts = f.findField(StringField)[0].readableStr().split("\\")
       
   962                 if len(parts[len(parts) - 1]) > 0 :
       
   963                     path = os.path.abspath(options.extract)
       
   964                     path += os.sep + os.sep.join(parts[1: - 1])
       
   965                     if not os.path.exists(path) :
       
   966                         os.makedirs(path)
       
   967                     newFile = file(path + os.sep + parts[len(parts) - 1], "wb")
       
   968                     newFile.write(self.fileDatas[f.fileIndex].findField(CompressedField)[0].data)
       
   969                     newFile.close()
       
   970         for s in self.signatureCertificateChains :
       
   971             if options.certificate:
       
   972                 buf = s.findField(CertificateChainField)[0].subFields[0].data
       
   973                 print "Certificate chain:"
       
   974                 i = 1
       
   975                 while len(buf) > 0 :
       
   976                     print "   Certificate " + str(i) + ":"
       
   977                     i += 1
       
   978                     decoded = decoder.decode(buf)
       
   979                     cer = CertificateInfo()
       
   980                     cer.parse(decoded[0])
       
   981                     readableStr = cer.readableStr()
       
   982                     print "      " + "\n      ".join(readableStr.split('\n'))
       
   983                     buf = decoded[1]
       
   984             
       
   985 class ContentPrinter :
       
   986     def __init__(self) :
       
   987         pass
       
   988         
       
   989     def handleField(self, field, depth) :
       
   990         buf = ""
       
   991         for i in range(depth) :
       
   992             buf += "  "
       
   993         buf += FieldNames[field.type] + " "
       
   994         if len(field.readableStr()) > 0 :
       
   995             buf += field.readableStr()
       
   996         print buf
       
   997 
       
   998 class IADHandler :
       
   999     def __init__(self) :
       
  1000         self.packageVersion = (0, 0, 0)
       
  1001         self.packageUid = 0
       
  1002         self.vendorName = ""
       
  1003         self.packageNames = []
       
  1004         self.packageNamesFields = []
       
  1005         self.languages = []
       
  1006         self.platformDependencies = []
       
  1007         self.packageDependencies = []
       
  1008         self.installType = 0
       
  1009         self.installFlags = 0
       
  1010         
       
  1011     def handleDependency(self, field) :
       
  1012         dep = [0, - 1, - 1, - 1, - 1, - 1, - 1]
       
  1013         dep[0] = field.subFields[0].uid
       
  1014         if field.subFields[1] and field.subFields[1].type == VersionRangeField :
       
  1015             r = field.subFields[1]
       
  1016             if r.fromVersion != None :
       
  1017                 dep[1] = r.fromVersion.version[0]
       
  1018                 dep[2] = r.fromVersion.version[1]
       
  1019                 dep[3] = r.fromVersion.version[2]
       
  1020             if r.toVersion != None :
       
  1021                 dep[4] = r.toVersion.version[0]
       
  1022                 dep[5] = r.toVersion.version[1]
       
  1023                 dep[6] = r.toVersion.version[2]
       
  1024         return dep
       
  1025         
       
  1026     def handleField(self, field, depth) :
       
  1027         if field.type == InfoField :
       
  1028             self.packageVersion = field.subFields[4].version
       
  1029             self.packageVersionField = field.subFields[4]
       
  1030             self.packageUid = field.subFields[0].uid
       
  1031             self.packageUidField = field.subFields[0]
       
  1032             self.vendorName = field.subFields[1].data
       
  1033             self.vendorNameField = field.subFields[1]
       
  1034             self.installType = field.installType
       
  1035             self.installFlags = field.installFlags
       
  1036             for name in field.subFields[2].subFields :
       
  1037                 self.packageNames.append(name.data)
       
  1038         elif field.type == LanguageField :
       
  1039             self.languages.append(field.language)
       
  1040         elif field.type == PrerequisitiesField :
       
  1041             for f in field.subFields[0].subFields :
       
  1042                 dependency = self.handleDependency(f)
       
  1043                 self.platformDependencies.append(dependency)
       
  1044             for f in field.subFields[1].subFields :
       
  1045                 dependency = self.handleDependency(f)
       
  1046                 self.packageDependencies.append(dependency)
       
  1047         
       
  1048     def getInfo (self, fileName) :
       
  1049         sisInfo = SISInfo()
       
  1050         sisInfo.parse(fileName)
       
  1051         handler = IADHandler()
       
  1052         sisInfo.traverse(handler)
       
  1053         info = "<sisinfo>\n" \
       
  1054              + "  <uid>" + hex(handler.packageUid) + "</uid>\n" \
       
  1055              + "  <vendor>" + handler.vendorName + "</vendor>\n" \
       
  1056              + "  <version>" \
       
  1057              + "<major>" + repr(handler.packageVersion[0]) + "</major>" \
       
  1058              + "<minor>" + repr(handler.packageVersion[1]) + "</minor>" \
       
  1059              + "<build>" + repr(handler.packageVersion[2]) + "</build>" \
       
  1060              + "</version>\n" \
       
  1061              + "  <type>" + InstallTypes[self.installType] + "</type>\n"
       
  1062         for num, name in enumerate(handler.packageNames) :
       
  1063             info += "  <name language='" + repr(handler.languages[num]) + "'>" + name + "</name>\n"
       
  1064         for language in handler.languages :
       
  1065             info += "  <language>" + repr(language) + "</language>\n"
       
  1066         for platDep in handler.platformDependencies :
       
  1067             info += "  <platform_dependency><uid>" + hex(platDep[0]) + "</uid>\n"
       
  1068             info += "    <from>" \
       
  1069                  + "<major>" + repr(platDep[1]) + "</major>" \
       
  1070                  + "<minor>" + repr(platDep[2]) + "</minor>"
       
  1071 #           info += "<build>" + repr(platDep[3]) + "</build>"
       
  1072             info += "</from>\n    <to>" \
       
  1073                  + "<major>" + repr(platDep[4]) + "</major>" \
       
  1074                  + "<minor>" + repr(platDep[5]) + "</minor>"
       
  1075 #           info += "<build>" + repr(platDep[6]) + "</build>"
       
  1076             info += "</to>\n" \
       
  1077              + "  </platform_dependency>\n"
       
  1078         for packageDep in handler.packageDependencies :
       
  1079             info += "  <package_dependency><uid>" + hex(packageDep[0]) + "</uid>\n"
       
  1080             info += "    <from>" \
       
  1081                  + "<major>" + repr(packageDep[1]) + "</major>" \
       
  1082                  + "<minor>" + repr(packageDep[2]) + "</minor>"
       
  1083 #           info += "<build>" + repr(packageDep[3]) + "</build>"
       
  1084             info += "</from>\n    <to>" \
       
  1085                  + "<major>" + repr(packageDep[4]) + "</major>" \
       
  1086                  + "<minor>" + repr(packageDep[5]) + "</minor>"
       
  1087 #           info += "<build>" + repr(packageDep[6]) + "</build>"
       
  1088             info += "</to>\n" \
       
  1089                  + "  </package_dependency>\n"
       
  1090         info += "</sisinfo>\n"
       
  1091         return info
       
  1092 
       
  1093 if __name__ == "__main__" :
       
  1094     handler = IADHandler()
       
  1095     print (handler.getInfo (sys.argv[1]))