#include #include #include #include #include #include /* for unlink() */ #include "global.h" #include "custom.h" /* for date FORMAT strings */ #include "manhat-lib/shared_util.h" #include "manhat-lib/shared_cs_util.h" #include "manhat-lib/shared_person_list.h" #include "manhat-lib/shared_news_util.h" #include "manhat-lib/shared_post_outbox.h" #include "manhat-lib/shared_translate_url.h" #include "manhat-lib/shared_access.h" #include "manhat-lib/shared_lock.h" typedef struct outbox_node { OUTBOX_RECORD data; struct outbox_node *next; struct outbox_node *prev; long offset; } OUTBOX_NODE; OUTBOX_NODE *outbox_head = 0; OUTBOX_NODE *outbox_tail = 0; static void read_parameters (char *course, char *key) { cs_get_required_parameter ("crs", course, MAX_PATH); cs_get_required_parameter ("id", key, MAX_KEY); } static void set_outbox_commands (const char *course, const char *key, int can_write, int access, const char *fromstring) { char url[MAX_PATH +1]; snprintf (url, MAX_PATH +1, "%s?crs=%s&id=%s", "main_menu", course, key); cs_set_value("main_menu_url", url); snprintf (url, MAX_PATH +1, "%s?crs=%s&id=%s","post_inbox", course, key); cs_set_value("post_inbox_url", url); if(can_write) { snprintf (url, MAX_PATH +1, "%s?crs=%s&id=%s&from=%s","post_new_memo", course, key, fromstring); cs_set_value("new_memo_url", url); } cs_set_int_value("outbox", 1); } static void build_outbox_list (CONFIG_STRUCT *conf, SESSION *user) { FILE *fp; char outbox_path[MAX_PATH + 1]; OUTBOX_RECORD msg; OUTBOX_NODE *ptr = 0; long offset = 0; snprintf (outbox_path, MAX_PATH + 1, "%s%s/%s/%s/%s", conf->course_path, PEOPLE_DIR, user->username, MAIL_DIR, OUTBOX_FNAME); fp = fopen (outbox_path, "r"); if (fp) { get_shared_lock(fileno(fp), 1); while (fread (&msg, sizeof (OUTBOX_RECORD), 1, fp) == 1) { if (msg.how_sent != DELETED) { /* add the record to the end of the linked list */ if (!outbox_head) { outbox_head = (OUTBOX_NODE *) malloc (sizeof (OUTBOX_NODE)); if (!outbox_head) cs_critical_error (ERR_MALLOC_FAILED, ""); ptr = outbox_head; ptr->prev = 0; } else { ptr->next = (OUTBOX_NODE *) malloc (sizeof (OUTBOX_NODE)); if (!ptr->next) cs_critical_error (ERR_MALLOC_FAILED, ""); ptr->next->prev = ptr; ptr = ptr->next; } ptr->data = msg; ptr->offset = offset; ptr->next = 0; outbox_tail = ptr; } offset = ftell (fp); } release_lock(fileno(fp)); fclose (fp); } } static void free_outbox_list () { OUTBOX_NODE *ptr; while (outbox_head) { ptr = outbox_head; outbox_head = outbox_head->next; free (ptr); } } void set_outbox_msgs (const char *course, const char *key, NEWS_FILTER *filter, CONFIG_STRUCT *conf, SESSION *user, const char *fromstring, int can_write, int allow_user_hidden) { #define MAX_TMP_NAME 30 char timestring[MAX_TIMESTRING + 1]; char *cptr; OUTBOX_NODE *ptr; int several_recipients; /* does the message have more than one recipient? */ int i =0; int str_index = 0, recipient_number = 0, partial_to_list = 0; char url[MAX_PATH +1]; char temp[MAX_NAME +1]; char name[MAX_TMP_NAME ]; char *escaped_subject = (char *) 0; int fixed_width_font; fixed_width_font = USE_FIXED_FONT(conf->misc); /* global.h */ cs_set_int_value("fixed_font", fixed_width_font? 1: 0); cs_set_int_value("allow_user_hidden", allow_user_hidden? 1 : 0); if (outbox_head) { for (i = 0, ptr = filter->oldest_first ? outbox_head : outbox_tail; ptr; ptr = filter->oldest_first ? ptr->next : ptr->prev, i++) { if(!allow_user_hidden || filter->show_user_hidden || !ptr->data.is_sleepy) { several_recipients = strchr (ptr->data.to, '|')? 1 : 0; if(allow_user_hidden) { snprintf(url, MAX_PATH +1, "%s?crs=%s&id=%s&loc=%ld&outbox=1&hide=%d", "post_mark_hidden", course, key, ptr->offset, ptr->data.is_sleepy?0:1); snprintf(name, MAX_TMP_NAME, "msg.%d.%s", i, ptr->data.is_sleepy? "unhide_url" : "hide_url"); cs_set_value(name, url); snprintf(name, MAX_TMP_NAME, "msg.%d.is_sleepy", i); cs_set_int_value(name, ptr->data.is_sleepy); } snprintf(name, MAX_TMP_NAME, "msg.%d.is_unread", i); cs_set_int_value(name, ptr->data.unread? 1 : 0); snprintf(name, MAX_TMP_NAME, "msg.%d.has_attachments", i); cs_set_int_value(name, ptr->data.attachments? 1 : 0); snprintf (url, MAX_PATH +1, "%s?crs=%s&id=%s&loc=%ld&from=%s", "post_outbox_info", course, key, ptr->offset, fromstring); snprintf(name, MAX_TMP_NAME, "msg.%d.info_url", i); cs_set_value(name, url); snprintf(name, MAX_TMP_NAME, "msg.%d.read_msg_url", i); snprintf (url, MAX_PATH +1, "%s?crs=%s&id=%s&loc=%ld", "post_read_outbox", course, key, ptr->offset); if(fixed_width_font) strcat(url,"&fixed=1"); cs_set_value(name, url); /* handle subject - need to html escape it */ snprintf(name, MAX_TMP_NAME, "msg.%d.subject", i); if(cgi_html_escape_strfunc(ptr->data.subject, &escaped_subject) == STATUS_OK) cs_set_value(name, escaped_subject); else cs_set_value(name, ptr->data.subject); if(escaped_subject) { free(escaped_subject); escaped_subject = (char *) 0; } strftime (timestring, MAX_TIMESTRING, DOW_DATE_FORMAT, localtime (&ptr->data.time_sent)); snprintf(name, MAX_TMP_NAME, "msg.%d.time_sent", i); cs_set_value(name, timestring); /* insert delete link */ if(can_write) { snprintf(url, MAX_PATH +1, "%s?crs=%s&id=%s&loc=%ld&next=-1&outbox=1", "post_delete", course, key, ptr->offset); snprintf(name, MAX_TMP_NAME, "msg.%d.delete_url", i); cs_set_value(name, url); } snprintf(name, MAX_TMP_NAME, "msg.%d.tolist", i); cs_set_value(name, ptr->data.to); /* print list of recipients */ if (!several_recipients) /* faster for one recipient */ { snprintf(name, MAX_TMP_NAME, "msg.%d.to.0", i); cs_set_value(name, ptr->data.to); } else { recipient_number = 0; str_index = 0; partial_to_list = 0; for (cptr = ptr->data.to; *cptr; cptr++) { if (*cptr == '|') /* we've reached the end of a name */ { if (*(cptr + 1) == '\0') { partial_to_list = 1; } snprintf(name, MAX_TMP_NAME, "msg.%d.to.%d", i, recipient_number); cs_set_value(name, temp); str_index = 0; recipient_number++; } else { temp[str_index] = *cptr; temp[str_index + 1] = '\0'; str_index++; } } if(partial_to_list) { snprintf(name, MAX_TMP_NAME, "msg.%d.partial_to_list", i); cs_set_int_value(name, 1); } else { snprintf(name, MAX_TMP_NAME, "msg.%d.to.%d", i, recipient_number); cs_set_value(name, temp); } } } /* if(!allow_user_hidden ... */ } /* for(i = 0 ... */ } /* if outbox_head */ #undef MAX_TMP_NAME } static void read_outbox_filter (NEWS_FILTER * filter, CONFIG_STRUCT *conf, SESSION *user) { FILE *fp; char filter_path[MAX_PATH + 1]; filter->oldest_first = 1; filter->show_user_hidden = 1; /* always use defaults for capture mode */ if(conf->access == ACCESS_CAPTURE) return; snprintf (filter_path, MAX_PATH + 1, "%s%s/%s/%s/%s", conf->course_path, PEOPLE_DIR, user->username,MAIL_DIR, OUTBOX_FILTER_FNAME); fp = fopen (filter_path, "r"); if (fp) { if(fread (filter, sizeof (NEWS_FILTER), 1, fp) != 1) { filter->oldest_first = 1; filter->show_user_hidden = 1; } fclose (fp); } } static void set_gather_form (const char *course, const char *key, int oldestfirst, CONFIG_STRUCT *conf, const char *fromstring) { P_NODE *p; cs_set_value("gather_action", "post_outbox_gather"); p = build_option_person_list (conf); /* shared_person_list.c */ set_option_userlist (p); /* shared_person_list.c */ free_option_person_list (p); /* shared_person_list.c */ } static void set_sort_url(char *course, char *key, int oldestfirst, const char *fromstring) { char url[MAX_PATH +1]; snprintf (url, MAX_PATH +1, "%s?crs=%s&id=%s&grp=%d&cmd=%d&from=%s", "news_filter_set", course, key, MAIL, oldestfirst? 1: 0, fromstring); cs_set_value("sort_order_url", url); } static void set_sleepy_urls(NEWS_FILTER *filter,const char *fromstring, const char *course, const char *key) { #define LARGE_STRING 512 OUTBOX_NODE *ptr; int hidden_count; char url[LARGE_STRING +1]; /* count topics marked as 'hidden' by the user */ for(ptr=outbox_head, hidden_count=0; ptr; ptr=ptr->next) if(ptr->data.is_sleepy) hidden_count++; cs_set_int_value("hidden_count", hidden_count); if(filter->show_user_hidden) { snprintf (url, LARGE_STRING + 1, "%s?crs=%s&id=%s&grp=%d&cmd=%d&from=%s", "news_filter_set", course, key, MAIL, HIDE_USER_HIDDEN, fromstring); cs_set_value("hide_sleepy_url", url); } else { snprintf (url, LARGE_STRING + 1, "%s?crs=%s&id=%s&grp=%d&cmd=%d&from=%s", "news_filter_set", course, key, MAIL, SHOW_USER_HIDDEN, fromstring); cs_set_value("list_all_url", url); } #undef LARGE_STRING } static void set_outbox_data (char *course, char *key, CONFIG_STRUCT *conf, SESSION *user, int can_write) { NEWS_FILTER filter; char fromstring[MAX_FROM + 1]; int allow_user_hidden; cs_set_value("crs", course); cs_set_value("id", key); cs_set_course_info(conf); cs_set_current_time(); cs_set_int_value("can_write", can_write? 1 : 0 ); cs_set_int_value("capture_mode", (conf->access == ACCESS_CAPTURE)? 1: 0); allow_user_hidden = (conf->postoffice == 2); read_outbox_filter (&filter, conf, user); build_outbox_list (conf, user); snprintf(fromstring, MAX_FROM + 1, "%s%ccrs%c%s%cid%c%s", "post_outbox",QMARK_SUB,EQUAL_SUB,course,AMP_SUB,EQUAL_SUB,key); set_outbox_commands (course, key, can_write, conf->access,fromstring); /* show gather form, reverse order button and show sleepy options ** only if we are not ** capturing this course */ if(conf->access != ACCESS_CAPTURE) { set_gather_form (course, key, filter.oldest_first, conf, fromstring); set_sort_url(course, key, filter.oldest_first, fromstring); if(allow_user_hidden) set_sleepy_urls(&filter, fromstring, course, key); } set_outbox_msgs (course, key, &filter, conf, user, fromstring, can_write, allow_user_hidden); free_outbox_list (); } int main (void) { char course[MAX_PATH + 1]; /* from crs=? command line */ char key[MAX_KEY + 1]; /* from id=? command line */ SESSION user; CONFIG_STRUCT conf; /* the configuration read from config file */ int can_write; /* does this user have write access to this course */ cs_cgi_init(); read_parameters (course, key); read_configuration_file (course, &conf); /* shared_util.c */ validate_key (key, &user, &conf); /* shared_util.c */ can_write = has_write_permission(&user, &conf); /* shared_access.c */ /** see custom.h for next **/ #ifndef SUPPORT_PRE24_POST_OFFICE_MSGS update_post_outbox (&conf, &user); /* shared_post_outbox.c */ #else if(SUPPORT_PRE24_POST_OFFICE_MSGS) update_post_outbox (&conf, &user); /* shared_post_outbox.c */ #endif if(!conf.postoffice) cs_critical_error(ERR_REQUEST_DENIED, ""); set_outbox_data (course, key, &conf, &user, can_write); /* NOTE: post_inbox_outbox.cs is used for both post_inbox.c and post_outbox.c */ cs_cgi_display("post_inbox_outbox", 1); cs_cgi_destroy(); return 0; }