From c6b56a1f6db79ec4fa38e3fcd802bebf44984eb5 Mon Sep 17 00:00:00 2001
From: Eric_Lee <xplzv@126.com>
Date: Wed, 9 Oct 2019 16:52:57 +0800
Subject: [PATCH] Dev (#98)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* [bugfix] cat二进制文件 界面卡顿 (#96)

* [Bugfix] config的从环境变量解析非字符串值报错 (#97)
---
 pkg/config/config.go   | 32 ++++++++++++++++++++++++++-
 pkg/proxy/parsercmd.go | 50 +++++++++++++++++++++++++++---------------
 pkg/utils/terminal.go  |  2 ++
 3 files changed, 65 insertions(+), 19 deletions(-)

diff --git a/pkg/config/config.go b/pkg/config/config.go
index 9d39d78..d993bbf 100644
--- a/pkg/config/config.go
+++ b/pkg/config/config.go
@@ -5,6 +5,7 @@ import (
 	"io/ioutil"
 	"log"
 	"os"
+	"strconv"
 	"strings"
 	"sync"
 	"time"
@@ -95,7 +96,36 @@ func (c *Config) LoadFromEnv() error {
 		vSlice := strings.Split(v, "=")
 		key := vSlice[0]
 		value := vSlice[1]
-		envMap[key] = value
+		// 环境变量的值,非字符串类型的解析,需要另作处理
+		switch key {
+		case "SFTP_SHOW_HIDDEN_FILE", "REUSE_CONNECTION", "UPLOAD_FAILED_REPLAY_ON_START":
+			switch strings.ToLower(value) {
+			case "true", "on":
+				switch key {
+				case "SFTP_SHOW_HIDDEN_FILE":
+					c.ShowHiddenFile = true
+				case "REUSE_CONNECTION":
+					c.ReuseConnection = true
+				case "UPLOAD_FAILED_REPLAY_ON_START":
+					c.UploadFailedReplay = true
+				}
+			case "false", "off":
+				switch key {
+				case "SFTP_SHOW_HIDDEN_FILE":
+					c.ShowHiddenFile = false
+				case "REUSE_CONNECTION":
+					c.ReuseConnection = false
+				case "UPLOAD_FAILED_REPLAY_ON_START":
+					c.UploadFailedReplay = false
+				}
+			}
+		case "SSH_TIMEOUT":
+			if num, err := strconv.Atoi(value); err == nil {
+				c.SSHTimeout = time.Duration(num)
+			}
+		default:
+			envMap[key] = value
+		}
 	}
 	envYAML, err := yaml.Marshal(&envMap)
 	if err != nil {
diff --git a/pkg/proxy/parsercmd.go b/pkg/proxy/parsercmd.go
index 14aaeb5..2fcb038 100644
--- a/pkg/proxy/parsercmd.go
+++ b/pkg/proxy/parsercmd.go
@@ -19,56 +19,70 @@ func NewCmdParser() *CmdParser {
 }
 
 type CmdParser struct {
-	term *utils.Terminal
-	reader io.ReadCloser
-	writer io.WriteCloser
-	currentLines []string
-	lock *sync.Mutex
-	maxLength int
+	term          *utils.Terminal
+	reader        io.ReadCloser
+	writer        io.WriteCloser
+	currentLines  []string
+	lock          *sync.Mutex
+	maxLength     int
 	currentLength int
-
+	closed        chan struct{}
 }
 
-func (cp *CmdParser) WriteData(p []byte) (int,error){
+func (cp *CmdParser) WriteData(p []byte) (int, error) {
 	return cp.writer.Write(p)
 }
 
-func (cp *CmdParser) Write (p []byte) (int,error){
-	return len(p),nil
+func (cp *CmdParser) Write(p []byte) (int, error) {
+	return len(p), nil
 }
 
-func (cp *CmdParser) Read(p []byte)(int,error){
+func (cp *CmdParser) Read(p []byte) (int, error) {
 	return cp.reader.Read(p)
 }
 
-func (cp *CmdParser) Close() error{
+func (cp *CmdParser) Close() error {
+	select {
+	case <-cp.closed:
+		return nil
+	default:
+		close(cp.closed)
+	}
 	return cp.writer.Close()
 }
 
 func (cp *CmdParser) initial() {
-	cp.reader,cp.writer = io.Pipe()
-	cp.currentLines = make([]string,0)
+	cp.reader, cp.writer = io.Pipe()
+	cp.currentLines = make([]string, 0)
 	cp.lock = new(sync.Mutex)
 	cp.maxLength = 1024
 	cp.currentLength = 0
+	cp.closed = make(chan struct{})
 
 	cp.term = utils.NewTerminal(cp, "")
 	cp.term.SetEcho(false)
 	go func() {
 		logger.Debug("command Parser start")
 		defer logger.Debug("command Parser close")
+	inloop:
 		for {
 			line, err := cp.term.ReadLine()
-			if err != nil{
-				break
+			if err != nil {
+				select {
+				case <-cp.closed:
+					goto outloop
+				default:
+				}
+				goto inloop
 			}
 			cp.lock.Lock()
 			cp.currentLength += len(line)
 			if cp.currentLength < cp.maxLength {
-				cp.currentLines = append(cp.currentLines,line)
+				cp.currentLines = append(cp.currentLines, line)
 			}
 			cp.lock.Unlock()
 		}
+	outloop:
 	}()
 }
 
@@ -83,7 +97,7 @@ func (cp *CmdParser) Parse() string {
 	defer cp.lock.Unlock()
 	output := strings.TrimSpace(strings.Join(cp.currentLines, "\r\n"))
 	output = cp.parsePS1(output)
-	cp.currentLines = make([]string,0)
+	cp.currentLines = make([]string, 0)
 	cp.currentLength = 0
 	return output
 }
diff --git a/pkg/utils/terminal.go b/pkg/utils/terminal.go
index eebfe04..d1c5165 100644
--- a/pkg/utils/terminal.go
+++ b/pkg/utils/terminal.go
@@ -801,6 +801,8 @@ func (t *Terminal) readLine() (line string, err error) {
 			if !t.pasteActive {
 				if key == keyCtrlD {
 					if len(t.line) == 0 {
+						// as key has already handled, we need update remainder data,
+						t.remainder = rest
 						return "", io.EOF
 					}
 				}
-- 
2.18.0