Being localization process

This commit is contained in:
Evan Su 2021-08-18 20:34:35 -04:00 committed by GitHub
parent bc7d1ec8b2
commit 656c5fc256
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -37,6 +37,7 @@ import (
"image/color"
"archive/zip"
"encoding/hex"
"encoding/json"
"path/filepath"
"runtime/debug"
@ -60,25 +61,40 @@ import (
"github.com/AllenDang/giu"
// Reed-Solomon
"github.com/HACKERALERT/infectious" // v0.0.0-20210730231340-8af02cb9ed0a
"github.com/HACKERALERT/infectious" // v0.0.0-20210818221523-92bdec168696
// Helpers
"github.com/cloudfoundry-attic/jibber_jabber"
"github.com/HACKERALERT/clipboard" // v0.1.5-0.20210716140604-61d96bf4fc94
"github.com/HACKERALERT/dialog" // v0.0.0-20210716143851-223edea1d840
"github.com/HACKERALERT/browser" // v0.0.0-20210730230128-85901a8dd82f
"github.com/HACKERALERT/browser" // v0.0.0-20210818221535-991cc324ab76
"github.com/HACKERALERT/zxcvbn-go" // v0.0.0-20210730224720-b29e9dba62c2
)
var version = "v1.17"
//go:embed NotoSans-Regular.ttf
//go:embed font.ttf
var font []byte
//go:embed sdelete64.exe
var sdelete64bytes []byte
//go:embed icon.png
var iconBytes []byte
//go:embed strings.json
var localeBytes []byte
type locale struct{
iso string
data []string
}
var locales []locale
var selectedLocale = "en"
// Languages
var languages = []string{
"English",
@ -132,7 +148,7 @@ var passwordState = giu.InputTextFlagsPassword
var passwordStateLabel = "Show"
var cPassword string // Confirm password text entry string variable
var keyfilePath string
var keyfileLabel = "Use a keyfile"
var keyfileLabel = "Keyfile"
var metadata string
var metadataPrompt = "Metadata (optional):"
var metadataState = giu.InputTextFlagsNone
@ -205,7 +221,7 @@ func startUI(){
// The tab bar, which contains different tabs for different functions
giu.TabBar().TabItems(
// Main file encryption/decryption tab
giu.TabItem("Main").Layout(
giu.TabItem(s("Encryption")).Layout(
// Update 'tab' to indicate that this is the active tab
giu.Custom(func(){
if giu.IsItemActive(){
@ -216,22 +232,22 @@ func startUI(){
// Password generator modal
giu.Custom(func(){
if showGenpass{
giu.PopupModal("Generate password:").Layout(
giu.PopupModal(s("Generate password:")).Layout(
giu.Row(
giu.Label("Length: "),
giu.Label(s("Length:")),
giu.SliderInt("",&genpassLength,4,64).Size(-0.0000001),
),
giu.Checkbox("Uppercase",&genpassUpper),
giu.Checkbox("Lowercase",&genpassLower),
giu.Checkbox("Numbers",&genpassNums),
giu.Checkbox("Symbols",&genpassSymbols),
giu.Checkbox("Copy to clipboard",&genpassCopy),
giu.Checkbox(s("Uppercase"),&genpassUpper),
giu.Checkbox(s("Lowercase"),&genpassLower),
giu.Checkbox(s("Numbers"),&genpassNums),
giu.Checkbox(s("Symbols"),&genpassSymbols),
giu.Checkbox(s("Copy to clipboard"),&genpassCopy),
giu.Row(
giu.Button("Cancel").Size(100,0).OnClick(func(){
giu.Button(s("Cancel")).Size(100,0).OnClick(func(){
giu.CloseCurrentPopup()
showGenpass = false
}),
giu.Button("Generate").Size(100,0).OnClick(func(){
giu.Button(s("Generate")).Size(100,0).OnClick(func(){
tmp := genPassword()
password = tmp
cPassword = tmp
@ -242,7 +258,7 @@ func startUI(){
}),
),
).Build()
giu.OpenPopup("Generate password:")
giu.OpenPopup(s("Generate password:"))
giu.Update()
}
}),
@ -250,14 +266,14 @@ func startUI(){
// Confirm overwrite with a modal
giu.Custom(func(){
if showConfirmation{
giu.PopupModal("Warning:").Layout(
giu.Label("Output already exists. Overwrite?"),
giu.PopupModal(s("Warning:")).Layout(
giu.Label(s("Output already exists. Overwrite?")),
giu.Row(
giu.Button("No").Size(100,0).OnClick(func(){
giu.Button(s("No")).Size(100,0).OnClick(func(){
giu.CloseCurrentPopup()
showConfirmation = false
}),
giu.Button("Yes").Size(100,0).OnClick(func(){
giu.Button(s("Yes")).Size(100,0).OnClick(func(){
giu.CloseCurrentPopup()
showConfirmation = false
showProgress = true
@ -272,7 +288,7 @@ func startUI(){
}),
),
).Build()
giu.OpenPopup("Warning:")
giu.OpenPopup(s("Warning:"))
giu.Update()
}
}),
@ -290,7 +306,7 @@ func startUI(){
// Progress bar
giu.Row(
giu.ProgressBar(progress).Size(280,0).Overlay(progressInfo),
giu.Button("Cancel").Size(58,0).OnClick(func(){
giu.Button(s("Cancel")).Size(58,0).OnClick(func(){
working = false
}),
),
@ -303,21 +319,21 @@ func startUI(){
// Label listing the input files and a button to clear them
giu.Row(
giu.Label(inputLabel),
giu.Label(s(inputLabel)),
giu.Row(
giu.Dummy(-58,0),
giu.Button("Clear").Size(50,0).OnClick(resetUI),
giu.Tooltip("Clear all input files and reset UI state."),
giu.Button(s("Clear")).Size(50,0).OnClick(resetUI),
giu.Tooltip(s("Clear all input files and reset UI state.")),
),
),
// Allow user to choose a custom output path and/or name
giu.Label("Save output as:"),
giu.Label(s("Save output as:")),
giu.Row(
giu.InputText(&outputEntry).Size(outputWidth/dpi),
giu.Label(orLabel),
giu.Button("Choose").OnClick(func(){
file,_ := dialog.File().Title("Save output as...").Save()
giu.Button(s("Choose")).OnClick(func(){
file,_ := dialog.File().Title(s("Save output as...")).Save()
// Return if user canceled the file dialog
if file==""{
@ -338,52 +354,52 @@ func startUI(){
outputEntry = file
}).Size(64,0),
giu.Tooltip("Select a custom name and path to save the output as."),
giu.Tooltip(s("Select a custom name and path to save the output as.")),
),
// Prompt for password
giu.Row(
giu.Label("Password:"),
giu.Label(s("Password:")),
giu.Custom(func(){
if mode!="decrypt"{
giu.Row(
giu.Button("Generate").OnClick(func(){
giu.Button(s("Generate")).OnClick(func(){
showGenpass = true
}),
giu.Tooltip("Use this to generate a cryptographically secure password."),
giu.Tooltip(s("Use this to generate a cryptographically secure password.")),
giu.Button("Copy").OnClick(func(){
giu.Button(s("Copy")).OnClick(func(){
clipboard.WriteAll(password)
}),
giu.Tooltip("Copies the contents of the password field into your clipboard."),
giu.Tooltip(s("Copies the contents of the password field into your clipboard.")),
).Build()
}
}),
giu.Button("Paste").OnClick(func(){
giu.Button(s("Paste")).OnClick(func(){
tmp,_ := clipboard.ReadAll()
password = tmp
cPassword = tmp
passwordStrength = zxcvbn.PasswordStrength(password,nil).Score
giu.Update()
}),
giu.Tooltip("Paste your clipboard content into the password fields."),
giu.Tooltip(s("Paste your clipboard content into the password fields.")),
giu.Button("Clear").OnClick(func(){
giu.Button(s("Clear")).OnClick(func(){
password = ""
cPassword = ""
}),
giu.Tooltip("Clear both password fields."),
giu.Tooltip(s("Clear both password fields.")),
giu.Button(passwordStateLabel).OnClick(func(){
if passwordState==giu.InputTextFlagsPassword{
passwordState = giu.InputTextFlagsNone
passwordStateLabel = "Hide"
passwordStateLabel = s("Hide")
}else{
passwordState = giu.InputTextFlagsPassword
passwordStateLabel = "Show"
passwordStateLabel = s("Show")
}
}),
giu.Tooltip("Click to toggle the password state."),
giu.Tooltip(s("Click to toggle the password state.")),
),
giu.Row(
giu.InputText(&password).Size(300/dpi).Flags(passwordState).OnChange(func(){
@ -438,9 +454,9 @@ func startUI(){
}),
giu.Custom(func(){
if keyfile&&mode=="encrypt"{
giu.Button("Clear").OnClick(func(){
giu.Button(s("Clear")).OnClick(func(){
keyfile = false
keyfileLabel = "Use keyfile(s)"
keyfileLabel = s("Keyfile")
keyfilePath = ""
}).Build()
}
@ -451,7 +467,7 @@ func startUI(){
// Prompt to confirm password
giu.Custom(func(){
if mode!="decrypt"{
giu.Label("Confirm password:").Build()
giu.Label(s("Confirm password:")).Build()
giu.Row(
giu.InputText(&cPassword).Size(300/dpi).Flags(passwordState),
giu.Custom(func(){
@ -479,42 +495,42 @@ func startUI(){
}),
// Optional metadata
giu.Label(metadataPrompt),
giu.Label(s(metadataPrompt)),
giu.InputText(&metadata).Size(-0.0000001).Flags(metadataState),
giu.Custom(func(){
if mode!=""{
giu.Label("Advanced options:").Build()
giu.Label(s("Advanced options:")).Build()
}
}),
// Advanced options can be enabled with checkboxes
giu.Custom(func(){
if mode=="encrypt"{
giu.Checkbox("Shred temporary files",&shredTemp).Build()
giu.Tooltip("Use this to shred temporary zip archives and volumes used by Picocrypt.").Build()
giu.Checkbox(s("Shred temporary files"),&shredTemp).Build()
giu.Tooltip(s("Use this to shred temporary zip archives and volumes used by Picocrypt.")).Build()
giu.Checkbox("Use fast mode",&fast).OnChange(func(){
giu.Checkbox(s("Use fast mode"),&fast).OnChange(func(){
paranoid = false
}).Build()
giu.Tooltip("Uses BLAKE2b instead of SHA3 with less Argon2; faster, but less secure.").Build()
giu.Tooltip(s("Uses BLAKE2b instead of SHA3 with less Argon2; faster, but less secure.")).Build()
giu.Checkbox("Use paranoid mode",&paranoid).OnChange(func(){
giu.Checkbox(s("Use paranoid mode"),&paranoid).OnChange(func(){
fast = false
}).Build()
giu.Tooltip("Cascades Serpent with XChaCha20 plus high Argon2; highly secure, but slower.").Build()
giu.Tooltip(s("Uses Serpent and high Argon2; highly secure, but slower.")).Build()
giu.Row(
giu.Checkbox("Encode with Reed-Solomon",&reedsolo),
giu.Tooltip("Reed-Solomon can detect and fix corrupted data."),
giu.Checkbox(s("Encode with Reed-Solomon"),&reedsolo),
giu.Tooltip(s("Reed-Solomon can detect and fix corrupted data.")),
giu.Button("?").Size(24,25).OnClick(func(){
browser.OpenURL(rsWikipedia)
}),
).Build()
giu.Row(
giu.Checkbox("Split output into chunks of",&split),
giu.Tooltip("Use this to split the output file into chunks."),
giu.Checkbox(s("Split output into chunks of"),&split),
giu.Tooltip(s("Use this to split the output file into chunks.")),
giu.InputText(&splitSize).Size(50).Flags(giu.InputTextFlagsCharsDecimal).OnChange(func(){
if splitSize==""{
split = false
@ -527,15 +543,15 @@ func startUI(){
giu.Dummy(0,1).Build()
}else if mode=="decrypt"{
giu.Checkbox("Keep decrypted output even if it's corrupted or modified",&keep).Build()
giu.Tooltip("Tells Picocrypt to always keep decrypted outputs.").Build()
giu.Checkbox(s("Keep decrypted output even if it's corrupted or modified"),&keep).Build()
giu.Tooltip(s("Tells Picocrypt to always keep decrypted outputs.")).Build()
giu.Checkbox("Delete the input file(s) after decryption",&deleteEncrypted).Build()
giu.Tooltip("Removes the encrypted Picocrypt volume (and chunks).").Build()
giu.Checkbox(s("Delete the input file(s) after decryption"),&deleteEncrypted).Build()
giu.Tooltip(s("Removes the encrypted Picocrypt volume (and chunks).")).Build()
giu.Dummy(0,112).Build()
}else{
giu.Dummy(0,67).Build()
giu.Label(" No files selected yet.").Build()
giu.Label(s(" No files selected yet.")).Build()
giu.Dummy(0,68).Build()
}
}),
@ -543,12 +559,12 @@ func startUI(){
// Start button
giu.Button("Start").Size(-0.0000001,35).OnClick(func(){
if mode=="encrypt"&&password!=cPassword{
_status = "Passwords don't match."
_status = s("Passwords don't match.")
_status_color = color.RGBA{0xff,0x00,0x00,255}
return
}
if keyfile&&keyfilePath==""{
_status = "Please select a keyfile."
_status = s("Please select a keyfile.")
_status_color = color.RGBA{0xff,0x00,0x00,255}
return
}
@ -584,20 +600,20 @@ func startUI(){
),
// File checksum generator tab
giu.TabItem("Checksum").Layout(
giu.TabItem(s("Checksum")).Layout(
giu.Custom(func(){
if giu.IsItemActive(){
tab = 1
}
}),
giu.Label("Toggle the hashes you would like to generate and drop a file here."),
giu.Label(s("Toggle the hashes you would like to generate and drop a file here.")),
// MD5
giu.Row(
giu.Checkbox("MD5:",&md5_selected),
giu.Dummy(-58,0),
giu.Button("Copy##md5").Size(50,0).OnClick(func(){
giu.Button(s("Copy")+"##md5").Size(50,0).OnClick(func(){
clipboard.WriteAll(cs_md5)
}),
),
@ -609,7 +625,7 @@ func startUI(){
giu.Row(
giu.Checkbox("SHA1:",&sha1_selected),
giu.Dummy(-58,0),
giu.Button("Copy##sha1").Size(50,0).OnClick(func(){
giu.Button(s("Copy")+"##sha1").Size(50,0).OnClick(func(){
clipboard.WriteAll(cs_sha1)
}),
),
@ -621,7 +637,7 @@ func startUI(){
giu.Row(
giu.Checkbox("SHA256:",&sha256_selected),
giu.Dummy(-58,0),
giu.Button("Copy##sha256").Size(50,0).OnClick(func(){
giu.Button(s("Copy")+"##sha256").Size(50,0).OnClick(func(){
clipboard.WriteAll(cs_sha256)
}),
),
@ -633,7 +649,7 @@ func startUI(){
giu.Row(
giu.Checkbox("SHA3-256:",&sha3_256_selected),
giu.Dummy(-58,0),
giu.Button("Copy##sha3_256").Size(50,0).OnClick(func(){
giu.Button(s("Copy")+"##sha3_256").Size(50,0).OnClick(func(){
clipboard.WriteAll(cs_sha3_256)
}),
),
@ -645,7 +661,7 @@ func startUI(){
giu.Row(
giu.Checkbox("BLAKE2b:",&blake2b_selected),
giu.Dummy(-58,0),
giu.Button("Copy##blake2b").Size(50,0).OnClick(func(){
giu.Button(s("Copy")+"##blake2b").Size(50,0).OnClick(func(){
clipboard.WriteAll(cs_blake2b)
}),
),
@ -657,7 +673,7 @@ func startUI(){
giu.Row(
giu.Checkbox("BLAKE2s:",&blake2s_selected),
giu.Dummy(-58,0),
giu.Button("Copy##blake2s").Size(50,0).OnClick(func(){
giu.Button(s("Copy")+"##blake2s").Size(50,0).OnClick(func(){
clipboard.WriteAll(cs_blake2s)
}),
),
@ -666,7 +682,7 @@ func startUI(){
),
// Input entry for validating a checksum
giu.Label("Validate a checksum:"),
giu.Label(s("Validate a checksum:")),
giu.InputText(&cs_validate).Size(-0.0000001).OnChange(func(){
md5_color = color.RGBA{0x10,0x10,0x10,255}
sha1_color = color.RGBA{0x10,0x10,0x10,255}
@ -694,25 +710,25 @@ func startUI(){
}),
// Progress bar
giu.Label("Progress:"),
giu.Label(s("Progress:")),
giu.ProgressBar(cs_progress).Size(-0.0000001,0),
),
// File shredder tab
giu.TabItem("Shredder").Layout(
giu.TabItem(s("Shredder")).Layout(
giu.Custom(func(){
if giu.IsItemActive(){
tab = 2
}
}),
giu.Label("Drop file(s) and folder(s) here to shred them."),
giu.Label(s("Drop file(s) and folder(s) here to shred them.")),
giu.Custom(func(){
if runtime.GOOS=="darwin"{
giu.Label("Number of passes: Not supported on macOS").Build()
giu.Label(s("Number of passes: Not supported on macOS")).Build()
}else{
giu.Row(
giu.Label("Number of passes:"),
giu.Label(s("Number of passes:")),
giu.InputText(&shredPasses).Size(16).Flags(giu.InputTextFlagsCharsDecimal),
).Build()
}
@ -720,9 +736,9 @@ func startUI(){
giu.Dummy(0,-50),
giu.Row(
giu.ProgressBar(shredProgress).Overlay(shredOverlay).Size(-65,0),
giu.Button("Cancel").Size(58,0).OnClick(func(){
giu.Button(s("Cancel")).Size(58,0).OnClick(func(){
stopShredding = true
shredding = "Ready."
shredding = s("Ready.")
shredProgress = 0
shredOverlay = ""
}),
@ -736,29 +752,29 @@ func startUI(){
),
// About tab
giu.TabItem("About").Layout(
giu.TabItem(s("About")).Layout(
giu.Custom(func(){
if giu.IsItemActive(){
tab = 3
}
}),
giu.Label("Picocrypt "+version+", created by Evan Su (https://evansu.cc)."),
giu.Label("Released under a GNU GPL v3 License."),
giu.Label("A warm thank you to all the people listed below."),
giu.Label("Patrons:"),
giu.Label(fmt.Sprintf(s("Picocrypt %s, created by Evan Su (https://evansu.cc/)."),version)),
giu.Label(s("Released under a GNU GPL v3 License.")),
giu.Label(s("A warm thank you to all the people listed below.")),
giu.Label(s("Patrons:")),
giu.Label(" - Frederick Doe"),
giu.Label("Donators:"),
giu.Label(s("Donators:")),
giu.Label(" - jp26"),
giu.Label(" - W.Graham"),
giu.Label(" - N. Chin"),
giu.Label(" - Manjot"),
giu.Label(" - Phil P."),
giu.Label(" - E. Zahard"),
giu.Label("Translators"),
giu.Label(s("Translators:")),
giu.Label(" - umitseyhan75 (Turkish)"),
giu.Label(" - digitalblossom (German)"),
giu.Label(" - maguszeal (Brazilian Portuguese)"),
giu.Label("Other"),
giu.Label(s("Other:")),
giu.Label(" - Fuderal for setting up Picocrypt's Discord server"),
giu.Label(" - u/greenreddits for constant feedback and support"),
giu.Label(" - u/Tall_Escape for helping me test Picocrypt"),
@ -771,7 +787,7 @@ func startUI(){
// Handle files dropped into Picocrypt by user
func onDrop(names []string){
_status = "Ready."
_status = s("Ready.")
recombine = false
if tab==0{
// Clear variables
@ -784,7 +800,7 @@ func onDrop(names []string){
resetUI()
// Hide the ".pcv" label
orLabel = "or"
orLabel = s("or")
outputWidth = 370
// There's only one dropped item
@ -795,13 +811,13 @@ func onDrop(names []string){
if stat.IsDir(){
mode = "encrypt"
folders++
inputLabel = "1 folder selected."
inputLabel = s("1 folder selected.")
// Add the folder
onlyFolders = append(onlyFolders,names[0])
// Set 'outputEntry' to 'Encrypted'
outputEntry = filepath.Join(filepath.Dir(names[0]),"Encrypted")
outputEntry = filepath.Join(filepath.Dir(names[0]),s("Encrypted"))
// Show the ".zip.pcv" file extension
orLabel = ".zip.pcv or"
@ -823,12 +839,12 @@ func onDrop(names []string){
if strings.HasSuffix(names[0],".pcv")||isSplit{
var err error
mode = "decrypt"
inputLabel = name+" (will decrypt)"
metadataPrompt = "Metadata (read-only):"
inputLabel = name+s(" (will decrypt)")
metadataPrompt = s("Metadata (read-only):")
metadataState = giu.InputTextFlagsReadOnly
if isSplit{
inputLabel = name+" (will recombine and decrypt)"
inputLabel = name+s(" (will recombine and decrypt)")
ind := strings.Index(names[0],".pcv")
names[0] = names[0][:ind]
outputEntry = names[0]
@ -850,14 +866,14 @@ func onDrop(names []string){
fin.Read(tmp)
if string(tmp[:5])=="v1.13"{
resetUI()
_status = "Please use Picocrypt v1.13 to decrypt this file."
_status = s("Please use Picocrypt v1.13 to decrypt this file.")
_status_color = color.RGBA{0xff,0x00,0x00,255}
fin.Close()
return
}
if valid,_:=regexp.Match(`^v\d\.\d{2}.{10}0?\d+`,tmp);!valid&&!isSplit{
resetUI()
_status = "This doesn't seem to be a Picocrypt volume."
_status = s("This doesn't seem to be a Picocrypt volume.")
_status_color = color.RGBA{0xff,0x00,0x00,255}
fin.Close()
return
@ -871,7 +887,7 @@ func onDrop(names []string){
tmp,_ = rsDecode(rs5,tmp)
if string(tmp)=="v1.14"||string(tmp)=="v1.15"||string(tmp)=="v1.16"{
resetUI()
_status = "Please use Picocrypt v1.16 to decrypt this file."
_status = s("Please use Picocrypt v1.16 to decrypt this file.")
_status_color = color.RGBA{0xff,0x00,0x00,255}
fin.Close()
return
@ -889,33 +905,33 @@ func onDrop(names []string){
for i:=0;i<metadataLength*3;i+=3{
t,err := rsDecode(rs1,tmp[i:i+3])
if err!=nil{
metadata = "Metadata is corrupted."
metadata = s("Metadata is corrupted.")
break
}
metadata += string(t)
}
}else{
metadata = "Metadata is corrupted."
metadata = s("Metadata is corrupted.")
}
flags := make([]byte,15)
fin.Read(flags)
flags,err = rsDecode(rs5,flags)
if err!=nil{
_status = "Input file is corrupt and cannot be decrypted."
_status = s("Input file is corrupt and cannot be decrypted.")
_status_color = color.RGBA{0xff,0x00,0x00,255}
return
}
if flags[2]==1{
keyfile = true
keyfileLabel = "Select keyfile"
keyfileLabel = s("Select keyfile")
}
fin.Close()
}else{
mode = "encrypt"
inputLabel = name+" (will encrypt)"
inputLabel = name+s(" (will encrypt)")
outputEntry = names[0]
// Show the ".pcv" file extension
@ -950,25 +966,25 @@ func onDrop(names []string){
if folders==0{
// If folders==0, then there are multiple files
inputLabel = fmt.Sprintf("%d files selected.",files)
inputLabel = fmt.Sprintf(s("%d files selected."),files)
}else if files==0{
// If files==0, then there are multiple folders
inputLabel = fmt.Sprintf("%d folders selected.",folders)
inputLabel = fmt.Sprintf(s("%d folders selected."),folders)
}else{
// There are multiple files and folders
if files==1&&folders>1{
inputLabel = fmt.Sprintf("1 file and %d folders selected.",folders)
inputLabel = fmt.Sprintf(s("1 file and %d folders selected."),folders)
}else if folders==1&&files>1{
inputLabel = fmt.Sprintf("%d files and 1 folder selected.",files)
inputLabel = fmt.Sprintf(s("%d files and 1 folder selected."),files)
}else if folders==1&&files==1{
inputLabel = "1 file and 1 folder selected."
inputLabel = s("1 file and 1 folder selected.")
}else{
inputLabel = fmt.Sprintf("%d files and %d folders selected.",files,folders)
inputLabel = fmt.Sprintf(s("%d files and %d folders selected."),files,folders)
}
}
// Set 'outputEntry' to 'Encrypted'
outputEntry = filepath.Join(filepath.Dir(names[0]),"Encrypted")
outputEntry = filepath.Join(filepath.Dir(names[0]),s("Encrypted"))
}
// If there are folders that were dropped, recusively add all files into 'allFiles'
@ -996,7 +1012,7 @@ func onDrop(names []string){
// Start encryption/decryption
func work(){
// Set some variables
status = "Starting..."
status = s("Starting...")
working = true
padded := false
var salt []byte
@ -1012,7 +1028,7 @@ func work(){
// Set the output file based on mode
if mode=="encrypt"{
status = "Combining files..."
status = s("Combining files...")
// "Tar" files into a zip archive with a compression level of 0 (store)
if len(allFiles)>1||len(onlyFolders)>0{
@ -1033,7 +1049,7 @@ func work(){
w.Close()
file.Close()
os.Remove(inputFile)
_status = "Operation cancelled by user."
_status = s("Operation cancelled by user.")
_status_color = color.RGBA{0xff,0xff,0xff,255}
return
}
@ -1066,7 +1082,7 @@ func work(){
}
if recombine{
status = "Recombining file..."
status = s("Recombining file...")
total := 0
if strings.HasSuffix(inputFile,".pcv"){
@ -1114,7 +1130,7 @@ func work(){
// XChaCha20's max message size is 256 GiB
if total>256*1073741824{
_status = "Total size is larger than 256 GiB, XChaCha20's limit."
_status = s("Total size is larger than 256 GiB, XChaCha20's limit.")
_status_color = color.RGBA{0xff,0x00,0x00,255}
return
}
@ -1125,7 +1141,7 @@ func work(){
// If encrypting, generate values; If decrypting, read values from file
if mode=="encrypt"{
status = "Generating values..."
status = s("Generating values...")
giu.Update()
fout,_ = os.OpenFile(
outputFile,
@ -1215,7 +1231,7 @@ func work(){
var err9 error
var err10 error
status = "Reading values..."
status = s("Reading values...")
giu.Update()
version := make([]byte,15)
fin.Read(version)
@ -1270,7 +1286,7 @@ func work(){
if keep{
kept = true
}else{
_status = "The header is corrupt and the input file cannot be decrypted."
_status = s("The header is corrupt and the input file cannot be decrypted.")
_status_color = color.RGBA{0xff,0x00,0x00,255}
fin.Close()
return
@ -1278,7 +1294,7 @@ func work(){
}
}
status = "Deriving key..."
status = s("Deriving key...")
progress = 0
progressInfo = ""
giu.Update()
@ -1315,7 +1331,7 @@ func work(){
}
if !working{
_status = "Operation cancelled by user."
_status = s("Operation cancelled by user.")
_status_color = color.RGBA{0xff,0xff,0xff,255}
fin.Close()
fout.Close()
@ -1370,9 +1386,9 @@ func work(){
}else{
fin.Close()
if !keyCorrect{
_status = "The provided password is incorrect."
_status = s("The provided password is incorrect.")
}else{
_status = "The provided keyfile is incorrect."
_status = s("The provided keyfile is incorrect.")
}
_status_color = color.RGBA{0xff,0x00,0x00,255}
key = nil
@ -1421,7 +1437,7 @@ func work(){
for{
if !working{
_status = "Operation cancelled by user."
_status = s("Operation cancelled by user.")
_status_color = color.RGBA{0xff,0xff,0xff,255}
fin.Close()
fout.Close()
@ -1491,7 +1507,7 @@ func work(){
if keep{
kept = true
}else{
_status = "The input file is too corrupted to decrypt."
_status = s("The input file is too corrupted to decrypt.")
_status_color = color.RGBA{0xff,0x00,0x00,255}
fin.Close()
fout.Close()
@ -1513,7 +1529,7 @@ func work(){
if keep{
kept = true
}else{
_status = "The input file is too corrupted to decrypt."
_status = s("The input file is too corrupted to decrypt.")
_status_color = color.RGBA{0xff,0x00,0x00,255}
fin.Close()
fout.Close()
@ -1529,7 +1545,7 @@ func work(){
if keep{
kept = true
}else{
_status = "The input file is too corrupted to decrypt."
_status = s("The input file is too corrupted to decrypt.")
_status_color = color.RGBA{0xff,0x00,0x00,255}
fin.Close()
fout.Close()
@ -1570,7 +1586,7 @@ func work(){
}
progressInfo = fmt.Sprintf("%.2f%%",progress*100)
status = fmt.Sprintf("Working at %.2f MB/s (ETA: %s)",speed,humanize(eta))
status = fmt.Sprintf(s("Working at %.2f MB/s (ETA: %s)"),speed,humanize(eta))
giu.Update()
}
@ -1600,7 +1616,7 @@ func work(){
// Split files into chunks
if split{
var splitted []string
status = "Splitting file..."
status = s("Splitting file...")
stat,_ := os.Stat(outputFile)
size := stat.Size()
finished := 0
@ -1629,7 +1645,7 @@ func work(){
if !working{
fin.Close()
fout.Close()
_status = "Operation cancelled by user."
_status = s("Operation cancelled by user.")
_status_color = color.RGBA{0xff,0xff,0xff,255}
// If user cancels, remove the unfinished files
@ -1660,7 +1676,7 @@ func work(){
fin.Close()
if shredTemp{
progressInfo = ""
status = "Shredding temporary files..."
status = s("Shredding temporary files...")
shred([]string{outputFile}[:],false)
}else{
os.Remove(outputFile)
@ -1676,7 +1692,7 @@ func work(){
if len(allFiles)>1||len(onlyFolders)>0{
if shredTemp{
progressInfo = ""
status = "Shredding temporary files..."
status = s("Shredding temporary files...")
giu.Update()
shred([]string{outputEntry+".zip"}[:],false)
}else{
@ -1704,10 +1720,10 @@ func work(){
// If user chose to keep a corrupted/modified file, let them know
if kept{
_status = "The input file is corrupted and/or modified. Please be careful."
_status = s("The input file is corrupted and/or modified. Please be careful.")
_status_color = color.RGBA{0xff,0xff,0x00,255}
}else{
_status = "Completed."
_status = s("Completed.")
_status_color = color.RGBA{0x00,0xff,0x00,255}
}
@ -1715,12 +1731,12 @@ func work(){
working = false
kept = false
key = nil
status = "Ready."
status = s("Ready.")
}
// This function is run if an issue occurs during decryption
func broken(){
_status = "The input file is either corrupted or intentionally modified."
_status = s("The input file is either corrupted or intentionally modified.")
_status_color = color.RGBA{0xff,0x00,0x00,255}
if recombine{
os.Remove(inputFile)
@ -1749,22 +1765,22 @@ func generateChecksums(file string){
cs_validate = ""
if md5_selected{
cs_md5 = "Calculating..."
cs_md5 = s("Calculating...")
}
if sha1_selected{
cs_sha1 = "Calculating..."
cs_sha1 = s("Calculating...")
}
if sha256_selected{
cs_sha256 = "Calculating..."
cs_sha256 = s("Calculating...")
}
if sha3_256_selected{
cs_sha3_256 = "Calculating..."
cs_sha3_256 = s("Calculating...")
}
if blake2b_selected{
cs_blake2b = "Calculating..."
cs_blake2b = s("Calculating...")
}
if blake2s_selected{
cs_blake2s = "Calculating..."
cs_blake2s = s("Calculating...")
}
// Create the checksum objects
@ -1842,7 +1858,7 @@ func shred(names []string,separate bool){
// 'separate' is true if this function is being called from the encryption/decryption tab
if separate{
shredOverlay = "Shredding..."
shredOverlay = s("Shredding...")
}
// Walk through directories to get the total number of files for statistics
@ -1995,7 +2011,7 @@ func shred(names []string,separate bool){
}
// Clear UI state
shredding = "Completed."
shredding = s("Completed.")
shredProgress = 0
shredOverlay = ""
}
@ -2015,17 +2031,17 @@ func shredUpdate(separate bool){
// Reset the UI to a clean state with nothing selected or checked
func resetUI(){
mode = ""
inputLabel = "Drag and drop file(s) and folder(s) into this window."
inputLabel = s("Drag and drop file(s) and folder(s) into this window.")
outputEntry = ""
orLabel = "or"
orLabel = s("or")
outputWidth = 370
password = ""
cPassword = ""
keyfileLabel = "Use a keyfile"
keyfileLabel = s("Use a keyfile")
keyfilePath = ""
keyfile = false
metadata = ""
metadataPrompt = "Metadata (optional):"
metadataPrompt = s("Metadata (optional):")
metadataState = giu.InputTextFlagsNone
shredTemp = false
keep = false
@ -2037,7 +2053,7 @@ func resetUI(){
paranoid = false
progress = 0
progressInfo = ""
_status = "Ready."
_status = s("Ready.")
_status_color = color.RGBA{0xff,0xff,0xff,255}
giu.Update()
}
@ -2125,7 +2141,56 @@ func genPassword() string{
return string(tmp)
}
func s(term string) string{
for _,i := range locales{
if i.iso==selectedLocale{
for _,j := range locales{
if j.iso=="en"{
for k,l := range j.data{
if l==term{
return i.data[k]
}
}
}
}
}
}
return term
}
func main(){
// Parse locales
var obj map[string]json.RawMessage
json.Unmarshal(localeBytes,&obj)
for i := range obj{
var tmp []string
json.Unmarshal(obj[i],&tmp)
locales = append(locales,locale{
iso:i,
data:tmp,
})
}
// Check system locale
for _,i := range locales{
tmp,err := jibber_jabber.DetectIETF()
if err==nil{
if strings.HasPrefix(tmp,i.iso){
selectedLocale = i.iso
}
}
}
inputLabel = s("Drag and drop file(s) and folder(s) into this window.")
orLabel = s("or")
status = s("Ready.")
_status = s("Ready.")
shredding = s("Ready.")
passwordStateLabel = s("Show")
keyfileLabel = s("Keyfile")
metadataPrompt = s("Metadata (optional):")
// Create a temporary file to store sdelete64.exe
sdelete64,_ := os.CreateTemp("","sdelete64.*.exe")
sdelete64path = sdelete64.Name()
@ -2143,7 +2208,7 @@ func main(){
v.Body.Close()
if err==nil{
if string(body[:5])!=version{
_status = "A newer version is available."
_status = s("A newer version is available.")
_status_color = color.RGBA{0,255,0,255}
}
}
@ -2164,7 +2229,7 @@ func main(){
window.SetDropCallback(onDrop)
window.SetCloseCallback(func() bool{
// Disable closing window if a Picocrypt is working to prevent temporary files
if working||(shredding!="Ready."&&shredding!="Completed."){
if working||(shredding!=s("Ready.")&&shredding!=s("Completed.")){
return false
}
return true