Compare commits

...

16 Commits
phar ... master

Author SHA1 Message Date
5c2d5b5ad2 Adding README.md. 2015-10-03 12:53:03 +02:00
4b5059bfc4 Batch tagging (first pass but working).
Search will now look in bookmarks addresses too.
Some bugfixes.
2015-09-20 05:49:33 +02:00
e567e30ce0 Separate Netscape bookmark parser and add a license header. 2015-09-18 20:19:37 +02:00
0600f02a13 Shoulder surfing protection with new default option. Enabled only
for logged users as we use logged user's tags to decide what
should be hidden. Tags linked to the tag defined in the
configuration, associated bookmarks, relevant links and
"last searches" block will be hidden. Hidden state is active
unless disabled by clicking on the top right button :
require user's password. This setting is remembered by
a session cookie.
2015-09-18 19:53:21 +02:00
2b4044a26a Block everything if global private mode enabled and user not logged on. 2015-09-15 02:35:06 +02:00
02185ad7e4 Merge branch 'yohan' into HEAD
Conflicts:
	www/bookmarks.php
	www/importNetscape.php

Successful merging.
2015-09-13 04:52:16 +02:00
7699c685e6 Better import for XML bookmark file.
Support for adding multiple bookmarks at once with my modified Firefox's Scuttle plugin.
2015-09-13 03:33:39 +02:00
Christian Weiske
200aa3c793 link another theme 2015-07-26 08:02:35 +02:00
Christian Weiske
11e56e5861 Integrate Firefox Social API for bookmarking 2015-01-21 22:05:12 +01:00
Christian Weiske
f6902bc09d link pear manual ldap options 2014-07-20 21:50:42 +02:00
Christian Weiske
6b3f1d4bb5 Add support for phancap website thumbnailer.
Drop support for artviper, since their service is gone.
2014-04-23 23:12:55 +02:00
Christian Weiske
af2a061ecd mention scuttle for android 2014-03-31 11:13:15 +02:00
Christian Weiske
e37b58a15a mention scuttle for android 2014-03-31 11:11:50 +02:00
Christian Weiske
f095a0bd71 add scuttleoid to docs/tools 2014-03-31 11:08:03 +02:00
David Glenck
0a5eed2dd3 add option to get last modified date instead of creation date 2014-03-26 22:15:09 +01:00
David Glenck
49f1259c42 add status attribute to post in all relevant api functions 2014-01-16 21:07:17 +01:00
43 changed files with 1285 additions and 263 deletions

12
README.md Normal file
View File

@ -0,0 +1,12 @@
Patched SemanticScuttle (social bookmarking tool).
================================================
### New :
* Better import for XML bookmark file.
* Support for adding multiple bookmarks at once with my modified Firefox's Scuttle plugin.
* Block everything if global private mode enabled and user not logged on.
* Shoulder surfing protection.
* Batch tagging.
* Search will now look in bookmarks addresses too.

View File

@ -253,10 +253,13 @@ $adminsAreAdvisedTagsFromOtherAdmins = false;
*
* @var array
*/
$reservedusers = array('all', 'watchlist');
$reservedusers = array('all', 'watchlist');
/**
* If global private mode is enabled (everything will be blocked for unlogged users).
* @var boolean
*/
$privatemode = false;
/***************************************************
* Anti SPAM measures
@ -542,35 +545,27 @@ $defaults['privacy'] = 0;
*/
/**
* Enable bookmark website thumbnails.
* Which thumbnail service type to use.
*
* According to artviper.net license, buy a license if you
* gain profit with your pages.
*
* @var boolean
* @link http://www.websitethumbnail.de/
*/
$enableWebsiteThumbnails = false;
/**
* User ID from websitethumbnail.de
*
* You need to register on
* http://www.artviper.net/registerapi.php
* in order to use thumbnails on your domain
*
* @var string
* @link http://www.artviper.net/registerapi.php
*/
$thumbnailsUserId = null;
/**
* API key.
* Sent to you by artviper.net after registration.
* Currently supported:
* - null (no screenshots)
* - 'phancap', see http://cweiske.de/phancap.htm
*
* @var string
*/
$thumbnailsKey = null;
$thumbnailsType = null;
/**
* Configuration for thumbnail service.
*
* Phancap requires an array with the following keys:
* - url: URL to phancap's get.php file
* - token: user name (if access protected)
* - secret: password for the user (if access protected)
*
* @var array
*/
$thumbnailsConfig = array();
@ -620,6 +615,13 @@ $menu2Tags = array(
'menu2', 'tags', 'configurable', 'in', 'data/config.php'
);
/**
* Tag protected from shoulder surfing.
* This tag, his children and the associated bookmarks won't appear anywhere unless enabled in the UI.
*
* @var string
*/
$shoulderSurfingProtectedTag = 's_hidden';
/****************************

View File

@ -115,3 +115,38 @@ echo jsEscTitle(htmlspecialchars($link));
}
//]]>
</script>
<script type="text/javascript">
function activateSocialApi(node) {
var baseurl = <?php echo json_encode(addProtocolToUrl(createURL())); ?>;
var socialApiData = {
// currently required
"name": <?php echo json_encode($GLOBALS['sitename']); ?>,
"iconURL": baseurl + "themes/default/images/logo.png",
"icon32URL": baseurl + "themes/default/images/logo.png",
"icon64URL": baseurl + "themes/default/images/logo.png",
"markURL": "<?php echo addProtocolToUrl(createURL('bookmarks', $GLOBALS['user'])); ?>?action=add&amp;popup=1&amp;width=800&amp;height=470&amp;address=%{url}&amp;title=%{title}&amp;description=%{description}%{text}",
"markedIcon": baseurl + "themes/default/images/logo.png",
"unmarkedIcon": baseurl + "themes/default/images/logo-empty.png",
// should be available for display purposes
"description": "Self-hosted bookmark manager",
"author": "Christian Weiske",
"homepageURL": "http://semanticscuttle.sf.net/",
// optional
"version": "0.0.3"
};
var event = new CustomEvent("ActivateSocialFeature");
node.setAttribute("data-service", JSON.stringify(socialApiData));
node.dispatchEvent(event);
}
</script>
<p>
<button onclick="activateSocialApi(this)" title="activate semanticscuttle in firefox">
Add SemanticScuttle to Firefox
</button>
</p>

View File

@ -5,14 +5,14 @@
*
* Expects a $row variable with bookmark data.
*/
if (!$GLOBALS['enableWebsiteThumbnails']) {
return;
$thumbnailer = SemanticScuttle_Service_Factory::get('Thumbnails')->getThumbnailer();
$imgUrl = $thumbnailer->getThumbnailUrl($address, 120, 90);
if ($imgUrl !== false) {
echo '<a href="' . htmlspecialchars($address) . '">'
. '<img class="thumbnail" width="120" height="90" src="'
. htmlspecialchars($imgUrl).
'" />'
. '</a>';
}
$thumbnailHash = md5(
$address . $GLOBALS['thumbnailsUserId'] . $GLOBALS['thumbnailsKey']
);
//echo '<a href="'. $address .'"'. $rel .' ><img class="thumbnail" src="http://www.artviper.net/screenshots/screener.php?url='.$address.'&w=120&sdx=1280&userID='.$GLOBALS['thumbnailsUserId'].'&hash='.$thumbnailHash.'" />';
echo '<img class="thumbnail" onclick="window.location.href=\''.htmlspecialchars($address).'\'" src="http://www.artviper.net/screenshots/screener.php?url='.htmlspecialchars($address).'&amp;w=120&amp;sdx=1280&amp;userID='.$GLOBALS['thumbnailsUserId'].'&amp;hash='.$thumbnailHash.'" />';
?>

View File

@ -162,6 +162,14 @@ default:
<a href="?sort=<?php echo $votingSort ?>"><?php echo T_("Voting").$votingArrow; ?></a>
<span>/</span>
<?php } ?>
<?php
if ($userservice->isLoggedOn() && $_SERVER['PHP_SELF'] !== "/index.php") {
echo '<form method="get" action="'. $_SERVER['REQUEST_URI'] .'">';
echo '<input type="hidden" name="batch" value="1"/>';
echo '<input type="submit" value="Batch tagging"/>';
echo "</form>";
}
?>
<?php
if ($currenttag!= '') {
@ -178,7 +186,6 @@ if ($currenttag!= '') {
}
}
?></p>
<?php
// PAGINATION

View File

@ -6,11 +6,6 @@ echo '<a href="'.createURL('about').'">'.T_('About').'</a>';
echo ' - ';
echo T_("Propulsed by ");
echo " <a href=\"https://sourceforge.net/projects/semanticscuttle/\">SemanticScuttle</a>";
if($GLOBALS['enableWebsiteThumbnails']) {
// Licence to the thumbnails provider (OBLIGATORY IF YOU USE ARTVIPER SERVICE)
echo ' (Thumbnails by <a href="http://www.artviper.net">webdesign</a>)';
}
?>
</div>

View File

@ -1,6 +1,5 @@
<?php
$this->includeTemplate($GLOBALS['top_include']);
$accessPublic = '';
$accessShared = '';
$accessPrivate = '';
@ -33,6 +32,14 @@ if (is_array($row['tags'])) {
$row['tags'] = implode(', ', $row['tags']);
}
if (! is_array($row['bAddress'])) {
$row['bAddress'] = array($row['bAddress']);
}
if (! is_array($row['bTitle'])) {
$row['bTitle'] = array($row['bTitle']);
}
$ajaxUrl = ROOT . 'ajax/'
. (
($GLOBALS['adminsAreAdvisedTagsFromOtherAdmins'] && $currentUser->isAdmin())
@ -40,18 +47,8 @@ $ajaxUrl = ROOT . 'ajax/'
: 'getcontacttags'
) . '.php';
?>
<form action="<?php echo $formaction; ?>" method="post">
<form onsubmit="var ind = 0; var cb = document.getElementById('checkbox'+ind); while (cb !== null) {var title = document.getElementById('titleField'+ind); var address = document.getElementById('address'+ind); if(cb.checked) {cb.parentNode.removeChild(cb);} else {cb.parentNode.removeChild(cb); title.parentNode.removeChild(title); address.parentNode.removeChild(address);} ind++; cb = document.getElementById('checkbox'+ind);}" action="<?php echo $formaction; ?>" method="post">
<table>
<tr>
<th align="left"><?php echo T_('Address'); ?></th>
<td><input type="text" id="address" name="address" size="75" maxlength="65535" value="<?php echo filter($row['bAddress'], 'xml'); ?>" onblur="useAddress(this)" /></td>
<td> <?php echo T_('Required'); ?></td>
</tr>
<tr>
<th align="left"><?php echo T_('Title'); ?></th>
<td><input type="text" id="titleField" name="title" size="75" maxlength="255" value="<?php echo filter($row['bTitle'], 'xml'); ?>" onkeypress="this.style.backgroundImage = 'none';" /></td>
<td> <?php echo T_('Required'); ?></td>
</tr>
<tr>
<th align="left">
<?php echo T_('Description'); ?>
@ -78,13 +75,44 @@ $ajaxUrl = ROOT . 'ajax/'
<td> <?php echo T_('Just visible by you and your contacts.'); ?>
</td>
</tr>
<?php if(! isset($batch)): ?>
<tr>
<th align="left"><?php echo T_('Tags'); ?></th>
<td class="scuttletheme">
<input type="text" id="tags" name="tags" size="75" value="<?php echo filter($row['tags'], 'xml'); ?>"/>
<input type="text" id="tags" class="tags" name="tags" size="75" value="<?php echo filter($row['tags'], 'xml'); ?>"/>
</td>
<td> <?php echo T_('Comma-separated'); ?></td>
</tr>
<?php else: ?>
<tr>
<th align="left"><?php echo 'Common tags'; ?></th>
<td class="scuttletheme">
<span><?php echo filter($commontags, 'xml'); ?></span>
</td>
<td> <?php echo 'Tags common to all those bookmarks'; ?></td>
</tr>
<tr>
<th align="left"><?php echo 'Associated tags'; ?></th>
<td class="scuttletheme">
<span><?php echo filter($alltags, 'xml'); ?></span>
</td>
<td> <?php echo 'All tags associated to those bookmarks'; ?></td>
</tr>
<tr>
<th align="left"><?php echo 'Add those tags'; ?></th>
<td class="scuttletheme">
<input type="text" id="tags" class="tags" name="tags" size="75" value="<?php echo filter($row['tags'], 'xml'); ?>"/>
</td>
<td> <?php echo T_('Comma-separated'); ?></td>
</tr>
<tr>
<th align="left"><?php echo 'Remove those tags'; ?></th>
<td class="scuttletheme">
<input type="text" id="removetags" class="tags" name="removetags" size="75" value="<?php echo filter($row['tags'], 'xml'); ?>"/>
</td>
<td> <?php echo T_('Comma-separated'); ?></td>
</tr>
<?php endif; ?>
<tr>
<th></th>
<td align="right"><small><?php echo htmlspecialchars(T_('Note: use ">" to include one tag in another. e.g.: europe>france>paris'))?></small></td>
@ -115,6 +143,9 @@ $ajaxUrl = ROOT . 'ajax/'
<input type="submit" name="delete" value="<?php echo T_('Delete Bookmark'); ?>" />
<?php
}
?>
<button type="button" id="button" title="Invert selection" onclick="var ind = 0; var cb = document.getElementById('checkbox'+ind); while (cb !== null) {var title = document.getElementById('titleField'+ind); var address = document.getElementById('address'+ind); if(cb.checked) {cb.checked=false;} else {cb.checked=true;} ind++; cb = document.getElementById('checkbox'+ind);}">Invert selection</button>
<?php
if (isset($showdelete) && $showdelete) {
echo ' (<a href="'.createURL('bookmarkcommondescriptionedit', $row['bHash']).'">';
echo T_('edit common description').'</a>)';
@ -126,14 +157,42 @@ $ajaxUrl = ROOT . 'ajax/'
<?php
} elseif (isset($referrer)) {
?>
<input type="hidden" name="referrer" value="<?php echo $referrer; ?>" />
<input type="hidden" name="referrer" value="<?php echo filter($referrer, 'xml'); ?>" />
<?php
}
?>
</td>
<td></td>
</tr>
</table>
<?php
$ind = 0;
foreach($row['bAddress'] as $index => $address) {
?>
<tr>
<td height="20px"></td>
<td><input type="checkbox" id="checkbox<?php echo $ind; ?>" checked="checked" /></td>
<td></td>
</tr>
<tr>
<th align="left"><?php echo T_('Address'); ?></th>
<td><input type="text" id="address<?php echo $ind; ?>" name="address[<?php echo $index; ?>]" size="75" maxlength="65535" value="<?php echo filter($address, 'xml'); ?>" onblur="useAddress(this)" /></td>
<td> <?php echo T_('Required'); ?></td>
</tr>
<tr>
<th align="left"><?php echo T_('Title'); ?></th>
<td><input type="text" id="titleField<?php echo $ind; ?>" name="title[<?php echo $index; ?>]" size="75" maxlength="255" value="<?php echo filter($row['bTitle'][$index], 'xml'); ?>" onkeypress="this.style.backgroundImage = 'none';" /></td>
<td> <?php echo T_('Required'); ?></td>
</tr>
<tr>
<td height="20px"></td>
<td></td>
<td></td>
</tr>
<?php
$ind++;
}
?>
</table>
</form>
<link href="<?php echo ROOT ?>js/jquery-ui-1.8.11/themes/base/jquery.ui.all.css" rel="stylesheet" type="text/css"/>
@ -156,7 +215,8 @@ jQuery(document).ready(function() {
}
//var availableTags = ["c++", "java", "php", "coldfusion", "javascript", "asp", "ruby"];
jQuery("input#tags").autocomplete({
//jQuery("input#tags").autocomplete({
jQuery("input.tags").autocomplete({
autoFocus: true,
minLength: 1,

View File

@ -11,14 +11,62 @@ if ($userservice->isLoggedOn() && is_object($currentUser)) {
<li><a href="<?php echo createURL('watchlist', $cUsername); ?>"><?php echo T_('Watchlist'); ?></a></li>
<li><a href="<?php echo $userservice->getProfileUrl($cUserId, $cUsername); ?>"><?php echo T_('Profile'); ?></a></li>
<li><a href="<?php echo createURL('bookmarks', $cUsername . '?action=add'); ?>"><?php echo T_('Add a Bookmark'); ?></a></li>
<?php if (isset($loadjs)) :?>
<li class="access"><button type="button" id="button" title="shoulder surfing protection" onclick="if(! $.cookie('noshoulderSurfingProtection')) {toggle();} else {$.removeCookie('noshoulderSurfingProtection', { path: '/' }); location.reload();}"><?php if(! isset($_COOKIE["noshoulderSurfingProtection"])) {echo "Protected";} else {echo "Unprotected";} ?></button></li>
<?php endif ?>
<li class="access"><?php echo $cUsername?><a href="<?php echo ROOT ?>?action=logout">(<?php echo T_('Log Out'); ?>)</a></li>
<li><a href="<?php echo createURL('about'); ?>"><?php echo T_('About'); ?></a></li>
<?php if($currentUser->isAdmin()): ?>
<li><a href="<?php echo createURL('admin', ''); ?>"><?php echo '['.T_('Admin').']'; ?></a></li>
<?php endif; ?>
</ul>
<?php if (isset($loadjs)) :?>
<div id="password-form" style="background:white; z-index: 2; position:absolute; top:55px; right:10px; visibility:hidden;">
<form id="noshoulderSurfingProtectionPassword">
<input type="password" name="password" id="password" size="40" placeholder="Type your password then press Enter to unprotect."/>
<!-- Allow form submission with keyboard without duplicating the dialog button -->
<input type="submit" tabindex="-1" style="position:absolute; top:-1000px"/>
</form>
</div>
<script>
// Prevents browser autocompletion. autocomplete="off" as input type="password" attribute only works with HTML5.
setTimeout(
clear(),
1000 //1,000 milliseconds = 1 second
);
function clear() {
$('#password').val('');
}
function toggle() {
if ($("#password-form").css("visibility") == "visible") {
$("#password-form").css("visibility", "hidden");
}
else {
clear();
$("#password-form").css("visibility", "visible");
}
}
$( "#noshoulderSurfingProtectionPassword" ).submit(function( event ) {
$.post(
'<?php echo ROOT ?>ajax/checkpassword.php',
{
password : $("#password").val(),
},
function(data) {
if(data == 'true') {
$.cookie('noshoulderSurfingProtection', 'null', { path: '/' });
location.reload();
}
},
'text'
);
event.preventDefault();
});
</script>
<?php endif ?>
<?php
} else {
?>

View File

@ -22,19 +22,35 @@ if (isset($rsschannels)) {
<?php if (DEBUG_MODE) : ?>
<script type="text/javascript" src="<?php echo ROOT_JS ?>jquery-1.4.2.js"></script>
<script type="text/javascript" src="<?php echo ROOT_JS ?>jquery.jstree.js"></script>
<script type="text/javascript" src="<?php echo ROOT_JS ?>jquery.cookie-1.4.1.js"></script>
<?php else: ?>
<script type="text/javascript" src="<?php echo ROOT_JS ?>jquery-1.4.2.min.js"></script>
<script type="text/javascript" src="<?php echo ROOT_JS ?>jquery.jstree.min.js"></script>
<script type="text/javascript" src="<?php echo ROOT_JS ?>jquery.cookie-1.4.1.js"></script>
<?php endif ?>
<script type="text/javascript" src="<?php echo ROOT ?>jsScuttle.php"></script>
<?php endif ?>
</head>
<body>
<?php
$bodystyle = '';
if (isset($_GET['popup'])) {
if (isset($_GET['height'])) {
$bodystyle .= 'height:' . intval($_GET['height']) . 'px;';
}
if (isset($_GET['width'])) {
$bodystyle .= 'width:' . intval($_GET['width']) . 'px;';
}
if ($bodystyle != '') {
$bodystyle = ' style="' . $bodystyle . '"';
}
}
?>
<body<?php echo $bodystyle; ?>>
<?php
$headerstyle = '';
if(isset($_GET['popup'])) {
if (isset($_GET['popup'])) {
$headerstyle = ' class="popup"';
}
?>

View File

@ -211,3 +211,6 @@ Here we authenticate against an active directory server.
);
$authEmailSuffix = '@example.org';
More LDAP options can be found in the `PEAR manual`__.
__ http://pear.php.net/manual/en/package.authentication.auth.storage.ldap.php

View File

@ -51,7 +51,8 @@ Existing themes
===============
* `Flat`__ by Roman Lehnhof. See the `introduction blog post`__
* `sscuttlizr`__
__ https://github.com/rlehnhof/flat
__ http://lehnhof.net/2013/08/semantic-scuttle-new-flat-interface-theme-template/
__ https://github.com/jonrandoem/sscuttlizr

View File

@ -2,7 +2,35 @@
Tools to use with SemanticScuttle
=================================
TTRSS2SCUTTLE
Scuttleoid
==========
Scuttloid is an android client for managing your bookmarks that are
stored on a Semantic Scuttle server.
It allows to list/search your personal bookmarks, add and edit existing
bookmarks, and share them to other applications.
Installable via `f-droid`__.
Also see the `source code`__.
__ https://f-droid.org/repository/browse/?fdid=gr.ndre.scuttloid
__ https://github.com/ilesinge/scuttloid
Scuttle for Android
===================
Scuttle for Android is a client for the Scuttle bookmarking software.
Enter your Scuttle login information and you will presented with a list of your
bookmarks.
Touching a bookmark will load that web page in the browser.
Use the browser's "Share" menu option to add bookmarks to your Scuttle.
See the homepage__ and `source code`__.
__ http://slideme.org/application/scuttle-android
__ https://github.com/shadybrooksoftware/Scuttle-For-Android
ttrss2scuttle
=============
Announced in a `blog post`__, the plugin for the feed reader `Tiny Tiny RSS`__
allows you to bookmark any of the articles in your own SemanticScuttle

View File

@ -51,7 +51,7 @@ class SemanticScuttle_Service
{
static $instance;
if (!isset($instance)) {
$instance = new self($db);
$instance = new static($db);
}
return $instance;
}

View File

@ -687,6 +687,7 @@ class SemanticScuttle_Service_Bookmark extends SemanticScuttle_DbService
* @param string $terms Search terms separated by spaces
* @param string $sortOrder One of the following values:
* "date_asc", "date_desc",
* "modified_asc", "modified_desc"
* "title_desc", "title_asc",
* "url_desc", "url_asc",
* "voting_asc", "voting_desc"
@ -732,11 +733,26 @@ class SemanticScuttle_Service_Bookmark extends SemanticScuttle_DbService
if (!is_array($tags) && !is_null($tags)) {
$tags = explode('+', trim($tags));
}
$tagcount = count($tags);
for ($i = 0; $i < $tagcount; $i ++) {
$tags[$i] = trim($tags[$i]);
if (!is_null($tags)) {
$tags = array_map('trim', $tags);
}
// Remove shoulder surfing protected tags.
if (! empty($GLOBALS['shoulderSurfingProtectedTag']) && $userservice->isLoggedOn() && ! isset($_COOKIE["noshoulderSurfingProtection"])) {
$shoulderSurfingProtectedTags = $tag2tagservice->getAllLinkedTags($GLOBALS['shoulderSurfingProtectedTag'], '>', $sId, array());
$shoulderSurfingProtectedTags[] = $GLOBALS['shoulderSurfingProtectedTag'];
$tags2 = [];
foreach ($tags as $tag) {
if (! in_array($tag, $shoulderSurfingProtectedTags, true)) {
$tags2[] = $tag;
}
}
// If we filtered everything, we stop here and return nothing.
if(! empty($tags) && empty($tags2)) {
return array();
}
$tags = $tags2;
}
$tagcount = count($tags);
// Set up the SQL query.
$query_1 = 'SELECT DISTINCT ';
@ -814,6 +830,12 @@ class SemanticScuttle_Service_Bookmark extends SemanticScuttle_DbService
case 'url_asc':
$query_5 .= ' ORDER BY B.bAddress ASC ';
break;
case 'modified_desc':
$query_5 .= ' ORDER BY B.bModified DESC ';
break;
case 'modified_asc':
$query_5 .= ' ORDER BY B.bModified ASC ';
break;
default:
$query_5 .= ' ORDER BY B.' . $GLOBALS['dateOrderField'] . ' DESC ';
}
@ -866,10 +888,13 @@ class SemanticScuttle_Service_Bookmark extends SemanticScuttle_DbService
// but private notes won't appear if not allowed.
$query_4 .= ' OR B.bPrivateNote LIKE "'
. $this->db->sql_escape($aTerms[$i])
.'%"';
. '%"';
$query_4 .= ' OR U.username = "'
. $this->db->sql_escape($aTerms[$i])
. '"'; //exact match for username
$query_4 .= ' OR B.bAddress LIKE "%'
. $this->db->sql_escape($aTerms[$i])
. '%"';
if ($dotags) {
$query_4 .= ' OR T.tag LIKE "'
. $this->db->sql_escape($aTerms[$i])
@ -892,6 +917,20 @@ class SemanticScuttle_Service_Bookmark extends SemanticScuttle_DbService
$query_4 .= ' AND B.bHash = "'. $hash .'"';
}
// Exclude bookmarks with shoulder surfing protected tags.
if (! empty($GLOBALS['shoulderSurfingProtectedTag']) && $userservice->isLoggedOn() && ! isset($_COOKIE["noshoulderSurfingProtection"])) {
$query_4 .= ' AND B.bId NOT IN (SELECT DISTINCT B0.bId FROM '.
$this->getTableName() .' AS B0, ' . $userservice->getTableName()
.' AS U, ' . $b2tservice->getTableName() .' AS T WHERE B0.uId = U.'
. $userservice->getFieldName('primary') . $privacy .' AND B0.uId = '
. $sId . ' AND (';
$count_s = count($shoulderSurfingProtectedTags);
for ($i = 0; $i < $count_s - 1; $i++) {
$query_4 .= 'T.tag = "'. $shoulderSurfingProtectedTags[$i] .'" OR ';
}
$query_4 .= 'T.tag = "'. $shoulderSurfingProtectedTags[$count_s - 1] .'")'
.' AND T.bId = B0.bId)';
}
$query = $query_1 . $query_2 . $query_3 . $query_4 . $query_5;
@ -904,10 +943,10 @@ class SemanticScuttle_Service_Bookmark extends SemanticScuttle_DbService
'', __LINE__, __FILE__, $query, $this->db
);
}
if (SQL_LAYER == 'mysql4') {
$totalquery = 'SELECT FOUND_ROWS() AS total';
} else {
// Disabled because breaks when in debug mode…
//if (SQL_LAYER == 'mysql4') {
// $totalquery = 'SELECT FOUND_ROWS() AS total';
//} else {
if ($hash) {
$totalquery = 'SELECT COUNT(*) AS total'. $query_2
. $query_3 . $query_4;
@ -915,7 +954,7 @@ class SemanticScuttle_Service_Bookmark extends SemanticScuttle_DbService
$totalquery = 'SELECT COUNT(DISTINCT bAddress) AS total'
. $query_2 . $query_3 . $query_4;
}
}
//}
if (!($totalresult = $this->db->sql_query($totalquery))
|| (!($row = $this->db->sql_fetchrow($totalresult)))

View File

@ -149,7 +149,7 @@ class SemanticScuttle_Service_Bookmark2Tag extends SemanticScuttle_DbService
foreach ($tags as $key => $tag) {
if (strpos($tag, '=')) {
// case "="
$pieces = explode('=', $tag);
$pieces = $tagservice->normalize(explode('=', $tag));
$nbPieces = count($pieces);
if ($nbPieces <= 1) {
continue;
@ -163,7 +163,7 @@ class SemanticScuttle_Service_Bookmark2Tag extends SemanticScuttle_DbService
$tags[$key] = $pieces[0];
} else {
// case ">"
$pieces = explode('>', $tag);
$pieces = $tagservice->normalize(explode('>', $tag));
$nbPieces = count($pieces);
if ($nbPieces <= 1) {
continue;
@ -329,7 +329,7 @@ class SemanticScuttle_Service_Bookmark2Tag extends SemanticScuttle_DbService
$query = 'SELECT tag, bId FROM ' . $this->getTableName()
. ' WHERE bId IN (' . implode(',', $bookmarkids) . ')'
. ' AND LEFT(tag, 7) <> "system:"'
. ' AND LEFT(tag, 7) <> "system:"'
. ' ORDER BY id, bId ASC';
if (!($dbresult = $this->db->sql_query($query))) {
@ -353,7 +353,7 @@ class SemanticScuttle_Service_Bookmark2Tag extends SemanticScuttle_DbService
function &getTags($userid = NULL) {
$userservice =SemanticScuttle_Service_Factory::get('User');
$userservice = SemanticScuttle_Service_Factory::get('User');
$logged_on_user = $userservice->getCurrentUserId();
$query = 'SELECT T.tag, COUNT(B.bId) AS bCount FROM '. $GLOBALS['tableprefix'] .'bookmarks AS B INNER JOIN '. $userservice->getTableName() .' AS U ON B.uId = U.'. $userservice->getFieldName('primary') .' INNER JOIN '. $GLOBALS['tableprefix'] .'bookmarks2tags AS T ON B.bId = T.bId';
@ -366,7 +366,6 @@ class SemanticScuttle_Service_Bookmark2Tag extends SemanticScuttle_DbService
} else {
$conditions['B.bStatus'] = 0;
}
$query .= ' WHERE '. $this->db->sql_build_array('SELECT', $conditions) .' AND LEFT(T.tag, 7) <> "system:" GROUP BY T.tag ORDER BY bCount DESC, tag';
if (!($dbresult = $this->db->sql_query($query))) {
@ -375,10 +374,33 @@ class SemanticScuttle_Service_Bookmark2Tag extends SemanticScuttle_DbService
}
$output = $this->db->sql_fetchrowset($dbresult);
$this->db->sql_freeresult($dbresult);
return $output;
}
$this->db->sql_freeresult($dbresult);
return $this->filterShoulderSurfingProtectedTags($output);
}
function &filterShoulderSurfingProtectedTags($dboutput) {
$userservice = SemanticScuttle_Service_Factory::get('User');
if (! empty($GLOBALS['shoulderSurfingProtectedTag']) && $userservice->isLoggedOn() && ! isset($_COOKIE["noshoulderSurfingProtection"])) {
$logged_on_user = $userservice->getCurrentUserId();
$ttt = SemanticScuttle_Service_Factory::get('Tag2Tag');
$shoulderSurfingProtectedTags = $ttt->getAllLinkedTags($GLOBALS['shoulderSurfingProtectedTag'], '>', $logged_on_user, array());
$shoulderSurfingProtectedTags[] = $GLOBALS['shoulderSurfingProtectedTag'];
$output = array();
foreach ($dboutput as $array) {
$flag = 1;
foreach ($shoulderSurfingProtectedTags as $tag) {
if ($array['tag'] === $tag) {
$flag = 0;
break;
}
}
if ($flag) {$output[] = $array;}
}
return $output;
}
else {return $dboutput;}
}
// Returns the tags related to the specified tags; i.e. attached to the same bookmarks
function &getRelatedTags($tags, $for_user = NULL, $logged_on_user = NULL, $limit = 10) {
@ -423,7 +445,7 @@ class SemanticScuttle_Service_Bookmark2Tag extends SemanticScuttle_DbService
}
$output = $this->db->sql_fetchrowset($dbresult);
$this->db->sql_freeresult($dbresult);
return $output;
return $this->filterShoulderSurfingProtectedTags($output);
}
// Returns the most popular tags used for a particular bookmark hash
@ -453,7 +475,7 @@ class SemanticScuttle_Service_Bookmark2Tag extends SemanticScuttle_DbService
}
$output = $this->db->sql_fetchrowset($dbresult);
$this->db->sql_freeresult($dbresult);
return $output;
return $this->filterShoulderSurfingProtectedTags($output);
}
@ -613,7 +635,7 @@ class SemanticScuttle_Service_Bookmark2Tag extends SemanticScuttle_DbService
$output = $this->db->sql_fetchrowset($dbresult);
$this->db->sql_freeresult($dbresult);
return $output;
return $this->filterShoulderSurfingProtectedTags($output);
}

View File

@ -151,6 +151,10 @@ class SemanticScuttle_Service_SearchHistory extends SemanticScuttle_DbService
$range = null, $uId = null, $nb = null,
$start = null, $distinct = false, $withResults = false
) {
$userservice = SemanticScuttle_Service_Factory::get('User');
if ($userservice->isLoggedOn() && ! isset($_COOKIE["noshoulderSurfingProtection"])) {
return array();
}
$sql = 'SELECT DISTINCT(shTerms),'
. ' shId, shRange, shNbResults, shDatetime, uId';
$sql.= ' FROM '. $this->getTableName();

View File

@ -318,7 +318,8 @@ class SemanticScuttle_Service_Tag2Tag extends SemanticScuttle_DbService
}
$output = $this->db->sql_fetchrowset($dbresult);
$this->db->sql_freeresult($dbresult);
return $output;
$btt = SemanticScuttle_Service_Factory::get('Bookmark2Tag');
return $btt->filterShoulderSurfingProtectedTags($output);
}
function getMenuTags($uId) {
@ -377,6 +378,25 @@ class SemanticScuttle_Service_Tag2Tag extends SemanticScuttle_DbService
$dbres = $this->db->sql_query($query);
$rowset = $this->db->sql_fetchrowset($dbres);
$this->db->sql_freeresult($dbres);
$userservice = SemanticScuttle_Service_Factory::get('User');
if (count($rowset)>0 && ! empty($GLOBALS['shoulderSurfingProtectedTag']) && $userservice->isLoggedOn() && ! isset($_COOKIE["noshoulderSurfingProtection"])) {
$logged_on_user = $userservice->getCurrentUserId();
$shoulderSurfingProtectedTags = $this->getAllLinkedTags($GLOBALS['shoulderSurfingProtectedTag'], '>', $logged_on_user, array());
$shoulderSurfingProtectedTags[] = $GLOBALS['shoulderSurfingProtectedTag'];
$output = array();
foreach($rowset as $link) {
$flag = 1;
foreach ($shoulderSurfingProtectedTags as $tag) {
if ($link['tag1'] === $tag || $link['tag2'] === $tag) {
$flag = 0;
break;
}
}
if ($flag) {$output[] = $link;}
}
$rowset = $output;
}
return $rowset;
}

View File

@ -0,0 +1,59 @@
<?php
/**
* SemanticScuttle - your social bookmark manager.
*
* PHP version 5.
*
* @category Bookmarking
* @package SemanticScuttle
* @author Christian Weiske <cweiske@cweiske.de>
* @license GPL http://www.gnu.org/licenses/gpl.html
* @link http://sourceforge.net/projects/semanticscuttle
*/
/**
* Instantiates the configured website thumbnailer object.
*
* @category Bookmarking
* @package SemanticScuttle
* @author Christian Weiske <cweiske@cweiske.de>
* @license GPL http://www.gnu.org/licenses/gpl.html
* @link http://sourceforge.net/projects/semanticscuttle
*/
class SemanticScuttle_Service_Thumbnails extends SemanticScuttle_Service
{
/**
* Instantiates the configured website thumbnailer object.
*
* @return object Website thumbnailer
*/
public function getThumbnailer()
{
if (!isset($GLOBALS['thumbnailsType'])
|| $GLOBALS['thumbnailsType'] == ''
) {
$class = 'SemanticScuttle_Thumbnailer_Null';
} else {
$class = 'SemanticScuttle_Thumbnailer_'
. ucfirst($GLOBALS['thumbnailsType']);
}
if (!class_exists($class)) {
//PEAR classname to filename rule
$file = str_replace('_', '/', $class) . '.php';
include_once $file;
}
$thumbnailer = new $class();
if (!isset($GLOBALS['thumbnailsConfig'])
|| $GLOBALS['thumbnailsConfig'] == ''
) {
$thumbnailer->setConfig(null);
} else {
$thumbnailer->setConfig($GLOBALS['thumbnailsConfig']);
}
return $thumbnailer;
}
}
?>

View File

@ -0,0 +1,52 @@
<?php
/**
* SemanticScuttle - your social bookmark manager.
*
* PHP version 5.
*
* @category Bookmarking
* @package SemanticScuttle
* @author Christian Weiske <cweiske@cweiske.de>
* @license GPL http://www.gnu.org/licenses/gpl.html
* @link http://sourceforge.net/projects/semanticscuttle
*/
/**
* Dummy thumbnailer that never returns a thumbnail URL
*
* @category Bookmarking
* @package SemanticScuttle
* @author Christian Weiske <cweiske@cweiske.de>
* @license GPL http://www.gnu.org/licenses/gpl.html
* @link http://sourceforge.net/projects/semanticscuttle
*/
class SemanticScuttle_Thumbnailer_Null
{
/**
* Set dummy configuration
*
* @param array $config Dummy configuration
*
* @return void
*/
public function setConfig($config)
{
}
/**
* Get the URL for a website thumbnail.
* Always returns false.
*
* @param string $bookmarkUrl URL of website to create thumbnail for
* @param integer $width Screenshot width
* @param integer $height Screenshot height
*
* @return mixed FALSE when no screenshot could be obtained,
* string with the URL otherwise
*/
public function getThumbnailUrl($bookmarkUrl, $width, $height)
{
return false;
}
}
?>

View File

@ -0,0 +1,92 @@
<?php
/**
* SemanticScuttle - your social bookmark manager.
*
* PHP version 5.
*
* @category Bookmarking
* @package SemanticScuttle
* @author Christian Weiske <cweiske@cweiske.de>
* @license GPL http://www.gnu.org/licenses/gpl.html
* @link http://sourceforge.net/projects/semanticscuttle
*/
/**
* Show website thumbnails/screenshots using phancap
*
* @category Bookmarking
* @package SemanticScuttle
* @author Christian Weiske <cweiske@cweiske.de>
* @license GPL http://www.gnu.org/licenses/gpl.html
* @link http://sourceforge.net/projects/semanticscuttle
* @see http://cweiske.de/phancap.htm
*/
class SemanticScuttle_Thumbnailer_Phancap
{
/**
* Configuration array.
* Required keys:
* - url
* - token
* - secret
*/
protected $config = array();
/**
* Set phancap configuration
*
* @param array $config Phancap configuration
*
* @return void
*/
public function setConfig($config)
{
$this->config = $config;
}
/**
* Get the URL for a website thumbnail
*
* @param string $bookmarkUrl URL of website to create thumbnail for
* @param integer $width Screenshot width
* @param integer $height Screenshot height
*
* @return mixed FALSE when no screenshot could be obtained,
* string with the URL otherwise
*/
public function getThumbnailUrl($bookmarkUrl, $width, $height)
{
//default parameters for the phancap service
$parameters = array(
'url' => $bookmarkUrl,
'swidth' => $width,
'sheight' => $height,
'sformat' => 'jpg',
);
if (isset($this->config['token']) && $this->config['token'] != '') {
$parameters['atoken'] = $this->config['token'];
$parameters['atimestamp'] = time();
//create signature
ksort($parameters);
foreach ($parameters as $key => $value) {
$encparams[] = $key . '=' . rawurlencode($value);
}
$encstring = implode('&', $encparams);
$signature = hash_hmac('sha1', $encstring, $this->config['secret']);
//append signature to parameters
$parameters['asignature'] = $signature;
}
//url-encode the parameters
$urlParams = array();
foreach ($parameters as $key => $value) {
$urlParams[] = $key . '=' . urlencode($value);
}
//final URL
return $this->config['url'] . '?' . implode('&', $urlParams);
}
}
?>

View File

@ -281,13 +281,14 @@ class sql_db
if ($query_id)
{
unset($this->rowset[$query_id]);
unset($this->row[$query_id]);
$id = (int) $query_id;
unset($this->rowset[$id]);
unset($this->row[$id]);
$result = array();
while ($this->rowset[$query_id] = $this->sql_fetchrow($query_id))
while ($this->rowset[$id] = $this->sql_fetchrow($query_id))
{
$result[] = $this->rowset[$query_id];
$result[] = $this->rowset[$id];
}
return $result;
}
@ -549,4 +550,4 @@ class sql_db
} // if ... define
?>
?>

View File

@ -87,7 +87,7 @@ require_once 'SemanticScuttle/constants.php';
// Debug Management using constants
if (DEBUG_MODE) {
ini_set('display_errors', '1');
ini_set('display_errors', '0');
ini_set('mysql.trace_mode', '1');
error_reporting(E_ALL);
} else {
@ -171,4 +171,29 @@ if (!defined('UNIT_TEST_MODE') || defined('HTTP_UNIT_TEST_MODE')) {
header('Content-Type: ' . $httpContentType . '; charset=utf-8');
}
}
// 7 // Block everything if global private mode enabled and user not logged on
// This is required to prevent breaking the API. Some API PHP source files include httpauth.inc.php
// which already check if the user is logged on and include www-header.php.
// We also allow password.php so users can reset their password and login.php so they can log in.
if (isset($GLOBALS['privatemode'])) {
if ($GLOBALS['privatemode'] && ! $userservice->isLoggedOn()) {
$flag = 1;
$included_files = get_included_files();
foreach ($included_files as $filename) {
if (strpos($filename,'httpauth.inc.php') !== false || strpos($filename,'password.php') !== false || strpos($filename,'login.php') !== false) {
$flag = 0;
break;
}
}
if ($flag) {
$tplVars['error'] = T_('You must log in.');
$tplVars['subtitle'] = T_('Log In');
$tplVars['formaction'] = createURL('login');
$tplVars['querystring'] = filter($_SERVER['QUERY_STRING']);
$templateservice->loadTemplate('login.tpl', $tplVars);
die();
}
}
}
?>

View File

@ -0,0 +1,149 @@
<?php
/***************************************************************************
The MIT License (MIT)
Copyright (c) 2015 kafene
https://github.com/kafene/netscape-bookmark-parser
http://kafene.org
Slightly modified by yohan.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
***************************************************************************/
/**
* Basically netscape bookmark files often come so badly formed, there's
* no reliable way I could find to parse them with DOM or SimpleXML,
* even after running HTML Tidy on them. So, this function does a bunch of
* transformations on the general format of a netscape bookmark file, to get
* Each bookmark and its description onto one line, and goes through line by
* line, matching tags and attributes. It's messy, but it works better than
* anything I could find in hours of googling, and anything that I could
* write after hours with DOM and SimpleXML. I didn't want to pull in a big
* DOM parsing library just to do this one thing, so this is it.
*/
/*
print '<PRE>';
var_dump(parse_netscape_bookmarks(file_get_contents('bookmarks_export.htm')));
*/
function parse_netscape_bookmarks($bkmk_str, $default_tag = null) {
$i = 0;
$next = false;
$items = [];
$current_tag = $default_tag = $default_tag ?: 'autoimported-'.date("Ymd");
$bkmk_str = str_replace(["\r","\n","\t"], ['','',' '], $bkmk_str);
$bkmk_str = preg_replace_callback('@<dd>(.*?)(<A|<\/|<DL|<DT|<P)@mis', function($m) {
return '<dd>'.str_replace(["\r", "\n"], ['', '<br>'], trim($m[1])).'</';
}, $bkmk_str);
$bkmk_str = preg_replace('/>(\s*?)</mis', ">\n<", $bkmk_str);
$bkmk_str = preg_replace('/(<!DOCTYPE|<META|<!--|<TITLE|<H1|<P)(.*?)\n/i', '', $bkmk_str);
$bkmk_str = trim($bkmk_str);
$bkmk_str = preg_replace('/\n<dd/i', '<dd', $bkmk_str);
//best way to do it :
$bkmk_str = preg_replace('/(?<=.)<\/DL>/', "\n</DL>", $bkmk_str);
$lines = explode("\n", $bkmk_str);
$str_bool = function($str, $default = false) {
if (!$str) {
return false;
} elseif (!is_string($str) && $str) {
return true;
}
$true = 'y|yes|on|checked|ok|1|true|array|\+|okay|yes+|t|one';
$false = 'n|no|off|empty|null|false|0|-|exit|die|neg|f|zero|void';
if (preg_match("/^($true)$/i", $str)) {
return true;
} elseif (preg_match("/^($false)$/i", $str)) {
return false;
}
return $default;
};
$tags = array($default_tag);
foreach ($lines as $line_no => $line) {
/* If we match a tag, set current tag to that, if <DL>, stop tag. */
if (preg_match('/^<h\d(.*?)>(.*?)<\/h\d>/i', $line, $m1)) {
$current_tag = trim(preg_replace("/\s+/", "_", strtr($m1[2], ', /+', '____')));
$tags[] = $current_tag;
continue;
} elseif (preg_match('/^<\/DL>/i', $line)) {
$current_tag = $default_tag;
array_pop($tags);
}
if (preg_match('/<a/i', $line, $m2)) {
$items[$i]['tags'] = $tags;
if (preg_match('/href="(.*?)"/i', $line, $m3)) {
$items[$i]['uri'] = $m3[1];
// $items[$i]['meta'] = meta($m3[1]);
} else {
$items[$i]['uri'] = '';
// $items[$i]['meta'] = '';
}
if (preg_match('/<a(.*?)>(.*?)<\/a>/i', $line, $m4)) {
$items[$i]['title'] = $m4[2];
// $items[$i]['slug'] = slugify($m4[2]);
} else {
$items[$i]['title'] = 'untitled';
// $items[$i]['slug'] = '';
}
if (preg_match('/note="(.*?)"<\/a>/i', $line, $m5)) {
$items[$i]['note'] = $m5[1];
} elseif (preg_match('/<dd>(.*?)<\//i', $line, $m6)) {
$items[$i]['note'] = str_replace('<br>', "\n", $m6[1]);
} else {
$items[$i]['note'] = '';
}
if (preg_match('/(tags?|labels?|folders?)="(.*?)"/i', $line, $m7)) {
array_unique(array_merge($items[$i]['tags'], explode(' ', trim(preg_replace("/\s+/", " ", strtr($m7[2], ',', ' '))))));
}
if (preg_match('/add_date="(.*?)"/i', $line, $m8)) {
$items[$i]['time'] = $m8[1];
} else {
$items[$i]['time'] = time();
}
if (preg_match('/(public|published|pub)="(.*?)"/i', $line, $m9)) {
$items[$i]['pub'] = $str_bool($m9[2], false) ? 1 : 0;
} elseif (preg_match('/(private|shared)="(.*?)"/i', $line, $m10)) {
$items[$i]['pub'] = $str_bool($m10[2], true) ? 0 : 1;
}
$i++;
}
}
ksort($items);
return $items;
}
?>

View File

@ -22,6 +22,7 @@ require_once 'www-header.php';
$tplVars['pagetitle'] = T_('About');
$tplVars['subtitle'] = T_('About');
$tplVars['loadjs'] = true;
$templateservice->loadTemplate('about.tpl', $tplVars);
?>
?>

View File

@ -0,0 +1,33 @@
<?php
require_once '../www-header.php';
if(isset($_POST['password']) && $userservice->isLoggedOn()){
$password = $userservice->sanitisePassword($_POST['password']);
$username = $currentUser->getUsername();
$db = SemanticScuttle_Service_Factory::getDb();
$query = 'SELECT '. $userservice->getFieldName('primary') .' FROM '. $userservice->getTableName() .' WHERE '. $userservice->getFieldName('username') .' = "'. $db->sql_escape($username) .'" AND '. $userservice->getFieldName('password') .' = "'. $db->sql_escape($password) .'"';
if (!($dbresult = $db->sql_query($query))) {
message_die(
GENERAL_ERROR,
'Could not get user',
'', __LINE__, __FILE__, $query, $db
);
echo 'false';
}
else {
$row = $db->sql_fetchrow($dbresult);
$db->sql_freeresult($dbresult);
if ($row) {
echo 'true';
}
else {
echo 'false';
}
}
}
else {
echo 'false';
}
?>

View File

@ -138,4 +138,4 @@ $tagData = assembleLinkedTagData(
SemanticScuttle_Service_Factory::get('Tag2Tag')
);
echo json_encode($tagData);
?>
?>

View File

@ -72,7 +72,6 @@ if (isset($userid)) {
} else {
$tplVars['cat_url'] = createURL('tags', '%2$s');
}
$tplVars['sidebar_blocks'] = array('linked');
$tplVars['userid'] = $userid;
$tplVars['loadjs'] = true;

View File

@ -4,6 +4,9 @@
// del.icio.us behavior:
// - doesn't include the filtered tag as an attribute on the root element (we do)
// Scuttle behavior:
// - returns privacy status of each bookmark.
// Force HTTP authentication first!
$httpContentType = 'text/xml';
require_once 'httpauth.inc.php';
@ -40,8 +43,8 @@ foreach($bookmarks['bookmarks'] as $row) {
$taglist = 'system:unfiled';
}
echo "\t<post href=\"". filter($row['bAddress'], 'xml') .'" description="'. filter($row['bTitle'], 'xml') .'" '. $description .'hash="'. md5($row['bAddress']) .'" tag="'. filter($taglist, 'xml') .'" time="'. gmdate('Y-m-d\TH:i:s\Z', strtotime($row['bDatetime'])) ."\" />\r\n";
echo "\t<post href=\"". filter($row['bAddress'], 'xml') .'" description="'. filter($row['bTitle'], 'xml') .'" '. $description .'hash="'. md5($row['bAddress']) .'" tag="'. filter($taglist, 'xml') .'" time="'. gmdate('Y-m-d\TH:i:s\Z', strtotime($row['bDatetime'])) . '" status="'. filter($row['bStatus'], 'xml') ."\" />\r\n";
}
echo '</posts>';
?>
?>

View File

@ -10,6 +10,7 @@
*
* Scuttle behavior:
* - Uses today, instead of the last bookmarked date, if no date is specified
* - returns privacy status of each bookmark.
*
* SemanticScuttle - your social bookmark manager.
*
@ -75,8 +76,8 @@ foreach ($bookmarks['bookmarks'] as $row) {
$taglist = 'system:unfiled';
}
echo "\t<post href=\"". filter($row['bAddress'], 'xml') .'" description="'. filter($row['bTitle'], 'xml') .'" '. $description .'hash="'. $row['bHash'] .'" others="'. $bookmarkservice->countOthers($row['bAddress']) .'" tag="'. filter($taglist, 'xml') .'" time="'. gmdate('Y-m-d\TH:i:s\Z', strtotime($row['bDatetime'])) ."\" />\r\n";
echo "\t<post href=\"". filter($row['bAddress'], 'xml') .'" description="'. filter($row['bTitle'], 'xml') .'" '. $description .'hash="'. $row['bHash'] .'" others="'. $bookmarkservice->countOthers($row['bAddress']) .'" tag="'. filter($taglist, 'xml') .'" time="'. gmdate('Y-m-d\TH:i:s\Z', strtotime($row['bDatetime'])) . '" status="'. filter($row['bStatus'], 'xml') ."\" />\r\n";
}
echo '</posts>';
?>
?>

View File

@ -4,6 +4,9 @@
// del.icio.us behavior:
// - doesn't include the filtered tag as an attribute on the root element (we do)
// Scuttle behavior:
// - returns privacy status of each bookmark.
// Force HTTP authentication first!
//require_once('httpauth.inc.php');
$httpContentType = 'text/xml';
@ -41,7 +44,7 @@ foreach($bookmarks['bookmarks'] as $row) {
$taglist = 'system:unfiled';
}
echo "\t<post href=\"". filter($row['bAddress'], 'xml') .'" description="'. filter($row['bTitle'], 'xml') .'" '. $description .'hash="'. md5($row['bAddress']) .'" tag="'. filter($taglist, 'xml') .'" time="'. gmdate('Y-m-d\TH:i:s\Z', strtotime($row['bDatetime'])) ."\" />\r\n";
echo "\t<post href=\"". filter($row['bAddress'], 'xml') .'" description="'. filter($row['bTitle'], 'xml') .'" '. $description .'hash="'. md5($row['bAddress']) .'" tag="'. filter($taglist, 'xml') .'" time="'. gmdate('Y-m-d\TH:i:s\Z', strtotime($row['bDatetime'])) . '" status="'. filter($row['bStatus'], 'xml') ."\" />\r\n";
}
echo '</posts>';

View File

@ -4,6 +4,9 @@
* optionally filtered by tag and/or number of posts
* (default 15, max 100, just like del.icio.us).
*
* Scuttle behavior:
* - returns privacy status of each bookmark.
*
* SemanticScuttle - your social bookmark manager.
*
* PHP version 5.
@ -75,8 +78,8 @@ foreach ($bookmarks['bookmarks'] as $row) {
$taglist = 'system:unfiled';
}
echo "\t<post href=\"". filter($row['bAddress'], 'xml') .'" description="'. filter($row['bTitle'], 'xml') .'" '. $description .'hash="'. $row['bHash'] .'" tag="'. filter($taglist, 'xml') .'" time="'. gmdate('Y-m-d\TH:i:s\Z', strtotime($row['bDatetime'])) ."\" />\r\n";
echo "\t<post href=\"". filter($row['bAddress'], 'xml') .'" description="'. filter($row['bTitle'], 'xml') .'" '. $description .'hash="'. $row['bHash'] .'" tag="'. filter($taglist, 'xml') .'" time="'. gmdate('Y-m-d\TH:i:s\Z', strtotime($row['bDatetime'])) . '" status="'. filter($row['bStatus'], 'xml') ."\" />\r\n";
}
echo '</posts>';
?>
?>

View File

@ -9,6 +9,11 @@
* that too, so we are as close at the API as possible,
* not breaking delicious clients.
*
* SemanticScuttle supports an extra parameter:
* - ?datemode=modified
* - sorts by modified date and returns modification time
* instead of creation time
*
* SemanticScuttle - your social bookmark manager.
*
* PHP version 5.
@ -27,18 +32,27 @@
$httpContentType = 'text/xml';
require_once 'httpauth.inc.php';
// parameter "datemode=modified" will get last modified date
// instead of last created date
$orderby = null;
$timeField = 'bDatetime';
if (isset($_GET['datemode']) && $_GET['datemode'] == 'modified') {
$orderby = 'modified_desc';
$timeField = 'bModified';
}
$bs = SemanticScuttle_Service_Factory::get('Bookmark');
$bookmarks = $bs->getBookmarks(0, 1, $userservice->getCurrentUserId());
$bookmarks = $bs->getBookmarks(0, 1, $userservice->getCurrentUserId(), null, null, $orderby);
// Set up the XML file and output all the tags.
echo '<?xml version="1.0" standalone="yes" ?' . ">\r\n";
//foreach is used in case there are no bookmarks
foreach ($bookmarks['bookmarks'] as $row) {
echo '<update time="'
. gmdate('Y-m-d\TH:i:s\Z', strtotime($row['bDatetime']))
. gmdate('Y-m-d\TH:i:s\Z', strtotime($row[$timeField]))
. '"'
. ' inboxnew="0"'
. ' />';
}
?>
?>

View File

@ -29,15 +29,21 @@ $cacheservice =SemanticScuttle_Service_Factory::get('Cache');
isset($_GET['action']) ? define('GET_ACTION', $_GET['action']): define('GET_ACTION', '');
isset($_POST['submitted']) ? define('POST_SUBMITTED', $_POST['submitted']): define('POST_SUBMITTED', '');
isset($_GET['title']) ? define('GET_TITLE', $_GET['title']): define('GET_TITLE', '');
isset($_GET['address']) ? define('GET_ADDRESS', $_GET['address']): define('GET_ADDRESS', '');
// define does not support arrays before PHP version 7
isset($_GET['title']) ? $TITLE = $_GET['title']: $TITLE = array();
//isset($_GET['title']) ? define('GET_TITLE', $_GET['title']): define('GET_TITLE', '');
isset($_GET['address']) ? $ADDRESS = $_GET['address']: $ADDRESS = array();
//isset($_GET['address']) ? define('GET_ADDRESS', $_GET['address']): define('GET_ADDRESS', '');
isset($_GET['description']) ? define('GET_DESCRIPTION', $_GET['description']): define('GET_DESCRIPTION', '');
isset($_GET['privateNote']) ? define('GET_PRIVATENOTE', $_GET['privateNote']): define('GET_PRIVATENOTE', '');
isset($_GET['tags']) ? define('GET_TAGS', $_GET['tags']): define('GET_TAGS', '');
isset($_GET['copyOf']) ? define('GET_COPYOF', $_GET['copyOf']): define('GET_COPYOF', '');
isset($_POST['title']) ? define('POST_TITLE', $_POST['title']): define('POST_TITLE', '');
isset($_POST['address']) ? define('POST_ADDRESS', $_POST['address']): define('POST_ADDRESS', '');
// define does not support arrays before PHP version 7
isset($_POST['title']) ? $TITLE = $_POST['title']: $TITLE = array();
//isset($_POST['title']) ? define('POST_TITLE', $_POST['title']): define('POST_TITLE', '');
isset($_POST['address']) ? $ADDRESS = $_POST['address']: $ADDRESS = array();
//isset($_POST['address']) ? define('POST_ADDRESS', $_POST['address']): define('POST_ADDRESS', '');
isset($_POST['description']) ? define('POST_DESCRIPTION', $_POST['description']): define('POST_DESCRIPTION', '');
isset($_POST['privateNote']) ? define('POST_PRIVATENOTE', $_POST['privateNote']): define('POST_PRIVATENOTE', '');
isset($_POST['status']) ? define('POST_STATUS', $_POST['status']): define('POST_STATUS', '');
@ -48,12 +54,22 @@ isset($_POST['popup']) ? define('POST_POPUP', $_POST['popup']): define('POST_POP
isset($_GET['page']) ? define('GET_PAGE', $_GET['page']): define('GET_PAGE', 0);
isset($_GET['sort']) ? define('GET_SORT', $_GET['sort']): define('GET_SORT', '');
isset($_GET['batch']) ? define('GET_BATCH', $_GET['batch']): define('GET_BATCH', 0);
if (!isset($_POST['tags'])) {
$_POST['tags'] = array();
}
if (!isset($_POST['removetags'])) {
$_POST['removetags'] = array();
}
//echo '<p>' . var_export($_POST, true) . '</p>';die();
if (! is_array($ADDRESS)) {
$ADDRESS = array($ADDRESS);
}
if (! is_array($TITLE)) {
$TITLE = array($TITLE);
}
if ((GET_ACTION == "add") && !$userservice->isLoggedOn()) {
$loginqry = str_replace("'", '%27', stripslashes($_SERVER['QUERY_STRING']));
@ -130,71 +146,119 @@ $tplVars['loadjs'] = true;
$saved = false;
$templatename = 'bookmarks.tpl';
if ($userservice->isLoggedOn() && POST_SUBMITTED != '') {
if (!POST_TITLE || !POST_ADDRESS) {
if (!$TITLE || !$ADDRESS) {
$tplVars['error'] = T_('Your bookmark must have a title and an address');
$templatename = 'editbookmark.tpl';
} else {
$address = trim(POST_ADDRESS);
if (!SemanticScuttle_Model_Bookmark::isValidUrl($address)) {
$tplVars['error'] = T_('This bookmark URL may not be added');
$templatename = 'editbookmark.tpl';
} else if ($bookmarkservice->bookmarkExists($address, $currentUserID)) {
// If the bookmark exists already, edit the original
$bookmark = $bookmarkservice->getBookmarkByAddress($address);
header('Location: '. createURL('edit', $bookmark['bId']));
exit();
// If it's new, save it
} else {
$title = trim(POST_TITLE);
$description = trim(POST_DESCRIPTION);
$privateNote = trim(POST_PRIVATENOTE);
$status = intval(POST_STATUS);
$categories = explode(',', $_POST['tags']);
$saved = true;
if ($bookmarkservice->addBookmark($address, $title, $description, $privateNote, $status, $categories)) {
if (POST_POPUP != '') {
$tplVars['msg'] = '<script type="text/javascript">window.close();</script>';
} else {
$tplVars['msg'] = T_('Bookmark saved') . ' <a href="javascript:history.go(-2)">'.T_('(Come back to previous page.)').'</a>';
// Redirection option
if ($GLOBALS['useredir']) {
$address = $GLOBALS['url_redir'] . $address;
}
}
} else {
$tplVars['error'] = T_('There was an error saving your bookmark. Please try again or contact the administrator.');
$templatename = 'editbookmark.tpl';
$saved = false;
}
}
}
else {
$address = array_map('trim', $ADDRESS);
$valid = 1;
foreach($address as $value) {
if (!SemanticScuttle_Model_Bookmark::isValidUrl($value)) {
$tplVars['error'] = T_('This bookmark URL may not be added' + $value);
$templatename = 'editbookmark.tpl';
$valid = 0;
break;
}
}
if ($valid) {
$title = array_map('trim', $TITLE);
$description = trim(POST_DESCRIPTION);
$privateNote = trim(POST_PRIVATENOTE);
$status = intval(POST_STATUS);
$categories = array_map('trim', explode(',', trim($_POST['tags'])));
$removecategories = array_map('trim', explode(',', trim($_POST['removetags'])));
$saved = true;
foreach($address as $index => $value) {
if ($bookmarkservice->bookmarkExists($value, $currentUserID)) {
// If the bookmark exists already, edit the original
$bookmark = $bookmarkservice->getBookmarkByAddress($value);
$bId = intval($bookmark['bId']);
$row = $bookmarkservice->getBookmark($bId, true);
$categories = array_unique(array_merge($row['tags'], $categories));
// remove tags
$categories = array_diff($categories, $removecategories);
if (!$bookmarkservice->updateBookmark($bId, $value, $title[$index], $description, $privateNote, $status, $categories)) {
$tplvars['error'] = T_('Error while saving this bookmark : ' + $value);
$templatename = 'editbookmark.tpl';
$saved = false;
break;
}
}
// If it's new, save it
elseif (!$bookmarkservice->addBookmark($value, $title[$index], $description, $privateNote, $status, $categories)) {
$tplVars['error'] = T_('There was an error saving this bookmark : ' + $value + ' Please try again or contact the administrator.');
$templatename = 'editbookmark.tpl';
$saved = false;
break;
}
}
if ($saved) {
if (POST_POPUP != '') {
$tplVars['msg'] = '<script type="text/javascript">window.close();</script>';
}
else {
$tplVars['msg'] = T_('Bookmark saved') . ' <a href="javascript:history.go(-2)">'.T_('(Come back to previous page.)').'</a>';
}
}
}
}
}
if (GET_ACTION == "add") {
if (GET_ACTION == "add" || GET_BATCH) {
// If the bookmark exists already, edit the original
if ($bookmarkservice->bookmarkExists(stripslashes(GET_ADDRESS), $currentUserID)) {
$bookmark = $bookmarkservice->getBookmarks(0, NULL, $currentUserID, NULL, NULL, NULL, NULL, NULL, NULL, $bookmarkservice->getHash(stripslashes(GET_ADDRESS)));
$popup = (GET_POPUP!='') ? '?popup=1' : '';
header('Location: '. createURL('edit', $bookmark['bookmarks'][0]['bId'] . $popup));
exit();
if (count($ADDRESS) === 1) {
if ($bookmarkservice->bookmarkExists(stripslashes($ADDRESS[0]), $currentUserID)) {
$bookmark =& $bookmarkservice->getBookmarks(0, NULL, $currentUserID, NULL, NULL, NULL, NULL, NULL, NULL, $bookmarkservice->getHash(stripslashes($ADDRESS[0])));
$popup = (GET_POPUP!='') ? '?popup=1' : '';
header('Location: '. createURL('edit', $bookmark['bookmarks'][0]['bId'] . $popup));
exit();
}
}
$templatename = 'editbookmark.tpl';
}
if ($templatename == 'editbookmark.tpl') {
if ($templatename == 'editbookmark.tpl') { // Prepare to display the edit bookmark page.
if ($userservice->isLoggedOn()) {
$tplVars['formaction'] = createURL('bookmarks', $currentUsername);
if (POST_SUBMITTED != '') {
$tplVars['row'] = array(
'bTitle' => stripslashes(POST_TITLE),
'bAddress' => stripslashes(POST_ADDRESS),
'bDescription' => stripslashes(POST_DESCRIPTION),
'bPrivateNote' => stripslashes(POST_PRIVATENOTE),
'tags' => ($_POST['tags'] ? $_POST['tags'] : array()),
'bTitle' => array_map('stripslashes', $TITLE),
'bAddress' => array_map('stripslashes', $ADDRESS),
'bDescription' => stripslashes(POST_DESCRIPTION),
'bPrivateNote' => stripslashes(POST_PRIVATENOTE),
'tags' => ($_POST['tags'] ? $_POST['tags'] : array()),
'bStatus' => $GLOBALS['defaults']['privacy'],
);
$tplVars['tags'] = $_POST['tags'];
} else {
}
elseif (GET_BATCH) {
$completebookmarks = $bookmarkservice->getBookmarks(0, null, $userid, $cat, null, getSortOrder());
$addresses2 = array();
$titles2 = array();
$tags2 = array();
foreach ($completebookmarks['bookmarks'] as $key => &$row) {
$addresses2[$row['bId']] = $row['bAddress'];
$titles2[$row['bId']] = $row['bTitle'];
$row = $bookmarkservice->getBookmark($row['bId'], true);
$tags2[] = $row['tags'];
}
$alltags2 = array_unique(call_user_func_array('array_merge', $tags2));
$commontags2 = call_user_func_array('array_intersect', $tags2);
$tplVars['row'] = array(
'bTitle' => $titles2,
'bAddress' => $addresses2,
'bDescription' => '',
'bPrivateNote' => '',
'tags' => array(),
'bStatus' => $GLOBALS['defaults']['privacy']
);
$tplVars['batch'] = '1';
$tplVars['alltags'] = implode(', ', $alltags2);
$tplVars['commontags'] = implode(', ', $commontags2);
}
else {
if(GET_COPYOF != '') { //copy from bookmarks page
$tplVars['row'] = $bookmarkservice->getBookmark(intval(GET_COPYOF), true);
if(!$currentUser->isAdmin()) {
@ -202,12 +266,12 @@ if ($templatename == 'editbookmark.tpl') {
}
}else { //copy from pop-up bookmarklet
$tplVars['row'] = array(
'bTitle' => stripslashes(GET_TITLE),
'bAddress' => stripslashes(GET_ADDRESS),
'bDescription' => stripslashes(GET_DESCRIPTION),
'bPrivateNote' => stripslashes(GET_PRIVATENOTE),
'tags' => (GET_TAGS ? explode(',', stripslashes(GET_TAGS)) : array()),
'bStatus' => $GLOBALS['defaults']['privacy']
'bTitle' => array_map('stripslashes', $TITLE),
'bAddress' => array_map('stripslashes', $ADDRESS),
'bDescription' => stripslashes(GET_DESCRIPTION),
'bPrivateNote' => stripslashes(GET_PRIVATENOTE),
'tags' => (GET_TAGS ? explode(',', stripslashes(GET_TAGS)) : array()),
'bStatus' => $GLOBALS['defaults']['privacy']
);
}
@ -229,20 +293,46 @@ if ($templatename == 'editbookmark.tpl') {
$tplVars['sidebar_blocks'] = array('watchstatus');
if (!$cat) { //user page without tags
$rssTitle = "My Bookmarks";
$rssTitle = "My Bookmarks";
$cat = NULL;
$tplVars['currenttag'] = NULL;
//$tplVars['sidebar_blocks'][] = 'menu2';
$tplVars['sidebar_blocks'][] = 'linked';
$tplVars['sidebar_blocks'][] = 'popular';
} else { //pages with tags
$rssTitle = "Tags" . $catTitle;
$rssTitle = "Tags" . $catTitle;
$rssCat = '/'. filter($cat, 'url');
$tplVars['currenttag'] = $cat;
$tplVars['sidebar_blocks'][] = 'tagactions';
//$tplVars['sidebar_blocks'][] = 'menu2';
$tplVars['sidebar_blocks'][] = 'linked';
$tplVars['sidebar_blocks'][] = 'related';
if (! empty($GLOBALS['shoulderSurfingProtectedTag']) && ! isset($_COOKIE["noshoulderSurfingProtection"])) {
$tag2tagservice = SemanticScuttle_Service_Factory::get('Tag2Tag');
$b2tservice = SemanticScuttle_Service_Factory::get('Bookmark2Tag');
$alltags = $b2tservice->getTags($currentUserID);
$shoulderSurfingProtectedTags = $tag2tagservice->getAllLinkedTags($GLOBALS['shoulderSurfingProtectedTag'], '>', $currentUserID, array());
$shoulderSurfingProtectedTags[] = $GLOBALS['shoulderSurfingProtectedTag'];
$flag = 0;
if (! in_array($cat, $shoulderSurfingProtectedTags, true)) {
foreach ($alltags as $tag) {
if ($tag['tag'] === $cat) {
$flag = 1;
break;
}
}
}
if ($flag) {
$tplVars['sidebar_blocks'][] = 'tagactions';
$tplVars['sidebar_blocks'][] = 'linked';
$tplVars['sidebar_blocks'][] = 'related';
}
}
else {
$tplVars['sidebar_blocks'][] = 'tagactions';
$tplVars['sidebar_blocks'][] = 'linked';
$tplVars['sidebar_blocks'][] = 'related';
}
/*$tplVars['sidebar_blocks'][] = 'menu';*/
}
$tplVars['sidebar_blocks'][] = 'menu2';
@ -273,24 +363,24 @@ if ($templatename == 'editbookmark.tpl') {
)
);
if ($userservice->isLoggedOn()) {
$currentUsername = $currentUser->getUsername();
if ($userservice->isPrivateKeyValid($currentUser->getPrivateKey())) {
array_push(
$tplVars['rsschannels'],
array(
sprintf(
T_('%s: %s (+private %s)'),
$sitename, $rssTitle, $currentUsername
),
createURL('rss', filter($currentUsername, 'url'))
. $rssCat
. '?sort=' . getSortOrder()
. '&privateKey=' . $currentUser->getPrivateKey()
)
);
if ($userservice->isLoggedOn()) {
$currentUsername = $currentUser->getUsername();
if ($userservice->isPrivateKeyValid($currentUser->getPrivateKey())) {
array_push(
$tplVars['rsschannels'],
array(
sprintf(
T_('%s: %s (+private %s)'),
$sitename, $rssTitle, $currentUsername
),
createURL('rss', filter($currentUsername, 'url'))
. $rssCat
. '?sort=' . getSortOrder()
. '&privateKey=' . $currentUser->getPrivateKey()
)
);
}
}
}
$tplVars['page'] = $page;
$tplVars['start'] = $start;

View File

@ -29,8 +29,12 @@ $bookmarkservice = SemanticScuttle_Service_Factory :: get('Bookmark');
isset($_POST['submitted']) ? define('POST_SUBMITTED', $_POST['submitted']): define('POST_SUBMITTED', '');
isset($_POST['delete']) ? define('POST_DELETE', $_POST['delete']): define('POST_DELETE', '');
isset($_POST['title']) ? define('POST_TITLE', $_POST['title']): define('POST_TITLE', '');
isset($_POST['address']) ? define('POST_ADDRESS', $_POST['address']): define('POST_ADDRESS', '');
// define does not support arrays before PHP version 7
isset($_POST['title']) ? $TITLE = $_POST['title']: $TITLE = array();
//isset($_POST['title']) ? define('POST_TITLE', $_POST['title']): define('POST_TITLE', '');
isset($_POST['address']) ? $ADDRESS = $_POST['address']: $ADDRESS = array();
//isset($_POST['address']) ? define('POST_ADDRESS', $_POST['address']): define('POST_ADDRESS', '');
isset($_POST['description']) ? define('POST_DESCRIPTION', $_POST['description']): define('POST_DESCRIPTION', '');
isset($_POST['privateNote']) ? define('POST_PRIVATENOTE', $_POST['privateNote']): define('POST_PRIVATENOTE', '');
isset($_POST['status']) ? define('POST_STATUS', $_POST['status']): define('POST_STATUS', $GLOBALS['defaults']['privacy']);
@ -40,6 +44,14 @@ isset($_GET['popup']) ? define('GET_POPUP', $_GET['popup']): define('GET_POPUP',
isset($_POST['popup']) ? define('POST_POPUP', $_POST['popup']): define('POST_POPUP', '');
isset($_POST['referrer']) ? define('POST_REFERRER', $_POST['referrer']): define('POST_REFERRER', '');
if (! is_array($ADDRESS)) {
$ADDRESS = array($ADDRESS);
}
if (! is_array($TITLE)) {
$TITLE = array($TITLE);
}
// Header variables
$tplVars['pagetitle'] = T_('Edit Bookmark');
$tplVars['subtitle'] = T_('Edit Bookmark');
@ -52,28 +64,24 @@ if (!($row = $bookmarkservice->getBookmark(intval($bookmark), true))) {
$templateservice->loadTemplate('error.404.tpl', $tplVars);
exit();
} else {
if (!$bookmarkservice->editAllowed($row)) {
$tplVars['error'] = T_('You are not allowed to edit this bookmark');
$templateservice->loadTemplate('error.500.tpl', $tplVars);
exit();
} else if (POST_SUBMITTED != '') {
if (!POST_TITLE || !POST_ADDRESS) {
if (!$TITLE || !$ADDRESS) {
$tplVars['error'] = T_('Your bookmark must have a title and an address');
} else {
// Update bookmark
$bId = intval($bookmark);
$address = trim(POST_ADDRESS);
$title = trim(POST_TITLE);
$address = array_map('trim', $ADDRESS);
$title = array_map('trim', $TITLE);
$description = trim(POST_DESCRIPTION);
$privateNote = trim(POST_PRIVATENOTE);
$status = intval(POST_STATUS);
$tags = trim(POST_TAGS);
if (!$bookmarkservice->updateBookmark($bId, $address, $title, $description, $privateNote, $status, $tags)) {
if (!$bookmarkservice->updateBookmark($bId, $address[0], $title[0], $description, $privateNote, $status, $tags)) {
$tplvars['error'] = T_('Error while saving your bookmark');
} else {
if (POST_POPUP != '') {

View File

@ -20,6 +20,13 @@
***************************************************************************/
require_once 'www-header.php';
if ('@data_dir@' == '@' . 'data_dir@') {
//non pear-install
require_once dirname(__FILE__) . '/../src/SemanticScuttle/parse_netscape_bookmarks.php';
} else {
//pear installation; files are in include path
require_once 'SemanticScuttle/parse_netscape_bookmarks.php';
}
/* Service creation: only useful services are created */
$bookmarkservice =SemanticScuttle_Service_Factory::get('Bookmark');
@ -44,78 +51,45 @@ if ($userservice->isLoggedOn() && sizeof($_FILES) > 0 && $_FILES['userfile']['si
// File handle
$html = file_get_contents($_FILES['userfile']['tmp_name']);
// Create array
$matches = parse_netscape_bookmarks($html);
//var_dump($matches);
// Create link array
//preg_match_all('/<a\s+(.*?)\s*\/*>([^<]*)/si', $html, $matches);
preg_match_all('/<a\s+(.*?)>([^<]*?)<\/a>.*?(<dd>([^<]*)|<dt>)/si', $html, $matches);
//var_dump($matches);die();
$links = $matches[1];
$titles = $matches[2];
$descriptions = $matches[4];
$size = count($links);
$size = count($matches);
for ($i = 0; $i < $size; $i++) {
// echo "<hr/>";
// echo $links[$i]."<br/>";
preg_match_all('/(\w*\s*=\s*"[^"]*")/', $links[$i], $attributes);
//$attributes = $attributes[0]; // we keep just one row
$bDatetime = ""; //bDateTime optional
$bCategories = ""; //bCategories optional
$bPrivateNote = ""; //bPrivateNote optional
$bPrivate = $status; //bPrivate set default
foreach ($attributes[0] as $attribute) {
$att = preg_split('/\s*=\s*/s', $attribute, 2);
$attrTitle = $att[0];
$attrVal = str_replace(
'&quot;', '"',
preg_replace('/([\'"]?)(.*)\1/', '$2', $att[1])
);
switch ($attrTitle) {
case "HREF":
$bAddress = $attrVal;
break;
case "ADD_DATE":
$bDatetime = gmdate('Y-m-d H:i:s', $attrVal);
break;
case "TAGS":
$bCategories = $attrVal;
break;
case "NOTE":
$bPrivateNote = $attrVal;
break;
case "PRIVATE":
if ($attrVal) {
$bPrivate = 2;//private
}
}
}
$bTitle = trim($titles[$i]);
$bDescription = trim($descriptions[$i]);
$bDatetime = gmdate('Y-m-d H:i:s', $matches[$i]['time']); //bDateTime optional
$bCategories = $matches[$i]['tags']; //bCategories optional
$bAddress = $matches[$i]['uri'];
$bDescription = $matches[$i]['note'];
$bTitle = $matches[$i]['title'];
$bPrivateNote = '';
if ($bookmarkservice->bookmarkExists($bAddress, $userservice->getCurrentUserId())) {
$tplVars['error'] = T_('You have already submitted some of these bookmarks.');
//$tplVars['error'] = T_('You have already submitted some of these bookmarks.');
// If the bookmark exists already, edit the original
$bookmark = $bookmarkservice->getBookmarkByAddress($bAddress);
$bId = intval($bookmark['bId']);
$row = $bookmarkservice->getBookmark($bId, true);
$categories = array_unique(array_merge($row['tags'], $bCategories));
//var_dump('update', $bId, $bAddress, $row['bTitle'], $row['bDescription'], $row['bPrivateNote'], $row['bStatus'], $categories);
if ($bookmarkservice->updateBookmark($bId, $bAddress, $row['bTitle'], $row['bDescription'], $row['bPrivateNote'], $row['bStatus'], $categories)) {
$countImportedBookmarks++;
}
else {
$tplvars['error'] = T_('Error while saving this bookmark : ' + $bAddress);
}
} else {
// If bookmark is local (like javascript: or place: in Firefox3), do nothing
if(substr($bAddress, 0, 7) == "http://" || substr($bAddress, 0, 8) == "https://") {
// If bookmark claims to be from the future, set it to be now instead
if (strtotime($bDatetime) > time()) {
$bDatetime = gmdate('Y-m-d H:i:s');
}
if ($bookmarkservice->addBookmark($bAddress, $bTitle, $bDescription, $bPrivateNote, $bPrivate, $bCategories, null, $bDatetime, false, true)) {
//var_dump('add ', $bAddress, $bTitle, $bDescription, $bPrivateNote, $status, $bCategories, $bDatetime);
if ($bookmarkservice->addBookmark($bAddress, $bTitle, $bDescription, $bPrivateNote, $status, $bCategories, null, $bDatetime, false, true)) {
$countImportedBookmarks++;
} else {
$tplVars['error'] = T_('There was an error saving your bookmark. Please try again or contact the administrator.');
$tplVars['error'] = T_('There was an error saving your bookmark : ' . $bAddress . ' Please try again or contact the administrator.');
}
}
}
@ -133,4 +107,5 @@ if ($userservice->isLoggedOn() && sizeof($_FILES) > 0 && $_FILES['userfile']['si
$tplVars['formaction'] = createURL('importNetscape');
$templateservice->loadTemplate($templatename, $tplVars);
}
?>

View File

@ -0,0 +1,117 @@
/*!
* jQuery Cookie Plugin v1.4.1
* https://github.com/carhartl/jquery-cookie
*
* Copyright 2013 Klaus Hartl
* Released under the MIT license
*/
(function (factory) {
if (typeof define === 'function' && define.amd) {
// AMD
define(['jquery'], factory);
} else if (typeof exports === 'object') {
// CommonJS
factory(require('jquery'));
} else {
// Browser globals
factory(jQuery);
}
}(function ($) {
var pluses = /\+/g;
function encode(s) {
return config.raw ? s : encodeURIComponent(s);
}
function decode(s) {
return config.raw ? s : decodeURIComponent(s);
}
function stringifyCookieValue(value) {
return encode(config.json ? JSON.stringify(value) : String(value));
}
function parseCookieValue(s) {
if (s.indexOf('"') === 0) {
// This is a quoted cookie as according to RFC2068, unescape...
s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\');
}
try {
// Replace server-side written pluses with spaces.
// If we can't decode the cookie, ignore it, it's unusable.
// If we can't parse the cookie, ignore it, it's unusable.
s = decodeURIComponent(s.replace(pluses, ' '));
return config.json ? JSON.parse(s) : s;
} catch(e) {}
}
function read(s, converter) {
var value = config.raw ? s : parseCookieValue(s);
return $.isFunction(converter) ? converter(value) : value;
}
var config = $.cookie = function (key, value, options) {
// Write
if (value !== undefined && !$.isFunction(value)) {
options = $.extend({}, config.defaults, options);
if (typeof options.expires === 'number') {
var days = options.expires, t = options.expires = new Date();
t.setTime(+t + days * 864e+5);
}
return (document.cookie = [
encode(key), '=', stringifyCookieValue(value),
options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
options.path ? '; path=' + options.path : '',
options.domain ? '; domain=' + options.domain : '',
options.secure ? '; secure' : ''
].join(''));
}
// Read
var result = key ? undefined : {};
// To prevent the for loop in the first place assign an empty array
// in case there are no cookies at all. Also prevents odd result when
// calling $.cookie().
var cookies = document.cookie ? document.cookie.split('; ') : [];
for (var i = 0, l = cookies.length; i < l; i++) {
var parts = cookies[i].split('=');
var name = decode(parts.shift());
var cookie = parts.join('=');
if (key && key === name) {
// If second argument (value) is a function it's a converter...
result = read(cookie, value);
break;
}
// Prevent storing a cookie that we couldn't decode.
if (!key && (cookie = read(cookie)) !== undefined) {
result[name] = cookie;
}
}
return result;
};
config.defaults = {};
$.removeCookie = function (key, options) {
if ($.cookie(key) === undefined) {
return false;
}
// Must not alter options, thus extending a fresh object...
$.cookie(key, '', $.extend({}, options, { expires: -1 }));
return !$.cookie(key);
};
}));

View File

@ -26,7 +26,7 @@ isset($_POST['terms']) ? define('POST_TERMS', $_POST['terms']): define('POST_TER
isset($_POST['range']) ? define('POST_RANGE', $_POST['range']): define('POST_RANGE', '');
isset($_GET['page']) ? define('GET_PAGE', $_GET['page']): define('GET_PAGE', 0);
isset($_GET['sort']) ? define('GET_SORT', $_GET['sort']): define('GET_SORT', '');
isset($_GET['batch']) ? define('GET_BATCH', $_GET['batch']): define('GET_BATCH', 0);
// POST
if (POST_TERMS != '') {
@ -115,6 +115,41 @@ if (is_null($terms)) {
}
}
if ($userservice->isLoggedOn() && GET_BATCH) {
$currentUsername = $currentUser->getUsername();
$completebookmarks = $bookmarkservice->getBookmarks(0, null, $s_user, null, $terms, getSortOrder(),
$s_watchlist, $s_start, $s_end);
$templatename = 'editbookmark.tpl';
$addresses2 = array();
$titles2 = array();
$tags2 = array();
foreach ($completebookmarks['bookmarks'] as $key => &$row) {
$addresses2[$row['bId']] = $row['bAddress'];
$titles2[$row['bId']] = $row['bTitle'];
$row = $bookmarkservice->getBookmark($row['bId'], true);
$tags2[] = $row['tags'];
}
$alltags2 = array_unique(call_user_func_array('array_merge', $tags2));
$commontags2 = call_user_func_array('array_intersect', $tags2);
$tplVars['row'] = array(
'bTitle' => $titles2,
'bAddress' => $addresses2,
'bDescription' => '',
'bPrivateNote' => '',
'tags' => array(),
'bStatus' => $GLOBALS['defaults']['privacy']
);
$tplVars['pagetitle'] = T_('Add a Bookmark');
$tplVars['subtitle'] = T_('Add a Bookmark');
$tplVars['btnsubmit'] = T_('Add Bookmark');
$tplVars['popup'] = null;
$tplVars['batch'] = '1';
$tplVars['alltags'] = implode(', ', $alltags2);
$tplVars['commontags'] = implode(', ', $commontags2);
$tplVars['formaction'] = createURL('bookmarks', $currentUsername);
$templateservice->loadTemplate($templatename, $tplVars);
}
else {
$bookmarks = $bookmarkservice->getBookmarks(
$start, $perpage, $s_user, NULL, $terms, getSortOrder(),
$s_watchlist, $s_start, $s_end
@ -152,4 +187,5 @@ $tplVars['cat_url'] = createURL('tags', '%2$s');
$tplVars['nav_url'] = createURL('search', $range .'/'. $terms .'/%3$s');
$templateservice->loadTemplate('bookmarks.tpl', $tplVars);
}
?>

View File

@ -63,7 +63,7 @@ if (POST_CONFIRM != '') {
}
$tplVars['links'] = $tag2tagservice->getLinks($currentUser->getId());
$tplVars['loadjs'] = true;
$tplVars['tag1'] = $tag1;
$tplVars['tag2'] = '';
$tplVars['subtitle'] = T_('Add Tag Link') .': '. $tag1;

View File

@ -75,7 +75,7 @@ if (POST_CONFIRM) {
}
$tplVars['links'] = $tag2tagservice->getLinks($currentUser->getId());
$tplVars['loadjs'] = true;
$tplVars['tag1'] = $tag1;
$tplVars['tag2'] = $tag2;
$tplVars['subtitle'] = T_('Delete Link Between Tags') .': '. $tag1.' > '.$tag2;

View File

@ -73,6 +73,7 @@ if (POST_CONFIRM) {
$tplVars['formaction'] = $_SERVER['SCRIPT_NAME'] .'/'. $tag;
$tplVars['referrer'] = $_SERVER['HTTP_REFERER'];
$tplVars['old'] = $tag;
$tplVars['loadjs'] = true;
}
$templateservice->loadTemplate($template, $tplVars);
?>

View File

@ -20,7 +20,6 @@
***************************************************************************/
require_once 'www-header.php';
/* Service creation: only useful services are created */
$bookmarkservice =SemanticScuttle_Service_Factory::get('Bookmark');
$cacheservice =SemanticScuttle_Service_Factory::get('Cache');
@ -28,6 +27,7 @@ $cacheservice =SemanticScuttle_Service_Factory::get('Cache');
/* Managing all possible inputs */
isset($_GET['page']) ? define('GET_PAGE', $_GET['page']): define('GET_PAGE', 0);
isset($_GET['sort']) ? define('GET_SORT', $_GET['sort']): define('GET_SORT', '');
isset($_GET['batch']) ? define('GET_BATCH', $_GET['batch']): define('GET_BATCH', 0);
/* Managing current logged user */
$currentUser = $userservice->getCurrentObjectUser();
@ -63,6 +63,43 @@ if ($usecache) {
$cacheservice->Start($hash, 1800);
}
// We need all bookmarks (without paging) for batch tagging.
if ($userservice->isLoggedOn() && GET_BATCH) {
$currentUsername = $currentUser->getUsername();
$completebookmarks = $bookmarkservice->getBookmarks(0, null, null, $cat, null, getSortOrder());
$templatename = 'editbookmark.tpl';
$addresses2 = array();
$titles2 = array();
$tags2 = array();
foreach ($completebookmarks['bookmarks'] as $key => &$row) {
$addresses2[$row['bId']] = $row['bAddress'];
$titles2[$row['bId']] = $row['bTitle'];
$row = $bookmarkservice->getBookmark($row['bId'], true);
$tags2[] = $row['tags'];
}
$alltags2 = array_unique(call_user_func_array('array_merge', $tags2));
$commontags2 = call_user_func_array('array_intersect', $tags2);
$tplVars['row'] = array(
'bTitle' => $titles2,
'bAddress' => $addresses2,
'bDescription' => '',
'bPrivateNote' => '',
'tags' => array(),
'bStatus' => $GLOBALS['defaults']['privacy']
);
$tplVars['pagetitle'] = T_('Add a Bookmark');
$tplVars['subtitle'] = T_('Add a Bookmark');
$tplVars['btnsubmit'] = T_('Add Bookmark');
$tplVars['popup'] = null;
$tplVars['batch'] = '1';
$tplVars['alltags'] = implode(', ', $alltags2);
$tplVars['commontags'] = implode(', ', $commontags2);
$tplVars['formaction'] = createURL('bookmarks', $currentUsername);
$tplVars['loadjs'] = true;
$templateservice->loadTemplate($templatename, $tplVars);
}
else {
// Header variables
$tplVars['pagetitle'] = T_('Tags') .': '. $cat;
$tplVars['loadjs'] = true;
@ -106,7 +143,38 @@ $tplVars['page'] = $page;
$tplVars['start'] = $start;
$tplVars['popCount'] = 25;
$tplVars['currenttag'] = $cat;
$tplVars['sidebar_blocks'] = array('linked', 'related', 'menu2');//array('linked', 'related', 'popular');
if ($userservice->isLoggedOn() && ! empty($GLOBALS['shoulderSurfingProtectedTag']) && ! isset($_COOKIE["noshoulderSurfingProtection"])) {
$tag2tagservice = SemanticScuttle_Service_Factory::get('Tag2Tag');
$b2tservice = SemanticScuttle_Service_Factory::get('Bookmark2Tag');
$currentUserID = $currentUser->getId();
$alltags = $b2tservice->getTags($currentUserID);
$shoulderSurfingProtectedTags = $tag2tagservice->getAllLinkedTags($GLOBALS['shoulderSurfingProtectedTag'], '>', $currentUserID, array());
$shoulderSurfingProtectedTags[] = $GLOBALS['shoulderSurfingProtectedTag'];
$flag = 0;
if (! in_array($cat, $shoulderSurfingProtectedTags, true)) {
foreach ($alltags as $tag) {
if ($tag['tag'] === $cat) {
$flag = 1;
break;
}
}
}
if ($flag) {
$tplVars['sidebar_blocks'][] = 'tagactions';
$tplVars['sidebar_blocks'][] = 'linked';
$tplVars['sidebar_blocks'][] = 'related';
$tplVars['sidebar_blocks'][] = 'menu2';
}
}
else {
$tplVars['sidebar_blocks'][] = 'tagactions';
$tplVars['sidebar_blocks'][] = 'linked';
$tplVars['sidebar_blocks'][] = 'related';
$tplVars['sidebar_blocks'][] = 'menu2';
}
$tplVars['subtitlehtml'] = $pagetitle;
$tplVars['bookmarkCount'] = $start + 1;
$bookmarks = $bookmarkservice->getBookmarks($start, $perpage, NULL, $cat, NULL, getSortOrder());
@ -116,7 +184,7 @@ $tplVars['cat_url'] = createURL('bookmarks', '%1$s/%2$s');
$tplVars['nav_url'] = createURL('tags', '%2$s%3$s');
$templateservice->loadTemplate('bookmarks.tpl', $tplVars);
}
if ($usecache) {
// Cache output if existing copy has expired
$cacheservice->End($hash);

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -110,7 +110,8 @@ html > body h1 {
padding-left: 75px;
}
html > body div#header.popup h1 {
background: url('images/logo_24.gif') no-repeat 10px;
background: url('images/logo.png') no-repeat 10px;
background-size: 24px;
padding: 0.5em 0.5em 0.5em 50px;
}
/*html > body div#header #welcome {
@ -195,7 +196,6 @@ img.thumbnail {
padding: 1px;
margin-right: 6px;
margin-bottom:4px;
cursor:pointer;
border:1px solid #AAA;
}
div.link a {