Net2/usr/src/contrib/isode/others/quipu/uips/pod/modify.c

Compare this file to the similar file:
Show the results in this format:

#include <sys/types.h>
#include <malloc.h>
#include <string.h>
#include <ctype.h>

#include "quipu/util.h"
#include "quipu/common.h"
#include "quipu/entry.h"
#include "quipu/modify.h"
#include "quipu/name.h"

#include "sequence.h"
#include "dir_entry.h"
#include "defs.h"
#include "util.h"

#define AS_SYNTAX(attrSeq) attrSeq->attr_type->oa_syntax
#define AS_STROID(attrSeq) attrSeq->attr_type->oa_ot.ot_stroid
#define FOREACH(a) for (eptr = a; eptr != NULLATTR; eptr=eptr->attr_link)

extern bool photo_on;

char *modify_error();
Attr_Sequence as_sort();
void char_map(), char_unmap();

static Attr_Sequence eptr;

#ifndef NO_STATS
extern LLog    *log_stat;
#endif

struct entrymod * ems_append (a,b)
     struct entrymod *a;
     struct entrymod *b;
{
  struct entrymod *ptr;

  if ((ptr = a) == NULLMOD)
    return b;
  
  for ( ; ptr->em_next != NULLMOD; ptr = ptr->em_next)
    ;
  
  ptr->em_next = b;
  return a;
}


dsErrorStruct modify_entry(mods)
     dirEntry mods;
{
  struct ds_modifyentry_arg mod_arg;
  dsErrorStruct mod_error;
  struct DSError error;
  struct entrymod *curr_mod = 0, *entrymods = 0;
  AttributeType attr_type = 0;
  AttributeValue attr_val = 0;
  AV_Sequence attrVal_seq = 0;
  register modVals curr_val;
  dirAttrs attrs;
  char err_buf[STRINGLEN], attr_val_buf[STRINGLEN];
  short attr_removed;
  
  if (get_default_service(&mod_arg.mea_common) != 0) {
    mod_error.error = serviceerror;
    mod_error.err_mess = strdup("Directory Service Error!\n");
  }

  mod_arg.mea_common.ca_servicecontrol.svc_options = SVC_OPT_PREFERCHAIN;
  mod_arg.mea_object = str2dn(mods->entry_name);

  for (attrs = mods->attrs; attrs; attrs = attrs->next) {
    if (attrs->mod_flag) {
      attr_type = str2AttrT(attrs->attr_name);

      for (curr_val = attrs->val_seq; 
	   curr_val && curr_val->mod_flag;
	   curr_val = curr_val->next)
	;

      if (!curr_val) {
	if (attrs->in_flag) {
	  curr_mod = em_alloc();
	  curr_mod->em_next = NULLMOD;
	  curr_mod->em_type = EM_REMOVEATTRIBUTE;
	  curr_mod->em_what = NULLATTR;
	  
	  curr_mod->em_what = as_comp_new(attr_type, NULLAV, NULLACL_INFO);
	  entrymods = ems_append(entrymods, curr_mod);
	}

	curr_mod = em_alloc();
	curr_mod->em_next = NULLMOD;
	curr_mod->em_type = EM_ADDATTRIBUTE;
	curr_mod->em_what = NULLATTR;
	
	for (curr_val = attrs->val_seq; curr_val; curr_val = curr_val->next) {
	  char_unmap(attr_val_buf, curr_val->new_value);
	  if (attr_val_buf[0] != '\0') {
	    attr_val = str2AttrV(attr_val_buf, attr_type->oa_syntax);
	    if (attr_val) {
	      if (attrVal_seq) 
		attrVal_seq = avs_merge(attrVal_seq, avs_comp_new(attr_val));
	      else 
		attrVal_seq = avs_comp_new(attr_val);
	    } else {
	      if (entrymods) ems_free(entrymods);
	      AttrT_free(attr_type);
	      mod_error.error = attributerror;
	      (void) sprintf(err_buf,
		     "Attribute Error!\nInvalid syntax for value %s type %s.", 
		      curr_val->new_value, attrs->attr_name);
	      mod_error.err_mess = strdup(err_buf);
	      return mod_error;
	    }
	  }
	}

	if (attrVal_seq) {
	  curr_mod->em_what = as_comp_new(AttrT_cpy(attr_type),
					  attrVal_seq, 
					  NULLACL_INFO);
	  entrymods = ems_append(entrymods, curr_mod);
	  attrVal_seq = 0;
	  curr_mod = 0;
	  AttrT_free(attr_type);
	}
      } else {
	if (attrs->in_flag) {
	  for (curr_val = attrs->val_seq;
	       curr_val;
	       curr_val = curr_val->next) {
	    char_unmap(attr_val_buf, curr_val->value);
	    if (curr_val->mod_flag && attr_val_buf[0] != '\0') {
	      attrVal_seq = avs_comp_new(str2AttrV(attr_val_buf,
						   attr_type->
						   oa_syntax));
	      curr_mod = em_alloc();
	      curr_mod->em_next = NULLMOD;
	      curr_mod->em_type = EM_REMOVEVALUES;
	      curr_mod->em_what = as_comp_new(AttrT_cpy(attr_type),
					      attrVal_seq,
					      NULLACL_INFO);
	      entrymods = ems_append(entrymods, curr_mod);
	    }
	  }
	  
	  for (curr_val = attrs->val_seq;
	       curr_val;
	       curr_val = curr_val->next) {
	    char_unmap(attr_val_buf, curr_val->new_value);
	    if (curr_val->mod_flag && attr_val_buf[0] != '\0') {
	      attr_val = str2AttrV(attr_val_buf, 
				   attr_type->oa_syntax);
	      if (attr_val) {
		if (attrVal_seq) 
		  attrVal_seq = avs_merge(attrVal_seq, 
					  avs_comp_new(attr_val));
		else 
		  attrVal_seq = avs_comp_new(attr_val);
	      } else {
		if (entrymods) ems_free(entrymods);
		AttrT_free(attr_type);
		mod_error.error = attributerror;
		(void) sprintf(err_buf,
		     "Attribute Error!\nInvalid syntax for value %s type %s.", 
		      curr_val->new_value, attrs->attr_name);
		mod_error.err_mess = strdup(err_buf);
		return mod_error;
	      }

	      curr_mod = em_alloc();
	      curr_mod->em_next = NULLMOD;
	      curr_mod->em_type = EM_ADDVALUES;
	      curr_mod->em_what = as_comp_new(AttrT_cpy(attr_type),
					      attrVal_seq,
					      NULLACL_INFO);
	      entrymods = ems_append(entrymods, curr_mod);
	    }
	  }
	} else {
	  curr_mod = em_alloc();
	  curr_mod->em_next = NULLMOD;
	  curr_mod->em_type = EM_ADDATTRIBUTE;
	  
	  for (curr_val = attrs->val_seq; 
	       curr_val; 
	       curr_val = curr_val->next) {
	    char_unmap(attr_val_buf, curr_val->new_value);
	    if (attr_val_buf[0] != '\0') {
	      attr_val = str2AttrV(attr_val_buf, 
				   attr_type->oa_syntax);
	      if (attr_val) {
		if (attrVal_seq) 
		  attrVal_seq = avs_merge(attrVal_seq, 
					  avs_comp_new(attr_val));
		else 
		  attrVal_seq = avs_comp_new(attr_val);
	      } else {
		if (entrymods) ems_free(entrymods);
		AttrT_free(attr_type);
		mod_error.error = attributerror;
		(void) sprintf(err_buf,
		     "Attribute Error!\nInvalid syntax for value %s type %s.", 
		      curr_val->new_value, attrs->attr_name);
		mod_error.err_mess = strdup(err_buf);
		return mod_error;
	      }
	    }
	  }

	  if (attrVal_seq) {
	    curr_mod->em_what = as_comp_new(AttrT_cpy(attr_type),
					    attrVal_seq, 
					    NULLACL_INFO);
	    entrymods = ems_append(entrymods, curr_mod);
	    attrVal_seq = 0;
	    curr_mod = 0;
	    AttrT_free(attr_type);
	  }
	}
      }
    }
  }

  if (entrymods) {
    mod_arg.mea_changes = entrymods;
    if (ds_modifyentry(&mod_arg, &error) != DS_OK) {
      mod_error.err_mess = modify_error(&error);

      switch (error.dse_type) {
      case DSE_LOCALERROR:
	mod_error.error = duaerror;
	if (!mod_error.err_mess) {
	  mod_error.err_mess = 
	    strdup("Internal Error, No modifications made. Sorry!");
	}
	break;
	
      case DSE_REMOTEERROR:
	mod_error.error = localdsaerror;
	break;
	
      case DSE_ATTRIBUTEERROR:
	mod_error.error = attributerror;
	if (!mod_error.err_mess) {
	  mod_error.err_mess = 
	    strdup("Attribute Error! No Modifications made.");
	}
	break;

      case DSE_REFERRAL:
      case DSE_DSAREFERRAL:
	mod_error.error = remotedsaerror;
	if (!mod_error.err_mess) {
	  mod_error.err_mess = 
	    strdup("Referral Error! No Modifications made.");
	}
	break;

      case DSE_SECURITYERROR:
	mod_error.error = security;
	if (!mod_error.err_mess) {
	  mod_error.err_mess = strdup("Security Error! Check access rights.");
	}
	break;

      case DSE_NAMEERROR:
	mod_error.error = namerror;
	if (!mod_error.err_mess) {
	  switch (error.dse_un.dse_un_name.DSE_na_problem) {
	  case DSE_NA_NOSUCHOBJECT:
	    mod_error.err_mess = 
	      strdup("Name Error! No such object.");
	    break;
	  case DSE_NA_ALIASPROBLEM:
	  case DSE_NA_ALIASDEREFERENCE:
	    mod_error.err_mess = strdup("Error! Alias problem.");
	    break;
	  case DSE_NA_INVALIDATTRIBUTESYNTAX:
	    mod_error.err_mess = 
	      strdup("Name Error! Invalid attribute syntax.");
	    break;
	  }
	}
	break;
	
      case DSE_SERVICEERROR:
	mod_error.error = serviceerror;
	break;
	
      case DSE_UPDATEERROR:
	mod_error.error = updaterror;
	break;
	
      default:
	mod_error.error = localdsaerror;
	break;
      }
      ds_error_free(&error);
      dn_free(mod_arg.mea_object);
      return mod_error;
    } else {
      ems_free(entrymods);
      delete_cache(mod_arg.mea_object);
    }
  } else {
    mod_error.error = updaterror;
    mod_error.err_mess = strdup("No modifications to make!");
    dn_free(mod_arg.mea_object);
    return mod_error;
  }

  for (attrs = mods->attrs; attrs; attrs = attrs->next) {
    if (attrs->mod_flag == TRUE && attrs->in_flag == FALSE) 
      attrs->in_flag = TRUE;
    attrs->mod_flag = FALSE;

    attr_removed = TRUE;
    for (curr_val = attrs->val_seq; curr_val; curr_val = curr_val->next) {
      if (curr_val->new_value != NULLCP) {
	if (curr_val->value != NULLCP) free(curr_val->value);
	curr_val->value = curr_val->new_value;
	curr_val->new_value = NULLCP;
	attr_removed = FALSE;
      }

      if (curr_val->value && *curr_val->value != '\0' && !curr_val->mod_flag)
	attr_removed = FALSE;

      curr_val->mod_flag = FALSE;
    }
    if (attr_removed) attrs->in_flag = FALSE;
  }
  mod_error.error = Okay;
  dn_free(mod_arg.mea_object);
  return mod_error;
}	  
  

void make_template(entry_name, attrs)
     char *entry_name;
     dirAttrs *attrs;
{
  static char buffer[RESBUF];
  PS ps;
  extern AttributeType at_objectclass;
  struct ds_read_arg read_arg;
  struct ds_read_result   result;
  struct DSError          error;
  Entry read_entry;
  Attr_Sequence   as, read_attrs;
  Attr_Sequence   nas = 0, tas = 0, templ_as, make_template_as();

  buffer[0] = '\0';
  *attrs = 0;

  if (*entry_name == '\0') return;

  if ((ps = ps_alloc(str_open)) == NULLPS) return;
  if (str_setup(ps, buffer, RESBUF, 1) == NOTOK) return;

  if (get_default_service (&read_arg.rda_common) != 0) return;

  read_arg.rda_common.ca_servicecontrol.svc_options = SVC_OPT_PREFERCHAIN;
  read_arg.rda_eis.eis_allattributes = TRUE;
  read_arg.rda_eis.eis_infotypes = EIS_ATTRIBUTESANDVALUES;
  
  read_arg.rda_object = str2dn(entry_name);

  photo_on = FALSE;
  
  if ((read_entry = local_find_entry(read_arg.rda_object, FALSE))
      != NULLENTRY &&
      read_entry->e_data != E_TYPE_CONSTRUCTOR) {
    read_attrs = read_entry->e_attributes;
  } else {
    if (ds_read(&read_arg, &error, &result) != DS_OK) {
      photo_on = TRUE;
      return;
    }
    if (result.rdr_entry.ent_attr == NULLATTR) {
      photo_on = TRUE;
      return;
    }

    read_attrs = result.rdr_entry.ent_attr;
  }

  for (as = read_attrs; as != NULLATTR; as = as->attr_link)
    if (as->attr_type == at_objectclass)
      break;

  templ_as = make_template_as(as->attr_value);
  
  for (as = read_attrs; 
       as != NULLATTR; 
       as = as->attr_link)
    if (!(AS_SYNTAX(as) == str2syntax("schema") ||
	  AS_SYNTAX(as) == str2syntax("objectclass") ||
	  AS_SYNTAX(as) == str2syntax("acl") ||
	  AS_SYNTAX(as) == str2syntax("edbinfo") ||
	  AS_SYNTAX(as) == str2syntax("octetstring") ||
	  !strcmp(AS_STROID(as), "0.9.2342.19200300.100.1.23") ||
	  !strcmp(AS_STROID(as), "0.9.2342.19200300.100.1.24"))) {
      nas = as_comp_new(AttrT_cpy(as->attr_type), 
			avs_cpy(as->attr_value),
			NULLACL_INFO);
      if (tas) tas = as_merge(tas, nas);
      else tas = nas;
    }

  as = templ_as;
  nas = templ_as = 0;
  for (; as != NULLATTR; as = as->attr_link)
    if (!(AS_SYNTAX(as) == str2syntax("schema") ||
          AS_SYNTAX(as) == str2syntax("objectclass") ||
          AS_SYNTAX(as) == str2syntax("acl") ||
          AS_SYNTAX(as) == str2syntax("edbinfo") ||
          AS_SYNTAX(as) == str2syntax("octetstring") ||
	  !strcmp(AS_STROID(as), "0.9.2342.19200300.100.1.23") ||
	  !strcmp(AS_STROID(as), "0.9.2342.19200300.100.1.24"))) {
      nas = as_comp_new(AttrT_cpy(as->attr_type), NULLAV, NULLACL_INFO);
      if (templ_as) templ_as = as_merge(templ_as, nas);
      else templ_as = nas;
    }

  as = as_merge(tas, templ_as);
  as = as_sort(as);
  
  my_as_print(ps, as, READOUT);
  *--ps->ps_ptr = NULL, ps->ps_cnt++;

  photo_on = TRUE;

  ps_free(ps);
  as_free(as);
  
  make_attr_sequence(buffer, attrs);
}

make_attr_sequence(entry_string, attrs)
     char *entry_string;
     dirAttrs *attrs;
{
  register char *str, *sptr;
  char save, buffer[RESBUF];
  modVals curr_val = 0;
  dirAttrs curr_attr = 0;
  AttributeType curr_attr_type;
  int count = 0;

  str = sptr = entry_string;
  while (1) {
    str = index(sptr, '-');
    if (!str || str == sptr) return;
    while (!isalpha(*str)) {
      if (str < sptr) return;
      else --str;
    }
    str++;

    save = *str;
    *str = '\0';
    
    if (curr_attr) {
      if (strcmp(curr_attr->attr_name, sptr)) {
	curr_val = 0;
	curr_attr->next = (dirAttrs) malloc(sizeof(dir_attrs));
	curr_attr = curr_attr->next;

	curr_attr->next = 0;
	curr_attr->val_seq = 0;
	curr_attr->mod_flag = FALSE;
	curr_attr->in_flag = TRUE;

	curr_attr->attr_name = strdup(sptr);

	curr_attr_type = str2AttrT(curr_attr->attr_name);
	if (!strcmp(curr_attr_type->oa_ot.ot_stroid, "2.5.4.35"))
	  curr_attr->hidden_flag = TRUE;
	else
	  curr_attr->hidden_flag = FALSE;
	AttrT_free(curr_attr_type);
      }
    } else {
      curr_attr = (dirAttrs) malloc(sizeof(dir_attrs));
      *attrs = curr_attr;

      curr_attr->next = 0;
      curr_attr->val_seq = (modVals) 0;
      curr_attr->mod_flag = FALSE;
      curr_attr->in_flag = TRUE;

      curr_attr->attr_name = strdup(sptr);

      curr_attr_type = str2AttrT(curr_attr->attr_name);
      if (!strcmp(curr_attr_type->oa_ot.ot_stroid, "2.5.4.35"))
	curr_attr->hidden_flag = TRUE;
      else
	curr_attr->hidden_flag = FALSE;
      AttrT_free(curr_attr_type);
    }
    
    *str = save;
    while ((isspace(*str) || (*str == '-')) && *str != '\n' && *str != '\0') 
      str++;

    sptr = str;
    count = 0;

    while (1) {
      while (*str != '\n' && *str != '\0') {
	buffer[count++] = *str;
	str++;
      }
      if (*str != '\0' && *(str + 1) == '\t') {
	buffer[count++] = '\n';
	while (isspace(*str)) str++;
      } else break;
    }

    buffer[count] = '\0';
    save = *str;
    *str = '\0';

    if (curr_val) {
      curr_val->next = (modVals) malloc(sizeof(struct mod_vals));
      curr_val = curr_val->next;
    } else {
      curr_val = (modVals) malloc(sizeof(struct mod_vals));
      curr_attr->val_seq = curr_val;

      if (!count) curr_attr->in_flag = FALSE;
    }
    curr_val->attr = curr_attr;
    curr_val->next = 0;
    curr_val->mod_flag = FALSE;
    curr_val->new_value = 0;
    curr_val->text_widg = 0;

    curr_val->value = strdup(buffer);
    char_map(buffer, curr_val->value);
    free(curr_val->value);
    curr_val->value = strdup(buffer);

    *str = save;
    if (*str == '\0' || *++str == '\0') return;
    sptr = str;
  }
}

void char_map(buffer, value)
     char *buffer, *value;
{
  if (value != NULLCP && *value != '\0') {
    while (*value != '\0') {
      switch (*value) {
      case '$':
	*buffer = '\n';
	break;
      case '\\':
	if (*((char *) (value + 1)) == '4' && 
	    *((char *) (value + 2)) == '0') {
	  *buffer = '@';
	  value += 2;
	}
	break;
      default:
	*buffer = *value;
      }
      value++;
      buffer++;
    }
  }
  
  *buffer = '\0';
}

void char_unmap(buffer, value)
     char *buffer, *value;
{
  if (value != NULLCP && *value != '\0') {
    while (*value != '\0') {
      switch (*value) {
      case '\n':
	*buffer = '$';
	break;
      default:
	*buffer = *value;
      }
      value++;
      buffer++;
    }
  }

  *buffer = '\0';
}
    

Attr_Sequence make_template_as(oc)
     AV_Sequence oc;
{
  AV_Sequence avs;
  Attr_Sequence newas;
  Attr_Sequence as = NULLATTR;
  table_seq optr;
  AttributeType at;
  objectclass * ocp;
  
  for (avs = oc; avs != NULLAV; avs = avs->avseq_next) {
    ocp = (objectclass *) avs->avseq_av.av_struct;
    for (optr = ocp->oc_must; optr != NULLTABLE_SEQ; optr = optr->ts_next) {
      at = optr->ts_oa;
      newas = as_comp_new(at, NULLAV, NULLACL_INFO);
      as = as_merge(as, newas);
    }
  }
  
  for (avs = oc; avs != NULLAV; avs = avs->avseq_next) {
    ocp = (objectclass *) avs->avseq_av.av_struct;
    for (optr = ocp->oc_may; optr != NULLTABLE_SEQ; optr = optr->ts_next) {
      at = optr->ts_oa;
      newas = as_comp_new(at, NULLAV, NULLACL_INFO);
      as = as_merge(as, newas);
    }
  }
  return(as);
}

/*Big Bodge!*/
char *modify_error(error)
     struct DSError *error;
{
  PS ps;
  char buffer[RESBUF];
  char *str, *message;
  
  if ((ps = ps_alloc(str_open)) == NULLPS) {
    return NULLCP;
  }

  if (str_setup(ps, buffer, RESBUF, 1) == NOTOK) {
    return NULLCP;
  }

  ds_error(ps, error);
  *ps->ps_ptr = 0;
  ps_free(ps);

  str = buffer;

  if (*str != '\0') {
    message = strdup(str);
  } else message = NULLCP;

  return message;
}

  
my_as_comp_print (ps,as,format)
     PS   ps;
     Attr_Sequence  as;
     int  format;
{
  AV_Sequence avs;
  char buffer[RESBUF];
  extern int oidformat;
  
  if (as!=NULLATTR) {
      if (format == READOUT)
	(void) sprintf(buffer,"%s",attr2name (as->attr_type, 1));
      else
	(void) sprintf (buffer,"%s",attr2name_aux (as->attr_type));
    
    if (split_attr (as)) {
      if ((as->attr_value == NULLAV) && (format != READOUT)) 
	ps_printf (ps, "%s=\n", buffer);
      else {
	if (as->attr_value == NULLAV) {
	  ps_printf(ps, "%-21s - \n", buffer);
	} else {
	  for (avs = as->attr_value; avs != NULLAV; avs = avs->avseq_next) {
	    if (format == READOUT)
	      ps_printf (ps, "%-21s - ", buffer);
	    else
	      ps_printf (ps, "%s= ", buffer);
	    avs_comp_print (ps, avs, EDBOUT);
	  ps_print (ps, "\n");
	  }
	}
      }
    } else {
      if (format == READOUT)
	ps_printf (ps, "%-21s - ", buffer);
      else
	ps_printf (ps, "%s= ", buffer);
      avs_print (ps, as->attr_value, format);
    }
  }
}

my_as_print (ps,as,format)
Attr_Sequence  as;
PS   ps;
int  format;
{
  if (as != NULLATTR)
    FOREACH(as)
      my_as_comp_print(ps,eptr,format);
}

Attr_Sequence as_sort(as)
     Attr_Sequence as;
{
  Attr_Sequence with_vals = NULLATTR, without_vals = NULLATTR, next_as;

  if (as == NULLATTR) return as;

  while (as != NULLATTR) {
    next_as = as->attr_link;
    as->attr_link = NULLATTR;

    if (as->attr_value) with_vals = as_merge(with_vals, as);
    else without_vals = as_merge(without_vals, as);
    
    as = next_as;
  }

  as = with_vals;

  if (as != NULLATTR) 
    for (; as->attr_link != NULLATTR; as = as->attr_link)
      ;
  else return without_vals;

  as->attr_link = without_vals;
  return with_vals;
}