invent):
* - Dual L/R panels (Try Peer / PeerID / Send) after ENTER; sprite-sheet media panes.
* - Default HTML mode (safer, pixelated); HD opt-in with honest risk.
* - DNA line: CHAT · sprite green. Empire entrance is #disclaimerOverlay:
* Options · Mirrors · Donate + feature rows + I AGREE ENTER (template for other crops).
* - Debug/stragglers live on Options (not corner-only primary chrome).
* - Full protocol MUST/MUST NOT block lives deeper in this file — keep it.
*/
/**
* LORD rent credit placeholder (ledger units) if rent/claim is ever wired for this crop.
* Chat has no visitor ledger / mint this ship — define only (com-style utility crop).
* Not a faucet; not visitor wallet; no chat-gems. Money/buy on nosignup.trade.
*/
const LORD_RENT_CREDIT = 10000;
/* ---- SITE-LOCAL CONTROL PANEL (renter key; not OS root) ---- */
function nsp_vault_dir(): string {
$sib = dirname(__DIR__) . DIRECTORY_SEPARATOR . 'vault';
$loc = __DIR__ . DIRECTORY_SEPARATOR . 'vault';
foreach ([$sib, $loc] as $d) {
if (is_dir($d) || @mkdir($d, 0700, true)) {
if (is_dir($d) && is_writable($d)) return $d;
}
}
return $sib;
}
function nsp_data_dir(): string {
$d = __DIR__ . DIRECTORY_SEPARATOR . 'data';
if (!is_dir($d)) @mkdir($d, 0755, true);
$ht = $d . DIRECTORY_SEPARATOR . '.htaccess';
if (!is_file($ht)) @file_put_contents($ht, "Require all denied\nDeny from all\n");
return $d;
}
function nsp_hash_file(): string { return nsp_data_dir() . DIRECTORY_SEPARATOR . 'admin.pass.hash'; }
function nsp_seed_file(): string { return nsp_data_dir() . DIRECTORY_SEPARATOR . 'site.seed'; }
function nsp_norm_seed(string $s): string {
return strtolower(trim(preg_replace('/\s+/', ' ', $s) ?? ''));
}
/** Identity surface only (same scheme as trade); chat has no visitor spend ledger. */
function nsp_addr_from_seed(string $seed): string {
return hash('sha256', 'nsu-addr-v1|' . nsp_norm_seed($seed));
}
/**
* 12-word site seed (not BIP39). CSPRNG into fixed word pool.
* Panel unlock for THIS crop only — not a faucet mint (chat has no visitor wallet / chat-gems).
*/
function nsp_generate_site_seed(): string {
static $wl = [
'able','acid','aged','also','aqua','arch','area','army','atom','aunt','auto','avoid',
'axis','baby','band','bank','bare','barn','base','bean','bear','belt','bike','bind',
'bird','bite','blue','boat','body','bold','bolt','bone','book','boot','born','bowl',
'brass','brave','bread','brick','brief','bring','broad','broke','brown','brush','build','bulk',
'burn','burst','bush','busy','cable','cage','cake','calm','camp','cane','cape','card',
'care','cart','case','cash','cast','cave','cell','cent','chat','chef','chin','chip',
'city','clap','clay','clip','club','coal','coat','code','coil','coin','cold','come',
'cook','cool','cope','copy','cord','core','corn','cost','cove','crab','crew','crop',
'crow','cube','cult','curb','cure','curl','dark','dart','dash','data','dawn','deal',
'dear','deck','deep','deer','desk','dial','dice','diet','dine','dirt','disc','dock',
'dome','done','door','dose','down','draw','drip','drop','drum','dual','duck','dune',
'dusk','dust','duty','each','earn','east','easy','echo','edge','edit','else','emit',
'epic','even','ever','evil','exit','face','fact','fade','fail','fair','fall','fame',
'farm','fast','fate','fear','feed','feel','fern','file','fill','film','find','fine',
'fire','firm','fish','flag','flat','flee','flip','flow','foam','foil','fold','font',
'food','fool','foot','ford','fork','form','fort','foul','four','free','frog','from',
'fuel','full','fund','fuse','gain','game','gate','gear','gene','gift','girl','give',
'glad','glow','glue','goal','goat','gold','golf','good','grab','grad','gram','gray',
'grid','grim','grin','grip','grow','gulf','guru','hail','hair','half','hall','hand',
'hang','hard','harm','harp','hate','have','hawk','haze','head','heal','heap','heat',
'heed','heel','held','help','herb','here','hero','hide','high','hill','hint','hire',
'hold','hole','home','hood','hook','hope','horn','host','hour','huge','hull','hung',
'hunt','hurt','icon','idea','idle','inch','info','into','iron','item','jade','jail',
'jazz','join','joke','jump','june','jury','just','keen','keep','kept','kick','kind',
'king','kite','knee','knew','knit','knot','know','lace','lack','lady','lake','lamp',
'land','lane','last','late','lava','lawn','lead','leaf','lean','left','lend','lens',
];
$n = count($wl);
$bytes = random_bytes(12);
$out = [];
for ($i = 0; $i < 12; $i++) {
$out[] = $wl[ord($bytes[$i]) % $n];
}
return implode(' ', $out);
}
/** Owner-only vault note: site seed = panel unlock for THIS crop. Never to renters/visitors. */
function nsp_vault_site_seed_note(string $seed): void {
$d = nsp_vault_dir();
if (!is_dir($d) && !@mkdir($d, 0700, true)) {
return;
}
@chmod($d, 0700);
$body = "NOSIGNUP.CHAT SITE WALLET SEED (OWNER ONLY)\n"
. "This seed unlocks /controlpanel for THIS crop only.\n"
. "Chat has no visitor ledger, faucet mint, or chat-gems on this crop. Money/buy: nosignup.trade.\n"
. "NO RECOVERY. Renters must NOT receive this secret (LORD seed is issued offline per epoch).\n"
. "Generated: " . gmdate('c') . "\n\n"
. trim($seed) . "\n";
@file_put_contents($d . DIRECTORY_SEPARATOR . 'SITE_WALLET_SEED.txt', $body, LOCK_EX);
@chmod($d . DIRECTORY_SEPARATOR . 'SITE_WALLET_SEED.txt', 0600);
}
/** True if $seed matches data/site.seed (normalized). */
function nsp_panel_seed_ok(string $seed): bool {
$seed = nsp_norm_seed($seed);
if ($seed === '') {
return false;
}
$path = nsp_seed_file();
if (!is_file($path)) {
return false;
}
$have = nsp_norm_seed((string)@file_get_contents($path));
if ($have === '') {
return false;
}
return hash_equals($have, $seed);
}
/**
* Ensure data/site.seed exists; mirror to vault SITE_WALLET_SEED.txt on first write.
* Idempotent. Call before admin API so setup is never land-grabable.
* NOT a treasury faucet mint — chat has no visitor ledger this crop.
*/
function nsp_ensure_site_seed(): void {
$path = nsp_seed_file();
if (is_file($path) && nsp_norm_seed((string)@file_get_contents($path)) !== '') {
$vd = nsp_vault_dir();
$note = $vd . DIRECTORY_SEPARATOR . 'SITE_WALLET_SEED.txt';
if (!is_file($note) || trim((string)@file_get_contents($note)) === '') {
nsp_vault_site_seed_note(nsp_norm_seed((string)@file_get_contents($path)));
}
return;
}
$seed = nsp_generate_site_seed();
file_put_contents($path, $seed . "\n", LOCK_EX);
@chmod($path, 0600);
nsp_vault_site_seed_note($seed);
}
function nsp_vault_write(string $plain): void {
$d = nsp_vault_dir();
@chmod($d, 0700);
@file_put_contents($d . DIRECTORY_SEPARATOR . 'README.txt',
"NOSIGNUP.CHAT VAULT - ROOT/OPERATOR ONLY\n"
. "Site seed unlocks /controlpanel (SITE_WALLET_SEED.txt + data/site.seed).\n"
. "Legacy admin password (optional migrate): ADMIN_PASSWORD.txt\n"
. "No visitor wallet on chat — money/buy on nosignup.trade.\n"
. gmdate('c') . "\n", LOCK_EX);
@file_put_contents($d . DIRECTORY_SEPARATOR . 'ADMIN_PASSWORD.txt', $plain . "\n", LOCK_EX);
@chmod($d . DIRECTORY_SEPARATOR . 'ADMIN_PASSWORD.txt', 0600);
$ht = $d . DIRECTORY_SEPARATOR . '.htaccess';
if (!is_file($ht)) @file_put_contents($ht, "Require all denied\nDeny from all\n");
}
function nsp_json(array $x, int $c = 200): void {
http_response_code($c);
header('Content-Type: application/json; charset=UTF-8');
header('Cache-Control: no-store');
echo json_encode($x, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
exit;
}
function nsp_pass_set(string $pass): void {
$pass = trim($pass);
if (strlen($pass) < 8) nsp_json(['ok' => false, 'err' => 'admin pass min 8 chars'], 400);
$h = password_hash($pass, PASSWORD_DEFAULT);
if ($h === false) nsp_json(['ok' => false, 'err' => 'hash fail'], 500);
file_put_contents(nsp_hash_file(), $h . "\n", LOCK_EX);
@chmod(nsp_hash_file(), 0600);
nsp_vault_write($pass);
}
function nsp_pass_is_set(): bool {
return is_file(nsp_hash_file()) && trim((string)file_get_contents(nsp_hash_file())) !== '';
}
function nsp_ok(?string $pass): bool {
if ($pass === null || $pass === '') return false;
if (!nsp_pass_is_set()) return false;
$h = trim((string)file_get_contents(nsp_hash_file()));
return $h !== '' && password_verify(trim($pass), $h);
}
function nsp_require(): void {
// POST body only — never accept admin_pass / seed from query (URL/access logs/Referer).
$seed = (string)($_POST['seed'] ?? '');
if ($seed !== '' && nsp_panel_seed_ok($seed)) {
return;
}
$p = (string)($_POST['admin_pass'] ?? '');
if (!nsp_ok($p)) nsp_json(['ok' => false, 'err' => 'admin auth'], 401);
}
function nsp_handle_admin_api(string $api): bool {
if (!str_starts_with($api, 'admin_')) return false;
nsp_ensure_site_seed();
if ($api === 'admin_status') {
// Soft-verify: admin_pass_set + site only. No filesystem vault path to strangers.
nsp_json(['ok' => true, 'admin_pass_set' => nsp_pass_is_set(), 'site' => 'chat', 'version' => 'chat']);
}
if ($api === 'admin_setup' && ($_SERVER['REQUEST_METHOD'] ?? '') === 'POST') {
if (nsp_pass_is_set()) nsp_json(['ok' => false, 'err' => 'already set - use admin_login'], 400);
// Seed exists at genesis — no unauthenticated land-grab of the legacy password door.
$seed = (string)($_POST['seed'] ?? '');
if ($seed === '' || !nsp_panel_seed_ok($seed)) {
nsp_json(['ok' => false, 'err' => 'admin auth'], 401);
}
nsp_pass_set((string)($_POST['admin_pass'] ?? ''));
// No absolute vault path on first-setup response (filesystem paths stay off unauth JSON).
nsp_json(['ok' => true, 'msg' => 'hash+vault set (seed-proved)']);
}
if ($api === 'admin_login' && ($_SERVER['REQUEST_METHOD'] ?? '') === 'POST') {
nsp_require();
nsp_json(['ok' => true, 'msg' => 'ok', 'site' => 'chat', 'vault_hint' => nsp_vault_dir(), 'version' => 'chat']);
}
if ($api === 'admin_change_pass' && ($_SERVER['REQUEST_METHOD'] ?? '') === 'POST') {
nsp_require();
nsp_pass_set((string)($_POST['new_pass'] ?? ''));
nsp_json(['ok' => true, 'msg' => 'rotated']);
}
if ($api === 'admin_get_source' && ($_SERVER['REQUEST_METHOD'] ?? '') === 'POST') {
nsp_require();
$raw = (string)file_get_contents(__FILE__);
nsp_json(['ok' => true, 'bytes' => strlen($raw), 'sha256' => hash('sha256', $raw), 'source' => $raw]);
}
if ($api === 'admin_put_source' && ($_SERVER['REQUEST_METHOD'] ?? '') === 'POST') {
nsp_require();
$src = (string)($_POST['source'] ?? '');
if (strlen($src) < 100 || strpos($src, ' false, 'err' => 'bad source'], 400);
$bak = __FILE__ . '.bak.' . time();
@copy(__FILE__, $bak);
if (file_put_contents(__FILE__, $src, LOCK_EX) === false) nsp_json(['ok' => false, 'err' => 'write failed'], 500);
nsp_json(['ok' => true, 'msg' => 'replaced', 'backup' => basename($bak), 'sha256' => hash('sha256', $src)]);
}
nsp_json(['ok' => false, 'err' => 'unknown admin api'], 404);
return true;
}
function nsp_render_controlpanel(): void {
header('Content-Type: text/html; charset=UTF-8');
header('Cache-Control: no-store');
$site = 'Nosignup.Chat';
echo '
';
echo '' . htmlspecialchars($site) . ' Control ';
echo '';
echo '
DNA · CHAT · sprite green
';
echo '
' . htmlspecialchars($site) . ' · Control Panel ';
echo '
Site-local renter key for THIS crop. '
. 'Paste this crop\'s site wallet seed (vault SITE_WALLET_SEED.txt / data/site.seed). '
. 'UTTER control of THIS index.php (incl. replace). Not OS root. Independent vault. '
. 'Rent until yearly reset — no refunds. Yearly wipe re-keys panel seed so leaked keys die. '
. 'This peer-chat crop has no visitor wallet, faucet mint, or chat-gems . '
. 'Money/buy lives on nosignup.trade. Going-forward door is site seed; legacy admin password (if already set) is one-release migrate read only.
';
echo '
';
echo '
Site wallet seed (12 words) ';
echo '
';
echo '
Unlock with site seed ';
echo '
';
echo '
Legacy password (one-release migrate only) ';
echo 'Only if data/admin.pass.hash already exists from an older deploy. Not the product path.
';
echo 'Legacy admin password ';
echo ' ';
echo 'Unlock with legacy pass ';
echo '
Owner: seed auto-generated at first boot into data/site.seed + vault SITE_WALLET_SEED.txt (root pull). Paste seed → unlock. No password product path. No recovery desk. Chat is not a mint. Not a visitor account.
';
echo '
Vault: -
';
echo '
Migrate: rotate legacy password (optional) ';
echo 'New password Update
';
echo '
Source (utter control) Load Save ';
echo '
';
echo '
← back
';
exit;
}
// --- controlpanel early gate (before any HTML) ---
// Site seed genesis BEFORE any admin API / controlpanel (no land-grab window).
$_nsp_api = (string)($_GET['api'] ?? $_POST['api'] ?? '');
$_nsp_panel = isset($_GET['controlpanel']) || (isset($_SERVER['REQUEST_URI']) && preg_match('#/controlpanel/?(\?|$)#', (string)$_SERVER['REQUEST_URI']));
if (($_nsp_api !== '' && str_starts_with($_nsp_api, 'admin_')) || ($_nsp_panel && $_nsp_api === '')) {
nsp_ensure_site_seed();
}
if ($_nsp_api !== '' && str_starts_with($_nsp_api, 'admin_')) { nsp_handle_admin_api($_nsp_api); }
if ($_nsp_panel && $_nsp_api === '') { nsp_render_controlpanel(); }
/**
* DO NOT DELETE/REMOVE THIS BLOCK - NOSIGNUP.CHAT PROTOCOL CONTRACT.
* AUTHORITATIVE. Change code to satisfy this; MUST/MUST NOT/MAY/SHOULD bind.
*
* 0 PRIME: no signup/install/account/cookie. One readable index.php over ordinary
* HTTP for cheap hosts/hostile networks. PHP is a dumb switchboard; browser owns
* robustness, identity, payments, mirrors, UI. Stay near 150KB; >200KB requires
* reduction. Mirrors are disposable; swarm regrows through browser gossip plus
* RAM-only reminders. Parity proves source bytes, not host behavior. No central
* server, obfuscation, mirror-side entitlements, or server trust/moderation.
*
* 1 BOUNDARIES: MUST NOT use WebSocket, SSE, STUN, TURN, long-poll, sessions,
* cookies, accounts, or server media decode. Single deployable file; runtime
* files only as sec 4 permits. One upload pass and one fetch pass per active
* panel/tick. Server routes by filename + size + mtime + tail only.
*
* 2 WIRE: [4 vLen BE][JPEG 3x3 80x60 sheet][4 aLen BE][G.711 u-law][UTF-8 tail].
* Host-only RTC after visible media MAY send vLen=0/aLen=0 maintenance blobs.
* 9 frames x 256ms=2304ms, center crop .85, JPEG_Q=.50. Audio ON: 9 x 256ms
* mono u-law at 12kHz (~30KB/s); OFF sends aLen=0. Non-8kHz audio MUST carry sr.
* Exhaustive tail keys: head, sid, sr, msg, msg_ts, bridge_target, px_hit, rtc.
* Adding keys is a protocol change. MUST NOT add seq.
*
* 3 IDENTITY: browser owns stable localStorage deviceId -> {deviceId}_{L|R};
* seekers append _S. KYC identity is separate by IP.
*
* 4 STORAGE: RAM: /dev/shm/nosignup/sprite/{peerId}.bin and
* /dev/shm/nosignup/mirrors.txt. One RAM blob/user, two while bridging; newest
* replaces old; flat dir; routing in filename. mirrors.txt is untrusted URL+ts
* gossip only, cap 64, lazy/TTL, torn reads OK. Persistent KYC only:
* /var/lib/nosignup/kyc/{HMAC-tag}/metadata.log (server-local .salt + hash_hmac);
* ts + client tag + peer/session ids + act only; no sample.jpg/raw IP; lazy 30d.
* Sprite writes SHOULD be direct final replacement; clients drop torn/invalid/
* truncated/decode-failed blobs as no-fresh-frame. Seek uses fresh _S only.
*
* 5 UPLOAD: active panel prep blob -> fire POST without await -> base pass at
* UPLOAD_MS - prep; if ACK is still pending then retry at the ACK cutoff, not
* another full grid. Cadence=max(prep,UPLOAD_MS), not prep+post. Exactly one POST;
* _postInflight skips prep+POST while prior POST is out. ACK cutoff below
* UPLOAD_MS. Idle uploads nothing. Instrument prep_ms/post_ms/queue/code. JPEG
* encode SHOULD use Worker; fallback explicit synchronous toDataURL, never
* main-thread toBlob callback. Mic SHOULD use AudioWorklet; ScriptProcessor is
* fallback. api=encworker/api=micworklet are startup-only same-file scripts.
* MUST NOT vary chunks, frame rate, upload cadence, or JPEG_Q to chase bytes.
*
* 6 FETCH/LIVENESS: fetch target peerId on 1024ms grid, one GET in flight/panel.
* Manual stop/reset is authoritative; stale async callbacks MUST NOT revive old
* epochs. Fresh decoded head > high-water is alive. Same/older head, 404/204,
* fetch error, invalid blob, decode failure -> same no-fresh-frame path. Match
* may echo _S sid/head; client rejects sid mismatch or far-out first head. After
* match briefly publish own _S; exact remote BASE fetch MAY serve fresh remote _S.
* Disconnect budgets are wall-clock: orphan 6s, established 6s. Silence=black/silence.
*
* 7 PLAYBACK: cursor advances 1 frame/256ms by wall clock. Blobs lay absolute
* rails: firstAbs=head-8; wantAbs=anchor.abs+floor((now-anchor.time)/256). Draw
* newest blob covering wantAbs; audio same abs, play once. Arrival order irrelevant.
* Re-anchor only on first blob/underrun/runaway/sender swap; skip forward to
* newestAbs-PLAY_RUNWAY. Exhaustion blanks. No hold, loop, catch-up speed, or back replay.
*
* 8 SENDER/BRIDGE: head > high-water alive; head <= high-water within
* SWAP_GAP_FRAMES drop; larger drop means sender swap -> re-anchor. Bridge only
* after both panels have same-mirror remote IDs. Bridge is HTTP-mode only; WebRTC/HD
* disables Bridge UI/state. Bridge sets bridge_target={peerId}; /sprite
* reads only that key, emits X-Bridge-Target, streams target if fresh.
* Clients accept SID changes only under that header.
*
* 9 ADD-ONS: PIXEL px_hit best-effort; click/draw mapping MUST use displayed
* bitmap rect; receiver dedupes id and blacks mapped outgoing pixel for 1d/session;
* px_hit MUST carry w,h. HELP NETWORK ?src=1 MUST expose normalized parity CORS;
* browser MUST hash source before mirror use. PHP MAY remember untrusted mirror
* URLs only in RAM mirrors.txt; MUST NOT fetch/probe/score/relay mirrors. DONATION
* vanity is browser self-rename only; PHP MUST NOT check ledgers, trust proofs,
* store names, edit KYC, reserve IDs, refund, recover, or be name authority.
* AUDIO RAIL is local visualization only. SPECIFIC-ID is browser-owned; explicit
* ID/substr plus optional mirror hint resolves via fresh base/_S sprite filenames;
* no directory/inbox/caller queue/mailbox. Cross-mirror lookup MAY probe same-parity staged mirrors by CORS
* sprite reads; remote mirror URL stays browser-local; PHP MUST NOT relay. TRUSTED
* mirrors are user-staged/browser-held; PHP stores URL hints only, never trust/rank/vote.
*
* 9A AUDIO/ADULT: audio media only: sr=12000 when ON, aLen=0 when OFF, no match
* split. Adult section publishes {deviceId}_H_{L|R}; normal publishes {deviceId}_{L|R};
* random/partial/explicit same-mirror matches MUST NOT cross namespace. `_H`
* reserved; PHP enforces by filename/fromPeerId. HTML Mode default. WebRTC Mode
* explicit opt-in: host-only, iceServers=[], signaling via rtc tail, PHP blind,
* peer IP may be exposed, strict NAT falls back to HTTP. UI MUST warn in large
* direct-IP language before enabling HD; no moderation/warranty/recovery/recourse.
* HD tooltip states current mode; toggle retunes own cam.
* Once RTC visible, HTTP SHOULD become no-media head/sid/rtc/chat/px maintenance.
*
* 10 DIAGNOSTICS: trace/overlay opt-in and MUST NOT alter protocol. Trace DOM
* and debug-only state MUST be bounded. Judge production with trace/debug OFF.
* Key metric: jitter-buffer lead vs PLAY_RUNWAY.
*
* 11 LANDMINES: no background-send uploads; no await-held prep guard; no rAF
* capture/playback; no unbounded/awaited upload cadence or skip grids; no seq;
* no held/looped underrun frame; no unmeasured timing cuts; no per-event DOM trace;
* no temp files/locks/validation for sprite races; no masking gaps by raising
* runway; no ACK wait past next slot; no jitter re-anchor; no main-thread toBlob;
* no ScriptProcessor-only mic.
* DO NOT DELETE/REMOVE THIS BLOCK - NOSIGNUP.CHAT PROTOCOL CONTRACT.
*/
// ===== FILE MAP (sections in physical order) =====
// ABOVE (do not reorder): charter/soul header; vault+admin API+controlpanel;
// PROTOCOL CONTRACT (bookends — immutable); then this map.
// BLOCK 1 PHP config + /dev/shm storage + helpers (mirrors, sprites, pid_*)
// API encworker · micworklet · mirror gossip · upload · sprite fetch · seek/match/bridge
// SRC ?src=1 / ?download=1 source/parity stream
// HTML/CSS dual L/R shell · entry #disclaimerOverlay · Options/Mirrors/Donate/HD
// BLOCK 2 JS config + state · deviceId / API helper
// TICK payload builders · normalizePeerId / normalizePeerQuery
// BLOCK 3–9 utilities · forensic trace · capture · media · audio · pack · debug
// BLOCK 10–12 upload loop · fetch loop · playback timeline
// BLOCK 13–14 device switchers · bindings + disclaimer enter flow
// TAIL donate modal · network/mirror staging · empire DBG (opt-in)
// =================================================
// ===== BLOCK 1: PHP CONFIG + STORAGE DIRS =====
error_reporting(0); ini_set('display_errors', 0); ini_set('log_errors', 1);
$SPRITE_DIR = '/dev/shm/nosignup/sprite';
$MIRROR_FILE = '/dev/shm/nosignup/mirrors.txt';
$KYC_BASE = '/var/lib/nosignup/kyc';
$SEEK_MATCH_FRESH_MS = 3000;
$SPRITE_FRESH_SEC = 5;
$MIRROR_FRESH_SEC = 86400 * 30;
$MIRROR_CAP = 64;
if (!is_dir($SPRITE_DIR)) @mkdir($SPRITE_DIR, 0755, true);
if (!is_dir($KYC_BASE)) @mkdir($KYC_BASE, 0700, true);
if (is_dir($KYC_BASE)) @chmod($KYC_BASE, 0700);
$STORAGE_PROBLEMS = array();
if (!is_dir($SPRITE_DIR) || !is_writable($SPRITE_DIR)) {
$STORAGE_PROBLEMS[] = array('crit', 'Chat storage is not writable', $SPRITE_DIR,
'Frames cannot be stored, so chat will not work until this is fixed.');
} elseif (!is_dir($KYC_BASE) || !is_writable($KYC_BASE)) {
$STORAGE_PROBLEMS[] = array('warn', 'Verification (KYC) storage is not writable', $KYC_BASE,
'Chat works now; optional telemetry/kyc log is disabled until this folder exists and is writable.');
}
function lazy_expire($path) {
if (file_exists($path) && (time() - filemtime($path)) > 86400 * 30) {
@unlink($path);
}
}
function source_hash($source = null) {
$s = $source === null ? (string)@file_get_contents(__FILE__) : (string)$source;
if (substr($s, 0, 3) === "\xEF\xBB\xBF") $s = substr($s, 3);
$s = str_replace(["\r\n", "\r"], "\n", $s);
$s = preg_replace('/[ \t]+\n/', "\n", $s);
return hash('sha256', rtrim($s, "\n") . "\n");
}
/** P1-CHAT-MIRROR-POISON RR233: reject RFC2606/reserved + private; never sample poison. */
function mirror_host_ok($host) {
$host = strtolower(trim((string)$host));
if ($host === '') return false;
if (preg_match('/^(localhost|127\.|10\.|192\.168\.|172\.(1[6-9]|2\d|3[01])\.|0\.|169\.254\.|::1)/i', $host)) return false;
if (preg_match('/\.(example|invalid|test|localhost)$/i', $host)) return false;
if (preg_match('/^(example|invalid|test|localhost)$/i', $host)) return false;
if (preg_match('/(^|\.)example\.(com|net|org|edu)$/i', $host)) return false;
if (strpos($host, '.') === false && !filter_var($host, FILTER_VALIDATE_IP)) return false;
return true;
}
function mirror_ok($u) {
$u = trim((string)$u);
if ($u === '') return null;
if (!preg_match('#^https?://#i', $u)) $u = 'https://' . $u;
if (strlen($u) > 220) return null;
$p = @parse_url($u);
if (!$p || empty($p['host'])) return null;
$scheme = strtolower($p['scheme'] ?? 'https');
if ($scheme !== 'http' && $scheme !== 'https') return null;
$host = strtolower($p['host']);
if (!mirror_host_ok($host)) return null;
$port = isset($p['port']) ? ':' . (int)$p['port'] : '';
$path = $p['path'] ?? '/index.php';
if ($path === '' || $path === '/') $path = '/index.php';
elseif (!preg_match('/\.php$/i', $path)) $path = rtrim($path, '/') . '/index.php';
return $scheme . '://' . $host . $port . $path;
}
function mirrors_read() {
global $MIRROR_FILE, $MIRROR_FRESH_SEC;
if (!is_file($MIRROR_FILE)) return [];
$now = time(); $out = [];
foreach (@file($MIRROR_FILE, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) ?: [] as $line) {
$p = explode("\t", $line, 2);
$u = mirror_ok($p[0] ?? '');
$t = (int)($p[1] ?? 0);
if ($u !== null && $t > 0 && ($now - $t) < $MIRROR_FRESH_SEC) $out[$u] = $t;
}
return $out;
}
function mirrors_add($txt) {
global $MIRROR_FILE, $MIRROR_CAP;
$cur = mirrors_read(); $now = time(); $changed = false;
foreach (preg_split('/[\s,]+/', (string)$txt) as $u) {
$u = mirror_ok($u);
if ($u === null) continue;
unset($cur[$u]);
$cur[$u] = $now; $changed = true;
}
if (!$changed) return;
if (count($cur) > $MIRROR_CAP) $cur = array_slice($cur, -$MIRROR_CAP, null, true);
$s = '';
foreach ($cur as $u => $t) $s .= $u . "\t" . $t . "\n";
@file_put_contents($MIRROR_FILE, $s);
}
function mirrors_sample($n) {
$u = array_keys(mirrors_read());
if (!$u) return [];
shuffle($u);
return array_slice($u, 0, $n);
}
function sprite_info($pid) {
global $SPRITE_DIR;
$pid = preg_replace('/[^a-zA-Z0-9_\-]/', '', $pid);
if (strlen($pid) < 8) return null;
$file = "$SPRITE_DIR/$pid.bin";
if (!is_file($file)) return null;
$mt = @filemtime($file);
$sz = @filesize($file);
if ($mt === false || $sz === false) return null;
return [$file, $mt, $sz];
}
function pid_hd_video($pid) {
return preg_match('/_H_(L|R)(?:_S)?$/', $pid) === 1;
}
function pid_has_panel($pid) {
return preg_match('/_(?:H_)?(L|R)(?:_S)?$/', $pid) === 1;
}
function sprite_partial_info($prefix, $exclude = '') {
global $SPRITE_DIR, $SPRITE_FRESH_SEC;
$prefix = preg_replace('/[^a-zA-Z0-9_\-]/', '', $prefix);
$exclude = preg_replace('/[^a-zA-Z0-9_\-]/', '', $exclude);
$excludeBase = preg_replace('/_S$/', '', $exclude);
if (strlen($prefix) < 3) return null;
$hasMode = pid_has_panel($exclude);
$wantHd = pid_hd_video($exclude);
if (preg_match('/^(.+)_(L|R)$/', $prefix, $m)) {
$needle = $m[1]; $wantCh = $m[2];
} else {
$needle = $prefix; $wantCh = null;
}
$now = time();
$best = null; $bestMt = -1;
foreach (glob("$SPRITE_DIR/*.bin") ?: [] as $f) {
$pid = basename($f, '.bin');
$basePid = preg_replace('/_S$/', '', $pid);
if ($excludeBase !== '' && $basePid === $excludeBase) continue;
if (!preg_match('/^(.+)_(L|R)(?:_S)?$/', $pid, $pm)) continue;
if ($hasMode && pid_hd_video($pid) !== $wantHd) continue;
if ($wantCh !== null && $pm[2] !== $wantCh) continue;
$hay = $wantCh === null ? $pid : $pm[1];
if (stripos($hay, $needle) === false) continue;
$mt = @filemtime($f);
if ($mt === false || ($now - $mt) > $SPRITE_FRESH_SEC) continue;
$sz = @filesize($f);
if ($sz === false || $sz <= 0) continue;
if ($mt > $bestMt || ($mt === $bestMt && strcmp($pid, $best[0] ?? '') < 0)) {
$best = [$basePid, $f, $mt, $sz]; $bestMt = $mt;
}
}
return $best;
}
function sprite_tail_get($file, $size, $key) {
$fh = @fopen($file, 'rb');
if (!$fh) return null;
$st = @fstat($fh);
if ($st && isset($st['size'])) $size = $st['size'];
$h = fread($fh, 4);
if (strlen($h) < 4) { fclose($fh); return null; }
$vLen = unpack('N', $h)[1];
if (4 + $vLen + 4 > $size) { fclose($fh); return null; }
fseek($fh, 4 + $vLen);
$ah = fread($fh, 4);
if (strlen($ah) < 4) { fclose($fh); return null; }
$aLen = unpack('N', $ah)[1];
$tailStart = 8 + $vLen + $aLen;
if ($tailStart > $size) { fclose($fh); return null; }
fseek($fh, $tailStart);
$tail = stream_get_contents($fh);
fclose($fh);
foreach (explode("\n", $tail) as $line) {
$eq = strpos($line, '=');
if ($eq !== false && substr($line, 0, $eq) === $key) {
return preg_replace('/[^a-zA-Z0-9_\-]/', '', substr($line, $eq + 1));
}
}
return null;
}
function stream_sprite_file($file) {
$sz = @filesize($file);
if ($sz === false || $sz <= 0) return false;
header('Content-Type: application/octet-stream');
header('Content-Length: ' . $sz);
@readfile($file);
return true;
}
/* KYC privacy: server-local .salt + HMAC client tag (mirror work nsw_* shape; chat names) */
function kyc_priv_salt() {
global $KYC_BASE;
if (!is_dir($KYC_BASE)) @mkdir($KYC_BASE, 0700, true);
$f = $KYC_BASE . '/.salt';
if (is_file($f)) {
$s = trim((string)@file_get_contents($f));
if ($s !== '') return $s;
}
try { $s = bin2hex(random_bytes(32)); } catch (Exception $e) {
$s = hash('sha256', uniqid('', true) . mt_rand());
}
if (@file_put_contents($f, $s, LOCK_EX) !== false) @chmod($f, 0600);
return $s;
}
function kyc_client_tag($ip, $extra = '') {
return substr(hash_hmac('sha256', (string)$ip . '|' . $extra, kyc_priv_salt()), 0, 24);
}
function kyc_tag_dir($ip = null) {
global $KYC_BASE;
$ip = ($ip === null || $ip === '') ? (string)($_SERVER['REMOTE_ADDR'] ?? '0.0.0.0') : (string)$ip;
$d = $KYC_BASE . '/' . kyc_client_tag($ip, 'log');
if (!is_dir($d)) @mkdir($d, 0700, true);
return $d;
}
function log_kyc($peerId) {
$pid = preg_replace('/[^a-zA-Z0-9_\-]/', '', $peerId);
if (preg_match('/^(.+)_S$/', $pid, $m)) $pid = $m[1];
if ($pid === '') return;
$ip = (string)($_SERVER['REMOTE_ADDR'] ?? '0.0.0.0');
$tag = kyc_client_tag($ip, 'event');
$dir = kyc_tag_dir($ip);
if (!is_dir($dir)) return;
$logFile = "$dir/metadata.log";
lazy_expire($logFile);
/* no sample.jpg / no media persist; ts + client tag + peer + act only */
if (@file_put_contents($logFile, time() . ",$tag,$pid,kyc\n", FILE_APPEND | LOCK_EX) !== false) {
@chmod($logFile, 0600);
}
}
function log_kyc_session($peerId, $remoteId) {
$pid = preg_replace('/[^a-zA-Z0-9_\-]/', '', $peerId);
if (preg_match('/^(.+)_S$/', $pid, $m)) $pid = $m[1];
$rid = preg_replace('/[^a-zA-Z0-9_\-]/', '', $remoteId);
if ($pid === '' || $rid === '') return;
$ip = (string)($_SERVER['REMOTE_ADDR'] ?? '0.0.0.0');
$tag = kyc_client_tag($ip, 'event');
$dir = kyc_tag_dir($ip);
if (!is_dir($dir)) return;
$logFile = "$dir/metadata.log";
lazy_expire($logFile);
/* ts + client tag + peer + session + act; no raw ip/xff/ua */
if (@file_put_contents($logFile, time() . ",$tag,$pid,$rid,session\n", FILE_APPEND | LOCK_EX) !== false) {
@chmod($logFile, 0600);
}
}
function write_sprite($pid, $blob) {
global $SPRITE_DIR;
$pid = preg_replace('/[^a-zA-Z0-9_\-]/', '', $pid);
if (strlen($pid) < 8 || $blob === false || strlen($blob) === 0) return false;
$dst = "$SPRITE_DIR/$pid.bin";
$n = @file_put_contents($dst, $blob);
if ($n === false) return false;
if (!preg_match('/_S$/', $pid)) @unlink("$SPRITE_DIR/{$pid}_S.bin");
return true;
}
$a = $_GET['api'] ?? '';
if ($a !== '') {
header('Cache-Control: no-store, no-cache, must-revalidate');
/* WIRING-PARITY: public selfhash (trade-shape; no auth) */
if ($a === 'selfhash') {
nsp_json([
'ok' => true,
'version' => 'chat',
'sha256' => @hash_file('sha256', __FILE__) ?: null,
'file' => basename(__FILE__),
]);
}
// ===== ENCODER WORKER SCRIPT =====
if ($a === 'encworker' && $_SERVER['REQUEST_METHOD'] === 'GET') {
$worker = <<<'JS'
let _ocv=null,_octx=null;
self.onmessage=async (e)=>{
const d=e.data;
try{
const t0=performance.now();
if(!_ocv||_ocv.width!==d.w||_ocv.height!==d.h){ _ocv=new OffscreenCanvas(d.w,d.h); _octx=_ocv.getContext('2d'); }
_octx.putImageData(new ImageData(new Uint8ClampedArray(d.buf),d.w,d.h),0,0);
const t1=performance.now();
const b=await _ocv.convertToBlob({type:'image/jpeg',quality:d.q});
const ab=await b.arrayBuffer();
const t2=performance.now();
self.postMessage({id:d.id,ab:ab,wdraw:Math.round(t1-t0),wenc:Math.round(t2-t1)},[ab]);
}catch(err){ self.postMessage({id:d.id,err:String(err)}); }
};
JS;
header('Content-Type: application/javascript; charset=UTF-8');
header('Content-Length: ' . strlen($worker));
echo $worker;
exit;
}
if ($a === 'micworklet' && $_SERVER['REQUEST_METHOD'] === 'GET') {
$worker = <<<'JS'
class N extends AudioWorkletProcessor{constructor(o){super();let p=o&&o.processorOptions||{};this.r=p.targetRate||8000;this.c=p.chunkBytes||2048;this.q=sampleRate/this.r;this.n=0;this.a=[]}e(v){let s=Math.max(-32768,Math.min(32767,v*32768))|0,g=s<0?128:0;if(g)s=-s;s=Math.min(s+132,32767);let e=7,m=16384;while(e>0&&!(s&m)){e--;m>>=1}return~(g|e<<4|(s>>e+3&15))&255}p(b){this.a.push(b);while(this.a.length>=this.c){let o=new Uint8Array(this.a.splice(0,this.c));this.port.postMessage({buf:o.buffer},[o.buffer])}}process(i,o){let z=o[0]&&o[0][0];if(z)z.fill(0);let x=i[0]&&i[0][0];if(!x)return true;let r=this.q>0?this.q:sampleRate/this.r,p=this.n;while(p 1, 'mirrors' => mirrors_sample(8)], JSON_UNESCAPED_SLASHES);
header('Content-Length: ' . strlen($j));
echo $j;
exit;
}
// ===== UPLOAD =====
/** P1-CHAT-UPLOAD-METHOD RR209: non-POST must not fall through as unknown api (404).
* Sisters date/work/market answer write routes with 405 POST only. */
if ($a === 'upload' && strtoupper((string)($_SERVER['REQUEST_METHOD'] ?? '')) !== 'POST') {
nsp_json(['ok' => false, 'err' => 'POST only'], 405);
}
if ($a === 'upload' && $_SERVER['REQUEST_METHOD'] === 'POST') {
$codeStart = microtime(true);
$reqStart = $_SERVER['REQUEST_TIME_FLOAT'] ?? $codeStart; // pre-PHP time: body upload + FPM queue
$writes = 0;
header('Content-Type: application/json');
$body = @file_get_contents('php://input');
if ($body !== false && strlen($body) > 0) {
$mode = $_GET['mode'] ?? 'same';
$doKyc = (mt_rand(1, 128) === 1);
$kycPid = null;
if ($mode === 'split') {
$lenL = max(0, (int)($_GET['lenL'] ?? 0));
$lenR = max(0, (int)($_GET['lenR'] ?? 0));
if ($lenL > 0 && isset($_GET['peerIdL'])) {
$part = substr($body, 0, $lenL);
if (write_sprite($_GET['peerIdL'], $part)) {
$writes++;
if ($doKyc && $kycPid === null) { $kycPid = $_GET['peerIdL']; }
if (isset($_GET['sessL'])) log_kyc_session($_GET['peerIdL'], $_GET['sessL']);
}
}
if ($lenR > 0 && isset($_GET['peerIdR'])) {
$part = substr($body, $lenL, $lenR);
if (write_sprite($_GET['peerIdR'], $part)) {
$writes++;
if ($doKyc && $kycPid === null) { $kycPid = $_GET['peerIdR']; }
if (isset($_GET['sessR'])) log_kyc_session($_GET['peerIdR'], $_GET['sessR']);
}
}
} else {
foreach (['L', 'R'] as $ch) {
$key = 'peerId' . $ch;
if (isset($_GET[$key]) && write_sprite($_GET[$key], $body)) {
$writes++;
if ($doKyc && $kycPid === null) { $kycPid = $_GET[$key]; }
if (isset($_GET['sess' . $ch])) log_kyc_session($_GET[$key], $_GET['sess' . $ch]);
}
}
}
if ($doKyc && $kycPid !== null) log_kyc($kycPid);
}
header('X-Upload-Queue-Ms: ' . round(($codeStart - $reqStart) * 1000));
header('X-Upload-Code-Ms: ' . round((microtime(true) - $codeStart) * 1000));
header('X-Upload-Writes: ' . $writes);
header('X-Sprite-Store: shm');
header('Content-Length: 8'); // exact length of {"ok":1} - client finishes the response immediately, doesn't wait on connection framing
echo '{"ok":1}';
exit;
}
// ===== SPRITE FETCH =====
if ($a === 'sprite' && $_SERVER['REQUEST_METHOD'] === 'GET') {
header('Access-Control-Allow-Origin: *');
header('Access-Control-Expose-Headers: X-Match-Peer, X-Match-Sid, X-Match-Head, X-Resolved-Peer, X-Bridge-Target');
$pid = preg_replace('/[^a-zA-Z0-9_\-]/', '', $_GET['peerId'] ?? '');
if (strlen($pid) < 3) { http_response_code(400); exit; }
$fromPid = preg_replace('/[^a-zA-Z0-9_\-]/', '', $_GET['fromPeerId'] ?? '');
if ($fromPid !== '' && pid_has_panel($fromPid) && pid_has_panel($pid) && pid_hd_video($fromPid) !== pid_hd_video($pid)) {
http_response_code(404); exit;
}
$now = time();
if (preg_match('/^(.+)_(L|R)_S$/', $pid, $m)) {
$base = $m[1]; $ch = $m[2];
$candidates = [];
$nowMs = microtime(true) * 1000;
$wantHd = pid_hd_video($pid);
foreach (glob("$SPRITE_DIR/*_{$ch}_S.bin") ?: [] as $f) {
$other = basename($f, '.bin');
if ($other === $pid) continue;
if (pid_hd_video($other) !== $wantHd) continue;
$mt = @filemtime($f);
if ($mt === false) continue;
if (($nowMs - ($mt * 1000)) > $SEEK_MATCH_FRESH_MS) continue;
if (strpos($other, $base) === 0) continue;
$candidates[] = $other;
}
if ($candidates) {
$found = $candidates[array_rand($candidates)];
$remoteBase = preg_replace('/_S$/', '', $found);
$sz = @filesize("$SPRITE_DIR/$found.bin");
$sid = ($sz !== false) ? sprite_tail_get("$SPRITE_DIR/$found.bin", $sz, 'sid') : null;
$head = ($sz !== false) ? sprite_tail_get("$SPRITE_DIR/$found.bin", $sz, 'head') : null;
header('X-Match-Peer: ' . $remoteBase);
if ($sid !== null && $sid !== '') header('X-Match-Sid: ' . $sid);
if ($head !== null && $head !== '') header('X-Match-Head: ' . preg_replace('/[^0-9]/', '', $head));
header('Content-Type: application/octet-stream');
header('Content-Length: 0');
http_response_code(200);
exit;
}
http_response_code(204);
exit;
}
$resolvedPid = null;
$info = sprite_info($pid);
if ($info !== null && ($now - $info[1]) > $SPRITE_FRESH_SEC) $info = null;
if ($info === null && preg_match('/^.+_(L|R)$/', $pid)) {
$aliasInfo = sprite_info($pid . '_S');
if ($aliasInfo !== null && ($now - $aliasInfo[1]) <= $SPRITE_FRESH_SEC) $info = $aliasInfo;
}
if ($info === null) {
$partial = sprite_partial_info($pid, $fromPid);
if ($partial !== null) {
$resolvedPid = $partial[0];
$info = [$partial[1], $partial[2], $partial[3]];
}
}
if ($info === null || ($now - $info[1]) > $SPRITE_FRESH_SEC) { http_response_code(404); exit; }
if ($resolvedPid !== null) header('X-Resolved-Peer: ' . $resolvedPid);
$serve = $info[0];
$bt = sprite_tail_get($info[0], $info[2], 'bridge_target');
if ($bt !== null && $bt !== '' && $bt !== $pid) {
$btInfo = sprite_info($bt);
if ($btInfo !== null && ($now - $btInfo[1]) <= $SPRITE_FRESH_SEC) {
$serve = $btInfo[0];
header('X-Bridge-Target: ' . $bt);
}
}
if (!stream_sprite_file($serve)) http_response_code(404);
exit;
}
http_response_code(404);
exit;
}
if (isset($_GET['src']) || isset($_GET['download'])) {
$raw = (string)file_get_contents(__FILE__);
$download = isset($_GET['download']);
header('Content-Type: text/plain; charset=UTF-8');
header('Content-Disposition: ' . ($download ? 'attachment' : 'inline') . '; filename="index.php"');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Expose-Headers: X-NSC-Parity-SHA256, X-NSC-Source-SHA256');
header('X-NSC-Source-SHA256: ' . hash('sha256', $raw));
header('X-NSC-Parity-SHA256: ' . source_hash($raw));
header('Content-Length: ' . strlen($raw));
echo $raw;
exit;
}
?>
NOSIGNUP.CHAT · peer pixel chat (try a peer path)
! . Operator: make writable (mkdir + chown web user + chmod 755). Path not shown.
1 · LEFT 2 · RIGHT
WAIT
Try Peer
After enter: Try Peer — may wait · no match promised
WAIT
Try Peer
After enter: Try Peer — may wait · no match promised
Options Mirrors Donate
Peer chat · no signup Try a peer path Channels: Two panes L/R · try peer may wait · no match promised or paste PeerID Bridge + mode: Link L+R peers · HTML safer/pixelated HD clearer · IP may show No Accounts: No signup · no tracking accounts no app install No wallet here: Peer IDs stay in THIS browser only · no local balance Money/buy on nosignup.trade · optional donate No warranty, moderation, recovery, or recourse. Experimental · unmoderated · enter at your own risk.
I AGREE ENTER I am a minor — leave
x * Options
Performance Diagnostics - OFF Trace Diagnostics - OFF Center Crop - ON Prefer Trusted Mirrors - OFF Empire DBG overlay - OFF
x HD CLARITY · READ BEFORE SWITCHING
HD IS CLEARER — AND RISKIER Default is HTML mode: safer, heavily pixelated so faces and details stay hard to make out. HD is sharper and may show your IP to the other person.
HTML mode (default) Safer. Remote video stays pixelated. Goes through the site/mirrors. No account.
HD mode Clearer video. More direct link — your IP may show. Strangers can show anything. No filters.
Birth year and month stay in THIS browser only — not sent as an account. No moderation, warranty, recovery, or recourse.
Birth year Month
I am of age · turn on HD Stay in safer HTML mode
x $ one .php file. drop it on any PHP host. no build step. no dependencies. it just runs.
download index.php BITCOIN - electrum bc1qqnu6n0jztxl4f6krv7klradghle09uhyu7uymz
MONERO - feather 8Ab24DppUvcdtHfm7K8gTqdBTmPCBiak1GwxgPm1C3osYVQL2QdC1C8GMwggKF77RKKzDgP2R8E3VH8ifetsKms5AqkVyVg
LITECOIN - electrum-ltc ltc1qlpdy8qzejcmjdn6vwarpyz8djdlk780w4qkwyp
x + Mirrors
Free tributaries. Host a copy · help the network · zero cut · no price power. Free mirrors help the network; hosting is unpaid until parent-proven hits (no free daily host pay); host so the swarm stays hard to kill. No free pay on chat; money/buy lives on nosignup.trade .
Drop this file into any PHP host, then paste its URL or IP below. Your browser checks readable source parity before saving it locally.
download full index.php Submit mirror