#include #include #include /* for tolower() */ #include /* for mkdir() */ #include /* for stat() */ #include #include /* for exec(), wait() et. al */ #include #include #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_clipboard_util.h" #include "manhat-lib/shared_copy_file.h" #include "manhat-lib/shared_translate_url.h" #include "manhat-lib/shared_file_util.h" #include "manhat-lib/shared_access.h" #include "manhat-lib/shared_post_inbox.h" #include "manhat-lib/shared_lock.h" #include "manhat-lib/shared_fold_file.h" typedef struct html_file_node { char fname[MAX_FILENAME + 1]; struct html_file_node *next; } HTML_FILE_NODE; HTML_FILE_NODE *html_file_head; SESSION user; CONFIG_STRUCT conf; /* the configuration read from config file */ RECEIVER_NODE *to_head = 0; /* next two apply to POST OFFICE messages */ RECEIVER_NODE *cc_head = 0; /* who was carbon copied? */ RECEIVER_NODE *bcc_head = 0; /* who was blind carbon copied? */ FILE_NODE *file_head = (FILE_NODE *) 0; /*list of attached files */ int attachments = 0; /* how many files are attached? - **same as number of nodes pointed to ** by file_head */ FILE_NODE *pasted_file_head = (FILE_NODE *) 0; /* list of 'pasted' files */ int pasted_attachments = 0; /* how many pasted files are attached? - **same as number of nodes pointed to ** by pasted_file_head */ int attachments_written = 0; /* set to 1 when uploaded files are written to disk */ /* deletes all files in list headed by file_head ** called to clean up sender directory when a ** critical error occurs after the files were written */ void delete_attachment_files () { FILE_NODE *ptr; char fname[MAX_PATH + 1]; for (ptr = file_head; ptr; ptr = ptr->next) { snprintf (fname, MAX_PATH + 1, "%s/%s", discussion_path, ptr->unique_fname); unlink (fname); } } void big_error (const char* error_no, char *msg) { if (attachments_written) delete_attachment_files (); cs_critical_error (error_no, msg); } static void read_parameters (char *course, char *key, char *fromprog, int *website, int *pasted_website, int *pasted_files, int *width) { char string[80]; cs_get_required_parameter ("crs", course, MAX_PATH); cs_get_required_parameter ("id", key, MAX_KEY); cs_get_required_parameter ("from", fromprog, MAX_PATH); cs_get_required_parameter ("width", string, 10); *width = atoi(string); cs_get_optional_parameter("website", string, 79); if(strlen(string)) *website = 1; else *website = 0; cs_get_optional_parameter("pasted_website", string, 79); if(strlen(string)) *pasted_website = atoi(string); else *pasted_website = 0; cs_get_optional_parameter("pasted_files", string, 79); if(strlen(string)) *pasted_files = atoi(string); else *pasted_files = 0; } int is_blank (char *string) { char *ptr; for (ptr = string; *ptr; ptr++) if (!isspace (*ptr)) return 0; return 1; } /* make sure no empty files have been uploaded and that there is an entry in ** the first file field, that is 'file1' must not be empty. **/ static void check_website_individual_files () { #define MAX_TMP_NAME 30 int homefile = 0; int i; char name[MAX_TMP_NAME]; char filename[MAX_PATH +1]; FILE *fp; struct stat buf; for(i =1; i<= conf.mail_attachments; i++) { snprintf(name, MAX_TMP_NAME, "file%d", i); cs_get_optional_parameter(name, filename, MAX_PATH); if (strlen(filename)) { fp = cgi_filehandle(global_cgi, name); if(fstat(fileno(fp), &buf)) cs_critical_error (ERR_FOPEN_READ_FAILED, filename); if (buf.st_size == 0) big_error(ERR_EMPTY_FILE, filename); else if (!strcmp (name, "file1")) homefile = 1; } } if (!homefile) big_error (ERR_FIRST_ATTACHMENT_FIELD_BLANK, ""); #undef MAX_TMP_NAME } static void strtolower (char *string) { char *ptr; for (ptr = string; *ptr; ptr++) *ptr = tolower (*ptr); } void check_more_than_one_files(CONFIG_STRUCT *conf) { int i; char fname[MAX_PATH +1]; char value[MAX_PATH +1]; int count =0; for(i =0; imail_attachments; i++) { snprintf(fname, MAX_PATH +1, "file%d", i); cs_get_optional_parameter(fname, value, MAX_PATH); if(strlen(value)) count++; } if(count > 1) cs_critical_error(ERR_ATTACH_ZIP_ONLY_ONE_FILE, ""); } static void check_website_upload_type (int *iszip) { #define MAX_MSG 300 char fname[MAX_PATH + 1]; char orig_fname[MAX_PATH + 1]; char ext[MAX_FILENAME + 1]; cs_get_required_parameter("file1", fname, MAX_PATH); strncpy (orig_fname, fname, MAX_FILENAME + 1); strtolower (fname); get_extension (fname, ext); /* shared_news_util.c */ if (!strcmp (ext, "zip")) { *iszip = 1; check_more_than_one_files(&conf); } else { /* check to see if file ends in .htm or .html */ *iszip = 0; if (strcmp (ext, "htm") && strcmp (ext, "html")) { big_error (ERR_FIRST_FIELD_NOT_ZIP_OR_HTML, orig_fname); } } #undef MAX_MSG } /* this simply ensures that the zipfile is not empty ** additional integrity checks are done later **/ static void check_zipfile () { char str[MAX_PATH +1]; FILE *fp; struct stat buf; cs_get_required_parameter("file1", str, MAX_PATH); fp = cgi_filehandle(global_cgi, "file1"); fstat(fileno(fp), &buf); if(buf.st_size ==0) big_error (ERR_EMPTY_FILE, str); } static void check_website_data (int *iszip) { char *subject =0; subject = hdf_get_value(global_cgi->hdf, "Query.subject", 0); if(!subject || !strlen(subject)) cs_critical_error(ERR_PARAM_MISSING, "subject"); check_website_upload_type (iszip); /* did user upload a zip file or multiple files */ if (*iszip) check_zipfile (); else check_website_individual_files (); } static void add_to_file_list (FILE_NODE ** head, const char *unique_fname, const char *orig_fname) { FILE_NODE *ptr; if (!*head) { *head = (FILE_NODE *) malloc (sizeof (FILE_NODE)); if (!*head) { big_error (ERR_MALLOC_FAILED, ""); } ptr = *head; } else { for (ptr = *head; ptr->next; ptr = ptr->next); ptr->next = (FILE_NODE *) malloc (sizeof (FILE_NODE)); if (!ptr->next) { big_error (ERR_MALLOC_FAILED, ""); } ptr = ptr->next; } strncpy (ptr->unique_fname, unique_fname, MAX_FILENAME + 1); strncpy (ptr->orig_fname, orig_fname, MAX_FILENAME + 1); ptr->next = (FILE_NODE *) 0; } static void parse_raw_filename (char *raw_fname, char *orig_fname, char *unique_fname) { char *ptr; ptr = strstr (raw_fname, "::"); if (!ptr) big_error (ERR_PARAM_FORMAT, raw_fname); *ptr = '\0'; strncpy (orig_fname, raw_fname, MAX_FILENAME + 1); ptr += 2; /* skip past "::" */ strncpy (unique_fname, ptr, MAX_FILENAME + 1); } static void build_pasted_attachment_list (int pasted_website, int pasted_files) { int i; char parameter[10]; /* letter 'f' followed by a small integer, eg 'f1' f2' */ char raw_filename[2 * (MAX_FILENAME + 1)]; /* consists of "orig_fname::unique_fname" */ char orig_fname[MAX_FILENAME + 1]; char unique_fname[MAX_FILENAME + 1]; for (i = 1; i <= pasted_files + pasted_website; i++) { snprintf (parameter, 10, "f%d", i); cs_get_optional_parameter(parameter, raw_filename, 2*MAX_FILENAME); if(strlen(raw_filename)) { parse_raw_filename (raw_filename, orig_fname, unique_fname); add_to_file_list (&pasted_file_head, unique_fname, orig_fname); pasted_attachments++; } } } static void get_unique_fname (char *unique_fname, const char *ext, time_t * time_sent) { static int n = 0; char timestring[MAX_TIMESTRING + 1]; char filepath[MAX_PATH + 1]; strftime (timestring, MAX_TIMESTRING, "%m%d%Y%H%M%S", localtime (time_sent)); do { n++; snprintf (unique_fname, MAX_FILENAME + 1, "%s%d%d.%s", timestring, n, getpid(), ext); snprintf (filepath, MAX_PATH + 1, "%s%s", discussion_path, unique_fname); } while (file_exists(filepath)); /* shared_file_util.c */ } static void get_system_filenames (const char *full_orig_name, char *unique_fname, char *orig_fname, time_t * time_sent) { get_unique_fname (unique_fname, "fil", time_sent); get_orig_fname (full_orig_name, orig_fname); } static void build_normal_file_list (time_t * time_sent) { #define MAX_TMP_NAME 30 char unique_fname[MAX_PATH + 1]; char orig_fname[MAX_PATH + 1]; char name[MAX_TMP_NAME]; char filename[MAX_PATH +1]; int i; FILE *fp; struct stat buf; for(i =1; i <= conf.mail_attachments; i++) { snprintf(name, MAX_TMP_NAME, "file%d", i); cs_get_optional_parameter(name, filename, MAX_PATH ); if (strlen(filename)) { fp = cgi_filehandle(global_cgi, name); if(fstat(fileno(fp), &buf)) big_error(ERR_STAT_FAILED, filename); if(buf.st_size == 0) big_error(ERR_EMPTY_FILE, filename); get_system_filenames (filename, unique_fname, orig_fname, time_sent); add_to_file_list (&file_head, unique_fname, orig_fname); write_cgi_file (fp, buf.st_size, unique_fname); attachments_written = 1; /* set global flag for possible use in big_error() */ attachments++; } } #undef MAX_TMP_NAME } static void check_form_data (int *is_web_zipfile, int website, int pasted_website, int pasted_files, time_t * time_sent) { char *to =0; to = hdf_get_value(global_cgi->hdf, "Query.to", 0); if(!to || !strlen(to)) cs_critical_error(ERR_PARAM_MISSING, "to"); /* the following test should always fail, unless someone ** is mucking around with the form */ if (pasted_website && pasted_files) big_error (ERR_INTERNAL_ERROR, "check_form_data() found both pasted_website and pasted_files"); build_pasted_attachment_list (pasted_website, pasted_files); if (website) { check_incomplete_upload(); /*shared_news_util.c */ check_website_data (is_web_zipfile); /* make sure message is not empty + do preliminary checks on web files */ /* still here? make sure nothing but the new web site is attached */ if (pasted_attachments) big_error (ERR_CANT_ATTACH_NEW_WEB_SITE, ""); } else { *is_web_zipfile = 0; build_normal_file_list (time_sent); // verify_non_empty (); /* make sure message is not empty */ if(attachments) check_incomplete_upload(); /* shared_news_util.c */ if (pasted_website && pasted_attachments && attachments) big_error (ERR_CANT_MAKE_ADDITIONAL_ATTACHMENTS, ""); } } /****** POST OFFICE specific routines ********/ static int in_to_list (char *username) { RECEIVER_NODE *ptr; for (ptr = to_head; ptr; ptr = ptr->next) if (!strcmp (ptr->username, username)) return 1; return 0; } static int in_cc_list (char *username) { RECEIVER_NODE *ptr; for (ptr = cc_head; ptr; ptr = ptr->next) if (!strcmp (ptr->username, username)) return 1; return 0; } /** SCRAP THIS??? not used ***/ void clean_bcc_list () { RECEIVER_NODE *ptr, *ptr2; ptr = bcc_head; while (ptr) if (in_to_list (ptr->username) || in_cc_list (ptr->username)) { if (ptr == bcc_head) { ptr2 = ptr; bcc_head = bcc_head->next; free (ptr2); ptr = bcc_head; } else { for (ptr2 = bcc_head; ptr2->next != ptr; ptr2 = ptr2->next); ptr2->next = ptr->next; free (ptr); ptr = ptr2->next; } } else ptr = ptr->next; } static void clean_cc_list () { RECEIVER_NODE *ptr, *ptr2; ptr = cc_head; while (ptr) if (in_to_list (ptr->username)) { if (ptr == cc_head) { ptr2 = ptr; cc_head = cc_head->next; free (ptr2); ptr = cc_head; } else { for (ptr2 = cc_head; ptr2->next != ptr; ptr2 = ptr2->next); ptr2->next = ptr->next; free (ptr); ptr = ptr2->next; } } else ptr = ptr->next; } static void build_mail_receiver_list () { create_rec_list ("to", &to_head); /* shared multipart.c */ if(!to_head) big_error(ERR_PARAM_MISSING, "to"); create_rec_list ("cc", &cc_head); clean_cc_list (); } /***** end POST OFFICE routines *****/ static void free_receiver_lists () { RECEIVER_NODE *ptr; while (to_head) { ptr = to_head; to_head = to_head->next; free (ptr); } while (cc_head) { ptr = cc_head; cc_head = cc_head->next; free (ptr); } while (bcc_head) { ptr = bcc_head; bcc_head = bcc_head->next; free (ptr); } } static void free_file_list (FILE_NODE ** head) { FILE_NODE *ptr; while (*head) { ptr = *head; *head = (*head)->next; free (ptr); } } static void free_html_filelist (void) { HTML_FILE_NODE *ptr; while (html_file_head) { ptr = html_file_head; html_file_head = html_file_head->next; free (ptr); } } static void process_message_file (char *msg_fname, time_t * time_sent, int width) { char *msg =0; FILE *fp; char filepath[MAX_PATH +1]; int len; msg = hdf_get_value(global_cgi->hdf, "Query.msg", 0); get_unique_fname (msg_fname, "msg", time_sent); snprintf(filepath, MAX_PATH +1, "%s%s", discussion_path, msg_fname); fp = fopen(filepath, "w"); if(!fp) big_error(ERR_FOPEN_WRITE_FAILED, msg_fname); if(msg && strlen(msg)) { len = strlen(msg); if(len < width || USE_TEXTAREA_HARD_WRAP) { if(fwrite (msg, strlen(msg), 1, fp) != 1) big_error (ERR_FWRITE_FAILED, filepath); } else write_folded(fp, msg, width); } fclose(fp); } static void process_pasted_attached_files (int pasted_files, int pasted_website, time_t * time_sent) { FILE_NODE *fptr; char clipboard_path[MAX_PATH + 1]; char unique_fname[MAX_FILENAME + 1]; char sourcepath[MAX_PATH + 1]; char destpath[MAX_PATH + 1]; if ((pasted_files || pasted_website) && pasted_file_head) { snprintf (clipboard_path, MAX_PATH + 1, "%s%s/", CLIPBOARD_PATH, user.id); if (pasted_website) { get_unique_fname (unique_fname, "dir", time_sent); copy_dir (clipboard_path, /* shared_copy_file.c */ discussion_path, pasted_file_head->unique_fname, unique_fname); strncpy (pasted_file_head->unique_fname, unique_fname, MAX_FILENAME + 1); } else { for (fptr = pasted_file_head; fptr; fptr = fptr->next) { get_unique_fname (unique_fname, "fil", time_sent); snprintf (sourcepath, MAX_PATH + 1, "%s%s", clipboard_path, fptr->unique_fname); snprintf (destpath, MAX_PATH + 1, "%s%s", discussion_path, unique_fname); copy_file (sourcepath, destpath); /* shared_copy_file.c */ strncpy (fptr->unique_fname, unique_fname, MAX_FILENAME + 1); } } } } static void write_info_file (char *msg_fname, char *info_fname, char *subject, time_t time_sent, int website, int pasted_website) { FILE *fp; INFO info; ATTACHMENT attach; PERSON mail_person; FILE_NODE *fptr; RECEIVER_NODE *rptr; char info_path[MAX_PATH + 1]; cs_get_required_parameter("subject", subject, MAX_SUBJECT); get_unique_fname (info_fname, "inf", &time_sent); strncpy (info.msg_fname, msg_fname, MAX_FILENAME + 1); strncpy (info.subject, subject, MAX_SUBJECT + 1); info.version = VERSION24; /* flags this as a message sent with the 'new' post office module ** introduced with version 24 */ info.time_sent = time_sent; /* websites are marked with a -1 flag in no_attachments */ info.no_attachments = website || (pasted_website && pasted_attachments) ? -1 : attachments + pasted_attachments; snprintf (info_path, MAX_PATH + 1, "%s/%s", discussion_path, info_fname); fp = fopen (info_path, "w"); if (!fp) big_error (ERR_FOPEN_WRITE_FAILED, info_path); if (fwrite (&info, sizeof (INFO), 1, fp) != 1) big_error (ERR_FWRITE_FAILED, info_path); for (fptr = file_head; fptr; fptr = fptr->next) { strncpy (attach.unique_fname, fptr->unique_fname, MAX_FILENAME + 1); strncpy (attach.orig_fname, fptr->orig_fname, MAX_FILENAME + 1); if (fwrite (&attach, sizeof (ATTACHMENT), 1, fp) != 1) big_error (ERR_FWRITE_FAILED, info_path); } for (fptr = pasted_file_head; fptr; fptr = fptr->next) { strncpy (attach.unique_fname, fptr->unique_fname, MAX_FILENAME + 1); strncpy (attach.orig_fname, fptr->orig_fname, MAX_FILENAME + 1); if (fwrite (&attach, sizeof (ATTACHMENT), 1, fp) != 1) big_error (ERR_FWRITE_FAILED, info_path); } for (rptr = to_head; rptr; rptr = rptr->next) { strncpy (mail_person.username, rptr->username, MAX_USERNAME + 1); strncpy (mail_person.realname, rptr->realname, MAX_NAME + 1); mail_person.how_received = TO; mail_person.time_read = 0; mail_person.time_deleted = 0; if (fwrite (&mail_person, sizeof (PERSON), 1, fp) != 1) big_error (ERR_FWRITE_FAILED, info_path); } for (rptr = cc_head; rptr; rptr = rptr->next) { strncpy (mail_person.username, rptr->username, MAX_USERNAME + 1); strncpy (mail_person.realname, rptr->realname, MAX_NAME + 1); mail_person.how_received = CC; mail_person.time_read = 0; mail_person.time_deleted = 0; if (fwrite (&mail_person, sizeof (PERSON), 1, fp) != 1) big_error (ERR_FWRITE_FAILED, info_path); } for (rptr = bcc_head; rptr; rptr = rptr->next) { strncpy (mail_person.username, rptr->username, MAX_USERNAME + 1); strncpy (mail_person.realname, rptr->realname, MAX_NAME + 1); mail_person.how_received = BCC; mail_person.time_read = 0; mail_person.time_deleted = 0; if (fwrite (&mail_person, sizeof (PERSON), 1, fp) != 1) big_error (ERR_FWRITE_FAILED, info_path); } fclose (fp); } static void update_inboxes (NEWFILE_RECORD * newinfo, RECEIVE_TYPE t) { RECEIVER_NODE *rptr; char inbox_path[MAX_PATH + 1]; rptr = (t == TO ? to_head : t == CC ? cc_head : bcc_head); newinfo->how_received = t; for (; rptr; rptr = rptr->next) { snprintf (inbox_path, MAX_PATH + 1, "%s%s/%s/%s/%s", conf.course_path,PEOPLE_DIR, rptr->username, MAIL_DIR, INBOX_FNAME); add_new_post_msg(newinfo, inbox_path); /* shared_post_inbox.c */ } } void update_all_inboxes (char *inf_fname, char *subject, time_t time_sent, int website, int pasted_website) { NEWFILE_RECORD newinfo; strncpy (newinfo.sender, user.username, MAX_USERNAME + 1); strncpy (newinfo.sender_realname, user.realname, MAX_NAME + 1); newinfo.how_sent = NEWMSG; strncpy (newinfo.subject, subject, MAX_SUBJECT + 1); newinfo.time_sent = time_sent; newinfo.attachments = website || (pasted_website && pasted_attachments) ? 1 : attachments + pasted_attachments; strncpy (newinfo.info_fname, inf_fname, MAX_FILENAME + 1); update_inboxes (&newinfo, TO); update_inboxes (&newinfo, CC); update_inboxes (&newinfo, BCC); } static void back_up (char *program) { char temp[MAX_PATH + 1]; translate_url_substitutes (temp, program, MAX_PATH + 1, 0); /* shared_translate_url.c */ printf ("Location: %s\n\n", temp); } void clean_zip_temp_dir () { char dirname[MAX_PATH + 1]; snprintf (dirname, MAX_PATH + 1, "%s/%s", discussion_path, ZIP_TMP_DIRNAME); kill_directory(dirname); /* shared_file_util.c */ } void create_tmp_zip_dir () { char dirname[MAX_PATH + 1]; snprintf (dirname, MAX_PATH + 1, "%s/%s", discussion_path, ZIP_TMP_DIRNAME); if (mkdir (dirname, 0777)) big_error (ERR_MKDIR_FAILED, dirname); } void delete_zip_tmp_file () { char fname[MAX_PATH + 1]; snprintf (fname, MAX_PATH + 1, "%s/%s", discussion_path, ZIP_TMP_FNAME); unlink (fname); } static void check_unzip_status (int error) { delete_zip_tmp_file (); switch (error) { /* this is my error code if exec() failed */ case 88: big_error (ERR_CANT_START_UNZIP, "code_88"); break; /* remaining errors reported by unzip */ case 0: return; /* everything went OK */ case 1: big_error (ERR_UNZIP_CODE_1, "code_1"); break; case 2: big_error (ERR_UNZIP_CODE_2, "code_2"); break; case 3: big_error (ERR_UNZIP_CODE_3, "code_3"); break; case 51: big_error (ERR_UNZIP_CODE_51, "code_51"); break; case 4: /* memory allocation error 4-8 */ case 5: case 6: case 7: case 8: big_error (ERR_UNZIP_MEMORY_ERROR, ""); break; case 9: big_error (ERR_UNZIP_CODE_9, "code_9"); break; case 10: big_error (ERR_UNZIP_CODE_10, "code_10"); break; case 11: big_error (ERR_UNZIP_CODE_11, "code_11"); break; case 50: big_error (ERR_UNZIP_CODE_50, "code_50"); break; default: big_error (ERR_UNZIP_UNDOCUMENTED_ERROR, "default"); break; } } static void unzip_zipfile () { char zip_path[MAX_PATH + 1]; char zipdir_path[MAX_PATH + 1]; char zipdir_switch[MAX_PATH + 1]; char zipfile[MAX_PATH +1]; FILE *fp; struct stat buf; pid_t pid, status; cs_get_required_parameter("file1", zipfile, MAX_PATH); fp = cgi_filehandle(global_cgi, "file1"); if(fstat(fileno(fp), &buf)) big_error (ERR_CANT_FIND_ZIPFILE, zipfile); if(buf.st_size ==0) big_error (ERR_EMPTY_FILE, zipfile); write_cgi_file (fp, buf.st_size, ZIP_TMP_FNAME); snprintf (zipdir_path, MAX_PATH + 1, "%s/%s", discussion_path, ZIP_TMP_DIRNAME); clean_zip_temp_dir (); snprintf (zipdir_switch, MAX_PATH + 1, "-d%s", zipdir_path); /* tells unzip to extract to this directory */ snprintf (zip_path, MAX_PATH + 1, "%s/%s", discussion_path, ZIP_TMP_FNAME); if ((pid = fork ()) < 0) big_error (ERR_CANT_START_NEW_PROCESS, "in unzip_zipfile()"); if (pid == 0) { /* child process */ execl (UNZIP_PATH, "unzip", zipdir_switch, "-o", "-qq", zip_path, (char *) 0); exit (88); /* this is returned if above execl() fails */ } /*** parent process */ while (wait (&status) != pid); check_unzip_status (WEXITSTATUS (status)); /* report on status */ } static void get_lowercase_extension (const char *filename, char *extension) { char *ptr; ptr = strrchr (filename, '.'); if (!ptr) { *extension = '\0'; return; } strncpy (extension, ptr + 1, MAX_FILENAME + 1); for (ptr = extension; *ptr; ptr++) *ptr = tolower (*ptr); } static void add_to_html_file_list (const char *fname) { HTML_FILE_NODE *ptr; if (!html_file_head) { html_file_head = (HTML_FILE_NODE *) malloc (sizeof (HTML_FILE_NODE)); if (!html_file_head) big_error (ERR_MALLOC_FAILED, ""); ptr = html_file_head; } else { for (ptr = html_file_head; ptr->next; ptr = ptr->next); ptr->next = (HTML_FILE_NODE *) malloc (sizeof (HTML_FILE_NODE)); if (!ptr->next) big_error (ERR_MALLOC_FAILED, ""); ptr = ptr->next; } strncpy (ptr->fname, fname, MAX_FILENAME + 1); ptr->next = (HTML_FILE_NODE *) 0; } static void build_html_file_list (int *file_count) { char dirname[MAX_PATH + 1]; DIR *dir_p; struct dirent *dir_entry_p; char extension[MAX_FILENAME + 1]; *file_count = 0; snprintf (dirname, MAX_PATH + 1, "%s/%s", discussion_path, ZIP_TMP_DIRNAME); dir_p = opendir (dirname); if (!dir_p) big_error (ERR_OPENDIR_FAILED, dirname); while (NULL != (dir_entry_p = readdir (dir_p))) { if (!isdirectory (dirname, dir_entry_p->d_name)) /* shared_file_util.c */ { get_lowercase_extension (dir_entry_p->d_name, extension); if (!strcmp (extension, "htm") || !strcmp (extension, "html")) { add_to_html_file_list (dir_entry_p->d_name); (*file_count)++; } } } closedir (dir_p); } static void verify_start_file (char *start_fname, int *done) { #define MAX_MSG 100 char start_path[MAX_PATH + 1]; struct stat buf; int file_count; char msg[MAX_MSG]; *done = 1; /* be optimistic! */ snprintf (start_path, MAX_PATH + 1, "%s/%s/%s", discussion_path, ZIP_TMP_DIRNAME, ZIP_START_FNAME); if (!stat (start_path, &buf)) { /* if a file named ZIP_START_FNAME exists ... */ if (S_ISDIR (buf.st_mode)) { /* is it a directory? */ build_html_file_list (&file_count); if (file_count == 1) strncpy (start_fname, html_file_head->fname, MAX_FILENAME + 1); else { snprintf (msg, MAX_MSG, "%s %s", ZIP_START_FNAME, ZIP_START_FNAME); big_error (ERR_DIR_NAMED_X_FOUND_X_IS_RESERVED, msg); } } else /* ZIP_START_FNAME was not a directory */ strncpy (start_fname, ZIP_START_FNAME, MAX_FILENAME + 1); } else { /* no file named ZIP_START_FNAME was found */ build_html_file_list (&file_count); if (!file_count) big_error (ERR_NO_HTML_FILES_FOUND, ""); else if (file_count == 1) strncpy (start_fname, html_file_head->fname, MAX_FILENAME + 1); else { *done = 0; /* we'll have to ask the user to name the file */ strncpy (start_fname, ZIP_START_FNAME, MAX_FILENAME + 1); } } #undef MAX_MSG } static void process_individual_website_files (char *start_fname) { #define MAX_TMP_NAME 30 char name[MAX_TMP_NAME]; char orig_fname[MAX_PATH + 1]; char write_dest_fname[MAX_PATH + 1]; int i; char filename[MAX_PATH +1]; FILE *fp; struct stat buf; clean_zip_temp_dir (); create_tmp_zip_dir (); strncpy (start_fname, "index.html", MAX_FILENAME + 1); /* assume this, just to be safe */ for(i =1; i<= conf.mail_attachments; i++) { snprintf(name, MAX_TMP_NAME, "file%d", i); cs_get_optional_parameter(name, filename, MAX_PATH); if (strlen(filename)) { fp = cgi_filehandle(global_cgi, name); if(fstat(fileno(fp), &buf)) big_error(ERR_STAT_FAILED, filename); if(buf.st_size == 0) big_error(ERR_EMPTY_FILE, filename); get_orig_fname (filename, orig_fname); snprintf (write_dest_fname, MAX_PATH + 1, "%s/%s", ZIP_TMP_DIRNAME, orig_fname); /* so we can spoof write_cgi_file */ write_cgi_file (fp,buf.st_size, write_dest_fname); if (!strcmp (name, "file1")) strncpy (start_fname, orig_fname, MAX_FILENAME + 1); } } #undef MAX_TMP_NAME } static void rename_tmp_dir (char *directory_fname, time_t * time_sent) { char oldname[MAX_PATH + 1]; char newname[MAX_PATH + 1]; snprintf (oldname, MAX_PATH + 1, "%s/%s", discussion_path, ZIP_TMP_DIRNAME); get_unique_fname (directory_fname, "dir", time_sent); snprintf (newname, MAX_PATH + 1, "%s/%s", discussion_path, directory_fname); if (rename (oldname, newname)) big_error (ERR_CANT_RENAME_TEMP_DIR, newname); } static void process_website_attached_files (time_t * time_sent, int is_web_zipfile, int *done) { char start_file[MAX_FILENAME + 1]; char directory_fname[MAX_FILENAME + 1]; if (is_web_zipfile) { unzip_zipfile (); verify_start_file (start_file, done); } else { process_individual_website_files (start_file); *done = 1; } rename_tmp_dir (directory_fname, time_sent); add_to_file_list (&file_head, directory_fname, start_file); } void ask_which_fname ( char *course, char *key, char *from) { #define MAX_TMP_NAME 30 HTML_FILE_NODE *ptr; int i =0; char name[MAX_TMP_NAME]; cs_set_course_info(&conf); cs_set_current_time(); cs_set_int_value("grp", MAIL); cs_set_value("crs", course); cs_set_value("id", key); cs_set_value("from", from); cs_set_value("dir", file_head->unique_fname); cs_set_int_value("ask_which", 1); for (ptr = html_file_head; ptr; ptr = ptr->next) { snprintf(name, MAX_TMP_NAME, "file.%d.name", i); cs_set_value(name, "fname"); snprintf(name, MAX_TMP_NAME, "file.%d.value", i); cs_set_value(name, ptr->fname); if(i ==0) { snprintf(name, MAX_TMP_NAME, "file.%d.checked", i); cs_set_int_value(name, 1); } i++; } free_html_filelist (); free_file_list (&file_head); #undef MAX_TMP_NAME } static void record_in_outbox (const char *inf_fname, const char *subject, time_t time_sent, int website, int pasted_website) { OUTBOX_RECORD outbox; FILE *fp; RECEIVER_NODE *rptr; int i; char outbox_fname[MAX_PATH + 1]; strncpy (outbox.info_fname, inf_fname, MAX_FILENAME + 1); strncpy (outbox.subject, subject, MAX_SUBJECT + 1); outbox.time_sent = time_sent; /* build list of up to MAX_TO recipients, each recipient name separated by ** vertical bar character */ *outbox.to = '\0'; for (rptr = to_head, i = 1; rptr && i <= MAX_TO; rptr = rptr->next, i++) { if (i > 1) strcat (outbox.to, "|"); strcat (outbox.to, rptr->realname); } if (rptr) /* if we did not finish list */ strcat (outbox.to, "|"); /* then end list with a vertical bar */ /** the how_sent item is not used at the moment, for now fill in with a valid *** value for all ***/ outbox.how_sent = NEWMSG; outbox.is_sleepy = 0; /* not yet deleted */ outbox.unread = 1; outbox.attachments = website || (pasted_website && pasted_attachments) ? 1 : attachments + pasted_attachments; snprintf (outbox_fname, MAX_PATH + 1, "%s%s/%s/%s/%s", conf.course_path, PEOPLE_DIR, user.username, MAIL_DIR, OUTBOX_FNAME); fp = fopen (outbox_fname, "a"); if (!fp) big_error (ERR_FOPEN_APPEND_FAILED, outbox_fname); get_exclusive_lock(fileno(fp), 1); /* shared_lock.c */ if (fwrite (&outbox, sizeof (OUTBOX_RECORD), 1, fp) != 1) big_error (ERR_FWRITE_FAILED, outbox_fname); release_lock(fileno(fp)); fclose (fp); } int main (void) { char course[MAX_PATH + 1]; /* from crs=? command line */ char key[MAX_KEY + 1]; /* from id=? command line */ char from[MAX_PATH + 1]; /* from from=? command line */ int pasted_website; /* from optional pasted_website=? cmd line */ int pasted_files; /* from optional pasted_files=? cmd line */ char msg_fname[MAX_FILENAME + 1]; /* name given to the message */ char inf_fname[MAX_FILENAME + 1]; /* the info file name */ time_t time_sent; char subject[MAX_SUBJECT + 1]; int website; /* was the 'website' checkbox checked? */ int is_web_zipfile; /* was a web page attached as a single zip file? */ int done; /* are we done, or do we have to ask user to pick the starting html file from a list */ int width; cs_cgi_init(); read_parameters (course, key, from, &website, &pasted_website, &pasted_files, &width); 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(); /* shared_access.c */ time_sent = time (NULL); set_discussion_names (conf.course_path, user.username, MAIL); /* shared_news_util.c */ check_form_data (&is_web_zipfile, website, pasted_website, pasted_files, &time_sent); if (website) process_website_attached_files (&time_sent, is_web_zipfile, &done); else done = 1; /* no need for more info from user */ build_mail_receiver_list(); /* determine who to send to */ process_message_file (msg_fname, &time_sent, width); process_pasted_attached_files (pasted_files, pasted_website, &time_sent); write_info_file (msg_fname, inf_fname, subject, time_sent, website, pasted_website); update_all_inboxes (inf_fname, subject, time_sent, website, pasted_website); record_in_outbox (inf_fname, subject, time_sent, website, pasted_website); free_receiver_lists (); if (done) { free_file_list (&file_head); free_file_list (&pasted_file_head); free_html_filelist (); back_up (from); } else { ask_which_fname (course, key, from); cs_cgi_display("select_home_html_file", 1); } cs_cgi_destroy(); return 0; }