aboutsummaryrefslogtreecommitdiffhomepage
path: root/index.php
diff options
context:
space:
mode:
Diffstat (limited to 'index.php')
-rw-r--r--index.php120
1 files changed, 67 insertions, 53 deletions
diff --git a/index.php b/index.php
index c4c0d15a..a0a3a8c7 100644
--- a/index.php
+++ b/index.php
@@ -1,6 +1,6 @@
1<?php 1<?php
2/** 2/**
3 * Shaarli v0.8.0 - Shaare your links... 3 * Shaarli v0.8.1 - Shaare your links...
4 * 4 *
5 * The personal, minimalist, super-fast, database free, bookmarking service. 5 * The personal, minimalist, super-fast, database free, bookmarking service.
6 * 6 *
@@ -25,7 +25,7 @@ if (date_default_timezone_get() == '') {
25/* 25/*
26 * PHP configuration 26 * PHP configuration
27 */ 27 */
28define('shaarli_version', '0.8.0'); 28define('shaarli_version', '0.8.1');
29 29
30// http://server.com/x/shaarli --> /shaarli/ 30// http://server.com/x/shaarli --> /shaarli/
31define('WEB_PATH', substr($_SERVER['REQUEST_URI'], 0, 1+strrpos($_SERVER['REQUEST_URI'], '/', 0))); 31define('WEB_PATH', substr($_SERVER['REQUEST_URI'], 0, 1+strrpos($_SERVER['REQUEST_URI'], '/', 0)));
@@ -564,24 +564,19 @@ function showDailyRSS($conf) {
564 ); 564 );
565 565
566 /* Some Shaarlies may have very few links, so we need to look 566 /* Some Shaarlies may have very few links, so we need to look
567 back in time (rsort()) until we have enough days ($nb_of_days). 567 back in time until we have enough days ($nb_of_days).
568 */ 568 */
569 $linkdates = array();
570 foreach ($LINKSDB as $linkdate => $value) {
571 $linkdates[] = $linkdate;
572 }
573 rsort($linkdates);
574 $nb_of_days = 7; // We take 7 days. 569 $nb_of_days = 7; // We take 7 days.
575 $today = date('Ymd'); 570 $today = date('Ymd');
576 $days = array(); 571 $days = array();
577 572
578 foreach ($linkdates as $linkdate) { 573 foreach ($LINKSDB as $link) {
579 $day = substr($linkdate, 0, 8); // Extract day (without time) 574 $day = $link['created']->format('Ymd'); // Extract day (without time)
580 if (strcmp($day,$today) < 0) { 575 if (strcmp($day, $today) < 0) {
581 if (empty($days[$day])) { 576 if (empty($days[$day])) {
582 $days[$day] = array(); 577 $days[$day] = array();
583 } 578 }
584 $days[$day][] = $linkdate; 579 $days[$day][] = $link;
585 } 580 }
586 581
587 if (count($days) > $nb_of_days) { 582 if (count($days) > $nb_of_days) {
@@ -601,24 +596,18 @@ function showDailyRSS($conf) {
601 echo '<copyright>'. $pageaddr .'</copyright>'. PHP_EOL; 596 echo '<copyright>'. $pageaddr .'</copyright>'. PHP_EOL;
602 597
603 // For each day. 598 // For each day.
604 foreach ($days as $day => $linkdates) { 599 foreach ($days as $day => $links) {
605 $dayDate = DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, $day.'_000000'); 600 $dayDate = DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, $day.'_000000');
606 $absurl = escape(index_url($_SERVER).'?do=daily&day='.$day); // Absolute URL of the corresponding "Daily" page. 601 $absurl = escape(index_url($_SERVER).'?do=daily&day='.$day); // Absolute URL of the corresponding "Daily" page.
607 602
608 // Build the HTML body of this RSS entry.
609 $links = array();
610
611 // We pre-format some fields for proper output. 603 // We pre-format some fields for proper output.
612 foreach ($linkdates as $linkdate) { 604 foreach ($links as &$link) {
613 $l = $LINKSDB[$linkdate]; 605 $link['formatedDescription'] = format_description($link['description'], $conf->get('redirector.url'));
614 $l['formatedDescription'] = format_description($l['description'], $conf->get('redirector.url')); 606 $link['thumbnail'] = thumbnail($conf, $link['url']);
615 $l['thumbnail'] = thumbnail($conf, $l['url']); 607 $link['timestamp'] = $link['created']->getTimestamp();
616 $l_date = DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, $l['linkdate']); 608 if (startsWith($link['url'], '?')) {
617 $l['timestamp'] = $l_date->getTimestamp(); 609 $link['url'] = index_url($_SERVER) . $link['url']; // make permalink URL absolute
618 if (startsWith($l['url'], '?')) {
619 $l['url'] = index_url($_SERVER) . $l['url']; // make permalink URL absolute
620 } 610 }
621 $links[$linkdate] = $l;
622 } 611 }
623 612
624 // Then build the HTML for this day: 613 // Then build the HTML for this day:
@@ -680,8 +669,7 @@ function showDaily($pageBuilder, $LINKSDB, $conf, $pluginManager)
680 $linksToDisplay[$key]['taglist']=$taglist; 669 $linksToDisplay[$key]['taglist']=$taglist;
681 $linksToDisplay[$key]['formatedDescription'] = format_description($link['description'], $conf->get('redirector.url')); 670 $linksToDisplay[$key]['formatedDescription'] = format_description($link['description'], $conf->get('redirector.url'));
682 $linksToDisplay[$key]['thumbnail'] = thumbnail($conf, $link['url']); 671 $linksToDisplay[$key]['thumbnail'] = thumbnail($conf, $link['url']);
683 $date = DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, $link['linkdate']); 672 $linksToDisplay[$key]['timestamp'] = $link['created']->getTimestamp();
684 $linksToDisplay[$key]['timestamp'] = $date->getTimestamp();
685 } 673 }
686 674
687 /* We need to spread the articles on 3 columns. 675 /* We need to spread the articles on 3 columns.
@@ -831,7 +819,7 @@ function renderPage($conf, $pluginManager)
831 // Get only links which have a thumbnail. 819 // Get only links which have a thumbnail.
832 foreach($links as $link) 820 foreach($links as $link)
833 { 821 {
834 $permalink='?'.escape(smallHash($link['linkdate'])); 822 $permalink='?'.$link['shorturl'];
835 $thumb=lazyThumbnail($conf, $link['url'],$permalink); 823 $thumb=lazyThumbnail($conf, $link['url'],$permalink);
836 if ($thumb!='') // Only output links which have a thumbnail. 824 if ($thumb!='') // Only output links which have a thumbnail.
837 { 825 {
@@ -1078,6 +1066,7 @@ function renderPage($conf, $pluginManager)
1078 { 1066 {
1079 $data = array( 1067 $data = array(
1080 'pageabsaddr' => index_url($_SERVER), 1068 'pageabsaddr' => index_url($_SERVER),
1069 'sslenabled' => !empty($_SERVER['HTTPS'])
1081 ); 1070 );
1082 $pluginManager->executeHooks('render_tools', $data); 1071 $pluginManager->executeHooks('render_tools', $data);
1083 1072
@@ -1244,13 +1233,30 @@ function renderPage($conf, $pluginManager)
1244 // -------- User clicked the "Save" button when editing a link: Save link to database. 1233 // -------- User clicked the "Save" button when editing a link: Save link to database.
1245 if (isset($_POST['save_edit'])) 1234 if (isset($_POST['save_edit']))
1246 { 1235 {
1247 $linkdate = $_POST['lf_linkdate'];
1248 $updated = isset($LINKSDB[$linkdate]) ? strval(date('Ymd_His')) : false;
1249
1250 // Go away! 1236 // Go away!
1251 if (! tokenOk($_POST['token'])) { 1237 if (! tokenOk($_POST['token'])) {
1252 die('Wrong token.'); 1238 die('Wrong token.');
1253 } 1239 }
1240
1241 // lf_id should only be present if the link exists.
1242 $id = !empty($_POST['lf_id']) ? intval(escape($_POST['lf_id'])) : $LINKSDB->getNextId();
1243 // Linkdate is kept here to:
1244 // - use the same permalink for notes as they're displayed when creating them
1245 // - let users hack creation date of their posts
1246 // See: https://github.com/shaarli/Shaarli/wiki/Datastore-hacks#changing-the-timestamp-for-a-link
1247 $linkdate = escape($_POST['lf_linkdate']);
1248 if (isset($LINKSDB[$id])) {
1249 // Edit
1250 $created = DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, $linkdate);
1251 $updated = new DateTime();
1252 $shortUrl = $LINKSDB[$id]['shorturl'];
1253 } else {
1254 // New link
1255 $created = DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, $linkdate);
1256 $updated = null;
1257 $shortUrl = link_small_hash($created, $id);
1258 }
1259
1254 // Remove multiple spaces. 1260 // Remove multiple spaces.
1255 $tags = trim(preg_replace('/\s\s+/', ' ', $_POST['lf_tags'])); 1261 $tags = trim(preg_replace('/\s\s+/', ' ', $_POST['lf_tags']));
1256 // Remove first '-' char in tags. 1262 // Remove first '-' char in tags.
@@ -1267,14 +1273,17 @@ function renderPage($conf, $pluginManager)
1267 } 1273 }
1268 1274
1269 $link = array( 1275 $link = array(
1276 'id' => $id,
1270 'title' => trim($_POST['lf_title']), 1277 'title' => trim($_POST['lf_title']),
1271 'url' => $url, 1278 'url' => $url,
1272 'description' => $_POST['lf_description'], 1279 'description' => $_POST['lf_description'],
1273 'private' => (isset($_POST['lf_private']) ? 1 : 0), 1280 'private' => (isset($_POST['lf_private']) ? 1 : 0),
1274 'linkdate' => $linkdate, 1281 'created' => $created,
1275 'updated' => $updated, 1282 'updated' => $updated,
1276 'tags' => str_replace(',', ' ', $tags) 1283 'tags' => str_replace(',', ' ', $tags),
1284 'shorturl' => $shortUrl,
1277 ); 1285 );
1286
1278 // If title is empty, use the URL as title. 1287 // If title is empty, use the URL as title.
1279 if ($link['title'] == '') { 1288 if ($link['title'] == '') {
1280 $link['title'] = $link['url']; 1289 $link['title'] = $link['url'];
@@ -1282,7 +1291,7 @@ function renderPage($conf, $pluginManager)
1282 1291
1283 $pluginManager->executeHooks('save_link', $link); 1292 $pluginManager->executeHooks('save_link', $link);
1284 1293
1285 $LINKSDB[$linkdate] = $link; 1294 $LINKSDB[$id] = $link;
1286 $LINKSDB->save($conf->get('resource.page_cache')); 1295 $LINKSDB->save($conf->get('resource.page_cache'));
1287 pubsubhub($conf); 1296 pubsubhub($conf);
1288 1297
@@ -1295,7 +1304,7 @@ function renderPage($conf, $pluginManager)
1295 $returnurl = !empty($_POST['returnurl']) ? $_POST['returnurl'] : '?'; 1304 $returnurl = !empty($_POST['returnurl']) ? $_POST['returnurl'] : '?';
1296 $location = generateLocation($returnurl, $_SERVER['HTTP_HOST'], array('addlink', 'post', 'edit_link')); 1305 $location = generateLocation($returnurl, $_SERVER['HTTP_HOST'], array('addlink', 'post', 'edit_link'));
1297 // Scroll to the link which has been edited. 1306 // Scroll to the link which has been edited.
1298 $location .= '#' . smallHash($_POST['lf_linkdate']); 1307 $location .= '#' . $link['shorturl'];
1299 // After saving the link, redirect to the page the user was on. 1308 // After saving the link, redirect to the page the user was on.
1300 header('Location: '. $location); 1309 header('Location: '. $location);
1301 exit; 1310 exit;
@@ -1306,27 +1315,31 @@ function renderPage($conf, $pluginManager)
1306 { 1315 {
1307 // If we are called from the bookmarklet, we must close the popup: 1316 // If we are called from the bookmarklet, we must close the popup:
1308 if (isset($_GET['source']) && ($_GET['source']=='bookmarklet' || $_GET['source']=='firefoxsocialapi')) { echo '<script>self.close();</script>'; exit; } 1317 if (isset($_GET['source']) && ($_GET['source']=='bookmarklet' || $_GET['source']=='firefoxsocialapi')) { echo '<script>self.close();</script>'; exit; }
1318 $link = $LINKSDB[(int) escape($_POST['lf_id'])];
1309 $returnurl = ( isset($_POST['returnurl']) ? $_POST['returnurl'] : '?' ); 1319 $returnurl = ( isset($_POST['returnurl']) ? $_POST['returnurl'] : '?' );
1310 $returnurl .= '#'.smallHash($_POST['lf_linkdate']); // Scroll to the link which has been edited. 1320 // Scroll to the link which has been edited.
1321 $returnurl .= '#'. $link['shorturl'];
1311 $returnurl = generateLocation($returnurl, $_SERVER['HTTP_HOST'], array('addlink', 'post', 'edit_link')); 1322 $returnurl = generateLocation($returnurl, $_SERVER['HTTP_HOST'], array('addlink', 'post', 'edit_link'));
1312 header('Location: '.$returnurl); // After canceling, redirect to the page the user was on. 1323 header('Location: '.$returnurl); // After canceling, redirect to the page the user was on.
1313 exit; 1324 exit;
1314 } 1325 }
1315 1326
1316 // -------- User clicked the "Delete" button when editing a link: Delete link from database. 1327 // -------- User clicked the "Delete" button when editing a link: Delete link from database.
1317 if ($targetPage == Router::$PAGE_DELETELINK) 1328 if (isset($_POST['delete_link']))
1318 { 1329 {
1319 if (!tokenOk($_GET['token'])) die('Wrong token.'); 1330 if (!tokenOk($_POST['token'])) die('Wrong token.');
1331
1320 // We do not need to ask for confirmation: 1332 // We do not need to ask for confirmation:
1321 // - confirmation is handled by JavaScript 1333 // - confirmation is handled by JavaScript
1322 // - we are protected from XSRF by the token. 1334 // - we are protected from XSRF by the token.
1323 $linkdate = $_GET['delete_link'];
1324 $link = $LINKSDB[$linkdate];
1325
1326 $pluginManager->executeHooks('delete_link', $link);
1327 1335
1328 unset($LINKSDB[$linkdate]); 1336 // FIXME! We keep `lf_linkdate` for consistency before a proper API. To be removed.
1329 $LINKSDB->save($conf->get('resource.page_cache')); // save to disk 1337 $id = isset($_POST['lf_id']) ? intval(escape($_POST['lf_id'])) : intval(escape($_POST['lf_linkdate']));
1338
1339 $pluginManager->executeHooks('delete_link', $LINKSDB[$id]);
1340
1341 unset($LINKSDB[$id]);
1342 $LINKSDB->save('resource.page_cache'); // save to disk
1330 1343
1331 // If we are called from the bookmarklet, we must close the popup: 1344 // If we are called from the bookmarklet, we must close the popup:
1332 if (isset($_GET['source']) && ($_GET['source']=='bookmarklet' || $_GET['source']=='firefoxsocialapi')) { echo '<script>self.close();</script>'; exit; } 1345 if (isset($_GET['source']) && ($_GET['source']=='bookmarklet' || $_GET['source']=='firefoxsocialapi')) { echo '<script>self.close();</script>'; exit; }
@@ -1364,8 +1377,10 @@ function renderPage($conf, $pluginManager)
1364 // -------- User clicked the "EDIT" button on a link: Display link edit form. 1377 // -------- User clicked the "EDIT" button on a link: Display link edit form.
1365 if (isset($_GET['edit_link'])) 1378 if (isset($_GET['edit_link']))
1366 { 1379 {
1367 $link = $LINKSDB[$_GET['edit_link']]; // Read database 1380 $id = (int) escape($_GET['edit_link']);
1381 $link = $LINKSDB[$id]; // Read database
1368 if (!$link) { header('Location: ?'); exit; } // Link not found in database. 1382 if (!$link) { header('Location: ?'); exit; } // Link not found in database.
1383 $link['linkdate'] = $link['created']->format(LinkDB::LINK_DATE_FORMAT);
1369 $data = array( 1384 $data = array(
1370 'link' => $link, 1385 'link' => $link,
1371 'link_is_new' => false, 1386 'link_is_new' => false,
@@ -1389,10 +1404,10 @@ function renderPage($conf, $pluginManager)
1389 $link_is_new = false; 1404 $link_is_new = false;
1390 // Check if URL is not already in database (in this case, we will edit the existing link) 1405 // Check if URL is not already in database (in this case, we will edit the existing link)
1391 $link = $LINKSDB->getLinkFromUrl($url); 1406 $link = $LINKSDB->getLinkFromUrl($url);
1392 if (!$link) 1407 if (! $link)
1393 { 1408 {
1394 $link_is_new = true; 1409 $link_is_new = true;
1395 $linkdate = strval(date('Ymd_His')); 1410 $linkdate = strval(date(LinkDB::LINK_DATE_FORMAT));
1396 // Get title if it was provided in URL (by the bookmarklet). 1411 // Get title if it was provided in URL (by the bookmarklet).
1397 $title = empty($_GET['title']) ? '' : escape($_GET['title']); 1412 $title = empty($_GET['title']) ? '' : escape($_GET['title']);
1398 // Get description if it was provided in URL (by the bookmarklet). [Bronco added that] 1413 // Get description if it was provided in URL (by the bookmarklet). [Bronco added that]
@@ -1416,7 +1431,7 @@ function renderPage($conf, $pluginManager)
1416 } 1431 }
1417 1432
1418 if ($url == '') { 1433 if ($url == '') {
1419 $url = '?' . smallHash($linkdate); 1434 $url = '?' . smallHash($linkdate . $LINKSDB->getNextId());
1420 $title = 'Note: '; 1435 $title = 'Note: ';
1421 } 1436 }
1422 $url = escape($url); 1437 $url = escape($url);
@@ -1430,6 +1445,8 @@ function renderPage($conf, $pluginManager)
1430 'tags' => $tags, 1445 'tags' => $tags,
1431 'private' => $private 1446 'private' => $private
1432 ); 1447 );
1448 } else {
1449 $link['linkdate'] = $link['created']->format(LinkDB::LINK_DATE_FORMAT);
1433 } 1450 }
1434 1451
1435 $data = array( 1452 $data = array(
@@ -1635,18 +1652,15 @@ function buildLinkList($PAGE,$LINKSDB, $conf, $pluginManager)
1635 $link['description'] = format_description($link['description'], $conf->get('redirector.url')); 1652 $link['description'] = format_description($link['description'], $conf->get('redirector.url'));
1636 $classLi = ($i % 2) != 0 ? '' : 'publicLinkHightLight'; 1653 $classLi = ($i % 2) != 0 ? '' : 'publicLinkHightLight';
1637 $link['class'] = $link['private'] == 0 ? $classLi : 'private'; 1654 $link['class'] = $link['private'] == 0 ? $classLi : 'private';
1638 $date = DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, $link['linkdate']); 1655 $link['timestamp'] = $link['created']->getTimestamp();
1639 $link['timestamp'] = $date->getTimestamp();
1640 if (! empty($link['updated'])) { 1656 if (! empty($link['updated'])) {
1641 $date = DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, $link['updated']); 1657 $link['updated_timestamp'] = $link['updated']->getTimestamp();
1642 $link['updated_timestamp'] = $date->getTimestamp();
1643 } else { 1658 } else {
1644 $link['updated_timestamp'] = ''; 1659 $link['updated_timestamp'] = '';
1645 } 1660 }
1646 $taglist = explode(' ', $link['tags']); 1661 $taglist = explode(' ', $link['tags']);
1647 uasort($taglist, 'strcasecmp'); 1662 uasort($taglist, 'strcasecmp');
1648 $link['taglist'] = $taglist; 1663 $link['taglist'] = $taglist;
1649 $link['shorturl'] = smallHash($link['linkdate']);
1650 // Check for both signs of a note: starting with ? and 7 chars long. 1664 // Check for both signs of a note: starting with ? and 7 chars long.
1651 if ($link['url'][0] === '?' && 1665 if ($link['url'][0] === '?' &&
1652 strlen($link['url']) === 7) { 1666 strlen($link['url']) === 7) {