--- a/PSKManagement.py Tue Nov 20 11:32:42 2018 +0100
+++ b/PSKManagement.py Wed Nov 21 14:10:51 2018 +0100
@@ -7,7 +7,10 @@
+from zipfile import ZipFile +# PSK Management Data model : +# [[ID,Desc, LastKnownURI, LastConnect]] COL_ID,COL_URI,COL_DESC,COL_LAST = range(4)
def _pskpath(project_path):
@@ -16,51 +19,52 @@
def _mgtpath(project_path):
return os.path.join(_pskpath(project_path), 'management.json')
- return ['', # default description
+ '', # default description None] # last connection date
+ return {row[COL_ID]:row for row in data} def _LoadData(project_path):
+ """ load known keys metadata """ if os.path.isdir(_pskpath(project_path)):
_path = _mgtpath(project_path)
- # load known keys metadata
- # {ID:(Desc, LastKnownURI, LastConnect)}
- return json.loads(open(_path).read()) \
- if os.path.exists(_path) else {}
+ if os.path.exists(_path): + return json.loads(open(_path).read()) -def GetData(project_path):
- # [(ID, Desc, LastKnownURI, LastConnect)
- loaded_data = _LoadData(project_path)
+def _filterData(psk_files, data_input): + input_by_ID = _dataByID(data_input) # go through all secret files available an build data
# out of data recoverd from json and list of secret.
# this implicitly filters IDs out of metadata who's
- psk_files = os.listdir(_pskpath(project_path))
for filename in psk_files:
if filename.endswith('.secret'):
ID = filename[:-7] # strip filename extension
- meta = loaded_data.get(ID,_default())
+ output.append(input_by_ID.get(ID,_default(ID))) +def GetData(project_path): + loaded_data = _LoadData(project_path) + psk_files = os.listdir(_pskpath(project_path)) + return _filterData(psk_files, loaded_data) def DeleteID(project_path, ID):
secret_path = os.path.join(_pskpath(project_path), ID+'.secret')
-def _StoreData(project_path, data):
+def SaveData(project_path, data): pskpath = _pskpath(project_path)
if not os.path.isdir(pskpath):
with open(_mgtpath(project_path), 'w') as f:
f.write(json.dumps(data))
-def SaveData(project_path, data):
- to_store = {row[0]:row[1:] for row in data}
- _StoreData(project_path, to_store)
def UpdateID(project_path, ID, secret, URI):
pskpath = _pskpath(project_path)
@@ -71,11 +75,49 @@
with open(secpath, 'w') as f:
+ # here we directly use _LoadData, avoiding filtering that could be long data = _LoadData(project_path)
- dataForID = [ID] + (data.get(ID, _default()) if data else _default())
+ idata = _dataByID(data) + dataForID = idata.get(ID, _default(ID)) if data else _default(ID) # FIXME : could store time instead os a string and use DVC model's cmp
# then date display could be smarter, etc - sortable sting hack for now
dataForID[COL_LAST] = time.strftime('%y/%M/%d-%H:%M:%S')
- data[ID] = dataForID[1:]
- _StoreData(project_path, data)
+ SaveData(project_path, data) +def ExportIDs(project_path, export_zip): + with ZipFile(export_zip, 'w') as zf: + path = _pskpath(project_path) + for nm in os.listdir(path): + if nm.endswith('.secret') or nm == 'management.json': + zf.write(os.path.join(path, nm), nm) +def ImportIDs(project_path, import_zip, should_I_replace_callback): + data = GetData(project_path) + zip_loaded_data = json.loads(zf.open('management.json').read()) + name_list = zf.namelist() + zip_filtered_data = _filterData(name_list, loaded_data) + idata = _dataByID(data) + for imported_row in zip_filtered_data: + ID = imported_row[COL_ID] + existing_row = idata.get(ID, None) + if existing_row is None: + data.append(imported_row) + # callback returns the selected list for merge or none if canceled + result = should_I_replace_callback(existing_row, imported_row) + # replace with imported + existing_row[:] = imported_row + # copy the key of selected + self.extract(ID+".secret", _pskpath(project_path)) + SaveData(project_path, data) --- a/controls/IDBrowser.py Tue Nov 20 11:32:42 2018 +0100
+++ b/controls/IDBrowser.py Wed Nov 21 14:10:51 2018 +0100
@@ -11,14 +11,14 @@
from PSKManagement import COL_ID,COL_URI,COL_DESC,COL_LAST
class IDBrowserModel(dv.PyDataViewIndexListModel):
- def __init__(self, psk_path, columncount):
- self.psk_path = psk_path
+ def __init__(self, project_path, columncount): + self.project_path = project_path self.columncount = columncount
- self.data = PSK.GetData(psk_path)
+ self.data = PSK.GetData(project_path) dv.PyDataViewIndexListModel.__init__(self, len(self.data))
- PSK.SaveData(self.psk_path, self.data)
+ PSK.SaveData(self.project_path, self.data) def GetColumnType(self, col):
@@ -59,7 +59,7 @@
- PSK.DeleteID(self.psk_path, self.data[row][COL_ID])
+ PSK.DeleteID(self.project_path, self.data[row][COL_ID]) @@ -69,13 +69,20 @@
+ def Import(self, filepath, sircb): + PSK.ImportIDs(self.project_path, filepath, sircb) + def Export(self, filepath): + PSK.ExportIDs(self.project_path, filepath) colflags = dv.DATAVIEW_COL_RESIZABLE|dv.DATAVIEW_COL_SORTABLE
class IDBrowser(wx.Panel):
def __init__(self, parent, ctr, SelectURICallBack=None, SelectIDCallBack=None, **kwargs):
- wx.Panel.__init__(self, parent, -1, size=(400,200))
+ big = self.isManager = SelectURICallBack is None and SelectIDCallBack is None + wx.Panel.__init__(self, parent, -1, size=(800 if big else 400, - self.isManager = SelectURICallBack is None and SelectIDCallBack is None
self.SelectURICallBack = SelectURICallBack
self.SelectIDCallBack = SelectIDCallBack
@@ -89,12 +96,12 @@
args(_("ID"), COL_ID, width = 100),
- args(_("Last URI"), COL_URI, width = 80),
+ args(_("Last URI"), COL_URI, width = 160 if big else 80), args(_("Description"), COL_DESC, width = 200,
mode = dv.DATAVIEW_CELL_EDITABLE
else dv.DATAVIEW_CELL_INERT),
- args(_("Last connection"), COL_LAST, width = 100),
+ args(_("Last connection"), COL_LAST, width = 120), self.model = IDBrowserModel(ctr.ProjectPath, len(ColumnsDesc))
@@ -171,14 +178,22 @@
self.SelectURICallBack(URI)
def OnExportButton(self, evt):
- wx.YES_NO | wx.CENTRE | wx.NO_DEFAULT)
+ dialog = wx.FileDialog(self, _("Choose a file"), + wildcard = _("PSK ZIP files (*.zip)|*.zip"), + style = wx.SAVE | wx.OVERWRITE_PROMPT) + if dialog.ShowModal() == wx.ID_OK: + self.model.Export(dialog.GetPath()) + def ShouldIReplaceCallback(self,some,stuff): + wx.MessageBox("TODO : ShouldIReplaceCallback") def OnImportButton(self, evt):
- wx.YES_NO | wx.CENTRE | wx.NO_DEFAULT)
+ dialog = wx.FileDialog(self, _("Choose a file"), + wildcard = _("PSK ZIP files (*.zip)|*.zip"), + style = wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) + if dialog.ShowModal() == wx.ID_OK: + self.model.Import(dialog.GetPath(), + self.ShouldIReplaceCallback)