def makeinstallblock(files = [], embeddedsisfiles = [], ifblocks = []): '''Make a SISInstallBlock SISField out of the given lists of SISFields. makeinstallblock(...) -> SISInstallBlock files a list of SISFileDescription SISFields (normal files) embeddedsisfiles a list of SISController SISFields (embedded SIS files) ifblocks a list of SISIf SISFields (conditionally installed files) SISInstallBlock the returned SISInstallBlock instance NOTE: Any of the lists may be empty (and are, by default).''' # Convert lists to SISArrays. sa1 = sisfield.SISArray(SISFields = files, SISFieldType = "SISFileDescription") sa2 = sisfield.SISArray(SISFields = embeddedsisfiles, SISFieldType = "SISController") sa3 = sisfield.SISArray(SISFields = ifblocks, SISFieldType = "SISIf") # Create a SISInstallBlock SISField and return it. return sisfield.SISInstallBlock(Files = sa1, EmbeddedSISFiles = sa2, IfBlocks = sa3)
def makelangconditional(languages, langdepfiles): '''Make a SISIf and SISElseIfs for language dependent installation of files. makelangconditional(...) -> SISIf or None languages a list of language numbers (not names, IDs or SISLanguages) landepfiles a list of file lists, where each file list is a list of alternative SISFileDescription SISFields for each language SISIf the returned SISIf instance or None if no files''' if len(langdepfiles) == 0: # No language dependent files, leave. return None # Create a file list per language. filesperlang = [] for n in xrange(len(languages)): filesperlang.append([]) # Gather all files from the same language to a single list. for files in langdepfiles: if len(files) != len(languages): raise ValueError("%d files given but number of languages is %d" % (len(files), len(languages))) for n in xrange(len(languages)): filesperlang[n].append(files[n]) if len(languages) == 0: # No languages, leave. (This is down here so that errors # can still be caught above.) return None # Create a SISArray of SISElseIf SISFields. elseiffields = [] for n in xrange(1, len(languages)): elseifexpfield = parseexpression("language == %d" % languages[n]) elseiffield = sisfield.SISElseIf(Expression=elseifexpfield, InstallBlock=makeinstallblock( filesperlang[n])) elseiffields.append(elseiffield) elseiffieldarray = sisfield.SISArray(SISFields=elseiffields, SISFieldType="SISElseIf") # Create and return the final SISIf SISField. ifexpfield = parseexpression("language == %d" % languages[0]) return sisfield.SISIf(Expression=ifexpfield, InstallBlock=makeinstallblock(filesperlang[0]), ElseIfs=elseiffieldarray)
def makedependency(uid, fromversion, toversion, names): '''Make a SISDependency SISField for the given UID, version dependency. makedependency(...) -> SISDependency uid UID, an unsigned integer fromversion from-version, a triple-item list/tuple (major, minor, build) toversion to-version, a triple-item list/tuple or None names names for the dependency, a list of string per language SISDependency the returned SISDependency SISField NOTE: toversion may be None, indicating any version after fromversion.''' # Convert parameters to SISFields. uidfield = sisfield.SISUid(UID1=uid) fromverfield = sisfield.SISVersion(Major=fromversion[0], Minor=fromversion[1], Build=fromversion[2]) if toversion != None: toverfield = sisfield.SISVersion(Major=toversion[0], Minor=toversion[1], Build=toversion[2]) else: toverfield = None verrangefield = sisfield.SISVersionRange(FromVersion=fromverfield, ToVersion=toverfield) l = [] for name in names: l.append(sisfield.SISString(String=name)) namesfield = sisfield.SISArray(SISFields=l, SISFieldType="SISString") # Create a SISDependency SISField and return it. return sisfield.SISDependency(UID=uidfield, VersionRange=verrangefield, DependencyNames=namesfield)
def run(pgmname, argv): global debug # Determine system character encodings. try: # getdefaultlocale() may sometimes return None. # Fall back to ASCII encoding in that case. terminalenc = locale.getdefaultlocale()[1] + "" except TypeError: # Invalid locale, fall back to ASCII terminal encoding. terminalenc = "ascii" try: # sys.getfilesystemencoding() was introduced in Python v2.3 and # it can sometimes return None. Fall back to ASCII if something # goes wrong. filesystemenc = sys.getfilesystemencoding() + "" except (AttributeError, TypeError): filesystemenc = "ascii" try: gopt = getopt.gnu_getopt except: # Python <v2.3, GNU-style parameter ordering not supported. gopt = getopt.getopt # Parse command line arguments. short_opts = "ua:k:p:b:d:e:vh" long_opts = [ "unsign", "cert=", "privkey=", "passphrase=", "execaps=", "dllcaps=", "encoding=", "verbose", "debug", "help" ] args = gopt(argv, short_opts, long_opts) opts = dict(args[0]) pargs = args[1] if len(pargs) == 0: raise ValueError("no SIS file name given") # Override character encoding of command line and filesystem. encs = opts.get("--encoding", opts.get("-e", "%s,%s" % (terminalenc, filesystemenc))) try: terminalenc, filesystemenc = encs.split(",") except (ValueError, TypeError): raise ValueError("invalid encoding string '%s'" % encs) # Get input SIS file name. infile = pargs[0].decode(terminalenc).encode(filesystemenc) # Determine output SIS file name. if len(pargs) == 1: # No output file, overwrite original SIS file. outfile = infile elif len(pargs) == 2: outfile = pargs[1].decode(terminalenc).encode(filesystemenc) if os.path.isdir(outfile): # Output to directory, use input file name. outfile = os.path.join(outfile, os.path.basename(infile)) else: raise ValueError("wrong number of arguments") # Get unsign option. unsign = False if "--unsign" in opts.keys() or "-u" in opts.keys(): unsign = True # Get certificate and its private key file names. cert = opts.get("--cert", opts.get("-a", None)) privkey = opts.get("--privkey", opts.get("-k", None)) if unsign: if cert != None or privkey != None: raise ValueError("certificate or private key given when unsigning") elif cert != None and privkey != None: # Convert file names from terminal encoding to filesystem encoding. cert = cert.decode(terminalenc).encode(filesystemenc) privkey = privkey.decode(terminalenc).encode(filesystemenc) # Read certificate file. f = file(cert, "rb") certdata = f.read(MAXCERTIFICATELENGTH + 1) f.close() if len(certdata) > MAXCERTIFICATELENGTH: raise ValueError("certificate file too large") # Read private key file. f = file(privkey, "rb") privkeydata = f.read(MAXPRIVATEKEYLENGTH + 1) f.close() if len(privkeydata) > MAXPRIVATEKEYLENGTH: raise ValueError("private key file too large") elif cert == None and privkey == None: # No certificate given, use the Ensymble default certificate. # defaultcert.py is not imported when not needed. This speeds # up program start-up a little. import defaultcert certdata = defaultcert.cert privkeydata = defaultcert.privkey print( "%s: warning: no certificate given, using " "insecure built-in one" % pgmname) else: raise ValueError("missing certificate or private key") # Get pass phrase. Pass phrase remains in terminal encoding. passphrase = opts.get("--passphrase", opts.get("-p", None)) if passphrase == None and privkey != None: # Private key given without "--passphrase" option, ask it. if sys.stdin.isatty(): # Standard input is a TTY, ask password interactively. passphrase = getpass.getpass("Enter private key pass phrase:") else: # Not connected to a TTY, read stdin non-interactively instead. passphrase = sys.stdin.read(MAXPASSPHRASELENGTH + 1) if len(passphrase) > MAXPASSPHRASELENGTH: raise ValueError("pass phrase too long") passphrase = passphrase.strip() # Get EXE capabilities and normalize the names. execaps = opts.get("--execaps", opts.get("-b", None)) if execaps != None: execapmask = symbianutil.capstringtomask(execaps) execaps = symbianutil.capmasktostring(execapmask, True) else: execapmask = None # Get DLL capabilities and normalize the names. dllcaps = opts.get("--dllcaps", opts.get("-d", None)) if dllcaps != None: dllcapmask = symbianutil.capstringtomask(dllcaps) dllcaps = symbianutil.capmasktostring(dllcapmask, True) else: dllcapmask = None # Determine verbosity. verbose = False if "--verbose" in opts.keys() or "-v" in opts.keys(): verbose = True # Determine if debug output is requested. if "--debug" in opts.keys(): debug = True # Enable debug output for OpenSSL-related functions. cryptutil.setdebug(True) # Ingredients for successful SIS generation: # # terminalenc Terminal character encoding (autodetected) # filesystemenc File system name encoding (autodetected) # infile Input SIS file name, filesystemenc encoded # outfile Output SIS file name, filesystemenc encoded # cert Certificate in PEM format # privkey Certificate private key in PEM format # passphrase Pass phrase of priv. key, terminalenc encoded string # execaps, execapmask Capability names and bitmask for EXE files or None # dllcaps, dllcapmask Capability names and bitmask for DLL files or None # verbose Boolean indicating verbose terminal output if verbose: print print "Input SIS file %s" % ( infile.decode(filesystemenc).encode(terminalenc)) print "Output SIS file %s" % ( outfile.decode(filesystemenc).encode(terminalenc)) if unsign: print "Remove signatures Yes" else: print "Certificate %s" % ( (cert and cert.decode(filesystemenc).encode(terminalenc)) or "<default>") print "Private key %s" % ( (privkey and privkey.decode(filesystemenc).encode(terminalenc)) or "<default>") if execaps != None: print "EXE capabilities 0x%x (%s)" % (execapmask, execaps) else: print "EXE capabilities <not set>" if dllcaps != None: print "DLL capabilities 0x%x (%s)" % (dllcapmask, dllcaps) else: print "DLL capabilities <not set>" print # Read input SIS file. f = file(infile, "rb") instring = f.read(MAXSISFILESIZE + 1) f.close() if len(instring) > MAXSISFILESIZE: raise ValueError("input SIS file too large") # Convert input SIS file to SISFields. uids = instring[:16] # UID1, UID2, UID3 and UIDCRC insis, rlen = sisfield.SISField(instring[16:], False) # Ignore extra bytes after SIS file. if len(instring) > (rlen + 16): print("%s: warning: %d extra bytes after input SIS file (ignored)" % (pgmname, (len(instring) - (rlen + 16)))) # Try to release some memory early. del instring # Check if there are embedded SIS files. Warn if there are. if len(insis.Data.DataUnits) > 1: print( "%s: warning: input SIS file contains " "embedded SIS files (ignored)" % pgmname) # Modify EXE- and DLL-files according to new capabilities. if execaps != None or dllcaps != None: # Generate FileIndex to SISFileDescription mapping. sisfiledescmap = mapfiledesc(insis.Controller.Data.InstallBlock) exemods, dllmods = modifycaps(insis, sisfiledescmap, execapmask, dllcapmask) print( "%s: %d EXE-files will be modified, " "%d DLL-files will be modified" % (pgmname, exemods, dllmods)) # Temporarily remove the SISDataIndex SISField from SISController. ctrlfield = insis.Controller.Data didxfield = ctrlfield.DataIndex ctrlfield.DataIndex = None if not unsign: # Remove old signatures. if len(ctrlfield.getsignatures()) > 0: print( "%s: warning: removing old signatures " "from input SIS file" % pgmname) ctrlfield.setsignatures([]) # Calculate a signature of the modified SISController. string = ctrlfield.tostring() string = sisfield.stripheaderandpadding(string) signature, algoid = sisfile.signstring(privkeydata, passphrase, string) # Create a SISCertificateChain SISField from certificate data. sf1 = sisfield.SISBlob(Data=cryptutil.certtobinary(certdata)) sf2 = sisfield.SISCertificateChain(CertificateData=sf1) # Create a SISSignature SISField from calculated signature. sf3 = sisfield.SISString(String=algoid) sf4 = sisfield.SISSignatureAlgorithm(AlgorithmIdentifier=sf3) sf5 = sisfield.SISBlob(Data=signature) sf6 = sisfield.SISSignature(SignatureAlgorithm=sf4, SignatureData=sf5) # Create a new SISSignatureCertificateChain SISField. sa = sisfield.SISArray(SISFields=[sf6]) sf7 = sisfield.SISSignatureCertificateChain(Signatures=sa, CertificateChain=sf2) # Set new certificate. ctrlfield.Signature0 = sf7 else: # Unsign, remove old signatures. ctrlfield.setsignatures([]) # Restore data index. ctrlfield.DataIndex = didxfield # Convert SISFields to string. outstring = insis.tostring() # Write output SIS file. f = file(outfile, "wb") f.write(uids) f.write(outstring) f.close()
def run(pgmname, argv): global debug # Determine system character encodings. try: # getdefaultlocale() may sometimes return None. # Fall back to ASCII encoding in that case. terminalenc = locale.getdefaultlocale()[1] + "" except TypeError: # Invalid locale, fall back to ASCII terminal encoding. terminalenc = "ascii" try: # sys.getfilesystemencoding() was introduced in Python v2.3 and # it can sometimes return None. Fall back to ASCII if something # goes wrong. filesystemenc = sys.getfilesystemencoding() + "" except (AttributeError, TypeError): filesystemenc = "ascii" try: gopt = getopt.gnu_getopt except: # Python <v2.3, GNU-style parameter ordering not supported. gopt = getopt.getopt # Parse command line arguments. short_opts = "a:k:p:e:vh" long_opts = [ "cert=", "privkey=", "passphrase=", "encoding=", "verbose", "debug", "help" ] args = gopt(argv, short_opts, long_opts) opts = dict(args[0]) pargs = args[1] if len(pargs) < 2: raise ValueError("wrong number of arguments") # Override character encoding of command line and filesystem. encs = opts.get("--encoding", opts.get("-e", "%s,%s" % (terminalenc, filesystemenc))) try: terminalenc, filesystemenc = encs.split(",") except (ValueError, TypeError): raise ValueError("invalid encoding string '%s'" % encs) # Get input SIS file names. infiles = [f.decode(terminalenc).encode(filesystemenc) for f in pargs[:-1]] # Determine output SIS file name. outfile = pargs[-1].decode(terminalenc).encode(filesystemenc) if os.path.isdir(outfile): # Output to directory, use input file name. outfile = os.path.join(outfile, os.path.basename(infiles[0])) # Get certificate and its private key file names. cert = opts.get("--cert", opts.get("-a", None)) privkey = opts.get("--privkey", opts.get("-k", None)) if cert != None and privkey != None: # Convert file names from terminal encoding to filesystem encoding. cert = cert.decode(terminalenc).encode(filesystemenc) privkey = privkey.decode(terminalenc).encode(filesystemenc) # Read certificate file. f = file(cert, "rb") certdata = f.read(MAXCERTIFICATELENGTH + 1) f.close() if len(certdata) > MAXCERTIFICATELENGTH: raise ValueError("certificate file too large") # Read private key file. f = file(privkey, "rb") privkeydata = f.read(MAXPRIVATEKEYLENGTH + 1) f.close() if len(privkeydata) > MAXPRIVATEKEYLENGTH: raise ValueError("private key file too large") elif cert == None and privkey == None: # No certificate given, use the Ensymble default certificate. # defaultcert.py is not imported when not needed. This speeds # up program start-up a little. import defaultcert certdata = defaultcert.cert privkeydata = defaultcert.privkey print( "%s: warning: no certificate given, using " "insecure built-in one" % pgmname) else: raise ValueError("missing certificate or private key") # Get pass phrase. Pass phrase remains in terminal encoding. passphrase = opts.get("--passphrase", opts.get("-p", None)) if passphrase == None and privkey != None: # Private key given without "--passphrase" option, ask it. if sys.stdin.isatty(): # Standard input is a TTY, ask password interactively. passphrase = getpass.getpass("Enter private key pass phrase:") else: # Not connected to a TTY, read stdin non-interactively instead. passphrase = sys.stdin.read(MAXPASSPHRASELENGTH + 1) if len(passphrase) > MAXPASSPHRASELENGTH: raise ValueError("pass phrase too long") passphrase = passphrase.strip() # Determine verbosity. verbose = False if "--verbose" in opts.keys() or "-v" in opts.keys(): verbose = True # Determine if debug output is requested. if "--debug" in opts.keys(): debug = True # Enable debug output for OpenSSL-related functions. cryptutil.setdebug(True) # Ingredients for successful SIS generation: # # terminalenc Terminal character encoding (autodetected) # filesystemenc File system name encoding (autodetected) # infiles A list of input SIS file names, filesystemenc encoded # outfile Output SIS file name, filesystemenc encoded # cert Certificate in PEM format # privkey Certificate private key in PEM format # passphrase Pass phrase of priv. key, terminalenc encoded string # verbose Boolean indicating verbose terminal output if verbose: print print "Input SIS files %s" % " ".join( [f.decode(filesystemenc).encode(terminalenc) for f in infiles]) print "Output SIS file %s" % ( outfile.decode(filesystemenc).encode(terminalenc)) print "Certificate %s" % ( (cert and cert.decode(filesystemenc).encode(terminalenc)) or "<default>") print "Private key %s" % ( (privkey and privkey.decode(filesystemenc).encode(terminalenc)) or "<default>") print insis = [] for n in xrange(len(infiles)): # Read input SIS files. f = file(infiles[n], "rb") instring = f.read(MAXSISFILESIZE + 1) f.close() if len(instring) > MAXSISFILESIZE: raise ValueError("%s: input SIS file too large" % infiles[n]) if n == 0: # Store UIDs for later use. uids = instring[:16] # UID1, UID2, UID3 and UIDCRC # Convert input SIS file to SISFields. sf, rlen = sisfield.SISField(instring[16:], False) # Ignore extra bytes after SIS file. if len(instring) > (rlen + 16): print("%s: %s: warning: %d extra bytes after SIS file (ignored)" % (pgmname, infiles[n], (len(instring) - (rlen + 16)))) # Try to release some memory early. del instring # Check that there are no embedded SIS files. if len(sf.Data.DataUnits) > 1: raise ValueError("%s: input SIS file contains " "embedded SIS files" % infiles[n]) insis.append(sf) # Temporarily remove the SISDataIndex SISField from the first SISController. ctrlfield = insis[0].Controller.Data didxfield = ctrlfield.DataIndex ctrlfield.DataIndex = None # Remove old signatures from the first SIS file. if len(ctrlfield.getsignatures()) > 0: print( "%s: warning: removing old signatures " "from the first input SIS file" % pgmname) ctrlfield.setsignatures([]) for n in xrange(1, len(insis)): # Append SISDataUnit SISFields into SISData array of the first SIS file. insis[0].Data.DataUnits.append(insis[n].Data.DataUnits[0]) # Set data index in SISController SISField. insis[n].Controller.Data.DataIndex.DataIndex = n # Embed SISController into SISInstallBlock of the first SIS file. ctrlfield.InstallBlock.EmbeddedSISFiles.append( insis[n].Controller.Data) # Calculate a signature of the modified SISController. string = ctrlfield.tostring() string = sisfield.stripheaderandpadding(string) signature, algoid = sisfile.signstring(privkeydata, passphrase, string) # Create a SISCertificateChain SISField from certificate data. sf1 = sisfield.SISBlob(Data=cryptutil.certtobinary(certdata)) sf2 = sisfield.SISCertificateChain(CertificateData=sf1) # Create a SISSignature SISField from calculated signature. sf3 = sisfield.SISString(String=algoid) sf4 = sisfield.SISSignatureAlgorithm(AlgorithmIdentifier=sf3) sf5 = sisfield.SISBlob(Data=signature) sf6 = sisfield.SISSignature(SignatureAlgorithm=sf4, SignatureData=sf5) # Create a new SISSignatureCertificateChain SISField. sa = sisfield.SISArray(SISFields=[sf6]) sf7 = sisfield.SISSignatureCertificateChain(Signatures=sa, CertificateChain=sf2) # Set certificate, restore data index. ctrlfield.Signature0 = sf7 ctrlfield.DataIndex = didxfield # Convert SISFields to string. outstring = insis[0].tostring() # Write output SIS file. f = file(outfile, "wb") f.write(uids) f.write(outstring) f.close()
def tostring(self): '''Convert this SIS instance to a (possibly very large) string.''' # Generate a SISInfo SISField. infofield = sisfield.SISInfo(UID=self.uid, VendorUniqueName=self.vendorname, Names=self.names, VendorNames=self.vendornames, Version=self.version, CreationTime=self.creationtime, InstallType=sisfield.EInstInstallation, InstallFlags=0) # Generate an empty SISSupportedOptions SISField. # Option lists are not supported by SimpleSISWriter. sa = sisfield.SISArray(SISFields=[], SISFieldType="SISSupportedOption") optfield = sisfield.SISSupportedOptions(Options=sa) # Convert language numbers to SISArray of SISLanguages # and generate a SISSupportedLanguages SISField. langfieldlist = [] for lang in self.languages: langfieldlist.append(sisfield.SISLanguage(Language=lang)) sa = sisfield.SISArray(SISFields=langfieldlist, SISFieldType="SISLanguage") langfield = sisfield.SISSupportedLanguages(Languages=sa) # Generate SISPrerequisites SISField. sa1 = sisfield.SISArray(SISFields=self.targetdevices, SISFieldType="SISDependency") sa2 = sisfield.SISArray(SISFields=self.dependencies, SISFieldType="SISDependency") prereqfield = sisfield.SISPrerequisites(TargetDevices=sa1, Dependencies=sa2) # Generate SISProperties SISField. sa = sisfield.SISArray(SISFields=self.properties, SISFieldType="SISProperty") propfield = sisfield.SISProperties(Properties=sa) # Generate SISInstallBlock SISField. iffield = makelangconditional(self.languages, self.langdepfiles) if iffield: # Some language dependent files iffieldlist = [iffield] else: # No language dependent files iffieldlist = [] ibfield = makeinstallblock(self.files, [], iffieldlist) # Generate a data index field. No embedded SIS files, index is 0. didxfield = sisfield.SISDataIndex(DataIndex=0) # Generate a SISController SISField without any signatures. ctrlfield = sisfield.SISController(Info=infofield, Options=optfield, Languages=langfield, Prerequisites=prereqfield, Properties=propfield, Logo=self.logo, InstallBlock=ibfield) # Calculate metadata signature for each certificate. certfieldlist = [] for cert in self.certificates: # Calculate a signature of the SISController so far. string = ctrlfield.tostring() string = sisfield.stripheaderandpadding(string) signature, algoid = signstring(cert[0], cert[2], string) # Create a SISCertificateChain SISField from certificate data. sf1 = sisfield.SISBlob(Data=cryptutil.certtobinary(cert[1])) sf2 = sisfield.SISCertificateChain(CertificateData=sf1) # Create a SISSignature SISField from calculated signature. sf3 = sisfield.SISString(String=algoid) sf4 = sisfield.SISSignatureAlgorithm(AlgorithmIdentifier=sf3) sf5 = sisfield.SISBlob(Data=signature) sf6 = sisfield.SISSignature(SignatureAlgorithm=sf4, SignatureData=sf5) # Create a new SISSignatureCertificateChain SISField. sa = sisfield.SISArray(SISFields=[sf6]) certfieldlist.append( sisfield.SISSignatureCertificateChain(Signatures=sa, CertificateChain=sf2)) # Add certificate to SISController SISField. ctrlfield.setsignatures(certfieldlist) # Finally add a data index field to SISController SISField. # and wrap it in SISCompressed SISField. ctrlfield.DataIndex = didxfield ctrlcompfield = sisfield.SISCompressed( Data=ctrlfield, CompressionAlgorithm=sisfield.ECompressDeflate) # Generate SISData SISField. sa = sisfield.SISArray(SISFields=self.filedata, SISFieldType="SISFileData") dufield = sisfield.SISDataUnit(FileData=sa) sa = sisfield.SISArray(SISFields=[dufield]) datafield = sisfield.SISData(DataUnits=sa) # Calculate SISController checksum. # TODO: Requires an extra tostring() conversion. ctrlcs = symbianutil.crc16ccitt(ctrlcompfield.tostring()) ctrlcsfield = sisfield.SISControllerChecksum(Checksum=ctrlcs) # Calculate SISData checksum. # TODO: Requires an extra tostring() conversion. datacs = symbianutil.crc16ccitt(datafield.tostring()) datacsfield = sisfield.SISDataChecksum(Checksum=datacs) # Generate SISContents SISField. contentsfield = sisfield.SISContents(ControllerChecksum=ctrlcsfield, DataChecksum=datacsfield, Controller=ctrlcompfield, Data=datafield) # Generate a SIS UID string. uidstring = symbianutil.uidstostring(0x10201a7aL, 0x00000000L, self.uid.UID1) # Return the completed SIS file as a string. return uidstring + contentsfield.tostring()
def __init__(self, languages, names, uid, version, vendorname, vendornames, creationtime=None): # Set empty list of languages, names, files, certificates and so on. self.languages = [] self.filedata = [] self.files = [] self.langdepfiles = [] self.logo = None self.certificates = [] self.targetdevices = [] self.dependencies = [] self.properties = [] # Convert language IDs/names to language numbers. for lang in languages: try: langnum = symbianutil.langidtonum[lang] except KeyError: # Not a language ID, try names next. try: langnum = symbianutil.langnametonum[lang] except KeyError: raise ValueError("invalid language '%s'" % lang) self.languages.append(langnum) # Verify number of names and vendor names wrt. number of languages. if len(names) != len(self.languages): raise ValueError( "%d package names given but number of languages is %d" % (len(names), len(self.languages))) if len(vendornames) != len(self.languages): raise ValueError( "%d vendor names given but number of languages is %d" % (len(vendornames), len(self.languages))) # Convert language dependent names to a SISArray of SISStrings. l = [] for name in names: l.append(sisfield.SISString(String=name)) self.names = sisfield.SISArray(SISFields=l, SISFieldType="SISString") # Convert integer UID to SISUid SISField. self.uid = sisfield.SISUid(UID1=uid) # Convert version number triplet to SISVersion SISField. self.version = sisfield.SISVersion(Major=version[0], Minor=version[1], Build=version[2]) # Convert unique vendor name to SISString SISField. self.vendorname = sisfield.SISString(String=vendorname) # Convert language dependent vendor names to a SISArray of SISStrings. l = [] for name in vendornames: l.append(sisfield.SISString(String=name)) self.vendornames = sisfield.SISArray(SISFields=l, SISFieldType="SISString") if creationtime == None: # If no creation time given, use the time # of SimpleSISWriter instantiation. creationtime = time.gmtime() # Convert standard Python time representation to SISFields. datefield = sisfield.SISDate(Year=creationtime.tm_year, Month=creationtime.tm_mon - 1, Day=creationtime.tm_mday) timefield = sisfield.SISTime(Hours=creationtime.tm_hour, Minutes=creationtime.tm_min, Seconds=creationtime.tm_sec) self.creationtime = sisfield.SISDateTime(Date=datefield, Time=timefield)