diff options
Diffstat (limited to 'mapi/pmapi.c')
-rw-r--r-- | mapi/pmapi.c | 2929 |
1 files changed, 2929 insertions, 0 deletions
diff --git a/mapi/pmapi.c b/mapi/pmapi.c new file mode 100644 index 00000000..7fa3b455 --- /dev/null +++ b/mapi/pmapi.c @@ -0,0 +1,2929 @@ + +/* + * ======================================================================== + * Copyright 2006-2009 University of Washington + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * ======================================================================== + */ + +#include "pmapi.h" + +static int xlate_key; + +mapi_global_s *ms_global = NULL; +#define SIZEOF_20KBUF (20480) +char tmp_20k_buf[SIZEOF_20KBUF]; + +void mm_searched (MAILSTREAM *stream,unsigned long number); +void mm_exists (MAILSTREAM *stream,unsigned long number); +void mm_expunged (MAILSTREAM *stream,unsigned long number); +void mm_flags (MAILSTREAM *stream,unsigned long number); +void mm_notify (MAILSTREAM *stream,char *string,long errflg); +void mm_list (MAILSTREAM *stream,int delimiter,char *name,long attributes); +void mm_lsub (MAILSTREAM *stream,int delimiter,char *name,long attributes); +void mm_status (MAILSTREAM *stream,char *mailbox,MAILSTATUS *status); +void mm_log (char *string,long errflg); +void mm_dlog (char *string); +int fetch_recursively(BODY *body, long msgno, char *prefix, + PART *part, long flags, FLAGS MAPIflags, + sessionlist_s *cs); +LRESULT CALLBACK Login(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); +void mm_login (NETMBX *mb,char *user,char *pwd,long trial); +void mm_critical (MAILSTREAM *stream); +void mm_nocritical (MAILSTREAM *stream); +long mm_diskerror (MAILSTREAM *stream,long errcode,long serious); +void mm_fatal (char *string); +lpMapiFileDesc new_mapi_file_desc(int arraysize); +void free_mapi_file_desc(lpMapiFileDesc lpmfd, int arraysize); +file_s *new_file_s(); +void free_file_s(file_s *fs); +void init_prcvars(mapi_global_s *nmg); +void init_prcfeats(mapi_global_s *nmg); +void expand_env_vars(mapi_global_s *nmg); +void init_fcc_folder(mapi_global_s *nmg); +void init_pmapi_registry_vars(mapi_global_s *nmg); +void init_pmapi_vars(mapi_global_s *nmg); +char *copy_remote_to_local(char *pinerc, sessionlist_s *cs); +int read_pinerc(mapi_global_s *nmg, sessionlist_s *cs, + char *prc, char *pineconf, char *pinercex, int depth); +void free_mapi_global(mapi_global_s *nmg); +MAILSTREAM *first_open(sessionlist_s *cs); +int lookup_file_mime_type(char *fn, BODY *body); +int LookupMIMEFileExt(char *val, char *mime_type, DWORD *vallen); +int in_passfile(sessionlist_s *cs); +int set_text_data(BODY *body, char *txt); +int get_suggested_directory(char *dir); +int get_suggested_file_ext(char *file_ext, PART *part, DWORD *file_extlen); +int InitDebug(); +int GetPineData(); +int UnderlineSpace(char *s); +int GetOutlookVersion(); +char *pmapi_generate_message_id(); +SENDSTREAM *mapi_smtp_open(sessionlist_s *cs, char **servers, long options); +char *encode_mailto_addr_keyval(lpMapiRecipDesc lpmr); +char *encode_mailto_keyval(char *key, char* val); + + +void mm_searched (MAILSTREAM *stream,unsigned long number) +{ + if(MSDEBUG){ + fprintf(ms_global->dfd, "IMAP mm_searched: not implemented\r\n"); + _flushall(); + } +} + +void mm_exists (MAILSTREAM *stream,unsigned long number) +{ + if(MSDEBUG){ + fprintf(ms_global->dfd, "IMAP mm_exists: not implemented\r\n"); + _flushall(); + } +} + +void mm_expunged (MAILSTREAM *stream,unsigned long number) +{ + if(MSDEBUG){ + fprintf(ms_global->dfd, "IMAP mm_expunged: not implemented\r\n"); + _flushall(); + } +} + +void mm_flags (MAILSTREAM *stream,unsigned long number) +{ + if(MSDEBUG){ + fprintf(ms_global->dfd, "IMAP mm_flags: number is %d\r\n", number); + _flushall(); + } +} + +void mm_notify (MAILSTREAM *stream,char *string,long errflg) +{ + mapi_global_s *nmg; + + nmg = ms_global; + if(MSDEBUG){ + fprintf(nmg->dfd, "IMAP mm_notify:%s %s\r\n", + (errflg == NIL ? "" : + (errflg == WARN ? " WARN:": + (errflg == ERROR ? " ERROR:": + (errflg == PARSE ? " PARSE:":" BYE:")))), string); + _flushall(); + } +} + +void mm_list (MAILSTREAM *stream,int delimiter,char *name,long attributes) +{ + if(MSDEBUG){ + fprintf(ms_global->dfd, "IMAP mm_list: not implemented\r\n"); + _flushall(); + } +} + +void mm_lsub (MAILSTREAM *stream,int delimiter,char *name,long attributes) +{ + if(MSDEBUG){ + fprintf(ms_global->dfd, "IMAP mm_lsub: not implemented\r\n"); + _flushall(); + } +} + +void mm_status (MAILSTREAM *stream,char *mailbox,MAILSTATUS *status) +{ + if(MSDEBUG){ + fprintf(ms_global->dfd, "IMAP mm_status: not implemented\r\n"); + _flushall(); + } +} + +void mm_log (char *string,long errflg) +{ + if(MSDEBUG){ + fprintf(ms_global->dfd, "IMAP mm_log:%s %s\r\n", + (errflg == NIL ? "" : + (errflg == WARN ? " WARN:": + (errflg == ERROR ? " ERROR:": + (errflg == PARSE ? " PARSE:":" BYE:")))), string); + _flushall(); + } + if(errflg == ERROR) + ErrorBox("ERROR: %s", string); +} + +void mm_dlog (char *string) +{ + if(MSDEBUG){ + time_t now; + struct tm *tm_now; + + now = time((time_t *)0); + tm_now = localtime(&now); + + fprintf(ms_global->dfd, "IMAP %2.2d:%2.2d:%2.2d %d/%d: %s\r\n", + tm_now->tm_hour, tm_now->tm_min, tm_now->tm_sec, + tm_now->tm_mon+1, tm_now->tm_mday, string); + _flushall(); + } +} + +int fetch_recursively(BODY *body, long msgno, char *prefix, PART *part, + long flags, FLAGS MAPIflags, sessionlist_s *cs) +{ + FILE *attfd; + PART *subpart; + mapi_global_s *nmg; + int num = 0, tmplen; + file_s *tfs, *tfs2; + unsigned long declen, numwritten; + void *decf; + char tmp[64], file_ext[64], filename[1024], dir[1024]; + DWORD file_extlen = 64; + char *tmpatt; + unsigned long tmpattlen; + + nmg = ms_global; + tmp[0] = '\0'; + if(body && body->type == TYPEMULTIPART){ + part = body->nested.part; + fetch_recursively(&part->body, msgno, prefix, part, + flags, MAPIflags, cs); + } + else{ + do{ + num++; + sprintf(tmp, "%s%s%d", prefix, (*prefix ? "." : ""), num); + if(part && part->body.type == TYPEMULTIPART){ + subpart = part->body.nested.part; + fetch_recursively(&subpart->body, msgno, tmp, + subpart, flags, MAPIflags, cs); + } + else{ + tmpatt = mail_fetch_body(cs->open_stream, msgno, + tmp, &tmpattlen, flags); + if(strcmp(tmp, "1") == 0){ + if(((part && part->body.type == TYPETEXT) || + (!part && body->type == TYPETEXT)) && + !(MAPIflags & MAPI_BODY_AS_FILE)){ + if(cs->lpm->lpszNoteText){ + fs_give((void **)&cs->lpm->lpszNoteText); + cs->lpm->lpszNoteText = NULL; + } + cs->lpm->lpszNoteText = mstrdup(tmpatt); + tmpatt = NULL; + } + else + cs->lpm->lpszNoteText = mstrdup(""); + if(MAPIflags & MAPI_SUPPRESS_ATTACH) + return 0; + } + if(tmpatt && part && part->body.encoding == ENCBASE64){ + decf = rfc822_base64(tmpatt, tmpattlen, &declen); + tmpatt = NULL; + } + else if(tmpatt && part && part->body.encoding == ENCQUOTEDPRINTABLE){ + decf = rfc822_qprint(tmpatt, tmpattlen, &declen); + tmpatt = NULL; + } + else{ + if(tmpatt){ + decf = mstrdup(tmpatt); + declen = tmpattlen; + } + else decf = NULL; + } + if(decf){ + dir[0] = '\0'; + get_suggested_directory(dir); + tmplen = strlen(dir); + if(dir[tmplen - 1] != '\\'){ + dir[tmplen] = '\\'; + dir[tmplen+1] = '\0'; + } + file_ext[0] = '\0'; + get_suggested_file_ext(file_ext,part, &file_extlen); + do{ + sprintf(filename, "%smapiapp%d%s", dir, nmg->attach_no, + file_ext); + nmg->attach_no++; + }while (_access(filename, 00) != -1); + attfd = fopen(filename, "wb"); + if(attfd){ + if(MSDEBUG) + fprintf(nmg->dfd,"preparing to write attachment to %s\r\n", + filename); + numwritten = fwrite(decf, sizeof(char), declen, attfd); + fclose(attfd); + fs_give((void **)&decf); + tfs = new_file_s(); + tfs->filename = mstrdup(filename); + if(!cs->fs) + cs->fs = tfs; + else{ + for(tfs2 = cs->fs; tfs2->next; tfs2 = tfs2->next); + tfs2->next = tfs; + } + } + else{ + if(MSDEBUG) + fprintf(nmg->dfd,"Failure in opening %s for attachment\r\n", + filename); + } + } + } + }while(part && (part = part->next)); + } + return 0; +} + +int fetch_structure_and_attachments(long msgno, long flags, + FLAGS MAPIflags, sessionlist_s *cs) +{ + BODY *body = NULL; + ENVELOPE *env; + ADDRESS *addr; + MESSAGECACHE *elt = NULL; + mapi_global_s *nmg; + file_s *tfs; + int num = 0, restore_seen = 0, file_count = 0, i; + unsigned long recips; + char tmp[1024]; /* don't know how much space we'll need */ + + nmg = ms_global; + env = mail_fetch_structure(cs->open_stream, msgno, &body, flags); + if(env == NULL || body == NULL){ + if(MSDEBUG) + fprintf(nmg->dfd, "mail_fetch_structure returned %p for env and %p for body\r\n", env, body); + return MAPI_E_FAILURE; + } + if(cs->lpm){ + if(MSDEBUG) + fprintf(nmg->dfd, "global lpm is set when it SHOULDN'T be! Freeing\r\n"); + if(free_mbuffer(cs->lpm)) + free_MapiMessage(cs->lpm, 1); + cs->lpm = NULL; + } + cs->lpm = new_MapiMessage(1); + if(env->subject) cs->lpm->lpszSubject = mstrdup(env->subject); + if(env->date){ + elt = mail_elt(cs->open_stream, msgno); + mail_parse_date(elt, env->date); + sprintf(tmp, "%d/%s%d/%s%d %s%d:%s%d", + elt->year+BASEYEAR, (elt->month < 10) ? "0": "", + elt->month, (elt->day < 10) ? "0":"", elt->day, + (elt->hours < 10) ? "0":"", elt->hours, + (elt->minutes < 10) ? "0":"", elt->minutes); + cs->lpm->lpszDateReceived = mstrdup(tmp); + } + if(env->from){ + cs->lpm->lpOriginator = new_MapiRecipDesc(1); + if(env->from->personal) + cs->lpm->lpOriginator->lpszName = mstrdup(env->from->personal); + if(env->from->mailbox && env->from->host){ + /* don't know if these could ever be empty */ + sprintf(tmp, "%s@%s", env->from->mailbox, env->from->host); + cs->lpm->lpOriginator->lpszAddress = mstrdup(tmp); + } + cs->lpm->lpOriginator->ulRecipClass = MAPI_ORIG; + } + if(env->to || env->cc || env->bcc){ /* should always be true */ + recips = 0; + if(env->to){ + addr = env->to; + while(addr){ + recips++; + addr = addr->next; + } + } + if(env->cc){ + addr = env->cc; + while(addr){ + recips++; + addr = addr->next; + } + } + if(env->bcc){ + addr = env->bcc; + while(addr){ + recips++; + addr = addr->next; + } + } + cs->lpm->nRecipCount = recips; + cs->lpm->lpRecips = new_MapiRecipDesc(recips); + recips = 0; + if(env->to){ + addr = env->to; + while(addr){ + cs->lpm->lpRecips[recips].ulRecipClass = MAPI_TO; + if(addr->personal) + cs->lpm->lpRecips[recips].lpszName = mstrdup(addr->personal); + if(addr->mailbox && addr->host){ + sprintf(tmp, "%s@%s", addr->mailbox, addr->host); + cs->lpm->lpRecips[recips].lpszAddress = mstrdup(tmp); + } + recips++; + addr = addr->next; + } + } + if(env->cc){ + addr = env->cc; + while(addr){ + cs->lpm->lpRecips[recips].ulRecipClass = MAPI_CC; + if(addr->personal) + cs->lpm->lpRecips[recips].lpszName = mstrdup(addr->personal); + if(addr->mailbox && addr->host){ + sprintf(tmp, "%s@%s", addr->mailbox, addr->host); + cs->lpm->lpRecips[recips].lpszAddress = mstrdup(tmp); + } + recips++; + addr = addr->next; + } + } + if(env->bcc){ + addr = env->bcc; + while(addr){ + cs->lpm->lpRecips[recips].ulRecipClass = MAPI_BCC; + if(addr->personal) + cs->lpm->lpRecips[recips].lpszName = mstrdup(addr->personal); + if(addr->mailbox && addr->host){ + sprintf(tmp, "%s@%s", addr->mailbox, addr->host); + cs->lpm->lpRecips[recips].lpszAddress = mstrdup(tmp); + } + recips++; + addr = addr->next; + } + } + } + + if(flags & FT_PEEK){ + /* gotta remember to unflag \Seen if we just want a peek */ + sprintf(tmp, "%d", msgno); + mail_fetch_flags(cs->open_stream, tmp, NIL); + elt = mail_elt(cs->open_stream, msgno); + if(!elt->seen){ + if(MSDEBUG) + fprintf(nmg->dfd, "Message has not been seen, and a PEEK is requested\r\n"); + restore_seen = 1; + } + else if(MSDEBUG) + fprintf(nmg->dfd, "Message has already been marked seen\r\n"); + } + if(!(MAPIflags & MAPI_ENVELOPE_ONLY)) + fetch_recursively(body, msgno, "", NULL, flags, MAPIflags, cs); + if(cs->fs){ + for(tfs = cs->fs; tfs; tfs = tfs->next) + file_count++; + cs->lpm->lpFiles = new_mapi_file_desc(file_count); + for(i = 0, tfs = cs->fs; i < file_count && tfs; i++, tfs = tfs->next){ + cs->lpm->lpFiles[i].lpszPathName = mstrdup(tfs->filename); + } + cs->lpm->nFileCount = file_count; + free_file_s(cs->fs); + cs->fs = NULL; + } + if(restore_seen){ + elt = mail_elt(cs->open_stream, msgno); + if(!elt->seen && MSDEBUG) + fprintf(nmg->dfd, "Fetched body and Message still isn't seen\r\n"); + else if(MSDEBUG) + fprintf(nmg->dfd, "Message has been seen, clearing flag\r\n"); + if(elt->seen){ + mail_flag(cs->open_stream, tmp, "\\SEEN", NIL); + elt = mail_elt(cs->open_stream, msgno); + if(MSDEBUG) + fprintf(nmg->dfd, "After calling mail_flag(), elt->seen is %s\r\n", + elt->seen ? "SET" : "UNSET"); + } + } + return SUCCESS_SUCCESS; +} + +LRESULT CALLBACK Login(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + mapi_global_s *nmg; + + nmg = ms_global; + + switch(message){ + case WM_INITDIALOG: + SetDlgItemText(hDlg, IDC_SERVER, nmg->tmpmbxptr); + if(/*nmg->flags.mapi_logon_ui &&*/ in_passfile(nmg->cs)){ + SetDlgItemText(hDlg, IDC_LOGIN, nmg->cs->dlge.edit1); + SetDlgItemText(hDlg, IDC_PASSWORD, nmg->cs->dlge.edit2); + } + else + SetDlgItemText(hDlg, IDC_LOGIN, + (*nmg->cs->mb->user) ? nmg->cs->mb->user + : nmg->prcvars[USER_ID]->val.p); + return TRUE; + case WM_COMMAND: + if(LOWORD(wParam) == IDOK){ + nmg->cs->flags.dlg_cancel = 0; + GetDlgItemText(hDlg, IDC_LOGIN, nmg->cs->dlge.edit1, EDITLEN); + GetDlgItemText(hDlg, IDC_PASSWORD, nmg->cs->dlge.edit2, EDITLEN); + EndDialog(hDlg, LOWORD(wParam)); + return TRUE; + } + else if(LOWORD(wParam) == IDCANCEL){ + nmg->cs->flags.dlg_cancel = 1; + EndDialog(hDlg, LOWORD(wParam)); + return TRUE; + } + break; + } + return FALSE; +} + +void mm_login (NETMBX *mb,char *user,char *pwd,long trial) +{ + mapi_global_s *nmg; + pw_cache_s *tpwc, *dpwc; + int tmp_set_mbx = 0; + + nmg = ms_global; + nmg->cs->mb = mb; + if(!nmg->cs->flags.dlg_cancel){ + for(tpwc = nmg->cs->pwc; tpwc; tpwc = tpwc->next){ + if(tpwc->validpw && strcmp(tpwc->host, mb->host) == 0) + break; + } + if(tpwc){ + strcpy(user, tpwc->user); + strcpy(pwd, tpwc->pwd); + tpwc->validpw = 0; + } + /* else if(!nmg->cs->flags.check_stream) { */ + else if(nmg->cs->flags.mapi_logon_ui || !nmg->pmapi_strict_no_dialog) { + if(!nmg->tmpmbxptr){ + tmp_set_mbx = 1; + nmg->tmpmbxptr = mb->host; + } + DialogBox(nmg->mhinst, MAKEINTRESOURCE(IDD_DIALOG1), + nmg->cs->mhwnd, (DLGPROC)Login); + if(tmp_set_mbx) + nmg->tmpmbxptr = NULL; + if(!nmg->cs->flags.dlg_cancel){ + strcpy(user, nmg->cs->dlge.edit1); + strcpy(pwd, nmg->cs->dlge.edit2); + tpwc = nmg->cs->pwc; + while(tpwc){ + if(tpwc->validpw == 0){ + dpwc = tpwc; + tpwc = tpwc->next; + if(dpwc == nmg->cs->pwc) + nmg->cs->pwc = dpwc->next; + fs_give((void **)&dpwc); + } + else + tpwc = tpwc->next; + } + if(nmg->cs->pwc == NULL){ + nmg->cs->pwc = (pw_cache_s *)fs_get(sizeof(pw_cache_s)); + tpwc = nmg->cs->pwc; + } + else { + for(tpwc = nmg->cs->pwc; tpwc->next; tpwc = tpwc->next); + tpwc->next = (pw_cache_s *)fs_get(sizeof(pw_cache_s)); + tpwc = tpwc->next; + } + memset(tpwc, 0, sizeof(pw_cache_s)); + strncpy(tpwc->user, nmg->cs->dlge.edit1, EDITLEN - 1); + strncpy(tpwc->pwd, nmg->cs->dlge.edit2, EDITLEN - 1); + strncpy(tpwc->host, mb->host, EDITLEN - 1); + } + } + } + nmg->cs->mb = NULL; +} + +void mm_critical (MAILSTREAM *stream) +{ + if(MSDEBUG){ + fprintf(ms_global->dfd, "IMAP mm_critical: not implemented\r\n"); + _flushall(); + } +} + +void mm_nocritical (MAILSTREAM *stream) +{ + if(MSDEBUG){ + fprintf(ms_global->dfd, "IMAP mm_nocritical: not implemented\r\n"); + _flushall(); + } +} + +long mm_diskerror (MAILSTREAM *stream,long errcode,long serious) +{ + if(MSDEBUG){ + fprintf(ms_global->dfd, "IMAP mm_diskerror: not implemented\r\n"); + _flushall(); + } + return 1; +} + +void mm_fatal (char *string) +{ + if(MSDEBUG){ + fprintf(ms_global->dfd, "IMAP mm_fatal: %s\r\n", string); + _flushall(); + } +} + +sessionlist_s *new_sessionlist() +{ + sessionlist_s *cs; + + cs = (sessionlist_s *)fs_get(sizeof(sessionlist_s)); + memset(cs, 0, sizeof(sessionlist_s)); + cs->session_number = ms_global->next_session++; + + return cs; +} + +sessionlist_s *free_sessionlist_node(sessionlist_s *cs) +{ + sessionlist_s *ts; + + ts = cs->next; + + if(cs->currently_open) + fs_give((void **)&cs->currently_open); + if(cs->fs) + free_file_s(cs->fs); + if(cs->lpm){ + if(free_mbuffer(cs->lpm)) + free_MapiMessage(cs->lpm, 1); + cs->lpm = NULL; + } + fs_give((void **)&cs); + + return ts; +} + +sessionlist_s *get_session(unsigned long num) +{ + mapi_global_s *nmg = ms_global; + sessionlist_s *ts; + + ts = nmg->sessionlist; + while(ts && ts->session_number != num) ts = ts->next; + return ts; +} + +/* +void *mm_cache (MAILSTREAM *stream,unsigned long msgno,long op){} +*/ +mapi_global_s *new_mapi_global() +{ + mapi_global_s *nmg; + int i; + + nmg = (mapi_global_s *)fs_get(sizeof(mapi_global_s)); + memset(nmg, 0, sizeof(mapi_global_s)); + for(i=0; i < NUMPRCVARS; i++){ + nmg->prcvars[i] = (rc_entry_s *)fs_get(sizeof(rc_entry_s)); + memset(nmg->prcvars[i], 0, sizeof(rc_entry_s)); + } + for(i=0; i < NUMPRCFEATS; i++){ + nmg->prcfeats[i] = (rc_feat_s *)fs_get(sizeof(rc_feat_s)); + memset(nmg->prcfeats[i], 0, sizeof(rc_feat_s)); + } + nmg->next_session = 1; + + return nmg; +} + +int InitPineSpecific(sessionlist_s *cs) +{ + mapi_global_s *nmg = ms_global; + + if(nmg->inited) return 0; + init_prcvars(ms_global); + init_prcfeats(ms_global); + init_pmapi_registry_vars(ms_global); + if(read_pinerc(ms_global, cs, ms_global->pinerc, + ms_global->pineconf, ms_global->pinercex, 0) == -1) + return -1; + expand_env_vars(ms_global); + init_fcc_folder(ms_global); + msprint1("Fcc folder defined: %s", ms_global->fccfolder); + init_pmapi_vars(ms_global); + nmg->inited = 1; + return 1; +} + +int +new_mbuffer(void *buf, int arraysize, BufType type) +{ + MBUFFER_LIST_S *tlist, *tlist2; + mapi_global_s *nmg = ms_global; + + tlist = (MBUFFER_LIST_S *)fs_get(sizeof(MBUFFER_LIST_S)); + memset(tlist, 0, sizeof(MBUFFER_LIST_S)); + tlist->buf = buf; + tlist->arraysize = arraysize; + tlist->type = type; + + if(!nmg->mapi_bufs) + nmg->mapi_bufs = tlist; + else{ + for(tlist2 = nmg->mapi_bufs; tlist2->next; tlist2 = tlist2->next); + tlist2->next = tlist; + } + + return(0); +} + +int +free_mbuffer(void *buf) +{ + MBUFFER_LIST_S *tlist, *pre_tlist = NULL; + mapi_global_s *nmg = ms_global; + sessionlist_s *session; + + for(tlist = nmg->mapi_bufs; tlist && tlist->buf != buf; pre_tlist = tlist, tlist = tlist->next); + if(!tlist){ + msprint1("ERROR: buf %p not found in list!\r\n", buf); + return 1; + } + if(tlist == nmg->mapi_bufs) + nmg->mapi_bufs = tlist->next; + else + pre_tlist->next = tlist->next; + switch (tlist->type) { + case RecipDesc: + free_MapiRecipDesc(tlist->buf, tlist->arraysize); + break; + case Message: + for(session = nmg->sessionlist; session; session = session->next){ + if(session->lpm == tlist->buf) + session->lpm = NULL; + } + free_MapiMessage(tlist->buf, tlist->arraysize); + break; + } + fs_give((void **)&tlist); + return 0; +} + +lpMapiRecipDesc +new_MapiRecipDesc(int arraysize) +{ + lpMapiRecipDesc lpmrd; + mapi_global_s *nmg = ms_global; + + lpmrd = (MapiRecipDesc *)fs_get(arraysize*sizeof(MapiRecipDesc)); + memset(lpmrd, 0, arraysize*sizeof(MapiRecipDesc)); + new_mbuffer((void *)lpmrd, arraysize, RecipDesc); + return lpmrd; +} + +void +free_MapiRecipDesc(lpMapiRecipDesc buf, int arraysize) +{ + int i; + + for(i = 0; i < arraysize; i++){ + if(buf[i].lpszName) + fs_give((void **)&buf[i].lpszName); + if(buf[i].lpszAddress) + fs_give((void **)&buf[i].lpszAddress); + } + fs_give((void **)&buf); +} + +lpMapiMessage +new_MapiMessage(int arraysize) +{ + lpMapiMessage lpmm; + mapi_global_s *nmg = ms_global; + + lpmm = (lpMapiMessage)fs_get(arraysize*sizeof(MapiMessage)); + memset(lpmm, 0, arraysize*sizeof(MapiMessage)); + new_mbuffer((void *)lpmm, arraysize, Message); + return lpmm; +} + +void +free_MapiMessage(lpMapiMessage buf, int arraysize) +{ + int i; + + for(i = 0; i < arraysize; i++){ + if(buf[i].lpszSubject) + fs_give((void **)&buf[i].lpszSubject); + if(buf[i].lpszNoteText) + fs_give((void **)&buf[i].lpszNoteText); + if(buf[i].lpszMessageType) + fs_give((void **)&buf[i].lpszMessageType); + if(buf[i].lpszDateReceived) + fs_give((void **)&buf[i].lpszDateReceived); + if(buf[i].lpszConversationID) + fs_give((void **)&buf[i].lpszConversationID); + if(buf[i].lpOriginator){ + if(free_mbuffer(buf[i].lpOriginator)) + free_MapiRecipDesc(buf[i].lpOriginator, 1); + } + if(buf[i].lpRecips){ + if(free_mbuffer(buf[i].lpRecips)) + free_MapiRecipDesc(buf[i].lpRecips, buf[i].nRecipCount); + } + if(buf[i].lpFiles) + free_mapi_file_desc(buf[i].lpFiles, buf[i].nFileCount); + } + fs_give((void **)&buf); +} + +lpMapiFileDesc new_mapi_file_desc(int arraysize) +{ + lpMapiFileDesc lpmfd; + + lpmfd = (MapiFileDesc *)fs_get(arraysize * sizeof (MapiFileDesc)); + memset(lpmfd, 0, arraysize * sizeof(MapiFileDesc)); + return lpmfd; +} + +void free_mapi_file_desc(lpMapiFileDesc lpmfd, int arraysize) +{ + int i; + + if(lpmfd == NULL) return; + + for(i = 0; i < arraysize; i++){ + if(lpmfd[i].lpszPathName) + fs_give((void **)&lpmfd[i].lpszPathName); + if(lpmfd[i].lpszFileName) + fs_give((void **)&lpmfd[i].lpszFileName); + /* NOTE: if lpFileType gets used, free it here */ + } + fs_give((void **)&lpmfd); +} + +file_s *new_file_s() +{ + file_s *tmp_fs; + + tmp_fs = (file_s *)fs_get(sizeof(file_s)); + memset(tmp_fs, 0, sizeof(file_s)); + return tmp_fs; +} + +void free_file_s(file_s *fs) +{ + if(fs == NULL) return; + if(fs->next) + free_file_s(fs->next); + if(fs->filename) + fs_give((void **)&fs->filename); + fs_give((void **)&fs); +} + +void +init_prcvars(mapi_global_s *nmg) +{ + int i=0; + + nmg->prcvars[USER_ID]->var = mstrdup("user-id"); + nmg->prcvars[PERSONAL_NAME]->var = mstrdup("personal-name"); + nmg->prcvars[USER_DOMAIN]->var = mstrdup("user-domain"); + nmg->prcvars[SMTP_SERVER]->var = mstrdup("smtp-server"); + nmg->prcvars[SMTP_SERVER]->islist = 1; + nmg->prcvars[INBOX_PATH]->var = mstrdup("inbox-path"); + nmg->prcvars[FEATURE_LIST]->var = mstrdup("feature-list"); + nmg->prcvars[FEATURE_LIST]->islist = 1; + nmg->prcvars[CHARACTER_SET]->var = mstrdup("character-set"); + nmg->prcvars[FOLDER_COLLECTIONS]->var = mstrdup("folder-collections"); + nmg->prcvars[FOLDER_COLLECTIONS]->islist = 1; + nmg->prcvars[PMAPI_SEND_BEHAVIOR]->var = mstrdup("pmapi-send-behavior"); + nmg->prcvars[PMAPI_SEND_BEHAVIOR]->ispmapivar = 1; + nmg->prcvars[DEFAULT_FCC]->var = mstrdup("default-fcc"); + nmg->prcvars[PMAPI_SUPPRESS_DIALOGS]->var = mstrdup("pmapi-suppress-dialogs"); + nmg->prcvars[PMAPI_SUPPRESS_DIALOGS]->ispmapivar = 1; + nmg->prcvars[PMAPI_STRICT_NO_DIALOG]->var = mstrdup("pmapi-strict-no-dialog"); + nmg->prcvars[PMAPI_STRICT_NO_DIALOG]->ispmapivar = 1; +} + +void +init_prcfeats(mapi_global_s *nmg) +{ + nmg->prcfeats[ENABLE8BIT]->var = mstrdup("enable-8bit-esmtp-negotiation"); +} + +void init_fcc_folder(mapi_global_s *nmg) +{ + char *fcc, **fc, *desc = NULL, *col = NULL, *tfcc, *p, *p2; + int i = 0; + + if(!nmg->prcvars[DEFAULT_FCC]->val.p) + nmg->prcvars[DEFAULT_FCC]->val.p = cpystr("sent-mail"); + fcc = nmg->prcvars[DEFAULT_FCC]->val.p; + if(!fcc || !(*fcc)) return; + if(strcmp(fcc, "\"\"") == 0) return; + if((*fcc == '{') || (isalpha(fcc[0]) && (fcc[1] == ':')) + || ((fcc[0] == '\\') && (fcc[1] == '\\'))){ + nmg->fccfolder = cpystr(fcc); + return; + } + fc = nmg->prcvars[FOLDER_COLLECTIONS]->val.l; + if(!fc || !fc[0] || !fc[0][0]) return; + get_pair(fc[i], &desc, &col, 0, 0); + if(desc) + fs_give((void **)&desc); + if(!col) + return; + p = strrchr(col, '['); + p2 = strrchr(col, ']'); + if((p2 < p) || (!p)){ + if(col) + fs_give((void **)&col); + return; + } + tfcc = (char *)fs_get((strlen(col) + strlen(fcc) + 1) * sizeof(char)); + *p = '\0'; + p2++; + sprintf(tfcc, "%s%s%s", col, fcc, p2); + nmg->fccfolder = tfcc; + if(col) + fs_give((void **)&col); +} + +void init_pmapi_registry_vars(mapi_global_s *nmg) +{ + HKEY hKey; + BYTE keyData[1024]; + DWORD keyDataSize = 1024; + DWORD keyDataType; + int i; + + if(RegOpenKeyEx(HKEY_CURRENT_USER, + "Software\\University of Washington\\Alpine\\1.0\\PmapiOpts", + 0, + KEY_QUERY_VALUE, + &hKey) != ERROR_SUCCESS) + return; + + for(i = 0; i < NUMPRCVARS; i++){ + if(nmg->prcvars[i]->ispmapivar && nmg->prcvars[i]->islist == 0){ + keyDataSize = 1024; + if((RegQueryValueEx(hKey, nmg->prcvars[i]->var, 0, &keyDataType, + keyData, &keyDataSize) == ERROR_SUCCESS) + && keyDataType == REG_SZ){ + if(nmg->prcvars[i]->val.p) + fs_give((void **)&nmg->prcvars[i]->val.p); + nmg->prcvars[i]->val.p = mstrdup(keyData); + } + } + } + + RegCloseKey(hKey); +} + +void init_pmapi_vars(mapi_global_s *nmg) +{ + char *b; + + if(b = nmg->prcvars[PMAPI_SEND_BEHAVIOR]->val.p){ + if(_stricmp(b, "always-prompt") == 0) + nmg->pmapi_send_behavior = PMSB_ALWAYS_PROMPT; + else if(_stricmp(b, "always-send") == 0) + nmg->pmapi_send_behavior = PMSB_ALWAYS_SEND; + else if(_stricmp(b, "never-send") == 0) + nmg->pmapi_send_behavior = PMSB_NEVER_SEND; + } + else + nmg->pmapi_send_behavior = PMSB_ALWAYS_PROMPT; + if(b = nmg->prcvars[PMAPI_SUPPRESS_DIALOGS]->val.p){ + if(_stricmp(b, "yes") == 0) + nmg->pmapi_suppress_dialogs = PMSD_YES; + else if(_stricmp(b, "prompt") == 0) + nmg->pmapi_suppress_dialogs = PMSD_PROMPT; + else if(_stricmp(b, "no") == 0) + nmg->pmapi_suppress_dialogs = PMSD_NO; + } + else + nmg->pmapi_suppress_dialogs = PMSD_NO; + if(b = nmg->prcvars[PMAPI_STRICT_NO_DIALOG]->val.p){ + if(_stricmp(b, "yes") == 0) + nmg->pmapi_strict_no_dialog = 1; + } + else + nmg->pmapi_strict_no_dialog = 0; +} + +char *copy_remote_to_local(char *pinerc, sessionlist_s *cs) +{ + mapi_global_s *nmg = ms_global; + char *tmptext, dir[1024], filename[1024]; + unsigned long tmptextlen, i = 0, numwritten; + FILE *prcfd; + + if(nmg->cs) return NULL; + if(!(cs->open_stream = mapi_mail_open(cs, NULL, pinerc, + ms_global->debug ? OP_DEBUG : NIL))){ + ErrorBox("Couldn't open %s for reading as remote pinerc", pinerc); + return NULL; + } + nmg->cs = NULL; + nmg->tmpmbxptr = NULL; + tmptext = mail_fetch_body(cs->open_stream, cs->open_stream->nmsgs, + "1", &tmptextlen, NIL); + dir[0] = '\0'; + get_suggested_directory(dir); + do{ + sprintf(filename, "%s%smapipinerc%d", dir, + dir[strlen(dir)-1] == '\\' ? "" : "\\", i); + i++; + }while (_access(filename, 00) != -1); + if(prcfd = fopen(filename, "wb")){ + if(MSDEBUG) + fprintf(ms_global->dfd,"preparing to write pinerc to %s\r\n", + filename); + numwritten = fwrite(tmptext, sizeof(char), tmptextlen, prcfd); + fclose(prcfd); + } + else{ + ErrorBox("Couldn't open temp file %s for writing", filename); + mail_close_full(cs->open_stream, NIL); + return NULL; + } + cs->open_stream = mail_close_full(cs->open_stream, NIL); + return(mstrdup(filename)); +} + +int read_pinerc(mapi_global_s *nmg, sessionlist_s *cs, + char *prc, char *pineconf, char *pinercex, int depth) +{ + FILE *prcfd; + int i, varnum, j, varlen, create_local = 0, k; + char line[BUFLEN], *local_pinerc, *p; + + if(nmg == NULL) return -1; + if(MSDEBUG){ + fprintf(nmg->dfd, + "read_pinerc called: prc: %s, pineconf: %s, pinercex: %s, depth: %d\r\n", + prc ? prc : "NULL", pineconf ? pineconf : "NULL", + pinercex ? pinercex : "NULL", depth); + } + if(pineconf){ + if(MSDEBUG) + fprintf(nmg->dfd, "Recursively calling read_pinerc for pineconf\r\n"); + read_pinerc(nmg, cs, pineconf, NULL, NULL, 1); + } + if(prc == NULL){ + ErrorBox("No value found for %s. Try running Alpine.", "pinerc"); + DEBUG_WRITE("No value found for %s\r\n","pinerc"); + _flushall(); + return -1; + } + if(*prc == '{'){ + if(MSDEBUG) + fprintf(ms_global->dfd, "REMOTE PINERC: %s\r\n", prc); + if(!(local_pinerc = copy_remote_to_local(prc, cs))){ + if(MSDEBUG) + fprintf(nmg->dfd, "Couldn't copy remote pinerc to local\r\n"); + return -1; + } + create_local = 1; + } + else{ + if(!(local_pinerc = mstrdup(prc))){ + ErrorBox("Couldn't fs_get for %s","pinerc"); + return -1; + } + } + if(MSDEBUG) + fprintf(nmg->dfd, "Preparing to open local pinerc %s\r\n", local_pinerc); + prcfd = fopen(local_pinerc, "r"); + if(prcfd == NULL){ + DEBUG_WRITE("Couldn't open %s\r\n","pinerc"); + _flushall(); + ErrorBox("Couldn't open %s\r\n","pinerc"); + if(local_pinerc) + fs_give((void **)&local_pinerc); + return -1; + } + DEBUG_WRITE("Opened %s for reading\r\n", "pinerc"); + for(i = 0; i < NUMPRCVARS && nmg->prcvars[i]->var; i++); + varnum = i; + while(fgets(line, BUFLEN, prcfd)){ + j = 0; + while(isspace(line[j])) j++; + if(line[j] != '#' && line[j] != '\0'){ + for(i = 0; i < varnum; i ++){ + varlen = strlen(nmg->prcvars[i]->var); + if(_strnicmp(nmg->prcvars[i]->var, line+j, varlen)==0){ + j += varlen; + if(line[j] == '='){ + /* we found a match in the pinerc */ + j++; + if(nmg->prcvars[i]->islist){ + while(isspace(line[j])) j++; + if(line[j] != '\0'){ + STRLIST_S *strl = NULL, *tl, *tln; + + if(nmg->prcvars[i]->val.l){ + for(k = 0; nmg->prcvars[i]->val.l[k]; k++) + fs_give((void **)&nmg->prcvars[i]->val.l[k]); + fs_give((void **)&nmg->prcvars[i]->val.l); + } + strl = (STRLIST_S *)fs_get(sizeof(STRLIST_S)); + memset(strl, 0, sizeof(STRLIST_S)); + tl = strl; + while(line[j]){ + while(isspace(line[j])) j++; + if(p = strchr(line+j, ',')) + *p = '\0'; + if(tl != strl || tl->str){ + tl->next = (STRLIST_S *)fs_get(sizeof(STRLIST_S)); + tl = tl->next; + memset(tl, 0, sizeof(STRLIST_S)); + } + varlen = strlen(line+j); + while(isspace((line+j)[varlen - 1])){ + varlen--; + (line+j)[varlen] = '\0'; + } + tl->str = mstrdup(line+j); + if(p){ + j = p - line + 1; + while(isspace(line[j])) j++; + if(!line[j]){ + fgets(line, BUFLEN, prcfd); + j = 0; + } + } + else + break; + } + for(tl = strl, k = 0; tl; tl = tl->next, k++); + nmg->prcvars[i]->val.l = (char **)fs_get((k+1)*sizeof(char *)); + for(tl = strl, k = 0; tl; tl = tln, k++){ + nmg->prcvars[i]->val.l[k] = tl->str; + tln = tl->next; + fs_give((void **)&tl); + } + nmg->prcvars[i]->val.l[k] = NULL; + } + } + else{ + while(isspace(line[j])) j++; + if(line[j] != '\0'){ + varlen = strlen(line+j); + while(isspace((line+j)[varlen-1])){ + varlen--; + (line+j)[varlen] = '\0'; + } + if(nmg->prcvars[i]->val.p) fs_give((void **)&nmg->prcvars[i]->val.p); + nmg->prcvars[i]->val.p = (char *)fs_get((varlen + 1)*sizeof(char)); + strncpy(nmg->prcvars[i]->val.p, line+j, varlen); + nmg->prcvars[i]->val.p[varlen] = '\0'; + } + } + } + } + } + } + } + if(!depth){ + if(pinercex){ + if(MSDEBUG) + fprintf(nmg->dfd, + "Recursively calling read_pinerc for exceptions\r\n"); + read_pinerc(nmg, cs, pinercex, NULL, NULL, 1); + } + } + _flushall(); + fclose(prcfd); + for(i = 0; nmg->prcvars[FEATURE_LIST]->val.l + && nmg->prcvars[FEATURE_LIST]->val.l[i]; i++){ + for(j = 0; j < NUMPRCFEATS; j++){ + if(strcmp(nmg->prcfeats[j]->var, nmg->prcvars[FEATURE_LIST]->val.l[i]) == 0) + nmg->prcfeats[j]->is_set = 1; + else if((strncmp("no-", nmg->prcvars[FEATURE_LIST]->val.l[i], 3) == 0) + && (strcmp(nmg->prcfeats[j]->var, + nmg->prcvars[FEATURE_LIST]->val.l[i] + 3) == 0)){ + nmg->prcfeats[j]->is_set = 0; + } + } + } + if(create_local && local_pinerc){ + if(MSDEBUG) + fprintf(nmg->dfd, "Removing %s\r\n", local_pinerc); + _unlink(local_pinerc); + } + if(local_pinerc) + fs_give((void **)&local_pinerc); + if(MSDEBUG){ + fprintf(nmg->dfd, "Current pinerc settings:\r\n"); + for(i = 0; i < varnum; i++){ + fprintf(nmg->dfd, "%s:", nmg->prcvars[i]->var); + if(!nmg->prcvars[i]->islist) + fprintf(nmg->dfd, " %s\r\n", + nmg->prcvars[i]->val.p ? nmg->prcvars[i]->val.p : " NOT DEFINED"); + else{ + if(!nmg->prcvars[i]->val.l) + fprintf(nmg->dfd, " NOT DEFINED\r\n"); + else { + for(j = 0; nmg->prcvars[i]->val.l[j]; j++) + fprintf(nmg->dfd, "\t%s\r\n", + nmg->prcvars[i]->val.l[j]); + } + } + } + } + return 0; +} + +void expand_env_vars(mapi_global_s *nmg) +{ + int i, j, check_reg = 0, islist; + DWORD keyDataSize = 1024, keyDataType; + char *p1, *p2, *p3, keyData[1024], *newstr, **valstrp; + HKEY hKey; + + + if(RegOpenKeyEx(HKEY_CURRENT_USER, + "Software\\University of Washington\\Alpine\\1.0\\PmapiOpts\\Env", + 0, + KEY_QUERY_VALUE, + &hKey) == ERROR_SUCCESS) + check_reg = 1; + for(i = 0; i < NUMPRCVARS; i++){ + islist = nmg->prcvars[i]->islist; + for(j = 0; islist ? (int)(nmg->prcvars[i]->val.l && nmg->prcvars[i]->val.l[j]) + : (j < 1); j++){ + valstrp = islist ? &nmg->prcvars[i]->val.l[j] : &nmg->prcvars[i]->val.p; + if(*valstrp == NULL) continue; + while((p1 = strstr(*valstrp, "${")) && (p2 = strchr(p1, '}'))){ + msprint1("%s -> ", *valstrp); + *p2 = '\0'; + p3 = NULL; + if((p3 = getenv(p1+2)) && *p3) + ; + else if(check_reg && (keyDataSize = 1024) + && (RegQueryValueEx(hKey, p1+2, 0, &keyDataType, + keyData, &keyDataSize) == ERROR_SUCCESS) + && keyDataType == REG_SZ) + p3 = keyData; + newstr = (char *)fs_get(sizeof(char)*(strlen(*valstrp) + + strlen(p3 ? p3 : "") + strlen(p2+1) + 1)); + *p1 = '\0'; + strcpy(newstr, *valstrp); + strcat(newstr, p3 && *p3 ? p3 : ""); + strcat(newstr, p2 + 1); + fs_give((void **)valstrp); + *valstrp = newstr; + msprint1(" %s\r\n", *valstrp); + } + } + } + if(check_reg) + RegCloseKey(hKey); +} + +void free_mapi_global(mapi_global_s *nmg) +{ + int i, j; + sessionlist_s *ts; + + if(nmg->pineExe) + fs_give((void **)&nmg->pineExe); + if(nmg->pineExeAlt) + fs_give((void **)&nmg->pineExeAlt); + if(nmg->pinerc) + fs_give((void **)&nmg->pinerc); + if(nmg->pineconf) + fs_give((void **)&nmg->pineconf); + if(nmg->pinercex) + fs_give((void **)&nmg->pinercex); + if(nmg->fccfolder) + fs_give((void **)&nmg->fccfolder); + if(nmg->attachDir) + fs_give((void **)&nmg->attachDir); + for(i = 0; i < NUMPRCFEATS; i++){ + if(nmg->prcfeats[i]->var) + fs_give((void **)&nmg->prcfeats[i]->var); + fs_give((void **)&nmg->prcfeats[i]); + } + for(i = 0; i < NUMPRCVARS; i++){ + if(nmg->prcvars[i]->var) + fs_give((void **)&nmg->prcvars[i]->var); + if(nmg->prcvars[i]->islist){ + if(nmg->prcvars[i]->val.l){ + for(j = 0; nmg->prcvars[i]->val.l[j]; j++) + fs_give((void **)&nmg->prcvars[i]->val.l[j]); + fs_give((void **)&nmg->prcvars[i]->val.l); + } + } + else { + if(nmg->prcvars[i]->val.p) + fs_give((void **)&nmg->prcvars[i]->val.p); + } + fs_give((void **)&nmg->prcvars[i]); + } + for(ts = nmg->sessionlist; ts;){ + if(ts->open_stream) + ts->open_stream = mail_close_full(ts->open_stream, NIL); + ts = free_sessionlist_node(ts); + } + if(nmg->debugFile) + fs_give((void **)&nmg->debugFile); + if(nmg->debug && nmg->dfd) + fclose(nmg->dfd); + nmg->debug = FALSE; + fs_give((void **)&nmg); +} + +MAILSTREAM *first_open(sessionlist_s *cs) +{ + mapi_global_s *nmg = ms_global; + /* cs->mhwnd = (HWND)ulUIParam; + * if(flFlags & MAPI_LOGON_UI) + * cs->flags.mapi_logon_ui = TRUE; + */ + /* if someone is logging in right now, return failure */ + if(nmg->cs) return NULL; + if(MSDEBUG) + fprintf(nmg->dfd, "Opening mailbox for the first time\r\n"); + if(nmg->prcvars[INBOX_PATH]->val.p == NULL){ + ErrorBox("No value set for %s!", "inbox"); + return NULL; + } + cs->open_stream = mapi_mail_open(cs, cs->open_stream, nmg->prcvars[INBOX_PATH]->val.p, + nmg->debug ? OP_DEBUG : NIL); + /* cs->flags.mapi_logon_ui = FALSE; */ + if(cs->open_stream){ + if(cs->currently_open){ + fs_give((void **)&cs->currently_open); + cs->currently_open = NULL; + } + cs->currently_open = mstrdup(nmg->prcvars[INBOX_PATH]->val.p); + if(nmg->debug) + mail_debug(cs->open_stream); + if(MSDEBUG){ + fprintf(nmg->dfd, "returning SUCCESS_SUCCESS\r\n"); + _flushall(); + } + return cs->open_stream; + } + else if(cs->flags.dlg_cancel){ + if(MSDEBUG){ + fprintf(nmg->dfd, "returning MAPI_E_FAILURE\r\n"); + _flushall(); + } + return NULL; + } + else{ + cs->dlge.edit1[0] = '\0'; + cs->dlge.edit2[0] = '\0'; + if(cs->currently_open){ + fs_give((void **)&cs->currently_open); + cs->currently_open = NULL; + } + if(MSDEBUG){ + fprintf(nmg->dfd, "returning MAPI_E_FAILURE\r\n"); + _flushall(); + } + return NULL; + } +} + +SENDSTREAM * +mapi_smtp_open(sessionlist_s *cs, char **servers, long options) +{ + mapi_global_s *nmg = ms_global; + SENDSTREAM *newstream; + pw_cache_s *tpwc, *dpwc; + + nmg->cs = cs; + nmg->tmpmbxptr = NULL; + nmg->cs->flags.dlg_cancel = 0; + newstream = smtp_open(servers, options); + nmg->cs = NULL; + nmg->tmpmbxptr = NULL; + + if(newstream){ /* if open stream, valid password */ + for(tpwc = cs->pwc; tpwc; tpwc = tpwc->next) + tpwc->validpw = 1; + } + else{ + for(tpwc = cs->pwc, dpwc = NULL; tpwc; dpwc = tpwc, tpwc = tpwc->next){ + if(tpwc->validpw == 0){ + if(tpwc == cs->pwc) + cs->pwc = tpwc->next; + else + dpwc->next = tpwc->next; + fs_give((void **)&tpwc); + } + } + } + return(newstream); +} + +MAILSTREAM * +mapi_mail_open(sessionlist_s *cs, MAILSTREAM *stream, char *name, long options) +{ + MAILSTREAM *newstream; + mapi_global_s *nmg = ms_global; + pw_cache_s *tpwc, *dpwc; + + nmg->cs = cs; + nmg->tmpmbxptr = name; + nmg->cs->flags.dlg_cancel = 0; + newstream = mail_open(stream, name, options); + nmg->tmpmbxptr = NULL; + nmg->cs = NULL; + + if(newstream){ /* if open stream, valid password */ + for(tpwc = cs->pwc; tpwc; tpwc = tpwc->next) + tpwc->validpw = 1; + } + else{ + tpwc = cs->pwc; + while(tpwc){ + if(tpwc->validpw == 0){ + dpwc = tpwc; + tpwc = tpwc->next; + if(dpwc == cs->pwc) + cs->pwc = dpwc->next; + fs_give((void **)&dpwc); + } + else + tpwc = tpwc->next; + } + } + + return (newstream); +} + + +MAILSTREAM *check_mailstream(sessionlist_s *cs) +{ + mapi_global_s *nmg; + + nmg = ms_global; + + if(!cs->open_stream){ + return(first_open(cs)); + } + cs->flags.check_stream = TRUE; + if(!mail_ping(cs->open_stream)){ + if(nmg->cs) return NULL; + cs->open_stream = mapi_mail_open(cs, cs->open_stream, + cs->currently_open ? cs->currently_open : + nmg->prcvars[INBOX_PATH]->val.p, + nmg->debug ? OP_DEBUG : NIL); + if(!cs->open_stream){ + fs_give((void **)&cs->currently_open); + cs->currently_open = NULL; + cs->dlge.edit1[0] = '\0'; + cs->dlge.edit2[0] = '\0'; + cs->flags.check_stream = FALSE; + return NULL; + } + } + cs->flags.check_stream = FALSE; + return cs->open_stream; +} + +/* pretty much changes a string to an integer, + * but if it is not a valid message number, then 0 is returned + */ +unsigned long convert_to_msgno(char *msgid) +{ + unsigned long place_holder = 1, msgno = 0; + int i, len; + + len = strlen(msgid); + for(i = 0; i < len; i++){ + if(msgid[len-1-i] - '0' < 0 || msgid[len-1-i] - '0' > 9) + return 0; + msgno += (msgid[len - 1 - i] - '0')*place_holder; + place_holder *= 10; + } + + return msgno; +} + +/* + * Lookup file's mimetype by its file extension + * fn - filename + * body - body in which to store new type, subtype + * + * A mime type is ALWAYS set + * + * Returns 0 if the file extension was found and mimetype was set accordingly + * 1 if otherwise + */ +int lookup_file_mime_type(char *fn, BODY *body) +{ + char *p, subkey[1024], val[1024]; + DWORD dtype, vallen = 1024; + HKEY hKey; + int i, rv = 0; + + if(body->subtype) + fs_give((void **)&body->subtype); + if((p = strrchr(fn, '.')) && p[1]){ + sprintf(subkey, "%.1020s", p); + if(RegOpenKeyEx(HKEY_CLASSES_ROOT, subkey, 0, KEY_READ, &hKey) == ERROR_SUCCESS){ + if(RegQueryValueEx(hKey, "Content Type", NULL, &dtype, val, &vallen) == ERROR_SUCCESS){ + RegCloseKey(hKey); + if((p = strrchr(val, '/')) && p[1]){ + *(p++) = '\0'; + body->subtype = mstrdup(p); + for(i=0; (i <= TYPEMAX) && body_types[i] && _stricmp(val, body_types[i]); i++); + if(i > TYPEMAX) + i = TYPEOTHER; + else if(!body_types[i]) + body_types[i] = mstrdup(val); + body->type = i; + return 0; + } + } + } + } + body->type = TYPEAPPLICATION; + body->subtype = "octet-stream"; + return 1; +} + +int LookupMIMEFileExt(char *val, char *mime_type, DWORD *vallen) +{ + HKEY hKey; + DWORD dtype; + LONG rv = !ERROR_SUCCESS; + char subkey[1024]; + + sprintf(subkey, "MIME\\Database\\Content Type\\%s", mime_type); + if(RegOpenKeyEx(HKEY_CLASSES_ROOT, subkey, 0, KEY_READ, &hKey) == ERROR_SUCCESS){ + rv = RegQueryValueEx(hKey,"extension",NULL, &dtype, val, vallen); + RegCloseKey(hKey); + } + + return(rv); +} + +/* + * xlate_out() - xlate_out the given character + */ +char +xlate_out(c) + char c; +{ + register int dti; + register int xch; + + if((c >= FIRSTCH) && (c <= LASTCH)){ + xch = c - (dti = xlate_key); + xch += (xch < FIRSTCH-TABSZ) ? 2*TABSZ : (xch < FIRSTCH) ? TABSZ : 0; + dti = (xch - FIRSTCH) + dti; + dti -= (dti >= 2*TABSZ) ? 2*TABSZ : (dti >= TABSZ) ? TABSZ : 0; + xlate_key = dti; + return(xch); + } + else + return(c); +} + +/* return TRUE if the pwd is found, FALSE if not */ +int in_passfile(sessionlist_s *cs) +{ + mapi_global_s *nmg; + char *tf, *tp, *ui[4], tmp[1024], *dir; + int i, j, n; + FILE *tfd; + + nmg = ms_global; + + if(*nmg->pinerc == '{') + dir = nmg->pineExe; + else + dir = nmg->pinerc; + + /* if(nmg->flags.passfile_checked) return FALSE; */ + if(!(tf = (char *)fs_get(sizeof(char)*(strlen(dir) + strlen("pine.pwd") + 1)))){ + /* nmg->flags.passfile_checked = TRUE; */ + return FALSE; + } + strcpy(tf,dir); + if(tp = strrchr(tf, '\\')){ + tp++; + strcpy(tp, "pine.pwd"); + } + else /* don't know when this will ever happen */ + strcpy(tf, "pine.pwd"); + if(_access(tf, 00) == 0){ + if(MSDEBUG) + fprintf(nmg->dfd,"found %s for passwords\r\n", tf); + if(!(tfd = fopen(tf,"r"))){ + fs_give((void **)&tf); + /* nmg->flags.passfile_checked = TRUE; */ + return FALSE; + } + else{ + for(n = 0; fgets(tmp, 1024, tfd); n++){ + /*** do any necessary DEcryption here ***/ + xlate_key = n; + for(i = 0; tmp[i]; i++) + tmp[i] = xlate_out(tmp[i]); + + if(i && tmp[i-1] == '\n') + tmp[i-1] = '\0'; /* blast '\n' */ + + ui[0] = ui[1] = ui[2] = ui[3] = NULL; + for(i = 0, j = 0; tmp[i] && j < 4; j++){ + for(ui[j] = &tmp[i]; tmp[i] && tmp[i] != '\t'; i++) + ; + + if(tmp[i]) + tmp[i++] = '\0'; + } + + if(ui[0] && ui[1] && ui[2]){ + if(strcmp(ui[2], cs->mb->host) == 0){ + if((cs->mb->altflag && ui[3] && *ui[3] == '1') + || (!cs->mb->altflag && (!ui[3] || (*ui[3] == '0')))){ + if(strcmp(ui[1], *cs->mb->user ? cs->mb->user + : nmg->prcvars[USER_ID]->val.p) == 0){ + /* winner */ + strcpy(cs->dlge.edit1, *cs->mb->user ? cs->mb->user + : nmg->prcvars[USER_ID]->val.p); + strcpy(cs->dlge.edit2, ui[0]); + fclose(tfd); + fs_give((void **)&tf); + /* nmg->flags.passfile_checked = TRUE; */ + return TRUE; + } + } + } + } + } + fclose(tfd); + fs_give((void **)&tf); + } + } + else{ + fs_give((void **)&tf); + /* nmg->flags.passfile_checked = TRUE; */ + return FALSE; + } + /* nmg->flags.passfile_checked = TRUE; */ + return FALSE; +} + +int get_suggested_directory(char *dir) +{ + char *tmpdir; + + if(tmpdir = getenv("TEMP")){ + strcpy(dir, tmpdir); + return TRUE; + } + else if(tmpdir = getenv("TMP")){ + strcpy(dir, tmpdir); + return TRUE; + } + else if(ms_global && ms_global->attachDir){ + strcpy(dir, ms_global->attachDir); + return TRUE; + } + else{ /* should NEVER get here */ + strcpy(dir, "C:\\"); + return TRUE; + } + return FALSE; +} + + +/* return TRUE if file_ext is modified, FALSE if not */ +int get_suggested_file_ext(char *file_ext, PART *part, DWORD *file_extlen) +{ + char mime_type[1024], *tmp_ext; + int rv = !ERROR_SUCCESS; + PARAMETER *param; + + if(part->body.subtype){ + sprintf(mime_type, "%s/%s", body_types[part->body.type], part->body.subtype); + rv = LookupMIMEFileExt(file_ext, mime_type, file_extlen); + } + if(rv == ERROR_SUCCESS) + return TRUE; + else{ + param = part->body.parameter; + while(param && (_stricmp("NAME", param->attribute))) + param = param->next; + if(!param){ + if(part->body.type == TYPEMESSAGE){ + /* don't try to recurse through attached messages yet */ + strcpy(file_ext, ".txt"); + return TRUE; + } + } + tmp_ext = strrchr(param->value, (int)'.'); + if(!tmp_ext) return FALSE; + strcpy(file_ext, tmp_ext); + } + return TRUE; +} + +/* return -1 for failure */ +int InitDebug() +{ + char path[1024]; + + if(!ms_global){ + if((ms_global = new_mapi_global()) == NULL) return -1; + } + /* + * if debug file exists, turn on debugging mode + */ + if(ms_global->debug == 1) /* debug file already initialized, somehow */ + return 1; + get_suggested_directory(path); + if(path[strlen(path-1)] != '\\') + strcat(path, "\\"); + strcat(path, "mapi_debug.txt"); + if(_access(path, 00) == 0){ + ms_global->debug = 1; + } + else{ + get_suggested_directory(path); + if(path[strlen(path-1)] != '\\') + strcat(path, "\\"); + strcat(path, "mapisend"); + if(_access(path, 00) == 0){ + ms_global->debug = 1; + } + } + + if(ms_global->debug){ + ms_global->dfd = fopen(path, "wb"); + if(!ms_global->dfd){ + ErrorBox("MAPISendMail: debug off: can't open debug file %.200s", + path); + ms_global->debug = 0; /* can't open the file, turn off debugging */ + } + else if(ms_global->debug == 1){ + ms_global->debugFile = (char *)fs_get((1+strlen(path))*sizeof(char)); + strcpy(ms_global->debugFile, path); + } + } + + if(ms_global->debug && (ms_global->dfd == NULL)) + ms_global->debug = 0; + + return ms_global->debug; +} + +int GetPineData() +{ + HKEY pineKey; + BYTE pineKeyData[1024]; + DWORD pineKeyDataSize; + DWORD pineKeyDataType; + char *defPath = "c:\\pine\\pine.exe"; + char *pineExe = strrchr(defPath, '\\')+1; + char *freepineExe = NULL; + char *defAttachDir = "c:\\tmp"; + char *penv = NULL; + + /* + * get name of and path to pine.exe from registry + */ + if (RegOpenKeyEx( + HKEY_LOCAL_MACHINE, + "SOFTWARE\\University of Washington\\Alpine\\1.0", + 0, + KEY_QUERY_VALUE, + &pineKey) == ERROR_SUCCESS) { + pineKeyDataSize = sizeof(pineKeyData); + if (RegQueryValueEx( + pineKey, + "PineEXE", + 0, + &pineKeyDataType, + pineKeyData, + &pineKeyDataSize) == ERROR_SUCCESS) { + freepineExe = (char *)fs_get((pineKeyDataSize + 1) * sizeof(char)); + if ((pineExe = freepineExe) != NULL) { + strcpy(pineExe, pineKeyData); + } + else { + ErrorBox("MAPISendMail: can't fs_get %d bytes for pineExe", + pineKeyDataSize); + return 0; + } + if (MSDEBUG) { + fprintf(ms_global->dfd,"pine.exe pineKeyDataSize: %d\r\n", pineKeyDataSize); + fprintf(ms_global->dfd,"pine.exe pineKeyData: %s\r\n", pineKeyData); + } + } + pineKeyDataSize = sizeof(pineKeyData); + if (RegQueryValueEx( + pineKey, + "pinedir", + 0, + &pineKeyDataType, + pineKeyData, + &pineKeyDataSize) == ERROR_SUCCESS) { + ms_global->pineExe = (char *)fs_get(sizeof(char)*(pineKeyDataSize+strlen(pineExe))); + if (ms_global->pineExe) { + strncpy(ms_global->pineExe, pineKeyData, pineKeyDataSize); + strcat(ms_global->pineExe, pineExe); + } + else { + ErrorBox("MAPISendMail: can't fs_get %d bytes for av[0]", + pineKeyDataSize); + return 0; + } + if (MSDEBUG) { + fprintf(ms_global->dfd,"pine.exe pineKeyDataSize: %d\r\n", pineKeyDataSize); + fprintf(ms_global->dfd,"pine.exe pineKeyData: %s\r\n", pineKeyData); + } + } + RegCloseKey(pineKey); + } + if(!ms_global->pineExe){ + ms_global->pineExe = (char *)fs_get((1+strlen(defPath))*sizeof(char)); + if(!ms_global->pineExe){ + ErrorBox("Couldn't fs_get for %s","pineExe"); + return 0; + } + else + strcpy(ms_global->pineExe, defPath); + } + + if(freepineExe) + ms_global->pineExeAlt = freepineExe; + else{ + ms_global->pineExeAlt = (char *)fs_get((strlen(strrchr(defPath, '\\')+1)+1)*sizeof(char)); + if(!ms_global->pineExeAlt){ + ErrorBox("Couldn't fs_get for %s","pineExeAlt"); + return 0; + } + else + strcpy(ms_global->pineExeAlt, strrchr(defPath, '\\')+1); + } + + /* + * get path to pinerc from registry + */ + if (RegOpenKeyEx( + HKEY_CURRENT_USER, + "Software\\University of Washington\\Alpine\\1.0", + 0, + KEY_QUERY_VALUE, + &pineKey) == ERROR_SUCCESS) { + pineKeyDataSize = sizeof(pineKeyData); + if( RegQueryValueEx( + pineKey, + "PineRC", + 0, + &pineKeyDataType, + pineKeyData, + &pineKeyDataSize) == ERROR_SUCCESS) { + if(*pineKeyData != '{' || ms_global->pineExe) + ms_global->attachDir = (char *)fs_get(sizeof(char)*(*pineKeyData == '{' ? + pineKeyDataSize + 1 : + strlen(ms_global->pineExe)+1)); + ms_global->pinerc = (char *)fs_get(pineKeyDataSize); + if(ms_global->attachDir){ + char *p; + if(*pineKeyData != '{'){ + strncpy(ms_global->attachDir, pineKeyData, pineKeyDataSize); + ms_global->attachDir[pineKeyDataSize] = '\0'; + } + else + strcpy(ms_global->attachDir, ms_global->pineExe); + p = strrchr(ms_global->attachDir, '\\'); + if (p) *p = '\0'; + } + if(ms_global->pinerc) + strncpy(ms_global->pinerc, pineKeyData, pineKeyDataSize); + else { + ErrorBox("MAPISendMail: can't fs_get %d bytes for pinercPath", + pineKeyDataSize); + return 0; + } + if (MSDEBUG) { + fprintf(ms_global->dfd, "pinerc pineKeyDataSize: %d\r\n", pineKeyDataSize); + fprintf(ms_global->dfd, "pinerc pineKeyData: %s\r\n", pineKeyData); + fprintf(ms_global->dfd, "attachDir: %s\r\n", + ms_global->attachDir ? ms_global->attachDir : + "NOT YET DEFINED"); + } + } + pineKeyDataSize = sizeof(pineKeyData); + if( RegQueryValueEx( + pineKey, + "PineConf", + 0, + &pineKeyDataType, + pineKeyData, + &pineKeyDataSize) == ERROR_SUCCESS){ + ms_global->pineconf = mstrdup(pineKeyData); + msprint1("ms_global->pineconf: %s (due to Registry setting)\r\n", ms_global->pineconf); + } + RegCloseKey(pineKey); + } + + if(ms_global->attachDir == NULL){ + if(ms_global->attachDir = (char *)fs_get((strlen(defAttachDir)+1)*sizeof(char))) + strcpy(ms_global->attachDir, defAttachDir); + else + ErrorBox("Can't find TEMP directory for %s!","attachments"); + } + + + if(penv = getenv("PINERC")){ + if(ms_global->pinerc) + fs_give((void **)&ms_global->pinerc); + if(ms_global->pinerc = (char *)fs_get((strlen(penv)+1)*sizeof(char))) + strcpy(ms_global->pinerc, penv); + else + ErrorBox("Couldn't fs_get for %s", "pinerc"); + } + if(penv = getenv("PINECONF")){ + if(ms_global->pineconf) + fs_give((void **)&ms_global->pineconf); + if(ms_global->pineconf = (char *)fs_get((strlen(penv)+1)*sizeof(char))) + strcpy(ms_global->pineconf, penv); + else + ErrorBox("Couldn't fs_get for %s", "pineconf"); + } + else{ + + } + if(penv = getenv("PINERCEX")){ + if(ms_global->pinercex) + fs_give((void **)&ms_global->pinercex); + if(ms_global->pinercex = mstrdup(penv)) + strcpy(ms_global->pinercex, penv); + else + ErrorBox("Couldn't fs_get for %s", "pinercex"); + } + if(MSDEBUG){ + fprintf(ms_global->dfd,"ms_global->pineExe: %s\r\n", + (ms_global->pineExe) ? ms_global->pineExe : "NULL"); + fprintf(ms_global->dfd,"ms_global->pineExeAlt: %s\r\n", + ms_global->pineExeAlt ? ms_global->pineExeAlt : "NULL"); + fprintf(ms_global->dfd,"ms_global->attachDir: %s\r\n", + ms_global->attachDir ? ms_global->attachDir : "NULL"); + fprintf(ms_global->dfd,"ms_global->pinerc: %s\r\n", + ms_global->pinerc ? ms_global->pinerc : "NULL"); + fprintf(ms_global->dfd,"ms_global->pineconf: %s\r\n", + ms_global->pinerc ? ms_global->pineconf : "NULL"); + fprintf(ms_global->dfd,"ms_global->pinercex: %s\r\n", + ms_global->pinerc ? ms_global->pinercex : "NULL"); + } + return 1; +} + +BOOL APIENTRY DllMain( + HANDLE hInst, + DWORD ul_reason_being_called, + LPVOID lpReserved) +{ + switch(ul_reason_being_called){ + case DLL_THREAD_ATTACH: + /* if(ms_global) + * return 1; + */ + case DLL_PROCESS_ATTACH: + if(!ms_global) + ms_global = new_mapi_global(); + if(!ms_global) return 0; + ms_global->attached++; + ms_global->mhinst = hInst; + if(InitDebug() == -1){ + ErrorBox("Mapi32.dll could not %s", "initialize"); + return 0; + } + if(MSDEBUG && ms_global->attached <= 1){ + time_t now; + struct tm *tm_now; + extern char datestamp[], hoststamp[]; + + now = time((time_t *)0); + tm_now = localtime(&now); + fprintf(ms_global->dfd, "pmapi32.dll for Alpine Version 2.10r\n"); + fprintf(ms_global->dfd, " Build date: %s\r\n", datestamp); + fprintf(ms_global->dfd, + " please report all bugs to alpine-contact@u.washington.edu\r\n"); + if(tm_now) + fprintf(ms_global->dfd, + "Created: %2.2d:%2.2d:%2.2d %d/%d/%d\r\n", + tm_now->tm_hour, tm_now->tm_min, tm_now->tm_sec, + tm_now->tm_mon+1, tm_now->tm_mday, tm_now->tm_year+1900); + + fprintf(ms_global->dfd, "\r\n\r\n"); + } + DEBUG_WRITE("%s called. Debug initialized (in DllMain)\r\n", + ul_reason_being_called == DLL_PROCESS_ATTACH ? + "DLL_PROCESS_ATTACH":"DLL_THREAD_ATTACH"); + GetPineData(); +#include "../c-client-dll/linkage.c" + break; + case DLL_PROCESS_DETACH: + case DLL_THREAD_DETACH: + DEBUG_WRITE("\r\n%s called\r\n", + ul_reason_being_called == DLL_PROCESS_DETACH ? + "DLL_PROCESS_DETACH" : "DLL_THREAD_DETACH"); + ms_global->attached--; + /* if(ms_global->open_stream) + * ms_global->open_stream = mail_close_full(ms_global->open_stream, NIL); + */ + if(ms_global->attached <= 0 && + ul_reason_being_called == DLL_PROCESS_DETACH){ + if(MSDEBUG) + fprintf(ms_global->dfd, + "detaching last thread/process. freeing mapi global struct\r\n"); + free_mapi_global(ms_global); + } + break; + } + return 1; +} + +static char *V="\r\n@(#) Alpine Simple Mapi Library Ver. 1.3\r\n"; + +int +UnderlineSpace(char *s) +{ + char *p; + + if(p = strrchr(s, '\\')) + s = p++; + + for(; *s; s++) + if(*s == ' ') + *s = '_'; + return 1; +} + +/* + * Given source file name and destination directory, make a binary copy + * of the file and return the full name of the copy (mangled as necessary + * to avoid conflicts). The return value will be a fs_get'd string + */ +char * +TmpCopy(char *srcFile, int is_pinerc) +{ + char *dstName; /* constructed and fs_get'd full output pathname */ + char *srcTail; /* last component of source pathname */ + char *srcExt; /* extension, if any, of srcTail */ + char dstDir[1024]; + int i, cnt, c, len, spc = 0; + FILE *sfd, *dfd; + + if (!srcFile) { + ErrorBox("TmpCopy: srcFile is %s", "NULL"); + return NULL; + } + if(is_pinerc){ + len = strlen(srcFile); + for(i = 0; i < len; i++){ + if(srcFile[i] == ' ') spc = 1; + } + if(spc == 0) return mstrdup(srcFile); + } + + get_suggested_directory(dstDir); + if (!dstDir) { + ErrorBox("TmpCopy: dstDir is %s", "NULL"); + return NULL; + } + + dstName = (char *)fs_get(sizeof(char)*(strlen(srcFile) + 5 + + max(strlen(dstDir), strlen(PINERC_FILE)))); + + if (dstName == NULL) { + ErrorBox("TmpCopy: can't fs_get space %d bytes for dstName", + strlen(srcFile)+5+max(strlen(dstDir),strlen(PINERC_FILE))); + return NULL; + } + + if(!is_pinerc){ + srcTail = strrchr(srcFile, '\\'); + if (srcTail) + ++srcTail; + else + srcTail = srcFile; + + srcExt = strrchr(srcTail, '.'); + + sfd = fopen(srcFile, "rb"); + if (sfd == NULL) { + ErrorBox("TmpCopy: can't open %.200s for reading", srcFile); + fs_give((void **)&dstName); + return NULL; + } + + i = sprintf(dstName, "%s%s%s", dstDir, + dstDir[strlen(dstDir)-1] == '\\' ? "" : "\\", + srcTail); + UnderlineSpace(dstName); + for (cnt = 0; cnt < 1000; ++cnt) { + int handle = _open(dstName, _O_CREAT|_O_EXCL , _S_IREAD|_S_IWRITE); + if (handle != -1) { + if (_close(handle)) /* this shouldn't be able to happen */ + ErrorBox("TmpCopy: _close of new %.200s failed", dstName); + dfd = fopen(dstName, "wb"); + if (dfd) break; + } + if (srcExt) + sprintf(dstName+i-strlen(srcExt), "%03d%s", cnt, srcExt); + else + sprintf(dstName+i, "%03d", cnt); + } + if (dfd == NULL) { + ErrorBox("TmpCopy: can't create anything like %.200s", dstName); + fclose(sfd); + fs_give((void **)&dstName); + return NULL; + } + } + else{ /* is_pinerc */ + i = sprintf(dstName, "%s%s%s", dstDir, + dstDir[strlen(dstDir)-1] == '\\' ? "" : "\\", + PINERC_FILE); + dfd = fopen(dstName, "wb"); + if(!dfd){ + ErrorBox("Couldn't create temp %s for pine", "pinerc"); + fs_give((void **)&dstName); + return NULL; + } + sfd = fopen(srcFile, "rb"); + if (sfd == NULL) { + ErrorBox("TmpCopy: can't open %.200s for reading", srcFile); + fclose(dfd); + fs_give((void **)&dstName); + return NULL; + } + } + c = fgetc(sfd); + while(feof(sfd) == 0) { + putc(c, dfd); + c = fgetc(sfd); + } + if (ferror(dfd)) { + ErrorBox("TmpCopy: write error on %.200s", dstName); + fs_give((void **)&dstName); + fclose(dfd); + return NULL; + } + if (ferror(sfd)) { + ErrorBox("TmpCopy: read error on %.200s", srcFile); + fs_give((void **)&dstName); + fclose(sfd); + return NULL; + } + if (fclose(sfd)) { + ErrorBox("TmpCopy: fclose error on %.200s", srcFile); + } + if (fclose(dfd)) { + ErrorBox("TmpCopy: fclose error on %.200s", dstName); + } + + return dstName; +} + +int send_documents(char *files, char sep) +{ + int ac, i, tmplen, j; + char **av, *tmpfiles, *file, *tmpfree; + mapi_global_s *nmg; + + nmg = ms_global; + ac = 3; + tmplen = strlen(files); + tmpfiles = (char *)fs_get(sizeof(char)*(tmplen + 1)); + strcpy(tmpfiles,files); + for(i = 0; i <= tmplen; i++){ + if(files[i] == sep || files[i] == '\0') + ac += 2; + } + ac += 2; /* just for safe measure */ + av = (char **)fs_get(ac * sizeof(char *)); + if(nmg->pinerc){ + av[1] = mstrdup("-p"); + /* copy pinerc to temp directory just in case it too + * has spaces in its directory + */ + if(tmpfree = TmpCopy(nmg->pinerc, IS_PINERC)){ + av[2] = quote(tmpfree); + fs_give((void **)&tmpfree); + } + else + av[2] = quote(nmg->pinerc); + } + for(i = 0, j = 3, file = tmpfiles; i <= tmplen; i++){ + if(tmpfiles[i] == sep || i == tmplen){ + tmpfiles[i] = '\0'; + if(i - (file - tmpfiles) > 1){ + tmpfree = TmpCopy(file, NOT_PINERC); + if(tmpfree){ + av[j++] = mstrdup("-attach_and_delete"); + av[j++] = quote(tmpfree); + fs_give((void **)&tmpfree); + } + } + } + } + av[j] = NULL; + av[0] = quote(nmg->pineExe); + if(MSDEBUG){ + fprintf(ms_global->dfd, "spawning %s (else %s):\r\n", + ms_global->pineExe, ms_global->pineExeAlt); + fprintf(nmg->dfd, " av:\r\n"); + for(i = 0; av[i]; i++) + fprintf(nmg->dfd, " av[%d]: %s\r\n", i, av[i]); + } + + /* clean up quote()'s */ + if (_spawnvp(_P_NOWAIT, ms_global->pineExe, av) == -1 && + _spawnvp(_P_NOWAIT, ms_global->pineExeAlt, av) == -1){ + ErrorBox("MAPISendMail: _spawnvp of %s failed", ms_global->pineExe); + if(MSDEBUG) + fprintf(ms_global->dfd, "_spawnvp %s and %s failed\r\n", + ms_global->pineExe,ms_global->pineExeAlt); + return(MAPI_E_FAILURE); + } + for(i = 0; av[i]; i++) + fs_give((void **)&av[i]); + fs_give((void **)&av); + return SUCCESS_SUCCESS; +} + +char * +message_structure_to_mailto_url(lpMapiMessage lpm) +{ + char **keyvals, **keyvalp, *url; + int keyvallen; + unsigned long i, url_len = 0; + + if(lpm == NULL) + return NULL; + + keyvallen = lpm->nRecipCount + 4; /* subject + body + from + recips + NULL */ + keyvals = (char **)fs_get(keyvallen * sizeof(char *)); + keyvalp = keyvals; + + for(i = 0; i < lpm->nRecipCount; i++) + *keyvalp++ = encode_mailto_addr_keyval(&lpm->lpRecips[i]); + if(lpm->lpszSubject) + *keyvalp++ = encode_mailto_keyval("subject", lpm->lpszSubject); + if(lpm->lpOriginator) + *keyvalp++ = encode_mailto_addr_keyval(lpm->lpOriginator); + if(lpm->lpszNoteText) + *keyvalp++ = encode_mailto_keyval("body", lpm->lpszNoteText); + *keyvalp = NULL; + + if(*keyvals == NULL){ + fs_give((void **)&keyvals); + return(NULL); + } + + url_len = keyvallen + 10; /* mailto url extra chars */ + for(keyvalp = keyvals; *keyvalp; keyvalp++) + url_len += strlen(*keyvalp); + + url = (char *)fs_get(url_len * sizeof(char)); + sprintf(url, "mailto:?"); + for(keyvalp = keyvals; *keyvalp; keyvalp++){ + strcat(url, *keyvalp); + if(*(keyvalp+1)) + strcat(url, "&"); + fs_give((void **)&(*keyvalp)); + } + fs_give((void **)&keyvals); + return url; +} + +char * +encode_mailto_addr_keyval(lpMapiRecipDesc lpmr) +{ + ADDRESS *adr = NULL; + char *addr, *retstr; + int use_quotes = 0; + + adr = mapirecip2address(lpmr); + addr = (char *)fs_get((size_t)est_size(adr)); + addr[0] = '\0'; + rfc822_write_address(addr, adr); + mail_free_address(&adr); + + retstr = encode_mailto_keyval(lpmr->ulRecipClass == MAPI_CC ? "cc" + : (lpmr->ulRecipClass == MAPI_BCC ? "bcc" + : (lpmr->ulRecipClass == MAPI_ORIG ? "from" + : "to")), + addr); + fs_give((void **)&addr); + return(retstr); +} + + + +/* + * Hex conversion aids from alpine.h + */ +#define HEX_ARRAY "0123456789ABCDEF" +#define HEX_CHAR1(C) HEX_ARRAY[((C) & 0xf0) >> 4] +#define HEX_CHAR2(C) HEX_ARRAY[(C) & 0xf] + +/* strings.c macros */ +#define C2XPAIR(C, S) { \ + *(S)++ = HEX_CHAR1(C); \ + *(S)++ = HEX_CHAR2(C); \ + } + +#define RFC1738_SAFE "$-_.+" /* "safe" */ +#define RFC1738_EXTRA "!*'()," /* "extra" */ + +/* adapted from rfc1738_encode_mailto */ +char * +encode_mailto_keyval(char *key, char* val) +{ + char *d, *ret = NULL, *v = val; + + if(key && val){ + ret = (char *)fs_get(sizeof(char) * (strlen(key) + (3*strlen(val)) + 2)); + strcpy(ret, key); + d = ret + strlen(key); + *d++ = '='; + while(*v){ + if(isalnum((unsigned char)*v) + || strchr(RFC1738_SAFE, *v) + || strchr(RFC1738_EXTRA, *v)) + *d++ = *v++; + else{ + *d++ = '%'; + C2XPAIR(*v, d); + v++; + } + } + *d = '\0'; + } + + return(ret); +} + +unsigned long +send_msg_nodlg(LHANDLE lhSession, ULONG ulUIParam, lpMapiMessage lpMessage, + FLAGS flFlags, ULONG ulReserved) +{ + sessionlist_s *cs; + int tsession = 0, orig_in_recip = 0; + unsigned long i, orig_index; + ADDRESS *tadr = NULL, *tadr2 = NULL; + ENVELOPE *env = NULL; + BODY *body = NULL; + mapi_global_s *nmg = ms_global; + SENDSTREAM *sending_stream = NULL; + unsigned long rv; + time_t now; + struct tm *tm_now; + char *p = NULL; + + if(nmg->pmapi_send_behavior == PMSB_NEVER_SEND) + return MAPI_E_USER_ABORT; + else if(nmg->pmapi_send_behavior == PMSB_ALWAYS_PROMPT){ + if(MessageBox(NULL, "Really Send Message?", "pmapi32.dll", MB_YESNO|MB_ICONQUESTION) == IDNO) + return MAPI_E_USER_ABORT; + } + if((flFlags & MAPI_NEW_SESSION) || lhSession == 0){ + cs = new_sessionlist(); + tsession = 1; + } + else{ + cs = get_session(lhSession); + if(!cs) + return MAPI_E_INVALID_SESSION; + } + cs->flags.mapi_logon_ui = (flFlags & MAPI_LOGON_UI) || (flFlags & MAPI_DIALOG) ? 1 : 0; + if(InitPineSpecific(cs) == -1){ + rv = MAPI_E_LOGIN_FAILURE; + goto smn_cleanup; + } + msprint("Preparing to Send Message with no dialogs...\r\n"); + /* Make an envelope */ + env = (ENVELOPE *)fs_get(sizeof(ENVELOPE)); + memset(env, 0, sizeof(ENVELOPE)); + if(lpMessage->lpszSubject){ + p = rfc1522_encode(tmp_20k_buf, SIZEOF_20KBUF, lpMessage->lpszSubject, + nmg->prcvars[CHARACTER_SET]->val.p); + env->subject = mstrdup(p); + if(MSDEBUG) + fprintf(ms_global->dfd, " Subject: %s\r\n", env->subject); + } + /* + * Since it is "DateReceived", I think the right thing to do is ignore it, + * since we're sending, not receiving. + */ + rfc822_date(tmp_20k_buf); + env->date = mstrdup(tmp_20k_buf); + msprint1(" Date: %s\r\n", env->date); + env->message_id = pmapi_generate_message_id(); + msprint1(" Message-Id: %s\r\n", env->message_id); + + for(i = 0; i < lpMessage->nRecipCount; i++){ + if((&lpMessage->lpRecips[i])->ulRecipClass == MAPI_ORIG){ + orig_in_recip = 1; + orig_index = i; + } + } + + if(lpMessage->lpOriginator || orig_in_recip){ + if((env->from = mapirecip2address(lpMessage->lpOriginator + ? lpMessage->lpOriginator + : (&lpMessage->lpRecips[orig_index]))) + == NULL){ + rv = MAPI_E_INVALID_RECIPS; + goto smn_cleanup; + } + if(MSDEBUG){ + sprintf(tmp_20k_buf, "%.100s <%.100s@%.100s>", env->from->personal ? env->from->personal + : "", env->from->mailbox ? env->from->mailbox : "", + env->from->host ? env->from->host : ""); + msprint1("From: %s\r\n", tmp_20k_buf); + } + } + else if(nmg->prcvars[USER_ID]->val.p && nmg->prcvars[USER_DOMAIN]->val.p){ + /* + * judgment call: I guess we'll try to generate the from header if it's not + * given to us + */ + env->from = mail_newaddr(); + if(nmg->prcvars[PERSONAL_NAME]->val.p){ + p = rfc1522_encode(tmp_20k_buf, SIZEOF_20KBUF, nmg->prcvars[PERSONAL_NAME]->val.p, + nmg->prcvars[CHARACTER_SET]->val.p); + env->from->personal = mstrdup(p); + } + env->from->mailbox = mstrdup(nmg->prcvars[USER_ID]->val.p); + env->from->host = mstrdup(nmg->prcvars[USER_DOMAIN]->val.p); + if(MSDEBUG){ + sprintf(tmp_20k_buf, "%.100s <%.100s@%.100s>", env->from->personal ? env->from->personal + : "", env->from->mailbox ? env->from->mailbox : "", + env->from->host ? env->from->host : ""); + msprint1("From: %s\r\n", tmp_20k_buf); + } + } + for(i = 0; i < lpMessage->nRecipCount; i++){ + if((tadr = mapirecip2address(&lpMessage->lpRecips[i])) == NULL){ + rv = MAPI_E_INVALID_RECIPS; + goto smn_cleanup; + } + switch (lpMessage->lpRecips[i].ulRecipClass) { + case MAPI_TO: + case MAPI_ORIG: + if(!env->to) + env->to = tadr; + else{ + for(tadr2 = env->to; tadr2->next; tadr2 = tadr2->next); + tadr2->next = tadr; + } + msprint(" To: "); + break; + case MAPI_CC: + if(!env->cc) + env->cc = tadr; + else{ + for(tadr2 = env->cc; tadr2->next; tadr2 = tadr2->next); + tadr2->next = tadr; + } + msprint(" Cc: "); + break; + case MAPI_BCC: + if(!env->bcc) + env->bcc = tadr; + else{ + for(tadr2 = env->bcc; tadr2->next; tadr2 = tadr2->next); + tadr2->next = tadr; + } + msprint(" Bcc: "); + break; + default: + rv = MAPI_E_INVALID_RECIPS; + goto smn_cleanup; + break; + } + if(MSDEBUG){ + sprintf(tmp_20k_buf, "%.100s <%.100s@%.100s>", tadr->personal ? tadr->personal + : "", tadr->mailbox ? tadr->mailbox : "", + tadr->host ? tadr->host : ""); + msprint1("%s\r\n", tmp_20k_buf); + } + } + /* Now we have an envelope, let's make us a body */ + if(lpMessage->lpszNoteText == NULL) + msprint("Empty Message Text\r\n"); + body = mail_newbody(); + if(lpMessage->nFileCount){ + PART *p; + struct _stat sbuf; + unsigned long fsize, n; + FILE *sfd; + char c, *fn; + + msprint1("Number of files to be Attached: %d\r\n", (void *)lpMessage->nFileCount); + body->type = TYPEMULTIPART; + body->nested.part = mail_newbody_part(); + p = body->nested.part; + set_text_data(&p->body, lpMessage->lpszNoteText ? lpMessage->lpszNoteText + : ""); + + for(i = 0; i < lpMessage->nFileCount; i++){ + p->next = mail_newbody_part(); + p = p->next; + p->body.encoding = ENCBINARY; + if(lpMessage->lpFiles[i].lpszPathName == NULL) + return(MAPI_E_FAILURE); + if(lpMessage->lpFiles[i].lpszFileName == NULL + || lpMessage->lpFiles[i].lpszFileName[0] == '\0'){ + fn = strrchr(lpMessage->lpFiles[i].lpszPathName, '\\'); + if(!fn) + fn = lpMessage->lpFiles[i].lpszPathName; + else + fn++; + } + else + fn = lpMessage->lpFiles[i].lpszFileName; + if(lookup_file_mime_type(fn, &p->body) && (fn == lpMessage->lpFiles[i].lpszFileName)) + lookup_file_mime_type(lpMessage->lpFiles[i].lpszPathName, &p->body); + msprint1(" Attaching file %s;", lpMessage->lpFiles[i].lpszPathName); + if(_stat(lpMessage->lpFiles[i].lpszPathName, &sbuf)) + return(MAPI_E_FAILURE); + fsize = sbuf.st_size; + if((sfd = fopen(lpMessage->lpFiles[i].lpszPathName, "rb")) == NULL) + return(MAPI_E_FAILURE); + p->body.contents.text.data = fs_get((fsize+1)*sizeof(char)); + n = 0; + c = fgetc(sfd); + while(feof(sfd) == 0){ + p->body.contents.text.data[n++] = c; + if(n > fsize){ + fsize += 20000; + fs_resize((void **)&p->body.contents.text.data, (fsize+1)*sizeof(char)); + } + c = fgetc(sfd); + } + fclose(sfd); + p->body.contents.text.data[n] = '\0'; + p->body.contents.text.size = n; + msprint1(" File size: %d\r\n", (void *)n); + if(fn){ + p->body.parameter = mail_newbody_parameter(); + p->body.parameter->attribute = mstrdup("name"); + p->body.parameter->value = mstrdup(fn); + + p->body.disposition.type = mstrdup("attachment"); + p->body.disposition.parameter = mail_newbody_parameter(); + p->body.disposition.parameter->attribute = mstrdup("filename"); + p->body.disposition.parameter->value = mstrdup(fn); + } + } + } + else { + set_text_data(body, lpMessage->lpszNoteText ? lpMessage->lpszNoteText + : ""); + msprint1(" Message Body size: %d\r\n", (void *)body->contents.text.size); + } + + if(MSDEBUG){ + now = time((time_t *)0); + tm_now = localtime(&now); + fprintf(ms_global->dfd, "%2.2d:%2.2d:%2.2d %d/%d/%d ", + tm_now->tm_hour, tm_now->tm_min, tm_now->tm_sec, + tm_now->tm_mon+1, tm_now->tm_mday, tm_now->tm_year+1900); + } + if(nmg->prcvars[SMTP_SERVER]->val.l && nmg->prcvars[SMTP_SERVER]->val.l[0] + && nmg->prcvars[SMTP_SERVER]->val.l[0][0]){ + if(MSDEBUG){ + fprintf(ms_global->dfd, "Preparing to open SMTP connection (%s ...)\r\n", + nmg->prcvars[SMTP_SERVER]->val.l[0]); + _flushall(); + } + sending_stream = mapi_smtp_open(cs, nmg->prcvars[SMTP_SERVER]->val.l, + nmg->prcfeats[ENABLE8BIT]->is_set ? SOP_8BITMIME : NIL); + } + else { + rv = MAPI_E_FAILURE; + if(MSDEBUG){ + fprintf(ms_global->dfd, "Error! No SMTP server defined!\r\n"); + } + goto smn_cleanup; + } + if(!sending_stream){ + rv = MAPI_E_FAILURE; + if(MSDEBUG){ + fprintf(ms_global->dfd, "Couldn't open SMTP connection!\r\n"); + } + goto smn_cleanup; + } + if(!smtp_mail(sending_stream, "MAIL", env, body)){ + if(MSDEBUG){ + fprintf(ms_global->dfd, "Attempt to Send Failed\r\n"); + } + rv = MAPI_E_FAILURE; + } + else { + if(MSDEBUG){ + fprintf(ms_global->dfd, "Message SENT!\r\n"); + } + if(!nmg->fccfolder) + msprint("No fcc defined\r\n"); + else { /* Now try to write to fcc */ + STRBUFFER_S *sb; + MAILSTREAM *fccstream; + STRING msg; + + msprint1("FCCing to %s\r\n", nmg->fccfolder); + sb = (STRBUFFER_S *)fs_get(sizeof(STRBUFFER_S)); + sb->buf = (char *)fs_get(20000*sizeof(char)); + sb->cur_bytes = 0; + sb->increment = 20000; + sb->bufsize = 20000; + rfc822_output(tmp_20k_buf, env, body, pmapi_soutr, sb, 1); + INIT(&msg, mail_string, (void *)sb->buf, sb->cur_bytes); + fccstream = mapi_mail_open(cs, NULL, nmg->fccfolder, ms_global->debug ? OP_DEBUG : NIL); + if(fccstream){ + if(mail_append(fccstream, nmg->fccfolder, &msg) == NIL) + msprint1("Fcc to %s failed\r\n", nmg->fccfolder); + else + msprint1("Fcc to %s SUCCEEDED\r\n", nmg->fccfolder); + mail_close(fccstream); + } + else + msprint1("Open of %s failed, abandoning FCC\r\n", nmg->fccfolder); + if(sb->buf) + fs_give((void **)&sb->buf); + if(sb) + fs_give((void **)&sb); + } + if((flFlags & MAPI_LOGON_UI) || (flFlags & MAPI_DIALOG)) + MessageBox(NULL, "Message SENT!\r\n", "pmapi32.dll", MB_OK|MB_ICONINFORMATION); + rv = SUCCESS_SUCCESS; + } + smtp_close(sending_stream); + smn_cleanup: + if(env) + mail_free_envelope(&env); + if(body) + mail_free_body(&body); + if(tsession) + fs_give((void **)&cs); + return(rv); +} + +int +set_text_data(BODY *body, char *txt) +{ + char *p; + int has_8bit = 0; + PARAMETER *pm; + + for(p = txt; *p; p++) + if(*p & 0x80) + has_8bit++; + + body->contents.text.data = mstrdup(txt); + body->contents.text.size = strlen(txt); + if(has_8bit){ + body->encoding = ENC8BIT; + if(!body->parameter) + pm = body->parameter = mail_newbody_parameter(); + else { + for(pm = body->parameter; pm->next; pm = pm->next); + pm->next = mail_newbody_parameter(); + pm = pm->next; + } + pm->attribute = mstrdup("charset"); + if(ms_global->prcvars[CHARACTER_SET]->val.p) + pm->value = mstrdup(ms_global->prcvars[CHARACTER_SET]->val.p); + else + pm->value = mstrdup("X-UNKNOWN"); + } + return 0; +} + +long +pmapi_soutr(STRBUFFER_S *s, char *str) +{ + unsigned long i; + + if(s->cur_bytes >= s->bufsize){ + fs_resize((void **)&s->buf, s->bufsize+ s->increment); + s->bufsize += s->increment; + } + for(i = 0; str[i]; i++){ + s->buf[s->cur_bytes++] = str[i]; + if(s->cur_bytes >= s->bufsize){ + fs_resize((void **)&s->buf, s->bufsize+ s->increment); + s->bufsize += s->increment; + } + } + s->buf[s->cur_bytes] = '\0'; + return T; +} + +ADDRESS * +mapirecip2address(lpMapiRecipDesc lpmrd) +{ + ADDRESS *adr = NULL; + static char *fakedomain = "@", *p; + mapi_global_s *nmg = ms_global; + + if(!lpmrd->lpszAddress) + return(NULL); + rfc822_parse_adrlist(&adr, _strnicmp(lpmrd->lpszAddress, "SMTP:", 5) == 0 + ? lpmrd->lpszAddress + 5 : lpmrd->lpszAddress, + nmg->prcvars[USER_DOMAIN]->val.p + ? nmg->prcvars[USER_DOMAIN]->val.p : fakedomain); + if(!adr) + return(NULL); + if(adr->next || adr->error){ + mail_free_address(&adr); + return(NULL); + } + + if(lpmrd->lpszName && adr->personal) + fs_give((void **)&adr->personal); + if(lpmrd->lpszName){ + p = rfc1522_encode(tmp_20k_buf, SIZEOF_20KBUF, lpmrd->lpszName, + nmg->prcvars[CHARACTER_SET]->val.p); + adr->personal = mstrdup(p); + } + return(adr); +} + +/* + * given a fs_get'd string, return a newly fs_get'd quoted copy + */ +char * +quote(char *old) +{ + char *new, *newp, *oldp; + int newSize = strlen(old)*2+3; + + if (!old) return mstrdup(old); + if(!strchr(old, ' ')) return mstrdup(old); + + newp = new = (char *)fs_get(sizeof(char)*newSize); /* worst case */ + if (new == NULL) { + ErrorBox("quote: fs_get of %d bytes failed", newSize); + return old; + } + + *newp++ = '"'; + for (oldp=old; *oldp; ++oldp) { + switch(*oldp) { + case '"': *newp++ = '\\'; /* fall through */ + default : *newp++ = *oldp; + } + } + *newp++ = '"'; + *newp = '\0'; + return(new); +} + + +int GetPCPineVersion(int *major, int *minor, int *minorminor) +{ + *major = 4; + *minor = 52; + *minorminor = 0; + + return 1; +} + +int +msprint(char *str) +{ + if(MSDEBUG) + fprintf(ms_global->dfd, "%s", str); + _flushall(); + return 0; +} + +int +msprint1(char *str, void *arg1) +{ + if(MSDEBUG) + fprintf(ms_global->dfd, str, arg1); + _flushall(); + return 0; +} + +int +msprint_message_structure(lpMapiMessage lpm) +{ + unsigned long i; + + if(MSDEBUG){ + msprint1("lpMapiMessage: %p\r\n", lpm); + if(!lpm) + return 1; + msprint1(" ulReserved: %d\r\n", (void *)lpm->ulReserved); + msprint1(" lpszSubsect: %s\r\n", lpm->lpszSubject ? lpm->lpszSubject : "(NULL)"); + msprint1(" lpszNoteText size: %d\r\n", lpm->lpszNoteText + ? (void *)strlen(lpm->lpszNoteText) : (void *)0); + if(lpm->lpszNoteText) + msprint1("\tleading text: %.10s\r\n", lpm->lpszNoteText); + msprint1(" lpszMessageType: %s\r\n", lpm->lpszMessageType ? lpm->lpszMessageType : "(NULL)"); + msprint1(" lpszDateReceived: %s\r\n", lpm->lpszDateReceived ? lpm->lpszDateReceived : "(NULL)"); + msprint1(" lpszConversationID: %s\r\n", lpm->lpszConversationID ? lpm->lpszConversationID : "(NULL)"); + msprint1(" flFlags: %d\r\n", (void *)lpm->flFlags); + msprint(" Originator:\r\n"); + msprint_recipient_structure(lpm->lpOriginator, 0); + msprint1(" nRecipCount: %d\r\n", (void *)lpm->nRecipCount); + for(i = 0; i < lpm->nRecipCount; i++) + msprint_recipient_structure(&lpm->lpRecips[i], 1); + msprint1(" nFileCount: %d\r\n", (void *)lpm->nFileCount); + for(i = 0; i < lpm->nFileCount; i++) + msprint_file_structure(&lpm->lpFiles[i]); + msprint("\r\n"); + } + return 0; +} + +int +msprint_recipient_structure(lpMapiRecipDesc lmrd, int mapi_orig_is_unexpected) +{ + if(MSDEBUG){ + msprint1(" lpMapiRecipDesc: %p\r\n", (void *)lmrd); + if(lmrd == NULL) + return 1; + msprint1(" ulReserved: %d\r\n", (void *)lmrd->ulReserved); + msprint1(" ulRecipClass: %s\r\n", lmrd->ulRecipClass == MAPI_ORIG ? "MAPI_ORIG" + : lmrd->ulRecipClass == MAPI_TO ? "MAPI_TO" : lmrd->ulRecipClass == MAPI_CC + ? "MAPI_CC" : "MAPI_BCC"); + if(mapi_orig_is_unexpected && lmrd->ulRecipClass == MAPI_ORIG){ + msprint(" # NOTE: it is seemingly strange behavior that a MAPI client would use\r\n # MAPI_ORIG instead of the lpOriginator. This may result in unexpected behavior.\r\n"); + } + msprint1(" lpszName: %s\r\n", lmrd->lpszName ? lmrd->lpszName : "(NULL)"); + msprint1(" lpszAddress: %s\r\n", lmrd->lpszAddress ? lmrd->lpszAddress : "(NULL)"); + msprint1(" ulEIDSize: %p\r\n", (void *)lmrd->ulEIDSize); + msprint1(" lpEntryID: %p\r\n", (void *)lmrd->lpEntryID); + } + return 0; +} + + +int +msprint_file_structure(lpMapiFileDesc lmfd) +{ + if(MSDEBUG){ + msprint1(" lpMapiFileDesc: %p\r\n", (void *)lmfd); + if(lmfd == NULL) + return 1; + msprint1(" ulReserved: %d\r\n", (void *)lmfd->ulReserved); + msprint1(" flFlags: %d\r\n", (void *)lmfd->flFlags); + msprint1(" nPosition: %d\r\n", (void *)lmfd->nPosition); + msprint1(" lpszPathName: %s\r\n", lmfd->lpszPathName ? lmfd->lpszPathName : "(NULL)"); + msprint1(" lpszFileName: %s\r\n", lmfd->lpszFileName ? lmfd->lpszFileName : "(NULL)"); + msprint1(" lpFileType: %p\r\n", (void *)lmfd->lpFileType); + } + return 0; +} + + +char *mstrdup(char *old) +{ + char *tmp; + + tmp = fs_get((strlen(old)+1) * sizeof(char)); + strcpy(tmp, old); + + return tmp; +} + +int +est_size(a) + ADDRESS *a; +{ + int cnt = 0; + + for(; a; a = a->next){ + + /* two times personal for possible quoting */ + cnt += 2 * (a->personal ? strlen(a->personal) : 0); + cnt += (a->mailbox ? strlen(a->mailbox) : 0); + cnt += (a->adl ? strlen(a->adl) : 0); + cnt += (a->host ? strlen(a->host) : 0); + + /* + * add room for: + * possible single space between fullname and addr + * left and right brackets + * @ sign + * possible : for route addr + * , <space> + * + * So I really think that adding 7 is enough. Instead, I'll add 10. + */ + cnt += 10; + } + + return(max(cnt, 50)); /* just making sure */ +} + +void ErrorBoxFunc(char *msg) +{ + if(MSDEBUG){ + fprintf(ms_global->dfd,"ErrorBox: %s\r\n", msg); + fclose(ms_global->dfd); + ms_global->dfd = fopen(ms_global->debugFile, "ab"); + if(!ms_global->dfd){ + MessageBox(NULL, "debug file problems! Debugging turned off.", + "mapi32.dll", + MB_OK|MB_ICONERROR); + ms_global->debug = 0; + fs_give((void **)&ms_global->debugFile); + ms_global->debugFile = NULL; + } + } + MessageBox(NULL, msg, "mapi32.dll", MB_OK|MB_ICONERROR); +} + +/*---------------------------------------------------------------------- + This was borrowed from reply.c, and modified + Generate a unique message id string. + + Args: ps -- The usual pine structure + + Result: Alloc'd unique string is returned + +Uniqueness is gaurenteed by using the host name, process id, date to the +second and a single unique character +*----------------------------------------------------------------------*/ +char * +pmapi_generate_message_id() +{ + static short osec = 0, cnt = 0; + char *id; + time_t now; + struct tm *now_x; + + now = time((time_t *)0); + now_x = localtime(&now); + id = (char *)fs_get(128 * sizeof(char)); + + if(now_x->tm_sec == osec){ + cnt++; + }else{ + cnt = 0; + osec = now_x->tm_sec; + } + sprintf(id,"<Pmapi32.%04d%02d%02d%02d%02d%02d%X.%d@%.50s>", + (now_x->tm_year) + 1900, now_x->tm_mon + 1, + now_x->tm_mday, now_x->tm_hour, now_x->tm_min, now_x->tm_sec, + cnt, getpid(), mylocalhost()); + + return(id); +} |