#include #include #include #include #include "global.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_translate_url.h" #define NOTEAM '!' /* flags no team parameter defined */ typedef struct expanded_topic_node { int topic; struct expanded_topic_node *next; } EXPANDED_TOPIC_NODE; EXPANDED_TOPIC_NODE *expanded_head = 0; /* list of topics that are expanded */ static void read_parameters (char *course, char *key, int *grp, int *topic, int *expand, char *from) { char tmp[10]; cs_get_required_parameter ("crs", course, MAX_PATH); cs_get_required_parameter ("id", key, MAX_KEY); cs_get_required_parameter ("grp", tmp, 5); *grp = atoi (tmp); cs_get_required_parameter ("topic", tmp, 5); *topic = atoi (tmp); cs_get_required_parameter ("expand", tmp, 5); *expand = atoi (tmp); cs_get_required_parameter ("from", from, MAX_PATH); } static void report_write_error () { cs_critical_error (ERR_ERROR_WRITING_FILTER, ""); } static void report_memory_error () { cs_critical_error (ERR_MALLOC_FAILED,""); } static void add_to_list (int new_topic) { EXPANDED_TOPIC_NODE *ptr; if (!expanded_head) { expanded_head = (EXPANDED_TOPIC_NODE *) malloc (sizeof (EXPANDED_TOPIC_NODE)); if (!expanded_head) report_memory_error (); expanded_head->topic = new_topic; expanded_head->next = (EXPANDED_TOPIC_NODE *) 0; } else { for (ptr = expanded_head; ptr->next; ptr = ptr->next) if (ptr->topic == new_topic) return; /* new_topic is already on the list */ if (ptr->topic == new_topic) return; /* check last node */ ptr->next = (EXPANDED_TOPIC_NODE *) malloc (sizeof (EXPANDED_TOPIC_NODE)); if (!ptr->next) report_memory_error (); ptr = ptr->next; ptr->topic = new_topic; ptr->next = (EXPANDED_TOPIC_NODE *) 0; } } static void remove_from_list (int remove_topic) { EXPANDED_TOPIC_NODE *ptr, *ptr2; for (ptr = expanded_head; ptr && (ptr->topic != remove_topic); ptr = ptr->next); if (!ptr) return; /* not found, shouldn't happen, but let's ignore */ if (ptr == expanded_head) { expanded_head = expanded_head->next; free (ptr); } else { for (ptr2 = expanded_head; ptr2 && (ptr2->next != ptr); ptr2 = ptr2->next); if (!ptr2) cs_critical_error (ERR_REMOVAL_FROM_LIST_FAILED, ""); ptr2->next = ptr->next; free (ptr); } } static void build_expand_list (const char *filter_path, NEWS_FILTER * filter) { FILE *fp; EXPANDED_TOPIC_NODE *ptr = 0; int topic; fp = fopen (filter_path, "r"); if (fp) { fread (filter, sizeof (NEWS_FILTER), 1, fp); while (fread (&topic, sizeof (int), 1, fp) == 1) { if (!expanded_head) { expanded_head = (EXPANDED_TOPIC_NODE *) malloc (sizeof (EXPANDED_TOPIC_NODE)); ptr = expanded_head; } else { ptr->next = (EXPANDED_TOPIC_NODE *) malloc (sizeof (EXPANDED_TOPIC_NODE)); ptr = ptr->next; } if (!ptr) cs_critical_error (ERR_MALLOC_FAILED, ""); ptr->topic = topic; ptr->next = (EXPANDED_TOPIC_NODE *) 0; } fclose (fp); } } static void write_expand_list (const char *filter_path, NEWS_FILTER * filter) { FILE *fp; EXPANDED_TOPIC_NODE *ptr; fp = fopen (filter_path, "w"); if (!fp) report_write_error (); if (fwrite (filter, sizeof (NEWS_FILTER), 1, fp) != 1) report_write_error (); for (ptr = expanded_head; ptr; ptr = ptr->next) if (fwrite (&ptr->topic, sizeof (int), 1, fp) != 1) report_write_error (); fclose (fp); } static void free_expand_list () { EXPANDED_TOPIC_NODE *ptr; while (expanded_head) { ptr = expanded_head; expanded_head = expanded_head->next; free (ptr); } } static void expand_topic (int expand, int new_topic) { NEWS_FILTER filter; char filter_path[MAX_PATH + 1]; snprintf (filter_path, MAX_PATH + 1, "%s/%s", discussion_path, NEWS_FILTER_FNAME); build_expand_list (filter_path, &filter); if (expand) /* if we are adding 'new_topic' */ add_to_list (new_topic); else remove_from_list (new_topic); write_expand_list (filter_path, &filter); free_expand_list (); } static void redirect_user (char *from, int topic) { char new_from[MAX_PATH + 1]; translate_url_substitutes (new_from, from, MAX_PATH + 1, 0); /* shared_translate_url.c */ if(topic == -1) printf ("Location: %s\n\n", new_from); else printf ("Location: %s#%d\n\n", new_from,topic); } static void expand_all (SESSION *user, int grp) { FILE *fp; NEWS_FILTER filter; char filter_path[MAX_PATH + 1]; MSG_TREE_NODE *ptr; snprintf (filter_path, MAX_PATH + 1, "%s/%s", discussion_path, NEWS_FILTER_FNAME); fp = fopen (filter_path, "r"); if (fp) { if (fread (&filter, sizeof (NEWS_FILTER), 1, fp) != 1) cs_critical_error (ERR_ERROR_READING_FILTER, ""); fclose (fp); } else { filter.oldest_first = 1; filter.show_user_hidden = 1; filter.show_teacher_hidden = 1; } fp = fopen (filter_path, "w"); if (!fp) cs_critical_error (ERR_ERROR_CREATING_FILTER, ""); if (fwrite (&filter, sizeof (NEWS_FILTER), 1, fp) != 1) cs_critical_error (ERR_ERROR_WRITING_FILTER, ""); build_topic_only_tree(user,grp); /* shared_news_util.c */ for(ptr = tree_head; ptr; ptr=ptr->next) if (fwrite (&ptr->data.info.topic_id, sizeof (int), 1, fp) != 1) cs_critical_error (ERR_ERROR_WRITING_FILTER, ""); fclose (fp); free_msg_tree(tree_head); /* shared_news_util.c */ } static void collapse_all () { FILE *fp; NEWS_FILTER filter; char filter_path[MAX_PATH + 1]; snprintf (filter_path, MAX_PATH + 1, "%s/%s", discussion_path, NEWS_FILTER_FNAME); fp = fopen (filter_path, "r"); if (fp) { if (fread (&filter, sizeof (NEWS_FILTER), 1, fp) != 1) cs_critical_error (ERR_ERROR_READING_FILTER, ""); fclose (fp); } else { filter.oldest_first = 1; filter.show_user_hidden = 1; filter.show_teacher_hidden = 1; } fp = fopen (filter_path, "w"); if (!fp) cs_critical_error (ERR_ERROR_CREATING_FILTER, ""); if (fwrite (&filter, sizeof (NEWS_FILTER), 1, fp) != 1) cs_critical_error (ERR_ERROR_WRITING_FILTER, ""); fclose (fp); } int main (void) { char course[MAX_PATH + 1]; /* from crs=? command line */ char key[MAX_KEY + 1]; /* from id=? command line */ int grp; /* from grp=? command line */ int topic; /* from topic=? command line */ int expand; /* from expand=? command line */ char from[MAX_PATH + 1]; /* from from=? command line */ SESSION user; CONFIG_STRUCT conf; /* the configuration read from config file */ char scratch[10]; cs_cgi_init(); read_parameters (course, key, &grp, &topic, &expand, from); read_configuration_file (course, &conf); /* shared_util.c */ validate_key (key, &user, &conf); /* shared_util.c */ set_discussion_names (conf.course_path, user.username, grp); /* shared_news_util.c */ if (topic == -1) { if (expand) { if ((user.group == FACULTY) && (grp == TEAM_TEACH)) { cs_get_required_parameter ("team", scratch, 5); /* shared_cgi_util.c */ user.team = *scratch; /* switch this teacher's team to that supplied on the command line */ } expand_all (&user,grp); } else collapse_all (); } else expand_topic (expand, topic); redirect_user (from, topic); cs_cgi_destroy(); return 0; }