#include #include #include #include #include #include /* for opendir() */ #include #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_news_util.h" #include "manhat-lib/shared_translate_url.h" #include "manhat-lib/shared_access.h" #include "manhat-lib/shared_lock.h" #include "manhat-lib/shared_msg_line.h" #include "manhat-lib/shared_bio.h" #include "manhat-lib/shared_post_outbox.h" PERSON_NODE *person_head = 0; ATTACHMENT_NODE *attachment_head = 0; static void free_attachment_list (void) { ATTACHMENT_NODE *ptr; while (attachment_head) { ptr = attachment_head; attachment_head = attachment_head->next; free (ptr); } } static void free_person_list (void) { PERSON_NODE *ptr; while (person_head) { ptr = person_head; person_head = person_head->next; free (ptr); } } static void read_parameters (char *course, char *key, long *offset, int *del_link, int *printer_friendly, int *fixed_font) { char off_set[MAX_FILENAME + 1]; cs_get_required_parameter ("crs", course, MAX_PATH); cs_get_required_parameter ("id", key, MAX_KEY); /* just check if the "del_link" parameter is there */ cs_get_optional_parameter ("del_link", off_set, 5); *del_link = strlen(off_set); cs_get_required_parameter ("loc", off_set, 10); *offset = atol (off_set); /* provide printer-friendly version? */ cs_get_optional_parameter ("print", off_set, 5); /* shared_cs_util.c */ *printer_friendly = *off_set? 1: 0; /* provide preformatted text (instead of proportional) ? */ cs_get_optional_parameter ("fixed", off_set, 5); /* shared_cs_util.c */ *fixed_font = *off_set? 1: 0; } static void get_next_offset (const char *outbox_path, long offset, long *next_offset, int *found, int show_user_hidden) { FILE *fp; OUTBOX_RECORD data; fp = fopen (outbox_path, "r"); if (!fp) cs_critical_error (ERR_FOPEN_READ_FAILED, outbox_path); get_shared_lock(fileno(fp), 1); /* shared_lock.c */ fseek (fp, offset, SEEK_SET); fread (&data, sizeof (OUTBOX_RECORD), 1, fp); /* read THIS record */ *found = 0; while (!*found && fread (&data, sizeof (OUTBOX_RECORD), 1, fp) == 1) if(data.how_sent != DELETED) *found = show_user_hidden || !data.is_sleepy; if (*found) *next_offset = ftell (fp) - sizeof (OUTBOX_RECORD); release_lock(fileno(fp)); /* shared_lock.c */ fclose (fp); } static void get_previous_offset (const char *outbox_path, long offset, long *prev_offset, int *found, int show_user_hidden) { FILE *fp; OUTBOX_RECORD data; fp = fopen (outbox_path, "r"); if (!fp) cs_critical_error (ERR_FOPEN_READ_FAILED, outbox_path); get_shared_lock(fileno(fp), 1); /* shared_lock.c */ *prev_offset = offset; *found = 0; do { *prev_offset = (*prev_offset - sizeof (OUTBOX_RECORD)); if (*prev_offset < 0) { *found = 0; release_lock(fileno(fp)); /* shared_lock.c */ fclose (fp); return; } fseek (fp, *prev_offset, SEEK_SET); fread (&data, sizeof (OUTBOX_RECORD), 1, fp); if(data.how_sent != DELETED) *found = show_user_hidden || !data.is_sleepy; if (*found) { release_lock(fileno(fp)); /* shared_lock.c */ fclose (fp); } } while (!*found); } static void set_command_button_urls (char *course, char *key, long offset, NEWS_FILTER * filter, CONFIG_STRUCT *conf, SESSION *user, int can_write ) { char outbox_path[MAX_PATH + 1]; long next_offset, prev_offset; int found; char url[MAX_PATH + 1]; char fromstring[MAX_FROM + 1]; snprintf (outbox_path, MAX_PATH + 1, "%s%s/%s/%s/%s", conf->course_path, PEOPLE_DIR,user->username, MAIL_DIR, OUTBOX_FNAME); snprintf (url, MAX_PATH , "%s?crs=%s&id=%s","post_outbox", course, key); cs_set_value("post_outbox_url", url); cs_set_value("back_url", url); /* goto inbox button */ snprintf (url, MAX_PATH , "%s?crs=%s&id=%s", "post_inbox", course, key); cs_set_value("post_inbox_url", url); /* main menu button */ snprintf (url, MAX_PATH, "%s?crs=%s&id=%s", "main_menu", course, key); cs_set_value("main_menu_url", url); /*the from parameter is the complete command line of this program. ** substitutions are defined in global.h * */ snprintf (fromstring, MAX_FROM + 1, "%s%ccrs%c%s%cid%c%s%cloc%c%ld", "post_read_outbox", QMARK_SUB, EQUAL_SUB, course, AMP_SUB, EQUAL_SUB, key, AMP_SUB, EQUAL_SUB, offset); /* new memo button , only if can_write */ if(can_write) { snprintf (url, MAX_PATH, "%s?crs=%s&id=%s&from=%s", "post_new_memo", course, key, fromstring); cs_set_value("new_memo_url", url); } /* forward mail button, only if can_write */ if(can_write) { snprintf (url, MAX_PATH, "%s?crs=%s&id=%s&loc=%ld&src=0&from=%s", "post_forward_mail", course, key, offset, fromstring); cs_set_value("forward_url", url); } if (filter->oldest_first) get_next_offset (outbox_path, offset, &next_offset, &found, filter->show_user_hidden); else get_previous_offset (outbox_path, offset, &next_offset, &found, filter->show_user_hidden); if(can_write) { snprintf (url, MAX_PATH, "%s?crs=%s&id=%s&loc=%ld&next=%ld&outbox=1", "post_delete", course, key, offset, found ? next_offset : -1); cs_set_value("delete_url", url); } /* read next button */ if (found) { snprintf (url, MAX_PATH, "%s?crs=%s&id=%s&loc=%ld", "post_read_outbox", course, key, next_offset); cs_set_value("next_msg_url", url); } if (filter->oldest_first) get_previous_offset (outbox_path, offset, &prev_offset, &found, filter->show_user_hidden); else get_next_offset (outbox_path, offset, &prev_offset, &found, filter->show_user_hidden); /* read previous button */ if (found) { snprintf (url, MAX_PATH, "%s?crs=%s&id=%s&loc=%ld", "post_read_outbox", course, key, prev_offset); cs_set_value("prev_msg_url", url); } /* info button */ snprintf (url, MAX_PATH, "%s?crs=%s&id=%s&loc=%ld&from=%s", "post_outbox_info", course, key, offset, fromstring); cs_set_value("info_url", url); } /* reads the outbox file and then the corresponding *.inf file, to get everything ** ready to be displayed **/ static void process_outbox_record (long offset, OUTBOX_RECORD * outbox, INFO * infofile_info, int *website_attached, CONFIG_STRUCT *conf, SESSION *user ) { char outbox_path[MAX_PATH + 1]; FILE *fp; char infopath[MAX_PATH + 1]; ATTACHMENT_NODE *aptr = 0; PERSON_NODE *pptr = 0; int i; PERSON person_buffer; 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) cs_critical_error (ERR_FOPEN_READ_FAILED, outbox_path); get_shared_lock(fileno(fp), 1); /* shared_lock.c */ if (fseek (fp, offset, SEEK_SET)) cs_critical_error (ERR_FSEEK_FAILED, outbox_path); if (fread (outbox, sizeof (OUTBOX_RECORD), 1, fp) != 1) cs_critical_error (ERR_FREAD_FAILED, outbox_path); release_lock(fileno(fp)); /* shared_lock.c */ fclose (fp); snprintf (infopath, MAX_PATH + 1, "%s%s/%s/%s/%s", conf->course_path, PEOPLE_DIR, user->username, MAIL_DIR, outbox->info_fname); fp = fopen (infopath, "r"); if (!fp) cs_critical_error (ERR_FOPEN_READ_FAILED, infopath); get_shared_lock(fileno(fp), 1); /* shared_lock.h */ if (fread (infofile_info, sizeof (INFO), 1, fp) != 1) cs_critical_error (ERR_FREAD_FAILED, infopath); /* process attachments */ *website_attached = (infofile_info->no_attachments == -1); if (*website_attached) infofile_info->no_attachments = 1; /* since we have to pick up the dirname in next loop */ for (i = 1; i <= infofile_info->no_attachments; i++) { if (!attachment_head) { attachment_head = (ATTACHMENT_NODE *) malloc (sizeof (ATTACHMENT_NODE)); if (!attachment_head) cs_critical_error (ERR_MALLOC_FAILED, ""); aptr = attachment_head; } else { aptr->next = (ATTACHMENT_NODE *) malloc (sizeof (ATTACHMENT_NODE)); if (!aptr->next) cs_critical_error (ERR_MALLOC_FAILED, ""); aptr = aptr->next; } if (fread (&aptr->data, sizeof (ATTACHMENT), 1, fp) != 1) cs_critical_error (ERR_FREAD_FAILED, infopath); aptr->next = 0; } /* process list of people msg was sent to */ while (fread (&person_buffer, sizeof (PERSON), 1, fp) == 1) { if (!person_head) { person_head = (PERSON_NODE *) malloc (sizeof (PERSON_NODE)); if (!person_head) cs_critical_error (ERR_MALLOC_FAILED, ""); pptr = person_head; } else { pptr->next = (PERSON_NODE *) malloc (sizeof (PERSON_NODE)); if (!pptr->next) cs_critical_error (ERR_MALLOC_FAILED, ""); pptr = pptr->next; } pptr->data = person_buffer; pptr->next = 0; } release_lock(fileno(fp)); /* shared_lock.c */ fclose (fp); } static void read_filter (NEWS_FILTER * filter, CONFIG_STRUCT *conf, SESSION *user) { FILE *fp; char filter_path[MAX_PATH + 1]; 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) { fread (filter, sizeof (NEWS_FILTER), 1, fp); fclose (fp); } else { filter->oldest_first = 1; filter->show_user_hidden = 1; } } static void set_outbox_msg_data (char *course, char *key, long offset, CONFIG_STRUCT *conf, SESSION *user, int can_write ) { OUTBOX_RECORD outbox; INFO infofile_info; NEWS_FILTER filter; int website_attached; char url[MAX_PATH + 1]; char msg_path[MAX_PATH + 1]; read_filter (&filter, conf, user); process_outbox_record (offset, &outbox, &infofile_info, &website_attached, conf, user); cs_set_course_info(conf); cs_set_value("crs", course); cs_set_value("key", key); set_command_button_urls (course, key, offset, &filter, conf, user, can_write); /* shared_post_outbox.c */ set_outbox_msg_header_data(&outbox, course, key, website_attached, offset, conf, user, attachment_head, person_head, -1); snprintf (msg_path, MAX_PATH + 1, "%s%s/%s/%s/%s", conf->course_path, PEOPLE_DIR, user->username, MAIL_DIR, infofile_info.msg_fname); set_msg_body_data (msg_path, "", ""); /* shared_msg_line.c */ if(user->group == FACULTY) { cs_set_value("is_faculty", "1"); if (conf->access != ACCESS_CAPTURE) { snprintf (url, MAX_PATH * 2, "%s?crs=%s&id=%s&loc=%ld&grp=%d&inbox=no", "clipboard_copy", course, key, offset, MAIL); cs_set_value("clipboard_url", url); } } cs_set_int_value("can_write", can_write? 1 : 0); if(conf->access == ACCESS_CAPTURE) cs_set_value("capture_mode", "1"); } int main (void) { char course[MAX_PATH + 1]; /* from crs=? command line */ char key[MAX_KEY + 1]; /* from id=? command line */ long offset; /* from loc=? command line */ int del_link; /* from del_link=?command line ** do we need to rm a symbolic link ** to an attached web page? */ int printer_friendly; /* from print=? command line provide "printer friendly" version? */ int fixed_font; /* from fixed=? command line print body as fixed font? */ SESSION user; CONFIG_STRUCT conf; /* the configuration read from config file */ int can_write; /* can this user change this course? */ cs_cgi_init(); read_parameters (course, key, &offset, &del_link, &printer_friendly, &fixed_font); 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 */ cs_set_int_value("printer_friendly", printer_friendly); cs_set_int_value("fixed_font", fixed_font); set_outbox_msg_data (course, key, offset, &conf, &user, can_write); free_person_list (); /* #included */ if (del_link) remove_stale_symlinks (user.username, course, conf.access); /* shared_news_util.c */ free_attachment_list (); /* #included */ cs_set_int_value("is_inbox", 0); /* NOTE: the post_read.cs ClearSilver template is used to process both ** post_read_inbox.c and post_read_outbox.c */ cs_cgi_display("post_read", 1); cs_cgi_destroy(); return 0; }