def convertqcptowav(qcpfile, wavfile): pvconv=shortfilename(gethelperbinary('pvconv')) q_name=shortfilename(qcpfile) w_name=common.stripext(q_name)+'.wav' try: os.remove(w_name) except: pass run(pvconv, q_name) try: os.remove(wavfile) except: pass os.rename(w_name, wavfile)
def _add_files(self, index_key, media_key, media_path, new_list, fundamentals): """Add new file using OBEX""" _index=fundamentals.get(index_key, {}) _media=fundamentals.get(media_key, {}) _adding_ringtones=index_key=='ringtone-index' for _file in new_list: _data=self._item_from_index(_file, 'data', _media) if not _data: self.log('Failed to write file %s due to no data'%_file) continue if self._item_from_index(_file, None, _index) is None: # new file _name=_file if _adding_ringtones and \ common.getext(_name).lower()=='mp3': # need to adjust the file name since this model only # accepts qcp and mid files (AFAIK). _name='%s.mid'%common.stripext(_name) _file_name='%(pathname)s/%(filename)s'% \ { 'pathname': media_path, 'filename': _name } try: self.obex.writefile(_file_name, _data) except: self.log('Failed to write OBEX file '+_file_name) if __debug__: raise
def _add_files(self, index_key, media_key, media_path, new_list, fundamentals): """Add new file using OBEX""" _index = fundamentals.get(index_key, {}) _media = fundamentals.get(media_key, {}) _adding_ringtones = index_key == 'ringtone-index' for _file in new_list: _data = self._item_from_index(_file, 'data', _media) if not _data: self.log('Failed to write file %s due to no data' % _file) continue if self._item_from_index(_file, None, _index) is None: # new file _name = _file if _adding_ringtones and \ common.getext(_name).lower()=='mp3': # need to adjust the file name since this model only # accepts qcp and mid files (AFAIK). _name = '%s.mid' % common.stripext(_name) _file_name='%(pathname)s/%(filename)s'% \ { 'pathname': media_path, 'filename': _name } try: self.obex.writefile(_file_name, _data) except: self.log('Failed to write OBEX file ' + _file_name) if __debug__: raise
def make_new_media_entry(self, entry, index, type): c=self.protocolclass.content_entry() e=self.protocolclass.content_entry() name=common.stripext(entry['name']) ext=common.getext(entry['name']) data=entry.get("data", None) add_to_index='index' c.type='!C' c.index1=index c.name1=name try: c.mime_type=self.__mimetype[ext] except: add_to_index='none' return c, e, add_to_index if c.mime_type=='application/java-archive': c.content_type='Games' e.location_maybe='midlet:'+name add_to_index='content' elif type=='ringers': c.content_type='Ringers' else: c.content_type='Screen Savers' c.size=`((3024+len(data))/1008)*1008` e.type='!E' e.index2=index e.name2=name return c, e, add_to_index
def get_content_file(self, key): index={} buf=prototypes.buffer(self.getfilecontents(self.protocolclass.content_file_name)) g=self.protocolclass.content_file() g.readfrombuffer(buf) self.logdata("Content file %s read with %d entries" % (self.protocolclass.content_file_name,len(g.items)), buf.getdata(), g) if key=='ringtone' or key=='ringtone-index': type='Ringers' index_const=self.protocolclass.ringerconst*0x100 indexfile=self.getindex(self.protocolclass.ringerindex) else: type='Screen Savers' index_const=self.protocolclass.imageconst*0x100 indexfile=self.getindex(self.protocolclass.imageindex) for i in g.items: if i.type=='!C' and i.content_type==type: try: ext=self.__reverse_mimetype[i.mime_type] found=False for j in indexfile.keys(): try: if int(common.stripext(indexfile[j]))==int(i.index1): index[j + index_const]=i.name1+'.'+ext found=True break; except: pass if not found: self.logdata("Unable to find index entry for "+i.name1+". Index : "+`i.index1`) except: pass return index, indexfile, index_const
def convertwavtoqcp(wavfile, qcpfile, optimization=None): pvconv=shortfilename(gethelperbinary('pvconv')) w_name=shortfilename(wavfile) q_name=common.stripext(w_name)+'.qcp' try: os.remove(q_name) except: pass if optimization is None: run(pvconv, w_name) else: run(pvconv, '-r', _qcp_optimization_params[optimization], w_name) try: os.remove(qcpfile) except: pass os.rename(q_name, qcpfile)
def _add_wallpapers(self, names, name_dict, media): self.charset_base64() for n in names: _media_key=name_dict[n] if not self._add_media_file(n, common.stripext(n), 12, media[_media_key].get('data', '')): self.log('Failed to send wallpaper %s'%n) self.charset_ascii()
def _add_wallpapers(self, names, name_dict, media): self.charset_base64() for n in names: _media_key = name_dict[n] if not self._add_media_file(n, common.stripext(n), 12, media[_media_key].get('data', '')): self.log('Failed to send wallpaper %s' % n) self.charset_ascii()
def saveringtones(self, result, merge): dircache=self.DirCache(self) media_prefix=self.protocolclass.RINGERPREFIX endtransactionpath=self.protocolclass.ENDTRANSACTION media=result.get('ringtone', {}) media_index=result.get('ringtone-index', {}) media_names=[x['name'] for x in media.values()] index_names=[x['name'] for x in media_index.values()] if merge: del_names=[] else: del_names=[common.stripext(x) for x in index_names if x not in media_names] gcdpattern=re.compile("[\n\r]Content-Name: +(.*?)[\n\r]") new_names=[x for x in media_names if x not in index_names] progressmax=len(del_names)+len(new_names) progresscur=0 self.log("Writing ringers") self.progress(progresscur, progressmax, "Writing ringers") for icnt in range(1,101): if not (new_names or del_names): break fname=media_prefix+`icnt` fnamegcd=media_prefix+`icnt`+".gcd" fstat=dircache.stat(fnamegcd) if del_names and fstat: gcdcontents=dircache.readfile(fnamegcd) thisfile=gcdpattern.search(gcdcontents).groups()[0] if thisfile in del_names: self.log("Deleting ringer "+thisfile) self.progress(progresscur, progressmax, "Deleting ringer "+thisfile) progresscur+=1 dircache.rmfile(fname) dircache.rmfile(fnamegcd) del_names.remove(thisfile) fstat=False if new_names and not fstat: newname=new_names.pop() contents="" for k in media.keys(): if media[k]['name']==newname: contents=media[k]['data'] break contentsize=len(contents) if contentsize: gcdcontents=self.makegcd(newname,contentsize,self.__audio_mimetype) self.log("Writing ringer "+newname) self.progress(progresscur, progressmax, "Deleting ringer "+newname) progresscur+=1 dircache.writefile(fname,contents) dircache.writefile(fnamegcd,gcdcontents) fstat=dircache.stat(endtransactionpath) self.log("Finished writing ringers") self.progress(progressmax, progressmax, "Finished writing ringers") if fstat: dircache.rmfile(endtransactionpath) result['rebootphone']=True return
def makegcd(self, filename,size,mimetable): "Build a GCD file for filename" ext=common.getext(filename.lower()) try: mimetype=mimetable[ext] except: return "" noextname=common.stripext(filename) gcdcontent="Content-Type: "+mimetype+"\nContent-Name: "+noextname+"\nContent-Version: 1.0\nContent-Vendor: BitPim\nContent-URL: file:"+filename+"\nContent-Size: "+`size`+"\n\n\n" return gcdcontent
def makegcd(self,filename,size): "Build a GCD file for filename" ext=common.getext(filename.lower()) noextname=common.stripext(filename) try: mimetype=self.__mimetype[ext] gcdcontent="Content-Type: "+mimetype+"\nContent-Name: "+noextname+"\nContent-Version: 1.0\nContent-Vendor: BitPim\nContent-URL: file://"+filename+"\nContent-Size: "+`size`+"\nContent-Description: Content for V10044 LG PM225"+"\n\n\n" except: gcdcontent="Content-Name: "+noextname+"\nContent-Version: 1.0\nContent-Vendor: BitPim\nContent-URL: file://"+filename+"\nContent-Size: "+`size`+"\n\n\n" return gcdcontent
def makegcd(self, filename, size, mimetable): "Build a GCD file for filename" ext = common.getext(filename.lower()) try: mimetype = mimetable[ext] except: return "" noextname = common.stripext(filename) gcdcontent = "Content-Type: " + mimetype + "\nContent-Name: " + noextname + "\nContent-Version: 1.0\nContent-Vendor: BitPim\nContent-URL: file:" + filename + "\nContent-Size: " + ` size ` + "\n\n\n" return gcdcontent
def _read_pl_list(self, filename): # read and return the contents of the specified playlist _req=self.protocolclass.PLPlayListFile() _buf=prototypes.buffer(self.getfilecontents(filename)) _req.readfrombuffer(_buf, logtitle="Read playlist "+filename) _songs=[] for _item in _req.items: _songs.append(common.basename(_item.pathname)) _entry=playlist.PlaylistEntry() _entry.name=common.stripext(common.basename(filename)) _entry.songs=_songs return _entry
def convertqcptowav(qcpfile, wavfile): pvconv = shortfilename(gethelperbinary('pvconv')) q_name = shortfilename(qcpfile) w_name = common.stripext(q_name) + '.wav' try: os.remove(w_name) except: pass run(pvconv, q_name) try: os.remove(wavfile) except: pass os.rename(w_name, wavfile)
def makejad(self,filename,size): "Build a JAD file for filename" ext=common.getext(filename.lower()) noextname=common.stripext(filename) jadcontent="MIDlet-1: "+noextname+", "+noextname+".png, BitPim\nMIDlet-Jar-Size: "+`size`+"\nMIDlet-Jar-URL: "+filename+"\nMIDlet-Name: "+noextname+"\nMIDlet-Vendor: Unknown\nMIDlet-Version: 1.0\nMicroEdition-Configuration: CLDC-1.0\nMicroEdition-Profile: MIDP-1.0\nContent-Folder: Games\n\n\n" return jadcontent brew_version_file='ams/version.txt' brew_version_txt_key='ams_version.txt' my_model='PM225' def getphoneinfo(self, phone_info):
def convertwavtoqcp(wavfile, qcpfile, optimization=None): pvconv=shortfilename(gethelperbinary('pvconv')) w_name=shortfilename(wavfile) q_name=common.stripext(w_name)+'.qcp' try: os.remove(q_name) except: pass # Have not figured out how to specify output file for pvconv if optimization is None: run(pvconv, w_name) else: run(pvconv, '-r', _qcp_optimization_params[optimization], w_name) # mv output file to qcpfile try: os.remove(qcpfile) except: pass os.rename(q_name, qcpfile)
def convertwavtoqcp(wavfile, qcpfile, optimization=None): pvconv = shortfilename(gethelperbinary('pvconv')) w_name = shortfilename(wavfile) q_name = common.stripext(w_name) + '.qcp' try: os.remove(q_name) except: pass # Have not figured out how to specify output file for pvconv if optimization is None: run(pvconv, w_name) else: run(pvconv, '-r', _qcp_optimization_params[optimization], w_name) # mv output file to qcpfile try: os.remove(qcpfile) except: pass os.rename(q_name, qcpfile)
def _add_wp_cache(self, wp, idx, fundamentals): # check to see if it already exists _wp_range=fundamentals.get('wallpaper-range', {}) # add this wallpaper into the cache dir _wp_index=fundamentals.get('wallpaper-index', {}) # look for the file name _filename=self._get_wp_filename(wp, _wp_index) if not _filename: # couldn't find the filename return # copy the image file, rescale, and put it in the cache dir _newfilename=self._rescale_and_cache(wp, _filename, idx, fundamentals) if _newfilename: # rescale successful, update the dict _wp_range[wp]='/ff/'+_newfilename _wp_range[wp]='/ff/%(filename)s|%(wpname)s'%\ { 'filename': _newfilename, 'wpname': common.stripext(wp), } fundamentals['wallpaper-range']=_wp_range
def savemedia(self, mediakey, mediaindexkey, results, merge, reindexfunction): """Actually saves out the media @param mediakey: key of the media (eg 'wallpapers' or 'ringtones') @param mediaindexkey: index key (eg 'wallpaper-index') @param maps: list index files and locations @param results: results dict @param merge: are we merging or overwriting what is there? @param reindexfunction: the media is re-indexed at the end. this function is called to do it """ content_changed=False media=results[mediakey].copy() if mediaindexkey=='ringtone-index': type='ringers' content_type="Ringers" indexfile=self.protocolclass.ringerindex index_const=self.protocolclass.ringerconst max_media_entries=self.protocolclass.max_ringers for i in media.keys(): try: if media[i]['origin']=='voice_memo': del media[i] except: pass else: type='images' content_type="Screen Savers" indexfile=self.protocolclass.imageindex index_const=self.protocolclass.imageconst max_media_entries=self.protocolclass.max_images for i in media.keys(): try: if media[i]['origin']=='camera': del media[i] except: pass content={} buf=prototypes.buffer(self.getfilecontents(self.protocolclass.content_file_name)) g=self.protocolclass.content_file() g.readfrombuffer(buf) for i in g.items: if i.type=='!C': content[int(i.index1)]= {'C': i} elif i.type=='!E': content[int(i.index2)]['E']=i dirlisting=self.getfilesystem(self.protocolclass.media_directory) for i in dirlisting.keys(): dirlisting[i[len(self.protocolclass.media_directory)+1:]]=dirlisting[i] del dirlisting[i] init={} for k in content.keys(): if content[k]['C'].content_type==content_type: index=k name=content[k]['C'].name1 size=int(content[k]['C'].size) data=None for w in media: if common.stripext(media[w]['name'])==name and media[w]['data']!=None: size_fix=((3024+len(media[w]['data']))/1008)*1008 if size_fix==size: data=media[w]['data'] del media[w] break if not merge and data is None: del content[k] content_changed=True _fname='%02d.dat' % k if _fname in dirlisting: self.rmfile(self.protocolclass.media_directory+'/'+_fname) del dirlisting[_fname] gcdname='%02d.gcd' % k if gcdname in dirlisting: self.rmfile(self.protocolclass.media_directory+'/'+gcdname) del dirlisting[gcdname] urlname='%02d.url' % k if urlname in dirlisting: self.rmfile(self.protocolclass.media_directory+'/'+urlname) del dirlisting[urlname] continue init[index]={'name': name, 'data': data} applications={} for sp in range(100): if len(media.keys()) == 0: break if sp not in content: for w in media.keys(): C,E,add_to_index=self.make_new_media_entry(media[w], sp, type) if add_to_index=='index': content[sp]= {'C': C, 'E': E} init[sp]=media[w] content_changed=True elif add_to_index=='content': content[sp]= {'C': C, 'E': E} applications[sp]=media[w] content_changed=True else: self.log("Unknown media type for "+`media[w]['name']`+". Not written to phone.") sp-=1 del media[w] break if len(media.keys()): self.log("Phone index full, some media not written to phone") content_count=0 keys=content.keys() keys.sort() cfile=self.protocolclass.content_file() for k in keys: content_count+=1 cfile.items.append(content[k]['C']) for k in keys: cfile.items.append(content[k]['E']) entry=self.protocolclass.content_entry() entry.type='!F' cfile.items.append(entry) buffer=prototypes.buffer() cfile.writetobuffer(buffer) self.logdata("Updated content file "+self.protocolclass.content_file_name, buffer.getvalue(), cfile) self.writefile(self.protocolclass.content_file_name, buffer.getvalue()) countfile=self.protocolclass.content_count() countfile.count=`content_count` buffer=prototypes.buffer() countfile.writetobuffer(buffer) self.logdata("Updated content count file "+self.protocolclass.content_count_file_name, buffer.getvalue(), countfile) self.writefile(self.protocolclass.content_count_file_name, buffer.getvalue()) keys=init.keys() keys.sort() ifile=self.protocolclass.indexfile() ifile.numactiveitems=len(keys) for k in keys: entry=self.protocolclass.indexentry() entry.index=k entry.const=index_const entry.name='%02d.dat' % k ifile.items.append(entry) for k in range(max_media_entries): if k in keys: continue entry=self.protocolclass.indexentry() entry.index=k entry.const=index_const ifile.items.append(entry) buffer=prototypes.buffer() ifile.writetobuffer(buffer) self.logdata("Updated index file "+indexfile, buffer.getvalue(), ifile) self.writefile(indexfile, buffer.getvalue()) for k in keys: entry=init[k] data=entry.get("data", None) _fname='%02d.dat' % k gcdname='%02d.gcd' % k urlname='%02d.url' % k if data is None: if _fname not in dirlisting: self.log("Index error. I have no data for "+entry['name']+" and it isn't already in the filesystem") continue contentsize=len(data) urlcontents='file://'+entry['name'] gcdcontents=self.makegcd(entry['name'],contentsize) if _fname in dirlisting and len(data)==dirlisting[_fname]['size']: self.log("Skipping writing %s/%s as there is already a file of the same length" % (self.protocolclass.media_directory,entry['name'])) if gcdname not in dirlisting: self.writefile(self.protocolclass.media_directory+"/"+gcdname, gcdcontents) if urlname not in dirlisting: self.writefile(self.protocolclass.media_directory+"/"+urlname, urlcontents) continue self.writefile(self.protocolclass.media_directory+"/"+_fname, data) self.writefile(self.protocolclass.media_directory+"/"+gcdname, gcdcontents) self.writefile(self.protocolclass.media_directory+"/"+urlname, urlcontents) for k in applications.keys(): entry=applications[k] data=entry.get("data", None) _fname='%02d.jar' % k jadname='%02d.jad' % k urlname='%02d.url' % k if data is None: if _fname not in dirlisting: self.log("Index error. I have no data for "+entry['name']+" and it isn't already in the filesystem") print "here2" continue contentsize=len(data) urlcontents='file://'+entry['name'] jadcontents=self.makejad(entry['name'],contentsize) print "here3" if _fname in dirlisting and len(data)==dirlisting[_fname]['size']: self.log("Skipping writing %s/%s as there is already a file of the same length" % (self.protocolclass.media_directory,entry['name'])) if jadname not in dirlisting: self.writefile(self.protocolclass.media_directory+"/"+jadname, jadcontents) if urlname not in dirlisting: self.writefile(self.protocolclass.media_directory+"/"+urlname, urlcontents) print "here4" continue print "here5" self.writefile(self.protocolclass.media_directory+"/"+_fname, data) self.writefile(self.protocolclass.media_directory+"/"+jadname, jadcontents) self.writefile(self.protocolclass.media_directory+"/"+urlname, urlcontents) del results[mediakey] reindexfunction(results) if content_changed: results["rebootphone"]=True return results def make_new_media_entry(self, entry, index, type): c=self.protocolclass.content_entry() e=self.protocolclass.content_entry() name=common.stripext(entry['name']) ext=common.getext(entry['name']) data=entry.get("data", None) add_to_index='index' c.type='!C' c.index1=index c.name1=name try: c.mime_type=self.__mimetype[ext] except: add_to_index='none' return c, e, add_to_index if c.mime_type=='application/java-archive': c.content_type='Games' e.location_maybe='midlet:'+name add_to_index='content' elif type=='ringers': c.content_type='Ringers' else: c.content_type='Screen Savers' c.size=`((3024+len(data))/1008)*1008` e.type='!E' e.index2=index e.name2=name return c, e, add_to_index def makegcd(self,filename,size): "Build a GCD file for filename" ext=common.getext(filename.lower()) noextname=common.stripext(filename) try: mimetype=self.__mimetype[ext] gcdcontent="Content-Type: "+mimetype+"\nContent-Name: "+noextname+"\nContent-Version: 1.0\nContent-Vendor: BitPim\nContent-URL: file://"+filename+"\nContent-Size: "+`size`+"\nContent-Description: Content for V10044 LG PM225"+"\n\n\n" except: gcdcontent="Content-Name: "+noextname+"\nContent-Version: 1.0\nContent-Vendor: BitPim\nContent-URL: file://"+filename+"\nContent-Size: "+`size`+"\n\n\n" return gcdcontent def makejad(self,filename,size): "Build a JAD file for filename" ext=common.getext(filename.lower()) noextname=common.stripext(filename) jadcontent="MIDlet-1: "+noextname+", "+noextname+".png, BitPim\nMIDlet-Jar-Size: "+`size`+"\nMIDlet-Jar-URL: "+filename+"\nMIDlet-Name: "+noextname+"\nMIDlet-Vendor: Unknown\nMIDlet-Version: 1.0\nMicroEdition-Configuration: CLDC-1.0\nMicroEdition-Profile: MIDP-1.0\nContent-Folder: Games\n\n\n" return jadcontent brew_version_file='ams/version.txt' brew_version_txt_key='ams_version.txt' my_model='LX325' def getphoneinfo(self, phone_info): self.log('Getting Phone Info') try: s=self.getfilecontents('ams/version.txt') if s[:5]==self.my_model: phone_info.append('Model:', self.my_model+'/PM325') phone_info.append('ESN:', self.get_brew_esn()) req=p_brew.firmwarerequest() res=self.sendbrewcommand(req, self.protocolclass.firmwareresponse) phone_info.append('Firmware Version:', res.firmware) txt=self.getfilecontents("nvm/nvm/nvm_0000")[207:217] phone_info.append('Phone Number:', txt) except: self.log('Error Getting Phone Info') pass return "Talk to the LG LX325/PM325 cell phone" parentprofile=com_lgvx4400.Profile class Profile (parentprofile) : protocolclass=Phone.protocolclass serialsname=Phone.serialsname BP_Calendar_Version=3 phone_manufacturer='LG Electronics Inc' phone_model='LX325' brew_required=True DIALSTRING_CHARS="[^0-9PT#*]" 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={} speeds={} for pbentry in data['phonebook']: if len(results)==self.protocolclass.NUMPHONEBOOKENTRIES: break e={} entry=data['phonebook'][pbentry] try: serial1=helper.getserial(entry.get('serials', []), self.serialsname, data['uniqueserial'], 'serial1', 0xFFFFFFFF) e['serial1']=serial1 for ss in entry["serials"]: if ss["sourcetype"]=="bitpim": e['bitpimserial']=ss assert e['bitpimserial'] e['name']=helper.getfullname(entry.get('names', []),1,1,32)[0] cat=helper.makeone(helper.getcategory(entry.get('categories', []),0,1,32), None) if cat is None: e['group']=0 else: key,value=self._getgroup(cat, data['groups']) if key is not None: e['group']=key else: e['group']=0 emails=helper.getemails(entry.get('emails', []) ,0,self.protocolclass.NUMEMAILS,48) e['emails']=helper.filllist(emails, self.protocolclass.NUMEMAILS, "") e['url']=helper.makeone(helper.geturls(entry.get('urls', []), 0,1,48), "") e['memo']=helper.makeone(helper.getmemos(entry.get('memos', []), 0, 1, self.protocolclass.MEMOLENGTH-1), "") minnumbers=1 if len(emails): minnumbers=0 numbers=helper.getnumbers(entry.get('numbers', []),minnumbers,self.protocolclass.NUMPHONENUMBERS) e['numberspeeds']=[] e['numbertypes']=[] e['numbers']=[] for numindex in range(len(numbers)): num=numbers[numindex] b4=len(e['numbertypes']) type=num['type'] for i,t in enumerate(self.protocolclass.numbertypetab): if type==t: e['numbertypes'].append(i) break if t=='none': e['numbertypes'].append(i) break if len(e['numbertypes'])==b4: continue number=self.phonize(num['number']) if len(number)==0: continue if len(number)>48: number=number[:48] e['numbers'].append(number) sd=num.get("speeddial", -1) if self.protocolclass.NUMSPEEDDIALS: if sd>=self.protocolclass.FIRSTSPEEDDIAL and sd<=self.protocolclass.LASTSPEEDDIAL: speeds[sd]=(e['bitpimserial'], numindex) e['numberspeeds']=helper.filllist(e['numberspeeds'], 5, 0) e['numbertypes']=helper.filllist(e['numbertypes'], 5, 0) e['numbers']=helper.filllist(e['numbers'], 5, "") 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) results[pbentry]=e except helper.ConversionFailed: continue if self.protocolclass.NUMSPEEDDIALS: data['speeddials']=speeds data['phonebook']=results return data _supportedsyncs=( ('phonebook', 'read', None), ('calendar', 'read', None), ('wallpaper', 'read', None), ('ringtone', 'read', None), ('call_history', 'read', None), ('sms', 'read', None), )
def _add_wallpapers(self, names, name_dict, media): self.charset_base64() for n in names: _media_key=name_dict[n] if not self._add_media_file(n, common.stripext(n), 12, media[_media_key].get('data', '')): self.log('Failed to send wallpaper %s'%n) self.charset_ascii() def savewallpapers(self, result, merge): self.log('Saving wallpapers') self.setmode(self.MODEMODEM) self.charset_ascii() self._wallpaper_mode() media=result.get('wallpapers', {}) media_index=result.get('wallpaper-index', {}) media_names=[x['name'] for x in media.values()] index_names=[x['name'] for x in media_index.values()] del_names=[x for x in index_names if x not in media_names] new_names=[x for x in media_names if x not in index_names] self._del_media_files(del_names) names_to_keys={} for k,e in media.items(): names_to_keys[e['name']]=k self._add_wallpapers(new_names, names_to_keys, media) return result def getmemo(self, result): self.log('Reading Memo') self.setmode(self.MODEMODEM) self.charset_ascii() _req=self.protocolclass.memo_read_req() _res=self.sendATcommand(_req, self.protocolclass.memo_read_resp) res={} for e in _res: _memo=memo.MemoEntry() _memo.text=e.text res[_memo.id]=_memo result['memo']=res return res def savememo(self, result, merge): self.log('Writing Memo') self.setmode(self.MODEMODEM) self.charset_ascii() _req=self.protocolclass.memo_del_req() for i in range(self.protocolclass.MEMO_MIN_INDEX, self.protocolclass.MEMO_MAX_INDEX+1): _req.index=i try: self.sendATcommand(_req, None) except: pass _memo_dict=result.get('memo', {}) _keys=_memo_dict.keys() _keys.sort() _req=self.protocolclass.memo_write_req() for k in _keys: _req.text=_memo_dict[k].text try: self.sendATcommand(_req, None) except: self.log('Failed to write memo %s'%_req.text) return _memo_dict def _process_sms(self, _resp, res): for i in range(0, len(_resp), 2): try: _entry=self.protocolclass.sms_msg_list_header() _buf=prototypes.buffer(_resp[i]) _entry.readfrombuffer(_buf) _sms=sms.SMSEntry() if _entry.msg_type==self.protocolclass.SMS_MSG_REC_UNREAD or \ _entry.msg_type==self.protocolclass.SMS_MSG_REC_READ: _sms._from=_entry.address _sms.folder=sms.SMSEntry.Folder_Inbox _sms.read=_entry.msg_type==self.protocolclass.SMS_MSG_REC_READ elif _entry.msg_type==self.protocolclass.SMS_MSG_STO_SENT: _sms.add_recipient(_entry.address) _sms.folder=sms.SMSEntry.Folder_Sent elif _entry.msg_type==self.protocolclass.SMS_MSG_STO_UNSENT: _sms.folder=sms.SMSEntry.Folder_Saved _sms.add_recipient(_entry.address) else: self.log('Unknown message type: %s'%_entry.msg_type) _sms=None if _sms: if _entry.timestamp: _sms.datetime=_entry.timestamp _sms.text=_resp[i+1] res[_sms.id]=_sms except: if __debug__: raise return res def getsms(self, result): self.log('Getting SMS Messages') self.setmode(self.MODEMODEM) self.charset_ascii() res={} _req=self.protocolclass.sms_format_req() self.sendATcommand(_req, None) self.log('Getting SMS messages from the phone memory') _sms_mem=self.protocolclass.sms_memory_select_req() _sms_mem.list_memory=self.protocolclass.SMS_MEMORY_PHONE self.sendATcommand(_sms_mem, None) _list_sms=self.protocolclass.sms_msg_list_req() _resp=self.sendATcommand(_list_sms, None) self._process_sms(_resp, res) self.log('Getting SMS message from the SIM card') _sms_mem.list_memory=self.protocolclass.SMS_MEMORY_SIM self.sendATcommand(_sms_mem, None) _resp=self.sendATcommand(_list_sms, None) self._process_sms(_resp, res) try: self.sendATcommand(_sms_mem, None) except commport.ATError: pass result['sms']=res return result def _get_history_calls(self, log_str, call_type, min_idx, max_idx): self.log(log_str) _sel_mem=self.protocolclass.select_storage_req() _sel_mem.storage=call_type self.sendATcommand(_sel_mem, None) _list_pb=self.protocolclass.read_phonebook_req() _list_pb.start_index=min_idx _list_pb.end_index=max_idx self.sendATcommand(_list_pb, None) def getcallhistory(self, result): self.log('Getting Call History') self.setmode(self.MODEMODEM) self.charset_ascii() res={} for l in self.protocolclass.PB_CALL_HISTORY_INFO: self._get_history_calls(*l) result['call_history']=res return result """ Talk to the LG G4015 Phone""" parent_profile=com_gsm.Profile class Profile (parent_profile) : serialsname=Phone.serialsname WALLPAPER_WIDTH=128 WALLPAPER_HEIGHT=128 MAX_WALLPAPER_BASENAME_LENGTH=19 WALLPAPER_FILENAME_CHARS="abcdefghijklmnopqrstuvwxyz0123456789_ ." WALLPAPER_CONVERT_FORMAT="jpg" MAX_RINGTONE_BASENAME_LENGTH=19 RINGTONE_FILENAME_CHARS="abcdefghijklmnopqrstuvwxyz0123456789_ ." RINGTONE_LIMITS= { 'MAXSIZE': 20480 } phone_manufacturer='LGE' phone_model='G4015' usbids=( ( 0x10AB, 0x10C5, 1), ) deviceclasses=("serial",) imageorigins={} imageorigins.update(common.getkv(parent_profile.stockimageorigins, "images")) imagetargets={} imagetargets.update(common.getkv(parent_profile.stockimagetargets, "wallpaper", {'width': 128, 'height': 128, 'format': "JPEG"})) def GetImageOrigins(self): return self.imageorigins def GetTargetsForImageOrigin(self, origin): if origin=='images': return self.imagetargets def __init__(self): parent_profile.__init__(self) _supportedsyncs=( ('phonebook', 'read', None), ('phonebook', 'write', 'OVERWRITE'), ('calendar', 'read', None), ('calendar', 'write', 'OVERWRITE'), ('ringtone', 'read', None), ('ringtone', 'write', 'OVERWRITE'), ('wallpaper', 'read', None), ('wallpaper', 'write', 'OVERWRITE'), ('memo', 'read', None), ('memo', 'write', 'OVERWRITE'), ('sms', 'read', None), ('call_history', 'read', None), ) def convertphonebooktophone(self, helper, data): return data imageorigins.update(common.getkv(parent_profile.stockimageorigins, "images")) imagetargets.update(common.getkv(parent_profile.stockimagetargets, "wallpaper", {'width': 128, 'height': 128, 'format': "JPEG"}))
def makejad(self,filename,size): "Build a JAD file for filename" ext=common.getext(filename.lower()) noextname=common.stripext(filename) jadcontent="MIDlet-1: "+noextname+", "+noextname+".png, BitPim\nMIDlet-Jar-Size: "+`size`+"\nMIDlet-Jar-URL: "+filename+"\nMIDlet-Name: "+noextname+"\nMIDlet-Vendor: Unknown\nMIDlet-Version: 1.0\nMicroEdition-Configuration: CLDC-1.0\nMicroEdition-Profile: MIDP-1.0\nContent-Folder: Games\n\n\n" return jadcontent
def saveringtones(self, result, merge): dircache=self.DirCache(self) media_prefix=self.protocolclass.RINGERPREFIX endtransactionpath=self.protocolclass.ENDTRANSACTION media=result.get('ringtone', {}) media_index=result.get('ringtone-index', {}) media_names=[x['name'] for x in media.values()] index_names=[x['name'] for x in media_index.values()] if merge: del_names=[] else: del_names=[common.stripext(x) for x in index_names if x not in media_names] gcdpattern=re.compile("[\n\r]Content-Name: +(.*?)[\n\r]") new_names=[x for x in media_names if x not in index_names] progressmax=len(del_names)+len(new_names) progresscur=0 self.log("Writing ringers") self.progress(progresscur, progressmax, "Writing ringers") for icnt in range(1,101): if not (new_names or del_names): break fname=media_prefix+`icnt` fnamegcd=media_prefix+`icnt`+".gcd" fstat=dircache.stat(fnamegcd) if del_names and fstat: gcdcontents=dircache.readfile(fnamegcd) thisfile=gcdpattern.search(gcdcontents).groups()[0] if thisfile in del_names: self.log("Deleting ringer "+thisfile) self.progress(progresscur, progressmax, "Deleting ringer "+thisfile) progresscur+=1 dircache.rmfile(fname) dircache.rmfile(fnamegcd) del_names.remove(thisfile) fstat=False if new_names and not fstat: newname=new_names.pop() contents="" for k in media.keys(): if media[k]['name']==newname: contents=media[k]['data'] break contentsize=len(contents) if contentsize: gcdcontents=self.makegcd(newname,contentsize,self.__audio_mimetype) self.log("Writing ringer "+newname) self.progress(progresscur, progressmax, "Deleting ringer "+newname) progresscur+=1 dircache.writefile(fname,contents) dircache.writefile(fnamegcd,gcdcontents) fstat=dircache.stat(endtransactionpath) self.log("Finished writing ringers") self.progress(progressmax, progressmax, "Finished writing ringers") if fstat: dircache.rmfile(endtransactionpath) result['rebootphone']=True return def savewallpapers(self, result, merge): dircache=self.DirCache(self) media_prefix=self.protocolclass.WALLPAPERPREFIX endtransactionpath=self.protocolclass.ENDTRANSACTION media=result.get('wallpapers', {}) for i in media.keys(): try: if media[i]['origin']=='camera': del media[i] except: pass media_index=result.get('wallpaper-index', {}) media_names=[x['name'] for x in media.values()] index_names=[x['name'] for x in media_index.values()] if merge: del_names=[] else: del_names=[common.stripext(x) for x in index_names if x not in media_names] gcdpattern=re.compile("[\n\r]Content-Name: +(.*?)[\n\r]") new_names=[x for x in media_names if x not in index_names] progressmax=len(del_names)+len(new_names) progresscur=0 self.log("Writing images") self.progress(progresscur, progressmax, "Writing images") for icnt in range(1,101): if not (new_names or del_names): break fname=media_prefix+`icnt` fnamegcd=media_prefix+`icnt`+".gcd" fstat=dircache.stat(fnamegcd) if del_names and fstat: gcdcontents=dircache.readfile(fnamegcd) thisfile=gcdpattern.search(gcdcontents).groups()[0] if thisfile in del_names: self.log("Deleting image "+thisfile) self.progress(progresscur, progressmax, "Deleting image "+thisfile) progresscur+=1 dircache.rmfile(fname) dircache.rmfile(fnamegcd) del_names.remove(thisfile) fstat=False if new_names and not fstat: newname=new_names.pop() contents="" for k in media.keys(): if media[k]['name']==newname: contents=media[k]['data'] break contentsize=len(contents) if contentsize: gcdcontents=self.makegcd(newname,contentsize,self.__image_mimetype) self.log("Writing image "+newname) self.progress(progresscur, progressmax, "Deleting image "+newname) progresscur+=1 dircache.writefile(fname,contents) dircache.writefile(fnamegcd,gcdcontents) fstat=dircache.stat(endtransactionpath) self.log("Finished writing images") self.progress(progressmax, progressmax, "Finished writing images") if fstat: dircache.rmfile(endtransactionpath) result['rebootphone']=True return "Talk to a Samsung SPH-A620 phone" class Profile (com_samsung_packet.Profile) : protocolclass=Phone.protocolclass serialsname=Phone.serialsname MAX_RINGTONE_BASENAME_LENGTH=19 RINGTONE_FILENAME_CHARS="abcdefghijklmnopqrstuvwxyz0123456789_ ." RINGTONE_LIMITS= { 'MAXSIZE': 30000 } phone_manufacturer='SAMSUNG' phone_model='SPH-A620/152' def __init__(self): com_samsung_packet.Profile.__init__(self) self.numbertypetab=numbertypetab _supportedsyncs=( ('phonebook', 'read', None), ('phonebook', 'write', 'OVERWRITE'), ('wallpaper', 'read', None), ('wallpaper', 'write', None), ('ringtone', 'read', None), ('ringtone', 'write', None), ('calendar', 'read', None), ('calendar', 'write', 'OVERWRITE'), ('todo', 'read', None), ('todo', 'write', 'OVERWRITE'), ('memo', 'read', None), ('memo', 'write', 'OVERWRITE'), ) __audio_ext={ 'MIDI': 'mid', 'PMD': 'pmd', 'QCP': 'qcp' } def QueryAudio(self, origin, currentextension, afi):
def make_new_media_entry(self, entry, index, type): c=self.protocolclass.content_entry() e=self.protocolclass.content_entry() name=common.stripext(entry['name']) ext=common.getext(entry['name']) data=entry.get("data", None) add_to_index='index' c.type='!C' c.index1=index c.name1=name try: c.mime_type=self.__mimetype[ext] except: add_to_index='none' return c, e, add_to_index if c.mime_type=='application/java-archive': c.content_type='Games' e.location_maybe='midlet:'+name add_to_index='content' elif type=='ringers': c.content_type='Ringers' else: c.content_type='Screen Savers' c.size=`((3024+len(data))/1008)*1008` e.type='!E' e.index2=index e.name2=name return c, e, add_to_index def makegcd(self,filename,size): "Build a GCD file for filename" ext=common.getext(filename.lower()) noextname=common.stripext(filename) try: mimetype=self.__mimetype[ext] gcdcontent="Content-Type: "+mimetype+"\nContent-Name: "+noextname+"\nContent-Version: 1.0\nContent-Vendor: BitPim\nContent-URL: file://"+filename+"\nContent-Size: "+`size`+"\nContent-Description: Content for V10044 LG PM225"+"\n\n\n" except: gcdcontent="Content-Name: "+noextname+"\nContent-Version: 1.0\nContent-Vendor: BitPim\nContent-URL: file://"+filename+"\nContent-Size: "+`size`+"\n\n\n" return gcdcontent def makejad(self,filename,size): "Build a JAD file for filename" ext=common.getext(filename.lower()) noextname=common.stripext(filename) jadcontent="MIDlet-1: "+noextname+", "+noextname+".png, BitPim\nMIDlet-Jar-Size: "+`size`+"\nMIDlet-Jar-URL: "+filename+"\nMIDlet-Name: "+noextname+"\nMIDlet-Vendor: Unknown\nMIDlet-Version: 1.0\nMicroEdition-Configuration: CLDC-1.0\nMicroEdition-Profile: MIDP-1.0\nContent-Folder: Games\n\n\n" return jadcontent brew_version_file='ams/version.txt' brew_version_txt_key='ams_version.txt' my_model='PM225' def getphoneinfo(self, phone_info): self.log('Getting Phone Info') try: s=self.getfilecontents('ams/version.txt') if s[:5]==self.my_model: phone_info.append('Model:', self.my_model) phone_info.append('ESN:', self.get_brew_esn()) req=p_brew.firmwarerequest() txt=self.getfilecontents("nvm/nvm/nvm_0000")[207:217] phone_info.append('Phone Number:', txt) except: pass return "Talk to the LG PM225 cell phone"
def savemedia(self, mediakey, mediaindexkey, results, merge, reindexfunction): """Actually saves out the media @param mediakey: key of the media (eg 'wallpapers' or 'ringtones') @param mediaindexkey: index key (eg 'wallpaper-index') @param maps: list index files and locations @param results: results dict @param merge: are we merging or overwriting what is there? @param reindexfunction: the media is re-indexed at the end. this function is called to do it """ content_changed=False media=results[mediakey].copy() if mediaindexkey=='ringtone-index': type='ringers' content_type="Ringers" indexfile=self.protocolclass.ringerindex index_const=self.protocolclass.ringerconst max_media_entries=self.protocolclass.max_ringers for i in media.keys(): try: if media[i]['origin']=='voice_memo': del media[i] except: pass else: type='images' content_type="Screen Savers" indexfile=self.protocolclass.imageindex index_const=self.protocolclass.imageconst max_media_entries=self.protocolclass.max_images for i in media.keys(): try: if media[i]['origin']=='camera': del media[i] except: pass content={} buf=prototypes.buffer(self.getfilecontents(self.protocolclass.content_file_name)) g=self.protocolclass.content_file() g.readfrombuffer(buf) for i in g.items: if i.type=='!C': content[int(i.index1)]= {'C': i} elif i.type=='!E': content[int(i.index2)]['E']=i dirlisting=self.getfilesystem(self.protocolclass.media_directory) for i in dirlisting.keys(): dirlisting[i[len(self.protocolclass.media_directory)+1:]]=dirlisting[i] del dirlisting[i] init={} for k in content.keys(): if content[k]['C'].content_type==content_type: index=k name=content[k]['C'].name1 size=int(content[k]['C'].size) data=None for w in media: if common.stripext(media[w]['name'])==name and media[w]['data']!=None: size_fix=((3024+len(media[w]['data']))/1008)*1008 if size_fix==size: data=media[w]['data'] del media[w] break if not merge and data is None: del content[k] content_changed=True _fname='%02d.dat' % k if _fname in dirlisting: self.rmfile(self.protocolclass.media_directory+'/'+_fname) del dirlisting[_fname] gcdname='%02d.gcd' % k if gcdname in dirlisting: self.rmfile(self.protocolclass.media_directory+'/'+gcdname) del dirlisting[gcdname] urlname='%02d.url' % k if urlname in dirlisting: self.rmfile(self.protocolclass.media_directory+'/'+urlname) del dirlisting[urlname] continue init[index]={'name': name, 'data': data} applications={} for sp in range(100): if len(media.keys()) == 0: break if sp not in content: for w in media.keys(): C,E,add_to_index=self.make_new_media_entry(media[w], sp, type) if add_to_index=='index': content[sp]= {'C': C, 'E': E} init[sp]=media[w] content_changed=True elif add_to_index=='content': content[sp]= {'C': C, 'E': E} applications[sp]=media[w] content_changed=True else: self.log("Unknown media type for "+`media[w]['name']`+". Not written to phone.") sp-=1 del media[w] break if len(media.keys()): self.log("Phone index full, some media not written to phone") content_count=0 keys=content.keys() keys.sort() cfile=self.protocolclass.content_file() for k in keys: content_count+=1 cfile.items.append(content[k]['C']) for k in keys: cfile.items.append(content[k]['E']) entry=self.protocolclass.content_entry() entry.type='!F' cfile.items.append(entry) buffer=prototypes.buffer() cfile.writetobuffer(buffer) self.logdata("Updated content file "+self.protocolclass.content_file_name, buffer.getvalue(), cfile) self.writefile(self.protocolclass.content_file_name, buffer.getvalue()) countfile=self.protocolclass.content_count() countfile.count=`content_count` buffer=prototypes.buffer() countfile.writetobuffer(buffer) self.logdata("Updated content count file "+self.protocolclass.content_count_file_name, buffer.getvalue(), countfile) self.writefile(self.protocolclass.content_count_file_name, buffer.getvalue()) keys=init.keys() keys.sort() ifile=self.protocolclass.indexfile() ifile.numactiveitems=len(keys) for k in keys: entry=self.protocolclass.indexentry() entry.index=k entry.const=index_const entry.name='%02d.dat' % k ifile.items.append(entry) for k in range(max_media_entries): if k in keys: continue entry=self.protocolclass.indexentry() entry.index=k entry.const=index_const ifile.items.append(entry) buffer=prototypes.buffer() ifile.writetobuffer(buffer) self.logdata("Updated index file "+indexfile, buffer.getvalue(), ifile) self.writefile(indexfile, buffer.getvalue()) for k in keys: entry=init[k] data=entry.get("data", None) _fname='%02d.dat' % k gcdname='%02d.gcd' % k urlname='%02d.url' % k if data is None: if _fname not in dirlisting: self.log("Index error. I have no data for "+entry['name']+" and it isn't already in the filesystem") continue contentsize=len(data) urlcontents='file://'+entry['name'] gcdcontents=self.makegcd(entry['name'],contentsize) if _fname in dirlisting and len(data)==dirlisting[_fname]['size']: self.log("Skipping writing %s/%s as there is already a file of the same length" % (self.protocolclass.media_directory,entry['name'])) if gcdname not in dirlisting: self.writefile(self.protocolclass.media_directory+"/"+gcdname, gcdcontents) if urlname not in dirlisting: self.writefile(self.protocolclass.media_directory+"/"+urlname, urlcontents) continue self.writefile(self.protocolclass.media_directory+"/"+_fname, data) self.writefile(self.protocolclass.media_directory+"/"+gcdname, gcdcontents) self.writefile(self.protocolclass.media_directory+"/"+urlname, urlcontents) for k in applications.keys(): entry=applications[k] data=entry.get("data", None) _fname='%02d.jar' % k jadname='%02d.jad' % k urlname='%02d.url' % k if data is None: if _fname not in dirlisting: self.log("Index error. I have no data for "+entry['name']+" and it isn't already in the filesystem") print "here2" continue contentsize=len(data) urlcontents='file://'+entry['name'] jadcontents=self.makejad(entry['name'],contentsize) print "here3" if _fname in dirlisting and len(data)==dirlisting[_fname]['size']: self.log("Skipping writing %s/%s as there is already a file of the same length" % (self.protocolclass.media_directory,entry['name'])) if jadname not in dirlisting: self.writefile(self.protocolclass.media_directory+"/"+jadname, jadcontents) if urlname not in dirlisting: self.writefile(self.protocolclass.media_directory+"/"+urlname, urlcontents) print "here4" continue print "here5" self.writefile(self.protocolclass.media_directory+"/"+_fname, data) self.writefile(self.protocolclass.media_directory+"/"+jadname, jadcontents) self.writefile(self.protocolclass.media_directory+"/"+urlname, urlcontents) del results[mediakey] # done with it reindexfunction(results) if content_changed: results["rebootphone"]=True return results
def makegcd(self,filename,size): "Build a GCD file for filename" ext=common.getext(filename.lower()) noextname=common.stripext(filename) try: mimetype=self.__mimetype[ext] gcdcontent="Content-Type: "+mimetype+"\nContent-Name: "+noextname+"\nContent-Version: 1.0\nContent-Vendor: BitPim\nContent-URL: file://"+filename+"\nContent-Size: "+`size`+"\nContent-Description: Content for V10044 LG PM225"+"\n\n\n" except: gcdcontent="Content-Name: "+noextname+"\nContent-Version: 1.0\nContent-Vendor: BitPim\nContent-URL: file://"+filename+"\nContent-Size: "+`size`+"\n\n\n" return gcdcontent def makejad(self,filename,size): "Build a JAD file for filename" ext=common.getext(filename.lower()) noextname=common.stripext(filename) jadcontent="MIDlet-1: "+noextname+", "+noextname+".png, BitPim\nMIDlet-Jar-Size: "+`size`+"\nMIDlet-Jar-URL: "+filename+"\nMIDlet-Name: "+noextname+"\nMIDlet-Vendor: Unknown\nMIDlet-Version: 1.0\nMicroEdition-Configuration: CLDC-1.0\nMicroEdition-Profile: MIDP-1.0\nContent-Folder: Games\n\n\n" return jadcontent brew_version_file='ams/version.txt' brew_version_txt_key='ams_version.txt' my_model='PM225' def getphoneinfo(self, phone_info): self.log('Getting Phone Info') try: s=self.getfilecontents('ams/version.txt') if s[:5]==self.my_model: phone_info.append('Model:', self.my_model) phone_info.append('ESN:', self.get_brew_esn()) req=p_brew.firmwarerequest() txt=self.getfilecontents("nvm/nvm/nvm_0000")[207:217] phone_info.append('Phone Number:', txt) except: pass return "Talk to the LG PM225 cell phone"
def get_content_file(self, key): index={} if key=='ringtone' or key=='ringtone-index': type='Ringers' index_const=self.protocolclass.ringerconst*0x100 indexfile=self.getindex(self.protocolclass.ringerindex) else: type='Screen Savers' index_const=self.protocolclass.imageconst*0x100 indexfile=self.getindex(self.protocolclass.imageindex) try: buf=prototypes.buffer(self.getfilecontents(self.protocolclass.content_file_name)) g=self.protocolclass.content_file() g.readfrombuffer(buf) self.logdata("Content file %s read with %d entries" % (self.protocolclass.content_file_name,len(g.items)), buf.getdata(), g) for i in g.items: if i.type=='!C' and i.content_type==type: try: ext=self.__reverse_mimetype[i.mime_type] found=False for j in indexfile.keys(): try: if int(common.stripext(indexfile[j]))==int(i.index1): index[j + index_const]=i.name1+'.'+ext found=True break; except: pass if not found: self.logdata("Unable to find index entry for "+i.name1+". Index : "+`i.index1`) except: pass except com_brew.BrewNoSuchFileException: pass return index, indexfile, index_const def getmedia(self, maps, result, key): """Returns the contents of media as a dict where the key is a name as returned by getindex, and the value is the contents of the media""" media={} type=None for offset,indexfile,location,type,maxentries,const in maps: index=self.getindex(indexfile) for i in index: try: media[index[i]]=self.getfilecontents(location+"/"+index[i], True) except (com_brew.BrewNoSuchFileException,com_brew.BrewBadPathnameException,com_brew.BrewNameTooLongException): self.log("It was in the index, but not on the filesystem") index, indexfile, index_const=self.get_content_file(key) for i in index: try: buf=prototypes.buffer(self.getfilecontents(self.protocolclass.media_directory+'/'+indexfile[i-index_const], True)) _fname=index[i] media[_fname]=buf.getdata() except (com_brew.BrewNoSuchFileException,com_brew.BrewBadPathnameException,com_brew.BrewNameTooLongException): self.log("It was in the index, but not on the filesystem") self.log("Contents not in the filesystem") result[key]=media return result def getmediaindex(self, builtins, maps, results, key): """Gets the media (wallpaper/ringtone) index @param builtins: the builtin list on the phone @param results: places results in this dict @param maps: the list of index files and locations @param key: key to place results in """ self.log("Reading "+key) media={} c=1 for name in builtins: media[c]={'name': name, 'origin': 'builtin' } c+=1 type=None for offset,indexfile,location,type,maxentries,const in maps: index=self.getindex(indexfile) for i in index: media[i+offset]={'name': index[i], 'origin': type} if key=='ringtone-index': type='ringers' else: type='images' index,_,_=self.get_content_file(key) for i in index: media[i]={'name': index[i], 'origin': type} results[key]=media return media def savemedia(self, mediakey, mediaindexkey, results, merge, reindexfunction): """Actually saves out the media @param mediakey: key of the media (eg 'wallpapers' or 'ringtones') @param mediaindexkey: index key (eg 'wallpaper-index') @param maps: list index files and locations @param results: results dict @param merge: are we merging or overwriting what is there? @param reindexfunction: the media is re-indexed at the end. this function is called to do it """ content_changed=False media=results[mediakey].copy() if mediaindexkey=='ringtone-index': type='ringers' content_type="Ringers" indexfile=self.protocolclass.ringerindex index_const=self.protocolclass.ringerconst max_media_entries=self.protocolclass.max_ringers for i in media.keys(): try: if media[i]['origin']=='voice_memo': del media[i] except: pass else: type='images' content_type="Screen Savers" indexfile=self.protocolclass.imageindex index_const=self.protocolclass.imageconst max_media_entries=self.protocolclass.max_images for i in media.keys(): try: if media[i]['origin']=='camera': del media[i] except: pass content={} try: buf=prototypes.buffer(self.getfilecontents(self.protocolclass.content_file_name)) g=self.protocolclass.content_file() g.readfrombuffer(buf) for i in g.items: if i.type=='!C': content[int(i.index1)]= {'C': i} elif i.type=='!E': content[int(i.index2)]['E']=i except (com_brew.BrewNoSuchFileException,com_brew.BrewBadPathnameException,com_brew.BrewNameTooLongException): pass dirlisting=self.getfilesystem(self.protocolclass.media_directory) for i in dirlisting.keys(): dirlisting[i[len(self.protocolclass.media_directory)+1:]]=dirlisting[i] del dirlisting[i] init={} for k in content.keys(): if content[k]['C'].content_type==content_type: index=k name=content[k]['C'].name1 size=int(content[k]['C'].size) data=None for w in media: if common.stripext(media[w]['name'])==name and media[w]['data']!=None: size_fix=((3024+len(media[w]['data']))/1008)*1008 if size_fix==size: data=media[w]['data'] del media[w] break if not merge and data is None: del content[k] content_changed=True _fname='%02d.dat' % k if _fname in dirlisting: self.rmfile(self.protocolclass.media_directory+'/'+_fname) del dirlisting[_fname] gcdname='%02d.gcd' % k if gcdname in dirlisting: self.rmfile(self.protocolclass.media_directory+'/'+gcdname) del dirlisting[gcdname] urlname='%02d.url' % k if urlname in dirlisting: self.rmfile(self.protocolclass.media_directory+'/'+urlname) del dirlisting[urlname] continue init[index]={'name': name, 'data': data} applications={} for sp in range(100): if len(media.keys()) == 0: break if sp not in content: for w in media.keys(): C,E,add_to_index=self.make_new_media_entry(media[w], sp, type) if add_to_index=='index': content[sp]= {'C': C, 'E': E} init[sp]=media[w] content_changed=True elif add_to_index=='content': content[sp]= {'C': C, 'E': E} applications[sp]=media[w] content_changed=True else: self.log("Unknown media type for "+`media[w]['name']`+". Not written to phone.") sp-=1 del media[w] break if len(media.keys()): self.log("Phone index full, some media not written to phone") content_count=0 keys=content.keys() keys.sort() cfile=self.protocolclass.content_file() for k in keys: content_count+=1 cfile.items.append(content[k]['C']) for k in keys: cfile.items.append(content[k]['E']) entry=self.protocolclass.content_entry() entry.type='!F' cfile.items.append(entry) buffer=prototypes.buffer() cfile.writetobuffer(buffer) self.logdata("Updated content file "+self.protocolclass.content_file_name, buffer.getvalue(), cfile) self.writefile(self.protocolclass.content_file_name, buffer.getvalue()) countfile=self.protocolclass.content_count() countfile.count=`content_count` buffer=prototypes.buffer() countfile.writetobuffer(buffer) self.logdata("Updated content count file "+self.protocolclass.content_count_file_name, buffer.getvalue(), countfile) self.writefile(self.protocolclass.content_count_file_name, buffer.getvalue()) keys=init.keys() keys.sort() ifile=self.protocolclass.indexfile() ifile.numactiveitems=len(keys) for k in keys: entry=self.protocolclass.indexentry() entry.index=k entry.const=index_const entry.name='%02d.dat' % k ifile.items.append(entry) for k in range(max_media_entries): if k in keys: continue entry=self.protocolclass.indexentry() entry.index=k entry.const=index_const ifile.items.append(entry) buffer=prototypes.buffer() ifile.writetobuffer(buffer) self.logdata("Updated index file "+indexfile, buffer.getvalue(), ifile) self.writefile(indexfile, buffer.getvalue()) for k in keys: entry=init[k] data=entry.get("data", None) _fname='%02d.dat' % k gcdname='%02d.gcd' % k urlname='%02d.url' % k if data is None: if _fname not in dirlisting: self.log("Index error. I have no data for "+entry['name']+" and it isn't already in the filesystem") continue contentsize=len(data) urlcontents='file://'+entry['name'] gcdcontents=self.makegcd(entry['name'],contentsize) if _fname in dirlisting and len(data)==dirlisting[_fname]['size']: self.log("Skipping writing %s/%s as there is already a file of the same length" % (self.protocolclass.media_directory,entry['name'])) if gcdname not in dirlisting: self.writefile(self.protocolclass.media_directory+"/"+gcdname, gcdcontents) if urlname not in dirlisting: self.writefile(self.protocolclass.media_directory+"/"+urlname, urlcontents) continue self.writefile(self.protocolclass.media_directory+"/"+_fname, data) self.writefile(self.protocolclass.media_directory+"/"+gcdname, gcdcontents) self.writefile(self.protocolclass.media_directory+"/"+urlname, urlcontents) for k in applications.keys(): entry=applications[k] data=entry.get("data", None) _fname='%02d.jar' % k jadname='%02d.jad' % k urlname='%02d.url' % k if data is None: if _fname not in dirlisting: self.log("Index error. I have no data for "+entry['name']+" and it isn't already in the filesystem") print "here2" continue contentsize=len(data) urlcontents='file://'+entry['name'] jadcontents=self.makejad(entry['name'],contentsize) print "here3" if _fname in dirlisting and len(data)==dirlisting[_fname]['size']: self.log("Skipping writing %s/%s as there is already a file of the same length" % (self.protocolclass.media_directory,entry['name'])) if jadname not in dirlisting: self.writefile(self.protocolclass.media_directory+"/"+jadname, jadcontents) if urlname not in dirlisting: self.writefile(self.protocolclass.media_directory+"/"+urlname, urlcontents) print "here4" continue print "here5" self.writefile(self.protocolclass.media_directory+"/"+_fname, data) self.writefile(self.protocolclass.media_directory+"/"+jadname, jadcontents) self.writefile(self.protocolclass.media_directory+"/"+urlname, urlcontents) del results[mediakey] reindexfunction(results) if content_changed: results["rebootphone"]=True return results def make_new_media_entry(self, entry, index, type): c=self.protocolclass.content_entry() e=self.protocolclass.content_entry() name=common.stripext(entry['name']) ext=common.getext(entry['name']) data=entry.get("data", None) add_to_index='index' c.type='!C' c.index1=index c.name1=name try: c.mime_type=self.__mimetype[ext] except: add_to_index='none' return c, e, add_to_index if c.mime_type=='application/java-archive': c.content_type='Games' e.location_maybe='midlet:'+name add_to_index='content' elif type=='ringers': c.content_type='Ringers' else: c.content_type='Screen Savers' c.size=`((3024+len(data))/1008)*1008` e.type='!E' e.index2=index e.name2=name return c, e, add_to_index def makegcd(self,filename,size): "Build a GCD file for filename" ext=common.getext(filename.lower()) noextname=common.stripext(filename) try: mimetype=self.__mimetype[ext] gcdcontent="Content-Type: "+mimetype+"\nContent-Name: "+noextname+"\nContent-Version: 1.0\nContent-Vendor: BitPim\nContent-URL: file://"+filename+"\nContent-Size: "+`size`+"\nContent-Description: Content for V10044 LG PM225"+"\n\n\n" except: gcdcontent="Content-Name: "+noextname+"\nContent-Version: 1.0\nContent-Vendor: BitPim\nContent-URL: file://"+filename+"\nContent-Size: "+`size`+"\n\n\n" return gcdcontent def makejad(self,filename,size): "Build a JAD file for filename" ext=common.getext(filename.lower()) noextname=common.stripext(filename) jadcontent="MIDlet-1: "+noextname+", "+noextname+".png, BitPim\nMIDlet-Jar-Size: "+`size`+"\nMIDlet-Jar-URL: "+filename+"\nMIDlet-Name: "+noextname+"\nMIDlet-Vendor: Unknown\nMIDlet-Version: 1.0\nMicroEdition-Configuration: CLDC-1.0\nMicroEdition-Profile: MIDP-1.0\nContent-Folder: Games\n\n\n" return jadcontent brew_version_file='ams/version.txt' brew_version_txt_key='ams_version.txt' my_model='PM225' def getphoneinfo(self, phone_info): self.log('Getting Phone Info') try: s=self.getfilecontents('ams/version.txt') if s[:5]==self.my_model: phone_info.append('Model:', self.my_model) phone_info.append('ESN:', self.get_brew_esn()) req=p_brew.firmwarerequest() txt=self.getfilecontents("nvm/nvm/nvm_0000")[207:217] phone_info.append('Phone Number:', txt) except: pass return "Talk to the LG PM225 cell phone" parentprofile=com_lgvx4400.Profile class Profile (parentprofile) : protocolclass=Phone.protocolclass serialsname=Phone.serialsname BP_Calendar_Version=3 phone_manufacturer='LG Electronics Inc' phone_model='PM225' brew_required=True RINGTONE_LIMITS= { 'MAXSIZE': 250000 } WALLPAPER_WIDTH=160 WALLPAPER_HEIGHT=120 MAX_WALLPAPER_BASENAME_LENGTH=30 WALLPAPER_FILENAME_CHARS="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 .-_" WALLPAPER_CONVERT_FORMAT="jpg" MAX_RINGTONE_BASENAME_LENGTH=30 RINGTONE_FILENAME_CHARS="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 .-_" DIALSTRING_CHARS="[^0-9PT#*]" imagetargets={} imagetargets.update(common.getkv(parentprofile.stockimagetargets, "wallpaper", {'width': 160, 'height': 120, 'format': "JPEG"})) autodetect_delay=3 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={} speeds={} for pbentry in data['phonebook']: if len(results)==self.protocolclass.NUMPHONEBOOKENTRIES: break e={} entry=data['phonebook'][pbentry] try: serial1=helper.getserial(entry.get('serials', []), self.serialsname, data['uniqueserial'], 'serial1', 0xFFFFFFFF) e['serial1']=serial1 for ss in entry["serials"]: if ss["sourcetype"]=="bitpim": e['bitpimserial']=ss assert e['bitpimserial'] e['name']=helper.getfullname(entry.get('names', []),1,1,32)[0] cat=helper.makeone(helper.getcategory(entry.get('categories', []),0,1,32), None) if cat is None: e['group']=0 else: key,value=self._getgroup(cat, data['groups']) if key is not None: e['group']=key else: e['group']=0 emails=helper.getemails(entry.get('emails', []) ,0,self.protocolclass.NUMEMAILS,72) e['emails']=helper.filllist(emails, self.protocolclass.NUMEMAILS, "") e['url']=helper.makeone(helper.geturls(entry.get('urls', []), 0,1,74), "") e['memo']=helper.makeone(helper.getmemos(entry.get('memos', []), 0, 1, self.protocolclass.MEMOLENGTH-1), "") minnumbers=1 if len(emails): minnumbers=0 numbers=helper.getnumbers(entry.get('numbers', []),minnumbers,self.protocolclass.NUMPHONENUMBERS) e['numberspeeds']=[] e['numbertypes']=[] e['numbers']=[] for numindex in range(len(numbers)): num=numbers[numindex] b4=len(e['numbertypes']) type=num['type'] for i,t in enumerate(self.protocolclass.numbertypetab): if type==t: e['numbertypes'].append(i) break if t=='none': e['numbertypes'].append(i) break if len(e['numbertypes'])==b4: helper.add_error_message("%s has number %s if of type %s not supported by phone" % (e['name'], num['number'], num['type'])) continue number=self.phonize(num['number']) if len(number)==0: continue if len(number)>48: number=number[:48] e['numbers'].append(number) sd=num.get("speeddial", 0xFF) if sd>=self.protocolclass.FIRSTSPEEDDIAL and sd<=self.protocolclass.LASTSPEEDDIAL: e['numberspeeds'].append(sd) else: e['numberspeeds'].append(0xFF) e['numberspeeds']=helper.filllist(e['numberspeeds'], 5, 0xFF) e['numbertypes']=helper.filllist(e['numbertypes'], 5, 0) e['numbers']=helper.filllist(e['numbers'], 5, "") 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) results[pbentry]=e except helper.ConversionFailed: continue data['phonebook']=results return data _supportedsyncs=( ('phonebook', 'read', None), ('calendar', 'read', None), ('wallpaper', 'read', None), ('ringtone', 'read', None), ('call_history', 'read', None), ('memo', 'read', None), ('sms', 'read', None), ('phonebook', 'write', 'OVERWRITE'), ('calendar', 'write', 'OVERWRITE'), ('wallpaper', 'write', 'MERGE'), ('wallpaper', 'write', 'OVERWRITE'), ('ringtone', 'write', 'MERGE'), ('ringtone', 'write', 'OVERWRITE'), ('memo', 'write', 'OVERWRITE'), ('sms', 'write', 'OVERWRITE'), ) def QueryAudio(self, origin, currentextension, afi): if afi.format in ("MIDI", "QCP"): return currentextension, afi if afi.format=="MP3": if afi.channels==1 and 8<=afi.bitrate<=128 and 16000<=afi.samplerate<=44100: return currentextension, afi return ("mp3", fileinfo.AudioFileInfo(afi, **{'format': 'MP3', 'channels': 1, 'bitrate': 32, 'samplerate': 22050})) field_color_data={ 'phonebook': { 'name': { 'first': 0, 'middle': 0, 'last': 0, 'full': 1, 'nickname': 0, 'details': 1 }, 'number': { 'type': 5, 'speeddial': 5, 'number': 5, 'details': 5 }, 'email': 3, 'address': { 'type': 0, 'company': 0, 'street': 0, 'street2': 0, 'city': 0, 'state': 0, 'postalcode': 0, 'country': 0, 'details': 0 }, 'url': 1, 'memo': 1, 'category': 1, 'wallpaper': 1, 'ringtone': 1, 'storage': 0, }, 'calendar': { 'description': True, 'location': False, 'allday': True, 'start': True, 'end': True, 'priority': False, 'alarm': True, 'vibrate': False, 'repeat': True, 'memo': False, 'category': False, 'wallpaper': False, 'ringtone': True, }, 'memo': { 'subject': True, 'date': False, 'secret': False, 'category': False, 'memo': True, }, 'todo': { 'summary': False, 'status': False, 'due_date': False, 'percent_complete': False, 'completion_date': False, 'private': False, 'priority': False, 'category': False, 'memo': False, }, } imagetargets.update(common.getkv(parentprofile.stockimagetargets, "wallpaper", {'width': 160, 'height': 120, 'format': "JPEG"}))
def savemedia(self, mediakey, mediaindexkey, maps, results, merge, reindexfunction): """Actually saves out the media @param mediakey: key of the media (eg 'wallpapers' or 'ringtones') @param mediaindexkey: index key (eg 'wallpaper-index') @param maps: list index files and locations @param results: results dict @param merge: are we merging or overwriting what is there? @param reindexfunction: the media is re-indexed at the end. this function is called to do it """ print results.keys() # I humbly submit this as the longest function in the bitpim code ... # wp and wpi are used as variable names as this function was originally # written to do wallpaper. it works just fine for ringtones as well wp = results[mediakey].copy() wpi = results[mediaindexkey].copy() # remove builtins for k in wpi.keys(): if wpi[k]["origin"] == "builtin": del wpi[k] # sort results['mediakey'+'-index'] into origin buckets # build up list into init init = {} for offset, indexfile, location, type, maxentries in maps: if type == "camera": continue init[type] = {} for k in wpi.keys(): if wpi[k]["origin"] == type: index = k - offset name = wpi[k]["name"] data = None del wpi[k] for w in wp.keys(): if wp[w]["name"] == name and wp[w]["origin"] == type: data = wp[w]["data"] del wp[w] if not merge and data is None: # delete the entry continue init[type][index] = {"name": name, "data": data} # init now contains everything from wallpaper-index print init.keys() # now look through wallpapers and see if anything remaining was assigned a particular # origin for w in wp.keys(): o = wp[w].get("origin", "") if o is not None and len(o) and o in init: idx = -1 while idx in init[o]: idx -= 1 init[o][idx] = wp[w] del wp[w] # we now have init[type] with the entries and index number as key (negative indices are # unallocated). Proceed to deal with each one, taking in stuff from wp as we have space for offset, indexfile, location, type, maxentries in maps: if type == "camera": continue index = init[type] try: dirlisting = self.getfilesystem(location) except com_brew.BrewNoSuchDirectoryException: self.mkdirs(location) dirlisting = {} # rename keys to basename, allow for debug filesystem not putting full path in key for i in dirlisting.keys(): if len(i) > len(location) and i[len(location)] == location: dirlisting[i[len(location) + 1 :]] = dirlisting[i] del dirlisting[i] # what we will be deleting dellist = [] if not merge: # get existing wpi for this location wpi = results[mediaindexkey] for i in wpi: entry = wpi[i] if entry["origin"] == type: # it is in the original index, are we writing it back out? delit = True for idx in index: if index[idx]["name"] == entry["name"]: delit = False break if delit: if common.stripext(entry["name"]) in dirlisting: dellist.append(common.stripext(entry["name"])) else: self.log("%s in %s index but not filesystem" % (entry["name"], type)) # go ahead and delete unwanted files print "deleting", dellist for f in dellist: self.rmdirs(location + "/" + f) # slurp up any from wp we can take while len(index) < maxentries and len(wp): idx = -1 while idx in index: idx -= 1 k = wp.keys()[0] index[idx] = wp[k] del wp[k] # normalise indices index = self._normaliseindices(index) # hey look, I called a function! # move any overflow back into wp if len(index) > maxentries: keys = index.keys() keys.sort() for k in keys[maxentries:]: idx = -1 while idx in wp: idx -= 1 wp[idx] = index[k] del index[k] # write out the new index keys = index.keys() keys.sort() ifile = self.protocolclass.indexfile() ifile.numactiveitems = len(keys) for k in keys: entry = self.protocolclass.indexentry() entry.index = k entry.name = common.stripext(index[k]["name"]) ifile.items.append(entry) while len(ifile.items) < maxentries: ifile.items.append(self.protocolclass.indexentry()) buffer = prototypes.buffer() ifile.writetobuffer(buffer, logtitle="Updated index file " + indexfile) self.writefile(indexfile, buffer.getvalue()) # Write out files - we compare against existing dir listing and don't rewrite if they # are the same size for k in keys: entry = index[k] data = entry.get("data", None) dirname = common.stripext(entry["name"]) if data is None: if dirname not in dirlisting: self.log( "Index error. I have no data for " + dirname + " and it isn't already in the filesystem" ) continue if dirname in dirlisting: try: stat = self.statfile(location + "/" + dirname + "/body") if stat["size"] == len(data): # check that the .desc file exists stat = self.statfile(location + "/" + dirname + "/.desc") if stat["size"] == 152: self.log( "Skipping writing %s/%s/body as there is already a file of the same length" % (location, dirname) ) continue except com_brew.BrewNoSuchFileException: pass elif dirname not in dirlisting: try: self.mkdir(location + "/" + dirname) except com_brew.BrewDirectoryExistsException: pass # write out media self.writefile(location + "/" + dirname + "/body", data) mimetype = self._getmimetype(entry["name"]) desc = self.protocolclass.mediadesc() desc.mimetype = mimetype desc.totalsize = 0 desc.totalsize = desc.packetsize() + len(data) buf = prototypes.buffer() descfile = "%s/%s/.desc" % (location, dirname) desc.writetobuffer(buf, logtitle="Desc file at " + descfile) self.writefile(descfile, buf.getvalue()) # did we have too many if len(wp): for k in wp: self.log("Unable to put %s on the phone as there weren't any spare index entries" % (wp[k]["name"],)) # tidy up - reread indices del results[mediakey] # done with it reindexfunction(results) return results
def savemedia(self, mediakey, mediaindexkey, maps, results, merge, reindexfunction): """Actually saves out the media @param mediakey: key of the media (eg 'wallpapers' or 'ringtones') @param mediaindexkey: index key (eg 'wallpaper-index') @param maps: list index files and locations @param results: results dict @param merge: are we merging or overwriting what is there? @param reindexfunction: the media is re-indexed at the end. this function is called to do it """ print results.keys() wp=results[mediakey].copy() wpi=results[mediaindexkey].copy() for k in wpi.keys(): if wpi[k]['origin']=='builtin': del wpi[k] init={} for offset,indexfile,location,type,maxentries in maps: if type=='camera': continue init[type]={} for k in wpi.keys(): if wpi[k]['origin']==type: index=k-offset name=wpi[k]['name'] data=None del wpi[k] for w in wp.keys(): if wp[w]['name']==name: data=wp[w]['data'] del wp[w] if not merge and data is None: continue init[type][index]={'name': name, 'data': data} print init.keys() for w in wp.keys(): o=wp[w].get("origin", "") if o is not None and len(o) and o in init: idx=-1 while idx in init[o]: idx-=1 init[o][idx]=wp[w] del wp[w] for offset,indexfile,location,type,maxentries in maps: if type=='camera': continue index=init[type] try: dirlisting=self.getfilesystem(location) except com_brew.BrewNoSuchDirectoryException: self.mkdirs(location) dirlisting={} for i in dirlisting.keys(): if len(i)>len(location) and i[len(location)]==location: dirlisting[i[len(location)+1:]]=dirlisting[i] del dirlisting[i] dellist=[] if not merge: wpi=results[mediaindexkey] for i in wpi: entry=wpi[i] if entry['origin']==type: delit=True for idx in index: if index[idx]['name']==entry['name']: delit=False break if delit: if common.stripext(entry['name']) in dirlisting: dellist.append(common.stripext(entry['name'])) else: self.log("%s in %s index but not filesystem" % (entry['name'], type)) print "deleting",dellist for f in dellist: self.rmdirs(location+"/"+f) while len(index)<maxentries and len(wp): idx=-1 while idx in index: idx-=1 k=wp.keys()[0] index[idx]=wp[k] del wp[k] index=self._normaliseindices(index) # hey look, I called a function! if len(index)>maxentries: keys=index.keys() keys.sort() for k in keys[maxentries:]: idx=-1 while idx in wp: idx-=1 wp[idx]=index[k] del index[k] keys=index.keys() keys.sort() ifile=self.protocolclass.indexfile() ifile.numactiveitems=len(keys) for k in keys: entry=self.protocolclass.indexentry() entry.index=k entry.name=common.stripext(index[k]['name']) ifile.items.append(entry) while len(ifile.items)<maxentries: ifile.items.append(self.protocolclass.indexentry()) buffer=prototypes.buffer() ifile.writetobuffer(buffer, logtitle="Updated index file "+indexfile) self.writefile(indexfile, buffer.getvalue()) for k in keys: entry=index[k] data=entry.get("data", None) dirname=common.stripext(entry['name']) if data is None: if dirname not in dirlisting: self.log("Index error. I have no data for "+dirname+" and it isn't already in the filesystem") continue if dirname in dirlisting: try: stat=self.statfile(location+"/"+dirname+"/body") if stat['size']==len(data): stat=self.statfile(location+"/"+dirname+"/.desc") if stat['size']==152: self.log("Skipping writing %s/%s/body as there is already a file of the same length" % (location,dirname)) continue except com_brew.BrewNoSuchFileException: pass elif dirname not in dirlisting: try: self.mkdir(location+"/"+dirname) except com_brew.BrewDirectoryExistsException: pass self.writefile(location+"/"+dirname+"/body", data) mimetype=self._getmimetype(entry['name']) desc=self.protocolclass.mediadesc() desc.mimetype=mimetype desc.totalsize=0 desc.totalsize=desc.packetsize()+len(data) buf=prototypes.buffer() descfile="%s/%s/.desc" % (location, dirname) desc.writetobuffer(buf, logtitle="Desc file at "+descfile) self.writefile(descfile, buf.getvalue()) if len(wp): for k in wp: self.log("Unable to put %s on the phone as there weren't any spare index entries" % (wp[k]['name'],)) del results[mediakey] # done with it reindexfunction(results) return results
def savewallpapers(self, result, merge): dircache = self.DirCache(self) media_prefix = self.protocolclass.WALLPAPERPREFIX endtransactionpath = self.protocolclass.ENDTRANSACTION media = result.get('wallpapers', {}) for i in media.keys(): try: if media[i]['origin'] == 'camera': del media[i] except: pass media_index = result.get('wallpaper-index', {}) media_names = [x['name'] for x in media.values()] index_names = [x['name'] for x in media_index.values()] if merge: del_names = [] else: del_names = [ common.stripext(x) for x in index_names if x not in media_names ] gcdpattern = re.compile("[\n\r]Content-Name: +(.*?)[\n\r]") new_names = [x for x in media_names if x not in index_names] progressmax = len(del_names) + len(new_names) progresscur = 0 self.log("Writing images") self.progress(progresscur, progressmax, "Writing images") for icnt in range(1, 101): if not (new_names or del_names): break fname = media_prefix + ` icnt ` fnamegcd = media_prefix + ` icnt ` + ".gcd" fstat = dircache.stat(fnamegcd) if del_names and fstat: # See if this file is in list of files to delete gcdcontents = dircache.readfile(fnamegcd) thisfile = gcdpattern.search(gcdcontents).groups()[0] if thisfile in del_names: self.log("Deleting image " + thisfile) self.progress(progresscur, progressmax, "Deleting image " + thisfile) progresscur += 1 dircache.rmfile(fname) dircache.rmfile(fnamegcd) del_names.remove(thisfile) fstat = False if new_names and not fstat: newname = new_names.pop() contents = "" for k in media.keys(): if media[k]['name'] == newname: contents = media[k]['data'] break contentsize = len(contents) if contentsize: gcdcontents = self.makegcd(newname, contentsize, self.__image_mimetype) self.log("Writing image " + newname) self.progress(progresscur, progressmax, "Deleting image " + newname) progresscur += 1 dircache.writefile(fname, contents) dircache.writefile(fnamegcd, gcdcontents) fstat = dircache.stat(endtransactionpath) self.log("Finished writing images") self.progress(progressmax, progressmax, "Finished writing images") if fstat: dircache.rmfile(endtransactionpath) result['rebootphone'] = True return
def savemedia(self, mediakey, mediaindexkey, maps, results, merge, reindexfunction): """Actually saves out the media @param mediakey: key of the media (eg 'wallpapers' or 'ringtones') @param mediaindexkey: index key (eg 'wallpaper-index') @param maps: list index files and locations @param results: results dict @param merge: are we merging or overwriting what is there? @param reindexfunction: the media is re-indexed at the end. this function is called to do it """ print results.keys() # I humbly submit this as the longest function in the bitpim code ... # wp and wpi are used as variable names as this function was originally # written to do wallpaper. it works just fine for ringtones as well wp = results[mediakey].copy() wpi = results[mediaindexkey].copy() # remove builtins for k in wpi.keys(): if wpi[k]['origin'] == 'builtin': del wpi[k] # sort results['mediakey'+'-index'] into origin buckets # build up list into init init = {} for offset, indexfile, location, type, maxentries in maps: if type == 'camera': continue init[type] = {} for k in wpi.keys(): if wpi[k]['origin'] == type: index = k - offset name = wpi[k]['name'] data = None del wpi[k] for w in wp.keys(): if wp[w]['name'] == name and wp[w]['origin'] == type: data = wp[w]['data'] del wp[w] if not merge and data is None: # delete the entry continue init[type][index] = {'name': name, 'data': data} # init now contains everything from wallpaper-index print init.keys() # now look through wallpapers and see if anything remaining was assigned a particular # origin for w in wp.keys(): o = wp[w].get("origin", "") if o is not None and len(o) and o in init: idx = -1 while idx in init[o]: idx -= 1 init[o][idx] = wp[w] del wp[w] # we now have init[type] with the entries and index number as key (negative indices are # unallocated). Proceed to deal with each one, taking in stuff from wp as we have space for offset, indexfile, location, type, maxentries in maps: if type == 'camera': continue index = init[type] try: dirlisting = self.getfilesystem(location) except com_brew.BrewNoSuchDirectoryException: self.mkdirs(location) dirlisting = {} # rename keys to basename, allow for debug filesystem not putting full path in key for i in dirlisting.keys(): if len(i) > len(location) and i[len(location)] == location: dirlisting[i[len(location) + 1:]] = dirlisting[i] del dirlisting[i] # what we will be deleting dellist = [] if not merge: # get existing wpi for this location wpi = results[mediaindexkey] for i in wpi: entry = wpi[i] if entry['origin'] == type: # it is in the original index, are we writing it back out? delit = True for idx in index: if index[idx]['name'] == entry['name']: delit = False break if delit: if common.stripext(entry['name']) in dirlisting: dellist.append(common.stripext(entry['name'])) else: self.log("%s in %s index but not filesystem" % (entry['name'], type)) # go ahead and delete unwanted files print "deleting", dellist for f in dellist: self.rmdirs(location + "/" + f) # slurp up any from wp we can take while len(index) < maxentries and len(wp): idx = -1 while idx in index: idx -= 1 k = wp.keys()[0] index[idx] = wp[k] del wp[k] # normalise indices index = self._normaliseindices( index) # hey look, I called a function! # move any overflow back into wp if len(index) > maxentries: keys = index.keys() keys.sort() for k in keys[maxentries:]: idx = -1 while idx in wp: idx -= 1 wp[idx] = index[k] del index[k] # write out the new index keys = index.keys() keys.sort() ifile = self.protocolclass.indexfile() ifile.numactiveitems = len(keys) for k in keys: entry = self.protocolclass.indexentry() entry.index = k entry.name = common.stripext(index[k]['name']) ifile.items.append(entry) while len(ifile.items) < maxentries: ifile.items.append(self.protocolclass.indexentry()) buffer = prototypes.buffer() ifile.writetobuffer(buffer, logtitle="Updated index file " + indexfile) self.writefile(indexfile, buffer.getvalue()) # Write out files - we compare against existing dir listing and don't rewrite if they # are the same size for k in keys: entry = index[k] data = entry.get("data", None) dirname = common.stripext(entry['name']) if data is None: if dirname not in dirlisting: self.log("Index error. I have no data for " + dirname + " and it isn't already in the filesystem") continue if dirname in dirlisting: try: stat = self.statfile(location + "/" + dirname + "/body") if stat['size'] == len(data): # check that the .desc file exists stat = self.statfile(location + "/" + dirname + "/.desc") if stat['size'] == 152: self.log( "Skipping writing %s/%s/body as there is already a file of the same length" % (location, dirname)) continue except com_brew.BrewNoSuchFileException: pass elif dirname not in dirlisting: try: self.mkdir(location + "/" + dirname) except com_brew.BrewDirectoryExistsException: pass # write out media self.writefile(location + "/" + dirname + "/body", data) mimetype = self._getmimetype(entry['name']) desc = self.protocolclass.mediadesc() desc.mimetype = mimetype desc.totalsize = 0 desc.totalsize = desc.packetsize() + len(data) buf = prototypes.buffer() descfile = "%s/%s/.desc" % (location, dirname) desc.writetobuffer(buf, logtitle="Desc file at " + descfile) self.writefile(descfile, buf.getvalue()) # did we have too many if len(wp): for k in wp: self.log( "Unable to put %s on the phone as there weren't any spare index entries" % (wp[k]['name'], )) # tidy up - reread indices del results[mediakey] # done with it reindexfunction(results) return results