Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
efd842174f
52 changed files with 1901 additions and 325 deletions
168
build.xml
168
build.xml
|
@ -9,18 +9,31 @@
|
||||||
<property file="build.properties" />
|
<property file="build.properties" />
|
||||||
<property file="html.properties" />
|
<property file="html.properties" />
|
||||||
|
|
||||||
<property name="version-m" value="0.97" />
|
<property name="version-m" value="0.98" />
|
||||||
<property name="version" value="0.97.0" />
|
<property name="version" value="0.98.0" />
|
||||||
<property name="stability" value="beta" />
|
<property name="stability" value="beta" />
|
||||||
<property name="releasenotes" value="- Many SQL optimizations
|
<property name="releasenotes" value="- Switch to jQuery and drop dojo
|
||||||
- SemanticScuttle shows bookmarks 4 times faster now
|
- Implement request #2928950: Private keys for RSS feeds (Mark Pemberton)
|
||||||
- New config option to skip 'SET NAMES UTF8' call: $dbneedssetnames
|
- Implement request #3164348: Configurable default privacy (Brett Dee)
|
||||||
- Do not highlight admin bookmarks when $enableAdminColors is disabled
|
- Implement request #1989987: Theming support
|
||||||
- Add russian translation
|
- Implement request #3054906: Show user's full name instead of nickname
|
||||||
- Make HTML export follow the specifications a bit better
|
- Implement patch #3059829: update ``FR_CA`` translation
|
||||||
- Fix bug #2953732: faulty error message for duplicate bookmarks
|
- Fix bug #3187177: Wrong URL / Export XML Bookmarks
|
||||||
- Fix bug #2960663: do not send content-type headers twice for ajax/api scripts
|
- Fix bug #3097187: Using opensearch with two tags does not work in Firefox
|
||||||
- Fix bug #2976593: fr_FR locale is vietnamese
|
- Fix bug #3251877: French translation JavaScript Bug when editing bookmarks
|
||||||
|
- Fix bug #3168521: Title of tag-filtered RSS Feed is broken
|
||||||
|
- Fix bug #2853627: Javascript warning
|
||||||
|
- Fix bug in ``getTagsForBookmarks()`` that fetched all tags
|
||||||
|
- Fix privacy issue when fetching tags of several users
|
||||||
|
- Fix Google custom search XML
|
||||||
|
- Show error message on mysqli connection errors
|
||||||
|
- Update php-gettext library to 1.0.10
|
||||||
|
- ``api/posts/add`` respects the 'replace' parameter now
|
||||||
|
- Only URLs with an allowed protocol may be added to the database
|
||||||
|
- Support HTTPS connections when ``$root`` is not configured
|
||||||
|
- SQL schema version table to ease future database upgrades
|
||||||
|
- Documentation is written with rST (reStructuredText) now
|
||||||
|
- Support per-host configuration files
|
||||||
" />
|
" />
|
||||||
<property name="zipfile" value="${phing.project.name}-${version}.zip" />
|
<property name="zipfile" value="${phing.project.name}-${version}.zip" />
|
||||||
<property name="pkgfile" value="${phing.project.name}-${version}.tgz" />
|
<property name="pkgfile" value="${phing.project.name}-${version}.tgz" />
|
||||||
|
@ -30,7 +43,8 @@
|
||||||
<property name="sffilepath" value="s/se/semanticscuttle/" />
|
<property name="sffilepath" value="s/se/semanticscuttle/" />
|
||||||
<property name="svnpath" value="https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/" />
|
<property name="svnpath" value="https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/" />
|
||||||
|
|
||||||
<taskdef classname="phing.tasks.ext.d51PearPkg2Task" name="d51pearpkg2" />
|
<taskdef name="rST" classname="phing.tasks.ext.rSTTask" />
|
||||||
|
<taskdef name="d51pearpkg2" classname="phing.tasks.ext.d51PearPkg2Task" />
|
||||||
|
|
||||||
<target name="zip" depends="check"
|
<target name="zip" depends="check"
|
||||||
description="Create zip file for release"
|
description="Create zip file for release"
|
||||||
|
@ -52,11 +66,12 @@
|
||||||
<exclude name="**/.gitignore/"/>
|
<exclude name="**/.gitignore/"/>
|
||||||
<exclude name="**/.svn/"/>
|
<exclude name="**/.svn/"/>
|
||||||
<exclude name="data/config.php"/>
|
<exclude name="data/config.php"/>
|
||||||
|
<exclude name="data/config.testing.php"/>
|
||||||
|
<exclude name="data/config.testing-tmp.php"/>
|
||||||
<exclude name="data/locales/messages.po"/>
|
<exclude name="data/locales/messages.po"/>
|
||||||
<exclude name="data/locales/*/LC_MESSAGES/messages.po"/>
|
<exclude name="data/locales/*/LC_MESSAGES/messages.po"/>
|
||||||
<exclude name="doc/developers/"/>
|
|
||||||
<exclude name="src/php-gettext/examples/" />
|
<exclude name="src/php-gettext/examples/" />
|
||||||
<exclude name="src/php-gettext/bin/"/>
|
<exclude name="src/php-gettext/tests/"/>
|
||||||
</fileset>
|
</fileset>
|
||||||
</zip>
|
</zip>
|
||||||
</target>
|
</target>
|
||||||
|
@ -66,7 +81,6 @@
|
||||||
<target name="package" depends="check"
|
<target name="package" depends="check"
|
||||||
description="Creates the pear package"
|
description="Creates the pear package"
|
||||||
>
|
>
|
||||||
<!-- fixme: create package.xml with d51pearpkg2 -->
|
|
||||||
<d51pearpkg2 dir="." baseinstalldir="/">
|
<d51pearpkg2 dir="." baseinstalldir="/">
|
||||||
<name>SemanticScuttle</name>
|
<name>SemanticScuttle</name>
|
||||||
<summary>A social bookmarking tool</summary>
|
<summary>A social bookmarking tool</summary>
|
||||||
|
@ -108,30 +122,34 @@
|
||||||
<ignore>**/.svn</ignore>
|
<ignore>**/.svn</ignore>
|
||||||
<ignore>build*</ignore>
|
<ignore>build*</ignore>
|
||||||
<ignore>data/config.php</ignore>
|
<ignore>data/config.php</ignore>
|
||||||
|
<ignore>data/config.testing.php</ignore>
|
||||||
|
<ignore>data/config.testing-tmp.php</ignore>
|
||||||
<ignore>data/locales/messages.po</ignore>
|
<ignore>data/locales/messages.po</ignore>
|
||||||
<ignore>data/locales/*/LC_MESSAGES/messages.po</ignore>
|
<ignore>data/locales/*/LC_MESSAGES/messages.po</ignore>
|
||||||
<ignore>dist/**</ignore>
|
<ignore>dist/**</ignore>
|
||||||
<ignore>doc/developers/**</ignore>
|
|
||||||
<ignore>scripts/**</ignore>
|
<ignore>scripts/**</ignore>
|
||||||
<ignore>src/php-gettext/examples/**</ignore>
|
<ignore>src/php-gettext/examples/**</ignore>
|
||||||
<ignore>src/php-gettext/bin/**</ignore>
|
<ignore>src/php-gettext/tests/**</ignore>
|
||||||
<ignore>*.tgz</ignore>
|
|
||||||
<ignore>*.properties</ignore>
|
<ignore>*.properties</ignore>
|
||||||
|
<ignore>semanticscuttle-dump.sql</ignore>
|
||||||
|
<ignore>*.tgz</ignore>
|
||||||
|
|
||||||
<replacement
|
<replacement path="src/SemanticScuttle/header.php"
|
||||||
path="src/SemanticScuttle/header.php"
|
|
||||||
type="pear-config" from="@data_dir@" to="data_dir"
|
type="pear-config" from="@data_dir@" to="data_dir"
|
||||||
/>
|
/>
|
||||||
<replacement
|
<replacement path="src/SemanticScuttle/header.php"
|
||||||
path="src/SemanticScuttle/header.php"
|
|
||||||
type="pear-config" from="@www_dir@" to="www_dir"
|
type="pear-config" from="@www_dir@" to="www_dir"
|
||||||
/>
|
/>
|
||||||
<replacement
|
<replacement path="src/SemanticScuttle/Config.php"
|
||||||
path="www/www-header.php"
|
|
||||||
type="pear-config" from="@data_dir@" to="data_dir"
|
type="pear-config" from="@data_dir@" to="data_dir"
|
||||||
/>
|
/>
|
||||||
<replacement
|
<replacement path="src/SemanticScuttle/Config.php"
|
||||||
path="tests/prepare.php"
|
type="pear-config" from="@www_dir@" to="www_dir"
|
||||||
|
/>
|
||||||
|
<replacement path="www/www-header.php"
|
||||||
|
type="pear-config" from="@data_dir@" to="data_dir"
|
||||||
|
/>
|
||||||
|
<replacement path="tests/prepare.php"
|
||||||
type="pear-config" from="@data_dir@" to="data_dir"
|
type="pear-config" from="@data_dir@" to="data_dir"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
@ -207,49 +225,31 @@
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
|
|
||||||
<!-- you need to have the python docutils package installed, since
|
<target name="build-docs" description="render documentation">
|
||||||
we use the rst2html tool -->
|
<rST format="html" uptodate="true"
|
||||||
<target name="build-docs">
|
toolparam="--stylesheet=res/docs/style.css"
|
||||||
<foreach param="fname" absparam="abs-fname" target="build-doc-file">
|
>
|
||||||
<fileset dir=".">
|
<fileset dir="doc">
|
||||||
<include name="doc/ChangeLog"/>
|
<include name="ChangeLog"/>
|
||||||
<include name="doc/**.txt"/>
|
<include name="**.txt"/>
|
||||||
<include name="doc/**.rst"/>
|
<include name="**.rst"/>
|
||||||
<include name="doc/**/*.rst"/>
|
<include name="**/*.rst"/>
|
||||||
<exclude name="doc/LICENSE.txt"/>
|
<exclude name="LICENSE.txt"/>
|
||||||
<exclude name="doc/developers/TODO.rst"/>
|
<exclude name="developers/TODO.rst"/>
|
||||||
</fileset>
|
<exclude name="allinone.rst"/>
|
||||||
</foreach>
|
</fileset>
|
||||||
|
<mapper type="regexp" from="^doc/(.+?)(.rst|.txt)?$" to="dist/docs/\1.html"/>
|
||||||
|
<!--
|
||||||
|
<filterchain>
|
||||||
|
<replacetokenswithfile dir="res/docs">
|
||||||
|
<
|
||||||
|
</replacetokenswithfile>
|
||||||
|
</filterchain>
|
||||||
|
-->
|
||||||
|
</rST>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
|
|
||||||
<target name="build-doc-file" depends="check"
|
|
||||||
description="Builds a single documentation file. Pass file path as $fname"
|
|
||||||
>
|
|
||||||
<echo msg="${fname}"/>
|
|
||||||
<php function="preg_replace" returnProperty="outfile">
|
|
||||||
<param value="/^(.+)(.rst|.txt)$/"/>
|
|
||||||
<param value="dist/\1.html"/>
|
|
||||||
<param value="${fname}"/>
|
|
||||||
</php>
|
|
||||||
|
|
||||||
<!-- only render file if the doc file is newer than the html file -->
|
|
||||||
<property name="isuptodate" value="false"/>
|
|
||||||
<uptodate property="isuptodate" srcfile="${fname}" targetfile="${outfile}" />
|
|
||||||
<if>
|
|
||||||
<not><istrue value="${isuptodate}"/></not>
|
|
||||||
<then>
|
|
||||||
<exec
|
|
||||||
command="rst2html --exit-status=2 ${fname} ${outfile}"
|
|
||||||
checkreturn="1"
|
|
||||||
/>
|
|
||||||
</then>
|
|
||||||
</if>
|
|
||||||
|
|
||||||
</target>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<target name="release" depends="check,zip,package,deploy-sf"
|
<target name="release" depends="check,zip,package,deploy-sf"
|
||||||
description="Release the version on sourceforge"
|
description="Release the version on sourceforge"
|
||||||
>
|
>
|
||||||
|
@ -284,7 +284,7 @@
|
||||||
|
|
||||||
|
|
||||||
<target name="deploy-sf-pear" depends="check,package"
|
<target name="deploy-sf-pear" depends="check,package"
|
||||||
description="Update PEAR channel on sourceforge"
|
description="Update PEAR channel + website on sourceforge"
|
||||||
>
|
>
|
||||||
<available file="${websitedir}"
|
<available file="${websitedir}"
|
||||||
type="dir" property="available.websitedir"
|
type="dir" property="available.websitedir"
|
||||||
|
@ -349,6 +349,38 @@
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
|
|
||||||
|
<target name="deploy-docs" depends="build-docs"
|
||||||
|
description="sync docs to sourceforge website"
|
||||||
|
>
|
||||||
|
<copy todir="${websitedir}/docs">
|
||||||
|
<fileset dir="dist/docs">
|
||||||
|
<include name="**"/>
|
||||||
|
</fileset>
|
||||||
|
</copy>
|
||||||
|
|
||||||
|
<exec
|
||||||
|
command="rsync -avP -e ssh . ${sfuser},${sfproject}@web.sourceforge.net:htdocs/docs"
|
||||||
|
dir="${websitedir}/docs"
|
||||||
|
escape="false" checkreturn="false"
|
||||||
|
passthru="true"
|
||||||
|
/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
|
||||||
|
<target name="deploy-demo"
|
||||||
|
description="sync demo to sourceforge website"
|
||||||
|
>
|
||||||
|
<exec
|
||||||
|
command="rsync -avP -e ssh . ${sfuser},${sfproject}@web.sourceforge.net:htdocs/demo"
|
||||||
|
dir="${websitedir}/demo"
|
||||||
|
escape="false" checkreturn="false"
|
||||||
|
passthru="true"
|
||||||
|
/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<target name="check"
|
<target name="check"
|
||||||
description="Check variables"
|
description="Check variables"
|
||||||
>
|
>
|
||||||
|
@ -358,8 +390,6 @@
|
||||||
<fail unless="sffilepath" message="Sourceforge project file path not defined!" />
|
<fail unless="sffilepath" message="Sourceforge project file path not defined!" />
|
||||||
|
|
||||||
<mkdir dir="dist" />
|
<mkdir dir="dist" />
|
||||||
<mkdir dir="dist/doc" />
|
|
||||||
<mkdir dir="dist/doc/developers" />
|
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -13,3 +13,7 @@ CREATE TABLE `sc_users_sslclientcerts` (
|
||||||
PRIMARY KEY ( `id` ) ,
|
PRIMARY KEY ( `id` ) ,
|
||||||
UNIQUE (`id`)
|
UNIQUE (`id`)
|
||||||
) CHARACTER SET utf8 COLLATE utf8_general_ci;
|
) CHARACTER SET utf8 COLLATE utf8_general_ci;
|
||||||
|
|
||||||
|
ALTER TABLE `sc_users` ADD `privateKey` VARCHAR(33) NULL;
|
||||||
|
CREATE UNIQUE INDEX `privateKey` ON `sc_users` (`privateKey`);
|
||||||
|
|
||||||
|
|
|
@ -72,7 +72,9 @@ CREATE TABLE `sc_users` (
|
||||||
`email` varchar(50) NOT NULL default '',
|
`email` varchar(50) NOT NULL default '',
|
||||||
`homepage` varchar(255) default NULL,
|
`homepage` varchar(255) default NULL,
|
||||||
`uContent` text,
|
`uContent` text,
|
||||||
PRIMARY KEY (`uId`)
|
`privateKey` varchar(33) default NULL,
|
||||||
|
PRIMARY KEY (`uId`),
|
||||||
|
UNIQUE KEY `privateKey` (`privateKey`)
|
||||||
) CHARACTER SET utf8 COLLATE utf8_general_ci ;
|
) CHARACTER SET utf8 COLLATE utf8_general_ci ;
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
-- --------------------------------------------------------
|
||||||
|
@ -84,8 +86,7 @@ CREATE TABLE `sc_users_sslclientcerts` (
|
||||||
`sslClientIssuerDn` VARCHAR( 1024 ) NOT NULL ,
|
`sslClientIssuerDn` VARCHAR( 1024 ) NOT NULL ,
|
||||||
`sslName` VARCHAR( 64 ) NOT NULL ,
|
`sslName` VARCHAR( 64 ) NOT NULL ,
|
||||||
`sslEmail` VARCHAR( 64 ) NOT NULL ,
|
`sslEmail` VARCHAR( 64 ) NOT NULL ,
|
||||||
PRIMARY KEY ( `id` ) ,
|
PRIMARY KEY ( `id` )
|
||||||
UNIQUE (`id`)
|
|
||||||
) CHARACTER SET utf8 COLLATE utf8_general_ci;
|
) CHARACTER SET utf8 COLLATE utf8_general_ci;
|
||||||
|
|
||||||
--
|
--
|
||||||
|
|
|
@ -17,7 +17,7 @@ $this->includeTemplate($GLOBALS['top_include']);
|
||||||
|
|
||||||
|
|
||||||
<?php if(!is_null($currentUser) && $currentUser->isAdmin()): ?>
|
<?php if(!is_null($currentUser) && $currentUser->isAdmin()): ?>
|
||||||
<li>SemanticScuttle v0.97.0</li>
|
<li>SemanticScuttle v0.98.0</li>
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
|
|
@ -221,13 +221,13 @@ if ($currenttag!= '') {
|
||||||
$brss = '';
|
$brss = '';
|
||||||
$size = count($rsschannels);
|
$size = count($rsschannels);
|
||||||
for ($i = 0; $i < $size; $i++) {
|
for ($i = 0; $i < $size; $i++) {
|
||||||
$brss = '<a style="background:#FFFFFF"'
|
$brss = '<a style="background:#FFFFFF"'
|
||||||
. ' href="'. htmlspecialchars($rsschannels[$i][1]) . '"'
|
. ' href="'. htmlspecialchars($rsschannels[$i][1]) . '"'
|
||||||
. ' title="' . htmlspecialchars($rsschannels[$i][0]) . '">'
|
. ' title="' . htmlspecialchars($rsschannels[$i][0]) . '">'
|
||||||
. '<img src="' . $theme->resource('images/rss.gif') . '"'
|
. '<img src="' . $theme->resource('images/rss.gif') . '"'
|
||||||
. ' width="16" height="16"'
|
. ' width="16" height="16"'
|
||||||
. ' alt="' . htmlspecialchars($rsschannels[$i][0]) .'"/>'
|
. ' alt="' . htmlspecialchars($rsschannels[$i][0]) .'"/>'
|
||||||
. '</a>';
|
. '</a>';
|
||||||
}
|
}
|
||||||
|
|
||||||
$pagesBanner = '<p class="paging">'. $bfirst .'<span> / </span>'. $bprev .'<span> / </span>'. $bnext .'<span> / </span>'. $blast .'<span> / </span>'. sprintf(T_('Page %d of %d'), $page, $totalpages) ." ". $brss ." </p>\n";
|
$pagesBanner = '<p class="paging">'. $bfirst .'<span> / </span>'. $bprev .'<span> / </span>'. $bnext .'<span> / </span>'. $blast .'<span> / </span>'. sprintf(T_('Page %d of %d'), $page, $totalpages) ." ". $brss ." </p>\n";
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
<?php
|
|
||||||
/***************************************************************************
|
|
||||||
Copyright (C) 2005 - 2006 Scuttle project
|
|
||||||
http://sourceforge.net/projects/scuttle/
|
|
||||||
http://scuttle.org/
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
?>
|
|
||||||
|
|
||||||
<?php if (isset($loadjs)) :?>
|
|
||||||
<script type="text/javascript"
|
|
||||||
src="http://ajax.googleapis.com/ajax/libs/dojo/1.2/dojo/dojo.xd.js"
|
|
||||||
djConfig="parseOnLoad:true, isDebug:<?php echo DEBUG_MODE?'true':'false' ?>, usePlainJson:true, baseUrl: '<?php echo ROOT ?>', modulePaths: {'js': 'js'}"></script>
|
|
||||||
|
|
||||||
<script type="text/javascript">
|
|
||||||
dojo.require("dojo.parser");
|
|
||||||
dojo.require("dojo.data.ItemFileReadStore");
|
|
||||||
dojo.require("js.MultiComboBox"); // DOJO module adapted for SemanticScuttle
|
|
||||||
dojo.require("dijit.Tree");
|
|
||||||
</script>
|
|
||||||
<?php endif ?>
|
|
|
@ -28,6 +28,14 @@ $this->includeTemplate($GLOBALS['top_include']);
|
||||||
<td><input type="text" name="pMail" size="75" value="<?php echo filter($objectUser->getEmail(), 'xml'); ?>" /></td>
|
<td><input type="text" name="pMail" size="75" value="<?php echo filter($objectUser->getEmail(), 'xml'); ?>" /></td>
|
||||||
<td>← <?php echo T_('Required'); ?></td>
|
<td>← <?php echo T_('Required'); ?></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th align="left"><?php echo T_('Private RSS Feed'); ?></th>
|
||||||
|
<td><input type="checkbox" id="pEnablePrivateKey" name="pEnablePrivateKey" value="true" <?php echo $privateKeyIsEnabled;?> />
|
||||||
|
<label for="pEnablePrivateKey"><?php echo T_('Enable'); ?></label>
|
||||||
|
<input type="text" id="pPrivateKey" name="pPrivateKey" size="40" value="<?php echo $privateKey;?>" readonly="readonly" />
|
||||||
|
<a onclick="getNewPrivateKey(this); return false;"><button type="submit" name="submittedPK" value="1"><?php echo T_('Generate New Key'); ?></button></a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<h3><?php echo T_('Personal Details'); ?></h3>
|
<h3><?php echo T_('Personal Details'); ?></h3>
|
||||||
|
|
|
@ -3,7 +3,7 @@ echo '<' . '?xml version="1.0" encoding="utf-8" ?' . ">\n";
|
||||||
?>
|
?>
|
||||||
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
|
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||||
<channel>
|
<channel>
|
||||||
<title><?php echo htmlspecialchars($feedtitle); ?></title>
|
<title><?php echo $feedtitle; ?></title>
|
||||||
<link><?php echo htmlspecialchars($feedlink); ?></link>
|
<link><?php echo htmlspecialchars($feedlink); ?></link>
|
||||||
<description><?php echo htmlspecialchars($feeddescription); ?></description>
|
<description><?php echo htmlspecialchars($feeddescription); ?></description>
|
||||||
<pubDate><?php echo date('r'); ?></pubDate>
|
<pubDate><?php echo date('r'); ?></pubDate>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?php echo '<'; ?>?xml version="1.0" encoding="utf-8"?>
|
||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
|
||||||
<head>
|
<head>
|
||||||
|
@ -13,7 +13,7 @@ if (isset($rsschannels)) {
|
||||||
for ($i = 0; $i < $size; $i++) {
|
for ($i = 0; $i < $size; $i++) {
|
||||||
echo ' <link rel="alternate" type="application/rss+xml" title="'
|
echo ' <link rel="alternate" type="application/rss+xml" title="'
|
||||||
. htmlspecialchars($rsschannels[$i][0]) . '"'
|
. htmlspecialchars($rsschannels[$i][0]) . '"'
|
||||||
. ' href="'. $rsschannels[$i][1] .'" />';
|
. ' href="'. htmlspecialchars($rsschannels[$i][1]) .'" />' . "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
|
|
@ -12,7 +12,7 @@ if (isset($rsschannels)) {
|
||||||
$size = count($rsschannels);
|
$size = count($rsschannels);
|
||||||
for ($i = 0; $i < $size; $i++) {
|
for ($i = 0; $i < $size; $i++) {
|
||||||
echo ' <link rel="alternate" type="application/rss+xml" title="'
|
echo ' <link rel="alternate" type="application/rss+xml" title="'
|
||||||
. htmlspecialchars($rsschannels[$i][0]) . '"'
|
. $rsschannels[$i][0] . '"'
|
||||||
. ' href="'. $rsschannels[$i][1] .'" />';
|
. ' href="'. $rsschannels[$i][1] .'" />';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,28 +1,39 @@
|
||||||
ChangeLog for SemantiScuttle
|
ChangeLog for SemantiScuttle
|
||||||
============================
|
============================
|
||||||
|
|
||||||
|
.. contents::
|
||||||
|
|
||||||
0.98.0 - 2011-XX-XX
|
0.98.1 - 2011-XX-XX
|
||||||
|
-------------------
|
||||||
|
- Fix bug #3375635: XML parsing problem in top.inc.php
|
||||||
|
- Fix bug #3375428: Forgot to remove some old dojo files
|
||||||
|
- Fix bug #3160512: Make SemanticScuttle work with FastCGI
|
||||||
|
|
||||||
|
|
||||||
|
0.98.0 - 2011-07-21
|
||||||
-------------------
|
-------------------
|
||||||
- Switch to jQuery and drop dojo
|
- Switch to jQuery and drop dojo
|
||||||
|
- Implement request #2928950: Private keys for RSS feeds (Mark Pemberton)
|
||||||
|
- Implement request #3164348: Configurable default privacy (Brett Dee)
|
||||||
|
- Implement request #1989987: Theming support
|
||||||
|
- Implement request #3054906: Show user's full name instead of nickname
|
||||||
|
- Implement patch #3059829: update ``FR_CA`` translation
|
||||||
- Fix bug #3187177: Wrong URL / Export XML Bookmarks
|
- Fix bug #3187177: Wrong URL / Export XML Bookmarks
|
||||||
- Fix bug in ``getTagsForBookmarks()`` that fetched all tags
|
|
||||||
- Fix bug #3097187: Using opensearch with two tags does not work in Firefox
|
- Fix bug #3097187: Using opensearch with two tags does not work in Firefox
|
||||||
- Fix bug #3251877: French translation JavaScript Bug when editing bookmarks
|
- Fix bug #3251877: French translation JavaScript Bug when editing bookmarks
|
||||||
- Fix bug #3168521: Title of tag-filtered RSS Feed is broken
|
- Fix bug #3168521: Title of tag-filtered RSS Feed is broken
|
||||||
- Fix bug #2853627: Javascript warning
|
- Fix bug #2853627: Javascript warning
|
||||||
- Implement request #1989987: Theming support
|
- Fix bug in ``getTagsForBookmarks()`` that fetched all tags
|
||||||
- Implement request #3054906: Show user's full name instead of nickname
|
- Fix privacy issue when fetching tags of several users
|
||||||
- Implement patch #3059829: update ``FR_CA`` translation
|
- Fix Google custom search XML
|
||||||
- Show error message on mysqli connection errors
|
- Show error message on mysqli connection errors
|
||||||
- Update php-gettext library to 1.0.10
|
- Update php-gettext library to 1.0.10
|
||||||
- ``api/posts/add`` respects the "replace" parameter now
|
- ``api/posts/add`` respects the "replace" parameter now
|
||||||
- Fix privacy issue when fetching tags of several users
|
|
||||||
- Fix Google custom search XML
|
|
||||||
- Only URLs with an allowed protocol may be added to the database
|
- Only URLs with an allowed protocol may be added to the database
|
||||||
- Support HTTPS connections when ``$root`` is not configured
|
- Support HTTPS connections when ``$root`` is not configured
|
||||||
- SQL schema version table to ease future database upgrades
|
- SQL schema version table to ease future database upgrades
|
||||||
- Documentation is written with rST (reStructuredText) now
|
- Documentation is written with rST (reStructuredText) now
|
||||||
|
- Support per-host configuration files
|
||||||
|
|
||||||
|
|
||||||
0.97.2 - 2011-02-17
|
0.97.2 - 2011-02-17
|
||||||
|
|
|
@ -22,7 +22,7 @@ Installation instructions
|
||||||
on the shell ("semanticscuttle" being the database name)
|
on the shell ("semanticscuttle" being the database name)
|
||||||
|
|
||||||
3. Copy ``data/config.php.dist`` to ``data/config.php`` and modify it as
|
3. Copy ``data/config.php.dist`` to ``data/config.php`` and modify it as
|
||||||
necessary.
|
necessary. See configuration_ for more information.
|
||||||
4. Make the cache directory writable by your web server.
|
4. Make the cache directory writable by your web server.
|
||||||
For example, run ::
|
For example, run ::
|
||||||
|
|
||||||
|
@ -31,6 +31,12 @@ Installation instructions
|
||||||
on the shell.
|
on the shell.
|
||||||
5. Set the ``www/`` directory as document root in your web server,
|
5. Set the ``www/`` directory as document root in your web server,
|
||||||
restart the web server.
|
restart the web server.
|
||||||
|
6. That's all! Visit your SemanticScuttle installation web site now
|
||||||
|
with your browser.
|
||||||
|
7. Register a user and add bookmarks.
|
||||||
|
|
||||||
|
|
||||||
|
.. _configuration: configuration.html
|
||||||
|
|
||||||
|
|
||||||
Ugly www directory in URLs
|
Ugly www directory in URLs
|
||||||
|
|
|
@ -4,7 +4,9 @@ SemanticScuttle 0.98
|
||||||
A social bookmarking tool experimenting with new features
|
A social bookmarking tool experimenting with new features
|
||||||
like structured tags or collaborative descriptions of tags.
|
like structured tags or collaborative descriptions of tags.
|
||||||
|
|
||||||
https://sourceforge.net/projects/semanticscuttle/
|
- Home page: http://semanticscuttle.sourceforge.net/
|
||||||
|
- Project page: https://sourceforge.net/projects/semanticscuttle/
|
||||||
|
- Demo: http://semanticscuttle.sourceforge.net/demo/
|
||||||
|
|
||||||
Available under the GNU General Public License
|
Available under the GNU General Public License
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
Upgrading SemanticScuttle from a previous version
|
Upgrading SemanticScuttle from a previous version
|
||||||
=================================================
|
=================================================
|
||||||
|
|
||||||
|
.. contents::
|
||||||
|
|
||||||
From version 0.97 to 0.98
|
From version 0.97 to 0.98
|
||||||
=========================
|
=========================
|
||||||
|
@ -9,6 +10,9 @@ Database updates
|
||||||
----------------
|
----------------
|
||||||
Apply ``data/schema/6.sql``
|
Apply ``data/schema/6.sql``
|
||||||
|
|
||||||
|
ALTER TABLE `sc_users` ADD `privateKey` VARCHAR(33) NULL;
|
||||||
|
CREATE UNIQUE INDEX `privateKey` ON `sc_users` (`privateKey`);
|
||||||
|
|
||||||
|
|
||||||
From version 0.96 to 0.97
|
From version 0.96 to 0.97
|
||||||
=========================
|
=========================
|
||||||
|
|
31
doc/allinone.rst
Normal file
31
doc/allinone.rst
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
=============================
|
||||||
|
SemanticScuttle documentation
|
||||||
|
=============================
|
||||||
|
|
||||||
|
.. contents::
|
||||||
|
|
||||||
|
First reads
|
||||||
|
===========
|
||||||
|
.. include:: README.rst
|
||||||
|
.. include:: INSTALL.txt
|
||||||
|
.. include:: UPGRADE.txt
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Features
|
||||||
|
========
|
||||||
|
.. include:: authentication.rst
|
||||||
|
.. include:: ssl-client-certificates.rst
|
||||||
|
.. include:: themes.rst
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Developer documentation
|
||||||
|
=======================
|
||||||
|
.. include:: developers/rules.rst
|
||||||
|
.. include:: developers/api.rst
|
||||||
|
.. include:: developers/debugging.rst
|
||||||
|
.. include:: developers/release-new-version.rst
|
||||||
|
.. include:: developers/running-unit-tests.rst
|
||||||
|
.. include:: developers/translation.rst
|
||||||
|
.. include:: ChangeLog
|
58
doc/configuration.rst
Normal file
58
doc/configuration.rst
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
===================
|
||||||
|
Configuration files
|
||||||
|
===================
|
||||||
|
|
||||||
|
SemanticScuttle uses at least two configuration files:
|
||||||
|
|
||||||
|
1. Default configuration file ``config.default.php``
|
||||||
|
2. Custom configuration file ``config.php``
|
||||||
|
|
||||||
|
|
||||||
|
The **default configuration** file contains sensible defaults for most users
|
||||||
|
that do not need to be changed to get started.
|
||||||
|
|
||||||
|
Never change it - it will get overwritten with the next update.
|
||||||
|
If you want to change values in it, copy them into your personal
|
||||||
|
``config.php`` file - updates to SemanticScuttle will not change that one.
|
||||||
|
|
||||||
|
The **custom configuration** file, ``config.php`` is created by copying the
|
||||||
|
shipped ``config.php.dist`` file and modifying the values in there.
|
||||||
|
|
||||||
|
It consists of the configuration directives that should be set on every
|
||||||
|
fresh installation.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Configuration scenarios
|
||||||
|
=======================
|
||||||
|
|
||||||
|
Simple installation
|
||||||
|
-------------------
|
||||||
|
Put your configuration file in ``data/config.php``.
|
||||||
|
If you installed SemanticScuttle's PEAR package, use::
|
||||||
|
|
||||||
|
$ pear config-get data_dir
|
||||||
|
/usr/share/php/data
|
||||||
|
|
||||||
|
to find the data directory location and append ``SemanticScuttle/`` to it.
|
||||||
|
In this case, the configuration file has to be in::
|
||||||
|
|
||||||
|
/usr/share/php/data/SemanticScuttle/config.php
|
||||||
|
|
||||||
|
|
||||||
|
The configuration file may also be saved into::
|
||||||
|
|
||||||
|
/etc/semanticscuttle/config.php
|
||||||
|
|
||||||
|
|
||||||
|
Multiple SemanticScuttle instances
|
||||||
|
----------------------------------
|
||||||
|
The files of one single SemanticScuttle installation may be shared
|
||||||
|
for several SemanticScuttle instances.
|
||||||
|
|
||||||
|
To be able to configure them differently, SemanticScuttle supports
|
||||||
|
per-host configuration files:
|
||||||
|
|
||||||
|
- ``data/config.$hostname.php``
|
||||||
|
- ``/etc/semanticscuttle/config.$hostname.php``
|
||||||
|
|
|
@ -2,18 +2,18 @@ How to release a new version of SemanticScuttle
|
||||||
===============================================
|
===============================================
|
||||||
|
|
||||||
0. Run unit tests and verify that all of them pass
|
0. Run unit tests and verify that all of them pass
|
||||||
1. Update doc/ChangeLog
|
1. Update ``doc/ChangeLog``
|
||||||
2. Update doc/UPGRADE.txt
|
2. Update ``doc/UPGRADE.txt``
|
||||||
3. Update version in data/templates/about.tpl.php,
|
3. Update version in ``data/templates/about.tpl.php``,
|
||||||
build.xml and doc/README.txt
|
``build.xml`` and ``doc/README.rst``
|
||||||
4. Create a release zip file via the build script:
|
4. Create a release zip file via the build script:
|
||||||
Just type "phing".
|
Just type "``phing``".
|
||||||
5. Make a test installation from your zip file with a fresh
|
5. Make a test installation from your zip file with a fresh
|
||||||
database. Register a user, add bookmarks etc.
|
database. Register a user, add bookmarks etc.
|
||||||
6. When all is fine, it's time to release.
|
6. When all is fine, it's time to release.
|
||||||
The build script takes care for most of the
|
The build script takes care for most of the
|
||||||
tasks.
|
tasks.
|
||||||
Run "phing release", and it will upload the release to
|
Run "``phing release``", and it will upload the release to
|
||||||
sourceforge and create a svn tag.
|
sourceforge and create a svn tag.
|
||||||
7. Write announcement mail to the SemanticScuttle mailing list
|
7. Write announcement mail to the SemanticScuttle mailing list
|
||||||
semanticscuttle-devel@lists.sourceforge.net
|
semanticscuttle-devel@lists.sourceforge.net
|
||||||
|
|
|
@ -20,10 +20,12 @@ Features
|
||||||
- `Custom user authentication`__
|
- `Custom user authentication`__
|
||||||
- `SSL Client certificates`__
|
- `SSL Client certificates`__
|
||||||
- Themes__
|
- Themes__
|
||||||
|
- `Configuration files`__
|
||||||
|
|
||||||
__ authentication.html
|
__ authentication.html
|
||||||
__ ssl-client-certificates.html
|
__ ssl-client-certificates.html
|
||||||
__ themes.html
|
__ themes.html
|
||||||
|
__ configuration.html
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -35,6 +37,7 @@ Developer documentation
|
||||||
- `How to release a new version`__
|
- `How to release a new version`__
|
||||||
- `Running unit testes`__
|
- `Running unit testes`__
|
||||||
- `How to translate SemanticScuttle`__
|
- `How to translate SemanticScuttle`__
|
||||||
|
- `ChangeLog`__
|
||||||
|
|
||||||
__ developers/rules.html
|
__ developers/rules.html
|
||||||
__ developers/api.html
|
__ developers/api.html
|
||||||
|
@ -42,4 +45,4 @@ __ developers/debugging.html
|
||||||
__ developers/release-new-version.html
|
__ developers/release-new-version.html
|
||||||
__ developers/running-unit-tests.html
|
__ developers/running-unit-tests.html
|
||||||
__ developers/translation.html
|
__ developers/translation.html
|
||||||
|
__ ChangeLog.html
|
||||||
|
|
8
res/docs/header.tpl.html
Normal file
8
res/docs/header.tpl.html
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<ul class="menu">
|
||||||
|
<li><a href="index.html">Index</a></li>
|
||||||
|
<li><a href="INSTALL.html">Installation</a></li>
|
||||||
|
<li><a href="UPGRADE.html">Upgrade</a></li>
|
||||||
|
<li><a href="ChangeLog.html">ChangeLog</a></li>
|
||||||
|
<li><a href="http://semanticscuttle.sourceforget.net/">Homepage</a></li>
|
||||||
|
<li><a href="https://sourceforget.net/projects/semanticscuttle">Project page</a></li>
|
||||||
|
</ul>
|
25
res/docs/style.css
Normal file
25
res/docs/style.css
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
/* SemanticScuttle improvements */
|
||||||
|
h1.title {
|
||||||
|
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAABHNCSVQICAgIfAhkiAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAsvSURBVGiBxZprjCRXdcd/p6r6Nd0979mHZ+3sCkfx4AdJsAhGm2BMYhAbrAgsEimKjGIlxELk8SkrQoQiSGgrCSJZh9hECsQ8hJCQlRDjYDsY4RAvRF6b9drN2t7HzOzOzmtnpl/V1fW4Jx+qu6emZ3pmbI/kI7Wq+9Ste///87j33FstqspeS7kkR4HPAAeAx4G/mDqu9T0fCJC9JlAuyXuB72Ymbklnxt9K/fxjmFblf4A7p45rc08HA6y97KxcksPAI5mJW9JDN99DbvI2Rt7+CSSVPwo8tJdjdWRPCQAPWZmhYuHn70LwyeQFOzvC4C/cDfB75ZL85h6Pt3cEyiW5B7gzf+T9ABRGM+SHHFIZQ3p8isz4TajyYLkkQ3s1JuwRgXJJ9gGfT49NkSpeQzYvpDMKxic/kkLUp3D9MaxUbhL4u70YsyN75YH7xcmN5q75FUQCCqNp0BaYFraE5IdTiJUmf+ROVLm3XJLb9mjcN06gXJJ3Avdk9/0iqDK0L4slAZgA1Af1yeaFVMaQGXsrqeKkGOWBckn2xHhvqJNySQQ4YWVHxRk8RCYvZHICptX1ACYmURhLo8Zj4OfegyXyy8C9bzoB4GPArZmxKYg8hvbn2lYP2sCDLgnHMQwMOtjZETLjN2IMnyuXZORNI1AuyU3A553CJOJkKY5ncZxog9W7V/XBtOKExid78Fbs9MCYUf71TSHQBv8tSeVzTnESJxVSnMgkgLfWwyhBxCJgcF8WEPJxKP1WuSSfLZdk8PUS2FUpUS7JAeCdwG3AMeBGsbOkhg5jpXNM3nQd6YEsiAU48VVsoH0VC7Db323WrtRorHr4Ky/TWnwejVot4HvAD4BngOemjmvrdRMol+Qg8OvAbwC/ChwGASuFlcphpQqIk0XEZuL6/QzuH2kD7AVub6lXtVi6sELgGRAhbMwTVGeJGgsYvwrgA6eAp4iLwf+dOq7+tgTKJbkF+Ggb9E3xbQssG7EcxE6D2IjYWKkU+fFBhg+MkhvO94DcgUj7atSisdKkWfXbRGzEstEoIGouE7qLhLU5ouYSQAP4IfBd4OGp41rtEnjpc+SBh4EPbe0kC7EtcsMFsoMFBkYK5EeKWI5DMiz6hctu9IGvePWAoBkReBFhAGK125mAsD5PULtEsHYOjVoV4ONTx/XrHQL/DPzRBrdYwsDwAPmRPAOjA2QLWcSSra2btHI//WsIL8TGRELLDWm5AX4jJAxBxAYUb/4U3sIpBd4+dVyfc4APdIAXxguMXjtKbjiHZW01QUWg7Y9YoB0gUft7r5UT+k7bThttA07q220tyyZXsMgVB0AswgBa9YD6VZfMvrfhLZwS4H3Acw5wBbgOIFvMkh/Nbx1JG8SAGiBMAEiAwtqlPtqsJ6mPDeA4NtagTW2xhb86DcBilaWp+ElOdGAtX1ymsdLYBYFer/QuWtuvBxv0Znf6lZkrBG4Fb/5ZWgGLv/sgMyIybgHfaIWcBEDh8guX8Ztbzli7INIuHbpg2wWdWS8pNul7wXafXddXrizjXl2jefkkGrp8v8wDl1fxgWtFVbnvDvmlj93B4xmHcYBMPsPhWw9jpTKQmoD0frAH25177U8LWpdiXV/pJKnD5tlod/pGxWPp3ApB5SJhbZZXF/jWXV/gi+0BPAfgwac4m0nxl39wO/9oWU4qdeiDVPQwwweuRTqdqqGbxGisswvgnoX6s+DP9/FKlIjpZPJaINH66r2FvtWIWHplkdBdIazNslLn2d/+Ig8mBlhxAFTVFZHv33CQv3/3DeHxsDKNHjpKo+pQGMkCJgathvUENhDWYw9N3A2RC9WT4L60BZH2MxomQDqsz1JRj/UjAs9w5cV5Qq9BUJnGC7jyx1/jr5o+Zt06TCfnyvP3/RuPlOf4qjf/f9TPPUqr5uKu1duDR20gHasaEI0BRY04pIbfCxO/E3tmS9GYxIaE3Vy1Rn6TuTMXCRprBJUZwkgbJ57gk6emqSY6e0VV/S4BVQ2BMx8+wZcurfBfjYtP0Jw7ibtap9VorpPoeiFK6NqhEC6DpODgH0L+5j4kkuGVTPo4adW0mDtzkVa1QtiYx6gJvvljPvnlp7mQePiSqi5ATzmtqi5Q/tAJ/na5xo9rZx8hqFygtrhGFAY9edDxSoIIGs8e3kzbGx8Ba6d1xazPSuqzfH6OxtU1Im8VNZF54gx//Tff4aeJB1aB850fm5ZbVb1a9zh3z5f4tOub2erZb2OCJtWFVbTXA0SgGv/uxnk7X7yLYGXhmvtg6NdAMjsQUZprNZbPz6GBCxpx5jJf/rNv8INEIxd4SRMl9JYbGlWdvrDMxa88zWej5mrUuPgkgesTND02JHHXI4ZNeYKBYAXcn8XhdOhPYfg9YOX6Urg6c7VrkEqTFz/6L3w9cdsHXmiHele225G9/MCTPLNc5ydB7TKqESYMEiAT4DeFVfJ+CM2XYyK5G2DyT+LwckY3DRj669gef4Gv9Mw4L6iq1/uM0w+9qqqIvCTgYhIzT8f6vSFDMg96pls1ENXiKVYccEZg7FgcVurH9/wl0qOD+P4FIneReovOQbACL6pufbq97Z5YVaPhAdZQAyaKc6BfyCRnpU0eSuiNB/5lcF+BxumYlHcJALt4mIHrbgfAGDpxPqOqq/0w9vVAt4HNsDgZVCNEeuM/4YEu4J6k3tCm10OJtlEL9eYIKi4gjBd1kHgnNr0tvp0IAAcklQcTYdusg9guZDbptgK/+b6dEtTEZcdYIRwFmrrDqcOuCFhODtUIy5adwe8EuGv5iI3eM9iOgEaIZTM0EI62B9tWtiVQLkkKGBUnBxph2dtZOxE+m0gpuwkv26HtAYtChlF2cW61kwdGABE7jYhB+gF+LR7YcN9sIG070ClLBjKMA+k3SqAI8QmBSD/rbgTsey2aqw3ctRqRH5DOp8gP58gW03EObUkq7ltsUDWIWKQsBvaMAGLH1t9g1XUPGBPhrtSoLVUJ3BaqBtNaw/gNAncI92oVMORHcwzuK5IZcLYIL4NldQwBjr2HBERsxNq8iEVBQG2pSn25hgkCTFAnqM4QuUto1DkZFKx0ATs3Ri0coba4RibvMLS/SH4kF3u23a9lxTmgqjgWOUBExOktH14LgWx86cR63LlXaVBfqeFVXTSKCN0Fgso0xlvBGPzFKj86fYmny3PM3DGltx3ZV7u94NfeQnUWOzuK8YfxKnVsRyiO5ylMDJDJOSCdRdEQbwUBsIHXTWAJwAQNAs9nZfYqzaqL8QNM6BJUZwmrs2jk4Ycsn73Cv3/he3znmXOsdTp46CleBb7658e45f03R3fvG1w6Ks0lS1J5onSRVa/Jyqwhk0/hZKx4xTchrYCVBIG+shOBl4FaUJku2rkx6o0KUXM5PohtLqOqutrg1LMXefTTj/DDNbe/pe5/lNP3P8rpY29j/73v5oNHJhrvywSNiQgLK53HCzLxwa+JX46sNji3G4w7Hq+XS/IJVf5BBOnoWgGL5xZ57OEf8dh/PMdWu/mO+MQbkByw4R1ALo31qbt4x7uu5wMTg7zLknWgfsjyp77Nx//zeRaA09vVQrt6P/CZD8vv33CQo65P9acznP2n/+ZnftgtdXtFgWVgTlW7oSQiGeL/TlxDz+xy6xEGP/IObj48zlu8APeBJ3niJ+eptG8/r6oV+siuCIjIjRCfGW0jIfEx5WXV/i8nRESACWCSHq/0kZPb9bebWghgkf4E1oB5YElV+3mlK+3ibBFYFJECsVf298Gyth142KUHAERkEjgEpIA6cWwvbLVLeq0iIhYwRuyZQeKZZxV4VXXboz/+HwP+91Qbpr+OAAAAAElFTkSuQmCC");
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
padding-left: 64px;
|
||||||
|
padding-top: 0.2em;
|
||||||
|
margin-bottom: 00px;
|
||||||
|
height: 60px;
|
||||||
|
border-bottom: 3px solid #666;
|
||||||
|
}
|
||||||
|
h2 {
|
||||||
|
margin-top: 1.5em;
|
||||||
|
|
||||||
|
}
|
||||||
|
pre {
|
||||||
|
padding: 1em;
|
||||||
|
background-color: #EEE;
|
||||||
|
border: 1px solid #BBB;
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
tt, code {
|
||||||
|
background-color: #DDD;
|
||||||
|
padding: 0.2ex;
|
||||||
|
}
|
109
src/SemanticScuttle/Config.php
Normal file
109
src/SemanticScuttle/Config.php
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* SemanticScuttle - your social bookmark manager.
|
||||||
|
*
|
||||||
|
* PHP version 5.
|
||||||
|
*
|
||||||
|
* @category Bookmarking
|
||||||
|
* @package SemanticScuttle
|
||||||
|
* @author Christian Weiske <cweiske@cweiske.de>
|
||||||
|
* @license AGPL http://www.gnu.org/licenses/agpl.html
|
||||||
|
* @link http://sourceforge.net/projects/semanticscuttle
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configuration handling
|
||||||
|
*
|
||||||
|
* @category Bookmarking
|
||||||
|
* @package SemanticScuttle
|
||||||
|
* @author Christian Weiske <cweiske@cweiske.de>
|
||||||
|
* @license AGPL http://www.gnu.org/licenses/agpl.html
|
||||||
|
* @link http://sourceforge.net/projects/semanticscuttle
|
||||||
|
*/
|
||||||
|
class SemanticScuttle_Config
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Prefix for configuration files.
|
||||||
|
* Used to inject stream wrapper protocol for unit testing
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $filePrefix = '';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds the correct data directory
|
||||||
|
*
|
||||||
|
* @return string Full path to the data directory with a trailing slash
|
||||||
|
*/
|
||||||
|
protected function getDataDir()
|
||||||
|
{
|
||||||
|
if ('@data_dir@' == '@' . 'data_dir@') {
|
||||||
|
//non pear-install
|
||||||
|
$datadir = dirname(__FILE__) . '/../../data/';
|
||||||
|
} else {
|
||||||
|
//pear installation; files are in include path
|
||||||
|
$datadir = '@data_dir@/SemanticScuttle/';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $datadir;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tries to find a configuration file by looking in different
|
||||||
|
* places:
|
||||||
|
* - pear data_dir/SemanticScuttle/config-$hostname.php
|
||||||
|
* - pear data_dir/SemanticScuttle/config.php
|
||||||
|
* - /etc/semanticscuttle/config-$hostname.php
|
||||||
|
* - /etc/semanticscuttle/config.php
|
||||||
|
*
|
||||||
|
* Paths with host name have priority.
|
||||||
|
*
|
||||||
|
* @return array Array with config file path as first value
|
||||||
|
* and default config file path as second value.
|
||||||
|
* Any may be NULL if not found
|
||||||
|
*/
|
||||||
|
public function findFiles()
|
||||||
|
{
|
||||||
|
//use basename to prevent path injection
|
||||||
|
$host = basename($_SERVER['HTTP_HOST']);
|
||||||
|
$datadir = $this->getDataDir();
|
||||||
|
|
||||||
|
$arFiles = array(
|
||||||
|
$datadir . 'config.' . $host . '.php',
|
||||||
|
'/etc/semanticscuttle/config.' . $host . '.php',
|
||||||
|
$datadir . 'config.php',
|
||||||
|
'/etc/semanticscuttle/config.php',
|
||||||
|
);
|
||||||
|
|
||||||
|
$configfile = null;
|
||||||
|
foreach ($arFiles as $file) {
|
||||||
|
if (file_exists($this->filePrefix . $file)) {
|
||||||
|
$configfile = $file;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//find default file
|
||||||
|
$arDefaultFiles = array_unique(
|
||||||
|
array(
|
||||||
|
substr($configfile, 0, -3) . 'default.php',
|
||||||
|
$datadir . 'config.default.php',
|
||||||
|
'/etc/semanticscuttle/config.default.php',
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$defaultfile = null;
|
||||||
|
foreach ($arDefaultFiles as $file) {
|
||||||
|
if (file_exists($this->filePrefix . $file)) {
|
||||||
|
$defaultfile = $file;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return array($configfile, $defaultfile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
52
src/SemanticScuttle/Environment.php
Normal file
52
src/SemanticScuttle/Environment.php
Normal 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 AGPL http://www.gnu.org/licenses/agpl.html
|
||||||
|
* @link http://sourceforge.net/projects/semanticscuttle
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Server environment handling methods
|
||||||
|
*
|
||||||
|
* @category Bookmarking
|
||||||
|
* @package SemanticScuttle
|
||||||
|
* @author Christian Weiske <cweiske@cweiske.de>
|
||||||
|
* @license AGPL http://www.gnu.org/licenses/agpl.html
|
||||||
|
* @link http://sourceforge.net/projects/semanticscuttle
|
||||||
|
*/
|
||||||
|
class SemanticScuttle_Environment
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determines the correct $_SERVER['PATH_INFO'] value
|
||||||
|
*
|
||||||
|
* @return string New value
|
||||||
|
*/
|
||||||
|
public static function getServerPathInfo()
|
||||||
|
{
|
||||||
|
/* old code that does not work today.
|
||||||
|
if you find that this code helps you, tell us
|
||||||
|
and send us the output of var_export($_SERVER);
|
||||||
|
// Correct bugs with PATH_INFO (maybe for Apache 1 or CGI) -- for 1&1 host...
|
||||||
|
if (isset($_SERVER['PATH_INFO']) && isset($_SERVER['ORIG_PATH_INFO'])) {
|
||||||
|
if (strlen($_SERVER["PATH_INFO"])<strlen($_SERVER["ORIG_PATH_INFO"])) {
|
||||||
|
$_SERVER["PATH_INFO"] = $_SERVER["ORIG_PATH_INFO"];
|
||||||
|
}
|
||||||
|
if (strcasecmp($_SERVER["PATH_INFO"], $_SERVER["SCRIPT_NAME"]) == 0) {
|
||||||
|
unset($_SERVER["PATH_INFO"]);
|
||||||
|
}
|
||||||
|
if (strpos($_SERVER["PATH_INFO"], '.php') !== false) {
|
||||||
|
unset($_SERVER["PATH_INFO"]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
return $_SERVER['PATH_INFO'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
|
@ -23,6 +23,23 @@
|
||||||
*/
|
*/
|
||||||
class SemanticScuttle_Model_Bookmark
|
class SemanticScuttle_Model_Bookmark
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Status "public" / visible for all
|
||||||
|
*/
|
||||||
|
const SPUBLIC = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Status "shared" / visible for people on your watchlist
|
||||||
|
*/
|
||||||
|
const SWATCHLIST = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Status "private" / visible for yourself only
|
||||||
|
*/
|
||||||
|
const SPRIVATE = 2;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the given URL is valid and may be used with this
|
* Checks if the given URL is valid and may be used with this
|
||||||
* SemanticScuttle installation.
|
* SemanticScuttle installation.
|
||||||
|
|
|
@ -35,6 +35,7 @@ class SemanticScuttle_Model_User
|
||||||
var $content;
|
var $content;
|
||||||
var $datetime;
|
var $datetime;
|
||||||
var $isAdmin;
|
var $isAdmin;
|
||||||
|
var $privateKey;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new user object
|
* Create a new user object
|
||||||
|
@ -68,6 +69,29 @@ class SemanticScuttle_Model_User
|
||||||
return $this->username;
|
return $this->username;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns private key
|
||||||
|
*
|
||||||
|
* @param boolean return sanitized value which basically drops
|
||||||
|
* leading dash if exists
|
||||||
|
*
|
||||||
|
* @return string private key
|
||||||
|
*/
|
||||||
|
public function getPrivateKey($sanitized = false)
|
||||||
|
{
|
||||||
|
// Look for value only if not already set
|
||||||
|
if (!isset($this->privateKey)) {
|
||||||
|
$us = SemanticScuttle_Service_Factory::get('User');
|
||||||
|
$user = $us->getUser($this->id);
|
||||||
|
$this->privateKey = $user['privateKey'];
|
||||||
|
}
|
||||||
|
if ($sanitized == true) {
|
||||||
|
return substr($this->privateKey, -32);
|
||||||
|
} else {
|
||||||
|
return $this->privateKey;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns full user name as specified in the profile.
|
* Returns full user name as specified in the profile.
|
||||||
*
|
*
|
||||||
|
|
|
@ -427,6 +427,7 @@ class SemanticScuttle_Service_Bookmark extends SemanticScuttle_DbService
|
||||||
$existence[$hashes[$row['bHash']]] = $row['count'] > 0;
|
$existence[$hashes[$row['bHash']]] = $row['count'] > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->db->sql_freeresult($dbresult);
|
||||||
return $existence;
|
return $existence;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -99,7 +99,7 @@ class SemanticScuttle_Service_Bookmark2Tag extends SemanticScuttle_DbService
|
||||||
$tags_count = is_array($tags)?count($tags):0;
|
$tags_count = is_array($tags)?count($tags):0;
|
||||||
|
|
||||||
for ($i = 0; $i < $tags_count; $i++) {
|
for ($i = 0; $i < $tags_count; $i++) {
|
||||||
$tags[$i] = trim(strtolower($tags[$i]));
|
$tags[$i] = trim(utf8_strtolower($tags[$i]));
|
||||||
if ($fromApi) {
|
if ($fromApi) {
|
||||||
include_once 'SemanticScuttle/functions.php';
|
include_once 'SemanticScuttle/functions.php';
|
||||||
$tags[$i] = convertTag($tags[$i], 'in');
|
$tags[$i] = convertTag($tags[$i], 'in');
|
||||||
|
@ -584,7 +584,7 @@ class SemanticScuttle_Service_Bookmark2Tag extends SemanticScuttle_DbService
|
||||||
|
|
||||||
if (is_int($days)) {
|
if (is_int($days)) {
|
||||||
$query .= ' AND B.bDatetime > "'
|
$query .= ' AND B.bDatetime > "'
|
||||||
. date('Y-m-d H:i:s', time() - (86400 * $days))
|
. gmdate('Y-m-d H:i:s', time() - (86400 * $days))
|
||||||
. '"';
|
. '"';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -141,10 +141,10 @@ class SemanticScuttle_Service_Tag extends SemanticScuttle_DbService
|
||||||
|
|
||||||
//normalize
|
//normalize
|
||||||
if(!is_array($tags)) {
|
if(!is_array($tags)) {
|
||||||
$tags = strtolower(trim($tags));
|
$tags = utf8_strtolower(trim($tags));
|
||||||
} else {
|
} else {
|
||||||
for($i=0; $i<count($tags); $i++) {
|
for($i=0; $i<count($tags); $i++) {
|
||||||
$tags[$i] = strtolower(trim($tags[$i]));
|
$tags[$i] = utf8_strtolower(trim($tags[$i]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $tags;
|
return $tags;
|
||||||
|
|
|
@ -48,9 +48,10 @@ class SemanticScuttle_Service_User extends SemanticScuttle_DbService
|
||||||
protected $currentuser = null;
|
protected $currentuser = null;
|
||||||
|
|
||||||
protected $fields = array(
|
protected $fields = array(
|
||||||
'primary' => 'uId',
|
'primary' => 'uId',
|
||||||
'username' => 'username',
|
'username' => 'username',
|
||||||
'password' => 'password'
|
'password' => 'password',
|
||||||
|
'privateKey' => 'privateKey'
|
||||||
);
|
);
|
||||||
|
|
||||||
protected $profileurl;
|
protected $profileurl;
|
||||||
|
@ -215,6 +216,18 @@ class SemanticScuttle_Service_User extends SemanticScuttle_DbService
|
||||||
return $this->_getuser($this->getFieldName('username'), $username);
|
return $this->_getuser($this->getFieldName('username'), $username);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns user row from database.
|
||||||
|
*
|
||||||
|
* @param string $privateKey Private Key
|
||||||
|
*
|
||||||
|
* @return array User array from database, false if no user was found
|
||||||
|
*/
|
||||||
|
public function getUserByPrivateKey($privateKey)
|
||||||
|
{
|
||||||
|
return $this->_getuser($this->getFieldName('privateKey'), $privateKey);
|
||||||
|
}
|
||||||
|
|
||||||
function getObjectUserByUsername($username) {
|
function getObjectUserByUsername($username) {
|
||||||
$user = $this->_getuser($this->getFieldName('username'), $username);
|
$user = $this->_getuser($this->getFieldName('username'), $username);
|
||||||
if($user != false) {
|
if($user != false) {
|
||||||
|
@ -279,6 +292,22 @@ class SemanticScuttle_Service_User extends SemanticScuttle_DbService
|
||||||
return ($this->getCurrentUserId() !== false);
|
return ($this->getCurrentUserId() !== false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tells you if the private key is enabled and valid
|
||||||
|
*
|
||||||
|
* @param string $privateKey Private Key
|
||||||
|
*
|
||||||
|
* @return boolean True if enabled and valid
|
||||||
|
*/
|
||||||
|
public function isPrivateKeyValid($privateKey)
|
||||||
|
{
|
||||||
|
// check length of private key
|
||||||
|
if (strlen($privateKey) == 32) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the current user object
|
* Returns the current user object
|
||||||
*
|
*
|
||||||
|
@ -293,7 +322,7 @@ class SemanticScuttle_Service_User extends SemanticScuttle_DbService
|
||||||
{
|
{
|
||||||
if (!is_null($newval)) {
|
if (!is_null($newval)) {
|
||||||
//internal use only: reset currentuser
|
//internal use only: reset currentuser
|
||||||
$currentuser = $newval;
|
$this->currentuser = $newval;
|
||||||
} else if ($refresh || !isset($this->currentuser)) {
|
} else if ($refresh || !isset($this->currentuser)) {
|
||||||
if ($id = $this->getCurrentUserId()) {
|
if ($id = $this->getCurrentUserId()) {
|
||||||
$this->currentuser = $this->getUser($id);
|
$this->currentuser = $this->getUser($id);
|
||||||
|
@ -509,6 +538,46 @@ class SemanticScuttle_Service_User extends SemanticScuttle_DbService
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Try to authenticate via the privateKey
|
||||||
|
*
|
||||||
|
* @param string $privateKey Private Key
|
||||||
|
*
|
||||||
|
* @return boolean true if the user could be authenticated,
|
||||||
|
* false if not.
|
||||||
|
*/
|
||||||
|
public function loginPrivateKey($privateKey)
|
||||||
|
{
|
||||||
|
/* Check if private key valid and enabled */
|
||||||
|
if (!$this->isPrivateKeyValid($privateKey)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$query = 'SELECT '. $this->getFieldName('primary') .' FROM '
|
||||||
|
. $this->getTableName() .' WHERE '
|
||||||
|
. $this->getFieldName('privateKey') .' = "'
|
||||||
|
. $this->db->sql_escape($privateKey) .'"';
|
||||||
|
|
||||||
|
if (!($dbresult = $this->db->sql_query($query))) {
|
||||||
|
message_die(
|
||||||
|
GENERAL_ERROR,
|
||||||
|
'Could not get user',
|
||||||
|
'', __LINE__, __FILE__, $query, $this->db
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$row = $this->db->sql_fetchrow($dbresult);
|
||||||
|
$this->db->sql_freeresult($dbresult);
|
||||||
|
|
||||||
|
if ($row) {
|
||||||
|
$this->setCurrentUserId($row[$this->getFieldName('primary')], false);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Logs the user off
|
* Logs the user off
|
||||||
*
|
*
|
||||||
|
@ -519,7 +588,8 @@ class SemanticScuttle_Service_User extends SemanticScuttle_DbService
|
||||||
@setcookie($this->getCookiekey(), '', time() - 1, '/');
|
@setcookie($this->getCookiekey(), '', time() - 1, '/');
|
||||||
unset($_COOKIE[$this->getCookiekey()]);
|
unset($_COOKIE[$this->getCookiekey()]);
|
||||||
session_unset();
|
session_unset();
|
||||||
$this->getCurrentUser(TRUE, false);
|
$this->currentuserId = null;
|
||||||
|
$this->currentuser = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getWatchlist($uId) {
|
function getWatchlist($uId) {
|
||||||
|
@ -603,11 +673,12 @@ class SemanticScuttle_Service_User extends SemanticScuttle_DbService
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$arrWatch = array();
|
$retval = true;
|
||||||
if ($this->db->sql_numrows($dbresult) == 0)
|
if ($this->db->sql_numrows($dbresult) == 0)
|
||||||
return false;
|
$retval = false;
|
||||||
else
|
|
||||||
return true;
|
$this->db->sql_freeresult($dbresult);
|
||||||
|
return $retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
function setWatchStatus($subjectUserID) {
|
function setWatchStatus($subjectUserID) {
|
||||||
|
@ -646,24 +717,26 @@ class SemanticScuttle_Service_User extends SemanticScuttle_DbService
|
||||||
* No checks are done in here - you ought to have checked
|
* No checks are done in here - you ought to have checked
|
||||||
* everything before calling this method!
|
* everything before calling this method!
|
||||||
*
|
*
|
||||||
* @param string $username Username to use
|
* @param string $username Username to use
|
||||||
* @param string $password Password to use
|
* @param string $password Password to use
|
||||||
* @param string $email Email to use
|
* @param string $email Email to use
|
||||||
|
* @param string $privateKey Key for RSS auth
|
||||||
*
|
*
|
||||||
* @return mixed Integer user ID if all is well,
|
* @return mixed Integer user ID if all is well,
|
||||||
* boolean false if an error occured
|
* boolean false if an error occured
|
||||||
*/
|
*/
|
||||||
public function addUser($username, $password, $email)
|
public function addUser($username, $password, $email, $privateKey = null)
|
||||||
{
|
{
|
||||||
// Set up the SQL UPDATE statement.
|
// Set up the SQL UPDATE statement.
|
||||||
$datetime = gmdate('Y-m-d H:i:s', time());
|
$datetime = gmdate('Y-m-d H:i:s', time());
|
||||||
$password = $this->sanitisePassword($password);
|
$password = $this->sanitisePassword($password);
|
||||||
$values = array(
|
$values = array(
|
||||||
'username' => $username,
|
'username' => $username,
|
||||||
'password' => $password,
|
'password' => $password,
|
||||||
'email' => $email,
|
'email' => $email,
|
||||||
'uDatetime' => $datetime,
|
'uDatetime' => $datetime,
|
||||||
'uModified' => $datetime
|
'uModified' => $datetime,
|
||||||
|
'privateKey' => $privateKey
|
||||||
);
|
);
|
||||||
$sql = 'INSERT INTO '. $this->getTableName()
|
$sql = 'INSERT INTO '. $this->getTableName()
|
||||||
. ' '. $this->db->sql_build_array('INSERT', $values);
|
. ' '. $this->db->sql_build_array('INSERT', $values);
|
||||||
|
@ -687,40 +760,64 @@ class SemanticScuttle_Service_User extends SemanticScuttle_DbService
|
||||||
/**
|
/**
|
||||||
* Updates the given user
|
* Updates the given user
|
||||||
*
|
*
|
||||||
* @param integer $uId ID of user to change
|
* @param integer $uId ID of user to change
|
||||||
* @param string $password Password to use
|
* @param string $password Password to use
|
||||||
* @param string $name Realname to use
|
* @param string $name Realname to use
|
||||||
* @param string $email Email to use
|
* @param string $email Email to use
|
||||||
* @param string $homepage User's homepage
|
* @param string $homepage User's homepage
|
||||||
* @param string $uContent User note
|
* @param string $uContent User note
|
||||||
|
* @param string $privateKey RSS Private Key
|
||||||
|
* @param boolean $enablePrivateKey RSS Private Key Flag
|
||||||
*
|
*
|
||||||
* @return boolean True when all is well, false if not
|
* @return boolean True when all is well, false if not
|
||||||
*/
|
*/
|
||||||
public function updateUser(
|
public function updateUser(
|
||||||
$uId, $password, $name, $email, $homepage, $uContent
|
$uId, $password, $name, $email, $homepage, $uContent,
|
||||||
|
$privateKey = null, $enablePrivateKey = false
|
||||||
) {
|
) {
|
||||||
if (!is_numeric($uId)) {
|
if (!is_numeric($uId)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// prepend '-' to privateKey if disabled
|
||||||
|
if ($privateKey != null && strlen($privateKey) == 32
|
||||||
|
&& $enablePrivateKey == false
|
||||||
|
) {
|
||||||
|
$privateKey = '-' . $privateKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove '-' from privateKey if enabling
|
||||||
|
if ($privateKey != null && strlen($privateKey) == 33
|
||||||
|
&& $enablePrivateKey == true
|
||||||
|
) {
|
||||||
|
$privateKey = substr($privateKey, 1, 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if new user is enabling Private Key, create new key
|
||||||
|
if ($privateKey == null && $enablePrivateKey == true) {
|
||||||
|
$privateKey = $this->getNewPrivateKey();
|
||||||
|
}
|
||||||
|
|
||||||
// Set up the SQL UPDATE statement.
|
// Set up the SQL UPDATE statement.
|
||||||
$moddatetime = gmdate('Y-m-d H:i:s', time());
|
$moddatetime = gmdate('Y-m-d H:i:s', time());
|
||||||
if ($password == '') {
|
if ($password == '') {
|
||||||
$updates = array(
|
$updates = array(
|
||||||
'uModified' => $moddatetime,
|
'uModified' => $moddatetime,
|
||||||
'name' => $name,
|
'name' => $name,
|
||||||
'email' => $email,
|
'email' => $email,
|
||||||
'homepage' => $homepage,
|
'homepage' => $homepage,
|
||||||
'uContent' => $uContent
|
'uContent' => $uContent,
|
||||||
|
'privateKey' => $privateKey
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
$updates = array(
|
$updates = array(
|
||||||
'uModified' => $moddatetime,
|
'uModified' => $moddatetime,
|
||||||
'password' => $this->sanitisePassword($password),
|
'password' => $this->sanitisePassword($password),
|
||||||
'name' => $name,
|
'name' => $name,
|
||||||
'email' => $email,
|
'email' => $email,
|
||||||
'homepage' => $homepage,
|
'homepage' => $homepage,
|
||||||
'uContent' => $uContent
|
'uContent' => $uContent,
|
||||||
|
'privateKey' => $privateKey
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
$sql = 'UPDATE '. $this->getTableName()
|
$sql = 'UPDATE '. $this->getTableName()
|
||||||
|
@ -837,6 +934,56 @@ class SemanticScuttle_Service_User extends SemanticScuttle_DbService
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a new private key and confirms it isn't being used.
|
||||||
|
* Private key is 32 characters long, consisting of lowercase and
|
||||||
|
* numeric characters.
|
||||||
|
*
|
||||||
|
* @return string the new key value
|
||||||
|
*/
|
||||||
|
public function getNewPrivateKey()
|
||||||
|
{
|
||||||
|
do {
|
||||||
|
$newKey = md5(uniqid('SemanticScuttle', true));
|
||||||
|
} while ($this->privateKeyExists($newKey));
|
||||||
|
|
||||||
|
return $newKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if a private key already exists
|
||||||
|
*
|
||||||
|
* @param string $privateKey key that has been generated
|
||||||
|
*
|
||||||
|
* @return boolean true when the private key exists,
|
||||||
|
* False if not.
|
||||||
|
*/
|
||||||
|
public function privateKeyExists($privateKey)
|
||||||
|
{
|
||||||
|
if (!$privateKey) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$crit = array('privateKey' => $privateKey);
|
||||||
|
|
||||||
|
$sql = 'SELECT COUNT(*) as "0" FROM '
|
||||||
|
. $GLOBALS['tableprefix'] . 'users'
|
||||||
|
. ' WHERE '. $this->db->sql_build_array('SELECT', $crit);
|
||||||
|
|
||||||
|
if (!($dbresult = $this->db->sql_query($sql))) {
|
||||||
|
message_die(
|
||||||
|
GENERAL_ERROR, 'Could not get vars', '',
|
||||||
|
__LINE__, __FILE__, $sql, $this->db
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if ($this->db->sql_fetchfield(0, 0) > 0) {
|
||||||
|
$exists = true;
|
||||||
|
} else {
|
||||||
|
$exists = false;
|
||||||
|
}
|
||||||
|
$this->db->sql_freeresult($dbresult);
|
||||||
|
return $exists;
|
||||||
|
}
|
||||||
|
|
||||||
function isReserved($username) {
|
function isReserved($username) {
|
||||||
if (in_array($username, $GLOBALS['reservedusers'])) {
|
if (in_array($username, $GLOBALS['reservedusers'])) {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -69,16 +69,6 @@ define('PAGE_WATCHLIST', "watchlist");
|
||||||
// installations on the same host server
|
// installations on the same host server
|
||||||
define('INSTALLATION_ID', md5($GLOBALS['dbname'].$GLOBALS['tableprefix']));
|
define('INSTALLATION_ID', md5($GLOBALS['dbname'].$GLOBALS['tableprefix']));
|
||||||
|
|
||||||
// Correct bugs with PATH_INFO (maybe for Apache 1 or CGI) -- for 1&1 host...
|
//currently not needed
|
||||||
if (isset($_SERVER['PATH_INFO']) && isset($_SERVER['ORIG_PATH_INFO'])) {
|
//$_SERVER['PATH_INFO'] = SemanticScuttle_Environment::getServerPathInfo();
|
||||||
if (strlen($_SERVER["PATH_INFO"])<strlen($_SERVER["ORIG_PATH_INFO"])) {
|
|
||||||
$_SERVER["PATH_INFO"] = $_SERVER["ORIG_PATH_INFO"];
|
|
||||||
}
|
|
||||||
if (strcasecmp($_SERVER["PATH_INFO"], $_SERVER["SCRIPT_NAME "]) == 0) {
|
|
||||||
unset($_SERVER["PATH_INFO"]);
|
|
||||||
}
|
|
||||||
if (strpos($_SERVER["PATH_INFO"], '.php') !== false) {
|
|
||||||
unset($_SERVER["PATH_INFO"]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
?>
|
?>
|
||||||
|
|
|
@ -25,8 +25,20 @@ if ('@data_dir@' == '@' . 'data_dir@') {
|
||||||
//FIXME: when you have multiple installations, the www_dir will be wrong
|
//FIXME: when you have multiple installations, the www_dir will be wrong
|
||||||
$wwwdir = '@www_dir@/SemanticScuttle/';
|
$wwwdir = '@www_dir@/SemanticScuttle/';
|
||||||
}
|
}
|
||||||
|
require_once dirname(__FILE__) . '/Environment.php';
|
||||||
|
require_once dirname(__FILE__) . '/Config.php';
|
||||||
|
|
||||||
if (!file_exists($datadir . '/config.php')) {
|
$cfg = new SemanticScuttle_Config();
|
||||||
|
list($configfile, $defaultfile) = $cfg->findFiles();
|
||||||
|
if ($defaultfile === null) {
|
||||||
|
header('HTTP/1.0 500 Internal Server Error');
|
||||||
|
die(
|
||||||
|
'No default configuration file config.default.php found.'
|
||||||
|
. ' This is really, really strange'
|
||||||
|
. "\n"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if ($configfile === null) {
|
||||||
header('HTTP/1.0 500 Internal Server Error');
|
header('HTTP/1.0 500 Internal Server Error');
|
||||||
die(
|
die(
|
||||||
'Please copy "config.php.dist" to "config.php" in data/ folder.'
|
'Please copy "config.php.dist" to "config.php" in data/ folder.'
|
||||||
|
@ -39,8 +51,8 @@ set_include_path(
|
||||||
);
|
);
|
||||||
|
|
||||||
// 1 // First requirements part (before debug management)
|
// 1 // First requirements part (before debug management)
|
||||||
require_once $datadir . '/config.default.php';
|
require_once $defaultfile;
|
||||||
require_once $datadir . '/config.php';
|
require_once $configfile;
|
||||||
|
|
||||||
if (isset($_GET['unittestMode']) && $_GET['unittestMode'] == 1
|
if (isset($_GET['unittestMode']) && $_GET['unittestMode'] == 1
|
||||||
) {
|
) {
|
||||||
|
|
|
@ -46,6 +46,7 @@ class AllTests extends PHPUnit_Framework_TestSuite
|
||||||
$suite->addTestFile($tdir . '/VoteTest.php');
|
$suite->addTestFile($tdir . '/VoteTest.php');
|
||||||
$suite->addTestFile($tdir . '/UserTest.php');
|
$suite->addTestFile($tdir . '/UserTest.php');
|
||||||
$suite->addTestFile($tdir . '/Api/ExportCsvTest.php');
|
$suite->addTestFile($tdir . '/Api/ExportCsvTest.php');
|
||||||
|
$suite->addTestFile($tdir . '/Api/OpenSearchTest.php');
|
||||||
$suite->addTestFile($tdir . '/Api/PostsAddTest.php');
|
$suite->addTestFile($tdir . '/Api/PostsAddTest.php');
|
||||||
$suite->addTestFile($tdir . '/Api/PostsDeleteTest.php');
|
$suite->addTestFile($tdir . '/Api/PostsDeleteTest.php');
|
||||||
$suite->addTestFile($tdir . '/Api/PostsUpdateTest.php');
|
$suite->addTestFile($tdir . '/Api/PostsUpdateTest.php');
|
||||||
|
|
|
@ -108,7 +108,7 @@ TXT;
|
||||||
|
|
||||||
$this->assertEquals($bmUrl, $bm['bAddress']);
|
$this->assertEquals($bmUrl, $bm['bAddress']);
|
||||||
$this->assertEquals($bmTitle, $bm['bTitle']);
|
$this->assertEquals($bmTitle, $bm['bTitle']);
|
||||||
$this->assertEquals($bmDescription, $bm['bDescription']);
|
$this->assertEquals($bmDescription, stripslashes($bm['bDescription']));
|
||||||
$this->assertEquals($bmTags, $bm['tags']);
|
$this->assertEquals($bmTags, $bm['tags']);
|
||||||
$this->assertEquals(
|
$this->assertEquals(
|
||||||
gmdate('Y-m-d H:i:s', strtotime($bmDatetime)),
|
gmdate('Y-m-d H:i:s', strtotime($bmDatetime)),
|
||||||
|
@ -170,7 +170,7 @@ TXT;
|
||||||
|
|
||||||
$this->assertEquals($bmUrl, $bm['bAddress']);
|
$this->assertEquals($bmUrl, $bm['bAddress']);
|
||||||
$this->assertEquals($bmTitle, $bm['bTitle']);
|
$this->assertEquals($bmTitle, $bm['bTitle']);
|
||||||
$this->assertEquals($bmDescription, $bm['bDescription']);
|
$this->assertEquals($bmDescription, stripslashes($bm['bDescription']));
|
||||||
$this->assertEquals($bmTags, $bm['tags']);
|
$this->assertEquals($bmTags, $bm['tags']);
|
||||||
$this->assertEquals(
|
$this->assertEquals(
|
||||||
gmdate('Y-m-d H:i:s', strtotime($bmDatetime)),
|
gmdate('Y-m-d H:i:s', strtotime($bmDatetime)),
|
||||||
|
|
|
@ -282,10 +282,10 @@ class Bookmark2TagTest extends TestBase
|
||||||
public function testGetPopularTagsDays()
|
public function testGetPopularTagsDays()
|
||||||
{
|
{
|
||||||
$user = $this->addUser();
|
$user = $this->addUser();
|
||||||
$this->addTagBookmark($user, array('one', 'two'), 'today');
|
$this->addTagBookmark($user, array('one', 'two'), 'now');
|
||||||
$this->addTagBookmark($user, array('one', 'thr'), 'today');
|
$this->addTagBookmark($user, array('one', 'thr'), 'now');
|
||||||
$this->addTagBookmark($user, array('one', 'two'), '-1 day 1 hour');
|
$this->addTagBookmark($user, array('one', 'two'), '-1 day -1 hour');
|
||||||
$this->addTagBookmark($user, array('one', 'thr'), '-3 days 1 hour');
|
$this->addTagBookmark($user, array('one', 'thr'), '-3 days -1 hour');
|
||||||
|
|
||||||
$arTags = $this->b2ts->getPopularTags(null, 10, null, 1);
|
$arTags = $this->b2ts->getPopularTags(null, 10, null, 1);
|
||||||
$this->assertInternalType('array', $arTags);
|
$this->assertInternalType('array', $arTags);
|
||||||
|
|
|
@ -1330,5 +1330,51 @@ class BookmarkTest extends TestBase
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test private bookmarks
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function testPrivateBookmarks()
|
||||||
|
{
|
||||||
|
$uid = $this->addUser();
|
||||||
|
/* create private bookmark */
|
||||||
|
$this->bs->addBookmark(
|
||||||
|
'http://test', 'test', 'desc', 'note',
|
||||||
|
2,//private
|
||||||
|
array(), null, null, false, false, $uid
|
||||||
|
);
|
||||||
|
/* create public bookmark */
|
||||||
|
$this->bs->addBookmark(
|
||||||
|
'http://example.org', 'title', 'desc', 'priv',
|
||||||
|
0,//public
|
||||||
|
array(), null, null, false, false, $uid
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals(1, $this->bs->countBookmarks($uid, 'public'));
|
||||||
|
$this->assertEquals(1, $this->bs->countBookmarks($uid, 'private'));
|
||||||
|
$this->assertEquals(0, $this->bs->countBookmarks($uid, 'shared'));
|
||||||
|
$this->assertEquals(2, $this->bs->countBookmarks($uid, 'all'));
|
||||||
|
|
||||||
|
$this->us->setCurrentUserId($uid);
|
||||||
|
$bookmarks = $this->bs->getBookmarks();
|
||||||
|
// first record should be private bookmark
|
||||||
|
$b0 = $bookmarks['bookmarks'][0];
|
||||||
|
$this->assertEquals('test', $b0['bTitle']);
|
||||||
|
// second record should be public bookmark
|
||||||
|
$b0 = $bookmarks['bookmarks'][1];
|
||||||
|
$this->assertEquals('title', $b0['bTitle']);
|
||||||
|
|
||||||
|
// test non authenticated query
|
||||||
|
$this->us->setCurrentUserId(null);
|
||||||
|
$bookmarks = $this->bs->getBookmarks();
|
||||||
|
// should only result in one link - public
|
||||||
|
$b2 = $bookmarks['bookmarks'][0];
|
||||||
|
$this->assertEquals('title', $b2['bTitle']);
|
||||||
|
// there should be no second record
|
||||||
|
$this->assertEquals(1,count($bookmarks['bookmarks']));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
|
206
tests/SemanticScuttle/ConfigTest.php
Normal file
206
tests/SemanticScuttle/ConfigTest.php
Normal file
|
@ -0,0 +1,206 @@
|
||||||
|
<?php
|
||||||
|
//that's PEAR's Stream_Var package
|
||||||
|
require_once 'Stream/Var.php';
|
||||||
|
|
||||||
|
class SemanticScuttle_ConfigTest_StreamVar extends Stream_Var {
|
||||||
|
public function url_stat($path, $flags)
|
||||||
|
{
|
||||||
|
$url = parse_url($path);
|
||||||
|
|
||||||
|
$scope = $url['host'];
|
||||||
|
if (isset($url['path'])) {
|
||||||
|
$varpath = substr($url['path'], 1);
|
||||||
|
} else {
|
||||||
|
$varpath = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$this->_setPointer($scope, $varpath)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent::url_stat($path, $flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SemanticScuttle_ConfigTest extends PHPUnit_Framework_TestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Configuration object to test
|
||||||
|
*/
|
||||||
|
protected $cfg;
|
||||||
|
|
||||||
|
|
||||||
|
public function setUpWrapper()
|
||||||
|
{
|
||||||
|
if (!in_array('unittest', stream_get_wrappers())) {
|
||||||
|
stream_wrapper_register(
|
||||||
|
'unittest', 'SemanticScuttle_ConfigTest_StreamVar'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->cfg = $this->getMock(
|
||||||
|
'SemanticScuttle_Config',
|
||||||
|
array('getDataDir')
|
||||||
|
);
|
||||||
|
$this->cfg->expects($this->once())
|
||||||
|
->method('getDataDir')
|
||||||
|
->will($this->returnValue('/data-dir/'));
|
||||||
|
|
||||||
|
$this->cfg->filePrefix = 'unittest://GLOBALS/unittest-dir';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public function testFindLocalData()
|
||||||
|
{
|
||||||
|
$this->setUpWrapper();
|
||||||
|
$GLOBALS['unittest-dir']['data-dir'] = array(
|
||||||
|
'config.php' => 'content',
|
||||||
|
'config.default.php' => 'content'
|
||||||
|
);
|
||||||
|
$this->assertEquals(
|
||||||
|
array(
|
||||||
|
'/data-dir/config.php',
|
||||||
|
'/data-dir/config.default.php'
|
||||||
|
),
|
||||||
|
$this->cfg->findFiles()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testFindHostPreferredOverNonHostConfig()
|
||||||
|
{
|
||||||
|
$this->setUpWrapper();
|
||||||
|
$_SERVER['HTTP_HOST'] = 'foo.example.org';
|
||||||
|
|
||||||
|
$GLOBALS['unittest-dir']['data-dir'] = array(
|
||||||
|
'config.php' => 'content',
|
||||||
|
'config.foo.example.org.php' => 'content',
|
||||||
|
'config.default.php' => 'content'
|
||||||
|
);
|
||||||
|
$this->assertEquals(
|
||||||
|
array(
|
||||||
|
'/data-dir/config.foo.example.org.php',
|
||||||
|
'/data-dir/config.default.php'
|
||||||
|
),
|
||||||
|
$this->cfg->findFiles()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testFindEtcHostPreferredOverLocalConfigPhp()
|
||||||
|
{
|
||||||
|
$this->setUpWrapper();
|
||||||
|
$_SERVER['HTTP_HOST'] = 'foo.example.org';
|
||||||
|
|
||||||
|
$GLOBALS['unittest-dir'] = array(
|
||||||
|
'etc' => array(
|
||||||
|
'semanticscuttle' => array(
|
||||||
|
'config.foo.example.org.php' => 'content',
|
||||||
|
)
|
||||||
|
),
|
||||||
|
'data-dir' => array(
|
||||||
|
'config.php' => 'content',
|
||||||
|
'config.default.php' => 'content'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
array(
|
||||||
|
'/etc/semanticscuttle/config.foo.example.org.php',
|
||||||
|
'/data-dir/config.default.php'
|
||||||
|
),
|
||||||
|
$this->cfg->findFiles()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testFindEtcConfig()
|
||||||
|
{
|
||||||
|
$this->setUpWrapper();
|
||||||
|
$GLOBALS['unittest-dir'] = array(
|
||||||
|
'etc' => array(
|
||||||
|
'semanticscuttle' => array(
|
||||||
|
'config.php' => 'content'
|
||||||
|
)
|
||||||
|
),
|
||||||
|
'data-dir' => array(
|
||||||
|
'config.default.php' => 'content'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$this->assertEquals(
|
||||||
|
array(
|
||||||
|
'/etc/semanticscuttle/config.php',
|
||||||
|
'/data-dir/config.default.php'
|
||||||
|
),
|
||||||
|
$this->cfg->findFiles()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testFindEtcDefaultConfig()
|
||||||
|
{
|
||||||
|
$this->setUpWrapper();
|
||||||
|
$GLOBALS['unittest-dir'] = array(
|
||||||
|
'etc' => array(
|
||||||
|
'semanticscuttle' => array(
|
||||||
|
'config.php' => 'content',
|
||||||
|
'config.default.php' => 'content'
|
||||||
|
)
|
||||||
|
),
|
||||||
|
);
|
||||||
|
$this->assertEquals(
|
||||||
|
array(
|
||||||
|
'/etc/semanticscuttle/config.php',
|
||||||
|
'/etc/semanticscuttle/config.default.php'
|
||||||
|
),
|
||||||
|
$this->cfg->findFiles()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testFindLocalDefaultPreferredOverEtcDefault()
|
||||||
|
{
|
||||||
|
$this->setUpWrapper();
|
||||||
|
$GLOBALS['unittest-dir'] = array(
|
||||||
|
'etc' => array(
|
||||||
|
'semanticscuttle' => array(
|
||||||
|
'config.php' => 'content',
|
||||||
|
'config.default.php' => 'content'
|
||||||
|
)
|
||||||
|
),
|
||||||
|
'data-dir' => array(
|
||||||
|
'config.php' => 'content',
|
||||||
|
'config.default.php' => 'content'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$this->assertEquals(
|
||||||
|
array(
|
||||||
|
'/data-dir/config.php',
|
||||||
|
'/data-dir/config.default.php'
|
||||||
|
),
|
||||||
|
$this->cfg->findFiles()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testFindSameDirDefaultPreferred()
|
||||||
|
{
|
||||||
|
$this->setUpWrapper();
|
||||||
|
$GLOBALS['unittest-dir'] = array(
|
||||||
|
'etc' => array(
|
||||||
|
'semanticscuttle' => array(
|
||||||
|
'config.php' => 'content',
|
||||||
|
'config.default.php' => 'content'
|
||||||
|
)
|
||||||
|
),
|
||||||
|
'data-dir' => array(
|
||||||
|
'config.default.php' => 'content'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$this->assertEquals(
|
||||||
|
array(
|
||||||
|
'/etc/semanticscuttle/config.php',
|
||||||
|
'/etc/semanticscuttle/config.default.php'
|
||||||
|
),
|
||||||
|
$this->cfg->findFiles()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
95
tests/SemanticScuttle/EnvironmentTest.php
Normal file
95
tests/SemanticScuttle/EnvironmentTest.php
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class SemanticScuttle_EnvironmentTest extends PHPUnit_Framework_TestCase
|
||||||
|
{
|
||||||
|
public function testServerPathInfoModPhp()
|
||||||
|
{
|
||||||
|
$_SERVER = array(
|
||||||
|
'HTTP_USER_AGENT' => 'Opera/9.80 (X11; Linux x86_64; U; de) Presto/2.9.168 Version/11.50',
|
||||||
|
'HTTP_HOST' => 'bm-cgi.bogo',
|
||||||
|
'HTTP_ACCEPT' => 'text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/webp, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1',
|
||||||
|
'HTTP_ACCEPT_LANGUAGE' => 'de-DE,de;q=0.9,en;q=0.8',
|
||||||
|
'HTTP_ACCEPT_ENCODING' => 'gzip, deflate',
|
||||||
|
'HTTP_COOKIE' => 'PHPSESSID=ga446jhs0e09hkt60u9bsmp0n0',
|
||||||
|
'HTTP_CACHE_CONTROL' => 'no-cache',
|
||||||
|
'HTTP_CONNECTION' => 'Keep-Alive',
|
||||||
|
'PATH' => '/usr/local/bin:/usr/bin:/bin',
|
||||||
|
'SERVER_SIGNATURE' => '<address>Apache/2.2.17 (Ubuntu) Server at bm-cgi.bogo Port 80</address>',
|
||||||
|
'SERVER_SOFTWARE' => 'Apache/2.2.17 (Ubuntu)',
|
||||||
|
'SERVER_NAME' => 'bm-cgi.bogo',
|
||||||
|
'SERVER_ADDR' => '127.0.0.1',
|
||||||
|
'SERVER_PORT' => '80',
|
||||||
|
'REMOTE_ADDR' => '127.0.0.1',
|
||||||
|
'DOCUMENT_ROOT' => '/etc/apache2/htdocs',
|
||||||
|
'SERVER_ADMIN' => '[no address given]',
|
||||||
|
'SCRIPT_FILENAME' => '/home/cweiske/Dev/html/hosts/bm-cgi.bogo/profile.php',
|
||||||
|
'REMOTE_PORT' => '45349',
|
||||||
|
'GATEWAY_INTERFACE' => 'CGI/1.1',
|
||||||
|
'SERVER_PROTOCOL' => 'HTTP/1.1',
|
||||||
|
'REQUEST_METHOD' => 'GET',
|
||||||
|
'QUERY_STRING' => '',
|
||||||
|
'REQUEST_URI' => '/profile.php/dummy',
|
||||||
|
'SCRIPT_NAME' => '/profile.php',
|
||||||
|
'PATH_INFO' => '/dummy',
|
||||||
|
'PATH_TRANSLATED' => '/home/cweiske/Dev/html/hosts/bm-cgi.bogo/dummy',
|
||||||
|
'PHP_SELF' => '/profile.php/dummy',
|
||||||
|
'REQUEST_TIME' => 1311422546,
|
||||||
|
);
|
||||||
|
$this->assertEquals(
|
||||||
|
'/dummy', SemanticScuttle_Environment::getServerPathInfo()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function testServerPathInfoFastCgi()
|
||||||
|
{
|
||||||
|
$_SERVER = array(
|
||||||
|
'PHP_FCGI_MAX_REQUESTS' => '5000',
|
||||||
|
'PHPRC' => '/etc/php5/cgi/5.3.6/',
|
||||||
|
'PHP_FCGI_CHILDREN' => '3',
|
||||||
|
'PWD' => '/var/www/cgi-bin',
|
||||||
|
'FCGI_ROLE' => 'RESPONDER',
|
||||||
|
'REDIRECT_HANDLER' => 'php-cgi',
|
||||||
|
'REDIRECT_STATUS' => '200',
|
||||||
|
'HTTP_USER_AGENT' => 'Opera/9.80 (X11; Linux x86_64; U; de) Presto/2.9.168 Version/11.50',
|
||||||
|
'HTTP_HOST' => 'bm-cgi.bogo',
|
||||||
|
'HTTP_ACCEPT' => 'text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/webp, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1',
|
||||||
|
'HTTP_ACCEPT_LANGUAGE' => 'de-DE,de;q=0.9,en;q=0.8',
|
||||||
|
'HTTP_ACCEPT_ENCODING' => 'gzip, deflate',
|
||||||
|
'HTTP_COOKIE' => 'PHPSESSID=ga446jhs0e09hkt60u9bsmp0n0',
|
||||||
|
'HTTP_CONNECTION' => 'Keep-Alive',
|
||||||
|
'PATH' => '/usr/local/bin:/usr/bin:/bin',
|
||||||
|
'SERVER_SIGNATURE' => '<address>Apache/2.2.17 (Ubuntu) Server at bm-cgi.bogo Port 80</address>',
|
||||||
|
'SERVER_SOFTWARE' => 'Apache/2.2.17 (Ubuntu)',
|
||||||
|
'SERVER_NAME' => 'bm-cgi.bogo',
|
||||||
|
'SERVER_ADDR' => '127.0.0.1',
|
||||||
|
'SERVER_PORT' => '80',
|
||||||
|
'REMOTE_ADDR' => '127.0.0.1',
|
||||||
|
'DOCUMENT_ROOT' => '/etc/apache2/htdocs',
|
||||||
|
'SERVER_ADMIN' => '[no address given]',
|
||||||
|
'SCRIPT_FILENAME' => '/home/cweiske/Dev/html/hosts/bm-cgi.bogo/profile.php',
|
||||||
|
'REMOTE_PORT' => '45342',
|
||||||
|
'REDIRECT_URL' => '/profile.php/dummy',
|
||||||
|
'GATEWAY_INTERFACE' => 'CGI/1.1',
|
||||||
|
'SERVER_PROTOCOL' => 'HTTP/1.1',
|
||||||
|
'REQUEST_METHOD' => 'GET',
|
||||||
|
'QUERY_STRING' => '',
|
||||||
|
'REQUEST_URI' => '/profile.php/dummy',
|
||||||
|
'SCRIPT_NAME' => '/profile.php',
|
||||||
|
'PATH_INFO' => '/dummy',
|
||||||
|
'PATH_TRANSLATED' => '/etc/apache2/htdocs/dummy',
|
||||||
|
'ORIG_PATH_INFO' => '/profile.php/dummy',
|
||||||
|
'ORIG_SCRIPT_NAME' => '/cgi-bin-php/php-cgi-5.3.6',
|
||||||
|
'ORIG_SCRIPT_FILENAME' => '/var/www/cgi-bin/php-cgi-5.3.6',
|
||||||
|
'ORIG_PATH_TRANSLATED' => '/home/cweiske/Dev/html/hosts/bm-cgi.bogo/profile.php/dummy',
|
||||||
|
'PHP_SELF' => '/profile.php/dummy',
|
||||||
|
'REQUEST_TIME' => 1311422521,
|
||||||
|
);
|
||||||
|
$this->assertEquals(
|
||||||
|
'/dummy', SemanticScuttle_Environment::getServerPathInfo()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
|
@ -332,6 +332,7 @@ class Tag2TagTest extends TestBase
|
||||||
$this->assertSame('B3', $results['bookmarks'][0]['bTitle']);
|
$this->assertSame('B3', $results['bookmarks'][0]['bTitle']);
|
||||||
|
|
||||||
$results = $bs->getBookmarks(0, NULL, 1, 'aa+ee');
|
$results = $bs->getBookmarks(0, NULL, 1, 'aa+ee');
|
||||||
|
|
||||||
$this->assertSame(1, intval($results['total']));
|
$this->assertSame(1, intval($results['total']));
|
||||||
$this->assertSame('B2', $results['bookmarks'][0]['bTitle']);
|
$this->assertSame('B2', $results['bookmarks'][0]['bTitle']);
|
||||||
|
|
||||||
|
|
|
@ -76,16 +76,18 @@ class TestBase extends PHPUnit_Framework_TestCase
|
||||||
/**
|
/**
|
||||||
* Creates a new user in the database.
|
* Creates a new user in the database.
|
||||||
*
|
*
|
||||||
* @param string $username Username
|
* @param string $username Username, may be null
|
||||||
* @param string $password Password
|
* @param string $password Password, may be null
|
||||||
|
* @param mixed $privateKey String private key or boolean true to generate one
|
||||||
*
|
*
|
||||||
* @return integer ID of user
|
* @return integer ID of user
|
||||||
*
|
*
|
||||||
* @uses addUserData()
|
* @uses addUserData()
|
||||||
*/
|
*/
|
||||||
protected function addUser($username = null, $password = null)
|
protected function addUser(
|
||||||
{
|
$username = null, $password = null, $privateKey = null
|
||||||
return reset($this->addUserData($username, $password));
|
) {
|
||||||
|
return reset($this->addUserData($username, $password, $privateKey));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -93,13 +95,15 @@ class TestBase extends PHPUnit_Framework_TestCase
|
||||||
/**
|
/**
|
||||||
* Creates a new user in the database and returns id, username and password.
|
* Creates a new user in the database and returns id, username and password.
|
||||||
*
|
*
|
||||||
* @param string $username Username
|
* @param string $username Username, may be null
|
||||||
* @param string $password Password
|
* @param string $password Password, may be null
|
||||||
|
* @param mixed $privateKey String private key or boolean true to generate one
|
||||||
*
|
*
|
||||||
* @return array ID of user, Name of user, password of user
|
* @return array ID of user, Name of user, password of user, privateKey
|
||||||
*/
|
*/
|
||||||
protected function addUserData($username = null, $password = null)
|
protected function addUserData(
|
||||||
{
|
$username = null, $password = null, $privateKey = null
|
||||||
|
) {
|
||||||
$us = SemanticScuttle_Service_Factory::get('User');
|
$us = SemanticScuttle_Service_Factory::get('User');
|
||||||
$rand = rand();
|
$rand = rand();
|
||||||
|
|
||||||
|
@ -109,13 +113,17 @@ class TestBase extends PHPUnit_Framework_TestCase
|
||||||
if ($password === null) {
|
if ($password === null) {
|
||||||
$password = $rand;
|
$password = $rand;
|
||||||
}
|
}
|
||||||
|
if ($privateKey === true) {
|
||||||
|
$privateKey = $this->us->getNewPrivateKey();
|
||||||
|
}
|
||||||
|
|
||||||
$uid = $us->addUser(
|
$uid = $us->addUser(
|
||||||
$username,
|
$username,
|
||||||
$password,
|
$password,
|
||||||
'unittest-' . $rand . '@example.org'
|
'unittest-' . $rand . '@example.org',
|
||||||
|
$privateKey
|
||||||
);
|
);
|
||||||
return array($uid, $username, $password);
|
return array($uid, $username, $password, $privateKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,20 @@ require_once 'HTTP/Request2.php';
|
||||||
*/
|
*/
|
||||||
class TestBaseApi extends TestBase
|
class TestBaseApi extends TestBase
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Created from the configured host and the $urlPart.
|
||||||
|
* Should be used as base for all generated URLs
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
protected $url;
|
protected $url;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Part of the URL behind the configured host.
|
||||||
|
* Needs to be overwritten in each derived test case class.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
protected $urlPart = null;
|
protected $urlPart = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -164,23 +177,25 @@ class TestBaseApi extends TestBase
|
||||||
*
|
*
|
||||||
* Useful for testing HTML pages or ajax URLs.
|
* Useful for testing HTML pages or ajax URLs.
|
||||||
*
|
*
|
||||||
* @param string $urlSuffix Suffix for the URL
|
* @param string $urlSuffix Suffix for the URL
|
||||||
* @param mixed $auth If user authentication is needed (true/false)
|
* @param mixed $auth If user authentication is needed (true/false)
|
||||||
* or array with username and password
|
* or array with username and password
|
||||||
|
* @param boolean $privateKey True if to add user with private key
|
||||||
*
|
*
|
||||||
* @return array(HTTP_Request2, integer) HTTP request object and user id
|
* @return array(HTTP_Request2, integer) HTTP request object and user id
|
||||||
*
|
*
|
||||||
* @uses getRequest()
|
* @uses getRequest()
|
||||||
*/
|
*/
|
||||||
protected function getLoggedInRequest($urlSuffix = null, $auth = true)
|
protected function getLoggedInRequest(
|
||||||
{
|
$urlSuffix = null, $auth = true, $privateKey = null
|
||||||
|
) {
|
||||||
if (is_array($auth)) {
|
if (is_array($auth)) {
|
||||||
list($username, $password) = $auth;
|
list($username, $password) = $auth;
|
||||||
} else {
|
} else {
|
||||||
$username = 'testuser';
|
$username = 'testuser';
|
||||||
$password = 'testpassword';
|
$password = 'testpassword';
|
||||||
}
|
}
|
||||||
$uid = $this->addUser($username, $password);
|
$uid = $this->addUser($username, $password, $privateKey);
|
||||||
|
|
||||||
$req = new HTTP_Request2(
|
$req = new HTTP_Request2(
|
||||||
$GLOBALS['unittestUrl'] . '/login.php?unittestMode=1',
|
$GLOBALS['unittestUrl'] . '/login.php?unittestMode=1',
|
||||||
|
@ -234,7 +249,7 @@ class TestBaseApi extends TestBase
|
||||||
*/
|
*/
|
||||||
protected function setUnittestConfig($arConfig)
|
protected function setUnittestConfig($arConfig)
|
||||||
{
|
{
|
||||||
$str = '<' . "?php\r\n";
|
$str = '<' . "?php\n";
|
||||||
foreach ($arConfig as $name => $value) {
|
foreach ($arConfig as $name => $value) {
|
||||||
$str .= '$' . $name . ' = '
|
$str .= '$' . $name . ' = '
|
||||||
. var_export($value, true) . ";\n";
|
. var_export($value, true) . ";\n";
|
||||||
|
|
|
@ -34,6 +34,157 @@ class UserTest extends TestBase
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers SemanticScuttle_Service_User::addUser
|
||||||
|
*/
|
||||||
|
public function testAddUserPrivateKey()
|
||||||
|
{
|
||||||
|
$name = substr(md5(uniqid()), 0, 6);
|
||||||
|
$pkey = 'my-privateKey';
|
||||||
|
$id = $this->us->addUser(
|
||||||
|
$name, uniqid(), 'foo@example.org', $pkey
|
||||||
|
);
|
||||||
|
$this->assertNotEquals(false, $id);
|
||||||
|
$this->assertInternalType('integer', $id);
|
||||||
|
|
||||||
|
$arUser = $this->us->getUserByPrivateKey($pkey);
|
||||||
|
$this->assertNotEquals(false, $arUser, 'user not found by private key');
|
||||||
|
$this->assertEquals($id, $arUser['uId'], 'wrong user loaded');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers SemanticScuttle_Service_User::updateUser
|
||||||
|
*/
|
||||||
|
public function testUpdateUserFalseWhenIdNotNumeric()
|
||||||
|
{
|
||||||
|
$this->assertFalse(
|
||||||
|
$this->us->updateUser('foo', null, null, null, null, null)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers SemanticScuttle_Service_User::updateUser
|
||||||
|
*/
|
||||||
|
public function testUpdateUserPrivateKeyNewKeyEnabled()
|
||||||
|
{
|
||||||
|
$pkey = 'testUpdateUserPrivateKeyNewKey12';
|
||||||
|
$uid = $this->addUser();
|
||||||
|
|
||||||
|
$this->assertTrue(
|
||||||
|
$this->us->updateUser(
|
||||||
|
$uid, 'password', 'name', 'test@example.org', '', '',
|
||||||
|
$pkey, true
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$arUser = $this->us->getUser($uid);
|
||||||
|
$this->assertInternalType('array', $arUser);
|
||||||
|
$this->assertEquals($pkey, $arUser['privateKey']);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers SemanticScuttle_Service_User::updateUser
|
||||||
|
*/
|
||||||
|
public function testUpdateUserPrivateKeyNewKeyDisabled()
|
||||||
|
{
|
||||||
|
$pkey = 'testUpdateUserPrivateKeyNewKeyDi';
|
||||||
|
$uid = $this->addUser();
|
||||||
|
|
||||||
|
$this->assertTrue(
|
||||||
|
$this->us->updateUser(
|
||||||
|
$uid, 'password', 'name', 'test@example.org', '', '',
|
||||||
|
$pkey, false
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$arUser = $this->us->getUser($uid);
|
||||||
|
$this->assertInternalType('array', $arUser);
|
||||||
|
$this->assertEquals(
|
||||||
|
'-' . $pkey, $arUser['privateKey'],
|
||||||
|
'private key did not get disabled'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Passing an empty string / NULL as key but enabling it
|
||||||
|
* should automatically create a new key.
|
||||||
|
*
|
||||||
|
* @covers SemanticScuttle_Service_User::updateUser
|
||||||
|
*/
|
||||||
|
public function testUpdateUserPrivateKeyNoKeyEnabled()
|
||||||
|
{
|
||||||
|
$pkey = 'testUpdateUserPrivateKeyNoKeyEna';
|
||||||
|
$uid = $this->addUser();
|
||||||
|
|
||||||
|
$this->assertTrue(
|
||||||
|
$this->us->updateUser(
|
||||||
|
$uid, 'password', 'name', 'test@example.org', '', '',
|
||||||
|
null, true
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$arUser = $this->us->getUser($uid);
|
||||||
|
$this->assertInternalType('array', $arUser);
|
||||||
|
$this->assertNotEquals(
|
||||||
|
'', $arUser['privateKey'], 'private key was not created'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Passing an empty string / NULL as key and disabling it
|
||||||
|
* should keep no key
|
||||||
|
*
|
||||||
|
* @covers SemanticScuttle_Service_User::updateUser
|
||||||
|
*/
|
||||||
|
public function testUpdateUserPrivateKeyNoKeyDisabled()
|
||||||
|
{
|
||||||
|
$pkey = 'testUpdateUserPrivateKeyNoKeyDis';
|
||||||
|
$uid = $this->addUser();
|
||||||
|
|
||||||
|
$this->assertTrue(
|
||||||
|
$this->us->updateUser(
|
||||||
|
$uid, 'password', 'name', 'test@example.org', '', '',
|
||||||
|
null, false
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$arUser = $this->us->getUser($uid);
|
||||||
|
$this->assertInternalType('array', $arUser);
|
||||||
|
$this->assertEquals(
|
||||||
|
'', $arUser['privateKey'], 'private key was set'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Passing an empty string / NULL as key and disabling it
|
||||||
|
* should keep no key
|
||||||
|
*
|
||||||
|
* @covers SemanticScuttle_Service_User::updateUser
|
||||||
|
*/
|
||||||
|
public function testUpdateUserPrivateKeyExistingKeyEnabled()
|
||||||
|
{
|
||||||
|
$pkey = '12345678901234567890123456789012';
|
||||||
|
$uid = $this->addUser();
|
||||||
|
|
||||||
|
$this->assertTrue(
|
||||||
|
$this->us->updateUser(
|
||||||
|
$uid, 'password', 'name', 'test@example.org', '', '',
|
||||||
|
'-' . $pkey, true
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$arUser = $this->us->getUser($uid);
|
||||||
|
$this->assertInternalType('array', $arUser);
|
||||||
|
$this->assertEquals(
|
||||||
|
$pkey, $arUser['privateKey'], 'private key was not enabled'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
//FIXME: verify I cannot re-use private key of different user
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test that setting the current user ID is permanent.
|
* Test that setting the current user ID is permanent.
|
||||||
* and that the current user array is the same ID
|
* and that the current user array is the same ID
|
||||||
|
@ -176,5 +327,185 @@ class UserTest extends TestBase
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function testGetUserByPrivateKeyEmptyKey()
|
||||||
|
{
|
||||||
|
$arUser = $this->us->getUserByPrivateKey(null);
|
||||||
|
$this->assertFalse($arUser);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function testGetUserByPrivateKeyInvalid()
|
||||||
|
{
|
||||||
|
$arUser = $this->us->getUserByPrivateKey('foobar');
|
||||||
|
$this->assertFalse($arUser);
|
||||||
|
|
||||||
|
$arUser = $this->us->getUserByPrivateKey('%');
|
||||||
|
$this->assertFalse($arUser);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function testGetUserByPrivateKeyValidKey()
|
||||||
|
{
|
||||||
|
$pkey = $this->us->getNewPrivateKey();
|
||||||
|
$uId = $this->addUser(null, null, $pkey);
|
||||||
|
|
||||||
|
$arUser = $this->us->getUserByPrivateKey($pkey);
|
||||||
|
$this->assertInternalType('array', $arUser);
|
||||||
|
$this->assertArrayHasKey('uId', $arUser);
|
||||||
|
$this->assertArrayHasKey('username', $arUser);
|
||||||
|
|
||||||
|
$this->assertEquals($uId, $arUser['uId']);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers SemanticScuttle_Service_User::privateKeyExists
|
||||||
|
*/
|
||||||
|
public function testPrivateKeyExistsEmpty()
|
||||||
|
{
|
||||||
|
$this->assertFalse($this->us->privateKeyExists(null));
|
||||||
|
$this->assertFalse($this->us->privateKeyExists(''));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers SemanticScuttle_Service_User::privateKeyExists
|
||||||
|
*/
|
||||||
|
public function testPrivateKeyExistsInvalid()
|
||||||
|
{
|
||||||
|
$this->assertFalse($this->us->privateKeyExists('-1'));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers SemanticScuttle_Service_User::privateKeyExists
|
||||||
|
*/
|
||||||
|
public function testPrivateKeyExists()
|
||||||
|
{
|
||||||
|
$randKey = $this->us->getNewPrivateKey();
|
||||||
|
$this->assertFalse($this->us->privateKeyExists($randKey));
|
||||||
|
$uid = $this->addUser(null, null, $randKey);
|
||||||
|
|
||||||
|
$this->us->setCurrentUserId($uid);
|
||||||
|
$this->assertEquals($uid, $this->us->getCurrentUserId());
|
||||||
|
|
||||||
|
$this->assertTrue($this->us->privateKeyExists($randKey));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers SemanticScuttle_Service_User::isPrivateKeyValid
|
||||||
|
*/
|
||||||
|
public function testIsPrivateKeyValid()
|
||||||
|
{
|
||||||
|
$this->assertFalse(
|
||||||
|
$this->us->isPrivateKeyValid(null),
|
||||||
|
'NULL is an invalid private key'
|
||||||
|
);
|
||||||
|
|
||||||
|
$randKey = $this->us->getNewPrivateKey();
|
||||||
|
$this->assertTrue(
|
||||||
|
$this->us->isPrivateKeyValid($randKey),
|
||||||
|
'generated key should be valid'
|
||||||
|
);
|
||||||
|
|
||||||
|
$randKey2 = '-'.$this->us->getNewPrivateKey();
|
||||||
|
$this->assertFalse(
|
||||||
|
$this->us->isPrivateKeyValid($randKey2),
|
||||||
|
'disabled privateKey should return false'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function testLoginPrivateKeyInvalid()
|
||||||
|
{
|
||||||
|
/* normal user with enabled privateKey */
|
||||||
|
$randKey = $this->us->getNewPrivateKey();
|
||||||
|
$uid1 = $this->addUser('testusername', 'passw0rd', $randKey);
|
||||||
|
/* user that has disabled privateKey */
|
||||||
|
$randKey2 = '-'.$this->us->getNewPrivateKey();
|
||||||
|
$uid2 = $this->addUser('seconduser', 'passw0RD', $randKey2);
|
||||||
|
|
||||||
|
/* test invalid private key */
|
||||||
|
$this->assertFalse(
|
||||||
|
$this->us->loginPrivateKey('02848248084082408240824802408248')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function testLoginPrivateKeyValidEnabledKey()
|
||||||
|
{
|
||||||
|
/* normal user with enabled privateKey */
|
||||||
|
$randKey = $this->us->getNewPrivateKey();
|
||||||
|
$uid1 = $this->addUser('testusername', 'passw0rd', $randKey);
|
||||||
|
/* user that has disabled privateKey */
|
||||||
|
$randKey2 = '-'.$this->us->getNewPrivateKey();
|
||||||
|
$uid2 = $this->addUser('seconduser', 'passw0RD', $randKey2);
|
||||||
|
|
||||||
|
|
||||||
|
/* test valid credentials with private key enabled */
|
||||||
|
$this->assertTrue(
|
||||||
|
$this->us->loginPrivateKey($randKey)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function testLoginPrivateKeyInvalidEnabledKey()
|
||||||
|
{
|
||||||
|
/* normal user with enabled privateKey */
|
||||||
|
$randKey = $this->us->getNewPrivateKey();
|
||||||
|
$uid1 = $this->addUser('testusername', 'passw0rd', $randKey);
|
||||||
|
/* user that has disabled privateKey */
|
||||||
|
$randKey2 = '-'.$this->us->getNewPrivateKey();
|
||||||
|
$uid2 = $this->addUser('seconduser', 'passw0RD', $randKey2);
|
||||||
|
|
||||||
|
|
||||||
|
/* test valid credentials with private key enabled but invalid key */
|
||||||
|
$this->assertFalse(
|
||||||
|
$this->us->loginPrivateKey('123')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function testLoginPrivateKeyValidDisabledKey()
|
||||||
|
{
|
||||||
|
/* normal user with enabled privateKey */
|
||||||
|
$randKey = $this->us->getNewPrivateKey();
|
||||||
|
$uid1 = $this->addUser('testusername', 'passw0rd', $randKey);
|
||||||
|
/* user that has disabled privateKey */
|
||||||
|
$randKey2 = '-'.$this->us->getNewPrivateKey();
|
||||||
|
$uid2 = $this->addUser('seconduser', 'passw0RD', $randKey2);
|
||||||
|
|
||||||
|
/* confirm user exists so future fails should be due to randkey */
|
||||||
|
$this->assertTrue(
|
||||||
|
$this->us->login('seconduser', 'passw0RD', false)
|
||||||
|
);
|
||||||
|
|
||||||
|
/* test valid credentials with private key disabled */
|
||||||
|
$this->assertFalse(
|
||||||
|
$this->us->loginPrivateKey($randKey2)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function testLoginPrivateKeyInvalidDisabled()
|
||||||
|
{
|
||||||
|
/* normal user with enabled privateKey */
|
||||||
|
$randKey = $this->us->getNewPrivateKey();
|
||||||
|
$uid1 = $this->addUser('testusername', 'passw0rd', $randKey);
|
||||||
|
/* user that has disabled privateKey */
|
||||||
|
$randKey2 = '-'.$this->us->getNewPrivateKey();
|
||||||
|
$uid2 = $this->addUser('seconduser', 'passw0RD', $randKey2);
|
||||||
|
|
||||||
|
/* test valid credentials with private key disabled and invalid key */
|
||||||
|
$this->assertFalse(
|
||||||
|
$this->us->loginPrivateKey('-1')
|
||||||
|
);
|
||||||
|
$this->assertFalse(
|
||||||
|
$this->us->loginPrivateKey(null)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
?>
|
?>
|
|
@ -4,7 +4,7 @@ require_once 'HTTP/Request2.php';
|
||||||
|
|
||||||
class www_bookmarksTest extends TestBaseApi
|
class www_bookmarksTest extends TestBaseApi
|
||||||
{
|
{
|
||||||
protected $urlPart = 'api/posts/add';
|
protected $urlPart = 'bookmarks.php';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test that the default privacy setting is selected in the Privacy
|
* Test that the default privacy setting is selected in the Privacy
|
||||||
|
@ -16,23 +16,11 @@ class www_bookmarksTest extends TestBaseApi
|
||||||
$this->setUnittestConfig(
|
$this->setUnittestConfig(
|
||||||
array('defaults' => array('privacy' => 2))
|
array('defaults' => array('privacy' => 2))
|
||||||
);
|
);
|
||||||
|
|
||||||
list($req, $uId) = $this->getLoggedInRequest();
|
list($req, $uId) = $this->getLoggedInRequest();
|
||||||
$cookies = $req->getCookieJar();
|
|
||||||
$req->setMethod(HTTP_Request2::METHOD_POST);
|
|
||||||
$req->addPostParameter('url', 'http://www.example.org/testdefaultprivacyposts_bookmarksget');
|
|
||||||
$req->addPostParameter('description', 'Test bookmark 1 for default privacy.');
|
|
||||||
$req->addPostParameter('status', '0');
|
|
||||||
$req->send();
|
|
||||||
|
|
||||||
$bms = $this->bs->getBookmarks(0, null, $uId);
|
|
||||||
$this->assertEquals(1, count($bms['bookmarks']));
|
|
||||||
$user = $this->us->getUser($uId);
|
$user = $this->us->getUser($uId);
|
||||||
$reqUrl = $GLOBALS['unittestUrl'] . 'bookmarks.php/' . $user['username'] . '?action=get' . '&unittestMode=1';
|
|
||||||
|
|
||||||
list($req, $uId) = $this->getAuthRequest('?unittestMode=1');
|
|
||||||
$req->setMethod(HTTP_Request2::METHOD_POST);
|
$req->setMethod(HTTP_Request2::METHOD_POST);
|
||||||
$req->setUrl($reqUrl);
|
$req->setUrl($this->getTestUrl('/' . $user['username'] . '?action=get'));
|
||||||
$req->setCookieJar($cookies);
|
|
||||||
$req->addPostParameter('submitted', '1');
|
$req->addPostParameter('submitted', '1');
|
||||||
$response = $req->send();
|
$response = $req->send();
|
||||||
$response_body = $response->getBody();
|
$response_body = $response->getBody();
|
||||||
|
@ -41,12 +29,15 @@ class www_bookmarksTest extends TestBaseApi
|
||||||
$ns = $x->getDocNamespaces();
|
$ns = $x->getDocNamespaces();
|
||||||
$x->registerXPathNamespace('ns', reset($ns));
|
$x->registerXPathNamespace('ns', reset($ns));
|
||||||
|
|
||||||
$elements = $x->xpath('//ns:select[@name="status"]/ns:option[@selected="selected"]');
|
$elements = $x->xpath(
|
||||||
|
'//ns:select[@name="status"]/ns:option[@selected="selected"]'
|
||||||
|
);
|
||||||
$this->assertEquals(1, count($elements), 'No selected status option found');
|
$this->assertEquals(1, count($elements), 'No selected status option found');
|
||||||
$this->assertEquals(2, (string)$elements[0]['value']);
|
$this->assertEquals(2, (string)$elements[0]['value']);
|
||||||
}//end testDefaultPrivacyBookmarksAddMissingTitleMissingPrivacy
|
}//end testDefaultPrivacyBookmarksAddMissingTitleMissingPrivacy
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test that the default privacy setting is selected in the Privacy
|
* Test that the default privacy setting is selected in the Privacy
|
||||||
* drop-down list when a new bookmark is being created.
|
* drop-down list when a new bookmark is being created.
|
||||||
|
@ -56,13 +47,10 @@ class www_bookmarksTest extends TestBaseApi
|
||||||
$this->setUnittestConfig(
|
$this->setUnittestConfig(
|
||||||
array('defaults' => array('privacy' => 1))
|
array('defaults' => array('privacy' => 1))
|
||||||
);
|
);
|
||||||
list($req, $uId) = $this->getLoggedInRequest('?unittestMode=1');
|
list($req, $uId) = $this->getLoggedInRequest();
|
||||||
|
|
||||||
$user = $this->us->getUser($uId);
|
$user = $this->us->getUser($uId);
|
||||||
$reqUrl = $GLOBALS['unittestUrl'] . 'bookmarks.php/'
|
$req->setUrl($this->getTestUrl('/' . $user['username'] . '?action=add'));
|
||||||
. $user['username'] . '?action=add' . '&unittestMode=1';
|
|
||||||
$req->setUrl($reqUrl);
|
|
||||||
$req->setMethod(HTTP_Request2::METHOD_GET);
|
|
||||||
$response = $req->send();
|
$response = $req->send();
|
||||||
$response_body = $response->getBody();
|
$response_body = $response->getBody();
|
||||||
$this->assertNotEquals('', $response_body, 'Response is empty');
|
$this->assertNotEquals('', $response_body, 'Response is empty');
|
||||||
|
@ -71,10 +59,70 @@ class www_bookmarksTest extends TestBaseApi
|
||||||
$ns = $x->getDocNamespaces();
|
$ns = $x->getDocNamespaces();
|
||||||
$x->registerXPathNamespace('ns', reset($ns));
|
$x->registerXPathNamespace('ns', reset($ns));
|
||||||
|
|
||||||
$elements = $x->xpath('//ns:select[@name="status"]/ns:option[@selected="selected"]');
|
$elements = $x->xpath(
|
||||||
|
'//ns:select[@name="status"]/ns:option[@selected="selected"]'
|
||||||
|
);
|
||||||
$this->assertEquals(1, count($elements), 'No selected status option found');
|
$this->assertEquals(1, count($elements), 'No selected status option found');
|
||||||
$this->assertEquals(1, (string)$elements[0]['value']);
|
$this->assertEquals(1, (string)$elements[0]['value']);
|
||||||
}//end testDefaultPrivacyBookmarksAdd
|
}//end testDefaultPrivacyBookmarksAdd
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test that the private RSS link exists when a user
|
||||||
|
* has a private key and is enabled
|
||||||
|
*/
|
||||||
|
public function testVerifyPrivateRSSLinkExists()
|
||||||
|
{
|
||||||
|
list($req, $uId) = $this->getLoggedInRequest('?unittestMode=1', true, true);
|
||||||
|
|
||||||
|
$user = $this->us->getUser($uId);
|
||||||
|
$req->setUrl($this->getTestUrl('/' . $user['username']));
|
||||||
|
$response = $req->send();
|
||||||
|
$response_body = $response->getBody();
|
||||||
|
$this->assertNotEquals('', $response_body, 'Response is empty');
|
||||||
|
|
||||||
|
$x = simplexml_load_string($response_body);
|
||||||
|
$ns = $x->getDocNamespaces();
|
||||||
|
$x->registerXPathNamespace('ns', reset($ns));
|
||||||
|
|
||||||
|
$elements = $x->xpath(
|
||||||
|
'//ns:link[@rel="alternate" and @type="application/rss+xml"]'
|
||||||
|
);
|
||||||
|
$this->assertEquals(
|
||||||
|
2, count($elements), 'Number of Links in Head not correct'
|
||||||
|
);
|
||||||
|
$this->assertContains('privateKey=', (string)$elements[1]['href']);
|
||||||
|
}//end testVerifyPrivateRSSLinkExists
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test that the private RSS link doesn't exists when a user
|
||||||
|
* does not have a private key or is not enabled
|
||||||
|
*/
|
||||||
|
public function testVerifyPrivateRSSLinkDoesNotExist()
|
||||||
|
{
|
||||||
|
list($req, $uId) = $this->getLoggedInRequest('?unittestMode=1', true);
|
||||||
|
|
||||||
|
$user = $this->us->getUser($uId);
|
||||||
|
$req->setUrl($this->getTestUrl('/' . $user['username']));
|
||||||
|
$response = $req->send();
|
||||||
|
$response_body = $response->getBody();
|
||||||
|
$this->assertNotEquals('', $response_body, 'Response is empty');
|
||||||
|
|
||||||
|
$x = simplexml_load_string($response_body);
|
||||||
|
$ns = $x->getDocNamespaces();
|
||||||
|
$x->registerXPathNamespace('ns', reset($ns));
|
||||||
|
|
||||||
|
$elements = $x->xpath(
|
||||||
|
'//ns:link[@rel="alternate" and @type="application/rss+xml"]'
|
||||||
|
);
|
||||||
|
$this->assertEquals(
|
||||||
|
1, count($elements), 'Number of Links in Head not correct'
|
||||||
|
);
|
||||||
|
$this->assertNotContains('privateKey=', (string)$elements[0]['href']);
|
||||||
|
}//end testVerifyPrivateRSSLinkDoesNotExist
|
||||||
|
|
||||||
}//end class www_bookmarksTest
|
}//end class www_bookmarksTest
|
||||||
?>
|
?>
|
||||||
|
|
58
tests/www/indexTest.php
Normal file
58
tests/www/indexTest.php
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
<?php
|
||||||
|
require_once dirname(__FILE__) . '/../prepare.php';
|
||||||
|
require_once 'HTTP/Request2.php';
|
||||||
|
|
||||||
|
class www_indexTest extends TestBaseApi
|
||||||
|
{
|
||||||
|
protected $urlPart = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test that the private rss feed exists when user is setup
|
||||||
|
* with a private key and is enabled
|
||||||
|
*/
|
||||||
|
public function testVerifyPrivateRSSLinkExists()
|
||||||
|
{
|
||||||
|
list($req, $uId) = $this->getLoggedInRequest('?unittestMode=1', true, true);
|
||||||
|
|
||||||
|
$user = $this->us->getUser($uId);
|
||||||
|
$response = $req->send();
|
||||||
|
$response_body = $response->getBody();
|
||||||
|
|
||||||
|
$this->assertNotEquals('', $response_body, 'Response is empty');
|
||||||
|
|
||||||
|
$x = simplexml_load_string($response_body);
|
||||||
|
$ns = $x->getDocNamespaces();
|
||||||
|
$x->registerXPathNamespace('ns', reset($ns));
|
||||||
|
|
||||||
|
$elements = $x->xpath('//ns:link[@rel="alternate" and @type="application/rss+xml"]');
|
||||||
|
$this->assertEquals(2, count($elements), 'Number of Links in Head not correct');
|
||||||
|
$this->assertContains('privateKey=', (string)$elements[1]['href']);
|
||||||
|
}//end testVerifyPrivateRSSLinkExists
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test that the private RSS link doesn't exists when a user
|
||||||
|
* does not have a private key, or the private key is not enabled
|
||||||
|
*/
|
||||||
|
public function testVerifyPrivateRSSLinkDoesNotExist()
|
||||||
|
{
|
||||||
|
list($req, $uId) = $this->getLoggedInRequest('?unittestMode=1', true);
|
||||||
|
|
||||||
|
$user = $this->us->getUser($uId);
|
||||||
|
$response = $req->send();
|
||||||
|
$response_body = $response->getBody();
|
||||||
|
$this->assertNotEquals('', $response_body, 'Response is empty');
|
||||||
|
|
||||||
|
$x = simplexml_load_string($response_body);
|
||||||
|
$ns = $x->getDocNamespaces();
|
||||||
|
$x->registerXPathNamespace('ns', reset($ns));
|
||||||
|
|
||||||
|
$elements = $x->xpath('//ns:link[@rel="alternate" and @type="application/rss+xml"]');
|
||||||
|
$this->assertEquals(1, count($elements), 'Number of Links in Head not correct');
|
||||||
|
$this->assertNotContains('privateKey=', (string)$elements[0]['href']);
|
||||||
|
}//end testVerifyPrivateRSSLinkDoesNotExist
|
||||||
|
|
||||||
|
|
||||||
|
}//end class www_bookmarksTest
|
||||||
|
?>
|
151
tests/www/rssTest.php
Normal file
151
tests/www/rssTest.php
Normal file
|
@ -0,0 +1,151 @@
|
||||||
|
<?php
|
||||||
|
require_once dirname(__FILE__) . '/../prepare.php';
|
||||||
|
require_once 'HTTP/Request2.php';
|
||||||
|
|
||||||
|
class www_rssTest extends TestBaseApi
|
||||||
|
{
|
||||||
|
protected $urlPart = 'rss.php';
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies that the given number of feed items exist in the feed
|
||||||
|
* XML tree.
|
||||||
|
*
|
||||||
|
* @var SimpleXMLElement $simpleXml RSS feed root element
|
||||||
|
* @var integer $nCount Number of expected feed items
|
||||||
|
* @var string $msg Error message
|
||||||
|
*/
|
||||||
|
protected function assertItemCount(
|
||||||
|
SimpleXMLElement $simpleXml, $nCount, $msg = null
|
||||||
|
) {
|
||||||
|
$this->assertEquals($nCount, count($simpleXml->channel->item), $msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A private bookmark should not show up in the global rss feed if the
|
||||||
|
* user is not logged in nor passes the private key
|
||||||
|
*/
|
||||||
|
public function testAllPrivateBookmarkNotLoggedIn()
|
||||||
|
{
|
||||||
|
list($uId, $username) = $this->addUserData();
|
||||||
|
$this->addBookmark(
|
||||||
|
$uId, null, SemanticScuttle_Model_Bookmark::SPRIVATE
|
||||||
|
);
|
||||||
|
|
||||||
|
$req = $this->getRequest();
|
||||||
|
$response_body = $req->send()->getBody();
|
||||||
|
|
||||||
|
$rss = simplexml_load_string($response_body);
|
||||||
|
$this->assertItemCount($rss, 0, 'I see a private bookmark');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A private bookmark should not show up in the user's rss feed if the
|
||||||
|
* user is not logged in nor passes the private key
|
||||||
|
*/
|
||||||
|
public function testUserPrivateBookmarkNotLoggedIn()
|
||||||
|
{
|
||||||
|
list($uId, $username) = $this->addUserData();
|
||||||
|
$this->addBookmark(
|
||||||
|
$uId, null, SemanticScuttle_Model_Bookmark::SPRIVATE
|
||||||
|
);
|
||||||
|
|
||||||
|
$req = $this->getRequest('/' . $username);
|
||||||
|
$response_body = $req->send()->getBody();
|
||||||
|
|
||||||
|
$rss = simplexml_load_string($response_body);
|
||||||
|
$this->assertItemCount($rss, 0, 'I see a private bookmark');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test the global feed by passing the private key
|
||||||
|
*/
|
||||||
|
public function testAllPrivateBookmarkWithPrivateKey()
|
||||||
|
{
|
||||||
|
list($uId, $username, $password, $privateKey) = $this->addUserData(
|
||||||
|
null, null, true
|
||||||
|
);
|
||||||
|
$this->addBookmark(
|
||||||
|
$uId, null, SemanticScuttle_Model_Bookmark::SPRIVATE,
|
||||||
|
null, 'private bookmark'
|
||||||
|
);
|
||||||
|
|
||||||
|
$req = $this->getRequest('?privateKey=' . $privateKey);
|
||||||
|
$response_body = $req->send()->getBody();
|
||||||
|
|
||||||
|
$rss = simplexml_load_string($response_body);
|
||||||
|
$this->assertItemCount($rss, 1, 'I miss the private bookmark');
|
||||||
|
$this->assertEquals(
|
||||||
|
'private bookmark', (string)$rss->channel->item[0]->title
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test the user feed by passing the private key
|
||||||
|
*/
|
||||||
|
public function testUserPrivateBookmarkWithPrivateKey()
|
||||||
|
{
|
||||||
|
list($uId, $username, $password, $privateKey) = $this->addUserData(
|
||||||
|
null, null, true
|
||||||
|
);
|
||||||
|
$this->addBookmark(
|
||||||
|
$uId, null, SemanticScuttle_Model_Bookmark::SPRIVATE,
|
||||||
|
null, 'private bookmark'
|
||||||
|
);
|
||||||
|
|
||||||
|
$req = $this->getRequest('/' . $username . '?privateKey=' . $privateKey);
|
||||||
|
$response_body = $req->send()->getBody();
|
||||||
|
|
||||||
|
$rss = simplexml_load_string($response_body);
|
||||||
|
$this->assertItemCount($rss, 1, 'I miss the private bookmark');
|
||||||
|
$this->assertEquals(
|
||||||
|
'private bookmark', (string)$rss->channel->item[0]->title
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify that fetching the feed with a private key
|
||||||
|
* does not keep you logged in
|
||||||
|
*/
|
||||||
|
public function testUserPrivateKeyDoesNotKeepLoggedYouIn()
|
||||||
|
{
|
||||||
|
list($uId, $username, $password, $privateKey) = $this->addUserData(
|
||||||
|
null, null, true
|
||||||
|
);
|
||||||
|
$this->addBookmark(
|
||||||
|
$uId, null, SemanticScuttle_Model_Bookmark::SPRIVATE,
|
||||||
|
null, 'private bookmark'
|
||||||
|
);
|
||||||
|
|
||||||
|
$req = $this->getRequest('/' . $username . '?privateKey=' . $privateKey);
|
||||||
|
$cookies = $req->setCookieJar()->getCookieJar();
|
||||||
|
$response_body = $req->send()->getBody();
|
||||||
|
|
||||||
|
$rss = simplexml_load_string($response_body);
|
||||||
|
$items = $rss->channel->item;
|
||||||
|
|
||||||
|
$this->assertEquals(1, count($items), 'I miss the private bookmark');
|
||||||
|
$this->assertEquals('private bookmark', (string)$items[0]->title);
|
||||||
|
|
||||||
|
//request the feed again, with the same cookies
|
||||||
|
$req = $this->getRequest('/' . $username);
|
||||||
|
$req->setCookieJar($cookies);
|
||||||
|
$response_body = $req->send()->getBody();
|
||||||
|
$rss = simplexml_load_string($response_body);
|
||||||
|
$this->assertItemCount($rss, 0, 'I still see the private bookmark');
|
||||||
|
}
|
||||||
|
|
||||||
|
}//end class www_rssTest
|
||||||
|
?>
|
|
@ -1,4 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
require_once dirname(__FILE__) . '/../prepare.php';
|
||||||
|
require_once 'HTTP/Request2.php';
|
||||||
|
|
||||||
class www_SearchTest extends TestBaseApi
|
class www_SearchTest extends TestBaseApi
|
||||||
{
|
{
|
||||||
|
|
35
www/ajaxGetNewPrivateKey.php
Normal file
35
www/ajaxGetNewPrivateKey.php
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Ajax script to retrieve new Private Key
|
||||||
|
*
|
||||||
|
* PHP version 5.
|
||||||
|
*
|
||||||
|
* @category Bookmarking
|
||||||
|
* @package SemanticScuttle
|
||||||
|
* @author Christian Weiske <cweiske@cweiske.de>
|
||||||
|
* @author Mark Pemberton <mpemberton5@gmail.com>
|
||||||
|
* @license AGPL http://www.gnu.org/licenses/agpl.html
|
||||||
|
* @link http://sourceforge.net/projects/semanticscuttle
|
||||||
|
*/
|
||||||
|
|
||||||
|
header("Last-Modified: ". gmdate("D, d M Y H:i:s") ." GMT");
|
||||||
|
header("Cache-Control: no-cache, must-revalidate");
|
||||||
|
|
||||||
|
$httpContentType = 'text/xml';
|
||||||
|
require_once 'www-header.php';
|
||||||
|
|
||||||
|
$us = SemanticScuttle_Service_Factory::get('User');
|
||||||
|
|
||||||
|
/* Managing all possible inputs */
|
||||||
|
isset($_GET['url']) ? define('GET_URL', $_GET['url']): define('GET_URL', '');
|
||||||
|
|
||||||
|
echo '<?xml version="1.0" encoding="utf-8"?>';
|
||||||
|
?>
|
||||||
|
<response>
|
||||||
|
<method>
|
||||||
|
getNewPrivateKey
|
||||||
|
</method>
|
||||||
|
<result>
|
||||||
|
<?php echo $us->getNewPrivateKey(); ?>
|
||||||
|
</result>
|
||||||
|
</response>
|
|
@ -229,12 +229,14 @@ if ($templatename == 'editbookmark.tpl') {
|
||||||
$tplVars['sidebar_blocks'] = array('watchstatus');
|
$tplVars['sidebar_blocks'] = array('watchstatus');
|
||||||
|
|
||||||
if (!$cat) { //user page without tags
|
if (!$cat) { //user page without tags
|
||||||
|
$rssTitle = "My Bookmarks";
|
||||||
$cat = NULL;
|
$cat = NULL;
|
||||||
$tplVars['currenttag'] = NULL;
|
$tplVars['currenttag'] = NULL;
|
||||||
//$tplVars['sidebar_blocks'][] = 'menu2';
|
//$tplVars['sidebar_blocks'][] = 'menu2';
|
||||||
$tplVars['sidebar_blocks'][] = 'linked';
|
$tplVars['sidebar_blocks'][] = 'linked';
|
||||||
$tplVars['sidebar_blocks'][] = 'popular';
|
$tplVars['sidebar_blocks'][] = 'popular';
|
||||||
} else { //pages with tags
|
} else { //pages with tags
|
||||||
|
$rssTitle = "Tags" . $catTitle;
|
||||||
$rssCat = '/'. filter($cat, 'url');
|
$rssCat = '/'. filter($cat, 'url');
|
||||||
$tplVars['currenttag'] = $cat;
|
$tplVars['currenttag'] = $cat;
|
||||||
$tplVars['sidebar_blocks'][] = 'tagactions';
|
$tplVars['sidebar_blocks'][] = 'tagactions';
|
||||||
|
@ -264,9 +266,32 @@ if ($templatename == 'editbookmark.tpl') {
|
||||||
|
|
||||||
// Set template vars
|
// Set template vars
|
||||||
$tplVars['rsschannels'] = array(
|
$tplVars['rsschannels'] = array(
|
||||||
array(filter($sitename .': '. $pagetitle), createURL('rss', filter($user, 'url') . $rssCat.'?sort='.getSortOrder()))
|
array(
|
||||||
|
sprintf(T_('%s: %s'), $sitename, $rssTitle),
|
||||||
|
createURL('rss', filter($user, 'url'))
|
||||||
|
. $rssCat . '?sort='.getSortOrder()
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
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['page'] = $page;
|
||||||
$tplVars['start'] = $start;
|
$tplVars['start'] = $start;
|
||||||
$tplVars['bookmarkCount'] = $start + 1;
|
$tplVars['bookmarkCount'] = $start + 1;
|
||||||
|
|
|
@ -42,9 +42,30 @@ if (GET_ACTION == "logout") {
|
||||||
// Header variables
|
// Header variables
|
||||||
$tplVars['loadjs'] = true;
|
$tplVars['loadjs'] = true;
|
||||||
$tplVars['rsschannels'] = array(
|
$tplVars['rsschannels'] = array(
|
||||||
array(sprintf(T_('%s: Recent bookmarks'), $sitename), createURL('rss').'?sort='.getSortOrder())
|
array(
|
||||||
|
sprintf(T_('%s: Recent bookmarks'), $sitename),
|
||||||
|
createURL('rss') . '?sort=' . getSortOrder()
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if ($userservice->isLoggedOn()) {
|
||||||
|
if ($userservice->isPrivateKeyValid($currentUser->getPrivateKey())) {
|
||||||
|
$currentUsername = $currentUser->getUsername();
|
||||||
|
array_push(
|
||||||
|
$tplVars['rsschannels'],
|
||||||
|
array(
|
||||||
|
sprintf(
|
||||||
|
T_('%s: Recent bookmarks (+private %s)'),
|
||||||
|
$sitename, $currentUsername
|
||||||
|
),
|
||||||
|
createURL('rss')
|
||||||
|
. '?sort=' . getSortOrder()
|
||||||
|
. '&privateKey=' . $currentUser->getPrivateKey()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ($usecache) {
|
if ($usecache) {
|
||||||
// Generate hash for caching on
|
// Generate hash for caching on
|
||||||
$hashtext = $_SERVER['REQUEST_URI'];
|
$hashtext = $_SERVER['REQUEST_URI'];
|
||||||
|
|
|
@ -1,72 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright (c) 2004-2008, The Dojo Foundation All Rights Reserved.
|
|
||||||
Available via Academic Free License >= 2.1 OR the modified BSD license.
|
|
||||||
see: http://dojotoolkit.org/license for details
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* SemanticScuttle: This script is a light modification of dojox.form.MultiComboBox
|
|
||||||
This fork allows specific use until DOJO 1.2.3 in Google CDN. */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if(!dojo._hasResource["js.MultiComboBox"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
|
||||||
dojo._hasResource["js.MultiComboBox"] = true;
|
|
||||||
dojo.provide("js.MultiComboBox");
|
|
||||||
dojo.experimental("js.MultiComboBox");
|
|
||||||
dojo.require("dijit.form.ComboBox");
|
|
||||||
dojo.require("dijit.form.ValidationTextBox");
|
|
||||||
|
|
||||||
dojo.declare("js.MultiComboBox",
|
|
||||||
[dijit.form.ValidationTextBox, dijit.form.ComboBoxMixin],{
|
|
||||||
//
|
|
||||||
// summary: A ComboBox that accpets multiple inputs on a single line?
|
|
||||||
//
|
|
||||||
// delimiter: String
|
|
||||||
// The character to use to separate items in the ComboBox input
|
|
||||||
delimiter: ",",
|
|
||||||
_previousMatches: false,
|
|
||||||
|
|
||||||
_setValueAttr: function(value){
|
|
||||||
if (this.delimiter && value.length != 0){
|
|
||||||
value = value+this.delimiter+" ";
|
|
||||||
arguments[0] = this._addPreviousMatches(value);
|
|
||||||
}
|
|
||||||
this.inherited(arguments);
|
|
||||||
},
|
|
||||||
|
|
||||||
_addPreviousMatches: function(/* String */text){
|
|
||||||
if(this._previousMatches){
|
|
||||||
if(!text.match(new RegExp("^"+this._previousMatches))){
|
|
||||||
text = this._previousMatches+text;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
text = this._cleanupDelimiters(text); // SScuttle: this line was moved
|
|
||||||
return text; // String
|
|
||||||
},
|
|
||||||
|
|
||||||
_cleanupDelimiters: function(/* String */text){
|
|
||||||
if(this.delimiter){
|
|
||||||
text = text.replace(new RegExp(" +"), " ");
|
|
||||||
text = text.replace(new RegExp("^ *"+this.delimiter+"* *"), "");
|
|
||||||
text = text.replace(new RegExp(this.delimiter+" *"+this.delimiter), this.delimiter);
|
|
||||||
}
|
|
||||||
return text;
|
|
||||||
},
|
|
||||||
|
|
||||||
_autoCompleteText: function(/* String */text){
|
|
||||||
arguments[0] = this._addPreviousMatches(text);
|
|
||||||
this.inherited(arguments);
|
|
||||||
},
|
|
||||||
|
|
||||||
_startSearch: function(/* String */text){
|
|
||||||
text = this._cleanupDelimiters(text);
|
|
||||||
var re = new RegExp("^.*"+this.delimiter+" *");
|
|
||||||
|
|
||||||
if((this._previousMatches = text.match(re))){
|
|
||||||
arguments[0] = text.replace(re, "");
|
|
||||||
}
|
|
||||||
this.inherited(arguments);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
|
@ -90,6 +90,24 @@ function useAddress(ele) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Makes an ajax call to PHP script to generate an new Private Key
|
||||||
|
*
|
||||||
|
* @param input Calling object
|
||||||
|
* @param response Response object that returned value is placed
|
||||||
|
*
|
||||||
|
* @return boolean Returns false to halt execution after call
|
||||||
|
*/
|
||||||
|
function getNewPrivateKey(input, response){
|
||||||
|
var pk = document.getElementById('pPrivateKey');
|
||||||
|
if (response != null) {
|
||||||
|
pk.value = response.trim();
|
||||||
|
} else {
|
||||||
|
loadXMLDocProc('<?php echo ROOT; ?>ajaxGetNewPrivateKey.php');
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
function getTitle(input, response){
|
function getTitle(input, response){
|
||||||
var title = document.getElementById('titleField');
|
var title = document.getElementById('titleField');
|
||||||
if (title.value == '') {
|
if (title.value == '') {
|
||||||
|
|
|
@ -23,12 +23,16 @@ require_once 'www-header.php';
|
||||||
|
|
||||||
/* Service creation: only useful services are created */
|
/* Service creation: only useful services are created */
|
||||||
// No specific services
|
// No specific services
|
||||||
|
$tplVars['loadjs'] = true;
|
||||||
|
|
||||||
/* Managing all possible inputs */
|
/* Managing all possible inputs */
|
||||||
|
isset($_POST['submittedPK']) ? define('POST_SUBMITTEDPK', $_POST['submittedPK']): define('POST_SUBMITTEDPK', '');
|
||||||
isset($_POST['submitted']) ? define('POST_SUBMITTED', $_POST['submitted']): define('POST_SUBMITTED', '');
|
isset($_POST['submitted']) ? define('POST_SUBMITTED', $_POST['submitted']): define('POST_SUBMITTED', '');
|
||||||
isset($_POST['pPass']) ? define('POST_PASS', $_POST['pPass']): define('POST_PASS', '');
|
isset($_POST['pPass']) ? define('POST_PASS', $_POST['pPass']): define('POST_PASS', '');
|
||||||
isset($_POST['pPassConf']) ? define('POST_PASSCONF', $_POST['pPassConf']): define('POST_PASSCONF', '');
|
isset($_POST['pPassConf']) ? define('POST_PASSCONF', $_POST['pPassConf']): define('POST_PASSCONF', '');
|
||||||
isset($_POST['pName']) ? define('POST_NAME', $_POST['pName']): define('POST_NAME', '');
|
isset($_POST['pName']) ? define('POST_NAME', $_POST['pName']): define('POST_NAME', '');
|
||||||
|
isset($_POST['pPrivateKey']) ? define('POST_PRIVATEKEY', $_POST['pPrivateKey']): define('POST_PRIVATEKEY', '');
|
||||||
|
isset($_POST['pEnablePrivateKey']) ? define('POST_ENABLEPRIVATEKEY', $_POST['pEnablePrivateKey']): define('POST_ENABLEPRIVATEKEY', '');
|
||||||
isset($_POST['pMail']) ? define('POST_MAIL', $_POST['pMail']): define('POST_MAIL', '');
|
isset($_POST['pMail']) ? define('POST_MAIL', $_POST['pMail']): define('POST_MAIL', '');
|
||||||
isset($_POST['pPage']) ? define('POST_PAGE', $_POST['pPage']): define('POST_PAGE', '');
|
isset($_POST['pPage']) ? define('POST_PAGE', $_POST['pPage']): define('POST_PAGE', '');
|
||||||
isset($_POST['pDesc']) ? define('POST_DESC', $_POST['pDesc']): define('POST_DESC', '');
|
isset($_POST['pDesc']) ? define('POST_DESC', $_POST['pDesc']): define('POST_DESC', '');
|
||||||
|
@ -61,10 +65,19 @@ if ($user) {
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$tplVars['privateKeyIsEnabled'] = '';
|
||||||
if ($userservice->isLoggedOn() && $user == $currentUser->getUsername()) {
|
if ($userservice->isLoggedOn() && $user == $currentUser->getUsername()) {
|
||||||
$title = T_('My Profile');
|
$title = T_('My Profile');
|
||||||
|
$tplVars['privateKey'] = $currentUser->getPrivateKey(true);
|
||||||
|
|
||||||
|
if ($userservice->isPrivateKeyValid($currentUser->getPrivateKey())) {
|
||||||
|
$tplVars['privateKeyIsEnabled'] = 'checked="checked"';
|
||||||
|
} else {
|
||||||
|
$tplVars['privateKeyIsEnabled'] = '';
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
$title = T_('Profile') .': '. $user;
|
$title = T_('Profile') .': '. $user;
|
||||||
|
$tplVars['privateKey'] = '';
|
||||||
}
|
}
|
||||||
$tplVars['pagetitle'] = $title;
|
$tplVars['pagetitle'] = $title;
|
||||||
$tplVars['subtitle'] = $title;
|
$tplVars['subtitle'] = $title;
|
||||||
|
@ -72,11 +85,19 @@ $tplVars['subtitle'] = $title;
|
||||||
$tplVars['user'] = $user;
|
$tplVars['user'] = $user;
|
||||||
$tplVars['userid'] = $userid;
|
$tplVars['userid'] = $userid;
|
||||||
|
|
||||||
|
/* Update Private Key */
|
||||||
|
if (POST_SUBMITTEDPK!='' && $currentUser->getId() == $userid) {
|
||||||
|
$userinfo = $userservice->getObjectUserByUsername($user);
|
||||||
|
$tplVars['privateKey'] = $userservice->getNewPrivateKey();
|
||||||
|
}
|
||||||
|
|
||||||
if (POST_SUBMITTED!='' && $currentUser->getId() == $userid) {
|
if (POST_SUBMITTED!='' && $currentUser->getId() == $userid) {
|
||||||
$error = false;
|
$error = false;
|
||||||
$detPass = trim(POST_PASS);
|
$detPass = trim(POST_PASS);
|
||||||
$detPassConf = trim(POST_PASSCONF);
|
$detPassConf = trim(POST_PASSCONF);
|
||||||
$detName = trim(POST_NAME);
|
$detName = trim(POST_NAME);
|
||||||
|
$detPrivateKey = trim(POST_PRIVATEKEY);
|
||||||
|
$detEnablePrivateKey = trim(POST_ENABLEPRIVATEKEY);
|
||||||
$detMail = trim(POST_MAIL);
|
$detMail = trim(POST_MAIL);
|
||||||
$detPage = trim(POST_PAGE);
|
$detPage = trim(POST_PAGE);
|
||||||
$detDesc = filter(POST_DESC);
|
$detDesc = filter(POST_DESC);
|
||||||
|
@ -102,13 +123,19 @@ if (POST_SUBMITTED!='' && $currentUser->getId() == $userid) {
|
||||||
$tplVars['error'] = T_('E-mail address is not valid.');
|
$tplVars['error'] = T_('E-mail address is not valid.');
|
||||||
}
|
}
|
||||||
if (!$error) {
|
if (!$error) {
|
||||||
if (!$userservice->updateUser($userid, $detPass, $detName, $detMail, $detPage, $detDesc)) {
|
if (!$userservice->updateUser($userid, $detPass, $detName, $detMail, $detPage, $detDesc, $detPrivateKey, $detEnablePrivateKey)) {
|
||||||
$tplVars['error'] = T_('An error occurred while saving your changes.');
|
$tplVars['error'] = T_('An error occurred while saving your changes.');
|
||||||
} else {
|
} else {
|
||||||
$tplVars['msg'] = T_('Changes saved.');
|
$tplVars['msg'] = T_('Changes saved.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$userinfo = $userservice->getObjectUserByUsername($user);
|
$userinfo = $userservice->getObjectUserByUsername($user);
|
||||||
|
$tplVars['privateKey'] = $userinfo->getPrivateKey(true);
|
||||||
|
if ($userservice->isPrivateKeyValid($userinfo->getPrivateKey())) {
|
||||||
|
$tplVars['privateKeyIsEnabled'] = 'checked="checked"';
|
||||||
|
} else {
|
||||||
|
$tplVars['privateKeyIsEnabled'] = '';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$userservice->isLoggedOn() || $currentUser->getId() != $userid) {
|
if (!$userservice->isLoggedOn() || $currentUser->getId() != $userid) {
|
||||||
|
|
34
www/rss.php
34
www/rss.php
|
@ -64,7 +64,12 @@ if (!isset($rssEntries) || $rssEntries <= 0) {
|
||||||
$rssEntries = $maxRssEntries;
|
$rssEntries = $maxRssEntries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$privateKey = null;
|
||||||
|
if (isset($_GET['privateKey'])) {
|
||||||
|
$privateKey = $_GET['privateKey'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$userid = null;
|
||||||
$watchlist = null;
|
$watchlist = null;
|
||||||
$pagetitle = '';
|
$pagetitle = '';
|
||||||
if ($user && $user != 'all') {
|
if ($user && $user != 'all') {
|
||||||
|
@ -78,8 +83,22 @@ if ($user && $user != 'all') {
|
||||||
} else {
|
} else {
|
||||||
if ($userinfo = $userservice->getUserByUsername($user)) {
|
if ($userinfo = $userservice->getUserByUsername($user)) {
|
||||||
$userid =& $userinfo[$userservice->getFieldName('primary')];
|
$userid =& $userinfo[$userservice->getFieldName('primary')];
|
||||||
|
/* if user is not logged in and has valid privateKey */
|
||||||
|
if (!$userservice->isLoggedOn()) {
|
||||||
|
if ($privateKey != null) {
|
||||||
|
if (!$userservice->loginPrivateKey($privateKey)) {
|
||||||
|
$tplVars['error'] = sprintf(T_('Failed to Autenticate User with username %s using private key'), $user);
|
||||||
|
header('Content-type: text/html; charset=utf-8');
|
||||||
|
$templateservice->loadTemplate('error.404.tpl', $tplVars);
|
||||||
|
//throw a 404 error
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
$tplVars['error'] = sprintf(T_('User with username %s was not found'), $user);
|
$tplVars['error'] = sprintf(T_('User with username %s was not found'), $user);
|
||||||
|
header('Content-type: text/html; charset=utf-8');
|
||||||
$templateservice->loadTemplate('error.404.tpl', $tplVars);
|
$templateservice->loadTemplate('error.404.tpl', $tplVars);
|
||||||
//throw a 404 error
|
//throw a 404 error
|
||||||
exit();
|
exit();
|
||||||
|
@ -87,7 +106,17 @@ if ($user && $user != 'all') {
|
||||||
}
|
}
|
||||||
$pagetitle .= ": ". $user;
|
$pagetitle .= ": ". $user;
|
||||||
} else {
|
} else {
|
||||||
$userid = null;
|
if ($privateKey != null) {
|
||||||
|
if (!$userservice->loginPrivateKey($privateKey)) {
|
||||||
|
$tplVars['error'] = sprintf(T_('Failed to Autenticate User with username %s using private key'), $user);
|
||||||
|
header('Content-type: text/html; charset=utf-8');
|
||||||
|
$templateservice->loadTemplate('error.404.tpl', $tplVars);
|
||||||
|
//throw a 404 error
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$userid = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($cat) {
|
if ($cat) {
|
||||||
|
@ -100,7 +129,8 @@ $tplVars['feeddescription'] = sprintf(T_('Recent bookmarks posted to %s'), $GLOB
|
||||||
|
|
||||||
$bookmarks = $bookmarkservice->getBookmarks(
|
$bookmarks = $bookmarkservice->getBookmarks(
|
||||||
0, $rssEntries, $userid, $cat,
|
0, $rssEntries, $userid, $cat,
|
||||||
null, getSortOrder(), $watchlist
|
null, getSortOrder(), $watchlist,
|
||||||
|
null, null, null
|
||||||
);
|
);
|
||||||
|
|
||||||
$bookmarks_tmp = filter($bookmarks['bookmarks']);
|
$bookmarks_tmp = filter($bookmarks['bookmarks']);
|
||||||
|
|
24
www/tags.php
24
www/tags.php
|
@ -67,9 +67,31 @@ if ($usecache) {
|
||||||
$tplVars['pagetitle'] = T_('Tags') .': '. $cat;
|
$tplVars['pagetitle'] = T_('Tags') .': '. $cat;
|
||||||
$tplVars['loadjs'] = true;
|
$tplVars['loadjs'] = true;
|
||||||
$tplVars['rsschannels'] = array(
|
$tplVars['rsschannels'] = array(
|
||||||
array(filter($sitename .': '. $pagetitle), createURL('rss', 'all/'. filter($cat, 'url')).'?sort='.getSortOrder())
|
array(
|
||||||
|
sprintf(T_('%s: tagged with "%s"'), $sitename, $cat),
|
||||||
|
createURL('rss', 'all/' . filter($cat, 'url'))
|
||||||
|
. '?sort='.getSortOrder()
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if ($userservice->isLoggedOn()) {
|
||||||
|
if ($userservice->isPrivateKeyValid($currentUser->getPrivateKey())) {
|
||||||
|
$currentUsername = $currentUser->getUsername();
|
||||||
|
array_push(
|
||||||
|
$tplVars['rsschannels'],
|
||||||
|
array(
|
||||||
|
sprintf(
|
||||||
|
T_('%s: tagged with "%s" (+private %s)'),
|
||||||
|
$sitename, $cat, $currentUsername
|
||||||
|
),
|
||||||
|
createURL('rss', filter($currentUsername, 'url'))
|
||||||
|
. '?sort=' . getSortOrder()
|
||||||
|
. '&privateKey=' . $currentUser->getPrivateKey()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Pagination
|
// Pagination
|
||||||
$perpage = getPerPageCount($currentUser);
|
$perpage = getPerPageCount($currentUser);
|
||||||
if (intval(GET_PAGE) > 1) {
|
if (intval(GET_PAGE) > 1) {
|
||||||
|
|
Loading…
Reference in a new issue