aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorVirtualTam <tamisier.aurelien@gmail.com>2015-07-12 19:56:13 +0200
committerVirtualTam <tamisier.aurelien@gmail.com>2015-07-12 19:56:13 +0200
commit5b0ebbc5de06b8a0e9679b78b45d0dc755db7986 (patch)
treeed6a7f6c7ea02d0942d32c31637553976e978c5f
parent1dcbe29611a4ba4b4b2d37954105c1fc8da33496 (diff)
parent775803a05cdba9d7fc1b37af4b15ecd80a8cbcc2 (diff)
downloadShaarli-5b0ebbc5de06b8a0e9679b78b45d0dc755db7986.tar.gz
Shaarli-5b0ebbc5de06b8a0e9679b78b45d0dc755db7986.tar.zst
Shaarli-5b0ebbc5de06b8a0e9679b78b45d0dc755db7986.zip
Merge pull request #257 from ArthurHoaro/tag-http-referer
Prevent redirection loop everytime we rely on HTTP_REFERER
-rw-r--r--application/Utils.php34
-rw-r--r--index.php91
-rw-r--r--tests/UtilsTest.php27
3 files changed, 108 insertions, 44 deletions
diff --git a/application/Utils.php b/application/Utils.php
index a1e97b35..658b97bc 100644
--- a/application/Utils.php
+++ b/application/Utils.php
@@ -84,4 +84,36 @@ function checkDateFormat($format, $string)
84 $date = DateTime::createFromFormat($format, $string); 84 $date = DateTime::createFromFormat($format, $string);
85 return $date && $date->format($string) == $string; 85 return $date && $date->format($string) == $string;
86} 86}
87?> 87
88/**
89 * Generate a header location from HTTP_REFERER.
90 * Make sure the referer is Shaarli itself and prevent redirection loop.
91 *
92 * @param string $referer - HTTP_REFERER.
93 * @param string $host - Server HOST.
94 * @param array $loopTerms - Contains list of term to prevent redirection loop.
95 *
96 * @return string $referer - final referer.
97 */
98function generateLocation($referer, $host, $loopTerms = array())
99{
100 $final_referer = '?';
101
102 // No referer if it contains any value in $loopCriteria.
103 foreach ($loopTerms as $value) {
104 if (strpos($referer, $value) !== false) {
105 return $final_referer;
106 }
107 }
108
109 // Remove port from HTTP_HOST
110 if ($pos = strpos($host, ':')) {
111 $host = substr($host, 0, $pos);
112 }
113
114 if (!empty($referer) && strpos(parse_url($referer, PHP_URL_HOST), $host) !== false) {
115 $final_referer = $referer;
116 }
117
118 return $final_referer;
119}
diff --git a/index.php b/index.php
index b705146a..bf0b99e0 100644
--- a/index.php
+++ b/index.php
@@ -1120,6 +1120,11 @@ function renderPage()
1120 if (empty($_SERVER['HTTP_REFERER'])) { header('Location: ?searchtags='.urlencode($_GET['addtag'])); exit; } // In case browser does not send HTTP_REFERER 1120 if (empty($_SERVER['HTTP_REFERER'])) { header('Location: ?searchtags='.urlencode($_GET['addtag'])); exit; } // In case browser does not send HTTP_REFERER
1121 parse_str(parse_url($_SERVER['HTTP_REFERER'],PHP_URL_QUERY), $params); 1121 parse_str(parse_url($_SERVER['HTTP_REFERER'],PHP_URL_QUERY), $params);
1122 1122
1123 // Prevent redirection loop
1124 if (isset($params['addtag'])) {
1125 unset($params['addtag']);
1126 }
1127
1123 // Check if this tag is already in the search query and ignore it if it is. 1128 // Check if this tag is already in the search query and ignore it if it is.
1124 // Each tag is always separated by a space 1129 // Each tag is always separated by a space
1125 if (isset($params['searchtags'])) { 1130 if (isset($params['searchtags'])) {
@@ -1148,16 +1153,29 @@ function renderPage()
1148 } 1153 }
1149 1154
1150 // -------- User clicks on a tag in result count: Remove the tag from the list of searched tags (searchtags=...) 1155 // -------- User clicks on a tag in result count: Remove the tag from the list of searched tags (searchtags=...)
1151 if (isset($_GET['removetag'])) 1156 if (isset($_GET['removetag'])) {
1152 {
1153 // Get previous URL (http_referer) and remove the tag from the searchtags parameters in query. 1157 // Get previous URL (http_referer) and remove the tag from the searchtags parameters in query.
1154 if (empty($_SERVER['HTTP_REFERER'])) { header('Location: ?'); exit; } // In case browser does not send HTTP_REFERER 1158 if (empty($_SERVER['HTTP_REFERER'])) {
1155 parse_str(parse_url($_SERVER['HTTP_REFERER'],PHP_URL_QUERY), $params); 1159 header('Location: ?');
1156 if (isset($params['searchtags'])) 1160 exit;
1157 { 1161 }
1162
1163 // In case browser does not send HTTP_REFERER
1164 parse_str(parse_url($_SERVER['HTTP_REFERER'], PHP_URL_QUERY), $params);
1165
1166 // Prevent redirection loop
1167 if (isset($params['removetag'])) {
1168 unset($params['removetag']);
1169 }
1170
1171 if (isset($params['searchtags'])) {
1158 $tags = explode(' ',$params['searchtags']); 1172 $tags = explode(' ',$params['searchtags']);
1159 $tags=array_diff($tags, array($_GET['removetag'])); // Remove value from array $tags. 1173 $tags=array_diff($tags, array($_GET['removetag'])); // Remove value from array $tags.
1160 if (count($tags)==0) unset($params['searchtags']); else $params['searchtags'] = implode(' ',$tags); 1174 if (count($tags)==0) {
1175 unset($params['searchtags']);
1176 } else {
1177 $params['searchtags'] = implode(' ',$tags);
1178 }
1161 unset($params['page']); // We also remove page (keeping the same page has no sense, since the results are different) 1179 unset($params['page']); // We also remove page (keeping the same page has no sense, since the results are different)
1162 } 1180 }
1163 header('Location: ?'.http_build_query($params)); 1181 header('Location: ?'.http_build_query($params));
@@ -1165,33 +1183,24 @@ function renderPage()
1165 } 1183 }
1166 1184
1167 // -------- User wants to change the number of links per page (linksperpage=...) 1185 // -------- User wants to change the number of links per page (linksperpage=...)
1168 if (isset($_GET['linksperpage'])) 1186 if (isset($_GET['linksperpage'])) {
1169 { 1187 if (is_numeric($_GET['linksperpage'])) {
1170 if (is_numeric($_GET['linksperpage'])) { $_SESSION['LINKS_PER_PAGE']=abs(intval($_GET['linksperpage'])); } 1188 $_SESSION['LINKS_PER_PAGE']=abs(intval($_GET['linksperpage']));
1171 // Make sure the referrer is Shaarli itself. 1189 }
1172 $referer = '?'; 1190
1173 if (!empty($_SERVER['HTTP_REFERER']) && strcmp(parse_url($_SERVER['HTTP_REFERER'],PHP_URL_HOST),$_SERVER['HTTP_HOST'])==0) 1191 header('Location: '. generateLocation($_SERVER['HTTP_REFERER'], $_SERVER['HTTP_HOST'], array('linksperpage')));
1174 $referer = $_SERVER['HTTP_REFERER'];
1175 header('Location: '.$referer);
1176 exit; 1192 exit;
1177 } 1193 }
1178 1194
1179 // -------- User wants to see only private links (toggle) 1195 // -------- User wants to see only private links (toggle)
1180 if (isset($_GET['privateonly'])) 1196 if (isset($_GET['privateonly'])) {
1181 { 1197 if (empty($_SESSION['privateonly'])) {
1182 if (empty($_SESSION['privateonly'])) 1198 $_SESSION['privateonly'] = 1; // See only private links
1183 { 1199 } else {
1184 $_SESSION['privateonly']=1; // See only private links
1185 }
1186 else
1187 {
1188 unset($_SESSION['privateonly']); // See all links 1200 unset($_SESSION['privateonly']); // See all links
1189 } 1201 }
1190 // Make sure the referrer is Shaarli itself. 1202
1191 $referer = '?'; 1203 header('Location: '. generateLocation($_SERVER['HTTP_REFERER'], $_SERVER['HTTP_HOST'], array('privateonly')));
1192 if (!empty($_SERVER['HTTP_REFERER']) && strcmp(parse_url($_SERVER['HTTP_REFERER'],PHP_URL_HOST),$_SERVER['HTTP_HOST'])==0)
1193 $referer = $_SERVER['HTTP_REFERER'];
1194 header('Location: '.$referer);
1195 exit; 1204 exit;
1196 } 1205 }
1197 1206
@@ -1398,10 +1407,10 @@ function renderPage()
1398 1407
1399 // If we are called from the bookmarklet, we must close the popup: 1408 // If we are called from the bookmarklet, we must close the popup:
1400 if (isset($_GET['source']) && ($_GET['source']=='bookmarklet' || $_GET['source']=='firefoxsocialapi')) { echo '<script>self.close();</script>'; exit; } 1409 if (isset($_GET['source']) && ($_GET['source']=='bookmarklet' || $_GET['source']=='firefoxsocialapi')) { echo '<script>self.close();</script>'; exit; }
1401 $returnurl = ( isset($_POST['returnurl']) ? $_POST['returnurl'] : '?' ); 1410 $returnurl = ( !empty($_POST['returnurl']) ? escape($_POST['returnurl']) : '?' );
1402 $returnurl .= '#'.smallHash($linkdate); // Scroll to the link which has been edited. 1411 $returnurl .= '#'.smallHash($_POST['lf_linkdate']); // Scroll to the link which has been edited.
1403 if (strstr($returnurl, "do=addlink")) { $returnurl = '?'; } //if we come from ?do=addlink, set returnurl to homepage instead 1412 $location = generateLocation($returnurl, $_SERVER['HTTP_HOST'], array('addlink', 'post', 'edit_link'));
1404 header('Location: '.$returnurl); // After saving the link, redirect to the page the user was on. 1413 header('Location: '. $location); // After saving the link, redirect to the page the user was on.
1405 exit; 1414 exit;
1406 } 1415 }
1407 1416
@@ -1412,6 +1421,7 @@ function renderPage()
1412 if (isset($_GET['source']) && ($_GET['source']=='bookmarklet' || $_GET['source']=='firefoxsocialapi')) { echo '<script>self.close();</script>'; exit; } 1421 if (isset($_GET['source']) && ($_GET['source']=='bookmarklet' || $_GET['source']=='firefoxsocialapi')) { echo '<script>self.close();</script>'; exit; }
1413 $returnurl = ( isset($_POST['returnurl']) ? $_POST['returnurl'] : '?' ); 1422 $returnurl = ( isset($_POST['returnurl']) ? $_POST['returnurl'] : '?' );
1414 $returnurl .= '#'.smallHash($_POST['lf_linkdate']); // Scroll to the link which has been edited. 1423 $returnurl .= '#'.smallHash($_POST['lf_linkdate']); // Scroll to the link which has been edited.
1424 $returnurl = generateLocation($returnurl, $_SERVER['HTTP_HOST'], array('addlink', 'post', 'edit_link'));
1415 header('Location: '.$returnurl); // After canceling, redirect to the page the user was on. 1425 header('Location: '.$returnurl); // After canceling, redirect to the page the user was on.
1416 exit; 1426 exit;
1417 } 1427 }
@@ -1444,18 +1454,15 @@ function renderPage()
1444 // redirect is not satisfied, and only then redirect to / 1454 // redirect is not satisfied, and only then redirect to /
1445 $location = "?"; 1455 $location = "?";
1446 // Self redirection 1456 // Self redirection
1447 if (count($_GET) == 0 || 1457 if (count($_GET) == 0
1448 isset($_GET['page']) || 1458 || isset($_GET['page'])
1449 isset($_GET['searchterm']) || 1459 || isset($_GET['searchterm'])
1450 isset($_GET['searchtags'])) { 1460 || isset($_GET['searchtags'])
1451 1461 ) {
1452 if (isset($_POST['returnurl'])) { 1462 if (isset($_POST['returnurl'])) {
1453 $location = $_POST['returnurl']; // Handle redirects given by the form 1463 $location = $_POST['returnurl']; // Handle redirects given by the form
1454 } 1464 } else {
1455 1465 $location = generateLocation($_SERVER['HTTP_REFERER'], $_SERVER['HTTP_HOST'], array('delete_link'));
1456 if ($location === "?" &&
1457 isset($_SERVER['HTTP_REFERER'])) { // Handle HTTP_REFERER in case we're not coming from the same place.
1458 $location = $_SERVER['HTTP_REFERER'];
1459 } 1466 }
1460 } 1467 }
1461 1468
diff --git a/tests/UtilsTest.php b/tests/UtilsTest.php
index 90392dfb..8355c7f8 100644
--- a/tests/UtilsTest.php
+++ b/tests/UtilsTest.php
@@ -93,5 +93,30 @@ class UtilsTest extends PHPUnit_Framework_TestCase
93 $this->assertFalse(checkDateFormat('Y-m-d', '2015-06')); 93 $this->assertFalse(checkDateFormat('Y-m-d', '2015-06'));
94 $this->assertFalse(checkDateFormat('Ymd', 'DeLorean')); 94 $this->assertFalse(checkDateFormat('Ymd', 'DeLorean'));
95 } 95 }
96
97 /**
98 * Test generate location with valid data.
99 */
100 public function testGenerateLocation() {
101 $ref = 'http://localhost/?test';
102 $this->assertEquals($ref, generateLocation($ref, 'localhost'));
103 $ref = 'http://localhost:8080/?test';
104 $this->assertEquals($ref, generateLocation($ref, 'localhost:8080'));
105 }
106
107 /**
108 * Test generate location - anti loop.
109 */
110 public function testGenerateLocationLoop() {
111 $ref = 'http://localhost/?test';
112 $this->assertEquals('?', generateLocation($ref, 'localhost', ['test']));
113 }
114
115 /**
116 * Test generate location - from other domain.
117 */
118 public function testGenerateLocationOut() {
119 $ref = 'http://somewebsite.com/?test';
120 $this->assertEquals('?', generateLocation($ref, 'localhost'));
121 }
96} 122}
97?>