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 }