static char rcsid[] = "@(#)$Id: remote_mbx.c,v 1.6 2006/06/27 16:56:54 hurtta Exp $";

/******************************************************************************
 *  The Elm (ME+) Mail System  -  $Revision: 1.6 $   $State: Exp $
 *
 *  Author: Kari Hurtta <hurtta+elm@posti.FMI.FI>
 *      or  Kari Hurtta <elm@elmme-mailer.org>
 *****************************************************************************/

#include "def_mbox.h"
#include "ss_imp.h"
#ifdef USE_DLOPEN
#include "shared_imp.h"
#endif
#include "s_me.h"
#include "s_elm.h"

DEBUG_VAR(Debug,__FILE__,"net");


#ifdef REMOTE_MBX

/* Seems that h_errno is macro on AIX */
#ifndef h_errno
extern int h_errno;
#endif

#include <errno.h>
#ifndef ANSI_C
extern int errno;
#endif

void set_remote_tempmbox P_((struct folder_info *fh,
			     struct remote_account *X));
void set_remote_tempmbox(fh,X)
     struct folder_info *fh;
     struct remote_account *X;
{
    char * prefix = "mbox.";
    char *tmp;

    static int counter = 0;

    /* In here we can use temp_dir instead of default_temp because
     * that file does not act as session lock ...
     */


    if (X->magic  != REMOTE_ACCOUNT_magic)
	panic("CONNECTION PANIC",__FILE__,__LINE__,
	      "set_remote_tempmbox",
	      "Bad magic number",0);

    tmp = give_dt_estr_as_str(&temp_dir_e,"tmpdir");
    if (!tmp)
	tmp = "/tmp/";

    elm_sfprintf(fh-> cur_tempfolder,
		 sizeof fh -> cur_tempfolder,
		 FRM("%s%s%s.%s.%d.%d"),
		 tmp,prefix,username,X->host,getpid(),counter++);

    DPRINT(Debug,12,(&Debug,
		     "set_remote_tempmbox: cur_tempfolder=%s\n",
		     fh-> cur_tempfolder));
}

/* May free X (if succeed) or copy
   If make copy of X, then X is zeroed 
 */
int make_remote_mbox(fh,X,se,rest,rewrite)
     struct folder_info *fh; 
     struct remote_account *X;
     struct service_entry *se;
     char * rest;
     int rewrite;
{
    struct remote_account *status = NULL;

    char * imap_only = NULL;  /* Flag and name of imap folder ... */
    int got;
    static struct connection_cache *CX;

    if (X->magic  != REMOTE_ACCOUNT_magic)
	panic("CONNECTION PANIC",__FILE__,__LINE__,
	      "make_remote_mbox",
	      "Bad magic number",0);

    DPRINT(Debug,10,(&Debug,
		     "make_remote_mbox: fh=%X, rest=%s, rewrite=%d\n",
		     fh,rest ? rest : "<NULL>", rewrite));

    if (rewrite) {
	/* canonify folder name .... */
	if (rest) {
	    /* Inbox is case insensitive */
	    if (0 == istrcmp(":inbox",rest))
		rest = ":INBOX";
	    
	    imap_only = safe_strdup(rest);
	    free(fh->cur_folder_sys);
	    fh->cur_folder_sys = elm_message(FRM("%s@%s%s"),
					     X->username,
					     se->official_name,
					     imap_only);
 
	    /* No support of international folder names on here! */
	    free_string(&(fh->cur_folder_disp));
	    fh->cur_folder_disp = format_string(FRM("%s@%s%s"),
						X->username,
						se->official_name,
						imap_only); 
	    
	    rest = NULL; /* is no longer valid pointer if 
			    rest was pointing to fh->cur_folder_sys
			 */
	} else {
	    free(fh->cur_folder_sys);
	    fh->cur_folder_sys = elm_message(FRM("%s@%s"),
					     X->username,se->official_name);
	    free_string(&(fh->cur_folder_disp));
	    fh->cur_folder_disp = format_string(FRM("%s@%s"),
						X->username,
						se->official_name);    
	}
    }

    /* Only IMAP connections are cached */
    CX = locate_from_cache(X->username,X->host,&IMAP_connection,
			   0   /* Default port */ );
    
    if (CX) {
	if (!imap_only)
	    imap_only = safe_strdup(":INBOX");
	fh -> folder_type = IMAP_MBX;

	DPRINT(Debug,8,(&Debug,
		   "make_remote_mbox: IMAP mailbox (from cache)\n"));
	
	fh->folder_type->init_it(fh);
	folder_from_connection(CX,fh);
	
	status = &(fh->p->a.imap_mbx.Ch->C);
	
	if (':' == imap_only[0]) 
	    fh->p->a.imap_mbx.folder = safe_strdup(imap_only+1);
	else
	    fh->p->a.imap_mbx.folder = safe_strdup(imap_only);
	
    } else {
	PORTS ports[] = { PORT_imap4, PORT_pop3, PORT_end };
	PORTS ports_imaponly[] = { PORT_imap4, PORT_end };

	if (!connect_remote_account(X,&got,se,
				    imap_only ? ports_imaponly : ports,
				    PORT_end))
	    goto fail;
	
	if (IMAP_SERVICE == se->service)
	    goto is_imap;
	else if (POP_SERVICE == se->service)
	    goto is_pop;
	else switch (got) {
	case PORT_pop3:
	is_pop:

	    fh -> folder_type = POP_MBX;
	    
	    DPRINT(Debug,8,(&Debug,
			    "make_remote_mbox: POP mailbox (succeed)\n"));
	    
	    fh->folder_type->init_it(fh);
	    free_remote_account(&(fh->p->a.pop_mbx.C));
	    fh->p->a.pop_mbx.C = *X;	    
	    zero_remote_account(X);     /* Avoid double free */

	    status = &(fh->p->a.pop_mbx.C);
	    
	    break;

	case PORT_imap4:
	is_imap:
	    if (!imap_only)
		imap_only = safe_strdup(":INBOX");
	    fh -> folder_type = IMAP_MBX;
	    
	    DPRINT(Debug,8,(&Debug,
			    "make_remote_mbox: IMAP mailbox (succeed)\n"));
	    
	    fh->folder_type->init_it(fh);
	    
	    if (!join_connection(fh->p->a.imap_mbx.Ch,X,CON_greeting)) 
		set_imap_connection_state(fh->p->a.imap_mbx.Ch,IMAP_error);
	    else
		set_imap_connection_state(fh->p->a.imap_mbx.Ch,IMAP_idle);
	    status = &(fh->p->a.imap_mbx.Ch->C);
	    
	    if (':' == imap_only[0]) 
		fh->p->a.imap_mbx.folder = safe_strdup(imap_only+1);
	    else
		fh->p->a.imap_mbx.folder = safe_strdup(imap_only);
	    break;
	default:
	    DPRINT(Debug,8,(&Debug,
			    "make_remote_mbox: Unknown mailbox type (service=%x, port =%d)\n",
			    se->service,got));
	    
	    lib_error(CATGETS(elm_msg_cat, MeSet,MeUnknownRemoteMailboxType,
			      "Remote mailbox type of %S unknown"),
		      fh->cur_folder_disp);
	    status = NULL;
	}	
    }

    if (status) {
	/* In here we can use temp_dir instead of default_temp because
	 * that file does not act as session lock ...
	 */

	set_remote_tempmbox(fh,status);

    } 
    
 fail:

    free_remote_account(X);

    if (imap_only)
	free(imap_only);
      
    if (status) {
	DPRINT(Debug,12,(&Debug,
			 "make_remote_mbox=1\n"));
	return 1;
    }

    DPRINT(Debug,12,(&Debug,
		     "make_remote_mbox=0\n"));
    return 0;
}


#endif


int remote_folder_type(fh)
     struct folder_info *fh;
{
    char * rest, *p;
    int ret = 0;
#ifdef REMOTE_MBX
    struct remote_account X;
    struct service_entry *se = NULL;
    int z;
#endif

    /* Explicite disallow $MAIL to be interpreted as remote mailbox */

    if ('/' == fh->cur_folder_sys[0] ||
	((p = getenv("MAIL")) && strcmp(fh->cur_folder_sys, p) == 0) ||
	0 == access(fh->cur_folder_sys,ACCESS_EXISTS)) {

	DPRINT(Debug,8,(&Debug,
			"remote_folder_type=0 (file: %s)\n",
			fh->cur_folder_sys));
	return 0;
    }

#ifdef REMOTE_MBX
    
    /* -1 == name not found or bad syntax
        0 == not a remote address
	1 == name found 
    */
    if ((z = split_remote_name(fh->cur_folder_sys,&X,&se,&rest,
			       0 /* Both IMAP and POP are OK */))) {
	
	if (z < 0) 
	    goto clean;

	/* May free X (if succeed) or copy */
	if (!make_remote_mbox(fh,&X,se,rest,1)) {
	clean:
	    free_remote_account(&X);
	    
	    fh -> folder_type = NO_NAME;
	    fh->folder_type->init_it(fh);
	}	
	free_temporary_service_entry(&se);

	ret = 1;      /* Is 'remote mailbox' ... */	    
    }
#else
    DPRINT(Debug,9,(&Debug,
		    "remote_folder_type: (remote mailboxes are not supported.)\n"));
#endif /* REMOTE_MBX */

    DPRINT(Debug,8,(&Debug,
		    "remote_folder_type=%d\n",ret));
    return ret;
}


/*
 * Local Variables:
 *  mode:c
 *  c-basic-offset:4
 *  buffer-file-coding-system: iso-8859-1
 * End:
 */


syntax highlighted by Code2HTML, v. 0.9.1