#pragma ident "@(#) ftx.h 1.1.1 2012.12.10,14:57"
#ifndef FTX_H
#define FTX_H FTX_H

#include <stdio.h>
#include <stdlib.h>
#include <string>
//#include <iostream.h>
#include <ctype.h>
#include <malloc.h>

#ifdef CYGWIN
#include <ncurses/curses.h>
#include <ncurses/form.h>
#else
#include <curses.h>
#include <form.h>
#endif

#include <locale.h>
#include <signal.h>

#include <memory.h>
#include <time.h>

#include <pthread.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>

#include <dirent.h>
#include <sys/stat.h>
#include "unistd.h"

#define True	1
#define False	0
#define INVALID_SOCKET -1
#define HFILE_ERROR -1
#define MAX_LIST	12000
#define FTX_MAX_FILES	12000

#define SOCKET int
#define BOOL int

class ftxError {
	public:
	const std::string Msg;

	ftxError(const std::string& MsgString) : Msg(MsgString) {};
};

//基底クラスはデバッグにも使える関数群にまとめた。
//これらの関数はポップアップして文字列を表示もしくは入力を行う。
//Ｘ軸とＹ軸が反対になっているのが特徴（これで見分ける?）
class PopMsg {
protected:
	char listboxmsg[1024];	//リストボックス内の文字列最大数
	char ImmediateMsg[1024];//イミディエイトボックス内の文字列最大数

	char txtWorkingDir[256];//FTX内部操作バッファ
	char txtSystemType[256];//FTX内部操作バッファ
	char cdHostPath[256];//FTX内部操作バッファ
public:

	PopMsg() {};
	virtual int popmsg(int y, int x, const std::string Message);
	virtual int popmsgBig(int y, int x, const std::string Message);
	virtual void errormsg(int y,int x,const std::string Nessage);
	virtual void ErrorMsg(const std::string Message);
	virtual void dialogmsg(int y,int x, const std::string  Message);
	virtual void MsgBox(const std::string Message);
	virtual int MsgBoxBig(const std::string Message);
	virtual int MsgBox2(const std::string Message);
	virtual void *input_window(int y,int x,char *buff,const std::string Message);
	virtual void *input_window(int y,int x,char *buff,char *buff2,const std::string Message);
	~PopMsg() {};
};

class frmSockFTP : public PopMsg {
private:
	char gszCommandBuffer[256];	//SendFTPCommand()内で使用する重要バッファ

protected:
	pid_t tmp_pid;	//テンポラリ作成時使用

public:
	//hosts.ftx ファイルの行の内容が保存される
	struct hostsFTX {
		char hostname[256];	//接続するホスト名（アドレス）
		char userid[32];	//接続するホストのユーザID
		char passwd[128];	//接続するホストのパスワード
		char homedir[256];	//接続時最初に表示するディレクトリ
		char OPTL[32];	//接続後ディレクトリ表示を行うFTPコマンド(LIST -aL 等)
		int TYPE;	//データ送受信時に設定されるデータタイプ(Image or ascci)
		int PASV;	//データ送受信時 Active-FTP か Passive-FTP かを設定する
		int WAIT;	//サーバの自動切断時間を設定する（現在簡易的処理のみ）
		char editor[128];	//利用するエディターを指定する。オプション可
		char viewer[128];	//利用するビューワーを指定する。オプション可
		char browser[256];	//利用するブラウザを指定する。オプション可
	} pf[256];

	int sig;	//未使用

	// /home/cms/etc/hosts.ftx の情報を保存
	char txtPasswordFile[256];//FTXの基本情報ファイルのパス
   	char txtHostName[256];	//登録されているホスト名
   	char txtUserID[256];	//に登録されているユーザ名
   	char txtPassword[256];	//に登録されているパスワード
   	char txtHomeDir[256];	//FTXが最初に表示するディレクトリ
	char txtOPTL[32];			//LISTコマンドとオプション
	int intTYPE;				//アスキー:0 バイナリ:1
	int intPASV;				//Acctive:0 Passive:1
	int intWAIT;				//サーバーに切断されるまでの時間
	char txtEditor[128];	//利用するエディターのデフォルトは vi
	char txtViewer[128];	//利用するビューワーのデフォルトは eog
	char txtBrowser[256];	//利用するブラウザのデフォルトは epiphany

	//
	char txtTmpDir[128];			//LISTコマンドがダウンロードするディレクトリ
	char txtTmpDirListFile[256];//LISTコマンドがダウンロードするファイル名
	char txtEditFile[256];		//テキストエディタで編集するダウンロードファイル
	char txtEditDir[256];		//ダウンロードするディレクトリ

	int optImageFileType;		//バイナリイメージ
	int strLISTfilePos;			//LISTファイルのファイル名の位置

	//for ftpfrm.cc
	void setTmpDir(void);	//
	void readHostSetFile(void);	// /home/cms/etc/hosts.ftx を読見込む
	void writeListBox(char *host,int n);	//設定を pf 構造体にセットする

	//FTPプロトコルを使用して通信を行う。直接呼出が可能。
	//以下の関数の説明は FTX のマニュアルに詳しく記述してあるのでそれを参照。
	//for ftpcom.cc
	int intDoFirstConnect(void);
	int intDoReConnect(const std::string strDirectory);
    int intDoDisconnect(void);
	u_int intDoListCommand(void);
	u_int intDoRMFILECommand(const std::string strFileName);
	u_int intDoRMDIRCommand(const std::string strDirName);
	u_int intDoMKDIRCommand(const std::string strDirName);
	u_int intDoRNFRCommand(const std::string strDirName);
	u_int intDoRNTOCommand(const std::string strDirName);
	u_int intDoNOOPCommand(void);
	u_int intDoPASSCommand(void);
	u_int intDoRETRCommand(const std::string strFileName, int optImage);
	u_int intDoSTORCommand(const std::string strFileName, int optImage);
	u_int intDoEDITCommand(const std::string strFileName, const std::string strEditFileName, int optImage);
	u_int intDoVIEWCommand(const std::string strFileName, const std::string strViewFileName);
	u_int intDoOVERWRITECommand(const std::string strFileName, const std::string strEditFileName, int optImage);
	u_int intDoPASVCommand(void);
	u_int intDoUSERCommand(void);

	//補助的な関数 ftpfrm.cc と ftpcom.cc の両方で使用
	char *Right(char *s, size_t n);
	char *Left(char *s, size_t n);
	int InStr(int start, char *str, int c);
	int rInStr(char *s, int c);
	char *Mid(char *ss, int a, int b);
	int IsKanji(char *s);
	int Findex(char *s,char *t);

	//限定的な関数 ftpcom.cc で使用
	static char *strCutCr(char *strCommand);
	static char *strCutLf(char *strCommand);
	static char *strCutCrLf(char *strText);

	//FTPプロトコルを使用して通信を行う。直接呼出が可能。
	char *strDoCDUPCommand(void);
	char *strDoXCUPCommand(void);
	char *strDoSITECommand(const std::string siteCommand,const std::string strMode,const std::string strFileName);
	char *strDoCWDCommand(const std::string  strDirectory);
	char *strDoPWDCommand(void);
	char *strDoSYSTCommand(void);
	char *strExtractQuotedExpression(char *strValue);
	char *strGetServerReply(void);
	char *strGetServerReplyText(void);
	void subGetServerReplyText(void);
	char *strTransferGetFile(int hDataSocket, const std::string strFileName);
	char *strTransferPutFile(int hControlSocket, int hDataSocket, const std::string strFileName);
	void subCloseIncompleteConnection(void);
	void subShowServerCommand(const std::string Message);
	void subShowServerReplyCode(int intReplyCode);

	void ftx(void);
	void ftx2(void);

private:
	//ソケットを使用して通信制御を行う。直接扱うことはしないこと。
	//for ftplib.cc
	u_int GetReplyCode(char *lpszServerReply);
	BOOL IsReadyToRead(int hSocket);
	u_int ReadReplyLine(char *lpszReplyBuffer);
	char *GetFTPServerReplyText(void);
BOOL CheckReceivable(int hControlSocket);
	u_int ReadFTPServerReply(int hControlChannel);
	u_int SendFTPCommand(int hControlChannel, const std::string gszCommandBuffer);
	BOOL ReadDataChannel(int hControlSocket, int hDataSocket, char *lpszFileName);
	ssize_t TransferFile(int hControlSocket, int hDataSocket, int hFile);
	int ftpwrite(int hDataSocket,char *buff,int bcount);
	int TransferFile3(int hControlSocket, int hDataSocket, int hFile);
	void ExtractFileName(char *lpPathString, char *lpszFileName);
	int CreateTransferFile(const std::string lpszFileName);
	int CreateTransferFile2(const std::string lpszFileName);
	int CreateTransferFile3(char *lpszFileName, char *strEditFileName);
	SOCKET ConnectFTPControlSocket(char *lpszHost);
	SOCKET RequestDataConnection(int hControlSocket, int hListenSocket);
	SOCKET CreateListenSocket(int hControlSocket);
	SOCKET AcceptDataConnection(int hListenSocket);
	SOCKET CreateDataSocketPASV(char * lpszHost, char *port);
};

//以下はリストボックスクラスを成形する関数
class ListBox : public frmSockFTP {
private:
	void initline(void)
	{
		line = 0;
		cursol = 0;
		index = 0;
	}
	void saveline(int y, int j)
	{
		line = y;
		cursol = j;
	}
	void ListIndex(int y, int j)
	{
		index = y + j;
	}

protected:
	char itemlist[MAX_LIST][1024];
	char initmenu[MAX_LIST][128];
	int maxline;

public:
	char selcp[256][512];	// 複数選択用
	int cpflag[256]; 		// 複数選択用
	int regline[FTX_MAX_FILES];	//ファイラー行の選択された行
	int intCPnum;	//選択された数

	int dirlocatey[256];	//ディレクトリ履歴（全体行）
	int dirlocateyy[256];	//ディレクトリ履歴（カーソル行）
	char dirlocate[256][512];	//
	int deep;	//ディレクトリ階層の深さ

	int height;	//リストボックスの高さ
	int width;	//リストボックスの横幅
	int sx;	//リストボックスの表示開始Ｘ軸位置
	int sy;	//リストボックスの表示開始Ｙ軸位置
	char title[256];	//リストボックスのタイトル
	int line;	//リストボックスの全体行
	int cursol;	//リストボックスのカーソル行
	int index;	//リストボックス内の行位置

	ListBox() {};
	virtual ~ListBox() {};
	virtual void helpmsg(int x,int y);
	virtual char *Listbox(void);
	virtual int FilerListbox(char *strEditDir);
	virtual void Filerbox(char *strEditDir);
	virtual char *Immediatebox(int fin);
	virtual char *ImmediateListbox(int addline);

	//リストボックスに行を追加する（表示は最初の行になる）
	virtual int AddItem(char *item)
	{
		maxline = maxline + 1;
		if(maxline > MAX_LIST)
			return(FALSE);
		sprintf(itemlist[maxline-1],"%s",item);
		return(TRUE);
	}
	//リストボックスに行を追加する（表示は最後の行から上になる）
	virtual int AddItemTail(char *item)
	{
		maxline = maxline + 1;
		if(maxline > MAX_LIST)
			return(FALSE);
		sprintf(itemlist[maxline-1],"%s",item);
		return(TRUE);
	}
	//リストボックスの最後の行を削除する
	virtual int DeleteItem(void)
	{
		maxline = maxline - 1;
		if(maxline < 0)
		{
			maxline = 0;
			return(FALSE);
		}
		memset(itemlist[maxline],'\0',1024);
		return(TRUE);
	}
	//リストボックス全体を消去する（行数に変化無し）
	virtual int Clear(void)
	{
		int i;
		for(i=0;i<maxline;i++)
		{
			memset(itemlist[i],'\0',1024);
		}
		line = 0;
		cursol = 0;
		maxline = 0;
		return(TRUE);
	}

	//ディレクトリ移動時の履歴と階層を保存するバッファを初期化する
	void InitCursol(int deep);
	//受信または送信ファイルの属性を調査
	char *setChmod(char *attr);
	//ファイル送信時の後で SITE コマンドで属性を設定するときに使用
	void attrview(int at,char *attrbuff);
};

//このクラスは LIST コマンドがリストファイル受信時にそのファイルをオープンする
//時使用している。
//リストボックスにファイルの内容を書き込む時や、リストボックス内の内容を保存
//する場合に使用可能
class OpenFileListBox : public ListBox {
public:
	OpenFileListBox() {};
	void ExtractFileListBox(char *name);
	virtual int SaveFileListBox(char *name);
	virtual ~OpenFileListBox() {};
};

//ftplib.cc で利用するバッファの既定値
static const int MAX_DATA_BUFF	= 4096;
static const int MAX_TXT_BUFF = 2048;

//stat 構造体定義
typedef struct stat Dir;
static Dir dptr;
static Dir *fptr = &dptr;

//libsubform.a 内にある日本語入力用関数(EUC用に作成)現在UTF8には対応していないが何とか使える。
extern "C" int jmvwgetnstr(WINDOW *win, int y, int x, unsigned char *str, int n, int wmode, int cmode);

#endif
