1   // joi/10/juno/LoginInterpreter.java                         
2   //                                                            
3   //                                                            
4   // Copyright 2003 Ethan Bolker and Bill Campbell                         
5                                                               
6   import java.util.*;
7   
8   /**
9    * Interpreter for Juno login commands.
10   * 
11   * There are so few commands that if-then-else logic is OK.
12   *
13   * @version 10
14   */
15  
16  public class LoginInterpreter 
17      implements InterpreterInterface
18  {
19      private static final String LOGIN_COMMANDS =
20          "help, register, <username>, exit";
21  
22      private Juno system;             // the Juno object
23      private OutputInterface console; // where output goes
24  
25      /**
26       * Construct a new LoginInterpreter for interpreting
27       * login commands.
28       *
29       * @param system the system creating this interpreter.
30       * @param console the Terminal used for input and output.
31       */
32  
33      public LoginInterpreter( Juno system, OutputInterface console) 
34      {
35          this.system  = system;
36          this.console = console;
37      }
38  
39      /**
40       * Set the console for this interpreter.  Used by the
41       * creator of this interpreter.
42       *
43       * @param console the Terminal to be used for input and output.
44       */
45  
46      public void setConsole( OutputInterface console) 
47      {
48          this.console = console;
49      }
50  
51      /** 
52       * Simulates behavior at login: prompt.
53       */
54  
55      public void CLILogin()  
56      {
57          welcome();
58          boolean moreWork = true;
59          while( moreWork ) { 
60              moreWork = interpret(((InputInterface)console).
61                                   readLine( "Juno login: " ) );
62          }
63      }
64  
65  
66      /**
67       * Parse user's command line and dispatch appropriate
68       * semantic action.
69       *
70       * @param  inputLine the User's instructions.
71       * @return true except for "exit" command 
72       *         or null inputLine.
73       */
74  
75      public boolean interpret( String inputLine ) 
76      {
77          if (inputLine == null) {
78              return false;
79          }
80          StringTokenizer st = 
81              new StringTokenizer( inputLine );
82          if (st.countTokens() == 0) {
83              return true; // skip blank line
84          }
85          String visitor = st.nextToken();
86          if (visitor.equals( "exit" )) {      
87              return false;
88          }
89          if (visitor.equals( "register" )) {
90              register( st );
91          }
92          else if (visitor.equals( "help" )) {
93              help();
94          }
95          else {
96              String password; 
97              try { 
98                  if (console.isGUI()) {
99                      password = st.nextToken();
100                 }
101                 else {;
102                     password = readPassword( "password: " );
103                 }
104                 User user = system.lookupUser(visitor);
105                 user.matchPassword( password );
106                 new Shell( system, user, console );
107             }
108             catch (Exception e) {
109 
110                 // NullPointerException if no such user,
111                 // JunoException if password fails to match -
112                 // message to user doesn't give away which.
113                 // The sysadmin would probably want a log
114                 // that did keep track.
115                 //
116                 // Other exceptions should be caught in shell()
117 
118                 console.println("sorry");
119             }
120         }
121         return true;
122     }
123 
124     // Register a new user, giving him or her a login name and a
125     // home directory on the system.
126     // 
127     // StringTokenizer argument contains the new user's login name
128     // followed by full real name.
129 
130     private void register( StringTokenizer line )
131     {
132         String username = "";
133         String password = "";
134         String realname = "";
135         try {
136             username = line.nextToken();
137             password = line.nextToken();
138             realname = line.nextToken("").trim();
139         }
140         catch (NoSuchElementException e) {
141         }
142 
143         if (username.equals("") || password.equals("")
144             || realname.equals("") ) {
145             console.println(
146                   "please supply username, password, real name");
147             return;
148         }
149         User user = system.lookupUser(username);
150 
151         if (user != null) {  // user already exists
152             console.println("sorry");
153             return;
154         }
155         if (badPassword( password )) {
156             console.println("password too easy to guess");
157             return;
158         }
159         Directory home = new Directory( username, null,
160                                         system.getUserHomes() );
161 
162         user = system.createUser( username, home, password, realname );
163         home.setOwner( user );
164     }
165 
166     // test to see if password is unacceptable:
167     //   fewer than 6 characters
168     //   contains only alphabetic characters
169 
170     private boolean badPassword( String pwd )
171     {
172         if (pwd.length() < 6) {
173             return true;
174         }
175         int nonAlphaCount = 0;
176         for (int i=0; i < pwd.length(); i++) {
177             if (!Character.isLetter(pwd.charAt(i))) {
178                 nonAlphaCount++;
179             }
180         }
181         return (nonAlphaCount == 0);
182     }
183 
184     // Used for reading the user's password in CLI.
185 
186     private String readPassword( String prompt ) 
187     {
188         String line = 
189             ((InputInterface) console).readLine( prompt );
190         StringTokenizer st = new StringTokenizer( line );
191         try {
192             return st.nextToken();
193         }
194         catch ( NoSuchElementException e )  {}
195         return ""; // keeps compiler happy
196     }
197 
198 
199     // Display a short welcoming message, and remind users of
200     // available commands.
201 
202     private void welcome()
203     {
204         console.println( "Welcome to " + system.getHostName() +
205                          " running "   + system.getOS() +
206                          " version "   + system.getVersion() );
207         help();
208     }
209 
210     // Remind user of available commands.
211 
212     private void help()
213     {
214         console.println( LOGIN_COMMANDS );
215         console.println("");
216     }
217 }
218