/***************************************
  $Revision: 1.21 $

  NT (Notifications) module

  Status: NOT REVIEWED, NOT TESTED

  Author(s):       Engin Gunduz

  ******************/ /******************
  Modification History:
        engin (06/07/2000) Created.
  ******************/ /******************
  Copyright (c) 2000                              RIPE NCC
 
  All Rights Reserved
  
  Permission to use, copy, modify, and distribute this software and its
  documentation for any purpose and without fee is hereby granted,
  provided that the above copyright notice appear in all copies and that
  both that copyright notice and this permission notice appear in
  supporting documentation, and that the name of the author not be
  used in advertising or publicity pertaining to distribution of the
  software without specific, written prior permission.
  
  THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
  AUTHOR BE LIABLE FOR 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.
 ***************************************/






#include "notification.h"
extern int supress_ack_notif;
extern char * defmail;
extern int reading_from_mail;
extern char * forwlog;

/*  Generates a unique file name and returns the full path of the filename 
    for storing notification message.  Creates the file at the same time. 
    May use PID or time or both to ensure uniqueness.  */
      
char * NT_ntfy_filename_generate( const char * tmpdir, const char * e_mail){

   FILE * ntfy_file;
   char * name;
   char * replaced_notimailtxt;
   char * replaced_notinetworktxt;
       
   /* allocate space for name.  32 should be enough for PID */
   name = (char*)malloc(strlen(tmpdir) + strlen(e_mail) + strlen("notify") +32 ); 
   
   sprintf(name, "%s/%s-%s.%i", tmpdir, "notify", e_mail, getpid());

   /* create the file */
   if(( ntfy_file = fopen(name, "w")) == NULL){
     fprintf(stderr, "Can't open notification file for creating, %s", name);
   }

   fprintf(ntfy_file, "To: %s\nFrom: %s\nSubject: Notification of RIPE Database changes\nReply-To: %s\n\n%s\n", e_mail, humailbox, humailbox, notitxt);
   if(reading_from_mail){
     replaced_notimailtxt = UP_replace_globals(notimailtxt);
     fprintf(ntfy_file, "%s\n\n", replaced_notimailtxt);
     free(replaced_notimailtxt);
   }

   if(networkupdate){
     replaced_notinetworktxt = UP_replace_globals(notinetworktxt);
     fprintf(ntfy_file, "%s\n\n", replaced_notinetworktxt);
     free(replaced_notinetworktxt);
   }
   
   /* close it */
   fclose(ntfy_file);
    
   return name;
      
}





/* Generates a unique file name and returns the full path of the filename 
   for storing forwarded message. Creates the file at the same time.  */ 
char * NT_forwd_filename_generate( const char * tmpdir, const char * e_mail){

   FILE * forwd_file;
   char * name;
   char * replaced_fwmailtxt;
          
   /* allocate space for name.  32 should be enough for PID */
   name = (char*)malloc(strlen(tmpdir) + strlen(e_mail) + strlen("forwd") +32 ); 
   
   sprintf(name, "%s/%s-%s.%i", tmpdir, "forwd", e_mail, getpid());
   /* create the file */
   if(( forwd_file = fopen(name, "w")) == NULL){
     fprintf(stderr, "Can't open forward file, %s", name);
   }

   fprintf(forwd_file, "To: %s\nFrom: %s\nSubject:  Requested RIPE database object changes \nReply-To: %s\n\n%s\n", e_mail, humailbox, humailbox, fwtxt);
   if(reading_from_mail){
     replaced_fwmailtxt = UP_replace_globals(fwmailtxt);
     fprintf(forwd_file, "\n%s\n", replaced_fwmailtxt);
     free(replaced_fwmailtxt);
   }

   /* close it */
   fclose(forwd_file);
    
   return name;

}





/* Generates a unique file name and returns the full path of the filename 
   for storing cross notification message. Creates the file at the same time.  */ 
char * NT_cross_filename_generate( const char * tmpdir, const char * e_mail, int mode){

   FILE * cross_file;
   char * name;
      
   /* allocate space for name.  32 should be enough for PID */
   name = (char*)malloc(strlen(tmpdir) + strlen(e_mail) + strlen("cross") +32 ); 
   
   sprintf(name, "%s/%s-%s.%i", tmpdir, "cross", e_mail, getpid());
   /* create the file */
   if(( cross_file = fopen(name, "w")) == NULL){
     fprintf(stderr, "Can't open cross notif file, %s", name);
   }

   if(mode == ADDITION){
     fprintf(cross_file, "To: %s\nFrom: %s\n%s\nReply-To: %s\n\n", e_mail, humailbox, cno_subject_add, humailbox);
   }else{
     fprintf(cross_file, "To: %s\nFrom: %s\n%s\nReply-To: %s\n\n", e_mail, humailbox, cno_subject_del, humailbox);
   }
   
   /* close it */
   fclose(cross_file);
    
   return name;

}







/* Generates a unique file name and returns the full path of the filename for 
   storing notification message. Creates the file at the same time.  */
char * NT_crossntfy_filename_generate( const char * tmpdir, const char * e_mail){
   FILE * cross_file;
   char * name;
      
   /* allocate space for name.  32 should be enough for PID */
   name = (char*)malloc(strlen(tmpdir) + strlen(e_mail) + strlen("cross") +32 ); 
   
   sprintf(name, "%s/%s-%s.%i", tmpdir, "cross", e_mail, getpid());

   /* create the file */
   if(( cross_file = fopen(name, "w")) == NULL){
     fprintf(stderr, "Can't open cross file, %s", name);
   }

   /* close it */
   fclose(cross_file);
    
   return name;

}





/* Adds the e-mail to the notify hash, generating appropriate temp files */
void NT_add_to_ntfy_hash(GHashTable * ntfy_hash, char * e_mail){

  if(g_hash_table_lookup(ntfy_hash ,e_mail) == NULL){/* there is no such entry, so create it */

    g_hash_table_insert(ntfy_hash, strdup(e_mail), NT_ntfy_filename_generate(tmpdir, e_mail));

  }

}




/* Adds the e-mail to the forw hash, generating appropriate temp files */
void NT_add_to_frwd_hash(GHashTable * frwd_hash, char * e_mail){

  if(g_hash_table_lookup(frwd_hash ,e_mail) == NULL){/* there is no such entry, so create it */
    g_hash_table_insert(frwd_hash, strdup(e_mail), NT_forwd_filename_generate(tmpdir, e_mail));
  }
    
}





/* Adds the e-mail to the cross hash, generating appropriate temp files */
void NT_add_to_cross_hash(GHashTable * cross_hash, const char * e_mail, int mode){

  /*  if e-mail is NULL, immediately return */
  if(e_mail == NULL){
    return;
  }

  if(g_hash_table_lookup(cross_hash ,e_mail) == NULL){/* there is no such entry, so create it */
    g_hash_table_insert(cross_hash, strdup(e_mail), NT_cross_filename_generate(tmpdir, e_mail, mode));
  }
    
}





/* Adds the e-mails in a linked list to the hash */
void NT_add_to_ntfy_hash_list(GHashTable * ntfy_hash, GSList * e_mail_list){

   GSList * temp = NULL;

   for(temp = e_mail_list; temp != NULL; temp = g_slist_next(temp)){
     NT_add_to_ntfy_hash(ntfy_hash, (char *)temp->data);
   }
  
}




/* Adds the e-mails in a linked list to the hash */
void NT_add_to_frwd_hash_list(GHashTable * frwd_hash, GSList * e_mail_list){

   GSList * temp = NULL;

   for(temp = e_mail_list; temp != NULL; temp = g_slist_next(temp)){
     NT_add_to_frwd_hash(frwd_hash, (char *)temp->data);
   }
  
}



/* Adds the e-mails in a linked list to the hash */
void NT_add_to_cross_hash_list(GHashTable * cross_hash, GSList * e_mail_list, int mode){

   GSList * temp = NULL;

   for(temp = e_mail_list; temp != NULL; temp = g_slist_next(temp)){
     NT_add_to_cross_hash(cross_hash, (char *)temp->data, mode);
   }
  
}






/* Appends the argument strings to the file.  */
void NT_add_to_ntfy( char * filename, char * fmt, ... ){
  va_list ap;  /* points to each unnamed arg in turn */
  FILE * ntfy_file;
 
  if(tracing){
    printf("TRACING: NT_add_to_ntfy\n"); 
  }
  if(( ntfy_file = fopen(filename, "a")) == NULL){
    fprintf(stderr, "Can't open notification file for writing, %s\n", filename);
    return;
  }
    
  va_start(ap, fmt);
  vfprintf(ntfy_file, fmt, ap);

  va_end(ap); /* clean up */
  fclose(ntfy_file);
}



/* Appends the argument strings to the file.  */
void NT_add_to_cross(const char * e_mail, GHashTable * hash, char * fmt, ...){

  va_list ap;  /* points to each unnamed arg in turn */
  FILE * cross_file;
  char * filename;

  /* if e-mail is NULL, immediately return */
  if(e_mail == NULL){
    return;
  }
   
  if(g_hash_table_lookup(hash, find_email_address(e_mail)) != NULL){
    filename = (char *)g_hash_table_lookup(hash, find_email_address(e_mail));
  }else{
    fprintf(stderr, "Can't find a cross notification file for e-mail %s\n", e_mail);
    return;
  }

  if(( cross_file = fopen(filename, "a")) == NULL){
    fprintf(stderr, "Can't open cross notification file, %s\n", filename);
  }
  
 
   
  if(tracing){
    printf("TRACING: NT_add_to_cross\n"); 
  }
  if(( cross_file = fopen(filename, "a")) == NULL){
    fprintf(stderr, "Can't open cross notification file for writing, %s\n", filename);
  }
    
  va_start(ap, fmt);
  vfprintf(cross_file, fmt, ap);

  va_end(ap); /* clean up */
  fclose(cross_file);
  

}





/* Appends the argument string to the temp notif files in the list */
void NT_add_to_ntfy_list(GSList * list, GHashTable * hash, char * arg){
  
  GSList * temp = NULL;

  for(temp = list; temp != NULL; temp = g_slist_next(temp)){
    NT_add_to_ntfy((char *)g_hash_table_lookup(hash, ((char *)temp->data)), arg);
  }
}








/* Sends the notification message which is stored in the temporary filefilename.  */
void NT_send_ntfy( const char * filename, const char * to_address, const char * mailercommand){

    char * mail_command_line = NULL;
    char * supress_file = NULL;
    FILE * notif_file, * supr_file_hdl;
    char buf[1024];


    /* if we are not supressing acks and notifs, send the notif */
    if(!supress_ack_notif){
      if(to_address != NULL){
        mail_command_line = (char *)malloc(strlen(mailercommand) + strlen(filename) + 128);
        sprintf(mail_command_line, "%s %s < %s", mailercommand, to_address, filename);
        system(mail_command_line);
      }
    /* if we are supressing acks and notifs, send notif to DEFMAIL  */
    }else{
      supress_file = (char *)malloc(strlen(filename) + strlen(".supress") + 2); 
      sprintf(supress_file, "%s.supress", filename);
      if(( supr_file_hdl = fopen(supress_file, "w")) == NULL){
        fprintf(stderr, "Can't open supress notif file, %s", supress_file);
      }else{
        fprintf(supr_file_hdl, "From: %s\nTo: %s\nSubject: Supressed notif mail\n\n",
            humailbox, defmail);
        if(( notif_file = fopen(filename, "r")) == NULL){
          fprintf(stderr, "Can't open notif file for reading, %s", filename);
        }else{
          while(fgets(buf, 1023, notif_file) != NULL){
            fprintf(supr_file_hdl, buf);
          }
          fclose(notif_file);
        }
      }
      fclose(supr_file_hdl);
      mail_command_line = (char *)malloc(strlen(mailercommand) + strlen(defmail) 
            + strlen(supress_file) + 128);
      sprintf(mail_command_line, "%s %s < %s", mailercommand, defmail, supress_file);
      system(mail_command_line);
      unlink(supress_file);
      free(supress_file);
    }


}



/* Adds the notification message which is in the filename into "logfilename.date". */
void NT_log_ntfy( const char * filename, const char * logfilename){

  FILE * notif_file, * log_file;
  char * buf;
  time_t cur_time;
  char * time_str;
  char * logfile_date;
  char * date;

  buf = (char *)malloc(1024);
  if(( notif_file = fopen(filename, "r")) == NULL){
    fprintf(stderr, "Can't open notification file for reading, [%s]\n", filename);
    return;
  }

  /* construct the "logfilename.date" string */
  logfile_date = (char *)malloc(strlen(logfilename) + 10);
  date = UP_get_current_date();
  snprintf(logfile_date, strlen(logfilename) + 10, "%s.%s", logfilename, date);
  free(date);

  if(( log_file = fopen(logfile_date, "a")) == NULL){
    fprintf(stderr, "Can't open log file, %s\n", logfilename);
    return;
  }

  /* get time */
  cur_time = time(NULL);
  time_str = strdup(ctime(&cur_time));
  /* cut the '\n' at the end */
  time_str[strlen(time_str) - 1] = '\0';

  fprintf(log_file, ">>> time: %s NOTIF <<<\n\n", time_str);


  while((buf=fgets(buf, 1023, notif_file)) > 0){
    fprintf(log_file, "%s", buf);
  }
  free(buf);

  fclose(notif_file);
  fclose(log_file);

}


/* Deletes the temporary notification file. */ 
void NT_delete_ntfy( const char * filename){

   unlink(filename);
   
}


/* The function required for NT_send_ntfy_list */
void  nt_gfunc_send(gpointer key, gpointer value, gpointer user_data){
  NT_send_ntfy((char *)value, (char *)key, (char *)user_data);
}


       
/* Sends the notification messages whose temp files are stored in filehash. */              
void NT_send_ntfy_list( GHashTable * filehash, char * mailercommand){

  g_hash_table_foreach( filehash, (GHFunc)nt_gfunc_send, mailercommand);
  
}




/* The function required for NT_log_ntfy_list */
void  nt_gfunc_log(gpointer key, gpointer value, gpointer user_data){
  NT_log_ntfy((char *)value, (char *)user_data);
}




/* Logs the notification whose temp files are in filehash to log_file. */
void NT_log_ntfy_list( GHashTable * filehash, char * log_file){

   g_hash_table_foreach( filehash, (GHFunc)nt_gfunc_log, log_file);
  
}



/* The function required for NT_delete_ntfy_list */
void  nt_gfunc_delete(gpointer key, gpointer value, gpointer user_data){
  NT_delete_ntfy((char *)value);
}



/* Deletes the temporary notification messages in the filehash. Empties and frees 
   the hash too.  */
void NT_delete_ntfy_list( GHashTable * filehash){

  g_hash_table_foreach(filehash, (GHFunc)nt_gfunc_delete, NULL);
  g_hash_table_destroy(filehash);
  
}


/* to be used with g_hash_table_foreach in NT_unify_list.
   Adds the 'key' to the list (a GSList) */
void nt_add_to_list(char * key, char * value, GSList ** list){

  *list = g_slist_append(*list, strdup(value));

  
}



/* "unifies" a list in a case insensitive manner */
GSList * NT_unify_list(GSList * in_list){

  GHashTable * unification_hash;
  GSList ** out_list;
  GSList * temp;
  char * key, * value;

  /* allocate space for out_list */ 
  out_list = (GSList **)malloc(sizeof(GSList *));
  *out_list = NULL;

  /* initialize the hash to be used for unification process */
  unification_hash = g_hash_table_new(g_str_hash, g_str_equal);

  /* first put the list elements into a hash, to unify them */
  for(temp = in_list; temp != NULL; temp = g_slist_next(temp)){
    
    /* convert the string into lowercase */
    key = strdup((char *)(temp->data));
    g_strdown(key);
    value = strdup((char *)(temp->data));
    
    if(g_hash_table_lookup(unification_hash, key) == NULL){/* if it is not there */
      
      g_hash_table_insert(unification_hash, key, value);
      
    }
  }

  /* now, get the elements back from the hash into a list */
  g_hash_table_foreach(unification_hash, (GHFunc)nt_add_to_list, out_list);

  g_slist_free(in_list);
  g_hash_table_destroy(unification_hash);
  
  return *out_list;

}








/* Gathers e-mail boxes to which we will send normal notification messages. It 
   takes old and new objects, looks up maintainers and less specific inetnums/domains/routes 
   when necessary, finds the addresses (in mnt-nfy and notify attributes) and returns 
   a list of them. */
GSList * NT_gather_ntfy_addresses( char * old_object, char * new_object){
  GSList * return_list = NULL, * temp = NULL;
  GSList * mntners = NULL; 

  if(old_object != NULL && new_object != NULL){/* it was an update */
    temp = get_attr_list(old_object, "notify");
    mntners = get_mntners(old_object);
    temp = g_slist_concat(temp, get_mntnfy_vector(mntners));
  }else if(old_object == NULL && new_object != NULL){/* it was a creation */
    temp = get_attr_list(new_object, "notify");
    mntners = get_mntners(new_object);
    temp = g_slist_concat(temp, get_mntnfy_vector(mntners));
  }else if(old_object != NULL && new_object == NULL){/* it was a deletion */
    temp = get_attr_list(old_object, "notify");
    mntners = get_mntners(old_object);
    temp = g_slist_concat(temp, get_mntnfy_vector(mntners));
  }

  /* we have to 'unify' the list here! */
  return_list = NT_unify_list(temp);

  return return_list;
}



/* Gathers e-mail boxes to which we will forward messages (or rather, objects). It 
   an object, looks up maintainers, finds the addresses (in upd-to attributes) and returns 
   a list of them. */
GSList * NT_gather_frwd_addresses(char * object){
  GSList *temp = NULL;
  GSList * mntners = NULL; 

  mntners = get_mntners(object);
  temp = get_updto_vector(mntners);
  return temp;
}




/* Accepts a route object as a "* char" and returns a list of overlapping routes */
overlap_routes get_overlapping_routes_list(char * object){

  char * route_prefix = NULL;
  GSList * tmp_list;
  char * result;
  char * query_string;  
  overlap_routes result_routes;
  char * origin;
  bool code;
  
    
  result_routes.less_spec = NULL;
  result_routes.exact_match = NULL;
  result_routes.more_spec = NULL;
      
  tmp_list = get_attr_list(object, "route");  

  if(tmp_list != NULL && tmp_list->data != NULL){
    route_prefix = strdup((char *)(tmp_list->data));
  }else{
    return result_routes; /* then, this wasn't a route object */
  }
  
  /* get the less specific route objects */
  /* form the query string */
  query_string = (char *)malloc(strlen("-Troute -r -l ") + strlen(route_prefix) + 2);
  sprintf(query_string, "-Troute -r -l %s", route_prefix);

  /* get the results */ 
  result = send_and_get(query_host, query_port, query_string);
  free(query_string);

  /* and fill in the result field  */
  result_routes.less_spec = take_objects(result);

  /* get the exact match route objects */
  /* form the query string */
  query_string = (char *)malloc(strlen("-Troute -r -x ") + strlen(route_prefix) + 2);
  sprintf(query_string, "-Troute -r -x %s", route_prefix);

  /* get the results */ 
  result = send_and_get(query_host, query_port, query_string);
  free(query_string);
  

  /* filter out the route object itself */
  result = UP_filter_out_same_origins(result, object);

  /* and fill in the result field  */
  if(result != NULL){
    result_routes.exact_match = take_objects(result);
  }
  

  /* get the more specific route objects */
  /* form the query string */
  query_string = (char *)malloc(strlen("-Troute -r -M ") + strlen(route_prefix) + 2);
  sprintf(query_string, "-Troute -r -M %s", route_prefix);

  /* get the results */ 
  result = send_and_get(query_host, query_port, query_string);
  free(query_string);

  /* and fill in the result field  */
  result_routes.more_spec = take_objects(result);

  /* Return the results */
  return result_routes;
  
}





/* Gets old and new versions of the object, and creates temporary notification
   files when necessary, and then writes appropriate strings into those
   temporary files. */
void NT_write_all_ntfs(char * old_object, char * new_object, char * formatted_object,
                       const char * tempdir,
                       GHashTable * ntfy_hash,  GHashTable * forwd_hash, GHashTable * cross_hash, 
                       char * from_address){ 

   GSList * e_mail_list = NULL;
   GSList * temp = NULL;
   char * e_mail_address;
   overlap_routes overlapping_routes; 
    
   /* from_address may contain also the name, like "Johnny Bravo <johnny@inter.net>",
      so extract the e-mail address from it */
   e_mail_address = find_email_address(from_address); 


   if(tracing && reading_from_mail){
     printf("TRACING: NT_write_all_ntfs: from_address=[%s], e_mail_address=[%s]\n", from_address, e_mail_address);
   }
   if(old_object != NULL && new_object != NULL){/* it was an update */
     e_mail_list = NT_gather_ntfy_addresses(old_object, new_object);
     NT_add_to_ntfy_hash_list(ntfy_hash, e_mail_list); 
     NT_add_to_ntfy_list(e_mail_list, ntfy_hash, "---\nPREVIOUS OBJECT:\n\n");
     NT_add_to_ntfy_list(e_mail_list, ntfy_hash, old_object);
     NT_add_to_ntfy_list(e_mail_list, ntfy_hash, "\n\nREPLACED BY:\n\n");
     NT_add_to_ntfy_list(e_mail_list, ntfy_hash, new_object);
     NT_add_to_ntfy_list(e_mail_list, ntfy_hash, "\n");
   }else if(old_object == NULL && new_object != NULL){/* it was a creation */
     e_mail_list = NT_gather_ntfy_addresses(old_object, new_object);
     NT_add_to_ntfy_hash_list(ntfy_hash, e_mail_list); 
     NT_add_to_ntfy_list(e_mail_list, ntfy_hash, "---\nOBJECT BELOW CREATED:\n\n");
     NT_add_to_ntfy_list(e_mail_list, ntfy_hash, 
            formatted_object ? formatted_object : new_object);
     NT_add_to_ntfy_list(e_mail_list, ntfy_hash, "\n");
     /* We'll deal with cross notifications only when we create or delete route objects */
     if(strcmp(get_class_type_char(new_object), "route") == 0){
       overlapping_routes = get_overlapping_routes_list(new_object);
       if(overlapping_routes.less_spec != NULL || overlapping_routes.exact_match != NULL ||
          overlapping_routes.more_spec != NULL ){
         NT_add_to_cross_hash(cross_hash, e_mail_address, ADDITION);
         NT_add_to_cross(e_mail_address, cross_hash, "%s\n\n%s\n\n%s\n\n", cno_explain_add, new_object, cno_overlap_add);
         if(overlapping_routes.less_spec != NULL){
           NT_add_to_cross(from_address, cross_hash, "LESS SPECIFIC MATCHES\n\n");
           for(temp = overlapping_routes.less_spec; temp != NULL; temp = g_slist_next(temp)){
             NT_add_to_cross(from_address, cross_hash, "%s\n\n", (char *)temp->data);
           }
         }
         if(overlapping_routes.exact_match != NULL){
           NT_add_to_cross(from_address, cross_hash, "EXACT MATCHES\n\n");
           for(temp = overlapping_routes.exact_match; temp != NULL; temp = g_slist_next(temp)){
             NT_add_to_cross(from_address, cross_hash, "%s\n\n", (char *)temp->data);
           }
         }
         if(overlapping_routes.more_spec != NULL){
           NT_add_to_cross(from_address, cross_hash, "MORE SPECIFIC MATCHES\n\n");
           for(temp = overlapping_routes.more_spec; temp != NULL; temp = g_slist_next(temp)){
             NT_add_to_cross(from_address, cross_hash, "%s\n\n", (char *)temp->data);
           }
         }
       }
     }
   }else if(old_object != NULL && new_object == NULL){/* it was a deletion */
     old_object = delete_delete_attrib(old_object);
     e_mail_list = NT_gather_ntfy_addresses(old_object, new_object);
     NT_add_to_ntfy_hash_list(ntfy_hash, e_mail_list); 
     NT_add_to_ntfy_list(e_mail_list, ntfy_hash, "---\nOBJECT BELOW DELETED:\n\n");
     NT_add_to_ntfy_list(e_mail_list, ntfy_hash, old_object);
     NT_add_to_ntfy_list(e_mail_list, ntfy_hash, "\n");
     /* We'll deal with cross notifications only when we create or delete route objects */
     if(strcmp(get_class_type_char(old_object), "route") == 0){
       overlapping_routes = get_overlapping_routes_list(old_object);
       if(overlapping_routes.less_spec != NULL || overlapping_routes.exact_match != NULL ||
          overlapping_routes.more_spec != NULL ){
         NT_add_to_cross_hash(cross_hash, e_mail_address, DELETION);
         NT_add_to_cross(e_mail_address, cross_hash, "%s\n\n%s\n\n%s\n\n", cno_explain_del, old_object, cno_overlap_del);
         if(overlapping_routes.less_spec != NULL){
           NT_add_to_cross(from_address, cross_hash, "LESS SPECIFIC MATCHES\n\n");
           for(temp = overlapping_routes.less_spec; temp != NULL; temp = g_slist_next(temp)){
             NT_add_to_cross(from_address, cross_hash, "%s\n\n", (char *)temp->data);
           }
         }
         if(overlapping_routes.exact_match != NULL){
           NT_add_to_cross(from_address, cross_hash, "EXACT MATCHES\n\n");
           for(temp = overlapping_routes.exact_match; temp != NULL; temp = g_slist_next(temp)){
             NT_add_to_cross(from_address, cross_hash, "%s\n\n", (char *)temp->data);
           }
         }
         if(overlapping_routes.more_spec != NULL){
           NT_add_to_cross(from_address, cross_hash, "MORE SPECIFIC MATCHES\n\n");
           for(temp = overlapping_routes.more_spec; temp != NULL; temp = g_slist_next(temp)){
             NT_add_to_cross(from_address, cross_hash, "%s\n\n", (char *)temp->data);
           }
         }
       }
     }
   }
}





/* Gets old and new versions of the object, and creates temporary notification
   files when necessary, and then writes appropriate strings into those
   temporary files. */
void NT_write_all_frwds(char * old_object, char * new_object, const char * tempdir,
                       GHashTable * ntfy_hash,  GHashTable * forwd_hash, GHashTable * cross_hash, 
                       const char * from_address){ 

   GSList * e_mail_list = NULL;


   if(tracing){
     printf("TRACING: NT_write_all_frwds\n");
   }
   if(old_object != NULL && new_object != NULL){/* it was an update */
     e_mail_list = NT_gather_frwd_addresses(old_object);
     NT_add_to_frwd_hash_list(forwd_hash, e_mail_list);
     NT_add_to_ntfy_list(e_mail_list, forwd_hash, "----\nUPDATE REQUESTED FOR:\n\n");
     NT_add_to_ntfy_list(e_mail_list, forwd_hash, new_object);
   }else if(old_object == NULL && new_object != NULL){/* it was a creation */
     e_mail_list = NT_gather_frwd_addresses(new_object);
     NT_add_to_frwd_hash_list(forwd_hash, e_mail_list);
     NT_add_to_ntfy_list(e_mail_list, forwd_hash, "----\nADDITION REQUESTED FOR:\n\n");
     NT_add_to_ntfy_list(e_mail_list, forwd_hash, new_object);
   }else if(old_object != NULL && new_object == NULL){/* it was a deletion */
     e_mail_list = NT_gather_frwd_addresses(old_object);
     NT_add_to_frwd_hash_list(forwd_hash, e_mail_list);
     NT_add_to_ntfy_list(e_mail_list, forwd_hash, "----\nDELETION REQUESTED FOR:\n\n");
     NT_add_to_ntfy_list(e_mail_list, forwd_hash, old_object);
   }
}



/* Sends the creation forward message which is stored in the temporary filefilename.  */
void NT_send_forw_creation( const char * filename, const char * to_address, const char * mailercommand){

    char * mail_command_line = NULL;


    if(to_address != NULL){
      mail_command_line = (char *)malloc(strlen(mailercommand) + strlen(filename) + 128);
      sprintf(mail_command_line, "%s %s < %s", mailercommand, to_address, filename);
      system(mail_command_line);
      free(mail_command_line);
    }

}





/* NT_forw_create_req forwards the maintainer and as-block creation requests
   to <HUMAILBOX> */
void NT_forw_create_req(const char * object){

   FILE * forw_file;
   char * filename;
   char * replaced_mtfwheader;
   char * replaced_mtfwtxt;

   /* allocate space for name.  32 should be enough for PID */
   filename = (char*)malloc(strlen(tmpdir) + strlen("creat-forw") +32 ); 
   
   sprintf(filename, "%s/%s.%i", tmpdir, "creat-forw", getpid());

   /* create the file */
   if(( forw_file = fopen(filename, "w")) == NULL){
     fprintf(stderr, "Can't open creation forward file for creating, %s", filename);
   }

   replaced_mtfwheader = UP_replace_globals(mtfwheader);
   replaced_mtfwtxt = UP_replace_globals(mtfwtxt);
   
   fprintf(forw_file, "%s\n\n", replaced_mtfwheader);
   
   if(reading_from_mail){
     fprintf(forw_file, "%s\n\n", replaced_mtfwtxt);
   }

   /* print the object */
   fprintf(forw_file, "%s\n\n", object);
    
   /* close it */
   fclose(forw_file);
    
   /* send it */ 
   NT_send_forw_creation(filename, humailbox, mailcmd);

   /* log it */
   NT_log_ntfy(filename, forwlog);
   
   /* delete it */
   unlink(filename);
 
   /* free the mem */ 
   free(filename);
   free(replaced_mtfwheader);
   free(replaced_mtfwtxt);
}
