Overview

Namespaces

  • MOC
    • Adapter
    • Core
      • Changelog
      • Depending
      • Drive
        • Directory
        • File
      • Error
        • Register
        • Type
      • Journal
      • Proxy
      • Template
      • Xml
    • Extension
      • Excel
      • Flot
      • Mail
      • Pdf
      • Word
      • Xml
      • YUICompressor
      • Zip
    • Generic
      • Common
      • Device
        • Extension
        • Widget
    • Module
      • Database
        • Driver
      • Drive
      • Image
        • Font
      • Installer
      • Network
        • Ftp
          • Directory
          • File
          • Transport
        • Http
        • ParcelTracker
          • Carrier
      • Office
        • Chart
          • Axis
        • Document
          • Excel
            • Cell
              • Format
              • Style
                • Border
                  • Bottom
                  • Left
                  • Right
                  • Top
                • Font
            • Close
            • Page
            • Worksheet
          • Pdf
            • Close
            • Font
            • Page
              • Margin
              • Position
            • Text
          • Xml
            • Close
        • Image
        • Mail
          • Address
          • Content
      • Packer
        • Yui
        • Zip
      • Template
    • Plugin
      • Gateway
      • Repository
      • Shared
  • PHP

Classes

  • Cache
  • Changelog
  • Depending
  • Drive
  • Encoding
  • Error
  • Journal
  • Proxy
  • Session
  • Template
  • Version
  • Xml
  • Overview
  • Namespace
  • Class
  • Tree
  • Deprecated
  • Todo
  • Download
  1: <?php
  2: /**
  3:  * LICENSE (BSD)
  4:  *
  5:  * Copyright (c) 2012, Gerd Christian Kunze
  6:  * All rights reserved.
  7:  *
  8:  * Redistribution and use in source and binary forms, with or without
  9:  * modification, are permitted provided that the following conditions are
 10:  * met:
 11:  *
 12:  *  * Redistributions of source code must retain the above copyright
 13:  *    notice, this list of conditions and the following disclaimer.
 14:  *
 15:  *  * Redistributions in binary form must reproduce the above copyright
 16:  *    notice, this list of conditions and the following disclaimer in the
 17:  *    documentation and/or other materials provided with the distribution.
 18:  *
 19:  *  * Neither the name of Gerd Christian Kunze nor the names of the
 20:  *    contributors may be used to endorse or promote products derived from
 21:  *    this software without specific prior written permission.
 22:  *
 23:  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 24:  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 25:  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 26:  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 27:  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 28:  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 29:  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 30:  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 31:  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 32:  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 33:  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 34:  *
 35:  * Proxy
 36:  * 02.09.2012 16:20
 37:  */
 38: namespace MOC\Core;
 39: use MOC\Api;
 40: use MOC\Generic\Device\Core;
 41: 
 42: /**
 43:  *
 44:  */
 45: class Proxy implements Core {
 46:     /** @var Proxy $Singleton */
 47:     private static $Singleton = null;
 48: 
 49:     /**
 50:      * Get Singleton/Instance
 51:      *
 52:      * @static
 53:      * @return Proxy
 54:      */
 55:     public static function InterfaceInstance() {
 56:         if( self::$Singleton === null ) {
 57:             self::$Singleton = new Proxy();
 58:         } return self::$Singleton;
 59:     }
 60: 
 61:     /**
 62:      * Get Changelog
 63:      *
 64:      * @static
 65:      * @return \MOC\Core\Changelog
 66:      */
 67:     public static function InterfaceChangelog() {
 68:         return Api::Core()->Changelog()->Create( __CLASS__ );
 69:     }
 70: 
 71:     /**
 72:      * Get Dependencies
 73:      *
 74:      * @static
 75:      * @return \MOC\Core\Depending
 76:      */
 77:     public static function InterfaceDepending() {
 78:         return Api::Core()->Depending();
 79:     }
 80: 
 81:     const PROXY_NONE = 0;
 82:     const PROXY_RELAY = 1;
 83:     const PROXY_BASIC = 2;
 84: 
 85:     /** @var null|Proxy\Server $Server */
 86:     private $Server = null;
 87:     /** @var null|Proxy\Credentials $Credentials */
 88:     private $Credentials = null;
 89: 
 90:     private $Timeout = 5;
 91:     private $ErrorNumber = null;
 92:     private $ErrorString = null;
 93:     private $ProxyType = self::PROXY_NONE;
 94: 
 95:     /**
 96:      * @param Drive\File $File
 97:      * @return string
 98:      */
 99:     public function Url( Drive\File $File ) {
100:         return Proxy\Seo::InterfaceInstance()->Url( $File );
101:     }
102: 
103:     /**
104:      * @param Proxy\Server      $Server
105:      * @param Proxy\Credentials $Credentials
106:      *
107:      * @return Proxy
108:      */
109:     public function Open( Proxy\Server $Server, Proxy\Credentials $Credentials = null ) {
110: 
111:         $this->Server = $Server;
112:         $this->Credentials = $Credentials;
113: 
114:         if( $this->Credentials == null ) {
115:             $this->ProxyType = self::PROXY_RELAY;
116:         } else {
117:             $this->ProxyType = self::PROXY_BASIC;
118:         }
119: 
120:         return $this;
121:     }
122: 
123:     /**
124:      * @return Proxy
125:      */
126:     public function Close() {
127: 
128:         $this->Server = null;
129:         $this->Credentials = null;
130: 
131:         $this->ProxyType = self::PROXY_NONE;
132: 
133:         return $this;
134:     }
135: 
136:     /**
137:      * @return Proxy\Server
138:      */
139:     public function Server() {
140:         return Proxy\Server::InterfaceInstance();
141:     }
142: 
143:     /**
144:      * @return Proxy\Credentials
145:      */
146:     public function Credentials() {
147:         return Proxy\Credentials::InterfaceInstance();
148:     }
149:     /**
150:      * @param string $Url
151:      * @param bool $Status
152:      *
153:      * @return null|string
154:      * @throws \Exception
155:      */
156:     public function GetFile( $Url, $Status = false ) {
157:         switch( $this->IsProxy() ) {
158:             case self::PROXY_NONE: return $this->ProxyNone( $Url, $Status );
159:             case self::PROXY_RELAY: return $this->ProxyRelay( $Url, $Status );
160:             case self::PROXY_BASIC: return $this->ProxyBasic( $Url, $Status );
161:             default: throw new \Exception('Proxy not available!');
162:         }
163:     }
164: 
165:     /**
166:      * @param string $Url
167:      *
168:      * @return string
169:      */
170:     public function GetContent( $Url ) {
171:         return $this->cURL( $Url );
172:     }
173: 
174:     /**
175:      * @return bool|int
176:      */
177:     private function IsProxy() {
178:         if( $this->ProxyType !== self::PROXY_NONE ) {
179:             return $this->ProxyType;
180:         } else {
181:             return false;
182:         }
183:     }
184: 
185:     /**
186:      * @param $Url
187:      * @param $Status
188:      *
189:      * @return null|string
190:      */
191:     private function ProxyNone( $Url, $Status ) {
192:         $this->Server = Proxy\Server::InterfaceInstance();
193:         $this->Server->Host( parse_url( $Url, PHP_URL_HOST ) );
194:         if( parse_url( $Url, PHP_URL_PORT ) === null ) {
195:             switch( strtoupper( parse_url( $Url, PHP_URL_SCHEME ) ) ) {
196:                 case 'HTTP': { $this->Server->Port( '80' ); break; }
197:                 case 'HTTPS': { $this->Server->Port( '443' ); break; }
198:             }
199:         } else {
200:             $this->Server->Port( parse_url( $Url, PHP_URL_PORT ) );
201:         }
202:         if( $this->Server->Port() == '443' ) {
203:             return file_get_contents( $Url );
204:         }
205:         if( ($Socket = fsockopen( $this->Server->Host(), $this->Server->Port(), $this->ErrorNumber, $this->ErrorString, $this->Timeout )) ) {
206:             $Content = '';
207:             fputs( $Socket, "GET ".$Url." HTTP/1.0\r\nHost: ".parse_url( $Url, PHP_URL_HOST )."\r\n\r\n");
208:             while( !feof( $Socket ) ) {
209:                 $Content .= fread( $Socket, 4096 );
210:                 if( $Status ) {
211:                     $Match = array();
212:                     preg_match( '![0-9]{3}!', $Content, $Match );
213:                     return $Match[0];
214:                 }
215:             }
216:             // Check Status e.g 302 -> Redirect
217:             $ContentToCheck = $this->StatusCode( $Content, $Url );
218:             fclose( $Socket );
219:             if( $Content == $ContentToCheck ) {
220:                 // Not Modified -> Care for Header
221:                 $Header = substr( $Content, 0, strpos( $Content, "\r\n\r\n" ) +4 );
222:                 $Content = substr( $Content, strpos( $Content, "\r\n\r\n" ) +4 );
223:                 if( preg_match( '!content-encoding: gzip!is', $Header ) ) {
224:                     $Content = $this->gzdecode( $Content );
225:                 }
226:             } else {
227:                 // Already Modified -> Nothing to do
228:                 $Content = $ContentToCheck;
229:             }
230:         } else {
231:             trigger_error( '['.$this->ErrorNumber.'] '.$this->ErrorString );
232:             $Content = null;
233:         }
234:         return $Content;
235:     }
236: 
237:     /**
238:      * @param $Url
239:      * @param $Status
240:      *
241:      * @return null|string
242:      */
243:     private function ProxyRelay( $Url, $Status ) {
244:         if( ($Socket = fsockopen( $this->Server->Host(), $this->Server->Port(), $this->ErrorNumber, $this->ErrorString, $this->Timeout )) ) {
245:             $Content = '';
246:             fputs( $Socket, "GET ".$Url." HTTP/1.0\r\nHost: ".$this->Server->Host()."\r\n\r\n");
247:             while( !feof( $Socket ) ) {
248:                 $Content .= fread( $Socket, 4096 );
249:                 if( $Status ) {
250:                     $Match = array();
251:                     preg_match( '![0-9]{3}!', $Content, $Match );
252:                     return $Match[0];
253:                 }
254:             }
255:             // Check Status e.g 302 -> Redirect
256:             $ContentToCheck = $this->StatusCode( $Content );
257:             fclose( $Socket );
258:             if( $Content == $ContentToCheck ) {
259:                 // Not Modified -> Care for Header
260:                 $Header = substr( $Content, 0, strpos( $Content, "\r\n\r\n" ) +4 );
261:                 $Content = substr( $Content, strpos( $Content, "\r\n\r\n" ) +4 );
262:                 if( preg_match( '!content-encoding: gzip!is', $Header ) ) {
263:                     $Content = $this->gzdecode( $Content );
264:                 }
265:             } else {
266:                 // Already Modified -> Nothing to do
267:                 $Content = $ContentToCheck;
268:             }
269:         } else {
270:             trigger_error( '['.$this->ErrorNumber.'] '.$this->ErrorString );
271:             $Content = null;
272:         }
273:         return $Content;
274:     }
275: 
276:     /**
277:      * @param $Url
278:      * @param $Status
279:      *
280:      * @return null|string
281:      */
282:     private function ProxyBasic( $Url, $Status ) {
283:         if( ($Socket = fsockopen( $this->Server->Host(), $this->Server->Port(), $this->ErrorNumber, $this->ErrorString, $this->Timeout )) ) {
284:             $Content = '';
285:             fputs( $Socket, "GET ".$Url." HTTP/1.0\r\nHost: ".$this->Server->Host()."\r\n");
286:             fputs( $Socket, "Proxy-Authorization: Basic ".base64_encode( $this->Credentials->Username().':'.$this->Credentials->Password() ) . "\r\n\r\n");
287:             while( !feof( $Socket ) ) {
288:                 $Content .= fread( $Socket, 4096 );
289:                 if( $Status ) {
290:                     $Match = array();
291:                     preg_match( '![0-9]{3}!', $Content, $Match );
292:                     return $Match[0];
293:                 }
294:             }
295:             // Check Status e.g 302 -> Redirect
296:             $ContentToCheck = $this->StatusCode( $Content );
297:             fclose( $Socket );
298:             if( $Content == $ContentToCheck ) {
299:                 // Not Modified -> Care for Header
300:                 $Header = substr( $Content, 0, strpos( $Content, "\r\n\r\n" ) +4 );
301:                 $Content = substr( $Content, strpos( $Content, "\r\n\r\n" ) +4 );
302:                 if( preg_match( '!content-encoding: gzip!is', $Header ) ) {
303:                     $Content = $this->gzdecode( $Content );
304:                 }
305:             } else {
306:                 // Already Modified -> Nothing to do
307:                 $Content = $ContentToCheck;
308:             }
309:         } else {
310:             trigger_error( '['.$this->ErrorNumber.'] '.$this->ErrorString );
311:             $Content = null;
312:         }
313:         return $Content;
314:     }
315: 
316:     /**
317:      * @param      $Content
318:      * @param null $Url
319:      *
320:      * @return null|string
321:      */
322:     private function StatusCode( $Content, $Url = null ) {
323:         preg_match( '![0-9]{3}!', $Content, $Match );
324:         switch( $Match[0] ) {
325:             case '302': {
326:                 preg_match( '!(?<=Location: )([^\s\n]+)!', $Content, $Match );
327:                 if( parse_url( $Match[0] ) ) {
328:                     // If Location is not correct
329:                     if( null !== $Url ) {
330:                         $Match[0] = str_replace( $Url, '', $Match[0] ).'?'.parse_url( $Url, PHP_URL_QUERY );
331:                     }
332:                     $Content = $this->GetFile( $Match[0] );
333:                 }
334:                 return $Content;
335:                 break;
336:             }
337:             case '301': {
338:                 preg_match( '!(?<=Location: )([^\s\n]+)!', $Content, $Match );
339:                 if( parse_url( $Match[0] ) ) {
340:                     $Content = $this->GetFile( $Match[0] );
341:                 }
342:                 return $Content;
343:                 break;
344:             }
345:             case '200': {
346:                 return $Content;
347:             }
348:             default: {
349:                 trigger_error( __CLASS__.': Status-Code '.$Match[0] );
350:                 return $Content;
351:             }
352:         }
353:     }
354: 
355:     private static $cURL = null;
356: 
357:     /**
358:      * @param $Url
359:      *
360:      * @return string
361:      */
362:     private function cURL( $Url ) {
363:         self::$cURL = curl_init();
364:         curl_setopt ( self::$cURL, CURLOPT_URL, $Url );
365:         curl_setopt ( self::$cURL, CURLOPT_HEADER, 0 );
366:         ob_start();
367:         curl_exec ( self::$cURL );
368:         curl_close ( self::$cURL );
369:         $Content = ob_get_contents();
370:         // Fix: gzip content
371:         $Header = substr( $Content, 0, strpos( $Content, "\r\n\r\n" ) +4 );
372:         $Content = substr( $Content, strpos( $Content, "\r\n\r\n" ) +4 );
373:         if( preg_match( '!content-encoding: gzip!is', $Header ) ) {
374:             $Content = $this->gzdecode( $Content );
375:         }
376:         ob_end_clean();
377:         return $Content;
378:     }
379: 
380:     /**
381:      * by katzlbtjunk@hotmail.com
382:      * http://de3.php.net/manual/en/function.gzdecode.php#82930
383:      *
384:      * @param        $data
385:      * @param string $filename
386:      * @param string $error
387:      * @param null   $maxlength
388:      *
389:      * @return bool|null|string
390:      */
391:     private function gzdecode($data,&$filename='',&$error='',$maxlength=null)
392:     {
393:         $len = strlen($data);
394:         if ($len < 18 || strcmp(substr($data,0,2),"\x1f\x8b")) {
395:             $error = "Not in GZIP format.";
396:             return null;  // Not GZIP format (See RFC 1952)
397:         }
398:         $method = ord(substr($data,2,1));  // Compression method
399:         $flags  = ord(substr($data,3,1));  // Flags
400:         if ($flags & 31 != $flags) {
401:             $error = "Reserved bits not allowed.";
402:             return null;
403:         }
404:         // NOTE: $mtime may be negative (PHP integer limitations)
405:         $mtime = unpack("V", substr($data,4,4));
406:         $mtime = $mtime[1];
407:         $xfl   = substr($data,8,1);
408:         $os    = substr($data,8,1);
409:         $headerlen = 10;
410:         $extralen  = 0;
411:         $extra     = "";
412:         if ($flags & 4) {
413:             // 2-byte length prefixed EXTRA data in header
414:             if ($len - $headerlen - 2 < 8) {
415:                 return false;  // invalid
416:             }
417:             $extralen = unpack("v",substr($data,8,2));
418:             $extralen = $extralen[1];
419:             if ($len - $headerlen - 2 - $extralen < 8) {
420:                 return false;  // invalid
421:             }
422:             $extra = substr($data,10,$extralen);
423:             $headerlen += 2 + $extralen;
424:         }
425:         $filenamelen = 0;
426:         $filename = "";
427:         if ($flags & 8) {
428:             // C-style string
429:             if ($len - $headerlen - 1 < 8) {
430:                 return false; // invalid
431:             }
432:             $filenamelen = strpos(substr($data,$headerlen),chr(0));
433:             if ($filenamelen === false || $len - $headerlen - $filenamelen - 1 < 8) {
434:                 return false; // invalid
435:             }
436:             $filename = substr($data,$headerlen,$filenamelen);
437:             $headerlen += $filenamelen + 1;
438:         }
439:         $commentlen = 0;
440:         $comment = "";
441:         if ($flags & 16) {
442:             // C-style string COMMENT data in header
443:             if ($len - $headerlen - 1 < 8) {
444:                 return false;    // invalid
445:             }
446:             $commentlen = strpos(substr($data,$headerlen),chr(0));
447:             if ($commentlen === false || $len - $headerlen - $commentlen - 1 < 8) {
448:                 return false;    // Invalid header format
449:             }
450:             $comment = substr($data,$headerlen,$commentlen);
451:             $headerlen += $commentlen + 1;
452:         }
453:         $headercrc = "";
454:         if ($flags & 2) {
455:             // 2-bytes (lowest order) of CRC32 on header present
456:             if ($len - $headerlen - 2 < 8) {
457:                 return false;    // invalid
458:             }
459:             $calccrc = crc32(substr($data,0,$headerlen)) & 0xffff;
460:             $headercrc = unpack("v", substr($data,$headerlen,2));
461:             $headercrc = $headercrc[1];
462:             if ($headercrc != $calccrc) {
463:                 $error = "Header checksum failed.";
464:                 return false;    // Bad header CRC
465:             }
466:             $headerlen += 2;
467:         }
468:         // GZIP FOOTER
469:         $datacrc = unpack("V",substr($data,-8,4));
470:         $datacrc = sprintf('%u',$datacrc[1] & 0xFFFFFFFF);
471:         $isize = unpack("V",substr($data,-4));
472:         $isize = $isize[1];
473:         // decompression:
474:         $bodylen = $len-$headerlen-8;
475:         if ($bodylen < 1) {
476:             // IMPLEMENTATION BUG!
477:             return null;
478:         }
479:         $body = substr($data,$headerlen,$bodylen);
480:         $data = "";
481:         if ($bodylen > 0) {
482:             switch ($method) {
483:             case 8:
484:                 // Currently the only supported compression method:
485:                 $data = gzinflate($body,$maxlength);
486:                 break;
487:             default:
488:                 $error = "Unknown compression method.";
489:                 return false;
490:             }
491:         }  // zero-byte body content is allowed
492:         // Verifiy CRC32
493:         $crc   = sprintf("%u",crc32($data));
494:         $crcOK = $crc == $datacrc;
495:         $lenOK = $isize == strlen($data);
496:         if (!$lenOK || !$crcOK) {
497:             $error = ( $lenOK ? '' : 'Length check FAILED. ') . ( $crcOK ? '' : 'Checksum FAILED.');
498:             return false;
499:         }
500:         return $data;
501:     }
502: 
503:     /**
504:      * @return string
505:      */
506:     function __toString() {
507:         return '';
508:     }
509: }
510: 
API documentation generated by ApiGen 2.8.0