@@ -8,62 +8,45 @@ import (
8
8
"net/http"
9
9
"os"
10
10
"path"
11
- "path/filepath"
12
11
"strings"
13
12
)
14
13
15
14
var (
16
- backupIndexFile = "backup_index.json"
17
- dataDir = "data"
18
- backupIndex []BackupEntry
19
- addrss = "0.0.0.0"
20
- port = 8080
21
- token = ""
15
+ SavePath = "data"
16
+ Addrss = "0.0.0.0"
17
+ Port = 8080
18
+ Token = ""
22
19
)
23
20
24
21
type BackupEntry struct {
25
- Id string `json:"id"`
26
- Files []string `json:"files"`
22
+ Id string `json:"id"`
23
+ Tag string `json:"tag"`
24
+ Files map [string ]string `json:"files"`
27
25
}
28
26
29
27
func main () {
30
-
31
- flag .StringVar (& token , "token" , "" , "Authorization" )
32
- flag .StringVar (& addrss , "address" , "0.0.0.0" , "Address to listen on" )
33
- flag .IntVar (& port , "port" , 8080 , "Port to listen on" )
28
+ flag .StringVar (& Token , "token" , "" , "Authorization" )
29
+ flag .StringVar (& Addrss , "address" , "0.0.0.0" , "Address to listen on" )
30
+ flag .IntVar (& Port , "port" , 8080 , "Port to listen on" )
34
31
flag .Parse ()
35
32
36
- if token == "" {
33
+ if Token == "" {
37
34
fmt .Println ("You need to specify a token that is the same as the client" )
38
35
return
39
36
}
40
37
41
- loadBackupIndex ( )
38
+ os . MkdirAll ( SavePath , os . ModePerm )
42
39
43
40
http .HandleFunc ("/backup" , withAuth (handleBackup ))
44
- http .HandleFunc ("/file" , withAuth (handleFile ))
45
- http .ListenAndServe (fmt .Sprintf ("%s:%d" , addrss , port ), nil )
46
- }
47
-
48
- func loadBackupIndex () {
49
- file , err := os .ReadFile (backupIndexFile )
50
- if err != nil {
51
- log .Printf ("Error reading backup index file: %v\n " , err )
52
- return
53
- }
54
-
55
- err = json .Unmarshal (file , & backupIndex )
56
- if err != nil {
57
- log .Printf ("Error decoding backup index JSON: %v\n " , err )
58
- return
59
- }
41
+ http .HandleFunc ("/sync" , withAuth (handleSync ))
42
+ http .ListenAndServe (fmt .Sprintf ("%s:%d" , Addrss , Port ), nil )
60
43
}
61
44
62
45
func withAuth (next http.HandlerFunc ) http.HandlerFunc {
63
46
return func (w http.ResponseWriter , r * http.Request ) {
64
47
authHeader := r .Header .Get ("Authorization" )
65
48
uaHeader := r .Header .Get ("User-Agent" )
66
- if uaHeader != "GUI.for.Cores" || authHeader != "Bearer " + token {
49
+ if uaHeader != "GUI.for.Cores" || authHeader != "Bearer " + Token {
67
50
http .Error (w , "Unauthorized" , http .StatusUnauthorized )
68
51
return
69
52
}
@@ -74,182 +57,118 @@ func withAuth(next http.HandlerFunc) http.HandlerFunc {
74
57
func handleBackup (w http.ResponseWriter , r * http.Request ) {
75
58
switch r .Method {
76
59
case http .MethodGet :
77
- idParam := r .URL .Query ().Get ("id" )
60
+ tag := r .URL .Query ().Get ("tag" )
61
+ p := path .Join (SavePath , tag )
78
62
79
- log .Printf ("List => %s\n " , idParam )
63
+ log .Printf ("List => where tag = %s\n " , tag )
80
64
81
- var response []byte
82
- result := make ([]string , 0 )
65
+ if ! strings .HasPrefix (path .Clean (p ), SavePath ) {
66
+ http .Error (w , "403" , http .StatusForbidden )
67
+ return
68
+ }
83
69
84
- if idParam != "" {
85
- for _ , entry := range backupIndex {
86
- if entry .Id == idParam {
87
- result = entry .Files
88
- break
89
- }
90
- }
70
+ dirs , err := os .ReadDir (p )
71
+ if err != nil {
72
+ http .Error (w , err .Error (), http .StatusInternalServerError )
73
+ return
74
+ }
91
75
92
- var err error
93
- response , err = json .Marshal (result )
94
- if err != nil {
95
- http .Error (w , "Failed to marshal JSON response" , http .StatusInternalServerError )
96
- return
97
- }
98
- } else {
99
- for _ , entry := range backupIndex {
100
- result = append (result , entry .Id )
76
+ result := make ([]string , 0 )
77
+ for _ , file := range dirs {
78
+ if ! file .IsDir () {
79
+ result = append (result , file .Name ())
101
80
}
81
+ }
102
82
103
- var err error
104
- response , err = json .Marshal (result )
105
- if err != nil {
106
- http .Error (w , "Failed to marshal JSON response" , http .StatusInternalServerError )
107
- return
108
- }
83
+ response , err := json .Marshal (result )
84
+ if err != nil {
85
+ http .Error (w , err .Error (), http .StatusInternalServerError )
86
+ return
109
87
}
110
88
111
89
w .Header ().Set ("Content-Type" , "application/json" )
112
90
w .WriteHeader (http .StatusOK )
113
91
w .Write (response )
114
92
115
93
case http .MethodDelete :
94
+ tag := r .URL .Query ().Get ("tag" )
116
95
ids := r .URL .Query ().Get ("ids" )
117
96
118
- if ids == "" {
119
- http .Error (w , "Error parameter" , http .StatusBadRequest )
120
- return
121
- }
122
-
97
+ p := path .Join (SavePath , tag )
123
98
idsToDelete := strings .Split (ids , "," )
124
99
125
- log .Printf ("Remove => %s\n " , ids )
126
-
127
- updatedBackupIndex := make ([]BackupEntry , 0 )
100
+ log .Printf ("Remove => where tag = %s and id in %s\n " , tag , ids )
128
101
129
- for _ , entry := range backupIndex {
130
- found := false
131
- for _ , id := range idsToDelete {
132
- if entry .Id == id {
133
- found = true
134
- break
135
- }
136
- }
137
- if ! found {
138
- updatedBackupIndex = append (updatedBackupIndex , entry )
139
- } else {
140
- filePath := filepath .Join (dataDir , entry .Id )
141
- os .RemoveAll (filePath )
142
- }
143
- }
144
-
145
- backupIndex = updatedBackupIndex
146
-
147
- updateBackupIndexFile ()
148
-
149
- default :
150
- http .Error (w , "Method not allowed" , http .StatusMethodNotAllowed )
151
- }
152
- }
153
-
154
- func handleFile (w http.ResponseWriter , r * http.Request ) {
155
- switch r .Method {
156
- case http .MethodGet :
157
- pathParam := r .URL .Query ().Get ("path" )
158
-
159
- _path := path .Clean (path .Join (dataDir , pathParam ))
160
- if ! strings .HasPrefix (_path , dataDir ) {
161
- w .WriteHeader (http .StatusBadRequest )
102
+ if ! strings .HasPrefix (path .Clean (p ), SavePath ) {
103
+ http .Error (w , "403" , http .StatusForbidden )
162
104
return
163
105
}
164
106
165
- log .Printf ("Sync : %v\n " , pathParam )
166
-
167
- body , err := os .ReadFile (_path )
168
- if err != nil {
169
- w .WriteHeader (http .StatusNotFound )
170
- return
107
+ for _ , id := range idsToDelete {
108
+ os .RemoveAll (path .Join (p , id ))
171
109
}
172
110
173
- w .Header ().Set ("Content-Type" , "text/plain" )
174
111
w .WriteHeader (http .StatusOK )
175
- w .Write (body )
176
112
177
113
case http .MethodPost :
178
- var requestBody map [ string ] string
179
- err := json .NewDecoder (r .Body ).Decode (& requestBody )
114
+ var body BackupEntry
115
+ err := json .NewDecoder (r .Body ).Decode (& body )
180
116
if err != nil {
181
- http .Error (w , "Failed to parse request body" , http .StatusBadRequest )
117
+ http .Error (w , err . Error () , http .StatusBadRequest )
182
118
return
183
119
}
184
120
185
- id := requestBody ["id" ]
186
- filename := requestBody ["file" ]
187
- fileContent := requestBody ["body" ]
121
+ p := path .Join (SavePath , body .Tag , body .Id )
188
122
189
- log .Printf ("Backup : %v => % v\n " , id , filename )
123
+ log .Printf ("Backup : id = %s, tag = %s, files.length = % v\n " , body . Id , body . Tag , len ( body . Files ) )
190
124
191
- filePath := filepath .Join (dataDir , id , filename )
192
- err = os .MkdirAll (filepath .Dir (filePath ), 0755 )
193
- if err != nil {
194
- http .Error (w , "Failed to create directory" , http .StatusInternalServerError )
125
+ if ! strings .HasPrefix (path .Clean (p ), SavePath ) {
126
+ http .Error (w , "403" , http .StatusForbidden )
195
127
return
196
128
}
197
129
198
- err = os . WriteFile ( filePath , [] byte ( fileContent ), 0644 )
130
+ b , err := json . Marshal ( body )
199
131
if err != nil {
200
- http .Error (w , "Failed to write file" , http .StatusInternalServerError )
132
+ log .Printf ("Backup err %v" , err .Error ())
133
+ http .Error (w , err .Error (), http .StatusBadRequest )
201
134
return
202
135
}
203
136
204
- updateBackupIndex (id , filename )
137
+ os .MkdirAll (path .Join (SavePath , body .Tag ), os .ModePerm )
138
+
139
+ os .WriteFile (p + ".json" , b , 0644 )
205
140
206
141
w .WriteHeader (http .StatusCreated )
142
+
207
143
default :
208
144
http .Error (w , "Method not allowed" , http .StatusMethodNotAllowed )
209
145
}
210
146
}
211
147
212
- func updateBackupIndex (id , filename string ) {
213
- var found bool
214
- for i , entry := range backupIndex {
215
- if entry .Id == id {
216
- // Check if file already exists in the list
217
- found = true
218
- foundFile := false
219
- for _ , file := range entry .Files {
220
- if file == filename {
221
- foundFile = true
222
- break
223
- }
224
- }
225
- // If file not found, append to the list
226
- if ! foundFile {
227
- backupIndex [i ].Files = append (backupIndex [i ].Files , filename )
228
- }
229
- break
148
+ func handleSync (w http.ResponseWriter , r * http.Request ) {
149
+ switch r .Method {
150
+ case http .MethodGet :
151
+ tag := r .URL .Query ().Get ("tag" )
152
+ id := r .URL .Query ().Get ("id" )
153
+
154
+ p := path .Join (SavePath , tag , id )
155
+
156
+ if ! strings .HasPrefix (p , SavePath ) {
157
+ http .Error (w , "403" , http .StatusForbidden )
158
+ return
230
159
}
231
- }
232
- if ! found {
233
- backupIndex = append (backupIndex , BackupEntry {
234
- Id : id ,
235
- Files : []string {filename },
236
- })
237
- }
238
160
239
- updateBackupIndexFile ()
240
- }
161
+ b , err := os .ReadFile (p )
162
+ if err != nil {
163
+ http .Error (w , "403" , http .StatusForbidden )
164
+ return
165
+ }
241
166
242
- func updateBackupIndexFile () {
243
- // Update backup index file
244
- jsonData , err := json .MarshalIndent (backupIndex , "" , " " )
245
- if err != nil {
246
- log .Printf ("Error marshaling backup index JSON: %v\n " , err )
247
- return
248
- }
167
+ w .Header ().Set ("Content-Type" , "application/json" )
168
+ w .WriteHeader (http .StatusOK )
169
+ w .Write (b )
249
170
250
- err = os .WriteFile (backupIndexFile , jsonData , 0644 )
251
- if err != nil {
252
- log .Printf ("Error writing backup index file: %v\n " , err )
253
- return
171
+ default :
172
+ http .Error (w , "Method not allowed" , http .StatusMethodNotAllowed )
254
173
}
255
174
}
0 commit comments