#include #include #include #include #include #include #include "global.h" #include "custom.h" /* for date FORMAT strings */ #include "survey.h" #include "manhat-lib/shared_util.h" #include "manhat-lib/shared_lock.h" #include "manhat-lib/shared_news_util.h" #include "manhat-lib/shared_file_util.h" #include "manhat-lib/shared_cs_util.h" #include "manhat-lib/shared_time.h" #include "manhat-lib/shared_copy_file.h" #include "manhat-lib/shared_person_list.h" #include "manhat-lib/shared_fold_file.h" static char* read_parameters (char *course, char *key, int *hide, char *subject, time_t *release_time, int *student_view_results, int *student_view_again, int *student_answer_required, int *public, char *dir, int *width) { char tmp[80]; char *string; char *msg; cs_get_required_parameter ("crs", course, MAX_PATH); cs_get_required_parameter ("id", key, MAX_KEY); cs_get_required_parameter ("subject", subject, MAX_SUBJECT); cs_get_required_parameter ("width", tmp, 79); *width = atoi(tmp); cs_get_required_parameter ("dir", dir, MAX_PATH); cs_get_required_parameter ("public", tmp, 10); *public = atoi(tmp); cs_get_optional_parameter ("student_1", tmp, 19); if(strlen(tmp)>0) *student_view_results = 1; else *student_view_results =0; cs_get_optional_parameter ("student_2", tmp, 19); if(strlen(tmp)>0) *student_view_again = 1; else *student_view_again =0; cs_get_optional_parameter ("student_3", tmp, 19); if(strlen(tmp)>0) *student_answer_required = 1; else *student_answer_required =0; cs_get_optional_parameter ("hide", tmp, 19); if(strlen(tmp)>0) *hide = 1; else *hide =0; string = hdf_get_value(global_cgi->hdf, "Query.msg", 0); if(!string) { msg = (char *) malloc(sizeof(char)*2); if(!msg) cs_critical_error(ERR_MALLOC_FAILED, ""); *msg= '\0'; } else { msg = (char *) malloc( (strlen(string) + 1) * sizeof(char)); if(!msg) cs_critical_error(ERR_MALLOC_FAILED, ""); strcpy(msg,string); } *release_time = get_time("result"); /* shared_time.c */ return msg; } static void write_msg_file ( char *msg, const char *unique_fname, int width) { FILE *outfp; char filepath[MAX_PATH + 1]; int len =0; snprintf (filepath, MAX_PATH + 1, "%s/%s", discussion_path, unique_fname); if(msg) len = strlen(msg); outfp = fopen (filepath, "w"); if (!outfp) cs_critical_error (ERR_FOPEN_WRITE_FAILED, ""); if(len < width || USE_TEXTAREA_HARD_WRAP) fprintf (outfp, "%s", msg); else write_folded(outfp, 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 ( char *msg, char *msg_fname, time_t * time_sent, int width) { get_unique_fname (msg_fname, discussion_path, "msg", time_sent); write_msg_file (msg, msg_fname, width); } static void complete_send (const char *msg_fname, SESSION *user, time_t time_sent, int hide, const char *subject, const char *survey_dir, CONFIG_STRUCT *conf) { 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; long offset; CENTRAL_INBOX_RECORD inbox_record, new_inbox_record; int inbox_record_size, attachment_size; ATTACHMENT attach; /* memorize the sizes of these data structures, ** so we don't have to repeatedly call sizeof() */ inbox_record_size = sizeof(CENTRAL_INBOX_RECORD); attachment_size = sizeof(ATTACHMENT); /* 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 = -1; /* pretend it's a web site attached */ 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; offset =0; } 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; offset = inbox_record_size * inbox_record.info.msg_id; } 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, ""); strncpy (attach.unique_fname, survey_dir, MAX_FILENAME + 1); strncpy (attach.orig_fname, SURVEY_XML_FNAME, MAX_FILENAME + 1); if (write (info_fd, &attach, attachment_size) != attachment_size) cs_critical_error (ERR_FWRITE_FAILED, ""); if(write (info_fd,&person, sizeof(NEWS_PERSON))!= sizeof(NEWS_PERSON)) cs_critical_error (ERR_FWRITE_FAILED, ""); release_lock(inbox_fd); /* shared_lock.c */ fclose(inbox_fp); write_user_inbox_record(msg_id, time_sent); /* shared_news_util.c */ } /** The selected survey needs to be copied into a new *** directory under the sender's 'surveys' directory. *** A file named SURVEY_RELEASE_FNAME, which records the *** results time is also created within that new directory. *** Returns name of the newly created directory in *** 'directory_fname' ***/ static void create_survey_dir(int public, const char *dir, time_t results_time, int student_view_results, int student_view_again, int student_answer_required, const char *username, char *xml_dir, time_t *time_sent, char *directory_fname, int student_count) { char src_path[MAX_PATH + 1]; char dest_path[MAX_PATH + 1]; char dest_dir[MAX_PATH + 1]; SURVEY_RELEASE_RECORD survey_info; FILE *fp; /*** create a randomly named directory to hold the survey files ***/ get_unique_fname (directory_fname, discussion_path, NORMAL_WEBSITE_DIR_PREFIX, time_sent); snprintf (dest_dir, MAX_PATH + 1, "%s%s", discussion_path, directory_fname); unlink(dest_dir); /* because get_unique_fname() created the file */ if(mkdir (dest_dir, 0777)) cs_critical_error(ERR_ERROR_CREATING_SURVEY_DIRECTORY, ""); snprintf(dest_path,MAX_PATH + 1, "%s/%s", dest_dir, SURVEY_XML_FNAME); /** The 'source' xml file to be copied is either in the user's private *** store of surveys, or is one of the public surveys **/ if(public) snprintf(src_path, MAX_PATH + 1, "../%s/_%s_/%s/%s", SURVEY_DIR, ADMIN_DIR,dir, SURVEY_XML_FNAME); else snprintf(src_path, MAX_PATH + 1, "../%s/%s/%s/%s", SURVEY_DIR, username, dir, SURVEY_XML_FNAME); copy_file(src_path, dest_path); /* shared_copy_file.c */ /* now write the info file, which records when the teacher can see the results */ survey_info.results_time = results_time; survey_info.student_view_results = student_view_results; survey_info.student_view_again = student_view_again; survey_info.student_answer_required = student_answer_required; survey_info.future2 = 0; snprintf(dest_path, MAX_PATH + 1, "%s/%s", dest_dir, SURVEY_RELEASE_FNAME); fp = fopen(dest_path, "w"); if(!fp) cs_critical_error(ERR_FOPEN_WRITE_FAILED, ""); if(fwrite(&survey_info, sizeof(SURVEY_RELEASE_RECORD), 1, fp) != 1) cs_critical_error(ERR_FWRITE_FAILED, ""); fclose(fp); /* create the results file, with a few opening tags */ snprintf(dest_path, MAX_PATH + 1, "%s/%s", dest_dir, SURVEY_RESULT_FNAME); fp = fopen(dest_path, "w"); if(!fp) cs_critical_error(ERR_FOPEN_WRITE_FAILED, ""); fprintf(fp, "\n"); fprintf(fp, "\n"); fprintf(fp, " %d\n", student_count); fprintf(fp, SURVEY_RESULT_END_TAG); fclose(fp); } static int student_count(CONFIG_STRUCT *conf) { P_NODE *head; int count; head = build_option_person_list(conf); /* shared_person_list.c */ count = count_students(head); /* shared_person_list.c */ free_option_person_list(head); /* shared_person_list.c */ return count; } int main (void) { char course[MAX_PATH + 1]; /* from crs=? command line */ char key[MAX_KEY + 1]; /* from id=? command line */ int hide; /* from hide=? command line */ char subject[MAX_SUBJECT +1]; /*from subject= command line */ time_t result_time; /* derived from command line */ int student_view_results; /* allow students to view the results? - from cmd line */ int student_view_again; /* allow students to view the survey after they take it? - from cmd line */ int student_answer_required; int public; /* from public = command line */ char dir[MAX_PATH + 1]; /* from dir = command line - name of survey to be copied */ char *msg; /* from msg = command line */ char survey_dir[MAX_FILENAME + 1]; /* mkstemp() name given to the directory where the survey ** xml files are copied */ time_t time_sent; char msg_fname[MAX_FILENAME + 1]; /* mkstemp() name given to the msg file */ int number_students; /* how many students are in this class ? */ int width; SESSION user; CONFIG_STRUCT conf; /* the configuration read from config file */ cs_cgi_init(); msg = read_parameters (course, key, &hide, subject,&result_time, &student_view_results, &student_view_again, &student_answer_required, &public, dir, &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, SURVEYS); /* #included */ time_sent = time (NULL); process_message_file (msg, msg_fname, &time_sent, width); /* writes the message */ number_students = student_count(&conf); create_survey_dir(public,dir,result_time, student_view_results, student_view_again, student_answer_required, user.username, dir, &time_sent, survey_dir, number_students); complete_send(msg_fname,&user,time_sent,hide, subject, survey_dir, &conf); if(msg) free(msg); printf ("Location: %s?crs=%s&id=%s&grp=%d\n\n", "news_topic",course, key, SURVEYS); cs_cgi_destroy(); return 0; }