irc.php 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. <?php
  2. ///////
  3. // IdleIRC - 2020
  4. // (C) Chris Dorman, GPLv3
  5. // https://notabug.org/Pentium44/idleirc
  6. ///////
  7. // irc.php - used to push and pull data from IRC server.
  8. // Currently supports PING / PONG, data receive, and data push
  9. // Done via PHP sockets.
  10. // Prevent PHP from stopping the script after 30 sec
  11. set_time_limit(0);
  12. // Include variables
  13. include_once("config.php");
  14. // Get username from command line argument / PHP-CLI
  15. $username = $argv[1];
  16. $servaddr = $argv[2]; // If server address is specified
  17. $servport = $argv[3]; // If server port is specified
  18. if(file_exists("users/$username.php")) {
  19. include("users/$username.php");
  20. }
  21. $server_address = isset($servaddr) ? $servaddr : $server;
  22. $server_port = isset($servport) ? $servport : $port;
  23. function usernameInMsg($username, $msgString) {
  24. if(strpos($msgString, $username) !== false){
  25. return true;
  26. } else{
  27. return false;
  28. }
  29. }
  30. // Function to search for username
  31. function get_string_between($string, $start, $end){
  32. $string = ' ' . $string;
  33. $ini = strpos($string, $start);
  34. if ($ini == 0) return '';
  35. $ini += strlen($start);
  36. $len = strpos($string, $end, $ini) - $ini;
  37. return substr($string, $ini, $len);
  38. }
  39. // If username isn't set, exit with error.
  40. if(!isset($username) || $username == "") {
  41. echo "Username not given...";
  42. exit(1);
  43. }
  44. // Create a socket to use
  45. $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
  46. // Send first packets to client to inform connection
  47. $socketFileContents = file_get_contents("users/$username.log"); // get current log contents
  48. $msgline = "<tr><td class='userinfo'><span style='color:$ipcolor;'>" . $server_address . "</span> ~ </td><td>Connecting to $server_address:$server_port... please wait a few</td></tr>\n";
  49. file_put_contents("users/$username.log", $socketFileContents . $msgline);
  50. // Connect to IRC server via socket above
  51. socket_connect($socket, $server_address, $server_port);
  52. sleep(2);
  53. // NICK and USER calls to IRC
  54. $nickline = "NICK " . $usernickname . "\n";
  55. $userline = "USER " . $usernickname . " 0 * :" . $username . "'s $title $version client\n";
  56. // Pass NICK and USER back to IRC server over socket
  57. socket_write($socket, $nickline, strlen($nickline));
  58. // Sleep for a second before sending USER lineage
  59. sleep(1);
  60. // SEND IT
  61. socket_write($socket, $userline, strlen($userline));
  62. //sleep(1);
  63. // Continue the rest of the script here
  64. // While script will continue as long as socket continues to be active
  65. while($bytes = socket_recv($socket, $r_data, 2048, MSG_DONTWAIT) !== '') {
  66. if($bytes !== FALSE) {
  67. //$data = socket_read($socket, 2048, PHP_NORMAL_READ);
  68. $packetdata = $r_data;
  69. }
  70. // If client sent something, push it to the IRC server!
  71. if(file_exists("users/.$username.push")) {
  72. // Grab IRC command from server.php
  73. $pushFile = file_get_contents("users/.$username.push");
  74. // Push this / these commands to socket
  75. socket_write($socket, $pushFile, strlen($pushFile));
  76. // Remove the push file
  77. unlink("users/.$username.push");
  78. }
  79. // Check if web client still up, if no pong after 15 seconds, connection closed.
  80. if(!file_exists("users/.$username.pingfile")) { // If file is missing, quit
  81. // Debug logging, check if IRC is exiting properly
  82. doLog("Exiting, $username logged out...");
  83. $quitline = "QUIT :$username toggled disconnect; $title $version\n"; // IRC QUIT line
  84. socket_write($socket, $quitline, strlen($quitline)); // Push to socket
  85. socket_close($socket); // Close the socket
  86. exit(0); // Exit the script, nothing to do.
  87. }
  88. // If data variable is set and buffer has data to recieve
  89. // RECIEVE IT!
  90. if(isset($packetdata)) { // If data variable is set, there's data from socket
  91. //doLog("Server received chunk: $packetdata");
  92. $lines = explode("\r\n", $packetdata);
  93. foreach($lines as $data) {
  94. if($data == "") { continue; }
  95. //doLog("Line: $data");
  96. $socketFileContents = file_get_contents("users/$username.log");
  97. $stringMsg = explode('PRIVMSG', $data); // Strip IRC commands
  98. $ex = explode(' ', $data);
  99. $data = htmlentities($data);
  100. if($ex[1] == "376" || $ex[1] == "366") { continue; }
  101. // Send PONG back to the server
  102. if ($ex[0] == "PING") {
  103. // Log pong
  104. doLog("PONG, $username response...");
  105. $pongline = "PONG " . $ex[1] . "\n"; // PONG IRC CMD
  106. // Push to IRC server via socket.
  107. socket_write($socket, $pongline, strlen($pongline));
  108. } else if ($ex[1] == "353") {
  109. // Userlist has been captured, lets generate it for the client.
  110. // Grabs raw user list
  111. $userlistContent = "<b>" . $ex[4] . "</b><br />";
  112. $userlistRaw = explode($ex[4] . " :", $data);
  113. $userArray = explode(" ", $userlistRaw[1]);
  114. // Generate a list of users, in HTML format for userlist
  115. foreach($userArray as $usi) {
  116. $userlistContent .= "<a onclick='UserPM(\"$usi\");' href='#'>$usi</a> <br />";
  117. }
  118. file_put_contents("users/$username.userlist", $userlistContent);
  119. } else if ($ex[1] == "PART") {
  120. $senderNick = get_string_between($data, ":", "!");
  121. $senderIp = get_string_between($data, "@", " ");
  122. $exitMsg = explode('PART', $data);
  123. $partChannel = explode(' :', $exitMsg[1]);
  124. $msgline = "<tr><td class='userinfo'><b>$senderNick</b>: Leaving<br /><span style='color:$ipcolor;font-size:9px;'>$senderIp</span></td><td> left " . stripslashes(trim($exitMsg[1])) . "</td></tr>";
  125. file_put_contents("users/$username.log", $socketFileContents . $msgline);
  126. file_put_contents("users/.$username.push", "NAMES " . $partChannel[0] . "\n");
  127. } else if ($ex[1] == "JOIN") {
  128. $senderNick = get_string_between($data, ":", "!");
  129. $senderIp = get_string_between($data, "@", " ");
  130. $joinChannel = explode("JOIN :", $data);
  131. if($senderNick != $usernickname) {
  132. $msgline = "<tr><td class='userinfo'><b>$senderNick</b>:" . $joinChannel[1] . "<br /><span style='color:$ipcolor;font-size:9px;'>$senderIp</span></td><td> joined " . $joinChannel[1] . "</td></tr>\n";
  133. file_put_contents("users/$username.log", $socketFileContents . $msgline);
  134. } else {
  135. $msgline = "<tr><td class='userinfo'><span style='color:$ipcolor;'>" . $server_address . "</span> ~ </td><td>Joining " . $joinChannel[1] . "</td></tr>\n";
  136. file_put_contents("users/$username.log", $socketFileContents . $msgline);
  137. }
  138. file_put_contents("users/.$username.push", "NAMES " . $joinChannel[1] . "\n");
  139. } else if ($ex[1] == "NICK") {
  140. $senderNick = get_string_between($data, ":", "!");
  141. $senderIp = get_string_between($data, "@", " ");
  142. $nickMsg = explode('NICK :', $data);
  143. $msgline = "<tr><td class='userinfo'><b>$senderNick</b>:" . trim($nickMsg[1]);
  144. $msgline .= "<br /><span style='color:$ipcolor;font-size:9px;'>$senderIp</span>";
  145. $msgline .= "</td><td> $senderNick is now known as" . trim($nickMsg[1]);
  146. $msgline .= "</td></tr>\n";
  147. file_put_contents("users/$username.log", $socketFileContents . $msgline);
  148. } else if ($ex[1] == "QUIT") {
  149. $senderNick = get_string_between($data, ":", "!");
  150. $senderIp = get_string_between($data, "@", " ");
  151. $quitMsg = explode('QUIT :', $data);
  152. $msgline = "<tr><td class='userinfo'><b>$senderNick</b><br /><span style='color:$ipcolor;font-size:9px;'>$senderIp</span></td><td> $senderNick left: " . trim($quitMsg[1]) . "</td></tr>\n";
  153. file_put_contents("users/$username.log", $socketFileContents . $msgline);
  154. file_put_contents("users/.$username.push", "NAMES");
  155. } else if ($ex[2] == $usernickname && $ex[1] == "PRIVMSG") {
  156. $senderNick = get_string_between($data, ":", "!");
  157. $senderIp = get_string_between($data, "@", " ");
  158. $privMsg = explode($usernickname . " :", $stringMsg[1]);
  159. file_put_contents("users/.$username.pmed", "$senderNick");
  160. $msgline = "<tr><td class='userinfo'>PM from <b>$senderNick</b><br /><span style='color:$ipcolor;font-size:9px;'>$senderIp</span></td><td> " . htmlentities(stripslashes(trim($privMsg[1]))) . "</td></tr>\n";
  161. file_put_contents("users/$username.log", $socketFileContents . $msgline);
  162. $msg = "";
  163. } else if ($stringMsg[1] != "") {
  164. $senderNick = get_string_between($data, ":", "!");
  165. $senderIp = get_string_between($data, "@", " ");
  166. $channel = explode(" :", $stringMsg[1]);
  167. $msg = explode($channel[0] . " :", $stringMsg[1]);
  168. $msgline = "<tr><td class='userinfo'><b>$senderNick</b>:" . $channel[0] . "<br /><span style='color:$ipcolor;font-size:9px;'>$senderIp</span></td><td> " . htmlentities(stripslashes(trim($msg[1]))) . "</td></tr>";
  169. if(usernameInMsg($usernickname, $msg[1])==true) {
  170. file_put_contents("users/.$username.mentioned", "$senderNick");
  171. }
  172. file_put_contents("users/$username.log", $socketFileContents . $msgline);
  173. } else if ($ex[0] == ":$server_address") {
  174. $msgline = "<tr><td class='userinfo'><span style='color:$ipcolor;'>" . $server_address . "</span> ~ </td><td> " . $data . "</td></tr>\n";
  175. file_put_contents("users/$username.log", $socketFileContents . $msgline);
  176. }
  177. }
  178. }
  179. // second sleep to prevent insane CPU load
  180. usleep(250000);
  181. }
  182. ?>