<html>
<head>
<title>Capn's PHP gnutella search<?php if ($query) echo ": $query" ?></title>
<meta name="Keywords" content="gnutella php mp3 divx">
<meta name="Description" content="A web-based (PHP) front-end for searching the gnutella distributed file network">
<?php
/****************************************************************
Copyright (C) 2000, Bryan Mayland created 2000. All rights reserved.
License to copy and use this software is granted provided that it
is identified as the "CapnBry's PHP gnutella search" in all material
mentioning or referencing this software or this function.
License is also granted to make and use derivative works provided
that such works are identified as "derived from CapnBry's PHP gnutella
search" in all material mentioning or referencing the derived work.
Bryan Mayland makes no representations concerning either
the merchantability of this software or the suitability of this
software for any particular purpose. It is provided "as is"
without express or implied warranty of any kind.
These notices must be retained in any copies of any part of this
documentation and/or sofftware.
*******************************************************************/
function printLastSearches()
{
if (!file_exists("last_searches"))
return;
$arFile = file("last_searches", 0);
if (!count($arFile))
return;
echo " <ul>";
for ($i=0; $i<count($arFile); $i+=2)
echo " <li><a href=\"$GLOBALS[PHP_SELF]?query=" .
rawurlencode(substr($arFile[$i], 0, strlen($arFile[$i])-1)).
"&maxresults=10&timeout=60\">$arFile[$i]</a> - ". $arFile[$i+1]. "</li>\n";
echo " </ul>\n";
}
function saveSearch($s)
{
if (!file_exists("last_searches"))
$arFile = array();
else
$arFile = file("last_searches", 0);
$newFile = array_slice($arFile, -18, 18);
array_push($newFile, $s."\n");
if (strlen($GLOBALS[REMOTE_HOST]))
array_push($newFile, $GLOBALS[REMOTE_HOST]."\n");
else
array_push($newFile, $GLOBALS[REMOTE_ADDR]."\n");
$fp = fopen("last_searches", "w");
for ($i=0; $i<count($newFile); $i++)
fputs($fp, $newFile[$i]);
fclose($fp);
}
function commonHeader()
{
?>
</head>
<body link="#FFFF00" vlink="#CCCC00" bgcolor="#000000" text="#FFFFFF" alink="#FFFFFF">
<font face="Arial">
<table width="100%" border="0" cellspacing="0">
<tr>
<td colspan="2">
<img src="pirate.gif" align="center"><font size="+2" color="#FFFFFF">
<b><i>Cap'n Bry's gnutella search</i></b>
</font>
</td?
</tr>
<tr bgcolor="#FFCC00"><td height="2" colspan="2"><img src="/images/1x1.gif"></td></tr>
<form action="gs.php" method="GET">
<tr>
<td colspan="2" valign="center" bgcolor="#000066" height="35">
Search for:
<input type="text" value="<?php echo $GLOBALS[query] ?>" name="query" size="30">
Server timeout
<select name="timeout">
<option value="10"<?php
if ($GLOBALS[timeout] == 10) echo " selected";
?>>10 secs</option>
<option value="30"<?php
if ($GLOBALS[timeout] == 30) echo " selected";
?>>30 secs</option>
<option value="60"<?php
if ((!isset($GLOBALS[timeout]) || $GLOBALS[timeout] == 60)) echo " selected";
?>>60 secs</option>
<option value="90"<?php
if ($GLOBALS[timeout] == 90) echo " selected";
?>>90 secs</option>
</select>
<input type="image" src="search_btn.gif" border=0>
</td>
</tr>
</form>
<tr bgcolor="#FFCC00"><td height="2" colspan="2"><img src="/images/1x1.gif"></td></tr>
</table>
<table width="100%" border=0 cellspacing=0>
<tr>
<td valign="top" width="120">
<font size="-1">
<br>
<img src="arrow.gif" width="6" height="11">
<a href="/gnutella/dl_help.php">Problems downloading?</a><br>
<img src="arrow.gif" width="6" height="11">
<a href="http://gnutella.wego.com">semiofficial gnutella site</a><br>
<img src="arrow.gif" width="6" height="11">
<a href="/gnutella/protocol.html">The protocol</a><br>
<img src="arrow.gif" width="6" height="11">
<a href="/gnutella/ss.php">Screenshots</a><br>
<img src="arrow.gif" width="6" height="11">
<a href="/gnutella/my_ss.php">My clone</a><br>
<img src="arrow.gif" width="6" height="11">
<a href="/gnutella/gs.phps">PHP source</a><br>
<!-- <hr width="80%">
<img src="arrow.gif" width="6" height="11">
<a target="myplay" href="http://tracker.clicktrade.com/tracker/tracker.dll?to='http://www.myplay.com/dd/mp/reg/aff_landing.jsp?sv=023-12-16'&lp=381750&ad=331278">
Store your results at myplay.com, it's free!
<center>
<img src="http://www.myplay.com/corp/affiliate/gifs/mp_affil.gif" border=0>
</center>
</a><br>
-->
</font>
</td>
<td>
<?php
}
function doSearchForm()
{
commonHeader();
?>
<p>Search for any type of file you like. If you're interested in
movies showing people shaving their cats, then search for
"<i>cat shaving avi</i>". If home improvement is more your thing,
try "<i>wood nailing jpg</i>". Queries are space-separated
words, the result must contain all words entered. Searching
for "*.mp3" is the same as searching for "mp3", so save
yourself some typing, and 2 bytes of my bandwidth and use
the latter. Be patient, the gnutellanet is not Yahoo! or
Hotbot-- the first search results usually don't start rolling in
for 15 seconds or so.</p>
<p>Please note that searches are logged by the web server!</p>
<font size="+1"><b>Last 10 searches</b></font>
<?php
printLastSearches();
printCommonFooter();
}
function printCommonFooter()
{
?>
</td>
</tr>
</table>
<table width="100%" border=0 cellspacing=0>
<tr bgcolor="#FFCC00"><td height="2"><img src="/images/1x1.gif"></td></tr>
<tr>
<td>
<a href="mailto:bmayland@leoninedev.SPAM.com">Email CapnBry</a>
<font size="-1"><i>remove spam from the address for it to work</i></font>
</td>
</tr>
<tr>
<td>
<a href="/gnutella/">Back</a>
</td>
</tr>
</table>
</font>
</body>
</html>
<?
}
function openStatusWin()
{
$GLOBALS[status_window_open] = 1;
?>
<script language="JavaScript">
<!--
var winOpts = "width=400,height=250,scrollbars";
sw = window.open("", "Status", winOpts);
if (sw.document == null) {
sw = window.open("", "Status", winOpts);
}
sw.document.open();
sw.bgcolor = "white";
sw.document.write("<code>");
// -->
</script>
<?php
}
function writeToStatusWin($s)
{
if (!$GLOBALS[status_window_open])
return;
?>
<script>
<!--
if (!sw.closed) { sw.document.write("<?php echo $s ?>"); }
// -->
</script>
<?php
flush();
}
function closeStatusWin()
{
if (!$GLOBALS[status_window_open])
return;
$GLOBALS[status_window_open] = 0;
?>
<script language="JavaScript">
<!--
if (!sw.closed) { sw.close(); }
// -->
</script>
<?php
}
function getByte($fp)
{
return ord(fread($fp, 1));
}
function getWord($fp)
{
$buff = fread($fp, 2);
return ord($buff[0]) | (ord($buff[1]) << 8);
}
function getInt($fp)
{
$buff = fread($fp, 4);
return ord($buff[0]) | (ord($buff[1]) << 8) |
(ord($buff[2]) << 16) | (ord($buff[3]) << 24);
}
function getIP($fp)
{
$buff = fread($fp, 4);
return ord($buff[0]).".".ord($buff[1]).".".ord($buff[2]).".".ord($buff[3]);
}
function getLPSZ($fp)
{
$result = "";
while (($c = fread($fp, 1)) != "\x00") {
$result = $result . $c;
}
return $result;
}
function sizeToStr($size)
{
if ($size > 1048576)
return sprintf("%.1f MB", (float)$size / 1048576.0);
if ($size > 1024)
return sprintf("%.1f KB", (float)$size / 1024.0);
else
return $size. " bytes";
}
function randomBanner()
{
echo "<center>\n";
switch (rand(0, 2)) {
case 0: ?>
<a target="myplay" href="http://tracker.clicktrade.com/tracker/tracker.dll?to='http://www.myplay.com/dd/mp/reg/aff_landing.jsp?sv=023-01-590'&lp=381750&ad=331278">
<img src="http://www.myplay.com/corp/affiliate/gifs/ssl-eq-468x60a.gif" border=0>
</a>
<?php break;
case 1: ?>
<a target="myplay" href="http://tracker.clicktrade.com/tracker/tracker.dll?to='http://www.myplay.com/dd/mp/reg/aff_landing.jsp?sv=023-01-589'&lp=381750&ad=331278">
<img src="http://www.myplay.com/corp/affiliate/gifs/3g-lckr-468x60c.gif" border=0>
</a>
<?php break;
case 2: ?>
<a target="myplay" href="http://tracker.clicktrade.com/tracker/tracker.dll?to='http://www.myplay.com/dd/mp/reg/aff_landing.jsp?sv=023-01-03'&lp=381750&ad=331278">
<img src="http://www.myplay.com/corp/affiliate/gifs/old-468x60.gif" border=0>
</a>
<?php break;
}
echo "</center>\n";
}
function QueryResponseDataAvail($fp, $datasize)
{
$numrecs = getByte($fp);
$port = getWord($fp);
$ip = getIP($fp);
$speed = getInt($fp);
// echo "<ul>\n";
// echo "<li>Numrecs: $numrecs</li>\n";
// echo "<li>Host port: $port</li>\n";
// echo "<li>Host IP: $ip</li>\n";
// echo "<li>Host speed: $speed kbps</li>\n";
// echo "<ul>\n";
if ((substr($ip, 0, 8) == "192.168.") || (substr($ip, 0, 3) == "10.")) {
writeToStatusWin("Query response, but on private net: $ip");
return;
}
$GLOBALS[results_found]++;
if ($GLOBALS[status_window_open]) {
closeStatusWin();
// randomBanner();
commonHeader();
}
?>
<table border="0" width="100%">
<tr>
<td bgcolor="#000066" colspan="3"><font color="#FFFFFF" size="+1">
Host is <b><?php
if ($GLOBALS[connectok])
echo "$ip:$port";
else
echo "gnutella";
?></b> running at <b><?php echo $speed ?></b>
kbps (<b><?php echo $numrecs ?></b> records)
</font></td>
</tr>
<tr bgcolor="#660000">
<!-- <td align="center">myplay.com</td> -->
<td>File name</td>
<td align="right" nowrap>Size</td>
</tr>
<?php
for ($i=0; $i<$numrecs; $i++) {
$fileidx = getInt($fp);
$filesize = getInt($fp);
$filename = getLPSZ($fp);
$fileurl = "http://$ip:$port/get/$fileidx/" . rawurlencode($filename);
if ($i % 2)
echo " <tr>\n";
else
echo " <tr bgcolor=\"#333333\">\n";
// echo " <td align=\"center\">";
// echo "<a target=\"myplay\" href=\"http://tracker.clicktrade.com/tracker/tracker.dll?to='http://www.myplay.com/dd/mp/?rurl=".
// $fileurl. "&sv=023-04-08'&lp=381750&ad=331278\">";
// echo "<img src=\"http://www.myplay.com/corp/affiliate/gifs/add_locker.gif\" ".
// "border=0 height=15 width=52></a></td>\n";
echo " <td><a href=\"";
if ($GLOBALS[connectok])
echo $fileurl;
else
echo "no_download.php?filename=" . rawurlencode($filename);
echo "\">$filename</a></td>\n";
echo " <td align=\"right\" nowrap>". sizeToStr($filesize). "</td>\n";
// echo " <td>$fileidx</td>\n";
echo " </tr>\n";
// there's an extra nullbyte on the end
fread($fp, 1);
}
// echo " <tr>\n";
// echo " <td colspan=\"2\">ClientID128: <b>". bin2Hex(fread($fp, 16)). "</b></td></tr>\n";
echo " <tr bgcolor=\"#FFFFFF\">\n";
echo " <td colspan=\"3\" align=\"center\">".
"<font color=\"#FF0000\"><b>Support the gnutella network! ".
"<a href=\"http://gnutella.wego.com/\">Run a server!</a></b></font>\n";
echo " </td></tr>\n";
echo " </table>\n";
}
function CoCreateGUID()
{
srand((double)microtime()*1000000);
$t = (string)rand() . bin2hex(microtime());
return substr($t, 1, 16);
}
function onShutdown()
{
fclose($GLOBALS[fp]);
printCommonFooter();
}
function IsValidGnutellaHeader($sin)
{
GLOBAL $datasize;
$datasize = ord($sin[19]) | (ord($sin[20]) << 8) |
(ord($sin[21]) << 16) | (ord($sin[22]) <<24);
return
((ord($sin[16]) == 0x00) && ($datasize == 0)) || // Inits always have 0 len
((ord($sin[16]) == 0x01) && ($datasize == 14)) || // Init resp 14
((ord($sin[16]) == 0x40) && ($datasize == 26)) || // Push req 26
(
((ord($sin[16]) == 0x80) || (ord($sin[16]) == 0x81)) &&
(($datasize < 5000) && ($datasize > 0))
);
}
function messageIn($stype)
{
GLOBAL $messages_in;
GLOBAL $MsgDataStr;
if (!$messages_in)
writetoStatusWin("Legend: <b>p</b>-ping <b>P</b>-pong ".
"<b>U</b>-push req <b>q</b>-query<br>");
$messages_in++;
if ($messages_in % 30)
$MsgDataStr = $MsgDataStr. $stype;
else {
writeToStatusWin($MsgDataStr. "<br>");
$MsgDataStr = "MsgData: ";
}
}
function doHostDown()
{
commonHeader();
?>
<h2>Gnutella Server Down?!?</h2>
<p>Shock of all shocks, then machine <?php echo $GLOBALS[host] ?>
is not up. Could it be that Windows 2000 has completely locked
up <b>again</b>? Could it be that the magic paperclip that is
usually is wedged in the switch has fallen out again? What is
the answer to life the universe and everything?
Try your search again in a few minutes.</p>
<?php
printCommonFooter();
}
function doHostRefused()
{
commonHeader();
?>
<h2>Connection Refused!</h2>
<p>For some reason, the host <?php echo $GLOBALS[host] ?> is refusing
the incoming gnutella connection. This is usually because I'm
rebooting the server. Try your search again in a few minutes.</p>
<?php
printCommonFooter();
}
/*
if (!$do)
{
?>
</head>
<body>
Temporarily down for script coding. Try back around 8:30 EST<br>
-- Bry<br>
</body>
</html>
<?php
exit;
}
*/
$status_window_open = 0;
if (!$query) {
doSearchForm();
exit;
}
if (!$maxresults)
$maxresults = 10;
else if ($maxresults > 50)
$maxresults = 50;
if (!$host)
$host = "192.168.100.74";
// $host = "127.0.0.1";
if (!$port)
$port = 22674;
// $port = 6346;
if (!$timeout)
$timeout = 30;
else if ($timeout > 60)
$timeout = 60;
// Allow direct download from this page
$connectok = 1;
if (!isset($connectok))
$connectok = 0;
openStatusWin();
writeToStatusWin("Saving search request...<br>");
saveSearch($query);
writeToStatusWin("Connecting to ".$host.":".$port."<br>");
$fp = fsockopen($host, $port, &$errno, &$errstr, 10);
if (!$fp) {
closeStatusWin();
switch ($errno) {
case 110:
doHostDown(); break;
case 111:
doHostRefused(); break;
default:
echo "Could not connect to $host:$port<br>\n";
echo "($errno) $errstr\n";
}
} else {
writeToStatusWin("Connected, initializing protocol...<br>");
register_shutdown_function("onShutdown");
fputs($fp, "GNUTELLA CONNECT/0.4\n\n");
$resp = fread($fp, 13);
if ($resp != "GNUTELLA OK\n\n") {
closeStatusWin();
echo "Was not a gnutella server\n";
} else {
$q_len = strlen($query);
$p_len = $q_len + 3;
$search = CoCreateGUID().
"\x80". // type = query
"\x05". // TTL = 5
"\x00". // HopCount = 0
chr($p_len & 0xff).
chr(($p_len & 0xff00) >> 8).
chr(($p_len & 0xff0000) >> 16).
chr(($p_len & 0xff000000) >> 24).
"\x00\x00". // Min Speed = 0
$query."\x00";
writeToStatusWin("Sending search request '".$query."'...<br>");
fwrite($fp, $search, 23 + $p_len);
$results_found = 0;
$messages_in = 0;
$MsgDataStr = "MsgData: ";
$sin = "";
$iStartTime = time();
while ($results_found < $maxresults) {
set_socket_blocking($fp, false);
while ((strlen($sin) < 23) && ($iStartTime + $timeout > time())) {
$spart = fread($fp, 23 - strlen($sin));
if (strlen($spart))
$sin = $sin . $spart;
else
usleep(250000);
}
set_socket_blocking($fp, true);
if (strlen($sin) < 23) {
if ($status_window_open) {
closeStatusWin();
commonHeader();
}
// echo "<tr><td colspan=\"2\">\n";
echo "Query timed out ($timeout secs). ";
echo "This usually indicates that there are no more search results\n";
echo "but might also mean that the gnutellanet is getting hammered.\n";
// echo "</td></tr>";
break;
}
// echo bin2hex($sin);
// echo "<br>\n";
if (!IsValidGnutellaHeader($sin)) {
// closeStatusWin();
// echo "Bogus packet received from gnutella, size=$datasize, type=0x".
// bin2hex($sin[16])."\n";
$sin = substr($sin, 1, 22);
continue;
}
switch (ord($sin[16])) {
case 0x00:
messageIn("p");
break;
case 0x01:
messageIn("P");
$sin = fread($fp, $datasize);
break;
case 0x40:
messageIn("U");
$sin = fread($fp, $datasize);
break;
case 0x80:
messageIn("Q");
$sin = fread($fp, $datasize);
break;
case 0x81;
QueryResponseDataAvail($fp, $datasize);
break;
} // switch
flush();
$sin = "";
}
}
onShutdown();
} // could connect
?>