Server.


//********************************************************************

// server.java

//********************************************************************

// Implements the server side of a Java based client/server chat system.

//

// Version History:

// 1.00  M. Ayers  2/3/97

//        Base version, contains comments and 'looks nice'

//

// 1.01  M. Ayers  3/30/97

//        Added filtering, tested all functions, no bugs found.

//

// 1.02  M. Ayers  4/15/97 

//        Multi Server, allows one server to connect to another as a

//        client.

//

// 1.03  M. Ayers  4/20/97

//        Tuned up server, checked for errors.

//********************************************************************



import java.io.*;

import sun.net.*;

import java.net.*;



class server extends NetworkServer   //Uses Sun's networking classes.

  {

    String user[];    //Base global declarations.

    DataInputStream net_input[];

    PrintStream net_output[];

    String channel_list[];

    int channel_count[];

    String user_type[];

    String user_channel[];

    String user_filter[];

    String other_server;

    int other_port;

    String temp_string;



    //Global counters.

    static int channel_counter = 0;

    static int perm_channel = 0;

    static int update = 0;

    static int maximum = 100;

    static int next_user = 0;

    static int port = 1111;



    Socket network_client;      // Networking Declarations.

    DataInputStream server_input;

    PrintStream server_output;

    boolean connected = false;

    server_writer w;



    public static void main(String args[])   //Start server.

      {

        new server();

      }



    public server()   //Begin server main code.

      {

        user = new String[maximum];            //Declare all arrays.

        net_input = new DataInputStream[maximum];

        net_output = new PrintStream[maximum];

        channel_list = new String[maximum];

        channel_count = new int[maximum];

        user_type = new String[maximum];

        user_channel = new String[maximum];

        user_filter = new String[maximum];



        try

          {

            read_info();    //Read startup information from file.

          }

        catch (IOException e)

          {             

            System.out.println("ERROR:  startup.channels file not

                                available.");

          }



        try

          {

            read_config();    //Read startup information from file.

          }

        catch (IOException e)

          {             

            System.out.println("ERROR:  server.config file not

                                available.");

          }



        try   

          {

            startServer(port);    //Bind server to port.

          }

        catch (Exception e)

          {

            System.out.println("ERROR:  Unable to start server.");

            return;

          }



        if (other_server != null)

          {

            if (connect())   //Check for connection creation.

              {

                  connected = true;

                  w = new server_writer(this);

                  w.start();

              }

            else

              {

                  System.out.println("Warning:  Not able to connect to

                                      server " + other_server);

              }

          }



        System.out.println("Message:  Server ready, waiting for

                            users...");

        update = 1;

        while(true)     //Infinite loop.

          {

            if(update == 1)    //Has server information been updated?

              {

                for (int i=perm_channel; i < channel_counter; I++)

                    //Check for empty channels.

                  {

                    if (channel_count[i] == 0)   //Clear empty channels.

                      {

                        for(int j = 0; j < maximum; j++) 

                          {

                            if ( user[j] != null)

                              {

                                if (user_type[j].equals("L"))

                                  {

                                    write_net_output(net_output[j],

                                                     "REMOVECHANNEL&" +

                                                     channel_list[i] ); 

                                  }

                              }

                          } 

                        for (int k=i; k < channel_counter ; k++) 

                          {

                            channel_list[k] = channel_list[k+1];  

                            channel_count[k] = channel_count[k+1];

                          }

                        channel_counter--; 

                      }

                  }

                for (int i=0; i < maximum ; i++) 

                  {

                    if (user[i] != null)

                      {

                        System.out.println("Info:  User - " + user[i] +

                                           " Channel - " +

                                           user_channel[i] + " Type - "

                                           + user_type[i]);

                      }

                  }

                for (int i=0; i < maximum ; i++) 

                  {

                    if (user[i] != null && user_type[i].equals("L"))

                      {

                        for (int j=0; j < channel_counter; j++)

                          {

                            write_net_output(net_output[i],

                                             "ADDCHANNEL&" +

                                             channel_list[j] +

                                             "&" + channel_count[j] );

                          }

                      }

                  }

                try 

                  {

                   write_info(); //Write server status (for use by CGI).

                  }

                catch (IOException e)

                  {

                    System.out.println("ERROR:  Problem with .list

                                        files.");

                  }

                update = 0;

              }  // End update.

            try   

              {

                Thread.sleep(1000);    

              }

            catch (InterruptedException e)   

              {

                ;   

              }

          } // End while.

      }  // End server.



    public void serviceRequest()     //Handle user connections.

      {

        DataInputStream input = new DataInputStream(clientInput);  

            //Get client IO streams.

        PrintStream output = clientOutput;

        boolean new_channel = true;



        for (int i=0;i < maximum ;i++ )   //Look for empty slot in table

          {

            if(user[i] == null)  

              {

                next_user = i;

                break;  

              }

          } 

        net_input[next_user] = input;

        net_output[next_user] = output;

        user[next_user] = read_net_input(input).trim();

        user_channel[next_user] = read_net_input(input).trim();

        user_type[next_user] = "L"; 

        if (user_channel[next_user].equals("server"))

          {

            user_type[next_user] = "S";

          }

        else

          {

            if (connected)

              {

                write_net_output(server_output, "ADDUSER&" +

                                 user[next_user] + "&" +

                                 user_channel[next_user]);

              }

            for (int k=0; k < channel_counter ; k++) 

              {

                if (channel_list[k].equals(user_channel[next_user]))  

                  {

                    channel_count[k]++;

                    new_channel = false;

                    break;

                  }

              }

            if (new_channel)

              {

                channel_list[channel_counter] = user_channel[next_user];

                channel_count[channel_counter] = 1;

                channel_counter++;

                for(int i = 0; i < maximum; i++) 

                  {

                    if (user[i] != null && user_type[i].equals("L"))

                      {

                        write_net_output(net_output[i], "ADDCHANNEL&" +

                                         user_channel[next_user]); 

                      }

                  }

              }

          }



        System.out.println("Info:  " + user[next_user] +

                           " connected on channel " +

                           user_channel[next_user] + " Index - " +

                           next_user);



        (new reader(this, next_user)).start();    

            //Start thread to handle user request.

        int c = next_user;



        while (user[c] != null)

          {

            try   

              {

                Thread.sleep(5000);    

              }

            catch (InterruptedException e)   

              {

                ;   

              }

          }

      } // End serviceRequest.



    String read_net_input(DataInputStream input) //Read network input,

                                                   one line at a time.

      {

        try  

          {

            return input.readLine();  

          }

        catch (IOException e)   

          {

            return null;  

          }

      }



    void write_net_output(PrintStream output, String string)    

        //Write to network, one line at a time.

      {

        output.println(string);

        output.flush();

      }



    void read_info() throws IOException     //Read startup info.

      {

        RandomAccessFile f = new RandomAccessFile("startup.channels",

                                    "r");  //Open startup.channels file.

        String string;

        int i =0;

        string = f.readLine();

        while(string != null) 

          {

            channel_list[i] = string.trim();

            System.out.println("Info:  Permanent channel - " +

                                channel_list[i]);

            i++;

            string = f.readLine();

          }

        channel_counter = i;

        perm_channel = i;

        f.close();

      }  // End read_info.



    void write_info() throws IOException   //Write status files for CGI.

      {

        RandomAccessFile file1 = new RandomAccessFile("channel.list",

                                         "rw");   //Open files.

        RandomAccessFile file2 = new RandomAccessFile("user.list",

                                         "rw");

        RandomAccessFile file3 = new RandomAccessFile(  

                                         "user_on_channel.list", "rw");

        int j = 0, k = 0;

        for(int i = 0; i < channel_counter; i++) 

          {

            file1.writeBytes(channel_list[i] + "\n" );  

          }

        for(int i = 0; i < maximum; i++) 

          {

            if (user[i] != null && !user[i].equals("server"))

              {

                file2.writeBytes(user[i] + "\n" );  

                j++;

              }

          }

        for(int i = 0; i < maximum; i++) 

          {

            if (user[i] != null && !user[i].equals("server"))

              {

                file3.writeBytes("User " + user[i] + " is on channel " +

                                  user_channel[i] + "\n" );  

                k++;

              }

          }

        for(int i = 0; i < maximum - channel_counter; I++)

            //Pad file to clear unwanted lines.

          {

            file1.writeBytes("\n" );  

          }

        for(int i = 0; i < maximum - j; i++) 

          {

            file2.writeBytes("\n" );  

          }

        for(int i = 0; i < maximum - k; i++)

          {

            file3.writeBytes("\n" );  

          }

        file1.close();

        file2.close();

        file3.close();

      }  // End write_info



    void read_config() throws IOException

      {

        String string;

        Integer integer;

        RandomAccessFile f = new RandomAccessFile("server.config", "r");

        string = f.readLine();



        while(string != null) 

          {

            if (string.startsWith("port"))

              {

                string = string.substring(4).trim();

                integer = new Integer(string);

                port = integer.intValue();

              }

            else

              {

                if (string.startsWith("server"))

                  {

                    other_server = string.substring(6).trim();

                    string = f.readLine();

                    string = string.substring(11).trim();

                    integer = new Integer(string);

                    other_port = integer.intValue();

                  }

              }

            string = f.readLine();

          }

        f.close();

      }



    public void display()    //Update server based on network activity.

      {

        String string;

        string = w.net_line;

        if (string.startsWith("ADDUSER&")) 

          {

            adduser(string);

          } 

        if (string.startsWith("REMOVEUSER&")) 

          {

            removeuser(string);

          } 

        if (string.startsWith("TEXT&")) 

          {

            text(string);

          } 

        update = 1;

      }  // End display.



    boolean connect()   //Create network to another server connaction.

      {

        System.out.println("Info:  Connecting server to " +

                            other_server);

        try 

          {

            network_client = new Socket(other_server, other_port); 

          }

        catch (IOException e)

          {

            System.out.println("Warning:  Unable to connect to host <" +

                                e + ">");

            return false;

          }

        System.out.println("Info:  Connected to server");

        try

          {

            server_input = 

                new DataInputStream (network_client.getInputStream());

            server_output =

                new PrintStream (network_client.getOutputStream());

          }

        catch (IOException e ) 

          {

            System.out.println("Warning:  Server is NOT ready.");

            return false;

          }

        write_net_output(server_output, "server");

        write_net_output(server_output, "server");

        return true;

      }   // End connect.



    void adduser(String input)

      {

        boolean new_channel = true;

        for (int i=0;i < maximum ;i++ )   //Look for empty slot in table

          {

            if(user[i] == null)  

              {

                next_user = i;

                break;  

              }

          } 

        user[next_user] = input.substring(8,input.lastIndexOf("&"));

        user_channel[next_user] = input.substring(input.lastIndexOf("&")

                                                  + 1).trim();

        user_type[next_user] = "R"; 

        for (int k=0; k < channel_counter ; k++) 

          {

            if (channel_list[k].equals(user_channel[next_user]))  

              {

                channel_count[k]++;

                new_channel = false;

                break;

              }

          }

        if (new_channel)

          {

            channel_list[channel_counter] = user_channel[next_user];

            channel_count[channel_counter] = 1;

            channel_counter++;

            for(int i = 0; i < maximum; i++) 

              {

                if( user[i] != null && user_type[i].equals("L"))

                  {

                    write_net_output(net_output[i], "ADDCHANNEL&" +

                                     user_channel[next_user]); 

                  }

              }

          }

        for(int i = 0; i < maximum; i++) 

          {

            if (user[i] != null &&

                user_channel[next_user].equals(user_channel[i]) &&

                user_type[i].equals("L")) 

              {

                write_net_output(net_output[i], "ADDUSER&" +

                                 user[next_user] );  

              }

          }

        for(int i = 0; i < maximum; i++) 

          {

            if (user[i] != null && user_type[i].equals("S")) 

              {

                write_net_output(net_output[i], "ADDUSER&" +

                                 user[next_user] + "&" +

                                 user_channel[next_user] );  

              }

          }

      }



    void removeuser(String input)

      {

        String person;

        person = input.substring(11).trim();

        for (int i=0;i < maximum ;i++ )   

          {

            if ( user[i].equals(person) )  

              {

                next_user = i;

                break;  

              }

          } 

        for (int k=0; k < channel_counter ; k++) 

          {

            if (channel_list[k].equals(user_channel[next_user]))  

              {

                channel_count[k]--;

                break;

              }

          }

        for(int i = 0; i < maximum; i++) 

          {

            if (user[i] != null &&

                user_channel[next_user].equals(user_channel[i]) &&

                user_type[i].equals("L")) 

              {

                write_net_output(net_output[i], "REMOVEUSER&" +

                                 user[next_user] );  

              }

          }

        for(int i = 0; i < maximum; i++) 

          {

            if (user[i] != null && user_type[i].equals("S")) 

              {

                write_net_output(net_output[i], "REMOVEUSER&" +

                                 user[next_user]);  

              }

          }

        user[next_user] = null;

      }



    void text(String input)   //Forward text to correct users.

      {

        String message;

        String person;

        int index = 0;

        message = input.substring(5);

        person = message.substring(0,message.indexOf(" "));

        for(int i = 0; i < maximum; i++) 

          {

            if (user[i] != null && user[i].equals(person))

              {

                index = i;

              }

          }

        System.out.println("Text:  Server " + other_server + " says " +

                            input.substring(5));

        for(int i = 0; i < maximum; i++) 

          {

            if (user[i] != null && i != index) 

              {

                if (user_channel[index].equals(user_channel[i]) ||

                    user_type[i].equals("S") ) 

                  {

                    if (user_filter[i].indexOf(user[index]) == -1)

                      {

                        if(!user_type[i].equals("R"))

                          {

                            write_net_output(net_output[i], input); 

                          }

                      }

                  }  

              }

          }

      }



  } // End server.





class reader extends Thread  //Thread created to handle user requests.

  {

    server s;

    int index;



    public reader(server s, int index)  //This thread's index and link

                                          to server.

      {

        this.s = s;

        this.index = index;

      }



    public void run()

      {

        setPriority(MIN_PRIORITY);

        s.user_filter[index] = "";

        if (s.user_type[index].equals("S"))

          {

            for(int i = 0; i < s.maximum; i++) 

              {

                if (s.user[i] != null && !s.user_type[i].equals("S"))

                  {

                    s.write_net_output(s.net_output[index], "ADDUSER&" +

                                       s.user[i] + "&" +

                                       s.user_channel[i]);

                  }

              }

          }

        else

          {

            s.write_net_output(s.net_output [index], "TEXT&<<<< Adding

                               Startup information... >>>>");  

                               //Add startup info to client.

            for(int i = 0; i < s.channel_counter; i++) 

              {

                s.write_net_output(s.net_output[index], "ADDCHANNEL&" +

                                   s.channel_list[i]);

              }

            for(int i = 0; i < s.maximum; i++) 

              {

                if (s.user[i] != null) 

                  {

                   if(s.user_channel[index].equals(s.user_channel[i]) ||

                      s.user_type[i].equals("S") ) 

                      {

                        if (s.user_type[i].equals("R"))

                          {

                            s.write_net_output(s.net_output[index],

                                               "ADDUSER&" + s.user[i] );  

                          }

                        if (s.user_type[i].equals("S"))

                          {

                            s.write_net_output(s.net_output[i],

                                               "ADDUSER&" +

                                               s.user[index] + "&" +

                                               s.user_channel[index]);

                          }

                        if (s.user_type[i].equals("L"))

                          {

                            s.write_net_output(s.net_output[index],

                                               "ADDUSER&" + s.user[i] );  

                            s.write_net_output(s.net_output[i],

                                               "ADDUSER&" +

                                               s.user[index] );  

                           }

                      }

                  }

              }

            s.write_net_output(s.net_output [index], "TEXT&<<<< You are

                               now connected on channel " +

                               s.user_channel[index] + " >>>>");

          }

        s.update = 1;

        while (true)

          {

            String string = s.read_net_input(s.net_input[index]);

                //Read network.



            if (string == null)

              break;



            System.out.println("Info:  " + s.user[index] + " - " +

                               string);



            if (string.startsWith("TEXT&"))   // Handlers for events.

              {

                text(string);

              } 

            if (string.startsWith("GO&")) 

              {

                gochannel(string);

              }

            if (string.startsWith("ADDCHANNEL&")) 

              {

                addchannel(string);

              } 

            if (string.startsWith("ADDUSER&")) 

              {

                adduser(string);

              } 

            if (string.startsWith("REMOVEUSER&")) 

              {

                removeuser(string);

              } 

            if (string.startsWith("FILTER&")) 

              {

                filter(string);

              } 

            if (string.startsWith("UNFILTER&")) 

              {

                unfilter(string);

              } 

            if (string.startsWith("STATUS&")) 

              {

                status(string);

              } 

          }  // End while.

          

        for(int i = 0; i < s.maximum; i++)   //When user quits, remove

                                               from other user's lists.

          {

            if (s.user[i] != null) 

              {

                if (s.user_channel[index].equals(s.user_channel[i]) ||

                    s.user_type[i].equals("S")) 

                  {

                    if(!s.user_type[i].equals("R"))

                      {

                        s.write_net_output(s.net_output[i],

                                           "REMOVEUSER&" +

                                           s.user[index]);  

                      }

                  }

              }

          }

        if (s.connected)

          {

            s.write_net_output(s.server_output, "REMOVEUSER&" +

                               s.user[index] );

          }

        for (int i = 0; i < s.channel_counter ; i++) 

          {

            if (s.channel_list[i].equals(s.user_channel[index]))  

              {

                s.channel_count[i]--;

                break;

              }

          }

        s.update = 1;



        System.out.println("Info:  " + s.user[index] + " has

                            disconnected.");

        s.user[index] = null;

      }  // End run.



    void text(String input)   //Forward text to correct users.

      {

        String message;

        String person;

        int person_index = 0;

        System.out.println("Text:  " + s.user[index] + " says " +

                            input.substring(5));

        if (s.user_type[index].equals("S"))

          {

            message = input.substring(5);

            person = message.substring(0,message.indexOf(" "));

            for(int i = 0; i < s.maximum; i++) 

              {

                if (s.user[i] != null && s.user[i].equals(person))

                  {

                    person_index = i;

                  }

              }

            for(int i = 0; i < s.maximum; i++) 

              {

                if (s.user[i] != null && i != person_index &&

                    i != index) 

                  {

                    if(!s.user_type[i].equals("R"))

                      {

                        if (s.user_channel[person_index].equals(      

                            s.user_channel[i]) ||

                            s.user_type[i].equals("S") ) 

                          {

                            if (s.user_filter[i].indexOf( 

                                s.user[person_index]) == -1)

                              {

                                s.write_net_output(s.net_output[i],

                                                   input); 

                              }

                          }

                      }  

                  }

              }

          }

        else

          {

            for(int i = 0; i < s.maximum; i++) 

              {

                if (s.user[i] != null && i != index) 

                  {

                    if(!s.user_type[i].equals("R"))

                      {

                        if (s.user_channel[index].equals( 

                            s.user_channel[i]) ||

                            s.user_type[i].equals("S") ) 

                          {

                            if (s.user_filter[i].indexOf(

                                s.user[index]) == -1)

                              {

                                s.write_net_output(s.net_output[i],

                                                   "TEXT&" +

                                                   s.user[index] +

                                                   " says: " +

                                                   input.substring(5)); 

                              }

                          }

                      }  

                  }

              }

          }

        if (s.connected)

          {

            s.write_net_output(s.server_output, "TEXT&" +

                               s.user[index] + " says: " +

                               input.substring(5)); 

          }

      }



    void gochannel(String input)   

        //Place user on a different channel, removing from other channel

      {

        System.out.println("Info:  User " + s.user[index] +

                           " is now on channel " + input.substring(3));

        for (int k=0; k < s.channel_counter ; k++) 

          {

            if (s.channel_list[k].equals(s.user_channel[index]))  

              {

                s.channel_count[k]--;

                break;

              }

          }

        for (int k=0; k < s.channel_counter ; k++) 

          {

            if (s.channel_list[k].equals(input.substring(3).trim()))  

              {

                s.channel_count[k]++;

                break;

              }

          }

        for(int i = 0; i < s.maximum; i++) 

          {

            if (s.user[i] != null &&

                s.user_channel[index].equals(s.user_channel[i])) 

              {

                if(s.user_type[i].equals("L"))

                  {

                    s.write_net_output(s.net_output[i], "REMOVEUSER&" +

                                       s.user[index] );  

                  }

              }

          }

        s.user_channel[index] = input.substring(3).trim();

        s.write_net_output(s.net_output[index], input); 

        s.write_net_output(s.net_output[index], "TEXT&<<<< You are now

                           on channel " + s.user_channel[index] +

                           " >>>>");

        for(int i = 0; i < s.maximum; i++) 

          {

            if (s.user[i] != null &&

                s.user_channel[index].equals(s.user_channel[i])) 

              {

                if(s.user_type[i].equals("L"))

                  {

                    s.write_net_output(s.net_output[i], "ADDUSER&" +

                                       s.user[index] );  

                    s.write_net_output(s.net_output[index], "ADDUSER&" +

                                       s.user[i] );  

                  }

                if(s.user_type[i].equals("R"))

                  {

                    s.write_net_output(s.net_output[index], "ADDUSER&" +

                                       s.user[i] );

                  }

              }

            else 

              {

                if(s.user[i] != null && s.user_type[i].equals("S") )

                  {

                    s.write_net_output(s.net_output[i], "REMOVEUSER&" +

                                       s.user[index] );  

                    s.write_net_output(s.net_output[i], "ADDUSER&" +

                                       s.user[index] + "&" +

                                       s.user_channel[index] );  

                  }

              }

          }

        if (s.connected)

          {

            s.write_net_output(s.server_output, "REMOVEUSER&" +

                               s.user[index] );  

            s.write_net_output(s.server_output, "ADDUSER&" +

                               s.user[index] + "&" +

                               s.user_channel[index] );  

          }

        s.update = 1;

      }



    void addchannel(String input)   

        //Add a new channel and move user to this channel.

      {

        System.out.println("Info:  User " + s.user[index] +

                           " is now on new channel " +

                           input.substring(11));

        boolean new_channel = true;

        for (int k=0; k < s.channel_counter ; k++) 

          {

            if (s.channel_list[k].equals(s.user_channel[index]))  

              {

                s.channel_count[k]--;

                break;

              }

          }

        s.user_channel[index] = input.substring(11).trim();

        for (int k=0; k < s.channel_counter ; k++) 

          {

            if (s.channel_list[k].equals(s.user_channel[index]))  

              {

                s.channel_count[k]++;

                new_channel = false;

                break;

              }

          }

        if (new_channel)

          {

            s.channel_list[s.channel_counter] =

                input.substring(11).trim();

            s.channel_count[s.channel_counter] = 1;

            s.channel_counter++;

            for(int i = 0; i < s.maximum; i++) 

              {

                if(s.user[i] != null && s.user_type[i].equals("L"))

                  {

                    s.write_net_output(s.net_output[i], "ADDCHANNEL&" +

                                       s.user_channel[index]); 

                  }

              }

          }

        s.write_net_output(s.net_output[index], "TEXT&<<<< You are now

                           on channel " + s.user_channel[index] +

                           " >>>>");

        for(int i = 0; i < s.maximum; i++) 

          {

            if (s.user[i] != null && s.user_channel[index].equals(s.user_channel[i])) 

              {

                if(s.user_type[i].equals("L"))

                  {

                    s.write_net_output(s.net_output[i], "ADDUSER&" +

                                       s.user[index] );  

                    s.write_net_output(s.net_output[index], "ADDUSER&" +

                                       s.user[i] );  

                  }

              }

            else 

              {

                if(s.user[i] != null && s.user_type[i].equals("S") )

                  {

                    s.write_net_output(s.net_output[i], "REMOVEUSER&" +

                                       s.user[index] );  

                    s.write_net_output(s.net_output[i], "ADDUSER&" +

                                       s.user[index] + "&" +

                                       s.user_channel[index] );  

                  }

              }

          }

        if (s.connected)

          {

            s.write_net_output(s.server_output, "REMOVEUSER&" +

                               s.user[index] );  

            s.write_net_output(s.server_output, "ADDUSER&" +

                               s.user[index] + "&" +

                               s.user_channel[index] );  

          }

        s.update = 1;

      }



    void filter(String input)    //Filter (ignore) text from a user.

      {

        if (s.user_filter[index].indexOf(input.substring(7)) == -1)

          {

            s.user_filter[index] = s.user_filter[index] +

                                   input.substring(7).trim() + "|";

          }

        s.write_net_output(s.net_output[index], input); 

      }



    void unfilter(String input)   //Unfilter a user.

      {

        String filter_name = input.substring(9).trim() + "|";

        if (s.user_filter[index].indexOf(filter_name) != -1)

          {

            s.user_filter[index] = s.user_filter[index].substring(

                0,s.user_filter[index].indexOf(filter_name)) +    

                s.user_filter[index].substring(   

                s.user_filter[index].indexOf(filter_name) +

                filter_name.length());

          }

        s.write_net_output(s.net_output[index], input); 

      }



    void status(String input)    //Show server status in client window.

      {

        int num_users = 0;

        int num_servers = 0;

        for (int i=0;i < s.maximum;i++)

          {

            if (s.user[i] != null)

              {

                if (s.user_type[i].equals("S"))

                  {

                    num_servers++;

                  }

                else

                  {

                    num_users++;

                  }

              }

          }

        System.out.println("Info:  User " + s.user[index] + " has

                            requested system status");

        s.write_net_output(s.net_output[index], "TEXT&<<<< The server

                            has " + num_users +

                            " users connected. >>>>");

        s.write_net_output(s.net_output[index], "TEXT&<<<< The server

                            has " + num_servers +

                            " servers connected. >>>>");

        s.write_net_output(s.net_output[index], "TEXT&<<<< The server

                            has " + (s.maximum - num_users) +

                            " connections available. >>>>");

        s.write_net_output(s.net_output[index], "TEXT&<<<< You are on

                            channel " + s.user_channel[index] +

                            " >>>>");

        s.update = 1;

      }



    void adduser(String input)

      {

        boolean new_channel = true;

        for (int i=0;i < s.maximum ;i++ ) //Look for empty slot in table

          {

            if(s.user[i] == null)  

              {

                s.next_user = i;

                break;  

              }

          } 

        s.user[s.next_user] = input.substring(8,input.lastIndexOf("&"));

        s.user_channel[s.next_user] = 

              input.substring(input.lastIndexOf("&") + 1).trim();

        s.user_type[s.next_user] = "R"; 

        for (int k=0; k < s.channel_counter ; k++) 

          {

            if (s.channel_list[k].equals(s.user_channel[s.next_user]))  

              {

                s.channel_count[k]++;

                new_channel = false;

                break;

              }

          }

        if (new_channel)

          {

            s.channel_list[s.channel_counter] =

                     s.user_channel[s.next_user];

            s.channel_count[s.channel_counter] = 1;

            s.channel_counter++;

            for(int i = 0; i < s.maximum; i++) 

              {

                if(s.user[i] != null && s.user_type[i].equals("L"))

                  {

                    s.write_net_output(s.net_output[i], "ADDCHANNEL&" +

                                       s.user_channel[s.next_user]); 

                  }

              }

          }

        for(int i = 0; i < s.maximum; i++) 

          {

            if (s.user[i] != null &&

                s.user_channel[s.next_user].equals(s.user_channel[i]) &&

                s.user_type[i].equals("L")) 

              {

                s.write_net_output(s.net_output[i], "ADDUSER&" +

                                   s.user[s.next_user] );  

              }

          }

        for(int i = 0; i < s.maximum; i++) 

          {

            if (s.user[i] != null && s.user_type[i].equals("S") &&

                i != index) 

              {

                s.write_net_output(s.net_output[i], "ADDUSER&" +

                                   s.user[s.next_user] + "&" +

                                   s.user_channel[s.next_user] );  

              }

          }

        if (s.connected)

          {

            s.write_net_output(s.server_output, "ADDUSER&" +

                               s.user[s.next_user] + "&" +

                               s.user_channel[s.next_user] );  

          }

        s.update = 1;

      }



    void removeuser(String input)

      {

        String person;

        person = input.substring(11).trim();

        for (int i=0;i < s.maximum ;i++ )   //

          {

            if ( s.user[i].equals(person) )  

              {

                s.next_user = i;

                break;  

              }

          } 

        for (int k=0; k < s.channel_counter ; k++) 

          {

            if (s.channel_list[k].equals(s.user_channel[s.next_user]))  

              {

                s.channel_count[k]--;

                break;

              }

          }

        for(int i = 0; i < s.maximum; i++) 

          {

            if (s.user[i] != null && i != s.next_user &&

                s.user_channel[s.next_user].equals(s.user_channel[i]) &&

                s.user_type[i].equals("L")) 

              {

                s.write_net_output(s.net_output[i], "REMOVEUSER&" +

                                   s.user[s.next_user] );  

              }

          }

        for(int i = 0; i < s.maximum; i++) 

          {

            if (s.user[i] != null && i != s.next_user &&

                s.user_type[i].equals("S") && i != index) 

              {

                s.write_net_output(s.net_output[i], "REMOVEUSER&" +

                                   s.user[s.next_user]);  

              }

          }

        if (s.connected) 

          {

            s.write_net_output(s.server_output, "REMOVEUSER&" +

                               s.user[s.next_user]);

          }

        s.user[s.next_user] = null;

        s.update = 1;

      }



  }  // End reader.





class server_writer extends Thread    

  //Thread to read from network, prevents display from blocking while

    reading from network.

  {

    String net_line = "";

    server s;



    public server_writer(server s)

      {

        this.s = s;

      }



    public void run()

      {

        while (true)

          {

            String input = s.read_net_input(s.server_input);    

                //Read a line from the network.

            net_line = input;

            s.display();  //Call code in display.

          }

      }



  }  // End server_writer.