|
6 | 6 | "encoding/json" |
7 | 7 | "errors" |
8 | 8 | "fmt" |
| 9 | + "github.com/forceu/gokapi/cmd/cli-uploader/cliflags" |
9 | 10 | "github.com/forceu/gokapi/internal/encryption" |
10 | 11 | "github.com/forceu/gokapi/internal/encryption/end2end" |
11 | 12 | "github.com/forceu/gokapi/internal/helper" |
@@ -106,68 +107,83 @@ func getUrl(url string, headers []header) (string, error) { |
106 | 107 | return string(body), nil |
107 | 108 | } |
108 | 109 |
|
109 | | -func UploadFile(f *os.File) (string, error) { |
| 110 | +func UploadFile(uploadParams cliflags.UploadConfig) (models.FileApiOutput, error) { |
| 111 | + file, err := os.OpenFile(uploadParams.File, os.O_RDONLY, 0664) |
| 112 | + if err != nil { |
| 113 | + fmt.Println("ERROR: Could not open file to upload") |
| 114 | + fmt.Println(err) |
| 115 | + os.Exit(4) |
| 116 | + } |
110 | 117 | maxSize, chunkSize, isE2e, err := GetConfig() |
111 | | - // TODO check for 401 |
112 | 118 | if err != nil { |
113 | | - return "", err |
| 119 | + return models.FileApiOutput{}, err |
114 | 120 | } |
115 | | - if len(e2eKey) == 0 { |
| 121 | + // TODO check for 401 |
| 122 | + |
| 123 | + if len(e2eKey) == 0 || !isE2e || uploadParams.DisableE2e { |
116 | 124 | isE2e = false |
117 | 125 | } |
118 | | - fi, err := f.Stat() |
| 126 | + fileStat, err := file.Stat() |
119 | 127 | if err != nil { |
120 | | - return "", err |
| 128 | + return models.FileApiOutput{}, err |
121 | 129 | } |
122 | | - sizeBytes := fi.Size() |
123 | | - realSize := fi.Size() |
| 130 | + sizeBytes := fileStat.Size() |
| 131 | + realSize := fileStat.Size() |
124 | 132 | if isE2e { |
125 | 133 | sizeBytes = encryption.CalculateEncryptedFilesize(sizeBytes) |
126 | 134 | } |
127 | 135 | if sizeBytes > int64(maxSize)*megaByte { |
128 | | - return "", EFileTooBig |
| 136 | + return models.FileApiOutput{}, EFileTooBig |
129 | 137 | } |
130 | 138 | uuid := helper.GenerateRandomString(30) |
131 | 139 |
|
132 | 140 | if isE2e { |
133 | 141 | cipher, err := encryption.GetRandomCipher() |
134 | 142 | if err != nil { |
135 | | - return "", err |
| 143 | + return models.FileApiOutput{}, err |
136 | 144 | } |
137 | | - stream, err := encryption.GetEncryptReader(cipher, f) |
| 145 | + stream, err := encryption.GetEncryptReader(cipher, file) |
138 | 146 | if err != nil { |
139 | | - return "", err |
| 147 | + return models.FileApiOutput{}, err |
140 | 148 | } |
141 | 149 | for i := int64(0); i < sizeBytes; i = i + (int64(chunkSize) * megaByte) { |
142 | 150 | err = uploadChunk(stream, uuid, i, int64(chunkSize)*megaByte, sizeBytes) |
143 | 151 | if err != nil { |
144 | | - return "", err |
| 152 | + return models.FileApiOutput{}, err |
145 | 153 | } |
146 | 154 | } |
147 | | - file, err := completeChunk(uuid, "Encrypted File", sizeBytes, realSize, true) |
| 155 | + metaData, err := completeChunk(uuid, "Encrypted File", sizeBytes, realSize, true, uploadParams) |
148 | 156 | if err != nil { |
149 | | - return "", err |
| 157 | + return models.FileApiOutput{}, err |
150 | 158 | } |
151 | | - err = addE2EFileInfo(models.E2EFile{ |
| 159 | + |
| 160 | + e2eFile := models.E2EFile{ |
152 | 161 | Uuid: uuid, |
153 | | - Id: file.Id, |
154 | | - Filename: getFileName(f), |
| 162 | + Id: metaData.Id, |
| 163 | + Filename: getFileName(file), |
155 | 164 | Cipher: cipher, |
156 | | - }) |
157 | | - return file.Id, err |
| 165 | + } |
| 166 | + err = addE2EFileInfo(e2eFile) |
| 167 | + if err != nil { |
| 168 | + return models.FileApiOutput{}, err |
| 169 | + } |
| 170 | + hashContent, err := getHashContent(e2eFile) |
| 171 | + metaData.UrlDownload = metaData.UrlDownload + "#" + hashContent |
| 172 | + metaData.Name = getFileName(file) |
| 173 | + return metaData, err |
158 | 174 | } |
159 | 175 |
|
160 | 176 | for i := int64(0); i < sizeBytes; i = i + (int64(chunkSize) * megaByte) { |
161 | | - err = uploadChunk(f, uuid, i, int64(chunkSize)*megaByte, sizeBytes) |
| 177 | + err = uploadChunk(file, uuid, i, int64(chunkSize)*megaByte, sizeBytes) |
162 | 178 | if err != nil { |
163 | | - return "", err |
| 179 | + return models.FileApiOutput{}, err |
164 | 180 | } |
165 | 181 | } |
166 | | - file, err := completeChunk(uuid, nameToBase64(f), sizeBytes, realSize, false) |
| 182 | + metaData, err := completeChunk(uuid, nameToBase64(file), sizeBytes, realSize, false, uploadParams) |
167 | 183 | if err != nil { |
168 | | - return "", err |
| 184 | + return models.FileApiOutput{}, err |
169 | 185 | } |
170 | | - return file.Id, nil |
| 186 | + return metaData, nil |
171 | 187 | } |
172 | 188 |
|
173 | 189 | func nameToBase64(f *os.File) string { |
@@ -237,24 +253,28 @@ func uploadChunk(f io.Reader, uuid string, offset, chunkSize, filesize int64) er |
237 | 253 | return nil |
238 | 254 | } |
239 | 255 |
|
240 | | -func completeChunk(uid, filename string, filesize, realsize int64, useE2e bool) (models.File, error) { |
| 256 | +func completeChunk(uid, filename string, filesize, realsize int64, useE2e bool, uploadParams cliflags.UploadConfig) (models.FileApiOutput, error) { |
241 | 257 | type expectedFormat struct { |
242 | | - FileInfo models.File `json:"FileInfo"` |
| 258 | + FileInfo models.FileApiOutput `json:"FileInfo"` |
243 | 259 | } |
244 | 260 | result, err := getUrl(gokapiUrl+"/chunk/complete", []header{ |
245 | 261 | {"uuid", uid}, |
246 | 262 | {"filename", filename}, |
247 | 263 | {"filesize", strconv.FormatInt(filesize, 10)}, |
248 | 264 | {"realsize", strconv.FormatInt(realsize, 10)}, |
249 | 265 | {"isE2E", strconv.FormatBool(useE2e)}, |
| 266 | + {"allowedDownloads", strconv.Itoa(uploadParams.ExpiryDownloads)}, |
| 267 | + {"expiryDays", strconv.Itoa(uploadParams.ExpiryDays)}, |
| 268 | + {"password", uploadParams.Password}, |
| 269 | + {"contenttype", "application/octet-stream"}, // TODO |
250 | 270 | }) |
251 | 271 | if err != nil { |
252 | | - return models.File{}, err |
| 272 | + return models.FileApiOutput{}, err |
253 | 273 | } |
254 | 274 | var parsedResult expectedFormat |
255 | 275 | err = json.Unmarshal([]byte(result), &parsedResult) |
256 | 276 | if err != nil { |
257 | | - return models.File{}, err |
| 277 | + return models.FileApiOutput{}, err |
258 | 278 | } |
259 | 279 | return parsedResult.FileInfo, nil |
260 | 280 | } |
@@ -321,5 +341,15 @@ func setE2eInfo(input models.E2EInfoEncrypted) error { |
321 | 341 | } |
322 | 342 | _ = resp.Body.Close() |
323 | 343 | return nil |
| 344 | +} |
324 | 345 |
|
| 346 | +func getHashContent(input models.E2EFile) (string, error) { |
| 347 | + output, err := json.Marshal(models.E2EHashContent{ |
| 348 | + Filename: input.Filename, |
| 349 | + Cipher: base64.StdEncoding.EncodeToString(input.Cipher), |
| 350 | + }) |
| 351 | + if err != nil { |
| 352 | + return "", err |
| 353 | + } |
| 354 | + return base64.StdEncoding.EncodeToString(output), nil |
325 | 355 | } |
0 commit comments