#include <stdio.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_lock.h"
#include "manhat-lib/shared_server_string.h"
#include "manhat-lib/shared_mp3_util.h"


ATTACHMENT_NODE *attachment_head = (ATTACHMENT_NODE *) 0;




static void
extract_play_one_params(char *string, char *course, char *sender, int *grp, char *fname, 
                                           char *infname, char *sender_realname, char *title, char *key)
{
 char *ptr, *ptr2;
 
       ptr = strstr(string, "sender^");
       if(!ptr)
           cs_critical_error(ERR_PARAM_MISSING, "can't find 'sender^' within 'crs' parameter");

       *ptr = '\0';
       strncpy(course, string, MAX_FILENAME +1);
       ptr++;

       ptr2 = strchr(ptr, '^');
       if(!ptr2)
          cs_critical_error(ERR_PARAM_MISSING, "can't find first ^ in 'crs' parameter");
       *ptr2 = '\0';
       ptr2++;
       
       ptr = strstr(ptr2, "grp^");
       if(!ptr)
          cs_critical_error(ERR_PARAM_MISSING, "can't find 'grp^' within 'crs' parameter");
       ptr--;
       *ptr = '\0';
       strncpy(sender, ptr2, MAX_USERNAME + 1);

       ptr++;
      ptr2 = strchr(ptr, '^');
      if(!ptr2)
          cs_critical_error(ERR_PARAM_MISSING, "can't find second ^ within 'crs' parameter");
      *ptr2 = '\0';
       ptr2++;
       ptr = strstr(ptr2, "fname^");
       if(!ptr)	
          cs_critical_error(ERR_PARAM_MISSING, "can't find 'fname' within 'crs' parameter");
       ptr--;
       *ptr = '\0';
       *grp = atoi(ptr2);

	ptr++;
        ptr2 = strchr(ptr, '^');
	if(!ptr2)
          cs_critical_error(ERR_PARAM_MISSING, "can't find third ^ within 'crs' parameter");
	*ptr2 = '\0';
        ptr2++;
        ptr = strstr(ptr2, "inf^");
        if(!ptr)
          cs_critical_error(ERR_PARAM_MISSING, "can't find 'inf^' within 'crs' parameter");
        ptr--;
	*ptr = '\0';
        strncpy(fname, ptr2, MAX_FILENAME + 1);

	ptr++;
        ptr2 = strchr(ptr, '^');
	if(!ptr2)
          cs_critical_error(ERR_PARAM_MISSING, "can't find fourth ^ within 'crs' parameter");
	*ptr2 = '\0';
        ptr2++;
        ptr = strstr(ptr2, "rlname^");
        if(!ptr)
          cs_critical_error(ERR_PARAM_MISSING, "can't find 'rlname^' within 'crs' parameter");
        ptr--;
	*ptr = '\0';
        strncpy(infname, ptr2, MAX_FILENAME + 1);

	ptr++;
        ptr2 = strchr(ptr, '^');
	if(!ptr2)
          cs_critical_error(ERR_PARAM_MISSING, "can't find fifth ^ within 'crs' parameter");
	*ptr2 = '\0';
        ptr2++;
        ptr = strstr(ptr2, "title^");
        if(!ptr)
          cs_critical_error(ERR_PARAM_MISSING, "can't find 'title^' within 'crs' parameter");
        ptr--;
	*ptr = '\0';
        strncpy(sender_realname, ptr2,  MAX_NAME + 1);

	ptr++;
        ptr2 = strchr(ptr, '^');
	if(!ptr2)
          cs_critical_error(ERR_PARAM_MISSING, "can't find sixth ^ within 'crs' parameter");
	*ptr2 = '\0';
        ptr2++;
        ptr = strstr(ptr2, "id^");
        if(!ptr)
          cs_critical_error(ERR_PARAM_MISSING, "can't find 'id^' within 'crs' parameter");
        ptr--;
	*ptr = '\0';
        strncpy(title, ptr2,  MAX_PATH+1);


	ptr++;
        ptr2 = strchr(ptr, '^');
	if(!ptr2)
          cs_critical_error(ERR_PARAM_MISSING, "can't find seventh ^ within 'crs' parameter");
	*ptr2 = '\0';
        ptr2++;

        ptr = strstr(ptr2, ".xml");
        if(!ptr)
          cs_critical_error(ERR_PARAM_MISSING, "'crs' parameter doesn't end in '.xml'");
	*ptr = '\0';
        strncpy(key, ptr2,  MAX_KEY + 1);

}





static
void extract_podcast_play_all_params(char *string, char *course, char *key, int *grp)
{
char *ptr, *ptr2;

       ptr = strstr(string, "id^");
       if(!ptr)
          cs_critical_error(ERR_PARAM_MISSING, "podcast_frama_playlist");
       *ptr = '\0';

       ptr++;
       strncpy(course, string, MAX_FILENAME +1);

       ptr2 = strchr(ptr, '^');
       if(!ptr2)
          cs_critical_error(ERR_PARAM_MISSING, "podcast_frama_playlist");
       *ptr2 = '\0';
       ptr2++; 
       ptr = strstr(ptr2, "grp^");
       if(!ptr)
            cs_critical_error(ERR_PARAM_MISSING, "podcast_frama_playlist");
       ptr--;
       *ptr = '\0';
       strncpy(key, ptr2,  MAX_KEY+1);


       ptr++;
       ptr2 = strchr(ptr, '^');
       if(!ptr2)
             cs_critical_error(ERR_PARAM_MISSING, "podcast_frama_playlist");
       *ptr2 = '\0';
       ptr2++;

       ptr = strstr(ptr2, ".xml");
       if(!ptr)
            cs_critical_error(ERR_PARAM_MISSING, "podcast_frama_playlist");
       *ptr = '\0';
       *grp = atoi(ptr2);
}




static void
read_parameters (char *course, char *key, char *sender, char *fname, char *infname, 
                                char *sender_realname, char *title, int *grp, char *link)
{
  char temp[MAX_PATH * 2 + 1];
  char *ptr;

  *key = '\0';
  *sender = '\0';
  *fname = '\0';
  *infname = '\0';
  *sender_realname = '\0';
  *title = '\0';
  *grp = 0;
  *link = '\0';


  

  /* if 'link' parameter exists, we're displaying a voice.mp3 lectern file
  ** the 'link' refers to the symbolic link created in the images/links
  ** directory.
  */
  cs_get_optional_parameter ("link", temp, MAX_PATH * 2);
  if(strlen(temp))  
  {
     ptr = strstr(temp, ".xml");
     if(!ptr)
        cs_critical_error(ERR_PARAM_MISSING, "link parameter doesn't contain '.xml'");
     *ptr = '\0';
      strncpy(link, temp, MAX_PATH +1);
  }
  else
  {
     cs_get_required_parameter ("crs", temp, MAX_PATH * 2);
     if(strstr(temp,"sender^"))
       extract_play_one_params(temp, course, sender, grp,fname, infname, sender_realname, title, key);
     else
       extract_podcast_play_all_params(temp, course, key, grp);
  }
}




static void
memory_error ()
{
  cs_critical_error (ERR_MALLOC_FAILED, "");
};



static void
free_attachment_list()
{
 ATTACHMENT_NODE *ptr;

 while(attachment_head)
  {
   ptr = attachment_head;
   attachment_head = attachment_head -> next;
   free(ptr);
  }

}   



static void
build_attachment_list (MSG_TREE_NODE * msg, CONFIG_STRUCT *conf)
{
  FILE *fp;
  int fd;
  char infopath[MAX_PATH + 1];
  int i;
  ATTACHMENT_NODE *aptr = 0;
  NEWS_INFO info;
  int n_attachments;
  
  free_attachment_list();
  
  if(!msg->data.info.attachments)
     return;
  
  n_attachments = abs(msg->data.info.attachments);  /* since a -1 is used to flag an attached website */
  
  snprintf (infopath, MAX_PATH + 1, "%s%s/%s/%s/%s", 
                                    conf->course_path,
		                    PEOPLE_DIR,
		                    msg->data.info.sender,
	    			    discussion_fname, 
	    			    msg->data.info_fname);

  fp = fopen (infopath, "r");
  if (!fp)
    cs_critical_error (ERR_FOPEN_READ_FAILED, infopath);
  fd = fileno(fp);  
  get_shared_lock(fd, 1);                      /* shared_lock.c */   
 
  if (fread (&info, sizeof (NEWS_INFO), 1, fp) != 1)
    cs_critical_error (ERR_FREAD_FAILED, infopath);

  /* process attachments, build linked list */

  for (i = 1; i <= n_attachments; i++)
    {
      if (!attachment_head)
	{
	  attachment_head = (ATTACHMENT_NODE *) malloc (sizeof (ATTACHMENT_NODE));
	  if (!attachment_head)
	          memory_error ();
	  aptr = attachment_head;
	}
      else
	{
	  aptr->next = (ATTACHMENT_NODE *) malloc (sizeof (ATTACHMENT_NODE));
	  if (!aptr->next)
	    memory_error ();
	  aptr = aptr->next;
	}

      if (fread (&aptr->data, sizeof (ATTACHMENT), 1, fp) != 1)
	cs_critical_error (ERR_FREAD_FAILED, infopath);
      aptr->next = 0;
    }				/* for .. */

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

}




static
void send_xml_escaped_string(char *string)
{
 char *ptr;
 
  if(string)
   {
    for(ptr=string; *ptr; ptr++)
      switch(*ptr)
       {
        case '<': fputs("&lt;", stdout);
                  break;

        case '>': fputs("&gt;", stdout);
                  break;

        case '&': fputs("%26", stdout);
                  break;
                  
 
        case '=': fputs("%3D", stdout);
                  break;

        case '?': fputs("%3F", stdout);
                  break;
                  
                  
        case '"': fputs("&quot;", stdout);
                  break;

        case '\'': fputs("&apos;", stdout);
                   break;

       // case ' ': fputs("%20", stdout);
        //          break;
                  
        default:  fputc(*ptr, stdout);
                  break;
        } 
     }   
 }
 
 


void send_one_item(MSG_TREE_NODE *msg_ptr, CONFIG_STRUCT *conf, const char *course, 
                                              const char *server_string, const char *key, int grp)
{

  char extension[MAX_FILENAME +1];
  char path[MAX_PATH + 1];
  int bitrate;
  
   
  build_attachment_list (msg_ptr, conf);

  if(attachment_head)
   {
      get_extension(attachment_head->data.orig_fname, extension);   /* shared_news_util.c */

      if(!strcmp(extension,"mp3"))   /* player only supports mp3 files */
       {
        snprintf (path, MAX_PATH + 1, "%s%s/%s/%s/%s", 
                                    conf->course_path,
		                    PEOPLE_DIR,
		                    msg_ptr->data.info.sender,
	    			    discussion_fname, 
	    			    attachment_head->data.unique_fname);
	    			    
        bitrate = mp3_bitrate(path);   /* shared_mp3_util.c */
     
        puts("<sound>");
        printf("<url>%s/%s/send_file?crs=%s&amp;id=%s&amp;grp=%d&amp;fname=%s&amp;user=%s&amp;info=%s&amp;attach=1&amp;dummy.%s</url>\n",
                   server_string, 
                   ALIAS, 
                   course,
                   key,
                   grp, 
                   attachment_head->data.unique_fname, 
                   msg_ptr->data.info.sender, 
                   msg_ptr->data.info_fname, 
                   extension);
        printf("<title>");
        send_xml_escaped_string(msg_ptr->data.info.subject);
	puts("</title>"); 
        printf("<artist>");
        send_xml_escaped_string(msg_ptr->data.info.sender_realname);
	puts("</artist>");
        printf("<bitrate>%d</bitrate>\n", bitrate== -1? 128: bitrate);

        printf("<downloadurl>%s/%s/send_file?crs=%s&amp;id=%s&amp;grp=%d&amp;fname=%s&amp;user=%s&amp;info=%s&amp;attach=1&amp;dummy.%s</downloadurl>\n",
                   server_string, 
                   ALIAS, 
                   course,
                   key, 
                   grp,
                   attachment_head->data.unique_fname, 
                   msg_ptr->data.info.sender, 
                   msg_ptr->data.info_fname, 
                   extension);
        puts("</sound>");
        free_attachment_list();
       }

   }
}









static void
send_frama_playlist_data (CONFIG_STRUCT *conf, SESSION *user, const char *course, const char *key, int grp)
{
  MSG_TREE_NODE *msg_ptr;
  time_t current_time;
  char server_string[MAX_PATH + 1];

    
  /* current_time is declared globally */
  build_msg_tree(user, PODCASTS, 0, 0, &current_time);   /* shared_news_util.c */
  puts ("Content-type:text/xml\n");
  puts ("<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>");
  puts ("<afAMPxml>");
  
  get_server_string(server_string, MAX_PATH +1);
  for(msg_ptr=tree_head; msg_ptr; msg_ptr=msg_ptr->next)
           send_one_item(msg_ptr, conf, course, server_string, key, grp);
  puts ("</afAMPxml>");
  
  free_msg_tree (tree_head);                     /* shared_news_util.c */

}





void one_item_playlist(const char *course,  const char *sender,  const char *fname, 
		      const char *infname,  char *sender_realname,  char *title, int grp, 
		      const char *key, const char *link, CONFIG_STRUCT *conf)
{
        
  char server_string[MAX_PATH + 1];
  char grp_string[MAX_NAME+1];
  char path[MAX_PATH + 1];
  int bitrate;

  
  
  get_server_string(server_string, MAX_PATH +1);

  snprintf(grp_string, MAX_NAME +1, "&amp;grp=%d", grp);

  puts ("Content-type:text/xml\n");
  puts ("<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>");
  puts ("<afAMPxml>");
  puts("<sound>");
  
  if(strlen(link))
   {
    printf("<url>%s%s%s/%s/voice.mp3</url>\n", server_string, IMAGE_PATH, "links", link);
    snprintf(path, MAX_PATH + 1, "%s/links/%s/voice.mp3",
              IMAGES_DIR,
              link);
   }	
  else
   {
    printf("<url>%s/%s/send_file?crs=%s&amp;id=%s%s&amp;fname=%s&amp;user=%s&amp;info=%s&amp;attach=1&amp;dummy.%s</url>\n",
                   server_string, 
                   ALIAS, 
                   course,
                   key, 
                   grp!=MAIL? grp_string:"",
                   fname, 
                   sender, 
                   infname, 
                   "mp3");
                   
   snprintf (path, MAX_PATH + 1, "%s%s/%s/%s/%s", 
                                    conf->course_path,
		                    PEOPLE_DIR,
		                    sender,
	    			    discussion_fname, 
	    			    fname);
   }                   
                   
  printf("<title>");
  

  
  if(strlen(link))
     printf("????");
  else	
    send_xml_escaped_string(title);
  puts("</title>"); 
  
  printf("<artist>");
  if(strlen(link))
     printf("????");
  else	
     send_xml_escaped_string(sender_realname);
     
  puts("</artist>");
  
  
  
  
  
  bitrate = mp3_bitrate(path);   /* shared_mp3_util.c */  
  printf("<bitrate>%d</bitrate>\n", bitrate == -1? 128 : bitrate );

  if(strlen(link))
     printf("<downloadurl>%s%s%s/%s/voice.mp3</downloadurl>\n", server_string, IMAGE_PATH, "links", link);
  
  else
    printf("<downloadurl>%s/%s/send_file?crs=%s&amp;id=%s%s&amp;fname=%s&amp;user=%s&amp;info=%s&amp;attach=1&amp;dummy.%s</downloadurl>\n",
             server_string, 
             ALIAS, 
             course,
             key, 
             grp!=MAIL? grp_string:"",
             fname, 
             sender, 
             infname, 
             "mp3");

  puts("</sound>");
  puts ("</afAMPxml>");
}



int
main (void)
{
 SESSION user;
 CONFIG_STRUCT conf;
 char course[MAX_PATH + 1];	
 int grp = 0;
 char fname[MAX_FILENAME +1];
 char infname[MAX_FILENAME +1];
 char sender[MAX_USERNAME +1];
 char sender_realname[MAX_NAME +1];
 char title[MAX_PATH +1];
 char key[MAX_KEY +1];
 char link[MAX_PATH +1];
  
 *sender = '\0';
 *link = '\0';


  cs_cgi_init(); 

  read_parameters (course, key, sender, fname, infname, sender_realname, title, &grp, link);
  if(!*link)   /*then we are NOT playing a voice.mp3 file from the lectern_handler program */
  {
    read_configuration_file (course, &conf);	/* shared_util.c */
    validate_key(key, &user, &conf);

    set_discussion_names (conf.course_path, user.username, grp);	/* shared_news_util.c */
  }
   
  
  
  if(*link)   /* play voice.mp3 posted by lectern handler */
      one_item_playlist(course, sender, fname, infname, sender_realname, title, grp, key, link, &conf);
  else if(!strlen(sender))  /* generate full playlist for podcast module */
      send_frama_playlist_data (&conf, &user, course, key, grp);
  else                     /* play a single mp3 file - could be in any group */
      one_item_playlist(course, sender, fname, infname, sender_realname, title, grp, key, link, &conf);


  cs_cgi_destroy();
  return 0;
}


