PageRenderTime 79ms CodeModel.GetById 12ms RepoModel.GetById 1ms app.codeStats 0ms

/hphp/test/zend/good/ext/ftp/tests/server.inc

http://github.com/facebook/hiphop-php
PHP | 428 lines | 364 code | 61 blank | 3 comment | 46 complexity | 21cb129a1aca20c59f48f66cb4fa47ce MD5 | raw file
Possible License(s): LGPL-2.1, BSD-2-Clause, BSD-3-Clause, MPL-2.0-no-copyleft-exception, MIT, LGPL-2.0, Apache-2.0
  1. <?php
  2. $socket = null;
  3. $errno = 0;
  4. $context = stream_context_create(array('ssl' => array('local_cert' => dirname(__FILE__).'/cert.pem', 'passphrase' => 'pass')));
  5. for ($i=0; $i<100 && !$socket; ++$i) {
  6. $port = rand(1025, 65535);
  7. $socket = @stream_socket_server("tcp://127.0.0.1:$port", $errno, $errstr, STREAM_SERVER_BIND|STREAM_SERVER_LISTEN, $context);
  8. }
  9. //set anther random port that is not the same as $port
  10. do{
  11. $pasv_port = rand(1025, 65535);
  12. }while($pasv_port == $port);
  13. if (!$socket) {
  14. die("could not start/bind the ftp server\n");
  15. }
  16. $pid = pcntl_fork();
  17. function pasv_listen($action){
  18. global $pasv_port, $tmp_file;
  19. $tmp_file = 'nm2.php';
  20. $pid = pcntl_fork();
  21. if($pid === 0){
  22. $soc = @stream_socket_server("tcp://127.0.0.1:$pasv_port");
  23. $fs = stream_socket_accept($soc, 3);
  24. switch ($action) {
  25. case 'fget':
  26. case 'get':
  27. //listen for 3 seconds 3 seconds
  28. fputs($fs, "I am passive.\r\n");
  29. break;
  30. case 'put':
  31. file_put_contents($tmp_file, stream_get_contents($fs));
  32. break;
  33. case 'list':
  34. fputs($fs, "drwxr-x--- 3 owner group 4096 Jul 12 12:16 .\r\n");
  35. fputs($fs, "drwxr-x--- 3 owner group 4096 Jul 12 12:16 ..\r\n");
  36. fputs($fs, "drwxr-x--- 3 owner group 4096 Jul 12 12:16 public_ftp\r\n");
  37. break;
  38. case 'list_null':
  39. fputs($fs, "\r\n");
  40. break;
  41. }
  42. fclose($fs);
  43. exit;
  44. }
  45. }
  46. if ($pid) {
  47. function dump_and_exit($buf)
  48. {
  49. var_dump($buf);
  50. fclose($GLOBALS['s']);
  51. exit;
  52. }
  53. function anonymous()
  54. {
  55. return $GLOBALS['user'] === 'anonymous';
  56. }
  57. /* quick&dirty realpath() like function */
  58. function change_dir($dir)
  59. {
  60. global $cwd;
  61. if ($dir[0] == '/') {
  62. $cwd = $dir;
  63. return;
  64. }
  65. $cwd = "$cwd/$dir";
  66. do {
  67. $old = $cwd;
  68. $cwd = preg_replace('@/?[^/]+/\.\.@', '', $cwd);
  69. } while ($old != $cwd);
  70. $cwd = strtr($cwd, array('//' => '/'));
  71. if (!$cwd) $cwd = '/';
  72. }
  73. $s = stream_socket_accept($socket);
  74. if (!$s) die("Error accepting a new connection\n");
  75. fputs($s, "220----- PHP FTP server 0.3 -----\r\n220 Service ready\r\n");
  76. $buf = fread($s, 2048);
  77. function user_auth($buf) {
  78. global $user, $s, $ssl, $bug37799;
  79. if (!empty($ssl)) {
  80. if ($buf !== "AUTH TLS\r\n") {
  81. fputs($s, "500 Syntax error, command unrecognized.\r\n");
  82. dump_and_exit($buf);
  83. }
  84. if (empty($bug37799)) {
  85. fputs($s, "234 auth type accepted\r\n");
  86. } else {
  87. fputs($s, "666 dummy\r\n");
  88. fputs($s, "666 bogus msg\r\n");
  89. exit;
  90. }
  91. if (!stream_socket_enable_crypto($s, true, STREAM_CRYPTO_METHOD_SSLv23_SERVER)) {
  92. die("SSLv23 handshake failed.\n");
  93. }
  94. if (!preg_match('/^PBSZ \d+\r\n$/', $buf = fread($s, 2048))) {
  95. fputs($s, "501 bogus data\r\n");
  96. dump_and_exit($buf);
  97. }
  98. fputs($s, "200 OK\r\n");
  99. $buf = fread($s, 2048);
  100. if ($buf !== "PROT P\r\n") {
  101. fputs($s, "504 Wrong protection.\r\n");
  102. dump_and_exit($buf);
  103. }
  104. fputs($s, "200 OK\r\n");
  105. $buf = fread($s, 2048);
  106. }
  107. if (!preg_match('/^USER (\w+)\r\n$/', $buf, $m)) {
  108. fputs($s, "500 Syntax error, command unrecognized.\r\n");
  109. dump_and_exit($buf);
  110. }
  111. $user = $m[1];
  112. if ($user !== 'user' && $user !== 'anonymous') {
  113. fputs($s, "530 Not logged in.\r\n");
  114. fclose($s);
  115. exit;
  116. }
  117. if (anonymous()) {
  118. fputs($s, "230 Anonymous user logged in\r\n");
  119. } else {
  120. fputs($s, "331 User name ok, need password\r\n");
  121. if (!preg_match('/^PASS (\w+)\r\n$/', $buf = fread($s, 100), $m)) {
  122. fputs($s, "500 Syntax error, command unrecognized.\r\n");
  123. dump_and_exit($buf);
  124. }
  125. $pass = $m[1];
  126. if ($pass === 'pass') {
  127. fputs($s, "230 User logged in\r\n");
  128. } else {
  129. fputs($s, "530 Not logged in.\r\n");
  130. fclose($s);
  131. exit;
  132. }
  133. }
  134. }
  135. user_auth($buf);
  136. $cwd = '/';
  137. $num_bogus_cmds = 0;
  138. while($buf = fread($s, 4098)) {
  139. if (!empty($bogus)) {
  140. fputs($s, "502 Command not implemented (".$num_bogus_cmds++.").\r\n");
  141. } else if ($buf === "HELP\r\n") {
  142. fputs($s, "214-There is help available for the following commands:\r\n");
  143. fputs($s, " USER\r\n");
  144. fputs($s, " HELP\r\n");
  145. fputs($s, "214 end of list\r\n");
  146. } elseif ($buf === "HELP HELP\r\n") {
  147. fputs($s, "214 Syntax: HELP [<SP> <string>] <CRLF>\r\n");
  148. } elseif ($buf === "PWD\r\n") {
  149. fputs($s, "257 \"$cwd\" is current directory.\r\n");
  150. } elseif ($buf === "CDUP\r\n") {
  151. change_dir('..');
  152. fputs($s, "250 CDUP command successful.\r\n");
  153. } elseif ($buf === "SYST\r\n") {
  154. if (isset($bug27809)) {
  155. fputs($s, "215 OS/400 is the remote operating system. The TCP/IP version is \"V5R2M0\"\r\n");
  156. } else {
  157. fputs($s, "215 UNIX Type: L8.\r\n");
  158. }
  159. } elseif ($buf === "TYPE A\r\n") {
  160. $ascii = true;
  161. fputs($s, "200 OK\r\n");
  162. } elseif ($buf === "TYPE I\r\n") {
  163. $ascii = false;
  164. fputs($s, "200 OK\r\n");
  165. } elseif ($buf === "QUIT\r\n") {
  166. break;
  167. } elseif (preg_match("~^PORT (\d+),(\d+),(\d+),(\d+),(\d+),(\d+)\r\n$~", $buf, $m)) {
  168. $host = "$m[1].$m[2].$m[3].$m[4]";
  169. $port = ((int)$m[5] << 8) + (int)$m[6];
  170. fputs($s, "200 OK.\r\n");
  171. } elseif (preg_match("~^STOR ([\w/.-]+)\r\n$~", $buf, $m)) {
  172. fputs($s, "150 File status okay; about to open data connection\r\n");
  173. if(empty($pasv))
  174. {
  175. if (!$fs = stream_socket_client("tcp://$host:$port")) {
  176. fputs($s, "425 Can't open data connection\r\n");
  177. continue;
  178. }
  179. $data = stream_get_contents($fs);
  180. $orig = file_get_contents(dirname(__FILE__).'/'.$m[1]);
  181. if (isset($ascii) && !$ascii && $orig === $data) {
  182. fputs($s, "226 Closing data Connection.\r\n");
  183. } elseif ((!empty($ascii) || isset($bug39583)) && $data === strtr($orig, array("\r\n" => "\n", "\r" => "\n", "\n" => "\r\n"))) {
  184. fputs($s, "226 Closing data Connection.\r\n");
  185. } else {
  186. var_dump($data);
  187. var_dump($orig);
  188. fputs($s, "552 Requested file action aborted.\r\n");
  189. }
  190. fclose($fs);
  191. }else{
  192. $data = file_get_contents('nm2.php');
  193. $orig = file_get_contents(dirname(__FILE__).'/'.$m[1]);
  194. if ( $orig === $data) {
  195. fputs($s, "226 Closing data Connection.\r\n");
  196. } else {
  197. var_dump($data);
  198. var_dump($orig);
  199. fputs($s, "552 Requested file action aborted.\r\n");
  200. }
  201. }
  202. } elseif (preg_match("~^CWD ([A-Za-z./]+)\r\n$~", $buf, $m)) {
  203. change_dir($m[1]);
  204. fputs($s, "250 CWD command successful.\r\n");
  205. } elseif (preg_match("~^NLST(?: ([A-Za-z./]+))?\r\n$~", $buf, $m)) {
  206. if (isset($m[1]) && $m[1] === 'bogusdir') {
  207. fputs($s, "250 $m[1]: No such file or directory\r\n");
  208. continue;
  209. }
  210. // there are some servers that don't open the ftp-data socket if there's nothing to send
  211. if (isset($bug39458) && isset($m[1]) && $m[1] === 'emptydir') {
  212. fputs($s, "226 Transfer complete.\r\n");
  213. continue;
  214. }
  215. fputs($s, "150 File status okay; about to open data connection\r\n");
  216. if (!$fs = stream_socket_client("tcp://$host:$port")) {
  217. fputs($s, "425 Can't open data connection\r\n");
  218. continue;
  219. }
  220. if (empty($m[1]) || $m[1] !== 'emptydir') {
  221. fputs($fs, "file1\r\nfile1\r\nfile\nb0rk\r\n");
  222. }
  223. fputs($s, "226 Closing data Connection.\r\n");
  224. fclose($fs);
  225. } elseif (preg_match("~^MKD ([A-Za-z./]+)\r\n$~", $buf, $m)) {
  226. if (isset($bug7216)) {
  227. fputs($s, "257 OK.\r\n");
  228. } else {
  229. fputs($s, "257 \"/path/to/ftproot$cwd$m[1]\" created.\r\n");
  230. }
  231. } elseif (preg_match('/^USER /', $buf)) {
  232. user_auth($buf);
  233. } elseif (preg_match('/^MDTM ([\w\h]+)/', $buf, $matches)) {
  234. switch ($matches [1]){
  235. case "A":
  236. fputs($s, "213 19980615100045.014\r\n");
  237. break;
  238. case "B":
  239. fputs($s, "213 19980615100045.014\r\n");
  240. break;
  241. case "C":
  242. fputs($s, "213 19980705132316\r\n");
  243. break;
  244. case "19990929043300 File6":
  245. fputs($s, "213 19991005213102\r\n");
  246. break;
  247. default :
  248. fputs($s, "550 No file named \"{$matches [1]}\"\r\n");
  249. break;
  250. }
  251. }elseif (preg_match('/^RETR ([\w\h]+)/', $buf, $matches)) {
  252. if(!empty($pasv)){
  253. ;
  254. }
  255. else if (!$fs = stream_socket_client("tcp://$host:$port")) {
  256. fputs($s, "425 Can't open data connection\r\n");
  257. continue;
  258. }
  259. switch($matches[1]){
  260. case "pasv":
  261. fputs($s, "150 File status okay; about to open data connection.\r\n");
  262. //the data connection is handled in another forked process
  263. // called from outside this while loop
  264. fputs($s, "226 Closing data Connection.\r\n");
  265. break;
  266. case "a story":
  267. fputs($s, "150 File status okay; about to open data connection.\r\n");
  268. fputs($fs, "For sale: baby shoes, never worn.\r\n");
  269. fputs($s, "226 Closing data Connection.\r\n");
  270. break;
  271. case "binary data":
  272. fputs($s, "150 File status okay; about to open data connection.\r\n");
  273. $transfer_type = $ascii? 'ASCII' : 'BINARY' ;
  274. fputs($fs, $transfer_type."Foo\0Bar\r\n");
  275. fputs($s, "226 Closing data Connection.\r\n");
  276. break;
  277. case "fget":
  278. fputs($s, "150 File status okay; about to open data connection.\r\n");
  279. $transfer_type = $ascii? 'ASCII' : 'BINARY' ;
  280. fputs($fs, $transfer_type."FooBar\r\n");
  281. fputs($s, "226 Closing data Connection.\r\n");
  282. break;
  283. case "fgetresume":
  284. fputs($s, "150 File status okay; about to open data connection.\r\n");
  285. $transfer_type = $ascii? 'ASCII' : 'BINARY' ;
  286. fputs($fs, "Bar\r\n");
  287. fputs($s, "226 Closing data Connection.\r\n");
  288. break;
  289. case "fget_large":
  290. fputs($s, "150 File status okay; about to open data connection.\r\n");
  291. $transfer_type = $ascii? 'ASCII' : 'BINARY' ;
  292. if ($GLOBALS['rest_pos'] == '5368709119') {
  293. fputs($fs, "X");
  294. } else {
  295. fputs($fs, "Y");
  296. }
  297. fputs($s, "226 Closing data Connection.\r\n");
  298. break;
  299. case "mediumfile":
  300. fputs($s, "150 File status okay; about to open data connection.\r\n");
  301. for($i = 0; $i < 150; $i++){
  302. fputs($fs, "This is line $i of the test data.\n");
  303. }
  304. fputs($s, "226 Closing data Connection.\r\n");
  305. default:
  306. fputs($s, "550 {$matches[1]}: No such file or directory \r\n");
  307. break;
  308. }
  309. if(isset($fs))
  310. fclose($fs);
  311. }elseif (preg_match('/^PASV/', $buf, $matches)) {
  312. $port = $pasv_port;
  313. $p2 = $port % ((int) 1 << 8);
  314. $p1 = ($port-$p2)/((int) 1 << 8);
  315. $host = "127.0.0.1";
  316. fputs($s, "227 Entering Passive Mode. (127,0,0,1,{$p1},{$p2})\r\n");
  317. } elseif (preg_match('/^SITE EXEC/', $buf, $matches)) {
  318. fputs($s, "200 OK\r\n");
  319. } elseif (preg_match('/^RMD/', $buf, $matches)) {
  320. fputs($s, "250 OK\r\n");
  321. } elseif (preg_match('/^SITE CHMOD/', $buf, $matches)) {
  322. fputs($s, "200 OK\r\n");
  323. } elseif (preg_match('/^ALLO (\d+)/', $buf, $matches)) {
  324. fputs($s, "200 " . $matches[1] . " bytes allocated\r\n");
  325. }elseif (preg_match('/^LIST www\//', $buf, $matches)) {
  326. fputs($s, "150 Opening ASCII mode data connection for file list\r\n");
  327. fputs($s, "226 Transfer complete\r\n");
  328. }elseif (preg_match('/^LIST no_exists\//', $buf, $matches)) {
  329. fputs($s, "425 Error establishing connection\r\n");
  330. }elseif (preg_match('/^REST (\d+)/', $buf, $matches)) {
  331. $GLOBALS['rest_pos'] = $matches[1];
  332. fputs($s, "350 OK\r\n");
  333. }elseif (preg_match('/^SIZE largefile/', $buf)) {
  334. fputs($s, "213 5368709120\r\n");
  335. }else {
  336. fputs($s, "500 Syntax error, command unrecognized.\r\n");
  337. dump_and_exit($buf);
  338. }
  339. }
  340. fclose($s);
  341. exit;
  342. }
  343. fclose($socket);
  344. ?>