ILIAS  release_8 Revision v8.24
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
 Backward compatibility. More...
 
class  nusoap_xmlschema
 parses an XML Schema, allows access to it's data, other utility methods. More...
 
class  XMLSchema
 Backward compatibility. More...
 
class  soapval
 For creating serializable abstractions of native PHP types. 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
 Backward compatibility. 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
 Backward compatibility. 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(!isset($GLOBALS['_transient'])||!isset($GLOBALS['_transient']['static'])||!isset($GLOBALS['_transient']['static']['nusoap_base'])||!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 @access public

Definition at line 971 of file nusoap.php.

972{
973 $pattern = '/' .
974 '([0-9]{4})-' . // centuries & years CCYY-
975 '([0-9]{2})-' . // months MM-
976 '([0-9]{2})' . // days DD
977 'T' . // separator T
978 '([0-9]{2}):' . // hours hh:
979 '([0-9]{2}):' . // minutes mm:
980 '([0-9]{2})(\.[0-9]+)?' . // seconds ss.ss...
981 '(Z|[+\-][0-9]{2}:?[0-9]{2})?' . // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
982 '/';
983
984 if (preg_match($pattern, $datestr, $regs)) {
985 // not utc
986 if ($regs[8] != 'Z') {
987 $op = substr($regs[8], 0, 1);
988 $h = substr($regs[8], 1, 2);
989 $m = substr($regs[8], strlen($regs[8])-2, 2);
990 if ($op == '-') {
991 $regs[4] = $regs[4] + $h;
992 $regs[5] = $regs[5] + $m;
993 } elseif ($op == '+') {
994 $regs[4] = $regs[4] - $h;
995 $regs[5] = $regs[5] - $m;
996 }
997 }
998 return gmmktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
999 // return strtotime("$regs[1]-$regs[2]-$regs[3] $regs[4]:$regs[5]:$regs[6]Z");
1000 } else {
1001 return false;
1002 }
1003}

◆ 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 @access public

Definition at line 941 of file nusoap.php.

942{
943 $datestr = date('Y-m-d\TH:i:sO', $timestamp);
944 if ($utc) {
945 $pattern = '/' .
946 '([0-9]{4})-' . // centuries & years CCYY-
947 '([0-9]{2})-' . // months MM-
948 '([0-9]{2})' . // days DD
949 'T' . // separator T
950 '([0-9]{2}):' . // hours hh:
951 '([0-9]{2}):' . // minutes mm:
952 '([0-9]{2})(\.[0-9]*)?' . // seconds ss.ss...
953 '(Z|[+\-][0-9]{2}:?[0-9]{2})?' . // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
954 '/';
955
956 if (preg_match($pattern, $datestr, $regs)) {
957 return sprintf('%04d-%02d-%02dT%02d:%02d:%02dZ', $regs[1], $regs[2], $regs[3], $regs[4], $regs[5], $regs[6]);
958 }
959 return false;
960 } else {
961 return $datestr;
962 }
963}
foreach($mandatory_scripts as $file) $timestamp
Definition: buildRTE.php:70

References $timestamp.

◆ usleepWindows()

usleepWindows (   $usec)

sleeps some number of microseconds

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

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

Definition at line 1012 of file nusoap.php.

1013{
1014 $start = gettimeofday();
1015
1016 do {
1017 $stop = gettimeofday();
1018 $timePassed = 1000000 * ($stop['sec'] - $start['sec'])
1019 + $stop['usec'] - $start['usec'];
1020 } while ($timePassed < $usec);
1021}
1022
1023?><?php
1024
1025
1026
1035class nusoap_fault extends nusoap_base
1036{
1042 public $faultcode;
1048 public $faultactor;
1054 public $faultstring;
1060 public $faultdetail;
1061
1070 public function __construct($faultcode, $faultactor='', $faultstring='', $faultdetail='')
1071 {
1073 $this->faultcode = $faultcode;
1074 $this->faultactor = $faultactor;
1075 $this->faultstring = $faultstring;
1076 $this->faultdetail = $faultdetail;
1077 }
1078
1085 public function serialize()
1086 {
1087 $ns_string = '';
1088 foreach ($this->namespaces as $k => $v) {
1089 $ns_string .= "\n xmlns:$k=\"$v\"";
1090 }
1091 $return_msg =
1092 '<?xml version="1.0" encoding="' . $this->soap_defencoding . '"?>' .
1093 '<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"' . $ns_string . ">\n" .
1094 '<SOAP-ENV:Body>' .
1095 '<SOAP-ENV:Fault>' .
1096 $this->serialize_val($this->faultcode, 'faultcode') .
1097 $this->serialize_val($this->faultstring, 'faultstring') .
1098 $this->serialize_val($this->faultactor, 'faultactor') .
1099 $this->serialize_val($this->faultdetail, 'detail') .
1100 '</SOAP-ENV:Fault>' .
1101 '</SOAP-ENV:Body>' .
1102 '</SOAP-ENV:Envelope>';
1103 return $return_msg;
1104 }
1105}
1106
1110class soap_fault extends nusoap_fault
1111{
1112}
1113
1114?><?php
1115
1116
1117
1127class nusoap_xmlschema extends nusoap_base
1128{
1129 // files
1130 public $schema = '';
1131 public $xml = '';
1132 // namespaces
1133 public $enclosingNamespaces;
1134 // schema info
1135 public $schemaInfo = array();
1136 public $schemaTargetNamespace = '';
1137 // types, elements, attributes defined by the schema
1138 public $attributes = array();
1139 public $complexTypes = array();
1140 public $complexTypeStack = array();
1141 public $currentComplexType = null;
1142 public $elements = array();
1143 public $elementStack = array();
1144 public $currentElement = null;
1145 public $simpleTypes = array();
1146 public $simpleTypeStack = array();
1147 public $currentSimpleType = null;
1148 // imports
1149 public $imports = array();
1150 // parser vars
1151 public $parser;
1152 public $position = 0;
1153 public $depth = 0;
1154 public $depth_array = array();
1155 public $message = array();
1156 public $defaultNamespace = array();
1157
1166 public function __construct($schema='', $xml='', $namespaces=array())
1167 {
1169 $this->debug('nusoap_xmlschema class instantiated, inside constructor');
1170 // files
1171 $this->schema = $schema;
1172 $this->xml = $xml;
1173
1174 // namespaces
1175 $this->enclosingNamespaces = $namespaces;
1176 $this->namespaces = array_merge($this->namespaces, $namespaces);
1177
1178 // parse schema file
1179 if ($schema != '') {
1180 $this->debug('initial schema file: ' . $schema);
1181 $this->parseFile($schema, 'schema');
1182 }
1183
1184 // parse xml file
1185 if ($xml != '') {
1186 $this->debug('initial xml file: ' . $xml);
1187 $this->parseFile($xml, 'xml');
1188 }
1189 }
1190
1199 public function parseFile($xml, $type)
1200 {
1201 // parse xml file
1202 if ($xml != "") {
1203 $xmlStr = @join("", @file($xml));
1204 if ($xmlStr == "") {
1205 $msg = 'Error reading XML from ' . $xml;
1206 $this->setError($msg);
1207 $this->debug($msg);
1208 return false;
1209 } else {
1210 $this->debug("parsing $xml");
1211 $this->parseString($xmlStr, $type);
1212 $this->debug("done parsing $xml");
1213 return true;
1214 }
1215 }
1216 return false;
1217 }
1218
1226 public function parseString($xml, $type)
1227 {
1228 // parse xml string
1229 if ($xml != "") {
1230
1231 // Create an XML parser.
1232 $this->parser = xml_parser_create();
1233 // Set the options for parsing the XML data.
1234 xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
1235
1236 // Set the object for the parser.
1237 xml_set_object($this->parser, $this);
1238
1239 // Set the element handlers for the parser.
1240 if ($type == "schema") {
1241 xml_set_element_handler($this->parser, 'schemaStartElement', 'schemaEndElement');
1242 xml_set_character_data_handler($this->parser, 'schemaCharacterData');
1243 } elseif ($type == "xml") {
1244 xml_set_element_handler($this->parser, 'xmlStartElement', 'xmlEndElement');
1245 xml_set_character_data_handler($this->parser, 'xmlCharacterData');
1246 }
1247
1248 // Parse the XML file.
1249 if (!xml_parse($this->parser, $xml, true)) {
1250 // Display an error message.
1251 $errstr = sprintf(
1252 'XML error parsing XML schema on line %d: %s',
1253 xml_get_current_line_number($this->parser),
1254 xml_error_string(xml_get_error_code($this->parser))
1255 );
1256 $this->debug($errstr);
1257 $this->debug("XML payload:\n" . $xml);
1258 $this->setError($errstr);
1259 }
1260
1261 xml_parser_free($this->parser);
1262 } else {
1263 $this->debug('no xml passed to parseString()!!');
1264 $this->setError('no xml passed to parseString()!!');
1265 }
1266 }
1267
1275 public function CreateTypeName($ename)
1276 {
1277 $scope = '';
1278 for ($i = 0; $i < count($this->complexTypeStack); $i++) {
1279 $scope .= $this->complexTypeStack[$i] . '_';
1280 }
1281 return $scope . $ename . '_ContainedType';
1282 }
1283
1292 public function schemaStartElement($parser, $name, $attrs)
1293 {
1294
1295 // position in the total number of elements, starting from 0
1296 $pos = $this->position++;
1297 $depth = $this->depth++;
1298 // set self as current value for this depth
1299 $this->depth_array[$depth] = $pos;
1300 $this->message[$pos] = array('cdata' => '');
1301 if ($depth > 0) {
1302 $this->defaultNamespace[$pos] = $this->defaultNamespace[$this->depth_array[$depth - 1]];
1303 } else {
1304 $this->defaultNamespace[$pos] = false;
1305 }
1306
1307 // get element prefix
1308 if ($prefix = $this->getPrefix($name)) {
1309 // get unqualified name
1310 $name = $this->getLocalPart($name);
1311 } else {
1312 $prefix = '';
1313 }
1314
1315 // loop thru attributes, expanding, and registering namespace declarations
1316 if (count($attrs) > 0) {
1317 foreach ($attrs as $k => $v) {
1318 // if ns declarations, add to class level array of valid namespaces
1319 if (preg_match('/^xmlns/', $k)) {
1320 //$this->xdebug("$k: $v");
1321 //$this->xdebug('ns_prefix: '.$this->getPrefix($k));
1322 if ($ns_prefix = substr(strrchr($k, ':'), 1)) {
1323 //$this->xdebug("Add namespace[$ns_prefix] = $v");
1324 $this->namespaces[$ns_prefix] = $v;
1325 } else {
1326 $this->defaultNamespace[$pos] = $v;
1327 if (! $this->getPrefixFromNamespace($v)) {
1328 $this->namespaces['ns' . (count($this->namespaces)+1)] = $v;
1329 }
1330 }
1331 if ($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema') {
1332 $this->XMLSchemaVersion = $v;
1333 $this->namespaces['xsi'] = $v . '-instance';
1334 }
1335 }
1336 }
1337 foreach ($attrs as $k => $v) {
1338 // expand each attribute
1339 $k = strpos($k, ':') ? $this->expandQname($k) : $k;
1340 $v = strpos($v, ':') ? $this->expandQname($v) : $v;
1341 $eAttrs[$k] = $v;
1342 }
1343 $attrs = $eAttrs;
1344 } else {
1345 $attrs = array();
1346 }
1347 // find status, register data
1348 switch ($name) {
1349 case 'all': // (optional) compositor content for a complexType
1350 case 'choice':
1351 case 'group':
1352 case 'sequence':
1353 //$this->xdebug("compositor $name for currentComplexType: $this->currentComplexType and currentElement: $this->currentElement");
1354 $this->complexTypes[$this->currentComplexType]['compositor'] = $name;
1355 //if($name == 'all' || $name == 'sequence'){
1356 // $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
1357 //}
1358 break;
1359 case 'attribute': // complexType attribute
1360 //$this->xdebug("parsing attribute $attrs[name] $attrs[ref] of value: ".$attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']);
1361 $this->xdebug("parsing attribute:");
1362 $this->appendDebug($this->varDump($attrs));
1363 if (!isset($attrs['form'])) {
1364 $attrs['form'] = $this->schemaInfo['attributeFormDefault'];
1365 }
1366 if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
1367 $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1368 if (!strpos($v, ':')) {
1369 // no namespace in arrayType attribute value...
1370 if ($this->defaultNamespace[$pos]) {
1371 // ...so use the default
1372 $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'] = $this->defaultNamespace[$pos] . ':' . $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1373 }
1374 }
1375 }
1376 if (isset($attrs['name'])) {
1377 $this->attributes[$attrs['name']] = $attrs;
1378 $aname = $attrs['name'];
1379 } elseif (isset($attrs['ref']) && $attrs['ref'] == 'http://schemas.xmlsoap.org/soap/encoding/:arrayType') {
1380 if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
1381 $aname = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1382 } else {
1383 $aname = '';
1384 }
1385 } elseif (isset($attrs['ref'])) {
1386 $aname = $attrs['ref'];
1387 $this->attributes[$attrs['ref']] = $attrs;
1388 }
1389
1390 if ($this->currentComplexType) { // This should *always* be
1391 $this->complexTypes[$this->currentComplexType]['attrs'][$aname] = $attrs;
1392 }
1393 // arrayType attribute
1394 if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']) || $this->getLocalPart($aname) == 'arrayType') {
1395 $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
1396 $prefix = $this->getPrefix($aname);
1397 if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
1398 $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1399 } else {
1400 $v = '';
1401 }
1402 if (strpos($v, '[,]')) {
1403 $this->complexTypes[$this->currentComplexType]['multidimensional'] = true;
1404 }
1405 $v = substr($v, 0, strpos($v, '[')); // clip the []
1406 if (!strpos($v, ':') && isset($this->typemap[$this->XMLSchemaVersion][$v])) {
1407 $v = $this->XMLSchemaVersion . ':' . $v;
1408 }
1409 $this->complexTypes[$this->currentComplexType]['arrayType'] = $v;
1410 }
1411 break;
1412 case 'complexContent': // (optional) content for a complexType
1413 break;
1414 case 'complexType':
1415 array_push($this->complexTypeStack, $this->currentComplexType);
1416 if (isset($attrs['name'])) {
1417 // TODO: what is the scope of named complexTypes that appear
1418 // nested within other c complexTypes?
1419 $this->xdebug('processing named complexType ' . $attrs['name']);
1420 //$this->currentElement = false;
1421 $this->currentComplexType = $attrs['name'];
1422 $this->complexTypes[$this->currentComplexType] = $attrs;
1423 $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
1424 // This is for constructs like
1425 // <complexType name="ListOfString" base="soap:Array">
1426 // <sequence>
1427 // <element name="string" type="xsd:string"
1428 // minOccurs="0" maxOccurs="unbounded" />
1429 // </sequence>
1430 // </complexType>
1431 if (isset($attrs['base']) && preg_match('/:Array$/', $attrs['base'])) {
1432 $this->xdebug('complexType is unusual array');
1433 $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
1434 } else {
1435 $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
1436 }
1437 } else {
1438 $name = $this->CreateTypeName($this->currentElement);
1439 $this->xdebug('processing unnamed complexType for element ' . $this->currentElement . ' named ' . $name);
1440 $this->currentComplexType = $name;
1441 //$this->currentElement = false;
1442 $this->complexTypes[$this->currentComplexType] = $attrs;
1443 $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
1444 // This is for constructs like
1445 // <complexType name="ListOfString" base="soap:Array">
1446 // <sequence>
1447 // <element name="string" type="xsd:string"
1448 // minOccurs="0" maxOccurs="unbounded" />
1449 // </sequence>
1450 // </complexType>
1451 if (isset($attrs['base']) && preg_match('/:Array$/', $attrs['base'])) {
1452 $this->xdebug('complexType is unusual array');
1453 $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
1454 } else {
1455 $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
1456 }
1457 }
1458 break;
1459 case 'element':
1460 array_push($this->elementStack, $this->currentElement);
1461 if (!isset($attrs['form'])) {
1462 $attrs['form'] = $this->schemaInfo['elementFormDefault'];
1463 }
1464 if (isset($attrs['type'])) {
1465 $this->xdebug("processing typed element " . $attrs['name'] . " of type " . $attrs['type']);
1466 if (! $this->getPrefix($attrs['type'])) {
1467 if ($this->defaultNamespace[$pos]) {
1468 $attrs['type'] = $this->defaultNamespace[$pos] . ':' . $attrs['type'];
1469 $this->xdebug('used default namespace to make type ' . $attrs['type']);
1470 }
1471 }
1472 // This is for constructs like
1473 // <complexType name="ListOfString" base="soap:Array">
1474 // <sequence>
1475 // <element name="string" type="xsd:string"
1476 // minOccurs="0" maxOccurs="unbounded" />
1477 // </sequence>
1478 // </complexType>
1479 if ($this->currentComplexType && $this->complexTypes[$this->currentComplexType]['phpType'] == 'array') {
1480 $this->xdebug('arrayType for unusual array is ' . $attrs['type']);
1481 $this->complexTypes[$this->currentComplexType]['arrayType'] = $attrs['type'];
1482 }
1483 $this->currentElement = $attrs['name'];
1484 $ename = $attrs['name'];
1485 } elseif (isset($attrs['ref'])) {
1486 $this->xdebug("processing element as ref to " . $attrs['ref']);
1487 $this->currentElement = "ref to " . $attrs['ref'];
1488 $ename = $this->getLocalPart($attrs['ref']);
1489 } else {
1490 $type = $this->CreateTypeName($this->currentComplexType . '_' . $attrs['name']);
1491 $this->xdebug("processing untyped element " . $attrs['name'] . ' type ' . $type);
1492 $this->currentElement = $attrs['name'];
1493 $attrs['type'] = $this->schemaTargetNamespace . ':' . $type;
1494 $ename = $attrs['name'];
1495 }
1496 if (isset($ename) && $this->currentComplexType) {
1497 $this->xdebug("add element $ename to complexType $this->currentComplexType");
1498 $this->complexTypes[$this->currentComplexType]['elements'][$ename] = $attrs;
1499 } elseif (!isset($attrs['ref'])) {
1500 $this->xdebug("add element $ename to elements array");
1501 $this->elements[ $attrs['name'] ] = $attrs;
1502 $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
1503 }
1504 break;
1505 case 'enumeration': // restriction value list member
1506 $this->xdebug('enumeration ' . $attrs['value']);
1507 if ($this->currentSimpleType) {
1508 $this->simpleTypes[$this->currentSimpleType]['enumeration'][] = $attrs['value'];
1509 } elseif ($this->currentComplexType) {
1510 $this->complexTypes[$this->currentComplexType]['enumeration'][] = $attrs['value'];
1511 }
1512 break;
1513 case 'extension': // simpleContent or complexContent type extension
1514 $this->xdebug('extension ' . $attrs['base']);
1515 if ($this->currentComplexType) {
1516 $this->complexTypes[$this->currentComplexType]['extensionBase'] = $attrs['base'];
1517 }
1518 break;
1519 case 'import':
1520 if (isset($attrs['schemaLocation'])) {
1521 //$this->xdebug('import namespace ' . $attrs['namespace'] . ' from ' . $attrs['schemaLocation']);
1522 $this->imports[$attrs['namespace']][] = array('location' => $attrs['schemaLocation'], 'loaded' => false);
1523 } else {
1524 //$this->xdebug('import namespace ' . $attrs['namespace']);
1525 $this->imports[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
1526 if (! $this->getPrefixFromNamespace($attrs['namespace'])) {
1527 $this->namespaces['ns' . (count($this->namespaces)+1)] = $attrs['namespace'];
1528 }
1529 }
1530 break;
1531 case 'list': // simpleType value list
1532 break;
1533 case 'restriction': // simpleType, simpleContent or complexContent value restriction
1534 $this->xdebug('restriction ' . $attrs['base']);
1535 if ($this->currentSimpleType) {
1536 $this->simpleTypes[$this->currentSimpleType]['type'] = $attrs['base'];
1537 } elseif ($this->currentComplexType) {
1538 $this->complexTypes[$this->currentComplexType]['restrictionBase'] = $attrs['base'];
1539 if (strstr($attrs['base'], ':') == ':Array') {
1540 $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
1541 }
1542 }
1543 break;
1544 case 'schema':
1545 $this->schemaInfo = $attrs;
1546 $this->schemaInfo['schemaVersion'] = $this->getNamespaceFromPrefix($prefix);
1547 if (isset($attrs['targetNamespace'])) {
1548 $this->schemaTargetNamespace = $attrs['targetNamespace'];
1549 }
1550 if (!isset($attrs['elementFormDefault'])) {
1551 $this->schemaInfo['elementFormDefault'] = 'unqualified';
1552 }
1553 if (!isset($attrs['attributeFormDefault'])) {
1554 $this->schemaInfo['attributeFormDefault'] = 'unqualified';
1555 }
1556 break;
1557 case 'simpleContent': // (optional) content for a complexType
1558 break;
1559 case 'simpleType':
1560 array_push($this->simpleTypeStack, $this->currentSimpleType);
1561 if (isset($attrs['name'])) {
1562 $this->xdebug("processing simpleType for name " . $attrs['name']);
1563 $this->currentSimpleType = $attrs['name'];
1564 $this->simpleTypes[ $attrs['name'] ] = $attrs;
1565 $this->simpleTypes[ $attrs['name'] ]['typeClass'] = 'simpleType';
1566 $this->simpleTypes[ $attrs['name'] ]['phpType'] = 'scalar';
1567 } else {
1568 $name = $this->CreateTypeName($this->currentComplexType . '_' . $this->currentElement);
1569 $this->xdebug('processing unnamed simpleType for element ' . $this->currentElement . ' named ' . $name);
1570 $this->currentSimpleType = $name;
1571 //$this->currentElement = false;
1572 $this->simpleTypes[$this->currentSimpleType] = $attrs;
1573 $this->simpleTypes[$this->currentSimpleType]['phpType'] = 'scalar';
1574 }
1575 break;
1576 case 'union': // simpleType type list
1577 break;
1578 default:
1579 //$this->xdebug("do not have anything to do for element $name");
1580 }
1581 }
1582
1590 public function schemaEndElement($parser, $name)
1591 {
1592 // bring depth down a notch
1593 $this->depth--;
1594 // position of current element is equal to the last value left in depth_array for my depth
1595 if (isset($this->depth_array[$this->depth])) {
1596 $pos = $this->depth_array[$this->depth];
1597 }
1598 // get element prefix
1599 if ($prefix = $this->getPrefix($name)) {
1600 // get unqualified name
1601 $name = $this->getLocalPart($name);
1602 } else {
1603 $prefix = '';
1604 }
1605 // move on...
1606 if ($name == 'complexType') {
1607 $this->xdebug('done processing complexType ' . ($this->currentComplexType ? $this->currentComplexType : '(unknown)'));
1608 $this->currentComplexType = array_pop($this->complexTypeStack);
1609 //$this->currentElement = false;
1610 }
1611 if ($name == 'element') {
1612 $this->xdebug('done processing element ' . ($this->currentElement ? $this->currentElement : '(unknown)'));
1613 $this->currentElement = array_pop($this->elementStack);
1614 }
1615 if ($name == 'simpleType') {
1616 $this->xdebug('done processing simpleType ' . ($this->currentSimpleType ? $this->currentSimpleType : '(unknown)'));
1617 $this->currentSimpleType = array_pop($this->simpleTypeStack);
1618 }
1619 }
1620
1628 public function schemaCharacterData($parser, $data)
1629 {
1630 $pos = $this->depth_array[$this->depth - 1];
1631 $this->message[$pos]['cdata'] .= $data;
1632 }
1633
1639 public function serializeSchema()
1640 {
1641 $schemaPrefix = $this->getPrefixFromNamespace($this->XMLSchemaVersion);
1642 $xml = '';
1643 // imports
1644 if (sizeof($this->imports) > 0) {
1645 foreach ($this->imports as $ns => $list) {
1646 foreach ($list as $ii) {
1647 if ($ii['location'] != '') {
1648 $xml .= " <$schemaPrefix:import location=\"" . $ii['location'] . '" namespace="' . $ns . "\" />\n";
1649 } else {
1650 $xml .= " <$schemaPrefix:import namespace=\"" . $ns . "\" />\n";
1651 }
1652 }
1653 }
1654 }
1655 // complex types
1656 foreach ($this->complexTypes as $typeName => $attrs) {
1657 $contentStr = '';
1658 // serialize child elements
1659 if (isset($attrs['elements']) && (count($attrs['elements']) > 0)) {
1660 foreach ($attrs['elements'] as $element => $eParts) {
1661 if (isset($eParts['ref'])) {
1662 $contentStr .= " <$schemaPrefix:element ref=\"$element\"/>\n";
1663 } else {
1664 $contentStr .= " <$schemaPrefix:element name=\"$element\" type=\"" . $this->contractQName($eParts['type']) . "\"";
1665 foreach ($eParts as $aName => $aValue) {
1666 // handle, e.g., abstract, default, form, minOccurs, maxOccurs, nillable
1667 if ($aName != 'name' && $aName != 'type') {
1668 $contentStr .= " $aName=\"$aValue\"";
1669 }
1670 }
1671 $contentStr .= "/>\n";
1672 }
1673 }
1674 // compositor wraps elements
1675 if (isset($attrs['compositor']) && ($attrs['compositor'] != '')) {
1676 $contentStr = " <$schemaPrefix:$attrs[compositor]>\n" . $contentStr . " </$schemaPrefix:$attrs[compositor]>\n";
1677 }
1678 }
1679 // attributes
1680 if (isset($attrs['attrs']) && (count($attrs['attrs']) >= 1)) {
1681 foreach ($attrs['attrs'] as $attr => $aParts) {
1682 $contentStr .= " <$schemaPrefix:attribute";
1683 foreach ($aParts as $a => $v) {
1684 if ($a == 'ref' || $a == 'type') {
1685 $contentStr .= " $a=\"" . $this->contractQName($v) . '"';
1686 } elseif ($a == 'http://schemas.xmlsoap.org/wsdl/:arrayType') {
1687 $this->usedNamespaces['wsdl'] = $this->namespaces['wsdl'];
1688 $contentStr .= ' wsdl:arrayType="' . $this->contractQName($v) . '"';
1689 } else {
1690 $contentStr .= " $a=\"$v\"";
1691 }
1692 }
1693 $contentStr .= "/>\n";
1694 }
1695 }
1696 // if restriction
1697 if (isset($attrs['restrictionBase']) && $attrs['restrictionBase'] != '') {
1698 $contentStr = " <$schemaPrefix:restriction base=\"" . $this->contractQName($attrs['restrictionBase']) . "\">\n" . $contentStr . " </$schemaPrefix:restriction>\n";
1699 // complex or simple content
1700 if ((isset($attrs['elements']) && count($attrs['elements']) > 0) || (isset($attrs['attrs']) && count($attrs['attrs']) > 0)) {
1701 $contentStr = " <$schemaPrefix:complexContent>\n" . $contentStr . " </$schemaPrefix:complexContent>\n";
1702 }
1703 }
1704 // finalize complex type
1705 if ($contentStr != '') {
1706 $contentStr = " <$schemaPrefix:complexType name=\"$typeName\">\n" . $contentStr . " </$schemaPrefix:complexType>\n";
1707 } else {
1708 $contentStr = " <$schemaPrefix:complexType name=\"$typeName\"/>\n";
1709 }
1710 $xml .= $contentStr;
1711 }
1712 // simple types
1713 if (isset($this->simpleTypes) && count($this->simpleTypes) > 0) {
1714 foreach ($this->simpleTypes as $typeName => $eParts) {
1715 $xml .= " <$schemaPrefix:simpleType name=\"$typeName\">\n <$schemaPrefix:restriction base=\"" . $this->contractQName($eParts['type']) . "\">\n";
1716 if (isset($eParts['enumeration'])) {
1717 foreach ($eParts['enumeration'] as $e) {
1718 $xml .= " <$schemaPrefix:enumeration value=\"$e\"/>\n";
1719 }
1720 }
1721 $xml .= " </$schemaPrefix:restriction>\n </$schemaPrefix:simpleType>";
1722 }
1723 }
1724 // elements
1725 if (isset($this->elements) && count($this->elements) > 0) {
1726 foreach ($this->elements as $element => $eParts) {
1727 $xml .= " <$schemaPrefix:element name=\"$element\" type=\"" . $this->contractQName($eParts['type']) . "\"/>\n";
1728 }
1729 }
1730 // attributes
1731 if (isset($this->attributes) && count($this->attributes) > 0) {
1732 foreach ($this->attributes as $attr => $aParts) {
1733 $xml .= " <$schemaPrefix:attribute name=\"$attr\" type=\"" . $this->contractQName($aParts['type']) . "\"\n/>";
1734 }
1735 }
1736 // finish 'er up
1737 $attr = '';
1738 foreach ($this->schemaInfo as $k => $v) {
1739 if ($k == 'elementFormDefault' || $k == 'attributeFormDefault') {
1740 $attr .= " $k=\"$v\"";
1741 }
1742 }
1743 $el = "<$schemaPrefix:schema$attr targetNamespace=\"$this->schemaTargetNamespace\"\n";
1744 foreach (array_diff($this->usedNamespaces, $this->enclosingNamespaces) as $nsp => $ns) {
1745 $el .= " xmlns:$nsp=\"$ns\"";
1746 }
1747 $xml = $el . ">\n" . $xml . "</$schemaPrefix:schema>\n";
1748 return $xml;
1749 }
1750
1757 public function xdebug($string)
1758 {
1759 $this->debug('<' . $this->schemaTargetNamespace . '> ' . $string);
1760 }
1761
1774 public function getPHPType($type, $ns)
1775 {
1776 if (isset($this->typemap[$ns][$type])) {
1777 //print "found type '$type' and ns $ns in typemap<br>";
1778 return $this->typemap[$ns][$type];
1779 } elseif (isset($this->complexTypes[$type])) {
1780 //print "getting type '$type' and ns $ns from complexTypes array<br>";
1781 return $this->complexTypes[$type]['phpType'];
1782 }
1783 return false;
1784 }
1785
1808 public function getTypeDef($type)
1809 {
1810 //$this->debug("in getTypeDef for type $type");
1811 if (substr($type, -1) == '^') {
1812 $is_element = 1;
1813 $type = substr($type, 0, -1);
1814 } else {
1815 $is_element = 0;
1816 }
1817
1818 if ((! $is_element) && isset($this->complexTypes[$type])) {
1819 $this->xdebug("in getTypeDef, found complexType $type");
1820 return $this->complexTypes[$type];
1821 } elseif ((! $is_element) && isset($this->simpleTypes[$type])) {
1822 $this->xdebug("in getTypeDef, found simpleType $type");
1823 if (!isset($this->simpleTypes[$type]['phpType'])) {
1824 // get info for type to tack onto the simple type
1825 // TODO: can this ever really apply (i.e. what is a simpleType really?)
1826 $uqType = substr($this->simpleTypes[$type]['type'], strrpos($this->simpleTypes[$type]['type'], ':') + 1);
1827 $ns = substr($this->simpleTypes[$type]['type'], 0, strrpos($this->simpleTypes[$type]['type'], ':'));
1828 $etype = $this->getTypeDef($uqType);
1829 if ($etype) {
1830 $this->xdebug("in getTypeDef, found type for simpleType $type:");
1831 $this->xdebug($this->varDump($etype));
1832 if (isset($etype['phpType'])) {
1833 $this->simpleTypes[$type]['phpType'] = $etype['phpType'];
1834 }
1835 if (isset($etype['elements'])) {
1836 $this->simpleTypes[$type]['elements'] = $etype['elements'];
1837 }
1838 }
1839 }
1840 return $this->simpleTypes[$type];
1841 } elseif (isset($this->elements[$type])) {
1842 $this->xdebug("in getTypeDef, found element $type");
1843 if (!isset($this->elements[$type]['phpType'])) {
1844 // get info for type to tack onto the element
1845 $uqType = substr($this->elements[$type]['type'], strrpos($this->elements[$type]['type'], ':') + 1);
1846 $ns = substr($this->elements[$type]['type'], 0, strrpos($this->elements[$type]['type'], ':'));
1847 $etype = $this->getTypeDef($uqType);
1848 if ($etype) {
1849 $this->xdebug("in getTypeDef, found type for element $type:");
1850 $this->xdebug($this->varDump($etype));
1851 if (isset($etype['phpType'])) {
1852 $this->elements[$type]['phpType'] = $etype['phpType'];
1853 }
1854 if (isset($etype['elements'])) {
1855 $this->elements[$type]['elements'] = $etype['elements'];
1856 }
1857 } elseif ($ns == 'http://www.w3.org/2001/XMLSchema') {
1858 $this->xdebug("in getTypeDef, element $type is an XSD type");
1859 $this->elements[$type]['phpType'] = 'scalar';
1860 }
1861 }
1862 return $this->elements[$type];
1863 } elseif (isset($this->attributes[$type])) {
1864 $this->xdebug("in getTypeDef, found attribute $type");
1865 return $this->attributes[$type];
1866 } elseif (preg_match('/_ContainedType$/', $type)) {
1867 $this->xdebug("in getTypeDef, have an untyped element $type");
1868 $typeDef['typeClass'] = 'simpleType';
1869 $typeDef['phpType'] = 'scalar';
1870 $typeDef['type'] = 'http://www.w3.org/2001/XMLSchema:string';
1871 return $typeDef;
1872 }
1873 $this->xdebug("in getTypeDef, did not find $type");
1874 return false;
1875 }
1876
1885 public function serializeTypeDef($type)
1886 {
1887 //print "in sTD() for type $type<br>";
1888 if ($typeDef = $this->getTypeDef($type)) {
1889 $str .= '<' . $type;
1890 if (is_array($typeDef['attrs'])) {
1891 foreach ($typeDef['attrs'] as $attName => $data) {
1892 $str .= " $attName=\"{type = " . $data['type'] . "}\"";
1893 }
1894 }
1895 $str .= " xmlns=\"" . $this->schema['targetNamespace'] . "\"";
1896 if (count($typeDef['elements']) > 0) {
1897 $str .= ">";
1898 foreach ($typeDef['elements'] as $element => $eData) {
1899 $str .= $this->serializeTypeDef($element);
1900 }
1901 $str .= "</$type>";
1902 } elseif ($typeDef['typeClass'] == 'element') {
1903 $str .= "></$type>";
1904 } else {
1905 $str .= "/>";
1906 }
1907 return $str;
1908 }
1909 return false;
1910 }
1911
1922 public function typeToForm($name, $type)
1923 {
1924 // get typedef
1925 if ($typeDef = $this->getTypeDef($type)) {
1926 // if struct
1927 if ($typeDef['phpType'] == 'struct') {
1928 $buffer .= '<table>';
1929 foreach ($typeDef['elements'] as $child => $childDef) {
1930 $buffer .= "
1931 <tr><td align='right'>$childDef[name] (type: " . $this->getLocalPart($childDef['type']) . "):</td>
1932 <td><input type='text' name='parameters[" . $name . "][$childDef[name]]'></td></tr>";
1933 }
1934 $buffer .= '</table>';
1935 // if array
1936 } elseif ($typeDef['phpType'] == 'array') {
1937 $buffer .= '<table>';
1938 for ($i=0;$i < 3; $i++) {
1939 $buffer .= "
1940 <tr><td align='right'>array item (type: $typeDef[arrayType]):</td>
1941 <td><input type='text' name='parameters[" . $name . "][]'></td></tr>";
1942 }
1943 $buffer .= '</table>';
1944 // if scalar
1945 } else {
1946 $buffer .= "<input type='text' name='parameters[$name]'>";
1947 }
1948 } else {
1949 $buffer .= "<input type='text' name='parameters[$name]'>";
1950 }
1951 return $buffer;
1952 }
1953
1995 public function addComplexType($name, $typeClass='complexType', $phpType='array', $compositor='', $restrictionBase='', $elements=array(), $attrs=array(), $arrayType='')
1996 {
1997 $this->complexTypes[$name] = array(
1998 'name' => $name,
1999 'typeClass' => $typeClass,
2000 'phpType' => $phpType,
2001 'compositor'=> $compositor,
2002 'restrictionBase' => $restrictionBase,
2003 'elements' => $elements,
2004 'attrs' => $attrs,
2005 'arrayType' => $arrayType
2006 );
2007
2008 $this->xdebug("addComplexType $name:");
2009 $this->appendDebug($this->varDump($this->complexTypes[$name]));
2010 }
2011
2024 public function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array())
2025 {
2026 $this->simpleTypes[$name] = array(
2027 'name' => $name,
2028 'typeClass' => $typeClass,
2029 'phpType' => $phpType,
2030 'type' => $restrictionBase,
2031 'enumeration' => $enumeration
2032 );
2033
2034 $this->xdebug("addSimpleType $name:");
2035 $this->appendDebug($this->varDump($this->simpleTypes[$name]));
2036 }
2037
2045 public function addElement($attrs)
2046 {
2047 if (! $this->getPrefix($attrs['type'])) {
2048 $attrs['type'] = $this->schemaTargetNamespace . ':' . $attrs['type'];
2049 }
2050 $this->elements[ $attrs['name'] ] = $attrs;
2051 $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
2052
2053 $this->xdebug("addElement " . $attrs['name']);
2054 $this->appendDebug($this->varDump($this->elements[ $attrs['name'] ]));
2055 }
2056}
2057
2061class XMLSchema extends nusoap_xmlschema
2062{
2063}
2064
2065?><?php
2066
2067
2068
2080class soapval extends nusoap_base
2081{
2088 public $name;
2095 public $type;
2102 public $value;
2109 public $element_ns;
2116 public $type_ns;
2123 public $attributes;
2124
2136 public function __construct($name='soapval', $type=false, $value=-1, $element_ns=false, $type_ns=false, $attributes=false)
2137 {
2139 $this->name = $name;
2140 $this->type = $type;
2141 $this->value = $value;
2142 $this->element_ns = $element_ns;
2143 $this->type_ns = $type_ns;
2144 $this->attributes = $attributes;
2145 }
2146
2154 public function serialize($use='encoded')
2155 {
2156 return $this->serialize_val($this->value, $this->name, $this->type, $this->element_ns, $this->type_ns, $this->attributes, $use, true);
2157 }
2158
2165 public function decode()
2166 {
2167 return $this->value;
2168 }
2169}
2170
2171
2172
2173?><?php
2174
2175
2176
2186class soap_transport_http extends nusoap_base
2187{
2188 public $url = '';
2189 public $uri = '';
2190 public $digest_uri = '';
2191 public $scheme = '';
2192 public $host = '';
2193 public $port = '';
2194 public $path = '';
2195 public $request_method = 'POST';
2196 public $protocol_version = '1.0';
2197 public $encoding = '';
2198 public $outgoing_headers = array();
2199 public $incoming_headers = array();
2200 public $incoming_cookies = array();
2201 public $outgoing_payload = '';
2202 public $incoming_payload = '';
2203 public $response_status_line; // HTTP response status line
2204 public $useSOAPAction = true;
2205 public $persistentConnection = false;
2206 public $ch = false; // cURL handle
2207 public $ch_options = array(); // cURL custom options
2208 public $use_curl = false; // force cURL use
2209 public $proxy = null; // proxy information (associative array)
2210 public $username = '';
2211 public $password = '';
2212 public $authtype = '';
2213 public $digestRequest = array();
2214 public $certRequest = array(); // keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional)
2215 // cainfofile: certificate authority file, e.g. '$pathToPemFiles/rootca.pem'
2216 // sslcertfile: SSL certificate file, e.g. '$pathToPemFiles/mycert.pem'
2217 // sslkeyfile: SSL key file, e.g. '$pathToPemFiles/mykey.pem'
2218 // passphrase: SSL key password/passphrase
2219 // certpassword: SSL certificate password
2220 // verifypeer: default is 1
2221 // verifyhost: default is 1
2222
2231 public function __construct($url, $curl_options = null, $use_curl = false)
2232 {
2234 $this->debug("ctor url=$url use_curl=$use_curl curl_options:");
2235 $this->appendDebug($this->varDump($curl_options));
2236 $this->setURL($url);
2237 if (is_array($curl_options)) {
2238 $this->ch_options = $curl_options;
2239 }
2240 $this->use_curl = $use_curl;
2241 preg_match('/\$Revisio' . 'n: ([^ ]+)/', $this->revision, $rev);
2242 // begin-patch php8
2243 $this->setHeader('User-Agent', $this->title . '/' . $this->version . ' (' . ($rev[1] ?? '1.1') . ')');
2244 }
2245
2253 public function setCurlOption($option, $value)
2254 {
2255 $this->debug("setCurlOption option=$option, value=");
2256 $this->appendDebug($this->varDump($value));
2257 curl_setopt($this->ch, $option, $value);
2258 }
2259
2267 public function setHeader($name, $value)
2268 {
2269 $this->outgoing_headers[$name] = $value;
2270 $this->debug("set header $name: $value");
2271 }
2272
2279 public function unsetHeader($name)
2280 {
2281 if (isset($this->outgoing_headers[$name])) {
2282 $this->debug("unset header $name");
2283 unset($this->outgoing_headers[$name]);
2284 }
2285 }
2286
2293 public function setURL($url)
2294 {
2295 $this->url = $url;
2296
2297 $u = parse_url($url);
2298 foreach ($u as $k => $v) {
2299 $this->debug("parsed URL $k = $v");
2300 $this->$k = $v;
2301 }
2302
2303 // add any GET params to path
2304 if (isset($u['query']) && $u['query'] != '') {
2305 $this->path .= '?' . $u['query'];
2306 }
2307
2308 // set default port
2309 if (!isset($u['port'])) {
2310 if ($u['scheme'] == 'https') {
2311 $this->port = 443;
2312 } else {
2313 $this->port = 80;
2314 }
2315 }
2316
2317 $this->uri = $this->path;
2318 $this->digest_uri = $this->uri;
2319
2320 // build headers
2321 if (!isset($u['port'])) {
2322 $this->setHeader('Host', $this->host);
2323 } else {
2324 $this->setHeader('Host', $this->host . ':' . $this->port);
2325 }
2326
2327 if (isset($u['user']) && $u['user'] != '') {
2328 $this->setCredentials(urldecode($u['user']), isset($u['pass']) ? urldecode($u['pass']) : '');
2329 }
2330 }
2331
2338 public function io_method()
2339 {
2340 if ($this->use_curl || ($this->scheme == 'https') || ($this->scheme == 'http' && $this->authtype == 'ntlm') || ($this->scheme == 'http' && is_array($this->proxy) && $this->proxy['authtype'] == 'ntlm')) {
2341 return 'curl';
2342 }
2343 if (($this->scheme == 'http' || $this->scheme == 'ssl') && $this->authtype != 'ntlm' && (!is_array($this->proxy) || $this->proxy['authtype'] != 'ntlm')) {
2344 return 'socket';
2345 }
2346 return 'unknown';
2347 }
2348
2357 public function connect($connection_timeout=0, $response_timeout=30)
2358 {
2359 // For PHP 4.3 with OpenSSL, change https scheme to ssl, then treat like
2360 // "regular" socket.
2361 // TODO: disabled for now because OpenSSL must be *compiled* in (not just
2362 // loaded), and until PHP5 stream_get_wrappers is not available.
2363 // if ($this->scheme == 'https') {
2364 // if (version_compare(phpversion(), '4.3.0') >= 0) {
2365 // if (extension_loaded('openssl')) {
2366 // $this->scheme = 'ssl';
2367 // $this->debug('Using SSL over OpenSSL');
2368 // }
2369 // }
2370 // }
2371 $this->debug("connect connection_timeout $connection_timeout, response_timeout $response_timeout, scheme $this->scheme, host $this->host, port $this->port");
2372 if ($this->io_method() == 'socket') {
2373 if (!is_array($this->proxy)) {
2376 } else {
2377 $host = $this->proxy['host'];
2378 $port = $this->proxy['port'];
2379 }
2380
2381 // use persistent connection
2382 if ($this->persistentConnection && isset($this->fp) && is_resource($this->fp)) {
2383 if (!feof($this->fp)) {
2384 $this->debug('Re-use persistent connection');
2385 return true;
2386 }
2387 fclose($this->fp);
2388 $this->debug('Closed persistent connection at EOF');
2389 }
2390
2391 // munge host if using OpenSSL
2392 if ($this->scheme == 'ssl') {
2393 $host = 'ssl://' . $host;
2394 }
2395 $this->debug('calling fsockopen with host ' . $host . ' connection_timeout ' . $connection_timeout);
2396
2397 // open socket
2398 if ($connection_timeout > 0) {
2399 $this->fp = @fsockopen($host, $this->port, $this->errno, $this->error_str, $connection_timeout);
2400 } else {
2401 $this->fp = @fsockopen($host, $this->port, $this->errno, $this->error_str);
2402 }
2403
2404 // test pointer
2405 if (!$this->fp) {
2406 $msg = 'Couldn\'t open socket connection to server ' . $this->url;
2407 if ($this->errno) {
2408 $msg .= ', Error (' . $this->errno . '): ' . $this->error_str;
2409 } else {
2410 $msg .= ' prior to connect(). This is often a problem looking up the host name.';
2411 }
2412 $this->debug($msg);
2413 $this->setError($msg);
2414 return false;
2415 }
2416
2417 // set response timeout
2418 $this->debug('set response timeout to ' . $response_timeout);
2419 socket_set_timeout($this->fp, $response_timeout);
2420
2421 $this->debug('socket connected');
2422 return true;
2423 } elseif ($this->io_method() == 'curl') {
2424 if (!extension_loaded('curl')) {
2425 // $this->setError('cURL Extension, or OpenSSL extension w/ PHP version >= 4.3 is required for HTTPS');
2426 $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.');
2427 return false;
2428 }
2429 // Avoid warnings when PHP does not have these options
2430 if (defined('CURLOPT_CONNECTIONTIMEOUT')) {
2431 $CURLOPT_CONNECTIONTIMEOUT = CURLOPT_CONNECTIONTIMEOUT;
2432 } else {
2433 $CURLOPT_CONNECTIONTIMEOUT = 78;
2434 }
2435 if (defined('CURLOPT_HTTPAUTH')) {
2436 $CURLOPT_HTTPAUTH = CURLOPT_HTTPAUTH;
2437 } else {
2438 $CURLOPT_HTTPAUTH = 107;
2439 }
2440 if (defined('CURLOPT_PROXYAUTH')) {
2441 $CURLOPT_PROXYAUTH = CURLOPT_PROXYAUTH;
2442 } else {
2443 $CURLOPT_PROXYAUTH = 111;
2444 }
2445 if (defined('CURLAUTH_BASIC')) {
2446 $CURLAUTH_BASIC = CURLAUTH_BASIC;
2447 } else {
2448 $CURLAUTH_BASIC = 1;
2449 }
2450 if (defined('CURLAUTH_DIGEST')) {
2451 $CURLAUTH_DIGEST = CURLAUTH_DIGEST;
2452 } else {
2453 $CURLAUTH_DIGEST = 2;
2454 }
2455 if (defined('CURLAUTH_NTLM')) {
2456 $CURLAUTH_NTLM = CURLAUTH_NTLM;
2457 } else {
2458 $CURLAUTH_NTLM = 8;
2459 }
2460
2461 $this->debug('connect using cURL');
2462 // init CURL
2463 $this->ch = curl_init();
2464 // set url
2465 $hostURL = ($this->port != '') ? "$this->scheme://$this->host:$this->port" : "$this->scheme://$this->host";
2466 // add path
2467 $hostURL .= $this->path;
2468 $this->setCurlOption(CURLOPT_URL, $hostURL);
2469 // follow location headers (re-directs)
2470 if (ini_get('safe_mode') || ini_get('open_basedir')) {
2471 $this->debug('safe_mode or open_basedir set, so do not set CURLOPT_FOLLOWLOCATION');
2472 $this->debug('safe_mode = ');
2473 $this->appendDebug($this->varDump(ini_get('safe_mode')));
2474 $this->debug('open_basedir = ');
2475 $this->appendDebug($this->varDump(ini_get('open_basedir')));
2476 } else {
2477 $this->setCurlOption(CURLOPT_FOLLOWLOCATION, 1);
2478 }
2479 // ask for headers in the response output
2480 $this->setCurlOption(CURLOPT_HEADER, 1);
2481 // ask for the response output as the return value
2482 $this->setCurlOption(CURLOPT_RETURNTRANSFER, 1);
2483 // encode
2484 // We manage this ourselves through headers and encoding
2485 // if(function_exists('gzuncompress')){
2486 // $this->setCurlOption(CURLOPT_ENCODING, 'deflate');
2487 // }
2488 // persistent connection
2489 if ($this->persistentConnection) {
2490 // I believe the following comment is now bogus, having applied to
2491 // the code when it used CURLOPT_CUSTOMREQUEST to send the request.
2492 // The way we send data, we cannot use persistent connections, since
2493 // there will be some "junk" at the end of our request.
2494 //$this->setCurlOption(CURL_HTTP_VERSION_1_1, true);
2495 $this->persistentConnection = false;
2496 $this->setHeader('Connection', 'close');
2497 }
2498 // set timeouts
2499 if ($connection_timeout != 0) {
2500 $this->setCurlOption($CURLOPT_CONNECTIONTIMEOUT, $connection_timeout);
2501 }
2502 if ($response_timeout != 0) {
2503 $this->setCurlOption(CURLOPT_TIMEOUT, $response_timeout);
2504 }
2505
2506 if ($this->scheme == 'https') {
2507 $this->debug('set cURL SSL verify options');
2508 // recent versions of cURL turn on peer/host checking by default,
2509 // while PHP binaries are not compiled with a default location for the
2510 // CA cert bundle, so disable peer/host checking.
2511 //$this->setCurlOption(CURLOPT_CAINFO, 'f:\php-4.3.2-win32\extensions\curl-ca-bundle.crt');
2512 $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 0);
2513 $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 0);
2514
2515 // support client certificates (thanks Tobias Boes, Doug Anarino, Eryan Ariobowo)
2516 if ($this->authtype == 'certificate') {
2517 $this->debug('set cURL certificate options');
2518 if (isset($this->certRequest['cainfofile'])) {
2519 $this->setCurlOption(CURLOPT_CAINFO, $this->certRequest['cainfofile']);
2520 }
2521 if (isset($this->certRequest['verifypeer'])) {
2522 $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, $this->certRequest['verifypeer']);
2523 } else {
2524 $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 1);
2525 }
2526 if (isset($this->certRequest['verifyhost'])) {
2527 $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, $this->certRequest['verifyhost']);
2528 } else {
2529 $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 1);
2530 }
2531 if (isset($this->certRequest['sslcertfile'])) {
2532 $this->setCurlOption(CURLOPT_SSLCERT, $this->certRequest['sslcertfile']);
2533 }
2534 if (isset($this->certRequest['sslkeyfile'])) {
2535 $this->setCurlOption(CURLOPT_SSLKEY, $this->certRequest['sslkeyfile']);
2536 }
2537 if (isset($this->certRequest['passphrase'])) {
2538 $this->setCurlOption(CURLOPT_SSLKEYPASSWD, $this->certRequest['passphrase']);
2539 }
2540 if (isset($this->certRequest['certpassword'])) {
2541 $this->setCurlOption(CURLOPT_SSLCERTPASSWD, $this->certRequest['certpassword']);
2542 }
2543 }
2544 }
2545 if ($this->authtype && ($this->authtype != 'certificate')) {
2546 if ($this->username) {
2547 $this->debug('set cURL username/password');
2548 $this->setCurlOption(CURLOPT_USERPWD, "$this->username:$this->password");
2549 }
2550 if ($this->authtype == 'basic') {
2551 $this->debug('set cURL for Basic authentication');
2552 $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_BASIC);
2553 }
2554 if ($this->authtype == 'digest') {
2555 $this->debug('set cURL for digest authentication');
2556 $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_DIGEST);
2557 }
2558 if ($this->authtype == 'ntlm') {
2559 $this->debug('set cURL for NTLM authentication');
2560 $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_NTLM);
2561 }
2562 }
2563 if (is_array($this->proxy)) {
2564 $this->debug('set cURL proxy options');
2565 if ($this->proxy['port'] != '') {
2566 $this->setCurlOption(CURLOPT_PROXY, $this->proxy['host'] . ':' . $this->proxy['port']);
2567 } else {
2568 $this->setCurlOption(CURLOPT_PROXY, $this->proxy['host']);
2569 }
2570 if ($this->proxy['username'] || $this->proxy['password']) {
2571 $this->debug('set cURL proxy authentication options');
2572 $this->setCurlOption(CURLOPT_PROXYUSERPWD, $this->proxy['username'] . ':' . $this->proxy['password']);
2573 if ($this->proxy['authtype'] == 'basic') {
2574 $this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_BASIC);
2575 }
2576 if ($this->proxy['authtype'] == 'ntlm') {
2577 $this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_NTLM);
2578 }
2579 }
2580 }
2581 $this->debug('cURL connection set up');
2582 return true;
2583 } else {
2584 $this->setError('Unknown scheme ' . $this->scheme);
2585 $this->debug('Unknown scheme ' . $this->scheme);
2586 return false;
2587 }
2588 }
2589
2600 public function send($data, $timeout=0, $response_timeout=30, $cookies=null)
2601 {
2602 $this->debug('entered send() with data of length: ' . strlen($data));
2603
2604 $this->tryagain = true;
2605 $tries = 0;
2606 while ($this->tryagain) {
2607 $this->tryagain = false;
2608 if ($tries++ < 2) {
2609 // make connnection
2610 if (!$this->connect($timeout, $response_timeout)) {
2611 return false;
2612 }
2613
2614 // send request
2615 if (!$this->sendRequest($data, $cookies)) {
2616 return false;
2617 }
2618
2619 // get response
2620 $respdata = $this->getResponse();
2621 } else {
2622 $this->setError("Too many tries to get an OK response ($this->response_status_line)");
2623 }
2624 }
2625 $this->debug('end of send()');
2626 return $respdata;
2627 }
2628
2629
2641 public function sendHTTPS($data, $timeout=0, $response_timeout=30, $cookies=null)
2642 {
2643 return $this->send($data, $timeout, $response_timeout, $cookies);
2644 }
2645
2656 public function setCredentials($username, $password, $authtype = 'basic', $digestRequest = array(), $certRequest = array())
2657 {
2658 $this->debug("setCredentials username=$username authtype=$authtype digestRequest=");
2659 $this->appendDebug($this->varDump($digestRequest));
2660 $this->debug("certRequest=");
2661 $this->appendDebug($this->varDump($certRequest));
2662 // cf. RFC 2617
2663 if ($authtype == 'basic') {
2664 $this->setHeader('Authorization', 'Basic ' . base64_encode(str_replace(':', '', $username) . ':' . $password));
2665 } elseif ($authtype == 'digest') {
2666 if (isset($digestRequest['nonce'])) {
2667 $digestRequest['nc'] = isset($digestRequest['nc']) ? $digestRequest['nc']++ : 1;
2668
2669 // calculate the Digest hashes (calculate code based on digest implementation found at: http://www.rassoc.com/gregr/weblog/stories/2002/07/09/webServicesSecurityHttpDigestAuthenticationWithoutActiveDirectory.html)
2670
2671 // A1 = unq(username-value) ":" unq(realm-value) ":" passwd
2672 $A1 = $username . ':' . (isset($digestRequest['realm']) ? $digestRequest['realm'] : '') . ':' . $password;
2673
2674 // H(A1) = MD5(A1)
2675 $HA1 = md5($A1);
2676
2677 // A2 = Method ":" digest-uri-value
2678 $A2 = $this->request_method . ':' . $this->digest_uri;
2679
2680 // H(A2)
2681 $HA2 = md5($A2);
2682
2683 // KD(secret, data) = H(concat(secret, ":", data))
2684 // if qop == auth:
2685 // request-digest = <"> < KD ( H(A1), unq(nonce-value)
2686 // ":" nc-value
2687 // ":" unq(cnonce-value)
2688 // ":" unq(qop-value)
2689 // ":" H(A2)
2690 // ) <">
2691 // if qop is missing,
2692 // request-digest = <"> < KD ( H(A1), unq(nonce-value) ":" H(A2) ) > <">
2693
2694 $unhashedDigest = '';
2695 $nonce = isset($digestRequest['nonce']) ? $digestRequest['nonce'] : '';
2696 $cnonce = $nonce;
2697 if ($digestRequest['qop'] != '') {
2698 $unhashedDigest = $HA1 . ':' . $nonce . ':' . sprintf("%08d", $digestRequest['nc']) . ':' . $cnonce . ':' . $digestRequest['qop'] . ':' . $HA2;
2699 } else {
2700 $unhashedDigest = $HA1 . ':' . $nonce . ':' . $HA2;
2701 }
2702
2703 $hashedDigest = md5($unhashedDigest);
2704
2705 $opaque = '';
2706 if (isset($digestRequest['opaque'])) {
2707 $opaque = ', opaque="' . $digestRequest['opaque'] . '"';
2708 }
2709
2710 $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 . '"');
2711 }
2712 } elseif ($authtype == 'certificate') {
2713 $this->certRequest = $certRequest;
2714 $this->debug('Authorization header not set for certificate');
2715 } elseif ($authtype == 'ntlm') {
2716 // do nothing
2717 $this->debug('Authorization header not set for ntlm');
2718 }
2719 $this->username = $username;
2720 $this->password = $password;
2721 $this->authtype = $authtype;
2722 $this->digestRequest = $digestRequest;
2723 }
2724
2731 public function setSOAPAction($soapaction)
2732 {
2733 $this->setHeader('SOAPAction', '"' . $soapaction . '"');
2734 }
2735
2742 public function setEncoding($enc='gzip, deflate')
2743 {
2744 if (function_exists('gzdeflate')) {
2745 $this->protocol_version = '1.1';
2746 $this->setHeader('Accept-Encoding', $enc);
2747 if (!isset($this->outgoing_headers['Connection'])) {
2748 $this->setHeader('Connection', 'close');
2749 $this->persistentConnection = false;
2750 }
2751 #set_magic_quotes_runtime(0);
2752 // deprecated
2753 $this->encoding = $enc;
2754 }
2755 }
2756
2767 public function setProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '', $proxyauthtype = 'basic')
2768 {
2769 if ($proxyhost) {
2770 $this->proxy = array(
2771 'host' => $proxyhost,
2772 'port' => $proxyport,
2773 'username' => $proxyusername,
2774 'password' => $proxypassword,
2775 'authtype' => $proxyauthtype
2776 );
2777 if ($proxyusername != '' && $proxypassword != '' && $proxyauthtype = 'basic') {
2778 $this->setHeader('Proxy-Authorization', ' Basic ' . base64_encode($proxyusername . ':' . $proxypassword));
2779 }
2780 } else {
2781 $this->debug('remove proxy');
2782 $proxy = null;
2783 unsetHeader('Proxy-Authorization');
2784 }
2785 }
2786
2787
2796 public function isSkippableCurlHeader(&$data)
2797 {
2798 $skipHeaders = array( 'HTTP/1.1 100',
2799 'HTTP/1.0 301',
2800 'HTTP/1.1 301',
2801 'HTTP/1.0 302',
2802 'HTTP/1.1 302',
2803 'HTTP/1.0 401',
2804 'HTTP/1.1 401',
2805 'HTTP/1.0 200 Connection established');
2806 foreach ($skipHeaders as $hd) {
2807 $prefix = substr($data, 0, strlen($hd));
2808 if ($prefix == $hd) {
2809 return true;
2810 }
2811 }
2812
2813 return false;
2814 }
2815
2826 public function decodeChunked($buffer, $lb)
2827 {
2828 // length := 0
2829 $length = 0;
2830 $new = '';
2831
2832 // read chunk-size, chunk-extension (if any) and CRLF
2833 // get the position of the linebreak
2834 $chunkend = strpos($buffer, $lb);
2835 if ($chunkend == false) {
2836 $this->debug('no linebreak found in decodeChunked');
2837 return $new;
2838 }
2839 $temp = substr($buffer, 0, $chunkend);
2840 $chunk_size = hexdec(trim($temp));
2841 $chunkstart = $chunkend + strlen($lb);
2842 // while (chunk-size > 0) {
2843 while ($chunk_size > 0) {
2844 $this->debug("chunkstart: $chunkstart chunk_size: $chunk_size");
2845 $chunkend = strpos($buffer, $lb, $chunkstart + $chunk_size);
2846
2847 // Just in case we got a broken connection
2848 if ($chunkend == false) {
2849 $chunk = substr($buffer, $chunkstart);
2850 // append chunk-data to entity-body
2851 $new .= $chunk;
2852 $length += strlen($chunk);
2853 break;
2854 }
2855
2856 // read chunk-data and CRLF
2857 $chunk = substr($buffer, $chunkstart, $chunkend-$chunkstart);
2858 // append chunk-data to entity-body
2859 $new .= $chunk;
2860 // length := length + chunk-size
2861 $length += strlen($chunk);
2862 // read chunk-size and CRLF
2863 $chunkstart = $chunkend + strlen($lb);
2864
2865 $chunkend = strpos($buffer, $lb, $chunkstart) + strlen($lb);
2866 if ($chunkend == false) {
2867 break; //Just in case we got a broken connection
2868 }
2869 $temp = substr($buffer, $chunkstart, $chunkend-$chunkstart);
2870 $chunk_size = hexdec(trim($temp));
2871 $chunkstart = $chunkend;
2872 }
2873 return $new;
2874 }
2875
2884 public function buildPayload($data, $cookie_str = '')
2885 {
2886 // Note: for cURL connections, $this->outgoing_payload is ignored,
2887 // as is the Content-Length header, but these are still created as
2888 // debugging guides.
2889
2890 // add content-length header
2891 $this->setHeader('Content-Length', strlen($data));
2892
2893 // start building outgoing payload:
2894 if ($this->proxy) {
2895 $uri = $this->url;
2896 } else {
2897 $uri = $this->uri;
2898 }
2899 $req = "$this->request_method $uri HTTP/$this->protocol_version";
2900 $this->debug("HTTP request: $req");
2901 $this->outgoing_payload = "$req\r\n";
2902
2903 // loop thru headers, serializing
2904 foreach ($this->outgoing_headers as $k => $v) {
2905 $hdr = $k . ': ' . $v;
2906 $this->debug("HTTP header: $hdr");
2907 $this->outgoing_payload .= "$hdr\r\n";
2908 }
2909
2910 // add any cookies
2911 if ($cookie_str != '') {
2912 $hdr = 'Cookie: ' . $cookie_str;
2913 $this->debug("HTTP header: $hdr");
2914 $this->outgoing_payload .= "$hdr\r\n";
2915 }
2916
2917 // header/body separator
2918 $this->outgoing_payload .= "\r\n";
2919
2920 // add data
2921 $this->outgoing_payload .= $data;
2922 }
2923
2932 public function sendRequest($data, $cookies = null)
2933 {
2934 // build cookie string
2935 $cookie_str = $this->getCookiesForRequest($cookies, (($this->scheme == 'ssl') || ($this->scheme == 'https')));
2936
2937 // build payload
2938 $this->buildPayload($data, $cookie_str);
2939
2940 if ($this->io_method() == 'socket') {
2941 // send payload
2942 if (!fputs($this->fp, $this->outgoing_payload, strlen($this->outgoing_payload))) {
2943 $this->setError('couldn\'t write message data to socket');
2944 $this->debug('couldn\'t write message data to socket');
2945 return false;
2946 }
2947 $this->debug('wrote data to socket, length = ' . strlen($this->outgoing_payload));
2948 return true;
2949 } elseif ($this->io_method() == 'curl') {
2950 // set payload
2951 // cURL does say this should only be the verb, and in fact it
2952 // turns out that the URI and HTTP version are appended to this, which
2953 // some servers refuse to work with (so we no longer use this method!)
2954 //$this->setCurlOption(CURLOPT_CUSTOMREQUEST, $this->outgoing_payload);
2955 $curl_headers = array();
2956 foreach ($this->outgoing_headers as $k => $v) {
2957 if ($k == 'Connection' || $k == 'Content-Length' || $k == 'Host' || $k == 'Authorization' || $k == 'Proxy-Authorization') {
2958 $this->debug("Skip cURL header $k: $v");
2959 } else {
2960 $curl_headers[] = "$k: $v";
2961 }
2962 }
2963 if ($cookie_str != '') {
2964 $curl_headers[] = 'Cookie: ' . $cookie_str;
2965 }
2966 $this->setCurlOption(CURLOPT_HTTPHEADER, $curl_headers);
2967 $this->debug('set cURL HTTP headers');
2968 if ($this->request_method == "POST") {
2969 $this->setCurlOption(CURLOPT_POST, 1);
2970 $this->setCurlOption(CURLOPT_POSTFIELDS, $data);
2971 $this->debug('set cURL POST data');
2972 } else {
2973 }
2974 // insert custom user-set cURL options
2975 foreach ($this->ch_options as $key => $val) {
2976 $this->setCurlOption($key, $val);
2977 }
2978
2979 $this->debug('set cURL payload');
2980 return true;
2981 }
2982 }
2983
2990 public function getResponse()
2991 {
2992 $this->incoming_payload = '';
2993
2994 if ($this->io_method() == 'socket') {
2995 // loop until headers have been retrieved
2996 $data = '';
2997 while (!isset($lb)) {
2998
2999 // We might EOF during header read.
3000 if (feof($this->fp)) {
3001 $this->incoming_payload = $data;
3002 $this->debug('found no headers before EOF after length ' . strlen($data));
3003 $this->debug("received before EOF:\n" . $data);
3004 $this->setError('server failed to send headers');
3005 return false;
3006 }
3007
3008 $tmp = fgets($this->fp, 256);
3009 $tmplen = strlen($tmp);
3010 $this->debug("read line of $tmplen bytes: " . trim($tmp));
3011
3012 if ($tmplen == 0) {
3013 $this->incoming_payload = $data;
3014 $this->debug('socket read of headers timed out after length ' . strlen($data));
3015 $this->debug("read before timeout: " . $data);
3016 $this->setError('socket read of headers timed out');
3017 return false;
3018 }
3019
3020 $data .= $tmp;
3021 $pos = strpos($data, "\r\n\r\n");
3022 if ($pos > 1) {
3023 $lb = "\r\n";
3024 } else {
3025 $pos = strpos($data, "\n\n");
3026 if ($pos > 1) {
3027 $lb = "\n";
3028 }
3029 }
3030 // remove 100 headers
3031 if (isset($lb) && preg_match('/^HTTP\/1.1 100/', $data)) {
3032 unset($lb);
3033 $data = '';
3034 }//
3035 }
3036 // store header data
3037 $this->incoming_payload .= $data;
3038 $this->debug('found end of headers after length ' . strlen($data));
3039 // process headers
3040 $header_data = trim(substr($data, 0, $pos));
3041 $header_array = explode($lb, $header_data);
3042 $this->incoming_headers = array();
3043 $this->incoming_cookies = array();
3044 foreach ($header_array as $header_line) {
3045 $arr = explode(':', $header_line, 2);
3046 if (count($arr) > 1) {
3047 $header_name = strtolower(trim($arr[0]));
3048 $this->incoming_headers[$header_name] = trim($arr[1]);
3049 if ($header_name == 'set-cookie') {
3050 // TODO: allow multiple cookies from parseCookie
3051 $cookie = $this->parseCookie(trim($arr[1]));
3052 if ($cookie) {
3053 $this->incoming_cookies[] = $cookie;
3054 $this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']);
3055 } else {
3056 $this->debug('did not find cookie in ' . trim($arr[1]));
3057 }
3058 }
3059 } elseif (isset($header_name)) {
3060 // append continuation line to previous header
3061 $this->incoming_headers[$header_name] .= $lb . ' ' . $header_line;
3062 }
3063 }
3064
3065 // loop until msg has been received
3066 if (isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked') {
3067 $content_length = 2147483647; // ignore any content-length header
3068 $chunked = true;
3069 $this->debug("want to read chunked content");
3070 } elseif (isset($this->incoming_headers['content-length'])) {
3071 $content_length = $this->incoming_headers['content-length'];
3072 $chunked = false;
3073 $this->debug("want to read content of length $content_length");
3074 } else {
3075 $content_length = 2147483647;
3076 $chunked = false;
3077 $this->debug("want to read content to EOF");
3078 }
3079 $data = '';
3080 do {
3081 if ($chunked) {
3082 $tmp = fgets($this->fp, 256);
3083 $tmplen = strlen($tmp);
3084 $this->debug("read chunk line of $tmplen bytes");
3085 if ($tmplen == 0) {
3086 $this->incoming_payload = $data;
3087 $this->debug('socket read of chunk length timed out after length ' . strlen($data));
3088 $this->debug("read before timeout:\n" . $data);
3089 $this->setError('socket read of chunk length timed out');
3090 return false;
3091 }
3092 $content_length = hexdec(trim($tmp));
3093 $this->debug("chunk length $content_length");
3094 }
3095 $strlen = 0;
3096 while (($strlen < $content_length) && (!feof($this->fp))) {
3097 $readlen = min(8192, $content_length - $strlen);
3098 $tmp = fread($this->fp, $readlen);
3099 $tmplen = strlen($tmp);
3100 $this->debug("read buffer of $tmplen bytes");
3101 if (($tmplen == 0) && (!feof($this->fp))) {
3102 $this->incoming_payload = $data;
3103 $this->debug('socket read of body timed out after length ' . strlen($data));
3104 $this->debug("read before timeout:\n" . $data);
3105 $this->setError('socket read of body timed out');
3106 return false;
3107 }
3108 $strlen += $tmplen;
3109 $data .= $tmp;
3110 }
3111 if ($chunked && ($content_length > 0)) {
3112 $tmp = fgets($this->fp, 256);
3113 $tmplen = strlen($tmp);
3114 $this->debug("read chunk terminator of $tmplen bytes");
3115 if ($tmplen == 0) {
3116 $this->incoming_payload = $data;
3117 $this->debug('socket read of chunk terminator timed out after length ' . strlen($data));
3118 $this->debug("read before timeout:\n" . $data);
3119 $this->setError('socket read of chunk terminator timed out');
3120 return false;
3121 }
3122 }
3123 } while ($chunked && ($content_length > 0) && (!feof($this->fp)));
3124 if (feof($this->fp)) {
3125 $this->debug('read to EOF');
3126 }
3127 $this->debug('read body of length ' . strlen($data));
3128 $this->incoming_payload .= $data;
3129 $this->debug('received a total of ' . strlen($this->incoming_payload) . ' bytes of data from server');
3130
3131 // close filepointer
3132 if (
3133 (isset($this->incoming_headers['connection']) && strtolower($this->incoming_headers['connection']) == 'close') ||
3134 (! $this->persistentConnection) || feof($this->fp)) {
3135 fclose($this->fp);
3136 $this->fp = false;
3137 $this->debug('closed socket');
3138 }
3139
3140 // connection was closed unexpectedly
3141 if ($this->incoming_payload == '') {
3142 $this->setError('no response from server');
3143 return false;
3144 }
3145
3146 // decode transfer-encoding
3147// if(isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked'){
3148// if(!$data = $this->decodeChunked($data, $lb)){
3149// $this->setError('Decoding of chunked data failed');
3150// return false;
3151// }
3152 //print "<pre>\nde-chunked:\n---------------\n$data\n\n---------------\n</pre>";
3153 // set decoded payload
3154// $this->incoming_payload = $header_data.$lb.$lb.$data;
3155// }
3156 } elseif ($this->io_method() == 'curl') {
3157 // send and receive
3158 $this->debug('send and receive with cURL');
3159 $this->incoming_payload = curl_exec($this->ch);
3161
3162 $cErr = curl_error($this->ch);
3163 if ($cErr != '') {
3164 $err = 'cURL ERROR: ' . curl_errno($this->ch) . ': ' . $cErr . '<br>';
3165 // TODO: there is a PHP bug that can cause this to SEGV for CURLINFO_CONTENT_TYPE
3166 foreach (curl_getinfo($this->ch) as $k => $v) {
3167 $err .= "$k: $v<br>";
3168 }
3169 $this->debug($err);
3170 $this->setError($err);
3171 curl_close($this->ch);
3172 return false;
3173 } else {
3174 //echo '<pre>';
3175 //var_dump(curl_getinfo($this->ch));
3176 //echo '</pre>';
3177 }
3178 // close curl
3179 $this->debug('No cURL error, closing cURL');
3180 curl_close($this->ch);
3181
3182 // try removing skippable headers
3183 $savedata = $data;
3184 while ($this->isSkippableCurlHeader($data)) {
3185 $this->debug("Found HTTP header to skip");
3186 if ($pos = strpos($data, "\r\n\r\n")) {
3187 $data = ltrim(substr($data, $pos));
3188 } elseif ($pos = strpos($data, "\n\n")) {
3189 $data = ltrim(substr($data, $pos));
3190 }
3191 }
3192
3193 if ($data == '') {
3194 // have nothing left; just remove 100 header(s)
3195 $data = $savedata;
3196 while (preg_match('/^HTTP\/1.1 100/', $data)) {
3197 if ($pos = strpos($data, "\r\n\r\n")) {
3198 $data = ltrim(substr($data, $pos));
3199 } elseif ($pos = strpos($data, "\n\n")) {
3200 $data = ltrim(substr($data, $pos));
3201 }
3202 }
3203 }
3204
3205 // separate content from HTTP headers
3206 if ($pos = strpos($data, "\r\n\r\n")) {
3207 $lb = "\r\n";
3208 } elseif ($pos = strpos($data, "\n\n")) {
3209 $lb = "\n";
3210 } else {
3211 $this->debug('no proper separation of headers and document');
3212 $this->setError('no proper separation of headers and document');
3213 return false;
3214 }
3215 $header_data = trim(substr($data, 0, $pos));
3216 $header_array = explode($lb, $header_data);
3217 $data = ltrim(substr($data, $pos));
3218 $this->debug('found proper separation of headers and document');
3219 $this->debug('cleaned data, stringlen: ' . strlen($data));
3220 // clean headers
3221 foreach ($header_array as $header_line) {
3222 $arr = explode(':', $header_line, 2);
3223 if (count($arr) > 1) {
3224 $header_name = strtolower(trim($arr[0]));
3225 $this->incoming_headers[$header_name] = trim($arr[1]);
3226 if ($header_name == 'set-cookie') {
3227 // TODO: allow multiple cookies from parseCookie
3228 $cookie = $this->parseCookie(trim($arr[1]));
3229 if ($cookie) {
3230 $this->incoming_cookies[] = $cookie;
3231 $this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']);
3232 } else {
3233 $this->debug('did not find cookie in ' . trim($arr[1]));
3234 }
3235 }
3236 } elseif (isset($header_name)) {
3237 // append continuation line to previous header
3238 $this->incoming_headers[$header_name] .= $lb . ' ' . $header_line;
3239 }
3240 }
3241 }
3242
3243 $this->response_status_line = $header_array[0];
3244 $arr = explode(' ', $this->response_status_line, 3);
3245 $http_version = $arr[0];
3246 $http_status = intval($arr[1]);
3247 $http_reason = count($arr) > 2 ? $arr[2] : '';
3248
3249 // see if we need to resend the request with http digest authentication
3250 if (isset($this->incoming_headers['location']) && ($http_status == 301 || $http_status == 302)) {
3251 $this->debug("Got $http_status $http_reason with Location: " . $this->incoming_headers['location']);
3252 $this->setURL($this->incoming_headers['location']);
3253 $this->tryagain = true;
3254 return false;
3255 }
3256
3257 // see if we need to resend the request with http digest authentication
3258 if (isset($this->incoming_headers['www-authenticate']) && $http_status == 401) {
3259 $this->debug("Got 401 $http_reason with WWW-Authenticate: " . $this->incoming_headers['www-authenticate']);
3260 if (strstr($this->incoming_headers['www-authenticate'], "Digest ")) {
3261 $this->debug('Server wants digest authentication');
3262 // remove "Digest " from our elements
3263 $digestString = str_replace('Digest ', '', $this->incoming_headers['www-authenticate']);
3264
3265 // parse elements into array
3266 $digestElements = explode(',', $digestString);
3267 foreach ($digestElements as $val) {
3268 $tempElement = explode('=', trim($val), 2);
3269 $digestRequest[$tempElement[0]] = str_replace("\"", '', $tempElement[1]);
3270 }
3271
3272 // should have (at least) qop, realm, nonce
3273 if (isset($digestRequest['nonce'])) {
3274 $this->setCredentials($this->username, $this->password, 'digest', $digestRequest);
3275 $this->tryagain = true;
3276 return false;
3277 }
3278 }
3279 $this->debug('HTTP authentication failed');
3280 $this->setError('HTTP authentication failed');
3281 return false;
3282 }
3283
3284 if (
3285 ($http_status >= 300 && $http_status <= 307) ||
3286 ($http_status >= 400 && $http_status <= 417) ||
3287 ($http_status >= 501 && $http_status <= 505)
3288 ) {
3289 $this->setError("Unsupported HTTP response status $http_status $http_reason (soapclient->response has contents of the response)");
3290 return false;
3291 }
3292
3293 // decode content-encoding
3294 if (isset($this->incoming_headers['content-encoding']) && $this->incoming_headers['content-encoding'] != '') {
3295 if (strtolower($this->incoming_headers['content-encoding']) == 'deflate' || strtolower($this->incoming_headers['content-encoding']) == 'gzip') {
3296 // if decoding works, use it. else assume data wasn't gzencoded
3297 if (function_exists('gzinflate')) {
3298 //$timer->setMarker('starting decoding of gzip/deflated content');
3299 // IIS 5 requires gzinflate instead of gzuncompress (similar to IE 5 and gzdeflate v. gzcompress)
3300 // this means there are no Zlib headers, although there should be
3301 $this->debug('The gzinflate function exists');
3302 $datalen = strlen($data);
3303 if ($this->incoming_headers['content-encoding'] == 'deflate') {
3304 if ($degzdata = @gzinflate($data)) {
3305 $data = $degzdata;
3306 $this->debug('The payload has been inflated to ' . strlen($data) . ' bytes');
3307 if (strlen($data) < $datalen) {
3308 // test for the case that the payload has been compressed twice
3309 $this->debug('The inflated payload is smaller than the gzipped one; try again');
3310 if ($degzdata = @gzinflate($data)) {
3311 $data = $degzdata;
3312 $this->debug('The payload has been inflated again to ' . strlen($data) . ' bytes');
3313 }
3314 }
3315 } else {
3316 $this->debug('Error using gzinflate to inflate the payload');
3317 $this->setError('Error using gzinflate to inflate the payload');
3318 }
3319 } elseif ($this->incoming_headers['content-encoding'] == 'gzip') {
3320 if ($degzdata = @gzinflate(substr($data, 10))) { // do our best
3321 $data = $degzdata;
3322 $this->debug('The payload has been un-gzipped to ' . strlen($data) . ' bytes');
3323 if (strlen($data) < $datalen) {
3324 // test for the case that the payload has been compressed twice
3325 $this->debug('The un-gzipped payload is smaller than the gzipped one; try again');
3326 if ($degzdata = @gzinflate(substr($data, 10))) {
3327 $data = $degzdata;
3328 $this->debug('The payload has been un-gzipped again to ' . strlen($data) . ' bytes');
3329 }
3330 }
3331 } else {
3332 $this->debug('Error using gzinflate to un-gzip the payload');
3333 $this->setError('Error using gzinflate to un-gzip the payload');
3334 }
3335 }
3336 //$timer->setMarker('finished decoding of gzip/deflated content');
3337 //print "<xmp>\nde-inflated:\n---------------\n$data\n-------------\n</xmp>";
3338 // set decoded payload
3339 $this->incoming_payload = $header_data . $lb . $lb . $data;
3340 } else {
3341 $this->debug('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.');
3342 $this->setError('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.');
3343 }
3344 } else {
3345 $this->debug('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']);
3346 $this->setError('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']);
3347 }
3348 } else {
3349 $this->debug('No Content-Encoding header');
3350 }
3351
3352 if (strlen($data) == 0) {
3353 $this->debug('no data after headers!');
3354 $this->setError('no data present after HTTP headers');
3355 return false;
3356 }
3357
3358 return $data;
3359 }
3360
3368 public function setContentType($type, $charset = false)
3369 {
3370 $this->setHeader('Content-Type', $type . ($charset ? '; charset=' . $charset : ''));
3371 }
3372
3379 public function usePersistentConnection()
3380 {
3381 if (isset($this->outgoing_headers['Accept-Encoding'])) {
3382 return false;
3383 }
3384 $this->protocol_version = '1.1';
3385 $this->persistentConnection = true;
3386 $this->setHeader('Connection', 'Keep-Alive');
3387 return true;
3388 }
3389
3397 /*
3398 * TODO: allow a Set-Cookie string to be parsed into multiple cookies
3399 */
3400 public function parseCookie($cookie_str)
3401 {
3402 $cookie_str = str_replace('; ', ';', $cookie_str) . ';';
3403 // begin-patch php8
3404 //$data = split(';', $cookie_str);
3405 $data = explode(';', $cookie_str);
3406 $value_str = $data[0];
3407
3408 $cookie_param = 'domain=';
3409 $start = strpos($cookie_str, $cookie_param);
3410 if ($start > 0) {
3411 $domain = substr($cookie_str, $start + strlen($cookie_param));
3412 $domain = substr($domain, 0, strpos($domain, ';'));
3413 } else {
3414 $domain = '';
3415 }
3416
3417 $cookie_param = 'expires=';
3418 $start = strpos($cookie_str, $cookie_param);
3419 if ($start > 0) {
3420 $expires = substr($cookie_str, $start + strlen($cookie_param));
3421 $expires = substr($expires, 0, strpos($expires, ';'));
3422 } else {
3423 $expires = '';
3424 }
3425
3426 $cookie_param = 'path=';
3427 $start = strpos($cookie_str, $cookie_param);
3428 if ($start > 0) {
3429 $path = substr($cookie_str, $start + strlen($cookie_param));
3430 $path = substr($path, 0, strpos($path, ';'));
3431 } else {
3432 $path = '/';
3433 }
3434
3435 $cookie_param = ';secure;';
3436 if (strpos($cookie_str, $cookie_param) !== false) {
3437 $secure = true;
3438 } else {
3439 $secure = false;
3440 }
3441
3442 $sep_pos = strpos($value_str, '=');
3443
3444 if ($sep_pos) {
3445 $name = substr($value_str, 0, $sep_pos);
3446 $value = substr($value_str, $sep_pos + 1);
3447 $cookie= array( 'name' => $name,
3448 'value' => $value,
3449 'domain' => $domain,
3450 'path' => $path,
3451 'expires' => $expires,
3452 'secure' => $secure
3453 );
3454 return $cookie;
3455 }
3456 return false;
3457 }
3458
3467 public function getCookiesForRequest($cookies, $secure=false)
3468 {
3469 $cookie_str = '';
3470 if ((! is_null($cookies)) && (is_array($cookies))) {
3471 foreach ($cookies as $cookie) {
3472 if (! is_array($cookie)) {
3473 continue;
3474 }
3475 $this->debug("check cookie for validity: " . $cookie['name'] . '=' . $cookie['value']);
3476 if ((isset($cookie['expires'])) && (! empty($cookie['expires']))) {
3477 if (strtotime($cookie['expires']) <= time()) {
3478 $this->debug('cookie has expired');
3479 continue;
3480 }
3481 }
3482 if ((isset($cookie['domain'])) && (! empty($cookie['domain']))) {
3483 $domain = preg_quote($cookie['domain']);
3484 if (! preg_match("'.*$domain$'i", $this->host)) {
3485 $this->debug('cookie has different domain');
3486 continue;
3487 }
3488 }
3489 if ((isset($cookie['path'])) && (! empty($cookie['path']))) {
3490 $path = preg_quote($cookie['path']);
3491 if (! preg_match("'^$path.*'i", $this->path)) {
3492 $this->debug('cookie is for a different path');
3493 continue;
3494 }
3495 }
3496 if ((! $secure) && (isset($cookie['secure'])) && ($cookie['secure'])) {
3497 $this->debug('cookie is secure, transport is not');
3498 continue;
3499 }
3500 $cookie_str .= $cookie['name'] . '=' . $cookie['value'] . '; ';
3501 $this->debug('add cookie to Cookie-String: ' . $cookie['name'] . '=' . $cookie['value']);
3502 }
3503 }
3504 return $cookie_str;
3505 }
3506}
3507
3508?><?php
3509
3510
3511
3522class nusoap_server extends nusoap_base
3523{
3529 public $headers = array();
3535 public $request = '';
3541 public $requestHeaders = '';
3547 public $requestHeader = null;
3553 public $document = '';
3559 public $requestSOAP = '';
3565 public $methodURI = '';
3571 public $methodname = '';
3577 public $methodparams = array();
3583 public $SOAPAction = '';
3589 public $xml_encoding = '';
3595 public $decode_utf8 = true;
3596
3602 public $outgoing_headers = array();
3608 public $response = '';
3614 public $responseHeaders = '';
3620 public $responseSOAP = '';
3626 public $methodreturn = false;
3632 public $methodreturnisliteralxml = false;
3638 public $fault = false;
3644 public $result = 'successful';
3645
3652 public $operations = array();
3658 public $wsdl = false;
3664 public $externalWSDLURL = false;
3670 public $debug_flag = false;
3671
3672
3680 public function __construct($wsdl=false)
3681 {
3683 // turn on debugging?
3684 global $debug;
3685 global $HTTP_SERVER_VARS;
3686
3687 if (isset($_SERVER)) {
3688 $this->debug("_SERVER is defined:");
3689 $this->appendDebug($this->varDump($_SERVER));
3690 } elseif (isset($HTTP_SERVER_VARS)) {
3691 $this->debug("HTTP_SERVER_VARS is defined:");
3692 $this->appendDebug($this->varDump($HTTP_SERVER_VARS));
3693 } else {
3694 $this->debug("Neither _SERVER nor HTTP_SERVER_VARS is defined.");
3695 }
3696
3697 if (isset($debug)) {
3698 $this->debug("In nusoap_server, set debug_flag=$debug based on global flag");
3699 $this->debug_flag = $debug;
3700 } elseif (isset($_SERVER['QUERY_STRING'])) {
3701 $qs = explode('&', $_SERVER['QUERY_STRING']);
3702 foreach ($qs as $v) {
3703 if (substr($v, 0, 6) == 'debug=') {
3704 $this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #1");
3705 $this->debug_flag = substr($v, 6);
3706 }
3707 }
3708 } elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
3709 $qs = explode('&', $HTTP_SERVER_VARS['QUERY_STRING']);
3710 foreach ($qs as $v) {
3711 if (substr($v, 0, 6) == 'debug=') {
3712 $this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #2");
3713 $this->debug_flag = substr($v, 6);
3714 }
3715 }
3716 }
3717
3718 // wsdl
3719 if ($wsdl) {
3720 $this->debug("In nusoap_server, WSDL is specified");
3721 if (is_object($wsdl) && (get_class($wsdl) == 'wsdl')) {
3722 $this->wsdl = $wsdl;
3723 $this->externalWSDLURL = $this->wsdl->wsdl;
3724 $this->debug('Use existing wsdl instance from ' . $this->externalWSDLURL);
3725 } else {
3726 $this->debug('Create wsdl from ' . $wsdl);
3727 $this->wsdl = new wsdl($wsdl);
3728 $this->externalWSDLURL = $wsdl;
3729 }
3730 $this->appendDebug($this->wsdl->getDebug());
3731 $this->wsdl->clearDebug();
3732 if ($err = $this->wsdl->getError()) {
3733 die('WSDL ERROR: ' . $err);
3734 }
3735 }
3736 }
3737
3744 public function service($data)
3745 {
3746 global $HTTP_SERVER_VARS;
3747
3748 if (isset($_SERVER['QUERY_STRING'])) {
3749 $qs = $_SERVER['QUERY_STRING'];
3750 } elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
3751 $qs = $HTTP_SERVER_VARS['QUERY_STRING'];
3752 } else {
3753 $qs = '';
3754 }
3755 $this->debug("In service, query string=$qs");
3756
3757 if (preg_match('/wsdl/', $qs)) {
3758 $this->debug("In service, this is a request for WSDL");
3759 if ($this->externalWSDLURL) {
3760 if (strpos($this->externalWSDLURL, "://")!==false) { // assume URL
3761 header('Location: ' . $this->externalWSDLURL);
3762 } else { // assume file
3763 header("Content-Type: text/xml\r\n");
3764 $fp = fopen($this->externalWSDLURL, 'r');
3765 fpassthru($fp);
3766 }
3767 } elseif ($this->wsdl) {
3768 header("Content-Type: text/xml; charset=ISO-8859-1\r\n");
3769 print $this->wsdl->serialize($this->debug_flag);
3770 if ($this->debug_flag) {
3771 $this->debug('wsdl:');
3772 $this->appendDebug($this->varDump($this->wsdl));
3773 print $this->getDebugAsXMLComment();
3774 }
3775 } else {
3776 header("Content-Type: text/html; charset=ISO-8859-1\r\n");
3777 print "This service does not provide WSDL";
3778 }
3779 } elseif ($data == '' && $this->wsdl) {
3780 $this->debug("In service, there is no data, so return Web description");
3781 print $this->wsdl->webDescription();
3782 } else {
3783 $this->debug("In service, invoke the request");
3784 $this->parse_request($data);
3785 if (! $this->fault) {
3786 $this->invoke_method();
3787 }
3788 if (! $this->fault) {
3789 $this->serialize_return();
3790 }
3791 $this->send_response();
3792 }
3793 }
3794
3807 public function parse_http_headers()
3808 {
3809 global $HTTP_SERVER_VARS;
3810
3811 $this->request = '';
3812 $this->SOAPAction = '';
3813 if (function_exists('getallheaders')) {
3814 $this->debug("In parse_http_headers, use getallheaders");
3815 $headers = getallheaders();
3816 foreach ($headers as $k=>$v) {
3817 $k = strtolower($k);
3818 $this->headers[$k] = $v;
3819 $this->request .= "$k: $v\r\n";
3820 $this->debug("$k: $v");
3821 }
3822 // get SOAPAction header
3823 if (isset($this->headers['soapaction'])) {
3824 $this->SOAPAction = str_replace('"', '', $this->headers['soapaction']);
3825 }
3826 // get the character encoding of the incoming request
3827 if (isset($this->headers['content-type']) && strpos($this->headers['content-type'], '=')) {
3828 $enc = str_replace('"', '', substr(strstr($this->headers["content-type"], '='), 1));
3829 if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i', $enc)) {
3830 $this->xml_encoding = strtoupper($enc);
3831 } else {
3832 $this->xml_encoding = 'US-ASCII';
3833 }
3834 } else {
3835 // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
3836 $this->xml_encoding = 'ISO-8859-1';
3837 }
3838 } elseif (isset($_SERVER) && is_array($_SERVER)) {
3839 $this->debug("In parse_http_headers, use _SERVER");
3840 foreach ($_SERVER as $k => $v) {
3841 if (substr($k, 0, 5) == 'HTTP_') {
3842 $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5))));
3843 } else {
3844 $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k)));
3845 }
3846 if ($k == 'soapaction') {
3847 // get SOAPAction header
3848 $k = 'SOAPAction';
3849 $v = str_replace('"', '', $v);
3850 $v = str_replace('\\', '', $v);
3851 $this->SOAPAction = $v;
3852 } elseif ($k == 'content-type') {
3853 // get the character encoding of the incoming request
3854 if (strpos($v, '=')) {
3855 $enc = substr(strstr($v, '='), 1);
3856 $enc = str_replace('"', '', $enc);
3857 $enc = str_replace('\\', '', $enc);
3858 if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i', $enc)) {
3859 $this->xml_encoding = strtoupper($enc);
3860 } else {
3861 $this->xml_encoding = 'US-ASCII';
3862 }
3863 } else {
3864 // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
3865 $this->xml_encoding = 'ISO-8859-1';
3866 }
3867 }
3868 $this->headers[$k] = $v;
3869 $this->request .= "$k: $v\r\n";
3870 $this->debug("$k: $v");
3871 }
3872 } elseif (is_array($HTTP_SERVER_VARS)) {
3873 $this->debug("In parse_http_headers, use HTTP_SERVER_VARS");
3874 foreach ($HTTP_SERVER_VARS as $k => $v) {
3875 if (substr($k, 0, 5) == 'HTTP_') {
3876 $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5))));
3877 $k = strtolower(substr($k, 5));
3878 } else {
3879 $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k)));
3880 $k = strtolower($k);
3881 }
3882 if ($k == 'soapaction') {
3883 // get SOAPAction header
3884 $k = 'SOAPAction';
3885 $v = str_replace('"', '', $v);
3886 $v = str_replace('\\', '', $v);
3887 $this->SOAPAction = $v;
3888 } elseif ($k == 'content-type') {
3889 // get the character encoding of the incoming request
3890 if (strpos($v, '=')) {
3891 $enc = substr(strstr($v, '='), 1);
3892 $enc = str_replace('"', '', $enc);
3893 $enc = str_replace('\\', '', $enc);
3894 if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i', $enc)) {
3895 $this->xml_encoding = strtoupper($enc);
3896 } else {
3897 $this->xml_encoding = 'US-ASCII';
3898 }
3899 } else {
3900 // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
3901 $this->xml_encoding = 'ISO-8859-1';
3902 }
3903 }
3904 $this->headers[$k] = $v;
3905 $this->request .= "$k: $v\r\n";
3906 $this->debug("$k: $v");
3907 }
3908 } else {
3909 $this->debug("In parse_http_headers, HTTP headers not accessible");
3910 $this->setError("HTTP headers not accessible");
3911 }
3912 }
3913
3936 public function parse_request($data='')
3937 {
3938 $this->debug('entering parse_request()');
3939 $this->parse_http_headers();
3940 $this->debug('got character encoding: ' . $this->xml_encoding);
3941 // uncompress if necessary
3942 if (isset($this->headers['content-encoding']) && $this->headers['content-encoding'] != '') {
3943 $this->debug('got content encoding: ' . $this->headers['content-encoding']);
3944 if ($this->headers['content-encoding'] == 'deflate' || $this->headers['content-encoding'] == 'gzip') {
3945 // if decoding works, use it. else assume data wasn't gzencoded
3946 if (function_exists('gzuncompress')) {
3947 if ($this->headers['content-encoding'] == 'deflate' && $degzdata = @gzuncompress($data)) {
3948 $data = $degzdata;
3949 } elseif ($this->headers['content-encoding'] == 'gzip' && $degzdata = gzinflate(substr($data, 10))) {
3950 $data = $degzdata;
3951 } else {
3952 $this->fault('SOAP-ENV:Client', 'Errors occurred when trying to decode the data');
3953 return;
3954 }
3955 } else {
3956 $this->fault('SOAP-ENV:Client', 'This Server does not support compressed data');
3957 return;
3958 }
3959 }
3960 }
3961 $this->request .= "\r\n" . $data;
3962 $data = $this->parseRequest($this->headers, $data);
3963 $this->requestSOAP = $data;
3964 $this->debug('leaving parse_request');
3965 }
3966
3984 public function invoke_method()
3985 {
3986 $this->debug('in invoke_method, methodname=' . $this->methodname . ' methodURI=' . $this->methodURI . ' SOAPAction=' . $this->SOAPAction);
3987
3988 if ($this->wsdl) {
3989 if ($this->opData = $this->wsdl->getOperationData($this->methodname)) {
3990 $this->debug('in invoke_method, found WSDL operation=' . $this->methodname);
3991 $this->appendDebug('opData=' . $this->varDump($this->opData));
3992 } elseif ($this->opData = $this->wsdl->getOperationDataForSoapAction($this->SOAPAction)) {
3993 // Note: hopefully this case will only be used for doc/lit, since rpc services should have wrapper element
3994 $this->debug('in invoke_method, found WSDL soapAction=' . $this->SOAPAction . ' for operation=' . $this->opData['name']);
3995 $this->appendDebug('opData=' . $this->varDump($this->opData));
3996 $this->methodname = $this->opData['name'];
3997 } else {
3998 $this->debug('in invoke_method, no WSDL for operation=' . $this->methodname);
3999 $this->fault('SOAP-ENV:Client', "Operation '" . $this->methodname . "' is not defined in the WSDL for this service");
4000 return;
4001 }
4002 } else {
4003 $this->debug('in invoke_method, no WSDL to validate method');
4004 }
4005
4006 // if a . is present in $this->methodname, we see if there is a class in scope,
4007 // which could be referred to. We will also distinguish between two deliminators,
4008 // to allow methods to be called a the class or an instance
4009 $class = '';
4010 $method = '';
4011 if (strpos($this->methodname, '..') > 0) {
4012 $delim = '..';
4013 } elseif (strpos($this->methodname, '.') > 0) {
4014 $delim = '.';
4015 } else {
4016 $delim = '';
4017 }
4018
4019 if (strlen($delim) > 0 && substr_count($this->methodname, $delim) == 1 &&
4020 class_exists(substr($this->methodname, 0, strpos($this->methodname, $delim)))) {
4021 // get the class and method name
4022 $class = substr($this->methodname, 0, strpos($this->methodname, $delim));
4023 $method = substr($this->methodname, strpos($this->methodname, $delim) + strlen($delim));
4024 $this->debug("in invoke_method, class=$class method=$method delim=$delim");
4025 }
4026 // set class handler
4027 // added to support single operations
4028 if ($class == '' && $this->class !='') {
4029 $class = $this->class;
4030 $delim = "..";
4031 $method = $this->methodname;
4032 }
4033
4034 // does method exist?
4035 if ($class == '') {
4036 if (!function_exists($this->methodname)) {
4037 $this->debug("in invoke_method, function '$this->methodname' not found!");
4038 $this->result = 'fault: method not found';
4039 $this->fault('SOAP-ENV:Client', "method '$this->methodname' not defined in service");
4040 return;
4041 }
4042 } else {
4043 $method_to_compare = (substr(phpversion(), 0, 2) == '4.') ? strtolower($method) : $method;
4044 if (!in_array($method_to_compare, get_class_methods($class))) {
4045 $this->debug("in invoke_method, method '$this->methodname' not found in class '$class'!");
4046 $this->result = 'fault: method not found';
4047 $this->fault('SOAP-ENV:Client', "method '$this->methodname' not defined in service");
4048 return;
4049 }
4050 }
4051
4052 // evaluate message, getting back parameters
4053 // verify that request parameters match the method's signature
4054 if (! $this->verify_method($this->methodname, $this->methodparams)) {
4055 // debug
4056 $this->debug('ERROR: request not verified against method signature');
4057 $this->result = 'fault: request failed validation against method signature';
4058 // return fault
4059 $this->fault('SOAP-ENV:Client', "Operation '$this->methodname' not defined in service.");
4060 return;
4061 }
4062
4063 // if there are parameters to pass
4064 $this->debug('in invoke_method, params:');
4065 $this->appendDebug($this->varDump($this->methodparams));
4066 $this->debug("in invoke_method, calling '$this->methodname'");
4067 if (!function_exists('call_user_func_array')) {
4068 if ($class == '') {
4069 $this->debug('in invoke_method, calling function using eval()');
4070 $funcCall = "\$this->methodreturn = $this->methodname(";
4071 } else {
4072 if ($delim == '..') {
4073 $this->debug('in invoke_method, calling class method using eval()');
4074 $funcCall = "\$this->methodreturn = " . $class . "::" . $method . "(";
4075 } else {
4076 $this->debug('in invoke_method, calling instance method using eval()');
4077 // generate unique instance name
4078 $instname = "\$inst_" . time();
4079 $funcCall = $instname . " = new " . $class . "(); ";
4080 $funcCall .= "\$this->methodreturn = " . $instname . "->" . $method . "(";
4081 }
4082 }
4083 if ($this->methodparams) {
4084 foreach ($this->methodparams as $param) {
4085 if (is_array($param) || is_object($param)) {
4086 $this->fault('SOAP-ENV:Client', 'NuSOAP does not handle complexType parameters correctly when using eval; call_user_func_array must be available');
4087 return;
4088 }
4089 $funcCall .= "\"$param\",";
4090 }
4091 $funcCall = substr($funcCall, 0, -1);
4092 }
4093 $funcCall .= ');';
4094 $this->debug('in invoke_method, function call: ' . $funcCall);
4095 @eval($funcCall);
4096 } else {
4097 if ($class == '') {
4098 $this->debug('in invoke_method, calling function using call_user_func_array()');
4099 $call_arg = "$this->methodname"; // straight assignment changes $this->methodname to lower case after call_user_func_array()
4100 } elseif ($delim == '..') {
4101 $this->debug('in invoke_method, calling class method using call_user_func_array()');
4102 $call_arg = array($class, $method);
4103 } else {
4104 $this->debug('in invoke_method, calling instance method using call_user_func_array()');
4105 $instance = new $class();
4106 $call_arg = array(&$instance, $method);
4107 }
4108 if (is_array($this->methodparams)) {
4109 $this->methodreturn = call_user_func_array($call_arg, array_values($this->methodparams));
4110 } else {
4111 $this->methodreturn = call_user_func_array($call_arg, array());
4112 }
4113 }
4114 $this->debug('in invoke_method, methodreturn:');
4115 $this->appendDebug($this->varDump($this->methodreturn));
4116 $this->debug("in invoke_method, called method $this->methodname, received data of type " . gettype($this->methodreturn));
4117 }
4118
4130 public function serialize_return()
4131 {
4132 $this->debug('Entering serialize_return methodname: ' . $this->methodname . ' methodURI: ' . $this->methodURI);
4133 // if fault
4134 if (isset($this->methodreturn) && ((get_class((object)$this->methodreturn) == 'soap_fault') || (get_class((object)$this->methodreturn) == 'nusoap_fault'))) {
4135 $this->debug('got a fault object from method');
4136 $this->fault = $this->methodreturn;
4137 return;
4138 } elseif ($this->methodreturnisliteralxml) {
4139 $return_val = $this->methodreturn;
4140 // returned value(s)
4141 } else {
4142 $this->debug('got a(n) ' . gettype($this->methodreturn) . ' from method');
4143 $this->debug('serializing return value');
4144 if ($this->wsdl) {
4145 if (sizeof($this->opData['output']['parts']) > 1) {
4146 $this->debug('more than one output part, so use the method return unchanged');
4147 $opParams = $this->methodreturn;
4148 } elseif (sizeof($this->opData['output']['parts']) == 1) {
4149 $this->debug('exactly one output part, so wrap the method return in a simple array');
4150 // TODO: verify that it is not already wrapped!
4151 //foreach ($this->opData['output']['parts'] as $name => $type) {
4152 // $this->debug('wrap in element named ' . $name);
4153 //}
4154 $opParams = array($this->methodreturn);
4155 }
4156 $return_val = $this->wsdl->serializeRPCParameters($this->methodname, 'output', $opParams);
4157 $this->appendDebug($this->wsdl->getDebug());
4158 $this->wsdl->clearDebug();
4159 if ($errstr = $this->wsdl->getError()) {
4160 $this->debug('got wsdl error: ' . $errstr);
4161 $this->fault('SOAP-ENV:Server', 'unable to serialize result');
4162 return;
4163 }
4164 } else {
4165 if (isset($this->methodreturn)) {
4166 $return_val = $this->serialize_val($this->methodreturn, 'return');
4167 } else {
4168 $return_val = '';
4169 $this->debug('in absence of WSDL, assume void return for backward compatibility');
4170 }
4171 }
4172 }
4173 $this->debug('return value:');
4174 $this->appendDebug($this->varDump($return_val));
4175
4176 $this->debug('serializing response');
4177 if ($this->wsdl) {
4178 $this->debug('have WSDL for serialization: style is ' . $this->opData['style']);
4179 if ($this->opData['style'] == 'rpc') {
4180 $this->debug('style is rpc for serialization: use is ' . $this->opData['output']['use']);
4181 if ($this->opData['output']['use'] == 'literal') {
4182 // 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
4183 $payload = '<ns1:' . $this->methodname . 'Response xmlns:ns1="' . $this->methodURI . '">' . $return_val . '</ns1:' . $this->methodname . "Response>";
4184 } else {
4185 $payload = '<ns1:' . $this->methodname . 'Response xmlns:ns1="' . $this->methodURI . '">' . $return_val . '</ns1:' . $this->methodname . "Response>";
4186 }
4187 } else {
4188 $this->debug('style is not rpc for serialization: assume document');
4189 $payload = $return_val;
4190 }
4191 } else {
4192 $this->debug('do not have WSDL for serialization: assume rpc/encoded');
4193 $payload = '<ns1:' . $this->methodname . 'Response xmlns:ns1="' . $this->methodURI . '">' . $return_val . '</ns1:' . $this->methodname . "Response>";
4194 }
4195 $this->result = 'successful';
4196 if ($this->wsdl) {
4197 //if($this->debug_flag){
4198 $this->appendDebug($this->wsdl->getDebug());
4199 // }
4200 if (isset($opData['output']['encodingStyle'])) {
4201 $encodingStyle = $opData['output']['encodingStyle'];
4202 } else {
4203 $encodingStyle = '';
4204 }
4205 // Added: In case we use a WSDL, return a serialized env. WITH the usedNamespaces.
4206 $this->responseSOAP = $this->serializeEnvelope($payload, $this->responseHeaders, $this->wsdl->usedNamespaces, $this->opData['style'], $this->opData['output']['use'], $encodingStyle);
4207 } else {
4208 $this->responseSOAP = $this->serializeEnvelope($payload, $this->responseHeaders);
4209 }
4210 $this->debug("Leaving serialize_return");
4211 }
4212
4223 public function send_response()
4224 {
4225 $this->debug('Enter send_response');
4226 if ($this->fault) {
4227 $payload = $this->fault->serialize();
4228 $this->outgoing_headers[] = "HTTP/1.0 500 Internal Server Error";
4229 $this->outgoing_headers[] = "Status: 500 Internal Server Error";
4230 } else {
4232 // Some combinations of PHP+Web server allow the Status
4233 // to come through as a header. Since OK is the default
4234 // just do nothing.
4235 // $this->outgoing_headers[] = "HTTP/1.0 200 OK";
4236 // $this->outgoing_headers[] = "Status: 200 OK";
4237 }
4238 // add debug data if in debug mode
4239 if (isset($this->debug_flag) && $this->debug_flag) {
4240 $payload .= $this->getDebugAsXMLComment();
4241 }
4242 $this->outgoing_headers[] = "Server: $this->title Server v$this->version";
4243 preg_match('/\$Revisio' . 'n: ([^ ]+)/', $this->revision, $rev);
4244 $this->outgoing_headers[] = "X-SOAP-Server: $this->title/$this->version (" . $rev[1] . ")";
4245 // Let the Web server decide about this
4246 //$this->outgoing_headers[] = "Connection: Close\r\n";
4247 $payload = $this->getHTTPBody($payload);
4248 $type = $this->getHTTPContentType();
4249 $charset = $this->getHTTPContentTypeCharset();
4250 $this->outgoing_headers[] = "Content-Type: $type" . ($charset ? '; charset=' . $charset : '');
4251 //begin code to compress payload - by John
4252 // NOTE: there is no way to know whether the Web server will also compress
4253 // this data.
4254 if (strlen($payload) > 1024 && isset($this->headers) && isset($this->headers['accept-encoding'])) {
4255 if (strstr($this->headers['accept-encoding'], 'gzip')) {
4256 if (function_exists('gzencode')) {
4257 if (isset($this->debug_flag) && $this->debug_flag) {
4258 $payload .= "<!-- Content being gzipped -->";
4259 }
4260 $this->outgoing_headers[] = "Content-Encoding: gzip";
4261 $payload = gzencode($payload);
4262 } else {
4263 if (isset($this->debug_flag) && $this->debug_flag) {
4264 $payload .= "<!-- Content will not be gzipped: no gzencode -->";
4265 }
4266 }
4267 } elseif (strstr($this->headers['accept-encoding'], 'deflate')) {
4268 // Note: MSIE requires gzdeflate output (no Zlib header and checksum),
4269 // instead of gzcompress output,
4270 // which conflicts with HTTP 1.1 spec (http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.5)
4271 if (function_exists('gzdeflate')) {
4272 if (isset($this->debug_flag) && $this->debug_flag) {
4273 $payload .= "<!-- Content being deflated -->";
4274 }
4275 $this->outgoing_headers[] = "Content-Encoding: deflate";
4276 $payload = gzdeflate($payload);
4277 } else {
4278 if (isset($this->debug_flag) && $this->debug_flag) {
4279 $payload .= "<!-- Content will not be deflated: no gzcompress -->";
4280 }
4281 }
4282 }
4283 }
4284 //end code
4285 $this->outgoing_headers[] = "Content-Length: " . strlen($payload);
4286 reset($this->outgoing_headers);
4287 foreach ($this->outgoing_headers as $hdr) {
4288 header($hdr, false);
4289 }
4290 print $payload;
4291 $this->response = join("\r\n", $this->outgoing_headers) . "\r\n\r\n" . $payload;
4292 }
4293
4303 public function verify_method($operation, $request)
4304 {
4305 if (isset($this->wsdl) && is_object($this->wsdl)) {
4306 if ($this->wsdl->getOperationData($operation)) {
4307 return true;
4308 }
4309 } elseif (isset($this->operations[$operation])) {
4310 return true;
4311 }
4312 return false;
4313 }
4314
4323 public function parseRequest($headers, $data)
4324 {
4325 $this->debug('Entering parseRequest() for data of length ' . strlen($data) . ' and type ' . $headers['content-type']);
4326 if (!strstr($headers['content-type'], 'text/xml')) {
4327 $this->setError('Request not of type text/xml');
4328 return false;
4329 }
4330 if (strpos($headers['content-type'], '=')) {
4331 $enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1));
4332 $this->debug('Got response encoding: ' . $enc);
4333 if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i', $enc)) {
4334 $this->xml_encoding = strtoupper($enc);
4335 } else {
4336 $this->xml_encoding = 'US-ASCII';
4337 }
4338 } else {
4339 // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
4340 $this->xml_encoding = 'ISO-8859-1';
4341 }
4342 $this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser');
4343 // parse response, get soap parser obj
4344 $parser = new nusoap_parser($data, $this->xml_encoding, '', $this->decode_utf8);
4345 // parser debug
4346 $this->debug("parser debug: \n" . $parser->getDebug());
4347 // if fault occurred during message parsing
4348 if ($err = $parser->getError()) {
4349 $this->result = 'fault: error in msg parsing: ' . $err;
4350 $this->fault('SOAP-ENV:Client', "error in msg parsing:\n" . $err);
4351 // else successfully parsed request into soapval object
4352 } else {
4353 // get/set methodname
4354 $this->methodURI = $parser->root_struct_namespace;
4355 $this->methodname = $parser->root_struct_name;
4356 $this->debug('methodname: ' . $this->methodname . ' methodURI: ' . $this->methodURI);
4357 $this->debug('calling parser->get_soapbody()');
4358 $this->methodparams = $parser->get_soapbody();
4359 // get SOAP headers
4360 $this->requestHeaders = $parser->getHeaders();
4361 // get SOAP Header
4362 $this->requestHeader = $parser->get_soapheader();
4363 // add document for doclit support
4364 $this->document = $parser->document;
4365 }
4366 }
4367
4375 public function getHTTPBody($soapmsg)
4376 {
4377 return $soapmsg;
4378 }
4379
4388 public function getHTTPContentType()
4389 {
4390 return 'text/xml';
4391 }
4392
4402 public function getHTTPContentTypeCharset()
4403 {
4405 }
4406
4416 public function add_to_map($methodname, $in, $out)
4417 {
4418 $this->operations[$methodname] = array('name' => $methodname,'in' => $in,'out' => $out);
4419 }
4420
4435 public function register($name, $in=array(), $out=array(), $namespace=false, $soapaction=false, $style=false, $use=false, $documentation='', $encodingStyle='')
4436 {
4437 global $HTTP_SERVER_VARS;
4438
4439 if ($this->externalWSDLURL) {
4440 die('You cannot bind to an external WSDL file, and register methods outside of it! Please choose either WSDL or no WSDL.');
4441 }
4442 if (! $name) {
4443 die('You must specify a name when you register an operation');
4444 }
4445 if (!is_array($in)) {
4446 die('You must provide an array for operation inputs');
4447 }
4448 if (!is_array($out)) {
4449 die('You must provide an array for operation outputs');
4450 }
4451 if (false == $namespace) {
4452 }
4453 if (false == $soapaction) {
4454 if (isset($_SERVER)) {
4455 $SERVER_NAME = $_SERVER['SERVER_NAME'];
4456 $SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
4457 $HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off');
4458 } elseif (isset($HTTP_SERVER_VARS)) {
4459 $SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
4460 $SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
4461 $HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off';
4462 } else {
4463 $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
4464 }
4465 if ($HTTPS == '1' || $HTTPS == 'on') {
4466 $SCHEME = 'https';
4467 } else {
4468 $SCHEME = 'http';
4469 }
4470 $soapaction = "$SCHEME://$SERVER_NAME$SCRIPT_NAME/$name";
4471 }
4472 if (false == $style) {
4473 $style = "rpc";
4474 }
4475 if (false == $use) {
4476 $use = "encoded";
4477 }
4478 if ($use == 'encoded' && $encodingStyle = '') {
4479 $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
4480 }
4481
4482 $this->operations[$name] = array(
4483 'name' => $name,
4484 'in' => $in,
4485 'out' => $out,
4486 'namespace' => $namespace,
4487 'soapaction' => $soapaction,
4488 'style' => $style);
4489 if ($this->wsdl) {
4490 $this->wsdl->addOperation($name, $in, $out, $namespace, $soapaction, $style, $use, $documentation, $encodingStyle);
4491 }
4492 return true;
4493 }
4494
4505 public function fault($faultcode, $faultstring, $faultactor='', $faultdetail='')
4506 {
4507 if ($faultdetail == '' && $this->debug_flag) {
4508 $faultdetail = $this->getDebug();
4509 }
4510 $this->fault = new nusoap_fault($faultcode, $faultactor, $faultstring, $faultdetail);
4511 $this->fault->soap_defencoding = $this->soap_defencoding;
4512 }
4513
4525 public function configureWSDL($serviceName, $namespace = false, $endpoint = false, $style='rpc', $transport = 'http://schemas.xmlsoap.org/soap/http', $schemaTargetNamespace = false)
4526 {
4527 global $HTTP_SERVER_VARS;
4528
4529 if (isset($_SERVER)) {
4530 $SERVER_NAME = $_SERVER['SERVER_NAME'];
4531 $SERVER_PORT = $_SERVER['SERVER_PORT'];
4532 $SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
4533 $HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off');
4534 } elseif (isset($HTTP_SERVER_VARS)) {
4535 $SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
4536 $SERVER_PORT = $HTTP_SERVER_VARS['SERVER_PORT'];
4537 $SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
4538 $HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off';
4539 } else {
4540 $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
4541 }
4542 // If server name has port number attached then strip it (else port number gets duplicated in WSDL output) (occurred using lighttpd and FastCGI)
4543 $colon = strpos($SERVER_NAME, ":");
4544 if ($colon) {
4545 $SERVER_NAME = substr($SERVER_NAME, 0, $colon);
4546 }
4547 if ($SERVER_PORT == 80) {
4548 $SERVER_PORT = '';
4549 } else {
4550 $SERVER_PORT = ':' . $SERVER_PORT;
4551 }
4552 if (false == $namespace) {
4553 $namespace = "http://$SERVER_NAME/soap/$serviceName";
4554 }
4555
4556 if (false == $endpoint) {
4557 if ($HTTPS == '1' || $HTTPS == 'on') {
4558 $SCHEME = 'https';
4559 } else {
4560 $SCHEME = 'http';
4561 }
4562 $endpoint = "$SCHEME://$SERVER_NAME$SERVER_PORT$SCRIPT_NAME";
4563 }
4564
4565 if (false == $schemaTargetNamespace) {
4566 $schemaTargetNamespace = $namespace;
4567 }
4568
4569 $this->wsdl = new wsdl();
4570 $this->wsdl->serviceName = $serviceName;
4571 $this->wsdl->endpoint = $endpoint;
4572 $this->wsdl->namespaces['tns'] = $namespace;
4573 $this->wsdl->namespaces['soap'] = 'http://schemas.xmlsoap.org/wsdl/soap/';
4574 $this->wsdl->namespaces['wsdl'] = 'http://schemas.xmlsoap.org/wsdl/';
4575 if ($schemaTargetNamespace != $namespace) {
4576 $this->wsdl->namespaces['types'] = $schemaTargetNamespace;
4577 }
4578 $this->wsdl->schemas[$schemaTargetNamespace][0] = new nusoap_xmlschema('', '', $this->wsdl->namespaces);
4579 if ($style == 'document') {
4580 $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaInfo['elementFormDefault'] = 'qualified';
4581 }
4582 $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaTargetNamespace = $schemaTargetNamespace;
4583 $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/soap/encoding/'][0] = array('location' => '', 'loaded' => true);
4584 $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/wsdl/'][0] = array('location' => '', 'loaded' => true);
4585 $this->wsdl->bindings[$serviceName . 'Binding'] = array(
4586 'name'=>$serviceName . 'Binding',
4587 'style'=>$style,
4588 'transport'=>$transport,
4589 'portType'=>$serviceName . 'PortType');
4590 $this->wsdl->ports[$serviceName . 'Port'] = array(
4591 'binding'=>$serviceName . 'Binding',
4592 'location'=>$endpoint,
4593 'bindingType'=>'http://schemas.xmlsoap.org/wsdl/soap/');
4594 }
4595}
4596
4600class soap_server extends nusoap_server
4601{
4602}
4603
4604?><?php
4605
4606
4607
4617class wsdl extends nusoap_base
4618{
4619 // URL or filename of the root of this WSDL
4620 public $wsdl;
4621 // define internal arrays of bindings, ports, operations, messages, etc.
4622 public $schemas = array();
4623 public $currentSchema;
4624 public $message = array();
4625 public $complexTypes = array();
4626 public $messages = array();
4627 public $currentMessage;
4628 public $currentOperation;
4629 public $portTypes = array();
4630 public $currentPortType;
4631 public $bindings = array();
4632 public $currentBinding;
4633 public $ports = array();
4634 public $currentPort;
4635 public $opData = array();
4636 public $status = '';
4637 public $documentation = false;
4638 public $endpoint = '';
4639 // array of wsdl docs to import
4640 public $import = array();
4641 // parser vars
4642 public $parser;
4643 public $position = 0;
4644 public $depth = 0;
4645 public $depth_array = array();
4646 // for getting wsdl
4647 public $proxyhost = '';
4648 public $proxyport = '';
4649 public $proxyusername = '';
4650 public $proxypassword = '';
4651 public $timeout = 0;
4652 public $response_timeout = 30;
4653 public $curl_options = array(); // User-specified cURL options
4654 public $use_curl = false; // whether to always try to use cURL
4655 // for HTTP authentication
4656 public $username = ''; // Username for HTTP authentication
4657 public $password = ''; // Password for HTTP authentication
4658 public $authtype = ''; // Type of HTTP authentication
4659 public $certRequest = array(); // Certificate for HTTP SSL authentication
4660
4675 public function __construct($wsdl = '', $proxyhost=false, $proxyport=false, $proxyusername=false, $proxypassword=false, $timeout=0, $response_timeout=30, $curl_options=null, $use_curl=false)
4676 {
4678 $this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout");
4679 $this->proxyhost = $proxyhost;
4680 $this->proxyport = $proxyport;
4681 $this->proxyusername = $proxyusername;
4682 $this->proxypassword = $proxypassword;
4683 $this->timeout = $timeout;
4684 $this->response_timeout = $response_timeout;
4685 if (is_array($curl_options)) {
4686 $this->curl_options = $curl_options;
4687 }
4688 $this->use_curl = $use_curl;
4689 $this->fetchWSDL($wsdl);
4690 }
4691
4697 public function fetchWSDL($wsdl)
4698 {
4699 $this->debug("parse and process WSDL path=$wsdl");
4700 $this->wsdl = $wsdl;
4701 // parse wsdl file
4702 if ($this->wsdl != "") {
4703 $this->parseWSDL($this->wsdl);
4704 }
4705 // imports
4706 // TODO: handle imports more properly, grabbing them in-line and nesting them
4707 $imported_urls = array();
4708 $imported = 1;
4709 while ($imported > 0) {
4710 $imported = 0;
4711 // Schema imports
4712 foreach ($this->schemas as $ns => $list) {
4713 foreach ($list as $xs) {
4714 $wsdlparts = parse_url($this->wsdl); // this is bogusly simple!
4715 foreach ($xs->imports as $ns2 => $list2) {
4716 for ($ii = 0; $ii < count($list2); $ii++) {
4717 if (! $list2[$ii]['loaded']) {
4718 $this->schemas[$ns]->imports[$ns2][$ii]['loaded'] = true;
4719 $url = $list2[$ii]['location'];
4720 if ($url != '') {
4721 $urlparts = parse_url($url);
4722 if (!isset($urlparts['host'])) {
4723 $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' . $wsdlparts['port'] : '') .
4724 substr($wsdlparts['path'], 0, strrpos($wsdlparts['path'], '/') + 1) . $urlparts['path'];
4725 }
4726 if (! in_array($url, $imported_urls)) {
4727 $this->parseWSDL($url);
4728 $imported++;
4729 $imported_urls[] = $url;
4730 }
4731 } else {
4732 $this->debug("Unexpected scenario: empty URL for unloaded import");
4733 }
4734 }
4735 }
4736 }
4737 }
4738 }
4739 // WSDL imports
4740 $wsdlparts = parse_url($this->wsdl); // this is bogusly simple!
4741 foreach ($this->import as $ns => $list) {
4742 for ($ii = 0; $ii < count($list); $ii++) {
4743 if (! $list[$ii]['loaded']) {
4744 $this->import[$ns][$ii]['loaded'] = true;
4745 $url = $list[$ii]['location'];
4746 if ($url != '') {
4747 $urlparts = parse_url($url);
4748 if (!isset($urlparts['host'])) {
4749 $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' . $wsdlparts['port'] : '') .
4750 substr($wsdlparts['path'], 0, strrpos($wsdlparts['path'], '/') + 1) . $urlparts['path'];
4751 }
4752 if (! in_array($url, $imported_urls)) {
4753 $this->parseWSDL($url);
4754 $imported++;
4755 $imported_urls[] = $url;
4756 }
4757 } else {
4758 $this->debug("Unexpected scenario: empty URL for unloaded import");
4759 }
4760 }
4761 }
4762 }
4763 }
4764 // add new data to operation data
4765 foreach ($this->bindings as $binding => $bindingData) {
4766 if (isset($bindingData['operations']) && is_array($bindingData['operations'])) {
4767 foreach ($bindingData['operations'] as $operation => $data) {
4768 $this->debug('post-parse data gathering for ' . $operation);
4769 $this->bindings[$binding]['operations'][$operation]['input'] =
4770 isset($this->bindings[$binding]['operations'][$operation]['input']) ?
4771 array_merge($this->bindings[$binding]['operations'][$operation]['input'], $this->portTypes[ $bindingData['portType'] ][$operation]['input']) :
4772 $this->portTypes[ $bindingData['portType'] ][$operation]['input'];
4773 $this->bindings[$binding]['operations'][$operation]['output'] =
4774 isset($this->bindings[$binding]['operations'][$operation]['output']) ?
4775 array_merge($this->bindings[$binding]['operations'][$operation]['output'], $this->portTypes[ $bindingData['portType'] ][$operation]['output']) :
4776 $this->portTypes[ $bindingData['portType'] ][$operation]['output'];
4777 if (isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ])) {
4778 $this->bindings[$binding]['operations'][$operation]['input']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ];
4779 }
4780 if (isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ])) {
4781 $this->bindings[$binding]['operations'][$operation]['output']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ];
4782 }
4783 // Set operation style if necessary, but do not override one already provided
4784 if (isset($bindingData['style']) && !isset($this->bindings[$binding]['operations'][$operation]['style'])) {
4785 $this->bindings[$binding]['operations'][$operation]['style'] = $bindingData['style'];
4786 }
4787 $this->bindings[$binding]['operations'][$operation]['transport'] = isset($bindingData['transport']) ? $bindingData['transport'] : '';
4788 $this->bindings[$binding]['operations'][$operation]['documentation'] = isset($this->portTypes[ $bindingData['portType'] ][$operation]['documentation']) ? $this->portTypes[ $bindingData['portType'] ][$operation]['documentation'] : '';
4789 $this->bindings[$binding]['operations'][$operation]['endpoint'] = isset($bindingData['endpoint']) ? $bindingData['endpoint'] : '';
4790 }
4791 }
4792 }
4793 }
4794
4801 public function parseWSDL($wsdl = '')
4802 {
4803 $this->debug("parse WSDL at path=$wsdl");
4804
4805 if ($wsdl == '') {
4806 $this->debug('no wsdl passed to parseWSDL()!!');
4807 $this->setError('no wsdl passed to parseWSDL()!!');
4808 return false;
4809 }
4810
4811 // parse $wsdl for url format
4812 $wsdl_props = parse_url($wsdl);
4813
4814 if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'http' || $wsdl_props['scheme'] == 'https')) {
4815 $this->debug('getting WSDL http(s) URL ' . $wsdl);
4816 // get wsdl
4817 $tr = new soap_transport_http($wsdl, $this->curl_options, $this->use_curl);
4818 $tr->request_method = 'GET';
4819 $tr->useSOAPAction = false;
4820 if ($this->proxyhost && $this->proxyport) {
4821 $tr->setProxy($this->proxyhost, $this->proxyport, $this->proxyusername, $this->proxypassword);
4822 }
4823 if ($this->authtype != '') {
4824 $tr->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest);
4825 }
4826 $tr->setEncoding('gzip, deflate');
4827 $wsdl_string = $tr->send('', $this->timeout, $this->response_timeout);
4828 //$this->debug("WSDL request\n" . $tr->outgoing_payload);
4829 //$this->debug("WSDL response\n" . $tr->incoming_payload);
4830 $this->appendDebug($tr->getDebug());
4831 // catch errors
4832 if ($err = $tr->getError()) {
4833 $errstr = 'HTTP ERROR: ' . $err;
4834 $this->debug($errstr);
4835 $this->setError($errstr);
4836 unset($tr);
4837 return false;
4838 }
4839 unset($tr);
4840 $this->debug("got WSDL URL");
4841 } else {
4842 // $wsdl is not http(s), so treat it as a file URL or plain file path
4843 if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'file') && isset($wsdl_props['path'])) {
4844 $path = isset($wsdl_props['host']) ? ($wsdl_props['host'] . ':' . $wsdl_props['path']) : $wsdl_props['path'];
4845 } else {
4846 $path = $wsdl;
4847 }
4848 $this->debug('getting WSDL file ' . $path);
4849 if ($fp = @fopen($path, 'r')) {
4850 $wsdl_string = '';
4851 while ($data = fread($fp, 32768)) {
4852 $wsdl_string .= $data;
4853 }
4854 fclose($fp);
4855 } else {
4856 $errstr = "Bad path to WSDL file $path";
4857 $this->debug($errstr);
4858 $this->setError($errstr);
4859 return false;
4860 }
4861 }
4862 $this->debug('Parse WSDL');
4863 // end new code added
4864 // Create an XML parser.
4865 $this->parser = xml_parser_create();
4866 // Set the options for parsing the XML data.
4867 // xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
4868 xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
4869 // Set the object for the parser.
4870 xml_set_object($this->parser, $this);
4871 // Set the element handlers for the parser.
4872 xml_set_element_handler($this->parser, 'start_element', 'end_element');
4873 xml_set_character_data_handler($this->parser, 'character_data');
4874 // Parse the XML file.
4875 if (!xml_parse($this->parser, $wsdl_string, true)) {
4876 // Display an error message.
4877 $errstr = sprintf(
4878 'XML error parsing WSDL from %s on line %d: %s',
4879 $wsdl,
4880 xml_get_current_line_number($this->parser),
4881 xml_error_string(xml_get_error_code($this->parser))
4882 );
4883 $this->debug($errstr);
4884 $this->debug("XML payload:\n" . $wsdl_string);
4885 $this->setError($errstr);
4886 return false;
4887 }
4888 // free the parser
4889 xml_parser_free($this->parser);
4890 $this->debug('Parsing WSDL done');
4891 // catch wsdl parse errors
4892 if ($this->getError()) {
4893 return false;
4894 }
4895 return true;
4896 }
4897
4906 public function start_element($parser, $name, $attrs)
4907 {
4908 if ($this->status == 'schema') {
4909 $this->currentSchema->schemaStartElement($parser, $name, $attrs);
4910 $this->appendDebug($this->currentSchema->getDebug());
4911 $this->currentSchema->clearDebug();
4912 } elseif (preg_match('/schema$/', $name)) {
4913 $this->debug('Parsing WSDL schema');
4914 // $this->debug("startElement for $name ($attrs[name]). status = $this->status (".$this->getLocalPart($name).")");
4915 $this->status = 'schema';
4916 $this->currentSchema = new nusoap_xmlschema('', '', $this->namespaces);
4917 $this->currentSchema->schemaStartElement($parser, $name, $attrs);
4918 $this->appendDebug($this->currentSchema->getDebug());
4919 $this->currentSchema->clearDebug();
4920 } else {
4921 // position in the total number of elements, starting from 0
4922 $pos = $this->position++;
4923 $depth = $this->depth++;
4924 // set self as current value for this depth
4925 $this->depth_array[$depth] = $pos;
4926 $this->message[$pos] = array('cdata' => '');
4927 // process attributes
4928 if (count($attrs) > 0) {
4929 // register namespace declarations
4930 foreach ($attrs as $k => $v) {
4931 if (preg_match('/^xmlns/', $k)) {
4932 if ($ns_prefix = substr(strrchr($k, ':'), 1)) {
4933 $this->namespaces[$ns_prefix] = $v;
4934 } else {
4935 $this->namespaces['ns' . (count($this->namespaces) + 1)] = $v;
4936 }
4937 if ($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema') {
4938 $this->XMLSchemaVersion = $v;
4939 $this->namespaces['xsi'] = $v . '-instance';
4940 }
4941 }
4942 }
4943 // expand each attribute prefix to its namespace
4944 foreach ($attrs as $k => $v) {
4945 $k = strpos($k, ':') ? $this->expandQname($k) : $k;
4946 if ($k != 'location' && $k != 'soapAction' && $k != 'namespace') {
4947 $v = strpos($v, ':') ? $this->expandQname($v) : $v;
4948 }
4949 $eAttrs[$k] = $v;
4950 }
4951 $attrs = $eAttrs;
4952 } else {
4953 $attrs = array();
4954 }
4955 // get element prefix, namespace and name
4956 if (preg_match('/:/', $name)) {
4957 // get ns prefix
4958 $prefix = substr($name, 0, strpos($name, ':'));
4959 // get ns
4960 $namespace = isset($this->namespaces[$prefix]) ? $this->namespaces[$prefix] : '';
4961 // get unqualified name
4962 $name = substr(strstr($name, ':'), 1);
4963 }
4964 // process attributes, expanding any prefixes to namespaces
4965 // find status, register data
4966 switch ($this->status) {
4967 case 'message':
4968 if ($name == 'part') {
4969 if (isset($attrs['type'])) {
4970 $this->debug("msg " . $this->currentMessage . ": found part (with type) $attrs[name]: " . implode(',', $attrs));
4971 $this->messages[$this->currentMessage][$attrs['name']] = $attrs['type'];
4972 }
4973 if (isset($attrs['element'])) {
4974 $this->debug("msg " . $this->currentMessage . ": found part (with element) $attrs[name]: " . implode(',', $attrs));
4975 $this->messages[$this->currentMessage][$attrs['name']] = $attrs['element'] . '^';
4976 }
4977 }
4978 break;
4979 case 'portType':
4980 switch ($name) {
4981 case 'operation':
4982 $this->currentPortOperation = $attrs['name'];
4983 $this->debug("portType $this->currentPortType operation: $this->currentPortOperation");
4984 if (isset($attrs['parameterOrder'])) {
4985 $this->portTypes[$this->currentPortType][$attrs['name']]['parameterOrder'] = $attrs['parameterOrder'];
4986 }
4987 break;
4988 case 'documentation':
4989 $this->documentation = true;
4990 break;
4991 // merge input/output data
4992 default:
4993 $m = isset($attrs['message']) ? $this->getLocalPart($attrs['message']) : '';
4994 $this->portTypes[$this->currentPortType][$this->currentPortOperation][$name]['message'] = $m;
4995 break;
4996 }
4997 break;
4998 case 'binding':
4999 switch ($name) {
5000 case 'binding':
5001 // get ns prefix
5002 if (isset($attrs['style'])) {
5003 $this->bindings[$this->currentBinding]['prefix'] = $prefix;
5004 }
5005 $this->bindings[$this->currentBinding] = array_merge($this->bindings[$this->currentBinding], $attrs);
5006 break;
5007 case 'header':
5008 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus]['headers'][] = $attrs;
5009 break;
5010 case 'operation':
5011 if (isset($attrs['soapAction'])) {
5012 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['soapAction'] = $attrs['soapAction'];
5013 }
5014 if (isset($attrs['style'])) {
5015 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['style'] = $attrs['style'];
5016 }
5017 if (isset($attrs['name'])) {
5018 $this->currentOperation = $attrs['name'];
5019 $this->debug("current binding operation: $this->currentOperation");
5020 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['name'] = $attrs['name'];
5021 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['binding'] = $this->currentBinding;
5022 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['endpoint'] = isset($this->bindings[$this->currentBinding]['endpoint']) ? $this->bindings[$this->currentBinding]['endpoint'] : '';
5023 }
5024 break;
5025 case 'input':
5026 $this->opStatus = 'input';
5027 break;
5028 case 'output':
5029 $this->opStatus = 'output';
5030 break;
5031 case 'body':
5032 if (isset($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus])) {
5033 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = array_merge($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus], $attrs);
5034 } else {
5035 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = $attrs;
5036 }
5037 break;
5038 }
5039 break;
5040 case 'service':
5041 switch ($name) {
5042 case 'port':
5043 $this->currentPort = $attrs['name'];
5044 $this->debug('current port: ' . $this->currentPort);
5045 $this->ports[$this->currentPort]['binding'] = $this->getLocalPart($attrs['binding']);
5046
5047 break;
5048 case 'address':
5049 $this->ports[$this->currentPort]['location'] = $attrs['location'];
5050 $this->ports[$this->currentPort]['bindingType'] = $namespace;
5051 $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['bindingType'] = $namespace;
5052 $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['endpoint'] = $attrs['location'];
5053 break;
5054 }
5055 break;
5056 }
5057 // set status
5058 switch ($name) {
5059 case 'import':
5060 if (isset($attrs['location'])) {
5061 $this->import[$attrs['namespace']][] = array('location' => $attrs['location'], 'loaded' => false);
5062 $this->debug('parsing import ' . $attrs['namespace'] . ' - ' . $attrs['location'] . ' (' . count($this->import[$attrs['namespace']]) . ')');
5063 } else {
5064 $this->import[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
5065 if (! $this->getPrefixFromNamespace($attrs['namespace'])) {
5066 $this->namespaces['ns' . (count($this->namespaces)+1)] = $attrs['namespace'];
5067 }
5068 $this->debug('parsing import ' . $attrs['namespace'] . ' - [no location] (' . count($this->import[$attrs['namespace']]) . ')');
5069 }
5070 break;
5071 //wait for schema
5072 //case 'types':
5073 // $this->status = 'schema';
5074 // break;
5075 case 'message':
5076 $this->status = 'message';
5077 $this->messages[$attrs['name']] = array();
5078 $this->currentMessage = $attrs['name'];
5079 break;
5080 case 'portType':
5081 $this->status = 'portType';
5082 $this->portTypes[$attrs['name']] = array();
5083 $this->currentPortType = $attrs['name'];
5084 break;
5085 case "binding":
5086 if (isset($attrs['name'])) {
5087 // get binding name
5088 if (strpos($attrs['name'], ':')) {
5089 $this->currentBinding = $this->getLocalPart($attrs['name']);
5090 } else {
5091 $this->currentBinding = $attrs['name'];
5092 }
5093 $this->status = 'binding';
5094 $this->bindings[$this->currentBinding]['portType'] = $this->getLocalPart($attrs['type']);
5095 $this->debug("current binding: $this->currentBinding of portType: " . $attrs['type']);
5096 }
5097 break;
5098 case 'service':
5099 $this->serviceName = $attrs['name'];
5100 $this->status = 'service';
5101 $this->debug('current service: ' . $this->serviceName);
5102 break;
5103 case 'definitions':
5104 foreach ($attrs as $name => $value) {
5105 $this->wsdl_info[$name] = $value;
5106 }
5107 break;
5108 }
5109 }
5110 }
5111
5119 public function end_element($parser, $name)
5120 {
5121 // unset schema status
5122 if (/*preg_match('/types$/', $name) ||*/ preg_match('/schema$/', $name)) {
5123 $this->status = "";
5124 $this->appendDebug($this->currentSchema->getDebug());
5125 $this->currentSchema->clearDebug();
5126 $this->schemas[$this->currentSchema->schemaTargetNamespace][] = $this->currentSchema;
5127 $this->debug('Parsing WSDL schema done');
5128 }
5129 if ($this->status == 'schema') {
5130 $this->currentSchema->schemaEndElement($parser, $name);
5131 } else {
5132 // bring depth down a notch
5133 $this->depth--;
5134 }
5135 // end documentation
5136 if ($this->documentation) {
5137 //TODO: track the node to which documentation should be assigned; it can be a part, message, etc.
5138 //$this->portTypes[$this->currentPortType][$this->currentPortOperation]['documentation'] = $this->documentation;
5139 $this->documentation = false;
5140 }
5141 }
5142
5150 public function character_data($parser, $data)
5151 {
5152 $pos = isset($this->depth_array[$this->depth]) ? $this->depth_array[$this->depth] : 0;
5153 if (isset($this->message[$pos]['cdata'])) {
5154 $this->message[$pos]['cdata'] .= $data;
5155 }
5156 if ($this->documentation) {
5157 $this->documentation .= $data;
5158 }
5159 }
5160
5170 public function setCredentials($username, $password, $authtype = 'basic', $certRequest = array())
5171 {
5172 $this->debug("setCredentials username=$username authtype=$authtype certRequest=");
5173 $this->appendDebug($this->varDump($certRequest));
5174 $this->username = $username;
5175 $this->password = $password;
5176 $this->authtype = $authtype;
5177 $this->certRequest = $certRequest;
5178 }
5179
5180 public function getBindingData($binding)
5181 {
5182 if (is_array($this->bindings[$binding])) {
5183 return $this->bindings[$binding];
5184 }
5185 }
5186
5194 public function getOperations($bindingType = 'soap')
5195 {
5196 $ops = array();
5197 if ($bindingType == 'soap') {
5198 $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
5199 } elseif ($bindingType == 'soap12') {
5200 $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
5201 }
5202 // loop thru ports
5203 foreach ($this->ports as $port => $portData) {
5204 // binding type of port matches parameter
5205 if ($portData['bindingType'] == $bindingType) {
5206 //$this->debug("getOperations for port $port");
5207 //$this->debug("port data: " . $this->varDump($portData));
5208 //$this->debug("bindings: " . $this->varDump($this->bindings[ $portData['binding'] ]));
5209 // merge bindings
5210 if (isset($this->bindings[ $portData['binding'] ]['operations'])) {
5211 $ops = array_merge($ops, $this->bindings[ $portData['binding'] ]['operations']);
5212 }
5213 }
5214 }
5215 return $ops;
5216 }
5217
5226 public function getOperationData($operation, $bindingType = 'soap')
5227 {
5228 if ($bindingType == 'soap') {
5229 $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
5230 } elseif ($bindingType == 'soap12') {
5231 $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
5232 }
5233 // loop thru ports
5234 foreach ($this->ports as $port => $portData) {
5235 // binding type of port matches parameter
5236 if ($portData['bindingType'] == $bindingType) {
5237 // get binding
5238 //foreach($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) {
5239 foreach (array_keys($this->bindings[ $portData['binding'] ]['operations']) as $bOperation) {
5240 // note that we could/should also check the namespace here
5241 if ($operation == $bOperation) {
5242 $opData = $this->bindings[ $portData['binding'] ]['operations'][$operation];
5243 return $opData;
5244 }
5245 }
5246 }
5247 }
5248 }
5249
5258 public function getOperationDataForSoapAction($soapAction, $bindingType = 'soap')
5259 {
5260 if ($bindingType == 'soap') {
5261 $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
5262 } elseif ($bindingType == 'soap12') {
5263 $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
5264 }
5265 // loop thru ports
5266 foreach ($this->ports as $port => $portData) {
5267 // binding type of port matches parameter
5268 if ($portData['bindingType'] == $bindingType) {
5269 // loop through operations for the binding
5270 foreach ($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) {
5271 if ($opData['soapAction'] == $soapAction) {
5272 return $opData;
5273 }
5274 }
5275 }
5276 }
5277 }
5278
5297 public function getTypeDef($type, $ns)
5298 {
5299 $this->debug("in getTypeDef: type=$type, ns=$ns");
5300 if ((! $ns) && isset($this->namespaces['tns'])) {
5301 $ns = $this->namespaces['tns'];
5302 $this->debug("in getTypeDef: type namespace forced to $ns");
5303 }
5304 if (!isset($this->schemas[$ns])) {
5305 foreach ($this->schemas as $ns0 => $schema0) {
5306 if (strcasecmp($ns, $ns0) == 0) {
5307 $this->debug("in getTypeDef: replacing schema namespace $ns with $ns0");
5308 $ns = $ns0;
5309 break;
5310 }
5311 }
5312 }
5313 if (isset($this->schemas[$ns])) {
5314 $this->debug("in getTypeDef: have schema for namespace $ns");
5315 for ($i = 0; $i < count($this->schemas[$ns]); $i++) {
5316 $xs = &$this->schemas[$ns][$i];
5317 $t = $xs->getTypeDef($type);
5318 //$this->appendDebug($xs->getDebug());
5319 //$xs->clearDebug();
5320 if ($t) {
5321 if (!isset($t['phpType'])) {
5322 // get info for type to tack onto the element
5323 $uqType = substr($t['type'], strrpos($t['type'], ':') + 1);
5324 $ns = substr($t['type'], 0, strrpos($t['type'], ':'));
5325 $etype = $this->getTypeDef($uqType, $ns);
5326 if ($etype) {
5327 $this->debug("found type for [element] $type:");
5328 $this->debug($this->varDump($etype));
5329 if (isset($etype['phpType'])) {
5330 $t['phpType'] = $etype['phpType'];
5331 }
5332 if (isset($etype['elements'])) {
5333 $t['elements'] = $etype['elements'];
5334 }
5335 if (isset($etype['attrs'])) {
5336 $t['attrs'] = $etype['attrs'];
5337 }
5338 }
5339 }
5340 return $t;
5341 }
5342 }
5343 } else {
5344 $this->debug("in getTypeDef: do not have schema for namespace $ns");
5345 }
5346 return false;
5347 }
5348
5354 public function webDescription()
5355 {
5356 global $HTTP_SERVER_VARS;
5357
5358 if (isset($_SERVER)) {
5359 $PHP_SELF = $_SERVER['PHP_SELF'];
5360 } elseif (isset($HTTP_SERVER_VARS)) {
5361 $PHP_SELF = $HTTP_SERVER_VARS['PHP_SELF'];
5362 } else {
5363 $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
5364 }
5365 // begin-patch: https://mantis.ilias.de/view.php?id=28866
5366 $PHP_SELF = filter_var($PHP_SELF, FILTER_SANITIZE_STRING);
5367 // end-patch
5368
5369 $b = '
5370 <html><head><title>NuSOAP: ' . $this->serviceName . '</title>
5371 <style type="text/css">
5372 body { font-family: arial; color: #000000; background-color: #ffffff; margin: 0px 0px 0px 0px; }
5373 p { font-family: arial; color: #000000; margin-top: 0px; margin-bottom: 12px; }
5374 pre { background-color: silver; padding: 5px; font-family: Courier New; font-size: x-small; color: #000000;}
5375 ul { margin-top: 10px; margin-left: 20px; }
5376 li { list-style-type: none; margin-top: 10px; color: #000000; }
5377 .content{
5378 margin-left: 0px; padding-bottom: 2em; }
5379 .nav {
5380 padding-top: 10px; padding-bottom: 10px; padding-left: 15px; font-size: .70em;
5381 margin-top: 10px; margin-left: 0px; color: #000000;
5382 background-color: #ccccff; width: 20%; margin-left: 20px; margin-top: 20px; }
5383 .title {
5384 font-family: arial; font-size: 26px; color: #ffffff;
5385 background-color: #999999; width: 105%; margin-left: 0px;
5386 padding-top: 10px; padding-bottom: 10px; padding-left: 15px;}
5387 .hidden {
5388 position: absolute; visibility: hidden; z-index: 200; left: 250px; top: 100px;
5389 font-family: arial; overflow: hidden; width: 600;
5390 padding: 20px; font-size: 10px; background-color: #999999;
5391 layer-background-color:#FFFFFF; }
5392 a,a:active { color: charcoal; font-weight: bold; }
5393 a:visited { color: #666666; font-weight: bold; }
5394 a:hover { color: cc3300; font-weight: bold; }
5395 </style>
5396 <script language="JavaScript" type="text/javascript">
5397 <!--
5398 // POP-UP CAPTIONS...
5399 function lib_bwcheck(){ //Browsercheck (needed)
5400 this.ver=navigator.appVersion
5401 this.agent=navigator.userAgent
5402 this.dom=document.getElementById?1:0
5403 this.opera5=this.agent.indexOf("Opera 5")>-1
5404 this.ie5=(this.ver.indexOf("MSIE 5")>-1 && this.dom && !this.opera5)?1:0;
5405 this.ie6=(this.ver.indexOf("MSIE 6")>-1 && this.dom && !this.opera5)?1:0;
5406 this.ie4=(document.all && !this.dom && !this.opera5)?1:0;
5407 this.ie=this.ie4||this.ie5||this.ie6
5408 this.mac=this.agent.indexOf("Mac")>-1
5409 this.ns6=(this.dom && parseInt(this.ver) >= 5) ?1:0;
5410 this.ns4=(document.layers && !this.dom)?1:0;
5411 this.bw=(this.ie6 || this.ie5 || this.ie4 || this.ns4 || this.ns6 || this.opera5)
5412 return this
5413 }
5414 var bw = new lib_bwcheck()
5415 //Makes crossbrowser object.
5416 function makeObj(obj){
5417 this.evnt=bw.dom? document.getElementById(obj):bw.ie4?document.all[obj]:bw.ns4?document.layers[obj]:0;
5418 if(!this.evnt) return false
5419 this.css=bw.dom||bw.ie4?this.evnt.style:bw.ns4?this.evnt:0;
5420 this.wref=bw.dom||bw.ie4?this.evnt:bw.ns4?this.css.document:0;
5421 this.writeIt=b_writeIt;
5422 return this
5423 }
5424 // A unit of measure that will be added when setting the position of a layer.
5425 //var px = bw.ns4||window.opera?"":"px";
5426 function b_writeIt(text){
5427 if (bw.ns4){this.wref.write(text);this.wref.close()}
5428 else this.wref.innerHTML = text
5429 }
5430 //Shows the messages
5431 var oDesc;
5432 function popup(divid){
5433 if(oDesc = new makeObj(divid)){
5434 oDesc.css.visibility = "visible"
5435 }
5436 }
5437 function popout(){ // Hides message
5438 if(oDesc) oDesc.css.visibility = "hidden"
5439 }
5440 //-->
5441 </script>
5442 </head>
5443 <body>
5444 <div class=content>
5445 <br><br>
5446 <div class=title>' . $this->serviceName . '</div>
5447 <div class=nav>
5448 <p>View the <a href="' . $PHP_SELF . '?wsdl">WSDL</a> for the service.
5449 Click on an operation name to view it&apos;s details.</p>
5450 <ul>';
5451 foreach ($this->getOperations() as $op => $data) {
5452 // begin-patch: https://mantis.ilias.de/view.php?id=28866
5453 if (isset($data['endpoint'])) {
5454 $data['endpoint'] = filter_var($data['endpoint'], FILTER_SANITIZE_STRING);
5455 }
5456 // end-patch
5457 $b .= "<li><a href='#' onclick=\"popout();popup('$op')\">$op</a></li>";
5458 // create hidden div
5459 $b .= "<div id='$op' class='hidden'>
5460 <a href='#' onclick='popout()'><font color='#ffffff'>Close</font></a><br><br>";
5461 foreach ($data as $donnie => $marie) { // loop through opdata
5462 if ($donnie == 'input' || $donnie == 'output') { // show input/output data
5463 $b .= "<font color='white'>" . ucfirst($donnie) . ':</font><br>';
5464 foreach ($marie as $captain => $tenille) { // loop through data
5465 if ($captain == 'parts') { // loop thru parts
5466 $b .= "&nbsp;&nbsp;$captain:<br>";
5467 //if(is_array($tenille)){
5468 foreach ($tenille as $joanie => $chachi) {
5469 $b .= "&nbsp;&nbsp;&nbsp;&nbsp;$joanie: $chachi<br>";
5470 }
5471 //}
5472 } else {
5473 $b .= "&nbsp;&nbsp;$captain: $tenille<br>";
5474 }
5475 }
5476 } else {
5477 $b .= "<font color='white'>" . ucfirst($donnie) . ":</font> $marie<br>";
5478 }
5479 }
5480 $b .= '</div>';
5481 }
5482 $b .= '
5483 <ul>
5484 </div>
5485 </div></body></html>';
5486 return $b;
5487 }
5488
5496 public function serialize($debug = 0)
5497 {
5498 $xml = '<?xml version="1.0" encoding="ISO-8859-1"?>';
5499 $xml .= "\n<definitions";
5500 foreach ($this->namespaces as $k => $v) {
5501 $xml .= " xmlns:$k=\"$v\"";
5502 }
5503 // 10.9.02 - add poulter fix for wsdl and tns declarations
5504 if (isset($this->namespaces['wsdl'])) {
5505 $xml .= " xmlns=\"" . $this->namespaces['wsdl'] . "\"";
5506 }
5507 if (isset($this->namespaces['tns'])) {
5508 $xml .= " targetNamespace=\"" . $this->namespaces['tns'] . "\"";
5509 }
5510 $xml .= '>';
5511 // imports
5512 if (sizeof($this->import) > 0) {
5513 foreach ($this->import as $ns => $list) {
5514 foreach ($list as $ii) {
5515 if ($ii['location'] != '') {
5516 $xml .= '<import location="' . $ii['location'] . '" namespace="' . $ns . '" />';
5517 } else {
5518 $xml .= '<import namespace="' . $ns . '" />';
5519 }
5520 }
5521 }
5522 }
5523 // types
5524 if (count($this->schemas)>=1) {
5525 $xml .= "\n<types>\n";
5526 foreach ($this->schemas as $ns => $list) {
5527 foreach ($list as $xs) {
5528 $xml .= $xs->serializeSchema();
5529 }
5530 }
5531 $xml .= '</types>';
5532 }
5533 // messages
5534 if (count($this->messages) >= 1) {
5535 foreach ($this->messages as $msgName => $msgParts) {
5536 $xml .= "\n<message name=\"" . $msgName . '">';
5537 if (is_array($msgParts)) {
5538 foreach ($msgParts as $partName => $partType) {
5539 // print 'serializing '.$partType.', sv: '.$this->XMLSchemaVersion.'<br>';
5540 if (strpos($partType, ':')) {
5541 $typePrefix = $this->getPrefixFromNamespace($this->getPrefix($partType));
5542 } elseif (isset($this->typemap[$this->namespaces['xsd']][$partType])) {
5543 // print 'checking typemap: '.$this->XMLSchemaVersion.'<br>';
5544 $typePrefix = 'xsd';
5545 } else {
5546 foreach ($this->typemap as $ns => $types) {
5547 if (isset($types[$partType])) {
5548 $typePrefix = $this->getPrefixFromNamespace($ns);
5549 }
5550 }
5551 if (!isset($typePrefix)) {
5552 die("$partType has no namespace!");
5553 }
5554 }
5555 $ns = $this->getNamespaceFromPrefix($typePrefix);
5556 $localPart = $this->getLocalPart($partType);
5557 $typeDef = $this->getTypeDef($localPart, $ns);
5558 if (($typeDef['typeClass'] ?? '') == 'element') {
5559 $elementortype = 'element';
5560 if (substr($localPart, -1) == '^') {
5561 $localPart = substr($localPart, 0, -1);
5562 }
5563 } else {
5564 $elementortype = 'type';
5565 }
5566 $xml .= "\n" . ' <part name="' . $partName . '" ' . $elementortype . '="' . $typePrefix . ':' . $localPart . '" />';
5567 }
5568 }
5569 $xml .= '</message>';
5570 }
5571 }
5572 // bindings & porttypes
5573 if (count($this->bindings) >= 1) {
5574 $binding_xml = '';
5575 $portType_xml = '';
5576 foreach ($this->bindings as $bindingName => $attrs) {
5577 $binding_xml .= "\n<binding name=\"" . $bindingName . '" type="tns:' . $attrs['portType'] . '">';
5578 $binding_xml .= "\n" . ' <soap:binding style="' . $attrs['style'] . '" transport="' . $attrs['transport'] . '"/>';
5579 $portType_xml .= "\n<portType name=\"" . $attrs['portType'] . '">';
5580 foreach ($attrs['operations'] as $opName => $opParts) {
5581 $binding_xml .= "\n" . ' <operation name="' . $opName . '">';
5582 $binding_xml .= "\n" . ' <soap:operation soapAction="' . $opParts['soapAction'] . '" style="' . $opParts['style'] . '"/>';
5583 if (isset($opParts['input']['encodingStyle']) && $opParts['input']['encodingStyle'] != '') {
5584 $enc_style = ' encodingStyle="' . $opParts['input']['encodingStyle'] . '"';
5585 } else {
5586 $enc_style = '';
5587 }
5588 $binding_xml .= "\n" . ' <input><soap:body use="' . $opParts['input']['use'] . '" namespace="' . $opParts['input']['namespace'] . '"' . $enc_style . '/></input>';
5589 if (isset($opParts['output']['encodingStyle']) && $opParts['output']['encodingStyle'] != '') {
5590 $enc_style = ' encodingStyle="' . $opParts['output']['encodingStyle'] . '"';
5591 } else {
5592 $enc_style = '';
5593 }
5594 $binding_xml .= "\n" . ' <output><soap:body use="' . $opParts['output']['use'] . '" namespace="' . $opParts['output']['namespace'] . '"' . $enc_style . '/></output>';
5595 $binding_xml .= "\n" . ' </operation>';
5596 $portType_xml .= "\n" . ' <operation name="' . $opParts['name'] . '"';
5597 if (isset($opParts['parameterOrder'])) {
5598 $portType_xml .= ' parameterOrder="' . $opParts['parameterOrder'] . '"';
5599 }
5600 $portType_xml .= '>';
5601 if (isset($opParts['documentation']) && $opParts['documentation'] != '') {
5602 $portType_xml .= "\n" . ' <documentation>' . htmlspecialchars($opParts['documentation']) . '</documentation>';
5603 }
5604 $portType_xml .= "\n" . ' <input message="tns:' . $opParts['input']['message'] . '"/>';
5605 $portType_xml .= "\n" . ' <output message="tns:' . $opParts['output']['message'] . '"/>';
5606 $portType_xml .= "\n" . ' </operation>';
5607 }
5608 $portType_xml .= "\n" . '</portType>';
5609 $binding_xml .= "\n" . '</binding>';
5610 }
5611 $xml .= $portType_xml . $binding_xml;
5612 }
5613 // services
5614 $xml .= "\n<service name=\"" . $this->serviceName . '">';
5615 $has_client = isset($_GET['client_id']);
5616 if (count($this->ports) >= 1) {
5617 foreach ($this->ports as $pName => $attrs) {
5618 $xml .= "\n" . ' <port name="' . $pName . '" binding="tns:' . $attrs['binding'] . '">';
5619 $address = $attrs['location'] . ($debug || $has_client ? "?" : "")
5620 . ($debug ? 'debug=1' : '') . ($debug && $has_client ? "&amp;" : "")
5621 . ($has_client ? 'client_id=' . $_GET['client_id'] : '');
5622 $xml .= "\n" . ' <soap:address location="' . $address . '"/>';
5623 $xml .= "\n" . ' </port>';
5624 }
5625 }
5626
5627 $xml .= "\n" . '</service>';
5628 return $xml . "\n</definitions>";
5629 }
5630
5640 public function parametersMatchWrapped($type, &$parameters)
5641 {
5642 $this->debug("in parametersMatchWrapped type=$type, parameters=");
5643 $this->appendDebug($this->varDump($parameters));
5644
5645 // split type into namespace:unqualified-type
5646 if (strpos($type, ':')) {
5647 $uqType = substr($type, strrpos($type, ':') + 1);
5648 $ns = substr($type, 0, strrpos($type, ':'));
5649 $this->debug("in parametersMatchWrapped: got a prefixed type: $uqType, $ns");
5650 if ($this->getNamespaceFromPrefix($ns)) {
5651 $ns = $this->getNamespaceFromPrefix($ns);
5652 $this->debug("in parametersMatchWrapped: expanded prefixed type: $uqType, $ns");
5653 }
5654 } else {
5655 // TODO: should the type be compared to types in XSD, and the namespace
5656 // set to XSD if the type matches?
5657 $this->debug("in parametersMatchWrapped: No namespace for type $type");
5658 $ns = '';
5659 $uqType = $type;
5660 }
5661
5662 // get the type information
5663 if (!$typeDef = $this->getTypeDef($uqType, $ns)) {
5664 $this->debug("in parametersMatchWrapped: $type ($uqType) is not a supported type.");
5665 return false;
5666 }
5667 $this->debug("in parametersMatchWrapped: found typeDef=");
5668 $this->appendDebug($this->varDump($typeDef));
5669 if (substr($uqType, -1) == '^') {
5670 $uqType = substr($uqType, 0, -1);
5671 }
5672 $phpType = $typeDef['phpType'];
5673 $arrayType = (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : '');
5674 $this->debug("in parametersMatchWrapped: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: $arrayType");
5675
5676 // we expect a complexType or element of complexType
5677 if ($phpType != 'struct') {
5678 $this->debug("in parametersMatchWrapped: not a struct");
5679 return false;
5680 }
5681
5682 // see whether the parameter names match the elements
5683 if (isset($typeDef['elements']) && is_array($typeDef['elements'])) {
5684 $elements = 0;
5685 $matches = 0;
5686 $change = false;
5687 if ($this->isArraySimpleOrStruct($parameters) == 'arraySimple' && count($parameters) == count($typeDef['elements'])) {
5688 $this->debug("in parametersMatchWrapped: (wrapped return value kludge) correct number of elements in simple array, so change array and wrap");
5689 $change = true;
5690 }
5691 foreach ($typeDef['elements'] as $name => $attrs) {
5692 if ($change) {
5693 $this->debug("in parametersMatchWrapped: change parameter $element to name $name");
5694 $parameters[$name] = $parameters[$elements];
5695 unset($parameters[$elements]);
5696 $matches++;
5697 } elseif (isset($parameters[$name])) {
5698 $this->debug("in parametersMatchWrapped: have parameter named $name");
5699 $matches++;
5700 } else {
5701 $this->debug("in parametersMatchWrapped: do not have parameter named $name");
5702 }
5703 $elements++;
5704 }
5705
5706 $this->debug("in parametersMatchWrapped: $matches parameter names match $elements wrapped parameter names");
5707 if ($matches == 0) {
5708 return false;
5709 }
5710 return true;
5711 }
5712
5713 // since there are no elements for the type, if the user passed no
5714 // parameters, the parameters match wrapped.
5715 $this->debug("in parametersMatchWrapped: no elements type $ns:$uqType");
5716 return count($parameters) == 0;
5717 }
5718
5734 public function serializeRPCParameters($operation, $direction, $parameters, $bindingType = 'soap')
5735 {
5736 $this->debug("in serializeRPCParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion, bindingType=$bindingType");
5737 $this->appendDebug('parameters=' . $this->varDump($parameters));
5738
5739 if ($direction != 'input' && $direction != 'output') {
5740 $this->debug('The value of the \$direction argument needs to be either "input" or "output"');
5741 $this->setError('The value of the \$direction argument needs to be either "input" or "output"');
5742 return false;
5743 }
5744 if (!$opData = $this->getOperationData($operation, $bindingType)) {
5745 $this->debug('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType);
5746 $this->setError('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType);
5747 return false;
5748 }
5749 $this->debug('in serializeRPCParameters: opData:');
5750 $this->appendDebug($this->varDump($opData));
5751
5752 // Get encoding style for output and set to current
5753 $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
5754 if (($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {
5755 $encodingStyle = $opData['output']['encodingStyle'];
5756 $enc_style = $encodingStyle;
5757 }
5758
5759 // set input params
5760 $xml = '';
5761 if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) {
5762 $parts = &$opData[$direction]['parts'];
5763 $part_count = sizeof($parts);
5764 $style = $opData['style'];
5765 $use = $opData[$direction]['use'];
5766 $this->debug("have $part_count part(s) to serialize using $style/$use");
5767 if (is_array($parameters)) {
5768 $parametersArrayType = $this->isArraySimpleOrStruct($parameters);
5769 $parameter_count = count($parameters);
5770 $this->debug("have $parameter_count parameter(s) provided as $parametersArrayType to serialize");
5771 // check for Microsoft-style wrapped parameters
5772 if ($style == 'document' && $use == 'literal' && $part_count == 1 && isset($parts['parameters'])) {
5773 $this->debug('check whether the caller has wrapped the parameters');
5774 if ((($parametersArrayType == 'arrayStruct' || $parameter_count == 0) && !isset($parameters['parameters'])) || ($direction == 'output' && $parametersArrayType == 'arraySimple' && $parameter_count == 1)) {
5775 $this->debug('check whether caller\'s parameters match the wrapped ones');
5776 if ($this->parametersMatchWrapped($parts['parameters'], $parameters)) {
5777 $this->debug('wrap the parameters for the caller');
5778 $parameters = array('parameters' => $parameters);
5779 $parameter_count = 1;
5780 }
5781 }
5782 }
5783 foreach ($parts as $name => $type) {
5784 $this->debug("serializing part $name of type $type");
5785 // Track encoding style
5786 if (isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {
5787 $encodingStyle = $opData[$direction]['encodingStyle'];
5788 $enc_style = $encodingStyle;
5789 } else {
5790 $enc_style = false;
5791 }
5792 // NOTE: add error handling here
5793 // if serializeType returns false, then catch global error and fault
5794 if ($parametersArrayType == 'arraySimple') {
5795 $p = array_shift($parameters);
5796 $this->debug('calling serializeType w/indexed param');
5797 $xml .= $this->serializeType($name, $type, $p, $use, $enc_style);
5798 } elseif (isset($parameters[$name])) {
5799 $this->debug('calling serializeType w/named param');
5800 $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style);
5801 } else {
5802 // TODO: only send nillable
5803 $this->debug('calling serializeType w/null param');
5804 $xml .= $this->serializeType($name, $type, null, $use, $enc_style);
5805 }
5806 }
5807 } else {
5808 $this->debug('no parameters passed.');
5809 }
5810 }
5811 $this->debug("serializeRPCParameters returning: $xml");
5812 return $xml;
5813 }
5814
5829 public function serializeParameters($operation, $direction, $parameters)
5830 {
5831 $this->debug("in serializeParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion");
5832 $this->appendDebug('parameters=' . $this->varDump($parameters));
5833
5834 if ($direction != 'input' && $direction != 'output') {
5835 $this->debug('The value of the \$direction argument needs to be either "input" or "output"');
5836 $this->setError('The value of the \$direction argument needs to be either "input" or "output"');
5837 return false;
5838 }
5839 if (!$opData = $this->getOperationData($operation)) {
5840 $this->debug('Unable to retrieve WSDL data for operation: ' . $operation);
5841 $this->setError('Unable to retrieve WSDL data for operation: ' . $operation);
5842 return false;
5843 }
5844 $this->debug('opData:');
5845 $this->appendDebug($this->varDump($opData));
5846
5847 // Get encoding style for output and set to current
5848 $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
5849 if (($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {
5850 $encodingStyle = $opData['output']['encodingStyle'];
5851 $enc_style = $encodingStyle;
5852 }
5853
5854 // set input params
5855 $xml = '';
5856 if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) {
5857 $use = $opData[$direction]['use'];
5858 $this->debug("use=$use");
5859 $this->debug('got ' . count($opData[$direction]['parts']) . ' part(s)');
5860 if (is_array($parameters)) {
5861 $parametersArrayType = $this->isArraySimpleOrStruct($parameters);
5862 $this->debug('have ' . $parametersArrayType . ' parameters');
5863 foreach ($opData[$direction]['parts'] as $name => $type) {
5864 $this->debug('serializing part "' . $name . '" of type "' . $type . '"');
5865 // Track encoding style
5866 if (isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {
5867 $encodingStyle = $opData[$direction]['encodingStyle'];
5868 $enc_style = $encodingStyle;
5869 } else {
5870 $enc_style = false;
5871 }
5872 // NOTE: add error handling here
5873 // if serializeType returns false, then catch global error and fault
5874 if ($parametersArrayType == 'arraySimple') {
5875 $p = array_shift($parameters);
5876 $this->debug('calling serializeType w/indexed param');
5877 $xml .= $this->serializeType($name, $type, $p, $use, $enc_style);
5878 } elseif (isset($parameters[$name])) {
5879 $this->debug('calling serializeType w/named param');
5880 $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style);
5881 } else {
5882 // TODO: only send nillable
5883 $this->debug('calling serializeType w/null param');
5884 $xml .= $this->serializeType($name, $type, null, $use, $enc_style);
5885 }
5886 }
5887 } else {
5888 $this->debug('no parameters passed.');
5889 }
5890 }
5891 $this->debug("serializeParameters returning: $xml");
5892 return $xml;
5893 }
5894
5907 public function serializeType($name, $type, $value, $use='encoded', $encodingStyle=false, $unqualified=false)
5908 {
5909 $this->debug("in serializeType: name=$name, type=$type, use=$use, encodingStyle=$encodingStyle, unqualified=" . ($unqualified ? "unqualified" : "qualified"));
5910 $this->appendDebug("value=" . $this->varDump($value));
5911 if ($use == 'encoded' && $encodingStyle) {
5912 $encodingStyle = ' SOAP-ENV:encodingStyle="' . $encodingStyle . '"';
5913 }
5914
5915 // if a soapval has been supplied, let its type override the WSDL
5916 if (is_object($value) && get_class($value) == 'soapval') {
5917 if ($value->type_ns) {
5918 $type = $value->type_ns . ':' . $value->type;
5919 $forceType = true;
5920 $this->debug("in serializeType: soapval overrides type to $type");
5921 } elseif ($value->type) {
5922 $type = $value->type;
5923 $forceType = true;
5924 $this->debug("in serializeType: soapval overrides type to $type");
5925 } else {
5926 $forceType = false;
5927 $this->debug("in serializeType: soapval does not override type");
5928 }
5929 $attrs = $value->attributes;
5930 $value = $value->value;
5931 $this->debug("in serializeType: soapval overrides value to $value");
5932 if ($attrs) {
5933 if (!is_array($value)) {
5934 $value['!'] = $value;
5935 }
5936 foreach ($attrs as $n => $v) {
5937 $value['!' . $n] = $v;
5938 }
5939 $this->debug("in serializeType: soapval provides attributes");
5940 }
5941 } else {
5942 $forceType = false;
5943 }
5944
5945 $xml = '';
5946 if (strpos($type, ':')) {
5947 $uqType = substr($type, strrpos($type, ':') + 1);
5948 $ns = substr($type, 0, strrpos($type, ':'));
5949 $this->debug("in serializeType: got a prefixed type: $uqType, $ns");
5950 if ($this->getNamespaceFromPrefix($ns)) {
5951 $ns = $this->getNamespaceFromPrefix($ns);
5952 $this->debug("in serializeType: expanded prefixed type: $uqType, $ns");
5953 }
5954
5955 if ($ns == $this->XMLSchemaVersion || $ns == 'http://schemas.xmlsoap.org/soap/encoding/') {
5956 $this->debug('in serializeType: type namespace indicates XML Schema or SOAP Encoding type');
5957 if ($unqualified && $use == 'literal') {
5958 $elementNS = " xmlns=\"\"";
5959 } else {
5960 $elementNS = '';
5961 }
5962 if (is_null($value)) {
5963 if ($use == 'literal') {
5964 // TODO: depends on minOccurs
5965 $xml = "<$name$elementNS/>";
5966 } else {
5967 // TODO: depends on nillable, which should be checked before calling this method
5968 $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>";
5969 }
5970 $this->debug("in serializeType: returning: $xml");
5971 return $xml;
5972 }
5973 if ($uqType == 'Array') {
5974 // JBoss/Axis does this sometimes
5975 return $this->serialize_val($value, $name, false, false, false, false, $use);
5976 }
5977 if ($uqType == 'boolean') {
5978 if ((is_string($value) && $value == 'false') || (! $value)) {
5979 $value = 'false';
5980 } else {
5981 $value = 'true';
5982 }
5983 }
5984 if ($uqType == 'string' && gettype($value) == 'string') {
5985 $value = $this->expandEntities($value);
5986 }
5987 if (($uqType == 'long' || $uqType == 'unsignedLong') && gettype($value) == 'double') {
5988 $value = sprintf("%.0lf", $value);
5989 }
5990 // it's a scalar
5991 // TODO: what about null/nil values?
5992 // check type isn't a custom type extending xmlschema namespace
5993 if (!$this->getTypeDef($uqType, $ns)) {
5994 if ($use == 'literal') {
5995 if ($forceType) {
5996 $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>";
5997 } else {
5998 $xml = "<$name$elementNS>$value</$name>";
5999 }
6000 } else {
6001 $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>";
6002 }
6003 $this->debug("in serializeType: returning: $xml");
6004 return $xml;
6005 }
6006 $this->debug('custom type extends XML Schema or SOAP Encoding namespace (yuck)');
6007 } elseif ($ns == 'http://xml.apache.org/xml-soap') {
6008 $this->debug('in serializeType: appears to be Apache SOAP type');
6009 if ($uqType == 'Map') {
6010 $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap');
6011 if (! $tt_prefix) {
6012 $this->debug('in serializeType: Add namespace for Apache SOAP type');
6013 $tt_prefix = 'ns' . rand(1000, 9999);
6014 $this->namespaces[$tt_prefix] = 'http://xml.apache.org/xml-soap';
6015 // force this to be added to usedNamespaces
6016 $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap');
6017 }
6018 $contents = '';
6019 foreach ($value as $k => $v) {
6020 $this->debug("serializing map element: key $k, value $v");
6021 $contents .= '<item>';
6022 $contents .= $this->serialize_val($k, 'key', false, false, false, false, $use);
6023 $contents .= $this->serialize_val($v, 'value', false, false, false, false, $use);
6024 $contents .= '</item>';
6025 }
6026 if ($use == 'literal') {
6027 if ($forceType) {
6028 $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\">$contents</$name>";
6029 } else {
6030 $xml = "<$name>$contents</$name>";
6031 }
6032 } else {
6033 $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\"$encodingStyle>$contents</$name>";
6034 }
6035 $this->debug("in serializeType: returning: $xml");
6036 return $xml;
6037 }
6038 $this->debug('in serializeType: Apache SOAP type, but only support Map');
6039 }
6040 } else {
6041 // TODO: should the type be compared to types in XSD, and the namespace
6042 // set to XSD if the type matches?
6043 $this->debug("in serializeType: No namespace for type $type");
6044 $ns = '';
6045 $uqType = $type;
6046 }
6047 if (!$typeDef = $this->getTypeDef($uqType, $ns)) {
6048 $this->setError("$type ($uqType) is not a supported type.");
6049 $this->debug("in serializeType: $type ($uqType) is not a supported type.");
6050 return false;
6051 } else {
6052 $this->debug("in serializeType: found typeDef");
6053 $this->appendDebug('typeDef=' . $this->varDump($typeDef));
6054 if (substr($uqType, -1) == '^') {
6055 $uqType = substr($uqType, 0, -1);
6056 }
6057 }
6058 $phpType = $typeDef['phpType'];
6059 $this->debug("in serializeType: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: " . (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : ''));
6060 // if php type == struct, map value to the <all> element names
6061 if ($phpType == 'struct') {
6062 if (isset($typeDef['typeClass']) && $typeDef['typeClass'] == 'element') {
6063 $elementName = $uqType;
6064 if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
6065 $elementNS = " xmlns=\"$ns\"";
6066 } else {
6067 $elementNS = " xmlns=\"\"";
6068 }
6069 } else {
6070 $elementName = $name;
6071 if ($unqualified) {
6072 $elementNS = " xmlns=\"\"";
6073 } else {
6074 $elementNS = '';
6075 }
6076 }
6077 if (is_null($value)) {
6078 if ($use == 'literal') {
6079 // TODO: depends on minOccurs
6080 $xml = "<$elementName$elementNS/>";
6081 } else {
6082 $xml = "<$elementName$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>";
6083 }
6084 $this->debug("in serializeType: returning: $xml");
6085 return $xml;
6086 }
6087 if (is_object($value)) {
6088 $value = get_object_vars($value);
6089 }
6090 if (is_array($value)) {
6091 $elementAttrs = $this->serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType);
6092 if ($use == 'literal') {
6093 if ($forceType) {
6094 $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">";
6095 } else {
6096 $xml = "<$elementName$elementNS$elementAttrs>";
6097 }
6098 } else {
6099 $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>";
6100 }
6101
6102 $xml .= $this->serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use, $encodingStyle);
6103 $xml .= "</$elementName>";
6104 } else {
6105 $this->debug("in serializeType: phpType is struct, but value is not an array");
6106 $this->setError("phpType is struct, but value is not an array: see debug output for details");
6107 $xml = '';
6108 }
6109 } elseif ($phpType == 'array') {
6110 if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
6111 $elementNS = " xmlns=\"$ns\"";
6112 } else {
6113 if ($unqualified) {
6114 $elementNS = " xmlns=\"\"";
6115 } else {
6116 $elementNS = '';
6117 }
6118 }
6119 if (is_null($value)) {
6120 if ($use == 'literal') {
6121 // TODO: depends on minOccurs
6122 $xml = "<$name$elementNS/>";
6123 } else {
6124 $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" .
6125 $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') .
6126 ":Array\" " .
6127 $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') .
6128 ':arrayType="' .
6129 $this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType'])) .
6130 ':' .
6131 $this->getLocalPart($typeDef['arrayType']) . "[0]\"/>";
6132 }
6133 $this->debug("in serializeType: returning: $xml");
6134 return $xml;
6135 }
6136 if (isset($typeDef['multidimensional'])) {
6137 $nv = array();
6138 foreach ($value as $v) {
6139 $cols = ',' . sizeof($v);
6140 $nv = array_merge($nv, $v);
6141 }
6142 $value = $nv;
6143 } else {
6144 $cols = '';
6145 }
6146 if (is_array($value) && sizeof($value) >= 1) {
6147 $rows = sizeof($value);
6148 $contents = '';
6149 foreach ($value as $k => $v) {
6150 $this->debug("serializing array element: $k, $v of type: $typeDef[arrayType]");
6151 //if (strpos($typeDef['arrayType'], ':') ) {
6152 if (!in_array($typeDef['arrayType'], $this->typemap['http://www.w3.org/2001/XMLSchema'])) {
6153 $contents .= $this->serializeType('item', $typeDef['arrayType'], $v, $use);
6154 } else {
6155 $contents .= $this->serialize_val($v, 'item', $typeDef['arrayType'], null, $this->XMLSchemaVersion, false, $use);
6156 }
6157 }
6158 } else {
6159 $rows = 0;
6160 $contents = null;
6161 }
6162 // TODO: for now, an empty value will be serialized as a zero element
6163 // array. Revisit this when coding the handling of null/nil values.
6164 if ($use == 'literal') {
6165 $xml = "<$name$elementNS>"
6166 . $contents
6167 . "</$name>";
6168 } else {
6169 $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') . ':Array" ' .
6170 $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/')
6171 . ':arrayType="'
6172 . $this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType']))
6173 . ":" . $this->getLocalPart($typeDef['arrayType']) . "[$rows$cols]\">"
6174 . $contents
6175 . "</$name>";
6176 }
6177 } elseif ($phpType == 'scalar') {
6178 if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
6179 $elementNS = " xmlns=\"$ns\"";
6180 } else {
6181 if ($unqualified) {
6182 $elementNS = " xmlns=\"\"";
6183 } else {
6184 $elementNS = '';
6185 }
6186 }
6187 if ($use == 'literal') {
6188 if ($forceType) {
6189 $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>";
6190 } else {
6191 $xml = "<$name$elementNS>$value</$name>";
6192 }
6193 } else {
6194 $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>";
6195 }
6196 }
6197 $this->debug("in serializeType: returning: $xml");
6198 return $xml;
6199 }
6200
6211 public function serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType)
6212 {
6213 $xml = '';
6214 if (isset($typeDef['attrs']) && is_array($typeDef['attrs'])) {
6215 $this->debug("serialize attributes for XML Schema type $ns:$uqType");
6216 if (is_array($value)) {
6217 $xvalue = $value;
6218 } elseif (is_object($value)) {
6219 $xvalue = get_object_vars($value);
6220 } else {
6221 $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType");
6222 $xvalue = array();
6223 }
6224 foreach ($typeDef['attrs'] as $aName => $attrs) {
6225 if (isset($xvalue['!' . $aName])) {
6226 $xname = '!' . $aName;
6227 $this->debug("value provided for attribute $aName with key $xname");
6228 } elseif (isset($xvalue[$aName])) {
6229 $xname = $aName;
6230 $this->debug("value provided for attribute $aName with key $xname");
6231 } elseif (isset($attrs['default'])) {
6232 $xname = '!' . $aName;
6233 $xvalue[$xname] = $attrs['default'];
6234 $this->debug('use default value of ' . $xvalue[$aName] . ' for attribute ' . $aName);
6235 } else {
6236 $xname = '';
6237 $this->debug("no value provided for attribute $aName");
6238 }
6239 if ($xname) {
6240 $xml .= " $aName=\"" . $this->expandEntities($xvalue[$xname]) . "\"";
6241 }
6242 }
6243 } else {
6244 $this->debug("no attributes to serialize for XML Schema type $ns:$uqType");
6245 }
6246 if (isset($typeDef['extensionBase'])) {
6247 $ns = $this->getPrefix($typeDef['extensionBase']);
6248 $uqType = $this->getLocalPart($typeDef['extensionBase']);
6249 if ($this->getNamespaceFromPrefix($ns)) {
6250 $ns = $this->getNamespaceFromPrefix($ns);
6251 }
6252 if ($typeDef = $this->getTypeDef($uqType, $ns)) {
6253 $this->debug("serialize attributes for extension base $ns:$uqType");
6254 $xml .= $this->serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType);
6255 } else {
6256 $this->debug("extension base $ns:$uqType is not a supported type");
6257 }
6258 }
6259 return $xml;
6260 }
6261
6274 public function serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use='encoded', $encodingStyle=false)
6275 {
6276 $xml = '';
6277 if (isset($typeDef['elements']) && is_array($typeDef['elements'])) {
6278 $this->debug("in serializeComplexTypeElements, serialize elements for XML Schema type $ns:$uqType");
6279 if (is_array($value)) {
6280 $xvalue = $value;
6281 } elseif (is_object($value)) {
6282 $xvalue = get_object_vars($value);
6283 } else {
6284 $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType");
6285 $xvalue = array();
6286 }
6287 // toggle whether all elements are present - ideally should validate against schema
6288 if (count($typeDef['elements']) != count($xvalue)) {
6289 $optionals = true;
6290 }
6291 foreach ($typeDef['elements'] as $eName => $attrs) {
6292 if (!isset($xvalue[$eName])) {
6293 if (isset($attrs['default'])) {
6294 $xvalue[$eName] = $attrs['default'];
6295 $this->debug('use default value of ' . $xvalue[$eName] . ' for element ' . $eName);
6296 }
6297 }
6298 // if user took advantage of a minOccurs=0, then only serialize named parameters
6299 if (isset($optionals)
6300 && (!isset($xvalue[$eName]))
6301 && ((!isset($attrs['nillable'])) || $attrs['nillable'] != 'true')
6302 ) {
6303 if (isset($attrs['minOccurs']) && $attrs['minOccurs'] <> '0') {
6304 $this->debug("apparent error: no value provided for element $eName with minOccurs=" . $attrs['minOccurs']);
6305 }
6306 // do nothing
6307 $this->debug("no value provided for complexType element $eName and element is not nillable, so serialize nothing");
6308 } else {
6309 // get value
6310 if (isset($xvalue[$eName])) {
6311 $v = $xvalue[$eName];
6312 } else {
6313 $v = null;
6314 }
6315 if (isset($attrs['form'])) {
6316 $unqualified = ($attrs['form'] == 'unqualified');
6317 } else {
6318 $unqualified = false;
6319 }
6320 if (isset($attrs['maxOccurs']) && ($attrs['maxOccurs'] == 'unbounded' || $attrs['maxOccurs'] > 1) && isset($v) && is_array($v) && $this->isArraySimpleOrStruct($v) == 'arraySimple') {
6321 $vv = $v;
6322 foreach ($vv as $k => $v) {
6323 if (isset($attrs['type']) || isset($attrs['ref'])) {
6324 // serialize schema-defined type
6325 $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
6326 } else {
6327 // serialize generic type (can this ever really happen?)
6328 $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use");
6329 $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use);
6330 }
6331 }
6332 } else {
6333 if (isset($attrs['type']) || isset($attrs['ref'])) {
6334 // serialize schema-defined type
6335 $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
6336 } else {
6337 // serialize generic type (can this ever really happen?)
6338 $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use");
6339 $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use);
6340 }
6341 }
6342 }
6343 }
6344 } else {
6345 $this->debug("no elements to serialize for XML Schema type $ns:$uqType");
6346 }
6347 if (isset($typeDef['extensionBase'])) {
6348 $ns = $this->getPrefix($typeDef['extensionBase']);
6349 $uqType = $this->getLocalPart($typeDef['extensionBase']);
6350 if ($this->getNamespaceFromPrefix($ns)) {
6351 $ns = $this->getNamespaceFromPrefix($ns);
6352 }
6353 if ($typeDef = $this->getTypeDef($uqType, $ns)) {
6354 $this->debug("serialize elements for extension base $ns:$uqType");
6355 $xml .= $this->serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use, $encodingStyle);
6356 } else {
6357 $this->debug("extension base $ns:$uqType is not a supported type");
6358 }
6359 }
6360 return $xml;
6361 }
6362
6377 public function addComplexType($name, $typeClass='complexType', $phpType='array', $compositor='', $restrictionBase='', $elements=array(), $attrs=array(), $arrayType='')
6378 {
6379 if (count($elements) > 0) {
6380 $eElements = array();
6381 foreach ($elements as $n => $e) {
6382 // expand each element
6383 $ee = array();
6384 foreach ($e as $k => $v) {
6385 $k = strpos($k, ':') ? $this->expandQname($k) : $k;
6386 $v = strpos($v, ':') ? $this->expandQname($v) : $v;
6387 $ee[$k] = $v;
6388 }
6389 $eElements[$n] = $ee;
6390 }
6391 $elements = $eElements;
6392 }
6393
6394 if (count($attrs) > 0) {
6395 foreach ($attrs as $n => $a) {
6396 // expand each attribute
6397 foreach ($a as $k => $v) {
6398 $k = strpos($k, ':') ? $this->expandQname($k) : $k;
6399 $v = strpos($v, ':') ? $this->expandQname($v) : $v;
6400 $aa[$k] = $v;
6401 }
6402 $eAttrs[$n] = $aa;
6403 }
6404 $attrs = $eAttrs;
6405 }
6406
6407 $restrictionBase = strpos($restrictionBase, ':') ? $this->expandQname($restrictionBase) : $restrictionBase;
6408 $arrayType = strpos($arrayType, ':') ? $this->expandQname($arrayType) : $arrayType;
6409
6410 $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
6411 $this->schemas[$typens][0]->addComplexType($name, $typeClass, $phpType, $compositor, $restrictionBase, $elements, $attrs, $arrayType);
6412 }
6413
6425 public function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array())
6426 {
6427 $restrictionBase = strpos($restrictionBase, ':') ? $this->expandQname($restrictionBase) : $restrictionBase;
6428
6429 $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
6430 $this->schemas[$typens][0]->addSimpleType($name, $restrictionBase, $typeClass, $phpType, $enumeration);
6431 }
6432
6440 public function addElement($attrs)
6441 {
6442 $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
6443 $this->schemas[$typens][0]->addElement($attrs);
6444 }
6445
6460 public function addOperation($name, $in = false, $out = false, $namespace = false, $soapaction = false, $style = 'rpc', $use = 'encoded', $documentation = '', $encodingStyle = '')
6461 {
6462 if ($use == 'encoded' && $encodingStyle == '') {
6463 $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
6464 }
6465
6466 if ($style == 'document') {
6467 $elements = array();
6468 foreach ($in as $n => $t) {
6469 $elements[$n] = array('name' => $n, 'type' => $t);
6470 }
6471 $this->addComplexType($name . 'RequestType', 'complexType', 'struct', 'all', '', $elements);
6472 $this->addElement(array('name' => $name, 'type' => $name . 'RequestType'));
6473 $in = array('parameters' => 'tns:' . $name . '^');
6474
6475 $elements = array();
6476 foreach ($out as $n => $t) {
6477 $elements[$n] = array('name' => $n, 'type' => $t);
6478 }
6479 $this->addComplexType($name . 'ResponseType', 'complexType', 'struct', 'all', '', $elements);
6480 $this->addElement(array('name' => $name . 'Response', 'type' => $name . 'ResponseType', 'form' => 'qualified'));
6481 $out = array('parameters' => 'tns:' . $name . 'Response' . '^');
6482 }
6483
6484 // get binding
6485 $this->bindings[ $this->serviceName . 'Binding' ]['operations'][$name] =
6486 array(
6487 'name' => $name,
6488 'binding' => $this->serviceName . 'Binding',
6489 'endpoint' => $this->endpoint,
6490 'soapAction' => $soapaction,
6491 'style' => $style,
6492 'input' => array(
6493 'use' => $use,
6494 'namespace' => $namespace,
6495 'encodingStyle' => $encodingStyle,
6496 'message' => $name . 'Request',
6497 'parts' => $in),
6498 'output' => array(
6499 'use' => $use,
6500 'namespace' => $namespace,
6501 'encodingStyle' => $encodingStyle,
6502 'message' => $name . 'Response',
6503 'parts' => $out),
6504 'namespace' => $namespace,
6505 'transport' => 'http://schemas.xmlsoap.org/soap/http',
6506 'documentation' => $documentation);
6507 // add portTypes
6508 // add messages
6509 if ($in) {
6510 foreach ($in as $pName => $pType) {
6511 if (strpos($pType, ':')) {
6512 $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)) . ":" . $this->getLocalPart($pType);
6513 }
6514 $this->messages[$name . 'Request'][$pName] = $pType;
6515 }
6516 } else {
6517 $this->messages[$name . 'Request']= '0';
6518 }
6519 if ($out) {
6520 foreach ($out as $pName => $pType) {
6521 if (strpos($pType, ':')) {
6522 $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)) . ":" . $this->getLocalPart($pType);
6523 }
6524 $this->messages[$name . 'Response'][$pName] = $pType;
6525 }
6526 } else {
6527 $this->messages[$name . 'Response']= '0';
6528 }
6529 return true;
6530 }
6531}
6532?><?php
6533
6534
6535
6545class nusoap_parser extends nusoap_base
6546{
6547 public $xml = '';
6548 public $xml_encoding = '';
6549 public $method = '';
6550 public $root_struct = '';
6551 public $root_struct_name = '';
6552 public $root_struct_namespace = '';
6553 public $root_header = '';
6554 public $document = ''; // incoming SOAP body (text)
6555 // determines where in the message we are (envelope,header,body,method)
6556 public $status = '';
6557 public $position = 0;
6558 public $depth = 0;
6559 public $default_namespace = '';
6560 public $namespaces = array();
6561 public $message = array();
6562 public $parent = '';
6563 public $fault = false;
6564 public $fault_code = '';
6565 public $fault_str = '';
6566 public $fault_detail = '';
6567 public $depth_array = array();
6568 public $debug_flag = true;
6569 public $soapresponse = null; // parsed SOAP Body
6570 public $soapheader = null; // parsed SOAP Header
6571 public $responseHeaders = ''; // incoming SOAP headers (text)
6572 public $body_position = 0;
6573 // for multiref parsing:
6574 // array of id => pos
6575 public $ids = array();
6576 // array of id => hrefs => pos
6577 public $multirefs = array();
6578 // toggle for auto-decoding element content
6579 public $decode_utf8 = true;
6580
6590 public function __construct($xml, $encoding='UTF-8', $method='', $decode_utf8=true)
6591 {
6593 $this->xml = $xml;
6594 $this->xml_encoding = $encoding;
6595 $this->method = $method;
6596 $this->decode_utf8 = $decode_utf8;
6597
6598 // Check whether content has been read.
6599 if (!empty($xml)) {
6600 // Check XML encoding
6601 $pos_xml = strpos($xml, '<?xml');
6602 if ($pos_xml !== false) {
6603 $xml_decl = substr($xml, $pos_xml, strpos($xml, '?>', $pos_xml + 2) - $pos_xml + 1);
6604 if (preg_match("/encoding=[\"']([^\"']*)[\"']/", $xml_decl, $res)) {
6605 $xml_encoding = $res[1];
6606 if (strtoupper($xml_encoding) != $encoding) {
6607 $err = "Charset from HTTP Content-Type '" . $encoding . "' does not match encoding from XML declaration '" . $xml_encoding . "'";
6608 $this->debug($err);
6609 if ($encoding != 'ISO-8859-1' || strtoupper($xml_encoding) != 'UTF-8') {
6610 $this->setError($err);
6611 return;
6612 }
6613 // when HTTP says ISO-8859-1 (the default) and XML says UTF-8 (the typical), assume the other endpoint is just sloppy and proceed
6614 } else {
6615 $this->debug('Charset from HTTP Content-Type matches encoding from XML declaration');
6616 }
6617 } else {
6618 $this->debug('No encoding specified in XML declaration');
6619 }
6620 } else {
6621 $this->debug('No XML declaration');
6622 }
6623 $this->debug('Entering nusoap_parser(), length=' . strlen($xml) . ', encoding=' . $encoding);
6624 // Create an XML parser - why not xml_parser_create_ns?
6625 $this->parser = xml_parser_create($this->xml_encoding);
6626 // Set the options for parsing the XML data.
6627 //xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
6628 xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
6629 xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, $this->xml_encoding);
6630 // Set the object for the parser.
6631 xml_set_object($this->parser, $this);
6632 // Set the element handlers for the parser.
6633 xml_set_element_handler($this->parser, 'start_element', 'end_element');
6634 xml_set_character_data_handler($this->parser, 'character_data');
6635
6636 // Parse the XML file.
6637 if (!xml_parse($this->parser, $xml, true)) {
6638 // Display an error message.
6639 $err = sprintf(
6640 'XML error parsing SOAP payload on line %d: %s',
6641 xml_get_current_line_number($this->parser),
6642 xml_error_string(xml_get_error_code($this->parser))
6643 );
6644 $this->debug($err);
6645 $this->debug("XML payload:\n" . $xml);
6646 $this->setError($err);
6647 } else {
6648 $this->debug('parsed successfully, found root struct: ' . $this->root_struct . ' of name ' . $this->root_struct_name);
6649 // get final value
6650 $this->soapresponse = $this->message[$this->root_struct]['result'];
6651 // get header value
6652 if ($this->root_header != '' && isset($this->message[$this->root_header]['result'])) {
6653 $this->soapheader = $this->message[$this->root_header]['result'];
6654 }
6655 // resolve hrefs/ids
6656 if (sizeof($this->multirefs) > 0) {
6657 foreach ($this->multirefs as $id => $hrefs) {
6658 $this->debug('resolving multirefs for id: ' . $id);
6659 $idVal = $this->buildVal($this->ids[$id]);
6660 if (is_array($idVal) && isset($idVal['!id'])) {
6661 unset($idVal['!id']);
6662 }
6663 foreach ($hrefs as $refPos => $ref) {
6664 $this->debug('resolving href at pos ' . $refPos);
6665 $this->multirefs[$id][$refPos] = $idVal;
6666 }
6667 }
6668 }
6669 }
6670 xml_parser_free($this->parser);
6671 } else {
6672 $this->debug('xml was empty, didn\'t parse!');
6673 $this->setError('xml was empty, didn\'t parse!');
6674 }
6675 }
6676
6685 public function start_element($parser, $name, $attrs)
6686 {
6687 // position in a total number of elements, starting from 0
6688 // update class level pos
6689 $pos = $this->position++;
6690 // and set mine
6691 $this->message[$pos] = array('pos' => $pos,'children'=>'','cdata'=>'');
6692 // depth = how many levels removed from root?
6693 // set mine as current global depth and increment global depth value
6694 $this->message[$pos]['depth'] = $this->depth++;
6695
6696 // else add self as child to whoever the current parent is
6697 if ($pos != 0) {
6698 $this->message[$this->parent]['children'] .= '|' . $pos;
6699 }
6700 // set my parent
6701 $this->message[$pos]['parent'] = $this->parent;
6702 // set self as current parent
6703 $this->parent = $pos;
6704 // set self as current value for this depth
6705 $this->depth_array[$this->depth] = $pos;
6706 // get element prefix
6707 if (strpos($name, ':')) {
6708 // get ns prefix
6709 $prefix = substr($name, 0, strpos($name, ':'));
6710 // get unqualified name
6711 $name = substr(strstr($name, ':'), 1);
6712 }
6713 // set status
6714 if ($name == 'Envelope') {
6715 $this->status = 'envelope';
6716 } elseif ($name == 'Header' && $this->status = 'envelope') {
6717 $this->root_header = $pos;
6718 $this->status = 'header';
6719 } elseif ($name == 'Body' && $this->status = 'envelope') {
6720 $this->status = 'body';
6721 $this->body_position = $pos;
6722 // set method
6723 } elseif ($this->status == 'body' && $pos == ($this->body_position+1)) {
6724 $this->status = 'method';
6725 $this->root_struct_name = $name;
6726 $this->root_struct = $pos;
6727 $this->message[$pos]['type'] = 'struct';
6728 $this->debug("found root struct $this->root_struct_name, pos $this->root_struct");
6729 }
6730 // set my status
6731 $this->message[$pos]['status'] = $this->status;
6732 // set name
6733 $this->message[$pos]['name'] = htmlspecialchars($name);
6734 // set attrs
6735 $this->message[$pos]['attrs'] = $attrs;
6736
6737 // loop through atts, logging ns and type declarations
6738 $attstr = '';
6739 foreach ($attrs as $key => $value) {
6740 $key_prefix = $this->getPrefix($key);
6741 $key_localpart = $this->getLocalPart($key);
6742 // if ns declarations, add to class level array of valid namespaces
6743 if ($key_prefix == 'xmlns') {
6744 if (preg_match('/^http:\/\/www.w3.org\/[0-9]{4}\/XMLSchema$/', $value)) {
6745 $this->XMLSchemaVersion = $value;
6746 $this->namespaces['xsd'] = $this->XMLSchemaVersion;
6747 $this->namespaces['xsi'] = $this->XMLSchemaVersion . '-instance';
6748 }
6749 $this->namespaces[$key_localpart] = $value;
6750 // set method namespace
6751 if ($name == $this->root_struct_name) {
6752 $this->methodNamespace = $value;
6753 }
6754 // if it's a type declaration, set type
6755 } elseif ($key_localpart == 'type') {
6756 if (isset($this->message[$pos]['type']) && $this->message[$pos]['type'] == 'array') {
6757 // do nothing: already processed arrayType
6758 } else {
6759 $value_prefix = $this->getPrefix($value);
6760 $value_localpart = $this->getLocalPart($value);
6761 $this->message[$pos]['type'] = $value_localpart;
6762 $this->message[$pos]['typePrefix'] = $value_prefix;
6763 if (isset($this->namespaces[$value_prefix])) {
6764 $this->message[$pos]['type_namespace'] = $this->namespaces[$value_prefix];
6765 } elseif (isset($attrs['xmlns:' . $value_prefix])) {
6766 $this->message[$pos]['type_namespace'] = $attrs['xmlns:' . $value_prefix];
6767 }
6768 // should do something here with the namespace of specified type?
6769 }
6770 } elseif ($key_localpart == 'arrayType') {
6771 $this->message[$pos]['type'] = 'array';
6772 /* do arrayType ereg here
6773 [1] arrayTypeValue ::= atype asize
6774 [2] atype ::= QName rank*
6775 [3] rank ::= '[' (',')* ']'
6776 [4] asize ::= '[' length~ ']'
6777 [5] length ::= nextDimension* Digit+
6778 [6] nextDimension ::= Digit+ ','
6779 */
6780 $expr = '/([A-Za-z0-9_]+):([A-Za-z]+[A-Za-z0-9_]+)\[([0-9]+),?([0-9]*)\]/';
6781 if (preg_match($expr, $value, $regs)) {
6782 $this->message[$pos]['typePrefix'] = $regs[1];
6783 $this->message[$pos]['arrayTypePrefix'] = $regs[1];
6784 if (isset($this->namespaces[$regs[1]])) {
6785 $this->message[$pos]['arrayTypeNamespace'] = $this->namespaces[$regs[1]];
6786 } elseif (isset($attrs['xmlns:' . $regs[1]])) {
6787 $this->message[$pos]['arrayTypeNamespace'] = $attrs['xmlns:' . $regs[1]];
6788 }
6789 $this->message[$pos]['arrayType'] = $regs[2];
6790 $this->message[$pos]['arraySize'] = $regs[3];
6791 $this->message[$pos]['arrayCols'] = $regs[4];
6792 }
6793 // specifies nil value (or not)
6794 } elseif ($key_localpart == 'nil') {
6795 $this->message[$pos]['nil'] = ($value == 'true' || $value == '1');
6796 // some other attribute
6797 } elseif ($key != 'href' && $key != 'xmlns' && $key_localpart != 'encodingStyle' && $key_localpart != 'root') {
6798 $this->message[$pos]['xattrs']['!' . $key] = $value;
6799 }
6800
6801 if ($key == 'xmlns') {
6802 $this->default_namespace = $value;
6803 }
6804 // log id
6805 if ($key == 'id') {
6806 $this->ids[$value] = $pos;
6807 }
6808 // root
6809 if ($key_localpart == 'root' && $value == 1) {
6810 $this->status = 'method';
6811 $this->root_struct_name = $name;
6812 $this->root_struct = $pos;
6813 $this->debug("found root struct $this->root_struct_name, pos $pos");
6814 }
6815 // for doclit
6816 $attstr .= " $key=\"$value\"";
6817 }
6818 // get namespace - must be done after namespace atts are processed
6819 if (isset($prefix)) {
6820 $this->message[$pos]['namespace'] = $this->namespaces[$prefix];
6821 $this->default_namespace = $this->namespaces[$prefix];
6822 } else {
6823 $this->message[$pos]['namespace'] = $this->default_namespace;
6824 }
6825 if ($this->status == 'header') {
6826 if ($this->root_header != $pos) {
6827 $this->responseHeaders .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>";
6828 }
6829 } elseif ($this->root_struct_name != '') {
6830 $this->document .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>";
6831 }
6832 }
6833
6841 public function end_element($parser, $name)
6842 {
6843 // position of current element is equal to the last value left in depth_array for my depth
6844 $pos = $this->depth_array[$this->depth--];
6845
6846 // get element prefix
6847 if (strpos($name, ':')) {
6848 // get ns prefix
6849 $prefix = substr($name, 0, strpos($name, ':'));
6850 // get unqualified name
6851 $name = substr(strstr($name, ':'), 1);
6852 }
6853
6854 // build to native type
6855 if (isset($this->body_position) && $pos > $this->body_position) {
6856 // deal w/ multirefs
6857 if (isset($this->message[$pos]['attrs']['href'])) {
6858 // get id
6859 $id = substr($this->message[$pos]['attrs']['href'], 1);
6860 // add placeholder to href array
6861 $this->multirefs[$id][$pos] = 'placeholder';
6862 // add set a reference to it as the result value
6863 $this->message[$pos]['result'] =& $this->multirefs[$id][$pos];
6864 // build complexType values
6865 } elseif ($this->message[$pos]['children'] != '') {
6866 // if result has already been generated (struct/array)
6867 if (!isset($this->message[$pos]['result'])) {
6868 $this->message[$pos]['result'] = $this->buildVal($pos);
6869 }
6870 // build complexType values of attributes and possibly simpleContent
6871 } elseif (isset($this->message[$pos]['xattrs'])) {
6872 if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) {
6873 $this->message[$pos]['xattrs']['!'] = null;
6874 } elseif (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') {
6875 if (isset($this->message[$pos]['type'])) {
6876 $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'] : '');
6877 } else {
6878 $parent = $this->message[$pos]['parent'];
6879 if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
6880 $this->message[$pos]['xattrs']['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
6881 } else {
6882 $this->message[$pos]['xattrs']['!'] = $this->message[$pos]['cdata'];
6883 }
6884 }
6885 }
6886 $this->message[$pos]['result'] = $this->message[$pos]['xattrs'];
6887 // set value of simpleType (or nil complexType)
6888 } else {
6889 //$this->debug('adding data for scalar value '.$this->message[$pos]['name'].' of value '.$this->message[$pos]['cdata']);
6890 if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) {
6891 $this->message[$pos]['xattrs']['!'] = null;
6892 } elseif (isset($this->message[$pos]['type'])) {
6893 $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'] : '');
6894 } else {
6895 $parent = $this->message[$pos]['parent'];
6896 if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
6897 $this->message[$pos]['result'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
6898 } else {
6899 $this->message[$pos]['result'] = $this->message[$pos]['cdata'];
6900 }
6901 }
6902
6903 /* add value to parent's result, if parent is struct/array
6904 $parent = $this->message[$pos]['parent'];
6905 if($this->message[$parent]['type'] != 'map'){
6906 if(strtolower($this->message[$parent]['type']) == 'array'){
6907 $this->message[$parent]['result'][] = $this->message[$pos]['result'];
6908 } else {
6909 $this->message[$parent]['result'][$this->message[$pos]['name']] = $this->message[$pos]['result'];
6910 }
6911 }
6912 */
6913 }
6914 }
6915
6916 // for doclit
6917 if ($this->status == 'header') {
6918 if ($this->root_header != $pos) {
6919 $this->responseHeaders .= "</" . (isset($prefix) ? $prefix . ':' : '') . "$name>";
6920 }
6921 } elseif ($pos >= $this->root_struct) {
6922 $this->document .= "</" . (isset($prefix) ? $prefix . ':' : '') . "$name>";
6923 }
6924 // switch status
6925 if ($pos == $this->root_struct) {
6926 $this->status = 'body';
6927 $this->root_struct_namespace = $this->message[$pos]['namespace'];
6928 } elseif ($name == 'Body') {
6929 $this->status = 'envelope';
6930 } elseif ($name == 'Header') {
6931 $this->status = 'envelope';
6932 } elseif ($name == 'Envelope') {
6933 //
6934 }
6935 // set parent back to my parent
6936 $this->parent = $this->message[$pos]['parent'];
6937 }
6938
6946 public function character_data($parser, $data)
6947 {
6948 $pos = $this->depth_array[$this->depth];
6949 if ($this->xml_encoding=='UTF-8') {
6950 // TODO: add an option to disable this for folks who want
6951 // raw UTF-8 that, e.g., might not map to iso-8859-1
6952 // TODO: this can also be handled with xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, "ISO-8859-1");
6953 if ($this->decode_utf8) {
6954 $data = utf8_decode($data);
6955 }
6956 }
6957 $this->message[$pos]['cdata'] .= $data;
6958 // for doclit
6959 if ($this->status == 'header') {
6960 $this->responseHeaders .= $data;
6961 } else {
6962 $this->document .= $data;
6963 }
6964 }
6965
6973 public function get_response()
6974 {
6975 return $this->soapresponse;
6976 }
6977
6984 public function get_soapbody()
6985 {
6986 return $this->soapresponse;
6987 }
6988
6995 public function get_soapheader()
6996 {
6997 return $this->soapheader;
6998 }
6999
7006 public function getHeaders()
7007 {
7009 }
7010
7020 public function decodeSimple($value, $type, $typens)
7021 {
7022 // TODO: use the namespace!
7023 if ((!isset($type)) || $type == 'string' || $type == 'long' || $type == 'unsignedLong') {
7024 return (string) $value;
7025 }
7026 if ($type == 'int' || $type == 'integer' || $type == 'short' || $type == 'byte') {
7027 return (int) $value;
7028 }
7029 if ($type == 'float' || $type == 'double' || $type == 'decimal') {
7030 return (float) $value;
7031 }
7032 if ($type == 'boolean') {
7033 if (strtolower($value) == 'false' || strtolower($value) == 'f') {
7034 return false;
7035 }
7036 return (bool) $value;
7037 }
7038 if ($type == 'base64' || $type == 'base64Binary') {
7039 $this->debug('Decode base64 value');
7040 return base64_decode($value);
7041 }
7042 // obscure numeric types
7043 if ($type == 'nonPositiveInteger' || $type == 'negativeInteger'
7044 || $type == 'nonNegativeInteger' || $type == 'positiveInteger'
7045 || $type == 'unsignedInt'
7046 || $type == 'unsignedShort' || $type == 'unsignedByte') {
7047 return (int) $value;
7048 }
7049 // bogus: parser treats array with no elements as a simple type
7050 if ($type == 'array') {
7051 return array();
7052 }
7053 // everything else
7054 return (string) $value;
7055 }
7056
7065 public function buildVal($pos)
7066 {
7067 if (!isset($this->message[$pos]['type'])) {
7068 $this->message[$pos]['type'] = '';
7069 }
7070 $this->debug('in buildVal() for ' . $this->message[$pos]['name'] . "(pos $pos) of type " . $this->message[$pos]['type']);
7071 // if there are children...
7072 if ($this->message[$pos]['children'] != '') {
7073 $this->debug('in buildVal, there are children');
7074 $children = explode('|', $this->message[$pos]['children']);
7075 array_shift($children); // knock off empty
7076 // md array
7077 if (isset($this->message[$pos]['arrayCols']) && $this->message[$pos]['arrayCols'] != '') {
7078 $r=0; // rowcount
7079 $c=0; // colcount
7080 foreach ($children as $child_pos) {
7081 $this->debug("in buildVal, got an MD array element: $r, $c");
7082 $params[$r][] = $this->message[$child_pos]['result'];
7083 $c++;
7084 if ($c == $this->message[$pos]['arrayCols']) {
7085 $c = 0;
7086 $r++;
7087 }
7088 }
7089 // array
7090 } elseif ($this->message[$pos]['type'] == 'array' || $this->message[$pos]['type'] == 'Array') {
7091 $this->debug('in buildVal, adding array ' . $this->message[$pos]['name']);
7092 foreach ($children as $child_pos) {
7093 $params[] = &$this->message[$child_pos]['result'];
7094 }
7095 // apache Map type: java hashtable
7096 } elseif ($this->message[$pos]['type'] == 'Map' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap') {
7097 $this->debug('in buildVal, Java Map ' . $this->message[$pos]['name']);
7098 foreach ($children as $child_pos) {
7099 $kv = explode("|", $this->message[$child_pos]['children']);
7100 $params[$this->message[$kv[1]]['result']] = &$this->message[$kv[2]]['result'];
7101 }
7102 // generic compound type
7103 //} elseif($this->message[$pos]['type'] == 'SOAPStruct' || $this->message[$pos]['type'] == 'struct') {
7104 } else {
7105 // Apache Vector type: treat as an array
7106 $this->debug('in buildVal, adding Java Vector or generic compound type ' . $this->message[$pos]['name']);
7107 if ($this->message[$pos]['type'] == 'Vector' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap') {
7108 $notstruct = 1;
7109 } else {
7110 $notstruct = 0;
7111 }
7112 //
7113 foreach ($children as $child_pos) {
7114 if ($notstruct) {
7115 $params[] = &$this->message[$child_pos]['result'];
7116 } else {
7117 if (isset($params[$this->message[$child_pos]['name']])) {
7118 // de-serialize repeated element name into an array
7119 if ((!is_array($params[$this->message[$child_pos]['name']])) || (!isset($params[$this->message[$child_pos]['name']][0]))) {
7120 $params[$this->message[$child_pos]['name']] = array($params[$this->message[$child_pos]['name']]);
7121 }
7122 $params[$this->message[$child_pos]['name']][] = &$this->message[$child_pos]['result'];
7123 } else {
7124 $params[$this->message[$child_pos]['name']] = &$this->message[$child_pos]['result'];
7125 }
7126 }
7127 }
7128 }
7129 if (isset($this->message[$pos]['xattrs'])) {
7130 $this->debug('in buildVal, handling attributes');
7131 foreach ($this->message[$pos]['xattrs'] as $n => $v) {
7132 $params[$n] = $v;
7133 }
7134 }
7135 // handle simpleContent
7136 if (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') {
7137 $this->debug('in buildVal, handling simpleContent');
7138 if (isset($this->message[$pos]['type'])) {
7139 $params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
7140 } else {
7141 $parent = $this->message[$pos]['parent'];
7142 if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
7143 $params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
7144 } else {
7145 $params['!'] = $this->message[$pos]['cdata'];
7146 }
7147 }
7148 }
7149 $ret = is_array($params) ? $params : array();
7150 $this->debug('in buildVal, return:');
7151 $this->appendDebug($this->varDump($ret));
7152 return $ret;
7153 } else {
7154 $this->debug('in buildVal, no children, building scalar');
7155 $cdata = isset($this->message[$pos]['cdata']) ? $this->message[$pos]['cdata'] : '';
7156 if (isset($this->message[$pos]['type'])) {
7157 $ret = $this->decodeSimple($cdata, $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
7158 $this->debug("in buildVal, return: $ret");
7159 return $ret;
7160 }
7161 $parent = $this->message[$pos]['parent'];
7162 if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
7163 $ret = $this->decodeSimple($cdata, $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
7164 $this->debug("in buildVal, return: $ret");
7165 return $ret;
7166 }
7167 $ret = $this->message[$pos]['cdata'];
7168 $this->debug("in buildVal, return: $ret");
7169 return $ret;
7170 }
7171 }
7172}
7173
7177class soap_parser extends nusoap_parser
7178{
7179}
7180
7181?><?php
7182
7183
7184
7205class nusoap_client extends nusoap_base
7206{
7207 public $username = ''; // Username for HTTP authentication
7208 public $password = ''; // Password for HTTP authentication
7209 public $authtype = ''; // Type of HTTP authentication
7210 public $certRequest = array(); // Certificate for HTTP SSL authentication
7211 public $requestHeaders = false; // SOAP headers in request (text)
7212 public $responseHeaders = ''; // SOAP headers from response (incomplete namespace resolution) (text)
7213 public $responseHeader = null; // SOAP Header from response (parsed)
7214 public $document = ''; // SOAP body response portion (incomplete namespace resolution) (text)
7215 public $endpoint;
7216 public $forceEndpoint = ''; // overrides WSDL endpoint
7217 public $proxyhost = '';
7218 public $proxyport = '';
7219 public $proxyusername = '';
7220 public $proxypassword = '';
7221 public $xml_encoding = ''; // character set encoding of incoming (response) messages
7222 public $http_encoding = false;
7223 public $timeout = 0; // HTTP connection timeout
7224 public $response_timeout = 30; // HTTP response timeout
7225 public $endpointType = ''; // soap|wsdl, empty for WSDL initialization error
7226 public $persistentConnection = false;
7227 public $defaultRpcParams = false; // This is no longer used
7228 public $request = ''; // HTTP request
7229 public $response = ''; // HTTP response
7230 public $responseData = ''; // SOAP payload of response
7231 public $cookies = array(); // Cookies from response or for request
7232 public $decode_utf8 = true; // toggles whether the parser decodes element content w/ utf8_decode()
7233 public $operations = array(); // WSDL operations, empty for WSDL initialization error
7234 public $curl_options = array(); // User-specified cURL options
7235 public $bindingType = ''; // WSDL operation binding type
7236 public $use_curl = false; // whether to always try to use cURL
7237
7238 /*
7239 * fault related variables
7240 */
7245 public $fault;
7250 public $faultcode;
7255 public $faultstring;
7260 public $faultdetail;
7261
7276 public function __construct($endpoint, $wsdl = false, $proxyhost = false, $proxyport = false, $proxyusername = false, $proxypassword = false, $timeout = 0, $response_timeout = 30)
7277 {
7279 $this->endpoint = $endpoint;
7280 $this->proxyhost = $proxyhost;
7281 $this->proxyport = $proxyport;
7282 $this->proxyusername = $proxyusername;
7283 $this->proxypassword = $proxypassword;
7284 $this->timeout = $timeout;
7285 $this->response_timeout = $response_timeout;
7286
7287 $this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout");
7288 $this->appendDebug('endpoint=' . $this->varDump($endpoint));
7289
7290 // make values
7291 if ($wsdl) {
7292 if (is_object($endpoint) && (get_class($endpoint) == 'wsdl')) {
7293 $this->wsdl = $endpoint;
7294 $this->endpoint = $this->wsdl->wsdl;
7295 $this->wsdlFile = $this->endpoint;
7296 $this->debug('existing wsdl instance created from ' . $this->endpoint);
7297 $this->checkWSDL();
7298 } else {
7299 $this->wsdlFile = $this->endpoint;
7300 $this->wsdl = null;
7301 $this->debug('will use lazy evaluation of wsdl from ' . $this->endpoint);
7302 }
7303 $this->endpointType = 'wsdl';
7304 } else {
7305 $this->debug("instantiate SOAP with endpoint at $endpoint");
7306 $this->endpointType = 'soap';
7307 }
7308 }
7309
7335 public function call($operation, $params=array(), $namespace='http://tempuri.org', $soapAction='', $headers=false, $rpcParams=null, $style='rpc', $use='encoded')
7336 {
7337 $this->operation = $operation;
7338 $this->fault = false;
7339 $this->setError('');
7340 $this->request = '';
7341 $this->response = '';
7342 $this->responseData = '';
7343 $this->faultstring = '';
7344 $this->faultcode = '';
7345 $this->opData = array();
7346
7347 $this->debug("call: operation=$operation, namespace=$namespace, soapAction=$soapAction, rpcParams=$rpcParams, style=$style, use=$use, endpointType=$this->endpointType");
7348 $this->appendDebug('params=' . $this->varDump($params));
7349 $this->appendDebug('headers=' . $this->varDump($headers));
7350 if ($headers) {
7351 $this->requestHeaders = $headers;
7352 }
7353 if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
7354 $this->loadWSDL();
7355 if ($this->getError()) {
7356 return false;
7357 }
7358 }
7359 // serialize parameters
7360 if ($this->endpointType == 'wsdl' && $opData = $this->getOperationData($operation)) {
7361 // use WSDL for operation
7362 $this->opData = $opData;
7363 $this->debug("found operation");
7364 $this->appendDebug('opData=' . $this->varDump($opData));
7365 if (isset($opData['soapAction'])) {
7366 $soapAction = $opData['soapAction'];
7367 }
7368 if (! $this->forceEndpoint) {
7369 $this->endpoint = $opData['endpoint'];
7370 } else {
7371 $this->endpoint = $this->forceEndpoint;
7372 }
7373 $namespace = isset($opData['input']['namespace']) ? $opData['input']['namespace'] : $namespace;
7374 $style = $opData['style'];
7375 $use = $opData['input']['use'];
7376 // add ns to ns array
7377 if ($namespace != '' && !isset($this->wsdl->namespaces[$namespace])) {
7378 $nsPrefix = 'ns' . rand(1000, 9999);
7379 $this->wsdl->namespaces[$nsPrefix] = $namespace;
7380 }
7381 $nsPrefix = $this->wsdl->getPrefixFromNamespace($namespace);
7382 // serialize payload
7383 if (is_string($params)) {
7384 $this->debug("serializing param string for WSDL operation $operation");
7385 $payload = $params;
7386 } elseif (is_array($params)) {
7387 $this->debug("serializing param array for WSDL operation $operation");
7388 $payload = $this->wsdl->serializeRPCParameters($operation, 'input', $params, $this->bindingType);
7389 } else {
7390 $this->debug('params must be array or string');
7391 $this->setError('params must be array or string');
7392 return false;
7393 }
7394 $usedNamespaces = $this->wsdl->usedNamespaces;
7395 if (isset($opData['input']['encodingStyle'])) {
7396 $encodingStyle = $opData['input']['encodingStyle'];
7397 } else {
7398 $encodingStyle = '';
7399 }
7400 $this->appendDebug($this->wsdl->getDebug());
7401 $this->wsdl->clearDebug();
7402 if ($errstr = $this->wsdl->getError()) {
7403 $this->debug('got wsdl error: ' . $errstr);
7404 $this->setError('wsdl error: ' . $errstr);
7405 return false;
7406 }
7407 } elseif ($this->endpointType == 'wsdl') {
7408 // operation not in WSDL
7409 $this->appendDebug($this->wsdl->getDebug());
7410 $this->wsdl->clearDebug();
7411 $this->setError('operation ' . $operation . ' not present.');
7412 $this->debug("operation '$operation' not present.");
7413 return false;
7414 } else {
7415 // no WSDL
7416 //$this->namespaces['ns1'] = $namespace;
7417 $nsPrefix = 'ns' . rand(1000, 9999);
7418 // serialize
7419 $payload = '';
7420 if (is_string($params)) {
7421 $this->debug("serializing param string for operation $operation");
7422 $payload = $params;
7423 } elseif (is_array($params)) {
7424 $this->debug("serializing param array for operation $operation");
7425 foreach ($params as $k => $v) {
7426 $payload .= $this->serialize_val($v, $k, false, false, false, false, $use);
7427 }
7428 } else {
7429 $this->debug('params must be array or string');
7430 $this->setError('params must be array or string');
7431 return false;
7432 }
7433 $usedNamespaces = array();
7434 if ($use == 'encoded') {
7435 $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
7436 } else {
7437 $encodingStyle = '';
7438 }
7439 }
7440 // wrap RPC calls with method element
7441 if ($style == 'rpc') {
7442 if ($use == 'literal') {
7443 $this->debug("wrapping RPC request with literal method element");
7444 if ($namespace) {
7445 // 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
7446 $payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" .
7447 $payload .
7448 "</$nsPrefix:$operation>";
7449 } else {
7450 $payload = "<$operation>" . $payload . "</$operation>";
7451 }
7452 } else {
7453 $this->debug("wrapping RPC request with encoded method element");
7454 if ($namespace) {
7455 $payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" .
7456 $payload .
7457 "</$nsPrefix:$operation>";
7458 } else {
7459 $payload = "<$operation>" .
7460 $payload .
7461 "</$operation>";
7462 }
7463 }
7464 }
7465 // serialize envelope
7466 $soapmsg = $this->serializeEnvelope($payload, $this->requestHeaders, $usedNamespaces, $style, $use, $encodingStyle);
7467 $this->debug("endpoint=$this->endpoint, soapAction=$soapAction, namespace=$namespace, style=$style, use=$use, encodingStyle=$encodingStyle");
7468 $this->debug('SOAP message length=' . strlen($soapmsg) . ' contents (max 1000 bytes)=' . substr($soapmsg, 0, 1000));
7469 // send
7470 $return = $this->send($this->getHTTPBody($soapmsg), $soapAction, $this->timeout, $this->response_timeout);
7471 if ($errstr = $this->getError()) {
7472 $this->debug('Error: ' . $errstr);
7473 return false;
7474 } else {
7475 $this->return = $return;
7476 $this->debug('sent message successfully and got a(n) ' . gettype($return));
7477 $this->appendDebug('return=' . $this->varDump($return));
7478
7479 // fault?
7480 if (is_array($return) && isset($return['faultcode'])) {
7481 $this->debug('got fault');
7482 $this->setError($return['faultcode'] . ': ' . $return['faultstring']);
7483 $this->fault = true;
7484 foreach ($return as $k => $v) {
7485 $this->$k = $v;
7486 $this->debug("$k = $v<br>");
7487 }
7488 return $return;
7489 } elseif ($style == 'document') {
7490 // NOTE: if the response is defined to have multiple parts (i.e. unwrapped),
7491 // we are only going to return the first part here...sorry about that
7492 return $return;
7493 } else {
7494 // array of return values
7495 if (is_array($return)) {
7496 // multiple 'out' parameters, which we return wrapped up
7497 // in the array
7498 if (sizeof($return) > 1) {
7499 return $return;
7500 }
7501 // single 'out' parameter (normally the return value)
7502 $return = array_shift($return);
7503 $this->debug('return shifted value: ');
7504 $this->appendDebug($this->varDump($return));
7505 return $return;
7506 // nothing returned (ie, echoVoid)
7507 } else {
7508 return "";
7509 }
7510 }
7511 }
7512 }
7513
7519 public function checkWSDL()
7520 {
7521 $this->appendDebug($this->wsdl->getDebug());
7522 $this->wsdl->clearDebug();
7523 $this->debug('checkWSDL');
7524 // catch errors
7525 if ($errstr = $this->wsdl->getError()) {
7526 $this->debug('got wsdl error: ' . $errstr);
7527 $this->setError('wsdl error: ' . $errstr);
7528 } elseif ($this->operations = $this->wsdl->getOperations('soap')) {
7529 $this->bindingType = 'soap';
7530 $this->debug('got ' . count($this->operations) . ' operations from wsdl ' . $this->wsdlFile . ' for binding type ' . $this->bindingType);
7531 } elseif ($this->operations = $this->wsdl->getOperations('soap12')) {
7532 $this->bindingType = 'soap12';
7533 $this->debug('got ' . count($this->operations) . ' operations from wsdl ' . $this->wsdlFile . ' for binding type ' . $this->bindingType);
7534 $this->debug('**************** WARNING: SOAP 1.2 BINDING *****************');
7535 } else {
7536 $this->debug('getOperations returned false');
7537 $this->setError('no operations defined in the WSDL document!');
7538 }
7539 }
7540
7546 public function loadWSDL()
7547 {
7548 $this->debug('instantiating wsdl class with doc: ' . $this->wsdlFile);
7549 $this->wsdl = new wsdl('', $this->proxyhost, $this->proxyport, $this->proxyusername, $this->proxypassword, $this->timeout, $this->response_timeout, $this->curl_options, $this->use_curl);
7550 $this->wsdl->setCredentials($this->username, $this->password, $this->authtype, $this->certRequest);
7551 $this->wsdl->fetchWSDL($this->wsdlFile);
7552 $this->checkWSDL();
7553 }
7554
7562 public function getOperationData($operation)
7563 {
7564 if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
7565 $this->loadWSDL();
7566 if ($this->getError()) {
7567 return false;
7568 }
7569 }
7570 if (isset($this->operations[$operation])) {
7571 return $this->operations[$operation];
7572 }
7573 $this->debug("No data for operation: $operation");
7574 }
7575
7590 public function send($msg, $soapaction = '', $timeout=0, $response_timeout=30)
7591 {
7592 $this->checkCookies();
7593 // detect transport
7594 switch (true) {
7595 // http(s)
7596 case preg_match('/^http/', $this->endpoint):
7597 $this->debug('transporting via HTTP');
7598 if ($this->persistentConnection == true && is_object($this->persistentConnection)) {
7600 } else {
7601 $http = new soap_transport_http($this->endpoint, $this->curl_options, $this->use_curl);
7602 if ($this->persistentConnection) {
7603 $http->usePersistentConnection();
7604 }
7605 }
7606 $http->setContentType($this->getHTTPContentType(), $this->getHTTPContentTypeCharset());
7607 $http->setSOAPAction($soapaction);
7608 if ($this->proxyhost && $this->proxyport) {
7609 $http->setProxy($this->proxyhost, $this->proxyport, $this->proxyusername, $this->proxypassword);
7610 }
7611 if ($this->authtype != '') {
7612 $http->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest);
7613 }
7614 if ($this->http_encoding != '') {
7615 $http->setEncoding($this->http_encoding);
7616 }
7617 $this->debug('sending message, length=' . strlen($msg));
7618 if (preg_match('/^http:/', $this->endpoint)) {
7619 //if(strpos($this->endpoint,'http:')){
7620 $this->responseData = $http->send($msg, $timeout, $response_timeout, $this->cookies);
7621 } elseif (preg_match('/^https/', $this->endpoint)) {
7622 //} elseif(strpos($this->endpoint,'https:')){
7623 //if(phpversion() == '4.3.0-dev'){
7624 //$response = $http->send($msg,$timeout,$response_timeout);
7625 //$this->request = $http->outgoing_payload;
7626 //$this->response = $http->incoming_payload;
7627 //} else
7628 $this->responseData = $http->sendHTTPS($msg, $timeout, $response_timeout, $this->cookies);
7629 } else {
7630 $this->setError('no http/s in endpoint url');
7631 }
7632 $this->request = $http->outgoing_payload;
7633 $this->response = $http->incoming_payload;
7634 $this->appendDebug($http->getDebug());
7635 $this->UpdateCookies($http->incoming_cookies);
7636
7637 // save transport object if using persistent connections
7638 if ($this->persistentConnection) {
7639 $http->clearDebug();
7640 if (!is_object($this->persistentConnection)) {
7641 $this->persistentConnection = $http;
7642 }
7643 }
7644
7645 if ($err = $http->getError()) {
7646 $this->setError('HTTP Error: ' . $err);
7647 return false;
7648 } elseif ($this->getError()) {
7649 return false;
7650 } else {
7651 $this->debug('got response, length=' . strlen($this->responseData) . ' type=' . $http->incoming_headers['content-type']);
7652 return $this->parseResponse($http->incoming_headers, $this->responseData);
7653 }
7654 break;
7655 default:
7656 $this->setError('no transport found, or selected transport is not yet supported!');
7657 return false;
7658 break;
7659 }
7660 }
7661
7670 public function parseResponse($headers, $data)
7671 {
7672 $this->debug('Entering parseResponse() for data of length ' . strlen($data) . ' headers:');
7673 $this->appendDebug($this->varDump($headers));
7674 if (!strstr($headers['content-type'], 'text/xml')) {
7675 $this->setError('Response not of type text/xml: ' . $headers['content-type']);
7676 return false;
7677 }
7678 if (strpos($headers['content-type'], '=')) {
7679 $enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1));
7680 $this->debug('Got response encoding: ' . $enc);
7681 if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i', $enc)) {
7682 $this->xml_encoding = strtoupper($enc);
7683 } else {
7684 $this->xml_encoding = 'US-ASCII';
7685 }
7686 } else {
7687 // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
7688 $this->xml_encoding = 'ISO-8859-1';
7689 }
7690 $this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser');
7691 $parser = new nusoap_parser($data, $this->xml_encoding, $this->operation, $this->decode_utf8);
7692 // add parser debug data to our debug
7693 $this->appendDebug($parser->getDebug());
7694 // if parse errors
7695 if ($errstr = $parser->getError()) {
7696 $this->setError($errstr);
7697 // destroy the parser object
7698 unset($parser);
7699 return false;
7700 } else {
7701 // get SOAP headers
7702 $this->responseHeaders = $parser->getHeaders();
7703 // get SOAP headers
7704 $this->responseHeader = $parser->get_soapheader();
7705 // get decoded message
7706 $return = $parser->get_soapbody();
7707 // add document for doclit support
7708 $this->document = $parser->document;
7709 // destroy the parser object
7710 unset($parser);
7711 // return decode message
7712 return $return;
7713 }
7714 }
7715
7723 public function setCurlOption($option, $value)
7724 {
7725 $this->debug("setCurlOption option=$option, value=");
7726 $this->appendDebug($this->varDump($value));
7727 $this->curl_options[$option] = $value;
7728 }
7729
7736 public function setEndpoint($endpoint)
7737 {
7738 $this->debug("setEndpoint(\"$endpoint\")");
7739 $this->forceEndpoint = $endpoint;
7740 }
7741
7748 public function setHeaders($headers)
7749 {
7750 $this->debug("setHeaders headers=");
7751 $this->appendDebug($this->varDump($headers));
7752 $this->requestHeaders = $headers;
7753 }
7754
7761 public function getHeaders()
7762 {
7764 }
7765
7772 public function getHeader()
7773 {
7774 return $this->responseHeader;
7775 }
7776
7786 public function setHTTPProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '')
7787 {
7788 $this->proxyhost = $proxyhost;
7789 $this->proxyport = $proxyport;
7790 $this->proxyusername = $proxyusername;
7791 $this->proxypassword = $proxypassword;
7792 }
7793
7803 public function setCredentials($username, $password, $authtype = 'basic', $certRequest = array())
7804 {
7805 $this->debug("setCredentials username=$username authtype=$authtype certRequest=");
7806 $this->appendDebug($this->varDump($certRequest));
7807 $this->username = $username;
7808 $this->password = $password;
7809 $this->authtype = $authtype;
7810 $this->certRequest = $certRequest;
7811 }
7812
7819 public function setHTTPEncoding($enc='gzip, deflate')
7820 {
7821 $this->debug("setHTTPEncoding(\"$enc\")");
7822 $this->http_encoding = $enc;
7823 }
7824
7831 public function setUseCURL($use)
7832 {
7833 $this->debug("setUseCURL($use)");
7834 $this->use_curl = $use;
7835 }
7836
7842 public function useHTTPPersistentConnection()
7843 {
7844 $this->debug("useHTTPPersistentConnection");
7845 $this->persistentConnection = true;
7846 }
7847
7859 public function getDefaultRpcParams()
7860 {
7862 }
7863
7875 public function setDefaultRpcParams($rpcParams)
7876 {
7877 $this->defaultRpcParams = $rpcParams;
7878 }
7879
7887 public function getProxy()
7888 {
7889 $r = rand();
7890 $evalStr = $this->_getProxyClassCode($r);
7891 //$this->debug("proxy class: $evalStr");
7892 if ($this->getError()) {
7893 $this->debug("Error from _getProxyClassCode, so return NULL");
7894 return null;
7895 }
7896 // eval the class
7897 eval($evalStr);
7898 // instantiate proxy object
7899 eval("\$proxy = new nusoap_proxy_$r('');");
7900 // transfer current wsdl data to the proxy thereby avoiding parsing the wsdl twice
7901 $proxy->endpointType = 'wsdl';
7902 $proxy->wsdlFile = $this->wsdlFile;
7903 $proxy->wsdl = $this->wsdl;
7904 $proxy->operations = $this->operations;
7905 $proxy->defaultRpcParams = $this->defaultRpcParams;
7906 // transfer other state
7907 $proxy->soap_defencoding = $this->soap_defencoding;
7908 $proxy->username = $this->username;
7909 $proxy->password = $this->password;
7910 $proxy->authtype = $this->authtype;
7911 $proxy->certRequest = $this->certRequest;
7912 $proxy->requestHeaders = $this->requestHeaders;
7913 $proxy->endpoint = $this->endpoint;
7914 $proxy->forceEndpoint = $this->forceEndpoint;
7915 $proxy->proxyhost = $this->proxyhost;
7916 $proxy->proxyport = $this->proxyport;
7917 $proxy->proxyusername = $this->proxyusername;
7918 $proxy->proxypassword = $this->proxypassword;
7919 $proxy->http_encoding = $this->http_encoding;
7920 $proxy->timeout = $this->timeout;
7921 $proxy->response_timeout = $this->response_timeout;
7922 $proxy->persistentConnection = &$this->persistentConnection;
7923 $proxy->decode_utf8 = $this->decode_utf8;
7924 $proxy->curl_options = $this->curl_options;
7925 $proxy->bindingType = $this->bindingType;
7926 $proxy->use_curl = $this->use_curl;
7927 return $proxy;
7928 }
7929
7936 public function _getProxyClassCode($r)
7937 {
7938 $this->debug("in getProxy endpointType=$this->endpointType");
7939 $this->appendDebug("wsdl=" . $this->varDump($this->wsdl));
7940 if ($this->endpointType != 'wsdl') {
7941 $evalStr = 'A proxy can only be created for a WSDL client';
7942 $this->setError($evalStr);
7943 $evalStr = "echo \"$evalStr\";";
7944 return $evalStr;
7945 }
7946 if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
7947 $this->loadWSDL();
7948 if ($this->getError()) {
7949 return "echo \"" . $this->getError() . "\";";
7950 }
7951 }
7952 $evalStr = '';
7953 foreach ($this->operations as $operation => $opData) {
7954 if ($operation != '') {
7955 // create param string and param comment string
7956 if (sizeof($opData['input']['parts']) > 0) {
7957 $paramStr = '';
7958 $paramArrayStr = '';
7959 $paramCommentStr = '';
7960 foreach ($opData['input']['parts'] as $name => $type) {
7961 $paramStr .= "\$$name, ";
7962 $paramArrayStr .= "'$name' => \$$name, ";
7963 $paramCommentStr .= "$type \$$name, ";
7964 }
7965 $paramStr = substr($paramStr, 0, strlen($paramStr)-2);
7966 $paramArrayStr = substr($paramArrayStr, 0, strlen($paramArrayStr)-2);
7967 $paramCommentStr = substr($paramCommentStr, 0, strlen($paramCommentStr)-2);
7968 } else {
7969 $paramStr = '';
7970 $paramArrayStr = '';
7971 $paramCommentStr = 'void';
7972 }
7973 $opData['namespace'] = !isset($opData['namespace']) ? 'http://testuri.com' : $opData['namespace'];
7974 $evalStr .= "// $paramCommentStr
7975 function " . str_replace('.', '__', $operation) . "($paramStr) {
7976 \$params = array($paramArrayStr);
7977 return \$this->call('$operation', \$params, '" . $opData['namespace'] . "', '" . (isset($opData['soapAction']) ? $opData['soapAction'] : '') . "');
7978 }
7979 ";
7980 unset($paramStr);
7981 unset($paramCommentStr);
7982 }
7983 }
7984 $evalStr = 'class nusoap_proxy_' . $r . ' extends nusoap_client {
7985 ' . $evalStr . '
7986}';
7987 return $evalStr;
7988 }
7989
7996 public function getProxyClassCode()
7997 {
7998 $r = rand();
7999 return $this->_getProxyClassCode($r);
8000 }
8001
8009 public function getHTTPBody($soapmsg)
8010 {
8011 return $soapmsg;
8012 }
8013
8022 public function getHTTPContentType()
8023 {
8024 return 'text/xml';
8025 }
8026
8036 public function getHTTPContentTypeCharset()
8037 {
8039 }
8040
8041 /*
8042 * whether or not parser should decode utf8 element content
8043 *
8044 * @return always returns true
8045 * @access public
8046 */
8047 public function decodeUTF8($bool)
8048 {
8049 $this->decode_utf8 = $bool;
8050 return true;
8051 }
8052
8061 public function setCookie($name, $value)
8062 {
8063 if (strlen($name) == 0) {
8064 return false;
8065 }
8066 $this->cookies[] = array('name' => $name, 'value' => $value);
8067 return true;
8068 }
8069
8076 public function getCookies()
8077 {
8078 return $this->cookies;
8079 }
8080
8087 public function checkCookies()
8088 {
8089 if (sizeof($this->cookies) == 0) {
8090 return true;
8091 }
8092 $this->debug('checkCookie: check ' . sizeof($this->cookies) . ' cookies');
8093 $curr_cookies = $this->cookies;
8094 $this->cookies = array();
8095 foreach ($curr_cookies as $cookie) {
8096 if (! is_array($cookie)) {
8097 $this->debug('Remove cookie that is not an array');
8098 continue;
8099 }
8100 if ((isset($cookie['expires'])) && (! empty($cookie['expires']))) {
8101 if (strtotime($cookie['expires']) > time()) {
8102 $this->cookies[] = $cookie;
8103 } else {
8104 $this->debug('Remove expired cookie ' . $cookie['name']);
8105 }
8106 } else {
8107 $this->cookies[] = $cookie;
8108 }
8109 }
8110 $this->debug('checkCookie: ' . sizeof($this->cookies) . ' cookies left in array');
8111 return true;
8112 }
8113
8121 public function UpdateCookies($cookies)
8122 {
8123 if (sizeof($this->cookies) == 0) {
8124 // no existing cookies: take whatever is new
8125 if (sizeof($cookies) > 0) {
8126 $this->debug('Setting new cookie(s)');
8127 $this->cookies = $cookies;
8128 }
8129 return true;
8130 }
8131 if (sizeof($cookies) == 0) {
8132 // no new cookies: keep what we've got
8133 return true;
8134 }
8135 // merge
8136 foreach ($cookies as $newCookie) {
8137 if (!is_array($newCookie)) {
8138 continue;
8139 }
8140 if ((!isset($newCookie['name'])) || (!isset($newCookie['value']))) {
8141 continue;
8142 }
8143 $newName = $newCookie['name'];
8144
8145 $found = false;
8146 for ($i = 0; $i < count($this->cookies); $i++) {
8147 $cookie = $this->cookies[$i];
8148 if (!is_array($cookie)) {
8149 continue;
8150 }
8151 if (!isset($cookie['name'])) {
8152 continue;
8153 }
8154 if ($newName != $cookie['name']) {
8155 continue;
8156 }
8157 $newDomain = isset($newCookie['domain']) ? $newCookie['domain'] : 'NODOMAIN';
8158 $domain = isset($cookie['domain']) ? $cookie['domain'] : 'NODOMAIN';
8159 if ($newDomain != $domain) {
8160 continue;
8161 }
8162 $newPath = isset($newCookie['path']) ? $newCookie['path'] : 'NOPATH';
8163 $path = isset($cookie['path']) ? $cookie['path'] : 'NOPATH';
8164 if ($newPath != $path) {
8165 continue;
8166 }
8167 $this->cookies[$i] = $newCookie;
8168 $found = true;
8169 $this->debug('Update cookie ' . $newName . '=' . $newCookie['value']);
8170 break;
8171 }
8172 if (! $found) {
8173 $this->debug('Add cookie ' . $newName . '=' . $newCookie['value']);
8174 $this->cookies[] = $newCookie;
8175 }
8176 }
8177 return true;
8178 }
8179}
8180
8181if (!extension_loaded('soap')) {
8185 class soapclient extends nusoap_client
8186 {
8187 }
8188}
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
$out
Definition: buildRTE.php:24
Backward compatibility.
Definition: nusoap.php:2062
nusoap_base
Definition: nusoap.php:97
getPrefix($str)
returns the prefix part of a prefixed string returns false, if not prefixed
Definition: nusoap.php:839
& getDebug()
gets the current debug data for this instance
Definition: nusoap.php:332
& getDebugAsXMLComment()
gets the current debug data for this instance as an XML comment this may change the contents of the d...
Definition: nusoap.php:346
setError($str)
sets error string
Definition: nusoap.php:395
getNamespaceFromPrefix($prefix)
pass it a prefix, it returns a namespace
Definition: nusoap.php:855
debug($string)
adds debug data to the instance debug string with formatting
Definition: nusoap.php:292
getPrefixFromNamespace($ns)
returns the prefix for a given namespace (or prefix) or false if no prefixes registered for the given...
Definition: nusoap.php:872
serialize_val($val, $name=false, $type=false, $name_ns=false, $type_ns=false, $attributes=false, $use='encoded', $soapval=false)
serializes PHP values in accordance w/ section 5.
Definition: nusoap.php:433
serializeEnvelope($body, $headers=false, $namespaces=array(), $style='rpc', $use='encoded', $encodingStyle='http://schemas.xmlsoap.org/soap/encoding/')
serializes a message
Definition: nusoap.php:700
clearDebug()
clears the current debug data for this instance
Definition: nusoap.php:319
expandEntities($val)
expands entities, e.g.
Definition: nusoap.php:363
$soap_defencoding
Definition: nusoap.php:164
expandQname($qname)
expands (changes prefix to namespace) a qualified name
Definition: nusoap.php:795
$XMLSchemaVersion
Definition: nusoap.php:155
varDump($data)
Returns a string with the output of var_dump.
Definition: nusoap.php:909
getError()
returns error string if present
Definition: nusoap.php:381
appendDebug($string)
adds debug data to the instance debug string without formatting
Definition: nusoap.php:305
getLocalPart($str)
returns the local part of a prefixed string returns the original string, if not prefixed
Definition: nusoap.php:821
isArraySimpleOrStruct($val)
detect if array is a simple array or a struct (associative array)
Definition: nusoap.php:407
__construct()
constructor
Definition: nusoap.php:237
[nu]soapclient higher level class for easy usage.
Definition: nusoap.php:7206
setCurlOption($option, $value)
sets user-specified cURL options
Definition: nusoap.php:7723
setCredentials($username, $password, $authtype='basic', $certRequest=array())
if authenticating, set user credentials here
Definition: nusoap.php:7803
setHTTPProxy($proxyhost, $proxyport, $proxyusername='', $proxypassword='')
set proxy info here
Definition: nusoap.php:7786
getProxy()
dynamically creates an instance of a proxy class, allowing user to directly call methods from wsdl
Definition: nusoap.php:7887
send($msg, $soapaction='', $timeout=0, $response_timeout=30)
send the SOAP message
Definition: nusoap.php:7590
setUseCURL($use)
Set whether to try to use cURL connections if possible.
Definition: nusoap.php:7831
call($operation, $params=array(), $namespace='http://tempuri.org', $soapAction='', $headers=false, $rpcParams=null, $style='rpc', $use='encoded')
calls method, returns PHP native type
Definition: nusoap.php:7335
getProxyClassCode()
dynamically creates proxy class code
Definition: nusoap.php:7996
checkCookies()
checks all Cookies and delete those which are expired
Definition: nusoap.php:8087
getHTTPContentType()
gets the HTTP content type for the current request.
Definition: nusoap.php:8022
setHTTPEncoding($enc='gzip, deflate')
use HTTP encoding
Definition: nusoap.php:7819
getHeader()
get the SOAP response Header (parsed)
Definition: nusoap.php:7772
decodeUTF8($bool)
Definition: nusoap.php:8047
useHTTPPersistentConnection()
use HTTP persistent connections if possible
Definition: nusoap.php:7842
setCookie($name, $value)
adds a new Cookie into $this->cookies array
Definition: nusoap.php:8061
getHTTPContentTypeCharset()
gets the HTTP content type charset for the current request.
Definition: nusoap.php:8036
getOperationData($operation)
get available data pertaining to an operation
Definition: nusoap.php:7562
getDefaultRpcParams()
gets the default RPC parameter setting.
Definition: nusoap.php:7859
checkWSDL()
check WSDL passed as an instance or pulled from an endpoint
Definition: nusoap.php:7519
setHeaders($headers)
set the SOAP headers
Definition: nusoap.php:7748
loadWSDL()
instantiate wsdl object and parse wsdl file
Definition: nusoap.php:7546
getHTTPBody($soapmsg)
gets the HTTP body for the current request.
Definition: nusoap.php:8009
setDefaultRpcParams($rpcParams)
sets the default RPC parameter setting.
Definition: nusoap.php:7875
setEndpoint($endpoint)
sets the SOAP endpoint, which can override WSDL
Definition: nusoap.php:7736
UpdateCookies($cookies)
updates the current cookies with a new set
Definition: nusoap.php:8121
getHeaders()
get the SOAP response headers (namespace resolution incomplete)
Definition: nusoap.php:7761
_getProxyClassCode($r)
dynamically creates proxy class code
Definition: nusoap.php:7936
getCookies()
gets all Cookies
Definition: nusoap.php:8076
parseResponse($headers, $data)
processes SOAP message returned from server
Definition: nusoap.php:7670
Contains information for a SOAP fault.
Definition: nusoap.php:1036
serialize()
serialize a fault
Definition: nusoap.php:1085
nusoap_parser class parses SOAP XML messages into native PHP values
Definition: nusoap.php:6546
$root_struct_namespace
Definition: nusoap.php:6552
character_data($parser, $data)
element content handler
Definition: nusoap.php:6946
get_soapbody()
get the parsed SOAP Body (NULL if there was none)
Definition: nusoap.php:6984
end_element($parser, $name)
end-element handler
Definition: nusoap.php:6841
getHeaders()
get the unparsed SOAP Header
Definition: nusoap.php:7006
get_response()
get the parsed message (SOAP Body)
Definition: nusoap.php:6973
decodeSimple($value, $type, $typens)
decodes simple types into PHP variables
Definition: nusoap.php:7020
get_soapheader()
get the parsed SOAP Header (NULL if there was none)
Definition: nusoap.php:6995
start_element($parser, $name, $attrs)
start-element handler
Definition: nusoap.php:6685
buildVal($pos)
builds response structures for compound values (arrays/structs) and scalars
Definition: nusoap.php:7065
nusoap_server allows the user to create a SOAP server that is capable of receiving messages and retur...
Definition: nusoap.php:3523
verify_method($operation, $request)
takes the value that was created by parsing the request and compares to the method's signature,...
Definition: nusoap.php:4303
$methodreturnisliteralxml
Definition: nusoap.php:3632
getHTTPBody($soapmsg)
gets the HTTP body for the current response.
Definition: nusoap.php:4375
invoke_method()
invokes a PHP function for the requested SOAP method
Definition: nusoap.php:3984
add_to_map($methodname, $in, $out)
add a method to the dispatch map (this has been replaced by the register method)
Definition: nusoap.php:4416
getHTTPContentType()
gets the HTTP content type for the current response.
Definition: nusoap.php:4388
parse_request($data='')
parses a request
Definition: nusoap.php:3936
getHTTPContentTypeCharset()
gets the HTTP content type charset for the current response.
Definition: nusoap.php:4402
serialize_return()
serializes the return value from a PHP function into a full SOAP Envelope
Definition: nusoap.php:4130
send_response()
sends an HTTP response
Definition: nusoap.php:4223
fault($faultcode, $faultstring, $faultactor='', $faultdetail='')
Specify a fault to be returned to the client.
Definition: nusoap.php:4505
parse_http_headers()
parses HTTP request headers.
Definition: nusoap.php:3807
service($data)
processes request and returns response
Definition: nusoap.php:3744
parseRequest($headers, $data)
processes SOAP message received from client
Definition: nusoap.php:4323
configureWSDL($serviceName, $namespace=false, $endpoint=false, $style='rpc', $transport='http://schemas.xmlsoap.org/soap/http', $schemaTargetNamespace=false)
Sets up wsdl object.
Definition: nusoap.php:4525
parses an XML Schema, allows access to it's data, other utility methods.
Definition: nusoap.php:1128
schemaCharacterData($parser, $data)
element content handler
Definition: nusoap.php:1628
getTypeDef($type)
returns an associative array of information about a given type returns false if no type exists by the...
Definition: nusoap.php:1808
addComplexType($name, $typeClass='complexType', $phpType='array', $compositor='', $restrictionBase='', $elements=array(), $attrs=array(), $arrayType='')
adds a complex type to the schema
Definition: nusoap.php:1995
typeToForm($name, $type)
returns HTML form elements that allow a user to enter values for creating an instance of the given ty...
Definition: nusoap.php:1922
addElement($attrs)
adds an element to the schema
Definition: nusoap.php:2045
getPHPType($type, $ns)
get the PHP type of a user defined type in the schema PHP type is kind of a misnomer since it actuall...
Definition: nusoap.php:1774
xdebug($string)
adds debug data to the clas level debug string
Definition: nusoap.php:1757
addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array())
adds a simple type to the schema
Definition: nusoap.php:2024
serializeSchema()
serialize the schema
Definition: nusoap.php:1639
parseString($xml, $type)
parse an XML string
Definition: nusoap.php:1226
schemaEndElement($parser, $name)
end-element handler
Definition: nusoap.php:1590
schemaStartElement($parser, $name, $attrs)
start-element handler
Definition: nusoap.php:1292
serializeTypeDef($type)
returns a sample serialization of a given type, or false if no type by the given name
Definition: nusoap.php:1885
parseFile($xml, $type)
parse an XML file
Definition: nusoap.php:1199
CreateTypeName($ename)
gets a type name for an unnamed type
Definition: nusoap.php:1275
Backward compatibility.
Definition: nusoap.php:1111
Backward compatibility.
Definition: nusoap.php:7178
Backward compatibility.
Definition: nusoap.php:4601
transport class for sending/receiving data via HTTP and HTTPS NOTE: PHP must be compiled with the CUR...
Definition: nusoap.php:2187
sendRequest($data, $cookies=null)
sends the SOAP request via HTTP[S]
Definition: nusoap.php:2932
setCurlOption($option, $value)
sets a cURL option
Definition: nusoap.php:2253
getCookiesForRequest($cookies, $secure=false)
sort out cookies for the current request
Definition: nusoap.php:3467
send($data, $timeout=0, $response_timeout=30, $cookies=null)
sends the SOAP request and gets the SOAP response via HTTP[S]
Definition: nusoap.php:2600
parseCookie($cookie_str)
parse an incoming Cookie into it's parts
Definition: nusoap.php:3400
setURL($url)
sets the URL to which to connect
Definition: nusoap.php:2293
getResponse()
gets the SOAP response via HTTP[S]
Definition: nusoap.php:2990
setContentType($type, $charset=false)
sets the content-type for the SOAP message to be sent
Definition: nusoap.php:3368
unsetHeader($name)
unsets an HTTP header
Definition: nusoap.php:2279
isSkippableCurlHeader(&$data)
Test if the given string starts with a header that is to be skipped.
Definition: nusoap.php:2796
setSOAPAction($soapaction)
set the soapaction value
Definition: nusoap.php:2731
setEncoding($enc='gzip, deflate')
use http encoding
Definition: nusoap.php:2742
usePersistentConnection()
specifies that an HTTP persistent connection should be used
Definition: nusoap.php:3379
setCredentials($username, $password, $authtype='basic', $digestRequest=array(), $certRequest=array())
if authenticating, set user credentials here
Definition: nusoap.php:2656
buildPayload($data, $cookie_str='')
Writes the payload, including HTTP headers, to $this->outgoing_payload.
Definition: nusoap.php:2884
connect($connection_timeout=0, $response_timeout=30)
establish an HTTP connection
Definition: nusoap.php:2357
setHeader($name, $value)
sets an HTTP header
Definition: nusoap.php:2267
io_method()
gets the I/O method to use
Definition: nusoap.php:2338
decodeChunked($buffer, $lb)
decode a string that is encoded w/ "chunked' transfer encoding as defined in RFC2068 19....
Definition: nusoap.php:2826
setProxy($proxyhost, $proxyport, $proxyusername='', $proxypassword='', $proxyauthtype='basic')
set proxy info here
Definition: nusoap.php:2767
sendHTTPS($data, $timeout=0, $response_timeout=30, $cookies=null)
sends the SOAP request and gets the SOAP response via HTTPS using CURL
Definition: nusoap.php:2641
For creating serializable abstractions of native PHP types.
Definition: nusoap.php:2081
serialize($use='encoded')
return serialized value
Definition: nusoap.php:2154
$element_ns
Definition: nusoap.php:2109
decode()
decodes a soapval object into a PHP native type
Definition: nusoap.php:2165
$attributes
Definition: nusoap.php:2123
parses a WSDL file, allows access to it's data, other utility methods.
Definition: nusoap.php:4618
$currentMessage
Definition: nusoap.php:4627
$import
Definition: nusoap.php:4640
$username
Definition: nusoap.php:4656
$ports
Definition: nusoap.php:4633
$proxyhost
Definition: nusoap.php:4647
character_data($parser, $data)
element content handler
Definition: nusoap.php:5150
serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType)
serializes the attributes for a complexType
Definition: nusoap.php:6211
$opData
Definition: nusoap.php:4635
$currentSchema
Definition: nusoap.php:4623
getBindingData($binding)
Definition: nusoap.php:5180
serializeRPCParameters($operation, $direction, $parameters, $bindingType='soap')
serialize PHP values according to a WSDL message definition contrary to the method name,...
Definition: nusoap.php:5734
$currentPortType
Definition: nusoap.php:4630
addElement($attrs)
adds an element to the WSDL types
Definition: nusoap.php:6440
getTypeDef($type, $ns)
returns an array of information about a given type returns false if no type exists by the given name
Definition: nusoap.php:5297
$status
Definition: nusoap.php:4636
getOperations($bindingType='soap')
returns an assoc array of operation names => operation data
Definition: nusoap.php:5194
setCredentials($username, $password, $authtype='basic', $certRequest=array())
if authenticating, set user credentials here
Definition: nusoap.php:5170
$proxypassword
Definition: nusoap.php:4650
$certRequest
Definition: nusoap.php:4659
getOperationData($operation, $bindingType='soap')
returns an associative array of data necessary for calling an operation
Definition: nusoap.php:5226
$portTypes
Definition: nusoap.php:4629
$currentOperation
Definition: nusoap.php:4628
$messages
Definition: nusoap.php:4626
serializeParameters($operation, $direction, $parameters)
serialize a PHP value according to a WSDL message definition
Definition: nusoap.php:5829
fetchWSDL($wsdl)
fetches the WSDL document and parses it
Definition: nusoap.php:4697
$password
Definition: nusoap.php:4657
addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array())
adds an XML Schema simple type to the WSDL types
Definition: nusoap.php:6425
$depth
Definition: nusoap.php:4644
$bindings
Definition: nusoap.php:4631
serialize($debug=0)
serialize the parsed wsdl
Definition: nusoap.php:5496
$wsdl
Definition: nusoap.php:4620
$timeout
Definition: nusoap.php:4651
$endpoint
Definition: nusoap.php:4638
$use_curl
Definition: nusoap.php:4654
$proxyusername
Definition: nusoap.php:4649
getOperationDataForSoapAction($soapAction, $bindingType='soap')
returns an associative array of data necessary for calling an operation
Definition: nusoap.php:5258
$documentation
Definition: nusoap.php:4637
webDescription()
prints html description of services
Definition: nusoap.php:5354
serializeType($name, $type, $value, $use='encoded', $encodingStyle=false, $unqualified=false)
serializes a PHP value according a given type definition
Definition: nusoap.php:5907
parseWSDL($wsdl='')
parses the wsdl document
Definition: nusoap.php:4801
$message
Definition: nusoap.php:4624
parametersMatchWrapped($type, &$parameters)
determine whether a set of parameters are unwrapped when they are expect to be wrapped,...
Definition: nusoap.php:5640
start_element($parser, $name, $attrs)
start-element handler
Definition: nusoap.php:4906
$proxyport
Definition: nusoap.php:4648
$authtype
Definition: nusoap.php:4658
end_element($parser, $name)
end-element handler
Definition: nusoap.php:5119
$parser
Definition: nusoap.php:4642
$depth_array
Definition: nusoap.php:4645
serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use='encoded', $encodingStyle=false)
serializes the elements for a complexType
Definition: nusoap.php:6274
$position
Definition: nusoap.php:4643
$schemas
Definition: nusoap.php:4622
$currentPort
Definition: nusoap.php:4634
$complexTypes
Definition: nusoap.php:4625
$curl_options
Definition: nusoap.php:4653
$response_timeout
Definition: nusoap.php:4652
addComplexType($name, $typeClass='complexType', $phpType='array', $compositor='', $restrictionBase='', $elements=array(), $attrs=array(), $arrayType='')
adds an XML Schema complex type to the WSDL types
Definition: nusoap.php:6377
addOperation($name, $in=false, $out=false, $namespace=false, $soapaction=false, $style='rpc', $use='encoded', $documentation='', $encodingStyle='')
register an operation with the server
Definition: nusoap.php:6460
$currentBinding
Definition: nusoap.php:4632
$c
Definition: cli.php:38
if($err=$client->getError()) $namespace
if(! $DIC->user() ->getId()||!ilLTIConsumerAccess::hasCustomProviderCreationAccess()) $params
Definition: ltiregstart.php:33
$scope
Definition: ltiregstart.php:53
$path
Definition: ltiservices.php:32
if(empty($path)) $serviceName
Definition: ltiservices.php:38
$res
Definition: ltiservices.php:69
if($clientAssertionType !='urn:ietf:params:oauth:client-assertion-type:jwt-bearer'|| $grantType !='client_credentials') $parts
Definition: ltitoken.php:64
if(count($parts) !=3) $payload
Definition: ltitoken.php:70
if($format !==null) $name
Definition: metadata.php:247
$i
Definition: metadata.php:41
$xml
Definition: metadata.php:351
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc
string $key
Consumer key/client ID value.
Definition: System.php:193
$a
thx to https://mlocati.github.io/php-cs-fixer-configurator for the examples
catch(\Exception $e) $req
Definition: xapiproxy.php:93
$type
$url
$_SERVER['HTTP_HOST']
Definition: raiseError.php:10
$http
Definition: raiseError.php:7
$_GET['client_id']
Definition: saml1-acs.php:21
$param
Definition: xapitoken.php:46
$cols
Definition: xhr_table.php:11
$rows
Definition: xhr_table.php:10

Variable Documentation

◆ globalDebugLevel

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

Definition at line 85 of file nusoap.php.