* Upgrade to new version 2.21.9. Version 2.22 will be a bug release
[alpine.git] / mapi / pmapi.c
blob945104f3e6eeb668a6f9990403b472a1f952197f
2 /*
3 * ========================================================================
4 * Copyright 2006-2009 University of Washington
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * ========================================================================
15 #include "pmapi.h"
17 static int xlate_key;
19 mapi_global_s *ms_global = NULL;
20 #define SIZEOF_20KBUF (20480)
21 char tmp_20k_buf[SIZEOF_20KBUF];
23 void mm_searched (MAILSTREAM *stream,unsigned long number);
24 void mm_exists (MAILSTREAM *stream,unsigned long number);
25 void mm_expunged (MAILSTREAM *stream,unsigned long number);
26 void mm_flags (MAILSTREAM *stream,unsigned long number);
27 void mm_notify (MAILSTREAM *stream,char *string,long errflg);
28 void mm_list (MAILSTREAM *stream,int delimiter,char *name,long attributes);
29 void mm_lsub (MAILSTREAM *stream,int delimiter,char *name,long attributes);
30 void mm_status (MAILSTREAM *stream,char *mailbox,MAILSTATUS *status);
31 void mm_log (char *string,long errflg);
32 void mm_dlog (char *string);
33 int fetch_recursively(BODY *body, long msgno, char *prefix,
34 PART *part, long flags, FLAGS MAPIflags,
35 sessionlist_s *cs);
36 LRESULT CALLBACK Login(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
37 void mm_login (NETMBX *mb,char *user,char *pwd,long trial);
38 void mm_critical (MAILSTREAM *stream);
39 void mm_nocritical (MAILSTREAM *stream);
40 long mm_diskerror (MAILSTREAM *stream,long errcode,long serious);
41 void mm_fatal (char *string);
42 lpMapiFileDesc new_mapi_file_desc(int arraysize);
43 void free_mapi_file_desc(lpMapiFileDesc lpmfd, int arraysize);
44 file_s *new_file_s();
45 void free_file_s(file_s *fs);
46 void init_prcvars(mapi_global_s *nmg);
47 void init_prcfeats(mapi_global_s *nmg);
48 void expand_env_vars(mapi_global_s *nmg);
49 void init_fcc_folder(mapi_global_s *nmg);
50 void init_pmapi_registry_vars(mapi_global_s *nmg);
51 void init_pmapi_vars(mapi_global_s *nmg);
52 char *copy_remote_to_local(char *pinerc, sessionlist_s *cs);
53 int read_pinerc(mapi_global_s *nmg, sessionlist_s *cs,
54 char *prc, char *pineconf, char *pinercex, int depth);
55 void free_mapi_global(mapi_global_s *nmg);
56 MAILSTREAM *first_open(sessionlist_s *cs);
57 int lookup_file_mime_type(char *fn, BODY *body);
58 int LookupMIMEFileExt(char *val, char *mime_type, DWORD *vallen);
59 int in_passfile(sessionlist_s *cs);
60 int set_text_data(BODY *body, char *txt);
61 int get_suggested_directory(char *dir);
62 int get_suggested_file_ext(char *file_ext, PART *part, DWORD *file_extlen);
63 int InitDebug();
64 int GetPineData();
65 int UnderlineSpace(char *s);
66 int GetOutlookVersion();
67 char *pmapi_generate_message_id();
68 SENDSTREAM *mapi_smtp_open(sessionlist_s *cs, char **servers, long options);
69 char *encode_mailto_addr_keyval(lpMapiRecipDesc lpmr);
70 char *encode_mailto_keyval(char *key, char* val);
73 void mm_searched (MAILSTREAM *stream,unsigned long number)
75 if(MSDEBUG){
76 fprintf(ms_global->dfd, "IMAP mm_searched: not implemented\r\n");
77 _flushall();
81 void mm_exists (MAILSTREAM *stream,unsigned long number)
83 if(MSDEBUG){
84 fprintf(ms_global->dfd, "IMAP mm_exists: not implemented\r\n");
85 _flushall();
89 void mm_expunged (MAILSTREAM *stream,unsigned long number)
91 if(MSDEBUG){
92 fprintf(ms_global->dfd, "IMAP mm_expunged: not implemented\r\n");
93 _flushall();
97 void mm_flags (MAILSTREAM *stream,unsigned long number)
99 if(MSDEBUG){
100 fprintf(ms_global->dfd, "IMAP mm_flags: number is %d\r\n", number);
101 _flushall();
105 void mm_notify (MAILSTREAM *stream,char *string,long errflg)
107 mapi_global_s *nmg;
109 nmg = ms_global;
110 if(MSDEBUG){
111 fprintf(nmg->dfd, "IMAP mm_notify:%s %s\r\n",
112 (errflg == NIL ? "" :
113 (errflg == WARN ? " WARN:":
114 (errflg == ERROR ? " ERROR:":
115 (errflg == PARSE ? " PARSE:":" BYE:")))), string);
116 _flushall();
120 void mm_list (MAILSTREAM *stream,int delimiter,char *name,long attributes)
122 if(MSDEBUG){
123 fprintf(ms_global->dfd, "IMAP mm_list: not implemented\r\n");
124 _flushall();
128 void mm_lsub (MAILSTREAM *stream,int delimiter,char *name,long attributes)
130 if(MSDEBUG){
131 fprintf(ms_global->dfd, "IMAP mm_lsub: not implemented\r\n");
132 _flushall();
136 void mm_status (MAILSTREAM *stream,char *mailbox,MAILSTATUS *status)
138 if(MSDEBUG){
139 fprintf(ms_global->dfd, "IMAP mm_status: not implemented\r\n");
140 _flushall();
144 void mm_log (char *string,long errflg)
146 if(MSDEBUG){
147 fprintf(ms_global->dfd, "IMAP mm_log:%s %s\r\n",
148 (errflg == NIL ? "" :
149 (errflg == WARN ? " WARN:":
150 (errflg == ERROR ? " ERROR:":
151 (errflg == PARSE ? " PARSE:":" BYE:")))), string);
152 _flushall();
154 if(errflg == ERROR)
155 ErrorBox("ERROR: %s", string);
158 void mm_dlog (char *string)
160 if(MSDEBUG){
161 time_t now;
162 struct tm *tm_now;
164 now = time((time_t *)0);
165 tm_now = localtime(&now);
167 fprintf(ms_global->dfd, "IMAP %2.2d:%2.2d:%2.2d %d/%d: %s\r\n",
168 tm_now->tm_hour, tm_now->tm_min, tm_now->tm_sec,
169 tm_now->tm_mon+1, tm_now->tm_mday, string);
170 _flushall();
174 int fetch_recursively(BODY *body, long msgno, char *prefix, PART *part,
175 long flags, FLAGS MAPIflags, sessionlist_s *cs)
177 FILE *attfd;
178 PART *subpart;
179 mapi_global_s *nmg;
180 int num = 0, tmplen;
181 file_s *tfs, *tfs2;
182 unsigned long declen, numwritten;
183 void *decf;
184 char tmp[64], file_ext[64], filename[1024], dir[1024];
185 DWORD file_extlen = 64;
186 char *tmpatt;
187 unsigned long tmpattlen;
189 nmg = ms_global;
190 tmp[0] = '\0';
191 if(body && body->type == TYPEMULTIPART){
192 part = body->nested.part;
193 fetch_recursively(&part->body, msgno, prefix, part,
194 flags, MAPIflags, cs);
196 else{
198 num++;
199 sprintf(tmp, "%s%s%d", prefix, (*prefix ? "." : ""), num);
200 if(part && part->body.type == TYPEMULTIPART){
201 subpart = part->body.nested.part;
202 fetch_recursively(&subpart->body, msgno, tmp,
203 subpart, flags, MAPIflags, cs);
205 else{
206 tmpatt = mail_fetch_body(cs->open_stream, msgno,
207 tmp, &tmpattlen, flags);
208 if(strcmp(tmp, "1") == 0){
209 if(((part && part->body.type == TYPETEXT) ||
210 (!part && body->type == TYPETEXT)) &&
211 !(MAPIflags & MAPI_BODY_AS_FILE)){
212 if(cs->lpm->lpszNoteText){
213 fs_give((void **)&cs->lpm->lpszNoteText);
214 cs->lpm->lpszNoteText = NULL;
216 cs->lpm->lpszNoteText = mstrdup(tmpatt);
217 tmpatt = NULL;
219 else
220 cs->lpm->lpszNoteText = mstrdup("");
221 if(MAPIflags & MAPI_SUPPRESS_ATTACH)
222 return 0;
224 if(tmpatt && part && part->body.encoding == ENCBASE64){
225 decf = rfc822_base64(tmpatt, tmpattlen, &declen);
226 tmpatt = NULL;
228 else if(tmpatt && part && part->body.encoding == ENCQUOTEDPRINTABLE){
229 decf = rfc822_qprint(tmpatt, tmpattlen, &declen);
230 tmpatt = NULL;
232 else{
233 if(tmpatt){
234 decf = mstrdup(tmpatt);
235 declen = tmpattlen;
237 else decf = NULL;
239 if(decf){
240 dir[0] = '\0';
241 get_suggested_directory(dir);
242 tmplen = strlen(dir);
243 if(dir[tmplen - 1] != '\\'){
244 dir[tmplen] = '\\';
245 dir[tmplen+1] = '\0';
247 file_ext[0] = '\0';
248 get_suggested_file_ext(file_ext,part, &file_extlen);
250 sprintf(filename, "%smapiapp%d%s", dir, nmg->attach_no,
251 file_ext);
252 nmg->attach_no++;
253 }while (_access(filename, 00) != -1);
254 attfd = fopen(filename, "wb");
255 if(attfd){
256 if(MSDEBUG)
257 fprintf(nmg->dfd,"preparing to write attachment to %s\r\n",
258 filename);
259 numwritten = fwrite(decf, sizeof(char), declen, attfd);
260 fclose(attfd);
261 fs_give((void **)&decf);
262 tfs = new_file_s();
263 tfs->filename = mstrdup(filename);
264 if(!cs->fs)
265 cs->fs = tfs;
266 else{
267 for(tfs2 = cs->fs; tfs2->next; tfs2 = tfs2->next);
268 tfs2->next = tfs;
271 else{
272 if(MSDEBUG)
273 fprintf(nmg->dfd,"Failure in opening %s for attachment\r\n",
274 filename);
278 }while(part && (part = part->next));
280 return 0;
283 int fetch_structure_and_attachments(long msgno, long flags,
284 FLAGS MAPIflags, sessionlist_s *cs)
286 BODY *body = NULL;
287 ENVELOPE *env;
288 ADDRESS *addr;
289 MESSAGECACHE *elt = NULL;
290 mapi_global_s *nmg;
291 file_s *tfs;
292 int num = 0, restore_seen = 0, file_count = 0, i;
293 unsigned long recips;
294 char tmp[1024]; /* don't know how much space we'll need */
296 nmg = ms_global;
297 env = mail_fetch_structure(cs->open_stream, msgno, &body, flags);
298 if(env == NULL || body == NULL){
299 if(MSDEBUG)
300 fprintf(nmg->dfd, "mail_fetch_structure returned %p for env and %p for body\r\n", env, body);
301 return MAPI_E_FAILURE;
303 if(cs->lpm){
304 if(MSDEBUG)
305 fprintf(nmg->dfd, "global lpm is set when it SHOULDN'T be! Freeing\r\n");
306 if(free_mbuffer(cs->lpm))
307 free_MapiMessage(cs->lpm, 1);
308 cs->lpm = NULL;
310 cs->lpm = new_MapiMessage(1);
311 if(env->subject) cs->lpm->lpszSubject = mstrdup(env->subject);
312 if(env->date){
313 elt = mail_elt(cs->open_stream, msgno);
314 mail_parse_date(elt, env->date);
315 sprintf(tmp, "%d/%s%d/%s%d %s%d:%s%d",
316 elt->year+BASEYEAR, (elt->month < 10) ? "0": "",
317 elt->month, (elt->day < 10) ? "0":"", elt->day,
318 (elt->hours < 10) ? "0":"", elt->hours,
319 (elt->minutes < 10) ? "0":"", elt->minutes);
320 cs->lpm->lpszDateReceived = mstrdup(tmp);
322 if(env->from){
323 cs->lpm->lpOriginator = new_MapiRecipDesc(1);
324 if(env->from->personal)
325 cs->lpm->lpOriginator->lpszName = mstrdup(env->from->personal);
326 if(env->from->mailbox && env->from->host){
327 /* don't know if these could ever be empty */
328 sprintf(tmp, "%s@%s", env->from->mailbox, env->from->host);
329 cs->lpm->lpOriginator->lpszAddress = mstrdup(tmp);
331 cs->lpm->lpOriginator->ulRecipClass = MAPI_ORIG;
333 if(env->to || env->cc || env->bcc){ /* should always be true */
334 recips = 0;
335 if(env->to){
336 addr = env->to;
337 while(addr){
338 recips++;
339 addr = addr->next;
342 if(env->cc){
343 addr = env->cc;
344 while(addr){
345 recips++;
346 addr = addr->next;
349 if(env->bcc){
350 addr = env->bcc;
351 while(addr){
352 recips++;
353 addr = addr->next;
356 cs->lpm->nRecipCount = recips;
357 cs->lpm->lpRecips = new_MapiRecipDesc(recips);
358 recips = 0;
359 if(env->to){
360 addr = env->to;
361 while(addr){
362 cs->lpm->lpRecips[recips].ulRecipClass = MAPI_TO;
363 if(addr->personal)
364 cs->lpm->lpRecips[recips].lpszName = mstrdup(addr->personal);
365 if(addr->mailbox && addr->host){
366 sprintf(tmp, "%s@%s", addr->mailbox, addr->host);
367 cs->lpm->lpRecips[recips].lpszAddress = mstrdup(tmp);
369 recips++;
370 addr = addr->next;
373 if(env->cc){
374 addr = env->cc;
375 while(addr){
376 cs->lpm->lpRecips[recips].ulRecipClass = MAPI_CC;
377 if(addr->personal)
378 cs->lpm->lpRecips[recips].lpszName = mstrdup(addr->personal);
379 if(addr->mailbox && addr->host){
380 sprintf(tmp, "%s@%s", addr->mailbox, addr->host);
381 cs->lpm->lpRecips[recips].lpszAddress = mstrdup(tmp);
383 recips++;
384 addr = addr->next;
387 if(env->bcc){
388 addr = env->bcc;
389 while(addr){
390 cs->lpm->lpRecips[recips].ulRecipClass = MAPI_BCC;
391 if(addr->personal)
392 cs->lpm->lpRecips[recips].lpszName = mstrdup(addr->personal);
393 if(addr->mailbox && addr->host){
394 sprintf(tmp, "%s@%s", addr->mailbox, addr->host);
395 cs->lpm->lpRecips[recips].lpszAddress = mstrdup(tmp);
397 recips++;
398 addr = addr->next;
403 if(flags & FT_PEEK){
404 /* gotta remember to unflag \Seen if we just want a peek */
405 sprintf(tmp, "%d", msgno);
406 mail_fetch_flags(cs->open_stream, tmp, NIL);
407 elt = mail_elt(cs->open_stream, msgno);
408 if(!elt->seen){
409 if(MSDEBUG)
410 fprintf(nmg->dfd, "Message has not been seen, and a PEEK is requested\r\n");
411 restore_seen = 1;
413 else if(MSDEBUG)
414 fprintf(nmg->dfd, "Message has already been marked seen\r\n");
416 if(!(MAPIflags & MAPI_ENVELOPE_ONLY))
417 fetch_recursively(body, msgno, "", NULL, flags, MAPIflags, cs);
418 if(cs->fs){
419 for(tfs = cs->fs; tfs; tfs = tfs->next)
420 file_count++;
421 cs->lpm->lpFiles = new_mapi_file_desc(file_count);
422 for(i = 0, tfs = cs->fs; i < file_count && tfs; i++, tfs = tfs->next){
423 cs->lpm->lpFiles[i].lpszPathName = mstrdup(tfs->filename);
425 cs->lpm->nFileCount = file_count;
426 free_file_s(cs->fs);
427 cs->fs = NULL;
429 if(restore_seen){
430 elt = mail_elt(cs->open_stream, msgno);
431 if(!elt->seen && MSDEBUG)
432 fprintf(nmg->dfd, "Fetched body and Message still isn't seen\r\n");
433 else if(MSDEBUG)
434 fprintf(nmg->dfd, "Message has been seen, clearing flag\r\n");
435 if(elt->seen){
436 mail_flag(cs->open_stream, tmp, "\\SEEN", NIL);
437 elt = mail_elt(cs->open_stream, msgno);
438 if(MSDEBUG)
439 fprintf(nmg->dfd, "After calling mail_flag(), elt->seen is %s\r\n",
440 elt->seen ? "SET" : "UNSET");
443 return SUCCESS_SUCCESS;
446 LRESULT CALLBACK Login(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
448 mapi_global_s *nmg;
450 nmg = ms_global;
452 switch(message){
453 case WM_INITDIALOG:
454 SetDlgItemText(hDlg, IDC_SERVER, nmg->tmpmbxptr);
455 if(/*nmg->flags.mapi_logon_ui &&*/ in_passfile(nmg->cs)){
456 SetDlgItemText(hDlg, IDC_LOGIN, nmg->cs->dlge.edit1);
457 SetDlgItemText(hDlg, IDC_PASSWORD, nmg->cs->dlge.edit2);
459 else
460 SetDlgItemText(hDlg, IDC_LOGIN,
461 (*nmg->cs->mb->user) ? nmg->cs->mb->user
462 : nmg->prcvars[USER_ID]->val.p);
463 return TRUE;
464 case WM_COMMAND:
465 if(LOWORD(wParam) == IDOK){
466 nmg->cs->flags.dlg_cancel = 0;
467 GetDlgItemText(hDlg, IDC_LOGIN, nmg->cs->dlge.edit1, EDITLEN);
468 GetDlgItemText(hDlg, IDC_PASSWORD, nmg->cs->dlge.edit2, EDITLEN);
469 EndDialog(hDlg, LOWORD(wParam));
470 return TRUE;
472 else if(LOWORD(wParam) == IDCANCEL){
473 nmg->cs->flags.dlg_cancel = 1;
474 EndDialog(hDlg, LOWORD(wParam));
475 return TRUE;
477 break;
479 return FALSE;
482 void mm_login (NETMBX *mb,char *user,char *pwd,long trial)
484 mapi_global_s *nmg;
485 pw_cache_s *tpwc, *dpwc;
486 int tmp_set_mbx = 0;
488 nmg = ms_global;
489 nmg->cs->mb = mb;
490 if(!nmg->cs->flags.dlg_cancel){
491 for(tpwc = nmg->cs->pwc; tpwc; tpwc = tpwc->next){
492 if(tpwc->validpw && strcmp(tpwc->host, mb->host) == 0)
493 break;
495 if(tpwc){
496 strcpy(user, tpwc->user);
497 strcpy(pwd, tpwc->pwd);
498 tpwc->validpw = 0;
500 /* else if(!nmg->cs->flags.check_stream) { */
501 else if(nmg->cs->flags.mapi_logon_ui || !nmg->pmapi_strict_no_dialog) {
502 if(!nmg->tmpmbxptr){
503 tmp_set_mbx = 1;
504 nmg->tmpmbxptr = mb->host;
506 DialogBox(nmg->mhinst, MAKEINTRESOURCE(IDD_DIALOG1),
507 nmg->cs->mhwnd, (DLGPROC)Login);
508 if(tmp_set_mbx)
509 nmg->tmpmbxptr = NULL;
510 if(!nmg->cs->flags.dlg_cancel){
511 strcpy(user, nmg->cs->dlge.edit1);
512 strcpy(pwd, nmg->cs->dlge.edit2);
513 tpwc = nmg->cs->pwc;
514 while(tpwc){
515 if(tpwc->validpw == 0){
516 dpwc = tpwc;
517 tpwc = tpwc->next;
518 if(dpwc == nmg->cs->pwc)
519 nmg->cs->pwc = dpwc->next;
520 fs_give((void **)&dpwc);
522 else
523 tpwc = tpwc->next;
525 if(nmg->cs->pwc == NULL){
526 nmg->cs->pwc = (pw_cache_s *)fs_get(sizeof(pw_cache_s));
527 tpwc = nmg->cs->pwc;
529 else {
530 for(tpwc = nmg->cs->pwc; tpwc->next; tpwc = tpwc->next);
531 tpwc->next = (pw_cache_s *)fs_get(sizeof(pw_cache_s));
532 tpwc = tpwc->next;
534 memset(tpwc, 0, sizeof(pw_cache_s));
535 strncpy(tpwc->user, nmg->cs->dlge.edit1, EDITLEN - 1);
536 strncpy(tpwc->pwd, nmg->cs->dlge.edit2, EDITLEN - 1);
537 strncpy(tpwc->host, mb->host, EDITLEN - 1);
541 nmg->cs->mb = NULL;
544 void mm_critical (MAILSTREAM *stream)
546 if(MSDEBUG){
547 fprintf(ms_global->dfd, "IMAP mm_critical: not implemented\r\n");
548 _flushall();
552 void mm_nocritical (MAILSTREAM *stream)
554 if(MSDEBUG){
555 fprintf(ms_global->dfd, "IMAP mm_nocritical: not implemented\r\n");
556 _flushall();
560 long mm_diskerror (MAILSTREAM *stream,long errcode,long serious)
562 if(MSDEBUG){
563 fprintf(ms_global->dfd, "IMAP mm_diskerror: not implemented\r\n");
564 _flushall();
566 return 1;
569 void mm_fatal (char *string)
571 if(MSDEBUG){
572 fprintf(ms_global->dfd, "IMAP mm_fatal: %s\r\n", string);
573 _flushall();
577 sessionlist_s *new_sessionlist()
579 sessionlist_s *cs;
581 cs = (sessionlist_s *)fs_get(sizeof(sessionlist_s));
582 memset(cs, 0, sizeof(sessionlist_s));
583 cs->session_number = ms_global->next_session++;
585 return cs;
588 sessionlist_s *free_sessionlist_node(sessionlist_s *cs)
590 sessionlist_s *ts;
592 ts = cs->next;
594 if(cs->currently_open)
595 fs_give((void **)&cs->currently_open);
596 if(cs->fs)
597 free_file_s(cs->fs);
598 if(cs->lpm){
599 if(free_mbuffer(cs->lpm))
600 free_MapiMessage(cs->lpm, 1);
601 cs->lpm = NULL;
603 fs_give((void **)&cs);
605 return ts;
608 sessionlist_s *get_session(unsigned long num)
610 mapi_global_s *nmg = ms_global;
611 sessionlist_s *ts;
613 ts = nmg->sessionlist;
614 while(ts && ts->session_number != num) ts = ts->next;
615 return ts;
619 void *mm_cache (MAILSTREAM *stream,unsigned long msgno,long op){}
621 mapi_global_s *new_mapi_global()
623 mapi_global_s *nmg;
624 int i;
626 nmg = (mapi_global_s *)fs_get(sizeof(mapi_global_s));
627 memset(nmg, 0, sizeof(mapi_global_s));
628 for(i=0; i < NUMPRCVARS; i++){
629 nmg->prcvars[i] = (rc_entry_s *)fs_get(sizeof(rc_entry_s));
630 memset(nmg->prcvars[i], 0, sizeof(rc_entry_s));
632 for(i=0; i < NUMPRCFEATS; i++){
633 nmg->prcfeats[i] = (rc_feat_s *)fs_get(sizeof(rc_feat_s));
634 memset(nmg->prcfeats[i], 0, sizeof(rc_feat_s));
636 nmg->next_session = 1;
638 return nmg;
641 int InitPineSpecific(sessionlist_s *cs)
643 mapi_global_s *nmg = ms_global;
645 if(nmg->inited) return 0;
646 init_prcvars(ms_global);
647 init_prcfeats(ms_global);
648 init_pmapi_registry_vars(ms_global);
649 if(read_pinerc(ms_global, cs, ms_global->pinerc,
650 ms_global->pineconf, ms_global->pinercex, 0) == -1)
651 return -1;
652 expand_env_vars(ms_global);
653 init_fcc_folder(ms_global);
654 msprint1("Fcc folder defined: %s", ms_global->fccfolder);
655 init_pmapi_vars(ms_global);
656 nmg->inited = 1;
657 return 1;
661 new_mbuffer(void *buf, int arraysize, BufType type)
663 MBUFFER_LIST_S *tlist, *tlist2;
664 mapi_global_s *nmg = ms_global;
666 tlist = (MBUFFER_LIST_S *)fs_get(sizeof(MBUFFER_LIST_S));
667 memset(tlist, 0, sizeof(MBUFFER_LIST_S));
668 tlist->buf = buf;
669 tlist->arraysize = arraysize;
670 tlist->type = type;
672 if(!nmg->mapi_bufs)
673 nmg->mapi_bufs = tlist;
674 else{
675 for(tlist2 = nmg->mapi_bufs; tlist2->next; tlist2 = tlist2->next);
676 tlist2->next = tlist;
679 return(0);
683 free_mbuffer(void *buf)
685 MBUFFER_LIST_S *tlist, *pre_tlist = NULL;
686 mapi_global_s *nmg = ms_global;
687 sessionlist_s *session;
689 for(tlist = nmg->mapi_bufs; tlist && tlist->buf != buf; pre_tlist = tlist, tlist = tlist->next);
690 if(!tlist){
691 msprint1("ERROR: buf %p not found in list!\r\n", buf);
692 return 1;
694 if(tlist == nmg->mapi_bufs)
695 nmg->mapi_bufs = tlist->next;
696 else
697 pre_tlist->next = tlist->next;
698 switch (tlist->type) {
699 case RecipDesc:
700 free_MapiRecipDesc(tlist->buf, tlist->arraysize);
701 break;
702 case Message:
703 for(session = nmg->sessionlist; session; session = session->next){
704 if(session->lpm == tlist->buf)
705 session->lpm = NULL;
707 free_MapiMessage(tlist->buf, tlist->arraysize);
708 break;
710 fs_give((void **)&tlist);
711 return 0;
714 lpMapiRecipDesc
715 new_MapiRecipDesc(int arraysize)
717 lpMapiRecipDesc lpmrd;
718 mapi_global_s *nmg = ms_global;
720 lpmrd = (MapiRecipDesc *)fs_get(arraysize*sizeof(MapiRecipDesc));
721 memset(lpmrd, 0, arraysize*sizeof(MapiRecipDesc));
722 new_mbuffer((void *)lpmrd, arraysize, RecipDesc);
723 return lpmrd;
726 void
727 free_MapiRecipDesc(lpMapiRecipDesc buf, int arraysize)
729 int i;
731 for(i = 0; i < arraysize; i++){
732 if(buf[i].lpszName)
733 fs_give((void **)&buf[i].lpszName);
734 if(buf[i].lpszAddress)
735 fs_give((void **)&buf[i].lpszAddress);
737 fs_give((void **)&buf);
740 lpMapiMessage
741 new_MapiMessage(int arraysize)
743 lpMapiMessage lpmm;
744 mapi_global_s *nmg = ms_global;
746 lpmm = (lpMapiMessage)fs_get(arraysize*sizeof(MapiMessage));
747 memset(lpmm, 0, arraysize*sizeof(MapiMessage));
748 new_mbuffer((void *)lpmm, arraysize, Message);
749 return lpmm;
752 void
753 free_MapiMessage(lpMapiMessage buf, int arraysize)
755 int i;
757 for(i = 0; i < arraysize; i++){
758 if(buf[i].lpszSubject)
759 fs_give((void **)&buf[i].lpszSubject);
760 if(buf[i].lpszNoteText)
761 fs_give((void **)&buf[i].lpszNoteText);
762 if(buf[i].lpszMessageType)
763 fs_give((void **)&buf[i].lpszMessageType);
764 if(buf[i].lpszDateReceived)
765 fs_give((void **)&buf[i].lpszDateReceived);
766 if(buf[i].lpszConversationID)
767 fs_give((void **)&buf[i].lpszConversationID);
768 if(buf[i].lpOriginator){
769 if(free_mbuffer(buf[i].lpOriginator))
770 free_MapiRecipDesc(buf[i].lpOriginator, 1);
772 if(buf[i].lpRecips){
773 if(free_mbuffer(buf[i].lpRecips))
774 free_MapiRecipDesc(buf[i].lpRecips, buf[i].nRecipCount);
776 if(buf[i].lpFiles)
777 free_mapi_file_desc(buf[i].lpFiles, buf[i].nFileCount);
779 fs_give((void **)&buf);
782 lpMapiFileDesc new_mapi_file_desc(int arraysize)
784 lpMapiFileDesc lpmfd;
786 lpmfd = (MapiFileDesc *)fs_get(arraysize * sizeof (MapiFileDesc));
787 memset(lpmfd, 0, arraysize * sizeof(MapiFileDesc));
788 return lpmfd;
791 void free_mapi_file_desc(lpMapiFileDesc lpmfd, int arraysize)
793 int i;
795 if(lpmfd == NULL) return;
797 for(i = 0; i < arraysize; i++){
798 if(lpmfd[i].lpszPathName)
799 fs_give((void **)&lpmfd[i].lpszPathName);
800 if(lpmfd[i].lpszFileName)
801 fs_give((void **)&lpmfd[i].lpszFileName);
802 /* NOTE: if lpFileType gets used, free it here */
804 fs_give((void **)&lpmfd);
807 file_s *new_file_s()
809 file_s *tmp_fs;
811 tmp_fs = (file_s *)fs_get(sizeof(file_s));
812 memset(tmp_fs, 0, sizeof(file_s));
813 return tmp_fs;
816 void free_file_s(file_s *fs)
818 if(fs == NULL) return;
819 if(fs->next)
820 free_file_s(fs->next);
821 if(fs->filename)
822 fs_give((void **)&fs->filename);
823 fs_give((void **)&fs);
826 void
827 init_prcvars(mapi_global_s *nmg)
829 int i=0;
831 nmg->prcvars[USER_ID]->var = mstrdup("user-id");
832 nmg->prcvars[PERSONAL_NAME]->var = mstrdup("personal-name");
833 nmg->prcvars[USER_DOMAIN]->var = mstrdup("user-domain");
834 nmg->prcvars[SMTP_SERVER]->var = mstrdup("smtp-server");
835 nmg->prcvars[SMTP_SERVER]->islist = 1;
836 nmg->prcvars[INBOX_PATH]->var = mstrdup("inbox-path");
837 nmg->prcvars[FEATURE_LIST]->var = mstrdup("feature-list");
838 nmg->prcvars[FEATURE_LIST]->islist = 1;
839 nmg->prcvars[CHARACTER_SET]->var = mstrdup("character-set");
840 nmg->prcvars[FOLDER_COLLECTIONS]->var = mstrdup("folder-collections");
841 nmg->prcvars[FOLDER_COLLECTIONS]->islist = 1;
842 nmg->prcvars[PMAPI_SEND_BEHAVIOR]->var = mstrdup("pmapi-send-behavior");
843 nmg->prcvars[PMAPI_SEND_BEHAVIOR]->ispmapivar = 1;
844 nmg->prcvars[DEFAULT_FCC]->var = mstrdup("default-fcc");
845 nmg->prcvars[PMAPI_SUPPRESS_DIALOGS]->var = mstrdup("pmapi-suppress-dialogs");
846 nmg->prcvars[PMAPI_SUPPRESS_DIALOGS]->ispmapivar = 1;
847 nmg->prcvars[PMAPI_STRICT_NO_DIALOG]->var = mstrdup("pmapi-strict-no-dialog");
848 nmg->prcvars[PMAPI_STRICT_NO_DIALOG]->ispmapivar = 1;
851 void
852 init_prcfeats(mapi_global_s *nmg)
854 nmg->prcfeats[ENABLE8BIT]->var = mstrdup("enable-8bit-esmtp-negotiation");
857 void init_fcc_folder(mapi_global_s *nmg)
859 char *fcc, **fc, *desc = NULL, *col = NULL, *tfcc, *p, *p2;
860 int i = 0;
862 if(!nmg->prcvars[DEFAULT_FCC]->val.p)
863 nmg->prcvars[DEFAULT_FCC]->val.p = cpystr("sent-mail");
864 fcc = nmg->prcvars[DEFAULT_FCC]->val.p;
865 if(!fcc || !(*fcc)) return;
866 if(strcmp(fcc, "\"\"") == 0) return;
867 if((*fcc == '{') || (isalpha(fcc[0]) && (fcc[1] == ':'))
868 || ((fcc[0] == '\\') && (fcc[1] == '\\'))){
869 nmg->fccfolder = cpystr(fcc);
870 return;
872 fc = nmg->prcvars[FOLDER_COLLECTIONS]->val.l;
873 if(!fc || !fc[0] || !fc[0][0]) return;
874 get_pair(fc[i], &desc, &col, 0, 0);
875 if(desc)
876 fs_give((void **)&desc);
877 if(!col)
878 return;
879 p = strrchr(col, '[');
880 p2 = strrchr(col, ']');
881 if((p2 < p) || (!p)){
882 if(col)
883 fs_give((void **)&col);
884 return;
886 tfcc = (char *)fs_get((strlen(col) + strlen(fcc) + 1) * sizeof(char));
887 *p = '\0';
888 p2++;
889 sprintf(tfcc, "%s%s%s", col, fcc, p2);
890 nmg->fccfolder = tfcc;
891 if(col)
892 fs_give((void **)&col);
895 void init_pmapi_registry_vars(mapi_global_s *nmg)
897 HKEY hKey;
898 BYTE keyData[1024];
899 DWORD keyDataSize = 1024;
900 DWORD keyDataType;
901 int i;
903 if(RegOpenKeyEx(HKEY_CURRENT_USER,
904 "Software\\University of Washington\\Alpine\\1.0\\PmapiOpts",
906 KEY_QUERY_VALUE,
907 &hKey) != ERROR_SUCCESS)
908 return;
910 for(i = 0; i < NUMPRCVARS; i++){
911 if(nmg->prcvars[i]->ispmapivar && nmg->prcvars[i]->islist == 0){
912 keyDataSize = 1024;
913 if((RegQueryValueEx(hKey, nmg->prcvars[i]->var, 0, &keyDataType,
914 keyData, &keyDataSize) == ERROR_SUCCESS)
915 && keyDataType == REG_SZ){
916 if(nmg->prcvars[i]->val.p)
917 fs_give((void **)&nmg->prcvars[i]->val.p);
918 nmg->prcvars[i]->val.p = mstrdup(keyData);
923 RegCloseKey(hKey);
926 void init_pmapi_vars(mapi_global_s *nmg)
928 char *b;
930 if(b = nmg->prcvars[PMAPI_SEND_BEHAVIOR]->val.p){
931 if(_stricmp(b, "always-prompt") == 0)
932 nmg->pmapi_send_behavior = PMSB_ALWAYS_PROMPT;
933 else if(_stricmp(b, "always-send") == 0)
934 nmg->pmapi_send_behavior = PMSB_ALWAYS_SEND;
935 else if(_stricmp(b, "never-send") == 0)
936 nmg->pmapi_send_behavior = PMSB_NEVER_SEND;
938 else
939 nmg->pmapi_send_behavior = PMSB_ALWAYS_PROMPT;
940 if(b = nmg->prcvars[PMAPI_SUPPRESS_DIALOGS]->val.p){
941 if(_stricmp(b, "yes") == 0)
942 nmg->pmapi_suppress_dialogs = PMSD_YES;
943 else if(_stricmp(b, "prompt") == 0)
944 nmg->pmapi_suppress_dialogs = PMSD_PROMPT;
945 else if(_stricmp(b, "no") == 0)
946 nmg->pmapi_suppress_dialogs = PMSD_NO;
948 else
949 nmg->pmapi_suppress_dialogs = PMSD_NO;
950 if(b = nmg->prcvars[PMAPI_STRICT_NO_DIALOG]->val.p){
951 if(_stricmp(b, "yes") == 0)
952 nmg->pmapi_strict_no_dialog = 1;
954 else
955 nmg->pmapi_strict_no_dialog = 0;
958 char *copy_remote_to_local(char *pinerc, sessionlist_s *cs)
960 mapi_global_s *nmg = ms_global;
961 char *tmptext, dir[1024], filename[1024];
962 unsigned long tmptextlen, i = 0, numwritten;
963 FILE *prcfd;
965 if(nmg->cs) return NULL;
966 if(!(cs->open_stream = mapi_mail_open(cs, NULL, pinerc,
967 ms_global->debug ? OP_DEBUG : NIL))){
968 ErrorBox("Couldn't open %s for reading as remote pinerc", pinerc);
969 return NULL;
971 nmg->cs = NULL;
972 nmg->tmpmbxptr = NULL;
973 tmptext = mail_fetch_body(cs->open_stream, cs->open_stream->nmsgs,
974 "1", &tmptextlen, NIL);
975 dir[0] = '\0';
976 get_suggested_directory(dir);
978 sprintf(filename, "%s%smapipinerc%d", dir,
979 dir[strlen(dir)-1] == '\\' ? "" : "\\", i);
980 i++;
981 }while (_access(filename, 00) != -1);
982 if(prcfd = fopen(filename, "wb")){
983 if(MSDEBUG)
984 fprintf(ms_global->dfd,"preparing to write pinerc to %s\r\n",
985 filename);
986 numwritten = fwrite(tmptext, sizeof(char), tmptextlen, prcfd);
987 fclose(prcfd);
989 else{
990 ErrorBox("Couldn't open temp file %s for writing", filename);
991 mail_close_full(cs->open_stream, NIL);
992 return NULL;
994 cs->open_stream = mail_close_full(cs->open_stream, NIL);
995 return(mstrdup(filename));
998 int read_pinerc(mapi_global_s *nmg, sessionlist_s *cs,
999 char *prc, char *pineconf, char *pinercex, int depth)
1001 FILE *prcfd;
1002 int i, varnum, j, varlen, create_local = 0, k;
1003 char line[BUFLEN], *local_pinerc, *p;
1005 if(nmg == NULL) return -1;
1006 if(MSDEBUG){
1007 fprintf(nmg->dfd,
1008 "read_pinerc called: prc: %s, pineconf: %s, pinercex: %s, depth: %d\r\n",
1009 prc ? prc : "NULL", pineconf ? pineconf : "NULL",
1010 pinercex ? pinercex : "NULL", depth);
1012 if(pineconf){
1013 if(MSDEBUG)
1014 fprintf(nmg->dfd, "Recursively calling read_pinerc for pineconf\r\n");
1015 read_pinerc(nmg, cs, pineconf, NULL, NULL, 1);
1017 if(prc == NULL){
1018 ErrorBox("No value found for %s. Try running Alpine.", "pinerc");
1019 DEBUG_WRITE("No value found for %s\r\n","pinerc");
1020 _flushall();
1021 return -1;
1023 if(*prc == '{'){
1024 if(MSDEBUG)
1025 fprintf(ms_global->dfd, "REMOTE PINERC: %s\r\n", prc);
1026 if(!(local_pinerc = copy_remote_to_local(prc, cs))){
1027 if(MSDEBUG)
1028 fprintf(nmg->dfd, "Couldn't copy remote pinerc to local\r\n");
1029 return -1;
1031 create_local = 1;
1033 else{
1034 if(!(local_pinerc = mstrdup(prc))){
1035 ErrorBox("Couldn't fs_get for %s","pinerc");
1036 return -1;
1039 if(MSDEBUG)
1040 fprintf(nmg->dfd, "Preparing to open local pinerc %s\r\n", local_pinerc);
1041 prcfd = fopen(local_pinerc, "r");
1042 if(prcfd == NULL){
1043 DEBUG_WRITE("Couldn't open %s\r\n","pinerc");
1044 _flushall();
1045 ErrorBox("Couldn't open %s\r\n","pinerc");
1046 if(local_pinerc)
1047 fs_give((void **)&local_pinerc);
1048 return -1;
1050 DEBUG_WRITE("Opened %s for reading\r\n", "pinerc");
1051 for(i = 0; i < NUMPRCVARS && nmg->prcvars[i]->var; i++);
1052 varnum = i;
1053 while(fgets(line, BUFLEN, prcfd)){
1054 j = 0;
1055 while(isspace(line[j])) j++;
1056 if(line[j] != '#' && line[j] != '\0'){
1057 for(i = 0; i < varnum; i ++){
1058 varlen = strlen(nmg->prcvars[i]->var);
1059 if(_strnicmp(nmg->prcvars[i]->var, line+j, varlen)==0){
1060 j += varlen;
1061 if(line[j] == '='){
1062 /* we found a match in the pinerc */
1063 j++;
1064 if(nmg->prcvars[i]->islist){
1065 while(isspace(line[j])) j++;
1066 if(line[j] != '\0'){
1067 STRLIST_S *strl = NULL, *tl, *tln;
1069 if(nmg->prcvars[i]->val.l){
1070 for(k = 0; nmg->prcvars[i]->val.l[k]; k++)
1071 fs_give((void **)&nmg->prcvars[i]->val.l[k]);
1072 fs_give((void **)&nmg->prcvars[i]->val.l);
1074 strl = (STRLIST_S *)fs_get(sizeof(STRLIST_S));
1075 memset(strl, 0, sizeof(STRLIST_S));
1076 tl = strl;
1077 while(line[j]){
1078 while(isspace(line[j])) j++;
1079 if(p = strchr(line+j, ','))
1080 *p = '\0';
1081 if(tl != strl || tl->str){
1082 tl->next = (STRLIST_S *)fs_get(sizeof(STRLIST_S));
1083 tl = tl->next;
1084 memset(tl, 0, sizeof(STRLIST_S));
1086 varlen = strlen(line+j);
1087 while(isspace((line+j)[varlen - 1])){
1088 varlen--;
1089 (line+j)[varlen] = '\0';
1091 tl->str = mstrdup(line+j);
1092 if(p){
1093 j = p - line + 1;
1094 while(isspace(line[j])) j++;
1095 if(!line[j]){
1096 fgets(line, BUFLEN, prcfd);
1097 j = 0;
1100 else
1101 break;
1103 for(tl = strl, k = 0; tl; tl = tl->next, k++);
1104 nmg->prcvars[i]->val.l = (char **)fs_get((k+1)*sizeof(char *));
1105 for(tl = strl, k = 0; tl; tl = tln, k++){
1106 nmg->prcvars[i]->val.l[k] = tl->str;
1107 tln = tl->next;
1108 fs_give((void **)&tl);
1110 nmg->prcvars[i]->val.l[k] = NULL;
1113 else{
1114 while(isspace(line[j])) j++;
1115 if(line[j] != '\0'){
1116 varlen = strlen(line+j);
1117 while(isspace((line+j)[varlen-1])){
1118 varlen--;
1119 (line+j)[varlen] = '\0';
1121 if(nmg->prcvars[i]->val.p) fs_give((void **)&nmg->prcvars[i]->val.p);
1122 nmg->prcvars[i]->val.p = (char *)fs_get((varlen + 1)*sizeof(char));
1123 strncpy(nmg->prcvars[i]->val.p, line+j, varlen);
1124 nmg->prcvars[i]->val.p[varlen] = '\0';
1132 if(!depth){
1133 if(pinercex){
1134 if(MSDEBUG)
1135 fprintf(nmg->dfd,
1136 "Recursively calling read_pinerc for exceptions\r\n");
1137 read_pinerc(nmg, cs, pinercex, NULL, NULL, 1);
1140 _flushall();
1141 fclose(prcfd);
1142 for(i = 0; nmg->prcvars[FEATURE_LIST]->val.l
1143 && nmg->prcvars[FEATURE_LIST]->val.l[i]; i++){
1144 for(j = 0; j < NUMPRCFEATS; j++){
1145 if(strcmp(nmg->prcfeats[j]->var, nmg->prcvars[FEATURE_LIST]->val.l[i]) == 0)
1146 nmg->prcfeats[j]->is_set = 1;
1147 else if((strncmp("no-", nmg->prcvars[FEATURE_LIST]->val.l[i], 3) == 0)
1148 && (strcmp(nmg->prcfeats[j]->var,
1149 nmg->prcvars[FEATURE_LIST]->val.l[i] + 3) == 0)){
1150 nmg->prcfeats[j]->is_set = 0;
1154 if(create_local && local_pinerc){
1155 if(MSDEBUG)
1156 fprintf(nmg->dfd, "Removing %s\r\n", local_pinerc);
1157 _unlink(local_pinerc);
1159 if(local_pinerc)
1160 fs_give((void **)&local_pinerc);
1161 if(MSDEBUG){
1162 fprintf(nmg->dfd, "Current pinerc settings:\r\n");
1163 for(i = 0; i < varnum; i++){
1164 fprintf(nmg->dfd, "%s:", nmg->prcvars[i]->var);
1165 if(!nmg->prcvars[i]->islist)
1166 fprintf(nmg->dfd, " %s\r\n",
1167 nmg->prcvars[i]->val.p ? nmg->prcvars[i]->val.p : " NOT DEFINED");
1168 else{
1169 if(!nmg->prcvars[i]->val.l)
1170 fprintf(nmg->dfd, " NOT DEFINED\r\n");
1171 else {
1172 for(j = 0; nmg->prcvars[i]->val.l[j]; j++)
1173 fprintf(nmg->dfd, "\t%s\r\n",
1174 nmg->prcvars[i]->val.l[j]);
1179 return 0;
1182 void expand_env_vars(mapi_global_s *nmg)
1184 int i, j, check_reg = 0, islist;
1185 DWORD keyDataSize = 1024, keyDataType;
1186 char *p1, *p2, *p3, keyData[1024], *newstr, **valstrp;
1187 HKEY hKey;
1190 if(RegOpenKeyEx(HKEY_CURRENT_USER,
1191 "Software\\University of Washington\\Alpine\\1.0\\PmapiOpts\\Env",
1193 KEY_QUERY_VALUE,
1194 &hKey) == ERROR_SUCCESS)
1195 check_reg = 1;
1196 for(i = 0; i < NUMPRCVARS; i++){
1197 islist = nmg->prcvars[i]->islist;
1198 for(j = 0; islist ? (int)(nmg->prcvars[i]->val.l && nmg->prcvars[i]->val.l[j])
1199 : (j < 1); j++){
1200 valstrp = islist ? &nmg->prcvars[i]->val.l[j] : &nmg->prcvars[i]->val.p;
1201 if(*valstrp == NULL) continue;
1202 while((p1 = strstr(*valstrp, "${")) && (p2 = strchr(p1, '}'))){
1203 msprint1("%s -> ", *valstrp);
1204 *p2 = '\0';
1205 p3 = NULL;
1206 if((p3 = getenv(p1+2)) && *p3)
1208 else if(check_reg && (keyDataSize = 1024)
1209 && (RegQueryValueEx(hKey, p1+2, 0, &keyDataType,
1210 keyData, &keyDataSize) == ERROR_SUCCESS)
1211 && keyDataType == REG_SZ)
1212 p3 = keyData;
1213 newstr = (char *)fs_get(sizeof(char)*(strlen(*valstrp)
1214 + strlen(p3 ? p3 : "") + strlen(p2+1) + 1));
1215 *p1 = '\0';
1216 strcpy(newstr, *valstrp);
1217 strcat(newstr, p3 && *p3 ? p3 : "");
1218 strcat(newstr, p2 + 1);
1219 fs_give((void **)valstrp);
1220 *valstrp = newstr;
1221 msprint1(" %s\r\n", *valstrp);
1225 if(check_reg)
1226 RegCloseKey(hKey);
1229 void free_mapi_global(mapi_global_s *nmg)
1231 int i, j;
1232 sessionlist_s *ts;
1234 if(nmg->pineExe)
1235 fs_give((void **)&nmg->pineExe);
1236 if(nmg->pineExeAlt)
1237 fs_give((void **)&nmg->pineExeAlt);
1238 if(nmg->pinerc)
1239 fs_give((void **)&nmg->pinerc);
1240 if(nmg->pineconf)
1241 fs_give((void **)&nmg->pineconf);
1242 if(nmg->pinercex)
1243 fs_give((void **)&nmg->pinercex);
1244 if(nmg->fccfolder)
1245 fs_give((void **)&nmg->fccfolder);
1246 if(nmg->attachDir)
1247 fs_give((void **)&nmg->attachDir);
1248 for(i = 0; i < NUMPRCFEATS; i++){
1249 if(nmg->prcfeats[i]->var)
1250 fs_give((void **)&nmg->prcfeats[i]->var);
1251 fs_give((void **)&nmg->prcfeats[i]);
1253 for(i = 0; i < NUMPRCVARS; i++){
1254 if(nmg->prcvars[i]->var)
1255 fs_give((void **)&nmg->prcvars[i]->var);
1256 if(nmg->prcvars[i]->islist){
1257 if(nmg->prcvars[i]->val.l){
1258 for(j = 0; nmg->prcvars[i]->val.l[j]; j++)
1259 fs_give((void **)&nmg->prcvars[i]->val.l[j]);
1260 fs_give((void **)&nmg->prcvars[i]->val.l);
1263 else {
1264 if(nmg->prcvars[i]->val.p)
1265 fs_give((void **)&nmg->prcvars[i]->val.p);
1267 fs_give((void **)&nmg->prcvars[i]);
1269 for(ts = nmg->sessionlist; ts;){
1270 if(ts->open_stream)
1271 ts->open_stream = mail_close_full(ts->open_stream, NIL);
1272 ts = free_sessionlist_node(ts);
1274 if(nmg->debugFile)
1275 fs_give((void **)&nmg->debugFile);
1276 if(nmg->debug && nmg->dfd)
1277 fclose(nmg->dfd);
1278 nmg->debug = FALSE;
1279 fs_give((void **)&nmg);
1282 MAILSTREAM *first_open(sessionlist_s *cs)
1284 mapi_global_s *nmg = ms_global;
1285 /* cs->mhwnd = (HWND)ulUIParam;
1286 * if(flFlags & MAPI_LOGON_UI)
1287 * cs->flags.mapi_logon_ui = TRUE;
1289 /* if someone is logging in right now, return failure */
1290 if(nmg->cs) return NULL;
1291 if(MSDEBUG)
1292 fprintf(nmg->dfd, "Opening mailbox for the first time\r\n");
1293 if(nmg->prcvars[INBOX_PATH]->val.p == NULL){
1294 ErrorBox("No value set for %s!", "inbox");
1295 return NULL;
1297 cs->open_stream = mapi_mail_open(cs, cs->open_stream, nmg->prcvars[INBOX_PATH]->val.p,
1298 nmg->debug ? OP_DEBUG : NIL);
1299 /* cs->flags.mapi_logon_ui = FALSE; */
1300 if(cs->open_stream){
1301 if(cs->currently_open){
1302 fs_give((void **)&cs->currently_open);
1303 cs->currently_open = NULL;
1305 cs->currently_open = mstrdup(nmg->prcvars[INBOX_PATH]->val.p);
1306 if(nmg->debug)
1307 mail_debug(cs->open_stream);
1308 if(MSDEBUG){
1309 fprintf(nmg->dfd, "returning SUCCESS_SUCCESS\r\n");
1310 _flushall();
1312 return cs->open_stream;
1314 else if(cs->flags.dlg_cancel){
1315 if(MSDEBUG){
1316 fprintf(nmg->dfd, "returning MAPI_E_FAILURE\r\n");
1317 _flushall();
1319 return NULL;
1321 else{
1322 cs->dlge.edit1[0] = '\0';
1323 cs->dlge.edit2[0] = '\0';
1324 if(cs->currently_open){
1325 fs_give((void **)&cs->currently_open);
1326 cs->currently_open = NULL;
1328 if(MSDEBUG){
1329 fprintf(nmg->dfd, "returning MAPI_E_FAILURE\r\n");
1330 _flushall();
1332 return NULL;
1336 SENDSTREAM *
1337 mapi_smtp_open(sessionlist_s *cs, char **servers, long options)
1339 mapi_global_s *nmg = ms_global;
1340 SENDSTREAM *newstream;
1341 pw_cache_s *tpwc, *dpwc;
1343 nmg->cs = cs;
1344 nmg->tmpmbxptr = NULL;
1345 nmg->cs->flags.dlg_cancel = 0;
1346 newstream = smtp_open(servers, options);
1347 nmg->cs = NULL;
1348 nmg->tmpmbxptr = NULL;
1350 if(newstream){ /* if open stream, valid password */
1351 for(tpwc = cs->pwc; tpwc; tpwc = tpwc->next)
1352 tpwc->validpw = 1;
1354 else{
1355 for(tpwc = cs->pwc, dpwc = NULL; tpwc; dpwc = tpwc, tpwc = tpwc->next){
1356 if(tpwc->validpw == 0){
1357 if(tpwc == cs->pwc)
1358 cs->pwc = tpwc->next;
1359 else
1360 dpwc->next = tpwc->next;
1361 fs_give((void **)&tpwc);
1365 return(newstream);
1368 MAILSTREAM *
1369 mapi_mail_open(sessionlist_s *cs, MAILSTREAM *stream, char *name, long options)
1371 MAILSTREAM *newstream;
1372 mapi_global_s *nmg = ms_global;
1373 pw_cache_s *tpwc, *dpwc;
1375 nmg->cs = cs;
1376 nmg->tmpmbxptr = name;
1377 nmg->cs->flags.dlg_cancel = 0;
1378 newstream = mail_open(stream, name, options);
1379 nmg->tmpmbxptr = NULL;
1380 nmg->cs = NULL;
1382 if(newstream){ /* if open stream, valid password */
1383 for(tpwc = cs->pwc; tpwc; tpwc = tpwc->next)
1384 tpwc->validpw = 1;
1386 else{
1387 tpwc = cs->pwc;
1388 while(tpwc){
1389 if(tpwc->validpw == 0){
1390 dpwc = tpwc;
1391 tpwc = tpwc->next;
1392 if(dpwc == cs->pwc)
1393 cs->pwc = dpwc->next;
1394 fs_give((void **)&dpwc);
1396 else
1397 tpwc = tpwc->next;
1401 return (newstream);
1405 MAILSTREAM *check_mailstream(sessionlist_s *cs)
1407 mapi_global_s *nmg;
1409 nmg = ms_global;
1411 if(!cs->open_stream){
1412 return(first_open(cs));
1414 cs->flags.check_stream = TRUE;
1415 if(!mail_ping(cs->open_stream)){
1416 if(nmg->cs) return NULL;
1417 cs->open_stream = mapi_mail_open(cs, cs->open_stream,
1418 cs->currently_open ? cs->currently_open :
1419 nmg->prcvars[INBOX_PATH]->val.p,
1420 nmg->debug ? OP_DEBUG : NIL);
1421 if(!cs->open_stream){
1422 fs_give((void **)&cs->currently_open);
1423 cs->currently_open = NULL;
1424 cs->dlge.edit1[0] = '\0';
1425 cs->dlge.edit2[0] = '\0';
1426 cs->flags.check_stream = FALSE;
1427 return NULL;
1430 cs->flags.check_stream = FALSE;
1431 return cs->open_stream;
1434 /* pretty much changes a string to an integer,
1435 * but if it is not a valid message number, then 0 is returned
1437 unsigned long convert_to_msgno(char *msgid)
1439 unsigned long place_holder = 1, msgno = 0;
1440 int i, len;
1442 len = strlen(msgid);
1443 for(i = 0; i < len; i++){
1444 if(msgid[len-1-i] - '0' < 0 || msgid[len-1-i] - '0' > 9)
1445 return 0;
1446 msgno += (msgid[len - 1 - i] - '0')*place_holder;
1447 place_holder *= 10;
1450 return msgno;
1454 * Lookup file's mimetype by its file extension
1455 * fn - filename
1456 * body - body in which to store new type, subtype
1458 * A mime type is ALWAYS set
1460 * Returns 0 if the file extension was found and mimetype was set accordingly
1461 * 1 if otherwise
1463 int lookup_file_mime_type(char *fn, BODY *body)
1465 char *p, subkey[1024], val[1024];
1466 DWORD dtype, vallen = 1024;
1467 HKEY hKey;
1468 int i, rv = 0;
1470 if(body->subtype)
1471 fs_give((void **)&body->subtype);
1472 if((p = strrchr(fn, '.')) && p[1]){
1473 sprintf(subkey, "%.1020s", p);
1474 if(RegOpenKeyEx(HKEY_CLASSES_ROOT, subkey, 0, KEY_READ, &hKey) == ERROR_SUCCESS){
1475 if(RegQueryValueEx(hKey, "Content Type", NULL, &dtype, val, &vallen) == ERROR_SUCCESS){
1476 RegCloseKey(hKey);
1477 if((p = strrchr(val, '/')) && p[1]){
1478 *(p++) = '\0';
1479 body->subtype = mstrdup(p);
1480 for(i=0; (i <= TYPEMAX) && body_types[i] && _stricmp(val, body_types[i]); i++);
1481 if(i > TYPEMAX)
1482 i = TYPEOTHER;
1483 else if(!body_types[i])
1484 body_types[i] = mstrdup(val);
1485 body->type = i;
1486 return 0;
1491 body->type = TYPEAPPLICATION;
1492 body->subtype = "octet-stream";
1493 return 1;
1496 int LookupMIMEFileExt(char *val, char *mime_type, DWORD *vallen)
1498 HKEY hKey;
1499 DWORD dtype;
1500 LONG rv = !ERROR_SUCCESS;
1501 char subkey[1024];
1503 sprintf(subkey, "MIME\\Database\\Content Type\\%s", mime_type);
1504 if(RegOpenKeyEx(HKEY_CLASSES_ROOT, subkey, 0, KEY_READ, &hKey) == ERROR_SUCCESS){
1505 rv = RegQueryValueEx(hKey,"extension",NULL, &dtype, val, vallen);
1506 RegCloseKey(hKey);
1509 return(rv);
1513 * xlate_out() - xlate_out the given character
1515 char
1516 xlate_out(c)
1517 char c;
1519 register int dti;
1520 register int xch;
1522 if((c >= FIRSTCH) && (c <= LASTCH)){
1523 xch = c - (dti = xlate_key);
1524 xch += (xch < FIRSTCH-TABSZ) ? 2*TABSZ : (xch < FIRSTCH) ? TABSZ : 0;
1525 dti = (xch - FIRSTCH) + dti;
1526 dti -= (dti >= 2*TABSZ) ? 2*TABSZ : (dti >= TABSZ) ? TABSZ : 0;
1527 xlate_key = dti;
1528 return(xch);
1530 else
1531 return(c);
1534 /* return TRUE if the pwd is found, FALSE if not */
1535 int in_passfile(sessionlist_s *cs)
1537 mapi_global_s *nmg;
1538 char *tf, *tp, *ui[4], tmp[1024], *dir;
1539 int i, j, n;
1540 FILE *tfd;
1542 nmg = ms_global;
1544 if(*nmg->pinerc == '{')
1545 dir = nmg->pineExe;
1546 else
1547 dir = nmg->pinerc;
1549 /* if(nmg->flags.passfile_checked) return FALSE; */
1550 if(!(tf = (char *)fs_get(sizeof(char)*(strlen(dir) + strlen("pine.pwd") + 1)))){
1551 /* nmg->flags.passfile_checked = TRUE; */
1552 return FALSE;
1554 strcpy(tf,dir);
1555 if(tp = strrchr(tf, '\\')){
1556 tp++;
1557 strcpy(tp, "pine.pwd");
1559 else /* don't know when this will ever happen */
1560 strcpy(tf, "pine.pwd");
1561 if(_access(tf, 00) == 0){
1562 if(MSDEBUG)
1563 fprintf(nmg->dfd,"found %s for passwords\r\n", tf);
1564 if(!(tfd = fopen(tf,"r"))){
1565 fs_give((void **)&tf);
1566 /* nmg->flags.passfile_checked = TRUE; */
1567 return FALSE;
1569 else{
1570 for(n = 0; fgets(tmp, 1024, tfd); n++){
1571 /*** do any necessary DEcryption here ***/
1572 xlate_key = n;
1573 for(i = 0; tmp[i]; i++)
1574 tmp[i] = xlate_out(tmp[i]);
1576 if(i && tmp[i-1] == '\n')
1577 tmp[i-1] = '\0'; /* blast '\n' */
1579 ui[0] = ui[1] = ui[2] = ui[3] = NULL;
1580 for(i = 0, j = 0; tmp[i] && j < 4; j++){
1581 for(ui[j] = &tmp[i]; tmp[i] && tmp[i] != '\t'; i++)
1584 if(tmp[i])
1585 tmp[i++] = '\0';
1588 if(ui[0] && ui[1] && ui[2]){
1589 if(strcmp(ui[2], cs->mb->host) == 0){
1590 if((cs->mb->altflag && ui[3] && *ui[3] == '1')
1591 || (!cs->mb->altflag && (!ui[3] || (*ui[3] == '0')))){
1592 if(strcmp(ui[1], *cs->mb->user ? cs->mb->user
1593 : nmg->prcvars[USER_ID]->val.p) == 0){
1594 /* winner */
1595 strcpy(cs->dlge.edit1, *cs->mb->user ? cs->mb->user
1596 : nmg->prcvars[USER_ID]->val.p);
1597 strcpy(cs->dlge.edit2, ui[0]);
1598 fclose(tfd);
1599 fs_give((void **)&tf);
1600 /* nmg->flags.passfile_checked = TRUE; */
1601 return TRUE;
1607 fclose(tfd);
1608 fs_give((void **)&tf);
1611 else{
1612 fs_give((void **)&tf);
1613 /* nmg->flags.passfile_checked = TRUE; */
1614 return FALSE;
1616 /* nmg->flags.passfile_checked = TRUE; */
1617 return FALSE;
1620 int get_suggested_directory(char *dir)
1622 char *tmpdir;
1624 if(tmpdir = getenv("TEMP")){
1625 strcpy(dir, tmpdir);
1626 return TRUE;
1628 else if(tmpdir = getenv("TMP")){
1629 strcpy(dir, tmpdir);
1630 return TRUE;
1632 else if(ms_global && ms_global->attachDir){
1633 strcpy(dir, ms_global->attachDir);
1634 return TRUE;
1636 else{ /* should NEVER get here */
1637 strcpy(dir, "C:\\");
1638 return TRUE;
1640 return FALSE;
1644 /* return TRUE if file_ext is modified, FALSE if not */
1645 int get_suggested_file_ext(char *file_ext, PART *part, DWORD *file_extlen)
1647 char mime_type[1024], *tmp_ext;
1648 int rv = !ERROR_SUCCESS;
1649 PARAMETER *param;
1651 if(part->body.subtype){
1652 sprintf(mime_type, "%s/%s", body_types[part->body.type], part->body.subtype);
1653 rv = LookupMIMEFileExt(file_ext, mime_type, file_extlen);
1655 if(rv == ERROR_SUCCESS)
1656 return TRUE;
1657 else{
1658 param = part->body.parameter;
1659 while(param && (_stricmp("NAME", param->attribute)))
1660 param = param->next;
1661 if(!param){
1662 if(part->body.type == TYPEMESSAGE){
1663 /* don't try to recurse through attached messages yet */
1664 strcpy(file_ext, ".txt");
1665 return TRUE;
1668 tmp_ext = strrchr(param->value, (int)'.');
1669 if(!tmp_ext) return FALSE;
1670 strcpy(file_ext, tmp_ext);
1672 return TRUE;
1675 /* return -1 for failure */
1676 int InitDebug()
1678 char path[1024];
1680 if(!ms_global){
1681 if((ms_global = new_mapi_global()) == NULL) return -1;
1684 * if debug file exists, turn on debugging mode
1686 if(ms_global->debug == 1) /* debug file already initialized, somehow */
1687 return 1;
1688 get_suggested_directory(path);
1689 if(path[strlen(path-1)] != '\\')
1690 strcat(path, "\\");
1691 strcat(path, "mapi_debug.txt");
1692 if(_access(path, 00) == 0){
1693 ms_global->debug = 1;
1695 else{
1696 get_suggested_directory(path);
1697 if(path[strlen(path-1)] != '\\')
1698 strcat(path, "\\");
1699 strcat(path, "mapisend");
1700 if(_access(path, 00) == 0){
1701 ms_global->debug = 1;
1705 if(ms_global->debug){
1706 ms_global->dfd = fopen(path, "wb");
1707 if(!ms_global->dfd){
1708 ErrorBox("MAPISendMail: debug off: can't open debug file %.200s",
1709 path);
1710 ms_global->debug = 0; /* can't open the file, turn off debugging */
1712 else if(ms_global->debug == 1){
1713 ms_global->debugFile = (char *)fs_get((1+strlen(path))*sizeof(char));
1714 strcpy(ms_global->debugFile, path);
1718 if(ms_global->debug && (ms_global->dfd == NULL))
1719 ms_global->debug = 0;
1721 return ms_global->debug;
1724 int GetPineData()
1726 HKEY pineKey;
1727 BYTE pineKeyData[1024];
1728 DWORD pineKeyDataSize;
1729 DWORD pineKeyDataType;
1730 char *defPath = "c:\\pine\\pine.exe";
1731 char *pineExe = strrchr(defPath, '\\')+1;
1732 char *freepineExe = NULL;
1733 char *defAttachDir = "c:\\tmp";
1734 char *penv = NULL;
1737 * get name of and path to pine.exe from registry
1739 if (RegOpenKeyEx(
1740 HKEY_LOCAL_MACHINE,
1741 "SOFTWARE\\University of Washington\\Alpine\\1.0",
1743 KEY_QUERY_VALUE,
1744 &pineKey) == ERROR_SUCCESS) {
1745 pineKeyDataSize = sizeof(pineKeyData);
1746 if (RegQueryValueEx(
1747 pineKey,
1748 "PineEXE",
1750 &pineKeyDataType,
1751 pineKeyData,
1752 &pineKeyDataSize) == ERROR_SUCCESS) {
1753 freepineExe = (char *)fs_get((pineKeyDataSize + 1) * sizeof(char));
1754 if ((pineExe = freepineExe) != NULL) {
1755 strcpy(pineExe, pineKeyData);
1757 else {
1758 ErrorBox("MAPISendMail: can't fs_get %d bytes for pineExe",
1759 pineKeyDataSize);
1760 return 0;
1762 if (MSDEBUG) {
1763 fprintf(ms_global->dfd,"pine.exe pineKeyDataSize: %d\r\n", pineKeyDataSize);
1764 fprintf(ms_global->dfd,"pine.exe pineKeyData: %s\r\n", pineKeyData);
1767 pineKeyDataSize = sizeof(pineKeyData);
1768 if (RegQueryValueEx(
1769 pineKey,
1770 "pinedir",
1772 &pineKeyDataType,
1773 pineKeyData,
1774 &pineKeyDataSize) == ERROR_SUCCESS) {
1775 ms_global->pineExe = (char *)fs_get(sizeof(char)*(pineKeyDataSize+strlen(pineExe)));
1776 if (ms_global->pineExe) {
1777 strncpy(ms_global->pineExe, pineKeyData, pineKeyDataSize);
1778 strcat(ms_global->pineExe, pineExe);
1780 else {
1781 ErrorBox("MAPISendMail: can't fs_get %d bytes for av[0]",
1782 pineKeyDataSize);
1783 return 0;
1785 if (MSDEBUG) {
1786 fprintf(ms_global->dfd,"pine.exe pineKeyDataSize: %d\r\n", pineKeyDataSize);
1787 fprintf(ms_global->dfd,"pine.exe pineKeyData: %s\r\n", pineKeyData);
1790 RegCloseKey(pineKey);
1792 if(!ms_global->pineExe){
1793 ms_global->pineExe = (char *)fs_get((1+strlen(defPath))*sizeof(char));
1794 if(!ms_global->pineExe){
1795 ErrorBox("Couldn't fs_get for %s","pineExe");
1796 return 0;
1798 else
1799 strcpy(ms_global->pineExe, defPath);
1802 if(freepineExe)
1803 ms_global->pineExeAlt = freepineExe;
1804 else{
1805 ms_global->pineExeAlt = (char *)fs_get((strlen(strrchr(defPath, '\\')+1)+1)*sizeof(char));
1806 if(!ms_global->pineExeAlt){
1807 ErrorBox("Couldn't fs_get for %s","pineExeAlt");
1808 return 0;
1810 else
1811 strcpy(ms_global->pineExeAlt, strrchr(defPath, '\\')+1);
1815 * get path to pinerc from registry
1817 if (RegOpenKeyEx(
1818 HKEY_CURRENT_USER,
1819 "Software\\University of Washington\\Alpine\\1.0",
1821 KEY_QUERY_VALUE,
1822 &pineKey) == ERROR_SUCCESS) {
1823 pineKeyDataSize = sizeof(pineKeyData);
1824 if( RegQueryValueEx(
1825 pineKey,
1826 "PineRC",
1828 &pineKeyDataType,
1829 pineKeyData,
1830 &pineKeyDataSize) == ERROR_SUCCESS) {
1831 if(*pineKeyData != '{' || ms_global->pineExe)
1832 ms_global->attachDir = (char *)fs_get(sizeof(char)*(*pineKeyData == '{' ?
1833 pineKeyDataSize + 1 :
1834 strlen(ms_global->pineExe)+1));
1835 ms_global->pinerc = (char *)fs_get(pineKeyDataSize);
1836 if(ms_global->attachDir){
1837 char *p;
1838 if(*pineKeyData != '{'){
1839 strncpy(ms_global->attachDir, pineKeyData, pineKeyDataSize);
1840 ms_global->attachDir[pineKeyDataSize] = '\0';
1842 else
1843 strcpy(ms_global->attachDir, ms_global->pineExe);
1844 p = strrchr(ms_global->attachDir, '\\');
1845 if (p) *p = '\0';
1847 if(ms_global->pinerc)
1848 strncpy(ms_global->pinerc, pineKeyData, pineKeyDataSize);
1849 else {
1850 ErrorBox("MAPISendMail: can't fs_get %d bytes for pinercPath",
1851 pineKeyDataSize);
1852 return 0;
1854 if (MSDEBUG) {
1855 fprintf(ms_global->dfd, "pinerc pineKeyDataSize: %d\r\n", pineKeyDataSize);
1856 fprintf(ms_global->dfd, "pinerc pineKeyData: %s\r\n", pineKeyData);
1857 fprintf(ms_global->dfd, "attachDir: %s\r\n",
1858 ms_global->attachDir ? ms_global->attachDir :
1859 "NOT YET DEFINED");
1862 pineKeyDataSize = sizeof(pineKeyData);
1863 if( RegQueryValueEx(
1864 pineKey,
1865 "PineConf",
1867 &pineKeyDataType,
1868 pineKeyData,
1869 &pineKeyDataSize) == ERROR_SUCCESS){
1870 ms_global->pineconf = mstrdup(pineKeyData);
1871 msprint1("ms_global->pineconf: %s (due to Registry setting)\r\n", ms_global->pineconf);
1873 RegCloseKey(pineKey);
1876 if(ms_global->attachDir == NULL){
1877 if(ms_global->attachDir = (char *)fs_get((strlen(defAttachDir)+1)*sizeof(char)))
1878 strcpy(ms_global->attachDir, defAttachDir);
1879 else
1880 ErrorBox("Can't find TEMP directory for %s!","attachments");
1884 if(penv = getenv("PINERC")){
1885 if(ms_global->pinerc)
1886 fs_give((void **)&ms_global->pinerc);
1887 if(ms_global->pinerc = (char *)fs_get((strlen(penv)+1)*sizeof(char)))
1888 strcpy(ms_global->pinerc, penv);
1889 else
1890 ErrorBox("Couldn't fs_get for %s", "pinerc");
1892 if(penv = getenv("PINECONF")){
1893 if(ms_global->pineconf)
1894 fs_give((void **)&ms_global->pineconf);
1895 if(ms_global->pineconf = (char *)fs_get((strlen(penv)+1)*sizeof(char)))
1896 strcpy(ms_global->pineconf, penv);
1897 else
1898 ErrorBox("Couldn't fs_get for %s", "pineconf");
1900 else{
1903 if(penv = getenv("PINERCEX")){
1904 if(ms_global->pinercex)
1905 fs_give((void **)&ms_global->pinercex);
1906 if(ms_global->pinercex = mstrdup(penv))
1907 strcpy(ms_global->pinercex, penv);
1908 else
1909 ErrorBox("Couldn't fs_get for %s", "pinercex");
1911 if(MSDEBUG){
1912 fprintf(ms_global->dfd,"ms_global->pineExe: %s\r\n",
1913 (ms_global->pineExe) ? ms_global->pineExe : "NULL");
1914 fprintf(ms_global->dfd,"ms_global->pineExeAlt: %s\r\n",
1915 ms_global->pineExeAlt ? ms_global->pineExeAlt : "NULL");
1916 fprintf(ms_global->dfd,"ms_global->attachDir: %s\r\n",
1917 ms_global->attachDir ? ms_global->attachDir : "NULL");
1918 fprintf(ms_global->dfd,"ms_global->pinerc: %s\r\n",
1919 ms_global->pinerc ? ms_global->pinerc : "NULL");
1920 fprintf(ms_global->dfd,"ms_global->pineconf: %s\r\n",
1921 ms_global->pinerc ? ms_global->pineconf : "NULL");
1922 fprintf(ms_global->dfd,"ms_global->pinercex: %s\r\n",
1923 ms_global->pinerc ? ms_global->pinercex : "NULL");
1925 return 1;
1928 BOOL APIENTRY DllMain(
1929 HANDLE hInst,
1930 DWORD ul_reason_being_called,
1931 LPVOID lpReserved)
1933 switch(ul_reason_being_called){
1934 case DLL_THREAD_ATTACH:
1935 /* if(ms_global)
1936 * return 1;
1938 case DLL_PROCESS_ATTACH:
1939 if(!ms_global)
1940 ms_global = new_mapi_global();
1941 if(!ms_global) return 0;
1942 ms_global->attached++;
1943 ms_global->mhinst = hInst;
1944 if(InitDebug() == -1){
1945 ErrorBox("Mapi32.dll could not %s", "initialize");
1946 return 0;
1948 if(MSDEBUG && ms_global->attached <= 1){
1949 time_t now;
1950 struct tm *tm_now;
1951 extern char datestamp[], hoststamp[];
1953 now = time((time_t *)0);
1954 tm_now = localtime(&now);
1955 fprintf(ms_global->dfd, "pmapi32.dll for Alpine Version 2.21.9\r\n");
1956 fprintf(ms_global->dfd, " Build date: %s\r\n", datestamp);
1957 fprintf(ms_global->dfd,
1958 " please report all bugs to chappa@gmx.com\r\n");
1959 if(tm_now)
1960 fprintf(ms_global->dfd,
1961 "Created: %2.2d:%2.2d:%2.2d %d/%d/%d\r\n",
1962 tm_now->tm_hour, tm_now->tm_min, tm_now->tm_sec,
1963 tm_now->tm_mon+1, tm_now->tm_mday, tm_now->tm_year+1900);
1965 fprintf(ms_global->dfd, "\r\n\r\n");
1967 DEBUG_WRITE("%s called. Debug initialized (in DllMain)\r\n",
1968 ul_reason_being_called == DLL_PROCESS_ATTACH ?
1969 "DLL_PROCESS_ATTACH":"DLL_THREAD_ATTACH");
1970 GetPineData();
1971 #include "../c-client-dll/linkage.c"
1972 break;
1973 case DLL_PROCESS_DETACH:
1974 case DLL_THREAD_DETACH:
1975 DEBUG_WRITE("\r\n%s called\r\n",
1976 ul_reason_being_called == DLL_PROCESS_DETACH ?
1977 "DLL_PROCESS_DETACH" : "DLL_THREAD_DETACH");
1978 ms_global->attached--;
1979 /* if(ms_global->open_stream)
1980 * ms_global->open_stream = mail_close_full(ms_global->open_stream, NIL);
1982 if(ms_global->attached <= 0 &&
1983 ul_reason_being_called == DLL_PROCESS_DETACH){
1984 if(MSDEBUG)
1985 fprintf(ms_global->dfd,
1986 "detaching last thread/process. freeing mapi global struct\r\n");
1987 free_mapi_global(ms_global);
1989 break;
1991 return 1;
1994 static char *V="\r\n@(#) Alpine Simple Mapi Library Ver. 1.3\r\n";
1997 UnderlineSpace(char *s)
1999 char *p;
2001 if(p = strrchr(s, '\\'))
2002 s = p++;
2004 for(; *s; s++)
2005 if(*s == ' ')
2006 *s = '_';
2007 return 1;
2011 * Given source file name and destination directory, make a binary copy
2012 * of the file and return the full name of the copy (mangled as necessary
2013 * to avoid conflicts). The return value will be a fs_get'd string
2015 char *
2016 TmpCopy(char *srcFile, int is_pinerc)
2018 char *dstName; /* constructed and fs_get'd full output pathname */
2019 char *srcTail; /* last component of source pathname */
2020 char *srcExt; /* extension, if any, of srcTail */
2021 char dstDir[1024];
2022 int i, cnt, c, len, spc = 0;
2023 FILE *sfd, *dfd;
2025 if (!srcFile) {
2026 ErrorBox("TmpCopy: srcFile is %s", "NULL");
2027 return NULL;
2029 if(is_pinerc){
2030 len = strlen(srcFile);
2031 for(i = 0; i < len; i++){
2032 if(srcFile[i] == ' ') spc = 1;
2034 if(spc == 0) return mstrdup(srcFile);
2037 get_suggested_directory(dstDir);
2038 if (!dstDir) {
2039 ErrorBox("TmpCopy: dstDir is %s", "NULL");
2040 return NULL;
2043 dstName = (char *)fs_get(sizeof(char)*(strlen(srcFile) + 5 +
2044 max(strlen(dstDir), strlen(PINERC_FILE))));
2046 if (dstName == NULL) {
2047 ErrorBox("TmpCopy: can't fs_get space %d bytes for dstName",
2048 strlen(srcFile)+5+max(strlen(dstDir),strlen(PINERC_FILE)));
2049 return NULL;
2052 if(!is_pinerc){
2053 srcTail = strrchr(srcFile, '\\');
2054 if (srcTail)
2055 ++srcTail;
2056 else
2057 srcTail = srcFile;
2059 srcExt = strrchr(srcTail, '.');
2061 sfd = fopen(srcFile, "rb");
2062 if (sfd == NULL) {
2063 ErrorBox("TmpCopy: can't open %.200s for reading", srcFile);
2064 fs_give((void **)&dstName);
2065 return NULL;
2068 i = sprintf(dstName, "%s%s%s", dstDir,
2069 dstDir[strlen(dstDir)-1] == '\\' ? "" : "\\",
2070 srcTail);
2071 UnderlineSpace(dstName);
2072 for (cnt = 0; cnt < 1000; ++cnt) {
2073 int handle = _open(dstName, _O_CREAT|_O_EXCL , _S_IREAD|_S_IWRITE);
2074 if (handle != -1) {
2075 if (_close(handle)) /* this shouldn't be able to happen */
2076 ErrorBox("TmpCopy: _close of new %.200s failed", dstName);
2077 dfd = fopen(dstName, "wb");
2078 if (dfd) break;
2080 if (srcExt)
2081 sprintf(dstName+i-strlen(srcExt), "%03d%s", cnt, srcExt);
2082 else
2083 sprintf(dstName+i, "%03d", cnt);
2085 if (dfd == NULL) {
2086 ErrorBox("TmpCopy: can't create anything like %.200s", dstName);
2087 fclose(sfd);
2088 fs_give((void **)&dstName);
2089 return NULL;
2092 else{ /* is_pinerc */
2093 i = sprintf(dstName, "%s%s%s", dstDir,
2094 dstDir[strlen(dstDir)-1] == '\\' ? "" : "\\",
2095 PINERC_FILE);
2096 dfd = fopen(dstName, "wb");
2097 if(!dfd){
2098 ErrorBox("Couldn't create temp %s for pine", "pinerc");
2099 fs_give((void **)&dstName);
2100 return NULL;
2102 sfd = fopen(srcFile, "rb");
2103 if (sfd == NULL) {
2104 ErrorBox("TmpCopy: can't open %.200s for reading", srcFile);
2105 fclose(dfd);
2106 fs_give((void **)&dstName);
2107 return NULL;
2110 c = fgetc(sfd);
2111 while(feof(sfd) == 0) {
2112 putc(c, dfd);
2113 c = fgetc(sfd);
2115 if (ferror(dfd)) {
2116 ErrorBox("TmpCopy: write error on %.200s", dstName);
2117 fs_give((void **)&dstName);
2118 fclose(dfd);
2119 return NULL;
2121 if (ferror(sfd)) {
2122 ErrorBox("TmpCopy: read error on %.200s", srcFile);
2123 fs_give((void **)&dstName);
2124 fclose(sfd);
2125 return NULL;
2127 if (fclose(sfd)) {
2128 ErrorBox("TmpCopy: fclose error on %.200s", srcFile);
2130 if (fclose(dfd)) {
2131 ErrorBox("TmpCopy: fclose error on %.200s", dstName);
2134 return dstName;
2137 int send_documents(char *files, char sep)
2139 int ac, i, tmplen, j;
2140 char **av, *tmpfiles, *file, *tmpfree;
2141 mapi_global_s *nmg;
2143 nmg = ms_global;
2144 ac = 3;
2145 tmplen = strlen(files);
2146 tmpfiles = (char *)fs_get(sizeof(char)*(tmplen + 1));
2147 strcpy(tmpfiles,files);
2148 for(i = 0; i <= tmplen; i++){
2149 if(files[i] == sep || files[i] == '\0')
2150 ac += 2;
2152 ac += 2; /* just for safe measure */
2153 av = (char **)fs_get(ac * sizeof(char *));
2154 if(nmg->pinerc){
2155 av[1] = mstrdup("-p");
2156 /* copy pinerc to temp directory just in case it too
2157 * has spaces in its directory
2159 if(tmpfree = TmpCopy(nmg->pinerc, IS_PINERC)){
2160 av[2] = quote(tmpfree);
2161 fs_give((void **)&tmpfree);
2163 else
2164 av[2] = quote(nmg->pinerc);
2166 for(i = 0, j = 3, file = tmpfiles; i <= tmplen; i++){
2167 if(tmpfiles[i] == sep || i == tmplen){
2168 tmpfiles[i] = '\0';
2169 if(i - (file - tmpfiles) > 1){
2170 tmpfree = TmpCopy(file, NOT_PINERC);
2171 if(tmpfree){
2172 av[j++] = mstrdup("-attach_and_delete");
2173 av[j++] = quote(tmpfree);
2174 fs_give((void **)&tmpfree);
2179 av[j] = NULL;
2180 av[0] = quote(nmg->pineExe);
2181 if(MSDEBUG){
2182 fprintf(ms_global->dfd, "spawning %s (else %s):\r\n",
2183 ms_global->pineExe, ms_global->pineExeAlt);
2184 fprintf(nmg->dfd, " av:\r\n");
2185 for(i = 0; av[i]; i++)
2186 fprintf(nmg->dfd, " av[%d]: %s\r\n", i, av[i]);
2189 /* clean up quote()'s */
2190 if (_spawnvp(_P_NOWAIT, ms_global->pineExe, av) == -1 &&
2191 _spawnvp(_P_NOWAIT, ms_global->pineExeAlt, av) == -1){
2192 ErrorBox("MAPISendMail: _spawnvp of %s failed", ms_global->pineExe);
2193 if(MSDEBUG)
2194 fprintf(ms_global->dfd, "_spawnvp %s and %s failed\r\n",
2195 ms_global->pineExe,ms_global->pineExeAlt);
2196 return(MAPI_E_FAILURE);
2198 for(i = 0; av[i]; i++)
2199 fs_give((void **)&av[i]);
2200 fs_give((void **)&av);
2201 return SUCCESS_SUCCESS;
2204 char *
2205 message_structure_to_mailto_url(lpMapiMessage lpm)
2207 char **keyvals, **keyvalp, *url;
2208 int keyvallen;
2209 unsigned long i, url_len = 0;
2211 if(lpm == NULL)
2212 return NULL;
2214 keyvallen = lpm->nRecipCount + 4; /* subject + body + from + recips + NULL */
2215 keyvals = (char **)fs_get(keyvallen * sizeof(char *));
2216 keyvalp = keyvals;
2218 for(i = 0; i < lpm->nRecipCount; i++)
2219 *keyvalp++ = encode_mailto_addr_keyval(&lpm->lpRecips[i]);
2220 if(lpm->lpszSubject)
2221 *keyvalp++ = encode_mailto_keyval("subject", lpm->lpszSubject);
2222 if(lpm->lpOriginator)
2223 *keyvalp++ = encode_mailto_addr_keyval(lpm->lpOriginator);
2224 if(lpm->lpszNoteText)
2225 *keyvalp++ = encode_mailto_keyval("body", lpm->lpszNoteText);
2226 *keyvalp = NULL;
2228 if(*keyvals == NULL){
2229 fs_give((void **)&keyvals);
2230 return(NULL);
2233 url_len = keyvallen + 10; /* mailto url extra chars */
2234 for(keyvalp = keyvals; *keyvalp; keyvalp++)
2235 url_len += strlen(*keyvalp);
2237 url = (char *)fs_get(url_len * sizeof(char));
2238 sprintf(url, "mailto:?");
2239 for(keyvalp = keyvals; *keyvalp; keyvalp++){
2240 strcat(url, *keyvalp);
2241 if(*(keyvalp+1))
2242 strcat(url, "&");
2243 fs_give((void **)&(*keyvalp));
2245 fs_give((void **)&keyvals);
2246 return url;
2249 char *
2250 encode_mailto_addr_keyval(lpMapiRecipDesc lpmr)
2252 ADDRESS *adr = NULL;
2253 char *addr, *retstr;
2254 int use_quotes = 0;
2256 adr = mapirecip2address(lpmr);
2257 addr = (char *)fs_get((size_t)est_size(adr));
2258 addr[0] = '\0';
2259 rfc822_write_address(addr, adr);
2260 mail_free_address(&adr);
2262 retstr = encode_mailto_keyval(lpmr->ulRecipClass == MAPI_CC ? "cc"
2263 : (lpmr->ulRecipClass == MAPI_BCC ? "bcc"
2264 : (lpmr->ulRecipClass == MAPI_ORIG ? "from"
2265 : "to")),
2266 addr);
2267 fs_give((void **)&addr);
2268 return(retstr);
2274 * Hex conversion aids from alpine.h
2276 #define HEX_ARRAY "0123456789ABCDEF"
2277 #define HEX_CHAR1(C) HEX_ARRAY[((C) & 0xf0) >> 4]
2278 #define HEX_CHAR2(C) HEX_ARRAY[(C) & 0xf]
2280 /* strings.c macros */
2281 #define C2XPAIR(C, S) { \
2282 *(S)++ = HEX_CHAR1(C); \
2283 *(S)++ = HEX_CHAR2(C); \
2286 #define RFC1738_SAFE "$-_.+" /* "safe" */
2287 #define RFC1738_EXTRA "!*'()," /* "extra" */
2289 /* adapted from rfc1738_encode_mailto */
2290 char *
2291 encode_mailto_keyval(char *key, char* val)
2293 char *d, *ret = NULL, *v = val;
2295 if(key && val){
2296 ret = (char *)fs_get(sizeof(char) * (strlen(key) + (3*strlen(val)) + 2));
2297 strcpy(ret, key);
2298 d = ret + strlen(key);
2299 *d++ = '=';
2300 while(*v){
2301 if(isalnum((unsigned char)*v)
2302 || strchr(RFC1738_SAFE, *v)
2303 || strchr(RFC1738_EXTRA, *v))
2304 *d++ = *v++;
2305 else{
2306 *d++ = '%';
2307 C2XPAIR(*v, d);
2308 v++;
2311 *d = '\0';
2314 return(ret);
2317 unsigned long
2318 send_msg_nodlg(LHANDLE lhSession, ULONG ulUIParam, lpMapiMessage lpMessage,
2319 FLAGS flFlags, ULONG ulReserved)
2321 sessionlist_s *cs;
2322 int tsession = 0, orig_in_recip = 0;
2323 unsigned long i, orig_index;
2324 ADDRESS *tadr = NULL, *tadr2 = NULL;
2325 ENVELOPE *env = NULL;
2326 BODY *body = NULL;
2327 mapi_global_s *nmg = ms_global;
2328 SENDSTREAM *sending_stream = NULL;
2329 unsigned long rv;
2330 time_t now;
2331 struct tm *tm_now;
2332 char *p = NULL;
2334 if(nmg->pmapi_send_behavior == PMSB_NEVER_SEND)
2335 return MAPI_E_USER_ABORT;
2336 else if(nmg->pmapi_send_behavior == PMSB_ALWAYS_PROMPT){
2337 if(MessageBox(NULL, "Really Send Message?", "pmapi32.dll", MB_YESNO|MB_ICONQUESTION) == IDNO)
2338 return MAPI_E_USER_ABORT;
2340 if((flFlags & MAPI_NEW_SESSION) || lhSession == 0){
2341 cs = new_sessionlist();
2342 tsession = 1;
2344 else{
2345 cs = get_session(lhSession);
2346 if(!cs)
2347 return MAPI_E_INVALID_SESSION;
2349 cs->flags.mapi_logon_ui = (flFlags & MAPI_LOGON_UI) || (flFlags & MAPI_DIALOG) ? 1 : 0;
2350 if(InitPineSpecific(cs) == -1){
2351 rv = MAPI_E_LOGIN_FAILURE;
2352 goto smn_cleanup;
2354 msprint("Preparing to Send Message with no dialogs...\r\n");
2355 /* Make an envelope */
2356 env = (ENVELOPE *)fs_get(sizeof(ENVELOPE));
2357 memset(env, 0, sizeof(ENVELOPE));
2358 if(lpMessage->lpszSubject){
2359 p = rfc1522_encode(tmp_20k_buf, SIZEOF_20KBUF, lpMessage->lpszSubject,
2360 nmg->prcvars[CHARACTER_SET]->val.p);
2361 env->subject = mstrdup(p);
2362 if(MSDEBUG)
2363 fprintf(ms_global->dfd, " Subject: %s\r\n", env->subject);
2366 * Since it is "DateReceived", I think the right thing to do is ignore it,
2367 * since we're sending, not receiving.
2369 rfc822_date(tmp_20k_buf);
2370 env->date = mstrdup(tmp_20k_buf);
2371 msprint1(" Date: %s\r\n", env->date);
2372 env->message_id = pmapi_generate_message_id();
2373 msprint1(" Message-Id: %s\r\n", env->message_id);
2375 for(i = 0; i < lpMessage->nRecipCount; i++){
2376 if((&lpMessage->lpRecips[i])->ulRecipClass == MAPI_ORIG){
2377 orig_in_recip = 1;
2378 orig_index = i;
2382 if(lpMessage->lpOriginator || orig_in_recip){
2383 if((env->from = mapirecip2address(lpMessage->lpOriginator
2384 ? lpMessage->lpOriginator
2385 : (&lpMessage->lpRecips[orig_index])))
2386 == NULL){
2387 rv = MAPI_E_INVALID_RECIPS;
2388 goto smn_cleanup;
2390 if(MSDEBUG){
2391 sprintf(tmp_20k_buf, "%.100s <%.100s@%.100s>", env->from->personal ? env->from->personal
2392 : "", env->from->mailbox ? env->from->mailbox : "",
2393 env->from->host ? env->from->host : "");
2394 msprint1("From: %s\r\n", tmp_20k_buf);
2397 else if(nmg->prcvars[USER_ID]->val.p && nmg->prcvars[USER_DOMAIN]->val.p){
2399 * judgment call: I guess we'll try to generate the from header if it's not
2400 * given to us
2402 env->from = mail_newaddr();
2403 if(nmg->prcvars[PERSONAL_NAME]->val.p){
2404 p = rfc1522_encode(tmp_20k_buf, SIZEOF_20KBUF, nmg->prcvars[PERSONAL_NAME]->val.p,
2405 nmg->prcvars[CHARACTER_SET]->val.p);
2406 env->from->personal = mstrdup(p);
2408 env->from->mailbox = mstrdup(nmg->prcvars[USER_ID]->val.p);
2409 env->from->host = mstrdup(nmg->prcvars[USER_DOMAIN]->val.p);
2410 if(MSDEBUG){
2411 sprintf(tmp_20k_buf, "%.100s <%.100s@%.100s>", env->from->personal ? env->from->personal
2412 : "", env->from->mailbox ? env->from->mailbox : "",
2413 env->from->host ? env->from->host : "");
2414 msprint1("From: %s\r\n", tmp_20k_buf);
2417 for(i = 0; i < lpMessage->nRecipCount; i++){
2418 if((tadr = mapirecip2address(&lpMessage->lpRecips[i])) == NULL){
2419 rv = MAPI_E_INVALID_RECIPS;
2420 goto smn_cleanup;
2422 switch (lpMessage->lpRecips[i].ulRecipClass) {
2423 case MAPI_TO:
2424 case MAPI_ORIG:
2425 if(!env->to)
2426 env->to = tadr;
2427 else{
2428 for(tadr2 = env->to; tadr2->next; tadr2 = tadr2->next);
2429 tadr2->next = tadr;
2431 msprint(" To: ");
2432 break;
2433 case MAPI_CC:
2434 if(!env->cc)
2435 env->cc = tadr;
2436 else{
2437 for(tadr2 = env->cc; tadr2->next; tadr2 = tadr2->next);
2438 tadr2->next = tadr;
2440 msprint(" Cc: ");
2441 break;
2442 case MAPI_BCC:
2443 if(!env->bcc)
2444 env->bcc = tadr;
2445 else{
2446 for(tadr2 = env->bcc; tadr2->next; tadr2 = tadr2->next);
2447 tadr2->next = tadr;
2449 msprint(" Bcc: ");
2450 break;
2451 default:
2452 rv = MAPI_E_INVALID_RECIPS;
2453 goto smn_cleanup;
2454 break;
2456 if(MSDEBUG){
2457 sprintf(tmp_20k_buf, "%.100s <%.100s@%.100s>", tadr->personal ? tadr->personal
2458 : "", tadr->mailbox ? tadr->mailbox : "",
2459 tadr->host ? tadr->host : "");
2460 msprint1("%s\r\n", tmp_20k_buf);
2463 /* Now we have an envelope, let's make us a body */
2464 if(lpMessage->lpszNoteText == NULL)
2465 msprint("Empty Message Text\r\n");
2466 body = mail_newbody();
2467 if(lpMessage->nFileCount){
2468 PART *p;
2469 struct _stat sbuf;
2470 unsigned long fsize, n;
2471 FILE *sfd;
2472 char c, *fn;
2474 msprint1("Number of files to be Attached: %d\r\n", (void *)lpMessage->nFileCount);
2475 body->type = TYPEMULTIPART;
2476 body->nested.part = mail_newbody_part();
2477 p = body->nested.part;
2478 set_text_data(&p->body, lpMessage->lpszNoteText ? lpMessage->lpszNoteText
2479 : "");
2481 for(i = 0; i < lpMessage->nFileCount; i++){
2482 p->next = mail_newbody_part();
2483 p = p->next;
2484 p->body.encoding = ENCBINARY;
2485 if(lpMessage->lpFiles[i].lpszPathName == NULL)
2486 return(MAPI_E_FAILURE);
2487 if(lpMessage->lpFiles[i].lpszFileName == NULL
2488 || lpMessage->lpFiles[i].lpszFileName[0] == '\0'){
2489 fn = strrchr(lpMessage->lpFiles[i].lpszPathName, '\\');
2490 if(!fn)
2491 fn = lpMessage->lpFiles[i].lpszPathName;
2492 else
2493 fn++;
2495 else
2496 fn = lpMessage->lpFiles[i].lpszFileName;
2497 if(lookup_file_mime_type(fn, &p->body) && (fn == lpMessage->lpFiles[i].lpszFileName))
2498 lookup_file_mime_type(lpMessage->lpFiles[i].lpszPathName, &p->body);
2499 msprint1(" Attaching file %s;", lpMessage->lpFiles[i].lpszPathName);
2500 if(_stat(lpMessage->lpFiles[i].lpszPathName, &sbuf))
2501 return(MAPI_E_FAILURE);
2502 fsize = sbuf.st_size;
2503 if((sfd = fopen(lpMessage->lpFiles[i].lpszPathName, "rb")) == NULL)
2504 return(MAPI_E_FAILURE);
2505 p->body.contents.text.data = fs_get((fsize+1)*sizeof(char));
2506 n = 0;
2507 c = fgetc(sfd);
2508 while(feof(sfd) == 0){
2509 p->body.contents.text.data[n++] = c;
2510 if(n > fsize){
2511 fsize += 20000;
2512 fs_resize((void **)&p->body.contents.text.data, (fsize+1)*sizeof(char));
2514 c = fgetc(sfd);
2516 fclose(sfd);
2517 p->body.contents.text.data[n] = '\0';
2518 p->body.contents.text.size = n;
2519 msprint1(" File size: %d\r\n", (void *)n);
2520 if(fn){
2521 p->body.parameter = mail_newbody_parameter();
2522 p->body.parameter->attribute = mstrdup("name");
2523 p->body.parameter->value = mstrdup(fn);
2525 p->body.disposition.type = mstrdup("attachment");
2526 p->body.disposition.parameter = mail_newbody_parameter();
2527 p->body.disposition.parameter->attribute = mstrdup("filename");
2528 p->body.disposition.parameter->value = mstrdup(fn);
2532 else {
2533 set_text_data(body, lpMessage->lpszNoteText ? lpMessage->lpszNoteText
2534 : "");
2535 msprint1(" Message Body size: %d\r\n", (void *)body->contents.text.size);
2538 if(MSDEBUG){
2539 now = time((time_t *)0);
2540 tm_now = localtime(&now);
2541 fprintf(ms_global->dfd, "%2.2d:%2.2d:%2.2d %d/%d/%d ",
2542 tm_now->tm_hour, tm_now->tm_min, tm_now->tm_sec,
2543 tm_now->tm_mon+1, tm_now->tm_mday, tm_now->tm_year+1900);
2545 if(nmg->prcvars[SMTP_SERVER]->val.l && nmg->prcvars[SMTP_SERVER]->val.l[0]
2546 && nmg->prcvars[SMTP_SERVER]->val.l[0][0]){
2547 if(MSDEBUG){
2548 fprintf(ms_global->dfd, "Preparing to open SMTP connection (%s ...)\r\n",
2549 nmg->prcvars[SMTP_SERVER]->val.l[0]);
2550 _flushall();
2552 sending_stream = mapi_smtp_open(cs, nmg->prcvars[SMTP_SERVER]->val.l,
2553 nmg->prcfeats[ENABLE8BIT]->is_set ? SOP_8BITMIME : NIL);
2555 else {
2556 rv = MAPI_E_FAILURE;
2557 if(MSDEBUG){
2558 fprintf(ms_global->dfd, "Error! No SMTP server defined!\r\n");
2560 goto smn_cleanup;
2562 if(!sending_stream){
2563 rv = MAPI_E_FAILURE;
2564 if(MSDEBUG){
2565 fprintf(ms_global->dfd, "Couldn't open SMTP connection!\r\n");
2567 goto smn_cleanup;
2569 if(!smtp_mail(sending_stream, "MAIL", env, body)){
2570 if(MSDEBUG){
2571 fprintf(ms_global->dfd, "Attempt to Send Failed\r\n");
2573 rv = MAPI_E_FAILURE;
2575 else {
2576 if(MSDEBUG){
2577 fprintf(ms_global->dfd, "Message SENT!\r\n");
2579 if(!nmg->fccfolder)
2580 msprint("No fcc defined\r\n");
2581 else { /* Now try to write to fcc */
2582 STRBUFFER_S *sb;
2583 MAILSTREAM *fccstream;
2584 STRING msg;
2586 msprint1("FCCing to %s\r\n", nmg->fccfolder);
2587 sb = (STRBUFFER_S *)fs_get(sizeof(STRBUFFER_S));
2588 sb->buf = (char *)fs_get(20000*sizeof(char));
2589 sb->cur_bytes = 0;
2590 sb->increment = 20000;
2591 sb->bufsize = 20000;
2592 rfc822_output(tmp_20k_buf, env, body, pmapi_soutr, sb, 1);
2593 INIT(&msg, mail_string, (void *)sb->buf, sb->cur_bytes);
2594 fccstream = mapi_mail_open(cs, NULL, nmg->fccfolder, ms_global->debug ? OP_DEBUG : NIL);
2595 if(fccstream){
2596 if(mail_append(fccstream, nmg->fccfolder, &msg) == NIL)
2597 msprint1("Fcc to %s failed\r\n", nmg->fccfolder);
2598 else
2599 msprint1("Fcc to %s SUCCEEDED\r\n", nmg->fccfolder);
2600 mail_close(fccstream);
2602 else
2603 msprint1("Open of %s failed, abandoning FCC\r\n", nmg->fccfolder);
2604 if(sb->buf)
2605 fs_give((void **)&sb->buf);
2606 if(sb)
2607 fs_give((void **)&sb);
2609 if((flFlags & MAPI_LOGON_UI) || (flFlags & MAPI_DIALOG))
2610 MessageBox(NULL, "Message SENT!\r\n", "pmapi32.dll", MB_OK|MB_ICONINFORMATION);
2611 rv = SUCCESS_SUCCESS;
2613 smtp_close(sending_stream);
2614 smn_cleanup:
2615 if(env)
2616 mail_free_envelope(&env);
2617 if(body)
2618 mail_free_body(&body);
2619 if(tsession)
2620 fs_give((void **)&cs);
2621 return(rv);
2625 set_text_data(BODY *body, char *txt)
2627 char *p;
2628 int has_8bit = 0;
2629 PARAMETER *pm;
2631 for(p = txt; *p; p++)
2632 if(*p & 0x80)
2633 has_8bit++;
2635 body->contents.text.data = mstrdup(txt);
2636 body->contents.text.size = strlen(txt);
2637 if(has_8bit){
2638 body->encoding = ENC8BIT;
2639 if(!body->parameter)
2640 pm = body->parameter = mail_newbody_parameter();
2641 else {
2642 for(pm = body->parameter; pm->next; pm = pm->next);
2643 pm->next = mail_newbody_parameter();
2644 pm = pm->next;
2646 pm->attribute = mstrdup("charset");
2647 if(ms_global->prcvars[CHARACTER_SET]->val.p)
2648 pm->value = mstrdup(ms_global->prcvars[CHARACTER_SET]->val.p);
2649 else
2650 pm->value = mstrdup("X-UNKNOWN");
2652 return 0;
2655 long
2656 pmapi_soutr(STRBUFFER_S *s, char *str)
2658 unsigned long i;
2660 if(s->cur_bytes >= s->bufsize){
2661 fs_resize((void **)&s->buf, s->bufsize+ s->increment);
2662 s->bufsize += s->increment;
2664 for(i = 0; str[i]; i++){
2665 s->buf[s->cur_bytes++] = str[i];
2666 if(s->cur_bytes >= s->bufsize){
2667 fs_resize((void **)&s->buf, s->bufsize+ s->increment);
2668 s->bufsize += s->increment;
2671 s->buf[s->cur_bytes] = '\0';
2672 return T;
2675 ADDRESS *
2676 mapirecip2address(lpMapiRecipDesc lpmrd)
2678 ADDRESS *adr = NULL;
2679 static char *fakedomain = "@", *p;
2680 mapi_global_s *nmg = ms_global;
2682 if(!lpmrd->lpszAddress)
2683 return(NULL);
2684 rfc822_parse_adrlist(&adr, _strnicmp(lpmrd->lpszAddress, "SMTP:", 5) == 0
2685 ? lpmrd->lpszAddress + 5 : lpmrd->lpszAddress,
2686 nmg->prcvars[USER_DOMAIN]->val.p
2687 ? nmg->prcvars[USER_DOMAIN]->val.p : fakedomain);
2688 if(!adr)
2689 return(NULL);
2690 if(adr->next || adr->error){
2691 mail_free_address(&adr);
2692 return(NULL);
2695 if(lpmrd->lpszName && adr->personal)
2696 fs_give((void **)&adr->personal);
2697 if(lpmrd->lpszName){
2698 p = rfc1522_encode(tmp_20k_buf, SIZEOF_20KBUF, lpmrd->lpszName,
2699 nmg->prcvars[CHARACTER_SET]->val.p);
2700 adr->personal = mstrdup(p);
2702 return(adr);
2706 * given a fs_get'd string, return a newly fs_get'd quoted copy
2708 char *
2709 quote(char *old)
2711 char *new, *newp, *oldp;
2712 int newSize = strlen(old)*2+3;
2714 if (!old) return mstrdup(old);
2715 if(!strchr(old, ' ')) return mstrdup(old);
2717 newp = new = (char *)fs_get(sizeof(char)*newSize); /* worst case */
2718 if (new == NULL) {
2719 ErrorBox("quote: fs_get of %d bytes failed", newSize);
2720 return old;
2723 *newp++ = '"';
2724 for (oldp=old; *oldp; ++oldp) {
2725 switch(*oldp) {
2726 case '"': *newp++ = '\\'; /* fall through */
2727 default : *newp++ = *oldp;
2730 *newp++ = '"';
2731 *newp = '\0';
2732 return(new);
2736 int GetPCPineVersion(int *major, int *minor, int *minorminor)
2738 *major = 4;
2739 *minor = 52;
2740 *minorminor = 0;
2742 return 1;
2746 msprint(char *str)
2748 if(MSDEBUG)
2749 fprintf(ms_global->dfd, "%s", str);
2750 _flushall();
2751 return 0;
2755 msprint1(char *str, void *arg1)
2757 if(MSDEBUG)
2758 fprintf(ms_global->dfd, str, arg1);
2759 _flushall();
2760 return 0;
2763 int
2764 msprint_message_structure(lpMapiMessage lpm)
2766 unsigned long i;
2768 if(MSDEBUG){
2769 msprint1("lpMapiMessage: %p\r\n", lpm);
2770 if(!lpm)
2771 return 1;
2772 msprint1(" ulReserved: %d\r\n", (void *)lpm->ulReserved);
2773 msprint1(" lpszSubsect: %s\r\n", lpm->lpszSubject ? lpm->lpszSubject : "(NULL)");
2774 msprint1(" lpszNoteText size: %d\r\n", lpm->lpszNoteText
2775 ? (void *)strlen(lpm->lpszNoteText) : (void *)0);
2776 if(lpm->lpszNoteText)
2777 msprint1("\tleading text: %.10s\r\n", lpm->lpszNoteText);
2778 msprint1(" lpszMessageType: %s\r\n", lpm->lpszMessageType ? lpm->lpszMessageType : "(NULL)");
2779 msprint1(" lpszDateReceived: %s\r\n", lpm->lpszDateReceived ? lpm->lpszDateReceived : "(NULL)");
2780 msprint1(" lpszConversationID: %s\r\n", lpm->lpszConversationID ? lpm->lpszConversationID : "(NULL)");
2781 msprint1(" flFlags: %d\r\n", (void *)lpm->flFlags);
2782 msprint(" Originator:\r\n");
2783 msprint_recipient_structure(lpm->lpOriginator, 0);
2784 msprint1(" nRecipCount: %d\r\n", (void *)lpm->nRecipCount);
2785 for(i = 0; i < lpm->nRecipCount; i++)
2786 msprint_recipient_structure(&lpm->lpRecips[i], 1);
2787 msprint1(" nFileCount: %d\r\n", (void *)lpm->nFileCount);
2788 for(i = 0; i < lpm->nFileCount; i++)
2789 msprint_file_structure(&lpm->lpFiles[i]);
2790 msprint("\r\n");
2792 return 0;
2796 msprint_recipient_structure(lpMapiRecipDesc lmrd, int mapi_orig_is_unexpected)
2798 if(MSDEBUG){
2799 msprint1(" lpMapiRecipDesc: %p\r\n", (void *)lmrd);
2800 if(lmrd == NULL)
2801 return 1;
2802 msprint1(" ulReserved: %d\r\n", (void *)lmrd->ulReserved);
2803 msprint1(" ulRecipClass: %s\r\n", lmrd->ulRecipClass == MAPI_ORIG ? "MAPI_ORIG"
2804 : lmrd->ulRecipClass == MAPI_TO ? "MAPI_TO" : lmrd->ulRecipClass == MAPI_CC
2805 ? "MAPI_CC" : "MAPI_BCC");
2806 if(mapi_orig_is_unexpected && lmrd->ulRecipClass == MAPI_ORIG){
2807 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");
2809 msprint1(" lpszName: %s\r\n", lmrd->lpszName ? lmrd->lpszName : "(NULL)");
2810 msprint1(" lpszAddress: %s\r\n", lmrd->lpszAddress ? lmrd->lpszAddress : "(NULL)");
2811 msprint1(" ulEIDSize: %p\r\n", (void *)lmrd->ulEIDSize);
2812 msprint1(" lpEntryID: %p\r\n", (void *)lmrd->lpEntryID);
2814 return 0;
2819 msprint_file_structure(lpMapiFileDesc lmfd)
2821 if(MSDEBUG){
2822 msprint1(" lpMapiFileDesc: %p\r\n", (void *)lmfd);
2823 if(lmfd == NULL)
2824 return 1;
2825 msprint1(" ulReserved: %d\r\n", (void *)lmfd->ulReserved);
2826 msprint1(" flFlags: %d\r\n", (void *)lmfd->flFlags);
2827 msprint1(" nPosition: %d\r\n", (void *)lmfd->nPosition);
2828 msprint1(" lpszPathName: %s\r\n", lmfd->lpszPathName ? lmfd->lpszPathName : "(NULL)");
2829 msprint1(" lpszFileName: %s\r\n", lmfd->lpszFileName ? lmfd->lpszFileName : "(NULL)");
2830 msprint1(" lpFileType: %p\r\n", (void *)lmfd->lpFileType);
2832 return 0;
2836 char *mstrdup(char *old)
2838 char *tmp;
2840 tmp = fs_get((strlen(old)+1) * sizeof(char));
2841 strcpy(tmp, old);
2843 return tmp;
2847 est_size(a)
2848 ADDRESS *a;
2850 int cnt = 0;
2852 for(; a; a = a->next){
2854 /* two times personal for possible quoting */
2855 cnt += 2 * (a->personal ? strlen(a->personal) : 0);
2856 cnt += (a->mailbox ? strlen(a->mailbox) : 0);
2857 cnt += (a->adl ? strlen(a->adl) : 0);
2858 cnt += (a->host ? strlen(a->host) : 0);
2861 * add room for:
2862 * possible single space between fullname and addr
2863 * left and right brackets
2864 * @ sign
2865 * possible : for route addr
2866 * , <space>
2868 * So I really think that adding 7 is enough. Instead, I'll add 10.
2870 cnt += 10;
2873 return(max(cnt, 50)); /* just making sure */
2876 void ErrorBoxFunc(char *msg)
2878 if(MSDEBUG){
2879 fprintf(ms_global->dfd,"ErrorBox: %s\r\n", msg);
2880 fclose(ms_global->dfd);
2881 ms_global->dfd = fopen(ms_global->debugFile, "ab");
2882 if(!ms_global->dfd){
2883 MessageBox(NULL, "debug file problems! Debugging turned off.",
2884 "mapi32.dll",
2885 MB_OK|MB_ICONERROR);
2886 ms_global->debug = 0;
2887 fs_give((void **)&ms_global->debugFile);
2888 ms_global->debugFile = NULL;
2891 MessageBox(NULL, msg, "mapi32.dll", MB_OK|MB_ICONERROR);
2894 /*----------------------------------------------------------------------
2895 This was borrowed from reply.c, and modified
2896 Generate a unique message id string.
2898 Args: ps -- The usual pine structure
2900 Result: Alloc'd unique string is returned
2902 Uniqueness is gaurenteed by using the host name, process id, date to the
2903 second and a single unique character
2904 *----------------------------------------------------------------------*/
2905 char *
2906 pmapi_generate_message_id()
2908 static short osec = 0, cnt = 0;
2909 char *id;
2910 time_t now;
2911 struct tm *now_x;
2913 now = time((time_t *)0);
2914 now_x = localtime(&now);
2915 id = (char *)fs_get(128 * sizeof(char));
2917 if(now_x->tm_sec == osec){
2918 cnt++;
2919 }else{
2920 cnt = 0;
2921 osec = now_x->tm_sec;
2923 sprintf(id,"<Pmapi32.%04d%02d%02d%02d%02d%02d%X.%d@%.50s>",
2924 (now_x->tm_year) + 1900, now_x->tm_mon + 1,
2925 now_x->tm_mday, now_x->tm_hour, now_x->tm_min, now_x->tm_sec,
2926 cnt, getpid(), mylocalhost());
2928 return(id);