#include "shared_xml_course_create_util.h" static USER_NODE * find_all_teachers(XML_COURSE_INFO *info) { USER_NODE *head =0, *ptr, *current=0; for(info->user_current = info->user_head; info->user_current; info->user_current=info->user_current->next) { if(info->user_current->data.group == FACULTY) { ptr = (USER_NODE*)malloc(sizeof(USER_NODE)); if(!ptr) cs_critical_error(ERR_MALLOC_FAILED, ""); ptr->next = 0; strncpy(ptr->user.first, info->user_current->data.realname, MAX_NAME + 1); strncpy(ptr->user.last, info->user_current->data.lastname, MAX_NAME + 1); strncpy(ptr->user.id, info->user_current->data.id, MAX_ID +1); strncpy(ptr->user.username, info->user_current->data.username, MAX_USERNAME +1); ptr->user.group = FACULTY; ptr->user.central_state = UN_CHANGE; /* assume this to start */ if(!head) head = ptr; else current->next = ptr; current = ptr; } } return head; } static USER_NODE * find_all_users_in_standalone(XML_COURSE_INFO *info) { USER_NODE *head =0, *ptr, *current=0; for(info->user_current = info->user_head; info->user_current; info->user_current=info->user_current->next) { ptr = (USER_NODE*)malloc(sizeof(USER_NODE)); if(!ptr) cs_critical_error(ERR_MALLOC_FAILED, ""); ptr->next =0; strncpy(ptr->user.first, info->user_current->data.realname, MAX_NAME +1); strncpy(ptr->user.last, info->user_current->data.lastname, MAX_NAME +1); strncpy(ptr->user.id, info->user_current->data.id, MAX_ID +1); strncpy(ptr->user.username, info->user_current->data.username, MAX_USERNAME +1); ptr->user.group = info->user_current->data.group; ptr->user.central_state = UN_CHANGE; if(!head) head = ptr; else current->next = ptr; current = ptr; } return head; } static USER_GROUP_INFO * find_exist_users(USER_GROUP_INFO_LIST *list, P_NODE* info) { USER_GROUP_INFO *ptr; for(ptr=list->head; ptr; ptr = ptr->next) { if(strcmp(ptr->user.id, info->data.id) ==0) return ptr; } return 0; } static USER_GROUP_INFO_LIST * process_one_course(USER_GROUP_INFO_LIST *list, XML_COURSE_INFO *info) { USER_GROUP_INFO *ptr, *find; /* for each user in the course */ for(info->user_current=info->user_head; info->user_current; info->user_current=info->user_current->next) { if(info->user_current->data.group != FACULTY) { find = find_exist_users(list, info->user_current); if(!find) { ptr = (USER_GROUP_INFO*)malloc(sizeof(USER_GROUP_INFO)); strncpy(ptr->user.first, info->user_current->data.realname,MAX_NAME +1); strncpy(ptr->user.last, info->user_current->data.lastname,MAX_NAME +1); strncpy(ptr->user.id, info->user_current->data.id,MAX_ID +1); if(strlen(info->user_current->data.username)>0) strncpy(ptr->user.username, info->user_current->data.username,MAX_USERNAME +1); else ptr->user.username[0]='\0'; ptr->user.is_new =NEW; ptr->user.central_state =UN_CHANGE; ptr->user.group=info->user_current->data.group; ptr->next =0; /** add a new course for this user */ ptr->head = (COURSE_GROUP*)malloc(sizeof(COURSE_GROUP)); ptr->current = ptr->head; ptr->head->next =0; strncpy(ptr->head->course_subdir, info->subdir, MAX_COURSE_SUBDIR +1); //strncpy(ptr->head->course_dir, info->dir_id, MAX_COURSE_NO +1); strncpy(ptr->head->course_dir, info->real_dir_id, MAX_COURSE_NO +1); ptr->head->course_type = info->course_type; ptr->head->group=info->user_current->data.group; if(!list->head) list->head = ptr; else list->current->next = ptr; list->current = ptr; } else /* user was already listed */ { find->user.central_state =UN_CHANGE; find->current->next=(COURSE_GROUP*)malloc(sizeof(COURSE_GROUP)); find->current = find->current->next; strncpy(find->current->course_subdir, info->subdir, MAX_COURSE_NO +1); //strncpy(find->current->course_dir, info->dir_id, MAX_COURSE_NO +1); strncpy(find->current->course_dir, info->real_dir_id, MAX_COURSE_NO +1); find->current->course_type = info->course_type; find->current->group = info->user_current->data.group; find->current->next =0; } } } return list; } USER_GROUP_INFO_LIST * build_user_list(XML_COURSE_INFO_LIST *list) { USER_GROUP_INFO_LIST *head; /* start with an empty user list */ head = (USER_GROUP_INFO_LIST *)malloc(sizeof(USER_GROUP_INFO_LIST)); if(!head) cs_critical_error(ERR_MALLOC_FAILED, "build_user_list"); head->head =0; head->current =0; /* for each course */ for(list->current=list->head; list->current; list->current = list->current->next) { if(list->current->course_type != STANDALONE) head = process_one_course(head, list->current); } return head; } /* start list with normal and template courses ** and only teacher info */ CREATED_COURSE_NODE* build_normal_template_course_list(XML_COURSE_INFO_LIST *list) { USER_NODE *teacher_head; char error[300]; CREATED_COURSE_NODE *head = 0, *ptr, *current = 0; get_lang_string(&hdf); for(list->current=list->head; list->current; list->current = list->current->next) { /* if NOT Standalone course */ if(list->current->course_type != STANDALONE && list->current->course_type != -1) { teacher_head = find_all_teachers(list->current); if(!teacher_head) { snprintf(error, 300, "%s %s", list->current->course_code, list->current->title); cs_critical_error(ERR_COURSE_X_Y_HAS_NO_TEACHER, error); } ptr = (CREATED_COURSE_NODE *)malloc(sizeof(CREATED_COURSE_NODE)); if(!ptr) cs_critical_error(ERR_MALLOC_FAILED, "build_temp"); strncpy(ptr->course_subdir, list->current->subdir, MAX_COURSE_SUBDIR + 1); strncpy(ptr->course_dir, list->current->real_dir_id, MAX_COURSE_ID +1); strncpy(ptr->org_id, list->current->dir_id, MAX_COURSE_ID +1); strncpy(ptr->course_no, list->current->course_code, MAX_COURSE_NO +1); strncpy(ptr->course_title, list->current->title, MAX_COURSE_TITLE +1); strncpy(ptr->instructor_title, list->current->instructor_title, MAX_INSTRUCTOR +1); ptr->course_type = list->current->course_type; /* change semester to a standard value for course templates */ if(list->current->course_type == TEMPLATE) strncpy(ptr->course_semester, hdf_get_value(hdf, "course_create_temp", ""), MAX_SEMESTER + 1); else strncpy(ptr->course_semester, list->current->semester, MAX_SEMESTER + 1); ptr->next = 0; ptr->head = teacher_head; ptr->add_head = 0; ptr->add_current = 0; if(!head) head = ptr; else current-> next = ptr; current = ptr; } } hdf_destroy(&hdf); return head; } static int find_this_username(USER_NODE *all, const char *username) { USER_NODE *ptr; for(ptr = all; ptr; ptr = ptr->next) { if(strlen(ptr->user.username) > 0 && strcmp(ptr->user.username, username) ==0) return 1; } return 0; } static void process_standalone_username(USER_NODE *one, USER_NODE *all) { char username[MAX_USERNAME +1]; int try; one->user.is_new = NEW; /* assume this to start */ if(!strlen(one->user.username)) /* if username wasn't supplied in XML file */ { derive_username (one->user.first, one->user.last, one->user.id, username, MAX_USERNAME+1); for(try = 1; (try <= MAX_USERNAME_TRIES) && (find_this_username(all, username)); try++) { derive_another_username(one->user.first, one->user.last, one->user.id, username, MAX_USERNAME + 1, try); } if(try > MAX_USERNAME_TRIES) one->user.is_new = ERROR_UID; } else /* username was supplied in XML file */ { strncpy(username, one->user.username, MAX_USERNAME + 1); *(username + MAX_USERNAME) = '\0'; } if(one->user.is_new != ERROR_UID) { one->user.is_new = NEW; strncpy(one->user.username, username, MAX_USERNAME + 1); derive_password (one->user.username, one->user.first,one->user.last, one->user.id, one->user.password, MAX_PASSWORD +1); /* shared_authenticate.c */ } } static USER_NODE * find_teacher_in_course_head(USER_NODE *head, const char *id) { USER_NODE *ptr; for(ptr = head; ptr; ptr = ptr->next) { if(strcmp(ptr->user.id, id) ==0) return ptr; } return 0; } void update_standalone_username(CREATED_COURSE_NODE *sta_list) { CREATED_COURSE_NODE *ptr; USER_NODE *t_node, *t_ptr; for(ptr = sta_list; ptr; ptr = ptr->next) { for(t_node = ptr->add_head; t_node; t_node = t_node->next) { process_standalone_username(t_node, ptr->add_head); if(t_node->user.group == FACULTY) { t_ptr =find_teacher_in_course_head(ptr->head, t_node->user.id); if(t_ptr) { strncpy(t_ptr->user.username, t_node->user.username, MAX_USERNAME +1); strncpy(t_ptr->user.password, t_node->user.password, MAX_PASSWORD +1); t_ptr->user.is_new = t_node->user.is_new; } } } } } /* build list of standalone courses with teachers and students */ CREATED_COURSE_NODE * standalone_course_list(XML_COURSE_INFO_LIST *list) { CREATED_COURSE_NODE *head =0, *ptr, *current=0; for(list->current=list->head; list->current; list->current = list->current->next) { if(list->current->course_type == STANDALONE) { ptr = (CREATED_COURSE_NODE *)malloc(sizeof(CREATED_COURSE_NODE)); strncpy(ptr->course_subdir, list->current->subdir, MAX_COURSE_SUBDIR +1); strncpy(ptr->course_dir, list->current->real_dir_id, MAX_COURSE_ID +1); strncpy(ptr->org_id, list->current->dir_id, MAX_COURSE_ID +1); snprintf(ptr->course_path, MAX_PATH + 1, "%s%s/%s", COURSE_PATH, ptr->course_subdir, ptr->course_dir); strncpy(ptr->course_no, list->current->course_code, MAX_COURSE_NO +1); strncpy(ptr->course_title, list->current->title, MAX_COURSE_TITLE +1); strncpy(ptr->instructor_title, list->current->instructor_title, MAX_INSTRUCTOR +1); ptr->course_type = list->current->course_type; strncpy(ptr->course_semester, list->current->semester, MAX_SEMESTER +1); ptr->next = 0; ptr->head = find_all_teachers(list->current); ptr->add_head =find_all_users_in_standalone(list->current); ptr->add_current = ptr->add_head; if(!head) head = ptr; else current->next = ptr; current = ptr; } } return head; } void set_course_table(CREATED_COURSE_NODE *head, const char *prefix) { #define MAX_TMP_NAME 50 CREATED_COURSE_NODE *ptr; USER_NODE *t_node; int course_count =0; int people_count, i =0; char name[MAX_TMP_NAME]; for(ptr = head; ptr; ptr = ptr->next) { snprintf(name, MAX_TMP_NAME, "%s.%d.type", prefix, i); cs_set_int_value(name, ptr->course_type); snprintf(name, MAX_TMP_NAME, "%s.%d.course_subdir", prefix , i); cs_set_value(name, ptr->course_subdir); snprintf(name, MAX_TMP_NAME, "%s.%d.course_dir", prefix , i); cs_set_value(name, ptr->course_dir); snprintf(name, MAX_TMP_NAME, "%s.%d.course_no", prefix , i); cs_set_value(name, ptr->course_no); snprintf(name, MAX_TMP_NAME, "%s.%d.course_title", prefix , i); cs_set_value(name, ptr->course_title); snprintf(name, MAX_TMP_NAME, "%s.%d.course_semester", prefix , i); cs_set_value(name, ptr->course_semester); snprintf(name, MAX_TMP_NAME, "%s.%d.exists", prefix , i); cs_set_int_value(name, ptr->exists); snprintf(name, MAX_TMP_NAME, "%s.%d.t_state", prefix , i); cs_set_int_value(name, ptr->t_state); course_count++; people_count =0; for(t_node = ptr->add_head; t_node; t_node = t_node->next) { if(strcmp(t_node->user.password, "drop") != 0) { snprintf(name, MAX_TMP_NAME, "%s.%d.users.%d.is_new", prefix , i, people_count); cs_set_int_value(name, t_node->user.is_new); snprintf(name, MAX_TMP_NAME, "%s.%d.users.%d.first", prefix , i, people_count); cs_set_value(name, t_node->user.first); snprintf(name, MAX_TMP_NAME, "%s.%d.users.%d.last", prefix , i, people_count); cs_set_value(name, t_node->user.last); snprintf(name, MAX_TMP_NAME, "%s.%d.users.%d.id", prefix , i, people_count); cs_set_value(name, t_node->user.id); snprintf(name, MAX_TMP_NAME, "%s.%d.users.%d.username", prefix , i, people_count); cs_set_value(name, t_node->user.username); snprintf(name, MAX_TMP_NAME, "%s.%d.users.%d.group", prefix , i, people_count); cs_set_int_value(name, t_node->user.group); snprintf(name, MAX_TMP_NAME, "%s.%d.users.%d.add_state", prefix , i, people_count); cs_set_int_value(name, t_node->user.add_state); if(ptr->course_type != STANDALONE) { snprintf(name, MAX_TMP_NAME, "%s.%d.users.%d.central_state", prefix , i, people_count); cs_set_int_value(name, t_node->user.central_state); } people_count++ ; } } snprintf(name, MAX_TMP_NAME, "%s.%d.total_users", prefix , i); cs_set_int_value(name, people_count); i++; } if(!strcmp(prefix, "ctr")) cs_set_int_value("ctr_total", course_count); else cs_set_int_value("std_total", course_count); #undef MAX_TMP_NAME } static DIRECTORY_NAME_NODE * build_directory_name_list( int course_count, int *standalone) { int i; char name[MAX_FILENAME + 1]; char tmp[20 + 1], *str =0; DIRECTORY_NAME_NODE *head = 0, *ptr, *current = 0; for(i=1; i <= course_count; i++) { snprintf(name, MAX_FILENAME + 1, "Query.c%d_orig_id", i); str = hdf_get_value(global_cgi->hdf, name, 0); if(str) { /* allocate new node */ ptr = (DIRECTORY_NAME_NODE *)malloc(sizeof(DIRECTORY_NAME_NODE)); if(!ptr) cs_critical_error(ERR_MALLOC_FAILED, ""); ptr->next = 0; /* store original internal name as it appears in the ** XML file */ snprintf(name, MAX_FILENAME + 1, "c%d_orig_id", i); cs_get_required_parameter(name, ptr->name, MAX_COURSE_NO); /* shared_cgi_util.c */ /* store new internal name, as modified by user */ snprintf(name, MAX_FILENAME + 1, "c%d_new_id", i); cs_get_required_parameter(name, ptr->dir_id, MAX_COURSE_ID); /* shared_cgi_util.c */ /* store new subdirectory name, as modified by user */ snprintf(name, MAX_FILENAME + 1, "c%d_subdir_or", i); cs_get_required_parameter(name, ptr->subdir, MAX_COURSE_SUBDIR); /* shared_cgi_util.c */ snprintf(name, MAX_FILENAME + 1, "c%d_subdir", i); cs_get_required_parameter(name, ptr->modified_subdir, MAX_COURSE_SUBDIR); /* shared_cgi_util.c */ /* store course type "Standalone", "Normal" or "Template" */ snprintf(name, MAX_FILENAME + 1, "c%d_type", i); cs_get_required_parameter(name,tmp,20); ptr->course_type = !strcmp(tmp,"Standalone")? STANDALONE: (!strcmp(tmp, "Template"))? TEMPLATE: CENTRAL; /* *standalone gets set if one or more courses is "Standalone" */ if(ptr->course_type == STANDALONE) *standalone = 1; if(!head) head = ptr; else current->next = ptr; current = ptr; } } return head; } DIRECTORY_NAME_NODE * get_parameters(char *key, int *standalone, char *roster_path) { DIRECTORY_NAME_NODE *head; char tmp[20 + 1]; int course_count; cs_get_required_parameter ("id", key, MAX_KEY); /* shared_cs_util.c */ cs_get_required_parameter ("count", tmp, 20); course_count = atoi(tmp); cs_get_required_parameter ("roster_path", roster_path, MAX_PATH); head = build_directory_name_list( course_count, standalone); if(!head) cs_critical_error(ERR_PARAM_MISSING, "course parameters"); return head; } void free_directory_name_list(DIRECTORY_NAME_NODE *head) { DIRECTORY_NAME_NODE *ptr; while(head) { ptr = head->next; free(head); head = ptr; } } void check_invalid_chars(const char *string) { const char *cptr; char msg[200]; /* check for invalid characters */ for(cptr = string; *cptr; cptr++) { if((*cptr != '_') && !isdigit(*cptr) && !isalpha(*cptr)) { snprintf(msg, 200, string); cs_critical_error(ERR_COURSE_X_HAS_INVALID_CHARS, msg); } } } /* assumes strings have been trimmed ** in read_parameters() */ void check_internal_course_names(XML_COURSE_INFO_LIST *list) { for(list->current=list->head; list->current; list->current=list->current->next) { if(!strlen(list->current->dir_id) || !strlen(list->current->subdir) ) cs_critical_error(ERR_COURSE_NAMES_EMPTY, ""); /* Central or Standalone Course subdir names can't start with a 'T' */ if( (list->current->course_type == CENTRAL) || (list->current->course_type == STANDALONE)) { if(*(list->current->subdir) == 'T') cs_critical_error(ERR_COURSE_CANT_START_WITH_T, ""); } check_invalid_chars(list->current->dir_id); check_invalid_chars(list->current->subdir); } /* for each course ... */ } /* parses the xml file into a linked list of ** course nodes */ XML_COURSE_INFO_LIST * parse_xml_file(const char *xml_file_path) { char msg[200]; XML_COURSE_INFO_LIST *list; /* shared_roster_xml_parser.h */ FILE *fp; struct stat file_stat; char *buf; if(stat(xml_file_path, &file_stat)) { snprintf(msg,200, xml_file_path); cs_critical_error(ERR_FILE_X_NOT_FOUND, msg); } buf = (char*)malloc( (file_stat.st_size + 1) * sizeof(char)); /* allocate an additional byte for terminating NULL */ if(!buf) cs_critical_error(ERR_MALLOC_FAILED, ""); fp = fopen(xml_file_path, "r"); if(!fp) cs_critical_error(ERR_FOPEN_READ_FAILED, xml_file_path); if(fread(buf, file_stat.st_size, 1, fp) != 1) cs_critical_error(ERR_FREAD_FAILED, ""); fclose(fp); *(buf + file_stat.st_size) = '\0'; /* null terminate the buf string */ list = xml_course_data_parser(buf); /*shared_roster_xml_parser.c */ free(buf); return list; } /** adds correct internal name and course type to *** the master course list **/ void update_xml_info_list(XML_COURSE_INFO_LIST *list, DIRECTORY_NAME_NODE *modified_head) { DIRECTORY_NAME_NODE *modified_ptr = 0; char dir[MAX_COURSE_ID + 1]; // char error_msg[200]; if(list->head && modified_head) { for(list->current=list->head; list->current; list->current=list->current->next) { /* find this course name in the user-supplied list */ for(modified_ptr = modified_head; modified_ptr; modified_ptr=modified_ptr->next) if(!strcmp(modified_ptr->name, list->current->dir_id) && !strcmp(list->current->subdir , modified_ptr->subdir)) break; if(modified_ptr) { /* if a course is a Template, must force first char to be an uppercase 'T' */ if( (modified_ptr->course_type == TEMPLATE) && *(modified_ptr->dir_id) !='T') { /* if course name is already at it's maximum length, strip one char from end */ if(strlen(modified_ptr->dir_id) == MAX_COURSE_ID) *(modified_ptr->dir_id + MAX_COURSE_ID - 1) = '\0'; snprintf(dir, MAX_COURSE_ID + 1, "%s%s","T", modified_ptr->dir_id); strncpy(modified_ptr->dir_id, dir, MAX_COURSE_ID + 1); } list->current->course_type = modified_ptr->course_type; //strncpy(list->current->dir_id, modified_ptr->dir_id, MAX_COURSE_ID + 1); strncpy(list->current->real_dir_id, modified_ptr->dir_id, MAX_COURSE_ID + 1); *(list->current->real_dir_id + MAX_COURSE_ID) = '\0'; strncpy(list->current->subdir, modified_ptr->modified_subdir, MAX_COURSE_SUBDIR + 1); *(list->current->subdir + MAX_COURSE_SUBDIR) = '\0'; } else { list->current->course_type = -1; //snprintf(error_msg, 200, list->current->dir_id); //cs_critical_error(ERR_DATA_FOR_X_NOT_FOUND, error_msg); } } /* for each course found in the XML file */ } else cs_critical_error(ERR_NO_DATA_FOUND, ""); } void free_teacher_node(USER_NODE *t_head) { USER_NODE *ptr; while(t_head) { ptr = t_head->next; free(t_head); t_head = ptr; } } void free_course_f_list(CREATED_COURSE_NODE *head) { CREATED_COURSE_NODE *ptr; while(head) { ptr = head->next; if(head->head) free_teacher_node(head->head); if(head->add_head) free_teacher_node(head->add_head); free(head); head = ptr; } } void free_course_group(COURSE_GROUP *head) { COURSE_GROUP *ptr; while(head) { ptr = head->next; free(head); head = ptr; } } void free_user_group_info_list(USER_GROUP_INFO_LIST *list) { USER_GROUP_INFO *ptr; while(list->head) { ptr = list->head->next; if(list->head->head) free_course_group(list->head->head); free(list->head); list->head = ptr; } free(list); } static INDEX_USER * find_this_user_from_index(INDEX_USER_LIST *list, USER *node) { INDEX_USER *ptr; for(ptr = list->head; ptr;ptr = ptr->next) { if(strcmp(ptr->id, node->id) ==0) return ptr; } return 0; } static int username_exist(INDEX_USER_LIST *index_list, const char *username) { INDEX_USER *ptr; for(ptr = index_list->head; ptr; ptr = ptr->next) { if(strcmp(ptr->username, username) ==0) return 1; } return 0; } INDEX_USER_LIST * process_one_username(USER *ptr, INDEX_USER_LIST *index_list) { INDEX_USER *a_user; char realname[MAX_NAME +1]; char username[MAX_USERNAME +1]; int try; ptr->is_new = NEW ; /* assume this to start */ a_user = find_this_user_from_index(index_list, ptr); if(!a_user) { if(!strlen(ptr->username)) /* if username wasn't supplied in XML file */ { derive_username (ptr->first, ptr->last, ptr->id, username, MAX_USERNAME+1); /* shared_authenticate.c */ for(try = 1; (try <= MAX_USERNAME_TRIES) && ( username_invalid(username) /* shared_authenticate.c */ || username_exist (index_list, username ) ); try++) { derive_another_username(ptr->first, ptr->last, ptr->id, username, MAX_USERNAME + 1, try); /* shared_authenticate.c */ } if(try > MAX_USERNAME_TRIES) ptr->is_new = ERROR_UID; /* couldn't derive username */ } else /* a username was supplied in the XML file */ { strncpy(username, ptr->username, MAX_USERNAME + 1); *(username + MAX_USERNAME) = '\0'; strtrm(username); /* shared_strtrm.c */ if(username_invalid(username) /* shared_authenticate.c */ || username_exist(index_list, username)) ptr->is_new = ERROR_UID; } if(ptr->is_new != ERROR_UID) { ptr->is_new = NEW; strncpy(ptr->username, username, MAX_USERNAME + 1); derive_password (ptr->username, ptr->first,ptr->last,ptr->id, ptr->password, MAX_PASSWORD +1); /* shared_authenticate.c */ snprintf(realname, MAX_NAME+1, "%s %s", ptr->first,ptr->last); index_list = add_to_index_list(index_list, ptr->username, ptr->id, realname); /* shared_user_index.c */ } } else /* person already has a central account */ { strncpy(ptr->username, a_user->username, MAX_USERNAME +1); derive_password (ptr->username, ptr->first,ptr->last,ptr->id, ptr->password, MAX_PASSWORD +1); /* shared_authenticate.c */ snprintf(realname, MAX_NAME+1, "%s %s", ptr->first,ptr->last); if(strcmp(realname, a_user->realname) == 0) ptr->is_new = EXISTS; else { /* copy correct real name into first, last fields */ get_first_last_names(a_user->realname, ptr->first, ptr->last); /* shared_authenticate.c */ ptr->is_new = ERROR_NAME; /* user exists, but they had a different real name on Manhattan */ } } return index_list; } INDEX_USER_LIST * derive_teacher_username_password(CREATED_COURSE_NODE *course_head, INDEX_USER_LIST *index_list) { CREATED_COURSE_NODE *course; USER_NODE *ptr; for(course = course_head; course; course = course->next) { for(ptr = course->head; ptr; ptr = ptr->next) index_list = process_one_username(&(ptr->user), index_list); } return index_list; } INDEX_USER_LIST * derive_student_username_password(USER_GROUP_INFO_LIST *user_list, INDEX_USER_LIST *index_list) { for(user_list->current = user_list->head; user_list->current; user_list->current = user_list->current->next) { index_list = process_one_username (&(user_list->current->user), index_list); } return index_list; } static int write_org_info(CREATED_COURSE_NODE *course) { char org_id_file[MAX_PATH +1]; FILE *fp; snprintf(org_id_file, MAX_PATH +1, "%s/%s", course->course_path, "org_id.txt"); fp = fopen(org_id_file, "w"); if(!fp) return 1; fprintf(fp, "%s\n", course->org_id); fclose(fp); return 0; } static int create_course_dir(CREATED_COURSE_NODE *course) { char path[MAX_PATH + 1]; /* create subdir, if necessary */ snprintf(path, MAX_PATH + 1, "%s%s", course->course_type == TEMPLATE? TEMPLATE_PATH : COURSE_PATH, course->course_subdir); if(!file_exists(path)) { if(mkdir (path, 0777)) return 0; } if(mkdir(course->course_path, 0777)) return 0; return 1; } static void get_config_default_value(CREATED_COURSE_NODE *course, CONFIG_STRUCT *conf) { char professor[MAX_INSTRUCTOR +1]; strncpy(conf->course_no, course->course_no, MAX_COURSE_NO+1); strncpy(conf->title, course->course_title, MAX_COURSE_TITLE+1); strncpy(conf->semester, course->course_semester, MAX_SEMESTER+1); if(strlen(course->instructor_title)) snprintf(professor, MAX_INSTRUCTOR +1, "%s", course->instructor_title); else snprintf(professor, MAX_INSTRUCTOR +1, "%s %s", "Prof.", course->head->user.last); strncpy(conf->instructor, professor, MAX_INSTRUCTOR +1); conf->login_expire = 0; conf -> key_expire = MAX_KEY_EXPIRE; conf -> mail_attachments = MAX_ATTACHMENTS; conf -> assignments = 0; conf -> syllabus = 0; conf -> discussion = 0; conf -> postoffice = 0; conf -> internet = 0; conf -> lounge = 0; conf -> chat = 0; conf -> anonymous = 0; conf -> team = 0; conf -> team_teach = 0; conf -> grades = 0; conf -> selftest = 0; conf -> lectures = 0; conf -> people = 0; conf -> surveys = 0; conf->access = ACCESS_ALL; /*Full access for teachers and students */ conf ->standalone = (course->course_type == STANDALONE)? 1 : 0; conf -> template = (course->course_type == TEMPLATE)? 1 : 0; conf->misc = 0; conf->podcasts = 0; conf->future6 = 0; conf->theme = 0; } static int write_config_file(const char *course, CONFIG_STRUCT *conf) { FILE *fp; char file_path[MAX_PATH +1]; snprintf(file_path, MAX_PATH +1, "%s/%s", course, CONFIG_FNAME); fp = fopen(file_path,"w"); if(!fp) return 0; if(fwrite(conf, sizeof(CONFIG_STRUCT), 1, fp) != 1) { fclose(fp); return 0; } fclose(fp); return 1; } static int create_inboxes_directory (const char *crs ) { char path[MAX_PATH + 1]; snprintf (path, MAX_PATH + 1, "%s/%s", crs, INBOXES_DIR); if(mkdir (path, 0777)) return 0; snprintf (path, MAX_PATH + 1, "%s/%s/%s", crs, INBOXES_DIR ,ANONYMOUS_DIR); if(mkdir (path, 0777)) return 0; snprintf (path, MAX_PATH + 1, "%s/%s/%s", crs, INBOXES_DIR, ASSIGNMENTS_DIR); if(mkdir (path, 0777)) return 0; snprintf (path, MAX_PATH + 1, "%s/%s/%s", crs, INBOXES_DIR, DISCUSSION_DIR); if(mkdir (path, 0777)) return 0; snprintf (path, MAX_PATH + 1, "%s/%s/%s", crs, INBOXES_DIR, TEAM_DIR); if(mkdir (path, 0777)) return 0; snprintf (path, MAX_PATH + 1, "%s/%s/%s", crs, INBOXES_DIR, INET_DIR); if(mkdir (path, 0777)) return 0; snprintf (path, MAX_PATH + 1, "%s/%s/%s", crs, INBOXES_DIR, LOUNGE_DIR); if(mkdir (path, 0777)) return 0; snprintf (path, MAX_PATH + 1, "%s/%s/%s", crs, INBOXES_DIR, MAIL_DIR); if(mkdir (path, 0777)) return 0; snprintf (path, MAX_PATH + 1, "%s/%s/%s", crs, INBOXES_DIR, HANDOUTS_DIR); if(mkdir (path, 0777)) return 0; snprintf (path, MAX_PATH + 1, "%s/%s/%s", crs, INBOXES_DIR, TEAM_TEACH_DIR); if(mkdir (path, 0777)) return 0; snprintf (path, MAX_PATH + 1, "%s/%s/%s", crs, INBOXES_DIR, GRADES_DIR); if(mkdir (path, 0777)) return 0; snprintf (path, MAX_PATH + 1, "%s/%s/%s", crs, INBOXES_DIR, SELFTEST_DIR); if(mkdir (path, 0777)) return 0; snprintf (path, MAX_PATH + 1, "%s/%s/%s", crs, INBOXES_DIR, LECTURES_DIR); if(mkdir (path, 0777)) return 0; snprintf (path, MAX_PATH + 1, "%s/%s/%s", crs, INBOXES_DIR, SURVEYS_DIR); if(mkdir (path, 0777)) return 0; return 1; } static int create_key_people(const char *course_path) { char path[MAX_PATH +1]; snprintf (path, MAX_PATH + 1, "%s/%s", course_path, KEY_DIR); if(mkdir (path, 0777)) return 0; snprintf (path, MAX_PATH + 1, "%s/%s", course_path, PEOPLE_DIR); if(mkdir (path, 0777)) return 0; return 1; } static int write_chat_message_log(const char *course) { FILE *fp; char log_fname[MAX_PATH +1]; snprintf(log_fname, MAX_PATH + 1, "%s/%s", course, CHAT_MSG_LOG); fp = fopen (log_fname, "w"); if(!fp) return 0; fclose(fp); return 1; } static int write_logout_html (const char *crs) { FILE *fp; char fname[MAX_PATH +1]; snprintf(fname, MAX_PATH + 1, "%s/%s", crs, EXIT_FILE); fp = fopen (fname, "w"); if(!fp) return 0; fprintf (fp, "
%s
", EXIT_URL, EXIT_URL); fclose (fp); return 1; } static int create_one_person_dir (const char *course_path, const char *username) { char basedir [MAX_PATH + 1]; snprintf (basedir, MAX_PATH + 1, "%s/", course_path); return create_directories(basedir,username); /* shared_add_util.c */ } CREATED_COURSE_NODE * add_user_to_course_list(CREATED_COURSE_NODE *course, USER *ptr) { USER_NODE *target; target = (USER_NODE *)malloc(sizeof(USER_NODE)); if(!target) cs_critical_error(ERR_MALLOC_FAILED, ""); strncpy(target->user.username, ptr->username, MAX_USERNAME +1); strncpy(target->user.first, ptr->first, MAX_NAME +1); strncpy(target->user.password, ptr->password, MAX_PASSWORD +1); strncpy(target->user.last, ptr->last, MAX_NAME +1); strncpy(target->user.id, ptr->id, MAX_ID +1); target->user.is_new = ptr->is_new; target->user.group = ptr->group; target->user.add_state = ptr->add_state; target->user.central_state = ptr->central_state; target->next =0; if(!course->add_head) { course->add_head = target; course->add_current = course->add_head; } else { course->add_current->next = target; course->add_current = course->add_current->next; } return course; } static void update_central_info(CREATED_COURSE_NODE *course, USER *user_ptr) { char realname[MAX_NAME +1]; char course_name[MAX_PATH + 1]; snprintf(realname, MAX_NAME +1, "%s %s", user_ptr->first, user_ptr->last); snprintf(course_name, MAX_PATH + 1, "%s/%s", course->course_subdir, course->course_dir); if( (user_ptr->is_new == NEW) && (user_ptr->add_state == FINISH) && ( (course->exists == C_NEW) || (course->exists == UPDATE)) && (user_ptr->central_state != SUCCESS) ) { /* create_central_letter_dir is in shared_central_user.c */ /* sub_dir_name is in shared_authenticate.c */ if(!create_central_letter_dir (sub_dir_name(user_ptr->username))) user_ptr->central_state = C_ERROR; if(!create_central_user_dir(user_ptr->username)) /* shared_central_user.c */ user_ptr->central_state = C_ERROR; if(!write_central_id_file (realname,user_ptr->username, user_ptr->id)) /* shared_central_user.c */ user_ptr->central_state = C_ERROR; if(!write_central_password_file (user_ptr->username, user_ptr->password)) /* shared_central_user.c */ user_ptr->central_state = C_ERROR; if(!add_course(user_ptr->username,course_name)) /* shared_central_user.c */ user_ptr->central_state = C_ERROR; else { user_ptr->central_state = SUCCESS; user_ptr->is_new = NEW_1; /* central records already updated for this user */ } } else if((user_ptr->is_new != ERROR_UID || user_ptr->is_new != NEW) && user_ptr->add_state == FINISH) { if(course->exists == C_NEW || course->exists == UPDATE) { if(!add_course(user_ptr->username,course_name)) /* shared_central_user.c */ user_ptr->central_state = C_ERROR; else user_ptr->central_state = SUCCESS; } } else user_ptr->central_state = UN_CHANGE; } static CREATED_COURSE_NODE * add_teachers(CREATED_COURSE_NODE *course) { USER_NODE *ptr; char file_path[MAX_PATH +1]; if(course->exists == C_NEW) { for(ptr = course->head; ptr; ptr=ptr->next) /* for each teacher */ { if(create_one_person_dir (course->course_path, ptr->user.username)) ptr->user.add_state = FINISH; else ptr->user.add_state = FAILED; if(course->course_type != STANDALONE) { update_central_info(course, &(ptr->user)); course =add_user_to_course_list(course, &(ptr->user)); } } } else if(course->exists == UPDATE) { for(ptr = course->head; ptr; ptr =ptr->next) { snprintf(file_path, MAX_PATH +1, "%s/%s/%s", course->course_path, PEOPLE_DIR, ptr->user.username); if(!file_exists(file_path)) { if(create_one_person_dir (course->course_path, ptr->user.username)) ptr->user.add_state = FINISH; else ptr->user.add_state = FAILED; if(course->course_type != STANDALONE) update_central_info(course, &(ptr->user)); } else ptr->user.add_state = USEREXISTS; if(course->course_type != STANDALONE) course =add_user_to_course_list(course, &(ptr->user)); } } return course; } static int write_passwd_file(CREATED_COURSE_NODE *course, USER_NODE *head) { USER_NODE *ptr; char file_path[MAX_PATH +1]; FILE *fp; if( (course->exists != C_NEW) && (course->exists != UPDATE) ) return 0; snprintf(file_path, MAX_PATH +1, "%s/%s", course->course_path, PASSWORD_FNAME); fp = fopen(file_path, "a+"); if(!fp) return -1; get_exclusive_lock(fileno(fp),1); /* shared_lock.c */ for(ptr = head; ptr; ptr = ptr->next) { if( (course->course_type == STANDALONE) && ptr->user.add_state == FINISH) { fprintf(fp, "%s:x:%s %s:%s:anonymous:Z:%s\n", ptr->user.username, ptr->user.first, ptr->user.last, "faculty", ptr->user.id); write_password(ptr->user.username, ptr->user.password, course->course_path); /* shared_encrypt.c */ } else if(ptr->user.add_state == FINISH && ptr->user.central_state == SUCCESS) { fprintf(fp, "%s:x:%s %s:%s:anonymous:Z:%s\n", ptr->user.username, ptr->user.first, ptr->user.last, "faculty", ptr->user.id); } } release_lock(fileno(fp)); /* shared_lock.c */ fclose(fp); return 1; } static CREATED_COURSE_NODE * find_this_course(CREATED_COURSE_NODE *course_head, const char *dir, const char *subdir) { CREATED_COURSE_NODE *ptr; for(ptr = course_head; ptr; ptr = ptr->next) { if(!strcmp(ptr->course_dir, dir) && !strcmp(ptr->course_subdir, subdir)) return ptr; } return 0; } static int find_user_in_this_course(CREATED_COURSE_NODE *course, const char *username) { USER_NODE *ptr; for(ptr = course->add_head; ptr; ptr = ptr->next) { if(!strcmp(ptr->user.username, username)) return 1; } return 0; } CREATED_COURSE_NODE * add_students_to_courses(CREATED_COURSE_NODE *course_head, USER_GROUP_INFO_LIST *user_list) { CREATED_COURSE_NODE *course_ptr; USER_GROUP_INFO *user_ptr; char file_path[MAX_PATH +1]; for(user_ptr = user_list->head; user_ptr; user_ptr = user_ptr->next) { for(user_ptr->current = user_ptr->head; user_ptr->current; user_ptr->current = user_ptr->current->next) { course_ptr = find_this_course(course_head, user_ptr->current->course_dir, user_ptr->current->course_subdir); if(course_ptr && (course_ptr->t_state == T_SUCCESS) && (course_ptr->course_type != TEMPLATE)) { snprintf(file_path, MAX_PATH +1, "%s/%s/%s", course_ptr->course_path, PEOPLE_DIR, user_ptr->user.username); if(!file_exists(file_path)) { if(user_ptr->user.is_new != ERROR_UID) { if(create_one_person_dir(course_ptr->course_path, user_ptr->user.username)) user_ptr->user.add_state = FINISH; else user_ptr->user.add_state = FAILED; if(course_ptr->course_type != STANDALONE) { update_central_info(course_ptr, &(user_ptr->user)); } } } else user_ptr->user.add_state = USEREXISTS; /* but he may not be in the password file! */ if(!find_user_in_this_course(course_ptr, user_ptr->user.username)) course_ptr = add_user_to_course_list(course_ptr, &(user_ptr->user)); } } } return course_head; } static P_NODE* build_password_list(const char *subdir, const char *dir) { char course_name[MAX_PATH + 1]; CONFIG_STRUCT conf; P_NODE *head = 0; snprintf(course_name, MAX_PATH + 1, "%s/%s", subdir, dir); if(read_configuration_file_ok(course_name,&conf)) head=build_option_person_list(&conf); return head; } static int listed_in_password(const char *username, P_NODE *person_head, int *star) { P_NODE *p_ptr; for(p_ptr = person_head; p_ptr; p_ptr=p_ptr->next) { if(!strcmp(username,p_ptr->data.username)) { if( *(p_ptr->data.realname) == '*' || *(p_ptr->data.realname) == '+') *star = 1; return 1; } } return 0; } static USER_NODE *initialize_usernode(P_NODE *one) { USER_NODE *ptr; ptr = (USER_NODE *) malloc(sizeof(USER_NODE)); if(!ptr) cs_critical_error(ERR_MALLOC_FAILED, "initialize_usernode"); strncpy(ptr->user.first, one->data.realname, MAX_NAME +1); strncpy(ptr->user.last, one->data.lastname, MAX_NAME +1); strncpy(ptr->user.username, one->data.username, MAX_USERNAME +1); strncpy(ptr->user.id, one->data.id, MAX_ID +1); memset(ptr->user.password, 0, MAX_PASSWORD +1); strncpy(ptr->user.password, "drop", MAX_PASSWORD +1); ptr->user.group = one->data.group; ptr->next =0; return ptr; } static int find_person_in_current_roster(CREATED_COURSE_NODE *course, P_NODE *person) { if(*(person->data.realname) == '*' || *(person->data.realname) == '+') return 1; for(course->add_current = course->add_head; course->add_current; course->add_current = course->add_current->next) { if(strcmp(course->add_current->user.id, person->data.id) == 0) return 1; } return 0; } static CREATED_COURSE_NODE * check_all_passwd_data_in_xml( P_NODE *person_head, CREATED_COURSE_NODE *course_ptr) { P_NODE *ptr; USER_NODE *user, *start; int found = 0; for(ptr = person_head; ptr; ptr = ptr->next) { found = find_person_in_current_roster(course_ptr, ptr); if(!found) { user = initialize_usernode(ptr); start = course_ptr->add_head; while(start->next) { start = start->next; } start->next = user; } } return course_ptr; } static void course_has_add_drop(CREATED_COURSE_NODE *ptr, int *drop, int *add) { for(ptr->add_current = ptr->add_head; ptr->add_current; ptr->add_current = ptr->add_current->next) { if(strcmp(ptr->add_current->user.password, "add") == 0) *add = 1; if(strcmp(ptr->add_current->user.password, "drop") == 0) *drop = 1; } } static void write_to_add_list(CREATED_COURSE_NODE *course) { FILE *fp; char path[MAX_PATH +1]; char *time_string; snprintf(path, MAX_PATH +1, "%s/%s", course->course_path, ADD_LIST_FNAME); fp = fopen(path, "a+"); if(!fp) return; time_string = get_time_string(); for(course->add_current = course->add_head; course->add_current; course->add_current = course->add_current->next) { if(strcmp(course->add_current->user.password, "add") == 0) fprintf(fp, "%s%s%s %s%s\n", course->add_current->user.id, course->add_current->user.username, course->add_current->user.first, course->add_current->user.last, time_string); } fclose(fp); free(time_string); } static void write_to_drop_list(CREATED_COURSE_NODE *course) { FILE *fp; char path[MAX_PATH +1]; char *time_string; snprintf(path, MAX_PATH +1, "%s/%s", course->course_path, DROP_LIST_FNAME); fp = fopen(path, "w"); if(!fp) return; time_string = get_time_string(); fprintf(fp, "%s\n", time_string); free(time_string); for(course->add_current = course->add_head; course->add_current; course->add_current = course->add_current->next) { if(strcmp(course->add_current->user.password, "drop") == 0 && course->add_current->user.group != FACULTY) fprintf(fp, "%s:x:%s:%s:anonymous:A:%s\n", course->add_current->user.username, course->add_current->user.first, course->add_current->user.group == FACULTY ? "faculty":"student", course->add_current->user.id ); } fclose(fp); } void write_add_drop_list(CREATED_COURSE_NODE *courses) { CREATED_COURSE_NODE *ptr; int drop =0; int add =0; for(ptr = courses; ptr; ptr = ptr->next) { course_has_add_drop(ptr, &drop, &add); if(add) write_to_add_list(ptr); if(drop) write_to_drop_list(ptr); drop = 0; add =0; } } COURSE_GROUP * initalize_course_group(CREATED_COURSE_NODE *course) { COURSE_GROUP *ptr; ptr = (COURSE_GROUP *)malloc(sizeof(COURSE_GROUP)); if(!ptr) cs_critical_error(ERR_MALLOC_FAILED, "initialize_course_group"); strncpy(ptr->course_subdir, course->course_subdir, MAX_COURSE_SUBDIR +1); strncpy(ptr->course_dir, course->course_dir, MAX_COURSE_ID +1); ptr->next = 0; return ptr; } COURSE_GROUP * is_this_course_in_check_list(COURSE_GROUP *check_head, CREATED_COURSE_NODE *course_ptr, int *found) { COURSE_GROUP *ptr; int is_in = 0; if(!check_head) { check_head = initalize_course_group(course_ptr); *found = 0; } else { for(ptr = check_head; ptr; ptr = ptr->next) { if(strcmp(ptr->course_subdir, course_ptr->course_subdir) == 0 && strcmp(ptr->course_dir, course_ptr->course_dir) == 0) { is_in = 1; *found = 1; break; } } if(!is_in) { *found = 0; ptr = check_head->next; while(ptr) { ptr = ptr->next; } ptr = initalize_course_group(course_ptr); } } return check_head; } int mark_star(FILE *fp, const char *username) { int found = 0; char line[200]; long offset = 0; char qmark = '?'; char *ptr; fseek(fp, 0, SEEK_SET); while( !found && fgets(line, 199, fp)) { if(*line != '?') { ptr = strchr(line, ':'); if(!ptr) return 0; *ptr = '\0'; if(!strcmp (line, username)) { fseek (fp, offset, SEEK_SET); if(fwrite (&qmark, sizeof(char), 1, fp) != 1) return 0; found =1; } } offset = ftell(fp); } return 1; } CREATED_COURSE_NODE * write_students_to_password_file(CREATED_COURSE_NODE *courses) { CREATED_COURSE_NODE *course_ptr; char file_path[MAX_PATH +1]; FILE *fp; P_NODE *person_head; COURSE_GROUP *check_head = 0; int found = 0; char course_name[MAX_PATH]; int is_in_passwd = -1; int student_count = 0; int star = 0; for(course_ptr = courses; course_ptr; course_ptr = course_ptr->next) { /* students are NOT added to course templates! */ if(course_ptr->course_type != TEMPLATE) { person_head = build_password_list( course_ptr->course_subdir, course_ptr->course_dir); snprintf(file_path, MAX_PATH +1, "%s/%s", course_ptr->course_path,PASSWORD_FNAME); //fp = fopen(file_path, "a"); fp = fopen(file_path, "r+"); if(!fp) { course_ptr->t_state = OPEN_ERR; break; } get_exclusive_lock(fileno(fp), 0); /* shared_lock.c */ student_count = 0; for(course_ptr->add_current = course_ptr->add_head; course_ptr->add_current; course_ptr->add_current = course_ptr->add_current->next) { if(course_ptr->add_current->user.add_state == USEREXISTS) is_in_passwd = listed_in_password(course_ptr->add_current->user.username,person_head, &star); if(is_in_passwd && star && course_ptr->add_current->user.group != FACULTY) { mark_star(fp, course_ptr->add_current->user.username); fseek(fp, 0, SEEK_END); fprintf(fp, "%s:x:%s %s:%s:anonymous:A:%s\n", course_ptr->add_current->user.username, course_ptr->add_current->user.first, course_ptr->add_current->user.last, "student", course_ptr->add_current->user.id); star = 0; is_in_passwd = 0; } else if( (course_ptr->add_current->user.group != FACULTY) && ( (course_ptr->add_current->user.add_state == FINISH) || ((course_ptr->add_current->user.add_state == USEREXISTS) && !is_in_passwd) ) ) { fseek(fp, 0, SEEK_END); fprintf(fp, "%s:x:%s %s:%s:anonymous:A:%s\n", course_ptr->add_current->user.username, course_ptr->add_current->user.first, course_ptr->add_current->user.last, "student", course_ptr->add_current->user.id); if(course_ptr->course_type == CENTRAL) { if((course_ptr->add_current->user.add_state == USEREXISTS) && !is_in_passwd) { snprintf(course_name, MAX_PATH , "%s/%s", course_ptr->course_subdir, course_ptr->course_dir); if(!add_course(course_ptr->add_current->user.username,course_name)) course_ptr->add_current->user.central_state = C_ERROR; } strncpy(course_ptr->add_current->user.password, "add", MAX_PASSWORD +1); } else if(course_ptr->course_type == STANDALONE) { write_password(course_ptr->add_current->user.username, course_ptr->add_current->user.password, course_ptr->course_path); /* shared_encrypt.c */ } } if(course_ptr->add_current->user.group == STUDENT) student_count++; } release_lock(fileno(fp)); /* shared_lock.c */ fclose(fp); if(course_ptr->course_type == CENTRAL && student_count > 0 ) { check_head = is_this_course_in_check_list(check_head, course_ptr, &found); if(!found) course_ptr = check_all_passwd_data_in_xml(person_head, course_ptr); } free_option_person_list(person_head); /* shared_person_list.c */ } } /* for... */ free_course_group(check_head); return courses; } static int check_course_type(CREATED_COURSE_NODE *course) { CONFIG_STRUCT conf; char file[MAX_PATH +1]; snprintf(file, MAX_PATH +1, "%s/%s", course->course_subdir, course->course_dir); read_configuration_file (file, &conf); if(conf.standalone && course->course_type == STANDALONE) return 1; else if((!conf.standalone) && course->course_type == CENTRAL) return 1; else return 0; } static int update_org_id(CREATED_COURSE_NODE *course) { char org_id_file[MAX_PATH +1]; char org_id[MAX_PATH +1]; FILE *fp; int found =0; snprintf(org_id_file, MAX_PATH +1, "%s/%s", course->course_path, "org_id.txt"); fp = fopen(org_id_file, "a+"); if(!fp) return 1; while(fgets(org_id,MAX_PATH +1, fp)) { org_id[strlen(org_id) -1] = '\0'; if(!strcmp(org_id, course->org_id)) { found = 1; break; } } if( !found) { if(fseek(fp, 0, SEEK_END)) return 1; fprintf(fp, "%s\n", course->org_id); } fclose(fp); return 0; } CREATED_COURSE_NODE * create_course_with_teachers(CREATED_COURSE_NODE *course_head) { CREATED_COURSE_NODE *ptr; CONFIG_STRUCT conf; for(ptr = course_head; ptr; ptr = ptr->next) { if(ptr->course_type == TEMPLATE) { /* the first teacher's username is used as the course_subdir within the templates directory */ snprintf(ptr->course_subdir, MAX_COURSE_SUBDIR + 1, "T%s", ptr->head->user.username); *(ptr->course_subdir + MAX_COURSE_SUBDIR) = '\0'; snprintf(ptr->course_path, MAX_PATH + 1, "%s%s/%s", TEMPLATE_PATH, ptr->course_subdir, ptr->course_dir); } else snprintf(ptr->course_path, MAX_PATH + 1, "%s%s/%s", COURSE_PATH, ptr->course_subdir, ptr->course_dir); if(file_exists(ptr->course_path)) /* shared_file_util.c */ { if(ptr->course_type == TEMPLATE) ptr->exists = UPDATE; /* Course already exists */ else { if(check_course_type(ptr)) { ptr->exists = UPDATE; /* Course already exists */ ptr =add_teachers(ptr); } else ptr->exists = TYPE_CONFLICT; } update_org_id(ptr); } else { ptr->exists = C_NEW; /* new course */ if(create_course_dir(ptr)) { write_org_info(ptr); get_config_default_value(ptr, &conf); if(write_config_file(ptr->course_path, &conf)) { if(!create_inboxes_directory (ptr->course_path) ) ptr->exists = DIR_ERR; //can't create inbox, key, or people dirs if(!create_key_people(ptr->course_path)) ptr->exists = DIR_ERR; //can't create inbox, key, or people dirs else { if(conf.standalone && !write_logout_html(ptr->course_path)) ptr->exists = MSG_ERR; //can't write logout html file for standalone course or chat log if( !write_chat_message_log(ptr->course_path)) ptr->exists = MSG_ERR; // chat log else ptr =add_teachers(ptr); } } else ptr->exists = CONFIG_ERR; // can't write conf file } else { ptr->exists = COURSE_ERR; // can't create course dir } } ptr->t_state = write_passwd_file(ptr, ptr->head) == 1? T_SUCCESS : OPEN_ERR; } return course_head; } void create_standalone_with_students(CREATED_COURSE_NODE *stand_head) { CREATED_COURSE_NODE *ptr; char file_path[MAX_PATH +1]; for(ptr = stand_head; ptr; ptr = ptr->next) { if(ptr && (ptr->t_state == T_SUCCESS)) { for(ptr->add_current = ptr->add_head; ptr->add_current; ptr->add_current = ptr->add_current->next) { if(ptr->add_current->user.group != FACULTY) { snprintf(file_path, MAX_PATH +1, "%s/%s/%s", ptr->course_path,PEOPLE_DIR, ptr->add_current->user.username); if(!file_exists(file_path)) { if(ptr->add_current->user.is_new != ERROR_UID) { if(create_one_person_dir(ptr->course_path, ptr->add_current->user.username)) ptr->add_current->user.add_state = FINISH; else ptr->add_current->user.add_state = FAILED; } } else ptr->add_current->user.add_state = USEREXISTS; } else { if(ptr->exists == C_NEW) ptr->add_current->user.add_state = FINISH; else ptr->add_current->user.add_state = USEREXISTS; } } } } } /* for debugging only */ void dump_xml_list(XML_COURSE_INFO_LIST *list) { int students = 0; send_content_type(); puts("
\n");
 for(list->current = list->head; list->current; list->current=list->current->next)
  {
   printf("\n\nCourse Code: %s\n", list->current->course_code);
   printf("Title: %s\n", list->current->title);
   printf("Semester: %s\n", list->current->semester);   
   printf("subdir: %s\n", list->current->subdir);   
   printf("dir_id: %s\n", list->current->dir_id);   
   printf("real_dir: %s\n", list->current->real_dir_id);   
   
   for(list->current->user_current = list->current->user_head, students = 0; 
                   list->current->user_current;
                      list->current->user_current = list->current->user_current->next, students++)
                      
    {
     printf("real name: %s
\n", list->current->user_current->data.realname); printf("last name: %s
\n", list->current->user_current->data.lastname); printf("id number: %s
\n", list->current->user_current->data.id); } printf("Total users: %d

\n", students); } // puts(""); // exit(1); } /*** for debugging only ***/ void dump_user_list(USER_GROUP_INFO_LIST *user_list) { USER_GROUP_INFO *ptr; COURSE_GROUP *course_ptr; for(ptr=user_list->head; ptr; ptr = ptr->next) { printf("lastname= %s
\n", ptr->user.last); printf("first= %s
\n", ptr->user.first); printf("id = %s
\n", ptr->user.id); for(course_ptr = ptr->head; course_ptr; course_ptr=course_ptr->next) { printf("subdir : %s
\n", course_ptr->course_subdir); printf("coursedir : %s
\n", course_ptr->course_dir); } } } void set_course_data_record_log(CREATED_COURSE_NODE *head, const char *prefix, const char *action) { #define MAX_TMP_NAME 50 CREATED_COURSE_NODE *ptr; USER_NODE *t_node; int course_count =0; int drop_count =0; int people_count, i =0; char name[MAX_TMP_NAME]; for(ptr = head; ptr; ptr = ptr->next) { snprintf(name, MAX_TMP_NAME, "%s.%d.type", prefix, i); cs_set_int_value(name, ptr->course_type); snprintf(name, MAX_TMP_NAME, "%s.%d.course_subdir", prefix , i); cs_set_value(name, ptr->course_subdir); snprintf(name, MAX_TMP_NAME, "%s.%d.course_dir", prefix , i); cs_set_value(name, ptr->course_dir); snprintf(name, MAX_TMP_NAME, "%s.%d.course_org", prefix , i); cs_set_value(name, ptr->org_id); snprintf(name, MAX_TMP_NAME, "%s.%d.course_no", prefix , i); cs_set_value(name, ptr->course_no); snprintf(name, MAX_TMP_NAME, "%s.%d.course_title", prefix , i); cs_set_value(name, ptr->course_title); snprintf(name, MAX_TMP_NAME, "%s.%d.course_semester", prefix , i); cs_set_value(name, ptr->course_semester); snprintf(name, MAX_TMP_NAME, "%s.%d.exists", prefix , i); cs_set_int_value(name, ptr->exists); course_count++; people_count =0; drop_count = 0; for(t_node = ptr->add_head; t_node; t_node = t_node->next) { if(strcmp(t_node->user.password, "drop") == 0) drop_count++; if(strcmp(t_node->user.password, "add") == 0 || (t_node->user.group == FACULTY && strcmp(t_node->user.password, "drop") != 0) ) { snprintf(name, MAX_TMP_NAME, "%s.%d.users.%d.first", prefix , i, people_count); cs_set_value(name, t_node->user.first); snprintf(name, MAX_TMP_NAME, "%s.%d.users.%d.last", prefix , i, people_count); cs_set_value(name, t_node->user.last); snprintf(name, MAX_TMP_NAME, "%s.%d.users.%d.id", prefix , i, people_count); cs_set_value(name, t_node->user.id); snprintf(name, MAX_TMP_NAME, "%s.%d.users.%d.username", prefix , i, people_count); cs_set_value(name, t_node->user.username); snprintf(name, MAX_TMP_NAME, "%s.%d.users.%d.group", prefix , i, people_count); cs_set_int_value(name, t_node->user.group); snprintf(name, MAX_TMP_NAME, "%s.%d.users.%d.is_new", prefix , i, people_count); cs_set_int_value(name, t_node->user.is_new); snprintf(name, MAX_TMP_NAME, "%s.%d.users.%d.add_state", prefix , i, people_count); cs_set_int_value(name, t_node->user.add_state); snprintf(name, MAX_TMP_NAME, "%s.%d.users.%d.central_state", prefix , i, people_count); cs_set_int_value(name, t_node->user.central_state); people_count++ ; } } if(people_count || drop_count) update_roster_log(action, "", ptr->course_no, ptr->course_title, people_count, drop_count, "Success"); /* shared_wnec_roster_log.h */ i++; } if(!strcmp(prefix, "ctr")) cs_set_int_value("ctr_total", course_count); #undef MAX_TMP_NAME }