#include #include #include #include #include #include "global.h" #include "custom.h" /* for date FORMAT strings */ #include "manhat-lib/shared_util.h" #include "manhat-lib/shared_news_util.h" #include "manhat-lib/shared_potato_util.h" #include "manhat-lib/shared_person_list.h" /* for get_user_info() */ #include "manhat-lib/shared_cs_util.h" #include "manhat-lib/shared_bio.h" #include "manhat-lib/shared_time.h" typedef enum event { NEW_MSG, READ_MSG, LOG_IN, SEND_MSG, ENTER_CHAT , TOOK_SELFTEST} EVENT; #define NO_MODULE 99 struct event_node { time_t date; /* this is a 'normalized' time 01:01.01 on the date of the event */ time_t time; /* this is the standard unix time (secs after 1/1/70) */ int module; /* one of MAIL, GRADES, TEAM_DISCUSSION, etc.. see global.h ** for logins, this is set to NO_MODULE, #defined above */ EVENT event; /* what happened */ char *tooltip; /* a description of what happened */ struct event_node *next; }; typedef struct event_node EVENT_NODE; EVENT_NODE *head = 0; EVENT_NODE *tail = 0; /* next two global variables are used in the recursive ** add_news_msg() function... they are made global to ** conserve stack space */ char temp_tip[MAX_PATH + 1]; char temp_timestring[MAX_TIMESTRING + 1]; HDF *hdf; void set_back_url(const char *prog, const char *course, const char *key, int show_list) { char url[MAX_PATH +1]; snprintf(url, MAX_PATH +1, "%s?id=%s&crs=%s&list=%d", prog, key, course, show_list); cs_set_value("back_url", url); } static void read_parameters (char *course, char *key, char *username) { #define MAX_TEMP_USERNAME (MAX_USERNAME + MAX_NAME + 2) char temp_username[MAX_TEMP_USERNAME]; /* may look like: "snarmont:Steve Narmontas" */ char *ptr; int show_list; char prog[MAX_PATH +1]; /* may look like: "snarmont:Steve Narmontas" */ cs_get_required_parameter ("crs", course, MAX_PATH); cs_set_value("crs", course); cs_get_required_parameter ("id", key, MAX_ID); cs_set_value("id", key); cs_get_optional_parameter ("list", temp_username, MAX_ID); show_list = atoi(temp_username); if(strlen(temp_username)) { cs_get_required_parameter ("username", temp_username, MAX_TEMP_USERNAME); ptr = strchr (temp_username, ':'); if (!ptr) cs_critical_error(ERR_PARAM_MISSING, "username"); *ptr = '\0'; if(!strlen(temp_username)) cs_critical_error(ERR_PARAM_MISSING, "username"); strncpy (username, temp_username, MAX_USERNAME); } else cs_get_required_parameter ("username", username, MAX_USERNAME); cs_get_required_parameter ("prog", prog, MAX_PATH); cs_set_value("prog", prog); cs_set_int_value("show_list", show_list); set_back_url(prog, course, key, show_list); #undef MAX_TEMP_USERNAME } void unexpected_end () { cs_critical_error (ERR_UNEXPECTED_END_OF_LINE, ""); } int record_cmp (EVENT_NODE * a, EVENT_NODE * b) { if ((a->time) < (b->time)) return -1; else if ((a->time) > (b->time)) return 1; return 0; } void sort_event_list () { EVENT_NODE *q, *t, *p, *r; if (head != NULL) { t = head; while (t->next) { q = t->next; if (record_cmp (q, head) < 0) { t->next = q->next; q->next = head; head = q; } else { r = head; p = r->next; while (record_cmp (q, p) > 0) { r = p; p = r->next; } if (q == p) t = q; else { t->next = q->next; q->next = p; r->next = q; } } } /* adjust global tail pointer */ for(tail=head; tail->next; tail=tail->next); } } void memory_error () { cs_critical_error (ERR_MALLOC_FAILED, ""); } /* allocates a new node at the end of the linked list with global variable 'tail' pointing to the ** new node... */ void new_event_node () { if (!head) { head = (EVENT_NODE *) malloc (sizeof (EVENT_NODE)); if (!head) memory_error (); tail = head; } else { tail->next = (EVENT_NODE *) malloc (sizeof (EVENT_NODE)); if (!tail->next) memory_error (); tail = tail->next; } tail->next = (EVENT_NODE *) 0; } /* returns a time_t value which is 01:01.01 on the same date as 'a' */ time_t normalized_time (time_t a) { struct tm a_tm; a_tm = *localtime (&a); a_tm.tm_hour = 1; a_tm.tm_min = 1; a_tm.tm_sec = 1; return (mktime (&a_tm)); } /* searches mail directory for *.new files and adds the new arrivals to the ** event list */ void add_newfile_postoffice_msgs (char *username, SESSION *user) { DIR *dir_p; struct dirent *dir_entry_p; char *cptr; char newpath[MAX_PATH + 1]; NEWFILE_RECORD newfile_info; FILE *fp; char timestring[MAX_TIMESTRING + 1], temp[MAX_PATH + 1]; int viewing_own; /* is teacher viewing his own record? */ int tip_len; dir_p = opendir (discussion_path); /* discussion_path is in shared_news_util.c */ if (!dir_p) cs_critical_error (ERR_OPENDIR_FAILED, ""); while (NULL != (dir_entry_p = readdir (dir_p))) { cptr = strstr (dir_entry_p->d_name, ".new"); if (cptr && *(cptr + 4) == '\0') { /* i.e. if file ends in .new */ new_event_node (); snprintf (newpath, MAX_PATH + 1, "%s/%s", discussion_path, dir_entry_p->d_name); fp = fopen (newpath, "r"); if (!fp) cs_critical_error (ERR_FOPEN_READ_FAILED, ""); if (fread (&newfile_info, sizeof (NEWFILE_RECORD), 1, fp) != 1) cs_critical_error (ERR_FREAD_FAILED, ""); fclose (fp); tail->event = NEW_MSG; tail->time = newfile_info.time_sent; /* if msg is from this (faculty) user, or if faculty is viewing his own ** stats, then show some detail ** otherwise, say "(private Post Office message)") */ viewing_own = !strcmp (user->username, username); if (viewing_own || !strcmp (user->username, newfile_info.sender)) { strftime (timestring, MAX_TIMESTRING, TIME_FORMAT, localtime (&newfile_info.time_sent)); snprintf (temp, MAX_PATH + 1, "%s (%s %s)", newfile_info.subject, viewing_own ? newfile_info.sender_realname : "", timestring); } else strncpy (temp, hdf_get_value(hdf, "stats_post_office", "(private Post Office message)"), MAX_PATH + 1); tip_len = strlen (temp); tail->tooltip = (char *) malloc ((tip_len + 1) * sizeof (char)); if (!tail->tooltip) memory_error (); strncpy (tail->tooltip, temp, tip_len + 1); tail->module = MAIL; tail->date = normalized_time (newfile_info.time_sent); } } closedir (dir_p); } void add_inbox_postoffice_msgs (char *username, SESSION *user) { char inbox_path[MAX_PATH + 1]; FILE *fp; INBOX_RECORD msg; char timestring[MAX_TIMESTRING + 1]; char temp[MAX_PATH + 1]; struct tm; int viewing_own; /* is this person viewing his own record? */ int tip_len; snprintf (inbox_path, MAX_PATH + 1, "%s/%s", discussion_path, INBOX_FNAME); fp = fopen (inbox_path, "r"); if (fp) { while (fread (&msg, sizeof (INBOX_RECORD), 1, fp) == 1) { /* FIRST DO NEW_MSG EVENTS */ new_event_node (); tail->event = NEW_MSG; tail->module = MAIL; tail->time = msg.newfile_info.time_sent; /* if msg is from this (faculty) user, or if faculty is viewing his own calendar, ** then show some detail ** otherwise, say "(private Post Office message)") */ viewing_own = !strcmp (user->username, username); if (viewing_own || !strcmp (user->username, msg.newfile_info.sender)) { strftime (timestring, MAX_TIMESTRING, TIME_FORMAT, localtime (&msg.newfile_info.time_sent)); snprintf (temp, MAX_PATH + 1, "%s (%s %s)", msg.newfile_info.subject, viewing_own ? msg.newfile_info.sender_realname : "", timestring); } else strncpy (temp, hdf_get_value(hdf, "stats_post_office", "(private Post Office message)"), MAX_PATH + 1); tip_len = strlen (temp); tail->tooltip = (char *) malloc ((tip_len + 1) * sizeof (char)); if (!tail->tooltip) memory_error (); strncpy (tail->tooltip, temp, tip_len + 1); tail->date = normalized_time (msg.newfile_info.time_sent); /* NEXT DO READ_MSG */ if (msg.time_read) { new_event_node (); tail->event = READ_MSG; tail->module = MAIL; tail->time = msg.time_read; /* if msg is from this (faculty) user, or if faculty is viewing his own calendar, ** then show some detail ** otherwise, say "(private Post Office message)") */ viewing_own = !strcmp (user->username, username); if (viewing_own || !strcmp (user->username, msg.newfile_info.sender)) { strftime (timestring, MAX_TIMESTRING, TIME_FORMAT, localtime (&msg.time_read)); snprintf (temp, MAX_PATH + 1, "%s (%s %s)", msg.newfile_info.subject, viewing_own ? msg. newfile_info.sender_realname : "", timestring); } else strncpy (temp, hdf_get_value(hdf, "stats_post_office", "(private Post Office message)"), MAX_PATH + 1); tip_len = strlen (temp); tail->tooltip = (char *) malloc ((tip_len + 1) * sizeof (char)); if (!tail->tooltip) memory_error (); strncpy (tail->tooltip, temp, tip_len + 1); tail->date = normalized_time (msg.time_read); } } /* while fread() */ fclose (fp); } } /* is username among the recipients of this msg? */ int user_is_recipient (char *this_username, OUTBOX_RECORD * msg) { char inf_path[MAX_PATH + 1]; FILE *fp; INFO info_record; int i; ATTACHMENT attach; PERSON pers; snprintf (inf_path, MAX_PATH + 1, "%s/%s", discussion_path, msg->info_fname); fp = fopen (inf_path, "r"); if (!fp) cs_critical_error (ERR_FOPEN_READ_FAILED, ""); if (fread (&info_record, sizeof (INFO), 1, fp) != 1) cs_critical_error (ERR_FREAD_FAILED, ""); for (i = 1; i <= info_record.no_attachments; i++) if (fread (&attach, sizeof (ATTACHMENT), 1, fp) != 1) cs_critical_error (ERR_FREAD_FAILED, ""); while (fread (&pers, sizeof (PERSON), 1, fp) == 1) if (!strcmp (pers.username, this_username)) { fclose (fp); return 1; } fclose (fp); return 0; } void add_outbox_post_office_events (char *username, SESSION *user) { #define TEMP_LEN 256 /*length of temp string : must be at least MAX_SUBJECT + (MAX_TO * MAX_NAME) + len of timestring */ char outbox_path[MAX_PATH + 1]; FILE *fp; OUTBOX_RECORD msg; char timestring[MAX_TIMESTRING + 1]; char temp[TEMP_LEN]; /* must be at least MAX_SUBJECT + (MAX_TO * MAX_NAME) + len of timestring */ struct tm; int viewing_own; /* is this person viewing his own record? */ int tip_len; snprintf (outbox_path, MAX_PATH + 1, "%s/%s", discussion_path, OUTBOX_FNAME); fp = fopen (outbox_path, "r"); if (fp) { while (fread (&msg, sizeof (OUTBOX_RECORD), 1, fp) == 1) { new_event_node (); tail->event = SEND_MSG; tail->module = MAIL; tail->time = msg.time_sent; /* if msg is to this (faculty) user, or if faculty is viewing his own info ** then show some detail ** otherwise, say "(private Post Office message)") */ viewing_own = !strcmp (user->username, username); if (viewing_own || user_is_recipient (user->username, &msg)) { strftime (timestring, MAX_TIMESTRING, TIME_FORMAT, localtime (&msg.time_sent)); snprintf (temp, TEMP_LEN, "%s (%s %s)", msg.subject, viewing_own ? msg.to : "", timestring); } else strncpy (temp, hdf_get_value(hdf, "stats_post_office", "(private Post Office message)"), TEMP_LEN); tip_len = strlen (temp); tail->tooltip = (char *) malloc ((tip_len + 1) * sizeof (char)); if (!tail->tooltip) memory_error (); strncpy (tail->tooltip, temp, tip_len + 1); tail->date = normalized_time (msg.time_sent); } fclose (fp); } #undef TEMP_LEN } void add_post_office_events (char *username, CONFIG_STRUCT *conf, SESSION *user) { set_discussion_names (conf->course_path, username, MAIL); /* shared_news_util.c */ add_inbox_postoffice_msgs (username, user); add_newfile_postoffice_msgs (username, user); add_outbox_post_office_events (username, user); } static void add_news_msg(SESSION *target_user, SESSION *user, MSG_TREE_NODE *root, int grp) { int user_sent; /* did 'target_user->username' send this msg? */ int tip_len; if(!root) return; user_sent = !strcmp(root->data.info.sender,target_user->username); new_event_node(); tail->module = grp; tail->event = user_sent ? SEND_MSG : NEW_MSG; tail->time = root->data.info.time_sent; /* don't show details if this is TEAM_DISCUSSION and the teacher running this program ** is not on the sender's team ** for the Assignments module, if we're looking at the teacher's record, we must show ** who the message is 'to' or 'from' */ if (grp == TEAM_DISCUSSION && (root->data.info.sender_team != user->team)) strncpy (temp_tip, hdf_get_value(hdf, "stats_team_discussion", "(private Team Discussion message)"), MAX_PATH + 1); else if ((grp == ASSIGNMENTS) && !strcmp (user->username, target_user->username)) { strftime (temp_timestring, MAX_TIMESTRING, TIME_FORMAT, localtime (&(root->data.info.time_sent)) ); snprintf (temp_tip, MAX_PATH + 1, "%s (%s %s)", root->data.info.subject, root->data.info.sender_realname, temp_timestring); } else { strftime (temp_timestring, MAX_TIMESTRING, TIME_FORMAT, localtime (&(root->data.info.time_sent)) ); snprintf (temp_tip, MAX_PATH + 1, "%s (%s)", root->data.info.subject, temp_timestring); } tip_len = strlen (temp_tip); tail->tooltip = (char *) malloc ((tip_len + 1) * sizeof (char)); if (!tail->tooltip) memory_error (); strncpy (tail->tooltip, temp_tip, tip_len + 1); tail->date = normalized_time (root->data.info.time_sent); /** in addition to the above, each message MAY also be a READ_MSG event ** if 'target->username' did not send the message and if the message was read */ if (!user_sent && root->user_data.time_read) { new_event_node (); tail->module = grp; tail->event = READ_MSG; tail->time = root->user_data.time_read; /* don't show details if this is TEAM_DISCUSSION and teacher running this program ** is not on the sender's team */ if (grp == TEAM_DISCUSSION && (root->data.info.sender_team != user->team)) strncpy (temp_tip, hdf_get_value(hdf, "stats_team_discussion", "(private Team Discussion message)"), MAX_PATH + 1); else { strftime (temp_timestring, MAX_TIMESTRING, TIME_FORMAT, localtime (&(root->user_data.time_read)) ); snprintf (temp_tip, MAX_PATH + 1, "%s (%s %s)", root->data.info.subject, root->data.info.sender_realname, temp_timestring); } tip_len = strlen (temp_tip); tail->tooltip = (char *) malloc ((tip_len + 1) * sizeof (char)); if (!tail->tooltip) memory_error (); strncpy (tail->tooltip, temp_tip, tip_len + 1); tail->date = normalized_time (root->user_data.time_read); } /* if (!user_sent && root->user_data.time_read)*/ add_news_msg(target_user,user,root->next,grp); add_news_msg(target_user,user,root->reply,grp); } void add_news_events (SESSION *target_user, int grp, CONFIG_STRUCT *conf, SESSION *user) { int is_fac_teamteach; time_t current_time; set_discussion_names (conf->course_path, target_user->username, grp); /* shared_news_util.c */ is_fac_teamteach = ((target_user->group == FACULTY) && (grp == TEAM_TEACH)); build_event_list_msg_tree(target_user,grp,is_fac_teamteach,¤t_time); /* shared_news_util.c */ add_news_msg(target_user,user,tree_head,grp); free_msg_tree(tree_head); /* shared_news_util.c */ } void add_login_events (char *username, CONFIG_STRUCT *conf) { char logpath[MAX_PATH + 1]; FILE *fp; time_t login_time; char timestring[MAX_TIMESTRING + 1]; int tip_len; snprintf (logpath, MAX_PATH + 1, "%speople/%s/%s", conf->course_path, username,ACCESS_LOG_FNAME); fp = fopen (logpath, "r"); if (!fp) return; while (fread (&login_time, sizeof (time_t), 1, fp) == 1) { new_event_node (); tail->event = LOG_IN; tail->module = NO_MODULE; tail->time = login_time; strftime (timestring, MAX_TIMESTRING, TIME_FORMAT, localtime (&login_time)); tip_len = strlen (timestring); tail->tooltip = (char *) malloc ((tip_len + 1) * sizeof (char)); if (!tail->tooltip) memory_error (); strncpy (tail->tooltip, timestring, tip_len + 1); tail->date = normalized_time (login_time); } fclose (fp); } void add_chat_events (char *username, CONFIG_STRUCT *conf) { char logpath[MAX_PATH + 1]; FILE *fp; time_t login_time; char timestring[MAX_TIMESTRING + 1]; int tip_len; snprintf (logpath, MAX_PATH + 1, "%speople/%s/chat_access.log", conf->course_path, username); fp = fopen (logpath, "r"); if (!fp) return; while (fread (&login_time, sizeof (time_t), 1, fp) == 1) { new_event_node (); tail->event = ENTER_CHAT; tail->module = CHATTER; tail->time = login_time; strftime (timestring, MAX_TIMESTRING, TIME_FORMAT, localtime (&login_time)); tip_len = strlen (timestring); tail->tooltip = (char *) malloc ((tip_len + 1) * sizeof (char)); if (!tail->tooltip) memory_error (); strncpy (tail->tooltip, timestring, tip_len + 1); tail->date = normalized_time (login_time); } fclose (fp); } void add_selftest_events (const char *username, CONFIG_STRUCT *conf) { #define MAX_LONGSTRING 500 char logpath[MAX_PATH + 1]; FILE *fp; HOTPOTATO_INFO_STRUCT info; char timestring1[MAX_TIMESTRING + 1]; char tempstring[MAX_LONGSTRING + 1]; int tip_len, hours, minutes, seconds; snprintf (logpath, MAX_PATH + 1, "%speople/%s/selftest/%s", conf->course_path, username, HOTPOT_FNAME); fp = fopen (logpath, "r"); if (!fp) return; while (fread (&info, sizeof (HOTPOTATO_INFO_STRUCT), 1, fp) == 1) { new_event_node (); tail->event = TOOK_SELFTEST; tail->module = SELFTEST; tail->time = info.time_submitted; strftime (timestring1, MAX_TIMESTRING, TIME_FORMAT, localtime (&info.time_submitted)); /* shared_potato_util.c */ calculate_elapsed_time(info.elapsed_time, &hours, &minutes, &seconds); snprintf(tempstring,MAX_LONGSTRING,"%s: %s (%s) %s %s %02d:%02d:%02d", timestring1, info.exercise, info.orig_fname, hdf_get_value(hdf, "stats_score", "Score:"), info.score, hours, minutes, seconds); tip_len = strlen (tempstring); tail->tooltip = (char *) malloc ((tip_len + 1) * sizeof (char)); if (!tail->tooltip) memory_error (); strncpy (tail->tooltip, tempstring, tip_len + 1); tail->date = normalized_time (info.time_submitted); } fclose (fp); #undef MAX_LONGSTRING } void build_event_list (SESSION *target_user, CONFIG_STRUCT *conf, SESSION *user) { add_post_office_events (target_user->username, conf, user); add_news_events (target_user, CLASS_DISCUSSION, conf, user); add_news_events (target_user, STUDENT_LOUNGE, conf, user); add_news_events (target_user, TEAM_DISCUSSION, conf, user); add_news_events (target_user, HANDOUTS_NOTICES, conf, user); add_news_events (target_user, INTERNET_RESOURCES, conf, user); add_news_events (target_user, ASSIGNMENTS, conf, user); add_news_events (target_user, TEAM_TEACH, conf, user); add_news_events (target_user, SELFTEST, conf, user); add_news_events (target_user, LECTURES, conf, user); //add_news_events (target_user, SURVEYS, conf, user); add_news_events (target_user, PODCASTS, conf, user); add_login_events (target_user->username, conf); add_chat_events (target_user->username, conf); add_selftest_events (target_user->username, conf); sort_event_list (); } void free_event_list () { EVENT_NODE *ptr; while (head) { ptr = head; head = head->next; free (ptr->tooltip); free (ptr); } } void no_event_error (char *realname) { cs_critical_error (ERR_NO_EVENTS_RECORDED_FOR_X, realname); } /* returns 'a' as same calendar date, but with hour=1 minute=1 second=1 */ time_t normalized (time_t a) { struct tm a_tm; a_tm = *localtime (&a); a_tm.tm_hour = 1; a_tm.tm_min = 1; a_tm.tm_sec = 1; return mktime (&a_tm); } /* returns a 'normalized' time_t value which is the first day of the ** same month of 'a' */ time_t first_monthday (time_t a) { struct tm a_tm; a_tm = *localtime (&a); a_tm.tm_hour = 1; a_tm.tm_min = 1; a_tm.tm_sec = 1; a_tm.tm_mday = 1; return mktime (&a_tm); } /* determine what dates our calendar will span ** 'warn' is set to true if the start date of our calendar is preceded by ** an event on the list */ void set_calendar_dates (COURSE_DATES * calendar_date, COURSE_DATES * course_date, time_t today, int *warn) { /* always use the first day of the same month ** as the START date specified by the user */ calendar_date->start_date = first_monthday (course_date->start_date); /* set 'warn' flag if an event happened before the start date */ *warn = (head->date < calendar_date->start_date); /* use the earlier of 'today' or the specified course ending date */ calendar_date->end_date = (today < course_date->end_date) ? today : course_date->end_date; } void get_month_info (time_t current_day, int *lastday, int *month, int *year, int *dow) { struct tm time_tm; time_tm = *localtime (¤t_day); *month = time_tm.tm_mon; *year = time_tm.tm_year + 1900; *lastday = days_in_month (time_tm.tm_mon, time_tm.tm_year + 1900); /*shared_time.c */ *dow = time_tm.tm_wday; } void set_day_events (time_t day, int year, int month, int this_day) { #define MAX_TMP_NAME 40 EVENT_NODE *ptr; char *cptr; int i =0; char name[MAX_TMP_NAME]; char timestring[MAX_TIMESTRING + 1]; for (ptr = head; ptr; ptr = ptr->next) if (ptr->date == day) { snprintf(name, MAX_TMP_NAME, "event.%d.%d.%d.%d.module", year, month, this_day, i); if(ptr->module == CLASS_DISCUSSION) cs_set_value(name, "class_discussion"); else if(ptr->module == STUDENT_LOUNGE ) cs_set_value(name, "student_lounge"); else if(ptr->module == ANONYMOUS_DISCUSSION) cs_set_value(name, "anonymous_discussion"); else if(ptr->module == TEAM_DISCUSSION) cs_set_value(name, "team_discussion"); else if(ptr->module == HANDOUTS_NOTICES) cs_set_value(name, "handouts_notices"); else if(ptr->module == INTERNET_RESOURCES) cs_set_value(name, "internet_resources"); else if(ptr->module == ASSIGNMENTS) cs_set_value(name, "assignments"); else if(ptr->module == TEAM_TEACH) cs_set_value(name, "team_teach"); else if(ptr->module == CHATTER) cs_set_value(name, "chatter"); else if(ptr->module == MAIL) cs_set_value(name, "mail"); else if(ptr->module == GRADES) cs_set_value(name, "grades"); else if(ptr->module == SELFTEST) cs_set_value(name, "selftest"); else if(ptr->module == LECTURES) cs_set_value(name, "lectures"); else if(ptr->module == CLIPBOARD) cs_set_value(name, "clipboard"); else if(ptr->module == PEOPLE) cs_set_value(name, "people"); else if(ptr->module == SURVEYS) cs_set_value(name, "surveys"); else if(ptr->module == PODCASTS) cs_set_value(name, "podcasts"); else if(ptr->module == 99) cs_set_value(name, "login"); /* strip out some HTML chars that will cause trouble */ for (cptr = ptr->tooltip; *cptr; cptr++) if ((*cptr == 44) || /* quote */ (*cptr == 39) || /* another quote ' */ (*cptr == '&') || (*cptr == '<') || (*cptr == '>') || (*cptr == '"')) *cptr = ' '; snprintf(name, MAX_TMP_NAME, "event.%d.%d.%d.%d.detail", year, month, this_day, i); cs_set_value(name, ptr->tooltip); snprintf(name, MAX_TMP_NAME, "event.%d.%d.%d.%d.time", year, month, this_day, i); strftime (timestring, MAX_TIMESTRING + 1, DOW_DATE_TIME_FORMAT,localtime (&(ptr->time))); cs_set_value(name, timestring); snprintf(name, MAX_TMP_NAME, "event.%d.%d.%d.%d.action", year, month, this_day, i); if(ptr->event == NEW_MSG) cs_set_value(name, "new_msg"); else if(ptr->event == READ_MSG) cs_set_value(name, "read_msg"); else if(ptr->event == LOG_IN) cs_set_value(name, "log_in"); else if(ptr->event == SEND_MSG) cs_set_value(name, "send_msg"); else if(ptr->event == ENTER_CHAT) cs_set_value(name, "enter_chat"); else if(ptr->event == TOOK_SELFTEST) cs_set_value(name, "took_selftest"); i++; } #undef MAX_TMP_NAME } void set_one_month_events (COURSE_DATES * calendar_date, COURSE_DATES * course_date, int *done) { #define SECS_PER_DAY (24 * 60 * 60) #define MAX_TMP_NAME 40 static time_t current_day = 0; static int i =0; char name[MAX_TMP_NAME]; int day, /* loop counter */ lastday, /* last day of month 28,29,30 or 31 */ month, /* 0 - 11 */ dow, /* day of week 0-6 */ year; /* eg, 1999 */ if (!current_day) current_day = calendar_date->start_date; get_month_info (current_day, &lastday, &month, &year, &dow); snprintf(name, MAX_TMP_NAME, "event_month.%d.year", i); cs_set_int_value(name, year); snprintf(name, MAX_TMP_NAME, "event_month.%d.month", i); cs_set_int_value(name, month); snprintf(name, MAX_TMP_NAME, "event_month.%d.days", i); cs_set_int_value(name, lastday); snprintf(name, MAX_TMP_NAME, "event_month.%d.start_day", i); cs_set_int_value(name, dow); i++; cs_set_int_value("max_month", i); for (day = 1; day <= lastday; day++) { set_day_events (current_day, year, month, day); current_day += SECS_PER_DAY; current_day = normalized_time (current_day); } *done = current_day > calendar_date->end_date; #undef SECS_PER_DAY #undef MAX_TMP_NAME } void set_event_data (char *realname, COURSE_DATES * course_date,CONFIG_STRUCT *conf) { time_t today_t; COURSE_DATES calendar_date; /* the dates our calendar will actually span */ int warn; /* warn viewer that events precede start date */ int done = 0; /* get current server time */ today_t = time (NULL); set_calendar_dates (&calendar_date, course_date, today_t, &warn); if(warn) cs_set_int_value("warn", 1); cs_set_value("realname", realname); while (!done) set_one_month_events (&calendar_date, course_date, &done); } static void get_actual_course_dates(COURSE_DATES *dates) { EVENT_NODE *ptr; if(head) { dates->start_date = head->date; for(ptr=head; ptr->next; ptr=ptr->next); dates->end_date = ptr->date; } else /* this should never be called w/out a valid list, but just in case */ { dates->start_date = 0; dates->end_date = 0; } } void set_user_info(SESSION *target, CONFIG_STRUCT *conf, const char *course, const char *key) { CONFIG_STRUCT fake_conf; fake_conf = *conf; fake_conf.people = 1; cs_set_bio_link( target->username, course, &fake_conf, key, 0, 0, "user", 30); /* shared_bio.c */ cs_set_value("user.0.realname", target->realname); cs_set_value("user.0.username", target->username); } void set_all_events (char *username, char *crs, char *key, CONFIG_STRUCT *conf, SESSION *user) { COURSE_DATES course_date; /* start/end dates specified by teacher */ SESSION target_user; if(!get_user_info(username, &target_user,conf)) /* shared_person_list.c */ cs_critical_error(ERR_PASSWD_PARSE_ERROR,""); get_lang_string(&hdf); build_event_list (&target_user, conf, user); set_user_info(&target_user, conf, crs, key); if (!head) no_event_error (target_user.realname); get_actual_course_dates(&course_date); set_event_data (target_user.realname, &course_date, conf); free_event_list (); hdf_destroy(&hdf); } int main () { char course[MAX_PATH + 1]; /* from crs=? command line */ char key[MAX_KEY + 1]; /* from id=? command line */ char username[MAX_USERNAME + 1]; /* from username=? command line */ SESSION user; CONFIG_STRUCT conf; /* the configuration read from config file */ cs_cgi_init(); read_parameters (course, key, username); read_configuration_file (course, &conf); /* shared_util.c */ validate_key (key, &user, &conf); /* shared_util.c */ cs_set_course_info(&conf); if ( (user.group == FACULTY) || (user.group == ADMIN)) set_all_events (username, course, key, &conf, &user); else cs_critical_error (ERR_REQUEST_DENIED, ""); #ifdef HIDE_MANHATTAN_USERNAMES cs_set_int_value("hide_manhattan_username", 1); #endif cs_cgi_display("stats_ind_calendar", 1); cs_cgi_destroy(); return 0; /* exit successfully */ }