ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
nusoap.php File Reference

Go to the source code of this file.

Data Structures

class  nusoap_base
 nusoap_base More...
 
class  nusoap_fault
 Contains information for a SOAP fault. More...
 
class  soap_fault
 soap_fault class, allows for creation of faults mainly used for returning faults from deployed functions in a server instance. More...
 
class  nusoap_xmlschema
 parses an XML Schema, allows access to it's data, other utility methods. More...
 
class  XMLSchema
 parses an XML Schema, allows access to it's data, other utility methods no validation... More...
 
class  soapval
 for creating serializable abstractions of native PHP types NOTE: this is only really used when WSDL is not available. More...
 
class  soap_transport_http
 transport class for sending/receiving data via HTTP and HTTPS NOTE: PHP must be compiled with the CURL extension for HTTPS support More...
 
class  nusoap_server
 nusoap_server allows the user to create a SOAP server that is capable of receiving messages and returning responses More...
 
class  soap_server
 soap_server allows the user to create a SOAP server that is capable of receiving messages and returning responses More...
 
class  wsdl
 parses a WSDL file, allows access to it's data, other utility methods More...
 
class  nusoap_parser
 nusoap_parser class parses SOAP XML messages into native PHP values More...
 
class  soap_parser
 soap_parser class parses SOAP XML messages into native PHP values More...
 
class  nusoap_client
 [nu]soapclient higher level class for easy usage. More...
 

Functions

 timestamp_to_iso8601 ($timestamp, $utc=true)
 convert unix timestamp to ISO 8601 compliant date string More...
 
 iso8601_to_timestamp ($datestr)
 convert ISO 8601 compliant date string to unix timestamp More...
 
 usleepWindows ($usec)
 sleeps some number of microseconds More...
 

Variables

if(!is_object($GLOBALS['_transient']['static']['nusoap_base'])) $GLOBALS [ '_transient'][ 'static'][ 'nusoap_base'] globalDebugLevel = 0
 

Function Documentation

◆ iso8601_to_timestamp()

iso8601_to_timestamp (   $datestr)

convert ISO 8601 compliant date string to unix timestamp

Parameters
string$datestrISO 8601 compliant date string public

Definition at line 939 of file nusoap.php.

References $h, and $m.

939  {
940  $pattern = '/'.
941  '([0-9]{4})-'. // centuries & years CCYY-
942  '([0-9]{2})-'. // months MM-
943  '([0-9]{2})'. // days DD
944  'T'. // separator T
945  '([0-9]{2}):'. // hours hh:
946  '([0-9]{2}):'. // minutes mm:
947  '([0-9]{2})(\.[0-9]+)?'. // seconds ss.ss...
948  '(Z|[+\-][0-9]{2}:?[0-9]{2})?'. // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
949  '/';
950 
951  if(preg_match($pattern,$datestr,$regs)){
952  // not utc
953  if($regs[8] != 'Z'){
954  $op = substr($regs[8],0,1);
955  $h = substr($regs[8],1,2);
956  $m = substr($regs[8],strlen($regs[8])-2,2);
957  if($op == '-'){
958  $regs[4] = $regs[4] + $h;
959  $regs[5] = $regs[5] + $m;
960  } elseif($op == '+'){
961  $regs[4] = $regs[4] - $h;
962  $regs[5] = $regs[5] - $m;
963  }
964  }
965  return gmmktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
966 // return strtotime("$regs[1]-$regs[2]-$regs[3] $regs[4]:$regs[5]:$regs[6]Z");
967  } else {
968  return false;
969  }
970 }
$h

◆ timestamp_to_iso8601()

timestamp_to_iso8601 (   $timestamp,
  $utc = true 
)

convert unix timestamp to ISO 8601 compliant date string

Parameters
string$timestampUnix time stamp
boolean$utcWhether the time stamp is UTC or local public

Definition at line 910 of file nusoap.php.

References $timestamp.

910  {
911  $datestr = date('Y-m-d\TH:i:sO',$timestamp);
912  if($utc){
913  $pattern = '/'.
914  '([0-9]{4})-'. // centuries & years CCYY-
915  '([0-9]{2})-'. // months MM-
916  '([0-9]{2})'. // days DD
917  'T'. // separator T
918  '([0-9]{2}):'. // hours hh:
919  '([0-9]{2}):'. // minutes mm:
920  '([0-9]{2})(\.[0-9]*)?'. // seconds ss.ss...
921  '(Z|[+\-][0-9]{2}:?[0-9]{2})?'. // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
922  '/';
923 
924  if(preg_match($pattern,$datestr,$regs)){
925  return sprintf('%04d-%02d-%02dT%02d:%02d:%02dZ',$regs[1],$regs[2],$regs[3],$regs[4],$regs[5],$regs[6]);
926  }
927  return false;
928  } else {
929  return $datestr;
930  }
931 }
foreach($mandatory_scripts as $file) $timestamp
Definition: buildRTE.php:81

◆ usleepWindows()

usleepWindows (   $usec)

sleeps some number of microseconds

Parameters
string$usecthe number of microseconds to sleep public
Deprecated:

For backwards compatiblity, define soapclient unless the PHP SOAP extension is loaded.

Definition at line 979 of file nusoap.php.

References $start.

980 {
981  $start = gettimeofday();
982 
983  do
984  {
985  $stop = gettimeofday();
986  $timePassed = 1000000 * ($stop['sec'] - $start['sec'])
987  + $stop['usec'] - $start['usec'];
988  }
989  while ($timePassed < $usec);
990 }
991 
992 ?><?php
993 
994 
995 
1004 class nusoap_fault extends nusoap_base {
1010  var $faultcode;
1016  var $faultactor;
1022  var $faultstring;
1028  var $faultdetail;
1029 
1038  function __construct($faultcode,$faultactor='',$faultstring='',$faultdetail=''){
1039  parent::__construct();
1040  $this->faultcode = $faultcode;
1041  $this->faultactor = $faultactor;
1042  $this->faultstring = $faultstring;
1043  $this->faultdetail = $faultdetail;
1044  }
1045 
1052  function serialize(){
1053  $ns_string = '';
1054  foreach($this->namespaces as $k => $v){
1055  $ns_string .= "\n xmlns:$k=\"$v\"";
1056  }
1057  $return_msg =
1058  '<?xml version="1.0" encoding="'.$this->soap_defencoding.'"?>'.
1059  '<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"'.$ns_string.">\n".
1060  '<SOAP-ENV:Body>'.
1061  '<SOAP-ENV:Fault>'.
1062  $this->serialize_val($this->faultcode, 'faultcode').
1063  $this->serialize_val($this->faultstring, 'faultstring').
1064  $this->serialize_val($this->faultactor, 'faultactor').
1065  $this->serialize_val($this->faultdetail, 'detail').
1066  '</SOAP-ENV:Fault>'.
1067  '</SOAP-ENV:Body>'.
1068  '</SOAP-ENV:Envelope>';
1069  return $return_msg;
1070  }
1071 }
1072 
1076 class soap_fault extends nusoap_fault {
1077 }
1078 
1079 ?><?php
1080 
1081 
1082 
1092 class nusoap_xmlschema extends nusoap_base {
1093 
1094  // files
1095  var $schema = '';
1096  var $xml = '';
1097  // namespaces
1098  var $enclosingNamespaces;
1099  // schema info
1100  var $schemaInfo = array();
1101  var $schemaTargetNamespace = '';
1102  // types, elements, attributes defined by the schema
1103  var $attributes = array();
1104  var $complexTypes = array();
1105  var $complexTypeStack = array();
1106  var $currentComplexType = null;
1107  var $elements = array();
1108  var $elementStack = array();
1109  var $currentElement = null;
1110  var $simpleTypes = array();
1111  var $simpleTypeStack = array();
1112  var $currentSimpleType = null;
1113  // imports
1114  var $imports = array();
1115  // parser vars
1116  var $parser;
1117  var $position = 0;
1118  var $depth = 0;
1119  var $depth_array = array();
1120  var $message = array();
1121  var $defaultNamespace = array();
1122 
1131  function __construct($schema='',$xml='',$namespaces=array()){
1132  parent::__construct();
1133  $this->debug('nusoap_xmlschema class instantiated, inside constructor');
1134  // files
1135  $this->schema = $schema;
1136  $this->xml = $xml;
1137 
1138  // namespaces
1139  $this->enclosingNamespaces = $namespaces;
1140  $this->namespaces = array_merge($this->namespaces, $namespaces);
1141 
1142  // parse schema file
1143  if($schema != ''){
1144  $this->debug('initial schema file: '.$schema);
1145  $this->parseFile($schema, 'schema');
1146  }
1147 
1148  // parse xml file
1149  if($xml != ''){
1150  $this->debug('initial xml file: '.$xml);
1151  $this->parseFile($xml, 'xml');
1152  }
1153 
1154  }
1155 
1164  function parseFile($xml,$type){
1165  // parse xml file
1166  if($xml != ""){
1167  $xmlStr = @join("",@file($xml));
1168  if($xmlStr == ""){
1169  $msg = 'Error reading XML from '.$xml;
1170  $this->setError($msg);
1171  $this->debug($msg);
1172  return false;
1173  } else {
1174  $this->debug("parsing $xml");
1175  $this->parseString($xmlStr,$type);
1176  $this->debug("done parsing $xml");
1177  return true;
1178  }
1179  }
1180  return false;
1181  }
1182 
1190  function parseString($xml,$type){
1191  // parse xml string
1192  if($xml != ""){
1193 
1194  // Create an XML parser.
1195  $this->parser = xml_parser_create();
1196  // Set the options for parsing the XML data.
1197  xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
1198 
1199  // Set the object for the parser.
1200  xml_set_object($this->parser, $this);
1201 
1202  // Set the element handlers for the parser.
1203  if($type == "schema"){
1204  xml_set_element_handler($this->parser, 'schemaStartElement','schemaEndElement');
1205  xml_set_character_data_handler($this->parser,'schemaCharacterData');
1206  } elseif($type == "xml"){
1207  xml_set_element_handler($this->parser, 'xmlStartElement','xmlEndElement');
1208  xml_set_character_data_handler($this->parser,'xmlCharacterData');
1209  }
1210 
1211  // Parse the XML file.
1212  if(!xml_parse($this->parser,$xml,true)){
1213  // Display an error message.
1214  $errstr = sprintf('XML error parsing XML schema on line %d: %s',
1215  xml_get_current_line_number($this->parser),
1216  xml_error_string(xml_get_error_code($this->parser))
1217  );
1218  $this->debug($errstr);
1219  $this->debug("XML payload:\n" . $xml);
1220  $this->setError($errstr);
1221  }
1222 
1223  xml_parser_free($this->parser);
1224  } else{
1225  $this->debug('no xml passed to parseString()!!');
1226  $this->setError('no xml passed to parseString()!!');
1227  }
1228  }
1229 
1237  function CreateTypeName($ename) {
1238  $scope = '';
1239  for ($i = 0; $i < count($this->complexTypeStack); $i++) {
1240  $scope .= $this->complexTypeStack[$i] . '_';
1241  }
1242  return $scope . $ename . '_ContainedType';
1243  }
1244 
1253  function schemaStartElement($parser, $name, $attrs) {
1254 
1255  // position in the total number of elements, starting from 0
1256  $pos = $this->position++;
1257  $depth = $this->depth++;
1258  // set self as current value for this depth
1259  $this->depth_array[$depth] = $pos;
1260  $this->message[$pos] = array('cdata' => '');
1261  if ($depth > 0) {
1262  $this->defaultNamespace[$pos] = $this->defaultNamespace[$this->depth_array[$depth - 1]];
1263  } else {
1264  $this->defaultNamespace[$pos] = false;
1265  }
1266 
1267  // get element prefix
1268  if($prefix = $this->getPrefix($name)){
1269  // get unqualified name
1270  $name = $this->getLocalPart($name);
1271  } else {
1272  $prefix = '';
1273  }
1274 
1275  // loop thru attributes, expanding, and registering namespace declarations
1276  if(count($attrs) > 0){
1277  foreach($attrs as $k => $v){
1278  // if ns declarations, add to class level array of valid namespaces
1279  if(preg_match('/^xmlns/',$k)){
1280  //$this->xdebug("$k: $v");
1281  //$this->xdebug('ns_prefix: '.$this->getPrefix($k));
1282  if($ns_prefix = substr(strrchr($k,':'),1)){
1283  //$this->xdebug("Add namespace[$ns_prefix] = $v");
1284  $this->namespaces[$ns_prefix] = $v;
1285  } else {
1286  $this->defaultNamespace[$pos] = $v;
1287  if (! $this->getPrefixFromNamespace($v)) {
1288  $this->namespaces['ns'.(count($this->namespaces)+1)] = $v;
1289  }
1290  }
1291  if($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema'){
1292  $this->XMLSchemaVersion = $v;
1293  $this->namespaces['xsi'] = $v.'-instance';
1294  }
1295  }
1296  }
1297  foreach($attrs as $k => $v){
1298  // expand each attribute
1299  $k = strpos($k,':') ? $this->expandQname($k) : $k;
1300  $v = strpos($v,':') ? $this->expandQname($v) : $v;
1301  $eAttrs[$k] = $v;
1302  }
1303  $attrs = $eAttrs;
1304  } else {
1305  $attrs = array();
1306  }
1307  // find status, register data
1308  switch($name){
1309  case 'all': // (optional) compositor content for a complexType
1310  case 'choice':
1311  case 'group':
1312  case 'sequence':
1313  //$this->xdebug("compositor $name for currentComplexType: $this->currentComplexType and currentElement: $this->currentElement");
1314  $this->complexTypes[$this->currentComplexType]['compositor'] = $name;
1315  //if($name == 'all' || $name == 'sequence'){
1316  // $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
1317  //}
1318  break;
1319  case 'attribute': // complexType attribute
1320  //$this->xdebug("parsing attribute $attrs[name] $attrs[ref] of value: ".$attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']);
1321  $this->xdebug("parsing attribute:");
1322  $this->appendDebug($this->varDump($attrs));
1323  if (!isset($attrs['form'])) {
1324  $attrs['form'] = $this->schemaInfo['attributeFormDefault'];
1325  }
1326  if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
1327  $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1328  if (!strpos($v, ':')) {
1329  // no namespace in arrayType attribute value...
1330  if ($this->defaultNamespace[$pos]) {
1331  // ...so use the default
1332  $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'] = $this->defaultNamespace[$pos] . ':' . $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1333  }
1334  }
1335  }
1336  if(isset($attrs['name'])){
1337  $this->attributes[$attrs['name']] = $attrs;
1338  $aname = $attrs['name'];
1339  } elseif(isset($attrs['ref']) && $attrs['ref'] == 'http://schemas.xmlsoap.org/soap/encoding/:arrayType'){
1340  if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
1341  $aname = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1342  } else {
1343  $aname = '';
1344  }
1345  } elseif(isset($attrs['ref'])){
1346  $aname = $attrs['ref'];
1347  $this->attributes[$attrs['ref']] = $attrs;
1348  }
1349 
1350  if($this->currentComplexType){ // This should *always* be
1351  $this->complexTypes[$this->currentComplexType]['attrs'][$aname] = $attrs;
1352  }
1353  // arrayType attribute
1354  if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']) || $this->getLocalPart($aname) == 'arrayType'){
1355  $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
1356  $prefix = $this->getPrefix($aname);
1357  if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])){
1358  $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1359  } else {
1360  $v = '';
1361  }
1362  if(strpos($v,'[,]')){
1363  $this->complexTypes[$this->currentComplexType]['multidimensional'] = true;
1364  }
1365  $v = substr($v,0,strpos($v,'[')); // clip the []
1366  if(!strpos($v,':') && isset($this->typemap[$this->XMLSchemaVersion][$v])){
1367  $v = $this->XMLSchemaVersion.':'.$v;
1368  }
1369  $this->complexTypes[$this->currentComplexType]['arrayType'] = $v;
1370  }
1371  break;
1372  case 'complexContent': // (optional) content for a complexType
1373  break;
1374  case 'complexType':
1375  array_push($this->complexTypeStack, $this->currentComplexType);
1376  if(isset($attrs['name'])){
1377  // TODO: what is the scope of named complexTypes that appear
1378  // nested within other c complexTypes?
1379  $this->xdebug('processing named complexType '.$attrs['name']);
1380  //$this->currentElement = false;
1381  $this->currentComplexType = $attrs['name'];
1382  $this->complexTypes[$this->currentComplexType] = $attrs;
1383  $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
1384  // This is for constructs like
1385  // <complexType name="ListOfString" base="soap:Array">
1386  // <sequence>
1387  // <element name="string" type="xsd:string"
1388  // minOccurs="0" maxOccurs="unbounded" />
1389  // </sequence>
1390  // </complexType>
1391  if(isset($attrs['base']) && preg_match('/:Array$/',$attrs['base'])){
1392  $this->xdebug('complexType is unusual array');
1393  $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
1394  } else {
1395  $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
1396  }
1397  } else {
1398  $name = $this->CreateTypeName($this->currentElement);
1399  $this->xdebug('processing unnamed complexType for element ' . $this->currentElement . ' named ' . $name);
1400  $this->currentComplexType = $name;
1401  //$this->currentElement = false;
1402  $this->complexTypes[$this->currentComplexType] = $attrs;
1403  $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
1404  // This is for constructs like
1405  // <complexType name="ListOfString" base="soap:Array">
1406  // <sequence>
1407  // <element name="string" type="xsd:string"
1408  // minOccurs="0" maxOccurs="unbounded" />
1409  // </sequence>
1410  // </complexType>
1411  if(isset($attrs['base']) && preg_match('/:Array$/',$attrs['base'])){
1412  $this->xdebug('complexType is unusual array');
1413  $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
1414  } else {
1415  $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
1416  }
1417  }
1418  break;
1419  case 'element':
1420  array_push($this->elementStack, $this->currentElement);
1421  if (!isset($attrs['form'])) {
1422  $attrs['form'] = $this->schemaInfo['elementFormDefault'];
1423  }
1424  if(isset($attrs['type'])){
1425  $this->xdebug("processing typed element ".$attrs['name']." of type ".$attrs['type']);
1426  if (! $this->getPrefix($attrs['type'])) {
1427  if ($this->defaultNamespace[$pos]) {
1428  $attrs['type'] = $this->defaultNamespace[$pos] . ':' . $attrs['type'];
1429  $this->xdebug('used default namespace to make type ' . $attrs['type']);
1430  }
1431  }
1432  // This is for constructs like
1433  // <complexType name="ListOfString" base="soap:Array">
1434  // <sequence>
1435  // <element name="string" type="xsd:string"
1436  // minOccurs="0" maxOccurs="unbounded" />
1437  // </sequence>
1438  // </complexType>
1439  if ($this->currentComplexType && $this->complexTypes[$this->currentComplexType]['phpType'] == 'array') {
1440  $this->xdebug('arrayType for unusual array is ' . $attrs['type']);
1441  $this->complexTypes[$this->currentComplexType]['arrayType'] = $attrs['type'];
1442  }
1443  $this->currentElement = $attrs['name'];
1444  $ename = $attrs['name'];
1445  } elseif(isset($attrs['ref'])){
1446  $this->xdebug("processing element as ref to ".$attrs['ref']);
1447  $this->currentElement = "ref to ".$attrs['ref'];
1448  $ename = $this->getLocalPart($attrs['ref']);
1449  } else {
1450  $type = $this->CreateTypeName($this->currentComplexType . '_' . $attrs['name']);
1451  $this->xdebug("processing untyped element " . $attrs['name'] . ' type ' . $type);
1452  $this->currentElement = $attrs['name'];
1453  $attrs['type'] = $this->schemaTargetNamespace . ':' . $type;
1454  $ename = $attrs['name'];
1455  }
1456  if (isset($ename) && $this->currentComplexType) {
1457  $this->xdebug("add element $ename to complexType $this->currentComplexType");
1458  $this->complexTypes[$this->currentComplexType]['elements'][$ename] = $attrs;
1459  } elseif (!isset($attrs['ref'])) {
1460  $this->xdebug("add element $ename to elements array");
1461  $this->elements[ $attrs['name'] ] = $attrs;
1462  $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
1463  }
1464  break;
1465  case 'enumeration': // restriction value list member
1466  $this->xdebug('enumeration ' . $attrs['value']);
1467  if ($this->currentSimpleType) {
1468  $this->simpleTypes[$this->currentSimpleType]['enumeration'][] = $attrs['value'];
1469  } elseif ($this->currentComplexType) {
1470  $this->complexTypes[$this->currentComplexType]['enumeration'][] = $attrs['value'];
1471  }
1472  break;
1473  case 'extension': // simpleContent or complexContent type extension
1474  $this->xdebug('extension ' . $attrs['base']);
1475  if ($this->currentComplexType) {
1476  $this->complexTypes[$this->currentComplexType]['extensionBase'] = $attrs['base'];
1477  }
1478  break;
1479  case 'import':
1480  if (isset($attrs['schemaLocation'])) {
1481  //$this->xdebug('import namespace ' . $attrs['namespace'] . ' from ' . $attrs['schemaLocation']);
1482  $this->imports[$attrs['namespace']][] = array('location' => $attrs['schemaLocation'], 'loaded' => false);
1483  } else {
1484  //$this->xdebug('import namespace ' . $attrs['namespace']);
1485  $this->imports[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
1486  if (! $this->getPrefixFromNamespace($attrs['namespace'])) {
1487  $this->namespaces['ns'.(count($this->namespaces)+1)] = $attrs['namespace'];
1488  }
1489  }
1490  break;
1491  case 'list': // simpleType value list
1492  break;
1493  case 'restriction': // simpleType, simpleContent or complexContent value restriction
1494  $this->xdebug('restriction ' . $attrs['base']);
1495  if($this->currentSimpleType){
1496  $this->simpleTypes[$this->currentSimpleType]['type'] = $attrs['base'];
1497  } elseif($this->currentComplexType){
1498  $this->complexTypes[$this->currentComplexType]['restrictionBase'] = $attrs['base'];
1499  if(strstr($attrs['base'],':') == ':Array'){
1500  $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
1501  }
1502  }
1503  break;
1504  case 'schema':
1505  $this->schemaInfo = $attrs;
1506  $this->schemaInfo['schemaVersion'] = $this->getNamespaceFromPrefix($prefix);
1507  if (isset($attrs['targetNamespace'])) {
1508  $this->schemaTargetNamespace = $attrs['targetNamespace'];
1509  }
1510  if (!isset($attrs['elementFormDefault'])) {
1511  $this->schemaInfo['elementFormDefault'] = 'unqualified';
1512  }
1513  if (!isset($attrs['attributeFormDefault'])) {
1514  $this->schemaInfo['attributeFormDefault'] = 'unqualified';
1515  }
1516  break;
1517  case 'simpleContent': // (optional) content for a complexType
1518  break;
1519  case 'simpleType':
1520  array_push($this->simpleTypeStack, $this->currentSimpleType);
1521  if(isset($attrs['name'])){
1522  $this->xdebug("processing simpleType for name " . $attrs['name']);
1523  $this->currentSimpleType = $attrs['name'];
1524  $this->simpleTypes[ $attrs['name'] ] = $attrs;
1525  $this->simpleTypes[ $attrs['name'] ]['typeClass'] = 'simpleType';
1526  $this->simpleTypes[ $attrs['name'] ]['phpType'] = 'scalar';
1527  } else {
1528  $name = $this->CreateTypeName($this->currentComplexType . '_' . $this->currentElement);
1529  $this->xdebug('processing unnamed simpleType for element ' . $this->currentElement . ' named ' . $name);
1530  $this->currentSimpleType = $name;
1531  //$this->currentElement = false;
1532  $this->simpleTypes[$this->currentSimpleType] = $attrs;
1533  $this->simpleTypes[$this->currentSimpleType]['phpType'] = 'scalar';
1534  }
1535  break;
1536  case 'union': // simpleType type list
1537  break;
1538  default:
1539  //$this->xdebug("do not have anything to do for element $name");
1540  }
1541  }
1542 
1550  function schemaEndElement($parser, $name) {
1551  // bring depth down a notch
1552  $this->depth--;
1553  // position of current element is equal to the last value left in depth_array for my depth
1554  if(isset($this->depth_array[$this->depth])){
1555  $pos = $this->depth_array[$this->depth];
1556  }
1557  // get element prefix
1558  if ($prefix = $this->getPrefix($name)){
1559  // get unqualified name
1560  $name = $this->getLocalPart($name);
1561  } else {
1562  $prefix = '';
1563  }
1564  // move on...
1565  if($name == 'complexType'){
1566  $this->xdebug('done processing complexType ' . ($this->currentComplexType ? $this->currentComplexType : '(unknown)'));
1567  $this->currentComplexType = array_pop($this->complexTypeStack);
1568  //$this->currentElement = false;
1569  }
1570  if($name == 'element'){
1571  $this->xdebug('done processing element ' . ($this->currentElement ? $this->currentElement : '(unknown)'));
1572  $this->currentElement = array_pop($this->elementStack);
1573  }
1574  if($name == 'simpleType'){
1575  $this->xdebug('done processing simpleType ' . ($this->currentSimpleType ? $this->currentSimpleType : '(unknown)'));
1576  $this->currentSimpleType = array_pop($this->simpleTypeStack);
1577  }
1578  }
1579 
1587  function schemaCharacterData($parser, $data){
1588  $pos = $this->depth_array[$this->depth - 1];
1589  $this->message[$pos]['cdata'] .= $data;
1590  }
1591 
1597  function serializeSchema(){
1598 
1599  $schemaPrefix = $this->getPrefixFromNamespace($this->XMLSchemaVersion);
1600  $xml = '';
1601  // imports
1602  if (sizeof($this->imports) > 0) {
1603  foreach($this->imports as $ns => $list) {
1604  foreach ($list as $ii) {
1605  if ($ii['location'] != '') {
1606  $xml .= " <$schemaPrefix:import location=\"" . $ii['location'] . '" namespace="' . $ns . "\" />\n";
1607  } else {
1608  $xml .= " <$schemaPrefix:import namespace=\"" . $ns . "\" />\n";
1609  }
1610  }
1611  }
1612  }
1613  // complex types
1614  foreach($this->complexTypes as $typeName => $attrs){
1615  $contentStr = '';
1616  // serialize child elements
1617  if(isset($attrs['elements']) && (count($attrs['elements']) > 0)){
1618  foreach($attrs['elements'] as $element => $eParts){
1619  if(isset($eParts['ref'])){
1620  $contentStr .= " <$schemaPrefix:element ref=\"$element\"/>\n";
1621  } else {
1622  $contentStr .= " <$schemaPrefix:element name=\"$element\" type=\"" . $this->contractQName($eParts['type']) . "\"";
1623  foreach ($eParts as $aName => $aValue) {
1624  // handle, e.g., abstract, default, form, minOccurs, maxOccurs, nillable
1625  if ($aName != 'name' && $aName != 'type') {
1626  $contentStr .= " $aName=\"$aValue\"";
1627  }
1628  }
1629  $contentStr .= "/>\n";
1630  }
1631  }
1632  // compositor wraps elements
1633  if (isset($attrs['compositor']) && ($attrs['compositor'] != '')) {
1634  $contentStr = " <$schemaPrefix:$attrs[compositor]>\n".$contentStr." </$schemaPrefix:$attrs[compositor]>\n";
1635  }
1636  }
1637  // attributes
1638  if(isset($attrs['attrs']) && (count($attrs['attrs']) >= 1)){
1639  foreach($attrs['attrs'] as $attr => $aParts){
1640  $contentStr .= " <$schemaPrefix:attribute";
1641  foreach ($aParts as $a => $v) {
1642  if ($a == 'ref' || $a == 'type') {
1643  $contentStr .= " $a=\"".$this->contractQName($v).'"';
1644  } elseif ($a == 'http://schemas.xmlsoap.org/wsdl/:arrayType') {
1645  $this->usedNamespaces['wsdl'] = $this->namespaces['wsdl'];
1646  $contentStr .= ' wsdl:arrayType="'.$this->contractQName($v).'"';
1647  } else {
1648  $contentStr .= " $a=\"$v\"";
1649  }
1650  }
1651  $contentStr .= "/>\n";
1652  }
1653  }
1654  // if restriction
1655  if (isset($attrs['restrictionBase']) && $attrs['restrictionBase'] != ''){
1656  $contentStr = " <$schemaPrefix:restriction base=\"".$this->contractQName($attrs['restrictionBase'])."\">\n".$contentStr." </$schemaPrefix:restriction>\n";
1657  // complex or simple content
1658  if ((isset($attrs['elements']) && count($attrs['elements']) > 0) || (isset($attrs['attrs']) && count($attrs['attrs']) > 0)){
1659  $contentStr = " <$schemaPrefix:complexContent>\n".$contentStr." </$schemaPrefix:complexContent>\n";
1660  }
1661  }
1662  // finalize complex type
1663  if($contentStr != ''){
1664  $contentStr = " <$schemaPrefix:complexType name=\"$typeName\">\n".$contentStr." </$schemaPrefix:complexType>\n";
1665  } else {
1666  $contentStr = " <$schemaPrefix:complexType name=\"$typeName\"/>\n";
1667  }
1668  $xml .= $contentStr;
1669  }
1670  // simple types
1671  if(isset($this->simpleTypes) && count($this->simpleTypes) > 0){
1672  foreach($this->simpleTypes as $typeName => $eParts){
1673  $xml .= " <$schemaPrefix:simpleType name=\"$typeName\">\n <$schemaPrefix:restriction base=\"".$this->contractQName($eParts['type'])."\">\n";
1674  if (isset($eParts['enumeration'])) {
1675  foreach ($eParts['enumeration'] as $e) {
1676  $xml .= " <$schemaPrefix:enumeration value=\"$e\"/>\n";
1677  }
1678  }
1679  $xml .= " </$schemaPrefix:restriction>\n </$schemaPrefix:simpleType>";
1680  }
1681  }
1682  // elements
1683  if(isset($this->elements) && count($this->elements) > 0){
1684  foreach($this->elements as $element => $eParts){
1685  $xml .= " <$schemaPrefix:element name=\"$element\" type=\"".$this->contractQName($eParts['type'])."\"/>\n";
1686  }
1687  }
1688  // attributes
1689  if(isset($this->attributes) && count($this->attributes) > 0){
1690  foreach($this->attributes as $attr => $aParts){
1691  $xml .= " <$schemaPrefix:attribute name=\"$attr\" type=\"".$this->contractQName($aParts['type'])."\"\n/>";
1692  }
1693  }
1694  // finish 'er up
1695  $attr = '';
1696  foreach ($this->schemaInfo as $k => $v) {
1697  if ($k == 'elementFormDefault' || $k == 'attributeFormDefault') {
1698  $attr .= " $k=\"$v\"";
1699  }
1700  }
1701  $el = "<$schemaPrefix:schema$attr targetNamespace=\"$this->schemaTargetNamespace\"\n";
1702  foreach (array_diff($this->usedNamespaces, $this->enclosingNamespaces) as $nsp => $ns) {
1703  $el .= " xmlns:$nsp=\"$ns\"";
1704  }
1705  $xml = $el . ">\n".$xml."</$schemaPrefix:schema>\n";
1706  return $xml;
1707  }
1708 
1715  function xdebug($string){
1716  $this->debug('<' . $this->schemaTargetNamespace . '> '.$string);
1717  }
1718 
1731  function getPHPType($type,$ns){
1732  if(isset($this->typemap[$ns][$type])){
1733  //print "found type '$type' and ns $ns in typemap<br>";
1734  return $this->typemap[$ns][$type];
1735  } elseif(isset($this->complexTypes[$type])){
1736  //print "getting type '$type' and ns $ns from complexTypes array<br>";
1737  return $this->complexTypes[$type]['phpType'];
1738  }
1739  return false;
1740  }
1741 
1764  function getTypeDef($type){
1765  //$this->debug("in getTypeDef for type $type");
1766  if (substr($type, -1) == '^') {
1767  $is_element = 1;
1768  $type = substr($type, 0, -1);
1769  } else {
1770  $is_element = 0;
1771  }
1772 
1773  if((! $is_element) && isset($this->complexTypes[$type])){
1774  $this->xdebug("in getTypeDef, found complexType $type");
1775  return $this->complexTypes[$type];
1776  } elseif((! $is_element) && isset($this->simpleTypes[$type])){
1777  $this->xdebug("in getTypeDef, found simpleType $type");
1778  if (!isset($this->simpleTypes[$type]['phpType'])) {
1779  // get info for type to tack onto the simple type
1780  // TODO: can this ever really apply (i.e. what is a simpleType really?)
1781  $uqType = substr($this->simpleTypes[$type]['type'], strrpos($this->simpleTypes[$type]['type'], ':') + 1);
1782  $ns = substr($this->simpleTypes[$type]['type'], 0, strrpos($this->simpleTypes[$type]['type'], ':'));
1783  $etype = $this->getTypeDef($uqType);
1784  if ($etype) {
1785  $this->xdebug("in getTypeDef, found type for simpleType $type:");
1786  $this->xdebug($this->varDump($etype));
1787  if (isset($etype['phpType'])) {
1788  $this->simpleTypes[$type]['phpType'] = $etype['phpType'];
1789  }
1790  if (isset($etype['elements'])) {
1791  $this->simpleTypes[$type]['elements'] = $etype['elements'];
1792  }
1793  }
1794  }
1795  return $this->simpleTypes[$type];
1796  } elseif(isset($this->elements[$type])){
1797  $this->xdebug("in getTypeDef, found element $type");
1798  if (!isset($this->elements[$type]['phpType'])) {
1799  // get info for type to tack onto the element
1800  $uqType = substr($this->elements[$type]['type'], strrpos($this->elements[$type]['type'], ':') + 1);
1801  $ns = substr($this->elements[$type]['type'], 0, strrpos($this->elements[$type]['type'], ':'));
1802  $etype = $this->getTypeDef($uqType);
1803  if ($etype) {
1804  $this->xdebug("in getTypeDef, found type for element $type:");
1805  $this->xdebug($this->varDump($etype));
1806  if (isset($etype['phpType'])) {
1807  $this->elements[$type]['phpType'] = $etype['phpType'];
1808  }
1809  if (isset($etype['elements'])) {
1810  $this->elements[$type]['elements'] = $etype['elements'];
1811  }
1812  } elseif ($ns == 'http://www.w3.org/2001/XMLSchema') {
1813  $this->xdebug("in getTypeDef, element $type is an XSD type");
1814  $this->elements[$type]['phpType'] = 'scalar';
1815  }
1816  }
1817  return $this->elements[$type];
1818  } elseif(isset($this->attributes[$type])){
1819  $this->xdebug("in getTypeDef, found attribute $type");
1820  return $this->attributes[$type];
1821  } elseif (preg_match('/_ContainedType$/', $type)) {
1822  $this->xdebug("in getTypeDef, have an untyped element $type");
1823  $typeDef['typeClass'] = 'simpleType';
1824  $typeDef['phpType'] = 'scalar';
1825  $typeDef['type'] = 'http://www.w3.org/2001/XMLSchema:string';
1826  return $typeDef;
1827  }
1828  $this->xdebug("in getTypeDef, did not find $type");
1829  return false;
1830  }
1831 
1840  function serializeTypeDef($type){
1841  //print "in sTD() for type $type<br>";
1842  if($typeDef = $this->getTypeDef($type)){
1843  $str .= '<'.$type;
1844  if(is_array($typeDef['attrs'])){
1845  foreach($typeDef['attrs'] as $attName => $data){
1846  $str .= " $attName=\"{type = ".$data['type']."}\"";
1847  }
1848  }
1849  $str .= " xmlns=\"".$this->schema['targetNamespace']."\"";
1850  if(count($typeDef['elements']) > 0){
1851  $str .= ">";
1852  foreach($typeDef['elements'] as $element => $eData){
1853  $str .= $this->serializeTypeDef($element);
1854  }
1855  $str .= "</$type>";
1856  } elseif($typeDef['typeClass'] == 'element') {
1857  $str .= "></$type>";
1858  } else {
1859  $str .= "/>";
1860  }
1861  return $str;
1862  }
1863  return false;
1864  }
1865 
1876  function typeToForm($name,$type){
1877  // get typedef
1878  if($typeDef = $this->getTypeDef($type)){
1879  // if struct
1880  if($typeDef['phpType'] == 'struct'){
1881  $buffer .= '<table>';
1882  foreach($typeDef['elements'] as $child => $childDef){
1883  $buffer .= "
1884  <tr><td align='right'>$childDef[name] (type: ".$this->getLocalPart($childDef['type'])."):</td>
1885  <td><input type='text' name='parameters[".$name."][$childDef[name]]'></td></tr>";
1886  }
1887  $buffer .= '</table>';
1888  // if array
1889  } elseif($typeDef['phpType'] == 'array'){
1890  $buffer .= '<table>';
1891  for($i=0;$i < 3; $i++){
1892  $buffer .= "
1893  <tr><td align='right'>array item (type: $typeDef[arrayType]):</td>
1894  <td><input type='text' name='parameters[".$name."][]'></td></tr>";
1895  }
1896  $buffer .= '</table>';
1897  // if scalar
1898  } else {
1899  $buffer .= "<input type='text' name='parameters[$name]'>";
1900  }
1901  } else {
1902  $buffer .= "<input type='text' name='parameters[$name]'>";
1903  }
1904  return $buffer;
1905  }
1906 
1948  function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType=''){
1949  $this->complexTypes[$name] = array(
1950  'name' => $name,
1951  'typeClass' => $typeClass,
1952  'phpType' => $phpType,
1953  'compositor'=> $compositor,
1954  'restrictionBase' => $restrictionBase,
1955  'elements' => $elements,
1956  'attrs' => $attrs,
1957  'arrayType' => $arrayType
1958  );
1959 
1960  $this->xdebug("addComplexType $name:");
1961  $this->appendDebug($this->varDump($this->complexTypes[$name]));
1962  }
1963 
1976  function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) {
1977  $this->simpleTypes[$name] = array(
1978  'name' => $name,
1979  'typeClass' => $typeClass,
1980  'phpType' => $phpType,
1981  'type' => $restrictionBase,
1982  'enumeration' => $enumeration
1983  );
1984 
1985  $this->xdebug("addSimpleType $name:");
1986  $this->appendDebug($this->varDump($this->simpleTypes[$name]));
1987  }
1988 
1996  function addElement($attrs) {
1997  if (! $this->getPrefix($attrs['type'])) {
1998  $attrs['type'] = $this->schemaTargetNamespace . ':' . $attrs['type'];
1999  }
2000  $this->elements[ $attrs['name'] ] = $attrs;
2001  $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
2002 
2003  $this->xdebug("addElement " . $attrs['name']);
2004  $this->appendDebug($this->varDump($this->elements[ $attrs['name'] ]));
2005  }
2006 }
2007 
2011 class XMLSchema extends nusoap_xmlschema {
2012 }
2013 
2014 ?><?php
2015 
2016 
2017 
2029 class soapval extends nusoap_base {
2036  var $name;
2043  var $type;
2050  var $value;
2057  var $element_ns;
2064  var $type_ns;
2071  var $attributes;
2072 
2084  function __construct($name='soapval',$type=false,$value=-1,$element_ns=false,$type_ns=false,$attributes=false) {
2085  parent::__construct();
2086  $this->name = $name;
2087  $this->type = $type;
2088  $this->value = $value;
2089  $this->element_ns = $element_ns;
2090  $this->type_ns = $type_ns;
2091  $this->attributes = $attributes;
2092  }
2093 
2101  function serialize($use='encoded') {
2102  return $this->serialize_val($this->value, $this->name, $this->type, $this->element_ns, $this->type_ns, $this->attributes, $use, true);
2103  }
2104 
2111  function decode(){
2112  return $this->value;
2113  }
2114 }
2115 
2116 
2117 
2118 ?><?php
2119 
2120 
2121 
2131 class soap_transport_http extends nusoap_base {
2132 
2133  var $url = '';
2134  var $uri = '';
2135  var $digest_uri = '';
2136  var $scheme = '';
2137  var $host = '';
2138  var $port = '';
2139  var $path = '';
2140  var $request_method = 'POST';
2141  var $protocol_version = '1.0';
2142  var $encoding = '';
2143  var $outgoing_headers = array();
2144  var $incoming_headers = array();
2145  var $incoming_cookies = array();
2146  var $outgoing_payload = '';
2147  var $incoming_payload = '';
2148  var $response_status_line; // HTTP response status line
2149  var $useSOAPAction = true;
2150  var $persistentConnection = false;
2151  var $ch = false; // cURL handle
2152  var $ch_options = array(); // cURL custom options
2153  var $use_curl = false; // force cURL use
2154  var $proxy = null; // proxy information (associative array)
2155  var $username = '';
2156  var $password = '';
2157  var $authtype = '';
2158  var $digestRequest = array();
2159  var $certRequest = array(); // keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional)
2160  // cainfofile: certificate authority file, e.g. '$pathToPemFiles/rootca.pem'
2161  // sslcertfile: SSL certificate file, e.g. '$pathToPemFiles/mycert.pem'
2162  // sslkeyfile: SSL key file, e.g. '$pathToPemFiles/mykey.pem'
2163  // passphrase: SSL key password/passphrase
2164  // certpassword: SSL certificate password
2165  // verifypeer: default is 1
2166  // verifyhost: default is 1
2167 
2176  function __construct($url, $curl_options = NULL, $use_curl = false){
2177  parent::__construct();
2178  $this->debug("ctor url=$url use_curl=$use_curl curl_options:");
2179  $this->appendDebug($this->varDump($curl_options));
2180  $this->setURL($url);
2181  if (is_array($curl_options)) {
2182  $this->ch_options = $curl_options;
2183  }
2184  $this->use_curl = $use_curl;
2185  preg_match('/\$Revisio' . 'n: ([^ ]+)/', $this->revision, $rev);
2186  $this->setHeader('User-Agent', $this->title.'/'.$this->version.' ('.$rev[1].')');
2187  }
2188 
2196  function setCurlOption($option, $value) {
2197  $this->debug("setCurlOption option=$option, value=");
2198  $this->appendDebug($this->varDump($value));
2199  curl_setopt($this->ch, $option, $value);
2200  }
2201 
2209  function setHeader($name, $value) {
2210  $this->outgoing_headers[$name] = $value;
2211  $this->debug("set header $name: $value");
2212  }
2213 
2220  function unsetHeader($name) {
2221  if (isset($this->outgoing_headers[$name])) {
2222  $this->debug("unset header $name");
2223  unset($this->outgoing_headers[$name]);
2224  }
2225  }
2226 
2233  function setURL($url) {
2234  $this->url = $url;
2235 
2236  $u = parse_url($url);
2237  foreach($u as $k => $v){
2238  $this->debug("parsed URL $k = $v");
2239  $this->$k = $v;
2240  }
2241 
2242  // add any GET params to path
2243  if(isset($u['query']) && $u['query'] != ''){
2244  $this->path .= '?' . $u['query'];
2245  }
2246 
2247  // set default port
2248  if(!isset($u['port'])){
2249  if($u['scheme'] == 'https'){
2250  $this->port = 443;
2251  } else {
2252  $this->port = 80;
2253  }
2254  }
2255 
2256  $this->uri = $this->path;
2257  $this->digest_uri = $this->uri;
2258 
2259  // build headers
2260  if (!isset($u['port'])) {
2261  $this->setHeader('Host', $this->host);
2262  } else {
2263  $this->setHeader('Host', $this->host.':'.$this->port);
2264  }
2265 
2266  if (isset($u['user']) && $u['user'] != '') {
2267  $this->setCredentials(urldecode($u['user']), isset($u['pass']) ? urldecode($u['pass']) : '');
2268  }
2269  }
2270 
2277  function io_method() {
2278  if ($this->use_curl || ($this->scheme == 'https') || ($this->scheme == 'http' && $this->authtype == 'ntlm') || ($this->scheme == 'http' && is_array($this->proxy) && $this->proxy['authtype'] == 'ntlm'))
2279  return 'curl';
2280  if (($this->scheme == 'http' || $this->scheme == 'ssl') && $this->authtype != 'ntlm' && (!is_array($this->proxy) || $this->proxy['authtype'] != 'ntlm'))
2281  return 'socket';
2282  return 'unknown';
2283  }
2284 
2293  function connect($connection_timeout=0,$response_timeout=30){
2294  // For PHP 4.3 with OpenSSL, change https scheme to ssl, then treat like
2295  // "regular" socket.
2296  // TODO: disabled for now because OpenSSL must be *compiled* in (not just
2297  // loaded), and until PHP5 stream_get_wrappers is not available.
2298 // if ($this->scheme == 'https') {
2299 // if (version_compare(phpversion(), '4.3.0') >= 0) {
2300 // if (extension_loaded('openssl')) {
2301 // $this->scheme = 'ssl';
2302 // $this->debug('Using SSL over OpenSSL');
2303 // }
2304 // }
2305 // }
2306  $this->debug("connect connection_timeout $connection_timeout, response_timeout $response_timeout, scheme $this->scheme, host $this->host, port $this->port");
2307  if ($this->io_method() == 'socket') {
2308  if (!is_array($this->proxy)) {
2309  $host = $this->host;
2310  $port = $this->port;
2311  } else {
2312  $host = $this->proxy['host'];
2313  $port = $this->proxy['port'];
2314  }
2315 
2316  // use persistent connection
2317  if($this->persistentConnection && isset($this->fp) && is_resource($this->fp)){
2318  if (!feof($this->fp)) {
2319  $this->debug('Re-use persistent connection');
2320  return true;
2321  }
2322  fclose($this->fp);
2323  $this->debug('Closed persistent connection at EOF');
2324  }
2325 
2326  // munge host if using OpenSSL
2327  if ($this->scheme == 'ssl') {
2328  $host = 'ssl://' . $host;
2329  }
2330  $this->debug('calling fsockopen with host ' . $host . ' connection_timeout ' . $connection_timeout);
2331 
2332  // open socket
2333  if($connection_timeout > 0){
2334  $this->fp = @fsockopen( $host, $this->port, $this->errno, $this->error_str, $connection_timeout);
2335  } else {
2336  $this->fp = @fsockopen( $host, $this->port, $this->errno, $this->error_str);
2337  }
2338 
2339  // test pointer
2340  if(!$this->fp) {
2341  $msg = 'Couldn\'t open socket connection to server ' . $this->url;
2342  if ($this->errno) {
2343  $msg .= ', Error ('.$this->errno.'): '.$this->error_str;
2344  } else {
2345  $msg .= ' prior to connect(). This is often a problem looking up the host name.';
2346  }
2347  $this->debug($msg);
2348  $this->setError($msg);
2349  return false;
2350  }
2351 
2352  // set response timeout
2353  $this->debug('set response timeout to ' . $response_timeout);
2354  socket_set_timeout( $this->fp, $response_timeout);
2355 
2356  $this->debug('socket connected');
2357  return true;
2358  } else if ($this->io_method() == 'curl') {
2359  if (!extension_loaded('curl')) {
2360 // $this->setError('cURL Extension, or OpenSSL extension w/ PHP version >= 4.3 is required for HTTPS');
2361  $this->setError('The PHP cURL Extension is required for HTTPS or NLTM. You will need to re-build or update your PHP to included cURL.');
2362  return false;
2363  }
2364  // Avoid warnings when PHP does not have these options
2365  if (defined('CURLOPT_CONNECTIONTIMEOUT'))
2366  $CURLOPT_CONNECTIONTIMEOUT = CURLOPT_CONNECTIONTIMEOUT;
2367  else
2368  $CURLOPT_CONNECTIONTIMEOUT = 78;
2369  if (defined('CURLOPT_HTTPAUTH'))
2370  $CURLOPT_HTTPAUTH = CURLOPT_HTTPAUTH;
2371  else
2372  $CURLOPT_HTTPAUTH = 107;
2373  if (defined('CURLOPT_PROXYAUTH'))
2374  $CURLOPT_PROXYAUTH = CURLOPT_PROXYAUTH;
2375  else
2376  $CURLOPT_PROXYAUTH = 111;
2377  if (defined('CURLAUTH_BASIC'))
2378  $CURLAUTH_BASIC = CURLAUTH_BASIC;
2379  else
2380  $CURLAUTH_BASIC = 1;
2381  if (defined('CURLAUTH_DIGEST'))
2382  $CURLAUTH_DIGEST = CURLAUTH_DIGEST;
2383  else
2384  $CURLAUTH_DIGEST = 2;
2385  if (defined('CURLAUTH_NTLM'))
2386  $CURLAUTH_NTLM = CURLAUTH_NTLM;
2387  else
2388  $CURLAUTH_NTLM = 8;
2389 
2390  $this->debug('connect using cURL');
2391  // init CURL
2392  $this->ch = curl_init();
2393  // set url
2394  $hostURL = ($this->port != '') ? "$this->scheme://$this->host:$this->port" : "$this->scheme://$this->host";
2395  // add path
2396  $hostURL .= $this->path;
2397  $this->setCurlOption(CURLOPT_URL, $hostURL);
2398  // follow location headers (re-directs)
2399  if (ini_get('safe_mode') || ini_get('open_basedir')) {
2400  $this->debug('safe_mode or open_basedir set, so do not set CURLOPT_FOLLOWLOCATION');
2401  $this->debug('safe_mode = ');
2402  $this->appendDebug($this->varDump(ini_get('safe_mode')));
2403  $this->debug('open_basedir = ');
2404  $this->appendDebug($this->varDump(ini_get('open_basedir')));
2405  } else {
2406  $this->setCurlOption(CURLOPT_FOLLOWLOCATION, 1);
2407  }
2408  // ask for headers in the response output
2409  $this->setCurlOption(CURLOPT_HEADER, 1);
2410  // ask for the response output as the return value
2411  $this->setCurlOption(CURLOPT_RETURNTRANSFER, 1);
2412  // encode
2413  // We manage this ourselves through headers and encoding
2414 // if(function_exists('gzuncompress')){
2415 // $this->setCurlOption(CURLOPT_ENCODING, 'deflate');
2416 // }
2417  // persistent connection
2418  if ($this->persistentConnection) {
2419  // I believe the following comment is now bogus, having applied to
2420  // the code when it used CURLOPT_CUSTOMREQUEST to send the request.
2421  // The way we send data, we cannot use persistent connections, since
2422  // there will be some "junk" at the end of our request.
2423  //$this->setCurlOption(CURL_HTTP_VERSION_1_1, true);
2424  $this->persistentConnection = false;
2425  $this->setHeader('Connection', 'close');
2426  }
2427  // set timeouts
2428  if ($connection_timeout != 0) {
2429  $this->setCurlOption($CURLOPT_CONNECTIONTIMEOUT, $connection_timeout);
2430  }
2431  if ($response_timeout != 0) {
2432  $this->setCurlOption(CURLOPT_TIMEOUT, $response_timeout);
2433  }
2434 
2435  if ($this->scheme == 'https') {
2436  $this->debug('set cURL SSL verify options');
2437  // recent versions of cURL turn on peer/host checking by default,
2438  // while PHP binaries are not compiled with a default location for the
2439  // CA cert bundle, so disable peer/host checking.
2440  //$this->setCurlOption(CURLOPT_CAINFO, 'f:\php-4.3.2-win32\extensions\curl-ca-bundle.crt');
2441  $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 0);
2442  $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 0);
2443 
2444  // support client certificates (thanks Tobias Boes, Doug Anarino, Eryan Ariobowo)
2445  if ($this->authtype == 'certificate') {
2446  $this->debug('set cURL certificate options');
2447  if (isset($this->certRequest['cainfofile'])) {
2448  $this->setCurlOption(CURLOPT_CAINFO, $this->certRequest['cainfofile']);
2449  }
2450  if (isset($this->certRequest['verifypeer'])) {
2451  $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, $this->certRequest['verifypeer']);
2452  } else {
2453  $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 1);
2454  }
2455  if (isset($this->certRequest['verifyhost'])) {
2456  $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, $this->certRequest['verifyhost']);
2457  } else {
2458  $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 1);
2459  }
2460  if (isset($this->certRequest['sslcertfile'])) {
2461  $this->setCurlOption(CURLOPT_SSLCERT, $this->certRequest['sslcertfile']);
2462  }
2463  if (isset($this->certRequest['sslkeyfile'])) {
2464  $this->setCurlOption(CURLOPT_SSLKEY, $this->certRequest['sslkeyfile']);
2465  }
2466  if (isset($this->certRequest['passphrase'])) {
2467  $this->setCurlOption(CURLOPT_SSLKEYPASSWD, $this->certRequest['passphrase']);
2468  }
2469  if (isset($this->certRequest['certpassword'])) {
2470  $this->setCurlOption(CURLOPT_SSLCERTPASSWD, $this->certRequest['certpassword']);
2471  }
2472  }
2473  }
2474  if ($this->authtype && ($this->authtype != 'certificate')) {
2475  if ($this->username) {
2476  $this->debug('set cURL username/password');
2477  $this->setCurlOption(CURLOPT_USERPWD, "$this->username:$this->password");
2478  }
2479  if ($this->authtype == 'basic') {
2480  $this->debug('set cURL for Basic authentication');
2481  $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_BASIC);
2482  }
2483  if ($this->authtype == 'digest') {
2484  $this->debug('set cURL for digest authentication');
2485  $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_DIGEST);
2486  }
2487  if ($this->authtype == 'ntlm') {
2488  $this->debug('set cURL for NTLM authentication');
2489  $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_NTLM);
2490  }
2491  }
2492  if (is_array($this->proxy)) {
2493  $this->debug('set cURL proxy options');
2494  if ($this->proxy['port'] != '') {
2495  $this->setCurlOption(CURLOPT_PROXY, $this->proxy['host'].':'.$this->proxy['port']);
2496  } else {
2497  $this->setCurlOption(CURLOPT_PROXY, $this->proxy['host']);
2498  }
2499  if ($this->proxy['username'] || $this->proxy['password']) {
2500  $this->debug('set cURL proxy authentication options');
2501  $this->setCurlOption(CURLOPT_PROXYUSERPWD, $this->proxy['username'].':'.$this->proxy['password']);
2502  if ($this->proxy['authtype'] == 'basic') {
2503  $this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_BASIC);
2504  }
2505  if ($this->proxy['authtype'] == 'ntlm') {
2506  $this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_NTLM);
2507  }
2508  }
2509  }
2510  $this->debug('cURL connection set up');
2511  return true;
2512  } else {
2513  $this->setError('Unknown scheme ' . $this->scheme);
2514  $this->debug('Unknown scheme ' . $this->scheme);
2515  return false;
2516  }
2517  }
2518 
2529  function send($data, $timeout=0, $response_timeout=30, $cookies=NULL) {
2530 
2531  $this->debug('entered send() with data of length: '.strlen($data));
2532 
2533  $this->tryagain = true;
2534  $tries = 0;
2535  while ($this->tryagain) {
2536  $this->tryagain = false;
2537  if ($tries++ < 2) {
2538  // make connnection
2539  if (!$this->connect($timeout, $response_timeout)){
2540  return false;
2541  }
2542 
2543  // send request
2544  if (!$this->sendRequest($data, $cookies)){
2545  return false;
2546  }
2547 
2548  // get response
2549  $respdata = $this->getResponse();
2550  } else {
2551  $this->setError("Too many tries to get an OK response ($this->response_status_line)");
2552  }
2553  }
2554  $this->debug('end of send()');
2555  return $respdata;
2556  }
2557 
2558 
2570  function sendHTTPS($data, $timeout=0, $response_timeout=30, $cookies) {
2571  return $this->send($data, $timeout, $response_timeout, $cookies);
2572  }
2573 
2584  function setCredentials($username, $password, $authtype = 'basic', $digestRequest = array(), $certRequest = array()) {
2585  $this->debug("setCredentials username=$username authtype=$authtype digestRequest=");
2586  $this->appendDebug($this->varDump($digestRequest));
2587  $this->debug("certRequest=");
2588  $this->appendDebug($this->varDump($certRequest));
2589  // cf. RFC 2617
2590  if ($authtype == 'basic') {
2591  $this->setHeader('Authorization', 'Basic '.base64_encode(str_replace(':','',$username).':'.$password));
2592  } elseif ($authtype == 'digest') {
2593  if (isset($digestRequest['nonce'])) {
2594  $digestRequest['nc'] = isset($digestRequest['nc']) ? $digestRequest['nc']++ : 1;
2595 
2596  // calculate the Digest hashes (calculate code based on digest implementation found at: http://www.rassoc.com/gregr/weblog/stories/2002/07/09/webServicesSecurityHttpDigestAuthenticationWithoutActiveDirectory.html)
2597 
2598  // A1 = unq(username-value) ":" unq(realm-value) ":" passwd
2599  $A1 = $username. ':' . (isset($digestRequest['realm']) ? $digestRequest['realm'] : '') . ':' . $password;
2600 
2601  // H(A1) = MD5(A1)
2602  $HA1 = md5($A1);
2603 
2604  // A2 = Method ":" digest-uri-value
2605  $A2 = $this->request_method . ':' . $this->digest_uri;
2606 
2607  // H(A2)
2608  $HA2 = md5($A2);
2609 
2610  // KD(secret, data) = H(concat(secret, ":", data))
2611  // if qop == auth:
2612  // request-digest = <"> < KD ( H(A1), unq(nonce-value)
2613  // ":" nc-value
2614  // ":" unq(cnonce-value)
2615  // ":" unq(qop-value)
2616  // ":" H(A2)
2617  // ) <">
2618  // if qop is missing,
2619  // request-digest = <"> < KD ( H(A1), unq(nonce-value) ":" H(A2) ) > <">
2620 
2621  $unhashedDigest = '';
2622  $nonce = isset($digestRequest['nonce']) ? $digestRequest['nonce'] : '';
2623  $cnonce = $nonce;
2624  if ($digestRequest['qop'] != '') {
2625  $unhashedDigest = $HA1 . ':' . $nonce . ':' . sprintf("%08d", $digestRequest['nc']) . ':' . $cnonce . ':' . $digestRequest['qop'] . ':' . $HA2;
2626  } else {
2627  $unhashedDigest = $HA1 . ':' . $nonce . ':' . $HA2;
2628  }
2629 
2630  $hashedDigest = md5($unhashedDigest);
2631 
2632  $opaque = '';
2633  if (isset($digestRequest['opaque'])) {
2634  $opaque = ', opaque="' . $digestRequest['opaque'] . '"';
2635  }
2636 
2637  $this->setHeader('Authorization', 'Digest username="' . $username . '", realm="' . $digestRequest['realm'] . '", nonce="' . $nonce . '", uri="' . $this->digest_uri . $opaque . '", cnonce="' . $cnonce . '", nc=' . sprintf("%08x", $digestRequest['nc']) . ', qop="' . $digestRequest['qop'] . '", response="' . $hashedDigest . '"');
2638  }
2639  } elseif ($authtype == 'certificate') {
2640  $this->certRequest = $certRequest;
2641  $this->debug('Authorization header not set for certificate');
2642  } elseif ($authtype == 'ntlm') {
2643  // do nothing
2644  $this->debug('Authorization header not set for ntlm');
2645  }
2646  $this->username = $username;
2647  $this->password = $password;
2648  $this->authtype = $authtype;
2649  $this->digestRequest = $digestRequest;
2650  }
2651 
2658  function setSOAPAction($soapaction) {
2659  $this->setHeader('SOAPAction', '"' . $soapaction . '"');
2660  }
2661 
2668  function setEncoding($enc='gzip, deflate') {
2669  if (function_exists('gzdeflate')) {
2670  $this->protocol_version = '1.1';
2671  $this->setHeader('Accept-Encoding', $enc);
2672  if (!isset($this->outgoing_headers['Connection'])) {
2673  $this->setHeader('Connection', 'close');
2674  $this->persistentConnection = false;
2675  }
2676  #set_magic_quotes_runtime(0);
2677  // deprecated
2678  $this->encoding = $enc;
2679  }
2680  }
2681 
2692  function setProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '', $proxyauthtype = 'basic') {
2693  if ($proxyhost) {
2694  $this->proxy = array(
2695  'host' => $proxyhost,
2696  'port' => $proxyport,
2697  'username' => $proxyusername,
2698  'password' => $proxypassword,
2699  'authtype' => $proxyauthtype
2700  );
2701  if ($proxyusername != '' && $proxypassword != '' && $proxyauthtype = 'basic') {
2702  $this->setHeader('Proxy-Authorization', ' Basic '.base64_encode($proxyusername.':'.$proxypassword));
2703  }
2704  } else {
2705  $this->debug('remove proxy');
2706  $proxy = null;
2707  unsetHeader('Proxy-Authorization');
2708  }
2709  }
2710 
2711 
2720  function isSkippableCurlHeader(&$data) {
2721  $skipHeaders = array( 'HTTP/1.1 100',
2722  'HTTP/1.0 301',
2723  'HTTP/1.1 301',
2724  'HTTP/1.0 302',
2725  'HTTP/1.1 302',
2726  'HTTP/1.0 401',
2727  'HTTP/1.1 401',
2728  'HTTP/1.0 200 Connection established');
2729  foreach ($skipHeaders as $hd) {
2730  $prefix = substr($data, 0, strlen($hd));
2731  if ($prefix == $hd) return true;
2732  }
2733 
2734  return false;
2735  }
2736 
2747  function decodeChunked($buffer, $lb){
2748  // length := 0
2749  $length = 0;
2750  $new = '';
2751 
2752  // read chunk-size, chunk-extension (if any) and CRLF
2753  // get the position of the linebreak
2754  $chunkend = strpos($buffer, $lb);
2755  if ($chunkend == FALSE) {
2756  $this->debug('no linebreak found in decodeChunked');
2757  return $new;
2758  }
2759  $temp = substr($buffer,0,$chunkend);
2760  $chunk_size = hexdec( trim($temp) );
2761  $chunkstart = $chunkend + strlen($lb);
2762  // while (chunk-size > 0) {
2763  while ($chunk_size > 0) {
2764  $this->debug("chunkstart: $chunkstart chunk_size: $chunk_size");
2765  $chunkend = strpos( $buffer, $lb, $chunkstart + $chunk_size);
2766 
2767  // Just in case we got a broken connection
2768  if ($chunkend == FALSE) {
2769  $chunk = substr($buffer,$chunkstart);
2770  // append chunk-data to entity-body
2771  $new .= $chunk;
2772  $length += strlen($chunk);
2773  break;
2774  }
2775 
2776  // read chunk-data and CRLF
2777  $chunk = substr($buffer,$chunkstart,$chunkend-$chunkstart);
2778  // append chunk-data to entity-body
2779  $new .= $chunk;
2780  // length := length + chunk-size
2781  $length += strlen($chunk);
2782  // read chunk-size and CRLF
2783  $chunkstart = $chunkend + strlen($lb);
2784 
2785  $chunkend = strpos($buffer, $lb, $chunkstart) + strlen($lb);
2786  if ($chunkend == FALSE) {
2787  break; //Just in case we got a broken connection
2788  }
2789  $temp = substr($buffer,$chunkstart,$chunkend-$chunkstart);
2790  $chunk_size = hexdec( trim($temp) );
2791  $chunkstart = $chunkend;
2792  }
2793  return $new;
2794  }
2795 
2804  function buildPayload($data, $cookie_str = '') {
2805  // Note: for cURL connections, $this->outgoing_payload is ignored,
2806  // as is the Content-Length header, but these are still created as
2807  // debugging guides.
2808 
2809  // add content-length header
2810  $this->setHeader('Content-Length', strlen($data));
2811 
2812  // start building outgoing payload:
2813  if ($this->proxy) {
2814  $uri = $this->url;
2815  } else {
2816  $uri = $this->uri;
2817  }
2818  $req = "$this->request_method $uri HTTP/$this->protocol_version";
2819  $this->debug("HTTP request: $req");
2820  $this->outgoing_payload = "$req\r\n";
2821 
2822  // loop thru headers, serializing
2823  foreach($this->outgoing_headers as $k => $v){
2824  $hdr = $k.': '.$v;
2825  $this->debug("HTTP header: $hdr");
2826  $this->outgoing_payload .= "$hdr\r\n";
2827  }
2828 
2829  // add any cookies
2830  if ($cookie_str != '') {
2831  $hdr = 'Cookie: '.$cookie_str;
2832  $this->debug("HTTP header: $hdr");
2833  $this->outgoing_payload .= "$hdr\r\n";
2834  }
2835 
2836  // header/body separator
2837  $this->outgoing_payload .= "\r\n";
2838 
2839  // add data
2840  $this->outgoing_payload .= $data;
2841  }
2842 
2851  function sendRequest($data, $cookies = NULL) {
2852  // build cookie string
2853  $cookie_str = $this->getCookiesForRequest($cookies, (($this->scheme == 'ssl') || ($this->scheme == 'https')));
2854 
2855  // build payload
2856  $this->buildPayload($data, $cookie_str);
2857 
2858  if ($this->io_method() == 'socket') {
2859  // send payload
2860  if(!fputs($this->fp, $this->outgoing_payload, strlen($this->outgoing_payload))) {
2861  $this->setError('couldn\'t write message data to socket');
2862  $this->debug('couldn\'t write message data to socket');
2863  return false;
2864  }
2865  $this->debug('wrote data to socket, length = ' . strlen($this->outgoing_payload));
2866  return true;
2867  } else if ($this->io_method() == 'curl') {
2868  // set payload
2869  // cURL does say this should only be the verb, and in fact it
2870  // turns out that the URI and HTTP version are appended to this, which
2871  // some servers refuse to work with (so we no longer use this method!)
2872  //$this->setCurlOption(CURLOPT_CUSTOMREQUEST, $this->outgoing_payload);
2873  $curl_headers = array();
2874  foreach($this->outgoing_headers as $k => $v){
2875  if ($k == 'Connection' || $k == 'Content-Length' || $k == 'Host' || $k == 'Authorization' || $k == 'Proxy-Authorization') {
2876  $this->debug("Skip cURL header $k: $v");
2877  } else {
2878  $curl_headers[] = "$k: $v";
2879  }
2880  }
2881  if ($cookie_str != '') {
2882  $curl_headers[] = 'Cookie: ' . $cookie_str;
2883  }
2884  $this->setCurlOption(CURLOPT_HTTPHEADER, $curl_headers);
2885  $this->debug('set cURL HTTP headers');
2886  if ($this->request_method == "POST") {
2887  $this->setCurlOption(CURLOPT_POST, 1);
2888  $this->setCurlOption(CURLOPT_POSTFIELDS, $data);
2889  $this->debug('set cURL POST data');
2890  } else {
2891  }
2892  // insert custom user-set cURL options
2893  foreach ($this->ch_options as $key => $val) {
2894  $this->setCurlOption($key, $val);
2895  }
2896 
2897  $this->debug('set cURL payload');
2898  return true;
2899  }
2900  }
2901 
2908  function getResponse(){
2909  $this->incoming_payload = '';
2910 
2911  if ($this->io_method() == 'socket') {
2912  // loop until headers have been retrieved
2913  $data = '';
2914  while (!isset($lb)){
2915 
2916  // We might EOF during header read.
2917  if(feof($this->fp)) {
2918  $this->incoming_payload = $data;
2919  $this->debug('found no headers before EOF after length ' . strlen($data));
2920  $this->debug("received before EOF:\n" . $data);
2921  $this->setError('server failed to send headers');
2922  return false;
2923  }
2924 
2925  $tmp = fgets($this->fp, 256);
2926  $tmplen = strlen($tmp);
2927  $this->debug("read line of $tmplen bytes: " . trim($tmp));
2928 
2929  if ($tmplen == 0) {
2930  $this->incoming_payload = $data;
2931  $this->debug('socket read of headers timed out after length ' . strlen($data));
2932  $this->debug("read before timeout: " . $data);
2933  $this->setError('socket read of headers timed out');
2934  return false;
2935  }
2936 
2937  $data .= $tmp;
2938  $pos = strpos($data,"\r\n\r\n");
2939  if($pos > 1){
2940  $lb = "\r\n";
2941  } else {
2942  $pos = strpos($data,"\n\n");
2943  if($pos > 1){
2944  $lb = "\n";
2945  }
2946  }
2947  // remove 100 headers
2948  if (isset($lb) && preg_match('/^HTTP\/1.1 100/',$data)) {
2949  unset($lb);
2950  $data = '';
2951  }//
2952  }
2953  // store header data
2954  $this->incoming_payload .= $data;
2955  $this->debug('found end of headers after length ' . strlen($data));
2956  // process headers
2957  $header_data = trim(substr($data,0,$pos));
2958  $header_array = explode($lb,$header_data);
2959  $this->incoming_headers = array();
2960  $this->incoming_cookies = array();
2961  foreach($header_array as $header_line){
2962  $arr = explode(':',$header_line, 2);
2963  if(count($arr) > 1){
2964  $header_name = strtolower(trim($arr[0]));
2965  $this->incoming_headers[$header_name] = trim($arr[1]);
2966  if ($header_name == 'set-cookie') {
2967  // TODO: allow multiple cookies from parseCookie
2968  $cookie = $this->parseCookie(trim($arr[1]));
2969  if ($cookie) {
2970  $this->incoming_cookies[] = $cookie;
2971  $this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']);
2972  } else {
2973  $this->debug('did not find cookie in ' . trim($arr[1]));
2974  }
2975  }
2976  } else if (isset($header_name)) {
2977  // append continuation line to previous header
2978  $this->incoming_headers[$header_name] .= $lb . ' ' . $header_line;
2979  }
2980  }
2981 
2982  // loop until msg has been received
2983  if (isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked') {
2984  $content_length = 2147483647; // ignore any content-length header
2985  $chunked = true;
2986  $this->debug("want to read chunked content");
2987  } elseif (isset($this->incoming_headers['content-length'])) {
2988  $content_length = $this->incoming_headers['content-length'];
2989  $chunked = false;
2990  $this->debug("want to read content of length $content_length");
2991  } else {
2992  $content_length = 2147483647;
2993  $chunked = false;
2994  $this->debug("want to read content to EOF");
2995  }
2996  $data = '';
2997  do {
2998  if ($chunked) {
2999  $tmp = fgets($this->fp, 256);
3000  $tmplen = strlen($tmp);
3001  $this->debug("read chunk line of $tmplen bytes");
3002  if ($tmplen == 0) {
3003  $this->incoming_payload = $data;
3004  $this->debug('socket read of chunk length timed out after length ' . strlen($data));
3005  $this->debug("read before timeout:\n" . $data);
3006  $this->setError('socket read of chunk length timed out');
3007  return false;
3008  }
3009  $content_length = hexdec(trim($tmp));
3010  $this->debug("chunk length $content_length");
3011  }
3012  $strlen = 0;
3013  while (($strlen < $content_length) && (!feof($this->fp))) {
3014  $readlen = min(8192, $content_length - $strlen);
3015  $tmp = fread($this->fp, $readlen);
3016  $tmplen = strlen($tmp);
3017  $this->debug("read buffer of $tmplen bytes");
3018  if (($tmplen == 0) && (!feof($this->fp))) {
3019  $this->incoming_payload = $data;
3020  $this->debug('socket read of body timed out after length ' . strlen($data));
3021  $this->debug("read before timeout:\n" . $data);
3022  $this->setError('socket read of body timed out');
3023  return false;
3024  }
3025  $strlen += $tmplen;
3026  $data .= $tmp;
3027  }
3028  if ($chunked && ($content_length > 0)) {
3029  $tmp = fgets($this->fp, 256);
3030  $tmplen = strlen($tmp);
3031  $this->debug("read chunk terminator of $tmplen bytes");
3032  if ($tmplen == 0) {
3033  $this->incoming_payload = $data;
3034  $this->debug('socket read of chunk terminator timed out after length ' . strlen($data));
3035  $this->debug("read before timeout:\n" . $data);
3036  $this->setError('socket read of chunk terminator timed out');
3037  return false;
3038  }
3039  }
3040  } while ($chunked && ($content_length > 0) && (!feof($this->fp)));
3041  if (feof($this->fp)) {
3042  $this->debug('read to EOF');
3043  }
3044  $this->debug('read body of length ' . strlen($data));
3045  $this->incoming_payload .= $data;
3046  $this->debug('received a total of '.strlen($this->incoming_payload).' bytes of data from server');
3047 
3048  // close filepointer
3049  if(
3050  (isset($this->incoming_headers['connection']) && strtolower($this->incoming_headers['connection']) == 'close') ||
3051  (! $this->persistentConnection) || feof($this->fp)){
3052  fclose($this->fp);
3053  $this->fp = false;
3054  $this->debug('closed socket');
3055  }
3056 
3057  // connection was closed unexpectedly
3058  if($this->incoming_payload == ''){
3059  $this->setError('no response from server');
3060  return false;
3061  }
3062 
3063  // decode transfer-encoding
3064 // if(isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked'){
3065 // if(!$data = $this->decodeChunked($data, $lb)){
3066 // $this->setError('Decoding of chunked data failed');
3067 // return false;
3068 // }
3069  //print "<pre>\nde-chunked:\n---------------\n$data\n\n---------------\n</pre>";
3070  // set decoded payload
3071 // $this->incoming_payload = $header_data.$lb.$lb.$data;
3072 // }
3073 
3074  } else if ($this->io_method() == 'curl') {
3075  // send and receive
3076  $this->debug('send and receive with cURL');
3077  $this->incoming_payload = curl_exec($this->ch);
3078  $data = $this->incoming_payload;
3079 
3080  $cErr = curl_error($this->ch);
3081  if ($cErr != '') {
3082  $err = 'cURL ERROR: '.curl_errno($this->ch).': '.$cErr.'<br>';
3083  // TODO: there is a PHP bug that can cause this to SEGV for CURLINFO_CONTENT_TYPE
3084  foreach(curl_getinfo($this->ch) as $k => $v){
3085  $err .= "$k: $v<br>";
3086  }
3087  $this->debug($err);
3088  $this->setError($err);
3089  curl_close($this->ch);
3090  return false;
3091  } else {
3092  //echo '<pre>';
3093  //var_dump(curl_getinfo($this->ch));
3094  //echo '</pre>';
3095  }
3096  // close curl
3097  $this->debug('No cURL error, closing cURL');
3098  curl_close($this->ch);
3099 
3100  // try removing skippable headers
3101  $savedata = $data;
3102  while ($this->isSkippableCurlHeader($data)) {
3103  $this->debug("Found HTTP header to skip");
3104  if ($pos = strpos($data,"\r\n\r\n")) {
3105  $data = ltrim(substr($data,$pos));
3106  } elseif($pos = strpos($data,"\n\n") ) {
3107  $data = ltrim(substr($data,$pos));
3108  }
3109  }
3110 
3111  if ($data == '') {
3112  // have nothing left; just remove 100 header(s)
3113  $data = $savedata;
3114  while (preg_match('/^HTTP\/1.1 100/',$data)) {
3115  if ($pos = strpos($data,"\r\n\r\n")) {
3116  $data = ltrim(substr($data,$pos));
3117  } elseif($pos = strpos($data,"\n\n") ) {
3118  $data = ltrim(substr($data,$pos));
3119  }
3120  }
3121  }
3122 
3123  // separate content from HTTP headers
3124  if ($pos = strpos($data,"\r\n\r\n")) {
3125  $lb = "\r\n";
3126  } elseif( $pos = strpos($data,"\n\n")) {
3127  $lb = "\n";
3128  } else {
3129  $this->debug('no proper separation of headers and document');
3130  $this->setError('no proper separation of headers and document');
3131  return false;
3132  }
3133  $header_data = trim(substr($data,0,$pos));
3134  $header_array = explode($lb,$header_data);
3135  $data = ltrim(substr($data,$pos));
3136  $this->debug('found proper separation of headers and document');
3137  $this->debug('cleaned data, stringlen: '.strlen($data));
3138  // clean headers
3139  foreach ($header_array as $header_line) {
3140  $arr = explode(':',$header_line,2);
3141  if(count($arr) > 1){
3142  $header_name = strtolower(trim($arr[0]));
3143  $this->incoming_headers[$header_name] = trim($arr[1]);
3144  if ($header_name == 'set-cookie') {
3145  // TODO: allow multiple cookies from parseCookie
3146  $cookie = $this->parseCookie(trim($arr[1]));
3147  if ($cookie) {
3148  $this->incoming_cookies[] = $cookie;
3149  $this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']);
3150  } else {
3151  $this->debug('did not find cookie in ' . trim($arr[1]));
3152  }
3153  }
3154  } else if (isset($header_name)) {
3155  // append continuation line to previous header
3156  $this->incoming_headers[$header_name] .= $lb . ' ' . $header_line;
3157  }
3158  }
3159  }
3160 
3161  $this->response_status_line = $header_array[0];
3162  $arr = explode(' ', $this->response_status_line, 3);
3163  $http_version = $arr[0];
3164  $http_status = intval($arr[1]);
3165  $http_reason = count($arr) > 2 ? $arr[2] : '';
3166 
3167  // see if we need to resend the request with http digest authentication
3168  if (isset($this->incoming_headers['location']) && ($http_status == 301 || $http_status == 302)) {
3169  $this->debug("Got $http_status $http_reason with Location: " . $this->incoming_headers['location']);
3170  $this->setURL($this->incoming_headers['location']);
3171  $this->tryagain = true;
3172  return false;
3173  }
3174 
3175  // see if we need to resend the request with http digest authentication
3176  if (isset($this->incoming_headers['www-authenticate']) && $http_status == 401) {
3177  $this->debug("Got 401 $http_reason with WWW-Authenticate: " . $this->incoming_headers['www-authenticate']);
3178  if (strstr($this->incoming_headers['www-authenticate'], "Digest ")) {
3179  $this->debug('Server wants digest authentication');
3180  // remove "Digest " from our elements
3181  $digestString = str_replace('Digest ', '', $this->incoming_headers['www-authenticate']);
3182 
3183  // parse elements into array
3184  $digestElements = explode(',', $digestString);
3185  foreach ($digestElements as $val) {
3186  $tempElement = explode('=', trim($val), 2);
3187  $digestRequest[$tempElement[0]] = str_replace("\"", '', $tempElement[1]);
3188  }
3189 
3190  // should have (at least) qop, realm, nonce
3191  if (isset($digestRequest['nonce'])) {
3192  $this->setCredentials($this->username, $this->password, 'digest', $digestRequest);
3193  $this->tryagain = true;
3194  return false;
3195  }
3196  }
3197  $this->debug('HTTP authentication failed');
3198  $this->setError('HTTP authentication failed');
3199  return false;
3200  }
3201 
3202  if (
3203  ($http_status >= 300 && $http_status <= 307) ||
3204  ($http_status >= 400 && $http_status <= 417) ||
3205  ($http_status >= 501 && $http_status <= 505)
3206  ) {
3207  $this->setError("Unsupported HTTP response status $http_status $http_reason (soapclient->response has contents of the response)");
3208  return false;
3209  }
3210 
3211  // decode content-encoding
3212  if(isset($this->incoming_headers['content-encoding']) && $this->incoming_headers['content-encoding'] != ''){
3213  if(strtolower($this->incoming_headers['content-encoding']) == 'deflate' || strtolower($this->incoming_headers['content-encoding']) == 'gzip'){
3214  // if decoding works, use it. else assume data wasn't gzencoded
3215  if(function_exists('gzinflate')){
3216  //$timer->setMarker('starting decoding of gzip/deflated content');
3217  // IIS 5 requires gzinflate instead of gzuncompress (similar to IE 5 and gzdeflate v. gzcompress)
3218  // this means there are no Zlib headers, although there should be
3219  $this->debug('The gzinflate function exists');
3220  $datalen = strlen($data);
3221  if ($this->incoming_headers['content-encoding'] == 'deflate') {
3222  if ($degzdata = @gzinflate($data)) {
3223  $data = $degzdata;
3224  $this->debug('The payload has been inflated to ' . strlen($data) . ' bytes');
3225  if (strlen($data) < $datalen) {
3226  // test for the case that the payload has been compressed twice
3227  $this->debug('The inflated payload is smaller than the gzipped one; try again');
3228  if ($degzdata = @gzinflate($data)) {
3229  $data = $degzdata;
3230  $this->debug('The payload has been inflated again to ' . strlen($data) . ' bytes');
3231  }
3232  }
3233  } else {
3234  $this->debug('Error using gzinflate to inflate the payload');
3235  $this->setError('Error using gzinflate to inflate the payload');
3236  }
3237  } elseif ($this->incoming_headers['content-encoding'] == 'gzip') {
3238  if ($degzdata = @gzinflate(substr($data, 10))) { // do our best
3239  $data = $degzdata;
3240  $this->debug('The payload has been un-gzipped to ' . strlen($data) . ' bytes');
3241  if (strlen($data) < $datalen) {
3242  // test for the case that the payload has been compressed twice
3243  $this->debug('The un-gzipped payload is smaller than the gzipped one; try again');
3244  if ($degzdata = @gzinflate(substr($data, 10))) {
3245  $data = $degzdata;
3246  $this->debug('The payload has been un-gzipped again to ' . strlen($data) . ' bytes');
3247  }
3248  }
3249  } else {
3250  $this->debug('Error using gzinflate to un-gzip the payload');
3251  $this->setError('Error using gzinflate to un-gzip the payload');
3252  }
3253  }
3254  //$timer->setMarker('finished decoding of gzip/deflated content');
3255  //print "<xmp>\nde-inflated:\n---------------\n$data\n-------------\n</xmp>";
3256  // set decoded payload
3257  $this->incoming_payload = $header_data.$lb.$lb.$data;
3258  } else {
3259  $this->debug('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.');
3260  $this->setError('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.');
3261  }
3262  } else {
3263  $this->debug('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']);
3264  $this->setError('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']);
3265  }
3266  } else {
3267  $this->debug('No Content-Encoding header');
3268  }
3269 
3270  if(strlen($data) == 0){
3271  $this->debug('no data after headers!');
3272  $this->setError('no data present after HTTP headers');
3273  return false;
3274  }
3275 
3276  return $data;
3277  }
3278 
3286  function setContentType($type, $charset = false) {
3287  $this->setHeader('Content-Type', $type . ($charset ? '; charset=' . $charset : ''));
3288  }
3289 
3296  function usePersistentConnection(){
3297  if (isset($this->outgoing_headers['Accept-Encoding'])) {
3298  return false;
3299  }
3300  $this->protocol_version = '1.1';
3301  $this->persistentConnection = true;
3302  $this->setHeader('Connection', 'Keep-Alive');
3303  return true;
3304  }
3305 
3313  /*
3314  * TODO: allow a Set-Cookie string to be parsed into multiple cookies
3315  */
3316  function parseCookie($cookie_str) {
3317  $cookie_str = str_replace('; ', ';', $cookie_str) . ';';
3318  $data = split(';', $cookie_str);
3319  $value_str = $data[0];
3320 
3321  $cookie_param = 'domain=';
3322  $start = strpos($cookie_str, $cookie_param);
3323  if ($start > 0) {
3324  $domain = substr($cookie_str, $start + strlen($cookie_param));
3325  $domain = substr($domain, 0, strpos($domain, ';'));
3326  } else {
3327  $domain = '';
3328  }
3329 
3330  $cookie_param = 'expires=';
3331  $start = strpos($cookie_str, $cookie_param);
3332  if ($start > 0) {
3333  $expires = substr($cookie_str, $start + strlen($cookie_param));
3334  $expires = substr($expires, 0, strpos($expires, ';'));
3335  } else {
3336  $expires = '';
3337  }
3338 
3339  $cookie_param = 'path=';
3340  $start = strpos($cookie_str, $cookie_param);
3341  if ( $start > 0 ) {
3342  $path = substr($cookie_str, $start + strlen($cookie_param));
3343  $path = substr($path, 0, strpos($path, ';'));
3344  } else {
3345  $path = '/';
3346  }
3347 
3348  $cookie_param = ';secure;';
3349  if (strpos($cookie_str, $cookie_param) !== FALSE) {
3350  $secure = true;
3351  } else {
3352  $secure = false;
3353  }
3354 
3355  $sep_pos = strpos($value_str, '=');
3356 
3357  if ($sep_pos) {
3358  $name = substr($value_str, 0, $sep_pos);
3359  $value = substr($value_str, $sep_pos + 1);
3360  $cookie= array( 'name' => $name,
3361  'value' => $value,
3362  'domain' => $domain,
3363  'path' => $path,
3364  'expires' => $expires,
3365  'secure' => $secure
3366  );
3367  return $cookie;
3368  }
3369  return false;
3370  }
3371 
3380  function getCookiesForRequest($cookies, $secure=false) {
3381  $cookie_str = '';
3382  if ((! is_null($cookies)) && (is_array($cookies))) {
3383  foreach ($cookies as $cookie) {
3384  if (! is_array($cookie)) {
3385  continue;
3386  }
3387  $this->debug("check cookie for validity: ".$cookie['name'].'='.$cookie['value']);
3388  if ((isset($cookie['expires'])) && (! empty($cookie['expires']))) {
3389  if (strtotime($cookie['expires']) <= time()) {
3390  $this->debug('cookie has expired');
3391  continue;
3392  }
3393  }
3394  if ((isset($cookie['domain'])) && (! empty($cookie['domain']))) {
3395  $domain = preg_quote($cookie['domain']);
3396  if (! preg_match("'.*$domain$'i", $this->host)) {
3397  $this->debug('cookie has different domain');
3398  continue;
3399  }
3400  }
3401  if ((isset($cookie['path'])) && (! empty($cookie['path']))) {
3402  $path = preg_quote($cookie['path']);
3403  if (! preg_match("'^$path.*'i", $this->path)) {
3404  $this->debug('cookie is for a different path');
3405  continue;
3406  }
3407  }
3408  if ((! $secure) && (isset($cookie['secure'])) && ($cookie['secure'])) {
3409  $this->debug('cookie is secure, transport is not');
3410  continue;
3411  }
3412  $cookie_str .= $cookie['name'] . '=' . $cookie['value'] . '; ';
3413  $this->debug('add cookie to Cookie-String: ' . $cookie['name'] . '=' . $cookie['value']);
3414  }
3415  }
3416  return $cookie_str;
3417  }
3418 }
3419 
3420 ?><?php
3421 
3422 
3423 
3434 class nusoap_server extends nusoap_base {
3440  var $headers = array();
3446  var $request = '';
3452  var $requestHeaders = '';
3458  var $requestHeader = NULL;
3464  var $document = '';
3470  var $requestSOAP = '';
3476  var $methodURI = '';
3482  var $methodname = '';
3488  var $methodparams = array();
3494  var $SOAPAction = '';
3500  var $xml_encoding = '';
3506  var $decode_utf8 = true;
3507 
3513  var $outgoing_headers = array();
3519  var $response = '';
3525  var $responseHeaders = '';
3531  var $responseSOAP = '';
3537  var $methodreturn = false;
3543  var $methodreturnisliteralxml = false;
3549  var $fault = false;
3555  var $result = 'successful';
3556 
3563  var $operations = array();
3569  var $wsdl = false;
3575  var $externalWSDLURL = false;
3581  var $debug_flag = false;
3582 
3583 
3591  function __construct($wsdl=false){
3592  parent::__construct();
3593  // turn on debugging?
3594  global $debug;
3595  global $HTTP_SERVER_VARS;
3596 
3597  if (isset($_SERVER)) {
3598  $this->debug("_SERVER is defined:");
3599  $this->appendDebug($this->varDump($_SERVER));
3600  } elseif (isset($HTTP_SERVER_VARS)) {
3601  $this->debug("HTTP_SERVER_VARS is defined:");
3602  $this->appendDebug($this->varDump($HTTP_SERVER_VARS));
3603  } else {
3604  $this->debug("Neither _SERVER nor HTTP_SERVER_VARS is defined.");
3605  }
3606 
3607  if (isset($debug)) {
3608  $this->debug("In nusoap_server, set debug_flag=$debug based on global flag");
3609  $this->debug_flag = $debug;
3610  } elseif (isset($_SERVER['QUERY_STRING'])) {
3611  $qs = explode('&', $_SERVER['QUERY_STRING']);
3612  foreach ($qs as $v) {
3613  if (substr($v, 0, 6) == 'debug=') {
3614  $this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #1");
3615  $this->debug_flag = substr($v, 6);
3616  }
3617  }
3618  } elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
3619  $qs = explode('&', $HTTP_SERVER_VARS['QUERY_STRING']);
3620  foreach ($qs as $v) {
3621  if (substr($v, 0, 6) == 'debug=') {
3622  $this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #2");
3623  $this->debug_flag = substr($v, 6);
3624  }
3625  }
3626  }
3627 
3628  // wsdl
3629  if($wsdl){
3630  $this->debug("In nusoap_server, WSDL is specified");
3631  if (is_object($wsdl) && (get_class($wsdl) == 'wsdl')) {
3632  $this->wsdl = $wsdl;
3633  $this->externalWSDLURL = $this->wsdl->wsdl;
3634  $this->debug('Use existing wsdl instance from ' . $this->externalWSDLURL);
3635  } else {
3636  $this->debug('Create wsdl from ' . $wsdl);
3637  $this->wsdl = new wsdl($wsdl);
3638  $this->externalWSDLURL = $wsdl;
3639  }
3640  $this->appendDebug($this->wsdl->getDebug());
3641  $this->wsdl->clearDebug();
3642  if($err = $this->wsdl->getError()){
3643  die('WSDL ERROR: '.$err);
3644  }
3645  }
3646  }
3647 
3654  function service($data){
3655  global $HTTP_SERVER_VARS;
3656 
3657  if (isset($_SERVER['QUERY_STRING'])) {
3658  $qs = $_SERVER['QUERY_STRING'];
3659  } elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
3660  $qs = $HTTP_SERVER_VARS['QUERY_STRING'];
3661  } else {
3662  $qs = '';
3663  }
3664  $this->debug("In service, query string=$qs");
3665 
3666  if (preg_match('/wsdl/', $qs) ){
3667  $this->debug("In service, this is a request for WSDL");
3668  if($this->externalWSDLURL){
3669  if (strpos($this->externalWSDLURL,"://")!==false) { // assume URL
3670  header('Location: '.$this->externalWSDLURL);
3671  } else { // assume file
3672  header("Content-Type: text/xml\r\n");
3673  $fp = fopen($this->externalWSDLURL, 'r');
3674  fpassthru($fp);
3675  }
3676  } elseif ($this->wsdl) {
3677  header("Content-Type: text/xml; charset=ISO-8859-1\r\n");
3678  print $this->wsdl->serialize($this->debug_flag);
3679  if ($this->debug_flag) {
3680  $this->debug('wsdl:');
3681  $this->appendDebug($this->varDump($this->wsdl));
3682  print $this->getDebugAsXMLComment();
3683  }
3684  } else {
3685  header("Content-Type: text/html; charset=ISO-8859-1\r\n");
3686  print "This service does not provide WSDL";
3687  }
3688  } elseif ($data == '' && $this->wsdl) {
3689  $this->debug("In service, there is no data, so return Web description");
3690  print $this->wsdl->webDescription();
3691  } else {
3692  $this->debug("In service, invoke the request");
3693  $this->parse_request($data);
3694  if (! $this->fault) {
3695  $this->invoke_method();
3696  }
3697  if (! $this->fault) {
3698  $this->serialize_return();
3699  }
3700  $this->send_response();
3701  }
3702  }
3703 
3716  function parse_http_headers() {
3717  global $HTTP_SERVER_VARS;
3718 
3719  $this->request = '';
3720  $this->SOAPAction = '';
3721  if(function_exists('getallheaders')){
3722  $this->debug("In parse_http_headers, use getallheaders");
3723  $headers = getallheaders();
3724  foreach($headers as $k=>$v){
3725  $k = strtolower($k);
3726  $this->headers[$k] = $v;
3727  $this->request .= "$k: $v\r\n";
3728  $this->debug("$k: $v");
3729  }
3730  // get SOAPAction header
3731  if(isset($this->headers['soapaction'])){
3732  $this->SOAPAction = str_replace('"','',$this->headers['soapaction']);
3733  }
3734  // get the character encoding of the incoming request
3735  if(isset($this->headers['content-type']) && strpos($this->headers['content-type'],'=')){
3736  $enc = str_replace('"','',substr(strstr($this->headers["content-type"],'='),1));
3737  if(preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)){
3738  $this->xml_encoding = strtoupper($enc);
3739  } else {
3740  $this->xml_encoding = 'US-ASCII';
3741  }
3742  } else {
3743  // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
3744  $this->xml_encoding = 'ISO-8859-1';
3745  }
3746  } elseif(isset($_SERVER) && is_array($_SERVER)){
3747  $this->debug("In parse_http_headers, use _SERVER");
3748  foreach ($_SERVER as $k => $v) {
3749  if (substr($k, 0, 5) == 'HTTP_') {
3750  $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5))));
3751  } else {
3752  $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k)));
3753  }
3754  if ($k == 'soapaction') {
3755  // get SOAPAction header
3756  $k = 'SOAPAction';
3757  $v = str_replace('"', '', $v);
3758  $v = str_replace('\\', '', $v);
3759  $this->SOAPAction = $v;
3760  } else if ($k == 'content-type') {
3761  // get the character encoding of the incoming request
3762  if (strpos($v, '=')) {
3763  $enc = substr(strstr($v, '='), 1);
3764  $enc = str_replace('"', '', $enc);
3765  $enc = str_replace('\\', '', $enc);
3766  if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)) {
3767  $this->xml_encoding = strtoupper($enc);
3768  } else {
3769  $this->xml_encoding = 'US-ASCII';
3770  }
3771  } else {
3772  // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
3773  $this->xml_encoding = 'ISO-8859-1';
3774  }
3775  }
3776  $this->headers[$k] = $v;
3777  $this->request .= "$k: $v\r\n";
3778  $this->debug("$k: $v");
3779  }
3780  } elseif (is_array($HTTP_SERVER_VARS)) {
3781  $this->debug("In parse_http_headers, use HTTP_SERVER_VARS");
3782  foreach ($HTTP_SERVER_VARS as $k => $v) {
3783  if (substr($k, 0, 5) == 'HTTP_') {
3784  $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5)))); $k = strtolower(substr($k, 5));
3785  } else {
3786  $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k))); $k = strtolower($k);
3787  }
3788  if ($k == 'soapaction') {
3789  // get SOAPAction header
3790  $k = 'SOAPAction';
3791  $v = str_replace('"', '', $v);
3792  $v = str_replace('\\', '', $v);
3793  $this->SOAPAction = $v;
3794  } else if ($k == 'content-type') {
3795  // get the character encoding of the incoming request
3796  if (strpos($v, '=')) {
3797  $enc = substr(strstr($v, '='), 1);
3798  $enc = str_replace('"', '', $enc);
3799  $enc = str_replace('\\', '', $enc);
3800  if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)) {
3801  $this->xml_encoding = strtoupper($enc);
3802  } else {
3803  $this->xml_encoding = 'US-ASCII';
3804  }
3805  } else {
3806  // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
3807  $this->xml_encoding = 'ISO-8859-1';
3808  }
3809  }
3810  $this->headers[$k] = $v;
3811  $this->request .= "$k: $v\r\n";
3812  $this->debug("$k: $v");
3813  }
3814  } else {
3815  $this->debug("In parse_http_headers, HTTP headers not accessible");
3816  $this->setError("HTTP headers not accessible");
3817  }
3818  }
3819 
3842  function parse_request($data='') {
3843  $this->debug('entering parse_request()');
3844  $this->parse_http_headers();
3845  $this->debug('got character encoding: '.$this->xml_encoding);
3846  // uncompress if necessary
3847  if (isset($this->headers['content-encoding']) && $this->headers['content-encoding'] != '') {
3848  $this->debug('got content encoding: ' . $this->headers['content-encoding']);
3849  if ($this->headers['content-encoding'] == 'deflate' || $this->headers['content-encoding'] == 'gzip') {
3850  // if decoding works, use it. else assume data wasn't gzencoded
3851  if (function_exists('gzuncompress')) {
3852  if ($this->headers['content-encoding'] == 'deflate' && $degzdata = @gzuncompress($data)) {
3853  $data = $degzdata;
3854  } elseif ($this->headers['content-encoding'] == 'gzip' && $degzdata = gzinflate(substr($data, 10))) {
3855  $data = $degzdata;
3856  } else {
3857  $this->fault('SOAP-ENV:Client', 'Errors occurred when trying to decode the data');
3858  return;
3859  }
3860  } else {
3861  $this->fault('SOAP-ENV:Client', 'This Server does not support compressed data');
3862  return;
3863  }
3864  }
3865  }
3866  $this->request .= "\r\n".$data;
3867  $data = $this->parseRequest($this->headers, $data);
3868  $this->requestSOAP = $data;
3869  $this->debug('leaving parse_request');
3870  }
3871 
3889  function invoke_method() {
3890  $this->debug('in invoke_method, methodname=' . $this->methodname . ' methodURI=' . $this->methodURI . ' SOAPAction=' . $this->SOAPAction);
3891 
3892  if ($this->wsdl) {
3893  if ($this->opData = $this->wsdl->getOperationData($this->methodname)) {
3894  $this->debug('in invoke_method, found WSDL operation=' . $this->methodname);
3895  $this->appendDebug('opData=' . $this->varDump($this->opData));
3896  } elseif ($this->opData = $this->wsdl->getOperationDataForSoapAction($this->SOAPAction)) {
3897  // Note: hopefully this case will only be used for doc/lit, since rpc services should have wrapper element
3898  $this->debug('in invoke_method, found WSDL soapAction=' . $this->SOAPAction . ' for operation=' . $this->opData['name']);
3899  $this->appendDebug('opData=' . $this->varDump($this->opData));
3900  $this->methodname = $this->opData['name'];
3901  } else {
3902  $this->debug('in invoke_method, no WSDL for operation=' . $this->methodname);
3903  $this->fault('SOAP-ENV:Client', "Operation '" . $this->methodname . "' is not defined in the WSDL for this service");
3904  return;
3905  }
3906  } else {
3907  $this->debug('in invoke_method, no WSDL to validate method');
3908  }
3909 
3910  // if a . is present in $this->methodname, we see if there is a class in scope,
3911  // which could be referred to. We will also distinguish between two deliminators,
3912  // to allow methods to be called a the class or an instance
3913  $class = '';
3914  $method = '';
3915  if (strpos($this->methodname, '..') > 0) {
3916  $delim = '..';
3917  } else if (strpos($this->methodname, '.') > 0) {
3918  $delim = '.';
3919  } else {
3920  $delim = '';
3921  }
3922 
3923  if (strlen($delim) > 0 && substr_count($this->methodname, $delim) == 1 &&
3924  class_exists(substr($this->methodname, 0, strpos($this->methodname, $delim)))) {
3925  // get the class and method name
3926  $class = substr($this->methodname, 0, strpos($this->methodname, $delim));
3927  $method = substr($this->methodname, strpos($this->methodname, $delim) + strlen($delim));
3928  $this->debug("in invoke_method, class=$class method=$method delim=$delim");
3929  }
3930  // set class handler
3931  // added to support single operations
3932  if ($class == '' && $this->class !='')
3933  {
3934  $class = $this->class;
3935  $delim = "..";
3936  $method = $this->methodname;
3937  }
3938 
3939  // does method exist?
3940  if ($class == '') {
3941  if (!function_exists($this->methodname)) {
3942  $this->debug("in invoke_method, function '$this->methodname' not found!");
3943  $this->result = 'fault: method not found';
3944  $this->fault('SOAP-ENV:Client',"method '$this->methodname' not defined in service");
3945  return;
3946  }
3947  } else {
3948  $method_to_compare = (substr(phpversion(), 0, 2) == '4.') ? strtolower($method) : $method;
3949  if (!in_array($method_to_compare, get_class_methods($class))) {
3950  $this->debug("in invoke_method, method '$this->methodname' not found in class '$class'!");
3951  $this->result = 'fault: method not found';
3952  $this->fault('SOAP-ENV:Client',"method '$this->methodname' not defined in service");
3953  return;
3954  }
3955  }
3956 
3957  // evaluate message, getting back parameters
3958  // verify that request parameters match the method's signature
3959  if(! $this->verify_method($this->methodname,$this->methodparams)){
3960  // debug
3961  $this->debug('ERROR: request not verified against method signature');
3962  $this->result = 'fault: request failed validation against method signature';
3963  // return fault
3964  $this->fault('SOAP-ENV:Client',"Operation '$this->methodname' not defined in service.");
3965  return;
3966  }
3967 
3968  // if there are parameters to pass
3969  $this->debug('in invoke_method, params:');
3970  $this->appendDebug($this->varDump($this->methodparams));
3971  $this->debug("in invoke_method, calling '$this->methodname'");
3972  if (!function_exists('call_user_func_array')) {
3973  if ($class == '') {
3974  $this->debug('in invoke_method, calling function using eval()');
3975  $funcCall = "\$this->methodreturn = $this->methodname(";
3976  } else {
3977  if ($delim == '..') {
3978  $this->debug('in invoke_method, calling class method using eval()');
3979  $funcCall = "\$this->methodreturn = ".$class."::".$method."(";
3980  } else {
3981  $this->debug('in invoke_method, calling instance method using eval()');
3982  // generate unique instance name
3983  $instname = "\$inst_".time();
3984  $funcCall = $instname." = new ".$class."(); ";
3985  $funcCall .= "\$this->methodreturn = ".$instname."->".$method."(";
3986  }
3987  }
3988  if ($this->methodparams) {
3989  foreach ($this->methodparams as $param) {
3990  if (is_array($param) || is_object($param)) {
3991  $this->fault('SOAP-ENV:Client', 'NuSOAP does not handle complexType parameters correctly when using eval; call_user_func_array must be available');
3992  return;
3993  }
3994  $funcCall .= "\"$param\",";
3995  }
3996  $funcCall = substr($funcCall, 0, -1);
3997  }
3998  $funcCall .= ');';
3999  $this->debug('in invoke_method, function call: '.$funcCall);
4000  @eval($funcCall);
4001  } else {
4002  if ($class == '') {
4003  $this->debug('in invoke_method, calling function using call_user_func_array()');
4004  $call_arg = "$this->methodname"; // straight assignment changes $this->methodname to lower case after call_user_func_array()
4005  } elseif ($delim == '..') {
4006  $this->debug('in invoke_method, calling class method using call_user_func_array()');
4007  $call_arg = array ($class, $method);
4008  } else {
4009  $this->debug('in invoke_method, calling instance method using call_user_func_array()');
4010  $instance = new $class ();
4011  $call_arg = array(&$instance, $method);
4012  }
4013  if (is_array($this->methodparams)) {
4014  $this->methodreturn = call_user_func_array($call_arg, array_values($this->methodparams));
4015  } else {
4016  $this->methodreturn = call_user_func_array($call_arg, array());
4017  }
4018  }
4019  $this->debug('in invoke_method, methodreturn:');
4020  $this->appendDebug($this->varDump($this->methodreturn));
4021  $this->debug("in invoke_method, called method $this->methodname, received data of type ".gettype($this->methodreturn));
4022  }
4023 
4035  function serialize_return() {
4036  $this->debug('Entering serialize_return methodname: ' . $this->methodname . ' methodURI: ' . $this->methodURI);
4037  // if fault
4038  if (isset($this->methodreturn) && ((get_class((object)$this->methodreturn) == 'soap_fault') || (get_class((object)$this->methodreturn) == 'nusoap_fault'))) {
4039  $this->debug('got a fault object from method');
4040  $this->fault = $this->methodreturn;
4041  return;
4042  } elseif ($this->methodreturnisliteralxml) {
4043  $return_val = $this->methodreturn;
4044  // returned value(s)
4045  } else {
4046  $this->debug('got a(n) '.gettype($this->methodreturn).' from method');
4047  $this->debug('serializing return value');
4048  if($this->wsdl){
4049  if (sizeof($this->opData['output']['parts']) > 1) {
4050  $this->debug('more than one output part, so use the method return unchanged');
4051  $opParams = $this->methodreturn;
4052  } elseif (sizeof($this->opData['output']['parts']) == 1) {
4053  $this->debug('exactly one output part, so wrap the method return in a simple array');
4054  // TODO: verify that it is not already wrapped!
4055  //foreach ($this->opData['output']['parts'] as $name => $type) {
4056  // $this->debug('wrap in element named ' . $name);
4057  //}
4058  $opParams = array($this->methodreturn);
4059  }
4060  $return_val = $this->wsdl->serializeRPCParameters($this->methodname,'output',$opParams);
4061  $this->appendDebug($this->wsdl->getDebug());
4062  $this->wsdl->clearDebug();
4063  if($errstr = $this->wsdl->getError()){
4064  $this->debug('got wsdl error: '.$errstr);
4065  $this->fault('SOAP-ENV:Server', 'unable to serialize result');
4066  return;
4067  }
4068  } else {
4069  if (isset($this->methodreturn)) {
4070  $return_val = $this->serialize_val($this->methodreturn, 'return');
4071  } else {
4072  $return_val = '';
4073  $this->debug('in absence of WSDL, assume void return for backward compatibility');
4074  }
4075  }
4076  }
4077  $this->debug('return value:');
4078  $this->appendDebug($this->varDump($return_val));
4079 
4080  $this->debug('serializing response');
4081  if ($this->wsdl) {
4082  $this->debug('have WSDL for serialization: style is ' . $this->opData['style']);
4083  if ($this->opData['style'] == 'rpc') {
4084  $this->debug('style is rpc for serialization: use is ' . $this->opData['output']['use']);
4085  if ($this->opData['output']['use'] == 'literal') {
4086  // http://www.ws-i.org/Profiles/BasicProfile-1.1-2004-08-24.html R2735 says rpc/literal accessor elements should not be in a namespace
4087  $payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
4088  } else {
4089  $payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
4090  }
4091  } else {
4092  $this->debug('style is not rpc for serialization: assume document');
4093  $payload = $return_val;
4094  }
4095  } else {
4096  $this->debug('do not have WSDL for serialization: assume rpc/encoded');
4097  $payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
4098  }
4099  $this->result = 'successful';
4100  if($this->wsdl){
4101  //if($this->debug_flag){
4102  $this->appendDebug($this->wsdl->getDebug());
4103  // }
4104  if (isset($opData['output']['encodingStyle'])) {
4105  $encodingStyle = $opData['output']['encodingStyle'];
4106  } else {
4107  $encodingStyle = '';
4108  }
4109  // Added: In case we use a WSDL, return a serialized env. WITH the usedNamespaces.
4110  $this->responseSOAP = $this->serializeEnvelope($payload,$this->responseHeaders,$this->wsdl->usedNamespaces,$this->opData['style'],$this->opData['output']['use'],$encodingStyle);
4111  } else {
4112  $this->responseSOAP = $this->serializeEnvelope($payload,$this->responseHeaders);
4113  }
4114  $this->debug("Leaving serialize_return");
4115  }
4116 
4127  function send_response() {
4128  $this->debug('Enter send_response');
4129  if ($this->fault) {
4130  $payload = $this->fault->serialize();
4131  $this->outgoing_headers[] = "HTTP/1.0 500 Internal Server Error";
4132  $this->outgoing_headers[] = "Status: 500 Internal Server Error";
4133  } else {
4134  $payload = $this->responseSOAP;
4135  // Some combinations of PHP+Web server allow the Status
4136  // to come through as a header. Since OK is the default
4137  // just do nothing.
4138  // $this->outgoing_headers[] = "HTTP/1.0 200 OK";
4139  // $this->outgoing_headers[] = "Status: 200 OK";
4140  }
4141  // add debug data if in debug mode
4142  if(isset($this->debug_flag) && $this->debug_flag){
4143  $payload .= $this->getDebugAsXMLComment();
4144  }
4145  $this->outgoing_headers[] = "Server: $this->title Server v$this->version";
4146  preg_match('/\$Revisio' . 'n: ([^ ]+)/', $this->revision, $rev);
4147  $this->outgoing_headers[] = "X-SOAP-Server: $this->title/$this->version (".$rev[1].")";
4148  // Let the Web server decide about this
4149  //$this->outgoing_headers[] = "Connection: Close\r\n";
4150  $payload = $this->getHTTPBody($payload);
4151  $type = $this->getHTTPContentType();
4152  $charset = $this->getHTTPContentTypeCharset();
4153  $this->outgoing_headers[] = "Content-Type: $type" . ($charset ? '; charset=' . $charset : '');
4154  //begin code to compress payload - by John
4155  // NOTE: there is no way to know whether the Web server will also compress
4156  // this data.
4157  if (strlen($payload) > 1024 && isset($this->headers) && isset($this->headers['accept-encoding'])) {
4158  if (strstr($this->headers['accept-encoding'], 'gzip')) {
4159  if (function_exists('gzencode')) {
4160  if (isset($this->debug_flag) && $this->debug_flag) {
4161  $payload .= "<!-- Content being gzipped -->";
4162  }
4163  $this->outgoing_headers[] = "Content-Encoding: gzip";
4164  $payload = gzencode($payload);
4165  } else {
4166  if (isset($this->debug_flag) && $this->debug_flag) {
4167  $payload .= "<!-- Content will not be gzipped: no gzencode -->";
4168  }
4169  }
4170  } elseif (strstr($this->headers['accept-encoding'], 'deflate')) {
4171  // Note: MSIE requires gzdeflate output (no Zlib header and checksum),
4172  // instead of gzcompress output,
4173  // which conflicts with HTTP 1.1 spec (http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.5)
4174  if (function_exists('gzdeflate')) {
4175  if (isset($this->debug_flag) && $this->debug_flag) {
4176  $payload .= "<!-- Content being deflated -->";
4177  }
4178  $this->outgoing_headers[] = "Content-Encoding: deflate";
4179  $payload = gzdeflate($payload);
4180  } else {
4181  if (isset($this->debug_flag) && $this->debug_flag) {
4182  $payload .= "<!-- Content will not be deflated: no gzcompress -->";
4183  }
4184  }
4185  }
4186  }
4187  //end code
4188  $this->outgoing_headers[] = "Content-Length: ".strlen($payload);
4189  reset($this->outgoing_headers);
4190  foreach($this->outgoing_headers as $hdr){
4191  header($hdr, false);
4192  }
4193  print $payload;
4194  $this->response = join("\r\n",$this->outgoing_headers)."\r\n\r\n".$payload;
4195  }
4196 
4206  function verify_method($operation,$request){
4207  if(isset($this->wsdl) && is_object($this->wsdl)){
4208  if($this->wsdl->getOperationData($operation)){
4209  return true;
4210  }
4211  } elseif(isset($this->operations[$operation])){
4212  return true;
4213  }
4214  return false;
4215  }
4216 
4225  function parseRequest($headers, $data) {
4226  $this->debug('Entering parseRequest() for data of length ' . strlen($data) . ' and type ' . $headers['content-type']);
4227  if (!strstr($headers['content-type'], 'text/xml')) {
4228  $this->setError('Request not of type text/xml');
4229  return false;
4230  }
4231  if (strpos($headers['content-type'], '=')) {
4232  $enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1));
4233  $this->debug('Got response encoding: ' . $enc);
4234  if(preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)){
4235  $this->xml_encoding = strtoupper($enc);
4236  } else {
4237  $this->xml_encoding = 'US-ASCII';
4238  }
4239  } else {
4240  // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
4241  $this->xml_encoding = 'ISO-8859-1';
4242  }
4243  $this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser');
4244  // parse response, get soap parser obj
4245  $parser = new nusoap_parser($data,$this->xml_encoding,'',$this->decode_utf8);
4246  // parser debug
4247  $this->debug("parser debug: \n".$parser->getDebug());
4248  // if fault occurred during message parsing
4249  if($err = $parser->getError()){
4250  $this->result = 'fault: error in msg parsing: '.$err;
4251  $this->fault('SOAP-ENV:Client',"error in msg parsing:\n".$err);
4252  // else successfully parsed request into soapval object
4253  } else {
4254  // get/set methodname
4255  $this->methodURI = $parser->root_struct_namespace;
4256  $this->methodname = $parser->root_struct_name;
4257  $this->debug('methodname: '.$this->methodname.' methodURI: '.$this->methodURI);
4258  $this->debug('calling parser->get_soapbody()');
4259  $this->methodparams = $parser->get_soapbody();
4260  // get SOAP headers
4261  $this->requestHeaders = $parser->getHeaders();
4262  // get SOAP Header
4263  $this->requestHeader = $parser->get_soapheader();
4264  // add document for doclit support
4265  $this->document = $parser->document;
4266  }
4267  }
4268 
4276  function getHTTPBody($soapmsg) {
4277  return $soapmsg;
4278  }
4279 
4288  function getHTTPContentType() {
4289  return 'text/xml';
4290  }
4291 
4301  function getHTTPContentTypeCharset() {
4302  return $this->soap_defencoding;
4303  }
4304 
4314  function add_to_map($methodname,$in,$out){
4315  $this->operations[$methodname] = array('name' => $methodname,'in' => $in,'out' => $out);
4316  }
4317 
4332  function register($name,$in=array(),$out=array(),$namespace=false,$soapaction=false,$style=false,$use=false,$documentation='',$encodingStyle=''){
4333  global $HTTP_SERVER_VARS;
4334 
4335  if($this->externalWSDLURL){
4336  die('You cannot bind to an external WSDL file, and register methods outside of it! Please choose either WSDL or no WSDL.');
4337  }
4338  if (! $name) {
4339  die('You must specify a name when you register an operation');
4340  }
4341  if (!is_array($in)) {
4342  die('You must provide an array for operation inputs');
4343  }
4344  if (!is_array($out)) {
4345  die('You must provide an array for operation outputs');
4346  }
4347  if(false == $namespace) {
4348  }
4349  if(false == $soapaction) {
4350  if (isset($_SERVER)) {
4351  $SERVER_NAME = $_SERVER['SERVER_NAME'];
4352  $SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
4353  $HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off');
4354  } elseif (isset($HTTP_SERVER_VARS)) {
4355  $SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
4356  $SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
4357  $HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off';
4358  } else {
4359  $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
4360  }
4361  if ($HTTPS == '1' || $HTTPS == 'on') {
4362  $SCHEME = 'https';
4363  } else {
4364  $SCHEME = 'http';
4365  }
4366  $soapaction = "$SCHEME://$SERVER_NAME$SCRIPT_NAME/$name";
4367  }
4368  if(false == $style) {
4369  $style = "rpc";
4370  }
4371  if(false == $use) {
4372  $use = "encoded";
4373  }
4374  if ($use == 'encoded' && $encodingStyle = '') {
4375  $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
4376  }
4377 
4378  $this->operations[$name] = array(
4379  'name' => $name,
4380  'in' => $in,
4381  'out' => $out,
4382  'namespace' => $namespace,
4383  'soapaction' => $soapaction,
4384  'style' => $style);
4385  if($this->wsdl){
4386  $this->wsdl->addOperation($name,$in,$out,$namespace,$soapaction,$style,$use,$documentation,$encodingStyle);
4387  }
4388  return true;
4389  }
4390 
4401  function fault($faultcode,$faultstring,$faultactor='',$faultdetail=''){
4402  if ($faultdetail == '' && $this->debug_flag) {
4403  $faultdetail = $this->getDebug();
4404  }
4405  $this->fault = new nusoap_fault($faultcode,$faultactor,$faultstring,$faultdetail);
4406  $this->fault->soap_defencoding = $this->soap_defencoding;
4407  }
4408 
4420  function configureWSDL($serviceName,$namespace = false,$endpoint = false,$style='rpc', $transport = 'http://schemas.xmlsoap.org/soap/http', $schemaTargetNamespace = false)
4421  {
4422  global $HTTP_SERVER_VARS;
4423 
4424  if (isset($_SERVER)) {
4425  $SERVER_NAME = $_SERVER['SERVER_NAME'];
4426  $SERVER_PORT = $_SERVER['SERVER_PORT'];
4427  $SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
4428  $HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off');
4429  } elseif (isset($HTTP_SERVER_VARS)) {
4430  $SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
4431  $SERVER_PORT = $HTTP_SERVER_VARS['SERVER_PORT'];
4432  $SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
4433  $HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off';
4434  } else {
4435  $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
4436  }
4437  // If server name has port number attached then strip it (else port number gets duplicated in WSDL output) (occurred using lighttpd and FastCGI)
4438  $colon = strpos($SERVER_NAME,":");
4439  if ($colon) {
4440  $SERVER_NAME = substr($SERVER_NAME, 0, $colon);
4441  }
4442  if ($SERVER_PORT == 80) {
4443  $SERVER_PORT = '';
4444  } else {
4445  $SERVER_PORT = ':' . $SERVER_PORT;
4446  }
4447  if(false == $namespace) {
4448  $namespace = "http://$SERVER_NAME/soap/$serviceName";
4449  }
4450 
4451  if(false == $endpoint) {
4452  if ($HTTPS == '1' || $HTTPS == 'on') {
4453  $SCHEME = 'https';
4454  } else {
4455  $SCHEME = 'http';
4456  }
4457  $endpoint = "$SCHEME://$SERVER_NAME$SERVER_PORT$SCRIPT_NAME";
4458  }
4459 
4460  if(false == $schemaTargetNamespace) {
4461  $schemaTargetNamespace = $namespace;
4462  }
4463 
4464  $this->wsdl = new wsdl;
4465  $this->wsdl->serviceName = $serviceName;
4466  $this->wsdl->endpoint = $endpoint;
4467  $this->wsdl->namespaces['tns'] = $namespace;
4468  $this->wsdl->namespaces['soap'] = 'http://schemas.xmlsoap.org/wsdl/soap/';
4469  $this->wsdl->namespaces['wsdl'] = 'http://schemas.xmlsoap.org/wsdl/';
4470  if ($schemaTargetNamespace != $namespace) {
4471  $this->wsdl->namespaces['types'] = $schemaTargetNamespace;
4472  }
4473  $this->wsdl->schemas[$schemaTargetNamespace][0] = new nusoap_xmlschema('', '', $this->wsdl->namespaces);
4474  if ($style == 'document') {
4475  $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaInfo['elementFormDefault'] = 'qualified';
4476  }
4477  $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaTargetNamespace = $schemaTargetNamespace;
4478  $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/soap/encoding/'][0] = array('location' => '', 'loaded' => true);
4479  $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/wsdl/'][0] = array('location' => '', 'loaded' => true);
4480  $this->wsdl->bindings[$serviceName.'Binding'] = array(
4481  'name'=>$serviceName.'Binding',
4482  'style'=>$style,
4483  'transport'=>$transport,
4484  'portType'=>$serviceName.'PortType');
4485  $this->wsdl->ports[$serviceName.'Port'] = array(
4486  'binding'=>$serviceName.'Binding',
4487  'location'=>$endpoint,
4488  'bindingType'=>'http://schemas.xmlsoap.org/wsdl/soap/');
4489  }
4490 }
4491 
4495 class soap_server extends nusoap_server {
4496 }
4497 
4498 ?><?php
4499 
4500 
4501 
4511 class wsdl extends nusoap_base {
4512  // URL or filename of the root of this WSDL
4513  var $wsdl;
4514  // define internal arrays of bindings, ports, operations, messages, etc.
4515  var $schemas = array();
4516  var $currentSchema;
4517  var $message = array();
4518  var $complexTypes = array();
4519  var $messages = array();
4520  var $currentMessage;
4521  var $currentOperation;
4522  var $portTypes = array();
4523  var $currentPortType;
4524  var $bindings = array();
4525  var $currentBinding;
4526  var $ports = array();
4527  var $currentPort;
4528  var $opData = array();
4529  var $status = '';
4530  var $documentation = false;
4531  var $endpoint = '';
4532  // array of wsdl docs to import
4533  var $import = array();
4534  // parser vars
4535  var $parser;
4536  var $position = 0;
4537  var $depth = 0;
4538  var $depth_array = array();
4539  // for getting wsdl
4540  var $proxyhost = '';
4541  var $proxyport = '';
4542  var $proxyusername = '';
4543  var $proxypassword = '';
4544  var $timeout = 0;
4545  var $response_timeout = 30;
4546  var $curl_options = array(); // User-specified cURL options
4547  var $use_curl = false; // whether to always try to use cURL
4548  // for HTTP authentication
4549  var $username = ''; // Username for HTTP authentication
4550  var $password = ''; // Password for HTTP authentication
4551  var $authtype = ''; // Type of HTTP authentication
4552  var $certRequest = array(); // Certificate for HTTP SSL authentication
4553 
4568  function __construct($wsdl = '',$proxyhost=false,$proxyport=false,$proxyusername=false,$proxypassword=false,$timeout=0,$response_timeout=30,$curl_options=null,$use_curl=false){
4569  parent::__construct();
4570  $this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout");
4571  $this->proxyhost = $proxyhost;
4572  $this->proxyport = $proxyport;
4573  $this->proxyusername = $proxyusername;
4574  $this->proxypassword = $proxypassword;
4575  $this->timeout = $timeout;
4576  $this->response_timeout = $response_timeout;
4577  if (is_array($curl_options))
4578  $this->curl_options = $curl_options;
4579  $this->use_curl = $use_curl;
4580  $this->fetchWSDL($wsdl);
4581  }
4582 
4588  function fetchWSDL($wsdl) {
4589  $this->debug("parse and process WSDL path=$wsdl");
4590  $this->wsdl = $wsdl;
4591  // parse wsdl file
4592  if ($this->wsdl != "") {
4593  $this->parseWSDL($this->wsdl);
4594  }
4595  // imports
4596  // TODO: handle imports more properly, grabbing them in-line and nesting them
4597  $imported_urls = array();
4598  $imported = 1;
4599  while ($imported > 0) {
4600  $imported = 0;
4601  // Schema imports
4602  foreach ($this->schemas as $ns => $list) {
4603  foreach ($list as $xs) {
4604  $wsdlparts = parse_url($this->wsdl); // this is bogusly simple!
4605  foreach ($xs->imports as $ns2 => $list2) {
4606  for ($ii = 0; $ii < count($list2); $ii++) {
4607  if (! $list2[$ii]['loaded']) {
4608  $this->schemas[$ns]->imports[$ns2][$ii]['loaded'] = true;
4609  $url = $list2[$ii]['location'];
4610  if ($url != '') {
4611  $urlparts = parse_url($url);
4612  if (!isset($urlparts['host'])) {
4613  $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' .$wsdlparts['port'] : '') .
4614  substr($wsdlparts['path'],0,strrpos($wsdlparts['path'],'/') + 1) .$urlparts['path'];
4615  }
4616  if (! in_array($url, $imported_urls)) {
4617  $this->parseWSDL($url);
4618  $imported++;
4619  $imported_urls[] = $url;
4620  }
4621  } else {
4622  $this->debug("Unexpected scenario: empty URL for unloaded import");
4623  }
4624  }
4625  }
4626  }
4627  }
4628  }
4629  // WSDL imports
4630  $wsdlparts = parse_url($this->wsdl); // this is bogusly simple!
4631  foreach ($this->import as $ns => $list) {
4632  for ($ii = 0; $ii < count($list); $ii++) {
4633  if (! $list[$ii]['loaded']) {
4634  $this->import[$ns][$ii]['loaded'] = true;
4635  $url = $list[$ii]['location'];
4636  if ($url != '') {
4637  $urlparts = parse_url($url);
4638  if (!isset($urlparts['host'])) {
4639  $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' . $wsdlparts['port'] : '') .
4640  substr($wsdlparts['path'],0,strrpos($wsdlparts['path'],'/') + 1) .$urlparts['path'];
4641  }
4642  if (! in_array($url, $imported_urls)) {
4643  $this->parseWSDL($url);
4644  $imported++;
4645  $imported_urls[] = $url;
4646  }
4647  } else {
4648  $this->debug("Unexpected scenario: empty URL for unloaded import");
4649  }
4650  }
4651  }
4652  }
4653  }
4654  // add new data to operation data
4655  foreach($this->bindings as $binding => $bindingData) {
4656  if (isset($bindingData['operations']) && is_array($bindingData['operations'])) {
4657  foreach($bindingData['operations'] as $operation => $data) {
4658  $this->debug('post-parse data gathering for ' . $operation);
4659  $this->bindings[$binding]['operations'][$operation]['input'] =
4660  isset($this->bindings[$binding]['operations'][$operation]['input']) ?
4661  array_merge($this->bindings[$binding]['operations'][$operation]['input'], $this->portTypes[ $bindingData['portType'] ][$operation]['input']) :
4662  $this->portTypes[ $bindingData['portType'] ][$operation]['input'];
4663  $this->bindings[$binding]['operations'][$operation]['output'] =
4664  isset($this->bindings[$binding]['operations'][$operation]['output']) ?
4665  array_merge($this->bindings[$binding]['operations'][$operation]['output'], $this->portTypes[ $bindingData['portType'] ][$operation]['output']) :
4666  $this->portTypes[ $bindingData['portType'] ][$operation]['output'];
4667  if(isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ])){
4668  $this->bindings[$binding]['operations'][$operation]['input']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ];
4669  }
4670  if(isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ])){
4671  $this->bindings[$binding]['operations'][$operation]['output']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ];
4672  }
4673  // Set operation style if necessary, but do not override one already provided
4674  if (isset($bindingData['style']) && !isset($this->bindings[$binding]['operations'][$operation]['style'])) {
4675  $this->bindings[$binding]['operations'][$operation]['style'] = $bindingData['style'];
4676  }
4677  $this->bindings[$binding]['operations'][$operation]['transport'] = isset($bindingData['transport']) ? $bindingData['transport'] : '';
4678  $this->bindings[$binding]['operations'][$operation]['documentation'] = isset($this->portTypes[ $bindingData['portType'] ][$operation]['documentation']) ? $this->portTypes[ $bindingData['portType'] ][$operation]['documentation'] : '';
4679  $this->bindings[$binding]['operations'][$operation]['endpoint'] = isset($bindingData['endpoint']) ? $bindingData['endpoint'] : '';
4680  }
4681  }
4682  }
4683  }
4684 
4691  function parseWSDL($wsdl = '') {
4692  $this->debug("parse WSDL at path=$wsdl");
4693 
4694  if ($wsdl == '') {
4695  $this->debug('no wsdl passed to parseWSDL()!!');
4696  $this->setError('no wsdl passed to parseWSDL()!!');
4697  return false;
4698  }
4699 
4700  // parse $wsdl for url format
4701  $wsdl_props = parse_url($wsdl);
4702 
4703  if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'http' || $wsdl_props['scheme'] == 'https')) {
4704  $this->debug('getting WSDL http(s) URL ' . $wsdl);
4705  // get wsdl
4706  $tr = new soap_transport_http($wsdl, $this->curl_options, $this->use_curl);
4707  $tr->request_method = 'GET';
4708  $tr->useSOAPAction = false;
4709  if($this->proxyhost && $this->proxyport){
4710  $tr->setProxy($this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword);
4711  }
4712  if ($this->authtype != '') {
4713  $tr->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest);
4714  }
4715  $tr->setEncoding('gzip, deflate');
4716  $wsdl_string = $tr->send('', $this->timeout, $this->response_timeout);
4717  //$this->debug("WSDL request\n" . $tr->outgoing_payload);
4718  //$this->debug("WSDL response\n" . $tr->incoming_payload);
4719  $this->appendDebug($tr->getDebug());
4720  // catch errors
4721  if($err = $tr->getError() ){
4722  $errstr = 'HTTP ERROR: '.$err;
4723  $this->debug($errstr);
4724  $this->setError($errstr);
4725  unset($tr);
4726  return false;
4727  }
4728  unset($tr);
4729  $this->debug("got WSDL URL");
4730  } else {
4731  // $wsdl is not http(s), so treat it as a file URL or plain file path
4732  if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'file') && isset($wsdl_props['path'])) {
4733  $path = isset($wsdl_props['host']) ? ($wsdl_props['host'] . ':' . $wsdl_props['path']) : $wsdl_props['path'];
4734  } else {
4735  $path = $wsdl;
4736  }
4737  $this->debug('getting WSDL file ' . $path);
4738  if ($fp = @fopen($path, 'r')) {
4739  $wsdl_string = '';
4740  while ($data = fread($fp, 32768)) {
4741  $wsdl_string .= $data;
4742  }
4743  fclose($fp);
4744  } else {
4745  $errstr = "Bad path to WSDL file $path";
4746  $this->debug($errstr);
4747  $this->setError($errstr);
4748  return false;
4749  }
4750  }
4751  $this->debug('Parse WSDL');
4752  // end new code added
4753  // Create an XML parser.
4754  $this->parser = xml_parser_create();
4755  // Set the options for parsing the XML data.
4756  // xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
4757  xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
4758  // Set the object for the parser.
4759  xml_set_object($this->parser, $this);
4760  // Set the element handlers for the parser.
4761  xml_set_element_handler($this->parser, 'start_element', 'end_element');
4762  xml_set_character_data_handler($this->parser, 'character_data');
4763  // Parse the XML file.
4764  if (!xml_parse($this->parser, $wsdl_string, true)) {
4765  // Display an error message.
4766  $errstr = sprintf(
4767  'XML error parsing WSDL from %s on line %d: %s',
4768  $wsdl,
4769  xml_get_current_line_number($this->parser),
4770  xml_error_string(xml_get_error_code($this->parser))
4771  );
4772  $this->debug($errstr);
4773  $this->debug("XML payload:\n" . $wsdl_string);
4774  $this->setError($errstr);
4775  return false;
4776  }
4777  // free the parser
4778  xml_parser_free($this->parser);
4779  $this->debug('Parsing WSDL done');
4780  // catch wsdl parse errors
4781  if($this->getError()){
4782  return false;
4783  }
4784  return true;
4785  }
4786 
4795  function start_element($parser, $name, $attrs)
4796  {
4797  if ($this->status == 'schema') {
4798  $this->currentSchema->schemaStartElement($parser, $name, $attrs);
4799  $this->appendDebug($this->currentSchema->getDebug());
4800  $this->currentSchema->clearDebug();
4801  } elseif (preg_match('/schema$/', $name)) {
4802  $this->debug('Parsing WSDL schema');
4803  // $this->debug("startElement for $name ($attrs[name]). status = $this->status (".$this->getLocalPart($name).")");
4804  $this->status = 'schema';
4805  $this->currentSchema = new nusoap_xmlschema('', '', $this->namespaces);
4806  $this->currentSchema->schemaStartElement($parser, $name, $attrs);
4807  $this->appendDebug($this->currentSchema->getDebug());
4808  $this->currentSchema->clearDebug();
4809  } else {
4810  // position in the total number of elements, starting from 0
4811  $pos = $this->position++;
4812  $depth = $this->depth++;
4813  // set self as current value for this depth
4814  $this->depth_array[$depth] = $pos;
4815  $this->message[$pos] = array('cdata' => '');
4816  // process attributes
4817  if (count($attrs) > 0) {
4818  // register namespace declarations
4819  foreach($attrs as $k => $v) {
4820  if (preg_match('/^xmlns/',$k)) {
4821  if ($ns_prefix = substr(strrchr($k, ':'), 1)) {
4822  $this->namespaces[$ns_prefix] = $v;
4823  } else {
4824  $this->namespaces['ns' . (count($this->namespaces) + 1)] = $v;
4825  }
4826  if ($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema') {
4827  $this->XMLSchemaVersion = $v;
4828  $this->namespaces['xsi'] = $v . '-instance';
4829  }
4830  }
4831  }
4832  // expand each attribute prefix to its namespace
4833  foreach($attrs as $k => $v) {
4834  $k = strpos($k, ':') ? $this->expandQname($k) : $k;
4835  if ($k != 'location' && $k != 'soapAction' && $k != 'namespace') {
4836  $v = strpos($v, ':') ? $this->expandQname($v) : $v;
4837  }
4838  $eAttrs[$k] = $v;
4839  }
4840  $attrs = $eAttrs;
4841  } else {
4842  $attrs = array();
4843  }
4844  // get element prefix, namespace and name
4845  if (preg_match('/:/', $name)) {
4846  // get ns prefix
4847  $prefix = substr($name, 0, strpos($name, ':'));
4848  // get ns
4849  $namespace = isset($this->namespaces[$prefix]) ? $this->namespaces[$prefix] : '';
4850  // get unqualified name
4851  $name = substr(strstr($name, ':'), 1);
4852  }
4853  // process attributes, expanding any prefixes to namespaces
4854  // find status, register data
4855  switch ($this->status) {
4856  case 'message':
4857  if ($name == 'part') {
4858  if (isset($attrs['type'])) {
4859  $this->debug("msg " . $this->currentMessage . ": found part (with type) $attrs[name]: " . implode(',', $attrs));
4860  $this->messages[$this->currentMessage][$attrs['name']] = $attrs['type'];
4861  }
4862  if (isset($attrs['element'])) {
4863  $this->debug("msg " . $this->currentMessage . ": found part (with element) $attrs[name]: " . implode(',', $attrs));
4864  $this->messages[$this->currentMessage][$attrs['name']] = $attrs['element'] . '^';
4865  }
4866  }
4867  break;
4868  case 'portType':
4869  switch ($name) {
4870  case 'operation':
4871  $this->currentPortOperation = $attrs['name'];
4872  $this->debug("portType $this->currentPortType operation: $this->currentPortOperation");
4873  if (isset($attrs['parameterOrder'])) {
4874  $this->portTypes[$this->currentPortType][$attrs['name']]['parameterOrder'] = $attrs['parameterOrder'];
4875  }
4876  break;
4877  case 'documentation':
4878  $this->documentation = true;
4879  break;
4880  // merge input/output data
4881  default:
4882  $m = isset($attrs['message']) ? $this->getLocalPart($attrs['message']) : '';
4883  $this->portTypes[$this->currentPortType][$this->currentPortOperation][$name]['message'] = $m;
4884  break;
4885  }
4886  break;
4887  case 'binding':
4888  switch ($name) {
4889  case 'binding':
4890  // get ns prefix
4891  if (isset($attrs['style'])) {
4892  $this->bindings[$this->currentBinding]['prefix'] = $prefix;
4893  }
4894  $this->bindings[$this->currentBinding] = array_merge($this->bindings[$this->currentBinding], $attrs);
4895  break;
4896  case 'header':
4897  $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus]['headers'][] = $attrs;
4898  break;
4899  case 'operation':
4900  if (isset($attrs['soapAction'])) {
4901  $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['soapAction'] = $attrs['soapAction'];
4902  }
4903  if (isset($attrs['style'])) {
4904  $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['style'] = $attrs['style'];
4905  }
4906  if (isset($attrs['name'])) {
4907  $this->currentOperation = $attrs['name'];
4908  $this->debug("current binding operation: $this->currentOperation");
4909  $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['name'] = $attrs['name'];
4910  $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['binding'] = $this->currentBinding;
4911  $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['endpoint'] = isset($this->bindings[$this->currentBinding]['endpoint']) ? $this->bindings[$this->currentBinding]['endpoint'] : '';
4912  }
4913  break;
4914  case 'input':
4915  $this->opStatus = 'input';
4916  break;
4917  case 'output':
4918  $this->opStatus = 'output';
4919  break;
4920  case 'body':
4921  if (isset($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus])) {
4922  $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = array_merge($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus], $attrs);
4923  } else {
4924  $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = $attrs;
4925  }
4926  break;
4927  }
4928  break;
4929  case 'service':
4930  switch ($name) {
4931  case 'port':
4932  $this->currentPort = $attrs['name'];
4933  $this->debug('current port: ' . $this->currentPort);
4934  $this->ports[$this->currentPort]['binding'] = $this->getLocalPart($attrs['binding']);
4935 
4936  break;
4937  case 'address':
4938  $this->ports[$this->currentPort]['location'] = $attrs['location'];
4939  $this->ports[$this->currentPort]['bindingType'] = $namespace;
4940  $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['bindingType'] = $namespace;
4941  $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['endpoint'] = $attrs['location'];
4942  break;
4943  }
4944  break;
4945  }
4946  // set status
4947  switch ($name) {
4948  case 'import':
4949  if (isset($attrs['location'])) {
4950  $this->import[$attrs['namespace']][] = array('location' => $attrs['location'], 'loaded' => false);
4951  $this->debug('parsing import ' . $attrs['namespace']. ' - ' . $attrs['location'] . ' (' . count($this->import[$attrs['namespace']]).')');
4952  } else {
4953  $this->import[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
4954  if (! $this->getPrefixFromNamespace($attrs['namespace'])) {
4955  $this->namespaces['ns'.(count($this->namespaces)+1)] = $attrs['namespace'];
4956  }
4957  $this->debug('parsing import ' . $attrs['namespace']. ' - [no location] (' . count($this->import[$attrs['namespace']]).')');
4958  }
4959  break;
4960  //wait for schema
4961  //case 'types':
4962  // $this->status = 'schema';
4963  // break;
4964  case 'message':
4965  $this->status = 'message';
4966  $this->messages[$attrs['name']] = array();
4967  $this->currentMessage = $attrs['name'];
4968  break;
4969  case 'portType':
4970  $this->status = 'portType';
4971  $this->portTypes[$attrs['name']] = array();
4972  $this->currentPortType = $attrs['name'];
4973  break;
4974  case "binding":
4975  if (isset($attrs['name'])) {
4976  // get binding name
4977  if (strpos($attrs['name'], ':')) {
4978  $this->currentBinding = $this->getLocalPart($attrs['name']);
4979  } else {
4980  $this->currentBinding = $attrs['name'];
4981  }
4982  $this->status = 'binding';
4983  $this->bindings[$this->currentBinding]['portType'] = $this->getLocalPart($attrs['type']);
4984  $this->debug("current binding: $this->currentBinding of portType: " . $attrs['type']);
4985  }
4986  break;
4987  case 'service':
4988  $this->serviceName = $attrs['name'];
4989  $this->status = 'service';
4990  $this->debug('current service: ' . $this->serviceName);
4991  break;
4992  case 'definitions':
4993  foreach ($attrs as $name => $value) {
4994  $this->wsdl_info[$name] = $value;
4995  }
4996  break;
4997  }
4998  }
4999  }
5000 
5008  function end_element($parser, $name){
5009  // unset schema status
5010  if (/*preg_match('/types$/', $name) ||*/ preg_match('/schema$/', $name)) {
5011  $this->status = "";
5012  $this->appendDebug($this->currentSchema->getDebug());
5013  $this->currentSchema->clearDebug();
5014  $this->schemas[$this->currentSchema->schemaTargetNamespace][] = $this->currentSchema;
5015  $this->debug('Parsing WSDL schema done');
5016  }
5017  if ($this->status == 'schema') {
5018  $this->currentSchema->schemaEndElement($parser, $name);
5019  } else {
5020  // bring depth down a notch
5021  $this->depth--;
5022  }
5023  // end documentation
5024  if ($this->documentation) {
5025  //TODO: track the node to which documentation should be assigned; it can be a part, message, etc.
5026  //$this->portTypes[$this->currentPortType][$this->currentPortOperation]['documentation'] = $this->documentation;
5027  $this->documentation = false;
5028  }
5029  }
5030 
5038  function character_data($parser, $data)
5039  {
5040  $pos = isset($this->depth_array[$this->depth]) ? $this->depth_array[$this->depth] : 0;
5041  if (isset($this->message[$pos]['cdata'])) {
5042  $this->message[$pos]['cdata'] .= $data;
5043  }
5044  if ($this->documentation) {
5045  $this->documentation .= $data;
5046  }
5047  }
5048 
5058  function setCredentials($username, $password, $authtype = 'basic', $certRequest = array()) {
5059  $this->debug("setCredentials username=$username authtype=$authtype certRequest=");
5060  $this->appendDebug($this->varDump($certRequest));
5061  $this->username = $username;
5062  $this->password = $password;
5063  $this->authtype = $authtype;
5064  $this->certRequest = $certRequest;
5065  }
5066 
5067  function getBindingData($binding)
5068  {
5069  if (is_array($this->bindings[$binding])) {
5070  return $this->bindings[$binding];
5071  }
5072  }
5073 
5081  function getOperations($bindingType = 'soap') {
5082  $ops = array();
5083  if ($bindingType == 'soap') {
5084  $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
5085  } elseif ($bindingType == 'soap12') {
5086  $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
5087  }
5088  // loop thru ports
5089  foreach($this->ports as $port => $portData) {
5090  // binding type of port matches parameter
5091  if ($portData['bindingType'] == $bindingType) {
5092  //$this->debug("getOperations for port $port");
5093  //$this->debug("port data: " . $this->varDump($portData));
5094  //$this->debug("bindings: " . $this->varDump($this->bindings[ $portData['binding'] ]));
5095  // merge bindings
5096  if (isset($this->bindings[ $portData['binding'] ]['operations'])) {
5097  $ops = array_merge ($ops, $this->bindings[ $portData['binding'] ]['operations']);
5098  }
5099  }
5100  }
5101  return $ops;
5102  }
5103 
5112  function getOperationData($operation, $bindingType = 'soap')
5113  {
5114  if ($bindingType == 'soap') {
5115  $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
5116  } elseif ($bindingType == 'soap12') {
5117  $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
5118  }
5119  // loop thru ports
5120  foreach($this->ports as $port => $portData) {
5121  // binding type of port matches parameter
5122  if ($portData['bindingType'] == $bindingType) {
5123  // get binding
5124  //foreach($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) {
5125  foreach(array_keys($this->bindings[ $portData['binding'] ]['operations']) as $bOperation) {
5126  // note that we could/should also check the namespace here
5127  if ($operation == $bOperation) {
5128  $opData = $this->bindings[ $portData['binding'] ]['operations'][$operation];
5129  return $opData;
5130  }
5131  }
5132  }
5133  }
5134  }
5135 
5144  function getOperationDataForSoapAction($soapAction, $bindingType = 'soap') {
5145  if ($bindingType == 'soap') {
5146  $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
5147  } elseif ($bindingType == 'soap12') {
5148  $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
5149  }
5150  // loop thru ports
5151  foreach($this->ports as $port => $portData) {
5152  // binding type of port matches parameter
5153  if ($portData['bindingType'] == $bindingType) {
5154  // loop through operations for the binding
5155  foreach ($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) {
5156  if ($opData['soapAction'] == $soapAction) {
5157  return $opData;
5158  }
5159  }
5160  }
5161  }
5162  }
5163 
5182  function getTypeDef($type, $ns) {
5183  $this->debug("in getTypeDef: type=$type, ns=$ns");
5184  if ((! $ns) && isset($this->namespaces['tns'])) {
5185  $ns = $this->namespaces['tns'];
5186  $this->debug("in getTypeDef: type namespace forced to $ns");
5187  }
5188  if (!isset($this->schemas[$ns])) {
5189  foreach ($this->schemas as $ns0 => $schema0) {
5190  if (strcasecmp($ns, $ns0) == 0) {
5191  $this->debug("in getTypeDef: replacing schema namespace $ns with $ns0");
5192  $ns = $ns0;
5193  break;
5194  }
5195  }
5196  }
5197  if (isset($this->schemas[$ns])) {
5198  $this->debug("in getTypeDef: have schema for namespace $ns");
5199  for ($i = 0; $i < count($this->schemas[$ns]); $i++) {
5200  $xs = &$this->schemas[$ns][$i];
5201  $t = $xs->getTypeDef($type);
5202  //$this->appendDebug($xs->getDebug());
5203  //$xs->clearDebug();
5204  if ($t) {
5205  if (!isset($t['phpType'])) {
5206  // get info for type to tack onto the element
5207  $uqType = substr($t['type'], strrpos($t['type'], ':') + 1);
5208  $ns = substr($t['type'], 0, strrpos($t['type'], ':'));
5209  $etype = $this->getTypeDef($uqType, $ns);
5210  if ($etype) {
5211  $this->debug("found type for [element] $type:");
5212  $this->debug($this->varDump($etype));
5213  if (isset($etype['phpType'])) {
5214  $t['phpType'] = $etype['phpType'];
5215  }
5216  if (isset($etype['elements'])) {
5217  $t['elements'] = $etype['elements'];
5218  }
5219  if (isset($etype['attrs'])) {
5220  $t['attrs'] = $etype['attrs'];
5221  }
5222  }
5223  }
5224  return $t;
5225  }
5226  }
5227  } else {
5228  $this->debug("in getTypeDef: do not have schema for namespace $ns");
5229  }
5230  return false;
5231  }
5232 
5238  function webDescription(){
5239  global $HTTP_SERVER_VARS;
5240 
5241  if (isset($_SERVER)) {
5242  $PHP_SELF = $_SERVER['PHP_SELF'];
5243  } elseif (isset($HTTP_SERVER_VARS)) {
5244  $PHP_SELF = $HTTP_SERVER_VARS['PHP_SELF'];
5245  } else {
5246  $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
5247  }
5248  // begin-patch: https://mantis.ilias.de/view.php?id=28866
5249  $PHP_SELF = filter_var($PHP_SELF, FILTER_SANITIZE_STRING);
5250  // end-patch
5251 
5252  $b = '
5253  <html><head><title>NuSOAP: '.$this->serviceName.'</title>
5254  <style type="text/css">
5255  body { font-family: arial; color: #000000; background-color: #ffffff; margin: 0px 0px 0px 0px; }
5256  p { font-family: arial; color: #000000; margin-top: 0px; margin-bottom: 12px; }
5257  pre { background-color: silver; padding: 5px; font-family: Courier New; font-size: x-small; color: #000000;}
5258  ul { margin-top: 10px; margin-left: 20px; }
5259  li { list-style-type: none; margin-top: 10px; color: #000000; }
5260  .content{
5261  margin-left: 0px; padding-bottom: 2em; }
5262  .nav {
5263  padding-top: 10px; padding-bottom: 10px; padding-left: 15px; font-size: .70em;
5264  margin-top: 10px; margin-left: 0px; color: #000000;
5265  background-color: #ccccff; width: 20%; margin-left: 20px; margin-top: 20px; }
5266  .title {
5267  font-family: arial; font-size: 26px; color: #ffffff;
5268  background-color: #999999; width: 105%; margin-left: 0px;
5269  padding-top: 10px; padding-bottom: 10px; padding-left: 15px;}
5270  .hidden {
5271  position: absolute; visibility: hidden; z-index: 200; left: 250px; top: 100px;
5272  font-family: arial; overflow: hidden; width: 600;
5273  padding: 20px; font-size: 10px; background-color: #999999;
5274  layer-background-color:#FFFFFF; }
5275  a,a:active { color: charcoal; font-weight: bold; }
5276  a:visited { color: #666666; font-weight: bold; }
5277  a:hover { color: cc3300; font-weight: bold; }
5278  </style>
5279  <script language="JavaScript" type="text/javascript">
5280  <!--
5281  // POP-UP CAPTIONS...
5282  function lib_bwcheck(){ //Browsercheck (needed)
5283  this.ver=navigator.appVersion
5284  this.agent=navigator.userAgent
5285  this.dom=document.getElementById?1:0
5286  this.opera5=this.agent.indexOf("Opera 5")>-1
5287  this.ie5=(this.ver.indexOf("MSIE 5")>-1 && this.dom && !this.opera5)?1:0;
5288  this.ie6=(this.ver.indexOf("MSIE 6")>-1 && this.dom && !this.opera5)?1:0;
5289  this.ie4=(document.all && !this.dom && !this.opera5)?1:0;
5290  this.ie=this.ie4||this.ie5||this.ie6
5291  this.mac=this.agent.indexOf("Mac")>-1
5292  this.ns6=(this.dom && parseInt(this.ver) >= 5) ?1:0;
5293  this.ns4=(document.layers && !this.dom)?1:0;
5294  this.bw=(this.ie6 || this.ie5 || this.ie4 || this.ns4 || this.ns6 || this.opera5)
5295  return this
5296  }
5297  var bw = new lib_bwcheck()
5298  //Makes crossbrowser object.
5299  function makeObj(obj){
5300  this.evnt=bw.dom? document.getElementById(obj):bw.ie4?document.all[obj]:bw.ns4?document.layers[obj]:0;
5301  if(!this.evnt) return false
5302  this.css=bw.dom||bw.ie4?this.evnt.style:bw.ns4?this.evnt:0;
5303  this.wref=bw.dom||bw.ie4?this.evnt:bw.ns4?this.css.document:0;
5304  this.writeIt=b_writeIt;
5305  return this
5306  }
5307  // A unit of measure that will be added when setting the position of a layer.
5308  //var px = bw.ns4||window.opera?"":"px";
5309  function b_writeIt(text){
5310  if (bw.ns4){this.wref.write(text);this.wref.close()}
5311  else this.wref.innerHTML = text
5312  }
5313  //Shows the messages
5314  var oDesc;
5315  function popup(divid){
5316  if(oDesc = new makeObj(divid)){
5317  oDesc.css.visibility = "visible"
5318  }
5319  }
5320  function popout(){ // Hides message
5321  if(oDesc) oDesc.css.visibility = "hidden"
5322  }
5323  //-->
5324  </script>
5325  </head>
5326  <body>
5327  <div class=content>
5328  <br><br>
5329  <div class=title>'.$this->serviceName.'</div>
5330  <div class=nav>
5331  <p>View the <a href="'.$PHP_SELF.'?wsdl">WSDL</a> for the service.
5332  Click on an operation name to view it&apos;s details.</p>
5333  <ul>';
5334  foreach($this->getOperations() as $op => $data){
5335  // begin-patch: https://mantis.ilias.de/view.php?id=28866
5336  if (isset($data['endpoint'])) {
5337  $data['endpoint'] = filter_var($data['endpoint'], FILTER_SANITIZE_STRING);
5338  }
5339  // end-patch
5340  $b .= "<li><a href='#' onclick=\"popout();popup('$op')\">$op</a></li>";
5341  // create hidden div
5342  $b .= "<div id='$op' class='hidden'>
5343  <a href='#' onclick='popout()'><font color='#ffffff'>Close</font></a><br><br>";
5344  foreach($data as $donnie => $marie){ // loop through opdata
5345  if($donnie == 'input' || $donnie == 'output'){ // show input/output data
5346  $b .= "<font color='white'>".ucfirst($donnie).':</font><br>';
5347  foreach($marie as $captain => $tenille){ // loop through data
5348  if($captain == 'parts'){ // loop thru parts
5349  $b .= "&nbsp;&nbsp;$captain:<br>";
5350  //if(is_array($tenille)){
5351  foreach($tenille as $joanie => $chachi){
5352  $b .= "&nbsp;&nbsp;&nbsp;&nbsp;$joanie: $chachi<br>";
5353  }
5354  //}
5355  } else {
5356  $b .= "&nbsp;&nbsp;$captain: $tenille<br>";
5357  }
5358  }
5359  } else {
5360  $b .= "<font color='white'>".ucfirst($donnie).":</font> $marie<br>";
5361  }
5362  }
5363  $b .= '</div>';
5364  }
5365  $b .= '
5366  <ul>
5367  </div>
5368  </div></body></html>';
5369  return $b;
5370  }
5371 
5379  function serialize($debug = 0)
5380  {
5381  $xml = '<?xml version="1.0" encoding="ISO-8859-1"?>';
5382  $xml .= "\n<definitions";
5383  foreach($this->namespaces as $k => $v) {
5384  $xml .= " xmlns:$k=\"$v\"";
5385  }
5386  // 10.9.02 - add poulter fix for wsdl and tns declarations
5387  if (isset($this->namespaces['wsdl'])) {
5388  $xml .= " xmlns=\"" . $this->namespaces['wsdl'] . "\"";
5389  }
5390  if (isset($this->namespaces['tns'])) {
5391  $xml .= " targetNamespace=\"" . $this->namespaces['tns'] . "\"";
5392  }
5393  $xml .= '>';
5394  // imports
5395  if (sizeof($this->import) > 0) {
5396  foreach($this->import as $ns => $list) {
5397  foreach ($list as $ii) {
5398  if ($ii['location'] != '') {
5399  $xml .= '<import location="' . $ii['location'] . '" namespace="' . $ns . '" />';
5400  } else {
5401  $xml .= '<import namespace="' . $ns . '" />';
5402  }
5403  }
5404  }
5405  }
5406  // types
5407  if (count($this->schemas)>=1) {
5408  $xml .= "\n<types>\n";
5409  foreach ($this->schemas as $ns => $list) {
5410  foreach ($list as $xs) {
5411  $xml .= $xs->serializeSchema();
5412  }
5413  }
5414  $xml .= '</types>';
5415  }
5416  // messages
5417  if (count($this->messages) >= 1) {
5418  foreach($this->messages as $msgName => $msgParts) {
5419  $xml .= "\n<message name=\"" . $msgName . '">';
5420  if(is_array($msgParts)){
5421  foreach($msgParts as $partName => $partType) {
5422  // print 'serializing '.$partType.', sv: '.$this->XMLSchemaVersion.'<br>';
5423  if (strpos($partType, ':')) {
5424  $typePrefix = $this->getPrefixFromNamespace($this->getPrefix($partType));
5425  } elseif (isset($this->typemap[$this->namespaces['xsd']][$partType])) {
5426  // print 'checking typemap: '.$this->XMLSchemaVersion.'<br>';
5427  $typePrefix = 'xsd';
5428  } else {
5429  foreach($this->typemap as $ns => $types) {
5430  if (isset($types[$partType])) {
5431  $typePrefix = $this->getPrefixFromNamespace($ns);
5432  }
5433  }
5434  if (!isset($typePrefix)) {
5435  die("$partType has no namespace!");
5436  }
5437  }
5438  $ns = $this->getNamespaceFromPrefix($typePrefix);
5439  $localPart = $this->getLocalPart($partType);
5440  $typeDef = $this->getTypeDef($localPart, $ns);
5441  if ($typeDef['typeClass'] == 'element') {
5442  $elementortype = 'element';
5443  if (substr($localPart, -1) == '^') {
5444  $localPart = substr($localPart, 0, -1);
5445  }
5446  } else {
5447  $elementortype = 'type';
5448  }
5449  $xml .= "\n" . ' <part name="' . $partName . '" ' . $elementortype . '="' . $typePrefix . ':' . $localPart . '" />';
5450  }
5451  }
5452  $xml .= '</message>';
5453  }
5454  }
5455  // bindings & porttypes
5456  if (count($this->bindings) >= 1) {
5457  $binding_xml = '';
5458  $portType_xml = '';
5459  foreach($this->bindings as $bindingName => $attrs) {
5460  $binding_xml .= "\n<binding name=\"" . $bindingName . '" type="tns:' . $attrs['portType'] . '">';
5461  $binding_xml .= "\n" . ' <soap:binding style="' . $attrs['style'] . '" transport="' . $attrs['transport'] . '"/>';
5462  $portType_xml .= "\n<portType name=\"" . $attrs['portType'] . '">';
5463  foreach($attrs['operations'] as $opName => $opParts) {
5464  $binding_xml .= "\n" . ' <operation name="' . $opName . '">';
5465  $binding_xml .= "\n" . ' <soap:operation soapAction="' . $opParts['soapAction'] . '" style="'. $opParts['style'] . '"/>';
5466  if (isset($opParts['input']['encodingStyle']) && $opParts['input']['encodingStyle'] != '') {
5467  $enc_style = ' encodingStyle="' . $opParts['input']['encodingStyle'] . '"';
5468  } else {
5469  $enc_style = '';
5470  }
5471  $binding_xml .= "\n" . ' <input><soap:body use="' . $opParts['input']['use'] . '" namespace="' . $opParts['input']['namespace'] . '"' . $enc_style . '/></input>';
5472  if (isset($opParts['output']['encodingStyle']) && $opParts['output']['encodingStyle'] != '') {
5473  $enc_style = ' encodingStyle="' . $opParts['output']['encodingStyle'] . '"';
5474  } else {
5475  $enc_style = '';
5476  }
5477  $binding_xml .= "\n" . ' <output><soap:body use="' . $opParts['output']['use'] . '" namespace="' . $opParts['output']['namespace'] . '"' . $enc_style . '/></output>';
5478  $binding_xml .= "\n" . ' </operation>';
5479  $portType_xml .= "\n" . ' <operation name="' . $opParts['name'] . '"';
5480  if (isset($opParts['parameterOrder'])) {
5481  $portType_xml .= ' parameterOrder="' . $opParts['parameterOrder'] . '"';
5482  }
5483  $portType_xml .= '>';
5484  if(isset($opParts['documentation']) && $opParts['documentation'] != '') {
5485  $portType_xml .= "\n" . ' <documentation>' . htmlspecialchars($opParts['documentation']) . '</documentation>';
5486  }
5487  $portType_xml .= "\n" . ' <input message="tns:' . $opParts['input']['message'] . '"/>';
5488  $portType_xml .= "\n" . ' <output message="tns:' . $opParts['output']['message'] . '"/>';
5489  $portType_xml .= "\n" . ' </operation>';
5490  }
5491  $portType_xml .= "\n" . '</portType>';
5492  $binding_xml .= "\n" . '</binding>';
5493  }
5494  $xml .= $portType_xml . $binding_xml;
5495  }
5496  // services
5497  $xml .= "\n<service name=\"" . $this->serviceName . '">';
5498  $has_client = isset($_GET['client_id']);
5499  if (count($this->ports) >= 1) {
5500  foreach($this->ports as $pName => $attrs) {
5501  $xml .= "\n" . ' <port name="' . $pName . '" binding="tns:' . $attrs['binding'] . '">';
5502  $address = $attrs['location'] . ($debug || $has_client ? "?" : "")
5503  . ($debug ? 'debug=1' : '') . ($debug && $has_client ? "&amp;" : "")
5504  . ($has_client ? 'client_id=' . $_GET['client_id'] : '');
5505  $xml .= "\n" . ' <soap:address location="' . $address. '"/>';
5506  $xml .= "\n" . ' </port>';
5507  }
5508  }
5509 
5510  $xml .= "\n" . '</service>';
5511  return $xml . "\n</definitions>";
5512  }
5513 
5523  function parametersMatchWrapped($type, &$parameters) {
5524  $this->debug("in parametersMatchWrapped type=$type, parameters=");
5525  $this->appendDebug($this->varDump($parameters));
5526 
5527  // split type into namespace:unqualified-type
5528  if (strpos($type, ':')) {
5529  $uqType = substr($type, strrpos($type, ':') + 1);
5530  $ns = substr($type, 0, strrpos($type, ':'));
5531  $this->debug("in parametersMatchWrapped: got a prefixed type: $uqType, $ns");
5532  if ($this->getNamespaceFromPrefix($ns)) {
5533  $ns = $this->getNamespaceFromPrefix($ns);
5534  $this->debug("in parametersMatchWrapped: expanded prefixed type: $uqType, $ns");
5535  }
5536  } else {
5537  // TODO: should the type be compared to types in XSD, and the namespace
5538  // set to XSD if the type matches?
5539  $this->debug("in parametersMatchWrapped: No namespace for type $type");
5540  $ns = '';
5541  $uqType = $type;
5542  }
5543 
5544  // get the type information
5545  if (!$typeDef = $this->getTypeDef($uqType, $ns)) {
5546  $this->debug("in parametersMatchWrapped: $type ($uqType) is not a supported type.");
5547  return false;
5548  }
5549  $this->debug("in parametersMatchWrapped: found typeDef=");
5550  $this->appendDebug($this->varDump($typeDef));
5551  if (substr($uqType, -1) == '^') {
5552  $uqType = substr($uqType, 0, -1);
5553  }
5554  $phpType = $typeDef['phpType'];
5555  $arrayType = (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : '');
5556  $this->debug("in parametersMatchWrapped: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: $arrayType");
5557 
5558  // we expect a complexType or element of complexType
5559  if ($phpType != 'struct') {
5560  $this->debug("in parametersMatchWrapped: not a struct");
5561  return false;
5562  }
5563 
5564  // see whether the parameter names match the elements
5565  if (isset($typeDef['elements']) && is_array($typeDef['elements'])) {
5566  $elements = 0;
5567  $matches = 0;
5568  $change = false;
5569  if ($this->isArraySimpleOrStruct($parameters) == 'arraySimple' && count($parameters) == count($typeDef['elements'])) {
5570  $this->debug("in parametersMatchWrapped: (wrapped return value kludge) correct number of elements in simple array, so change array and wrap");
5571  $change = true;
5572  }
5573  foreach ($typeDef['elements'] as $name => $attrs) {
5574  if ($change) {
5575  $this->debug("in parametersMatchWrapped: change parameter $element to name $name");
5576  $parameters[$name] = $parameters[$elements];
5577  unset($parameters[$elements]);
5578  $matches++;
5579  } elseif (isset($parameters[$name])) {
5580  $this->debug("in parametersMatchWrapped: have parameter named $name");
5581  $matches++;
5582  } else {
5583  $this->debug("in parametersMatchWrapped: do not have parameter named $name");
5584  }
5585  $elements++;
5586  }
5587 
5588  $this->debug("in parametersMatchWrapped: $matches parameter names match $elements wrapped parameter names");
5589  if ($matches == 0) {
5590  return false;
5591  }
5592  return true;
5593  }
5594 
5595  // since there are no elements for the type, if the user passed no
5596  // parameters, the parameters match wrapped.
5597  $this->debug("in parametersMatchWrapped: no elements type $ns:$uqType");
5598  return count($parameters) == 0;
5599  }
5600 
5616  function serializeRPCParameters($operation, $direction, $parameters, $bindingType = 'soap') {
5617  $this->debug("in serializeRPCParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion, bindingType=$bindingType");
5618  $this->appendDebug('parameters=' . $this->varDump($parameters));
5619 
5620  if ($direction != 'input' && $direction != 'output') {
5621  $this->debug('The value of the \$direction argument needs to be either "input" or "output"');
5622  $this->setError('The value of the \$direction argument needs to be either "input" or "output"');
5623  return false;
5624  }
5625  if (!$opData = $this->getOperationData($operation, $bindingType)) {
5626  $this->debug('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType);
5627  $this->setError('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType);
5628  return false;
5629  }
5630  $this->debug('in serializeRPCParameters: opData:');
5631  $this->appendDebug($this->varDump($opData));
5632 
5633  // Get encoding style for output and set to current
5634  $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
5635  if(($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {
5636  $encodingStyle = $opData['output']['encodingStyle'];
5637  $enc_style = $encodingStyle;
5638  }
5639 
5640  // set input params
5641  $xml = '';
5642  if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) {
5643  $parts = &$opData[$direction]['parts'];
5644  $part_count = sizeof($parts);
5645  $style = $opData['style'];
5646  $use = $opData[$direction]['use'];
5647  $this->debug("have $part_count part(s) to serialize using $style/$use");
5648  if (is_array($parameters)) {
5649  $parametersArrayType = $this->isArraySimpleOrStruct($parameters);
5650  $parameter_count = count($parameters);
5651  $this->debug("have $parameter_count parameter(s) provided as $parametersArrayType to serialize");
5652  // check for Microsoft-style wrapped parameters
5653  if ($style == 'document' && $use == 'literal' && $part_count == 1 && isset($parts['parameters'])) {
5654  $this->debug('check whether the caller has wrapped the parameters');
5655  if ((($parametersArrayType == 'arrayStruct' || $parameter_count == 0) && !isset($parameters['parameters'])) || ($direction == 'output' && $parametersArrayType == 'arraySimple' && $parameter_count == 1)) {
5656  $this->debug('check whether caller\'s parameters match the wrapped ones');
5657  if ($this->parametersMatchWrapped($parts['parameters'], $parameters)) {
5658  $this->debug('wrap the parameters for the caller');
5659  $parameters = array('parameters' => $parameters);
5660  $parameter_count = 1;
5661  }
5662  }
5663  }
5664  foreach ($parts as $name => $type) {
5665  $this->debug("serializing part $name of type $type");
5666  // Track encoding style
5667  if (isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {
5668  $encodingStyle = $opData[$direction]['encodingStyle'];
5669  $enc_style = $encodingStyle;
5670  } else {
5671  $enc_style = false;
5672  }
5673  // NOTE: add error handling here
5674  // if serializeType returns false, then catch global error and fault
5675  if ($parametersArrayType == 'arraySimple') {
5676  $p = array_shift($parameters);
5677  $this->debug('calling serializeType w/indexed param');
5678  $xml .= $this->serializeType($name, $type, $p, $use, $enc_style);
5679  } elseif (isset($parameters[$name])) {
5680  $this->debug('calling serializeType w/named param');
5681  $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style);
5682  } else {
5683  // TODO: only send nillable
5684  $this->debug('calling serializeType w/null param');
5685  $xml .= $this->serializeType($name, $type, null, $use, $enc_style);
5686  }
5687  }
5688  } else {
5689  $this->debug('no parameters passed.');
5690  }
5691  }
5692  $this->debug("serializeRPCParameters returning: $xml");
5693  return $xml;
5694  }
5695 
5710  function serializeParameters($operation, $direction, $parameters)
5711  {
5712  $this->debug("in serializeParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion");
5713  $this->appendDebug('parameters=' . $this->varDump($parameters));
5714 
5715  if ($direction != 'input' && $direction != 'output') {
5716  $this->debug('The value of the \$direction argument needs to be either "input" or "output"');
5717  $this->setError('The value of the \$direction argument needs to be either "input" or "output"');
5718  return false;
5719  }
5720  if (!$opData = $this->getOperationData($operation)) {
5721  $this->debug('Unable to retrieve WSDL data for operation: ' . $operation);
5722  $this->setError('Unable to retrieve WSDL data for operation: ' . $operation);
5723  return false;
5724  }
5725  $this->debug('opData:');
5726  $this->appendDebug($this->varDump($opData));
5727 
5728  // Get encoding style for output and set to current
5729  $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
5730  if(($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {
5731  $encodingStyle = $opData['output']['encodingStyle'];
5732  $enc_style = $encodingStyle;
5733  }
5734 
5735  // set input params
5736  $xml = '';
5737  if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) {
5738 
5739  $use = $opData[$direction]['use'];
5740  $this->debug("use=$use");
5741  $this->debug('got ' . count($opData[$direction]['parts']) . ' part(s)');
5742  if (is_array($parameters)) {
5743  $parametersArrayType = $this->isArraySimpleOrStruct($parameters);
5744  $this->debug('have ' . $parametersArrayType . ' parameters');
5745  foreach($opData[$direction]['parts'] as $name => $type) {
5746  $this->debug('serializing part "'.$name.'" of type "'.$type.'"');
5747  // Track encoding style
5748  if(isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {
5749  $encodingStyle = $opData[$direction]['encodingStyle'];
5750  $enc_style = $encodingStyle;
5751  } else {
5752  $enc_style = false;
5753  }
5754  // NOTE: add error handling here
5755  // if serializeType returns false, then catch global error and fault
5756  if ($parametersArrayType == 'arraySimple') {
5757  $p = array_shift($parameters);
5758  $this->debug('calling serializeType w/indexed param');
5759  $xml .= $this->serializeType($name, $type, $p, $use, $enc_style);
5760  } elseif (isset($parameters[$name])) {
5761  $this->debug('calling serializeType w/named param');
5762  $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style);
5763  } else {
5764  // TODO: only send nillable
5765  $this->debug('calling serializeType w/null param');
5766  $xml .= $this->serializeType($name, $type, null, $use, $enc_style);
5767  }
5768  }
5769  } else {
5770  $this->debug('no parameters passed.');
5771  }
5772  }
5773  $this->debug("serializeParameters returning: $xml");
5774  return $xml;
5775  }
5776 
5789  function serializeType($name, $type, $value, $use='encoded', $encodingStyle=false, $unqualified=false)
5790  {
5791  $this->debug("in serializeType: name=$name, type=$type, use=$use, encodingStyle=$encodingStyle, unqualified=" . ($unqualified ? "unqualified" : "qualified"));
5792  $this->appendDebug("value=" . $this->varDump($value));
5793  if($use == 'encoded' && $encodingStyle) {
5794  $encodingStyle = ' SOAP-ENV:encodingStyle="' . $encodingStyle . '"';
5795  }
5796 
5797  // if a soapval has been supplied, let its type override the WSDL
5798  if (is_object($value) && get_class($value) == 'soapval') {
5799  if ($value->type_ns) {
5800  $type = $value->type_ns . ':' . $value->type;
5801  $forceType = true;
5802  $this->debug("in serializeType: soapval overrides type to $type");
5803  } elseif ($value->type) {
5804  $type = $value->type;
5805  $forceType = true;
5806  $this->debug("in serializeType: soapval overrides type to $type");
5807  } else {
5808  $forceType = false;
5809  $this->debug("in serializeType: soapval does not override type");
5810  }
5811  $attrs = $value->attributes;
5812  $value = $value->value;
5813  $this->debug("in serializeType: soapval overrides value to $value");
5814  if ($attrs) {
5815  if (!is_array($value)) {
5816  $value['!'] = $value;
5817  }
5818  foreach ($attrs as $n => $v) {
5819  $value['!' . $n] = $v;
5820  }
5821  $this->debug("in serializeType: soapval provides attributes");
5822  }
5823  } else {
5824  $forceType = false;
5825  }
5826 
5827  $xml = '';
5828  if (strpos($type, ':')) {
5829  $uqType = substr($type, strrpos($type, ':') + 1);
5830  $ns = substr($type, 0, strrpos($type, ':'));
5831  $this->debug("in serializeType: got a prefixed type: $uqType, $ns");
5832  if ($this->getNamespaceFromPrefix($ns)) {
5833  $ns = $this->getNamespaceFromPrefix($ns);
5834  $this->debug("in serializeType: expanded prefixed type: $uqType, $ns");
5835  }
5836 
5837  if($ns == $this->XMLSchemaVersion || $ns == 'http://schemas.xmlsoap.org/soap/encoding/'){
5838  $this->debug('in serializeType: type namespace indicates XML Schema or SOAP Encoding type');
5839  if ($unqualified && $use == 'literal') {
5840  $elementNS = " xmlns=\"\"";
5841  } else {
5842  $elementNS = '';
5843  }
5844  if (is_null($value)) {
5845  if ($use == 'literal') {
5846  // TODO: depends on minOccurs
5847  $xml = "<$name$elementNS/>";
5848  } else {
5849  // TODO: depends on nillable, which should be checked before calling this method
5850  $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>";
5851  }
5852  $this->debug("in serializeType: returning: $xml");
5853  return $xml;
5854  }
5855  if ($uqType == 'Array') {
5856  // JBoss/Axis does this sometimes
5857  return $this->serialize_val($value, $name, false, false, false, false, $use);
5858  }
5859  if ($uqType == 'boolean') {
5860  if ((is_string($value) && $value == 'false') || (! $value)) {
5861  $value = 'false';
5862  } else {
5863  $value = 'true';
5864  }
5865  }
5866  if ($uqType == 'string' && gettype($value) == 'string') {
5867  $value = $this->expandEntities($value);
5868  }
5869  if (($uqType == 'long' || $uqType == 'unsignedLong') && gettype($value) == 'double') {
5870  $value = sprintf("%.0lf", $value);
5871  }
5872  // it's a scalar
5873  // TODO: what about null/nil values?
5874  // check type isn't a custom type extending xmlschema namespace
5875  if (!$this->getTypeDef($uqType, $ns)) {
5876  if ($use == 'literal') {
5877  if ($forceType) {
5878  $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>";
5879  } else {
5880  $xml = "<$name$elementNS>$value</$name>";
5881  }
5882  } else {
5883  $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>";
5884  }
5885  $this->debug("in serializeType: returning: $xml");
5886  return $xml;
5887  }
5888  $this->debug('custom type extends XML Schema or SOAP Encoding namespace (yuck)');
5889  } else if ($ns == 'http://xml.apache.org/xml-soap') {
5890  $this->debug('in serializeType: appears to be Apache SOAP type');
5891  if ($uqType == 'Map') {
5892  $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap');
5893  if (! $tt_prefix) {
5894  $this->debug('in serializeType: Add namespace for Apache SOAP type');
5895  $tt_prefix = 'ns' . rand(1000, 9999);
5896  $this->namespaces[$tt_prefix] = 'http://xml.apache.org/xml-soap';
5897  // force this to be added to usedNamespaces
5898  $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap');
5899  }
5900  $contents = '';
5901  foreach($value as $k => $v) {
5902  $this->debug("serializing map element: key $k, value $v");
5903  $contents .= '<item>';
5904  $contents .= $this->serialize_val($k,'key',false,false,false,false,$use);
5905  $contents .= $this->serialize_val($v,'value',false,false,false,false,$use);
5906  $contents .= '</item>';
5907  }
5908  if ($use == 'literal') {
5909  if ($forceType) {
5910  $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\">$contents</$name>";
5911  } else {
5912  $xml = "<$name>$contents</$name>";
5913  }
5914  } else {
5915  $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\"$encodingStyle>$contents</$name>";
5916  }
5917  $this->debug("in serializeType: returning: $xml");
5918  return $xml;
5919  }
5920  $this->debug('in serializeType: Apache SOAP type, but only support Map');
5921  }
5922  } else {
5923  // TODO: should the type be compared to types in XSD, and the namespace
5924  // set to XSD if the type matches?
5925  $this->debug("in serializeType: No namespace for type $type");
5926  $ns = '';
5927  $uqType = $type;
5928  }
5929  if(!$typeDef = $this->getTypeDef($uqType, $ns)){
5930  $this->setError("$type ($uqType) is not a supported type.");
5931  $this->debug("in serializeType: $type ($uqType) is not a supported type.");
5932  return false;
5933  } else {
5934  $this->debug("in serializeType: found typeDef");
5935  $this->appendDebug('typeDef=' . $this->varDump($typeDef));
5936  if (substr($uqType, -1) == '^') {
5937  $uqType = substr($uqType, 0, -1);
5938  }
5939  }
5940  $phpType = $typeDef['phpType'];
5941  $this->debug("in serializeType: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: " . (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : '') );
5942  // if php type == struct, map value to the <all> element names
5943  if ($phpType == 'struct') {
5944  if (isset($typeDef['typeClass']) && $typeDef['typeClass'] == 'element') {
5945  $elementName = $uqType;
5946  if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
5947  $elementNS = " xmlns=\"$ns\"";
5948  } else {
5949  $elementNS = " xmlns=\"\"";
5950  }
5951  } else {
5952  $elementName = $name;
5953  if ($unqualified) {
5954  $elementNS = " xmlns=\"\"";
5955  } else {
5956  $elementNS = '';
5957  }
5958  }
5959  if (is_null($value)) {
5960  if ($use == 'literal') {
5961  // TODO: depends on minOccurs
5962  $xml = "<$elementName$elementNS/>";
5963  } else {
5964  $xml = "<$elementName$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>";
5965  }
5966  $this->debug("in serializeType: returning: $xml");
5967  return $xml;
5968  }
5969  if (is_object($value)) {
5970  $value = get_object_vars($value);
5971  }
5972  if (is_array($value)) {
5973  $elementAttrs = $this->serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType);
5974  if ($use == 'literal') {
5975  if ($forceType) {
5976  $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">";
5977  } else {
5978  $xml = "<$elementName$elementNS$elementAttrs>";
5979  }
5980  } else {
5981  $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>";
5982  }
5983 
5984  $xml .= $this->serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use, $encodingStyle);
5985  $xml .= "</$elementName>";
5986  } else {
5987  $this->debug("in serializeType: phpType is struct, but value is not an array");
5988  $this->setError("phpType is struct, but value is not an array: see debug output for details");
5989  $xml = '';
5990  }
5991  } elseif ($phpType == 'array') {
5992  if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
5993  $elementNS = " xmlns=\"$ns\"";
5994  } else {
5995  if ($unqualified) {
5996  $elementNS = " xmlns=\"\"";
5997  } else {
5998  $elementNS = '';
5999  }
6000  }
6001  if (is_null($value)) {
6002  if ($use == 'literal') {
6003  // TODO: depends on minOccurs
6004  $xml = "<$name$elementNS/>";
6005  } else {
6006  $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" .
6007  $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') .
6008  ":Array\" " .
6009  $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') .
6010  ':arrayType="' .
6011  $this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType'])) .
6012  ':' .
6013  $this->getLocalPart($typeDef['arrayType'])."[0]\"/>";
6014  }
6015  $this->debug("in serializeType: returning: $xml");
6016  return $xml;
6017  }
6018  if (isset($typeDef['multidimensional'])) {
6019  $nv = array();
6020  foreach($value as $v) {
6021  $cols = ',' . sizeof($v);
6022  $nv = array_merge($nv, $v);
6023  }
6024  $value = $nv;
6025  } else {
6026  $cols = '';
6027  }
6028  if (is_array($value) && sizeof($value) >= 1) {
6029  $rows = sizeof($value);
6030  $contents = '';
6031  foreach($value as $k => $v) {
6032  $this->debug("serializing array element: $k, $v of type: $typeDef[arrayType]");
6033  //if (strpos($typeDef['arrayType'], ':') ) {
6034  if (!in_array($typeDef['arrayType'],$this->typemap['http://www.w3.org/2001/XMLSchema'])) {
6035  $contents .= $this->serializeType('item', $typeDef['arrayType'], $v, $use);
6036  } else {
6037  $contents .= $this->serialize_val($v, 'item', $typeDef['arrayType'], null, $this->XMLSchemaVersion, false, $use);
6038  }
6039  }
6040  } else {
6041  $rows = 0;
6042  $contents = null;
6043  }
6044  // TODO: for now, an empty value will be serialized as a zero element
6045  // array. Revisit this when coding the handling of null/nil values.
6046  if ($use == 'literal') {
6047  $xml = "<$name$elementNS>"
6048  .$contents
6049  ."</$name>";
6050  } else {
6051  $xml = "<$name$elementNS xsi:type=\"".$this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/').':Array" '.
6052  $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/')
6053  .':arrayType="'
6054  .$this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType']))
6055  .":".$this->getLocalPart($typeDef['arrayType'])."[$rows$cols]\">"
6056  .$contents
6057  ."</$name>";
6058  }
6059  } elseif ($phpType == 'scalar') {
6060  if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
6061  $elementNS = " xmlns=\"$ns\"";
6062  } else {
6063  if ($unqualified) {
6064  $elementNS = " xmlns=\"\"";
6065  } else {
6066  $elementNS = '';
6067  }
6068  }
6069  if ($use == 'literal') {
6070  if ($forceType) {
6071  $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>";
6072  } else {
6073  $xml = "<$name$elementNS>$value</$name>";
6074  }
6075  } else {
6076  $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>";
6077  }
6078  }
6079  $this->debug("in serializeType: returning: $xml");
6080  return $xml;
6081  }
6082 
6093  function serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType) {
6094  $xml = '';
6095  if (isset($typeDef['attrs']) && is_array($typeDef['attrs'])) {
6096  $this->debug("serialize attributes for XML Schema type $ns:$uqType");
6097  if (is_array($value)) {
6098  $xvalue = $value;
6099  } elseif (is_object($value)) {
6100  $xvalue = get_object_vars($value);
6101  } else {
6102  $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType");
6103  $xvalue = array();
6104  }
6105  foreach ($typeDef['attrs'] as $aName => $attrs) {
6106  if (isset($xvalue['!' . $aName])) {
6107  $xname = '!' . $aName;
6108  $this->debug("value provided for attribute $aName with key $xname");
6109  } elseif (isset($xvalue[$aName])) {
6110  $xname = $aName;
6111  $this->debug("value provided for attribute $aName with key $xname");
6112  } elseif (isset($attrs['default'])) {
6113  $xname = '!' . $aName;
6114  $xvalue[$xname] = $attrs['default'];
6115  $this->debug('use default value of ' . $xvalue[$aName] . ' for attribute ' . $aName);
6116  } else {
6117  $xname = '';
6118  $this->debug("no value provided for attribute $aName");
6119  }
6120  if ($xname) {
6121  $xml .= " $aName=\"" . $this->expandEntities($xvalue[$xname]) . "\"";
6122  }
6123  }
6124  } else {
6125  $this->debug("no attributes to serialize for XML Schema type $ns:$uqType");
6126  }
6127  if (isset($typeDef['extensionBase'])) {
6128  $ns = $this->getPrefix($typeDef['extensionBase']);
6129  $uqType = $this->getLocalPart($typeDef['extensionBase']);
6130  if ($this->getNamespaceFromPrefix($ns)) {
6131  $ns = $this->getNamespaceFromPrefix($ns);
6132  }
6133  if ($typeDef = $this->getTypeDef($uqType, $ns)) {
6134  $this->debug("serialize attributes for extension base $ns:$uqType");
6135  $xml .= $this->serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType);
6136  } else {
6137  $this->debug("extension base $ns:$uqType is not a supported type");
6138  }
6139  }
6140  return $xml;
6141  }
6142 
6155  function serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use='encoded', $encodingStyle=false) {
6156  $xml = '';
6157  if (isset($typeDef['elements']) && is_array($typeDef['elements'])) {
6158  $this->debug("in serializeComplexTypeElements, serialize elements for XML Schema type $ns:$uqType");
6159  if (is_array($value)) {
6160  $xvalue = $value;
6161  } elseif (is_object($value)) {
6162  $xvalue = get_object_vars($value);
6163  } else {
6164  $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType");
6165  $xvalue = array();
6166  }
6167  // toggle whether all elements are present - ideally should validate against schema
6168  if (count($typeDef['elements']) != count($xvalue)){
6169  $optionals = true;
6170  }
6171  foreach ($typeDef['elements'] as $eName => $attrs) {
6172  if (!isset($xvalue[$eName])) {
6173  if (isset($attrs['default'])) {
6174  $xvalue[$eName] = $attrs['default'];
6175  $this->debug('use default value of ' . $xvalue[$eName] . ' for element ' . $eName);
6176  }
6177  }
6178  // if user took advantage of a minOccurs=0, then only serialize named parameters
6179  if (isset($optionals)
6180  && (!isset($xvalue[$eName]))
6181  && ( (!isset($attrs['nillable'])) || $attrs['nillable'] != 'true')
6182  ){
6183  if (isset($attrs['minOccurs']) && $attrs['minOccurs'] <> '0') {
6184  $this->debug("apparent error: no value provided for element $eName with minOccurs=" . $attrs['minOccurs']);
6185  }
6186  // do nothing
6187  $this->debug("no value provided for complexType element $eName and element is not nillable, so serialize nothing");
6188  } else {
6189  // get value
6190  if (isset($xvalue[$eName])) {
6191  $v = $xvalue[$eName];
6192  } else {
6193  $v = null;
6194  }
6195  if (isset($attrs['form'])) {
6196  $unqualified = ($attrs['form'] == 'unqualified');
6197  } else {
6198  $unqualified = false;
6199  }
6200  if (isset($attrs['maxOccurs']) && ($attrs['maxOccurs'] == 'unbounded' || $attrs['maxOccurs'] > 1) && isset($v) && is_array($v) && $this->isArraySimpleOrStruct($v) == 'arraySimple') {
6201  $vv = $v;
6202  foreach ($vv as $k => $v) {
6203  if (isset($attrs['type']) || isset($attrs['ref'])) {
6204  // serialize schema-defined type
6205  $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
6206  } else {
6207  // serialize generic type (can this ever really happen?)
6208  $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use");
6209  $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use);
6210  }
6211  }
6212  } else {
6213  if (isset($attrs['type']) || isset($attrs['ref'])) {
6214  // serialize schema-defined type
6215  $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
6216  } else {
6217  // serialize generic type (can this ever really happen?)
6218  $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use");
6219  $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use);
6220  }
6221  }
6222  }
6223  }
6224  } else {
6225  $this->debug("no elements to serialize for XML Schema type $ns:$uqType");
6226  }
6227  if (isset($typeDef['extensionBase'])) {
6228  $ns = $this->getPrefix($typeDef['extensionBase']);
6229  $uqType = $this->getLocalPart($typeDef['extensionBase']);
6230  if ($this->getNamespaceFromPrefix($ns)) {
6231  $ns = $this->getNamespaceFromPrefix($ns);
6232  }
6233  if ($typeDef = $this->getTypeDef($uqType, $ns)) {
6234  $this->debug("serialize elements for extension base $ns:$uqType");
6235  $xml .= $this->serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use, $encodingStyle);
6236  } else {
6237  $this->debug("extension base $ns:$uqType is not a supported type");
6238  }
6239  }
6240  return $xml;
6241  }
6242 
6257  function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType='') {
6258  if (count($elements) > 0) {
6259  $eElements = array();
6260  foreach($elements as $n => $e){
6261  // expand each element
6262  $ee = array();
6263  foreach ($e as $k => $v) {
6264  $k = strpos($k,':') ? $this->expandQname($k) : $k;
6265  $v = strpos($v,':') ? $this->expandQname($v) : $v;
6266  $ee[$k] = $v;
6267  }
6268  $eElements[$n] = $ee;
6269  }
6270  $elements = $eElements;
6271  }
6272 
6273  if (count($attrs) > 0) {
6274  foreach($attrs as $n => $a){
6275  // expand each attribute
6276  foreach ($a as $k => $v) {
6277  $k = strpos($k,':') ? $this->expandQname($k) : $k;
6278  $v = strpos($v,':') ? $this->expandQname($v) : $v;
6279  $aa[$k] = $v;
6280  }
6281  $eAttrs[$n] = $aa;
6282  }
6283  $attrs = $eAttrs;
6284  }
6285 
6286  $restrictionBase = strpos($restrictionBase,':') ? $this->expandQname($restrictionBase) : $restrictionBase;
6287  $arrayType = strpos($arrayType,':') ? $this->expandQname($arrayType) : $arrayType;
6288 
6289  $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
6290  $this->schemas[$typens][0]->addComplexType($name,$typeClass,$phpType,$compositor,$restrictionBase,$elements,$attrs,$arrayType);
6291  }
6292 
6304  function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) {
6305  $restrictionBase = strpos($restrictionBase,':') ? $this->expandQname($restrictionBase) : $restrictionBase;
6306 
6307  $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
6308  $this->schemas[$typens][0]->addSimpleType($name, $restrictionBase, $typeClass, $phpType, $enumeration);
6309  }
6310 
6318  function addElement($attrs) {
6319  $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
6320  $this->schemas[$typens][0]->addElement($attrs);
6321  }
6322 
6337  function addOperation($name, $in = false, $out = false, $namespace = false, $soapaction = false, $style = 'rpc', $use = 'encoded', $documentation = '', $encodingStyle = ''){
6338  if ($use == 'encoded' && $encodingStyle == '') {
6339  $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
6340  }
6341 
6342  if ($style == 'document') {
6343  $elements = array();
6344  foreach ($in as $n => $t) {
6345  $elements[$n] = array('name' => $n, 'type' => $t);
6346  }
6347  $this->addComplexType($name . 'RequestType', 'complexType', 'struct', 'all', '', $elements);
6348  $this->addElement(array('name' => $name, 'type' => $name . 'RequestType'));
6349  $in = array('parameters' => 'tns:' . $name . '^');
6350 
6351  $elements = array();
6352  foreach ($out as $n => $t) {
6353  $elements[$n] = array('name' => $n, 'type' => $t);
6354  }
6355  $this->addComplexType($name . 'ResponseType', 'complexType', 'struct', 'all', '', $elements);
6356  $this->addElement(array('name' => $name . 'Response', 'type' => $name . 'ResponseType', 'form' => 'qualified'));
6357  $out = array('parameters' => 'tns:' . $name . 'Response' . '^');
6358  }
6359 
6360  // get binding
6361  $this->bindings[ $this->serviceName . 'Binding' ]['operations'][$name] =
6362  array(
6363  'name' => $name,
6364  'binding' => $this->serviceName . 'Binding',
6365  'endpoint' => $this->endpoint,
6366  'soapAction' => $soapaction,
6367  'style' => $style,
6368  'input' => array(
6369  'use' => $use,
6370  'namespace' => $namespace,
6371  'encodingStyle' => $encodingStyle,
6372  'message' => $name . 'Request',
6373  'parts' => $in),
6374  'output' => array(
6375  'use' => $use,
6376  'namespace' => $namespace,
6377  'encodingStyle' => $encodingStyle,
6378  'message' => $name . 'Response',
6379  'parts' => $out),
6380  'namespace' => $namespace,
6381  'transport' => 'http://schemas.xmlsoap.org/soap/http',
6382  'documentation' => $documentation);
6383  // add portTypes
6384  // add messages
6385  if($in)
6386  {
6387  foreach($in as $pName => $pType)
6388  {
6389  if(strpos($pType,':')) {
6390  $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)).":".$this->getLocalPart($pType);
6391  }
6392  $this->messages[$name.'Request'][$pName] = $pType;
6393  }
6394  } else {
6395  $this->messages[$name.'Request']= '0';
6396  }
6397  if($out)
6398  {
6399  foreach($out as $pName => $pType)
6400  {
6401  if(strpos($pType,':')) {
6402  $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)).":".$this->getLocalPart($pType);
6403  }
6404  $this->messages[$name.'Response'][$pName] = $pType;
6405  }
6406  } else {
6407  $this->messages[$name.'Response']= '0';
6408  }
6409  return true;
6410  }
6411 }
6412 ?><?php
6413 
6414 
6415 
6425 class nusoap_parser extends nusoap_base {
6426 
6427  var $xml = '';
6428  var $xml_encoding = '';
6429  var $method = '';
6430  var $root_struct = '';
6431  var $root_struct_name = '';
6432  var $root_struct_namespace = '';
6433  var $root_header = '';
6434  var $document = ''; // incoming SOAP body (text)
6435  // determines where in the message we are (envelope,header,body,method)
6436  var $status = '';
6437  var $position = 0;
6438  var $depth = 0;
6439  var $default_namespace = '';
6440  var $namespaces = array();
6441  var $message = array();
6442  var $parent = '';
6443  var $fault = false;
6444  var $fault_code = '';
6445  var $fault_str = '';
6446  var $fault_detail = '';
6447  var $depth_array = array();
6448  var $debug_flag = true;
6449  var $soapresponse = NULL; // parsed SOAP Body
6450  var $soapheader = NULL; // parsed SOAP Header
6451  var $responseHeaders = ''; // incoming SOAP headers (text)
6452  var $body_position = 0;
6453  // for multiref parsing:
6454  // array of id => pos
6455  var $ids = array();
6456  // array of id => hrefs => pos
6457  var $multirefs = array();
6458  // toggle for auto-decoding element content
6459  var $decode_utf8 = true;
6460 
6470  function __construct($xml,$encoding='UTF-8',$method='',$decode_utf8=true){
6471  parent::__construct();
6472  $this->xml = $xml;
6473  $this->xml_encoding = $encoding;
6474  $this->method = $method;
6475  $this->decode_utf8 = $decode_utf8;
6476 
6477  // Check whether content has been read.
6478  if(!empty($xml)){
6479  // Check XML encoding
6480  $pos_xml = strpos($xml, '<?xml');
6481  if ($pos_xml !== FALSE) {
6482  $xml_decl = substr($xml, $pos_xml, strpos($xml, '?>', $pos_xml + 2) - $pos_xml + 1);
6483  if (preg_match("/encoding=[\"']([^\"']*)[\"']/", $xml_decl, $res)) {
6484  $xml_encoding = $res[1];
6485  if (strtoupper($xml_encoding) != $encoding) {
6486  $err = "Charset from HTTP Content-Type '" . $encoding . "' does not match encoding from XML declaration '" . $xml_encoding . "'";
6487  $this->debug($err);
6488  if ($encoding != 'ISO-8859-1' || strtoupper($xml_encoding) != 'UTF-8') {
6489  $this->setError($err);
6490  return;
6491  }
6492  // when HTTP says ISO-8859-1 (the default) and XML says UTF-8 (the typical), assume the other endpoint is just sloppy and proceed
6493  } else {
6494  $this->debug('Charset from HTTP Content-Type matches encoding from XML declaration');
6495  }
6496  } else {
6497  $this->debug('No encoding specified in XML declaration');
6498  }
6499  } else {
6500  $this->debug('No XML declaration');
6501  }
6502  $this->debug('Entering nusoap_parser(), length='.strlen($xml).', encoding='.$encoding);
6503  // Create an XML parser - why not xml_parser_create_ns?
6504  $this->parser = xml_parser_create($this->xml_encoding);
6505  // Set the options for parsing the XML data.
6506  //xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
6507  xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
6508  xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, $this->xml_encoding);
6509  // Set the object for the parser.
6510  xml_set_object($this->parser, $this);
6511  // Set the element handlers for the parser.
6512  xml_set_element_handler($this->parser, 'start_element','end_element');
6513  xml_set_character_data_handler($this->parser,'character_data');
6514 
6515  // Parse the XML file.
6516  if(!xml_parse($this->parser,$xml,true)){
6517  // Display an error message.
6518  $err = sprintf('XML error parsing SOAP payload on line %d: %s',
6519  xml_get_current_line_number($this->parser),
6520  xml_error_string(xml_get_error_code($this->parser)));
6521  $this->debug($err);
6522  $this->debug("XML payload:\n" . $xml);
6523  $this->setError($err);
6524  } else {
6525  $this->debug('parsed successfully, found root struct: '.$this->root_struct.' of name '.$this->root_struct_name);
6526  // get final value
6527  $this->soapresponse = $this->message[$this->root_struct]['result'];
6528  // get header value
6529  if($this->root_header != '' && isset($this->message[$this->root_header]['result'])){
6530  $this->soapheader = $this->message[$this->root_header]['result'];
6531  }
6532  // resolve hrefs/ids
6533  if(sizeof($this->multirefs) > 0){
6534  foreach($this->multirefs as $id => $hrefs){
6535  $this->debug('resolving multirefs for id: '.$id);
6536  $idVal = $this->buildVal($this->ids[$id]);
6537  if (is_array($idVal) && isset($idVal['!id'])) {
6538  unset($idVal['!id']);
6539  }
6540  foreach($hrefs as $refPos => $ref){
6541  $this->debug('resolving href at pos '.$refPos);
6542  $this->multirefs[$id][$refPos] = $idVal;
6543  }
6544  }
6545  }
6546  }
6547  xml_parser_free($this->parser);
6548  } else {
6549  $this->debug('xml was empty, didn\'t parse!');
6550  $this->setError('xml was empty, didn\'t parse!');
6551  }
6552  }
6553 
6562  function start_element($parser, $name, $attrs) {
6563  // position in a total number of elements, starting from 0
6564  // update class level pos
6565  $pos = $this->position++;
6566  // and set mine
6567  $this->message[$pos] = array('pos' => $pos,'children'=>'','cdata'=>'');
6568  // depth = how many levels removed from root?
6569  // set mine as current global depth and increment global depth value
6570  $this->message[$pos]['depth'] = $this->depth++;
6571 
6572  // else add self as child to whoever the current parent is
6573  if($pos != 0){
6574  $this->message[$this->parent]['children'] .= '|'.$pos;
6575  }
6576  // set my parent
6577  $this->message[$pos]['parent'] = $this->parent;
6578  // set self as current parent
6579  $this->parent = $pos;
6580  // set self as current value for this depth
6581  $this->depth_array[$this->depth] = $pos;
6582  // get element prefix
6583  if(strpos($name,':')){
6584  // get ns prefix
6585  $prefix = substr($name,0,strpos($name,':'));
6586  // get unqualified name
6587  $name = substr(strstr($name,':'),1);
6588  }
6589  // set status
6590  if($name == 'Envelope'){
6591  $this->status = 'envelope';
6592  } elseif($name == 'Header' && $this->status = 'envelope'){
6593  $this->root_header = $pos;
6594  $this->status = 'header';
6595  } elseif($name == 'Body' && $this->status = 'envelope'){
6596  $this->status = 'body';
6597  $this->body_position = $pos;
6598  // set method
6599  } elseif($this->status == 'body' && $pos == ($this->body_position+1)){
6600  $this->status = 'method';
6601  $this->root_struct_name = $name;
6602  $this->root_struct = $pos;
6603  $this->message[$pos]['type'] = 'struct';
6604  $this->debug("found root struct $this->root_struct_name, pos $this->root_struct");
6605  }
6606  // set my status
6607  $this->message[$pos]['status'] = $this->status;
6608  // set name
6609  $this->message[$pos]['name'] = htmlspecialchars($name);
6610  // set attrs
6611  $this->message[$pos]['attrs'] = $attrs;
6612 
6613  // loop through atts, logging ns and type declarations
6614  $attstr = '';
6615  foreach($attrs as $key => $value){
6616  $key_prefix = $this->getPrefix($key);
6617  $key_localpart = $this->getLocalPart($key);
6618  // if ns declarations, add to class level array of valid namespaces
6619  if($key_prefix == 'xmlns'){
6620  if(preg_match('/^http:\/\/www.w3.org\/[0-9]{4}\/XMLSchema$/',$value)){
6621  $this->XMLSchemaVersion = $value;
6622  $this->namespaces['xsd'] = $this->XMLSchemaVersion;
6623  $this->namespaces['xsi'] = $this->XMLSchemaVersion.'-instance';
6624  }
6625  $this->namespaces[$key_localpart] = $value;
6626  // set method namespace
6627  if($name == $this->root_struct_name){
6628  $this->methodNamespace = $value;
6629  }
6630  // if it's a type declaration, set type
6631  } elseif($key_localpart == 'type'){
6632  if (isset($this->message[$pos]['type']) && $this->message[$pos]['type'] == 'array') {
6633  // do nothing: already processed arrayType
6634  } else {
6635  $value_prefix = $this->getPrefix($value);
6636  $value_localpart = $this->getLocalPart($value);
6637  $this->message[$pos]['type'] = $value_localpart;
6638  $this->message[$pos]['typePrefix'] = $value_prefix;
6639  if(isset($this->namespaces[$value_prefix])){
6640  $this->message[$pos]['type_namespace'] = $this->namespaces[$value_prefix];
6641  } else if(isset($attrs['xmlns:'.$value_prefix])) {
6642  $this->message[$pos]['type_namespace'] = $attrs['xmlns:'.$value_prefix];
6643  }
6644  // should do something here with the namespace of specified type?
6645  }
6646  } elseif($key_localpart == 'arrayType'){
6647  $this->message[$pos]['type'] = 'array';
6648  /* do arrayType ereg here
6649  [1] arrayTypeValue ::= atype asize
6650  [2] atype ::= QName rank*
6651  [3] rank ::= '[' (',')* ']'
6652  [4] asize ::= '[' length~ ']'
6653  [5] length ::= nextDimension* Digit+
6654  [6] nextDimension ::= Digit+ ','
6655  */
6656  $expr = '/([A-Za-z0-9_]+):([A-Za-z]+[A-Za-z0-9_]+)\[([0-9]+),?([0-9]*)\]/';
6657  if(preg_match($expr,$value,$regs)){
6658  $this->message[$pos]['typePrefix'] = $regs[1];
6659  $this->message[$pos]['arrayTypePrefix'] = $regs[1];
6660  if (isset($this->namespaces[$regs[1]])) {
6661  $this->message[$pos]['arrayTypeNamespace'] = $this->namespaces[$regs[1]];
6662  } else if (isset($attrs['xmlns:'.$regs[1]])) {
6663  $this->message[$pos]['arrayTypeNamespace'] = $attrs['xmlns:'.$regs[1]];
6664  }
6665  $this->message[$pos]['arrayType'] = $regs[2];
6666  $this->message[$pos]['arraySize'] = $regs[3];
6667  $this->message[$pos]['arrayCols'] = $regs[4];
6668  }
6669  // specifies nil value (or not)
6670  } elseif ($key_localpart == 'nil'){
6671  $this->message[$pos]['nil'] = ($value == 'true' || $value == '1');
6672  // some other attribute
6673  } elseif ($key != 'href' && $key != 'xmlns' && $key_localpart != 'encodingStyle' && $key_localpart != 'root') {
6674  $this->message[$pos]['xattrs']['!' . $key] = $value;
6675  }
6676 
6677  if ($key == 'xmlns') {
6678  $this->default_namespace = $value;
6679  }
6680  // log id
6681  if($key == 'id'){
6682  $this->ids[$value] = $pos;
6683  }
6684  // root
6685  if($key_localpart == 'root' && $value == 1){
6686  $this->status = 'method';
6687  $this->root_struct_name = $name;
6688  $this->root_struct = $pos;
6689  $this->debug("found root struct $this->root_struct_name, pos $pos");
6690  }
6691  // for doclit
6692  $attstr .= " $key=\"$value\"";
6693  }
6694  // get namespace - must be done after namespace atts are processed
6695  if(isset($prefix)){
6696  $this->message[$pos]['namespace'] = $this->namespaces[$prefix];
6697  $this->default_namespace = $this->namespaces[$prefix];
6698  } else {
6699  $this->message[$pos]['namespace'] = $this->default_namespace;
6700  }
6701  if($this->status == 'header'){
6702  if ($this->root_header != $pos) {
6703  $this->responseHeaders .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>";
6704  }
6705  } elseif($this->root_struct_name != ''){
6706  $this->document .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>";
6707  }
6708  }
6709 
6717  function end_element($parser, $name) {
6718  // position of current element is equal to the last value left in depth_array for my depth
6719  $pos = $this->depth_array[$this->depth--];
6720 
6721  // get element prefix
6722  if(strpos($name,':')){
6723  // get ns prefix
6724  $prefix = substr($name,0,strpos($name,':'));
6725  // get unqualified name
6726  $name = substr(strstr($name,':'),1);
6727  }
6728 
6729  // build to native type
6730  if(isset($this->body_position) && $pos > $this->body_position){
6731  // deal w/ multirefs
6732  if(isset($this->message[$pos]['attrs']['href'])){
6733  // get id
6734  $id = substr($this->message[$pos]['attrs']['href'],1);
6735  // add placeholder to href array
6736  $this->multirefs[$id][$pos] = 'placeholder';
6737  // add set a reference to it as the result value
6738  $this->message[$pos]['result'] =& $this->multirefs[$id][$pos];
6739  // build complexType values
6740  } elseif($this->message[$pos]['children'] != ''){
6741  // if result has already been generated (struct/array)
6742  if(!isset($this->message[$pos]['result'])){
6743  $this->message[$pos]['result'] = $this->buildVal($pos);
6744  }
6745  // build complexType values of attributes and possibly simpleContent
6746  } elseif (isset($this->message[$pos]['xattrs'])) {
6747  if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) {
6748  $this->message[$pos]['xattrs']['!'] = null;
6749  } elseif (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') {
6750  if (isset($this->message[$pos]['type'])) {
6751  $this->message[$pos]['xattrs']['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
6752  } else {
6753  $parent = $this->message[$pos]['parent'];
6754  if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
6755  $this->message[$pos]['xattrs']['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
6756  } else {
6757  $this->message[$pos]['xattrs']['!'] = $this->message[$pos]['cdata'];
6758  }
6759  }
6760  }
6761  $this->message[$pos]['result'] = $this->message[$pos]['xattrs'];
6762  // set value of simpleType (or nil complexType)
6763  } else {
6764  //$this->debug('adding data for scalar value '.$this->message[$pos]['name'].' of value '.$this->message[$pos]['cdata']);
6765  if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) {
6766  $this->message[$pos]['xattrs']['!'] = null;
6767  } elseif (isset($this->message[$pos]['type'])) {
6768  $this->message[$pos]['result'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
6769  } else {
6770  $parent = $this->message[$pos]['parent'];
6771  if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
6772  $this->message[$pos]['result'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
6773  } else {
6774  $this->message[$pos]['result'] = $this->message[$pos]['cdata'];
6775  }
6776  }
6777 
6778  /* add value to parent's result, if parent is struct/array
6779  $parent = $this->message[$pos]['parent'];
6780  if($this->message[$parent]['type'] != 'map'){
6781  if(strtolower($this->message[$parent]['type']) == 'array'){
6782  $this->message[$parent]['result'][] = $this->message[$pos]['result'];
6783  } else {
6784  $this->message[$parent]['result'][$this->message[$pos]['name']] = $this->message[$pos]['result'];
6785  }
6786  }
6787  */
6788  }
6789  }
6790 
6791  // for doclit
6792  if($this->status == 'header'){
6793  if ($this->root_header != $pos) {
6794  $this->responseHeaders .= "</" . (isset($prefix) ? $prefix . ':' : '') . "$name>";
6795  }
6796  } elseif($pos >= $this->root_struct){
6797  $this->document .= "</" . (isset($prefix) ? $prefix . ':' : '') . "$name>";
6798  }
6799  // switch status
6800  if($pos == $this->root_struct){
6801  $this->status = 'body';
6802  $this->root_struct_namespace = $this->message[$pos]['namespace'];
6803  } elseif($name == 'Body'){
6804  $this->status = 'envelope';
6805  } elseif($name == 'Header'){
6806  $this->status = 'envelope';
6807  } elseif($name == 'Envelope'){
6808  //
6809  }
6810  // set parent back to my parent
6811  $this->parent = $this->message[$pos]['parent'];
6812  }
6813 
6821  function character_data($parser, $data){
6822  $pos = $this->depth_array[$this->depth];
6823  if ($this->xml_encoding=='UTF-8'){
6824  // TODO: add an option to disable this for folks who want
6825  // raw UTF-8 that, e.g., might not map to iso-8859-1
6826  // TODO: this can also be handled with xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, "ISO-8859-1");
6827  if($this->decode_utf8){
6828  $data = utf8_decode($data);
6829  }
6830  }
6831  $this->message[$pos]['cdata'] .= $data;
6832  // for doclit
6833  if($this->status == 'header'){
6834  $this->responseHeaders .= $data;
6835  } else {
6836  $this->document .= $data;
6837  }
6838  }
6839 
6847  function get_response(){
6848  return $this->soapresponse;
6849  }
6850 
6857  function get_soapbody(){
6858  return $this->soapresponse;
6859  }
6860 
6867  function get_soapheader(){
6868  return $this->soapheader;
6869  }
6870 
6877  function getHeaders(){
6878  return $this->responseHeaders;
6879  }
6880 
6890  function decodeSimple($value, $type, $typens) {
6891  // TODO: use the namespace!
6892  if ((!isset($type)) || $type == 'string' || $type == 'long' || $type == 'unsignedLong') {
6893  return (string) $value;
6894  }
6895  if ($type == 'int' || $type == 'integer' || $type == 'short' || $type == 'byte') {
6896  return (int) $value;
6897  }
6898  if ($type == 'float' || $type == 'double' || $type == 'decimal') {
6899  return (double) $value;
6900  }
6901  if ($type == 'boolean') {
6902  if (strtolower($value) == 'false' || strtolower($value) == 'f') {
6903  return false;
6904  }
6905  return (boolean) $value;
6906  }
6907  if ($type == 'base64' || $type == 'base64Binary') {
6908  $this->debug('Decode base64 value');
6909  return base64_decode($value);
6910  }
6911  // obscure numeric types
6912  if ($type == 'nonPositiveInteger' || $type == 'negativeInteger'
6913  || $type == 'nonNegativeInteger' || $type == 'positiveInteger'
6914  || $type == 'unsignedInt'
6915  || $type == 'unsignedShort' || $type == 'unsignedByte') {
6916  return (int) $value;
6917  }
6918  // bogus: parser treats array with no elements as a simple type
6919  if ($type == 'array') {
6920  return array();
6921  }
6922  // everything else
6923  return (string) $value;
6924  }
6925 
6934  function buildVal($pos){
6935  if(!isset($this->message[$pos]['type'])){
6936  $this->message[$pos]['type'] = '';
6937  }
6938  $this->debug('in buildVal() for '.$this->message[$pos]['name']."(pos $pos) of type ".$this->message[$pos]['type']);
6939  // if there are children...
6940  if($this->message[$pos]['children'] != ''){
6941  $this->debug('in buildVal, there are children');
6942  $children = explode('|',$this->message[$pos]['children']);
6943  array_shift($children); // knock off empty
6944  // md array
6945  if(isset($this->message[$pos]['arrayCols']) && $this->message[$pos]['arrayCols'] != ''){
6946  $r=0; // rowcount
6947  $c=0; // colcount
6948  foreach($children as $child_pos){
6949  $this->debug("in buildVal, got an MD array element: $r, $c");
6950  $params[$r][] = $this->message[$child_pos]['result'];
6951  $c++;
6952  if($c == $this->message[$pos]['arrayCols']){
6953  $c = 0;
6954  $r++;
6955  }
6956  }
6957  // array
6958  } elseif($this->message[$pos]['type'] == 'array' || $this->message[$pos]['type'] == 'Array'){
6959  $this->debug('in buildVal, adding array '.$this->message[$pos]['name']);
6960  foreach($children as $child_pos){
6961  $params[] = &$this->message[$child_pos]['result'];
6962  }
6963  // apache Map type: java hashtable
6964  } elseif($this->message[$pos]['type'] == 'Map' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap'){
6965  $this->debug('in buildVal, Java Map '.$this->message[$pos]['name']);
6966  foreach($children as $child_pos){
6967  $kv = explode("|",$this->message[$child_pos]['children']);
6968  $params[$this->message[$kv[1]]['result']] = &$this->message[$kv[2]]['result'];
6969  }
6970  // generic compound type
6971  //} elseif($this->message[$pos]['type'] == 'SOAPStruct' || $this->message[$pos]['type'] == 'struct') {
6972  } else {
6973  // Apache Vector type: treat as an array
6974  $this->debug('in buildVal, adding Java Vector or generic compound type '.$this->message[$pos]['name']);
6975  if ($this->message[$pos]['type'] == 'Vector' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap') {
6976  $notstruct = 1;
6977  } else {
6978  $notstruct = 0;
6979  }
6980  //
6981  foreach($children as $child_pos){
6982  if($notstruct){
6983  $params[] = &$this->message[$child_pos]['result'];
6984  } else {
6985  if (isset($params[$this->message[$child_pos]['name']])) {
6986  // de-serialize repeated element name into an array
6987  if ((!is_array($params[$this->message[$child_pos]['name']])) || (!isset($params[$this->message[$child_pos]['name']][0]))) {
6988  $params[$this->message[$child_pos]['name']] = array($params[$this->message[$child_pos]['name']]);
6989  }
6990  $params[$this->message[$child_pos]['name']][] = &$this->message[$child_pos]['result'];
6991  } else {
6992  $params[$this->message[$child_pos]['name']] = &$this->message[$child_pos]['result'];
6993  }
6994  }
6995  }
6996  }
6997  if (isset($this->message[$pos]['xattrs'])) {
6998  $this->debug('in buildVal, handling attributes');
6999  foreach ($this->message[$pos]['xattrs'] as $n => $v) {
7000  $params[$n] = $v;
7001  }
7002  }
7003  // handle simpleContent
7004  if (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') {
7005  $this->debug('in buildVal, handling simpleContent');
7006  if (isset($this->message[$pos]['type'])) {
7007  $params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
7008  } else {
7009  $parent = $this->message[$pos]['parent'];
7010  if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
7011  $params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
7012  } else {
7013  $params['!'] = $this->message[$pos]['cdata'];
7014  }
7015  }
7016  }
7017  $ret = is_array($params) ? $params : array();
7018  $this->debug('in buildVal, return:');
7019  $this->appendDebug($this->varDump($ret));
7020  return $ret;
7021  } else {
7022  $this->debug('in buildVal, no children, building scalar');
7023  $cdata = isset($this->message[$pos]['cdata']) ? $this->message[$pos]['cdata'] : '';
7024  if (isset($this->message[$pos]['type'])) {
7025  $ret = $this->decodeSimple($cdata, $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
7026  $this->debug("in buildVal, return: $ret");
7027  return $ret;
7028  }
7029  $parent = $this->message[$pos]['parent'];
7030  if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
7031  $ret = $this->decodeSimple($cdata, $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
7032  $this->debug("in buildVal, return: $ret");
7033  return $ret;
7034  }
7035  $ret = $this->message[$pos]['cdata'];
7036  $this->debug("in buildVal, return: $ret");
7037  return $ret;
7038  }
7039  }
7040 }
7041 
7045 class soap_parser extends nusoap_parser {
7046 }
7047 
7048 ?><?php
7049 
7050 
7051 
7072 class nusoap_client extends nusoap_base {
7073 
7074  var $username = ''; // Username for HTTP authentication
7075  var $password = ''; // Password for HTTP authentication
7076  var $authtype = ''; // Type of HTTP authentication
7077  var $certRequest = array(); // Certificate for HTTP SSL authentication
7078  var $requestHeaders = false; // SOAP headers in request (text)
7079  var $responseHeaders = ''; // SOAP headers from response (incomplete namespace resolution) (text)
7080  var $responseHeader = NULL; // SOAP Header from response (parsed)
7081  var $document = ''; // SOAP body response portion (incomplete namespace resolution) (text)
7082  var $endpoint;
7083  var $forceEndpoint = ''; // overrides WSDL endpoint
7084  var $proxyhost = '';
7085  var $proxyport = '';
7086  var $proxyusername = '';
7087  var $proxypassword = '';
7088  var $xml_encoding = ''; // character set encoding of incoming (response) messages
7089  var $http_encoding = false;
7090  var $timeout = 0; // HTTP connection timeout
7091  var $response_timeout = 30; // HTTP response timeout
7092  var $endpointType = ''; // soap|wsdl, empty for WSDL initialization error
7093  var $persistentConnection = false;
7094  var $defaultRpcParams = false; // This is no longer used
7095  var $request = ''; // HTTP request
7096  var $response = ''; // HTTP response
7097  var $responseData = ''; // SOAP payload of response
7098  var $cookies = array(); // Cookies from response or for request
7099  var $decode_utf8 = true; // toggles whether the parser decodes element content w/ utf8_decode()
7100  var $operations = array(); // WSDL operations, empty for WSDL initialization error
7101  var $curl_options = array(); // User-specified cURL options
7102  var $bindingType = ''; // WSDL operation binding type
7103  var $use_curl = false; // whether to always try to use cURL
7104 
7105  /*
7106  * fault related variables
7107  */
7112  var $fault;
7117  var $faultcode;
7122  var $faultstring;
7127  var $faultdetail;
7128 
7143  function __construct($endpoint,$wsdl = false,$proxyhost = false,$proxyport = false,$proxyusername = false, $proxypassword = false, $timeout = 0, $response_timeout = 30){
7144  parent::__construct();
7145  $this->endpoint = $endpoint;
7146  $this->proxyhost = $proxyhost;
7147  $this->proxyport = $proxyport;
7148  $this->proxyusername = $proxyusername;
7149  $this->proxypassword = $proxypassword;
7150  $this->timeout = $timeout;
7151  $this->response_timeout = $response_timeout;
7152 
7153  $this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout");
7154  $this->appendDebug('endpoint=' . $this->varDump($endpoint));
7155 
7156  // make values
7157  if($wsdl){
7158  if (is_object($endpoint) && (get_class($endpoint) == 'wsdl')) {
7159  $this->wsdl = $endpoint;
7160  $this->endpoint = $this->wsdl->wsdl;
7161  $this->wsdlFile = $this->endpoint;
7162  $this->debug('existing wsdl instance created from ' . $this->endpoint);
7163  $this->checkWSDL();
7164  } else {
7165  $this->wsdlFile = $this->endpoint;
7166  $this->wsdl = null;
7167  $this->debug('will use lazy evaluation of wsdl from ' . $this->endpoint);
7168  }
7169  $this->endpointType = 'wsdl';
7170  } else {
7171  $this->debug("instantiate SOAP with endpoint at $endpoint");
7172  $this->endpointType = 'soap';
7173  }
7174  }
7175 
7201  function call($operation,$params=array(),$namespace='http://tempuri.org',$soapAction='',$headers=false,$rpcParams=null,$style='rpc',$use='encoded'){
7202  $this->operation = $operation;
7203  $this->fault = false;
7204  $this->setError('');
7205  $this->request = '';
7206  $this->response = '';
7207  $this->responseData = '';
7208  $this->faultstring = '';
7209  $this->faultcode = '';
7210  $this->opData = array();
7211 
7212  $this->debug("call: operation=$operation, namespace=$namespace, soapAction=$soapAction, rpcParams=$rpcParams, style=$style, use=$use, endpointType=$this->endpointType");
7213  $this->appendDebug('params=' . $this->varDump($params));
7214  $this->appendDebug('headers=' . $this->varDump($headers));
7215  if ($headers) {
7216  $this->requestHeaders = $headers;
7217  }
7218  if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
7219  $this->loadWSDL();
7220  if ($this->getError())
7221  return false;
7222  }
7223  // serialize parameters
7224  if($this->endpointType == 'wsdl' && $opData = $this->getOperationData($operation)){
7225  // use WSDL for operation
7226  $this->opData = $opData;
7227  $this->debug("found operation");
7228  $this->appendDebug('opData=' . $this->varDump($opData));
7229  if (isset($opData['soapAction'])) {
7230  $soapAction = $opData['soapAction'];
7231  }
7232  if (! $this->forceEndpoint) {
7233  $this->endpoint = $opData['endpoint'];
7234  } else {
7235  $this->endpoint = $this->forceEndpoint;
7236  }
7237  $namespace = isset($opData['input']['namespace']) ? $opData['input']['namespace'] : $namespace;
7238  $style = $opData['style'];
7239  $use = $opData['input']['use'];
7240  // add ns to ns array
7241  if($namespace != '' && !isset($this->wsdl->namespaces[$namespace])){
7242  $nsPrefix = 'ns' . rand(1000, 9999);
7243  $this->wsdl->namespaces[$nsPrefix] = $namespace;
7244  }
7245  $nsPrefix = $this->wsdl->getPrefixFromNamespace($namespace);
7246  // serialize payload
7247  if (is_string($params)) {
7248  $this->debug("serializing param string for WSDL operation $operation");
7249  $payload = $params;
7250  } elseif (is_array($params)) {
7251  $this->debug("serializing param array for WSDL operation $operation");
7252  $payload = $this->wsdl->serializeRPCParameters($operation,'input',$params,$this->bindingType);
7253  } else {
7254  $this->debug('params must be array or string');
7255  $this->setError('params must be array or string');
7256  return false;
7257  }
7258  $usedNamespaces = $this->wsdl->usedNamespaces;
7259  if (isset($opData['input']['encodingStyle'])) {
7260  $encodingStyle = $opData['input']['encodingStyle'];
7261  } else {
7262  $encodingStyle = '';
7263  }
7264  $this->appendDebug($this->wsdl->getDebug());
7265  $this->wsdl->clearDebug();
7266  if ($errstr = $this->wsdl->getError()) {
7267  $this->debug('got wsdl error: '.$errstr);
7268  $this->setError('wsdl error: '.$errstr);
7269  return false;
7270  }
7271  } elseif($this->endpointType == 'wsdl') {
7272  // operation not in WSDL
7273  $this->appendDebug($this->wsdl->getDebug());
7274  $this->wsdl->clearDebug();
7275  $this->setError( 'operation '.$operation.' not present.');
7276  $this->debug("operation '$operation' not present.");
7277  return false;
7278  } else {
7279  // no WSDL
7280  //$this->namespaces['ns1'] = $namespace;
7281  $nsPrefix = 'ns' . rand(1000, 9999);
7282  // serialize
7283  $payload = '';
7284  if (is_string($params)) {
7285  $this->debug("serializing param string for operation $operation");
7286  $payload = $params;
7287  } elseif (is_array($params)) {
7288  $this->debug("serializing param array for operation $operation");
7289  foreach($params as $k => $v){
7290  $payload .= $this->serialize_val($v,$k,false,false,false,false,$use);
7291  }
7292  } else {
7293  $this->debug('params must be array or string');
7294  $this->setError('params must be array or string');
7295  return false;
7296  }
7297  $usedNamespaces = array();
7298  if ($use == 'encoded') {
7299  $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
7300  } else {
7301  $encodingStyle = '';
7302  }
7303  }
7304  // wrap RPC calls with method element
7305  if ($style == 'rpc') {
7306  if ($use == 'literal') {
7307  $this->debug("wrapping RPC request with literal method element");
7308  if ($namespace) {
7309  // http://www.ws-i.org/Profiles/BasicProfile-1.1-2004-08-24.html R2735 says rpc/literal accessor elements should not be in a namespace
7310  $payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" .
7311  $payload .
7312  "</$nsPrefix:$operation>";
7313  } else {
7314  $payload = "<$operation>" . $payload . "</$operation>";
7315  }
7316  } else {
7317  $this->debug("wrapping RPC request with encoded method element");
7318  if ($namespace) {
7319  $payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" .
7320  $payload .
7321  "</$nsPrefix:$operation>";
7322  } else {
7323  $payload = "<$operation>" .
7324  $payload .
7325  "</$operation>";
7326  }
7327  }
7328  }
7329  // serialize envelope
7330  $soapmsg = $this->serializeEnvelope($payload,$this->requestHeaders,$usedNamespaces,$style,$use,$encodingStyle);
7331  $this->debug("endpoint=$this->endpoint, soapAction=$soapAction, namespace=$namespace, style=$style, use=$use, encodingStyle=$encodingStyle");
7332  $this->debug('SOAP message length=' . strlen($soapmsg) . ' contents (max 1000 bytes)=' . substr($soapmsg, 0, 1000));
7333  // send
7334  $return = $this->send($this->getHTTPBody($soapmsg),$soapAction,$this->timeout,$this->response_timeout);
7335  if($errstr = $this->getError()){
7336  $this->debug('Error: '.$errstr);
7337  return false;
7338  } else {
7339  $this->return = $return;
7340  $this->debug('sent message successfully and got a(n) '.gettype($return));
7341  $this->appendDebug('return=' . $this->varDump($return));
7342 
7343  // fault?
7344  if(is_array($return) && isset($return['faultcode'])){
7345  $this->debug('got fault');
7346  $this->setError($return['faultcode'].': '.$return['faultstring']);
7347  $this->fault = true;
7348  foreach($return as $k => $v){
7349  $this->$k = $v;
7350  $this->debug("$k = $v<br>");
7351  }
7352  return $return;
7353  } elseif ($style == 'document') {
7354  // NOTE: if the response is defined to have multiple parts (i.e. unwrapped),
7355  // we are only going to return the first part here...sorry about that
7356  return $return;
7357  } else {
7358  // array of return values
7359  if(is_array($return)){
7360  // multiple 'out' parameters, which we return wrapped up
7361  // in the array
7362  if(sizeof($return) > 1){
7363  return $return;
7364  }
7365  // single 'out' parameter (normally the return value)
7366  $return = array_shift($return);
7367  $this->debug('return shifted value: ');
7368  $this->appendDebug($this->varDump($return));
7369  return $return;
7370  // nothing returned (ie, echoVoid)
7371  } else {
7372  return "";
7373  }
7374  }
7375  }
7376  }
7377 
7383  function checkWSDL() {
7384  $this->appendDebug($this->wsdl->getDebug());
7385  $this->wsdl->clearDebug();
7386  $this->debug('checkWSDL');
7387  // catch errors
7388  if ($errstr = $this->wsdl->getError()) {
7389  $this->debug('got wsdl error: '.$errstr);
7390  $this->setError('wsdl error: '.$errstr);
7391  } elseif ($this->operations = $this->wsdl->getOperations('soap')) {
7392  $this->bindingType = 'soap';
7393  $this->debug('got '.count($this->operations).' operations from wsdl '.$this->wsdlFile.' for binding type '.$this->bindingType);
7394  } elseif ($this->operations = $this->wsdl->getOperations('soap12')) {
7395  $this->bindingType = 'soap12';
7396  $this->debug('got '.count($this->operations).' operations from wsdl '.$this->wsdlFile.' for binding type '.$this->bindingType);
7397  $this->debug('**************** WARNING: SOAP 1.2 BINDING *****************');
7398  } else {
7399  $this->debug('getOperations returned false');
7400  $this->setError('no operations defined in the WSDL document!');
7401  }
7402  }
7403 
7409  function loadWSDL() {
7410  $this->debug('instantiating wsdl class with doc: '.$this->wsdlFile);
7411  $this->wsdl = new wsdl('',$this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword,$this->timeout,$this->response_timeout,$this->curl_options,$this->use_curl);
7412  $this->wsdl->setCredentials($this->username, $this->password, $this->authtype, $this->certRequest);
7413  $this->wsdl->fetchWSDL($this->wsdlFile);
7414  $this->checkWSDL();
7415  }
7416 
7424  function getOperationData($operation){
7425  if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
7426  $this->loadWSDL();
7427  if ($this->getError())
7428  return false;
7429  }
7430  if(isset($this->operations[$operation])){
7431  return $this->operations[$operation];
7432  }
7433  $this->debug("No data for operation: $operation");
7434  }
7435 
7450  function send($msg, $soapaction = '', $timeout=0, $response_timeout=30) {
7451  $this->checkCookies();
7452  // detect transport
7453  switch(true){
7454  // http(s)
7455  case preg_match('/^http/',$this->endpoint):
7456  $this->debug('transporting via HTTP');
7457  if($this->persistentConnection == true && is_object($this->persistentConnection)){
7458  $http =& $this->persistentConnection;
7459  } else {
7460  $http = new soap_transport_http($this->endpoint, $this->curl_options, $this->use_curl);
7461  if ($this->persistentConnection) {
7462  $http->usePersistentConnection();
7463  }
7464  }
7465  $http->setContentType($this->getHTTPContentType(), $this->getHTTPContentTypeCharset());
7466  $http->setSOAPAction($soapaction);
7467  if($this->proxyhost && $this->proxyport){
7468  $http->setProxy($this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword);
7469  }
7470  if($this->authtype != '') {
7471  $http->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest);
7472  }
7473  if($this->http_encoding != ''){
7474  $http->setEncoding($this->http_encoding);
7475  }
7476  $this->debug('sending message, length='.strlen($msg));
7477  if(preg_match('/^http:/',$this->endpoint)){
7478  //if(strpos($this->endpoint,'http:')){
7479  $this->responseData = $http->send($msg,$timeout,$response_timeout,$this->cookies);
7480  } elseif(preg_match('/^https/',$this->endpoint)){
7481  //} elseif(strpos($this->endpoint,'https:')){
7482  //if(phpversion() == '4.3.0-dev'){
7483  //$response = $http->send($msg,$timeout,$response_timeout);
7484  //$this->request = $http->outgoing_payload;
7485  //$this->response = $http->incoming_payload;
7486  //} else
7487  $this->responseData = $http->sendHTTPS($msg,$timeout,$response_timeout,$this->cookies);
7488  } else {
7489  $this->setError('no http/s in endpoint url');
7490  }
7491  $this->request = $http->outgoing_payload;
7492  $this->response = $http->incoming_payload;
7493  $this->appendDebug($http->getDebug());
7494  $this->UpdateCookies($http->incoming_cookies);
7495 
7496  // save transport object if using persistent connections
7497  if ($this->persistentConnection) {
7498  $http->clearDebug();
7499  if (!is_object($this->persistentConnection)) {
7500  $this->persistentConnection = $http;
7501  }
7502  }
7503 
7504  if($err = $http->getError()){
7505  $this->setError('HTTP Error: '.$err);
7506  return false;
7507  } elseif($this->getError()){
7508  return false;
7509  } else {
7510  $this->debug('got response, length='. strlen($this->responseData).' type='.$http->incoming_headers['content-type']);
7511  return $this->parseResponse($http->incoming_headers, $this->responseData);
7512  }
7513  break;
7514  default:
7515  $this->setError('no transport found, or selected transport is not yet supported!');
7516  return false;
7517  break;
7518  }
7519  }
7520 
7529  function parseResponse($headers, $data) {
7530  $this->debug('Entering parseResponse() for data of length ' . strlen($data) . ' headers:');
7531  $this->appendDebug($this->varDump($headers));
7532  if (!strstr($headers['content-type'], 'text/xml')) {
7533  $this->setError('Response not of type text/xml: ' . $headers['content-type']);
7534  return false;
7535  }
7536  if (strpos($headers['content-type'], '=')) {
7537  $enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1));
7538  $this->debug('Got response encoding: ' . $enc);
7539  if(preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)){
7540  $this->xml_encoding = strtoupper($enc);
7541  } else {
7542  $this->xml_encoding = 'US-ASCII';
7543  }
7544  } else {
7545  // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
7546  $this->xml_encoding = 'ISO-8859-1';
7547  }
7548  $this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser');
7549  $parser = new nusoap_parser($data,$this->xml_encoding,$this->operation,$this->decode_utf8);
7550  // add parser debug data to our debug
7551  $this->appendDebug($parser->getDebug());
7552  // if parse errors
7553  if($errstr = $parser->getError()){
7554  $this->setError( $errstr);
7555  // destroy the parser object
7556  unset($parser);
7557  return false;
7558  } else {
7559  // get SOAP headers
7560  $this->responseHeaders = $parser->getHeaders();
7561  // get SOAP headers
7562  $this->responseHeader = $parser->get_soapheader();
7563  // get decoded message
7564  $return = $parser->get_soapbody();
7565  // add document for doclit support
7566  $this->document = $parser->document;
7567  // destroy the parser object
7568  unset($parser);
7569  // return decode message
7570  return $return;
7571  }
7572  }
7573 
7581  function setCurlOption($option, $value) {
7582  $this->debug("setCurlOption option=$option, value=");
7583  $this->appendDebug($this->varDump($value));
7584  $this->curl_options[$option] = $value;
7585  }
7586 
7593  function setEndpoint($endpoint) {
7594  $this->debug("setEndpoint(\"$endpoint\")");
7595  $this->forceEndpoint = $endpoint;
7596  }
7597 
7604  function setHeaders($headers){
7605  $this->debug("setHeaders headers=");
7606  $this->appendDebug($this->varDump($headers));
7607  $this->requestHeaders = $headers;
7608  }
7609 
7616  function getHeaders(){
7617  return $this->responseHeaders;
7618  }
7619 
7626  function getHeader(){
7627  return $this->responseHeader;
7628  }
7629 
7639  function setHTTPProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '') {
7640  $this->proxyhost = $proxyhost;
7641  $this->proxyport = $proxyport;
7642  $this->proxyusername = $proxyusername;
7643  $this->proxypassword = $proxypassword;
7644  }
7645 
7655  function setCredentials($username, $password, $authtype = 'basic', $certRequest = array()) {
7656  $this->debug("setCredentials username=$username authtype=$authtype certRequest=");
7657  $this->appendDebug($this->varDump($certRequest));
7658  $this->username = $username;
7659  $this->password = $password;
7660  $this->authtype = $authtype;
7661  $this->certRequest = $certRequest;
7662  }
7663 
7670  function setHTTPEncoding($enc='gzip, deflate'){
7671  $this->debug("setHTTPEncoding(\"$enc\")");
7672  $this->http_encoding = $enc;
7673  }
7674 
7681  function setUseCURL($use) {
7682  $this->debug("setUseCURL($use)");
7683  $this->use_curl = $use;
7684  }
7685 
7691  function useHTTPPersistentConnection(){
7692  $this->debug("useHTTPPersistentConnection");
7693  $this->persistentConnection = true;
7694  }
7695 
7707  function getDefaultRpcParams() {
7708  return $this->defaultRpcParams;
7709  }
7710 
7722  function setDefaultRpcParams($rpcParams) {
7723  $this->defaultRpcParams = $rpcParams;
7724  }
7725 
7733  function getProxy() {
7734  $r = rand();
7735  $evalStr = $this->_getProxyClassCode($r);
7736  //$this->debug("proxy class: $evalStr");
7737  if ($this->getError()) {
7738  $this->debug("Error from _getProxyClassCode, so return NULL");
7739  return null;
7740  }
7741  // eval the class
7742  eval($evalStr);
7743  // instantiate proxy object
7744  eval("\$proxy = new nusoap_proxy_$r('');");
7745  // transfer current wsdl data to the proxy thereby avoiding parsing the wsdl twice
7746  $proxy->endpointType = 'wsdl';
7747  $proxy->wsdlFile = $this->wsdlFile;
7748  $proxy->wsdl = $this->wsdl;
7749  $proxy->operations = $this->operations;
7750  $proxy->defaultRpcParams = $this->defaultRpcParams;
7751  // transfer other state
7752  $proxy->soap_defencoding = $this->soap_defencoding;
7753  $proxy->username = $this->username;
7754  $proxy->password = $this->password;
7755  $proxy->authtype = $this->authtype;
7756  $proxy->certRequest = $this->certRequest;
7757  $proxy->requestHeaders = $this->requestHeaders;
7758  $proxy->endpoint = $this->endpoint;
7759  $proxy->forceEndpoint = $this->forceEndpoint;
7760  $proxy->proxyhost = $this->proxyhost;
7761  $proxy->proxyport = $this->proxyport;
7762  $proxy->proxyusername = $this->proxyusername;
7763  $proxy->proxypassword = $this->proxypassword;
7764  $proxy->http_encoding = $this->http_encoding;
7765  $proxy->timeout = $this->timeout;
7766  $proxy->response_timeout = $this->response_timeout;
7767  $proxy->persistentConnection = &$this->persistentConnection;
7768  $proxy->decode_utf8 = $this->decode_utf8;
7769  $proxy->curl_options = $this->curl_options;
7770  $proxy->bindingType = $this->bindingType;
7771  $proxy->use_curl = $this->use_curl;
7772  return $proxy;
7773  }
7774 
7781  function _getProxyClassCode($r) {
7782  $this->debug("in getProxy endpointType=$this->endpointType");
7783  $this->appendDebug("wsdl=" . $this->varDump($this->wsdl));
7784  if ($this->endpointType != 'wsdl') {
7785  $evalStr = 'A proxy can only be created for a WSDL client';
7786  $this->setError($evalStr);
7787  $evalStr = "echo \"$evalStr\";";
7788  return $evalStr;
7789  }
7790  if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
7791  $this->loadWSDL();
7792  if ($this->getError()) {
7793  return "echo \"" . $this->getError() . "\";";
7794  }
7795  }
7796  $evalStr = '';
7797  foreach ($this->operations as $operation => $opData) {
7798  if ($operation != '') {
7799  // create param string and param comment string
7800  if (sizeof($opData['input']['parts']) > 0) {
7801  $paramStr = '';
7802  $paramArrayStr = '';
7803  $paramCommentStr = '';
7804  foreach ($opData['input']['parts'] as $name => $type) {
7805  $paramStr .= "\$$name, ";
7806  $paramArrayStr .= "'$name' => \$$name, ";
7807  $paramCommentStr .= "$type \$$name, ";
7808  }
7809  $paramStr = substr($paramStr, 0, strlen($paramStr)-2);
7810  $paramArrayStr = substr($paramArrayStr, 0, strlen($paramArrayStr)-2);
7811  $paramCommentStr = substr($paramCommentStr, 0, strlen($paramCommentStr)-2);
7812  } else {
7813  $paramStr = '';
7814  $paramArrayStr = '';
7815  $paramCommentStr = 'void';
7816  }
7817  $opData['namespace'] = !isset($opData['namespace']) ? 'http://testuri.com' : $opData['namespace'];
7818  $evalStr .= "// $paramCommentStr
7819  function " . str_replace('.', '__', $operation) . "($paramStr) {
7820  \$params = array($paramArrayStr);
7821  return \$this->call('$operation', \$params, '".$opData['namespace']."', '".(isset($opData['soapAction']) ? $opData['soapAction'] : '')."');
7822  }
7823  ";
7824  unset($paramStr);
7825  unset($paramCommentStr);
7826  }
7827  }
7828  $evalStr = 'class nusoap_proxy_'.$r.' extends nusoap_client {
7829  '.$evalStr.'
7830 }';
7831  return $evalStr;
7832  }
7833 
7840  function getProxyClassCode() {
7841  $r = rand();
7842  return $this->_getProxyClassCode($r);
7843  }
7844 
7852  function getHTTPBody($soapmsg) {
7853  return $soapmsg;
7854  }
7855 
7864  function getHTTPContentType() {
7865  return 'text/xml';
7866  }
7867 
7877  function getHTTPContentTypeCharset() {
7878  return $this->soap_defencoding;
7879  }
7880 
7881  /*
7882  * whether or not parser should decode utf8 element content
7883  *
7884  * @return always returns true
7885  * @access public
7886  */
7887  function decodeUTF8($bool){
7888  $this->decode_utf8 = $bool;
7889  return true;
7890  }
7891 
7900  function setCookie($name, $value) {
7901  if (strlen($name) == 0) {
7902  return false;
7903  }
7904  $this->cookies[] = array('name' => $name, 'value' => $value);
7905  return true;
7906  }
7907 
7914  function getCookies() {
7915  return $this->cookies;
7916  }
7917 
7924  function checkCookies() {
7925  if (sizeof($this->cookies) == 0) {
7926  return true;
7927  }
7928  $this->debug('checkCookie: check ' . sizeof($this->cookies) . ' cookies');
7929  $curr_cookies = $this->cookies;
7930  $this->cookies = array();
7931  foreach ($curr_cookies as $cookie) {
7932  if (! is_array($cookie)) {
7933  $this->debug('Remove cookie that is not an array');
7934  continue;
7935  }
7936  if ((isset($cookie['expires'])) && (! empty($cookie['expires']))) {
7937  if (strtotime($cookie['expires']) > time()) {
7938  $this->cookies[] = $cookie;
7939  } else {
7940  $this->debug('Remove expired cookie ' . $cookie['name']);
7941  }
7942  } else {
7943  $this->cookies[] = $cookie;
7944  }
7945  }
7946  $this->debug('checkCookie: '.sizeof($this->cookies).' cookies left in array');
7947  return true;
7948  }
7949 
7957  function UpdateCookies($cookies) {
7958  if (sizeof($this->cookies) == 0) {
7959  // no existing cookies: take whatever is new
7960  if (sizeof($cookies) > 0) {
7961  $this->debug('Setting new cookie(s)');
7962  $this->cookies = $cookies;
7963  }
7964  return true;
7965  }
7966  if (sizeof($cookies) == 0) {
7967  // no new cookies: keep what we've got
7968  return true;
7969  }
7970  // merge
7971  foreach ($cookies as $newCookie) {
7972  if (!is_array($newCookie)) {
7973  continue;
7974  }
7975  if ((!isset($newCookie['name'])) || (!isset($newCookie['value']))) {
7976  continue;
7977  }
7978  $newName = $newCookie['name'];
7979 
7980  $found = false;
7981  for ($i = 0; $i < count($this->cookies); $i++) {
7982  $cookie = $this->cookies[$i];
7983  if (!is_array($cookie)) {
7984  continue;
7985  }
7986  if (!isset($cookie['name'])) {
7987  continue;
7988  }
7989  if ($newName != $cookie['name']) {
7990  continue;
7991  }
7992  $newDomain = isset($newCookie['domain']) ? $newCookie['domain'] : 'NODOMAIN';
7993  $domain = isset($cookie['domain']) ? $cookie['domain'] : 'NODOMAIN';
7994  if ($newDomain != $domain) {
7995  continue;
7996  }
7997  $newPath = isset($newCookie['path']) ? $newCookie['path'] : 'NOPATH';
7998  $path = isset($cookie['path']) ? $cookie['path'] : 'NOPATH';
7999  if ($newPath != $path) {
8000  continue;
8001  }
8002  $this->cookies[$i] = $newCookie;
8003  $found = true;
8004  $this->debug('Update cookie ' . $newName . '=' . $newCookie['value']);
8005  break;
8006  }
8007  if (! $found) {
8008  $this->debug('Add cookie ' . $newName . '=' . $newCookie['value']);
8009  $this->cookies[] = $newCookie;
8010  }
8011  }
8012  return true;
8013  }
8014 }
8015 
8016 if (!extension_loaded('soap')) {
8020  class soapclient extends nusoap_client {
8021  }
8022 }
if($err=$client->getError()) $namespace
appendDebug($string)
adds debug data to the instance debug string without formatting
Definition: nusoap.php:294
soap_server allows the user to create a SOAP server that is capable of receiving messages and returni...
Definition: nusoap.php:2313
$path
Definition: aliased.php:25
& getDebugAsXMLComment()
gets the current debug data for this instance as an XML comment this may change the contents of the d...
Definition: nusoap.php:332
serializeEnvelope($body, $headers=false, $namespaces=array(), $style='rpc', $use='encoded')
serialize message
Definition: nusoap.php:417
setError($str)
sets error string
Definition: nusoap.php:184
if(isset($_REQUEST['delete'])) $list
Definition: registry.php:41
$style
Definition: example_012.php:70
Contains information for a SOAP fault.
Definition: nusoap.php:1004
if((!isset($_SERVER['DOCUMENT_ROOT'])) OR(empty($_SERVER['DOCUMENT_ROOT']))) $_SERVER['DOCUMENT_ROOT']
transport class for sending/receiving data via HTTP and HTTPS NOTE: PHP must be compiled with the CUR...
Definition: nusoap.php:1552
& getDebug()
gets the current debug data for this instance
Definition: nusoap.php:319
$result
isArraySimpleOrStruct($val)
detect if array is a simple array or a struct (associative array)
Definition: nusoap.php:195
parses a WSDL file, allows access to it&#39;s data, other utility methods
Definition: nusoap.php:3133
foreach($paths as $path) $request
Definition: asyncclient.php:32
$type
$_GET["client_id"]
$endpoint
getOperationDataForSoapAction($soapAction, $bindingType='soap')
returns an associative array of data necessary for calling an operation
Definition: nusoap.php:5144
split($path)
Returns the &#39;dirname&#39; and &#39;basename&#39; for a path.
Definition: functions.php:279
$XMLSchemaVersion
Definition: nusoap.php:78
soap_fault class, allows for creation of faults mainly used for returning faults from deployed functi...
Definition: nusoap.php:669
if(!array_key_exists('StateId', $_REQUEST)) $id
nusoap_server allows the user to create a SOAP server that is capable of receiving messages and retur...
Definition: nusoap.php:3434
serialize()
serialize the parsed wsdl
Definition: nusoap.php:3741
addOperation($name, $in=false, $out=false, $namespace=false, $soapaction=false, $style='rpc', $use='encoded', $documentation='')
register a service with the server
Definition: nusoap.php:4362
setHeaders(array $headers)
getLocalPart($str)
returns the local part of a prefixed string returns the original string, if not prefixed ...
Definition: nusoap.php:508
$req
Definition: getUserInfo.php:20
__construct()
constructor
Definition: nusoap.php:232
parses an XML Schema, allows access to it&#39;s data, other utility methods no validation...
Definition: nusoap.php:734
for creating serializable abstractions of native PHP types NOTE: this is only really used when WSDL i...
Definition: nusoap.php:1495
$start
Definition: bench.php:8
getError()
returns error string if present
Definition: nusoap.php:171
$bindings
debug($string)
adds debug data to the class level debug string
Definition: nusoap.php:144
$messages
Definition: en.php:5
setHeader($name, $value)
Updates a HTTP header.
soap_parser class parses SOAP XML messages into native PHP values
Definition: nusoap.php:4431
$r
Definition: example_031.php:79
catch(Exception $e) $message
foreach($_POST as $key=> $value) $res
getPrefixFromNamespace($ns)
returns the prefix for a given namespace (or prefix) or false if no prefixes registered for the given...
Definition: nusoap.php:557
expandQname($qname)
expands a qualified name
Definition: nusoap.php:483
parses an XML Schema, allows access to it&#39;s data, other utility methods.
Definition: nusoap.php:1092
setCredentials($username, $password, $authtype='basic', $certRequest=array())
if authenticating, set user credentials here
Definition: nusoap.php:5058
nusoap_base
Definition: nusoap.php:61
webDescription()
prints html description of services
Definition: nusoap.php:5238
[nu]soapclient higher level class for easy usage.
Definition: nusoap.php:7072
serialize_val($val, $name=false, $type=false, $name_ns=false, $type_ns=false, $attributes=false, $use='encoded')
serializes PHP values in accordance w/ section 5.
Definition: nusoap.php:212
wsdl($wsdl='', $proxyhost=false, $proxyport=false, $proxyusername=false, $proxypassword=false, $timeout=0, $response_timeout=30)
constructor
Definition: nusoap.php:3181
$n
Definition: RandomTest.php:85
$http
Definition: raiseError.php:7
if(array_key_exists('yes', $_REQUEST)) $attributes
Definition: getconsent.php:85
varDump($data)
Definition: nusoap.php:567
getPrefix($str)
returns the prefix part of a prefixed string returns false, if not prefixed
Definition: nusoap.php:525
getOperations($bindingType='soap')
returns an assoc array of operation names => operation data
Definition: nusoap.php:3649
if(php_sapi_name() !='cli') $in
Definition: Utf8Test.php:37
$rows
Definition: xhr_table.php:10
serialize()
serialize a fault
Definition: nusoap.php:1052
$parser
Definition: BPMN2Parser.php:23
$password
Definition: cron.php:14
$soap_defencoding
Definition: nusoap.php:86
expandEntities($val)
expands entities, e.g.
Definition: nusoap.php:154
serializeRPCParameters($operation, $direction, $parameters)
serialize a PHP value according to a WSDL message definition
Definition: nusoap.php:3870
$ret
Definition: parser.php:6
$i
Definition: disco.tpl.php:19
parse_request($message)
Parses a request message string into a request object.
Definition: functions.php:463
getNamespaceFromPrefix($prefix)
pass it a prefix, it returns a namespace returns false if no namespace registered with the given pref...
Definition: nusoap.php:541
nusoap_parser class parses SOAP XML messages into native PHP values
Definition: nusoap.php:6425
getOperationData($operation, $bindingType='soap')
returns an associative array of data necessary for calling an operation
Definition: nusoap.php:3679
$url
if(!array_key_exists('domain', $_REQUEST)) $domain
Definition: resume.php:8
clearDebug()
clears the current debug data for this instance
Definition: nusoap.php:307
$response
$binding
$key
Definition: croninfo.php:18
fetchWSDL($wsdl)
fetches the WSDL document and parses it
Definition: nusoap.php:4588
$cols
Definition: xhr_table.php:11
$data
Definition: bench.php:6

Variable Documentation

◆ globalDebugLevel

if (!is_object( $GLOBALS[ '_transient'][ 'static'][ 'nusoap_base'])) $GLOBALS ['_transient']['static']['nusoap_base'] globalDebugLevel = 0

Definition at line 81 of file nusoap.php.