#include <stdio.h>
#include <time.h>
#include <ctype.h>
#include <string.h>

#include "global.h"


#include "manhat-lib/shared_util.h"
#include "manhat-lib/shared_cs_util.h"
#include "manhat-lib/shared_news_util.h"
#include "manhat-lib/shared_clipboard_util.h"
#include "manhat-lib/shared_read_infofile.h"
#include "manhat-lib/shared_lock.h"
#include "manhat-lib/shared_translate_url.h"
#include "manhat-lib/shared_access.h"
#include "manhat-lib/shared_spelling_util.h"
#include "manhat-lib/shared_teamstring.h"
#include "manhat-lib/shared_podcast_util.h"
#include "manhat-lib/shared_msg_line.h"

#define NOTEAM '!'

int find_num_lines( char *buf);


static void
read_parameters (char *course,
		 char *key,
		 long *offset,
		 int *grp,
		 int *topic, 
	         int *reply_to,
	         char *team,
		 int *paste, 
	 	 char *from,
		 char *recipient)
{
  char msg[MAX_FILENAME + 1];

  cs_get_required_parameter ("crs", course, MAX_PATH);  /* shared_cs_util.c */
  cs_get_required_parameter ("id", key, MAX_KEY); 	/* shared_cs_util.c */
  cs_get_required_parameter ("from", from, MAX_PATH);	/* shared_cs_util.c */

  cs_get_required_parameter ("grp", msg, MAX_FILENAME);	/* shared_cs_util.c */
  *grp = atoi (msg);

  if (!group_uses_topic (*grp))   		/* shared_news_util.c */
   {
    *topic = -1;
    *reply_to = -1;
    cs_set_value("no_topic_type","1");
   } 
  else
    {
      cs_get_required_parameter ("topic", msg, MAX_FILENAME);  /* shared_cs_util.c */
      *topic = atoi (msg);
      cs_get_required_parameter ("reply_to", msg, MAX_FILENAME); /* shared_cs_util.c */
      *reply_to = atoi (msg);
    }


 /** now get the optional parameters */
  cs_get_optional_parameter ("loc", msg, MAX_FILENAME);    /* shared_cs_util.c */
 
  if (!*msg)	/* loc param not found, assume not a reply */
    *offset = -1;		/* -1 means this is not a reply */
  else
    *offset = atol (msg);

  cs_get_optional_parameter ("paste", msg, MAX_FILENAME);        /* shared_cs_util.c */
  if (!*msg)	                
    *paste = 0;			/* not pasting */
  else
    *paste = 1;			/* we are pasting from clipboard */
 

  cs_get_optional_parameter ("team", msg, MAX_FILENAME);   /* shared_cs_util.c */
  if (!*msg)
    *team = NOTEAM;
  else
    *team = *msg;
    
    
  cs_get_optional_parameter ("to", recipient, MAX_USERNAME);  /* shared_cs_util.c */
    
}






static void
get_topic_subject (int topic, char *subject,
		   char *topic_sender, char *topic_realname)
{
  int fd;
  FILE *fp;
  char inbox_path[MAX_PATH + 1];
  int found = 0;
  CENTRAL_INBOX_RECORD msg;
  
  *subject = '\0';
  *topic_sender = '\0';
  *topic_realname = '\0';

  snprintf (inbox_path, MAX_PATH + 1, "%s/%s", central_discussion_path, INBOX_FNAME);
  
  fp = fopen(inbox_path,"r");
  if(!fp)
    return;  
  
  fd = fileno(fp); 
  get_shared_lock(fd, 1);                      /* shared_lock.c */

 while(!found &&  (fread(&msg,sizeof(CENTRAL_INBOX_RECORD),1,fp) == 1))
   if ((msg.info.reply_to == -1) && (msg.info.msg_id == topic))
    	          {
 	           found = 1;
 	           strncpy (subject, msg.info.subject, MAX_SUBJECT + 1);
 	           strncpy (topic_sender, msg.info.sender, MAX_USERNAME + 1);
 	           strncpy (topic_realname, msg.info.sender_realname, MAX_NAME + 1);
 	           }
		

 release_lock(fd);   /* shared_lock.c */
 fclose(fp);

}






static void
set_basic_new_memo_data (char *course, char *key, int grp, int topic, int reply_to, 
			char team, char *from, char *recipient, CONFIG_STRUCT *conf, SESSION *user)
{

  int empty_clipboard;
  char topic_subject[MAX_SUBJECT + 1];
  char translated_from[MAX_PATH + 1];
  char topic_author_username[MAX_USERNAME + 1];	/* username of person who started topic */
  char topic_author_realname[MAX_NAME + 1];	/* real name    ""       "" */
  char temp[20];
  char *realname;

  cs_set_course_info(conf);             /* shared_cs_util.c */
  cs_set_current_time();                /* shared_cs_util.c */
  

 /** clipboard_empty() is in shared_clipboard_utils.c */
  empty_clipboard = (user->group != FACULTY)
			    || clipboard_empty (user->username, conf->course_path, user);
	
 /*** for use in the back button *****/
  translate_url_substitutes (translated_from, from, MAX_PATH + 1, 1);	/* shared_translate_url.c */
  cs_set_value("back_url", translated_from);                            /* shared_cs_util.c */

  if (topic != -1)
    get_topic_subject (topic, topic_subject, topic_author_username, topic_author_realname);

    
  insert_spell_check_button(conf);  /* shared_spelling_util.c */
  
  cs_set_int_value("emoticons_disabled", EMOTICONS_DISABLED(conf->misc)? 1 : 0);
  
  
  
  
  cs_set_value("crs", course);
  cs_set_value("id", key);
  cs_set_int_value("grp", grp);
  cs_set_int_value("topic", topic);
  cs_set_int_value("reply_to", reply_to);
  cs_set_value("from", from);

  cs_set_int_value("msg.textarea.hard_wrap", USE_TEXTAREA_HARD_WRAP);  /* custom.h */
  
   if (team != NOTEAM)
   {
      snprintf(temp, 2, "%c", team);
      cs_set_value("team", temp);
      
      get_team_name(team, temp);  /* shared_teamstring.c */
      cs_set_value("team_name", temp);
   }

   if(strlen(recipient))
      cs_set_value("to", recipient);
   else 
     if ((grp == ASSIGNMENTS) && (topic != -1))
         cs_set_value("to", topic_author_username);

  if (!empty_clipboard)
	cs_set_int_value("content_clipboard", 1);   /* shared_cs_util.c */

  if (topic == -1)
       cs_set_int_value("topic_assign", grp == ASSIGNMENTS? 1: 0);   /* shared_cs_util.c */
  else
    {
      if ((grp == ASSIGNMENTS) && (user->group == FACULTY) && strlen(recipient) )
      {
	   realname = hdf_get_value(global_cgi->hdf, "Query.realname", 0);
	   if(realname)
              cs_set_value("feedbackto_realname", realname);    /* shared_cs_util.c */

           cs_set_value("feedbackto_recipient", recipient);    /* shared_cs_util.c */
      }
      cs_set_value("topic_subject", topic_subject);                  /* shared_cs_util.c */
      cs_set_value("topic_author_realname", topic_author_realname);         /* shared_cs_util.c */
      cs_set_value("topic_author_username", topic_author_username);  /* shared_cs_util.c */
    }
}





static void
set_new_memo_attachments (int add_note, CONFIG_STRUCT *conf, int allow_hotpot_exam)
{
  if (add_note)
	 cs_set_int_value("attach.add_note", 1);    /* shared_cs_util.c */
    
  if(allow_hotpot_exam)
	 cs_set_int_value("attach.allow_hotpot_exam", 1);   /* shared_cs_util.c */
	 
  cs_set_int_value("attach.max_files", conf->mail_attachments);   /* shared_cs_util.c */

}


/** reads the message data for msg at offset into CENTRAL_INBOX_RECORD *msg ***/
static void
read_inbox_record (long offset, CENTRAL_INBOX_RECORD *msg)
{
  int fd;
  FILE *fp;
  char inbox_path[MAX_PATH + 1];

  snprintf (inbox_path, MAX_PATH + 1, "%s/%s", central_discussion_path, INBOX_FNAME);
  *(inbox_path + MAX_PATH) = '\0';
  
  fp = fopen(inbox_path,"r");
  if(!fp)
     cs_critical_error(ERR_FOPEN_READ_FAILED, inbox_path);
 
  fd = fileno(fp);
  get_shared_lock(fd, 1);                      /* shared_lock.c */

  if (fseek (fp, offset, SEEK_SET))
    cs_critical_error (ERR_FSEEK_FAILED, inbox_path);   /* shared_cs_util.c */

  if (fread(msg, sizeof(CENTRAL_INBOX_RECORD),1,fp) != 1)
    cs_critical_error (ERR_FREAD_FAILED, inbox_path);    /* shared_cs_util.c */


   release_lock(fd);   /* shared_lock.c */
   fclose(fp);

}




/* creates a textarea field which is one char wider than the longest line
** of the message to allow for insertion of > char
*/

static void
set_reply_textarea (const char *sender_username,
		   const char *msg_fname, int grp, CONFIG_STRUCT *conf)
{
  FILE *fp;
  char fullpath[MAX_PATH + 1];
  struct stat file_stat;
  char *buf = 0, *add_reply_mark = 0;
  int longest;

  snprintf (fullpath, MAX_PATH + 1, "%s/%s/%s/%s/%s",
	    conf->course_path, PEOPLE_DIR,sender_username, discussion_fname, msg_fname);
  *(fullpath + MAX_PATH) = '\0';	    

  if(stat(fullpath, &file_stat))
     cs_critical_error(ERR_STAT_FAILED, fullpath);      /* shared_cs_util.c */

  buf = (char*)malloc( (file_stat.st_size + 1) * sizeof(char) );
  if(!buf)
     cs_critical_error( ERR_MALLOC_FAILED, "set_reply_textarea()");   /* shared_cs_util.c */

  if(file_stat.st_size)   /* if the file is not empty */
   {
     fp = fopen (fullpath, "r");
     if (!fp)
       cs_critical_error (ERR_FOPEN_READ_FAILED, fullpath);    	/* shared_cs_util.c */

     if(fread(buf, file_stat.st_size, 1, fp) != 1)
       cs_critical_error (ERR_FREAD_FAILED, fullpath);	/* shared_cs_util.c */

    fclose (fp);
   } 
  
   *(buf + file_stat.st_size) = '\0';

  remove_smart_quotes(buf);    /* shared_msg_line.c */
  
  longest = find_longest_line(buf, conf);                   /* shared_news_util.c */
  cs_set_int_value("msg.textarea.cols", longest + 1);     /* shared_cs_util.c */

  longest = find_num_lines(buf);                      /* shared_news_util.c */
  add_reply_mark = add_mark_to_msg(buf, longest);     /* shared_news_util.c */
  cs_set_value("msg.textarea.body", add_reply_mark);  /* shared_cs_util.c */

  if(buf)
     free(buf);
  if(add_reply_mark)
     free(add_reply_mark);
}




void handle_podcast_attached_files()
{
 #define MAX_TMP_NAME 50
 
  ATTACHMENT_NODE *aptr;
  int attachment_count = 0;
  char extension[MAX_FILENAME +1], name[MAX_TMP_NAME +1], value[MAX_PATH];

   for ( aptr = attachment_head; aptr; aptr = aptr->next)
   {
     get_extension(aptr->data.orig_fname, extension);         /* shared_news_util.c */
     if(is_valid_podcast_file_extension(extension))
      {
	  snprintf(name, MAX_TMP_NAME + 1, "attach.file.%d.value", attachment_count);
	  snprintf(value, MAX_PATH, "%s::%s", aptr->data.orig_fname, aptr->data.unique_fname);
	  cs_set_value(name, value); 
	  
          snprintf(name, MAX_TMP_NAME + 1, "attach.file.%d.orig", attachment_count);
	  cs_set_value(name, aptr->data.orig_fname);         /* shared_cs_util.c */
          
          attachment_count++;
      }
   }

   if(attachment_count)
   {
         cs_set_int_value("has_attach", 1);                 /* shared_cs_util.c */
	 cs_set_value("attach.type", "pasted_files");       /* shared_cs_util.c */
   }
     
 #undef MAX_TMP_NAME
}




static int
do_paste (int topic, int *files_attached, SESSION *user, int grp, CONFIG_STRUCT *conf)
{
  #define MAX_TMP_NAME 30
  
  char name[MAX_TMP_NAME + 1];
  char value[MAX_PATH + 1];
  CLIPBOARD_INFO clipboard_info;
  char clipboard_path[MAX_PATH + 1];
  ATTACHMENT_NODE *aptr;
  int i;
  int hotpot_exam;   /* are we trying to paste a Hot Potatoes exam? */
  char *clip_subject = 0;
  
  *files_attached = 0;		/* assume this to start */

  if (user->group != FACULTY)
    cs_critical_error (ERR_REQUEST_DENIED, "");      /* shared_cs_util.c */

  if (get_clipboard_info (&clipboard_info, clipboard_path, user))   /* shared_read_infofile.c */
    return 1; /* clipboard is empty */

  cs_set_int_value("do_clipboard", 1);   /* shared_cs_util.c */

  *files_attached = clipboard_info.attachments;

  /* print clipboard subject but must replace quotes " with &quot; */
  clip_subject = replace_quot(clipboard_info.subject);    /* shared_news_util.c */
  cs_set_value("msg.subject.value", clip_subject);       /* shared_cs_util.c */
  if(clip_subject)
      free(clip_subject);

  /* handle textarea -  shared_news_util.c */
  do_paste_textarea (clipboard_path, clipboard_info.msg_fname,       
		     clipboard_info.sender_username,
		     clipboard_info.sender_realname, user, conf);
 
  if (attachment_head)
    {
      if(grp == PODCASTS)
         handle_podcast_attached_files();
      else
      {
         cs_set_int_value("has_attach", 1);           /* shared_cs_util.c */
         hotpot_exam = clipboard_info.website_attached && 
                              is_hotpot_exam_dir(attachment_head->data.unique_fname);  /* shared_news_util.c */

        if(hotpot_exam && !allow_hotpot_exam_post(user,grp,topic))    /* shared_news_util.c */
	   cs_set_int_value("attach.not_allow", 1);    /* shared_cs_util.c */
        else
        { 
	   if(clipboard_info.website_attached)
	      {
	       cs_set_value("attach.type", "pasted_website");  /* shared_cs_util.c */
	       cs_set_int_value("attach.website", 1);		/* shared_cs_util.c */
	       cs_set_int_value("attach.value", 1);		/* shared_cs_util.c */
	      }
	   else
	      {
	       cs_set_value("attach.type", "pasted_files");   		        /* shared_cs_util.c */
	       cs_set_int_value("attach.value", clipboard_info.attachments);	/* shared_cs_util.c */
	      }
       }
        
        for (i = 1, aptr = attachment_head; aptr; aptr = aptr->next, i++)
	  {
	    snprintf(name, MAX_TMP_NAME + 1, "attach.file.%d.value", i-1);
	    snprintf(value, MAX_PATH, "%s::%s", aptr->data.orig_fname, aptr->data.unique_fname);
	    cs_set_value(name, value); 
            if( (i == 1) && clipboard_info.website_attached )
	       {
	        snprintf(name, MAX_TMP_NAME + 1, "attach.file.%d.type", i-1);
		if(hotpot_exam)
		  cs_set_int_value(name, 0);   /* lang.news_new_memo.attach.type.0 = attached hot potato exam */
	        else	
		  cs_set_int_value(name, 1);   /* lang.news_new_memo.attach.type.1 = attached website */
	       } 
	    else
	       { 
	         snprintf(name, MAX_TMP_NAME + 1, "attach.file.%d.orig", i-1);
	         cs_set_value(name, aptr->data.orig_fname);   /* shared_cs_util.c */
	       }
            
	  }
      }
    }
   free_attachment_list ();

  return 0;			/* paste successful */
  #undef MAX_TMP_NAME 

}




static void
set_new_memo_form_data (char *course, char *key,
		       long offset, int grp, int topic, int reply_to, char team,
		       int paste, char *from, char *recipient, CONFIG_STRUCT *conf, SESSION *user)
{
  CENTRAL_INBOX_RECORD inbox;
  char reply_subject[MAX_SUBJECT + 1];
  int paste_failed = 0;
  int files_attached = 0;
  int allow_hotpot_exam;         /* should form allow attachment of a Hot Potatoes exam? */
  char *subject = 0;
    
  set_basic_new_memo_data (course, key, grp, topic, reply_to, team, from, recipient, conf, user);

  /* If this is a teacher posting a new topic, put in 
  ** a 'hide message' checkbox
  */
  if ( (user->group == FACULTY) && (topic == -1) )
      cs_set_int_value("include_mark_hidden_option", 1);      /* shared_cs_util.c */

  /* handle subject */
  
  cs_set_int_value("msg.subject.max", MAX_SUBJECT-1);


  if (paste)
      paste_failed = do_paste (topic, &files_attached, user, grp, conf);

  if (!paste || paste_failed)
    {
      if ((offset == -1) || paste_failed)	/* i.e. if this is not a reply */
          cs_set_int_value("msg.textarea.cols", editor_width_config(conf->misc));  /* shared_news_util.c */
      else		/* this is a reply */
	{
          /* read the data for this message */
	  read_inbox_record (offset, &inbox);

	  /* handle subject */
	  cs_set_int_value("msg.subject.add_re", 1);
	  strncpy (reply_subject, inbox.info.subject, MAX_SUBJECT - 1);
	  
	  /* Internet Explorer has a problem since it ignores the 
	     maxlength=xxx value for an <input type="text"... > field
	     if the length of value is > maxlength.  The following chops
	     off three characters from the end of the string to allow for
	     the addition of "Re:" to the beginning of the string
	  */
   
	  *(reply_subject + MAX_SUBJECT - 1 - 3) = '\0';   
	  
	  
	  cs_set_int_value("msg.subject.max", MAX_SUBJECT -1);
	  cs_set_int_value("msg.subject.size", MAX_SUBJECT -1);
          
	  /* print subject but must replace quotes " with &quot; */
          subject = replace_quot(reply_subject);     /* shared_news_util.c */
          cs_set_value("msg.subject.value", subject);
          if(subject)
	      free(subject);

	  /* handle textarea */
	  set_reply_textarea (inbox.info.sender, inbox.info.msg_fname, grp, conf);

          cs_set_value("msg.textarea.feedback", inbox.info.sender_realname);
          cs_set_value("msg.textarea.feedback_newline", "\n \n");

	}	/* else: this is a reply */
    }

  /* deal with the attachment area */
  allow_hotpot_exam = allow_hotpot_exam_post(user,grp, topic); /* shared_news_util.c */
  set_new_memo_attachments (files_attached, conf, allow_hotpot_exam);
  

}



/* Faculty using the team teach module must send along the 'team' parameter so we know who to send the
** msgs to. Others who send the 'team' parameter are imposters and should be stopped
**
** also, only FACULTY can post to some groups
**/

static void
check_imposter (char team, int grp, SESSION *user, int topic, const char *recipient)
{
 

/** only FACULTY can create new topics in the assignments module */
  if((topic == -1) && (grp == ASSIGNMENTS) && (user->group != FACULTY)) 
         cs_critical_error (ERR_REQUEST_DENIED, "");
         
/** non-blank recipient is OK only for FACULTY in ASSIGNMENTS module and non-topic */
    if(strlen(recipient) && ((grp != ASSIGNMENTS) || (topic == -1)) )
       cs_critical_error (ERR_REQUEST_DENIED, "");
      

  if (faculty_only_group (grp)	/* shared_news_util.c */
      && user->group != FACULTY)
    cs_critical_error (ERR_REQUEST_DENIED, "");


  if ((user->group == FACULTY) && (grp == TEAM_TEACH))
    {
      if (team == NOTEAM)
	cs_critical_error (ERR_PARAM_MISSING, "team");
    }
  else if (team != NOTEAM)
    cs_critical_error (ERR_REQUEST_DENIED, "");
}


int
main (void)
{
  char course[MAX_PATH + 1];		/* from crs=? command line */
  char key[MAX_KEY + 1];		/* from id=? command line */
  long offset;				/* from loc=? optional cmd line */
  int grp;				/* from grp=? cmd line */
  int topic;				/* from topic=? command line */
  int reply_to;                 	/* from reply_to=? command line */
  char from[MAX_PATH + 1];		/* from from=? command line */
  char team;				/* from [optional] team=? command line */
  int paste;				/* from [optional] paste=? command line */
  char recipient[MAX_USERNAME + 1];  	/* from [optional] to=? command line */

  SESSION user;
  CONFIG_STRUCT conf;		

  cs_cgi_init();			/* shared_cs_util.c */

  read_parameters (course, key, &offset, &grp, &topic, &reply_to, &team, &paste, from, recipient);
  read_configuration_file (course, &conf);	/* shared_util.c */
  validate_key (key, &user, &conf);		/* shared_util.c */

  if(!has_write_permission(&user, &conf))   /* shared_access.c */
      access_denied_error();
      
  /* only FACULTY can address a message to someone other than themselves 
  ** that happens in the assignments module 
  */
  if(strlen(recipient) && (user.group != FACULTY) && strcmp(recipient,user.username))
      cs_critical_error(ERR_REQUEST_DENIED, "");

  set_discussion_names (conf.course_path, user.username, grp);	/* shared_news_util.c */

  cs_set_int_value("grp", grp);					/* shared_cs_util.c */
  check_imposter (team, grp, &user, topic, recipient);
  set_new_memo_form_data (course, key, offset, grp, topic, reply_to, team, paste, from, recipient, &conf, &user);

  cs_cgi_display("news_new_memo", 1);   /* shared_cs_util.c */
  cs_cgi_destroy();			/* shared_cs_util.c */
  return 0;
}



