SIMON Master Console Rebuild
True command center for SIMON + WEB360
This rebuild gives you a cleaner production spine: interactive tree, live viewer, guarded editor, dynamic graphics, architecture map, and note storage. It is designed to sit beside your existing
console.php
and become the stronger replacement path.
Dashboard
Tree
Viewer
System Map
File Registry
Notes
Files
15,025
Folders
377
Scanned Size
3.79 GB
PHP Files
791
Editable Text Files
12,309
File viewer
guarded to /htdocs
/ddg_proxy.php
<?php /* ============================================================ * SIMON · DuckDuckGo Search Proxy (HTML scraper) * ------------------------------------------------------------ * Upload to: /htdocs/connlink/test1/ui/ddg_proxy.php * Reached at: https://www.gaylordsinclair.com/connlink/test1/ui/ddg_proxy.php?q=QUERY * * DuckDuckGo's free Instant Answer API only returns zero-click * boxes, not organic results. For real web results we hit the * lightweight HTML endpoint at html.duckduckgo.com/html/ and * parse the result list. No key required. * * We also blend in the Instant Answer API ("abstract" + "related * topics") when it has data, labeled as the top hit. * * Query params: * q : query string (required) * num : 1..25 results (default 10) * ============================================================ */ header('Content-Type: application/json; charset=utf-8'); header('Access-Control-Allow-Origin: *'); header('Access-Control-Allow-Methods: GET, OPTIONS'); if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { http_response_code(204); exit; } $q = trim((string)($_GET['q'] ?? '')); if ($q === '') { echo json_encode(['ok'=>false, 'err'=>'missing q', 'results'=>[]]); exit; } $num = max(1, min(25, intval($_GET['num'] ?? 10))); /* ----- cache ----- */ $CACHE_DIR = __DIR__ . '/cache'; $CACHE_TTL = 600; if (!is_dir($CACHE_DIR)) { @mkdir($CACHE_DIR, 0755, true); } $ckey = sha1('ddg|' . $q . '|' . $num); $cfile = $CACHE_DIR . '/ddg_' . $ckey . '.json'; if (file_exists($cfile) && (time() - filemtime($cfile)) < $CACHE_TTL) { header('X-SIMON-Cache: HIT'); readfile($cfile); exit; } /* ----- fetch HTML results ----- */ $upstream = 'https://html.duckduckgo.com/html/?' . http_build_query(['q' => $q]); $ch = curl_init($upstream); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 12, CURLOPT_FOLLOWLOCATION => true, CURLOPT_MAXREDIRS => 3, CURLOPT_ENCODING => '', CURLOPT_HTTPHEADER => [ 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 13_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Safari/605.1.15', 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'Accept-Language: en-US,en;q=0.9', 'Referer: https://duckduckgo.com/', ], ]); $html = curl_exec($ch); $http = curl_getinfo($ch, CURLINFO_HTTP_CODE); $err = curl_error($ch); curl_close($ch); if ($html === false || $http >= 500 || $http === 0) { if (file_exists($cfile)) { header('X-SIMON-Cache: STALE'); readfile($cfile); exit; } http_response_code(502); echo json_encode(['ok'=>false,'err'=>'ddg upstream failed','detail'=>$err,'status'=>$http,'query'=>$q,'results'=>[]]); exit; } /* ----- parse HTML results ----- * * Each result is <div class="result results_links results_links_deep web-result"> * <h2 class="result__title"><a class="result__a" href="URL">TITLE</a></h2> * <a class="result__snippet" href="URL">SNIPPET</a> */ $items = []; libxml_use_internal_errors(true); $doc = new DOMDocument(); @$doc->loadHTML('<?xml encoding="utf-8" ?>' . $html); libxml_clear_errors(); $xp = new DOMXPath($doc); $nodes = $xp->query('//div[contains(concat(" ", normalize-space(@class), " "), " result ") and not(contains(@class,"result--ad"))]'); if ($nodes && $nodes->length) { foreach ($nodes as $r) { $aNode = $xp->query('.//a[contains(@class,"result__a")]', $r)->item(0); if (!$aNode) continue; $url = $aNode->getAttribute('href'); $title = trim(preg_replace('/\s+/', ' ', $aNode->textContent)); // DuckDuckGo redirects through /l/?uddg=... — unwrap it. if (stripos($url, '/l/?') !== false || stripos($url, 'duckduckgo.com/l/') !== false) { $parts = []; parse_str(parse_url($url, PHP_URL_QUERY) ?? '', $parts); if (!empty($parts['uddg'])) { $url = urldecode($parts['uddg']); } } if ($title === '' || $url === '' || stripos($url, 'http') !== 0) continue; $snipNode = $xp->query('.//a[contains(@class,"result__snippet")] | .//div[contains(@class,"result__snippet")]', $r)->item(0); $snip = $snipNode ? trim(preg_replace('/\s+/', ' ', $snipNode->textContent)) : ''; $src = ''; $citeNode = $xp->query('.//a[contains(@class,"result__url")] | .//span[contains(@class,"result__url")]', $r)->item(0); if ($citeNode) { $src = trim($citeNode->textContent); } if ($src === '') { $src = parse_url($url, PHP_URL_HOST) ?? ''; } $items[] = [ 'title' => $title, 'snippet' => $snip, 'url' => $url, 'source' => $src, 'image' => '', ]; if (count($items) >= $num) break; } } /* ----- optional: blend in Instant Answer abstract as top hit ----- */ $iaUrl = 'https://api.duckduckgo.com/?' . http_build_query([ 'q' => $q, 'format' => 'json', 'no_html' => 1, 'skip_disambig' => 1, 't' => 'simon', ]); $ch = curl_init($iaUrl); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 8, CURLOPT_HTTPHEADER => ['Accept: application/json', 'User-Agent: SIMON/1.0'], ]); $iaRaw = curl_exec($ch); curl_close($ch); $ia = $iaRaw ? json_decode($iaRaw, true) : null; if (is_array($ia) && !empty($ia['AbstractText']) && !empty($ia['AbstractURL'])) { array_unshift($items, [ 'title' => !empty($ia['Heading']) ? $ia['Heading'] : $q, 'snippet' => $ia['AbstractText'], 'url' => $ia['AbstractURL'], 'source' => !empty($ia['AbstractSource']) ? $ia['AbstractSource'] : 'DuckDuckGo', 'image' => !empty($ia['Image']) ? (stripos($ia['Image'],'http')===0 ? $ia['Image'] : 'https://duckduckgo.com'.$ia['Image']) : '', ]); if (count($items) > $num) { $items = array_slice($items, 0, $num); } } $out = [ 'ok' => true, 'query' => $q, 'results' => $items, 'meta' => [ 'engine' => 'duckduckgo', 'count' => count($items), 'status' => $http, ], ]; $encoded = json_encode($out, JSON_UNESCAPED_SLASHES|JSON_UNESCAPED_UNICODE); @file_put_contents($cfile, $encoded, LOCK_EX); header('X-SIMON-Cache: MISS'); echo $encoded;
Save file
Quick jump
open a path
Open