#include #include #include #include #include #include "ClearSilver.h" #include "sqlite3.h" #include "global.h" #include "custom.h" /* for date FORMAT strings */ #include "grade.h" /* for date FORMAT strings */ #include "manhat-lib/shared_util.h" #include "manhat-lib/shared_grade_book_menu.h" #include "manhat-lib/shared_grade_book_util.h" #include "manhat-lib/shared_time.h" void read_parameters ( char *course, char *key, int *save_option, int *item_id) { char temp[MAX_KEY +1]; char *ptr; cs_get_required_parameter("crs", course, MAX_PATH); cs_get_required_parameter("id", key, MAX_KEY); cs_get_required_parameter("save_option", temp, MAX_KEY); if(strcmp(temp, "save") == 0) *save_option = 1; /* save new item */ else if(strcmp(temp, "no") == 0) *save_option = 0; else if(strcmp(temp, "update") == 0) /* update items */ *save_option = 2; else /* delete items */ { ptr = strstr(temp, "delete"); if(!ptr) cs_critical_error(ERR_GRADE_BOOK_UNDEFINED_OPERATION, "grade_book_items_save"); ptr = strchr(temp, ':'); if(ptr) *ptr = '\0'; *save_option = 3; ptr++; *item_id = atoi(ptr); } } SCALE_LIST *getLetterGrades(int number, int *error) { #define MAX_TMP 40 SCALE_LIST *list = 0; SCALE *ptr; char name[MAX_TMP]; char *letter = 0; char *points = 0; int error_count = 0; int i; list = (SCALE_LIST *)malloc(sizeof(SCALE_LIST )); if(!list) cs_critical_error(ERR_MALLOC_FAILED, "get_letter_grades"); list->head = 0; list->current =0; for(i = 0; ihdf, name, ""); snprintf(name, MAX_TMP, "Query.points_%d", i); points = hdf_get_value(global_cgi->hdf, name, ""); if(strlen(letter) && strlen(points)) { if(check_spe_char(letter) && check_float_number(points)) { ptr = (SCALE*) malloc (sizeof(SCALE)); if(!ptr) cs_critical_error(ERR_MALLOC_FAILED, "get_letter_grades loop"); ptr->next =0; strncpy(ptr->grade, letter, MAX_GRADE_LEN +1); ptr->start = atof(points); if(!list->head) list->head = ptr; else list->current->next = ptr; list->current = ptr; } else error_count++; } } *error = error_count; return list; #undef MAX_TMP } SCALE_LIST * validate_new_item(ITEM *new_item, int *errors) { char temp[MAX_PATH +1]; int number; SCALE_LIST *list = 0; int count = 0; int error_count = 0; cs_get_required_parameter("item_name", temp, MAX_PATH); if(!check_spe_char(temp)) count++; else strncpy(new_item->item_name, temp, MAX_ITEM_LEN); cs_get_required_parameter("item_category", temp, MAX_PATH); if(!strcmp(temp, "-1")) count++; else new_item->cat_id = atoi(temp); cs_get_required_parameter("item_extra_credit", new_item->extra_credit, MAX_EXTRA_CREDIT_LEN); cs_get_required_parameter("item_due_date", temp, MAX_PATH); new_item->due_date = get_time("item_due_date"); cs_get_required_parameter("grade_method", temp, MAX_PATH); if(!strcmp(temp, "-1")) count++; else if(!strcmp(temp, "points")) { cs_get_required_parameter("item_points", temp, MAX_PATH); if(!check_float_number(temp)) count++; else new_item->points = atof(temp); strncpy(new_item->is_letter_grade, "no", MAX_BOOLEN_LEN +1); } else if(!strcmp(temp, "letter_grades")) { cs_get_required_parameter("number_letters", temp, MAX_PATH); number = atoi(temp); list = getLetterGrades(number, &error_count); if(!list || !list->head) count++; strncpy(new_item->is_letter_grade, "yes", MAX_BOOLEN_LEN +1); } strncpy(new_item->grade_entered, "no", MAX_BOOLEN_LEN +1); strncpy(new_item->hide, "no", MAX_BOOLEN_LEN +1); *errors = count + error_count; return list; } void insert_item_to_db(CONFIG_STRUCT *conf, ITEM *new_item, SCALE_LIST *list) { char path[MAX_PATH +1]; int ret = 0; sqlite3 *db; char *stmt; SCALE *ptr; int new_id =0; snprintf(path, MAX_PATH +1, "%s%s/%s", conf->course_path, GRADE_BOOK_DIR, GRADE_BOOK_DB); ret = sqlite3_open(path, &db); if(ret) cs_critical_error(ERR_GRADES_DB, "insert function"); ret = sqlite3_exec(db, "Begin transaction insert_new_item", 0, 0, 0); if(ret) { sqlite3_close(db); cs_critical_error(ERR_GRADES_DB, "begin insert item function"); } stmt = sqlite3_mprintf("insert into Items values(NULL, '%q', %4.2f, %d, '%q', '%q', '%q', '%q', %d)", new_item->item_name, new_item->points, new_item->due_date, new_item->extra_credit, new_item->is_letter_grade, new_item->grade_entered, new_item->hide, new_item->cat_id); if(stmt) { ret = sqlite3_exec(db, stmt, 0, 0,0); if(ret) { sqlite3_free(stmt); sqlite3_close(db); cs_critical_error(ERR_GRADES_DB, "ERR insert new item in grade_book_items_save"); } sqlite3_free(stmt); new_id = sqlite3_last_insert_rowid(db); } else cs_critical_error(ERR_GRADES_DB, "ERR insert new item in grade_book_items_save"); if(list && list->head && strcmp(new_item->is_letter_grade, "yes") == 0) { for(ptr = list->head; ptr; ptr = ptr->next) { stmt = sqlite3_mprintf("insert into LetterGrades values(NULL, '%q', %4.2f, %d)", ptr->grade, ptr->start, new_id); if(stmt) { ret = sqlite3_exec(db, stmt, 0, 0,0); if(ret) { ret = sqlite3_exec(db, "rollback transaction insert_new_item", 0, 0, 0); sqlite3_free(stmt); sqlite3_close(db); cs_critical_error(ERR_GRADES_DB, "ERR insert new item in grade_book_items_save"); } sqlite3_free(stmt); } } } ret = sqlite3_exec(db,"commit transaction insert_new_item", 0,0,0); ret = sqlite3_exec(db,"end transaction insert_new_item", 0,0,0); sqlite3_close(db); } void save_new_item(CONFIG_STRUCT *conf) { ITEM new_item; SCALE_LIST *list = 0; int errors = 0; list = validate_new_item(&new_item, &errors); if(errors > 0) cs_critical_error(ERR_GRADE_BOOK_NEW_ITEM, "save_new_item int grade_book_items_save"); insert_item_to_db(conf, &new_item, list); if(list) free_scale_list(list); } ITEM_LIST * get_changed_items() { #define MAX_TMP_NAME 60 char name[MAX_TMP_NAME]; char temp[MAX_TMP_NAME]; int number = hdf_get_int_value(global_cgi->hdf, "Query.number_items", 0); int i; char item_name[MAX_ITEM_LEN +1]; char item_name_old[MAX_ITEM_LEN +1]; int item_cat; int item_cat_old; char extra[MAX_EXTRA_CREDIT_LEN +1]; char extra_old[MAX_EXTRA_CREDIT_LEN +1]; int item_points; int item_points_old; int item_id; char hide[MAX_BOOLEN_LEN +1]; char hide_old[MAX_BOOLEN_LEN +1]; ITEM_LIST *list; ITEM *ptr; if(!number) cs_critical_error(ERR_PARAM_MISSING, "number_items"); list = (ITEM_LIST *)malloc(sizeof(ITEM_LIST)); if(!list) cs_critical_error(ERR_MALLOC_FAILED, "get changed items"); list->head =0; list->current =0; for(i = 1; i<= number; i++) { snprintf(name, MAX_TMP_NAME, "item_id_%d", i); cs_get_required_parameter(name, temp, MAX_TMP_NAME); item_id = atoi(temp); snprintf(name, MAX_TMP_NAME, "item_name_%d", i); cs_get_required_parameter(name, item_name, MAX_ITEM_LEN); snprintf(name, MAX_TMP_NAME, "item_name_old_%d", i); cs_get_required_parameter(name, item_name_old, MAX_ITEM_LEN); snprintf(name, MAX_TMP_NAME, "item_cat_%d", i); cs_get_required_parameter(name, temp, MAX_TMP_NAME); item_cat = atoi(temp); snprintf(name, MAX_TMP_NAME, "item_name_old_%d", i); cs_get_required_parameter(name, temp, MAX_TMP_NAME); item_cat_old = atoi(temp); snprintf(name, MAX_TMP_NAME, "item_extra_%d", i); cs_get_required_parameter(name, extra, MAX_EXTRA_CREDIT_LEN); snprintf(name, MAX_TMP_NAME, "item_extra_old_%d", i); cs_get_required_parameter(name, extra_old, MAX_EXTRA_CREDIT_LEN); snprintf(name, MAX_TMP_NAME, "item_points_%d", i); cs_get_optional_parameter(name, temp, MAX_TMP_NAME); if(strlen(temp)) item_points = atof(temp); else item_points = -1; snprintf(name, MAX_TMP_NAME, "item_points_old_%d", i); cs_get_optional_parameter(name, temp, MAX_TMP_NAME); if(strlen(temp)) item_points_old = atof(temp); else item_points_old = -1; if(item_points_old != -1 && item_points == -1) cs_critical_error(ERR_PARAM_MISSING, "item_points"); snprintf(name, MAX_TMP_NAME, "item_hide_%d", i); cs_get_required_parameter(name, hide, MAX_BOOLEN_LEN); snprintf(name, MAX_TMP_NAME, "item_hide_old_%d", i); cs_get_required_parameter(name, hide_old, MAX_BOOLEN_LEN); if(strcmp(item_name, item_name_old) || strcmp(extra, extra_old) || item_cat != item_cat_old || (item_points_old != -1 && item_points != item_points_old) || strcmp(hide, hide_old)) { ptr = (ITEM*)malloc(sizeof(ITEM)); if(!ptr) cs_critical_error(ERR_MALLOC_FAILED, "get changed items"); ptr->item_id = item_id; ptr->cat_id = item_cat; strncpy(ptr->item_name, item_name, MAX_ITEM_LEN +1); strncpy(ptr->extra_credit, extra, MAX_EXTRA_CREDIT_LEN +1); ptr->points = item_points; strncpy(ptr->hide, hide, MAX_BOOLEN_LEN +1); ptr->next =0; if(!list->head) list->head = ptr; else list->current->next = ptr; list->current = ptr; } } return list; #undef MAX_TMP_NAME } void update_items(CONFIG_STRUCT *conf) { char path[MAX_PATH +1]; int ret = 0; sqlite3 *db; char *stmt; ITEM_LIST *list=0; ITEM *ptr; list = get_changed_items(); if(!list || !list->head) cs_critical_error(ERR_GRADE_BOOK_ITEM_NO_CHANGE, "update items"); snprintf(path, MAX_PATH +1, "%s%s/%s", conf->course_path, GRADE_BOOK_DIR, GRADE_BOOK_DB); ret = sqlite3_open(path, &db); if(ret) cs_critical_error(ERR_GRADES_DB, "update items"); for(ptr=list->head; ptr; ptr = ptr->next) { stmt = sqlite3_mprintf("update Items set itemName='%q', points=%4.2f, catId=%d, extraCredit='%q', hide='%q' where itemId=%d", ptr->item_name, ptr->points, ptr->cat_id, ptr->extra_credit, ptr->hide, ptr->item_id); if(stmt) { ret = sqlite3_exec(db, stmt, 0, 0,0); if(ret) { sqlite3_free(stmt); sqlite3_close(db); cs_critical_error(ERR_GRADES_DB, "ERR update item in grade_book_item_save"); } sqlite3_free(stmt); } } sqlite3_close(db); } void delete_item(CONFIG_STRUCT *conf, int item_id) { char path[MAX_PATH +1]; int ret = 0; sqlite3 *db; char *stmt; snprintf(path, MAX_PATH +1, "%s%s/%s", conf->course_path, GRADE_BOOK_DIR, GRADE_BOOK_DB); ret = sqlite3_open(path, &db); if(ret) cs_critical_error(ERR_GRADES_DB, "update items"); ret = sqlite3_exec(db, "Begin transaction delete_item", 0, 0, 0); if(ret) { sqlite3_close(db); cs_critical_error(ERR_GRADES_DB, "begin insert item function"); } stmt = sqlite3_mprintf("delete from Items where itemId=%d", item_id); if(stmt) { ret = sqlite3_exec(db, stmt, 0, 0, 0); if(ret) { sqlite3_free(stmt); sqlite3_close(db); cs_critical_error(ERR_GRADES_DB, "ERR delete item in grade_book_item_save"); } sqlite3_free(stmt); } stmt = sqlite3_mprintf("delete from letterGrades where itemId=%d", item_id); if(stmt) { ret = sqlite3_exec(db, stmt, 0, 0, 0); if(ret) { sqlite3_free(stmt); ret = sqlite3_exec(db, "rollback transaction delete_item", 0, 0, 0); sqlite3_close(db); cs_critical_error(ERR_GRADES_DB, "ERR delete item in grade_book_item_save"); } sqlite3_free(stmt); } stmt = sqlite3_mprintf("delete from Grades where itemId=%d", item_id); { ret = sqlite3_exec(db, stmt, 0, 0, 0); if(ret) { sqlite3_free(stmt); ret = sqlite3_exec(db, "rollback transaction delete_item", 0, 0, 0); sqlite3_close(db); cs_critical_error(ERR_GRADES_DB, "ERR delete item in grade_book_item_save"); } sqlite3_free(stmt); } ret = sqlite3_exec(db, "commit transaction delete_item", 0, 0, 0); ret = sqlite3_exec(db, "end transaction delete_item", 0, 0, 0); sqlite3_close(db); } void do_action(const char *course, const char *id, CONFIG_STRUCT *conf, int save_option, int item_id) { char *next_url; next_url = hdf_get_value(global_cgi->hdf, "Query.nextUrl", ""); if(strlen(next_url) == 0) cs_critical_error(ERR_PARAM_MISSING, "grade_book_items_save"); if(save_option == 0) // do not save any thing just relocate to another program printf("Location: %s\n\n", next_url); else if(save_option == 1) // save new item { save_new_item(conf); printf("Location: %s\n\n", next_url); } else if(save_option == 2) // update existing items { update_items(conf); printf("Location: %s\n\n", next_url); } else if(save_option == 3) // delete item { delete_item(conf, item_id); printf("Location: %s\n\n", next_url); } } int main () { char course[MAX_PATH +1]; char key[MAX_KEY +1]; SESSION user; CONFIG_STRUCT conf; int save_option; int item_id; cs_cgi_init(); /* shared_cs_util.h */ read_parameters ( course, key, &save_option, &item_id); read_configuration_file (course, &conf); validate_key (key, &user, &conf); if(user.group != FACULTY) cs_critical_error(ERR_REQUEST_DENIED, "grade_book_item_save"); cs_set_course_info(&conf); do_action(course, key, &conf, save_option, item_id); cs_cgi_destroy(); return 0; }