<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], 0strlen($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, -1818);
  
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($fp1));
}

function 
getWord($fp)
{
  
$buff fread($fp2);
  return 
ord($buff[0]) | (ord($buff[1]) << 8);
}

function 
getInt($fp)
{
  
$buff fread($fp4);
  return 
ord($buff[0]) | (ord($buff[1]) << 8) |
    (
ord($buff[2]) << 16) | (ord($buff[3]) << 24);
}

function 
getIP($fp)
{
  
$buff fread($fp4);
  return 
ord($buff[0]).".".ord($buff[1]).".".ord($buff[2]).".".ord($buff[3]);
}

function 
getLPSZ($fp)
{
  
$result "";
  while ((
$c fread($fp1)) != "\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(02))  {
    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($ip08) == "192.168.") || (substr($ip03) == "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($fp1);
  }

  
// 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($t116);
}

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, &$errstr10);

  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($fp13);
    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$search23 $p_len);

      
$results_found 0;
      
$messages_in 0;
      
$MsgDataStr "MsgData: ";
      
$sin "";
      
$iStartTime time();
      while (
$results_found $maxresults)  {
        
set_socket_blocking($fpfalse);
        while ((
strlen($sin) < 23) && ($iStartTime $timeout time())) {
          
$spart fread($fp23 strlen($sin));
          if (
strlen($spart))
            
$sin $sin $spart;
          else
            
usleep(250000);
        }
        
set_socket_blocking($fptrue);

        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($sin122);
          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
?>