ios: Add a EULA to try to appease Apple's Guideline 1.2 - Safety - User-Generated Content.
All checks were successful
Build Tilde Friends / Build-All (push) Successful in 22m0s

This commit is contained in:
2025-11-02 14:30:25 -05:00
parent 24f0cdb398
commit 7879ab1d50
12 changed files with 305 additions and 82 deletions

View File

@@ -18,7 +18,7 @@ MAKEFLAGS += --no-builtin-rules
VERSION_CODE := 45
VERSION_CODE_IOS := 19
VERSION_NUMBER := 0.2026.11-wip
VERSION_NUMBER := 0.2026.10.1
VERSION_NAME := This program kills fascists.
IPHONEOS_VERSION_MIN=14.0
@@ -876,6 +876,10 @@ src/version.h : $(firstword $(MAKEFILE_LIST))
@echo "#define VERSION_NUMBER \"$(VERSION_NUMBER)\"" > $@
@echo "#define VERSION_NAME \"$(VERSION_NAME)\"" >> $@
src/eula.h : core/eula.html
@echo "[xxd] $@"
@xxd -i -n k_eula $< $@
src/android/AndroidManifest.xml : $(firstword $(MAKEFILE_LIST))
@echo "[android_version] $@"
@sed -i \

67
core/eula.html Normal file
View File

@@ -0,0 +1,67 @@
<!doctype html>
<html>
<head>
<title>Tilde Friends End User License Agreement</title>
<link type="text/css" rel="stylesheet" href="/static/w3.css" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
</head>
<body class="w3-content">
<h1>Tilde Friends End User License Agreement</h1>
<p>
Tilde Friends is an app that enables communication with other users
through the
<a href="https://ssbc.github.io/scuttlebutt-protocol-guide/"
>Secure Scuttlebutt</a
>
protocol.
</p>
<h2>You are responsible for your actions</h2>
<p>
Apple tolerates no objectionable content or abusive users on their
platforms.
</p>
<p>
Your government, employer, family, friend group, etc. may impose
additional restrictions on acceptable behavior that you may be expected to
follow.
</p>
<p>
You are solely responsible for your own actions within this app,
especially but not limited to what content you choose to post.
</p>
<h2>You choose what you see</h2>
<p>
You are in full control of the content you see in Tilde Friends by the
peers to which you choose to connect and the users you choose to follow.
Initially you will be following no one with no connections and as a result
see no content from other users.
</p>
<p>
If you find some content objectionable, you can filter it from your view
by blocking the user who posted it. This also makes it so that users
following you will not see it as a result of following you.
</p>
<p>
The <code>admin</code> app contains a variety of settings that control the
types of connections Tilde Friends will make or accept, including whether
the app will even accept or make connections at all.
</p>
<h2>This app is not a service</h2>
<p>
This app relies on no official servers. The author of this app has no more
ability to see or filter what you post or read than any other user of the
network.
</p>
<p>
If you believe objectionable content obtained from a service that is
running as part of the Secure Scuttlebutt network should be flagged, look
for an email address contact for the service, generally by accessing the
server address in a web browser, and report it to the operator.
</p>
<h2>Agree with these terms?</h2>
<p>If you do not accept these terms, do not use this app.</p>
<div class="w3-bar w3-center">
<a class="w3-button w3-blue" href="/eula/accept">Accept Agreement</a>
</div>
</body>
</html>

View File

@@ -60,6 +60,7 @@ options:
broadcast (default: true): Send network discovery broadcasts.
discovery (default: true): Receive network discovery broadcasts.
stay_connected (default: false): Whether to attempt to keep several peer connections open.
accepted_eula_crc (default: 0): The CRC32 of the last accepted EULA.
-o, --one-proc Run everything in one process (unsafely!).
-z, --zip path Zip archive from which to load files.
-v, --verbose Log raw messages.

View File

@@ -2,7 +2,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.unprompted.tildefriends"
android:versionCode="45"
android:versionName="0.2026.11-wip">
android:versionName="0.2026.10.1">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<application

88
src/eula.h Normal file
View File

@@ -0,0 +1,88 @@
unsigned char k_eula[] = { 0x3c, 0x21, 0x64, 0x6f, 0x63, 0x74, 0x79, 0x70, 0x65, 0x20, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0x0a, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0x0a, 0x09, 0x3c,
0x68, 0x65, 0x61, 0x64, 0x3e, 0x0a, 0x09, 0x09, 0x3c, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0x54, 0x69, 0x6c, 0x64, 0x65, 0x20, 0x46, 0x72, 0x69, 0x65, 0x6e, 0x64, 0x73, 0x20,
0x45, 0x6e, 0x64, 0x20, 0x55, 0x73, 0x65, 0x72, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x41, 0x67, 0x72, 0x65, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x3c, 0x2f, 0x74,
0x69, 0x74, 0x6c, 0x65, 0x3e, 0x0a, 0x09, 0x09, 0x3c, 0x6c, 0x69, 0x6e, 0x6b, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x22, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x63, 0x73, 0x73, 0x22,
0x20, 0x72, 0x65, 0x6c, 0x3d, 0x22, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x73, 0x68, 0x65, 0x65, 0x74, 0x22, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x2f, 0x73, 0x74, 0x61, 0x74,
0x69, 0x63, 0x2f, 0x77, 0x33, 0x2e, 0x63, 0x73, 0x73, 0x22, 0x20, 0x2f, 0x3e, 0x0a, 0x09, 0x09, 0x3c, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76,
0x69, 0x65, 0x77, 0x70, 0x6f, 0x72, 0x74, 0x22, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x3d, 0x22, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x64, 0x65, 0x76, 0x69, 0x63,
0x65, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x2c, 0x20, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x2d, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x3d, 0x31, 0x22, 0x20, 0x2f, 0x3e, 0x0a,
0x09, 0x3c, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x3e, 0x0a, 0x09, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x77, 0x33, 0x2d, 0x63, 0x6f, 0x6e,
0x74, 0x65, 0x6e, 0x74, 0x22, 0x3e, 0x0a, 0x09, 0x09, 0x3c, 0x68, 0x31, 0x3e, 0x54, 0x69, 0x6c, 0x64, 0x65, 0x20, 0x46, 0x72, 0x69, 0x65, 0x6e, 0x64, 0x73, 0x20, 0x45, 0x6e,
0x64, 0x20, 0x55, 0x73, 0x65, 0x72, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x41, 0x67, 0x72, 0x65, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x3c, 0x2f, 0x68, 0x31, 0x3e,
0x0a, 0x09, 0x09, 0x3c, 0x70, 0x3e, 0x0a, 0x09, 0x09, 0x09, 0x54, 0x69, 0x6c, 0x64, 0x65, 0x20, 0x46, 0x72, 0x69, 0x65, 0x6e, 0x64, 0x73, 0x20, 0x69, 0x73, 0x20, 0x61, 0x6e,
0x20, 0x61, 0x70, 0x70, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61, 0x74, 0x69,
0x6f, 0x6e, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x75, 0x73, 0x65, 0x72, 0x73, 0x0a, 0x09, 0x09, 0x09, 0x74, 0x68, 0x72, 0x6f, 0x75, 0x67,
0x68, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x09, 0x09, 0x09, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x73, 0x73, 0x62,
0x63, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x69, 0x6f, 0x2f, 0x73, 0x63, 0x75, 0x74, 0x74, 0x6c, 0x65, 0x62, 0x75, 0x74, 0x74, 0x2d, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x63, 0x6f, 0x6c, 0x2d, 0x67, 0x75, 0x69, 0x64, 0x65, 0x2f, 0x22, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x3e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x53, 0x63, 0x75, 0x74, 0x74,
0x6c, 0x65, 0x62, 0x75, 0x74, 0x74, 0x3c, 0x2f, 0x61, 0x0a, 0x09, 0x09, 0x09, 0x3e, 0x0a, 0x09, 0x09, 0x09, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x0a, 0x09,
0x09, 0x3c, 0x2f, 0x70, 0x3e, 0x0a, 0x09, 0x09, 0x3c, 0x68, 0x32, 0x3e, 0x59, 0x6f, 0x75, 0x20, 0x61, 0x72, 0x65, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x69, 0x62,
0x6c, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3c, 0x2f, 0x68, 0x32, 0x3e, 0x0a, 0x09, 0x09, 0x3c, 0x70,
0x3e, 0x0a, 0x09, 0x09, 0x09, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x74, 0x6f, 0x6c, 0x65, 0x72, 0x61, 0x74, 0x65, 0x73, 0x20, 0x6e, 0x6f, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63,
0x74, 0x69, 0x6f, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x72, 0x20, 0x61, 0x62, 0x75, 0x73, 0x69, 0x76, 0x65, 0x20, 0x75,
0x73, 0x65, 0x72, 0x73, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x0a, 0x09, 0x09, 0x09, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x2e, 0x0a, 0x09,
0x09, 0x3c, 0x2f, 0x70, 0x3e, 0x0a, 0x09, 0x09, 0x3c, 0x70, 0x3e, 0x0a, 0x09, 0x09, 0x09, 0x59, 0x6f, 0x75, 0x72, 0x20, 0x67, 0x6f, 0x76, 0x65, 0x72, 0x6e, 0x6d, 0x65, 0x6e,
0x74, 0x2c, 0x20, 0x65, 0x6d, 0x70, 0x6c, 0x6f, 0x79, 0x65, 0x72, 0x2c, 0x20, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x2c, 0x20, 0x66, 0x72, 0x69, 0x65, 0x6e, 0x64, 0x20, 0x67,
0x72, 0x6f, 0x75, 0x70, 0x2c, 0x20, 0x65, 0x74, 0x63, 0x2e, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x69, 0x6d, 0x70, 0x6f, 0x73, 0x65, 0x0a, 0x09, 0x09, 0x09, 0x61, 0x64, 0x64, 0x69,
0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x72, 0x65, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x6e, 0x20, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74,
0x61, 0x62, 0x6c, 0x65, 0x20, 0x62, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x62, 0x65,
0x20, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x0a, 0x09, 0x09, 0x09, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x2e, 0x0a, 0x09, 0x09, 0x3c, 0x2f, 0x70,
0x3e, 0x0a, 0x09, 0x09, 0x3c, 0x70, 0x3e, 0x0a, 0x09, 0x09, 0x09, 0x59, 0x6f, 0x75, 0x20, 0x61, 0x72, 0x65, 0x20, 0x73, 0x6f, 0x6c, 0x65, 0x6c, 0x79, 0x20, 0x72, 0x65, 0x73,
0x70, 0x6f, 0x6e, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x6f, 0x77, 0x6e, 0x20, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73,
0x20, 0x77, 0x69, 0x74, 0x68, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x61, 0x70, 0x70, 0x2c, 0x0a, 0x09, 0x09, 0x09, 0x65, 0x73, 0x70, 0x65, 0x63, 0x69, 0x61, 0x6c,
0x6c, 0x79, 0x20, 0x62, 0x75, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x77, 0x68, 0x61, 0x74, 0x20, 0x63, 0x6f,
0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x63, 0x68, 0x6f, 0x6f, 0x73, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x6f, 0x73, 0x74, 0x2e, 0x0a, 0x09, 0x09, 0x3c,
0x2f, 0x70, 0x3e, 0x0a, 0x09, 0x09, 0x3c, 0x68, 0x32, 0x3e, 0x59, 0x6f, 0x75, 0x20, 0x63, 0x68, 0x6f, 0x6f, 0x73, 0x65, 0x20, 0x77, 0x68, 0x61, 0x74, 0x20, 0x79, 0x6f, 0x75,
0x20, 0x73, 0x65, 0x65, 0x3c, 0x2f, 0x68, 0x32, 0x3e, 0x0a, 0x09, 0x09, 0x3c, 0x70, 0x3e, 0x0a, 0x09, 0x09, 0x09, 0x59, 0x6f, 0x75, 0x20, 0x61, 0x72, 0x65, 0x20, 0x69, 0x6e,
0x20, 0x66, 0x75, 0x6c, 0x6c, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20,
0x79, 0x6f, 0x75, 0x20, 0x73, 0x65, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x54, 0x69, 0x6c, 0x64, 0x65, 0x20, 0x46, 0x72, 0x69, 0x65, 0x6e, 0x64, 0x73, 0x20, 0x62, 0x79, 0x20, 0x74,
0x68, 0x65, 0x0a, 0x09, 0x09, 0x09, 0x70, 0x65, 0x65, 0x72, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x63, 0x68, 0x6f, 0x6f,
0x73, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x75, 0x73, 0x65, 0x72, 0x73, 0x20, 0x79,
0x6f, 0x75, 0x20, 0x63, 0x68, 0x6f, 0x6f, 0x73, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x2e, 0x0a, 0x09, 0x09, 0x09, 0x49, 0x6e, 0x69, 0x74, 0x69,
0x61, 0x6c, 0x6c, 0x79, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x20, 0x6e, 0x6f,
0x20, 0x6f, 0x6e, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6e, 0x6f, 0x20, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20,
0x61, 0x73, 0x20, 0x61, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x0a, 0x09, 0x09, 0x09, 0x73, 0x65, 0x65, 0x20, 0x6e, 0x6f, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74,
0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x75, 0x73, 0x65, 0x72, 0x73, 0x2e, 0x0a, 0x09, 0x09, 0x3c, 0x2f, 0x70, 0x3e, 0x0a, 0x09, 0x09, 0x3c,
0x70, 0x3e, 0x0a, 0x09, 0x09, 0x09, 0x49, 0x66, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x66, 0x69, 0x6e, 0x64, 0x20, 0x73, 0x6f, 0x6d, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e,
0x74, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x2c, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x66, 0x69, 0x6c, 0x74,
0x65, 0x72, 0x20, 0x69, 0x74, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x76, 0x69, 0x65, 0x77, 0x0a, 0x09, 0x09, 0x09, 0x62, 0x79, 0x20, 0x62, 0x6c,
0x6f, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x75, 0x73, 0x65, 0x72, 0x20, 0x77, 0x68, 0x6f, 0x20, 0x70, 0x6f, 0x73, 0x74, 0x65, 0x64, 0x20, 0x69, 0x74,
0x2e, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x73, 0x20, 0x69, 0x74, 0x20, 0x73, 0x6f, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20,
0x75, 0x73, 0x65, 0x72, 0x73, 0x0a, 0x09, 0x09, 0x09, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x6e,
0x6f, 0x74, 0x20, 0x73, 0x65, 0x65, 0x20, 0x69, 0x74, 0x20, 0x61, 0x73, 0x20, 0x61, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x66, 0x6f, 0x6c, 0x6c,
0x6f, 0x77, 0x69, 0x6e, 0x67, 0x20, 0x79, 0x6f, 0x75, 0x2e, 0x0a, 0x09, 0x09, 0x3c, 0x2f, 0x70, 0x3e, 0x0a, 0x09, 0x09, 0x3c, 0x70, 0x3e, 0x0a, 0x09, 0x09, 0x09, 0x54, 0x68,
0x65, 0x20, 0x3c, 0x63, 0x6f, 0x64, 0x65, 0x3e, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x3c, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x3e, 0x20, 0x61, 0x70, 0x70, 0x20, 0x63, 0x6f, 0x6e, 0x74,
0x61, 0x69, 0x6e, 0x73, 0x20, 0x61, 0x20, 0x76, 0x61, 0x72, 0x69, 0x65, 0x74, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x74, 0x68,
0x61, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x09, 0x09, 0x09, 0x74, 0x79, 0x70, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x63, 0x6f,
0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x54, 0x69, 0x6c, 0x64, 0x65, 0x20, 0x46, 0x72, 0x69, 0x65, 0x6e, 0x64, 0x73, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20,
0x6d, 0x61, 0x6b, 0x65, 0x20, 0x6f, 0x72, 0x20, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2c, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x77, 0x68, 0x65,
0x74, 0x68, 0x65, 0x72, 0x0a, 0x09, 0x09, 0x09, 0x74, 0x68, 0x65, 0x20, 0x61, 0x70, 0x70, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x20, 0x61, 0x63, 0x63,
0x65, 0x70, 0x74, 0x20, 0x6f, 0x72, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x61, 0x74, 0x20, 0x61, 0x6c,
0x6c, 0x2e, 0x0a, 0x09, 0x09, 0x3c, 0x2f, 0x70, 0x3e, 0x0a, 0x09, 0x09, 0x3c, 0x68, 0x32, 0x3e, 0x54, 0x68, 0x69, 0x73, 0x20, 0x61, 0x70, 0x70, 0x20, 0x69, 0x73, 0x20, 0x6e,
0x6f, 0x74, 0x20, 0x61, 0x20, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x3c, 0x2f, 0x68, 0x32, 0x3e, 0x0a, 0x09, 0x09, 0x3c, 0x70, 0x3e, 0x0a, 0x09, 0x09, 0x09, 0x54, 0x68,
0x69, 0x73, 0x20, 0x61, 0x70, 0x70, 0x20, 0x72, 0x65, 0x6c, 0x69, 0x65, 0x73, 0x20, 0x6f, 0x6e, 0x20, 0x6e, 0x6f, 0x20, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x69, 0x61, 0x6c, 0x20,
0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x20, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x61,
0x70, 0x70, 0x20, 0x68, 0x61, 0x73, 0x20, 0x6e, 0x6f, 0x20, 0x6d, 0x6f, 0x72, 0x65, 0x0a, 0x09, 0x09, 0x09, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x20, 0x74, 0x6f, 0x20,
0x73, 0x65, 0x65, 0x20, 0x6f, 0x72, 0x20, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x20, 0x77, 0x68, 0x61, 0x74, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x70, 0x6f, 0x73, 0x74, 0x20, 0x6f,
0x72, 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x75, 0x73, 0x65, 0x72, 0x20, 0x6f, 0x66,
0x20, 0x74, 0x68, 0x65, 0x0a, 0x09, 0x09, 0x09, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x2e, 0x0a, 0x09, 0x09, 0x3c, 0x2f, 0x70, 0x3e, 0x0a, 0x09, 0x09, 0x3c, 0x70, 0x3e,
0x0a, 0x09, 0x09, 0x09, 0x49, 0x66, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x62, 0x65, 0x6c, 0x69, 0x65, 0x76, 0x65, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x61,
0x62, 0x6c, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x62, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x61, 0x20, 0x73,
0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73, 0x0a, 0x09, 0x09, 0x09, 0x72, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x73, 0x20,
0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x53, 0x63, 0x75, 0x74, 0x74, 0x6c, 0x65, 0x62, 0x75, 0x74,
0x74, 0x20, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x66, 0x6c, 0x61, 0x67, 0x67, 0x65, 0x64, 0x2c, 0x20,
0x6c, 0x6f, 0x6f, 0x6b, 0x0a, 0x09, 0x09, 0x09, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x6e, 0x20, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20,
0x63, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2c, 0x20, 0x67, 0x65, 0x6e, 0x65,
0x72, 0x61, 0x6c, 0x6c, 0x79, 0x20, 0x62, 0x79, 0x20, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x09, 0x09, 0x09, 0x73, 0x65, 0x72,
0x76, 0x65, 0x72, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x20, 0x77, 0x65, 0x62, 0x20, 0x62, 0x72, 0x6f, 0x77, 0x73, 0x65, 0x72, 0x2c,
0x20, 0x61, 0x6e, 0x64, 0x20, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x69, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f,
0x72, 0x2e, 0x0a, 0x09, 0x09, 0x3c, 0x2f, 0x70, 0x3e, 0x0a, 0x09, 0x09, 0x3c, 0x68, 0x32, 0x3e, 0x41, 0x67, 0x72, 0x65, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68,
0x65, 0x73, 0x65, 0x20, 0x74, 0x65, 0x72, 0x6d, 0x73, 0x3f, 0x3c, 0x2f, 0x68, 0x32, 0x3e, 0x0a, 0x09, 0x09, 0x3c, 0x70, 0x3e, 0x49, 0x66, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x64,
0x6f, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x20, 0x74, 0x68, 0x65, 0x73, 0x65, 0x20, 0x74, 0x65, 0x72, 0x6d, 0x73, 0x2c, 0x20, 0x64, 0x6f, 0x20,
0x6e, 0x6f, 0x74, 0x20, 0x75, 0x73, 0x65, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x61, 0x70, 0x70, 0x2e, 0x3c, 0x2f, 0x70, 0x3e, 0x0a, 0x09, 0x09, 0x3c, 0x64, 0x69, 0x76, 0x20,
0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x77, 0x33, 0x2d, 0x62, 0x61, 0x72, 0x20, 0x77, 0x33, 0x2d, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x22, 0x3e, 0x0a, 0x09, 0x09, 0x09,
0x3c, 0x61, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x77, 0x33, 0x2d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x20, 0x77, 0x33, 0x2d, 0x62, 0x6c, 0x75, 0x65, 0x22, 0x20,
0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x2f, 0x65, 0x75, 0x6c, 0x61, 0x2f, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x22, 0x3e, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x20, 0x41, 0x67,
0x72, 0x65, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x3c, 0x2f, 0x61, 0x3e, 0x0a, 0x09, 0x09, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0x0a, 0x09, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e,
0x0a, 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0x0a };
unsigned int k_eula_len = 2499;

View File

@@ -1,5 +1,6 @@
#include "httpd.js.h"
#include "eula.h"
#include "file.js.h"
#include "http.h"
#include "log.h"
@@ -13,6 +14,11 @@
#include "sodium/crypto_sign.h"
#include "sodium/utils.h"
#include "zlib.h"
#if defined(__APPLE__)
#include <TargetConditionals.h>
#endif
#define CYAN "\e[1;36m"
#define MAGENTA "\e[1;35m"
@@ -616,28 +622,99 @@ tf_httpd_user_app_t* tf_httpd_parse_user_app_from_path(const char* path, const c
return result;
}
static void _httpd_endpoint_root_callback(const char* path, void* user_data)
typedef struct _root_t
{
tf_http_request_t* request = user_data;
const char* headers[] = {
"Location",
path ? path : "/~core/apps/",
};
tf_http_respond(request, 303, headers, tf_countof(headers) / 2, NULL, 0);
tf_http_request_unref(request);
}
tf_http_request_t* request;
const char* path;
} root_t;
static void _httpd_endpoint_root(tf_http_request_t* request)
static void _httpd_root_work(tf_ssb_t* ssb, void* user_data)
{
root_t* root = user_data;
tf_http_request_t* request = root->request;
const char* host = tf_http_request_get_header(request, "x-forwarded-host");
if (!host)
{
host = tf_http_request_get_header(request, "host");
}
bool require_eula =
#if TARGET_OS_IPHONE
true;
#else
false;
#endif
int64_t accepted_eula_crc = 0;
uint32_t eula_crc = crc32(crc32(0, NULL, 0), k_eula, k_eula_len);
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
tf_ssb_db_get_global_setting_int64(db, "accepted_eula_crc", &accepted_eula_crc);
if (require_eula && accepted_eula_crc != eula_crc)
{
root->path = tf_strdup("/static/eula.html");
}
else
{
root->path = tf_ssb_db_resolve_index(db, host);
}
tf_ssb_release_db_reader(ssb, db);
}
static void _httpd_root_after_work(tf_ssb_t* ssb, int status, void* user_data)
{
root_t* root = user_data;
tf_http_request_t* request = root->request;
const char* headers[] = {
"Location",
root->path ? root->path : "/~core/apps/",
};
tf_http_respond(request, 303, headers, tf_countof(headers) / 2, NULL, 0);
tf_http_request_unref(request);
tf_free((void*)root->path);
tf_free(root);
}
static void _httpd_endpoint_root(tf_http_request_t* request)
{
root_t* root = tf_malloc(sizeof(root_t));
*root = (root_t) {
.request = request,
};
tf_http_request_ref(request);
tf_task_t* task = request->user_data;
tf_ssb_t* ssb = tf_task_get_ssb(task);
tf_ssb_run_work(ssb, _httpd_root_work, _httpd_root_after_work, root);
}
static void _httpd_accept_eula_work(tf_ssb_t* ssb, void* user_data)
{
uint32_t eula_crc = crc32(crc32(0, NULL, 0), k_eula, k_eula_len);
char buffer[64];
snprintf(buffer, sizeof(buffer), "%u", eula_crc);
sqlite3* db = tf_ssb_acquire_db_writer(ssb);
tf_ssb_db_set_global_setting_from_string(db, "accepted_eula_crc", buffer);
tf_ssb_release_db_writer(ssb, db);
}
static void _httpd_accept_eula_after_work(tf_ssb_t* ssb, int status, void* user_data)
{
tf_http_request_t* request = user_data;
const char* headers[] = {
"Location",
"/",
};
tf_http_respond(request, 303, headers, tf_countof(headers) / 2, NULL, 0);
tf_http_request_unref(request);
}
static void _httpd_endpoint_accept_eula(tf_http_request_t* request)
{
tf_http_request_ref(request);
tf_ssb_db_resolve_index_async(ssb, host, _httpd_endpoint_root_callback, request);
tf_task_t* task = request->user_data;
tf_ssb_t* ssb = tf_task_get_ssb(task);
tf_ssb_run_work(ssb, _httpd_accept_eula_work, _httpd_accept_eula_after_work, request);
}
static void _httpd_endpoint_robots_txt(tf_http_request_t* request)
@@ -913,6 +990,7 @@ tf_http_t* tf_httpd_create(JSContext* context)
tf_http_add_handler(http, "/login/logout", tf_httpd_endpoint_logout, NULL, task);
tf_http_add_handler(http, "/login/auto", tf_httpd_endpoint_login_auto, NULL, task);
tf_http_add_handler(http, "/login", tf_httpd_endpoint_login, NULL, task);
tf_http_add_handler(http, "/eula/accept", _httpd_endpoint_accept_eula, NULL, task);
tf_http_add_handler(http, "/app/socket", tf_httpd_endpoint_app_socket, NULL, task);

View File

@@ -124,6 +124,7 @@ void tf_httpd_endpoint_static(tf_http_request_t* request)
const char* k_static_files[] = {
"index.html",
"eula.html",
"client.js",
"tildefriends.svg",
"jszip.min.js",

View File

@@ -13,7 +13,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>0.2026.11</string>
<string>0.2026.10.1</string>
<key>CFBundleSupportedPlatforms</key>
<array>
<string>iPhoneOS</string>

View File

@@ -2186,56 +2186,40 @@ bool tf_ssb_db_identity_get_active(sqlite3* db, const char* user, const char* pa
return found;
}
typedef struct _resolve_index_t
const char* tf_ssb_db_resolve_index(sqlite3* db, const char* host)
{
const char* host;
const char* path;
void (*callback)(const char* path, void* user_data);
void* user_data;
} resolve_index_t;
const char* result = NULL;
static void _tf_ssb_db_resolve_index_work(tf_ssb_t* ssb, void* user_data)
{
resolve_index_t* request = user_data;
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
sqlite3_stmt* statement;
if (sqlite3_prepare_v2(db, "SELECT json_extract(value, '$.index_map') FROM properties WHERE id = 'core' AND key = 'settings'", -1, &statement, NULL) == SQLITE_OK)
if (!result)
{
if (sqlite3_step(statement) == SQLITE_ROW)
{
const char* index_map = (const char*)sqlite3_column_text(statement, 0);
const char* start = index_map;
while (start)
{
const char* end = strchr(start, '\n');
const char* equals = strchr(start, '=');
if (equals && strncasecmp(request->host, start, equals - start) == 0)
{
size_t value_length = end && equals < end ? (size_t)(end - (equals + 1)) : strlen(equals + 1);
char* path = tf_malloc(value_length + 1);
memcpy(path, equals + 1, value_length);
path[value_length] = '\0';
request->path = path;
break;
}
start = end ? end + 1 : NULL;
}
}
sqlite3_finalize(statement);
}
else
{
tf_printf("prepare failed: %s\n", sqlite3_errmsg(db));
/* Maybe we need to force the EULA first. */
}
if (!request->path)
if (!result)
{
if (sqlite3_prepare_v2(db, "SELECT json_extract(value, '$.index') FROM properties WHERE id = 'core' AND key = 'settings'", -1, &statement, NULL) == SQLITE_OK)
/* Use the index_map setting. */
sqlite3_stmt* statement;
if (sqlite3_prepare_v2(db, "SELECT json_extract(value, '$.index_map') FROM properties WHERE id = 'core' AND key = 'settings'", -1, &statement, NULL) == SQLITE_OK)
{
if (sqlite3_step(statement) == SQLITE_ROW)
{
request->path = tf_strdup((const char*)sqlite3_column_text(statement, 0));
const char* index_map = (const char*)sqlite3_column_text(statement, 0);
const char* start = index_map;
while (start)
{
const char* end = strchr(start, '\n');
const char* equals = strchr(start, '=');
if (equals && strncasecmp(host, start, equals - start) == 0)
{
size_t value_length = end && equals < end ? (size_t)(end - (equals + 1)) : strlen(equals + 1);
char* path = tf_malloc(value_length + 1);
memcpy(path, equals + 1, value_length);
path[value_length] = '\0';
result = path;
break;
}
start = end ? end + 1 : NULL;
}
}
sqlite3_finalize(statement);
}
@@ -2244,32 +2228,32 @@ static void _tf_ssb_db_resolve_index_work(tf_ssb_t* ssb, void* user_data)
tf_printf("prepare failed: %s\n", sqlite3_errmsg(db));
}
}
tf_ssb_release_db_reader(ssb, db);
if (!request->path)
if (!result)
{
request->path = tf_strdup(tf_util_get_default_global_setting_string("index"));
/* Use the index setting. */
sqlite3_stmt* statement;
if (sqlite3_prepare_v2(db, "SELECT json_extract(value, '$.index') FROM properties WHERE id = 'core' AND key = 'settings'", -1, &statement, NULL) == SQLITE_OK)
{
if (sqlite3_step(statement) == SQLITE_ROW)
{
result = tf_strdup((const char*)sqlite3_column_text(statement, 0));
}
sqlite3_finalize(statement);
}
else
{
tf_printf("prepare failed: %s\n", sqlite3_errmsg(db));
}
}
}
static void _tf_ssb_db_resolve_index_after_work(tf_ssb_t* ssb, int status, void* user_data)
{
resolve_index_t* request = user_data;
request->callback(request->path, request->user_data);
tf_free((void*)request->host);
tf_free((void*)request->path);
tf_free(request);
}
if (!result)
{
/* Use the default index. */
result = tf_strdup(tf_util_get_default_global_setting_string("index"));
}
void tf_ssb_db_resolve_index_async(tf_ssb_t* ssb, const char* host, void (*callback)(const char* path, void* user_data), void* user_data)
{
resolve_index_t* request = tf_malloc(sizeof(resolve_index_t));
*request = (resolve_index_t) {
.host = tf_strdup(host),
.callback = callback,
.user_data = user_data,
};
tf_ssb_run_work(ssb, _tf_ssb_db_resolve_index_work, _tf_ssb_db_resolve_index_after_work, request);
return result;
}
static void _tf_ssb_db_set_flags(tf_ssb_t* ssb, const char* message_id, int flags)
@@ -2514,7 +2498,7 @@ bool tf_ssb_db_set_global_setting_from_string(sqlite3* db, const char* name, cha
bound = sqlite3_bind_int(statement, 2, value && (strcmp(value, "true") == 0 || atoi(value))) == SQLITE_OK;
break;
case k_kind_int:
bound = sqlite3_bind_int(statement, 2, atoi(value)) == SQLITE_OK;
bound = sqlite3_bind_int64(statement, 2, atoll(value)) == SQLITE_OK;
break;
case k_kind_string:
bound = sqlite3_bind_text(statement, 2, value, -1, NULL) == SQLITE_OK;

View File

@@ -445,12 +445,11 @@ bool tf_ssb_db_add_value_to_array_property(tf_ssb_t* ssb, const char* id, const
/**
** Resolve a hostname to its index path by global settings.
** @param ssb The SSB instance.
** @param db The database.
** @param host The hostname.
** @param callback The callback.
** @param user_data The callback user data.
** @return The resolved index. Free with tf_free().
*/
void tf_ssb_db_resolve_index_async(tf_ssb_t* ssb, const char* host, void (*callback)(const char* path, void* user_data), void* user_data);
const char* tf_ssb_db_resolve_index(sqlite3* db, const char* host);
/**
** Verify an author's feed.

View File

@@ -338,6 +338,7 @@ static const setting_t k_settings[] = {
.type = "boolean",
.description = "Whether to attempt to keep several peer connections open.",
.default_value = { .kind = k_kind_bool, .bool_value = false } },
{ .name = "accepted_eula_crc", .type = "hidden", .description = "The CRC32 of the last accepted EULA.", .default_value = { .kind = k_kind_int, .int_value = 0 } },
};
static const setting_t* _util_get_setting(const char* name, tf_setting_kind_t kind)

View File

@@ -1,2 +1,2 @@
#define VERSION_NUMBER "0.2026.11-wip"
#define VERSION_NUMBER "0.2026.10.1"
#define VERSION_NAME "This program kills fascists."