def sendpbcommand(self, request, responseclass): self.setmode(self.MODEBREW) buffer = prototypes.buffer() request.writetobuffer(buffer, logtitle="audiovox cdm8900 phonebook request") data = buffer.getvalue() data = common.pppescape(data + common.crcs(data)) + common.pppterminator first = data[0] try: data = self.comm.writethenreaduntil(data, False, common.pppterminator, logreaduntilsuccess=False) except com_phone.modeignoreerrortypes: self.mode = self.MODENONE self.raisecommsdnaexception("manipulating the phonebook") self.comm.success = True origdata = data # sometimes there is junk at the begining, eg if the user # turned off the phone and back on again. So if there is more # than one 7e in the escaped data we should start after the # second to last one d = data.rfind(common.pppterminator, 0, -1) if d >= 0: self.log( "Multiple PB packets in data - taking last one starting at " + ` d + 1 `) self.logdata("Original pb data", origdata, None) data = data[d + 1:] # turn it back to normal data = common.pppunescape(data) # sometimes there is other crap at the begining d = data.find(first) if d > 0: self.log("Junk at begining of pb packet, data at " + ` d `) self.logdata("Original pb data", origdata, None) self.logdata("Working on pb data", data, None) data = data[d:] # take off crc and terminator crc = data[-3:-1] data = data[:-3] if common.crcs(data) != crc: self.logdata("Original pb data", origdata, None) self.logdata("Working on pb data", data, None) raise common.CommsDataCorruption( "Audiovox phonebook packet failed CRC check", self.desc) # parse data buffer = prototypes.buffer(data) res = responseclass() res.readfrombuffer(buffer, logtitle="Audiovox phonebook response") return res
def sendpbcommand(self, request, responseclass): self.setmode(self.MODEBREW) buffer=prototypes.buffer() request.writetobuffer(buffer, logtitle="audiovox cdm8900 phonebook request") data=buffer.getvalue() data=common.pppescape(data+common.crcs(data))+common.pppterminator first=data[0] try: data=self.comm.writethenreaduntil(data, False, common.pppterminator, logreaduntilsuccess=False) except com_phone.modeignoreerrortypes: self.mode=self.MODENONE self.raisecommsdnaexception("manipulating the phonebook") self.comm.success=True origdata=data # sometimes there is junk at the begining, eg if the user # turned off the phone and back on again. So if there is more # than one 7e in the escaped data we should start after the # second to last one d=data.rfind(common.pppterminator,0,-1) if d>=0: self.log("Multiple PB packets in data - taking last one starting at "+`d+1`) self.logdata("Original pb data", origdata, None) data=data[d+1:] # turn it back to normal data=common.pppunescape(data) # sometimes there is other crap at the begining d=data.find(first) if d>0: self.log("Junk at begining of pb packet, data at "+`d`) self.logdata("Original pb data", origdata, None) self.logdata("Working on pb data", data, None) data=data[d:] # take off crc and terminator crc=data[-3:-1] data=data[:-3] if common.crcs(data)!=crc: self.logdata("Original pb data", origdata, None) self.logdata("Working on pb data", data, None) raise common.CommsDataCorruption("Audiovox phonebook packet failed CRC check", self.desc) # parse data buffer=prototypes.buffer(data) res=responseclass() res.readfrombuffer(buffer, logtitle="Audiovox phonebook response") return res
def sendpbcommand(self, request, responseclass, callsetmode=True): if callsetmode: self.setmode(self.MODEPHONEBOOK) buffer=prototypes.buffer() request.header.sequence=self.pbseq self.pbseq+=1 if self.pbseq>0xff: self.pbseq=0 request.writetobuffer(buffer, logtitle="lg phonebook request") data=buffer.getvalue() data=common.pppescape(data+common.crcs(data))+common.pppterminator firsttwo=data[:2] try: data=self.comm.writethenreaduntil(data, False, common.pppterminator, logreaduntilsuccess=False) except com_phone.modeignoreerrortypes: self.mode=self.MODENONE self.raisecommsdnaexception("manipulating the phonebook") self.comm.success=True origdata=data d=data.rfind(common.pppterminator,0,-1) if d>=0: self.log("Multiple LG packets in data - taking last one starting at "+`d+1`) self.logdata("Original LG data", origdata, None) data=data[d+1:] data=common.pppunescape(data) crc=data[-3:-1] data=data[:-3] calccrc=common.crcs(data) if calccrc!=crc: d=data.find(firsttwo) if d>0: self.log("Junk at begining of LG packet, data at "+`d`) self.logdata("Original LG data", origdata, None) self.logdata("Working on LG data", data, None) data=data[d:] calccrc=common.crcs(data) if calccrc!=crc: self.logdata("Original LG data", origdata, None) self.logdata("Working on LG data", data, None) raise common.CommsDataCorruption("LG packet failed CRC check", self.desc) if ord(data[0])==0x13: raise com_brew.BrewBadBrewCommandException() if ord(data[0])==0x14: raise com_brew.BrewMalformedBrewCommandException() buffer=prototypes.buffer(data) res=responseclass() res.readfrombuffer(buffer, logtitle="lg phonebook response") return res
def sendpbcommand(self, request, responseclass): self.setmode(self.MODEBREW) buffer=prototypes.buffer() request.writetobuffer(buffer) data=buffer.getvalue() self.logdata("toshiba vm4050 phonebook request", data, request) data=common.pppescape(data+common.crcs(data))+common.pppterminator first=data[0] try: data=self.comm.writethenreaduntil(data, False, common.pppterminator, logreaduntilsuccess=False) except com_phone.modeignoreerrortypes: self.mode=self.MODENONE self.raisecommsdnaexception("manipulating the phonebook") self.comm.success=True origdata=data d=data.rfind(common.pppterminator,0,-1) if d>=0: self.log("Multiple PB packets in data - taking last one starting at "+`d+1`) self.logdata("Original pb data", origdata, None) data=data[d+1:] data=common.pppunescape(data) d=data.find(first) if d>0: self.log("Junk at begining of pb packet, data at "+`d`) self.logdata("Original pb data", origdata, None) self.logdata("Working on pb data", data, None) data=data[d:] crc=data[-3:-1] data=data[:-3] if common.crcs(data)!=crc: self.logdata("Original pb data", origdata, None) self.logdata("Working on pb data", data, None) raise common.CommsDataCorruption("toshiba phonebook packet failed CRC check", self.desc) self.logdata("toshiba phonebook response", data, responseclass) buffer=prototypes.buffer(data) res=responseclass() res.readfrombuffer(buffer) return res
def readfrombuffer(self, buf): self._bufferstartoffset=buf.getcurrentoffset() if self._terminator is None: self._value=buf.getremainingbytes() else: self._value=chr(buf.getnextbyte()) if self._value == ',': self._value = '' else: inquotes=False if self._quotechar is not None: if self._value[0]==chr(self._quotechar): inquotes=True while buf.hasmore(): self._value+=chr(buf.getnextbyte()) if inquotes: if self._value[-1]==chr(self._quotechar): inquotes=False else: if self._value[-1]==chr(self._terminator): break if self._value[-1]==self._terminator: if self._raiseonunterminatedread: raise NotTerminatedException() else: self._value=self._value[:-1] if self._quotechar is not None and self._value: if self._value[0]==chr(self._quotechar) and self._value[-1]==chr(self._quotechar): self._value=self._value[1:-1] else: raise MissingQuotesException() if self._readescape: self._value=common.pppunescape(self._value) if self._constant is not None and self._value!=self._constant: raise ValueException("The value read was not the constant") self._bufferendoffset=buf.getcurrentoffset()
def sendbrewcommand(self, request, responseclass, callsetmode=True): if callsetmode: self.setmode(self.MODEBREW) buffer=prototypes.buffer() request.writetobuffer(buffer, logtitle="sendbrewcommand") data=buffer.getvalue() data=common.pppescape(data+common.crcs(data))+common.pppterminator firsttwo=data[:2] try: data=self.comm.writethenreaduntil(data, False, common.pppterminator, logreaduntilsuccess=False) except modeignoreerrortypes: self.mode=self.MODENONE self.raisecommsdnaexception("manipulating the filesystem") self.comm.success=True origdata=data d=data.rfind(common.pppterminator,0,-1) if d>=0: self.log("Multiple packets in data - taking last one starting at "+`d+1`) self.logdata("Original data", origdata, None) data=data[d+1:] data=common.pppunescape(data) crc=data[-3:-1] data=data[:-3] calccrc=common.crcs(data) if calccrc!=crc: d=data.find(firsttwo) if d>0: self.log("Junk at begining of packet, data at "+`d`) self.logdata("Original data", origdata, None) self.logdata("Working on data", data, None) data=data[d:] calccrc=common.crcs(data) if calccrc!=crc: self.logdata("Original data", origdata, None) self.logdata("Working on data", data, None) raise common.CommsDataCorruption("Brew packet failed CRC check", self.desc) self.logdata("brew response", data, responseclass) if firsttwo=="Y\x0c" and data==firsttwo: raise common.CommsWrongPort("The port you are using is echoing data back, and is not valid for Brew data. Most likely you have selected the modem interface when you should be using the diagnostic interface.", self.desc) if data[0]=="Y" and data[2]!="\x00": # Y is 0x59 which is brew command prefix err=ord(data[2]) if err==0x1c: raise BrewNoMoreEntriesException() if err==0x08: raise BrewNoSuchDirectoryException() if err==0x06: raise BrewNoSuchFileException() if err==0x1a: raise BrewBadPathnameException() if err==0x0b: raise BrewFileLockedException() if err==0x0d: raise BrewNameTooLongException() if err==0x07: raise BrewDirectoryExistsException() if err==0x04: raise BrewAccessDeniedException() if err==0x16: raise BrewFileSystemFullException() raise BrewCommandException(err) if ord(data[0])==0x13: if firsttwo[0]=="Y": # brew command raise BrewAccessDeniedException() else: raise BrewBadBrewCommandException() if ord(data[0])==0x14: raise BrewMalformedBrewCommandException() buffer=prototypes.buffer(data) res=responseclass() try: res.readfrombuffer(buffer, autolog=False) except: self.log(formatpacketerrorlog("Error decoding response", origdata, data, responseclass)) raise return res
def sendpbcommand(self, request, responseclass): self.setmode(self.MODEBREW) buffer=prototypes.buffer() request.writetobuffer(buffer) data=buffer.getvalue() self.logdata("toshiba vm4050 phonebook request", data, request) data=common.pppescape(data+common.crcs(data))+common.pppterminator first=data[0] try: data=self.comm.writethenreaduntil(data, False, common.pppterminator, logreaduntilsuccess=False) except com_phone.modeignoreerrortypes: self.mode=self.MODENONE self.raisecommsdnaexception("manipulating the phonebook") self.comm.success=True origdata=data d=data.rfind(common.pppterminator,0,-1) if d>=0: self.log("Multiple PB packets in data - taking last one starting at "+`d+1`) self.logdata("Original pb data", origdata, None) data=data[d+1:] data=common.pppunescape(data) d=data.find(first) if d>0: self.log("Junk at begining of pb packet, data at "+`d`) self.logdata("Original pb data", origdata, None) self.logdata("Working on pb data", data, None) data=data[d:] crc=data[-3:-1] data=data[:-3] if common.crcs(data)!=crc: self.logdata("Original pb data", origdata, None) self.logdata("Working on pb data", data, None) raise common.CommsDataCorruption("toshiba phonebook packet failed CRC check", self.desc) self.logdata("toshiba phonebook response", data, responseclass) buffer=prototypes.buffer(data) res=responseclass() res.readfrombuffer(buffer) return res def get_detect_data(self, res): self.modemmoderequest() res['manufacturer']=self.comm.sendatcommand('+GMI')[0] res['model']=self.comm.sendatcommand('+GMM')[0] res['firmware_version']=self.comm.sendatcommand('+GMR')[0] res['esn']=self.comm.sendatcommand('+GSN')[0][2:] return def detectphone(coms, likely_ports, res, _module, _log): if not likely_ports: return None for port in likely_ports: if not res.has_key(port): res[port]={ 'mode_modem': None, 'mode_brew': None, 'manufacturer': None, 'model': None, 'firmware_version': None, 'esn': None, 'firmwareresponse': None } try: if res[port]['model']: continue p=_module.Phone(_log, commport.CommConnection(_log, port, timeout=1)) res[port]['mode_brew']=p._setmodebrew() if res[port]['mode_brew']: p.get_detect_data(res[port]) p.comm.close() except: if __debug__: raise detectphone=staticmethod(detectphone) "Talk to Toshiba VM4050 cell phone" class Profile (com_phone.Profile) : protocolclass=Phone.protocolclass serialsname=Phone.serialsname phone_manufacturer='Audiovox Communications Corporation' phone_model='VM4050' usbids=((0x05C6, 0x3100, 1), ) deviceclasses=("modem",) _supportedsyncs=( ('phonebook', 'read', None), ('phonebook', 'write', 'OVERWRITE'), ) def convertphonebooktophone(self, helper, data): """Converts the data to what will be used by the phone @param data: contains the dict returned by getfundamentals as well as where the results go""" results={} slotsused={} for pbentry in data['phonebook']: entry=data['phonebook'][pbentry] serial1=helper.getserial(entry.get('serials', []), self.serialsname, data['uniqueserial'], 'serial1', -1) if(serial1 >= 0 and serial1 < self.protocolclass.NUMSLOTS): slotsused[serial1]=1 lastunused=0 for pbentry in data['phonebook']: if len(results)==self.protocolclass.NUMSLOTS: break e={} entry=data['phonebook'][pbentry] try: e['name']=helper.getfullname(entry.get('names', []),1,1,36)[0] serial1=helper.getserial(entry.get('serials', []), self.serialsname, data['uniqueserial'], 'serial1', -1) if(serial1 >= 0 and serial1 < self.protocolclass.NUMSLOTS): e['slot']=serial1 else: while(slotsused.has_key(lastunused)): lastunused+=1 if(lastunused >= self.protocolclass.NUMSLOTS): helper.add_error_message("Name: %s. Unable to add, phonebook full" % e['name']) raise helper.ConversionFailed() e['slot']=lastunused slotsused[lastunused]=1 emails=helper.getemails(entry.get('emails', []) ,0,self.protocolclass.MAXEMAILS,self.protocolclass.MAXEMAILLEN) e['emails']=helper.filllist(emails, self.protocolclass.MAXEMAILS, "") e['web_page']=helper.makeone(helper.geturls(entry.get('urls', []), 0,1,48), "") numbers=helper.getnumbers(entry.get('numbers', []),0,self.protocolclass.MAXPHONENUMBERS) e['numbertypes']=[] e['numbers']=[] typesused={} for num in numbers: type=num['type'] if(typesused.has_key(type)): continue typesused[type]=1 for typenum,tnsearch in enumerate(self.protocolclass.numbertypetab): if type==tnsearch: number=self.phonize(num['number']) if len(number)==0: continue if len(number)>self.protocolclass.MAXPHONENUMBERLEN: number=number[:self.protocolclass.MAXPHONENUMBERLEN] e['numbers'].append(number) e['numbertypes'].append(typenum) break e['ringtone']=helper.getringtone(entry.get('ringtones', []), 'call', None) e['secret']=helper.getflag(entry.get('flags',[]), 'secret', False) results[pbentry]=e except helper.ConversionFailed: continue data['phonebook']=results return data def phonize(self, str): """Convert the phone number into something the phone understands All digits, P, T, *, # are kept, everything else is removed. In theory the phone can store a dash in the phonebook, but that is not normal.""" return re.sub("[^0-9PT#*]", "", str)[:self.protocolclass.MAXPHONENUMBERLEN]
def sendpbcommand(self, request, responseclass, callsetmode=True, writemode=False, numsendretry=0, returnerror=False): if writemode: numretry=3 else: numretry=0 if callsetmode: self.setmode(self.MODEPHONEBOOK) buffer=prototypes.buffer() request.writetobuffer(buffer) data=buffer.getvalue() firsttwo=data[:2] data=common.pppescape(data+common.crcs(data))+common.pppterminator self.logdata("N400 phonebook request", data, request) isendretry=numsendretry while isendretry>=0: try: rdata=self.comm.writethenreaduntil(data, False, common.pppterminator, logreaduntilsuccess=False, numfailures=numretry) break except com_phone.modeignoreerrortypes: if isendretry>0: self.log("Resending request packet...") time.sleep(0.3) else: self.comm.success=False self.mode=self.MODENONE self.raisecommsdnaexception("manipulating the phonebook") isendretry-=1 self.comm.success=True origdata=rdata d=rdata.rfind(common.pppterminator,0,-1) if d>=0: self.log("Multiple N400 packets in data - taking last one starting at "+`d+1`) self.logdata("Original N400 data", origdata, None) rdata=rdata[d+1:] data=common.pppunescape(rdata) d=data.find(firsttwo) crc=data[-3:-1] crcok=False for i in range(0,d+1): trydata=data[i:-3] if common.crcs(trydata)==crc: crcok=True break if not crcok: self.logdata("first two",firsttwo, None) self.logdata("Original N400 data", origdata, None) self.logdata("Working on N400 data", data, None) raise common.CommsDataCorruption("N400 packet failed CRC check", self.desc) res=responseclass() if d>0: if d==i: self.log("Junk at beginning of N400 packet, data at "+`d`) self.logdata("Original N400 data", origdata, None) self.logdata("Working on N400 data", data, None) else: if returnerror: res=self.protocolclass.sanyoerror() else: self.log("N400 Error code "+`ord(data[0])`) self.logdata("Samsung phonebook response", data, None) raise N400CommandException(ord(data[0])) data=trydata self.logdata("sanyo phonebook response", data, responseclass) buffer=prototypes.buffer(data) res.readfrombuffer(buffer) return res
def sendpbcommand(self, request, responseclass, callsetmode=True, writemode=False, numsendretry=0, returnerror=False): if writemode: numretry=3 else: numretry=0 if callsetmode: self.setmode(self.MODEPHONEBOOK) buffer=prototypes.buffer() request.writetobuffer(buffer) data=buffer.getvalue() firsttwo=data[:2] data=common.pppescape(data+common.crcs(data))+common.pppterminator self.logdata("N400 phonebook request", data, request) isendretry=numsendretry while isendretry>=0: try: rdata=self.comm.writethenreaduntil(data, False, common.pppterminator, logreaduntilsuccess=False, numfailures=numretry) break except com_phone.modeignoreerrortypes: if isendretry>0: self.log("Resending request packet...") time.sleep(0.3) else: self.comm.success=False self.mode=self.MODENONE self.raisecommsdnaexception("manipulating the phonebook") isendretry-=1 self.comm.success=True origdata=rdata d=rdata.rfind(common.pppterminator,0,-1) if d>=0: self.log("Multiple N400 packets in data - taking last one starting at "+`d+1`) self.logdata("Original N400 data", origdata, None) rdata=rdata[d+1:] data=common.pppunescape(rdata) d=data.find(firsttwo) crc=data[-3:-1] crcok=False for i in range(0,d+1): trydata=data[i:-3] if common.crcs(trydata)==crc: crcok=True break if not crcok: self.logdata("first two",firsttwo, None) self.logdata("Original N400 data", origdata, None) self.logdata("Working on N400 data", data, None) raise common.CommsDataCorruption("N400 packet failed CRC check", self.desc) res=responseclass() if d>0: if d==i: self.log("Junk at beginning of N400 packet, data at "+`d`) self.logdata("Original N400 data", origdata, None) self.logdata("Working on N400 data", data, None) else: if returnerror: res=self.protocolclass.sanyoerror() else: self.log("N400 Error code "+`ord(data[0])`) self.logdata("Samsung phonebook response", data, None) raise N400CommandException(ord(data[0])) data=trydata self.logdata("sanyo phonebook response", data, responseclass) buffer=prototypes.buffer(data) res.readfrombuffer(buffer) return res def getphonebook(self, result): pbook={} reqname=self.protocolclass.phonebooknamerequest() reqnumbers=self.protocolclass.phonebooknumbersrequest() count = 0 for i in range(2, 251): reqname.slot=i resname=self.sendpbcommand(reqname, self.protocolclass.phonebooknameresponse) if resname.entry.nonzeroifused: entry={} entry['serials']=[ {'sourcetype': self.serialsname, 'slot': i, 'sourceuniqueid': result['uniqueserial']} ] entry['names']=[{'full': resname.entry.name} ] entry['numbers'] = [] for i in range(7): numptr = resname.entry.numbers[i].pnumber if numptr: reqnumbers.slot=numptr resnumbers=self.sendpbcommand(reqnumbers, self.protocolclass.phonebooknumbersresponse) numhash={'number': resnumbers.entry.number, 'type': numbertypetab[i]} if numptr==resname.entry.pspeed: numhash['speeddial']=i entry['numbers'].append(numhash) if resname.entry.pemail: reqnumbers.slot=resname.entry.pemail resnumbers=self.sendpbcommand(reqnumbers, self.protocolclass.phonebooknumbersresponse) entry['emails']=[{'email': resnumbers.entry.number}] if resname.entry.purl: reqnumbers.slot=resname.entry.purl resnumbers=self.sendpbcommand(reqnumbers, self.protocolclass.phonebooknumbersresponse) entry['urls']=[{'url': resnumbers.entry.number}] self.log("Read entry "+`i`+": "+resname.entry.name) pbook[count]=entry count+=1 result['phonebook']=pbook return result def getcalendar(self, result): pbook={} result['calendar']=pbook return result def getwallpapers(self, results): pass def getringtones(self, results): pass "Talk to a Samsung SPH-N400 cell phone" class Profile (com_phone.Profile) : protocolclass=Phone.protocolclass serialsname=Phone.serialsname phone_manufacturer='SAMSUNG' phone_model='SPH-N400' usbids_usbtoserial=( ( 0x067b, 0x2303, None), ( 0x0403, 0x6001, None), ( 0x0731, 0x2003, None), ) usbids=usbids_usbtoserial deviceclasses=("serial",) def __init__(self): com_phone.Profile.__init__(self) _supportedsyncs=( ('phonebook', 'read', None), )
def readfrombuffer(self, buf): self._bufferstartoffset=buf.getcurrentoffset() if self._terminator is None: self._value=buf.getremainingbytes() else: self._value=chr(buf.getnextbyte()) if self._value == ',': self._value = '' else: inquotes=False if self._quotechar is not None: if self._value[0]==chr(self._quotechar): inquotes=True while buf.hasmore(): self._value+=chr(buf.getnextbyte()) if inquotes: if self._value[-1]==chr(self._quotechar): inquotes=False else: if self._value[-1]==chr(self._terminator): break if self._value[-1]==self._terminator: if self._raiseonunterminatedread: raise NotTerminatedException() else: self._value=self._value[:-1] if self._quotechar is not None and self._value: if self._value[0]==chr(self._quotechar) and self._value[-1]==chr(self._quotechar): self._value=self._value[1:-1] else: raise MissingQuotesException() if self._readescape: self._value=common.pppunescape(self._value) if self._constant is not None and self._value!=self._constant: raise ValueException("The value read was not the constant") self._bufferendoffset=buf.getcurrentoffset() def writetobuffer(self, buf): if self._value is None: raise ValueNotSetException() self._bufferstartoffset=buf.getcurrentoffset() if self._quotechar is not None: buf.appendbyte(self._quotechar) buf.appendbytes(self._value) if self._quotechar is not None: buf.appendbyte(self._quotechar) if self._terminator is not None: buf.appendbyte(self._terminator) self._bufferendoffset=buf.getcurrentoffset() def packetsize(self): if self._sizeinbytes is not None: return self._sizeinbytes if self._value is None: raise ValueNotSetException() l=len(self._value) if self._terminator is not None: l+=1 return l def getvalue(self): """Returns the string we are""" if self._value is None: raise ValueNotSetException() return self._value """A text string enclosed in quotes, with a way to escape quotes that a supposed to be part of the string. Typical of Samsung phones.""" class CSVINT (CSVSTRING) : """Integers in CSV lines""" def __init__(self, *args, **kwargs): super(CSVINT,self).__init__(*args, **kwargs) self._quotechar=None if self._ismostderived(CSVINT): self._update(args,kwargs) def _update(self, args, kwargs): for k in 'constant', 'default', 'value': if kwargs.has_key(k): kwargs[k]=str(kwargs[k]) if len(args)==0: pass elif len(args)==1: args=(str(args[0]),) else: raise TypeError("expected integer as arg") super(CSVINT,self)._update(args,kwargs) self._complainaboutunusedargs(CSVINT,kwargs) def getvalue(self): """Convert the string into an integer @rtype: integer """ val=super(CSVINT,self).getvalue() try: ival=int(val) except: try: ival=int(self._default) except: raise ValueException("The field '%s' is not an integer" % (val)) return ival """Integers in CSV lines""" class CSVDATE (CSVSTRING) : """Dates in CSV lines""" def __init__(self, *args, **kwargs): super(CSVDATE,self).__init__(*args, **kwargs) self._valuedate=(0,0,0) self._quotechar=None if self._ismostderived(CSVDATE): self._update(args,kwargs) def _update(self, args, kwargs): for k in 'constant', 'default', 'value': if kwargs.has_key(k): kwargs[k]=self._converttostring(kwargs[k]) if len(args)==0: pass elif len(args)==1: args=(self._converttostring(args[0]),) else: raise TypeError("expected (year,month,day) as arg") super(CSVDATE,self)._update(args, kwargs) self._complainaboutunusedargs(CSVDATE,kwargs) def getvalue(self): """Unpack the string into the date @rtype: tuple @return: (year, month, day) """ s=super(CSVDATE,self).getvalue() val=s.split("/") if len(val)<2: year = 0 month = 0 day = 0 else: year=int(val[2]) month=int(val[0]) day=int(val[1]) return (year, month, day) def _converttostring(self, date): if len(date)>=3: year,month,day=date[:3] if month>0 or day>0 or year>0: s='%2.2d/%2.2d/%4.4d'%(month, day, year) else: s="" else: s="" return s """Dates in CSV lines""" class CSVTIME (CSVSTRING) : """Timestamp in CSV lines""" def __init__(self, *args, **kwargs): super(CSVTIME,self).__init__(*args, **kwargs) self._valuetime=(0,0,0,0,0,0) self._quotechar=None if self._ismostderived(CSVTIME): self._update(args,kwargs) def _update(self, args, kwargs): for k in 'constant', 'default', 'value': if kwargs.has_key(k): kwargs[k]=self._converttostring(kwargs[k]) if len(args)==0: pass elif len(args)==1: args=(self._converttostring(args[0]),) else: raise TypeError("expected (year,month,day) as arg") super(CSVTIME,self)._update(args, kwargs) self._complainaboutunusedargs(CSVTIME,kwargs) def getvalue(self): """Unpack the string into the date @rtype: tuple @return: (year, month, day) """ s=super(CSVTIME,self).getvalue() year=int(s[0:4]) month=int(s[4:6]) day=int(s[6:8]) hour=int(s[9:11]) minute=int(s[11:13]) second=int(s[13:15]) return (year, month, day, hour, minute, second) def _converttostring(self, time): if len(time)>=6: year,month,day,hour,minute,second=time[:6] s='%4.4d%2.2d%2.2dT%2.2d%2.2d%2.2d'%(year, month, day, hour, minute, second) else: s="" return s """Timestamp in CSV lines""" class COUNTEDBUFFEREDSTRING (BaseProtogenClass) : """A string as used on Audiovox. There is a one byte header saying how long the string is, followed by the string in a fixed sized buffer""" def __init__(self, *args, **kwargs): """ A string value can be specified to this constructor, or in the value keyword arg. @keyword constant: (Optional) A constant value. All reads must have this value @keyword pad: (Default=32 - space) When writing, what to pad the rest of the buffer with @keyword default: (Optional) Our default value @keyword raiseontruncate: (Default True) raise L{ValueLengthException} if the supplied value is too large to fit within the buffer. @keyword value: (Optional) Value @keyword sizeinbytes: (Mandatory) Size of the buffer, including the count byte """ super(COUNTEDBUFFEREDSTRING,self).__init__(*args, **kwargs) self._constant=None self._pad=32 self._sizeinbytes=None self._default=None self._raiseontruncate=True self._value=None if self._ismostderived(COUNTEDBUFFEREDSTRING): self._update(args, kwargs) def _update(self, args, kwargs): super(COUNTEDBUFFEREDSTRING,self)._update(args, kwargs) self._consumekw(kwargs, ("constant", "pad", "sizeinbytes", "default", "raiseontruncate", "value")) self._complainaboutunusedargs(COUNTEDBUFFEREDSTRING,kwargs) if len(args)==0: pass elif len(args)==1: self._value=str(args[0]) if self._constant is not None and self._constant!=self._value: raise ValueException("This field is a constant of '%s'. You tried setting it to '%s'" % (self._constant, self._value)) else: raise TypeError("Unexpected arguments "+`args`) if self._value is None and self._default is not None: self._value=self._default if self._sizeinbytes is None: raise ValueException("sizeinbytes must be specified for COUNTEDBUFFEREDSTRING") if self._value is not None: l=len(self._value) if l>self._sizeinbytes-1: if self._raiseontruncate: raise ValueLengthException(l, self._sizeinbytes-1) self._value=self._value[:self._sizeinbytes-1] def readfrombuffer(self, buf): assert self._sizeinbytes is not None self._bufferstartoffset=buf.getcurrentoffset() strlen=buf.getnextbyte() if strlen>self._sizeinbytes-1: raise ValueException("counter specifies size of %d which is greater than remaining stringbuffer size of %d!" % (strlen, self._sizeinbytes-1)) self._value=buf.getnextbytes(self._sizeinbytes-1) self._value=self._value[:strlen] if self._constant is not None and self._value!=self._constant: raise ValueException("The value read was not the constant") self._bufferendoffset=buf.getcurrentoffset() def writetobuffer(self, buf): assert self._sizeinbytes is not None if self._value is None: raise ValueNotSetException() self._bufferstartoffset=buf.getcurrentoffset() buf.appendbyte(len(self._value)) buf.appendbytes(self._value) if len(self._value)+1<self._sizeinbytes: buf.appendbytes(chr(self._pad)*(self._sizeinbytes-1-len(self._value))) self._bufferendoffset=buf.getcurrentoffset() def packetsize(self): assert self._sizeinbytes is not None return self._sizeinbytes def getvalue(self): """Returns the string we are""" if self._value is None: raise ValueNotSetException() return self._value """A string as used on Audiovox. There is a one byte header saying how long the string is, followed by the string in a fixed sized buffer""" class DATA (BaseProtogenClass) : "A block of bytes" def __init__(self, *args, **kwargs): """ A data value can be specified to this constructor or in the value keyword arg @keyword constant: (Optional) A constant value. All reads must have this value @keyword pad: (Default=0) The padding byte if fixed length when writing and the value isn't long enough @keyword sizeinbytes: (Optional) Set if fixed length. If not set, then the rest of the packet will be consumed on reads. @keyword default: (Optional) Our default value @keyword raiseonwrongsize: (Default True) raise L{ValueLengthException} if the supplied value is too large to fit within sizeinbytes. """ super(DATA, self).__init__(*args, **kwargs) self._constant=None self._pad=0 self._sizeinbytes=None self._default=None self._raiseonwrongsize=True self._value=None if self._ismostderived(DATA): self._update(args,kwargs) def _update(self, args, kwargs): super(DATA,self)._update(args, kwargs) self._consumekw(kwargs, ("constant", "pad", "sizeinbytes", "default", "raiseonwrongsize", "value")) self._complainaboutunusedargs(DATA,kwargs) if len(args)==0: pass elif len(args)==1: self._value=args[0] if self._constant is not None and self._constant!=self._value: raise ValueException("This field is a constant and you set it to a different value") else: raise TypeError("Unexpected arguments "+`args`) if self._value is None and self._default is not None: self._value=self._default if self._value is not None: if self._sizeinbytes is not None: l=len(self._value) if l<self._sizeinbytes: if self._pad is not None: self._value+=chr(self._pad)*(self._sizeinbytes-l) l=len(self._value) if l!=self._sizeinbytes: if self._raiseonwrongsize: raise ValueLengthException(l, self._sizeinbytes) else: self._value=self._value[:self._sizeinbytes] def readfrombuffer(self, buf): self._bufferstartoffset=buf.getcurrentoffset() if self._sizeinbytes is not None: self._value=buf.getnextbytes(self._sizeinbytes) else: self._value=buf.getremainingbytes() if self._constant is not None and self._value!=self._constant: raise ValueException("The value read was not the constant") self._bufferendoffset=buf.getcurrentoffset() def writetobuffer(self, buf): if self._value is None: raise ValueNotSetException() self._bufferstartoffset=buf.getcurrentoffset() buf.appendbytes(self._value) self._bufferendoffset=buf.getcurrentoffset() def packetsize(self): if self._sizeinbytes is not None: return self._sizeinbytes if self._value is None: raise ValueNotSetException() l=len(self._value) return l def getvalue(self): """Returns the bytes we are""" if self._value is None: raise ValueNotSetException() return self._value "A block of bytes" class UNKNOWN (DATA) : "A block of bytes whose purpose we don't know" def __init__(self, *args, **kwargs): """ Same arguments as L{DATA.__init__}. We default to a block of pad chars (usually \x00) """ dict={'pad':0 , 'default': ""} dict.update(kwargs) super(UNKNOWN,self).__init__(*args, **dict) if self._ismostderived(UNKNOWN): self._update(args,dict) def _update(self, args, kwargs): super(UNKNOWN,self)._update(args, kwargs) self._complainaboutunusedargs(UNKNOWN,kwargs) if len(args)==1: self._value=args[0] elif len(args)>1: raise TypeError("Unexpected arguments "+`args`) "A block of bytes whose purpose we don't know" class LIST (BaseProtogenClass) : """A list of items You can generally treat this class as though it is a list. Note that some list like methods haven't been implemented (there are so darn many!) If you are missing one you want to use, please add it to this class. """ def __init__(self, *args, **kwargs): """ You can pass objects to start the list with, or to the value keyword arg @keyword createdefault: (Default False) Creates default members of the list if enough were not supplied before writing. @keyword length: (Optional) How many items there are in the list @keyword raiseonbadlength: (Default True) raises L{ValueLengthException} if there are the wrong number of items in the list. Note that this checking is only done when writing or reading from a buffer. length must be set for this to have any effect. If you have createdefault set then having less than length elements will not cause the exception. @keyword elementclass: (Mandatory) The class of each element @keyword elementinitkwargs: (Optional) KWargs for the constructor of each element @keyword value: (Optional) Value """ self._thelist=[] super(LIST, self).__init__(*args, **kwargs) self._createdefault=False self._length=None self._raiseonbadlength=True self._elementclass=None self._elementinitkwargs={} if self._ismostderived(LIST): self._update(args,kwargs) def _update(self, args, kwargs): super(LIST,self)._update(args, kwargs) self._consumekw(kwargs, ("createdefault","length","raiseonbadlength","elementclass","elementinitkwargs")) if kwargs.has_key("value"): self._thelist=list(kwargs['value']) del kwargs['value'] self._complainaboutunusedargs(LIST,kwargs) if self._elementclass is None: raise TypeError("elementclass argument was not supplied") if len(args): self.extend(args) def readfrombuffer(self,buf): self._bufferstartoffset=buf.getcurrentoffset() self._thelist=[] if self._length is None: while buf.hasmore(): x=self._makeitem() x.readfrombuffer(buf) self._thelist.append(x) else: for dummy in range(self._length): x=self._makeitem() x.readfrombuffer(buf) self._thelist.append(x) self._bufferendoffset=buf.getcurrentoffset() def writetobuffer(self, buf): self._bufferstartoffset=buf.getcurrentoffset() self._ensurelength() for i in self: i.writetobuffer(buf) self._bufferendoffset=buf.getcurrentoffset() def packetsize(self): self._ensurelength() sz=0 for item in self: sz+=item.packetsize() return sz def iscontainer(self): return True def containerelements(self): self._ensurelength() for i,v in enumerate(self._thelist): yield "["+`i`+"]",v,None def append(self, item): self._thelist.append(self._makeitem(item)) def extend(self, items): self._thelist.extend(map(self._makeitem, items)) def insert(self, index, item): self._thelist.insert(index, self._makeitem(item)) def __getitem__(self, index): return self._thelist[index] def __iter__(self): try: return self._thelist.__iter__() except: return self.__fallbackiter() def __fallbackiter(self): for item in self._thelist: yield item def __len__(self): return self._thelist.__len__() def __setitem__(self, index, value): self._thelist.__setitem__(index, self._makeitem(value)) def __delitem__(self, index): self._thelist.__delitem__(index) def _makeitem(self, *args, **kwargs): "Creates a child element" if len(args)==1 and isinstance(args[0], self._elementclass): return args[0] d={} d.update(self._elementinitkwargs) d.update(kwargs) return self._elementclass(*args, **d) def _ensurelength(self): "Ensures we are the correct length" if self._createdefault and self._length is not None and len(self._thelist)<self._length: while len(self._thelist)<self._length: x=self._makeitem() self._thelist.append(x) return if self._length is not None and self._raiseonbadlength and len(self._thelist)!=self._length: raise ValueLengthException(len(self), self._length) """A list of items You can generally treat this class as though it is a list. Note that some list like methods haven't been implemented (there are so darn many!) If you are missing one you want to use, please add it to this class. """ class buffer : "This is used for reading and writing byte data" def __init__(self, data=None): "Call with data to read from it, or with None to write to it" if data is not None: self._data=data else: self._buffer=cStringIO.StringIO() self._offset=0 def getcurrentoffset(self): "Returns distance into data we are" return self._offset def peeknextbyte(self, howmuch=0): "Returns value of next byte, but doesn't advance position" if self._offset+howmuch>=len(self._data): return None return ord(self._data[self._offset+howmuch]) def getnextbyte(self): "Returns next byte" if self._offset>=len(self._data): raise IndexError("trying to read one byte beyond end of "+`len(self._data)`+" byte buffer") res=ord(self._data[self._offset]) self._offset+=1 return res def getnextbytes(self, howmany): "Returns howmany bytes" assert howmany>=0 if self._offset+howmany>len(self._data): raise IndexError("Trying to read "+`howmany`+" bytes starting at "+`self._offset`+" which will go beyond end of "+`len(self._data)`+" byte buffer") res=self._data[self._offset:self._offset+howmany] self._offset+=howmany return res def peeknextbytes(self, howmany): if self._offset+howmany>len(self._data): return None return self._data[self._offset:self._offset+howmany] def getremainingbytes(self): "Returns rest of buffer" sz=len(self._data)-self._offset return self.getnextbytes(sz) def hasmore(self): "Is there any data left?" return self._offset<len(self._data) def howmuchmore(self): "Returns how many bytes left" return len(self._data)-self._offset def appendbyte(self, val): """Appends byte to data. @param val: a number 0 <= val <=255 """ assert val>=0 and val<=255 self._buffer.write(chr(val)) self._offset+=1 assert self._offset==len(self._buffer.getvalue()) def appendbytes(self, bytes): "Adds bytes to end" self._buffer.write(bytes) self._offset+=len(bytes) assert self._offset==len(self._buffer.getvalue()) def getvalue(self): "Returns the buffer being built" return self._buffer.getvalue() def getdata(self): "Returns the data passed in" return self._data "This is used for reading and writing byte data"
def sendpbcommand(self, request, responseclass, callsetmode=True, writemode=False, numsendretry=0, returnerror=False): if writemode: numretry=3 else: numretry=0 if callsetmode: self.setmode(self.MODEPHONEBOOK) buffer=prototypes.buffer() request.writetobuffer(buffer, logtitle="Samsung phonebook request") data=buffer.getvalue() firsttwo=data[:2] data=common.pppescape(data+common.crcs(data))+common.pppterminator isendretry=numsendretry while isendretry>=0: try: rdata=self.comm.writethenreaduntil(data, False, common.pppterminator, logreaduntilsuccess=False, numfailures=numretry) break except com_phone.modeignoreerrortypes: if isendretry>0: self.log("Resending request packet...") time.sleep(0.3) else: self.comm.success=False self.mode=self.MODENONE self.raisecommsdnaexception("manipulating the phonebook") isendretry-=1 self.comm.success=True origdata=rdata # sometimes there is junk at the beginning, eg if the user # turned off the phone and back on again. So if there is more # than one 7e in the escaped data we should start after the # second to last one d=rdata.rfind(common.pppterminator,0,-1) if d>=0: self.log("Multiple Samsung packets in data - taking last one starting at "+`d+1`) self.logdata("Original Samsung data", origdata, None) rdata=rdata[d+1:] # turn it back to normal data=common.pppunescape(rdata) # Sometimes there is other crap at the beginning. But it might # be a Sanyo error byte. So strip off bytes from the beginning # until the crc agrees, or we get to the first two bytes of the # request packet. d=data.find(firsttwo) crc=data[-3:-1] crcok=False for i in range(0,d+1): trydata=data[i:-3] if common.crcs(trydata)==crc: crcok=True break if not crcok: self.logdata("first two",firsttwo, None) self.logdata("Original Sanyo data", origdata, None) self.logdata("Working on Sanyo data", data, None) raise common.CommsDataCorruption("Sanyo packet failed CRC check", self.desc) res=responseclass() if d>0: if d==i: self.log("Junk at beginning of Sanyo packet, data at "+`d`) self.logdata("Original Sanyo data", origdata, None) self.logdata("Working on Sanyo data", data, None) else: if returnerror: res=self.protocolclass.sanyoerror() else: self.log("Sanyo Error code "+`ord(data[0])`) self.logdata("sanyo phonebook response", data, None) raise SanyoCommandException(ord(data[0])) data=trydata # parse data buffer=prototypes.buffer(data) res.readfrombuffer(buffer, logtitle="sanyo phonebook response") return res
def sendpbcommand(self, request, responseclass, callsetmode=True, writemode=False, numsendretry=0, returnerror=False): if writemode: numretry=3 else: numretry=0 if callsetmode: self.setmode(self.MODEPHONEBOOK) buffer=prototypes.buffer() request.writetobuffer(buffer) data=buffer.getvalue() self.logdata("Sanyo phonebook request", data, request) firsttwo=data[:2] data=common.pppescape(data+common.crcs(data))+common.pppterminator isendretry=numsendretry while isendretry>=0: try: rdata=self.comm.writethenreaduntil(data, False, common.pppterminator, logreaduntilsuccess=False, numfailures=numretry) break except com_phone.modeignoreerrortypes: if isendretry>0: self.log("Resending request packet...") time.sleep(0.3) else: self.comm.success=False self.mode=self.MODENONE self.raisecommsdnaexception("manipulating the phonebook") isendretry-=1 self.comm.success=True origdata=rdata d=rdata.rfind(common.pppterminator,0,-1) if d>=0: self.log("Multiple Sanyo packets in data - taking last one starting at "+`d+1`) self.logdata("Original Sanyo data", origdata, None) rdata=rdata[d+1:] data=common.pppunescape(rdata) d=data.find(firsttwo) crc=data[-3:-1] crcok=False for i in range(0,d+1): trydata=data[i:-3] if common.crcs(trydata)==crc: crcok=True break if not crcok: self.logdata("first two",firsttwo, None) self.logdata("Original Sanyo data", origdata, None) self.logdata("Working on Sanyo data", data, None) raise common.CommsDataCorruption("Sanyo packet failed CRC check", self.desc) res=responseclass() if d>0: if d==i: self.log("Junk at beginning of Sanyo packet, data at "+`d`) self.logdata("Original Sanyo data", origdata, None) self.logdata("Working on Sanyo data", data, None) else: if returnerror: res=self.protocolclass.sanyoerror() else: self.log("Sanyo Error code "+`ord(data[0])`) self.logdata("sanyo phonebook response", data, None) raise SanyoCommandException(ord(data[0])) data=trydata self.logdata("sanyo phonebook response", data, responseclass) buffer=prototypes.buffer(data) res.readfrombuffer(buffer) return res def getfundamentals(self, results): """Gets information fundamental to interopating with the phone and UI.""" print "HASRINGPICBUF=",self.protocolclass.HASRINGPICBUF self.log("Retrieving fundamental phone information") self.log("Phone serial number") results['uniqueserial']=sha.new(self.getfilecontents("nvm/$SYS.ESN")).hexdigest() self.getmediaindices(results) self.log("Fundamentals retrieved") return results def sanyosort(self, a, b): "Sanyo sort order. Case insensitive, letters first" x=a[1] y=b[1] if(x[0:1].isalpha() and not y[0:1].isalpha()): return -1 if(y[0:1].isalpha() and not x[0:1].isalpha()): return 1 return cmp(x.lower(), y.lower()) def getsms(self, result): gsms = {} self.log("Getting sms entries") req=self.protocolclass.messagerequest() for slot in range(self.protocolclass.NUMMESSAGESLOTS): req.slot=slot res=self.sendpbcommand(req, self.protocolclass.messageresponse) if res.entry.dunno4==2: entry=sms.SMSEntry() entry.folder=entry.Folder_Inbox entry.datetime="200%d%02d%02dT%02d%02d%02d" % ((res.entry.year, res.entry.month, res.entry.day, res.entry.hour,res.entry.minute, res.entry.second)) if res.entry.read==17: entry.read=1 else: entry.read=0 entry._from=res.entry.phonenum entry.callback=res.entry.callback entry.subject="%d-%s-%s" % ((res.entry.counter, res.entry.phonenum, res.entry.message[:12])) self.log(res.entry.message[:8]) if res.entry.priority==100: entry.priority=sms.SMSEntry.Priority_Normal if res.entry.priority==200: entry.priority=sms.SMSEntry.Priority_High entry.text=unicode(res.entry.message, errors='ignore') gsms[entry.id]=entry result['sms']=gsms return result def gettodo(self, result): gtodo = {} self.log("Getting todo entries") req=self.protocolclass.todorequest() for slot in range(self.protocolclass.NUMTODOSLOTS): req.slot=slot res=self.sendpbcommand(req, self.protocolclass.todoresponse) entry=todo.TodoEntry() if res.entry.flag: entry.summary=res.entry.todo if res.entry.priority==2: entry.status=4 if res.entry.priority==0: entry.priority=5 if res.entry.priority==1: entry.priority=1 gtodo[entry.id]=entry result['todo']=gtodo return result def getphonebook(self,result): pbook={} sortstuff = self.getsanyobuffer(self.protocolclass.pbsortbuffer) if self.protocolclass.HASRINGPICBUF: ringpic = self.getsanyobuffer(self.protocolclass.ringerpicbuffer) speedslot=[] speedtype=[] for i in range(self.protocolclass._NUMSPEEDDIALS): speedslot.append(sortstuff.speeddialindex[i].pbslotandtype & 0xfff) numtype=(sortstuff.speeddialindex[i].pbslotandtype>>12)-1 if(numtype >= 0 and numtype <= len(self.numbertypetab)): speedtype.append(self.numbertypetab[numtype]) else: speedtype.append("") numentries=sortstuff.slotsused self.log("There are %d entries" % (numentries,)) count = 0 numcount = 0 numemail = 0 numurl = 0 res=self.protocolclass.phonebookentry() usedefaultnum = 'defaultnum' in res.getfields() print "usedefaultnum =",usedefaultnum req=self.protocolclass.phonebookslotrequest() for i in range(0, self.protocolclass._NUMPBSLOTS): if sortstuff.usedflags[i].used: req.slot = i res=self.sendpbcommand(req, self.protocolclass.phonebookslotresponse) self.log("Read entry "+`i`+" - "+res.entry.name) entry=self.extractphonebookentry(res.entry, result) for j in range(len(speedslot)): if(speedslot[j]==req.slot): for k in range(len(entry['numbers'])): if(entry['numbers'][k]['type']==speedtype[j]): entry['numbers'][k]['speeddial']=j+2 break if self.protocolclass.HASRINGPICBUF: if ringpic.ringtones[i].ringtone>0: try: tone=result['ringtone-index'][ringpic.ringtones[i].ringtone]['name'] except: tone=self.serialsname+"Index_"+`ringpic.ringtones[i].ringtone` entry['ringtones']=[{'ringtone': tone, 'use': 'call'}] if ringpic.wallpapers[i].wallpaper>0: try: paper=result['wallpaper-index'][ringpic.wallpapers[i].wallpaper]['name'] except: paper=self.serialsname+"Index_"+`ringpic.wallpapers[i].wallpaper` entry['wallpapers']=[{'wallpaper': paper, 'use': 'call'}] if usedefaultnum: firsttype=res.entry.defaultnum-1 if firsttype < len(self.numbertypetab): defaulttype=self.numbertypetab[firsttype] k=0 for j in range(len(entry['numbers'])): if entry['numbers'][j]['type'] == defaulttype: k=j break if k>0: exchange=entry['numbers'][k] for kk in range(k,0,-1): entry['numbers'][kk]=entry['numbers'][kk-1] entry['numbers'][0]=exchange pbook[count]=entry self.progress(count, numentries, res.entry.name) count+=1 numcount+=len(entry['numbers']) if entry.has_key('emails'): numemail+=len(entry['emails']) if entry.has_key('urls'): numurl+=len(entry['urls']) self.progress(numentries, numentries, "Phone book read completed") self.log("Phone contains "+`count`+" contacts, "+`numcount`+" phone numbers, "+`numemail`+" Emails, "+`numurl`+" URLs") result['phonebook']=pbook return pbook def extractphonebookentry(self, entry, fundamentals): """Return a phonebook entry in BitPim format""" res={} res['serials']=[ {'sourcetype': self.serialsname, 'serial1': entry.slot, 'serial2': entry.slotdup, 'sourceuniqueid': fundamentals['uniqueserial']} ] res['names']=[ {'full': entry.name} ] if len(entry.email): res['emails']=[ {'email': entry.email} ] if len(entry.url): res['urls']=[ {'url': entry.url} ] res['flags']=[ {'secret': entry.secret } ] res['numbers']=[] numberindex = 0 for type in self.numbertypetab: if len(entry.numbers[numberindex].number): res['numbers'].append({'number': entry.numbers[numberindex].number, 'type': type }) numberindex+=1 return res def _findmediaindex(self, index, name, pbentryname, type): if name is None: return 0 for i in index: if index[i]['name']==name: return i pos=name.find('_') if(pos>=0): i=int(name[pos+1:]) return i return 0 def makeentry(self, entry, dict): e=self.protocolclass.phonebookentry() for k in entry: if k=='ringtones' or k=='wallpapers' or k=='numbertypes': continue if k=='numbers': for numberindex in range(self.protocolclass.NUMPHONENUMBERS): enpn=self.protocolclass.phonenumber() e.numbers.append(enpn) for i in range(len(entry[k])): numberindex=entry['numbertypes'][i] e.numbers[numberindex].number=entry[k][i] e.numbers[numberindex].number_len=len(e.numbers[numberindex].number) continue setattr(e,k,entry[k]) return e def writewait(self): """Loop until phone status indicates ready to write""" for i in range(100): req=self.protocolclass.statusrequest() res=self.sendpbcommand(req, self.protocolclass.statusresponse) if res.ready==res.readyvalue: return time.sleep(0.1) self.log("Phone did not transfer to ready to write state") self.log("Waiting a bit longer and trying anyway") return def savephonebook(self, data): newphonebook={} self.mode=self.MODENONE self.setmode(self.MODEBREW) self.setmode(self.MODEPHONEBOOK) sortstuff=self.protocolclass.pbsortbuffer() ringpic=self.protocolclass.ringerpicbuffer() callerid=self.protocolclass.calleridbuffer() res=self.protocolclass.phonebookentry() usedefaultnum = 'defaultnum' in res.getfields() for i in range(self.protocolclass._NUMPBSLOTS): sortstuff.usedflags.append(0) sortstuff.firsttypes.append(0) sortstuff.sortorder.append(0xffff) sortstuff.sortorder2.append(0xffff) sortstuff.emails.append(0xffff) sortstuff.urls.append(0xffff) ringpic.ringtones.append(0) ringpic.wallpapers.append(0) for i in range(self.protocolclass._NUMSPEEDDIALS): sortstuff.speeddialindex.append(0xffff) for i in range(self.protocolclass._NUMLONGNUMBERS): sortstuff.longnumbersindex.append(0xffff) namemap=[] emailmap=[] urlmap=[] callerid.numentries=0 pbook=data['phonephonebook'] self.log("Putting phone into write mode") req=self.protocolclass.beginendupdaterequest() req.beginend=1 res=self.sendpbcommand(req, self.protocolclass.beginendupdateresponse, writemode=True) self.writewait() keys=pbook.keys() keys.sort() sortstuff.slotsused=len(keys) sortstuff.numemail=0 sortstuff.numurl=0 progresscur=0 progressmax=len(keys) self.log("Writing %d entries to phone" % (len(keys),)) nlongphonenumbers=0 nonumbercount=0 for ikey in keys: ii=pbook[ikey] slot=ii['slot'] progresscur+=1 self.progress(progresscur, progressmax, "Writing "+ii['name']) self.log("Writing entry "+`slot`+" - "+ii['name']) entry=self.makeentry(ii, data) if not usedefaultnum: delattr(entry,'defaultnum') req=self.protocolclass.phonebookslotupdaterequest() req.entry=entry res=self.sendpbcommand(req, self.protocolclass.phonebookslotresponse, writemode=True) entry=self.extractphonebookentry(entry, data) entry['ringtones']=[{'ringtone': ii['ringtone'], 'use': 'call'}] entry['wallpapers']=[{'wallpaper': ii['wallpaper'], 'use': 'call'}] sortstuff.usedflags[slot].used=1 if(len(ii['numbers'])): sortstuff.firsttypes[slot].firsttype=min(ii['numbertypes'])+1 else: if(len(ii['email'])): sortstuff.firsttypes[slot].firsttype=8 nonumbercount+=1 elif(len(ii['url'])): sortstuff.firsttypes[slot].firsttype=9 nonumbercount+=1 else: sortstuff.firsttypes[slot].firsttype=0 for i in range(len(ii['numbers'])): nindex=ii['numbertypes'][i] speeddial=ii['speeddials'][i] code=slot+((nindex+1)<<12) if(speeddial>=2 and speeddial<=self.protocolclass._NUMSPEEDDIALS+1): sortstuff.speeddialindex[speeddial-2]=code for k in range(len(entry['numbers'])): if(entry['numbers'][k]['type']==nindex): entry['numbers'][k]['speeddial']=speeddial break if(callerid.numentries<callerid.maxentries): phonenumber=ii['numbers'][i] cidentry=self.makecidentry(phonenumber,slot,nindex) callerid.items.append(cidentry) callerid.numentries+=1 if(len(phonenumber)>self.protocolclass._LONGPHONENUMBERLEN): if(nlongphonenumbers<self.protocolclass._NUMLONGNUMBERS): sortstuff.longnumbersindex[nlongphonenumbers].pbslotandtype=code namemap.append((slot,ii['name'])) if(len(ii['email'])): emailmap.append((slot,ii['email'])) sortstuff.numemail+=1 if(len(ii['url'])): urlmap.append((slot,ii['url'])) sortstuff.numurl+=1 ringpic.ringtones[slot].ringtone=self._findmediaindex(data['ringtone-index'], ii['ringtone'],ii['name'],'ringtone') ringpic.wallpapers[slot].wallpaper=self._findmediaindex(data['wallpaper-index'], ii['wallpaper'],ii['name'],'wallpaper') newphonebook[slot]=entry sortstuff.slotsused2=len(keys)-nonumbercount i=0 j=0 sortstuff.pbfirstletters="" namemap.sort(self.sanyosort) for (slot, name) in namemap: sortstuff.sortorder[i].pbslot=slot if sortstuff.firsttypes[slot].firsttype<=7: sortstuff.sortorder2[j].pbslot=slot j+=1 if name: sortstuff.pbfirstletters+=name[0] else: sortstuff.pbfirstletters+=chr(0) i+=1 i=0 sortstuff.emailfirstletters="" emailmap.sort(self.sanyosort) for (slot, email) in emailmap: sortstuff.emails[i].pbslot=slot sortstuff.emailfirstletters+=email[0] i+=1 i=0 sortstuff.urlfirstletters="" urlmap.sort(self.sanyosort) for (slot, url) in urlmap: sortstuff.urls[i].pbslot=slot sortstuff.urlfirstletters+=url[0] i+=1 self.sendsanyobuffer(sortstuff) if self.protocolclass.HASRINGPICBUF: self.sendsanyobuffer(ringpic) self.sendsanyobuffer(callerid) time.sleep(1.0) data['phonebook']=newphonebook del data['phonephonebook'] data['rebootphone'] = 1 def makecidentry(self, number, slot, nindex): "Prepare entry for caller ID lookup buffer" numstripped=re.sub("[^0-9PT#*]", "", number) numonly=re.sub("^(\\d*).*$", "\\1", numstripped) cidentry=self.protocolclass.calleridentry() cidentry.pbslotandtype=slot+((nindex+1)<<12) cidentry.actualnumberlen=len(numonly) cidentry.numberfragment=numonly[-10:] return cidentry def savewallpapers(self, results, merge): return self.savemedia('wallpapers', 'wallpaper-index', 'images', results, merge) def saveringtones(self, results, merge): return self.savemedia('ringtone', 'ringtone-index', 'ringers', results, merge) def savemedia(self, mediakey, mediaindexkey, mediatype, results, merge): """Actually saves out the media @param mediakey: key of the media (eg 'wallpapers' or 'ringtones') Index of media in wallpaper or ringer tab @param mediaindexkey: index key (eg 'wallpaper-index') Index of media on the phone @param results: results dict """ wp=results[mediakey].copy() wpi=results[mediaindexkey].copy() for k in wpi.keys(): if wpi[k]['origin']=='builtin': del wpi[k] for w in wp.keys(): name=wp[w]['name'] if wp[w].get("origin", "")=='camera': self.log("Not transferring camera picture "+name+" to phone") del wp[w] else: for k in wpi.keys(): if name==wpi[k]['name']: self.log("Not transferring "+name+" as it is already on the phone") del wp[w] break init={} init[mediatype]={} idx=0 for w in wp.keys(): idx-=1 data=wp[w]['data'] name=wp[w]['name'] init[mediatype][idx]={'name': name, 'data': data} index=init[mediatype] errors=False for key in index: efile=index[key]['name'] content=index[key]['data'] if content is None: continue if mediatype=='images': content = conversions.convertto8bitpng(content,16383) if not self.writesanyofile(efile, content): errors=True if errors: self.log("One or more files were rejected by the phone, due to") self.log("invalid file type (only PNG or MIDI are allowed), file") self.log("size too big, or too many ringers or wallpaper on the phone") self.log("See Sanyo Error Codes section of the Sanyh Phone Notes") self.log("in the help for more information") return results def writesanyofile(self, name, contents): start=time.time() self.log("Writing file '"+name+"' bytes "+`len(contents)`) desc="Writing "+name try: name=name[:name.index(".mid")] except: try: name=name[:name.index(".png")] except: pass if hasattr(self.protocolclass,"sanyomediathingyrequest"): req=self.protocolclass.sanyomediathingyrequest() req.faset = 0x10 res=self.sendpbcommand(req, self.protocolclass.sanyomediathingyresponse) time.sleep(10.0) req.faset = 0x13 res=self.sendpbcommand(req, self.protocolclass.sanyomediathingyresponse) req=self.protocolclass.sanyosendfilename() req.filename=name res=self.sendpbcommand(req, self.protocolclass.sanyosendfileresponse, returnerror=True) if 'errorcode' in res.getfields(): if res.errorcode==0x65: self.alert("Please put your phone into PC Sync Mode", False) else: raise SanyoCommandException(res.errorcode) waitcount=120 while waitcount>0: time.sleep(1.0) res=self.sendpbcommand(req, self.protocolclass.sanyosendfileresponse, returnerror=True) if not 'errorcode' in res.getfields(): break waitcount-=1 if waitcount==0: raise SanyoCommandException(res.errorcode) req=self.protocolclass.sanyosendfilesize() req.filesize=len(contents) self.sendpbcommand(req, self.protocolclass.sanyosendfileresponse) req=self.protocolclass.sanyosendfilefragment() packetsize=req.payloadsize offset=0 count=0 numblocks=len(contents)/packetsize+1 for offset in range(0, len(contents), packetsize): count+=1 if count % 5==0: self.progress(count,numblocks,desc) req.header.command=offset req.data=contents[offset:min(offset+packetsize,len(contents))] self.sendpbcommand(req, self.protocolclass.sanyosendfileresponse, writemode=True, returnerror=True) if 'errorcode' in res.getfields(): self.log(name+" not written due to error code "+`res.errorcode`) return False req=self.protocolclass.sanyosendfileterminator() try: res=self.sendpbcommand(req, self.protocolclass.sanyosendfileresponse, writemode=True, returnerror=True) if 'errorcode' in res.getfields(): self.log(name+" not written due to error code "+`res.errorcode`) return False except: self.log("Exception on writing terminator for file "+name) self.log("Continuing...") end=time.time() if end-start>3: self.log("Wrote "+`len(contents)`+" bytes at "+`int(len(contents)/(end-start))`+" bytes/second") return True def getcalendar(self,result): calres={} progressmax=self.protocolclass._NUMEVENTSLOTS+self.protocolclass._NUMCALLALARMSLOTS req=self.protocolclass.eventrequest() count=0 try: reqflag=self.protocolclass.eventslotinuserequest() except: reqflag=0 for i in range(0, self.protocolclass._NUMEVENTSLOTS): self.progress(i,progressmax,"Events") if reqflag: reqflag.slot=i resflag=self.sendpbcommand(reqflag, self.protocolclass.eventslotinuseresponse) if not resflag.flag: continue req.slot = i res=self.sendpbcommand(req, self.protocolclass.eventresponse) if not reqflag: if not res.entry.flag: continue self.log("Read calendar event "+`i`+" - "+res.entry.eventname+", alarm ID "+`res.entry.ringtone`) entry=bpcalendar.CalendarEntry() entry.changeserial=res.entry.serial entry.description=res.entry.eventname entry.location=res.entry.location starttime=res.entry.start entry.start=self.decodedate(starttime) entry.end=self.decodedate(res.entry.end) repeat=self._calrepeatvalues[res.entry.period] entry.repeat = self.makerepeat(repeat,entry.start) if res.entry.alarm==0xffffffff: entry.alarm=res.entry.alarmdiff/60 else: alarmtime=res.entry.alarm entry.alarm=(starttime-alarmtime)/60 ringtone=res.entry.ringtone if ringtone in self.calendar_tonerange: ringtone-=self.calendar_toneoffset if ringtone!=self.calendar_defaultringtone: if result['ringtone-index'].has_key(ringtone): entry.ringtone=result['ringtone-index'][ringtone]['name'] entry.snoozedelay=0 calres[entry.id]=entry count+=1 req=self.protocolclass.callalarmrequest() for i in range(0, self.protocolclass._NUMCALLALARMSLOTS): self.progress(self.protocolclass._NUMEVENTSLOTS,progressmax,"Call Alarms") req.slot=i res=self.sendpbcommand(req, self.protocolclass.callalarmresponse) if res.entry.flag and res.entry.date: self.log("Read call alarm entry "+`i`+" - "+res.entry.phonenum+", alarm ID "+`res.entry.ringtone`) entry=bpcalendar.CalendarEntry() entry.changeserial=res.entry.serial entry.description=res.entry.phonenum starttime=res.entry.date entry.start=self.decodedate(starttime) entry.end=entry.start repeat=self._calrepeatvalues[res.entry.period] entry.repeat = self.makerepeat(repeat,entry.start) entry.alarm=0 if res.entry.ringtone!=self.calendar_defaultcaringtone: entry.ringtone=result['ringtone-index'][res.entry.ringtone]['name'] entry.snoozedelay=0 calres[entry.id]=entry count+=1 result['calendar']=calres return result def makerepeat(self, repeatword, startdate): if repeatword is None: repeat_entry=None else: repeat_entry=bpcalendar.RepeatEntry() if repeatword=='daily': repeat_entry.repeat_type=repeat_entry.daily repeat_entry.interval=1 elif repeatword=='monfri': repeat_entry.repeat_type=repeat_entry.daily repeat_entry.interval=0 elif repeatword=='weekly': repeat_entry.repeat_type=repeat_entry.weekly repeat_entry.interval=1 dow=datetime.date(*startdate[:3]).isoweekday()%7 repeat_entry.dow=1<<dow elif repeatword=='monthly': repeat_entry.repeat_type=repeat_entry.monthly else: repeat_entry.repeat_type=repeat_entry.yearly return repeat_entry def savecalendar(self, dict, merge): cal=dict['calendar'] newcal={} keys=cal.keys() zonedif=time.mktime(time.gmtime(0))-time.mktime(time.localtime(0)) try: reqflag=self.protocolclass.eventslotinuseupdaterequest() except: reqflag=0 eventslot=0 callslot=0 progressmax=self.protocolclass._NUMEVENTSLOTS+self.protocolclass._NUMCALLALARMSLOTS for k in keys: entry=cal[k] descloc=entry.description self.progress(eventslot+callslot, progressmax, "Writing "+descloc) rp=entry.repeat if rp is None: repeat=0 else: repeatname=None if rp.repeat_type==rp.daily: repeatname='daily' elif rp.repeat_type==rp.weekly: repeatname='weekly' elif rp.repeat_type==rp.monthly: repeatname='monthly' elif rp.repeat_type==rp.yearly: repeatname='yearly' for k,v in self._calrepeatvalues.items(): if repeatname==v: repeat=k break if repeatname is None: self.log(descloc+": Repeat type "+`entry.repeat`+" not valid for this phone") repeat=0 phonenum=re.sub("\-","",descloc) now=time.mktime(time.localtime(time.time()))-zonedif if(phonenum.isdigit()): self.log("Write calendar call alarm slot "+`callslot`+ " - "+descloc) e=self.protocolclass.callalarmentry() e.slot=callslot e.phonenum=phonenum e.phonenum_len=len(e.phonenum) timearray=list(entry.start)+[0,0,0,0] starttimelocal=time.mktime(timearray)-zonedif if(starttimelocal<now and repeat==0): e.flag=2 else: e.flag=1 e.date=starttimelocal-self._sanyoepochtounix e.datedup=e.date e.phonenumbertype=0 e.phonenumberslot=0 e.name="" e.name_len=len(e.name) e.ringtone=self.calendar_defaultcaringtone print "Setting ringtone "+`e.ringtone` req=self.protocolclass.callalarmupdaterequest() callslot+=1 respc=self.protocolclass.callalarmresponse else: self.log("Write calendar event slot "+`eventslot`+ " - "+descloc) e=self.protocolclass.evententry() e.slot=eventslot slashpos=descloc.find('/') if(slashpos >= 0): eventname=descloc[0:slashpos] location=descloc[slashpos+1:] else: eventname=descloc location='' e.eventname=descloc e.eventname_len=len(e.eventname) e.location=entry.location e.location_len=len(e.location) timearray=list(entry.start)+[0,0,0,0] starttimelocal=time.mktime(timearray)-zonedif e.start=starttimelocal-self._sanyoepochtounix try: timearray=list(entry.end)+[0,0,0,0] endtimelocal=time.mktime(timearray)-zonedif e.end=endtimelocal-self._sanyoepochtounix except: e.end=e.start+60 alarmdiff=entry.alarm if alarmdiff<0: alarmdiff=0 alarmdiff=max(alarmdiff,0)*60 e.alarmdiff=alarmdiff e.alarm=starttimelocal-self._sanyoepochtounix-alarmdiff if reqflag: reqflag.slot=eventslot if(e.alarm+self._sanyoepochtounix<now and repeat==0): reqflag.flag=4 else: reqflag.flag=1 res=self.sendpbcommand(reqflag, self.protocolclass.eventslotinuseresponse) else: if(starttimelocal<now and repeat==0): e.flag=2 else: e.flag=1 try: timearray=list(entry.end)+[0,0,0,0] endtimelocal=time.mktime(timearray)-zonedif e.end=endtimelocal-self._sanyoepochtounix except: e.end=e.start+60 e.ringtone=self.calendar_defaultringtone print "Setting ringtone "+`e.ringtone` req=self.protocolclass.eventupdaterequest() eventslot+=1 respc=self.protocolclass.eventresponse e.period=repeat e.dom=entry.start[2] if entry.id>=0 and entry.id<256: e.serial=entry.id else: e.serial=0 req.entry=e res=self.sendpbcommand(req, respc, writemode=True) if reqflag: req=reqflag req.flag=0 else: e=self.protocolclass.evententry() e.flag=0 e.eventname="" e.eventname_len=0 e.location="" e.location_len=0 e.start=0 e.end=0 e.period=0 e.dom=0 e.ringtone=0 e.alarm=0 e.alarmdiff=0 req=self.protocolclass.eventupdaterequest() req.entry=e for eventslot in range(eventslot,self.protocolclass._NUMEVENTSLOTS): self.progress(eventslot+callslot, progressmax, "Writing unused") self.log("Write calendar event slot "+`eventslot`+ " - Unused") if reqflag: req.slot=eventslot else: req.entry.slot=eventslot res=self.sendpbcommand(req, self.protocolclass.eventresponse, writemode=True) e=self.protocolclass.callalarmentry() e.flag=0 e.name="" e.name_len=0 e.phonenum="" e.phonenum_len=0 e.date=0 e.datedup=0 e.period=0 e.dom=0 e.ringtone=0 e.phonenumbertype=0 e.phonenumberslot=0 req=self.protocolclass.callalarmupdaterequest() req.entry=e for callslot in range(callslot,self.protocolclass._NUMCALLALARMSLOTS): self.progress(eventslot+callslot, progressmax, "Writing unused") self.log("Write calendar call alarm slot "+`callslot`+ " - Unused") req.entry.slot=callslot res=self.sendpbcommand(req, self.protocolclass.callalarmresponse, writemode=True) self.progress(progressmax, progressmax, "Calendar write done") dict['rebootphone'] = True return dict def getcallhistory(self, result): res={} self._readhistory(self.protocolclass.OUTGOING,'Outgoing',res) self._readhistory(self.protocolclass.MISSED,'Missed',res) self._readhistory(self.protocolclass.INCOMING,'Incoming',res) result['call_history']=res return result def _readhistory(self, type, folder, res): req=self.protocolclass.historyrequest() req.type=type for slot in range(self.protocolclass.NUMCALLHISTORY): req.slot=slot call=self.sendpbcommand(req, self.protocolclass.historyresponse) if call.entry.phonenum=='' and call.entry.name=='': continue entry=call_history.CallHistoryEntry() entry.folder=folder entry.name=call.entry.name entry.number=call.entry.phonenum entry.datetime=((call.entry.date)) res[entry.id]=entry def decodedate(self,val): """Unpack 32 bit value into date/time @rtype: tuple @return: (year, month, day, hour, minute) """ return list(time.gmtime(val+self._sanyoepochtounix)[:5]) _calrepeatvalues={ 0: None, 1: 'daily', 2: 'weekly', 3: 'monthly', 4: 'yearly' } "Talk to a Sanyo Sprint Phone such as SCP-4900, SCP-5300, or SCP-8100" def phonize(str): """Convert the phone number into something the phone understands All digits, P, T, * and # are kept, everything else is removed""" return re.sub("[^0-9PT#*]", "", str) class Profile (com_phone.Profile) : serialsname='sanyo' WALLPAPER_WIDTH=120 WALLPAPER_HEIGHT=128 OVERSIZE_PERCENTAGE=100 MAX_WALLPAPER_BASENAME_LENGTH=19 WALLPAPER_FILENAME_CHARS="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 .`~!@#$%^&()-_=+[{]};\'" WALLPAPER_CONVERT_FORMAT="png" MAX_RINGTONE_BASENAME_LENGTH=19 RINGTONE_FILENAME_CHARS="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 .`~!@#$%^&()-_=+[{]};\'" usbids=( ( 0x0474, 0x0701, 1), ) deviceclasses=("modem",) BP_Calendar_Version=3 def __init__(self): self.numbertypetab=numbertypetab com_phone.Profile.__init__(self) _supportedsyncs=( ('phonebook', 'read', None), ('calendar', 'read', None), ('phonebook', 'write', 'OVERWRITE'), ('calendar', 'write', 'OVERWRITE'), ('wallpaper', 'write', 'MERGE'), ('ringtone', 'write', 'MERGE'), ('call_history', 'read', None), ('sms', 'read', None), ) def convertphonebooktophone(self, helper, data): "Converts the data to what will be used by the phone" results={} slotsused={} for pbentry in data['phonebook']: entry=data['phonebook'][pbentry] serial1=helper.getserial(entry.get('serials', []), self.serialsname, data['uniqueserial'], 'serial1', -1) if(serial1 >= 0 and serial1 < self.protocolclass._NUMPBSLOTS): slotsused[serial1]=1 lastunused=0 for pbentry in data['phonebook']: e={} entry=data['phonebook'][pbentry] try: try: e['name']=helper.getfullname(entry.get('names', []),1,1,16)[0] except: e['name']='' e['name_len']=len(e['name']) serial1=helper.getserial(entry.get('serials', []), self.serialsname, data['uniqueserial'], 'serial1', -1) if(serial1 >= 0 and serial1 < self.protocolclass._NUMPBSLOTS): e['slot']=serial1 else: while(slotsused.has_key(lastunused)): lastunused+=1 if(lastunused >= self.protocolclass._NUMPBSLOTS): raise helper.ConversionFailed() e['slot']=lastunused slotsused[lastunused]=1 e['slotdup']=e['slot'] e['email']=helper.makeone(helper.getemails(entry.get('emails', []),0,1,self.protocolclass._MAXEMAILLEN), "") e['email_len']=len(e['email']) e['url']=helper.makeone(helper.geturls(entry.get('urls', []), 0,1,self.protocolclass._MAXEMAILLEN), "") e['url_len']=len(e['url']) numbers=helper.getnumbers(entry.get('numbers', []),0,7) e['numbertypes']=[] e['numbers']=[] e['speeddials']=[] unusednumbers=[] typesused={} defaultnum=0 for num in numbers: typename=num['type'] if(typesused.has_key(typename)): unusednumbers.append(num) continue typesused[typename]=1 for typenum,tnsearch in enumerate(self.numbertypetab): if typename==tnsearch: if defaultnum==0: defaultnum=typenum+1 number=phonize(num['number']) if len(number)>self.protocolclass._MAXNUMBERLEN: number=number[:self.protocolclass._MAXNUMBERLEN] e['numbers'].append(number) if(num.has_key('speeddial')): e['speeddials'].append(num['speeddial']) else: e['speeddials'].append(-1) e['numbertypes'].append(typenum) break trytype=len(self.numbertypetab) for num in unusednumbers: while trytype>0: trytype-=1 if not typesused.has_key(self.numbertypetab[trytype]): break else: break if defaultnum==0: defaultnum=trytype+1 number=phonize(num['number']) if len(number)>self.protocolclass._MAXNUMBERLEN: number=number[:self.protocolclass._MAXNUMBERLEN] e['numbers'].append(number) e['numbertypes'].append(trytype) if(num.has_key('speeddial')): e['speeddials'].append(num['speeddial']) else: e['speeddials'].append(-1) if defaultnum==0: if e['url_len'] > 0: defaultnum=8 elif e['email_len'] > 0: defaultnum=9 e['ringtone']=helper.getringtone(entry.get('ringtones', []), 'call', None) e['wallpaper']=helper.getwallpaper(entry.get('wallpapers', []), 'call', None) e['secret']=helper.getflag(entry.get('flags', []), 'secret', False) e['defaultnum']=defaultnum results[pbentry]=e except helper.ConversionFailed: print "No Free Slot for "+e['name'] continue data['phonephonebook']=results return data class Phone (SanyoPhonebook,com_phone.Phone,com_brew.BrewProtocol) : "Talk to a Sanyo Sprint Phone such as SCP-4900, SCP-5300, or SCP-8100" desc="Sanyo" imagelocations=() ringtonelocations=() builtinimages=() builtinringtones=() def __init__(self, logtarget, commport): "Call all the contructors and sets initial modes" com_phone.Phone.__init__(self, logtarget, commport) com_brew.BrewProtocol.__init__(self) SanyoPhonebook.__init__(self) self.log("Attempting to contact phone") self.mode=self.MODENONE getwallpapers=None getringtones=None "Talk to a Sanyo Sprint Phone such as SCP-4900, SCP-5300, or SCP-8100"
def sendpbcommand( self, request, responseclass, callsetmode=True, writemode=False, numsendretry=0, returnerror=False ): if writemode: numretry = 3 else: numretry = 0 if callsetmode: self.setmode(self.MODEPHONEBOOK) buffer = prototypes.buffer() request.writetobuffer(buffer, logtitle="Samsung phonebook request") data = buffer.getvalue() firsttwo = data[:2] data = common.pppescape(data + common.crcs(data)) + common.pppterminator isendretry = numsendretry while isendretry >= 0: try: rdata = self.comm.writethenreaduntil( data, False, common.pppterminator, logreaduntilsuccess=False, numfailures=numretry ) break except com_phone.modeignoreerrortypes: if isendretry > 0: self.log("Resending request packet...") time.sleep(0.3) else: self.comm.success = False self.mode = self.MODENONE self.raisecommsdnaexception("manipulating the phonebook") isendretry -= 1 self.comm.success = True origdata = rdata # sometimes there is junk at the beginning, eg if the user # turned off the phone and back on again. So if there is more # than one 7e in the escaped data we should start after the # second to last one d = rdata.rfind(common.pppterminator, 0, -1) if d >= 0: self.log("Multiple Samsung packets in data - taking last one starting at " + ` d + 1 `) self.logdata("Original Samsung data", origdata, None) rdata = rdata[d + 1 :] # turn it back to normal data = common.pppunescape(rdata) # Sometimes there is other crap at the beginning. But it might # be a Sanyo error byte. So strip off bytes from the beginning # until the crc agrees, or we get to the first two bytes of the # request packet. d = data.find(firsttwo) crc = data[-3:-1] crcok = False for i in range(0, d + 1): trydata = data[i:-3] if common.crcs(trydata) == crc: crcok = True break if not crcok: self.logdata("first two", firsttwo, None) self.logdata("Original Sanyo data", origdata, None) self.logdata("Working on Sanyo data", data, None) raise common.CommsDataCorruption("Sanyo packet failed CRC check", self.desc) res = responseclass() if d > 0: if d == i: self.log("Junk at beginning of Sanyo packet, data at " + ` d `) self.logdata("Original Sanyo data", origdata, None) self.logdata("Working on Sanyo data", data, None) else: if returnerror: res = self.protocolclass.sanyoerror() else: self.log("Sanyo Error code " + ` ord(data[0]) `) self.logdata("sanyo phonebook response", data, None) raise SanyoCommandException(ord(data[0])) data = trydata # parse data buffer = prototypes.buffer(data) res.readfrombuffer(buffer, logtitle="sanyo phonebook response") return res