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
				
			
		
		
	
	
				
					
				
			
		
			All checks were successful
		
		
	
	Build Tilde Friends / Build-All (push) Successful in 22m0s
				
			This commit is contained in:
		@@ -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
									
								
							
							
						
						
									
										67
									
								
								core/eula.html
									
									
									
									
									
										Normal 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>
 | 
			
		||||
@@ -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.
 | 
			
		||||
 
 | 
			
		||||
@@ -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
									
								
							
							
						
						
									
										88
									
								
								src/eula.h
									
									
									
									
									
										Normal 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;
 | 
			
		||||
							
								
								
									
										100
									
								
								src/httpd.js.c
									
									
									
									
									
								
							
							
						
						
									
										100
									
								
								src/httpd.js.c
									
									
									
									
									
								
							@@ -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);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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",
 | 
			
		||||
 
 | 
			
		||||
@@ -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>
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										110
									
								
								src/ssb.db.c
									
									
									
									
									
								
							
							
						
						
									
										110
									
								
								src/ssb.db.c
									
									
									
									
									
								
							@@ -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;
 | 
			
		||||
 
 | 
			
		||||
@@ -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.
 | 
			
		||||
 
 | 
			
		||||
@@ -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)
 | 
			
		||||
 
 | 
			
		||||
@@ -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."
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user