#include #include #include #include /* for tolower() */ #include #include #include "global.h" #include "manhat-lib/shared_util.h" #include "manhat-lib/shared_cs_util.h" #include "manhat-lib/shared_news_util.h" #include "manhat-lib/shared_lock.h" #include "manhat-lib/shared_copy_file.h" #include "manhat-lib/shared_file_util.h" ATTACHMENT_NODE *attachment_head = 0; /* linked list of file info */ char inbox_path[MAX_PATH + 1]; /* full path to inbox.dat */ static void read_parameters (char *course, char *key, long *offset, int *grp, int *inbox) { char tmp[MAX_FILENAME + 1]; /* for holding the long value * */ cs_get_required_parameter ("crs", course, MAX_FILENAME); /* cgihtml library */ cs_get_required_parameter ("id", key, MAX_KEY); cs_get_required_parameter ("grp", tmp, MAX_FILENAME); *grp = atoi (tmp); cs_get_required_parameter ("loc", tmp, MAX_FILENAME); *offset = atol (tmp); if (*grp == MAIL) { cs_get_required_parameter ("inbox", tmp, MAX_FILENAME); *inbox = (*tmp == 'Y') || (*tmp == 'y'); } else *inbox = 1; /* doesn't really matter, but it's best to initialize this to prevent compiler warnings */ } /* reads the inbox file and then the corresponding *.inf file ** to get everything ready to copy ** this function is almost the same as the one with the same name ** in news_read.c (this version doesn't bother sending marking ** the message as read) **/ static void process_news_inbox_record (long offset, CENTRAL_INBOX_RECORD * inbox, int grp, int *website_attached,CONFIG_STRUCT *conf) { int fd; FILE *fp; char infopath[MAX_PATH + 1]; int i; ATTACHMENT_NODE *aptr = 0; NEWS_INFO infofile_info; /** this sets global inbox_path string */ snprintf(inbox_path,MAX_PATH + 1,"%s%s",central_discussion_path,INBOX_FNAME); fp = fopen (inbox_path, "r"); if (!fp) cs_critical_error (ERR_FOPEN_READ_FAILED, ""); fd = fileno(fp); get_shared_lock(fd, 1); /* shared_lock.c */ if (fseek (fp, offset, SEEK_SET)) cs_critical_error (ERR_FSEEK_FAILED, ""); if (fread (inbox, sizeof (CENTRAL_INBOX_RECORD), 1, fp) != 1) cs_critical_error (ERR_FREAD_FAILED, ""); release_lock(fd); /* shared_lock.c */ fclose(fp); *website_attached = 0; /* assume this to start */ if(inbox->info.attachments) /* read the info file to get the attachment data */ { snprintf (infopath, MAX_PATH + 1, "%s%s/%s/%s/%s", conf->course_path,PEOPLE_DIR, inbox->info.sender, discussion_fname, inbox->info_fname); fp = fopen (infopath, "r"); if (!fp) cs_critical_error (ERR_FOPEN_READ_FAILED, ""); fd = fileno(fp); get_shared_lock(fd, 1); /* shared_lock.c */ if (fread (&infofile_info, sizeof (NEWS_INFO), 1, fp) != 1) cs_critical_error (ERR_FREAD_FAILED, ""); /* process attachments, build linked list */ *website_attached = (infofile_info.attachments == -1); /* so we go thru next for loop */ if (*website_attached) infofile_info.attachments = 1; for (i = 1; i <= infofile_info.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, ""); aptr->next = 0; } /* for .. */ release_lock(fd); /* shared_lock.c */ fclose (fp); } } static void get_news_clipboard_info (CLIPBOARD_INFO * clipboard_info, int grp, int offset, CONFIG_STRUCT *conf) { CENTRAL_INBOX_RECORD inbox; int website_attached; process_news_inbox_record (offset, &inbox, grp, &website_attached, conf); clipboard_info->group = grp; strncpy (clipboard_info->subject, inbox.info.subject, MAX_SUBJECT + 1); strncpy (clipboard_info->sender_username, inbox.info.sender, MAX_USERNAME + 1); strncpy (clipboard_info->sender_realname, inbox.info.sender_realname, MAX_NAME + 1); clipboard_info->time_sent = inbox.info.time_sent; clipboard_info->attachments = inbox.info.attachments; strncpy (clipboard_info->msg_fname, inbox.info.msg_fname, MAX_FILENAME + 1); clipboard_info->website_attached = website_attached; } static void process_mail_inbox_record (long offset, INBOX_RECORD * inbox, INFO * infofile_info, int *website_attached, CONFIG_STRUCT *conf, SESSION *user) { char infopath[MAX_PATH + 1]; FILE *fp; ATTACHMENT_NODE *aptr = 0; int i; snprintf (inbox_path, MAX_PATH + 1, "%speople/%s/mail/%s", conf->course_path, user->username, INBOX_FNAME); fp = fopen (inbox_path, "r"); if (!fp) cs_critical_error (ERR_FOPEN_READ_FAILED, ""); 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, ""); fclose (fp); snprintf (infopath, MAX_PATH + 1, "%speople/%s/mail/%s", conf->course_path, inbox->newfile_info.sender, inbox->newfile_info.info_fname); fp = fopen (infopath, "r"); if (!fp) cs_critical_error (ERR_FOPEN_READ_FAILED, ""); /* note that file locking is not necessary when working with the Post Office */ if (fread (infofile_info, sizeof (INFO), 1, fp) != 1) cs_critical_error (ERR_FREAD_FAILED, ""); /* 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 */ 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, ""); aptr->next = 0; } fclose (fp); } static void get_mail_inbox_clipboard_info (CLIPBOARD_INFO * clipboard_info, int grp, int offset, CONFIG_STRUCT *conf, SESSION *user) { INBOX_RECORD inbox; INFO infofile_info; int website_attached; process_mail_inbox_record (offset, &inbox, &infofile_info, &website_attached, conf, user); clipboard_info->group = grp; strncpy (clipboard_info->subject, inbox.newfile_info.subject, MAX_SUBJECT + 1); strncpy (clipboard_info->sender_username, inbox.newfile_info.sender, MAX_USERNAME + 1); strncpy (clipboard_info->sender_realname, inbox.newfile_info.sender_realname, MAX_NAME + 1); clipboard_info->time_sent = inbox.newfile_info.time_sent; clipboard_info->attachments = inbox.newfile_info.attachments; strncpy (clipboard_info->msg_fname, infofile_info.msg_fname, MAX_FILENAME + 1); clipboard_info->website_attached = website_attached; } static void process_mail_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; int i; snprintf (outbox_path, MAX_PATH + 1, "%speople/%s/mail/%s", conf->course_path, user->username, OUTBOX_FNAME); fp = fopen (outbox_path, "r"); if (!fp) cs_critical_error (ERR_FOPEN_READ_FAILED, ""); if (fseek (fp, offset, SEEK_SET)) cs_critical_error (ERR_FSEEK_FAILED, ""); if (fread (outbox, sizeof (OUTBOX_RECORD), 1, fp) != 1) cs_critical_error (ERR_FREAD_FAILED, ""); fclose (fp); snprintf (infopath, MAX_PATH + 1, "%speople/%s/mail/%s", conf->course_path, user->username, outbox->info_fname); fp = fopen (infopath, "r"); if (!fp) cs_critical_error (ERR_FOPEN_READ_FAILED, ""); /* note file locking not necessary when working with the Post Office */ if (fread (infofile_info, sizeof (INFO), 1, fp) != 1) cs_critical_error (ERR_FREAD_FAILED, ""); /* 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, ""); aptr->next = 0; } fclose (fp); } void get_mail_outbox_clipboard_info (CLIPBOARD_INFO * clipboard_info, int grp, int offset, CONFIG_STRUCT *conf, SESSION *user) { OUTBOX_RECORD outbox; INFO infofile_info; int website_attached; process_mail_outbox_record (offset, &outbox, &infofile_info, &website_attached,conf, user ); clipboard_info->group = grp; strncpy (clipboard_info->subject, outbox.subject, MAX_SUBJECT + 1); strncpy (clipboard_info->sender_username, user->username, MAX_USERNAME + 1); strncpy (clipboard_info->sender_realname, user->realname, MAX_NAME + 1); clipboard_info->time_sent = outbox.time_sent; clipboard_info->attachments = outbox.attachments; strncpy (clipboard_info->msg_fname, infofile_info.msg_fname, MAX_FILENAME + 1); clipboard_info->website_attached = website_attached; } static void get_clipboard_info (CLIPBOARD_INFO * clipboard_info, int grp, long offset, int inbox, CONFIG_STRUCT *conf, SESSION *user) { switch (grp) { case CLASS_DISCUSSION: case STUDENT_LOUNGE: case ANONYMOUS_DISCUSSION: case TEAM_DISCUSSION: case HANDOUTS_NOTICES: case TEAM_TEACH: case SELFTEST: case LECTURES: case ASSIGNMENTS: case INTERNET_RESOURCES: case SURVEYS: case PODCASTS: get_news_clipboard_info (clipboard_info, grp, offset, conf); break; case MAIL: if (inbox) get_mail_inbox_clipboard_info (clipboard_info, grp, offset, conf, user); else get_mail_outbox_clipboard_info (clipboard_info, grp, offset, conf, user); break; default: cs_critical_error (ERR_UNSUPPORTED_GROUP, ""); break; } } static void write_msg_file (const char *destpath, const char *sender_username, const char *msg_fname, int grp, CONFIG_STRUCT *conf) { FILE *fp, *outfp; char fullpath[MAX_PATH + 1]; char fulldestpath[MAX_PATH + 1]; int big_buffer = 200; char *buffer, c; int i; char *unescape_url; buffer = (char*)malloc ( sizeof(char) * (big_buffer +1)); if(!buffer) cs_critical_error(ERR_MALLOC_FAILED, ""); snprintf (fulldestpath, MAX_PATH + 1, "%s/%s", destpath, msg_fname); outfp = fopen (fulldestpath, "w"); if (!outfp) cs_critical_error (ERR_FOPEN_WRITE_FAILED, fulldestpath); /* discussion_fname is global and should have been set in set_discussion_names() */ snprintf (fullpath, MAX_PATH + 1, "%s%s/%s/%s/%s", conf->course_path, PEOPLE_DIR, sender_username, discussion_fname, msg_fname); fp = fopen (fullpath, "r"); if (!fp) cs_critical_error (ERR_FOPEN_READ_FAILED, fullpath); /** Early versions of Manhattan 'escaped' the characters of the URL typed *** into an INTERNET_RESOURCES module. The current version does not. *** (This URL is stored in the first line of the message.) The next 'if' *** maintains compatiblity with those earlier versions by 'unescaping' the *** first line of the msg before writing it to the clipboard. You can *** safely remove this 'if' if you don't have to deal with classrooms created *** with 'old' Manhattans **/ if (grp == INTERNET_RESOURCES) { i =0; while((c = getc(fp)) != '\n') { if((int)strlen(buffer) >= big_buffer) { buffer = realloc(buffer, big_buffer*2 +1); big_buffer = big_buffer *2; } buffer[i] = c; buffer[i+1] = '\0'; i++; } unescape_url = (char *)cgi_url_unescape (buffer); /* Clearsilver.h */ fprintf (outfp, "%s\n", unescape_url); } /*** end kludge */ while (fgets (buffer, big_buffer, fp)) fprintf (outfp, "%s", buffer); fclose (outfp); fclose (fp); if(buffer) free(buffer); } static void write_clipboard_file (const char *clipboard_dir, CLIPBOARD_INFO * clipboard_info) { ATTACHMENT_NODE *ptr; char dest_path[MAX_PATH + 1]; FILE *fp; snprintf (dest_path, MAX_PATH + 1, "%s/%s", clipboard_dir, CLIPBOARD_INF_FNAME); fp = fopen (dest_path, "w"); if (!fp) cs_critical_error (ERR_FOPEN_WRITE_FAILED, ""); if (fwrite (clipboard_info, sizeof (CLIPBOARD_INFO), 1, fp) != 1) cs_critical_error (ERR_FWRITE_FAILED, ""); for (ptr = attachment_head; ptr; ptr = ptr->next) if (fwrite (&(ptr->data), sizeof (ATTACHMENT), 1, fp) != 1) cs_critical_error (ERR_RED_WRITE, ""); fclose (fp); } static void write_website (const char *clipboard_dir, const char *sender_username, CONFIG_STRUCT *conf) { char source_base[MAX_PATH + 1], dest_base[MAX_PATH + 1]; snprintf (source_base, MAX_PATH + 1, "%s%s/%s/%s/", conf->course_path, PEOPLE_DIR, sender_username, discussion_fname); snprintf (dest_base, MAX_PATH + 1, "%s/", clipboard_dir); copy_dir (source_base, dest_base, /* shared_copy_file.c */ attachment_head->data.unique_fname, attachment_head->data.unique_fname); } static void write_attachments (const char *clipboard_dir, int website_attached, const char *sender_username, CONFIG_STRUCT *conf) { char source_path[MAX_PATH + 1], dest_path[MAX_PATH + 1]; ATTACHMENT_NODE *ptr; if (website_attached) write_website (clipboard_dir, sender_username, conf); else { for (ptr = attachment_head; ptr; ptr = ptr->next) { snprintf (source_path, MAX_PATH + 1, "%speople/%s/%s/%s", conf->course_path, sender_username, discussion_fname, ptr->data.unique_fname); snprintf (dest_path, MAX_PATH + 1, "%s/%s", clipboard_dir, ptr->data.unique_fname); copy_file (source_path, dest_path); /* shared_copy_file.c */ } } } static void free_attachment_list () { ATTACHMENT_NODE *aptr; while (attachment_head) { aptr = attachment_head; attachment_head = attachment_head->next; free (aptr); } } void write_clipboard_data (const char *path, const char *course, const char *key, long offset, int grp, int inbox, CONFIG_STRUCT *conf, SESSION *user) { CLIPBOARD_INFO clipboard_info; /* this directory should NOT exist (because we killed it earlier), ** so we create it first */ if (mkdir (path, 0777)) cs_critical_error (ERR_MKDIR_FAILED, path); /* gather information about this message */ get_clipboard_info (&clipboard_info, grp, offset, inbox, conf, user); write_clipboard_file (path, &clipboard_info); write_msg_file (path, clipboard_info.sender_username, clipboard_info.msg_fname, grp, conf); if (clipboard_info.attachments) write_attachments (path, clipboard_info.website_attached, clipboard_info.sender_username, conf); free_attachment_list (); } 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 grp; /* from grp=? command line */ int inbox; /* from optional inbox=? command line */ char clipboard_path[MAX_PATH + 1]; /* complete path to this user's clipboard directory */ SESSION user; CONFIG_STRUCT conf; cs_cgi_init(); read_parameters (course, key, &offset, &grp, &inbox); read_configuration_file (course, &conf); /* shared_util.c */ validate_key (key, &user, &conf); /* shared_util.c */ if (user.group != FACULTY) cs_critical_error (ERR_REQUEST_DENIED, ""); set_discussion_names (conf.course_path, user.username, grp); /* shared_news_util.c */ snprintf (clipboard_path, MAX_PATH + 1, "%s%s/", CLIPBOARD_PATH, user.id); kill_directory (clipboard_path); /* shared_file_util.c */ write_clipboard_data (clipboard_path, course, key, offset, grp, inbox, &conf, &user); cs_cgi_display("clipboard_copy", 1); cs_cgi_destroy(); return (0); }