<?php
  
if (!isset($query))
    
setCookie("LastVisit"time(), time()+31536000"/gnutella/"); ?>
<html>
<head>
  <title>Capn's PHP gnutella search<?php if (isset($query)) echo ": $query?></title>
  <meta name="Keywords" content="gnutella php">
  <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.
*******************************************************************/

require 'sick.php';   // if you are copying this code for use on your site,
                      // comment out the require 'sick.php'
require 'gs_config.php';
require 
'top_n_bottom.php';
require 
'status_window.php';
require 
'error_msgs.php';
require 
'search_history.php';
require 
'byte_funcs.php';

function 
GWD(&$array$key$default NULL)
{
  return (isset(
$array[$key])) ? $array[$key] : $default;
}

function 
doSearchForm()
{                                  
  
commonHeader();
  require 
'index_text.php';
  
// echo "    <font size=\"+1\"><b>Last 10 searches</b></font>\n";
  // searchPrintLast(10);
  
LastUpdates();
  
commonFooter();
}

function 
lastUpdate($filename$desc)
{
  if (
$desc)
    echo 
"      <li><a href=\"$filename\">$desc</a> - <font size=\"-1\">";
  else
    echo 
"      <font size=\"-1\">";
  
$ftime filemtime($filename);
  echo 
date("l, F dS Y h:i:s A"$ftime);
  if (
$ftime GWD($GLOBALS,'LastVisit',0))
    echo 
" - <font color=\"#ff0000\"><b>NEW</b></font>!";
  if (
$desc)
    echo 
"</font></li>\n";
  else
    echo 
"</font>\n";
}

function 
LastUpdates()
{
  
  echo 
"    <font size=\"+1\"><b>Latest updates</b></font> <font size=\"-1\">(since ";
  echo 
date("l, F dS Y h:i:s A"$GLOBALS['LastVisit']). ")</font>\n";
  echo 
"    <ul>\n";
  
lastUpdate("gs_source.php""PHP Source Code");
  echo 
"      <ul>\n";
  
lastUpdate("gs.phps""gs.php");
  
lastUpdate("gs_config.phps""gs_config.php");
  
lastUpdate("top_n_bottom.phps""top_n_bottom.php");
  
lastUpdate("status_window.phps""status_window.php");
  
lastUpdate("error_msgs.phps""error_msgs.php");
  
lastUpdate("byte_funcs.phps""byte_funcs.php");
  
lastUpdate("search_history.phps""search_history.php");
  
lastUpdate("gs_mysql.sql""gs_mysql.sql");
  
lastUpdate("gs_old.phps""gs_old.php");
  
lastUpdate("links.phps""links.php");
  echo 
"      </ul>\n";
  
lastUpdate("my_client.php""My Clone");
  echo 
"      <ul>\n";
  
lastUpdate("gnutellatrans.html""gnutellatrans.pas");
  
lastUpdate("src.zip""Source zipball");
  echo 
"      </ul>\n";
  
lastUpdate("protocol.php""Gnutella Protocol Reference");
  
lastUpdate("dl_help.php""Downloading Help");
  echo 
"    </ul>\n";
}

function 
QueryResponseDataAvail($fp$datasize)
{
  
$numrecs getByte($fp);
  
$port getWord($fp);
  
$ip getIP($fp);
  
$speed getInt($fp);

  if ((
substr($ip08) == "192.168.") || (substr($ip03) == "10."))  {
    
statusWinWrite("Query response on private net: $ip");
    return;
  }

  
$GLOBALS[result_hosts]++;
  
$GLOBALS[result_files] += $numrecs;

  if (
$GLOBALS[status_window_open])  {
    
statusWinClose();
    
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><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 
onShutdown()
{
  global 
$fp$result_hosts$result_files$messages_in;

  
fclose($fp);
  
searchSaveResults($result_hosts$result_files$messages_in);
  
commonFooter();
}

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)
    
statusWinWrite("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  {
    
statusWinWrite($MsgDataStr"<br>");
    
$MsgDataStr "MsgData: ";
  }
}

  
error_reporting(E_ALL & ~E_NOTICE & ~E_WARNING);

  
$query $_REQUEST["query"];
  
$timeout $_REQUEST["timeout"];
  
$maxresults $_REQUEST["maxresults"];

  
$status_window_open 0;

  if (!
$query)  {
    
doSearchForm();
    exit;
  }
  if (!
$maxresults)
    
$maxresults 10;
  else if (
$maxresults 50)
    
$maxresults 50;
  if (!
$timeout)
    
$timeout 30;
  else if (
$timeout 60)
    
$timeout 60;

    
// Allow direct download from this page
  
$connectok 1;
  if (!isset(
$connectok))
    
$connectok 0;

  
statusWinOpen();
  
statusWinWrite("Saving search request...<br>");
  
searchSaveQuery($query);

  while (list(
$gnutella_host$gnutella_port) = each($gnutella_server_list)) {
    
statusWinWrite("Connecting to ".$gnutella_host.":".$gnutella_port."<br>");
   
    
// BRY: This code removed on account of call-time pass-by-reference
    // being removed from PHP. This code won't work without it 
    
$fp 0//@fsockopen($gnutella_host, $gnutella_port, &$errno, &$errstr, 10);
    
if ($fp)
      break;
  }

  if (!
$fp)  {
    
statusWinClose();
    switch (
$errno) {
      case 
110:
          
doHostDown($query); break;
      case 
111:
          
doHostRefused($query); break;
      default:
        echo 
"Could not connect to $gnutella_host:$gnutella_port<br>\n";
        echo 
"($errno$errstr\n";
      }
  } else {
    
statusWinWrite("Connected, initializing protocol...<br>");

    
fputs($fp"GNUTELLA CONNECT/0.4\n\n");
    
$resp fread($fp13);
    if (
$resp != "GNUTELLA OK\n\n")  {
      
statusWinClose();
      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";
      
statusWinWrite("Sending search request '".$query."'...<br>");
      
fwrite($fp$search23 $p_len);

      
$result_hosts 0;
      
$result_files 0;
      
$messages_in 0;
      
$MsgDataStr "MsgData: ";
      
$sin "";
      
$iStartTime time();
      while (
$result_hosts $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(1000000);
        }
        
set_socket_blocking($fptrue);

        if (
strlen($sin) < 23)  {
          if (
$status_window_open)  {
            
statusWinClose();
            
commonHeader();
          }
          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";
          break;
        }

        if (!
IsValidGnutellaHeader($sin))  {
          
// statusWinClose();
          // 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
?>