#include #include #include #include #include #include "global.h" #include "custom.h" /* for date FORMAT strings */ #include "manhat-lib/shared_util.h" #include "manhat-lib/shared_lock.h" #include "manhat-lib/shared_news_util.h" #include "manhat-lib/shared_person_list.h" #include "manhat-lib/shared_translate_url.h" #include "manhat-lib/shared_file_util.h" #include "manhat-lib/shared_cs_util.h" #include "manhat-lib/shared_fold_file.h" #include "manhat-lib/shared_strtrm.h" typedef struct data { char *url; char *msg; }DATA; void free_data(DATA *data) { if(data) { if(data->url) free(data->url); if(data->msg) free(data->msg); free(data); } } DATA * read_parameters (char *course, char *key, char *fromprog, int *hide, char *subject, int *width) { char tmp[20]; DATA *msg_data; char *string; cs_get_required_parameter ("crs", course, MAX_PATH); cs_get_required_parameter ("id", key, MAX_KEY); cs_get_required_parameter ("from", fromprog, MAX_PATH); cs_get_required_parameter ("subject", subject, MAX_SUBJECT); cs_get_required_parameter ("width", tmp, 19); *width = atoi(tmp); cs_get_optional_parameter ("hide", tmp, 19); if(strlen(tmp)>0) *hide = 1; else *hide =0; msg_data = (DATA*)malloc(sizeof(DATA)); if(!msg_data) cs_critical_error(ERR_MALLOC_FAILED, ""); string = hdf_get_value(global_cgi->hdf, "Query.url", 0); strtrm(string); /* shared_strtrm.c */ if(!string || !strlen(string)) cs_critical_error(ERR_PARAM_MISSING, "url"); msg_data->url = (char*)malloc(sizeof(char)*(strlen(string)+1)); if(!msg_data->url) cs_critical_error(ERR_MALLOC_FAILED, ""); strncpy(msg_data->url, string, strlen(string) +1); string = hdf_get_value(global_cgi->hdf, "Query.msg", 0); if(string) { msg_data->msg = (char*)malloc(sizeof(char)*(strlen(string)+1)); if(!msg_data->msg) cs_critical_error(ERR_MALLOC_FAILED, ""); strncpy(msg_data->msg, string, strlen(string) +1); } else msg_data->msg = 0; return msg_data; } static void write_link_file (DATA *msg_data, const char *unique_fname, int width) { FILE *outfp; char filepath[MAX_PATH + 1]; int len; snprintf (filepath, MAX_PATH + 1, "%s/%s", discussion_path, unique_fname); outfp = fopen (filepath, "w"); if (!outfp) cs_critical_error (ERR_FOPEN_WRITE_FAILED, ""); fprintf (outfp, "%s\n", msg_data->url); len = strlen(msg_data->msg); if(len < width || USE_TEXTAREA_HARD_WRAP) fprintf (outfp, "%s\n", msg_data->msg); else write_folded(outfp, msg_data->msg, width); /* shared_fold_file.c */ fclose (outfp); } /* note that this creates the file */ void get_unique_fname(char *unique_fname, const char *base_dir, const char *filetype, time_t *time_sent) { int fd; fd = get_unique_fd(base_dir, filetype, unique_fname, time_sent); close(fd); } static void process_message_file (DATA *msg_data, char *msg_fname, time_t * time_sent, int width) { get_unique_fname (msg_fname, discussion_path, "msg", time_sent); write_link_file (msg_data, msg_fname, width); } static void complete_send (const char *msg_fname, SESSION *user, time_t time_sent, int hide, const char *subject) { FILE *inbox_fp; int info_fd, inbox_fd; struct stat buf; NEWS_PERSON person; char info_fname[MAX_FILENAME + 1]; char inbox_fname[MAX_PATH + 1]; int msg_id; CENTRAL_INBOX_RECORD inbox_record, new_inbox_record; int inbox_record_size, news_person_size; /* memorize the sizes of these data structures, ** so we don't have to repeatedly call sizeof() */ inbox_record_size = sizeof(CENTRAL_INBOX_RECORD); news_person_size = sizeof(NEWS_PERSON); /* this user has already read this message ** set a NEWS_PERSON record to be written ** to the end of the new inf file. */ strncpy(person.username,user->username, MAX_USERNAME + 1); strncpy(person.realname, user->realname, MAX_NAME + 1); person.time_read = time_sent; person.user_unlocked = 0; /* set up as much of the new inbox record as we can before locking ** the inbox.dat file */ strncpy(new_inbox_record.info.msg_fname, msg_fname, MAX_FILENAME + 1); strncpy(new_inbox_record.info.sender, user->username, MAX_USERNAME + 1); strncpy(new_inbox_record.info.sender_realname, user->realname, MAX_NAME + 1); strncpy(new_inbox_record.info.receiver_username,"",MAX_USERNAME + 1); strncpy(new_inbox_record.info.subject, subject, MAX_SUBJECT + 1); new_inbox_record.info.time_sent = time_sent; new_inbox_record.info.attachments = 0; new_inbox_record.info.sender_team = user->team; new_inbox_record.info.reply_to = -1; /* get the name of the 'inf' file to do so, we need to open ** (create) the file */ info_fd = get_unique_fd (discussion_path,"inf", info_fname, &time_sent); /* don't bother to lock it, since no one knows it's there yet! */ strncpy(new_inbox_record.info_fname,info_fname,MAX_FILENAME + 1); new_inbox_record.release_time = 0; new_inbox_record.unrelease_time = 0; new_inbox_record.status = hide? TEACHER_HIDDEN: NORMAL; /* now open and lock the inbox.dat file */ snprintf(inbox_fname,MAX_PATH + 1,"%s%s",central_discussion_path,INBOX_FNAME); inbox_fp = fopen(inbox_fname,"a+"); if(!inbox_fp) /* couldn't open or create inbox.dat */ cs_critical_error(ERR_FOPEN_WRITE_FAILED,""); inbox_fd = fileno(inbox_fp); get_exclusive_lock(inbox_fd, 1); /* shared_lock.c */ /* get the next available msg_id, by incrementing the msg_id of the ** last msg in the inbox.dat file */ fstat(inbox_fd, &buf); if(!buf.st_size) /* this is the first message */ msg_id = 1; else { if(fseek(inbox_fp,-inbox_record_size,SEEK_END) == -1) cs_critical_error(ERR_FSEEK_FAILED, ""); if(fread( &inbox_record, inbox_record_size, 1, inbox_fp) != 1) cs_critical_error(ERR_FREAD_FAILED, ""); msg_id = inbox_record.info.msg_id + 1; } new_inbox_record.info.msg_id = msg_id; new_inbox_record.info.topic_id = msg_id; if(fseek(inbox_fp,0,SEEK_END) == -1) cs_critical_error(ERR_FSEEK_FAILED, ""); if(fwrite(&new_inbox_record, inbox_record_size,1,inbox_fp) != 1) cs_critical_error(ERR_FWRITE_FAILED, ""); /* now write the info file */ if (write (info_fd, &new_inbox_record.info, sizeof (NEWS_INFO)) != sizeof(NEWS_INFO)) cs_critical_error (ERR_FWRITE_FAILED, ""); if(write (info_fd,&person, sizeof(NEWS_PERSON))!= sizeof(NEWS_PERSON)) cs_critical_error (ERR_FWRITE_FAILED, ""); close (info_fd); release_lock(inbox_fd); /* shared_lock.c */ fclose(inbox_fp); write_user_inbox_record(msg_id, time_sent); /* shared_news_util.c */ } static void back_up (char *program) { char temp[MAX_PATH + 1]; translate_url_substitutes (temp, program, MAX_PATH + 1, 0); /* shared_translate_url.c */ printf ("Location: %s\n\n", temp); } int main (void) { char course[MAX_PATH + 1]; /* from crs=? command line */ char key[MAX_KEY + 1]; /* from id=? command line */ char from[MAX_PATH + 1]; /* from from=? command line */ int hide; /* from hide=? command line */ char subject[MAX_SUBJECT +1]; char msg_fname[MAX_FILENAME + 1]; /* name given to the message */ time_t time_sent; DATA *msg_data; int width; SESSION user; CONFIG_STRUCT conf; /* the configuration read from config file */ cs_cgi_init(); msg_data = read_parameters (course, key, from, &hide, subject, &width); read_configuration_file (course, &conf); /* shared_util.c */ validate_key (key, &user, &conf); /* shared_util.c */ if (user.group != FACULTY) cs_critical_error (ERR_REQUEST_DENIED, ""); set_discussion_names (conf.course_path, user.username, INTERNET_RESOURCES); /* #included */ time_sent = time (NULL); process_message_file (msg_data, msg_fname, &time_sent, width); complete_send(msg_fname,&user,time_sent,hide, subject); back_up (from); free_data(msg_data); cs_cgi_destroy(); return 0; }