/*## (c) SECURITY EXPLORATIONS    2018 poland                                #*/
/*##     http://www.security-explorations.com                                #*/

/* THIS SOFTWARE IS PROTECTED BY DOMESTIC AND INTERNATIONAL COPYRIGHT LAWS    */
/* UNAUTHORISED COPYING OF THIS SOFTWARE IN EITHER SOURCE OR BINARY FORM IS   */
/* EXPRESSLY FORBIDDEN. ANY USE, INCLUDING THE REPRODUCTION, MODIFICATION,    */
/* DISTRIBUTION, TRANSMISSION, RE-PUBLICATION, STORAGE OR DISPLAY OF ANY      */
/* PART OF THE SOFTWARE, FOR COMMERCIAL OR ANY OTHER PURPOSES REQUIRES A      */
/* VALID LICENSE FROM THE COPYRIGHT HOLDER.                                   */

/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS    */
/* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,*/
/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL    */
/* SECURITY EXPLORATIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
/* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF  */
/* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE     */
/* SOFTWARE.                                                                  */

import java.lang.*;
import java.io.*;
import java.util.*;
import java.net.*;

public class NLogReader {

 public static class Client extends Thread {
  CommChannel cc;
  String saddr;

  public static String ROOT="FS_DUMP";
  public static int LINESIZE=16;

  private static int N=0;

  private static String allowed_chars="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890!@#$%^&*()_+-={}[]|:\";',.<>?/";

  public Client(CommChannel cc) {
   this.cc=cc;
   InetAddress addr=cc.get_client().getInetAddress();
   saddr=ConsoleUtils.padded_string("["+addr.toString()+"] ",16);
  }

  public void println(String s) {
   System.out.println(saddr+s);
  }

  private String char_value(char c) {
   char tab[]=new char[1];

   if (allowed_chars.indexOf(c)!=-1) {
    tab[0]=c;
    return new String(tab);
   } else return ".";
  }

  private void print_line(byte tab[],int pos) {
   String str="       "+ConsoleUtils.hex_value(pos,4)+": ";

   int size=tab.length-pos;
   
   if (size>LINESIZE) size=LINESIZE;

   for(int i=pos;i<(pos+size);i++) {
    str+=" "+ConsoleUtils.hex_value((int)tab[i],2);
   }

   str+="  ";  

   for(int i=pos;i<(pos+size);i++) {
    str+=char_value((char)tab[i]);
   }

   println(str);
  }

  public void print_buf(byte tab[]) throws Throwable {
   String str=" size: "+ConsoleUtils.hex_value(tab.length,8);

   println(str);

   int pos=0;
  
   while(pos<tab.length) {
    print_line(tab,pos);
    pos+=LINESIZE;
   }
  }

  private void read_table() throws Throwable {
   Calendar cal=Calendar.getInstance();
   println(cal.getTime().toString());

   byte tab[]=cc.read_buf();
   print_buf(tab);  
  }

  public void run() {
   boolean done=false;

   try {
    while(!done) {
     int cmd=cc.read_int();

     switch(cmd) {
      case -1:
       done=true;
       break;

      case 0:
       String s=cc.read_string();
       if (s==null) break;
        else println(s);
       break;

      case 3:
       read_table();
       break;

      case 4:
       int val=cc.read_int();
       println("0x"+Integer.toHexString(val));
       break;
     }
    }

    println("[DONE]");
   } catch(Throwable e) {
    e.printStackTrace();
   }
  }
 }

 public static void main(String args[])  throws Throwable {
  try {
   int bindport=ConfigDefs.LOGGER_PORT;

   if (args.length>0) {
    bindport=Integer.parseInt(args[0]);
   }

   ServerSocket srv=new ServerSocket(bindport,5);

   System.out.println("started logger at "+bindport);

   while(true) {
    CommChannel cc=new CommChannel(srv);
    new Client(cc).start();
   }
  } catch(Throwable e) {
   e.printStackTrace();
  }
 }
}
