//**************************************************************************
//*                     This file is part of the                           *
//*                      Mpxplay - audio player.                           *
//*                  The source code of Mpxplay is                         *
//*        (C) copyright 1998-2011 by PDSoft (Attila Padar)                *
//*                http://mpxplay.sourceforge.net                          *
//*                  email: mpxplay@freemail.hu                            *
//**************************************************************************
//*  This program is distributed in the hope that it will be useful,       *
//*  but WITHOUT ANY WARRANTY; without even the implied warranty of        *
//*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                  *
//*  Please contact with the author (with me) if you want to use           *
//*  or modify this source.                                                *
//**************************************************************************
//function:open ftp connection window (ctrl-f)

#include "mpxplay.h"
#include "control/cntfuncs.h"
#include "diskdriv/diskdriv.h"
#include "display/display.h"
#include <string.h>

#ifdef MPXPLAY_LINK_TCPIP

#define OPENFTP_MAINFLAGS_FTPINI_CHECKED   (1 <<  0)
#define OPENFTP_MAINFLAGS_FTPINI_MODIFIED  (1 <<  1)
#define OPENFTP_MAINFLAGS_EDITTYPE_NEW     (1 <<  2)

#define OPENFTP_SESSIONFLAGS_CONSTANT      (1 <<  0)

#define OPENFTP_FTPINI_DATATYPE_NORMSTR 0
#define OPENFTP_FTPINI_DATATYPE_DECNUM  1 // decimal number
#define OPENFTP_FTPINI_DATATYPE_HEXNUM  2 // hex number
#define OPENFTP_FTPINI_DATATYPE_HEXSTR  3 // hex-coded str
#define OPENFTP_FTPINI_DATATYPE_CFGBIN  4 // hex-coded binary data (configlen allocated)
#define OPENFTP_FTPINI_DATATYPE_MASK   0x0f

#define OPENFTP_FTPINI_DATAFLAG_CHKNULL (1<<8)
#define OPENFTP_FTPINI_DATAFLAG_SESNEW  (1<<9)
#define OPENFTP_FTPINI_DATAFLAG_CFGLINE (1<<10)

// else normal str

struct openftp_session_info_s{
 unsigned long flags;
 //unsigned int configtype;
 //unsigned int configlen;
 unsigned long configdata;
 char session_name[64];
 char protocol_name[16];
 char server_name[128];
 char login_name[64];
 char password[64];
 char remote_dir[256];
 char drive_letter[4];
};

static struct openftp_main_info_s{
 unsigned long flags;
 unsigned int nb_sessions;          // number of all loaded sessions
 unsigned int nb_builtin_sessions;  // don't save these in mpxp_ftp.ini
 unsigned int session_select;
 struct openftp_session_info_s *session_infos;
 char **session_names;
 struct playlist_side_info *psi;
 unsigned int drivenum;
 unsigned long ftp_default_config;
 struct openftp_session_info_s ses_tmp;
 char ftpurl_name[MAX_PATHNAMELEN];
}openftp_main_infos;

extern unsigned long mpxplay_diskdrive_drvftp_config;

static struct openftp_session_info_s *openftp_session_new(struct openftp_main_info_s *omi)
{
 struct openftp_session_info_s *sis_new=pds_malloc((omi->nb_sessions+1)*sizeof(*sis_new)),*sn;
 if(!sis_new)
  return sis_new;
 if(omi->session_infos){
  pds_memcpy(sis_new,omi->session_infos,omi->nb_sessions*sizeof(*sis_new));
  pds_free(omi->session_infos);
 }
 omi->session_infos=sis_new;
 sn=sis_new+omi->nb_sessions;
 pds_memset(sn,0,sizeof(*sn));
 //sn->configtype=OPENFTP_FTPINI_DATATYPE_HEXNUM; //
 //sn->configlen=4;                        //
 sn->configdata=omi->ftp_default_config; // !!! ftp only
 omi->session_select=omi->nb_sessions++;
 return sn;
}

static struct openftp_session_info_s *openftp_session_dup(struct openftp_main_info_s *omi)
{
 struct openftp_session_info_s *sn;
 unsigned int snum=omi->session_select;
 if(!omi->nb_sessions || !omi->session_infos || (snum>=omi->nb_sessions))
  return NULL;
 if(!openftp_session_new(omi))
  return NULL;
 snum++;
 omi->session_select=snum;
 sn=omi->session_infos+snum;
 memmove(sn,(sn-1),(omi->nb_sessions-snum)*sizeof(*sn));
 funcbit_enable(omi->flags,OPENFTP_MAINFLAGS_FTPINI_MODIFIED);
 return sn;
}

static void openftp_session_del(struct openftp_main_info_s *omi)
{
 unsigned int snum=omi->session_select;
 if(!omi->nb_sessions || !omi->session_infos || (snum>=omi->nb_sessions))
  return;
 omi->nb_sessions--;
 if(snum<omi->nb_sessions){
  struct openftp_session_info_s *sd=omi->session_infos+snum;
  pds_memcpy(sd,sd+1,(omi->nb_sessions-snum)*sizeof(*sd));
 }else if(snum)
  omi->session_select--;
}

static void openftp_session_sort(struct openftp_main_info_s *omi,unsigned int twodirection)
{
 struct openftp_session_info_s *sn;
 unsigned int snum=omi->session_select;
 if((omi->nb_sessions<2) || !omi->session_infos || (snum>=omi->nb_sessions))
  return;
 sn=omi->session_infos+snum;
 while(snum > omi->nb_builtin_sessions){
  if(pds_stricmp((sn-1)->session_name,sn->session_name)<=0)
   break;
  pds_memxch((char *)(sn-1),(char *)sn,sizeof(*sn));
  snum--;sn--;
 }
 if(twodirection && (omi->session_select==snum) && (snum<(omi->nb_sessions-1))){
  do{
   if(pds_stricmp((sn+1)->session_name,sn->session_name)>=0)
    break;
   pds_memxch((char *)(sn+1),(char *)sn,sizeof(*sn));
   sn++;snum++;
  }while(snum<(omi->nb_sessions-1));
 }
 omi->session_select=snum;
}

static void openftp_session_names_collect(struct openftp_main_info_s *omi)
{
 struct openftp_session_info_s *si;
 char **sn=pds_malloc((omi->nb_sessions+1)*sizeof(*sn));
 unsigned int i;
 if(!sn)
  return;
 if(omi->session_names)
  pds_free(omi->session_names);
 omi->session_names=sn;
 i=omi->nb_sessions;
 si=omi->session_infos;
 if(i && si){
  do{
   *sn=&si->session_name[0];
   sn++;si++;
  }while(--i);
 }
 *sn=NULL;
}

//------------------------------------------------------------------------
static display_textwin_button_t openftp_editsession_buttons[]={
 {"[ Ok ]"    ,KEY_ENTER1},// gray enter
 {""          ,KEY_ENTER2},// white enter
 {"[ Cancel ]",KEY_ESC},   // ESC
 {NULL,0}
};

static void openftp_editsession_finish(struct openftp_main_info_s *omi,unsigned int extkey)
{
 struct openftp_session_info_s *s;
 switch(extkey){
  case KEY_ENTER1:
  case KEY_ENTER2:
   s=omi->session_infos+omi->session_select;
   pds_memcpy(s,&omi->ses_tmp,sizeof(omi->ses_tmp));
   if(!s->protocol_name[0])
    pds_strcpy(s->protocol_name,"ftp");
   if(!s->server_name[0])
    pds_strcpy(s->server_name,s->session_name);
   else if(!s->session_name)
    pds_strcpy(s->session_name,s->server_name);
   if(!s->session_name[0])
    sprintf(s->session_name,"Session %d",(omi->session_select+1));
   s->drive_letter[1]=0;
   if((s->drive_letter[0]<'0') || (s->drive_letter[0]>'7')) // !!!
    s->drive_letter[0]=0;
   openftp_session_sort(omi,((omi->flags&OPENFTP_MAINFLAGS_EDITTYPE_NEW)? 0:1));
   funcbit_enable(omi->flags,OPENFTP_MAINFLAGS_FTPINI_MODIFIED);
   break;
  case KEY_ESC:
   if(funcbit_test(omi->flags,OPENFTP_MAINFLAGS_EDITTYPE_NEW)){
    openftp_session_del(omi);
    omi->session_select=0;
   }
   break;
 }
 mpxplay_timer_addfunc(mpxplay_diskdrive_openftp_connect,omi->psi,MPXPLAY_TIMERTYPE_WAKEUP,0);
}

static void openftp_editsession_window(struct openftp_main_info_s *omi)
{
 struct openftp_session_info_s *s=&omi->ses_tmp;
 void *tw=display_textwin_allocwindow_items(NULL,0," Edit session ",openftp_editsession_finish,omi);

 display_textwin_additem_msg_static(tw,0,0,0,"Session name");
 display_textwin_additem_editline(tw,0,0,16,0,30,s->session_name,sizeof(s->session_name)-1);

 display_textwin_additem_msg_static(tw,0,0,2,"Protocol (ftp)");
 display_textwin_additem_editline(tw,0,0,16,2,30,s->protocol_name,sizeof(s->protocol_name)-1);

 display_textwin_additem_msg_static(tw,0,0,4,"Hostname[:port]");
 display_textwin_additem_editline(tw,0,0,16,4,30,s->server_name,sizeof(s->server_name)-1);

 display_textwin_additem_msg_static(tw,0,0,6,"Login name");
 display_textwin_additem_editline(tw,0,0,16,6,30,s->login_name,sizeof(s->login_name)-1);

 display_textwin_additem_msg_static(tw,0,0,8,"Password");
 display_textwin_additem_editline(tw,0,TEXTWIN_EDITFLAG_HIDDENTYPE,16,8,30,s->password,sizeof(s->password)-1);

 display_textwin_additem_msg_static(tw,0,0,10,"Remote dir");
 display_textwin_additem_editline(tw,0,0,16,10,30,s->remote_dir,sizeof(s->remote_dir)-1);

 display_textwin_additem_msg_static(tw,0,0,12,"DrvLetter (0-7)");
 display_textwin_additem_editline(tw,0,0,16,12,30,s->drive_letter,sizeof(s->drive_letter)-1);

 display_textwin_additem_switchline(tw,0,0,14,&s->configdata,DRVFTP_FTPDRIVE_FLAG_PASSIVE_MODE,"Use passive mode (like www browsers)");
 display_textwin_additem_switchline(tw,0,0,-1,&s->configdata,DRVFTP_FTPDRIVE_FLAG_AUTO_RECONNECT,"Auto reconnect (if connection losts)");
 display_textwin_additem_switchline(tw,0,0,-1,&s->configdata,DRVFTP_FTPDRIVE_FLAG_USE_ANONYM_LOGIN,"Use anonym login (if no user/pasw)");
 display_textwin_additem_switchline(tw,0,0,-1,&s->configdata,DRVFTP_FTPDRIVE_FLAG_USE_UTF8,"Use UTF-8 communication (if available)");

 display_textwin_additem_separatorline(tw,-1);
 display_textwin_additem_buttons(tw,TEXTWIN_FLAG_MSGCENTERALIGN,0,-1,&openftp_editsession_buttons[0],NULL);
 display_textwin_openwindow_items(tw,0,0,0);
}

//------------------------------------------------------------------------
static void openftp_urlopen_do(struct openftp_main_info_s *omi)
{
 struct mpxplay_virtualdrivemount_s vdm;
 pds_memset((char *)(&vdm),0,sizeof(vdm));
 vdm.psi=omi->psi;
 vdm.fullinitside=1;
 vdm.retry=1;
 vdm.drivenum=omi->drivenum;
 pds_strcpy(vdm.path,omi->ftpurl_name);
 playlist_loaddir_virtualdrive_mount(&vdm);
}

static void openftp_urlopen_window(struct openftp_main_info_s *omi)
{
 void *tw;
 struct mpxplay_diskdrive_data_s mdds;
 unsigned long len=sizeof(omi->ftpurl_name);

 mpxplay_diskdrive_drvftp_config=omi->ftp_default_config; // !!! ftp only

 pds_memset(&mdds,0,sizeof(mdds));
 mdds.mdfs=mpxplay_diskdrive_search_driver((omi->ftpurl_name[0])? omi->ftpurl_name:"ftp:");
 mpxplay_diskdrive_drive_config(&mdds,MPXPLAY_DISKDRIV_CFGFUNCNUM_GET_DRVOPENNAME,&omi->ftpurl_name[0],&len);
 omi->drivenum=0;

 tw=display_textwin_allocwindow_items(NULL,TEXTWIN_FLAG_MSGCENTERALIGN|TEXTWIN_FLAG_CONFIRM|TEXTWIN_FLAG_NOWINMINSIZE," Connect ",openftp_urlopen_do,omi);
#ifdef MPXPLAY_WIN32
 display_textwin_additem_msg_static(tw,0,0,-1," Open connection (ftp[es]://user:pasw@server[:port][/dir])");
#else
 display_textwin_additem_msg_static(tw,0,0,-1," Open connection (ftp://user:pasw@server[:port][/dir])");
#endif
 display_textwin_additem_editline(tw,TEXTWIN_FLAG_MSGCENTERALIGN,0,0,-1,55,&omi->ftpurl_name[0],sizeof(omi->ftpurl_name)-16);
 display_textwin_additem_separatorline(tw,-1);
 display_textwin_additem_buttons(tw,TEXTWIN_FLAG_MSGCENTERALIGN,0,-1,&openftp_editsession_buttons[0],NULL);
 display_textwin_openwindow_items(tw,0,0,0);
}

//---------------------------------------------------------------------
static display_textwin_button_t openftp_delsession_buttons[]={
 {" Delete "  ,KEY_ENTER1},// gray enter
 {""          ,KEY_ENTER2},// white enter
 {" Cancel "  ,KEY_ESC},   // ESC
 {NULL,0}
};

static void openftp_delsession_keyhand(struct openftp_main_info_s *omi,unsigned int extkey)
{
 switch(extkey){
  case KEY_ENTER1:
  case KEY_ENTER2:
     openftp_session_del(omi);
     funcbit_enable(omi->flags,OPENFTP_MAINFLAGS_FTPINI_MODIFIED);
     break;
 }
 mpxplay_timer_addfunc(mpxplay_diskdrive_openftp_connect,omi->psi,MPXPLAY_TIMERTYPE_WAKEUP,0);
}

static void openftp_delsession_window(struct openftp_main_info_s *omi)
{
 struct openftp_session_info_s *s=omi->session_infos+omi->session_select;
 void *tw=display_textwin_allocwindow_items(NULL,TEXTWIN_FLAG_ERRORMSG|TEXTWIN_FLAG_MSGCENTERALIGN," Delete session ",openftp_delsession_keyhand,omi);
 display_textwin_additem_msg_static(tw,TEXTWIN_FLAG_MSGCENTERALIGN,0,-1,s->session_name);
 display_textwin_additem_buttons(tw,TEXTWIN_FLAG_MSGCENTERALIGN,0,-1,&openftp_delsession_buttons[0],NULL);
 display_textwin_openwindow_items(tw,0,0,0);
}

//------------------------------------------------------------------------
static display_textwin_button_t openftp_selectfunc_buttons[]={
 {"[ Connect  ]",0x2e63}, // 'c'
 {""            ,0x2e43}, // 'C'
 {"[ New Conn ]",0x316e}, // 'n'
 {""            ,0x314e}, // 'N'
 {"[ URL open ]",0x1675}, // 'u'
 {""            ,0x1655}, // 'U'
 {"[ Duplicate]",0x2064}, // 'd'
 {""            ,0x2044}, // 'D'
 {"[   Edit   ]",0x1265}, // 'e'
 {""            ,0x1245}, // 'E'
 {"[  Delete  ]",0x266c}, // 'l'
 {""            ,0x264c}, // 'L'
 {"[  Cancel  ]",0x2106}, // ctrl-f
 {""            ,KEY_ESC},// ESC
 {NULL,0}
};

static void openftp_function_select(struct playlist_side_info *psi,unsigned int extkey)
{
 struct openftp_main_info_s *omi=&openftp_main_infos;
 struct openftp_session_info_s *s;

 if(omi->session_infos && omi->nb_sessions){
  if(omi->session_select>=omi->nb_sessions)
   omi->session_select=0;
  s=omi->session_infos+omi->session_select;
 }else
  s=NULL;

 omi->psi=psi;
 switch(extkey){
  case 0x2e63: // 'c'
  case 0x2e43:if(s){
               snprintf(omi->ftpurl_name,sizeof(omi->ftpurl_name),"%s://%s%s%s%s%s%s%s",
                s->protocol_name,s->login_name,((s->login_name[0] && s->password[0])? ":":""),
                s->password,((s->login_name[0] || s->password[0])? "@":""),
                s->server_name,((s->remote_dir[0] && s->remote_dir[0]!='/')? "/":""),
                s->remote_dir);
               omi->drivenum=(s->drive_letter[0]? (pds_atol(s->drive_letter)+1):0);
               mpxplay_diskdrive_drvftp_config=s->configdata; // !!! ftp only
               openftp_urlopen_do(omi);
               return;
              }
              break;
  case 0x316e: // 'n'
  case 0x314e:if(openftp_session_new(omi)){
               funcbit_enable(omi->flags,OPENFTP_MAINFLAGS_EDITTYPE_NEW);
               s=omi->session_infos+omi->session_select;
               pds_memcpy(&omi->ses_tmp,s,sizeof(omi->ses_tmp));
               mpxplay_timer_addfunc(openftp_editsession_window,omi,MPXPLAY_TIMERTYPE_WAKEUP,0);
               return;
              }
              break;
  case 0x1675: // 'u'
  case 0x1655:mpxplay_timer_addfunc(openftp_urlopen_window,omi,MPXPLAY_TIMERTYPE_WAKEUP,0);
              return;
  case 0x2106: // ctrl-f
  case KEY_ESC:return;// ESC
 }

 if(s && !funcbit_test(s->flags, OPENFTP_SESSIONFLAGS_CONSTANT)){
  switch(extkey){
   case 0x2064: // 'd'
   case 0x2044:openftp_session_dup(omi);
               break;
   case 0x1265: // 'e'
   case 0x1245:if(s){
                funcbit_disable(omi->flags,OPENFTP_MAINFLAGS_EDITTYPE_NEW);
                pds_memcpy(&omi->ses_tmp,s,sizeof(omi->ses_tmp));
                mpxplay_timer_addfunc(openftp_editsession_window,omi,MPXPLAY_TIMERTYPE_WAKEUP,0);
                return;
               }
               break;
   case 0x266c: // 'l'
   case 0x264c:if(s){
                mpxplay_timer_addfunc(openftp_delsession_window,omi,MPXPLAY_TIMERTYPE_WAKEUP,0);
                return;
               }
               break;
  }
 }

 mpxplay_timer_addfunc(mpxplay_diskdrive_openftp_connect,psi,MPXPLAY_TIMERTYPE_WAKEUP,0);
}

//------------------------------------------------------------------------
struct ftpini_data_s{
 char *type_name;
 unsigned short maxdatasize;
 unsigned short dataoffs;
 unsigned short flags;
}ftpini_datas[]={
 {"Session",64,offsetof(struct openftp_session_info_s,session_name),OPENFTP_FTPINI_DATAFLAG_SESNEW},
 {"Protocol",16,offsetof(struct openftp_session_info_s,protocol_name),OPENFTP_FTPINI_DATATYPE_NORMSTR},
 {"Server",128,offsetof(struct openftp_session_info_s,server_name),OPENFTP_FTPINI_DATAFLAG_CHKNULL},
 {"Login",64,offsetof(struct openftp_session_info_s,login_name),OPENFTP_FTPINI_DATAFLAG_CHKNULL},
 {"Password",64,offsetof(struct openftp_session_info_s,password),(OPENFTP_FTPINI_DATAFLAG_CHKNULL|OPENFTP_FTPINI_DATATYPE_HEXSTR)},
 {"Remotedir",256,offsetof(struct openftp_session_info_s,remote_dir),OPENFTP_FTPINI_DATAFLAG_CHKNULL},
 {"Driveletter",4,offsetof(struct openftp_session_info_s,drive_letter),OPENFTP_FTPINI_DATAFLAG_CHKNULL},
 {"Flags",4,offsetof(struct openftp_session_info_s,configdata),OPENFTP_FTPINI_DATATYPE_HEXNUM},
 //{"Configtype",4,offsetof(struct openftp_session_info_s,configtype),OPENFTP_FTPINI_DATATYPE_DECNUM},
 //{"Configlen",4,offsetof(struct openftp_session_info_s,configlen),OPENFTP_FTPINI_DATATYPE_DECNUM},
 //{"Configdata",4,offsetof(struct openftp_session_info_s,configdata),OPENFTP_FTPINI_DATAFLAG_CFGBIN},
 {NULL,0,0}
};

static void openftp_get_ftpini_filename(char *strbuf)
{
 mpxplay_control_get_ini_path(strbuf);
 pds_filename_assemble_fullname(strbuf,strbuf,"MPXP_FTP.INI");
}

static unsigned int openftp_read_sessiontextdata(struct openftp_main_info_s *omi, void *fp,unsigned long extra_session_flags)
{
 struct openftp_session_info_s *s=NULL;
 unsigned int session_count=0;
 char strtmp[MAX_PATHNAMELEN],stmp[256];

 while(mpxplay_diskdrive_textfile_readline(fp,strtmp,sizeof(strtmp)-1) > 0){
  struct ftpini_data_s *fid;
  char *d=pds_strchr(strtmp,'=');
  if(!d)
   continue;
  *d++=0;
  fid=&ftpini_datas[0];
  do{
   if(pds_strcmp(strtmp,fid->type_name)==0){
    char *dataptr;
    if(fid->flags&OPENFTP_FTPINI_DATAFLAG_SESNEW){
     s=openftp_session_new(omi);
     if(s){
      funcbit_enable(s->flags, extra_session_flags);
      session_count++;
     }
    }
    if(!s)
     break;
    dataptr=(char *)s+fid->dataoffs;
    switch(fid->flags&OPENFTP_FTPINI_DATATYPE_MASK){
     case OPENFTP_FTPINI_DATATYPE_HEXNUM:
      *((unsigned long *)dataptr)=pds_atol16(d);
      break;
     case OPENFTP_FTPINI_DATATYPE_HEXSTR:
      pds_hexs_to_str(d,stmp,sizeof(stmp));
      d=&stmp[0];
     case OPENFTP_FTPINI_DATATYPE_NORMSTR:
      pds_strncpy(dataptr,d,fid->maxdatasize);
      dataptr[fid->maxdatasize-1]=0;
    }
    break;
   }
  }while((++fid)->type_name);
 }
 return session_count;
}

static void openftp_load_ftpini(struct openftp_main_info_s *omi)
{
 void *fp;
 struct mpxplay_drivehand_func_s *mdfs,**mdfp;
 char strtmp[MAX_PATHNAMELEN];

 if(funcbit_test(omi->flags,OPENFTP_MAINFLAGS_FTPINI_CHECKED))
  return;
 funcbit_enable(omi->flags,OPENFTP_MAINFLAGS_FTPINI_CHECKED);
 omi->ftp_default_config=mpxplay_diskdrive_drvftp_config; // !!!

 mdfp = &mpxplay_diskdriv_all_drivehand_funcs[0];
 mdfs = *mdfp;
 do{
  char *sessdata;
  unsigned long datalen;
  sessdata = NULL;
  datalen = 0;
  if(mdfs->drive_config && (mdfs->drive_config(NULL,MPXPLAY_DISKDRIV_CFGFUNCNUM_GET_CONSTSESSIONS,&sessdata,&datalen) >= 0) && sessdata && datalen){
   fp=mpxplay_diskdrive_textfile_virtual_open(sessdata, datalen, O_TEXT);
   if(fp){
    omi->nb_builtin_sessions += openftp_read_sessiontextdata(omi, fp, OPENFTP_SESSIONFLAGS_CONSTANT);
    mpxplay_diskdrive_textfile_close(fp);
   }
  }
  mdfp++;
  mdfs=*mdfp;
 }while(mdfs);

 openftp_get_ftpini_filename(&strtmp[0]);
 fp=mpxplay_diskdrive_textfile_open(NULL,strtmp,(O_RDONLY|O_TEXT));
 if(!fp)
  return;
 openftp_read_sessiontextdata(omi, fp, 0);
 mpxplay_diskdrive_textfile_close(fp);
 omi->session_select=0;
}

static void openftp_save_ftpini(struct openftp_main_info_s *omi)
{
 unsigned int i;
 void *fp;
 struct openftp_session_info_s *s;
 char sout[MAX_PATHNAMELEN],stmp[256];

 if(!funcbit_test(omi->flags,OPENFTP_MAINFLAGS_FTPINI_CHECKED))
  return;
 if(!funcbit_test(omi->flags,OPENFTP_MAINFLAGS_FTPINI_MODIFIED))
  return;

 openftp_get_ftpini_filename(&sout[0]);

 if(!omi->nb_sessions){
  pds_unlink(sout);
  return;
 }

 fp=mpxplay_diskdrive_textfile_open(NULL,sout,(O_WRONLY|O_CREAT|O_TEXT));
 if(!fp)
  return;

 i=MPXPLAY_TEXTCONV_TYPE_MPXNATIVE;
 mpxplay_diskdrive_textfile_config(fp,MPXPLAY_DISKTEXTFILE_CFGFUNCNUM_SET_TEXTCODETYPE_DEST,((void *)&i),NULL);

 s=omi->session_infos + omi->nb_builtin_sessions;
 i=omi->nb_sessions - omi->nb_builtin_sessions;
 do{
  struct ftpini_data_s *fid=&ftpini_datas[0];
  do{
   unsigned long numdata;
   char *dataptr=(char *)s+fid->dataoffs;
   switch(fid->flags&OPENFTP_FTPINI_DATATYPE_MASK){
    case OPENFTP_FTPINI_DATATYPE_HEXNUM:
     numdata=*((unsigned long *)dataptr);
     if((fid->flags&OPENFTP_FTPINI_DATAFLAG_CHKNULL) && !numdata)
      continue;
     snprintf(sout,sizeof(sout),"%s=%8.8X",fid->type_name,numdata);
     break;
    case OPENFTP_FTPINI_DATATYPE_HEXSTR:
     pds_str_to_hexs(dataptr,stmp,sizeof(stmp));
     dataptr=&stmp[0];
    case OPENFTP_FTPINI_DATATYPE_NORMSTR:
     if((fid->flags&OPENFTP_FTPINI_DATAFLAG_CHKNULL) && !dataptr[0])
      continue;
     snprintf(sout,sizeof(sout),"%s=%s",fid->type_name,dataptr);
   }
   mpxplay_diskdrive_textfile_writeline(fp,sout);
  }while((++fid)->type_name);
  s++;
 }while(--i);
 mpxplay_diskdrive_textfile_close(fp);
}

//------------------------------------------------------------------------
void mpxplay_diskdrive_openftp_connect(struct playlist_side_info *psi)
{
 struct openftp_main_info_s *omi=&openftp_main_infos;
 void *tw;
 openftp_load_ftpini(omi);
 openftp_session_names_collect(omi);
 tw=display_textwin_allocwindow_items(NULL,TEXTWIN_FLAG_MSGCENTERALIGN|TEXTWIN_FLAG_NOWINMINSIZE," Connect to server ",openftp_function_select,psi);
 display_textwin_additem_msg_static(tw,0,0,-1," Select host:");
 display_textwin_additem_listlines(tw,0,1,1,25,13,omi->nb_sessions,&openftp_main_infos.session_names[0],&(openftp_main_infos.session_select));
 display_textwin_additem_buttons(tw,TEXTWIN_FLAG_VERTICALBUTTONS|TEXTWIN_FLAG_USEEMPTYLINES,28,1,&openftp_selectfunc_buttons[0],NULL);
 display_textwin_openwindow_items(tw,0,0,0);
}

void mpxplay_diskdrive_openftp_disconnect(struct playlist_side_info *psi)
{
 if(psi->mdds && psi->mdds->mdfs && funcbit_test(psi->mdds->mdfs->infobits,MPXPLAY_DRIVEHANDFUNC_INFOBIT_DISCONNECT))
  playlist_loaddir_drive_unmount(psi,psi->mdds);
 else if(psi->psio->mdds && psi->psio->mdds->mdfs && funcbit_test(psi->psio->mdds->mdfs->infobits,MPXPLAY_DRIVEHANDFUNC_INFOBIT_DISCONNECT))
  playlist_loaddir_drive_unmount(psi->psio,psi->psio->mdds);
}

void mpxplay_diskdrive_openftp_close(void)
{
 struct openftp_main_info_s *omi=&openftp_main_infos;
 openftp_save_ftpini(omi);
 if(omi->session_infos){
  pds_free(omi->session_infos);
  omi->session_infos=NULL;
 }
 if(omi->session_names){
  pds_free(omi->session_names);
  omi->session_names=NULL;
 }
}

#else
void mpxplay_diskdrive_openftp_connect(struct playlist_side_info *psi)
{
 display_textwin_openwindow_errormsg_head_ok(" FTP "," FTP client is not implemented in this version!");
}
void mpxplay_diskdrive_openftp_disconnect(struct playlist_side_info *psi)
{
}
void mpxplay_diskdrive_openftp_close(void)
{
}
#endif // MPXPLAY_LINK_TCPIP
