Skip to content

Commit

Permalink
feat: Add GUI options to copy/edit Battlefield 2 profile passwords
Browse files Browse the repository at this point in the history
  • Loading branch information
cetteup committed Sep 26, 2022
1 parent cb38f91 commit 4cccd1b
Show file tree
Hide file tree
Showing 3 changed files with 151 additions and 1 deletion.
31 changes: 31 additions & 0 deletions cmd/bf2-conman/internal/actions/actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package actions
import (
"fmt"

"github.com/cetteup/conman/pkg/config"
"github.com/cetteup/conman/pkg/game/bf2"
"github.com/cetteup/conman/pkg/handler"
)
Expand All @@ -26,6 +27,36 @@ func SetDefaultProfile(h *handler.Handler, profileKey string) error {
return h.WriteConfigFile(globalCon)
}

func GetProfilePassword(h *handler.Handler, profileKey string) (string, error) {
profileCon, err := bf2.ReadProfileConfigFile(h, profileKey, bf2.ProfileConfigFileProfileCon)
if err != nil {
return "", err
}

encryptedPassword, err := profileCon.GetValue(bf2.ProfileConKeyPassword)
if err != nil {
return "", err
}

return bf2.DecryptProfileConPassword(encryptedPassword.String())
}

func SetProfilePassword(h *handler.Handler, profileKey string, password string) error {
profileCon, err := bf2.ReadProfileConfigFile(h, profileKey, bf2.ProfileConfigFileProfileCon)
if err != nil {
return err
}

encryptedPassword, err := bf2.EncryptProfileConPassword(password)
if err != nil {
return err
}

profileCon.SetValue(bf2.ProfileConKeyPassword, *config.NewValue(encryptedPassword))

return h.WriteConfigFile(profileCon)
}

func PurgeServerHistory(h *handler.Handler, profileKey string) error {
generalCon, err := bf2.ReadProfileConfigFile(h, profileKey, bf2.ProfileConfigFileGeneralCon)
if err != nil {
Expand Down
56 changes: 55 additions & 1 deletion cmd/bf2-conman/internal/gui/main_window.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (

const (
windowWidth = 300
windowHeight = 328
windowHeight = 395
)

type DropDownItem struct { // Used in the ComboBox dropdown
Expand All @@ -38,6 +38,7 @@ func CreateMainWindow(h *handler.Handler, profiles []game.Profile, defaultProfil

var mw *walk.MainWindow
var profileSelection *walk.ComboBox
var passwordGB *walk.GroupBox

if err := (declarative.MainWindow{
AssignTo: &mw,
Expand Down Expand Up @@ -66,6 +67,14 @@ func CreateMainWindow(h *handler.Handler, profiles []game.Profile, defaultProfil
BindingMember: "Key",
Name: "Select profile",
ToolTipText: "Select profile",
OnCurrentIndexChanged: func() {
// Password actions cannot be used with singleplayer profiles, since those don't have passwords
if profiles[profileSelection.CurrentIndex()].Type == game.ProfileTypeMultiplayer {
passwordGB.SetEnabled(true)
} else {
passwordGB.SetEnabled(false)
}
},
},
declarative.GroupBox{
Title: "Profile actions",
Expand Down Expand Up @@ -105,6 +114,51 @@ func CreateMainWindow(h *handler.Handler, profiles []game.Profile, defaultProfil
}
},
},
declarative.GroupBox{
AssignTo: &passwordGB,
Title: "Password (multiplayer profiles only)",
Name: "Password",
Layout: declarative.HBox{},
MaxSize: declarative.Size{Width: windowWidth, Height: 60},
Children: []declarative.Widget{
declarative.Composite{
Layout: declarative.HBox{},
Children: []declarative.Widget{
declarative.PushButton{
Text: "Copy",
OnClicked: func() {
profile := profiles[profileSelection.CurrentIndex()]
password, err := actions.GetProfilePassword(h, profile.Key)
if err != nil {
walk.MsgBox(mw, "Error", "Failed get profile password\n\nIf the password was encrypted on another Windows installation or with another user, the password cannot be decrypted by design.\n\nYou can provide the password via the password \"Edit\" functionality or by logging in in game.", walk.MsgBoxIconError)
return
}
if err := walk.Clipboard().SetText(password); err != nil {
walk.MsgBox(mw, "Error", "Failed to copy password to clipboard", walk.MsgBoxIconError)
return
}
walk.MsgBox(mw, "Success", "Password copied to clipboard", walk.MsgBoxIconInformation)
},
},
declarative.PushButton{
Text: "Edit",
OnClicked: func() {
profile := profiles[profileSelection.CurrentIndex()]
password, err := actions.GetProfilePassword(h, profile.Key)
if err != nil {
walk.MsgBox(mw, "Error", "Failed get profile password\n\nIf the password was encrypted on another Windows installation or with another user, the password cannot be decrypted by design.\n\nYou can still update the password, but ensure you know the current password before continuing.", walk.MsgBoxIconError)
}
if cmd, err := RunPasswordEditDialog(mw, h, profile, password); err != nil {
walk.MsgBox(mw, "Error", "Failed to set password", walk.MsgBoxIconError)
} else if cmd == walk.DlgCmdOK {
walk.MsgBox(mw, "Success", "Password updated", walk.MsgBoxIconInformation)
}
},
},
},
},
},
},
},
},
declarative.GroupBox{
Expand Down
65 changes: 65 additions & 0 deletions cmd/bf2-conman/internal/gui/password_edit.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package gui

import (
"fmt"

"github.com/cetteup/conman/cmd/bf2-conman/internal/actions"
"github.com/cetteup/conman/pkg/game"
"github.com/cetteup/conman/pkg/handler"
"github.com/lxn/walk"
"github.com/lxn/walk/declarative"
"github.com/lxn/win"
)

func RunPasswordEditDialog(owner walk.Form, h *handler.Handler, profile game.Profile, currentPassword string) (int, error) {
var dialog *walk.Dialog
var passwordTE *walk.TextEdit
var savePB, cancelPB *walk.PushButton

return declarative.Dialog{
AssignTo: &dialog,
Title: fmt.Sprintf("Edit password for %s", profile.Name),
Name: fmt.Sprintf("Edit password for %s", profile.Name),
MinSize: declarative.Size{Width: windowWidth - 20},
FixedSize: true,
Layout: declarative.VBox{},
Icon: owner.Icon(),
DefaultButton: &savePB,
CancelButton: &cancelPB,
Children: []declarative.Widget{
declarative.Label{
Text: "Enter/update password",
TextColor: walk.Color(win.GetSysColor(win.COLOR_CAPTIONTEXT)),
Background: declarative.SolidColorBrush{Color: walk.Color(win.GetSysColor(win.COLOR_BTNFACE))},
},
declarative.TextEdit{
AssignTo: &passwordTE,
Name: "Password",
Text: currentPassword,
},
declarative.Composite{
Layout: declarative.HBox{},
Children: []declarative.Widget{
declarative.HSpacer{},
declarative.PushButton{
AssignTo: &savePB,
Text: "Save",
OnClicked: func() {
if err := actions.SetProfilePassword(h, profile.Key, passwordTE.Text()); err != nil {
return
}
dialog.Accept()
},
},
declarative.PushButton{
AssignTo: &cancelPB,
Text: "Cancel",
OnClicked: func() {
dialog.Cancel()
},
},
},
},
},
}.Run(owner)
}

0 comments on commit 4cccd1b

Please sign in to comment.