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 _mark_files(self, local_files, rs_files, local_dir): # create empty local files as markers for remote files _empty_files=[common.basename(x) for x,_entry in local_files.items() \ if not _entry['size']] _remote_files=[common.basename(x) for x in rs_files] for _file in _remote_files: if _file not in _empty_files: # mark this one self.writefile(local_dir+'/'+_file, '') for _file in _empty_files: if _file not in _remote_files: # remote file no longer exists, del the marker self.rmfile(local_dir+'/'+_file)
def getmedia(self, maps, results, key): media={} for type, indexfile, sizefile, directory, lowestindex, maxentries, typemajor, def_icon, idx_ofs in maps: for item in self.getindex(indexfile): try: if not self._is_rs_file(item.filename): media[common.basename(item.filename)]=self.getfilecontents( item.filename, True) except (com_brew.BrewNoSuchFileException,com_brew.BrewBadPathnameException,com_brew.BrewNameTooLongException): self.log("It was in the index, but not on the filesystem") except com_brew.BrewAccessDeniedException: self.log('Failed to read file: '+item.filename) media[common.basename(item.filename)]='' results[key]=media return results
def getmedia(self, maps, results, key): origins={} # signal that we are using the new media storage that includes the origin and timestamp origins['new_media_version']=1 for type, indexfile, sizefile, directory, lowestindex, maxentries, typemajor, def_icon, idx_ofs in maps: media={} for item in self.getindex(indexfile): data=None timestamp=None try: stat_res=self.statfile(item.filename) if stat_res!=None: timestamp=stat_res['date'][0] if not self._is_rs_file(item.filename): data=self.getfilecontents(item.filename, True) except (com_brew.BrewNoSuchFileException,com_brew.BrewBadPathnameException,com_brew.BrewNameTooLongException): self.log("It was in the index, but not on the filesystem") except com_brew.BrewAccessDeniedException: # firmware wouldn't let us read this file, just mark it then self.log('Failed to read file: '+item.filename) data='' except: if __debug__: raise self.log('Failed to read file: '+item.filename) data='' if data!=None: media[common.basename(item.filename)]={ 'data': data, 'timestamp': timestamp} origins[type]=media results[key]=origins return results
def ReplaceContents(self, name, origin, new_file_name): """Replace the contents of 'file_name' by the contents of 'new_file_name' by going through the image converter dialog """ file_stat=os.stat(new_file_name) mtime=file_stat.st_mtime afi=fileinfo.identify_audiofile(new_file_name) if afi.size<=0: return # zero length file or other issues newext,convertinfo=self.mainwindow.phoneprofile.QueryAudio( None, common.getext(new_file_name), afi) if convertinfo is not afi: filedata=None try: filedata=self.ConvertFormat(new_file_name, convertinfo) except: pass if filedata is None: return else: filedata=open(new_file_name, "rb").read() # check for the size limit on the file, if specified max_size=getattr(convertinfo, 'MAXSIZE', None) if max_size is not None and len(filedata)>max_size: # the data is too big self.log('ringtone %s is too big!'%common.basename(file)) with guihelper.WXDialogWrapper(wx.MessageDialog(self, 'Ringtone %s may be too big. Do you want to proceed anway?'%common.basename(file), 'Warning', style=wx.YES_NO|wx.ICON_ERROR), True) as (dlg, dlg_resp): if dlg_resp==wx.ID_NO: return self.AddToIndex(name, origin, filedata, self._data, mtime)
def _get_ringtone_index(self): res = {} # first the builtin ones for _l in self.builtinringtones: _idx = _l[0] for _e in _l[1]: res[_idx] = {'name': _e, 'origin': 'builtin'} _idx += 1 # now the custome one _buf = prototypes.buffer( self.getfilecontents(self.protocolclass.RT_INDEX_FILE)) _idx_file = self.protocolclass.ringtone_index_file() _idx_file.readfrombuffer(_buf, logtitle='Read ringtone index file') for _entry in _idx_file.items: _filename = self.decode_utf16(_entry.name) if _filename.startswith(self.protocolclass.RT_PATH): _origin = 'ringers' elif _filename.startswith(self.protocolclass.SND_PATH): _origin = 'sounds' else: # neither ringtone nor sounds, can't use this continue res[_entry.index] = { 'name': common.basename(_filename), 'filename': _filename, 'type': _entry.ringtone_type, 'origin': _origin } return res
def _get_file_wallpaper_index(self, idx, result, indexfilename, origin): try: _buf=prototypes.buffer(self.getfilecontents(indexfilename)) except (com_brew.BrewNoSuchFileException, com_brew.BrewBadPathnameException, com_brew.BrewFileLockedException, com_brew.BrewAccessDeniedException): return idx except: if __debug__: raise return idx _index_file=self.protocolclass.RPictureIndexFile() _index_file.readfrombuffer(_buf) for _entry in _index_file.items: if _entry.pictype==self.protocolclass.PIC_TYPE_USERS: if _entry.pathname.startswith('/ff/'): _file_name=_entry.pathname[4:] else: _file_name=_entry.pathname result[idx]={ 'name': common.basename(_entry.pathname), 'filename': _file_name, 'origin': origin, } idx+=1 return idx
def ReplaceContents(self, name, origin, new_file_name): """Replace the contents of 'file_name' by the contents of 'new_file_name' by going through the image converter dialog """ file_stat=os.stat(new_file_name) mtime=file_stat.st_mtime afi=fileinfo.identify_audiofile(new_file_name) if afi.size<=0: return # zero length file or other issues newext,convertinfo=self.mainwindow.phoneprofile.QueryAudio( None, common.getext(new_file_name), afi) if convertinfo is not afi: filedata=None try: filedata=self.ConvertFormat(new_file_name, convertinfo) except: pass if filedata is None: return else: filedata=open(new_file_name, "rb").read() max_size=getattr(convertinfo, 'MAXSIZE', None) if max_size is not None and len(filedata)>max_size: self.log('ringtone %s is too big!'%common.basename(file)) dlg=wx.MessageDialog(self, 'Ringtone %s may be too big. Do you want to proceed anway?'%common.basename(file), 'Warning', style=wx.YES_NO|wx.ICON_ERROR) dlg_resp=dlg.ShowModal() dlg.Destroy() if dlg_resp==wx.ID_NO: return self.AddToIndex(name, origin, filedata, self._data, mtime)
def _get_ringtone_index(self): res={} # first the builtin ones for _l in self.builtinringtones: _idx=_l[0] for _e in _l[1]: res[_idx]={ 'name': _e, 'origin': 'builtin' } _idx+=1 # now the custome one _buf=prototypes.buffer(self.getfilecontents( self.protocolclass.RT_INDEX_FILE)) _idx_file=self.protocolclass.ringtone_index_file() _idx_file.readfrombuffer(_buf, logtitle='Read ringtone index file') for _entry in _idx_file.items: _filename=self.decode_utf16(_entry.name) if _filename.startswith(self.protocolclass.RT_PATH): _origin='ringers' elif _filename.startswith(self.protocolclass.SND_PATH): _origin='sounds' else: # neither ringtone nor sounds, can't use this continue res[_entry.index]={ 'name': common.basename(_filename), 'filename': _filename, 'type': _entry.ringtone_type, 'origin': _origin } return res
def getmedia(self, maps, results, key): origins={} # signal that we are using the new media storage that includes the origin and timestamp origins['new_media_version']=1 for type, indexfile, sizefile, directory, lowestindex, maxentries, typemajor, def_icon, idx_ofs in maps: media={} for item in self.getindex(indexfile): data=None timestamp=None try: stat_res=self.statfile(item.filename) if stat_res!=None: timestamp=stat_res['date'][0] if not self._is_rs_file(item.filename): data=self.getfilecontents(item.filename, True) except (com_brew.BrewNoSuchFileException,com_brew.BrewBadPathnameException,com_brew.BrewNameTooLongException): self.log("It was in the index, but not on the filesystem") except com_brew.BrewAccessDeniedException: # firmware wouldn't let us read this file, just mark it then self.log('Failed to read file: '+item.filename) data='' if data!=None: media[common.basename(item.filename)]={ 'data': data, 'timestamp': timestamp} origins[type]=media results[key]=origins return results
def _extract_ringtone(self, entry, p_class): if self.pb.info&p_class.PB_FLG_CRINGTONE and \ self.pb.ringtone: entry['ringtones'] = [{ 'ringtone': common.basename(self.pb.ringtone), 'use': 'call' }]
def _get_file_ringtone_index(self, idx, result, index_file_name, index_file_class, origin): try: _buf=prototypes.buffer(self.getfilecontents(index_file_name)) except (com_brew.BrewNoSuchFileException, com_brew.BrewBadPathnameException, com_brew.BrewFileLockedException, com_brew.BrewAccessDeniedException): return idx except: if __debug__: raise return idx _index_file=index_file_class() _index_file.readfrombuffer(_buf) for _entry in _index_file.items: if _entry.pathname.startswith('/ff/'): _file_name=_entry.pathname[4:] else: _file_name=_entry.pathname result[idx]= { 'name': common.basename(_entry.pathname), 'filename': _file_name, 'origin': origin, } idx+=1 return idx
def _get_file_ringtone_index(self, idx, result, index_file_name, index_file_class, origin): try: _buf = prototypes.buffer(self.getfilecontents(index_file_name)) except (com_brew.BrewNoSuchFileException, com_brew.BrewBadPathnameException, com_brew.BrewFileLockedException, com_brew.BrewAccessDeniedException): return idx except: if __debug__: raise return idx _index_file = index_file_class() _index_file.readfrombuffer(_buf) for _entry in _index_file.items: if _entry.pathname.startswith('/ff/'): _file_name = _entry.pathname[4:] else: _file_name = _entry.pathname if not _file_name.startswith( self.protocolclass.SND_PRELOADED_PREFIX): result[idx] = { 'name': common.basename(_entry.pathname), 'filename': _file_name, 'origin': origin, } idx += 1 return idx
def getcalendar(self, result): res = {} # Read exceptions file first exceptions = self.getexceptions() # Now read schedule try: buf = prototypes.buffer(self.getfilecontents( self.calendarlocation)) if len(buf.getdata()) < 3: # file is empty, and hence same as non-existent raise com_brew.BrewNoSuchFileException() sc = self.protocolclass.schedulefile() sc.readfrombuffer(buf, logtitle="Calendar") for event in sc.events: # the vx8100 has a bad entry when the calender is empty # stop processing the calender when we hit this record if event.pos == 0: #invalid entry continue entry = bpcalendar.CalendarEntry() try: # delete events are still in the calender file but have garbage dates self.getcalendarcommon(entry, event) except ValueError: continue if self.protocolclass.CALENDAR_HAS_SEPARATE_END_TIME_AND_DATE: # MIC Unlike previous phones, the VX8300 passes the ringtone # via both the index, and a path. If the index is set to 100 # (0x64), then the ringtone information will be found in the # "ringpath", the last 256 bytes of the calendar packet. If # the index is between 0 and 15, inclusive, then it is using # one of the builtin ringers, and the ringpath is set to # null. try: if (event.ringtone == 100 ): # MIC Ringer is downloaded to phone or microSD entry.ringtone = common.basename(event.ringpath) else: # MIC Ringer is built-in entry.ringtone = self.builtinringtones[ event.ringtone] except: # hack, not having a phone makes it hard to figure out the best approach if entry.alarm == None: entry.ringtone = 'No Ring' else: entry.ringtone = 'Loud Beeps' else: entry.ringtone = result['ringtone-index'][ event.ringtone]['name'] # check for exceptions and remove them if event.repeat[3] and exceptions.has_key(event.pos): for year, month, day in exceptions[event.pos]: entry.suppress_repeat_entry(year, month, day) res[entry.id] = entry assert sc.numactiveitems == len(res) except com_brew.BrewNoSuchFileException: pass # do nothing if file doesn't exist result['calendar'] = res return result
def _createnamewithmimetype(self, name, mt): name=common.basename(name) if mt=="image/jpeg": mt="image/jpg" try: return name+self.__mimetoextensionmapping[mt] except KeyError: self.log("Unable to figure out extension for mime type "+mt) return name
def getcalendar(self, result): res = {} # Read exceptions file first exceptions = self.getexceptions() try: buf = prototypes.buffer( self.getfilecontents(self.calendarringerlocation)) ringersf = self.protocolclass.scheduleringerfile() ringersf.readfrombuffer(buf) except: self.log("unable to read schedule ringer path file") # Now read schedule try: buf = prototypes.buffer(self.getfilecontents( self.calendarlocation)) if len(buf.getdata()) < 3: # file is empty, and hence same as non-existent raise com_brew.BrewNoSuchFileException() sc = self.protocolclass.schedulefile() sc.readfrombuffer(buf, logtitle="Calendar") for event in sc.events: # the vx8100 has a bad entry when the calender is empty # stop processing the calender when we hit this record if event.pos == 0: #invalid entry continue entry = bpcalendar.CalendarEntry() try: # delete events are still in the calender file but have garbage dates self.getcalendarcommon(entry, event) except ValueError: continue try: if (event.ringtone >= 100 ): # MIC Ringer is downloaded to phone or microSD entry.ringtone = common.basename( ringersf.ringerpaths[event.ringtone - 100].path) else: # MIC Ringer is built-in entry.ringtone = self.builtinringtones[event.ringtone] except: self.log("Setting default ringer for event\n") # hack, not having a phone makes it hard to figure out the best approach if entry.alarm == None: entry.ringtone = 'No Ring' else: entry.ringtone = 'Loud Beeps' # check for exceptions and remove them if event.repeat[3] and exceptions.has_key(event.pos): for year, month, day in exceptions[event.pos]: entry.suppress_repeat_entry(year, month, day) res[entry.id] = entry assert sc.numactiveitems == len(res) except com_brew.BrewNoSuchFileException: pass # do nothing if file doesn't exist result['calendar'] = res return result
def _createnamewithmimetype(self, name, mt): name = common.basename(name) if mt == "image/jpeg": mt = "image/jpg" try: return name + self.__mimetoextensionmapping[mt] except KeyError: self.log("Unable to figure out extension for mime type " + mt) return name
def _get_wallpaper_index(self): res={} _files=self.listfiles(self.protocolclass.WP_PATH).keys() _files.sort() _wp_path_len=len(self.protocolclass.WP_PATH)+1 for _index,_name in enumerate(_files): res[_index]={ 'name': common.basename(_name), 'filename': _name, 'origin': 'images' } return res
def _get_wallpaper_index(self): res = {} _files = self.listfiles(self.protocolclass.WP_PATH).keys() _files.sort() _wp_path_len = len(self.protocolclass.WP_PATH) + 1 for _index, _filename in enumerate(_files): _name = common.basename(_filename) if _name not in self.protocolclass.WP_EXCLUDED_FILES: res[_index] = {"name": _name, "filename": _filename, "origin": "images"} return res
def getcalendar(self,result): res={} # Read exceptions file first exceptions = self.getexceptions () # Now read schedule try: buf=prototypes.buffer(self.getfilecontents(self.calendarlocation)) if len(buf.getdata())<3: # file is empty, and hence same as non-existent raise com_brew.BrewNoSuchFileException() sc=self.protocolclass.schedulefile() sc.readfrombuffer(buf, logtitle="Calendar") for event in sc.events: # the vx8100 has a bad entry when the calender is empty # stop processing the calender when we hit this record if event.pos==0: #invalid entry continue entry=bpcalendar.CalendarEntry() try: # delete events are still in the calender file but have garbage dates self.getcalendarcommon (entry, event) except ValueError: continue if self.protocolclass.CALENDAR_HAS_SEPARATE_END_TIME_AND_DATE: # MIC Unlike previous phones, the VX8300 passes the ringtone # via both the index, and a path. If the index is set to 100 # (0x64), then the ringtone information will be found in the # "ringpath", the last 256 bytes of the calendar packet. If # the index is between 0 and 15, inclusive, then it is using # one of the builtin ringers, and the ringpath is set to # null. try: if (event.ringtone == 100): # MIC Ringer is downloaded to phone or microSD entry.ringtone = common.basename(event.ringpath) else: # MIC Ringer is built-in entry.ringtone=self.builtinringtones[event.ringtone] except: # hack, not having a phone makes it hard to figure out the best approach if entry.alarm==None: entry.ringtone='No Ring' else: entry.ringtone='Loud Beeps' else: entry.ringtone=result['ringtone-index'][event.ringtone]['name'] # check for exceptions and remove them if event.repeat[3] and exceptions.has_key(event.pos): for year, month, day in exceptions[event.pos]: entry.suppress_repeat_entry(year, month, day) res[entry.id]=entry assert sc.numactiveitems==len(res) except com_brew.BrewNoSuchFileException: pass # do nothing if file doesn't exist result['calendar']=res return result
def _get_wallpaper_index(self): res={} _files=self.listfiles(self.protocolclass.WP_PATH).keys() _files.sort() for _index,_filename in enumerate(_files): _name=common.basename(_filename) if self.protocolclass.valid_wp_filename(_name): res[_index]={ 'name': _name, 'filename': _filename, 'origin': 'images' } return res
def get_wallpaper_index(self): _res=self._get_builtin_index(self.builtin_pictures) self.setmode(self.MODEBREW) _files=self.listfiles(self.protocolclass.WP_CAMERA_PATH) _idx=self.camera_picture_index for _pathname in _files: _res[_idx]={ 'name': common.basename(_pathname)+'.jpg', 'origin': 'camera' } _idx+=1 self.setmode(self.MODEMODEM) return _res
def scan(filelist, conf=DEFAULTCONF): resultlist = [] tasks = [] if conf['API URL'].endswith('/'): url = conf['API URL'] else: url = conf['API URL'] + '/' new_file_url = url + 'tasks/create/file' report_url = url + 'tasks/report/' view_url = url + 'tasks/view/' delete_url = url + 'tasks/delete/' for fname in filelist: with open(fname, "rb") as sample: multipart_file = {"file": (basename(fname), sample)} payload = {"timeout": conf['timeout']} request = requests.post(new_file_url, files=multipart_file, json=json.dumps(payload)) task_id = request.json()["task_id"] if task_id is not None: tasks.append((fname, str(task_id))) else: #TODO Do something here? pass # Wait for tasks to finish while tasks: for fname, task_id in tasks[:]: status = requests.get(view_url+task_id).json()['task']['status'] # If we have a report if status == 'reported': report = requests.get(report_url+task_id) if report.status_code == 200: report = report.json() resultlist.append((fname, report)) tasks.remove((fname, task_id)) if conf['delete tasks']: requests.get(delete_url+task_id) else: # Do we ever actually hit here? pass # If there is an unknown status elif status not in ['pending', 'processing', 'finished', 'completed', 'running']: print(status) tasks.remove((fname, task_id)) time.sleep(15) metadata = {} metadata["Name"] = NAME metadata["Type"] = TYPE metadata["Include"] = False return (resultlist, metadata)
def getcalendar(self,result): res={} # Read exceptions file first exceptions = self.getexceptions() try: buf = prototypes.buffer(self.getfilecontents(self.calendarringerlocation)) ringersf = self.protocolclass.scheduleringerfile() ringersf.readfrombuffer (buf) except: self.log ("unable to read schedule ringer path file") # Now read schedule try: buf=prototypes.buffer(self.getfilecontents(self.calendarlocation)) if len(buf.getdata())<3: # file is empty, and hence same as non-existent raise com_brew.BrewNoSuchFileException() sc=self.protocolclass.schedulefile() sc.readfrombuffer(buf, logtitle="Calendar") for event in sc.events: # the vx8100 has a bad entry when the calender is empty # stop processing the calender when we hit this record if event.pos==0: #invalid entry continue entry=bpcalendar.CalendarEntry() try: # delete events are still in the calender file but have garbage dates self.getcalendarcommon(entry, event) except ValueError: continue try: if (event.ringtone >= 100): # MIC Ringer is downloaded to phone or microSD entry.ringtone = common.basename(ringersf.ringerpaths[event.ringtone-100].path) else: # MIC Ringer is built-in entry.ringtone=self.builtinringtones[event.ringtone] except: self.log ("Setting default ringer for event\n") # hack, not having a phone makes it hard to figure out the best approach if entry.alarm==None: entry.ringtone='No Ring' else: entry.ringtone='Loud Beeps' # check for exceptions and remove them if event.repeat[3] and exceptions.has_key(event.pos): for year, month, day in exceptions[event.pos]: entry.suppress_repeat_entry(year, month, day) res[entry.id]=entry assert sc.numactiveitems==len(res) except com_brew.BrewNoSuchFileException: pass # do nothing if file doesn't exist result['calendar']=res return result
def _extract_ringtone(self, entry, p_class): if self.pb.has_ringtone and \ self.pb.ringtone: if self.pb.ringtone.startswith('/ff/'): # user's ringtone _ringtone = common.basename(self.pb.ringtone) else: # built-in ringtone _ringtone = self.phone.ringtone_name_from_range( self.pb.ringtone, self.fundamentals) if _ringtone: entry['ringtones'] = [{'ringtone': _ringtone, 'use': 'call'}]
def getwallpaperindices(self, results): # index the list of files in known camera dirs _res={} _idx=1 for _dir in self.wallpaperdirs: for _file in self.listfiles(_dir): _res[_idx]={ 'name': common.basename(_file), 'filename': _file, 'origin': 'images' } _idx+=1 results['wallpaper-index']=_res return results
def _get_wallpaper_index(self): res={} _files=self.listfiles(self.protocolclass.WP_PATH).keys() _files.sort() _wp_path_len=len(self.protocolclass.WP_PATH)+1 for _index,_filename in enumerate(_files): _name=common.basename(_filename) if _name not in self.protocolclass.WP_EXCLUDED_FILES: res[_index]={ 'name': _name, 'filename': _filename, 'origin': 'images' } return res
def getwallpapers(self, fundamentals): """Read camera pictures from the phone""" self.log('Reading Camera Pictures') self.setmode(self.MODEBREW) _files=self.listfiles(self.protocolclass.WP_CAMERA_PATH) _media={} for _pathname in _files: _filename=common.basename(_pathname)+'.jpg' try: _media[_filename]=self.getfilecontents(_pathname, True) except Exception,e: self.log('Failed to read file %s due to: %s'%(_pathname, str(e)))
def _get_dir_index(self, idx, result, pathname, origin, excludenames=()): # build the index list by listing contents of the specified dir for _path in self.listfiles(pathname): _file=common.basename(_path) if _file in excludenames: continue result[idx]={ 'name': _file, 'filename': _path, 'origin': origin, } idx+=1 return idx
def _get_video_index(self, idx, result): # just scan the dir for *.3g2 files _files=self.listfiles(self.protocolclass.FLIX_PATH) for _,_f in _files.items(): _filename=_f['name'] _name=common.basename(_filename) if fnmatch.fnmatch(_name, '*.3g2'): result[idx]= { 'name': _name, 'filename': _filename, 'origin': 'video', } idx+=1 return idx
def _get_dir_index(self, idx, result, pathname, origin, excludenames=()): # build the index list by listing contents of the specified dir for _path in self.listfiles(pathname): _file = common.basename(_path) if _file in excludenames: continue result[idx] = { 'name': _file, 'filename': _path, 'origin': origin, } idx += 1 return idx
def ringtone_name_from_range(self, range, fundamentals): # check for builtin ringtones for _key, _value in self.builtin_ringtones.items(): if range == _value: return _key # check for builtin sounds for _key, _value in self.builtin_sounds.items(): if range == _value: return _key # now check for the "custom" ones # Again, this model does not use ringtone ranges, just filename if range.startswith('/ff/'): return common.basename(range)
def ringtone_name_from_range(self, range, fundamentals): # check for builtin ringtones for _key,_value in self.builtin_ringtones.items(): if range==_value: return _key # check for builtin sounds for _key,_value in self.builtin_sounds.items(): if range==_value: return _key # now check for the "custom" ones # Again, this model does not use ringtone ranges, just filename if range.startswith('/ff/'): return common.basename(range)
def _extract_ringtone(self, entry, p_class): if self.pb.has_ringtone and \ self.pb.ringtone: if self.pb.ringtone.startswith('/ff/'): # user's ringtone _ringtone=common.basename(self.pb.ringtone) else: # built-in ringtone _ringtone=self.phone.ringtone_name_from_range( self.pb.ringtone, self.fundamentals) if _ringtone: entry['ringtones']=[{ 'ringtone': _ringtone, 'use': 'call' }]
def _get_video_index(self, idx, result): # just scan the dir for *.3g2 files _files = self.listfiles(self.protocolclass.FLIX_PATH) for _, _f in _files.items(): _filename = _f['name'] _name = common.basename(_filename) if fnmatch.fnmatch(_name, '*.3g2'): result[idx] = { 'name': _name, 'filename': _filename, 'origin': 'video', } idx += 1 return idx
def _populate_pb_misc(self, pb_entry, pb_sub_entry, key_name, entry, fundamentals): """Populate ringtone, wallpaper to a number, email, or mail list """ _rt_index=fundamentals.get('ringtone-index', {}) _rt_name=_rt_index.get(entry.ringtone, {}).get('name', None) if _rt_name: pb_sub_entry['ringtone']=_rt_name if entry.picture_name: pb_sub_entry['wallpaper']=common.basename(entry.picture_name) if entry.is_primary: pb_entry[key_name]=[pb_sub_entry]+pb_entry.get(key_name, []) else: pb_entry.setdefault(key_name, []).append(pb_sub_entry)
def getwallpaperindices(self, results): # index the list of files in known camera dirs _res = {} _idx = 1 for _dir in self.wallpaperdirs: for _file in self.listfiles(_dir): _res[_idx] = { 'name': common.basename(_file), 'filename': _file, 'origin': 'images' } _idx += 1 results['wallpaper-index'] = _res return results
def OnMediaNameChanged(self, msg): d=msg.data _type=d.get(pubsub.media_change_type, None) _old_name=d.get(pubsub.media_old_name, None) _new_name=d.get(pubsub.media_new_name, None) if _type is None or _old_name is None or _new_name is None: return if _type!=pubsub.wallpaper_type and \ _type!=pubsub.ringtone_type: return _old_name=common.basename(_old_name) _new_name=common.basename(_new_name) if _type==pubsub.wallpaper_type: attr_name='wallpaper' else: attr_name='ringtone' modified=False for k,e in self._data.items(): if getattr(e, attr_name, None)==_old_name: setattr(e, attr_name, _new_name) modified=True if modified: self.updateonchange()
def _submit_sample(fname, scan_url, user_agent, api_key=None): ''' Submits the specified sample file to Metadefender and returns Metadefender's response. Parameters: fname - sample file name scan_url - API URL for scan submission user_agent - Metadefender user agent string Returns: Dictionary in the form: { status_code: <HTTP status code>, scan_id: <scan ID if present> | None, error: <error message if present> | None } ''' with open(fname, "rb") as sample: # TODO - send file in chunks if file size > some threshold. # Due to MD's API, we would have to split the file up manually # and perform several POSTS headers = { 'content-type': 'application/json', 'user_agent': user_agent, 'filename': basename(fname) } if api_key: headers['apikey'] = api_key request = requests.post(scan_url, data=sample, headers=headers) resp_status_code = request.status_code resp_json = None if resp_status_code == requests.codes.ok: resp_json = request.json() scan_id = resp_json.get('data_id', None) error_msg = None else: scan_id = None try: resp_json = request.json() error_msg = resp_json.get( 'err', MD_HTTP_ERR_CODES.get(resp_status_code, UNKNOWN_ERROR)) except (ValueError, AttributeError): error_msg = MD_HTTP_ERR_CODES.get(resp_status_code, UNKNOWN_ERROR) submission_response = { 'status_code': resp_status_code, 'scan_id': scan_id, 'error': error_msg } return submission_response
def _get_info_from_index(self, filename): _res={} try: _buf=prototypes.buffer( self.getfilecontents(filename)) _req=self.protocolclass.indexfile() _req.readfrombuffer(_buf, logtitle='Reading Index File') for _item in _req.items: _res[common.basename(_item.filename)]={ 'size': _item.size, 'filename': _item.filename } except com_brew.BrewNoSuchFileException: pass except: if __debug__: raise return _res
def _update_media_index(self, index_file_class, index_entry_class, media_path, excluded_files, index_file_name): _index_file=index_file_class() _files=self.listfiles(media_path).keys() _files.sort() for _f in _files: _file_name=common.basename(_f) if _file_name in excluded_files: continue _entry=index_entry_class() _entry.name=_file_name _index_file.items.append(_entry) _buf=prototypes.buffer() _index_file.writetobuffer(_buf) self.writefile(index_file_name, _buf.getvalue())
def _get_file_ringtone_index(self, idx, result, index_file_name, index_file_class, origin): _buf=prototypes.buffer(self.getfilecontents(index_file_name)) _index_file=index_file_class() _index_file.readfrombuffer(_buf) for _entry in _index_file.items: if _entry.pathname.startswith('/ff/'): _file_name=_entry.pathname[4:] else: _file_name=_entry.pathname result[idx]= { 'name': common.basename(_entry.pathname), 'filename': _file_name, 'origin': origin, } idx+=1 return idx
def _populate_pb_misc(self, pb_entry, pb_sub_entry, key_name, entry, fundamentals): """Populate ringtone, wallpaper to a number, email, or mail list """ # any ringtones? _rt_index = fundamentals.get("ringtone-index", {}) _rt_name = _rt_index.get(entry.ringtone, {}).get("name", None) if _rt_name: pb_sub_entry["ringtone"] = _rt_name # any wallpaper if entry.picture_name: pb_sub_entry["wallpaper"] = common.basename(entry.picture_name) if entry.is_primary: # primary entry: insert it to the front pb_entry[key_name] = [pb_sub_entry] + pb_entry.get(key_name, []) else: # append it to the end pb_entry.setdefault(key_name, []).append(pb_sub_entry)
def _populate_pb_misc(self, pb_entry, pb_sub_entry, key_name, entry, fundamentals): """Populate ringtone, wallpaper to a number, email, or mail list """ # any ringtones? _rt_index=fundamentals.get('ringtone-index', {}) _rt_name=_rt_index.get(entry.ringtone, {}).get('name', None) if _rt_name: pb_sub_entry['ringtone']=_rt_name # any wallpaper if entry.picture_name: pb_sub_entry['wallpaper']=common.basename(entry.picture_name) if entry.is_primary: # primary entry: insert it to the front pb_entry[key_name]=[pb_sub_entry]+pb_entry.get(key_name, []) else: # append it to the end pb_entry.setdefault(key_name, []).append(pb_sub_entry)
def _get_ringtone_index(self): res={} for _l in self.builtinringtones: _idx=_l[0] for _e in _l[1]: res[_idx]={ 'name': _e, 'origin': 'builtin' } _idx+=1 _buf=prototypes.buffer(self.getfilecontents( self.protocolclass.RT_INDEX_FILE)) _idx_file=self.protocolclass.ringtone_index_file() _idx_file.readfrombuffer(_buf, logtitle='Read ringtone index file') _path_len=len(self.protocolclass.RT_PATH)+1 for _entry in _idx_file.items: _filename=self.decode_utf16(_entry.name) res[_entry.index]={ 'name': common.basename(_filename), 'filename': _filename, 'type': _entry.ringtone_type, 'origin': 'ringers' } return res
def _read_obex_media(self, index_key, media_key, media_path, fundamentals): # read media files through OBEX in case BREW fails # need to be in OBEX mode _media=fundamentals.get(media_key, {}) _dir_list=fundamentals.get(media_path, {}) for _key,_entry in fundamentals.get(index_key, {}).items(): if _entry.get('filename', None) and \ not _media.has_key(_entry['name']): # this one associates with a file AND has not been read try: _filename=media_path+'/'+common.basename(_entry['filename']) _filesize=_dir_list.get(_entry['filename'], {}).get('size', None) _media[_entry['name']]=self.obex.getfilecontents(_filename, _filesize) except: self.log('Failed to read media file.') if __debug__: raise return _media
def _get_ringtone_index(self): res={} # first the builtin ones for _l in self.builtinringtones: _idx=_l[0] for _e in _l[1]: res[_idx]={ 'name': _e, 'origin': 'builtin' } _idx+=1 # now the custome one _buf=prototypes.buffer(self.getfilecontents( self.protocolclass.RT_INDEX_FILE)) _idx_file=self.protocolclass.ringtone_index_file() _idx_file.readfrombuffer(_buf, logtitle='Read ringtone index file') for _entry in _idx_file.items: _filename=self.decode_utf16(_entry.name) res[_entry.index]={ 'name': common.basename(_filename), 'filename': _filename, 'type': _entry.ringtone_type, 'origin': 'ringers' } return res
def OnAddFiles(self, filenames): for file in filenames: if file is None: continue # failed dragdrop? file_stat=os.stat(file) mtime=file_stat.st_mtime if self._raw_media: target=self.get_media_name_from_filename(file) data=open(file, 'rb').read() self.AddToIndex(target, self.active_section, data, self._data, mtime) else: # do we want to convert file? afi=fileinfo.identify_audiofile(file) if afi.size<=0: continue # zero length file or other issues newext,convertinfo=self.mainwindow.phoneprofile.QueryAudio(None, common.getext(file), afi) if convertinfo is not afi: filedata=None wx.EndBusyCursor() try: filedata=self.ConvertFormat(file, convertinfo) finally: # ensure they match up wx.BeginBusyCursor() if filedata is None: continue else: filedata=open(file, "rb").read() # check for the size limit on the file, if specified max_size=getattr(convertinfo, 'MAXSIZE', None) if max_size is not None and len(filedata)>max_size: # the data is too big self.log('ringtone %s is too big!'%common.basename(file)) with guihelper.WXDialogWrapper(wx.MessageDialog(self, 'Ringtone %s may be too big. Do you want to proceed anway?'%common.basename(file), 'Warning', style=wx.YES_NO|wx.ICON_ERROR), True) as (dlg, dlg_resp): if dlg_resp==wx.ID_NO: continue target=self.get_media_name_from_filename(file, newext) self.AddToIndex(target, self.active_section, filedata, self._data, mtime) self.OnRefresh()
def scan(filelist, conf=DEFAULTCONF): resultlist = [] tasks = [] api_url = normalize_url(conf['API URL']) web_url = normalize_url(conf['WEB URL']) new_file_url = api_url + 'tasks/create/file' report_url = api_url + 'tasks/report/' view_url = api_url + 'tasks/view/' delete_url = api_url + 'tasks/delete/' maec_report_url = '<a href="' + api_url + '/v1/tasks/report/{task_id}/maec" target="_blank"' + '>View the Cuckoo MAEC report</a>' web_report_url = '<a href="' + web_url + 'analysis/{task_id}/summary/" target="_blank"' + '>View the report in Cuckoo</a>' for fname in filelist: with open(fname, "rb") as sample: multipart_file = {"file": (basename(fname), sample)} payload = {"timeout": conf['timeout']} request = requests.post(new_file_url, files=multipart_file, json=json.dumps(payload)) task_id = request.json()["task_id"] if task_id is not None: tasks.append((fname, str(task_id))) else: #TODO Do something here? pass # Wait for tasks to finish task_status = {} while tasks: for fname, task_id in tasks[:]: status = requests.get(view_url+task_id).json()['task']['status'] # TODO - if we don't find a report, should we add (fname, {}) or # just skip fname? # If we have a report if status == 'reported': report = fetch_report_json(report_url+task_id) if conf['maec']: report['info']['maec report'] = maec_report_url.format(task_id=task_id) # maec_report = fetch_report_json( # maec_report_url.format(task_id=task_id)) # report['maec'] = maec_report # TODO - should we just modify Cuckoo to add this itself? if report.get('info'): report['info']['web_report'] = web_report_url.format( task_id=task_id) resultlist.append((fname, report)) tasks.remove((fname, task_id)) if conf['delete tasks']: requests.get(delete_url+task_id) # Check for dead tasks elif status == 'running': if task_id not in task_status: task_status[task_id] = time.time() + conf['timeout'] + conf['running timeout'] else: if time.time() > task_status[task_id]: #TODO Log timeout tasks.remove((fname, task_id)) # If there is an unknown status elif status not in ['pending', 'processing', 'finished', 'completed', 'running']: #TODO Log errors better tasks.remove((fname, task_id)) time.sleep(15) metadata = {} metadata["Name"] = NAME metadata["Type"] = TYPE metadata["Include"] = False return (resultlist, metadata)
def multiscan(Files, recursive=False, configregen=False, configfile=CONFIG, config=None, module_list=None): """ The meat and potatoes. Returns the list of module results Files - A list of files and dirs to be scanned recursive - If true it will search the dirs in Files recursively configregen - If True a new config file will be created overwriting the old configfile - What config file to use. Can be None. config - A dictionary containing the configuration options to be used. """ # Redirect stdout to stderr stdout = sys.stdout sys.stdout = sys.stderr # TODO: Make sure the cleanup from this works is something breaks # Init some vars # If recursive is None we don't parse the file list and take it as is. if recursive is not None: filelist = parseFileList(Files, recursive=recursive) else: filelist = Files # A list of files in the module dir if module_list is None: module_list = parseDir(MODULEDIR, recursive=True) # A dictionary used for the copyfileto parameter filedic = {} # What will be the config file object config_object = None # Read in config if configfile: config_object = configparser.SafeConfigParser() config_object.optionxform = str # Regen the config if needed or wanted if configregen or not os.path.isfile(configfile): _rewrite_config(module_list, config_object, filepath=configfile) config_object.read(configfile) main_config = _get_main_config(config_object, filepath=configfile) if config: file_conf = parse_config(config_object) for key in config: if key not in file_conf: file_conf[key] = config[key] file_conf[key]['_load_default'] = True else: file_conf[key].update(config[key]) config = file_conf else: config = parse_config(config_object) else: if config is None: config = {} else: config['_load_default'] = True if 'main' in config: main_config = config['main'] else: main_config = DEFAULTCONF # If none of the files existed if not filelist: sys.stdout = stdout raise ValueError("No valid files") # Copy files to a share if configured if "copyfilesto" not in main_config: main_config["copyfilesto"] = False if main_config["copyfilesto"]: if os.path.isdir(main_config["copyfilesto"]): filelist = _copy_to_share(filelist, filedic, main_config["copyfilesto"]) else: sys.stdout = stdout raise IOError('The copyfilesto dir" ' + main_config["copyfilesto"] + '" is not a valid dir') # Create the global module interface global_module_interface = _GlobalModuleInterface() # Start a thread for each module thread_list = _start_module_threads(filelist, module_list, config, global_module_interface) # Write the default configure settings for missing ones if config_object: _write_missing_module_configs(module_list, config_object, filepath=configfile) # Warn about spaces in file names for f in filelist: if ' ' in f: print( 'WARNING: You are using file paths with spaces. This may result in modules not reporting correctly.' ) break # Wait for all threads to finish thread_wait_list = thread_list[:] i = 0 while thread_wait_list: i += 1 for thread in thread_wait_list: if not thread.is_alive(): i = 0 thread_wait_list.remove(thread) if VERBOSE: print(thread.name, "took", thread.endtime - thread.starttime) if i == 15: i = 0 if VERBOSE: p = 'Waiting on' for thread in thread_wait_list: p += ' ' + thread.name p += '...' print(p) time.sleep(1) # Delete copied files if main_config["copyfilesto"]: for item in filelist: try: os.remove(item) except OSError: pass # Get Result list results = [] for thread in thread_list: if thread.ret is not None: results.append(thread.ret) del thread # Translates file names back to the originals if filedic: # I have no idea if this is the best way to do in-place modifications for i in range(0, len(results)): (result, metadata) = results[i] modded = False for j in range(0, len(result)): (filename, hit) = result[j] base = basename(filename) if base in filedic: filename = filedic[base] modded = True result[j] = (filename, hit) if modded: results[i] = (result, metadata) # Scan subfiles if needed subscan_list = global_module_interface._get_subscan_list() if subscan_list: # Translate from_filename back to original if needed if filedic: for i in range(0, len(subscan_list)): file_path, from_filename, module_name = subscan_list[i] base = basename(from_filename) if base in filedic: from_filename = filedic[base] subscan_list[i] = (file_path, from_filename, module_name) results.extend( _subscan(subscan_list, config, main_config, module_list, global_module_interface)) global_module_interface._cleanup() # Return stdout to previous state sys.stdout = stdout return results
def _subscan(subscan_list, config, main_config, module_list, global_module_interface): """ Scans files created by modules subscan_list - The result of _get_subscan_list() from the global module interface config - The configuration dictionary main_config - A dictionary of the configuration for main module_list - The list of modules global_module_interface - The global module interface """ # The file list to be scanned filelist = [] # Keeps mapping of files when they are copied to a share filedic = {} # Maps the subfile to its parent file_mapping = {} # The result list to be returned results = [] # The results to map children to their parent parent_results = [] # Used to map parents to their children subfiles_dict = {} # The results to map parents to their children subfiles_results = [] # The results to show which module created the file createdby_results = [] for file_path, from_filename, module_name in subscan_list: # Add each file to be scanned filelist.append(file_path) # Map file_path to the filename that will be used in the results new_filename = os.path.join(from_filename, basename(file_path)) file_mapping[file_path] = (from_filename, new_filename) # Map the child file to its parent parent_results.append((new_filename, from_filename)) # Map parent files to their children if from_filename not in subfiles_dict: subfiles_dict[from_filename] = [] subfiles_dict[from_filename].append(new_filename) # Add createdby result createdby_results.append((new_filename, module_name)) # Create the results for parent files for parent_file in subfiles_dict: subfiles_results.append((parent_file, subfiles_dict[parent_file])) # Emulate a module for so the parent child relationships are in the reports results.append((parent_results, { 'Name': 'Parent', 'Type': 'subscan', 'Include': False })) results.append((subfiles_results, { 'Name': 'Children', 'Type': 'subscan', 'Include': False })) results.append((createdby_results, { 'Name': 'Created by', 'Type': 'subscan', 'Include': False })) del subscan_list, subfiles_dict # Copy files to a share if configured if "copyfilesto" not in main_config: main_config["copyfilesto"] = False if main_config["copyfilesto"]: filelist = _copy_to_share(filelist, filedic, main_config["copyfilesto"]) # Start a thread for each module thread_list = _start_module_threads(filelist, module_list, config, global_module_interface) # Wait for all threads to finish thread_wait_list = thread_list[:] i = 0 while thread_wait_list: i += 1 for thread in thread_wait_list: if not thread.is_alive(): i = 0 thread_wait_list.remove(thread) if VERBOSE: print(thread.name, "took", thread.endtime - thread.starttime) if i == 15: i = 0 if VERBOSE: p = 'Waiting on' for thread in thread_wait_list: p += ' ' + thread.name p += '...' print(p) time.sleep(1) # Delete copied files if main_config["copyfilesto"]: for item in filelist: os.remove(item) # Get Result list for thread in thread_list: if thread.ret is not None: results.append(thread.ret) del thread # I have no idea if this is the best way to do in-place modifications for i in range(0, len(results)): (result, metadata) = results[i] for j in range(0, len(result)): (filename, hit) = result[j] base = basename(filename) # Convert filename back if copied if base in filedic: filename = filedic[base] base = basename(filename) # Change filename to represent original file if filename in file_mapping: from_filename, new_filename = file_mapping[filename] result[j] = (new_filename, hit) results[i] = (result, metadata) # Scan subfiles if needed subscan_list = global_module_interface._get_subscan_list() if subscan_list: for i in range(0, len(subscan_list)): file_path, from_filename, module_name = subscan_list[i] base = basename(from_filename) # Translate from_filename back to original if needed if base in filedic: from_filename = filedic[base] if from_filename in file_mapping: null, from_filename = file_mapping[from_filename] subscan_list[i] = (file_path, from_filename, module_name) results.extend( _subscan(subscan_list, config, main_config, module_list, global_module_interface)) return results
def _run_module(modname, mod, filelist, threadDict, global_module_interface, conf=None): """ Runs a module on a file list. Modules are loaded and check is called followed by scan. modname - The name of the module mod - The imported module filelist - The list of files on the host to be scanned threadDict - A dictionary of all threads. {modname: Thread} global_module_interface - The global module interface to be injected in each module conf - The config to be passed to the module. If None it will try to use the default conf """ mod.multiscanner = _ModuleInterface(modname, global_module_interface) mod.print = print if not conf: try: conf = mod.DEFAULTCONF except: pass required = None if hasattr(mod, "REQUIRES"): required = mod.REQUIRES if not isinstance(required, list): required = [] # If the module has requirements if required: # Give the modules a chance to all start reqresults = [] for reqmodname in required: if reqmodname in threadDict: # Wait for module to start while not threadDict[reqmodname].started: time.sleep(5) # Wait for required modules to finish threadDict[reqmodname].join() # Append results to a list reqresults.append(threadDict[reqmodname].ret) else: # If no module of that name, append None reqresults.append(None) # Overwrite REQUIRES var mod.REQUIRES = reqresults threadDict[modname].starttime = time.time() if conf: if mod.check(conf=conf) is True: # If replacement path is set change the file list filedict = {} if "replacement path" in conf: # Copy filelist so we don't break the other modules filelist = filelist[:] for i in range(0, len(filelist)): # For windows replacement paths oldname = filelist[i] if re.match("[a-zA-Z]:\\\\", conf["replacement path"]): if conf["replacement path"].endswith("\\"): filelist[i] = conf["replacement path"] + basename( filelist[i]) else: filelist[i] = conf[ "replacement path"] + "\\" + basename( filelist[i]) # For linux replacement paths else: if conf["replacement path"].endswith("/"): filelist[i] = conf["replacement path"] + basename( filelist[i]) else: filelist[ i] = conf["replacement path"] + "/" + basename( filelist[i]) filedict[filelist[i]] = oldname # Replace the paths on required modules if any if required: for mresult in reqresults: if mresult is None: continue (result, metadata) = mresult for j in range(0, len(result)): (filename, hit) = result[j] # For windows replacement paths if re.match("[a-zA-Z]:\\\\", conf["replacement path"]): if conf["replacement path"].endswith("\\"): filename = conf[ "replacement path"] + basename( filename) else: filename = conf[ "replacement path"] + "\\" + basename( filename) # For linux replacement paths else: if conf["replacement path"].endswith("/"): filename = conf[ "replacement path"] + basename( filename) else: filename = conf[ "replacement path"] + "/" + basename( filename) result[j] = (filename, hit) mod.REQUIRES = reqresults # Run the scan results = mod.scan(filelist, conf=conf) # If filenames were replaced, change them back if filedict and results: (result, metadata) = results modded = False for j in range(0, len(result)): (filename, hit) = result[j] if filename in filedict: filename = filedict[filename] modded = True result[j] = (filename, hit) if modded: results = (result, metadata) return results elif VERBOSE: print(modname, "failed check(conf)") else: if mod.check() is True: return mod.scan(filelist) elif VERBOSE: print(modname, "failed check()")