Update mautrix-go and make it build without crypto
This commit is contained in:
		
							
								
								
									
										4
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								go.mod
									
									
									
									
									
								
							@@ -23,9 +23,7 @@ require (
 | 
				
			|||||||
	golang.org/x/net v0.0.0-20200602114024-627f9648deb9
 | 
						golang.org/x/net v0.0.0-20200602114024-627f9648deb9
 | 
				
			||||||
	gopkg.in/toast.v1 v1.0.0-20180812000517-0a84660828b2
 | 
						gopkg.in/toast.v1 v1.0.0-20180812000517-0a84660828b2
 | 
				
			||||||
	gopkg.in/yaml.v2 v2.3.0
 | 
						gopkg.in/yaml.v2 v2.3.0
 | 
				
			||||||
	maunium.net/go/mautrix v0.5.5
 | 
						maunium.net/go/mautrix v0.7.0-rc.1
 | 
				
			||||||
	maunium.net/go/mauview v0.1.1
 | 
						maunium.net/go/mauview v0.1.1
 | 
				
			||||||
	maunium.net/go/tcell v0.2.0
 | 
						maunium.net/go/tcell v0.2.0
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					 | 
				
			||||||
replace maunium.net/go/mautrix => github.com/nikofil/mautrix-go v0.5.2-0.20200725175335-dd3f90913c4d
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										2
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								go.sum
									
									
									
									
									
								
							@@ -112,6 +112,8 @@ maunium.net/go/mautrix v0.5.3 h1:Lu4PGZvKZwhXmdDnBdLwmiImNM3jNGwJI9Sk78P+Gys=
 | 
				
			|||||||
maunium.net/go/mautrix v0.5.3/go.mod h1:LnkFnB1yjCbb8V+upoEHDGvI/F38NHSTWYCe2RRJgSY=
 | 
					maunium.net/go/mautrix v0.5.3/go.mod h1:LnkFnB1yjCbb8V+upoEHDGvI/F38NHSTWYCe2RRJgSY=
 | 
				
			||||||
maunium.net/go/mautrix v0.5.5 h1:e0Pql1FdxoNUudx2oXo1gZHMrqIh5MC72cdXEPIrYLA=
 | 
					maunium.net/go/mautrix v0.5.5 h1:e0Pql1FdxoNUudx2oXo1gZHMrqIh5MC72cdXEPIrYLA=
 | 
				
			||||||
maunium.net/go/mautrix v0.5.5/go.mod h1:FLbMANzwqlsX2Fgm7SDe+E4I3wSa4UxJRKqS5wGkCwA=
 | 
					maunium.net/go/mautrix v0.5.5/go.mod h1:FLbMANzwqlsX2Fgm7SDe+E4I3wSa4UxJRKqS5wGkCwA=
 | 
				
			||||||
 | 
					maunium.net/go/mautrix v0.7.0-rc.1 h1:DT7bNR9q+HlFs5Oo9IqmtWPkE4WPKZdRfIWRtlqkXtM=
 | 
				
			||||||
 | 
					maunium.net/go/mautrix v0.7.0-rc.1/go.mod h1:Va/74MijqaS0DQ3aUqxmFO54/PMfr1LVsCOcGRHbYmo=
 | 
				
			||||||
maunium.net/go/mauview v0.1.1 h1:wfTXyPx3LGAGpTskh+UbBv/QItUWnEpaneHmywoYnfY=
 | 
					maunium.net/go/mauview v0.1.1 h1:wfTXyPx3LGAGpTskh+UbBv/QItUWnEpaneHmywoYnfY=
 | 
				
			||||||
maunium.net/go/mauview v0.1.1/go.mod h1:3QBUiuLct9moP1LgDhCGIg0Ovxn38Bd2sGndnUOuj4o=
 | 
					maunium.net/go/mauview v0.1.1/go.mod h1:3QBUiuLct9moP1LgDhCGIg0Ovxn38Bd2sGndnUOuj4o=
 | 
				
			||||||
maunium.net/go/tcell v0.2.0 h1:1Q0kN3wCOGAIGu1r3QHADsjSUOPDylKREvCv3EzJpVg=
 | 
					maunium.net/go/tcell v0.2.0 h1:1Q0kN3wCOGAIGu1r3QHADsjSUOPDylKREvCv3EzJpVg=
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										207
									
								
								ui/commands.go
									
									
									
									
									
								
							
							
						
						
									
										207
									
								
								ui/commands.go
									
									
									
									
									
								
							@@ -37,7 +37,6 @@ import (
 | 
				
			|||||||
	"github.com/russross/blackfriday/v2"
 | 
						"github.com/russross/blackfriday/v2"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"maunium.net/go/mautrix"
 | 
						"maunium.net/go/mautrix"
 | 
				
			||||||
	"maunium.net/go/mautrix/crypto"
 | 
					 | 
				
			||||||
	"maunium.net/go/mautrix/event"
 | 
						"maunium.net/go/mautrix/event"
 | 
				
			||||||
	"maunium.net/go/mautrix/format"
 | 
						"maunium.net/go/mautrix/format"
 | 
				
			||||||
	"maunium.net/go/mautrix/id"
 | 
						"maunium.net/go/mautrix/id"
 | 
				
			||||||
@@ -366,212 +365,6 @@ func cmdFingerprint(cmd *Command) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// region TODO these four functions currently use the crypto internals directly. switch to interfaces before releasing
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func autocompleteDeviceUserID(cmd *CommandAutocomplete) (completions []string, newText string) {
 | 
					 | 
				
			||||||
	userCompletions := cmd.Room.AutocompleteUser(cmd.Args[0])
 | 
					 | 
				
			||||||
	if len(userCompletions) == 1 {
 | 
					 | 
				
			||||||
		newText = fmt.Sprintf("/%s %s ", cmd.OrigCommand, userCompletions[0].id)
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		completions = make([]string, len(userCompletions))
 | 
					 | 
				
			||||||
		for i, completion := range userCompletions {
 | 
					 | 
				
			||||||
			completions[i] = completion.id
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func autocompleteDeviceDeviceID(cmd *CommandAutocomplete) (completions []string, newText string) {
 | 
					 | 
				
			||||||
	mach := cmd.Matrix.Crypto().(*crypto.OlmMachine)
 | 
					 | 
				
			||||||
	devices, err := mach.CryptoStore.GetDevices(id.UserID(cmd.Args[0]))
 | 
					 | 
				
			||||||
	if len(devices) == 0 || err != nil {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	var completedDeviceID id.DeviceID
 | 
					 | 
				
			||||||
	if len(cmd.Args) > 1 {
 | 
					 | 
				
			||||||
		existingID := strings.ToUpper(cmd.Args[1])
 | 
					 | 
				
			||||||
		for _, device := range devices {
 | 
					 | 
				
			||||||
			deviceIDStr := string(device.DeviceID)
 | 
					 | 
				
			||||||
			if deviceIDStr == existingID {
 | 
					 | 
				
			||||||
				// We don't want to do any autocompletion if there's already a full device ID there.
 | 
					 | 
				
			||||||
				return []string{}, ""
 | 
					 | 
				
			||||||
			} else if strings.HasPrefix(strings.ToUpper(device.Name), existingID) || strings.HasPrefix(deviceIDStr, existingID) {
 | 
					 | 
				
			||||||
				completedDeviceID = device.DeviceID
 | 
					 | 
				
			||||||
				completions = append(completions, fmt.Sprintf("%s (%s)", device.DeviceID, device.Name))
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		completions = make([]string, len(devices))
 | 
					 | 
				
			||||||
		i := 0
 | 
					 | 
				
			||||||
		for _, device := range devices {
 | 
					 | 
				
			||||||
			completedDeviceID = device.DeviceID
 | 
					 | 
				
			||||||
			completions[i] = fmt.Sprintf("%s (%s)", device.DeviceID, device.Name)
 | 
					 | 
				
			||||||
			i++
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if len(completions) == 1 {
 | 
					 | 
				
			||||||
		newText = fmt.Sprintf("/%s %s %s ", cmd.OrigCommand, cmd.Args[0], completedDeviceID)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func autocompleteDevice(cmd *CommandAutocomplete) ([]string, string) {
 | 
					 | 
				
			||||||
	if len(cmd.Args) == 0 {
 | 
					 | 
				
			||||||
		return []string{}, ""
 | 
					 | 
				
			||||||
	} else if len(cmd.Args) == 1 && !unicode.IsSpace(rune(cmd.RawArgs[len(cmd.RawArgs)-1])) {
 | 
					 | 
				
			||||||
		return autocompleteDeviceUserID(cmd)
 | 
					 | 
				
			||||||
	} else if cmd.Command != "devices" {
 | 
					 | 
				
			||||||
		return autocompleteDeviceDeviceID(cmd)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return []string{}, ""
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func getDevice(cmd *Command) *crypto.DeviceIdentity {
 | 
					 | 
				
			||||||
	if len(cmd.Args) < 2 {
 | 
					 | 
				
			||||||
		cmd.Reply("Usage: /%s <user id> <device id> [fingerprint]", cmd.Command)
 | 
					 | 
				
			||||||
		return nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	mach := cmd.Matrix.Crypto().(*crypto.OlmMachine)
 | 
					 | 
				
			||||||
	device, err := mach.GetOrFetchDevice(id.UserID(cmd.Args[0]), id.DeviceID(cmd.Args[1]))
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		cmd.Reply("Failed to get device: %v", err)
 | 
					 | 
				
			||||||
		return nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return device
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func putDevice(cmd *Command, device *crypto.DeviceIdentity, action string) {
 | 
					 | 
				
			||||||
	mach := cmd.Matrix.Crypto().(*crypto.OlmMachine)
 | 
					 | 
				
			||||||
	err := mach.CryptoStore.PutDevice(device.UserID, device)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		cmd.Reply("Failed to save device: %v", err)
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		cmd.Reply("Successfully %s %s/%s (%s)", action, device.UserID, device.DeviceID, device.Name)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	mach.OnDevicesChanged(device.UserID)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func cmdDevices(cmd *Command) {
 | 
					 | 
				
			||||||
	if len(cmd.Args) == 0 {
 | 
					 | 
				
			||||||
		cmd.Reply("Usage: /devices <user id>")
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	userID := id.UserID(cmd.Args[0])
 | 
					 | 
				
			||||||
	mach := cmd.Matrix.Crypto().(*crypto.OlmMachine)
 | 
					 | 
				
			||||||
	devices, err := mach.CryptoStore.GetDevices(userID)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		cmd.Reply("Failed to get device list: %v", err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if len(devices) == 0 {
 | 
					 | 
				
			||||||
		cmd.Reply("Fetching device list from server...")
 | 
					 | 
				
			||||||
		devices = mach.LoadDevices(userID)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if len(devices) == 0 {
 | 
					 | 
				
			||||||
		cmd.Reply("No devices found for %s", userID)
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	var buf strings.Builder
 | 
					 | 
				
			||||||
	for _, device := range devices {
 | 
					 | 
				
			||||||
		_, _ = fmt.Fprintf(&buf, "%s (%s) - %s\n    Fingerprint: %s\n", device.DeviceID, device.Name, device.Trust.String(), device.Fingerprint())
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	resp := buf.String()
 | 
					 | 
				
			||||||
	cmd.Reply("%s", resp[:len(resp)-1])
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func cmdDevice(cmd *Command) {
 | 
					 | 
				
			||||||
	device := getDevice(cmd)
 | 
					 | 
				
			||||||
	if device == nil {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	deviceType := "Device"
 | 
					 | 
				
			||||||
	if device.Deleted {
 | 
					 | 
				
			||||||
		deviceType = "Deleted device"
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	cmd.Reply("%s %s of %s\nFingerprint: %s\nIdentity key: %s\nDevice name: %s\nTrust state: %s",
 | 
					 | 
				
			||||||
		deviceType, device.DeviceID, device.UserID,
 | 
					 | 
				
			||||||
		device.Fingerprint(), device.IdentityKey,
 | 
					 | 
				
			||||||
		device.Name, device.Trust.String())
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func cmdVerify(cmd *Command) {
 | 
					 | 
				
			||||||
	device := getDevice(cmd)
 | 
					 | 
				
			||||||
	if device == nil {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if device.Trust == crypto.TrustStateVerified {
 | 
					 | 
				
			||||||
		cmd.Reply("That device is already verified")
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if len(cmd.Args) == 2 {
 | 
					 | 
				
			||||||
		mach := cmd.Matrix.Crypto().(*crypto.OlmMachine)
 | 
					 | 
				
			||||||
		mach.DefaultSASTimeout = 120 * time.Second
 | 
					 | 
				
			||||||
		modal := NewVerificationModal(cmd.MainView, device, mach.DefaultSASTimeout)
 | 
					 | 
				
			||||||
		cmd.MainView.ShowModal(modal)
 | 
					 | 
				
			||||||
		err := mach.NewSimpleSASVerificationWith(device, modal)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			cmd.Reply("Failed to start interactive verification: %v", err)
 | 
					 | 
				
			||||||
			return
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		fingerprint := strings.Join(cmd.Args[2:], "")
 | 
					 | 
				
			||||||
		if string(device.SigningKey) != fingerprint {
 | 
					 | 
				
			||||||
			cmd.Reply("Mismatching fingerprint")
 | 
					 | 
				
			||||||
			return
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		action := "verified"
 | 
					 | 
				
			||||||
		if device.Trust == crypto.TrustStateBlacklisted {
 | 
					 | 
				
			||||||
			action = "unblacklisted and verified"
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		device.Trust = crypto.TrustStateVerified
 | 
					 | 
				
			||||||
		putDevice(cmd, device, action)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func cmdUnverify(cmd *Command) {
 | 
					 | 
				
			||||||
	device := getDevice(cmd)
 | 
					 | 
				
			||||||
	if device == nil {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if device.Trust == crypto.TrustStateUnset {
 | 
					 | 
				
			||||||
		cmd.Reply("That device is already not verified")
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	action := "unverified"
 | 
					 | 
				
			||||||
	if device.Trust == crypto.TrustStateBlacklisted {
 | 
					 | 
				
			||||||
		action = "unblacklisted"
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	device.Trust = crypto.TrustStateUnset
 | 
					 | 
				
			||||||
	putDevice(cmd, device, action)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func cmdBlacklist(cmd *Command) {
 | 
					 | 
				
			||||||
	device := getDevice(cmd)
 | 
					 | 
				
			||||||
	if device == nil {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if device.Trust == crypto.TrustStateBlacklisted {
 | 
					 | 
				
			||||||
		cmd.Reply("That device is already blacklisted")
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	action := "blacklisted"
 | 
					 | 
				
			||||||
	if device.Trust == crypto.TrustStateVerified {
 | 
					 | 
				
			||||||
		action = "unverified and blacklisted"
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	device.Trust = crypto.TrustStateBlacklisted
 | 
					 | 
				
			||||||
	putDevice(cmd, device, action)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func cmdResetSession(cmd *Command) {
 | 
					 | 
				
			||||||
	err := cmd.Matrix.Crypto().(*crypto.OlmMachine).CryptoStore.RemoveOutboundGroupSession(cmd.Room.Room.ID)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		cmd.Reply("Failed to remove outbound group session: %v", err)
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		cmd.Reply("Removed outbound group session for this room")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// endregion
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func cmdHeapProfile(cmd *Command) {
 | 
					func cmdHeapProfile(cmd *Command) {
 | 
				
			||||||
	if len(cmd.Args) == 0 || cmd.Args[0] != "nogc" {
 | 
						if len(cmd.Args) == 0 || cmd.Args[0] != "nogc" {
 | 
				
			||||||
		runtime.GC()
 | 
							runtime.GC()
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										231
									
								
								ui/crypto-commands.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										231
									
								
								ui/crypto-commands.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,231 @@
 | 
				
			|||||||
 | 
					// gomuks - A terminal Matrix client written in Go.
 | 
				
			||||||
 | 
					// Copyright (C) 2020 Tulir Asokan
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// This program is free software: you can redistribute it and/or modify
 | 
				
			||||||
 | 
					// it under the terms of the GNU Affero General Public License as published by
 | 
				
			||||||
 | 
					// the Free Software Foundation, either version 3 of the License, or
 | 
				
			||||||
 | 
					// (at your option) any later version.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					// GNU Affero General Public License for more details.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// You should have received a copy of the GNU Affero General Public License
 | 
				
			||||||
 | 
					// along with this program.  If not, see <https://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// +build cgo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package ui
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
						"unicode"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"maunium.net/go/mautrix/crypto"
 | 
				
			||||||
 | 
						"maunium.net/go/mautrix/id"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func autocompleteDeviceUserID(cmd *CommandAutocomplete) (completions []string, newText string) {
 | 
				
			||||||
 | 
						userCompletions := cmd.Room.AutocompleteUser(cmd.Args[0])
 | 
				
			||||||
 | 
						if len(userCompletions) == 1 {
 | 
				
			||||||
 | 
							newText = fmt.Sprintf("/%s %s ", cmd.OrigCommand, userCompletions[0].id)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							completions = make([]string, len(userCompletions))
 | 
				
			||||||
 | 
							for i, completion := range userCompletions {
 | 
				
			||||||
 | 
								completions[i] = completion.id
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func autocompleteDeviceDeviceID(cmd *CommandAutocomplete) (completions []string, newText string) {
 | 
				
			||||||
 | 
						mach := cmd.Matrix.Crypto().(*crypto.OlmMachine)
 | 
				
			||||||
 | 
						devices, err := mach.CryptoStore.GetDevices(id.UserID(cmd.Args[0]))
 | 
				
			||||||
 | 
						if len(devices) == 0 || err != nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						var completedDeviceID id.DeviceID
 | 
				
			||||||
 | 
						if len(cmd.Args) > 1 {
 | 
				
			||||||
 | 
							existingID := strings.ToUpper(cmd.Args[1])
 | 
				
			||||||
 | 
							for _, device := range devices {
 | 
				
			||||||
 | 
								deviceIDStr := string(device.DeviceID)
 | 
				
			||||||
 | 
								if deviceIDStr == existingID {
 | 
				
			||||||
 | 
									// We don't want to do any autocompletion if there's already a full device ID there.
 | 
				
			||||||
 | 
									return []string{}, ""
 | 
				
			||||||
 | 
								} else if strings.HasPrefix(strings.ToUpper(device.Name), existingID) || strings.HasPrefix(deviceIDStr, existingID) {
 | 
				
			||||||
 | 
									completedDeviceID = device.DeviceID
 | 
				
			||||||
 | 
									completions = append(completions, fmt.Sprintf("%s (%s)", device.DeviceID, device.Name))
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							completions = make([]string, len(devices))
 | 
				
			||||||
 | 
							i := 0
 | 
				
			||||||
 | 
							for _, device := range devices {
 | 
				
			||||||
 | 
								completedDeviceID = device.DeviceID
 | 
				
			||||||
 | 
								completions[i] = fmt.Sprintf("%s (%s)", device.DeviceID, device.Name)
 | 
				
			||||||
 | 
								i++
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if len(completions) == 1 {
 | 
				
			||||||
 | 
							newText = fmt.Sprintf("/%s %s %s ", cmd.OrigCommand, cmd.Args[0], completedDeviceID)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func autocompleteDevice(cmd *CommandAutocomplete) ([]string, string) {
 | 
				
			||||||
 | 
						if len(cmd.Args) == 0 {
 | 
				
			||||||
 | 
							return []string{}, ""
 | 
				
			||||||
 | 
						} else if len(cmd.Args) == 1 && !unicode.IsSpace(rune(cmd.RawArgs[len(cmd.RawArgs)-1])) {
 | 
				
			||||||
 | 
							return autocompleteDeviceUserID(cmd)
 | 
				
			||||||
 | 
						} else if cmd.Command != "devices" {
 | 
				
			||||||
 | 
							return autocompleteDeviceDeviceID(cmd)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return []string{}, ""
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func getDevice(cmd *Command) *crypto.DeviceIdentity {
 | 
				
			||||||
 | 
						if len(cmd.Args) < 2 {
 | 
				
			||||||
 | 
							cmd.Reply("Usage: /%s <user id> <device id> [fingerprint]", cmd.Command)
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						mach := cmd.Matrix.Crypto().(*crypto.OlmMachine)
 | 
				
			||||||
 | 
						device, err := mach.GetOrFetchDevice(id.UserID(cmd.Args[0]), id.DeviceID(cmd.Args[1]))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							cmd.Reply("Failed to get device: %v", err)
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return device
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func putDevice(cmd *Command, device *crypto.DeviceIdentity, action string) {
 | 
				
			||||||
 | 
						mach := cmd.Matrix.Crypto().(*crypto.OlmMachine)
 | 
				
			||||||
 | 
						err := mach.CryptoStore.PutDevice(device.UserID, device)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							cmd.Reply("Failed to save device: %v", err)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							cmd.Reply("Successfully %s %s/%s (%s)", action, device.UserID, device.DeviceID, device.Name)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						mach.OnDevicesChanged(device.UserID)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func cmdDevices(cmd *Command) {
 | 
				
			||||||
 | 
						if len(cmd.Args) == 0 {
 | 
				
			||||||
 | 
							cmd.Reply("Usage: /devices <user id>")
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						userID := id.UserID(cmd.Args[0])
 | 
				
			||||||
 | 
						mach := cmd.Matrix.Crypto().(*crypto.OlmMachine)
 | 
				
			||||||
 | 
						devices, err := mach.CryptoStore.GetDevices(userID)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							cmd.Reply("Failed to get device list: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if len(devices) == 0 {
 | 
				
			||||||
 | 
							cmd.Reply("Fetching device list from server...")
 | 
				
			||||||
 | 
							devices = mach.LoadDevices(userID)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if len(devices) == 0 {
 | 
				
			||||||
 | 
							cmd.Reply("No devices found for %s", userID)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						var buf strings.Builder
 | 
				
			||||||
 | 
						for _, device := range devices {
 | 
				
			||||||
 | 
							_, _ = fmt.Fprintf(&buf, "%s (%s) - %s\n    Fingerprint: %s\n", device.DeviceID, device.Name, device.Trust.String(), device.Fingerprint())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						resp := buf.String()
 | 
				
			||||||
 | 
						cmd.Reply("%s", resp[:len(resp)-1])
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func cmdDevice(cmd *Command) {
 | 
				
			||||||
 | 
						device := getDevice(cmd)
 | 
				
			||||||
 | 
						if device == nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						deviceType := "Device"
 | 
				
			||||||
 | 
						if device.Deleted {
 | 
				
			||||||
 | 
							deviceType = "Deleted device"
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						cmd.Reply("%s %s of %s\nFingerprint: %s\nIdentity key: %s\nDevice name: %s\nTrust state: %s",
 | 
				
			||||||
 | 
							deviceType, device.DeviceID, device.UserID,
 | 
				
			||||||
 | 
							device.Fingerprint(), device.IdentityKey,
 | 
				
			||||||
 | 
							device.Name, device.Trust.String())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func cmdVerify(cmd *Command) {
 | 
				
			||||||
 | 
						device := getDevice(cmd)
 | 
				
			||||||
 | 
						if device == nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if device.Trust == crypto.TrustStateVerified {
 | 
				
			||||||
 | 
							cmd.Reply("That device is already verified")
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if len(cmd.Args) == 2 {
 | 
				
			||||||
 | 
							mach := cmd.Matrix.Crypto().(*crypto.OlmMachine)
 | 
				
			||||||
 | 
							mach.DefaultSASTimeout = 120 * time.Second
 | 
				
			||||||
 | 
							modal := NewVerificationModal(cmd.MainView, device, mach.DefaultSASTimeout)
 | 
				
			||||||
 | 
							cmd.MainView.ShowModal(modal)
 | 
				
			||||||
 | 
							_, err := mach.NewSimpleSASVerificationWith(device, modal)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								cmd.Reply("Failed to start interactive verification: %v", err)
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							fingerprint := strings.Join(cmd.Args[2:], "")
 | 
				
			||||||
 | 
							if string(device.SigningKey) != fingerprint {
 | 
				
			||||||
 | 
								cmd.Reply("Mismatching fingerprint")
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							action := "verified"
 | 
				
			||||||
 | 
							if device.Trust == crypto.TrustStateBlacklisted {
 | 
				
			||||||
 | 
								action = "unblacklisted and verified"
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							device.Trust = crypto.TrustStateVerified
 | 
				
			||||||
 | 
							putDevice(cmd, device, action)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func cmdUnverify(cmd *Command) {
 | 
				
			||||||
 | 
						device := getDevice(cmd)
 | 
				
			||||||
 | 
						if device == nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if device.Trust == crypto.TrustStateUnset {
 | 
				
			||||||
 | 
							cmd.Reply("That device is already not verified")
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						action := "unverified"
 | 
				
			||||||
 | 
						if device.Trust == crypto.TrustStateBlacklisted {
 | 
				
			||||||
 | 
							action = "unblacklisted"
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						device.Trust = crypto.TrustStateUnset
 | 
				
			||||||
 | 
						putDevice(cmd, device, action)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func cmdBlacklist(cmd *Command) {
 | 
				
			||||||
 | 
						device := getDevice(cmd)
 | 
				
			||||||
 | 
						if device == nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if device.Trust == crypto.TrustStateBlacklisted {
 | 
				
			||||||
 | 
							cmd.Reply("That device is already blacklisted")
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						action := "blacklisted"
 | 
				
			||||||
 | 
						if device.Trust == crypto.TrustStateVerified {
 | 
				
			||||||
 | 
							action = "unverified and blacklisted"
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						device.Trust = crypto.TrustStateBlacklisted
 | 
				
			||||||
 | 
						putDevice(cmd, device, action)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func cmdResetSession(cmd *Command) {
 | 
				
			||||||
 | 
						err := cmd.Matrix.Crypto().(*crypto.OlmMachine).CryptoStore.RemoveOutboundGroupSession(cmd.Room.Room.ID)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							cmd.Reply("Failed to remove outbound group session: %v", err)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							cmd.Reply("Removed outbound group session for this room")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										36
									
								
								ui/no-crypto-commands.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								ui/no-crypto-commands.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,36 @@
 | 
				
			|||||||
 | 
					// gomuks - A terminal Matrix client written in Go.
 | 
				
			||||||
 | 
					// Copyright (C) 2020 Tulir Asokan
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// This program is free software: you can redistribute it and/or modify
 | 
				
			||||||
 | 
					// it under the terms of the GNU Affero General Public License as published by
 | 
				
			||||||
 | 
					// the Free Software Foundation, either version 3 of the License, or
 | 
				
			||||||
 | 
					// (at your option) any later version.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					// GNU Affero General Public License for more details.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// You should have received a copy of the GNU Affero General Public License
 | 
				
			||||||
 | 
					// along with this program.  If not, see <https://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// +build !cgo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package ui
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func autocompleteDevice(cmd *CommandAutocomplete) ([]string, string) {
 | 
				
			||||||
 | 
						return []string{}, ""
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func cmdNoCrypto(cmd *Command) {
 | 
				
			||||||
 | 
						cmd.Reply("This gomuks was built without encryption support")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						cmdDevices = cmdNoCrypto
 | 
				
			||||||
 | 
						cmdDevice = cmdNoCrypto
 | 
				
			||||||
 | 
						cmdVerify = cmdNoCrypto
 | 
				
			||||||
 | 
						cmdUnverify = cmdNoCrypto
 | 
				
			||||||
 | 
						cmdBlacklist = cmdNoCrypto
 | 
				
			||||||
 | 
						cmdResetSession = cmdNoCrypto
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
@@ -629,8 +629,6 @@ func (view *RoomView) InputTabComplete(text string, cursorOffset int) {
 | 
				
			|||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	debug.Print("Tab completing", cursorOffset, text)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	str := runewidth.Truncate(text, cursorOffset, "")
 | 
						str := runewidth.Truncate(text, cursorOffset, "")
 | 
				
			||||||
	word := findWordToTabComplete(str)
 | 
						word := findWordToTabComplete(str)
 | 
				
			||||||
	startIndex := len(str) - len(word)
 | 
						startIndex := len(str) - len(word)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,6 +14,8 @@
 | 
				
			|||||||
// You should have received a copy of the GNU Affero General Public License
 | 
					// You should have received a copy of the GNU Affero General Public License
 | 
				
			||||||
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
 | 
					// along with this program.  If not, see <https://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// +build cgo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package ui
 | 
					package ui
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
@@ -32,14 +34,17 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
type EmojiView struct {
 | 
					type EmojiView struct {
 | 
				
			||||||
	mauview.SimpleEventHandler
 | 
						mauview.SimpleEventHandler
 | 
				
			||||||
	Numbers *[3]uint
 | 
						Data crypto.SASData
 | 
				
			||||||
	Emojis  *[7]crypto.VerificationEmoji
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (e *EmojiView) Draw(screen mauview.Screen) {
 | 
					func (e *EmojiView) Draw(screen mauview.Screen) {
 | 
				
			||||||
	if e.Emojis != nil {
 | 
						if e.Data == nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						switch e.Data.Type() {
 | 
				
			||||||
 | 
						case event.SASEmoji:
 | 
				
			||||||
		width := 10
 | 
							width := 10
 | 
				
			||||||
		for i, emoji := range e.Emojis {
 | 
							for i, emoji := range e.Data.(crypto.EmojiSASData) {
 | 
				
			||||||
			x := i*width + i
 | 
								x := i*width + i
 | 
				
			||||||
			y := 0
 | 
								y := 0
 | 
				
			||||||
			if i >= 4 {
 | 
								if i >= 4 {
 | 
				
			||||||
@@ -49,9 +54,9 @@ func (e *EmojiView) Draw(screen mauview.Screen) {
 | 
				
			|||||||
			mauview.Print(screen, string(emoji.Emoji), x, y, width, mauview.AlignCenter, tcell.ColorDefault)
 | 
								mauview.Print(screen, string(emoji.Emoji), x, y, width, mauview.AlignCenter, tcell.ColorDefault)
 | 
				
			||||||
			mauview.Print(screen, emoji.Description, x, y+1, width, mauview.AlignCenter, tcell.ColorDefault)
 | 
								mauview.Print(screen, emoji.Description, x, y+1, width, mauview.AlignCenter, tcell.ColorDefault)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else if e.Numbers != nil {
 | 
						case event.SASDecimal:
 | 
				
			||||||
		maxWidth := 43
 | 
							maxWidth := 43
 | 
				
			||||||
		for i, number := range e.Numbers {
 | 
							for i, number := range e.Data.(crypto.DecimalSASData) {
 | 
				
			||||||
			mauview.Print(screen, strconv.FormatUint(uint64(number), 10), 0, i, maxWidth, mauview.AlignCenter, tcell.ColorDefault)
 | 
								mauview.Print(screen, strconv.FormatUint(uint64(number), 10), 0, i, maxWidth, mauview.AlignCenter, tcell.ColorDefault)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -69,6 +74,8 @@ type VerificationModal struct {
 | 
				
			|||||||
	emojiText  *EmojiView
 | 
						emojiText  *EmojiView
 | 
				
			||||||
	inputBar   *mauview.InputField
 | 
						inputBar   *mauview.InputField
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						progress    int
 | 
				
			||||||
 | 
						progressMax int
 | 
				
			||||||
	stopWaiting chan struct{}
 | 
						stopWaiting chan struct{}
 | 
				
			||||||
	confirmChan chan bool
 | 
						confirmChan chan bool
 | 
				
			||||||
	done        bool
 | 
						done        bool
 | 
				
			||||||
@@ -85,14 +92,15 @@ func NewVerificationModal(mainView *MainView, device *crypto.DeviceIdentity, tim
 | 
				
			|||||||
		done:        false,
 | 
							done:        false,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	progress := int(timeout.Seconds())
 | 
						vm.progressMax = int(timeout.Seconds())
 | 
				
			||||||
 | 
						vm.progress = vm.progressMax
 | 
				
			||||||
	vm.waitingBar = mauview.NewProgressBar().
 | 
						vm.waitingBar = mauview.NewProgressBar().
 | 
				
			||||||
		SetMax(progress).
 | 
							SetMax(vm.progressMax).
 | 
				
			||||||
		SetProgress(progress).
 | 
							SetProgress(vm.progress).
 | 
				
			||||||
		SetIndeterminate(false)
 | 
							SetIndeterminate(false)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	vm.infoText = mauview.NewTextView()
 | 
						vm.infoText = mauview.NewTextView()
 | 
				
			||||||
	vm.infoText.SetText(fmt.Sprintf("Waiting for %s to accept", device.UserID))
 | 
						vm.infoText.SetText(fmt.Sprintf("Waiting for %s\nto accept", device.UserID))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	vm.emojiText = &EmojiView{}
 | 
						vm.emojiText = &EmojiView{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -113,59 +121,58 @@ func NewVerificationModal(mainView *MainView, device *crypto.DeviceIdentity, tim
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	vm.Component = mauview.Center(vm.container, 45, 12).SetAlwaysFocusChild(true)
 | 
						vm.Component = mauview.Center(vm.container, 45, 12).SetAlwaysFocusChild(true)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	go vm.decrementWaitingBar(progress)
 | 
						go vm.decrementWaitingBar()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return vm
 | 
						return vm
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (vm *VerificationModal) decrementWaitingBar(progress int) {
 | 
					func (vm *VerificationModal) decrementWaitingBar() {
 | 
				
			||||||
	for {
 | 
						for {
 | 
				
			||||||
		select {
 | 
							select {
 | 
				
			||||||
		case <-time.Tick(time.Second):
 | 
							case <-time.Tick(time.Second):
 | 
				
			||||||
			if progress <= 0 {
 | 
								if vm.progress <= 0 {
 | 
				
			||||||
 | 
									vm.waitingBar.SetIndeterminate(true)
 | 
				
			||||||
 | 
									vm.parent.parent.app.SetRedrawTicker(100 * time.Millisecond)
 | 
				
			||||||
				return
 | 
									return
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			progress--
 | 
								vm.progress--
 | 
				
			||||||
			vm.waitingBar.SetProgress(progress)
 | 
								vm.waitingBar.SetProgress(vm.progress)
 | 
				
			||||||
			vm.parent.parent.Render()
 | 
								vm.parent.parent.Render()
 | 
				
			||||||
		case <-vm.stopWaiting:
 | 
							case <-vm.stopWaiting:
 | 
				
			||||||
			vm.waitingBar.SetIndeterminate(true)
 | 
					 | 
				
			||||||
			vm.parent.parent.app.SetRedrawTicker(100 * time.Millisecond)
 | 
					 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (vm *VerificationModal) VerifyEmojisMatch(emojis [7]crypto.VerificationEmoji) bool {
 | 
					func (vm *VerificationModal) VerificationMethods() []crypto.VerificationMethod {
 | 
				
			||||||
	vm.infoText.SetText("Check if the other device is showing the\nsame emojis as below, then type \"yes\" to\naccept, or \"no\" to reject")
 | 
						return []crypto.VerificationMethod{crypto.VerificationMethodEmoji{}, crypto.VerificationMethodDecimal{}}
 | 
				
			||||||
	vm.inputBar.
 | 
					 | 
				
			||||||
		SetTextColor(tcell.ColorWhite).
 | 
					 | 
				
			||||||
		SetBackgroundColor(tcell.ColorDarkCyan).
 | 
					 | 
				
			||||||
		SetPlaceholder("Type \"yes\" or \"no\"").
 | 
					 | 
				
			||||||
		Focus()
 | 
					 | 
				
			||||||
	vm.emojiText.Emojis = &emojis
 | 
					 | 
				
			||||||
	vm.parent.parent.Render()
 | 
					 | 
				
			||||||
	vm.stopWaiting <- struct{}{}
 | 
					 | 
				
			||||||
	confirm := <-vm.confirmChan
 | 
					 | 
				
			||||||
	vm.emojiText.Emojis = nil
 | 
					 | 
				
			||||||
	vm.infoText.SetText(fmt.Sprintf("Waiting for %s to accept", vm.device.UserID))
 | 
					 | 
				
			||||||
	vm.parent.parent.Render()
 | 
					 | 
				
			||||||
	return confirm
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (vm *VerificationModal) VerifyNumbersMatch(numbers [3]uint) bool {
 | 
					func (vm *VerificationModal) VerifySASMatch(_ *crypto.DeviceIdentity, data crypto.SASData) bool {
 | 
				
			||||||
	vm.infoText.SetText("Check if the other device is showing the\nsame numbers as below, then type \"yes\" to\naccept, or \"no\" to reject")
 | 
						var typeName string
 | 
				
			||||||
 | 
						if data.Type() == event.SASDecimal {
 | 
				
			||||||
 | 
							typeName = "numbers"
 | 
				
			||||||
 | 
						} else if data.Type() == event.SASEmoji {
 | 
				
			||||||
 | 
							typeName = "emojis"
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						vm.infoText.SetText(fmt.Sprintf(
 | 
				
			||||||
 | 
							"Check if the other device is showing the\n"+
 | 
				
			||||||
 | 
								"same %s as below, then type \"yes\" to\n"+
 | 
				
			||||||
 | 
								"accept, or \"no\" to reject", typeName))
 | 
				
			||||||
	vm.inputBar.
 | 
						vm.inputBar.
 | 
				
			||||||
		SetTextColor(tcell.ColorWhite).
 | 
							SetTextColor(tcell.ColorWhite).
 | 
				
			||||||
		SetBackgroundColor(tcell.ColorDarkCyan).
 | 
							SetBackgroundColor(tcell.ColorDarkCyan).
 | 
				
			||||||
		SetPlaceholder("Type \"yes\" or \"no\"").
 | 
							SetPlaceholder("Type \"yes\" or \"no\"").
 | 
				
			||||||
		Focus()
 | 
							Focus()
 | 
				
			||||||
	vm.emojiText.Numbers = &numbers
 | 
						vm.emojiText.Data = data
 | 
				
			||||||
	vm.parent.parent.Render()
 | 
						vm.parent.parent.Render()
 | 
				
			||||||
	vm.stopWaiting <- struct{}{}
 | 
						vm.progress = vm.progressMax
 | 
				
			||||||
	confirm := <-vm.confirmChan
 | 
						confirm := <-vm.confirmChan
 | 
				
			||||||
	vm.emojiText.Numbers = nil
 | 
						vm.progress = vm.progressMax
 | 
				
			||||||
	vm.infoText.SetText(fmt.Sprintf("Waiting for %s to accept", vm.device.UserID))
 | 
						vm.emojiText.Data = nil
 | 
				
			||||||
 | 
						vm.infoText.SetText(fmt.Sprintf("Waiting for %s\nto confirm", vm.device.UserID))
 | 
				
			||||||
	vm.parent.parent.Render()
 | 
						vm.parent.parent.Render()
 | 
				
			||||||
	return confirm
 | 
						return confirm
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -179,6 +186,7 @@ func (vm *VerificationModal) OnCancel(cancelledByUs bool, reason string, _ event
 | 
				
			|||||||
		vm.infoText.SetText(fmt.Sprintf("Verification cancelled by %s: %s", vm.device.UserID, reason))
 | 
							vm.infoText.SetText(fmt.Sprintf("Verification cancelled by %s: %s", vm.device.UserID, reason))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	vm.inputBar.SetPlaceholder("Press enter to close the dialog")
 | 
						vm.inputBar.SetPlaceholder("Press enter to close the dialog")
 | 
				
			||||||
 | 
						vm.stopWaiting <- struct{}{}
 | 
				
			||||||
	vm.done = true
 | 
						vm.done = true
 | 
				
			||||||
	vm.parent.parent.Render()
 | 
						vm.parent.parent.Render()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -188,6 +196,7 @@ func (vm *VerificationModal) OnSuccess() {
 | 
				
			|||||||
	vm.parent.parent.app.SetRedrawTicker(1 * time.Minute)
 | 
						vm.parent.parent.app.SetRedrawTicker(1 * time.Minute)
 | 
				
			||||||
	vm.infoText.SetText(fmt.Sprintf("Successfully verified %s (%s) of %s", vm.device.Name, vm.device.DeviceID, vm.device.UserID))
 | 
						vm.infoText.SetText(fmt.Sprintf("Successfully verified %s (%s) of %s", vm.device.Name, vm.device.DeviceID, vm.device.UserID))
 | 
				
			||||||
	vm.inputBar.SetPlaceholder("Press enter to close the dialog")
 | 
						vm.inputBar.SetPlaceholder("Press enter to close the dialog")
 | 
				
			||||||
 | 
						vm.stopWaiting <- struct{}{}
 | 
				
			||||||
	vm.done = true
 | 
						vm.done = true
 | 
				
			||||||
	vm.parent.parent.Render()
 | 
						vm.parent.parent.Render()
 | 
				
			||||||
	if vm.parent.config.SendToVerifiedOnly {
 | 
						if vm.parent.config.SendToVerifiedOnly {
 | 
				
			||||||
@@ -203,7 +212,7 @@ func (vm *VerificationModal) OnKeyEvent(event mauview.KeyEvent) bool {
 | 
				
			|||||||
			return true
 | 
								return true
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return false
 | 
							return false
 | 
				
			||||||
	} else if vm.emojiText.Emojis == nil && vm.emojiText.Numbers == nil {
 | 
						} else if vm.emojiText.Data == nil {
 | 
				
			||||||
		debug.Print("Ignoring pre-emoji key event")
 | 
							debug.Print("Ignoring pre-emoji key event")
 | 
				
			||||||
		return false
 | 
							return false
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -216,8 +225,11 @@ func (vm *VerificationModal) OnKeyEvent(event mauview.KeyEvent) bool {
 | 
				
			|||||||
			debug.Print("Rejecting verification")
 | 
								debug.Print("Rejecting verification")
 | 
				
			||||||
			vm.confirmChan <- false
 | 
								vm.confirmChan <- false
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		vm.inputBar.SetPlaceholder("")
 | 
							vm.inputBar.
 | 
				
			||||||
		vm.inputBar.SetTextAndMoveCursor("")
 | 
								SetPlaceholder("").
 | 
				
			||||||
 | 
								SetTextAndMoveCursor("").
 | 
				
			||||||
 | 
								SetBackgroundColor(tcell.ColorDefault).
 | 
				
			||||||
 | 
								SetTextColor(tcell.ColorDefault)
 | 
				
			||||||
		return true
 | 
							return true
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		return vm.inputBar.OnKeyEvent(event)
 | 
							return vm.inputBar.OnKeyEvent(event)
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user