$ git clone http://thingshare.ion.nu/thingshare.git
commit 434cacd913ba19aa0fc239fc0dc894e6a968a7ff
Author: Alicia <...>
Date:   Fri Mar 20 17:51:21 2020 +0100

    Added an option to add indirect peers.

diff --git a/admin_federation.php b/admin_federation.php
index 00db036..2f7cbc1 100644
--- a/admin_federation.php
+++ b/admin_federation.php
@@ -19,9 +19,11 @@
 */
 include_once('db.php');
 include_once('nonce.php');
+include_once('rpc.php');
 if(!isset($_SESSION['id'])){die(_('Insufficient privileges'));}
 if(!($privileges&PRIV_FEDERATION)){die(_('Insufficient privileges'));}
 
+$error='';
 if(checknonce()) // Save changes
 {
   if(isset($_POST['options']))
@@ -40,7 +42,40 @@ if(checknonce()) // Save changes
     $peer=mysqli_real_escape_string($db, $_POST['deletepeer']);
     mysqli_query($db, 'delete from peers where domain="'.$peer.'"');
   }
+  if(isset($_POST['action']) && $_POST['action']=='addindirectpeers')
+  {
+    $peers=Array();
+    $blacklist=Array();
+    $res=mysqli_query($db, 'select domain, blacklist from peers order by domain asc');
+    while($row=mysqli_fetch_assoc($res))
+    {
+      if($row['blacklist']){$blacklist[]=$row['domain'];}else{$peers[]=$row['domain'];}
+    }
+    $oldpeers=count($peers); // For inserting new peers later
+    for($i=0; $i<count($peers); ++$i)
+    {
+      $newpeers=rpc_get($peers[$i], 'peers');
+      if(isset($newpeers['error']))
+      {
+        $error.=$peers[$i].': '.$newpeers['error'].'<br />';
+        if($i>=$oldpeers){array_splice($peers, $i, 1); --$i;} // Don't add if there are issues (but ignore old peers because we're not autoremoving)
+        continue;
+      }
+      foreach($newpeers['peers'] as $peer)
+      {
+        // Skip already known peers
+        if($peer==DOMAIN || in_array($peer, $peers) || in_array($peer, $blacklist)){continue;}
+        $peers[]=$peer;
+      }
+    }
+    for($i=$oldpeers; $i<count($peers); ++$i)
+    {
+      $peer=mysqli_real_escape_string($db, $peers[$i]);
+      mysqli_query($db, 'insert into peers(domain, blacklist) values("'.$peer.'", 0)');
+    }
+  }
 }
+if($error!=''){$error='<span class="error">'.$error.'</span>';}
 
 // Load current
 $peers='';
@@ -53,6 +88,7 @@ while($row=mysqli_fetch_assoc($res))
 }
 $autofollowcheck=(getoption('autofollow')?' checked':'');
 ?>
+<?=$error?>
 <form method="post"><?=nonce()?>
   <h2><?=_('Options')?></h2>
   <label><input type="checkbox" name="autofollow"<?=$autofollowcheck?> />Automatically follow peers</label><br />
@@ -61,5 +97,6 @@ $autofollowcheck=(getoption('autofollow')?' checked':'');
 <form method="post"><?=nonce()?>
 <h2><?=_('Peers')?></h2>
 <?=$peers?>
-  <input type="text" name="newpeer" placeholder="<?=_('domain.tld')?>" /><button name="addpeer"><?=_('Add peer')?></button><button name="blacklistpeer" title="<?=_('Don\'t autofollow this peer')?>"><?=_('Add peer to blacklist')?></button>
+  <input type="text" name="newpeer" placeholder="<?=_('domain.tld')?>" /><button name="addpeer"><?=_('Add peer')?></button><button name="blacklistpeer" title="<?=_('Don\'t autofollow this peer')?>"><?=_('Add peer to blacklist')?></button><br />
+  <button name="action" value="addindirectpeers"><?=_('Add indirect peers')?></button>
 </form>
diff --git a/index.php b/index.php
index 70517ff..3f2b34c 100644
--- a/index.php
+++ b/index.php
@@ -69,6 +69,7 @@ switch($path[1])
       case 'rpckey': print(json_encode(Array('public'=>file_get_contents('rpckey.pem')), true)); exit();
       case 'report': include('rpc_report.php'); exit();
       case 'messages': include('rpc_messages.php'); exit();
+      case 'peers': include('rpc_peers.php'); exit();
     }
     header('HTTP/1.1 404 Not found');
     die('{"httpresponse":404,"error":"Not found"}');
diff --git a/rpc_peers.php b/rpc_peers.php
new file mode 100644
index 0000000..b6394c6
--- /dev/null
+++ b/rpc_peers.php
@@ -0,0 +1,30 @@
+<...>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Affero General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Affero General Public License for more details.
+
+    You should have received a copy of the GNU Affero General Public License
+    along with this program.  If not, see <https://www.gnu.org/licenses/>.
+*/
+include_once('db.php');
+$obj=Array();
+$obj['peers']=Array();
+$obj['blacklist']=Array();
+$res=mysqli_query($db, 'select domain, blacklist from peers');
+while($row=mysqli_fetch_assoc($res))
+{
+  $obj[$row['blacklist']?'blacklist':'peers'][]=$row['domain'];
+}
+print(json_encode($obj));
+?>