/administrator/components/com_virtuemart/helpers/connection.php
PHP | 335 lines | 224 code | 25 blank | 86 comment | 73 complexity | 87b35aaf4149108eda1aa03ddaba95ea MD5 | raw file
Possible License(s): GPL-2.0, LGPL-3.0, LGPL-2.1, BSD-3-Clause, JSON
- <?php
- if( !defined( '_JEXEC' ) ) die( 'Direct Access to '.basename(__FILE__).' is not allowed.' );
- /**
- *
- * @version $Id:connection.php 431 2006-10-17 21:55:46 +0200 (Di, 17 Okt 2006) soeren_nb $
- * @package VirtueMart
- * @subpackage classes
- * @copyright Copyright (C) 2004-2007 soeren, 2009-2011 VirtueMart Team. All rights reserved.
- * @license http://www.gnu.org/copyleft/gpl.html GNU/GPL, see LICENSE.php
- * VirtueMart is free software. This version may have been modified pursuant
- * to the GNU General Public License, and as distributed it includes or
- * is derivative of works licensed under the GNU General Public License or
- * other free or open source software licenses.
- * See /administrator/components/com_virtuemart/COPYRIGHT.php for copyright notices and details.
- *
- * http://virtuemart.org
- */
-
- /**
- * Provides general tools to handle connections (http, headers, ... )
- *
- * @author soeren
- * @since VirtueMart 1.1.0
- */
- class VmConnector {
-
- var $handle = null;
-
- /**
- * Clears the output buffer, sends a http status code and a content if given
- * @static
- * @param int $http_status
- * @param string $mime_type
- * @param string $content
- */
- function sendHeaderAndContent( $http_status=200, $content='', $mime_type='text/html' ) {
-
- // Clear all Joomla header and buffer stuff
- while( @ob_end_clean() );
-
- $http_status = intval( $http_status );
- @header("HTTP/1.0 $http_status");
- if( $mime_type ) {
- @header( "Content-type: $mime_type; charset=".vmGetCharset() );
- } elseif( $mime_type != '' ) {
- @header( "Content-type: text/html; charset=".vmGetCharset() );
- }
- if( $content ) {
- echo $content;
- }
- }
- /**
- * This is a general function to safely open a connection to a server,
- * post data when needed and read the result.
- * Tries using cURL and switches to fopen/fsockopen if cURL is not available
- * @since VirtueMart 1.1.0
- * @static
- * @param string $url
- * @param string $postData
- * @param array $headers
- * @param resource $fileToSaveData
- * @return mixed
- */
- static function handleCommunication( $url, $postData='', $headers=array(), $fileToSaveData=null ) {
-
- $urlParts = parse_url( $url );
- if( !isset( $urlParts['port'] )) $urlParts['port'] = 80;
- if( !isset( $urlParts['scheme'] )) $urlParts['scheme'] = 'http';
-
- if( isset( $urlParts['query'] )){
- $urlParts['query'] = '?'.$urlParts['query'];
- if( isset( $urlParts['path'] )) $urlParts['path'] = $urlParts['path'].$urlParts['query'];
- }
-
- $vm_proxy_url = VmConfig::get('conf_VM_PROXY_URL','');
- // Check proxy
- if( trim( $vm_proxy_url ) != '') {
- if( !stristr($vm_proxy_url, 'http')) {
- $proxyURL['host'] = $vm_proxy_url;
- $proxyURL['scheme'] = 'http';
- } else {
- $proxyURL = parse_url($vm_proxy_url);
- }
- }
- else {
- $proxyURL = '';
- }
-
- if( function_exists( "curl_init" ) && function_exists( 'curl_exec' ) ) {
- $CR = curl_init();
- curl_setopt($CR, CURLOPT_URL, $url);
-
- // just to get sure the script doesn't die
- curl_setopt($CR, CURLOPT_TIMEOUT, 30 );
- if( !empty( $headers )) {
- // Add additional headers if provided
- curl_setopt($CR, CURLOPT_HTTPHEADER, $headers);
- }
- curl_setopt($CR, CURLOPT_FAILONERROR, true);
- if( $postData ) {
- curl_setopt($CR, CURLOPT_POSTFIELDS, $postData );
- curl_setopt($CR, CURLOPT_POST, 1);
- }
- if( is_resource($fileToSaveData)) {
- curl_setopt($CR, CURLOPT_FILE, $fileToSaveData );
- } else {
- curl_setopt($CR, CURLOPT_RETURNTRANSFER, 1);
- }
- // Do we need to set up the proxy?
- if( !empty($proxyURL) ) {
- // $vmLogger->debug( 'Setting up proxy: '.$proxyURL['host'].':'.VM_PROXY_PORT );
- //curl_setopt($CR, CURLOPT_HTTPPROXYTUNNEL, true);
- curl_setopt($CR, CURLOPT_PROXY, $proxyURL['host'] );
- curl_setopt($CR, CURLOPT_PROXYPORT, VM_PROXY_PORT );
- // Check if the proxy needs authentication
- if( trim( @VM_PROXY_USER ) != '') {
- // $vmLogger->debug( 'Using proxy authentication!' );
- curl_setopt($CR, CURLOPT_PROXYUSERPWD, VM_PROXY_USER.':'.VM_PROXY_PASS );
- }
- }
-
- if( $urlParts['scheme'] == 'https') {
- // No PEER certificate validation...as we don't have
- // a certificate file for it to authenticate the host www.ups.com against!
- curl_setopt($CR, CURLOPT_SSL_VERIFYPEER, 0);
- //curl_setopt($CR, CURLOPT_SSLCERT , "/usr/locale/xxxx/clientcertificate.pem");
- }
- $result = curl_exec( $CR );
- $error = curl_error( $CR );
- if( !empty( $error ) && stristr( $error, '502') && !empty( $proxyURL )) {
- // $vmLogger->debug( 'Switching to NTLM authenticaton.');
- curl_setopt( $CR, CURLOPT_PROXYAUTH, CURLAUTH_NTLM );
- $result = curl_exec( $CR );
- $error = curl_error( $CR );
- }
- curl_close( $CR );
-
- if( !empty( $error )) {
- //JError::raiseError(1, $error );
- return false;
- } else {
- return $result;
- }
- } else {
- if( $postData ) {
- if( !empty( $proxyURL )) {
- // If we have something to post we need to write into a socket
- if( $proxyURL['scheme'] == 'https') {
- $protocol = 'ssl';
- }
- else {
- $protocol = 'http';
- }
- $fp = fsockopen("$protocol://".$proxyURL['host'], VM_PROXY_PORT, $errno, $errstr, $timeout = 30);
- }
- else {
- // If we have something to post we need to write into a socket
- if( $urlParts['scheme'] == 'https') {
- $protocol = 'ssl';
- }
- else {
- $protocol = $urlParts['scheme'];
- }
- $fp = fsockopen("$protocol://".$urlParts['host'], $urlParts['port'], $errno, $errstr, $timeout = 30);
- }
- } else {
- if( !empty( $proxyURL )) {
- // Do a read-only fopen transaction
- $fp = fopen( $proxyURL['scheme'].'://'.$proxyURL['host'].':'.VM_PROXY_PORT, 'rb' );
- }
- else {
- // Do a read-only fopen transaction
- $fp = fopen( $urlParts['scheme'].'://'.$urlParts['host'].':'.$urlParts['port'].$urlParts['path'], 'rb' );
- }
- }
- if(!$fp) {
- //error tell us
- JError::raiseWarning(1, 'Possible server error! - '.$errstr .'('.$errno.')\n' );
- return false;
- }
- else {
- //Would be interesting to set this only for debug
- // JError::raiseNotice(1, 'Connection opened to '.$urlParts['host']);
- }
- if( $postData ) {
- // $vmLogger->debug('Now posting the variables.' );
- //send the server request
- if( !empty( $proxyURL )) {
- fputs($fp, "POST ".$urlParts['host'].':'.$urlParts['port'].$urlParts['path']." HTTP/1.0\r\n");
- fputs($fp, "Host: ".$proxyURL['host']."\r\n");
-
- if( trim( @VM_PROXY_USER )!= '') {
- fputs($fp, "Proxy-Authorization: Basic " . base64_encode (VM_PROXY_USER.':'.VM_PROXY_PASS ) . "\r\n\r\n");
- }
- }
- else {
- fputs($fp, 'POST '.$urlParts['path']." HTTP/1.0\r\n");
- fputs($fp, 'Host:'. $urlParts['host']."\r\n");
- }
- fputs($fp, "Content-type: application/x-www-form-urlencoded\r\n");
- fputs($fp, "Content-length: ".strlen($postData)."\r\n");
- fputs($fp, "Connection: close\r\n\r\n");
- fputs($fp, $postData . "\r\n\r\n");
- } else {
- if( !empty( $proxyURL )) {
- fputs($fp, "GET ".$urlParts['host'].':'.$urlParts['port'].$urlParts['path']." HTTP/1.0\r\n");
- fputs($fp, "Host: ".$proxyURL['host']."\r\n");
- if( trim( @VM_PROXY_USER )!= '') {
- fputs($fp, "Proxy-Authorization: Basic " . base64_encode (VM_PROXY_USER.':'.VM_PROXY_PASS ) . "\r\n\r\n");
- }
- }
- else {
- // JError::raiseNotice(1, 'Host:'. $urlParts['host'].' path: '. $urlParts['path'] );
- fputs($fp, 'GET '.$urlParts['path']." HTTP/1.0\r\n");
- fputs($fp, 'Host:'. $urlParts['host']."\r\n");
- }
- }
- // Add additional headers if provided
- foreach( $headers as $header ) {
- fputs($fp, $header."\r\n");
- }
- $data = "";
- while (!feof($fp)) {
- $data .= @fgets ($fp, 4096);
- }
- fclose( $fp );
-
- // If didnt get content-lenght, something is wrong, return false.
- if ( trim($data) == '' ) {
- JError::raiseWarning(E_WARNING,'An error occured while communicating with the server '.$urlParts['host'].'. It didn\'t reply (correctly). Please try again later, thank you.' );
- return false;
- }
- $result = trim( $data );
- if( is_resource($fileToSaveData )) {
- fwrite($fileToSaveData, $result );
- return true;
- } else {
- return $result;
- }
- }
- }
- /**
- * Set headers and send the file to the client
- *
- * @author Andreas Gohr <andi@splitbrain.org>
- * @param string The full path to the file
- * @param string The Mime Type of the file
- */
- function sendFile($file,$mime, $overrideFileName='') {
-
- // send headers
- header("Content-Type: $mime");
-
- list($start,$len) = VmConnector::http_rangeRequest(filesize($file));
-
- header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
- header('Pragma: public');
- header('Accept-Ranges: bytes');
-
- //application mime type is downloadable
- if(strtolower(substr($mime,0,11)) == 'application') {
- if( $overrideFileName == '') {
- $filename = basename($file);
- } else {
- $filename = $overrideFileName;
- }
- header('Content-Disposition: attachment; filename="'.$filename.'";');
- }
-
- $chunksize = 1*(1024*1024);
- // send file contents
- $fp = @fopen($file,"rb");
- if($fp) {
- fseek($fp,$start); //seek to start of range
-
- $chunk = ($len > $chunksize) ? $chunksize : $len;
- while (!feof($fp) && $chunk > 0) {
- @set_time_limit(); // large files can take a lot of time
- print fread($fp, $chunk);
- flush();
- $len -= $chunk;
- $chunk = ($len > $chunksize) ? $chunksize : $len;
- }
- fclose($fp);
- }else {
- header("HTTP/1.0 500 Internal Server Error");
- print "Could not read $file - bad permissions?";
- JFactory::getApplication()->close(true);
- }
- }
- /**
- * Checks and sets headers to handle range requets
- *
- * @author Andreas Gohr <andi@splitbrain.org>
- * @return array The start byte and the amount of bytes to send
- * @param int The file size
- */
- function http_rangeRequest($size, $exitOnError=true ) {
-
- if(!isset($_SERVER['HTTP_RANGE'])) {
- // no range requested - send the whole file
- header("Content-Length: $size");
- return array(0,$size);
- }
-
- $t = explode('=', $_SERVER['HTTP_RANGE']);
- if (!$t[0]=='bytes') {
- // we only understand byte ranges - send the whole file
- header("Content-Length: $size");
- return array(0,$size);
- }
-
- $r = explode('-', $t[1]);
- $start = (int)$r[0];
- $end = (int)$r[1];
- if (!$end) $end = $size - 1;
- if ($start > $end || $start > $size || $end > $size) {
- if( $exitOnError ) {
- header('HTTP/1.1 416 Requested Range Not Satisfiable');
- print 'Bad Range Request!';
- JFactory::getApplication()->close(true);
- } else {
- return array(0,$size);
- }
- }
-
- $tot = $end - $start + 1;
- header('HTTP/1.1 206 Partial Content');
- header("Content-Range: bytes {$start}-{$end}/{$size}");
- header("Content-Length: $tot");
-
- return array($start,$tot);
- }
- }
- // pure php no closing tag