Source

lsw / lsw32.c

#include <windows.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <dir.h>
#include <string.h>
#include <assert.h>

typedef enum {
  false,
  true
} bool;

#include "cgihelp.h"
/*-------------------------------------------------------------------------*/
const static struct {
  const char* Path;
  const char* PassKey;
} authDirs[] = {
  { "e://cyberid/daybologic/dev/rttb/downloads", NULL },
  { "e://cyberid/daybologic/aim/archive", NULL },
  { "e://cyberid/daybologic/tory/minutes", "blahdy-bleh" },
  { "e://cyberid/daybologic/dev/daybodep/downloads", NULL },
  { "e://cyberid/daybologic/dev/cobjects/downloads", NULL },
  { "e://cyberid/daybologic/dev/dlini/downloads", NULL },
  { "e://cyberid/daybologic/dev/dpcrtlmm/downloads", NULL },
  { "e://cyberid/daybologic/dev/ml64/downloads", NULL },
  { "e://cyberid/daybologic/dev/raw2c/downloads", NULL },
  { "e://cyberid/daybologic/dev/rttb/downloads", NULL },
  { "e://cyberid/daybologic/dev/dlutils/downloads", NULL },
  { "e://cyberid/daybologic/dev/cidr/downloads", NULL },
  { "e://cyberid/daybologic/dev/dlscripts/downloads", NULL },
  { "e://cyberid/daybologic/dev/dlstds/downloads", NULL },
  { "e://cyberid/daybologic/dev/daybothreads/downloads", NULL },
  { "e://cyberid/daybologic/dev/dupfiles/downloads", NULL },
  { "e://cyberid/daybologic/dev/overchat/downloads", NULL },
  { "e://cyberid/daybologic/dev/overchat/downloads/servers", NULL },
  { "e://cyberid/daybologic/dev/overchat/downloads/clients", NULL },
  { "e://cyberid/daybologic/dev/daybocrypt/downloads", NULL },
  { "e://cyberid/daybologic/ddrp", "piggy123" },
  { "e://cyberid/daybologic/lan", "Broadmead1" }
};

static const char MasterKey[] = "vZmpV61dd";
/*-------------------------------------------------------------------------*/
static void DoList(const char* Directory, const char* Key);
static bool NiceDir(const char* Directory);
static void PrintEntry(const char* Directory, const char* Key, WIN32_FIND_DATA* PFindFileData);
static char* Downsize(const char* Dir);
static bool CheckPass(const char* Directory, const char* Password);
static bool TestExtension(const char* FileName, const char* Extension);
static bool TestExtensionReversed(const char* FileName, const char* ExtensionReversed);
static bool TestLog(const char* FileName);
static bool TestPng(const char* FileName);
static bool TestDownload(const char* FileName);
static bool IsCurrentDir(const char* FileName);
static bool IsParentDir(const char* FileName);
static char* MakeParent(const char* Directory);
/*-------------------------------------------------------------------------*/
static void DoList(const char* Directory, const char* Key)
{
  HANDLE contHandle; /* Continuation of find handle */
  WIN32_FIND_DATA findFileData;
  BOOL ok = TRUE;
  char mask[MAX_PATH];

  mask[0] = '\0';
  strncat(mask, Directory, MAX_PATH-1);
  strncat(mask, "./*", MAX_PATH-1);

  contHandle = FindFirstFile(mask, &findFileData);
  if ( contHandle ) PrintEntry(Directory, Key, &findFileData);
  while ( contHandle && ok ) {
    ok = FindNextFile(contHandle, &findFileData);
    if ( ok ) PrintEntry(Directory, Key, &findFileData);
  }

  FindClose(contHandle);
}
/*-------------------------------------------------------------------------*/
static bool NiceDir(const char* Directory)
{
  unsigned int i;
  bool nice = false;

  for ( i = 0U; i < sizeof(authDirs)/sizeof(authDirs[0]); i++ ) {
    if ( strcmp(Directory, authDirs[i].Path) == 0 ) { /* Aye! */
      nice = true;
      break;
    }
  }
  return nice;
}
/*-------------------------------------------------------------------------*/
static void PrintEntry(const char* Directory, const char* Key, WIN32_FIND_DATA* PFindFileData)
{
  FILETIME localTime;
  SYSTEMTIME sysTime;

  if ( PFindFileData->dwFileAttributes & FILE_ATTRIBUTE_HIDDEN )
    return; /* Do not list hidden files */
  if ( PFindFileData->dwFileAttributes & FILE_ATTRIBUTE_SYSTEM )
    return; /* Do not list operating system files */
  if ( PFindFileData->dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY )
    return; /* Do not list temporary working files */

  if ( PFindFileData->dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE ) putc('a', stdout);
  else putc('-', stdout);

  if ( PFindFileData->dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED ) putc('c', stdout);
  else putc('-', stdout);

  if ( PFindFileData->dwFileAttributes & FILE_ATTRIBUTE_READONLY ) putc('r', stdout);
  else putc('-', stdout);

  puts("  "); /* Space from attributes to date */

  /* Date handling */
  FileTimeToLocalFileTime(&PFindFileData->ftCreationTime, &localTime);
  FileTimeToSystemTime(&localTime, &sysTime);

  printf("%0u/%u/%u   %u:%u:%u   ", sysTime.wDay, sysTime.wMonth, sysTime.wYear, sysTime.wHour, sysTime.wMinute, sysTime.wSecond);

  if ( PFindFileData->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
    printf("&lt; DIR &gt; &nbsp;");
  else
    printf("%lu bytes &nbsp;", PFindFileData->nFileSizeLow);

  if ( PFindFileData->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) {
    if ( IsParentDir(PFindFileData->cFileName) ) {
      char* parent = MakeParent(Directory);
      if ( parent ) {
        printf("<a href=\"./lsw32.exe?dir=%s\">%s</a>&nbsp;(parent)<br>", parent, PFindFileData->cFileName);
        free(parent);
      }
    }
    else if ( IsCurrentDir(PFindFileData->cFileName) ) {
      printf("<a href=\"./lsw32.exe?dir=%s&key=%s\">%s</a>&nbsp;(this)<br>", Directory, Key, PFindFileData->cFileName);
    }
    else {
      printf("<a href=\"./lsw32.exe?dir=%s/%s&key=%s\">%s</a><br>", Directory, PFindFileData->cFileName, Key, PFindFileData->cFileName);
    }
  }
  else { /* File */
    if ( TestLog(PFindFileData->cFileName) ) /* Is file a logfile? */
      printf("<a href=\"./aimview.exe?file=%s/%s\">%s</a><br>", Downsize(Directory), PFindFileData->cFileName, PFindFileData->cFileName);
    else if ( TestPng(PFindFileData->cFileName) ) /* Is file a PNG image? */
      printf("<a href=\"./pngview.cgi?file=%s/%s\">%s</a><br>", Downsize(Directory), PFindFileData->cFileName, PFindFileData->cFileName);
    else if ( TestDownload(PFindFileData->cFileName) ) /* Is this file a download? */
      printf("<a href=\"./download.cgi?file=%s/%s\">%s</a><br>", Downsize(Directory), PFindFileData->cFileName, PFindFileData->cFileName);
    else /* Normal non-log */
      printf("<a href=\"../%s/%s\">%s</a><br>\n", Downsize(Directory), PFindFileData->cFileName, PFindFileData->cFileName);
  }
}
/*-------------------------------------------------------------------------*/
static char* Downsize(const char* Dir)
{
  /* Strip off four forward slashes */
  unsigned int i;
  char* blah = (char*)Dir;

  assert(blah);
  for ( i = 0U; i < 4; i++ ) {
    blah = strchr(blah, '/');
    if ( !blah ) break;
    blah++;
  }
  if ( !blah ) return (char*)Dir;
  return blah;
}
/*-------------------------------------------------------------------------*/
static bool CheckPass(const char* Directory, const char* Password)
{
  bool allow = false;

  if ( Directory ) {
    unsigned int i, c = sizeof(authDirs)/sizeof(authDirs[0]);

    for ( i = 0U; i < c; i++ ) {
      if ( strcmp(authDirs[i].Path, Directory) == 0 ) { /* Got correct path */
        if ( !authDirs[i].PassKey ) return true; /* No pass required! */
        if ( Password ) {
          if ( strcmp(authDirs[i].PassKey, Password) == 0 ||
               strcmp(MasterKey, Password) == 0 )
          {
            allow = true; /* OK, open the old gate */
            break;
          }
        }
      }
    }
  }
  return allow;
}
/*-------------------------------------------------------------------------*/
static bool TestExtension(const char* FileName, const char* Extension)
{
  bool ret = false;
  if ( Extension && FileName ) {
    char* extensionReversed = strdup(Extension);
    if ( extensionReversed ) {
      strrev(extensionReversed);
      ret = TestExtensionReversed(FileName, extensionReversed);
      free(extensionReversed);
    }
  }
  return ret;
}
/*-------------------------------------------------------------------------*/
static bool TestExtensionReversed(const char* FileName, const char* ExtensionReversed)
{
  bool ret = false;
  unsigned int extensionReversedLen = strlen(ExtensionReversed);
  if ( strlen(FileName) >= extensionReversedLen ) {
    char* copy = strdup(FileName);
    if ( copy ) {
      copy = strrev(copy);
      if ( strncmp(copy, ExtensionReversed, extensionReversedLen) == 0 )
        ret = true; /* Appears to be a log file */
    }
    free(copy);
  }
  return ret;
}
/*-------------------------------------------------------------------------*/
static bool TestLog(const char* FileName)
{
  if ( TestExtension(FileName, ".log") ) return true;
  return false;
}
/*-------------------------------------------------------------------------*/
static bool TestPng(const char* FileName)
{
  if ( TestExtension(FileName, ".png") ) return true;
  return false;
}
/*-------------------------------------------------------------------------*/
static bool TestDownload(const char* FileName)
{
  unsigned int i;
  const char* validExt[] = { /* Downloadable extensions */
    ".exe",
    ".zip",
    ".tar.gz",
    ".tgz",
    ".tar.bz2",
    ".bin",
    ".arc",
    ".gz"
  };

  for ( i = 0U; i < sizeof(validExt)/sizeof(validExt[0]); i++ ) {
    if ( TestExtension(FileName, validExt[i]) )
      return true;
  }
  return false;
}
/*-------------------------------------------------------------------------*/
static bool IsCurrentDir(const char* FileName)
{
  if ( strcmp(FileName, ".") == 0 )
    return true;
  return false;
}
/*-------------------------------------------------------------------------*/
static bool IsParentDir(const char* FileName)
{
  if ( strcmp(FileName, "..") == 0 )
    return true;
  return false;
}
/*-------------------------------------------------------------------------*/
static char* MakeParent(const char* Directory)
{
  char* copy = (char*)malloc(strlen(Directory)+1);
  if ( copy ) {
    char* lastBS;
    strcpy(copy, Directory);
    lastBS = strrchr(copy, (int)'/');
    if ( lastBS )
      copy[lastBS-copy] = '\0';
  }
  return copy;
}
/*-------------------------------------------------------------------------*/
int main()
{
  char* cgicmd;

  puts("Content-type: text/html\n");
  puts("<html><head>");
  /*DoTitle();*/
  puts("</head><body bgcolor=\"#CCCCCC\" text=\"#000000\" background=\"../res/misc/backdrop.jpg\" nosave><body>");
  puts("<!--lsw32 version 2.1 by David Duncan Ross Palmer -->");

  cgicmd = getenv("QUERY_STRING");
  if ( cgicmd ) {
    char* cgicmdCopy = (char*)malloc( (strlen(cgicmd)+1)*sizeof(char) );
    if ( cgicmdCopy ) {
      char *dir, *key;
      unsigned int dirLen, keyLen;

      strcpy(cgicmdCopy, cgicmd);
      cgicmdCopy = cgihelp_RFCURL_RecoverAll(cgicmdCopy); /* "Get that crap out of here" -- Duke Nukem */
      dir = cgihelp_ExtractCGIQuery(cgicmdCopy, "dir", &dirLen);
      key = cgihelp_ExtractCGIQuery(cgicmdCopy, "key", &keyLen);
      if ( dir ) {
        dir[dirLen] = '\0'; /* Terminate */
        if ( key )
          key[keyLen] = '\0';

        if ( NiceDir(dir) ) {
          if ( CheckPass(dir, key) ) {
            printf("<a href=\"../\">Daybo Logic</a> Directory listing for %s...<p>\n", Downsize(dir));
            chdir(dir);
            DoList(dir, key); /* Key is passed so that lsw32 can call itself recursively (via URLs) */
          }
          else
            puts("Restricted directory -- access denied");
        }
        else
          printf("The directory \"%s\" is not authorised for world listing or does not exist.", dir);
      }
      else
        puts("lsw32: No dir specified.");

      free(cgicmdCopy);
    }
    else
      puts("lsw32: Not enough memory to process command");
  }
  else
    puts("lsw32: No CGI command!<br>");

  puts("<p><a href=\"javascript:history.back()\">Back</a>");    
  puts("</body></html>");
  return 0;
}
/*-------------------------------------------------------------------------*/