1 
2 /*
3  * ========================================================================
4  * Copyright 2006-2009 University of Washington
5  *
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
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * ========================================================================
13  */
14 
15 #include "pmapi.h"
16 
17 static	int		xlate_key;
18 
19 mapi_global_s *ms_global = NULL;
20 #define SIZEOF_20KBUF (20480)
21 char         tmp_20k_buf[SIZEOF_20KBUF];
22 
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);
71 
72 
mm_searched(MAILSTREAM * stream,unsigned long number)73 void mm_searched (MAILSTREAM *stream,unsigned long number)
74 {
75     if(MSDEBUG){
76       fprintf(ms_global->dfd, "IMAP mm_searched: not implemented\r\n");
77       _flushall();
78     }
79 }
80 
mm_exists(MAILSTREAM * stream,unsigned long number)81 void mm_exists (MAILSTREAM *stream,unsigned long number)
82 {
83     if(MSDEBUG){
84       fprintf(ms_global->dfd, "IMAP mm_exists: not implemented\r\n");
85       _flushall();
86     }
87 }
88 
mm_expunged(MAILSTREAM * stream,unsigned long number)89 void mm_expunged (MAILSTREAM *stream,unsigned long number)
90 {
91     if(MSDEBUG){
92       fprintf(ms_global->dfd, "IMAP mm_expunged: not implemented\r\n");
93       _flushall();
94     }
95 }
96 
mm_flags(MAILSTREAM * stream,unsigned long number)97 void mm_flags (MAILSTREAM *stream,unsigned long number)
98 {
99     if(MSDEBUG){
100       fprintf(ms_global->dfd, "IMAP mm_flags: number is %d\r\n", number);
101       _flushall();
102     }
103 }
104 
mm_notify(MAILSTREAM * stream,char * string,long errflg)105 void mm_notify (MAILSTREAM *stream,char *string,long errflg)
106 {
107     mapi_global_s *nmg;
108 
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();
117     }
118 }
119 
mm_list(MAILSTREAM * stream,int delimiter,char * name,long attributes)120 void mm_list (MAILSTREAM *stream,int delimiter,char *name,long attributes)
121 {
122     if(MSDEBUG){
123       fprintf(ms_global->dfd, "IMAP mm_list: not implemented\r\n");
124       _flushall();
125     }
126 }
127 
mm_lsub(MAILSTREAM * stream,int delimiter,char * name,long attributes)128 void mm_lsub (MAILSTREAM *stream,int delimiter,char *name,long attributes)
129 {
130     if(MSDEBUG){
131       fprintf(ms_global->dfd, "IMAP mm_lsub: not implemented\r\n");
132       _flushall();
133     }
134 }
135 
mm_status(MAILSTREAM * stream,char * mailbox,MAILSTATUS * status)136 void mm_status (MAILSTREAM *stream,char *mailbox,MAILSTATUS *status)
137 {
138     if(MSDEBUG){
139       fprintf(ms_global->dfd, "IMAP mm_status: not implemented\r\n");
140       _flushall();
141     }
142 }
143 
mm_log(char * string,long errflg)144 void mm_log (char *string,long errflg)
145 {
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();
153     }
154     if(errflg == ERROR)
155       ErrorBox("ERROR: %s", string);
156 }
157 
mm_dlog(char * string)158 void mm_dlog (char *string)
159 {
160     if(MSDEBUG){
161       time_t now;
162       struct tm *tm_now;
163 
164       now = time((time_t *)0);
165       tm_now = localtime(&now);
166 
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();
171     }
172 }
173 
fetch_recursively(BODY * body,long msgno,char * prefix,PART * part,long flags,FLAGS MAPIflags,sessionlist_s * cs)174 int fetch_recursively(BODY *body, long msgno, char *prefix, PART *part,
175 		      long flags, FLAGS MAPIflags, sessionlist_s *cs)
176 {
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;
188 
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);
195     }
196     else{
197       do{
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);
204 	}
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;
215 	      }
216 	      cs->lpm->lpszNoteText = mstrdup(tmpatt);
217 	      tmpatt = NULL;
218 	    }
219 	    else
220 	      cs->lpm->lpszNoteText = mstrdup("");
221 	    if(MAPIflags & MAPI_SUPPRESS_ATTACH)
222 	      return 0;
223 	  }
224 	  if(tmpatt && part && part->body.encoding == ENCBASE64){
225 	    decf = rfc822_base64(tmpatt, tmpattlen, &declen);
226 	    tmpatt = NULL;
227 	  }
228 	  else if(tmpatt && part && part->body.encoding == ENCQUOTEDPRINTABLE){
229 	    decf = rfc822_qprint(tmpatt, tmpattlen, &declen);
230 	    tmpatt = NULL;
231 	  }
232 	  else{
233 	    if(tmpatt){
234 	      decf = mstrdup(tmpatt);
235 	      declen = tmpattlen;
236 	    }
237 	    else decf = NULL;
238 	  }
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';
246 	    }
247 	    file_ext[0] = '\0';
248 	    get_suggested_file_ext(file_ext,part, &file_extlen);
249 	    do{
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;
269 	      }
270 	    }
271 	    else{
272 	      if(MSDEBUG)
273 		fprintf(nmg->dfd,"Failure in opening %s for attachment\r\n",
274 			filename);
275 	    }
276 	  }
277 	}
278       }while(part && (part = part->next));
279     }
280     return 0;
281 }
282 
fetch_structure_and_attachments(long msgno,long flags,FLAGS MAPIflags,sessionlist_s * cs)283 int fetch_structure_and_attachments(long msgno, long flags,
284 				    FLAGS MAPIflags, sessionlist_s *cs)
285 {
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 */
295 
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;
302     }
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;
309     }
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);
321     }
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);
330       }
331       cs->lpm->lpOriginator->ulRecipClass = MAPI_ORIG;
332     }
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;
340 	}
341       }
342       if(env->cc){
343 	addr = env->cc;
344 	while(addr){
345 	  recips++;
346 	  addr = addr->next;
347 	}
348       }
349       if(env->bcc){
350 	addr = env->bcc;
351 	while(addr){
352 	  recips++;
353 	  addr = addr->next;
354 	}
355       }
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);
368 	  }
369 	  recips++;
370 	  addr = addr->next;
371 	}
372       }
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);
382 	  }
383 	  recips++;
384 	  addr = addr->next;
385 	}
386       }
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);
396 	  }
397 	  recips++;
398 	  addr = addr->next;
399 	}
400       }
401     }
402 
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;
412       }
413       else if(MSDEBUG)
414 	fprintf(nmg->dfd, "Message has already been marked seen\r\n");
415     }
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);
424       }
425       cs->lpm->nFileCount = file_count;
426       free_file_s(cs->fs);
427       cs->fs = NULL;
428     }
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");
441       }
442     }
443     return SUCCESS_SUCCESS;
444 }
445 
Login(HWND hDlg,UINT message,WPARAM wParam,LPARAM lParam)446 LRESULT CALLBACK Login(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
447 {
448     mapi_global_s *nmg;
449 
450     nmg = ms_global;
451 
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);
458       }
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;
471       }
472       else if(LOWORD(wParam) == IDCANCEL){
473 	nmg->cs->flags.dlg_cancel = 1;
474 	EndDialog(hDlg, LOWORD(wParam));
475 	return TRUE;
476       }
477       break;
478     }
479     return FALSE;
480 }
481 
mm_login(NETMBX * mb,char * user,char * pwd,long trial)482 void mm_login (NETMBX *mb,char *user,char *pwd,long trial)
483 {
484     mapi_global_s *nmg;
485     pw_cache_s *tpwc, *dpwc;
486     int tmp_set_mbx = 0;
487 
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;
494 	}
495 	if(tpwc){
496 	    strcpy(user, tpwc->user);
497 	    strcpy(pwd, tpwc->pwd);
498 	    tpwc->validpw = 0;
499 	}
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;
505 	    }
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);
521 		    }
522 		    else
523 		      tpwc = tpwc->next;
524 		}
525 		if(nmg->cs->pwc == NULL){
526 		    nmg->cs->pwc = (pw_cache_s *)fs_get(sizeof(pw_cache_s));
527 		    tpwc = nmg->cs->pwc;
528 		}
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;
533 		}
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);
538 	    }
539 	}
540     }
541     nmg->cs->mb = NULL;
542 }
543 
mm_critical(MAILSTREAM * stream)544 void mm_critical (MAILSTREAM *stream)
545 {
546     if(MSDEBUG){
547       fprintf(ms_global->dfd, "IMAP mm_critical: not implemented\r\n");
548       _flushall();
549     }
550 }
551 
mm_nocritical(MAILSTREAM * stream)552 void mm_nocritical (MAILSTREAM *stream)
553 {
554     if(MSDEBUG){
555       fprintf(ms_global->dfd, "IMAP mm_nocritical: not implemented\r\n");
556       _flushall();
557     }
558 }
559 
mm_diskerror(MAILSTREAM * stream,long errcode,long serious)560 long mm_diskerror (MAILSTREAM *stream,long errcode,long serious)
561 {
562     if(MSDEBUG){
563       fprintf(ms_global->dfd, "IMAP mm_diskerror: not implemented\r\n");
564       _flushall();
565     }
566     return 1;
567 }
568 
mm_fatal(char * string)569 void mm_fatal (char *string)
570 {
571     if(MSDEBUG){
572       fprintf(ms_global->dfd, "IMAP mm_fatal: %s\r\n", string);
573       _flushall();
574     }
575 }
576 
new_sessionlist()577 sessionlist_s *new_sessionlist()
578 {
579     sessionlist_s *cs;
580 
581     cs = (sessionlist_s *)fs_get(sizeof(sessionlist_s));
582     memset(cs, 0, sizeof(sessionlist_s));
583     cs->session_number = ms_global->next_session++;
584 
585     return cs;
586 }
587 
free_sessionlist_node(sessionlist_s * cs)588 sessionlist_s *free_sessionlist_node(sessionlist_s *cs)
589 {
590     sessionlist_s *ts;
591 
592     ts = cs->next;
593 
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;
602     }
603     fs_give((void **)&cs);
604 
605     return ts;
606 }
607 
get_session(unsigned long num)608 sessionlist_s *get_session(unsigned long num)
609 {
610     mapi_global_s *nmg = ms_global;
611     sessionlist_s *ts;
612 
613     ts = nmg->sessionlist;
614     while(ts && ts->session_number != num) ts = ts->next;
615     return ts;
616 }
617 
618 /*
619 void *mm_cache (MAILSTREAM *stream,unsigned long msgno,long op){}
620 */
new_mapi_global()621 mapi_global_s *new_mapi_global()
622 {
623     mapi_global_s *nmg;
624     int i;
625 
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));
631     }
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));
635     }
636     nmg->next_session = 1;
637 
638     return nmg;
639 }
640 
InitPineSpecific(sessionlist_s * cs)641 int InitPineSpecific(sessionlist_s *cs)
642 {
643     mapi_global_s *nmg = ms_global;
644 
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;
658 }
659 
660 int
new_mbuffer(void * buf,int arraysize,BufType type)661 new_mbuffer(void *buf, int arraysize, BufType type)
662 {
663     MBUFFER_LIST_S *tlist, *tlist2;
664     mapi_global_s *nmg = ms_global;
665 
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;
671 
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;
677     }
678 
679     return(0);
680 }
681 
682 int
free_mbuffer(void * buf)683 free_mbuffer(void *buf)
684 {
685     MBUFFER_LIST_S *tlist, *pre_tlist = NULL;
686     mapi_global_s *nmg = ms_global;
687     sessionlist_s *session;
688 
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;
693     }
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;
706 	}
707 	free_MapiMessage(tlist->buf, tlist->arraysize);
708 	break;
709     }
710     fs_give((void **)&tlist);
711     return 0;
712 }
713 
714 lpMapiRecipDesc
new_MapiRecipDesc(int arraysize)715 new_MapiRecipDesc(int arraysize)
716 {
717     lpMapiRecipDesc lpmrd;
718     mapi_global_s *nmg = ms_global;
719 
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;
724 }
725 
726 void
free_MapiRecipDesc(lpMapiRecipDesc buf,int arraysize)727 free_MapiRecipDesc(lpMapiRecipDesc buf, int arraysize)
728 {
729     int i;
730 
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);
736     }
737     fs_give((void **)&buf);
738 }
739 
740 lpMapiMessage
new_MapiMessage(int arraysize)741 new_MapiMessage(int arraysize)
742 {
743     lpMapiMessage lpmm;
744     mapi_global_s *nmg = ms_global;
745 
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;
750 }
751 
752 void
free_MapiMessage(lpMapiMessage buf,int arraysize)753 free_MapiMessage(lpMapiMessage buf, int arraysize)
754 {
755     int i;
756 
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);
771 	}
772 	if(buf[i].lpRecips){
773 	    if(free_mbuffer(buf[i].lpRecips))
774 	      free_MapiRecipDesc(buf[i].lpRecips, buf[i].nRecipCount);
775 	}
776 	if(buf[i].lpFiles)
777 	  free_mapi_file_desc(buf[i].lpFiles, buf[i].nFileCount);
778     }
779     fs_give((void **)&buf);
780 }
781 
new_mapi_file_desc(int arraysize)782 lpMapiFileDesc new_mapi_file_desc(int arraysize)
783 {
784     lpMapiFileDesc lpmfd;
785 
786     lpmfd = (MapiFileDesc *)fs_get(arraysize * sizeof (MapiFileDesc));
787     memset(lpmfd, 0, arraysize * sizeof(MapiFileDesc));
788     return lpmfd;
789 }
790 
free_mapi_file_desc(lpMapiFileDesc lpmfd,int arraysize)791 void free_mapi_file_desc(lpMapiFileDesc lpmfd, int arraysize)
792 {
793     int i;
794 
795     if(lpmfd == NULL) return;
796 
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 */
803     }
804     fs_give((void **)&lpmfd);
805 }
806 
new_file_s()807 file_s *new_file_s()
808 {
809     file_s *tmp_fs;
810 
811     tmp_fs = (file_s *)fs_get(sizeof(file_s));
812     memset(tmp_fs, 0, sizeof(file_s));
813     return tmp_fs;
814 }
815 
free_file_s(file_s * fs)816 void free_file_s(file_s *fs)
817 {
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);
824 }
825 
826 void
init_prcvars(mapi_global_s * nmg)827 init_prcvars(mapi_global_s *nmg)
828 {
829     int i=0;
830 
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;
849 }
850 
851 void
init_prcfeats(mapi_global_s * nmg)852 init_prcfeats(mapi_global_s *nmg)
853 {
854     nmg->prcfeats[ENABLE8BIT]->var = mstrdup("enable-8bit-esmtp-negotiation");
855 }
856 
init_fcc_folder(mapi_global_s * nmg)857 void init_fcc_folder(mapi_global_s *nmg)
858 {
859     char *fcc, **fc, *desc = NULL, *col = NULL, *tfcc, *p, *p2;
860     int i = 0;
861 
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;
871     }
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;
885     }
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);
893 }
894 
init_pmapi_registry_vars(mapi_global_s * nmg)895 void init_pmapi_registry_vars(mapi_global_s *nmg)
896 {
897     HKEY hKey;
898     BYTE keyData[1024];
899     DWORD keyDataSize = 1024;
900     DWORD keyDataType;
901     int i;
902 
903     if(RegOpenKeyEx(HKEY_CURRENT_USER,
904 		    "Software\\University of Washington\\Alpine\\1.0\\PmapiOpts",
905 		    0,
906 		    KEY_QUERY_VALUE,
907 		    &hKey) != ERROR_SUCCESS)
908       return;
909 
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);
919 	    }
920 	}
921     }
922 
923     RegCloseKey(hKey);
924 }
925 
init_pmapi_vars(mapi_global_s * nmg)926 void init_pmapi_vars(mapi_global_s *nmg)
927 {
928     char *b;
929 
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;
937     }
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;
947     }
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;
953     }
954     else
955       nmg->pmapi_strict_no_dialog = 0;
956 }
957 
copy_remote_to_local(char * pinerc,sessionlist_s * cs)958 char *copy_remote_to_local(char *pinerc, sessionlist_s *cs)
959 {
960     mapi_global_s *nmg = ms_global;
961     char *tmptext, dir[1024], filename[1024];
962     unsigned long tmptextlen, i = 0, numwritten;
963     FILE *prcfd;
964 
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;
970     }
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);
977     do{
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);
988     }
989     else{
990       ErrorBox("Couldn't open temp file %s for writing", filename);
991       mail_close_full(cs->open_stream, NIL);
992       return NULL;
993     }
994     cs->open_stream =  mail_close_full(cs->open_stream, NIL);
995     return(mstrdup(filename));
996 }
997 
read_pinerc(mapi_global_s * nmg,sessionlist_s * cs,char * prc,char * pineconf,char * pinercex,int depth)998 int read_pinerc(mapi_global_s *nmg, sessionlist_s *cs,
999 		char *prc, char *pineconf, char *pinercex, int depth)
1000 {
1001     FILE *prcfd;
1002     int i, varnum, j, varlen, create_local = 0, k;
1003     char line[BUFLEN], *local_pinerc, *p;
1004 
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);
1011     }
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);
1016     }
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;
1022     }
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;
1030       }
1031       create_local = 1;
1032     }
1033     else{
1034       if(!(local_pinerc = mstrdup(prc))){
1035 	ErrorBox("Couldn't fs_get for %s","pinerc");
1036 	return -1;
1037       }
1038     }
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;
1049     }
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;
1068 
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);
1073 		      }
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));
1085 			  }
1086 			  varlen = strlen(line+j);
1087 			  while(isspace((line+j)[varlen - 1])){
1088 			      varlen--;
1089 			      (line+j)[varlen] = '\0';
1090 			  }
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;
1098 			      }
1099 			  }
1100 			  else
1101 			    break;
1102 		      }
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);
1109 		      }
1110 		      nmg->prcvars[i]->val.l[k] = NULL;
1111 		  }
1112 	      }
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';
1120 		      }
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';
1125 		  }
1126 	      }
1127 	    }
1128 	  }
1129 	}
1130       }
1131     }
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);
1138       }
1139     }
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;
1151 	    }
1152 	}
1153     }
1154     if(create_local && local_pinerc){
1155       if(MSDEBUG)
1156 	fprintf(nmg->dfd, "Removing %s\r\n", local_pinerc);
1157       _unlink(local_pinerc);
1158     }
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]);
1175 	      }
1176 	  }
1177       }
1178     }
1179     return 0;
1180 }
1181 
expand_env_vars(mapi_global_s * nmg)1182 void expand_env_vars(mapi_global_s *nmg)
1183 {
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;
1188 
1189 
1190     if(RegOpenKeyEx(HKEY_CURRENT_USER,
1191 		    "Software\\University of Washington\\Alpine\\1.0\\PmapiOpts\\Env",
1192 		    0,
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)
1207 		  ;
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);
1222 	    }
1223 	}
1224     }
1225     if(check_reg)
1226       RegCloseKey(hKey);
1227 }
1228 
free_mapi_global(mapi_global_s * nmg)1229 void free_mapi_global(mapi_global_s *nmg)
1230 {
1231   int i, j;
1232   sessionlist_s *ts;
1233 
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]);
1252   }
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);
1261 	}
1262     }
1263     else {
1264 	if(nmg->prcvars[i]->val.p)
1265 	  fs_give((void **)&nmg->prcvars[i]->val.p);
1266     }
1267     fs_give((void **)&nmg->prcvars[i]);
1268   }
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);
1273   }
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);
1280 }
1281 
first_open(sessionlist_s * cs)1282 MAILSTREAM *first_open(sessionlist_s *cs)
1283 {
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;
1288    */
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;
1296     }
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;
1304       }
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();
1311       }
1312       return cs->open_stream;
1313     }
1314     else if(cs->flags.dlg_cancel){
1315       if(MSDEBUG){
1316 	fprintf(nmg->dfd, "returning MAPI_E_FAILURE\r\n");
1317 	_flushall();
1318       }
1319       return NULL;
1320     }
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;
1327       }
1328       if(MSDEBUG){
1329 	fprintf(nmg->dfd, "returning MAPI_E_FAILURE\r\n");
1330 	_flushall();
1331       }
1332       return NULL;
1333     }
1334 }
1335 
1336 SENDSTREAM *
mapi_smtp_open(sessionlist_s * cs,char ** servers,long options)1337 mapi_smtp_open(sessionlist_s *cs, char **servers, long options)
1338 {
1339     mapi_global_s *nmg = ms_global;
1340     SENDSTREAM *newstream;
1341     pw_cache_s *tpwc, *dpwc;
1342 
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;
1349 
1350     if(newstream){ /* if open stream, valid password */
1351 	for(tpwc = cs->pwc; tpwc; tpwc = tpwc->next)
1352 	  tpwc->validpw = 1;
1353     }
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);
1362 	    }
1363 	}
1364     }
1365     return(newstream);
1366 }
1367 
1368 MAILSTREAM *
mapi_mail_open(sessionlist_s * cs,MAILSTREAM * stream,char * name,long options)1369 mapi_mail_open(sessionlist_s *cs, MAILSTREAM *stream, char *name, long options)
1370 {
1371     MAILSTREAM *newstream;
1372     mapi_global_s *nmg = ms_global;
1373     pw_cache_s *tpwc, *dpwc;
1374 
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;
1381 
1382     if(newstream){ /* if open stream, valid password */
1383 	for(tpwc = cs->pwc; tpwc; tpwc = tpwc->next)
1384 	  tpwc->validpw = 1;
1385     }
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);
1395 	    }
1396 	    else
1397 	      tpwc = tpwc->next;
1398 	}
1399     }
1400 
1401     return (newstream);
1402 }
1403 
1404 
check_mailstream(sessionlist_s * cs)1405 MAILSTREAM *check_mailstream(sessionlist_s *cs)
1406 {
1407     mapi_global_s *nmg;
1408 
1409     nmg = ms_global;
1410 
1411     if(!cs->open_stream){
1412       return(first_open(cs));
1413     }
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;
1428       }
1429     }
1430     cs->flags.check_stream = FALSE;
1431     return cs->open_stream;
1432 }
1433 
1434 /* pretty much changes a string to an integer,
1435  * but if it is not a valid message number, then 0 is returned
1436  */
convert_to_msgno(char * msgid)1437 unsigned long convert_to_msgno(char *msgid)
1438 {
1439     unsigned long place_holder = 1, msgno = 0;
1440     int i, len;
1441 
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;
1448     }
1449 
1450     return msgno;
1451 }
1452 
1453 /*
1454  * Lookup file's mimetype by its file extension
1455  *  fn - filename
1456  *  body - body in which to store new type, subtype
1457  *
1458  *  A mime type is ALWAYS set
1459  *
1460  *  Returns 0 if the file extension was found and mimetype was set accordingly
1461  *          1 if otherwise
1462  */
lookup_file_mime_type(char * fn,BODY * body)1463 int lookup_file_mime_type(char *fn, BODY *body)
1464 {
1465     char *p, subkey[1024], val[1024];
1466     DWORD dtype, vallen = 1024;
1467     HKEY hKey;
1468     int i, rv = 0;
1469 
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;
1487 		}
1488 	    }
1489 	}
1490     }
1491     body->type = TYPEAPPLICATION;
1492     body->subtype = "octet-stream";
1493     return 1;
1494 }
1495 
LookupMIMEFileExt(char * val,char * mime_type,DWORD * vallen)1496 int LookupMIMEFileExt(char *val, char *mime_type, DWORD *vallen)
1497 {
1498     HKEY hKey;
1499     DWORD dtype;
1500     LONG rv = !ERROR_SUCCESS;
1501     char subkey[1024];
1502 
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);
1507     }
1508 
1509     return(rv);
1510 }
1511 
1512 /*
1513  * xlate_out() - xlate_out the given character
1514  */
1515 char
xlate_out(c)1516 xlate_out(c)
1517     char c;
1518 {
1519     register int  dti;
1520     register int  xch;
1521 
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);
1529     }
1530     else
1531       return(c);
1532 }
1533 
1534 /* return TRUE if the pwd is found, FALSE if not */
in_passfile(sessionlist_s * cs)1535 int in_passfile(sessionlist_s *cs)
1536 {
1537     mapi_global_s *nmg;
1538     char *tf, *tp, *ui[4], tmp[1024], *dir;
1539     int i, j, n;
1540     FILE *tfd;
1541 
1542     nmg = ms_global;
1543 
1544     if(*nmg->pinerc == '{')
1545       dir = nmg->pineExe;
1546     else
1547       dir = nmg->pinerc;
1548 
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;
1553     }
1554     strcpy(tf,dir);
1555     if(tp = strrchr(tf, '\\')){
1556       tp++;
1557       strcpy(tp, "pine.pwd");
1558     }
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;
1568       }
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]);
1575 
1576 	  if(i && tmp[i-1] == '\n')
1577 	    tmp[i-1] = '\0';			/* blast '\n' */
1578 
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++)
1582 	      ;
1583 
1584 	    if(tmp[i])
1585 	      tmp[i++] = '\0';
1586 	  }
1587 
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;
1602 		}
1603 	      }
1604 	    }
1605 	  }
1606 	}
1607 	fclose(tfd);
1608 	fs_give((void **)&tf);
1609       }
1610     }
1611     else{
1612       fs_give((void **)&tf);
1613       /*      nmg->flags.passfile_checked = TRUE; */
1614       return FALSE;
1615     }
1616     /*    nmg->flags.passfile_checked = TRUE; */
1617     return FALSE;
1618 }
1619 
get_suggested_directory(char * dir)1620 int get_suggested_directory(char *dir)
1621 {
1622     char *tmpdir;
1623 
1624     if(tmpdir = getenv("TEMP")){
1625       strcpy(dir, tmpdir);
1626       return TRUE;
1627     }
1628     else if(tmpdir = getenv("TMP")){
1629       strcpy(dir, tmpdir);
1630       return TRUE;
1631     }
1632     else if(ms_global && ms_global->attachDir){
1633       strcpy(dir, ms_global->attachDir);
1634       return TRUE;
1635     }
1636     else{  /* should NEVER get here */
1637       strcpy(dir, "C:\\");
1638       return TRUE;
1639     }
1640     return FALSE;
1641 }
1642 
1643 
1644 /* return TRUE if file_ext is modified, FALSE if not */
get_suggested_file_ext(char * file_ext,PART * part,DWORD * file_extlen)1645 int get_suggested_file_ext(char *file_ext, PART *part, DWORD *file_extlen)
1646 {
1647     char mime_type[1024], *tmp_ext;
1648     int rv = !ERROR_SUCCESS;
1649     PARAMETER *param;
1650 
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);
1654     }
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;
1666 	}
1667       }
1668       tmp_ext = strrchr(param->value, (int)'.');
1669       if(!tmp_ext) return FALSE;
1670       strcpy(file_ext, tmp_ext);
1671     }
1672     return TRUE;
1673 }
1674 
1675 /* return -1 for failure */
InitDebug()1676 int InitDebug()
1677 {
1678     char path[1024];
1679 
1680     if(!ms_global){
1681       if((ms_global = new_mapi_global()) == NULL) return -1;
1682     }
1683     /*
1684      * if debug file exists, turn on debugging mode
1685      */
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;
1694     }
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;
1702       }
1703     }
1704 
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 */
1711       }
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);
1715       }
1716     }
1717 
1718     if(ms_global->debug && (ms_global->dfd == NULL))
1719       ms_global->debug = 0;
1720 
1721     return ms_global->debug;
1722 }
1723 
GetPineData()1724 int GetPineData()
1725 {
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;
1735 
1736     /*
1737      * get name of and path to pine.exe from registry
1738      */
1739     if (RegOpenKeyEx(
1740 		     HKEY_LOCAL_MACHINE,
1741 		     "SOFTWARE\\University of Washington\\Alpine\\1.0",
1742 		     0,
1743 		     KEY_QUERY_VALUE,
1744 		     &pineKey) == ERROR_SUCCESS) {
1745       pineKeyDataSize = sizeof(pineKeyData);
1746       if (RegQueryValueEx(
1747 			  pineKey,
1748 			  "PineEXE",
1749 			  0,
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);
1756 	}
1757 	else {
1758 	  ErrorBox("MAPISendMail: can't fs_get %d bytes for pineExe",
1759 		   pineKeyDataSize);
1760 	  return 0;
1761 	}
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);
1765 	}
1766       }
1767       pineKeyDataSize = sizeof(pineKeyData);
1768       if (RegQueryValueEx(
1769 			  pineKey,
1770 			  "pinedir",
1771 			  0,
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);
1779 	}
1780 	else {
1781 	  ErrorBox("MAPISendMail: can't fs_get %d bytes for av[0]",
1782 			 pineKeyDataSize);
1783 	  return 0;
1784 	}
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);
1788 	}
1789       }
1790       RegCloseKey(pineKey);
1791     }
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;
1797       }
1798       else
1799 	strcpy(ms_global->pineExe, defPath);
1800     }
1801 
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;
1809       }
1810       else
1811 	strcpy(ms_global->pineExeAlt, strrchr(defPath, '\\')+1);
1812     }
1813 
1814     /*
1815      * get path to pinerc from registry
1816      */
1817     if (RegOpenKeyEx(
1818 		     HKEY_CURRENT_USER,
1819 		     "Software\\University of Washington\\Alpine\\1.0",
1820 		     0,
1821 		     KEY_QUERY_VALUE,
1822 		     &pineKey) == ERROR_SUCCESS) {
1823       pineKeyDataSize = sizeof(pineKeyData);
1824       if( RegQueryValueEx(
1825 			  pineKey,
1826 			  "PineRC",
1827 			  0,
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';
1841 	  }
1842 	  else
1843 	    strcpy(ms_global->attachDir,  ms_global->pineExe);
1844 	  p = strrchr(ms_global->attachDir, '\\');
1845 	  if (p) *p = '\0';
1846 	}
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;
1853 	}
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");
1860 	}
1861       }
1862       pineKeyDataSize = sizeof(pineKeyData);
1863       if( RegQueryValueEx(
1864 	  pineKey,
1865 	  "PineConf",
1866 	  0,
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);
1872       }
1873       RegCloseKey(pineKey);
1874     }
1875 
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");
1881     }
1882 
1883 
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");
1891     }
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");
1899     }
1900     else{
1901 
1902     }
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");
1910     }
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");
1924     }
1925     return 1;
1926 }
1927 
DllMain(HANDLE hInst,DWORD ul_reason_being_called,LPVOID lpReserved)1928 BOOL APIENTRY DllMain(
1929     HANDLE hInst,
1930     DWORD ul_reason_being_called,
1931     LPVOID lpReserved)
1932 {
1933     switch(ul_reason_being_called){
1934     case DLL_THREAD_ATTACH:
1935       /*      if(ms_global)
1936        *	return 1;
1937        */
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;
1947       }
1948       if(MSDEBUG && ms_global->attached <= 1){
1949 	time_t now;
1950 	struct tm *tm_now;
1951 	extern char datestamp[], hoststamp[];
1952 
1953 	now = time((time_t *)0);
1954 	tm_now = localtime(&now);
1955 	fprintf(ms_global->dfd, "pmapi32.dll for Alpine Version 2.25\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);
1964 
1965 	fprintf(ms_global->dfd, "\r\n\r\n");
1966       }
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);
1981        */
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);
1988       }
1989       break;
1990     }
1991     return 1;
1992 }
1993 
1994 static char *V="\r\n@(#) Alpine Simple Mapi Library Ver. 1.3\r\n";
1995 
1996 int
UnderlineSpace(char * s)1997 UnderlineSpace(char *s)
1998 {
1999     char *p;
2000 
2001     if(p = strrchr(s, '\\'))
2002       s = p++;
2003 
2004     for(; *s; s++)
2005       if(*s == ' ')
2006 	*s = '_';
2007     return 1;
2008 }
2009 
2010 /*
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
2014  */
2015 char *
TmpCopy(char * srcFile,int is_pinerc)2016 TmpCopy(char *srcFile, int is_pinerc)
2017 {
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;
2024 
2025     if (!srcFile) {
2026 	ErrorBox("TmpCopy: srcFile is %s", "NULL");
2027 	return NULL;
2028 	}
2029     if(is_pinerc){
2030       len = strlen(srcFile);
2031       for(i = 0; i < len; i++){
2032 	if(srcFile[i] == ' ') spc = 1;
2033       }
2034       if(spc == 0) return mstrdup(srcFile);
2035     }
2036 
2037     get_suggested_directory(dstDir);
2038     if (!dstDir) {
2039 	ErrorBox("TmpCopy: dstDir is %s", "NULL");
2040 	return NULL;
2041 	}
2042 
2043     dstName = (char *)fs_get(sizeof(char)*(strlen(srcFile) + 5 +
2044 			     max(strlen(dstDir), strlen(PINERC_FILE))));
2045 
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;
2050     }
2051 
2052     if(!is_pinerc){
2053       srcTail = strrchr(srcFile, '\\');
2054       if (srcTail)
2055 	++srcTail;
2056       else
2057 	srcTail = srcFile;
2058 
2059       srcExt = strrchr(srcTail, '.');
2060 
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;
2066       }
2067 
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;
2079 	}
2080 	if (srcExt)
2081 	  sprintf(dstName+i-strlen(srcExt), "%03d%s", cnt, srcExt);
2082 	else
2083 	  sprintf(dstName+i, "%03d", cnt);
2084       }
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;
2090       }
2091     }
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;
2101       }
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;
2108       }
2109     }
2110     c = fgetc(sfd);
2111     while(feof(sfd) == 0) {
2112 	putc(c, dfd);
2113 	c = fgetc(sfd);
2114     }
2115     if (ferror(dfd)) {
2116 	ErrorBox("TmpCopy: write error on %.200s", dstName);
2117 	fs_give((void **)&dstName);
2118 	fclose(dfd);
2119 	return NULL;
2120 	}
2121     if (ferror(sfd)) {
2122 	ErrorBox("TmpCopy: read error on %.200s", srcFile);
2123 	fs_give((void **)&dstName);
2124 	fclose(sfd);
2125 	return NULL;
2126 	}
2127     if (fclose(sfd)) {
2128 	ErrorBox("TmpCopy: fclose error on %.200s", srcFile);
2129 	}
2130     if (fclose(dfd)) {
2131 	ErrorBox("TmpCopy: fclose error on %.200s", dstName);
2132 	}
2133 
2134     return dstName;
2135 }
2136 
send_documents(char * files,char sep)2137 int send_documents(char *files, char sep)
2138 {
2139     int ac, i, tmplen, j;
2140     char **av, *tmpfiles, *file, *tmpfree;
2141     mapi_global_s *nmg;
2142 
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;
2151     }
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
2158        */
2159       if(tmpfree = TmpCopy(nmg->pinerc, IS_PINERC)){
2160 	av[2] = quote(tmpfree);
2161 	fs_give((void **)&tmpfree);
2162       }
2163       else
2164 	av[2] = quote(nmg->pinerc);
2165     }
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);
2175 	  }
2176 	}
2177       }
2178     }
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]);
2187     }
2188 
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);
2197     }
2198     for(i = 0; av[i]; i++)
2199       fs_give((void **)&av[i]);
2200     fs_give((void **)&av);
2201     return SUCCESS_SUCCESS;
2202 }
2203 
2204 char *
message_structure_to_mailto_url(lpMapiMessage lpm)2205 message_structure_to_mailto_url(lpMapiMessage lpm)
2206 {
2207     char **keyvals, **keyvalp, *url;
2208     int keyvallen;
2209     unsigned long i, url_len = 0;
2210 
2211     if(lpm == NULL)
2212       return NULL;
2213 
2214     keyvallen = lpm->nRecipCount + 4; /* subject + body + from + recips + NULL */
2215     keyvals = (char **)fs_get(keyvallen * sizeof(char *));
2216     keyvalp = keyvals;
2217 
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;
2227 
2228     if(*keyvals == NULL){
2229 	fs_give((void **)&keyvals);
2230 	return(NULL);
2231     }
2232 
2233     url_len = keyvallen + 10; /* mailto url extra chars */
2234     for(keyvalp = keyvals; *keyvalp; keyvalp++)
2235       url_len += strlen(*keyvalp);
2236 
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));
2244     }
2245     fs_give((void **)&keyvals);
2246     return url;
2247 }
2248 
2249 char *
encode_mailto_addr_keyval(lpMapiRecipDesc lpmr)2250 encode_mailto_addr_keyval(lpMapiRecipDesc lpmr)
2251 {
2252     ADDRESS *adr = NULL;
2253     char *addr, *retstr;
2254     int use_quotes = 0;
2255 
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);
2261 
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);
2269 }
2270 
2271 
2272 
2273 /*
2274  * Hex conversion aids from alpine.h
2275  */
2276 #define HEX_ARRAY	"0123456789ABCDEF"
2277 #define	HEX_CHAR1(C)	HEX_ARRAY[((C) & 0xf0) >> 4]
2278 #define	HEX_CHAR2(C)	HEX_ARRAY[(C) & 0xf]
2279 
2280 /* strings.c macros */
2281 #define	C2XPAIR(C, S)	{ \
2282 			    *(S)++ = HEX_CHAR1(C); \
2283 			    *(S)++ = HEX_CHAR2(C); \
2284 			}
2285 
2286 #define	RFC1738_SAFE	"$-_.+"			/* "safe" */
2287 #define	RFC1738_EXTRA	"!*'(),"		/* "extra" */
2288 
2289 /* adapted from rfc1738_encode_mailto */
2290 char *
encode_mailto_keyval(char * key,char * val)2291 encode_mailto_keyval(char *key, char* val)
2292 {
2293     char *d, *ret = NULL, *v = val;
2294 
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++;
2309 	    }
2310 	}
2311 	*d = '\0';
2312     }
2313 
2314     return(ret);
2315 }
2316 
2317 unsigned long
send_msg_nodlg(LHANDLE lhSession,ULONG ulUIParam,lpMapiMessage lpMessage,FLAGS flFlags,ULONG ulReserved)2318 send_msg_nodlg(LHANDLE lhSession, ULONG ulUIParam, lpMapiMessage lpMessage,
2319 	       FLAGS flFlags, ULONG ulReserved)
2320 {
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;
2333 
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;
2339     }
2340     if((flFlags & MAPI_NEW_SESSION) || lhSession == 0){
2341 	cs = new_sessionlist();
2342 	tsession = 1;
2343     }
2344     else{
2345 	cs = get_session(lhSession);
2346 	if(!cs)
2347 	  return MAPI_E_INVALID_SESSION;
2348     }
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;
2353     }
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);
2364     }
2365     /*
2366      * Since it is "DateReceived", I think the right thing to do is ignore it,
2367      * since we're sending, not receiving.
2368      */
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);
2374 
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;
2379 	}
2380     }
2381 
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;
2389 	}
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);
2395 	}
2396     }
2397     else if(nmg->prcvars[USER_ID]->val.p && nmg->prcvars[USER_DOMAIN]->val.p){
2398 	/*
2399 	 * judgment call: I guess we'll try to generate the from header if it's not
2400 	 * given to us
2401 	 */
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);
2407 	}
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);
2415 	}
2416     }
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;
2421 	}
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;
2430 	    }
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;
2439 	    }
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;
2448 	    }
2449 	    msprint(" Bcc: ");
2450 	    break;
2451 	  default:
2452 	    rv = MAPI_E_INVALID_RECIPS;
2453 	    goto smn_cleanup;
2454 	    break;
2455 	}
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);
2461 	}
2462     }
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;
2473 
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 		      : "");
2480 
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++;
2494 	    }
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));
2513 		}
2514 		c = fgetc(sfd);
2515 	    }
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);
2524 
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);
2529 	    }
2530 	}
2531     }
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);
2536     }
2537 
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);
2544     }
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();
2551 	}
2552 	sending_stream = mapi_smtp_open(cs, nmg->prcvars[SMTP_SERVER]->val.l,
2553 				   nmg->prcfeats[ENABLE8BIT]->is_set ? SOP_8BITMIME : NIL);
2554     }
2555     else {
2556 	rv = MAPI_E_FAILURE;
2557 	if(MSDEBUG){
2558 	    fprintf(ms_global->dfd, "Error! No SMTP server defined!\r\n");
2559 	}
2560 	goto smn_cleanup;
2561     }
2562     if(!sending_stream){
2563 	rv = MAPI_E_FAILURE;
2564 	if(MSDEBUG){
2565 	    fprintf(ms_global->dfd, "Couldn't open SMTP connection!\r\n");
2566 	}
2567 	goto smn_cleanup;
2568     }
2569     if(!smtp_mail(sending_stream, "MAIL", env, body)){
2570 	if(MSDEBUG){
2571 	    fprintf(ms_global->dfd, "Attempt to Send Failed\r\n");
2572 	}
2573 	rv = MAPI_E_FAILURE;
2574     }
2575     else {
2576 	if(MSDEBUG){
2577 	    fprintf(ms_global->dfd, "Message SENT!\r\n");
2578 	}
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;
2585 
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);
2601 	    }
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);
2608 	}
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;
2612     }
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);
2622 }
2623 
2624 int
set_text_data(BODY * body,char * txt)2625 set_text_data(BODY *body, char *txt)
2626 {
2627     char *p;
2628     int has_8bit = 0;
2629     PARAMETER *pm;
2630 
2631     for(p = txt; *p; p++)
2632       if(*p & 0x80)
2633 	has_8bit++;
2634 
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;
2645 	}
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");
2651     }
2652     return 0;
2653 }
2654 
2655 long
pmapi_soutr(STRBUFFER_S * s,char * str)2656 pmapi_soutr(STRBUFFER_S *s, char *str)
2657 {
2658     unsigned long i;
2659 
2660     if(s->cur_bytes >= s->bufsize){
2661 	fs_resize((void **)&s->buf, s->bufsize+ s->increment);
2662 	s->bufsize += s->increment;
2663     }
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;
2669 	}
2670     }
2671     s->buf[s->cur_bytes] = '\0';
2672     return T;
2673 }
2674 
2675 ADDRESS *
mapirecip2address(lpMapiRecipDesc lpmrd)2676 mapirecip2address(lpMapiRecipDesc lpmrd)
2677 {
2678     ADDRESS *adr = NULL;
2679     static char *fakedomain = "@", *p;
2680     mapi_global_s *nmg = ms_global;
2681 
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);
2693     }
2694 
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);
2701     }
2702     return(adr);
2703 }
2704 
2705 /*
2706  * given a fs_get'd string, return a newly fs_get'd quoted copy
2707  */
2708 char *
quote(char * old)2709 quote(char *old)
2710 {
2711     char *new, *newp, *oldp;
2712     int newSize = strlen(old)*2+3;
2713 
2714     if (!old) return mstrdup(old);
2715     if(!strchr(old, ' ')) return mstrdup(old);
2716 
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;
2721     }
2722 
2723     *newp++ = '"';
2724     for (oldp=old; *oldp; ++oldp) {
2725 	switch(*oldp) {
2726 	    case '"':  *newp++ = '\\';		/* fall through */
2727 	    default :  *newp++ = *oldp;
2728 	}
2729     }
2730     *newp++ = '"';
2731     *newp = '\0';
2732     return(new);
2733 }
2734 
2735 
GetPCPineVersion(int * major,int * minor,int * minorminor)2736 int GetPCPineVersion(int *major, int *minor, int *minorminor)
2737 {
2738     *major = 4;
2739     *minor = 52;
2740     *minorminor = 0;
2741 
2742     return 1;
2743 }
2744 
2745 int
msprint(char * str)2746 msprint(char *str)
2747 {
2748     if(MSDEBUG)
2749       fprintf(ms_global->dfd, "%s", str);
2750     _flushall();
2751     return 0;
2752 }
2753 
2754 int
msprint1(char * str,void * arg1)2755 msprint1(char *str, void *arg1)
2756 {
2757     if(MSDEBUG)
2758       fprintf(ms_global->dfd, str, arg1);
2759     _flushall();
2760     return 0;
2761 }
2762 
2763 int
msprint_message_structure(lpMapiMessage lpm)2764 msprint_message_structure(lpMapiMessage lpm)
2765 {
2766     unsigned long i;
2767 
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");
2791     }
2792     return 0;
2793 }
2794 
2795 int
msprint_recipient_structure(lpMapiRecipDesc lmrd,int mapi_orig_is_unexpected)2796 msprint_recipient_structure(lpMapiRecipDesc lmrd, int mapi_orig_is_unexpected)
2797 {
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");
2808 	}
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);
2813     }
2814     return 0;
2815 }
2816 
2817 
2818 int
msprint_file_structure(lpMapiFileDesc lmfd)2819 msprint_file_structure(lpMapiFileDesc lmfd)
2820 {
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);
2831     }
2832     return 0;
2833 }
2834 
2835 
mstrdup(char * old)2836 char *mstrdup(char *old)
2837 {
2838     char *tmp;
2839 
2840     tmp = fs_get((strlen(old)+1) * sizeof(char));
2841     strcpy(tmp, old);
2842 
2843     return tmp;
2844 }
2845 
2846 int
est_size(a)2847 est_size(a)
2848     ADDRESS *a;
2849 {
2850     int cnt = 0;
2851 
2852     for(; a; a = a->next){
2853 
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);
2859 
2860 	/*
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>
2867 	 *
2868 	 * So I really think that adding 7 is enough.  Instead, I'll add 10.
2869 	 */
2870 	cnt   += 10;
2871     }
2872 
2873     return(max(cnt, 50));  /* just making sure */
2874 }
2875 
ErrorBoxFunc(char * msg)2876 void ErrorBoxFunc(char *msg)
2877 {
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;
2889       }
2890     }
2891     MessageBox(NULL, msg, "mapi32.dll", MB_OK|MB_ICONERROR);
2892 }
2893 
2894 /*----------------------------------------------------------------------
2895   This was borrowed from reply.c, and modified
2896         Generate a unique message id string.
2897 
2898    Args: ps -- The usual pine structure
2899 
2900   Result: Alloc'd unique string is returned
2901 
2902 Uniqueness is guaranteed by using the host name, process id, date to the
2903 second and a single unique character
2904 *----------------------------------------------------------------------*/
2905 char *
pmapi_generate_message_id()2906 pmapi_generate_message_id()
2907 {
2908     static short osec = 0, cnt = 0;
2909     char        *id;
2910     time_t       now;
2911     struct tm   *now_x;
2912 
2913     now   = time((time_t *)0);
2914     now_x = localtime(&now);
2915     id    = (char *)fs_get(128 * sizeof(char));
2916 
2917     if(now_x->tm_sec == osec){
2918 	cnt++;
2919     }else{
2920 	cnt = 0;
2921 	osec = now_x->tm_sec;
2922     }
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());
2927 
2928     return(id);
2929 }
2930