Merge branch 'cross-signing'
This commit is contained in:
commit
9b42f5df8e
4
go.mod
4
go.mod
@ -18,11 +18,11 @@ require (
|
|||||||
github.com/zyedidia/clipboard v1.0.3
|
github.com/zyedidia/clipboard v1.0.3
|
||||||
go.etcd.io/bbolt v1.3.5
|
go.etcd.io/bbolt v1.3.5
|
||||||
golang.org/x/image v0.0.0-20200927104501-e162460cd6b5
|
golang.org/x/image v0.0.0-20200927104501-e162460cd6b5
|
||||||
golang.org/x/net v0.0.0-20201022231255-08b38378de70
|
golang.org/x/net v0.0.0-20201026091529-146b70c837a4
|
||||||
gopkg.in/toast.v1 v1.0.0-20180812000517-0a84660828b2
|
gopkg.in/toast.v1 v1.0.0-20180812000517-0a84660828b2
|
||||||
gopkg.in/vansante/go-ffprobe.v2 v2.0.2
|
gopkg.in/vansante/go-ffprobe.v2 v2.0.2
|
||||||
gopkg.in/yaml.v2 v2.3.0
|
gopkg.in/yaml.v2 v2.3.0
|
||||||
maunium.net/go/mautrix v0.7.13
|
maunium.net/go/mautrix v0.8.0-rc.2
|
||||||
maunium.net/go/mauview v0.1.2
|
maunium.net/go/mauview v0.1.2
|
||||||
maunium.net/go/tcell v0.2.0
|
maunium.net/go/tcell v0.2.0
|
||||||
)
|
)
|
||||||
|
77
go.sum
77
go.sum
@ -1,57 +1,63 @@
|
|||||||
github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
|
github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
|
||||||
github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38 h1:smF2tmSOzy2Mm+0dGI2AIUHY+w0BUc+4tn40djz7+6U=
|
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
|
||||||
github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38/go.mod h1:r7bzyVFMNntcxPZXK3/+KdruV1H5KSlyVY0gc+NgInI=
|
github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38/go.mod h1:r7bzyVFMNntcxPZXK3/+KdruV1H5KSlyVY0gc+NgInI=
|
||||||
github.com/alecthomas/chroma v0.8.0 h1:HS+HE97sgcqjQGu5uVr8jIE55Mmh5UeQ7kckAhHg2pY=
|
|
||||||
github.com/alecthomas/chroma v0.8.0/go.mod h1:sko8vR34/90zvl5QdcUdvzL3J8NKjAUx9va9jPuFNoM=
|
|
||||||
github.com/alecthomas/chroma v0.8.1 h1:ym20sbvyC6RXz45u4qDglcgr8E313oPROshcuCHqiEE=
|
github.com/alecthomas/chroma v0.8.1 h1:ym20sbvyC6RXz45u4qDglcgr8E313oPROshcuCHqiEE=
|
||||||
github.com/alecthomas/chroma v0.8.1/go.mod h1:sko8vR34/90zvl5QdcUdvzL3J8NKjAUx9va9jPuFNoM=
|
github.com/alecthomas/chroma v0.8.1/go.mod h1:sko8vR34/90zvl5QdcUdvzL3J8NKjAUx9va9jPuFNoM=
|
||||||
github.com/alecthomas/colour v0.0.0-20160524082231-60882d9e2721 h1:JHZL0hZKJ1VENNfmXvHbgYlbUOvpzYzvy2aZU5gXVeo=
|
|
||||||
github.com/alecthomas/colour v0.0.0-20160524082231-60882d9e2721/go.mod h1:QO9JBoKquHd+jz9nshCh40fOfO+JzsoXy8qTHF68zU0=
|
github.com/alecthomas/colour v0.0.0-20160524082231-60882d9e2721/go.mod h1:QO9JBoKquHd+jz9nshCh40fOfO+JzsoXy8qTHF68zU0=
|
||||||
github.com/alecthomas/kong v0.2.4/go.mod h1:kQOmtJgV+Lb4aj+I2LEn40cbtawdWJ9Y8QLq+lElKxE=
|
github.com/alecthomas/kong v0.2.4/go.mod h1:kQOmtJgV+Lb4aj+I2LEn40cbtawdWJ9Y8QLq+lElKxE=
|
||||||
github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897 h1:p9Sln00KOTlrYkxI1zYWl1QLnEqAqEARBEYa8FQnQcY=
|
|
||||||
github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897/go.mod h1:xTS7Pm1pD1mvyM075QCDSRqH6qRLXylzS24ZTpRiSzQ=
|
github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897/go.mod h1:xTS7Pm1pD1mvyM075QCDSRqH6qRLXylzS24ZTpRiSzQ=
|
||||||
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
|
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
|
||||||
|
github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ=
|
||||||
|
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA=
|
||||||
|
github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
|
||||||
|
github.com/btcsuite/btcutil v1.0.2 h1:9iZ1Terx9fMIOtq1VrwdqfsATL9MC2l8ZrUY6YZ2uts=
|
||||||
|
github.com/btcsuite/btcutil v1.0.2/go.mod h1:j9HUFwoQRsZL3V4n+qG+CUnEGHOarIxfC3Le2Yhbcts=
|
||||||
|
github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg=
|
||||||
|
github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY=
|
||||||
|
github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc=
|
||||||
|
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY=
|
||||||
|
github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs=
|
||||||
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 h1:y5HC9v93H5EPKqaS1UYVg1uYah5Xf51mBfIoWehClUQ=
|
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 h1:y5HC9v93H5EPKqaS1UYVg1uYah5Xf51mBfIoWehClUQ=
|
||||||
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964/go.mod h1:Xd9hchkHSWYkEqJwUGisez3G1QY8Ryz0sdWrLPMGjLk=
|
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964/go.mod h1:Xd9hchkHSWYkEqJwUGisez3G1QY8Ryz0sdWrLPMGjLk=
|
||||||
|
github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c=
|
github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c=
|
||||||
github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4=
|
github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4=
|
||||||
github.com/dlclark/regexp2 v1.2.0 h1:8sAhBGEM0dRWogWqWyQeIJnxjWO6oIjl8FKqREDsGfk=
|
github.com/dlclark/regexp2 v1.2.0 h1:8sAhBGEM0dRWogWqWyQeIJnxjWO6oIjl8FKqREDsGfk=
|
||||||
github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
|
github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
|
||||||
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
github.com/gabriel-vasile/mimetype v1.1.1 h1:qbN9MPuRf3bstHu9zkI9jDWNfH//9+9kHxr9oRBBBOA=
|
github.com/gabriel-vasile/mimetype v1.1.1 h1:qbN9MPuRf3bstHu9zkI9jDWNfH//9+9kHxr9oRBBBOA=
|
||||||
github.com/gabriel-vasile/mimetype v1.1.1/go.mod h1:6CDPel/o/3/s4+bp6kIbsWATq8pmgOisOPG40CJa6To=
|
github.com/gabriel-vasile/mimetype v1.1.1/go.mod h1:6CDPel/o/3/s4+bp6kIbsWATq8pmgOisOPG40CJa6To=
|
||||||
github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko=
|
github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko=
|
||||||
github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
|
github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
|
||||||
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||||
github.com/kyokomi/emoji v2.2.2+incompatible h1:gaQFbK2+uSxOR4iGZprJAbpmtqTrHhSdgOyIMD6Oidc=
|
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||||
github.com/kyokomi/emoji v2.2.2+incompatible/go.mod h1:mZ6aGCD7yk8j6QY6KICwnZ2pxoszVseX1DNoGtU2tBA=
|
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||||
|
github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=
|
||||||
|
github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4=
|
||||||
github.com/kyokomi/emoji/v2 v2.2.5 h1:sxOmQKMB3ICTDWiJbtMHUnKn1HFHjGk9av0+IYWVovI=
|
github.com/kyokomi/emoji/v2 v2.2.5 h1:sxOmQKMB3ICTDWiJbtMHUnKn1HFHjGk9av0+IYWVovI=
|
||||||
github.com/kyokomi/emoji/v2 v2.2.5/go.mod h1:JUcn42DTdsXJo1SWanHh4HKDEyPaR5CqkmoirZZP9qE=
|
github.com/kyokomi/emoji/v2 v2.2.5/go.mod h1:JUcn42DTdsXJo1SWanHh4HKDEyPaR5CqkmoirZZP9qE=
|
||||||
github.com/lib/pq v1.7.0 h1:h93mCPfUSkaul3Ka/VG8uZdmW1uMHDGxzu0NWHuJmHY=
|
github.com/lib/pq v1.7.0 h1:h93mCPfUSkaul3Ka/VG8uZdmW1uMHDGxzu0NWHuJmHY=
|
||||||
github.com/lib/pq v1.7.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
github.com/lib/pq v1.7.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||||
github.com/lithammer/fuzzysearch v1.1.0 h1:go9v8tLCrNTTlH42OAaq4eHFe81TDHEnlrMEb6R4f+A=
|
|
||||||
github.com/lithammer/fuzzysearch v1.1.0/go.mod h1:Bqx4wo8lTOFcJr3ckpY6HA9lEIOO0H5HrkJ5CsN56HQ=
|
|
||||||
github.com/lithammer/fuzzysearch v1.1.1 h1:8F9OAV2xPuYblToVohjanztdnPjbtA0MLgMvDKQ0Z08=
|
github.com/lithammer/fuzzysearch v1.1.1 h1:8F9OAV2xPuYblToVohjanztdnPjbtA0MLgMvDKQ0Z08=
|
||||||
github.com/lithammer/fuzzysearch v1.1.1/go.mod h1:H2bng+w5gsR7NlfIJM8ElGZI0sX6C/9uzGqicVXGU6c=
|
github.com/lithammer/fuzzysearch v1.1.1/go.mod h1:H2bng+w5gsR7NlfIJM8ElGZI0sX6C/9uzGqicVXGU6c=
|
||||||
github.com/lucasb-eyer/go-colorful v1.0.3 h1:QIbQXiugsb+q10B+MI+7DI1oQLdmnep86tWFlaaUAac=
|
github.com/lucasb-eyer/go-colorful v1.0.3 h1:QIbQXiugsb+q10B+MI+7DI1oQLdmnep86tWFlaaUAac=
|
||||||
github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||||
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
|
||||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||||
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
|
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
|
||||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||||
github.com/mattn/go-sqlite3 v1.14.0 h1:mLyGNKR8+Vv9CAU7PphKa2hkEqxxhn8i32J6FPj1/QA=
|
|
||||||
github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus=
|
github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus=
|
||||||
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d h1:VhgPp6v9qf9Agr/56bj7Y/xa04UccTW04VP0Qed4vnQ=
|
|
||||||
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d/go.mod h1:YUTz3bUH2ZwIWBy3CJBeOBEugqcmXREj14T+iG/4k4U=
|
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d/go.mod h1:YUTz3bUH2ZwIWBy3CJBeOBEugqcmXREj14T+iG/4k4U=
|
||||||
|
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
|
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
|
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||||
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 h1:q2e307iGHPdTGp0hoxKjt1H5pDo6utceo3dQVK3I5XQ=
|
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 h1:q2e307iGHPdTGp0hoxKjt1H5pDo6utceo3dQVK3I5XQ=
|
||||||
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o=
|
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o=
|
||||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
|
||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/rivo/uniseg v0.1.0 h1:+2KBaVoUmb9XzDsrx/Ct0W/EYOSFf/nWTauy++DprtY=
|
github.com/rivo/uniseg v0.1.0 h1:+2KBaVoUmb9XzDsrx/Ct0W/EYOSFf/nWTauy++DprtY=
|
||||||
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||||
@ -59,15 +65,12 @@ github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0
|
|||||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/sasha-s/go-deadlock v0.2.0 h1:lMqc+fUb7RrFS3gQLtoQsJ7/6TV/pAIFvBsqX73DK8Y=
|
github.com/sasha-s/go-deadlock v0.2.0 h1:lMqc+fUb7RrFS3gQLtoQsJ7/6TV/pAIFvBsqX73DK8Y=
|
||||||
github.com/sasha-s/go-deadlock v0.2.0/go.mod h1:StQn567HiB1fF2yJ44N9au7wOhrPS3iZqiDbRupzT10=
|
github.com/sasha-s/go-deadlock v0.2.0/go.mod h1:StQn567HiB1fF2yJ44N9au7wOhrPS3iZqiDbRupzT10=
|
||||||
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
|
|
||||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
|
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
|
||||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||||
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
|
|
||||||
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.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
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.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
|
||||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/tidwall/gjson v1.6.0 h1:9VEQWz6LLMUsUl6PueE49ir4Ka6CzLymOAZDxpFsTDc=
|
github.com/tidwall/gjson v1.6.0 h1:9VEQWz6LLMUsUl6PueE49ir4Ka6CzLymOAZDxpFsTDc=
|
||||||
github.com/tidwall/gjson v1.6.0/go.mod h1:P256ACg0Mn+j1RXIDXoss50DeIABTYK1PULOJHhxOls=
|
github.com/tidwall/gjson v1.6.0/go.mod h1:P256ACg0Mn+j1RXIDXoss50DeIABTYK1PULOJHhxOls=
|
||||||
@ -78,35 +81,31 @@ github.com/tidwall/pretty v1.0.1 h1:WE4RBSZ1x6McVVC8S/Md+Qse8YUv6HRObAx6ke00NY8=
|
|||||||
github.com/tidwall/pretty v1.0.1/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
github.com/tidwall/pretty v1.0.1/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||||
github.com/tidwall/sjson v1.1.1 h1:7h1vk049Jnd5EH9NyzNiEuwYW4b5qgreBbqRC19AS3U=
|
github.com/tidwall/sjson v1.1.1 h1:7h1vk049Jnd5EH9NyzNiEuwYW4b5qgreBbqRC19AS3U=
|
||||||
github.com/tidwall/sjson v1.1.1/go.mod h1:yvVuSnpEQv5cYIrO+AT6kw4QVfd5SDZoGIS7/5+fZFs=
|
github.com/tidwall/sjson v1.1.1/go.mod h1:yvVuSnpEQv5cYIrO+AT6kw4QVfd5SDZoGIS7/5+fZFs=
|
||||||
github.com/zyedidia/clipboard v0.0.0-20200421031010-7c45b8673834 h1:0nOfq3JwYRiY3+nwfWVQYEaXDmGCQgj3RKoqTifLzP4=
|
|
||||||
github.com/zyedidia/clipboard v0.0.0-20200421031010-7c45b8673834/go.mod h1:zykFnZUXX0ErxqvYLUFEq7QDJKId8rmh2FgD0/Y8cjA=
|
github.com/zyedidia/clipboard v0.0.0-20200421031010-7c45b8673834/go.mod h1:zykFnZUXX0ErxqvYLUFEq7QDJKId8rmh2FgD0/Y8cjA=
|
||||||
github.com/zyedidia/clipboard v1.0.3 h1:F/nCDVYMdbDWTmY8s8cJl0tnwX32q96IF09JHM14bUI=
|
github.com/zyedidia/clipboard v1.0.3 h1:F/nCDVYMdbDWTmY8s8cJl0tnwX32q96IF09JHM14bUI=
|
||||||
github.com/zyedidia/clipboard v1.0.3/go.mod h1:zykFnZUXX0ErxqvYLUFEq7QDJKId8rmh2FgD0/Y8cjA=
|
github.com/zyedidia/clipboard v1.0.3/go.mod h1:zykFnZUXX0ErxqvYLUFEq7QDJKId8rmh2FgD0/Y8cjA=
|
||||||
github.com/zyedidia/poller v1.0.1 h1:Tt9S3AxAjXwWGNiC2TUdRJkQDZSzCBNVQ4xXiQ7440s=
|
|
||||||
github.com/zyedidia/poller v1.0.1/go.mod h1:vZXJOHGDcuK08GXhF6IAY0ZFd2WcgOR5DOTp84Uk5eE=
|
github.com/zyedidia/poller v1.0.1/go.mod h1:vZXJOHGDcuK08GXhF6IAY0ZFd2WcgOR5DOTp84Uk5eE=
|
||||||
go.etcd.io/bbolt v1.3.4 h1:hi1bXHMVrlQh6WwxAy+qZCV/SYIlqo+Ushwdpa4tAKg=
|
|
||||||
go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
|
|
||||||
go.etcd.io/bbolt v1.3.5 h1:XAzx9gjCb0Rxj7EoqcClPD1d5ZBxZJk0jbuoPHenBt0=
|
go.etcd.io/bbolt v1.3.5 h1:XAzx9gjCb0Rxj7EoqcClPD1d5ZBxZJk0jbuoPHenBt0=
|
||||||
go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
|
go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
|
golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
|
golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
|
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 h1:pLI5jrR7OSLijeIDcmRxNmw2api+jEfxLoykJVice/E=
|
||||||
|
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||||
golang.org/x/image v0.0.0-20200430140353-33d19683fad8 h1:6WW6V3x1P/jokJBpRQYUJnMHRP6isStQwCozxnU7XQw=
|
|
||||||
golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
|
||||||
golang.org/x/image v0.0.0-20200927104501-e162460cd6b5 h1:QelT11PB4FXiDEXucrfNckHoFxwt8USGY1ajP1ZF5lM=
|
golang.org/x/image v0.0.0-20200927104501-e162460cd6b5 h1:QelT11PB4FXiDEXucrfNckHoFxwt8USGY1ajP1ZF5lM=
|
||||||
golang.org/x/image v0.0.0-20200927104501-e162460cd6b5/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
golang.org/x/image v0.0.0-20200927104501-e162460cd6b5/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||||
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
golang.org/x/net v0.0.0-20200602114024-627f9648deb9 h1:pNX+40auqi2JqRfOP1akLGtYcn15TUbkhwuCO3foqqM=
|
|
||||||
golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
|
||||||
golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA=
|
|
||||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
|
||||||
golang.org/x/net v0.0.0-20201022231255-08b38378de70 h1:Z6x4N9mAi4oF0TbHweCsH618MO6OI6UFgV0FP5n0wBY=
|
|
||||||
golang.org/x/net v0.0.0-20201022231255-08b38378de70/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201022231255-08b38378de70/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
|
golang.org/x/net v0.0.0-20201026091529-146b70c837a4 h1:awiuzyrRjJDb+OXi9ceHO3SDxVoN3JER57mhtqkdQBs=
|
||||||
|
golang.org/x/net v0.0.0-20201026091529-146b70c837a4/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@ -114,33 +113,27 @@ golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200413165638-669c56c373c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200413165638-669c56c373c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200501145240-bc7a7d42d5c3 h1:5B6i6EAiSYyejWfvc5Rc9BbI3rzIsrrXfAQBWnYfn+w=
|
|
||||||
golang.org/x/sys v0.0.0-20200501145240-bc7a7d42d5c3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200501145240-bc7a7d42d5c3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA=
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA=
|
||||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
|
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/toast.v1 v1.0.0-20180812000517-0a84660828b2 h1:MZF6J7CV6s/h0HBkfqebrYfKCVEo5iN+wzE4QhV3Evo=
|
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||||
gopkg.in/toast.v1 v1.0.0-20180812000517-0a84660828b2/go.mod h1:s1Sn2yZos05Qfs7NKt867Xe18emOmtsO3eAKbDaon0o=
|
gopkg.in/toast.v1 v1.0.0-20180812000517-0a84660828b2/go.mod h1:s1Sn2yZos05Qfs7NKt867Xe18emOmtsO3eAKbDaon0o=
|
||||||
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||||
gopkg.in/vansante/go-ffprobe.v2 v2.0.2 h1:DdxSfFnlqeawPIVbIQEI6LR6OQHQNR7tNgWb2mWuC4w=
|
gopkg.in/vansante/go-ffprobe.v2 v2.0.2 h1:DdxSfFnlqeawPIVbIQEI6LR6OQHQNR7tNgWb2mWuC4w=
|
||||||
gopkg.in/vansante/go-ffprobe.v2 v2.0.2/go.mod h1:qF0AlAjk7Nqzqf3y333Ly+KxN3cKF2JqA3JT5ZheUGE=
|
gopkg.in/vansante/go-ffprobe.v2 v2.0.2/go.mod h1:qF0AlAjk7Nqzqf3y333Ly+KxN3cKF2JqA3JT5ZheUGE=
|
||||||
|
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
||||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
maunium.net/go/maulogger/v2 v2.1.1/go.mod h1:TYWy7wKwz/tIXTpsx8G3mZseIRiC5DoMxSZazOHy68A=
|
maunium.net/go/maulogger/v2 v2.1.1/go.mod h1:TYWy7wKwz/tIXTpsx8G3mZseIRiC5DoMxSZazOHy68A=
|
||||||
maunium.net/go/mautrix v0.7.6 h1:jB9oCimPq0mVyolwQBC/9N1fu21AU+Ryq837cLf4gOo=
|
maunium.net/go/mautrix v0.8.0-rc.2 h1:H1OieKdfTr4+i3lGgvydl+3z21CM4XgHzTrW8ozmsb8=
|
||||||
maunium.net/go/mautrix v0.7.6/go.mod h1:Va/74MijqaS0DQ3aUqxmFO54/PMfr1LVsCOcGRHbYmo=
|
maunium.net/go/mautrix v0.8.0-rc.2/go.mod h1:TtVePxoEaw6+RZDKVajw66Yaj1lqLjH8l4FF3krsqWY=
|
||||||
maunium.net/go/mautrix v0.7.13 h1:qfnvLxvQafvLgHbdZF/+9qs9gyArYf8fUnzfQbjgQaU=
|
|
||||||
maunium.net/go/mautrix v0.7.13/go.mod h1:Jn0ijwXwMFvJFIN9IljirIVKpZQbZP/Dk7pdX2qDmXk=
|
|
||||||
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.2 h1:6Y3GpyckIlzCNkry6k025YhWg8oh5XJFj3RAMf4VwWo=
|
maunium.net/go/mauview v0.1.2 h1:6Y3GpyckIlzCNkry6k025YhWg8oh5XJFj3RAMf4VwWo=
|
||||||
maunium.net/go/mauview v0.1.2/go.mod h1:3QBUiuLct9moP1LgDhCGIg0Ovxn38Bd2sGndnUOuj4o=
|
maunium.net/go/mauview v0.1.2/go.mod h1:3QBUiuLct9moP1LgDhCGIg0Ovxn38Bd2sGndnUOuj4o=
|
||||||
maunium.net/go/tcell v0.2.0 h1:1Q0kN3wCOGAIGu1r3QHADsjSUOPDylKREvCv3EzJpVg=
|
maunium.net/go/tcell v0.2.0 h1:1Q0kN3wCOGAIGu1r3QHADsjSUOPDylKREvCv3EzJpVg=
|
||||||
|
@ -51,6 +51,7 @@ type MatrixContainer interface {
|
|||||||
|
|
||||||
Login(user, password string) error
|
Login(user, password string) error
|
||||||
Logout()
|
Logout()
|
||||||
|
UIAFallback(authType mautrix.AuthType, sessionID string) error
|
||||||
|
|
||||||
SendPreferencesToMatrix()
|
SendPreferencesToMatrix()
|
||||||
PrepareMarkdownMessage(roomID id.RoomID, msgtype event.MessageType, text, html string, relation *Relation) *muksevt.Event
|
PrepareMarkdownMessage(roomID id.RoomID, msgtype event.MessageType, text, html string, relation *Relation) *muksevt.Event
|
||||||
@ -82,6 +83,7 @@ type Crypto interface {
|
|||||||
Load() error
|
Load() error
|
||||||
FlushStore() error
|
FlushStore() error
|
||||||
ProcessSyncResponse(resp *mautrix.RespSync, since string)
|
ProcessSyncResponse(resp *mautrix.RespSync, since string)
|
||||||
|
ProcessInRoomVerification(evt *event.Event) error
|
||||||
HandleMemberEvent(*event.Event)
|
HandleMemberEvent(*event.Event)
|
||||||
DecryptMegolmEvent(*event.Event) (*event.Event, error)
|
DecryptMegolmEvent(*event.Event) (*event.Event, error)
|
||||||
EncryptMegolmEvent(id.RoomID, event.Type, interface{}) (*event.EncryptedEventContent, error)
|
EncryptMegolmEvent(id.RoomID, event.Type, interface{}) (*event.EncryptedEventContent, error)
|
||||||
|
@ -585,8 +585,17 @@ func (c *Container) HandleEncrypted(source mautrix.EventSource, mxEvent *event.E
|
|||||||
c.HandleMessage(source, mxEvent)
|
c.HandleMessage(source, mxEvent)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if evt.Type.IsInRoomVerification() {
|
||||||
|
err := c.crypto.ProcessInRoomVerification(evt)
|
||||||
|
if err != nil {
|
||||||
|
debug.Printf("[Crypto/Error] Failed to process in-room verification event %s of type %s: %v", evt.ID, evt.Type.String(), err)
|
||||||
|
} else {
|
||||||
|
debug.Printf("[Crypto/Debug] Processed in-room verification event %s of type %s", evt.ID, evt.Type.String())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
c.HandleMessage(source, evt)
|
c.HandleMessage(source, evt)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// HandleMessage is the event handler for the m.room.message timeline event.
|
// HandleMessage is the event handler for the m.room.message timeline event.
|
||||||
func (c *Container) HandleMessage(source mautrix.EventSource, mxEvent *event.Event) {
|
func (c *Container) HandleMessage(source mautrix.EventSource, mxEvent *event.Event) {
|
||||||
@ -744,14 +753,14 @@ func (c *Container) HandleReadReceipt(source mautrix.EventSource, evt *event.Eve
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Container) parseDirectChatInfo(evt *event.Event) map[*rooms.Room]bool {
|
func (c *Container) parseDirectChatInfo(evt *event.Event) map[*rooms.Room]id.UserID {
|
||||||
directChats := make(map[*rooms.Room]bool)
|
directChats := make(map[*rooms.Room]id.UserID)
|
||||||
for _, roomIDList := range *evt.Content.AsDirectChats() {
|
for userID, roomIDList := range *evt.Content.AsDirectChats() {
|
||||||
for _, roomID := range roomIDList {
|
for _, roomID := range roomIDList {
|
||||||
// TODO we shouldn't create direct chat rooms that we aren't in
|
// TODO we shouldn't create direct chat rooms that we aren't in
|
||||||
room := c.GetOrCreateRoom(roomID)
|
room := c.GetOrCreateRoom(roomID)
|
||||||
if room != nil && !room.HasLeft {
|
if room != nil && !room.HasLeft {
|
||||||
directChats[room] = true
|
directChats[room] = userID
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -761,9 +770,10 @@ func (c *Container) parseDirectChatInfo(evt *event.Event) map[*rooms.Room]bool {
|
|||||||
func (c *Container) HandleDirectChatInfo(_ mautrix.EventSource, evt *event.Event) {
|
func (c *Container) HandleDirectChatInfo(_ mautrix.EventSource, evt *event.Event) {
|
||||||
directChats := c.parseDirectChatInfo(evt)
|
directChats := c.parseDirectChatInfo(evt)
|
||||||
for _, room := range c.config.Rooms.Map {
|
for _, room := range c.config.Rooms.Map {
|
||||||
shouldBeDirect := directChats[room]
|
userID, isDirect := directChats[room]
|
||||||
if shouldBeDirect != room.IsDirect {
|
if isDirect != room.IsDirect {
|
||||||
room.IsDirect = shouldBeDirect
|
room.IsDirect = isDirect
|
||||||
|
room.OtherUser = userID
|
||||||
if c.config.AuthCache.InitialSyncDone {
|
if c.config.AuthCache.InitialSyncDone {
|
||||||
c.ui.MainView().UpdateTags(room)
|
c.ui.MainView().UpdateTags(room)
|
||||||
}
|
}
|
||||||
@ -879,7 +889,7 @@ func (c *Container) prepareEvent(roomID id.RoomID, content *event.MessageEventCo
|
|||||||
Type: event.RelReplace,
|
Type: event.RelReplace,
|
||||||
EventID: rel.Event.ID,
|
EventID: rel.Event.ID,
|
||||||
}
|
}
|
||||||
} else if rel != nil && rel.Type == event.RelReference {
|
} else if rel != nil && rel.Type == event.RelReply {
|
||||||
content.SetReply(rel.Event.Event)
|
content.SetReply(rel.Event.Event)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,6 +94,7 @@ type Room struct {
|
|||||||
lastMarkedRead id.EventID
|
lastMarkedRead id.EventID
|
||||||
// Whether or not this room is marked as a direct chat.
|
// Whether or not this room is marked as a direct chat.
|
||||||
IsDirect bool
|
IsDirect bool
|
||||||
|
OtherUser id.UserID
|
||||||
|
|
||||||
// List of tags given to this room.
|
// List of tags given to this room.
|
||||||
RawTags []RoomTag
|
RawTags []RoomTag
|
||||||
|
115
matrix/uia-fallback.go
Normal file
115
matrix/uia-fallback.go
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
// 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/>.
|
||||||
|
|
||||||
|
package matrix
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"maunium.net/go/mautrix"
|
||||||
|
|
||||||
|
"maunium.net/go/gomuks/debug"
|
||||||
|
"maunium.net/go/gomuks/lib/open"
|
||||||
|
)
|
||||||
|
|
||||||
|
const uiaFallbackPage = `<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<title>gomuks user-interactive auth</title>
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h2>Please complete the login in the popup window</h2>
|
||||||
|
<p>Keep this page open while logging in, it will close automatically after the login finishes.</p>
|
||||||
|
<button onclick="openPopup()">Open popup</button>
|
||||||
|
<button onclick="finish(false)">Cancel</button>
|
||||||
|
<script>
|
||||||
|
const url = location.hash.substr(1)
|
||||||
|
let popupWindow
|
||||||
|
|
||||||
|
function finish(success) {
|
||||||
|
if (popupWindow) {
|
||||||
|
popupWindow.close()
|
||||||
|
}
|
||||||
|
fetch("", {method: success ? "POST" : "DELETE"}).then(() => window.close())
|
||||||
|
}
|
||||||
|
|
||||||
|
function openPopup() {
|
||||||
|
popupWindow = window.open(url)
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener("message", evt => evt.data === "authDone" && finish(true))
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
`
|
||||||
|
|
||||||
|
func (c *Container) UIAFallback(loginType mautrix.AuthType, sessionID string) error {
|
||||||
|
errChan := make(chan error, 1)
|
||||||
|
server := &http.Server{Addr: ":29325"}
|
||||||
|
server.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if r.Method == "GET" {
|
||||||
|
w.Header().Add("Content-Type", "text/html")
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
_, _ = w.Write([]byte(uiaFallbackPage))
|
||||||
|
} else if r.Method == "POST" || r.Method == "DELETE" {
|
||||||
|
w.Header().Add("Content-Type", "text/html")
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
err := server.Shutdown(ctx)
|
||||||
|
if err != nil {
|
||||||
|
debug.Printf("Failed to shut down SSO server: %v\n", err)
|
||||||
|
}
|
||||||
|
if r.Method == "DELETE" {
|
||||||
|
errChan <- errors.New("login cancelled")
|
||||||
|
} else {
|
||||||
|
errChan <- nil
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
} else {
|
||||||
|
w.WriteHeader(http.StatusMethodNotAllowed)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
go server.ListenAndServe()
|
||||||
|
defer server.Close()
|
||||||
|
authURL := c.client.BuildURLWithQuery(mautrix.URLPath{"auth", loginType, "fallback", "web"}, map[string]string{
|
||||||
|
"session": sessionID,
|
||||||
|
})
|
||||||
|
link := url.URL{
|
||||||
|
Scheme: "http",
|
||||||
|
Host: "localhost:29325",
|
||||||
|
Path: "/",
|
||||||
|
Fragment: authURL,
|
||||||
|
}
|
||||||
|
err := open.Open(link.String())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = <-errChan
|
||||||
|
return err
|
||||||
|
}
|
@ -104,11 +104,15 @@ func NewCommandProcessor(parent *MainView) *CommandProcessor {
|
|||||||
"e": {"edit"},
|
"e": {"edit"},
|
||||||
"dl": {"download"},
|
"dl": {"download"},
|
||||||
"o": {"open"},
|
"o": {"open"},
|
||||||
|
"4s": {"ssss"},
|
||||||
|
"s4": {"ssss"},
|
||||||
|
"cs": {"cross-signing"},
|
||||||
},
|
},
|
||||||
autocompleters: map[string]CommandAutocompleter{
|
autocompleters: map[string]CommandAutocompleter{
|
||||||
"devices": autocompleteDevice,
|
"devices": autocompleteUser,
|
||||||
"device": autocompleteDevice,
|
"device": autocompleteDevice,
|
||||||
"verify": autocompleteDevice,
|
"verify": autocompleteUser,
|
||||||
|
"verify-device": autocompleteDevice,
|
||||||
"unverify": autocompleteDevice,
|
"unverify": autocompleteDevice,
|
||||||
"blacklist": autocompleteDevice,
|
"blacklist": autocompleteDevice,
|
||||||
"upload": autocompleteFile,
|
"upload": autocompleteFile,
|
||||||
@ -164,6 +168,7 @@ func NewCommandProcessor(parent *MainView) *CommandProcessor {
|
|||||||
|
|
||||||
"fingerprint": cmdFingerprint,
|
"fingerprint": cmdFingerprint,
|
||||||
"devices": cmdDevices,
|
"devices": cmdDevices,
|
||||||
|
"verify-device": cmdVerifyDevice,
|
||||||
"verify": cmdVerify,
|
"verify": cmdVerify,
|
||||||
"device": cmdDevice,
|
"device": cmdDevice,
|
||||||
"unverify": cmdUnverify,
|
"unverify": cmdUnverify,
|
||||||
@ -172,6 +177,8 @@ func NewCommandProcessor(parent *MainView) *CommandProcessor {
|
|||||||
"import": cmdImportKeys,
|
"import": cmdImportKeys,
|
||||||
"export": cmdExportKeys,
|
"export": cmdExportKeys,
|
||||||
"export-room": cmdExportRoomKeys,
|
"export-room": cmdExportRoomKeys,
|
||||||
|
"ssss": cmdSSSS,
|
||||||
|
"cross-signing": cmdCrossSigning,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
package ui
|
package ui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@ -26,7 +27,10 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
"unicode"
|
"unicode"
|
||||||
|
|
||||||
|
ifc "maunium.net/go/gomuks/interface"
|
||||||
|
"maunium.net/go/mautrix"
|
||||||
"maunium.net/go/mautrix/crypto"
|
"maunium.net/go/mautrix/crypto"
|
||||||
|
"maunium.net/go/mautrix/crypto/ssss"
|
||||||
"maunium.net/go/mautrix/id"
|
"maunium.net/go/mautrix/id"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -77,15 +81,20 @@ func autocompleteDeviceDeviceID(cmd *CommandAutocomplete) (completions []string,
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func autocompleteUser(cmd *CommandAutocomplete) ([]string, string) {
|
||||||
|
if len(cmd.Args) == 1 && !unicode.IsSpace(rune(cmd.RawArgs[len(cmd.RawArgs)-1])) {
|
||||||
|
return autocompleteDeviceUserID(cmd)
|
||||||
|
}
|
||||||
|
return []string{}, ""
|
||||||
|
}
|
||||||
|
|
||||||
func autocompleteDevice(cmd *CommandAutocomplete) ([]string, string) {
|
func autocompleteDevice(cmd *CommandAutocomplete) ([]string, string) {
|
||||||
if len(cmd.Args) == 0 {
|
if len(cmd.Args) == 0 {
|
||||||
return []string{}, ""
|
return []string{}, ""
|
||||||
} else if len(cmd.Args) == 1 && !unicode.IsSpace(rune(cmd.RawArgs[len(cmd.RawArgs)-1])) {
|
} else if len(cmd.Args) == 1 && !unicode.IsSpace(rune(cmd.RawArgs[len(cmd.RawArgs)-1])) {
|
||||||
return autocompleteDeviceUserID(cmd)
|
return autocompleteDeviceUserID(cmd)
|
||||||
} else if cmd.Command != "devices" {
|
|
||||||
return autocompleteDeviceDeviceID(cmd)
|
|
||||||
}
|
}
|
||||||
return []string{}, ""
|
return autocompleteDeviceDeviceID(cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getDevice(cmd *Command) *crypto.DeviceIdentity {
|
func getDevice(cmd *Command) *crypto.DeviceIdentity {
|
||||||
@ -134,7 +143,11 @@ func cmdDevices(cmd *Command) {
|
|||||||
}
|
}
|
||||||
var buf strings.Builder
|
var buf strings.Builder
|
||||||
for _, device := range devices {
|
for _, device := range devices {
|
||||||
_, _ = fmt.Fprintf(&buf, "%s (%s) - %s\n Fingerprint: %s\n", device.DeviceID, device.Name, device.Trust.String(), device.Fingerprint())
|
trust := device.Trust.String()
|
||||||
|
if device.Trust == crypto.TrustStateUnset && mach.IsDeviceTrusted(device) {
|
||||||
|
trust = "verified (transitive)"
|
||||||
|
}
|
||||||
|
_, _ = fmt.Fprintf(&buf, "%s (%s) - %s\n Fingerprint: %s\n", device.DeviceID, device.Name, trust, device.Fingerprint())
|
||||||
}
|
}
|
||||||
resp := buf.String()
|
resp := buf.String()
|
||||||
cmd.Reply("%s", resp[:len(resp)-1])
|
cmd.Reply("%s", resp[:len(resp)-1])
|
||||||
@ -149,13 +162,28 @@ func cmdDevice(cmd *Command) {
|
|||||||
if device.Deleted {
|
if device.Deleted {
|
||||||
deviceType = "Deleted device"
|
deviceType = "Deleted device"
|
||||||
}
|
}
|
||||||
|
mach := cmd.Matrix.Crypto().(*crypto.OlmMachine)
|
||||||
|
trustState := device.Trust.String()
|
||||||
|
if device.Trust == crypto.TrustStateUnset && mach.IsDeviceTrusted(device) {
|
||||||
|
trustState = "verified (transitive)"
|
||||||
|
}
|
||||||
cmd.Reply("%s %s of %s\nFingerprint: %s\nIdentity key: %s\nDevice name: %s\nTrust state: %s",
|
cmd.Reply("%s %s of %s\nFingerprint: %s\nIdentity key: %s\nDevice name: %s\nTrust state: %s",
|
||||||
deviceType, device.DeviceID, device.UserID,
|
deviceType, device.DeviceID, device.UserID,
|
||||||
device.Fingerprint(), device.IdentityKey,
|
device.Fingerprint(), device.IdentityKey,
|
||||||
device.Name, device.Trust.String())
|
device.Name, trustState)
|
||||||
}
|
}
|
||||||
|
|
||||||
func cmdVerify(cmd *Command) {
|
func crossSignDevice(cmd *Command, device *crypto.DeviceIdentity) {
|
||||||
|
mach := cmd.Matrix.Crypto().(*crypto.OlmMachine)
|
||||||
|
err := mach.SignOwnDevice(device)
|
||||||
|
if err != nil {
|
||||||
|
cmd.Reply("Failed to upload cross-signing signature: %v", err)
|
||||||
|
} else {
|
||||||
|
cmd.Reply("Successfully cross-signed %s (%s)", device.DeviceID, device.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func cmdVerifyDevice(cmd *Command) {
|
||||||
device := getDevice(cmd)
|
device := getDevice(cmd)
|
||||||
if device == nil {
|
if device == nil {
|
||||||
return
|
return
|
||||||
@ -184,10 +212,48 @@ func cmdVerify(cmd *Command) {
|
|||||||
if device.Trust == crypto.TrustStateBlacklisted {
|
if device.Trust == crypto.TrustStateBlacklisted {
|
||||||
action = "unblacklisted and verified"
|
action = "unblacklisted and verified"
|
||||||
}
|
}
|
||||||
|
if device.UserID == cmd.Matrix.Client().UserID {
|
||||||
|
crossSignDevice(cmd, device)
|
||||||
device.Trust = crypto.TrustStateVerified
|
device.Trust = crypto.TrustStateVerified
|
||||||
putDevice(cmd, device, action)
|
putDevice(cmd, device, action)
|
||||||
|
} else {
|
||||||
|
putDevice(cmd, device, action)
|
||||||
|
cmd.Reply("Warning: verifying individual devices of other users is not synced with cross-signing")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func cmdVerify(cmd *Command) {
|
||||||
|
if len(cmd.Args) < 1 {
|
||||||
|
cmd.Reply("Usage: /%s <user ID> [--force]", cmd.OrigCommand)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
force := len(cmd.Args) >= 2 && strings.ToLower(cmd.Args[1]) == "--force"
|
||||||
|
userID := id.UserID(cmd.Args[0])
|
||||||
|
room := cmd.Room.Room
|
||||||
|
if !room.Encrypted {
|
||||||
|
cmd.Reply("In-room verification is only supported in encrypted rooms")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!room.IsDirect || room.OtherUser != userID) && !force {
|
||||||
|
cmd.Reply("This doesn't seem to be a direct chat. Either switch to a direct chat with %s, "+
|
||||||
|
"or use `--force` to start the verification anyway.", userID)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
mach := cmd.Matrix.Crypto().(*crypto.OlmMachine)
|
||||||
|
if mach.CrossSigningKeys == nil && !force {
|
||||||
|
cmd.Reply("Cross-signing private keys not cached. Generate or fetch cross-signing keys with `/cross-signing`, " +
|
||||||
|
"or use `--force` to start the verification anyway")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
modal := NewVerificationModal(cmd.MainView, &crypto.DeviceIdentity{UserID: userID}, mach.DefaultSASTimeout)
|
||||||
|
_, err := mach.NewInRoomSASVerificationWith(cmd.Room.Room.ID, userID, modal, 120*time.Second)
|
||||||
|
if err != nil {
|
||||||
|
cmd.Reply("Failed to start in-room verification: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
cmd.MainView.ShowModal(modal)
|
||||||
|
}
|
||||||
|
|
||||||
func cmdUnverify(cmd *Command) {
|
func cmdUnverify(cmd *Command) {
|
||||||
device := getDevice(cmd)
|
device := getDevice(cmd)
|
||||||
@ -243,7 +309,7 @@ func cmdImportKeys(cmd *Command) {
|
|||||||
cmd.Reply("Failed to read %s: %v", path, err)
|
cmd.Reply("Failed to read %s: %v", path, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
passphrase, ok := cmd.MainView.AskPassword("Key import", false)
|
passphrase, ok := cmd.MainView.AskPassword("Key import", "passphrase", "", false)
|
||||||
if !ok {
|
if !ok {
|
||||||
cmd.Reply("Passphrase entry cancelled")
|
cmd.Reply("Passphrase entry cancelled")
|
||||||
return
|
return
|
||||||
@ -263,7 +329,7 @@ func exportKeys(cmd *Command, sessions []*crypto.InboundGroupSession) {
|
|||||||
cmd.Reply("Failed to get absolute path: %v", err)
|
cmd.Reply("Failed to get absolute path: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
passphrase, ok := cmd.MainView.AskPassword("Key export", true)
|
passphrase, ok := cmd.MainView.AskPassword("Key export", "passphrase", "", true)
|
||||||
if !ok {
|
if !ok {
|
||||||
cmd.Reply("Passphrase entry cancelled")
|
cmd.Reply("Passphrase entry cancelled")
|
||||||
return
|
return
|
||||||
@ -299,3 +365,333 @@ func cmdExportRoomKeys(cmd *Command) {
|
|||||||
}
|
}
|
||||||
exportKeys(cmd, sessions)
|
exportKeys(cmd, sessions)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ssssHelp = `Usage: /%s <subcommand> [...]
|
||||||
|
|
||||||
|
Subcommands:
|
||||||
|
* status [key ID] - Check the status of your SSSS.
|
||||||
|
* generate [--set-default] - Generate a SSSS key and optionally set it as the default.
|
||||||
|
* set-default <key ID> - Set a SSSS key as the default.`
|
||||||
|
|
||||||
|
func cmdSSSS(cmd *Command) {
|
||||||
|
if len(cmd.Args) == 0 {
|
||||||
|
cmd.Reply(ssssHelp, cmd.OrigCommand)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
mach := cmd.Matrix.Crypto().(*crypto.OlmMachine)
|
||||||
|
|
||||||
|
switch strings.ToLower(cmd.Args[0]) {
|
||||||
|
case "status":
|
||||||
|
keyID := ""
|
||||||
|
if len(cmd.Args) > 1 {
|
||||||
|
keyID = cmd.Args[1]
|
||||||
|
}
|
||||||
|
cmdS4Status(cmd, mach, keyID)
|
||||||
|
case "generate":
|
||||||
|
setDefault := len(cmd.Args) > 1 && strings.ToLower(cmd.Args[1]) == "--set-default"
|
||||||
|
cmdS4Generate(cmd, mach, setDefault)
|
||||||
|
case "set-default":
|
||||||
|
if len(cmd.Args) < 2 {
|
||||||
|
cmd.Reply("Usage: /%s set-default <key ID>", cmd.OrigCommand)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
cmdS4SetDefault(cmd, mach, cmd.Args[1])
|
||||||
|
default:
|
||||||
|
cmd.Reply(ssssHelp, cmd.OrigCommand)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func cmdS4Status(cmd *Command, mach *crypto.OlmMachine, keyID string) {
|
||||||
|
var keyData *ssss.KeyMetadata
|
||||||
|
var err error
|
||||||
|
if len(keyID) == 0 {
|
||||||
|
keyID, keyData, err = mach.SSSS.GetDefaultKeyData()
|
||||||
|
} else {
|
||||||
|
keyData, err = mach.SSSS.GetKeyData(keyID)
|
||||||
|
}
|
||||||
|
if errors.Is(err, ssss.ErrNoDefaultKeyAccountDataEvent) {
|
||||||
|
cmd.Reply("SSSS is not set up: no default key set")
|
||||||
|
return
|
||||||
|
} else if err != nil {
|
||||||
|
cmd.Reply("Failed to get key data: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
hasPassphrase := "no"
|
||||||
|
if keyData.Passphrase != nil {
|
||||||
|
hasPassphrase = fmt.Sprintf("yes (alg=%s,bits=%d,iter=%d)", keyData.Passphrase.Algorithm, keyData.Passphrase.Bits, keyData.Passphrase.Iterations)
|
||||||
|
}
|
||||||
|
algorithm := keyData.Algorithm
|
||||||
|
if algorithm != ssss.AlgorithmAESHMACSHA2 {
|
||||||
|
algorithm += " (not supported!)"
|
||||||
|
}
|
||||||
|
cmd.Reply("Default key is set.\n Key ID: %s\n Has passphrase: %s\n Algorithm: %s", keyID, hasPassphrase, algorithm)
|
||||||
|
}
|
||||||
|
|
||||||
|
func cmdS4Generate(cmd *Command, mach *crypto.OlmMachine, setDefault bool) {
|
||||||
|
passphrase, ok := cmd.MainView.AskPassword("Passphrase", "", "", true)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
key, err := ssss.NewKey(passphrase)
|
||||||
|
if err != nil {
|
||||||
|
cmd.Reply("Failed to generate new key: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = mach.SSSS.SetKeyData(key.ID, key.Metadata)
|
||||||
|
if err != nil {
|
||||||
|
cmd.Reply("Failed to upload key metadata: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO if we start persisting command replies, the recovery key needs to be moved into a popup
|
||||||
|
cmd.Reply("Successfully generated key %s\nRecovery key: %s", key.ID, key.RecoveryKey())
|
||||||
|
|
||||||
|
if setDefault {
|
||||||
|
err = mach.SSSS.SetDefaultKeyID(key.ID)
|
||||||
|
if err != nil {
|
||||||
|
cmd.Reply("Failed to set key as default: %v", err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cmd.Reply("You can use `/%s set-default %s` to set it as the default", cmd.OrigCommand, key.ID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func cmdS4SetDefault(cmd *Command, mach *crypto.OlmMachine, keyID string) {
|
||||||
|
_, err := mach.SSSS.GetKeyData(keyID)
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, mautrix.MNotFound) {
|
||||||
|
cmd.Reply("Couldn't find key data on server")
|
||||||
|
} else {
|
||||||
|
cmd.Reply("Failed to fetch key data: %v", err)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = mach.SSSS.SetDefaultKeyID(keyID)
|
||||||
|
if err != nil {
|
||||||
|
cmd.Reply("Failed to set key as default: %v", err)
|
||||||
|
} else {
|
||||||
|
cmd.Reply("Successfully set key %s as default", keyID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const crossSigningHelp = `Usage: /%s <subcommand> [...]
|
||||||
|
|
||||||
|
Subcommands:
|
||||||
|
* status
|
||||||
|
Check the status of your own cross-signing keys.
|
||||||
|
* generate [--force]
|
||||||
|
Generate and upload new cross-signing keys.
|
||||||
|
This will prompt you to enter your account password.
|
||||||
|
If you already have existing keys, --force is required.
|
||||||
|
* self-sign
|
||||||
|
Sign the current device with cached cross-signing keys.
|
||||||
|
* fetch [--save-to-disk]
|
||||||
|
Fetch your cross-signing keys from SSSS and decrypt them.
|
||||||
|
If --save-to-disk is specified, the keys are saved to disk.
|
||||||
|
* upload
|
||||||
|
Upload your cross-signing keys to SSSS.`
|
||||||
|
|
||||||
|
func cmdCrossSigning(cmd *Command) {
|
||||||
|
if len(cmd.Args) == 0 {
|
||||||
|
cmd.Reply(crossSigningHelp, cmd.OrigCommand)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
client := cmd.Matrix.Client()
|
||||||
|
mach := cmd.Matrix.Crypto().(*crypto.OlmMachine)
|
||||||
|
|
||||||
|
switch strings.ToLower(cmd.Args[0]) {
|
||||||
|
case "status":
|
||||||
|
cmdCrossSigningStatus(cmd, mach)
|
||||||
|
case "generate":
|
||||||
|
force := len(cmd.Args) > 1 && strings.ToLower(cmd.Args[1]) == "--force"
|
||||||
|
cmdCrossSigningGenerate(cmd, cmd.Matrix, mach, client, force)
|
||||||
|
case "fetch":
|
||||||
|
saveToDisk := len(cmd.Args) > 1 && strings.ToLower(cmd.Args[1]) == "--save-to-disk"
|
||||||
|
cmdCrossSigningFetch(cmd, mach, saveToDisk)
|
||||||
|
case "upload":
|
||||||
|
cmdCrossSigningUpload(cmd, mach)
|
||||||
|
case "self-sign":
|
||||||
|
cmdCrossSigningSelfSign(cmd, mach)
|
||||||
|
default:
|
||||||
|
cmd.Reply(crossSigningHelp, cmd.OrigCommand)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func cmdCrossSigningStatus(cmd *Command, mach *crypto.OlmMachine) {
|
||||||
|
keys := mach.GetOwnCrossSigningPublicKeys()
|
||||||
|
if keys == nil {
|
||||||
|
if mach.CrossSigningKeys != nil {
|
||||||
|
cmd.Reply("Cross-signing keys are cached, but not published")
|
||||||
|
} else {
|
||||||
|
cmd.Reply("Didn't find published cross-signing keys")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if mach.CrossSigningKeys != nil {
|
||||||
|
cmd.Reply("Cross-signing keys are published and private keys are cached")
|
||||||
|
} else {
|
||||||
|
cmd.Reply("Cross-signing keys are published, but private keys are not cached")
|
||||||
|
}
|
||||||
|
cmd.Reply("Master key: %s", keys.MasterKey)
|
||||||
|
cmd.Reply("User signing key: %s", keys.UserSigningKey)
|
||||||
|
cmd.Reply("Self-signing key: %s", keys.SelfSigningKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
func cmdCrossSigningFetch(cmd *Command, mach *crypto.OlmMachine, saveToDisk bool) {
|
||||||
|
key := getSSSS(cmd, mach)
|
||||||
|
if key == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err := mach.FetchCrossSigningKeysFromSSSS(key)
|
||||||
|
if err != nil {
|
||||||
|
cmd.Reply("Error fetching cross-signing keys: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if saveToDisk {
|
||||||
|
cmd.Reply("Saving keys to disk is not yet implemented")
|
||||||
|
}
|
||||||
|
cmd.Reply("Successfully unlocked cross-signing keys")
|
||||||
|
}
|
||||||
|
|
||||||
|
func cmdCrossSigningGenerate(cmd *Command, container ifc.MatrixContainer, mach *crypto.OlmMachine, client *mautrix.Client, force bool) {
|
||||||
|
if !force {
|
||||||
|
existingKeys := mach.GetOwnCrossSigningPublicKeys()
|
||||||
|
if existingKeys != nil {
|
||||||
|
cmd.Reply("Found existing cross-signing keys. Use `--force` if you want to overwrite them.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
keys, err := mach.GenerateCrossSigningKeys()
|
||||||
|
if err != nil {
|
||||||
|
cmd.Reply("Failed to generate cross-signing keys: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = mach.PublishCrossSigningKeys(keys, func(uia *mautrix.RespUserInteractive) interface{} {
|
||||||
|
if !uia.HasSingleStageFlow(mautrix.AuthTypePassword) {
|
||||||
|
for _, flow := range uia.Flows {
|
||||||
|
if len(flow.Stages) != 1 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
cmd.Reply("Opening browser for authentication")
|
||||||
|
err := container.UIAFallback(flow.Stages[0], uia.Session)
|
||||||
|
if err != nil {
|
||||||
|
cmd.Reply("Authentication failed: %v", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &mautrix.ReqUIAuthFallback{
|
||||||
|
Session: uia.Session,
|
||||||
|
User: mach.Client.UserID.String(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cmd.Reply("No supported authentication mechanisms found")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
password, ok := cmd.MainView.AskPassword("Account password", "", "correct horse battery staple", false)
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &mautrix.ReqUIAuthLogin{
|
||||||
|
BaseAuthData: mautrix.BaseAuthData{
|
||||||
|
Type: mautrix.AuthTypePassword,
|
||||||
|
Session: uia.Session,
|
||||||
|
},
|
||||||
|
User: mach.Client.UserID.String(),
|
||||||
|
Password: password,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
cmd.Reply("Failed to publish cross-signing keys: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
cmd.Reply("Successfully generated and published cross-signing keys")
|
||||||
|
|
||||||
|
err = mach.SignOwnMasterKey()
|
||||||
|
if err != nil {
|
||||||
|
cmd.Reply("Failed to sign master key with device key: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getSSSS(cmd *Command, mach *crypto.OlmMachine) *ssss.Key {
|
||||||
|
_, keyData, err := mach.SSSS.GetDefaultKeyData()
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, mautrix.MNotFound) {
|
||||||
|
cmd.Reply("SSSS not set up, use `!ssss generate --set-default` first")
|
||||||
|
} else {
|
||||||
|
cmd.Reply("Failed to fetch default SSSS key data: %v", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var key *ssss.Key
|
||||||
|
if keyData.Passphrase != nil && keyData.Passphrase.Algorithm == ssss.PassphraseAlgorithmPBKDF2 {
|
||||||
|
passphrase, ok := cmd.MainView.AskPassword("Passphrase", "", "correct horse battery staple", false)
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
key, err = keyData.VerifyPassphrase(passphrase)
|
||||||
|
if errors.Is(err, ssss.ErrIncorrectSSSSKey) {
|
||||||
|
cmd.Reply("Incorrect passphrase")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
recoveryKey, ok := cmd.MainView.AskPassword("Recovery key", "", "tDAK LMRH PiYE bdzi maCe xLX5 wV6P Nmfd c5mC wLef 15Fs VVSc", false)
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
key, err = keyData.VerifyRecoveryKey(recoveryKey)
|
||||||
|
if errors.Is(err, ssss.ErrInvalidRecoveryKey) {
|
||||||
|
cmd.Reply("Malformed recovery key")
|
||||||
|
return nil
|
||||||
|
} else if errors.Is(err, ssss.ErrIncorrectSSSSKey) {
|
||||||
|
cmd.Reply("Incorrect recovery key")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// All the errors should already be handled above, this is just for backup
|
||||||
|
if err != nil {
|
||||||
|
cmd.Reply("Failed to get SSSS key: %v", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return key
|
||||||
|
}
|
||||||
|
|
||||||
|
func cmdCrossSigningUpload(cmd *Command, mach *crypto.OlmMachine) {
|
||||||
|
if mach.CrossSigningKeys == nil {
|
||||||
|
cmd.Reply("Cross-signing keys not cached, use `!%s generate` first", cmd.OrigCommand)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
key := getSSSS(cmd, mach)
|
||||||
|
if key == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err := mach.UploadCrossSigningKeysToSSSS(key, mach.CrossSigningKeys)
|
||||||
|
if err != nil {
|
||||||
|
cmd.Reply("Failed to upload keys to SSSS: %v", err)
|
||||||
|
} else {
|
||||||
|
cmd.Reply("Successfully uploaded cross-signing keys to SSSS")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func cmdCrossSigningSelfSign(cmd *Command, mach *crypto.OlmMachine) {
|
||||||
|
if mach.CrossSigningKeys == nil {
|
||||||
|
cmd.Reply("Cross-signing keys not cached")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err := mach.SignOwnDevice(mach.OwnIdentity())
|
||||||
|
if err != nil {
|
||||||
|
cmd.Reply("Failed to self-sign: %v", err)
|
||||||
|
} else {
|
||||||
|
cmd.Reply("Successfully self-signed. This device is now trusted by other devices")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -29,6 +29,7 @@ func cmdNoCrypto(cmd *Command) {
|
|||||||
var (
|
var (
|
||||||
cmdDevices = cmdNoCrypto
|
cmdDevices = cmdNoCrypto
|
||||||
cmdDevice = cmdNoCrypto
|
cmdDevice = cmdNoCrypto
|
||||||
|
cmdVerifyDevice = cmdNoCrypto
|
||||||
cmdVerify = cmdNoCrypto
|
cmdVerify = cmdNoCrypto
|
||||||
cmdUnverify = cmdNoCrypto
|
cmdUnverify = cmdNoCrypto
|
||||||
cmdBlacklist = cmdNoCrypto
|
cmdBlacklist = cmdNoCrypto
|
||||||
|
@ -17,6 +17,9 @@
|
|||||||
package ui
|
package ui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"maunium.net/go/mauview"
|
"maunium.net/go/mauview"
|
||||||
"maunium.net/go/tcell"
|
"maunium.net/go/tcell"
|
||||||
)
|
)
|
||||||
@ -41,13 +44,20 @@ type PasswordModal struct {
|
|||||||
parent *MainView
|
parent *MainView
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *MainView) AskPassword(title string, isNew bool) (string, bool) {
|
func (view *MainView) AskPassword(title, thing, placeholder string, isNew bool) (string, bool) {
|
||||||
pwm := NewPasswordModal(view, title, isNew)
|
pwm := NewPasswordModal(view, title, thing, placeholder, isNew)
|
||||||
view.ShowModal(pwm)
|
view.ShowModal(pwm)
|
||||||
|
view.parent.Render()
|
||||||
return pwm.Wait()
|
return pwm.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewPasswordModal(parent *MainView, title string, isNew bool) *PasswordModal {
|
func NewPasswordModal(parent *MainView, title, thing, placeholder string, isNew bool) *PasswordModal {
|
||||||
|
if placeholder == "" {
|
||||||
|
placeholder = "correct horse battery staple"
|
||||||
|
}
|
||||||
|
if thing == "" {
|
||||||
|
thing = strings.ToLower(title)
|
||||||
|
}
|
||||||
pwm := &PasswordModal{
|
pwm := &PasswordModal{
|
||||||
parent: parent,
|
parent: parent,
|
||||||
form: mauview.NewForm(),
|
form: mauview.NewForm(),
|
||||||
@ -64,13 +74,13 @@ func NewPasswordModal(parent *MainView, title string, isNew bool) *PasswordModal
|
|||||||
|
|
||||||
pwm.text = mauview.NewTextField()
|
pwm.text = mauview.NewTextField()
|
||||||
if isNew {
|
if isNew {
|
||||||
pwm.text.SetText("Create a passphrase")
|
pwm.text.SetText(fmt.Sprintf("Create a %s", thing))
|
||||||
} else {
|
} else {
|
||||||
pwm.text.SetText("Enter the passphrase")
|
pwm.text.SetText(fmt.Sprintf("Enter the %s", thing))
|
||||||
}
|
}
|
||||||
pwm.input = mauview.NewInputField().
|
pwm.input = mauview.NewInputField().
|
||||||
SetMaskCharacter('*').
|
SetMaskCharacter('*').
|
||||||
SetPlaceholder("correct horse battery staple")
|
SetPlaceholder(placeholder)
|
||||||
pwm.form.AddComponent(pwm.text, 1, 1, 3, 1)
|
pwm.form.AddComponent(pwm.text, 1, 1, 3, 1)
|
||||||
pwm.form.AddFormItem(pwm.input, 1, 2, 3, 1)
|
pwm.form.AddFormItem(pwm.input, 1, 2, 3, 1)
|
||||||
|
|
||||||
@ -78,10 +88,10 @@ func NewPasswordModal(parent *MainView, title string, isNew bool) *PasswordModal
|
|||||||
height += 3
|
height += 3
|
||||||
pwm.confirmInput = mauview.NewInputField().
|
pwm.confirmInput = mauview.NewInputField().
|
||||||
SetMaskCharacter('*').
|
SetMaskCharacter('*').
|
||||||
SetPlaceholder("correct horse battery staple").
|
SetPlaceholder(placeholder).
|
||||||
SetChangedFunc(pwm.HandleChange)
|
SetChangedFunc(pwm.HandleChange)
|
||||||
pwm.input.SetChangedFunc(pwm.HandleChange)
|
pwm.input.SetChangedFunc(pwm.HandleChange)
|
||||||
pwm.confirmText = mauview.NewTextField().SetText("Confirm passphrase")
|
pwm.confirmText = mauview.NewTextField().SetText(fmt.Sprintf("Confirm %s", thing))
|
||||||
|
|
||||||
pwm.form.SetRow(3, 1).SetRow(4, 1).SetRow(5, 1)
|
pwm.form.SetRow(3, 1).SetRow(4, 1).SetRow(5, 1)
|
||||||
pwm.form.AddComponent(pwm.confirmText, 1, 4, 3, 1)
|
pwm.form.AddComponent(pwm.confirmText, 1, 4, 3, 1)
|
||||||
|
@ -771,7 +771,7 @@ func (view *RoomView) getRelationForNewEvent() *ifc.Relation {
|
|||||||
}
|
}
|
||||||
} else if view.replying != nil {
|
} else if view.replying != nil {
|
||||||
return &ifc.Relation{
|
return &ifc.Relation{
|
||||||
Type: event.RelReference,
|
Type: event.RelReply,
|
||||||
Event: view.replying,
|
Event: view.replying,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -148,7 +148,8 @@ func (vm *VerificationModal) VerificationMethods() []crypto.VerificationMethod {
|
|||||||
return []crypto.VerificationMethod{crypto.VerificationMethodEmoji{}, crypto.VerificationMethodDecimal{}}
|
return []crypto.VerificationMethod{crypto.VerificationMethodEmoji{}, crypto.VerificationMethodDecimal{}}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (vm *VerificationModal) VerifySASMatch(_ *crypto.DeviceIdentity, data crypto.SASData) bool {
|
func (vm *VerificationModal) VerifySASMatch(device *crypto.DeviceIdentity, data crypto.SASData) bool {
|
||||||
|
vm.device = device
|
||||||
var typeName string
|
var typeName string
|
||||||
if data.Type() == event.SASDecimal {
|
if data.Type() == event.SASDecimal {
|
||||||
typeName = "numbers"
|
typeName = "numbers"
|
||||||
|
Loading…
Reference in New Issue
Block a user