20
18
* along with this program; if not, write to the Free Software
21
19
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24
* @copyright 2001 - 2011 Ampache.org
25
* @license http://opensource.org/licenses/gpl-2.0 GPLv2
26
* @link http://www.ampache.org/
35
* @copyright 2001 - 2011 Ampache.org
36
* @license http://opensource.org/licenses/gpl-2.0 GPLv2
37
* @link http://www.ampache.org/
48
public $queued_tracks;
49
public $reset_handshake = false;
50
public $scrobble_host = 'post.audioscrobbler.com';
54
* This is the constructer it takes a username and password
56
public function __construct($username, $password,$host='',$port='',$url='',$challenge='',$scrobble_host='') {
58
$this->error_msg = '';
59
$this->username = trim($username);
60
$this->password = trim($password);
61
$this->challenge = $challenge;
62
$this->submit_host = $host;
63
$this->submit_port = $port;
64
$this->submit_url = $url;
65
$this->queued_tracks = array();
66
if ($scrobble_host) { $this->scrobble_host = $scrobble_host; }
73
public function get_error_msg() {
75
return $this->error_msg;
82
public function get_queue_count() {
84
return count($this->queued_tracks);
90
* This does a handshake with the audioscrobber server it doesn't pass the password, but
91
* it does pass the username and has a 10 second timeout
93
public function handshake() {
95
$as_socket = fsockopen($this->scrobble_host, 80, $errno, $errstr, 2);
97
$this->error_msg = $errstr;
101
$username = rawurlencode($this->username);
103
$auth_token = rawurlencode(md5($this->password . $timestamp));
105
$get_string = "GET /?hs=true&p=1.2&c=apa&v=0.1&u=$username&t=$timestamp&a=$auth_token HTTP/1.1\r\n";
107
fwrite($as_socket, $get_string);
108
fwrite($as_socket, "Host: $this->scrobble_host\r\n");
109
fwrite($as_socket, "Accept: */*\r\n\r\n");
112
while(!feof($as_socket)) {
113
$buffer .= fread($as_socket, 4096);
116
$split_response = preg_split("/\r\n\r\n/", $buffer);
117
if(!isset($split_response[1])) {
118
$this->error_msg = 'Did not receive a valid response';
121
$response = explode("\n", $split_response[1]);
123
// Handle the fact Libre.FM has extranious values at the start of it's handshake response
124
if(is_numeric(trim($response['0']))) {
125
array_shift($response);
126
debug_event('SCROBBLER','Junk in handshake, removing first line',1);
128
if(substr($response[0], 0, 6) == 'FAILED') {
129
$this->error_msg = substr($response[0], 7);
132
if(substr($response[0], 0, 7) == 'BADUSER') {
133
$this->error_msg = 'Invalid Username';
136
if(substr($response[0],0,7) == 'BADTIME') {
137
$this->error_msg = 'Your time is too far off from the server, or your PHP timezone is incorrect';
140
if(substr($response[0], 0, 6) == 'UPDATE') {
141
$this->error_msg = 'You need to update your client: '.substr($response[0], 7);
145
if(preg_match('/http:\/\/([^\/]+)\/(.*)$/', $response[3], $matches)) {
146
$host_parts = explode(":",$matches[1]);
147
$data['submit_host'] = $host_parts[0];
148
$data['submit_port'] = $host_parts[1] ? $host_parts[1] : '80';
149
$data['submit_url'] = '/' . $matches[2];
151
$this->error_msg = "Invalid POST URL returned, unable to continue. Sent:\n$get_string\n----\nReceived:\n" . $buffer .
152
"\n---------\nExpeceted:" . print_r($response,1);
156
// Remove any extra junk around the challenge
157
$data['challenge'] = trim($response[1]);
164
* This queues the LastFM track by storing it in this object, it doesn't actually
165
* submit the track or talk to LastFM in anyway, kind of useless for our uses but its
166
* here, and that's how it is.
168
public function queue_track($artist, $album, $title, $timestamp, $length,$track) {
171
debug_event('Scrobbler',"Not queuing track, too short",'5');
176
$newtrack['artist'] = $artist;
177
$newtrack['album'] = $album;
178
$newtrack['title'] = $title;
179
$newtrack['track'] = $track;
180
$newtrack['length'] = $length;
181
$newtrack['time'] = $timestamp;
183
$this->queued_tracks[$timestamp] = $newtrack;
190
* This actually talks to LastFM submiting the tracks that are queued up. It
191
* passed the md5'd password combinted with the challenge, which is then md5'd
193
public function submit_tracks() {
195
// Check and make sure that we've got some queued tracks
196
if(!count($this->queued_tracks)) {
197
$this->error_msg = "No tracks to submit";
201
//sort array by timestamp
202
ksort($this->queued_tracks);
204
// build the query string
205
$query_str = 's='.rawurlencode($this->challenge).'&';
209
foreach($this->queued_tracks as $track) {
210
$query_str .= "a[$i]=".rawurlencode($track['artist'])."&t[$i]=".rawurlencode($track['title'])."&b[$i]=".rawurlencode($track['album'])."&";
211
$query_str .= "m[$i]=&l[$i]=".rawurlencode($track['length'])."&i[$i]=".rawurlencode($track['time'])."&";
212
$query_str .= "n[$i]=" . rawurlencode($track['track']) . "&o[$i]=P&r[$i]=&";
216
if (!trim($this->submit_host) || !$this->submit_port) {
217
$this->reset_handshake = true;
221
$as_socket = fsockopen($this->submit_host, intval($this->submit_port), $errno, $errstr, 2);
224
$this->error_msg = $errstr;
225
$this->reset_handshake = true;
229
$action = "POST ".$this->submit_url." HTTP/1.0\r\n";
230
fwrite($as_socket, $action);
231
fwrite($as_socket, "Host: ".$this->submit_host."\r\n");
232
fwrite($as_socket, "Accept: */*\r\n");
233
fwrite($as_socket, "User-Agent: Ampache/3.6\r\n");
234
fwrite($as_socket, "Content-type: application/x-www-form-urlencoded\r\n");
235
fwrite($as_socket, "Content-length: ".strlen($query_str)."\r\n\r\n");
237
fwrite($as_socket, $query_str."\r\n\r\n");
238
// Allow us to debug this
239
debug_event('SCROBBLER','Query String:' . $query_str,6);
242
while(!feof($as_socket)) {
243
$buffer .= fread($as_socket, 8192);
247
$split_response = preg_split("/\r\n\r\n/", $buffer);
248
if(!isset($split_response[1])) {
249
$this->error_msg = 'Did not receive a valid response';
250
$this->reset_handshake = true;
253
$response = explode("\n", $split_response[1]);
254
if(!isset($response[0])) {
255
$this->error_msg = 'Unknown error submitting tracks'.
256
"\nDebug output:\n".$buffer;
257
$this->reset_handshake = true;
260
if(substr($response[0], 0, 6) == 'FAILED') {
261
$this->error_msg = $response[0];
262
$this->reset_handshake = true;
265
if(substr($response[0], 0, 7) == 'BADAUTH') {
266
$this->error_msg = 'Invalid username/password (' . trim($response[0]) . ')';
269
if (substr($response[0],0,10) == 'BADSESSION') {
270
$this->error_msg = 'Invalid Session passed (' . trim($response[0]) . ')';
271
$this->reset_handshake = true;
274
if(substr($response[0], 0, 2) != 'OK') {
275
$this->error_msg = 'Response Not ok, unknown error'.
276
"\nDebug output:\n".$buffer;
277
$this->reset_handshake = true;
32
public $queued_tracks;
33
public $reset_handshake = false;
34
public $scrobble_host = 'post.audioscrobbler.com';
38
* This is the constructer it takes a username and password
40
public function __construct($username, $password,$host='',$port='',$url='',$challenge='',$scrobble_host='') {
42
$this->error_msg = '';
43
$this->username = trim($username);
44
$this->password = trim($password);
45
$this->challenge = $challenge;
46
$this->submit_host = $host;
47
$this->submit_port = $port;
48
$this->submit_url = $url;
49
$this->queued_tracks = array();
50
if ($scrobble_host) { $this->scrobble_host = $scrobble_host; }
57
public function get_error_msg() {
59
return $this->error_msg;
66
public function get_queue_count() {
68
return count($this->queued_tracks);
74
* This does a handshake with the audioscrobber server it doesn't pass the password, but
75
* it does pass the username and has a 10 second timeout
77
public function handshake() {
79
$as_socket = fsockopen($this->scrobble_host, 80, $errno, $errstr, 2);
81
$this->error_msg = $errstr;
85
$username = rawurlencode($this->username);
87
$auth_token = rawurlencode(md5($this->password . $timestamp));
89
$get_string = "GET /?hs=true&p=1.2&c=apa&v=0.1&u=$username&t=$timestamp&a=$auth_token HTTP/1.1\r\n";
91
fwrite($as_socket, $get_string);
92
fwrite($as_socket, "Host: $this->scrobble_host\r\n");
93
fwrite($as_socket, "Accept: */*\r\n\r\n");
96
while(!feof($as_socket)) {
97
$buffer .= fread($as_socket, 4096);
100
$split_response = preg_split("/\r\n\r\n/", $buffer);
101
if(!isset($split_response[1])) {
102
$this->error_msg = 'Did not receive a valid response';
105
$response = explode("\n", $split_response[1]);
107
// Handle the fact Libre.FM has extranious values at the start of it's handshake response
108
if(is_numeric(trim($response['0']))) {
109
array_shift($response);
110
debug_event('SCROBBLER','Junk in handshake, removing first line',1);
112
if(substr($response[0], 0, 6) == 'FAILED') {
113
$this->error_msg = substr($response[0], 7);
116
if(substr($response[0], 0, 7) == 'BADUSER') {
117
$this->error_msg = 'Invalid Username';
120
if(substr($response[0],0,7) == 'BADTIME') {
121
$this->error_msg = 'Your time is too far off from the server, or your PHP timezone is incorrect';
124
if(substr($response[0], 0, 6) == 'UPDATE') {
125
$this->error_msg = 'You need to update your client: '.substr($response[0], 7);
129
if(preg_match('/http:\/\/([^\/]+)\/(.*)$/', $response[3], $matches)) {
130
$host_parts = explode(":",$matches[1]);
131
$data['submit_host'] = $host_parts[0];
132
$data['submit_port'] = $host_parts[1] ? $host_parts[1] : '80';
133
$data['submit_url'] = '/' . $matches[2];
135
$this->error_msg = "Invalid POST URL returned, unable to continue. Sent:\n$get_string\n----\nReceived:\n" . $buffer .
136
"\n---------\nExpected:" . print_r($response, true);
140
// Remove any extra junk around the challenge
141
$data['challenge'] = trim($response[1]);
148
* This queues the LastFM track by storing it in this object, it doesn't actually
149
* submit the track or talk to LastFM in anyway, kind of useless for our uses but its
150
* here, and that's how it is.
152
public function queue_track($artist, $album, $title, $timestamp, $length,$track) {
155
debug_event('Scrobbler',"Not queuing track, too short",'5');
160
$newtrack['artist'] = $artist;
161
$newtrack['album'] = $album;
162
$newtrack['title'] = $title;
163
$newtrack['track'] = $track;
164
$newtrack['length'] = $length;
165
$newtrack['time'] = $timestamp;
167
$this->queued_tracks[$timestamp] = $newtrack;
174
* This actually talks to LastFM submiting the tracks that are queued up. It
175
* passed the md5'd password combinted with the challenge, which is then md5'd
177
public function submit_tracks() {
179
// Check and make sure that we've got some queued tracks
180
if(!count($this->queued_tracks)) {
181
$this->error_msg = "No tracks to submit";
185
//sort array by timestamp
186
ksort($this->queued_tracks);
188
// build the query string
189
$query_str = 's='.rawurlencode($this->challenge).'&';
193
foreach($this->queued_tracks as $track) {
194
$query_str .= "a[$i]=".rawurlencode($track['artist'])."&t[$i]=".rawurlencode($track['title'])."&b[$i]=".rawurlencode($track['album'])."&";
195
$query_str .= "m[$i]=&l[$i]=".rawurlencode($track['length'])."&i[$i]=".rawurlencode($track['time'])."&";
196
$query_str .= "n[$i]=" . rawurlencode($track['track']) . "&o[$i]=P&r[$i]=&";
200
if (!trim($this->submit_host) || !$this->submit_port) {
201
$this->reset_handshake = true;
205
$as_socket = fsockopen($this->submit_host, intval($this->submit_port), $errno, $errstr, 2);
208
$this->error_msg = $errstr;
209
$this->reset_handshake = true;
213
$action = "POST ".$this->submit_url." HTTP/1.0\r\n";
214
fwrite($as_socket, $action);
215
fwrite($as_socket, "Host: ".$this->submit_host."\r\n");
216
fwrite($as_socket, "Accept: */*\r\n");
217
fwrite($as_socket, "User-Agent: Ampache/3.6\r\n");
218
fwrite($as_socket, "Content-type: application/x-www-form-urlencoded\r\n");
219
fwrite($as_socket, "Content-length: ".strlen($query_str)."\r\n\r\n");
221
fwrite($as_socket, $query_str."\r\n\r\n");
222
// Allow us to debug this
223
debug_event('SCROBBLER','Query String:' . $query_str,6);
226
while(!feof($as_socket)) {
227
$buffer .= fread($as_socket, 8192);
231
$split_response = preg_split("/\r\n\r\n/", $buffer);
232
if(!isset($split_response[1])) {
233
$this->error_msg = 'Did not receive a valid response';
234
$this->reset_handshake = true;
237
$response = explode("\n", $split_response[1]);
238
if(!isset($response[0])) {
239
$this->error_msg = 'Unknown error submitting tracks'.
240
"\nDebug output:\n".$buffer;
241
$this->reset_handshake = true;
244
if(substr($response[0], 0, 6) == 'FAILED') {
245
$this->error_msg = $response[0];
246
$this->reset_handshake = true;
249
if(substr($response[0], 0, 7) == 'BADAUTH') {
250
$this->error_msg = 'Invalid username/password (' . trim($response[0]) . ')';
253
if (substr($response[0],0,10) == 'BADSESSION') {
254
$this->error_msg = 'Invalid Session passed (' . trim($response[0]) . ')';
255
$this->reset_handshake = true;
258
if(substr($response[0], 0, 2) != 'OK') {
259
$this->error_msg = 'Response Not ok, unknown error'.
260
"\nDebug output:\n".$buffer;
261
$this->reset_handshake = true;
285
269
} // end audioscrobbler class