#include #include /* for stat() */ #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_cs_util.h" #include "manhat-lib/shared_news_util.h" #include "manhat-lib/shared_lock.h" #include "manhat-lib/shared_person_list.h" typedef struct news_person_node { NEWS_PERSON data; struct news_person_node *next; } NEWS_PERSON_NODE; static void read_parameters (char *course, char *key, long *offset) { char tmp[MAX_FILENAME + 1]; /* for holding the long value, length should be long enough, don't you think? */ cs_get_required_parameter ("crs", course, MAX_PATH); /* shared_cgi_util.c */ cs_get_required_parameter ("id", key, MAX_KEY); /* shared_cgi_util.c */ cs_get_required_parameter ("loc", tmp, MAX_FILENAME); /* shared_cgi_util.c */ *offset = atol (tmp); } void read_release_file(const char *course_path, const char *sender, const char *survey_dir, SURVEY_RELEASE_RECORD *release) { char path[MAX_PATH + 1]; FILE *fp; snprintf(path, MAX_PATH + 1, "%s%s/%s/%s/%s/%s", course_path, PEOPLE_DIR, sender, SURVEY_DIR, survey_dir, SURVEY_RELEASE_FNAME); fp = fopen(path, "r"); if(!fp) cs_critical_error(ERR_FOPEN_READ_FAILED, ""); if(fread(release, sizeof(SURVEY_RELEASE_RECORD), 1, fp) != 1) cs_critical_error(ERR_FREAD_FAILED, ""); fclose(fp); } static NEWS_PERSON_NODE * free_news_person_list (NEWS_PERSON_NODE *person_head) { NEWS_PERSON_NODE *pptr; while (person_head) { pptr = person_head; person_head = person_head->next; free (pptr); } return person_head; } static int count_student_respondents(NEWS_PERSON_NODE *respondent_head, P_NODE *roster_head) { int student_count = 0; P_NODE *roster_ptr; NEWS_PERSON_NODE *resp_ptr; for(resp_ptr = respondent_head; resp_ptr; resp_ptr = resp_ptr->next) { for(roster_ptr = roster_head; roster_ptr; roster_ptr = roster_ptr->next) if(!strcmp(roster_ptr->data.username, resp_ptr->data.username)) { if(roster_ptr->data.group == STUDENT) student_count++; break; } } return student_count; } static void count_respondents(NEWS_PERSON_NODE *person_head, int *number_respondents, int *total_students, CONFIG_STRUCT *conf) { P_NODE *roster_head; roster_head = build_option_person_list(conf); /* shared_option_person_list.c */ *number_respondents = count_student_respondents(person_head, roster_head); *total_students = count_students(roster_head); /* shared_option_person_list.c */ free_option_person_list(roster_head); /* shared_option_person_list.c */ } /* reads the inbox file and then the corresponding *.inf file, to get everything ** ready to be displayed **/ static void process_inbox_record (long offset, CENTRAL_INBOX_RECORD * inbox, NEWS_INFO * infofile_info, CONFIG_STRUCT *conf, SESSION *user, SURVEY_RELEASE_RECORD *release, char *survey_dir, int *number_respondents, int *total_students) { FILE *fp; int fd; char infopath[MAX_PATH + 1]; ATTACHMENT attachment; char inbox_path[MAX_PATH + 1]; /* full path to inbox.dat */ NEWS_PERSON person; NEWS_PERSON_NODE *person_head = 0, *pptr = 0; snprintf(inbox_path,MAX_PATH + 1,"%s%s",central_discussion_path,INBOX_FNAME); fp = fopen(inbox_path,"r"); if (!fp) cs_critical_error (ERR_FOPEN_READ_FAILED, ""); fd = fileno(fp); get_shared_lock(fd, 1); /* shared_lock.c */ if (fseek (fp, offset, SEEK_SET)) cs_critical_error (ERR_FSEEK_FAILED, ""); if (fread (inbox, sizeof (CENTRAL_INBOX_RECORD), 1, fp) != 1) cs_critical_error (ERR_FREAD_FAILED, ""); release_lock(fd); /* shared_lock.c */ fclose (fp); /*** now read the info file */ snprintf (infopath, MAX_PATH + 1, "%s%s/%s/%s/%s", conf->course_path, PEOPLE_DIR, inbox->info.sender, discussion_fname, inbox->info_fname); fp = fopen (infopath, "r"); if (!fp) cs_critical_error (ERR_FOPEN_READ_FAILED, ""); fd = fileno(fp); get_shared_lock(fd,1); /* shared_lock.c */ if (fread (infofile_info, sizeof (NEWS_INFO), 1, fp) != 1) cs_critical_error (ERR_FREAD_FAILED, ""); /* read the attachment to extract the name of the survey directory*/ if (fread (&attachment, sizeof (ATTACHMENT), 1, fp) != 1) cs_critical_error (ERR_FREAD_FAILED, ""); strncpy(survey_dir, attachment.unique_fname, MAX_FILENAME + 1); read_release_file(conf->course_path, inbox->info.sender, survey_dir, release); *number_respondents = 0; *total_students = 0; /* count the number of respondents */ if(release->student_view_results || user->group == FACULTY) { while (fread (&person, sizeof (NEWS_PERSON), 1, fp) == 1) { if (!person_head) { person_head = (NEWS_PERSON_NODE *) malloc (sizeof (NEWS_PERSON_NODE)); if (!person_head) cs_critical_error (ERR_MALLOC_FAILED, ""); pptr = person_head; } else { pptr->next = (NEWS_PERSON_NODE *) malloc (sizeof (NEWS_PERSON_NODE)); if (!pptr->next) cs_critical_error (ERR_MALLOC_FAILED, ""); pptr = pptr->next; } pptr->data = person; pptr->next = 0; } count_respondents(person_head, number_respondents, total_students, conf); person_head = free_news_person_list(person_head); } release_lock(fd); /* shared_lock.c */ fclose (fp); } static void print_basic_info ( char *sender, NEWS_INFO * infofile_info, SESSION *user, CONFIG_STRUCT *conf, SURVEY_RELEASE_RECORD *release, int number_respondents, int total_students) { char timestring[MAX_TIMESTRING +1]; char url[MAX_PATH +1]; char *scaped_subject; cs_set_course_info(conf); cs_set_current_time(); cs_html_escape_string(infofile_info->subject, &scaped_subject); cs_set_value("subject", scaped_subject); free(scaped_subject); cs_set_value("sender", infofile_info->sender_realname); strftime (timestring, MAX_TIMESTRING, DOW_DATE_TIME_FORMAT, localtime (&(infofile_info->time_sent)) ); cs_set_value("send_time", timestring); /** print result time */ strftime (timestring, MAX_TIMESTRING, DOW_DATE_TIME_FORMAT, localtime (&(release->results_time)) ); cs_set_value("release_time", timestring); /** can students view results? */ cs_set_int_value("review_result", release->student_view_results); cs_set_int_value("review_survey", release->student_view_again); cs_set_int_value("answer_required", release->student_answer_required); /* total respondents to-date */ if((user->group == FACULTY) || (release->student_view_results)) { snprintf(url, MAX_PATH +1, "%d/%d (%.1f %%)",number_respondents, total_students, ((float) number_respondents/total_students) * 100.0); cs_set_value("total", url); } } static void insert_results_links(const char *sender, const char *info_fname, const char *course, const char *key) { char url[MAX_PATH +1]; /* set url to graphs */ snprintf(url, MAX_PATH +1, "%s?crs=%s&id=%s&sender=%s&inf=%s", "survey_module_bar_graph", course, key, sender, info_fname); cs_set_value("graph_url", url); /* set url to tables */ snprintf(url, MAX_PATH +1, "%s?crs=%s&id=%s&sender=%s&inf=%s", "survey_module_table", course, key, sender, info_fname); cs_set_value("table_url", url); /* set url to csv file */ snprintf(url, MAX_PATH +1, "%s?crs=%s&id=%s&sender=%s&inf=%s&csv=yes&ext=.csv", "survey_module_table", course, key, sender, info_fname); cs_set_value("csv_url", url); } static void print_results_not_available(time_t results_time) { char timestring[MAX_TIMESTRING + 1]; strftime (timestring, MAX_TIMESTRING, DOW_DATE_TIME_FORMAT, localtime (&results_time)); cs_set_value("result_time", timestring); } static void display_info (char *course, char *key, long offset, CONFIG_STRUCT *conf, SESSION *user) { CENTRAL_INBOX_RECORD inbox; NEWS_INFO infofile_info; SURVEY_RELEASE_RECORD release; char survey_dir[MAX_FILENAME + 1]; time_t now; int number_respondents, total_students; process_inbox_record (offset, &inbox, &infofile_info, conf, user, &release, survey_dir, &number_respondents, &total_students); /* print the header info */ print_basic_info (inbox.info.sender, &infofile_info, user, conf, &release, number_respondents, total_students); now = time(NULL); if(release.student_view_results || (user->group == FACULTY)) { cs_set_int_value("show_results", 1); if(release.results_time <= now) insert_results_links(inbox.info.sender, inbox.info_fname, course, key); else print_results_not_available(release.results_time); } } 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=? command line */ SESSION user; CONFIG_STRUCT conf; /* the configuration read from config file */ cs_cgi_init(); read_parameters (course, key, &offset); read_configuration_file (course, &conf); /* shared_util.c */ validate_key (key, &user, &conf); /* shared_util.c */ set_discussion_names (conf.course_path, user.username, SURVEYS); /* shared_news_util.c */ display_info (course, key, offset, &conf, &user); cs_cgi_display("survey_info", 1); cs_cgi_destroy(); return 0; }