www.gusucode.com > ShopEx481 & PHPWind 整合版码程序 > core/assistant/lib/nudime.php

    <?php
require_once('nusoap.php');
require_once('DIME.php');

class nusoap_server_dime extends nusoap_server {
	
	var $requestAttachments  = array();	
	var $responseAttachments = array();
	var $raw_post_data;
	var $dimeContentType = 'application/dime';
	var $soap_defencoding = 'UTF-8';
	var $decode_utf8 = false;
	var $validate_factory = null;
			
	function addAttachment($data, $contenttype = 'application/octet-stream', $type=NET_DIME_TYPE_UNKNOWN, $cid = false) {
		if (! $cid) {
			$cid = md5(uniqid(time()));
		}
				
		$info = array();
		$info['data'] = $data;
		$info['filename'] = $cid;
		$info['contenttype'] = $contenttype;
		$info['cid'] = $cid;
		$info['type'] = $type;
		
		$this->responseAttachments[] = $info;
		
		return $cid;
	}
	
	function clearAttachments() {
		$this->responseAttachments = array();
	}
		
	function getAttachments() {
		return $this->requestAttachments;
	}

	function getHTTPBody($soapmsg) {		 
		//file_put_contents(dirname(__FILE__).'/logout.txt', $soapmsg);				
		if (count($this->responseAttachments) > 0) {									
			$soapmsg = &$this->_makeDIMEMessage($soapmsg);										
		}

		return parent::getHTTPBody($soapmsg);						
	}
	
	function getHTTPContentType() {
		if (count($this->responseAttachments) > 0) {
			return $this->dimeContentType;
		}
		return parent::getHTTPContentType();
	}
	
	function getHTTPContentTypeCharset() {
		if (count($this->responseAttachments) > 0) {
			return false;
		}
		return parent::getHTTPContentTypeCharset();
	}
	
	function service(&$data){
		$this->raw_post_data = $data;		
		parent::service($data);		
	}
					
    function parseRequest($headers, $data) {
		$this->debug('Entering parseRequest() for payload of length ' . strlen($data) . ' and type of ' . $headers['content-type']);
		$this->requestAttachments = array();
		
		//ob_start();
		//var_dump($headers);
		//var_dump($data);		
		//echo "\r\n\r\n";		
		if (strstr($headers['content-type'], $this->dimeContentType)) 
		{			
			$this->_decodeDIMEMessage($headers, $data);						
		}else{
			$this->debug('Not dime content');						
		}
		
		if(!$this->validate_signatrue($data)){
			$this->fault('TokenError', '证书验证失败,请使用正确的ShopEx证书。');
		}
			
		//var_dump($this->requestAttachments);			
		//$logdata = ob_get_contents();		
		//file_put_contents(dirname(__FILE__).'/log.txt', $logdata);
		//ob_end_clean();
								
		return parent::parseRequest($headers, $data);
	}
		   
    function &_makeDIMEMessage(&$xml)
    {
        // encode any attachments
        // see http://msdn.microsoft.com/library/en-us/dnglobspec/html/draft-nielsen-dime-02.txt
        // now we have to DIME encode the message
        $dime = &new Net_DIME_Message();
        $msg  = &$dime->encodeData($xml, $this->namespaces['SOAP-ENV'], NULL, NET_DIME_TYPE_URI);

        // add the attachements
        $c = count($this->responseAttachments);
        $this->debug('Found '. $c .' attachments');
        for ($i=0; $i < $c; $i++) {
            $att =& $this->responseAttachments[$i];            
            $msg .= $dime->encodeData($att['data'], $att['contenttype'], $att['cid'], NET_DIME_TYPE_MEDIA);
        }
        $msg .= $dime->endMessage();
        return $msg;
    }

    function _decodeDIMEMessage(&$headers, &$data)
    {
        // XXX this SHOULD be moved to the transport layer, e.g. PHP  itself        
        $dime =& new Net_DIME_Message();
        $err = $dime->decodeData($data);
        if ( PEAR::isError($err) ) 
        {
            $this->_raiseSoapFault('Failed to decode the DIME message!','','','Server');
            $this->debug('Failed to decode the DIME message!');
            $this->setError('Failed to decode the DIME message!');
            return;
        }
        if (strcasecmp($dime->parts[0]['type'], $this->namespaces['SOAP-ENV']) != 0) 
        {
            $this->_raiseSoapFault('DIME record 1 is not a SOAP envelop!','','','Server');
            $this->debug('DIME record 1 is not a SOAP envelop!');
            $this->setError('DIME record 1 is not a SOAP envelop!');
            return;
        }

        // return by reference
        $data = $dime->parts[0]['data'];
        $headers['content-type'] = 'text/xml;charset=utf-8';
        $headers["content-length"] = strlen($data);
        $c = count($dime->parts);
        for ($i = 1; $i < $c; $i++) 
        {
            $part =& $dime->parts[$i];
            // XXX we need to handle URI's better
            //$id = strncmp( $part['id'], 'cid:', 4 ) ? 'cid:'.$part['id'] : $part['id'];
            $info = array('cid' 	    => $part['id'],
				 		  'filename' 	=> $part['id'],
				 		  'contenttype' => $part['type'],
				 		  'data' 		=> $part['data']
				 				  );
			$this->requestAttachments[$part['id']] = $info;            
			$this->debug('Attachment Type:' . $part['type'] . 'id/uri: '. $id );
        }
    }
    
    function validate_signatrue($xml_data){
		$parser = new shopexapi_validate_parser($this);
		$xdata = $parser->parse($xml_data);

		if ($this->validate_factory)
		{
			return call_user_func_array($this->validate_factory,array($xdata['CLIENTID'],$xdata['SOAP-BODY'],$xdata['DIGESTVALUE'],$xdata['DIGEST_ALGORITHM'],$xdata['METHOD'],$xdata['DIGEST_OPTIONS']));
		}
		
		return true;
	}
}

/*
 *	For backwards compatiblity
 */
class nusoapserverdime extends nusoap_server_dime {
}


class shopexapi_validate_parser{

	var $ns=null;

	function shopexapi_validate_parser(&$api_server){
		$this->api_server = &$api_server;
	}

	function parse($xml_data){
		$this->path=array();
		$xml_parser = xml_parser_create();
		xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, true);
		xml_set_element_handler($xml_parser, array(&$this,"start_element"), array(&$this,"end_element"));
		xml_set_character_data_handler($xml_parser, array(&$this,"character_data"));

		if (!xml_parse($xml_parser, $xml_data)) {
			$this->fault('Client', 'Request not of type text/xml');
		}
		xml_parser_free($xml_parser);
		preg_match('#\<'.str_replace('-','\-',$this->ns).'\:Body[^>]*\>(.*)\</'.str_replace('-','\-',$this->ns).'\:Body\>#i',$xml_data,$matchs);
		$this->result['SOAP-BODY'] = $matchs[1];
//        print_r($this->result);
		return $this->result;
	}

	function start_element($parser, $name, $attrs){
		array_push($this->path,$name);
		if(!$this->ns){
			if(preg_match('#(.+)\:ENVELOPE#i',$name,$matchs)){
				$this->ns = $matchs[1];
			}
		}else{
			if($name == 'DIGESTMETHOD' && in_array('SHOPEX-SEC',$this->path)){
				$this->result['DIGEST_ALGORITHM'] = $attrs['ALGORITHM'];
				unset($attrs['ALGORITHM']);
				$this->result['DIGEST_OPTIONS'] = $attrs;
			}elseif(strtolower($name) == strtolower($this->ns.':body')){
				xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, false);
			}elseif(strtolower($this->path[count($this->path)-2]) == strtolower($this->ns.':body')){
				$this->result['METHOD'] = ($pos = strpos($name,':'))?substr($name,$pos+1):$name;						                    
				if(isset($attrs['VERSION']) && $attrs['VERSION'])$this->api_server->cmd_version = $attrs['VERSION'];
			}
		}
	}

	function character_data($parser,$data){
		if(in_array('SHOPEX-SEC',$this->path)){
			if(in_array('DIGESTVALUE',$this->path)){
				$this->result['DIGESTVALUE'] = $data;
			}elseif(in_array('CLIENTID',$this->path)){
				$this->result['CLIENTID'] = $data;
			}
		}
	}

	function end_element($parser, $name){
		array_pop($this->path);
	}
}

?>