PDO::ERRMODE_WARNING, PDO::ATTR_PERSISTENT=>PERSISTENT]);
}catch(PDOException $e){
http_response_code(500);
}
date_default_timezone_set('UTC');
//select output format
if(!isset($_REQUEST['format'])){
send_html();
}elseif($_REQUEST['format']==='text'){
send_text();
}elseif($_REQUEST['format']==='json'){
send_json();
}else{
send_html();
}
function send_html(): void
{
global $categories, $db, $language, $dir, $locale, $canonical_query;
$numrows = 0;
$not_found = false;
$style = '.row{display:flex;flex-wrap:wrap}.headerrow{font-weight:bold}.col{display:flex;flex:1;padding:3px 3px;flex-direction:column}';
$style .= '.red{color:red}.green{color:green}.up .col:nth-child(0n+3){background-color:#aaff88}.down .col:nth-child(0n+3){background-color:#ff4444}';
$style .= '.promo{outline:medium solid #FFD700}.list{padding:0;}.list li{display:inline-block;padding:0.35em}.pagination{font-size:1.2em}';
$style .= '.active{font-weight:bold}#maintable .col{word-break:break-all;min-width:6em}#maintable,#maintable .col{border: 1px solid black}';
$style .= '#maintable .col:nth-child(0n+2){flex-grow:3;min-width:12em} #maintable .col:nth-child(0n+3){word-break:unset}#maintable .col:last-child{max-width:6em}.software-link{text-align:center;font-size:small}';
send_headers([$style]);
asort($categories);
//sql for special categories
$special=[
_('All legitimate')=>"address!='' AND category!=15 AND id NOT IN (SELECT onion_id FROM " . PREFIX . 'phishing) AND timediff<604800',
_('Last added')=>"address!='' AND id NOT IN (SELECT onion_id FROM " . PREFIX . 'phishing)',
_('Offline > 1 week')=>"address!='' AND id NOT IN (SELECT onion_id FROM " . PREFIX . 'phishing) AND timediff>604800'
];
$canonical_query = [];
if(!isset($_REQUEST['pg'])){
$_REQUEST['pg']=1;
}else{
settype($_REQUEST['pg'], 'int');
if($_REQUEST['pg'] !== 1) {
$canonical_query[ 'pg' ] = $_REQUEST[ 'pg' ];
}
}
$category=count($categories);
if(isset($_REQUEST['cat']) && $_REQUEST['cat']<(count($categories)+count($special)+1) && $_REQUEST['cat']>=0){
settype($_REQUEST['cat'], 'int');
$category=$_REQUEST['cat'];
if($category !== count($categories)) {
$canonical_query[ 'cat' ] = $category;
}
}
$pages=1;
$admin_approval = '';
if(REQUIRE_APPROVAL){
$admin_approval = PREFIX . 'onions.approved = 1 AND';
}
$category_count = [];
$cat=count($categories);
if($db instanceof PDO) {
foreach ( $special as $name => $query ) {
if ( $name === _('Last added') ) {
$category_count[ $cat ] = PER_PAGE;
} else {
$category_count[ $cat ] = $db->query( 'SELECT COUNT(*) FROM ' . PREFIX . "onions WHERE $admin_approval $query;" )->fetch( PDO::FETCH_NUM )[ 0 ];
}
if ( $category == $cat ) {
$pages = ceil( $category_count[ $cat ] / PER_PAGE );
}
++$cat;
}
$category_count[ $cat ] = $db->query( 'SELECT COUNT(*) FROM ' . PREFIX . 'phishing, ' . PREFIX . 'onions WHERE ' . "$admin_approval " . PREFIX . "onions.id=onion_id AND address!='' AND timediff<604800;" )->fetch( PDO::FETCH_NUM )[ 0 ];
$category_count[ 'removed' ] = $db->query( 'SELECT COUNT(*) FROM ' . PREFIX . "onions WHERE address='';" )->fetch( PDO::FETCH_NUM )[ 0 ];
if ( REQUIRE_APPROVAL ) {
$category_count[ 'pending' ] = $db->query( 'SELECT COUNT(*) FROM ' . PREFIX . "onions WHERE approved = 0 AND address!='';" )->fetch( PDO::FETCH_NUM )[ 0 ];
$category_count[ 'rejected' ] = $db->query( 'SELECT COUNT(*) FROM ' . PREFIX . "onions WHERE approved = -1 AND address!='';" )->fetch( PDO::FETCH_NUM )[ 0 ];
}
$stmt = $db->prepare( 'SELECT COUNT(*) FROM ' . PREFIX . "onions WHERE $admin_approval category=? AND address!='' AND id NOT IN (SELECT onion_id FROM " . PREFIX . 'phishing) AND timediff<604800;' );
foreach ( $categories as $cat => $name ) {
$stmt->execute( [ $cat ] );
$category_count[ $cat ] = $stmt->fetch( PDO::FETCH_NUM )[ 0 ];
if ( $category == $cat ) {
$pages = ceil( $category_count[ $cat ] / PER_PAGE );
}
}
if ( $_REQUEST[ 'pg' ] > $pages && $_REQUEST[ 'pg' ] > 1 ) {
http_response_code( 404 );
$not_found = true;
}
}
if($not_found) {
$title = _( 'Onion link list - Not found');
}elseif(!empty($_REQUEST['q'])) {
$title = sprintf(_( 'Onion link list - Searching for %s' ), htmlspecialchars($_REQUEST['q']));
} elseif ($category === count($categories) && $_REQUEST[ 'pg' ] > 1){
$title = sprintf(_( 'Onion link list - Page %d' ), $_REQUEST[ 'pg' ]);
} elseif ($category < count($categories) && $_REQUEST[ 'pg' ] > 1){
$title = sprintf(_( 'Onion link list - %1$s - Page %2$d' ), $categories[$category], $_REQUEST[ 'pg' ]);
} elseif ($category < count($categories)){
$title = sprintf(_( 'Onion link list - %s' ), $categories[$category]);
} elseif ($category === count($categories) + 3){
$title = sprintf(_( 'Onion link list - %s' ), _('Phishing Clones'));
} elseif ($category === count($categories) + 2 && $_REQUEST[ 'pg' ] > 1){
$title = sprintf(_( 'Onion link list - %1$s - Page %2$d' ), _('Offline > 1 week'), $_REQUEST['pg']);
} elseif ($category === count($categories) + 2){
$title = sprintf(_( 'Onion link list - %s' ), _('Offline > 1 week'));
} elseif ($category === count($categories) + 1){
$title = sprintf(_( 'Onion link list - %s' ), _('Last added'));
} else {
$title = _( 'Onion link list' );
}
echo '
';
echo ''.$title.' ';
echo ' ';
echo ' ';
echo ' ';
echo ' ';
echo ' ';
echo ' ';
echo ' ';
alt_links();
echo ' ';
echo ' ';
echo ' ';
echo ' ';
echo ' ';
if(empty($_SERVER['QUERY_STRING'])) {
echo '';
}
echo '';
echo ' ';
echo '';
echo ''.$title.' ';
if(!isset($db)){
send_error(_('Error: No database connection!'));
}
echo ''._('I\'m not responsible for any content of websites linked here. 99% of darkweb sites selling anything are scams. Be careful and use your brain. I regularly receive E-Mails from people that were desperate to make money and fell for scammers, don\'t be one of them!').'
';
//update onions description form
echo '';
//search from
echo '
';
echo '
';
echo '';
print_langs();
//List special categories
echo ''._('Special categories:').' ';
$cat=count($categories);
foreach($special as $name=>$query){
echo ' '."$name ($category_count[$cat]) ";
++$cat;
}
echo ' '._('Phishing Clones')." ($category_count[$cat]) ";
echo ' '._('Removed/Child porn')." ($category_count[removed]) ";
if(REQUIRE_APPROVAL) {
echo ' '._('Pending approval')." ($category_count[pending]) ";
echo ' '._('Rejected')." ($category_count[rejected]) ";
}
echo ' ';
//List normal categories
echo '';
if($_SERVER['REQUEST_METHOD']==='POST' && !empty($_REQUEST['addr'])){
if(!preg_match('~(^(https?://)?([a-z0-9]*\.)?([a-z2-7]{55}d)(\.onion(/.*)?)?$)~i', trim($_REQUEST['addr']), $addr)){
echo ''._('Invalid onion address!').'
';
echo ''.sprintf(_('A valid address looks like this: %s'), 'http://danielas3rtn54uwmofdo3x2bsdifr47huasnmbgqzfrec5ubupvtpid.onion') .'
';
}else{
if(CAPTCHA !== 0) {
if ( ! isset( $_REQUEST[ 'challenge' ] ) ) {
send_error( _( 'Error: Wrong captcha' ) );
}
$stmt = $db->prepare( 'SELECT code FROM ' . PREFIX . 'captcha WHERE id=?;' );
$stmt->execute( [ $_REQUEST[ 'challenge' ] ] );
$stmt->bindColumn( 1, $code );
if ( ! $stmt->fetch( PDO::FETCH_BOUND ) ) {
send_error( _( 'Error: Captcha expired' ) );
}
$time = time();
$stmt = $db->prepare( 'DELETE FROM ' . PREFIX . 'captcha WHERE id=? OR time;' );
$stmt->execute( [ $_REQUEST[ 'challenge' ], $time - 3600 ] );
if ( $_REQUEST[ 'captcha' ] !== $code ) {
if ( strrev( $_REQUEST[ 'captcha' ] ) !== $code ) {
send_error( _( 'Error: Wrong captcha' ) );
}
}
}
$addr=strtolower($addr[4]);
$md5=md5($addr, true);
$stmt=$db->prepare('SELECT locked FROM ' . PREFIX . 'onions WHERE md5sum=?;');
$stmt->execute([$md5]);
$stmt->bindColumn(1, $locked);
if($category==count($categories)){
$category=0;
}
if(!isset($_POST['desc'])){
$desc='';
}else{
$desc=trim($_POST['desc']);
$desc=htmlspecialchars($desc);
$desc=preg_replace("/(\r?\n|\r\n?)/", ' ', $desc);
}
if(!$stmt->fetch(PDO::FETCH_BOUND)){//new link, add to database
$stmt=$db->prepare('INSERT INTO ' . PREFIX . 'onions (address, description, md5sum, category, timeadded, timechanged) VALUES (?, ?, ?, ?, ?, ?);');
$stmt->execute([$addr, $desc, $md5, $category, time(), time()]);
echo ''._('Successfully added onion address!').'
';
}elseif($locked==1){//locked, not editable
echo ''._('Sorry, editing this onion address has been locked!').'
';
}elseif($desc!==''){//update description
$stmt=$db->prepare('UPDATE ' . PREFIX . 'onions SET description=?, category=?, timechanged=? WHERE md5sum=?;');
$stmt->execute([$desc, $category, time(), $md5]);
echo ''._('Successfully updated description!').'
';
}elseif($category!=0){//update category only
$stmt=$db->prepare('UPDATE ' . PREFIX . 'onions SET category=?, timechanged=? WHERE md5sum=?;');
$stmt->execute([$category, time(), $md5]);
echo ''._('Successfully updated category!').'
';
}else{//nothing changed and already known
echo ''._('Thanks, but I already knew this address!').'
';
}
}
}
$pagination=get_pagination($category, $pages);
echo $pagination;
if(isset($_REQUEST['q'])){//run search query
$query=trim(str_replace(['http://', 'https://', '.onion', '/'], '', htmlspecialchars($_REQUEST['q'])));
$query="%$query%";
if(isset($_REQUEST['hidelocked'])){
$hidelocked='AND locked=0';
}else{
$hidelocked='';
}
if($category>=count($categories)){
$stmt=$db->prepare('SELECT address, lasttest, lastup, timeadded, description, locked, special FROM ' . PREFIX . "onions WHERE $admin_approval address!='' AND id NOT IN (SELECT onion_id FROM " . PREFIX . "phishing) AND timediff<604800 $hidelocked AND (description LIKE ? OR address LIKE ?) ORDER BY address;");
$stmt->execute([$query, $query]);
}else{
$stmt=$db->prepare('SELECT address, lasttest, lastup, timeadded, description, locked, special FROM ' . PREFIX . "onions WHERE $admin_approval address!='' AND category=? AND id NOT IN (SELECT onion_id FROM " . PREFIX . "phishing) AND timediff<604800 $hidelocked AND (description LIKE ? OR address LIKE ?) ORDER BY address;");
$stmt->execute([$category, $query, $query]);
}
$table=get_table($stmt, $numrows);
printf(''._('Searching for "%1$s", %2$d results found:').'
', trim(str_replace(['http://', 'https://', '.onion', '/'], '', htmlspecialchars($_REQUEST['q']))), $numrows);
echo $table;
}elseif($category>=count($categories)+count($special)){//show phishing clones
print_phishing_table();
}elseif($category>=count($categories)){//show special categories
$tmp=$category-count($categories);
$query = '';
foreach($special as $query){
if($tmp===0) break;
--$tmp;
}
if($category-count($categories)===1){
$query.=' ORDER BY id DESC LIMIT ' . PER_PAGE;
}else{
$query.=' ORDER BY address';
if($_REQUEST['pg']>0){
$offset=PER_PAGE*($_REQUEST['pg']-1);
$query.=' LIMIT ' . PER_PAGE ." OFFSET $offset";
}
}
$stmt=$db->query('SELECT address, lasttest, lastup, timeadded, description, locked, special FROM ' . PREFIX . "onions WHERE $admin_approval $query;");
echo get_table($stmt, $numrows, true);
}else{//show normal categories
if($_REQUEST['pg']>0){
$offset=PER_PAGE*($_REQUEST['pg']-1);
$offsetquery=' LIMIT ' . PER_PAGE . " OFFSET $offset";
}else{
$offsetquery='';
}
$stmt=$db->prepare('SELECT address, lasttest, lastup, timeadded, description, locked, special FROM ' . PREFIX . "onions WHERE $admin_approval address!='' AND id NOT IN (SELECT onion_id FROM " . PREFIX . "phishing) AND category=? AND timediff<604800 ORDER BY address$offsetquery;");
$stmt->execute([$category]);
echo get_table($stmt, $numrows, true);
}
echo ' ';
echo $pagination;
echo 'Onion Link List - ' . VERSION . '
';
echo ' ';
}
function get_table(PDOStatement $stmt, int &$numrows = 0, bool $promoted = false) : string {
global $db;
$time=time();
$admin_approval = '';
if(REQUIRE_APPROVAL){
$admin_approval = PREFIX . 'onions.approved = 1 AND';
}
ob_start();
echo '';
if($promoted){//print promoted links at the top
$time=time();
$promo=$db->prepare('SELECT address, lasttest, lastup, timeadded, description, locked, special FROM ' . PREFIX . "onions WHERE $admin_approval special>? AND address!='' AND id NOT IN (SELECT onion_id FROM " . PREFIX . 'phishing) AND timediff<604800 ORDER BY address;');
$promo->execute([$time]);
while($link=$promo->fetch(PDO::FETCH_ASSOC)){
if($link['lastup']===$link['lasttest']){
$class='up';
}else{
$class='down';
}
if($link['lastup']==0){
$lastup=_('Never');
}else{
$lastup=date('Y-m-d H:i', $link['lastup']);
}
if($link['lasttest']==0){
$class='';
}
$timeadded=date('Y-m-d', $link['timeadded']);
echo '
';
}
}
while($link=$stmt->fetch(PDO::FETCH_ASSOC)){
if($link['lastup']===$link['lasttest']){
$class='up';
}else{
$class='down';
}
if($link['lastup']==0){
$lastup=_('Never');
}else{
$lastup=date('Y-m-d H:i', $link['lastup']);
}
if($link['lasttest']==0){
$class='';
}
$timeadded=date('Y-m-d', $link['timeadded']);
if($link['special']>$time){
$class.=' promo';
}
if($link['locked']==1){
$edit='';
}else{
$edit='
'._('Edit').' ';
}
echo '
'.$link['description'].'
'.$lastup.'
'.$timeadded.'
'.$edit.'
'._('Test').' ';
++$numrows;
}
echo '
';
return ob_get_clean();
}
function print_phishing_table(): void
{
global $db;
$admin_approval = '';
if(REQUIRE_APPROVAL){
$admin_approval = 'approved = 1 AND';
}
echo '';
$stmt=$db->query('SELECT address, original, lasttest, lastup FROM ' . PREFIX . 'onions, ' . PREFIX . 'phishing WHERE ' . "$admin_approval " . PREFIX . "onions.id=onion_id AND address!='' AND timediff<604800 ORDER BY address;");
while($link=$stmt->fetch(PDO::FETCH_ASSOC)){
if($link['lastup']===$link['lasttest']){
$class='up';
}else{
$class='down';
}
if($link['lastup']==0){
$lastup=_('Never');
}else{
$lastup=date('Y-m-d H:i', $link['lastup']);
}
if($link['original']!==''){
$orig='
'.$link['original'].'.onion ';
}else{
$orig=_('Unknown');
}
echo '
'.$link['address'].'.onion
'.$orig.'
'.$lastup.'
';
}
echo '
';
}
function send_text(): void
{
global $db;
if(!isset($db)){
die(_('Error: No database connection!'));
}
header('Content-Type: text/plain; charset=UTF-8');
$admin_approval = '';
if(REQUIRE_APPROVAL){
$admin_approval = 'approved = 1 AND';
}
$stmt=$db->query('SELECT address FROM ' . PREFIX . "onions WHERE $admin_approval address!='' AND id NOT IN (SELECT onion_id FROM " . PREFIX . 'phishing) AND timediff<604800 ORDER BY address;');
while($tmp=$stmt->fetch(PDO::FETCH_NUM)){
echo "$tmp[0].onion\n";
}
}
function send_json(): void
{
global $db, $categories;
if(!isset($db)){
die(_('Error: No database connection!'));
}
header('Content-Type: application/json;');
$admin_approval = '';
if(REQUIRE_APPROVAL){
$admin_approval = PREFIX . 'onions.approved = 1 AND';
}
$data=['categories'=>$categories];
$stmt=$db->query('SELECT address, category, description, locked, lastup, lasttest, timeadded, timechanged FROM ' . PREFIX . "onions WHERE $admin_approval address!='' AND id NOT IN (SELECT onion_id FROM " . PREFIX . 'phishing) AND timediff<604800 ORDER BY address;');
$data['onions']=$stmt->fetchALL(PDO::FETCH_ASSOC);
$stmt=$db->query('SELECT md5sum FROM ' . PREFIX . "onions WHERE address='';");
while($tmp=$stmt->fetch(PDO::FETCH_ASSOC)){
$data['removed'][]=bin2hex($tmp['md5sum']);
}
$stmt=$db->query('SELECT address, original FROM ' . PREFIX . 'onions, ' . PREFIX . 'phishing WHERE onion_id=' . PREFIX . "onions.id AND $admin_approval address!='' AND timediff<604800 ORDER BY address;");
$data['phishing']=$stmt->fetchALL(PDO::FETCH_ASSOC);
echo json_encode($data);
}
function get_pagination(int $category, int $pages) : string {
$pagination = '';
if($pages<=1 || isset($_REQUEST['q'])){
return $pagination;
}
$pagination .= '';
return $pagination;
}
function send_captcha(): void
{
global $db;
if(CAPTCHA === 0 || !extension_loaded('gd')){
return;
}
$captchachars='ABCDEFGHJKMNPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz23456789';
$length=strlen($captchachars)-1;
$code='';
for($i=0;$i<5;++$i){
$code.=$captchachars[mt_rand(0, $length)];
}
$randid=mt_rand();
$time=time();
$stmt=$db->prepare('INSERT INTO ' . PREFIX . 'captcha (id, time, code) VALUES (?, ?, ?);');
$stmt->execute([$randid, $time, $code]);
echo ''._('Copy:');
if(CAPTCHA === 1){
$im = imagecreatetruecolor(55, 24);
$bg = imagecolorallocate($im, 0, 0, 0);
$fg = imagecolorallocate($im, 255, 255, 255);
imagefill($im, 0, 0, $bg);
imagestring($im, 5, 5, 5, $code, $fg);
echo ' ';
echo '
';
}
function send_error(string $msg): void
{
die(''.$msg.'