Port core package

This commit is contained in:
2026-02-01 13:09:27 -05:00
parent cefdb30193
commit a58d8d407a
7 changed files with 172 additions and 18 deletions
+10
View File
@@ -42,6 +42,16 @@ func getCPascalStringArrayFromStringSlice(goSlice []string) C.PascalStringArray
return C.PascalStringArray{data: cArrPtr, len: C.int(len(goSlice))} return C.PascalStringArray{data: cArrPtr, len: C.int(len(goSlice))}
} }
// getStringSliceFromCPascalStringArray converts a C.PascalStringArray to a go slice.
func getStringSliceFromCPascalStringArray(pascalStringArray C.PascalStringArray) []string {
var goSlice []string
cArr := (*[1 << 30]C.PascalString)(unsafe.Pointer(pascalStringArray.data))[:pascalStringArray.len:pascalStringArray.len]
for i := 0; i < int(pascalStringArray.len); i++ {
goSlice = append(goSlice, C.GoStringN(cArr[i].data, cArr[i].len))
}
return goSlice
}
// GetPascalStringFromCString is a helper meant to be used from C. // GetPascalStringFromCString is a helper meant to be used from C.
// //
//export GetPascalStringFromCString //export GetPascalStringFromCString
+11 -11
View File
@@ -78,16 +78,16 @@ int main() {
- [X] config - [X] config
- [X] Write(cfg *CfgT, appendMode bool) error - [X] Write(cfg *CfgT, appendMode bool) error
- [X] Load() (*CfgT, error) - [X] Load() (*CfgT, error)
- [ ] core - [X] core
- [ ] EntryAddPrecheck(realPath string) (uint8, error) - [X] EntryAddPrecheck(realPath string) (uint8, error)
- [ ] EntryIsNotEmpty(entryData []string) bool - [X] EntryIsNotEmpty(entryData []string) bool
- [ ] EntryRefresh(oldRCWPassword, newRCWPassword []byte, removeOldDir bool) error - [X] EntryRefresh(oldRCWPassword, newRCWPassword []byte, removeOldDir bool) error
- [ ] GenTOTP(secret string, time time.Time) (string, error) - [X] GenTOTP(secret string, time time.Time) (string, error)
- [ ] GetOldEntryData(realPath string, field int, rcwPassword []byte) ([]string, error) - [X] GetOldEntryData(realPath string, field int, rcwPassword []byte) ([]string, error)
- [ ] LibmuttonInit(inputCB func(prompt string) string, rcwPassword []byte, ...) error - [X] LibmuttonInit(inputCB func(prompt string) string, rcwPassword []byte, ...) error
- [ ] RCWSanityCheckGen(password []byte) error - [X] RCWSanityCheckGen(password []byte) error
- [ ] VerifyEntries(rcwPassword []byte) error - [X] VerifyEntries(rcwPassword []byte) error
- [ ] WriteEntry(realPath string, decSlice []string, passwordIsNew bool, rcwPassword []byte) error - [X] WriteEntry(realPath string, decSlice []string, passwordIsNew bool, rcwPassword []byte) error
- [X] crypt - [X] crypt
- [X] ~~VAR: RetryPassword bool~~ (RCWD not supported) - [X] ~~VAR: RetryPassword bool~~ (RCWD not supported)
- [X] DecryptFileToSlice(realPath string) ([]string, error) - [X] DecryptFileToSlice(realPath string) ([]string, error)
@@ -102,7 +102,7 @@ int main() {
- [X] GetRealPath(vanityPath string) string - [X] GetRealPath(vanityPath string) string
- [X] ~~GetSysProcAttr() *syscall.SysProcAttr~~ (not for use outside of libmutton) - [X] ~~GetSysProcAttr() *syscall.SysProcAttr~~ (not for use outside of libmutton)
- [X] GetVanityPath(realPath string) string - [X] GetVanityPath(realPath string) string
- [ ] syncclient - [X] syncclient
- [X] AddFolderRemote(vanityPath string) error - [X] AddFolderRemote(vanityPath string) error
- [X] GenDeviceID(oldDeviceID, prefix string) (string, string, bool, error) - [X] GenDeviceID(oldDeviceID, prefix string) (string, string, bool, error)
- [X] ~~GetSSHClient() (*ssh.Client, bool, *bool, *string, *string, error)~~ (not for use outside of libmutton) - [X] ~~GetSSHClient() (*ssh.Client, bool, *bool, *string, *string, error)~~ (not for use outside of libmutton)
+1 -1
View File
@@ -9,7 +9,7 @@ import (
// ClearProcess clears the clipboard in 30 seconds if its contents still match assignedContents. // ClearProcess clears the clipboard in 30 seconds if its contents still match assignedContents.
// If assignedContents is an empty string, the clipboard will clear immediately and unconditionally. // If assignedContents is an empty string, the clipboard will clear immediately and unconditionally.
// // Returns:
// r0: err // r0: err
// //
//export ClearProcess //export ClearProcess
+2
View File
@@ -8,6 +8,7 @@ import (
) )
// LoadOfficialCfg returns the currently set (libmutton official) values in the libmutton config file. // LoadOfficialCfg returns the currently set (libmutton official) values in the libmutton config file.
// Returns:
// r0: err // r0: err
// //
// r1: OfflineMode (bool) // r1: OfflineMode (bool)
@@ -38,6 +39,7 @@ func LoadOfficialCfg() (*C.char, bool, C.PascalString, C.PascalString, C.PascalS
} }
// WriteOfficialCfg writes the provided (libmutton official) values to the libmutton config file. // WriteOfficialCfg writes the provided (libmutton official) values to the libmutton config file.
// Returns:
// r0: err // r0: err
// //
//export WriteOfficialCfg //export WriteOfficialCfg
+142
View File
@@ -0,0 +1,142 @@
package main
// #include <stdlib.h>
// #include "types.h"
import "C"
import (
"strings"
"time"
"github.com/rwinkhart/libmutton/core"
)
// EntryAddPrecheck returns:
// r0: err
//
// r1: status
//
//export EntryAddPrecheck
func EntryAddPrecheck(realPath C.PascalString) (*C.char, uint8) {
status, err := core.EntryAddPrecheck(C.GoStringN(realPath.data, realPath.len))
if err != nil {
return C.CString(err.Error()), status
}
return nil, status
}
// EntryIsNotEmpty returns:
// r0: notEmpty
//
//export EntryIsNotEmpty
func EntryIsNotEmpty(entryData C.PascalStringArray) bool {
notEmpty := core.EntryIsNotEmpty(getStringSliceFromCPascalStringArray(entryData))
return notEmpty
}
// EntryRefresh returns:
// r0: err
//
//export EntryRefresh
func EntryRefresh(oldRCWPassword, newRCWPassword C.PascalString, removeOldDir bool) *C.char {
err := core.EntryRefresh([]byte(C.GoStringN(oldRCWPassword.data, oldRCWPassword.len)), []byte(C.GoStringN(newRCWPassword.data, newRCWPassword.len)), removeOldDir)
if err != nil {
return C.CString(err.Error())
}
return nil
}
// GenTOTP returns:
// r0: err
//
// r1: token
//
//export GenTOTP
func GenTOTP(secret C.PascalString, unixTimestamp int64) (*C.char, C.PascalString) {
token, err := core.GenTOTP(C.GoStringN(secret.data, secret.len), time.Unix(unixTimestamp, 0))
if err != nil {
return C.CString(err.Error()), C.PascalString{data: nil, len: -1}
}
return nil, getPascalString(token)
}
// GetOldEntryData returns:
// r0: err
//
// r1: lines
//
//export GetOldEntryData
func GetOldEntryData(realPath C.PascalString, field int, rcwPassword C.PascalString) (*C.char, C.PascalStringArray) {
lines, err := core.GetOldEntryData(C.GoStringN(realPath.data, realPath.len), field, []byte(C.GoStringN(rcwPassword.data, rcwPassword.len)))
if err != nil {
return C.CString(err.Error()), C.PascalStringArray{}
}
return nil, getCPascalStringArrayFromStringSlice(lines)
}
// LibmuttonInit is a partial implementation that does not allow for client-specific config.
// Returns:
// r0: err
//
// Special requirement:
// An array of ordered responses to inputCB questions.
//
//export LibmuttonInit
func LibmuttonInit(inputCBResponses C.PascalStringArray, rcwPassword C.PascalString, appendMode bool, forceOfflineMode bool, deviceIDPrefix C.PascalString) *C.char {
inputCBRespSlice := getStringSliceFromCPascalStringArray(inputCBResponses)
supplyInputForInit := func(prompt string) string {
if strings.HasPrefix(prompt, "Configure SSH settings (for synchronization)? (Y/n)") {
return inputCBRespSlice[0]
} else if strings.HasPrefix(prompt, "SSH private identity file path (falls back to") {
return inputCBRespSlice[1]
} else if strings.HasPrefix(prompt, "Is the identity file password-protected? (y/N)") {
return inputCBRespSlice[2]
} else if strings.HasPrefix(prompt, "Remote SSH username:") {
return inputCBRespSlice[3]
} else if strings.HasPrefix(prompt, "Remote SSH IP/domain:") {
return inputCBRespSlice[4]
} else if strings.HasPrefix(prompt, "Remote SSH port:") {
return inputCBRespSlice[5]
}
return ""
}
if err := core.LibmuttonInit(supplyInputForInit, []byte(C.GoStringN(rcwPassword.data, rcwPassword.len)), appendMode, forceOfflineMode, C.GoStringN(deviceIDPrefix.data, deviceIDPrefix.len), nil); err != nil {
return C.CString(err.Error())
}
return nil
}
// RCWSanityCheckGen returns:
// r0: err
//
//export RCWSanityCheckGen
func RCWSanityCheckGen(password C.PascalString) *C.char {
err := core.RCWSanityCheckGen([]byte(C.GoStringN(password.data, password.len)))
if err != nil {
return C.CString(err.Error())
}
return nil
}
// VerifyEntries returns:
// r0: err
//
//export VerifyEntries
func VerifyEntries(rcwPassword C.PascalString) *C.char {
err := core.VerifyEntries([]byte(C.GoStringN(rcwPassword.data, rcwPassword.len)))
if err != nil {
return C.CString(err.Error())
}
return nil
}
// WriteEntry returns:
// r0: err
//
//export WriteEntry
func WriteEntry(realPath C.PascalString, decSlice C.PascalStringArray, passwordIsNew bool, rcwPassword C.PascalString) *C.char {
if err := core.WriteEntry(C.GoStringN(realPath.data, realPath.len), getStringSliceFromCPascalStringArray(decSlice), passwordIsNew, []byte(C.GoStringN(rcwPassword.data, rcwPassword.len))); err != nil {
return C.CString(err.Error())
}
return nil
}
+2 -2
View File
@@ -3,8 +3,8 @@ module cmutton
go 1.26rc2 go 1.26rc2
require ( require (
github.com/rwinkhart/libmutton v0.4.3-0.20260124190333-b963ccf33e54 github.com/rwinkhart/libmutton v0.4.3-0.20260125215941-ec9c6b506232
github.com/rwinkhart/rcw v0.2.4 github.com/rwinkhart/rcw v0.2.5
) )
require ( require (
+4 -4
View File
@@ -16,12 +16,12 @@ github.com/pquerna/otp v1.5.0 h1:NMMR+WrmaqXU4EzdGJEE1aUUI0AMRzsp96fFFWNPwxs=
github.com/pquerna/otp v1.5.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg= github.com/pquerna/otp v1.5.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
github.com/rwinkhart/go-boilerplate v0.2.2 h1:SVHTAQU+HWFivtUnDBcfrgClJV5ZmHyFS7/uERh7NKU= github.com/rwinkhart/go-boilerplate v0.2.2 h1:SVHTAQU+HWFivtUnDBcfrgClJV5ZmHyFS7/uERh7NKU=
github.com/rwinkhart/go-boilerplate v0.2.2/go.mod h1:/NVRKGslU20E5xU5YOgXzWxA6aa94BMtv5MtHRTb5Ek= github.com/rwinkhart/go-boilerplate v0.2.2/go.mod h1:/NVRKGslU20E5xU5YOgXzWxA6aa94BMtv5MtHRTb5Ek=
github.com/rwinkhart/libmutton v0.4.3-0.20260124190333-b963ccf33e54 h1:04PtrDqnj6NrrhY5Uu21wc/N3n9lio+WCD6+55xbaIo= github.com/rwinkhart/libmutton v0.4.3-0.20260125215941-ec9c6b506232 h1:NzUoqkjBy9u9a3wV+D1DR2DemVpYi0Hxug800ybarZE=
github.com/rwinkhart/libmutton v0.4.3-0.20260124190333-b963ccf33e54/go.mod h1:4/Ry5uDUaWTdNqVR/URhqM6NveB3dFfxCmO+LyisBcQ= github.com/rwinkhart/libmutton v0.4.3-0.20260125215941-ec9c6b506232/go.mod h1:63SCVQaWcg4JiEBxYEtLwAiRxXQvlpyFsmWUxxfdIpU=
github.com/rwinkhart/peercred-mini v0.1.2 h1:4cGWDbv0whvLeVvbUdx84V/9p+2fS+DEXgrA1KxlRFo= github.com/rwinkhart/peercred-mini v0.1.2 h1:4cGWDbv0whvLeVvbUdx84V/9p+2fS+DEXgrA1KxlRFo=
github.com/rwinkhart/peercred-mini v0.1.2/go.mod h1:LLHG7YshHEpbpJJP+Il9nx2dnGj5O3VGE32rWmflj0c= github.com/rwinkhart/peercred-mini v0.1.2/go.mod h1:LLHG7YshHEpbpJJP+Il9nx2dnGj5O3VGE32rWmflj0c=
github.com/rwinkhart/rcw v0.2.4 h1:FrRSsl+ui1WLmDwqjLSROtFPKqSeGLEfF2SPENt4qP0= github.com/rwinkhart/rcw v0.2.5 h1:3GJeii9sDZsZNL+HRkfHrnbgxnaB8a9kejiMIfPXnpE=
github.com/rwinkhart/rcw v0.2.4/go.mod h1:nhW4RAHvEjW2QcOlqEdWqRQOFJLjoOGSPkSRZlMjU3s= github.com/rwinkhart/rcw v0.2.5/go.mod h1:qVw8Yp/SKtsuVZYOzzluVEVkoRJ1G7UEh2aR1CXso/U=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=