#include #include /* for free() */ #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_news_util.h" #include "manhat-lib/shared_potato_util.h" #include "manhat-lib/shared_lock.h" #include "manhat-lib/shared_server_string.h" #include "manhat-lib/shared_mime_type.h" /* sender is really the offset into inbox.dat -- for anonymous groups --- ** this fcn returns the real sender username **/ static void get_sender_username (char *sender, CONFIG_STRUCT *conf, SESSION *user) { int fd; long offset; FILE *fp; char inbox_path[MAX_PATH + 1]; CENTRAL_INBOX_RECORD inbox; snprintf (inbox_path, MAX_PATH + 1, "%s%s/%s/%s", conf->course_path, INBOXES_DIR, ANONYMOUS_DIR, INBOX_FNAME); offset = atol (sender); 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, ""); strncpy (sender, inbox.info.sender, MAX_USERNAME + 1); release_lock(fd); /* shared_lock.c */ fclose (fp); } static void read_parameters (char *course, char *key, char *sender, char *fname, char *info_fname, int *attach, int *grp, int *ra_file) { char intstring[20]; cs_get_required_parameter ("crs", course, MAX_FILENAME); /* shared_cgi_util.c */ cs_get_required_parameter ("id", key, MAX_KEY); cs_get_required_parameter ("user", sender, MAX_USERNAME); cs_get_required_parameter ("fname", fname, MAX_FILENAME); cs_get_required_parameter ("info", info_fname, MAX_FILENAME); cs_get_required_parameter ("attach", intstring, 5); *attach = atoi (intstring); /* grp parameter is optional */ cs_get_optional_parameter ("grp", intstring, 5); if (strlen(intstring)) *grp = atoi (intstring); else *grp = -1; /* flag that this is not a newsgroup */ /* ra_file parameter (Used for Real Audio files) is optional */ cs_get_optional_parameter ("ra_file", intstring, 5); if(strlen(intstring)) *ra_file = 1; else *ra_file = 0; } static void verify_access_rights (SESSION *user) { PERSON_NODE *ptr; for (ptr = person_head; ptr; ptr = ptr->next) if (!strcmp (user->username, ptr->data.username)) return; cs_critical_error (ERR_REQUEST_DENIED, ""); } static void get_original_fname (char *original_fname, const char *fname) { ATTACHMENT_NODE *ptr; for (ptr = attachment_head; ptr; ptr = ptr->next) if (!strcmp (ptr->data.unique_fname, fname)) { strncpy (original_fname, ptr->data.orig_fname, MAX_FILENAME + 1); return; } cs_critical_error (ERR_UNABLE_TO_DETERMINE_FILENAME, ""); } static void deliver_special_selftest ( char *source_file, char *dest_file, char *course, char *key, char *sender, char *info_fname, char *original_fname, char *system_fname) { FILE *fp; struct stat buf; char *buffer; if (stat (source_file, &buf)) cs_critical_error (ERR_STAT_FAILED, ""); /* allocate an extra byte for a terminating null */ buffer = (char *) malloc( (buf.st_size + 1) * sizeof(char)); if(!buffer) cs_critical_error (ERR_MALLOC_FAILED, ""); fp = fopen (source_file, "r"); if (!fp) cs_critical_error (ERR_FOPEN_READ_FAILED, source_file); /* read the whole file in one gulp */ if (fread (buffer, buf.st_size, 1, fp) != 1) cs_critical_error (ERR_FREAD_FAILED, ""); fclose(fp); /* shared_potato_util.c */ if (!process_cgi_enabled_potato(buffer,buf.st_size, course, key, sender, info_fname, original_fname,system_fname,ALIAS,stdout)) { /* send the file as-is */ printf ("Content-type:text/html\n"); printf ("Content-disposition: filename=\"%s\"\n", dest_file); printf ("Content-length: %ld\n\n", (long)buf.st_size); if (fwrite (buffer, buf.st_size, 1, stdout) != 1) cs_critical_error (ERR_FWRITE_FAILED, ""); } free(buffer); } static void deliver_file (char *mime_type, char *source_file, char *dest_file) { #define CHUNKSIZE 8192 FILE *fp; struct stat buf; int bytes_read; int bytes_left; char buffer[CHUNKSIZE]; if (stat (source_file, &buf)) cs_critical_error (ERR_STAT_FAILED, ""); fp = fopen (source_file, "r"); if (!fp) cs_critical_error (ERR_FOPEN_READ_FAILED, ""); printf ("Content-type:%s\n", mime_type); printf ("Content-disposition: filename=\"%s\"\n", dest_file); printf ("Content-length: %ld\n\n", (long)buf.st_size); bytes_left = buf.st_size; bytes_read = CHUNKSIZE; while (bytes_left) { if (bytes_left < CHUNKSIZE) bytes_read = bytes_left; if (fread (buffer, bytes_read, 1, fp) != 1) cs_critical_error (ERR_FREAD_FAILED, ""); bytes_left -= bytes_read; if (fwrite (buffer, bytes_read, 1, stdout) != 1) cs_critical_error (ERR_FWRITE_FAILED, ""); } fclose (fp); #undef CHUNKSIZE } static void deliver_realaudio_meta (char *mime_type, char *course, char *key, const char *sender, const char *fname, const char *info_fname, int attach, int grp) { char server_string[MAX_PATH + 1]; char *script_name; get_server_string(server_string, MAX_PATH + 1); printf ("Content-type:%s\n\n", mime_type); /* work on this later */ /* SCRIPT_NAME is defined in cgi-lib.h */ script_name = hdf_get_value(global_cgi->hdf, "CGI.ScriptName", ""); printf ("%s%s?crs=%s&id=%s&user=%s&fname=%s&info=%s&attach=%d&grp=%d&ra_file=1", server_string, script_name, course, key, sender, fname, info_fname, attach, grp); } static void send_file (char *sender, char *fname, char *info_fname, int attach, int grp, int ra_file, char *key, char *course, CONFIG_STRUCT *conf, SESSION *user) { INFO infofile_info; char original_fname[MAX_FILENAME + 1]; char mime_type[MAX_MIME_TYPE + 1]; char source_path[MAX_PATH + 1]; int is_realaudio; /* is this a real audio file? */ read_post_infofile (sender, info_fname, &infofile_info, conf); /* shared_read_infofile.c */ if (strcmp (user->username, sender)) /* if this user didn't send the file */ verify_access_rights (user); get_original_fname (original_fname, fname); snprintf (source_path, MAX_PATH + 1, "%s%s/%s/%s/%s", conf->course_path, PEOPLE_DIR, sender, MAIL_DIR, fname); /* shared_mime_type.c */ get_mime_type (source_path, original_fname, mime_type, &is_realaudio); if (is_realaudio && !ra_file) deliver_realaudio_meta (mime_type, course, key, sender, fname, info_fname, attach, grp); else deliver_file (mime_type, source_path, original_fname); } static void send_news_file (char *sender, char *fname, char *info_fname, int attach, int grp, int ra_file, char *key, char *course, CONFIG_STRUCT *conf) { NEWS_INFO infofile_info; char original_fname[MAX_FILENAME + 1]; char mime_type[MAX_MIME_TYPE + 1]; char source_path[MAX_PATH + 1]; int is_realaudio; read_news_infofile (sender, info_fname, &infofile_info, grp, conf); /* shared_read_infofile.c */ /* we don't have to verify_access_rights because we know by definition that ** everyone has been sent the same file. Fortunate, because of the way the ** person list is mucked up... see comment above *** *** well... that's not quite true. the 'small group' thing is where not everyone *** gets the same file oh well, we'll take our chances and skip the validation anyway **/ /*** verify_access_rights(); ******/ get_original_fname (original_fname, fname); set_discussion_names (conf->course_path, sender, grp); /* shared_news_util.c */ snprintf (source_path, MAX_PATH + 1, "%s/%s", discussion_path, fname); /* discussion_path global in shared_news_util.c */ /* shared_mime_type.c */ get_mime_type (source_path, original_fname, mime_type, &is_realaudio); if (is_realaudio && !ra_file) deliver_realaudio_meta (mime_type, course, key, sender, fname, info_fname, attach, grp); else if ( (grp == SELFTEST) && !strcmp(mime_type,"text/html") ) deliver_special_selftest(source_path,original_fname,course, key,sender,info_fname,original_fname, fname); else deliver_file (mime_type, source_path, original_fname); } static void send_clipboard_file (char *sender, char *fname, char *info_fname, int attach, int grp, int ra_file, char *key, char *course, SESSION *user) { CLIPBOARD_INFO infofile_info; char clipboard_path[MAX_PATH + 1]; char original_fname[MAX_FILENAME + 1]; char mime_type[MAX_MIME_TYPE + 1]; char source_path[MAX_PATH + 1]; int is_realaudio; get_clipboard_info (&infofile_info,clipboard_path, user); get_original_fname (original_fname, fname); snprintf (source_path, MAX_PATH + 1, "%s%s", clipboard_path, fname); /* shared_mime_type.c */ get_mime_type (source_path, original_fname, mime_type, &is_realaudio); deliver_file (mime_type, source_path, original_fname); } int main (void) { char course[MAX_PATH + 1]; /* from crs=? command line */ char key[MAX_KEY + 1]; /* from id=? command line */ char sender[MAX_USERNAME + 1]; /* from user=? command line */ char fname[MAX_FILENAME + 1]; /* from fname=? cmd line */ char info_fname[MAX_FILENAME + 1]; /* from inf=? cmd line */ int attach; /* from attach=? cmd line */ int grp; /* from optional grp=? cmd line */ int ra_file; /* from optional ra_file=? cmd line */ SESSION user; CONFIG_STRUCT conf; /* the configuration read from config file */ cs_cgi_init(); read_parameters (course, key, sender, fname, info_fname, &attach, &grp, &ra_file); read_configuration_file (course, &conf); /* shared_util.c */ validate_key (key, &user, &conf); /* shared_util.c */ if (grp == ANONYMOUS_DISCUSSION) /*the 'user' param was really the offset into inbox.dat */ get_sender_username (sender, &conf, &user); if (grp == -1) send_file (sender, fname, info_fname, attach, grp, ra_file, key, course, &conf, &user); /* from mail system */ else if (grp == CLIPBOARD) send_clipboard_file(sender, fname, info_fname, attach, grp, ra_file, key, course, &user); else { send_news_file (sender, fname, info_fname, attach, grp, ra_file, key, course, &conf); } free_attachment_list (); /* shared_read_infofile.c */ cs_cgi_destroy(); return 0; }