1: <?php
2:
3: namespace SMSApi\Proxy\Http;
4:
5: use SMSApi\Proxy\Proxy;
6:
7: class Native extends AbstractHttp implements Proxy {
8:
9: const CONNECT_FOPEN = 1;
10: const CONNECT_SOCKET = 2;
11:
12: private $connGateway = self::CONNECT_FOPEN;
13: private $response = array( 'meta' => null, 'output' => null );
14:
15: public function execute( \SMSApi\Api\Action\AbstractAction $action ) {
16:
17: try {
18:
19: $this->uri = $action->uri();
20: $this->file = $action->file();
21:
22: if ( $this->uri == null ) {
23: throw new \SMSApi\Exception\ProxyException( "Invalid URI" );
24: }
25:
26: if ( !empty( $this->file ) && file_exists( $this->file ) ) {
27:
28: $this->toConnect( $this->file );
29: } else {
30:
31: $this->toConnect();
32: }
33:
34: $code = $this->getStatusCode( $this->response[ 'meta' ] );
35:
36: $this->checkCode( $code );
37:
38: if ( empty( $this->response[ 'output' ] ) ) {
39: throw new \SMSApi\Exception\ProxyException( 'Error fetching remote content empty' );
40: }
41: } catch ( \Exception $ex ) {
42: throw new \SMSApi\Exception\ProxyException( $ex->getMessage() );
43: }
44:
45: return $this->response[ 'output' ];
46: }
47:
48: private function getStatusCode( $meta_data ) {
49: $status_code = null;
50:
51: if ( isset( $meta_data[ 'wrapper_data' ] ) AND is_array( $meta_data[ 'wrapper_data' ] ) ) {
52: foreach ( $meta_data[ 'wrapper_data' ] as $_ ) {
53:
54: if ( preg_match( '/^[\s]*HTTP\/1\.[01]\s([\d]+)\sOK[\s]*$/i', $_, $_code ) ) {
55: $status_code = next( $_code );
56: }
57: }
58: }
59:
60: return $status_code;
61: }
62:
63: private function toConnect( $filename = null ) {
64:
65: $body = "";
66:
67: $this->headers[ 'User-Agent' ] = 'SMSApi';
68: $this->headers[ 'Accept' ] = '';
69:
70: if ( $filename ) {
71:
72: $this->headers[ 'Content-Type' ] = 'multipart/form-data; boundary=' . $this->boundary;
73:
74: $body = $this->prepareFileContent( $filename );
75: } else {
76: $this->headers[ 'Content-Type' ] = 'application/x-www-form-urlencoded';
77: }
78:
79: switch ( $this->connGateway ) {
80: case self::CONNECT_FOPEN:
81: $this->doFopen( $body );
82: break;
83:
84: case self::CONNECT_SOCKET:
85: if ( $this->getPort() == 433 || $this->getProtocol() == "https" ) {
86: throw new \SMSApi\Exception\ProxyException( 'Connect socket not supported to https' );
87: }
88: $this->doSocket( $body );
89: break;
90: }
91: }
92:
93: private function doFopen( $body ) {
94: if ( isset( $this->uri ) ) {
95: $url = $this->uri->getSchema() . "://" . $this->uri->getHost() . $this->uri->getPath();
96:
97: $heders = "";
98: foreach ( $this->headers as $k => $v ) {
99: if ( is_string( $k ) )
100: $v = ucfirst( $k ) . ": $v";
101: $heders .= "$v\r\n";
102: }
103:
104: $opts = array(
105: 'http' => array(
106: 'method' => $this->method,
107: 'header' => $heders,
108: 'content' => empty( $body ) ? $this->uri->getQuery() : $body,
109: )
110: );
111:
112: $context = stream_context_create( $opts );
113:
114: if ( !empty( $body ) ) {
115: $url .= '?' . $this->uri->getQuery();
116: }
117:
118: $fp = fopen( $url, 'r', false, $context );
119:
120: $this->response[ 'meta' ] = stream_get_meta_data( $fp );
121: $this->response[ 'output' ] = stream_get_contents( $fp );
122:
123: if ( $fp ) {
124: fclose( $fp );
125: }
126: }
127: }
128:
129: private function doSocket( $body ) {
130: if ( isset( $this->uri ) ) {
131:
132: $flags = STREAM_CLIENT_CONNECT;
133: $contextTest = stream_context_create();
134:
135: $socket = stream_socket_client(
136: $this->uri->getHost() . ':' . $this->getPort(), $errno, $errstr, (int) $this->timeout, $flags, $contextTest
137: );
138:
139: if ( !is_resource( $socket ) ) {
140: throw new \SMSApi\Exception\ProxyException( 'Unable to connect' );
141: }
142:
143:
144:
145: $request = "{$this->method} {$this->uri->getPath()} HTTP/1.1\r\n";
146:
147: $body = $this->renderQueryByBody( $this->uri->getQuery(), $body );
148:
149: foreach ( $this->headers as $k1 => $v1 ) {
150: if ( is_string( $k1 ) )
151: $v1 = ucfirst( $k1 ) . ": $v1";
152: $request .= "$v1\r\n";
153: }
154:
155: if ( !in_array( 'Content-Length', $this->headers ) ) {
156: $request .= "Content-Length: " . strlen( $body ) . "\r\n";
157: }
158:
159: if ( !empty( $body ) ) {
160: $request .= "\r\n" . $body;
161: }
162:
163:
164:
165: if ( fwrite( $socket, $request ) ) {
166:
167: $gotStatus = false;
168: $meta = "";
169:
170: while ( ($line = fgets( $socket )) !== false ) {
171: $gotStatus = $gotStatus || (strpos( $line, 'HTTP' ) !== false);
172: if ( $gotStatus ) {
173: $meta .= $line;
174: if ( rtrim( $line ) === '' )
175: break;
176: }
177: }
178:
179: $this->response[ 'meta' ] = $meta;
180:
181: $info = stream_get_meta_data( $socket );
182: if ( $info[ 'timed_out' ] ) {
183: fclose( $socket );
184: throw new \SMSApi\Exception\ProxyException( "Read timed out after {$this->timeout} seconds" );
185: }
186:
187: $this->response[ 'output' ] = stream_get_contents( $socket );
188: }
189:
190: fclose( $socket );
191: }
192: }
193:
194: }