Compare commits

..

No commits in common. "47b65d6fe0f97ac4b9cc5935048e34eeb9e1d3bf" and "525ee4d591c6a87dd7e7584044dd5c8210fab859" have entirely different histories.

View file

@ -120,8 +120,7 @@ var splitSelected int32 = 1
var recombine bool
var compress bool
var delete bool
var autoUnzip bool
var sameLevel bool
var unpack bool
var keep bool
var kept bool
@ -556,19 +555,8 @@ func draw() {
).Build()
giu.Row(
giu.Style().SetDisabled(!strings.HasSuffix(inputFile, ".zip.pcv")).To(
giu.Checkbox("Auto unzip", &autoUnzip).OnChange(func() {
if !autoUnzip {
sameLevel = false
}
}),
giu.Tooltip("Extract .zip upon decryption (may overwrite)"),
),
giu.Dummy(-170, 0),
giu.Style().SetDisabled(!autoUnzip).To(
giu.Checkbox("Same level", &sameLevel),
giu.Tooltip("Extract .zip contents to same folder as volume"),
),
giu.Checkbox("Unpack .zip", &unpack),
giu.Tooltip("Extract the decrypted .zip (overwrite files)"),
).Build()
}
}),
@ -2130,21 +2118,29 @@ func work() {
os.Remove(inputFile)
}
if mode == "decrypt" && !kept && autoUnzip {
showProgress = true
popupStatus = "Unzipping..."
if mode == "decrypt" && !kept && unpack {
showProgress = true // Turn on the progress popup
canCancel = true // Allow the user to cancel
progress = 0
progressInfo = ""
popupStatus = "Preparing to unpack..."
giu.Update()
if err := unpackArchive(outputFile); err != nil {
mainStatus = "Auto unzipping failed!"
err := unpackArchive(outputFile)
if err != nil {
mainStatus = "Extraction failed: " + err.Error()
mainStatusColor = RED
giu.Update()
return
}
os.Remove(outputFile)
// Turn off the progress UI
showProgress = false
canCancel = false
progress = 0
progressInfo = ""
popupStatus = ""
giu.Update()
}
// All done, reset the UI
oldKept := kept
resetUI()
@ -2242,8 +2238,7 @@ func resetUI() {
recombine = false
compress = false
delete = false
autoUnzip = false
sameLevel = false
unpack = false
keep = false
kept = false
@ -2366,31 +2361,33 @@ func sizeify(size int64) string {
}
func unpackArchive(zipPath string) error {
// Open the .zip
reader, err := zip.OpenReader(zipPath)
if err != nil {
return err
}
defer reader.Close()
// Calculate total unpack size by summing each entrys UncompressedSize64
var totalSize int64
for _, f := range reader.File {
totalSize += int64(f.UncompressedSize64)
}
var extractDir string
if sameLevel {
extractDir = filepath.Dir(zipPath)
} else {
extractDir = filepath.Join(filepath.Dir(zipPath), strings.TrimSuffix(filepath.Base(zipPath), ".zip"))
}
// Directory containing the .zip
extractDir := filepath.Dir(zipPath)
// Setup progress tracking
var done int64
startTime := time.Now()
for _, f := range reader.File {
if strings.Contains(f.Name, "..") {
return errors.New("potentially malicious zip item path")
// Iterate over each file in the archive
for i, f := range reader.File {
// If user clicked "Cancel" elsewhere, stop
if !working {
return errors.New("operation canceled by user")
}
outPath := filepath.Join(extractDir, f.Name)
// Make directory if current entry is a folder
@ -2398,21 +2395,9 @@ func unpackArchive(zipPath string) error {
if err := os.MkdirAll(outPath, f.Mode()); err != nil {
return err
}
}
}
for i, f := range reader.File {
if strings.Contains(f.Name, "..") {
return errors.New("potentially malicious zip item path")
}
// Already handled above
if f.FileInfo().IsDir() {
continue
}
outPath := filepath.Join(extractDir, f.Name)
// Otherwise create necessary parent directories
if err := os.MkdirAll(filepath.Dir(outPath), 0755); err != nil {
return err
@ -2425,14 +2410,20 @@ func unpackArchive(zipPath string) error {
}
defer fileInArchive.Close()
dstFile, err := os.Create(outPath)
// Create/overwrite the destination file
dstFile, err := os.OpenFile(outPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
if err != nil {
return err
}
// Read from zip in chunks to update progress
buffer := make([]byte, MiB)
buffer := make([]byte, MiB) // e.g., 1 MiB chunk
for {
if !working {
dstFile.Close()
os.Remove(outPath) // remove partial extraction if canceled
return errors.New("operation canceled by user")
}
n, readErr := fileInArchive.Read(buffer)
if n > 0 {
_, writeErr := dstFile.Write(buffer[:n])
@ -2441,6 +2432,7 @@ func unpackArchive(zipPath string) error {
return writeErr
}
// Update "done" and recalc progress, speed, eta
done += int64(n)
progress, speed, eta = statify(done, totalSize, startTime)
progressInfo = fmt.Sprintf("%d/%d", i+1, len(reader.File))