$ git clone http://thingshare.ion.nu/thingshare.git
commit 9b1f646aece2cb94508f7139177481f0fb4b518a
Author: Alicia <...>
Date:   Sun Mar 29 22:01:47 2020 +0200

    Sanitize inputs for HTML-injection.

diff --git a/editprofile.php b/editprofile.php
index ae06395..74050bc 100644
--- a/editprofile.php
+++ b/editprofile.php
@@ -39,9 +39,9 @@ $res=mysqli_fetch_assoc($res);
 <form method="post">
   <?=nonce()?>
   <a href="<?=BASEURL?>/changepassword"><?=_('Change password')?></a><br />
-  <?=_('Display name:')?> <input type="text" name="displayname" value="<?=$res['displayname']?>" /><br />
+  <?=_('Display name:')?> <input type="text" name="displayname" value="<?=htmlentities($res['displayname'])?>" /><br />
   <?=_('Profile:')?><br />
-  <textarea name="profile" rows="15" style="width:100%;" onchange="document.getElementById('mdpreview').innerHTML='Markdown preview:<br />'+Mdjs.md2html(this.value);" onkeyup="this.onchange();"><?=$res['profile']?></textarea><br />
+  <textarea name="profile" rows="15" style="width:100%;" onchange="document.getElementById('mdpreview').innerHTML='Markdown preview:<br />'+Mdjs.md2html(this.value.replace(/&/g,'&amp;amp;').replace(/</g,'&amp;lt;'));" onkeyup="this.onchange();"><?=htmlentities($res['profile'])?></textarea><br />
   <div id="mdpreview"></div>
   <button><?=_('Save')?></button>
 </form>
diff --git a/editthing.php b/editthing.php
index 53e031d..4ca36ee 100644
--- a/editthing.php
+++ b/editthing.php
@@ -214,7 +214,7 @@ function morefiles(prev)
   <input type="hidden" name="MAX_FILE_SIZE" value="<?=$maxsize?>" /><!-- This limit is taken from the upload_max_filesize value in php.ini -->
   <?=_('Name:')?> <input type="text" name="name" value="<?=htmlentities($name)?>" /><br />
   <?=_('Description:')?><br />
-  <textarea name="description" rows="15" style="width:100%;" onchange="document.getElementById('mdpreview').innerHTML='Markdown preview:<br />'+Mdjs.md2html(this.value);" onkeyup="this.onchange();"><?=htmlentities($description)?></textarea><br />
+  <textarea name="description" rows="15" style="width:100%;" onchange="document.getElementById('mdpreview').innerHTML='Markdown preview:<br />'+Mdjs.md2html(this.value.replace(/&/g,'&amp;amp;').replace(/</g,'&amp;lt;'));" onkeyup="this.onchange();"><?=htmlentities($description)?></textarea><br />
   <div id="mdpreview"></div>
   <div class="paragraph">
     <?=_('License')?>:
diff --git a/head.php b/head.php
index a1ac9b3..5b28e6f 100644
--- a/head.php
+++ b/head.php
@@ -65,7 +65,7 @@ $search=htmlentities(isset($_GET['q'])?$_GET['q']:'');
     </div>
     <div id="user"><?php if(isset($_SESSION['name'])){ ?>
       <!-- Link to user settings, messages -->
-      <a href="<?=BASEURL?>/user/<...>">My profile</a>
+      <a href="<?=BASEURL?>/user/<...>">My profile</a>
       <a href="<?=BASEURL?>/messages"<?=$unreadmsgs?>>Messages</a>
       <a href="<?=$logoutlink?>">Log out</a>
     <?php }else{ ?>
diff --git a/messages.php b/messages.php
index edee07d..1025643 100644
--- a/messages.php
+++ b/messages.php
@@ -103,7 +103,7 @@ if(!isset($path[2]) || $path[2]=='') // Overview
   while($row=mysqli_fetch_assoc($res))
   {
     $user=(($row['recipient']==$_SESSION['name'].'@'.DOMAIN)?$row['sender']:$row['recipient']);
-    $user='<a href="'.BASEURL.'/user/'.$user.'" title="'.htmlentities($user).'">'.htmlentities(getdisplayname($user)).'</a>';
+    $user='<a href="'.BASEURL.'/user/'.htmlentities($user).'" title="'.htmlentities($user).'">'.htmlentities(getdisplayname($user)).'</a>';
     $subjectline=htmlentities($row['subject']);
     $chain=htmlentities($row['chain']);
     $aclass=($row['msgread']?'':' class="highlight"'); // Highlight link if unread
@@ -122,8 +122,8 @@ elseif($error=='' && $path[2]!='new') // Thread view
   while($row=mysqli_fetch_assoc($res))
   {
     $sender=htmlentities($row['sender']);
-    $displayname=getdisplayname($row['sender']);
-    $msg=$md->text($row['message']);
+    $displayname=htmlentities(getdisplayname($row['sender']));
+    $msg=$md->text(htmlentities($row['message']));
     $time=htmlentities($row['sent']);
 // TODO: CSS for this
     $messages.='<div class="message'.($row['msgread']?'':' message_unread').'"><div class="message_sender"><a href="'.BASEURL.'/user/'.$sender.'" title="'.$sender.'">'.$displayname.'</a> <span class="time">'.$time.'</span></div>'.$msg.'</div>';
@@ -133,14 +133,14 @@ elseif($error=='' && $path[2]!='new') // Thread view
 }
 if($path[2]=='new')
 {
-  $to='<label>'._('To:').' <...></label><br />';
+  $to='<label>'._('To:').' <...></label><br />';
 }else{
-  $to=_('To:').' '.$to.'<br />';
+  $to=_('To:').' '.htmlentities($to).'<br />';
 }
 if($error!=''){$info='<span class="error">'.$error.'</span>';}
 include_once('head.php');
 ?>
-<h1><?=(($subject=='')?_('Messages'):$subject)?></h1>
+<h1><?=(($subject=='')?_('Messages'):htmlentities($subject))?></h1>
 <?=$info?>
 <table>
   <?=$header?>
@@ -151,7 +151,7 @@ include_once('head.php');
 <?=(($path[2]=='new')?'':'<h2>'._('Reply').'</h2>')?>
 <form method="post" action="<?=BASEURL?>/messages/<?=$path[2]?>"><?=nonce().$to?>
   <?=_('Subject:')?> <input type="text" name="subject" value="<?=$subject?>" /><br />
-  <textarea rows="12" style="width:100%;" name="msg" onchange="document.getElementById('mdpreview').innerHTML='Markdown preview:<br />'+Mdjs.md2html(this.value);" onkeyup="this.onchange();"></textarea>
+  <textarea rows="12" style="width:100%;" name="msg" onchange="document.getElementById('mdpreview').innerHTML='Markdown preview:<br />'+Mdjs.md2html(this.value.replace(/&/g,'&amp;amp;').replace(/</g,'&amp;lt;'));" onkeyup="this.onchange();"></textarea>
   <div id="mdpreview"></div>
   <button><?=_('Send')?></button>
 </form>
diff --git a/rpc_user.php b/rpc_user.php
index db7756e..25c3b0f 100644
--- a/rpc_user.php
+++ b/rpc_user.php
@@ -20,7 +20,7 @@
 if(!isset($path[3])){die();}
 include_once('db.php');
 include_once('files.php');
-$user=mysqli_real_escape_string($db, $path[3]);
+$user=mysqli_real_escape_string($db, urldecode($path[3]));
 $res=mysqli_query($db, 'select id, displayname, profile, status from users where name="'.$user.'"');
 $res=mysqli_fetch_assoc($res);
 if(!$res){header('HTTP/1.1 404 Not found'); die('{"error":"User not found"}');}
diff --git a/search.php b/search.php
index ca6ef45..1b7f112 100644
--- a/search.php
+++ b/search.php
@@ -77,7 +77,9 @@ usort($results, 'sortthings');
 $things='';
 foreach($results as $thing)
 {
-  $things.='<div class="thing"><div class="boxtop">By <a href="'.BASEURL.'/user/'.$thing['by']['name'].'@'.$thing['peer'].'" title="'.$thing['by']['name'].'@'.$thing['peer'].'">'.$thing['by']['displayname'].'</a></div><...><div class="boxbottom">'.htmlentities($thing['name']).'</div><img src="https://'.$thing['peer'].$thing['preview'].'" /></a></div>';
+  $by=htmlentities($thing['by']['name']);
+  $by='<a href="'.BASEURL.'/user/'.$by.'@'.$thing['peer'].'" title="'.$by.'@'.$thing['peer'].'">'.htmlentities($thing['by']['displayname']).'</a>';
+  $things.='<div class="thing"><div class="boxtop">By '.$by.'</div><...><div class="boxbottom">'.htmlentities($thing['name']).'</div><img src="https://'.$thing['peer'].$thing['preview'].'" /></a></div>';
 }
 ?>
 <div class="sidebar">
diff --git a/start.php b/start.php
index 307b5b6..768f73d 100644
--- a/start.php
+++ b/start.php
@@ -24,7 +24,9 @@ $things='';
 $res=rpc_get(DOMAIN, 'search//newest/10/0');
 foreach($res as $thing)
 {
-  $things.='<div class="thing"><div class="boxtop">By <a href="'.BASEURL.'/user/'.$thing['by']['name'].'@'.DOMAIN.'" title="'.$thing['by']['name'].'@'.DOMAIN.'">'.$thing['by']['displayname'].'</a></div><...><div class="boxbottom">'.htmlentities($thing['name']).'</div><img src="https://'.DOMAIN.$thing['preview'].'" /></a></div>';
+  $by=htmlentities($thing['by']['name']);
+  $by='<a href="'.BASEURL.'/user/'.$by.'@'.DOMAIN.'" title="'.$by.'@'.DOMAIN.'">'.htmlentities($thing['by']['displayname']).'</a>';
+  $things.='<div class="thing"><div class="boxtop">By '.$by.'</div><...><div class="boxbottom">'.htmlentities($thing['name']).'</div><img src="https://'.DOMAIN.$thing['preview'].'" /></a></div>';
 }
 // Get statistics
 function getcount($table)
diff --git a/thing.php b/thing.php
index cc5722d..b22126e 100644
--- a/thing.php
+++ b/thing.php
@@ -29,6 +29,8 @@ if(isset($thingobj['error']))
   exit();
 }
 $name=htmlentities($thingobj['name']);
+$by=htmlentities($thingobj['by']['name']);
+$by='<a href="'.BASEURL.'/user/'.$by.'@'.$thing[1].'" title="'.$by.'@'.$thing[1].'">'.htmlentities($thingobj['by']['displayname']).'</a>';
 $license=$thingobj['license']['name'];
 if($license=='other')
 {
@@ -39,7 +41,7 @@ if($license=='other')
 }
 include_once('parsedown/Parsedown.php');
 $md=new Parsedown();
-$description=$md->text($thingobj['description']);
+$description=$md->text(htmlentities($thingobj['description']));
 if(isset($_SESSION['name']))
 {
   if($thing[1]==DOMAIN && $thingobj['by']['name']==$_SESSION['name'])
@@ -58,7 +60,7 @@ foreach($thingobj['files'] as $file)
   $files.='<a href="https://'.$thing[1].$file['path'].'" download="'.htmlentities($file['name']).'" type="'.$type.'"><div class="boxbottom">'.htmlentities($file['name']).'</div><img src="https://'.$thing[1].$file['preview'].'" /></a></div>';
 }
 ?>
-<h1><?=$name?> <small class="subheader">by <a href="<?=BASEURL?>/user/<?=$thingobj['by']['name']?>@<?=$thing[1]?>" title="<?=$thingobj['by']['name']?>@<?=$thing[1]?>"><?=htmlentities($thingobj['by']['displayname'])?></a></small></h1>
+<h1><?=$name?> <small class="subheader">by <?=$by?></small></h1>
 <small><?=sprintf(_('Published on %s under the license %s'), '<span class="time">'.htmlentities($thingobj['date']).'</span>', $license)?></small><br />
 <?=$description?><br />
 <?=$files?>
diff --git a/user.php b/user.php
index 722334a..16fc7c1 100644
--- a/user.php
+++ b/user.php
@@ -29,12 +29,12 @@ if(isset($userobj['error']))
   exit();
 }
 $displayname=htmlentities($userobj['displayname']);
-$username=htmlentities(implode('@',$user));
+$username=htmlentities(urldecode(implode('@',$user)));
 include_once('parsedown/Parsedown.php');
 $md=new Parsedown();
-$profile=$md->text($userobj['profile']);
+$profile=$md->text(htmlentities($userobj['profile']));
 $things='';
-if($user[1]==DOMAIN && $user[0]==$_SESSION['name'])
+if($user[1]==DOMAIN && urldecode($user[0])==$_SESSION['name'])
 {
   $profile.='<a href="'.BASEURL.'/editprofile">'._('Edit').'</a>';
   $things='<div class="thing thing-add"><a href="'.BASEURL.'/editthing/new">+</a></div>';