#!/usr/bin/perl # # This software may be used and distributed according to the terms # of the GNU Public License, incorporated herein by reference # # MyNapster WebClient copyright 2000 # info@mynapster.com # # You are welcome to modify and distribute this code package Napster; use IO::Socket; use FileHandle; use CGI; ##use LWP::Simple; use strict; sub new { my $class = $_[0]; bless { nick => $_[1], pass => $_[2], socket => "" }, $class; } ##sub get_servers_list ##{ ## my $content = get('http://www.napigator.com/servers.php?version=105'); ## my @servers = split /\n/, $content; ## return @servers; ##} sub register_new_user { my ($object, $new_nick, $new_pass, $new_email) = @_; my ($type, $msg, $response, $ip, $port, $socket); $socket = IO::Socket::INET->new(PeerAddr => "server.napster.com", PeerPort => 8875, Type => SOCK_STREAM, Timeout => 15) or return (-1, -1); $response = <$socket>; ($ip, $port) = split ":" , $response; close($socket); $socket = IO::Socket::INET->new(PeerAddr => $ip, PeerPort => $port, Type => SOCK_STREAM, Timeout => 15) or return (-2,-2); $socket->autoflush(1); unless(_sendpacket($socket, 7, $new_nick)) { close($socket); return (-3, -3); }; ($type, $msg) = _recvpacket($socket); if ($type == 8) { $msg = sprintf("%s %s %d \"%s\" %d %s", $new_nick, $new_pass, 9002, "v2.0 BETA 6", 10, $new_email); unless(_sendpacket($socket, 6, $msg)) { close($socket); return (-4, -4); }; ($type, $msg) = _recvpacket($socket); }; close($socket); return $type, $msg; } sub connect { my ($type, $msg, $response, $ip, $port, $socket); if (@_ == 1) { $socket = $_[0]->{socket}; $socket = IO::Socket::INET->new(PeerAddr => "server.napster.com", PeerPort => 8875, Type => SOCK_STREAM, Timeout => 15) or return (-1,-1); $response = <$socket>; ($ip, $port) = split ":" , $response; close($socket); } else { $ip = $_[1]; $port = $_[2]; }; $_[0]->{socket} = IO::Socket::INET->new(PeerAddr => $ip, PeerPort => $port, Type => SOCK_STREAM, Timeout => 15) or return (-1,-1); $_[0]->{socket}->autoflush(1); $msg = sprintf("%s %s %d \"%s\" %d", $_[0]->{nick}, $_[0]->{pass}, 9002, "v2.0 BETA 5", 10); unless(_sendpacket($_[0]->{socket}, 2, $msg)) { close($_[0]->{socket}); return (-1,-1); }; ($type, $msg) = _recvpacket($_[0]->{socket}); if ($type == 3) { return ($ip, $port); } else { return (-1,-1); }; } sub disconnect { close($_[0]->{socket}); } sub search { my %songs; my ($msg, $type); my ($object, %arg) = @_; $msg = sprintf("%s \"%s\" %s %d", 'FILENAME CONTAINS', $arg{FILENAME}, 'MAX_RESULTS', $arg{MAX_RESULTS}); unless(_sendpacket($object->{socket}, 200, $msg)) { return; }; do { ($type, $_) = _recvpacket($object->{socket}); } until (($type == 201) or ($type == 202)); if ($type == 202) { return; }; do { if ($type == 201) { s/(".*")//; $songs{$1} = $_; ($type, $_) = _recvpacket($object->{socket}); }; } until ($type == 202); return %songs; } sub get_song { my ($msg, $type, $ip, $port, $client_socket, $buf, $server, $dtype); my ($object, $song, $nick, $size) = @_; my $filename = (split(/\\/, $song))[-1]; $filename =~ s/"//g; $msg = sprintf("%s %s", $nick, $song); unless(_sendpacket($object->{socket}, 203, $msg)) { close($object->{socket}); return -203; }; do { ($type, $_) = _recvpacket($object->{socket}); if (($type != 214) and ($type != 621) and ($type != 204)) { close($object->{socket}); return -$type; }; } until ($type == 204); ($nick, $ip, $port) = split; $ip = inet_ntoa pack "L", $ip; if ($port != 0) { $dtype = 0; $client_socket = IO::Socket::INET->new(PeerAddr => $ip, PeerPort => $port, Type => SOCK_STREAM, Timeout => 60) or return -1; unless ($client_socket->sysread($buf, 1) == 1) { close($object->{socket}); close($client_socket); return -2; } unless ($buf eq '1') { close($object->{socket}); close($client_socket); return -3; } unless ($client_socket->syswrite("GET", 3) == 3) { close($object->{socket}); close($client_socket); return -4; } $buf = sprintf "%s %s %d", $_[0]->{nick}, $song, 0; unless ($client_socket->syswrite($buf, length $buf)) { close($object->{socket}); close($client_socket); return -5; } unless ($client_socket->sysread($size, 1024) && $size =~ /^\d+$/) { close($object->{socket}); close($client_socket); return -6; } my $buf; print "Content-type: music/mp3\n", "Content-Disposition: attachment; filename=$filename\n\n"; while ($size > 0) { unless ($client_socket->sysread($buf, 10240)) { close($object->{socket}); close($client_socket); return -7; } $size -= length $buf; print $buf; } } else { $port = 9001; $dtype = 1; while (!($server)) { $server = IO::Socket::INET->new(LocalPort => $port, Type => SOCK_STREAM, Reuse => 1, Listen => 1 ) or $port = $port + 1; if ($port > 9100) { return (-$port); }; }; $msg = sprintf("%s %s", $nick, $song); unless(_sendpacket($object->{socket}, 500, $msg)) { close($object->{socket}); close($server); return -8; }; $client_socket = $server->accept(); unless ($client_socket->syswrite("1", 1) == 1) { close($object->{socket}); close($client_socket); close($server); return -9; } unless ($client_socket->sysread($buf, 4) == 4 && $buf eq 'SEND') { close($client_socket); return -91; } unless ($client_socket->sysread($buf, 2048)) { close($object->{socket}); close($client_socket); close($server); return -10; } my $buf; unless ($client_socket->syswrite(0, 1) == 1) { close($object->{socket}); close($server); close($client_socket); return -11; } print "Content-type: music/mp3\n", "Content-Disposition: attachment; filename=$filename\n\n"; while ($size > 0) { unless ($client_socket->sysread($buf, 10240)) { close($client_socket); close($server); return -12; } $size -= length $buf; print $buf; } close($server); }; close($object->{socket}); close($client_socket); return $dtype; } sub _sendpacket { my ($socket, $type, $msg) = @_; my $header = pack("vv", length $msg, $type); unless($socket->syswrite($header, 4)) { return; }; unless($socket->syswrite($msg, length $msg)) { return; }; } sub _recvpacket { my $socket = shift; my ($header, $msg); unless($socket->sysread($header, 4)) { return; }; my ($len, $type) = unpack("vv", $header); return ($type, $msg) if $len == 0; until (defined $msg && length $msg == $len) { my $msg_len = defined $msg ? length $msg : 0; unless($socket->sysread($msg, ($len - $msg_len), $msg_len)) { return; }; } return ($type, $msg); } 1;