0001 ### BITPIM 0002 ### 0003 ### Copyright (C) 2003 Roger Binns <rogerb@rogerbinns.com> 0004 ### Copyright (C) 2003 Scott Craig <scott.craig@shaw.ca> 0005 ### Copyright (C) 2003 Alan Gonzalez <agonzalez@yahoo.com> 0006 ### 0007 ### This program is free software; you can redistribute it and/or modify 0008 ### it under the terms of the BitPim license as detailed in the LICENSE file. 0009 ### 0010 ### $Id: com_lgtm520.py 4543 2008-01-04 23:44:24Z djpham $ 0011 0012 "Talk to the LG TM520/VX10 cell phone" 0013 0014 # standard modules 0015 import re 0016 import time 0017 import cStringIO 0018 import sha 0019 0020 # my modules 0021 import common 0022 import p_lgtm520 0023 import com_brew 0024 import com_phone 0025 import com_lg 0026 import prototypes 0027 0028 typemap = { 0029 'fwd': ( 'home', 'office', 'cell', 'pager', 'data' ), 0030 'rev': { 'home': 0, 'office': 1, 'cell': 2, 'pager': 3, 'data': 4, 'fax': 4 } 0031 } 0032 0033 class Phone(com_phone.Phone,com_brew.BrewProtocol,com_lg.LGPhonebook): 0034 "Talk to the LG TM520/VX10 cell phone" 0035 desc="LG-TM520/VX10" 0036 protocolclass=p_lgtm520 0037 serialsname='lgtm520' 0038 0039 ringtonelocations=( 0040 # offset, index file, files location, type, maximumentries 0041 # There really isn't an index file 0042 ( 0, "", "ringer", "ringers", 5), 0043 # phonebook linkage 0044 #( 0, "pim/midiringer.dat", "ringer", "ringers", 199), 0045 # main ringer 0046 #( 0, "pim/ringtitle.dat", "ringer", "ringers", 1), 0047 ) 0048 0049 builtinringtones=( 'Standard1', 'Standard2', 'Standard3', 'Standard4', 0050 'Standard5', 'Radetzky March', 'Nocturn', 'Carmen', 0051 'La Traviata', 'Liberty Bell', 'Semper Fidelis', 0052 'Take Me Out', 'Turkey In The Straw', 'We Wish...', 0053 'Csikos Post', 'Bumble Bee Twist', 'Badinerie', 0054 'Silken Ladder', 'Chestnut' ) 0055 0056 # phone uses Jan 1, 1980 as epoch. Python uses Jan 1, 1970. This is difference 0057 # plus a fudge factor of 5 days, 20 hours for no reason I can find 0058 _tm520epochtounix=315532800+460800 0059 _brewepochtounix=315532800+460800 # trying to override inherited entry 0060 _calrepeatvalues={ 0: None, 1: None, 2: 'daily' } 0061 0062 getwallpapers=None 0063 0064 def __init__(self, logtarget, commport): 0065 com_phone.Phone.__init__(self, logtarget, commport) 0066 com_brew.BrewProtocol.__init__(self) 0067 com_lg.LGPhonebook.__init__(self) 0068 self.log("Attempting to contact phone") 0069 self.mode=self.MODENONE 0070 0071 def getfundamentals(self, results): 0072 """Gets information fundamental to interopating with the phone and UI.""" 0073 0074 # use a hash of ESN and other stuff (being paranoid) 0075 self.log("Retrieving fundamental phone information") 0076 self.log("Phone serial number") 0077 results['uniqueserial']=sha.new(self.getfilecontents("nvm/$SYS.ESN")).hexdigest() 0078 results['ringtone-index'] = {} 0079 ringcount = 1 0080 for r in self.builtinringtones: 0081 results['ringtone-index'][ringcount] = {'name': r, 'origin': 'builtin'} 0082 ringcount += 1 0083 0084 try: 0085 ringers=self.getfilesystem('ringer') 0086 for r in ringers.keys(): 0087 results['ringtone-index'][ringcount] = {'name': r[len('ringer/'):], 'origin': 'ringers'} 0088 ringcount +=1 0089 except com_brew.BrewNoSuchDirectoryException: 0090 self.log("Ringer directory doesn't exist, firmware might not be download capable") 0091 self.log("Fundamentals retrieved") 0092 return results 0093 0094 def pbinit(self): 0095 self.mode = self.MODEPHONEBOOK 0096 self.sendpbcommand(self.protocolclass.pbstartsyncrequest(), self.protocolclass.pbstartsyncresponse) 0097 0098 self.mode = self.MODEBREW 0099 res=self.sendpbcommand(self.protocolclass.pbinforequest(), self.protocolclass.pbinforesponse) 0100 0101 return res.numentries 0102 0103 def pbend(self): 0104 req=self.protocolclass.pbendsyncrequest() 0105 self.sendpbcommand(req, self.protocolclass.pbendsyncresponse) 0106 0107 def pregetpb(self, result): 0108 index={} 0109 try: 0110 buf=prototypes.buffer(self.getfilecontents("pim/midiringer.dat")) 0111 except com_brew.BrewNoSuchFileException: 0112 # file may not exist 0113 result['intermediate'] = index 0114 return 0115 g=self.protocolclass.ringindex() 0116 g.readfrombuffer(buf, logtitle="ringer index") 0117 for i in g.items: 0118 if i.name != "default": 0119 index[i.index+1]=i.name[len('ringer/'):] 0120 result['intermediate'] = index 0121 0122 def postgetdb(self, result): 0123 #cats=[] 0124 #for i in result['groups']: 0125 # if result['groups'][i]['name']!='No Group': 0126 # cats.append(result['groups'][i]['name']) 0127 #result['categories'] = cats 0128 del result['intermediate'] 0129 0130 def getphonebook(self,result): 0131 """Reads the phonebook data. The L{getfundamentals} information will 0132 already be in result.""" 0133 pbook={} 0134 # Bug in the phone. if you repeatedly read the phone book it starts 0135 # returning a random number as the number of entries. We get around 0136 # this by switching into brew mode which clears that. 0137 #self.mode=self.MODENONE 0138 #self.setmode(self.MODEBREW) 0139 0140 self.pregetpb(result) 0141 self.log("Reading number of phonebook entries") 0142 0143 numentries=self.pbinit() 0144 self.log("There are %d entries" % (numentries,)) 0145 for i in range(0, numentries): 0146 ### Read current entry 0147 req=self.protocolclass.pbreadentryrequest() 0148 res=self.sendpbcommand(req, self.protocolclass.pbreadentryresponse) 0149 self.log("Read entry "+`i`+" - "+res.entry.name) 0150 entry=self.extractphonebookentry(res.entry, result) 0151 pbook[i]=entry 0152 self.progress(i, numentries, res.entry.name) 0153 #### Advance to next entry 0154 req=self.protocolclass.pbnextentryrequest() 0155 self.sendpbcommand(req, self.protocolclass.pbnextentryresponse) 0156 0157 self.progress(numentries, numentries, "Phone book read completed") 0158 result['phonebook']=pbook 0159 self.pbend() 0160 self.postgetdb(result) 0161 0162 print "returning keys",result.keys() 0163 return pbook 0164 0165 def extractphonebookentry(self, entry, fundamentals): 0166 """Return a phonebook entry in BitPim format""" 0167 res={} 0168 # serials 0169 res['serials']=[ {'sourcetype': self.serialsname, 'serial1': entry.serial1, 'serial2': entry.serial2, 0170 'sourceuniqueid': fundamentals['uniqueserial']} ] 0171 # only one name 0172 res['names']=[ {'full': entry.name} ] 0173 # only one email 0174 if len(entry.email) > 0: res['emails']=[ {'email': entry.email} ] 0175 res['flags'] = [] 0176 # we only supply secret/voicetag if it is true 0177 if entry.secret: res['flags'].append({'secret': entry.secret }) 0178 if entry.voicetag: res['flags'].append({'voicetag': entry.voicetag }) 0179 0180 # ringtones 0181 res['ringtones'] = [] 0182 if entry.ringtone > 0: 0183 # individual ringtone 0184 if entry.ringtone > len(self.builtinringtones): 0185 # custom individual ringtone 0186 try: 0187 res['ringtones'].append({'ringtone': fundamentals['intermediate'][entry.entrynumber], 'use': 'call'}) 0188 except: 0189 self.log('Custom ringtone not properly assigned for '+entry.name) 0190 else: 0191 # stock individual ringtone 0192 res['ringtones'].append({'ringtone': fundamentals['ringtone-index'][entry.ringtone]['name'], 'use': 'call'}) 0193 # 5 phone numbers 0194 res['numbers']=[] 0195 numbernumber=0 0196 for type in typemap['fwd']: 0197 item = entry.numbers[numbernumber] 0198 if len(item.number) > 0: 0199 res['numbers'].append({'number': item.number, 'type': type, 'sum': item.chksum }) 0200 if numbernumber == entry.default: res['numbers'][-1]['speeddial'] = entry.entrynumber 0201 numbernumber+=1 0202 return res 0203 0204 def savegroups(self, data): pass 0205 0206 def savephonebook(self, data): 0207 self.savegroups(data) 0208 # To write the phone book, we scan through all existing entries 0209 # and record their record number and serials. 0210 # We then delete any entries that aren't in data 0211 # We then write out our records, usng overwrite or append 0212 # commands as necessary 0213 serialupdates=[] 0214 existingpbook={} # keep track of the phonebook that is on the phone 0215 ringindex = {} 0216 0217 # Ringtones 0218 pbook = data['phonebook'] 0219 for i in pbook.keys(): 0220 if not 'ringtone' in pbook[i]: continue 0221 if not pbook[i]['ringtone'] is None and not pbook[i]['ringtone'] in self.builtinringtones: 0222 ringindex[pbook[i]['entrynumber']] = pbook[i]['ringtone']; 0223 0224 ringidxfile=self.protocolclass.ringindex() 0225 for i in range(1, 200): 0226 ringerentry = self.protocolclass.ringentry() 0227 ringerentry.index = i 0228 ringerentry.name = '' 0229 if i in ringindex: ringerentry.name = 'ringer/'+ringindex[i] 0230 ringidxfile.items.append(ringerentry) 0231 buf=prototypes.buffer() 0232 ringidxfile.writetobuffer(buf, logtitle="Custom ringer index") 0233 0234 # ::TODO:: this code looks wrong. Why isn't the if before the loop above? 0235 # and if the user deleted all ringers then shouldn't the file be truncated 0236 # rather than ignored? 0237 if len(ringindex) > 0: 0238 self.writefile("pim/midiringer.dat", buf.getvalue()) 0239 0240 #self.mode=self.MODENONE 0241 #self.setmode(self.MODEBREW) # see note in getphonebook() for why this is necessary 0242 #self.setmode(self.MODEPHONEBOOK) 0243 # similar loop to reading 0244 numexistingentries=self.pbinit() 0245 progressmax=numexistingentries+len(data['phonebook'].keys()) 0246 progresscur=0 0247 self.log("There are %d existing entries" % (numexistingentries,)) 0248 for i in range(0, numexistingentries): 0249 ### Read current entry 0250 req=self.protocolclass.pbreadentryrequest() 0251 res=self.sendpbcommand(req, self.protocolclass.pbreadentryresponse) 0252 0253 entry={ 'number': res.entry.entrynumber, 'serial1': res.entry.serial1, 0254 'serial2': res.entry.serial2, 'name': res.entry.name} 0255 assert entry['serial1']==entry['serial2'] # always the same 0256 self.log("Reading entry "+`i`+" - "+entry['name']) 0257 existingpbook[i]=entry 0258 self.progress(progresscur, progressmax, "existing "+entry['name']) 0259 #### Advance to next entry 0260 req=self.protocolclass.pbnextentryrequest() 0261 self.sendpbcommand(req, self.protocolclass.pbnextentryresponse) 0262 progresscur+=1 0263 # we have now looped around back to begining 0264 0265 # Find entries that have been deleted 0266 pbook=data['phonebook'] 0267 dellist=[] 0268 for i in range(0, numexistingentries): 0269 ii=existingpbook[i] 0270 serial=ii['serial1'] 0271 item=self._findserial(serial, pbook) 0272 if item is None: 0273 dellist.append(i) 0274 0275 progressmax+=len(dellist) # more work to do 0276 0277 # Delete those entries 0278 for i in dellist: 0279 progresscur+=1 0280 numexistingentries-=1 # keep count right 0281 ii=existingpbook[i] 0282 self.log("Deleting entry "+`i`+" - "+ii['name']) 0283 req=self.protocolclass.pbdeleteentryrequest() 0284 req.serial1=ii['serial1'] 0285 req.serial2=ii['serial2'] 0286 req.entrynumber=ii['number'] 0287 self.sendpbcommand(req, self.protocolclass.pbdeleteentryresponse) 0288 self.progress(progresscur, progressmax, "Deleting "+ii['name']) 0289 # also remove them from existingpbook 0290 del existingpbook[i] 0291 0292 # counter to keep track of record number (otherwise appends don't work) 0293 counter=0 0294 # Now rewrite out existing entries 0295 keys=existingpbook.keys() 0296 existingserials=[] 0297 keys.sort() # do in same order as existingpbook 0298 for i in keys: 0299 progresscur+=1 0300 ii=pbook[self._findserial(existingpbook[i]['serial1'], pbook)] 0301 self.log("Rewriting entry "+`i`+" - "+ii['name']) 0302 self.progress(progresscur, progressmax, "Rewriting "+ii['name']) 0303 entry=self.makeentry(counter, ii, data) 0304 counter+=1 0305 existingserials.append(existingpbook[i]['serial1']) 0306 req=self.protocolclass.pbupdateentryrequest() 0307 req.entry=entry 0308 res=self.sendpbcommand(req, self.protocolclass.pbupdateentryresponse) 0309 serialupdates.append( ( ii["bitpimserial"], 0310 {'sourcetype': self.serialsname, 'serial1': res.serial1, 'serial2': res.serial1, 0311 'sourceuniqueid': data['uniqueserial']}) 0312 ) 0313 assert ii['serial1']==res.serial1 # serial should stay the same 0314 0315 # Finally write out new entries 0316 keys=pbook.keys() 0317 keys.sort() 0318 for i in keys: 0319 ii=pbook[i] 0320 if ii['serial1'] in existingserials: 0321 continue # already wrote this one out 0322 progresscur+=1 0323 entry=self.makeentry(counter, ii, data) 0324 counter+=1 0325 self.log("Appending entry "+ii['name']) 0326 self.progress(progresscur, progressmax, "Writing "+ii['name']) 0327 req=self.protocolclass.pbappendentryrequest() 0328 req.entry=entry 0329 res=self.sendpbcommand(req, self.protocolclass.pbappendentryresponse) 0330 serialupdates.append( ( ii["bitpimserial"], 0331 {'sourcetype': self.serialsname, 'serial1': res.newserial, 'serial2': res.newserial, 0332 'sourceuniqueid': data['uniqueserial']}) 0333 ) 0334 0335 self.pbend() 0336 data["serialupdates"]=serialupdates 0337 if len(ringindex) == 0: return 0338 0339 0340 def _findserial(self, serial, dict): 0341 """Searches dict to find entry with matching serial. If not found, 0342 returns None""" 0343 for i in dict: 0344 if dict[i]['serial1']==serial: 0345 return i 0346 return None 0347 0348 def getcalendar(self,result): 0349 res={} 0350 # Now read schedule 0351 buf=prototypes.buffer(self.getfilecontents("sch/sch_00.dat")) 0352 sc=self.protocolclass.schedulefile() 0353 sc.readfrombuffer(buf, logtitle="Calendar") 0354 self.logdata("Calendar", buf.getdata(), sc) 0355 for event in sc.events: 0356 entry={} 0357 if event.state == 0 or event.repeat == 0: continue # deleted entry 0358 if event.date == 0x11223344: continue # blanked entry 0359 date = event.date 0360 date += self._tm520epochtounix 0361 entry['start'] = self.decodedate(date) 0362 entry['end'] = self.decodedate(date) 0363 entry['pos']=event.pos 0364 entry['description'] = event.description 0365 if event.pos == 0: entry['description'] = 'Wake Up' 0366 entry['alarm'] = 0 0367 if event.alarm & 0xB0 == 0xB0: entry['alarm'] = 1 0368 entry['ringtone'] = 0 0369 entry['changeserial'] = 0 0370 entry['repeat'] = self._calrepeatvalues[event.repeat] 0371 0372 # Hack - using snoozedelay to store the DST flag 0373 entry['snoozedelay'] = time.localtime(date)[8] 0374 res[event.pos]=entry 0375 0376 result['calendar']=res 0377 return result 0378 0379 def savecalendar(self, dict, merge): 0380 # ::TODO:: obey merge param 0381 # what will be written to the files 0382 eventsf=self.protocolclass.schedulefile() 0383 0384 # what are we working with 0385 cal=dict['calendar'] 0386 newcal={} 0387 keys=cal.keys() 0388 keys.sort() 0389 0390 # number of entries 0391 numactiveitems=len(keys) 0392 self.log("There are %d calendar entries" % (numactiveitems,)) 0393 counter = 1 0394 0395 # Write out alarm entry - see below for special handling 0396 alarm=self.protocolclass.scheduleevent() 0397 alarm.pos = 0 0398 alarm.date = 0x11223344 0399 alarm.state = 0 0400 alarm.alarm = 0x80 0401 alarm.repeat = 0 0402 alarm.description = " NO ENTRY NO ENTRY " 0403 0404 eventsf.events.append(dummy) 0405 # play with each entry 0406 for k in keys: 0407 # entry is what we will return to user 0408 entry=cal[k] 0409 data=self.protocolclass.scheduleevent() 0410 if counter >= 50: 0411 self.log("More than 49 entries in calendar, only writing out the first 49") 0412 break 0413 data.pos=counter 0414 counter+=1 0415 entry['pos']=data.pos 0416 # simple copy of these fields 0417 for field in 'start','description': 0418 setattr(data,field,entry[field]) 0419 0420 data.state = 2 0421 data.alarm = 0 0422 data.repeat = 1 0423 0424 dst = -1 0425 if entry['snoozedelay']: dst = entry['snoozedelay'] 0426 data.date = self.encodedate(entry['start'],dst)-self._tm520epochtounix 0427 0428 # Special alarm handling - TM520 is not capable of having an alarmed 0429 # entry, so we will only alarm on the earliest entry 0430 if entry['alarm'] > 0 and ( alarm.date == 0x11223344 or data.date < alarm.date ): 0431 alarm.date = data.date 0432 alarm.state = 1 0433 alarm.alarm = 0xB0 0434 alarm.repeat = 1 0435 if entry['repeat'] > 0: alarm.repeat = 2 0436 0437 # put entry in nice shiny new dict we are building 0438 newcal[data.pos]=entry 0439 eventsf.events.append(data) 0440 0441 if counter < 50: 0442 for i in range(counter, 50): 0443 dummy=self.protocolclass.scheduleevent() 0444 dummy.pos = i 0445 dummy.date = 0x11223344 0446 dummy.state = 0 0447 dummy.alarm = 0x80 0448 dummy.repeat = 0 0449 dummy.description = " NO ENTRY NO ENTRY " 0450 eventsf.events.append(dummy) 0451 0452 # scribble everything out 0453 buf=prototypes.buffer() 0454 eventsf.writetobuffer(buf, logtitle="Writing calendar") 0455 self.writefile("sch/sch_00.dat", buf.getvalue()) 0456 0457 # fix passed in dict 0458 dict['calendar']=newcal 0459 0460 return dict 0461 0462 def getringtones(self, result): 0463 media = {} 0464 try: 0465 ringers=self.getfilesystem('ringer') 0466 for r in ringers: 0467 name = r[len('ringer/'):] 0468 media[name] = self.getfilecontents(r) 0469 except com_brew.BrewNoSuchDirectoryException: pass 0470 result['ringtone'] = media 0471 return result 0472 0473 def saveringtones(self, results, merge): 0474 try: 0475 ringers=self.getfilesystem('ringer') 0476 for r in ringers.keys(): 0477 ringers[r[len('ringer/'):]] = ringers[r] 0478 del ringers[r] 0479 except com_brew.BrewNoSuchDirectoryException: 0480 self.log("Ringer directory doesn't exist, firmware might not be download capable") 0481 return results 0482 0483 index={} 0484 for r in results['ringtone-index']: 0485 if r['origin'] == 'ringers': index.append(r['name']) 0486 0487 for r in ringers.keys(): 0488 # it is in the original index, are we writing it back out? 0489 if r in index and ringers[r]['size'] == len(results['ringtone'][r]): continue 0490 else: 0491 if not merge or r in index: 0492 # go ahead and delete unwanted files 0493 print "deleting",r 0494 self.rmfile("ringer/"+r) 0495 if r in index: self.writefile("ringer/"+r, results['ringtone'][r]) 0496 0497 def decodedate(self,val): 0498 """Unpack 32 bit value into date/time 0499 0500 @rtype: tuple 0501 @return: (year, month, day, hour, minute) 0502 """ 0503 return time.localtime(val)[:5] 0504 0505 def encodedate(self,val,dst): 0506 tmp = [] 0507 for i in val: tmp.append(i) 0508 tmp += [0, 0, 0, dst] 0509 return time.mktime(tmp) 0510 0511 def _findringtoneindex(self, index, name, pbentryname): 0512 if name is None: return 0 0513 for i in index: 0514 if index[i]['name'] == name: 0515 return i 0516 self.log("%s: Unable to find ringtone %s in the index. Setting to default." % (pbentryname, name)) 0517 return 0 0518 0519 def _calcnumsum(self, entry, number): 0520 sumtbl = { '0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9, 0521 'H': 24, 'T': 36, '#': -13, '*': -6 } 0522 entry.number = number 0523 entry.chksum = 0 0524 lastseven = number 0525 if len(lastseven) > 7: lastseven = lastseven[len(lastseven)-7:] 0526 if len(lastseven) > 0: 0527 for i in lastseven: 0528 entry.chksum += sumtbl[i] 0529 else: entry.chksum = 255 0530 0531 def makeentry(self, counter, entry, dict): 0532 e=self.protocolclass.pbentry() 0533 e.entrynumber=counter 0534 0535 for k in entry: 0536 # special treatment for lists 0537 if k == 'numbers': 0538 l=getattr(e,k) 0539 for item in entry[k]: 0540 num=self.protocolclass.numentry() 0541 self._calcnumsum(num, item) 0542 l.append(num) 0543 elif k == 'ringtone': 0544 e.ringtone = self._findringtoneindex(dict['ringtone-index'], entry[k], entry['name']) 0545 else: 0546 # everything else we just set 0547 setattr(e,k,entry[k]) 0548 0549 return e 0550 0551 def phonize(str): 0552 """Convert the phone number into something the phone understands 0553 0554 All digits, P, H, T, * and # are kept, everything else is removed""" 0555 return re.sub("[^0-9HPT#*]", "", str) 0556 0557 0558 class Profile(com_phone.Profile): 0559 serialsname='lgtm520' 0560 WALLPAPER_WIDTH=100 0561 WALLPAPER_HEIGHT=100 0562 MAX_WALLPAPER_BASENAME_LENGTH=19 0563 MAX_RINGTONE_BASENAME_LENGTH=19 0564 WALLPAPER_FILENAME_CHARS="abcdefghijklmnopqrstuvwxyz0123456789 ." 0565 RINGTONE_FILENAME_CHARS="abcdefghijklmnopqrstuvwxyz0123456789 ." 0566 WALLPAPER_CONVERT_FORMAT="bmp" 0567 0568 usbids = ( ) 0569 deviceclasses = ("serial", ) 0570 _supportedsyncs=( 0571 ('phonebook', 'read', None), # all phonebook reading 0572 ('calendar', 'read', None), # all calendar reading 0573 ('ringtone', 'read', None), # all ringtone reading 0574 ('phonebook', 'write', 'OVERWRITE'), # only overwriting phonebook 0575 ('calendar', 'write', 'OVERWRITE'), # only overwriting calendar 0576 ('ringtone', 'write', 'MERGE'), 0577 ('ringtone', 'write', 'OVERWRITE'), 0578 ) 0579 0580 def convertphonebooktophone(self, helper, data): 0581 "Converts the data to what will be used by the phone" 0582 0583 results = {} 0584 speeddial = {} 0585 entrynumber = 1 0586 0587 for pbentry in data['phonebook']: 0588 e = {} # entry out 0589 entry = data['phonebook'][pbentry] # entry in 0590 0591 try: 0592 try: 0593 e['name'] = helper.getfullname(entry.get('names', []),1,1,16)[0] 0594 except IndexError: raise helper.ConversionFailed("No name assigned to entry") 0595 try: 0596 e['email']= helper.getemails(entry.get('emails', []),0,1,48)[0] 0597 except IndexError: e['email'] = "" 0598 e['ringtone'] = helper.getringtone(entry.get('ringtones', []), 'call', None) 0599 e['secret'] = helper.getflag(entry.get('flags',[]), 'secret', False) 0600 e['voicetag'] = helper.getflag(entry.get('flags',[]), 'voicetag', False) 0601 e['default'] = 0 0602 0603 numbers = entry.get('numbers', []) 0604 if len(numbers) < 1: raise helper.ConversionFailed("Too few numbers. Need at least 1 number") 0605 e['numbers']=[ '', '', '', '', '' ] 0606 available = 5 0607 deferred = [] 0608 for num in numbers: 0609 number=phonize(num['number']) 0610 if len(number) == 0: continue # no actual digits in number 0611 if len(number) > 32: number = number[:32] # truncate long number 0612 if available == 0: break # all slots filled 0613 if not 'type' in num: 0614 deferred.append(num) 0615 continue 0616 elif not num['type'] in typemap['rev']: 0617 deferred.append(num) 0618 continue 0619 else: 0620 typeidx = typemap['rev'][num['type']] 0621 if len(e['numbers'][typeidx]) == 0: 0622 e['numbers'][typeidx] = number 0623 if 'speeddial' in num and not 'entrynumber' in e: 0624 if not num['speeddial'] in speeddial: 0625 e['entrynumber'] = num['speeddial'] 0626 e['default'] = typeidx 0627 available -= 1 0628 if available > 0 and len(deferred) > 0: 0629 for num in deferred: 0630 if available == 0: break 0631 number=phonize(num['number']) 0632 if len(number) > 32: number = number[:32] # truncate long number 0633 for slot in range(0, 5): 0634 if len(e['numbers'][slot]) > 0: continue 0635 e['numbers'][slot] = number 0636 if 'speeddial' in num and not 'entrynumber' in e: 0637 if not num['speeddial'] in speeddial: 0638 e['entrynumber'] = num['speeddial'] 0639 e['default'] = slot 0640 available -= 1 0641 if available == 5: 0642 raise helper.ConversionFailed("The phone numbers didn't have any digits for this entry") 0643 if not 'entrynumber' in e: 0644 while entrynumber in speedial: 0645 entrynumber += 1 0646 if entrynumber > 199: 0647 self.log("Too many entries in phonebook, only 199 entries supported") 0648 break 0649 e['entrynumber'] = entrynumber 0650 speeddial[e['entrynumber']] = pbentry 0651 0652 serial1 = helper.getserial(entry.get('serials', []), self.serialsname, data['uniqueserial'], 'serial1', 0) 0653 serial2 = helper.getserial(entry.get('serials', []), self.serialsname, data['uniqueserial'], 'serial2', serial1) 0654 0655 e['serial1'] = serial1 0656 e['serial2'] = serial2 0657 for ss in entry["serials"]: 0658 if ss["sourcetype"]=="bitpim": 0659 e['bitpimserial']=ss 0660 assert e['bitpimserial'] 0661 0662 results[pbentry] = e 0663 0664 except helper.ConversionFailed: continue 0665 0666 data['phonebook'] = results 0667 return data 0668
Generated by PyXR 0.9.4