/*
 * Copyright (c) 2003-2012
 * Distributed Systems Software.  All rights reserved.
 * See the file LICENSE for redistribution information.
 *
 * $Id: group.h 2594 2012-10-19 17:28:49Z brachman $
 */

/*****************************************************************************
 * COPYRIGHT AND PERMISSION NOTICE
 * 
 * Copyright (c) 2001-2003 The Queen in Right of Canada
 * 
 * All rights reserved.
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation 
 * the rights to use, copy, modify, merge, publish, distribute, and/or sell
 * copies of the Software, and to permit persons to whom the Software is 
 * furnished to do so, provided that the above copyright notice(s) and this
 * permission notice appear in all copies of the Software and that both the
 * above copyright notice(s) and this permission notice appear in supporting
 * documentation.
 * 
 * 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 OF THIRD PARTY RIGHTS.
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE 
 * BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES,
 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
 * SOFTWARE.
 * 
 * Except as contained in this notice, the name of a copyright holder shall not
 * be used in advertising or otherwise to promote the sale, use or other
 * dealings in this Software without prior written authorization of the
 * copyright holder.
 ***************************************************************************/

#ifndef _GROUPS_H_
#define _GROUPS_H_

#include "auth.h"
#include "local.h"

/*************************************************************************/

/* Corresponds to a "group_member" element. */
typedef enum {
	GROUP_MEMBER_TYPE_ROLE     = 0,
	GROUP_MEMBER_TYPE_NFIS     = 1,
	GROUP_MEMBER_TYPE_USERNAME = 2,
	GROUP_MEMBER_TYPE_META     = 3
} Group_member_type;

static char MAYBE_UNUSED *Group_member_type_symbols[] = {
  "role", "dacs", "username", "meta", NULL
};

typedef struct Group_member {
  char *jurisdiction;
  char *name;
  char *type;
  char *alt_name;
  char *dacs_url;
  char *authenticates;
  char *prompts;
  char *auxiliary;
  char *public_key_str;
  EVP_PKEY *public_key;
  char *public_key_pem;
  struct Group_member *next;
} Group_member;

/* Corresponds to a "group_definition" element. */
typedef enum {
  GROUP_DEFINITION_TYPE_PRIVATE = 0,
  GROUP_DEFINITION_TYPE_PUBLIC  = 1
} Group_definition_type;

static char MAYBE_UNUSED *Group_definition_type_symbols[] = {
  "private", "public", NULL
};

typedef struct Group_definition {
  char *jurisdiction;
  char *name;
  char *mod_date;
  char *type;
  Group_member *group_member_head;
  struct Group_definition *next;
} Group_definition;

/* Corresponds to a "groups" element. */
typedef struct Groups {
  struct Group_definition *group_definition_head;
} Groups;

typedef enum Parse_xml_groups_state_code {
	GROUPS_PARSE_GROUPS           = 1,
	GROUPS_PARSE_GROUP_DEFINITION = 2,
	GROUPS_PARSE_GROUP_MEMBER     = 3,
	GROUPS_PARSE_GROUP_NAME       = 4
} Parse_xml_groups_state_code;

typedef struct Parse_xml_groups_state {
  Parse_xml_groups_state_code code;
  union {
	Groups *groups;
	Group_definition *group_definition;
	Group_member *group_member;
	Group_name *group_name;
  } object;
} Parse_xml_groups_state;

/*************************************************************************/

typedef enum {
  GROUP_DELTAS_TYPE_REPLACE    = 0,
  GROUP_DELTAS_TYPE_ADD_DELETE = 1
} Group_deltas_type;

static char MAYBE_UNUSED *Group_deltas_type_symbols[] = {
  "replace", "add_delete", NULL
};

typedef struct Group_meta_update {
  char *newname;
} Group_meta_update;

typedef struct Group_delete_member {
  char *jurisdiction;
  char *name;
} Group_delete_member;

typedef struct Group_add_delete {
  Group_member *group_member;
  Group_delete_member *group_delete_member;
  struct Group_add_delete *next;
} Group_add_delete;

typedef struct Group_deltas {
  char *jurisdiction;
  char *name;
  char *type;
  char *timestamp;
  Group_meta_update *group_meta_update;
  Group_add_delete *group_add_delete;
} Group_deltas;

typedef enum Parse_xml_group_deltas_state_code {
	GROUPS_PARSE_GROUP_DELTAS        = 1
} Parse_xml_group_deltas_state_code;

typedef struct Parse_xml_group_deltas_state {
  Parse_xml_group_deltas_state_code code;
  union {
	Group_deltas *group_deltas;
  } object;
} Parse_xml_group_deltas_state;

/*************************************************************************/

typedef struct Jurisdiction {
  char *jname;
  char *name;
  char *alt_name;
  char *dacs_url;
  char *authenticates;
  char *prompts;
  char *auxiliary;
  char *public_key_str;
  EVP_PKEY *public_key;
  char *public_key_pem;
} Jurisdiction;

typedef struct Group_file {
  char *path;
  Group_name group_name;
  time_t mod_date;
  Group_definition_type type;
} Group_file;

static inline MAYBE_UNUSED mode_t
set_public_group_mode(mode_t mode)
{

  return(mode & ~GROUPS_PRIVATE_MODE_BIT);
}

static inline MAYBE_UNUSED mode_t
set_private_group_mode(mode_t mode)
{

  return(mode | GROUPS_PRIVATE_MODE_BIT);
}

static inline MAYBE_UNUSED int
is_public_group_mode(mode_t mode)
{

  return((mode & GROUPS_PRIVATE_MODE_BIT) == 0);
}

static inline MAYBE_UNUSED int
is_private_group_mode(mode_t mode)
{

  return((mode & GROUPS_PRIVATE_MODE_BIT) != 0);
}

typedef struct Roles_list {
  Credentials *cr;
  Group_name **group_names;
  struct Roles_list *next;
} Roles_list;

extern Jurisdiction *jurisdictions;
extern int njurisdictions;

#ifdef __cplusplus
extern "C" {
#endif

extern char *make_group_pathname(char *jurisdiction, char *name);
extern char *make_group_itemname(char *jurisdiction, char *name);
extern int is_valid_name(const char *name);
extern int load_jurisdictions(void);
extern int get_group_list(Dsvec **);
extern int refresh_group_list(Dsvec **gf);
extern int load_group(char *jurisdiction, char *name, char **buf);
extern int parse_xml_groups(char *str, Groups **groups);
extern void add_group_member_to_group(Group_definition *gd, Group_member *gm);
extern int set_mod_date(Group_definition *gd);
extern int store_group_file(Groups *groups, char *jurisdiction, char *name);
extern int delete_group_member_from_group(Group_definition *gd,
										  char *jurisdiction, char *name);
extern void groups_xml_html(FILE *fp, Groups *groups);
extern int is_valid_federation_name(char *federation);
extern int is_valid_jurisdiction_name(char *jurisdiction);
extern int exists_group(char *jurisdiction, char *name);
extern Group_name *make_group_name_from_str(Group_name *gn, const char *str);
extern int is_valid_group_name(Group_name *gn);
extern int groups_xml_text(FILE *fp, Groups *groups);
extern int parse_xml_group_deltas(char *str, Group_deltas **group_deltas);
extern int rename_group_file(char *jurisdiction, char *oldname, char *newname);
extern int group_member_name_from_str(const char *str, char **jurisdiction,
									  char **name);
extern Group_name **make_group_names_from_role_str(char *jurisdiction,
												   char *role_str);
extern void add_group_to_groups(Groups *groups, Group_definition *gd);
extern char *groups_xml_text_to_buf(Groups *groups);
extern int get_jurisdiction_meta(char *jurisdiction, Jurisdiction **jp);

extern int is_group_member(char *jname, char *uname, Group_name **roles,
						   char *jurisdiction, char *name);
extern int has_unauth_role(char *role_str, char *jurisdiction, char *name);

#ifdef __cplusplus
}
#endif

#endif
