#include <stdio.h>
#include <dbm.h>
#include <ctype.h>
#include "Error.h"
#include "Parse.h"
#include "server.h"
#include "authorize.h"

Trap setUsers(), setFile();

Keywords authorizeWords[] =
{
  { "groupfile",	setFile },
  { "users",		setUsers },
/*
  { "platforms",	setPlatforms },
  { "hosts",		setHosts },
  { "failuremsg",	setMsg },
*/
  { NULL,		NULL }
};

char *filename;
char *user;
datum userData;

typedef struct _authinfo
{
  char *s;
  int size;
  int length;
} authinfo;

/*
 * ERRORS:
 *
 * APP_DBMOPEN: FATAL
 * Couldn't open database.
 */
Trap setFile(block, line)
     MasterBlock *block;
     char *line;
{
  int len;

  while (isspace(*line)) line++;
  len = strlen(line);

  if (len)
    {
      filename = (char *)malloc(len + 1);
      if (filename != NULL)
	strcpy(filename, line);
      else
	Return(MEMORY_ALLOC, len + 1);
    }
  else
    Return(APP_BADSTRING, NULL);

  if (0 != dbminit(filename))
    Return(APP_DBMOPEN, filename);

  return OK;
}

Trap setUsers(block, line)
     MasterBlock *block;
     char *line;
{
  authinfo *info;

  if (Parse_GetCurrentData(block, AUTHINFO,
			   (caddr_t *)&info, sizeof(authinfo)))
    {
      if (Error_Severity == S_FATAL)
	return CHECK;
      else
	Error_Pop();
    }

  while (isspace(*line)) line++;

  if (*line != '\0')
    {
      if (info->size == 0)
	{
	  info->length = strlen(line);
	  info->size = info->length + 1;
	  info->s = (char *)malloc(info->size);
	  if (info->s == NULL)
	    Return(MEMORY_ALLOC, info->size);
	  strcpy(info->s, line);
	}
      else
	{
	  info->length += strlen(line) + 1; /* +1 for space */
	  info->size = info->length + 1;
	  info->s = (char *)realloc(info->size);
	  if (info->s == NULL)
	    Return(MEMORY_ALLOC, info->size);
	  strcat(info->s, " ");
	  strcat(info->s, line);
	}
    }

  return OK;
}
      
Trap Authorize_LoadInfo(what)
     Adr *what;
{
  datum key;
  user = what->user;
  key.dptr = what->user;
  key.dsize = strlen(what->user) + 1;
  userData = fetch(key);

  return OK;
}

int checkList(what, where) /* is the first string a token of the second */
     char *what, *where;
{
  int len;

  len = strlen(what);

  while (1)
    {
      while (isspace(*where)) where++;
      if (!strncasecmp(what, where, len) && where[len] == '\0')
	return 1;
      while (!isspace(*where) && *where != '\0') where++;
      if (*where == '\0')
	return 0;
    }
}

int Authorized(mb, pb)
     MasterBlock *mb;
     ParseBlock *pb;
{
  authinfo *info;
  char *ptr;

  Parse_SetCurrentBlock(mb, pb);

/* need to test for negative acls first */

/* WHAT is this doing? */
  if (Parse_GetCurrentData(mb, AUTHINFO, (caddr_t *)&info, 0))
    return 1; /* XXX think a little more before giving access? */

  if (checkList(user, info->s))  /* check if the username is specifically 
				    on the acl */
    return 1;

  ptr = userData.dptr;
  if (ptr == NULL)
    return 0;
  /* now check all the groups */
  while (ptr - userData.dptr < userData.dsize)
    {
      if (checkList(ptr, info->s))
	return 1;
      while (*ptr != '\0') ptr++;
      ptr++;
    }

  return 0;
}
