Compare commits

...

42 Commits
v0.0.5 ... 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
Sarah Jamie Lewis 20dc170a78 Upgrade Cwtch
continuous-integration/drone/pr Build is pending Details
continuous-integration/drone/push Build is passing Details
2023-09-19 17:02:09 -07:00
Sarah Jamie Lewis 267e79368e Upgrade Cwtch, Log Errors for Experiments
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is passing Details
2023-09-19 13:05:08 -07:00
Sarah Jamie Lewis f93616615a Upgrade Cwtch
continuous-integration/drone/pr Build is pending Details
continuous-integration/drone/push Build is passing Details
2023-09-18 08:09:50 -07:00
Sarah Jamie Lewis 3e9c9c3b70 Use Constant from Cwtch
continuous-integration/drone/pr Build is running Details
continuous-integration/drone/push Build is passing Details
2023-09-13 11:52:11 -07:00
Sarah Jamie Lewis f60fbfc3d5 Upgrade Cwtch. Support Disconnection and Appearing Offline 2023-09-13 11:50:13 -07:00
Sarah Jamie Lewis f32ad741e0 Hashes
continuous-integration/drone/pr Build is running Details
continuous-integration/drone/push Build is passing Details
2023-08-31 11:56:41 -07:00
Sarah Jamie Lewis a453ca9dc8 Update Cwtch
continuous-integration/drone/pr Build is running Details
2023-08-31 11:55:02 -07:00
Sarah Jamie Lewis 3d2124126b Update
continuous-integration/drone/pr Build is running Details
continuous-integration/drone/push Build is passing Details
2023-08-22 14:06:27 -07:00
Sarah Jamie Lewis 0f40f0d12d Upgrade Cwtch Expose DeleteServerInfo
continuous-integration/drone/pr Build is failing Details
2023-08-22 13:27:09 -07:00
Sarah Jamie Lewis 6e0623170f Fix up Spec and Makefile
continuous-integration/drone/pr Build is running Details
continuous-integration/drone/push Build is passing Details
2023-08-02 13:12:53 -07:00
Sarah Jamie Lewis 6fdcf5bac7 Upgrade Cwtch
continuous-integration/drone/pr Build is pending Details
continuous-integration/drone/push Build is passing Details
2023-08-02 09:30:19 -07:00
Sarah Jamie Lewis ae18550f71 Upgrade Cwtch
continuous-integration/drone/pr Build is running Details
2023-07-27 11:09:54 -07:00
Sarah Jamie Lewis 988ec07ebc Correct Package name
continuous-integration/drone/pr Build is running Details
2023-07-25 14:54:59 -07:00
Sarah Jamie Lewis 44241e2352 Update Server Info
continuous-integration/drone/pr Build is running Details
2023-07-25 14:48:33 -07:00
Sarah Jamie Lewis 403398b7a1 Patch Makefile 2023-07-25 14:46:52 -07:00
Sarah Jamie Lewis 5916333723 Expose Search and new ServerList Functions 2023-07-25 14:46:09 -07:00
Dan Ballard 24b534d436 give makefile a concept of cross compiling, use conditionals to determin what it is, and if it can
continuous-integration/drone/pr Build is running Details
continuous-integration/drone/push Build is pending Details
2023-07-24 07:59:07 -07:00
Dan Ballard c8692cc1b2 use op golang x arm container 2023-07-23 17:02:32 -07:00
Dan Ballard dcec0f9274 add linux arm64 target 2023-07-23 17:02:32 -07:00
Sarah Jamie Lewis 2e7a9be6c1 Hashes
continuous-integration/drone/pr Build is running Details
continuous-integration/drone/push Build is passing Details
2023-07-13 19:54:33 +00:00
Sarah Jamie Lewis 7ebbfe91c9 Upgrade Cwtch 2023-07-13 19:54:33 +00:00
Sarah Jamie Lewis 3029ed65ff Add 'LICENSE'
continuous-integration/drone/pr Build is pending Details
continuous-integration/drone/push Build is pending Details
2023-06-16 21:26:36 +00:00
Sarah Jamie Lewis e91db69e6e Update 'README.md'
continuous-integration/drone/pr Build is pending Details
continuous-integration/drone/push Build is pending Details
2023-06-16 20:52:17 +00:00
16 changed files with 262 additions and 230 deletions

View File

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

9
LICENSE Normal file
View File

@ -0,0 +1,9 @@
MIT License
Copyright (c) 2023 Open Privacy Research Society
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -7,20 +7,28 @@ DEFAULT_GOAL: linux
all: linux android windows
linux: EXPERIMENTS ?= serverExperiment
linux: libCwtch.so
ARCH := $(shell uname -m)
ARM_X_CC := aarch64-linux-gnu-gcc
macos: EXPERIMENTS ?= serverExperiment
# determine if the x64 cross arm64 compiler is available so we can add that target
LINUX_X_ARM=
ifneq (,$(shell which $(ARM_X_CC)))
LINUX_X_ARM = libCwtch.x.so
endif
linux: EXPERIMENTS ?= "serverExperiment"
linux: libCwtch.so $(LINUX_X_ARM)
macos: EXPERIMENTS ?= "serverExperiment"
macos: libCwtch.x64.dylib libCwtch.arm64.dylib
android: EXPERIMENTS ?=
android: EXPERIMENTS ?= ""
android: cwtch.aar
windows: EXPERIMENTS ?= serverExperiment
windows: EXPERIMENTS ?= "serverExperiment"
windows: libCwtch.dll
lib.go: generate/generate_bindings.go spec
go run generate/generate_bindings.go --experiments "$(EXPERIMENTS)"
@ -29,18 +37,31 @@ libCwtch.so: lib.go
./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.so
mkdir -p build/linux
mv libCwtch.so build/linux/
mv libCwtch.h build/linux/
ifeq ($(ARCH),x86_64)
mv libCwtch.so build/linux/libCwtch.x64.so
else ifeq ($(ARCH),aarch64)
mv libCwtch.so build/linux/libCwtch.arm64.so
endif
mv libCwtch.h build/linux/libCwtch.h
libCwtch.x.so: lib.go
./switch-ffi.sh
mkdir -p build/linux
ifeq ($(ARCH),x86_64)
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.h build/linux/libCwtch.h
endif
libCwtch.x64.dylib: lib.go
./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
mv libCwtch.x64.dylib build/macos/
libCwtch.arm64.dylib: lib.go
./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
mv libCwtch.arm64.dylib build/macos/
@ -66,7 +87,7 @@ clean-autobindings:
rm -f lib.go
clean:
rm -fr lib.go cwtch.aar cwtch_go.apk libCwtch.h libCwtch.so cwtch-sources.jar libCwtch.dll libCwtch.*.dylib build
rm -fr lib.go cwtch.aar cwtch_go.apk libCwtch.*.h libCwtch.*.so cwtch-sources.jar libCwtch.dll libCwtch.*.dylib build
# iOS - for testing purposes only for now, not officially supported

View File

@ -10,8 +10,6 @@ Note for the Flutter-based Cwtch UI Application see: https://git.openprivacy.ca/
go run generate/generate_bindings.go
make linux // alternatively windows, android, macos
**NOTE:** Autobindings currently depends on an unreleased version of Cwtch (`cwtch.im/cwtch v0.18.10-0.20230221235514-49e0d849fa3e`).
### Experiments
Autobindings allow for comile time selection of experiments. Default selections for each target platform are supplied in Makefile but can be overridden with:
@ -61,6 +59,10 @@ Other directives:
- `LD_LIBRARY_PATH` set to point to `libCwtch.so`
- or drop a symlink into `/usr/lib`
### Cross compile arm 64
Needs `sudo apt install gcc-aarch64-linux-gnu`
## Android
- copy `cwtch.aar` into `flutter_app/android/cwtch`

View File

@ -13,8 +13,5 @@ const PeerOnline = "peer-online"
const PeerAutostart = "autostart"
// Description is used on server contacts,
const Description = "description"
// ConversationNotificationPolicy is the attribute label for conversations. When App NotificationPolicy is OptIn a true value here opts in
const ConversationNotificationPolicy = "notification-policy"

View File

@ -1,4 +1,4 @@
package servers
package server_hosting
import (
"cwtch.im/cwtch/app"

View File

@ -1,66 +0,0 @@
package groups
import (
"cwtch.im/cwtch/event"
"cwtch.im/cwtch/model"
"cwtch.im/cwtch/model/attr"
constants2 "cwtch.im/cwtch/model/constants"
"cwtch.im/cwtch/peer"
"cwtch.im/cwtch/protocol/connections"
"fmt"
"git.openprivacy.ca/cwtch.im/cwtch-autobindings/constants"
)
const groupExperiment = "tapir-groups-experiment"
const (
// ServerList is a json encoded list of servers
ServerList = event.Field("ServerList")
)
const (
// UpdateServerInfo is an event containing a ProfileOnion and a ServerList
UpdateServerInfo = event.Type("UpdateServerInfo")
)
// GroupFunctionality provides experiment gated server functionality
type GroupFunctionality struct {
}
// ExperimentGate returns GroupFunctionality if the experiment is enabled, and an error otherwise.
func ExperimentGate(experimentMap map[string]bool) (*GroupFunctionality, error) {
if experimentMap[groupExperiment] {
return new(GroupFunctionality), nil
}
return nil, fmt.Errorf("gated by %v", groupExperiment)
}
// GetServerInfoList compiles all the information the UI might need regarding all servers..
func (gf *GroupFunctionality) GetServerInfoList(profile peer.CwtchPeer) []Server {
var servers []Server
for _, server := range profile.GetServers() {
servers = append(servers, gf.GetServerInfo(server, profile))
}
return servers
}
// GetServerInfo compiles all the information the UI might need regarding a particular server including any verified
// cryptographic keys
func (gf *GroupFunctionality) GetServerInfo(serverOnion string, profile peer.CwtchPeer) Server {
serverInfo, _ := profile.FetchConversationInfo(serverOnion)
keyTypes := []model.KeyType{model.KeyTypeServerOnion, model.KeyTypeTokenOnion, model.KeyTypePrivacyPass}
var serverKeys []ServerKey
for _, keyType := range keyTypes {
if key, has := serverInfo.GetAttribute(attr.PublicScope, attr.ServerKeyZone, string(keyType)); has {
serverKeys = append(serverKeys, ServerKey{Type: string(keyType), Key: key})
}
}
description, _ := serverInfo.GetAttribute(attr.LocalScope, attr.ServerZone, constants.Description)
startTimeStr := serverInfo.Attributes[attr.LocalScope.ConstructScopedZonedPath(attr.LegacyGroupZone.ConstructZonedPath(constants2.SyncPreLastMessageTime)).ToString()]
recentTimeStr := serverInfo.Attributes[attr.LocalScope.ConstructScopedZonedPath(attr.LegacyGroupZone.ConstructZonedPath(constants2.SyncMostRecentMessageTime)).ToString()]
syncStatus := SyncStatus{startTimeStr, recentTimeStr}
return Server{Onion: serverOnion, Identifier: serverInfo.ID, Status: connections.ConnectionStateName[profile.GetPeerState(serverInfo.Handle)], Keys: serverKeys, Description: description, SyncProgress: syncStatus}
}

View File

@ -1,23 +0,0 @@
package groups
import "testing"
func TestGroupFunctionality_IsEnabled(t *testing.T) {
_, err := ExperimentGate(map[string]bool{})
if err == nil {
t.Fatalf("group functionality should be disabled")
}
_, err = ExperimentGate(map[string]bool{groupExperiment: true})
if err != nil {
t.Fatalf("group functionality should be enabled")
}
_, err = ExperimentGate(map[string]bool{groupExperiment: false})
if err == nil {
t.Fatalf("group functionality should be disabled")
}
}

View File

@ -1,20 +0,0 @@
package groups
type ServerKey struct {
Type string `json:"type"`
Key string `json:"key"`
}
type SyncStatus struct {
StartTime string `json:"startTime"`
LastMessageTime string `json:"lastMessageTime"`
}
type Server struct {
Onion string `json:"onion"`
Identifier int `json:"identifier"`
Status string `json:"status"`
Description string `json:"description"`
Keys []ServerKey `json:"keys"`
SyncProgress SyncStatus `json:"syncProgress"`
}

View File

@ -96,7 +96,9 @@ func main() {
case "profile":
generatedBindings = generateProfileFunction(generatedBindings, fName, args)
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":
experiment := args[0]
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
}
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) {
return intArgPrototype(varName)
}
@ -235,7 +241,7 @@ func mapArgs(argsTypes []string) (string, string, string, string) {
gUse = append(gUse, c4)
case "int":
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)
}
c1, c2, c3, c4 := intArgPrototype(argTypeParts[1])
@ -243,6 +249,20 @@ func mapArgs(argsTypes []string) (string, string, string, string) {
c2GoArgs = append(c2GoArgs, c2)
goSpec = append(goSpec, c3)
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":
if len(argTypeParts) != 2 {
fmt.Printf("generic string arg must have have e.g. string:<name>\n")
@ -364,7 +384,7 @@ func {{FNAME}}({{GO_ARGS_SPEC}}) {
return bindings
}
func generateJsonProfileFunction(bindings string, name string, argsTypes []string) string {
func generateJsonProfileFunction(bindings string, name string, argsTypes []string, handleErr bool) string {
appPrototype := `
//export c_{{FNAME}}
func c_{{FNAME}}({{C_ARGS}}) *C.char {
@ -374,14 +394,26 @@ func c_{{FNAME}}({{C_ARGS}}) *C.char {
func {{FNAME}}({{GO_ARGS_SPEC}}) string {
cwtchProfile := application.GetPeer(profile)
if cwtchProfile != nil {
return cwtchProfile.{{LIBNAME}}({{GO_ARG}})
{{HANDLE_FUNC}}
}
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)
appPrototype = strings.ReplaceAll(appPrototype, "{{HANDLE_FUNC}}", functionPrototype)
appPrototype = strings.ReplaceAll(appPrototype, "{{FNAME}}", strings.TrimPrefix(name, "Enhanced"))
appPrototype = strings.ReplaceAll(appPrototype, "{{LIBNAME}}", name)
// We need to prepend a set of profile handle arguments...
@ -407,7 +439,10 @@ func {{FNAME}}({{GO_ARGS_SPEC}}) {
if cwtchProfile != nil {
functionality := {{EXPERIMENT}}.FunctionalityGate()
if functionality != nil {
functionality.{{LIBNAME}}(cwtchProfile, {{GO_ARG}})
err := functionality.{{LIBNAME}}(cwtchProfile, {{GO_ARG}})
if err != nil {
log.Errorf("error calling experimental feature {{FNAME}}: %v", err)
}
}
}
}

7
go.mod
View File

@ -1,11 +1,11 @@
module git.openprivacy.ca/cwtch.im/cwtch-autobindings
go 1.19
go 1.20
require (
cwtch.im/cwtch v0.20.8
cwtch.im/cwtch v0.27.0
git.openprivacy.ca/cwtch.im/server v1.4.5
git.openprivacy.ca/openprivacy/connectivity v1.10.0
git.openprivacy.ca/openprivacy/connectivity v1.11.0
git.openprivacy.ca/openprivacy/log v1.0.3
github.com/mutecomm/go-sqlcipher/v4 v4.4.2
)
@ -24,5 +24,4 @@ require (
golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b // indirect
golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64 // indirect
golang.org/x/tools v0.1.12 // indirect
)

8
go.sum
View File

@ -1,6 +1,6 @@
cwtch.im/cwtch v0.18.0/go.mod h1:StheazFFY7PKqBbEyDVLhzWW6WOat41zV0ckC240c5Y=
cwtch.im/cwtch v0.20.8 h1:5N95p6uYquu9Vj2E9jK41FJpa679h1oYfiv/2jm5gbA=
cwtch.im/cwtch v0.20.8/go.mod h1:h8S7EgEM+8pE1k+XLB5jAFdIPlOzwoXEY0GH5mQye5A=
cwtch.im/cwtch v0.27.0 h1:MkNIZ+pT5ZwiGlKHk20GMUTlzBsmCWJEibbj6hr+WHw=
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 h1:0wAIcmJUqRdI8IJ/3eGi5/HwXZWPujYXXlkrQogz0Ek=
filippo.io/edwards25519 v1.0.0/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns=
@ -13,8 +13,8 @@ git.openprivacy.ca/openprivacy/bine v0.0.4/go.mod h1:13ZqhKyqakDsN/ZkQkIGNULsmLy
git.openprivacy.ca/openprivacy/bine v0.0.5 h1:DJs5gqw3SkvLSgRDvroqJxZ7F+YsbxbBRg5t0rU5gYE=
git.openprivacy.ca/openprivacy/bine v0.0.5/go.mod h1:fwdeq6RO08WDkV0k7HfArsjRvurVULoUQmT//iaABZM=
git.openprivacy.ca/openprivacy/connectivity v1.8.6/go.mod h1:Hn1gpOx/bRZp5wvCtPQVJPXrfeUH0EGiG/Aoa0vjGLg=
git.openprivacy.ca/openprivacy/connectivity v1.10.0 h1:7P5xdFL4mGg9bwlIY+sdaNGUMazlMB82/v/6kXlvqxY=
git.openprivacy.ca/openprivacy/connectivity v1.10.0/go.mod h1:OQO1+7OIz/jLxDrorEMzvZA6SEbpbDyLGpjoFqT3z1Y=
git.openprivacy.ca/openprivacy/connectivity v1.11.0 h1:roASjaFtQLu+HdH5fa2wx6F00NL3YsUTlmXBJh8aLZk=
git.openprivacy.ca/openprivacy/connectivity v1.11.0/go.mod h1:OQO1+7OIz/jLxDrorEMzvZA6SEbpbDyLGpjoFqT3z1Y=
git.openprivacy.ca/openprivacy/log v1.0.3 h1:E/PMm4LY+Q9s3aDpfySfEDq/vYQontlvNj/scrPaga0=
git.openprivacy.ca/openprivacy/log v1.0.3/go.mod h1:gGYK8xHtndRLDymFtmjkG26GaMQNgyhioNS82m812Iw=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=

View File

@ -3,22 +3,29 @@
echo "Checking code quality (you want to see no output here)"
echo ""
echo "Vetting:"
go vet generate/*
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"
gofmt -l -s -w .
gofmt -l -s -w ./utils/*
gofmt -l -s -w ./generate/*
# ineffassign (https://github.com/gordonklaus/ineffassign)
echo "Checking for ineffectual assignment of errors (unchecked errors...)"
ineffassign .
# echo "Checking for ineffectual assignment of errors (unchecked errors...)"
# ineffassign .
# misspell (https://github.com/client9/misspell/cmd/misspell)
echo "Checking for misspelled words..."
misspell . | grep -v "testing/" | grep -v "vendor/" | grep -v "go.sum" | grep -v ".idea"
# echo "Checking for misspelled words..."
# misspell . | grep -v "testing/" | grep -v "vendor/" | grep -v "go.sum" | grep -v ".idea"

21
spec
View File

@ -3,6 +3,7 @@
# Peer Engine
app ActivatePeerEngine profile
app DeactivatePeerEngine profile
app ConfigureConnections profile bool:listen bool:peers bool:servers
# Profile Management
app CreateProfile name password bool:autostart
@ -20,17 +21,31 @@ profile BlockConversation conversation
profile UnblockConversation conversation
profile DeleteConversation conversation
profile PeerWithOnion string:handle
profile DisconnectFromPeer string:handle
(json-err)profile EnhancedGetConversationAccessControlList conversation
profile EnhancedUpdateConversationAccessControlList conversation string:json
# Search
(json)profile SearchConversations string:pattern
# Message Management
(json)profile EnhancedSendMessage conversation string:msg
(json)profile EnhancedGetMessageById conversation message
(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
profile UpdateMessageAttribute conversation channel message string:attributeKey string:attributeValue
# Group Management
profile StartGroup string:name string:server
profile QueueJoinServer string:handle
profile DisconnectFromServer string:handle
## Server List Management...
import "cwtch.im/cwtch/functionality/servers"
@profile-experiment PublishServerUpdate servers
@profile-experiment GetServerInfoList servers
@profile-experiment DeleteServerInfo servers string:serverOnion
# Filesharing Management
import "cwtch.im/cwtch/functionality/filesharing"
@ -44,8 +59,8 @@ import "cwtch.im/cwtch/functionality/filesharing"
# Server Hosting Experiment
!serverExperiment import "git.openprivacy.ca/cwtch.im/cwtch-autobindings/experiments/servers"
!serverExperiment global serverExperiment *servers.ServersFunctionality servers
!serverExperiment import "git.openprivacy.ca/cwtch.im/cwtch-autobindings/experiments/server_hosting"
!serverExperiment global serverExperiment *server_hosting.ServersFunctionality server_hosting
!serverExperiment exp CreateServer application password string:description bool:autostart
!serverExperiment exp SetServerAttribute application string:handle string:key string:val
!serverExperiment exp LoadServers application acn password

View File

@ -22,6 +22,7 @@ import (
"runtime"
"runtime/pprof"
"strings"
"strconv"
"time"
mrand "math/rand"
"crypto/rand"
@ -189,7 +190,6 @@ func _startCwtch(appDir string, torPath string) {
log.Infof("libcwtch-go application launched")
application.GetPrimaryBus().Publish(event.NewEvent(settings.CwtchStarted, map[event.Field]string{}))
application.QueryACNVersion()
application.LoadProfiles(app.DefactoPasswordForUnencryptedProfiles)
{{EXPERIMENT_REGISTER}}
@ -247,7 +247,7 @@ func ReconnectCwtchForeground() {
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.CwtchStarted, map[event.Field]string{}))
application.GetPrimaryBus().Publish(event.NewEvent(settings.CwtchStarted, map[event.Field]string{utils.ReloadEvent: event.True}))
application.QueryACNStatus()
application.QueryACNVersion()
}
@ -314,6 +314,8 @@ func SetProfileAttribute(profileOnion string, key string, value string) {
profile.SetScopedZonedAttribute(attr.PublicScope, attr.ProfileZone, constants.ProfileStatus, value)
} else if zone == attr.ProfileZone && key == constants.PeerAutostart {
profile.SetScopedZonedAttribute(attr.LocalScope, attr.ProfileZone, constants.PeerAutostart, value)
} else if zone == attr.ProfileZone && key == constants.PeerAppearOffline {
profile.SetScopedZonedAttribute(attr.LocalScope, attr.ProfileZone, constants.PeerAppearOffline, value)
} else {
log.Errorf("attempted to set an attribute with an unknown zone: %v", key)
}
@ -440,7 +442,6 @@ const (
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
controlPort := socksPort + 1
@ -469,7 +470,30 @@ func buildACN(globalSettings settings.GlobalSettings, torPath string, appDir str
// Override Ports if on Tails...
if cwtchTails := os.Getenv("CWTCH_TAILS"); strings.ToLower(cwtchTails) == "true" {
log.Infof("CWTCH_TAILS environment variable set... overriding tor config...")
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
globalSettings.CustomControlPort = controlPort
globalSettings.CustomSocksPort = socksPort

View File

@ -1,23 +1,22 @@
package utils
import (
"cwtch.im/cwtch/settings"
"encoding/json"
"fmt"
"git.openprivacy.ca/cwtch.im/cwtch-autobindings/experiments/servers"
"os"
"strconv"
"cwtch.im/cwtch/app"
"cwtch.im/cwtch/app/plugins"
"cwtch.im/cwtch/functionality/servers"
"cwtch.im/cwtch/model"
"cwtch.im/cwtch/model/attr"
"cwtch.im/cwtch/model/constants"
"cwtch.im/cwtch/peer"
"cwtch.im/cwtch/protocol/connections"
"cwtch.im/cwtch/settings"
"encoding/json"
"fmt"
constants2 "git.openprivacy.ca/cwtch.im/cwtch-autobindings/constants"
"git.openprivacy.ca/cwtch.im/cwtch-autobindings/features/groups"
"git.openprivacy.ca/cwtch.im/cwtch-autobindings/experiments/server_hosting"
"git.openprivacy.ca/openprivacy/log"
"os"
"strconv"
"time"
@ -66,10 +65,10 @@ func (eh *EventHandler) HandleApp(application app.Application) {
application.GetPrimaryBus().Subscribe(event.ACNVersion, eh.appBusQueue)
application.GetPrimaryBus().Subscribe(settings.UpdateGlobalSettings, eh.appBusQueue)
application.GetPrimaryBus().Subscribe(settings.CwtchStarted, eh.appBusQueue)
application.GetPrimaryBus().Subscribe(servers.NewServer, eh.appBusQueue)
application.GetPrimaryBus().Subscribe(servers.ServerIntentUpdate, eh.appBusQueue)
application.GetPrimaryBus().Subscribe(servers.ServerDeleted, eh.appBusQueue)
application.GetPrimaryBus().Subscribe(servers.ServerStatsUpdate, eh.appBusQueue)
application.GetPrimaryBus().Subscribe(server_hosting.NewServer, eh.appBusQueue)
application.GetPrimaryBus().Subscribe(server_hosting.ServerIntentUpdate, eh.appBusQueue)
application.GetPrimaryBus().Subscribe(server_hosting.ServerDeleted, eh.appBusQueue)
application.GetPrimaryBus().Subscribe(server_hosting.ServerStatsUpdate, eh.appBusQueue)
application.GetPrimaryBus().Subscribe(event.StartingStorageMiragtion, eh.appBusQueue)
application.GetPrimaryBus().Subscribe(event.DoneStorageMigration, eh.appBusQueue)
}
@ -146,9 +145,15 @@ func (eh *EventHandler) handleAppBusEvent(e *event.Event) string {
// Start up the Profile
if acnStatus == 100 {
autostart, exists := profile.GetScopedZonedAttribute(attr.LocalScope, attr.ProfileZone, constants2.PeerAutostart)
autostart, exists := profile.GetScopedZonedAttribute(attr.LocalScope, attr.ProfileZone, constants.PeerAutostart)
appearOffline, appearOfflineExists := profile.GetScopedZonedAttribute(attr.LocalScope, attr.ProfileZone, constants.PeerAppearOffline)
if !exists || autostart == "true" {
eh.app.ActivatePeerEngine(onion)
if appearOfflineExists && appearOffline == "true" {
// don't configure any connections...
} else {
eh.app.ConfigureConnections(onion, true, true, true)
}
}
}
@ -162,6 +167,13 @@ func (eh *EventHandler) handleAppBusEvent(e *event.Event) string {
}
e.Data["autostart"] = autostart
appearOffline, exists := profile.GetScopedZonedAttribute(attr.LocalScope, attr.ProfileZone, constants.PeerAppearOffline)
// legacy profiles should not appearOffline by default
if !exists {
appearOffline = "false"
}
e.Data["appearOffline"] = appearOffline
// Name always exists
e.Data[constants.Name], _ = profile.GetScopedZonedAttribute(attr.PublicScope, attr.ProfileZone, constants.Name)
e.Data[constants2.DefaultProfilePicture] = RandomProfileImage(onion)
@ -174,7 +186,7 @@ func (eh *EventHandler) handleAppBusEvent(e *event.Event) string {
}
// Construct our conversations and our srever lists
var contacts []Contact
var servers []groups.Server
var knownServers []servers.Server
conversations, err := profile.FetchConversations()
@ -186,9 +198,10 @@ func (eh *EventHandler) handleAppBusEvent(e *event.Event) string {
// has been disabled and then is later re-enabled. As such we need to ensure that this list is
// re-fetched when the group experiment is enabled via a dedicated ListServerInfo event...
if conversationInfo.IsServer() {
groupHandler, err := groups.ExperimentGate(eh.app.ReadSettings().Experiments)
groupHandler := servers.FunctionalityGate()
if err == nil {
servers = append(servers, groupHandler.GetServerInfo(conversationInfo.Handle, profile))
serverInfo, _ := groupHandler.GetServerInfo(profile, conversationInfo.Handle)
knownServers = append(knownServers, serverInfo)
}
continue
}
@ -211,7 +224,7 @@ func (eh *EventHandler) handleAppBusEvent(e *event.Event) string {
cpicPath = RandomGroupImage(conversationInfo.Handle)
defaultPath = RandomGroupImage(conversationInfo.Handle)
} else {
cpicPath = GetProfileImage(profile, conversationInfo, settings.DownloadPath)
cpicPath = eh.GetProfileImage(profile, conversationInfo, settings.DownloadPath)
defaultPath = RandomProfileImage(conversationInfo.Handle)
}
@ -309,8 +322,8 @@ func (eh *EventHandler) handleAppBusEvent(e *event.Event) string {
e.Data["ContactsJson"] = string(bytes)
// Marshal the server list into the new peer event...
serversListBytes, _ := json.Marshal(servers)
e.Data[groups.ServerList] = string(serversListBytes)
serversListBytes, _ := json.Marshal(knownServers)
e.Data[servers.ServerList] = string(serversListBytes)
log.Debugf("contactsJson %v", e.Data["ContactsJson"])
}
@ -320,15 +333,17 @@ func (eh *EventHandler) handleAppBusEvent(e *event.Event) string {
return string(json)
}
func 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 err == nil {
if value, exists := profile.GetScopedZonedAttribute(attr.LocalScope, attr.FilesharingZone, fmt.Sprintf("%s.complete", fileKey)); exists && value == event.True {
fp, _ := filesharing.GenerateDownloadPath(basepath, fileKey, true)
// check if the file exists...if it does then set the path...
if _, err := os.Stat(fp); err == nil {
image, _ := profile.GetScopedZonedAttribute(attr.LocalScope, attr.FilesharingZone, fmt.Sprintf("%s.path", fileKey))
return image
func (eh *EventHandler) GetProfileImage(profile peer.CwtchPeer, conversationInfo *model.Conversation, basepath string) string {
if eh.app.IsFeatureEnabled(constants.ImagePreviewsExperiment) {
fileKey, err := profile.GetConversationAttribute(conversationInfo.ID, attr.PublicScope.ConstructScopedZonedPath(attr.ProfileZone.ConstructZonedPath(constants.CustomProfileImageKey)))
if err == nil {
if value, exists := profile.GetScopedZonedAttribute(attr.LocalScope, attr.FilesharingZone, fmt.Sprintf("%s.complete", fileKey)); exists && value == event.True {
fp, _ := filesharing.GenerateDownloadPath(basepath, fileKey, true)
// check if the file exists...if it does then set the path...
if _, err := os.Stat(fp); err == nil {
image, _ := profile.GetScopedZonedAttribute(attr.LocalScope, attr.FilesharingZone, fmt.Sprintf("%s.path", fileKey))
return image
}
}
}
}
@ -344,6 +359,10 @@ func (eh *EventHandler) handleProfileEvent(ev *EventProfileEnvelope) string {
log.Errorf("eh.app == nil in handleProfileEvent... this shouldnt happen?")
} else {
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)
switch ev.Event.EventType {
case event.NewMessageFromPeer: //event.TimestampReceived, event.RemotePeer, event.Data
@ -353,7 +372,7 @@ func (eh *EventHandler) handleProfileEvent(ev *EventProfileEnvelope) string {
if ci != nil && err == nil {
ev.Event.Data[event.ConversationID] = strconv.Itoa(ci.ID)
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 {
// 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...")
@ -382,13 +401,17 @@ func (eh *EventHandler) handleProfileEvent(ev *EventProfileEnvelope) string {
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])
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()]
state := profile.GetPeerState(groupServer)
// if syncing, don't flood with notifications
@ -407,11 +430,13 @@ func (eh *EventHandler) handleProfileEvent(ev *EventProfileEnvelope) string {
count, err := profile.GetChannelMessageCount(conversationID, 0)
if err != nil {
log.Errorf("error fetching channel message count %v %v", conversationID, err)
break
}
conversationInfo, err := profile.GetConversationInfo(conversationID)
if err != nil {
log.Errorf("error fetching conversation info for %v %v", conversationID, err)
break
}
blocked := constants.False
@ -424,7 +449,11 @@ func (eh *EventHandler) handleProfileEvent(ev *EventProfileEnvelope) string {
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)
ev.Event.Data["unread"] = strconv.Itoa(count) // if this is a new contact with messages attached then by-definition these are unread...
@ -444,8 +473,16 @@ func (eh *EventHandler) handleProfileEvent(ev *EventProfileEnvelope) string {
groupPic := RandomGroupImage(ev.Event.Data[event.GroupID])
ev.Event.Data[constants2.Picture] = groupPic
conversationID, _ := strconv.Atoi(ev.Event.Data[event.ConversationID])
conversationInfo, _ := profile.GetConversationInfo(conversationID)
conversationID, err := strconv.Atoi(ev.Event.Data[event.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)
ev.Event.Data["accessControlList"] = string(acl)
case event.NewGroup:
@ -456,51 +493,34 @@ func (eh *EventHandler) handleProfileEvent(ev *EventProfileEnvelope) string {
groupPic := RandomGroupImage(invite.GroupID)
ev.Event.Data[constants2.Picture] = groupPic
conversationID, _ := strconv.Atoi(ev.Event.Data[event.ConversationID])
conversationInfo, _ := profile.GetConversationInfo(conversationID)
acl, _ := json.Marshal(conversationInfo.ACL)
conversationID, err := strconv.Atoi(ev.Event.Data[event.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, err := json.Marshal(conversationInfo.ACL)
ev.Event.Data["accessControlList"] = string(acl)
if err != nil {
log.Errorf("received invalid ACL in conversation: %v", err)
break
}
} 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)
return ""
}
case event.PeerStateChange:
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() {
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
case event.ServerStateChange:
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
case event.TokenManagerInfo:
conversations, err := profile.FetchConversations()
@ -546,6 +566,10 @@ func unwrap(original *EventProfileEnvelope) *event.Event {
func (eh *EventHandler) startHandlingPeer(onion string) {
eventBus := eh.app.GetEventBus(onion)
if eventBus == nil {
log.Errorf("could not start handling peer events .. event bus is nil")
return
}
q := event.NewQueue()
eventBus.Subscribe(event.NetworkStatus, q)
@ -572,6 +596,9 @@ func (eh *EventHandler) startHandlingPeer(onion string) {
eventBus.Subscribe(event.FileDownloaded, q)
eventBus.Subscribe(event.TokenManagerInfo, q)
eventBus.Subscribe(event.ProtocolEngineCreated, q)
eventBus.Subscribe(event.SearchResult, q)
eventBus.Subscribe(event.SearchCancelled, q)
eventBus.Subscribe(servers.UpdateServerInfo, q)
go eh.forwardProfileMessages(onion, q)
}