#include #include /* for free() */ #include #include #include #include /* for symlink() */ #include #include "global.h" #include "custom.h" SESSION user; CONFIG_STRUCT conf; /* the configuration read from config file */ #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_hotpot_parser.h" #include "manhat-lib/shared_hotpot_exam_util.h" #include "manhat-lib/shared_server_string.h" #include "manhat-lib/shared_access.h" static void read_parameters (char *course, char *key, char *sender, char *info_fname, long *offset) { char tmp[25]; cs_get_required_parameter ("crs", course, MAX_FILENAME); /* shared_cgi_util.c */ cs_get_required_parameter ("id", key, MAX_KEY); cs_get_required_parameter ("sender", sender, MAX_USERNAME); cs_get_required_parameter ("inf", info_fname, MAX_FILENAME); cs_get_required_parameter ("loc", tmp, 24); *offset = atol(tmp); } static void do_header(const char *symlink_fname) { char server_string[MAX_PATH + 1]; char url[MAX_PATH + 1]; get_server_string(server_string, MAX_PATH + 1); /* shared_server_string.c */ snprintf(url, MAX_PATH +1, "%s%slinks/%s/", server_string, IMAGE_PATH, symlink_fname); cs_set_value("base_url", url); if(quiz_data.pg_bg_color) cs_set_value("bg_color", quiz_data.pg_bg_color); if(quiz_data.text_color) cs_set_value("text_color", quiz_data.text_color); if(quiz_data.link_color) cs_set_value("link_color", quiz_data.link_color); if(quiz_data.vlink_color) cs_set_value("vlink_color", quiz_data.vlink_color); if(quiz_data.font_face) cs_set_value("font_face", quiz_data.font_face); if(quiz_data.ex_bg_color) cs_set_value("ex_bg_color", quiz_data.ex_bg_color); } static void print_string(char *string, const char *prefix) { #define MAX_TMP_NAME 30 char *ptr; int line_num =0; int chars_added = 0; int j =0; char name[MAX_TMP_NAME]; char *buf =0; buf = (char*)malloc(sizeof(char) * (strlen(string) + 1)); if(!buf) cs_critical_error(ERR_MALLOC_FAILED, ""); *buf = '\0'; for(ptr=string; *ptr; ptr++) { if(*ptr == '\n') { buf[j] = *ptr; buf[j+1] = '\0'; snprintf(name, MAX_PATH +1, "%s.line.%d", prefix, line_num); cs_set_value(name, buf); buf[0] = '\0'; j = 0; line_num++; chars_added = 0; } else { buf[j] = *ptr; j++; buf[j] = '\0'; chars_added = 1; } } if(chars_added && strlen(buf)) { snprintf(name, MAX_PATH +1, "%s.line.%d", prefix, line_num); cs_set_value(name, buf); } free(buf); #undef MAX_TMP_NAME } static void do_instructions() { if(quiz_data.title) { cs_set_value("quiz.title", quiz_data.title); if(quiz_data.title_color) cs_set_value("quiz.title_color", quiz_data.title_color); } if(quiz_data.sub_title) print_string(quiz_data.sub_title, "quiz.sub_title"); if(quiz_data.instructions) print_string(quiz_data.instructions, "quiz.instruction"); } /* hotpot_answer_letters is global in shared_hotpot_parser.h */ static void do_questions() { #define MAX_TMP_NAME 40 int q,a =0; QUESTION_NODE *q_ptr; ANSWER_NODE *a_ptr; char url[MAX_PATH +1]; char name[MAX_TMP_NAME]; char temp[MAX_TMP_NAME]; snprintf(url, MAX_PATH +1, "%s/%s",ALIAS, "hotpot_exam_score"); cs_set_value("action", url); for(q_ptr = quiz_data.head, q=0 ; q_ptr; q_ptr=q_ptr->next, q++) { snprintf(name, MAX_TMP_NAME, "quiz.ques.%d.body", q); print_string(q_ptr->question, name); snprintf(name, MAX_TMP_NAME, "quiz.ques.%d.type", q); switch(q_ptr->question_type) { case 0: cs_set_value(name,"mc"); break; case 1: cs_set_value(name, "short"); break; case 2: cs_set_value(name,"mc_multi"); break; default: cs_set_value(name,"unknown"); break; } if(q_ptr->question_type == MC) /* multiple-choice */ { for(a_ptr = q_ptr->head, a=0; a_ptr; a_ptr = a_ptr->next, a++) { if(a >= MAX_HOTPOT_CHOICES) /* shared_hotpot_parser.h */ break; snprintf(name, MAX_TMP_NAME, "quiz.ques.%d.mc.%d.letter", q, a); snprintf(temp, MAX_TMP_NAME, "%c", hotpot_answer_letters[a]); cs_set_value(name, temp); /* why are letter and value same ?? */ snprintf(name, MAX_TMP_NAME, "quiz.ques.%d.mc.%d.value", q, a); cs_set_value(name, temp); snprintf(name, MAX_TMP_NAME, "quiz.ques.%d.mc.%d.name", q, a); snprintf(temp, MAX_TMP_NAME, "q%d", q); cs_set_value(name, temp); snprintf(name, MAX_TMP_NAME, "quiz.ques.%d.mc.%d.answer", q, a); cs_set_value(name, a_ptr->answer); } } else if(q_ptr->question_type == MC_MULTI) /*multiple-select */ { for(a_ptr = q_ptr->head, a=0; a_ptr; a_ptr = a_ptr->next, a++) { if(a >= MAX_HOTPOT_CHOICES) /* shared_hotpot_parser.h */ break; snprintf(name, MAX_TMP_NAME, "quiz.ques.%d.mcmulti.%d.letter", q, a); snprintf(temp, MAX_TMP_NAME, "%c", hotpot_answer_letters[a]); cs_set_value(name, temp); snprintf(name, MAX_TMP_NAME, "quiz.ques.%d.mcmulti.%d.value", q, a); cs_set_value(name, temp); snprintf(name, MAX_TMP_NAME, "quiz.ques.%d.mcmulti.%d.name", q, a); snprintf(temp, MAX_TMP_NAME, "q%d", q); cs_set_value(name, temp); snprintf(name, MAX_TMP_NAME, "quiz.ques.%d.mcmulti.%d.answer", q, a); cs_set_value(name, a_ptr->answer); } } else if(q_ptr ->question_type == SHORT) { a=0; snprintf(name, MAX_TMP_NAME, "quiz.ques.%d.short.%d.name", q, a); snprintf(temp, MAX_TMP_NAME, "q%d", q); cs_set_value(name, temp); } } cs_set_int_value("quiz_total", q); #undef MAX_TMP_NAME } static void do_submit( char *course, char *key, char *sender, char *info_fname, long offset, time_t *current_time, int access) { char temp[MAX_PATH +1]; *current_time = time(NULL); if(access != ACCESS_CAPTURE) { cs_set_int_value("access", 1); cs_set_value("crs", course); cs_set_value("id", key); cs_set_value("sender", sender); cs_set_value("inf", info_fname); snprintf(temp, MAX_PATH, "%ld", (long)*current_time); cs_set_value("test", temp); snprintf(temp, MAX_PATH, "%ld", offset); cs_set_value("loc", temp); } } static void show_quiz( char *course, char *key, char *sender, const char *dirname, char *info_fname, long offset, const SESSION *user, const CONFIG_STRUCT *conf, time_t *current_time) { char symlink_fname[MAX_FILENAME + 1]; create_hotpot_exam_symlink(conf->course_path, sender, dirname, user, course, symlink_fname, conf->access); /*shared_hotpot_exam_util.c */ do_header(symlink_fname); do_instructions(); do_questions(); do_submit(course,key,sender,info_fname, offset, current_time, conf->access); } /* writes current_time to the beginning of ** the hotpot score file, but only if the ** file is new, or if the time that's stored ** in the file is 0. ** These restrictions prevent someone from ** reloading the web page to reset the timer **/ static void write_viewed_flag(time_t current_time, SESSION *user, const char *sender_username, const char *info_fname, const char *course_path) { char path[MAX_PATH + 1]; FILE *fp; int fd; time_t last_time; int new_file = 0; get_hotpot_score_path(course_path, user->username, sender_username,info_fname, path); /* shared_hotpot_exam_util.c */ fp = fopen(path,"r+"); if(!fp) { fp = fopen(path, "w"); if(!fp) cs_critical_error(ERR_FOPEN_WRITE_FAILED, path); new_file = 1; } fd = fileno(fp); get_exclusive_lock(fd,1); /* shared_lock.c */ if(new_file) last_time = 0; else { if(fread(&last_time, sizeof(time_t), 1, fp) != 1) cs_critical_error(ERR_FREAD_FAILED, path); if(fseek(fp, 0,SEEK_SET)) cs_critical_error(ERR_FSEEK_FAILED, path); } if(!last_time) { if(fwrite(¤t_time, sizeof(time_t),1, fp) != 1) cs_critical_error(ERR_FWRITE_FAILED, path); } release_lock(fd); /* shared_lock.c */ fclose(fp); } int main (void) { char course[MAX_PATH + 1]; /* from crs=? command line */ char key[MAX_KEY + 1]; /* from id=? command line */ char sender[MAX_USERNAME + 1]; /* from user=? command line */ char info_fname[MAX_FILENAME + 1]; /* from info=? cmd line */ long offset; /* from loc=? cmd line */ char source_path[MAX_PATH + 1]; char dirname[MAX_FILENAME + 1]; time_t current_time; int can_write; /* can this user write to this course? */ cs_cgi_init(); /* shared_cs_util.c */ read_parameters (course, key, sender, info_fname, &offset); read_configuration_file (course, &conf); /* shared_util.c */ validate_key (key, &user, &conf); /* shared_util.c */ can_write = has_write_permission(&user, &conf); /* shared_access.c */ if( (user.group == STUDENT) && !can_write) /* don't allow students without write access to see the exam */ access_denied_error(); /* shared_access.h */ get_hotpot_exam_source_fname (source_path, dirname, conf.course_path, sender, info_fname); /* shared_hotpot_exam_util.c */ if(parse_hotpot_file(source_path)) /* shared_hotpot_parser.c */ cs_critical_error(ERR_ERROR_PARSING_HOTPOT_FILE, ""); show_quiz(course,key,sender,dirname, info_fname, offset, &user, &conf, ¤t_time); free_quiz_data(); /* shared_hotpot_parser.c */ if(user.group == STUDENT) write_viewed_flag(current_time, &user, sender, info_fname, conf.course_path); else cs_set_int_value("teacher_test_exam", 1); cs_set_course_info(&conf); /* shared_cs_util.c */ cs_set_current_time(); /* shared_cs_util.c */ cs_set_server_name(); /* shared_cs_util.c */ cs_cgi_display("hotpot_exam_present", 1); /* shared_cs_util.c */ cs_cgi_destroy(); /* shared_cs_util.c */ return 0; }