Compare commits

...

19 Commits
v0.0.8 ... main

Author SHA1 Message Date
Dan Ballard 7a65efaa78 change to use new go-cross-compile container
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is pending Details
2024-03-05 09:38:14 -08:00
Sarah Jamie Lewis 83c84b2049
Add Reload Field to CwtchStarted event
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is passing Details
2024-02-26 18:01:46 -08:00
Sarah Jamie Lewis 6618410cc9
Upgrade Cwtch
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is passing Details
2024-02-26 09:28:36 -08:00
Sarah Jamie Lewis 89f19928c2
Load Correct Profile Image when ProfileImageExperiment is Disabled
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is passing Details
2024-02-23 15:22:12 -08:00
Sarah Jamie Lewis 243727a131 Fix Cwtch on Tails > 5.13
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is passing Details
2024-02-12 11:04:54 -08:00
Sarah Jamie Lewis dd0f1cd868 Upgrade Cwtch for eventbus dedupe fix
continuous-integration/drone/pr Build is pending Details
continuous-integration/drone/push Build is passing Details
2024-02-09 13:23:42 -08:00
Sarah Jamie Lewis 5bf954f3d0 Upgrade Cwtch
continuous-integration/drone/push Build is pending Details
continuous-integration/drone/pr Build is passing Details
2024-02-09 13:07:30 -08:00
Sarah Jamie Lewis 425c3e6030 Expose new Enhanced Permission APIs
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is passing Details
2024-01-15 10:14:52 -08:00
Sarah Jamie Lewis 32ea146ec0 Upgrade Cwtch 2024-01-15 10:07:19 -08:00
Sarah Jamie Lewis 6321f09aad Improve Quality Scripts and Fix nilaway issues. 2024-01-15 10:07:19 -08:00
Dan Ballard 9e3fc6123b fix building mac amd64 build on m1 arm machines
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is passing Details
2024-01-05 18:11:05 -08:00
Sarah Jamie Lewis cbe687ce2e Try out minimal version flags on Mac Builds
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is passing Details
2024-01-05 21:11:54 +00:00
Sarah Jamie Lewis 6c0b2e2a4f Explicitly Use Bullseye for Linux Builds
continuous-integration/drone/push Build is passing Details
2024-01-03 20:52:51 +00:00
Sarah Jamie Lewis 7c042334d3 Update '.drone.yml'
continuous-integration/drone/pr Build is pending Details
continuous-integration/drone/push Build is passing Details
2024-01-03 17:55:51 +00:00
Sarah Jamie Lewis c7c2259c2d More .drone updates
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is failing Details
2024-01-02 16:09:07 -08:00
Sarah Jamie Lewis c2c3c2894d Upgade Cwtch, Allow Unsigned APIs.
continuous-integration/drone/pr Build is failing Details
Also update .drone
2024-01-02 16:06:38 -08:00
Sarah Jamie Lewis 7ddf09caec Expose PublishServerInfo
continuous-integration/drone/pr Build is pending Details
continuous-integration/drone/push Build is passing Details
2023-09-26 13:15:16 -07:00
Sarah Jamie Lewis 41a554a198 Upgrade Cwtch
continuous-integration/drone/pr Build is pending Details
continuous-integration/drone/push Build is passing Details
2023-09-25 18:37:46 +00:00
Dan Ballard b80db89284 Remove auto loadProfiles with default password from StartCwtch. Leave for apps to do
continuous-integration/drone/pr Build is pending Details
continuous-integration/drone/push Build is passing Details
2023-09-24 09:56:37 -07:00
9 changed files with 164 additions and 83 deletions

View File

@ -5,15 +5,20 @@ name: linux-android-windows-test
steps: steps:
- name: fetch - name: fetch
image: golang:1.19.1 image: openpriv/go-cross-compile:2024.02
volumes: volumes:
- name: deps - name: deps
path: /go path: /go
commands: commands:
- go install honnef.co/go/tools/cmd/staticcheck@latest - go install honnef.co/go/tools/cmd/staticcheck@latest
- wget https://git.openprivacy.ca/openprivacy/buildfiles/raw/master/tor/tor - go install go.uber.org/nilaway/cmd/nilaway@latest
- wget https://git.openprivacy.ca/openprivacy/buildfiles/raw/master/tor/torrc - wget https://git.openprivacy.ca/openprivacy/buildfiles/raw/branch/master/tor/tor-0.4.8.9-linux-x86_64.tar.gz -O tor.tar.gz
- chmod a+x tor - tar -xzf tor.tar.gz
- chmod a+x Tor/tor
- export PATH=$PWD/Tor/:$PATH
- export LD_LIBRARY_PATH=$PWD/Tor/
- tor --version
- export GO111MODULE=on
- git fetch --tags - git fetch --tags
- go mod download - go mod download
- echo `git describe --tags` > VERSION - echo `git describe --tags` > VERSION
@ -21,7 +26,7 @@ steps:
- export GOSUMDB="off" - export GOSUMDB="off"
- name: build-linux - name: build-linux
image: openpriv/golangxarm:1.19.1 image: openpriv/go-cross-compile:2024.02
volumes: volumes:
- name: deps - name: deps
path: /go path: /go
@ -31,7 +36,7 @@ steps:
- make linux - make linux
- name: build-android - name: build-android
image: openpriv/android-go-mobile:2023.02 image: openpriv/go-cross-compile:2024.02
volumes: volumes:
- name: deps - name: deps
path: /go path: /go
@ -44,7 +49,7 @@ steps:
- make android - make android
- name: build-windows - name: build-windows
image: openpriv/mingw-go:2023.01 image: openpriv/go-cross-compile:2024.02
environment: environment:
GOPATH: /go GOPATH: /go
volumes: volumes:
@ -55,7 +60,7 @@ steps:
- make windows - make windows
- name: deploy-buildfiles - name: deploy-buildfiles
image: kroniak/ssh-client image: openpriv/go-cross-compile:2024.02
pull: if-not-exists pull: if-not-exists
environment: environment:
BUILDFILES_KEY: BUILDFILES_KEY:
@ -146,7 +151,7 @@ steps:
status: [ success ] status: [ success ]
commands: commands:
- echo $BUILDFILES_KEY > ~/id_rsab64 - echo $BUILDFILES_KEY > ~/id_rsab64
- base64 -d ~/id_rsab64 > ~/id_rsa - base64 -d -i ~/id_rsab64 -o ~/id_rsa
- chmod 400 ~/id_rsa - chmod 400 ~/id_rsa
- export DIR=libCwtch-autobindings-`cat COMMIT_DATE`-`cat VERSION` - export DIR=libCwtch-autobindings-`cat COMMIT_DATE`-`cat VERSION`
- mkdir -p $DIR - mkdir -p $DIR

View File

@ -48,20 +48,20 @@ libCwtch.x.so: lib.go
./switch-ffi.sh ./switch-ffi.sh
mkdir -p build/linux mkdir -p build/linux
ifeq ($(ARCH),x86_64) ifeq ($(ARCH),x86_64)
env CGO_ENABLED=1 CC=$(ARM_X_CC) GOARCH=arm64 go build -trimpath -ldflags "-buildid=autobindings-v0.0.3-22-g20065b2 -X main.buildVer=autobindings-v0.0.3-22-g20065b2 -X main.buildDate=2023-05-01-21-41" -buildmode c-shared -o libCwtch.x.so env CGO_ENABLED=1 CC=$(ARM_X_CC) GOARCH=arm64 go build -trimpath -ldflags "-buildid=autobindings-$(shell git describe --tags) -X main.buildVer=autobindings-$(shell git describe --tags) -X main.buildDate=$(shell git log -1 --format=%cd --date=format:%G-%m-%d-%H-%M)" -buildmode c-shared -o libCwtch.x.so
mv libCwtch.x.so build/linux/libCwtch.arm64.so mv libCwtch.x.so build/linux/libCwtch.arm64.so
mv libCwtch.x.h build/linux/libCwtch.h mv libCwtch.x.h build/linux/libCwtch.h
endif endif
libCwtch.x64.dylib: lib.go libCwtch.x64.dylib: lib.go
./switch-ffi.sh ./switch-ffi.sh
go build -trimpath -ldflags "-buildid=autobindings-$(shell git describe --tags) -X main.buildVer=autobindings-$(shell git describe --tags) -X main.buildDate=$(shell git log -1 --format=%cd --date=format:%G-%m-%d-%H-%M)" -buildmode c-shared -o libCwtch.x64.dylib env CGO_CFLAGS="-mmacosx-version-min=10.12" CGO_LDFLAGS="-mmacosx-version-min=10.12" GOARCH=amd64 GOOS=darwin CGO_ENABLED=1 go build -trimpath -ldflags "-buildid=autobindings-$(shell git describe --tags) -X main.buildVer=autobindings-$(shell git describe --tags) -X main.buildDate=$(shell git log -1 --format=%cd --date=format:%G-%m-%d-%H-%M)" -buildmode c-shared -o libCwtch.x64.dylib
mkdir -p build/macos mkdir -p build/macos
mv libCwtch.x64.dylib build/macos/ mv libCwtch.x64.dylib build/macos/
libCwtch.arm64.dylib: lib.go libCwtch.arm64.dylib: lib.go
./switch-ffi.sh ./switch-ffi.sh
env GOARCH=arm64 GOOS=darwin CGO_ENABLED=1 go build -trimpath -ldflags "-buildid=$(shell git describe --tags) -X main.buildVer=$(shell git describe --tags) -X main.buildDate=$(shell git log -1 --format=%cd --date=format:%G-%m-%d-%H-%M)" -buildmode c-shared -o libCwtch.arm64.dylib env CGO_CFLAGS="-mmacosx-version-min=10.12" CGO_LDFLAGS="-mmacosx-version-min=10.12" GOARCH=arm64 GOOS=darwin CGO_ENABLED=1 go build -trimpath -ldflags "-buildid=$(shell git describe --tags) -X main.buildVer=$(shell git describe --tags) -X main.buildDate=$(shell git log -1 --format=%cd --date=format:%G-%m-%d-%H-%M)" -buildmode c-shared -o libCwtch.arm64.dylib
mkdir -p build/macos mkdir -p build/macos
mv libCwtch.arm64.dylib build/macos/ mv libCwtch.arm64.dylib build/macos/

View File

@ -96,7 +96,9 @@ func main() {
case "profile": case "profile":
generatedBindings = generateProfileFunction(generatedBindings, fName, args) generatedBindings = generateProfileFunction(generatedBindings, fName, args)
case "(json)profile": case "(json)profile":
generatedBindings = generateJsonProfileFunction(generatedBindings, fName, args) generatedBindings = generateJsonProfileFunction(generatedBindings, fName, args, false)
case "(json-err)profile":
generatedBindings = generateJsonProfileFunction(generatedBindings, fName, args, true)
case "@profile-experiment": case "@profile-experiment":
experiment := args[0] experiment := args[0]
generatedBindings = generateExperimentalProfileFunction(generatedBindings, experiment, fName, args[1:]) generatedBindings = generateExperimentalProfileFunction(generatedBindings, experiment, fName, args[1:])
@ -146,6 +148,10 @@ func intArgPrototype(varName string) (string, string, string, string) {
return fmt.Sprintf(`%s C.int`, ToSnakeCase(varName)), fmt.Sprintf(`int(%v)`, ToSnakeCase(varName)), fmt.Sprintf(`%v int`, varName), varName return fmt.Sprintf(`%s C.int`, ToSnakeCase(varName)), fmt.Sprintf(`int(%v)`, ToSnakeCase(varName)), fmt.Sprintf(`%v int`, varName), varName
} }
func uintArgPrototype(varName string) (string, string, string, string) {
return fmt.Sprintf(`%s C.uint`, ToSnakeCase(varName)), fmt.Sprintf(`int(%v)`, ToSnakeCase(varName)), fmt.Sprintf(`%v int`, varName), varName
}
func conversationArgPrototype(varName string) (string, string, string, string) { func conversationArgPrototype(varName string) (string, string, string, string) {
return intArgPrototype(varName) return intArgPrototype(varName)
} }
@ -235,7 +241,7 @@ func mapArgs(argsTypes []string) (string, string, string, string) {
gUse = append(gUse, c4) gUse = append(gUse, c4)
case "int": case "int":
if len(argTypeParts) != 2 { if len(argTypeParts) != 2 {
fmt.Printf("generic bool arg must have have e.g. bool:<name>\n") fmt.Printf("generic int arg must have have e.g. int:<name>\n")
os.Exit(1) os.Exit(1)
} }
c1, c2, c3, c4 := intArgPrototype(argTypeParts[1]) c1, c2, c3, c4 := intArgPrototype(argTypeParts[1])
@ -243,6 +249,20 @@ func mapArgs(argsTypes []string) (string, string, string, string) {
c2GoArgs = append(c2GoArgs, c2) c2GoArgs = append(c2GoArgs, c2)
goSpec = append(goSpec, c3) goSpec = append(goSpec, c3)
gUse = append(gUse, c4) gUse = append(gUse, c4)
case "uint":
if len(argTypeParts) != 2 {
fmt.Printf("generic uint arg must have have e.g. uint:<name>\n")
os.Exit(1)
}
c1, c2, c3, c4 := uintArgPrototype(argTypeParts[1])
cArgs = append(cArgs, c1)
c2GoArgs = append(c2GoArgs, c2)
goSpec = append(goSpec, c3)
// because of java/kotlin/android/gomobile inability to recognize unsigned integers
// we need to pretent this is a signed interface...so do the final cast here...
// this will cause bad behavior if a negative number is passed through the java
// interface...so...don't do that...
gUse = append(gUse, fmt.Sprintf("uint(%s)", c4))
case "string": case "string":
if len(argTypeParts) != 2 { if len(argTypeParts) != 2 {
fmt.Printf("generic string arg must have have e.g. string:<name>\n") fmt.Printf("generic string arg must have have e.g. string:<name>\n")
@ -364,7 +384,7 @@ func {{FNAME}}({{GO_ARGS_SPEC}}) {
return bindings return bindings
} }
func generateJsonProfileFunction(bindings string, name string, argsTypes []string) string { func generateJsonProfileFunction(bindings string, name string, argsTypes []string, handleErr bool) string {
appPrototype := ` appPrototype := `
//export c_{{FNAME}} //export c_{{FNAME}}
func c_{{FNAME}}({{C_ARGS}}) *C.char { func c_{{FNAME}}({{C_ARGS}}) *C.char {
@ -374,14 +394,26 @@ func c_{{FNAME}}({{C_ARGS}}) *C.char {
func {{FNAME}}({{GO_ARGS_SPEC}}) string { func {{FNAME}}({{GO_ARGS_SPEC}}) string {
cwtchProfile := application.GetPeer(profile) cwtchProfile := application.GetPeer(profile)
if cwtchProfile != nil { if cwtchProfile != nil {
return cwtchProfile.{{LIBNAME}}({{GO_ARG}}) {{HANDLE_FUNC}}
} }
return "" return ""
} }
` `
noErrorPrototype := `return cwtchProfile.{{LIBNAME}}({{GO_ARG}})`
withErrorPrototype := `res,err := cwtchProfile.{{LIBNAME}}({{GO_ARG}})
if err != nil {
log.Errorf("could not {{FNAME}} %v", err)
}
return res`
functionPrototype := noErrorPrototype
if handleErr {
functionPrototype = withErrorPrototype
}
cArgs, c2GoArgs, goSpec, gUse := mapArgs(argsTypes) cArgs, c2GoArgs, goSpec, gUse := mapArgs(argsTypes)
appPrototype = strings.ReplaceAll(appPrototype, "{{HANDLE_FUNC}}", functionPrototype)
appPrototype = strings.ReplaceAll(appPrototype, "{{FNAME}}", strings.TrimPrefix(name, "Enhanced")) appPrototype = strings.ReplaceAll(appPrototype, "{{FNAME}}", strings.TrimPrefix(name, "Enhanced"))
appPrototype = strings.ReplaceAll(appPrototype, "{{LIBNAME}}", name) appPrototype = strings.ReplaceAll(appPrototype, "{{LIBNAME}}", name)
// We need to prepend a set of profile handle arguments... // We need to prepend a set of profile handle arguments...

4
go.mod
View File

@ -1,9 +1,9 @@
module git.openprivacy.ca/cwtch.im/cwtch-autobindings module git.openprivacy.ca/cwtch.im/cwtch-autobindings
go 1.19 go 1.20
require ( require (
cwtch.im/cwtch v0.24.3 cwtch.im/cwtch v0.27.0
git.openprivacy.ca/cwtch.im/server v1.4.5 git.openprivacy.ca/cwtch.im/server v1.4.5
git.openprivacy.ca/openprivacy/connectivity v1.11.0 git.openprivacy.ca/openprivacy/connectivity v1.11.0
git.openprivacy.ca/openprivacy/log v1.0.3 git.openprivacy.ca/openprivacy/log v1.0.3

4
go.sum
View File

@ -1,6 +1,6 @@
cwtch.im/cwtch v0.18.0/go.mod h1:StheazFFY7PKqBbEyDVLhzWW6WOat41zV0ckC240c5Y= cwtch.im/cwtch v0.18.0/go.mod h1:StheazFFY7PKqBbEyDVLhzWW6WOat41zV0ckC240c5Y=
cwtch.im/cwtch v0.24.3 h1:K0GRQU4fetJOPF9mcQUTSuoVQAAfMm4xffnrm5ZTAC8= cwtch.im/cwtch v0.27.0 h1:MkNIZ+pT5ZwiGlKHk20GMUTlzBsmCWJEibbj6hr+WHw=
cwtch.im/cwtch v0.24.3/go.mod h1:o8uZBYjDS1DEHftxdYl91iMQZ2WDxlajM7Pa0ScfviI= cwtch.im/cwtch v0.27.0/go.mod h1:A3i92aFuhyHI2DYO2Qnvl5iqEw0Cox22pdiypHnMOy4=
filippo.io/edwards25519 v1.0.0-rc.1/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= filippo.io/edwards25519 v1.0.0-rc.1/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns=
filippo.io/edwards25519 v1.0.0 h1:0wAIcmJUqRdI8IJ/3eGi5/HwXZWPujYXXlkrQogz0Ek= filippo.io/edwards25519 v1.0.0 h1:0wAIcmJUqRdI8IJ/3eGi5/HwXZWPujYXXlkrQogz0Ek=
filippo.io/edwards25519 v1.0.0/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= filippo.io/edwards25519 v1.0.0/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns=

View File

@ -3,22 +3,29 @@
echo "Checking code quality (you want to see no output here)" echo "Checking code quality (you want to see no output here)"
echo "" echo ""
echo "Vetting:"
go vet generate/*
echo "" echo ""
echo "Linting:" echo "Running staticcheck..."
staticcheck ./generate staticcheck lib.go
staticcheck ./utils/*
# In the future we should remove include-pkgs. However, there are a few false positives in the overall go stdlib that make this
# too noisy right now, specifically assigning nil to initialize slices (safe), and using go internal context channels assigned
# nil (also safe).
# We also have one file infinite_channel.go written in a way that static analysis cannot reason about easily. So it is explictly
# ignored.
echo "Running nilaway..."
nilaway -include-pkgs="git.openprivacy.ca/cwtch.im/cwtch-autobindings,cwtch.im/cwtch,cwtch.im/tapir,git.openprivacy.ca/openprivacy/connectivity" -exclude-errors-in-files="./templates/lib_template.go" -exclude-file-docstrings="nolint:nilaway" lib.go
nilaway -include-pkgs="git.openprivacy.ca/cwtch.im/cwtch-autobindings,cwtch.im/cwtch,cwtch.im/tapir,git.openprivacy.ca/openprivacy/connectivity" -exclude-errors-in-files="./templates/lib_template.go" -exclude-file-docstrings="nolint:nilaway" ./utils/
echo "Time to format" echo "Time to format"
gofmt -l -s -w . gofmt -l -s -w ./utils/*
gofmt -l -s -w ./generate/*
# ineffassign (https://github.com/gordonklaus/ineffassign) # ineffassign (https://github.com/gordonklaus/ineffassign)
echo "Checking for ineffectual assignment of errors (unchecked errors...)" # echo "Checking for ineffectual assignment of errors (unchecked errors...)"
ineffassign . # ineffassign .
# misspell (https://github.com/client9/misspell/cmd/misspell) # misspell (https://github.com/client9/misspell/cmd/misspell)
echo "Checking for misspelled words..." # echo "Checking for misspelled words..."
misspell . | grep -v "testing/" | grep -v "vendor/" | grep -v "go.sum" | grep -v ".idea" # misspell . | grep -v "testing/" | grep -v "vendor/" | grep -v "go.sum" | grep -v ".idea"

5
spec
View File

@ -22,6 +22,8 @@ profile UnblockConversation conversation
profile DeleteConversation conversation profile DeleteConversation conversation
profile PeerWithOnion string:handle profile PeerWithOnion string:handle
profile DisconnectFromPeer string:handle profile DisconnectFromPeer string:handle
(json-err)profile EnhancedGetConversationAccessControlList conversation
profile EnhancedUpdateConversationAccessControlList conversation string:json
# Search # Search
(json)profile SearchConversations string:pattern (json)profile SearchConversations string:pattern
@ -30,7 +32,7 @@ profile DisconnectFromPeer string:handle
(json)profile EnhancedSendMessage conversation string:msg (json)profile EnhancedSendMessage conversation string:msg
(json)profile EnhancedGetMessageById conversation message (json)profile EnhancedGetMessageById conversation message
(json)profile EnhancedGetMessageByContentHash conversation string:contentHash (json)profile EnhancedGetMessageByContentHash conversation string:contentHash
(json)profile EnhancedGetMessages conversation int:index int:count (json)profile EnhancedGetMessages conversation int:index uint:count
(json)profile EnhancedSendInviteMessage conversation conversation:target (json)profile EnhancedSendInviteMessage conversation conversation:target
profile UpdateMessageAttribute conversation channel message string:attributeKey string:attributeValue profile UpdateMessageAttribute conversation channel message string:attributeKey string:attributeValue
@ -41,6 +43,7 @@ profile DisconnectFromServer string:handle
## Server List Management... ## Server List Management...
import "cwtch.im/cwtch/functionality/servers" import "cwtch.im/cwtch/functionality/servers"
@profile-experiment PublishServerUpdate servers
@profile-experiment GetServerInfoList servers @profile-experiment GetServerInfoList servers
@profile-experiment DeleteServerInfo servers string:serverOnion @profile-experiment DeleteServerInfo servers string:serverOnion

View File

@ -22,6 +22,7 @@ import (
"runtime" "runtime"
"runtime/pprof" "runtime/pprof"
"strings" "strings"
"strconv"
"time" "time"
mrand "math/rand" mrand "math/rand"
"crypto/rand" "crypto/rand"
@ -189,7 +190,6 @@ func _startCwtch(appDir string, torPath string) {
log.Infof("libcwtch-go application launched") log.Infof("libcwtch-go application launched")
application.GetPrimaryBus().Publish(event.NewEvent(settings.CwtchStarted, map[event.Field]string{})) application.GetPrimaryBus().Publish(event.NewEvent(settings.CwtchStarted, map[event.Field]string{}))
application.QueryACNVersion() application.QueryACNVersion()
application.LoadProfiles(app.DefactoPasswordForUnencryptedProfiles)
{{EXPERIMENT_REGISTER}} {{EXPERIMENT_REGISTER}}
@ -247,7 +247,7 @@ func ReconnectCwtchForeground() {
settingsJson, _ := json.Marshal(application.ReadSettings()) settingsJson, _ := json.Marshal(application.ReadSettings())
application.GetPrimaryBus().Publish(event.NewEvent(settings.UpdateGlobalSettings, map[event.Field]string{event.Data: string(settingsJson)})) application.GetPrimaryBus().Publish(event.NewEvent(settings.UpdateGlobalSettings, map[event.Field]string{event.Data: string(settingsJson)}))
application.GetPrimaryBus().Publish(event.NewEvent(settings.CwtchStarted, map[event.Field]string{})) application.GetPrimaryBus().Publish(event.NewEvent(settings.CwtchStarted, map[event.Field]string{utils.ReloadEvent: event.True}))
application.QueryACNStatus() application.QueryACNStatus()
application.QueryACNVersion() application.QueryACNVersion()
} }
@ -442,7 +442,6 @@ const (
func buildACN(globalSettings settings.GlobalSettings, torPath string, appDir string) (connectivity.ACN, settings.GlobalSettings, error) { func buildACN(globalSettings settings.GlobalSettings, torPath string, appDir string) (connectivity.ACN, settings.GlobalSettings, error) {
mrand.Seed(int64(time.Now().Nanosecond()))
socksPort := mrand.Intn(1000) + 9600 socksPort := mrand.Intn(1000) + 9600
controlPort := socksPort + 1 controlPort := socksPort + 1
@ -471,7 +470,30 @@ func buildACN(globalSettings settings.GlobalSettings, torPath string, appDir str
// Override Ports if on Tails... // Override Ports if on Tails...
if cwtchTails := os.Getenv("CWTCH_TAILS"); strings.ToLower(cwtchTails) == "true" { if cwtchTails := os.Getenv("CWTCH_TAILS"); strings.ToLower(cwtchTails) == "true" {
log.Infof("CWTCH_TAILS environment variable set... overriding tor config...") log.Infof("CWTCH_TAILS environment variable set... overriding tor config...")
controlPort = 9051 controlPort = 9051
// In tails 5.13 the control port was changed to 951
// so read the Tails Version File and if it exists...
b, err := os.ReadFile("/etc/amnesia/version")
if err == nil {
// the file should start with the version followed
// by a space...
versionEnd := strings.Index(string(b), " ")
versionStr := string(b)[:versionEnd]
version, err := strconv.ParseFloat(versionStr, 64)
if err == nil {
log.Infof("Confirming Tails Version: %v", version)
// assert the control port if we are at the dedicated version...
// we know this change happened sometime after 5.11
if version >= 5.13 {
controlPort = 951
}
} else {
log.Errorf("Unable to confirm Tails version. CWTCH_TAILS options may not function correctly.")
}
}
socksPort = 9050 socksPort = 9050
globalSettings.CustomControlPort = controlPort globalSettings.CustomControlPort = controlPort
globalSettings.CustomSocksPort = socksPort globalSettings.CustomSocksPort = socksPort

View File

@ -200,7 +200,8 @@ func (eh *EventHandler) handleAppBusEvent(e *event.Event) string {
if conversationInfo.IsServer() { if conversationInfo.IsServer() {
groupHandler := servers.FunctionalityGate() groupHandler := servers.FunctionalityGate()
if err == nil { if err == nil {
knownServers = append(knownServers, groupHandler.GetServerInfo(profile, conversationInfo.Handle)) serverInfo, _ := groupHandler.GetServerInfo(profile, conversationInfo.Handle)
knownServers = append(knownServers, serverInfo)
} }
continue continue
} }
@ -223,7 +224,7 @@ func (eh *EventHandler) handleAppBusEvent(e *event.Event) string {
cpicPath = RandomGroupImage(conversationInfo.Handle) cpicPath = RandomGroupImage(conversationInfo.Handle)
defaultPath = RandomGroupImage(conversationInfo.Handle) defaultPath = RandomGroupImage(conversationInfo.Handle)
} else { } else {
cpicPath = GetProfileImage(profile, conversationInfo, settings.DownloadPath) cpicPath = eh.GetProfileImage(profile, conversationInfo, settings.DownloadPath)
defaultPath = RandomProfileImage(conversationInfo.Handle) defaultPath = RandomProfileImage(conversationInfo.Handle)
} }
@ -332,15 +333,17 @@ func (eh *EventHandler) handleAppBusEvent(e *event.Event) string {
return string(json) return string(json)
} }
func GetProfileImage(profile peer.CwtchPeer, conversationInfo *model.Conversation, basepath string) string { func (eh *EventHandler) GetProfileImage(profile peer.CwtchPeer, conversationInfo *model.Conversation, basepath string) string {
fileKey, err := profile.GetConversationAttribute(conversationInfo.ID, attr.PublicScope.ConstructScopedZonedPath(attr.ProfileZone.ConstructZonedPath(constants.CustomProfileImageKey))) if eh.app.IsFeatureEnabled(constants.ImagePreviewsExperiment) {
if err == nil { fileKey, err := profile.GetConversationAttribute(conversationInfo.ID, attr.PublicScope.ConstructScopedZonedPath(attr.ProfileZone.ConstructZonedPath(constants.CustomProfileImageKey)))
if value, exists := profile.GetScopedZonedAttribute(attr.LocalScope, attr.FilesharingZone, fmt.Sprintf("%s.complete", fileKey)); exists && value == event.True { if err == nil {
fp, _ := filesharing.GenerateDownloadPath(basepath, fileKey, true) if value, exists := profile.GetScopedZonedAttribute(attr.LocalScope, attr.FilesharingZone, fmt.Sprintf("%s.complete", fileKey)); exists && value == event.True {
// check if the file exists...if it does then set the path... fp, _ := filesharing.GenerateDownloadPath(basepath, fileKey, true)
if _, err := os.Stat(fp); err == nil { // check if the file exists...if it does then set the path...
image, _ := profile.GetScopedZonedAttribute(attr.LocalScope, attr.FilesharingZone, fmt.Sprintf("%s.path", fileKey)) if _, err := os.Stat(fp); err == nil {
return image image, _ := profile.GetScopedZonedAttribute(attr.LocalScope, attr.FilesharingZone, fmt.Sprintf("%s.path", fileKey))
return image
}
} }
} }
} }
@ -356,6 +359,10 @@ func (eh *EventHandler) handleProfileEvent(ev *EventProfileEnvelope) string {
log.Errorf("eh.app == nil in handleProfileEvent... this shouldnt happen?") log.Errorf("eh.app == nil in handleProfileEvent... this shouldnt happen?")
} else { } else {
profile := eh.app.GetPeer(ev.Profile) profile := eh.app.GetPeer(ev.Profile)
if profile == nil {
log.Errorf("something has gone very wrong. profile is nil in handleProfileEvent")
return ""
}
log.Debugf("New Profile Event to Handle: %v", ev) log.Debugf("New Profile Event to Handle: %v", ev)
switch ev.Event.EventType { switch ev.Event.EventType {
case event.NewMessageFromPeer: //event.TimestampReceived, event.RemotePeer, event.Data case event.NewMessageFromPeer: //event.TimestampReceived, event.RemotePeer, event.Data
@ -365,7 +372,7 @@ func (eh *EventHandler) handleProfileEvent(ev *EventProfileEnvelope) string {
if ci != nil && err == nil { if ci != nil && err == nil {
ev.Event.Data[event.ConversationID] = strconv.Itoa(ci.ID) ev.Event.Data[event.ConversationID] = strconv.Itoa(ci.ID)
profile.SetConversationAttribute(ci.ID, attr.LocalScope.ConstructScopedZonedPath(attr.ProfileZone.ConstructZonedPath(constants2.Archived)), event.False) profile.SetConversationAttribute(ci.ID, attr.LocalScope.ConstructScopedZonedPath(attr.ProfileZone.ConstructZonedPath(constants2.Archived)), event.False)
ev.Event.Data[constants2.Picture] = GetProfileImage(profile, ci, eh.app.ReadSettings().DownloadPath) ev.Event.Data[constants2.Picture] = eh.GetProfileImage(profile, ci, eh.app.ReadSettings().DownloadPath)
} else { } else {
// TODO This Conversation May Not Exist Yet...But we are not in charge of creating it... // TODO This Conversation May Not Exist Yet...But we are not in charge of creating it...
log.Errorf("todo wait for contact to be added before processing this event...") log.Errorf("todo wait for contact to be added before processing this event...")
@ -394,13 +401,17 @@ func (eh *EventHandler) handleProfileEvent(ev *EventProfileEnvelope) string {
ev.Event.Data["Nick"] = ev.Event.Data["RemotePeer"] ev.Event.Data["Nick"] = ev.Event.Data["RemotePeer"]
} }
} }
ev.Event.Data[constants2.Picture] = GetProfileImage(profile, ci, eh.app.ReadSettings().DownloadPath) ev.Event.Data[constants2.Picture] = eh.GetProfileImage(profile, ci, eh.app.ReadSettings().DownloadPath)
} }
conversationID, _ := strconv.Atoi(ev.Event.Data[event.ConversationID]) conversationID, _ := strconv.Atoi(ev.Event.Data[event.ConversationID])
profile.SetConversationAttribute(conversationID, attr.LocalScope.ConstructScopedZonedPath(attr.ProfileZone.ConstructZonedPath(constants2.Archived)), event.False) profile.SetConversationAttribute(conversationID, attr.LocalScope.ConstructScopedZonedPath(attr.ProfileZone.ConstructZonedPath(constants2.Archived)), event.False)
gci, _ := profile.GetConversationInfo(conversationID) gci, err := profile.GetConversationInfo(conversationID)
if err != nil {
log.Errorf("new message from non-existant group: %v", err)
break
}
groupServer := gci.Attributes[attr.LocalScope.ConstructScopedZonedPath(attr.LegacyGroupZone.ConstructZonedPath(constants.GroupServer)).ToString()] groupServer := gci.Attributes[attr.LocalScope.ConstructScopedZonedPath(attr.LegacyGroupZone.ConstructZonedPath(constants.GroupServer)).ToString()]
state := profile.GetPeerState(groupServer) state := profile.GetPeerState(groupServer)
// if syncing, don't flood with notifications // if syncing, don't flood with notifications
@ -419,11 +430,13 @@ func (eh *EventHandler) handleProfileEvent(ev *EventProfileEnvelope) string {
count, err := profile.GetChannelMessageCount(conversationID, 0) count, err := profile.GetChannelMessageCount(conversationID, 0)
if err != nil { if err != nil {
log.Errorf("error fetching channel message count %v %v", conversationID, err) log.Errorf("error fetching channel message count %v %v", conversationID, err)
break
} }
conversationInfo, err := profile.GetConversationInfo(conversationID) conversationInfo, err := profile.GetConversationInfo(conversationID)
if err != nil { if err != nil {
log.Errorf("error fetching conversation info for %v %v", conversationID, err) log.Errorf("error fetching conversation info for %v %v", conversationID, err)
break
} }
blocked := constants.False blocked := constants.False
@ -436,7 +449,11 @@ func (eh *EventHandler) handleProfileEvent(ev *EventProfileEnvelope) string {
accepted = constants.True accepted = constants.True
} }
acl, _ := json.Marshal(conversationInfo.ACL) acl, err := json.Marshal(conversationInfo.ACL)
if err != nil {
log.Errorf("received invalid ACL in conversation: %v", err)
break
}
lastMessage, _ := profile.GetMostRecentMessages(conversationID, 0, 0, 1) lastMessage, _ := profile.GetMostRecentMessages(conversationID, 0, 0, 1)
ev.Event.Data["unread"] = strconv.Itoa(count) // if this is a new contact with messages attached then by-definition these are unread... ev.Event.Data["unread"] = strconv.Itoa(count) // if this is a new contact with messages attached then by-definition these are unread...
@ -456,8 +473,16 @@ func (eh *EventHandler) handleProfileEvent(ev *EventProfileEnvelope) string {
groupPic := RandomGroupImage(ev.Event.Data[event.GroupID]) groupPic := RandomGroupImage(ev.Event.Data[event.GroupID])
ev.Event.Data[constants2.Picture] = groupPic ev.Event.Data[constants2.Picture] = groupPic
conversationID, _ := strconv.Atoi(ev.Event.Data[event.ConversationID]) conversationID, err := strconv.Atoi(ev.Event.Data[event.ConversationID])
conversationInfo, _ := profile.GetConversationInfo(conversationID) if err != nil {
log.Errorf("invalid conversation id recieved %v", err)
break
}
conversationInfo, err := profile.GetConversationInfo(conversationID)
if err != nil {
log.Errorf("error fetching conversation info for %v %v", conversationID, err)
break
}
acl, _ := json.Marshal(conversationInfo.ACL) acl, _ := json.Marshal(conversationInfo.ACL)
ev.Event.Data["accessControlList"] = string(acl) ev.Event.Data["accessControlList"] = string(acl)
case event.NewGroup: case event.NewGroup:
@ -468,51 +493,34 @@ func (eh *EventHandler) handleProfileEvent(ev *EventProfileEnvelope) string {
groupPic := RandomGroupImage(invite.GroupID) groupPic := RandomGroupImage(invite.GroupID)
ev.Event.Data[constants2.Picture] = groupPic ev.Event.Data[constants2.Picture] = groupPic
conversationID, _ := strconv.Atoi(ev.Event.Data[event.ConversationID]) conversationID, err := strconv.Atoi(ev.Event.Data[event.ConversationID])
conversationInfo, _ := profile.GetConversationInfo(conversationID) if err != nil {
acl, _ := json.Marshal(conversationInfo.ACL) log.Errorf("invalid conversation id recieved %v", err)
break
}
conversationInfo, err := profile.GetConversationInfo(conversationID)
if err != nil {
log.Errorf("error fetching conversation info for %v %v", conversationID, err)
break
}
acl, err := json.Marshal(conversationInfo.ACL)
ev.Event.Data["accessControlList"] = string(acl) ev.Event.Data["accessControlList"] = string(acl)
if err != nil {
log.Errorf("received invalid ACL in conversation: %v", err)
break
}
} else { } else {
log.Errorf("received a new group event which contained an invalid invite %v. this should never happen and likely means there is a bug in cwtch. Please file a ticket @ https://git.openprivacy.ca/cwtch.im/cwtch", err) log.Errorf("received a new group event which contained an invalid invite %v. this should never happen and likely means there is a bug in cwtch. Please file a ticket @ https://git.openprivacy.ca/cwtch.im/cwtch", err)
return "" return ""
} }
case event.PeerStateChange: case event.PeerStateChange:
cxnState := connections.ConnectionStateToType()[ev.Event.Data[event.ConnectionState]] cxnState := connections.ConnectionStateToType()[ev.Event.Data[event.ConnectionState]]
// skip events the UI doesn't act on
if cxnState == connections.CONNECTING || cxnState == connections.CONNECTED {
return ""
}
contact, err := profile.FetchConversationInfo(ev.Event.Data[event.RemotePeer])
if ev.Event.Data[event.RemotePeer] == profile.GetOnion() { if ev.Event.Data[event.RemotePeer] == profile.GetOnion() {
return "" // suppress events from our own profile... return "" // suppress events from our own profile...
} }
// We do not know who this is...don't send any event until we see a message from them
// (at that point the conversation will have been created...)
if contact == nil || err != nil || contact.ID == 0 {
return ""
}
// if we already know this state, suppress
if knownState, exists := contactStateCache[ev.Event.Data[event.RemotePeer]]; exists && cxnState == knownState {
return ""
}
contactStateCache[ev.Event.Data[event.RemotePeer]] = cxnState contactStateCache[ev.Event.Data[event.RemotePeer]] = cxnState
case event.ServerStateChange: case event.ServerStateChange:
cxnState := connections.ConnectionStateToType()[ev.Event.Data[event.ConnectionState]] cxnState := connections.ConnectionStateToType()[ev.Event.Data[event.ConnectionState]]
// skip events the UI doesn't act on
if cxnState == connections.CONNECTING || cxnState == connections.CONNECTED {
return ""
}
// if we already know this state, suppress
if knownState, exists := contactStateCache[ev.Event.Data[event.RemotePeer]]; exists && cxnState == knownState {
return ""
}
contactStateCache[ev.Event.Data[event.RemotePeer]] = cxnState contactStateCache[ev.Event.Data[event.RemotePeer]] = cxnState
case event.TokenManagerInfo: case event.TokenManagerInfo:
conversations, err := profile.FetchConversations() conversations, err := profile.FetchConversations()
@ -558,6 +566,10 @@ func unwrap(original *EventProfileEnvelope) *event.Event {
func (eh *EventHandler) startHandlingPeer(onion string) { func (eh *EventHandler) startHandlingPeer(onion string) {
eventBus := eh.app.GetEventBus(onion) eventBus := eh.app.GetEventBus(onion)
if eventBus == nil {
log.Errorf("could not start handling peer events .. event bus is nil")
return
}
q := event.NewQueue() q := event.NewQueue()
eventBus.Subscribe(event.NetworkStatus, q) eventBus.Subscribe(event.NetworkStatus, q)