github.com/upyun/upx@v0.4.7-0.20240419023638-b184a7cb7c10/config.go (about)

     1  package upx
     2  
     3  import (
     4  	"encoding/base64"
     5  	"encoding/json"
     6  	"fmt"
     7  	"io/ioutil"
     8  	"os"
     9  	"path/filepath"
    10  	"runtime"
    11  
    12  	"github.com/upyun/upx/xerrors"
    13  )
    14  
    15  const (
    16  	LOGIN     = true
    17  	NO_LOGIN  = false
    18  	MinJitter = 5
    19  	MaxJitter = 60
    20  	MaxRetry  = 10
    21  )
    22  
    23  type Config struct {
    24  	SessionId int        `json:"user_idx"`
    25  	Sessions  []*Session `json:"users"`
    26  }
    27  
    28  func (c *Config) PopCurrent() {
    29  	if c.SessionId == -1 {
    30  		c.SessionId = 0
    31  	}
    32  
    33  	c.Sessions = append(c.Sessions[0:c.SessionId], c.Sessions[c.SessionId+1:]...)
    34  	c.SessionId = 0
    35  }
    36  
    37  func (c *Config) Insert(sess *Session) {
    38  	for idx, s := range c.Sessions {
    39  		if s.Bucket == sess.Bucket && s.Operator == sess.Operator {
    40  			c.Sessions[idx] = sess
    41  			c.SessionId = idx
    42  			return
    43  		}
    44  	}
    45  	c.Sessions = append(c.Sessions, sess)
    46  	c.SessionId = len(c.Sessions) - 1
    47  }
    48  
    49  var (
    50  	confname string
    51  	config   *Config
    52  )
    53  
    54  func makeAuthStr(bucket, operator, password string) (string, error) {
    55  	sess := &Session{
    56  		Bucket:   bucket,
    57  		Operator: operator,
    58  		Password: password,
    59  		CWD:      "/",
    60  	}
    61  	if err := sess.Init(); err != nil {
    62  		return "", err
    63  	}
    64  
    65  	s := []string{bucket, operator, password}
    66  
    67  	b, err := json.Marshal(s)
    68  	if err != nil {
    69  		return "", err
    70  	}
    71  	return hashEncode(base64.StdEncoding.EncodeToString(b)), nil
    72  }
    73  
    74  func authStrToConfig(auth string) error {
    75  	data, err := base64.StdEncoding.DecodeString(hashEncode(auth))
    76  	if err != nil {
    77  		return err
    78  	}
    79  	ss := []string{}
    80  	if err := json.Unmarshal(data, &ss); err != nil {
    81  		return err
    82  	}
    83  	if len(ss) == 3 {
    84  		session = &Session{
    85  			Bucket:   ss[0],
    86  			Operator: ss[1],
    87  			Password: ss[2],
    88  			CWD:      "/",
    89  		}
    90  		if err := session.Init(); err != nil {
    91  			return err
    92  		}
    93  	} else {
    94  		return fmt.Errorf("invalid auth string")
    95  	}
    96  	return nil
    97  }
    98  
    99  func readConfigFromFile(login bool) error {
   100  	if confname == "" {
   101  		confname = getConfigName()
   102  	}
   103  
   104  	b, err := ioutil.ReadFile(confname)
   105  	if err != nil {
   106  		os.RemoveAll(confname)
   107  		if os.IsNotExist(err) && login == NO_LOGIN {
   108  			return nil
   109  		}
   110  		return err
   111  	}
   112  
   113  	data, err := base64.StdEncoding.DecodeString(hashEncode(string(b)))
   114  	if err != nil {
   115  		os.RemoveAll(confname)
   116  		return err
   117  	}
   118  
   119  	config = &Config{SessionId: -1}
   120  	if err := json.Unmarshal(data, config); err != nil {
   121  		os.RemoveAll(confname)
   122  		return err
   123  	}
   124  
   125  	if config.SessionId != -1 && config.SessionId < len(config.Sessions) {
   126  		session = config.Sessions[config.SessionId]
   127  		if login == LOGIN {
   128  			if err := session.Init(); err != nil {
   129  				config.PopCurrent()
   130  				return err
   131  			}
   132  		}
   133  	} else {
   134  		if login == LOGIN {
   135  			return xerrors.ErrRequireLogin
   136  		}
   137  	}
   138  	return nil
   139  }
   140  
   141  func saveConfigToFile() {
   142  	if confname == "" {
   143  		confname = getConfigName()
   144  	}
   145  
   146  	b, err := json.Marshal(config)
   147  	if err != nil {
   148  		PrintErrorAndExit("save config: %v", err)
   149  	}
   150  	s := hashEncode(base64.StdEncoding.EncodeToString(b))
   151  
   152  	fd, err := os.Create(confname)
   153  	if err != nil {
   154  		PrintErrorAndExit("save config: %v", err)
   155  	}
   156  	defer fd.Close()
   157  	_, err = fd.WriteString(s)
   158  
   159  	if err != nil {
   160  		PrintErrorAndExit("save config: %v", err)
   161  	}
   162  }
   163  
   164  func getConfigName() string {
   165  	if runtime.GOOS == "windows" {
   166  		return filepath.Join(os.Getenv("USERPROFILE"), ".upx.cfg")
   167  	}
   168  	return filepath.Join(os.Getenv("HOME"), ".upx.cfg")
   169  }
   170  
   171  func hashEncode(s string) string {
   172  	r := []rune(s)
   173  	for i := 0; i < len(r); i++ {
   174  		switch {
   175  		case r[i] >= 'a' && r[i] <= 'z':
   176  			r[i] += 'A' - 'a'
   177  		case r[i] >= 'A' && r[i] <= 'Z':
   178  			r[i] += 'a' - 'A'
   179  		case r[i] >= '0' && r[i] <= '9':
   180  			r[i] = '9' - r[i] + '0'
   181  		}
   182  	}
   183  	return string(r)
   184  }