ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
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
 This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Learning e.V. More...
 

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 929 of file nusoap.php.

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

◆ 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 899 of file nusoap.php.

900{
901 $datestr = date('Y-m-d\TH:i:sO', $timestamp);
902 if ($utc) {
903 $pattern = '/' .
904 '([0-9]{4})-' . // centuries & years CCYY-
905 '([0-9]{2})-' . // months MM-
906 '([0-9]{2})' . // days DD
907 'T' . // separator T
908 '([0-9]{2}):' . // hours hh:
909 '([0-9]{2}):' . // minutes mm:
910 '([0-9]{2})(\.[0-9]*)?' . // seconds ss.ss...
911 '(Z|[+\-][0-9]{2}:?[0-9]{2})?' . // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
912 '/';
913
914 if (preg_match($pattern, $datestr, $regs)) {
915 return sprintf('%04d-%02d-%02dT%02d:%02d:%02dZ', $regs[1], $regs[2], $regs[3], $regs[4], $regs[5], $regs[6]);
916 }
917 return false;
918 } else {
919 return $datestr;
920 }
921}
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 970 of file nusoap.php.

971{
972 $start = gettimeofday();
973
974 do {
975 $stop = gettimeofday();
976 $timePassed = 1000000 * ($stop['sec'] - $start['sec'])
977 + $stop['usec'] - $start['usec'];
978 } while ($timePassed < $usec);
979}
980
981?><?php
982
983
984
993class nusoap_fault extends nusoap_base
994{
1000 public $faultcode;
1006 public $faultactor;
1012 public $faultstring;
1018 public $faultdetail;
1019
1028 public function __construct($faultcode, $faultactor = '', $faultstring = '', $faultdetail = '')
1029 {
1031 $this->faultcode = $faultcode;
1032 $this->faultactor = $faultactor;
1033 $this->faultstring = $faultstring;
1034 $this->faultdetail = $faultdetail;
1035 }
1036
1043 public function serialize()
1044 {
1045 $ns_string = '';
1046 foreach ($this->namespaces as $k => $v) {
1047 $ns_string .= "\n xmlns:$k=\"$v\"";
1048 }
1049 $return_msg =
1050 '<?xml version="1.0" encoding="' . $this->soap_defencoding . '"?>' .
1051 '<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"' . $ns_string . ">\n" .
1052 '<SOAP-ENV:Body>' .
1053 '<SOAP-ENV:Fault>' .
1054 $this->serialize_val($this->faultcode, 'faultcode') .
1055 $this->serialize_val($this->faultstring, 'faultstring') .
1056 $this->serialize_val($this->faultactor, 'faultactor') .
1057 $this->serialize_val($this->faultdetail, 'detail') .
1058 '</SOAP-ENV:Fault>' .
1059 '</SOAP-ENV:Body>' .
1060 '</SOAP-ENV:Envelope>';
1061 return $return_msg;
1062 }
1063}
1064
1068class soap_fault extends nusoap_fault
1069{
1070}
1071
1072?><?php
1073
1074
1075
1085class nusoap_xmlschema extends nusoap_base
1086{
1087 // files
1088 public $schema = '';
1089 public $xml = '';
1090 // namespaces
1091 public $enclosingNamespaces;
1092 // schema info
1093 public $schemaInfo = array();
1094 public $schemaTargetNamespace = '';
1095 // types, elements, attributes defined by the schema
1096 public $attributes = array();
1097 public $complexTypes = array();
1098 public $complexTypeStack = array();
1099 public $currentComplexType = null;
1100 public $elements = array();
1101 public $elementStack = array();
1102 public $currentElement = null;
1103 public $simpleTypes = array();
1104 public $simpleTypeStack = array();
1105 public $currentSimpleType = null;
1106 // imports
1107 public $imports = array();
1108 // parser vars
1109 public $parser;
1110 public $position = 0;
1111 public $depth = 0;
1112 public $depth_array = array();
1113 public $message = array();
1114 public $defaultNamespace = array();
1115
1124 public function __construct($schema = '', $xml = '', $namespaces = array())
1125 {
1127 $this->debug('nusoap_xmlschema class instantiated, inside constructor');
1128 // files
1129 $this->schema = $schema;
1130 $this->xml = $xml;
1131
1132 // namespaces
1133 $this->enclosingNamespaces = $namespaces;
1134 $this->namespaces = array_merge($this->namespaces, $namespaces);
1135
1136 // parse schema file
1137 if ($schema != '') {
1138 $this->debug('initial schema file: ' . $schema);
1139 $this->parseFile($schema, 'schema');
1140 }
1141
1142 // parse xml file
1143 if ($xml != '') {
1144 $this->debug('initial xml file: ' . $xml);
1145 $this->parseFile($xml, 'xml');
1146 }
1147 }
1148
1157 public function parseFile($xml, $type)
1158 {
1159 // parse xml file
1160 if ($xml != "") {
1161 $xmlStr = @join("", @file($xml));
1162 if ($xmlStr == "") {
1163 $msg = 'Error reading XML from ' . $xml;
1164 $this->setError($msg);
1165 $this->debug($msg);
1166 return false;
1167 } else {
1168 $this->debug("parsing $xml");
1169 $this->parseString($xmlStr, $type);
1170 $this->debug("done parsing $xml");
1171 return true;
1172 }
1173 }
1174 return false;
1175 }
1176
1184 public function parseString($xml, $type)
1185 {
1186 // parse xml string
1187 if ($xml != "") {
1188 // Create an XML parser.
1189 $this->parser = xml_parser_create();
1190 // Set the options for parsing the XML data.
1191 xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
1192
1193 // Set the element handlers for the parser.
1194 if ($type == "schema") {
1195 xml_set_element_handler($this->parser, $this->schemaStartElement(...), $this->schemaEndElement(...));
1196 xml_set_character_data_handler($this->parser, $this->schemaCharacterData(...));
1197 } elseif ($type == "xml") {
1198 xml_set_element_handler($this->parser, $this->xmlStartElement(...), $this->xmlEndElement(...));
1199 xml_set_character_data_handler($this->parser, $this->xmlCharacterData(...));
1200 }
1201
1202 // Parse the XML file.
1203 if (!xml_parse($this->parser, $xml, true)) {
1204 // Display an error message.
1205 $errstr = sprintf(
1206 'XML error parsing XML schema on line %d: %s',
1207 xml_get_current_line_number($this->parser),
1208 xml_error_string(xml_get_error_code($this->parser))
1209 );
1210 $this->debug($errstr);
1211 $this->debug("XML payload:\n" . $xml);
1212 $this->setError($errstr);
1213 }
1214
1215 xml_parser_free($this->parser);
1216 } else {
1217 $this->debug('no xml passed to parseString()!!');
1218 $this->setError('no xml passed to parseString()!!');
1219 }
1220 }
1221
1229 public function CreateTypeName($ename)
1230 {
1231 $scope = '';
1232 for ($i = 0; $i < count($this->complexTypeStack); $i++) {
1233 $scope .= $this->complexTypeStack[$i] . '_';
1234 }
1235 return $scope . $ename . '_ContainedType';
1236 }
1237
1246 public function schemaStartElement($parser, $name, $attrs)
1247 {
1248
1249 // position in the total number of elements, starting from 0
1250 $pos = $this->position++;
1251 $depth = $this->depth++;
1252 // set self as current value for this depth
1253 $this->depth_array[$depth] = $pos;
1254 $this->message[$pos] = array('cdata' => '');
1255 if ($depth > 0) {
1256 $this->defaultNamespace[$pos] = $this->defaultNamespace[$this->depth_array[$depth - 1]];
1257 } else {
1258 $this->defaultNamespace[$pos] = false;
1259 }
1260
1261 // get element prefix
1262 if ($prefix = $this->getPrefix($name)) {
1263 // get unqualified name
1264 $name = $this->getLocalPart($name);
1265 } else {
1266 $prefix = '';
1267 }
1268
1269 // loop thru attributes, expanding, and registering namespace declarations
1270 if (count($attrs) > 0) {
1271 foreach ($attrs as $k => $v) {
1272 // if ns declarations, add to class level array of valid namespaces
1273 if (preg_match('/^xmlns/', $k)) {
1274 //$this->xdebug("$k: $v");
1275 //$this->xdebug('ns_prefix: '.$this->getPrefix($k));
1276 if ($ns_prefix = substr(strrchr($k, ':'), 1)) {
1277 //$this->xdebug("Add namespace[$ns_prefix] = $v");
1278 $this->namespaces[$ns_prefix] = $v;
1279 } else {
1280 $this->defaultNamespace[$pos] = $v;
1281 if (! $this->getPrefixFromNamespace($v)) {
1282 $this->namespaces['ns' . (count($this->namespaces) + 1)] = $v;
1283 }
1284 }
1285 if ($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema') {
1286 $this->XMLSchemaVersion = $v;
1287 $this->namespaces['xsi'] = $v . '-instance';
1288 }
1289 }
1290 }
1291 foreach ($attrs as $k => $v) {
1292 // expand each attribute
1293 $k = strpos($k, ':') ? $this->expandQname($k) : $k;
1294 $v = strpos($v, ':') ? $this->expandQname($v) : $v;
1295 $eAttrs[$k] = $v;
1296 }
1297 $attrs = $eAttrs;
1298 } else {
1299 $attrs = array();
1300 }
1301 // find status, register data
1302 switch ($name) {
1303 case 'all': // (optional) compositor content for a complexType
1304 case 'choice':
1305 case 'group':
1306 case 'sequence':
1307 //$this->xdebug("compositor $name for currentComplexType: $this->currentComplexType and currentElement: $this->currentElement");
1308 $this->complexTypes[$this->currentComplexType]['compositor'] = $name;
1309 //if($name == 'all' || $name == 'sequence'){
1310 // $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
1311 //}
1312 break;
1313 case 'attribute': // complexType attribute
1314 //$this->xdebug("parsing attribute $attrs[name] $attrs[ref] of value: ".$attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']);
1315 $this->xdebug("parsing attribute:");
1316 $this->appendDebug($this->varDump($attrs));
1317 if (!isset($attrs['form'])) {
1318 $attrs['form'] = $this->schemaInfo['attributeFormDefault'];
1319 }
1320 if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
1321 $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1322 if (!strpos($v, ':')) {
1323 // no namespace in arrayType attribute value...
1324 if ($this->defaultNamespace[$pos]) {
1325 // ...so use the default
1326 $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'] = $this->defaultNamespace[$pos] . ':' . $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1327 }
1328 }
1329 }
1330 if (isset($attrs['name'])) {
1331 $this->attributes[$attrs['name']] = $attrs;
1332 $aname = $attrs['name'];
1333 } elseif (isset($attrs['ref']) && $attrs['ref'] == 'http://schemas.xmlsoap.org/soap/encoding/:arrayType') {
1334 if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
1335 $aname = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1336 } else {
1337 $aname = '';
1338 }
1339 } elseif (isset($attrs['ref'])) {
1340 $aname = $attrs['ref'];
1341 $this->attributes[$attrs['ref']] = $attrs;
1342 }
1343
1344 if ($this->currentComplexType) { // This should *always* be
1345 $this->complexTypes[$this->currentComplexType]['attrs'][$aname] = $attrs;
1346 }
1347 // arrayType attribute
1348 if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']) || $this->getLocalPart($aname) == 'arrayType') {
1349 $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
1350 $prefix = $this->getPrefix($aname);
1351 if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
1352 $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1353 } else {
1354 $v = '';
1355 }
1356 if (strpos($v, '[,]')) {
1357 $this->complexTypes[$this->currentComplexType]['multidimensional'] = true;
1358 }
1359 $v = substr($v, 0, strpos($v, '[')); // clip the []
1360 if (!strpos($v, ':') && isset($this->typemap[$this->XMLSchemaVersion][$v])) {
1361 $v = $this->XMLSchemaVersion . ':' . $v;
1362 }
1363 $this->complexTypes[$this->currentComplexType]['arrayType'] = $v;
1364 }
1365 break;
1366 case 'complexContent': // (optional) content for a complexType
1367 break;
1368 case 'complexType':
1369 array_push($this->complexTypeStack, $this->currentComplexType);
1370 if (isset($attrs['name'])) {
1371 // TODO: what is the scope of named complexTypes that appear
1372 // nested within other c complexTypes?
1373 $this->xdebug('processing named complexType ' . $attrs['name']);
1374 //$this->currentElement = false;
1375 $this->currentComplexType = $attrs['name'];
1376 $this->complexTypes[$this->currentComplexType] = $attrs;
1377 $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
1378 // This is for constructs like
1379 // <complexType name="ListOfString" base="soap:Array">
1380 // <sequence>
1381 // <element name="string" type="xsd:string"
1382 // minOccurs="0" maxOccurs="unbounded" />
1383 // </sequence>
1384 // </complexType>
1385 if (isset($attrs['base']) && preg_match('/:Array$/', $attrs['base'])) {
1386 $this->xdebug('complexType is unusual array');
1387 $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
1388 } else {
1389 $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
1390 }
1391 } else {
1392 $name = $this->CreateTypeName($this->currentElement);
1393 $this->xdebug('processing unnamed complexType for element ' . $this->currentElement . ' named ' . $name);
1394 $this->currentComplexType = $name;
1395 //$this->currentElement = false;
1396 $this->complexTypes[$this->currentComplexType] = $attrs;
1397 $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
1398 // This is for constructs like
1399 // <complexType name="ListOfString" base="soap:Array">
1400 // <sequence>
1401 // <element name="string" type="xsd:string"
1402 // minOccurs="0" maxOccurs="unbounded" />
1403 // </sequence>
1404 // </complexType>
1405 if (isset($attrs['base']) && preg_match('/:Array$/', $attrs['base'])) {
1406 $this->xdebug('complexType is unusual array');
1407 $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
1408 } else {
1409 $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
1410 }
1411 }
1412 break;
1413 case 'element':
1414 array_push($this->elementStack, $this->currentElement);
1415 if (!isset($attrs['form'])) {
1416 $attrs['form'] = $this->schemaInfo['elementFormDefault'];
1417 }
1418 if (isset($attrs['type'])) {
1419 $this->xdebug("processing typed element " . $attrs['name'] . " of type " . $attrs['type']);
1420 if (! $this->getPrefix($attrs['type'])) {
1421 if ($this->defaultNamespace[$pos]) {
1422 $attrs['type'] = $this->defaultNamespace[$pos] . ':' . $attrs['type'];
1423 $this->xdebug('used default namespace to make type ' . $attrs['type']);
1424 }
1425 }
1426 // This is for constructs like
1427 // <complexType name="ListOfString" base="soap:Array">
1428 // <sequence>
1429 // <element name="string" type="xsd:string"
1430 // minOccurs="0" maxOccurs="unbounded" />
1431 // </sequence>
1432 // </complexType>
1433 if ($this->currentComplexType && $this->complexTypes[$this->currentComplexType]['phpType'] == 'array') {
1434 $this->xdebug('arrayType for unusual array is ' . $attrs['type']);
1435 $this->complexTypes[$this->currentComplexType]['arrayType'] = $attrs['type'];
1436 }
1437 $this->currentElement = $attrs['name'];
1438 $ename = $attrs['name'];
1439 } elseif (isset($attrs['ref'])) {
1440 $this->xdebug("processing element as ref to " . $attrs['ref']);
1441 $this->currentElement = "ref to " . $attrs['ref'];
1442 $ename = $this->getLocalPart($attrs['ref']);
1443 } else {
1444 $type = $this->CreateTypeName($this->currentComplexType . '_' . $attrs['name']);
1445 $this->xdebug("processing untyped element " . $attrs['name'] . ' type ' . $type);
1446 $this->currentElement = $attrs['name'];
1447 $attrs['type'] = $this->schemaTargetNamespace . ':' . $type;
1448 $ename = $attrs['name'];
1449 }
1450 if (isset($ename) && $this->currentComplexType) {
1451 $this->xdebug("add element $ename to complexType $this->currentComplexType");
1452 $this->complexTypes[$this->currentComplexType]['elements'][$ename] = $attrs;
1453 } elseif (!isset($attrs['ref'])) {
1454 $this->xdebug("add element $ename to elements array");
1455 $this->elements[ $attrs['name'] ] = $attrs;
1456 $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
1457 }
1458 break;
1459 case 'enumeration': // restriction value list member
1460 $this->xdebug('enumeration ' . $attrs['value']);
1461 if ($this->currentSimpleType) {
1462 $this->simpleTypes[$this->currentSimpleType]['enumeration'][] = $attrs['value'];
1463 } elseif ($this->currentComplexType) {
1464 $this->complexTypes[$this->currentComplexType]['enumeration'][] = $attrs['value'];
1465 }
1466 break;
1467 case 'extension': // simpleContent or complexContent type extension
1468 $this->xdebug('extension ' . $attrs['base']);
1469 if ($this->currentComplexType) {
1470 $this->complexTypes[$this->currentComplexType]['extensionBase'] = $attrs['base'];
1471 }
1472 break;
1473 case 'import':
1474 if (isset($attrs['schemaLocation'])) {
1475 //$this->xdebug('import namespace ' . $attrs['namespace'] . ' from ' . $attrs['schemaLocation']);
1476 $this->imports[$attrs['namespace']][] = array('location' => $attrs['schemaLocation'], 'loaded' => false);
1477 } else {
1478 //$this->xdebug('import namespace ' . $attrs['namespace']);
1479 $this->imports[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
1480 if (! $this->getPrefixFromNamespace($attrs['namespace'])) {
1481 $this->namespaces['ns' . (count($this->namespaces) + 1)] = $attrs['namespace'];
1482 }
1483 }
1484 break;
1485 case 'list': // simpleType value list
1486 break;
1487 case 'restriction': // simpleType, simpleContent or complexContent value restriction
1488 $this->xdebug('restriction ' . $attrs['base']);
1489 if ($this->currentSimpleType) {
1490 $this->simpleTypes[$this->currentSimpleType]['type'] = $attrs['base'];
1491 } elseif ($this->currentComplexType) {
1492 $this->complexTypes[$this->currentComplexType]['restrictionBase'] = $attrs['base'];
1493 if (strstr($attrs['base'], ':') == ':Array') {
1494 $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
1495 }
1496 }
1497 break;
1498 case 'schema':
1499 $this->schemaInfo = $attrs;
1500 $this->schemaInfo['schemaVersion'] = $this->getNamespaceFromPrefix($prefix);
1501 if (isset($attrs['targetNamespace'])) {
1502 $this->schemaTargetNamespace = $attrs['targetNamespace'];
1503 }
1504 if (!isset($attrs['elementFormDefault'])) {
1505 $this->schemaInfo['elementFormDefault'] = 'unqualified';
1506 }
1507 if (!isset($attrs['attributeFormDefault'])) {
1508 $this->schemaInfo['attributeFormDefault'] = 'unqualified';
1509 }
1510 break;
1511 case 'simpleContent': // (optional) content for a complexType
1512 break;
1513 case 'simpleType':
1514 array_push($this->simpleTypeStack, $this->currentSimpleType);
1515 if (isset($attrs['name'])) {
1516 $this->xdebug("processing simpleType for name " . $attrs['name']);
1517 $this->currentSimpleType = $attrs['name'];
1518 $this->simpleTypes[ $attrs['name'] ] = $attrs;
1519 $this->simpleTypes[ $attrs['name'] ]['typeClass'] = 'simpleType';
1520 $this->simpleTypes[ $attrs['name'] ]['phpType'] = 'scalar';
1521 } else {
1522 $name = $this->CreateTypeName($this->currentComplexType . '_' . $this->currentElement);
1523 $this->xdebug('processing unnamed simpleType for element ' . $this->currentElement . ' named ' . $name);
1524 $this->currentSimpleType = $name;
1525 //$this->currentElement = false;
1526 $this->simpleTypes[$this->currentSimpleType] = $attrs;
1527 $this->simpleTypes[$this->currentSimpleType]['phpType'] = 'scalar';
1528 }
1529 break;
1530 case 'union': // simpleType type list
1531 break;
1532 default:
1533 //$this->xdebug("do not have anything to do for element $name");
1534 }
1535 }
1536
1544 public function schemaEndElement($parser, $name)
1545 {
1546 // bring depth down a notch
1547 $this->depth--;
1548 // position of current element is equal to the last value left in depth_array for my depth
1549 if (isset($this->depth_array[$this->depth])) {
1550 $pos = $this->depth_array[$this->depth];
1551 }
1552 // get element prefix
1553 if ($prefix = $this->getPrefix($name)) {
1554 // get unqualified name
1555 $name = $this->getLocalPart($name);
1556 } else {
1557 $prefix = '';
1558 }
1559 // move on...
1560 if ($name == 'complexType') {
1561 $this->xdebug('done processing complexType ' . ($this->currentComplexType ? $this->currentComplexType : '(unknown)'));
1562 $this->currentComplexType = array_pop($this->complexTypeStack);
1563 //$this->currentElement = false;
1564 }
1565 if ($name == 'element') {
1566 $this->xdebug('done processing element ' . ($this->currentElement ? $this->currentElement : '(unknown)'));
1567 $this->currentElement = array_pop($this->elementStack);
1568 }
1569 if ($name == 'simpleType') {
1570 $this->xdebug('done processing simpleType ' . ($this->currentSimpleType ? $this->currentSimpleType : '(unknown)'));
1571 $this->currentSimpleType = array_pop($this->simpleTypeStack);
1572 }
1573 }
1574
1582 public function schemaCharacterData($parser, $data)
1583 {
1584 $pos = $this->depth_array[$this->depth - 1];
1585 $this->message[$pos]['cdata'] .= $data;
1586 }
1587
1593 public function serializeSchema()
1594 {
1595 $schemaPrefix = $this->getPrefixFromNamespace($this->XMLSchemaVersion);
1596 $xml = '';
1597 // imports
1598 if (sizeof($this->imports) > 0) {
1599 foreach ($this->imports as $ns => $list) {
1600 foreach ($list as $ii) {
1601 if ($ii['location'] != '') {
1602 $xml .= " <$schemaPrefix:import location=\"" . $ii['location'] . '" namespace="' . $ns . "\" />\n";
1603 } else {
1604 $xml .= " <$schemaPrefix:import namespace=\"" . $ns . "\" />\n";
1605 }
1606 }
1607 }
1608 }
1609 // complex types
1610 foreach ($this->complexTypes as $typeName => $attrs) {
1611 $contentStr = '';
1612 // serialize child elements
1613 if (isset($attrs['elements']) && (count($attrs['elements']) > 0)) {
1614 foreach ($attrs['elements'] as $element => $eParts) {
1615 if (isset($eParts['ref'])) {
1616 $contentStr .= " <$schemaPrefix:element ref=\"$element\"/>\n";
1617 } else {
1618 $contentStr .= " <$schemaPrefix:element name=\"$element\" type=\"" . $this->contractQName($eParts['type']) . "\"";
1619 foreach ($eParts as $aName => $aValue) {
1620 // handle, e.g., abstract, default, form, minOccurs, maxOccurs, nillable
1621 if ($aName != 'name' && $aName != 'type') {
1622 $contentStr .= " $aName=\"$aValue\"";
1623 }
1624 }
1625 $contentStr .= "/>\n";
1626 }
1627 }
1628 // compositor wraps elements
1629 if (isset($attrs['compositor']) && ($attrs['compositor'] != '')) {
1630 $contentStr = " <$schemaPrefix:$attrs[compositor]>\n" . $contentStr . " </$schemaPrefix:$attrs[compositor]>\n";
1631 }
1632 }
1633 // attributes
1634 if (isset($attrs['attrs']) && (count($attrs['attrs']) >= 1)) {
1635 foreach ($attrs['attrs'] as $attr => $aParts) {
1636 $contentStr .= " <$schemaPrefix:attribute";
1637 foreach ($aParts as $a => $v) {
1638 if ($a == 'ref' || $a == 'type') {
1639 $contentStr .= " $a=\"" . $this->contractQName($v) . '"';
1640 } elseif ($a == 'http://schemas.xmlsoap.org/wsdl/:arrayType') {
1641 $this->usedNamespaces['wsdl'] = $this->namespaces['wsdl'];
1642 $contentStr .= ' wsdl:arrayType="' . $this->contractQName($v) . '"';
1643 } else {
1644 $contentStr .= " $a=\"$v\"";
1645 }
1646 }
1647 $contentStr .= "/>\n";
1648 }
1649 }
1650 // if restriction
1651 if (isset($attrs['restrictionBase']) && $attrs['restrictionBase'] != '') {
1652 $contentStr = " <$schemaPrefix:restriction base=\"" . $this->contractQName($attrs['restrictionBase']) . "\">\n" . $contentStr . " </$schemaPrefix:restriction>\n";
1653 // complex or simple content
1654 if ((isset($attrs['elements']) && count($attrs['elements']) > 0) || (isset($attrs['attrs']) && count($attrs['attrs']) > 0)) {
1655 $contentStr = " <$schemaPrefix:complexContent>\n" . $contentStr . " </$schemaPrefix:complexContent>\n";
1656 }
1657 }
1658 // finalize complex type
1659 if ($contentStr != '') {
1660 $contentStr = " <$schemaPrefix:complexType name=\"$typeName\">\n" . $contentStr . " </$schemaPrefix:complexType>\n";
1661 } else {
1662 $contentStr = " <$schemaPrefix:complexType name=\"$typeName\"/>\n";
1663 }
1664 $xml .= $contentStr;
1665 }
1666 // simple types
1667 if (isset($this->simpleTypes) && count($this->simpleTypes) > 0) {
1668 foreach ($this->simpleTypes as $typeName => $eParts) {
1669 $xml .= " <$schemaPrefix:simpleType name=\"$typeName\">\n <$schemaPrefix:restriction base=\"" . $this->contractQName($eParts['type']) . "\">\n";
1670 if (isset($eParts['enumeration'])) {
1671 foreach ($eParts['enumeration'] as $e) {
1672 $xml .= " <$schemaPrefix:enumeration value=\"$e\"/>\n";
1673 }
1674 }
1675 $xml .= " </$schemaPrefix:restriction>\n </$schemaPrefix:simpleType>";
1676 }
1677 }
1678 // elements
1679 if (isset($this->elements) && count($this->elements) > 0) {
1680 foreach ($this->elements as $element => $eParts) {
1681 $xml .= " <$schemaPrefix:element name=\"$element\" type=\"" . $this->contractQName($eParts['type']) . "\"/>\n";
1682 }
1683 }
1684 // attributes
1685 if (isset($this->attributes) && count($this->attributes) > 0) {
1686 foreach ($this->attributes as $attr => $aParts) {
1687 $xml .= " <$schemaPrefix:attribute name=\"$attr\" type=\"" . $this->contractQName($aParts['type']) . "\"\n/>";
1688 }
1689 }
1690 // finish 'er up
1691 $attr = '';
1692 foreach ($this->schemaInfo as $k => $v) {
1693 if ($k == 'elementFormDefault' || $k == 'attributeFormDefault') {
1694 $attr .= " $k=\"$v\"";
1695 }
1696 }
1697 $el = "<$schemaPrefix:schema$attr targetNamespace=\"$this->schemaTargetNamespace\"\n";
1698 foreach (array_diff($this->usedNamespaces, $this->enclosingNamespaces) as $nsp => $ns) {
1699 $el .= " xmlns:$nsp=\"$ns\"";
1700 }
1701 $xml = $el . ">\n" . $xml . "</$schemaPrefix:schema>\n";
1702 return $xml;
1703 }
1704
1711 public function xdebug($string)
1712 {
1713 $this->debug('<' . $this->schemaTargetNamespace . '> ' . $string);
1714 }
1715
1728 public function getPHPType($type, $ns)
1729 {
1730 if (isset($this->typemap[$ns][$type])) {
1731 //print "found type '$type' and ns $ns in typemap<br>";
1732 return $this->typemap[$ns][$type];
1733 } elseif (isset($this->complexTypes[$type])) {
1734 //print "getting type '$type' and ns $ns from complexTypes array<br>";
1735 return $this->complexTypes[$type]['phpType'];
1736 }
1737 return false;
1738 }
1739
1762 public function getTypeDef($type)
1763 {
1764 //$this->debug("in getTypeDef for type $type");
1765 if (substr($type, -1) == '^') {
1766 $is_element = 1;
1767 $type = substr($type, 0, -1);
1768 } else {
1769 $is_element = 0;
1770 }
1771
1772 if ((! $is_element) && isset($this->complexTypes[$type])) {
1773 $this->xdebug("in getTypeDef, found complexType $type");
1774 return $this->complexTypes[$type];
1775 } elseif ((! $is_element) && isset($this->simpleTypes[$type])) {
1776 $this->xdebug("in getTypeDef, found simpleType $type");
1777 if (!isset($this->simpleTypes[$type]['phpType'])) {
1778 // get info for type to tack onto the simple type
1779 // TODO: can this ever really apply (i.e. what is a simpleType really?)
1780 $uqType = substr($this->simpleTypes[$type]['type'], strrpos($this->simpleTypes[$type]['type'], ':') + 1);
1781 $ns = substr($this->simpleTypes[$type]['type'], 0, strrpos($this->simpleTypes[$type]['type'], ':'));
1782 $etype = $this->getTypeDef($uqType);
1783 if ($etype) {
1784 $this->xdebug("in getTypeDef, found type for simpleType $type:");
1785 $this->xdebug($this->varDump($etype));
1786 if (isset($etype['phpType'])) {
1787 $this->simpleTypes[$type]['phpType'] = $etype['phpType'];
1788 }
1789 if (isset($etype['elements'])) {
1790 $this->simpleTypes[$type]['elements'] = $etype['elements'];
1791 }
1792 }
1793 }
1794 return $this->simpleTypes[$type];
1795 } elseif (isset($this->elements[$type])) {
1796 $this->xdebug("in getTypeDef, found element $type");
1797 if (!isset($this->elements[$type]['phpType'])) {
1798 // get info for type to tack onto the element
1799 $uqType = substr($this->elements[$type]['type'], strrpos($this->elements[$type]['type'], ':') + 1);
1800 $ns = substr($this->elements[$type]['type'], 0, strrpos($this->elements[$type]['type'], ':'));
1801 $etype = $this->getTypeDef($uqType);
1802 if ($etype) {
1803 $this->xdebug("in getTypeDef, found type for element $type:");
1804 $this->xdebug($this->varDump($etype));
1805 if (isset($etype['phpType'])) {
1806 $this->elements[$type]['phpType'] = $etype['phpType'];
1807 }
1808 if (isset($etype['elements'])) {
1809 $this->elements[$type]['elements'] = $etype['elements'];
1810 }
1811 } elseif ($ns == 'http://www.w3.org/2001/XMLSchema') {
1812 $this->xdebug("in getTypeDef, element $type is an XSD type");
1813 $this->elements[$type]['phpType'] = 'scalar';
1814 }
1815 }
1816 return $this->elements[$type];
1817 } elseif (isset($this->attributes[$type])) {
1818 $this->xdebug("in getTypeDef, found attribute $type");
1819 return $this->attributes[$type];
1820 } elseif (preg_match('/_ContainedType$/', $type)) {
1821 $this->xdebug("in getTypeDef, have an untyped element $type");
1822 $typeDef['typeClass'] = 'simpleType';
1823 $typeDef['phpType'] = 'scalar';
1824 $typeDef['type'] = 'http://www.w3.org/2001/XMLSchema:string';
1825 return $typeDef;
1826 }
1827 $this->xdebug("in getTypeDef, did not find $type");
1828 return false;
1829 }
1830
1839 public function serializeTypeDef($type)
1840 {
1841 //print "in sTD() for type $type<br>";
1842 if ($typeDef = $this->getTypeDef($type)) {
1843 $str .= '<' . $type;
1844 if (is_array($typeDef['attrs'])) {
1845 foreach ($typeDef['attrs'] as $attName => $data) {
1846 $str .= " $attName=\"{type = " . $data['type'] . "}\"";
1847 }
1848 }
1849 $str .= " xmlns=\"" . $this->schema['targetNamespace'] . "\"";
1850 if (count($typeDef['elements']) > 0) {
1851 $str .= ">";
1852 foreach ($typeDef['elements'] as $element => $eData) {
1853 $str .= $this->serializeTypeDef($element);
1854 }
1855 $str .= "</$type>";
1856 } elseif ($typeDef['typeClass'] == 'element') {
1857 $str .= "></$type>";
1858 } else {
1859 $str .= "/>";
1860 }
1861 return $str;
1862 }
1863 return false;
1864 }
1865
1876 public function typeToForm($name, $type)
1877 {
1878 // get typedef
1879 if ($typeDef = $this->getTypeDef($type)) {
1880 // if struct
1881 if ($typeDef['phpType'] == 'struct') {
1882 $buffer .= '<table>';
1883 foreach ($typeDef['elements'] as $child => $childDef) {
1884 $buffer .= "
1885 <tr><td align='right'>$childDef[name] (type: " . $this->getLocalPart($childDef['type']) . "):</td>
1886 <td><input type='text' name='parameters[" . $name . "][$childDef[name]]'></td></tr>";
1887 }
1888 $buffer .= '</table>';
1889 // if array
1890 } elseif ($typeDef['phpType'] == 'array') {
1891 $buffer .= '<table>';
1892 for ($i = 0;$i < 3; $i++) {
1893 $buffer .= "
1894 <tr><td align='right'>array item (type: $typeDef[arrayType]):</td>
1895 <td><input type='text' name='parameters[" . $name . "][]'></td></tr>";
1896 }
1897 $buffer .= '</table>';
1898 // if scalar
1899 } else {
1900 $buffer .= "<input type='text' name='parameters[$name]'>";
1901 }
1902 } else {
1903 $buffer .= "<input type='text' name='parameters[$name]'>";
1904 }
1905 return $buffer;
1906 }
1907
1949 public function addComplexType($name, $typeClass = 'complexType', $phpType = 'array', $compositor = '', $restrictionBase = '', $elements = array(), $attrs = array(), $arrayType = '')
1950 {
1951 $this->complexTypes[$name] = array(
1952 'name' => $name,
1953 'typeClass' => $typeClass,
1954 'phpType' => $phpType,
1955 'compositor' => $compositor,
1956 'restrictionBase' => $restrictionBase,
1957 'elements' => $elements,
1958 'attrs' => $attrs,
1959 'arrayType' => $arrayType
1960 );
1961
1962 $this->xdebug("addComplexType $name:");
1963 $this->appendDebug($this->varDump($this->complexTypes[$name]));
1964 }
1965
1978 public function addSimpleType($name, $restrictionBase = '', $typeClass = 'simpleType', $phpType = 'scalar', $enumeration = array())
1979 {
1980 $this->simpleTypes[$name] = array(
1981 'name' => $name,
1982 'typeClass' => $typeClass,
1983 'phpType' => $phpType,
1984 'type' => $restrictionBase,
1985 'enumeration' => $enumeration
1986 );
1987
1988 $this->xdebug("addSimpleType $name:");
1989 $this->appendDebug($this->varDump($this->simpleTypes[$name]));
1990 }
1991
1999 public function addElement($attrs)
2000 {
2001 if (! $this->getPrefix($attrs['type'])) {
2002 $attrs['type'] = $this->schemaTargetNamespace . ':' . $attrs['type'];
2003 }
2004 $this->elements[ $attrs['name'] ] = $attrs;
2005 $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
2006
2007 $this->xdebug("addElement " . $attrs['name']);
2008 $this->appendDebug($this->varDump($this->elements[ $attrs['name'] ]));
2009 }
2010}
2011
2015class XMLSchema extends nusoap_xmlschema
2016{
2017}
2018
2019?><?php
2020
2021
2022
2034class soapval extends nusoap_base
2035{
2042 public $name;
2049 public $type;
2056 public $value;
2063 public $element_ns;
2070 public $type_ns;
2077 public $attributes;
2078
2090 public function __construct($name = 'soapval', $type = false, $value = -1, $element_ns = false, $type_ns = false, $attributes = false)
2091 {
2093 $this->name = $name;
2094 $this->type = $type;
2095 $this->value = $value;
2096 $this->element_ns = $element_ns;
2097 $this->type_ns = $type_ns;
2098 $this->attributes = $attributes;
2099 }
2100
2108 public function serialize($use = 'encoded')
2109 {
2110 return $this->serialize_val($this->value, $this->name, $this->type, $this->element_ns, $this->type_ns, $this->attributes, $use, true);
2111 }
2112
2119 public function decode()
2120 {
2121 return $this->value;
2122 }
2123}
2124
2125
2126
2127?><?php
2128
2129
2130
2140class soap_transport_http extends nusoap_base
2141{
2142 public $fp;
2143 public $tryagain;
2144 public $url = '';
2145 public $uri = '';
2146 public $digest_uri = '';
2147 public $scheme = '';
2148 public $host = '';
2149 public $port = '';
2150 public $path = '';
2151 public $request_method = 'POST';
2152 public $protocol_version = '1.0';
2153 public $encoding = '';
2154 public $outgoing_headers = array();
2155 public $incoming_headers = array();
2156 public $incoming_cookies = array();
2157 public $outgoing_payload = '';
2158 public $incoming_payload = '';
2159 public $response_status_line; // HTTP response status line
2160 public $useSOAPAction = true;
2161 public $persistentConnection = false;
2162 public $ch = false; // cURL handle
2163 public $ch_options = array(); // cURL custom options
2164 public $use_curl = false; // force cURL use
2165 public $proxy = null; // proxy information (associative array)
2166 public $username = '';
2167 public $password = '';
2168 public $authtype = '';
2169 public $digestRequest = array();
2170 public $certRequest = array(); // keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional)
2171 // cainfofile: certificate authority file, e.g. '$pathToPemFiles/rootca.pem'
2172 // sslcertfile: SSL certificate file, e.g. '$pathToPemFiles/mycert.pem'
2173 // sslkeyfile: SSL key file, e.g. '$pathToPemFiles/mykey.pem'
2174 // passphrase: SSL key password/passphrase
2175 // certpassword: SSL certificate password
2176 // verifypeer: default is 1
2177 // verifyhost: default is 1
2178
2187 public function __construct($url, $curl_options = null, $use_curl = false)
2188 {
2190 $this->debug("ctor url=$url use_curl=$use_curl curl_options:");
2191 $this->appendDebug($this->varDump($curl_options));
2192 $this->setURL($url);
2193 if (is_array($curl_options)) {
2194 $this->ch_options = $curl_options;
2195 }
2196 $this->use_curl = $use_curl;
2197 preg_match('/\$Revisio' . 'n: ([^ ]+)/', $this->revision, $rev);
2198 // begin-patch php8
2199 $this->setHeader('User-Agent', $this->title . '/' . $this->version . ' (' . ($rev[1] ?? '1.1') . ')');
2200 }
2201
2209 public function setCurlOption($option, $value)
2210 {
2211 $this->debug("setCurlOption option=$option, value=");
2212 $this->appendDebug($this->varDump($value));
2213 curl_setopt($this->ch, $option, $value);
2214 }
2215
2223 public function setHeader($name, $value)
2224 {
2225 $this->outgoing_headers[$name] = $value;
2226 $this->debug("set header $name: $value");
2227 }
2228
2235 public function unsetHeader($name)
2236 {
2237 if (isset($this->outgoing_headers[$name])) {
2238 $this->debug("unset header $name");
2239 unset($this->outgoing_headers[$name]);
2240 }
2241 }
2242
2249 public function setURL($url)
2250 {
2251 $this->url = $url;
2252
2253 $u = parse_url($url);
2254 foreach ($u as $k => $v) {
2255 $this->debug("parsed URL $k = $v");
2256 $this->$k = $v;
2257 }
2258
2259 // add any GET params to path
2260 if (isset($u['query']) && $u['query'] != '') {
2261 $this->path .= '?' . $u['query'];
2262 }
2263
2264 // set default port
2265 if (!isset($u['port'])) {
2266 if ($u['scheme'] == 'https') {
2267 $this->port = 443;
2268 } else {
2269 $this->port = 80;
2270 }
2271 }
2272
2273 $this->uri = $this->path;
2274 $this->digest_uri = $this->uri;
2275
2276 // build headers
2277 if (!isset($u['port'])) {
2278 $this->setHeader('Host', $this->host);
2279 } else {
2280 $this->setHeader('Host', $this->host . ':' . $this->port);
2281 }
2282
2283 if (isset($u['user']) && $u['user'] != '') {
2284 $this->setCredentials(urldecode($u['user']), isset($u['pass']) ? urldecode($u['pass']) : '');
2285 }
2286 }
2287
2294 public function io_method()
2295 {
2296 if ($this->use_curl || ($this->scheme == 'https') || ($this->scheme == 'http' && $this->authtype == 'ntlm') || ($this->scheme == 'http' && is_array($this->proxy) && $this->proxy['authtype'] == 'ntlm')) {
2297 return 'curl';
2298 }
2299 if (($this->scheme == 'http' || $this->scheme == 'ssl') && $this->authtype != 'ntlm' && (!is_array($this->proxy) || $this->proxy['authtype'] != 'ntlm')) {
2300 return 'socket';
2301 }
2302 return 'unknown';
2303 }
2304
2313 public function connect($connection_timeout = 0, $response_timeout = 30)
2314 {
2315 // For PHP 4.3 with OpenSSL, change https scheme to ssl, then treat like
2316 // "regular" socket.
2317 // TODO: disabled for now because OpenSSL must be *compiled* in (not just
2318 // loaded), and until PHP5 stream_get_wrappers is not available.
2319 // if ($this->scheme == 'https') {
2320 // if (version_compare(phpversion(), '4.3.0') >= 0) {
2321 // if (extension_loaded('openssl')) {
2322 // $this->scheme = 'ssl';
2323 // $this->debug('Using SSL over OpenSSL');
2324 // }
2325 // }
2326 // }
2327 $this->debug("connect connection_timeout $connection_timeout, response_timeout $response_timeout, scheme $this->scheme, host $this->host, port $this->port");
2328 if ($this->io_method() == 'socket') {
2329 if (!is_array($this->proxy)) {
2332 } else {
2333 $host = $this->proxy['host'];
2334 $port = $this->proxy['port'];
2335 }
2336
2337 // use persistent connection
2338 if ($this->persistentConnection && isset($this->fp) && is_resource($this->fp)) {
2339 if (!feof($this->fp)) {
2340 $this->debug('Re-use persistent connection');
2341 return true;
2342 }
2343 fclose($this->fp);
2344 $this->debug('Closed persistent connection at EOF');
2345 }
2346
2347 // munge host if using OpenSSL
2348 if ($this->scheme == 'ssl') {
2349 $host = 'ssl://' . $host;
2350 }
2351 $this->debug('calling fsockopen with host ' . $host . ' connection_timeout ' . $connection_timeout);
2352
2353 // open socket
2354 if ($connection_timeout > 0) {
2355 $this->fp = @fsockopen($host, $this->port, $this->errno, $this->error_str, $connection_timeout);
2356 } else {
2357 $this->fp = @fsockopen($host, $this->port, $this->errno, $this->error_str);
2358 }
2359
2360 // test pointer
2361 if (!$this->fp) {
2362 $msg = 'Couldn\'t open socket connection to server ' . $this->url;
2363 if ($this->errno) {
2364 $msg .= ', Error (' . $this->errno . '): ' . $this->error_str;
2365 } else {
2366 $msg .= ' prior to connect(). This is often a problem looking up the host name.';
2367 }
2368 $this->debug($msg);
2369 $this->setError($msg);
2370 return false;
2371 }
2372
2373 // set response timeout
2374 $this->debug('set response timeout to ' . $response_timeout);
2375 socket_set_timeout($this->fp, $response_timeout);
2376
2377 $this->debug('socket connected');
2378 return true;
2379 } elseif ($this->io_method() == 'curl') {
2380 if (!extension_loaded('curl')) {
2381 // $this->setError('cURL Extension, or OpenSSL extension w/ PHP version >= 4.3 is required for HTTPS');
2382 $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.');
2383 return false;
2384 }
2385 // Avoid warnings when PHP does not have these options
2386 if (defined('CURLOPT_CONNECTIONTIMEOUT')) {
2387 $CURLOPT_CONNECTIONTIMEOUT = CURLOPT_CONNECTIONTIMEOUT;
2388 } else {
2389 $CURLOPT_CONNECTIONTIMEOUT = 78;
2390 }
2391 if (defined('CURLOPT_HTTPAUTH')) {
2392 $CURLOPT_HTTPAUTH = CURLOPT_HTTPAUTH;
2393 } else {
2394 $CURLOPT_HTTPAUTH = 107;
2395 }
2396 if (defined('CURLOPT_PROXYAUTH')) {
2397 $CURLOPT_PROXYAUTH = CURLOPT_PROXYAUTH;
2398 } else {
2399 $CURLOPT_PROXYAUTH = 111;
2400 }
2401 if (defined('CURLAUTH_BASIC')) {
2402 $CURLAUTH_BASIC = CURLAUTH_BASIC;
2403 } else {
2404 $CURLAUTH_BASIC = 1;
2405 }
2406 if (defined('CURLAUTH_DIGEST')) {
2407 $CURLAUTH_DIGEST = CURLAUTH_DIGEST;
2408 } else {
2409 $CURLAUTH_DIGEST = 2;
2410 }
2411 if (defined('CURLAUTH_NTLM')) {
2412 $CURLAUTH_NTLM = CURLAUTH_NTLM;
2413 } else {
2414 $CURLAUTH_NTLM = 8;
2415 }
2416
2417 $this->debug('connect using cURL');
2418 // init CURL
2419 $this->ch = curl_init();
2420 // set url
2421 $hostURL = ($this->port != '') ? "$this->scheme://$this->host:$this->port" : "$this->scheme://$this->host";
2422 // add path
2423 $hostURL .= $this->path;
2424 $this->setCurlOption(CURLOPT_URL, $hostURL);
2425 // follow location headers (re-directs)
2426 if (ini_get('safe_mode') || ini_get('open_basedir')) {
2427 $this->debug('safe_mode or open_basedir set, so do not set CURLOPT_FOLLOWLOCATION');
2428 $this->debug('safe_mode = ');
2429 $this->appendDebug($this->varDump(ini_get('safe_mode')));
2430 $this->debug('open_basedir = ');
2431 $this->appendDebug($this->varDump(ini_get('open_basedir')));
2432 } else {
2433 $this->setCurlOption(CURLOPT_FOLLOWLOCATION, 1);
2434 }
2435 // ask for headers in the response output
2436 $this->setCurlOption(CURLOPT_HEADER, 1);
2437 // ask for the response output as the return value
2438 $this->setCurlOption(CURLOPT_RETURNTRANSFER, 1);
2439 // encode
2440 // We manage this ourselves through headers and encoding
2441 // if(function_exists('gzuncompress')){
2442 // $this->setCurlOption(CURLOPT_ENCODING, 'deflate');
2443 // }
2444 // persistent connection
2445 if ($this->persistentConnection) {
2446 // I believe the following comment is now bogus, having applied to
2447 // the code when it used CURLOPT_CUSTOMREQUEST to send the request.
2448 // The way we send data, we cannot use persistent connections, since
2449 // there will be some "junk" at the end of our request.
2450 //$this->setCurlOption(CURL_HTTP_VERSION_1_1, true);
2451 $this->persistentConnection = false;
2452 $this->setHeader('Connection', 'close');
2453 }
2454 // set timeouts
2455 if ($connection_timeout != 0) {
2456 $this->setCurlOption($CURLOPT_CONNECTIONTIMEOUT, $connection_timeout);
2457 }
2458 if ($response_timeout != 0) {
2459 $this->setCurlOption(CURLOPT_TIMEOUT, $response_timeout);
2460 }
2461
2462 if ($this->scheme == 'https') {
2463 $this->debug('set cURL SSL verify options');
2464 // recent versions of cURL turn on peer/host checking by default,
2465 // while PHP binaries are not compiled with a default location for the
2466 // CA cert bundle, so disable peer/host checking.
2467 //$this->setCurlOption(CURLOPT_CAINFO, 'f:\php-4.3.2-win32\extensions\curl-ca-bundle.crt');
2468 $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 0);
2469 $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 0);
2470
2471 // support client certificates (thanks Tobias Boes, Doug Anarino, Eryan Ariobowo)
2472 if ($this->authtype == 'certificate') {
2473 $this->debug('set cURL certificate options');
2474 if (isset($this->certRequest['cainfofile'])) {
2475 $this->setCurlOption(CURLOPT_CAINFO, $this->certRequest['cainfofile']);
2476 }
2477 if (isset($this->certRequest['verifypeer'])) {
2478 $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, $this->certRequest['verifypeer']);
2479 } else {
2480 $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 1);
2481 }
2482 if (isset($this->certRequest['verifyhost'])) {
2483 $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, $this->certRequest['verifyhost']);
2484 } else {
2485 $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 1);
2486 }
2487 if (isset($this->certRequest['sslcertfile'])) {
2488 $this->setCurlOption(CURLOPT_SSLCERT, $this->certRequest['sslcertfile']);
2489 }
2490 if (isset($this->certRequest['sslkeyfile'])) {
2491 $this->setCurlOption(CURLOPT_SSLKEY, $this->certRequest['sslkeyfile']);
2492 }
2493 if (isset($this->certRequest['passphrase'])) {
2494 $this->setCurlOption(CURLOPT_SSLKEYPASSWD, $this->certRequest['passphrase']);
2495 }
2496 if (isset($this->certRequest['certpassword'])) {
2497 $this->setCurlOption(CURLOPT_SSLCERTPASSWD, $this->certRequest['certpassword']);
2498 }
2499 }
2500 }
2501 if ($this->authtype && ($this->authtype != 'certificate')) {
2502 if ($this->username) {
2503 $this->debug('set cURL username/password');
2504 $this->setCurlOption(CURLOPT_USERPWD, "$this->username:$this->password");
2505 }
2506 if ($this->authtype == 'basic') {
2507 $this->debug('set cURL for Basic authentication');
2508 $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_BASIC);
2509 }
2510 if ($this->authtype == 'digest') {
2511 $this->debug('set cURL for digest authentication');
2512 $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_DIGEST);
2513 }
2514 if ($this->authtype == 'ntlm') {
2515 $this->debug('set cURL for NTLM authentication');
2516 $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_NTLM);
2517 }
2518 }
2519 if (is_array($this->proxy)) {
2520 $this->debug('set cURL proxy options');
2521 if ($this->proxy['port'] != '') {
2522 $this->setCurlOption(CURLOPT_PROXY, $this->proxy['host'] . ':' . $this->proxy['port']);
2523 } else {
2524 $this->setCurlOption(CURLOPT_PROXY, $this->proxy['host']);
2525 }
2526 if ($this->proxy['username'] || $this->proxy['password']) {
2527 $this->debug('set cURL proxy authentication options');
2528 $this->setCurlOption(CURLOPT_PROXYUSERPWD, $this->proxy['username'] . ':' . $this->proxy['password']);
2529 if ($this->proxy['authtype'] == 'basic') {
2530 $this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_BASIC);
2531 }
2532 if ($this->proxy['authtype'] == 'ntlm') {
2533 $this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_NTLM);
2534 }
2535 }
2536 }
2537 $this->debug('cURL connection set up');
2538 return true;
2539 } else {
2540 $this->setError('Unknown scheme ' . $this->scheme);
2541 $this->debug('Unknown scheme ' . $this->scheme);
2542 return false;
2543 }
2544 }
2545
2556 public function send($data, $timeout = 0, $response_timeout = 30, $cookies = null)
2557 {
2558 $this->debug('entered send() with data of length: ' . strlen($data));
2559
2560 $this->tryagain = true;
2561 $tries = 0;
2562 while ($this->tryagain) {
2563 $this->tryagain = false;
2564 if ($tries++ < 2) {
2565 // make connnection
2566 if (!$this->connect($timeout, $response_timeout)) {
2567 return false;
2568 }
2569
2570 // send request
2571 if (!$this->sendRequest($data, $cookies)) {
2572 return false;
2573 }
2574
2575 // get response
2576 $respdata = $this->getResponse();
2577 } else {
2578 $this->setError("Too many tries to get an OK response ($this->response_status_line)");
2579 }
2580 }
2581 $this->debug('end of send()');
2582 return $respdata;
2583 }
2584
2585
2597 public function sendHTTPS($data, $timeout = 0, $response_timeout = 30, $cookies = null)
2598 {
2599 return $this->send($data, $timeout, $response_timeout, $cookies);
2600 }
2601
2612 public function setCredentials($username, $password, $authtype = 'basic', $digestRequest = array(), $certRequest = array())
2613 {
2614 $this->debug("setCredentials username=$username authtype=$authtype digestRequest=");
2615 $this->appendDebug($this->varDump($digestRequest));
2616 $this->debug("certRequest=");
2617 $this->appendDebug($this->varDump($certRequest));
2618 // cf. RFC 2617
2619 if ($authtype == 'basic') {
2620 $this->setHeader('Authorization', 'Basic ' . base64_encode(str_replace(':', '', $username) . ':' . $password));
2621 } elseif ($authtype == 'digest') {
2622 if (isset($digestRequest['nonce'])) {
2623 $digestRequest['nc'] = isset($digestRequest['nc']) ? $digestRequest['nc']++ : 1;
2624
2625 // calculate the Digest hashes (calculate code based on digest implementation found at: http://www.rassoc.com/gregr/weblog/stories/2002/07/09/webServicesSecurityHttpDigestAuthenticationWithoutActiveDirectory.html)
2626
2627 // A1 = unq(username-value) ":" unq(realm-value) ":" passwd
2628 $A1 = $username . ':' . (isset($digestRequest['realm']) ? $digestRequest['realm'] : '') . ':' . $password;
2629
2630 // H(A1) = MD5(A1)
2631 $HA1 = md5($A1);
2632
2633 // A2 = Method ":" digest-uri-value
2634 $A2 = $this->request_method . ':' . $this->digest_uri;
2635
2636 // H(A2)
2637 $HA2 = md5($A2);
2638
2639 // KD(secret, data) = H(concat(secret, ":", data))
2640 // if qop == auth:
2641 // request-digest = <"> < KD ( H(A1), unq(nonce-value)
2642 // ":" nc-value
2643 // ":" unq(cnonce-value)
2644 // ":" unq(qop-value)
2645 // ":" H(A2)
2646 // ) <">
2647 // if qop is missing,
2648 // request-digest = <"> < KD ( H(A1), unq(nonce-value) ":" H(A2) ) > <">
2649
2650 $unhashedDigest = '';
2651 $nonce = isset($digestRequest['nonce']) ? $digestRequest['nonce'] : '';
2652 $cnonce = $nonce;
2653 if ($digestRequest['qop'] != '') {
2654 $unhashedDigest = $HA1 . ':' . $nonce . ':' . sprintf("%08d", $digestRequest['nc']) . ':' . $cnonce . ':' . $digestRequest['qop'] . ':' . $HA2;
2655 } else {
2656 $unhashedDigest = $HA1 . ':' . $nonce . ':' . $HA2;
2657 }
2658
2659 $hashedDigest = md5($unhashedDigest);
2660
2661 $opaque = '';
2662 if (isset($digestRequest['opaque'])) {
2663 $opaque = ', opaque="' . $digestRequest['opaque'] . '"';
2664 }
2665
2666 $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 . '"');
2667 }
2668 } elseif ($authtype == 'certificate') {
2669 $this->certRequest = $certRequest;
2670 $this->debug('Authorization header not set for certificate');
2671 } elseif ($authtype == 'ntlm') {
2672 // do nothing
2673 $this->debug('Authorization header not set for ntlm');
2674 }
2675 $this->username = $username;
2676 $this->password = $password;
2677 $this->authtype = $authtype;
2678 $this->digestRequest = $digestRequest;
2679 }
2680
2687 public function setSOAPAction($soapaction)
2688 {
2689 $this->setHeader('SOAPAction', '"' . $soapaction . '"');
2690 }
2691
2698 public function setEncoding($enc = 'gzip, deflate')
2699 {
2700 if (function_exists('gzdeflate')) {
2701 $this->protocol_version = '1.1';
2702 $this->setHeader('Accept-Encoding', $enc);
2703 if (!isset($this->outgoing_headers['Connection'])) {
2704 $this->setHeader('Connection', 'close');
2705 $this->persistentConnection = false;
2706 }
2707 #set_magic_quotes_runtime(0);
2708 // deprecated
2709 $this->encoding = $enc;
2710 }
2711 }
2712
2723 public function setProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '', $proxyauthtype = 'basic')
2724 {
2725 if ($proxyhost) {
2726 $this->proxy = array(
2727 'host' => $proxyhost,
2728 'port' => $proxyport,
2729 'username' => $proxyusername,
2730 'password' => $proxypassword,
2731 'authtype' => $proxyauthtype
2732 );
2733 if ($proxyusername != '' && $proxypassword != '' && $proxyauthtype = 'basic') {
2734 $this->setHeader('Proxy-Authorization', ' Basic ' . base64_encode($proxyusername . ':' . $proxypassword));
2735 }
2736 } else {
2737 $this->debug('remove proxy');
2738 $proxy = null;
2739 unsetHeader('Proxy-Authorization');
2740 }
2741 }
2742
2743
2752 public function isSkippableCurlHeader(&$data)
2753 {
2754 $skipHeaders = array( 'HTTP/1.1 100',
2755 'HTTP/1.0 301',
2756 'HTTP/1.1 301',
2757 'HTTP/1.0 302',
2758 'HTTP/1.1 302',
2759 'HTTP/1.0 401',
2760 'HTTP/1.1 401',
2761 'HTTP/1.0 200 Connection established');
2762 foreach ($skipHeaders as $hd) {
2763 $prefix = substr($data, 0, strlen($hd));
2764 if ($prefix == $hd) {
2765 return true;
2766 }
2767 }
2768
2769 return false;
2770 }
2771
2782 public function decodeChunked($buffer, $lb)
2783 {
2784 // length := 0
2785 $length = 0;
2786 $new = '';
2787
2788 // read chunk-size, chunk-extension (if any) and CRLF
2789 // get the position of the linebreak
2790 $chunkend = strpos($buffer, $lb);
2791 if ($chunkend == false) {
2792 $this->debug('no linebreak found in decodeChunked');
2793 return $new;
2794 }
2795 $temp = substr($buffer, 0, $chunkend);
2796 $chunk_size = hexdec(trim($temp));
2797 $chunkstart = $chunkend + strlen($lb);
2798 // while (chunk-size > 0) {
2799 while ($chunk_size > 0) {
2800 $this->debug("chunkstart: $chunkstart chunk_size: $chunk_size");
2801 $chunkend = strpos($buffer, $lb, $chunkstart + $chunk_size);
2802
2803 // Just in case we got a broken connection
2804 if ($chunkend == false) {
2805 $chunk = substr($buffer, $chunkstart);
2806 // append chunk-data to entity-body
2807 $new .= $chunk;
2808 $length += strlen($chunk);
2809 break;
2810 }
2811
2812 // read chunk-data and CRLF
2813 $chunk = substr($buffer, $chunkstart, $chunkend - $chunkstart);
2814 // append chunk-data to entity-body
2815 $new .= $chunk;
2816 // length := length + chunk-size
2817 $length += strlen($chunk);
2818 // read chunk-size and CRLF
2819 $chunkstart = $chunkend + strlen($lb);
2820
2821 $chunkend = strpos($buffer, $lb, $chunkstart) + strlen($lb);
2822 if ($chunkend == false) {
2823 break; //Just in case we got a broken connection
2824 }
2825 $temp = substr($buffer, $chunkstart, $chunkend - $chunkstart);
2826 $chunk_size = hexdec(trim($temp));
2827 $chunkstart = $chunkend;
2828 }
2829 return $new;
2830 }
2831
2840 public function buildPayload($data, $cookie_str = '')
2841 {
2842 // Note: for cURL connections, $this->outgoing_payload is ignored,
2843 // as is the Content-Length header, but these are still created as
2844 // debugging guides.
2845
2846 // add content-length header
2847 $this->setHeader('Content-Length', strlen($data));
2848
2849 // start building outgoing payload:
2850 if ($this->proxy) {
2851 $uri = $this->url;
2852 } else {
2853 $uri = $this->uri;
2854 }
2855 $req = "$this->request_method $uri HTTP/$this->protocol_version";
2856 $this->debug("HTTP request: $req");
2857 $this->outgoing_payload = "$req\r\n";
2858
2859 // loop thru headers, serializing
2860 foreach ($this->outgoing_headers as $k => $v) {
2861 $hdr = $k . ': ' . $v;
2862 $this->debug("HTTP header: $hdr");
2863 $this->outgoing_payload .= "$hdr\r\n";
2864 }
2865
2866 // add any cookies
2867 if ($cookie_str != '') {
2868 $hdr = 'Cookie: ' . $cookie_str;
2869 $this->debug("HTTP header: $hdr");
2870 $this->outgoing_payload .= "$hdr\r\n";
2871 }
2872
2873 // header/body separator
2874 $this->outgoing_payload .= "\r\n";
2875
2876 // add data
2877 $this->outgoing_payload .= $data;
2878 }
2879
2888 public function sendRequest($data, $cookies = null)
2889 {
2890 // build cookie string
2891 $cookie_str = $this->getCookiesForRequest($cookies, (($this->scheme == 'ssl') || ($this->scheme == 'https')));
2892
2893 // build payload
2894 $this->buildPayload($data, $cookie_str);
2895
2896 if ($this->io_method() == 'socket') {
2897 // send payload
2898 if (!fputs($this->fp, $this->outgoing_payload, strlen($this->outgoing_payload))) {
2899 $this->setError('couldn\'t write message data to socket');
2900 $this->debug('couldn\'t write message data to socket');
2901 return false;
2902 }
2903 $this->debug('wrote data to socket, length = ' . strlen($this->outgoing_payload));
2904 return true;
2905 } elseif ($this->io_method() == 'curl') {
2906 // set payload
2907 // cURL does say this should only be the verb, and in fact it
2908 // turns out that the URI and HTTP version are appended to this, which
2909 // some servers refuse to work with (so we no longer use this method!)
2910 //$this->setCurlOption(CURLOPT_CUSTOMREQUEST, $this->outgoing_payload);
2911 $curl_headers = array();
2912 foreach ($this->outgoing_headers as $k => $v) {
2913 if ($k == 'Connection' || $k == 'Content-Length' || $k == 'Host' || $k == 'Authorization' || $k == 'Proxy-Authorization') {
2914 $this->debug("Skip cURL header $k: $v");
2915 } else {
2916 $curl_headers[] = "$k: $v";
2917 }
2918 }
2919 if ($cookie_str != '') {
2920 $curl_headers[] = 'Cookie: ' . $cookie_str;
2921 }
2922 $this->setCurlOption(CURLOPT_HTTPHEADER, $curl_headers);
2923 $this->debug('set cURL HTTP headers');
2924 if ($this->request_method == "POST") {
2925 $this->setCurlOption(CURLOPT_POST, 1);
2926 $this->setCurlOption(CURLOPT_POSTFIELDS, $data);
2927 $this->debug('set cURL POST data');
2928 } else {
2929 }
2930 // insert custom user-set cURL options
2931 foreach ($this->ch_options as $key => $val) {
2932 $this->setCurlOption($key, $val);
2933 }
2934
2935 $this->debug('set cURL payload');
2936 return true;
2937 }
2938 }
2939
2946 public function getResponse()
2947 {
2948 $this->incoming_payload = '';
2949
2950 if ($this->io_method() == 'socket') {
2951 // loop until headers have been retrieved
2952 $data = '';
2953 while (!isset($lb)) {
2954 // We might EOF during header read.
2955 if (feof($this->fp)) {
2956 $this->incoming_payload = $data;
2957 $this->debug('found no headers before EOF after length ' . strlen($data));
2958 $this->debug("received before EOF:\n" . $data);
2959 $this->setError('server failed to send headers');
2960 return false;
2961 }
2962
2963 $tmp = fgets($this->fp, 256);
2964 $tmplen = strlen($tmp);
2965 $this->debug("read line of $tmplen bytes: " . trim($tmp));
2966
2967 if ($tmplen == 0) {
2968 $this->incoming_payload = $data;
2969 $this->debug('socket read of headers timed out after length ' . strlen($data));
2970 $this->debug("read before timeout: " . $data);
2971 $this->setError('socket read of headers timed out');
2972 return false;
2973 }
2974
2975 $data .= $tmp;
2976 $pos = strpos($data, "\r\n\r\n");
2977 if ($pos > 1) {
2978 $lb = "\r\n";
2979 } else {
2980 $pos = strpos($data, "\n\n");
2981 if ($pos > 1) {
2982 $lb = "\n";
2983 }
2984 }
2985 // remove 100 headers
2986 if (isset($lb) && preg_match('/^HTTP\/1.1 100/', $data)) {
2987 unset($lb);
2988 $data = '';
2989 }//
2990 }
2991 // store header data
2992 $this->incoming_payload .= $data;
2993 $this->debug('found end of headers after length ' . strlen($data));
2994 // process headers
2995 $header_data = trim(substr($data, 0, $pos));
2996 $header_array = explode($lb, $header_data);
2997 $this->incoming_headers = array();
2998 $this->incoming_cookies = array();
2999 foreach ($header_array as $header_line) {
3000 $arr = explode(':', $header_line, 2);
3001 if (count($arr) > 1) {
3002 $header_name = strtolower(trim($arr[0]));
3003 $this->incoming_headers[$header_name] = trim($arr[1]);
3004 if ($header_name == 'set-cookie') {
3005 // TODO: allow multiple cookies from parseCookie
3006 $cookie = $this->parseCookie(trim($arr[1]));
3007 if ($cookie) {
3008 $this->incoming_cookies[] = $cookie;
3009 $this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']);
3010 } else {
3011 $this->debug('did not find cookie in ' . trim($arr[1]));
3012 }
3013 }
3014 } elseif (isset($header_name)) {
3015 // append continuation line to previous header
3016 $this->incoming_headers[$header_name] .= $lb . ' ' . $header_line;
3017 }
3018 }
3019
3020 // loop until msg has been received
3021 if (isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked') {
3022 $content_length = 2147483647; // ignore any content-length header
3023 $chunked = true;
3024 $this->debug("want to read chunked content");
3025 } elseif (isset($this->incoming_headers['content-length'])) {
3026 $content_length = $this->incoming_headers['content-length'];
3027 $chunked = false;
3028 $this->debug("want to read content of length $content_length");
3029 } else {
3030 $content_length = 2147483647;
3031 $chunked = false;
3032 $this->debug("want to read content to EOF");
3033 }
3034 $data = '';
3035 do {
3036 if ($chunked) {
3037 $tmp = fgets($this->fp, 256);
3038 $tmplen = strlen($tmp);
3039 $this->debug("read chunk line of $tmplen bytes");
3040 if ($tmplen == 0) {
3041 $this->incoming_payload = $data;
3042 $this->debug('socket read of chunk length timed out after length ' . strlen($data));
3043 $this->debug("read before timeout:\n" . $data);
3044 $this->setError('socket read of chunk length timed out');
3045 return false;
3046 }
3047 $content_length = hexdec(trim($tmp));
3048 $this->debug("chunk length $content_length");
3049 }
3050 $strlen = 0;
3051 while (($strlen < $content_length) && (!feof($this->fp))) {
3052 $readlen = min(8192, $content_length - $strlen);
3053 $tmp = fread($this->fp, $readlen);
3054 $tmplen = strlen($tmp);
3055 $this->debug("read buffer of $tmplen bytes");
3056 if (($tmplen == 0) && (!feof($this->fp))) {
3057 $this->incoming_payload = $data;
3058 $this->debug('socket read of body timed out after length ' . strlen($data));
3059 $this->debug("read before timeout:\n" . $data);
3060 $this->setError('socket read of body timed out');
3061 return false;
3062 }
3063 $strlen += $tmplen;
3064 $data .= $tmp;
3065 }
3066 if ($chunked && ($content_length > 0)) {
3067 $tmp = fgets($this->fp, 256);
3068 $tmplen = strlen($tmp);
3069 $this->debug("read chunk terminator of $tmplen bytes");
3070 if ($tmplen == 0) {
3071 $this->incoming_payload = $data;
3072 $this->debug('socket read of chunk terminator timed out after length ' . strlen($data));
3073 $this->debug("read before timeout:\n" . $data);
3074 $this->setError('socket read of chunk terminator timed out');
3075 return false;
3076 }
3077 }
3078 } while ($chunked && ($content_length > 0) && (!feof($this->fp)));
3079 if (feof($this->fp)) {
3080 $this->debug('read to EOF');
3081 }
3082 $this->debug('read body of length ' . strlen($data));
3083 $this->incoming_payload .= $data;
3084 $this->debug('received a total of ' . strlen($this->incoming_payload) . ' bytes of data from server');
3085
3086 // close filepointer
3087 if (
3088 (isset($this->incoming_headers['connection']) && strtolower($this->incoming_headers['connection']) == 'close') ||
3089 (! $this->persistentConnection) || feof($this->fp)) {
3090 fclose($this->fp);
3091 $this->fp = false;
3092 $this->debug('closed socket');
3093 }
3094
3095 // connection was closed unexpectedly
3096 if ($this->incoming_payload == '') {
3097 $this->setError('no response from server');
3098 return false;
3099 }
3100
3101 // decode transfer-encoding
3102 // if(isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked'){
3103 // if(!$data = $this->decodeChunked($data, $lb)){
3104 // $this->setError('Decoding of chunked data failed');
3105 // return false;
3106 // }
3107 //print "<pre>\nde-chunked:\n---------------\n$data\n\n---------------\n</pre>";
3108 // set decoded payload
3109 // $this->incoming_payload = $header_data.$lb.$lb.$data;
3110 // }
3111 } elseif ($this->io_method() == 'curl') {
3112 // send and receive
3113 $this->debug('send and receive with cURL');
3114 $this->incoming_payload = curl_exec($this->ch);
3116
3117 $cErr = curl_error($this->ch);
3118 if ($cErr != '') {
3119 $err = 'cURL ERROR: ' . curl_errno($this->ch) . ': ' . $cErr . '<br>';
3120 // TODO: there is a PHP bug that can cause this to SEGV for CURLINFO_CONTENT_TYPE
3121 foreach (curl_getinfo($this->ch) as $k => $v) {
3122 $err .= "$k: $v<br>";
3123 }
3124 $this->debug($err);
3125 $this->setError($err);
3126 curl_close($this->ch);
3127 return false;
3128 } else {
3129 //echo '<pre>';
3130 //var_dump(curl_getinfo($this->ch));
3131 //echo '</pre>';
3132 }
3133 // close curl
3134 $this->debug('No cURL error, closing cURL');
3135 curl_close($this->ch);
3136
3137 // try removing skippable headers
3138 $savedata = $data;
3139 while ($this->isSkippableCurlHeader($data)) {
3140 $this->debug("Found HTTP header to skip");
3141 if ($pos = strpos($data, "\r\n\r\n")) {
3142 $data = ltrim(substr($data, $pos));
3143 } elseif ($pos = strpos($data, "\n\n")) {
3144 $data = ltrim(substr($data, $pos));
3145 }
3146 }
3147
3148 if ($data == '') {
3149 // have nothing left; just remove 100 header(s)
3150 $data = $savedata;
3151 while (preg_match('/^HTTP\/1.1 100/', $data)) {
3152 if ($pos = strpos($data, "\r\n\r\n")) {
3153 $data = ltrim(substr($data, $pos));
3154 } elseif ($pos = strpos($data, "\n\n")) {
3155 $data = ltrim(substr($data, $pos));
3156 }
3157 }
3158 }
3159
3160 // separate content from HTTP headers
3161 if ($pos = strpos($data, "\r\n\r\n")) {
3162 $lb = "\r\n";
3163 } elseif ($pos = strpos($data, "\n\n")) {
3164 $lb = "\n";
3165 } else {
3166 $this->debug('no proper separation of headers and document');
3167 $this->setError('no proper separation of headers and document');
3168 return false;
3169 }
3170 $header_data = trim(substr($data, 0, $pos));
3171 $header_array = explode($lb, $header_data);
3172 $data = ltrim(substr($data, $pos));
3173 $this->debug('found proper separation of headers and document');
3174 $this->debug('cleaned data, stringlen: ' . strlen($data));
3175 // clean headers
3176 foreach ($header_array as $header_line) {
3177 $arr = explode(':', $header_line, 2);
3178 if (count($arr) > 1) {
3179 $header_name = strtolower(trim($arr[0]));
3180 $this->incoming_headers[$header_name] = trim($arr[1]);
3181 if ($header_name == 'set-cookie') {
3182 // TODO: allow multiple cookies from parseCookie
3183 $cookie = $this->parseCookie(trim($arr[1]));
3184 if ($cookie) {
3185 $this->incoming_cookies[] = $cookie;
3186 $this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']);
3187 } else {
3188 $this->debug('did not find cookie in ' . trim($arr[1]));
3189 }
3190 }
3191 } elseif (isset($header_name)) {
3192 // append continuation line to previous header
3193 $this->incoming_headers[$header_name] .= $lb . ' ' . $header_line;
3194 }
3195 }
3196 }
3197
3198 $this->response_status_line = $header_array[0];
3199 $arr = explode(' ', $this->response_status_line, 3);
3200 $http_version = $arr[0];
3201 $http_status = intval($arr[1]);
3202 $http_reason = count($arr) > 2 ? $arr[2] : '';
3203
3204 // see if we need to resend the request with http digest authentication
3205 if (isset($this->incoming_headers['location']) && ($http_status == 301 || $http_status == 302)) {
3206 $this->debug("Got $http_status $http_reason with Location: " . $this->incoming_headers['location']);
3207 $this->setURL($this->incoming_headers['location']);
3208 $this->tryagain = true;
3209 return false;
3210 }
3211
3212 // see if we need to resend the request with http digest authentication
3213 if (isset($this->incoming_headers['www-authenticate']) && $http_status == 401) {
3214 $this->debug("Got 401 $http_reason with WWW-Authenticate: " . $this->incoming_headers['www-authenticate']);
3215 if (strstr($this->incoming_headers['www-authenticate'], "Digest ")) {
3216 $this->debug('Server wants digest authentication');
3217 // remove "Digest " from our elements
3218 $digestString = str_replace('Digest ', '', $this->incoming_headers['www-authenticate']);
3219
3220 // parse elements into array
3221 $digestElements = explode(',', $digestString);
3222 foreach ($digestElements as $val) {
3223 $tempElement = explode('=', trim($val), 2);
3224 $digestRequest[$tempElement[0]] = str_replace("\"", '', $tempElement[1]);
3225 }
3226
3227 // should have (at least) qop, realm, nonce
3228 if (isset($digestRequest['nonce'])) {
3229 $this->setCredentials($this->username, $this->password, 'digest', $digestRequest);
3230 $this->tryagain = true;
3231 return false;
3232 }
3233 }
3234 $this->debug('HTTP authentication failed');
3235 $this->setError('HTTP authentication failed');
3236 return false;
3237 }
3238
3239 if (
3240 ($http_status >= 300 && $http_status <= 307) ||
3241 ($http_status >= 400 && $http_status <= 417) ||
3242 ($http_status >= 501 && $http_status <= 505)
3243 ) {
3244 $this->setError("Unsupported HTTP response status $http_status $http_reason (soapclient->response has contents of the response)");
3245 return false;
3246 }
3247
3248 // decode content-encoding
3249 if (isset($this->incoming_headers['content-encoding']) && $this->incoming_headers['content-encoding'] != '') {
3250 if (strtolower($this->incoming_headers['content-encoding']) == 'deflate' || strtolower($this->incoming_headers['content-encoding']) == 'gzip') {
3251 // if decoding works, use it. else assume data wasn't gzencoded
3252 if (function_exists('gzinflate')) {
3253 //$timer->setMarker('starting decoding of gzip/deflated content');
3254 // IIS 5 requires gzinflate instead of gzuncompress (similar to IE 5 and gzdeflate v. gzcompress)
3255 // this means there are no Zlib headers, although there should be
3256 $this->debug('The gzinflate function exists');
3257 $datalen = strlen($data);
3258 if ($this->incoming_headers['content-encoding'] == 'deflate') {
3259 if ($degzdata = @gzinflate($data)) {
3260 $data = $degzdata;
3261 $this->debug('The payload has been inflated to ' . strlen($data) . ' bytes');
3262 if (strlen($data) < $datalen) {
3263 // test for the case that the payload has been compressed twice
3264 $this->debug('The inflated payload is smaller than the gzipped one; try again');
3265 if ($degzdata = @gzinflate($data)) {
3266 $data = $degzdata;
3267 $this->debug('The payload has been inflated again to ' . strlen($data) . ' bytes');
3268 }
3269 }
3270 } else {
3271 $this->debug('Error using gzinflate to inflate the payload');
3272 $this->setError('Error using gzinflate to inflate the payload');
3273 }
3274 } elseif ($this->incoming_headers['content-encoding'] == 'gzip') {
3275 if ($degzdata = @gzinflate(substr($data, 10))) { // do our best
3276 $data = $degzdata;
3277 $this->debug('The payload has been un-gzipped to ' . strlen($data) . ' bytes');
3278 if (strlen($data) < $datalen) {
3279 // test for the case that the payload has been compressed twice
3280 $this->debug('The un-gzipped payload is smaller than the gzipped one; try again');
3281 if ($degzdata = @gzinflate(substr($data, 10))) {
3282 $data = $degzdata;
3283 $this->debug('The payload has been un-gzipped again to ' . strlen($data) . ' bytes');
3284 }
3285 }
3286 } else {
3287 $this->debug('Error using gzinflate to un-gzip the payload');
3288 $this->setError('Error using gzinflate to un-gzip the payload');
3289 }
3290 }
3291 //$timer->setMarker('finished decoding of gzip/deflated content');
3292 //print "<xmp>\nde-inflated:\n---------------\n$data\n-------------\n</xmp>";
3293 // set decoded payload
3294 $this->incoming_payload = $header_data . $lb . $lb . $data;
3295 } else {
3296 $this->debug('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.');
3297 $this->setError('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.');
3298 }
3299 } else {
3300 $this->debug('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']);
3301 $this->setError('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']);
3302 }
3303 } else {
3304 $this->debug('No Content-Encoding header');
3305 }
3306
3307 if (strlen($data) == 0) {
3308 $this->debug('no data after headers!');
3309 $this->setError('no data present after HTTP headers');
3310 return false;
3311 }
3312
3313 return $data;
3314 }
3315
3323 public function setContentType($type, $charset = false)
3324 {
3325 $this->setHeader('Content-Type', $type . ($charset ? '; charset=' . $charset : ''));
3326 }
3327
3334 public function usePersistentConnection()
3335 {
3336 if (isset($this->outgoing_headers['Accept-Encoding'])) {
3337 return false;
3338 }
3339 $this->protocol_version = '1.1';
3340 $this->persistentConnection = true;
3341 $this->setHeader('Connection', 'Keep-Alive');
3342 return true;
3343 }
3344
3352 /*
3353 * TODO: allow a Set-Cookie string to be parsed into multiple cookies
3354 */
3355 public function parseCookie($cookie_str)
3356 {
3357 $cookie_str = str_replace('; ', ';', $cookie_str) . ';';
3358 // begin-patch php8
3359 //$data = split(';', $cookie_str);
3360 $data = explode(';', $cookie_str);
3361 $value_str = $data[0];
3362
3363 $cookie_param = 'domain=';
3364 $start = strpos($cookie_str, $cookie_param);
3365 if ($start > 0) {
3366 $domain = substr($cookie_str, $start + strlen($cookie_param));
3367 $domain = substr($domain, 0, strpos($domain, ';'));
3368 } else {
3369 $domain = '';
3370 }
3371
3372 $cookie_param = 'expires=';
3373 $start = strpos($cookie_str, $cookie_param);
3374 if ($start > 0) {
3375 $expires = substr($cookie_str, $start + strlen($cookie_param));
3376 $expires = substr($expires, 0, strpos($expires, ';'));
3377 } else {
3378 $expires = '';
3379 }
3380
3381 $cookie_param = 'path=';
3382 $start = strpos($cookie_str, $cookie_param);
3383 if ($start > 0) {
3384 $path = substr($cookie_str, $start + strlen($cookie_param));
3385 $path = substr($path, 0, strpos($path, ';'));
3386 } else {
3387 $path = '/';
3388 }
3389
3390 $cookie_param = ';secure;';
3391 if (strpos($cookie_str, $cookie_param) !== false) {
3392 $secure = true;
3393 } else {
3394 $secure = false;
3395 }
3396
3397 $sep_pos = strpos($value_str, '=');
3398
3399 if ($sep_pos) {
3400 $name = substr($value_str, 0, $sep_pos);
3401 $value = substr($value_str, $sep_pos + 1);
3402 $cookie = array( 'name' => $name,
3403 'value' => $value,
3404 'domain' => $domain,
3405 'path' => $path,
3406 'expires' => $expires,
3407 'secure' => $secure
3408 );
3409 return $cookie;
3410 }
3411 return false;
3412 }
3413
3422 public function getCookiesForRequest($cookies, $secure = false)
3423 {
3424 $cookie_str = '';
3425 if ((! is_null($cookies)) && (is_array($cookies))) {
3426 foreach ($cookies as $cookie) {
3427 if (! is_array($cookie)) {
3428 continue;
3429 }
3430 $this->debug("check cookie for validity: " . $cookie['name'] . '=' . $cookie['value']);
3431 if ((isset($cookie['expires'])) && (! empty($cookie['expires']))) {
3432 if (strtotime($cookie['expires']) <= time()) {
3433 $this->debug('cookie has expired');
3434 continue;
3435 }
3436 }
3437 if ((isset($cookie['domain'])) && (! empty($cookie['domain']))) {
3438 $domain = preg_quote($cookie['domain']);
3439 if (! preg_match("'.*$domain$'i", $this->host)) {
3440 $this->debug('cookie has different domain');
3441 continue;
3442 }
3443 }
3444 if ((isset($cookie['path'])) && (! empty($cookie['path']))) {
3445 $path = preg_quote($cookie['path']);
3446 if (! preg_match("'^$path.*'i", $this->path)) {
3447 $this->debug('cookie is for a different path');
3448 continue;
3449 }
3450 }
3451 if ((! $secure) && (isset($cookie['secure'])) && ($cookie['secure'])) {
3452 $this->debug('cookie is secure, transport is not');
3453 continue;
3454 }
3455 $cookie_str .= $cookie['name'] . '=' . $cookie['value'] . '; ';
3456 $this->debug('add cookie to Cookie-String: ' . $cookie['name'] . '=' . $cookie['value']);
3457 }
3458 }
3459 return $cookie_str;
3460 }
3461}
3462
3463?><?php
3464
3465
3466
3477class nusoap_server extends nusoap_base
3478{
3479 public $opData;
3485 public $headers = array();
3491 public $request = '';
3497 public $requestHeaders = '';
3503 public $requestHeader = null;
3509 public $document = '';
3515 public $requestSOAP = '';
3521 public $methodURI = '';
3527 public $methodname = '';
3533 public $methodparams = array();
3539 public $SOAPAction = '';
3545 public $xml_encoding = '';
3551 public $decode_utf8 = true;
3552 public $class;
3553
3559 public $outgoing_headers = array();
3565 public $response = '';
3571 public $responseHeaders = '';
3577 public $responseSOAP = '';
3583 public $methodreturn = false;
3589 public $methodreturnisliteralxml = false;
3595 public $fault = false;
3601 public $result = 'successful';
3602
3609 public $operations = array();
3615 public $wsdl = false;
3621 public $externalWSDLURL = false;
3627 public $debug_flag = false;
3628
3629
3637 public function __construct($wsdl = false)
3638 {
3640 // turn on debugging?
3641 global $debug;
3642 global $HTTP_SERVER_VARS;
3643
3644 if (isset($_SERVER)) {
3645 $this->debug("_SERVER is defined:");
3646 $this->appendDebug($this->varDump($_SERVER));
3647 } elseif (isset($HTTP_SERVER_VARS)) {
3648 $this->debug("HTTP_SERVER_VARS is defined:");
3649 $this->appendDebug($this->varDump($HTTP_SERVER_VARS));
3650 } else {
3651 $this->debug("Neither _SERVER nor HTTP_SERVER_VARS is defined.");
3652 }
3653
3654 if (isset($debug)) {
3655 $this->debug("In nusoap_server, set debug_flag=$debug based on global flag");
3656 $this->debug_flag = $debug;
3657 } elseif (isset($_SERVER['QUERY_STRING'])) {
3658 $qs = explode('&', $_SERVER['QUERY_STRING']);
3659 foreach ($qs as $v) {
3660 if (substr($v, 0, 6) == 'debug=') {
3661 $this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #1");
3662 $this->debug_flag = substr($v, 6);
3663 }
3664 }
3665 } elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
3666 $qs = explode('&', $HTTP_SERVER_VARS['QUERY_STRING']);
3667 foreach ($qs as $v) {
3668 if (substr($v, 0, 6) == 'debug=') {
3669 $this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #2");
3670 $this->debug_flag = substr($v, 6);
3671 }
3672 }
3673 }
3674
3675 // wsdl
3676 if ($wsdl) {
3677 $this->debug("In nusoap_server, WSDL is specified");
3678 if (is_object($wsdl) && (get_class($wsdl) == 'wsdl')) {
3679 $this->wsdl = $wsdl;
3680 $this->externalWSDLURL = $this->wsdl->wsdl;
3681 $this->debug('Use existing wsdl instance from ' . $this->externalWSDLURL);
3682 } else {
3683 $this->debug('Create wsdl from ' . $wsdl);
3684 $this->wsdl = new wsdl($wsdl);
3685 $this->externalWSDLURL = $wsdl;
3686 }
3687 $this->appendDebug($this->wsdl->getDebug());
3688 $this->wsdl->clearDebug();
3689 if ($err = $this->wsdl->getError()) {
3690 die('WSDL ERROR: ' . $err);
3691 }
3692 }
3693 }
3694
3701 public function service($data)
3702 {
3703 global $HTTP_SERVER_VARS;
3704
3705 if (isset($_SERVER['QUERY_STRING'])) {
3706 $qs = $_SERVER['QUERY_STRING'];
3707 } elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
3708 $qs = $HTTP_SERVER_VARS['QUERY_STRING'];
3709 } else {
3710 $qs = '';
3711 }
3712 $this->debug("In service, query string=$qs");
3713
3714 if (preg_match('/wsdl/', $qs)) {
3715 $this->debug("In service, this is a request for WSDL");
3716 if ($this->externalWSDLURL) {
3717 if (strpos($this->externalWSDLURL, "://") !== false) { // assume URL
3718 header('Location: ' . $this->externalWSDLURL);
3719 } else { // assume file
3720 header("Content-Type: text/xml\r\n");
3721 $fp = fopen($this->externalWSDLURL, 'r');
3722 fpassthru($fp);
3723 }
3724 } elseif ($this->wsdl) {
3725 header("Content-Type: text/xml; charset=ISO-8859-1\r\n");
3726 print $this->wsdl->serialize($this->debug_flag);
3727 if ($this->debug_flag) {
3728 $this->debug('wsdl:');
3729 $this->appendDebug($this->varDump($this->wsdl));
3730 print $this->getDebugAsXMLComment();
3731 }
3732 } else {
3733 header("Content-Type: text/html; charset=ISO-8859-1\r\n");
3734 print "This service does not provide WSDL";
3735 }
3736 } elseif ($data == '' && $this->wsdl) {
3737 $this->debug("In service, there is no data, so return Web description");
3738 print $this->wsdl->webDescription();
3739 } else {
3740 $this->debug("In service, invoke the request");
3741 $this->parse_request($data);
3742 if (! $this->fault) {
3743 $this->invoke_method();
3744 }
3745 if (! $this->fault) {
3746 $this->serialize_return();
3747 }
3748 $this->send_response();
3749 }
3750 }
3751
3764 public function parse_http_headers()
3765 {
3766 global $HTTP_SERVER_VARS;
3767
3768 $this->request = '';
3769 $this->SOAPAction = '';
3770 if (function_exists('getallheaders')) {
3771 $this->debug("In parse_http_headers, use getallheaders");
3772 $headers = getallheaders();
3773 foreach ($headers as $k => $v) {
3774 $k = strtolower($k);
3775 $this->headers[$k] = $v;
3776 $this->request .= "$k: $v\r\n";
3777 $this->debug("$k: $v");
3778 }
3779 // get SOAPAction header
3780 if (isset($this->headers['soapaction'])) {
3781 $this->SOAPAction = str_replace('"', '', $this->headers['soapaction']);
3782 }
3783 // get the character encoding of the incoming request
3784 if (isset($this->headers['content-type']) && strpos($this->headers['content-type'], '=')) {
3785 $enc = str_replace('"', '', substr(strstr($this->headers["content-type"], '='), 1));
3786 if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i', $enc)) {
3787 $this->xml_encoding = strtoupper($enc);
3788 } else {
3789 $this->xml_encoding = 'US-ASCII';
3790 }
3791 } else {
3792 // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
3793 $this->xml_encoding = 'ISO-8859-1';
3794 }
3795 } elseif (isset($_SERVER) && is_array($_SERVER)) {
3796 $this->debug("In parse_http_headers, use _SERVER");
3797 foreach ($_SERVER as $k => $v) {
3798 if (substr($k, 0, 5) == 'HTTP_') {
3799 $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5))));
3800 } else {
3801 $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k)));
3802 }
3803 if ($k == 'soapaction') {
3804 // get SOAPAction header
3805 $k = 'SOAPAction';
3806 $v = str_replace('"', '', $v);
3807 $v = str_replace('\\', '', $v);
3808 $this->SOAPAction = $v;
3809 } elseif ($k == 'content-type') {
3810 // get the character encoding of the incoming request
3811 if (strpos($v, '=')) {
3812 $enc = substr(strstr($v, '='), 1);
3813 $enc = str_replace('"', '', $enc);
3814 $enc = str_replace('\\', '', $enc);
3815 if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i', $enc)) {
3816 $this->xml_encoding = strtoupper($enc);
3817 } else {
3818 $this->xml_encoding = 'US-ASCII';
3819 }
3820 } else {
3821 // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
3822 $this->xml_encoding = 'ISO-8859-1';
3823 }
3824 }
3825 $this->headers[$k] = $v;
3826 $this->request .= "$k: $v\r\n";
3827 $this->debug("$k: $v");
3828 }
3829 } elseif (is_array($HTTP_SERVER_VARS)) {
3830 $this->debug("In parse_http_headers, use HTTP_SERVER_VARS");
3831 foreach ($HTTP_SERVER_VARS as $k => $v) {
3832 if (substr($k, 0, 5) == 'HTTP_') {
3833 $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5))));
3834 $k = strtolower(substr($k, 5));
3835 } else {
3836 $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k)));
3837 $k = strtolower($k);
3838 }
3839 if ($k == 'soapaction') {
3840 // get SOAPAction header
3841 $k = 'SOAPAction';
3842 $v = str_replace('"', '', $v);
3843 $v = str_replace('\\', '', $v);
3844 $this->SOAPAction = $v;
3845 } elseif ($k == 'content-type') {
3846 // get the character encoding of the incoming request
3847 if (strpos($v, '=')) {
3848 $enc = substr(strstr($v, '='), 1);
3849 $enc = str_replace('"', '', $enc);
3850 $enc = str_replace('\\', '', $enc);
3851 if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i', $enc)) {
3852 $this->xml_encoding = strtoupper($enc);
3853 } else {
3854 $this->xml_encoding = 'US-ASCII';
3855 }
3856 } else {
3857 // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
3858 $this->xml_encoding = 'ISO-8859-1';
3859 }
3860 }
3861 $this->headers[$k] = $v;
3862 $this->request .= "$k: $v\r\n";
3863 $this->debug("$k: $v");
3864 }
3865 } else {
3866 $this->debug("In parse_http_headers, HTTP headers not accessible");
3867 $this->setError("HTTP headers not accessible");
3868 }
3869 }
3870
3893 public function parse_request($data = '')
3894 {
3895 $this->debug('entering parse_request()');
3896 $this->parse_http_headers();
3897 $this->debug('got character encoding: ' . $this->xml_encoding);
3898 // uncompress if necessary
3899 if (isset($this->headers['content-encoding']) && $this->headers['content-encoding'] != '') {
3900 $this->debug('got content encoding: ' . $this->headers['content-encoding']);
3901 if ($this->headers['content-encoding'] == 'deflate' || $this->headers['content-encoding'] == 'gzip') {
3902 // if decoding works, use it. else assume data wasn't gzencoded
3903 if (function_exists('gzuncompress')) {
3904 if ($this->headers['content-encoding'] == 'deflate' && $degzdata = @gzuncompress($data)) {
3905 $data = $degzdata;
3906 } elseif ($this->headers['content-encoding'] == 'gzip' && $degzdata = gzinflate(substr($data, 10))) {
3907 $data = $degzdata;
3908 } else {
3909 $this->fault('SOAP-ENV:Client', 'Errors occurred when trying to decode the data');
3910 return;
3911 }
3912 } else {
3913 $this->fault('SOAP-ENV:Client', 'This Server does not support compressed data');
3914 return;
3915 }
3916 }
3917 }
3918 $this->request .= "\r\n" . $data;
3919 $data = $this->parseRequest($this->headers, $data);
3920 $this->requestSOAP = $data;
3921 $this->debug('leaving parse_request');
3922 }
3923
3941 public function invoke_method()
3942 {
3943 $this->debug('in invoke_method, methodname=' . $this->methodname . ' methodURI=' . $this->methodURI . ' SOAPAction=' . $this->SOAPAction);
3944
3945 if ($this->wsdl) {
3946 if ($this->opData = $this->wsdl->getOperationData($this->methodname)) {
3947 $this->debug('in invoke_method, found WSDL operation=' . $this->methodname);
3948 $this->appendDebug('opData=' . $this->varDump($this->opData));
3949 } elseif ($this->opData = $this->wsdl->getOperationDataForSoapAction($this->SOAPAction)) {
3950 // Note: hopefully this case will only be used for doc/lit, since rpc services should have wrapper element
3951 $this->debug('in invoke_method, found WSDL soapAction=' . $this->SOAPAction . ' for operation=' . $this->opData['name']);
3952 $this->appendDebug('opData=' . $this->varDump($this->opData));
3953 $this->methodname = $this->opData['name'];
3954 } else {
3955 $this->debug('in invoke_method, no WSDL for operation=' . $this->methodname);
3956 $this->fault('SOAP-ENV:Client', "Operation '" . $this->methodname . "' is not defined in the WSDL for this service");
3957 return;
3958 }
3959 } else {
3960 $this->debug('in invoke_method, no WSDL to validate method');
3961 }
3962
3963 // if a . is present in $this->methodname, we see if there is a class in scope,
3964 // which could be referred to. We will also distinguish between two deliminators,
3965 // to allow methods to be called a the class or an instance
3966 $class = '';
3967 $method = '';
3968 if (strpos($this->methodname, '..') > 0) {
3969 $delim = '..';
3970 } elseif (strpos($this->methodname, '.') > 0) {
3971 $delim = '.';
3972 } else {
3973 $delim = '';
3974 }
3975
3976 if (strlen($delim) > 0 && substr_count($this->methodname, $delim) == 1 &&
3977 class_exists(substr($this->methodname, 0, strpos($this->methodname, $delim)))) {
3978 // get the class and method name
3979 $class = substr($this->methodname, 0, strpos($this->methodname, $delim));
3980 $method = substr($this->methodname, strpos($this->methodname, $delim) + strlen($delim));
3981 $this->debug("in invoke_method, class=$class method=$method delim=$delim");
3982 }
3983 // set class handler
3984 // added to support single operations
3985 if ($class == '' && $this->class != '') {
3987 $delim = "..";
3988 $method = $this->methodname;
3989 }
3990
3991 // does method exist?
3992 if ($class == '') {
3993 if (!function_exists($this->methodname)) {
3994 $this->debug("in invoke_method, function '$this->methodname' not found!");
3995 $this->result = 'fault: method not found';
3996 $this->fault('SOAP-ENV:Client', "method '$this->methodname' not defined in service");
3997 return;
3998 }
3999 } else {
4000 $method_to_compare = (substr(phpversion(), 0, 2) == '4.') ? strtolower($method) : $method;
4001 if (!in_array($method_to_compare, get_class_methods($class))) {
4002 $this->debug("in invoke_method, method '$this->methodname' not found in class '$class'!");
4003 $this->result = 'fault: method not found';
4004 $this->fault('SOAP-ENV:Client', "method '$this->methodname' not defined in service");
4005 return;
4006 }
4007 }
4008
4009 // evaluate message, getting back parameters
4010 // verify that request parameters match the method's signature
4011 if (! $this->verify_method($this->methodname, $this->methodparams)) {
4012 // debug
4013 $this->debug('ERROR: request not verified against method signature');
4014 $this->result = 'fault: request failed validation against method signature';
4015 // return fault
4016 $this->fault('SOAP-ENV:Client', "Operation '$this->methodname' not defined in service.");
4017 return;
4018 }
4019
4020 // if there are parameters to pass
4021 $this->debug('in invoke_method, params:');
4022 $this->appendDebug($this->varDump($this->methodparams));
4023 $this->debug("in invoke_method, calling '$this->methodname'");
4024 if (!function_exists('call_user_func_array')) {
4025 if ($class == '') {
4026 $this->debug('in invoke_method, calling function using eval()');
4027 $funcCall = "\$this->methodreturn = $this->methodname(";
4028 } else {
4029 if ($delim == '..') {
4030 $this->debug('in invoke_method, calling class method using eval()');
4031 $funcCall = "\$this->methodreturn = " . $class . "::" . $method . "(";
4032 } else {
4033 $this->debug('in invoke_method, calling instance method using eval()');
4034 // generate unique instance name
4035 $instname = "\$inst_" . time();
4036 $funcCall = $instname . " = new " . $class . "(); ";
4037 $funcCall .= "\$this->methodreturn = " . $instname . "->" . $method . "(";
4038 }
4039 }
4040 if ($this->methodparams) {
4041 foreach ($this->methodparams as $param) {
4042 if (is_array($param) || is_object($param)) {
4043 $this->fault('SOAP-ENV:Client', 'NuSOAP does not handle complexType parameters correctly when using eval; call_user_func_array must be available');
4044 return;
4045 }
4046 $funcCall .= "\"$param\",";
4047 }
4048 $funcCall = substr($funcCall, 0, -1);
4049 }
4050 $funcCall .= ');';
4051 $this->debug('in invoke_method, function call: ' . $funcCall);
4052 @eval($funcCall);
4053 } else {
4054 if ($class == '') {
4055 $this->debug('in invoke_method, calling function using call_user_func_array()');
4056 $call_arg = "$this->methodname"; // straight assignment changes $this->methodname to lower case after call_user_func_array()
4057 } elseif ($delim == '..') {
4058 $this->debug('in invoke_method, calling class method using call_user_func_array()');
4059 $call_arg = array($class, $method);
4060 } else {
4061 $this->debug('in invoke_method, calling instance method using call_user_func_array()');
4062 $instance = new $class();
4063 $call_arg = array(&$instance, $method);
4064 }
4065 if (is_array($this->methodparams)) {
4066 $this->methodreturn = call_user_func_array($call_arg, array_values($this->methodparams));
4067 } else {
4068 $this->methodreturn = call_user_func_array($call_arg, array());
4069 }
4070 }
4071 $this->debug('in invoke_method, methodreturn:');
4072 $this->appendDebug($this->varDump($this->methodreturn));
4073 $this->debug("in invoke_method, called method $this->methodname, received data of type " . gettype($this->methodreturn));
4074 }
4075
4087 public function serialize_return()
4088 {
4089 $this->debug('Entering serialize_return methodname: ' . $this->methodname . ' methodURI: ' . $this->methodURI);
4090 // if fault
4091 if (isset($this->methodreturn) && ((get_class((object) $this->methodreturn) == 'soap_fault') || (get_class((object) $this->methodreturn) == 'nusoap_fault'))) {
4092 $this->debug('got a fault object from method');
4093 $this->fault = $this->methodreturn;
4094 return;
4095 } elseif ($this->methodreturnisliteralxml) {
4096 $return_val = $this->methodreturn;
4097 // returned value(s)
4098 } else {
4099 $this->debug('got a(n) ' . gettype($this->methodreturn) . ' from method');
4100 $this->debug('serializing return value');
4101 if ($this->wsdl) {
4102 if (sizeof($this->opData['output']['parts']) > 1) {
4103 $this->debug('more than one output part, so use the method return unchanged');
4104 $opParams = $this->methodreturn;
4105 } elseif (sizeof($this->opData['output']['parts']) == 1) {
4106 $this->debug('exactly one output part, so wrap the method return in a simple array');
4107 // TODO: verify that it is not already wrapped!
4108 //foreach ($this->opData['output']['parts'] as $name => $type) {
4109 // $this->debug('wrap in element named ' . $name);
4110 //}
4111 $opParams = array($this->methodreturn);
4112 }
4113 $return_val = $this->wsdl->serializeRPCParameters($this->methodname, 'output', $opParams);
4114 $this->appendDebug($this->wsdl->getDebug());
4115 $this->wsdl->clearDebug();
4116 if ($errstr = $this->wsdl->getError()) {
4117 $this->debug('got wsdl error: ' . $errstr);
4118 $this->fault('SOAP-ENV:Server', 'unable to serialize result');
4119 return;
4120 }
4121 } else {
4122 if (isset($this->methodreturn)) {
4123 $return_val = $this->serialize_val($this->methodreturn, 'return');
4124 } else {
4125 $return_val = '';
4126 $this->debug('in absence of WSDL, assume void return for backward compatibility');
4127 }
4128 }
4129 }
4130 $this->debug('return value:');
4131 $this->appendDebug($this->varDump($return_val));
4132
4133 $this->debug('serializing response');
4134 if ($this->wsdl) {
4135 $this->debug('have WSDL for serialization: style is ' . $this->opData['style']);
4136 if ($this->opData['style'] == 'rpc') {
4137 $this->debug('style is rpc for serialization: use is ' . $this->opData['output']['use']);
4138 if ($this->opData['output']['use'] == 'literal') {
4139 // 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
4140 $payload = '<ns1:' . $this->methodname . 'Response xmlns:ns1="' . $this->methodURI . '">' . $return_val . '</ns1:' . $this->methodname . "Response>";
4141 } else {
4142 $payload = '<ns1:' . $this->methodname . 'Response xmlns:ns1="' . $this->methodURI . '">' . $return_val . '</ns1:' . $this->methodname . "Response>";
4143 }
4144 } else {
4145 $this->debug('style is not rpc for serialization: assume document');
4146 $payload = $return_val;
4147 }
4148 } else {
4149 $this->debug('do not have WSDL for serialization: assume rpc/encoded');
4150 $payload = '<ns1:' . $this->methodname . 'Response xmlns:ns1="' . $this->methodURI . '">' . $return_val . '</ns1:' . $this->methodname . "Response>";
4151 }
4152 $this->result = 'successful';
4153 if ($this->wsdl) {
4154 //if($this->debug_flag){
4155 $this->appendDebug($this->wsdl->getDebug());
4156 // }
4157 if (isset($opData['output']['encodingStyle'])) {
4158 $encodingStyle = $opData['output']['encodingStyle'];
4159 } else {
4160 $encodingStyle = '';
4161 }
4162 // Added: In case we use a WSDL, return a serialized env. WITH the usedNamespaces.
4163 $this->responseSOAP = $this->serializeEnvelope($payload, $this->responseHeaders, $this->wsdl->usedNamespaces, $this->opData['style'], $this->opData['output']['use'], $encodingStyle);
4164 } else {
4165 $this->responseSOAP = $this->serializeEnvelope($payload, $this->responseHeaders);
4166 }
4167 $this->debug("Leaving serialize_return");
4168 }
4169
4180 public function send_response()
4181 {
4182 $this->debug('Enter send_response');
4183 if ($this->fault) {
4184 $payload = $this->fault->serialize();
4185 $this->outgoing_headers[] = "HTTP/1.0 500 Internal Server Error";
4186 $this->outgoing_headers[] = "Status: 500 Internal Server Error";
4187 } else {
4189 // Some combinations of PHP+Web server allow the Status
4190 // to come through as a header. Since OK is the default
4191 // just do nothing.
4192 // $this->outgoing_headers[] = "HTTP/1.0 200 OK";
4193 // $this->outgoing_headers[] = "Status: 200 OK";
4194 }
4195 // add debug data if in debug mode
4196 if (isset($this->debug_flag) && $this->debug_flag) {
4197 $payload .= $this->getDebugAsXMLComment();
4198 }
4199 $this->outgoing_headers[] = "Server: $this->title Server v$this->version";
4200 preg_match('/\$Revisio' . 'n: ([^ ]+)/', $this->revision, $rev);
4201 $this->outgoing_headers[] = "X-SOAP-Server: $this->title/$this->version (" . $rev[1] . ")";
4202 // Let the Web server decide about this
4203 //$this->outgoing_headers[] = "Connection: Close\r\n";
4204 $payload = $this->getHTTPBody($payload);
4205 $type = $this->getHTTPContentType();
4206 $charset = $this->getHTTPContentTypeCharset();
4207 $this->outgoing_headers[] = "Content-Type: $type" . ($charset ? '; charset=' . $charset : '');
4208 //begin code to compress payload - by John
4209 // NOTE: there is no way to know whether the Web server will also compress
4210 // this data.
4211 if (strlen($payload) > 1024 && isset($this->headers) && isset($this->headers['accept-encoding'])) {
4212 if (strstr($this->headers['accept-encoding'], 'gzip')) {
4213 if (function_exists('gzencode')) {
4214 if (isset($this->debug_flag) && $this->debug_flag) {
4215 $payload .= "<!-- Content being gzipped -->";
4216 }
4217 $this->outgoing_headers[] = "Content-Encoding: gzip";
4218 $payload = gzencode($payload);
4219 } else {
4220 if (isset($this->debug_flag) && $this->debug_flag) {
4221 $payload .= "<!-- Content will not be gzipped: no gzencode -->";
4222 }
4223 }
4224 } elseif (strstr($this->headers['accept-encoding'], 'deflate')) {
4225 // Note: MSIE requires gzdeflate output (no Zlib header and checksum),
4226 // instead of gzcompress output,
4227 // which conflicts with HTTP 1.1 spec (http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.5)
4228 if (function_exists('gzdeflate')) {
4229 if (isset($this->debug_flag) && $this->debug_flag) {
4230 $payload .= "<!-- Content being deflated -->";
4231 }
4232 $this->outgoing_headers[] = "Content-Encoding: deflate";
4233 $payload = gzdeflate($payload);
4234 } else {
4235 if (isset($this->debug_flag) && $this->debug_flag) {
4236 $payload .= "<!-- Content will not be deflated: no gzcompress -->";
4237 }
4238 }
4239 }
4240 }
4241 //end code
4242 $this->outgoing_headers[] = "Content-Length: " . strlen($payload);
4243 reset($this->outgoing_headers);
4244 foreach ($this->outgoing_headers as $hdr) {
4245 header($hdr, false);
4246 }
4247 print $payload;
4248 $this->response = join("\r\n", $this->outgoing_headers) . "\r\n\r\n" . $payload;
4249 }
4250
4260 public function verify_method($operation, $request)
4261 {
4262 if (isset($this->wsdl) && is_object($this->wsdl)) {
4263 if ($this->wsdl->getOperationData($operation)) {
4264 return true;
4265 }
4266 } elseif (isset($this->operations[$operation])) {
4267 return true;
4268 }
4269 return false;
4270 }
4271
4280 public function parseRequest($headers, $data)
4281 {
4282 $this->debug('Entering parseRequest() for data of length ' . strlen($data) . ' and type ' . $headers['content-type']);
4283 if (!strstr($headers['content-type'], 'text/xml')) {
4284 $this->setError('Request not of type text/xml');
4285 return false;
4286 }
4287 if (strpos($headers['content-type'], '=')) {
4288 $enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1));
4289 $this->debug('Got response encoding: ' . $enc);
4290 if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i', $enc)) {
4291 $this->xml_encoding = strtoupper($enc);
4292 } else {
4293 $this->xml_encoding = 'US-ASCII';
4294 }
4295 } else {
4296 // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
4297 $this->xml_encoding = 'ISO-8859-1';
4298 }
4299 $this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser');
4300 // parse response, get soap parser obj
4301 $parser = new nusoap_parser($data, $this->xml_encoding, '', $this->decode_utf8);
4302 // parser debug
4303 $this->debug("parser debug: \n" . $parser->getDebug());
4304 // if fault occurred during message parsing
4305 if ($err = $parser->getError()) {
4306 $this->result = 'fault: error in msg parsing: ' . $err;
4307 $this->fault('SOAP-ENV:Client', "error in msg parsing:\n" . $err);
4308 // else successfully parsed request into soapval object
4309 } else {
4310 // get/set methodname
4311 $this->methodURI = $parser->root_struct_namespace;
4312 $this->methodname = $parser->root_struct_name;
4313 $this->debug('methodname: ' . $this->methodname . ' methodURI: ' . $this->methodURI);
4314 $this->debug('calling parser->get_soapbody()');
4315 $this->methodparams = $parser->get_soapbody();
4316 // get SOAP headers
4317 $this->requestHeaders = $parser->getHeaders();
4318 // get SOAP Header
4319 $this->requestHeader = $parser->get_soapheader();
4320 // add document for doclit support
4321 $this->document = $parser->document;
4322 }
4323 }
4324
4332 public function getHTTPBody($soapmsg)
4333 {
4334 return $soapmsg;
4335 }
4336
4345 public function getHTTPContentType()
4346 {
4347 return 'text/xml';
4348 }
4349
4359 public function getHTTPContentTypeCharset()
4360 {
4362 }
4363
4373 public function add_to_map($methodname, $in, $out)
4374 {
4375 $this->operations[$methodname] = array('name' => $methodname,'in' => $in,'out' => $out);
4376 }
4377
4392 public function register($name, $in = array(), $out = array(), $namespace = false, $soapaction = false, $style = false, $use = false, $documentation = '', $encodingStyle = '')
4393 {
4394 global $HTTP_SERVER_VARS;
4395
4396 if ($this->externalWSDLURL) {
4397 die('You cannot bind to an external WSDL file, and register methods outside of it! Please choose either WSDL or no WSDL.');
4398 }
4399 if (! $name) {
4400 die('You must specify a name when you register an operation');
4401 }
4402 if (!is_array($in)) {
4403 die('You must provide an array for operation inputs');
4404 }
4405 if (!is_array($out)) {
4406 die('You must provide an array for operation outputs');
4407 }
4408 if (false == $namespace) {
4409 }
4410 if (false == $soapaction) {
4411 if (isset($_SERVER)) {
4412 $SERVER_NAME = $_SERVER['SERVER_NAME'];
4413 $SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
4414 $HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off');
4415 } elseif (isset($HTTP_SERVER_VARS)) {
4416 $SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
4417 $SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
4418 $HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off';
4419 } else {
4420 $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
4421 }
4422 if ($HTTPS == '1' || $HTTPS == 'on') {
4423 $SCHEME = 'https';
4424 } else {
4425 $SCHEME = 'http';
4426 }
4427 $soapaction = "$SCHEME://$SERVER_NAME$SCRIPT_NAME/$name";
4428 }
4429 if (false == $style) {
4430 $style = "rpc";
4431 }
4432 if (false == $use) {
4433 $use = "encoded";
4434 }
4435 if ($use == 'encoded' && $encodingStyle = '') {
4436 $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
4437 }
4438
4439 $this->operations[$name] = array(
4440 'name' => $name,
4441 'in' => $in,
4442 'out' => $out,
4443 'namespace' => $namespace,
4444 'soapaction' => $soapaction,
4445 'style' => $style);
4446 if ($this->wsdl) {
4447 $this->wsdl->addOperation($name, $in, $out, $namespace, $soapaction, $style, $use, $documentation, $encodingStyle);
4448 }
4449 return true;
4450 }
4451
4462 public function fault($faultcode, $faultstring, $faultactor = '', $faultdetail = '')
4463 {
4464 if ($faultdetail == '' && $this->debug_flag) {
4465 $faultdetail = $this->getDebug();
4466 }
4467 $this->fault = new nusoap_fault($faultcode, $faultactor, $faultstring, $faultdetail);
4468 $this->fault->soap_defencoding = $this->soap_defencoding;
4469 }
4470
4482 public function configureWSDL($serviceName, $namespace = false, $endpoint = false, $style = 'rpc', $transport = 'http://schemas.xmlsoap.org/soap/http', $schemaTargetNamespace = false)
4483 {
4484 global $HTTP_SERVER_VARS;
4485
4486 if (isset($_SERVER)) {
4487 $SERVER_NAME = $_SERVER['SERVER_NAME'];
4488 $SERVER_PORT = $_SERVER['SERVER_PORT'];
4489 $SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
4490 $HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off');
4491 } elseif (isset($HTTP_SERVER_VARS)) {
4492 $SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
4493 $SERVER_PORT = $HTTP_SERVER_VARS['SERVER_PORT'];
4494 $SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
4495 $HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off';
4496 } else {
4497 $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
4498 }
4499 // If server name has port number attached then strip it (else port number gets duplicated in WSDL output) (occurred using lighttpd and FastCGI)
4500 $colon = strpos($SERVER_NAME, ":");
4501 if ($colon) {
4502 $SERVER_NAME = substr($SERVER_NAME, 0, $colon);
4503 }
4504 if ($SERVER_PORT == 80) {
4505 $SERVER_PORT = '';
4506 } else {
4507 $SERVER_PORT = ':' . $SERVER_PORT;
4508 }
4509 if (false == $namespace) {
4510 $namespace = "http://$SERVER_NAME/soap/$serviceName";
4511 }
4512
4513 if (false == $endpoint) {
4514 if ($HTTPS == '1' || $HTTPS == 'on') {
4515 $SCHEME = 'https';
4516 } else {
4517 $SCHEME = 'http';
4518 }
4519 $endpoint = "$SCHEME://$SERVER_NAME$SERVER_PORT$SCRIPT_NAME";
4520 }
4521
4522 if (false == $schemaTargetNamespace) {
4523 $schemaTargetNamespace = $namespace;
4524 }
4525
4526 $this->wsdl = new wsdl();
4527 $this->wsdl->serviceName = $serviceName;
4528 $this->wsdl->endpoint = $endpoint;
4529 $this->wsdl->namespaces['tns'] = $namespace;
4530 $this->wsdl->namespaces['soap'] = 'http://schemas.xmlsoap.org/wsdl/soap/';
4531 $this->wsdl->namespaces['wsdl'] = 'http://schemas.xmlsoap.org/wsdl/';
4532 if ($schemaTargetNamespace != $namespace) {
4533 $this->wsdl->namespaces['types'] = $schemaTargetNamespace;
4534 }
4535 $this->wsdl->schemas[$schemaTargetNamespace][0] = new nusoap_xmlschema('', '', $this->wsdl->namespaces);
4536 if ($style == 'document') {
4537 $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaInfo['elementFormDefault'] = 'qualified';
4538 }
4539 $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaTargetNamespace = $schemaTargetNamespace;
4540 $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/soap/encoding/'][0] = array('location' => '', 'loaded' => true);
4541 $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/wsdl/'][0] = array('location' => '', 'loaded' => true);
4542 $this->wsdl->bindings[$serviceName . 'Binding'] = array(
4543 'name' => $serviceName . 'Binding',
4544 'style' => $style,
4545 'transport' => $transport,
4546 'portType' => $serviceName . 'PortType');
4547 $this->wsdl->ports[$serviceName . 'Port'] = array(
4548 'binding' => $serviceName . 'Binding',
4549 'location' => $endpoint,
4550 'bindingType' => 'http://schemas.xmlsoap.org/wsdl/soap/');
4551 }
4552
4553 public function addInternalPort(string $serviceName, string $url): void
4554 {
4555 $this->wsdl->ports['Internal' . $serviceName . 'Port'] = [
4556 'binding' => $serviceName . 'Binding',
4557 'location' => (string) (new \ILIAS\Data\URI($url))->withQuery(),
4558 'bindingType' => 'http://schemas.xmlsoap.org/wsdl/soap/'
4559 ];
4560 }
4561}
4562
4566class soap_server extends nusoap_server
4567{
4568}
4569
4570?><?php
4571
4572
4573
4583class wsdl extends nusoap_base
4584{
4585 // URL or filename of the root of this WSDL
4586 public $serviceName;
4587 public $opStatus;
4588 public $currentPortOperation;
4589 public $wsdl;
4590 // define internal arrays of bindings, ports, operations, messages, etc.
4591 public $schemas = array();
4592 public $currentSchema;
4593 public $message = array();
4594 public $complexTypes = array();
4595 public $messages = array();
4596 public $currentMessage;
4597 public $currentOperation;
4598 public $portTypes = array();
4599 public $currentPortType;
4600 public $bindings = array();
4601 public $currentBinding;
4602 public $ports = array();
4603 public $currentPort;
4604 public $opData = array();
4605 public $status = '';
4606 public $documentation = false;
4607 public $endpoint = '';
4608 // array of wsdl docs to import
4609 public $import = array();
4610 // parser vars
4611 public $parser;
4612 public $position = 0;
4613 public $depth = 0;
4614 public $depth_array = array();
4615 // for getting wsdl
4616 public $proxyhost = '';
4617 public $proxyport = '';
4618 public $proxyusername = '';
4619 public $proxypassword = '';
4620 public $timeout = 0;
4621 public $response_timeout = 30;
4622 public $curl_options = array(); // User-specified cURL options
4623 public $use_curl = false; // whether to always try to use cURL
4624 // for HTTP authentication
4625 public $username = ''; // Username for HTTP authentication
4626 public $password = ''; // Password for HTTP authentication
4627 public $authtype = ''; // Type of HTTP authentication
4628 public $certRequest = array(); // Certificate for HTTP SSL authentication
4629
4644 public function __construct($wsdl = '', $proxyhost = false, $proxyport = false, $proxyusername = false, $proxypassword = false, $timeout = 0, $response_timeout = 30, $curl_options = null, $use_curl = false)
4645 {
4647 $this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout");
4648 $this->proxyhost = $proxyhost;
4649 $this->proxyport = $proxyport;
4650 $this->proxyusername = $proxyusername;
4651 $this->proxypassword = $proxypassword;
4652 $this->timeout = $timeout;
4653 $this->response_timeout = $response_timeout;
4654 if (is_array($curl_options)) {
4655 $this->curl_options = $curl_options;
4656 }
4657 $this->use_curl = $use_curl;
4658 $this->fetchWSDL($wsdl);
4659 }
4660
4666 public function fetchWSDL($wsdl)
4667 {
4668 $this->debug("parse and process WSDL path=$wsdl");
4669 $this->wsdl = $wsdl;
4670 // parse wsdl file
4671 if ($this->wsdl != "") {
4672 $this->parseWSDL($this->wsdl);
4673 }
4674 // imports
4675 // TODO: handle imports more properly, grabbing them in-line and nesting them
4676 $imported_urls = array();
4677 $imported = 1;
4678 while ($imported > 0) {
4679 $imported = 0;
4680 // Schema imports
4681 foreach ($this->schemas as $ns => $list) {
4682 foreach ($list as $xs) {
4683 $wsdlparts = parse_url($this->wsdl); // this is bogusly simple!
4684 foreach ($xs->imports as $ns2 => $list2) {
4685 for ($ii = 0; $ii < count($list2); $ii++) {
4686 if (! $list2[$ii]['loaded']) {
4687 $this->schemas[$ns]->imports[$ns2][$ii]['loaded'] = true;
4688 $url = $list2[$ii]['location'];
4689 if ($url != '') {
4690 $urlparts = parse_url($url);
4691 if (!isset($urlparts['host'])) {
4692 $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' . $wsdlparts['port'] : '') .
4693 substr($wsdlparts['path'], 0, strrpos($wsdlparts['path'], '/') + 1) . $urlparts['path'];
4694 }
4695 if (! in_array($url, $imported_urls)) {
4696 $this->parseWSDL($url);
4697 $imported++;
4698 $imported_urls[] = $url;
4699 }
4700 } else {
4701 $this->debug("Unexpected scenario: empty URL for unloaded import");
4702 }
4703 }
4704 }
4705 }
4706 }
4707 }
4708 // WSDL imports
4709 $wsdlparts = parse_url($this->wsdl); // this is bogusly simple!
4710 foreach ($this->import as $ns => $list) {
4711 for ($ii = 0; $ii < count($list); $ii++) {
4712 if (! $list[$ii]['loaded']) {
4713 $this->import[$ns][$ii]['loaded'] = true;
4714 $url = $list[$ii]['location'];
4715 if ($url != '') {
4716 $urlparts = parse_url($url);
4717 if (!isset($urlparts['host'])) {
4718 $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' . $wsdlparts['port'] : '') .
4719 substr($wsdlparts['path'], 0, strrpos($wsdlparts['path'], '/') + 1) . $urlparts['path'];
4720 }
4721 if (! in_array($url, $imported_urls)) {
4722 $this->parseWSDL($url);
4723 $imported++;
4724 $imported_urls[] = $url;
4725 }
4726 } else {
4727 $this->debug("Unexpected scenario: empty URL for unloaded import");
4728 }
4729 }
4730 }
4731 }
4732 }
4733 // add new data to operation data
4734 foreach ($this->bindings as $binding => $bindingData) {
4735 if (isset($bindingData['operations']) && is_array($bindingData['operations'])) {
4736 foreach ($bindingData['operations'] as $operation => $data) {
4737 $this->debug('post-parse data gathering for ' . $operation);
4738 $this->bindings[$binding]['operations'][$operation]['input'] =
4739 isset($this->bindings[$binding]['operations'][$operation]['input']) ?
4740 array_merge($this->bindings[$binding]['operations'][$operation]['input'], $this->portTypes[ $bindingData['portType'] ][$operation]['input']) :
4741 $this->portTypes[ $bindingData['portType'] ][$operation]['input'];
4742 $this->bindings[$binding]['operations'][$operation]['output'] =
4743 isset($this->bindings[$binding]['operations'][$operation]['output']) ?
4744 array_merge($this->bindings[$binding]['operations'][$operation]['output'], $this->portTypes[ $bindingData['portType'] ][$operation]['output']) :
4745 $this->portTypes[ $bindingData['portType'] ][$operation]['output'];
4746 if (isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ])) {
4747 $this->bindings[$binding]['operations'][$operation]['input']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ];
4748 }
4749 if (isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ])) {
4750 $this->bindings[$binding]['operations'][$operation]['output']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ];
4751 }
4752 // Set operation style if necessary, but do not override one already provided
4753 if (isset($bindingData['style']) && !isset($this->bindings[$binding]['operations'][$operation]['style'])) {
4754 $this->bindings[$binding]['operations'][$operation]['style'] = $bindingData['style'];
4755 }
4756 $this->bindings[$binding]['operations'][$operation]['transport'] = isset($bindingData['transport']) ? $bindingData['transport'] : '';
4757 $this->bindings[$binding]['operations'][$operation]['documentation'] = isset($this->portTypes[ $bindingData['portType'] ][$operation]['documentation']) ? $this->portTypes[ $bindingData['portType'] ][$operation]['documentation'] : '';
4758 $this->bindings[$binding]['operations'][$operation]['endpoint'] = isset($bindingData['endpoint']) ? $bindingData['endpoint'] : '';
4759 }
4760 }
4761 }
4762 }
4763
4770 public function parseWSDL($wsdl = '')
4771 {
4772 $this->debug("parse WSDL at path=$wsdl");
4773
4774 if ($wsdl == '') {
4775 $this->debug('no wsdl passed to parseWSDL()!!');
4776 $this->setError('no wsdl passed to parseWSDL()!!');
4777 return false;
4778 }
4779
4780 // parse $wsdl for url format
4781 $wsdl_props = parse_url($wsdl);
4782
4783 if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'http' || $wsdl_props['scheme'] == 'https')) {
4784 $this->debug('getting WSDL http(s) URL ' . $wsdl);
4785 // get wsdl
4786 $tr = new soap_transport_http($wsdl, $this->curl_options, $this->use_curl);
4787 $tr->request_method = 'GET';
4788 $tr->useSOAPAction = false;
4789 if ($this->proxyhost && $this->proxyport) {
4790 $tr->setProxy($this->proxyhost, $this->proxyport, $this->proxyusername, $this->proxypassword);
4791 }
4792 if ($this->authtype != '') {
4793 $tr->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest);
4794 }
4795 $tr->setEncoding('gzip, deflate');
4796 $wsdl_string = $tr->send('', $this->timeout, $this->response_timeout);
4797 //$this->debug("WSDL request\n" . $tr->outgoing_payload);
4798 //$this->debug("WSDL response\n" . $tr->incoming_payload);
4799 $this->appendDebug($tr->getDebug());
4800 // catch errors
4801 if ($err = $tr->getError()) {
4802 $errstr = 'HTTP ERROR: ' . $err;
4803 $this->debug($errstr);
4804 $this->setError($errstr);
4805 unset($tr);
4806 return false;
4807 }
4808 unset($tr);
4809 $this->debug("got WSDL URL");
4810 } else {
4811 // $wsdl is not http(s), so treat it as a file URL or plain file path
4812 if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'file') && isset($wsdl_props['path'])) {
4813 $path = isset($wsdl_props['host']) ? ($wsdl_props['host'] . ':' . $wsdl_props['path']) : $wsdl_props['path'];
4814 } else {
4815 $path = $wsdl;
4816 }
4817 $this->debug('getting WSDL file ' . $path);
4818 if ($fp = @fopen($path, 'r')) {
4819 $wsdl_string = '';
4820 while ($data = fread($fp, 32768)) {
4821 $wsdl_string .= $data;
4822 }
4823 fclose($fp);
4824 } else {
4825 $errstr = "Bad path to WSDL file $path";
4826 $this->debug($errstr);
4827 $this->setError($errstr);
4828 return false;
4829 }
4830 }
4831 $this->debug('Parse WSDL');
4832 // end new code added
4833 // Create an XML parser.
4834 $this->parser = xml_parser_create();
4835 // Set the options for parsing the XML data.
4836 // xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
4837 xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
4838 // Set the object for the parser.
4839 // Set the element handlers for the parser.
4840 xml_set_element_handler($this->parser, $this->start_element(...), $this->end_element(...));
4841 xml_set_character_data_handler($this->parser, $this->character_data(...));
4842 // Parse the XML file.
4843 if (!xml_parse($this->parser, $wsdl_string, true)) {
4844 // Display an error message.
4845 $errstr = sprintf(
4846 'XML error parsing WSDL from %s on line %d: %s',
4847 $wsdl,
4848 xml_get_current_line_number($this->parser),
4849 xml_error_string(xml_get_error_code($this->parser))
4850 );
4851 $this->debug($errstr);
4852 $this->debug("XML payload:\n" . $wsdl_string);
4853 $this->setError($errstr);
4854 return false;
4855 }
4856 // free the parser
4857 xml_parser_free($this->parser);
4858 $this->debug('Parsing WSDL done');
4859 // catch wsdl parse errors
4860 if ($this->getError()) {
4861 return false;
4862 }
4863 return true;
4864 }
4865
4874 public function start_element($parser, $name, $attrs)
4875 {
4876 if ($this->status == 'schema') {
4877 $this->currentSchema->schemaStartElement($parser, $name, $attrs);
4878 $this->appendDebug($this->currentSchema->getDebug());
4879 $this->currentSchema->clearDebug();
4880 } elseif (preg_match('/schema$/', $name)) {
4881 $this->debug('Parsing WSDL schema');
4882 // $this->debug("startElement for $name ($attrs[name]). status = $this->status (".$this->getLocalPart($name).")");
4883 $this->status = 'schema';
4884 $this->currentSchema = new nusoap_xmlschema('', '', $this->namespaces);
4885 $this->currentSchema->schemaStartElement($parser, $name, $attrs);
4886 $this->appendDebug($this->currentSchema->getDebug());
4887 $this->currentSchema->clearDebug();
4888 } else {
4889 // position in the total number of elements, starting from 0
4890 $pos = $this->position++;
4891 $depth = $this->depth++;
4892 // set self as current value for this depth
4893 $this->depth_array[$depth] = $pos;
4894 $this->message[$pos] = array('cdata' => '');
4895 // process attributes
4896 if (count($attrs) > 0) {
4897 // register namespace declarations
4898 foreach ($attrs as $k => $v) {
4899 if (preg_match('/^xmlns/', $k)) {
4900 if ($ns_prefix = substr(strrchr($k, ':'), 1)) {
4901 $this->namespaces[$ns_prefix] = $v;
4902 } else {
4903 $this->namespaces['ns' . (count($this->namespaces) + 1)] = $v;
4904 }
4905 if ($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema') {
4906 $this->XMLSchemaVersion = $v;
4907 $this->namespaces['xsi'] = $v . '-instance';
4908 }
4909 }
4910 }
4911 // expand each attribute prefix to its namespace
4912 foreach ($attrs as $k => $v) {
4913 $k = strpos($k, ':') ? $this->expandQname($k) : $k;
4914 if ($k != 'location' && $k != 'soapAction' && $k != 'namespace') {
4915 $v = strpos($v, ':') ? $this->expandQname($v) : $v;
4916 }
4917 $eAttrs[$k] = $v;
4918 }
4919 $attrs = $eAttrs;
4920 } else {
4921 $attrs = array();
4922 }
4923 // get element prefix, namespace and name
4924 if (preg_match('/:/', $name)) {
4925 // get ns prefix
4926 $prefix = substr($name, 0, strpos($name, ':'));
4927 // get ns
4928 $namespace = isset($this->namespaces[$prefix]) ? $this->namespaces[$prefix] : '';
4929 // get unqualified name
4930 $name = substr(strstr($name, ':'), 1);
4931 }
4932 // process attributes, expanding any prefixes to namespaces
4933 // find status, register data
4934 switch ($this->status) {
4935 case 'message':
4936 if ($name == 'part') {
4937 if (isset($attrs['type'])) {
4938 $this->debug("msg " . $this->currentMessage . ": found part (with type) $attrs[name]: " . implode(',', $attrs));
4939 $this->messages[$this->currentMessage][$attrs['name']] = $attrs['type'];
4940 }
4941 if (isset($attrs['element'])) {
4942 $this->debug("msg " . $this->currentMessage . ": found part (with element) $attrs[name]: " . implode(',', $attrs));
4943 $this->messages[$this->currentMessage][$attrs['name']] = $attrs['element'] . '^';
4944 }
4945 }
4946 break;
4947 case 'portType':
4948 switch ($name) {
4949 case 'operation':
4950 $this->currentPortOperation = $attrs['name'];
4951 $this->debug("portType $this->currentPortType operation: $this->currentPortOperation");
4952 if (isset($attrs['parameterOrder'])) {
4953 $this->portTypes[$this->currentPortType][$attrs['name']]['parameterOrder'] = $attrs['parameterOrder'];
4954 }
4955 break;
4956 case 'documentation':
4957 $this->documentation = true;
4958 break;
4959 // merge input/output data
4960 default:
4961 $m = isset($attrs['message']) ? $this->getLocalPart($attrs['message']) : '';
4962 $this->portTypes[$this->currentPortType][$this->currentPortOperation][$name]['message'] = $m;
4963 break;
4964 }
4965 break;
4966 case 'binding':
4967 switch ($name) {
4968 case 'binding':
4969 // get ns prefix
4970 if (isset($attrs['style'])) {
4971 $this->bindings[$this->currentBinding]['prefix'] = $prefix;
4972 }
4973 $this->bindings[$this->currentBinding] = array_merge($this->bindings[$this->currentBinding], $attrs);
4974 break;
4975 case 'header':
4976 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus]['headers'][] = $attrs;
4977 break;
4978 case 'operation':
4979 if (isset($attrs['soapAction'])) {
4980 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['soapAction'] = $attrs['soapAction'];
4981 }
4982 if (isset($attrs['style'])) {
4983 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['style'] = $attrs['style'];
4984 }
4985 if (isset($attrs['name'])) {
4986 $this->currentOperation = $attrs['name'];
4987 $this->debug("current binding operation: $this->currentOperation");
4988 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['name'] = $attrs['name'];
4989 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['binding'] = $this->currentBinding;
4990 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['endpoint'] = isset($this->bindings[$this->currentBinding]['endpoint']) ? $this->bindings[$this->currentBinding]['endpoint'] : '';
4991 }
4992 break;
4993 case 'input':
4994 $this->opStatus = 'input';
4995 break;
4996 case 'output':
4997 $this->opStatus = 'output';
4998 break;
4999 case 'body':
5000 if (isset($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus])) {
5001 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = array_merge($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus], $attrs);
5002 } else {
5003 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = $attrs;
5004 }
5005 break;
5006 }
5007 break;
5008 case 'service':
5009 switch ($name) {
5010 case 'port':
5011 $this->currentPort = $attrs['name'];
5012 $this->debug('current port: ' . $this->currentPort);
5013 $this->ports[$this->currentPort]['binding'] = $this->getLocalPart($attrs['binding']);
5014
5015 break;
5016 case 'address':
5017 $this->ports[$this->currentPort]['location'] = $attrs['location'];
5018 $this->ports[$this->currentPort]['bindingType'] = $namespace;
5019 $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['bindingType'] = $namespace;
5020 $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['endpoint'] = $attrs['location'];
5021 break;
5022 }
5023 break;
5024 }
5025 // set status
5026 switch ($name) {
5027 case 'import':
5028 if (isset($attrs['location'])) {
5029 $this->import[$attrs['namespace']][] = array('location' => $attrs['location'], 'loaded' => false);
5030 $this->debug('parsing import ' . $attrs['namespace'] . ' - ' . $attrs['location'] . ' (' . count($this->import[$attrs['namespace']]) . ')');
5031 } else {
5032 $this->import[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
5033 if (! $this->getPrefixFromNamespace($attrs['namespace'])) {
5034 $this->namespaces['ns' . (count($this->namespaces) + 1)] = $attrs['namespace'];
5035 }
5036 $this->debug('parsing import ' . $attrs['namespace'] . ' - [no location] (' . count($this->import[$attrs['namespace']]) . ')');
5037 }
5038 break;
5039 //wait for schema
5040 //case 'types':
5041 // $this->status = 'schema';
5042 // break;
5043 case 'message':
5044 $this->status = 'message';
5045 $this->messages[$attrs['name']] = array();
5046 $this->currentMessage = $attrs['name'];
5047 break;
5048 case 'portType':
5049 $this->status = 'portType';
5050 $this->portTypes[$attrs['name']] = array();
5051 $this->currentPortType = $attrs['name'];
5052 break;
5053 case "binding":
5054 if (isset($attrs['name'])) {
5055 // get binding name
5056 if (strpos($attrs['name'], ':')) {
5057 $this->currentBinding = $this->getLocalPart($attrs['name']);
5058 } else {
5059 $this->currentBinding = $attrs['name'];
5060 }
5061 $this->status = 'binding';
5062 $this->bindings[$this->currentBinding]['portType'] = $this->getLocalPart($attrs['type']);
5063 $this->debug("current binding: $this->currentBinding of portType: " . $attrs['type']);
5064 }
5065 break;
5066 case 'service':
5067 $this->serviceName = $attrs['name'];
5068 $this->status = 'service';
5069 $this->debug('current service: ' . $this->serviceName);
5070 break;
5071 case 'definitions':
5072 foreach ($attrs as $name => $value) {
5073 $this->wsdl_info[$name] = $value;
5074 }
5075 break;
5076 }
5077 }
5078 }
5079
5087 public function end_element($parser, $name)
5088 {
5089 // unset schema status
5090 if (/*preg_match('/types$/', $name) ||*/ preg_match('/schema$/', $name)) {
5091 $this->status = "";
5092 $this->appendDebug($this->currentSchema->getDebug());
5093 $this->currentSchema->clearDebug();
5094 $this->schemas[$this->currentSchema->schemaTargetNamespace][] = $this->currentSchema;
5095 $this->debug('Parsing WSDL schema done');
5096 }
5097 if ($this->status == 'schema') {
5098 $this->currentSchema->schemaEndElement($parser, $name);
5099 } else {
5100 // bring depth down a notch
5101 $this->depth--;
5102 }
5103 // end documentation
5104 if ($this->documentation) {
5105 //TODO: track the node to which documentation should be assigned; it can be a part, message, etc.
5106 //$this->portTypes[$this->currentPortType][$this->currentPortOperation]['documentation'] = $this->documentation;
5107 $this->documentation = false;
5108 }
5109 }
5110
5118 public function character_data($parser, $data)
5119 {
5120 $pos = isset($this->depth_array[$this->depth]) ? $this->depth_array[$this->depth] : 0;
5121 if (isset($this->message[$pos]['cdata'])) {
5122 $this->message[$pos]['cdata'] .= $data;
5123 }
5124 if ($this->documentation) {
5125 $this->documentation .= $data;
5126 }
5127 }
5128
5138 public function setCredentials($username, $password, $authtype = 'basic', $certRequest = array())
5139 {
5140 $this->debug("setCredentials username=$username authtype=$authtype certRequest=");
5141 $this->appendDebug($this->varDump($certRequest));
5142 $this->username = $username;
5143 $this->password = $password;
5144 $this->authtype = $authtype;
5145 $this->certRequest = $certRequest;
5146 }
5147
5148 public function getBindingData($binding)
5149 {
5150 if (is_array($this->bindings[$binding])) {
5151 return $this->bindings[$binding];
5152 }
5153 }
5154
5162 public function getOperations($bindingType = 'soap')
5163 {
5164 $ops = array();
5165 if ($bindingType == 'soap') {
5166 $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
5167 } elseif ($bindingType == 'soap12') {
5168 $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
5169 }
5170 // loop thru ports
5171 foreach ($this->ports as $port => $portData) {
5172 // binding type of port matches parameter
5173 if ($portData['bindingType'] == $bindingType) {
5174 //$this->debug("getOperations for port $port");
5175 //$this->debug("port data: " . $this->varDump($portData));
5176 //$this->debug("bindings: " . $this->varDump($this->bindings[ $portData['binding'] ]));
5177 // merge bindings
5178 if (isset($this->bindings[ $portData['binding'] ]['operations'])) {
5179 $ops = array_merge($ops, $this->bindings[ $portData['binding'] ]['operations']);
5180 }
5181 }
5182 }
5183 return $ops;
5184 }
5185
5194 public function getOperationData($operation, $bindingType = 'soap')
5195 {
5196 if ($bindingType == 'soap') {
5197 $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
5198 } elseif ($bindingType == 'soap12') {
5199 $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
5200 }
5201 // loop thru ports
5202 foreach ($this->ports as $port => $portData) {
5203 // binding type of port matches parameter
5204 if ($portData['bindingType'] == $bindingType) {
5205 // get binding
5206 //foreach($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) {
5207 foreach (array_keys($this->bindings[ $portData['binding'] ]['operations']) as $bOperation) {
5208 // note that we could/should also check the namespace here
5209 if ($operation == $bOperation) {
5210 $opData = $this->bindings[ $portData['binding'] ]['operations'][$operation];
5211 return $opData;
5212 }
5213 }
5214 }
5215 }
5216 }
5217
5226 public function getOperationDataForSoapAction($soapAction, $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 // loop through operations for the binding
5238 foreach ($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) {
5239 if ($opData['soapAction'] == $soapAction) {
5240 return $opData;
5241 }
5242 }
5243 }
5244 }
5245 }
5246
5265 public function getTypeDef($type, $ns)
5266 {
5267 $this->debug("in getTypeDef: type=$type, ns=$ns");
5268 if ((! $ns) && isset($this->namespaces['tns'])) {
5269 $ns = $this->namespaces['tns'];
5270 $this->debug("in getTypeDef: type namespace forced to $ns");
5271 }
5272 if (!isset($this->schemas[$ns])) {
5273 foreach ($this->schemas as $ns0 => $schema0) {
5274 if (strcasecmp($ns, $ns0) == 0) {
5275 $this->debug("in getTypeDef: replacing schema namespace $ns with $ns0");
5276 $ns = $ns0;
5277 break;
5278 }
5279 }
5280 }
5281 if (isset($this->schemas[$ns])) {
5282 $this->debug("in getTypeDef: have schema for namespace $ns");
5283 for ($i = 0; $i < count($this->schemas[$ns]); $i++) {
5284 $xs = &$this->schemas[$ns][$i];
5285 $t = $xs->getTypeDef($type);
5286 //$this->appendDebug($xs->getDebug());
5287 //$xs->clearDebug();
5288 if ($t) {
5289 if (!isset($t['phpType'])) {
5290 // get info for type to tack onto the element
5291 $uqType = substr($t['type'], strrpos($t['type'], ':') + 1);
5292 $ns = substr($t['type'], 0, strrpos($t['type'], ':'));
5293 $etype = $this->getTypeDef($uqType, $ns);
5294 if ($etype) {
5295 $this->debug("found type for [element] $type:");
5296 $this->debug($this->varDump($etype));
5297 if (isset($etype['phpType'])) {
5298 $t['phpType'] = $etype['phpType'];
5299 }
5300 if (isset($etype['elements'])) {
5301 $t['elements'] = $etype['elements'];
5302 }
5303 if (isset($etype['attrs'])) {
5304 $t['attrs'] = $etype['attrs'];
5305 }
5306 }
5307 }
5308 return $t;
5309 }
5310 }
5311 } else {
5312 $this->debug("in getTypeDef: do not have schema for namespace $ns");
5313 }
5314 return false;
5315 }
5316
5322 public function webDescription()
5323 {
5324 global $HTTP_SERVER_VARS;
5325
5326 if (isset($_SERVER)) {
5327 $PHP_SELF = $_SERVER['PHP_SELF'];
5328 } elseif (isset($HTTP_SERVER_VARS)) {
5329 $PHP_SELF = $HTTP_SERVER_VARS['PHP_SELF'];
5330 } else {
5331 $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
5332 }
5333 // begin-patch: https://mantis.ilias.de/view.php?id=28866
5334 $PHP_SELF = htmlspecialchars($PHP_SELF, ENT_QUOTES | ENT_HTML5, 'UTF-8');
5335 // end-patch
5336
5337 $b = '
5338 <html><head><title>NuSOAP: ' . $this->serviceName . '</title>
5339 <style type="text/css">
5340 body { font-family: arial; color: #000000; background-color: #ffffff; margin: 0px 0px 0px 0px; }
5341 p { font-family: arial; color: #000000; margin-top: 0px; margin-bottom: 12px; }
5342 pre { background-color: silver; padding: 5px; font-family: Courier New; font-size: x-small; color: #000000;}
5343 ul { margin-top: 10px; margin-left: 20px; }
5344 li { list-style-type: none; margin-top: 10px; color: #000000; }
5345 .content{
5346 margin-left: 0px; padding-bottom: 2em; }
5347 .nav {
5348 padding-top: 10px; padding-bottom: 10px; padding-left: 15px; font-size: .70em;
5349 margin-top: 10px; margin-left: 0px; color: #000000;
5350 background-color: #ccccff; width: 20%; margin-left: 20px; margin-top: 20px; }
5351 .title {
5352 font-family: arial; font-size: 26px; color: #ffffff;
5353 background-color: #999999; width: 105%; margin-left: 0px;
5354 padding-top: 10px; padding-bottom: 10px; padding-left: 15px;}
5355 .hidden {
5356 position: absolute; visibility: hidden; z-index: 200; left: 250px; top: 100px;
5357 font-family: arial; overflow: hidden; width: 600;
5358 padding: 20px; font-size: 10px; background-color: #999999;
5359 layer-background-color:#FFFFFF; }
5360 a,a:active { color: charcoal; font-weight: bold; }
5361 a:visited { color: #666666; font-weight: bold; }
5362 a:hover { color: cc3300; font-weight: bold; }
5363 </style>
5364 <script language="JavaScript" type="text/javascript">
5365 <!--
5366 // POP-UP CAPTIONS...
5367 function lib_bwcheck(){ //Browsercheck (needed)
5368 this.ver=navigator.appVersion
5369 this.agent=navigator.userAgent
5370 this.dom=document.getElementById?1:0
5371 this.opera5=this.agent.indexOf("Opera 5")>-1
5372 this.ie5=(this.ver.indexOf("MSIE 5")>-1 && this.dom && !this.opera5)?1:0;
5373 this.ie6=(this.ver.indexOf("MSIE 6")>-1 && this.dom && !this.opera5)?1:0;
5374 this.ie4=(document.all && !this.dom && !this.opera5)?1:0;
5375 this.ie=this.ie4||this.ie5||this.ie6
5376 this.mac=this.agent.indexOf("Mac")>-1
5377 this.ns6=(this.dom && parseInt(this.ver) >= 5) ?1:0;
5378 this.ns4=(document.layers && !this.dom)?1:0;
5379 this.bw=(this.ie6 || this.ie5 || this.ie4 || this.ns4 || this.ns6 || this.opera5)
5380 return this
5381 }
5382 var bw = new lib_bwcheck()
5383 //Makes crossbrowser object.
5384 function makeObj(obj){
5385 this.evnt=bw.dom? document.getElementById(obj):bw.ie4?document.all[obj]:bw.ns4?document.layers[obj]:0;
5386 if(!this.evnt) return false
5387 this.css=bw.dom||bw.ie4?this.evnt.style:bw.ns4?this.evnt:0;
5388 this.wref=bw.dom||bw.ie4?this.evnt:bw.ns4?this.css.document:0;
5389 this.writeIt=b_writeIt;
5390 return this
5391 }
5392 // A unit of measure that will be added when setting the position of a layer.
5393 //var px = bw.ns4||window.opera?"":"px";
5394 function b_writeIt(text){
5395 if (bw.ns4){this.wref.write(text);this.wref.close()}
5396 else this.wref.innerHTML = text
5397 }
5398 //Shows the messages
5399 var oDesc;
5400 function popup(divid){
5401 if(oDesc = new makeObj(divid)){
5402 oDesc.css.visibility = "visible"
5403 }
5404 }
5405 function popout(){ // Hides message
5406 if(oDesc) oDesc.css.visibility = "hidden"
5407 }
5408 //-->
5409 </script>
5410 </head>
5411 <body>
5412 <div class=content>
5413 <br><br>
5414 <div class=title>' . $this->serviceName . '</div>
5415 <div class=nav>
5416 <p>View the <a href="' . $PHP_SELF . '?wsdl">WSDL</a> for the service.
5417 Click on an operation name to view it&apos;s details.</p>
5418 <ul>';
5419 foreach ($this->getOperations() as $op => $data) {
5420 // begin-patch: https://mantis.ilias.de/view.php?id=28866
5421 if (isset($data['endpoint'])) {
5422 $data['endpoint'] = htmlspecialchars($data['endpoint'], ENT_QUOTES | ENT_HTML5, 'UTF-8');
5423 }
5424 // end-patch
5425 $b .= "<li><a href='#' onclick=\"popout();popup('$op')\">$op</a></li>";
5426 // create hidden div
5427 $b .= "<div id='$op' class='hidden'>
5428 <a href='#' onclick='popout()'><font color='#ffffff'>Close</font></a><br><br>";
5429 foreach ($data as $donnie => $marie) { // loop through opdata
5430 if ($donnie == 'input' || $donnie == 'output') { // show input/output data
5431 $b .= "<font color='white'>" . ucfirst($donnie) . ':</font><br>';
5432 foreach ($marie as $captain => $tenille) { // loop through data
5433 if ($captain == 'parts') { // loop thru parts
5434 $b .= "&nbsp;&nbsp;$captain:<br>";
5435 //if(is_array($tenille)){
5436 foreach ($tenille as $joanie => $chachi) {
5437 $b .= "&nbsp;&nbsp;&nbsp;&nbsp;$joanie: $chachi<br>";
5438 }
5439 //}
5440 } else {
5441 $b .= "&nbsp;&nbsp;$captain: $tenille<br>";
5442 }
5443 }
5444 } else {
5445 $b .= "<font color='white'>" . ucfirst($donnie) . ":</font> $marie<br>";
5446 }
5447 }
5448 $b .= '</div>';
5449 }
5450 $b .= '
5451 <ul>
5452 </div>
5453 </div></body></html>';
5454 return $b;
5455 }
5456
5464 public function serialize($debug = 0)
5465 {
5466 $xml = '<?xml version="1.0" encoding="ISO-8859-1"?>';
5467 $xml .= "\n<definitions";
5468 foreach ($this->namespaces as $k => $v) {
5469 $xml .= " xmlns:$k=\"$v\"";
5470 }
5471 // 10.9.02 - add poulter fix for wsdl and tns declarations
5472 if (isset($this->namespaces['wsdl'])) {
5473 $xml .= " xmlns=\"" . $this->namespaces['wsdl'] . "\"";
5474 }
5475 if (isset($this->namespaces['tns'])) {
5476 $xml .= " targetNamespace=\"" . $this->namespaces['tns'] . "\"";
5477 }
5478 $xml .= '>';
5479 // imports
5480 if (sizeof($this->import) > 0) {
5481 foreach ($this->import as $ns => $list) {
5482 foreach ($list as $ii) {
5483 if ($ii['location'] != '') {
5484 $xml .= '<import location="' . $ii['location'] . '" namespace="' . $ns . '" />';
5485 } else {
5486 $xml .= '<import namespace="' . $ns . '" />';
5487 }
5488 }
5489 }
5490 }
5491 // types
5492 if (count($this->schemas) >= 1) {
5493 $xml .= "\n<types>\n";
5494 foreach ($this->schemas as $ns => $list) {
5495 foreach ($list as $xs) {
5496 $xml .= $xs->serializeSchema();
5497 }
5498 }
5499 $xml .= '</types>';
5500 }
5501 // messages
5502 if (count($this->messages) >= 1) {
5503 foreach ($this->messages as $msgName => $msgParts) {
5504 $xml .= "\n<message name=\"" . $msgName . '">';
5505 if (is_array($msgParts)) {
5506 foreach ($msgParts as $partName => $partType) {
5507 // print 'serializing '.$partType.', sv: '.$this->XMLSchemaVersion.'<br>';
5508 if (strpos($partType, ':')) {
5509 $typePrefix = $this->getPrefixFromNamespace($this->getPrefix($partType));
5510 } elseif (isset($this->typemap[$this->namespaces['xsd']][$partType])) {
5511 // print 'checking typemap: '.$this->XMLSchemaVersion.'<br>';
5512 $typePrefix = 'xsd';
5513 } else {
5514 foreach ($this->typemap as $ns => $types) {
5515 if (isset($types[$partType])) {
5516 $typePrefix = $this->getPrefixFromNamespace($ns);
5517 }
5518 }
5519 if (!isset($typePrefix)) {
5520 die("$partType has no namespace!");
5521 }
5522 }
5523 $ns = $this->getNamespaceFromPrefix($typePrefix);
5524 $localPart = $this->getLocalPart($partType);
5525 $typeDef = $this->getTypeDef($localPart, $ns);
5526 if (($typeDef['typeClass'] ?? '') == 'element') {
5527 $elementortype = 'element';
5528 if (substr($localPart, -1) == '^') {
5529 $localPart = substr($localPart, 0, -1);
5530 }
5531 } else {
5532 $elementortype = 'type';
5533 }
5534 $xml .= "\n" . ' <part name="' . $partName . '" ' . $elementortype . '="' . $typePrefix . ':' . $localPart . '" />';
5535 }
5536 }
5537 $xml .= '</message>';
5538 }
5539 }
5540 // bindings & porttypes
5541 if (count($this->bindings) >= 1) {
5542 $binding_xml = '';
5543 $portType_xml = '';
5544 foreach ($this->bindings as $bindingName => $attrs) {
5545 $binding_xml .= "\n<binding name=\"" . $bindingName . '" type="tns:' . $attrs['portType'] . '">';
5546 $binding_xml .= "\n" . ' <soap:binding style="' . $attrs['style'] . '" transport="' . $attrs['transport'] . '"/>';
5547 $portType_xml .= "\n<portType name=\"" . $attrs['portType'] . '">';
5548 foreach ($attrs['operations'] as $opName => $opParts) {
5549 $binding_xml .= "\n" . ' <operation name="' . $opName . '">';
5550 $binding_xml .= "\n" . ' <soap:operation soapAction="' . $opParts['soapAction'] . '" style="' . $opParts['style'] . '"/>';
5551 if (isset($opParts['input']['encodingStyle']) && $opParts['input']['encodingStyle'] != '') {
5552 $enc_style = ' encodingStyle="' . $opParts['input']['encodingStyle'] . '"';
5553 } else {
5554 $enc_style = '';
5555 }
5556 $binding_xml .= "\n" . ' <input><soap:body use="' . $opParts['input']['use'] . '" namespace="' . $opParts['input']['namespace'] . '"' . $enc_style . '/></input>';
5557 if (isset($opParts['output']['encodingStyle']) && $opParts['output']['encodingStyle'] != '') {
5558 $enc_style = ' encodingStyle="' . $opParts['output']['encodingStyle'] . '"';
5559 } else {
5560 $enc_style = '';
5561 }
5562 $binding_xml .= "\n" . ' <output><soap:body use="' . $opParts['output']['use'] . '" namespace="' . $opParts['output']['namespace'] . '"' . $enc_style . '/></output>';
5563 $binding_xml .= "\n" . ' </operation>';
5564 $portType_xml .= "\n" . ' <operation name="' . $opParts['name'] . '"';
5565 if (isset($opParts['parameterOrder'])) {
5566 $portType_xml .= ' parameterOrder="' . $opParts['parameterOrder'] . '"';
5567 }
5568 $portType_xml .= '>';
5569 if (isset($opParts['documentation']) && $opParts['documentation'] != '') {
5570 $portType_xml .= "\n" . ' <documentation>' . htmlspecialchars($opParts['documentation']) . '</documentation>';
5571 }
5572 $portType_xml .= "\n" . ' <input message="tns:' . $opParts['input']['message'] . '"/>';
5573 $portType_xml .= "\n" . ' <output message="tns:' . $opParts['output']['message'] . '"/>';
5574 $portType_xml .= "\n" . ' </operation>';
5575 }
5576 $portType_xml .= "\n" . '</portType>';
5577 $binding_xml .= "\n" . '</binding>';
5578 }
5579 $xml .= $portType_xml . $binding_xml;
5580 }
5581 // services
5582 $xml .= "\n<service name=\"" . $this->serviceName . '">';
5583 $has_client = isset($_GET['client_id']);
5584 if (count($this->ports) >= 1) {
5585 foreach ($this->ports as $pName => $attrs) {
5586 $xml .= "\n" . ' <port name="' . $pName . '" binding="tns:' . $attrs['binding'] . '">';
5587 $locations = $attrs['location'];
5588 $locations = is_array($locations) ? $locations : [$locations];
5589 foreach ($locations as $location) {
5590 $address = $location . ($debug || $has_client ? "?" : "")
5591 . ($debug ? 'debug=1' : '') . ($debug && $has_client ? "&amp;" : "")
5592 . ($has_client ? 'client_id=' . $_GET['client_id'] : '');
5593 $xml .= "\n" . ' <soap:address location="' . $address . '"/>';
5594 }
5595 $xml .= "\n" . ' </port>';
5596 }
5597 }
5598
5599 $xml .= "\n" . '</service>';
5600 return $xml . "\n</definitions>";
5601 }
5602
5612 public function parametersMatchWrapped($type, &$parameters)
5613 {
5614 $this->debug("in parametersMatchWrapped type=$type, parameters=");
5615 $this->appendDebug($this->varDump($parameters));
5616
5617 // split type into namespace:unqualified-type
5618 if (strpos($type, ':')) {
5619 $uqType = substr($type, strrpos($type, ':') + 1);
5620 $ns = substr($type, 0, strrpos($type, ':'));
5621 $this->debug("in parametersMatchWrapped: got a prefixed type: $uqType, $ns");
5622 if ($this->getNamespaceFromPrefix($ns)) {
5623 $ns = $this->getNamespaceFromPrefix($ns);
5624 $this->debug("in parametersMatchWrapped: expanded prefixed type: $uqType, $ns");
5625 }
5626 } else {
5627 // TODO: should the type be compared to types in XSD, and the namespace
5628 // set to XSD if the type matches?
5629 $this->debug("in parametersMatchWrapped: No namespace for type $type");
5630 $ns = '';
5631 $uqType = $type;
5632 }
5633
5634 // get the type information
5635 if (!$typeDef = $this->getTypeDef($uqType, $ns)) {
5636 $this->debug("in parametersMatchWrapped: $type ($uqType) is not a supported type.");
5637 return false;
5638 }
5639 $this->debug("in parametersMatchWrapped: found typeDef=");
5640 $this->appendDebug($this->varDump($typeDef));
5641 if (substr($uqType, -1) == '^') {
5642 $uqType = substr($uqType, 0, -1);
5643 }
5644 $phpType = $typeDef['phpType'];
5645 $arrayType = (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : '');
5646 $this->debug("in parametersMatchWrapped: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: $arrayType");
5647
5648 // we expect a complexType or element of complexType
5649 if ($phpType != 'struct') {
5650 $this->debug("in parametersMatchWrapped: not a struct");
5651 return false;
5652 }
5653
5654 // see whether the parameter names match the elements
5655 if (isset($typeDef['elements']) && is_array($typeDef['elements'])) {
5656 $elements = 0;
5657 $matches = 0;
5658 $change = false;
5659 if ($this->isArraySimpleOrStruct($parameters) == 'arraySimple' && count($parameters) == count($typeDef['elements'])) {
5660 $this->debug("in parametersMatchWrapped: (wrapped return value kludge) correct number of elements in simple array, so change array and wrap");
5661 $change = true;
5662 }
5663 foreach ($typeDef['elements'] as $name => $attrs) {
5664 if ($change) {
5665 $this->debug("in parametersMatchWrapped: change parameter $element to name $name");
5666 $parameters[$name] = $parameters[$elements];
5667 unset($parameters[$elements]);
5668 $matches++;
5669 } elseif (isset($parameters[$name])) {
5670 $this->debug("in parametersMatchWrapped: have parameter named $name");
5671 $matches++;
5672 } else {
5673 $this->debug("in parametersMatchWrapped: do not have parameter named $name");
5674 }
5675 $elements++;
5676 }
5677
5678 $this->debug("in parametersMatchWrapped: $matches parameter names match $elements wrapped parameter names");
5679 if ($matches == 0) {
5680 return false;
5681 }
5682 return true;
5683 }
5684
5685 // since there are no elements for the type, if the user passed no
5686 // parameters, the parameters match wrapped.
5687 $this->debug("in parametersMatchWrapped: no elements type $ns:$uqType");
5688 return count($parameters) == 0;
5689 }
5690
5706 public function serializeRPCParameters($operation, $direction, $parameters, $bindingType = 'soap')
5707 {
5708 $this->debug("in serializeRPCParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion, bindingType=$bindingType");
5709 $this->appendDebug('parameters=' . $this->varDump($parameters));
5710
5711 if ($direction != 'input' && $direction != 'output') {
5712 $this->debug('The value of the \$direction argument needs to be either "input" or "output"');
5713 $this->setError('The value of the \$direction argument needs to be either "input" or "output"');
5714 return false;
5715 }
5716 if (!$opData = $this->getOperationData($operation, $bindingType)) {
5717 $this->debug('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType);
5718 $this->setError('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType);
5719 return false;
5720 }
5721 $this->debug('in serializeRPCParameters: opData:');
5722 $this->appendDebug($this->varDump($opData));
5723
5724 // Get encoding style for output and set to current
5725 $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
5726 if (($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {
5727 $encodingStyle = $opData['output']['encodingStyle'];
5728 $enc_style = $encodingStyle;
5729 }
5730
5731 // set input params
5732 $xml = '';
5733 if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) {
5734 $parts = &$opData[$direction]['parts'];
5735 $part_count = sizeof($parts);
5736 $style = $opData['style'];
5737 $use = $opData[$direction]['use'];
5738 $this->debug("have $part_count part(s) to serialize using $style/$use");
5739 if (is_array($parameters)) {
5740 $parametersArrayType = $this->isArraySimpleOrStruct($parameters);
5741 $parameter_count = count($parameters);
5742 $this->debug("have $parameter_count parameter(s) provided as $parametersArrayType to serialize");
5743 // check for Microsoft-style wrapped parameters
5744 if ($style == 'document' && $use == 'literal' && $part_count == 1 && isset($parts['parameters'])) {
5745 $this->debug('check whether the caller has wrapped the parameters');
5746 if ((($parametersArrayType == 'arrayStruct' || $parameter_count == 0) && !isset($parameters['parameters'])) || ($direction == 'output' && $parametersArrayType == 'arraySimple' && $parameter_count == 1)) {
5747 $this->debug('check whether caller\'s parameters match the wrapped ones');
5748 if ($this->parametersMatchWrapped($parts['parameters'], $parameters)) {
5749 $this->debug('wrap the parameters for the caller');
5750 $parameters = array('parameters' => $parameters);
5751 $parameter_count = 1;
5752 }
5753 }
5754 }
5755 foreach ($parts as $name => $type) {
5756 $this->debug("serializing part $name of type $type");
5757 // Track encoding style
5758 if (isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {
5759 $encodingStyle = $opData[$direction]['encodingStyle'];
5760 $enc_style = $encodingStyle;
5761 } else {
5762 $enc_style = false;
5763 }
5764 // NOTE: add error handling here
5765 // if serializeType returns false, then catch global error and fault
5766 if ($parametersArrayType == 'arraySimple') {
5767 $p = array_shift($parameters);
5768 $this->debug('calling serializeType w/indexed param');
5769 $xml .= $this->serializeType($name, $type, $p, $use, $enc_style);
5770 } elseif (isset($parameters[$name])) {
5771 $this->debug('calling serializeType w/named param');
5772 $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style);
5773 } else {
5774 // TODO: only send nillable
5775 $this->debug('calling serializeType w/null param');
5776 $xml .= $this->serializeType($name, $type, null, $use, $enc_style);
5777 }
5778 }
5779 } else {
5780 $this->debug('no parameters passed.');
5781 }
5782 }
5783 $this->debug("serializeRPCParameters returning: $xml");
5784 return $xml;
5785 }
5786
5801 public function serializeParameters($operation, $direction, $parameters)
5802 {
5803 $this->debug("in serializeParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion");
5804 $this->appendDebug('parameters=' . $this->varDump($parameters));
5805
5806 if ($direction != 'input' && $direction != 'output') {
5807 $this->debug('The value of the \$direction argument needs to be either "input" or "output"');
5808 $this->setError('The value of the \$direction argument needs to be either "input" or "output"');
5809 return false;
5810 }
5811 if (!$opData = $this->getOperationData($operation)) {
5812 $this->debug('Unable to retrieve WSDL data for operation: ' . $operation);
5813 $this->setError('Unable to retrieve WSDL data for operation: ' . $operation);
5814 return false;
5815 }
5816 $this->debug('opData:');
5817 $this->appendDebug($this->varDump($opData));
5818
5819 // Get encoding style for output and set to current
5820 $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
5821 if (($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {
5822 $encodingStyle = $opData['output']['encodingStyle'];
5823 $enc_style = $encodingStyle;
5824 }
5825
5826 // set input params
5827 $xml = '';
5828 if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) {
5829 $use = $opData[$direction]['use'];
5830 $this->debug("use=$use");
5831 $this->debug('got ' . count($opData[$direction]['parts']) . ' part(s)');
5832 if (is_array($parameters)) {
5833 $parametersArrayType = $this->isArraySimpleOrStruct($parameters);
5834 $this->debug('have ' . $parametersArrayType . ' parameters');
5835 foreach ($opData[$direction]['parts'] as $name => $type) {
5836 $this->debug('serializing part "' . $name . '" of type "' . $type . '"');
5837 // Track encoding style
5838 if (isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {
5839 $encodingStyle = $opData[$direction]['encodingStyle'];
5840 $enc_style = $encodingStyle;
5841 } else {
5842 $enc_style = false;
5843 }
5844 // NOTE: add error handling here
5845 // if serializeType returns false, then catch global error and fault
5846 if ($parametersArrayType == 'arraySimple') {
5847 $p = array_shift($parameters);
5848 $this->debug('calling serializeType w/indexed param');
5849 $xml .= $this->serializeType($name, $type, $p, $use, $enc_style);
5850 } elseif (isset($parameters[$name])) {
5851 $this->debug('calling serializeType w/named param');
5852 $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style);
5853 } else {
5854 // TODO: only send nillable
5855 $this->debug('calling serializeType w/null param');
5856 $xml .= $this->serializeType($name, $type, null, $use, $enc_style);
5857 }
5858 }
5859 } else {
5860 $this->debug('no parameters passed.');
5861 }
5862 }
5863 $this->debug("serializeParameters returning: $xml");
5864 return $xml;
5865 }
5866
5879 public function serializeType($name, $type, $value, $use = 'encoded', $encodingStyle = false, $unqualified = false)
5880 {
5881 $this->debug("in serializeType: name=$name, type=$type, use=$use, encodingStyle=$encodingStyle, unqualified=" . ($unqualified ? "unqualified" : "qualified"));
5882 $this->appendDebug("value=" . $this->varDump($value));
5883 if ($use == 'encoded' && $encodingStyle) {
5884 $encodingStyle = ' SOAP-ENV:encodingStyle="' . $encodingStyle . '"';
5885 }
5886
5887 // if a soapval has been supplied, let its type override the WSDL
5888 if (is_object($value) && get_class($value) == 'soapval') {
5889 if ($value->type_ns) {
5890 $type = $value->type_ns . ':' . $value->type;
5891 $forceType = true;
5892 $this->debug("in serializeType: soapval overrides type to $type");
5893 } elseif ($value->type) {
5894 $type = $value->type;
5895 $forceType = true;
5896 $this->debug("in serializeType: soapval overrides type to $type");
5897 } else {
5898 $forceType = false;
5899 $this->debug("in serializeType: soapval does not override type");
5900 }
5901 $attrs = $value->attributes;
5902 $value = $value->value;
5903 $this->debug("in serializeType: soapval overrides value to $value");
5904 if ($attrs) {
5905 if (!is_array($value)) {
5906 $value['!'] = $value;
5907 }
5908 foreach ($attrs as $n => $v) {
5909 $value['!' . $n] = $v;
5910 }
5911 $this->debug("in serializeType: soapval provides attributes");
5912 }
5913 } else {
5914 $forceType = false;
5915 }
5916
5917 $xml = '';
5918 if (strpos($type, ':')) {
5919 $uqType = substr($type, strrpos($type, ':') + 1);
5920 $ns = substr($type, 0, strrpos($type, ':'));
5921 $this->debug("in serializeType: got a prefixed type: $uqType, $ns");
5922 if ($this->getNamespaceFromPrefix($ns)) {
5923 $ns = $this->getNamespaceFromPrefix($ns);
5924 $this->debug("in serializeType: expanded prefixed type: $uqType, $ns");
5925 }
5926
5927 if ($ns == $this->XMLSchemaVersion || $ns == 'http://schemas.xmlsoap.org/soap/encoding/') {
5928 $this->debug('in serializeType: type namespace indicates XML Schema or SOAP Encoding type');
5929 if ($unqualified && $use == 'literal') {
5930 $elementNS = " xmlns=\"\"";
5931 } else {
5932 $elementNS = '';
5933 }
5934 if (is_null($value)) {
5935 if ($use == 'literal') {
5936 // TODO: depends on minOccurs
5937 $xml = "<$name$elementNS/>";
5938 } else {
5939 // TODO: depends on nillable, which should be checked before calling this method
5940 $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>";
5941 }
5942 $this->debug("in serializeType: returning: $xml");
5943 return $xml;
5944 }
5945 if ($uqType == 'Array') {
5946 // JBoss/Axis does this sometimes
5947 return $this->serialize_val($value, $name, false, false, false, false, $use);
5948 }
5949 if ($uqType == 'boolean') {
5950 if ((is_string($value) && $value == 'false') || (! $value)) {
5951 $value = 'false';
5952 } else {
5953 $value = 'true';
5954 }
5955 }
5956 if ($uqType == 'string' && gettype($value) == 'string') {
5957 $value = $this->expandEntities($value);
5958 }
5959 if (($uqType == 'long' || $uqType == 'unsignedLong') && gettype($value) == 'double') {
5960 $value = sprintf("%.0lf", $value);
5961 }
5962 // it's a scalar
5963 // TODO: what about null/nil values?
5964 // check type isn't a custom type extending xmlschema namespace
5965 if (!$this->getTypeDef($uqType, $ns)) {
5966 if ($use == 'literal') {
5967 if ($forceType) {
5968 $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>";
5969 } else {
5970 $xml = "<$name$elementNS>$value</$name>";
5971 }
5972 } else {
5973 $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>";
5974 }
5975 $this->debug("in serializeType: returning: $xml");
5976 return $xml;
5977 }
5978 $this->debug('custom type extends XML Schema or SOAP Encoding namespace (yuck)');
5979 } elseif ($ns == 'http://xml.apache.org/xml-soap') {
5980 $this->debug('in serializeType: appears to be Apache SOAP type');
5981 if ($uqType == 'Map') {
5982 $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap');
5983 if (! $tt_prefix) {
5984 $this->debug('in serializeType: Add namespace for Apache SOAP type');
5985 $tt_prefix = 'ns' . rand(1000, 9999);
5986 $this->namespaces[$tt_prefix] = 'http://xml.apache.org/xml-soap';
5987 // force this to be added to usedNamespaces
5988 $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap');
5989 }
5990 $contents = '';
5991 foreach ($value as $k => $v) {
5992 $this->debug("serializing map element: key $k, value $v");
5993 $contents .= '<item>';
5994 $contents .= $this->serialize_val($k, 'key', false, false, false, false, $use);
5995 $contents .= $this->serialize_val($v, 'value', false, false, false, false, $use);
5996 $contents .= '</item>';
5997 }
5998 if ($use == 'literal') {
5999 if ($forceType) {
6000 $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\">$contents</$name>";
6001 } else {
6002 $xml = "<$name>$contents</$name>";
6003 }
6004 } else {
6005 $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\"$encodingStyle>$contents</$name>";
6006 }
6007 $this->debug("in serializeType: returning: $xml");
6008 return $xml;
6009 }
6010 $this->debug('in serializeType: Apache SOAP type, but only support Map');
6011 }
6012 } else {
6013 // TODO: should the type be compared to types in XSD, and the namespace
6014 // set to XSD if the type matches?
6015 $this->debug("in serializeType: No namespace for type $type");
6016 $ns = '';
6017 $uqType = $type;
6018 }
6019 if (!$typeDef = $this->getTypeDef($uqType, $ns)) {
6020 $this->setError("$type ($uqType) is not a supported type.");
6021 $this->debug("in serializeType: $type ($uqType) is not a supported type.");
6022 return false;
6023 } else {
6024 $this->debug("in serializeType: found typeDef");
6025 $this->appendDebug('typeDef=' . $this->varDump($typeDef));
6026 if (substr($uqType, -1) == '^') {
6027 $uqType = substr($uqType, 0, -1);
6028 }
6029 }
6030 $phpType = $typeDef['phpType'];
6031 $this->debug("in serializeType: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: " . (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : ''));
6032 // if php type == struct, map value to the <all> element names
6033 if ($phpType == 'struct') {
6034 if (isset($typeDef['typeClass']) && $typeDef['typeClass'] == 'element') {
6035 $elementName = $uqType;
6036 if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
6037 $elementNS = " xmlns=\"$ns\"";
6038 } else {
6039 $elementNS = " xmlns=\"\"";
6040 }
6041 } else {
6042 $elementName = $name;
6043 if ($unqualified) {
6044 $elementNS = " xmlns=\"\"";
6045 } else {
6046 $elementNS = '';
6047 }
6048 }
6049 if (is_null($value)) {
6050 if ($use == 'literal') {
6051 // TODO: depends on minOccurs
6052 $xml = "<$elementName$elementNS/>";
6053 } else {
6054 $xml = "<$elementName$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>";
6055 }
6056 $this->debug("in serializeType: returning: $xml");
6057 return $xml;
6058 }
6059 if (is_object($value)) {
6060 $value = get_object_vars($value);
6061 }
6062 if (is_array($value)) {
6063 $elementAttrs = $this->serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType);
6064 if ($use == 'literal') {
6065 if ($forceType) {
6066 $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">";
6067 } else {
6068 $xml = "<$elementName$elementNS$elementAttrs>";
6069 }
6070 } else {
6071 $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>";
6072 }
6073
6074 $xml .= $this->serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use, $encodingStyle);
6075 $xml .= "</$elementName>";
6076 } else {
6077 $this->debug("in serializeType: phpType is struct, but value is not an array");
6078 $this->setError("phpType is struct, but value is not an array: see debug output for details");
6079 $xml = '';
6080 }
6081 } elseif ($phpType == 'array') {
6082 if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
6083 $elementNS = " xmlns=\"$ns\"";
6084 } else {
6085 if ($unqualified) {
6086 $elementNS = " xmlns=\"\"";
6087 } else {
6088 $elementNS = '';
6089 }
6090 }
6091 if (is_null($value)) {
6092 if ($use == 'literal') {
6093 // TODO: depends on minOccurs
6094 $xml = "<$name$elementNS/>";
6095 } else {
6096 $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" .
6097 $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') .
6098 ":Array\" " .
6099 $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') .
6100 ':arrayType="' .
6101 $this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType'])) .
6102 ':' .
6103 $this->getLocalPart($typeDef['arrayType']) . "[0]\"/>";
6104 }
6105 $this->debug("in serializeType: returning: $xml");
6106 return $xml;
6107 }
6108 if (isset($typeDef['multidimensional'])) {
6109 $nv = array();
6110 foreach ($value as $v) {
6111 $cols = ',' . sizeof($v);
6112 $nv = array_merge($nv, $v);
6113 }
6114 $value = $nv;
6115 } else {
6116 $cols = '';
6117 }
6118 if (is_array($value) && sizeof($value) >= 1) {
6119 $rows = sizeof($value);
6120 $contents = '';
6121 foreach ($value as $k => $v) {
6122 $this->debug("serializing array element: $k, $v of type: $typeDef[arrayType]");
6123 //if (strpos($typeDef['arrayType'], ':') ) {
6124 if (!in_array($typeDef['arrayType'], $this->typemap['http://www.w3.org/2001/XMLSchema'])) {
6125 $contents .= $this->serializeType('item', $typeDef['arrayType'], $v, $use);
6126 } else {
6127 $contents .= $this->serialize_val($v, 'item', $typeDef['arrayType'], null, $this->XMLSchemaVersion, false, $use);
6128 }
6129 }
6130 } else {
6131 $rows = 0;
6132 $contents = null;
6133 }
6134 // TODO: for now, an empty value will be serialized as a zero element
6135 // array. Revisit this when coding the handling of null/nil values.
6136 if ($use == 'literal') {
6137 $xml = "<$name$elementNS>"
6138 . $contents
6139 . "</$name>";
6140 } else {
6141 $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') . ':Array" ' .
6142 $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/')
6143 . ':arrayType="'
6144 . $this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType']))
6145 . ":" . $this->getLocalPart($typeDef['arrayType']) . "[$rows$cols]\">"
6146 . $contents
6147 . "</$name>";
6148 }
6149 } elseif ($phpType == 'scalar') {
6150 if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
6151 $elementNS = " xmlns=\"$ns\"";
6152 } else {
6153 if ($unqualified) {
6154 $elementNS = " xmlns=\"\"";
6155 } else {
6156 $elementNS = '';
6157 }
6158 }
6159 if ($use == 'literal') {
6160 if ($forceType) {
6161 $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>";
6162 } else {
6163 $xml = "<$name$elementNS>$value</$name>";
6164 }
6165 } else {
6166 $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>";
6167 }
6168 }
6169 $this->debug("in serializeType: returning: $xml");
6170 return $xml;
6171 }
6172
6183 public function serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType)
6184 {
6185 $xml = '';
6186 if (isset($typeDef['attrs']) && is_array($typeDef['attrs'])) {
6187 $this->debug("serialize attributes for XML Schema type $ns:$uqType");
6188 if (is_array($value)) {
6189 $xvalue = $value;
6190 } elseif (is_object($value)) {
6191 $xvalue = get_object_vars($value);
6192 } else {
6193 $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType");
6194 $xvalue = array();
6195 }
6196 foreach ($typeDef['attrs'] as $aName => $attrs) {
6197 if (isset($xvalue['!' . $aName])) {
6198 $xname = '!' . $aName;
6199 $this->debug("value provided for attribute $aName with key $xname");
6200 } elseif (isset($xvalue[$aName])) {
6201 $xname = $aName;
6202 $this->debug("value provided for attribute $aName with key $xname");
6203 } elseif (isset($attrs['default'])) {
6204 $xname = '!' . $aName;
6205 $xvalue[$xname] = $attrs['default'];
6206 $this->debug('use default value of ' . $xvalue[$aName] . ' for attribute ' . $aName);
6207 } else {
6208 $xname = '';
6209 $this->debug("no value provided for attribute $aName");
6210 }
6211 if ($xname) {
6212 $xml .= " $aName=\"" . $this->expandEntities($xvalue[$xname]) . "\"";
6213 }
6214 }
6215 } else {
6216 $this->debug("no attributes to serialize for XML Schema type $ns:$uqType");
6217 }
6218 if (isset($typeDef['extensionBase'])) {
6219 $ns = $this->getPrefix($typeDef['extensionBase']);
6220 $uqType = $this->getLocalPart($typeDef['extensionBase']);
6221 if ($this->getNamespaceFromPrefix($ns)) {
6222 $ns = $this->getNamespaceFromPrefix($ns);
6223 }
6224 if ($typeDef = $this->getTypeDef($uqType, $ns)) {
6225 $this->debug("serialize attributes for extension base $ns:$uqType");
6226 $xml .= $this->serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType);
6227 } else {
6228 $this->debug("extension base $ns:$uqType is not a supported type");
6229 }
6230 }
6231 return $xml;
6232 }
6233
6246 public function serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use = 'encoded', $encodingStyle = false)
6247 {
6248 $xml = '';
6249 if (isset($typeDef['elements']) && is_array($typeDef['elements'])) {
6250 $this->debug("in serializeComplexTypeElements, serialize elements for XML Schema type $ns:$uqType");
6251 if (is_array($value)) {
6252 $xvalue = $value;
6253 } elseif (is_object($value)) {
6254 $xvalue = get_object_vars($value);
6255 } else {
6256 $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType");
6257 $xvalue = array();
6258 }
6259 // toggle whether all elements are present - ideally should validate against schema
6260 if (count($typeDef['elements']) != count($xvalue)) {
6261 $optionals = true;
6262 }
6263 foreach ($typeDef['elements'] as $eName => $attrs) {
6264 if (!isset($xvalue[$eName])) {
6265 if (isset($attrs['default'])) {
6266 $xvalue[$eName] = $attrs['default'];
6267 $this->debug('use default value of ' . $xvalue[$eName] . ' for element ' . $eName);
6268 }
6269 }
6270 // if user took advantage of a minOccurs=0, then only serialize named parameters
6271 if (isset($optionals)
6272 && (!isset($xvalue[$eName]))
6273 && ((!isset($attrs['nillable'])) || $attrs['nillable'] != 'true')
6274 ) {
6275 if (isset($attrs['minOccurs']) && $attrs['minOccurs'] <> '0') {
6276 $this->debug("apparent error: no value provided for element $eName with minOccurs=" . $attrs['minOccurs']);
6277 }
6278 // do nothing
6279 $this->debug("no value provided for complexType element $eName and element is not nillable, so serialize nothing");
6280 } else {
6281 // get value
6282 if (isset($xvalue[$eName])) {
6283 $v = $xvalue[$eName];
6284 } else {
6285 $v = null;
6286 }
6287 if (isset($attrs['form'])) {
6288 $unqualified = ($attrs['form'] == 'unqualified');
6289 } else {
6290 $unqualified = false;
6291 }
6292 if (isset($attrs['maxOccurs']) && ($attrs['maxOccurs'] == 'unbounded' || $attrs['maxOccurs'] > 1) && isset($v) && is_array($v) && $this->isArraySimpleOrStruct($v) == 'arraySimple') {
6293 $vv = $v;
6294 foreach ($vv as $k => $v) {
6295 if (isset($attrs['type']) || isset($attrs['ref'])) {
6296 // serialize schema-defined type
6297 $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
6298 } else {
6299 // serialize generic type (can this ever really happen?)
6300 $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use");
6301 $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use);
6302 }
6303 }
6304 } else {
6305 if (isset($attrs['type']) || isset($attrs['ref'])) {
6306 // serialize schema-defined type
6307 $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
6308 } else {
6309 // serialize generic type (can this ever really happen?)
6310 $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use");
6311 $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use);
6312 }
6313 }
6314 }
6315 }
6316 } else {
6317 $this->debug("no elements to serialize for XML Schema type $ns:$uqType");
6318 }
6319 if (isset($typeDef['extensionBase'])) {
6320 $ns = $this->getPrefix($typeDef['extensionBase']);
6321 $uqType = $this->getLocalPart($typeDef['extensionBase']);
6322 if ($this->getNamespaceFromPrefix($ns)) {
6323 $ns = $this->getNamespaceFromPrefix($ns);
6324 }
6325 if ($typeDef = $this->getTypeDef($uqType, $ns)) {
6326 $this->debug("serialize elements for extension base $ns:$uqType");
6327 $xml .= $this->serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use, $encodingStyle);
6328 } else {
6329 $this->debug("extension base $ns:$uqType is not a supported type");
6330 }
6331 }
6332 return $xml;
6333 }
6334
6349 public function addComplexType($name, $typeClass = 'complexType', $phpType = 'array', $compositor = '', $restrictionBase = '', $elements = array(), $attrs = array(), $arrayType = '')
6350 {
6351 if (count($elements) > 0) {
6352 $eElements = array();
6353 foreach ($elements as $n => $e) {
6354 // expand each element
6355 $ee = array();
6356 foreach ($e as $k => $v) {
6357 $k = strpos($k, ':') ? $this->expandQname($k) : $k;
6358 $v = strpos($v, ':') ? $this->expandQname($v) : $v;
6359 $ee[$k] = $v;
6360 }
6361 $eElements[$n] = $ee;
6362 }
6363 $elements = $eElements;
6364 }
6365
6366 if (count($attrs) > 0) {
6367 foreach ($attrs as $n => $a) {
6368 // expand each attribute
6369 foreach ($a as $k => $v) {
6370 $k = strpos($k, ':') ? $this->expandQname($k) : $k;
6371 $v = strpos($v, ':') ? $this->expandQname($v) : $v;
6372 $aa[$k] = $v;
6373 }
6374 $eAttrs[$n] = $aa;
6375 }
6376 $attrs = $eAttrs;
6377 }
6378
6379 $restrictionBase = strpos($restrictionBase, ':') ? $this->expandQname($restrictionBase) : $restrictionBase;
6380 $arrayType = strpos($arrayType, ':') ? $this->expandQname($arrayType) : $arrayType;
6381
6382 $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
6383 $this->schemas[$typens][0]->addComplexType($name, $typeClass, $phpType, $compositor, $restrictionBase, $elements, $attrs, $arrayType);
6384 }
6385
6397 public function addSimpleType($name, $restrictionBase = '', $typeClass = 'simpleType', $phpType = 'scalar', $enumeration = array())
6398 {
6399 $restrictionBase = strpos($restrictionBase, ':') ? $this->expandQname($restrictionBase) : $restrictionBase;
6400
6401 $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
6402 $this->schemas[$typens][0]->addSimpleType($name, $restrictionBase, $typeClass, $phpType, $enumeration);
6403 }
6404
6412 public function addElement($attrs)
6413 {
6414 $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
6415 $this->schemas[$typens][0]->addElement($attrs);
6416 }
6417
6432 public function addOperation($name, $in = false, $out = false, $namespace = false, $soapaction = false, $style = 'rpc', $use = 'encoded', $documentation = '', $encodingStyle = '')
6433 {
6434 if ($use == 'encoded' && $encodingStyle == '') {
6435 $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
6436 }
6437
6438 if ($style == 'document') {
6439 $elements = array();
6440 foreach ($in as $n => $t) {
6441 $elements[$n] = array('name' => $n, 'type' => $t);
6442 }
6443 $this->addComplexType($name . 'RequestType', 'complexType', 'struct', 'all', '', $elements);
6444 $this->addElement(array('name' => $name, 'type' => $name . 'RequestType'));
6445 $in = array('parameters' => 'tns:' . $name . '^');
6446
6447 $elements = array();
6448 foreach ($out as $n => $t) {
6449 $elements[$n] = array('name' => $n, 'type' => $t);
6450 }
6451 $this->addComplexType($name . 'ResponseType', 'complexType', 'struct', 'all', '', $elements);
6452 $this->addElement(array('name' => $name . 'Response', 'type' => $name . 'ResponseType', 'form' => 'qualified'));
6453 $out = array('parameters' => 'tns:' . $name . 'Response' . '^');
6454 }
6455
6456 // get binding
6457 $this->bindings[ $this->serviceName . 'Binding' ]['operations'][$name] =
6458 array(
6459 'name' => $name,
6460 'binding' => $this->serviceName . 'Binding',
6461 'endpoint' => $this->endpoint,
6462 'soapAction' => $soapaction,
6463 'style' => $style,
6464 'input' => array(
6465 'use' => $use,
6466 'namespace' => $namespace,
6467 'encodingStyle' => $encodingStyle,
6468 'message' => $name . 'Request',
6469 'parts' => $in),
6470 'output' => array(
6471 'use' => $use,
6472 'namespace' => $namespace,
6473 'encodingStyle' => $encodingStyle,
6474 'message' => $name . 'Response',
6475 'parts' => $out),
6476 'namespace' => $namespace,
6477 'transport' => 'http://schemas.xmlsoap.org/soap/http',
6478 'documentation' => $documentation);
6479 // add portTypes
6480 // add messages
6481 if ($in) {
6482 foreach ($in as $pName => $pType) {
6483 if (strpos($pType, ':')) {
6484 $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)) . ":" . $this->getLocalPart($pType);
6485 }
6486 $this->messages[$name . 'Request'][$pName] = $pType;
6487 }
6488 } else {
6489 $this->messages[$name . 'Request'] = '0';
6490 }
6491 if ($out) {
6492 foreach ($out as $pName => $pType) {
6493 if (strpos($pType, ':')) {
6494 $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)) . ":" . $this->getLocalPart($pType);
6495 }
6496 $this->messages[$name . 'Response'][$pName] = $pType;
6497 }
6498 } else {
6499 $this->messages[$name . 'Response'] = '0';
6500 }
6501 return true;
6502 }
6503}
6504?><?php
6505
6506
6507
6517class nusoap_parser extends nusoap_base
6518{
6519 public $methodNamespace;
6520 public $parser;
6521 public $xml = '';
6522 public $xml_encoding = '';
6523 public $method = '';
6524 public $root_struct = '';
6525 public $root_struct_name = '';
6526 public $root_struct_namespace = '';
6527 public $root_header = '';
6528 public $document = ''; // incoming SOAP body (text)
6529 // determines where in the message we are (envelope,header,body,method)
6530 public $status = '';
6531 public $position = 0;
6532 public $depth = 0;
6533 public $default_namespace = '';
6534 public $namespaces = array();
6535 public $message = array();
6536 public $parent = '';
6537 public $fault = false;
6538 public $fault_code = '';
6539 public $fault_str = '';
6540 public $fault_detail = '';
6541 public $depth_array = array();
6542 public $debug_flag = true;
6543 public $soapresponse = null; // parsed SOAP Body
6544 public $soapheader = null; // parsed SOAP Header
6545 public $responseHeaders = ''; // incoming SOAP headers (text)
6546 public $body_position = 0;
6547 // for multiref parsing:
6548 // array of id => pos
6549 public $ids = array();
6550 // array of id => hrefs => pos
6551 public $multirefs = array();
6552 // toggle for auto-decoding element content
6553 public $decode_utf8 = true;
6554
6564 public function __construct($xml, $encoding = 'UTF-8', $method = '', $decode_utf8 = true)
6565 {
6567 $this->xml = $xml;
6568 $this->xml_encoding = $encoding;
6569 $this->method = $method;
6570 $this->decode_utf8 = $decode_utf8;
6571
6572 // Check whether content has been read.
6573 if (!empty($xml)) {
6574 // Check XML encoding
6575 $pos_xml = strpos($xml, '<?xml');
6576 if ($pos_xml !== false) {
6577 $xml_decl = substr($xml, $pos_xml, strpos($xml, '?>', $pos_xml + 2) - $pos_xml + 1);
6578 if (preg_match("/encoding=[\"']([^\"']*)[\"']/", $xml_decl, $res)) {
6579 $xml_encoding = $res[1];
6580 if (strtoupper($xml_encoding) != $encoding) {
6581 $err = "Charset from HTTP Content-Type '" . $encoding . "' does not match encoding from XML declaration '" . $xml_encoding . "'";
6582 $this->debug($err);
6583 if ($encoding != 'ISO-8859-1' || strtoupper($xml_encoding) != 'UTF-8') {
6584 $this->setError($err);
6585 return;
6586 }
6587 // when HTTP says ISO-8859-1 (the default) and XML says UTF-8 (the typical), assume the other endpoint is just sloppy and proceed
6588 } else {
6589 $this->debug('Charset from HTTP Content-Type matches encoding from XML declaration');
6590 }
6591 } else {
6592 $this->debug('No encoding specified in XML declaration');
6593 }
6594 } else {
6595 $this->debug('No XML declaration');
6596 }
6597 $this->debug('Entering nusoap_parser(), length=' . strlen($xml) . ', encoding=' . $encoding);
6598 // Create an XML parser - why not xml_parser_create_ns?
6599 $this->parser = xml_parser_create($this->xml_encoding);
6600 // Set the options for parsing the XML data.
6601 //xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
6602 xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
6603 xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, $this->xml_encoding);
6604 // Set the object for the parser.
6605 // Set the element handlers for the parser.
6606 xml_set_element_handler($this->parser, $this->start_element(...), $this->end_element(...));
6607 xml_set_character_data_handler($this->parser, $this->character_data(...));
6608
6609 // Parse the XML file.
6610 if (!xml_parse($this->parser, $xml, true)) {
6611 // Display an error message.
6612 $err = sprintf(
6613 'XML error parsing SOAP payload on line %d: %s',
6614 xml_get_current_line_number($this->parser),
6615 xml_error_string(xml_get_error_code($this->parser))
6616 );
6617 $this->debug($err);
6618 $this->debug("XML payload:\n" . $xml);
6619 $this->setError($err);
6620 } else {
6621 $this->debug('parsed successfully, found root struct: ' . $this->root_struct . ' of name ' . $this->root_struct_name);
6622 // get final value
6623 $this->soapresponse = $this->message[$this->root_struct]['result'];
6624 // get header value
6625 if ($this->root_header != '' && isset($this->message[$this->root_header]['result'])) {
6626 $this->soapheader = $this->message[$this->root_header]['result'];
6627 }
6628 // resolve hrefs/ids
6629 if (sizeof($this->multirefs) > 0) {
6630 foreach ($this->multirefs as $id => $hrefs) {
6631 $this->debug('resolving multirefs for id: ' . $id);
6632 $idVal = $this->buildVal($this->ids[$id]);
6633 if (is_array($idVal) && isset($idVal['!id'])) {
6634 unset($idVal['!id']);
6635 }
6636 foreach ($hrefs as $refPos => $ref) {
6637 $this->debug('resolving href at pos ' . $refPos);
6638 $this->multirefs[$id][$refPos] = $idVal;
6639 }
6640 }
6641 }
6642 }
6643 xml_parser_free($this->parser);
6644 } else {
6645 $this->debug('xml was empty, didn\'t parse!');
6646 $this->setError('xml was empty, didn\'t parse!');
6647 }
6648 }
6649
6658 public function start_element($parser, $name, $attrs)
6659 {
6660 // position in a total number of elements, starting from 0
6661 // update class level pos
6662 $pos = $this->position++;
6663 // and set mine
6664 $this->message[$pos] = array('pos' => $pos,'children' => '','cdata' => '');
6665 // depth = how many levels removed from root?
6666 // set mine as current global depth and increment global depth value
6667 $this->message[$pos]['depth'] = $this->depth++;
6668
6669 // else add self as child to whoever the current parent is
6670 if ($pos != 0) {
6671 $this->message[$this->parent]['children'] .= '|' . $pos;
6672 }
6673 // set my parent
6674 $this->message[$pos]['parent'] = $this->parent;
6675 // set self as current parent
6676 $this->parent = $pos;
6677 // set self as current value for this depth
6678 $this->depth_array[$this->depth] = $pos;
6679 // get element prefix
6680 if (strpos($name, ':')) {
6681 // get ns prefix
6682 $prefix = substr($name, 0, strpos($name, ':'));
6683 // get unqualified name
6684 $name = substr(strstr($name, ':'), 1);
6685 }
6686 // set status
6687 if ($name == 'Envelope') {
6688 $this->status = 'envelope';
6689 } elseif ($name == 'Header' && $this->status = 'envelope') {
6690 $this->root_header = $pos;
6691 $this->status = 'header';
6692 } elseif ($name == 'Body' && $this->status = 'envelope') {
6693 $this->status = 'body';
6694 $this->body_position = $pos;
6695 // set method
6696 } elseif ($this->status == 'body' && $pos == ($this->body_position + 1)) {
6697 $this->status = 'method';
6698 $this->root_struct_name = $name;
6699 $this->root_struct = $pos;
6700 $this->message[$pos]['type'] = 'struct';
6701 $this->debug("found root struct $this->root_struct_name, pos $this->root_struct");
6702 }
6703 // set my status
6704 $this->message[$pos]['status'] = $this->status;
6705 // set name
6706 $this->message[$pos]['name'] = htmlspecialchars($name);
6707 // set attrs
6708 $this->message[$pos]['attrs'] = $attrs;
6709
6710 // loop through atts, logging ns and type declarations
6711 $attstr = '';
6712 foreach ($attrs as $key => $value) {
6713 $key_prefix = $this->getPrefix($key);
6714 $key_localpart = $this->getLocalPart($key);
6715 // if ns declarations, add to class level array of valid namespaces
6716 if ($key_prefix == 'xmlns') {
6717 if (preg_match('/^http:\/\/www.w3.org\/[0-9]{4}\/XMLSchema$/', $value)) {
6718 $this->XMLSchemaVersion = $value;
6719 $this->namespaces['xsd'] = $this->XMLSchemaVersion;
6720 $this->namespaces['xsi'] = $this->XMLSchemaVersion . '-instance';
6721 }
6722 $this->namespaces[$key_localpart] = $value;
6723 // set method namespace
6724 if ($name == $this->root_struct_name) {
6725 $this->methodNamespace = $value;
6726 }
6727 // if it's a type declaration, set type
6728 } elseif ($key_localpart == 'type') {
6729 if (isset($this->message[$pos]['type']) && $this->message[$pos]['type'] == 'array') {
6730 // do nothing: already processed arrayType
6731 } else {
6732 $value_prefix = $this->getPrefix($value);
6733 $value_localpart = $this->getLocalPart($value);
6734 $this->message[$pos]['type'] = $value_localpart;
6735 $this->message[$pos]['typePrefix'] = $value_prefix;
6736 if (isset($this->namespaces[$value_prefix])) {
6737 $this->message[$pos]['type_namespace'] = $this->namespaces[$value_prefix];
6738 } elseif (isset($attrs['xmlns:' . $value_prefix])) {
6739 $this->message[$pos]['type_namespace'] = $attrs['xmlns:' . $value_prefix];
6740 }
6741 // should do something here with the namespace of specified type?
6742 }
6743 } elseif ($key_localpart == 'arrayType') {
6744 $this->message[$pos]['type'] = 'array';
6745 /* do arrayType ereg here
6746 [1] arrayTypeValue ::= atype asize
6747 [2] atype ::= QName rank*
6748 [3] rank ::= '[' (',')* ']'
6749 [4] asize ::= '[' length~ ']'
6750 [5] length ::= nextDimension* Digit+
6751 [6] nextDimension ::= Digit+ ','
6752 */
6753 $expr = '/([A-Za-z0-9_]+):([A-Za-z]+[A-Za-z0-9_]+)\[([0-9]+),?([0-9]*)\]/';
6754 if (preg_match($expr, $value, $regs)) {
6755 $this->message[$pos]['typePrefix'] = $regs[1];
6756 $this->message[$pos]['arrayTypePrefix'] = $regs[1];
6757 if (isset($this->namespaces[$regs[1]])) {
6758 $this->message[$pos]['arrayTypeNamespace'] = $this->namespaces[$regs[1]];
6759 } elseif (isset($attrs['xmlns:' . $regs[1]])) {
6760 $this->message[$pos]['arrayTypeNamespace'] = $attrs['xmlns:' . $regs[1]];
6761 }
6762 $this->message[$pos]['arrayType'] = $regs[2];
6763 $this->message[$pos]['arraySize'] = $regs[3];
6764 $this->message[$pos]['arrayCols'] = $regs[4];
6765 }
6766 // specifies nil value (or not)
6767 } elseif ($key_localpart == 'nil') {
6768 $this->message[$pos]['nil'] = ($value == 'true' || $value == '1');
6769 // some other attribute
6770 } elseif ($key != 'href' && $key != 'xmlns' && $key_localpart != 'encodingStyle' && $key_localpart != 'root') {
6771 $this->message[$pos]['xattrs']['!' . $key] = $value;
6772 }
6773
6774 if ($key == 'xmlns') {
6775 $this->default_namespace = $value;
6776 }
6777 // log id
6778 if ($key == 'id') {
6779 $this->ids[$value] = $pos;
6780 }
6781 // root
6782 if ($key_localpart == 'root' && $value == 1) {
6783 $this->status = 'method';
6784 $this->root_struct_name = $name;
6785 $this->root_struct = $pos;
6786 $this->debug("found root struct $this->root_struct_name, pos $pos");
6787 }
6788 // for doclit
6789 $attstr .= " $key=\"$value\"";
6790 }
6791 // get namespace - must be done after namespace atts are processed
6792 if (isset($prefix)) {
6793 $this->message[$pos]['namespace'] = $this->namespaces[$prefix];
6794 $this->default_namespace = $this->namespaces[$prefix];
6795 } else {
6796 $this->message[$pos]['namespace'] = $this->default_namespace;
6797 }
6798 if ($this->status == 'header') {
6799 if ($this->root_header != $pos) {
6800 $this->responseHeaders .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>";
6801 }
6802 } elseif ($this->root_struct_name != '') {
6803 $this->document .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>";
6804 }
6805 }
6806
6814 public function end_element($parser, $name)
6815 {
6816 // position of current element is equal to the last value left in depth_array for my depth
6817 $pos = $this->depth_array[$this->depth--];
6818
6819 // get element prefix
6820 if (strpos($name, ':')) {
6821 // get ns prefix
6822 $prefix = substr($name, 0, strpos($name, ':'));
6823 // get unqualified name
6824 $name = substr(strstr($name, ':'), 1);
6825 }
6826
6827 // build to native type
6828 if (isset($this->body_position) && $pos > $this->body_position) {
6829 // deal w/ multirefs
6830 if (isset($this->message[$pos]['attrs']['href'])) {
6831 // get id
6832 $id = substr($this->message[$pos]['attrs']['href'], 1);
6833 // add placeholder to href array
6834 $this->multirefs[$id][$pos] = 'placeholder';
6835 // add set a reference to it as the result value
6836 $this->message[$pos]['result'] = & $this->multirefs[$id][$pos];
6837 // build complexType values
6838 } elseif ($this->message[$pos]['children'] != '') {
6839 // if result has already been generated (struct/array)
6840 if (!isset($this->message[$pos]['result'])) {
6841 $this->message[$pos]['result'] = $this->buildVal($pos);
6842 }
6843 // build complexType values of attributes and possibly simpleContent
6844 } elseif (isset($this->message[$pos]['xattrs'])) {
6845 if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) {
6846 $this->message[$pos]['xattrs']['!'] = null;
6847 } elseif (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') {
6848 if (isset($this->message[$pos]['type'])) {
6849 $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'] : '');
6850 } else {
6851 $parent = $this->message[$pos]['parent'];
6852 if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
6853 $this->message[$pos]['xattrs']['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
6854 } else {
6855 $this->message[$pos]['xattrs']['!'] = $this->message[$pos]['cdata'];
6856 }
6857 }
6858 }
6859 $this->message[$pos]['result'] = $this->message[$pos]['xattrs'];
6860 // set value of simpleType (or nil complexType)
6861 } else {
6862 //$this->debug('adding data for scalar value '.$this->message[$pos]['name'].' of value '.$this->message[$pos]['cdata']);
6863 if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) {
6864 $this->message[$pos]['xattrs']['!'] = null;
6865 } elseif (isset($this->message[$pos]['type'])) {
6866 $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'] : '');
6867 } else {
6868 $parent = $this->message[$pos]['parent'];
6869 if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
6870 $this->message[$pos]['result'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
6871 } else {
6872 $this->message[$pos]['result'] = $this->message[$pos]['cdata'];
6873 }
6874 }
6875
6876 /* add value to parent's result, if parent is struct/array
6877 $parent = $this->message[$pos]['parent'];
6878 if($this->message[$parent]['type'] != 'map'){
6879 if(strtolower($this->message[$parent]['type']) == 'array'){
6880 $this->message[$parent]['result'][] = $this->message[$pos]['result'];
6881 } else {
6882 $this->message[$parent]['result'][$this->message[$pos]['name']] = $this->message[$pos]['result'];
6883 }
6884 }
6885 */
6886 }
6887 }
6888
6889 // for doclit
6890 if ($this->status == 'header') {
6891 if ($this->root_header != $pos) {
6892 $this->responseHeaders .= "</" . (isset($prefix) ? $prefix . ':' : '') . "$name>";
6893 }
6894 } elseif ($pos >= $this->root_struct) {
6895 $this->document .= "</" . (isset($prefix) ? $prefix . ':' : '') . "$name>";
6896 }
6897 // switch status
6898 if ($pos == $this->root_struct) {
6899 $this->status = 'body';
6900 $this->root_struct_namespace = $this->message[$pos]['namespace'];
6901 } elseif ($name == 'Body') {
6902 $this->status = 'envelope';
6903 } elseif ($name == 'Header') {
6904 $this->status = 'envelope';
6905 } elseif ($name == 'Envelope') {
6906 //
6907 }
6908 // set parent back to my parent
6909 $this->parent = $this->message[$pos]['parent'];
6910 }
6911
6919 public function character_data($parser, $data)
6920 {
6921 $pos = $this->depth_array[$this->depth];
6922 if ($this->xml_encoding == 'UTF-8') {
6923 // TODO: add an option to disable this for folks who want
6924 // raw UTF-8 that, e.g., might not map to iso-8859-1
6925 // TODO: this can also be handled with xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, "ISO-8859-1");
6926 if ($this->decode_utf8) {
6927 $data = utf8_decode($data);
6928 }
6929 }
6930 $this->message[$pos]['cdata'] .= $data;
6931 // for doclit
6932 if ($this->status == 'header') {
6933 $this->responseHeaders .= $data;
6934 } else {
6935 $this->document .= $data;
6936 }
6937 }
6938
6946 public function get_response()
6947 {
6948 return $this->soapresponse;
6949 }
6950
6957 public function get_soapbody()
6958 {
6959 return $this->soapresponse;
6960 }
6961
6968 public function get_soapheader()
6969 {
6970 return $this->soapheader;
6971 }
6972
6979 public function getHeaders()
6980 {
6982 }
6983
6993 public function decodeSimple($value, $type, $typens)
6994 {
6995 // TODO: use the namespace!
6996 if ((!isset($type)) || $type == 'string' || $type == 'long' || $type == 'unsignedLong') {
6997 return (string) $value;
6998 }
6999 if ($type == 'int' || $type == 'integer' || $type == 'short' || $type == 'byte') {
7000 return (int) $value;
7001 }
7002 if ($type == 'float' || $type == 'double' || $type == 'decimal') {
7003 return (float) $value;
7004 }
7005 if ($type == 'boolean') {
7006 if (strtolower($value) == 'false' || strtolower($value) == 'f') {
7007 return false;
7008 }
7009 return (bool) $value;
7010 }
7011 if ($type == 'base64' || $type == 'base64Binary') {
7012 $this->debug('Decode base64 value');
7013 return base64_decode($value);
7014 }
7015 // obscure numeric types
7016 if ($type == 'nonPositiveInteger' || $type == 'negativeInteger'
7017 || $type == 'nonNegativeInteger' || $type == 'positiveInteger'
7018 || $type == 'unsignedInt'
7019 || $type == 'unsignedShort' || $type == 'unsignedByte') {
7020 return (int) $value;
7021 }
7022 // bogus: parser treats array with no elements as a simple type
7023 if ($type == 'array') {
7024 return array();
7025 }
7026 // everything else
7027 return (string) $value;
7028 }
7029
7038 public function buildVal($pos)
7039 {
7040 if (!isset($this->message[$pos]['type'])) {
7041 $this->message[$pos]['type'] = '';
7042 }
7043 $this->debug('in buildVal() for ' . $this->message[$pos]['name'] . "(pos $pos) of type " . $this->message[$pos]['type']);
7044 // if there are children...
7045 if ($this->message[$pos]['children'] != '') {
7046 $this->debug('in buildVal, there are children');
7047 $children = explode('|', $this->message[$pos]['children']);
7048 array_shift($children); // knock off empty
7049 // md array
7050 if (isset($this->message[$pos]['arrayCols']) && $this->message[$pos]['arrayCols'] != '') {
7051 $r = 0; // rowcount
7052 $c = 0; // colcount
7053 foreach ($children as $child_pos) {
7054 $this->debug("in buildVal, got an MD array element: $r, $c");
7055 $params[$r][] = $this->message[$child_pos]['result'];
7056 $c++;
7057 if ($c == $this->message[$pos]['arrayCols']) {
7058 $c = 0;
7059 $r++;
7060 }
7061 }
7062 // array
7063 } elseif ($this->message[$pos]['type'] == 'array' || $this->message[$pos]['type'] == 'Array') {
7064 $this->debug('in buildVal, adding array ' . $this->message[$pos]['name']);
7065 foreach ($children as $child_pos) {
7066 $params[] = &$this->message[$child_pos]['result'];
7067 }
7068 // apache Map type: java hashtable
7069 } elseif ($this->message[$pos]['type'] == 'Map' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap') {
7070 $this->debug('in buildVal, Java Map ' . $this->message[$pos]['name']);
7071 foreach ($children as $child_pos) {
7072 $kv = explode("|", $this->message[$child_pos]['children']);
7073 $params[$this->message[$kv[1]]['result']] = &$this->message[$kv[2]]['result'];
7074 }
7075 // generic compound type
7076 //} elseif($this->message[$pos]['type'] == 'SOAPStruct' || $this->message[$pos]['type'] == 'struct') {
7077 } else {
7078 // Apache Vector type: treat as an array
7079 $this->debug('in buildVal, adding Java Vector or generic compound type ' . $this->message[$pos]['name']);
7080 if ($this->message[$pos]['type'] == 'Vector' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap') {
7081 $notstruct = 1;
7082 } else {
7083 $notstruct = 0;
7084 }
7085 //
7086 foreach ($children as $child_pos) {
7087 if ($notstruct) {
7088 $params[] = &$this->message[$child_pos]['result'];
7089 } else {
7090 if (isset($params[$this->message[$child_pos]['name']])) {
7091 // de-serialize repeated element name into an array
7092 if ((!is_array($params[$this->message[$child_pos]['name']])) || (!isset($params[$this->message[$child_pos]['name']][0]))) {
7093 $params[$this->message[$child_pos]['name']] = array($params[$this->message[$child_pos]['name']]);
7094 }
7095 $params[$this->message[$child_pos]['name']][] = &$this->message[$child_pos]['result'];
7096 } else {
7097 $params[$this->message[$child_pos]['name']] = &$this->message[$child_pos]['result'];
7098 }
7099 }
7100 }
7101 }
7102 if (isset($this->message[$pos]['xattrs'])) {
7103 $this->debug('in buildVal, handling attributes');
7104 foreach ($this->message[$pos]['xattrs'] as $n => $v) {
7105 $params[$n] = $v;
7106 }
7107 }
7108 // handle simpleContent
7109 if (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') {
7110 $this->debug('in buildVal, handling simpleContent');
7111 if (isset($this->message[$pos]['type'])) {
7112 $params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
7113 } else {
7114 $parent = $this->message[$pos]['parent'];
7115 if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
7116 $params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
7117 } else {
7118 $params['!'] = $this->message[$pos]['cdata'];
7119 }
7120 }
7121 }
7122 $ret = is_array($params) ? $params : array();
7123 $this->debug('in buildVal, return:');
7124 $this->appendDebug($this->varDump($ret));
7125 return $ret;
7126 } else {
7127 $this->debug('in buildVal, no children, building scalar');
7128 $cdata = isset($this->message[$pos]['cdata']) ? $this->message[$pos]['cdata'] : '';
7129 if (isset($this->message[$pos]['type'])) {
7130 $ret = $this->decodeSimple($cdata, $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
7131 $this->debug("in buildVal, return: $ret");
7132 return $ret;
7133 }
7134 $parent = $this->message[$pos]['parent'];
7135 if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
7136 $ret = $this->decodeSimple($cdata, $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
7137 $this->debug("in buildVal, return: $ret");
7138 return $ret;
7139 }
7140 $ret = $this->message[$pos]['cdata'];
7141 $this->debug("in buildVal, return: $ret");
7142 return $ret;
7143 }
7144 }
7145}
7146
7150class soap_parser extends nusoap_parser
7151{
7152}
7153
7154?><?php
7155
7156
7157
7178class nusoap_client extends nusoap_base
7179{
7180 public $return;
7181 public $wsdl;
7182 public $wsdlFile;
7183 public $opData;
7184 public $operation;
7185 public $username = ''; // Username for HTTP authentication
7186 public $password = ''; // Password for HTTP authentication
7187 public $authtype = ''; // Type of HTTP authentication
7188 public $certRequest = array(); // Certificate for HTTP SSL authentication
7189 public $requestHeaders = false; // SOAP headers in request (text)
7190 public $responseHeaders = ''; // SOAP headers from response (incomplete namespace resolution) (text)
7191 public $responseHeader = null; // SOAP Header from response (parsed)
7192 public $document = ''; // SOAP body response portion (incomplete namespace resolution) (text)
7193 public $endpoint;
7194 public $forceEndpoint = ''; // overrides WSDL endpoint
7195 public $proxyhost = '';
7196 public $proxyport = '';
7197 public $proxyusername = '';
7198 public $proxypassword = '';
7199 public $xml_encoding = ''; // character set encoding of incoming (response) messages
7200 public $http_encoding = false;
7201 public $timeout = 0; // HTTP connection timeout
7202 public $response_timeout = 30; // HTTP response timeout
7203 public $endpointType = ''; // soap|wsdl, empty for WSDL initialization error
7204 public $persistentConnection = false;
7205 public $defaultRpcParams = false; // This is no longer used
7206 public $request = ''; // HTTP request
7207 public $response = ''; // HTTP response
7208 public $responseData = ''; // SOAP payload of response
7209 public $cookies = array(); // Cookies from response or for request
7210 public $decode_utf8 = true; // toggles whether the parser decodes element content w/ utf8_decode()
7211 public $operations = array(); // WSDL operations, empty for WSDL initialization error
7212 public $curl_options = array(); // User-specified cURL options
7213 public $bindingType = ''; // WSDL operation binding type
7214 public $use_curl = false; // whether to always try to use cURL
7215
7216 /*
7217 * fault related variables
7218 */
7223 public $fault;
7228 public $faultcode;
7233 public $faultstring;
7238 public $faultdetail;
7239
7254 public function __construct($endpoint, $wsdl = false, $proxyhost = false, $proxyport = false, $proxyusername = false, $proxypassword = false, $timeout = 0, $response_timeout = 30)
7255 {
7257 $this->endpoint = $endpoint;
7258 $this->proxyhost = $proxyhost;
7259 $this->proxyport = $proxyport;
7260 $this->proxyusername = $proxyusername;
7261 $this->proxypassword = $proxypassword;
7262 $this->timeout = $timeout;
7263 $this->response_timeout = $response_timeout;
7264
7265 $this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout");
7266 $this->appendDebug('endpoint=' . $this->varDump($endpoint));
7267
7268 // make values
7269 if ($wsdl) {
7270 if (is_object($endpoint) && (get_class($endpoint) == 'wsdl')) {
7271 $this->wsdl = $endpoint;
7272 $this->endpoint = $this->wsdl->wsdl;
7273 $this->wsdlFile = $this->endpoint;
7274 $this->debug('existing wsdl instance created from ' . $this->endpoint);
7275 $this->checkWSDL();
7276 } else {
7277 $this->wsdlFile = $this->endpoint;
7278 $this->wsdl = null;
7279 $this->debug('will use lazy evaluation of wsdl from ' . $this->endpoint);
7280 }
7281 $this->endpointType = 'wsdl';
7282 } else {
7283 $this->debug("instantiate SOAP with endpoint at $endpoint");
7284 $this->endpointType = 'soap';
7285 }
7286 }
7287
7313 public function call($operation, $params = array(), $namespace = 'http://tempuri.org', $soapAction = '', $headers = false, $rpcParams = null, $style = 'rpc', $use = 'encoded')
7314 {
7315 $this->operation = $operation;
7316 $this->fault = false;
7317 $this->setError('');
7318 $this->request = '';
7319 $this->response = '';
7320 $this->responseData = '';
7321 $this->faultstring = '';
7322 $this->faultcode = '';
7323 $this->opData = array();
7324
7325 $this->debug("call: operation=$operation, namespace=$namespace, soapAction=$soapAction, rpcParams=$rpcParams, style=$style, use=$use, endpointType=$this->endpointType");
7326 $this->appendDebug('params=' . $this->varDump($params));
7327 $this->appendDebug('headers=' . $this->varDump($headers));
7328 if ($headers) {
7329 $this->requestHeaders = $headers;
7330 }
7331 if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
7332 $this->loadWSDL();
7333 if ($this->getError()) {
7334 return false;
7335 }
7336 }
7337 // serialize parameters
7338 if ($this->endpointType == 'wsdl' && $opData = $this->getOperationData($operation)) {
7339 // use WSDL for operation
7340 $this->opData = $opData;
7341 $this->debug("found operation");
7342 $this->appendDebug('opData=' . $this->varDump($opData));
7343 if (isset($opData['soapAction'])) {
7344 $soapAction = $opData['soapAction'];
7345 }
7346 if (! $this->forceEndpoint) {
7347 $this->endpoint = $opData['endpoint'];
7348 } else {
7349 $this->endpoint = $this->forceEndpoint;
7350 }
7351 $namespace = isset($opData['input']['namespace']) ? $opData['input']['namespace'] : $namespace;
7352 $style = $opData['style'];
7353 $use = $opData['input']['use'];
7354 // add ns to ns array
7355 if ($namespace != '' && !isset($this->wsdl->namespaces[$namespace])) {
7356 $nsPrefix = 'ns' . rand(1000, 9999);
7357 $this->wsdl->namespaces[$nsPrefix] = $namespace;
7358 }
7359 $nsPrefix = $this->wsdl->getPrefixFromNamespace($namespace);
7360 // serialize payload
7361 if (is_string($params)) {
7362 $this->debug("serializing param string for WSDL operation $operation");
7363 $payload = $params;
7364 } elseif (is_array($params)) {
7365 $this->debug("serializing param array for WSDL operation $operation");
7366 $payload = $this->wsdl->serializeRPCParameters($operation, 'input', $params, $this->bindingType);
7367 } else {
7368 $this->debug('params must be array or string');
7369 $this->setError('params must be array or string');
7370 return false;
7371 }
7372 $usedNamespaces = $this->wsdl->usedNamespaces;
7373 if (isset($opData['input']['encodingStyle'])) {
7374 $encodingStyle = $opData['input']['encodingStyle'];
7375 } else {
7376 $encodingStyle = '';
7377 }
7378 $this->appendDebug($this->wsdl->getDebug());
7379 $this->wsdl->clearDebug();
7380 if ($errstr = $this->wsdl->getError()) {
7381 $this->debug('got wsdl error: ' . $errstr);
7382 $this->setError('wsdl error: ' . $errstr);
7383 return false;
7384 }
7385 } elseif ($this->endpointType == 'wsdl') {
7386 // operation not in WSDL
7387 $this->appendDebug($this->wsdl->getDebug());
7388 $this->wsdl->clearDebug();
7389 $this->setError('operation ' . $operation . ' not present.');
7390 $this->debug("operation '$operation' not present.");
7391 return false;
7392 } else {
7393 // no WSDL
7394 //$this->namespaces['ns1'] = $namespace;
7395 $nsPrefix = 'ns' . rand(1000, 9999);
7396 // serialize
7397 $payload = '';
7398 if (is_string($params)) {
7399 $this->debug("serializing param string for operation $operation");
7400 $payload = $params;
7401 } elseif (is_array($params)) {
7402 $this->debug("serializing param array for operation $operation");
7403 foreach ($params as $k => $v) {
7404 $payload .= $this->serialize_val($v, $k, false, false, false, false, $use);
7405 }
7406 } else {
7407 $this->debug('params must be array or string');
7408 $this->setError('params must be array or string');
7409 return false;
7410 }
7411 $usedNamespaces = array();
7412 if ($use == 'encoded') {
7413 $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
7414 } else {
7415 $encodingStyle = '';
7416 }
7417 }
7418 // wrap RPC calls with method element
7419 if ($style == 'rpc') {
7420 if ($use == 'literal') {
7421 $this->debug("wrapping RPC request with literal method element");
7422 if ($namespace) {
7423 // 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
7424 $payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" .
7425 $payload .
7426 "</$nsPrefix:$operation>";
7427 } else {
7428 $payload = "<$operation>" . $payload . "</$operation>";
7429 }
7430 } else {
7431 $this->debug("wrapping RPC request with encoded method element");
7432 if ($namespace) {
7433 $payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" .
7434 $payload .
7435 "</$nsPrefix:$operation>";
7436 } else {
7437 $payload = "<$operation>" .
7438 $payload .
7439 "</$operation>";
7440 }
7441 }
7442 }
7443 // serialize envelope
7444 $soapmsg = $this->serializeEnvelope($payload, $this->requestHeaders, $usedNamespaces, $style, $use, $encodingStyle);
7445 $this->debug("endpoint=$this->endpoint, soapAction=$soapAction, namespace=$namespace, style=$style, use=$use, encodingStyle=$encodingStyle");
7446 $this->debug('SOAP message length=' . strlen($soapmsg) . ' contents (max 1000 bytes)=' . substr($soapmsg, 0, 1000));
7447 // send
7448 $return = $this->send($this->getHTTPBody($soapmsg), $soapAction, $this->timeout, $this->response_timeout);
7449 if ($errstr = $this->getError()) {
7450 $this->debug('Error: ' . $errstr);
7451 return false;
7452 } else {
7453 $this->return = $return;
7454 $this->debug('sent message successfully and got a(n) ' . gettype($return));
7455 $this->appendDebug('return=' . $this->varDump($return));
7456
7457 // fault?
7458 if (is_array($return) && isset($return['faultcode'])) {
7459 $this->debug('got fault');
7460 $this->setError($return['faultcode'] . ': ' . $return['faultstring']);
7461 $this->fault = true;
7462 foreach ($return as $k => $v) {
7463 $this->$k = $v;
7464 $this->debug("$k = $v<br>");
7465 }
7466 return $return;
7467 } elseif ($style == 'document') {
7468 // NOTE: if the response is defined to have multiple parts (i.e. unwrapped),
7469 // we are only going to return the first part here...sorry about that
7470 return $return;
7471 } else {
7472 // array of return values
7473 if (is_array($return)) {
7474 // multiple 'out' parameters, which we return wrapped up
7475 // in the array
7476 if (sizeof($return) > 1) {
7477 return $return;
7478 }
7479 // single 'out' parameter (normally the return value)
7480 $return = array_shift($return);
7481 $this->debug('return shifted value: ');
7482 $this->appendDebug($this->varDump($return));
7483 return $return;
7484 // nothing returned (ie, echoVoid)
7485 } else {
7486 return "";
7487 }
7488 }
7489 }
7490 }
7491
7497 public function checkWSDL()
7498 {
7499 $this->appendDebug($this->wsdl->getDebug());
7500 $this->wsdl->clearDebug();
7501 $this->debug('checkWSDL');
7502 // catch errors
7503 if ($errstr = $this->wsdl->getError()) {
7504 $this->debug('got wsdl error: ' . $errstr);
7505 $this->setError('wsdl error: ' . $errstr);
7506 } elseif ($this->operations = $this->wsdl->getOperations('soap')) {
7507 $this->bindingType = 'soap';
7508 $this->debug('got ' . count($this->operations) . ' operations from wsdl ' . $this->wsdlFile . ' for binding type ' . $this->bindingType);
7509 } elseif ($this->operations = $this->wsdl->getOperations('soap12')) {
7510 $this->bindingType = 'soap12';
7511 $this->debug('got ' . count($this->operations) . ' operations from wsdl ' . $this->wsdlFile . ' for binding type ' . $this->bindingType);
7512 $this->debug('**************** WARNING: SOAP 1.2 BINDING *****************');
7513 } else {
7514 $this->debug('getOperations returned false');
7515 $this->setError('no operations defined in the WSDL document!');
7516 }
7517 }
7518
7524 public function loadWSDL()
7525 {
7526 $this->debug('instantiating wsdl class with doc: ' . $this->wsdlFile);
7527 $this->wsdl = new wsdl('', $this->proxyhost, $this->proxyport, $this->proxyusername, $this->proxypassword, $this->timeout, $this->response_timeout, $this->curl_options, $this->use_curl);
7528 $this->wsdl->setCredentials($this->username, $this->password, $this->authtype, $this->certRequest);
7529 $this->wsdl->fetchWSDL($this->wsdlFile);
7530 $this->checkWSDL();
7531 }
7532
7540 public function getOperationData($operation)
7541 {
7542 if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
7543 $this->loadWSDL();
7544 if ($this->getError()) {
7545 return false;
7546 }
7547 }
7548 if (isset($this->operations[$operation])) {
7549 return $this->operations[$operation];
7550 }
7551 $this->debug("No data for operation: $operation");
7552 }
7553
7568 public function send($msg, $soapaction = '', $timeout = 0, $response_timeout = 30)
7569 {
7570 $this->checkCookies();
7571 // detect transport
7572 switch (true) {
7573 // http(s)
7574 case preg_match('/^http/', $this->endpoint):
7575 $this->debug('transporting via HTTP');
7576 if ($this->persistentConnection == true && is_object($this->persistentConnection)) {
7578 } else {
7579 $http = new soap_transport_http($this->endpoint, $this->curl_options, $this->use_curl);
7580 if ($this->persistentConnection) {
7581 $http->usePersistentConnection();
7582 }
7583 }
7584 $http->setContentType($this->getHTTPContentType(), $this->getHTTPContentTypeCharset());
7585 $http->setSOAPAction($soapaction);
7586 if ($this->proxyhost && $this->proxyport) {
7587 $http->setProxy($this->proxyhost, $this->proxyport, $this->proxyusername, $this->proxypassword);
7588 }
7589 if ($this->authtype != '') {
7590 $http->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest);
7591 }
7592 if ($this->http_encoding != '') {
7593 $http->setEncoding($this->http_encoding);
7594 }
7595 $this->debug('sending message, length=' . strlen($msg));
7596 if (preg_match('/^http:/', $this->endpoint)) {
7597 //if(strpos($this->endpoint,'http:')){
7598 $this->responseData = $http->send($msg, $timeout, $response_timeout, $this->cookies);
7599 } elseif (preg_match('/^https/', $this->endpoint)) {
7600 //} elseif(strpos($this->endpoint,'https:')){
7601 //if(phpversion() == '4.3.0-dev'){
7602 //$response = $http->send($msg,$timeout,$response_timeout);
7603 //$this->request = $http->outgoing_payload;
7604 //$this->response = $http->incoming_payload;
7605 //} else
7606 $this->responseData = $http->sendHTTPS($msg, $timeout, $response_timeout, $this->cookies);
7607 } else {
7608 $this->setError('no http/s in endpoint url');
7609 }
7610 $this->request = $http->outgoing_payload;
7611 $this->response = $http->incoming_payload;
7612 $this->appendDebug($http->getDebug());
7613 $this->UpdateCookies($http->incoming_cookies);
7614
7615 // save transport object if using persistent connections
7616 if ($this->persistentConnection) {
7617 $http->clearDebug();
7618 if (!is_object($this->persistentConnection)) {
7619 $this->persistentConnection = $http;
7620 }
7621 }
7622
7623 if ($err = $http->getError()) {
7624 $this->setError('HTTP Error: ' . $err);
7625 return false;
7626 } elseif ($this->getError()) {
7627 return false;
7628 } else {
7629 $this->debug('got response, length=' . strlen($this->responseData) . ' type=' . $http->incoming_headers['content-type']);
7630 return $this->parseResponse($http->incoming_headers, $this->responseData);
7631 }
7632 break;
7633 default:
7634 $this->setError('no transport found, or selected transport is not yet supported!');
7635 return false;
7636 break;
7637 }
7638 }
7639
7648 public function parseResponse($headers, $data)
7649 {
7650 $this->debug('Entering parseResponse() for data of length ' . strlen($data) . ' headers:');
7651 $this->appendDebug($this->varDump($headers));
7652 if (!strstr($headers['content-type'], 'text/xml')) {
7653 $this->setError('Response not of type text/xml: ' . $headers['content-type']);
7654 return false;
7655 }
7656 if (strpos($headers['content-type'], '=')) {
7657 $enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1));
7658 $this->debug('Got response encoding: ' . $enc);
7659 if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i', $enc)) {
7660 $this->xml_encoding = strtoupper($enc);
7661 } else {
7662 $this->xml_encoding = 'US-ASCII';
7663 }
7664 } else {
7665 // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
7666 $this->xml_encoding = 'ISO-8859-1';
7667 }
7668 $this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser');
7669 $parser = new nusoap_parser($data, $this->xml_encoding, $this->operation, $this->decode_utf8);
7670 // add parser debug data to our debug
7671 $this->appendDebug($parser->getDebug());
7672 // if parse errors
7673 if ($errstr = $parser->getError()) {
7674 $this->setError($errstr);
7675 // destroy the parser object
7676 unset($parser);
7677 return false;
7678 } else {
7679 // get SOAP headers
7680 $this->responseHeaders = $parser->getHeaders();
7681 // get SOAP headers
7682 $this->responseHeader = $parser->get_soapheader();
7683 // get decoded message
7684 $return = $parser->get_soapbody();
7685 // add document for doclit support
7686 $this->document = $parser->document;
7687 // destroy the parser object
7688 unset($parser);
7689 // return decode message
7690 return $return;
7691 }
7692 }
7693
7701 public function setCurlOption($option, $value)
7702 {
7703 $this->debug("setCurlOption option=$option, value=");
7704 $this->appendDebug($this->varDump($value));
7705 $this->curl_options[$option] = $value;
7706 }
7707
7714 public function setEndpoint($endpoint)
7715 {
7716 $this->debug("setEndpoint(\"$endpoint\")");
7717 $this->forceEndpoint = $endpoint;
7718 }
7719
7726 public function setHeaders($headers)
7727 {
7728 $this->debug("setHeaders headers=");
7729 $this->appendDebug($this->varDump($headers));
7730 $this->requestHeaders = $headers;
7731 }
7732
7739 public function getHeaders()
7740 {
7742 }
7743
7750 public function getHeader()
7751 {
7752 return $this->responseHeader;
7753 }
7754
7764 public function setHTTPProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '')
7765 {
7766 $this->proxyhost = $proxyhost;
7767 $this->proxyport = $proxyport;
7768 $this->proxyusername = $proxyusername;
7769 $this->proxypassword = $proxypassword;
7770 }
7771
7781 public function setCredentials($username, $password, $authtype = 'basic', $certRequest = array())
7782 {
7783 $this->debug("setCredentials username=$username authtype=$authtype certRequest=");
7784 $this->appendDebug($this->varDump($certRequest));
7785 $this->username = $username;
7786 $this->password = $password;
7787 $this->authtype = $authtype;
7788 $this->certRequest = $certRequest;
7789 }
7790
7797 public function setHTTPEncoding($enc = 'gzip, deflate')
7798 {
7799 $this->debug("setHTTPEncoding(\"$enc\")");
7800 $this->http_encoding = $enc;
7801 }
7802
7809 public function setUseCURL($use)
7810 {
7811 $this->debug("setUseCURL($use)");
7812 $this->use_curl = $use;
7813 }
7814
7820 public function useHTTPPersistentConnection()
7821 {
7822 $this->debug("useHTTPPersistentConnection");
7823 $this->persistentConnection = true;
7824 }
7825
7837 public function getDefaultRpcParams()
7838 {
7840 }
7841
7853 public function setDefaultRpcParams($rpcParams)
7854 {
7855 $this->defaultRpcParams = $rpcParams;
7856 }
7857
7865 public function getProxy()
7866 {
7867 $r = rand();
7868 $evalStr = $this->_getProxyClassCode($r);
7869 //$this->debug("proxy class: $evalStr");
7870 if ($this->getError()) {
7871 $this->debug("Error from _getProxyClassCode, so return NULL");
7872 return null;
7873 }
7874 // eval the class
7875 eval($evalStr);
7876 // instantiate proxy object
7877 eval("\$proxy = new nusoap_proxy_$r('');");
7878 // transfer current wsdl data to the proxy thereby avoiding parsing the wsdl twice
7879 $proxy->endpointType = 'wsdl';
7880 $proxy->wsdlFile = $this->wsdlFile;
7881 $proxy->wsdl = $this->wsdl;
7882 $proxy->operations = $this->operations;
7883 $proxy->defaultRpcParams = $this->defaultRpcParams;
7884 // transfer other state
7885 $proxy->soap_defencoding = $this->soap_defencoding;
7886 $proxy->username = $this->username;
7887 $proxy->password = $this->password;
7888 $proxy->authtype = $this->authtype;
7889 $proxy->certRequest = $this->certRequest;
7890 $proxy->requestHeaders = $this->requestHeaders;
7891 $proxy->endpoint = $this->endpoint;
7892 $proxy->forceEndpoint = $this->forceEndpoint;
7893 $proxy->proxyhost = $this->proxyhost;
7894 $proxy->proxyport = $this->proxyport;
7895 $proxy->proxyusername = $this->proxyusername;
7896 $proxy->proxypassword = $this->proxypassword;
7897 $proxy->http_encoding = $this->http_encoding;
7898 $proxy->timeout = $this->timeout;
7899 $proxy->response_timeout = $this->response_timeout;
7900 $proxy->persistentConnection = &$this->persistentConnection;
7901 $proxy->decode_utf8 = $this->decode_utf8;
7902 $proxy->curl_options = $this->curl_options;
7903 $proxy->bindingType = $this->bindingType;
7904 $proxy->use_curl = $this->use_curl;
7905 return $proxy;
7906 }
7907
7914 public function _getProxyClassCode($r)
7915 {
7916 $this->debug("in getProxy endpointType=$this->endpointType");
7917 $this->appendDebug("wsdl=" . $this->varDump($this->wsdl));
7918 if ($this->endpointType != 'wsdl') {
7919 $evalStr = 'A proxy can only be created for a WSDL client';
7920 $this->setError($evalStr);
7921 $evalStr = "echo \"$evalStr\";";
7922 return $evalStr;
7923 }
7924 if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
7925 $this->loadWSDL();
7926 if ($this->getError()) {
7927 return "echo \"" . $this->getError() . "\";";
7928 }
7929 }
7930 $evalStr = '';
7931 foreach ($this->operations as $operation => $opData) {
7932 if ($operation != '') {
7933 // create param string and param comment string
7934 if (sizeof($opData['input']['parts']) > 0) {
7935 $paramStr = '';
7936 $paramArrayStr = '';
7937 $paramCommentStr = '';
7938 foreach ($opData['input']['parts'] as $name => $type) {
7939 $paramStr .= "\$$name, ";
7940 $paramArrayStr .= "'$name' => \$$name, ";
7941 $paramCommentStr .= "$type \$$name, ";
7942 }
7943 $paramStr = substr($paramStr, 0, strlen($paramStr) - 2);
7944 $paramArrayStr = substr($paramArrayStr, 0, strlen($paramArrayStr) - 2);
7945 $paramCommentStr = substr($paramCommentStr, 0, strlen($paramCommentStr) - 2);
7946 } else {
7947 $paramStr = '';
7948 $paramArrayStr = '';
7949 $paramCommentStr = 'void';
7950 }
7951 $opData['namespace'] = !isset($opData['namespace']) ? 'http://testuri.com' : $opData['namespace'];
7952 $evalStr .= "// $paramCommentStr
7953 function " . str_replace('.', '__', $operation) . "($paramStr) {
7954 \$params = array($paramArrayStr);
7955 return \$this->call('$operation', \$params, '" . $opData['namespace'] . "', '" . (isset($opData['soapAction']) ? $opData['soapAction'] : '') . "');
7956 }
7957 ";
7958 unset($paramStr);
7959 unset($paramCommentStr);
7960 }
7961 }
7962 $evalStr = 'class nusoap_proxy_' . $r . ' extends nusoap_client {
7963 ' . $evalStr . '
7964}';
7965 return $evalStr;
7966 }
7967
7974 public function getProxyClassCode()
7975 {
7976 $r = rand();
7977 return $this->_getProxyClassCode($r);
7978 }
7979
7987 public function getHTTPBody($soapmsg)
7988 {
7989 return $soapmsg;
7990 }
7991
8000 public function getHTTPContentType()
8001 {
8002 return 'text/xml';
8003 }
8004
8014 public function getHTTPContentTypeCharset()
8015 {
8017 }
8018
8019 /*
8020 * whether or not parser should decode utf8 element content
8021 *
8022 * @return always returns true
8023 * @access public
8024 */
8025 public function decodeUTF8($bool)
8026 {
8027 $this->decode_utf8 = $bool;
8028 return true;
8029 }
8030
8039 public function setCookie($name, $value)
8040 {
8041 if (strlen($name) == 0) {
8042 return false;
8043 }
8044 $this->cookies[] = array('name' => $name, 'value' => $value);
8045 return true;
8046 }
8047
8054 public function getCookies()
8055 {
8056 return $this->cookies;
8057 }
8058
8065 public function checkCookies()
8066 {
8067 if (sizeof($this->cookies) == 0) {
8068 return true;
8069 }
8070 $this->debug('checkCookie: check ' . sizeof($this->cookies) . ' cookies');
8071 $curr_cookies = $this->cookies;
8072 $this->cookies = array();
8073 foreach ($curr_cookies as $cookie) {
8074 if (! is_array($cookie)) {
8075 $this->debug('Remove cookie that is not an array');
8076 continue;
8077 }
8078 if ((isset($cookie['expires'])) && (! empty($cookie['expires']))) {
8079 if (strtotime($cookie['expires']) > time()) {
8080 $this->cookies[] = $cookie;
8081 } else {
8082 $this->debug('Remove expired cookie ' . $cookie['name']);
8083 }
8084 } else {
8085 $this->cookies[] = $cookie;
8086 }
8087 }
8088 $this->debug('checkCookie: ' . sizeof($this->cookies) . ' cookies left in array');
8089 return true;
8090 }
8091
8099 public function UpdateCookies($cookies)
8100 {
8101 if (sizeof($this->cookies) == 0) {
8102 // no existing cookies: take whatever is new
8103 if (sizeof($cookies) > 0) {
8104 $this->debug('Setting new cookie(s)');
8105 $this->cookies = $cookies;
8106 }
8107 return true;
8108 }
8109 if (sizeof($cookies) == 0) {
8110 // no new cookies: keep what we've got
8111 return true;
8112 }
8113 // merge
8114 foreach ($cookies as $newCookie) {
8115 if (!is_array($newCookie)) {
8116 continue;
8117 }
8118 if ((!isset($newCookie['name'])) || (!isset($newCookie['value']))) {
8119 continue;
8120 }
8121 $newName = $newCookie['name'];
8122
8123 $found = false;
8124 for ($i = 0; $i < count($this->cookies); $i++) {
8125 $cookie = $this->cookies[$i];
8126 if (!is_array($cookie)) {
8127 continue;
8128 }
8129 if (!isset($cookie['name'])) {
8130 continue;
8131 }
8132 if ($newName != $cookie['name']) {
8133 continue;
8134 }
8135 $newDomain = isset($newCookie['domain']) ? $newCookie['domain'] : 'NODOMAIN';
8136 $domain = isset($cookie['domain']) ? $cookie['domain'] : 'NODOMAIN';
8137 if ($newDomain != $domain) {
8138 continue;
8139 }
8140 $newPath = isset($newCookie['path']) ? $newCookie['path'] : 'NOPATH';
8141 $path = isset($cookie['path']) ? $cookie['path'] : 'NOPATH';
8142 if ($newPath != $path) {
8143 continue;
8144 }
8145 $this->cookies[$i] = $newCookie;
8146 $found = true;
8147 $this->debug('Update cookie ' . $newName . '=' . $newCookie['value']);
8148 break;
8149 }
8150 if (! $found) {
8151 $this->debug('Add cookie ' . $newName . '=' . $newCookie['value']);
8152 $this->cookies[] = $newCookie;
8153 }
8154 }
8155 return true;
8156 }
8157}
8158
8159if (!extension_loaded('soap')) {
8163 class soapclient extends nusoap_client
8164 {
8165 }
8166}
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
$out
Definition: buildRTE.php:24
$location
Definition: buildRTE.php:22
Backward compatibility.
Definition: nusoap.php:2016
nusoap_base
Definition: nusoap.php:55
getPrefix($str)
returns the prefix part of a prefixed string returns false, if not prefixed
Definition: nusoap.php:797
& getDebug()
gets the current debug data for this instance
Definition: nusoap.php:290
& getDebugAsXMLComment()
gets the current debug data for this instance as an XML comment this may change the contents of the d...
Definition: nusoap.php:304
setError($str)
sets error string
Definition: nusoap.php:353
getNamespaceFromPrefix($prefix)
pass it a prefix, it returns a namespace
Definition: nusoap.php:813
debug($string)
adds debug data to the instance debug string with formatting
Definition: nusoap.php:250
getPrefixFromNamespace($ns)
returns the prefix for a given namespace (or prefix) or false if no prefixes registered for the given...
Definition: nusoap.php:830
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:391
serializeEnvelope($body, $headers=false, $namespaces=array(), $style='rpc', $use='encoded', $encodingStyle='http://schemas.xmlsoap.org/soap/encoding/')
serializes a message
Definition: nusoap.php:658
clearDebug()
clears the current debug data for this instance
Definition: nusoap.php:277
expandEntities($val)
expands entities, e.g.
Definition: nusoap.php:321
$soap_defencoding
Definition: nusoap.php:122
expandQname($qname)
expands (changes prefix to namespace) a qualified name
Definition: nusoap.php:753
$XMLSchemaVersion
Definition: nusoap.php:113
varDump($data)
Returns a string with the output of var_dump.
Definition: nusoap.php:867
getError()
returns error string if present
Definition: nusoap.php:339
appendDebug($string)
adds debug data to the instance debug string without formatting
Definition: nusoap.php:263
getLocalPart($str)
returns the local part of a prefixed string returns the original string, if not prefixed
Definition: nusoap.php:779
isArraySimpleOrStruct($val)
detect if array is a simple array or a struct (associative array)
Definition: nusoap.php:365
__construct()
constructor
Definition: nusoap.php:195
[nu]soapclient higher level class for easy usage.
Definition: nusoap.php:7179
setCurlOption($option, $value)
sets user-specified cURL options
Definition: nusoap.php:7701
setCredentials($username, $password, $authtype='basic', $certRequest=array())
if authenticating, set user credentials here
Definition: nusoap.php:7781
setHTTPProxy($proxyhost, $proxyport, $proxyusername='', $proxypassword='')
set proxy info here
Definition: nusoap.php:7764
getProxy()
dynamically creates an instance of a proxy class, allowing user to directly call methods from wsdl
Definition: nusoap.php:7865
send($msg, $soapaction='', $timeout=0, $response_timeout=30)
send the SOAP message
Definition: nusoap.php:7568
setUseCURL($use)
Set whether to try to use cURL connections if possible.
Definition: nusoap.php:7809
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:7313
getProxyClassCode()
dynamically creates proxy class code
Definition: nusoap.php:7974
checkCookies()
checks all Cookies and delete those which are expired
Definition: nusoap.php:8065
getHTTPContentType()
gets the HTTP content type for the current request.
Definition: nusoap.php:8000
setHTTPEncoding($enc='gzip, deflate')
use HTTP encoding
Definition: nusoap.php:7797
getHeader()
get the SOAP response Header (parsed)
Definition: nusoap.php:7750
decodeUTF8($bool)
Definition: nusoap.php:8025
useHTTPPersistentConnection()
use HTTP persistent connections if possible
Definition: nusoap.php:7820
setCookie($name, $value)
adds a new Cookie into $this->cookies array
Definition: nusoap.php:8039
getHTTPContentTypeCharset()
gets the HTTP content type charset for the current request.
Definition: nusoap.php:8014
getOperationData($operation)
get available data pertaining to an operation
Definition: nusoap.php:7540
getDefaultRpcParams()
gets the default RPC parameter setting.
Definition: nusoap.php:7837
checkWSDL()
check WSDL passed as an instance or pulled from an endpoint
Definition: nusoap.php:7497
setHeaders($headers)
set the SOAP headers
Definition: nusoap.php:7726
loadWSDL()
instantiate wsdl object and parse wsdl file
Definition: nusoap.php:7524
getHTTPBody($soapmsg)
gets the HTTP body for the current request.
Definition: nusoap.php:7987
setDefaultRpcParams($rpcParams)
sets the default RPC parameter setting.
Definition: nusoap.php:7853
setEndpoint($endpoint)
sets the SOAP endpoint, which can override WSDL
Definition: nusoap.php:7714
UpdateCookies($cookies)
updates the current cookies with a new set
Definition: nusoap.php:8099
getHeaders()
get the SOAP response headers (namespace resolution incomplete)
Definition: nusoap.php:7739
_getProxyClassCode($r)
dynamically creates proxy class code
Definition: nusoap.php:7914
getCookies()
gets all Cookies
Definition: nusoap.php:8054
parseResponse($headers, $data)
processes SOAP message returned from server
Definition: nusoap.php:7648
Contains information for a SOAP fault.
Definition: nusoap.php:994
serialize()
serialize a fault
Definition: nusoap.php:1043
nusoap_parser class parses SOAP XML messages into native PHP values
Definition: nusoap.php:6518
$root_struct_namespace
Definition: nusoap.php:6526
character_data($parser, $data)
element content handler
Definition: nusoap.php:6919
get_soapbody()
get the parsed SOAP Body (NULL if there was none)
Definition: nusoap.php:6957
end_element($parser, $name)
end-element handler
Definition: nusoap.php:6814
getHeaders()
get the unparsed SOAP Header
Definition: nusoap.php:6979
get_response()
get the parsed message (SOAP Body)
Definition: nusoap.php:6946
decodeSimple($value, $type, $typens)
decodes simple types into PHP variables
Definition: nusoap.php:6993
get_soapheader()
get the parsed SOAP Header (NULL if there was none)
Definition: nusoap.php:6968
start_element($parser, $name, $attrs)
start-element handler
Definition: nusoap.php:6658
buildVal($pos)
builds response structures for compound values (arrays/structs) and scalars
Definition: nusoap.php:7038
nusoap_server allows the user to create a SOAP server that is capable of receiving messages and retur...
Definition: nusoap.php:3478
verify_method($operation, $request)
takes the value that was created by parsing the request and compares to the method's signature,...
Definition: nusoap.php:4260
$methodreturnisliteralxml
Definition: nusoap.php:3589
getHTTPBody($soapmsg)
gets the HTTP body for the current response.
Definition: nusoap.php:4332
invoke_method()
invokes a PHP function for the requested SOAP method
Definition: nusoap.php:3941
add_to_map($methodname, $in, $out)
add a method to the dispatch map (this has been replaced by the register method)
Definition: nusoap.php:4373
getHTTPContentType()
gets the HTTP content type for the current response.
Definition: nusoap.php:4345
addInternalPort(string $serviceName, string $url)
Definition: nusoap.php:4553
parse_request($data='')
parses a request
Definition: nusoap.php:3893
getHTTPContentTypeCharset()
gets the HTTP content type charset for the current response.
Definition: nusoap.php:4359
serialize_return()
serializes the return value from a PHP function into a full SOAP Envelope
Definition: nusoap.php:4087
send_response()
sends an HTTP response
Definition: nusoap.php:4180
fault($faultcode, $faultstring, $faultactor='', $faultdetail='')
Specify a fault to be returned to the client.
Definition: nusoap.php:4462
parse_http_headers()
parses HTTP request headers.
Definition: nusoap.php:3764
service($data)
processes request and returns response
Definition: nusoap.php:3701
parseRequest($headers, $data)
processes SOAP message received from client
Definition: nusoap.php:4280
configureWSDL($serviceName, $namespace=false, $endpoint=false, $style='rpc', $transport='http://schemas.xmlsoap.org/soap/http', $schemaTargetNamespace=false)
Sets up wsdl object.
Definition: nusoap.php:4482
parses an XML Schema, allows access to it's data, other utility methods.
Definition: nusoap.php:1086
schemaCharacterData($parser, $data)
element content handler
Definition: nusoap.php:1582
getTypeDef($type)
returns an associative array of information about a given type returns false if no type exists by the...
Definition: nusoap.php:1762
addComplexType($name, $typeClass='complexType', $phpType='array', $compositor='', $restrictionBase='', $elements=array(), $attrs=array(), $arrayType='')
adds a complex type to the schema
Definition: nusoap.php:1949
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:1876
addElement($attrs)
adds an element to the schema
Definition: nusoap.php:1999
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:1728
xdebug($string)
adds debug data to the clas level debug string
Definition: nusoap.php:1711
addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array())
adds a simple type to the schema
Definition: nusoap.php:1978
serializeSchema()
serialize the schema
Definition: nusoap.php:1593
parseString($xml, $type)
parse an XML string
Definition: nusoap.php:1184
schemaEndElement($parser, $name)
end-element handler
Definition: nusoap.php:1544
schemaStartElement($parser, $name, $attrs)
start-element handler
Definition: nusoap.php:1246
serializeTypeDef($type)
returns a sample serialization of a given type, or false if no type by the given name
Definition: nusoap.php:1839
parseFile($xml, $type)
parse an XML file
Definition: nusoap.php:1157
CreateTypeName($ename)
gets a type name for an unnamed type
Definition: nusoap.php:1229
Backward compatibility.
Definition: nusoap.php:1069
Backward compatibility.
Definition: nusoap.php:7151
Backward compatibility.
Definition: nusoap.php:4567
transport class for sending/receiving data via HTTP and HTTPS NOTE: PHP must be compiled with the CUR...
Definition: nusoap.php:2141
sendRequest($data, $cookies=null)
sends the SOAP request via HTTP[S]
Definition: nusoap.php:2888
setCurlOption($option, $value)
sets a cURL option
Definition: nusoap.php:2209
getCookiesForRequest($cookies, $secure=false)
sort out cookies for the current request
Definition: nusoap.php:3422
send($data, $timeout=0, $response_timeout=30, $cookies=null)
sends the SOAP request and gets the SOAP response via HTTP[S]
Definition: nusoap.php:2556
parseCookie($cookie_str)
parse an incoming Cookie into it's parts
Definition: nusoap.php:3355
setURL($url)
sets the URL to which to connect
Definition: nusoap.php:2249
getResponse()
gets the SOAP response via HTTP[S]
Definition: nusoap.php:2946
setContentType($type, $charset=false)
sets the content-type for the SOAP message to be sent
Definition: nusoap.php:3323
unsetHeader($name)
unsets an HTTP header
Definition: nusoap.php:2235
isSkippableCurlHeader(&$data)
Test if the given string starts with a header that is to be skipped.
Definition: nusoap.php:2752
setSOAPAction($soapaction)
set the soapaction value
Definition: nusoap.php:2687
setEncoding($enc='gzip, deflate')
use http encoding
Definition: nusoap.php:2698
usePersistentConnection()
specifies that an HTTP persistent connection should be used
Definition: nusoap.php:3334
setCredentials($username, $password, $authtype='basic', $digestRequest=array(), $certRequest=array())
if authenticating, set user credentials here
Definition: nusoap.php:2612
buildPayload($data, $cookie_str='')
Writes the payload, including HTTP headers, to $this->outgoing_payload.
Definition: nusoap.php:2840
connect($connection_timeout=0, $response_timeout=30)
establish an HTTP connection
Definition: nusoap.php:2313
setHeader($name, $value)
sets an HTTP header
Definition: nusoap.php:2223
io_method()
gets the I/O method to use
Definition: nusoap.php:2294
decodeChunked($buffer, $lb)
decode a string that is encoded w/ "chunked' transfer encoding as defined in RFC2068 19....
Definition: nusoap.php:2782
setProxy($proxyhost, $proxyport, $proxyusername='', $proxypassword='', $proxyauthtype='basic')
set proxy info here
Definition: nusoap.php:2723
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:2597
For creating serializable abstractions of native PHP types.
Definition: nusoap.php:2035
serialize($use='encoded')
return serialized value
Definition: nusoap.php:2108
$element_ns
Definition: nusoap.php:2063
decode()
decodes a soapval object into a PHP native type
Definition: nusoap.php:2119
$attributes
Definition: nusoap.php:2077
parses a WSDL file, allows access to it's data, other utility methods.
Definition: nusoap.php:4584
$currentMessage
Definition: nusoap.php:4596
$import
Definition: nusoap.php:4609
$username
Definition: nusoap.php:4625
$ports
Definition: nusoap.php:4602
$proxyhost
Definition: nusoap.php:4616
character_data($parser, $data)
element content handler
Definition: nusoap.php:5118
serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType)
serializes the attributes for a complexType
Definition: nusoap.php:6183
$opData
Definition: nusoap.php:4604
$currentSchema
Definition: nusoap.php:4592
getBindingData($binding)
Definition: nusoap.php:5148
serializeRPCParameters($operation, $direction, $parameters, $bindingType='soap')
serialize PHP values according to a WSDL message definition contrary to the method name,...
Definition: nusoap.php:5706
$currentPortType
Definition: nusoap.php:4599
addElement($attrs)
adds an element to the WSDL types
Definition: nusoap.php:6412
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:5265
$status
Definition: nusoap.php:4605
getOperations($bindingType='soap')
returns an assoc array of operation names => operation data
Definition: nusoap.php:5162
setCredentials($username, $password, $authtype='basic', $certRequest=array())
if authenticating, set user credentials here
Definition: nusoap.php:5138
$serviceName
Definition: nusoap.php:4586
$proxypassword
Definition: nusoap.php:4619
$certRequest
Definition: nusoap.php:4628
getOperationData($operation, $bindingType='soap')
returns an associative array of data necessary for calling an operation
Definition: nusoap.php:5194
$currentPortOperation
Definition: nusoap.php:4588
$portTypes
Definition: nusoap.php:4598
$currentOperation
Definition: nusoap.php:4597
$messages
Definition: nusoap.php:4595
serializeParameters($operation, $direction, $parameters)
serialize a PHP value according to a WSDL message definition
Definition: nusoap.php:5801
fetchWSDL($wsdl)
fetches the WSDL document and parses it
Definition: nusoap.php:4666
$password
Definition: nusoap.php:4626
addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array())
adds an XML Schema simple type to the WSDL types
Definition: nusoap.php:6397
$depth
Definition: nusoap.php:4613
$bindings
Definition: nusoap.php:4600
serialize($debug=0)
serialize the parsed wsdl
Definition: nusoap.php:5464
$wsdl
Definition: nusoap.php:4589
$timeout
Definition: nusoap.php:4620
$endpoint
Definition: nusoap.php:4607
$use_curl
Definition: nusoap.php:4623
$proxyusername
Definition: nusoap.php:4618
getOperationDataForSoapAction($soapAction, $bindingType='soap')
returns an associative array of data necessary for calling an operation
Definition: nusoap.php:5226
$documentation
Definition: nusoap.php:4606
webDescription()
prints html description of services
Definition: nusoap.php:5322
serializeType($name, $type, $value, $use='encoded', $encodingStyle=false, $unqualified=false)
serializes a PHP value according a given type definition
Definition: nusoap.php:5879
parseWSDL($wsdl='')
parses the wsdl document
Definition: nusoap.php:4770
$message
Definition: nusoap.php:4593
parametersMatchWrapped($type, &$parameters)
determine whether a set of parameters are unwrapped when they are expect to be wrapped,...
Definition: nusoap.php:5612
start_element($parser, $name, $attrs)
start-element handler
Definition: nusoap.php:4874
$proxyport
Definition: nusoap.php:4617
$authtype
Definition: nusoap.php:4627
end_element($parser, $name)
end-element handler
Definition: nusoap.php:5087
$parser
Definition: nusoap.php:4611
$depth_array
Definition: nusoap.php:4614
serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use='encoded', $encodingStyle=false)
serializes the elements for a complexType
Definition: nusoap.php:6246
$position
Definition: nusoap.php:4612
$schemas
Definition: nusoap.php:4591
$currentPort
Definition: nusoap.php:4603
$complexTypes
Definition: nusoap.php:4594
$curl_options
Definition: nusoap.php:4622
$response_timeout
Definition: nusoap.php:4621
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:6349
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:6432
$currentBinding
Definition: nusoap.php:4601
$opStatus
Definition: nusoap.php:4587
$http
Definition: deliver.php:30
$c
Definition: deliver.php:25
if($err=$client->getError()) $namespace
$_GET['cmd']
Definition: lti.php:26
if(! $DIC->user() ->getId()||!ilLTIConsumerAccess::hasCustomProviderCreationAccess()) $params
Definition: ltiregstart.php:31
$scope
Definition: ltiregstart.php:51
$path
Definition: ltiservices.php:30
if(empty($path)) $serviceName
Definition: ltiservices.php:37
$res
Definition: ltiservices.php:69
if($clientAssertionType !='urn:ietf:params:oauth:client-assertion-type:jwt-bearer'|| $grantType !='client_credentials') $parts
Definition: ltitoken.php:61
if(count($parts) !=3) $payload
Definition: ltitoken.php:67
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc
Interface Observer \BackgroundTasks Contains several chained tasks and infos about them.
$a
thx to https://mlocati.github.io/php-cs-fixer-configurator for the examples
catch(\Exception $e) $req
Definition: xapiproxy.php:91
$_SERVER['HTTP_HOST']
Definition: raiseError.php:26
$url
Definition: shib_logout.php:68
$param
Definition: xapitoken.php:46

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

This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Learning e.V.

ILIAS is licensed with the GPL-3.0, see https://www.gnu.org/licenses/gpl-3.0.en.html You should have received a copy of said license along with the source code, too.

If this is not the case or you just want to try ILIAS, you'll find us at: https://www.ilias.de https://github.com/ILIAS-eLearning

Definition at line 43 of file nusoap.php.