Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
/**
3
 * Net_Socket
4
 *
5
 * PHP Version 4
6
 *
7
 * Copyright (c) 1997-2003 The PHP Group
8
 *
9
 * This source file is subject to version 2.0 of the PHP license,
10
 * that is bundled with this package in the file LICENSE, and is
11
 * available at through the world-wide-web at
12
 * http://www.php.net/license/2_02.txt.
13
 * If you did not receive a copy of the PHP license and are unable to
14
 * obtain it through the world-wide-web, please send a note to
15
 * license@php.net so we can mail you a copy immediately.
16
 *
17
 * Authors: Stig Bakken <ssb@php.net>
18
 *          Chuck Hagenbuch <chuck@horde.org>
19
 *
20
 * @category  Net
21
 * @package   Net_Socket
22
 * @author    Stig Bakken <ssb@php.net>
23
 * @author    Chuck Hagenbuch <chuck@horde.org>
24
 * @copyright 1997-2003 The PHP Group
25
 * @license   http://www.php.net/license/2_02.txt PHP 2.02
26
 * @version   CVS: $Id: Socket.php 304428 2010-10-15 13:51:46Z clockwerx $
27
 * @link      http://pear.php.net/packages/Net_Socket
28
 */
29
 
30
require_once 'PEAR.php';
31
 
32
define('NET_SOCKET_READ', 1);
33
define('NET_SOCKET_WRITE', 2);
34
define('NET_SOCKET_ERROR', 4);
35
 
36
/**
37
 * Generalized Socket class.
38
 *
39
 * @category  Net
40
 * @package   Net_Socket
41
 * @author    Stig Bakken <ssb@php.net>
42
 * @author    Chuck Hagenbuch <chuck@horde.org>
43
 * @copyright 1997-2003 The PHP Group
44
 * @license   http://www.php.net/license/2_02.txt PHP 2.02
45
 * @link      http://pear.php.net/packages/Net_Socket
46
 */
47
class Net_Socket extends PEAR
48
{
49
    /**
50
     * Socket file pointer.
51
     * @var resource $fp
52
     */
53
    var $fp = null;
54
 
55
    /**
56
     * Whether the socket is blocking. Defaults to true.
57
     * @var boolean $blocking
58
     */
59
    var $blocking = true;
60
 
61
    /**
62
     * Whether the socket is persistent. Defaults to false.
63
     * @var boolean $persistent
64
     */
65
    var $persistent = false;
66
 
67
    /**
68
     * The IP address to connect to.
69
     * @var string $addr
70
     */
71
    var $addr = '';
72
 
73
    /**
74
     * The port number to connect to.
75
     * @var integer $port
76
     */
77
    var $port = 0;
78
 
79
    /**
80
     * Number of seconds to wait on socket connections before assuming
81
     * there's no more data. Defaults to no timeout.
82
     * @var integer $timeout
83
     */
84
    var $timeout = false;
85
 
86
    /**
87
     * Number of bytes to read at a time in readLine() and
88
     * readAll(). Defaults to 2048.
89
     * @var integer $lineLength
90
     */
91
    var $lineLength = 2048;
92
 
93
    /**
94
     * The string to use as a newline terminator. Usually "\r\n" or "\n".
95
     * @var string $newline
96
     */
97
    var $newline = "\r\n";
98
 
99
    /**
100
     * Connect to the specified port. If called when the socket is
101
     * already connected, it disconnects and connects again.
102
     *
103
     * @param string  $addr       IP address or host name.
104
     * @param integer $port       TCP port number.
105
     * @param boolean $persistent (optional) Whether the connection is
106
     *                            persistent (kept open between requests
107
     *                            by the web server).
108
     * @param integer $timeout    (optional) How long to wait for data.
109
     * @param array   $options    See options for stream_context_create.
110
     *
111
     * @access public
112
     *
113
     * @return boolean | PEAR_Error  True on success or a PEAR_Error on failure.
114
     */
115
    function connect($addr, $port = 0, $persistent = null,
116
                     $timeout = null, $options = null)
117
    {
118
        if (is_resource($this->fp)) {
119
            @fclose($this->fp);
120
            $this->fp = null;
121
        }
122
 
123
        if (!$addr) {
124
            return $this->raiseError('$addr cannot be empty');
125
        } elseif (strspn($addr, '.0123456789') == strlen($addr) ||
126
                  strstr($addr, '/') !== false) {
127
            $this->addr = $addr;
128
        } else {
129
            $this->addr = @gethostbyname($addr);
130
        }
131
 
132
        $this->port = $port % 65536;
133
 
134
        if ($persistent !== null) {
135
            $this->persistent = $persistent;
136
        }
137
 
138
        if ($timeout !== null) {
139
            $this->timeout = $timeout;
140
        }
141
 
142
        $openfunc = $this->persistent ? 'pfsockopen' : 'fsockopen';
143
        $errno    = 0;
144
        $errstr   = '';
145
 
146
        $old_track_errors = @ini_set('track_errors', 1);
147
 
148
        if ($options && function_exists('stream_context_create')) {
149
            if ($this->timeout) {
150
                $timeout = $this->timeout;
151
            } else {
152
                $timeout = 0;
153
            }
154
            $context = stream_context_create($options);
155
 
156
            // Since PHP 5 fsockopen doesn't allow context specification
157
            if (function_exists('stream_socket_client')) {
158
                $flags = STREAM_CLIENT_CONNECT;
159
 
160
                if ($this->persistent) {
161
                    $flags = STREAM_CLIENT_PERSISTENT;
162
                }
163
 
164
                $addr = $this->addr . ':' . $this->port;
165
                $fp   = stream_socket_client($addr, $errno, $errstr,
166
                                             $timeout, $flags, $context);
167
            } else {
168
                $fp = @$openfunc($this->addr, $this->port, $errno,
169
                                 $errstr, $timeout, $context);
170
            }
171
        } else {
172
            if ($this->timeout) {
173
                $fp = @$openfunc($this->addr, $this->port, $errno,
174
                                 $errstr, $this->timeout);
175
            } else {
176
                $fp = @$openfunc($this->addr, $this->port, $errno, $errstr);
177
            }
178
        }
179
 
180
        if (!$fp) {
181
            if ($errno == 0 && !strlen($errstr) && isset($php_errormsg)) {
182
                $errstr = $php_errormsg;
183
            }
184
            @ini_set('track_errors', $old_track_errors);
185
            return $this->raiseError($errstr, $errno);
186
        }
187
 
188
        @ini_set('track_errors', $old_track_errors);
189
        $this->fp = $fp;
190
 
191
        return $this->setBlocking($this->blocking);
192
    }
193
 
194
    /**
195
     * Disconnects from the peer, closes the socket.
196
     *
197
     * @access public
198
     * @return mixed true on success or a PEAR_Error instance otherwise
199
     */
200
    function disconnect()
201
    {
202
        if (!is_resource($this->fp)) {
203
            return $this->raiseError('not connected');
204
        }
205
 
206
        @fclose($this->fp);
207
        $this->fp = null;
208
        return true;
209
    }
210
 
211
    /**
212
     * Set the newline character/sequence to use.
213
     *
214
     * @param string $newline  Newline character(s)
215
     * @return boolean True
216
     */
217
    function setNewline($newline)
218
    {
219
        $this->newline = $newline;
220
        return true;
221
    }
222
 
223
    /**
224
     * Find out if the socket is in blocking mode.
225
     *
226
     * @access public
227
     * @return boolean  The current blocking mode.
228
     */
229
    function isBlocking()
230
    {
231
        return $this->blocking;
232
    }
233
 
234
    /**
235
     * Sets whether the socket connection should be blocking or
236
     * not. A read call to a non-blocking socket will return immediately
237
     * if there is no data available, whereas it will block until there
238
     * is data for blocking sockets.
239
     *
240
     * @param boolean $mode True for blocking sockets, false for nonblocking.
241
     *
242
     * @access public
243
     * @return mixed true on success or a PEAR_Error instance otherwise
244
     */
245
    function setBlocking($mode)
246
    {
247
        if (!is_resource($this->fp)) {
248
            return $this->raiseError('not connected');
249
        }
250
 
251
        $this->blocking = $mode;
252
        stream_set_blocking($this->fp, (int)$this->blocking);
253
        return true;
254
    }
255
 
256
    /**
257
     * Sets the timeout value on socket descriptor,
258
     * expressed in the sum of seconds and microseconds
259
     *
260
     * @param integer $seconds      Seconds.
261
     * @param integer $microseconds Microseconds.
262
     *
263
     * @access public
264
     * @return mixed true on success or a PEAR_Error instance otherwise
265
     */
266
    function setTimeout($seconds, $microseconds)
267
    {
268
        if (!is_resource($this->fp)) {
269
            return $this->raiseError('not connected');
270
        }
271
 
272
        return socket_set_timeout($this->fp, $seconds, $microseconds);
273
    }
274
 
275
    /**
276
     * Sets the file buffering size on the stream.
277
     * See php's stream_set_write_buffer for more information.
278
     *
279
     * @param integer $size Write buffer size.
280
     *
281
     * @access public
282
     * @return mixed on success or an PEAR_Error object otherwise
283
     */
284
    function setWriteBuffer($size)
285
    {
286
        if (!is_resource($this->fp)) {
287
            return $this->raiseError('not connected');
288
        }
289
 
290
        $returned = stream_set_write_buffer($this->fp, $size);
291
        if ($returned == 0) {
292
            return true;
293
        }
294
        return $this->raiseError('Cannot set write buffer.');
295
    }
296
 
297
    /**
298
     * Returns information about an existing socket resource.
299
     * Currently returns four entries in the result array:
300
     *
301
     * <p>
302
     * timed_out (bool) - The socket timed out waiting for data<br>
303
     * blocked (bool) - The socket was blocked<br>
304
     * eof (bool) - Indicates EOF event<br>
305
     * unread_bytes (int) - Number of bytes left in the socket buffer<br>
306
     * </p>
307
     *
308
     * @access public
309
     * @return mixed Array containing information about existing socket
310
     *               resource or a PEAR_Error instance otherwise
311
     */
312
    function getStatus()
313
    {
314
        if (!is_resource($this->fp)) {
315
            return $this->raiseError('not connected');
316
        }
317
 
318
        return socket_get_status($this->fp);
319
    }
320
 
321
    /**
322
     * Get a specified line of data
323
     *
324
     * @param int $size ??
325
     *
326
     * @access public
327
     * @return $size bytes of data from the socket, or a PEAR_Error if
328
     *         not connected.
329
     */
330
    function gets($size = null)
331
    {
332
        if (!is_resource($this->fp)) {
333
            return $this->raiseError('not connected');
334
        }
335
 
336
        if (is_null($size)) {
337
            return @fgets($this->fp);
338
        } else {
339
            return @fgets($this->fp, $size);
340
        }
341
    }
342
 
343
    /**
344
     * Read a specified amount of data. This is guaranteed to return,
345
     * and has the added benefit of getting everything in one fread()
346
     * chunk; if you know the size of the data you're getting
347
     * beforehand, this is definitely the way to go.
348
     *
349
     * @param integer $size The number of bytes to read from the socket.
350
     *
351
     * @access public
352
     * @return $size bytes of data from the socket, or a PEAR_Error if
353
     *         not connected.
354
     */
355
    function read($size)
356
    {
357
        if (!is_resource($this->fp)) {
358
            return $this->raiseError('not connected');
359
        }
360
 
361
        return @fread($this->fp, $size);
362
    }
363
 
364
    /**
365
     * Write a specified amount of data.
366
     *
367
     * @param string  $data      Data to write.
368
     * @param integer $blocksize Amount of data to write at once.
369
     *                           NULL means all at once.
370
     *
371
     * @access public
372
     * @return mixed If the socket is not connected, returns an instance of
373
     *               PEAR_Error
374
     *               If the write succeeds, returns the number of bytes written
375
     *               If the write fails, returns false.
376
     */
377
    function write($data, $blocksize = null)
378
    {
379
        if (!is_resource($this->fp)) {
380
            return $this->raiseError('not connected');
381
        }
382
 
383
        if (is_null($blocksize) && !OS_WINDOWS) {
384
            return @fwrite($this->fp, $data);
385
        } else {
386
            if (is_null($blocksize)) {
387
                $blocksize = 1024;
388
            }
389
 
390
            $pos  = 0;
391
            $size = strlen($data);
392
            while ($pos < $size) {
393
                $written = @fwrite($this->fp, substr($data, $pos, $blocksize));
394
                if (!$written) {
395
                    return $written;
396
                }
397
                $pos += $written;
398
            }
399
 
400
            return $pos;
401
        }
402
    }
403
 
404
    /**
405
     * Write a line of data to the socket, followed by a trailing newline.
406
     *
407
     * @param string $data Data to write
408
     *
409
     * @access public
410
     * @return mixed fputs result, or an error
411
     */
412
    function writeLine($data)
413
    {
414
        if (!is_resource($this->fp)) {
415
            return $this->raiseError('not connected');
416
        }
417
 
418
        return fwrite($this->fp, $data . $this->newline);
419
    }
420
 
421
    /**
422
     * Tests for end-of-file on a socket descriptor.
423
     *
424
     * Also returns true if the socket is disconnected.
425
     *
426
     * @access public
427
     * @return bool
428
     */
429
    function eof()
430
    {
431
        return (!is_resource($this->fp) || feof($this->fp));
432
    }
433
 
434
    /**
435
     * Reads a byte of data
436
     *
437
     * @access public
438
     * @return 1 byte of data from the socket, or a PEAR_Error if
439
     *         not connected.
440
     */
441
    function readByte()
442
    {
443
        if (!is_resource($this->fp)) {
444
            return $this->raiseError('not connected');
445
        }
446
 
447
        return ord(@fread($this->fp, 1));
448
    }
449
 
450
    /**
451
     * Reads a word of data
452
     *
453
     * @access public
454
     * @return 1 word of data from the socket, or a PEAR_Error if
455
     *         not connected.
456
     */
457
    function readWord()
458
    {
459
        if (!is_resource($this->fp)) {
460
            return $this->raiseError('not connected');
461
        }
462
 
463
        $buf = @fread($this->fp, 2);
464
        return (ord($buf[0]) + (ord($buf[1]) << 8));
465
    }
466
 
467
    /**
468
     * Reads an int of data
469
     *
470
     * @access public
471
     * @return integer  1 int of data from the socket, or a PEAR_Error if
472
     *                  not connected.
473
     */
474
    function readInt()
475
    {
476
        if (!is_resource($this->fp)) {
477
            return $this->raiseError('not connected');
478
        }
479
 
480
        $buf = @fread($this->fp, 4);
481
        return (ord($buf[0]) + (ord($buf[1]) << 8) +
482
                (ord($buf[2]) << 16) + (ord($buf[3]) << 24));
483
    }
484
 
485
    /**
486
     * Reads a zero-terminated string of data
487
     *
488
     * @access public
489
     * @return string, or a PEAR_Error if
490
     *         not connected.
491
     */
492
    function readString()
493
    {
494
        if (!is_resource($this->fp)) {
495
            return $this->raiseError('not connected');
496
        }
497
 
498
        $string = '';
499
        while (($char = @fread($this->fp, 1)) != "\x00") {
500
            $string .= $char;
501
        }
502
        return $string;
503
    }
504
 
505
    /**
506
     * Reads an IP Address and returns it in a dot formatted string
507
     *
508
     * @access public
509
     * @return Dot formatted string, or a PEAR_Error if
510
     *         not connected.
511
     */
512
    function readIPAddress()
513
    {
514
        if (!is_resource($this->fp)) {
515
            return $this->raiseError('not connected');
516
        }
517
 
518
        $buf = @fread($this->fp, 4);
519
        return sprintf('%d.%d.%d.%d', ord($buf[0]), ord($buf[1]),
520
                       ord($buf[2]), ord($buf[3]));
521
    }
522
 
523
    /**
524
     * Read until either the end of the socket or a newline, whichever
525
     * comes first. Strips the trailing newline from the returned data.
526
     *
527
     * @access public
528
     * @return All available data up to a newline, without that
529
     *         newline, or until the end of the socket, or a PEAR_Error if
530
     *         not connected.
531
     */
532
    function readLine()
533
    {
534
        if (!is_resource($this->fp)) {
535
            return $this->raiseError('not connected');
536
        }
537
 
538
        $line = '';
539
 
540
        $timeout = time() + $this->timeout;
541
 
542
        while (!feof($this->fp) && (!$this->timeout || time() < $timeout)) {
543
            $line .= @fgets($this->fp, $this->lineLength);
544
            if (substr($line, -1) == "\n") {
545
                return rtrim($line, $this->newline);
546
            }
547
        }
548
        return $line;
549
    }
550
 
551
    /**
552
     * Read until the socket closes, or until there is no more data in
553
     * the inner PHP buffer. If the inner buffer is empty, in blocking
554
     * mode we wait for at least 1 byte of data. Therefore, in
555
     * blocking mode, if there is no data at all to be read, this
556
     * function will never exit (unless the socket is closed on the
557
     * remote end).
558
     *
559
     * @access public
560
     *
561
     * @return string  All data until the socket closes, or a PEAR_Error if
562
     *                 not connected.
563
     */
564
    function readAll()
565
    {
566
        if (!is_resource($this->fp)) {
567
            return $this->raiseError('not connected');
568
        }
569
 
570
        $data = '';
571
        while (!feof($this->fp)) {
572
            $data .= @fread($this->fp, $this->lineLength);
573
        }
574
        return $data;
575
    }
576
 
577
    /**
578
     * Runs the equivalent of the select() system call on the socket
579
     * with a timeout specified by tv_sec and tv_usec.
580
     *
581
     * @param integer $state   Which of read/write/error to check for.
582
     * @param integer $tv_sec  Number of seconds for timeout.
583
     * @param integer $tv_usec Number of microseconds for timeout.
584
     *
585
     * @access public
586
     * @return False if select fails, integer describing which of read/write/error
587
     *         are ready, or PEAR_Error if not connected.
588
     */
589
    function select($state, $tv_sec, $tv_usec = 0)
590
    {
591
        if (!is_resource($this->fp)) {
592
            return $this->raiseError('not connected');
593
        }
594
 
595
        $read   = null;
596
        $write  = null;
597
        $except = null;
598
        if ($state & NET_SOCKET_READ) {
599
            $read[] = $this->fp;
600
        }
601
        if ($state & NET_SOCKET_WRITE) {
602
            $write[] = $this->fp;
603
        }
604
        if ($state & NET_SOCKET_ERROR) {
605
            $except[] = $this->fp;
606
        }
607
        if (false === ($sr = stream_select($read, $write, $except,
608
                                          $tv_sec, $tv_usec))) {
609
            return false;
610
        }
611
 
612
        $result = 0;
613
        if (count($read)) {
614
            $result |= NET_SOCKET_READ;
615
        }
616
        if (count($write)) {
617
            $result |= NET_SOCKET_WRITE;
618
        }
619
        if (count($except)) {
620
            $result |= NET_SOCKET_ERROR;
621
        }
622
        return $result;
623
    }
624
 
625
    /**
626
     * Turns encryption on/off on a connected socket.
627
     *
628
     * @param bool    $enabled Set this parameter to true to enable encryption
629
     *                         and false to disable encryption.
630
     * @param integer $type    Type of encryption. See stream_socket_enable_crypto()
631
     *                         for values.
632
     *
633
     * @see    http://se.php.net/manual/en/function.stream-socket-enable-crypto.php
634
     * @access public
635
     * @return false on error, true on success and 0 if there isn't enough data
636
     *         and the user should try again (non-blocking sockets only).
637
     *         A PEAR_Error object is returned if the socket is not
638
     *         connected
639
     */
640
    function enableCrypto($enabled, $type)
641
    {
642
        if (version_compare(phpversion(), "5.1.0", ">=")) {
643
            if (!is_resource($this->fp)) {
644
                return $this->raiseError('not connected');
645
            }
646
            return @stream_socket_enable_crypto($this->fp, $enabled, $type);
647
        } else {
648
            $msg = 'Net_Socket::enableCrypto() requires php version >= 5.1.0';
649
            return $this->raiseError($msg);
650
        }
651
    }
652
 
653
}