#include #include #include #include #include "global.h" #include "custom.h" #include "manhat-lib/shared_util.h" #include "manhat-lib/shared_cs_util.h" #include "manhat-lib/shared_read_infofile.h" #include "manhat-lib/shared_person_list.h" #include "manhat-lib/shared_news_util.h" #include "manhat-lib/shared_clipboard_util.h" #include "manhat-lib/shared_translate_url.h" #include "manhat-lib/shared_access.h" #include "manhat-lib/shared_spelling_util.h" #include "manhat-lib/shared_lock.h" ATTACHMENT_NODE *pasted_attachment_head = 0; /* linked list of file info, used for pasting */ /** The 'paste' parameter is optional, and is used to flag whether or *** not this program was called because someone (a teacher) clicked on *** the "Paste from clipboard' button. *** *** Two additional optional parameters work together: loc and grp. *** if loc parameter does not exist, **** then this is not a reply. **** Otherwise *** - the loc parameter represents the file offset *** at which the message we are replying to is located *** - the 'grp' parameter is now required. It's a 0/1 *** value, which tells whether or not this is a "Group Reply" **/ static void get_optional_parameters (long *reply_offset, int *group_reply, int *paste) { char value[20]; cs_get_optional_parameter("paste", value, 19); if (!*value) *paste = 0; else *paste = (*value == 'Y' || *value == 'y'); cs_get_optional_parameter("loc", value, 19); if (!*value) /* loc param not found, assume not a reply */ *reply_offset = -1; /* -1 means this is not a reply */ else { *reply_offset = atol (value); cs_get_required_parameter("grp", value, 19); *group_reply = atoi (value); } } static void read_parameters (char *course, char *key, char *from_prog, long *reply_offset, int *group_reply, int *paste) { cs_get_required_parameter ("crs", course, MAX_PATH); cs_get_required_parameter ("id", key, MAX_KEY); cs_get_required_parameter ("from", from_prog, MAX_PATH); get_optional_parameters (reply_offset, group_reply, paste); } static void set_basic_data (char *course, char *key, char *from, long reply_offset, int group_reply, CONFIG_STRUCT *conf, SESSION *user) { char temp[MAX_PATH + 1]; int empty_clipboard; cs_set_value("crs", course); cs_set_value("id", key); cs_set_course_info(conf); /* shared_cs_util.c */ cs_set_current_time(); /* shared_cs_util.c */ /** clipboard_empty() is in shared_clipboard_util.c */ empty_clipboard = (user->group != FACULTY) || clipboard_empty (user->username, conf->course_path, user); cs_set_int_value("content_clipboard", empty_clipboard? 0 : 1); translate_url_substitutes (temp, from, MAX_PATH + 1,1); /* shared_translate_url.c */ cs_set_value("from", from); cs_set_value("back_url", temp); /* If the value of reply_offset is not -1 , then this is a reply */ if(reply_offset == - 1) { cs_set_int_value("is_reply", 0); } else { cs_set_int_value("is_reply", 1); snprintf(temp, MAX_PATH, "%ld", reply_offset); cs_set_value("reply_offset", temp); cs_set_int_value("is_group_reply", group_reply? 1: 0); } cs_set_int_value("msg.textarea.cols", editor_width_config(conf->misc)); /* shared_news_util.c */ cs_set_int_value("msg.textarea.hard_wrap", USE_TEXTAREA_HARD_WRAP); cs_set_int_value("msg.subject.max", MAX_SUBJECT - 1); cs_set_int_value("msg.subject.size", MAX_SUBJECT - 1); } void new_memo_attach (int add_note, CONFIG_STRUCT *conf) { if (add_note) cs_set_int_value("attach.add_note", 1); cs_set_int_value("attach.max_files", conf->mail_attachments); } static void process_inbox (long offset, INBOX_RECORD * inbox, INFO * infofile_info, CONFIG_STRUCT *conf, SESSION *user) { char inbox_path[MAX_PATH + 1]; FILE *fp; snprintf (inbox_path, MAX_PATH + 1, "%s%s/%s/%s/%s", conf->course_path,PEOPLE_DIR, user->username, MAIL_DIR, INBOX_FNAME); fp = fopen (inbox_path, "r+"); if (!fp) cs_critical_error (ERR_FOPEN_APPEND_FAILED, ""); get_exclusive_lock(fileno(fp), 1); /* shared_lock.c */ if (fseek (fp, offset, SEEK_SET)) cs_critical_error (ERR_FSEEK_FAILED, ""); if (fread (inbox, sizeof (INBOX_RECORD), 1, fp) != 1) cs_critical_error (ERR_FREAD_FAILED, ""); release_lock(fileno(fp)); /* shared_lock.c */ fclose (fp); /*** now read the info file- see shared_read_info.c */ read_post_infofile (inbox->newfile_info.sender, inbox->newfile_info.info_fname, infofile_info, conf); } /* creates a textarea field which is one char wider than the longest line ** of the message to allow for insertion of > char */ static void do_reply_textarea (const char *sender_username, const char *msg_fname, CONFIG_STRUCT *conf) { FILE *fp; char fullpath[MAX_PATH + 1]; int longest; struct stat file_stat; char *buf =0, *add_reply_mark =0; snprintf (fullpath, MAX_PATH + 1, "%s/%s/%s/%s/%s", conf->course_path, PEOPLE_DIR,sender_username, MAIL_DIR, msg_fname); if(stat(fullpath, &file_stat)) cs_critical_error (ERR_STAT_FAILED, ""); buf = (char *)malloc((file_stat.st_size +1)*sizeof(char)); if(!buf) cs_critical_error (ERR_MALLOC_FAILED, ""); fp = fopen (fullpath, "r"); if (!fp) cs_critical_error (ERR_FOPEN_READ_FAILED, ""); fread(buf, file_stat.st_size, 1, fp); *(buf + file_stat.st_size ) = '\0'; fclose (fp); longest = find_longest_line(buf, conf); /* shared_news_util.c */ cs_set_int_value("msg.textarea.cols", longest + 1); longest = find_num_lines(buf); /* shared_news_util.c */ if(strlen(buf)) { add_reply_mark = add_mark_to_msg(buf, longest); /* shared_news_util.c */ cs_set_value("msg.textarea.body", add_reply_mark); } if(buf) free(buf); if(add_reply_mark) free(add_reply_mark); } static int get_post_clipboard_info (CLIPBOARD_INFO * clipboard_info, char *clipboard_path, SESSION *user) { char fullpath[MAX_PATH + 1]; ATTACHMENT_NODE *aptr = 0; int i; FILE *fp; snprintf (clipboard_path, MAX_PATH + 1, "%s%s/", CLIPBOARD_PATH, user->id); snprintf (fullpath, MAX_PATH + 1, "%s%s", clipboard_path, CLIPBOARD_INF_FNAME); fp = fopen (fullpath, "r"); if (!fp) return 1; if (fread (clipboard_info, sizeof (CLIPBOARD_INFO), 1, fp) != 1) { fclose (fp); return 1; } /* now read attachment records */ if (clipboard_info->attachments == -1) /* -1 flags a website attached */ clipboard_info->attachments = 1; /* change -1 to 1 for the next 'for' loop */ for (i = 1; i <= clipboard_info->attachments; i++) { if (!pasted_attachment_head) { pasted_attachment_head = (ATTACHMENT_NODE *) malloc (sizeof (ATTACHMENT_NODE)); if (!pasted_attachment_head) cs_critical_error (ERR_MALLOC_FAILED, ""); aptr = pasted_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, ""); aptr->next = 0; } /* for .. */ fclose (fp); return 0; } static void free_pasted_attachment_list () { ATTACHMENT_NODE *aptr; while (pasted_attachment_head) { aptr = pasted_attachment_head; pasted_attachment_head = pasted_attachment_head->next; free (aptr); } } static int do_paste (int *files_attached, SESSION *user, CONFIG_STRUCT *conf) { #define MAX_TMP_NAME 30 CLIPBOARD_INFO clipboard_info; char clipboard_path[MAX_PATH + 1]; char *clip_subject =0; ATTACHMENT_NODE *aptr; int i; char name[MAX_TMP_NAME + 1]; char value[MAX_PATH +1]; *files_attached = 0; /* assume this to start */ if (user->group != FACULTY) cs_critical_error (ERR_REQUEST_DENIED, ""); if (get_post_clipboard_info (&clipboard_info, clipboard_path, user)) return 1; /* clipboard is empty */ cs_set_int_value("do_clipboard", 1); *files_attached = clipboard_info.attachments; /* handle subject */ clip_subject = replace_quot(clipboard_info.subject); /* shared_news_util.c */ cs_set_value("msg.subject.value", clip_subject); free(clip_subject); /* do_paste_textarea() is in shared_news_util.c*/ do_paste_textarea (clipboard_path, clipboard_info.msg_fname, clipboard_info.sender_username, clipboard_info.sender_realname, user, conf); if (pasted_attachment_head) { cs_set_int_value("has_attach", 1); if(clipboard_info.website_attached && is_hotpot_exam_dir(pasted_attachment_head->data.unique_fname)) /* shared_news_util.c */ cs_set_int_value("attach.not_allow", 1); else { if(clipboard_info.website_attached) { cs_set_value("attach.type", "pasted_website"); cs_set_int_value("attach.value", 1); cs_set_int_value("attach.website", 1); } else { cs_set_value("attach.type", "pasted_files"); cs_set_int_value("attach.value", clipboard_info.attachments); } for (i = 1, aptr = pasted_attachment_head; aptr; aptr = aptr->next, i++) { snprintf(name, MAX_TMP_NAME, "attach.file.%d.value", i-1); snprintf(value, MAX_PATH, "%s::%s", aptr->data.orig_fname, aptr->data.unique_fname); cs_set_value(name, value); if(i == 1 && clipboard_info.website_attached) { snprintf(name, MAX_TMP_NAME, "attach.file.%d.type", i-1); cs_set_int_value(name, 1); } else { snprintf(name, MAX_TMP_NAME, "attach.file.%d.orig", i-1); cs_set_value(name, aptr->data.orig_fname); } } } free_pasted_attachment_list (); } return 0; /* paste successful */ #undef MAX_TMP_NAME } static void set_new_memo_form (char *course, char *key, char *from_prog, long reply_offset, int group_reply, int paste, CONFIG_STRUCT *conf, SESSION *user) { INBOX_RECORD inbox; INFO infofile_info; char reply_subject[MAX_SUBJECT + 1]; int paste_failed = 0; int files_attached = 0; char *subject = 0; P_NODE *p; set_basic_data (course, key, from_prog, reply_offset, group_reply, conf, user); insert_spell_check_button(conf); /* shared_spelling_util.c */ cs_set_int_value("emoticons_disabled", EMOTICONS_DISABLED(conf->misc)? 1 : 0); p = build_option_person_list (conf); /* shared_person_list.c */ if(!ALLOW_POST_OFFICE_MSGS_TO_SELF) /* see custom.h */ p = option_list_remove_user( p, user->username); /* shared_person_list.c */ set_option_userlist(p); /* shared_person_list.c */ if (paste) paste_failed = do_paste (&files_attached, user, conf); if (!paste || paste_failed) { if ((reply_offset == -1) || paste_failed) { /* i.e. if this is not a reply */ /* do nothing */ } else { /* this is a reply or a group reply */ process_inbox (reply_offset, &inbox, &infofile_info, conf, user); /* need to know who to send it to */ if (!group_reply) { /* To: gets sender's name preselected */ set_post_recipient(TO, inbox.newfile_info.sender,inbox.newfile_info.sender_realname); /* shared_person_list.c */ } else { set_post_group_reply_recipients(inbox.newfile_info.sender, inbox.newfile_info.sender_realname, user->username, person_head); } /* handle subject */ cs_set_int_value("msg.subject.add_re", 1); strncpy (reply_subject, inbox.newfile_info.subject, MAX_SUBJECT+1); /* set subject but must replace quotes " with " */ subject = replace_quot(reply_subject); /* shared_news_util.c */ cs_set_value("msg.subject.value", subject); if(subject) free(subject); /* handle textarea */ do_reply_textarea (inbox.newfile_info.sender, infofile_info.msg_fname, conf); cs_set_value("msg.textarea.author", inbox.newfile_info.sender_realname); } /* else: if reply */ } /* if(!paste || paste_failed) */ free_option_person_list (p); /* shared_person_list.c */ new_memo_attach (files_attached, conf); } int main (void) { char course[MAX_PATH + 1]; /* from crs=? command line */ char key[MAX_KEY + 1]; /* from id=? command line */ char from_prog[MAX_PATH + 1]; /* from from=? cmd line */ long reply_offset; /* from loc=? optional cmd line */ int group_reply = 0; /* from grp=? optional cmd line */ int paste; /* from paste=? optional cmd line */ SESSION user; CONFIG_STRUCT conf; /* the configuration read from config file */ cs_cgi_init(); read_parameters (course, key, from_prog, &reply_offset, &group_reply, &paste); read_configuration_file (course, &conf); /* shared_util.c */ validate_key (key, &user, &conf); /* shared_util.c */ if(!has_write_permission(&user, &conf)) /* shared_access.c */ access_denied_error(); set_new_memo_form (course, key, from_prog, reply_offset, group_reply, paste, &conf, &user); cs_cgi_display("post_new_memo", 1); cs_cgi_destroy(); return 0; }