Fixed stuff.
[FinalKeyGui.git] / src / fkgui / FkManager.java
1 package fkgui;
2
3 import java.awt.event.ActionEvent;
4 import java.awt.event.ActionListener;
5 import java.util.Collections;
6 import java.util.Comparator;
7 import java.util.Vector;
8
9 import jssc.SerialPort;
10
11 import org.eclipse.swt.widgets.Display;
12
13 import fkgui.FkActionEventListener.FkActionEvent;
14 import fkgui.FkActionEventListener.FkActionEventType;
15
16 public class FkManager implements ActionListener {
17         private static FkManager instance = null;
18         private SerialWorker com = null;
19         static final char ENTER_KEY = (char)13;
20         static final char PAUSE_CODE = (char)23; 
21         static final char SPACE_KEY = (char)32;
22         private Comparator<Account> sortMethod = null;
23         
24         public class Account
25         {
26                 public String name;
27                 public String num;
28                 private Boolean showNumInName;
29                 public Account( String acNum, String acName )
30                 {
31                         name = acName;
32                         num = acNum;
33                 }
34
35                 //Used by the ListView
36                 public String toString()
37                 {
38                         if( showNumInName )
39                         {
40                                 return( "["+num+"] "+name);
41                         }
42                         return(name);
43                 }
44
45                 public Account showNumInName(Boolean showAccountId) {
46                         showNumInName=showAccountId;
47                         return this;
48                 }
49         }
50                 
51         private Vector<Account> list;
52         
53         protected FkManager()
54         {
55                 list = new Vector<Account>(256);
56         }
57         
58         public static FkManager getInstance()
59         {
60                 if( instance == null )
61                 {
62                         instance = new FkManager();
63                 }
64
65                 return( instance );
66         }
67         
68         public void setWorker( SerialWorker sw )
69         {
70                 com = sw;
71         }
72         
73
74         private class FkActionEventMsg implements Runnable  {
75                 private FkActionEventListener delegate;
76                 private FkActionEvent event;
77
78                 private FkActionEventMsg(FkActionEventListener d, FkActionEventType t, String data, Account acc, char act )
79                 {
80                         delegate=d;
81                         event=new FkActionEvent(t, data, acc,act) ;
82                 }
83                 @Override
84                 public void run() {
85                         if( delegate != null )
86                         {
87                                 delegate.fkActionEvent(event);
88                         }
89                 }
90         }
91         
92         
93         private Boolean checkState()
94         {
95
96                 int t=0;
97                 String msg="";
98                 Boolean stateOk=false;
99
100                 try {
101                         com.serialPort.writeByte((byte)SPACE_KEY);
102                         while( t < 100 )
103                         {
104                                 t++;
105                                 Thread.sleep(5);
106                                 
107                                 if( com.serialPort.getInputBufferBytesCount() > 0 )
108                                 {
109                                         msg += com.serialPort.readString();
110                                         if( msg.endsWith("\r\n>") )
111                                         {
112                                                 stateOk=true;
113                                                 msg="";
114                                                 break;
115                                         }
116                                 }
117                                 
118                         }
119                 
120                 } catch(Exception e)
121                 {
122                         stateOk=false;
123                 }
124                 flushSerial();
125                 if( !stateOk )
126                 {
127                         return(false);
128                 }
129                 return(true);
130                 
131         }
132         
133         private class TrigTask implements Runnable
134         {
135                 private Account acc;
136                 private char action;
137                 private FkActionEventListener delegate;
138                 public TrigTask(Account ac, char act, FkActionEventListener d )
139                 {
140                         acc=ac;
141                         action=act;
142                         delegate=d;
143                 }
144                 
145                 @Override
146                 public void run() {
147                         
148                         int t=0;
149                         String msg = "";
150
151
152                         try {
153                         
154                                 //First check that we get a prompt
155                                 if( !checkState() )
156                                 {
157                                         Display.getDefault().asyncExec( new FkActionEventMsg(delegate, FkActionEventListener.FkActionEventType.STATE_ERROR, "EXCEPTION",acc,action) );
158                                         return;
159                                 }
160
161                                 //if it's not '%' we need to type which action.
162                                 if(action != '%' )
163                                 {
164         
165                                                 //If the action is to delete or override, we start by deleting the account number.
166                                                 //Those commands are xd or xo so we type an x before the action.
167                                                 if( action == 'd' || action == 'o' )
168                                                 {
169                                                         com.serialPort.writeByte((byte)'x');
170                                                 }
171                                                 com.serialPort.writeByte((byte)action);
172         
173                                 }
174                         
175                                 com.serialPort.writeBytes(acc.num.toLowerCase().getBytes());
176                 
177                                 if( action == 'd' || action == 'o' )
178                                 {
179                                         com.serialPort.writeByte((byte)'y');
180                                 }                               
181                                 
182                                 Thread.sleep(200);
183
184                                 
185                                 t=0;
186                                 while( t < 1200 )
187                                 {
188                                         t++;
189                                         Thread.sleep(50);
190                                         if( com.serialPort.getInputBufferBytesCount() > 0 )
191                                         {
192                                                 msg += com.serialPort.readString();
193                                                 //System.out.println( msg );
194                                                 if( msg.contains("[done]") || msg.contains("[deleted]") )
195                                                 {
196                                                         if( action == 'd' )
197                                                         {
198                                                                 list.remove( acc );
199                                                         }
200                                                         Display.getDefault().asyncExec( new FkActionEventMsg(delegate, FkActionEventListener.FkActionEventType.ACTION_OKAY, msg, acc, action) );
201                                                         return;
202                                                 } else if( msg.contains("[abort]") )
203                                                 {
204                                                         //System.out.println("FkManager: Action Abort");;
205                                                         Display.getDefault().asyncExec( new FkActionEventMsg(delegate, FkActionEventListener.FkActionEventType.ACTION_ABORTED, msg,acc,action) );
206                                                         return;
207                                                 }
208                                         }
209                                 }
210                                 Display.getDefault().asyncExec( new FkActionEventMsg(delegate, FkActionEventListener.FkActionEventType.ACTION_ERROR, msg,acc,action) );
211
212                         } catch (Exception e1) {
213                                 System.out.println("TrigTask Exception:");
214                                 e1.printStackTrace();
215                                 Display.getDefault().asyncExec( new FkActionEventMsg(delegate, FkActionEventListener.FkActionEventType.ACTION_ERROR, "EXCEPTION",acc,action) );
216                         }
217                         
218                 }
219                 
220         }
221         
222         public void trig(Account acc, char action, FkActionEventListener delegate)
223         {
224                 TrigTask trigTask = new TrigTask(acc,action,delegate);
225                 new Thread(trigTask).start();
226         }
227         
228         
229         
230         private class SortByName implements Comparator<Account>
231         {
232                 @Override
233                 public int compare(Account o1, Account o2) {
234                         return o1.name.compareTo(o2.name);
235                 }
236         }
237         
238         private class SortById implements Comparator<Account>
239         {
240                 @Override
241                 public int compare(Account o1, Account o2) {
242                         int a = Integer.valueOf(o1.num, 16);
243                         int b = Integer.valueOf(o2.num, 16);
244                         return( a - b );
245                 }
246         }
247         
248         
249         
250         public void listAddAcc(String num, String name)
251         {
252                 list.addElement( new Account(num,name) );
253                 
254                 Collections.sort(list, sortMethod);
255         }
256         
257         public void listClear()
258         {
259                 list.clear();
260         }
261         
262         //Return the full list
263         public Vector<Account> getList()
264         {
265                 return(list);
266         }
267         
268         //Return a vector of accounts matching the keyword
269         public Vector<Account> getList(String key)
270         {
271                 Vector<Account> res = new Vector<Account>();
272                 String k = key.toLowerCase();
273                 for( Account a : list )
274                 {
275                         if( a.name.toLowerCase().contains( k ) ) 
276                         {
277                                 res.add(a);
278                         }
279                 }
280                 
281                 return(res);
282         }
283         
284         public void getCurrentLayout()
285         {
286                 
287         }
288         
289         public void getAvailableLayouts()
290         {
291                 
292         }
293         
294         public void setLayout(int num)
295         {
296                 
297         }
298
299         @Override
300         public void actionPerformed(ActionEvent e) {
301                 Account f=null;
302                 for( Account a : list )
303                 {
304                         if( a.num.compareTo( e.getActionCommand().substring(1, 3)) == 0 )
305                         {
306                                 f=a;
307                                 break;
308                         }
309                 }
310                 if(f!=null)
311                 {
312                         trig(f, e.getActionCommand().charAt(0), null);
313                 }
314                 
315         }
316
317         public void setCurrentLayout(String str) {
318                 System.out.println("FkManager: Got current layout:" + str );
319                 
320         }
321         
322         private class NewAccountTask implements Runnable
323         {
324                 private String seq;
325                 private Account acc;
326                 FkActionEventListener delegate;
327                 public NewAccountTask(String sequence, FkActionEventListener d, String accountName)
328                 {
329                         seq=sequence;
330                         delegate=d;
331                         acc = new Account( "00", accountName );
332                         System.out.println("NewAccountTask ctor");
333                 }
334                 @Override
335                 public void run() {
336                         System.out.println("NewAccountTask run");
337                         Boolean noTimeOut = false;
338
339                         //First check that we get a prompt
340                         if( !checkState() )
341                         {
342                                 Display.getDefault().asyncExec( new FkActionEventMsg(delegate, FkActionEventListener.FkActionEventType.STATE_ERROR, "EXCEPTION",acc,'A') );
343                                 return;
344                         }
345                         
346                         String data="";
347                         int timeOut;
348                         try {                   
349                         //First type x a and wait for account title
350                                 
351                                 com.serialPort.writeByte((byte)'x');
352                                 com.serialPort.writeByte((byte)'a');
353                                 Display.getDefault().asyncExec( new FkActionEventMsg(delegate, FkActionEventListener.FkActionEventType.ACTION_WAITING, "WAITING",acc,'A') );
354
355                                 timeOut = 6000;
356                                 while(timeOut > 0)
357                                 {
358                                         if( com.serialPort.getInputBufferBytesCount() > 0 )
359                                         {
360                                                 String in = com.serialPort.readString(); 
361                                                 data += in;
362                                                 System.out.println("Datain:" +in);
363                                                 if( data.contains("Account Title, (0-31):") )
364                                                 {
365                                                         System.out.println("Found");
366                                                         break;
367                                                 }
368                                         } else {
369                                                 timeOut -= 50;
370                                                 Thread.sleep(50);
371                                         }
372                                 }
373                                 
374                                 if(timeOut > 0 )
375                                 {
376                                         Display.getDefault().asyncExec( new FkActionEventMsg(delegate, FkActionEventListener.FkActionEventType.ACTION_WORKING, "WORKING",acc,'A') );
377
378                                         for(int p=0; p < seq.length();p++)
379                                         {
380
381                                                 if( com.serialPort.getOutputBufferBytesCount() > 1 )
382                                                 {
383                                                         Thread.sleep(100);
384                                                         System.out.println("[SLEEP]");
385                                                 } else {
386                                                         if( seq.charAt(p) == PAUSE_CODE)
387                                                         {
388                                                                 Thread.sleep(100);
389                                                                 System.out.println("[DELAY]");
390                                                         } else {
391                                                                 if( seq.charAt(p) == ENTER_KEY )
392                                                                 {
393                                                                         System.out.println( "[ENTER]" );
394                                                                 } else {
395                                                                         System.out.println( "Type from pos ("+p+"):" + seq.charAt(p));
396                                                                 }
397         
398                                                                 com.serialPort.writeByte( (byte)seq.charAt(p) );
399                                                                 Thread.sleep(5);
400                                                         }
401                                                         
402                                                 }
403                                                 
404                                                 if(  com.serialPort.getInputBufferBytesCount() > 0 )
405                                                 {
406                                                         System.out.print("Reading "+com.serialPort.getInputBufferBytesCount()+ " bytes: ");
407                                                         data="";
408                                                         while( com.serialPort.getInputBufferBytesCount() > 0 )
409                                                         {
410                                                                 String in = com.serialPort.readString();
411                                                                 data += in;
412                                                                 
413                                                         }
414                                                         if( data.contains("[generate]") )
415                                                         {
416                                                                 noTimeOut=true;
417                                                                 System.out.println("1: noTimeOut");
418                                                         }                                                       
419                                                         System.out.println(data);
420                                                 }
421                                         }//While typing
422                                         System.out.println("All chars typed, waiting for [save entry ");
423                                         
424                                         int step=0;
425                                         
426                                         timeOut = 30000;
427                                         while( timeOut > 0 || noTimeOut )
428                                         {
429                                                 
430                                                 if( com.serialPort.getInputBufferBytesCount() > 0 )
431                                                 {
432                                                         String in = com.serialPort.readString();
433                                                         //System.out.println("Read>"+in);
434                                                         data += in;
435                                                         System.out.println("Data:"+data);
436                                                         
437                                                         //Check for abort first, in that case, we don't want to do anything.
438                                                         if( data.contains("[abort]") )
439                                                         {
440                                                                 Display.getDefault().asyncExec( new FkActionEventMsg(delegate, FkActionEventListener.FkActionEventType.ACTION_ABORTED, "ERROR:"+data,null,'A') );
441                                                                 return;
442                                                         }
443                                                         
444                                                         //If we're generating a password, we don't want to timeout
445                                                         if( data.contains("[generate]") )
446                                                         {
447                                                                 noTimeOut=true;
448                                                                 System.out.println("2: noTimeOut");
449                                                                 
450                                                         }
451                                                         
452                                                         //If we're at step0 and have the saveentry string and there's a ] after it, we're good to fetch the account number.
453                                                         if( step==0 && data.contains("[save entry ") && (data.lastIndexOf(']') > data.lastIndexOf("[save entry ")) )
454                                                         {
455                                                                 int begin = data.lastIndexOf("[save entry ")+12;
456                                                                 String subStr = data.substring(begin);
457                                                                 int end = subStr.indexOf(']');
458                                                                 subStr = subStr.substring(0,end);
459                                                                 if( subStr.length()==1)
460                                                                 {
461                                                                         subStr = "0"+subStr;
462                                                                 }
463                                                                 acc.num = subStr;
464                                                                 listAddAcc( acc.num, acc.name);
465                                                                 System.out.println("Account: "+acc.num+" " + acc.name);
466                                                                 
467                                                                 //Cut data, so that the [done] step1 looks for will not be the one after [generate].
468                                                                 data = data.substring(begin+end);
469                                                                 
470                                                                 System.out.println("Found [save entry, looking for done.");
471                                                                 step++;
472                                                         }
473                                                         
474                                                         if( step==1 && data.contains("[done]") )
475                                                         {
476                                                                 System.out.println("Found [done] in: {"+data+"}");
477                                                                 Display.getDefault().asyncExec( new FkActionEventMsg(delegate, FkActionEventListener.FkActionEventType.ACTION_OKAY, "DONE:"+data,acc,'A') );
478                                                                 return;
479                                                         }
480
481                                                 } else {
482                                                         Thread.sleep(50);
483                                                         timeOut -= 50;
484                                                 }
485                                         } //While !timeout 
486                                 } //If !timeout
487                                 
488                                 Display.getDefault().asyncExec( new FkActionEventMsg(delegate, FkActionEventListener.FkActionEventType.ACTION_ABORTED, "TIMEOUT:"+data,null,'A') );
489
490                         } catch (Exception e) {
491                                 Display.getDefault().asyncExec( new FkActionEventMsg(delegate, FkActionEventListener.FkActionEventType.ACTION_ERROR, "EXCEPTION",null,'A') );
492                         }
493                         
494                 }
495
496                 
497         }
498
499         private void flushSerial() {
500                 try {
501                         Thread.sleep(10);
502                         com.serialPort.purgePort(SerialPort.PURGE_RXCLEAR | SerialPort.PURGE_TXCLEAR);
503                         
504                         System.out.println("Flushed "+com.serialPort.getInputBufferBytesCount()+" bytes.");
505                         while( com.serialPort.getInputBufferBytesCount() > 0 )
506                         {
507                                 com.serialPort.readBytes();
508                         }
509                         
510                 } catch(Exception e)
511                 {
512                         System.out.println("FkManager flushSerial Exception:"+e.getMessage() );
513                 }
514                 
515         }       
516         
517         public void createAccount(String strAccountName, String strUserName,
518                         Boolean autoPassword, int autoPassLen, Boolean autoPassAllSpecials,
519                         String autoPassSpecials, String strPassword, Boolean seperatorTab,
520                         FkActionEventListener delegate) {
521                         
522                         StringBuilder sb = new StringBuilder(256);
523                 
524                         
525                         
526                         sb.append(strAccountName);
527                         sb.append(ENTER_KEY);
528                         sb.append(PAUSE_CODE);
529                         sb.append(strUserName);
530                         sb.append(ENTER_KEY);
531                         sb.append(PAUSE_CODE);
532                         
533                         if( autoPassword )
534                         {
535                                 sb.append('2'); //Select automatic password
536                                 sb.append(PAUSE_CODE);
537                                 sb.append(autoPassLen);
538                                 sb.append(ENTER_KEY);
539
540                                 
541                                 if( autoPassAllSpecials )
542                                 {
543                                         sb.append('1'); //Allow all characters
544                                 } else {
545                                         if( autoPassSpecials.length() > 0 )
546                                         {
547                                                 sb.append('2'); //Allow only characters specified below
548                                                 sb.append(PAUSE_CODE);
549                                                 sb.append(autoPassSpecials);
550                                                 sb.append(ENTER_KEY);
551                                         } else {
552                                                 sb.append('3'); // Allow no special characters
553                                         }
554                                 }
555                         } else {
556                                 //Manual entered password
557                                 sb.append('1'); // Select manual password
558                                 sb.append(PAUSE_CODE);
559                                 sb.append(strPassword);
560                                 sb.append(ENTER_KEY);
561                         }
562                         
563                         sb.append(PAUSE_CODE);
564
565                         //Tab/Enter sep
566                         if( seperatorTab )
567                         {
568                                 sb.append('1'); //Select tab seperator
569                         } else {
570                                 sb.append('2'); //Select enter seperator
571                         }
572                         
573                         String seq = sb.toString();
574                         
575                         System.out.println("Seq ["+seq.replace(PAUSE_CODE, 'ø').replace(ENTER_KEY, 'å')+"]");
576                         
577                         NewAccountTask newTask = new NewAccountTask(seq, delegate, strAccountName);
578                         new Thread(newTask).start();                    
579                 
580         }
581
582         public void sortById(boolean byId) {
583                 if( byId )
584                 {
585                         sortMethod = new SortById();
586                 } else {
587                         sortMethod = new SortByName();
588                 }
589                 if(list != null )
590                 {
591                         Collections.sort(list, sortMethod);
592                 }
593         }
594
595
596 }