Commit 61e33676 authored by Mike Sheldon's avatar Mike Sheldon

Resolve conflicts between merge 51 and HEAD

parents 4d6ebecc 3ef41f80
......@@ -88,7 +88,7 @@ Installing Smarty:
$ tar zxvf Smarty*
$ tar zxvf smarty*
$ mv smarty/libs/* smarty/.
$ mv smarty-gettext/block.t.php smarty/.
$ mv smarty-gettext/block.t.php smarty/plugins/.
Installing ADOdb:
$ cp external_dependencies/adodb511.tgz /var/www/htdocs/nixtape/.
......
......@@ -7,7 +7,6 @@ RewriteRule ^user/([^/]+)/groups/?$ user-groups.php?user=$1 [NC,QSA]
RewriteRule ^user/([^/]+)/recent-tracks/?$ user-recent-tracks.php?user=$1 [NC,QSA]
RewriteRule ^user/([^/]+)/stats/?$ user-stats.php?user=$1 [NC,QSA]
RewriteRule ^user/([^/]+)/station/?$ user-station.php?user=$1 [NC,QSA]
RewriteRule ^user/([^/]+)/recommended/?$ user-recommended.php?user=$1 [NC,QSA]
RewriteRule ^artist/([^/]+)/track/([^/]+)/edit/?$ track-add.php?artist=$1&track=$2 [NC,QSA]
RewriteRule ^artist/([^/]+)/track/([^/]+)/tag/?$ track-tag.php?artist=$1&track=$2 [NC,QSA]
RewriteRule ^artist/([^/]+)/track/([^/]+)/?$ track.php?artist=$1&track=$2 [NC,QSA]
......
......@@ -109,6 +109,7 @@ $method_map = array(
'tag.gettoptracks' => method_tag_getTopTracks,
'tag.getinfo' => method_tag_getInfo,
'track.addtags' => method_track_addTags,
'track.removetag' => method_track_removeTag,
'track.gettoptags' => method_track_getTopTags,
'track.gettags' => method_track_getTags,
'track.ban' => method_track_ban,
......@@ -706,20 +707,14 @@ function method_album_getTags() {
* @api
*/
function method_auth_getToken() {
global $adodb;
$key = md5(time() . rand());
$token = Server::getAuthToken();
try {
$result = $adodb->Execute('INSERT INTO Auth (token, expires) VALUES ('
. $adodb->qstr($key) . ', '
. (int)(time() + 3600)
. ')');
} catch (Exception $e) {
if(!$token) {
report_failure(LFM_SERVICE_OFFLINE);
}
$xml = simplexml_load_string('<lfm status="ok"><token>' . $key . '</token></lfm>');
$xml = simplexml_load_string('<lfm status="ok"><token>' . $token . '</token></lfm>');
respond($xml);
}
/**
......@@ -1009,8 +1004,8 @@ function method_radio_getPlaylist() {
* Add tags to a track using a comma-separated list of tags.
*
* ###Parameters
* * **artist** (required) : Name of the tracks's artist.
* * **track** (required) : Name of the tracks.
* * **artist** (required) : Name of the track's artist.
* * **track** (required) : Name of the track.
* * **tags** (required) : Comma-separated list of tags.
* * **sk** (required) : Session key.
* * **album** (optional) : Name of the tracks's album.
......@@ -1036,6 +1031,40 @@ function method_track_addTags() {
respond($xml);
}
/**
* track.removetag : Remove tag from a track.
*
* ###Description
* Remove a tag from a track.
*
* ###Parameters
* * **artist** (required) : Name of the track's artist.
* * **track** (required) : Name of the track.
* * **tag** (required) : Name of tag.
* * **sk** (required) : Session key.
* * **format** (optional) : Format of response, **xml** or **json**. Default is xml.
*
* ###Additional info
* **This method requires authentication**.
*
* **HTTP request method** : POST.
* - - -
*
* @package Webservice
* @subpackage Track
* @api
*/
function method_track_removeTag() {
if (!isset($_POST['artist']) || !isset($_POST['track']) || !isset($_POST['tag'])) {
report_failure(LFM_INVALID_PARAMS);
}
$userid = get_userid();
$xml = TrackXML::removeTag($userid, $_POST['artist'], $_POST['track'], $_POST['tag']);
respond($xml);
}
/**
* track.gettoptags : Get the top tags for a track.
*
......
......@@ -43,6 +43,18 @@ class TrackXML {
return $xml;
}
public static function removeTag($userid, $artist, $trackName, $tag) {
try {
$track = new Track($trackName, $artist);
$track->removeTag($tag, $userid);
} catch (Exception $e) {
return(XML::error('failed', '7', 'Invalid resource specified'));
}
$xml = new SimpleXMLElement('<lfm status="ok"></lfm>');
return $xml;
}
public static function getTopTags($artist, $name, $limit, $cache) {
try {
......
......@@ -18,80 +18,96 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
require_once('../../config.php');
require_once($install_path . '/database.php');
require_once($install_path . '/templating.php');
require_once($install_path . '/data/Server.php');
require_once($install_path . '/data/clientcodes.php');
function displayError($error_msg) {
global $smarty;
$smarty->assign('error_msg', $error_msg);
$smarty->display('api_auth.tpl');
exit();
}
$smarty->assign('site_name', $site_name);
if ($logged_in) {
$smarty->assign('username', $this_user->name);
}
// We always need the api_key parameter and parameter cb or token
if (!isset($_REQUEST['api_key']) || !(isset($_REQUEST['cb']) || isset($_REQUEST['token']))) {
displayError('Must submit a combination of parameters api_key and cb or api_key and token to proceed.');
// Web app auth stage 1
} elseif (isset($_GET['api_key']) && isset($_GET['cb']) && !isset($_REQUEST['token'])) {
$token = Server::getAuthToken();
$smarty->assign('stage', 'webapp1');
$smarty->assign('token', $token);
$smarty->assign('cb', $_GET['cb']);
$smarty->assign('api_key', $_GET['api_key']);
// Desktop app auth stage 1
} elseif (isset($_GET['api_key']) && isset($_GET['token']) && !isset($_GET['cb']) && !isset($_POST['token'])) {
require_once('../../database.php');
?>
<html>
<body>
<?php
if (isset($_POST['username'], $_POST['api_key'], $_POST['token'])) {
// Authenticate the user using the submitted password
// Ensures the token exists and is not already bound to a user
$query = 'SELECT * FROM Auth WHERE token = ? AND username IS NULL';
$params = array($_GET['token']);
try {
$result = $adodb->GetOne('SELECT username FROM Users WHERE '
. 'lower(username) = ' . $adodb->qstr(strtolower($_POST['username'])) . ' AND '
. 'password = ' . $adodb->qstr(md5($_POST['password'])));
$result = $adodb->GetRow($query, $params);
} catch (Exception $e) {
die('Database error');
reportError($e->getMessage(), $e->getTraceAsString());
displayError('Database error');
}
if (!$result) {
die('Authentication failed');
displayError('Invalid token');
}
$smarty->assign('stage', 'deskapp1');
$smarty->assign('api_key', $_GET['api_key']);
$smarty->assign('token', $_GET['token']);
// Web/Desktop app auth stage 2.1
} elseif (isset($_POST['api_key'], $_POST['token'])) {
if(!$logged_in) {
// Authenticate the user using the submitted password
$query = 'SELECT username FROM Users WHERE lower(username) = lower(?) AND password = ?';
$params = array($_POST['username'], md5($_POST['password']));
try {
$username = $adodb->GetOne($query, $params);
} catch (Exception $e) {
reportError($e->getMessage(), $e->getTraceAsString());
displayError('Database error');
}
if (!$username) {
displayError('Authentication failed');
}
}
// Bind the user to the token and cancel the expiration rule
$query = 'UPDATE Auth SET username = ?, expires = 0 WHERE token = ?';
$params = array($username, $_POST['token']);
try {
$result = $adodb->Execute('UPDATE Auth SET '
. 'username = ' . $adodb->qstr($_POST['username']) . ', '
. 'expires = 0 '
. 'WHERE '
. 'token = ' . $adodb->qstr($_POST['token']));
$adodb->Execute($query, $params);
} catch (Exception $e) {
die('Database error');
reportError($e->getMessage(), $e->getTraceAsString());
displayError('Database error');
}
?>
<p>Thank you very much, <?php print($_POST['username']); ?>. Your authorization has been recorded.</p>
<p>You may now close the browser.</p>
<?php } else if (!isset($_GET['api_key'], $_GET['token'])) { ?>
<p>Must submit an api_key and token to proceed.</p>
<?php
} else {
// Web app auth step 2.2
if(isset($_POST['cb'])) {
$redirect_url = $_POST['cb'];
header('Location:' . $redirect_url . '&token=' . $_POST['token']);
// Ensures the token exists and is not already bound to a user
try {
$result = $adodb->GetRow('SELECT * FROM Auth WHERE '
. 'token = ' . $adodb->qstr($_GET['token']) . ' AND '
. 'username IS NULL');
} catch (Exception $e) {
die('Database error');
// Desktop app auth step 2.2
} else {
$smarty->assign('stage', 'deskapp2.2');
$smarty->assign('username', $username);
}
if (!$result) {
die('Invalid token');
}
?>
<form method="post" action="">
<p>Your Username: <input type="text" name="username" /></p>
<p>Your Password: <input type="password" name="password" /></p>
<p>
<input type="submit" value="Submit" />
<input type="hidden" name="api_key" value="<?php print($_GET['api_key']); ?>" />
<input type="hidden" name="token" value="<?php print($_GET['token']); ?>" />
</p>
</form>
<?php } ?>
</body>
}
</html>
$client = getClientData('null', $_REQUEST['api_key']);
$smarty->assign('clientname', $client['name']);
$smarty->assign('clienturl', $client['url']);
$smarty->display('api_auth.tpl');
......@@ -102,7 +102,6 @@ class GraphTopTracks extends Graph {
* plotting utility.
**/
private function buildGraphData() {
$this->begin = strtotime('-6 months');
$this->data_buffer = $this->user->getTopTracks($this->number_of_tracks, 0, False, $this->begin);
$tracks = array();
$listings = array();
......
......@@ -931,4 +931,25 @@ class Server {
return $result;
}
/**
* Create a random authentication token and return it
*
* @return string Token.
*/
static function getAuthToken() {
global $adodb;
$key = md5(time() . rand());
$expires = (int) (time() + 3600);
$query = 'INSERT INTO Auth(token, expires) VALUES(?,?)';
$params = array($key, $expires);
try {
$adodb->Execute($query, $params);
return $key;
} catch (Exception $e) {
reportError($e->getMessage(), $e->getTraceAsString());
}
}
}
......@@ -385,5 +385,27 @@ class Track {
}
return False;
}
/*
* Remove a tag from a track
*
* @param string $tag The tag to be removed
* @param int $userid The user removing the tag
*/
function removeTag($tag, $userid) {
global $adodb;
$tag = trim($tag);
if(strlen($tag) == 0) {
return;
}
$query = 'DELETE FROM Tags WHERE tag = ? AND lower(artist) = lower(?) AND lower(track) = lower(?) AND userid = ?';
$params = array($tag, $this->artist_name, $this->name, $userid);
try {
$adodb->Execute($query, $params);
} catch (Exception $e) {
reportError($e->getMessage(), $e->getTraceAsString());
}
}
}
......@@ -32,6 +32,7 @@ var playable_songs = false;
var streaming = false;
var example_tags = "e.g. guitar, violin, female vocals, piano";
var error_count = 0;
var base_url = base_url || "";
/**
* Initialises the javascript player (player.tpl must also be included on the target page)
......@@ -226,7 +227,7 @@ function scrobble() {
return;
}
timestamp = Math.round(new Date().getTime() / 1000);
$.post("/scrobble-proxy.php?method=scrobble", { "a[0]" : artist, "b[0]" : album, "t[0]" : track, "i[0]" : timestamp, "s" : session_key },
$.post(base_url + "/scrobble-proxy.php?method=scrobble", { "a[0]" : artist, "b[0]" : album, "t[0]" : track, "i[0]" : timestamp, "s" : session_key },
function(data){
if(data.substring(0, 2) == "OK") {
$("#scrobbled").text("Scrobbled");
......@@ -250,7 +251,7 @@ function nowPlaying() {
return;
}
timestamp = Math.round(new Date().getTime() / 1000);
$.post("/scrobble-proxy.php?method=nowplaying", { "a" : artist, "b" : album, "t" : track, "l" : audio.duration, "s" : session_key}, function(data) {}, "text");
$.post(base_url + "/scrobble-proxy.php?method=nowplaying", { "a" : artist, "b" : album, "t" : track, "l" : audio.duration, "s" : session_key}, function(data) {}, "text");
}
/**
......@@ -313,7 +314,7 @@ function loadSong(song) {
$("#love").fadeTo("normal", 1);
if($("#flattrstream")) {
$.getJSON('/2.0/', {'method' : 'artist.getflattr', 'artist' : artist, 'format' : 'json'}, updateFlattr);
$.getJSON(base_url + '/2.0/', {'method' : 'artist.getflattr', 'artist' : artist, 'format' : 'json'}, updateFlattr);
}
}
......@@ -336,7 +337,7 @@ function updateFlattr(data) {
*/
function getRadioPlaylist() {
var tracks, artist, album, title, url, extension, trackpage_url, i;
$.get("/2.0/", {'method' : 'radio.getPlaylist', 'sk' : radio_key}, function(data) {
$.get(base_url + "/2.0/", {'method' : 'radio.getPlaylist', 'sk' : radio_key}, function(data) {
parser=new DOMParser();
xmlDoc=parser.parseFromString(data,"text/xml");
tracks = xmlDoc.getElementsByTagName("track")
......@@ -409,14 +410,14 @@ function friendlyTime(timestamp) {
}
function love() {
$.post("/2.0/", {'method' : 'track.love', 'artist' : artist, 'track' : track, 'sk' : ws_key}, function(data) {}, "text");
$.post(base_url + "/2.0/", {'method' : 'track.love', 'artist' : artist, 'track' : track, 'sk' : ws_key}, function(data) {}, "text");
$("#love").fadeTo("normal", 0.5);
$("#scrobbled").text("Loved");
$("#scrobbled").fadeIn(5000, function() { $("#scrobbled").fadeOut(5000) } );
}
function ban() {
$.post("/2.0/", {'method' : 'track.ban', 'artist' : artist, 'track' : track, 'sk' : ws_key}, function(data) {}, "text");
$.post(base_url + "/2.0/", {'method' : 'track.ban', 'artist' : artist, 'track' : track, 'sk' : ws_key}, function(data) {}, "text");
$("#ban").fadeTo("normal", 0.5);
skipForward();
}
......@@ -430,7 +431,7 @@ function toggleTag() {
function tag() {
var tags = $("#tags").val();
if (tags != example_tags && tags != "") {
$.post("/2.0/", {'method' : 'track.addtags', 'artist' : artist, 'track' : track, 'tags' : tags, 'sk' : ws_key}, function(data) {}, "text");
$.post(base_url + "/2.0/", {'method' : 'track.addtags', 'artist' : artist, 'track' : track, 'tags' : tags, 'sk' : ws_key}, function(data) {}, "text");
toggleTag();
$("#tags").val("");
}
......
......@@ -271,6 +271,11 @@ function get_artist_selection($artists, $artist = false) {
*/
function get_loved_tracks($users) {
global $adodb;
if (!count($users)) {
return array();
}
$userclause = '( ';
for ($i = 0; $i < count($users); $i++) {
$userclause .= 'Loved_Tracks.userid = ' . $users[$i];
......
{include file='mini-header.tpl'}
{if $error_msg}
<p>{$error_msg}</p>
{elseif $stage == 'deskapp2.2'}
<p>Thank you very much {$username}. Your authorization has been recorded.</p>
<p>You may now close this page.</p>
{else}
{if $username}<h3>Hello {$username}</h3>{/if}
{if $clientname == 'Unknown client'}
<p><a href="{$clienturl}">{$clientname}</a> with<br /> API key: <b>{$api_key}</b><br />
{if $cb}
Callback URL: <b>{$cb}</b><br />
{/if}
{else}
<p><a href="{$clienturl}">{$clientname}</a>
{/if}
wants your permission to talk with this service.</p>
<form method="post" action="">
{if !$logged_in}
<p>Your Username: <input type="text" name="username" /></p>
<p>Your Password: <input type="password" name="password" /></p>
<p>
{/if}
<input type="submit" value="Submit" />
<input type="hidden" name="api_key" value="{$api_key}" />
<input type="hidden" name="token" value="{$token}" />
{if $cb}
<input type="hidden" name="cb" value="{$cb}" />
{/if}
</p>
</form>
{/if}
{include file='mini-footer.tpl'}
......@@ -16,6 +16,9 @@
<script type="text/javascript" src="{$base_url}/js/jquery-1.4.4.min.js"></script>
<script type="text/javascript" src="{$base_url}/js/jquery-ui-1.7.1.custom.min.js"></script>
<script type="text/javascript" src="{$base_url}/js/jquery.placeholdr.js"></script>
<script type="text/javascript">
var base_url="{$base_url}";
</script>
<script type="text/javascript" src="{$base_url}/js/player.js"></script>
<script type="text/javascript" src="{$base_url}/themes/{$default_theme}/js/modernizr.js"></script>
<meta name="author" content="FooCorp catalogue number FOO200 and contributors" />
......
{include file='header.tpl'}
<center>
<div id='player-container' style='float: none; text-align: center;'>
<h4>{t user=$me->name|capitalize}%1's Recommended Radio{/t}</h4><br />
{include file='player.tpl'}
<script type="text/javascript">
{if isset($this_user)}
playerInit(false, "{$this_user->getScrobbleSession()}", "{$this_user->getWebServiceSession()}", "{$radio_session}");
{else}
playerInit(false, false, false, "{$radio_session}");
{/if}
</script>
</div>
</center>
{include file='footer.tpl'}
......@@ -27,10 +27,15 @@
* @return string A mod_rewrite compatible encoding of the given text.
*/
function rewrite_encode($url) {
$url = urlencode($url);
$url = preg_replace('/%2B/', '%252B', $url); // +
$url = preg_replace('/%2F/', '%252F', $url); // /
$url = preg_replace('/%26/', '%2526', $url); // &
$url = preg_replace('/%23/', '%2523', $url); // #
if (preg_match('/Apache/', $_SERVER['SERVER_SOFTWARE'])) {
$url = urlencode($url);
$url = preg_replace('/%2B/', '%252B', $url); // +
$url = preg_replace('/%2F/', '%252F', $url); // /
$url = preg_replace('/%26/', '%2526', $url); // &
$url = preg_replace('/%23/', '%2523', $url); // #
} else {
$url = rawurlencode($url);
}
return $url;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment