mirror of
https://github.com/Picocrypt/Picocrypt.git
synced 2025-05-12 13:48:31 +02:00
Merge pull request #89 from Retengart/test-features
App version in the window title and zip unpacking
This commit is contained in:
commit
670d284603
4 changed files with 151 additions and 7 deletions
|
@ -3,6 +3,12 @@
|
|||
<li>Migrate golang.org/x/crypto to standard library imports (https://github.com/golang/go/issues/65269)</li>
|
||||
</ul>
|
||||
|
||||
# v1.46 (Released 01/29/2025)
|
||||
<ul>
|
||||
<li>✓ Added Picocrypt version to the window title</li>
|
||||
<li>✓ Added ability to automatically unzip archives upon decryption</li>
|
||||
</ul>
|
||||
|
||||
# v1.45 (Released 12/05/2024)
|
||||
<ul>
|
||||
<li>✓ Bumped GitHub Actions Ubuntu 22 -> 24 and macOS 14 -> 15</li>
|
||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
|||
1.45
|
||||
1.46
|
||||
|
|
|
@ -44,11 +44,17 @@
|
|||
</screenshot>
|
||||
</screenshots>
|
||||
<releases>
|
||||
<release version="1.45" date="2024-12-05">
|
||||
<url type="details">https://github.com/Picocrypt/Picocrypt/blob/main/Changelog.md#v145-released-12052024</url>
|
||||
<release version="1.46" date="2025-01-29">
|
||||
<url type="details">https://github.com/Picocrypt/Picocrypt/blob/main/Changelog.md#v146-released-01292025</url>
|
||||
<description>
|
||||
<p>No code changes; just updated dependencies.</p>
|
||||
<ul>
|
||||
<li>Added Picocrypt version to the window title.</li>
|
||||
<li>Added ability to automatically unpack zip archives during decryption.</li>
|
||||
</ul>
|
||||
</description>
|
||||
</release>
|
||||
<release version="1.45" date="2024-12-05">
|
||||
<description></description>
|
||||
</release>
|
||||
</releases>
|
||||
</component>
|
||||
|
|
138
src/Picocrypt.go
138
src/Picocrypt.go
|
@ -2,7 +2,7 @@ package main
|
|||
|
||||
/*
|
||||
|
||||
Picocrypt v1.45
|
||||
Picocrypt v1.46
|
||||
Copyright (c) Evan Su
|
||||
Released under a GNU GPL v3 License
|
||||
https://github.com/Picocrypt/Picocrypt
|
||||
|
@ -60,7 +60,7 @@ var TRANSPARENT = color.RGBA{0x00, 0x00, 0x00, 0x00}
|
|||
|
||||
// Generic variables
|
||||
var window *giu.MasterWindow
|
||||
var version = "v1.45"
|
||||
var version = "v1.46"
|
||||
var dpi float32
|
||||
var mode string
|
||||
var working bool
|
||||
|
@ -120,6 +120,8 @@ var splitSelected int32 = 1
|
|||
var recombine bool
|
||||
var compress bool
|
||||
var delete bool
|
||||
var autoUnzip bool
|
||||
var sameLevel bool
|
||||
var keep bool
|
||||
var kept bool
|
||||
|
||||
|
@ -552,6 +554,22 @@ func draw() {
|
|||
giu.Checkbox("Delete volume", &delete),
|
||||
giu.Tooltip("Delete the volume after a successful decryption"),
|
||||
).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"),
|
||||
),
|
||||
).Build()
|
||||
}
|
||||
}),
|
||||
|
||||
|
@ -2112,6 +2130,21 @@ func work() {
|
|||
os.Remove(inputFile)
|
||||
}
|
||||
|
||||
if mode == "decrypt" && !kept && autoUnzip {
|
||||
showProgress = true
|
||||
popupStatus = "Unzipping..."
|
||||
giu.Update()
|
||||
|
||||
if err := unpackArchive(outputFile); err != nil {
|
||||
mainStatus = "Auto unzipping failed!"
|
||||
mainStatusColor = RED
|
||||
giu.Update()
|
||||
return
|
||||
}
|
||||
|
||||
os.Remove(outputFile)
|
||||
}
|
||||
|
||||
// All done, reset the UI
|
||||
oldKept := kept
|
||||
resetUI()
|
||||
|
@ -2209,6 +2242,8 @@ func resetUI() {
|
|||
recombine = false
|
||||
compress = false
|
||||
delete = false
|
||||
autoUnzip = false
|
||||
sameLevel = false
|
||||
keep = false
|
||||
kept = false
|
||||
|
||||
|
@ -2330,9 +2365,106 @@ func sizeify(size int64) string {
|
|||
}
|
||||
}
|
||||
|
||||
func unpackArchive(zipPath string) error {
|
||||
reader, err := zip.OpenReader(zipPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer reader.Close()
|
||||
|
||||
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"))
|
||||
}
|
||||
|
||||
var done int64
|
||||
startTime := time.Now()
|
||||
|
||||
for _, f := range reader.File {
|
||||
if strings.Contains(f.Name, "..") {
|
||||
return errors.New("potentially malicious zip item path")
|
||||
}
|
||||
outPath := filepath.Join(extractDir, f.Name)
|
||||
|
||||
// Make directory if current entry is a folder
|
||||
if f.FileInfo().IsDir() {
|
||||
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
|
||||
}
|
||||
|
||||
// Open the file inside the archive
|
||||
fileInArchive, err := f.Open()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer fileInArchive.Close()
|
||||
|
||||
dstFile, err := os.Create(outPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Read from zip in chunks to update progress
|
||||
buffer := make([]byte, MiB)
|
||||
for {
|
||||
n, readErr := fileInArchive.Read(buffer)
|
||||
if n > 0 {
|
||||
_, writeErr := dstFile.Write(buffer[:n])
|
||||
if writeErr != nil {
|
||||
dstFile.Close()
|
||||
os.Remove(dstFile.Name())
|
||||
return writeErr
|
||||
}
|
||||
|
||||
done += int64(n)
|
||||
progress, speed, eta = statify(done, totalSize, startTime)
|
||||
progressInfo = fmt.Sprintf("%d/%d", i+1, len(reader.File))
|
||||
popupStatus = fmt.Sprintf("Unpacking at %.2f MiB/s (ETA: %s)", speed, eta)
|
||||
giu.Update()
|
||||
}
|
||||
if readErr != nil {
|
||||
if readErr == io.EOF {
|
||||
break
|
||||
}
|
||||
dstFile.Close()
|
||||
return readErr
|
||||
}
|
||||
}
|
||||
dstFile.Close()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Create the main window
|
||||
window = giu.NewMasterWindow("Picocrypt", 318, 507, giu.MasterWindowFlagsNotResizable)
|
||||
window = giu.NewMasterWindow("Picocrypt "+version[1:], 318, 507, giu.MasterWindowFlagsNotResizable)
|
||||
|
||||
// Start the dialog module
|
||||
dialog.Init()
|
||||
|
|
Loading…
Add table
Reference in a new issue